diff --git a/package/lean/mt/drivers/mt7603e/Makefile b/package/lean/mt/drivers/mt7603e/Makefile index 875104b3c..f34f3a379 100644 --- a/package/lean/mt/drivers/mt7603e/Makefile +++ b/package/lean/mt/drivers/mt7603e/Makefile @@ -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 diff --git a/package/lean/mt/drivers/mt7603e/config.in b/package/lean/mt/drivers/mt7603e/config.in index cb130d1df..634c9bf27 100644 --- a/package/lean/mt/drivers/mt7603e/config.in +++ b/package/lean/mt/drivers/mt7603e/config.in @@ -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 diff --git a/package/lean/mt/drivers/mt7612e/Makefile b/package/lean/mt/drivers/mt7612e/Makefile new file mode 100644 index 000000000..82664e462 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/Makefile @@ -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)) diff --git a/package/lean/mt/drivers/mt7612e/config.in b/package/lean/mt/drivers/mt7612e/config.in new file mode 100644 index 000000000..ceb312939 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/config.in @@ -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 + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/History.txt b/package/lean/mt/drivers/mt7612e/src/mt76x2/History.txt new file mode 100644 index 000000000..60a3694fe --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/History.txt @@ -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 diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap.c new file mode 100644 index 000000000..cd53938d7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap.c @@ -0,0 +1,2713 @@ +/**************************************************************************** + * 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: + soft_ap.c + + Abstract: + Access Point specific routines and MAC table maintenance routines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 08-04-2003 created for 11g soft-AP + + */ + +#include "rt_config.h" + +BOOLEAN ApCheckLongPreambleSTA( + IN PRTMP_ADAPTER pAd); + +char const *pEventText[EVENT_MAX_EVENT_TYPE] = { + "restart access point", + "successfully associated", + "has disassociated", + "has been aged-out and disassociated" , + "active countermeasures", + "has disassociated with invalid PSK password"}; + + +UCHAR get_apidx_by_addr(RTMP_ADAPTER *pAd, UCHAR *addr) +{ + UCHAR apidx; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (RTMPEqualMemory(addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN)) + break; + } + + return apidx; +} + + +/* + ========================================================================== + Description: + Initialize AP specific data especially the NDIS packet pool that's + used for wireless client bridging. + ========================================================================== + */ +NDIS_STATUS APInitialize(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT i; + + DBGPRINT(RT_DEBUG_TRACE, ("---> APInitialize\n")); + + /* Init Group key update timer, and countermeasures timer */ + for (i = 0; i < MAX_MBSSID_NUM(pAd); i++) + RTMPInitTimer(pAd, &pAd->ApCfg.MBSSID[i].REKEYTimer, GET_TIMER_FUNCTION(GREKEYPeriodicExec), pAd, TRUE); + + RTMPInitTimer(pAd, &pAd->ApCfg.CounterMeasureTimer, GET_TIMER_FUNCTION(CMTimerExec), pAd, FALSE); + +#ifdef IDS_SUPPORT + /* Init intrusion detection timer */ + RTMPInitTimer(pAd, &pAd->ApCfg.IDSTimer, GET_TIMER_FUNCTION(RTMPIdsPeriodicExec), pAd, FALSE); + pAd->ApCfg.IDSTimerRunning = FALSE; +#endif /* IDS_SUPPORT */ + +#ifdef WAPI_SUPPORT + /* Init WAPI rekey timer */ + RTMPInitWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + +#ifdef WDS_SUPPORT + NdisAllocateSpinLock(pAd, &pAd->WdsTabLock); +#endif /* WDS_SUPPORT */ + +#ifdef IGMP_SNOOP_SUPPORT + MulticastFilterTableInit(pAd, &pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DROP_MASK_SUPPORT + NdisAllocateSpinLock(pAd, &pAd->drop_mask_lock); + asic_drop_mask_reset(pAd); +#endif /* DROP_MASK_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + initList(&pAd->DMSEntryList); +#endif /* DOT11V_WNM_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- APInitialize\n")); + return Status; +} + +/* + ========================================================================== + Description: + Shutdown AP and free AP specific resources + ========================================================================== + */ +VOID APShutdown(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("---> APShutdown\n")); +/* if (pAd->OpMode == OPMODE_AP) */ +#ifdef RTMP_MAC_PCI + APStop(pAd); +#endif /* RTMP_MAC_PCI */ + +#ifdef RT65xx + if (!IS_MT76x0E(pAd) && !IS_MT76x2E(pAd)) +#endif /* RT65xx */ + MlmeRadioOff(pAd); + +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(pAd, &pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + DMSTable_Release(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + + NdisFreeSpinLock(&pAd->MacTabLock); + +#ifdef WDS_SUPPORT + NdisFreeSpinLock(&pAd->WdsTabLock); +#endif /* WDS_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- APShutdown\n")); +} + +/* + ========================================================================== + Description: + Start AP service. If any vital AP parameter is changed, a STOP-START + sequence is required to disassociate all STAs. + + IRQL = DISPATCH_LEVEL.(from SetInformationHandler) + IRQL = PASSIVE_LEVEL. (from InitializeHandler) + + Note: + Can't call NdisMIndicateStatus on this routine. + + RT61 is a serialized driver on Win2KXP and is a deserialized on Win9X + Serialized callers of NdisMIndicateStatus must run at IRQL = DISPATCH_LEVEL. + + ========================================================================== + */ +VOID APStartUp(RTMP_ADAPTER *pAd) +{ + UINT32 i; + BOOLEAN bWmmCapable = FALSE; + UCHAR idx; + BOOLEAN TxPreamble, SpectrumMgmt = FALSE; + UCHAR phy_mode = pAd->CommonCfg.cfg_wmode; +#ifdef DOT1X_SUPPORT + /* BOOLEAN bDot1xReload = FALSE; */ +#endif /* DOT1X_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> APStartUp\n")); + +#ifdef INF_AMAZON_SE + for (i=0;iBulkOutDataSizeLimit[i]=24576; +#endif /* INF_AMAZON_SE */ + + AsicDisableSync(pAd); + + TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); + +#ifdef A_BAND_SUPPORT + /* Decide the Capability information field */ + /* In IEEE Std 802.1h-2003, the spectrum management bit is enabled in the 5 GHz band */ + if ((pAd->CommonCfg.Channel > 14) && pAd->CommonCfg.bIEEE80211H == TRUE) + SpectrumMgmt = TRUE; +#endif /* A_BAND_SUPPORT */ + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[idx]; + struct wifi_dev *wdev = &pMbss->wdev; + + wdev->channel = pAd->CommonCfg.Channel; + + if ((pMbss->SsidLen <= 0) || (pMbss->SsidLen > MAX_LEN_OF_SSID)) + { + NdisMoveMemory(pMbss->Ssid, "HT_AP", 5); + pMbss->Ssid[5] = '0' + idx; + pMbss->SsidLen = 6; + } + +#ifdef SPECIFIC_TX_POWER_SUPPORT + pMbss->TxPwrAdj=0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* re-copy the MAC to virtual interface to avoid these MAC = all zero, + when re-open the ra0, + i.e. ifconfig ra0 down, ifconfig ra0 up, ifconfig ra0 down, ifconfig up ... */ + COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + UCHAR MacMask = 0; + + if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 2) + MacMask = 0xFE; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 4) + MacMask = 0xFC; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 8) + MacMask = 0xF8; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 16) + MacMask = 0xF0; + + if (idx > 0) + { + wdev->if_addr[0] |= 0x2; + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + { + /* + Refer to HW definition - + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ + wdev->if_addr[0] &= ((MacMask << 2) + 3); + wdev->if_addr[0] |= ((idx - 1) << 2); + } +#ifdef ENHANCE_NEW_MBSSID_MODE + else + { + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] |= (idx - 1); + } +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + } + else + wdev->if_addr[5] += idx; + + if (wdev->if_dev != NULL) + { + NdisMoveMemory(RTMP_OS_NETDEV_GET_PHYADDR(wdev->if_dev), + wdev->if_addr, MAC_ADDR_LEN); + } + COPY_MAC_ADDR(wdev->bssid, wdev->if_addr); + wdev->wdev_type = WDEV_TYPE_AP; + wdev->tx_pkt_allowed = ApAllowToSendPacket; + + if (pMbss->wdev.bWmmCapable) + bWmmCapable = TRUE; + +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + pMbss->bBcnSntReq = TRUE; + else + pMbss->bBcnSntReq = FALSE; +#endif /* AIRPLAY_SUPPORT */ + + pMbss->CapabilityInfo = CAP_GENERATE(1, 0, (wdev->WepStatus != Ndis802_11EncryptionDisabled), + TxPreamble, pAd->CommonCfg.bUseShortSlotTime, + SpectrumMgmt); + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, idx)) + pMbss->CapabilityInfo |= RRM_CAP_BIT; +#endif /* DOT11K_RRM_SUPPORT */ + + if (bWmmCapable == TRUE) + { + /* + In WMM spec v1.1, A WMM-only AP or STA does not set the "QoS" + bit in the capability field of association, beacon and probe + management frames. + */ +/* pMbss->CapabilityInfo |= 0x0200; */ + } + +#ifdef UAPSD_SUPPORT + if (pMbss->UapsdInfo.bAPSDCapable == TRUE) + { + /* + QAPs set the APSD subfield to 1 within the Capability + Information field when the MIB attribute + dot11APSDOptionImplemented is true and set it to 0 otherwise. + STAs always set this subfield to 0. + */ + pMbss->CapabilityInfo |= 0x0800; + } +#endif /* UAPSD_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + /* + IEEE 802.11W/P.10 - + A STA that has associated with Management Frame Protection enabled + shall not use pairwise cipher suite selectors WEP-40, WEP-104, + TKIP, or "Use Group cipher suite". + + IEEE 802.11W/P.3 - + IEEE Std 802.11 provides one security protocol, CCMP, for protection + of unicast Robust Management frames. + */ + pMbss->PmfCfg.MFPC = FALSE; + pMbss->PmfCfg.MFPR = FALSE; + pMbss->PmfCfg.PMFSHA256 = FALSE; + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2 || + wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) && + (wdev->WepStatus == Ndis802_11AESEnable) && + (pMbss->PmfCfg.Desired_MFPC)) + { + pMbss->PmfCfg.MFPC = TRUE; + pMbss->PmfCfg.MFPR = pMbss->PmfCfg.Desired_MFPR; + + /* IGTK default key index as 4 */ + pMbss->PmfCfg.IGTK_KeyIdx = 4; + + /* Derive IGTK */ + PMF_DeriveIGTK(pAd, &pMbss->PmfCfg.IGTK[0][0]); + + if ((pMbss->PmfCfg.Desired_PMFSHA256) || (pMbss->PmfCfg.MFPR)) + pMbss->PmfCfg.PMFSHA256 = TRUE; + + } else if (pMbss->PmfCfg.Desired_MFPC) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, MFPC=%d, MFPR=%d, SHA256=%d\n", + __FUNCTION__, idx, pMbss->PmfCfg.MFPC, + pMbss->PmfCfg.MFPR, pMbss->PmfCfg.PMFSHA256)); +#endif /* DOT11W_PMF_SUPPORT */ + + /* decide the mixed WPA cipher combination */ + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + { + switch ((UCHAR)wdev->AuthMode) + { + /* WPA mode */ + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_NONE; + break; + + /* WPA2 mode */ + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + wdev->WpaMixPairCipher = WPA_NONE_WPA2_TKIPAES; + break; + + /* WPA and WPA2 both mode */ + case Ndis802_11AuthModeWPA1WPA2: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + + /* In WPA-WPA2 and TKIP-AES mixed mode, it shall use the maximum */ + /* cipher capability unless users assign the desired setting. */ + if (wdev->WpaMixPairCipher == MIX_CIPHER_NOTUSE || + wdev->WpaMixPairCipher == WPA_TKIPAES_WPA2_NONE || + wdev->WpaMixPairCipher == WPA_NONE_WPA2_TKIPAES) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + break; + } + } + else + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + + if (wdev->WepStatus == Ndis802_11Encryption2Enabled || + wdev->WepStatus == Ndis802_11Encryption3Enabled || + wdev->WepStatus == Ndis802_11Encryption4Enabled) + { + RT_CfgSetWPAPSKKey(pAd, pMbss->WPAKeyString, + strlen(pMbss->WPAKeyString), + (PUCHAR)pAd->ApCfg.MBSSID[idx].Ssid, + pAd->ApCfg.MBSSID[idx].SsidLen, + pAd->ApCfg.MBSSID[idx].PMK); + } + + /* Generate the corresponding RSNIE */ + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, idx); + +#ifdef WSC_V2_SUPPORT + if (pMbss->WscControl.WscV2Info.bEnableWpsV2) + { + /* WPS V2 doesn't support WEP and WPA/WPAPSK-TKIP. */ + if ((wdev->WepStatus == Ndis802_11WEPEnabled) || + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (pMbss->bHideSsid)) + WscOnOff(pAd, idx, TRUE); + else + WscOnOff(pAd, idx, FALSE); + } +#endif /* WSC_V2_SUPPORT */ +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering && idx == BSS0) + BndStrg_Init(pAd); +#endif /* BAND_STEERING */ + } + +#ifdef DOT11_N_SUPPORT + if (phy_mode != pAd->CommonCfg.PhyMode) + RTMPSetPhyMode(pAd, phy_mode); + + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, pAd->CurrentAddress); + + /* Select DAC according to HT or Legacy, write to BBP R1(bit4:3) */ + /* In HT mode and two stream mode, both DACs are selected. */ + /* In legacy mode or one stream mode, DAC-0 is selected. */ + { +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->Antenna.field.TxPath == 2)) + bbp_set_txdac(pAd, 2); + else +#endif /* DOT11_N_SUPPORT */ + bbp_set_txdac(pAd, 0); + } + + /* Receiver Antenna selection */ + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) || bWmmCapable) + { + /* EDCA parameters used for AP's own transmission */ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + set_default_ap_edca_param(pAd); + + /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ + if (pAd->ApCfg.BssEdcaParm.bValid == FALSE) + set_default_sta_edca_param(pAd); + + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + } + else + AsicSetEdcaParm(pAd, NULL); + +#ifdef DOT11_N_SUPPORT + if (!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; /* Patch UI */ + + AsicSetRDG(pAd, pAd->CommonCfg.bRdg); + + AsicSetRalinkBurstMode(pAd, pAd->CommonCfg.bRalinkBurstMode); +#endif /* DOT11_N_SUPPORT */ + +#ifdef TMP_PROGRESS_TEST + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); +#endif /* TMP_PROGRESS_TEST */ + AsicSetBssid(pAd, pAd->CurrentAddress); + mgmt_tb_set_mcast_entry(pAd); + + + /*@!Release + Reset whole WCID table + + In AP mode, First WCID Table in ASIC will never be used. + To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. + + p.s ASIC use all 0xff as termination of WCID table search. + */ + DBGPRINT(RT_DEBUG_TRACE, ("%s():Reset WCID Table\n", __FUNCTION__)); + AsicDelWcidTab(pAd, WCID_ALL); + +#ifdef FIFO_EXT_SUPPORT + FifoExtTableInit(pAd); + AsicFifoExtSet(pAd); +#endif /* FIFO_EXT_SUPPORT */ + + pAd->MacTab.MsduLifeTime = 5; /* default 5 seconds */ + + pAd->MacTab.Content[0].Addr[0] = 0x01; + pAd->MacTab.Content[0].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[0].HTPhyMode.field.MCS = 3; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + + AsicBBPAdjust(pAd); + + /* Clear BG-Protection flag */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); +#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 DOT11_VHT_AC +//+++Add by shiang for debug +DBGPRINT(RT_DEBUG_OFF, ("%s(): AP Set CentralFreq at %d(Prim=%d, HT-CentCh=%d, VHT-CentCh=%d, BBP_BW=%d)\n", + __FUNCTION__, pAd->hw_cfg.cent_ch, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel, pAd->CommonCfg.vht_cent_ch, + pAd->CommonCfg.BBPCurrentBW)); +//---Add by shiang for debug +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPEnable == TRUE) + { + RTMP_CHIP_ENABLE_AP_MIMOPS(pAd,TRUE); + pAd->ApCfg.GreenAPLevel=GREENAP_WITHOUT_ANY_STAS_CONNECT; + } +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + MlmeUpdateTxRates(pAd, FALSE, idx); +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + MlmeUpdateHtTxRates(pAd, idx); +#endif /* DOT11_N_SUPPORT */ + } + + /* Set the RadarDetect Mode as Normal, bc the APUpdateAllBeaconFram() will refer this parameter. */ + RadarStateCheck(pAd); + +#ifdef CUSTOMER_DCC_FEATURE + pAd->CommonCfg.channelSwitch.CHSWMode = NORMAL_MODE; +#endif + /* Disable Protection first. */ + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + + APUpdateCapabilityAndErpIe(pAd); +#ifdef DOT11_N_SUPPORT + APUpdateOperationMode(pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_UP); +#endif /* LED_CONTROL_SUPPORT */ + + /* Initialize security variable per entry, + 1. pairwise key table, re-set all WCID entry as NO-security mode. + 2. access control port status + */ + DBGPRINT(RT_DEBUG_TRACE, ("%s():Reset Sec Table\n", __FUNCTION__)); + for (i=0; iMacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + AsicRemovePairwiseKeyEntry(pAd, (UCHAR)i); + } + + /* Init Security variables */ + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + USHORT Wcid = 0; + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[idx]; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[idx].wdev; + + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + if (IS_WPA_CAPABILITY(wdev->AuthMode)) + wdev->DefaultKeyId = 1; + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, idx); + + /* When WEP, TKIP or AES is enabled, set group key info to Asic */ + if (wdev->WepStatus == Ndis802_11WEPEnabled) + { + UCHAR CipherAlg, key_idx; + + for (key_idx=0; key_idx < SHARE_KEY_NUM; key_idx++) + { + CipherAlg = pAd->SharedKey[idx][key_idx].CipherAlg; + + if (pAd->SharedKey[idx][key_idx].KeyLen > 0) + { + /* Set key material to Asic */ + AsicAddSharedKeyEntry(pAd, idx, key_idx, &pAd->SharedKey[idx][key_idx]); + + if (key_idx == wdev->DefaultKeyId) + { + /* Generate 3-bytes IV randomly for software encryption using */ + for(i = 0; i < LEN_WEP_TSC; i++) + pAd->SharedKey[idx][key_idx].TxTsc[i] = RandomByte(pAd); + + /* Update WCID attribute table and IVEIV table */ + RTMPSetWcidSecurityInfo(pAd, + idx, + key_idx, + CipherAlg, + Wcid, + SHAREDKEYTABLE); + } + } + } + } + else if ((wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) + { + /* Generate GMK and GNonce randomly per MBSS */ + GenRandom(pAd, wdev->bssid, pMbss->GMK); + GenRandom(pAd, wdev->bssid, pMbss->GNonce); + + /* Derive GTK per BSSID */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + wdev->bssid, + pMbss->GTK, + LEN_TKIP_GTK); + + /* Install Shared key */ + WPAInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + idx, + wdev->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + + } +#ifdef WAPI_SUPPORT + else if (pMbss->wdev.WepStatus == Ndis802_11EncryptionSMS4Enabled) + { + INT cnt; + + /* Initial the related variables */ + pMbss->wdev.DefaultKeyId = 0; + NdisMoveMemory(pMbss->key_announce_flag, AE_BCAST_PN, LEN_WAPI_TSC); + if (IS_HW_WAPI_SUPPORT(pAd)) + pMbss->sw_wpi_encrypt = FALSE; + else + pMbss->sw_wpi_encrypt = TRUE; + + /* Generate NMK randomly */ + for (cnt = 0; cnt < LEN_WAPI_NMK; cnt++) + pMbss->NMK[cnt] = RandomByte(pAd); + + /* Count GTK for this BSSID */ + RTMPDeriveWapiGTK(pMbss->NMK, pMbss->GTK); + + /* Install Shared key */ + WAPIInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + idx, + wdev->DefaultKeyId, + Wcid, + pMbss->GTK); + + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* Send singal to daemon to indicate driver had restarted */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->IEEE8021X == TRUE)) + { + ;/*bDot1xReload = TRUE; */ + } +#endif /* DOT1X_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("### BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, AccessControlList.Policy=%ld\n", + idx, wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus), + pMbss->AccessControlList.Policy)); + } + + +#ifdef PIGGYBACK_SUPPORT + RTMPSetPiggyBack(pAd, pAd->CommonCfg.bPiggyBackCapable); +#endif /* PIGGYBACK_SUPPORT */ + + ApLogEvent(pAd, pAd->CurrentAddress, EVENT_RESET_ACCESS_POINT); + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + + OPSTATUS_SET_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + + + /* + NOTE!!!: + All timer setting shall be set after following flag be cleared + fRTMP_ADAPTER_HALT_IN_PROGRESS + */ + /* + Note : Owing to the flags setting too late to USB In-band commnad cannnot receive rsp + For this test,change to up setting + If test have no side effect , we will change this + */ +#ifndef TMP_PROGRESS_TEST + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); +#endif /* TMP_PROGRESS_TEST */ + + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { +#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 */ + + /* start sending BEACON out */ + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef DFS_SUPPORT + if (IS_DOT11_H_RADAR_STATE(pAd, RD_SILENCE_MODE)) + NewRadarDetectionStart(pAd); +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStart(pAd); +#endif /* CARRIER_DETECTION_SUPPORT */ + + if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + AsicEnableBssSync(pAd); + + /* Pre-tbtt interrupt setting. */ + AsicSetPreTbttInt(pAd, TRUE); + +#ifdef RTMP_MAC_PCI + RTMP_MAC_RX_ENABLE(pAd); +#endif /*RTMP_MAC_PCI*/ + +#ifdef WAPI_SUPPORT + RTMPStartWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + + /* + Set group re-key timer if necessary. + It must be processed after clear flag "fRTMP_ADAPTER_HALT_IN_PROGRESS" + */ + WPA_APSetGroupRekeyAction(pAd); + +#ifdef WDS_SUPPORT + /* Prepare WEP key */ + WdsPrepareWepKeyFromMainBss(pAd); + + /* Add wds key infomation to ASIC */ + AsicUpdateWdsRxWCIDTable(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef IDS_SUPPORT + /* Start IDS timer */ + if (pAd->ApCfg.IdsEnable) + { +#ifdef SYSTEM_LOG_SUPPORT + if (pAd->CommonCfg.bWirelessEvent == FALSE) + DBGPRINT(RT_DEBUG_WARN, ("!!! WARNING !!! The WirelessEvent parameter doesn't be enabled \n")); +#endif /* SYSTEM_LOG_SUPPORT */ + + RTMPIdsStart(pAd); + } +#endif /* IDS_SUPPORT */ + + + +#ifdef DOT11R_FT_SUPPORT + FT_Init(pAd); +#endif /* DOT11R_FT_SUPPORT */ + + + +#ifdef ED_MONITOR +{ + BOOLEAN bEdcca = FALSE; + + bEdcca = GetEDCCASupport(pAd); + + if (bEdcca) + { + ed_monitor_init(pAd); + } + else + ed_monitor_exit(pAd); +} +#endif /* ED_MONITOR */ +#ifdef CUSTOMER_DCC_FEATURE + pAd->CommonCfg.NewExtChanOffset.NewExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; +#endif + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== APStartUp\n")); +} + +/* + ========================================================================== + Description: + disassociate all STAs and stop AP service. + Note: + ========================================================================== + */ +VOID APStop( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + UINT32 Value; + INT idx; + MULTISSID_STRUCT *pMbss; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! APStop !!!\n")); + +#ifdef ED_MONITOR + if (pAd->ed_chk) + { + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: go to ed_monitor_exit()!!\n", __FUNCTION__)); + ed_monitor_exit(pAd); + } +#endif /* ED_MONITOR */ + +#ifdef DFS_SUPPORT + NewRadarDetectionStop(pAd); +#endif /* DFS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + /* make sure CarrierDetect wont send CTS */ + CarrierDetectionStop(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + ApCliIfDown(pAd); +#endif /* APCLI_SUPPORT */ + +#ifdef RTMP_MAC_PCI + + RTMP_MAC_RX_DISABLE(pAd); +#endif /*RTMP_MAC_PCI*/ + MacTableReset(pAd); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + /* Disable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &=0xe; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + /* Disable piggyback */ + RTMPSetPiggyBack(pAd, FALSE); + + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + /*RTMP_ASIC_INTERRUPT_DISABLE(pAd); */ + AsicDisableSync(pAd); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_DOWN); +#endif /* LED_CONTROL_SUPPORT */ + } + + + + for (idx = 0; idx < MAX_MBSSID_NUM(pAd); idx++) + { + pMbss = &pAd->ApCfg.MBSSID[idx]; + if (pMbss->REKEYTimerRunning == TRUE) + { + RTMPCancelTimer(&pMbss->REKEYTimer, &Cancelled); + pMbss->REKEYTimerRunning = FALSE; + } + } + + if (pAd->ApCfg.CMTimerRunning == TRUE) + { + RTMPCancelTimer(&pAd->ApCfg.CounterMeasureTimer, &Cancelled); + pAd->ApCfg.CMTimerRunning = FALSE; + } + +#ifdef WAPI_SUPPORT + RTMPCancelWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + + /* */ + /* Cancel the Timer, to make sure the timer was not queued. */ + /* */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + +#ifdef IDS_SUPPORT + /* if necessary, cancel IDS timer */ + RTMPIdsStop(pAd); +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_Release(pAd); +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + DMSTable_Release(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + +} + +/* + ========================================================================== + Description: + This routine is used to clean up a specified power-saving queue. It's + used whenever a wireless client is deleted. + ========================================================================== + */ +VOID APCleanupPsQueue( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_HEADER pQueue) +{ + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): (0x%08lx)...\n", __FUNCTION__, (ULONG)pQueue)); + + while (pQueue->Head) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():%u...\n", __FUNCTION__, pQueue->Number)); + + pEntry = RemoveHeadQueue(pQueue); + /*pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); */ + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} + + +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP +static VOID CheckApEntryInTraffic(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + UINT32 TxTotalByteCnt = 0; + UINT32 RxTotalByteCnt = 0; + + if ((IS_ENTRY_APCLI(pEntry) || IS_ENTRY_CLIENT(pEntry)) + && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) { + TxTotalByteCnt = pEntry->OneSecTxBytes; + RxTotalByteCnt = pEntry->OneSecRxBytes; + + DBGPRINT(RT_DEBUG_TRACE,("WCID%d, %dM, TxBytes:%d, RxBytes:%d\n", + pEntry->wcid, + (((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20), + TxTotalByteCnt, + RxTotalByteCnt)); + + if ((TxTotalByteCnt == 0) || (RxTotalByteCnt == 0)) + { + } + else if ((((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20) > pAd->CommonCfg.ManualTxopThreshold) + { + if (TxTotalByteCnt > RxTotalByteCnt) + { + if ((TxTotalByteCnt/RxTotalByteCnt) >= pAd->CommonCfg.ManualTxopUpBound) + { + if (IS_ENTRY_CLIENT(pEntry)) + pAd->StaTxopAbledCnt++; + else + pAd->ApClientTxopAbledCnt++; + + DBGPRINT(RT_DEBUG_TRACE,("WCID%d, StaTxopAbledCnt:%d, ApClientTxopAbledCnt:%d\n", + pEntry->wcid, + pAd->StaTxopAbledCnt, + pAd->ApClientTxopAbledCnt)); + } + } + else + { + if ((RxTotalByteCnt/TxTotalByteCnt) <= pAd->CommonCfg.ManualTxopLowBound) + { + if (IS_ENTRY_CLIENT(pEntry)) + pAd->StaTxopAbledCnt++; + else + pAd->ApClientTxopAbledCnt++; + } + } + } + } + + pEntry->OneSecTxBytes = 0; + pEntry->OneSecRxBytes = 0; + +} +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + + +/* + ========================================================================== + Description: + This routine is called by APMlmePeriodicExec() every second to check if + 1. any associated client in PSM. If yes, then TX MCAST/BCAST should be + out in DTIM only + 2. any client being idle for too long and should be aged-out from MAC table + 3. garbage collect PSQ + ========================================================================== +*/ +VOID MacTableMaintenance(RTMP_ADAPTER *pAd) +{ + int i, startWcid; +#ifdef DOT11_N_SUPPORT + ULONG MinimumAMPDUSize = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; /*Default set minimum AMPDU Size to 2, i.e. 32K */ + BOOLEAN bRdgActive; + BOOLEAN bRalinkBurstMode; +#endif /* DOT11_N_SUPPORT */ +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags; +#endif /* RTMP_MAC_PCI */ + UINT fAnyStationPortSecured[HW_BEACON_MAX_NUM]; + UINT bss_index; + MAC_TABLE *pMacTable; +#if defined(PRE_ANT_SWITCH) || defined(CFO_TRACK) + int lastClient=0; +#endif /* defined(PRE_ANT_SWITCH) || defined(CFO_TRACK) */ + MULTISSID_STRUCT *pMbss; +#ifdef WFA_VHT_PF + RSSI_SAMPLE *worst_rssi = NULL; + int worst_rssi_sta_idx = 0; +#endif /* WFA_VHT_PF */ + +#ifdef ED_MONITOR + INT total_sta = 0; +#endif /* ED_MONITOR */ + + NdisZeroMemory(fAnyStationPortSecured, sizeof(fAnyStationPortSecured)); + + pMacTable = &pAd->MacTab; + pMacTable->fAnyStationInPsm = FALSE; + pMacTable->fAnyStationBadAtheros = FALSE; + pMacTable->fAnyTxOPForceDisable = FALSE; + pMacTable->fAllStationAsRalink = TRUE; +#ifdef DOT11_N_SUPPORT + pMacTable->fAnyStationNonGF = FALSE; + pMacTable->fAnyStation20Only = FALSE; + pMacTable->fAnyStationIsLegacy = FALSE; + pMacTable->fAnyStationMIMOPSDynamic = FALSE; +#ifdef GREENAP_SUPPORT + /*Support Green AP */ + pMacTable->fAnyStationIsHT=FALSE; +#endif /* GREENAP_SUPPORT */ + +#ifdef DOT11N_DRAFT3 + pMacTable->fAnyStaFortyIntolerant = FALSE; +#endif /* DOT11N_DRAFT3 */ + pMacTable->fAllStationGainGoodMCS = TRUE; +#endif /* DOT11_N_SUPPORT */ + +#ifdef WAPI_SUPPORT + pMacTable->fAnyWapiStation = FALSE; +#endif /* WAPI_SUPPORT */ + + startWcid = 1; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* Skip the Infra Side */ + startWcid = 2; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP + pAd->StaTxopAbledCnt = 0; + pAd->ApClientTxopAbledCnt = 0; +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + + for (i = startWcid; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[i]; + BOOLEAN bDisconnectSta = FALSE; +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP + CheckApEntryInTraffic(pAd, pEntry); +#endif /* TRAFFIC_BASED_TXOP */ + + if(IS_ENTRY_APCLI(pEntry) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pEntry->bReptCli) + { + pEntry->ReptCliIdleCount++; + + if ((pEntry->bReptEthCli) && (pEntry->ReptCliIdleCount >= MAC_TABLE_AGEOUT_TIME)) + { +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pEntry->wcid); +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterDisconnectEntry(pAd, pEntry->wdev_idx, pEntry->MatchReptCliIdx); + RTMPRemoveRepeaterEntry(pAd, pEntry->wdev_idx, pEntry->MatchReptCliIdx); + continue; + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) + { + /* use Null or QoS Null to detect the ACTIVE station*/ + BOOLEAN ApclibQosNull = FALSE; + + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + ApclibQosNull = TRUE; + + ApCliRTMPSendNullFrame(pAd,pEntry->CurrTxRate, ApclibQosNull, pEntry, PWR_ACTIVE); + + continue; + } + } +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry)) + { + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)) + pMacTable->fAllStationAsRalink = FALSE; + + if (pAd->CommonCfg.bRdg && pMacTable->fAllStationAsRalink) + { + bRdgActive = TRUE; + } + else + { + bRdgActive = FALSE; + } + + if (bRdgActive != RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + AsicSetRDG(pAd, bRdgActive); + + continue; + } +#endif /* WDS_SUPPORT */ + +#ifdef MWDS + if (!IS_ENTRY_NONE(pEntry)) + { + if (pEntry->bEnableMWDS == TRUE) + pMacTable->fAllStationAsRalink = FALSE; + } +#endif /* MWDS */ + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (pEntry->NoDataIdleCount == 0) + pEntry->StationKeepAliveCount = 0; + + pEntry->NoDataIdleCount ++; + pEntry->StaConnectTime ++; + + pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + + /* 0. STA failed to complete association should be removed to save MAC table space. */ + if ((pEntry->Sst != SST_ASSOC) && (pEntry->NoDataIdleCount >= pEntry->AssocDeadLine)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%02x:%02x:%02x:%02x:%02x:%02x fail to complete ASSOC in %d sec\n", + PRINT_MAC(pEntry->Addr), MAC_TABLE_ASSOC_TIMEOUT)); +#ifdef WSC_AP_SUPPORT + if (NdisEqualMemory(pEntry->Addr, pMbss->WscControl.EntryAddr, MAC_ADDR_LEN)) + NdisZeroMemory(pMbss->WscControl.EntryAddr, MAC_ADDR_LEN); +#endif /* WSC_AP_SUPPORT */ + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + continue; + } + + /* 1. check if there's any associated STA in power-save mode. this affects outgoing */ + /* MCAST/BCAST frames should be stored in PSQ till DtimCount=0 */ + if (pEntry->PsMode == PWR_SAVE) + { + pMacTable->fAnyStationInPsm = TRUE; +#ifdef PS_ENTRY_MAITENANCE + pEntry->continuous_ps_count++; +#endif /* PS_ENTRY_MAITENANCE */ + } + +#ifdef DOT11_N_SUPPORT + if (pEntry->MmpsMode == MMPS_DYNAMIC) + pMacTable->fAnyStationMIMOPSDynamic = TRUE; + + if (pEntry->MaxHTPhyMode.field.BW == BW_20) + pMacTable->fAnyStation20Only = TRUE; + + if (pEntry->MaxHTPhyMode.field.MODE != MODE_HTGREENFIELD) + pMacTable->fAnyStationNonGF = TRUE; + + if ((pEntry->MaxHTPhyMode.field.MODE == MODE_OFDM) || (pEntry->MaxHTPhyMode.field.MODE == MODE_CCK)) + pMacTable->fAnyStationIsLegacy = TRUE; +#ifdef GREENAP_SUPPORT + else + pMacTable->fAnyStationIsHT=TRUE; +#endif /* GREENAP_SUPPORT */ + +#ifdef DOT11N_DRAFT3 + if (pEntry->bForty_Mhz_Intolerant) + pMacTable->fAnyStaFortyIntolerant = TRUE; +#endif /* DOT11N_DRAFT3 */ + + /* Get minimum AMPDU size from STA */ + if (MinimumAMPDUSize > pEntry->MaxRAmpduFactor) + MinimumAMPDUSize = pEntry->MaxRAmpduFactor; +#endif /* DOT11_N_SUPPORT */ + + if (pEntry->bIAmBadAtheros) + { + pMacTable->fAnyStationBadAtheros = TRUE; +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE) + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, pMacTable->fAnyStationNonGF); +#endif /* DOT11_N_SUPPORT */ + } + + /* detect the station alive status */ + /* detect the station alive status */ + if ((pMbss->StationKeepAliveTime > 0) && + (pEntry->NoDataIdleCount >= pMbss->StationKeepAliveTime)) + { + /* + If no any data success between ap and the station for + StationKeepAliveTime, try to detect whether the station is + still alive. + + Note: Just only keepalive station function, no disassociation + function if too many no response. + */ + + /* + For example as below: + + 1. Station in ACTIVE mode, + + ...... + sam> tx ok! + sam> count = 1! ==> 1 second after the Null Frame is acked + sam> count = 2! ==> 2 second after the Null Frame is acked + sam> count = 3! + sam> count = 4! + sam> count = 5! + sam> count = 6! + sam> count = 7! + sam> count = 8! + sam> count = 9! + sam> count = 10! + sam> count = 11! + sam> count = 12! + sam> count = 13! + sam> count = 14! + sam> count = 15! ==> 15 second after the Null Frame is acked + sam> tx ok! ==> (KeepAlive Mechanism) send a Null Frame to + detect the STA life status + sam> count = 1! ==> 1 second after the Null Frame is acked + sam> count = 2! + sam> count = 3! + sam> count = 4! + ...... + + If the station acknowledges the QoS Null Frame, + the NoDataIdleCount will be reset to 0. + + + 2. Station in legacy PS mode, + + We will set TIM bit after 15 seconds, the station will send a + PS-Poll frame and we will send a QoS Null frame to it. + If the station acknowledges the QoS Null Frame, the + NoDataIdleCount will be reset to 0. + + + 3. Station in legacy UAPSD mode, + + Currently we do not support the keep alive mechanism. + So if your station is in UAPSD mode, the station will be + kicked out after 300 seconds. + + Note: the rate of QoS Null frame can not be 1M of 2.4GHz or + 6M of 5GHz, or no any statistics count will occur. + */ + + if (pEntry->StationKeepAliveCount++ == 0) + { + if (pEntry->PsMode == PWR_SAVE) + { + /* use TIM bit to detect the PS station */ + WLAN_MR_TIM_BIT_SET(pAd, pEntry->apidx, pEntry->Aid); + } + else + { + /* use Null or QoS Null to detect the ACTIVE station */ + BOOLEAN bQosNull = FALSE; + + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + bQosNull = TRUE; + + RtmpEnqueueNullFrame(pAd, pEntry->Addr, pEntry->CurrTxRate, + pEntry->Aid, pEntry->apidx, bQosNull, TRUE, 0); + } + } + else + { + if (pEntry->StationKeepAliveCount >= pMbss->StationKeepAliveTime) + pEntry->StationKeepAliveCount = 0; + } + } + + /* 2. delete those MAC entry that has been idle for a long time */ + if ((pEntry->NoDataIdleCount >= pEntry->StaIdleTimeout) +#ifdef PS_ENTRY_MAITENANCE + || (pEntry->continuous_ps_count > pAd->ps_timeout) +#endif /* PS_ENTRY_MAITENANCE */ + ) + { + bDisconnectSta = TRUE; + +#ifdef PS_ENTRY_MAITENANCE + if (pEntry->continuous_ps_count > pAd->ps_timeout) + DBGPRINT(RT_DEBUG_WARN, ("ps_timeout(%u) !!!\n", pEntry->Aid)); +#endif /* PS_ENTRY_MAITENANCE */ + DBGPRINT(RT_DEBUG_WARN, ("ageout %02x:%02x:%02x:%02x:%02x:%02x after %d-sec silence\n", + PRINT_MAC(pEntry->Addr), pEntry->StaIdleTimeout)); + ApLogEvent(pAd, pEntry->Addr, EVENT_AGED_OUT); +#ifdef SMART_MESH_MONITOR + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.leave.type = NSMPIF_DRVEVNT_STA_TIMEOUT; + drvevnt.data.leave.channel = pAd->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.leave.sta_mac, pEntry->Addr, MAC_ADDR_LEN); + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_TIMEOUT, + NULL, (PUCHAR)&drvevnt.data.leave, sizeof(drvevnt.data.leave)); + } +#endif /* SMART_MESH_MONITOR */ + } + else if (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck) + { + /* + AP have no way to know that the PwrSaving STA is leaving or not. + So do not disconnect for PwrSaving STA. + */ + if (pEntry->PsMode != PWR_SAVE) + { + bDisconnectSta = TRUE; +#ifdef DROP_MASK_SUPPORT + asic_set_drop_mask(pAd, pEntry->Aid, TRUE); +#else + ClearTxRingClientAck(pAd, pEntry); +#endif + DBGPRINT(RT_DEBUG_WARN, ("STA-%02x:%02x:%02x:%02x:%02x:%02x had left (%d %lu)\n", + PRINT_MAC(pEntry->Addr), + pEntry->ContinueTxFailCnt, pAd->ApCfg.EntryLifeCheck)); + } + } +#ifdef BAND_STEERING + else if (pAd->ApCfg.BndStrgTable.bEnabled == TRUE) + { + if (BndStrg_IsClientStay(pAd, pEntry) == FALSE) + { + bDisconnectSta = TRUE; + } + } +#endif /* BAND_STEERING */ + + //YF: kickout sta when 3 of 5 exceeds the threshold. + if (pMbss->RssiLowForStaKickOut != 0) + { +#define CHECK_DATA_RSSI_UP_BOUND 3 + CHAR rssiIndex = 0, overRssiThresCount = 0; + + for (rssiIndex=0; rssiIndexLastDataRssi[rssiIndex] !=0 ) && + (pEntry->LastDataRssi[rssiIndex] < pMbss->RssiLowForStaKickOut)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d:[%d] Fail.\n",rssiIndex,pEntry->LastDataRssi[rssiIndex])); + overRssiThresCount++; + } + } + + if (overRssiThresCount >= CHECK_DATA_RSSI_UP_BOUND) + { + bDisconnectSta = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("Dis STA %02x:%02x:%02x:%02x:%02x:%02x , RSSI Kickout Thres[%d]-[%d]Times\n", + PRINT_MAC(pEntry->Addr), pMbss->RssiLowForStaKickOut, overRssiThresCount)); + } + + } + + if (bDisconnectSta) + { + /* send wireless event - for ageout */ + RTMPSendWirelessEvent(pAd, IW_AGEOUT_EVENT_FLAG, pEntry->Addr, 0, 0); + + if (pEntry->Sst == SST_ASSOC) + { + 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; + DBGPRINT(RT_DEBUG_WARN, ("Send DEAUTH - Reason = %d frame TO %x %x %x %x %x %x \n", + Reason, PRINT_MAC(pEntry->Addr))); + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + /* wait for DEAUTH processed */ + OS_WAIT(5); + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && IS_ENTRY_CLIENT(pEntry) +#ifdef MWDS + && (pEntry->bEnableMWDS == FALSE) +#endif /* MWDS */ + ) + { + UCHAR apCliIdx, CliIdx, isLinkValid; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, pEntry->Addr ,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 */ + } + + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + continue; + } +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry->BTMDisassocCount == 1) + { + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DisassocHdr; + 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_DISASSOC_INACTIVE; + DBGPRINT(RT_DEBUG_ERROR, ("BTM ASSOC - Send DISASSOC Reason = %d frame TO %x %x %x %x %x %x \n",Reason,pEntry->Addr[0], + pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5])); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pEntry->Addr, pMbss->wdev.if_addr, pMbss->wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &DisassocHdr, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, MGMT_USE_PS_FLAG, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + //JERRY + if (!pEntry->IsKeep) + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + continue; + } + if (pEntry->BTMDisassocCount != 0) + pEntry->BTMDisassocCount--; +#endif /* CONFIG_HOTSPOT_R2 */ + + /* 3. garbage collect the PsQueue if the STA has being idle for a while */ + if (pEntry->PsQueue.Head) + { + pEntry->PsQIdleCount++; +#ifdef NOISE_TEST_ADJUST + if (pEntry->PsQIdleCount > 4) +#else + if (pEntry->PsQIdleCount > 2) +#endif /* NOISE_TEST_ADJUST */ + { + ULONG irq_flags; + RTMP_IRQ_LOCK(&pAd->irq_lock, irq_flags); + APCleanupPsQueue(pAd, &pEntry->PsQueue); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irq_flags); + pEntry->PsQIdleCount = 0; + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, pEntry->Aid); + } + } + else + pEntry->PsQIdleCount = 0; + +#ifdef UAPSD_SUPPORT + UAPSD_QueueMaintenance(pAd, pEntry); +#endif /* UAPSD_SUPPORT */ + + /* check if this STA is Ralink-chipset */ + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)) + pMacTable->fAllStationAsRalink = FALSE; + + /* Check if the port is secured */ + if (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + fAnyStationPortSecured[pEntry->apidx]++; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if ((pEntry->BSS2040CoexistenceMgmtSupport) + && (pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_INFO_NOTIFY) + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + ) + { + SendNotifyBWActionFrame(pAd, pEntry->wcid, pEntry->apidx); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef WAPI_SUPPORT + if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) + pMacTable->fAnyWapiStation = TRUE; +#endif /* WAPI_SUPPORT */ + +#if defined(PRE_ANT_SWITCH) || defined(CFO_TRACK) + lastClient = i; +#endif /* defined(PRE_ANT_SWITCH) || defined(CFO_TRACK) */ + + /* only apply burst when run in MCS0,1,8,9,16,17, not care about phymode */ + if ((pEntry->HTPhyMode.field.MCS != 32) && + ((pEntry->HTPhyMode.field.MCS % 8 == 0) || (pEntry->HTPhyMode.field.MCS % 8 == 1))) + { + pMacTable->fAllStationGainGoodMCS = FALSE; + } + +#ifdef WFA_VHT_PF + if (worst_rssi == NULL) { + worst_rssi = &pEntry->RssiSample; + worst_rssi_sta_idx = i; + } else { + if (worst_rssi->AvgRssi0 > pEntry->RssiSample.AvgRssi0) { + worst_rssi = &pEntry->RssiSample; + worst_rssi_sta_idx = i; + } + } +#endif /* WFA_VHT_PF */ + } + +#ifdef WFA_VHT_PF + if (worst_rssi != NULL && + ((pAd->Mlme.OneSecPeriodicRound % 10) == 5) && + (worst_rssi_sta_idx >= 1)) + { + CHAR gain = 2; + if (worst_rssi->AvgRssi0 >= -40) + gain = 1; + else if (worst_rssi->AvgRssi0 <= -50) + gain = 2; + rt85592_lna_gain_adjust(pAd, gain); + DBGPRINT(RT_DEBUG_TRACE, ("%s():WorstRSSI for STA(%02x:%02x:%02x:%02x:%02x:%02x):%d,%d,%d, Set Gain as %s\n", + __FUNCTION__, + PRINT_MAC(pMacTable->Content[worst_rssi_sta_idx].Addr), + worst_rssi->AvgRssi0, worst_rssi->AvgRssi1, worst_rssi->AvgRssi2, + (gain == 2 ? "Mid" : "Low"))); + } +#endif /* WFA_VHT_PF */ + +#ifdef PRE_ANT_SWITCH +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK +#endif /* CFO_TRACK */ + + /* Update the state of port per MBSS */ + for (bss_index = BSS0; bss_index < MAX_MBSSID_NUM(pAd); bss_index++) + { +#ifdef ED_MONITOR + total_sta += pAd->ApCfg.MBSSID[bss_index].StaCount; +#endif /* ED_MONITOR */ + if (fAnyStationPortSecured[bss_index] > 0) + pAd->ApCfg.MBSSID[bss_index].wdev.PortSecured = WPA_802_1X_PORT_SECURED; + else + pAd->ApCfg.MBSSID[bss_index].wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_INFO_NOTIFY) + pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_INFO_NOTIFY); +#endif /* DOT11N_DRAFT3 */ + + /* If all associated STAs are Ralink-chipset, AP shall enable RDG. */ + if (pAd->CommonCfg.bRdg && pMacTable->fAllStationAsRalink) + { +#ifdef MWDS + if (pAd->MacTab.Size >= 2) + bRdgActive = FALSE; + else +#endif /* MWDS */ + bRdgActive = TRUE; + } + else + bRdgActive = FALSE; + + if (pAd->CommonCfg.bRalinkBurstMode && pMacTable->fAllStationGainGoodMCS) + bRalinkBurstMode = TRUE; + else + bRalinkBurstMode = FALSE; + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + if(pAd->MacTab.fAnyStationIsHT == FALSE + && pAd->ApCfg.bGreenAPEnable == TRUE) + { +#ifdef RTMP_RBUS_SUPPORT +#ifdef COC_SUPPORT + if ((pAd->MacTab.Size==0) && + (pAd->ApCfg.GreenAPLevel != GREENAP_WITHOUT_ANY_STAS_CONNECT)) + { + RTMP_CHIP_ENABLE_AP_MIMOPS(pAd,TRUE); + pAd->ApCfg.GreenAPLevel = GREENAP_WITHOUT_ANY_STAS_CONNECT; + + } + else +#endif /* COC_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + if (pAd->ApCfg.GreenAPLevel!=GREENAP_ONLY_11BG_STAS) + { + RTMP_CHIP_ENABLE_AP_MIMOPS(pAd,FALSE); + pAd->ApCfg.GreenAPLevel=GREENAP_ONLY_11BG_STAS; + } + } + else + { + if (pAd->ApCfg.GreenAPLevel!=GREENAP_11BGN_STAS) + { + RTMP_CHIP_DISABLE_AP_MIMOPS(pAd); + pAd->ApCfg.GreenAPLevel=GREENAP_11BGN_STAS; + } + } + } +#endif /* GREENAP_SUPPORT */ + + if (bRdgActive != RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + AsicSetRDG(pAd, bRdgActive); + + if (bRalinkBurstMode != RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE)) + AsicSetRalinkBurstMode(pAd, bRalinkBurstMode); +#endif /* DOT11_N_SUPPORT */ + + + if ((pMacTable->fAnyStationBadAtheros == FALSE) && (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == TRUE)) + { + AsicUpdateProtect(pAd, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, pMacTable->fAnyStationNonGF); + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef RTMP_MAC_PCI + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + /* + 4. + garbage collect pAd->MacTab.McastPsQueue if backlogged MCAST/BCAST frames + stale in queue. Since MCAST/BCAST frames always been sent out whenever + DtimCount==0, the only case to let them stale is surprise removal of the NIC, + so that ASIC-based Tbcn interrupt stops and DtimCount dead. + */ + if (pMacTable->McastPsQueue.Head) + { + UINT bss_index; + + pMacTable->PsQIdleCount ++; +#ifdef NOISE_TEST_ADJUST + if (pMacTable->PsQIdleCount > 2) +#else + if (pMacTable->PsQIdleCount > 1) +#endif /* NOISE_TEST_ADJUST */ + { + + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + APCleanupPsQueue(pAd, &pMacTable->McastPsQueue); + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + pMacTable->PsQIdleCount = 0; + + if (pAd->ApCfg.BssidNum > MAX_MBSSID_NUM(pAd)) + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + + /* clear MCAST/BCAST backlog bit for all BSS */ + for(bss_index=BSS0; bss_indexApCfg.BssidNum; bss_index++) + WLAN_MR_TIM_BCMC_CLEAR(bss_index); + } + } + else + pMacTable->PsQIdleCount = 0; +#ifdef RTMP_MAC_PCI + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ +} + + +UINT32 MacTableAssocStaNumGet( + IN PRTMP_ADAPTER pAd) +{ + UINT32 num = 0; + UINT32 i; + + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (pEntry->Sst == SST_ASSOC) + num ++; + } + + return num; +} + + +/* + ========================================================================== + Description: + Look up a STA MAC table. Return its Sst to decide if an incoming + frame from this STA or an outgoing frame to this STA is permitted. + Return: + ========================================================================== +*/ +MAC_TABLE_ENTRY *APSsPsInquiry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + if (MAC_ADDR_IS_GROUP(pAddr)) /* mcast & broadcast address */ + { + *Sst = SST_ASSOC; + *Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index */ + *PsMode = PWR_ACTIVE; + *Rate = pAd->CommonCfg.MlmeRate; + } + else /* unicast address */ + { + pEntry = MacTableLookup(pAd, pAddr); + if (pEntry) + { + *Sst = pEntry->Sst; + *Aid = pEntry->Aid; + *PsMode = pEntry->PsMode; + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEntry->GTKState != REKEY_ESTABLISHED)) + *Rate = pAd->CommonCfg.MlmeRate; + else + *Rate = pEntry->CurrTxRate; + } + else + { + *Sst = SST_NOT_AUTH; + *Aid = MCAST_WCID; + *PsMode = PWR_ACTIVE; + *Rate = pAd->CommonCfg.MlmeRate; + } + } + + return pEntry; +} + + +#ifdef SYSTEM_LOG_SUPPORT +/* + ========================================================================== + Description: + This routine is called to log a specific event into the event table. + The table is a QUERY-n-CLEAR array that stop at full. + ========================================================================== + */ +VOID ApLogEvent( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Event) +{ + if (pAd->EventTab.Num < MAX_NUM_OF_EVENT) + { + RT_802_11_EVENT_LOG *pLog = &pAd->EventTab.Log[pAd->EventTab.Num]; + RTMP_GetCurrentSystemTime(&pLog->SystemTime); + COPY_MAC_ADDR(pLog->Addr, pAddr); + pLog->Event = Event; + DBGPRINT_RAW(RT_DEBUG_TRACE,("LOG#%ld %02x:%02x:%02x:%02x:%02x:%02x %s\n", + pAd->EventTab.Num, pAddr[0], pAddr[1], pAddr[2], + pAddr[3], pAddr[4], pAddr[5], pEventText[Event])); + pAd->EventTab.Num += 1; + } +} +#endif /* SYSTEM_LOG_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + Operationg mode is as defined at 802.11n for how proteciton in this BSS operates. + Ap broadcast the operation mode at Additional HT Infroamtion Element Operating Mode fields. + 802.11n D1.0 might has bugs so this operating mode use EWC MAC 1.24 definition first. + + Called when receiving my bssid beacon or beaconAtJoin to update protection mode. + 40MHz or 20MHz protection mode in HT 40/20 capabale BSS. + As STA, this obeys the operation mode in ADDHT IE. + As AP, update protection when setting ADDHT IE and after new STA joined. + ========================================================================== +*/ +VOID APUpdateOperationMode( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN bDisableBGProtect = FALSE, bNonGFExist = FALSE; + + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; + if ((pAd->ApCfg.LastNoneHTOLBCDetectTime + (5 * OS_HZ)) > pAd->Mlme.Now32) /* non HT BSS exist within 5 sec */ + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 1; + bDisableBGProtect = FALSE; + bNonGFExist = TRUE; + } + + /* If I am 40MHz BSS, and there exist HT-20MHz station. */ + /* Update to 2 when it's zero. Because OperaionMode = 1 or 3 has more protection. */ + if ((pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode == 0) && + (pAd->MacTab.fAnyStation20Only) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == 1)) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 2; + bDisableBGProtect = TRUE; + } + + if (pAd->MacTab.fAnyStationIsLegacy) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 3; + bDisableBGProtect = TRUE; + } + + if (pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode == 0 && + !ERP_IS_USE_PROTECTION(pAd->ApCfg.ErpIeContent)) + { + bDisableBGProtect = TRUE; + } + + if (bNonGFExist == FALSE) + bNonGFExist = pAd->MacTab.fAnyStationNonGF; + + AsicUpdateProtect(pAd, + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, + (ALLN_SETPROTECT), + bDisableBGProtect, + bNonGFExist); + + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = pAd->MacTab.fAnyStationNonGF; +} +#endif /* DOT11_N_SUPPORT */ + +/* + ========================================================================== + Description: + Update ERP IE and CapabilityInfo based on STA association status. + The result will be auto updated into the next outgoing BEACON in next + TBTT interrupt service routine + ========================================================================== + */ +VOID APUpdateCapabilityAndErpIe( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, ErpIeContent = 0; + BOOLEAN ShortSlotCapable = pAd->CommonCfg.bUseShortSlotTime; + UCHAR apidx; + BOOLEAN bUseBGProtection; + BOOLEAN LegacyBssExist; + + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + return; + + for (i=1; iMacTab.Content[i]; + if (!IS_ENTRY_CLIENT(pEntry) || (pEntry->Sst != SST_ASSOC)) + continue; + + /* at least one 11b client associated, turn on ERP.NonERPPresent bit */ + /* almost all 11b client won't support "Short Slot" time, turn off for maximum compatibility */ + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + ShortSlotCapable = FALSE; + ErpIeContent |= 0x01; + } + + /* at least one client can't support short slot */ + if ((pEntry->CapabilityInfo & 0x0400) == 0) + ShortSlotCapable = FALSE; + } + + /* legacy BSS exist within 5 sec */ + if ((pAd->ApCfg.LastOLBCDetectTime + (5 * OS_HZ)) > pAd->Mlme.Now32) + LegacyBssExist = TRUE; + else + LegacyBssExist = FALSE; + + /* decide ErpIR.UseProtection bit, depending on pAd->CommonCfg.UseBGProtection + AUTO (0): UseProtection = 1 if any 11b STA associated + ON (1): always USE protection + OFF (2): always NOT USE protection + */ + if (pAd->CommonCfg.UseBGProtection == 0) + { + ErpIeContent = (ErpIeContent)? 0x03 : 0x00; + /*if ((pAd->ApCfg.LastOLBCDetectTime + (5 * OS_HZ)) > pAd->Mlme.Now32) // legacy BSS exist within 5 sec */ + if (LegacyBssExist) + { + ErpIeContent |= 0x02; /* set Use_Protection bit */ + } + } + else if (pAd->CommonCfg.UseBGProtection == 1) + ErpIeContent |= 0x02; + + + bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || /* always use */ + ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(ErpIeContent)); + +#ifdef A_BAND_SUPPORT + /* always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP */ + if (pAd->CommonCfg.Channel > 14) + bUseBGProtection = FALSE; +#endif /* A_BAND_SUPPORT */ + + if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + USHORT OperationMode = 0; + BOOLEAN bNonGFExist = 0; + +#ifdef DOT11_N_SUPPORT + OperationMode = pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode; + bNonGFExist = pAd->MacTab.fAnyStationNonGF; +#endif /* DOT11_N_SUPPORT */ + if (bUseBGProtection) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, OperationMode, (OFDMSETPROTECT), FALSE, bNonGFExist); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, OperationMode, (OFDMSETPROTECT), TRUE, bNonGFExist); + } + } + + /* Decide Barker Preamble bit of ERP IE */ + if ((pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong) || (ApCheckLongPreambleSTA(pAd) == TRUE)) + pAd->ApCfg.ErpIeContent = (ErpIeContent | 0x04); + else + pAd->ApCfg.ErpIeContent = ErpIeContent; + +#ifdef A_BAND_SUPPORT + /* Force to use ShortSlotTime at A-band */ + if (pAd->CommonCfg.Channel > 14) + ShortSlotCapable = TRUE; +#endif /* A_BAND_SUPPORT */ + + /* deicide CapabilityInfo.ShortSlotTime bit */ + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + USHORT *pCapInfo = &(pAd->ApCfg.MBSSID[apidx].CapabilityInfo); + + /* In A-band, the ShortSlotTime bit should be ignored. */ + if (ShortSlotCapable +#ifdef A_BAND_SUPPORT + && (pAd->CommonCfg.Channel <= 14) +#endif /* A_BAND_SUPPORT */ + ) + (*pCapInfo) |= 0x0400; + else + (*pCapInfo) &= 0xfbff; + + + if (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong) + (*pCapInfo) &= (~0x020); + else + (*pCapInfo) |= 0x020; + + } + + AsicSetSlotTime(pAd, ShortSlotCapable); + +} + +/* + ========================================================================== + Description: + Check to see the exist of long preamble STA in associated list + ========================================================================== + */ +BOOLEAN ApCheckLongPreambleSTA( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + + for (i=0; iMacTab.Content[i]; + if (!IS_ENTRY_CLIENT(pEntry) || (pEntry->Sst != SST_ASSOC)) + continue; + + if (!CAP_IS_SHORT_PREAMBLE_ON(pEntry->CapabilityInfo)) + { + return TRUE; + } + } + + return FALSE; +} + +/* + ========================================================================== + Description: + Check if the specified STA pass the Access Control List checking. + If fails to pass the checking, then no authentication nor association + is allowed + Return: + MLME_SUCCESS - this STA passes ACL checking + + ========================================================================== +*/ +BOOLEAN ApCheckAccessControlList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR Apidx) +{ + BOOLEAN Result = TRUE; + +#ifdef CUSTOMER_DCC_FEATURE + if (pAd->ApDisableSTAConnectFlag == TRUE) + { + INT count, i; + UINT32 time; + + Result = FALSE; + time = jiffies_to_msecs(jiffies); + count = pAd->AllowedStaList.StaCount; + for (i = 0; i < count; i++) + { + if (NdisEqualMemory(&(pAd->AllowedStaList.AllowedSta[i].MacAddr[0]), pAddr, MAC_ADDR_LEN)) + { + if ((time - pAd->AllowedStaList.AllowedSta[i].DissocTime) < 30000) + { + Result = TRUE; + } + } + } + + if (!Result) + return Result; + } +#endif + if (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 0) /* ACL is disabled */ + Result = TRUE; + else + { + ULONG i; + if (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 1) /* ACL is a positive list */ + Result = FALSE; + else /* ACL is a negative list */ + Result = TRUE; + for (i=0; iApCfg.MBSSID[Apidx].AccessControlList.Num; i++) + { + if (MAC_ADDR_EQUAL(pAddr, pAd->ApCfg.MBSSID[Apidx].AccessControlList.Entry[i].Addr)) + { + Result = !Result; + break; + } + } + } + +#ifdef SMART_MESH + if (pAd->ApCfg.MBSSID[Apidx].SmartMeshCfg.bSupportSmartMesh && + !pAd->ApCfg.MBSSID[Apidx].bSmartMeshACL) + Result = TRUE; +#endif /* SMART_MESH */ + + if (Result == FALSE) + { + CHAR *pRange = (pAd->CommonCfg.Channel <= 14) ? "2.4" : "5"; + printk("AP %sGHz - access denied for client MAC [%02x:%02x:%02x:%02x:%02x:%02x]!\n", + pRange, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5]); + } + + return Result; +} + +/* + ========================================================================== + Description: + This routine update the current MAC table based on the current ACL. + If ACL change causing an associated STA become un-authorized. This STA + will be kicked out immediately. + ========================================================================== +*/ +VOID ApUpdateAccessControlList(RTMP_ADAPTER *pAd, UCHAR Apidx) +{ + USHORT AclIdx, MacIdx; + BOOLEAN Matched; + + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DisassocHdr; + USHORT Reason; + MAC_TABLE_ENTRY *pEntry; + MULTISSID_STRUCT *pMbss; + BOOLEAN drop; + + ASSERT(Apidx < MAX_MBSSID_NUM(pAd)); + if (Apidx >= MAX_MBSSID_NUM(pAd)) + return; + DBGPRINT(RT_DEBUG_TRACE, ("ApUpdateAccessControlList : Apidx = %d\n", Apidx)); + + /* ACL is disabled. Do nothing about the MAC table. */ + pMbss = &pAd->ApCfg.MBSSID[Apidx]; + if (pMbss->AccessControlList.Policy == 0) + return; + + for (MacIdx=0; MacIdx < MAX_LEN_OF_MAC_TABLE; MacIdx++) + { + pEntry = &pAd->MacTab.Content[MacIdx]; + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + /* We only need to update associations related to ACL of MBSSID[Apidx]. */ + if (pEntry->apidx != Apidx) + continue; + + drop = FALSE; + Matched = FALSE; + for (AclIdx = 0; AclIdx < pMbss->AccessControlList.Num; AclIdx++) + { + if (MAC_ADDR_EQUAL(&pEntry->Addr[0], pMbss->AccessControlList.Entry[AclIdx].Addr)) + { + Matched = TRUE; + break; + } + } + + if ((Matched == FALSE) && (pMbss->AccessControlList.Policy == 1)) + { + drop = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("STA not on positive ACL. remove it...\n")); + } + else if ((Matched == TRUE) && (pMbss->AccessControlList.Policy == 2)) + { + drop = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("STA on negative ACL. remove it...\n")); + } + + if (drop == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("Apidx = %d\n", Apidx)); + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.MBSSID[%d].AccessControlList.Policy = %ld\n", Apidx, + pMbss->AccessControlList.Policy)); + + /* Before delete the entry from MacTable, send disassociation packet to client. */ + if (pEntry->Sst == SST_ASSOC) + { + /* send out a DISASSOC frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n")); + return; + } + + Reason = REASON_DECLINED; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOC - Send DISASSOC Reason = %d frame TO %x %x %x %x %x %x \n", + Reason, PRINT_MAC(pEntry->Addr))); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, + pEntry->Addr, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &DisassocHdr, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RtmpusecDelay(5000); + } + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } +} + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +/* + Depends on the 802.11n Draft 4.0, Before the HT AP start a BSS, it should scan some specific channels to +collect information of existing BSSs, then depens on the collected channel information, adjust the primary channel +and secondary channel setting. + + For 5GHz, + Rule 1: If the AP chooses to start a 20/40 MHz BSS in 5GHz and that occupies the same two channels + as any existing 20/40 MHz BSSs, then the AP shall ensure that the primary channel of the + new BSS is identical to the primary channel of the existing 20/40 MHz BSSs and that the + secondary channel of the new 20/40 MHz BSS is identical to the secondary channel of the + existing 20/40 MHz BSSs, unless the AP discoverr that on those two channels are existing + 20/40 MHz BSSs with different primary and secondary channels. + Rule 2: If the AP chooses to start a 20/40MHz BSS in 5GHz, the selected secondary channel should + correspond to a channel on which no beacons are detected during the overlapping BSS + scan time performed by the AP, unless there are beacons detected on both the selected + primary and secondary channels. + Rule 3: An HT AP should not start a 20 MHz BSS in 5GHz on a channel that is the secondary channel + of a 20/40 MHz BSS. + For 2.4GHz, + Rule 1: The AP shall not start a 20/40 MHz BSS in 2.4GHz if the value of the local variable "20/40 + Operation Permitted" is FALSE. + + 20/40OperationPermitted = (P == OPi for all values of i) AND + (P == OTi for all values of i) AND + (S == OSi for all values if i) + where + P is the operating or intended primary channel of the 20/40 MHz BSS + S is the operating or intended secondary channel of the 20/40 MHz BSS + OPi is member i of the set of channels that are members of the channel set C and that are the + primary operating channel of at least one 20/40 MHz BSS that is detected within the AP's + BSA during the previous X seconds + OSi is member i of the set of channels that are members of the channel set C and that are the + secondary operating channel of at least one 20/40 MHz BSS that is detected within AP's + BSA during the previous X seconds + OTi is member i of the set of channels that comparises all channels that are members of the + channel set C that were listed once in the Channel List fields of 20/40 BSS Intolerant Channel + Report elements receved during the previous X seconds and all channels that are members + of the channel set C and that are the primary operating channel of at least one 20/40 MHz + BSS that were detected within the AP's BSA during the previous X seconds. + C is the set of all channels that are allowed operating channels within the current operational + regulatory domain and whose center frequency falls within the 40 MHz affected channel + range given by following equation: + Fp + Fs Fp + Fs + 40MHz affected channel range = [ ------ - 25MHz, ------- + 25MHz ] + 2 2 + Where + Fp = the center frequency of channel P + Fs = the center frequency of channel S + + "==" means that the values on either side of the "==" are to be tested for equaliy with a resulting + Boolean value. + =>When the value of OPi is the empty set, then the expression (P == OPi for all values of i) + is defined to be TRUE + =>When the value of OTi is the empty set, then the expression (P == OTi for all values of i) + is defined to be TRUE + =>When the value of OSi is the empty set, then the expression (S == OSi for all values of i) + is defined to be TRUE +*/ + + +INT GetBssCoexEffectedChRange( + IN RTMP_ADAPTER *pAd, + IN BSS_COEX_CH_RANGE *pCoexChRange) +{ + INT index, cntrCh = 0; + + memset(pCoexChRange, 0, sizeof(BSS_COEX_CH_RANGE)); + + /* Build the effected channel list, if something wrong, return directly. */ +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { /* For 5GHz band */ + for (index = 0; index < pAd->ChannelListNum; index++) + { + if(pAd->ChannelList[index].Channel == pAd->CommonCfg.Channel) + break; + } + + if (index < pAd->ChannelListNum) + { + /* First get the primary channel */ + pCoexChRange->primaryCh = pAd->ChannelList[index].Channel; + + /* Now check about the secondary and central channel */ + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + pCoexChRange->effectChStart = pCoexChRange->primaryCh; + pCoexChRange->effectChEnd = pCoexChRange->primaryCh + 4; + pCoexChRange->secondaryCh = pCoexChRange->effectChEnd; + } + else + { + pCoexChRange->effectChStart = pCoexChRange->primaryCh -4; + pCoexChRange->effectChEnd = pCoexChRange->primaryCh; + pCoexChRange->secondaryCh = pCoexChRange->effectChStart; + } + + DBGPRINT(RT_DEBUG_TRACE,("5.0GHz: Found CtrlCh idx(%d) from the ChList, ExtCh=%s, PriCh=[Idx:%d, CH:%d], SecCh=[Idx:%d, CH:%d], effected Ch=[CH:%d~CH:%d]!\n", + index, + ((pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) ? "ABOVE" : "BELOW"), + pCoexChRange->primaryCh, pAd->ChannelList[pCoexChRange->primaryCh].Channel, + pCoexChRange->secondaryCh, pAd->ChannelList[pCoexChRange->secondaryCh].Channel, + pAd->ChannelList[pCoexChRange->effectChStart].Channel, + pAd->ChannelList[pCoexChRange->effectChEnd].Channel)); + return TRUE; + } + else + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("5GHz: Cannot found the CtrlCh(%d) in ChList, something wrong?\n", + pAd->CommonCfg.Channel)); + } + } + else +#endif /* A_BAND_SUPPORT */ + { /* For 2.4GHz band */ + for (index = 0; index < pAd->ChannelListNum; index++) + { + if(pAd->ChannelList[index].Channel == pAd->CommonCfg.Channel) + break; + } + + if (index < pAd->ChannelListNum) + { + /* First get the primary channel */ + pCoexChRange->primaryCh = index; + + /* Now check about the secondary and central channel */ + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + if ((index + 4) < pAd->ChannelListNum) + { + cntrCh = index + 2; + pCoexChRange->secondaryCh = index + 4; + } + } + else + { + if ((index - 4) >=0) + { + cntrCh = index - 2; + pCoexChRange->secondaryCh = index - 4; + } + } + + if (cntrCh) + { + pCoexChRange->effectChStart = (cntrCh - 5) > 0 ? (cntrCh - 5) : 0; + pCoexChRange->effectChEnd= (cntrCh + 5) > 0 ? (cntrCh + 5) : 0; + DBGPRINT(RT_DEBUG_TRACE,("2.4GHz: Found CtrlCh idx(%d) from the ChList, ExtCh=%s, PrimaryCh=[Idx:%d, CH:%d], SecondaryCh=[Idx:%d, CH:%d], effected Ch=[CH:%d~CH:%d]!\n", + index, + ((pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) ? "ABOVE" : "BELOW"), + pCoexChRange->primaryCh, pAd->ChannelList[pCoexChRange->primaryCh].Channel, + pCoexChRange->secondaryCh, pAd->ChannelList[pCoexChRange->secondaryCh].Channel, + pAd->ChannelList[pCoexChRange->effectChStart].Channel, + pAd->ChannelList[pCoexChRange->effectChEnd].Channel)); + } + return TRUE; + } + + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("2.4GHz: Didn't found valid channel range, Ch index=%d, ChListNum=%d, CtrlCh=%d\n", + index, pAd->ChannelListNum, pAd->CommonCfg.Channel)); + } + + return FALSE; +} + + +VOID APOverlappingBSSScan(RTMP_ADAPTER *pAd) +{ + BOOLEAN needFallBack = FALSE; + UCHAR Channel = pAd->CommonCfg.Channel; + INT chStartIdx, chEndIdx, index,curPriChIdx, curSecChIdx; + + if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || (pAd->CommonCfg.Channel > 14)) { + DBGPRINT(RT_DEBUG_TRACE, ("The PhyMode=%d, Channel=%d didn't need channel adjustment!\n", + pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); + return; + } + + /* Build the effected channel list, if something wrong, return directly. */ +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { /* For 5GHz band */ + for (index = 0; index < pAd->ChannelListNum; index++) + { + if(pAd->ChannelList[index].Channel == pAd->CommonCfg.Channel) + break; + } + + if (index < pAd->ChannelListNum) + { + curPriChIdx = index; + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + chStartIdx = index; + chEndIdx = chStartIdx + 1; + curSecChIdx = chEndIdx; + } + else + { + chStartIdx = index - 1; + chEndIdx = index; + curSecChIdx = chStartIdx; + } + } + else + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("5GHz: Cannot found the ControlChannel(%d) in ChannelList, something wrong?\n", + pAd->CommonCfg.Channel)); + return; + } + } + else +#endif /* A_BAND_SUPPORT */ + { /* For 2.4GHz band */ + for (index = 0; index < pAd->ChannelListNum; index++) + { + if(pAd->ChannelList[index].Channel == pAd->CommonCfg.Channel) + break; + } + + if (index < pAd->ChannelListNum) + { + + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + curPriChIdx = index; + curSecChIdx = ((index + 4) < pAd->ChannelListNum) ? (index + 4) : (pAd->ChannelListNum - 1); + + chStartIdx = (curPriChIdx >= 3) ? (curPriChIdx - 3) : 0; + chEndIdx = ((curSecChIdx + 3) < pAd->ChannelListNum) ? (curSecChIdx + 3) : (pAd->ChannelListNum - 1); + } + else + { + curPriChIdx = index; + curSecChIdx = ((index - 4) >=0 ) ? (index - 4) : 0; + chStartIdx =(curSecChIdx >= 3) ? (curSecChIdx - 3) : 0; + chEndIdx = ((curPriChIdx + 3) < pAd->ChannelListNum) ? (curPriChIdx + 3) : (pAd->ChannelListNum - 1); + } + } + else + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("2.4GHz: Cannot found the Control Channel(%d) in ChannelList, something wrong?\n", + pAd->CommonCfg.Channel)); + return; + } + } + +{ + BSS_COEX_CH_RANGE coexChRange; + GetBssCoexEffectedChRange(pAd, &coexChRange); +} + + /* Before we do the scanning, clear the bEffectedChannel as zero for latter use. */ + for (index = 0; index < pAd->ChannelListNum; index++) + pAd->ChannelList[index].bEffectedChannel = 0; + + pAd->CommonCfg.BssCoexApCnt = 0; + + /* If we are not ready for Tx/Rx Pakcet, enable it now for receiving Beacons. */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Card still not enable Tx/Rx, enable it now!\n")); +#ifdef RTMP_MAC_PCI + /* Enable Interrupt */ + rtmp_irq_init(pAd); + + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + + /* Now Enable RxTx */ + RTMPEnableRxTx(pAd); + + /* rtmp_rx_done_handle() API will check this flag to decide accept incoming packet or not. */ + /* Set the flag be ready to receive Beacon frame for autochannel select. */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + } + + + DBGPRINT(RT_DEBUG_TRACE, ("Ready to do passive scanning for Channel[%d] to Channel[%d]!\n", + pAd->ChannelList[chStartIdx].Channel, pAd->ChannelList[chEndIdx].Channel)); + + /* Now start to do the passive scanning. */ + pAd->CommonCfg.bOverlapScanning = TRUE; + for (index = chStartIdx; index<=chEndIdx; index++) + { + Channel = pAd->ChannelList[index].Channel; + AsicSetChannel(pAd, Channel, BW_20, EXTCHA_NONE, TRUE); + + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - BBP R4 to 20MHz.l\n")); + /*DBGPRINT(RT_DEBUG_TRACE, ("Passive scanning for Channel %d.....\n", Channel)); */ + OS_WAIT(300); /* wait for 200 ms at each channel. */ + } + pAd->CommonCfg.bOverlapScanning = FALSE; + + /* After scan all relate channels, now check the scan result to find out if we need fallback to 20MHz. */ + for (index = chStartIdx; index <= chEndIdx; index++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Channel[Idx=%d, Ch=%d].bEffectedChannel=0x%x!\n", + index, pAd->ChannelList[index].Channel, pAd->ChannelList[index].bEffectedChannel)); + if ((pAd->ChannelList[index].bEffectedChannel & (EFFECTED_CH_PRIMARY | EFFECTED_CH_LEGACY)) && (index != curPriChIdx) ) + { + needFallBack = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("needFallBack=TRUE due to OP/OT!\n")); + } + if ((pAd->ChannelList[index].bEffectedChannel & EFFECTED_CH_SECONDARY) && (index != curSecChIdx)) + { + needFallBack = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("needFallBack=TRUE due to OS!\n")); + } + } + + /* If need fallback, now do it. */ + if ((needFallBack == TRUE) + && (pAd->CommonCfg.BssCoexApCnt > pAd->CommonCfg.BssCoexApCntThr) + ) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 1; + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; + pAd->CommonCfg.Bss2040NeedFallBack = 1; + //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = 0; + } + + /* Recover the bandwidth to support 20/40Mhz if the original setting does support that, and no need to fallback */ + if ((needFallBack == FALSE) + && (pAd->CommonCfg.ori_bw_before_2040_coex == BW_40)) { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = pAd->CommonCfg.ori_bw_before_2040_coex; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.ori_ext_channel_before_2040_coex; + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 0; + pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_INFO_SYNC); + pAd->CommonCfg.Bss2040NeedFallBack = 0; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = pAd->CommonCfg.ori_ext_channel_before_2040_coex; + DBGPRINT(RT_DEBUG_ERROR, ("rollback the bandwidth setting to support 20/40Mhz\n")); + } + + return; +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT1X_SUPPORT +/* + ======================================================================== + Routine Description: + Send Leyer 2 Frame to notify 802.1x daemon. This is a internal command + + Arguments: + + Return Value: + TRUE - send successfully + FAIL - send fail + + Note: + ======================================================================== +*/ +BOOLEAN DOT1X_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UINT8 cmd) +{ + INT apidx = MAIN_MBSSID; + UCHAR RalinkIe[9] = {221, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; + UCHAR s_addr[MAC_ADDR_LEN]; + UCHAR EAPOL_IE[] = {0x88, 0x8e}; + UINT8 frame_len = LENGTH_802_3 + sizeof(RalinkIe); + UCHAR FrameBuf[frame_len]; + UINT8 offset = 0; + + /* Init the frame buffer */ + NdisZeroMemory(FrameBuf, frame_len); + + if (pEntry) + { + apidx = pEntry->apidx; + NdisMoveMemory(s_addr, pEntry->Addr, MAC_ADDR_LEN); + } + else + { + /* Fake a Source Address for transmission */ + NdisMoveMemory(s_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + s_addr[0] |= 0x80; + } + + /* Assign internal command for Ralink dot1x daemon */ + RalinkIe[5] = cmd; + + /* Prepare the 802.3 header */ + MAKE_802_3_HEADER(FrameBuf, + pAd->ApCfg.MBSSID[apidx].wdev.bssid, + s_addr, + EAPOL_IE); + offset += LENGTH_802_3; + + /* Prepare the specific header of internal command */ + NdisMoveMemory(&FrameBuf[offset], RalinkIe, sizeof(RalinkIe)); + + /* Report to upper layer */ + if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s done. (cmd=%d)\n", __FUNCTION__, cmd)); + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Send Leyer 2 Frame to trigger 802.1x EAP state machine. + + Arguments: + + Return Value: + TRUE - send successfully + FAIL - send fail + + Note: + ======================================================================== +*/ +BOOLEAN DOT1X_EapTriggerAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + INT apidx = MAIN_MBSSID; + UCHAR eapol_start_1x_hdr[4] = {0x01, 0x01, 0x00, 0x00}; + UINT8 frame_len = LENGTH_802_3 + sizeof(eapol_start_1x_hdr); + UCHAR FrameBuf[frame_len + 32]; + UINT8 offset = 0; + + if((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].wdev.IEEE8021X == TRUE)) + { + /* Init the frame buffer */ + NdisZeroMemory(FrameBuf, frame_len); + + /* Assign apidx */ + apidx = pEntry->apidx; + + /* Prepare the 802.3 header */ + MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].wdev.bssid, pEntry->Addr, EAPOL); + offset += LENGTH_802_3; + + /* Prepare a fake eapol-start body */ + NdisMoveMemory(&FrameBuf[offset], eapol_start_1x_hdr, sizeof(eapol_start_1x_hdr)); + +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if ((pMbss->HotSpotCtrl.HotSpotEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2) + && (pEntry->hs_info.ppsmo_exist == 1)) + { + UCHAR HS2_Header[4] = {0x50,0x6f,0x9a,0x12}; + memcpy(&FrameBuf[offset+sizeof(eapol_start_1x_hdr)], HS2_Header, 4); + memcpy(&FrameBuf[offset+sizeof(eapol_start_1x_hdr)+4], &pEntry->hs_info, sizeof(struct _sta_hs_info)); + frame_len += 4+sizeof(struct _sta_hs_info); + printk("event eapol start, %x:%x:%x:%x\n", + FrameBuf[offset+sizeof(eapol_start_1x_hdr)+4],FrameBuf[offset+sizeof(eapol_start_1x_hdr)+5], + FrameBuf[offset+sizeof(eapol_start_1x_hdr)+6],FrameBuf[offset+sizeof(eapol_start_1x_hdr)+7]); + } + } +#endif + + /* Report to upper layer */ + if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Notify 8021.x daemon to trigger EAP-SM for this sta(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pEntry->Addr))); + + } + + return TRUE; +} + +#endif /* DOT1X_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_apcli.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_apcli.c new file mode 100644 index 000000000..32f9e7b59 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_apcli.c @@ -0,0 +1,3859 @@ +/* + *************************************************************************** + * 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 +*/ + +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + +BOOLEAN ApCliWaitProbRsp(PRTMP_ADAPTER pAd, USHORT ifIndex) +{ + if (ifIndex >= MAX_APCLI_NUM) + return FALSE; + + return (pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState == APCLI_JOIN_WAIT_PROBE_RSP) ? + TRUE : FALSE; +} + +VOID ApCliSimulateRecvBeacon(RTMP_ADAPTER *pAd) +{ + INT loop; + ULONG Now32, BPtoJiffies; + PAPCLI_STRUCT pApCliEntry = NULL; + LONG timeDiff; + + NdisGetSystemUpTime(&Now32); + for (loop = 0; loop < MAX_APCLI_NUM; loop++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[loop]; + if ((pApCliEntry->Valid == TRUE) && (pApCliEntry->MacTabWCID < MAX_LEN_OF_MAC_TABLE)) + { + /* + When we are connected and do the scan progress, it's very possible we cannot receive + the beacon of the AP. So, here we simulate that we received the beacon. + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (RTMP_TIME_AFTER(pAd->Mlme.Now32, pApCliEntry->ApCliRcvBeaconTime + (1 * OS_HZ)))) + { + BPtoJiffies = (((pApCliEntry->ApCliBeaconPeriod * 1024 / 1000) * OS_HZ) / 1000); + timeDiff = (pAd->Mlme.Now32 - pApCliEntry->ApCliRcvBeaconTime) / BPtoJiffies; + if (timeDiff > 0) + pApCliEntry->ApCliRcvBeaconTime += (timeDiff * BPtoJiffies); + + if (RTMP_TIME_AFTER(pApCliEntry->ApCliRcvBeaconTime, pAd->Mlme.Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - APCli BeaconRxTime adjust wrong(BeaconRx=0x%lx, Now=0x%lx)\n", + pApCliEntry->ApCliRcvBeaconTime, pAd->Mlme.Now32)); + } + } + + /* update channel quality for Roaming and UI LinkQuality display */ + MlmeCalculateChannelQuality(pAd, &pAd->MacTab.Content[pApCliEntry->MacTabWCID], Now32); + } + } +} + +/* +======================================================================== +Routine Description: + Close ApCli network interface. + +Arguments: + ad_p points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_ApCli_Close(RTMP_ADAPTER *ad_p) +{ + UINT index; + + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + if (ad_p->ApCfg.ApCliTab[index].wdev.if_dev) + RtmpOSNetDevClose(ad_p->ApCfg.ApCliTab[index].wdev.if_dev); + } + +} + + +/* --------------------------------- Private -------------------------------- */ +INT ApCliIfLookUp(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + SHORT if_idx; + + for(if_idx = 0; if_idx < MAX_APCLI_NUM; if_idx++) + { + if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[if_idx].wdev.if_addr, pAddr)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():ApCliIfIndex=%d\n", + __FUNCTION__, if_idx)); + return if_idx; + } + } + + return -1; +} + + +BOOLEAN isValidApCliIf(SHORT if_idx) +{ + return (((if_idx >= 0) && (if_idx < MAX_APCLI_NUM)) ? TRUE : FALSE); +} + + +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->UserCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + */ +VOID ApCliMgtMacHeaderInit( + IN RTMP_ADAPTER *pAd, + INOUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pDA, + IN UCHAR *pBssid, + IN USHORT ifIndex) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + + Routine Description: + Verify the support rate for HT phy type + + Arguments: + pAd Pointer to our adapter + + Return Value: + FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +BOOLEAN ApCliCheckHt( + IN RTMP_ADAPTER *pAd, + IN USHORT IfIndex, + INOUT HT_CAPABILITY_IE *pHtCapability, + INOUT ADD_HT_INFO_IE *pAddHtInfo) +{ + APCLI_STRUCT *pApCliEntry = NULL; + HT_CAPABILITY_IE *aux_ht_cap; + RT_HT_CAPABILITY *rt_ht_cap = &pAd->CommonCfg.DesiredHtPhy; + + + if (IfIndex >= MAX_APCLI_NUM) + return FALSE; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + aux_ht_cap = &pApCliEntry->MlmeAux.HtCapability; + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[1] = 0x00; + aux_ht_cap->MCSSet[2] = 0x00; + aux_ht_cap->MCSSet[3] = 0x00; + break; + case 2: + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[1] = 0xff; + aux_ht_cap->MCSSet[2] = 0x00; + aux_ht_cap->MCSSet[3] = 0x00; + break; + case 3: + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[1] = 0xff; + aux_ht_cap->MCSSet[2] = 0xff; + aux_ht_cap->MCSSet[3] = 0x00; + break; + } + + /* Record the RxMcs of AP */ + NdisMoveMemory(pApCliEntry->RxMcsSet, pHtCapability->MCSSet, 16); + + /* choose smaller setting */ +#ifdef APCLI_AUTO_BW_SUPPORT + aux_ht_cap->HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pApCliEntry->wdev.bw; +#else + aux_ht_cap->HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & rt_ht_cap->ChannelWidth; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + aux_ht_cap->HtCapInfo.GF = pHtCapability->HtCapInfo.GF & rt_ht_cap->GF; + + /* Send Assoc Req with my HT capability. */ + aux_ht_cap->HtCapInfo.AMsduSize = rt_ht_cap->AmsduSize; + aux_ht_cap->HtCapInfo.MimoPs = pHtCapability->HtCapInfo.MimoPs; + aux_ht_cap->HtCapInfo.ShortGIfor20 = (rt_ht_cap->ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); + aux_ht_cap->HtCapInfo.ShortGIfor40 = (rt_ht_cap->ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + aux_ht_cap->HtCapInfo.TxSTBC = (rt_ht_cap->TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + aux_ht_cap->HtCapInfo.RxSTBC = (rt_ht_cap->RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + aux_ht_cap->HtCapParm.MaxRAmpduFactor = rt_ht_cap->MaxRAmpduFactor; + aux_ht_cap->HtCapParm.MpduDensity = pHtCapability->HtCapParm.MpduDensity; + aux_ht_cap->ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + aux_ht_cap->ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; + } + + if (pAd->CommonCfg.Channel < 14) { + pApCliEntry->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth = pAddHtInfo->AddHtInfo.RecomWidth; + pApCliEntry->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset = pAddHtInfo->AddHtInfo.ExtChanOffset; + pApCliEntry->MlmeAux.AddHtInfo.ControlChan = pAddHtInfo->ControlChan; + } + + /*COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); */ + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC +BOOLEAN ApCliCheckVht( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN MAC_TABLE_ENTRY *pEntry, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op) +{ + VHT_CAP_INFO *vht_cap_info = &vht_cap->vht_cap; + + // TODO: shiang-6590, not finish yet!!!! + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("============>ApCliCheckVht\n")); + /* Save Peer Capability*/ + if (vht_cap_info->sgi_80M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE); + + if (vht_cap_info->sgi_160M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE); + + if (pAd->CommonCfg.vht_stbc) { + if (vht_cap_info->tx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE); + if (vht_cap_info->rx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE); + } + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (vht_cap_info->rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE); + } + + /* Will check ChannelWidth for MCSSet[4] below */ + //NdisZeroMemory(&pApCliEntry->MlmeAux.vht_cap.mcs_set, sizeof(VHT_MCS_SET)); + //pApCliEntry->MlmeAux.vht_cap.mcs_set.rx_high_rate = pAd->CommonCfg.RxStream * 325; + //pApCliEntry->MlmeAux.vht_cap.mcs_set.tx_high_rate = pAd->CommonCfg.TxStream * 325; + + //pAd->MlmeAux.vht_cap.vht_cap.ch_width = vht_cap_info->ch_width; +#ifdef VHT_TXBF_SUPPORT + //Disable beamformee capability in Associate Request with 3x3 AP to avoid throughput drop issue + // MT76x2 only supports up to 2x2 sounding feedback + if(IS_MT76x2(pAd)) + { + if(vht_cap_info->num_snd_dimension >=2 ) + { + pAd->MlmeAux.vht_cap.vht_cap.bfee_cap_su = FALSE; + pAd->MlmeAux.vht_cap.vht_cap.bfee_cap_mu = FALSE; + + } + } +#endif /* TXBF_SUPPORT */ + pEntry->VhtMaxRAmpduFactor = vht_cap_info->max_ampdu_exp; + DBGPRINT(RT_DEBUG_WARN, ("%s():pEntry->VhtMaxRAmpduFactor =%d\n", + __FUNCTION__, pEntry->VhtMaxRAmpduFactor)); + + return TRUE; +} +#endif /* DOT11_VHT_AC */ + +VOID ComposeP2PPsPoll( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry) +{ + struct wifi_dev *wdev; + wdev = &pApCliEntry->wdev; + + NdisZeroMemory(&pApCliEntry->PsPollFrame, sizeof (PSPOLL_FRAME)); + pApCliEntry->PsPollFrame.FC.Type = FC_TYPE_CNTL; + pApCliEntry->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; + pApCliEntry->PsPollFrame.Aid = pAd->ApCfg.ApCliTab[0].MlmeAux.Aid | 0xC000; + + COPY_MAC_ADDR(pApCliEntry->PsPollFrame.Bssid, pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid); + COPY_MAC_ADDR(pApCliEntry->PsPollFrame.Ta, wdev->if_addr); +} + +VOID ComposeP2PNullFrame( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry) +{ + struct wifi_dev *wdev; + wdev = &pApCliEntry->wdev; + + NdisZeroMemory(&pApCliEntry->NullFrame, sizeof (HEADER_802_11)); + pApCliEntry->NullFrame.FC.Type = FC_TYPE_DATA; + pApCliEntry->NullFrame.FC.SubType = SUBTYPE_DATA_NULL; + pApCliEntry->NullFrame.FC.ToDs = 1; + + COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr1, pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid); + COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr2, wdev->if_addr); + COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr3, pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid); +} + +/* + ========================================================================== + + Routine Description: + Connected to the BSSID + + Arguments: + pAd - Pointer to our adapter + ApCliIdx - Which ApCli interface + Return Value: + FALSE: fail to alloc Mac entry. + + Note: + + ========================================================================== +*/ +BOOLEAN ApCliLinkUp(RTMP_ADAPTER *pAd, UCHAR ifIndex) +{ + BOOLEAN result = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + PMAC_TABLE_ENTRY pMacEntry = NULL; + struct wifi_dev *wdev; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; + INVAILD_TRIGGER_MAC_ENTRY *pSkipEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef APCLI_CERT_SUPPORT + UINT32 Data; +#endif /* APCLI_CERT_SUPPORT */ + UCHAR PhyMode = pAd->CommonCfg.PhyMode; +#ifdef MWDS + UCHAR ApCliIdx = 0; /* default use apcli0 */ +#endif /* MWDS */ + do + { +#ifdef MWDS + if (ifIndex < MAX_APCLI_NUM) + ApCliIdx = ifIndex; + else if(ifIndex >= 64) + ApCliIdx = ((ifIndex - 64) / 16); +#endif /* MWDS */ + + if ((ifIndex < MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + || (ifIndex >= 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) +#ifdef MWDS + && ((pAd->ApCfg.ApCliTab[ApCliIdx].bSupportMWDS == FALSE) || + (pAd->ApCfg.ApCliTab[ApCliIdx].MlmeAux.bSupportMWDS == FALSE)) +#endif /* MWDS */ + ) + { + if (ifIndex < MAX_APCLI_NUM) + { +#ifdef LINUX + struct net_device *pNetDev; + struct net *net= &init_net; + + for_each_netdev(net, pNetDev) + { + if (pNetDev->priv_flags == IFF_EBRIDGE) + { + COPY_MAC_ADDR(pAd->ApCfg.BridgeAddress, pNetDev->dev_addr); + DBGPRINT(RT_DEBUG_ERROR, (" Bridge Addr = %02X:%02X:%02X:%02X:%02X:%02X. !!!\n", + PRINT_MAC(pAd->ApCfg.BridgeAddress))); + + } + pSkipEntry = RepeaterInvaildMacLookup(pAd, pNetDev->dev_addr); + + if (pSkipEntry == NULL) + RTMPRepeaterInsertInvaildMacEntry(pAd, pNetDev->dev_addr); + } +#endif /* LINUX */ + } + + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + + pMacEntry = MacTableLookup(pAd, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].OriginalAddress); + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)) + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].bEthCli = FALSE; + else + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].bEthCli = TRUE; + + pMacEntry = NULL; + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK UP - IF(%s%d) AuthMode(%d)=%s, WepStatus(%d)=%s !!!\n", + INF_APCLI_DEV_NAME, ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode, GetAuthMode(pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode), + pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus, GetEncryptType(pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus))); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : APCLI LINK UP - IF(%s%d)!!!\n", INF_APCLI_DEV_NAME, ifIndex)); + result = FALSE; + break; + } + +#ifdef MAC_REPEATER_SUPPORT + if ((CliIdx != 0xFF) +#ifdef MWDS + && ((pAd->ApCfg.ApCliTab[ApCliIdx].bSupportMWDS == FALSE) || + (pAd->ApCfg.ApCliTab[ApCliIdx].MlmeAux.bSupportMWDS == FALSE)) +#endif /* MWDS */ + ) + DBGPRINT(RT_DEBUG_ERROR, ("(%s) ifIndex = %d, CliIdx = %d !!!\n", __FUNCTION__, ifIndex, CliIdx)); +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#ifndef APCLI_CONNECTION_TRIAL + if ((pApCliEntry->Valid) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link had existed - IF(%s%d)!!!\n", INF_APCLI_DEV_NAME, ifIndex)); + result = FALSE; + break; + } +#endif /* APCLI_CONNECTION_TRIAL */ + + wdev = &pApCliEntry->wdev; +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = wdev->PhyMode; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + printk("!!! APCLI LINK UP - IF(%s%d) AuthMode(%d)=%s, WepStatus(%d)=%s!\n", + INF_APCLI_DEV_NAME, ifIndex, + wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus)); + +#if defined (CONFIG_WIFI_PKT_FWD) +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + if (wf_fwd_get_rep_hook) + wf_fwd_get_rep_hook(pAd->CommonCfg.EtherTrafficBand); + + if (wf_fwd_entry_insert_hook) + wf_fwd_entry_insert_hook (wdev->if_dev, pAd->net_dev, pAd); + + if (wf_fwd_insert_repeater_mapping_hook) + wf_fwd_insert_repeater_mapping_hook (pAd, &pAd->ApCfg.ReptCliEntryLock, &pAd->ApCfg.ReptCliHash[0], &pAd->ApCfg.ReptMapHash[0], &pAd->ApCfg.ApCliTab[0].wdev.if_addr); + } + +#endif /* CONFIG_WIFI_PKT_FWD */ + + /* Insert the Remote AP to our MacTable. */ + /*pMacEntry = MacTableInsertApCliEntry(pAd, (PUCHAR)(pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid)); */ +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) +#ifdef MWDS + && (pApCliEntry != NULL) + && ((pApCliEntry->bSupportMWDS == FALSE) || + (pApCliEntry->MlmeAux.bSupportMWDS == FALSE)) +#endif /* MWDS */ + ) + pMacEntry = RTMPInsertRepeaterMacEntry(pAd, + (PUCHAR)(pApCliEntry->MlmeAux.Bssid), + wdev, + (ifIndex + MIN_NET_DEVICE_FOR_APCLI), + CliIdx, + TRUE); + else +#endif /* MAC_REPEATER_SUPPORT */ + pMacEntry = MacTableInsertEntry(pAd, (PUCHAR)(pApCliEntry->MlmeAux.Bssid), + wdev, (ifIndex + MIN_NET_DEVICE_FOR_APCLI), + OPMODE_AP, TRUE); + if (pMacEntry) + { + UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES]; + PUCHAR pRates = Rates; + UCHAR RatesLen; + UCHAR MaxSupportedRate = 0; + + pMacEntry->Sst = SST_ASSOC; + pMacEntry->wdev = &pApCliEntry->wdev; +#ifdef MAC_REPEATER_SUPPORT + if ((CliIdx != 0xFF) +#ifdef MWDS + && (pApCliEntry != NULL) + && ((pApCliEntry->bSupportMWDS == FALSE) || + (pApCliEntry->MlmeAux.bSupportMWDS == FALSE)) +#endif /* MWDS */ + ) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID = pMacEntry->Aid; + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = TRUE; + pMacEntry->bReptCli = TRUE; + pMacEntry->MatchReptCliIdx = CliIdx; + pMacEntry->ReptCliIdleCount = 0; + COPY_MAC_ADDR(pMacEntry->ReptCliAddr, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].bEthCli == TRUE) + pMacEntry->bReptEthCli = TRUE; + else + pMacEntry->bReptEthCli = FALSE; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = TRUE; + pApCliEntry->MacTabWCID = pMacEntry->wcid; +#ifdef MAC_REPEATER_SUPPORT + pMacEntry->bReptCli = FALSE; +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(&wdev->bssid[0], &pApCliEntry->MlmeAux.Bssid[0]); + COPY_MAC_ADDR(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID), pApCliEntry->MlmeAux.Bssid); + pApCliEntry->SsidLen = pApCliEntry->MlmeAux.SsidLen; + NdisMoveMemory(pApCliEntry->Ssid, pApCliEntry->MlmeAux.Ssid, pApCliEntry->SsidLen); + } + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + If ApCli connects to different AP, ApCli couldn't send EAPOL_Start for WpaSupplicant. + */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory(pAd->MlmeAux.Bssid, pApCliEntry->LastBssid, MAC_ADDR_LEN) == FALSE) && + (pApCliEntry->wpa_supplicant_info.bLostAp == TRUE)) + { + pApCliEntry->wpa_supplicant_info.bLostAp = FALSE; + } + + COPY_MAC_ADDR(pApCliEntry->LastBssid, pAd->MlmeAux.Bssid); +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef SMART_MESH + if(pApCliEntry->MlmeAux.bHyperFiPeer) + pMacEntry->bHyperFiPeer = TRUE; + else + pMacEntry->bHyperFiPeer = FALSE; +#endif /* SMART_MESH */ + + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP && + (pMacEntry->WepStatus == Ndis802_11WEPEnabled) && + (wdev->IEEE8021X == TRUE)) + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else +#endif /*WPA_SUPPLICANT_SUPPORT*/ + { + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef SMART_MESH + if(pApCliEntry && + pApCliEntry->MlmeAux.bSupportSmartMesh && + pApCliEntry->SmartMeshCfg.bSupportSmartMesh) + pMacEntry->bEnableSmartMesh = TRUE; + else + pMacEntry->bEnableSmartMesh = FALSE; +#endif /* SMART_MESH */ + +#ifdef MWDS +#ifdef WSC_AP_SUPPORT + BOOLEAN bWPSRunning = FALSE; + if (((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE))) + bWPSRunning = TRUE; +#endif /* WSC_AP_SUPPORT */ + if( +#ifdef WSC_AP_SUPPORT + !bWPSRunning && +#endif /* WSC_AP_SUPPORT */ + pApCliEntry->MlmeAux.bSupportMWDS && + pApCliEntry->bSupportMWDS) + { + pApCliEntry->bEnableMWDS = TRUE; + pMacEntry->bEnableMWDS = TRUE; + if((pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + SET_MWDS_OPMODE_APCLI(pMacEntry); + DBGPRINT(RT_DEBUG_ERROR, ("SET_MWDS_OPMODE_APCLI OK!\n")); + } + } + else + { + pApCliEntry->bEnableMWDS = FALSE; + pMacEntry->bEnableMWDS = FALSE; + SET_MWDS_OPMODE_NONE(pMacEntry); + } +#endif /* MWDS */ + } +#ifdef MAC_REPEATER_SUPPORT + if ((CliIdx != 0xFF) +#ifdef MWDS + && (pApCliEntry != NULL) + && ((pApCliEntry->bSupportMWDS == FALSE) || + (pApCliEntry->MlmeAux.bSupportMWDS == FALSE)) +#endif /* MWDS */ + ) + pApCliEntry->RepeaterCli[CliIdx].CliConnectState = 2; +#endif /* MAC_REPEATER_SUPPORT */ + } + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) && +#ifdef MAC_REPEATER_SUPPORT + (CliIdx == 0xFF) && +#endif /* MAC_REPEATER_SUPPORT */ + (pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCli auto connected: ApCliLinkUp()\n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + NdisGetSystemUpTime(&pApCliEntry->ApCliLinkUpTime); + + /* + Store appropriate RSN_IE for WPA SM negotiation later + If WPAPSK/WPA2SPK mix mode, driver just stores either WPAPSK or + WPA2PSK RSNIE. It depends on the AP-Client's authentication mode + to store the corresponding RSNIE. + */ + if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pApCliEntry->MlmeAux.VarIELen != 0)) + { + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + + pVIE = pApCliEntry->MlmeAux.VarIEs; + len = pApCliEntry->MlmeAux.VarIELen; + + while (len > 0) + { + pEid = (PEID_STRUCT) pVIE; + /* For WPA/WPAPSK */ + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && (pMacEntry->AuthMode == Ndis802_11AuthModeWPA || pMacEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pMacEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA SM negotiation \n")); + } + /* For WPA2/WPA2PSK */ + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + && (pMacEntry->AuthMode == Ndis802_11AuthModeWPA2 || pMacEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pMacEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA2 SM negotiation \n")); + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + } + + if (pMacEntry->RSNIE_Len == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: root-AP has no RSN_IE \n")); + } + else + { + hex_dump("The RSN_IE of root-AP", pMacEntry->RSN_IE, pMacEntry->RSNIE_Len); + } + + SupportRate(pApCliEntry->MlmeAux.SupRate, pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); + + pMacEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + pMacEntry->RateLen = RatesLen; + set_entry_phy_cfg(pAd, pMacEntry); + + pMacEntry->CapabilityInfo = pApCliEntry->MlmeAux.CapabilityInfo; + + pApCliEntry->ApCliBeaconPeriod = pApCliEntry->MlmeAux.BeaconPeriod; + + if ((wdev->WepStatus == Ndis802_11WEPEnabled) +#ifdef WPA_SUPPLICANT_SUPPORT + && (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + ) + { + CIPHER_KEY *pKey; + INT idx, BssIdx; + + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; +#ifdef MAC_APCLI_SUPPORT + BssIdx = APCLI_BSS_BASE + ifIndex; +#endif /* MAC_APCLI_SUPPORT */ + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + pKey = &pApCliEntry->SharedKey[idx]; + if (pKey->KeyLen > 0) + { + /* Set key material and cipherAlg to Asic */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BssIdx, + idx, + pKey); + } + + if (idx == wdev->DefaultKeyId) + { + INT cnt; + + /* Generate 3-bytes IV randomly for software encryption using */ + for(cnt = 0; cnt < LEN_WEP_TSC; cnt++) + pKey->TxTsc[cnt] = RandomByte(pAd); + + RTMP_SET_WCID_SEC_INFO(pAd, + BssIdx, + idx, + pKey->CipherAlg, + pMacEntry->wcid, + SHAREDKEYTABLE); + } + } + } + } + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (pApCliEntry->MlmeAux.HtCapabilityLen != 0) + { + PHT_CAPABILITY_IE pHtCapability = (PHT_CAPABILITY_IE)&pApCliEntry->MlmeAux.HtCapability; + + ht_mode_adjust(pAd, pMacEntry, pHtCapability, &pAd->CommonCfg.DesiredHtPhy); + + /* find max fixed rate */ + pMacEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], + &pHtCapability->MCSSet[0]); + + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-%s%d : Desired MCS = %d\n", + INF_APCLI_DEV_NAME, ifIndex, wdev->DesiredTransmitSetting.field.MCS)); + + set_ht_fixed_mcs(pAd, pMacEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + } + + pMacEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + if (pHtCapability->HtCapParm.MpduDensity < 5) + pMacEntry->MpduDensity = 5; + else + pMacEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pMacEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; + pMacEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; + pMacEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED); + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pHtCapability->ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + NdisMoveMemory(&pMacEntry->HTCapability, &pApCliEntry->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(pMacEntry->HTCapability.MCSSet, pApCliEntry->RxMcsSet, 16); + } + else + { + pAd->MacTab.fAnyStationIsLegacy = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp - MaxSupRate=%d Mbps\n", + RateIdToMbps[pMacEntry->MaxSupportedRate])); + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && pApCliEntry->MlmeAux.vht_cap_len && pApCliEntry->MlmeAux.vht_op_len) + { + vht_mode_adjust(pAd, pMacEntry, &(pApCliEntry->MlmeAux.vht_cap), &(pApCliEntry->MlmeAux.vht_op)); + ApCliCheckVht(pAd,pMacEntry->Aid, pMacEntry,&(pApCliEntry->MlmeAux.vht_cap), &(pApCliEntry->MlmeAux.vht_op)); + } +#endif /* DOT11_VHT_AC */ + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + pMacEntry->CurrTxRate = pMacEntry->MaxSupportedRate; + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pMacEntry, + pApCliEntry->MlmeAux.SupRate, + pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, +#ifdef DOT11_VHT_AC + pApCliEntry->MlmeAux.vht_cap_len, + &pApCliEntry->MlmeAux.vht_cap, +#endif /* DOT11_VHT_AC */ + &pApCliEntry->MlmeAux.HtCapability, + pApCliEntry->MlmeAux.HtCapabilityLen); + + if (wdev->bAutoTxRateSwitch == FALSE) + { + pMacEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pMacEntry); + } + else + { + UCHAR TableSize = 0; + + pMacEntry->bAutoTxRateSwitch = TRUE; + MlmeSelectTxRateTable(pAd, pMacEntry, &pMacEntry->pTable, &TableSize, &pMacEntry->CurrTxRateIndex); + MlmeNewTxRate(pAd, pMacEntry); +#ifdef NEW_RATE_ADAPT_SUPPORT + if (! ADAPT_RATE_TABLE(pMacEntry->pTable)) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pMacEntry->HTPhyMode.field.ShortGI = GI_800; + } + + /* set this entry WMM capable or not */ + if ((pApCliEntry->MlmeAux.APEdcaParm.bValid) +#ifdef DOT11_N_SUPPORT + || IS_HT_STA(pMacEntry) +#endif /* DOT11_N_SUPPORT */ + ) + { +#ifdef APCLI_CERT_SUPPORT + if (pApCliEntry->wdev.bWmmCapable == TRUE) + { + AsicSetEdcaParm(pAd, &pApCliEntry->MlmeAux.APEdcaParm); + pAd->ApCfg.BssEdcaParm.EdcaUpdateCount++; + } +#endif /* APCLI_CERT_SUPPORT */ + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && (pApCliEntry->MlmeAux.APRalinkIe & 0x00000003) == 3) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + RTMPSetPiggyBack(pAd, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); + } + else if (pApCliEntry->MlmeAux.APRalinkIe & 0x00000001) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink Aggregation\n")); + } + } + + /* Set falg to identify if peer AP is Ralink chipset */ + if (pApCliEntry->MlmeAux.APRalinkIe != 0x0) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET); + else + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET); + + NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); + /* set the apcli interface be valid. */ +#ifdef MAC_APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if ((CliIdx == 0xFF) +#ifdef APCLI_CONNECTION_TRIAL + && (pApCliEntry->TrialCh == 0) +#endif /* APCLI_CONNECTION_TRIAL */ + ) +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* MAC_APCLI_SUPPORT */ + { + pApCliEntry->Valid = TRUE; + pApCliEntry->wdev.allow_data_tx = TRUE; + pApCliEntry->wdev.PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef MAC_APCLI_SUPPORT + AsicSetApCliBssid(pAd, pApCliEntry->MlmeAux.Bssid, ifIndex); +#endif /* MAC_APCLI_SUPPORT */ + } + result = TRUE; + pAd->ApCfg.ApCliInfRunned++; + + break; + } + result = FALSE; + } while(FALSE); + + + if (result == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, (" (%s) alloc mac entry fail!!!\n", __FUNCTION__)); + return result; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + When AuthMode is WPA2-Enterprise and AP reboot or STA lost AP, + WpaSupplicant would not send EapolStart to AP after STA re-connect to AP again. + In this case, driver would send EapolStart to AP. + */ + if ((pMacEntry->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory(pAd->MlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].LastBssid, MAC_ADDR_LEN)) && + (pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.bLostAp == TRUE)) + { + ApcliWpaSendEapolStart(pAd, pAd->MlmeAux.Bssid,pMacEntry,&pAd->ApCfg.ApCliTab[ifIndex]); + pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.bLostAp = FALSE; + } +#endif /*WPA_SUPPLICANT_SUPPORT */ + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pMacEntry, + pApCliEntry->MlmeAux.SupRate, + pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, +#ifdef DOT11_VHT_AC + pApCliEntry->MlmeAux.vht_cap_len, + &pApCliEntry->MlmeAux.vht_cap, +#endif /* DOT11_VHT_AC */ + &pApCliEntry->MlmeAux.HtCapability, + pApCliEntry->MlmeAux.HtCapabilityLen); + +#ifdef WSC_AP_SUPPORT + /* WSC initial connect to AP, jump to Wsc start action and set the correct parameters */ + if ((result == TRUE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) + { + pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscState = WSC_STATE_LINK_UP; + pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscStatus = WSC_STATE_LINK_UP; + pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + NdisZeroMemory(pApCliEntry->WscControl.EntryAddr, MAC_ADDR_LEN); + NdisMoveMemory(pApCliEntry->WscControl.EntryAddr, pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + WscSendEapolStart(pAd, pMacEntry->Addr, AP_MODE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WSCSTOP: %d, %d, %d\n", result, + pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode, + pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)); + WscStop(pAd, TRUE, &pApCliEntry->WscControl); + } +#endif /* WSC_AP_SUPPORT */ +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + if ((pAd->CommonCfg.bBssCoexEnable == TRUE) + && (pAd->CommonCfg.Channel <= 14) + && (pApCliEntry->wdev.DesiredHtPhyInfo.bHtEnable == TRUE) + && (pApCliEntry->MlmeAux.ExtCapInfo.BssCoexistMgmtSupport == 1)) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040); + BuildEffectedChannelList(pAd); + /*pAd->CommonCfg.ScanParameter.Dot11BssWidthTriggerScanInt = 150; */ + DBGPRINT(RT_DEBUG_TRACE, + ("LinkUP AP supports 20/40 BSS COEX !!! Dot11BssWidthTriggerScanInt[%d]\n", + pAd->CommonCfg.Dot11BssWidthTriggerScanInt)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("not supports 20/40 BSS COEX !!! \n")); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->CommonCfg.bBssCoexEnable %d !!! \n", + pAd->CommonCfg.bBssCoexEnable)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->CommonCfg.Channel %d !!! \n", + pAd->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_TRACE, + ("pApCliEntry->DesiredHtPhyInfo.bHtEnable %d !!! \n", + pApCliEntry->wdev.DesiredHtPhyInfo.bHtEnable)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->MlmeAux.ExtCapInfo.BssCoexstSup %d !!! \n", + pApCliEntry->MlmeAux.ExtCapInfo.BssCoexistMgmtSupport)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->CommonCfg.CentralChannel %d !!! \n", + pAd->CommonCfg.CentralChannel)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->CommonCfg.PhyMode %d !!! \n", + pAd->CommonCfg.PhyMode)); + } + } +#endif /* APCLI_CERT_SUPPORT */ +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef SMART_MESH_MONITOR + if((result == TRUE) && (pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.linkstate.type = NSMPIF_DRVEVNT_EXT_UPLINK_STAT; + drvevnt.data.linkstate.link_state = NSMP_UPLINK_STAT_CONNECTED; + NdisCopyMemory(drvevnt.data.linkstate.bssid,pMacEntry->wdev->bssid,MAC_ADDR_LEN); + drvevnt.data.linkstate.channel = pAd->CommonCfg.Channel; + NdisZeroMemory(drvevnt.data.linkstate.op_channels,sizeof(drvevnt.data.linkstate.op_channels)); + drvevnt.data.linkstate.op_channels[0] = pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + drvevnt.data.linkstate.op_channels[1] = N_GetSecondaryChannel(pAd); +#endif /* DOT11_N_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_EXT_UPLINK_STAT, + NULL, (PUCHAR)&drvevnt.data.linkstate, sizeof(drvevnt.data.linkstate)); + } +#endif /* SMART_MESH_MONITOR */ + + /* When root AP is Open WEP, it will cause a fake connection state if user keys in wrong password. */ + if((result == TRUE) && + (wdev->AuthMode == Ndis802_11AuthModeOpen) && + (wdev->WepStatus == Ndis802_11WEPEnabled)) + pApCliEntry->OpenWEPErrPktChk = TRUE; + else + pApCliEntry->OpenWEPErrPktChk = FALSE; + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + return result; +} + + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + ApCliIdx - Which ApCli interface + Return Value: + None + + Note: + + ========================================================================== +*/ +VOID ApCliLinkDown(RTMP_ADAPTER *pAd, UCHAR ifIndex) +{ + APCLI_STRUCT *pApCliEntry = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + UCHAR MacTabWCID = 0; + + if ((ifIndex < MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + || (ifIndex >= 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + printk("!!! REPEATER CLI LINK DOWN - IF(%s%d) Cli %d !!!\n", INF_APCLI_DEV_NAME, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + printk("!!! APCLI LINK DOWN - IF(%s%d)!!!\n", INF_APCLI_DEV_NAME, ifIndex); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("!!! ERROR : APCLI LINK DOWN - IF(%s%d)!!!\n", INF_APCLI_DEV_NAME, ifIndex)); + return; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if ((pApCliEntry->Valid == FALSE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#if defined (CONFIG_WIFI_PKT_FWD) +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + if (wf_fwd_entry_delete_hook) + wf_fwd_entry_delete_hook (pApCliEntry->wdev.if_dev, pAd->net_dev, 1); + } +#ifdef MAC_REPEATER_SUPPORT + else + { + if (packet_source_delete_entry_hook) + packet_source_delete_entry_hook(100); + } +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* CONFIG_WIFI_PKT_FWD */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + pAd->ApCfg.ApCliInfRunned--; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + MacTabWCID = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID; + else +#endif /* MAC_REPEATER_SUPPORT */ + MacTabWCID = pApCliEntry->MacTabWCID; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkDown CliIdx != 0xFF(1) MacTabWCID=%d addr=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + MacTabWCID,PRINT_MAC(pAd->MacTab.Content[MacTabWCID].Addr))); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkDown CliIdx != 0xFF(2) pApCliEntry->MacTabWCID =%d addr=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + pApCliEntry->MacTabWCID,PRINT_MAC(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)))); + + } else +#endif /* MAC_REPEATER_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkDown CliIdx == 0xFF(1) MacTabWCID=%d addr=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + MacTabWCID,PRINT_MAC(pAd->MacTab.Content[MacTabWCID].Addr))); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkDown CliIdx == 0xFF(2) pApCliEntry->MacTabWCID =%d addr=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + pApCliEntry->MacTabWCID,PRINT_MAC(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)))); + + } + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkDown CliIdx != 0xFF MacTabWCID=%d addr=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + MacTabWCID,PRINT_MAC(pAd->MacTab.Content[MacTabWCID].Addr))); + MacTableDeleteEntry(pAd, MacTabWCID, pAd->MacTab.Content[MacTabWCID].Addr); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkDown CliIdx == 0xFF MacTabWCID=%d addr=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + MacTabWCID, PRINT_MAC(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)))); + MacTableDeleteEntry(pAd, MacTabWCID, APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)); + } + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; /* This link doesn't associated with any remote-AP */ + pApCliEntry->wdev.allow_data_tx = FALSE; + pApCliEntry->wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } +#ifdef MWDS + pApCliEntry->bEnableMWDS = FALSE; +#endif /* MWDS */ + pApCliEntry->OpenWEPErrPktChk = FALSE; + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + + pAd->ApCfg.ApCliTab[ifIndex].bPeerExist = FALSE; + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] Send RT_DISASSOC_EVENT_FLAG.\n", __FUNCTION__, ifIndex)); + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef APCLI_CERT_SUPPORT + if (pApCliEntry->wdev.bWmmCapable == TRUE) + { + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); /* Restore AP's EDCA parameters. */ + pAd->ApCfg.BssEdcaParm.EdcaUpdateCount++; + } +#endif /* APCLI_CERT_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + RT_CFG80211_LOST_GO_INFORM(pAd); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef SMART_MESH_MONITOR + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.linkstate.type = NSMPIF_DRVEVNT_EXT_UPLINK_STAT; + drvevnt.data.linkstate.link_state = NSMP_UPLINK_STAT_DISCONNECT; + drvevnt.data.linkstate.channel = pAd->CommonCfg.Channel; + NdisZeroMemory(drvevnt.data.linkstate.op_channels,sizeof(drvevnt.data.linkstate.op_channels)); + drvevnt.data.linkstate.op_channels[0] = pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + drvevnt.data.linkstate.op_channels[1] = N_GetSecondaryChannel(pAd); +#endif /* DOT11_N_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_EXT_UPLINK_STAT, + NULL, (PUCHAR)&drvevnt.data.linkstate, sizeof(drvevnt.data.linkstate)); + } +#endif /* SMART_MESH_MONITOR */ + +} + + +/* + ========================================================================== + Description: + APCLI Interface Up. + ========================================================================== + */ +VOID ApCliIfUp(RTMP_ADAPTER *pAd) +{ + UCHAR ifIndex; + APCLI_STRUCT *pApCliEntry; +#ifdef APCLI_CONNECTION_TRIAL + PULONG pCurrState = NULL; +#endif /* APCLI_CONNECTION_TRIAL */ + + /* Reset is in progress, stop immediately */ + if ( RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))) + return; + + /* sanity check whether the interface is initialized. */ + if (pAd->flg_apcli_init != TRUE) + return; + + for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef APCLI_CONNECTION_TRIAL + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; +#endif /* APCLI_CONNECTION_TRIAL */ + + if (APCLI_IF_UP_CHECK(pAd, ifIndex) + && (pApCliEntry->Enable == TRUE) + && (pApCliEntry->Valid == FALSE) +#ifdef APCLI_CONNECTION_TRIAL + && (ifIndex == 0) +#endif /* APCLI_CONNECTION_TRIAL */ + ) + { + if (IS_DOT11_H_RADAR_STATE(pAd, RD_SILENCE_MODE)) + { + if (pApCliEntry->bPeerExist == TRUE) + { + /* Got peer's beacon; change to normal mode */ + pAd->Dot11_H.RDCount = pAd->Dot11_H.ChMovingTime; + DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfUp - PeerExist\n")); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfUp - Stop probing while Radar state is silent\n")); + + continue; + } + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startup.\n", __FUNCTION__, ifIndex)); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ, 0, NULL, ifIndex); + /* Reset bPeerExist each time in case we could keep old status */ + pApCliEntry->bPeerExist = FALSE; + } +#ifdef APCLI_CONNECTION_TRIAL + else if ( + APCLI_IF_UP_CHECK(pAd, ifIndex) + && (*pCurrState == APCLI_CTRL_DISCONNECTED)//Apcli1 is not connected state. + && (pApCliEntry->TrialCh != 0) + //&& NdisCmpMemory(pApCliEntry->ApCliMlmeAux.Ssid, pApCliEntry->CfgSsid, pApCliEntry->SsidLen) != 0 + && (pApCliEntry->CfgSsidLen != 0) + && (pApCliEntry->Enable != 0) + //new ap ssid shall different from the origin one. + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Enqueue APCLI_CTRL_TRIAL_CONNECT\n", __func__)); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_TRIAL_CONNECT, 0, NULL, ifIndex); + } +#endif /* APCLI_CONNECTION_TRIAL */ + + } + + return; +} + + +/* + ========================================================================== + Description: + APCLI Interface Down. + ========================================================================== + */ +VOID ApCliIfDown(RTMP_ADAPTER *pAd) +{ + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx,idx; + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#if defined (CONFIG_WIFI_PKT_FWD) + if (wf_fwd_entry_delete_hook) + wf_fwd_entry_delete_hook (pApCliEntry->wdev.if_dev, pAd->net_dev, 1); +#endif /* CONFIG_WIFI_PKT_FWD */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex)); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable) + { +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID); +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterDisconnectEntry(pAd, ifIndex, CliIdx); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); + } + +#ifdef MAC_REPEATER_SUPPORT + for (idx = 0; idx< 32; idx++) + { + pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; + + RTMPRepeaterRemoveInvaildMacEntry(pAd, idx, pEntry->MacAddr); + } +#endif /* MAC_REPEATER_SUPPORT */ + + return; +} + + +/* + ========================================================================== + Description: + APCLI Interface Monitor. + ========================================================================== + */ +VOID ApCliIfMonitor(RTMP_ADAPTER *pAd) +{ + UCHAR index; + APCLI_STRUCT *pApCliEntry; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + /* Reset is in progress, stop immediately */ + if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + return; + + /* sanity check whether the interface is initialized. */ + if (pAd->flg_apcli_init != TRUE) + return; + + for(index = 0; index < MAX_APCLI_NUM; index++) + { +#ifdef APCLI_CONNECTION_TRIAL + if (index == 1) + continue;//skip apcli1 monitor. FIXME:Carter shall find a better way. +#endif /* APCLI_CONNECTION_TRIAL */ + UCHAR Wcid; + PMAC_TABLE_ENTRY pMacEntry; + BOOLEAN bForceBrocken = FALSE; + + pApCliEntry = &pAd->ApCfg.ApCliTab[index]; +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn) && (pApCliEntry->Enable)) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + pReptCliEntry = &pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx]; + + if (pReptCliEntry->CliEnable) + { + if (pReptCliEntry->CliValid) + { + Wcid = pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].MacTabWCID; + + if (!VALID_WCID(Wcid)) + continue; + + pMacEntry = &pAd->MacTab.Content[Wcid]; + + if ((pMacEntry->PortSecured != WPA_802_1X_PORT_SECURED) && + RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pReptCliEntry->CliTriggerTime + (5 * OS_HZ)))) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s, wcid = %d, %s%d, CliIdx = %d\n", __func__, Wcid, INF_APCLI_DEV_NAME, index, CliIdx)); + RTMPRemoveRepeaterDisconnectEntry(pAd, index, CliIdx); +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, Wcid); +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterEntry(pAd, index, CliIdx); + } + } + else + { + if (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pReptCliEntry->CliTriggerTime + (5 * OS_HZ)))) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s, %s%d, CliIdx = %d\n", __func__, INF_APCLI_DEV_NAME, index, CliIdx)); + RTMPRemoveRepeaterEntry(pAd, index, CliIdx); + } + } + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + if (pApCliEntry->Valid == TRUE) + { + Wcid = pAd->ApCfg.ApCliTab[index].MacTabWCID; + if (!VALID_WCID(Wcid)) + continue; + + pMacEntry = &pAd->MacTab.Content[Wcid]; +#ifdef WSC_AP_SUPPORT + if(!((pAd->ApCfg.ApCliTab[index].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[index].WscControl.bWscTrigger == TRUE))) +#endif /* WSC_AP_SUPPORT */ + { + if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) && + (pMacEntry->PortSecured != WPA_802_1X_PORT_SECURED) && + (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliLinkUpTime + (30 * OS_HZ))))) + bForceBrocken = TRUE; + } + + if (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliRcvBeaconTime + (8 * OS_HZ)))) + { + printk("ApCliIfMonitor: IF(%s%d) - no Beacon is received from Root-AP.\n", INF_APCLI_DEV_NAME, index); + bForceBrocken = TRUE; + } + } + else + { +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].CliEnable) + { +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + if (pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].CliValid) + { + Wcid = pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].MacTabWCID; + if (VALID_WCID(Wcid)) + BASessionTearDownALL(pAd, Wcid); + } +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterDisconnectEntry(pAd, index, CliIdx); + RTMPRemoveRepeaterEntry(pAd, index, CliIdx); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + continue; + } + + if (bForceBrocken == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: Reconnect the Root-Ap again.\n")); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].CliEnable) + { +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].MacTabWCID); +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterDisconnectEntry(pAd, index, CliIdx); + RTMPRemoveRepeaterEntry(pAd, index, CliIdx); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, index); + RTMP_MLME_HANDLER(pAd); + } + } + + return; +} + + +/*! \brief To substitute the message type if the message is coming from external + * \param pFrame 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 ApCliMsgTypeSubst( + 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 */ + + + /* 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 EAPOL PACKET */ + pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2); + if (pEntry && IS_ENTRY_APCLI(pEntry) && pAd->ApCfg.ApCliTab[pEntry->apidx].WscControl.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); + } + if (!Return) +#endif /* WSC_AP_SUPPORT */ + { + *Machine = WPA_STATE_MACHINE; + EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); + Return = WpaMsgTypeSubst(EAPType, MsgType); + } + return Return; + } + else if (pFrame->Hdr.FC.Type == FC_TYPE_MGMT) + { + switch (pFrame->Hdr.FC.SubType) + { + case SUBTYPE_ASSOC_RSP: + *Machine = APCLI_ASSOC_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_ASSOC_RSP; + break; + + case SUBTYPE_DISASSOC: + *Machine = APCLI_ASSOC_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_DISASSOC_REQ; + break; + + case SUBTYPE_DEAUTH: + *Machine = APCLI_AUTH_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_DEAUTH; + break; + + case SUBTYPE_AUTH: + /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ + NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); + if (Seq == 2 || Seq == 4) + { + *Machine = APCLI_AUTH_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_AUTH_EVEN; + } + else + { + return FALSE; + } + break; + + case SUBTYPE_ACTION: + *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; + } + + return TRUE; + } + + return FALSE; +} + + +BOOLEAN preCheckMsgTypeSubset( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType) +{ + if (pFrame->Hdr.FC.Type == FC_TYPE_MGMT) + { + switch (pFrame->Hdr.FC.SubType) + { + /* Beacon must be processed by AP Sync state machine. */ + case SUBTYPE_BEACON: + *Machine = AP_SYNC_STATE_MACHINE; + *MsgType = APMT2_PEER_BEACON; + break; + + /* Only Sta have chance to receive Probe-Rsp. */ + case SUBTYPE_PROBE_RSP: + *Machine = APCLI_SYNC_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_PROBE_RSP; + break; + + default: + return FALSE; + } + return TRUE; + } + return FALSE; +} + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN ApCliPeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *ie_list) +{ + CHAR IeType; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PEID_STRUCT pEid; + ULONG Length = 0; + + *pNewExtChannelOffset = 0xff; + *pHtCapabilityLen = 0; + *pAddHtInfoLen = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + Length += LENGTH_802_11; + + NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); + Length += 2; + NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); + Length += 2; + *pCkipFlag = 0; + *pExtRateLen = 0; + pEdcaParm->bValid = FALSE; + + if (*pStatus != MLME_SUCCESS) + return TRUE; + + NdisMoveMemory(pAid, &pFrame->Octet[4], 2); + Length += 2; + + /* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */ + *pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */ + + /* -- get supported rates from payload and advance the pointer */ + IeType = pFrame->Octet[6]; + *pSupRateLen = pFrame->Octet[7]; + if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong SupportedRates IE\n", __FUNCTION__)); + return FALSE; + } + else + NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); + + Length = Length + 2 + *pSupRateLen; + + /* many AP implement proprietary IEs in non-standard order, we'd better */ + /* tolerate mis-ordered IEs to get best compatibility */ + pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch (pEid->Eid) + { + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; +#ifdef DOT11_N_SUPPORT + case IE_HT_CAP: + case IE_HT_CAP2: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!! */ + { + NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); + *(USHORT *) (&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *) (&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_HT_CAP\n", __FUNCTION__)); + } + + break; + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ + /* copy first sizeof(ADD_HT_INFO_IE) */ + NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_ADD_HT\n", __FUNCTION__)); + } + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_SECONDARY_CH_OFFSET\n", __FUNCTION__)); + } + break; +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (pEid->Len == sizeof(VHT_CAP_IE)) { + NdisMoveMemory(&ie_list->vht_cap, pEid->Octet, sizeof(VHT_CAP_IE)); + ie_list->vht_cap_len = sizeof(VHT_CAP_IE); + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP\n", __FUNCTION__)); + } + break; + case IE_VHT_OP: + if (pEid->Len == sizeof(VHT_OP_IE)) { + NdisMoveMemory(&ie_list->vht_op, pEid->Octet, sizeof(VHT_OP_IE)); + ie_list->vht_op_len = sizeof(VHT_OP_IE); + }else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_OP\n", __FUNCTION__)); + } + break; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + /* CCX2, WMM use the same IE value */ + /* case IE_CCX_V2: */ + case IE_VENDOR_SPECIFIC: + /* handle WME PARAMTER ELEMENT */ + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + /* parsing EDCA parameters */ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ + /*pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; */ + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = (PUCHAR) &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin */ + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax */ + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us */ + ptr += 4; /* point to next AC */ + } + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s():ignore unrecognized EID = %d\n", __FUNCTION__, pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; +} + + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR *pAddrs) +{ + ULONG ApCliIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_WCID(wcid)) + return NULL; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + ApCliIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_APCLI(pCurEntry)) + { + ApCliIndex = pCurEntry->wdev_idx; + } + + if ((ApCliIndex == 0xff) || (ApCliIndex >= MAX_APCLI_NUM)) + break; + + if (pAd->ApCfg.ApCliTab[ApCliIndex].Valid != TRUE) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddrs)) + { + pEntry = pCurEntry; + break; + } + } while(FALSE); + + NdisReleaseSpinLock(&pAd->MacTabLock); + + return pEntry; +} + + +/* + ========================================================================== + Description: + Check the Apcli Entry is valid or not. + ========================================================================== + */ +static inline BOOLEAN ValidApCliEntry(RTMP_ADAPTER *pAd, INT apCliIdx) +{ + BOOLEAN result; + PMAC_TABLE_ENTRY pMacEntry; + APCLI_STRUCT *pApCliEntry; + + do + { + if ((apCliIdx < 0) || (apCliIdx >= MAX_APCLI_NUM)) + { + result = FALSE; + break; + } + + pApCliEntry = (APCLI_STRUCT *)&pAd->ApCfg.ApCliTab[apCliIdx]; + if (pApCliEntry->Valid != TRUE) + { + result = FALSE; + break; + } + + if ((pApCliEntry->MacTabWCID <= 0) + || (pApCliEntry->MacTabWCID >= MAX_LEN_OF_MAC_TABLE)) + { + result = FALSE; + break; + } + + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + if (!IS_ENTRY_APCLI(pMacEntry)) + { + result = FALSE; + break; + } + + result = TRUE; + } while(FALSE); + + return result; +} + + +INT ApCliAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR idx; + BOOLEAN allowed = FALSE; + APCLI_STRUCT *apcli_entry; + + + for(idx = 0; idx < MAX_APCLI_NUM; idx++) + { + apcli_entry = &pAd->ApCfg.ApCliTab[idx]; + if (apcli_entry && (&apcli_entry->wdev == wdev)) + { + if (ValidApCliEntry(pAd, idx) == FALSE) + break; + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) +#ifdef MWDS + && (apcli_entry->bEnableMWDS == FALSE) +#endif /* MWDS */ + ) + { + PUCHAR pSrcBufVA = NULL; + PACKET_INFO PacketInfo; + UINT SrcBufLen; + PMAC_TABLE_ENTRY pEntry = NULL; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR isLinkValid; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, (pSrcBufVA + MAC_ADDR_LEN), TRUE, &isLinkValid); + if (pReptEntry) + { + *pWcid = pReptEntry->MacTabWCID; + return TRUE; + } + else + { + if (!isLinkValid) + return FALSE; + + + if (RTMPRepeaterVaildMacEntry(pAd, pSrcBufVA + MAC_ADDR_LEN)) + { + pEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[idx].MacTabWCID]; + if ((pEntry) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + RTMPInsertRepeaterEntry(pAd, idx, (pSrcBufVA + MAC_ADDR_LEN)); + DBGPRINT(RT_DEBUG_TRACE, (" Receive trigger packet !!!\n")); + return FALSE; + } + } + } + + *pWcid = apcli_entry->MacTabWCID; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pAd->RalinkCounters.PendingNdisPacketCount ++; + RTMP_SET_PACKET_NET_DEVICE_APCLI(pPacket, idx); + *pWcid = apcli_entry->MacTabWCID; + } + allowed = TRUE; + break; + } + } + + return allowed; +} + + +/* + ======================================================================== + + Routine Description: + Validate the security configuration against the RSN information + element + + Arguments: + pAdapter Pointer to our adapter + eid_ptr Pointer to VIE + + Return Value: + TRUE for configuration match + FALSE for otherwise + + Note: + + ======================================================================== +*/ +BOOLEAN ApCliValidateRSNIE( + IN RTMP_ADAPTER *pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx) +{ + PUCHAR pVIE, pTmp; + UCHAR len; + PEID_STRUCT pEid; + CIPHER_SUITE WPA; /* AP announced WPA cipher suite */ + CIPHER_SUITE WPA2; /* AP announced WPA2 cipher suite */ + USHORT Count; + UCHAR Sanity; + PAPCLI_STRUCT pApCliEntry = NULL; + PRSN_IE_HEADER_STRUCT pRsnHeader; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + NDIS_802_11_AUTHENTICATION_MODE TmpAuthMode; + NDIS_802_11_AUTHENTICATION_MODE WPA_AuthMode; + NDIS_802_11_AUTHENTICATION_MODE WPA_AuthModeAux; + NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthMode; + NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthModeAux; + struct wifi_dev *wdev; + + pVIE = (PUCHAR) pEid_ptr; + len = eid_len; + + /*if (len >= MAX_LEN_OF_RSNIE || len <= MIN_LEN_OF_RSNIE) */ + /* return FALSE; */ + + /* Init WPA setting */ + WPA.PairCipher = Ndis802_11WEPDisabled; + WPA.PairCipherAux = Ndis802_11WEPDisabled; + WPA.GroupCipher = Ndis802_11WEPDisabled; + WPA.RsnCapability = 0; + WPA.bMixMode = FALSE; + WPA_AuthMode = Ndis802_11AuthModeOpen; + WPA_AuthModeAux = Ndis802_11AuthModeOpen; + + /* Init WPA2 setting */ + WPA2.PairCipher = Ndis802_11WEPDisabled; + WPA2.PairCipherAux = Ndis802_11WEPDisabled; + WPA2.GroupCipher = Ndis802_11WEPDisabled; + WPA2.RsnCapability = 0; + WPA2.bMixMode = FALSE; + WPA2_AuthMode = Ndis802_11AuthModeOpen; + WPA2_AuthModeAux = Ndis802_11AuthModeOpen; + + Sanity = 0; + + /* 1. Parse Cipher this received RSNIE */ + while (len > 0) + { + pTmp = pVIE; + pEid = (PEID_STRUCT) pTmp; + + switch(pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) + { + /* if unsupported vendor specific IE */ + break; + } + /* Skip OUI ,version and multicast suite OUI */ + pTmp += 11; + + /* + Cipher Suite Selectors from Spec P802.11i/D3.2 P26. + Value Meaning + 0 None + 1 WEP-40 + 2 Tkip + 3 WRAP + 4 AES + 5 WEP-104 + */ + /* Parse group cipher */ + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + WPA.GroupCipher = Ndis802_11WEPEnabled; + break; + case 2: + WPA.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + WPA.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + + /* number of unicast suite */ + pTmp += 1; + + /* Store unicast cipher count */ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + /* pointer to unicast cipher */ + pTmp += sizeof(USHORT); + + /* Parsing all unicast cipher suite */ + while (Count > 0) + { + /* Skip cipher suite OUI */ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > WPA.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux */ + WPA.PairCipherAux = WPA.PairCipher; + WPA.PairCipher = TmpCipher; + } + else + { + WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + + /* Get AKM suite counts */ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT); + + /* Parse AKM ciphers */ + /* Parsing all AKM cipher suite */ + while (Count > 0) + { + /* Skip cipher suite OUI */ + pTmp += 3; + TmpAuthMode = Ndis802_11AuthModeOpen; + switch (*pTmp) + { + case 1: + /* WPA-enterprise */ + TmpAuthMode = Ndis802_11AuthModeWPA; + break; + case 2: + /* WPA-personal */ + TmpAuthMode = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + if (TmpAuthMode > WPA_AuthMode) + { + /* Move the lower AKM suite to WPA_AuthModeAux */ + WPA_AuthModeAux = WPA_AuthMode; + WPA_AuthMode = TmpAuthMode; + } + else + { + WPA_AuthModeAux = TmpAuthMode; + } + pTmp++; + Count--; + } + + /* ToDo - Support WPA-None ? */ + + /* Check the Pair & Group, if different, turn on mixed mode flag */ + if (WPA.GroupCipher != WPA.PairCipher) + WPA.bMixMode = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA1 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n", + ((WPA.bMixMode) ? "Mix" : GetEncryptType(WPA.PairCipher)), + GetEncryptType(WPA.GroupCipher), + GetAuthMode(WPA_AuthMode))); + + Sanity |= 0x1; + break; /* End of case IE_WPA */ + case IE_RSN: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + /* 0. Version must be 1 */ + /* The pRsnHeader->Version exists in native little-endian order, so we may need swap it for RT_BIG_ENDIAN systems. */ + if (le2cpu16(pRsnHeader->Version) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - RSN Version isn't 1(%d) \n", pRsnHeader->Version)); + break; + } + + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Check cipher OUI */ + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + { + /* if unsupported vendor specific IE */ + break; + } + + /* Skip cipher suite OUI */ + pTmp += 3; + + /* Parse group cipher */ + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + WPA2.GroupCipher = Ndis802_11WEPEnabled; + break; + case 2: + WPA2.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + WPA2.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + + /* number of unicast suite */ + pTmp += 1; + + /* Get pairwise cipher counts */ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT); + + /* 3. Get pairwise cipher */ + /* Parsing all unicast cipher suite */ + while (Count > 0) + { + /* Skip OUI */ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > WPA2.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux */ + WPA2.PairCipherAux = WPA2.PairCipher; + WPA2.PairCipher = TmpCipher; + } + else + { + WPA2.PairCipherAux = TmpCipher; + } + pTmp ++; + Count--; + } + + /* Get AKM suite counts */ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT); + + /* Parse AKM ciphers */ + /* Parsing all AKM cipher suite */ + while (Count > 0) + { + /* Skip cipher suite OUI */ + pTmp += 3; + TmpAuthMode = Ndis802_11AuthModeOpen; + switch (*pTmp) + { + case 1: + /* WPA2-enterprise */ + TmpAuthMode = Ndis802_11AuthModeWPA2; + break; + case 2: + /* WPA2-personal */ + TmpAuthMode = Ndis802_11AuthModeWPA2PSK; + break; + default: + break; + } + if (TmpAuthMode > WPA2_AuthMode) + { + /* Move the lower AKM suite to WPA2_AuthModeAux */ + WPA2_AuthModeAux = WPA2_AuthMode; + WPA2_AuthMode = TmpAuthMode; + } + else + { + WPA2_AuthModeAux = TmpAuthMode; + } + pTmp++; + Count--; + } + + /* Check the Pair & Group, if different, turn on mixed mode flag */ + if (WPA2.GroupCipher != WPA2.PairCipher) + WPA2.bMixMode = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA2 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n", + (WPA2.bMixMode ? "Mix" : GetEncryptType(WPA2.PairCipher)), GetEncryptType(WPA2.GroupCipher), + GetAuthMode(WPA2_AuthMode))); + + Sanity |= 0x2; + break; /* End of case IE_RSN */ + default: + DBGPRINT(RT_DEBUG_WARN, ("ApCliValidateRSNIE - Unknown pEid->Eid(%d) \n", pEid->Eid)); + break; + } + + /* skip this Eid */ + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + + } + + /* 2. Validate this RSNIE with mine */ + pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; + wdev = &pApCliEntry->wdev; + + /* Peer AP doesn't include WPA/WPA2 capable */ + if (Sanity == 0) + { + /* Check the authenticaton mode */ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match \n", __FUNCTION__)); + return FALSE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - The pre-RSNA authentication mode is used. \n", __FUNCTION__)); + return TRUE; + } + } + else if (wdev->AuthMode < Ndis802_11AuthModeWPA) + { + /* Peer AP has RSN capability, but our AP-Client is pre-RSNA. Discard this */ + DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match. AP is WPA security but APCLI is not. \n", __FUNCTION__)); + return FALSE; + } + + + /* Recovery user-defined cipher suite */ + pApCliEntry->PairCipher = wdev->WepStatus; + pApCliEntry->GroupCipher = wdev->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (wdev->bWpaAutoMode == TRUE) + { + if (Sanity == 0x2) + { + DBGPRINT(RT_DEBUG_TRACE,("WPA_AUTO Mode ==> peerAp: Rsn IE\n")); + wdev->AuthMode = WPA2_AuthMode; + } + else if (Sanity == 0x3) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA_AUTO Mode ==> peerAp: including Rsn/WPA IE (DUAL)\n")); + wdev->AuthMode = WPA2_AuthMode; + } + else if (Sanity == 0x1) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA_AUTO Mode ==> peerAp: WPA IE\n")); + wdev->AuthMode = WPA_AuthMode; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA_AUTO Mode ==> peerAp: no Rsn/WPA IE\n")); + return FALSE; + } + } + + if(wdev->bEncryptAutoMode == TRUE) + { + if (Sanity == 0x2) + { + DBGPRINT(RT_DEBUG_TRACE,("ENCRYPT_AUTO Mode ==> peerAp: Rsn IE\n")); + wdev->WepStatus = WPA2.PairCipher; + } + else if (Sanity == 0x3) + { + DBGPRINT(RT_DEBUG_TRACE, ("ENCRYPT_AUTO Mode ==> peerAp: including Rsn/WPA IE (DUAL)\n")); + wdev->WepStatus = WPA2.PairCipher; + } + else if (Sanity == 0x1) + { + DBGPRINT(RT_DEBUG_TRACE, ("ENCRYPT_AUTO Mode ==> peerAp: WPA IE\n")); + wdev->WepStatus = WPA.PairCipher; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ENCRYPT_AUTO Mode ==> peerAp: no Rsn/WPA IE\n")); + return FALSE; + } + } + + Sanity = 0; + + /* Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode */ + /* WPAPSK */ + if ((WPA_AuthMode == wdev->AuthMode) || + ((WPA_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA_AuthModeAux == wdev->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA.bMixMode == FALSE) + { + if (wdev->WepStatus != WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (wdev->WepStatus < WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate group cipher error \n")); + return FALSE; + } + + /* + check pairwise cipher, skip if none matched + If profile set to AES, let it pass without question. + If profile set to TKIP, we must find one mateched + */ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != WPA.PairCipher) && + (wdev->WepStatus != WPA.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n")); + return FALSE; + } + + Sanity |= 0x1; + } + /* WPA2PSK */ + else if ((WPA2_AuthMode == wdev->AuthMode) || + ((WPA2_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA2_AuthModeAux == wdev->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA2.bMixMode == FALSE) + { + if (wdev->WepStatus != WPA2.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (wdev->WepStatus < WPA2.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate group cipher error \n")); + return FALSE; + } + + /* + check pairwise cipher, skip if none matched + If profile set to AES, let it pass without question. + If profile set to TKIP, we must find one mateched + */ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != WPA2.PairCipher) && + (wdev->WepStatus != WPA2.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate pairwise cipher error \n")); + return FALSE; + } + + Sanity |= 0x2; + } + + if (Sanity == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - Validate RSIE Failure \n")); + return FALSE; + } + + /*Re-assign pairwise-cipher and group-cipher. Re-build RSNIE. */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pApCliEntry->GroupCipher = WPA.GroupCipher; + + if (wdev->WepStatus == WPA.PairCipher) + pApCliEntry->PairCipher = WPA.PairCipher; + else if (WPA.PairCipherAux != Ndis802_11WEPDisabled) + pApCliEntry->PairCipher = WPA.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pApCliEntry->PairCipher = Ndis802_11TKIPEnable; + } + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pApCliEntry->GroupCipher = WPA2.GroupCipher; + + if (wdev->WepStatus == WPA2.PairCipher) + pApCliEntry->PairCipher = WPA2.PairCipher; + else if (WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pApCliEntry->PairCipher = WPA2.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pApCliEntry->PairCipher = Ndis802_11TKIPEnable; + } + + /* Set Mix cipher flag */ + if (pApCliEntry->PairCipher != pApCliEntry->GroupCipher) + { + pApCliEntry->bMixCipher = TRUE; + + /* re-build RSNIE */ + /*RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); */ + } + + /* re-build RSNIE */ + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); + + return TRUE; +} + + +BOOLEAN ApCliHandleRxBroadcastFrame( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FromWhichBSSID) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + APCLI_STRUCT *pApCliEntry = NULL; +#ifdef MAC_REPEATER_SUPPORT + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef WSC_AP_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[0].WscControl; +#endif /* WSC_AP_SUPPORT */ + + /* + It is possible to receive the multicast packet when in AP Client mode + ex: broadcast from remote AP to AP-client, + addr1=ffffff, addr2=remote AP's bssid, addr3=sta4_mac_addr + */ + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + + /* Filter out Bcast frame which AP relayed for us */ + /* Multicast packet send from AP1 , received by AP2 and send back to AP1, drop this frame */ +#ifdef MWDS + if(IS_MWDS_OPMODE_APCLI(pEntry) && + MAC_ADDR_EQUAL(pHeader->Octet, pApCliEntry->wdev.if_addr)) + return FALSE; +#endif /* MWDS */ + + if (MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr)) + return FALSE; + + if (pEntry->PrivacyFilter != Ndis802_11PrivFilterAcceptAll) + return FALSE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader->Addr3, TRUE, &isLinkValid); + if (pReptEntry) + return FALSE; /* give up this frame */ + } +#endif /* MAC_REPEATER_SUPPORT */ + + + + /* skip the 802.11 header */ +#ifdef MWDS + if(IS_MWDS_OPMODE_APCLI(pEntry)) + { + pRxBlk->pData += LENGTH_802_11_WITH_ADDR4; + pRxBlk->DataSize -= LENGTH_802_11_WITH_ADDR4; + } + else +#endif /* MWDS */ + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + } + + /* Use software to decrypt the encrypted frame. */ + /* Because this received frame isn't my BSS frame, Asic passed to driver without decrypting it. */ + /* If receiving an "encrypted" unicast packet(its WEP bit as 1) and doesn't match my BSSID, it */ + /* pass to driver with "Decrypted" marked as 0 in RxD. */ + if ((pRxInfo->MyBss == 0) && (pRxInfo->Decrypted == 0) && (pHeader->FC.Wep == 1) + && pEntry->PortSecured==WPA_802_1X_PORT_SECURED +#ifdef WSC_AP_SUPPORT + && pWpsCtrl->bWscTrigger == FALSE +#endif /*WSC_AP_SUPPORT*/ + ) + { + NDIS_STATUS NStatus; + + NStatus = RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, 0, + &pApCliEntry->SharedKey[pRxBlk->key_idx], + pRxBlk->pData, + &(pRxBlk->DataSize)); + if (NStatus != NDIS_STATUS_SUCCESS) + { +#ifdef APCLI_CERT_SUPPORT + if (NStatus == NDIS_STATUS_MICERROR && pApCliEntry->GroupCipher == Ndis802_11TKIPEnable) + ApCliRTMPReportMicError( pAd,&pApCliEntry->SharedKey[pRxBlk->key_idx],pEntry->wdev_idx); +#endif /* APCLI_CERT_SUPPORT */ + return FALSE; /* give up this frame */ + } + } + pRxInfo->MyBss = 1; +#ifdef APCLI_SUPPORT + rx_get_pn(pRxBlk,pRxInfo); +#endif /* APCLI_SUPPORT */ +#ifdef HDR_TRANS_SUPPORT + if (pRxBlk->bHdrRxTrans) + Indicate_Legacy_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID); + else +#endif /* HDR_TRANS_SUPPORT */ + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + + return TRUE; +} + + +VOID APCliInstallPairwiseKey( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR IfIdx; + UINT8 BssIdx; + + IfIdx = pEntry->wdev_idx; + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + IfIdx; +#ifdef MAC_APCLI_SUPPORT + BssIdx = APCLI_BSSID_IDX + IfIdx; +#endif /* MAC_APCLI_SUPPORT */ + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].PTK, pEntry->PTK, LEN_PTK); + + WPAInstallPairwiseKey(pAd, BssIdx, pEntry, FALSE); +} + + +BOOLEAN APCliInstallSharedKey( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyLen, + IN UCHAR DefaultKeyIdx, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR IfIdx; + UCHAR GTK_len = 0; + APCLI_STRUCT *apcli_entry; + + + if (!pEntry || !IS_ENTRY_APCLI(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : This Entry doesn't exist!!! \n", __FUNCTION__)); + return FALSE; + } + + IfIdx = pEntry->wdev_idx; + ASSERT((IfIdx < MAX_APCLI_NUM)); + + apcli_entry = &pAd->ApCfg.ApCliTab[IfIdx]; + if (apcli_entry->GroupCipher == Ndis802_11TKIPEnable && KeyLen >= LEN_TKIP_GTK) + GTK_len = LEN_TKIP_GTK; + else if (apcli_entry->GroupCipher == Ndis802_11AESEnable && KeyLen >= LEN_AES_GTK) + GTK_len = LEN_AES_GTK; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : GTK is invalid (GroupCipher=%d, DataLen=%d) !!! \n", + __FUNCTION__, apcli_entry->GroupCipher, KeyLen)); + return FALSE; + } + + /* Update GTK */ + /* set key material, TxMic and RxMic for WPAPSK */ + NdisMoveMemory(apcli_entry->GTK, pKey, GTK_len); + apcli_entry->wdev.DefaultKeyId = DefaultKeyIdx; + + /* Update shared key table */ + NdisZeroMemory(&apcli_entry->SharedKey[DefaultKeyIdx], sizeof(CIPHER_KEY)); + apcli_entry->SharedKey[DefaultKeyIdx].KeyLen = GTK_len; + NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].Key, pKey, LEN_TK); + if (GTK_len == LEN_TKIP_GTK) + { + NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].RxMic, pKey + 16, LEN_TKIP_MIC); + NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].TxMic, pKey + 24, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_NONE; + if (apcli_entry->GroupCipher == Ndis802_11TKIPEnable) + apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_TKIP; + else if (apcli_entry->GroupCipher == Ndis802_11AESEnable) + apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_AES; + +#ifdef MAC_APCLI_SUPPORT + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + APCLI_BSS_BASE + IfIdx, + DefaultKeyIdx, + &apcli_entry->SharedKey[DefaultKeyIdx]); +#endif /* MAC_APCLI_SUPPORT */ + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +// TODO: shiang-6590, modify this due to it's really a duplication of "RTMPUpdateMlmeRate()" in common/mlme.c +VOID ApCliUpdateMlmeRate(RTMP_ADAPTER *pAd, USHORT ifIndex) +{ + UCHAR MinimumRate; + UCHAR ProperMlmeRate; /*= RATE_54; */ + UCHAR i, j, RateIdx = 12; /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + BOOLEAN bMatch = FALSE; + UCHAR PhyMode = pAd->CommonCfg.PhyMode; + + PAPCLI_STRUCT pApCliEntry = NULL; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = pApCliEntry->wdev.PhyMode; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + switch (PhyMode) + { + case (WMODE_B): + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case (WMODE_B | WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_A |WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): + case (WMODE_B | WMODE_G | WMODE_GN): +#ifdef DOT11_VHT_AC + case (WMODE_A |WMODE_B | WMODE_G | WMODE_GN | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + if ((pApCliEntry->MlmeAux.SupRateLen == 4) && + (pApCliEntry->MlmeAux.ExtRateLen == 0)) + ProperMlmeRate = RATE_11; /* B only AP */ + else + ProperMlmeRate = RATE_24; + + if (pApCliEntry->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case (WMODE_A): +#ifdef DOT11_N_SUPPORT + case (WMODE_GN): + case (WMODE_G | WMODE_GN): + case (WMODE_A | WMODE_G | WMODE_AN | WMODE_GN): + case (WMODE_A | WMODE_AN): + case (WMODE_AN): +#ifdef DOT11_VHT_AC + case (WMODE_AC): + case (WMODE_AN | WMODE_AC): + case (WMODE_A | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case (WMODE_B | WMODE_A | WMODE_G): + ProperMlmeRate = RATE_24; + if (pApCliEntry->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: /* error */ + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pApCliEntry->MlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pApCliEntry->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pApCliEntry->MlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pApCliEntry->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + } + + if (bMatch == FALSE) + ProperMlmeRate = MinimumRate; + + if(!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) + { + pAd->CommonCfg.MlmeRate = MinimumRate; + pAd->CommonCfg.RtsRate = ProperMlmeRate; + if (pAd->CommonCfg.MlmeRate >= RATE_6) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s():=>MlmeTransmit=0x%x, MinimumRate=%d, ProperMlmeRate=%d\n", + __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word, MinimumRate, ProperMlmeRate)); +} + + +VOID ApCliCheckPeerExistence(RTMP_ADAPTER *pAd, CHAR *Ssid, UCHAR SsidLen, UCHAR Channel) +{ + UCHAR ifIndex; + APCLI_STRUCT *pApCliEntry; + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + + if (pApCliEntry->bPeerExist == TRUE) + continue; + + else if (Channel == pAd->CommonCfg.Channel && + ((SsidLen == pApCliEntry->CfgSsidLen && NdisEqualMemory(Ssid, pApCliEntry->CfgSsid, SsidLen)) || + SsidLen == 0 /* Hidden */)) + { + pApCliEntry->bPeerExist = TRUE; + } + else + { + /* No Root AP match the SSID */ + } + } +} + + +VOID APCli_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ + PNET_DEV new_dev_p; + INT idx; + APCLI_STRUCT *pApCliEntry; + struct wifi_dev *wdev; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_apcli_init != FALSE) + return; + + + /* init */ + for(idx = 0; idx < MAX_APCLI_NUM; idx++) + pAd->ApCfg.ApCliTab[idx].wdev.if_dev = NULL; + + /* create virtual network interface */ + for (idx = 0; idx < MAX_APCLI_NUM; idx++) + { + 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 */ + + dev_name = get_dev_name_prefix(pAd, INT_APCLI); + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_APCLI, idx, + sizeof(struct mt_dev_priv), dev_name); + if (!new_dev_p) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Create net_device for %s(%d) fail!\n", + __FUNCTION__, dev_name, idx)); + break; + } +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; + + NdisZeroMemory(&pApCliEntry->ApCliCounter, sizeof(APCLI_COUNTER)); + +#ifdef APCLI_CONNECTION_TRIAL + pApCliEntry->ifIndex = idx; + pApCliEntry->pAd = pAd; +#endif /* APCLI_CONNECTION_TRIAL */ + pApCliEntry->OpenWEPErrPktChk = FALSE; + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + wdev = &pApCliEntry->wdev; + wdev->wdev_type = WDEV_TYPE_STA; + wdev->func_dev = pApCliEntry; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = new_dev_p; + wdev->tx_pkt_allowed = ApCliAllowToSendPacket; + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + RTMP_OS_NETDEV_SET_WDEV(new_dev_p, wdev); + 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(new_dev_p))); + RtmpOSNetDevFree(new_dev_p); + break; + } + + NdisZeroMemory(&pApCliEntry->ApCliCounter, sizeof(APCLI_COUNTER)); + + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); + + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + if ((pAd->ApCfg.BssidNum > 0) || (MAX_MESH_NUM > 0)) + { + UCHAR MacMask = 0; + + if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 2) + MacMask = 0xFE; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 4) + MacMask = 0xFC; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 8) + MacMask = 0xF8; +#ifdef SPECIFIC_BCN_BUF_SUPPORT + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 16) + MacMask = 0xF0; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + idx = (pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1; + + /* + Refer to HW definition - + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + { + /* + Refer to HW definition - + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ + wdev->if_addr[0] &= (MacMask << 2); + wdev->if_addr[0] |= 0x2; + wdev->if_addr[0] |= (idx << 2); + } +#ifdef ENHANCE_NEW_MBSSID_MODE + else + { + wdev->if_addr[0] |= 0x2; + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] |= idx; + } +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + } + else + { + wdev->if_addr[MAC_ADDR_LEN - 1] = (wdev->if_addr[MAC_ADDR_LEN - 1] + pAd->ApCfg.BssidNum + MAX_MESH_NUM) & 0xFF; + } + + pNetDevOps->priv_flags = INT_APCLI; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + pNetDevOps->wdev = wdev; + NdisMoveMemory(pNetDevOps->devAddr, &wdev->if_addr[0], MAC_ADDR_LEN); + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + } + + pAd->flg_apcli_init = TRUE; +} + + +VOID ApCli_Remove(RTMP_ADAPTER *pAd) +{ + UINT index; + struct wifi_dev *wdev; + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + wdev = &pAd->ApCfg.ApCliTab[index].wdev; + if (wdev->if_dev) + { + RtmpOSNetDevProtect(1); + RtmpOSNetDevDetach(wdev->if_dev); + RtmpOSNetDevProtect(0); + rtmp_wdev_idx_unreg(pAd, wdev); + RtmpOSNetDevFree(wdev->if_dev); + + /* Clear it as NULL to prevent latter access error. */ + pAd->flg_apcli_init = FALSE; + wdev->if_dev = NULL; + } + } +} + + +BOOLEAN ApCli_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p) +{ + UCHAR ifIndex; +#if defined (CONFIG_WIFI_PKT_FWD) + if (wf_fwd_probe_adapter) + wf_fwd_probe_adapter(pAd); +#endif + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].wdev.if_dev == dev_p) + { + RTMP_OS_NETDEV_START_QUEUE(dev_p); + pAd->ApCfg.ApCliTab[ifIndex].Valid = FALSE; + ApCliIfUp(pAd); +#ifdef WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_UP, NULL, NULL, 0); +#endif /* WPA_SUPPLICANT_SUPPORT */ + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN ApCli_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p) +{ + UCHAR ifIndex; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ + struct wifi_dev *wdev; + APCLI_STRUCT *apcli_entry; + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + if (wdev->if_dev == dev_p) + { +#ifdef WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0); + + if (apcli_entry->wpa_supplicant_info.pWpaAssocIe) + { + os_free_mem(NULL, apcli_entry->wpa_supplicant_info.pWpaAssocIe); + apcli_entry->wpa_supplicant_info.pWpaAssocIe = NULL; + apcli_entry->wpa_supplicant_info.WpaAssocIeLen = 0; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); + + /* send disconnect-req to sta State Machine. */ + if (apcli_entry->Enable) + { +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable) + { +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID); +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterDisconnectEntry(pAd, ifIndex, CliIdx); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef SMART_MESH + /* To avoid to connect to previous bssid setting after interface up later. */ + NdisZeroMemory(apcli_entry->CfgApCliBssid, MAC_ADDR_LEN); +#endif /* SMART_MESH */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex)); + } + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN ApCli_StatsGet( + IN PRTMP_ADAPTER pAd, + IN RT_CMD_STATS64 *pStats) +{ + INT ifIndex = 0, index; + APCLI_STRUCT *pApCliTab; + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + if (pAd->ApCfg.ApCliTab[index].wdev.if_dev == pStats->pNetDev) + { + ifIndex = index; + break; + } + } + + if (index >= MAX_APCLI_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl apcli_statsGet can not find apcli I/F\n")); + return FALSE; + } + + pApCliTab = &pAd->ApCfg.ApCliTab[ifIndex]; + + pStats->rx_bytes = pApCliTab->ApCliCounter.ReceivedByteCount.QuadPart; + pStats->tx_bytes = pApCliTab->ApCliCounter.TransmittedByteCount.QuadPart; + + pStats->rx_packets = pApCliTab->ApCliCounter.ReceivedFragmentCount; + pStats->tx_packets = pApCliTab->ApCliCounter.TransmittedFragmentCount; + + pStats->rx_errors = pApCliTab->ApCliCounter.RxErrors; + pStats->multicast = pApCliTab->ApCliCounter.MulticastReceivedFrameCount; + + return TRUE; +} + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + +BOOLEAN ApCliSetIfState( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN state) +{ + pAd->ApCfg.ApCliTab[ifIndex].Enable = state; + +#ifdef APCLI_CONNECTION_TRIAL + if (pAd->ApCfg.ApCliTab[ifIndex].TrialCh == 0) +#endif /* APCLI_CONNECTION_TRIAL */ + ApCliIfDown(pAd); + + return TRUE; +} + + +BOOLEAN ApCliSetBssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN UCHAR *Bssid) +{ + BOOLEAN apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + /* bring apcli interface down first */ + if (apcliEn == TRUE) + { + pAd->ApCfg.ApCliTab[ifIndex].Enable = FALSE; +#ifdef APCLI_CONNECTION_TRIAL + if (pAd->ApCfg.ApCliTab[ifIndex].TrialCh == 0) +#endif /* APCLI_CONNECTION_TRIAL */ + ApCliIfDown(pAd); + } + + NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, Bssid, MAC_ADDR_LEN); + + pAd->ApCfg.ApCliTab[ifIndex].Enable = apcliEn; + + return TRUE; +} + + +BOOLEAN ApCliAutoConnectStart( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + AP_ADMIN_CONFIG *pApCfg = &pAd->ApCfg; + NDIS_802_11_SSID Ssid; + +#ifdef WSC_AP_SUPPORT + if ((pApCfg->ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pApCfg->ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) + return FALSE; +#endif /* WSC_AP_SUPPORT */ + + if (pApCfg->ApCliAutoConnectRunning == FALSE) + { + ApCliSetIfState(pAd, ifIndex, FALSE); + pApCfg->ApCliAutoConnectRunning = TRUE; + } + else + { + return TRUE; + } + + /* + use site survey function to trigger auto connecting (when pAd->ApCfg.ApAutoConnectRunning == TRUE) + */ + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + ApCliSiteSurvey(pAd, ifIndex, &Ssid, SCAN_ACTIVE, FALSE); + + return TRUE; +} + +/* + =================================================== + + Description: + Find the AP that is configured in the ApcliTab, and switch to + the channel of that AP + + Arguments: + pAd: pointer to our adapter + + Return Value: + TRUE: no error occured + FALSE: otherwise + + Note: + =================================================== +*/ +BOOLEAN ApCliAutoConnectExec( + IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIdx, CfgSsidLen, entryIdx; + STRING *pCfgSsid; + BSS_TABLE *pScanTab, *pSsidBssTab; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliAutoConnectExec()\n")); + + pObj->ioctl_if_type = INT_APCLI; + + for(ifIdx=0; ifIdxApCfg.ApCliTab[ifIdx].AutoConnectFlag == TRUE) + break; + } + + if(ifIdx >= MAX_APCLI_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error ifIdx=%d\n", ifIdx)); + return FALSE; + } + +#ifdef WSC_AP_SUPPORT + if ((pAd->ApCfg.ApCliTab[ifIdx].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIdx].WscControl.bWscTrigger == TRUE)) + { + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + return FALSE; + } +#endif /* WSC_AP_SUPPORT */ + + CfgSsidLen = pAd->ApCfg.ApCliTab[ifIdx].CfgSsidLen; + pCfgSsid = pAd->ApCfg.ApCliTab[ifIdx].CfgSsid; + pScanTab = &pAd->ScanTab; + pSsidBssTab = &pAd->MlmeAux.SsidBssTab; + pSsidBssTab->BssNr = 0; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIdx]; + wdev = &pApCliEntry->wdev; + /* + Find out APs with the desired SSID. + */ + for (entryIdx=0; entryIdxBssNr;entryIdx++) + { + BSS_ENTRY *pBssEntry = &pScanTab->BssEntry[entryIdx]; + BOOLEAN bAddEntry = FALSE; + + if ( pBssEntry->Channel == 0) + break; + + if (NdisEqualMemory(pCfgSsid, pBssEntry->Ssid, CfgSsidLen) && + (CfgSsidLen == pBssEntry->SsidLen) && + (pSsidBssTab->BssNr < MAX_LEN_OF_BSS_TABLE)) + { + + if (wdev->bWpaAutoMode == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE,("WPA_AUTO Mode under the APCLI_AUTO_CONNECT mode\n")); + if (pBssEntry->WPA2.PairCipher != Ndis802_11WEPDisabled) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA_AUTO Mode peerAp: RSN IE (ApCliAutoConnect)\n")); + wdev->AuthMode = pBssEntry->AuthMode; + } + else if (pBssEntry->WPA.PairCipher != Ndis802_11WEPDisabled) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA_AUTO Mode peerAp: WPA IE (ApCliAutoConnect)\n")); + wdev->AuthMode = pBssEntry->AuthMode; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA_AUTO Mode peerAp: no Rsn/WPA IE (ApCliAutoConnect)\n")); + } + } + + if (wdev->bEncryptAutoMode == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE,("ENCRYPT_AUTO Mode under the APCLI_AUTO_CONNECT mode\n")); + if (pBssEntry->WPA2.PairCipher != Ndis802_11WEPDisabled) + { + DBGPRINT(RT_DEBUG_TRACE, ("ENCRYPT_AUTO Mode peerAp: RSN IE (ApCliAutoConnect)\n")); + wdev->WepStatus = pBssEntry->WPA2.PairCipher; + } + else if (pBssEntry->WPA.PairCipher != Ndis802_11WEPDisabled) + { + DBGPRINT(RT_DEBUG_TRACE, ("ENCRYPT_AUTO Mode peerAp: WPA IE (ApCliAutoConnect)\n")); + wdev->WepStatus = pBssEntry->WPA.PairCipher; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ENCRYPT_AUTO Mode peerAp: no Rsn/WPA IE (ApCliAutoConnect)\n")); + } + } + + if (ApcliCompareAuthEncryp(&pAd->ApCfg.ApCliTab[ifIdx], + pBssEntry->AuthMode, + pBssEntry->AuthModeAux, + pBssEntry->WepStatus, + pBssEntry->WPA) || + ApcliCompareAuthEncryp(&pAd->ApCfg.ApCliTab[ifIdx], + pBssEntry->AuthMode, + pBssEntry->AuthModeAux, + pBssEntry->WepStatus, + pBssEntry->WPA2)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("Found desired ssid in Entry %2d:\n", entryIdx)); + DBGPRINT(RT_DEBUG_TRACE, + ("I/F(%s%d) ApCliAutoConnectExec:(Len=%d,Ssid=%s, Channel=%d, Rssi=%d)\n", + INF_APCLI_DEV_NAME, ifIdx, pBssEntry->SsidLen, pBssEntry->Ssid, + pBssEntry->Channel, pBssEntry->Rssi)); + DBGPRINT(RT_DEBUG_TRACE, + ("I/F(%s%d) ApCliAutoConnectExec::(AuthMode=%s, EncrypType=%s)\n", INF_APCLI_DEV_NAME, ifIdx, + GetAuthMode(pBssEntry->AuthMode), + GetEncryptType(pBssEntry->WepStatus)) ); + + if(MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + bAddEntry = TRUE; +#ifdef SMART_MESH + if(!pApCliEntry->SmartMeshCfg.bHiFiPeerFilter || pBssEntry->bHyperFiPeer) + bAddEntry = TRUE; + else + bAddEntry = FALSE; +#endif /* SMART_MESH */ + } + else if(MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, pBssEntry->Bssid)) + bAddEntry = TRUE; + + if(bAddEntry) + NdisMoveMemory(&pSsidBssTab->BssEntry[pSsidBssTab->BssNr++],pBssEntry, sizeof(BSS_ENTRY)); + } + } + } + + NdisZeroMemory(&pSsidBssTab->BssEntry[pSsidBssTab->BssNr], sizeof(BSS_ENTRY)); + + /* + Sort by Rssi in the increasing order, and connect to + the last entry (strongest Rssi) + */ + BssTableSortByRssi(pSsidBssTab, TRUE); + + + if ((pSsidBssTab->BssNr == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("No match entry.\n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } + else if (pSsidBssTab->BssNr > 0 && + pSsidBssTab->BssNr <=MAX_LEN_OF_BSS_TABLE) + { + /* + Switch to the channel of the candidate AP + */ + UCHAR CandidateAPChannel[8]; + UCHAR *pCandidateAPBssid = NULL; + BOOLEAN bChangeToCandidateAP = TRUE; + + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + /* + We don't want this feature to impact desired bssid. + */ + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid)) + { + bChangeToCandidateAP = FALSE; + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + DBGPRINT(RT_DEBUG_TRACE, + ("%s: This candidate AP(%02X:%02X:%02X:%02X:%02X:%02X) not match with CfgApCliBssid(%02X:%02X:%02X:%02X:%02X:%02X).\n", + __FUNCTION__,PRINT_MAC(pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid), + PRINT_MAC(pApCliEntry->CfgApCliBssid))); + } + } + else + { + pCandidateAPBssid = pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid; + } + + if(bChangeToCandidateAP) + { + BSS_ENTRY *pBssEntry = &pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1]; + + if (pAd->CommonCfg.Channel != pBssEntry->Channel) + { + ApCliSetIfState(pAd, ifIdx, FALSE); + + sprintf(CandidateAPChannel, "%d", pBssEntry->Channel); + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", CandidateAPChannel)); + Set_Channel_Proc(pAd, CandidateAPChannel); + } + + if (pCandidateAPBssid) + ApCliSetBssid(pAd, ifIdx, pCandidateAPBssid); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Error! Out of table range: (BssNr=%d).\n", pSsidBssTab->BssNr) ); + ApCliSetIfState(pAd, ifIdx, TRUE); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("<--- ApCliAutoConnectExec()\n")); + return FALSE; + } + + ApCliSetIfState(pAd, ifIdx, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("<--- ApCliAutoConnectExec()\n")); + + return TRUE; +} + +/* + =================================================== + + Description: + If the previous selected entry connected failed, this function will + choose next entry to connect. The previous entry will be deleted. + + Arguments: + pAd: pointer to our adapter + + Note: + Note that the table is sorted by Rssi in the "increasing" order, thus + the last entry in table has stringest Rssi. + =================================================== +*/ + +VOID ApCliSwitchCandidateAP( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + BSS_TABLE *pSsidBssTab; + PAPCLI_STRUCT pApCliEntry; + UCHAR lastEntryIdx; + +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (pAd->ApCfg.bPartialScanning == TRUE) + return; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliSwitchCandidateAP()\n")); + pSsidBssTab = &pAd->MlmeAux.SsidBssTab; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + if (pSsidBssTab->BssNr == 0) + { + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + goto exit_and_enable; + } + + /* + delete (zero) the previous connected-failled entry and always + connect to the last entry in talbe until the talbe is empty. + */ + NdisZeroMemory(&pSsidBssTab->BssEntry[--pSsidBssTab->BssNr], sizeof(BSS_ENTRY)); + lastEntryIdx = pSsidBssTab->BssNr -1; + + if ((pSsidBssTab->BssNr > 0) && (pSsidBssTab->BssNr < MAX_LEN_OF_BSS_TABLE)) + { + UCHAR CandidateAPChannel[8]; + UCHAR *pCandidateAPBssid = NULL; + BOOLEAN bChangeToCandidateAP = TRUE; + + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + /* + We don't want this feature to impact desired bssid. + */ + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, pSsidBssTab->BssEntry[lastEntryIdx].Bssid)) + { + bChangeToCandidateAP = FALSE; + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + DBGPRINT(RT_DEBUG_TRACE, + ("%s: This candidate AP(%02X:%02X:%02X:%02X:%02X:%02X) not match with CfgApCliBssid(%02X:%02X:%02X:%02X:%02X:%02X).\n", + __FUNCTION__,PRINT_MAC(pSsidBssTab->BssEntry[lastEntryIdx].Bssid),PRINT_MAC(pApCliEntry->CfgApCliBssid))); + } + } + else + { + pCandidateAPBssid = pSsidBssTab->BssEntry[lastEntryIdx].Bssid; + } + + if(bChangeToCandidateAP) + { + BSS_ENTRY *pBssEntry = &pSsidBssTab->BssEntry[lastEntryIdx]; + + if (pAd->CommonCfg.Channel != pBssEntry->Channel) + { + ApCliSetIfState(pAd, ifIndex, FALSE); + + sprintf(CandidateAPChannel, "%d", pBssEntry->Channel); + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", CandidateAPChannel)); + Set_Channel_Proc(pAd, CandidateAPChannel); + } + + if (pCandidateAPBssid) + ApCliSetBssid(pAd, ifIndex, pCandidateAPBssid); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("No candidate AP, the process is about to stop.\n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } + +exit_and_enable: + + ApCliSetIfState(pAd, ifIndex, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliSwitchCandidateAP()\n")); +} + + +BOOLEAN ApcliCompareAuthEncryp( + IN PAPCLI_STRUCT pApCliEntry, + IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, + IN NDIS_802_11_AUTHENTICATION_MODE AuthModeAux, + IN NDIS_802_11_WEP_STATUS WEPstatus, + IN CIPHER_SUITE WPA) +{ + NDIS_802_11_AUTHENTICATION_MODE tempAuthMode = pApCliEntry->wdev.AuthMode; + NDIS_802_11_WEP_STATUS tempWEPstatus = pApCliEntry->wdev.WepStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("ApcliAuthMode=%s, AuthMode=%s, AuthModeAux=%s, ApcliWepStatus=%s, WepStatus=%s, GroupCipher=%s, PairCipher=%s, \n", + GetAuthMode(pApCliEntry->wdev.AuthMode), + GetAuthMode(AuthMode), + GetAuthMode(AuthModeAux), + GetEncryptType(pApCliEntry->wdev.WepStatus), + GetEncryptType(WEPstatus), + GetEncryptType(WPA.GroupCipher), + GetEncryptType(WPA.PairCipher))); + + if (tempAuthMode <= Ndis802_11AuthModeAutoSwitch) + { + tempAuthMode = Ndis802_11AuthModeOpen; + return ((tempAuthMode == AuthMode || + tempAuthMode == AuthModeAux) && + (tempWEPstatus == WEPstatus) ); + } + else if (tempAuthMode <= Ndis802_11AuthModeWPA2PSK) + { + return ((tempAuthMode == AuthMode || + tempAuthMode == AuthModeAux) && + (tempWEPstatus == WPA.GroupCipher|| + tempWEPstatus == WPA.PairCipher) ); + } + else + { + /* not supported cases */ + return FALSE; + } + +} + +VOID RTMPApCliReconnectionCheck( + IN PRTMP_ADAPTER pAd) +{ + INT i; + PCHAR pApCliSsid, pApCliCfgSsid; + UCHAR CfgSsidLen; + NDIS_802_11_SSID Ssid; + + if (pAd->ApCfg.ApCliAutoConnectRunning == FALSE) + { + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliSsid = pAd->ApCfg.ApCliTab[i].Ssid; + pApCliCfgSsid = pAd->ApCfg.ApCliTab[i].CfgSsid; + CfgSsidLen = pAd->ApCfg.ApCliTab[i].CfgSsidLen; + if ((pAd->ApCfg.ApCliTab[i].CtrlCurrState < APCLI_CTRL_AUTH || + !NdisEqualMemory(pApCliSsid, pApCliCfgSsid, CfgSsidLen)) && + pAd->ApCfg.ApCliTab[i].CfgSsidLen > 0 && + pAd->Mlme.OneSecPeriodicRound % 10 == 0) + { + DBGPRINT(RT_DEBUG_TRACE, (" %s(): Scan channels for AP (%s)\n", + __FUNCTION__, pApCliCfgSsid)); + pAd->ApCfg.ApCliAutoConnectRunning = TRUE; + Ssid.SsidLength = CfgSsidLen; + NdisCopyMemory(Ssid.Ssid, pApCliCfgSsid, CfgSsidLen); + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE); + + } + } + } +} +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +/* + =================================================== + + Description: + + When root AP is Open WEP, it will cause a fake connection state if user keys in + wrong password. So we need this to fix the issue. + + Arguments: + pAd: pointer to our adapter + pRxBlk: carry necessary packet info 802.11 format + bSuccessPkt: see if it is a successfully decrypted packet. + Note: + =================================================== +*/ +VOID ApCliRxOpenWEPCheck( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN BOOLEAN bSuccessPkt) +{ + APCLI_STRUCT *pApCliEntry = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + BOOLEAN isMCPkt = FALSE; + int wcid; + + if(!pRxBlk || !pHeader || !pRxInfo) + return; + + wcid = pRxBlk->wcid; + if((wcid >= WCID_ALL) || (wcid == MCAST_WCID)) + return; + + if (VALID_WCID(wcid)) + pEntry = ApCliTableLookUpByWcid(pAd, wcid, pHeader->Addr2); + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if(!pEntry || !IS_ENTRY_APCLI(pEntry)) + return; + + if((pEntry->wdev_idx == 0xff) || + (pEntry->wdev_idx >= MAX_APCLI_NUM)) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + if(!pApCliEntry || + !pApCliEntry->Valid || + !pApCliEntry->OpenWEPErrPktChk) + return; + + if (pRxInfo->Mcast || pRxInfo->Bcast) + isMCPkt = TRUE; + + if(bSuccessPkt) + { + if((pHeader->FC.Type == FC_TYPE_DATA) && + (pHeader->FC.SubType != SUBTYPE_DATA_NULL) && + (pHeader->FC.SubType != SUBTYPE_QOS_NULL) && + (pRxBlk->DataSize > 0)) + { + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + pApCliEntry->OpenWEPErrPktChk = FALSE; + } + } + else + { + pApCliEntry->OpenWEPErrPktCnt++; + if(pApCliEntry->OpenWEPErrPktCnt >= OPENWEP_ERRPKT_MAX_COUNT) + { + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pApCliEntry->OpenWEPErrPktChk = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("(%s:%d): Stop Open WEP check!\n",__func__,__LINE__)); + } + if(isMCPkt) pApCliEntry->OpenWEPErrMCPktCnt++; + } +} + +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_apcli_inf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_apcli_inf.c new file mode 100644 index 000000000..1d4e340f5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_apcli_inf.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_assoc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_assoc.c new file mode 100644 index 000000000..d93d23a80 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_assoc.c @@ -0,0 +1,2442 @@ +/**************************************************************************** + * 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: + assoc.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 08-04-2003 created for 11g soft-AP + */ + +#include "rt_config.h" + +#ifdef DELAYED_TCP_ACK +DECLARE_TIMER_FUNCTION(RTMPQueueAckPeriodicExec); +BUILD_TIMER_FUNCTION(RTMPQueueAckPeriodicExec); +#endif /* DELAYED_TCP_ACK */ + +static void ap_assoc_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN isReassoc, + IN MAC_TABLE_ENTRY *pEntry, + IN IE_LISTS *ie_list) +{ +#ifdef DBG + PUCHAR sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; +#endif /* DBG */ + struct wifi_dev *wdev; + + wdev = &pAd->ApCfg.MBSSID[pEntry->apidx].wdev; + DBGPRINT(RT_DEBUG_TRACE, ("%s - \n\tAssign AID=%d to STA %02x:%02x:%02x:%02x:%02x:%02x\n", + sAssoc, pEntry->Aid, PRINT_MAC(pEntry->Addr))); + +#ifdef DOT11_N_SUPPORT + if (ie_list->ht_cap_len && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + assoc_ht_info_debugshow(pAd, pEntry, ie_list->ht_cap_len, &ie_list->HTCapability); + + DBGPRINT(RT_DEBUG_TRACE, ("\n%s - Update AP OperaionMode=%d, fAnyStationIsLegacy=%d, fAnyStation20Only=%d, fAnyStationNonGF=%d\n\n", + sAssoc, + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, + pAd->MacTab.fAnyStationIsLegacy, + pAd->MacTab.fAnyStation20Only, + pAd->MacTab.fAnyStationNonGF)); + +#ifdef DOT11_VHT_AC + if ((ie_list->vht_cap_len) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + { + assoc_vht_info_debugshow(pAd, pEntry, &ie_list->vht_cap, NULL); + } +#endif /* DOT11_VHT_AC */ + + + DBGPRINT(RT_DEBUG_TRACE, ("\tExt Cap Info: \n")); +#ifdef DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBss2040CoexistMgmt=%d\n", + pEntry->BSS2040CoexistenceMgmtSupport)); +#endif /* DOT11N_DRAFT3 */ +#ifdef DOT11_VHT_AC + DBGPRINT(RT_DEBUG_TRACE, ("\t\tOperatinModeNotification(%d)\n", + pEntry->ext_cap.operating_mode_notification)); + if (pEntry->ext_cap.operating_mode_notification) { + DBGPRINT(RT_DEBUG_TRACE, ("\t\t\tChannelWidth(%d), RxNss(%d), RxNssType(%d), ForceOpMode(%d)\n", + pEntry->operating_mode.ch_width, + pEntry->operating_mode.rx_nss, + pEntry->operating_mode.rx_nss_type, + pEntry->force_op_mode)); + } +#endif /* DOT11_VHT_AC */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - legacy STA\n", sAssoc)); + DBGPRINT(RT_DEBUG_TRACE, ("\n%s - MODE=%d, MCS=%d\n", sAssoc, + pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.MCS)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("\tAuthMode=%d, WepStatus=%d, WpaState=%d, GroupKeyWepStatus=%d\n", + pEntry->AuthMode, pEntry->WepStatus, pEntry->WpaState, wdev->GroupKeyWepStatus)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tWMMCap=%d, RalinkAgg=%d, PiggyBack=%d, RDG=%d, TxAMSDU=%d, IdleTimeout=%d\n", + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED), + pEntry->StaIdleTimeout)); + +} + + +static USHORT update_associated_mac_entry( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN IE_LISTS *ie_list, + IN UCHAR MaxSupportedRate) +{ + struct wifi_dev *wdev; +#ifdef TXBF_SUPPORT + BOOLEAN supportsETxBF = FALSE; +#endif // TXBF_SUPPORT // + + ASSERT((pEntry->apidx < pAd->ApCfg.BssidNum)); + wdev = &pAd->ApCfg.MBSSID[pEntry->apidx].wdev; + + /* Update auth, wep, legacy transmit rate setting . */ + pEntry->Sst = SST_ASSOC; + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + set_entry_phy_cfg(pAd, pEntry); + + pEntry->CapabilityInfo = ie_list->CapabilityInfo; + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + } +#ifdef DOT1X_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->IEEE8021X == TRUE)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_AUTHENTICATION; + } +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeWAICERT) || + (pEntry->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_AUTHENTICATION2; + } +#endif /* WAPI_SUPPORT */ + + /*if (ClientRalinkIe & 0x00000004) */ + if (ie_list->RalinkIe != 0x0) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + else + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + + /* Ralink proprietary Piggyback and Aggregation support for legacy RT61 chip */ + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); +#ifdef AGGREGATION_SUPPORT + if ((pAd->CommonCfg.bAggregationCapable) && (ie_list->RalinkIe & 0x00000001)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -RaAggregate= 1\n")); + } +#endif /* AGGREGATION_SUPPORT */ +#ifdef PIGGYBACK_SUPPORT + if ((pAd->CommonCfg.bPiggyBackCapable) && (ie_list->RalinkIe & 0x00000002)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -PiggyBack= 1\n")); + } +#endif /* PIGGYBACK_SUPPORT */ +#ifdef DOT11_VHT_AC + if ((pAd->CommonCfg.b256QAM_2G) + && ((ie_list->RalinkIe & 0x00000008) || (ie_list->MediatekIe & 0x00000008))) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_2G_256QAM_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -2.4G_256QAM= 1\n")); + } +#endif /* DOT11_VHT_AC */ + + /* In WPA or 802.1x mode, the port is not secured, otherwise is secued. */ + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif /* DOT1X_SUPPORT */ + ) + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + +#ifdef SOFT_ENCRYPT + /* There are some situation to need to encryption by software + 1. The Client support PMF. It shall ony support AES cipher. + 2. The Client support WAPI. + If use RT3883 or later, HW can handle the above. + */ +#ifdef WAPI_SUPPORT + if (!(IS_HW_WAPI_SUPPORT(pAd)) + && (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + if ((pAd->chipCap.FlgPMFEncrtptMode == PMF_ENCRYPT_MODE_0) + && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* SOFT_ENCRYPT */ + +#ifdef DOT11_N_SUPPORT + /* + WFA recommend to restrict the encryption type in 11n-HT mode. + So, the WEP and TKIP are not allowed in HT rate. + */ + if (pAd->CommonCfg.HT_DisallowTKIP && + IS_INVALID_HT_SECURITY(pEntry->WepStatus)) + { + /* Force to None-HT mode due to WiFi 11n policy */ + ie_list->ht_cap_len = 0; +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len = 0; +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_TRACE, ("%s : Force the STA as Non-HT mode\n", __FUNCTION__)); + } + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((ie_list->ht_cap_len != 0) && + (wdev->DesiredHtPhyInfo.bHtEnable) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ht_mode_adjust(pAd, pEntry, &ie_list->HTCapability, &pAd->CommonCfg.DesiredHtPhy); + +#ifdef DOT11N_DRAFT3 + if (ie_list->ExtCapInfo.BssCoexistMgmtSupport) + pEntry->BSS2040CoexistenceMgmtSupport = 1; +#endif /* DOT11N_DRAFT3 */ +#ifdef CONFIG_HOTSPOT_R2 + if (ie_list->ExtCapInfo.qosmap) + pEntry->QosMapSupport = 1; +#endif +#ifdef DOT11V_WNM_SUPPORT + if(IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, pEntry->apidx)) + { + if(ie_list->ExtCapInfo.BssTransitionManmt) + pEntry->BssTransitionManmtSupport = 1; + } + if(IS_WNMDMS_SUPPORT(pAd, pEntry->apidx)) + { + if(ie_list->ExtCapInfo.DMSSupport) + pEntry->DMSSupport = 1; + } +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11N_DRAFT3 + /* 40Mhz BSS Width Trigger events */ + if (ie_list->HTCapability.HtCapInfo.Forty_Mhz_Intolerant) + { + pEntry->bForty_Mhz_Intolerant = TRUE; + pAd->MacTab.fAnyStaFortyIntolerant = TRUE; + if(((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.Channel <=14)) && + ((pAd->CommonCfg.bBssCoexEnable == TRUE) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0)) + ) + { + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; + } + DBGPRINT(RT_DEBUG_TRACE, ("pEntry set 40MHz Intolerant as 1\n")); + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef TXBF_SUPPORT +#ifdef VHT_TXBF_SUPPORT + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (ie_list->vht_cap_len)) + supportsETxBF = clientSupportsVHTETxBF(pAd, &ie_list->vht_cap.vht_cap); + else +#endif /* VHT_TXBF_SUPPORT */ + supportsETxBF = clientSupportsETxBF(pAd, &ie_list->HTCapability.TxBFCap); +#endif /* TXBF_SUPPORT */ + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], + &ie_list->HTCapability.MCSSet[0]); + + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("@@@ IF-ra%d DesiredTransmitSetting.field.MCS = %d\n", + pEntry->apidx, + wdev->DesiredTransmitSetting.field.MCS)); + + set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + } + + pEntry->MaxHTPhyMode.field.STBC = (ie_list->HTCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + // TODO: shiang-6590, check if this is necessary here, perforce didn't have this + if (ie_list->HTCapability.HtCapParm.MpduDensity < 5) + ie_list->HTCapability.HtCapParm.MpduDensity = 5; + + pEntry->MpduDensity = ie_list->HTCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = ie_list->HTCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)ie_list->HTCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)ie_list->HTCapability.HtCapInfo.AMsduSize; + + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + + if (pAd->CommonCfg.ht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (ie_list->HTCapability.HtCapInfo.ht_rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE); + } + + if (ie_list->HTCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (ie_list->HTCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (ie_list->HTCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (ie_list->HTCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (ie_list->HTCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && ie_list->HTCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (ie_list->HTCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + /* Record the received capability from association request */ + NdisMoveMemory(&pEntry->HTCapability, &ie_list->HTCapability, sizeof(HT_CAPABILITY_IE)); + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + ie_list->vht_cap_len) + { + VHT_CAP_INFO *vht_cap_info = &ie_list->vht_cap.vht_cap; + + vht_mode_adjust(pAd, pEntry, &ie_list->vht_cap, (ie_list->vht_op_len == 0) ? NULL : &ie_list->vht_op); + + pEntry->VhtMaxRAmpduFactor = ie_list->vht_cap.vht_cap.max_ampdu_exp; + + DBGPRINT(RT_DEBUG_TRACE, ("Orig HT MaxRAmpduFactor %d , VHT MaxRAmpduFactor %d \n" + ,ie_list->HTCapability.HtCapParm.MaxRAmpduFactor,ie_list->vht_cap.vht_cap.max_ampdu_exp)); + + /* TODO: implement get_vht_max_mcs to get peer max MCS */ + if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = 8; + else + pEntry->MaxHTPhyMode.field.MCS = 9; + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = 8; + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = 7; + } + + if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + else + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 9); + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 7); + } + + + DBGPRINT(RT_DEBUG_OFF, ("%s(): Peer's PhyCap=>Mode:%s, BW:%s\n", + __FUNCTION__, + get_phymode_str(pEntry->MaxHTPhyMode.field.MODE), + get_bw_str(pEntry->MaxHTPhyMode.field.BW))); + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (vht_cap_info->rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE); + } + + if (vht_cap_info->sgi_80M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE); + + if (vht_cap_info->sgi_160M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE); + + if (pAd->CommonCfg.vht_stbc) + { + if (vht_cap_info->tx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE); + if (vht_cap_info->rx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE); + } + NdisMoveMemory(&pEntry->vht_cap_ie, &ie_list->vht_cap, sizeof(VHT_CAP_IE)); + } + + if (ie_list->operating_mode_len == sizeof(OPERATING_MODE) && + ie_list->operating_mode.rx_nss_type == 0) + { + pEntry->operating_mode = ie_list->operating_mode; + pEntry->force_op_mode = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("%s(): Peer's OperatingMode=>RxNssType: %d, RxNss: %d, ChBW: %d\n", + __FUNCTION__, pEntry->operating_mode.rx_nss_type, + pEntry->operating_mode.rx_nss, + pEntry->operating_mode.ch_width)); + } + else + pEntry->force_op_mode = FALSE; +#endif /* DOT11_VHT_AC */ + } + else + { +#ifdef CONFIG_HOTSPOT_R2 + if (ie_list->ExtCapInfo.qosmap) + pEntry->QosMapSupport = 1; +#endif + + pAd->MacTab.fAnyStationIsLegacy = TRUE; + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); +#ifdef DOT11_VHT_AC + // TODO: shiang-usw, it's ugly and need to revise it + NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); + NdisZeroMemory(&pEntry->SupportVHTMCS, sizeof(pEntry->SupportVHTMCS)); + pEntry->SupportRateMode &= (~SUPPORT_VHT_MODE); +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + +#ifdef MFB_SUPPORT + pEntry->lastLegalMfb = 0; + pEntry->isMfbChanged = FALSE; + pEntry->fLastChangeAccordingMfb = FALSE; + + pEntry->toTxMrq = TRUE; + pEntry->msiToTx = 0;/*has to increment whenever a mrq is sent */ + pEntry->mrqCnt = 0; + + pEntry->pendingMfsi = 0; + + pEntry->toTxMfb = FALSE; + pEntry->mfbToTx = 0; + pEntry->mfb0 = 0; + pEntry->mfb1 = 0; +#endif /* MFB_SUPPORT */ + + pEntry->freqOffsetValid = FALSE; + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) { + TxBFInit(pAd, pEntry, supportsETxBF); + if (supportsETxBF) { + HT_BF_CAP *pTxBFCap = &ie_list->HTCapability.TxBFCap; + UCHAR ndpSndgStreams = pAd->Antenna.field.TxPath; + + if ((pTxBFCap->ExpComBF > 0) && (!pAd->CommonCfg.ETxBfNoncompress)) + { + if ((pTxBFCap->ComSteerBFAntSup + 1) < pAd->Antenna.field.TxPath) + ndpSndgStreams = pTxBFCap->ComSteerBFAntSup + 1; + } + + if ((pTxBFCap->ExpNoComBF > 0) && (pAd->CommonCfg.ETxBfNoncompress)) + { + if ((pTxBFCap->NoComSteerBFAntSup + 1) < pAd->Antenna.field.TxPath) + ndpSndgStreams = pTxBFCap->NoComSteerBFAntSup + 1; + } + pEntry->ndpSndgStreams = ndpSndgStreams; + } + } +#endif // TXBF_SUPPORT // + + // Initialize Rate Adaptation + MlmeRAInit(pAd, pEntry); + + /* Set asic auto fall back */ + if (wdev->bAutoTxRateSwitch == TRUE) + { + UCHAR TableSize = 0; + + pEntry->bAutoTxRateSwitch = TRUE; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + MlmeNewTxRate(pAd, pEntry); + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (! ADAPT_RATE_TABLE(pEntry->pTable)) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pEntry->HTPhyMode.field.ShortGI = GI_800; + } + else + { + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; +#ifdef WFA_VHT_PF + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS + + ((pAd->CommonCfg.TxStream - 1) << 4); + } +#endif /* WFA_VHT_PF */ + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(SS=%d): pMbss(FixedTxMode=%d, MCS=%d), pEntry(Mode=%d, MCS=%d)\n", + __FUNCTION__, pAd->CommonCfg.TxStream, + wdev->DesiredTransmitSetting.field.FixedTxMode, + wdev->DesiredTransmitSetting.field.MCS, + pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.MCS)); + } + + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + ApLogEvent(pAd, pEntry->Addr, EVENT_ASSOCIATED); + + APUpdateCapabilityAndErpIe(pAd); +#ifdef DOT11_N_SUPPORT + APUpdateOperationMode(pAd); +#endif /* DOT11_N_SUPPORT */ + + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + +#ifdef HOSTAPD_SUPPORT + if((wdev->Hostapd == Hostapd_EXT) && + ((wdev->AuthMode >= Ndis802_11AuthModeWPA) || wdev->IEEE8021X)) + { + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, + -1, pEntry->Addr, NULL, 0, + ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); + } +#endif /*HOSTAPD_SUPPORT*/ + + return MLME_SUCCESS; +} + + +/* + ========================================================================== + Description: + assign a new AID to the newly associated/re-associated STA and + decide its MaxSupportedRate and CurrTxRate. Both rates should not + exceed AP's capapbility + Return: + MLME_SUCCESS - association successfully built + others - association failed due to resource issue + ========================================================================== + */ +static USHORT APBuildAssociation( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN IE_LISTS *ie_list, + IN UCHAR MaxSupportedRateIn500Kbps, + OUT USHORT *pAid) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR MaxSupportedRate = RATE_11; + struct wifi_dev *wdev; +#ifdef WSC_AP_SUPPORT + WSC_CTRL *wsc_ctrl; +#endif /* WSC_AP_SUPPORT */ + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + + if ((WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_G) +#ifdef DOT11_N_SUPPORT + || WMODE_EQUAL(pAd->CommonCfg.PhyMode, (WMODE_G | WMODE_GN)) +#endif /* DOT11_N_SUPPORT */ + ) + && (MaxSupportedRate < RATE_FIRST_OFDM_RATE) + ) + return MLME_ASSOC_REJ_DATA_RATE; + +#ifdef DOT11_N_SUPPORT + /* 11n only */ + if (WMODE_HT_ONLY(pAd->CommonCfg.PhyMode)&& (ie_list->ht_cap_len == 0)) + return MLME_ASSOC_REJ_DATA_RATE; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (ie_list->vht_cap_len == 0) && + (pAd->CommonCfg.bNonVhtDisallow)) + return MLME_ASSOC_REJ_DATA_RATE; +#endif /* DOT11_VHT_AC */ + + if (!pEntry) + return MLME_UNSPECIFY_FAIL; + + if (pEntry && ((pEntry->Sst == SST_AUTH) || (pEntry->Sst == SST_ASSOC))) + { + /* TODO: + should qualify other parameters, for example - + capablity, supported rates, listen interval, etc., to + decide the Status Code + */ + *pAid = pEntry->Aid; + pEntry->NoDataIdleCount = 0; + pEntry->StaConnectTime = 0; +#ifdef CONFIG_HOTSPOT_R2 + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE)) +#endif + { +#ifdef WSC_AP_SUPPORT + if (pEntry->bWscCapable == FALSE) +#endif /* WSC_AP_SUPPORT */ + { + /* check the validity of the received RSNIE */ + if ((StatusCode = APValidateRSNIE(pAd, pEntry, &ie_list->RSN_IE[0], ie_list->RSNIE_Len)) != MLME_SUCCESS) + return StatusCode; + } + } + + + NdisMoveMemory(pEntry->RSN_IE, &ie_list->RSN_IE[0], ie_list->RSNIE_Len); + pEntry->RSNIE_Len = ie_list->RSNIE_Len; + + + wdev = &pAd->ApCfg.MBSSID[pEntry->apidx].wdev; + if (*pAid == 0) + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + else if ((pEntry->RSNIE_Len == 0) && + (wdev->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef HOSTAPD_SUPPORT + && (wdev->Hostapd == Hostapd_EXT) +#endif /* HOSTAPD_SUPPORT */ +#ifdef RT_CFG80211_SUPPORT + && (wdev->Hostapd == Hostapd_CFG) +#endif /*RT_CFG80211_SUPPORT*/ + + ) + { +#ifdef WSC_AP_SUPPORT + wsc_ctrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl; + if (((wsc_ctrl->WscConfMode != WSC_DISABLE) && + pEntry->bWscCapable +#ifdef WSC_V2_SUPPORT + && (wsc_ctrl->WscV2Info.bWpsEnable || + (wsc_ctrl->WscV2Info.bEnableWpsV2 == FALSE)) +#endif /* WSC_V2_SUPPORT */ + ) +#ifdef HOSTAPD_SUPPORT + || wdev->Hostapd == Hostapd_EXT +#endif /*HOSTAPD_SUPPORT*/ +#ifdef RT_CFG80211_SUPPORT + || wdev->Hostapd== Hostapd_CFG +#endif /*RT_CFG80211_SUPPORT*/ + + ) + { + pEntry->Sst = SST_ASSOC; + StatusCode = MLME_SUCCESS; + /* In WPA or 802.1x mode, the port is not secured. */ + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif /* DOT1X_SUPPORT */ + ) + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + } +#ifdef DOT1X_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->IEEE8021X == TRUE)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_AUTHENTICATION; + } +#endif /* DOT1X_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - WSC_STATE_MACHINE is OFF.\n", + wsc_ctrl->WscConfMode, pEntry->apidx)); + StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; + } +#else /* WSC_AP_SUPPORT */ +#ifdef RT_CFG80211_SUPPORT + //CFG_TODO: due to WPS_AP flag + pEntry->Sst = SST_ASSOC; + StatusCode = MLME_SUCCESS; +#else + StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; +#endif /* RT_CFG80211_P2P_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + if(wdev->Hostapd == Hostapd_EXT + && (wdev->AuthMode >= Ndis802_11AuthModeWPA + || wdev->IEEE8021X)) + { + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, + -1, pEntry->Addr, NULL, 0, + ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); + } +#endif /*HOSTAPD_SUPPORT*/ + } + else + { + StatusCode = update_associated_mac_entry(pAd, pEntry, ie_list, MaxSupportedRate); + } + } + else /* CLASS 3 error should have been handled beforehand; here should be MAC table full */ + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + + if (StatusCode == MLME_SUCCESS) + { + if (ie_list->bWmmCapable) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + } + + return StatusCode; +} + + +#ifdef IAPP_SUPPORT +/* + ======================================================================== + Routine Description: + Send Leyer 2 Update Frame to update forwarding table in Layer 2 devices. + + Arguments: + *mac_p - the STATION MAC address pointer + + Return Value: + TRUE - send successfully + FAIL - send fail + + Note: + ======================================================================== +*/ +static BOOLEAN IAPP_L2_Update_Frame_Send(RTMP_ADAPTER *pAd, UINT8 *mac, INT bssid) +{ + + NDIS_PACKET *pNetBuf; + + pNetBuf = RtmpOsPktIappMakeUp(get_netdev_from_bssid(pAd, bssid), mac); + if (pNetBuf == NULL) + return FALSE; + + /* UCOS: update the built-in bridge, too (don't use gmac.xmit()) */ + announce_802_3_packet(pAd, pNetBuf, OPMODE_AP); + + IAPP_L2_UpdatePostCtrl(pAd, mac, bssid); + + return TRUE; +} /* End of IAPP_L2_Update_Frame_Send */ +#endif /* IAPP_SUPPORT */ + + +VOID ap_cmm_peer_assoc_req_action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN BOOLEAN isReassoc) +{ + IE_LISTS *ie_list = NULL; + HEADER_802_11 AssocRspHdr; + USHORT CapabilityInfoForAssocResp; + USHORT StatusCode = MLME_SUCCESS; + USHORT Aid; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR MaxSupportedRate = 0; + UCHAR SupRateLen, PhyMode, FlgIs11bSta; + UCHAR i; + MAC_TABLE_ENTRY *pEntry; +#ifdef DBG + UCHAR *sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; +#endif /* DBG */ + UCHAR SubType; + BOOLEAN bACLReject = FALSE; +#ifdef DOT1X_SUPPORT + PUINT8 pPmkid = NULL; + UINT8 pmkid_count = 0; +#endif /* DOT1X_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT + PFT_CFG pFtCfg = NULL; + PFT_INFO pFtInfoBuf = NULL; /*Wframe-larger-than=1024 warning removal*/ +#endif /* DOT11R_FT_SUPPORT */ + struct wifi_dev *wdev; + MULTISSID_STRUCT *pMbss; +#ifdef WSC_AP_SUPPORT + WSC_CTRL *wsc_ctrl; +#endif /* WSC_AP_SUPPORT */ + BOOLEAN bAssocSkip = FALSE; + BOOLEAN bAssocNoRsp = FALSE; + CHAR rssi; +#ifdef DOT11R_FT_SUPPORT + UCHAR zeroFT[LEN_TK]; +#endif +#ifdef RT_BIG_ENDIAN + UINT32 tmp_1; + UINT64 tmp_2; +#endif /*RT_BIG_ENDIAN*/ + +#ifdef DOT11R_FT_SUPPORT + os_alloc_mem(NULL, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO)); + if (pFtInfoBuf == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): pFtInfoBuf mem alloc failed\n", __FUNCTION__)); + return; + } + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); +#endif /* DOT11R_FT_SUPPORT */ + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(IE_LISTS)); + if (ie_list == NULL) { +#ifdef DOT11R_FT_SUPPORT + if (pFtInfoBuf != NULL) + os_free_mem(NULL, pFtInfoBuf); +#endif /* DOT11R_FT_SUPPORT */ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): mem alloc failed\n", __FUNCTION__)); + return; + } + NdisZeroMemory(ie_list, sizeof(IE_LISTS)); + + if (!PeerAssocReqCmmSanity(pAd, isReassoc, Elem->Msg, Elem->MsgLen, ie_list)) + goto LabelOK; + + pEntry = MacTableLookup(pAd, ie_list->Addr2); + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, ("NoAuth MAC - %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(ie_list->Addr2))); + goto LabelOK; + } + + if (!VALID_MBSS(pAd, pEntry->apidx)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():pEntry bounding invalid wdev(apidx=%d)\n", + __FUNCTION__, pEntry->apidx)); + goto LabelOK; + } + + pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + wdev = &pMbss->wdev; +#ifdef WSC_AP_SUPPORT + wsc_ctrl = &pMbss->WscControl; +#endif /* WSC_AP_SUPPORT */ + + PhyMode = wdev->PhyMode; + + FlgIs11bSta = 1; + for(i=0; iSupportedRatesLen; i++) + { + if (((ie_list->SupportedRates[i] & 0x7F) != 2) && + ((ie_list->SupportedRates[i] & 0x7F) != 4) && + ((ie_list->SupportedRates[i] & 0x7F) != 11) && + ((ie_list->SupportedRates[i] & 0x7F) != 22)) + { + FlgIs11bSta = 0; + break; + } + } + + /* drop this assoc req by silencely discard this frame */ + if (FlgIs11bSta == 1 && (pAd->LatchRfRegs.Channel > 14 || !WMODE_EQUAL(PhyMode, WMODE_B))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():pEntry is 11b only STA and AP do not support 11B rates\n", + __FUNCTION__)); + goto LabelOK; + } + +#ifdef DOT11W_PMF_SUPPORT + if ((pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + StatusCode = MLME_ASSOC_REJ_TEMPORARILY; + goto SendAssocResponse; + } +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + NdisZeroMemory(zeroFT, LEN_TK); +#endif + + /* clear the previous Pairwise key table */ + if(pEntry->Aid != 0 && +#ifdef DOT11R_FT_SUPPORT + (pEntry->AllowInsPTK == TRUE || !IS_FT_STA(pEntry) || (IS_FT_STA(pEntry) && (NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], zeroFT, LEN_TK) || !NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pEntry->LastTK, LEN_TK)))) && +#endif + (pEntry->WepStatus >= Ndis802_11TKIPEnable +#ifdef DOT1X_SUPPORT + || wdev->IEEE8021X +#endif /* DOT1X_SUPPORT */ + )) + { + /* clear GTK state */ + pEntry->GTKState = REKEY_NEGOTIATING; + + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + + /* clear this entry as no-security mode */ + AsicRemovePairwiseKeyEntry(pAd, pEntry->wcid); + +#ifdef DOT1X_SUPPORT + /* Notify 802.1x daemon to clear this sta info */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || + pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + 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); + + RTMPCancelWapiRekeyTimerAction(pAd, pEntry); +#endif /* WAPI_SUPPORT */ + } + +#ifdef WSC_AP_SUPPORT + /* since sta has been left, ap should receive EapolStart and EapRspId again. */ + pEntry->Receive_EapolStart_EapRspId = 0; + pEntry->bWscCapable = ie_list->bWscCapable; +#ifdef SMART_MESH_HIDDEN_WPS + if(pMbss->SmartMeshCfg.bSupportHiddenWPS && pEntry->bRunningHiddenWPS) + pEntry->bWscCapable = TRUE; +#endif /* SMART_MESH_HIDDEN_WPS */ +#ifdef WSC_V2_SUPPORT + if ((wsc_ctrl->WscV2Info.bEnableWpsV2) && + (wsc_ctrl->WscV2Info.bWpsEnable == FALSE)) + ; + else +#endif /* WSC_V2_SUPPORT */ + { + if (pEntry->apidx < pAd->ApCfg.BssidNum) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, wsc_ctrl->EntryAddr)) + { + BOOLEAN Cancelled; + RTMPZeroMemory(wsc_ctrl->EntryAddr, MAC_ADDR_LEN); + RTMPCancelTimer(&wsc_ctrl->EapolTimer, &Cancelled); + wsc_ctrl->EapolTimerRunning = FALSE; + } + } + + if ((ie_list->RSNIE_Len == 0) && + (wdev->AuthMode >= Ndis802_11AuthModeWPA) && + (wsc_ctrl->WscConfMode != WSC_DISABLE)) + pEntry->bWscCapable = TRUE; + } +#endif /* WSC_AP_SUPPORT */ + + /* for hidden SSID sake, SSID in AssociateRequest should be fully verified */ + if ((ie_list->SsidLen != pMbss->SsidLen) || + (NdisEqualMemory(ie_list->Ssid, pMbss->Ssid, ie_list->SsidLen)==0)) + goto LabelOK; + +#ifdef WSC_V2_SUPPORT + /* Do not check ACL when WPS V2 is enabled and ACL policy is positive. */ + if ((pEntry->bWscCapable) && + (wsc_ctrl->WscConfMode != WSC_DISABLE) && + (wsc_ctrl->WscV2Info.bEnableWpsV2) && + (wsc_ctrl->WscV2Info.bWpsEnable) && + (MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, ZERO_MAC_ADDR))) + ; + else +#endif /* WSC_V2_SUPPORT */ + /* set a flag for sending Assoc-Fail response to unwanted STA later. */ + if (!ApCheckAccessControlList(pAd, ie_list->Addr2, pEntry->apidx)) + bACLReject = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - MBSS(%d), receive %s request from %02x:%02x:%02x:%02x:%02x:%02x\n", + sAssoc, pEntry->apidx, sAssoc, PRINT_MAC(ie_list->Addr2))); + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (i=0; iSupportedRatesLen; i++) + { + if (MaxSupportedRate < (ie_list->SupportedRates[i] & 0x7f)) + MaxSupportedRate = ie_list->SupportedRates[i] & 0x7f; + } + + /* + Assign RateLen here or we will select wrong rate table in + APBuildAssociation() when 11N compile option is disabled. + */ + pEntry->RateLen = ie_list->SupportedRatesLen; + +#ifdef DOT11_VHT_AC +#ifdef RT_BIG_ENDIAN + NdisCopyMemory(&tmp_1,&ie_list->vht_cap.vht_cap, 4); + tmp_1=SWAP32(tmp_1); + NdisCopyMemory(&ie_list->vht_cap.vht_cap,&tmp_1, 4); + + NdisCopyMemory(&tmp_2,&(ie_list->vht_cap.mcs_set), 8); + tmp_2=SWAP64(tmp_2); + NdisCopyMemory(&(ie_list->vht_cap.mcs_set),&tmp_2, 8); + //SWAP32((UINT32)vht_cap_ie.vht_cap); + //SWAP32((UINT32)vht_cap_ie.mcs_set); +#endif /* RT_BIG_ENDIAN */ +#endif /* DOT11_VHT_AC */ + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + ie_list->SupportedRates, + ie_list->SupportedRatesLen, + NULL, + 0, +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len, + &ie_list->vht_cap, +#endif /* DOT11_VHT_AC */ + &ie_list->HTCapability, + ie_list->ht_cap_len); + + /* 2. qualify this STA's auth_asoc status in the MAC table, decide StatusCode */ + StatusCode = APBuildAssociation(pAd, pEntry, ie_list, MaxSupportedRate, &Aid); + + /* drop this assoc req and send reject */ + if (StatusCode == MLME_ASSOC_REJ_DATA_RATE || StatusCode == MLME_UNSPECIFY_FAIL) { + //RTMPSendWirelessEvent(pAd, IW_STA_MODE_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + goto SendAssocResponse; + } + +#ifdef DOT11R_FT_SUPPORT + if (pEntry->apidx < pAd->ApCfg.BssidNum) + { + pFtCfg = &(pAd->ApCfg.MBSSID[pEntry->apidx].FtCfg); + if ((pFtCfg->FtCapFlag.Dot11rFtEnable) + && (StatusCode == MLME_SUCCESS)) + StatusCode = FT_AssocReqHandler(pAd, isReassoc, pFtCfg, pEntry, + &ie_list->FtInfo, pFtInfoBuf); + + /* just silencely discard this frame */ + if (StatusCode == 0xFFFF) + goto LabelOK; + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if ((pEntry->apidx < pAd->ApCfg.BssidNum) + && IS_RRM_ENABLE(pAd, pEntry->apidx)) + { + pEntry->RrmEnCap.word = ie_list->RrmEnCap.word; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len) + { +//+++Add by shiang for debug + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s():Peer is VHT capable device!\n", __FUNCTION__)); + + NdisMoveMemory(&pEntry->ext_cap, &ie_list->ExtCapInfo, sizeof(ie_list->ExtCapInfo)); + DBGPRINT(RT_DEBUG_TRACE, ("\tOperatingModeNotification=%d\n", + pEntry->ext_cap.operating_mode_notification)); + //dump_vht_cap(pAd, &ie_list->vht_cap); + } +//---Add by shiang for debug + } +#endif /* DOT11_VHT_AC */ + +SendAssocResponse: + + /* 3. send Association Response */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + goto LabelOK; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - Send %s response (Status=%d)...\n", sAssoc, sAssoc, StatusCode)); + Aid |= 0xc000; /* 2 most significant bits should be ON */ + + SubType = isReassoc ? SUBTYPE_REASSOC_RSP : SUBTYPE_ASSOC_RSP; + + CapabilityInfoForAssocResp = pMbss->CapabilityInfo; /*use AP's cability */ +#ifdef WSC_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((wsc_ctrl->WscV2Info.bEnableWpsV2) && + (wsc_ctrl->WscV2Info.bWpsEnable == FALSE)) + ; + else +#endif /* WSC_V2_SUPPORT */ + { + if ((wsc_ctrl->WscConfMode != WSC_DISABLE) && + (ie_list->CapabilityInfo & 0x0010)) + { + CapabilityInfoForAssocResp |= 0x0010; + } + } +#endif /* WSC_AP_SUPPORT */ + + /* fail in ACL checking => send an Assoc-Fail resp. */ + SupRateLen = pAd->CommonCfg.SupRateLen; + + /* TODO: need to check rate in support rate element, not number */ + if (FlgIs11bSta == 1) + SupRateLen = 4; + + /* YF@20120419: Refuse the weak signal of AssocReq */ + 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: ASSOC_FAIL_REQ Threshold = %d, ASSOC_NO_RSP_REQ Threshold = %d,PktMaxRssi=%d\n", + wdev->if_dev->name, pMbss->AssocReqFailRssiThreshold, + pMbss->AssocReqNoRspRssiThreshold, rssi)); + + if ((pMbss->AssocReqFailRssiThreshold != 0) && (rssi < pMbss->AssocReqFailRssiThreshold)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Reject this ASSOC_FAIL_REQ due to Weak Signal.\n")); + bAssocSkip = TRUE; + } + else if ((pMbss->AssocReqNoRspRssiThreshold != 0) && (rssi < pMbss->AssocReqNoRspRssiThreshold)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Reject this ASSOC_NO_RSP_REQ due to Weak Signal.\n")); + bAssocNoRsp = TRUE; + } + +#ifdef SMART_MESH + if((pMbss->SmartMeshCfg.bHiFiPeerFilter == TRUE) && + (pEntry && (pEntry->bHyperFiPeer == FALSE))) + { + bAssocNoRsp = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("Reject this ASSOC_REQ due to not desired Hyper-Fi peer(%02X:%02X:%02X:%02X:%02X:%02X).\n",PRINT_MAC(pEntry->Addr))); + } +#ifdef WSC_AP_SUPPORT + if ((bAssocNoRsp == FALSE) && + (wsc_ctrl->WscConfMode != WSC_DISABLE) && + (wsc_ctrl->bWscTrigger == TRUE) && + ((wsc_ctrl->WscMode == 2) && (wsc_ctrl->bWscPBCAddrMode == TRUE)) && + (pEntry && pEntry->bWscCapable && !MAC_ADDR_EQUAL(wsc_ctrl->WscPBCAddr,pEntry->Addr))) + { + bAssocNoRsp = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Reject this ASSOC_REQ due not desired PBC MAC target.\n")); + } +#endif /* WSC_AP_SUPPORT */ +#endif /* SMART_MESH */ + + if (bACLReject == TRUE || bAssocSkip || bAssocNoRsp) + { + if (!bAssocNoRsp) + { + MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, + wdev->if_addr, wdev->bssid); + StatusCode = MLME_UNSPECIFY_FAIL; + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocRspHdr, + 2, &CapabilityInfoForAssocResp, + 2, &StatusCode, + 2, &Aid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + } + + RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, ie_list->Addr2, pEntry->apidx, 0); + +#ifdef WSC_V2_SUPPORT + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); +#endif /* WSC_V2_SUPPORT */ + + if (bAssocSkip == TRUE) + { + pEntry = MacTableLookup(pAd, ie_list->Addr2); + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + + MlmeFreeMemory(pAd, (PVOID) pOutBuffer); + goto LabelOK; + } + + MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, + wdev->if_addr, wdev->bssid); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocRspHdr, + 2, &CapabilityInfoForAssocResp, + 2, &StatusCode, + 2, &Aid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B) && (FlgIs11bSta == 0)) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef DOT11R_FT_SUPPORT + if ((pFtCfg != NULL) && (pFtCfg->FtCapFlag.Dot11rFtEnable)) + { + PUINT8 mdie_ptr; + UINT8 mdie_len; + PUINT8 ftie_ptr = NULL; + UINT8 ftie_len = 0; + PUINT8 ricie_ptr = NULL; + UINT8 ricie_len = 0; + + /* Insert RSNIE if necessary */ + if (pFtInfoBuf->RSNIE_Len != 0) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + pFtInfoBuf->RSNIE_Len, pFtInfoBuf->RSN_IE, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Insert MDIE. */ + mdie_ptr = pOutBuffer+FrameLen; + mdie_len = 5; + FT_InsertMdIE(pAd, pOutBuffer+FrameLen, &FrameLen, + pFtInfoBuf->MdIeInfo.MdId, pFtInfoBuf->MdIeInfo.FtCapPlc); + + /* Insert FTIE. */ + if (pFtInfoBuf->FtIeInfo.Len != 0) + { + ftie_ptr = pOutBuffer+FrameLen; + ftie_len = (2 + pFtInfoBuf->FtIeInfo.Len); + FT_InsertFTIE(pAd, pOutBuffer+FrameLen, &FrameLen, + pFtInfoBuf->FtIeInfo.Len, pFtInfoBuf->FtIeInfo.MICCtr, + pFtInfoBuf->FtIeInfo.MIC, pFtInfoBuf->FtIeInfo.ANonce, + pFtInfoBuf->FtIeInfo.SNonce); + } + /* Insert R1KH IE into FTIE. */ + if (pFtInfoBuf->FtIeInfo.R1khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R1KH_ID, pFtInfoBuf->FtIeInfo.R1khId, + pFtInfoBuf->FtIeInfo.R1khIdLen); + + /* Insert GTK Key info into FTIE. */ + if (pFtInfoBuf->FtIeInfo.GtkLen!= 0) + FT_FTIE_InsertGTKSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + pFtInfoBuf->FtIeInfo.GtkSubIE, pFtInfoBuf->FtIeInfo.GtkLen); + + /* Insert R0KH IE into FTIE. */ + if (pFtInfoBuf->FtIeInfo.R0khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R0KH_ID, pFtInfoBuf->FtIeInfo.R0khId, + pFtInfoBuf->FtIeInfo.R0khIdLen); + + /* Insert RIC. */ + if (ie_list->FtInfo.RicInfo.Len) + { + ULONG TempLen; + + FT_RIC_ResourceRequestHandle(pAd, pEntry, + (PUCHAR)ie_list->FtInfo.RicInfo.pRicInfo, + ie_list->FtInfo.RicInfo.Len, + (PUCHAR)pOutBuffer+FrameLen, + (PUINT32)&TempLen); + ricie_ptr = (PUCHAR)(pOutBuffer+FrameLen); + ricie_len = TempLen; + FrameLen += TempLen; + } + + /* Calculate the FT MIC for FT procedure */ + if (pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt) + { + UINT8 ft_mic[FT_MIC_LEN]; + PFT_FTIE pFtIe; + + FT_CalculateMIC(pEntry->Addr, + wdev->bssid, + pEntry->PTK, + 6, + pFtInfoBuf->RSN_IE, + pFtInfoBuf->RSNIE_Len, + mdie_ptr, + mdie_len, + ftie_ptr, + ftie_len, + ricie_ptr, + ricie_len, + ft_mic); + + /* Update the MIC field of FTIE */ + pFtIe = (PFT_FTIE)(ftie_ptr + 2); + NdisMoveMemory(pFtIe->MIC, ft_mic, FT_MIC_LEN); + + /* Only first allow install from assoc, later or rekey or install from auth (backward compatability with not patched clients) */ + if(pEntry->AllowInsPTK == TRUE +#ifdef DOT11R_FT_SUPPORT + || !IS_FT_STA(pEntry) || (IS_FT_STA(pEntry) && (NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], zeroFT, LEN_TK) || !NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pEntry->LastTK, LEN_TK))) +#endif + ) { + WPAInstallPairwiseKey(pAd, pEntry->apidx, pEntry, TRUE); + NdisMoveMemory(pEntry->LastTK, &pEntry->PTK[OFFSET_OF_PTK_TK], LEN_TK); + pEntry->AllowInsPTK = FALSE; + } + + /* set Port as Secured */ + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + } + + /* Record the MDIE & FTIE of (re)association response of + Initial Mobility Domain Association. It's used in + FT 4-Way handshaking */ + if (pEntry->AuthMode >= Ndis802_11AuthModeWPA2 && + ie_list->FtInfo.FtIeInfo.Len == 0) + { + NdisMoveMemory(&pEntry->InitialMDIE, mdie_ptr, mdie_len); + + pEntry->InitialFTIE_Len = ftie_len; + NdisMoveMemory(pEntry->InitialFTIE, ftie_ptr, ftie_len); + } + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, pEntry->apidx)) + RRM_InsertRRMEnCapIE(pAd, pOutBuffer+FrameLen, &FrameLen, pEntry->apidx); +#endif /* DOT11K_RRM_SUPPORT */ + + /* add WMM IE here */ + if (wdev->bWmmCapable && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + { + ULONG TmpLen; + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + + WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; +#ifdef UAPSD_SUPPORT + UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); +#endif /* UAPSD_SUPPORT */ + for (i = QID_AC_BE; i <= QID_AC_VO; i++) + { + WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ + ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ + (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ + WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ + (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ + WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ + WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ + } + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 26, WmeParmIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef DOT11W_PMF_SUPPORT + if (StatusCode == MLME_ASSOC_REJ_TEMPORARILY) { + ULONG TmpLen; + UCHAR IEType = IE_TIMEOUT_INTERVAL; //IE:0x15 + UCHAR IELen = 5; + UCHAR TIType = 3; + UINT32 units = 1 << 10; //1 seconds, should be 0x3E8 + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &IEType, + 1, &IELen, + 1, &TIType, + 4, &units, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* HT capability in AssocRsp frame. */ + if ((ie_list->ht_cap_len > 0) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG TmpLen; + UCHAR HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); + HT_CAPABILITY_IE HtCapabilityRsp; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + + NdisMoveMemory(&HtCapabilityRsp, &pAd->CommonCfg.HtCapability, ie_list->ht_cap_len); + + /* add HT Capability IE */ +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &ie_list->ht_cap_len, + ie_list->ht_cap_len, &HtCapabilityRsp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &HtCapabilityRsp, ie_list->ht_cap_len); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &ie_list->ht_cap_len, + ie_list->ht_cap_len, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + + if ((ie_list->RalinkIe) == 0 || (pAd->bBroadComHT == TRUE)) + { + UCHAR epigram_ie_len; + UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; + UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; + + + epigram_ie_len = ie_list->ht_cap_len + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + ie_list->ht_cap_len, &HtCapabilityRsp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + ie_list->ht_cap_len, &HtCapabilityTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + epigram_ie_len = HtLen1 + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + } + +#ifdef DOT11N_DRAFT3 + /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + OVERLAP_BSS_SCAN_IE OverlapScanParam; + ULONG TmpLen; + UCHAR OverlapScanIE, ScanIELen; + + OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; + ScanIELen = 14; + OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); + OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); + OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); + OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); + OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); + OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &OverlapScanIE, + 1, &ScanIELen, + ScanIELen, &OverlapScanParam, + END_OF_ARGS); + + FrameLen += TmpLen; + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (ie_list->vht_cap_len)) + { + FrameLen += build_vht_ies(pAd, pOutBuffer + FrameLen, SUBTYPE_ASSOC_RSP); + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_HOTSPOT_R2 + /* qosmap IE */ + printk("entry=%d\n", pEntry->QosMapSupport); + if (pEntry->QosMapSupport) + { + ULONG TmpLen; + UCHAR QosMapIE, ielen = 0, i = 0, explen = 0; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pEntry->apidx].HotSpotCtrl; + + if (pHSCtrl->QosMapEnable) + { + QosMapIE = IE_QOS_MAP_SET; + + for (i=0;i<21;i++) + { + if (pHSCtrl->DscpException[i] == 0xffff) + break; + else + explen += 2; + } + + pEntry->DscpExceptionCount = explen; + memcpy((UCHAR *)pEntry->DscpRange, (UCHAR *)pHSCtrl->DscpRange, 16); + memcpy((UCHAR *)pEntry->DscpException, (UCHAR *)pHSCtrl->DscpException, 42); + + ielen = explen+16; + + MakeOutgoingFrame(pOutBuffer+ FrameLen, &TmpLen, + 1, &QosMapIE, + 1, &ielen, + explen, pEntry->DscpException, + 16, pEntry->DscpRange, + END_OF_ARGS); + + FrameLen += TmpLen; + } + } +#endif /* CONFIG_HOTSPOT_R2 */ + + + /* 7.3.2.27 Extended Capabilities IE */ + { + ULONG TmpLen, infoPos; + PUCHAR pInfo; + UCHAR extInfoLen; + BOOLEAN bNeedAppendExtIE = FALSE; + EXT_CAP_INFO_ELEMENT extCapInfo; + + + extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D1.10, HT Information Exchange Support */ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && (pAd->CommonCfg.Channel <= 14) + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, pEntry->apidx)) + { + if( ie_list->ExtCapInfo.BssTransitionManmt == 1) + { + extCapInfo.BssTransitionManmt = 1; + pEntry->bBSSMantSTASupport = TRUE; + } + } + if (IS_WNMDMS_SUPPORT(pAd, pEntry->apidx)) + { + if ( ie_list->ExtCapInfo.DMSSupport == 1) + { + extCapInfo.DMSSupport = 1; + pEntry->bDMSSTASupport = TRUE; + } + } +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + extCapInfo.operating_mode_notification = 1; +#endif /* DOT11_VHT_AC */ + + pInfo = (UCHAR *)(&extCapInfo); + for (infoPos = 0; infoPos < extInfoLen; infoPos++) + { + if (pInfo[infoPos] != 0) + { + bNeedAppendExtIE = TRUE; + break; + } + } + + if (bNeedAppendExtIE == TRUE) + { +#ifdef RT_BIG_ENDIAN + *((UINT32*)(pInfo)) = SWAP32(*((UINT32*)(pInfo))); + *((UINT32*)(pInfo+4)) = SWAP32(*((UINT32*)(pInfo+4))) +#endif + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + + /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ +{ + ULONG TmpLen; + UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; + + if (pAd->CommonCfg.bAggregationCapable) + RalinkSpecificIe[5] |= 0x1; + if (pAd->CommonCfg.bPiggyBackCapable) + RalinkSpecificIe[5] |= 0x2; +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.bRdg) + RalinkSpecificIe[5] |= 0x4; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.b256QAM_2G && WMODE_2G_ONLY(pAd->CommonCfg.PhyMode)) + RalinkSpecificIe[5] |= 0x8; +#endif /* DOT11_VHT_AC */ + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + +} +#ifdef SMART_MESH + SMART_MESH_INSERT_IE(pAd->ApCfg.MBSSID[pEntry->apidx].SmartMeshCfg, + pOutBuffer, + FrameLen, + SM_IE_ASSOC_RSP); +#endif /* SMART_MESH */ + + /* add Mediatek-specific IE here */ + { + ULONG TmpLen = 0; + UCHAR MediatekSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0xe7, 0x00, 0x00, 0x00, 0x00}; + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.b256QAM_2G && WMODE_2G_ONLY(pAd->CommonCfg.PhyMode)) + MediatekSpecificIe[5] |= 0x8; +#endif /* DOT11_VHT_AC */ + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, MediatekSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef WSC_AP_SUPPORT + if (pEntry->bWscCapable) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + BOOLEAN bHasWscIe = TRUE; + +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.MBSSID[pEntry->apidx].SmartMeshCfg.bSupportHiddenWPS) + bHasWscIe = FALSE; +#endif /* SMART_MESH_HIDDEN_WPS */ + if(bHasWscIe) + { + os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); + if(pWscBuf) + { + NdisZeroMemory(pWscBuf, 512); + WscBuildAssocRespIE(pAd, pEntry->apidx, 0, pWscBuf, &WscIeLen); + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + } + } +#endif /* WSC_AP_SUPPORT */ + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, (PVOID) pOutBuffer); + +#ifdef DOT11W_PMF_SUPPORT + if (StatusCode == MLME_ASSOC_REJ_TEMPORARILY) + { + PMF_MlmeSAQueryReq(pAd, pEntry); + } +#endif /* DOT11W_PMF_SUPPORT */ + + /* set up BA session */ + if (StatusCode == MLME_SUCCESS) + { + pEntry->PsMode = PWR_ACTIVE; + + wdev->allow_data_tx = TRUE; + +#ifdef IAPP_SUPPORT + /*PFRAME_802_11 Fr = (PFRAME_802_11)Elem->Msg; */ +/* POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; */ + + /* send association ok message to IAPPD */ + IAPP_L2_Update_Frame_Send(pAd, pEntry->Addr, pEntry->apidx); + DBGPRINT(RT_DEBUG_TRACE, ("####### Send L2 Frame Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + +/* SendSingalToDaemon(SIGUSR2, pObj->IappPid); */ + +#ifdef DOT11R_FT_SUPPORT + /* + Do not do any check here. + We need to send MOVE-Req frame to AP1 even open mode. + */ +/* if (IS_FT_RSN_STA(pEntry) && (FtInfo.FtIeInfo.Len != 0)) */ + if (isReassoc == 1) + { + /* only for reassociation frame */ + FT_KDP_EVT_REASSOC EvtReAssoc; + + EvtReAssoc.SeqNum = 0; + NdisMoveMemory(EvtReAssoc.MacAddr, pEntry->Addr, MAC_ADDR_LEN); + NdisMoveMemory(EvtReAssoc.OldApMacAddr, ie_list->ApAddr, MAC_ADDR_LEN); + + FT_KDP_EVENT_INFORM(pAd, pEntry->apidx, FT_KDP_SIG_FT_REASSOCIATION, + &EvtReAssoc, sizeof(EvtReAssoc), NULL); + } +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* IAPP_SUPPORT */ + + ap_assoc_info_debugshow(pAd, isReassoc, pEntry, ie_list); + +#ifdef MWDS + if((pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + MWDSProxyEntryDelete(pAd,pEntry->Addr); +#ifdef WSC_AP_SUPPORT + BOOLEAN bWPSRunning = FALSE; + if (((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.bWscTrigger == TRUE))) + bWPSRunning = TRUE; +#ifdef SMART_MESH_HIDDEN_WPS + if (pAd->ApCfg.MBSSID[pEntry->apidx].SmartMeshCfg.bSupportHiddenWPS && pEntry->bRunningHiddenWPS) + bWPSRunning = TRUE; +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + if( + pEntry->bEnableMWDS +#ifdef WSC_AP_SUPPORT + && !bWPSRunning +#endif /* WSC_AP_SUPPORT */ + ) + { + SET_MWDS_OPMODE_AP(pEntry); + MWDSConnEntryUpdate(pAd,pEntry->wcid); + DBGPRINT(RT_DEBUG_ERROR, ("SET_MWDS_OPMODE_AP OK!\n")); + } + else + SET_MWDS_OPMODE_NONE(pEntry); + } +#endif /* MWDS */ + + /* send wireless event - for association */ + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pEntry->Addr, 0, 0); + +#ifdef SMART_MESH_MONITOR + if (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.join.type = NSMPIF_DRVEVNT_STA_JOIN; + drvevnt.data.join.channel = pAd->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.join.sta_mac, pEntry->Addr, MAC_ADDR_LEN); + drvevnt.data.join.aid= pEntry->Aid; + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_JOIN, + NULL, (PUCHAR)&drvevnt.data.join, sizeof(drvevnt.data.join)); + } +#endif /* SMART_MESH_MONITOR */ + + /* This is a reassociation procedure */ + pEntry->IsReassocSta = isReassoc; + +#ifdef DOT11_N_SUPPORT + /* clear txBA bitmap */ + pEntry->TXBAbitmap = 0; + if (pEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + if ((pAd->CommonCfg.Channel <=14) && + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset && + (ie_list->HTCapability.HtCapInfo.ChannelWidth==BW_40)) + { + SendBeaconRequest(pAd, pEntry->wcid); + } + /*BAOriSessionSetUp(pAd, pEntry, 0, 0, 3000, FALSE); */ + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11R_FT_SUPPORT + /* If the length of FTIE field of the (re)association-request frame + is larger than zero, it shall indicate the Fast-BSS transition is in progress. */ + if (ie_list->FtInfo.FtIeInfo.Len > 0) + { + ; + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef RT_CFG80211_SUPPORT + if (TRUE) /*CFG_TODO*/ + { + hex_dump("ASSOC_REQ", Elem->Msg, Elem->MsgLen); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + PNET_DEV pNetDev = NULL; + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_GO)) != NULL)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CONCURRENT_DEVICE CFG : GO NOITFY THE CLIENT ASSOCIATED\n")); + CFG80211OS_NewSta(pNetDev, ie_list->Addr2, (PUCHAR)Elem->Msg, Elem->MsgLen); + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + { + DBGPRINT(RT_DEBUG_TRACE, ("SINGLE_DEVICE CFG : GO NOITFY THE CLIENT ASSOCIATED\n")); + CFG80211OS_NewSta(pAd->net_dev, ie_list->Addr2, (PUCHAR)Elem->Msg, Elem->MsgLen); + if (pEntry->WepStatus == Ndis802_11WEPEnabled) + { + /* Set WEP key to ASIC */ + UCHAR KeyIdx = 0; + UCHAR CipherAlg = 0; + + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[pEntry->func_tb_idx][KeyIdx].CipherAlg; + + /* + If WEP is used, set pair-wise cipherAlg into WCID + attribute table for this entry. + */ + RTMP_SET_WCID_SEC_INFO(pAd, + pEntry->func_tb_idx, + KeyIdx, + CipherAlg, + pEntry->wcid, + SHAREDKEYTABLE); + } + } + } + else +#endif /* RT_CFG80211_SUPPORT */ + /* enqueue a EAPOL_START message to trigger EAP state machine doing the authentication */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { +#ifdef WSC_AP_SUPPORT + /* + In WPA-PSK mode, + If Association Request of station has RSN/SSN, WPS AP Must Not send EAP-Request/Identity to station + no matter WPS AP does receive EAPoL-Start from STA or not. + Marvell WPS test bed(v2.1.1.5) will send AssocReq with WPS IE and RSN/SSN IE. + */ + if (pEntry->bWscCapable || (ie_list->RSNIE_Len == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - IF(ra%d) This is a WPS Client.\n\n", pEntry->apidx)); + goto LabelOK; + } + else + { + pEntry->bWscCapable = FALSE; + pEntry->Receive_EapolStart_EapRspId = (WSC_ENTRY_GET_EAPOL_START | WSC_ENTRY_GET_EAP_RSP_ID); + /* This STA is not a WPS STA */ + NdisZeroMemory(wsc_ctrl->EntryAddr, 6); + } +#endif /* WSC_AP_SUPPORT */ + + /* Enqueue a EAPOL-start message with the pEntry for WPAPSK State Machine */ + if ((pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && wdev->Hostapd == Hostapd_Diable +#endif/*HOSTAPD_SUPPORT*/ + ) +#ifdef WSC_AP_SUPPORT + && !pEntry->bWscCapable +#endif /* WSC_AP_SUPPORT */ + ) + { + /* Enqueue a EAPOL-start message with the pEntry */ + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + } +#ifdef DOT1X_SUPPORT + /*else if (isReassoc && */ + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && + ((pPmkid = WPA_ExtractSuiteFromRSNIE(ie_list->RSN_IE, ie_list->RSNIE_Len, PMKID_LIST, &pmkid_count)) != NULL)) + { /* Key cache */ + INT CacheIdx; + + if (((CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->apidx, pEntry->Addr)) != -1) + && (RTMPEqualMemory(pPmkid, &pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMKID, LEN_PMKID))) + { + /* Enqueue a EAPOL-start message with the pEntry for WPAPSK State Machine */ + if ((pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && wdev->Hostapd == Hostapd_Diable +#endif /*HOSTAPD_SUPPORT*/ + ) +#ifdef WSC_AP_SUPPORT + && !pEntry->bWscCapable +#endif /* WSC_AP_SUPPORT */ + ) + { + /* Enqueue a EAPOL-start message with the pEntry */ + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + + pEntry->PMKID_CacheIdx = CacheIdx; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOC - 2.PMKID matched and start key cache algorithm\n")); + } + else + { + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOC - 2.PMKID not found \n")); + } + } + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + ((wdev->IEEE8021X) +#ifdef WSC_AP_SUPPORT + && (!pEntry->bWscCapable) +#endif /* WSC_AP_SUPPORT */ + ) + ) + { + /* Enqueue a EAPOL-start message to trigger EAP SM */ + if (pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && wdev->Hostapd == Hostapd_Diable +#endif/*HOSTAPD_SUPPORT*/ + ) + { + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_1X; + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + } +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if (pEntry->AuthMode == Ndis802_11AuthModeWAICERT) + { + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->apidx, + pEntry->Addr, + WAI_MLME_CERT_AUTH_START); + + RTMPInitWapiRekeyTimerAction(pAd, pEntry); + } + else if (pEntry->AuthMode == Ndis802_11AuthModeWAIPSK) + { + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->apidx, + pEntry->Addr, + WAI_MLME_KEY_HS_START); + RTMPInitWapiRekeyTimerAction(pAd, pEntry); + } +#endif /* WAPI_SUPPORT */ + else + { + if (pEntry->WepStatus == Ndis802_11WEPEnabled) + { + /* Set WEP key to ASIC */ + UCHAR KeyIdx = 0; + UCHAR CipherAlg = 0; + + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[pEntry->apidx][KeyIdx].CipherAlg; + + /* + If WEP is used, set pair-wise cipherAlg into WCID + attribute table for this entry. + */ + RTMP_SET_WCID_SEC_INFO(pAd, + pEntry->apidx, + KeyIdx, + CipherAlg, + pEntry->wcid, + SHAREDKEYTABLE); + } + } + + } + +#ifdef DELAYED_TCP_ACK + RTMPInitTimer(pAd, &pEntry->QueueAckTimer, GET_TIMER_FUNCTION(RTMPQueueAckPeriodicExec), pEntry, FALSE); + pEntry->QueueAckTimerRunning = FALSE; + skb_queue_head_init(&pEntry->ack_queue); +#endif /* DELAYED_TCP_ACK */ + +LabelOK: +#ifdef RT_CFG80211_P2P_SUPPORT + if (StatusCode != MLME_SUCCESS) + CFG80211_ApStaDelSendEvent(pAd, pEntry->Addr); +#endif /* RT_CFG80211_P2P_SUPPORT */ + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + +#ifdef DOT11R_FT_SUPPORT + if (pFtInfoBuf != NULL) + os_free_mem(NULL, pFtInfoBuf); +#endif /* DOT11R_FT_SUPPORT */ + + return; +} + + + +/* + ========================================================================== + Description: + peer assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored + Post : + -# An association response frame is generated and sent to the air + ========================================================================== + */ +VOID APPeerAssocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + ap_cmm_peer_assoc_req_action(pAd, Elem, 0); +} + +/* + ========================================================================== + Description: + mlme reassoc req handling procedure + Parameters: + Elem - + Pre: + -# SSID (Adapter->ApCfg.ssid[]) + -# BSSID (AP address, Adapter->ApCfg.bssid) + -# Supported rates (Adapter->ApCfg.supported_rates[]) + -# Supported rates length (Adapter->ApCfg.supported_rates_len) + -# Tx power (Adapter->ApCfg.tx_power) + ========================================================================== + */ +VOID APPeerReassocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + ap_cmm_peer_assoc_req_action(pAd, Elem, 1); +} + +/* + ========================================================================== + Description: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + ========================================================================== + */ +VOID APPeerDisassocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + UINT16 SeqNum; + MAC_TABLE_ENTRY *pEntry; + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - 1 receive DIS-ASSOC request \n")); + if (! PeerDisassocReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, Addr2, &SeqNum, &Reason)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive DIS-ASSOC(seq-%d) request from %02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n", + SeqNum, PRINT_MAC(Addr2), Reason)); + + pEntry = MacTableLookup(pAd, Addr2); + if (pEntry == NULL) + return; + + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) + { + + wdev = &pAd->ApCfg.MBSSID[pEntry->apidx].wdev; + /* + iPhone sometimes sends disassoc frame which DA is old AP and BSSID is new AP. + @2016/1/26 + */ + if (!MAC_ADDR_EQUAL(wdev->if_addr, Addr1)) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - The DA of this DIS-ASSOC request is %02x:%02x:%02x:%02x:%02x:%02x, ignore.\n", + PRINT_MAC(Addr1))); + return; + } + +#ifdef DOT1X_SUPPORT + /* Notify 802.1x daemon to clear this sta info */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || + pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + 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 disassociation */ + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, Addr2, 0, 0); + ApLogEvent(pAd, Addr2, EVENT_DISASSOCIATED); + + MacTableDeleteEntry(pAd, Elem->Wcid, Addr2); + +#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 */ + } +} + + +/* + ========================================================================== + Description: + delete it from STA and disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID MbssKickOutStas(RTMP_ADAPTER *pAd, INT apidx, USHORT Reason) +{ + INT i; + PMAC_TABLE_ENTRY pEntry; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) && pEntry->apidx == apidx) + APMlmeKickOutSta(pAd, pEntry->Addr, pEntry->wcid, Reason); + } + + return; +} + + +/* + ========================================================================== + Description: + delete it from STA and disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID APMlmeKickOutSta(RTMP_ADAPTER *pAd, UCHAR *pStaAddr, UCHAR Wcid, USHORT Reason) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + MAC_TABLE_ENTRY *pEntry; + UCHAR Aid; + UCHAR ApIdx; + + pEntry = MacTableLookup(pAd, pStaAddr); + + if (pEntry == NULL) + { + return; + } + Aid = pEntry->Aid; + ApIdx = pEntry->apidx; + + ASSERT(Aid == Wcid); + + if (ApIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Apidx=%d\n", + __FUNCTION__, ApIdx)); + return; + } + + if (Aid < MAX_LEN_OF_MAC_TABLE) + { + /* send wireless event - for disassocation */ + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pStaAddr, 0, 0); + ApLogEvent(pAd, pStaAddr, EVENT_DISASSOCIATED); + + /* 2. send out a DISASSOC request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MLME disassociates %02x:%02x:%02x:%02x:%02x:%02x; Send DISASSOC request\n", + PRINT_MAC(pStaAddr))); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pStaAddr, + pAd->ApCfg.MBSSID[ApIdx].wdev.if_addr, + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + MacTableDeleteEntry(pAd, Aid, pStaAddr); + } +} + + +#ifdef DOT11W_PMF_SUPPORT +VOID APMlmeKickOutAllSta(RTMP_ADAPTER *pAd, UCHAR apidx, USHORT Reason) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + PPMF_CFG pPmfCfg = NULL; + + pPmfCfg = &pAd->ApCfg.MBSSID[apidx].PmfCfg; + if ((apidx < pAd->ApCfg.BssidNum) && (pPmfCfg)) + { + /* Send out a Deauthentication request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + DBGPRINT(RT_DEBUG_ERROR, ("Send DISASSOC Broadcast frame(%d) with ra%d \n", Reason, apidx)); + + /* 802.11 Header */ + NdisZeroMemory(&DisassocHdr, sizeof(HEADER_802_11)); + DisassocHdr.FC.Type = FC_TYPE_MGMT; + DisassocHdr.FC.SubType = SUBTYPE_DISASSOC; + DisassocHdr.FC.ToDs = 0; + DisassocHdr.FC.Wep = 0; + COPY_MAC_ADDR(DisassocHdr.Addr1, BROADCAST_ADDR); + COPY_MAC_ADDR(DisassocHdr.Addr2, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + COPY_MAC_ADDR(DisassocHdr.Addr3, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + + if (pPmfCfg->MFPC == TRUE) + { + ULONG TmpLen; + UCHAR res_buf[LEN_PMF_MMIE]; + USHORT EID, ELen; + + EID = IE_PMF_MMIE; + ELen = LEN_PMF_MMIE; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &EID, + 1, &ELen, + LEN_PMF_MMIE, res_buf, + END_OF_ARGS); + FrameLen += TmpLen; + DBGPRINT(RT_DEBUG_WARN, ("[PMF]: This is a Broadcast Robust management frame, Add 0x4C(76) EID\n")); + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } +} +#endif /* DOT11W_PMF_PLUGFEST */ + + +/* + ========================================================================== + Description: + Upper layer orders to disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID APMlmeDisassocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_DISASSOC_REQ_STRUCT *DisassocReq = (MLME_DISASSOC_REQ_STRUCT *)(Elem->Msg); + + APMlmeKickOutSta(pAd, DisassocReq->Addr, Elem->Wcid, DisassocReq->Reason); +} + + +/* + ========================================================================== + Description: + right part of IEEE 802.11/1999 page 374 + Note: + This event should never cause ASSOC state machine perform state + transition, and has no relationship with CNTL machine. So we separate + this routine as a service outside of ASSOC state transition table. + ========================================================================== + */ +VOID APCls3errAction(RTMP_ADAPTER *pAd, ULONG Wcid, HEADER_802_11 *pHeader) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + USHORT Reason = REASON_CLS3ERR; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &(pAd->MacTab.Content[Wcid]); + + if (pEntry) + { + /*ApLogEvent(pAd, pAddr, EVENT_DISASSOCIATED); */ + MacTableDeleteEntry(pAd, pEntry->wcid, pHeader->Addr2); + } + + /* 2. send out a DISASSOC request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pHeader->Addr2))); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pHeader->Addr2, + pHeader->Addr1, + pHeader->Addr1); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + + AP_ASSOC_IDLE + APMT2_MLME_DISASSOC_REQ mlme_disassoc_req_action + APMT2_PEER_DISASSOC_REQ peer_disassoc_action + APMT2_PEER_ASSOC_REQ drop + APMT2_PEER_REASSOC_REQ drop + APMT2_CLS3ERR cls3err_action + ========================================================================== + */ +VOID APAssocStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ +#ifdef CUSTOMER_DCC_FEATURE + pAd->ApDisableSTAConnectFlag = FALSE; + pAd->AllowedStaList.StaCount = 0; +#endif + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, AP_MAX_ASSOC_STATE, AP_MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, AP_ASSOC_IDLE, AP_ASSOC_MACHINE_BASE); + + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)APMlmeDisassocReqAction); + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)APPeerDisassocReqAction); + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_PEER_ASSOC_REQ, (STATE_MACHINE_FUNC)APPeerAssocReqAction); + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_PEER_REASSOC_REQ, (STATE_MACHINE_FUNC)APPeerReassocReqAction); +/* StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_CLS3ERR, APCls3errAction); */ +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_auth.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_auth.c new file mode 100644 index 000000000..b5f510a49 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_auth.c @@ -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; iApMlmeAux.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); +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_autoChSel.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_autoChSel.c new file mode 100644 index 000000000..fb2ea867a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_autoChSel.c @@ -0,0 +1,1345 @@ +/**************************************************************************** + * 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: + + Abstract: +*/ + + +#include "rt_config.h" +#include "ap_autoChSel.h" + + +extern UCHAR ZeroSsid[32]; + +static inline INT GetABandChOffset( + IN PRTMP_ADAPTER pAd, + IN INT Channel) +{ +#ifdef A_BAND_SUPPORT + UCHAR region = GetCountryRegionFromCountryCode(pAd); + if((region==CE || region==JAP) && Channel >= 140) + return 0; + if(region==FCC && Channel >= 116 && Channel <= 128) + return 0; + if ((Channel == 36) || (Channel == 44) + || (Channel == 52) || (Channel == 60) + || (Channel == 100) || (Channel == 108) + || (Channel == 116) || (Channel == 124) + || (Channel == 132) || (Channel == 149) + || (Channel == 157)) + { + return 1; + } + else if ((Channel == 40) || (Channel == 48) + || (Channel == 56) || (Channel == 64) + || (Channel == 104) || (Channel == 112) + || (Channel == 120) || (Channel == 128) + || (Channel == 136) || (Channel == 153) + || (Channel == 161)) + { + return -1; + } +#endif /* A_BAND_SUPPORT */ + return 0; +} + +ULONG AutoChBssSearchWithSSID( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + PBSSINFO pBssInfoTab = pAd->pBssInfoTab; + + if(pBssInfoTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pBssInfoTab equal NULL.\n")); + return (ULONG)BSS_NOT_FOUND; + } + + for (i = 0; i < pBssInfoTab->BssNr; i++) + { + if ((((pBssInfoTab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((pBssInfoTab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(&(pBssInfoTab->BssEntry[i].Bssid), Bssid) && + (SSID_EQUAL(pSsid, SsidLen, pBssInfoTab->BssEntry[i].Ssid, pBssInfoTab->BssEntry[i].SsidLen) || + (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || + (NdisEqualMemory(pBssInfoTab->BssEntry[i].Ssid, ZeroSsid, pBssInfoTab->BssEntry[i].SsidLen)))) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +static inline VOID AutoChBssEntrySet( + OUT BSSENTRY *pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR Channel, + IN UCHAR ExtChOffset, + IN CHAR Rssi) +{ + COPY_MAC_ADDR(pBss->Bssid, pBssid); + if (SsidLen > 0) + { + /* + For hidden SSID AP, it might send beacon with SSID len equal to 0, + Or send beacon /probe response with SSID len matching real SSID length, + but SSID is all zero. such as "00-00-00-00" with length 4. + We have to prevent this case overwrite correct table + */ + if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) + { + NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); + pBss->SsidLen = SsidLen; + } + } + + pBss->Channel = Channel; + pBss->ExtChOffset = ExtChOffset; + pBss->Rssi = Rssi; + + return; +} + +static inline VOID AutoChBssTableReset( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pBssInfoTab) + NdisZeroMemory(pAd->pBssInfoTab, sizeof(BSSINFO)); + else + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pBssInfoTab equal NULL.\n")); + + return; +} + +static VOID ChannelInfoReset( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pChannelInfo) + NdisZeroMemory(pAd->pChannelInfo, sizeof(CHANNELINFO)); + else + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); + + return; +} + +#ifdef CUSTOMER_DCC_FEATURE +VOID ChannelInfoResetNew( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->ChannelInfo, sizeof(CHANNELINFO)); + pAd->ApCfg.current_channel_index = 0; + return; +} +#endif +VOID UpdateChannelInfo( + IN PRTMP_ADAPTER pAd, + IN int ch_index, + IN ChannelSel_Alg Alg) +{ + if(pAd->pChannelInfo != NULL) + { + UINT32 BusyTime; + +#ifndef CUSTOMER_DCC_FEATURE + if ( Alg == ChannelAlgCCA ) +#endif + { + RX_STA_CNT1_STRUC RxStaCnt1; + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + pAd->pChannelInfo->FalseCCA[ch_index] = RxStaCnt1.field.FalseCca; +#ifdef SMART_MESH + pAd->ChannelList[pAd->ApCfg.scan_channel_index].FalseCCA = RxStaCnt1.field.FalseCca; +#endif /* SMART_MESH */ +#ifdef CUSTOMER_DCC_FEATURE + pAd->ChannelInfo.FalseCCA[ch_index] = RxStaCnt1.field.FalseCca; + if(pAd->ChannelInfo.GetChannelInfo == 0) + pAd->ChannelInfo.GetChannelInfo++; +#endif + } + + + /* + do busy time statistics for primary channel + scan time 400ms, beacon interval 100 ms + */ + + RTMP_IO_READ32(pAd, CH_BUSY_STA, &BusyTime); +#ifdef AP_QLOAD_SUPPORT + pAd->pChannelInfo->chanbusytime[ch_index] = (BusyTime * 100) / AUTO_CHANNEL_SEL_TIMEOUT; +#endif /* AP_QLOAD_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + pAd->ChannelInfo.chanbusytime[ch_index] = BusyTime; +#endif + } + else + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); + + return; +} + +static inline INT GetChIdx( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + INT Idx; + + Idx = -1; + for (Idx = 0; Idx < pAd->ChannelListNum; Idx++) + { + if (Channel == pAd->ChannelList[Idx].Channel) + break; + } + + return Idx; +} + +static inline VOID AutoChannelSkipListSetDirty( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + for (i=0; i < pAd->ApCfg.AutoChannelSkipListNum ; i++) + { + UCHAR channel_idx = GetChIdx(pAd, pAd->ApCfg.AutoChannelSkipList[i]); + if ( channel_idx != pAd->ChannelListNum ) + { + pAd->pChannelInfo->SkipList[channel_idx] = TRUE; + } + } +} + +static inline BOOLEAN AutoChannelSkipListCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch) +{ + UCHAR i; + BOOLEAN result = FALSE; + + for (i=0; i < pAd->ApCfg.AutoChannelSkipListNum ; i++) + { + if (Ch == pAd->ApCfg.AutoChannelSkipList[i]) + { + result = TRUE; + break; + } + } + return result; +} + +static inline BOOLEAN BW40_ChannelCheck( + IN UCHAR ch) +{ + INT i; + BOOLEAN result = TRUE; + UCHAR NorBW40_CH[] = {140, 165}; + UCHAR NorBW40ChNum = sizeof(NorBW40_CH) / sizeof(UCHAR); + + for (i=0; iCommonCfg.bIEEE80211H) + { + cnt = 0; + + /* Filter out an available channel list */ + for (i = 0; i < pAd->ChannelListNum; i++) + { + /* Check DFS channel RemainingTimeForUse */ + if (pAd->ChannelList[i].RemainingTimeForUse) + continue; + + /* Check skip channel list */ + if (AutoChannelSkipListCheck(pAd, pAd->ChannelList[i].Channel) == TRUE) + continue; + +#ifdef DOT11_N_SUPPORT + /* Check N-group of BW40 */ + if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 +#ifdef DOT11_VHT_AC + &&(pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) && + !(pAd->ChannelList[i].Flags & CHANNEL_40M_CAP)) + continue; + +#ifdef DOT11_VHT_AC + /* Check VHT-group of BW80 */ + if (pAd->CommonCfg.vht_bw == VHT_BW_80 && + !(pAd->ChannelList[i].Flags & CHANNEL_80M_CAP) && + !AC_ChannelGroupCheck(pAd, pAd->ChannelList[i].Channel)) + continue; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + /* Store available channel to temp list */ + TempChList[cnt++] = pAd->ChannelList[i].Channel; + } + + /* Randomly select a channel from temp list */ + if (cnt) + { + RadomIdx = RandomByte2(pAd)%cnt; + ch = TempChList[RadomIdx]; + } + else + { + ch = get_channel_by_reference(pAd, 1); + } + + } + else + { + ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; + if (ch == 0) + ch = FirstChannel(pAd); + } + printk("%s(): Select Channel %d\n", __FUNCTION__, ch); + return ch; + +} + +/* + ========================================================================== + Description: + This routine calaulates the dirtyness of all channels by the + CCA value and Rssi. Store dirtyness to pChannelInfo strcut. + This routine is called at iwpriv cmmand or initialization. It chooses and returns + a good channel whith less interference. + Return: + ch - channel number that + NOTE: + ========================================================================== + */ +static inline UCHAR SelectClearChannelCCA( + IN PRTMP_ADAPTER pAd + ) +{ + #define CCA_THRESHOLD (100) + + PBSSINFO pBssInfoTab = pAd->pBssInfoTab; + PCHANNELINFO pChannelInfo = pAd->pChannelInfo; + INT ch = 1, channel_idx, BssTab_idx; + BSSENTRY *pBss; + UINT32 min_dirty, min_falsecca; + int candidate_ch; + UCHAR ExChannel[2] = {0}, candidate_ExChannel[2] = {0}; + UCHAR base; + + if(pBssInfoTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pBssInfoTab equal NULL.\n")); + return (FirstChannel(pAd)); + } + + if(pChannelInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); + return (FirstChannel(pAd)); + } + + for (BssTab_idx = 0; BssTab_idx < pBssInfoTab->BssNr; BssTab_idx++) + { + pBss = &(pBssInfoTab->BssEntry[BssTab_idx]); + channel_idx = GetChIdx(pAd, pBss->Channel); + if (channel_idx < 0 ) + continue; + + + if (pBss->Rssi >= -50) + { + /* high signal >= -50 dbm */ + pChannelInfo->dirtyness[channel_idx] += 50; + } + else if (pBss->Rssi <= -80) + { + /* low signal <= -80 dbm */ + pChannelInfo->dirtyness[channel_idx] += 30; + } + else + { + /* mid signal -50 ~ -80 dbm */ + pChannelInfo->dirtyness[channel_idx] += 40; + } + + pChannelInfo->dirtyness[channel_idx] += 40; + + { + INT BelowBound; + INT AboveBound; + INT loop; + + switch(pBss->ExtChOffset) + { + case EXTCHA_ABOVE: + BelowBound = pChannelInfo->IsABand ? 1 : 4; + AboveBound = pChannelInfo->IsABand ? 2 : 8; + break; + + case EXTCHA_BELOW: + BelowBound = pChannelInfo->IsABand ? 2 : 8; + AboveBound = pChannelInfo->IsABand ? 1 : 4; + break; + + default: + BelowBound = pChannelInfo->IsABand ? 1 : 4; + AboveBound = pChannelInfo->IsABand ? 1 : 4; + break; + } + + /* check neighbor channel */ + for (loop = (channel_idx+1); loop <= (channel_idx+AboveBound); loop++) + { + if (loop >= MAX_NUM_OF_CHANNELS) + break; + + if (pAd->ChannelList[loop].Channel - pAd->ChannelList[loop-1].Channel > 4) + break; + + pChannelInfo->dirtyness[loop] += ((9 - (loop - channel_idx)) * 4); + } + + /* check neighbor channel */ + for (loop=(channel_idx-1); loop >= (channel_idx-BelowBound); loop--) + { + if (loop < 0) + break; + + if (pAd->ChannelList[loop+1].Channel - pAd->ChannelList[loop].Channel > 4) + continue; + + pChannelInfo->dirtyness[loop] += + ((9 - (channel_idx - loop)) * 4); + } + } + + printk(" ch%d bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]); + } + + AutoChannelSkipListSetDirty(pAd); + + printk("=====================================================\n"); + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) + { + printk("Channel %d : Dirty = %ld, False CCA = %u, Busy Time = %u, Skip Channel = %s\n", + pAd->ChannelList[channel_idx].Channel, + pChannelInfo->dirtyness[channel_idx], + pChannelInfo->FalseCCA[channel_idx], +#ifdef AP_QLOAD_SUPPORT + pChannelInfo->chanbusytime[channel_idx], +#else + 0, +#endif /* AP_QLOAD_SUPPORT */ + (pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE"); + } + printk("=====================================================\n"); + + min_dirty = min_falsecca = 0xFFFFFFFF; + + /* + * Rule 1. Pick up a good channel that False_CCA =< CCA_THRESHOLD + * by dirtyness + */ + candidate_ch = -1; + + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) + { + if (pChannelInfo->SkipList[channel_idx] == TRUE) + continue; + + if (pChannelInfo->FalseCCA[channel_idx] <= CCA_THRESHOLD) + { + UINT32 dirtyness = pChannelInfo->dirtyness[channel_idx]; + ch = pAd->ChannelList[channel_idx].Channel; + +#ifdef AP_QLOAD_SUPPORT + /* QLOAD ALARM */ + /* when busy time of a channel > threshold, skip it */ + /* TODO: Use weight for different references to do channel selection */ + if (QBSS_LoadIsBusyTimeAccepted(pAd, + pChannelInfo->chanbusytime[channel_idx]) == FALSE) + { + /* check next one */ + continue; + } +#endif /* AP_QLOAD_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* + User require 40MHz Bandwidth. + In the case, ignor all channel + doesn't support 40MHz Bandwidth. + */ + if (((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + && (pChannelInfo->IsABand && (GetABandChOffset(pAd,ch) == 0))) { + continue; + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (!AC_ChannelGroupCheck(pAd, ch)) { + /* not in the BW_80 channel group */ + continue; + } + } +#endif /* DOT11_VHT_AC */ + + /* + Need to Consider the dirtyness of extending channel + in 40 MHz bandwidth channel. + */ + if (pAd->pChannelInfo->IsABand) + { + /* 5G Hz */ + if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + { + if (((channel_idx + GetABandChOffset(pAd,ch)) >=0) + && ((channel_idx + GetABandChOffset(pAd,ch)) < pAd->ChannelListNum)) + { + INT ChOffsetIdx = channel_idx + GetABandChOffset(pAd,ch); + + if (pChannelInfo->FalseCCA[ChOffsetIdx] > CCA_THRESHOLD) + continue; + + dirtyness += pChannelInfo->dirtyness[ChOffsetIdx]; + } + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + /* the same dirtyness with neighbor */ + INT vht_ch_idx = get_vht_neighbor_index(ch); + + if ((pChannelInfo->FalseCCA[vht_ch_idx+channel_idx] > CCA_THRESHOLD) || + (pChannelInfo->FalseCCA[vht_ch_idx+(channel_idx+1)] > CCA_THRESHOLD) || + (pChannelInfo->FalseCCA[vht_ch_idx+(channel_idx+2)] > CCA_THRESHOLD) || + (pChannelInfo->FalseCCA[vht_ch_idx+(channel_idx+3)] > CCA_THRESHOLD)) + continue; + + if (vht_ch_idx != (MAX_NUM_OF_CHANNELS+1)) + { + dirtyness = pChannelInfo->dirtyness[vht_ch_idx+channel_idx] + + pChannelInfo->dirtyness[vht_ch_idx+(channel_idx+1)] + + pChannelInfo->dirtyness[vht_ch_idx+(channel_idx+2)] + + pChannelInfo->dirtyness[vht_ch_idx+(channel_idx+3)]; + } + } +#endif /* DOT11_VHT_AC */ + } + else + { /* 2.4G Hz */ + UCHAR ExChannel_idx = 0; + if (pAd->ChannelList[channel_idx].Channel == 14) + { + dirtyness = 0xFFFFFFFF; + break; + } + else + { + NdisZeroMemory(ExChannel, sizeof(ExChannel)); + if (((channel_idx - 4) >=0) && ((channel_idx - 4) < pAd->ChannelListNum)) + { + dirtyness += pChannelInfo->dirtyness[channel_idx - 4]; + ExChannel[ExChannel_idx++] = pAd->ChannelList[channel_idx - 4].Channel; + } + + if (((channel_idx + 4) >=0) && ((channel_idx + 4) < pAd->ChannelListNum)) + { + dirtyness += pChannelInfo->dirtyness[channel_idx + 4]; + ExChannel[ExChannel_idx++] = pAd->ChannelList[channel_idx + 4].Channel; + } + } + } +#endif /* DOT11_N_SUPPORT */ + + if ((min_dirty > dirtyness)) + { + min_dirty = dirtyness; + candidate_ch = channel_idx; + NdisMoveMemory(candidate_ExChannel, ExChannel, 2); + } + } + } + + if (candidate_ch >= 0) + { + ch = pAd->ChannelList[candidate_ch].Channel; + printk("Rule 1 CCA value : Min Dirtiness (Include extension channel) ==> Select Channel %d \n", ch); + printk("Min Dirty = %u\n", min_dirty); + printk("ExChannel = %d , %d\n", candidate_ExChannel[0], candidate_ExChannel[1]); + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20) + printk("BW = %s\n", "20"); + else if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + printk("BW = %s\n", "40"); + else + printk("BW = %s\n", "80"); + return ch; + } + + /* + * Rule 2. Pick up a good channel that False_CCA > CCA_THRESHOLD + * by FalseCCA (FalseCCA + Dirtyness) + */ + candidate_ch = -1; + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) + { + if (pChannelInfo->SkipList[channel_idx] == TRUE) + continue; + + if (pChannelInfo->FalseCCA[channel_idx] > CCA_THRESHOLD) + { + UINT32 falsecca = pChannelInfo->FalseCCA[channel_idx] + pChannelInfo->dirtyness[channel_idx]; + ch = pAd->ChannelList[channel_idx].Channel; + +#ifdef DOT11_N_SUPPORT + if (((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + &&(pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + && (pChannelInfo->IsABand && (GetABandChOffset(pAd,ch) == 0))) { + continue; + } +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (!AC_ChannelGroupCheck(pAd, ch)) { + /* not in the BW_80 channel group */ + continue; + } + } +#endif /* DOT11_VHT_AC */ + + if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + + { + if ((GetABandChOffset(pAd,ch) != 0) + && ((channel_idx + GetABandChOffset(pAd,ch)) >=0) + && ((channel_idx + GetABandChOffset(pAd,ch)) < pAd->ChannelListNum)) + { + INT ChOffsetIdx = channel_idx + GetABandChOffset(pAd,ch); + falsecca += (pChannelInfo->FalseCCA[ChOffsetIdx] + + pChannelInfo->dirtyness[ChOffsetIdx]); + } + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + /* the same falsecca with neighbor */ + INT vht_ch_idx = get_vht_neighbor_index(ch); + + if (vht_ch_idx != (MAX_NUM_OF_CHANNELS+1)) + { + falsecca = (pChannelInfo->dirtyness[vht_ch_idx+channel_idx] + + pChannelInfo->FalseCCA[vht_ch_idx+channel_idx]) + + (pChannelInfo->dirtyness[vht_ch_idx+(channel_idx+1)] + + pChannelInfo->FalseCCA[vht_ch_idx+(channel_idx+1)]) + + (pChannelInfo->dirtyness[vht_ch_idx+(channel_idx+2)] + + pChannelInfo->FalseCCA[vht_ch_idx+(channel_idx+2)]) + + (pChannelInfo->dirtyness[vht_ch_idx+(channel_idx+3)] + + pChannelInfo->FalseCCA[vht_ch_idx+(channel_idx+3)]); + } + } +#endif /* DOT11_VHT_AC */ + +#ifdef AP_QLOAD_SUPPORT + /* QLOAD ALARM */ + /* when busy time of a channel > threshold, skip it */ + /* TODO: Use weight for different references to do channel selection */ + if (QBSS_LoadIsBusyTimeAccepted(pAd, + pChannelInfo->chanbusytime[channel_idx]) == FALSE) + { + /* check next one */ + continue; + } +#endif /* AP_QLOAD_SUPPORT */ + + if ((min_falsecca > falsecca)) + { + min_falsecca = falsecca; + candidate_ch = channel_idx; + } + } + } + + if (candidate_ch >= 0) + { + ch = pAd->ChannelList[candidate_ch].Channel; + printk("Rule 2 CCA value : Min False CCA value ==> Select Channel %d, min falsecca = %d \n", ch, min_falsecca); + return ch; + } + + base = RandomByte2(pAd); + for (channel_idx=0 ; channel_idx < pAd->ChannelListNum ; channel_idx++) + { + ch = pAd->ChannelList[(base + channel_idx) % pAd->ChannelListNum].Channel; + + if (AutoChannelSkipListCheck(pAd, ch)) + continue; + + if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) + && (pChannelInfo->IsABand == TRUE) + && RadarChannelCheck(pAd, ch)) + continue; +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (!AC_ChannelGroupCheck(pAd, ch)) { + /* not in the BW_80 channel group */ + continue; + } + } +#endif /* DOT11_VHT_AC */ + + break; + } + printk("Rule 3 CCA value : Randomly Select ==> Select Channel %d\n", ch); + return ch; +} + +/* + ========================================================================== + Description: + This routine calaulates the dirtyness of all channels by the dirtiness value and + number of AP in each channel and stores in pChannelInfo strcut. + This routine is called at iwpriv cmmand or initialization. It chooses and returns + a good channel whith less interference. + Return: + ch - channel number that + NOTE: + ========================================================================== + */ + +static inline UCHAR SelectClearChannelApCnt( + IN PRTMP_ADAPTER pAd + ) +{ + /*PBSSINFO pBssInfoTab = pAd->pBssInfoTab; */ + PCHANNELINFO pChannelInfo = pAd->pChannelInfo; + /*BSSENTRY *pBss; */ + UCHAR channel_index = 0,dirty,base = 0; + UCHAR final_channel = 0; + + + if(pChannelInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); + return (FirstChannel(pAd)); + } + + /* Calculate Dirtiness */ + + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + { + if (pChannelInfo->ApCnt[channel_index] > 0) + { + INT ll; + pChannelInfo->dirtyness[channel_index] += 30; + + /*5G */ + if (pChannelInfo->IsABand) + { + int Channel = pAd->ChannelList[channel_index].Channel; + + /*Make secondary channel dirty */ + if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + { + if (Channel > 14) + { + if ((Channel == 36) || (Channel == 44) + || (Channel == 52) || (Channel== 60) + || (Channel == 100) || (Channel == 108) + || (Channel == 116) || (Channel == 124) + || (Channel == 132) || (Channel == 149) + || (Channel == 157)) + { + if (channel_index + 1 < MAX_NUM_OF_CHANNELS) + if(pAd->ChannelList[channel_index+1].Channel - pAd->ChannelList[channel_index].Channel == 4) + pChannelInfo->dirtyness[channel_index+1] += 1; + } + else if ((Channel == 40) || (Channel == 48) + || (Channel == 56) || (Channel == 64) + || (Channel == 104) || (Channel == 112) + || (Channel == 120) || (Channel == 128) + || (Channel == 136) || (Channel== 153) + || (Channel == 161)) + { + if(channel_index - 1 >= 0) + if(pAd->ChannelList[channel_index].Channel - pAd->ChannelList[channel_index-1].Channel == 4) + pChannelInfo->dirtyness[channel_index-1] += 1; + } + } + } +#ifdef DOT11_VHT_AC + else if(pAd->CommonCfg.vht_bw == VHT_BW_80) { + INT vht_ch_idx = get_vht_neighbor_index(pAd->ChannelList[channel_index].Channel); + + if (vht_ch_idx != (MAX_NUM_OF_CHANNELS+1)) + { + pChannelInfo->dirtyness[vht_ch_idx+channel_index]++; + pChannelInfo->dirtyness[vht_ch_idx+(channel_index+1)]++; + pChannelInfo->dirtyness[vht_ch_idx+(channel_index+2)]++; + pChannelInfo->dirtyness[vht_ch_idx+(channel_index+3)]++; + } + } +#endif /* DOT11_VHT_AC */ + } + /*2.4G */ + if (!pChannelInfo->IsABand) + { + int ChanOffset = 0; + + if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)&& + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + /* + BW is 40Mhz + the distance between two channel to prevent interference + is 4 channel width plus 4 channel width (secondary channel) + */ + ChanOffset = 8; + } + else + { + /* + BW is 20Mhz + The channel width of 2.4G band is 5Mhz. + The distance between two channel to prevent interference is 4 channel width + */ + ChanOffset = 4; + } + + for (ll = channel_index + 1; ll < (channel_index + ChanOffset + 1); ll++) + { + if (ll < MAX_NUM_OF_CHANNELS) + pChannelInfo->dirtyness[ll]++; + } + + if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)&& + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)) + { + /* BW is 40Mhz */ + ChanOffset = 8; + } + else + { + /* BW is 20Mhz */ + ChanOffset = 4; + } + + for (ll = channel_index - 1; ll > (channel_index - ChanOffset - 1); ll--) + { + if (ll >= 0) + pChannelInfo->dirtyness[ll]++; + } + } + } + }/* Calculate Dirtiness */ + + AutoChannelSkipListSetDirty(pAd); + + printk("=====================================================\n"); + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + /* debug messages */ + printk("Channel %d : Dirty = %ld, ApCnt=%ld, Busy Time = %d, Skip Channel = %s\n", + pAd->ChannelList[channel_index].Channel, + pChannelInfo->dirtyness[channel_index], + pChannelInfo->ApCnt[channel_index], +#ifdef AP_QLOAD_SUPPORT + pChannelInfo->chanbusytime[channel_index], +#else + 0, +#endif /* AP_QLOAD_SUPPORT */ + (pChannelInfo->SkipList[channel_index] == TRUE) ? "TRUE" : "FALSE"); + printk("=====================================================\n"); + + pAd->ApCfg.AutoChannel_Channel = 0; + + /* RULE 1. pick up a good channel that no one used */ + + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + { + if (pChannelInfo->SkipList[channel_index] == TRUE) + continue; + + if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) + &&(pChannelInfo->IsABand == TRUE) + && RadarChannelCheck(pAd, pAd->ChannelList[channel_index].Channel)) + continue; + +#ifdef AP_QLOAD_SUPPORT + /* QLOAD ALARM */ + if (QBSS_LoadIsBusyTimeAccepted(pAd, + pChannelInfo->chanbusytime[channel_index]) == FALSE) + continue; +#endif /* AP_QLOAD_SUPPORT */ + + /* Check BW40/80 channel group */ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) { + if (!N_ChannelGroupCheck(pAd, pAd->ChannelList[channel_index].Channel)) { + printk ("channel_%d is not in BW_40 channel group\n", + pAd->ChannelList[channel_index].Channel); + continue; + } + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (!AC_ChannelGroupCheck(pAd, pAd->ChannelList[channel_index].Channel)) { + printk ("channel_%d is not in BW_80 channel group\n", + pAd->ChannelList[channel_index].Channel); + continue; + } + } +#endif /* DOT11_VHT_AC */ + + if (pChannelInfo->dirtyness[channel_index] == 0) + break; + } + if (channel_index < pAd->ChannelListNum) + { + printk("Rule 1 APCnt : dirtiness == 0 (no one used and no interference) ==> Select Channel %d\n", pAd->ChannelList[channel_index].Channel); + + return pAd->ChannelList[channel_index].Channel; + } + + /* RULE 2. if not available, then co-use a channel that's no interference (dirtyness=30) */ + /* RULE 3. if not available, then co-use a channel that has minimum interference (dirtyness=31,32) */ + for (dirty = 30; dirty <= 32; dirty++) + { + BOOLEAN candidate[MAX_NUM_OF_CHANNELS+1], candidate_num=0; + UCHAR min_ApCnt = 255; + final_channel = 0; + + NdisZeroMemory(candidate, MAX_NUM_OF_CHANNELS+1); + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + { + if (pChannelInfo->SkipList[channel_index] == TRUE) + continue; + + if (pChannelInfo->dirtyness[channel_index] == dirty) + { + candidate[channel_index]=TRUE; + candidate_num++; + } + } + /* if there's more than 1 candidate, pick up the channel with minimum RSSI */ + if (candidate_num) + { + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + { + +#ifdef AP_QLOAD_SUPPORT + /* QLOAD ALARM */ + /* when busy time of a channel > threshold, skip it */ + /* TODO: Use weight for different references to do channel selection */ + if (QBSS_LoadIsBusyTimeAccepted(pAd, + pChannelInfo->chanbusytime[channel_index]) == FALSE) + { + /* check next one */ + continue; + } +#endif /* AP_QLOAD_SUPPORT */ + + if (candidate[channel_index] && (pChannelInfo->ApCnt[channel_index] < min_ApCnt)) + { + + if(((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + && (BW40_ChannelCheck(pAd->ChannelList[channel_index].Channel) == FALSE)) { + continue; + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (!AC_ChannelGroupCheck(pAd, pAd->ChannelList[channel_index].Channel)) { + /* not in the BW_80 channel group */ + continue; + } + } +#endif /* DOT11_VHT_AC */ + + if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) + &&(pChannelInfo->IsABand == TRUE) + && RadarChannelCheck(pAd, pAd->ChannelList[channel_index].Channel)) + continue; + + final_channel = pAd->ChannelList[channel_index].Channel; + min_ApCnt = pChannelInfo->ApCnt[channel_index]; + } + } + if (final_channel != 0) + { + printk("Rule 2 APCnt : minimum APCnt with minimum interference(dirtiness: 30~32) ==> Select Channel %d\n", final_channel); + printk(" Dirtiness = %d , Min ApCnt = %d\n", dirty, min_ApCnt); + return final_channel; + } + } + } + /* RULE 3. still not available, pick up the random channel */ + base = RandomByte2(pAd); + + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + { + final_channel = pAd->ChannelList[(base + channel_index) % pAd->ChannelListNum].Channel; + + if (AutoChannelSkipListCheck(pAd, final_channel)) + continue; + + if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif + ) + { + if (!N_ChannelGroupCheck(pAd, pAd->ChannelList[channel_index].Channel)) + { + /* not in the BW_40 channel group */ + continue; + } + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (!AC_ChannelGroupCheck(pAd, pAd->ChannelList[channel_index].Channel)) { + /* not in the BW_80 channel group */ + continue; + } + } +#endif /* DOT11_VHT_AC */ + + if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) + &&(pChannelInfo->IsABand == TRUE) + && RadarChannelCheck(pAd, final_channel)) + continue; + + break; + } + printk("Rule 3 APCnt : Randomly Select ==> Select Channel %d\n",final_channel); + + return final_channel; +} + +ULONG AutoChBssInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR ChannelNo, + IN UCHAR ExtChOffset, + IN CHAR Rssi) +{ + ULONG Idx; + PBSSINFO pBssInfoTab = pAd->pBssInfoTab; + + if(pBssInfoTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pBssInfoTab equal NULL.\n")); + return BSS_NOT_FOUND; + } + + Idx = AutoChBssSearchWithSSID(pAd, pBssid, (PUCHAR)Ssid, SsidLen, ChannelNo); + if (Idx == BSS_NOT_FOUND) + { + if (pBssInfoTab->BssNr >= MAX_LEN_OF_BSS_TABLE) + return BSS_NOT_FOUND; + Idx = pBssInfoTab->BssNr; + AutoChBssEntrySet(&pBssInfoTab->BssEntry[Idx % MAX_LEN_OF_BSS_TABLE], pBssid, Ssid, SsidLen, + ChannelNo, ExtChOffset, Rssi); + pBssInfoTab->BssNr++; + } + else + { + AutoChBssEntrySet(&pBssInfoTab->BssEntry[Idx % MAX_LEN_OF_BSS_TABLE], pBssid, Ssid, SsidLen, + ChannelNo, ExtChOffset, Rssi); + } + + return Idx; +} + + +void AutoChBssTableInit( + IN PRTMP_ADAPTER pAd) +{ + os_alloc_mem(pAd, (UCHAR **)&pAd->pBssInfoTab, sizeof(BSSINFO)); + if (pAd->pBssInfoTab) + NdisZeroMemory(pAd->pBssInfoTab, sizeof(BSSINFO)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->pBssInfoTab", __FUNCTION__)); + + return; +} + +void ChannelInfoInit( + IN PRTMP_ADAPTER pAd) +{ + os_alloc_mem(pAd, (UCHAR **)&pAd->pChannelInfo, sizeof(CHANNELINFO)); + if (pAd->pChannelInfo) + NdisZeroMemory(pAd->pChannelInfo, sizeof(CHANNELINFO)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->pChannelInfo", __FUNCTION__)); + + + return; +} + +void AutoChBssTableDestroy( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pBssInfoTab) + { + os_free_mem(NULL, pAd->pBssInfoTab); + pAd->pBssInfoTab = NULL; + } + + return; +} + +void ChannelInfoDestroy( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pChannelInfo) + { + os_free_mem(NULL, pAd->pChannelInfo); + pAd->pChannelInfo = NULL; + } + + return; +} + +/* + ========================================================================== + Description: + This routine sets the current PhyMode for calculating + the dirtyness. + Return: + none + NOTE: + ========================================================================== + */ +void CheckPhyModeIsABand(RTMP_ADAPTER *pAd) +{ + pAd->pChannelInfo->IsABand = (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) ? TRUE : FALSE; + + return; +} + + +UCHAR SelectBestChannel(RTMP_ADAPTER *pAd, ChannelSel_Alg Alg) +{ + UCHAR ch = 0; + + /* init pAd->pChannelInfo->IsABand */ + CheckPhyModeIsABand(pAd); + +#ifdef MICROWAVE_OVEN_SUPPORT + if (Alg == ChannelAlgCCA) + pAd->CommonCfg.MO_Cfg.bEnable = TRUE; +#endif /* MICROWAVE_OVEN_SUPPORT */ + + switch ( Alg ) + { + case ChannelAlgRandom: + case ChannelAlgApCnt: + ch = SelectClearChannelApCnt(pAd); + break; + case ChannelAlgCCA: + ch = SelectClearChannelCCA(pAd); + break; + default: + ch = SelectClearChannelCCA(pAd); + break; + } + + RTMPSendWirelessEvent(pAd, IW_CHANNEL_CHANGE_EVENT_FLAG, 0, 0, ch); + + return ch; + +} + +VOID APAutoChannelInit(RTMP_ADAPTER *pAd) +{ + UINT32 BusyTime; + + /* reset bss table */ + AutoChBssTableReset(pAd); + + /* clear Channel Info */ + ChannelInfoReset(pAd); + + /* init pAd->pChannelInfo->IsABand */ + CheckPhyModeIsABand(pAd); + + pAd->ApCfg.current_channel_index = 0; + + /* read clear for primary channel */ + RTMP_IO_READ32(pAd, CH_BUSY_STA, &BusyTime); +} + +/* + ========================================================================== + Description: + This routine is called at initialization. It returns a channel number + that complies to regulation domain and less interference with current + enviornment. + Return: + ch - channel number that + NOTE: + The retruned channel number is guaranteed to comply to current regulation + domain that recorded in pAd->CommonCfg.CountryRegion + Usage: + 1.) iwpriv ra0 set AutoChannelSel=1 + Ues the number of AP and inference status to choose + 2.) iwpriv ra0 set AutoChannelSel=2 + Ues the False CCA count and Rssi to choose + ========================================================================== + */ +UCHAR APAutoSelectChannel(RTMP_ADAPTER *pAd, ChannelSel_Alg Alg) +{ + UCHAR ch = 0, i; + + /* passive scan channel 1-14. collect statistics */ + + /* + In the autochannel select case. AP didn't get channel yet. + So have no way to determine which Band AP used by channel number. + */ + + /* Init some structures before doing AutoChannelSelect() */ + APAutoChannelInit(pAd); + + if (( Alg == ChannelAlgRandom ) && (pAd->pChannelInfo->IsABand == TRUE)) + { /*for Dfs */ + ch = SelectClearChannelRandom(pAd); + } + else + { + +#ifdef MICROWAVE_OVEN_SUPPORT + pAd->CommonCfg.MO_Cfg.bEnable = FALSE; + AsicMeasureFalseCCA(pAd); +#endif /* MICROWAVE_OVEN_SUPPORT */ + + /*find RSSI in each channel */ + for (i=0; iChannelListNum; i++) + { + ULONG wait_time = 200; /* wait for 200 ms at each channel. */ + + AsicSwitchChannel(pAd, pAd->ChannelList[i].Channel, TRUE); + AsicLockChannel(pAd, pAd->ChannelList[i].Channel);/*do nothing */ + pAd->ApCfg.current_channel_index = i; + + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[i].Channel; + +#ifdef AP_QLOAD_SUPPORT + /* QLOAD ALARM, ever alarm from QLOAD module */ + if (QLOAD_DOES_ALARM_OCCUR(pAd)) + wait_time = 400; +#endif /* AP_QLOAD_SUPPORT */ + OS_WAIT(wait_time); + + UpdateChannelInfo(pAd, i,Alg); + } + + ch = SelectBestChannel(pAd, Alg); + } + + return ch; +} + + +#ifdef AP_SCAN_SUPPORT +/* + ========================================================================== + Description: + trigger Auto Channel Selection every period of ACSCheckTime. + + NOTE: + This function is called in a 1-sec mlme periodic check. + ========================================================================== + */ +VOID AutoChannelSelCheck(RTMP_ADAPTER *pAd) +{ + /* Do nothing if ACSCheckTime is not configured or AP is doing site survey */ + if (pAd->ApCfg.ACSCheckTime == 0 || ApScanRunning(pAd)) + return; + else + pAd->ApCfg.ACSCheckCount++; + + if (pAd->ApCfg.ACSCheckCount >= pAd->ApCfg.ACSCheckTime) + { + /* Reset Counter */ + pAd->ApCfg.ACSCheckCount = 0; + + /* Do Auto Channel Selection only when no client is associated */ + if (pAd->MacTab.Size != 0) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): ignore Channel Selection checking because has %u associated clients\n", + __FUNCTION__, pAd->MacTab.Size)); + return; + } + else + { + /* Do Auto Channel Selection */ + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Scanning channels for channel selection.\n", __FUNCTION__)); + ApSiteSurvey(pAd, NULL, SCAN_PASSIVE, TRUE); + } + } + +} +#endif /* AP_SCAN_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_band_steering.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_band_steering.c new file mode 100644 index 000000000..9d7a2e486 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_band_steering.c @@ -0,0 +1,1025 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + ap_band_steering.c +*/ + +#ifdef BAND_STEERING +#include "rt_config.h" + +extern BNDSTRG_OPS D_BndStrgOps; + +/* ioctl */ +INT Show_BndStrg_Info( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->ShowTableInfo(table); + + return TRUE; +} + + +INT Show_BndStrg_List( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->ShowTableEntries(P_BND_STRG_TABLE); + + return TRUE; +} + + +INT Set_BndStrg_Enable( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + BOOLEAN enable = (BOOLEAN) simple_strtol(arg, 0, 10); + + if (table->Ops) + table->Ops->SetEnable(table, enable); + else if (enable) { + pAd->ApCfg.BandSteering = TRUE; + BndStrg_Init(pAd); + } + + return TRUE; +} + + +INT Set_BndStrg_RssiDiff( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + CHAR RssiDiff = (CHAR) simple_strtol(arg, 0, 10); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetRssiDiff(table, RssiDiff); + + table->RssiDiff = RssiDiff; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): RssiCheck = %u\n", __FUNCTION__, table->RssiDiff)); + + return TRUE; +} + + +INT Set_BndStrg_RssiLow( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + CHAR RssiLow = (CHAR) simple_strtol(arg, 0, 10); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetRssiLow(table, RssiLow); + + table->RssiLow = RssiLow; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): RssiLow = %u\n", __FUNCTION__, table->RssiLow)); + + return TRUE; +} + + +INT Set_BndStrg_Age( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UINT32 AgeTime = (UINT32) simple_strtol(arg, 0, 10); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetAgeTime(table, AgeTime); + + return TRUE; +} + + +INT Set_BndStrg_HoldTime( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UINT32 HoldTime = (UINT32) simple_strtol(arg, 0, 10); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetHoldTime(table, HoldTime); + + return TRUE; +} + + +INT Set_BndStrg_CheckTime5G( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UINT32 CheckTime = (UINT32) simple_strtol(arg, 0, 10); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetCheckTime(table, CheckTime); + + return TRUE; +} + + +INT Set_BndStrg_FrmChkFlag( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UINT32 FrmChkFlag = (UINT32) simple_strtol(arg, 0, 16); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetFrmChkFlag(table, FrmChkFlag); + + return TRUE; +} + + +INT Set_BndStrg_CndChkFlag( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UINT32 CndChkFlag = (UINT32) simple_strtol(arg, 0, 16); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetCndChkFlag(table, CndChkFlag); + + return TRUE; +} + +#ifdef BND_STRG_DBG +INT Set_BndStrg_MonitorAddr( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UCHAR MonitorAddr[MAC_ADDR_LEN]; + PSTRING value; + INT i; + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, (UCHAR *)&MonitorAddr[i++], 1); + } + + if (table->Ops) + table->Ops->SetMntAddr(table, MonitorAddr); + + return TRUE; +} +#endif /* BND_STRG_DBG */ +/**** end of ioctl ****/ + +INT BndStrg_Init(PRTMP_ADAPTER pAd) +{ + INT ret_val = BND_STRG_SUCCESS; + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + DBGPRINT(RT_DEBUG_OFF, (YLW("%s()\n"), __FUNCTION__)); + + ret_val = BndStrg_TableInit(pAd, table); + + + if (ret_val != BND_STRG_SUCCESS) + { + BND_STRG_DBGPRINT(RT_DEBUG_ERROR, + ("Error in %s(), error code = %d!\n", __FUNCTION__, ret_val)); + } + + return ret_val; +} + +INT BndStrg_TableInit(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table) +{ + INT ret_val = BND_STRG_SUCCESS; + + if (table->bInitialized == TRUE) + return BND_STRG_SUCCESS; + + NdisZeroMemory(table, sizeof(BND_STRG_CLI_TABLE)); + OS_NdisAllocateSpinLock(&table->Lock); + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + table->Band = BAND_5G; + else + table->Band = BAND_24G; + + BndStrg_SetInfFlags(pAd, table, TRUE); + + table->Ops = &D_BndStrgOps; + table->RssiDiff = BND_STRG_RSSI_DIFF; + table->RssiLow = BND_STRG_RSSI_LOW; + table->AgeTime = BND_STRG_AGE_TIME; + table->HoldTime = BND_STRG_HOLD_TIME; + table->CheckTime_5G = BND_STRG_CHECK_TIME_5G; + table->AutoOnOffThrd = BND_STRG_AUTO_ONOFF_THRD; + table->AlgCtrl.ConditionCheck = fBND_STRG_CND_5G_RSSI; + table->AlgCtrl.FrameCheck = fBND_STRG_FRM_CHK_PRB_REQ | \ + fBND_STRG_FRM_CHK_ATH_REQ; + table->priv = (VOID *) pAd; + table->bInitialized = TRUE; + + if (ret_val != BND_STRG_SUCCESS) + { + BND_STRG_DBGPRINT(RT_DEBUG_ERROR, + ("Error in %s(), error code = %d!\n", __FUNCTION__, ret_val)); + } + + return BND_STRG_SUCCESS; +} + +INT BndStrg_Release(PRTMP_ADAPTER pAd) +{ + INT ret_val = BND_STRG_SUCCESS; + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + DBGPRINT(RT_DEBUG_OFF, (YLW("%s()\n"), __FUNCTION__)); + BndStrg_SetInfFlags(pAd, table, FALSE); + + if (table->bEnabled == TRUE) + ret_val = BndStrg_Enable(table, 0); + + if ((table->b2GInfReady == FALSE && table->b5GInfReady == FALSE)) + ret_val = BndStrg_TableRelease(table); + + return ret_val; +} + + +INT BndStrg_TableRelease(PBND_STRG_CLI_TABLE table) +{ + INT ret_val = BND_STRG_SUCCESS; + + if (table->bInitialized == FALSE) + return BND_STRG_NOT_INITIALIZED; + + OS_NdisFreeSpinLock(&table->Lock); + table->bInitialized = FALSE; + + return ret_val; +} + + +INT BndStrg_InsertEntry( + PBND_STRG_CLI_TABLE table, + PUCHAR pAddr, + PBND_STRG_CLI_ENTRY *entry_out) +{ + INT i; + UCHAR HashIdx; + PBND_STRG_CLI_ENTRY entry = NULL, this_entry = NULL; + INT ret_val = BND_STRG_SUCCESS; + + if (table->Size >= BND_STRG_MAX_TABLE_SIZE) { + DBGPRINT(RT_DEBUG_WARN, ("%s(): Table is full!\n", __FUNCTION__)); + return BND_STRG_TABLE_FULL; + } + + NdisAcquireSpinLock(&table->Lock); + for (i = 0; i< BND_STRG_MAX_TABLE_SIZE; i++) + { + entry = &table->Entry[i]; + + /* pick up the first available vacancy*/ + if (entry->bValid == FALSE) { + NdisZeroMemory(entry, sizeof(BND_STRG_CLI_ENTRY)); + /* Fill Entry */ + RTMP_GetCurrentSystemTick(&entry->jiffies); + COPY_MAC_ADDR(entry->Addr, pAddr); + entry->bValid = TRUE; + break; + } + } + + if (entry) { + /* add this MAC entry into HASH table */ + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + if (table->Hash[HashIdx] == NULL) { + table->Hash[HashIdx] = entry; + } else { + this_entry = table->Hash[HashIdx]; + while (this_entry->pNext != NULL) { + this_entry = this_entry->pNext; + } + this_entry->pNext = entry; + } + + *entry_out = entry; + table->Size++; + } + NdisReleaseSpinLock(&table->Lock); + return ret_val; +} + + +INT BndStrg_DeleteEntry(PBND_STRG_CLI_TABLE table, PUCHAR pAddr, UINT32 Index) +{ + USHORT HashIdx; + PBND_STRG_CLI_ENTRY entry, pre_entry, this_entry; + INT ret_val = BND_STRG_SUCCESS; + + + NdisAcquireSpinLock(&table->Lock); + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + if (Index >= BND_STRG_MAX_TABLE_SIZE) + { + entry = table->Hash[HashIdx]; + while (entry) { + if (MAC_ADDR_EQUAL(pAddr, entry->Addr)) { + /* this is the entry we're looking for */ + break; + } else { + entry = entry->pNext; + } + } + + if (entry == NULL) + { + BND_STRG_DBGPRINT(RT_DEBUG_WARN, + ("%s(): Index=%u, %02x:%02x:%02x:%02x:%02x:%02x, " + "Entry not found.\n", + __FUNCTION__, Index, PRINT_MAC(pAddr))); + NdisReleaseSpinLock(&table->Lock); + return BND_STRG_INVALID_ARG; + } + } + else + entry = &table->Entry[Index]; + + if (entry && entry->bValid) + { + { + pre_entry = NULL; + this_entry = table->Hash[HashIdx]; + ASSERT(this_entry); + if (this_entry != NULL) + { + /* update Hash list*/ + do + { + if (this_entry == entry) + { + if (pre_entry == NULL) + table->Hash[HashIdx] = entry->pNext; + else + pre_entry->pNext = entry->pNext; + break; + } + + pre_entry = this_entry; + this_entry = this_entry->pNext; + } while (this_entry); + } + + /* not found !!!*/ + ASSERT(this_entry != NULL); + + NdisZeroMemory(entry->Addr, MAC_ADDR_LEN); + entry->pNext = NULL; + entry->bValid = FALSE; + table->Size--; + } + } + NdisReleaseSpinLock(&table->Lock); + + return ret_val; +} + + +PBND_STRG_CLI_ENTRY BndStrg_TableLookup(PBND_STRG_CLI_TABLE table, PUCHAR pAddr) +{ + ULONG HashIdx; + BND_STRG_CLI_ENTRY *entry = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + entry = table->Hash[HashIdx]; + + while (entry && entry->bValid) + { + if (MAC_ADDR_EQUAL(entry->Addr, pAddr)) + break; + else + entry = entry->pNext; + } + + return entry; +} + +BOOLEAN BndStrg_CheckConnectionReq( + PRTMP_ADAPTER pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops && (table->bEnabled == TRUE)) + { + return table->Ops->CheckConnectionReq( + pAd, + pSrcAddr, + FrameType, + Rssi); + } + + return TRUE; +} + + +INT BndStrg_Enable(PBND_STRG_CLI_TABLE table, BOOLEAN enable) +{ + BNDSTRG_MSG msg; + PRTMP_ADAPTER pAd = NULL; + + if (table == NULL) + return BND_STRG_TABLE_IS_NULL; + + if (table->bInitialized == FALSE) + return BND_STRG_NOT_INITIALIZED; + if (!(table->bEnabled ^ enable)) + { + /* Already enabled/disabled */ + BND_STRG_DBGPRINT(RT_DEBUG_OFF, /* TRACE */ + (GRN("%s(): Band steering is already %s.\n"), + __FUNCTION__, (enable ? "enabled" : "disabled"))); + return BND_STRG_SUCCESS; + } + + if (enable) + { + table->bEnabled = TRUE; + } + else + { + + table->bEnabled = FALSE; + } + + pAd = (PRTMP_ADAPTER) table->priv; + msg.Action = BNDSTRG_ONOFF; + msg.OnOff = table->bEnabled; + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_BNDSTRG_MSG, + NULL, + (UCHAR *)&msg, + sizeof(msg)); + + BND_STRG_DBGPRINT(RT_DEBUG_OFF, + (GRN("%s(): Band steering %s running.\n"), + __FUNCTION__, (enable ? "start" : "stop"))); + + return BND_STRG_SUCCESS; +} + + +INT BndStrg_SetInfFlags(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BOOLEAN bInfReady) +{ + INT ret_val = BND_STRG_SUCCESS; + BNDSTRG_MSG msg; + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode) && + (table->b5GInfReady ^ bInfReady)) + { + table->b5GInfReady = bInfReady; + + msg.Action = INF_STATUS_RSP_5G; + msg.b5GInfReady = table->b5GInfReady; + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_BNDSTRG_MSG, + NULL, + (UCHAR *)&msg, + sizeof(msg)); + BND_STRG_DBGPRINT(RT_DEBUG_OFF, + (BLUE("%s(): BSS (%02x:%02x:%02x:%02x:%02x:%02x)") + BLUE(" set 5G Inf %s.\n") + , __FUNCTION__, PRINT_MAC(pAd->ApCfg.MBSSID[0].wdev.bssid), + bInfReady ? "ready" : "not ready")); + } + else if (table->b2GInfReady ^ bInfReady) + { + table->b2GInfReady = bInfReady; + msg.Action = INF_STATUS_RSP_2G; + msg.b2GInfReady = table->b2GInfReady; + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_BNDSTRG_MSG, + NULL, + (UCHAR *)&msg, + sizeof(msg)); + BND_STRG_DBGPRINT(RT_DEBUG_OFF, + (BLUE("%s(): BSS (%02x:%02x:%02x:%02x:%02x:%02x)") + BLUE(" set 2G Inf %s.\n") + , __FUNCTION__, PRINT_MAC(pAd->ApCfg.MBSSID[0].wdev.bssid), + bInfReady ? "ready" : "not ready")); + } + + return ret_val; +} + + +BOOLEAN BndStrg_IsClientStay( + PRTMP_ADAPTER pAd, + PMAC_TABLE_ENTRY pEntry) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + CHAR Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + if (table->AlgCtrl.ConditionCheck & fBND_STRG_CND_5G_RSSI && + table->Band == BAND_5G && + (Rssi < (table->RssiLow - 10/*Test*/))) + { + BNDSTRG_MSG msg; + + msg.Action = CLI_DEL; + COPY_MAC_ADDR(msg.Addr, pEntry->Addr); + /* we don't know the index, daemon should look it up */ + msg.TalbeIndex = BND_STRG_MAX_TABLE_SIZE; + + BND_STRG_DBGPRINT(RT_DEBUG_TRACE, + (YLW("%s(): Kick client (%02x:%02x:%02x:%02x:%02x:%02x)") + YLW(" due to low Rssi(%d).\n") + , __FUNCTION__, PRINT_MAC(pEntry->Addr), Rssi)); + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_BNDSTRG_MSG, + NULL, + (UCHAR *) &msg, + sizeof(BNDSTRG_MSG)); + + table->Ops->TableEntryDel(table, pEntry->Addr, BND_STRG_MAX_TABLE_SIZE); + + return FALSE; + } + + return TRUE; +} + + +INT BndStrg_MsgHandle(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + BNDSTRG_MSG msg; + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->bInitialized == FALSE) + return BND_STRG_NOT_INITIALIZED; + + if (wrq->u.data.length != sizeof(BNDSTRG_MSG)) + return BND_STRG_INVALID_ARG; + else + { + copy_from_user(&msg, wrq->u.data.pointer, wrq->u.data.length); + if (table->Ops->MsgHandle) + table->Ops->MsgHandle(pAd, &msg); + } + + return BND_STRG_SUCCESS; +} + +INT D_BndStrgSendMsg( + PRTMP_ADAPTER pAd, + BNDSTRG_MSG *msg) +{ + return RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_BNDSTRG_MSG, + NULL, + (UCHAR *) msg, + sizeof(BNDSTRG_MSG)); +} + + +static VOID D_ShowTableInfo(PBND_STRG_CLI_TABLE table) +{ + BNDSTRG_MSG msg; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + + msg.Action = TABLE_INFO; + + D_BndStrgSendMsg(pAd, &msg); +} + +static VOID D_ShowTableEntries(PBND_STRG_CLI_TABLE table) +{ + BNDSTRG_MSG msg; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + + INT i; + BND_STRG_DBGPRINT(RT_DEBUG_OFF, + ("\t%s Accessible Clients:\n", + (table->Band == BAND_24G) ? + "2.4G" : "5G")); + + for (i = 0; i < BND_STRG_MAX_TABLE_SIZE; i++) + { + if (table->Entry[i].bValid) + { + BND_STRG_DBGPRINT(RT_DEBUG_OFF, + ("\t%d: %02x:%02x:%02x:%02x:%02x:%02x\n", + i, PRINT_MAC(table->Entry[i].Addr))); + } + } + + msg.Action = ENTRY_LIST; + D_BndStrgSendMsg(pAd, &msg); +} + + +static BOOLEAN D_CheckConnectionReq( + PRTMP_ADAPTER pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + BNDSTRG_MSG msg; + UINT32 frame_type_to_frame_check_flags[] = { \ + fBND_STRG_FRM_CHK_PRB_REQ, + 0, + fBND_STRG_FRM_CHK_ASS_REQ, + fBND_STRG_FRM_CHK_ATH_REQ}; + UINT32 frame_check_flags = 0; + + /* Send to daemon */ + NdisCopyMemory(msg.Rssi, Rssi, 3); + msg.Action= CONNECTION_REQ; + msg.Band = table->Band; + msg.FrameType = FrameType; + COPY_MAC_ADDR(msg.Addr, pSrcAddr); + D_BndStrgSendMsg(pAd, &msg); + + if (FrameType < (sizeof(frame_type_to_frame_check_flags)/sizeof(UINT32))) + frame_check_flags = frame_type_to_frame_check_flags[FrameType]; + else + {/* invalid frame type */} + + if (table->bEnabled == TRUE && + frame_check_flags & table->AlgCtrl.FrameCheck) + { + PBND_STRG_CLI_ENTRY entry = NULL; + + if (table->Ops) + entry = table->Ops->TableLookup(table, pSrcAddr); + + if (entry/* || table->Band == BAND_5G*/) + return TRUE; + else + { +#ifdef BND_STRG_QA + BND_STRG_PRINTQAMSG(table, pSrcAddr, + (RED("%s: check %s request failed. client's (%02x:%02x:%02x:%02x:%02x:%02x)" + " request is ignored. \n"), (table->Band == BAND_24G ? "2.4G" : "5G"), + FrameType == 0 ? ("probe") : (FrameType == 3 ? "auth" : "unknow"), + PRINT_MAC(pSrcAddr))); +#endif + return FALSE; + } + + } + + return TRUE; +} + + +static VOID D_InfStatusRsp(PBND_STRG_CLI_TABLE table, BNDSTRG_MSG *msg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG Rsp; + + /* If user config is OFF, don't respond to this query */ + if (pAd->ApCfg.BandSteering == 0) + return; + else if (pAd->ApCfg.BandSteering == 2 /* Auto OnOff */ + && pAd->CommonCfg.Channel <= 14) + { + // TODO: Use Avg False CCA + if (pAd->RalinkCounters.OneSecFalseCCACnt > table->AutoOnOffThrd && + table->bEnabled == FALSE) { + table->Ops->SetEnable(table, 1); + return; + } else if (pAd->RalinkCounters.OneSecFalseCCACnt < table->AutoOnOffThrd && + table->bEnabled == TRUE){ + table->Ops->SetEnable(table, 0); + return; + } + } + + /*INF_STATUS*/ + if (table->bInitialized == TRUE) + { + /* Send to daemon */ + if (table->Band == BAND_24G) { + Rsp.Action = INF_STATUS_RSP_2G; + Rsp.b2GInfReady = table->b2GInfReady; + } else if (table->Band == BAND_5G) { + Rsp.Action = INF_STATUS_RSP_5G; + Rsp.b5GInfReady = table->b5GInfReady; + } + else + { + return; + } + D_BndStrgSendMsg(pAd, &Rsp); + + } +} + +/* For IOCTL */ +static INT D_SetEnable( + PBND_STRG_CLI_TABLE table, + BOOLEAN enable) +{ + INT ret_val = BND_STRG_SUCCESS; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + + DBGPRINT(RT_DEBUG_OFF, + ("%s(): enable = %u\n", __FUNCTION__, enable)); + + if (!(pAd->ApCfg.BandSteering ^ enable)) + { + /* Already enabled/disabled */ + BND_STRG_DBGPRINT(RT_DEBUG_OFF, /* TRACE */ + (GRN("%s(): Band steering is already %s.\n"), + __FUNCTION__, (enable ? "enabled" : "disabled"))); + return BND_STRG_SUCCESS; + } + + pAd->ApCfg.BandSteering = (enable) ? TRUE : FALSE; + + if (enable) + ret_val = BndStrg_Init(pAd); + else + ret_val = BndStrg_Release(pAd); + + if (ret_val != BND_STRG_SUCCESS) + { + BND_STRG_DBGPRINT(RT_DEBUG_ERROR, + ("Error in %s(), error code = %d!\n", __FUNCTION__, ret_val)); + } + + return TRUE; +} + + +static INT D_SetRssiDiff( + PBND_STRG_CLI_TABLE table, + CHAR RssiDiff) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->RssiDiff = RssiDiff; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): RssiCheck = %u\n", __FUNCTION__, table->RssiDiff)); + + msg.Action = SET_RSSI_DIFF; + msg.RssiDiff = RssiDiff; + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + + +static INT D_SetRssiLow( + PBND_STRG_CLI_TABLE table, + CHAR RssiLow) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->RssiLow = RssiLow; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): RssiLow = %u\n", __FUNCTION__, table->RssiLow)); + + msg.Action = SET_RSSI_LOW; + msg.RssiLow = RssiLow; + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + + +static INT D_SetAgeTime( + PBND_STRG_CLI_TABLE table, + UINT32 Time) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->AgeTime = Time; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): AgeTime = %u\n", __FUNCTION__, table->AgeTime)); + + msg.Action = SET_AGE_TIME; + msg.Time = table->AgeTime; + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + + +static INT D_SetHoldTime( + PBND_STRG_CLI_TABLE table, + UINT32 Time) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->HoldTime= Time; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): HoldTime = %u\n", __FUNCTION__, table->HoldTime)); + + msg.Action = SET_HOLD_TIME; + msg.Time = table->HoldTime; + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + + +static INT D_SetCheckTime( + PBND_STRG_CLI_TABLE table, + UINT32 Time) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->CheckTime_5G = Time; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): CheckTime_5G = %u\n", __FUNCTION__, table->CheckTime_5G)); + + msg.Action = SET_CHECK_TIME; + msg.Time = table->CheckTime_5G; + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + + +static INT D_SetFrmChkFlag( + PBND_STRG_CLI_TABLE table, + UINT32 FrmChkFlag) +{ + table->AlgCtrl.FrameCheck = FrmChkFlag; + + DBGPRINT(RT_DEBUG_OFF, + ("%s(): FrameCheck = 0x%x\n", __FUNCTION__, table->AlgCtrl.FrameCheck)); + + return TRUE; +} + + +static INT D_SetCndChkFlag( + PBND_STRG_CLI_TABLE table, + UINT32 CndChkFlag) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->AlgCtrl.ConditionCheck = CndChkFlag; + + DBGPRINT(RT_DEBUG_OFF, + ("%s(): CndChkFlag = 0x%x\n", __FUNCTION__, table->AlgCtrl.ConditionCheck)); + + msg.Action = SET_CHEK_CONDITIONS; + msg.ConditionCheck = table->AlgCtrl.ConditionCheck; + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + +#ifdef BND_STRG_DBG +static INT D_SetMntAddr( + PBND_STRG_CLI_TABLE table, + PUCHAR Addr) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + COPY_MAC_ADDR(table->MonitorAddr, Addr); + DBGPRINT(RT_DEBUG_OFF, + ("%s(): %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(table->MonitorAddr))); + + msg.Action = SET_MNT_ADDR; + COPY_MAC_ADDR(msg.Addr, table->MonitorAddr); + D_BndStrgSendMsg(pAd, &msg); + + return TRUE; +} +#endif /* BND_STRG_DBG */ + +static VOID D_MsgHandle( + PRTMP_ADAPTER pAd, + BNDSTRG_MSG *msg) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + PBND_STRG_CLI_ENTRY entry = NULL; + + BND_STRG_DBGPRINT(RT_DEBUG_INFO, ("%s: action code (%d)\n",__FUNCTION__, msg->Action)); + + if (!table) + return; + + switch (msg->Action) + { + case CLI_ADD: + if (!table->Ops->TableLookup(table, msg->Addr)) + table->Ops->TableEntryAdd(table, msg->Addr, &entry); + break; + + case CLI_DEL: + table->Ops->TableEntryDel(table, msg->Addr, 0xFF); + break; + + case CLI_AGING_REQ: + msg->Action = CLI_AGING_RSP; + msg->Band = table->Band; + + if (MacTableLookup(pAd, msg->Addr) == NULL) + { + /* we can aging the entry if it is not in the mac table */ + msg->ReturnCode = BND_STRG_SUCCESS; + table->Ops->TableEntryDel(table, msg->Addr, 0xFF); + } + else + { + msg->ReturnCode = BND_STRG_STA_IS_CONNECTED; + } + + D_BndStrgSendMsg(pAd, msg); + + break; + + case INF_STATUS_QUERY: + D_InfStatusRsp(table, msg); + break; + + case BNDSTRG_ONOFF: + BndStrg_Enable(table, msg->OnOff); + break; + + default: + DBGPRINT(RT_DEBUG_WARN, ("%s: unknown action code. (%d)\n",__FUNCTION__, msg->Action)); + break; + } +} + +BNDSTRG_OPS D_BndStrgOps = { + .ShowTableInfo = D_ShowTableInfo, + .ShowTableEntries = D_ShowTableEntries, + .TableEntryAdd = BndStrg_InsertEntry, + .TableEntryDel = BndStrg_DeleteEntry, + .TableLookup = BndStrg_TableLookup, + .CheckConnectionReq = D_CheckConnectionReq, + .SetEnable = D_SetEnable, + .SetRssiDiff = D_SetRssiDiff, + .SetRssiLow = D_SetRssiLow, + .SetAgeTime = D_SetAgeTime, + .SetHoldTime = D_SetHoldTime, + .SetCheckTime = D_SetCheckTime, + .SetFrmChkFlag = D_SetFrmChkFlag, + .SetCndChkFlag = D_SetCndChkFlag, +#ifdef BND_STRG_DBG + .SetMntAddr = D_SetMntAddr, +#endif /* BND_STRG_DBG */ + .MsgHandle= D_MsgHandle, +}; +#endif /* BAND_STEERING */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_cfg.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_cfg.c new file mode 100644 index 000000000..af5f22590 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_cfg.c @@ -0,0 +1,16492 @@ +/**************************************************************************** + * 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_cfg.c + + Abstract: + IOCTL related subroutines + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +#define A_BAND_REGION_0 0 +#define A_BAND_REGION_1 1 +#define A_BAND_REGION_2 2 +#define A_BAND_REGION_3 3 +#define A_BAND_REGION_4 4 +#define A_BAND_REGION_5 5 +#define A_BAND_REGION_6 6 +#define A_BAND_REGION_7 7 +#define A_BAND_REGION_8 8 +#define A_BAND_REGION_9 9 +#define A_BAND_REGION_10 10 + +#define G_BAND_REGION_0 0 +#define G_BAND_REGION_1 1 +#define G_BAND_REGION_2 2 +#define G_BAND_REGION_3 3 +#define G_BAND_REGION_4 4 +#define G_BAND_REGION_5 5 +#define G_BAND_REGION_6 6 + +COUNTRY_CODE_TO_COUNTRY_REGION allCountry[] = { + /* {Country Number, ISO Name, Country Name, Support 11A, 11A Country Region, Support 11G, 11G Country Region} */ + {0, "DB", "Debug", TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_5}, + {8, "AL", "ALBANIA", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {12, "DZ", "ALGERIA", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {32, "AR", "ARGENTINA", TRUE, A_BAND_REGION_3, TRUE, G_BAND_REGION_1}, + {51, "AM", "ARMENIA", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {36, "AU", "AUSTRALIA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {40, "AT", "AUSTRIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {31, "AZ", "AZERBAIJAN", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {48, "BH", "BAHRAIN", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {112, "BY", "BELARUS", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {56, "BE", "BELGIUM", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {84, "BZ", "BELIZE", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {68, "BO", "BOLIVIA", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {76, "BR", "BRAZIL", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {96, "BN", "BRUNEI DARUSSALAM", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {100, "BG", "BULGARIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {124, "CA", "CANADA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {152, "CL", "CHILE", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {156, "CN", "CHINA", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {170, "CO", "COLOMBIA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {188, "CR", "COSTA RICA", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {191, "HR", "CROATIA", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {196, "CY", "CYPRUS", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {203, "CZ", "CZECH REPUBLIC", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {208, "DK", "DENMARK", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {214, "DO", "DOMINICAN REPUBLIC", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {218, "EC", "ECUADOR", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {818, "EG", "EGYPT", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {222, "SV", "EL SALVADOR", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {233, "EE", "ESTONIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {246, "FI", "FINLAND", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {250, "FR", "FRANCE", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {268, "GE", "GEORGIA", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {276, "DE", "GERMANY", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {300, "GR", "GREECE", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {320, "GT", "GUATEMALA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {340, "HN", "HONDURAS", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {344, "HK", "HONG KONG", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {348, "HU", "HUNGARY", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {352, "IS", "ICELAND", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {356, "IN", "INDIA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {360, "ID", "INDONESIA", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {364, "IR", "IRAN", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {372, "IE", "IRELAND", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {376, "IL", "ISRAEL", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {380, "IT", "ITALY", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {392, "JP", "JAPAN", TRUE, A_BAND_REGION_9, TRUE, G_BAND_REGION_1}, + {400, "JO", "JORDAN", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {398, "KZ", "KAZAKHSTAN", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {408, "KP", "KOREA DEMOCRATIC PEOPLE'S REPUBLIC OF",TRUE, A_BAND_REGION_5, TRUE, G_BAND_REGION_1}, + {410, "KR", "KOREA REPUBLIC OF", TRUE, A_BAND_REGION_5, TRUE, G_BAND_REGION_1}, + {414, "KW", "KUWAIT", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {428, "LV", "LATVIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {422, "LB", "LEBANON", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {438, "LI", "LIECHTENSTEIN", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {440, "LT", "LITHUANIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {442, "LU", "LUXEMBOURG", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {446, "MO", "MACAU", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {807, "MK", "MACEDONIA", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {458, "MY", "MALAYSIA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {484, "MX", "MEXICO", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {492, "MC", "MONACO", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {504, "MA", "MOROCCO", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {528, "NL", "NETHERLANDS", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {554, "NZ", "NEW ZEALAND", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {578, "NO", "NORWAY", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {512, "OM", "OMAN", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {586, "PK", "PAKISTAN", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {591, "PA", "PANAMA", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {604, "PE", "PERU", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {608, "PH", "PHILIPPINES", TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1}, + {616, "PL", "POLAND", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {620, "PT", "PORTUGAL", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {630, "PR", "PUERTO RICO", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {634, "QA", "QATAR", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {642, "RO", "ROMANIA", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {643, "RU", "RUSSIA FEDERATION", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {682, "SA", "SAUDI ARABIA", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {702, "SG", "SINGAPORE", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {703, "SK", "SLOVAKIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {705, "SI", "SLOVENIA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {710, "ZA", "SOUTH AFRICA", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {724, "ES", "SPAIN", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {752, "SE", "SWEDEN", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {756, "CH", "SWITZERLAND", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {760, "SY", "SYRIAN ARAB REPUBLIC", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {158, "TW", "TAIWAN", TRUE, A_BAND_REGION_3, TRUE, G_BAND_REGION_0}, + {764, "TH", "THAILAND", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {780, "TT", "TRINIDAD AND TOBAGO", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {788, "TN", "TUNISIA", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {792, "TR", "TURKEY", TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1}, + {804, "UA", "UKRAINE", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {784, "AE", "UNITED ARAB EMIRATES", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {826, "GB", "UNITED KINGDOM", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1}, + {840, "US", "UNITED STATES", TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_0}, + {858, "UY", "URUGUAY", TRUE, A_BAND_REGION_5, TRUE, G_BAND_REGION_1}, + {860, "UZ", "UZBEKISTAN", TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_0}, + {862, "VE", "VENEZUELA", TRUE, A_BAND_REGION_5, TRUE, G_BAND_REGION_1}, + {704, "VN", "VIET NAM", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {887, "YE", "YEMEN", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {716, "ZW", "ZIMBABWE", FALSE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1}, + {999, "", "", 0, 0, 0, 0} +}; + +#define NUM_OF_COUNTRIES (sizeof(allCountry)/sizeof(COUNTRY_CODE_TO_COUNTRY_REGION)) + + +INT Set_CountryString_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CountryCode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_ChGeography_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef SPECIFIC_TX_POWER_SUPPORT +INT Set_AP_PKT_PWR( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +INT Set_AP_PROBE_RSP_TIMES( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef DELAYED_TCP_ACK +INT Set_ACKQ_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_CACKQ_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ACKWait_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ACKLen_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ShowACKQParm_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* DELAYED_TCP_ACK */ + +INT Set_TxRate_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + + +#ifdef DOT11_VHT_AC +INT Set_2G_256QAM_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* DOT11_VHT_AC */ + +INT Set_OLBCDetection_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_IdleTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef IAPP_SUPPORT +INT Set_IappPID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* IAPP_SUPPORT */ + +INT Set_AP_AuthMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_EncrypType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_WpaMixPairCipher_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_RekeyInterval_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_RekeyMethod_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_PMKCachePeriod_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_PACKET_FILTER_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_PROBE_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_AUTH_FAIL_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_AUTH_NO_RSP_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_ASSOC_REQ_FAIL_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_ASSOC_REQ_NO_RSP_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_KickStaRssiLow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_WPAPSK_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_BasicRate_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_BeaconPeriod_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_DtimPeriod_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_NoForwarding_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_NoForwardingBTNSSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_NoForwardingMBCast_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_WmmCapable_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_HideSSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_VLANID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_VLANPriority_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_VLAN_TAG_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AccessPolicy_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + + +INT Set_ACLAddEntry_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ACLDelEntry_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ACLShowAll_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ACLClearAll_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_RadioOn_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_SiteSurvey_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef CUSTOMER_DCC_FEATURE +INT Set_ApScan_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApEnableBeaconTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApDisableSTAConnect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApEnableRadioChStats( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif +INT Set_AutoChannelSel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef AP_PARTIAL_SCAN_SUPPORT +INT Set_PartialScan_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +#ifdef AP_SCAN_SUPPORT +INT Set_AutoChannelSelCheckTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* AP_SCAN_SUPPORT */ + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_StaCount_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_StaSecurityInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_LinkInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_RtsInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_ChannelTimeInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_DriverInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DOT11_N_SUPPORT +INT Show_BaTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DOT11_N_SUPPORT */ + +INT Show_Sat_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_RAInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DBG_DIAGNOSE +INT Set_DiagOpt_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BDInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DBG_DAIGNOSE */ + +INT Show_Sat_Reset_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_MATTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DOT1X_SUPPORT +VOID RTMPIoctlQueryRadiusConf( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +INT Set_IEEE8021X_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_PreAuth_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_RADIUS_Server_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RADIUS_Port_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RADIUS_Key_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DOT1X_SUPPORT */ + +INT Set_DisConnectSta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DisConnectAllSta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +#ifdef APCLI_SUPPORT +INT Set_ApCli_Enable_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Ssid_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Bssid_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_DefaultKeyID_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_WPAPSK_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Key1_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Key2_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Key3_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Key4_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_TxMode_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_TxMcs_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#ifdef APCLI_AUTO_CONNECT_SUPPORT +INT Set_ApCli_AutoConnect_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_SiteSurveyPeriod_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef APCLI_CONNECTION_TRIAL +INT Set_ApCli_Trial_Ch_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* APCLI_CONNECTION_TRIAL */ + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +INT Set_ApCli_Wpa_Support(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_IEEE8021X_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ + +#ifdef MAC_REPEATER_SUPPORT +INT Set_ReptMode_Enable_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +INT Set_AP_WscSsid_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* WSC_AP_SUPPORT */ +#ifdef APCLI_CERT_SUPPORT +INT Set_ApCli_Cert_Enable_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_WMM_Enable_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#ifdef UAPSD_SUPPORT +INT Set_UAPSD_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* UAPSD_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +INT Set_WscStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef BB_SOC +INT Set_WscOOB_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif + +INT Set_WscStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID RTMPIoctlWscProfile( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlWscPINCode( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlWscStatus( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetWscDynInfo( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetWscRegsDynInfo( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +BOOLEAN WscCheckEnrolleeNonceFromUpnp( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING pData, + IN USHORT Length, + IN PWSC_CTRL pWscControl); + +UCHAR WscRxMsgTypeFromUpnp( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING pData, + IN USHORT Length); + +INT WscGetConfForUpnp( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); + +INT Set_AP_WscConfMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_WscGetConf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_WscSecurityMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AP_WscMultiByteCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_WscVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscUUID_STR_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscUUID_HEX_E_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscSetupLock_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_V2_SUPPORT +INT Set_WscV2Support_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscVersion2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscExtraTlvTag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscExtraTlvType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscExtraTlvData_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscFragment_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscFragmentSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscMaxPinAttack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscSetupLockTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WSC_V2_SUPPORT */ +INT Set_WscAutoTriggerDisable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WSC_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MCAST_RATE_SPECIFIC +INT Set_McastPhyMode(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_McastMcs(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Show_McastRate(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* MCAST_RATE_SPECIFIC */ + +#ifdef DOT11N_DRAFT3 +INT Set_OBSSScanParam_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_AP2040ReScan_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* DOT11N_DRAFT3 */ + +INT Set_EntryLifeCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RTMP_RBUS_SUPPORT +#ifdef LED_CONTROL_SUPPORT +INT Set_WlanLed_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef AP_QLOAD_SUPPORT +INT Set_QloadClr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* QLOAD ALARM */ +INT Set_QloadAlarmTimeThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING Arg); + +INT Set_QloadAlarmNumThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING Arg); +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +INT Set_MemDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef CONFIG_AP_SUPPORT +INT Set_PowerSaveLifeTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_SkipLongRangeVga_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP_DyncVgaEnable_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT set_dynamic_lna_trigger_timer_proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT set_agc_vga_clamp_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_false_cca_hi_th(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_false_cca_low_th(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef AIRPLAY_SUPPORT +INT Set_Airplay_Enable(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* AIRPLAY_SUPPORT */ + +#ifdef ED_MONITOR +//let run-time turn on/off +INT set_ed_chk_proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef CONFIG_AP_SUPPORT +INT set_ed_sta_count_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_ap_count_proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +INT set_ed_ap_scaned_count_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_current_ch_ap_proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* CONFIG_STA_SUPPORT */ +INT set_ed_current_rssi_threhold_proc(RTMP_ADAPTER *pAd, PSTRING arg); + + +INT set_ed_block_tx_thresh(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_false_cca_threshold(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_threshold(RTMP_ADAPTER *pAd, PSTRING arg); +INT show_ed_stat_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_debug_proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* ED_MONITOR */ +INT show_ed_cnt_for_channel_quality(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Enable_Channel_Timer_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef THERMAL_PROTECT_SUPPORT +INT set_thermal_protection_criteria_proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* THERMAL_PROTECT_SUPPORT */ + +static struct { + PSTRING name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); +} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { + {"RateAlg", Set_RateAlg_Proc}, +#ifdef NEW_RATE_ADAPT_SUPPORT + {"PerThrdAdj", Set_PerThrdAdj_Proc}, + {"LowTrafficThrd", Set_LowTrafficThrd_Proc}, + {"TrainUpRule", Set_TrainUpRule_Proc}, + {"TrainUpRuleRSSI", Set_TrainUpRuleRSSI_Proc}, + {"TrainUpLowThrd", Set_TrainUpLowThrd_Proc}, + {"TrainUpHighThrd", Set_TrainUpHighThrd_Proc}, + {"RateTable", Set_RateTable_Proc}, +#endif /* NEW_RATE_ADAPT_SUPPORT */ + {"DriverVersion", Set_DriverVersion_Proc}, + {"CountryRegion", Set_CountryRegion_Proc}, + {"CountryRegionABand", Set_CountryRegionABand_Proc}, + {"CountryString", Set_CountryString_Proc}, + {"CountryCode", Set_CountryCode_Proc}, +#ifdef EXT_BUILD_CHANNEL_LIST + {"ChGeography", Set_ChGeography_Proc}, +#endif /* EXT_BUILD_CHANNEL_LIST */ +#ifdef SMART_MESH_MONITOR + // Set the address of monitered STA. 2013.11.29 Annie. + {"mnt_en", Set_Enable_Monitor_Proc}, + {"mnt_sta", Set_MonitorTarget_Proc}, + {"mnt_idx", Set_MonitorIndex_Proc}, + {"mnt_show", Set_MonitorShowAll_Proc}, + {"mnt_clr", Set_MonitorClearCounter_Proc}, + {"mnt_sta0", Set_MonitorTarget0_Proc}, + {"mnt_sta1", Set_MonitorTarget1_Proc}, + {"mnt_sta2", Set_MonitorTarget2_Proc}, + {"mnt_sta3", Set_MonitorTarget3_Proc}, + {"mnt_sta4", Set_MonitorTarget4_Proc}, + {"mnt_sta5", Set_MonitorTarget5_Proc}, + {"mnt_sta6", Set_MonitorTarget6_Proc}, +#endif /* SMART_MESH_MONITOR */ +#ifdef SMART_MESH + {"ApSmartMesh", Set_Ap_SmartMesh_Proc}, +#ifdef MWDS + {"ApDWDS", Set_Ap_DWDS_Proc}, +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + {"ApHiddenWPS", Set_Ap_HiddenWPS_Proc}, +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + {"APSmartMeshACL", Set_Ap_SmartMesh_ACL_Proc}, + {"SmartMeshIe", Set_SmartMesh_IE_Proc}, + {"SmIeCtrl", Set_SmartMesh_IE_Crtl_Proc}, + {"SmUniProbeReqSSID", Set_SmartMesh_Unicast_ProbeReq_SSID_Proc}, + {"SmUniProbeReqSend", Set_SmartMesh_Unicast_ProbeReq_Send_Proc}, + {"SmDfsScanEnable", Set_SmartMesh_DFSScanAP_Enable_Proc}, + {"SmHyperFiFilter", Set_SmartMesh_HyperFiPeer_Filter_Proc}, + {"SmHyperFiFlagMask", Set_SmartMesh_HyperFiFlagMask_Proc}, + {"SmHyperFiFlagValue", Set_SmartMesh_HyperFiFlagValue_Proc}, + {"LastPktStatEnable", Set_Cli_Pkt_Stats_Enable_Proc}, + {"LastTxPktStatShow", Set_Cli_Pkt_Stats_TX_Show_Proc}, + {"LastRxPktStatShow", Set_Cli_Pkt_Stats_RX_Show_Proc}, + {"MlmeQueueFullShow", Set_MLME_Queue_Full_Show_Proc}, +#ifdef WSC_AP_SUPPORT + {"SmWscPBCMac", Set_SmartMesh_WscPBCMAC_Proc}, +#endif /* WSC_AP_SUPPORT */ +#endif /* SMART_MESH */ +#ifdef MWDS + {"ApMWDS", Set_Ap_MWDS_Proc}, +#endif /* MWDS */ + {"SSID", Set_AP_SSID_Proc}, + {"WirelessMode", Set_WirelessMode_Proc}, + {"BasicRate", Set_BasicRate_Proc}, + {"ShortSlot", Set_ShortSlot_Proc}, + {"Channel", Set_Channel_Proc}, +#ifdef DOT11_VHT_AC + {"en2g256qam", Set_2G_256QAM_Proc}, +#endif /* DOT11_VHT_AC */ + +#ifdef DELAYED_TCP_ACK + {"enackq", Set_ACKQ_Proc}, + {"clearackq", Set_CACKQ_Proc}, + {"ackwait", Set_ACKWait_Proc}, + {"acklen", Set_ACKLen_Proc}, + {"show_ackq", Set_ShowACKQParm_Proc}, +#endif /* DELAYED_TCP_ACK */ + + {"BeaconPeriod", Set_BeaconPeriod_Proc}, + {"DtimPeriod", Set_DtimPeriod_Proc}, + {"TxPower", Set_TxPower_Proc}, + {"BGProtection", Set_BGProtection_Proc}, + {"DisableOLBC", Set_OLBCDetection_Proc}, + {"TxPreamble", Set_TxPreamble_Proc}, + {"RTSThreshold", Set_RTSThreshold_Proc}, + {"FragThreshold", Set_FragThreshold_Proc}, + {"TxBurst", Set_TxBurst_Proc}, + {"MaxStaNum", Set_AP_MaxStaNum_Proc}, +#ifdef RTMP_MAC_PCI + {"ShowRF", Set_ShowRF_Proc}, +#endif /* RTMP_MAC_PCI */ + {"IdleTimeout", Set_AP_IdleTimeout_Proc}, +#ifdef DOT11_N_SUPPORT + {"BASetup", Set_BASetup_Proc}, + {"BADecline", Set_BADecline_Proc}, + {"SendMIMOPS", Set_SendSMPSAction_Proc}, + {"BAOriTearDown", Set_BAOriTearDown_Proc}, + {"BARecTearDown", Set_BARecTearDown_Proc}, + {"HtBw", Set_HtBw_Proc}, + {"HtMcs", Set_HtMcs_Proc}, + {"HtGi", Set_HtGi_Proc}, + {"HtOpMode", Set_HtOpMode_Proc}, + {"HtStbc", Set_HtStbc_Proc}, + {"HtHtc", Set_HtHtc_Proc}, + {"HtExtcha", Set_HtExtcha_Proc}, + {"HtMpduDensity", Set_HtMpduDensity_Proc}, + {"HtBaWinSize", Set_HtBaWinSize_Proc}, + {"HtMIMOPS", Set_HtMIMOPSmode_Proc}, + {"HtRdg", Set_HtRdg_Proc}, + {"HtLinkAdapt", Set_HtLinkAdapt_Proc}, + {"HtAmsdu", Set_HtAmsdu_Proc}, + {"HtAutoBa", Set_HtAutoBa_Proc}, + {"HtProtect", Set_HtProtect_Proc}, + {"HtMimoPs", Set_HtMimoPs_Proc}, + {"HtTxStream", Set_HtTxStream_Proc}, + {"HtRxStream", Set_HtRxStream_Proc}, + {"ForceShortGI", Set_ForceShortGI_Proc}, + {"ForceGF", Set_ForceGF_Proc}, + {"HtTxBASize", Set_HtTxBASize_Proc}, + {"BurstMode", Set_BurstMode_Proc}, +#ifdef GREENAP_SUPPORT + {"GreenAP", Set_GreenAP_Proc}, +#endif /* GREENAP_SUPPORT */ + {"HtDisallowTKIP", Set_HtDisallowTKIP_Proc}, +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + {"VhtBw", Set_VhtBw_Proc}, + {"VhtStbc", Set_VhtStbc_Proc}, + {"VhtBwSignal", set_VhtBwSignal_Proc}, + {"VhtDisallowNonVHT", Set_VhtDisallowNonVHT_Proc}, +#endif /* DOT11_VHT_AC */ + +#ifdef IAPP_SUPPORT + {"IappPID", Set_IappPID_Proc}, +#endif /* IAPP_SUPPORT */ + +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Set_PktAggregate_Proc}, +#endif /* AGGREGATION_SUPPORT */ + +#ifdef INF_PPA_SUPPORT + {"INF_AMAZON_SE_PPA", Set_INF_AMAZON_SE_PPA_Proc}, +#endif /* INF_PPA_SUPPORT */ + +#ifdef WMM_SUPPORT + {"WmmCapable", Set_AP_WmmCapable_Proc}, +#endif /* WMM_SUPPORT */ + {"NoForwarding", Set_NoForwarding_Proc}, + {"NoForwardingBTNBSSID", Set_NoForwardingBTNSSID_Proc}, + {"NoForwardingMBCast", Set_NoForwardingMBCast_Proc}, + {"HideSSID", Set_HideSSID_Proc}, + {"IEEE80211H", Set_IEEE80211H_Proc}, + {"VLANID", Set_VLANID_Proc}, + {"VLANPriority", Set_VLANPriority_Proc}, + {"VLANTag", Set_VLAN_TAG_Proc}, + {"AuthMode", Set_AP_AuthMode_Proc}, + {"EncrypType", Set_AP_EncrypType_Proc}, + {"WpaMixPairCipher", Set_AP_WpaMixPairCipher_Proc}, + {"RekeyInterval", Set_AP_RekeyInterval_Proc}, + {"RekeyMethod", Set_AP_RekeyMethod_Proc}, + {"DefaultKeyID", Set_AP_DefaultKeyID_Proc}, + {"Key1", Set_AP_Key1_Proc}, + {"Key2", Set_AP_Key2_Proc}, + {"Key3", Set_AP_Key3_Proc}, + {"Key4", Set_AP_Key4_Proc}, + {"AccessPolicy", Set_AccessPolicy_Proc}, + {"ACLAddEntry", Set_ACLAddEntry_Proc}, + {"ACLDelEntry", Set_ACLDelEntry_Proc}, + {"ACLShowAll", Set_ACLShowAll_Proc}, + {"ACLClearAll", Set_ACLClearAll_Proc}, + {"WPAPSK", Set_AP_WPAPSK_Proc}, + {"RadioOn", Set_RadioOn_Proc}, +#ifdef SPECIFIC_TX_POWER_SUPPORT + {"PktPwr", Set_AP_PKT_PWR}, +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + {"ApProbeRspTimes", Set_AP_PROBE_RSP_TIMES}, + {"AuthRspFail", Set_AP_AUTH_FAIL_RSSI_THRESHOLD}, + {"AuthRspRssi", Set_AP_AUTH_NO_RSP_RSSI_THRESHOLD}, + {"AssocReqRssiThres", Set_AP_ASSOC_REQ_FAIL_RSSI_THRESHOLD}, + {"AssocRspIgnor", Set_AP_ASSOC_REQ_NO_RSP_RSSI_THRESHOLD}, + {"KickStaRssiLow", Set_AP_KickStaRssiLow_Proc}, + {"ProbeRspRssi", Set_AP_PROBE_RSSI_THRESHOLD}, + {"FilterUnused", Set_AP_PACKET_FILTER_Proc}, +#ifdef AP_SCAN_SUPPORT + {"SiteSurvey", Set_SiteSurvey_Proc}, + {"AutoChannelSel", Set_AutoChannelSel_Proc}, +#ifdef CUSTOMER_DCC_FEATURE + {"ApScanChannel", Set_ApScan_Proc}, + {"ApDisableSTAConnect", Set_ApDisableSTAConnect_Proc}, + {"ApEnableRadioChStats", Set_ApEnableRadioChStats}, + {"ApEnableBeaconTable", Set_ApEnableBeaconTable_Proc}, + {"ApChannelSwitch", Set_ApChannelSwitch_Proc}, +#endif +#ifdef AP_PARTIAL_SCAN_SUPPORT + {"PartialScan", Set_PartialScan_Proc}, +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + {"ACSCheckTime", Set_AutoChannelSelCheckTime_Proc}, +#endif /* AP_SCAN_SUPPORT */ + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"DisConnectSta", Set_DisConnectSta_Proc}, + {"DisConnectAllSta", Set_DisConnectAllSta_Proc}, +#ifdef DOT1X_SUPPORT + {"IEEE8021X", Set_IEEE8021X_Proc}, + {"PreAuth", Set_PreAuth_Proc}, + {"PMKCachePeriod", Set_AP_PMKCachePeriod_Proc}, + {"own_ip_addr", Set_OwnIPAddr_Proc}, + {"EAPifname", Set_EAPIfName_Proc}, + {"PreAuthifname", Set_PreAuthIfName_Proc}, + {"RADIUS_Server", Set_RADIUS_Server_Proc}, + {"RADIUS_Port", Set_RADIUS_Port_Proc}, + {"RADIUS_Key", Set_RADIUS_Key_Proc}, +#endif /* DOT1X_SUPPORT */ +#ifdef DBG + {"Debug", Set_Debug_Proc}, + {"DebugFunc", Set_DebugFunc_Proc}, +#endif /* DBG */ + +#if defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) + {"RadarShow", Set_RadarShow_Proc}, +#ifdef DFS_SUPPORT + {"RadarDebug", Set_RadarDebug_Proc}, + /*{"RadarHit", Set_RadarHit_Proc},*/ + {"CSPeriod", Set_CSPeriod_Proc}, + {"ResetRadarHwDetect", Set_ResetRadarHwDetect_Proc}, + {"DfsSwDisable", Set_DfsSwDisable_Proc}, + {"DfsEvDropAdjTime", Set_DfsEnvtDropAdjTime_Proc}, + {"RadarStart", Set_RadarStart_Proc}, + {"RadarStop", Set_RadarStop_Proc}, + {"RadarT1", Set_RadarSetTbl1_Proc}, + {"RadarT2", Set_RadarSetTbl2_Proc}, + {"PollTime", Set_PollTime_Proc}, + {"PrintBusyIdle", Set_PrintBusyIdle_Proc}, + {"BusyIdleRatio", Set_BusyIdleRatio_Proc}, + {"DfsRssiHigh", Set_DfsRssiHigh_Proc}, + {"DfsRssiLow", Set_DfsRssiLow_Proc}, + {"ChMovTime", Set_ChMovingTime_Proc}, + {"BlockChReset", Set_BlockChReset_Proc}, +#ifdef DFS_ATP_SUPPORT + {"DfsAtpStart", Set_DfsAtpStart_Proc}, + {"DfsAtpReset", Set_DfsAtpReset_Proc}, + {"DfsAtpReport", Set_DfsAtpReport_Proc}, +#endif /* DFS_ATP_SUPPORT */ +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + {"CarrierDetect", Set_CarrierDetect_Proc}, + {"CarrierCriteria", Set_CarrierCriteria_Proc}, + {"CarrierReCheck", Set_CarrierReCheck_Proc}, + {"CarrierGoneThreshold", Set_CarrierGoneThreshold_Proc}, + {"CarrierDebug", Set_CarrierDebug_Proc}, + {"Delta", Set_CarrierDelta_Proc}, + {"DivFlag", Set_CarrierDivFlag_Proc}, + {"CarrThrd", Set_CarrierThrd_Proc}, + /* v2 functions */ + {"SymRund", Set_CarrierSymRund_Proc}, + {"CarrMask", Set_CarrierMask_Proc}, +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) */ + + +#ifdef RT6352 + {"RfBankSel", Set_RfBankSel_Proc}, +#ifdef RTMP_TEMPERATURE_CALIBRATION + {"TemperatureInit", Set_TemperatureCAL_Proc}, +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#endif /* RT6352 */ + +#ifdef RALINK_ATE + {"ATE", Set_ATE_Proc}, + {"ATEDA", Set_ATE_DA_Proc}, + {"ATESA", Set_ATE_SA_Proc}, + {"ADCDump", Set_ADCDump_Proc}, + {"ATEBSSID", Set_ATE_BSSID_Proc}, + {"ATECHANNEL", Set_ATE_CHANNEL_Proc}, + {"ATEINITCHAN", Set_ATE_INIT_CHAN_Proc}, +#if defined(RTMP_TEMPERATURE_CALIBRATION) || defined(RTMP_TEMPERATURE_COMPENSATION) + {"ATETEMPCAL", Set_ATE_TEMP_CAL_Proc}, + {"ATESHOWTSSI", Set_ATE_SHOW_TSSI_Proc}, +#endif /* defined(RTMP_TEMPERATURE_CALIBRATION) || defined(RTMP_TEMPERATURE_COMPENSATION) */ +#ifdef RTMP_INTERNAL_TX_ALC + {"ATETSSICBA", Set_ATE_TSSI_CALIBRATION_Proc}, +#if defined(RT3350) || defined(RT3352) + {"ATETSSICALBRENABLE", RT335x_Set_ATE_TSSI_CALIBRATION_ENABLE_Proc}, +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + {"ATETSSICBAEX", Set_ATE_TSSI_CALIBRATION_EX_Proc}, +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + {"ATETXPOW0", Set_ATE_TX_POWER0_Proc}, + {"ATETXPOW1", Set_ATE_TX_POWER1_Proc}, +#ifdef DOT11N_SS3_SUPPORT + {"ATETXPOW2", Set_ATE_TX_POWER2_Proc}, +#endif /* DOT11N_SS3_SUPPORT */ + {"ATETXPOWEVAL", Set_ATE_TX_POWER_EVALUATION_Proc}, + {"ATETXANT", Set_ATE_TX_Antenna_Proc}, + {"ATERXANT", Set_ATE_RX_Antenna_Proc}, +#ifdef RT3350 + {"ATEPABIAS", Set_ATE_PA_Bias_Proc}, +#endif /* RT3350 */ + {"ATETXFREQOFFSET", Set_ATE_TX_FREQ_OFFSET_Proc}, + {"ATETXBW", Set_ATE_TX_BW_Proc}, + {"ATETXLEN", Set_ATE_TX_LENGTH_Proc}, + {"ATETXCNT", Set_ATE_TX_COUNT_Proc}, + {"ATETXMCS", Set_ATE_TX_MCS_Proc}, + {"ATETXSTBC", Set_ATE_TX_STBC_Proc}, + {"ATETXMODE", Set_ATE_TX_MODE_Proc}, + {"ATETXGI", Set_ATE_TX_GI_Proc}, + {"ATERXFER", Set_ATE_RX_FER_Proc}, + {"ATERRF", Set_ATE_Read_RF_Proc}, +#if (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) + {"ATEWRF1", Set_ATE_Write_RF1_Proc}, + {"ATEWRF2", Set_ATE_Write_RF2_Proc}, + {"ATEWRF3", Set_ATE_Write_RF3_Proc}, + {"ATEWRF4", Set_ATE_Write_RF4_Proc}, +#endif /* (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) */ + {"ATELDE2P", Set_ATE_Load_E2P_Proc}, + {"ATERE2P", Set_ATE_Read_E2P_Proc}, +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + {"ATEAUTOALC", Set_ATE_AUTO_ALC_Proc}, + {"ATETEMPSENSOR", Set_ATE_TEMP_SENSOR_Proc}, +#ifdef SINGLE_SKU_V2 + {"ATESINGLESKU", Set_ATE_SINGLE_SKU_Proc}, +#endif +#ifdef VCORECAL_SUPPORT + {"ATEVCOCAL", Set_ATE_VCO_CAL_Proc}, +#endif /* VCORECAL_SUPPORT */ + {"ATEIPG", Set_ATE_IPG_Proc}, + {"ATEPAYLOAD", Set_ATE_Payload_Proc}, + {"ATEFIXEDPAYLOAD", Set_ATE_Fixed_Payload_Proc}, +#ifdef TXBF_SUPPORT + {"ATETXBF", Set_ATE_TXBF_Proc}, + {"ATETXSOUNDING", Set_ATE_TXSOUNDING_Proc}, + {"ATETXBFDIVCAL", Set_ATE_TXBF_DIVCAL_Proc}, + {"ATETXBFLNACAL", Set_ATE_TXBF_LNACAL_Proc}, + {"ATETxBfInit", Set_ATE_TXBF_INIT_Proc}, + + /* iBF external Golden method */ + {"ATETxBfGdCal", Set_ATE_TXBF_Gd_Cal_Proc}, + {"ATETxBfGdVerify", Set_ATE_TXBF_Gd_Verify_Proc}, + {"ATETxBfGdVerifyN", Set_ATE_TXBF_Gd_Verify_NoComp_Proc}, + {"ATETxBfGdCalAndVerify", Set_ATE_TXBF_Gd_Phase_Cal_and_Verify_Proc}, + {"ATETxBfGdCalInitVerify", Set_ATE_TXBF_Gd_Phase_Cal_Init_Verify_Proc}, + {"ATETxBfGdCheckError", Set_ATE_TXBF_Gd_Check_Error_Proc}, + +#ifdef MT76x2 + /* iBF internal loop method */ + {"ATETxBfIntlCal", Set_ATE_TXBF_Intloop_Cal_Proc}, + {"ATETxBfIntlVerify", Set_ATE_TXBF_Intloop_Phase_Verify_Proc}, + {"ATETxBfIntlCalAndVerify", Set_ATE_TXBF_Intloop_Phase_Cal_and_Verify_Proc}, +#endif + {"ATETxBfGolden", Set_ATE_TXBF_GOLDEN_Proc}, // iBF Golden flow + {"ATEForceBBP", Set_ATE_ForceBBP_Proc}, +#endif /* TXBF_SUPPORT */ + {"ATESHOW", Set_ATE_Show_Proc}, + {"ATEHELP", Set_ATE_Help_Proc}, +#ifdef MT76x2 + {"ATEDoCal", Set_ATE_DO_CALIBRATION_Proc}, + {"ATELoadCR", Set_ATE_Load_CR_Proc}, +#endif /* MT76x2 */ +#ifdef RALINK_QA + {"TxStop", Set_TxStop_Proc}, + {"RxStop", Set_RxStop_Proc}, +#ifdef DBG + {"EERead", Set_EERead_Proc}, + {"EEWrite", Set_EEWrite_Proc}, + {"BBPRead", Set_BBPRead_Proc}, + {"BBPWrite", Set_BBPWrite_Proc}, +#endif /* DBG */ +#endif /* RALINK_QA */ +#endif /* RALINK_ATE */ + +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_BW_SUPPORT + {"ApCliBw", Set_ApCli_Bw_Proc}, + {"ApCliPhyMode", Set_ApCli_PhyMode_Proc}, +#endif /* APCLI_AUTO_BW_SUPPORT */ + {"ApCliEnable", Set_ApCli_Enable_Proc}, + {"ApCliSsid", Set_ApCli_Ssid_Proc}, + {"ApCliBssid", Set_ApCli_Bssid_Proc}, + {"ApCliAuthMode", Set_ApCli_AuthMode_Proc}, + {"ApCliEncrypType", Set_ApCli_EncrypType_Proc}, + {"ApCliDefaultKeyID", Set_ApCli_DefaultKeyID_Proc}, + {"ApCliWPAPSK", Set_ApCli_WPAPSK_Proc}, + {"ApCliKey1", Set_ApCli_Key1_Proc}, + {"ApCliKey2", Set_ApCli_Key2_Proc}, + {"ApCliKey3", Set_ApCli_Key3_Proc}, + {"ApCliKey4", Set_ApCli_Key4_Proc}, + {"ApCliTxMode", Set_ApCli_TxMode_Proc}, + {"ApCliTxMcs", Set_ApCli_TxMcs_Proc}, +#ifdef APCLI_CONNECTION_TRIAL + /* + for Trial the root AP which locates on another channel + what if the connection is ok, it will make BSSID switch to the new channel. + */ + {"ApCliTrialCh", Set_ApCli_Trial_Ch_Proc}, +#endif /* APCLI_CONNECTION_TRIAL */ +#ifdef APCLI_AUTO_CONNECT_SUPPORT + {"ApCliAutoConnect", Set_ApCli_AutoConnect_Proc}, + {"ApCliSiteSurveyPeriod", Set_ApCli_SiteSurveyPeriod_Proc}, +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + {"ApCliWpaSupport", Set_ApCli_Wpa_Support}, + {"ApCliIEEE1X", Set_ApCli_IEEE8021X_Proc}, +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + {"MACRepeaterEn", Set_ReptMode_Enable_Proc}, +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef SMART_MESH + {"ApCliSmartMesh", Set_ApCli_SmartMesh_Proc}, +#ifdef MWDS + {"ApCliDWDS", Set_ApCli_DWDS_Proc}, +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + {"ApCliHiddenWPS", Set_ApCli_HiddenWPS_Proc}, +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#endif /* SMART_MESH */ +#ifdef MWDS + {"ApCliMWDS", Set_ApCli_MWDS_Proc}, +#endif /* MWDS */ + +#ifdef WSC_AP_SUPPORT + {"ApCliWscSsid", Set_AP_WscSsid_Proc}, +#endif /* WSC_AP_SUPPORT */ +#ifdef APCLI_CERT_SUPPORT + {"ApCliCertEnable", Set_ApCli_Cert_Enable_Proc}, + {"ApCliWmmEnable", Set_ApCli_WMM_Enable_Proc}, +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#ifdef WSC_AP_SUPPORT + {"WscConfMode", Set_AP_WscConfMode_Proc}, + {"WscConfStatus", Set_AP_WscConfStatus_Proc}, + {"WscMode", Set_AP_WscMode_Proc}, + {"WscStatus", Set_WscStatus_Proc}, + {"WscGetConf", Set_AP_WscGetConf_Proc}, + {"WscPinCode", Set_AP_WscPinCode_Proc}, + {"WscStop", Set_WscStop_Proc}, + {"WscGenPinCode", Set_WscGenPinCode_Proc}, + {"WscVendorPinCode", Set_WscVendorPinCode_Proc}, + {"WscSecurityMode", Set_AP_WscSecurityMode_Proc}, + {"WscMultiByteCheck", Set_AP_WscMultiByteCheck_Proc}, + {"WscVersion", Set_WscVersion_Proc}, + //HEX : 32 Length + {"WscUUID_E", Set_WscUUID_HEX_E_Proc}, + //37 Length + {"WscUUID_Str", Set_WscUUID_STR_Proc}, +#ifdef BB_SOC + {"WscOOB", Set_WscOOB_Proc}, + {"WscResetPinCode", Set_WscResetPinCode_Proc}, +#endif /* BB_SOC */ + {"WscSetupLock", Set_WscSetupLock_Proc}, +#ifdef WSC_V2_SUPPORT + {"WscV2Support", Set_WscV2Support_Proc}, + {"WscVersion2", Set_WscVersion2_Proc}, + {"WscExtraTlvTag", Set_WscExtraTlvTag_Proc}, + {"WscExtraTlvType", Set_WscExtraTlvType_Proc}, + {"WscExtraTlvData", Set_WscExtraTlvData_Proc}, + {"WscFragment", Set_WscFragment_Proc}, + {"WscFragmentSize", Set_WscFragmentSize_Proc}, + {"WscMaxPinAttack", Set_WscMaxPinAttack_Proc}, + {"WscSetupLockTime", Set_WscSetupLockTime_Proc}, +#endif /* WSC_V2_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + {"NfcStatus", Set_NfcStatus_Proc}, + {"NfcPasswdToken", Set_NfcPasswdToken_Proc}, + {"NfcConfigToken", Set_NfcConfigurationToken_Proc}, + {"DoWpsByNFC", Set_DoWpsByNFC_Proc}, + {"NfcRegenPK", Set_NfcRegenPK_Proc}, /* For NFC negative test */ +#endif /* WSC_NFC_SUPPORT */ + {"WscAutoTriggerDisable", Set_WscAutoTriggerDisable_Proc}, +#endif /* WSC_AP_SUPPORT */ +#ifdef UAPSD_SUPPORT + {"UAPSDCapable", Set_UAPSD_Proc}, +#endif /* UAPSD_SUPPORT */ +#ifdef IGMP_SNOOP_SUPPORT + {"IgmpSnEnable", Set_IgmpSn_Enable_Proc}, + {"IgmpAdd", Set_IgmpSn_AddEntry_Proc}, + {"IgmpDel", Set_IgmpSn_DelEntry_Proc}, +#endif /* IGMP_SNOOP_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +#ifdef MCAST_RATE_SPECIFIC + {"McastPhyMode", Set_McastPhyMode}, + {"McastMcs", Set_McastMcs}, +#endif /* MCAST_RATE_SPECIFIC */ +#endif /* CONFIG_AP_SUPPORT */ + {"FixedTxMode", Set_FixedTxMode_Proc}, +#ifdef CONFIG_APSTA_MIXED_SUPPORT + {"OpMode", Set_OpMode_Proc}, +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +#ifdef TXBF_SUPPORT +#ifndef MT76x2 + {"TxBfTag", Set_TxBfTag_Proc}, + {"ReadITxBf", Set_ReadITxBf_Proc}, + {"WriteITxBf", Set_WriteITxBf_Proc}, + {"StatITxBf", Set_StatITxBf_Proc}, + {"ReadETxBf", Set_ReadETxBf_Proc}, + {"WriteETxBf", Set_WriteETxBf_Proc}, + {"StatETxBf", Set_StatETxBf_Proc}, + {"ITxBfTimeout", Set_ITxBfTimeout_Proc}, + {"ETxBfTimeout", Set_ETxBfTimeout_Proc}, + {"ITxBfCal", Set_ITxBfCal_Proc}, + {"ITxBfLnaCal", Set_ITxBfLnaCal_Proc}, +#endif + {"InvTxBfTag", Set_InvTxBfTag_Proc}, + {"ITxBfDivCal", Set_ITxBfDivCal_Proc}, + + {"ITxBfEn", Set_ITxBfEn_Proc}, + {"ITxBfCalibMode", Set_ITxBf_Calib_Mode_Proc}, + {"ETxBfEnCond", Set_ETxBfEnCond_Proc}, + //{"ETxBfEnCondApCli", Set_ETxBfEnCond_ApCliProc}, + {"ETxBfCodebook", Set_ETxBfCodebook_Proc}, + {"ETxBfCoefficient", Set_ETxBfCoefficient_Proc}, + {"ETxBfGrouping", Set_ETxBfGrouping_Proc}, + {"ETxBfNoncompress", Set_ETxBfNoncompress_Proc}, + {"ETxBfIncapable", Set_ETxBfIncapable_Proc}, + {"NoSndgCntThrd", Set_NoSndgCntThrd_Proc}, + {"NdpSndgStreams", Set_NdpSndgStreams_Proc}, + {"TriggerSounding", Set_Trigger_Sounding_Proc}, + +#ifdef MT76x2 + {"TxBfProfileTagHelp", Set_TxBfProfileTag_Help}, + {"TxBfProfileTagValid", Set_TxBfProfileTagValid}, + {"TxBfProfileTagTimeOut", Set_TxBfProfileTag_TimeOut}, + {"TxBfProfileTagMatrix", Set_TxBfProfileTag_Matrix}, + {"TxBfProfileTagSNR", Set_TxBfProfileTag_SNR}, + {"TxBfProfileTagTxScale", Set_TxBfProfileTag_TxScale}, + {"TxBfProfileTagMac", Set_TxBfProfileTag_MAC}, + {"TxBfProfileTagFlg", Set_TxBfProfileTag_Flg}, + {"TxBfProfileTagRead", Set_TxBfProfileTagRead}, + {"TxBfProfileTagWrite", Set_TxBfProfileTagWrite}, + {"TxBfProfileDataRead", Set_TxBfProfileDataRead}, + {"TxBfProfileDataWrite", Set_TxBfProfileDataWrite}, + {"TxBfProfileDataReadAll", Set_TxBfProfileDataReadAll}, + {"TxBfProfileDataWriteAll",Set_TxBfProfileDataWriteAll}, +#endif + +#endif /* TXBF_SUPPORT */ +#ifdef VHT_TXBF_SUPPORT + {"VhtNDPA", Set_VhtNDPA_Sounding_Proc}, +#endif /* VHT_TXBF_SUPPORT */ + +#if defined (CONFIG_WIFI_PKT_FWD) + {"wf_fwd", Set_WifiFwd_Proc}, + {"wf_fwd_acs", Set_WifiFwdAccessSchedule_Proc}, + {"wf_fwd_hij", Set_WifiFwdHijack_Proc}, + {"wf_fwd_rep", Set_WifiFwdRepDevice}, + {"wf_fwd_show", Set_WifiFwdShowEntry}, + {"wf_fwd_del", Set_WifiFwdDeleteEntry}, + {"pkt_src_show", Set_PacketSourceShowEntry}, + {"pkt_src_del", Set_PacketSourceDeleteEntry}, +#endif /* CONFIG_WIFI_PKT_FWD */ + + +#ifdef PRE_ANT_SWITCH + {"PreAntSwitch", Set_PreAntSwitch_Proc}, + {"PreAntSwitchRSSI", Set_PreAntSwitchRSSI_Proc}, + {"PreAntSwitchTimeout", Set_PreAntSwitchTimeout_Proc}, +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK + {"CFOTrack", Set_CFOTrack_Proc}, +#endif /* CFO_TRACK */ + +#ifdef STREAM_MODE_SUPPORT + {"StreamMode", Set_StreamMode_Proc}, + {"StreamModeMac", Set_StreamModeMac_Proc}, + {"StreamModeMCS", Set_StreamModeMCS_Proc}, +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + {"DebugFlags", Set_DebugFlags_Proc}, +#ifdef INCLUDE_DEBUG_QUEUE + {"DebugQueue", Set_DebugQueue_Proc}, +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + {"LongRetry", Set_LongRetryLimit_Proc}, + {"ShortRetry", Set_ShortRetryLimit_Proc}, + {"AutoFallBack", Set_AutoFallBack_Proc}, +#ifdef RTMP_MAC_PCI +#ifdef DBG_DIAGNOSE + {"DiagOpt", Set_DiagOpt_Proc}, + {"BDInfo", Set_BDInfo_Proc}, +#endif /* DBG_DIAGNOSE */ +#endif /* RTMP_MAC_PCI */ + + {"MeasureReq", Set_MeasureReq_Proc}, + {"TpcReq", Set_TpcReq_Proc}, + {"PwrConstraint", Set_PwrConstraint}, +#ifdef DOT11K_RRM_SUPPORT + {"BcnReq", Set_BeaconReq_Proc}, + {"LinkReq", Set_LinkMeasureReq_Proc}, + {"RrmEnable", Set_Dot11kRRM_Enable_Proc}, + {"TxReq", Set_TxStreamMeasureReq_Proc}, + + /* only for voice enterprise power constraint testing. */ + {"vopwrc", Set_VoPwrConsTest}, + + /* only for selftesting and debugging. */ + {"rrm", Set_RRM_Selftest_Proc}, +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef DOT11V_WNM_SUPPORT +/* {"WnmMaxIdlePeriod", Set_WnmMaxIdlePeriod_Proc}, */ + {"WNMTransMantREQ", Set_WNMTransMantREQ_Proc}, + {"APWNMDMSShow", Set_APWNMDMSShow_Proc}, +#endif /* DOT11V_WNM_SUPPORT */ +#ifdef DOT11N_DRAFT3 + {"OBSSScanParam", Set_OBSSScanParam_Proc}, + {"AP2040Rescan", Set_AP2040ReScan_Proc}, + {"HtBssCoex", Set_HT_BssCoex_Proc}, + {"HtBssCoexApCntThr", Set_HT_BssCoexApCntThr_Proc}, +#endif /* DOT11N_DRAFT3 */ + {"EntryLifeCheck", Set_EntryLifeCheck_Proc}, +#ifdef DOT11R_FT_SUPPORT + {"ft", FT_Ioctl}, + {"ftenable", Set_FT_Enable}, + {"ftmdid", Set_FT_Mdid}, + {"ftr0khid", Set_FT_R0khid}, + {"ftric", Set_FT_RIC}, + {"ftotd", Set_FT_OTD}, +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef RTMP_EFUSE_SUPPORT + {"efuseLoadFromBin", set_eFuseLoadFromBin_Proc}, /* For backward compatible, the usage is the same as bufferLoadFromBin + bufferWriteBack */ + {"efuseFreeNumber", set_eFuseGetFreeBlockCount_Proc}, + {"efuseDump", set_eFusedump_Proc}, +#ifdef RALINK_ATE + {"bufferLoadFromEfuse", Set_LoadEepromBufferFromEfuse_Proc}, + {"efuseBufferModeWriteBack", set_eFuseBufferModeWriteBack_Proc}, /* For backward compatible, the usage is the same as bufferWriteBack */ +#endif /* RALINK_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ +#if defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) + {"bufferLoadFromFlash", Set_LoadEepromBufferFromFlash_Proc}, +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + {"bufferLoadFromBin", Set_LoadEepromBufferFromBin_Proc}, + {"bufferWriteBack", Set_EepromBufferWriteBack_Proc}, + + + +#ifdef RTMP_RBUS_SUPPORT +#ifdef LED_CONTROL_SUPPORT + {"WlanLed", Set_WlanLed_Proc}, +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef AP_QLOAD_SUPPORT + {"qloadclr", Set_QloadClr_Proc}, + {"qloadalarmtimethres", Set_QloadAlarmTimeThreshold_Proc}, /* QLOAD ALARM */ + {"qloadalarmnumthres", Set_QloadAlarmNumThreshold_Proc}, /* QLOAD ALARM */ +#endif /* AP_QLOAD_SUPPORT */ + + {"ra_interval", Set_RateAdaptInterval}, + + + {"memdebug", Set_MemDebug_Proc}, + +#ifdef CONFIG_AP_SUPPORT + {"pslifetime", Set_PowerSaveLifeTime_Proc}, + +#ifdef MBSS_SUPPORT + {"MBSSWirelessMode", Set_MBSS_WirelessMode_Proc}, +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + {"VcoPeriod", Set_VcoPeriod_Proc}, +#ifdef CONFIG_SNIFFER_SUPPORT + {"MonitorMode", Set_MonitorMode_Proc}, +#endif /* CONFIG_SNIFFER_SUPPORT */ +#ifdef SINGLE_SKU + {"ModuleTxpower", Set_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ + +#ifdef RT6352 + {"TestDPDCalibration", Set_TestDPDCalibration_Proc}, + {"TestDPDCalibrationTX0", Set_TestDPDCalibrationTX0_Proc}, + {"TestDPDCalibrationTX1", Set_TestDPDCalibrationTX1_Proc}, +#endif /* RT6352 */ + +#ifdef DOT11W_PMF_SUPPORT + {"PMFMFPC", Set_PMFMFPC_Proc}, + {"PMFMFPR", Set_PMFMFPR_Proc}, + {"PMFSHA256", Set_PMFSHA256_Proc}, +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef MICROWAVE_OVEN_SUPPORT + {"MO_FalseCCATh", Set_MO_FalseCCATh_Proc}, +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + {"fpga_on", set_fpga_mode}, /* 1 = manual mode, 2 = fix phy/mode/rate/mcs */ + {"dataphy", set_data_phy_mode}, /* 0 = CCK, 1 = OFDM, 2 = MODE_HTMIX, 3 = HT-GF, 4 = VHT */ + {"databw", set_data_bw}, /* 0 = 20M, 1 = 40M, 2 = 80M */ + {"datamcs", set_data_mcs}, /* 0~ 15 */ + {"databasize", set_data_basize}, + {"datagi", set_data_gi}, + {"dataldpc", set_data_ldpc}, + {"txcnt", set_tx_kickcnt}, + {"stop_tr", set_tr_stop}, + {"vco_cal", set_vco_cal}, +#ifdef CAPTURE_MODE + {"cap_start", set_cap_start}, + {"cap_trigger", set_cap_trigger}, + {"cap_dump", set_cap_dump}, +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ +#ifdef WFA_VHT_PF + {"force_op", set_force_operating_mode}, + {"force_amsdu", set_force_amsdu}, + {"force_noack", set_force_noack}, + {"force_vht_sgi", set_force_vht_sgi}, + {"force_vht_stbc", set_force_vht_tx_stbc}, + {"ext_cca", set_force_ext_cca}, +#endif /* WFA_VHT_PF */ + {"rf", set_rf}, + {"rt_bit", set_rf_bit}, + {"tssi_enable", set_tssi_enable}, +#ifdef CONFIG_WIFI_TEST + {"pbf_loopback", set_pbf_loopback}, + {"pbf_rx_drop", set_pbf_rx_drop}, +#endif + +#ifdef DYNAMIC_VGA_SUPPORT + {"DyncVgaEnable", Set_AP_DyncVgaEnable_Proc}, + {"VgaClamp", set_agc_vga_clamp_proc}, + {"SkipLongRangeVga", Set_SkipLongRangeVga_Proc}, + {"lna_timer", set_dynamic_lna_trigger_timer_proc}, + {"fc_hth", set_false_cca_hi_th}, + {"fc_lth", set_false_cca_low_th}, +#endif /* DYNAMIC_VGA_SUPPORT */ +#ifdef AIRPLAY_SUPPORT + {"airplayEnable", Set_Airplay_Enable}, +#endif /* AIRPLAY_SUPPORT */ + + {"manual_txop_thld", SetManualTxOPThreshold}, + {"manual_txop_upbound", SetManualTxOPUpBound}, + {"manual_txop_lowbound", SetManualTxOPLowBound}, + +#ifdef CONFIG_ANDES_SUPPORT + {"fw_debug", set_fw_debug}, +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef RTMP_PCI_SUPPORT + {"cpu_int_analysis", set_cpu_int_analysis}, +#ifdef DMA_BUSY_RESET + {"pdma_dbg", Set_PDMAWatchDog_Proc}, + {"WlanResetB", Set_WlanResetB_Proc}, +#endif /* DMA_BUSY_RESET */ +#endif + {"cal_test", set_cal_test}, +#ifdef ED_MONITOR + //let run-time turn on/off + {"ed_chk", set_ed_chk_proc}, + +#ifdef CONFIG_AP_SUPPORT + {"ed_sta_th", set_ed_sta_count_proc}, + {"ed_ap_th", set_ed_ap_count_proc}, +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + {"ed_ap_scaned_th", set_ed_ap_scaned_count_proc}, + {"ed_current_ch_ap_th", set_ed_current_ch_ap_proc}, +#endif /* CONFIG_STA_SUPPORT */ + {"ed_current_rssi_th", set_ed_current_rssi_threhold_proc}, + {"ed_th", set_ed_threshold}, + {"ed_false_cca_th", set_ed_false_cca_threshold}, + {"ed_blk_cnt", set_ed_block_tx_thresh}, + {"ed_stat", show_ed_stat_proc}, + {"ed_debug", set_ed_debug_proc}, +#endif /* ED_MONITOR */ + {"ed_count_show", show_ed_cnt_for_channel_quality}, + {"chtimer_en", Set_Enable_Channel_Timer_Proc}, +#ifdef RT_CFG80211_SUPPORT + {"DisableCfg2040Scan", Set_DisableCfg2040Scan_Proc}, +#endif /* RT_CFG80211_SUPPORT */ +#ifdef THERMAL_PROTECT_SUPPORT + {"tpc", set_thermal_protection_criteria_proc}, +#endif /* THERMAL_PROTECT_SUPPORT */ +#ifdef MT76x2 + {"obtw", set_obtw_delta_proc}, + {"obtw_debug", set_obtw_debug_proc}, +#endif /* MT76x2 */ +#ifdef BAND_STEERING + {"BndStrgEnable", Set_BndStrg_Enable}, + {"BndStrgRssiDiff", Set_BndStrg_RssiDiff}, + {"BndStrgRssiLow", Set_BndStrg_RssiLow}, + {"BndStrgAge", Set_BndStrg_Age}, + {"BndStrgHoldTime", Set_BndStrg_HoldTime}, + {"BndStrgCheckTime", Set_BndStrg_CheckTime5G}, + {"BndStrgCndChk", Set_BndStrg_CndChkFlag}, + {"BndStrgFrmChk", Set_BndStrg_FrmChkFlag}, +#ifdef BND_STRG_DBG + {"BndStrgMntAddr", Set_BndStrg_MonitorAddr}, +#endif /* BND_STRG_DBG */ +#endif /* BAND_STEERING */ +#ifdef SINGLE_SKU_V2 + {"sku_debug", Set_Single_Sku_Debug_Proc}, +#endif + {"pwr_com", set_power_compensate}, + {NULL,} +}; + + +static struct { + PSTRING name; + INT (*set_proc)(RTMP_ADAPTER *pAd, PSTRING arg); +} *PRTMP_PRIVATE_SHOW_PROC, RTMP_PRIVATE_SHOW_SUPPORT_PROC[] = { + {"stainfo", Show_MacTable_Proc}, + {"stacountinfo", Show_StaCount_Proc}, + {"stasecinfo", Show_StaSecurityInfo_Proc}, + {"linkinfo", Show_LinkInfo_Proc}, + {"rtsinfo", Show_RtsInfo_Proc}, + {"chtime", Show_ChannelTimeInfo_Proc}, + {"descinfo", Show_DescInfo_Proc}, + {"driverinfo", Show_DriverInfo_Proc}, + {"devinfo", show_devinfo_proc}, + {"sysinfo", show_sysinfo_proc}, + {"trinfo", show_trinfo_proc}, + {"pwrinfo", show_pwr_info}, + {"txinfo", Show_TxInfo_Proc}, + +#ifdef WDS_SUPPORT + {"wdsinfo", Show_WdsTable_Proc}, +#endif /* WDS_SUPPORT */ +#ifdef DOT11_N_SUPPORT + {"bainfo", Show_BaTable_Proc}, +#endif /* DOT11_N_SUPPORT */ + {"stat", Show_Sat_Proc}, +#ifdef DBG_DIAGNOSE + {"diag", Show_Diag_Proc}, +#endif /* DBG_DIAGNOSE */ + {"stat_reset", Show_Sat_Reset_Proc}, +#ifdef IGMP_SNOOP_SUPPORT + {"igmpinfo", Set_IgmpSn_TabDisplay_Proc}, +#endif /* IGMP_SNOOP_SUPPORT */ +#ifdef MCAST_RATE_SPECIFIC + {"mcastrate", Show_McastRate}, +#endif /* MCAST_RATE_SPECIFIC */ +#ifdef MAT_SUPPORT + {"matinfo", Show_MATTable_Proc}, +#endif /* MAT_SUPPORT */ +#ifdef DFS_SUPPORT + {"blockch", Show_BlockCh_Proc}, +#endif /* DFS_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT + {"ftinfo", Show_FTConfig_Proc}, +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11K_RRM_SUPPORT + {"rrminfo", RRM_InfoDisplay_Proc}, +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef AP_QLOAD_SUPPORT + {"qload", Show_QoSLoad_Proc}, +#endif /* AP_QLOAD_SUPPORT */ +#ifdef APCLI_SUPPORT + {"connStatus", RTMPIoctlConnStatus}, +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + {"reptinfo", Show_Repeater_Cli_Proc}, + {"reptdumpinfo", Show_Repeater_Cli_Dump_Proc}, +#endif /* MAC_REPEATER_SUPPORT */ + + {"rainfo", Show_RAInfo_Proc}, + +#ifdef MBSS_SUPPORT + {"mbss", Show_MbssInfo_Display_Proc}, +#endif /* MBSS_SUPPORT */ +#ifdef WSC_AP_SUPPORT + {"WscPeerList", WscApShowPeerList}, +#ifdef WSC_NFC_SUPPORT + {"NfcStatus", Get_NfcStatus_Proc}, +#endif /* WSC_NFC_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ +#ifdef CONFIG_CALIBRATION_COLLECTION + {"calinfo", Show_Cal_Info}, +#endif +#ifdef BAND_STEERING + {"BndStrgList", Show_BndStrg_List}, + {"BndStrgInfo", Show_BndStrg_Info}, +#endif /* BAND_STEERING */ +#ifdef SMART_MESH + {"ApSmartMesh", Set_Ap_SmartMesh_Show_Proc}, + {"ApCliSmartMesh", Set_ApCli_SmartMesh_Show_Proc}, + {"SmartMeshIe", Set_SmartMesh_IE_Show_Proc}, +#ifdef MAC_REPEATER_SUPPORT + {"vMacPrefix", Set_vMacPrefix_Show_Proc}, +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef MWDS + {"ApMWDS", Set_Ap_MWDS_Show_Proc}, + {"ApCliMWDS", Set_ApCli_MWDS_Show_Proc}, + {"APProxyStatus", Set_APProxy_Status_Show_Proc}, +#endif /* MWDS */ + {"CliStatus", Set_Cli_Status_Show_Proc}, + {"SmDfsScanAp", Set_SmartMesh_DFSScanAP_Show_Proc}, +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + {"ApHiddenWPS", Set_Ap_HiddenWPS_Show_Proc}, + {"ApCliHiddenWPS", Set_ApCli_HiddenWPS_Show_Proc}, +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#endif /* SMART_MESH */ + {NULL,} +}; + + +INT RTMPAPPrivIoctlSet( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr) +{ + PSTRING this_char; + PSTRING value; + INT Status = NDIS_STATUS_SUCCESS; + + while ((this_char = strsep((char **)&pIoctlCmdStr->u.data.pointer, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value +#ifdef WSC_AP_SUPPORT + && ( + (strcmp(this_char, "WscStop") != 0) && +#ifdef BB_SOC + (strcmp(this_char, "WscResetPinCode") != 0) && +#endif + (strcmp(this_char, "WscGenPinCode")!= 0) + ) +#endif /* WSC_AP_SUPPORT */ + ) + continue; + + for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) + { + if (!strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name)) + { + if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAd, value)) + { /*FALSE:Set private failed then return Invalid argument */ + Status = -EINVAL; + } + break; /*Exit for loop. */ + } + } + + if(PRTMP_PRIVATE_SET_PROC->name == NULL) + { /*Not found argument */ + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::(iwpriv) Command not Support [%s=%s]\n", this_char, value)); + break; + } + } + + return Status; +} + + +INT RTMPAPPrivIoctlShow( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr) +{ + PSTRING this_char; + PSTRING value = NULL; + INT Status = NDIS_STATUS_SUCCESS; + + while ((this_char = strsep((char **)&pIoctlCmdStr->u.data.pointer, ",")) != NULL) + { + if (!*this_char) + continue; + + for (PRTMP_PRIVATE_SHOW_PROC = RTMP_PRIVATE_SHOW_SUPPORT_PROC; PRTMP_PRIVATE_SHOW_PROC->name; PRTMP_PRIVATE_SHOW_PROC++) + { + if (!strcmp(this_char, PRTMP_PRIVATE_SHOW_PROC->name)) + { + if(!PRTMP_PRIVATE_SHOW_PROC->set_proc(pAd, value)) + { /*FALSE:Set private failed then return Invalid argument */ + Status = -EINVAL; + } + break; /*Exit for loop. */ + } + } + + if(PRTMP_PRIVATE_SHOW_PROC->name == NULL) + { /*Not found argument */ + Status = -EINVAL; +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { + for (PRTMP_PRIVATE_SHOW_PROC = RTMP_PRIVATE_SHOW_SUPPORT_PROC; PRTMP_PRIVATE_SHOW_PROC->name; PRTMP_PRIVATE_SHOW_PROC++) + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", PRTMP_PRIVATE_SHOW_PROC->name)); + } +#endif /* RTMP_RBUS_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::(iwpriv) Command not Support [%s=%s]\n", this_char, value)); + break; + } + } + + return Status; + +} + + +#define ASSO_MAC_LINE_LEN (1+19+4+4+4+4+8+7+7+7+10+6+6+6+6+7+7+7+1) +VOID RTMPAPGetAssoMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UINT32 DataRate=0; + + INT i; + char *msg; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*ASSO_MAC_LINE_LEN)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*ASSO_MAC_LINE_LEN ); + + sprintf(msg+strlen(msg),"\n%-19s%-4s%-4s%-4s%-4s%-8s", + "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS"); + + if (pAd->CommonCfg.RxStream == 3) + sprintf(msg+strlen(msg),"%-7s%-7s%-7s","RSSI0", "RSSI1","RSSI2"); + else if (pAd->CommonCfg.RxStream == 2) + sprintf(msg+strlen(msg),"%-7s%-7s", "RSSI0", "RSSI1"); + else + sprintf(msg+strlen(msg),"%-7s", "RSSI0"); + + sprintf(msg+strlen(msg),"%-10s%-6s%-6s%-6s%-6s%-7s%-7s%-7s\n", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate", "TIME"); + + + for (i=0; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || (IS_ENTRY_APCLI(pEntry) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + )) + && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+ASSO_MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*ASSO_MAC_LINE_LEN) ) + break; + + DataRate=0; + RtmpDrvRateGet(pAd, pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.BW, pEntry->HTPhyMode.field.MCS, + newRateGetAntenna(pEntry->HTPhyMode.field.MCS, pEntry->HTPhyMode.field.MODE), &DataRate); + DataRate /= 500000; + DataRate /= 2; + + sprintf(msg+strlen(msg),"%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->Addr)); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->apidx); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)); +#ifdef DOT11_N_SUPPORT + sprintf(msg+strlen(msg),"%-8d", (int)pEntry->MmpsMode); +#endif /* DOT11_N_SUPPORT */ + + if (pAd->CommonCfg.RxStream == 3) + sprintf(msg+strlen(msg),"%-7d%-7d%-7d", pEntry->RssiSample.AvgRssi0, pEntry->RssiSample.AvgRssi1, pEntry->RssiSample.AvgRssi2); + else if (pAd->CommonCfg.RxStream == 2) + sprintf(msg+strlen(msg),"%-7d%-7d", pEntry->RssiSample.AvgRssi0, pEntry->RssiSample.AvgRssi1); + else + sprintf(msg+strlen(msg),"%-7d", pEntry->RssiSample.AvgRssi0); + + sprintf(msg+strlen(msg),"%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + sprintf(msg+strlen(msg),"%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + sprintf(msg+strlen(msg),"%dS-M%d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + sprintf(msg+strlen(msg),"%-6d", pEntry->HTPhyMode.field.MCS); + sprintf(msg+strlen(msg),"%-6d", pEntry->HTPhyMode.field.ShortGI); + sprintf(msg+strlen(msg),"%-6d", pEntry->HTPhyMode.field.STBC); + sprintf(msg+strlen(msg),"%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + sprintf(msg+strlen(msg),"%-7d", (int)DataRate); + sprintf(msg+strlen(msg),"%-7d", (int)pEntry->StaConnectTime); + sprintf(msg+strlen(msg),"%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); +//+++Add by shiang for debug +//---Add by shiang for debug + sprintf(msg+strlen(msg),"\n"); + } + } + + + /* for compatible with old API just do the printk to console*/ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} + + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +INT RTMPAPPrivIoctlAR9Show( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr) +{ + INT Status = NDIS_STATUS_SUCCESS; + + if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_mac_table")) + { + RTMPAR9IoctlGetMacTable(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_stat2")) + { + RTMPIoctlGetSTAT2(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_radio_dyn_info")) + { + RTMPIoctlGetRadioDynInfo(pAd,pIoctlCmdStr); + } +#ifdef WSC_AP_SUPPORT + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wsc_profile")) + { + RTMPAR9IoctlWscProfile(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wsc_pincode")) + { + RTMPIoctlWscPINCode(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wsc_status")) + { + RTMPIoctlWscStatus(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wps_dyn_info")) + { + RTMPIoctlGetWscDynInfo(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wps_regs_dyn_info")) + { + RTMPIoctlGetWscRegsDynInfo(pAd,pIoctlCmdStr); + } +#endif + return Status; +} +#endif /*AR9_MAPI_SUPPORT*/ +#endif/*AR9_INF*/ + +INT RTMPAPSetInformation( + IN PRTMP_ADAPTER pAd, + INOUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd) +{ + RTMP_IOCTL_INPUT_STRUCT *wrq = (RTMP_IOCTL_INPUT_STRUCT *) rq; + UCHAR Addr[MAC_ADDR_LEN]; + INT Status = NDIS_STATUS_SUCCESS; + +#ifdef SNMP_SUPPORT + /*snmp */ + PNDIS_AP_802_11_KEY pKey = NULL; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; +#endif /* SNMP_SUPPORT */ + + + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + NDIS_802_11_SSID Ssid; + +#ifdef HOSTAPD_SUPPORT + MAC_TABLE_ENTRY *pEntry; + struct ieee80211req_mlme mlme; + + struct ieee80211req_key Key; + struct ieee80211req_del_key delkey; + UINT8 Wcid; + PMULTISSID_STRUCT pMbss ; + WSC_LV_INFO WscIEBeacon; + WSC_LV_INFO WscIEProbeResp; + int i; +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + UCHAR ifIndex; + BOOLEAN apcliEn=FALSE; + PNDIS_APCLI_802_11_PMKID pPmkId = NULL; + BOOLEAN IEEE8021xState = FALSE; + BOOLEAN IEEE8021x_required_keys = FALSE; + UCHAR wpa_supplicant_enable = 0; + PNDIS_802_11_REMOVE_KEY pRemoveKey = NULL; + INT BssIdx, i; + PNDIS_802_11_WEP pWepKey =NULL; + PAPCLI_STRUCT pApCliEntry=NULL; + MAC_TABLE_ENTRY *pMacEntry=(MAC_TABLE_ENTRY *)NULL; + PNDIS_APCLI_802_11_KEY pApCliKey = NULL; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + MLME_DEAUTH_REQ_STRUCT DeAuthFrame; + PULONG pCurrState; +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + switch(cmd & 0x7FFF) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + case OID_802_11_SET_IEEE8021X: + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + + if(apcliEn == TRUE ) + { + Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.ApCliTab[ifIndex].wdev.IEEE8021X = IEEE8021xState; + DBGPRINT(RT_DEBUG_TRACE, ("Set Apcli(%d)::OID_802_11_SET_IEEE8021X (=%d)\n",ifIndex, IEEE8021xState)); + } + else + Status = -EINVAL; + } + break; + + case OID_802_11_SET_IEEE8021X_REQUIRE_KEY: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + if(apcliEn == TRUE ) + { + Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.ApCliTab[ifIndex].IEEE8021x_required_keys = IEEE8021x_required_keys; + DBGPRINT(RT_DEBUG_TRACE, ("Set Apcli(%d)::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n",ifIndex, IEEE8021x_required_keys)); + } + else + Status = -EINVAL; + } + break; + + case OID_802_11_PMKID: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + os_alloc_mem(NULL, (UCHAR **)&pPmkId, wrq->u.data.length); + + if(pPmkId == NULL) { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length); + + /* check the PMKID information */ + if (pPmkId->BSSIDInfoCount == 0) + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + else + { + PBSSID_INFO pBssIdInfo; + UINT BssIdx; + UINT CachedIdx; + + for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++) + { + /* point to the indexed BSSID_INFO structure */ + pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO)); + /* Find the entry in the saved data base. */ + for (CachedIdx = 0; CachedIdx < pAd->ApCfg.ApCliTab[ifIndex].SavedPMKNum; CachedIdx++) + { + /* compare the BSSID */ + if (NdisEqualMemory(pBssIdInfo->BSSID, pAd->ApCfg.ApCliTab[ifIndex].SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS))) + break; + } + + /* Found, replace it */ + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->ApCfg.ApCliTab[ifIndex].SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + pAd->ApCfg.ApCliTab[ifIndex].SavedPMKNum++; + } + /* Not found, replace the last one */ + else + { + /* Randomly replace one */ + CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->ApCfg.ApCliTab[ifIndex].SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + } + } + } + if(pPmkId) + os_free_mem(NULL, pPmkId); + break; + + case RT_OID_WPA_SUPPLICANT_SUPPORT: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length); + if (wpa_supplicant_enable & WPA_SUPPLICANT_ENABLE_WPS) + pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP |= WPA_SUPPLICANT_ENABLE_WPS; + else + { + pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP = wpa_supplicant_enable; + pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP &= 0x7F; + } + DBGPRINT(RT_DEBUG_TRACE, ("APCLI Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=0x%02X)\n", pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP)); + } + break; + + case OID_802_11_REMOVE_KEY: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + os_alloc_mem(NULL, (UCHAR **)&pRemoveKey, wrq->u.data.length); + if(pRemoveKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length); + if (pRemoveKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n")); + } + else + { + if (pAd->ApCfg.ApCliTab[ifIndex].AuthMode >= Ndis802_11AuthModeWPA) + { + RTMPWPARemoveKeyProc(pAd, pRemoveKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n")); + } + else + { + UINT KeyIdx; + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; + KeyIdx = pRemoveKey->KeyIndex; + + if (KeyIdx & 0x80000000) + { + /* Should never set default bit when remove key */ + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n")); + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx > 3) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx)); + } + else + { + pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx].KeyLen = 0; + pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BssIdx, (UCHAR)KeyIdx); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length)); + } + } + } + } + if (pRemoveKey) + os_free_mem(NULL, pRemoveKey); + break; + + case OID_802_11_ADD_WEP: + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + os_alloc_mem(NULL, (UCHAR **)&pWepKey, wrq->u.data.length); + if(pWepKey == NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set Apcli::OID_802_11_ADD_WEP, Failed!!\n")); + break; + } + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + + Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length); + if (Status) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n")); + } + else + { + UINT KeyIdx; + KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + /* KeyIdx must be 0 ~ 3 */ + if (KeyIdx > 4) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set ApCli::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n")); + } + else + { + UCHAR CipherAlg = 0; + PUCHAR Key; + + /* Zero the specific shared key */ + NdisZeroMemory(&pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx], sizeof(CIPHER_KEY)); + + /* set key material and key length */ + pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + + switch(pWepKey->KeyLength) + { + case 5: + CipherAlg = CIPHER_WEP64; + break; + case 13: + CipherAlg = CIPHER_WEP128; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n")); + Status = -EINVAL; + break; + } + pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx].CipherAlg = CipherAlg; + + /* Default key for tx (shared key) */ + if (pWepKey->KeyIndex & 0x80000000) + { + NdisZeroMemory(&pAd->ApCfg.ApCliTab[ifIndex].DesireSharedKey[KeyIdx], sizeof(CIPHER_KEY)); + + /* set key material and key length */ + pAd->ApCfg.ApCliTab[ifIndex].DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAd->ApCfg.ApCliTab[ifIndex].DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + pAd->ApCfg.ApCliTab[ifIndex].DesireSharedKeyId = KeyIdx; + pAd->ApCfg.ApCliTab[ifIndex].DesireSharedKey[KeyIdx].CipherAlg = CipherAlg; + + pAd->ApCfg.ApCliTab[ifIndex].DefaultKeyId = (UCHAR) KeyIdx; + } + + if ((pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode >= Ndis802_11AuthModeWPA)) + { + Key = pWepKey->KeyMaterial; + + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, BssIdx, KeyIdx, &pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx]); + + if (pWepKey->KeyIndex & 0x80000000) { + RTMPSetWcidSecurityInfo(pAd, BssIdx, KeyIdx, CipherAlg, pApCliEntry->MacTabWCID, SHAREDKEYTABLE); + } + NdisAcquireSpinLock(&pAd->MacTabLock); + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + NdisReleaseSpinLock(&pAd->MacTabLock); + } + else if ((pAd->ApCfg.ApCliTab[ifIndex].Valid == TRUE) + && (pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + Key = pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx].Key; + + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BssIdx, KeyIdx, &pAd->ApCfg.ApCliTab[ifIndex].SharedKey[KeyIdx]); + + if (pWepKey->KeyIndex & 0x80000000) + { + /* Assign pairwise key info */ + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + KeyIdx, + CipherAlg, + pApCliEntry->MacTabWCID, + SHAREDKEYTABLE); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set ApCli::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED ? "Port Secured":"Port NOT Secured")); + } + } + if (pWepKey) + os_free_mem(NULL, pWepKey); + break; + case OID_802_11_ADD_KEY: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + + os_alloc_mem(NULL, (UCHAR **)&pApCliKey, wrq->u.data.length); + if(pApCliKey == NULL) + { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pApCliKey, wrq->u.data.pointer, wrq->u.data.length); + if (pApCliKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n")); + } + else + { + RTMPApCliAddKey(pAd, ifIndex, pApCliKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pApCliKey->KeyIndex, pApCliKey->KeyLength)); + } + if (pApCliKey) + os_free_mem(NULL, pApCliKey); + break; + + case OID_802_11_DISASSOCIATE: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + if (!apcliEn || ifIndex >= MAX_APCLI_NUM) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n")); + + DisassocParmFill(pAd, &DisassocReq, pAd->MlmeAux.Bssid, REASON_DISASSOC_STA_LEAVING); + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, ifIndex); + + if (pApCliEntry->Valid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->MlmeAux.Rssi = 0; + + *pCurrState = APCLI_CTRL_DEASSOC; + break; + + case OID_802_11_DROP_UNENCRYPTED: + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + + if (!apcliEn) + return FALSE; + + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + + NdisAcquireSpinLock(&pAd->MacTabLock); + if (enabled == 1) + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + NdisReleaseSpinLock(&pAd->MacTabLock); + DBGPRINT(RT_DEBUG_TRACE, ("Set ApCLi::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled)); + } + break; + + case OID_SET_COUNTERMEASURES: + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + + if (!apcliEn) + return FALSE; + + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pApCliEntry->bBlockAssoc = TRUE; + else + /* WPA MIC error should block association attempt for 60 seconds */ + pApCliEntry->bBlockAssoc = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set ApCli::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pApCliEntry->bBlockAssoc ? "TRUE":"FALSE")); + } + break; +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + + + case OID_802_11_DEAUTHENTICATION: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION\n")); + if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT)) + Status = -EINVAL; + else + { + MAC_TABLE_ENTRY *pEntry = NULL; + MLME_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + + if(Elem == NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + break; + } + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + if (ifIndex >= MAX_APCLI_NUM) + { + os_free_mem(NULL, Elem); + return FALSE; + } + + os_alloc_mem(pAd, (UCHAR **)&pInfo, sizeof(MLME_DEAUTH_REQ_STRUCT)); + Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); + /* Fill in the related information */ + DeAuthFrame.Reason = (USHORT)pInfo->Reason; + COPY_MAC_ADDR(DeAuthFrame.Addr, pInfo->Addr); + + MlmeEnqueue(pAd, + APCLI_AUTH_STATE_MACHINE, + APCLI_MT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), + &DeAuthFrame, + ifIndex); + + if (pApCliEntry->Valid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid.*/ + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid.*/ + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->MlmeAux.Rssi = 0; + + *pCurrState = APCLI_CTRL_DISCONNECTED; + if(pInfo) + os_free_mem(NULL, pInfo); + + os_free_mem(NULL, Elem); + } + else +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif/*APCLI_SUPPORT*/ + { + if (Elem) + { + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); + + if ((pEntry = MacTableLookup(pAd, pInfo->Addr)) != NULL) + { + Elem->Wcid = pEntry->wcid; + MlmeEnqueue(pAd, AP_AUTH_STATE_MACHINE, APMT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), Elem, 0); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + /* kfree(Elem); */ + os_free_mem(NULL, Elem); + } + else + Status = -EFAULT; + } + } + + break; +#ifdef IAPP_SUPPORT + case RT_SET_IAPP_PID: + { + unsigned long IappPid; + if (copy_from_user(&IappPid, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + // TODO: correct the following line + /*RTMP_GET_OS_PID(pObj->IappPid, IappPid);*/ + pObj->IappPid_nr = IappPid; + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_APD_PID::(IappPid=%lu(0x%lx))\n", IappPid, IappPid)); + } + } + break; +#endif /* IAPP_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + case RT_SET_FT_STATION_NOTIFY: + case RT_SET_FT_KEY_REQ: + case RT_SET_FT_KEY_RSP: + case RT_FT_KEY_SET: + case RT_FT_NEIGHBOR_REPORT: + case RT_FT_NEIGHBOR_REQUEST: + case RT_FT_NEIGHBOR_RESPONSE: + case RT_FT_ACTION_FORWARD: + { + UCHAR *pBuffer; + + FT_MEM_ALLOC(pAd, &pBuffer, wrq->u.data.length+1); + if (pBuffer == NULL) + break; + + if (copy_from_user(pBuffer, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + FT_MEM_FREE(pAd, pBuffer); + break; + } + + switch(cmd & 0x7FFF) + { + case RT_SET_FT_STATION_NOTIFY: + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_FT_STATION_NOTIFY\n")); + FT_KDP_StationInform(pAd, pBuffer, wrq->u.data.length); + break; + case RT_SET_FT_KEY_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_FT_KEY_REQ\n")); + FT_KDP_IOCTL_KEY_REQ(pAd, pBuffer, wrq->u.data.length); + break; + case RT_SET_FT_KEY_RSP: + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_FT_KEY_RSP\n")); + FT_KDP_KeyResponseToUs(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_KEY_SET: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_KEY_SET\n")); + /* Note: the key must be ended by 0x00 */ + pBuffer[wrq->u.data.length] = 0x00; + FT_KDP_CryptKeySet(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_NEIGHBOR_REPORT: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_NEIGHBOR_REPORT\n")); +#ifdef FT_KDP_FUNC_INFO_BROADCAST + FT_KDP_NeighborReportHandle(pAd, pBuffer, wrq->u.data.length); +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + break; + case RT_FT_NEIGHBOR_REQUEST: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_NEIGHBOR_REPORT\n")); + FT_KDP_NeighborRequestHandle(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_NEIGHBOR_RESPONSE: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_NEIGHBOR_RESPONSE\n")); + FT_KDP_NeighborResponseHandle(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_ACTION_FORWARD: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_ACTION_FORWARD\n")); + FT_RRB_ActionHandle(pAd, pBuffer, wrq->u.data.length); + break; + } + + FT_MEM_FREE(pAd, pBuffer); + } + break; + + case OID_802_11R_SUPPORT: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + ULONG value; + Status = copy_from_user(&value, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable = (value == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_SUPPORT(=%d) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + break; + + case OID_802_11R_MDID: + if (wrq->u.data.length != FT_MDID_LEN) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + Status = copy_from_user(pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_MDID(=%c%c) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId[0], + pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId[0])); + } + + break; + + + case OID_802_11R_R0KHID: + if (wrq->u.data.length <= FT_ROKH_ID_LEN) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + Status = copy_from_user(pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khId, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khIdLen = wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_OID_802_11R_R0KHID(=%s) Len=%d\n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khIdLen)); + } + break; + + case OID_802_11R_RIC: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + ULONG value; + Status = copy_from_user(&value, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.RsrReqCap = (value == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_RIC(=%d) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + break; + + case OID_802_11R_OTD: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + ULONG value; + Status = copy_from_user(&value, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.FtOverDs = (value == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_OTD(=%d) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + break; +#endif /* DOT11R_FT_SUPPORT */ + case RT_SET_APD_PID: + { + unsigned long apd_pid; + if (copy_from_user(&apd_pid, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + // TODO: correct the following line + /*RTMP_GET_OS_PID(pObj->apd_pid, apd_pid);*/ + pObj->apd_pid_nr = apd_pid; + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_APD_PID::(ApdPid=%lu(0x%lx))\n", apd_pid, apd_pid)); + } + } + break; + case RT_SET_DEL_MAC_ENTRY: + if (copy_from_user(Addr, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_DEL_MAC_ENTRY::(%02x:%02x:%02x:%02x:%02x:%02x)\n", Addr[0],Addr[1],Addr[2],Addr[3],Addr[4],Addr[5])); + + pEntry = MacTableLookup(pAd, Addr); + if (pEntry) + { +#ifdef MAC_REPEATER_SUPPORT + /* + Need to delete repeater entry if this is mac repeater entry. + */ + if (pAd->ApCfg.bMACRepeaterEn) + { + UCHAR apCliIdx, CliIdx, isLinkValid; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, pEntry->Addr, TRUE, &isLinkValid); + + DBGPRINT(RT_DEBUG_TRACE, ("Delete (%02x:%02x:%02x:%02x:%02x:%02x) mac repeater entry\n", + Addr[0],Addr[1],Addr[2],Addr[3],Addr[4],Addr[5])); + + if (pReptEntry) + { + apCliIdx = pReptEntry->MatchApCliIdx; + CliIdx = pReptEntry->MatchLinkIdx; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, + (64 + MAX_EXT_MAC_ADDR_SIZE*apCliIdx + CliIdx)); + RTMP_MLME_HANDLER(pAd); + } + + } +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + /* + If AP send de-auth to Apple STA, + Apple STA will re-do auth/assoc and security handshaking with AP again. + @20150313 + */ + if (IS_FT_RSN_STA(pEntry)) + { + MacTableDeleteEntry(pAd, pEntry->Aid, Addr); + } + else +#endif /* DOT11R_FT_SUPPORT */ + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + } + } + break; +#ifdef WSC_AP_SUPPORT +#ifdef CON_WPS + case RT_OID_WSC_SET_CON_WPS_STOP: + { + UCHAR apidx = pObj->ioctl_if; + PWSC_UPNP_CTRL_WSC_BAND_STOP pWscUpnpBandStop; + PWSC_CTRL pWpsCtrl = NULL; + INT IsAPConfigured; + + if (pAd->conWscStatus == CON_WPS_STATUS_DISABLED) + { + Status = -EINVAL; + break; + } + + os_alloc_mem(NULL, (UCHAR **)&pWscUpnpBandStop, sizeof(WSC_UPNP_CTRL_WSC_BAND_STOP)); + + if(pWscUpnpBandStop) + { + Status = copy_from_user(pWscUpnpBandStop, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS BAND_STOP_CMD From[%s], isApCli[%d], is2gBand[%d]\n", + pWscUpnpBandStop->ifName, pWscUpnpBandStop->isApCli, pWscUpnpBandStop->is2gBand)); + + if (pWscUpnpBandStop->isApCli) + { + pWpsCtrl = &pAd->ApCfg.ApCliTab[BSS0].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS FROM IOCTL: Stop the ApCli WPS, state [%d]\n", + pWpsCtrl->WscState)); + + if (pWpsCtrl->WscState != WSC_STATE_OFF) + { + WscStop(pAd, TRUE, pWpsCtrl); + pWpsCtrl->WscConfMode = WSC_DISABLE; + } + } + else + { + pWpsCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + IsAPConfigured = pWpsCtrl->WscConfStatus; + + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pWpsCtrl->bWscTrigger == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("FROM IOCTL CON_WPS[%d]: Stop the AP Wsc Machine\n", apidx)); + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, + apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + WscStop(pAd, FALSE, pWpsCtrl); + } + + } + os_free_mem(NULL, pWscUpnpBandStop); + } + } + break; +#endif /* CON_WPS */ + + case RT_OID_WSC_SET_SELECTED_REGISTRAR: + { + PUCHAR upnpInfo; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + Status = -EINVAL; + } + else + { +#endif /*HOSTAPD_SUPPORT*/ + + + DBGPRINT(RT_DEBUG_TRACE, ("WSC::RT_OID_WSC_SET_SELECTED_REGISTRAR, wrq->u.data.length=%d!\n", wrq->u.data.length)); +/* upnpInfo = kmalloc(wrq->u.data.length, GFP_KERNEL); */ + os_alloc_mem(pAd, (UCHAR **)&upnpInfo, wrq->u.data.length); + if(upnpInfo) + { + int len, Status; + + Status = copy_from_user(upnpInfo, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + len = wrq->u.data.length; + + if((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode & WSC_PROXY)) + { + WscSelectedRegistrar(pAd, upnpInfo, len, apidx); + if (pAd->ApCfg.MBSSID[apidx].WscControl.Wsc2MinsTimerRunning == TRUE) + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pAd->ApCfg.MBSSID[apidx].WscControl.Wsc2MinsTimer, &Cancelled); + } + /* 2mins time-out timer */ + RTMPSetTimer(&pAd->ApCfg.MBSSID[apidx].WscControl.Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pAd->ApCfg.MBSSID[apidx].WscControl.Wsc2MinsTimerRunning = TRUE; + } + } +/* kfree(upnpInfo); */ + os_free_mem(NULL, upnpInfo); + } + else + { + Status = -EINVAL; + } +#ifdef HOSTAPD_SUPPORT + } +#endif /*HOSTAPD_SUPPORT*/ + + } + break; + case RT_OID_WSC_EAPMSG: + { + RTMP_WSC_U2KMSG_HDR *msgHdr = NULL; + PUCHAR pUPnPMsg = NULL; + UINT msgLen = 0, Machine = 0, msgType = 0; + int retVal, senderID = 0; +#ifdef HOSTAPD_SUPPORT + UCHAR apidx = pObj->ioctl_if; + + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + Status = -EINVAL; + } + else + { +#endif /*HOSTAPD_SUPPORT*/ + + + DBGPRINT(RT_DEBUG_TRACE, ("WSC::RT_OID_WSC_EAPMSG, wrq->u.data.length=%d, ioctl_if=%d\n", wrq->u.data.length, pObj->ioctl_if)); + + msgLen = wrq->u.data.length; + os_alloc_mem(pAd, (UCHAR **)&pUPnPMsg, msgLen); +/* if((pUPnPMsg = kmalloc(msgLen, GFP_KERNEL)) == NULL) */ + if (pUPnPMsg == NULL) + Status = -EINVAL; + else + { + int HeaderLen; + PSTRING pWpsMsg; + UINT WpsMsgLen; + PWSC_CTRL pWscControl; + + NdisZeroMemory(pUPnPMsg, msgLen); + retVal = copy_from_user(pUPnPMsg, wrq->u.data.pointer, msgLen); + + msgHdr = (RTMP_WSC_U2KMSG_HDR *)pUPnPMsg; + senderID = get_unaligned((INT32 *)(&msgHdr->Addr2[0])); + /*senderID = *((int *)&msgHdr->Addr2); */ + + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_EAPMSG++++++++\n\n")); + hex_dump("MAC::", &msgHdr->Addr3[0], MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_EAPMSG++++++++\n\n")); + + HeaderLen = LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME); + pWpsMsg = (PSTRING) &pUPnPMsg[HeaderLen]; + WpsMsgLen = msgLen - HeaderLen; + + /*assign the STATE_MACHINE type */ + Machine = WSC_STATE_MACHINE; + msgType = WSC_EAPOL_UPNP_MSG; + + pWscControl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + /* If AP is unconfigured, WPS state machine will be triggered after received M2. */ + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) +#ifdef WSC_V2_SUPPORT + && (pWscControl->WscV2Info.bWpsEnable || (pWscControl->WscV2Info.bEnableWpsV2 == FALSE)) +#endif /* WSC_V2_SUPPORT */ + ) + { + if (strstr(pWpsMsg, "SimpleConfig") && + !pWscControl->EapMsgRunning && + !pWscControl->WscUPnPNodeInfo.bUPnPInProgress) + { + /* GetDeviceInfo */ + WscInit(pAd, FALSE, pObj->ioctl_if); + /* trigger wsc re-generate public key */ + pWscControl->RegData.ReComputePke = 1; + } + else if (WscRxMsgTypeFromUpnp(pAd, pWpsMsg, WpsMsgLen) == WSC_MSG_M2 && + !pWscControl->EapMsgRunning && + !pWscControl->WscUPnPNodeInfo.bUPnPInProgress) + { + /* Check Enrollee Nonce of M2 */ + if (WscCheckEnrolleeNonceFromUpnp(pAd, pWpsMsg, WpsMsgLen, pWscControl)) + { + WscGetConfWithoutTrigger(pAd, pWscControl, TRUE); + pWscControl->WscState = WSC_STATE_SENT_M1; + } + } + } + + retVal = MlmeEnqueueForWsc(pAd, msgHdr->envID, senderID, Machine, msgType, msgLen, pUPnPMsg); + if((retVal == FALSE) && (msgHdr->envID != 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeEnqueuForWsc return False and envID=0x%x!\n", msgHdr->envID)); + Status = -EINVAL; + } + + os_free_mem(NULL, pUPnPMsg); + } + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_EAPMSG finished!\n")); +#ifdef HOSTAPD_SUPPORT + } +#endif /*HOSTAPD_SUPPORT*/ + } + break; + + case RT_OID_WSC_READ_UFD_FILE: + if (wrq->u.data.length > 0) + { + STRING *pWscUfdFileName = NULL; + UCHAR apIdx = pObj->ioctl_if; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[apIdx].WscControl; +/* pWscUfdFileName = (PSTRING)kmalloc(wrq->u.data.length+1, MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&pWscUfdFileName, wrq->u.data.length+1); + if (pWscUfdFileName) + { + RTMPZeroMemory(pWscUfdFileName, wrq->u.data.length+1); + if (copy_from_user(pWscUfdFileName, wrq->u.data.pointer, wrq->u.data.length)) + Status = -EFAULT; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_READ_UFD_FILE (WscUfdFileName=%s)\n", pWscUfdFileName)); + if (pWscCtrl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) + { + if (WscReadProfileFromUfdFile(pAd, apIdx, pWscUfdFileName)) + { + pWscCtrl->WscConfStatus = WSC_SCSTATE_CONFIGURED; + APStop(pAd); + APStartUp(pAd); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_READ_UFD_FILE: AP is configured.\n")); + Status = -EINVAL; + } + } +/* kfree(pWscUfdFileName); */ + os_free_mem(NULL, pWscUfdFileName); + } + else + Status = -ENOMEM; + } + else + Status = -EINVAL; + break; + + case RT_OID_WSC_WRITE_UFD_FILE: + if (wrq->u.data.length > 0) + { + STRING *pWscUfdFileName = NULL; + UCHAR apIdx = pObj->ioctl_if; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[apIdx].WscControl; +/* pWscUfdFileName = (PSTRING)kmalloc(wrq->u.data.length+1, MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&pWscUfdFileName, wrq->u.data.length+1); + if (pWscUfdFileName) + { + RTMPZeroMemory(pWscUfdFileName, wrq->u.data.length+1); + if (copy_from_user(pWscUfdFileName, wrq->u.data.pointer, wrq->u.data.length)) + Status = -EFAULT; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_WRITE_UFD_FILE (WscUfdFileName=%s)\n", pWscUfdFileName)); + if (pWscCtrl->WscConfStatus == WSC_SCSTATE_CONFIGURED) + { + WscWriteProfileToUfdFile(pAd, apIdx, pWscUfdFileName); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_WRITE_UFD_FILE: AP is un-configured.\n")); + Status = -EINVAL; + } + } +/* kfree(pWscUfdFileName); */ + os_free_mem(NULL, pWscUfdFileName); + } + else + Status = -ENOMEM; + } + else + Status = -EINVAL; + break; + + case RT_OID_WSC_UUID: + if (wrq->u.data.length == (UUID_LEN_STR-1)) + { + UCHAR apIdx = pObj->ioctl_if; + pAd->ApCfg.MBSSID[apIdx].WscControl.Wsc_Uuid_Str[0] = '\0'; + Status = copy_from_user(&pAd->ApCfg.MBSSID[apIdx].WscControl.Wsc_Uuid_Str[0], + wrq->u.data.pointer, + wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("UUID ASCII string: %s\n", + pAd->ApCfg.MBSSID[apIdx].WscControl.Wsc_Uuid_Str)); + } + else if (wrq->u.data.length == UUID_LEN_HEX) + { + UCHAR apIdx = pObj->ioctl_if, ii; + Status = copy_from_user(&pAd->ApCfg.MBSSID[apIdx].WscControl.Wsc_Uuid_E[0], + wrq->u.data.pointer, + wrq->u.data.length); + + for (ii=0; ii< 16; ii++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%02x", (pAd->ApCfg.MBSSID[apIdx].WscControl.Wsc_Uuid_E[ii] & 0xff))); + } + } + else + Status = -EINVAL; + break; +#endif /* WSC_AP_SUPPORT */ + + +#ifdef SNMP_SUPPORT + case OID_802_11_SHORTRETRYLIMIT: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit)); + } + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n")); + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit)); + } + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + { + UINT KeyIdx; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n")); +/* pKey = kmalloc(wrq->u.data.length, GFP_KERNEL); */ + os_alloc_mem(pAd, (UCHAR **)&pKey, wrq->u.data.length); + if (pKey == NULL) + { + Status= -EINVAL; + break; + } + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + /*pKey = &WepKey; */ + + if ( pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n")); + } + KeyIdx = pKey->KeyIndex & 0x0fffffff; + DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength)); + + /* it is a shared key */ + if (KeyIdx > 4) + Status = -EINVAL; + else + { + pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(&pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); + if (pKey->KeyIndex & 0x80000000) + { + /* Default key for tx (shared key) */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId = (UCHAR) KeyIdx; + } + /*RestartAPIsRequired = TRUE; */ + } + os_free_mem(NULL, pKey); + break; + + } + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n")); + + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + Status = copy_from_user(&pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); + + break; + +#endif /* SNMP_SUPPORT */ + + +#ifdef WAPI_SUPPORT + case OID_802_11_WAPI_PID: + { + unsigned long wapi_pid; + if (copy_from_user(&wapi_pid, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + RTMP_GET_OS_PID(pObj->wapi_pid, wapi_pid); + pObj->wapi_pid_nr = wapi_pid; + DBGPRINT(RT_DEBUG_TRACE, ("OID_802_11_WAPI_PID::(WapiPid=%lu(0x%lx))\n", wapi_pid, wapi_pid)); + } + } + break; + + case OID_802_11_PORT_SECURE_STATE: + if (wrq->u.data.length != sizeof(WAPI_PORT_SECURE_STRUCT)) + Status = -EINVAL; + else + { + MAC_TABLE_ENTRY *pEntry = NULL; + WAPI_PORT_SECURE_STRUCT wapi_port; + + Status = copy_from_user(&wapi_port, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + if ((pEntry = MacTableLookup(pAd, wapi_port.Addr)) != NULL) + { + switch (wapi_port.state) + { + case WAPI_PORT_SECURED: + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + break; + + default: + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_PORT_SECURE_STATE (state=%d)\n", wapi_port.state)); + } + } + break; + + case OID_802_11_UCAST_KEY_INFO: + if (wrq->u.data.length != sizeof(WAPI_UCAST_KEY_STRUCT)) + Status = -EINVAL; + else + { + MAC_TABLE_ENTRY *pEntry = NULL; + WAPI_UCAST_KEY_STRUCT wapi_ukey; + + Status = copy_from_user(&wapi_ukey, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + if ((pEntry = MacTableLookup(pAd, wapi_ukey.Addr)) != NULL) + { + pEntry->usk_id = wapi_ukey.key_id; + NdisMoveMemory(pEntry->PTK, wapi_ukey.PTK, 64); + + /* Install pairwise key */ + WAPIInstallPairwiseKey(pAd, pEntry, TRUE); + + /* Start or re-start USK rekey mechanism, if necessary. */ + RTMPCancelWapiRekeyTimerAction(pAd, pEntry); + RTMPStartWapiRekeyTimerAction(pAd, pEntry); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_UCAST_KEY_INFO complete\n")); + hex_dump("WAPI UCAST KEY", pEntry->PTK, 64); + } + } + break; + +#endif /* WAPI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + case OID_802_DOT1X_PMKID_CACHE: + RTMPIoctlAddPMKIDCache(pAd, wrq); + break; + + case OID_802_DOT1X_RADIUS_DATA: + RTMPIoctlRadiusData(pAd, wrq); + break; + + case OID_802_DOT1X_WPA_KEY: + RTMPIoctlAddWPAKey(pAd, wrq); + break; + + case OID_802_DOT1X_STATIC_WEP_COPY: + RTMPIoctlStaticWepCopy(pAd, wrq); + break; + + case OID_802_DOT1X_IDLE_TIMEOUT: + RTMPIoctlSetIdleTimeout(pAd, wrq); + break; +#endif /* DOT1X_SUPPORT */ + + case OID_802_11_AUTHENTICATION_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length); + if (AuthMode > Ndis802_11AuthModeMax) + { + Status = -EINVAL; + break; + } + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if(apcliEn) + { + if (pAd->ApCfg.ApCliTab[ifIndex].AuthMode != AuthMode) + { + /* Config has changed */ + pAd->ApCfg.ApCliTab[ifIndex].bConfigChanged = TRUE; + } + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = AuthMode; + + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + RTMPMakeRSNIE(pAd, pAd->ApCfg.ApCliTab[ifIndex].AuthMode, pAd->ApCfg.ApCliTab[ifIndex].WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + pAd->ApCfg.ApCliTab[ifIndex].DefaultKeyId = 0; + + if(pAd->ApCfg.ApCliTab[ifIndex].AuthMode >= Ndis802_11AuthModeWPA) + pAd->ApCfg.ApCliTab[ifIndex].DefaultKeyId = 1; + } + } +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + else + { + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode != AuthMode) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode = AuthMode; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n", pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode)); + } + APStop(pAd); + APStartUp(pAd); + break; + + case OID_802_11_WEP_STATUS: + if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length); + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + if (ifIndex >= MAX_APCLI_NUM) + return FALSE; + + if(apcliEn) + { + if (WepStatus <= Ndis802_11GroupWEP104Enabled) + { + if (pAd->ApCfg.ApCliTab[ifIndex].WepStatus != WepStatus) + { + /* Config has changed */ + pAd->ApCfg.ApCliTab[ifIndex].bConfigChanged = TRUE; + } + pAd->ApCfg.ApCliTab[ifIndex].WepStatus = WepStatus; + + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (pApCliEntry->WepStatus >= Ndis802_11Encryption2Enabled) + pApCliEntry->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, pAd->ApCfg.ApCliTab[ifIndex].AuthMode, pAd->ApCfg.ApCliTab[ifIndex].WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + + } + } + + } + else +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + { + /* Since TKIP, AES, WEP are all supported. It should not have any invalid setting */ + if (WepStatus <= Ndis802_11GroupWEP104Enabled) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if (wdev->WepStatus != WepStatus) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + wdev->WepStatus = WepStatus; + + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + wdev->GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + else + wdev->GroupKeyWepStatus = WepStatus; + } + else + { + Status = -EINVAL; + break; + } + APStop(pAd); + APStartUp(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus)); + } + } + + break; + + case OID_802_11_SSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) + Status = -EINVAL; + else + { + PSTRING pSsidString = NULL; + Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); + + if (Ssid.SsidLength > MAX_LEN_OF_SSID) + Status = -EINVAL; + else + { + if (Ssid.SsidLength == 0) + { + Status = -EINVAL; + } + else + { + os_alloc_mem(NULL, (UCHAR **)&pSsidString, MAX_LEN_OF_SSID+1); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength); +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + ifIndex = pObj->ioctl_if; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if(apcliEn) + { + Set_ApCli_Ssid_Proc(pAd,pSsidString); + } + } + else +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + { + NdisZeroMemory((PCHAR)pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid,MAX_LEN_OF_SSID); + strcpy((PCHAR)pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid,pSsidString); + pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen=strlen(pSsidString); + } + os_free_mem(NULL, pSsidString); + } + else + Status = -ENOMEM; + } + } + } + break; + + case OID_802_11_PASSPHRASE: + { + MULTISSID_STRUCT *pMBSSStruct; + INT retval; + NDIS80211PSK tmpPSK; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + NdisZeroMemory(&tmpPSK, sizeof(tmpPSK)); + Status = copy_from_user(&tmpPSK, wrq->u.data.pointer, wrq->u.data.length); + hex_dump("Set::OID_802_11_PASSPHRASE ==>", &tmpPSK.WPAKey[0], tmpPSK.WPAKeyLen); + + pMBSSStruct = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + retval = RT_CfgSetWPAPSKKey(pAd, &tmpPSK.WPAKey[0], tmpPSK.WPAKeyLen, (PUCHAR)pMBSSStruct->Ssid, pMBSSStruct->SsidLen, pMBSSStruct->PMK); + if (retval == FALSE) + DBGPRINT(RT_DEBUG_ERROR, ("PassPhrase Generate Fail\n")); + +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pMBSSStruct->WscControl.WpaPsk, 64); + pMBSSStruct->WscControl.WpaPskLen = 0; + pMBSSStruct->WscControl.WpaPskLen = tmpPSK.WPAKeyLen; + NdisMoveMemory(pMBSSStruct->WscControl.WpaPsk, &tmpPSK.WPAKey[0], pMBSSStruct->WscControl.WpaPskLen); + +#endif /* WSC_AP_SUPPORT */ + } + +#ifdef HOSTAPD_SUPPORT + case HOSTAPD_OID_SET_802_1X:/*pure 1x is enabled. */ + Set_IEEE8021X_Proc(pAd,"1"); + break; + + case HOSTAPD_OID_SET_KEY: + { + UINT KeyIdx; + Status = -EINVAL; + pObj = (POS_COOKIE) pAd->OS_Cookie; + UINT apidx = pObj->ioctl_if; + if(wrq->u.data.length != sizeof(struct ieee80211req_key) || !wrq->u.data.pointer) + break; + Status = copy_from_user(&Key, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, Key.ik_macaddr); + + + if((Key.ik_type == CIPHER_WEP64) ||(Key.ik_type == CIPHER_WEP128))/*dynamic wep with 1x */ + { + if (pEntry)/*pairwise key */ + { + pEntry->PairwiseKey.KeyLen = Key.ik_keylen; + NdisMoveMemory(pEntry->PairwiseKey.Key, Key.ik_keydata, Key.ik_keylen); + pEntry->PairwiseKey.CipherAlg = Key.ik_type; + KeyIdx=pAd->ApCfg.MBSSID[pEntry->apidx].DefaultKeyId; + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPAddWcidAttributeEntry( + pAd, + pEntry->apidx, + KeyIdx, /* The value may be not zero */ + pEntry->PairwiseKey.CipherAlg, + pEntry); + } + else/*group key */ + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + printk("Key.ik_keyix=%x\n",Key.ik_keyix); + KeyIdx = Key.ik_keyix& 0x0fff; + printk("ra%d KeyIdx=%d\n",apidx,KeyIdx); + printk("Key.ik_keyix=%x\n",Key.ik_keyix); + /* it is a shared key */ + if (KeyIdx < 4) + { + pAd->SharedKey[apidx][KeyIdx].KeyLen = (UCHAR) Key.ik_keylen; + NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].Key, &Key.ik_keydata, Key.ik_keylen); + if (Key.ik_keyix & 0x8000) + { + /* Default key for tx (shared key) */ + printk("ra%d DefaultKeyId=%d\n",apidx,KeyIdx); + pMbss->DefaultKeyId = (UCHAR) KeyIdx; + } + /*pMbss->DefaultKeyId=1; */ + + pAd->SharedKey[apidx][KeyIdx].CipherAlg = Key.ik_type; + AsicAddSharedKeyEntry( + pAd, + apidx, + KeyIdx, + &pAd->SharedKey[apidx][KeyIdx] + ); + + RTMPAddWcidAttributeEntry( + pAd, + apidx, + KeyIdx, + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg, + NULL); + } + } + } + else if (pEntry) + { + KeyIdx = Key.ik_keyix& 0x0fff; + if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) + { + pEntry->PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], Key.ik_keydata, Key.ik_keylen); + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], Key.ik_keylen); + } + + if(pEntry->WepStatus == Ndis802_11Encryption3Enabled) + { + pEntry->PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], Key.ik_keydata, OFFSET_OF_PTK_TK); + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], Key.ik_keylen); + } + + + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; + + pEntry->PairwiseKey.CipherAlg = Key.ik_type; + + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + } + else + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + KeyIdx = Key.ik_keyix& 0x0fff; + + /*if (Key.ik_keyix & 0x8000) */ + { + pMbss->DefaultKeyId = (UCHAR) KeyIdx; + } + + if (pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11Encryption2Enabled) + { + pAd->SharedKey[apidx][pMbss->DefaultKeyId].KeyLen= LEN_TK; + NdisMoveMemory(pAd->SharedKey[apidx][pMbss->DefaultKeyId].Key, Key.ik_keydata, 16); + NdisMoveMemory(pAd->SharedKey[apidx][pMbss->DefaultKeyId].RxMic, (Key.ik_keydata+16+8), 8); + NdisMoveMemory(pAd->SharedKey[apidx][pMbss->DefaultKeyId].TxMic, (Key.ik_keydata+16), 8); + } + + if(pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + pAd->SharedKey[apidx][pMbss->DefaultKeyId].KeyLen= LEN_TK; + NdisMoveMemory(pAd->SharedKey[apidx][pMbss->DefaultKeyId].Key, Key.ik_keydata, 16); + NdisMoveMemory(pAd->SharedKey[apidx][pMbss->DefaultKeyId].RxMic, (Key.ik_keydata+16+8), 8); + NdisMoveMemory(pAd->SharedKey[apidx][pMbss->DefaultKeyId].TxMic, (Key.ik_keydata+16), 8); + } + + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11Encryption2Enabled) + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg = CIPHER_AES; + + hex_dump("Key.ik_keydata,", (unsigned char*) Key.ik_keydata, 32); + + AsicAddSharedKeyEntry( + pAd, + apidx, + pMbss->DefaultKeyId, + &pAd->SharedKey[apidx][pMbss->DefaultKeyId] + ); + GET_GroupKey_WCID(pAd, Wcid, apidx); + + RTMPSetWcidSecurityInfo(pAd, apidx,(UINT8)KeyIdx, + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg, Wcid, SHAREDKEYTABLE); + + /*RTMPAddWcidAttributeEntry( + pAd, + apidx, + pMbss->DefaultKeyId, + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg, + NULL);*/ + } + break; + } + case HOSTAPD_OID_DEL_KEY: + + Status = -EINVAL; + if(wrq->u.data.length != sizeof(struct ieee80211req_del_key) || !wrq->u.data.pointer) + break; + Status = copy_from_user(&delkey, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, delkey.idk_macaddr); + if (pEntry){ + /* clear the previous Pairwise key table */ + if(pEntry->wcid != 0) + { + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + AsicRemovePairwiseKeyEntry(pAd,(UCHAR)pEntry->wcid); + } + } + else if((delkey.idk_macaddr == NULL) && (delkey.idk_keyix < 4)) + /* remove group key */ + AsicRemoveSharedKeyEntry(pAd, pEntry->apidx, delkey.idk_keyix); + break; + + case HOSTAPD_OID_SET_STA_AUTHORIZED:/*for portsecured flag. */ + + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, mlme.im_macaddr); + if (!pEntry){ + Status = -EINVAL; + } + else + { + switch (mlme.im_op) + { + case IEEE80211_MLME_AUTHORIZE: + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->WpaState = AS_PTKINITDONE;/*wpa state machine is not in use. */ + /*pAd->StaCfg.PortSecured= WPA_802_1X_PORT_SECURED; */ + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + break; + case IEEE80211_MLME_UNAUTHORIZE: + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + break; + default: + Status = -EINVAL; + } + } + } + break; + + case HOSTAPD_OID_STATIC_WEP_COPY: + { + UINT KeyIdx; + INT apidx; + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, mlme.im_macaddr); + if (!pEntry){ + Status = -EINVAL; + } + else{ + /*Status = -EINVAL; */ + printk("Woody HOSTAPD_OID_STATIC_WEP_COPY IEEE8021X=%d WepStatus=%d\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.IEEE8021X, pEntry->WepStatus); + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.IEEE8021X != TRUE) + break; + if (pEntry->WepStatus != Ndis802_11Encryption1Enabled) + break; + + apidx = pObj->ioctl_if; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + KeyIdx=pMbss->DefaultKeyId; + printk("Woody HOSTAPD_OID_STATIC_WEP_COPY=%d\n",KeyIdx); + pEntry->AuthMode=pAd->ApCfg.MBSSID[apidx].AuthMode; + pEntry->PairwiseKey.KeyLen = pAd->SharedKey[apidx][KeyIdx].KeyLen; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[apidx][KeyIdx].Key, pAd->SharedKey[apidx][KeyIdx].KeyLen); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPAddWcidAttributeEntry( + pAd, + pEntry->apidx, + KeyIdx, /* The value may be not zero */ + pEntry->PairwiseKey.CipherAlg, + pEntry); + + } + } + break; + } + case HOSTAPD_OID_SET_STA_DEAUTH: + DBGPRINT(RT_DEBUG_TRACE, ("Set::HOSTAPD_OID_SET_STA_DEAUTH\n")); + MLME_DEAUTH_REQ_STRUCT *pInfo; + MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if(Elem) + { + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(pInfo->Addr, mlme.im_macaddr, MAC_ADDR_LEN); + if ((pEntry = MacTableLookup(pAd, pInfo->Addr)) != NULL) + { + pInfo->Reason = mlme.im_reason; + Elem->Wcid = pEntry->wcid; + MlmeEnqueue(pAd, AP_AUTH_STATE_MACHINE, APMT2_MLME_DEAUTH_REQ, sizeof(MLME_DEAUTH_REQ_STRUCT), Elem,0); + } + } + os_free_mem(NULL, Elem); + } + break; + + case HOSTAPD_OID_SET_STA_DISASSOC:/*hostapd request to disassoc the station. */ + DBGPRINT(RT_DEBUG_TRACE, ("Set::HOSTAPD_OID_SET_STA_DISASSOC\n")); + MLME_DISASSOC_REQ_STRUCT DisassocReq; + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(DisassocReq.Addr, mlme.im_macaddr, MAC_ADDR_LEN); + DisassocReq.Reason = mlme.im_reason; + MlmeEnqueue(pAd, AP_ASSOC_STATE_MACHINE, APMT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq,0); + } + break; + + case OID_HOSTAPD_SUPPORT:/*notify the driver to support hostapd. */ + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN hostapd_enable; + int v, apidx; + apidx = pObj->ioctl_if; + Status = copy_from_user(&hostapd_enable, wrq->u.data.pointer, wrq->u.data.length); + printk("OID_HOSTAPD_SUPPORT apidx=%d\n",apidx); + pAd->ApCfg.MBSSID[apidx].Hostapd = hostapd_enable; + MULTISSID_STRUCT *pMBSSStruct; + + for(v=0;vApCfg.MBSSID[v].Hostapd == Hostapd_EXT) + printk("ApCfg->MBSSID[%d].Hostapd == TURE\n",v); + else + printk("ApCfg->MBSSID[%d].Hostapd == FALSE\n",v); + pMBSSStruct = &pAd->ApCfg.MBSSID[v]; + pMBSSStruct->WPAREKEY.ReKeyInterval = 0; + pMBSSStruct->WPAREKEY.ReKeyMethod = DISABLE_REKEY; + } + } + break; + + case HOSTAPD_OID_COUNTERMEASURES:/*report txtsc to hostapd. */ + + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN countermeasures_enable; + Status = copy_from_user(&countermeasures_enable, wrq->u.data.pointer, wrq->u.data.length); + + if(countermeasures_enable) + { + + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive CM Attack Twice within 60 seconds ====>>> \n")); + + /* send wireless event - for counter measures */ + pAd->ApCfg.CMTimerRunning = FALSE; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + /* happened twice within 60 sec, AP SENDS disaccociate all associated STAs. All STA's transition to State 2 */ + if (IS_ENTRY_CLIENT(pEntry)) + { + MlmeDeAuthAction(pAd, &pAd->MacTab.Content[i], REASON_MIC_FAILURE,FALSE); + } + } + + /* Further, ban all Class 3 DATA transportation for a period of 60 sec */ + /* disallow new association , too */ + pAd->ApCfg.BANClass3Data = TRUE; + } + + + } + else + { + pAd->ApCfg.BANClass3Data = FALSE; + } + } + break; + + case HOSTAPD_OID_SET_WPS_BEACON_IE:/*pure 1x is enabled. */ + DBGPRINT(RT_DEBUG_TRACE,("HOSTAPD_OID_SET_WPS_BEACON_IE\n")); + if (wrq->u.data.length != sizeof(WSC_LV_INFO)) + { + Status = -EINVAL; + } + else + { + INT apidx; + apidx = pObj->ioctl_if; + pAd->ApCfg.MBSSID[apidx].HostapdWPS = TRUE; + MULTISSID_STRUCT *pMBSSStruct; + NdisZeroMemory(&WscIEBeacon,sizeof(WSC_LV_INFO)); + Status = copy_from_user(&WscIEBeacon, wrq->u.data.pointer, wrq->u.data.length); + pMBSSStruct = &pAd->ApCfg.MBSSID[apidx]; + NdisMoveMemory(pMBSSStruct->WscIEBeacon.Value,WscIEBeacon.Value, WscIEBeacon.ValueLen); + pMBSSStruct->WscIEBeacon.ValueLen=WscIEBeacon.ValueLen; + APUpdateBeaconFrame(pAd, apidx); + } + + break; + + case HOSTAPD_OID_SET_WPS_PROBE_RESP_IE:/*pure 1x is enabled. */ + apidx = pObj->ioctl_if; + DBGPRINT(RT_DEBUG_TRACE,("HOSTAPD_OID_SET_WPS_PROBE_RESP_IE\n")); + if (wrq->u.data.length != sizeof(WSC_LV_INFO)) + { + DBGPRINT(RT_DEBUG_TRACE,("HOSTAPD_OID_SET_WPS_PROBE_RESP_IE failed\n")); + Status = -EINVAL; + } + else + { + INT apidx; + apidx = pObj->ioctl_if; + pAd->ApCfg.MBSSID[apidx].HostapdWPS = TRUE; + MULTISSID_STRUCT *pMBSSStruct; + NdisZeroMemory(&WscIEProbeResp,sizeof(WSC_LV_INFO)); + Status = copy_from_user(&WscIEProbeResp, wrq->u.data.pointer, wrq->u.data.length); + pMBSSStruct = &pAd->ApCfg.MBSSID[apidx]; + NdisMoveMemory(pMBSSStruct->WscIEProbeResp.Value,WscIEProbeResp.Value, WscIEProbeResp.ValueLen); + pMBSSStruct->WscIEProbeResp.ValueLen=WscIEProbeResp.ValueLen; + APUpdateBeaconFrame(pAd, apidx); + + } + break; +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef CONFIG_HOTSPOT + case OID_802_11_HS_TEST: + DBGPRINT(RT_DEBUG_TRACE, ("hotspot test\n")); + break; + case OID_802_11_HS_IE: + { + UCHAR *IE; + os_alloc_mem(NULL, (UCHAR **)&IE, wrq->u.data.length); + copy_from_user(IE, wrq->u.data.pointer, wrq->u.data.length); + Set_AP_IE(pAd, IE, wrq->u.data.length); + os_free_mem(NULL, IE); + } + break; + case OID_802_11_HS_ANQP_RSP: + { + UCHAR *Buf; + struct anqp_rsp_data *rsp_data; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + rsp_data = (struct anqp_rsp_data *)Buf; + Send_ANQP_Rsp(pAd, + rsp_data->peer_mac_addr, + rsp_data->anqp_rsp, + rsp_data->anqp_rsp_len); + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_HS_ONOFF: + { + UCHAR *Buf; + struct hs_onoff *onoff; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + onoff = (struct hs_onoff *)Buf; + Set_HotSpot_OnOff(pAd, onoff->hs_onoff, onoff->event_trigger, onoff->event_type); + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_HS_PARAM_SETTING: + { + UCHAR *Buf; + struct hs_param_setting *param_setting; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + param_setting = (struct hs_param_setting *)Buf; + Set_HotSpot_Param(pAd, param_setting->param, param_setting->value); + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_HS_RESET_RESOURCE: + DBGPRINT(RT_DEBUG_TRACE, ("hotspot reset some resource\n")); + Clear_Hotspot_All_IE(pAd); + //Clear_All_PROXY_TABLE(pAd); + break; +#ifdef CONFIG_HOTSPOT_R2 + case OID_802_11_HS_SASN_ENABLE: + { + UCHAR *Buf; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].HotSpotCtrl; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pHSCtrl->bASANEnable = Buf[0]; + os_free_mem(NULL, Buf); + //printk("\033[1;32m %s %d ========= status: %d ===\033[0m\n",__FUNCTION__,__LINE__,Status); //Kyle + } + break; + case OID_802_11_BSS_LOAD: + { + UCHAR *Buf; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].HotSpotCtrl; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pHSCtrl->QLoadTestEnable = Buf[0]; + pHSCtrl->QLoadCU = Buf[1]; + printk("!!!!!!!!!!!! pHSCtrl->QLoadTestEnable :%d pHSCtrl->QLoadCU:%d !!!!!!!!\n",pHSCtrl->QLoadTestEnable,pHSCtrl->QLoadCU); + memcpy(&pHSCtrl->QLoadStaCnt, &Buf[2], 2); + os_free_mem(NULL, Buf); + } + break; +#endif +#endif + +#ifdef CONFIG_DOT11V_WNM +#ifdef CONFIG_HOTSPOT_R2 + case OID_802_11_WNM_BTM_REQ: + { + UCHAR *Buf; + MAC_TABLE_ENTRY *pEntry; + struct btm_req_data *req_data; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].HotSpotCtrl; + + os_alloc_mem(Buf, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + req_data = (struct btm_req_data *)Buf; + + if ((pEntry = MacTableLookup(pAd, req_data->peer_mac_addr)) == NULL) + { + } + else if (((pHSCtrl->HotSpotEnable) && (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeOpen)) || + ((pEntry->WpaState == AS_PTKINITDONE) && (pEntry->GTKState = REKEY_ESTABLISHED))) + { + printk("btm1\n"); + Send_BTM_Req(pAd, + req_data->peer_mac_addr, + req_data->btm_req, + req_data->btm_req_len); + } + else + { + printk("btm2\n"); + pEntry->IsBTMReqValid = TRUE; + os_alloc_mem(pEntry->ReqbtmData, (UCHAR **)&pEntry->ReqbtmData, sizeof(struct btm_req_data)+req_data->btm_req_len); + memcpy(pEntry->ReqbtmData, Buf, sizeof(struct btm_req_data)+req_data->btm_req_len); + } + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_WNM_NOTIFY_REQ: + { + UCHAR *Buf; + MAC_TABLE_ENTRY *pEntry; + struct wnm_req_data *req_data; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].HotSpotCtrl; + + os_alloc_mem(Buf, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + + req_data = (struct wnm_req_data *)Buf; + //printk("addr=%02x:%02x:%02x:%02x:%02x:%02x\n", req_data->peer_mac_addr[0],req_data->peer_mac_addr[1],req_data->peer_mac_addr[2],req_data->peer_mac_addr[3],req_data->peer_mac_addr[4],req_data->peer_mac_addr[5]); + //for(k=0;kwnm_req_len;k++) + // printk("%02x:", *(req_data->wnm_req+k)); + + //printk("req len=%d\n",req_data->wnm_req_len); + if ((pEntry = MacTableLookup(pAd, req_data->peer_mac_addr)) == NULL) + { + } + else if (((pHSCtrl->HotSpotEnable) && (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeOpen)) || + ((pEntry->WpaState == AS_PTKINITDONE) && (pEntry->GTKState = REKEY_ESTABLISHED))) + { + printk("wnm1\n"); + Send_WNM_Notify_Req(pAd, + req_data->peer_mac_addr, + req_data->wnm_req, + req_data->wnm_req_len, + req_data->type); + } + else + { + printk("wnm2\n"); + pEntry->IsWNMReqValid = TRUE; + os_alloc_mem(pEntry->ReqData, (UCHAR **)&pEntry->ReqData, sizeof(struct wnm_req_data)+req_data->wnm_req_len); + memcpy(pEntry->ReqData, Buf, sizeof(struct wnm_req_data)+req_data->wnm_req_len); + } + + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_QOSMAP_CONFIGURE: + { + UCHAR *Buf; + MAC_TABLE_ENTRY *pEntry; + struct qosmap_data *req_data; + unsigned int i; + + os_alloc_mem(Buf, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + + req_data = (struct qosmap_data *)Buf; + + if ((pEntry = MacTableLookup(pAd, req_data->peer_mac_addr)) != NULL) + { + //clear previous data + pEntry->DscpExceptionCount = 0; + memset(pEntry->DscpRange, 0xff, 16); + memset(pEntry->DscpException, 0xff, 42); + + pEntry->DscpExceptionCount = req_data->qosmap_len-16; + memcpy((UCHAR *)pEntry->DscpRange, &req_data->qosmap[pEntry->DscpExceptionCount], 16); + if (pEntry->DscpExceptionCount != 0) + memcpy((UCHAR *)pEntry->DscpException, req_data->qosmap, pEntry->DscpExceptionCount); + + Send_QOSMAP_Configure(pAd, + req_data->peer_mac_addr, + req_data->qosmap, + req_data->qosmap_len, + pEntry->apidx); + } + else if ((req_data->peer_mac_addr[0] == 0) + && (req_data->peer_mac_addr[1] == 0) + && (req_data->peer_mac_addr[2] == 0) + && (req_data->peer_mac_addr[3] == 0) + && (req_data->peer_mac_addr[4] == 0) + && (req_data->peer_mac_addr[5] == 0) ) { + /* Special MAC 00:00:00:00:00:00 for HS2 QoS Map Change using. */ + for (i=0; iMacTab.Content[i]; + + if ((IS_ENTRY_CLIENT(pEntry)) + && (pEntry->Sst == SST_ASSOC)) { + if (pEntry->QosMapSupport) { + pEntry->DscpExceptionCount = 0; + memset(pEntry->DscpRange, 0xff, 16); + memset(pEntry->DscpException, 0xff, 42); + + pEntry->DscpExceptionCount = req_data->qosmap_len-16; + memcpy((UCHAR *)pEntry->DscpRange, + &req_data->qosmap[pEntry->DscpExceptionCount], 16); + if (pEntry->DscpExceptionCount != 0) { + memcpy((UCHAR *)pEntry->DscpException, + req_data->qosmap, pEntry->DscpExceptionCount); + } + printk ("send QoS map frame: apidx=%d\n", pEntry->apidx); + Send_QOSMAP_Configure(pAd, + pEntry->Addr, + req_data->qosmap, + req_data->qosmap_len, + pEntry->apidx); + } + } + } + } + os_free_mem(NULL, Buf); + } + break; +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* CONFIG_HOTSPOT */ + +#ifdef AIRPLAY_SUPPORT + /* + *Get Airplay IE content from user + */ + case OID_AIRPLAY_IE_INSERT: + { + printk(KERN_ALERT"!!##-----OID_AIRPLAY_IE_INSERT start...length=%d\n",wrq->u.data.length); + + if (wrq->u.data.length != 0) + { + /*Free IE spaces*/ + if (pAd->pAirplayIe) + { + Status = os_free_mem(NULL, pAd->pAirplayIe); + } + if (Status == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("oid: OID_AIRPLAY_IE_INSERT os_free_mem fail\n")); + break; + } + + pAd->pAirplayIe = NULL; + pAd->AirplayIeLen = wrq->u.data.length; + + Status = os_alloc_mem(NULL, &pAd->pAirplayIe, pAd->AirplayIeLen); + if (Status == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("os_alloc_mem fail\n")); + break; + } + + Status = copy_from_user(pAd->pAirplayIe, wrq->u.data.pointer, pAd->AirplayIeLen); + if (Status == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_AIRPLAY_IE_INSERT error!!\n")); + break; + } + /*show out the IE content for debug*/ + //hex_dump("The primary AIRPLAYIE", pAd->pAirplayIe, pAd->AirplayIeLen); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("wrq->u.data.length == 0, no data need to update\n")); + } + } + break; + + /* + * Enable/Disable driver Airplay functionality + * Value: + * 0: Not enable + * 1: Enable + */ + case OID_AIRPLAY_ENABLE: + { + if (wrq->u.data.length > sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN bEnable; + + Status = copy_from_user(&bEnable, wrq->u.data.pointer, wrq->u.data.length); + + if (Status == NDIS_STATUS_SUCCESS) + { + if (bEnable == TRUE) + { + INT apidx; + apidx = pObj->ioctl_if; + pAd->bAirplayEnable= TRUE; + pAd->ApCfg.MBSSID[apidx].bBcnSntReq = TRUE; + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + DBGPRINT(RT_DEBUG_OFF, ("Enable Airplay Support!\n")); + } + else + { + pAd->bAirplayEnable = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("Disable Airplay Support!\n")); + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_AIRPLAY_ENABLE error!!\n")); + } + } + break; +#endif /* AIRPLAY_SUPPORT */ + +#ifdef BAND_STEERING + case OID_BNDSTRG_MSG: + BndStrg_MsgHandle(pAd, wrq); + break; +#endif /* BAND_STEERING */ +#ifdef SMART_MESH + case RT_OID_LAST_TX_RX_STATS: + { + UCHAR *Buf; + PSET_PKT_STATS_INFO pPktStatsInfo; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pPktStatsInfo = (PSET_PKT_STATS_INFO)Buf; + if(pPktStatsInfo->bCliPktStatEnable) + Set_Cli_Pkt_Stats_Enable_Proc(pAd,"1"); + else + Set_Cli_Pkt_Stats_Enable_Proc(pAd,"0"); + COPY_MAC_ADDR(pAd->ApCfg.CliPktMac, pPktStatsInfo->Mac); + os_free_mem(NULL, Buf); + DBGPRINT(RT_DEBUG_TRACE,("SET RT_OID_LAST_TX_RX_STATS\n")); + } + break; + case RT_OID_SET_PKT_TX_RX_STATS: + { + UCHAR *Buf; + PSET_PKT_TX_RX_STATS pPktTxRxStats; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pPktTxRxStats = (PSET_PKT_TX_RX_STATS)Buf; +#ifdef ED_MONITOR + if (pPktTxRxStats->timer_en == 1) + RTMP_CHIP_ASIC_SET_EDCCA(pAd, TRUE); + else if (pPktTxRxStats->timer_en == 2) + { + UINT32 mac_val; + RTMP_CHIP_ASIC_SET_EDCCA(pAd, FALSE); + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val &= (~0x01); + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + } +#endif /* ED_MONITOR */ + + if (pPktTxRxStats->scan_time) + pAd->ApCfg.ScanTime = pPktTxRxStats->scan_time; + + if (pPktTxRxStats->trigger_site_survey) + Set_SiteSurvey_Proc(pAd, ""); + + if (pPktTxRxStats->channel_time_init) + { + pAd->ChannelTimerCounters.EdBusyTime = 0; + pAd->ChannelTimerCounters.ChBusyTime = 0; + pAd->ChannelTimerCounters.ChIdleTime = 0; + } + + os_free_mem(NULL, Buf); + DBGPRINT(RT_DEBUG_TRACE,("RT_OID_SET_PKT_TX_RX_STATS\n")); + } + break; + +#endif /* SMART_MESH */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + + + return Status; +} + + +INT RTMPAPQueryInformation( + IN RTMP_ADAPTER *pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd) +{ + RTMP_IOCTL_INPUT_STRUCT *wrq = (RTMP_IOCTL_INPUT_STRUCT *) rq; + INT Status = NDIS_STATUS_SUCCESS, i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + STRING driverVersion[16]; + struct wifi_dev *wdev __maybe_unused; +#if defined(DBG) || defined(WSC_AP_SUPPORT) || defined(BB_SOC) || defined(LLTD_SUPPORT) + UCHAR apidx = pObj->ioctl_if; +#endif +#ifdef WSC_AP_SUPPORT + UINT WscPinCode = 0; + PWSC_PROFILE pProfile; + PWSC_CTRL pWscControl; +#endif /* WSC_AP_SUPPORT */ + ULONG ulInfo; +#ifdef SNMP_SUPPORT + DefaultKeyIdxValue *pKeyIdxValue; + INT valueLen; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR snmp_tmp[64]; +#endif /* SNMP_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + struct default_group_key group_key; + struct ieee80211req_key ik; + unsigned char *p; + MAC_TABLE_ENTRY *pEntry=(MAC_TABLE_ENTRY *)NULL; + struct ieee80211req_wpaie wpaie; + PMULTISSID_STRUCT pMbss ; +#endif /*HOSTAPD_SUPPORT*/ +#ifdef CUSTOMER_DCC_FEATURE + CURRENT_CHANNEL_STATISTICS ChannelStats; + UINT32 AvgValue; + UINT64 temp; +#endif +#ifdef APCLI_SUPPORT + UCHAR ifIndex; + BOOLEAN apcliEn=FALSE; + PAPCLI_STRUCT pApCliEntry=NULL; +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + INT Padding = 0; + ULONG BssBufSize; + PUCHAR pBuf = NULL, pPtr=NULL; + NDIS_802_11_BSSID_LIST_EX *pBssidList = NULL; + USHORT BssLen = 0; + PNDIS_WLAN_BSSID_EX pBss; + MAC_TABLE_ENTRY *pMacEntry=(MAC_TABLE_ENTRY *)NULL; + NDIS_802_11_SSID Ssid; + UINT we_version_compiled; +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif/*APCLI_SUPPORT*/ + + + NDIS_802_11_STATISTICS *pStatistics; + + + + + INT IEEE8021X = 0; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + switch(cmd) + { +#ifdef CUSTOMER_DCC_FEATURE + case OID_802_11_GET_CURRENT_CHANNEL_STATS: + if(pAd->EnableChannelStatsCheck) + { + NdisZeroMemory(&ChannelStats,sizeof(CURRENT_CHANNEL_STATISTICS)); + ChannelStats.SamplePeriod = pAd->ChannelStats.TotalDuration; + ChannelStats.FalseCCACount = pAd->ChannelStats.FalseCCACount; + ChannelStats.EdCcaBusyTime = pAd->ChannelStats.CCABusytime; + ChannelStats.ChannelBusyTime = pAd->ChannelStats.ChBusytime; + temp = pAd->ChannelStats.ChannelApActivity; + do_div(temp, 1000); + ChannelStats.ChannelApActivity = temp; + wrq->u.data.length = sizeof(CURRENT_CHANNEL_STATISTICS); + Status = copy_to_user(wrq->u.data.pointer, &ChannelStats , wrq->u.data.length); + ResetChannelStatus(pAd); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Radio Channel Stats monitoring is not enabled \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + } + break; + + case OID_802_11_GET_CURRENT_CHANNEL_FALSE_CCA_AVG: + if(pAd->EnableChannelStatsCheck) + { + AvgValue = pAd->ChannelStats.FalseCCACountAvg; + pAd->ChannelStats.FalseCCACountAvg = 0; + wrq->u.data.length = sizeof(INT); + Status = copy_to_user(wrq->u.data.pointer, &AvgValue, wrq->u.data.length); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Radio Channel Stats monitoring is not enabled \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + + } + break; + + case OID_802_11_GET_CURRENT_CHANNEL_CST_TIME_AVG: + if(pAd->EnableChannelStatsCheck) + { + AvgValue = pAd->ChannelStats.CCABusyTimeAvg; + pAd->ChannelStats.CCABusyTimeAvg = 0; + wrq->u.data.length = sizeof(INT); + Status = copy_to_user(wrq->u.data.pointer, &AvgValue, wrq->u.data.length); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Radio Channel Stats monitoring is not enabled \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + + } + break; + + case OID_802_11_GET_CURRENT_CHANNEL_BUSY_TIME_AVG: + if(pAd->EnableChannelStatsCheck) + { + AvgValue = pAd->ChannelStats.ChBusyTimeAvg; + pAd->ChannelStats.ChBusyTimeAvg = 0; + wrq->u.data.length = sizeof(INT); + Status = copy_to_user(wrq->u.data.pointer, &AvgValue, wrq->u.data.length); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Radio Channel Stats monitoring is not enabled \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + + } + break; + + case OID_802_11_GET_CURRENT_CHANNEL_AP_ACTIVITY_AVG: + if(pAd->EnableChannelStatsCheck) + { + temp = pAd->ChannelStats.ChannelApActivityAvg; + do_div(temp, 1000); + AvgValue = temp; + pAd->ChannelStats.ChannelApActivityAvg = 0; + wrq->u.data.length = sizeof(INT); + Status = copy_to_user(wrq->u.data.pointer, &AvgValue, wrq->u.data.length); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Radio Channel Stats monitoring is not enabled \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + + } + break; + + case OID_802_11_STA_STATISTICS: + RTMPIoctlQuerySTAStat(pAd, wrq); + break; + + case OID_802_11_GET_CURRENT_CHANNEL_AP_TABLE: + if(pAd->ApEnableBeaconTable == TRUE) + RTMPIoctlGetApTable(pAd,wrq); + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Beacon Table monitoring is not enabled \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + } + break; + + case OID_802_11_GET_SCAN_RESULTS: + if(pAd->ChannelInfo.GetChannelInfo) + { + RTMPIoctlGetScanResults(pAd,wrq); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Channel scan has not been run before getting the scan result \n", __FUNCTION__)); + Status = RTMP_IO_EFAULT; + } + break; + + case OID_802_11_GET_ACCESS_CATEGORY_TRAFFIC_STATUS: + RTMPIoctlGetStreamType(pAd,wrq); + break; + + case OID_802_11_GET_RADIO_STATS_COUNT: + RTMPIoctlGetRadioStatsCount(pAd,wrq); + break; +#endif +#ifdef DOT1X_SUPPORT + case OID_802_11_SET_IEEE8021X: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SET_IEEE8021X \n")); + wrq->u.data.length = sizeof(INT); + if(pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.IEEE8021X == TRUE) + IEEE8021X=1; + else + IEEE8021X=0; + + Status = copy_to_user(wrq->u.data.pointer, &IEEE8021X, wrq->u.data.length); + break; +#endif /* DOT1X_SUPPORT */ + case OID_802_11_AUTHENTICATION_MODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE \n")); + wrq->u.data.length = sizeof(NDIS_802_11_AUTHENTICATION_MODE); + AuthMode=pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode; + Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length); + break; + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + case RT_OID_NEW_DRIVER: + { + UCHAR enabled = 1; + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query apcli::RT_OID_NEW_DRIVER (=%d)\n", enabled)); + break; + } + + case RT_OID_WE_VERSION_COMPILED: + wrq->u.data.length = sizeof(UINT); + we_version_compiled = RtmpOsWirelessExtVerGet(); + Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length); + break; + + case OID_802_11_BSSID_LIST: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ifIndex].MacTabWCID]; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n")); + return -EAGAIN; + } + if ((pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantScanCount = 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAd->ScanTab.BssNr)); + BssBufSize = sizeof(ULONG); + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen + Padding); + } + + BssBufSize += 256; + os_alloc_mem(pAd, (UCHAR **)&pBuf, BssBufSize); + if(pBuf == NULL) + { + Status = -ENOMEM; + break; + } + NdisZeroMemory(pBuf, BssBufSize); + pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf; + pBssidList->NumberOfItems = pAd->ScanTab.BssNr; + + BssLen = 4; /* Consist of NumberOfItems */ + pPtr = (PUCHAR) &pBssidList->Bssid[0]; + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = (PNDIS_WLAN_BSSID_EX) pPtr; + NdisMoveMemory(&pBss->MacAddress, &pAd->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); + if ((pAd->ScanTab.BssEntry[i].Hidden == 1)) + { + /* + We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation + and then failed to send EAPOl farame. + */ + if ((pAd->ApCfg.ApCliTab[ifIndex].AuthMode >= Ndis802_11AuthModeWPA) && (pMacEntry->PortSecured != WPA_802_1X_PORT_SECURED)) + { + pBss->Ssid.SsidLength = pAd->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAd->ScanTab.BssEntry[i].Ssid, pAd->ScanTab.BssEntry[i].SsidLen); + } + else + pBss->Ssid.SsidLength = 0; + } + else + { + pBss->Ssid.SsidLength = pAd->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAd->ScanTab.BssEntry[i].Ssid, pAd->ScanTab.BssEntry[i].SsidLen); + } + pBss->Privacy = pAd->ScanTab.BssEntry[i].Privacy; + pBss->Rssi = pAd->ScanTab.BssEntry[i].Rssi - pAd->BbpRssiToDbmDelta; + pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAd->ScanTab.BssEntry[i]); + pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION); + pBss->Configuration.BeaconPeriod = pAd->ScanTab.BssEntry[i].BeaconPeriod; + pBss->Configuration.ATIMWindow = pAd->ScanTab.BssEntry[i].AtimWin; + + MAP_CHANNEL_ID_TO_KHZ(pAd->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig); + + if (pAd->ScanTab.BssEntry[i].BssType == BSS_INFRA) + pBss->InfrastructureMode = Ndis802_11Infrastructure; + else + pBss->InfrastructureMode = Ndis802_11IBSS; + + NdisMoveMemory(pBss->SupportedRates, pAd->ScanTab.BssEntry[i].SupRate, pAd->ScanTab.BssEntry[i].SupRateLen); + NdisMoveMemory(pBss->SupportedRates + pAd->ScanTab.BssEntry[i].SupRateLen, + pAd->ScanTab.BssEntry[i].ExtRate, + pAd->ScanTab.BssEntry[i].ExtRateLen); + + if (pAd->ScanTab.BssEntry[i].VarIELen == 0) + { + pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAd->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + } + else + { + pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAd->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAd->ScanTab.BssEntry[i].VarIEs, pAd->ScanTab.BssEntry[i].VarIELen); + pPtr += pAd->ScanTab.BssEntry[i].VarIELen; + } + pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen + Padding); + +#if WIRELESS_EXT < 17 + if ((BssLen + pBss->Length) < wrq->u.data.length) + BssLen += pBss->Length; + else + { + pBssidList->NumberOfItems = i; + break; + } +#else + BssLen += pBss->Length; +#endif + } + +#if WIRELESS_EXT < 17 + wrq->u.data.length = BssLen; +#else + if (BssLen > wrq->u.data.length) + { + os_free_mem(NULL, pBssidList); + return -E2BIG; + } + else + wrq->u.data.length = BssLen; +#endif + Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen); + os_free_mem(NULL, pBssidList); + break; + case OID_802_3_CURRENT_ADDRESS: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry=&pAd->ApCfg.ApCliTab[ifIndex]; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ifIndex].MacTabWCID]; + + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, pApCliEntry->CurrentAddress, wrq->u.data.length); + break; + + case OID_802_11_BSSID: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry=&pAd->ApCfg.ApCliTab[ifIndex]; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + { + Status = copy_to_user(wrq->u.data.pointer, pApCliEntry->CfgApCliBssid, sizeof(NDIS_802_11_MAC_ADDRESS)); + + + DBGPRINT(RT_DEBUG_INFO, ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + pApCliEntry->CfgApCliBssid[0],pApCliEntry->CfgApCliBssid[1],pApCliEntry->CfgApCliBssid[2], + pApCliEntry->CfgApCliBssid[3],pApCliEntry->CfgApCliBssid[4],pApCliEntry->CfgApCliBssid[5])); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n")); + Status = -ENOTCONN; + } + break; + case OID_802_11_SSID: + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry=&pAd->ApCfg.ApCliTab[ifIndex]; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + if (!apcliEn) + return FALSE; + + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + Ssid.SsidLength = pApCliEntry->CfgSsidLen; + NdisMoveMemory(Ssid.Ssid, pApCliEntry->CfgSsid,Ssid.SsidLength); + wrq->u.data.length = sizeof(NDIS_802_11_SSID); + Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query Apcli::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid)); + break; +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + + + case RT_OID_802_11_PHY_MODE: + ulInfo = (ULONG)pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PhyMode; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld), %s\n", ulInfo, wmode_2_str(pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PhyMode))); + break; + + + case OID_802_11_CHANNEL_WIDTH: + { + wrq->u.data.length = sizeof(pAd->CommonCfg.BBPCurrentBW); + ulInfo = pAd->CommonCfg.BBPCurrentBW; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CHANNEL_WIDTH (%lu)\n",ulInfo)); + break; + } + break; + + + case RT_OID_802_11_COUNTRY_REGION: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.CountryRegionForABand; + ulInfo = (ulInfo << 8)|(pAd->CommonCfg.CountryRegion); + if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION (%lu)\n",ulInfo)); + break; + + case OID_802_11_BEACON_PERIOD: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.BeaconPeriod; + if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BEACON_PERIOD (%lu)\n",ulInfo)); + break; + + case RT_OID_802_11_TX_POWER_LEVEL_1: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.TxPowerPercentage; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.TxPowerPercentage, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); + break; + + case RT_OID_802_11_QUERY_WMM: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n",pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable)); + break; + + case OID_802_11_BSSID: + { +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + ifIndex = pObj->ioctl_if; + pApCliEntry=&pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if (!apcliEn) + { + printk("==>OID_802_11_BSSID !apcliEn\n"); + return FALSE; + } + + if (pApCliEntry->Valid) + { + Status = copy_to_user(wrq->u.data.pointer, wdev->bssid, sizeof(NDIS_802_11_MAC_ADDRESS)); + + + DBGPRINT(RT_DEBUG_OFF, ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + wdev->bssid[0],wdev->bssid[1],wdev->bssid[2], + wdev->bssid[3],wdev->bssid[4],wdev->bssid[5])); + + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("!pApCliEntry->Valid\n")); + Status = -ENOTCONN; + } + } else +#endif /*APCLI_SUPPORT*/ + { + + struct wifi_dev *wdev; + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &wdev->bssid[0], wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID (%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(wdev->bssid))); + } + + break; + } + + case RT_OID_802_11_PREAMBLE: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.TxPreamble; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%lu)\n", pAd->CommonCfg.TxPreamble)); + break; + + case OID_802_11_HT_STBC: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.RegTransmitSetting.field.STBC; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_HT_STBC(=%u)\n", pAd->CommonCfg.RegTransmitSetting.field.STBC)); + break; + + case OID_802_11_UAPSD: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].UapsdInfo.bAPSDCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_UAPSD (=%d)\n",pAd->ApCfg.MBSSID[pObj->ioctl_if].UapsdInfo.bAPSDCapable)); + break; + + case OID_802_11_TX_PACKET_BURST: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bEnableTxBurst, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_PACKET_BURST (=%d)\n",pAd->CommonCfg.bEnableTxBurst)); + break; + +#ifdef DOT11N_DRAFT3 + case OID_802_11_COEXISTENCE: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bBssCoexEnable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_COEXISTENCE (=%d)\n",pAd->CommonCfg.bBssCoexEnable)); + break; +#endif + + case OID_802_11_AMSDU: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.BACapability.field.AmsduEnable; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AMSDU (=%lu)\n",ulInfo)); + break; + + case OID_802_11_AMPDU: + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.BACapability.field.AutoBA; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AMPDU (=%lu)\n",ulInfo)); + break; + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n")); + wrq->u.data.length = sizeof(UCHAR); + DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAd->CommonCfg.Channel)); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Channel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; + + case RT_OID_VERSION_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n")); + wrq->u.data.length = strlen(AP_DRIVER_VERSION); + snprintf(&driverVersion[0], sizeof(driverVersion), "%s", AP_DRIVER_VERSION); + driverVersion[wrq->u.data.length] = '\0'; + if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + + case OID_802_11_ASSOLIST: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_ASSOLIST \n")); + RTMPAPGetAssoMacTable(pAd,wrq); + break; + + case OID_802_11_NETWORK_TYPES_SUPPORTED: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED \n")); + wrq->u.data.length = sizeof(UCHAR); + if (copy_to_user(wrq->u.data.pointer, &pAd->RfIcType, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + +#ifdef IAPP_SUPPORT + case RT_QUERY_SIGNAL_CONTEXT: + { + BOOLEAN FlgIs11rSup = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_SIGNAL_CONTEXT \n")); + +#ifdef DOT11R_FT_SUPPORT + FlgIs11rSup = TRUE; +#endif /* DOT11R_FT_SUPPORT */ + + if (FlgIs11rSup == FALSE) + { + { + Status = -EFAULT; + } + } +#ifdef DOT11R_FT_SUPPORT + else + { + FT_KDP_SIGNAL *pFtKdp; + FT_KDP_EVT_HEADER *pEvtHdr; + + + /* query signal content for 11r */ + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_FT_KDP_CONTEXT \n")); + + FT_KDP_EventGet(pAd, &pFtKdp); + if (pFtKdp != NULL) + pEvtHdr = (FT_KDP_EVT_HEADER *)pFtKdp->Content; + /* End of if */ + + if ((pFtKdp != NULL) && + ((RT_SIGNAL_STRUC_HDR_SIZE + pEvtHdr->EventLen) <= + wrq->u.data.length)) + { + /* copy the event */ + if (copy_to_user( + wrq->u.data.pointer, + pFtKdp, + RT_SIGNAL_STRUC_HDR_SIZE + pEvtHdr->EventLen)) + { + wrq->u.data.length = 0; + Status = -EFAULT; + } + else + { + wrq->u.data.length = RT_SIGNAL_STRUC_HDR_SIZE; + wrq->u.data.length += pEvtHdr->EventLen; + } + + FT_MEM_FREE(pAd, pFtKdp); + } + else + { + /* no event is queued */ + DBGPRINT(RT_DEBUG_TRACE, ("ft_kdp> no event is queued!\n")); + wrq->u.data.length = 0; + } + } +#endif /* DOT11R_FT_SUPPORT */ + } + break; + +#ifdef DOT11R_FT_SUPPORT + case RT_FT_DATA_ENCRYPT: + case RT_FT_DATA_DECRYPT: + { + UCHAR *pBuffer; + UINT32 DataLen; + + DataLen = wrq->u.data.length; + + /* + Make sure the data length is multiple of 8 + due to AES_KEY_WRAP() limitation. + */ + if (DataLen & 0x07) + DataLen += 8 - (DataLen & 0x07); + /* End of if */ + + FT_MEM_ALLOC(pAd, &pBuffer, DataLen+FT_KDP_KEY_ENCRYPTION_EXTEND); + if (pBuffer == NULL) + break; + NdisZeroMemory(pBuffer, DataLen+FT_KDP_KEY_ENCRYPTION_EXTEND); + + if (copy_from_user(pBuffer, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + FT_MEM_FREE(pAd, pBuffer); + break; + } + + switch(cmd) + { + case RT_FT_DATA_ENCRYPT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_FT_DATA_ENCRYPT \n")); + FT_KDP_DataEncrypt(pAd, (UCHAR *)pBuffer, &DataLen); + break; + + case RT_FT_DATA_DECRYPT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_FT_DATA_DECRYPT \n")); + FT_KDP_DataDecrypt(pAd, (UCHAR *)pBuffer, &DataLen); + break; + } + + wrq->u.data.length = DataLen; + if (copy_to_user(wrq->u.data.pointer, pBuffer, wrq->u.data.length)) + Status = -EFAULT; + FT_MEM_FREE(pAd, pBuffer); + } + break; + + case RT_OID_802_11R_INFO: + { + UCHAR apidx = pObj->ioctl_if; + PFT_CONFIG_INFO pFtConfig; + PFT_CFG pFtCfg; + +/* pFtConfig = kmalloc(sizeof(FT_CONFIG_INFO), GFP_ATOMIC); */ + os_alloc_mem(pAd, (UCHAR **)&pFtConfig, sizeof(FT_CONFIG_INFO)); + if (pFtConfig == NULL) + break; + + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + NdisZeroMemory(pFtConfig, sizeof(FT_CONFIG_INFO)); + + pFtConfig->FtSupport = pFtCfg->FtCapFlag.Dot11rFtEnable; + pFtConfig->FtRicSupport = pFtCfg->FtCapFlag.RsrReqCap; + pFtConfig->FtOtdSupport = pFtCfg->FtCapFlag.FtOverDs; + NdisMoveMemory(pFtConfig->MdId, pFtCfg->FtMdId, FT_MDID_LEN); + pFtConfig->R0KHIdLen = pFtCfg->FtR0khIdLen; + NdisMoveMemory(pFtConfig->R0KHId, pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen); + + wrq->u.data.length = sizeof(FT_CONFIG_INFO); + Status = copy_to_user(wrq->u.data.pointer, pFtConfig, wrq->u.data.length); + os_free_mem(NULL, pFtConfig); + } + break; +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* IAPP_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT + case RT_OID_WSC_QUERY_STATUS: + { + INT WscStatus; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_STATUS \n")); +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + INT ApCliIdx = pObj->ioctl_if; + APCLI_MR_APIDX_SANITY_CHECK(ApCliIdx); + WscStatus = pAd->ApCfg.ApCliTab[ApCliIdx].WscControl.WscStatus; + } + else +#endif /* APCLI_SUPPORT */ + { + WscStatus = pAd->ApCfg.MBSSID[apidx].WscControl.WscStatus; + } + + wrq->u.data.length = sizeof(INT); + if (copy_to_user(wrq->u.data.pointer, &WscStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + } + case RT_OID_WSC_PIN_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_PIN_CODE \n")); + wrq->u.data.length = sizeof(UINT); + /*WscPinCode = GenerateWpsPinCode(pAd, FALSE, apidx); */ + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + WscPinCode = pWscControl->WscEnrolleePinCode; + if (copy_to_user(wrq->u.data.pointer, &WscPinCode, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#ifdef APCLI_SUPPORT + case RT_OID_APCLI_WSC_PIN_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_APCLI_WSC_PIN_CODE \n")); + wrq->u.data.length = sizeof(UINT); + /*WscPinCode = GenerateWpsPinCode(pAd, TRUE, apidx); */ + WscPinCode = pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode; + + if (copy_to_user(wrq->u.data.pointer, &WscPinCode, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* APCLI_SUPPORT */ + case RT_OID_WSC_UUID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_UUID \n")); + wrq->u.data.length = UUID_LEN_STR; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + if (copy_to_user(wrq->u.data.pointer, &pWscControl->Wsc_Uuid_Str[0], UUID_LEN_STR)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_MAC_ADDRESS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_MAC_ADDRESS \n")); + wrq->u.data.length = MAC_ADDR_LEN; + if (copy_to_user(wrq->u.data.pointer, pAd->ApCfg.MBSSID[apidx].wdev.bssid, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_CONFIG_STATUS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_CONFIG_STATUS \n")); + wrq->u.data.length = sizeof(UCHAR); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + + case RT_OID_WSC_QUERY_PEER_INFO_ON_RUNNING: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_PEER_INFO_ON_RUNNING \n")); + + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscState > WSC_STATE_WAIT_M2) + { + wrq->u.data.length = sizeof(WSC_PEER_DEV_INFO); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscPeerInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + } + else + { + Status = -EFAULT; + } + break; + + case RT_OID_802_11_WSC_QUERY_PROFILE: + wrq->u.data.length = sizeof(WSC_PROFILE); +/* pProfile = kmalloc(sizeof(WSC_PROFILE), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&pProfile, sizeof(WSC_PROFILE)); + if (pProfile == NULL) + { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_WSC_QUERY_PROFILE fail!\n")); + break; + } + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + RTMPZeroMemory(pProfile, sizeof(WSC_PROFILE)); + NdisMoveMemory(pProfile, &pWscControl->WscProfile, sizeof(WSC_PROFILE)); + if ((pProfile->Profile[0].AuthType == WSC_AUTHTYPE_OPEN) && (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_NONE)) + { + pProfile->Profile[0].KeyLength = 0; + NdisZeroMemory(pProfile->Profile[0].Key, 64); + } + if (copy_to_user(wrq->u.data.pointer, pProfile, wrq->u.data.length)) + { + Status = -EFAULT; + } + + os_free_mem(NULL, pProfile); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WSC_QUERY_PROFILE \n")); + break; +#ifdef SMART_MESH + case RT_OID_LAST_TX_RX_STATS: + { + MAC_TABLE_ENTRY *pQueryEntry = NULL; + BOOLEAN bFound = FALSE; + int total_size = 0; + for (i=1; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pQueryEntry) || IS_ENTRY_APCLI(pQueryEntry)) +#ifdef MAC_REPEATER_SUPPORT + && (pQueryEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + && (pQueryEntry->Sst == SST_ASSOC) + && MAC_ADDR_EQUAL(pQueryEntry->Addr,pAd->ApCfg.CliPktMac)) + { + total_size = sizeof(pQueryEntry->CliPktStat); + bFound = TRUE; + break; + } + } + + if(bFound) + { + if(wrq->u.data.length > total_size) + wrq->u.data.length = total_size; + + if (copy_to_user(wrq->u.data.pointer, &pQueryEntry->CliPktStat, wrq->u.data.length)) + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::GET RT_OID_LAST_TX_RX_STATS, bFound=%d\n",bFound)); + } + break; + case RT_OID_GET_PKT_TX_RX_STATS: + { + PPKT_TX_RX_INFO pkt_info; + BA_ORI_ENTRY *pOriBAEntry; + RTS_TX_CNT_STRUC RtsCount; + MAC_TABLE_ENTRY *pEntry = NULL; + ULONG per; + INT j , k, entry_num = 0; + INT period_us = 0; + UINT32 ed_stats; + ULONG busy_time = 0, idle_time = 0; + + os_alloc_mem(pAd, (UCHAR **)&pkt_info, sizeof(PKT_TX_RX_INFO)); + + if (pkt_info == NULL) + { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_OFF, ("RT_OID_GET_PKT_TX_RX_STATS fail!\n")); + break; + } + + RTMPZeroMemory(pkt_info, sizeof(PKT_TX_RX_INFO)); + + per = pAd->WlanCounters.ReceivedFragmentCount.u.LowPart==0? \ + 0: 1000*(pAd->WlanCounters.FCSErrorCount.u.LowPart)/(pAd->WlanCounters.FCSErrorCount.u.LowPart+pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + + pkt_info->rx_pkt_error_rate = per; + pkt_info->tx_acked_num = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + pkt_info->false_cca_count = pAd->RalinkCounters.FalseCCACnt; + + RTMP_IO_READ32(pAd, 0x1140, &ed_stats); + RTMP_IO_READ32(pAd, CH_BUSY_STA, &busy_time); + RTMP_IO_READ32(pAd, CH_IDLE_STA, &idle_time); + pAd->ChannelTimerCounters.EdBusyTime += ed_stats; + pAd->ChannelTimerCounters.ChBusyTime += busy_time; + pAd->ChannelTimerCounters.ChIdleTime += idle_time; + + pkt_info->edcca_busy_time = pAd->ChannelTimerCounters.EdBusyTime; + pkt_info->channel_busy_time = pAd->ChannelTimerCounters.ChBusyTime; + pkt_info->channel_idle_time = pAd->ChannelTimerCounters.ChIdleTime; + + NicGetTxRTSCounters(pAd, &RtsCount); + pkt_info->rts_success_count = RtsCount.field.RtsTxOkCount; + pkt_info->rts_fail_count = RtsCount.field.RtsTxFailCount; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /*Still scanning*/ + DBGPRINT(RT_DEBUG_ERROR, ("Query::RT_OID_GET_PKT_TX_RX_STATS (Still scanning)\n")); + } + else + { + pkt_info->channel_list_num = pAd->ChannelListNum; + for (k=0; k < pAd->ChannelListNum; k++) + { + pkt_info->channel_list[k].channel = pAd->ChannelList[k].Channel; + pkt_info->channel_list[k].false_cca = pAd->ChannelList[k].FalseCCA; + } + } + pkt_info->entry_num = 0; + + for (i=1; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + && (pEntry->Sst == SST_ASSOC)) + { + COPY_MAC_ADDR(pkt_info->entry[pkt_info->entry_num].mac, &pEntry->Addr); + pkt_info->entry[pkt_info->entry_num].aid = pEntry->Aid; + pkt_info->entry[pkt_info->entry_num].tx_acked_packet = (ULONG)pEntry->TxPackets.QuadPart; + /* TxPER is per secound */ + pkt_info->entry[pkt_info->entry_num].tx_per = pEntry->LastTxPER; + + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + { + pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; + pkt_info->entry[pkt_info->entry_num].agg_size = pOriBAEntry->BAWinSize; + break; + } + } + pkt_info->entry_num++; + } + } + + wrq->u.data.length = sizeof(PKT_TX_RX_INFO); + if (copy_to_user(wrq->u.data.pointer, pkt_info, wrq->u.data.length)) + { + Status = -EFAULT; + } + + os_free_mem(NULL, pkt_info); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_GET_PKT_TX_RX_STATS \n")); + } + break; + + case RT_OID_GET_AP_LIST: + { + AP_LIST_INFO *ap_list = NULL; + BSS_ENTRY *pBss; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + DBGPRINT(RT_DEBUG_OFF, ("Query::RT_OID_GET_AP_LIST (Still scanning)\n")); + return -EAGAIN; + } + + os_alloc_mem(pAd, (UCHAR **)&ap_list, sizeof(AP_LIST_INFO)); + + if (ap_list == NULL) + { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_OFF, ("RT_OID_GET_AP_LIST fail!\n")); + break; + } + + NdisZeroMemory(ap_list, sizeof(AP_LIST_INFO)); + + ap_list->num = pAd->ScanTab.BssNr; + ap_list->channel = pAd->CommonCfg.Channel; + + for(i=0; iScanTab.BssNr ;i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if (pBss->Channel==0) + break; + + if (pBss->Channel == pAd->CommonCfg.Channel) + ap_list->channel_ap_num++; + + if (RTMPCheckStrPrintAble((PCHAR)pBss->Ssid, pBss->SsidLen)) + { + NdisMoveMemory(ap_list->ap[i].ssid, pBss->Ssid, pBss->SsidLen); + } + else + { + INT idx = 0; + sprintf(ap_list->ap[i].ssid, "0x"); + for (idx = 0; (idx < 14) && (idx < pBss->SsidLen); idx++) + sprintf(ap_list->ap[i].ssid + 2 + (idx*2), "%02X", (UCHAR)pBss->Ssid[idx]); + + } + + ap_list->ap[i].ssid_len = pBss->SsidLen; + ap_list->ap[i].channel = pBss->Channel; + ap_list->ap[i].bw = pBss->BW; + ap_list->ap[i].rssi = pAd->ScanTab.BssEntry[i].Rssi - pAd->BbpRssiToDbmDelta; + } + + wrq->u.data.length = sizeof(AP_LIST_INFO); + if (copy_to_user(wrq->u.data.pointer, ap_list, wrq->u.data.length)) + { + Status = -EFAULT; + } + + os_free_mem(NULL, ap_list); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_GET_AP_LIST \n")); + } + break; + +#endif /* SMART_MESH */ +#ifdef WSC_V2_SUPPORT + case RT_OID_WSC_V2_SUPPORT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_V2_SUPPORT (=%d)\n", pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2)); + wrq->u.data.length = sizeof(BOOLEAN); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_FRAGMENT_SIZE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_FRAGMENT_SIZE (=%d)\n", pAd->ApCfg.MBSSID[apidx].WscControl.WscFragSize)); + wrq->u.data.length = sizeof(USHORT); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscFragSize, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* WSC_V2_SUPPORT */ + +#ifdef WSC_NFC_SUPPORT + case RT_OID_NFC_STATUS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NFC_STATUS (=%d)\n", pAd->ApCfg.MBSSID[apidx].WscControl.NfcStatus)); + wrq->u.data.length = sizeof(UCHAR); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.NfcStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* WSC_NFC_SUPPORT */ + +#endif /* WSC_AP_SUPPORT */ +#ifdef LLTD_SUPPORT + case RT_OID_GET_LLTD_ASSO_TABLE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get LLTD association table\n")); + if ((wrq->u.data.pointer == NULL) || (apidx != MAIN_MBSSID)) + { + Status = -EFAULT; + } + else + { + INT i; + RT_LLTD_ASSOICATION_TABLE AssocTab; + + AssocTab.Num = 0; + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + if (AssocTab.Num < 64) /* avoid the size out of definition from LLTD daemon */ + { + COPY_MAC_ADDR(AssocTab.Entry[AssocTab.Num].Addr, &pAd->MacTab.Content[i].Addr); + AssocTab.Entry[AssocTab.Num].phyMode = pAd->CommonCfg.PhyMode; + AssocTab.Entry[AssocTab.Num].MOR = RateIdToMbps[pAd->ApCfg.MBSSID[apidx].MaxTxRate] * 2; + AssocTab.Num += 1; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Query::Get LLTD association table But of out table\n")); + break; + } + } + } + + wrq->u.data.length = sizeof(RT_LLTD_ASSOICATION_TABLE); + if (copy_to_user(wrq->u.data.pointer, &AssocTab, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("AssocTab.Num = %d \n", AssocTab.Num)); + } + break; +#ifdef APCLI_SUPPORT + case RT_OID_GET_REPEATER_AP_LINEAGE: + DBGPRINT(RT_DEBUG_TRACE, ("Not Support : Get repeater AP lineage.\n")); + break; +#endif /* APCLI_SUPPORT */ + +#endif /* LLTD_SUPPORT */ +#ifdef DOT1X_SUPPORT + case OID_802_DOT1X_CONFIGURATION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get Radius setting(%d)\n", sizeof(DOT1X_CMM_CONF))); + RTMPIoctlQueryRadiusConf(pAd, wrq); + break; + + case OID_802_DOT1X_QUERY_STA_AID: + RTMPIoctlQueryStaAid(pAd, wrq); + break; + +#endif /* DOT1X_SUPPORT */ + + case RT_OID_802_11_MAC_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].wdev.bssid, wrq->u.data.length); + break; + +#ifdef SNMP_SUPPORT + case RT_OID_802_11_MANUFACTUREROUI: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n")); + wrq->u.data.length = ManufacturerOUI_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTURERNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case RT_OID_802_11_RESOURCETYPEIDNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n")); + wrq->u.data.length = strlen(ResourceTypeIdName); + Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length); + break; + + case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED: + { + ULONG ulInfo; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n")); + ulInfo = 1; /* 1 is support wep else 2 is not support. */ + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + } + case RT_OID_802_11_POWERMANAGEMENTMODE: + { + ULONG ulInfo; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n")); + ulInfo = 1; /* 1 is power active else 2 is power save. */ + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + } + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n")); + pKeyIdxValue = (DefaultKeyIdxValue*)wrq->u.data.pointer; + DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx)); + + valueLen = pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId].KeyLen; + NdisMoveMemory(pKeyIdxValue->Value, + &pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId].Key, + valueLen); + pKeyIdxValue->Value[valueLen]='\0'; + + wrq->u.data.length = sizeof(DefaultKeyIdxValue); + + Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", pAd->ApCfg.MBSSID[pObj->ioctl_if].DefaultKeyId, wrq->u.data.length, pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].DefaultKeyId].KeyLen, + pAd->SharedKey[pObj->ioctl_if][0].Key[0], + pAd->SharedKey[pObj->ioctl_if][1].Key[0], + pAd->SharedKey[pObj->ioctl_if][2].Key[0], + pAd->SharedKey[pObj->ioctl_if][3].Key[0])); + break; + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId)); + break; + + case RT_OID_802_11_WEPKEYMAPPINGLENGTH: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, + &pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DefaultKeyId].KeyLen, + wrq->u.data.length); + break; + + case OID_802_11_SHORTRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit; + DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld, tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit)); + Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length); + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + LongRetryLimit = tx_rty_cfg.field.LongRtyLimit; + DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld, tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit)); + Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length); + break; + + case RT_OID_802_11_PRODUCTID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); + +#ifdef RTMP_MAC_PCI + { + + USHORT device_id; + if (((POS_COOKIE)pAd->OS_Cookie)->pci_dev != NULL) + pci_read_config_word(((POS_COOKIE)pAd->OS_Cookie)->pci_dev, PCI_DEVICE_ID, &device_id); + else + DBGPRINT(RT_DEBUG_TRACE, (" pci_dev = NULL\n")); + snprintf((PSTRING)snmp_tmp, sizeof(snmp_tmp), "%04x %04x\n", NIC_PCI_VENDOR_ID, device_id); + } +#endif /* RTMP_MAC_PCI */ + wrq->u.data.length = strlen((PSTRING) snmp_tmp); + Status = copy_to_user(wrq->u.data.pointer, snmp_tmp, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + +#endif /* SNMP_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + case OID_802_11_MBSS_STATISTICS: + RTMPIoctlQueryMbssStat(pAd, wrq); + break; +#endif +#endif + case OID_802_11_STATISTICS: +/* pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&pStatistics, sizeof(NDIS_802_11_STATISTICS)); + if (pStatistics) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n")); + /* add the most up-to-date h/w raw counters into software counters */ + /*NICUpdateRawCounters(pAd);*/ + + pStatistics->TransmittedFragmentCount.QuadPart = pAd->WlanCounters.TransmittedFragmentCount.QuadPart + pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart; + pStatistics->MulticastTransmittedFrameCount.QuadPart = pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart; + pStatistics->FailedCount.QuadPart = pAd->WlanCounters.FailedCount.QuadPart; + pStatistics->RetryCount.QuadPart = pAd->WlanCounters.RetryCount.QuadPart; + pStatistics->MultipleRetryCount.QuadPart = pAd->WlanCounters.MultipleRetryCount.QuadPart; + pStatistics->RTSSuccessCount.QuadPart = pAd->WlanCounters.RTSSuccessCount.QuadPart; + pStatistics->RTSFailureCount.QuadPart = pAd->WlanCounters.RTSFailureCount.QuadPart; + pStatistics->ACKFailureCount.QuadPart = pAd->WlanCounters.ACKFailureCount.QuadPart; + pStatistics->FrameDuplicateCount.QuadPart = pAd->WlanCounters.FrameDuplicateCount.QuadPart; + pStatistics->ReceivedFragmentCount.QuadPart = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + pStatistics->MulticastReceivedFrameCount.QuadPart = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; +#ifdef DBG + pStatistics->FCSErrorCount = pAd->RalinkCounters.RealFcsErrCount; +#else + pStatistics->FCSErrorCount.QuadPart = pAd->WlanCounters.FCSErrorCount.QuadPart; + pStatistics->FrameDuplicateCount.u.LowPart = pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100; +#endif + pStatistics->TransmittedFrameCount.QuadPart = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; + pStatistics->WEPUndecryptableCount.QuadPart = pAd->WlanCounters.WEPUndecryptableCount.QuadPart; + wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS); + Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length); +/* kfree(pStatistics); */ + os_free_mem(NULL, pStatistics); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + + case RT_OID_802_11_PER_BSS_STATISTICS: + { + PMBSS_STATISTICS pMbssStat; + INT apidx = pObj->ioctl_if; + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + + os_alloc_mem(pAd, (UCHAR * *) &pMbssStat, sizeof(MBSS_STATISTICS)); + NdisZeroMemory(pMbssStat, sizeof(MBSS_STATISTICS)); + + pMbssStat->TransmittedByteCount = pMbss->TransmittedByteCount.u.LowPart; + pMbssStat->ReceivedByteCount = pMbss->ReceivedByteCount.u.LowPart; + pMbssStat->TxCount = pMbss->TxCount; + pMbssStat->RxCount = pMbss->RxCount; + pMbssStat->RxErrorCount = pMbss->RxErrorCount; + pMbssStat->RxDropCount = pMbss->RxDropCount; + pMbssStat->TxErrorCount = pMbss->TxErrorCount; + pMbssStat->TxDropCount = pMbss->TxDropCount; + pMbssStat->ucPktsTx = pMbss->ucPktsTx; + pMbssStat->ucPktsRx = pMbss->ucPktsRx; + pMbssStat->mcPktsTx = pMbss->mcPktsTx; + pMbssStat->mcPktsRx = pMbss->mcPktsRx; + pMbssStat->bcPktsTx= pMbss->bcPktsTx; + pMbssStat->bcPktsRx= pMbss->bcPktsRx; + wrq->u.data.length = sizeof(MBSS_STATISTICS); + copy_to_user(wrq->u.data.pointer, pMbssStat, wrq->u.data.length); + os_free_mem(pAd, pMbssStat); + } + break; + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT + case RT_OID_802_11_QUERY_TXBF_TABLE: + if (!pAd->chipCap.FlgHwTxBfCap) + Status = -EFAULT; + else + { + INT i; + RT_802_11_TXBF_TABLE *pMacTab = NULL; + + os_alloc_mem(pAd, (UCHAR **) &pMacTab, sizeof(RT_802_11_TXBF_TABLE)); + if (!pMacTab) { + Status = -ENOMEM; + break; + } + NdisZeroMemory(pMacTab, sizeof(RT_802_11_TXBF_TABLE)); + + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + memcpy(&pMacTab->Entry[pMacTab->Num], &pAd->MacTab.Content[i].TxBFCounters, sizeof(RT_COUNTER_TXBF)); + pMacTab->Num++; + } + } + + wrq->u.data.length = sizeof(RT_802_11_TXBF_TABLE); + Status = copy_to_user(wrq->u.data.pointer, pMacTab, wrq->u.data.length); + os_free_mem(pAd, pMacTab); + } + break; +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + +#ifdef WAPI_SUPPORT + case OID_802_11_MCAST_TXIV: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MCAST_TXIV \n")); + Status = -EINVAL; + break; + case OID_802_11_WAPI_CONFIGURATION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get WAPI Configuration(%d)\n", sizeof(WAPI_CONF))); + RTMPIoctlQueryWapiConf(pAd, wrq); + break; + case OID_802_11_WAPI_IE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WAPI_IE\n")); + if (wrq->u.data.length != sizeof(WAPI_WIE_STRUCT)) + Status = -EINVAL; + else + { + WAPI_WIE_STRUCT wapi_ie; + MAC_TABLE_ENTRY *pWapiEntry; + + NdisZeroMemory(&wapi_ie, sizeof(WAPI_WIE_STRUCT)); + NdisMoveMemory(wapi_ie.addr, wrq->u.data.pointer, MAC_ADDR_LEN); + + pWapiEntry = MacTableLookup(pAd, wapi_ie.addr); + + if (pWapiEntry && IS_ENTRY_CLIENT(pWapiEntry) && (pWapiEntry->RSNIE_Len > 0)) + { + wapi_ie.wie_len = pWapiEntry->RSNIE_Len; + NdisMoveMemory(wapi_ie.wie, pWapiEntry->RSN_IE, pWapiEntry->RSNIE_Len); + } + + if (copy_to_user(wrq->u.data.pointer, &wapi_ie, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + break; + + case OID_802_11_MCAST_KEY_INFO: + { + PMULTISSID_STRUCT pMbss; + WAPI_MCAST_KEY_STRUCT wapi_mkey; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MCAST_KEY_INFO\n")); + + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + NdisZeroMemory(&wapi_mkey, sizeof(WAPI_MCAST_KEY_STRUCT)); + + if (pMbss->sw_wpi_encrypt) + { + NdisMoveMemory(wapi_mkey.m_tx_iv, + pAd->SharedKey[pObj->ioctl_if][pMbss->wdev.DefaultKeyId].TxTsc, + LEN_WAPI_TSC); + } + else + { + INT m_wcid; + + GET_GroupKey_WCID(pAd, m_wcid, apidx); + RTMPGetWapiTxTscFromAsic(pAd, m_wcid, wapi_mkey.m_tx_iv); + } + wapi_mkey.key_id = pMbss->wdev.DefaultKeyId; + NdisMoveMemory(wapi_mkey.key_announce, pMbss->key_announce_flag, LEN_WAPI_TSC); + NdisMoveMemory(wapi_mkey.NMK, pMbss->NMK, 16); + + wrq->u.data.length = sizeof(WAPI_MCAST_KEY_STRUCT); + Status = copy_to_user(wrq->u.data.pointer, &wapi_mkey, wrq->u.data.length); + } + break; + +#endif /* WAPI_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + + case HOSTAPD_OID_GETWPAIE:/*report wpa ie of the new station to hostapd. */ + + if (wrq->u.data.length != sizeof(wpaie)) + { + Status = -EINVAL; + } + else if (copy_from_user(&wpaie, wrq->u.data.pointer, IEEE80211_ADDR_LEN)) + { + Status = -EFAULT; + } + else + { + pEntry = MacTableLookup(pAd, wpaie.wpa_macaddr); + if (!pEntry){ + Status = -EINVAL; + break; + } + NdisZeroMemory(wpaie.rsn_ie,sizeof(wpaie.rsn_ie)); + /* For WPA1, RSN_IE=221 */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) + ||(pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA1WPA2) ||(pEntry->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + ) + { + int ielen = pEntry->RSNIE_Len; + DBGPRINT(RT_DEBUG_TRACE, ("pEntry->RSNIE_Len=%d\n",pEntry->RSNIE_Len)); + if (ielen > sizeof(wpaie.rsn_ie)) + ielen = sizeof(wpaie.rsn_ie)-1; + p = wpaie.rsn_ie; + hex_dump("HOSTAPD_OID_GETWPAIE woody==>pEntry->RSN_IE", (unsigned char*)pEntry->RSN_IE,ielen); + NdisMoveMemory(p, pEntry->RSN_IE, ielen); + } + } + if(copy_to_user(wrq->u.data.pointer, &wpaie, sizeof(wpaie))) + Status = -EFAULT; + break; + + + case HOSTAPD_OID_GET_SEQ:/*report txtsc to hostapd. */ + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + if (wrq->u.data.length != sizeof(ik)) + { + Status = -EINVAL; + } + else if (copy_from_user(&ik, wrq->u.data.pointer, IEEE80211_ADDR_LEN)) + { + Status = -EFAULT; + } + else + { + NdisZeroMemory(&ik.ik_keytsc, sizeof(ik.ik_keytsc)); + p = (unsigned char *)&ik.ik_keytsc; + NdisMoveMemory(p+2, pAd->SharedKey[apidx][ pMbss->DefaultKeyId].TxTsc, 6); + if(copy_to_user(wrq->u.data.pointer, &ik, sizeof(ik))) + Status = -EFAULT; + } + break; + + + case HOSTAPD_OID_GET_1X_GROUP_KEY:/*report default group key to hostapd. */ + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + if (wrq->u.data.length != sizeof(group_key)) + { + Status = -EINVAL; + } + else + { + if(pAd->SharedKey[apidx][ pMbss->DefaultKeyId].KeyLen!=0 && pAd->SharedKey[apidx][ pMbss->DefaultKeyId].Key!=NULL) + { + group_key.ik_keyix = pMbss->DefaultKeyId; + group_key.ik_keylen = pAd->SharedKey[apidx][ pMbss->DefaultKeyId].KeyLen; + NdisMoveMemory(group_key.ik_keydata, pAd->SharedKey[apidx][ pMbss->DefaultKeyId].Key,pAd->SharedKey[apidx][ pMbss->DefaultKeyId].KeyLen); + if(copy_to_user(wrq->u.data.pointer, &group_key, sizeof(group_key))) + Status = -EFAULT; + } + } + break; + +#endif/*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + case OID_GEN_MEDIA_CONNECT_STATUS: + { + ULONG ApCliIdx = pObj->ioctl_if; + + NDIS_MEDIA_STATE MediaState; + PMAC_TABLE_ENTRY pEntry; + PAPCLI_STRUCT pApCliEntry; + + if (pObj->ioctl_if_type != INT_APCLI) + { + Status = -EOPNOTSUPP; + break; + } + else + { + APCLI_MR_APIDX_SANITY_CHECK(ApCliIdx); + pApCliEntry = &pAd->ApCfg.ApCliTab[ApCliIdx]; + pEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + + if (!IS_ENTRY_APCLI(pEntry)) + { + Status = -EOPNOTSUPP; + break; + } + + if ((pAd->ApCfg.ApCliTab[ApCliIdx].Valid == TRUE) + && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + MediaState = NdisMediaStateConnected; + else + MediaState = NdisMediaStateDisconnected; + + wrq->u.data.length = sizeof(NDIS_MEDIA_STATE); + Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length); + } + } + break; +#endif /* APCLI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + case RT_OID_802_11_SNR_0: + if ((pAd->ApCfg.LastSNR0 > 0)) + { + ULONG ulInfo; + ulInfo = ConvertToSnr(pAd, pAd->ApCfg.LastSNR0); + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo)); + } + else + Status = -EFAULT; + break; + case RT_OID_802_11_SNR_1: + if ((pAd->Antenna.field.RxPath > 1) && + (pAd->ApCfg.LastSNR1 > 0)) + { + ULONG ulInfo; + ulInfo = ConvertToSnr(pAd, pAd->ApCfg.LastSNR1); + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo)); + } + else + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAd->ApCfg.LastSNR1=%d)\n",pAd->ApCfg.LastSNR1)); + break; +#ifdef DOT11N_SS3_SUPPORT + case RT_OID_802_11_SNR_2: + if ((pAd->Antenna.field.RxPath > 2) && + (pAd->ApCfg.LastSNR2 > 0)) + { + ULONG ulInfo; + ulInfo = ConvertToSnr(pAd, pAd->ApCfg.LastSNR2); + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_2(0x=%lx)\n",ulInfo)); + } + else + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_2(pAd->ApCfg.LastSNR2=%d)\n",pAd->ApCfg.LastSNR2)); + break; +#endif /* DOT11N_SS3_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + + + + case OID_802_11_ACL_LIST: + if (wrq->u.data.length < sizeof(RT_802_11_ACL)) + { + Status = -EINVAL; + } + else + { + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + } + break; +#ifdef CONFIG_HOTSPOT +#ifdef CONFIG_DOT11V_WNM + case OID_802_11_WNM_IPV4_PROXY_ARP_LIST: + { + PMULTISSID_STRUCT pMbss; + PUCHAR pProxyARPTable; + UINT32 ARPTableLen; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + ARPTableLen = IPv4ProxyARPTableLen(pAd, pMbss); + os_alloc_mem(NULL, &pProxyARPTable, ARPTableLen); + GetIPv4ProxyARPTable(pAd, pMbss, &pProxyARPTable); + wrq->u.data.length = ARPTableLen; + Status = copy_to_user(wrq->u.data.pointer, pProxyARPTable, ARPTableLen); + os_free_mem(NULL, pProxyARPTable); + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WNM_PROXY_ARP_LIST\n")); + break; + case OID_802_11_WNM_IPV6_PROXY_ARP_LIST: + { + PMULTISSID_STRUCT pMbss; + PUCHAR pProxyARPTable; + UINT32 ARPTableLen; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + ARPTableLen = IPv6ProxyARPTableLen(pAd, pMbss); + os_alloc_mem(NULL, &pProxyARPTable, ARPTableLen); + GetIPv6ProxyARPTable(pAd, pMbss, &pProxyARPTable); + wrq->u.data.length = ARPTableLen; + Status = copy_to_user(wrq->u.data.pointer, pProxyARPTable, ARPTableLen); + os_free_mem(NULL, pProxyARPTable); + } + break; +#endif + case OID_802_11_SECURITY_TYPE: + { + PMULTISSID_STRUCT pMbss; + PUCHAR pType; + struct security_type *SecurityType; + //DBGPRINT(RT_DEBUG_TRACE, ("Query:OID_802_11_SECURITY_TYPE\n")); + printk("Query:OID_802_11_SECURITY_TYPE\n"); + os_alloc_mem(NULL, &pType, sizeof(*SecurityType)); + SecurityType = (struct security_type *)pType; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + SecurityType->ifindex = pObj->ioctl_if; + SecurityType->auth_mode = pMbss->wdev.AuthMode; //pMbss->AuthMode; + SecurityType->encryp_type = pMbss->wdev.WepStatus; //pMbss->WepStatus; + wrq->u.data.length = sizeof(*SecurityType); + Status = copy_to_user(wrq->u.data.pointer, pType, sizeof(*SecurityType)); + os_free_mem(NULL, pType); + } + break; + case OID_802_11_HS_BSSID: + { + PMULTISSID_STRUCT pMbss; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + wrq->u.data.length = 6; + Status = copy_to_user(wrq->u.data.pointer, pMbss->wdev.bssid, 6); + } + break; +#ifdef CONFIG_HOTSPOT_R2 + case OID_802_11_HS_OSU_SSID: + { + wrq->u.data.length = pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen; //+2; + //tmpbuf[0] = IE_SSID; + //tmpbuf[1] = pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen; + //memcpy(&tmpbuf[2], pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen); + //Status = copy_to_user(wrq->u.data.pointer, tmpbuf, wrq->u.data.length); + Status = copy_to_user(wrq->u.data.pointer, pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen); + } + break; +//JERRY for hs test +#endif + +#endif +#ifdef CONFIG_WIFI_TEST + case OID_WIFI_TEST_BBP: + + break; + case OID_WIFI_TEST_BBP32: + { + UINT32 Index; + UINT32 j = 0; + struct bbp32_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct bbp32_info *)buf; + + printk("Info->bbp_start = %x\n", Info->bbp_start); + printk("Info->bbp_end = %x\n", Info->bbp_end); + + + for (Index = Info->bbp_start; Index <= Info->bbp_end; Index += 4) + { + UINT32 Value; + RTMP_IO_READ32(pAd, Index + pAd->chipCap.BBPMemMapOffset, &Value); + printk("Offset = %x\n", Index + pAd->chipCap.BBPMemMapOffset); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->bbp_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + + + break; + case OID_WIFI_TEST_RF: + + break; +#ifdef RLT_RF + case OID_WIFI_TEST_RF_BANK: + { + UINT16 Index; + UINT16 j = 0; + struct rf_bank_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct rf_bank_info *)buf; + + printk("Info->rf_bank = %x\n", Info->rf_bank); + printk("Info->rf_start = %x\n", Info->rf_start); + printk("Info->rf_end = %x\n", Info->rf_end); + + + for (Index = Info->rf_start; Index <= Info->rf_end; Index ++) + { + UINT8 Value; + rlt_rf_read(pAd, Info->rf_bank, Index, &Value); + printk("Offset = %x\n", Index); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->rf_value + j, &Value, 1); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif +#ifdef MT_RF + case OID_WIFI_TEST_RF_INDEX: + { + UINT16 Index; + UINT16 j = 0; + struct rf_index_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct rf_bank_info *)buf; + + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_index = %x\n", Info->rf_index)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + + for (Index = Info->rf_start; Index <= Info->rf_end; Index += 4) + { + UINT32 Value; + mt_rf_read(pAd, Info->rf_index, Index, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Offset = %x\n", Index)); + DBGPRINT(RT_DEBUG_OFF, ("Value = %x\n", Value)); + NdisMoveMemory(Info->rf_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif + case OID_WIFI_TEST_MEM_MAP_INFO: + { + UINT16 Index; + UINT16 j = 0; + struct mem_map_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct mem_map_info *)buf; + + printk("Info->base = %x\n", Info->base); + printk("Info->mem_map_start = %x\n", Info->mem_map_start); + printk("Info->mem_map_end = %x\n", Info->mem_map_end); + + + for (Index = Info->mem_map_start; Index <= Info->mem_map_end; Index += 4) + { + UINT32 Value; + read_reg(pAd, Info->base, Index, &Value); + NdisMoveMemory(Info->mem_map_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; + case OID_WIFI_TEST_E2P: + { + UINT16 Index; + UINT16 j = 0; + struct e2p_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct e2p_info *)buf; + + printk("Info->e2p_start = %x\n", Info->e2p_start); + printk("Info->e2p_end = %x\n", Info->e2p_end); + + + for (Index = Info->e2p_start; Index <= Info->e2p_end; Index += 2) + { + UINT16 Value; + RT28xx_EEPROM_READ16(pAd, Index, Value); + NdisMoveMemory(Info->e2p_value + j, &Value, 2); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; + case OID_WIFI_TEST_MAC: + { + UINT32 Index; + UINT32 j = 0; + struct mac_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct mac_info *)buf; + + printk("Info->mac_start = %x\n", Info->mac_start); + printk("Info->mac_end = %x\n", Info->mac_end); + + + for (Index = Info->mac_start; Index <= Info->mac_end; Index += 4) + { + UINT32 Value; + RTMP_IO_READ32(pAd, Index + pAd->chipCap.MacMemMapOffset, &Value); + printk("Offset = %x\n", Index + pAd->chipCap.MacMemMapOffset); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->mac_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; + case OID_WIFI_TEST_BBP_NUM: + { + struct bbp32_info Info; + Info.bbp_start = pAd->chipCap.BBPStart; + Info.bbp_end = pAd->chipCap.BBPEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_RF_NUM: + + break; + +#ifdef RLT_RF + case OID_WIFI_TEST_RF_BANK_OFFSET: + { + struct rf_bank_info *Info; + struct RF_BANK_OFFSET *Offset; + UINT8 Index; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, sizeof(*Info) * pAd->chipCap.RFBankNum); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Info = (struct rf_bank_info *)buf; + Offset = pAd->chipCap.RFBankOffset; + + printk("pAd->chipCap.RFBankNum = %d\n", pAd->chipCap.RFBankNum); + + for (Index = 0; Index < pAd->chipCap.RFBankNum; Index++) + { + Info->rf_bank = Offset->RFBankIndex; + Info->rf_start = Offset->RFStart; + Info->rf_end =Offset->RFEnd; + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_bank = %d\n", Info->rf_bank)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + Info++; + Offset++; + } + + wrq->u.data.length = sizeof(*Info) * pAd->chipCap.RFBankNum; + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif + +#ifdef MT_RF + case OID_WIFI_TEST_RF_INDEX_OFFSET: + { + struct rf_index_info *Info; + struct RF_INDEX_OFFSET *Offset; + UINT8 Index; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, sizeof(*Info) * pAd->chipCap.RFIndexNum); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Info = (struct rf_index_info *)buf; + Offset = pAd->chipCap.RFIndexOffset; + + DBGPRINT(RT_DEBUG_OFF, ("pAd->chipCap.RFIndexNum = %d\n", pAd->chipCap.RFIndexNum)); + + for (Index = 0; Index < pAd->chipCap.RFIndexNum; Index++) + { + Info->rf_index = Offset->RFIndex; + Info->rf_start = Offset->RFStart; + Info->rf_end =Offset->RFEnd; + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_index = %d\n", Info->rf_index)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + Info++; + Offset++; + } + + wrq->u.data.length = sizeof(*Info) * pAd->chipCap.RFIndexNum; + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif + case OID_WIFI_TEST_MAC_NUM: + { + struct mac_info Info; + Info.mac_start = pAd->chipCap.MacStart; + Info.mac_end = pAd->chipCap.MacEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_E2P_NUM: + { + struct e2p_info Info; + Info.e2p_start = pAd->chipCap.E2PStart; + Info.e2p_end = pAd->chipCap.E2PEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_MEM_MAP_NUM: + { + struct mem_map_info Info; + Info.mem_map_start = pAd->chipCap.MemMapStart; + Info.mem_map_end = pAd->chipCap.MemMapEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_PHY_MODE: + { + struct phy_mode_info info; + info.data_phy = pAd->fpga_ctl.rx_data_phy; + info.data_bw = pAd->fpga_ctl.rx_data_bw; + info.data_ldpc = pAd->fpga_ctl.rx_data_ldpc; + info.data_mcs = pAd->fpga_ctl.rx_data_mcs; + info.data_gi = pAd->fpga_ctl.rx_data_gi; + info.data_stbc = pAd->fpga_ctl.rx_data_stbc; + wrq->u.data.length = sizeof(info); + Status = copy_to_user(wrq->u.data.pointer, &info, wrq->u.data.length); + } + break; +#endif + default: + DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x, apidx=%d\n", cmd, apidx)); + Status = -EOPNOTSUPP; + break; + } + + return Status; +} + +/* + ========================================================================== + Description: + Set Country Code. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + +#ifdef EXT_BUILD_CHANNEL_LIST + /* reset temp table status */ + pAd->CommonCfg.pChDesp = NULL; + pAd->CommonCfg.DfsType = MAX_RD_REGION; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + if(strlen(arg) == 2) + { + NdisMoveMemory(pAd->CommonCfg.CountryCode, arg, 2); + pAd->CommonCfg.bCountryFlag = TRUE; + } + else + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + pAd->CommonCfg.bCountryFlag = FALSE; + } + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE); +#endif /* MT76x2 */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryCode_Proc::(bCountryFlag=%d, CountryCode=%s)\n", pAd->CommonCfg.bCountryFlag, pAd->CommonCfg.CountryCode)); + + return TRUE; +} + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_ChGeography_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Geography; + + Geography = simple_strtol(arg, 0, 10); + if (Geography <= BOTH) + pAd->CommonCfg.Geography = Geography; + else + DBGPRINT(RT_DEBUG_ERROR, ("Set_ChannelGeography_Proc::(wrong setting. 0: Out-door, 1: in-door, 2: both)\n")); + + pAd->CommonCfg.CountryCode[2] = + (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); + + DBGPRINT(RT_DEBUG_ERROR, ("Set_ChannelGeography_Proc:: Geography = %s\n", pAd->CommonCfg.Geography == ODOR ? "out-door" : (pAd->CommonCfg.Geography == IDOR ? "in-door" : "both"))); + + /* After Set ChGeography need invoke SSID change procedural again for Beacon update. */ + /* it's no longer necessary since APStartUp will rebuild channel again. */ + /*BuildChannelListEx(pAd); */ + + return TRUE; +} +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +/* + ========================================================================== + Description: + Set Country String. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryString_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT index = 0; + INT success = TRUE; + STRING name_buffer[40] = {0}; + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + if(strlen(arg) <= 38) + { + if (strlen(arg) < 4) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::Parameter of CountryString are too short !\n")); + return FALSE; + } + + for (index = 0; index < strlen(arg); index++) + { + if ((arg[index] >= 'a') && (arg[index] <= 'z')) + arg[index] = toupper(arg[index]); + } + + for (index = 0; index < NUM_OF_COUNTRIES; index++) + { + NdisZeroMemory(name_buffer, 40); + snprintf(name_buffer, sizeof(name_buffer), "\"%s\"", (PSTRING) allCountry[index].pCountryName); + + if (strncmp((PSTRING) allCountry[index].pCountryName, arg, strlen(arg)) == 0) + break; + else if (strncmp(name_buffer, arg, strlen(arg)) == 0) + break; + } + + if (index == NUM_OF_COUNTRIES) + success = FALSE; + } + else + { + success = FALSE; + } + + if (success == TRUE) + { + if (pAd->CommonCfg.CountryRegion & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::parameter of CountryRegion in eeprom is programmed \n")); + success = FALSE; + } + else + { + success = FALSE; + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + { + if (allCountry[index].SupportGBand == TRUE) + { + pAd->CommonCfg.CountryRegion = (UCHAR) allCountry[index].RegDomainNum11G; + success = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support G Band Channel\n")); + } + } + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + if (allCountry[index].SupportABand == TRUE) + { + pAd->CommonCfg.CountryRegionForABand = (UCHAR) allCountry[index].RegDomainNum11A; + success = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support A Band Channel\n")); + } + } + } + } + + if (success == TRUE) + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + NdisMoveMemory(pAd->CommonCfg.CountryCode, allCountry[index].IsoName, 2); + pAd->CommonCfg.CountryCode[2] = ' '; + /* After Set ChGeography need invoke SSID change procedural again for Beacon update. */ + /* it's no longer necessary since APStartUp will rebuild channel again. */ + /*BuildChannelList(pAd); */ + + pAd->CommonCfg.bCountryFlag = TRUE; + + /* if set country string, driver needs to be reset */ + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryString_Proc::(CountryString=%s CountryRegin=%d CountryCode=%s)\n", + allCountry[index].pCountryName, pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryCode)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::Parameters out of range\n")); + } + + return success; +} + +#ifdef DOT11_VHT_AC +INT Set_2G_256QAM_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = TRUE; + pAdapter->CommonCfg.b256QAM_2G = (UCHAR) simple_strtol(arg, 0, 10); + return success; + +} +#endif /* DOT11_VHT_AC */ + +#ifdef DELAYED_TCP_ACK +INT Set_ACKQ_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + pAdapter->CommonCfg.ACKQEN = (BOOLEAN) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ackqn=%d\n", pAdapter->CommonCfg.ACKQEN)); + + return TRUE; +} + +INT Set_CACKQ_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + UCHAR i; + pAdapter->CommonCfg.AckTimeout = 0; + pAdapter->CommonCfg.AckNOTimeout = 0; + + for (i=0; i<=TCP_ACK_BURST_LEVEL; i++) + pAdapter->CommonCfg.TcpAck[i] = 0; + + return TRUE; +} + +INT Set_ACKWait_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + pAdapter->CommonCfg.AckWaitTime = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("wait time=%d\n", pAdapter->CommonCfg.AckWaitTime)); + + return TRUE; +} + +INT Set_ACKLen_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + pAdapter->CommonCfg.Acklen = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("queue len=%d\n", pAdapter->CommonCfg.Acklen)); + + return TRUE; +} + +INT Set_ShowACKQParm_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + UCHAR i; + COMMON_CONFIG *pComCfg = &pAdapter->CommonCfg; + + printk("Delayed TCP ACK queue patameters\n"); + printk("[enackq] ACKQEN: %d\n", pComCfg->ACKQEN); + printk("[ackwait] AckWaitTime: %d\n", pComCfg->AckWaitTime); + printk("[acklen] Acklen: %d\n", pComCfg->Acklen); + printk("ack timeout: = %d\n", pComCfg->AckTimeout); + printk("ack no timeout: = %d\n", pComCfg->AckNOTimeout); + + for (i=0; i<=TCP_ACK_BURST_LEVEL; i++) + printk("ack%d: = %d\n", i, pComCfg->TcpAck[i]); + + return TRUE; +} +#endif /* DELAYED_TCP_ACK */ + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_SSID_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + MULTISSID_STRUCT *mbss; + + if(((pObj->ioctl_if < HW_BEACON_MAX_NUM)) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + mbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(mbss->Ssid, arg, strlen(arg)); + mbss->SsidLen = (UCHAR)strlen(arg); + success = TRUE; + + { + /* If in detection mode, need to stop detect first. */ + if (pAd->CommonCfg.bIEEE80211H == FALSE) + { + APStop(pAd); + APStartUp(pAd); + } + else + { + /* each mode has different restart method */ + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + APStop(pAd); + APStartUp(pAd); + } + else if (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE) + { + } + else if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + { + APStop(pAd); + APStartUp(pAd); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + mbss->SsidLen, mbss->Ssid)); + } + } + else + success = FALSE; + + return success; +} + + +/* + ========================================================================== + Description: + Set TxRate + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxRate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + NdisZeroMemory(pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredRates, MAX_LEN_OF_SUPPORTED_RATES); + + pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredRatesIndex = simple_strtol(arg, 0, 10); + /* todo RTMPBuildDesireRate(pAd, pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredRatesIndex); */ + + /*todo MlmeUpdateTxRates(pAd); */ + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set BasicRate + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BasicRate_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + ULONG BasicRateBitmap; + + BasicRateBitmap = (ULONG) simple_strtol(arg, 0, 10); + + if (BasicRateBitmap > 4095) /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return FALSE; + + pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; + pAd->CommonCfg.BasicRateBitmapOld = BasicRateBitmap; + + MlmeUpdateTxRates(pAd, FALSE, (UCHAR)pObj->ioctl_if); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BasicRate_Proc::(BasicRateBitmap=0x%08lx)\n", pAd->CommonCfg.BasicRateBitmap)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Beacon Period + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BeaconPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT BeaconPeriod; + INT success = FALSE; + + BeaconPeriod = (USHORT) simple_strtol(arg, 0, 10); + if((BeaconPeriod >= 20) && (BeaconPeriod < 1024)) + { + pAd->CommonCfg.BeaconPeriod = BeaconPeriod; + success = TRUE; + +#ifdef AP_QLOAD_SUPPORT + /* re-calculate QloadBusyTimeThreshold */ + QBSS_LoadAlarmReset(pAd); +#endif /* AP_QLOAD_SUPPORT */ + } + else + success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BeaconPeriod_Proc::(BeaconPeriod=%d)\n", pAd->CommonCfg.BeaconPeriod)); + + return success; +} + +/* + ========================================================================== + Description: + Set Dtim Period + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_DtimPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT DtimPeriod; + INT success = FALSE; + + DtimPeriod = (USHORT) simple_strtol(arg, 0, 10); + if((DtimPeriod >= 1) && (DtimPeriod <= 255)) + { + pAd->ApCfg.DtimPeriod = DtimPeriod; + success = TRUE; + } + else + success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DtimPeriod_Proc::(DtimPeriod=%d)\n", pAd->ApCfg.DtimPeriod)); + + return success; +} + + + +/* + ========================================================================== + Description: + Disable/enable OLBC detection manually + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_OLBCDetection_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + switch (simple_strtol(arg, 0, 10)) + { + case 0: /*enable OLBC detect */ + pAd->CommonCfg.DisableOLBCDetect = 0; + break; + case 1: /*disable OLBC detect */ + pAd->CommonCfg.DisableOLBCDetect = 1; + break; + default: /*Invalid argument */ + return FALSE; + } + + return TRUE; +} + + +#ifdef WMM_SUPPORT +/* + ========================================================================== + Description: + Set WmmCapable Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bWmmCapable; + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + bWmmCapable = simple_strtol(arg, 0, 10); + + if (bWmmCapable == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable = FALSE; + else + return FALSE; /*Invalid argument */ + + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapableOrg = \ + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable; + +#ifdef DOT11_N_SUPPORT + /*Sync with the HT relate info. In N mode, we should re-enable it */ + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WmmCapable_Proc::(bWmmCapable=%d)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable)); + + return TRUE; +} +#endif /* WMM_SUPPORT */ + + +INT Set_AP_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + + return ApCfg_Set_MaxStaNum_Proc(pAd, apidx, arg); +} + +/* + ========================================================================== + Description: + Set session idle timeout + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_IdleTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return ApCfg_Set_IdleTimeout_Proc(pAd, arg); +} +/* + ========================================================================== + Description: + Set No Forwarding Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_NoForwarding_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG NoForwarding; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + NoForwarding = simple_strtol(arg, 0, 10); + + if (NoForwarding == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaTraffic = TRUE; + else if (NoForwarding == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaTraffic = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_NoForwarding_Proc::(NoForwarding=%d)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaTraffic)); + + return TRUE; +} + + +INT Set_NoForwardingMBCast_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG NoForwardingMBCast; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + NoForwardingMBCast = simple_strtol(arg, 0, 10); + + if (NoForwardingMBCast == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaMBCast = TRUE; + else if (NoForwardingMBCast == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaMBCast = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_NoForwardingMBCast_Proc::(IsolateInterStaMBCast=%d)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaMBCast)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set No Forwarding between each SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_NoForwardingBTNSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG NoForwarding; + + NoForwarding = simple_strtol(arg, 0, 10); + + if (NoForwarding == 1) + pAd->ApCfg.IsolateInterStaTrafficBTNBSSID = TRUE; + else if (NoForwarding == 0) + pAd->ApCfg.IsolateInterStaTrafficBTNBSSID = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_NoForwardingBTNSSID_Proc::(NoForwarding=%d)\n", pAd->ApCfg.IsolateInterStaTrafficBTNBSSID)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Hide SSID Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_HideSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bHideSsid; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + bHideSsid = simple_strtol(arg, 0, 10); + + if (bHideSsid == 1) + bHideSsid = TRUE; + else if (bHideSsid == 0) + bHideSsid = FALSE; + else + return FALSE; /*Invalid argument */ + + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].bHideSsid != bHideSsid) + { + pAd->ApCfg.MBSSID[pObj->ioctl_if].bHideSsid = bHideSsid; + } + +#ifdef WSC_V2_SUPPORT + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscV2Info.bEnableWpsV2) + WscOnOff(pAd, pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].bHideSsid); +#endif /* WSC_V2_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_HideSSID_Proc::(HideSSID=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].bHideSsid)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set VLAN's ID field + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLANID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + wdev->VLAN_VID = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANID_Proc::(VLAN_VID=%d)\n", + pObj->ioctl_if, wdev->VLAN_VID)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set VLAN's priority field + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLANPriority_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + + wdev->VLAN_Priority = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANPriority_Proc::(VLAN_Priority=%d)\n", pObj->ioctl_if, wdev->VLAN_Priority)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set enable or disable carry VLAN in the air + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLAN_TAG_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + BOOLEAN bVLAN_Tag; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + bVLAN_Tag = simple_strtol(arg, 0, 10); + + if (bVLAN_Tag == 1) + bVLAN_Tag = TRUE; + else if (bVLAN_Tag == 0) + bVLAN_Tag = FALSE; + else + return FALSE; //Invalid argument + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + wdev->bVLAN_Tag = bVLAN_Tag; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLAN_TAG_Proc::(VLAN_Tag=%d)\n", + pObj->ioctl_if, wdev->bVLAN_Tag)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; + + + if (apidx >= pAd->ApCfg.BssidNum) + return FALSE; + + /* Set Authentication mode */ + ApCfg_Set_AuthMode_Proc(pAd, apidx, arg); + + /* reset the portSecure for all entries */ + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + /* reset the PortSecure this BSS */ + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + /* Default key index is always 2 in WPA mode */ + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 1; + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; + +#ifdef AIRPLAY_SUPPORT + PMULTISSID_STRUCT pMbss = NULL; +#endif /* AIRPLAY_SUPPORT*/ + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + wdev->WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + wdev->WepStatus = Ndis802_11Encryption3Enabled; + else if ((strcmp(arg, "TKIPAES") == 0) || (strcmp(arg, "tkipaes") == 0)) + wdev->WepStatus = Ndis802_11Encryption4Enabled; +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "SMS4") == 0) || (strcmp(arg, "sms4") == 0)) + wdev->WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + return FALSE; + + if (wdev->WepStatus >= Ndis802_11Encryption2Enabled) + wdev->DefaultKeyId = 1; + + /* decide the group key encryption type */ + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + wdev->GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + else + wdev->GroupKeyWepStatus = wdev->WepStatus; + + /* move to ap.c::APStartUp to process */ + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_EncrypType_Proc::(EncrypType=%d)\n", apidx, wdev->WepStatus)); + +#ifdef AIRPLAY_SUPPORT + pMbss = &pAd->ApCfg.MBSSID[apidx]; + /*If EncryptionDisabled, set privacy bit in CapabilityInfo to zero*/ + if(wdev->WepStatus == Ndis802_11EncryptionDisabled) + { + pMbss->CapabilityInfo &= 0xFFEF; + DBGPRINT(RT_DEBUG_OFF, ("##Diaplbe privacy ####")); + } + else + { + /* Enable encryption*/ + pMbss->CapabilityInfo |= 0x0010; + } +#endif /* AIRPLAY_SUPPORT*/ + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WPA pairwise mix-cipher combination + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_WpaMixPairCipher_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; + + /* + In WPA-WPA2 mix mode, it provides a more flexible cipher combination. + - WPA-AES and WPA2-TKIP + - WPA-AES and WPA2-TKIPAES + - WPA-TKIP and WPA2-AES + - WPA-TKIP and WPA2-TKIPAES + - WPA-TKIPAES and WPA2-AES + - WPA-TKIPAES and WPA2-TKIP + - WPA-TKIPAES and WPA2-TKIPAES (default) + */ + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + if ((strncmp(arg, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkipaes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkip", 17) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(arg, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(arg, "wpa_tkip_wpa2_aes", 17) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(arg, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_aes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_WpaMixPairCipher_Proc=0x%02x\n", apidx, wdev->WpaMixPairCipher)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA rekey interval value + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_RekeyInterval_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT32 val; + + val = simple_strtol(arg, 0, 10); + + if((val >= 10) && (val < MAX_REKEY_INTER)) + pAd->ApCfg.MBSSID[apidx].WPAREKEY.ReKeyInterval = val; + else /* Default */ + pAd->ApCfg.MBSSID[apidx].WPAREKEY.ReKeyInterval = 3600; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_RekeyInterval_Proc=%ld\n", + apidx, pAd->ApCfg.MBSSID[apidx].WPAREKEY.ReKeyInterval)); + + return TRUE; +} + +INT Set_AP_PROBE_RSP_TIMES( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT input; + input = simple_strtol(arg, 0, 10); + + if ((input >= 0) && (input <= 10)) + pAd->ApCfg.MBSSID[apidx].ProbeRspTimes = input; + else + DBGPRINT(RT_DEBUG_ERROR, ("AP[%u]->ProbeRspTimes: Out of Range\n", apidx)); + + DBGPRINT(RT_DEBUG_TRACE, ("AP[%u]->ProbeRspTimes: %d\n", apidx, pAd->ApCfg.MBSSID[apidx].ProbeRspTimes)); + + return TRUE; + +} + +#ifdef SPECIFIC_TX_POWER_SUPPORT +INT Set_AP_PKT_PWR( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT input; + input = simple_strtol(arg, 0, 10); + + /* + Tx_PWR_ADJ[3:0] From 0 to 7 is Positive & add with Tx Power (dB), + From 8 to 15 is minus with Tx Power mapping to -16 to -2 (step by 2), + Default value: 0. + + [0x13BC]TX_ALC_MONITOR, 13:8 + TX_ALC_REQ_ADJ TX ALC Req Saturated[5:0], unit (0.5dB) + */ + + if ((input >= 0) && (input <= 15)) + pAd->ApCfg.MBSSID[apidx].TxPwrAdj = input; + else + DBGPRINT(RT_DEBUG_ERROR, ("AP[%d]->PktPwr: Out of Range\n", apidx)); + + DBGPRINT(RT_DEBUG_TRACE, ("AP[%d]->PktPwr: %d\n", apidx, pAd->ApCfg.MBSSID[apidx].TxPwrAdj)); + + return TRUE; +} +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +/* + ========================================================================== + Description: + Set WPA rekey method + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_RekeyMethod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PRT_WPA_REKEY pInfo = &pAd->ApCfg.MBSSID[apidx].WPAREKEY; + + if ((strcmp(arg, "TIME") == 0) || (strcmp(arg, "time") == 0)) + pInfo->ReKeyMethod = TIME_REKEY; + else if ((strcmp(arg, "PKT") == 0) || (strcmp(arg, "pkt") == 0)) + pInfo->ReKeyMethod = PKT_REKEY; + else if ((strcmp(arg, "DISABLE") == 0) || (strcmp(arg, "disable") == 0)) + pInfo->ReKeyMethod = DISABLE_REKEY; + else + pInfo->ReKeyMethod = DISABLE_REKEY; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_RekeyMethod_Proc=%ld\n", + apidx, pInfo->ReKeyMethod)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set PMK-cache period + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_PMKCachePeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT32 val = simple_strtol(arg, 0, 10); + + pAd->ApCfg.MBSSID[apidx].PMKCachePeriod = val * 60 * OS_HZ; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_PMKCachePeriod_Proc=%ld\n", + apidx, pAd->ApCfg.MBSSID[apidx].PMKCachePeriod)); + + return TRUE; +} + + +INT Set_AP_PACKET_FILTER_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + CHAR val; + val = simple_strtol(arg, 0, 10); + + if (val == FILTER_NONE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_PACKET_FILTER\n")); + } + else if (val >= FILTER_TOTAL || val < FILTER_NONE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_PACKET_FILTER Value Error.\n")); + return FALSE; + } + + pAd->ApCfg.MBSSID[apidx].FilterUnusedPacket = val; + + return TRUE; +} + +INT Set_AP_PROBE_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_PROBE_RSSI_THRESHOLD\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_PROBE_RSSI_THRESHOLD Value Error.\n")); + return FALSE; + } + + pAd->ApCfg.MBSSID[apidx].ProbeRspRssiThreshold = rssi; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(%s) Set_AP_PROBE_RSSI_THRESHOLD=%d\n", + pAd->ApCfg.MBSSID[apidx].wdev.if_dev->name, + pAd->ApCfg.MBSSID[apidx].ProbeRspRssiThreshold)); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].ProbeRspRssiThreshold )); + } + + return TRUE; +} + +INT Set_AP_AUTH_FAIL_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_AUTH_FAIL_RSSI_THRESHOLD\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_AUTH_FAIL_RSSI_THRESHOLD Value Error.\n")); + return FALSE; + } + + pAd->ApCfg.MBSSID[apidx].AuthFailRssiThreshold = rssi; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(%s) Set_AP_AUTH_RSSI_THRESHOLD=%d\n", + pAd->ApCfg.MBSSID[apidx].wdev.if_dev->name, + pAd->ApCfg.MBSSID[apidx].AuthFailRssiThreshold)); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].AuthFailRssiThreshold )); + } + + return TRUE; +} + +INT Set_AP_AUTH_NO_RSP_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_AUTH_NO_RSP_RSSI_THRESHOLD\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_AUTH_NO_RSP_RSSI_THRESHOLD Value Error.\n")); + return FALSE; + } + + pAd->ApCfg.MBSSID[apidx].AuthNoRspRssiThreshold = rssi; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(%s) Set_AP_AUTH_NO_RSP_RSSI_THRESHOLD=%d\n", + pAd->ApCfg.MBSSID[apidx].wdev.if_dev->name, + pAd->ApCfg.MBSSID[apidx].AuthNoRspRssiThreshold)); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].AuthNoRspRssiThreshold )); + } + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set AssocReq RSSI Threshold to reject STA with weak signal. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_ASSOC_REQ_FAIL_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_ASSOC_REQ_FAIL_RSSI_THRESHOLD\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_ASSOC_REQ_FAIL_RSSI_THRESHOLD Value Error.\n")); + return FALSE; + } + + pAd->ApCfg.MBSSID[apidx].AssocReqFailRssiThreshold = rssi; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(%s) Set_AP_ASSOC_REQ_FAIL_RSSI_THRESHOLD=%d\n", + pAd->ApCfg.MBSSID[apidx].wdev.if_dev->name, + pAd->ApCfg.MBSSID[apidx].AssocReqFailRssiThreshold )); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].AssocReqFailRssiThreshold )); + } + + return TRUE; +} + + +INT Set_AP_ASSOC_REQ_NO_RSP_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_ASSOC_REQ_NO_RSP_RSSI_THRESHOLD\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_ASSOC_REQ_NO_RSP_RSSI_THRESHOLD Value Error.\n")); + return FALSE; + } + + + pAd->ApCfg.MBSSID[apidx].AssocReqNoRspRssiThreshold = rssi; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(%s) Set_AP_ASSOC_REQ_NO_RSP_RSSI_THRESHOLD=%d\n", + pAd->ApCfg.MBSSID[apidx].wdev.if_dev->name, + pAd->ApCfg.MBSSID[apidx].AssocReqNoRspRssiThreshold )); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].AssocReqNoRspRssiThreshold )); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set lower limit for AP kicking out a STA. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_KickStaRssiLow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable RssiLowForStaKickOut Function\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("RssiLowForStaKickOut Value Error.\n")); + return FALSE; + } + + + pAd->ApCfg.MBSSID[apidx].RssiLowForStaKickOut = rssi; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(%s) RssiLowForStaKickOut=%d\n", + pAd->ApCfg.MBSSID[apidx].wdev.if_dev->name, + pAd->ApCfg.MBSSID[apidx].RssiLowForStaKickOut)); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].RssiLowForStaKickOut )); + } + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG KeyIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", apidx, pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WEP KEY1 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][0]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 0); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 0, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key1_Proc::(Key1=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY2 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][1]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 1); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 1, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key2_Proc::(Key2=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY3 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key3_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][2]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 2); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 2, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key3_Proc::(Key3=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY4 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key4_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][3]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 3); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 3, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key4_Proc::(Key4=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set Access ctrol policy + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AccessPolicy_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + switch (simple_strtol(arg, 0, 10)) + { + case 0: /*Disable */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy = 0; + break; + case 1: /* Allow All, and ACL is positive. */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy = 1; + break; + case 2: /* Reject All, and ACL is negative. */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy = 2; + break; + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_ERROR, ("Set_AccessPolicy_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + + /* check if the change in ACL affects any existent association */ + ApUpdateAccessControlList(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AccessPolicy_Proc::(AccessPolicy=%ld)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy)); + + return TRUE; +} + + +/* Replaced by Set_ACLAddEntry_Proc() and Set_ACLClearAll_Proc() */ + +/* + ========================================================================== + Description: + Add one entry or several entries(if allowed to) + into Access control mac table list + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ACLAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; +/* RT_802_11_ACL acl; */ + RT_802_11_ACL *pacl = NULL; + PSTRING this_char; + PSTRING value; + INT i, j; + BOOLEAN isDuplicate=FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num >= (MAX_NUM_OF_ACL_LIST - 1)) + { + DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n")); + return FALSE; + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pacl, sizeof(RT_802_11_ACL)); + if (pacl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return FALSE; + } + + NdisZeroMemory(pacl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(pacl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + + while ((this_char = strsep((char **)&arg, ";")) != NULL) + { + if (*this_char == '\0') + { + DBGPRINT(RT_DEBUG_WARN, ("An unnecessary delimiter entered!\n")); + continue; + } + if (strlen(this_char) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address length!\n")); + continue; + } + for (i=0, value = rstrtok(this_char,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address format or octet!\n")); + /* Do not use "continue" to replace "break" */ + break; + } + AtoH(value, &macAddr[i++], 1); + } + + if (i != MAC_ADDR_LEN) + { + continue; + } + + /* Check if this entry is duplicate. */ + isDuplicate = FALSE; + for (j=0; jNum; j++) + { + if (memcmp(pacl->Entry[j].Addr, &macAddr, 6) == 0) + { + isDuplicate = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("You have added an entry before :\n")); + DBGPRINT(RT_DEBUG_WARN, ("The duplicate entry is %02x:%02x:%02x:%02x:%02x:%02x\n", + macAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5])); + } + } + + if (!isDuplicate) + { + NdisMoveMemory(pacl->Entry[pacl->Num++].Addr, &macAddr, MAC_ADDR_LEN); + } + + if (pacl->Num == MAX_NUM_OF_ACL_LIST) + { + DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n")); + DBGPRINT(RT_DEBUG_WARN, ("The last entry of ACL is %02x:%02x:%02x:%02x:%02x:%02x\n", + macAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5])); + break; + } + } + + ASSERT(pacl->Num < MAX_NUM_OF_ACL_LIST); + + NdisZeroMemory(&pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + NdisMoveMemory(&pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, pacl, sizeof(RT_802_11_ACL)); + + /* check if the change in ACL affects any existent association */ + ApUpdateAccessControlList(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_TRACE, ("Set::%s(Policy=%ld, Entry#=%ld)\n", + __FUNCTION__ , pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy, pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num)); + +#ifdef DBG + DBGPRINT(RT_DEBUG_TRACE, ("=============== Entry ===============\n")); + for (i=0; iApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num; i++) + { + printk("Entry #%02d: ", i+1); + for (j=0; jApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[i].Addr[j]); + printk("\n"); + } +#endif + + if (pacl != NULL) + os_free_mem(NULL, pacl); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Delete one entry or several entries(if allowed to) + from Access control mac table list + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ACLDelEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + UCHAR nullAddr[MAC_ADDR_LEN]; + RT_802_11_ACL acl; + PSTRING this_char; + PSTRING value; + INT i, j; + BOOLEAN isFound=FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + NdisZeroMemory(&acl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(&acl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + NdisZeroMemory(nullAddr, MAC_ADDR_LEN); + + while ((this_char = strsep((char **)&arg, ";")) != NULL) + { + if (*this_char == '\0') + { + DBGPRINT(RT_DEBUG_WARN, ("An unnecessary delimiter entered!\n")); + continue; + } + if (strlen(this_char) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address length!\n")); + continue; + } + + for (i=0, value = rstrtok(this_char,":"); value; value = rstrtok(NULL,":")) + { + if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address format or octet!\n")); + /* Do not use "continue" to replace "break" */ + break; + } + AtoH(value, &macAddr[i++], 1); + } + + if (i != MAC_ADDR_LEN) + { + continue; + } + + /* Check if this entry existed. */ + isFound = FALSE; + for (j=0; jApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy = acl.Policy; + ASSERT(pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num == 0); + i = 0; + + for (j=0; jApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[i++]), acl.Entry[j].Addr, MAC_ADDR_LEN); + } + } + + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num = i; + ASSERT(acl.Num >= pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num); + + /* check if the change in ACL affects any existent association */ + ApUpdateAccessControlList(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_TRACE, ("Set::%s(Policy=%ld, Entry#=%ld)\n", + __FUNCTION__ , pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy, pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num)); + +#ifdef DBG + DBGPRINT(RT_DEBUG_TRACE, ("=============== Entry ===============\n")); + for (i=0; iApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num; i++) + { + printk("Entry #%02d: ", i+1); + for (j=0; jApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[i].Addr[j]); + printk("\n"); + } +#endif + return TRUE; +} + + +/* for ACL policy message */ +#define ACL_POLICY_TYPE_NUM 3 +char const *pACL_PolicyMessage[ACL_POLICY_TYPE_NUM] = { + "the Access Control feature is disabled", /* 0 : Disable */ + "only the following entries are allowed to join this BSS", /* 1 : Allow */ + "all the following entries are rejected to join this BSS", /* 2 : Reject */ +}; + + +/* + ========================================================================== + Description: + Dump all the entries in the Access control + mac table list of a specified BSS + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ACLShowAll_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + RT_802_11_ACL acl; + BOOLEAN bDumpAll=FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT i, j; + + bDumpAll = simple_strtol(arg, 0, 10); + + if (bDumpAll == 1) + { + bDumpAll = TRUE; + } + else if (bDumpAll == 0) + { + bDumpAll = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("Your input is 0!\n")); + DBGPRINT(RT_DEBUG_WARN, ("The Access Control List will not be dumped!\n")); + return TRUE; + } + else + { + return FALSE; /* Invalid argument */ + } + + NdisZeroMemory(&acl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(&acl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + + /* Check if the list is already empty. */ + if (acl.Num == 0) + { + DBGPRINT(RT_DEBUG_WARN, ("The Access Control List is empty!\n")); + return TRUE; + } + + ASSERT(((bDumpAll == 1) && (acl.Num > 0))); + + /* Show the corresponding policy first. */ + printk("=============== Access Control Policy ===============\n"); + printk("Policy is %ld : ", acl.Policy); + printk("%s\n", pACL_PolicyMessage[acl.Policy]); + + /* Dump the entry in the list one by one */ + printk("=============== Access Control List ===============\n"); + for (i=0; iOS_Cookie; + + bClearAll = simple_strtol(arg, 0, 10); + + if (bClearAll == 1) + { + bClearAll = TRUE; + } + else if (bClearAll == 0) + { + bClearAll = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("Your input is 0!\n")); + DBGPRINT(RT_DEBUG_WARN, ("The Access Control List will be kept unchanged!\n")); + return TRUE; + } + else + { + return FALSE; /* Invalid argument */ + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pacl, sizeof(RT_802_11_ACL)); + if (pacl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return FALSE; + } + + NdisZeroMemory(pacl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(pacl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + + /* Check if the list is already empty. */ + if (pacl->Num == 0) + { + DBGPRINT(RT_DEBUG_WARN, ("The Access Control List is empty!\n")); + DBGPRINT(RT_DEBUG_WARN, ("No need to clear the Access Control List!\n")); + + if (pacl != NULL) + os_free_mem(NULL, pacl); + + return TRUE; + } + + ASSERT(((bClearAll == 1) && (pacl->Num > 0))); + + /* Clear the entry in the list one by one */ + /* Keep the corresponding policy unchanged. */ + do + { + NdisZeroMemory(pacl->Entry[pacl->Num - 1].Addr, MAC_ADDR_LEN); + pacl->Num -= 1; + }while (pacl->Num > 0); + + ASSERT(pacl->Num == 0); + + NdisZeroMemory(&(pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList), sizeof(RT_802_11_ACL)); + NdisMoveMemory(&(pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList), pacl, sizeof(RT_802_11_ACL)); + + /* check if the change in ACL affects any existent association */ + ApUpdateAccessControlList(pAd, pObj->ioctl_if); + + if (pacl != NULL) + os_free_mem(NULL, pacl); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::%s(Policy=%ld, Entry#=%ld)\n", + __FUNCTION__, pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Policy, pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num)); + + return TRUE; +} + +#ifdef DBG +static void _rtmp_hexdump(int level, const char *title, const UINT8 *buf, + size_t len, int show) +{ + size_t i; + if (level < RTDebugLevel) + return; + printk("%s - hexdump(len=%lu):", title, (unsigned long) len); + if (show) { + for (i = 0; i < len; i++) + printk(" %02x", buf[i]); + } else { + printk(" [REMOVED]"); + } + printk("\n"); +} + +void rtmp_hexdump(int level, const char *title, const UINT8 *buf, size_t len) +{ + _rtmp_hexdump(level, title, buf, len, 1); +} +#endif + + + +/* + ========================================================================== + Description: + Set WPA PSK key + + Arguments: + pAdapter Pointer to our adapter + arg WPA pre-shared key string + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT retval; + MULTISSID_STRUCT *pMBSSStruct; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); + + pMBSSStruct = &pAd->ApCfg.MBSSID[apidx]; + retval = RT_CfgSetWPAPSKKey(pAd, arg, strlen(arg), (PUCHAR)pMBSSStruct->Ssid, pMBSSStruct->SsidLen, pMBSSStruct->PMK); + if (retval == FALSE) + return FALSE; + + /* Keep this key string */ + strcpy(pAd->ApCfg.MBSSID[apidx].WPAKeyString, arg); + +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pMBSSStruct->WscControl.WpaPsk, 64); + pMBSSStruct->WscControl.WpaPskLen = 0; + pMBSSStruct->WscControl.WpaPskLen = strlen(arg); + NdisMoveMemory(pMBSSStruct->WscControl.WpaPsk, arg, pMBSSStruct->WscControl.WpaPskLen); +#endif /* WSC_AP_SUPPORT */ + + return TRUE; +} + +/* + ========================================================================== + Description: + Reset statistics counter + + Arguments: + pAdapter Pointer to our adapter + arg + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ + +INT Set_RadioOn_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR radio; + + radio = simple_strtol(arg, 0, 10); + + if (radio) + { + MlmeRadioOn(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("==>Set_RadioOn_Proc (ON)\n")); + } + else + { + MlmeRadioOff(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("==>Set_RadioOn_Proc (OFF)\n")); + } + + return TRUE; +} + +#ifdef AP_SCAN_SUPPORT +/* + ========================================================================== + Description: + Issue a site survey command to driver + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set site_survey + ========================================================================== +*/ + +/* + ========================================================================== + Description: + Issue a Auto-Channel Selection command to driver + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set AutoChannelSel=1 + Ues the number of AP to choose + 2.) iwpriv ra0 set AutoChannelSel=2 + Ues the False CCA count to choose + ========================================================================== +*/ +INT Set_AutoChannelSel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + NDIS_802_11_SSID Ssid; + + + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + if (strlen(arg) <= MAX_LEN_OF_SSID) + { + if (strlen(arg) != 0) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + else /*ANY ssid */ + { + Ssid.SsidLength = 0; + memcpy(Ssid.Ssid, "", 0); + } + } + if (strcmp(arg,"1") == 0) + pAd->ApCfg.AutoChannelAlg = ChannelAlgApCnt; + else if (strcmp(arg,"2") == 0) + pAd->ApCfg.AutoChannelAlg = ChannelAlgCCA; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_AutoChannelSel_Proc Alg isn't defined\n")); + return FALSE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set_AutoChannelSel_Proc Alg=%d \n", pAd->ApCfg.AutoChannelAlg)); + if (Ssid.SsidLength == 0) + ApSiteSurvey(pAd, &Ssid, SCAN_PASSIVE, TRUE); + else + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, TRUE); + + return TRUE; + +} + +#ifdef AP_PARTIAL_SCAN_SUPPORT +INT Set_PartialScan_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT8 bPartialScanning = simple_strtol(arg, 0, 10); + pAd->ApCfg.bPartialScanning = bPartialScanning ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): bPartialScanning = %u \n", __FUNCTION__, pAd->ApCfg.bPartialScanning)); + return TRUE; +} +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +/* + ========================================================================== + Description: + Set a periodic check time for auto channel selection (unit: hour) + Arguments: + pAdapter Pointer to our adapter + + Return Value: + TRUE if success, FALSE otherwise + + Note: + Usage: + iwpriv ra0 set ACSCheckTime=3 (unit: hour) + + ========================================================================== +*/ +INT Set_AutoChannelSelCheckTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT8 Hour = simple_strtol(arg, 0, 10); + + pAd->ApCfg.ACSCheckTime = Hour*3600; /* Hour to second */ + pAd->ApCfg.ACSCheckCount = 0; /* Reset counter */ + DBGPRINT(RT_DEBUG_TRACE, ("%s(): ACSCheckTime=%u seconds(%u hours)\n", + __FUNCTION__, pAd->ApCfg.ACSCheckTime, Hour)); + return TRUE; +} +#endif /* AP_SCAN_SUPPORT */ + + +INT Show_DriverInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + + +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->chipCap.MCUType == ANDES) { + UINT32 loop = 0; + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + if (pAd->chipCap.need_load_fw) { + USHORT fw_ver, build_ver; + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + DBGPRINT(RT_DEBUG_OFF, ("fw version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_OFF, ("build:%x\n", build_ver)); + DBGPRINT(RT_DEBUG_OFF, ("build time:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + if (pAd->chipCap.need_load_rom_patch) { + DBGPRINT(RT_DEBUG_OFF, ("rom patch version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 24 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("build time = \n")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + } +#endif /* CONFIG_ANDES_SUPPORT */ + + return TRUE; +} + + +INT Show_StaCount_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT i; + UINT32 RegValue; + + printk("\n"); + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08x\n", + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED) ? "short" : "long", + RegValue); + +#ifdef DOT11_N_SUPPORT + printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); + printk("\n"); +#endif /* DOT11_N_SUPPORT */ + + printk("\n%-19s%-4s%-12s%-12s%-12s%-12s\n", + "MAC", "AID","TxPackets","RxPackets","TxBytes","RxBytes"); + + for (i=0; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst == SST_ASSOC)) + { + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + printk("%-4d", (int)pEntry->Aid); + printk("%-12ld",(ULONG)pEntry->TxPackets.QuadPart); + printk("%-12ld", (ULONG)pEntry->RxPackets.QuadPart); + printk("%-12ld", (ULONG)pEntry->TxBytes); + printk("%-12ld", (ULONG)pEntry->RxBytes); + printk("\n"); + } + } + + return TRUE; +} + +INT Show_LinkInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + + INT i; + UINT32 TxDataRate = 0, RxDataRate = 0; + HTTRANSMIT_SETTING RX_HTSetting; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (pAd == NULL) + return FALSE; + + + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-8s%-8s%-12s%-8s\n", + "MAC", "AID", "TX Rate", "RX Rate", "Tx Retry", "PER")); + + for (i=0; iMacTab.Content[i]; + + if (pEntry && (IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && pEntry->Sst == SST_ASSOC) + { + /* Init */ + TxDataRate = 0; + RxDataRate = 0; + + /* TX Info */ + RtmpDrvRateGet(pAd, pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.BW, pEntry->HTPhyMode.field.MCS, + newRateGetAntenna(pEntry->HTPhyMode.field.MCS,pEntry->HTPhyMode.field.MODE), &TxDataRate); + + TxDataRate /= 500000; + TxDataRate /= 2; + + + /* RX Info */ + NdisCopyMemory(&RX_HTSetting, &pEntry->LastRxRate, sizeof(RX_HTSetting)); + + RtmpDrvRateGet(pAd, RX_HTSetting.field.MODE, RX_HTSetting.field.ShortGI, + RX_HTSetting.field.BW,RX_HTSetting.field.MCS, + newRateGetAntenna(RX_HTSetting.field.MCS, RX_HTSetting.field.MODE),&RxDataRate); + + RxDataRate /= 500000; + RxDataRate /= 2; + + + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", + PRINT_MAC(pEntry->Addr))); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); + DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)TxDataRate)); + DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)RxDataRate)); + DBGPRINT(RT_DEBUG_OFF, ("%-12d", pEntry->StatTxRetryOkCount)); + DBGPRINT(RT_DEBUG_OFF, ("%d%%", pEntry->LastTxPER)); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + + } + } + + return TRUE; +} + + +INT Show_StaSecurityInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT i; + UCHAR apidx; + struct wifi_dev *wdev; + + if (pAd == NULL) + return FALSE; + + printk("\n"); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + printk(" BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s, WPAMixPairCipher(0x%02X)\n", + apidx, + wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus), + wdev->GroupKeyWepStatus, GetEncryptType(wdev->GroupKeyWepStatus), + wdev->WpaMixPairCipher); + } + printk("\n"); + + printk("\n%-19s%-4s%-4s%-15s%-12s\n", + "MAC", "AID", "BSS", "Auth", "Encrypt"); + + for (i=0; iMacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) && pEntry->Sst == SST_ASSOC) + { + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + PRINT_MAC(pEntry->Addr)); + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->apidx); + printk("%-15s", GetAuthMode(pEntry->AuthMode)); + printk("%-12s", GetEncryptType(pEntry->WepStatus)); + printk("\n"); + } + } + + return TRUE; +} + +INT Show_RtsInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + static ULONG time_tmp_2g = 0; + static ULONG time_tmp_5g = 0; + + ULONG now = 0; + ULONG measured_time =0; + UINT32 rts_ok_count; + UINT32 rts_fail_count; + UINT32 rts_count; + RTS_TX_CNT_STRUC RtsCount; + + RTMP_GetCurrentSystemTick(&now); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + + if (!time_tmp_5g) { + + time_tmp_5g = now; + + NicGetTxRTSCounters(pAd, &RtsCount); + RTMP_GetCurrentSystemTick(&now); + } + measured_time = jiffies_to_msecs(now - time_tmp_5g); + time_tmp_5g = now; + } + else +#endif + { + if (!time_tmp_2g) { + + time_tmp_2g = now; + + NicGetTxRTSCounters(pAd, &RtsCount); + RTMP_GetCurrentSystemTick(&now); + } + measured_time = jiffies_to_msecs(now - time_tmp_2g); + time_tmp_2g = now; + } + + NicGetTxRTSCounters(pAd, &RtsCount); + + rts_ok_count = RtsCount.field.RtsTxOkCount; + rts_fail_count = RtsCount.field.RtsTxFailCount; + rts_count = rts_ok_count + rts_fail_count; + + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %ld (ms)\n", "Measured Time", measured_time)); + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %d\n", "RTS TX OK count", rts_ok_count)); + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %d\n", "RTS TX fail count", rts_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %d\n", "Total amount of RTS", rts_count)); + + + return TRUE; +} + +INT Show_ChannelTimeInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + + UINT32 busy_time; + UINT32 idle_time; + UINT32 polling_period; + UINT32 timer_enable; + + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &timer_enable); + timer_enable &= (0x01); + + if (timer_enable == 0) { + DBGPRINT(RT_DEBUG_OFF, ("Channel Timer is Disable\n")); + return TRUE; + } + + RTMP_IO_READ32(pAd, CH_BUSY_STA, &busy_time); + RTMP_IO_READ32(pAd, CH_IDLE_STA, &idle_time); + +#ifdef SMART_MESH + pAd->ChannelTimerCounters.ChBusyTime += busy_time; + pAd->ChannelTimerCounters.ChIdleTime += idle_time; +#endif /* SMART_MESH */ + /* translate us to ms */ + busy_time = busy_time >> 10; + idle_time = idle_time >> 10; + + polling_period = busy_time + idle_time; + + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %d(ms)\n", "Polling Period", polling_period)); + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %d(ms)\n", "Channel Busy Time", busy_time)); + DBGPRINT(RT_DEBUG_OFF, ("%-20s= %d(ms)\n", "Channel Idle Time", idle_time)); + + return TRUE; +} + +#ifdef DOT11_N_SUPPORT +INT Show_BaTable_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + STRING tmpBuf[8]; + + for (i=0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_NONE(pEntry)) + continue; + + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst != SST_ASSOC)) + continue; + + if (IS_ENTRY_APCLI(pEntry)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pEntry->bReptCli == TRUE) + strcpy(tmpBuf, "ReptCli"); + else +#endif /* MAC_REPEATER_SUPPORT */ + strcpy(tmpBuf, "ApCli"); + } + else if (IS_ENTRY_WDS(pEntry)) + strcpy(tmpBuf, "WDS"); + else if (IS_ENTRY_MESH(pEntry)) + strcpy(tmpBuf, "Mesh"); + else + strcpy(tmpBuf, "STA"); + + printk("%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (%s) -\n", + PRINT_MAC(pEntry->Addr), pEntry->Aid, tmpBuf); + + printk("[Recipient]\n"); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + { + pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; + printk("TID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); + } + } + printk("\n"); + + printk("[Originator]\n"); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + { + pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; + printk("TID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]); + } + } + printk("\n\n"); + } + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +INT Show_RAInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ +#ifdef PRE_ANT_SWITCH + DBGPRINT(RT_DEBUG_OFF, ("PreAntSwitch: %d\n", pAd->CommonCfg.PreAntSwitch)); + DBGPRINT(RT_DEBUG_OFF, ("PreAntSwitchRSSI: %d\n", pAd->CommonCfg.PreAntSwitchRSSI)); +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK + DBGPRINT(RT_DEBUG_OFF, ("CFOTrack: %d\n", pAd->CommonCfg.CFOTrack)); +#endif /* CFO_TRACK */ + + +#ifdef NEW_RATE_ADAPT_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("LowTrafficThrd: %d\n", pAd->CommonCfg.lowTrafficThrd)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpRule: %d\n", pAd->CommonCfg.TrainUpRule)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpRuleRSSI: %d\n", pAd->CommonCfg.TrainUpRuleRSSI)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpLowThrd: %d\n", pAd->CommonCfg.TrainUpLowThrd)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpHighThrd: %d\n", pAd->CommonCfg.TrainUpHighThrd)); +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("StreamMode: %d\n", pAd->CommonCfg.StreamMode)); + DBGPRINT(RT_DEBUG_OFF, ("StreamModeMCS: 0x%04x\n", pAd->CommonCfg.StreamModeMCS)); +#endif /* STREAM_MODE_SUPPORT */ +#ifdef TXBF_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("ITxBfEn: %d\n", pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn)); + DBGPRINT(RT_DEBUG_OFF, ("ITxBfTimeout: %ld\n", pAd->CommonCfg.ITxBfTimeout)); + DBGPRINT(RT_DEBUG_OFF, ("ETxBfTimeout: %ld\n", pAd->CommonCfg.ETxBfTimeout)); + DBGPRINT(RT_DEBUG_OFF, ("ETxBfEnCond: %ld\n", pAd->CommonCfg.ETxBfEnCond)); + DBGPRINT(RT_DEBUG_OFF, ("ETxBfNoncompress: %d\n", pAd->CommonCfg.ETxBfNoncompress)); + DBGPRINT(RT_DEBUG_OFF, ("ETxBfIncapable: %d\n", pAd->CommonCfg.ETxBfIncapable)); +#endif /* TXBF_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("DebugFlags: 0x%lx\n", pAd->CommonCfg.DebugFlags)); +#endif /* DBG_CTRL_SUPPORT */ + + return TRUE; +} + + +#ifdef DBG_DIAGNOSE +#ifdef RTMP_MAC_PCI +INT Set_DiagOpt_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG diagOpt; + /*POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; */ + + diagOpt = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DiagOpt=%ld!\n", diagOpt)); + + + return TRUE; +} + + +INT Set_BDInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT32 i, QueIdx=0; + UINT32 RegValue; + RXD_STRUC *pRxD; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD, *pDestTxD; + RXD_STRUC RxD, TxD; +#endif /* RT_BIG_ENDIAN */ + RTMP_TX_RING *pTxRing = &pAd->TxRing[QueIdx]; + RTMP_MGMT_RING *pMgmtRing = &pAd->MgmtRing; + RTMP_RX_RING *pRxRing = &pAd->RxRing[0]; + + printk("\n"); + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08x\n", + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED) ? "short" : "long", + RegValue); +#ifdef DOT11_N_SUPPORT + printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); +#endif /* DOT11_N_SUPPORT */ + printk("\n"); + printk("[Tx]: SwFreeIdx=%d, CpuIdx=%d, DmaIdx=%d\n", + pAd->TxRing[QueIdx].TxSwFreeIdx, + pAd->TxRing[QueIdx].TxCpuIdx, + pAd->TxRing[QueIdx].TxDmaIdx); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pTxRing->Cell[pAd->TxRing[QueIdx].TxSwFreeIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pTxRing->Cell[pAd->TxRing[QueIdx].TxSwFreeIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Tx SwFreeIdx Descriptor", (char *)pTxD, 16); + printk("pTxD->DMADONE = %x\n", pTxD->DMADONE); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Tx CpuIdx Descriptor", (char *)pTxD, 16); + printk("pTxD->DMADONE = %x\n", pTxD->DMADONE); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pTxRing->Cell[pAd->TxRing[QueIdx].TxDmaIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pTxRing->Cell[pAd->TxRing[QueIdx].TxDmaIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Tx DmaIdx Descriptor", (char *)pTxD, 16); + printk("pTxD->DMADONE = %x\n", pTxD->DMADONE); + + printk("[Mgmt]: SwFreeIdx=%d, CpuIdx=%d, DmaIdx=%d\n", + pAd->MgmtRing.TxSwFreeIdx, + pAd->MgmtRing.TxCpuIdx, + pAd->MgmtRing.TxDmaIdx); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Mgmt SwFreeIdx Descriptor", (char *)pTxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pMgmtRing->Cell[pAd->MgmtRing.TxCpuIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pMgmtRing->Cell[pAd->MgmtRing.TxCpuIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Mgmt CpuIdx Descriptor", (char *)pTxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pMgmtRing->Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pMgmtRing->Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Mgmt DmaIdx Descriptor", (char *)pTxD, 16); + printk("\n"); + printk("[Rx]: SwRedIdx=%d, CpuIdx=%d, DmaIdx=%d\n", + pAd->RxRing[0].RxSwReadIdx, + pAd->RxRing[0].RxCpuIdx, + pAd->RxRing[0].RxDmaIdx); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing[0].RxSwReadIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing[0].RxSwReadIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("RX SwRedIdx Descriptor", (char *)pRxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing[0].RxCpuIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing[0].RxCpuIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("RX RxCupIdx Descriptor", (char *)pRxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing[0].RxDmaIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing[0].RxDmaIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("RX RxDmaIdx Descritpro", (char *)pRxD, 16); + printk("\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", + "MAC", "AID", "PSM", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC"); + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->PsMode); + printk("%-7d", pEntry->RssiSample.AvgRssi0); + printk("%-7d", pEntry->RssiSample.AvgRssi1); + printk("%-7d", pEntry->RssiSample.AvgRssi2); + + + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-10d, %d, %d\n", pEntry->FIFOCount, pEntry->DebugTxCount, pEntry->DebugTxCount-pEntry->FIFOCount); + + printk("\n"); + } + } + + return TRUE; +} +#endif /* RTMP_MAC_PCI */ +#endif /* DBG_DIAGNOSE */ + + +INT Show_Sat_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + /* Sanity check for calculation of sucessful count */ + printk("TransmitCountFromOS = %d\n", pAd->WlanCounters.TransmitCountFrmOs.u.LowPart); + printk("TransmittedFragmentCount = %lld\n", pAd->WlanCounters.TransmittedFragmentCount.u.LowPart + pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart); + printk("MulticastTransmittedFrameCount = %d\n", pAd->WlanCounters.MulticastTransmittedFrameCount.u.LowPart); + printk("FailedCount = %d\n", pAd->WlanCounters.FailedCount.u.LowPart); + printk("RetryCount = %d\n", pAd->WlanCounters.RetryCount.u.LowPart); + printk("MultipleRetryCount = %d\n", pAd->WlanCounters.MultipleRetryCount.u.LowPart); + printk("RTSSuccessCount = %d\n", pAd->WlanCounters.RTSSuccessCount.u.LowPart); + printk("RTSFailureCount = %d\n", pAd->WlanCounters.RTSFailureCount.u.LowPart); + printk("ACKFailureCount = %d\n", pAd->WlanCounters.ACKFailureCount.u.LowPart); + printk("FrameDuplicateCount = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + printk("ReceivedFragmentCount = %d\n", pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + printk("MulticastReceivedFrameCount = %d\n", pAd->WlanCounters.MulticastReceivedFrameCount.u.LowPart); + printk("Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); +#ifdef DBG + printk("RealFcsErrCount = %d\n", pAd->RalinkCounters.RealFcsErrCount.u.LowPart); +#else + printk("FCSErrorCount = %d\n", pAd->WlanCounters.FCSErrorCount.u.LowPart); + printk("FrameDuplicateCount.LowPart = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100); +#endif + printk("TransmittedFrameCount = %d\n", pAd->WlanCounters.TransmittedFragmentCount.u.LowPart); + printk("WEPUndecryptableCount = %d\n", pAd->WlanCounters.WEPUndecryptableCount.u.LowPart); + +#ifdef DOT11_N_SUPPORT + printk("\n===Some 11n statistics variables: \n"); + /* Some 11n statistics variables */ + printk("TransmittedAMSDUCount = %ld\n", (ULONG)pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart); + printk("TransmittedOctetsInAMSDU = %ld\n", (ULONG)pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart); + printk("ReceivedAMSDUCount = %ld\n", (ULONG)pAd->RalinkCounters.ReceivedAMSDUCount.u.LowPart); + printk("ReceivedOctesInAMSDUCount = %ld\n", (ULONG)pAd->RalinkCounters.ReceivedOctesInAMSDUCount.QuadPart); + printk("TransmittedAMPDUCount = %ld\n", (ULONG)pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart); + printk("TransmittedMPDUsInAMPDUCount = %ld\n", (ULONG)pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart); + printk("TransmittedOctetsInAMPDUCount = %ld\n", (ULONG)pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.u.LowPart); + printk("MPDUInReceivedAMPDUCount = %ld\n", (ULONG)pAd->RalinkCounters.MPDUInReceivedAMPDUCount.u.LowPart); +#ifdef DOT11N_DRAFT3 + printk("fAnyStaFortyIntolerant=%d\n", pAd->MacTab.fAnyStaFortyIntolerant); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +{ + int apidx; + + for (apidx=0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + printk("-- IF-ra%d -- \n", apidx); + printk("Packets Received = %lu\n", pAd->ApCfg.MBSSID[apidx].RxCount); + printk("Packets Sent = %lu\n", pAd->ApCfg.MBSSID[apidx].TxCount); + printk("Bytes Received = %llu\n", pAd->ApCfg.MBSSID[apidx].ReceivedByteCount.QuadPart); + printk("Byte Sent = %llu\n", pAd->ApCfg.MBSSID[apidx].TransmittedByteCount.QuadPart); + printk("Error Packets Received = %lu\n", pAd->ApCfg.MBSSID[apidx].RxErrorCount); + printk("Drop Received Packets = %lu\n", pAd->ApCfg.MBSSID[apidx].RxDropCount); + +#ifdef WSC_INCLUDED + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) + { + WSC_CTRL *pWscCtrl; + + pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + printk("WscInfo:\n" + "\tWscConfMode=%d\n" + "\tWscMode=%s\n" + "\tWscConfStatus=%d\n" + "\tWscPinCode=%d\n" + "\tWscState=0x%x\n" + "\tWscStatus=0x%x\n", + pWscCtrl->WscConfMode, + ((pWscCtrl->WscMode == WSC_PIN_MODE) ? "PIN" : "PBC"), + pWscCtrl->WscConfStatus, pWscCtrl->WscEnrolleePinCode, + pWscCtrl->WscState, pWscCtrl->WscStatus); + } +#endif /* WSC_INCLUDED */ + + printk("-- IF-ra%d end -- \n", apidx); + } +} + +{ + int i, j, k, maxMcs = MAX_MCS_SET -1; + PMAC_TABLE_ENTRY pEntry; + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + maxMcs = 23; +#endif /* DOT11N_SS3_SUPPORT */ + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + printk("\n%02x:%02x:%02x:%02x:%02x:%02x - ", PRINT_MAC(pEntry->Addr)); + printk("%-4d\n", (int)pEntry->Aid); + + for (j=maxMcs; j>=0; j--) + { + if ((pEntry->TXMCSExpected[j] != 0) || (pEntry->TXMCSFailed[j] !=0)) + { + printk("MCS[%02d]: Expected %u, Successful %u (%d%%), Failed %u\n", + j, pEntry->TXMCSExpected[j], pEntry->TXMCSSuccessful[j], + pEntry->TXMCSExpected[j] ? (100*pEntry->TXMCSSuccessful[j])/pEntry->TXMCSExpected[j] : 0, + pEntry->TXMCSFailed[j]); + for(k=maxMcs; k>=0; k--) + { + if (pEntry->TXMCSAutoFallBack[j][k] != 0) + { + printk("\t\t\tAutoMCS[%02d]: %u (%d%%)\n", k, pEntry->TXMCSAutoFallBack[j][k], + (100*pEntry->TXMCSAutoFallBack[j][k])/pEntry->TXMCSExpected[j]); + } + } + } + } + } + } + +} + +#ifdef DOT11_N_SUPPORT + /* Display Tx Aggregation statistics */ + DisplayTxAgg(pAd); +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} + + + +INT Show_Sat_Reset_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + /* Sanity check for calculation of sucessful count */ + + printk("TransmittedFragmentCount = %lld\n", pAd->WlanCounters.TransmittedFragmentCount.u.LowPart + pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart); + printk("MulticastTransmittedFrameCount = %d\n", pAd->WlanCounters.MulticastTransmittedFrameCount.u.LowPart); + printk("FailedCount = %d\n", pAd->WlanCounters.FailedCount.u.LowPart); + printk("RetryCount = %d\n", pAd->WlanCounters.RetryCount.u.LowPart); + printk("MultipleRetryCount = %d\n", pAd->WlanCounters.MultipleRetryCount.u.LowPart); + printk("RTSSuccessCount = %d\n", pAd->WlanCounters.RTSSuccessCount.u.LowPart); + printk("RTSFailureCount = %d\n", pAd->WlanCounters.RTSFailureCount.u.LowPart); + printk("ACKFailureCount = %d\n", pAd->WlanCounters.ACKFailureCount.u.LowPart); + printk("FrameDuplicateCount = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + printk("ReceivedFragmentCount = %d\n", pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + printk("MulticastReceivedFrameCount = %d\n", pAd->WlanCounters.MulticastReceivedFrameCount.u.LowPart); + printk("Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); +#ifdef DBG + printk("RealFcsErrCount = %d\n", pAd->RalinkCounters.RealFcsErrCount.u.LowPart); +#else + printk("FCSErrorCount = %d\n", pAd->WlanCounters.FCSErrorCount.u.LowPart); + printk("FrameDuplicateCount.LowPart = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100); +#endif + printk("TransmittedFrameCount = %d\n", pAd->WlanCounters.TransmittedFrameCount.u.LowPart); + printk("WEPUndecryptableCount = %d\n", pAd->WlanCounters.WEPUndecryptableCount.u.LowPart); + + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart = 0; + pAd->WlanCounters.MulticastTransmittedFrameCount.u.LowPart = 0; + pAd->WlanCounters.FailedCount.u.LowPart = 0; + pAd->WlanCounters.RetryCount.u.LowPart = 0; + pAd->WlanCounters.MultipleRetryCount.u.LowPart = 0; + pAd->WlanCounters.RTSSuccessCount.u.LowPart = 0; + pAd->WlanCounters.RTSFailureCount.u.LowPart = 0; + pAd->WlanCounters.ACKFailureCount.u.LowPart = 0; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart = 0; + pAd->WlanCounters.ReceivedFragmentCount.u.LowPart = 0; + pAd->WlanCounters.MulticastReceivedFrameCount.u.LowPart = 0; + pAd->Counters8023.RxNoBuffer = 0; +#ifdef DBG + pAd->RalinkCounters.RealFcsErrCount.u.LowPart = 0; +#else + pAd->WlanCounters.FCSErrorCount.u.LowPart = 0; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart = 0; +#endif + + pAd->WlanCounters.TransmittedFrameCount.u.LowPart = 0; + pAd->WlanCounters.WEPUndecryptableCount.u.LowPart = 0; + + { + int i, j, k, maxMcs = 15; + PMAC_TABLE_ENTRY pEntry; + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + maxMcs = 23; +#endif /* DOT11N_SS3_SUPPORT */ + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + + printk("\n%02X:%02X:%02X:%02X:%02X:%02X - ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + printk("%-4d\n", (int)pEntry->Aid); + + for (j = maxMcs; j >= 0; j--) + { + if ((pEntry->TXMCSExpected[j] != 0) || (pEntry->TXMCSFailed[j] !=0)) + { + printk("MCS[%02d]: Expected %u, Successful %u (%d%%), Failed %u\n", + j, pEntry->TXMCSExpected[j], pEntry->TXMCSSuccessful[j], + pEntry->TXMCSExpected[j] ? (100*pEntry->TXMCSSuccessful[j])/pEntry->TXMCSExpected[j] : 0, + pEntry->TXMCSFailed[j] + ); + for(k = maxMcs; k >= 0; k--) + { + if (pEntry->TXMCSAutoFallBack[j][k] != 0) + { + printk("\t\t\tAutoMCS[%02d]: %u (%d%%)\n", k, pEntry->TXMCSAutoFallBack[j][k], + (100*pEntry->TXMCSAutoFallBack[j][k])/pEntry->TXMCSExpected[j]); + } + } + } + } + } + for (j = 0; j < (maxMcs + 1); j++) + { + pEntry->TXMCSExpected[j] = 0; + pEntry->TXMCSSuccessful[j] = 0; + pEntry->TXMCSFailed[j] = 0; + for(k = maxMcs; k >= 0; k--) + { + pEntry->TXMCSAutoFallBack[j][k] = 0; + } + } + } + } +#ifdef DOT11_N_SUPPORT + /* Display Tx Aggregation statistics */ + DisplayTxAgg(pAd); +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} + + +#ifdef MAT_SUPPORT +INT Show_MATTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + extern VOID dumpIPMacTb(MAT_STRUCT *pMatCfg, int index); + extern NDIS_STATUS dumpSesMacTb(MAT_STRUCT *pMatCfg, int hashIdx); + extern NDIS_STATUS dumpUidMacTb(MAT_STRUCT *pMatCfg, int hashIdx); + extern NDIS_STATUS dumpIPv6MacTb(MAT_STRUCT *pMatCfg, int hashIdx); + if(pAd->MatCfg.status == MAT_ENGINE_STAT_EXITED) + return TRUE; + + dumpIPMacTb(&pAd->MatCfg, -1); + dumpSesMacTb(&pAd->MatCfg, -1); + dumpUidMacTb(&pAd->MatCfg, -1); + dumpIPv6MacTb(&pAd->MatCfg, -1); + + printk("Default BroadCast Address=%02x:%02x:%02x:%02x:%02x:%02x!\n", BROADCAST_ADDR[0], BROADCAST_ADDR[1], + BROADCAST_ADDR[2], BROADCAST_ADDR[3], BROADCAST_ADDR[4], BROADCAST_ADDR[5]); + return TRUE; +} +#endif /* MAT_SUPPORT */ + + +#ifdef DOT1X_SUPPORT +/* + ========================================================================== + Description: + It only shall be queried by 802.1x daemon for querying radius configuration. + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlQueryRadiusConf( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR apidx, srv_idx, keyidx, KeyLen = 0; + UCHAR *mpool; + PDOT1X_CMM_CONF pConf; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlQueryRadiusConf==>\n")); + + /* Allocate memory */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, sizeof(DOT1X_CMM_CONF)); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s: out of resource!!!\n", __FUNCTION__)); + return; + } + NdisZeroMemory(mpool, sizeof(DOT1X_CMM_CONF)); + + pConf = (PDOT1X_CMM_CONF)mpool; + + /* get MBSS number */ + pConf->mbss_num = pAd->ApCfg.BssidNum; + + /* get own ip address */ + pConf->own_ip_addr = pAd->ApCfg.own_ip_addr; + + /* get retry interval */ + pConf->retry_interval = pAd->ApCfg.retry_interval; + + /* get session timeout interval */ + pConf->session_timeout_interval = pAd->ApCfg.session_timeout_interval; + + /* Get the quiet interval */ + pConf->quiet_interval = pAd->ApCfg.quiet_interval; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + PDOT1X_BSS_INFO p1xBssInfo = &pConf->Dot1xBssInfo[apidx]; + + p1xBssInfo->radius_srv_num = pMbss->radius_srv_num; + + /* prepare radius ip, port and key */ + for (srv_idx = 0; srv_idx < pMbss->radius_srv_num; srv_idx++) + { + if (pMbss->radius_srv_info[srv_idx].radius_ip != 0) + { + p1xBssInfo->radius_srv_info[srv_idx].radius_ip = pMbss->radius_srv_info[srv_idx].radius_ip; + p1xBssInfo->radius_srv_info[srv_idx].radius_port = pMbss->radius_srv_info[srv_idx].radius_port; + p1xBssInfo->radius_srv_info[srv_idx].radius_key_len = pMbss->radius_srv_info[srv_idx].radius_key_len; + if (pMbss->radius_srv_info[srv_idx].radius_key_len > 0) + { + NdisMoveMemory(p1xBssInfo->radius_srv_info[srv_idx].radius_key, + pMbss->radius_srv_info[srv_idx].radius_key, + pMbss->radius_srv_info[srv_idx].radius_key_len); + } + } + } + + p1xBssInfo->ieee8021xWEP = (pMbss->wdev.IEEE8021X) ? 1 : 0; + + if (p1xBssInfo->ieee8021xWEP) + { + /* Default Key index, length and material */ + keyidx = pMbss->wdev.DefaultKeyId; + p1xBssInfo->key_index = keyidx; + + /* Determine if the key is valid. */ + KeyLen = pAd->SharedKey[apidx][keyidx].KeyLen; + if (KeyLen == 5 || KeyLen == 13) + { + p1xBssInfo->key_length = KeyLen; + NdisMoveMemory(p1xBssInfo->key_material, pAd->SharedKey[apidx][keyidx].Key, KeyLen); + } + } + + /* Get NAS-ID per BSS */ + if (pMbss->NasIdLen > 0) + { + p1xBssInfo->nasId_len = pMbss->NasIdLen; + NdisMoveMemory(p1xBssInfo->nasId, pMbss->NasId, pMbss->NasIdLen); + } + + /* get EAPifname */ + if (pAd->ApCfg.EAPifname_len[apidx] > 0) + { + pConf->EAPifname_len[apidx] = pAd->ApCfg.EAPifname_len[apidx]; + NdisMoveMemory(pConf->EAPifname[apidx], pAd->ApCfg.EAPifname[apidx], pAd->ApCfg.EAPifname_len[apidx]); + } + + /* get PreAuthifname */ + if (pAd->ApCfg.PreAuthifname_len[apidx] > 0) + { + pConf->PreAuthifname_len[apidx] = pAd->ApCfg.PreAuthifname_len[apidx]; + NdisMoveMemory(pConf->PreAuthifname[apidx], pAd->ApCfg.PreAuthifname[apidx], pAd->ApCfg.PreAuthifname_len[apidx]); + } + + } + + wrq->u.data.length = sizeof(DOT1X_CMM_CONF); + if (copy_to_user(wrq->u.data.pointer, pConf, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + os_free_mem(NULL, mpool); + +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlRadiusData( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid MBSSID index(%d)!\n", + __FUNCTION__, pObj->ioctl_if)); + return; + } + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) + || (wdev->IEEE8021X == TRUE)) + WpaSend(pAd, (PUCHAR)wrq->u.data.pointer, wrq->u.data.length); +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlAddWPAKey( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + NDIS_AP_802_11_KEY *pKey; + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + UCHAR apidx; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = (UCHAR) pObj->ioctl_if; + + + pKey = (PNDIS_AP_802_11_KEY) wrq->u.data.pointer; + + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + { + if ((pKey->KeyLength == 32) || (pKey->KeyLength == 64)) + { + if ((pEntry = MacTableLookup(pAd, pKey->addr)) != NULL) + { + INT k_offset = 0; + +#ifdef DOT11R_FT_SUPPORT + /* The key shall be the second 256 bits of the MSK. */ + if (IS_FT_RSN_STA(pEntry) && pKey->KeyLength == 64) + k_offset = 32; +#endif /* DOT11R_FT_SUPPORT */ + + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].PMK, pKey->KeyMaterial + k_offset, 32); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Add PMK=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x....\n", apidx, + pAd->ApCfg.MBSSID[apidx].PMK[0],pAd->ApCfg.MBSSID[apidx].PMK[1],pAd->ApCfg.MBSSID[apidx].PMK[2],pAd->ApCfg.MBSSID[apidx].PMK[3], + pAd->ApCfg.MBSSID[apidx].PMK[4],pAd->ApCfg.MBSSID[apidx].PMK[5],pAd->ApCfg.MBSSID[apidx].PMK[6],pAd->ApCfg.MBSSID[apidx].PMK[7])); + } + } + } + else /* Old WEP stuff */ + { + UCHAR CipherAlg; + + if(pKey->KeyLength > 16) + return; + + KeyIdx = pKey->KeyIndex & 0x0fffffff; + + if (KeyIdx < 4) + { + /* it is a shared key */ + if (pKey->KeyIndex & 0x80000000) + { + UINT8 Wcid; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Set Group Key\n", apidx)); + + /* Default key for tx (shared key) */ + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId = (UCHAR) KeyIdx; + + /* set key material and key length */ + if (pKey->KeyLength > 16) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Key length too long %d\n", apidx, pKey->KeyLength)); + pKey->KeyLength = 16; + } + pAd->SharedKey[apidx][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* Set Ciper type */ + if (pKey->KeyLength == 5) + pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_WEP128; + + CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, apidx, (UINT8)KeyIdx, &pAd->SharedKey[apidx][KeyIdx]); + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + RTMPSetWcidSecurityInfo(pAd, apidx,(UINT8)KeyIdx, + CipherAlg, Wcid, SHAREDKEYTABLE); + } + else /* For Pairwise key setting */ + { + pEntry = MacTableLookup(pAd, pKey->addr); + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Set Pair-wise Key\n", apidx)); + + /* set key material and key length */ + pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* set Cipher type */ + if (pKey->KeyLength == 5) + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + else + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + + } + } + } + } +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR apidx; + NDIS_AP_802_11_KEY *pKey; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = (UCHAR) pObj->ioctl_if; + + pKey = (PNDIS_AP_802_11_KEY) wrq->u.data.pointer; + + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA2) + { + if(pKey->KeyLength == 32) + { + UCHAR digest[80], PMK_key[20], macaddr[MAC_ADDR_LEN]; + + /* Calculate PMKID */ + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pKey->addr, MAC_ADDR_LEN); + RT_HMAC_SHA1(pKey->KeyMaterial, PMK_LEN, PMK_key, 20, digest, SHA1_DIGEST_SIZE); + + NdisMoveMemory(macaddr, pKey->addr, MAC_ADDR_LEN); + RTMPAddPMKIDCache(pAd, apidx, macaddr, digest, pKey->KeyMaterial); + + DBGPRINT(RT_DEBUG_TRACE, ("WPA2(pre-auth):(%02x:%02x:%02x:%02x:%02x:%02x)Calc PMKID=%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey->addr[0],pKey->addr[1],pKey->addr[2],pKey->addr[3],pKey->addr[4],pKey->addr[5],digest[0],digest[1],digest[2],digest[3],digest[4],digest[5])); + DBGPRINT(RT_DEBUG_TRACE, ("PMK =%02x:%02x:%02x:%02x-%02x:%02x:%02x:%02x\n",pKey->KeyMaterial[0],pKey->KeyMaterial[1], + pKey->KeyMaterial[2],pKey->KeyMaterial[3],pKey->KeyMaterial[4],pKey->KeyMaterial[5],pKey->KeyMaterial[6],pKey->KeyMaterial[7])); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Set::RT_OID_802_11_WPA2_ADD_PMKID_CACHE ERROR or is wep key \n")); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPIoctlAddPMKIDCache\n")); +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlStaticWepCopy( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + MAC_TABLE_ENTRY *pEntry; + UCHAR MacAddr[MAC_ADDR_LEN]; + UCHAR apidx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = (UCHAR) pObj->ioctl_if; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlStaticWepCopy-IF(ra%d)\n", apidx)); + + if (wrq->u.data.length != sizeof(MacAddr)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPIoctlStaticWepCopy: the length isn't match (%d)\n", wrq->u.data.length)); + return; + } + else + { + copy_from_user(&MacAddr, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, MacAddr); + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPIoctlStaticWepCopy: the mac address isn't match\n")); + return; + } + else + { + UCHAR KeyIdx; + + KeyIdx = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId; + + /* need to copy the default shared-key to pairwise key table for this entry in 802.1x mode */ + if (pAd->SharedKey[apidx][KeyIdx].KeyLen == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: Can not get Default shared-key (index-%d)\n", KeyIdx)); + return; + } + else + { + pEntry->PairwiseKey.KeyLen = pAd->SharedKey[apidx][KeyIdx].KeyLen; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[apidx][KeyIdx].Key, pEntry->PairwiseKey.KeyLen); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + } + + } + } + return; +} + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlSetIdleTimeout( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + MAC_TABLE_ENTRY *pEntry; + PDOT1X_IDLE_TIMEOUT pIdleTime; + + if (wrq->u.data.length != sizeof(DOT1X_IDLE_TIMEOUT)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the length is mis-match\n", __FUNCTION__)); + return; + } + + pIdleTime = (PDOT1X_IDLE_TIMEOUT)wrq->u.data.pointer; + + if ((pEntry = MacTableLookup(pAd, pIdleTime->StaAddr)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the entry is empty\n", __FUNCTION__)); + return; + } + else + { + pEntry->NoDataIdleCount = 0; + pEntry->StaIdleTimeout = pIdleTime->idle_timeout; + DBGPRINT(RT_DEBUG_TRACE, ("%s : Update Idle-Timeout(%d) from dot1x daemon\n", + __FUNCTION__, pEntry->StaIdleTimeout)); + } + + return; +} + + +VOID RTMPIoctlQueryStaAid( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + DOT1X_QUERY_STA_AID macBuf; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (wrq->u.data.length != sizeof(DOT1X_QUERY_STA_AID)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the length is mis-match\n", __FUNCTION__)); + return; + } + else + { + copy_from_user(&macBuf, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, macBuf.StaAddr); + + if (pEntry != NULL) + { + wrq->u.data.length = sizeof(DOT1X_QUERY_STA_AID); + macBuf.aid = pEntry->Aid; + if (copy_to_user(wrq->u.data.pointer, &macBuf, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_DOT1X_QUERY_STA_AID(%02x:%02x:%02x:%02x:%02x:%02x, AID=%d)\n", + PRINT_MAC(macBuf.StaAddr), macBuf.aid)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_DOT1X_QUERY_STA_AID(%02x:%02x:%02x:%02x:%02x:%02x, Not Found)\n", + PRINT_MAC(macBuf.StaAddr))); + } + } +} +#endif /* DOT1X_SUPPORT */ + + +#if defined(DBG) || defined(RALINK_ATE) + +#ifdef RT65xx +VOID RTMPAPIoctlBBP32(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char; + PSTRING value; + UINT32 regBBP = 0; + PSTRING mpool, msg; /*msg[2048]; */ + PSTRING arg; /*arg[255]; */ + PSTRING ptr; + INT bbpId = 0; + LONG bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE, bAllowDump/*, bCopyMsg*/; + INT argLen; + + + + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(MAX_BBP_MSG_SIZE * 2 +256+12)); + if (mpool == NULL) { + return; + } + + NdisZeroMemory(mpool, MAX_BBP_MSG_SIZE * 2 +256+12); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (PSTRING)((ULONG)(msg+MAX_BBP_MSG_SIZE * 2+3) & (ULONG)~0x03); + + bAllowDump = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_NODUMPMSG) == RTPRIV_IOCTL_FLAG_NODUMPMSG) ? FALSE : TRUE; + argLen = strlen((char *)(wrq->u.data.pointer)); + + if (argLen > 0) + { + NdisMoveMemory(arg, wrq->u.data.pointer, (argLen > 255) ? 255 : argLen); + ptr = arg; + sprintf(msg, "\n"); + /* Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { + /*Read */ + if (sscanf(this_char, "%x", &(bbpId)) == 1) + { + if ((bbpId <= 0x2fff) && (bbpId >= 0x2000)) + { + /* according to Andy, Gary, David require. */ + /* the command bbp shall read BBP register directly for dubug. */ + RTMP_BBP_IO_READ32(pAd, bbpId, ®BBP); + sprintf(msg+strlen(msg), "BBP[0x%04x]:%08x \n", bbpId, regBBP); + } + else + { + /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + else + { + /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + else + { /* Write */ + if ((sscanf(this_char, "%x", &(bbpId)) == 1) && (sscanf(value, "%lx", &(bbpValue)) == 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("bbpID=%04x, value=0x%lx\n", bbpId, bbpValue)); + if ((bbpId <= 0x2fff) && (bbpId >= 0x2000)) + { + /* according to Andy, Gary, David require. */ + /* the command bbp shall read/write BBP register directly for dubug. */ + RTMP_BBP_IO_WRITE32(pAd, bbpId, bbpValue); + /*Read it back for showing */ + RTMP_BBP_IO_READ32(pAd, bbpId, ®BBP); + sprintf(msg+strlen(msg), "BBP[0x%04x]:%08x\n", bbpId, regBBP); + } + else + { + /* Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + else + { + /* Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + } + } + else + bIsPrintAllBBP = TRUE; + + if (bIsPrintAllBBP) + { + static RTMP_REG_PAIR bbp_regs[]={ + {CORE_R0, CORE_R44}, + {IBI_R0, IBI_R15}, + {AGC1_R0, AGC1_R63}, + {TXC_R0, TXC_R1}, + {RXC_R0, RXC_R9}, + {TXO_R0, TXO_R13}, + {TXBE_R0, TXBE_R52}, + {RXFE_R0, RXFE_R17}, + {RXO_R0, RXO_R63}, + {DFS_R0, DFS_R37}, + {TR_R0, TR_R9}, + {CAL_R0, CAL_R62}, + {DSC_R0, DSC_R10}, + {PFMU_R0, PFMU_R57} + }; + UINT32 reg, i; + + memset(msg, 0x00, MAX_BBP_MSG_SIZE * 2); + sprintf(msg, "\n"); + for (i = 0; i < sizeof(bbp_regs) / sizeof(RTMP_REG_PAIR); i++) + { + for (reg = bbp_regs[i].Register; reg <= bbp_regs[i].Value; reg += 4) + { + RTMP_BBP_IO_READ32(pAd, reg, ®BBP); + if (strlen(msg) >= (MAX_BBP_MSG_SIZE * 2 - 25)) + break; + sprintf(msg+strlen(msg), "BBP[0x%04x]:%08x\n", reg, regBBP); + if (bbpId%5 == 4) + sprintf(msg+strlen(msg), "\n"); + } + } + } + +#ifdef LINUX + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + + if (!bAllowDump) + { + DBGPRINT(RT_DEBUG_OFF, ("%s\n", msg)); + } + + os_free_mem(NULL, mpool); + if (!bAllowDump) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlBBP\n\n")); +} +#endif /* RT65xx */ + + +/* + ========================================================================== + Description: + Read / Write BBP +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 bbp ==> read all BBP + 2.) iwpriv ra0 bbp 1 ==> read BBP where RegID=1 + 3.) iwpriv ra0 bbp 1=10 ==> write BBP R1=0x10 + ========================================================================== +*/ +VOID RTMPAPIoctlBBP( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ +#ifdef RTMP_BBP + PSTRING this_char; + PSTRING value; + UCHAR regBBP = 0; + PSTRING mpool, msg; /*msg[2048]; */ + PSTRING arg; /*arg[255]; */ + PSTRING ptr; + INT bbpId; + LONG bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE, bAllowDump/*, bCopyMsg*/; + INT argLen; +#endif /* RTMP_BBP */ + + +#ifdef RT65xx + if (IS_RT65XX(pAdapter)) { + RTMPAPIoctlBBP32(pAdapter, wrq); + return; + } +#endif /* RT65xx */ + +#ifdef RTMP_BBP + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(MAX_BBP_MSG_SIZE+256+12)); + if (mpool == NULL) { + return; + } + + NdisZeroMemory(mpool, MAX_BBP_MSG_SIZE+256+12); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (PSTRING)((ULONG)(msg+MAX_BBP_MSG_SIZE+3) & (ULONG)~0x03); + + bAllowDump = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_NODUMPMSG) == RTPRIV_IOCTL_FLAG_NODUMPMSG) ? FALSE : TRUE; + argLen = strlen((char *)(wrq->u.data.pointer)); + + + if (argLen > 0) + { + NdisMoveMemory(arg, wrq->u.data.pointer, (argLen > 255) ? 255 : argLen); + ptr = arg; + sprintf(msg, "\n"); + /* Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + if (sscanf(this_char, "%d", &(bbpId)) == 1) + { + if (bbpId <= pAdapter->chipCap.MaxNumOfBbpId) + { +#ifdef RALINK_ATE + /* + In RT2860 ATE mode, we do not load 8051 firmware. + We must access BBP directly. + For RT2870 ATE mode, ATE_BBP_IO_WRITE8(/READ8)_BY_REG_ID are redefined. + */ + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", bbpId, regBBP); + } + else +#endif /* RALINK_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command bbp shall read BBP register directly for dubug. */ + //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + sprintf(msg+strlen(msg), "R%02d[0x%02x]:%02X ", bbpId, bbpId, regBBP); + } + } + else + { + /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + else + { + /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + else + { /* Write */ + if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%lx", &(bbpValue)) == 1)) + { + if (bbpId <= pAdapter->chipCap.MaxNumOfBbpId) + { +#ifdef RALINK_ATE + /* + In RT2860 ATE mode, we do not load 8051 firmware. + We must access BBP directly. + For RT2870 ATE mode, ATE_BBP_IO_WRITE8(/READ8)_BY_REG_ID are redefined. + */ + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)bbpId,(UCHAR) bbpValue); + + /*Read it back for showing */ + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", bbpId, regBBP); + } + else +#endif /* RALINK_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command bbp shall read/write BBP register directly for dubug. */ + //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + BBP_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)bbpId,(UCHAR) bbpValue); + /*Read it back for showing */ + //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X\n", bbpId, bbpId, regBBP); + } + } + else + { + /* Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + else + { + /* Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + break; + } + } + } + } + else + bIsPrintAllBBP = TRUE; + + if (bIsPrintAllBBP) + { + memset(msg, 0x00, MAX_BBP_MSG_SIZE); + sprintf(msg, "\n"); + for (bbpId = 0; bbpId <= pAdapter->chipCap.MaxNumOfBbpId; bbpId++) + { +#ifdef RALINK_ATE + /* + In RT2860 ATE mode, we do not load 8051 firmware. + We must access BBP directly. + For RT2870 ATE mode, ATE_BBP_IO_WRITE8(/READ8)_BY_REG_ID are redefined. + */ + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", bbpId, regBBP); + } + else +#endif /* RALINK_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command bbp shall read/write BBP register directly for dubug. */ + //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X ", bbpId, bbpId, regBBP); + if (bbpId%5 == 4) + sprintf(msg+strlen(msg), "\n"); + } + } + } + +#ifdef LINUX + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + + if (!bAllowDump) + { + DBGPRINT(RT_DEBUG_ERROR, ("Dump BBP msg[%d]=\n", (UINT32)strlen(msg))); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", msg)); + } + +/* kfree(mpool); */ + os_free_mem(NULL, mpool); + if (!bAllowDump) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlBBP\n\n")); +#endif /* RTMP_BBP */ +} + + +/* + ========================================================================== + Description: + Read / Write MAC +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 mac 0 ==> read MAC where Addr=0x0 + 2.) iwpriv ra0 mac 0=12 ==> write MAC where Addr=0x0, value=12 + ========================================================================== +*/ +VOID RTMPAPIoctlMAC( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char, value; + INT j = 0, k = 0; + PSTRING mpool, msg; + PSTRING arg, ptr; + UINT32 macAddr = 0; + UCHAR temp[16]; + STRING temp2[16]; + UINT32 macValue; + BOOLEAN bIsPrintAllMAC = FALSE, bFromUI; + + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(4096+256+12)); + if (!mpool) + return; + + bFromUI = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_UI) == RTPRIV_IOCTL_FLAG_UI) ? TRUE : FALSE; + + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (PSTRING)((ULONG)(msg+4096+3) & (ULONG)~0x03); + + memset(msg, 0x00, 4096); + memset(arg, 0x00, 256); + //DBGPRINT(RT_DEBUG_OFF, ("%s():wrq->u.data.length=%d, wrq->u.data.pointer=%s!\n", __FUNCTION__, wrq->u.data.length, wrq->u.data.pointer)); + if ((wrq->u.data.length > 1) + ) + { + NdisMoveMemory(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + ptr = arg; + sprintf(msg, "\n"); + /*Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + /* Sanity check */ + if(strlen(this_char) > 4) + break; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto done; + } + + /* Mac register */ + k = j = strlen(this_char); + while(j-- > 0) + this_char[4-k+j] = this_char[j]; + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + if (macAddr < 0xFFFF) + { + RTMP_IO_READ32(pAd, macAddr, &macValue); + if (!bFromUI) + DBGPRINT(RT_DEBUG_OFF, ("MacReg=0x%x, MacValue=0x%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%04x]:%08x ", macAddr , macValue); + } + else + { + /*Invalid parametes, so default printk all bbp */ + break; + } + } + } + else + { + /*Write */ + NdisMoveMemory(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + /* Sanity check */ + if((strlen(this_char) > 4) || strlen(temp2) > 8) + break; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto done; + } + + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + goto done; + } + + /* MAC register */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + /* MAC value */ + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[8-k+j] = temp2[j]; + } + + while(k < 8) + temp2[7-k++]='0'; + temp2[8]='\0'; + + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 4); + macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3]; + + /* debug mode */ + if (macAddr == (HW_DEBUG_SETTING_BASE + 4)) + { + /* 0x2bf4: byte0 non-zero: enable R66 tuning, 0: disable R66 tuning */ + if (macValue & 0x000000ff) + { + pAd->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("turn on R17 tuning\n")); + } + else + { + UCHAR R66; + pAd->BbpTuning.bEnable = FALSE; + R66 = 0x26 + GET_LNA_GAIN(pAd); + /* todo bbp_set_agc(pAd, (0x26 + GET_LNA_GAIN(pAd)), RX_CHAIN_ALL); */ + if (!bFromUI) + DBGPRINT(RT_DEBUG_OFF, ("turn off R66 tuning, restore to 0x%02x\n", R66)); + } + goto done; + } + if (!bFromUI) + DBGPRINT(RT_DEBUG_OFF, ("MacAddr=%02x, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAd, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%04x]:%08x ", macAddr, macValue); + } + } + } + } + else + { + UINT32 IdMac, mac_s = 0x1000; +#if defined(RT65xx) || defined (MT7601) + if (IS_RT65XX(pAd) || IS_MT7601(pAd)) + mac_s = 0x0; +#endif /* defined(RT65xx) || defined (MT7601) */ + + for(IdMac = mac_s; IdMac < 0x1700; IdMac += 4) + { +#ifdef RT65xx + if (IS_RT65XX(pAd)) + { + RTMP_IO_READ32(pAd, IdMac, &macValue); + DBGPRINT(RT_DEBUG_OFF, ("%08x = %08x\n", IdMac, macValue)); + } +#else + if ((IdMac & 0x0f) == 0) + DBGPRINT(RT_DEBUG_OFF, ("\n0x%04x: ", IdMac)); + + RTMP_IO_READ32(pAd, IdMac, &macValue); + DBGPRINT(RT_DEBUG_OFF, ("%08x ", macValue)); +#endif /* RT65xx */ + } + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + for(IdMac=0; IdMac<=0x2000; IdMac+=4) + { + if ((IdMac & 0x0f) == 0) + DBGPRINT(RT_DEBUG_TRACE, ("\n0x%04x: ", IdMac)); + + RTMP_IO_READ32(pAd, IdMac, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("%08x ", macValue)); + } + } +#endif /* RT6352 */ + bIsPrintAllMAC = TRUE; + } + + if (bIsPrintAllMAC) + {} + + + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + +#ifdef LINUX + /* Copy the information into the user buffer */ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + + + + +done: +/* kfree(mpool); */ + os_free_mem(NULL, mpool); + if (!bFromUI) + DBGPRINT(RT_DEBUG_INFO, ("<==RTMPIoctlMAC\n\n")); +} + +#ifdef MT_RF +VOID RTMPAPIoctlRF_mt( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UINT regRF = 0; + CHAR *mpool, *msg; /*msg[2048]; */ + BOOLEAN bIsPrintAllRF = TRUE; + UINT rfidx =0, offset = 0; + INT memLen = sizeof(CHAR) * 9000; //(2048+256+12); + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlRF\n")); + + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + NdisZeroMemory(mpool, memLen); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + + if (bIsPrintAllRF) + { + RTMPZeroMemory(msg, memLen); + sprintf(msg, "\n"); + for (rfidx = 0; rfidx <= 1; rfidx++) + { + for (offset = 0; offset <= 0x3ff; offset+=4) + { + mt_rf_read(pAd, rfidx, offset, ®RF); + sprintf(msg+strlen(msg), "%d %03x = %08X\n", rfidx, offset, regRF); + } + offset = 0xfff; + mt_rf_read(pAd, rfidx, offset, ®RF); + sprintf(msg+strlen(msg), "%d %03x = %08X\n", rfidx, offset, regRF); + } + RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); + + DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg)=%d\n", (UINT32)strlen(msg))); + /* Copy the information into the user buffer */ +#ifdef LINUX + wrq->u.data.length = strlen("Dump to RFDump.txt"); + if (copy_to_user(wrq->u.data.pointer, "Dump to RFDump.txt", wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +} +#endif /* MT_RF */ + +#ifdef RLT_RF +VOID RTMPAPIoctlRF_rlt(RTMP_ADAPTER *pAdapter, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR regRF = 0; + PSTRING mpool, msg; + INT rfId, maxRFIdx, bank_Id; + BOOLEAN bIsPrintAllRF = TRUE, bFromUI; + INT memLen = sizeof(CHAR) * (2048+256+12); + + maxRFIdx = pAdapter->chipCap.MaxNumOfRfId; + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlRF (maxRFIdx = %d)\n", maxRFIdx)); + + memLen = 12*(maxRFIdx+1)*MAC_RF_BANK; + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + bFromUI = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_UI) == RTPRIV_IOCTL_FLAG_UI) ? TRUE : FALSE; + + NdisZeroMemory(mpool, memLen); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + if (bIsPrintAllRF) + { + RTMPZeroMemory(msg, memLen); + sprintf(msg, "\n"); + for (bank_Id = 0; bank_Id <= MAC_RF_BANK; bank_Id++) + { + if (IS_MT76x0(pAdapter)) + { + if ((bank_Id <=4) && (bank_Id >=1)) + continue; + } + for (rfId = 0; rfId <= maxRFIdx; rfId++) + { + rlt_rf_read(pAdapter, bank_Id, rfId, ®RF); + sprintf(msg+strlen(msg), "%d %03d = %02X\n", bank_Id, rfId, regRF); + } + } + RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); + /* Copy the information into the user buffer */ + +#ifdef LINUX + wrq->u.data.length = strlen("Dump to RFDump.txt"); + if (copy_to_user(wrq->u.data.pointer, "Dump to RFDump.txt", wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n")); +} +#endif /* RLT_RF */ + +#ifdef RTMP_RF_RW_SUPPORT +/* + ========================================================================== + Description: + Read / Write RF register +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 rf ==> read all RF registers + 2.) iwpriv ra0 rf 1 ==> read RF where RegID=1 + 3.) iwpriv ra0 rf 1=10 ==> write RF R1=0x10 + ========================================================================== +*/ +VOID RTMPAPIoctlRF( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char; + PSTRING value; + UCHAR regRF = 0; + PSTRING mpool, msg; /*msg[2048]; */ + PSTRING arg; /*arg[255]; */ + PSTRING ptr; + INT rfId, maxRFIdx; + LONG rfValue; + BOOLEAN bIsPrintAllRF = FALSE, bFromUI; + INT memLen = sizeof(CHAR) * (2048+256+12); + +#ifdef RLT_RF + if (IS_MT7601(pAdapter) || IS_MT76x0(pAdapter)) { + RTMPAPIoctlRF_rlt(pAdapter, wrq); + return; + } +#endif /* RLT_RF */ + +#ifdef MT_RF + if (IS_MT76x2(pAdapter)) { + RTMPAPIoctlRF_mt(pAdapter, wrq); + return; + } +#endif /* MT_RF */ + + maxRFIdx = pAdapter->chipCap.MaxNumOfRfId; + +/* mpool = (PSTRING)kmalloc(memLen, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + bFromUI = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_UI) == RTPRIV_IOCTL_FLAG_UI) ? TRUE : FALSE; + + NdisZeroMemory(mpool, memLen); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (PSTRING)((ULONG)(msg+2048+3) & (ULONG)~0x03); + + if ((wrq->u.data.length > 1) /* No parameters. */ + ) + { + NdisMoveMemory(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + ptr = arg; + sprintf(msg, "\n"); + /*Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + if (sscanf(this_char, "%d", &(rfId)) == 1) + { + if (rfId <= pAdapter->chipCap.MaxNumOfRfId) + { +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); + else +#endif /* RT6352 */ + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + else +#endif /* RALINK_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command rf shall read rf register directly for dubug. */ + /* BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); */ +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + { + RT635xReadRFRegister(pAdapter, pAdapter->RfBank, rfId, ®RF); + sprintf(msg+strlen(msg), "Bank_%02d_R%02d[0x%02x]:%02X ", + pAdapter->RfBank, rfId, rfId, regRF); + } + else +#endif /* RT6352 */ + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d[0x%02x]:%02X ", rfId, rfId, regRF); + } + } + } + else + { + /* Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + break; + } + } + else + { + /* Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + break; + } + } + else + { /* Write */ + if ((sscanf(this_char, "%d", &(rfId)) == 1) && (sscanf(value, "%lx", &(rfValue)) == 1)) + { + if (rfId <= pAdapter->chipCap.MaxNumOfRfId) + { +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + { + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); + ATE_RF_IO_WRITE8_BY_REG_ID(pAdapter, pAdapter->RfBank, (UCHAR)rfId,(UCHAR) rfValue); + } + else +#endif /* RT6352 */ + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + RT30xxWriteRFRegister(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); + } + + + /* Read it back for showing. */ +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); + else +#endif /* RT6352 */ + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + else +#endif /* RALINK_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command RF shall read/write RF register directly for dubug. */ + /*BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); */ + /*BBP_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)bbpId,(UCHAR) bbpValue); */ +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + { + RT635xReadRFRegister(pAdapter, pAdapter->RfBank, rfId, ®RF); + RT635xWriteRFRegister(pAdapter, pAdapter->RfBank, (UCHAR)rfId, (UCHAR)rfValue); + /* Read it back for showing */ + RT635xReadRFRegister(pAdapter, pAdapter->RfBank, rfId, ®RF); + sprintf(msg+strlen(msg), "Bank_%02d_R%02d[0x%02x]:%02X ", + pAdapter->RfBank, rfId, rfId, regRF); + + } + else +#endif /* RT6352 */ + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + RT30xxWriteRFRegister(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); + /* Read it back for showing */ + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X\n", rfId, rfId, regRF); + } + } + } + else + { /* Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + break; + } + } + else + { /* Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + break; + } + } + } + } + else + bIsPrintAllRF = TRUE; + + if (bIsPrintAllRF) + { + memset(msg, 0x00, 2048); + sprintf(msg, "\n"); + for (rfId = 0; rfId <= maxRFIdx; rfId++) + { +#ifdef RALINK_ATE + /* + In RT2860 ATE mode, we do not load 8051 firmware. + We must access RF registers directly. + For RT2870 ATE mode, ATE_RF_IO_WRITE8(/READ8)_BY_REG_ID are redefined. + */ + if (ATE_ON(pAdapter)) + { +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); + else +#endif /* RT6352 */ + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + else +#endif /* RALINK_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command RF shall read/write RF register directly for dubug. */ +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + { + RT635xReadRFRegister(pAdapter, pAdapter->RfBank, rfId, ®RF); + sprintf(msg+strlen(msg), "Bank_%02d_R%02d[0x%02X]:%02X ", pAdapter->RfBank, rfId, rfId*2, regRF); + if (rfId%4 == 3) + sprintf(msg+strlen(msg), "\n"); + } + else +#endif /* RT6352 */ + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X ", rfId, rfId*2, regRF); + if (rfId%5 == 4) + sprintf(msg+strlen(msg), "\n"); + } + } + } + /* Copy the information into the user buffer */ + +#ifdef LINUX + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + else + { +#ifdef LINUX + /* Copy the information into the user buffer */ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + if (!bFromUI) + { + DBGPRINT(RT_DEBUG_ERROR, ("Dump RF msg[%d]=\n", (UINT32)strlen(msg))); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", msg)); + } + +/* kfree(mpool); */ + os_free_mem(NULL, mpool); + if (!bFromUI) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); + +} +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /*#ifdef DBG */ + +/* + ========================================================================== + Description: + Read / Write E2PROM +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 e2p 0 ==> read E2PROM where Addr=0x0 + 2.) iwpriv ra0 e2p 0=1234 ==> write E2PROM where Addr=0x0, value=1234 + ========================================================================== +*/ +VOID RTMPAPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char; + PSTRING value; + INT j = 0, k = 0; + PSTRING mpool, msg;/*msg[1024]; */ + PSTRING arg; /*arg[255]; */ + PSTRING ptr; + USHORT eepAddr = 0; + UCHAR temp[16]; + STRING temp2[16]; + USHORT eepValue; + BOOLEAN bIsPrintAllE2PROM = FALSE; + +/* mpool = (PSTRING)kmalloc(sizeof(CHAR)*(4096+256+12), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(4096+256+12)); + + if (mpool == NULL) { + return; + } + + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (PSTRING)((ULONG)(msg+4096+3) & (ULONG)~0x03); + + + memset(msg, 0x00, 4096); + memset(arg, 0x00, 256); + + if ( +#ifdef LINUX + (wrq->u.data.length > 1) /* If no parameter, dump all e2p. */ +#endif /* LINUX */ + ) + { + NdisMoveMemory(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + ptr = arg; + sprintf(msg, "\n"); + /*Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + + /* Sanity check */ + if(strlen(this_char) > 4) + break; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto done; /*return; */ + } + + /* E2PROM addr */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + if (eepAddr < 0xFFFF) + { + RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%04X]:0x%04X ", eepAddr , eepValue); + } + else + {/*Invalid parametes, so default printk all bbp */ + break; + } + } + } + else + { /*Write */ + NdisMoveMemory(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + /* Sanity check */ + if((strlen(this_char) > 4) || strlen(temp2) > 8) + break; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto done; /* return; */ + } + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + goto done; /* return; */ + } + + /* MAC Addr */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + /* MAC value */ + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[4-k+j] = temp2[j]; + } + + while(k < 4) + temp2[3-k++]='0'; + temp2[4]='\0'; + + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 2); + eepValue = *temp*256 + temp[1]; + + RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%02X]:%02X ", eepAddr, eepValue); + } + } + } + else + { + bIsPrintAllE2PROM = TRUE; + } + + if (bIsPrintAllE2PROM) + { + sprintf(msg, "\n"); + + /* E2PROM Registers */ + for (eepAddr = 0x00; eepAddr < 0x200; eepAddr += 2) + { + RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%04X]:%04X ", eepAddr , eepValue); + if ((eepAddr & 0x6) == 0x6) + sprintf(msg+strlen(msg), "\n"); + } + } + + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + /* Copy the information into the user buffer */ + + AP_E2PROM_IOCTL_PostCtrl(wrq, msg); + +done: +/* kfree(mpool); */ + os_free_mem(NULL, mpool); + if (wrq->u.data.flags != RT_OID_802_11_HARDWARE_REGISTER) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n")); +} + + +//#define ENHANCED_STAT_DISPLAY // Display PER and PLR statistics + + +/* + ========================================================================== + Description: + Read statistics counter +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 stat 0 ==> Read statistics counter + ========================================================================== +*/ +VOID RTMPIoctlStatistics(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING msg; +#ifdef WSC_AP_SUPPORT + UCHAR idx = 0; +#endif /* WSC_AP_SUPPORT */ + ULONG txCount = 0; + UINT32 rxCount = 0; +#ifdef ENHANCED_STAT_DISPLAY + ULONG per, plr; + INT i; +#endif +#ifdef RTMP_EFUSE_SUPPORT + UINT efusefreenum=0; +#endif /* RTMP_EFUSE_SUPPORT */ + +#ifdef BB_SOC + ULONG txPackets=0, rxPackets=0, txBytes=0, rxBytes=0; + UCHAR index=0; +#endif + + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + os_alloc_mem(pAd, (UCHAR **)&msg, sizeof(CHAR)*(2048)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 1600); + sprintf(msg, "\n"); + +#ifdef RALINK_QA + if(ATE_ON(pAd)) + { + txCount = pAd->ate.TxDoneCount; + rxCount = pAd->ate.U2M + pAd->ate.OtherData + pAd->ate.OtherCount; + } + else +#endif /* RALINK_QA */ + { + txCount = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + rxCount = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + } + + sprintf(msg+strlen(msg), "Current temperature = %d\n", pChipCap->current_temp); +#ifdef DYNAMIC_VGA_SUPPORT + sprintf(msg+strlen(msg), "Average RSSI = %d\n", pChipCap->avg_rssi_all); +#endif /* DYNAMIC_VGA_SUPPORT */ + sprintf(msg+strlen(msg), "Tx success = %ld\n", txCount); +#ifdef ENHANCED_STAT_DISPLAY + per = txCount==0? 0: 1000*(pAd->WlanCounters.RetryCount.u.LowPart+pAd->WlanCounters.FailedCount.u.LowPart)/(pAd->WlanCounters.RetryCount.u.LowPart+pAd->WlanCounters.FailedCount.u.LowPart+txCount); + sprintf(msg+strlen(msg), "Tx retry count = %ld, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.RetryCount.u.LowPart, + per/10, per % 10); + plr = txCount==0? 0: 10000*pAd->WlanCounters.FailedCount.u.LowPart/(pAd->WlanCounters.FailedCount.u.LowPart+txCount); + sprintf(msg+strlen(msg), "Tx fail to Rcv ACK after retry = %ld, PLR=%ld.%02ld%%\n", + (ULONG)pAd->WlanCounters.FailedCount.u.LowPart, plr/100, plr%100); + sprintf(msg+strlen(msg), "Rx success = %ld\n", (ULONG)rxCount); +#ifdef RALINK_QA + if(ATE_ON(pAd)) + per = rxCount==0? 0: 1000*(pAd->WlanCounters.FCSErrorCount.u.LowPart)/(pAd->WlanCounters.FCSErrorCount.u.LowPart+rxCount); + else +#endif /* RALINK_QA */ + per = pAd->WlanCounters.ReceivedFragmentCount.u.LowPart==0? 0: 1000*(pAd->WlanCounters.FCSErrorCount.u.LowPart)/(pAd->WlanCounters.FCSErrorCount.u.LowPart+pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + sprintf(msg+strlen(msg), "Rx with CRC = %ld, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.FCSErrorCount.u.LowPart, per/10, per % 10); + sprintf(msg+strlen(msg), "Rx with PhyErr = %ld\n", + (ULONG)pAd->RalinkCounters.PhyErrCnt); + sprintf(msg+strlen(msg), "Rx with PlcpErr = %ld\n", + (ULONG)pAd->RalinkCounters.PlcpErrCnt); + sprintf(msg+strlen(msg), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(msg+strlen(msg), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + + sprintf(msg+strlen(msg), "False CCA = %ld\n", (ULONG)pAd->RalinkCounters.FalseCCACnt); +#else + sprintf(msg+strlen(msg), "Tx retry count = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.u.LowPart); + sprintf(msg+strlen(msg), "Tx fail to Rcv ACK after retry = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.u.LowPart); + sprintf(msg+strlen(msg), "RTS Success Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.u.LowPart); + sprintf(msg+strlen(msg), "RTS Fail Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.u.LowPart); + + sprintf(msg+strlen(msg), "Rx success = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart); + sprintf(msg+strlen(msg), "Rx with CRC = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.u.LowPart); + sprintf(msg+strlen(msg), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(msg+strlen(msg), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + + sprintf(msg+strlen(msg), "False CCA (one second) = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt); +#endif /* ENHANCED_STAT_DISPLAY */ + +#ifdef RALINK_QA + if(ATE_ON(pAd)) + { + if (pAd->ate.RxAntennaSel == 0) + { + sprintf(msg+strlen(msg), "RSSI-A = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } + else + { + sprintf(msg+strlen(msg), "RSSI = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + } + sprintf(msg+strlen(msg), "Rx U2M = %ld\n", (ULONG)pAd->ate.U2M); + sprintf(msg+strlen(msg), "Rx other Data = %ld\n", (ULONG)pAd->ate.OtherData); + sprintf(msg+strlen(msg), "Rx others(Mgmt+Cntl) = %ld\n", (ULONG)pAd->ate.OtherCount); + } + else +#endif /* RALINK_QA */ + { +#ifdef ENHANCED_STAT_DISPLAY + sprintf(msg+strlen(msg), "RSSI = %ld %ld %ld\n", + (LONG)(pAd->ApCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta), + (LONG)(pAd->ApCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta), + (LONG)(pAd->ApCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); + + /* Display Last Rx Rate and BF SNR of first Associated entry in MAC table */ + if (pAd->MacTab.Size > 0) + { + static char *phyMode[5] = {"CCK", "OFDM", "MM", "GF", "VHT"}; +#ifdef RT65xx + static char *bw[3] = {"20M", "40M", "80M"}; + static char *fec_coding[2] = {"bcc", "ldpc"}; +#endif /* RT65xx */ + + for (i=1; iMacTab.Content[i]); + if (IS_ENTRY_CLIENT(pEntry) && pEntry->Sst==SST_ASSOC) + { + //sprintf(msg+strlen(msg), "sta mac: %02x:%02x:%02x:%02x:%02x:%02x\n", pEntry->wdev->if_addr[0], pEntry->wdev->if_addr[1], pEntry->wdev->if_addr[2], pEntry->wdev->if_addr[3], pEntry->wdev->if_addr[4], pEntry->wdev->if_addr[5]); + UINT32 lastRxRate = pEntry->LastRxRate; + UINT32 lastTxRate = pEntry->HTPhyMode.word; +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + ULONG TxTotalCnt, TxSuccess, TxRetransmit, TxFailCount, TxErrorRatio = 0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + + if (((lastTxRate >> 13) & 0x7) == 0x04) { + sprintf(msg+strlen(msg), "Last TX Rate = MCS%d, %dSS, %s, %s, %cGI, %s%s\n", + lastTxRate & 0x0F, + (((lastTxRate >> 4) & 0x3) + 1), + fec_coding[((lastTxRate >> 6) & 0x1)], + bw[((lastTxRate >> 7) & 0x3)], + ((lastTxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastTxRate >> 13) & 0x7], + ((lastTxRate >> 10) & 0x3)? ", STBC": " "); + + sprintf(msg+strlen(msg), "Last TX PER = %lu\n", TxErrorRatio); + } else { + sprintf(msg+strlen(msg), "Last TX Rate = MCS%d, %s, %s, %cGI, %s%s\n", + lastTxRate & 0x3F, + fec_coding[((lastTxRate >> 6) & 0x1)], + bw[((lastTxRate >> 7) & 0x3)], + ((lastTxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastTxRate >> 13) & 0x7], + ((lastTxRate >> 10) & 0x3)? ", STBC": " "); + } + + if (((lastRxRate >> 13) & 0x7) == 0x04) { + sprintf(msg+strlen(msg), "Last RX Rate = MCS%d, %dSS, %s, %s, %cGI, %s%s\n", + lastRxRate & 0x0F, + (((lastRxRate >> 4) & 0x3) + 1), + fec_coding[((lastRxRate >> 6) & 0x1)], + bw[((lastRxRate >> 7) & 0x3)], + ((lastRxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastRxRate >> 13) & 0x7], + ((lastRxRate >> 10) & 0x3)? ", STBC": " "); + } else { + sprintf(msg+strlen(msg), "Last RX Rate = MCS%d, %s, %s, %cGI, %s%s\n", + lastRxRate & 0x3F, + fec_coding[((lastRxRate >> 6) & 0x1)], + bw[((lastRxRate >> 7) & 0x3)], + ((lastRxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastRxRate >> 13) & 0x7], + ((lastRxRate >> 10) & 0x3)? ", STBC": " "); + } + } + else +#endif /* RT65xx */ + { + sprintf(msg+strlen(msg), "Last TX Rate = MCS%d, %2dM, %cGI, %s%s\n", + lastTxRate & 0x3F, ((lastTxRate>>7) & 0x3)? 40: 20, + ((lastTxRate>>9) & 0x1)? 'S': 'L', + phyMode[(lastTxRate>>13) & 0x3], + ((lastTxRate>>10) & 0x1)? ", STBC": " "); + sprintf(msg+strlen(msg), "Last RX Rate = MCS%d, %2dM, %cGI, %s%s\n", + lastRxRate & 0x3F, ((lastRxRate>>7) & 0x3)? 40: 20, + ((lastRxRate>>9) & 0x1)? 'S': 'L', + phyMode[(lastRxRate>>13) & 0x3], + ((lastRxRate>>10) & 0x1)? ", STBC": " "); + } + + break; + } + } + } +#else + sprintf(msg+strlen(msg), "RSSI-A = %ld\n", (LONG)(pAd->ApCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ApCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ApCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); +#endif /* ENHANCED_STAT_DISPLAY */ + } + +#ifdef WSC_AP_SUPPORT + sprintf(msg+strlen(msg), "WPS Information:\n"); + { +#ifdef BB_SOC + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++){ +// sprintf(msg+strlen(msg), "Enrollee PinCode(ra%d) = %08u\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCode); +// sprintf(msg+strlen(msg), "WPS Query Status(ra%d) = %d\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscStatus); + sprintf(msg+strlen(msg), "WPS Wsc2MinsTimerRunning(ra%d) = %d\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.Wsc2MinsTimerRunning); + } +#else + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + /* display pin code */ + if (pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCodeLen == 8) + sprintf(msg+strlen(msg), "Enrollee PinCode(ra%d) %08u\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCode); + else + sprintf(msg+strlen(msg), "Enrollee PinCode(ra%d) %04u\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCode); + } +#endif + } + +#ifdef APCLI_SUPPORT + sprintf(msg+strlen(msg), "\n"); + if (pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCodeLen == 8) + sprintf(msg+strlen(msg), "Enrollee PinCode(ApCli0) %08u\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + else + sprintf(msg+strlen(msg), "Enrollee PinCode(ApCli0) %04u\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + sprintf(msg+strlen(msg), "Ap Client WPS Profile Count = %d\n", pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.ProfileCnt); + for (idx = 0; idx < pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.ProfileCnt ; idx++) + { + PWSC_CREDENTIAL pCredential = &pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.Profile[idx]; + sprintf(msg+strlen(msg), "Profile[%d]:\n", idx); + sprintf(msg+strlen(msg), "SSID = %s\n", pCredential->SSID.Ssid); + sprintf(msg+strlen(msg), "AuthType = %s\n", WscGetAuthTypeStr(pCredential->AuthType)); + sprintf(msg+strlen(msg), "EncrypType = %s\n", WscGetEncryTypeStr(pCredential->EncrType)); + sprintf(msg+strlen(msg), "KeyIndex = %d\n", pCredential->KeyIndex); + if (pCredential->KeyLength != 0) + { + sprintf(msg+strlen(msg), "Key = %s\n", pCredential->Key); + } + } + sprintf(msg+strlen(msg), "\n"); +#endif /* APCLI_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + +#if /*TCSUPPORT_COMPILE*/ defined(TCSUPPORT_SCHEDULE) + if(pAd->Flags & fRTMP_ADAPTER_RADIO_OFF) + sprintf(msg+strlen(msg), "Enable Wireless LAN = %s\n", "0"); + else + sprintf(msg+strlen(msg), "Enable Wireless LAN = %s\n", "1"); + sprintf(msg+strlen(msg), "\n"); +#endif /*TCSUPPORT_COMPILE*/ + +/* + * Let "iwpriv ra0 stat" can print out Tx/Rx Packet and Byte count. + * Therefore, we can parse them out in cfg_manager. --Trey */ +#ifdef BB_SOC + for (index = 0; index < pAd->ApCfg.BssidNum; index++){ + rxPackets += (ULONG)pAd->ApCfg.MBSSID[index].RxCount; + txPackets += (ULONG)pAd->ApCfg.MBSSID[index].TxCount; + rxBytes += (ULONG)pAd->ApCfg.MBSSID[index].ReceivedByteCount; + txBytes += (ULONG)pAd->ApCfg.MBSSID[index].TransmittedByteCount; + } + sprintf(msg+strlen(msg), "Packets Received = %lu\n", rxPackets); + sprintf(msg+strlen(msg), "Packets Sent = %lu\n", txPackets); + sprintf(msg+strlen(msg), "Bytes Received = %lu\n", rxBytes); + sprintf(msg+strlen(msg), "Bytes Sent = %lu\n", txBytes); + sprintf(msg+strlen(msg), "\n"); +#endif + +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse == TRUE) + { + eFuseGetFreeBlockCount(pAd, &efusefreenum); + sprintf(msg+strlen(msg), "efuseFreeNumber = %d\n", efusefreenum); + } +#endif /* RTMP_EFUSE_SUPPORT */ +#ifdef CONFIG_HOTSPOT + { + PHOTSPOT_CTRL pHSCtrl; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[apidx].GASCtrl; +#ifdef CONFIG_DOT11V_WNM + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[apidx].WNMCtrl; +#endif + pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; + + sprintf(msg+strlen(msg), "\n"); + sprintf(msg+strlen(msg), "hotspot enable = %d\n", pHSCtrl->HotSpotEnable); + sprintf(msg+strlen(msg), "daemon ready = %d\n", pHSCtrl->HSDaemonReady); + sprintf(msg+strlen(msg), "hotspot DGAFDisable = %d\n", pHSCtrl->DGAFDisable); + sprintf(msg+strlen(msg), "hotspot L2Filter = %d\n", pHSCtrl->L2Filter); + sprintf(msg+strlen(msg), "hotspot ICMPv4Deny = %d\n", pHSCtrl->ICMPv4Deny); + sprintf(msg+strlen(msg), "hotspot QosMapEnable = %d\n", pHSCtrl->QosMapEnable); + sprintf(msg+strlen(msg), "hotspot QloadEnable = %d\n", pAd->phy_ctrl.FlgQloadEnable); + +#ifdef CONFIG_DOT11V_WNM + sprintf(msg+strlen(msg), "proxy arp enable = %d\n", pWNMCtrl->ProxyARPEnable); + sprintf(msg+strlen(msg), "WNMNotify enable = %d\n", pWNMCtrl->WNMNotifyEnable); +#endif + sprintf(msg+strlen(msg), "hotspot OSEN enable = %d\n", pHSCtrl->bASANEnable); + sprintf(msg+strlen(msg), "GAS come back delay = %d\n", pGASCtrl->cb_delay); + sprintf(msg+strlen(msg), "\n"); + } +#endif /* CONFIG_HOTSPOT */ + + + /* Copy the information into the user buffer */ + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + os_free_mem(NULL, msg); + +#if defined(TXBF_SUPPORT) && defined(ENHANCED_STAT_DISPLAY) +#ifdef DBG_CTRL_SUPPORT + /* Debug code to display BF statistics */ + if (pAd->CommonCfg.DebugFlags & DBF_SHOW_BF_STATS) + { + for (i=0; iMacTab.Content[i]); + COUNTER_TXBF *pCnt; + ULONG totalNBF, totalEBF, totalIBF, totalTx, totalRetry, totalSuccess; + + if (!IS_ENTRY_CLIENT(pEntry) || pEntry->Sst!=SST_ASSOC) + continue; + + pCnt = &pEntry->TxBFCounters; + + totalNBF = pCnt->TxSuccessCount + pCnt->TxFailCount; + totalEBF = pCnt->ETxSuccessCount + pCnt->ETxFailCount; + totalIBF = pCnt->ITxSuccessCount + pCnt->ITxFailCount; + + totalTx = totalNBF + totalEBF + totalIBF; + totalRetry = pCnt->TxRetryCount + pCnt->ETxRetryCount + pCnt->ITxRetryCount; + totalSuccess = pCnt->TxSuccessCount + pCnt->ETxSuccessCount + pCnt->ITxSuccessCount; + + DBGPRINT(RT_DEBUG_OFF, ("MacTable[%d] Success Retry/PER Fail/PLR\n", i) ); + if (totalTx==0) { + DBGPRINT(RT_DEBUG_OFF, (" Total = 0\n") ); + continue; + } + + if (totalNBF!=0) { + DBGPRINT(RT_DEBUG_OFF, (" NonBF (%3lu%%): %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + 100*totalNBF/totalTx, pCnt->TxSuccessCount, + pCnt->TxRetryCount, 100*pCnt->TxRetryCount/(pCnt->TxSuccessCount+pCnt->TxRetryCount), + pCnt->TxFailCount, 100*pCnt->TxFailCount/totalNBF) ); + } + + if (totalEBF!=0) { + DBGPRINT(RT_DEBUG_OFF, (" ETxBF (%3lu%%): %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + 100*totalEBF/totalTx, pCnt->ETxSuccessCount, + pCnt->ETxRetryCount, 100*pCnt->ETxRetryCount/(pCnt->ETxSuccessCount+pCnt->ETxRetryCount), + pCnt->ETxFailCount, 100*pCnt->ETxFailCount/totalEBF) ); + } + + if (totalIBF!=0) { + DBGPRINT(RT_DEBUG_OFF, (" ITxBF (%3lu%%): %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + 100*totalIBF/totalTx, pCnt->ITxSuccessCount, + pCnt->ITxRetryCount, 100*pCnt->ITxRetryCount/(pCnt->ITxSuccessCount+pCnt->ITxRetryCount), + pCnt->ITxFailCount, 100*pCnt->ITxFailCount/totalIBF) ); + } + + DBGPRINT(RT_DEBUG_OFF, (" Total %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + totalSuccess, totalRetry, 100*totalRetry/(totalSuccess + totalRetry), + pCnt->TxFailCount+pCnt->ETxFailCount+pCnt->ITxFailCount, + 100*(pCnt->TxFailCount+pCnt->ETxFailCount+pCnt->ITxFailCount)/totalTx) ); + } + } +#endif /* DBG_CTRL_SUPPORT */ +#endif /* defined(TXBF_SUPPORT) && defined(ENHANCED_STAT_DISPLAY) */ + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlStatistics\n")); +} + + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + Get Block ACK Table + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 get_ba_table + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +VOID RTMPIoctlQueryBaTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + /*char *msg; */ + UCHAR TotalEntry, i, j, index; + QUERYBA_TABLE *BAT; + + BAT = vmalloc(sizeof(QUERYBA_TABLE)); + + if (BAT == NULL) + return; + + RTMPZeroMemory(BAT, sizeof(QUERYBA_TABLE)); + + TotalEntry = pAd->MacTab.Size; + index = 0; + for (i=0; ((i < MAX_LEN_OF_MAC_TABLE) && (TotalEntry > 0)); i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC) && (pEntry->TXBAbitmap)) + { + NdisMoveMemory(BAT->BAOriEntry[index].MACAddr, pEntry->Addr, 6); + for (j=0;j<8;j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + BAT->BAOriEntry[index].BufSize[j] = pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]].BAWinSize; + else + BAT->BAOriEntry[index].BufSize[j] = 0; + } + + TotalEntry--; + index++; + BAT->OriNum++; + } + } + + TotalEntry = pAd->MacTab.Size; + index = 0; + for (i=0; ((i < MAX_LEN_OF_MAC_TABLE) && (TotalEntry > 0)); i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC) && (pEntry->RXBAbitmap)) + { + NdisMoveMemory(BAT->BARecEntry[index].MACAddr, pEntry->Addr, 6); + BAT->BARecEntry[index].BaBitmap = (UCHAR)pEntry->RXBAbitmap; + for (j = 0; j < 8; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + BAT->BARecEntry[index].BufSize[j] = pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]].BAWinSize; + else + BAT->BARecEntry[index].BufSize[j] = 0; + } + + TotalEntry--; + index++; + BAT->RecNum++; + } + } + + wrq->u.data.length = sizeof(QUERYBA_TABLE); + + if (copy_to_user(wrq->u.data.pointer, BAT, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + vfree(BAT); + +} +#endif /* DOT11_N_SUPPORT */ + + +#ifdef APCLI_SUPPORT +INT Set_ApCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj; + UCHAR ifIndex; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + Enable = simple_strtol(arg, 0, 16); + + pAd->ApCfg.ApCliTab[ifIndex].Enable = (Enable > 0) ? TRUE : FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Enable_Proc::(enable = %d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].Enable)); +#ifdef APCLI_CONNECTION_TRIAL + if (pAd->ApCfg.ApCliTab[ifIndex].TrialCh == 0) +#endif /* APCLI_CONNECTION_TRIAL */ + ApCliIfDown(pAd); + + return TRUE; +} + + +INT Set_ApCli_Ssid_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + /*UCHAR keyMaterial[40]; */ + UCHAR PskKey[100]; + APCLI_STRUCT *apcli_entry; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + + /* bring apcli interface down first */ + apcliEn = apcli_entry->Enable; +#ifdef APCLI_CONNECTION_TRIAL + if (pAd->ApCfg.ApCliTab[ifIndex].TrialCh == 0) + { +#endif /* APCLI_CONNECTION_TRIAL */ + if(apcliEn == TRUE ) + { + apcli_entry->Enable = FALSE; + ApCliIfDown(pAd); + } +#ifdef APCLI_CONNECTION_TRIAL + } +#endif /* APCLI_CONNECTION_TRIAL */ + + apcli_entry->bPeerExist = FALSE; + NdisZeroMemory(apcli_entry->CfgSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(apcli_entry->CfgSsid, arg, strlen(arg)); + apcli_entry->CfgSsidLen = (UCHAR)strlen(arg); + success = TRUE; + + /* reset BSSID */ + NdisZeroMemory(apcli_entry->CfgApCliBssid, MAC_ADDR_LEN); + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + apcli_entry->PSKLen > 0) + { + NdisZeroMemory(PskKey, 100); + NdisMoveMemory(PskKey, apcli_entry->PSK, apcli_entry->PSKLen); + + RT_CfgSetWPAPSKKey(pAd, (PSTRING)PskKey, + apcli_entry->PSKLen, + (PUCHAR)apcli_entry->CfgSsid, + apcli_entry->CfgSsidLen, + apcli_entry->PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", + ifIndex, apcli_entry->CfgSsidLen, apcli_entry->CfgSsid)); + + apcli_entry->Enable = apcliEn; + } + else + success = FALSE; + + return success; +} + + +INT Set_ApCli_Bssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + PSTRING value; + UCHAR ifIndex; + BOOLEAN apcliEn; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[ifIndex].Enable = FALSE; +#ifdef APCLI_CONNECTION_TRIAL + if (pAd->ApCfg.ApCliTab[ifIndex].TrialCh == 0) +#endif /* APCLI_CONNECTION_TRIAL */ + ApCliIfDown(pAd); + } + + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, MAC_ADDR_LEN); + + if(strlen(arg) == 17) /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":"), i++) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /* Invalid */ + + AtoH(value, &pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[i], 1); + } + + if(i != 6) + return FALSE; /* Invalid */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ApCli_Bssid_Proc (%2X:%2X:%2X:%2X:%2X:%2X)\n", + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[0], + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[1], + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[2], + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[3], + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[4], + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid[5])); + + pAd->ApCfg.ApCliTab[ifIndex].Enable = apcliEn; + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set ApCli-IF Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_AuthMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + struct wifi_dev *wdev; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + wdev->bWpaAutoMode = FALSE; + + if (rtstrcasecmp(arg, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (rtstrcasecmp(arg, "WPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + else if (rtstrcasecmp(arg, "WPAPSKWPA2PSK") == TRUE) + { + wdev->AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + wdev->bWpaAutoMode = TRUE; + } +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + else if (rtstrcasecmp(arg, "WPA") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if (rtstrcasecmp(arg, "WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2; +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT */ + + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + + wdev->DefaultKeyId = 0; + + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 1; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_AuthMode_Proc::(AuthMode=%d)\n", ifIndex, wdev->AuthMode)); + return TRUE; +} + + +/* + ========================================================================== + Description: + Set ApCli-IF Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + wdev->WepStatus = Ndis802_11WEPDisabled; + wdev->bEncryptAutoMode = FALSE; + + if (rtstrcasecmp(arg, "WEP") == TRUE) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11WEPEnabled; + } + else if (rtstrcasecmp(arg, "TKIP") == TRUE) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((rtstrcasecmp(arg, "AES") == TRUE)) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11Encryption3Enabled; + } + else if ((rtstrcasecmp(arg, "TKIPAES") == TRUE)) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + wdev->WepStatus = Ndis802_11Encryption4Enabled; + wdev->bEncryptAutoMode = TRUE; + } + } + else + { + wdev->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = wdev->WepStatus; + pApCliEntry->GroupCipher = wdev->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (wdev->WepStatus >= Ndis802_11Encryption2Enabled) + wdev->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_EncrypType_Proc::(EncrypType=%d)\n", ifIndex, wdev->WepStatus)); + + return TRUE; +} + + + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG KeyIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + wdev->DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", pObj->ioctl_if, wdev->DefaultKeyId)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA PSK key for ApCli link + + Arguments: + pAdapter Pointer to our adapter + arg WPA pre-shared key string + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ifIndex; + POS_COOKIE pObj; + PAPCLI_STRUCT pApCliEntry = NULL; + INT retval; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ApCli_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); + + retval = RT_CfgSetWPAPSKKey(pAd, arg, strlen(arg), (PUCHAR)pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, pApCliEntry->PMK); + if (retval == FALSE) + return FALSE; + + NdisZeroMemory(pApCliEntry->PSK, sizeof(pApCliEntry->PSK)); + NdisMoveMemory(pApCliEntry->PSK, arg, strlen(arg)); + pApCliEntry->PSKLen = strlen(arg); +#ifdef WSC_AP_SUPPORT + pApCliEntry->WscControl.WpaPskLen = pApCliEntry->PSKLen; + NdisZeroMemory(pApCliEntry->WscControl.WpaPsk, sizeof(pApCliEntry->WscControl.WpaPsk)); + NdisMoveMemory(pApCliEntry->WscControl.WpaPsk, pApCliEntry->PSK, pApCliEntry->PSKLen); +#endif /* WSC_AP_SUPPORT */ + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WEP KEY1 for ApCli-IF + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_Key1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR ifIndex; + INT retVal; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + retVal = RT_CfgSetWepKey(pAd, arg, &pApCliEntry->SharedKey[0], 0); + if(retVal == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_Key1_Proc::(Key1=%s) success!\n", ifIndex, arg)); + + return retVal; + +} + + +/* + ========================================================================== + Description: + Set WEP KEY2 for ApCli-IF + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_Key2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR ifIndex; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + retVal = RT_CfgSetWepKey(pAd, arg, &pApCliEntry->SharedKey[1], 1); + if(retVal == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_Key2_Proc::(Key2=%s) success!\n", ifIndex, arg)); + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY3 for ApCli-IF + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_Key3_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR ifIndex; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + retVal = RT_CfgSetWepKey(pAd, arg, &pApCliEntry->SharedKey[2], 2); + if(retVal == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_Key3_Proc::(Key3=%s) success!\n", ifIndex, arg)); + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY4 for ApCli-IF + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_Key4_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR ifIndex; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + retVal = RT_CfgSetWepKey(pAd, arg, &pApCliEntry->SharedKey[3], 3); + if(retVal == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_Key4_Proc::(Key4=%s) success!\n", ifIndex, arg)); + + return retVal; +} + +INT Set_ApCli_TxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + + wdev->DesiredTransmitSetting.field.FixedTxMode = RT_CfgSetFixedTxPhyMode(arg); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMode_Proc = %d\n", + pObj->ioctl_if, wdev->DesiredTransmitSetting.field.FixedTxMode)); + + return TRUE; +} + +INT Set_ApCli_TxMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + + wdev->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(arg, &wdev->bAutoTxRateSwitch); + + if (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = AUTO\n", pObj->ioctl_if)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = %d\n", + pObj->ioctl_if, wdev->DesiredTransmitSetting.field.MCS)); + } + + return TRUE; +} + +#ifdef APCLI_CONNECTION_TRIAL +INT Set_ApCli_Trial_Ch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->TrialCh = simple_strtol(arg, 0, 10); + + if (pApCliEntry->TrialCh) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) pApCliEntry->TrialCh = %d\n", ifIndex, pApCliEntry->TrialCh)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) pApCliEntry->TrialCh = %d\n", ifIndex, pApCliEntry->TrialCh)); + } + + return TRUE; +} +#endif /* APCLI_CONNECTION_TRIAL */ + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +INT Set_ApCli_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + if ( simple_strtol(arg, 0, 10) == 0) + pApCliEntry->WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + else if ( simple_strtol(arg, 0, 10) == 1) + pApCliEntry->WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + else if ( simple_strtol(arg, 0, 10) == 2) + pApCliEntry->WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; + else + pApCliEntry->WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ApCli_Wpa_Support::(WpaSupplicantUP=%d)\n", pApCliEntry->WpaSupplicantUP)); + + return TRUE; +} + + +INT Set_ApCli_IEEE8021X_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG ieee8021x; + POS_COOKIE pObj; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + ieee8021x = simple_strtol(arg, 0, 10); + + if (ieee8021x == 1) + pApCliEntry->wdev.IEEE8021X = TRUE; + else if (ieee8021x == 0) + pApCliEntry->wdev.IEEE8021X = FALSE; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_ApCli_IEEE8021X_Proc::(IEEE8021X=%d)\n", pObj->ioctl_if, pApCliEntry->wdev.IEEE8021X)); + + return TRUE; +} +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +INT Set_ReptMode_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR Enable; + UINT32 MacReg; + + Enable = simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAd, MAC_ADDR_EXT_EN, &MacReg); + if (Enable) + { + MacReg |= 0x1; + pAd->ApCfg.bMACRepeaterEn = TRUE; + DBGPRINT(RT_DEBUG_TRACE, (" Repeater Mode (ON)\n")); + } + else + { + MacReg &= (~0x1); + pAd->ApCfg.bMACRepeaterEn = FALSE; + DBGPRINT(RT_DEBUG_TRACE, (" Repeater Mode (OFF)\n")); + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_EXT_EN, MacReg); + + DBGPRINT(RT_DEBUG_WARN, (" MACRepeaterEn = %d \n", pAd->ApCfg.bMACRepeaterEn)); + + return TRUE; +} +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef APCLI_AUTO_CONNECT_SUPPORT +/* + ========================================================================== + Description: + Trigger Apcli Auto connect to find the missed AP. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_AutoConnect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj= (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAP_ADMIN_CONFIG pApCfg; + long scan_mode = simple_strtol(arg, 0, 10); + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + pApCfg = &pAd->ApCfg; + ifIndex = pObj->ioctl_if; + + if (scan_mode == 0) + { + pApCfg->ApCliTab[ifIndex].AutoConnectFlag = FALSE; + pApCfg->ApCliAutoConnectRunning = FALSE; + return TRUE; + } + + pApCfg->ApCliTab[ifIndex].AutoConnectFlag = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_AutoConnect_Proc::(Len=%d,Ssid=%s)\n", + ifIndex, pApCfg->ApCliTab[ifIndex].CfgSsidLen, pApCfg->ApCliTab[ifIndex].CfgSsid)); + +#ifdef AP_PARTIAL_SCAN_SUPPORT +#define AUTO_SCAN_MODE_FULL 1 +#define AUTO_SCAN_MODE_PARTIAL 2 + + if (scan_mode == AUTO_SCAN_MODE_PARTIAL) + { + pApCfg->bPartialScanning = TRUE; + } + else +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + { + /* AUTO_SCAN_MODE_FULL */ + ApCliAutoConnectStart(pAd, ifIndex); + } + + return TRUE; +} + +INT Set_ApCli_SiteSurveyPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj= (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + UINT32 SiteSurveyPeriod; + + ifIndex = pObj->ioctl_if; + if ((pObj->ioctl_if_type != INT_APCLI) || + (ifIndex >= MAX_APCLI_NUM)) + return FALSE; + + SiteSurveyPeriod = simple_strtol(arg, 0, 10); + pAd->ApCfg.ApCliTab[ifIndex].ApCliSiteSurveyPeriod = SiteSurveyPeriod; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) %s::(SiteSurveyPeriod = %d)\n", + ifIndex, __func__, SiteSurveyPeriod)); + + return TRUE; +} +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT +INT Set_AP_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + PWSC_CTRL pWscControl = &pAd->ApCfg.ApCliTab[ifIndex].WscControl; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + NdisZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + + if( (strlen(arg) > 0) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + NdisMoveMemory(pWscControl->WscSsid.Ssid, arg, strlen(arg)); + pWscControl->WscSsid.SsidLength = strlen(arg); + + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, arg, strlen(arg)); + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen = (UCHAR)strlen(arg); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscSsid_Proc:: (Select SsidLen=%d,Ssid=%s)\n", + pWscControl->WscSsid.SsidLength, pWscControl->WscSsid.Ssid)); + } + else + return FALSE; /*Invalid argument */ + + return TRUE; + +} +#endif /* WSC_AP_SUPPORT */ + +#ifdef APCLI_CERT_SUPPORT +INT Set_ApCli_Cert_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj; + UCHAR ifIndex; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + Enable = simple_strtol(arg, 0, 16); + + pAd->bApCliCertTest = (Enable > 0) ? TRUE : FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Cert_Enable_Proc::(enable = %d)\n", ifIndex, pAd->bApCliCertTest)); + + return TRUE; +} + +INT Set_ApCli_WMM_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + Enable = simple_strtol(arg, 0, 16); + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pApCliEntry->wdev.bWmmCapable = (Enable > 0) ? TRUE : FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_WMM_Enable_Proc::(enable = %d)\n", ifIndex, pApCliEntry->wdev.bWmmCapable)); + + return TRUE; +} +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT +#ifdef CON_WPS +static INT WscPushConcurrentPBCAction( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bIsApCli) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT idx; + + if (bIsApCli) + pWscControl->WscConfMode = WSC_ENROLLEE; + else + pWscControl->WscConfMode = WSC_REGISTRAR; + + WscInit(pAd, bIsApCli, apidx); + pWscControl->WscMode = WSC_PBC_MODE; + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + + WscStop(pAd, bIsApCli, pWscControl); + pWscControl->RegData.ReComputePke = 1; + WscInitRegistrarPair(pAd, pWscControl, apidx); + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + + pWscControl->bWscAutoTigeer = FALSE; + + if (bIsApCli) + { + pAd->ApCfg.ApCliTab[apidx].Enable = FALSE; + ApCliIfDown(pAd); + + pWscControl->WscSsid.SsidLength = 0; + NdisZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + pWscControl->WscPBCBssCount = 0; + /* WPS - SW PBC */ + WscPushPBCAction(pAd, pWscControl); + } + else + { + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, TRUE, DEV_PASS_ID_PBC, + pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, TRUE, DEV_PASS_ID_PBC, + pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + pWscControl->bWscTrigger = TRUE; + + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscClearPeerList(&pWscControl->WscPeerList); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + + } + + return TRUE; +} +#endif /* CON_WPS */ + +INT Set_AP_WscConfMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ConfModeIdx; + /*INT IsAPConfigured; */ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + BOOLEAN bFromApCli = FALSE; + PWSC_CTRL pWscControl; + + ConfModeIdx = simple_strtol(arg, 0, 10); + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef CON_WPS + if (ConfModeIdx == WSC_ENROLLEE_REGISTRAR) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is using concurrent WPS now.\n")); + + pAd->conWscStatus = CON_WPS_STATUS_APCLI_RUNNING; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + WscPushConcurrentPBCAction(pAd, pWscControl, TRUE); + + pAd->conWscStatus |= CON_WPS_STATUS_AP_RUNNING; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + WscPushConcurrentPBCAction(pAd, pWscControl, FALSE); + + return TRUE; + } +#endif /* CON_WPS */ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfMode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfMode_Proc:: This command is from ra interface now.\n", apidx)); + } + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + if((ConfModeIdx & WSC_REGISTRAR)) + Set_HiddenWps_Role(&pAd->ApCfg.ApCliTab[apidx].SmartMeshCfg, HIDDEN_WPS_ROLE_REGISTRAR); + else + Set_HiddenWps_Role(&pAd->ApCfg.ApCliTab[apidx].SmartMeshCfg, HIDDEN_WPS_ROLE_ENROLLEE); + } + else +#endif /* APCLI_SUPPORT */ + { + if((ConfModeIdx & WSC_ENROLLEE)) + Set_HiddenWps_Role(&pAd->ApCfg.MBSSID[apidx].SmartMeshCfg, HIDDEN_WPS_ROLE_ENROLLEE); + else + Set_HiddenWps_Role(&pAd->ApCfg.MBSSID[apidx].SmartMeshCfg, HIDDEN_WPS_ROLE_REGISTRAR); + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + pWscControl->bWscTrigger = FALSE; + if ((ConfModeIdx & WSC_ENROLLEE_PROXY_REGISTRAR) == WSC_DISABLE) + { + pWscControl->WscConfMode = WSC_DISABLE; + pWscControl->WscStatus = STATUS_WSC_NOTUSED; + if (bFromApCli) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfMode_Proc:: WPS is disabled.\n", apidx)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfMode_Proc:: WPS is disabled.\n", apidx)); + /* Clear WPS IE in Beacon and ProbeResp */ + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen = 0; + APUpdateBeaconFrame(pAd, apidx); + } + } + else + { +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + if (ConfModeIdx == WSC_ENROLLEE) + pWscControl->WscConfMode = WSC_ENROLLEE; + else + pWscControl->WscConfMode = WSC_REGISTRAR; + + WscInit(pAd, TRUE, apidx); + } + else +#endif /* APCLI_SUPPORT */ + { + pWscControl->WscConfMode = (ConfModeIdx & WSC_ENROLLEE_PROXY_REGISTRAR); + WscInit(pAd, FALSE, apidx); + } + pWscControl->WscStatus = STATUS_WSC_IDLE; + } + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + memcpy(mac_addr, &pAd->ApCfg.ApCliTab[apidx].wdev.if_addr[0], MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, &pAd->ApCfg.MBSSID[apidx].wdev.bssid[0], MAC_ADDR_LEN); + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscConfMode_Proc::(WscConfMode(0~7)=%d)\n", + PRINT_MAC(mac_addr), pWscControl->WscConfMode)); + return TRUE; +} + +INT Set_AP_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR IsAPConfigured = 0; + INT IsSelectedRegistrar; + USHORT WscMode; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfStatus_Proc:: Ap Client doesn't need this command.\n", apidx)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bWpsEnable == FALSE) && + (pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2)) + { + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen = 0; + return FALSE; + } +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + IsAPConfigured = (UCHAR)simple_strtol(arg, 0, 10); + IsSelectedRegistrar = pAd->ApCfg.MBSSID[apidx].WscControl.WscSelReg; + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscMode == 1) + WscMode = DEV_PASS_ID_PIN; + else + WscMode = DEV_PASS_ID_PBC; + + if ((IsAPConfigured > 0) && (IsAPConfigured <= 2)) + { + pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus = IsAPConfigured; + /* Change SC State of WPS IE in Beacon and ProbeResp */ + WscBuildBeaconIE(pAd, IsAPConfigured, IsSelectedRegistrar, WscMode, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, IsSelectedRegistrar, WscMode, 0, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfStatus_Proc:: Set failed!!(WscConfStatus=%s), WscConfStatus is 1 or 2 \n", apidx, arg)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfStatus_Proc:: WscConfStatus is not changed (%d) \n", apidx, pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus)); + return FALSE; /*Invalid argument */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscConfStatus_Proc::(WscConfStatus=%d)\n", + PRINT_MAC(pAd->ApCfg.MBSSID[apidx].wdev.bssid), + pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus)); + + return TRUE; +} + +INT Set_AP_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT WscMode; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + PWSC_CTRL pWscControl; + BOOLEAN bFromApCli = FALSE; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscMode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscMode_Proc:: This command is from ra interface now.\n", apidx)); + } + + WscMode = simple_strtol(arg, 0, 10); + + if ((WscMode > 0) && (WscMode <= 2)) + { + pWscControl->WscMode = WscMode; + if (WscMode == WSC_PBC_MODE) + { + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc:: Set failed!!(Set_WscMode_Proc=%s), WscConfStatus is 1 or 2 \n", arg)); + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc:: WscMode is not changed (%d) \n", pWscControl->WscMode)); + return FALSE; /*Invalid argument */ + } + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + memcpy(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscMode_Proc::(WscMode=%d)\n", + PRINT_MAC(mac_addr), pWscControl->WscMode)); + + return TRUE; +} + +INT Set_WscStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscStatus_Proc::(WscStatus=%d)\n", apidx, pAd->ApCfg.MBSSID[apidx].WscControl.WscStatus)); + return TRUE; +} + +#define WSC_GET_CONF_MODE_EAP 1 +#define WSC_GET_CONF_MODE_UPNP 2 +INT Set_AP_WscGetConf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT WscMode, wscGetConfMode = 0; + INT IsAPConfigured; + PWSC_CTRL pWscControl; + /*PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo;*/ + INT idx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + BOOLEAN bFromApCli = FALSE; +#ifdef APCLI_SUPPORT + BOOLEAN apcliEn = FALSE; +#endif /* APCLI_SUPPORT */ +#ifdef WSC_V2_SUPPORT + PWSC_V2_INFO pWscV2Info = NULL; +#endif /* WSC_V2_SUPPORT */ +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + if (pAd->flg_apcli_init == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_AP_WscGetConf_Proc:: ApCli is disabled.\n", apidx)); + return FALSE; + } + bFromApCli = TRUE; + apidx &= (~MIN_NET_DEVICE_FOR_APCLI); + apcliEn = pAd->ApCfg.ApCliTab[apidx].Enable; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_AP_WscGetConf_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AP_WscGetConf_Proc:: This command is from ra interface now.\n", apidx)); + } + pWscControl->bFromApCli = bFromApCli; + + NdisZeroMemory(mac_addr, MAC_ADDR_LEN); + +#ifdef WSC_V2_SUPPORT + pWscV2Info = &pWscControl->WscV2Info; +#endif /* WSC_V2_SUPPORT */ + wscGetConfMode = simple_strtol(arg, 0, 10); + + IsAPConfigured = pWscControl->WscConfStatus; + /*pWscUPnPNodeInfo = &pWscControl->WscUPnPNodeInfo;*/ + + if ((pWscControl->WscConfMode == WSC_DISABLE) +#ifdef WSC_V2_SUPPORT + || ((pWscV2Info->bWpsEnable == FALSE) && (pWscV2Info->bEnableWpsV2)) +#endif /* WSC_V2_SUPPORT */ + ) + { + pWscControl->bWscTrigger = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGetConf_Proc: WPS is disabled.\n")); + return FALSE; + } + + WscStop(pAd, bFromApCli, pWscControl); + + /* trigger wsc re-generate public key */ + pWscControl->RegData.ReComputePke = 1; + + if (pWscControl->WscMode == 1) + WscMode = DEV_PASS_ID_PIN; + else + WscMode = DEV_PASS_ID_PBC; + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + if(pAd->ApCfg.ApCliTab[apidx].SmartMeshCfg.bSupportHiddenWPS) + { + pWscControl->bRunningHiddenWPS = TRUE; + Set_HiddenWps_State(&pAd->ApCfg.ApCliTab[apidx].SmartMeshCfg, HIDDEN_WPS_STATE_RUNNING); + } + } + else +#endif /* APCLI_SUPPORT */ + { + if(pAd->ApCfg.MBSSID[apidx].SmartMeshCfg.bSupportHiddenWPS) + pWscControl->bRunningHiddenWPS = TRUE; + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + WscInitRegistrarPair(pAd, pWscControl, apidx); + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + /* bring apcli interface down first */ + pAd->ApCfg.ApCliTab[apidx].Enable = FALSE; + ApCliIfDown(pAd); + pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn; + + if (WscMode == DEV_PASS_ID_PIN) + { + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, + 6); + + NdisMoveMemory(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + } + else + { + pWscControl->WscSsid.SsidLength = 0; + NdisZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + pWscControl->WscPBCBssCount = 0; + /* WPS - SW PBC */ + WscPushPBCAction(pAd, pWscControl); + } + } + else +#endif /* APCLI_SUPPORT */ + { + WscBuildBeaconIE(pAd, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + NdisMoveMemory(mac_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + } + +#ifdef APCLI_SUPPORT + if (bFromApCli && (WscMode == DEV_PASS_ID_PBC)) + ; + else +#endif /* APCLI_SUPPORT */ + { + /* 2mins time-out timer */ + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + pWscControl->bWscTrigger = TRUE; + } + pWscControl->bWscAutoTigeer = FALSE; + + if (!bFromApCli) + { + if (WscMode == DEV_PASS_ID_PIN) + { + WscAssignEntryMAC(pAd, pWscControl); + WscSendUPnPConfReqMsg(pAd, pWscControl->EntryIfIdx, + (PUCHAR)pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx].Ssid, + pAd->ApCfg.MBSSID[apidx].wdev.bssid, 3, 0, AP_MODE); + } + else + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscClearPeerList(&pWscControl->WscPeerList); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + } + +#ifdef WSC_LED_SUPPORT + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + +#ifdef SMART_MESH_MONITOR + if(pWscControl->WscMode == WSC_PBC_MODE) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.wps_pbc_stat.type = NSMPIF_DRVEVNT_WPS_PBC_STAT; + drvevnt.data.wps_pbc_stat.stat = NSMP_WPS_PBC_STAT_BEGIN; + drvevnt.data.wps_pbc_stat.reason = 0; + drvevnt.data.wps_pbc_stat.channel = pAd->CommonCfg.Channel; +#ifdef SMART_MESH + if(pWscControl->bWscPBCAddrMode) + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->WscPBCAddr); + else +#endif /* SMART_MESH */ + NdisZeroMemory(drvevnt.data.wps_pbc_stat.sta_mac,MAC_ADDR_LEN); + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_WPS_PBC_STAT, + NULL, (PUCHAR)&drvevnt.data.wps_pbc_stat, sizeof(drvevnt.data.wps_pbc_stat)); + DBGPRINT(RT_DEBUG_OFF, + ("Send Custom Wireless Event. (NSMPIF_DRVEVNT_WPS_PBC_STAT:NSMP_WPS_PBC_STAT_BEGIN)\n")); + } +#endif /* SMART_MESH_MONITOR */ + + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscGetConf_Proc trigger WSC state machine, wscGetConfMode=%d\n", + PRINT_MAC(mac_addr), wscGetConfMode)); + + return TRUE; +} + +INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT PinCode = 0, PinCodeLen = 0; + BOOLEAN validatePin, bFromApCli = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + PWSC_CTRL pWscControl; +#define IsZero(c) ('0' == (c) ? TRUE:FALSE) + PinCode = simple_strtol(arg, 0, 10); /* When PinCode is 03571361, return value is 3571361. */ + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscPinCode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscPinCode_Proc:: This command is from ra interface now.\n", apidx)); + } + + PinCodeLen = strlen(arg); + /* It's mean the start with '0xxx' */ + if (PinCode < 1000) + PinCodeLen = 4; + + if (PinCodeLen == 4) + validatePin = TRUE; + else + validatePin = ValidateChecksum(PinCode); + + if ( validatePin ) + { + if (pWscControl->WscRejectSamePinFromEnrollee && + (PinCode == pWscControl->WscLastPinFromEnrollee)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PIN authentication or communication error occurs!!\n" + "Registrar does NOT accept the same PIN again!(PIN:%s)\n", arg)); + return FALSE; + } + else + { + pWscControl->WscPinCode = PinCode; + pWscControl->WscLastPinFromEnrollee = pWscControl->WscPinCode; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + /* PIN Code */ + if (PinCodeLen == 4) + { + pWscControl->WscPinCodeLen = 4; + pWscControl->RegData.PinCodeLen = 4; + NdisMoveMemory(pWscControl->RegData.PIN, arg, 4); + } + else + { + pWscControl->WscPinCodeLen = 8; + + if (IsZero(*arg)) + { + pWscControl->RegData.PinCodeLen = 8; + NdisMoveMemory(pWscControl->RegData.PIN, arg, 8); + } + else + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(Set_WscPinCode_Proc=%s), PinCode Checksum invalid \n", arg)); + return FALSE; /*Invalid argument */ + } + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + memcpy(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscPinCode_Proc::(PinCode=%d)\n", + PRINT_MAC(mac_addr), pWscControl->WscPinCode)); + + return TRUE; +} + +INT Set_WscOOB_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + char *pTempSsid = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscPinCode_Proc:: Ap Client doesn't need this command.\n", apidx)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + + Set_WscSetupLock_Proc(pAd, "0"); + Set_AP_WscConfStatus_Proc(pAd, "1"); + Set_AP_AuthMode_Proc(pAd, "WPA2PSK"); + Set_AP_EncrypType_Proc(pAd, "AES"); + pTempSsid = vmalloc(33); + if (pTempSsid) + { + memset(pTempSsid, 0, 33); + snprintf(pTempSsid, 33,"RalinkInitialAP%02X%02X%02X", + pAd->ApCfg.MBSSID[apidx].wdev.bssid[3], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[4], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[5]); + Set_AP_SSID_Proc(pAd, pTempSsid); + vfree(pTempSsid); + } + Set_AP_WPAPSK_Proc(pAd, "RalinkInitialAPxx1234"); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscOOB_Proc\n", apidx)); + return TRUE; +} + +INT Set_WscStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PWSC_CTRL pWscControl; + BOOLEAN bFromApCli = FALSE; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscStop_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscStop_Proc:: This command is from ra interface now.\n", apidx)); + } + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + WscStop(pAd, TRUE, pWscControl); + pWscControl->WscConfMode = WSC_DISABLE; + } + else +#endif /* APCLI_SUPPORT */ + { + INT IsAPConfigured = pWscControl->WscConfStatus; + WscStop(pAd, FALSE, pWscControl); + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + } + + pWscControl->bWscTrigger = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("<===== Set_WscStop_Proc")); + return TRUE; +} + +/* + ========================================================================== + Description: + Get WSC Profile + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 get_wsc_profile + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +VOID RTMPIoctlWscProfile( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + WSC_CONFIGURED_VALUE Profile; + PSTRING msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + MULTISSID_STRUCT *pMbss; + struct wifi_dev *wdev; + + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; +#ifdef HOSTAPD_SUPPORT + if (pMbss->Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return; + } +#endif /*HOSTAPD_SUPPORT*/ + + + memset(&Profile, 0x00, sizeof(WSC_CONFIGURED_VALUE)); + Profile.WscConfigured = pMbss->WscControl.WscConfStatus; + NdisZeroMemory(Profile.WscSsid, 32 + 1); + NdisMoveMemory(Profile.WscSsid, pMbss->Ssid, pMbss->SsidLen); + Profile.WscSsidLen = pMbss->SsidLen; + Profile.WscSsid[pMbss->SsidLen] = '\0'; + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(wdev->AuthMode); + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(wdev->WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = wdev->DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][wdev->DefaultKeyId].KeyLen; i++) + { + snprintf((PSTRING) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][wdev->DefaultKeyId].Key[i]); + } + Profile.WscWPAKeyLen = pAd->SharedKey[apidx][wdev->DefaultKeyId].KeyLen; + Profile.WscWPAKey[(pAd->SharedKey[apidx][wdev->DefaultKeyId].KeyLen)*2] = '\0'; + } + } + else if (Profile.WscEncrypType >= 4) + { + Profile.DefaultKeyIdx = 2; + NdisMoveMemory(Profile.WscWPAKey, pMbss->WscControl.WpaPsk, + pMbss->WscControl.WpaPskLen); + Profile.WscWPAKeyLen = pMbss->WscControl.WpaPskLen; + Profile.WscWPAKey[pMbss->WscControl.WpaPskLen] = '\0'; + } + else + { + Profile.DefaultKeyIdx = 1; + } + + wrq->u.data.length = sizeof(Profile); + + if (copy_to_user(wrq->u.data.pointer, &Profile, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + +/* msg = (PSTRING)kmalloc(sizeof(CHAR)*(2048), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&msg, sizeof(CHAR)*(2048)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 2048); + sprintf(msg,"%s","\n"); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s\n", "Configured", "SSID", "AuthMode", "EncrypType"); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-13s%-26s\n", "Configured", "SSID", "AuthMode", "EncrypType", "DefaultKeyID", "Key"); + } + else + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-64s\n", "Configured", "SSID", "AuthMode", "EncrypType", "Key"); + } + + if (Profile.WscConfigured == 1) + sprintf(msg+strlen(msg),"%-12s", "No"); + else + sprintf(msg+strlen(msg),"%-12s", "Yes"); + sprintf(msg+strlen(msg), "%-33s", Profile.WscSsid); + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + sprintf(msg+strlen(msg), "%-12s", "TKIPAES"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetEncryTypeStr(Profile.WscEncrypType)); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg), "%s\n", ""); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg), "%-13d",Profile.DefaultKeyIdx); + sprintf(msg+strlen(msg), "%-26s\n",Profile.WscWPAKey); + } + else if (Profile.WscEncrypType >= 4) + { + sprintf(msg+strlen(msg), "%-64s\n",Profile.WscWPAKey); + } +#ifdef INF_AR9 + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); +#endif/* INF_AR9 */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); +/* kfree(msg); */ + os_free_mem(NULL, msg); +} + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) + +/* + ========================================================================== + Description: + Get WSC Profile + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 ar9_show get_wsc_profile + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +VOID RTMPAR9IoctlWscProfile( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + WSC_CONFIGURED_VALUE Profile; + PSTRING msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + MULTISSID_STRUCT *pMbss; + struct wifi_dev *wdev; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + + memset(&Profile, 0x00, sizeof(WSC_CONFIGURED_VALUE)); + Profile.WscConfigured = pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus; + NdisZeroMemory(Profile.WscSsid, 32 + 1); + NdisMoveMemory(Profile.WscSsid, pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen); + Profile.WscSsid[pAd->ApCfg.MBSSID[apidx].SsidLen] = '\0'; + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(wdev->AuthMode); + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(wdev->WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = wdev->DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][wdev->DefaultKeyId].KeyLen; i++) + { + snprintf((PSTRING) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][wdev->DefaultKeyId].Key[i]); + } + Profile.WscWPAKey[(pAd->SharedKey[apidx][wdev->DefaultKeyId].KeyLen)*2] = '\0'; + } + } + else if (Profile.WscEncrypType >= 4) + { + Profile.DefaultKeyIdx = 2; + NdisMoveMemory(Profile.WscWPAKey, pAd->ApCfg.MBSSID[apidx].WscControl.WpaPsk, + pAd->ApCfg.MBSSID[apidx].WscControl.WpaPskLen); + Profile.WscWPAKey[pAd->ApCfg.MBSSID[apidx].WscControl.WpaPskLen] = '\0'; + } + else + { + Profile.DefaultKeyIdx = 1; + } + + +/* msg = (PSTRING)kmalloc(sizeof(CHAR)*(2048), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&msg, sizeof(CHAR)*(2048)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 2048); + sprintf(msg,"%s","\n"); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s\n", "Configured", "SSID", "AuthMode", "EncrypType"); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-13s%-26s\n", "Configured", "SSID", "AuthMode", "EncrypType", "DefaultKeyID", "Key"); + } + else + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-64s\n", "Configured", "SSID", "AuthMode", "EncrypType", "Key"); + } + + if (Profile.WscConfigured == 1) + sprintf(msg+strlen(msg),"%-12s", "No"); + else + sprintf(msg+strlen(msg),"%-12s", "Yes"); + sprintf(msg+strlen(msg), "%-33s", Profile.WscSsid); + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + sprintf(msg+strlen(msg), "%-12s", "TKIPAES"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetEncryTypeStr(Profile.WscEncrypType)); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg), "%s\n", ""); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg), "%-13d",Profile.DefaultKeyIdx); + sprintf(msg+strlen(msg), "%-26s\n",Profile.WscWPAKey); + } + else if (Profile.WscEncrypType >= 4) + { + sprintf(msg+strlen(msg), "%-64s\n",Profile.WscWPAKey); + } + + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + { + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + } +/* kfree(msg); */ + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlWscPINCode( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UCHAR tempPIN[9]={0}; + +/* msg = (PSTRING)kmalloc(sizeof(CHAR)*(128), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(128)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 128); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"WSC_PINCode="); + if(pAd->ApCfg.MBSSID[apidx].WscControl.WscEnrolleePinCode) + { + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscEnrolleePinCodeLen == 8) + sprintf((PSTRING) tempPIN, "%08u", pAd->ApCfg.MBSSID[apidx].WscControl.WscEnrolleePinCode); + else + sprintf((PSTRING) tempPIN, "%04u", pAd->ApCfg.MBSSID[apidx].WscControl.WscEnrolleePinCode); + sprintf(msg,"%s%s\n",msg,tempPIN); + } + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + { + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + } +/* kfree(msg); */ + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlWscStatus( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +/* msg = (PSTRING)kmalloc(sizeof(CHAR)*(128), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(128)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 128); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"WSC_Status="); + sprintf(msg,"%s%d\n",msg,pAd->ApCfg.MBSSID[apidx].WscControl.WscStatus); + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + { + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + } +/* kfree(msg); */ + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlGetWscDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + PMULTISSID_STRUCT pMbss; + INT apidx,configstate; + + +/* msg = kmalloc(sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128)), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128))); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128)); + sprintf(msg,"%s","\n"); + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + pMbss=&pAd->ApCfg.MBSSID[apidx]; + + if(pMbss->WscControl.WscConfStatus == WSC_SCSTATE_UNCONFIGURED) + configstate = 0; + else + configstate = 1; + + sprintf(msg+strlen(msg),"ra%d\n",apidx); +#ifdef BB_SOC + sprintf(msg+strlen(msg),"DeviceName = %s\n",(pMbss->WscControl.RegData.SelfInfo.DeviceName)); +#endif + sprintf(msg+strlen(msg),"UUID = %s\n",(pMbss->WscControl.Wsc_Uuid_Str)); + sprintf(msg+strlen(msg),"wpsVersion = 0x%x\n",WSC_VERSION); + sprintf(msg+strlen(msg),"setuoLockedState = %d\n",0); + sprintf(msg+strlen(msg),"configstate = %d\n",configstate); + sprintf(msg+strlen(msg),"lastConfigError = %d\n",0); + + } + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + +/* kfree(msg); */ + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlGetWscRegsDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + PMULTISSID_STRUCT pMbss; + INT apidx; + + +/* msg = kmalloc(sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128)), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128))); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128)); + sprintf(msg,"%s","\n"); + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + pMbss=&pAd->ApCfg.MBSSID[apidx]; + sprintf(msg+strlen(msg),"ra%d\n",apidx); +#ifdef BB_SOC + sprintf(msg+strlen(msg),"DeviceName = %s\n",(pMbss->WscControl.RegData.SelfInfo.DeviceName)); +#endif + sprintf(msg+strlen(msg),"UUID_R = %s\n",(pMbss->WscControl.RegData.PeerInfo.Uuid)); + } + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + +/* kfree(msg); */ + os_free_mem(NULL, msg); +} +#endif /* defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) */ +#endif /* defined(INF_AR9) || defined(BB_SOC) */ + +BOOLEAN WscCheckEnrolleeNonceFromUpnp( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING pData, + IN USHORT Length, + IN PWSC_CTRL pWscControl) +{ + USHORT WscType, WscLen; + USHORT WscId = WSC_ID_ENROLLEE_NONCE; + + DBGPRINT(RT_DEBUG_TRACE, ("check Enrollee Nonce\n")); + + /* We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */ + while (Length > 4) + { + WSC_IE TLV_Recv; + char ZeroNonce[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + if (WscType == WscId) + { + if (RTMPCompareMemory(pWscControl->RegData.SelfNonce, pData, 16) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Nonce match!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n")); + return TRUE; + } + else if (NdisEqualMemory(pData, ZeroNonce, 16)) + { + /* Intel external registrar will send WSC_NACK with enrollee nonce */ + /* "10 1A 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" */ + /* when AP is configured and user selects not to configure AP. */ + DBGPRINT(RT_DEBUG_TRACE, ("Zero Enrollee Nonce!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n")); + return TRUE; + } + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Nonce mismatch!!\n")); + return FALSE; +} + +UCHAR WscRxMsgTypeFromUpnp( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING pData, + IN USHORT Length) +{ + + USHORT WscType, WscLen; + + { /* Eap-Esp(Messages) */ + /* the first TLV item in EAP Messages must be WSC_IE_VERSION */ + NdisMoveMemory(&WscType, pData, 2); + if (ntohs(WscType) != WSC_ID_VERSION) + goto out; + + /* Not Wsc Start, We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */ + while (Length > 4) + { + /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */ + NdisMoveMemory(&WscType, pData, 2); + NdisMoveMemory(&WscLen, pData + 2, 2); + WscLen = ntohs(WscLen); + if (ntohs(WscType) == WSC_ID_MSG_TYPE) + { + return(*(pData + 4)); /* Found the message type */ + } + else + { + pData += (WscLen + 4); + Length -= (WscLen + 4); + } + } + } + +out: + return WSC_MSG_UNKNOWN; +} + +VOID RTMPIoctlSetWSCOOB( + IN PRTMP_ADAPTER pAd) +{ + char *pTempSsid = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscPinCode_Proc:: Ap Client doesn't need this command.\n", apidx)); + return; + } +#endif /* APCLI_SUPPORT */ + + Set_WscSetupLock_Proc(pAd, "0"); + Set_AP_WscConfStatus_Proc(pAd, "1"); + Set_AP_AuthMode_Proc(pAd, "WPAPSK"); + Set_AP_EncrypType_Proc(pAd, "TKIP"); + pTempSsid = vmalloc(33); + if (pTempSsid) + { + memset(pTempSsid, 0, 33); + snprintf(pTempSsid, 33, "RalinkInitialAP%02X%02X%02X", + pAd->ApCfg.MBSSID[apidx].wdev.bssid[3], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[4], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[5]); + Set_AP_SSID_Proc(pAd, pTempSsid); + vfree(pTempSsid); + } + Set_AP_WPAPSK_Proc(pAd, "RalinkInitialAPxx1234"); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscOOB_Proc\n", apidx)); + return; +} + +/* + ========================================================================== + Description: + Set Wsc Security Mode + 0 : WPA2PSK AES + 1 : WPA2PSK TKIP + 2 : WPAPSK AES + 3 : WPAPSK TKIP + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_WscSecurityMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + if (strcmp(arg, "0") == 0) + pAd->ApCfg.MBSSID[apidx].WscSecurityMode = WPA2PSKAES; + else if (strcmp(arg, "1") == 0) + pAd->ApCfg.MBSSID[apidx].WscSecurityMode = WPA2PSKTKIP; + else if (strcmp(arg, "2") == 0) + pAd->ApCfg.MBSSID[apidx].WscSecurityMode = WPAPSKAES; + else if (strcmp(arg, "3") == 0) + pAd->ApCfg.MBSSID[apidx].WscSecurityMode = WPAPSKTKIP; + else if (strcmp(arg, "4") == 0) + pAd->ApCfg.MBSSID[apidx].WscSecurityMode = WPAPSKWPA2PSKTKIPAES; + else + return FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscSecurityMode_Proc::(WscSecurityMode=%d)\n", + apidx, pAd->ApCfg.MBSSID[apidx].WscSecurityMode )); + + return TRUE; +} + +INT Set_AP_WscMultiByteCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + BOOLEAN bEnable = FALSE; + PWSC_CTRL pWpsCtrl = NULL; + BOOLEAN bFromApCli = FALSE; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWpsCtrl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfMode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWpsCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfMode_Proc:: This command is from ra interface now.\n", apidx)); + } + + if (strcmp(arg, "0") == 0) + bEnable = FALSE; + else if (strcmp(arg, "1") == 0) + bEnable = TRUE; + else + return FALSE; + + if (pWpsCtrl->bCheckMultiByte != bEnable) + { + pWpsCtrl->bCheckMultiByte = bEnable; + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AP_WscMultiByteCheck_Proc::(bCheckMultiByte=%d)\n", + apidx, pWpsCtrl->bCheckMultiByte)); + + return TRUE; +} + +INT Set_WscVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR version = (UCHAR)simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVersion_Proc::(version=%x)\n",version)); + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.RegData.SelfInfo.Version = version; + return TRUE; +} + +INT Set_WscUUID_STR_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (strlen(arg) == (UUID_LEN_STR-1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscUUID_E_Proc[%d]::(arg=%s)\n",pObj->ioctl_if,arg)); + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.Wsc_Uuid_Str[UUID_LEN_STR-1]=0; + NdisMoveMemory(&pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.Wsc_Uuid_Str[0], arg , strlen(arg)); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ERROR Set_WscUUID_E_Proc[%d]::(arg=%s), Leng(%d) is incorrect!\n",pObj->ioctl_if,arg,strlen(arg))); + return FALSE; + } + +} + + +INT Set_WscUUID_HEX_E_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (strlen(arg) == (UUID_LEN_HEX*2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscUUID_HEX_E_Proc[%d]::(arg=%s)\n",pObj->ioctl_if,arg)); + AtoH(arg, &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.Wsc_Uuid_E[0], UUID_LEN_HEX); + hex_dump("Set_WscUUID_HEX_E_Proc OK:", &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.Wsc_Uuid_E[0], UUID_LEN_HEX); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ERROR Set_WscUUID_HEX_E_Proc[%d]::(arg=%s), Leng(%d) is incorrect!\n",pObj->ioctl_if,arg,strlen(arg))); + return FALSE; + } + +} + + +INT Set_WscSetupLock_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR bEnable = (UCHAR)simple_strtol(arg, 0, 10); + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + + if (bEnable == 0) + { + BOOLEAN bCancelled = FALSE; + if (pWscControl->WscSetupLockTimerRunning) + { + RTMPCancelTimer(&pWscControl->WscSetupLockTimer, &bCancelled); + } + WscSetupLockTimeout(NULL, pWscControl, NULL, NULL); + } + else + { + pWscControl->bSetupLock = TRUE; + WscBuildBeaconIE(pAd, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pObj->ioctl_if, + NULL, + 0, + AP_MODE); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_AP_WLAN_MGR, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pObj->ioctl_if, + NULL, + 0, + AP_MODE); + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscSetupLock_Proc::(bSetupLock=%d)\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.bSetupLock)); + return TRUE; +} + +#ifdef WSC_V2_SUPPORT +INT Set_WscFragment_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR bool_flag = (UCHAR)simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscFragment_Proc::(bool_flag=%d)\n",bool_flag)); + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.bWscFragment = bool_flag; + return TRUE; +} + +INT Set_WscFragmentSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + USHORT WscFragSize = (USHORT)simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscFragmentSize_Proc::(WscFragSize=%d)\n", WscFragSize)); + if ((WscFragSize >=128) && (WscFragSize <=300)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscFragSize = WscFragSize; + return TRUE; +} + +INT Set_WscV2Support_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR bEnable = (UCHAR)simple_strtol(arg, 0, 10); + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + + if (bEnable == 0) + pWscControl->WscV2Info.bEnableWpsV2 = FALSE; + else + pWscControl->WscV2Info.bEnableWpsV2 = TRUE; + + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* + WPS V2 doesn't support WEP and WPA/WPAPSK-TKIP. + */ + if ((pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.WepStatus == Ndis802_11WEPEnabled) || + (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->ApCfg.MBSSID[pObj->ioctl_if].bHideSsid)) + WscOnOff(pAd, pObj->ioctl_if, TRUE); + else + WscOnOff(pAd, pObj->ioctl_if, FALSE); + + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + } + else + { + WscInit(pAd, FALSE, pObj->ioctl_if); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscV2Support_Proc::(bEnableWpsV2=%d)\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscV2Info.bEnableWpsV2)); + return TRUE; +} + +INT Set_WscVersion2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR version = (UCHAR)simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVersion2_Proc::(version=%x)\n",version)); + if (version >= 0x20) + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.RegData.SelfInfo.Version2 = version; + else + return FALSE; + return TRUE; +} + +INT Set_WscExtraTlvTag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + USHORT new_tag = (USHORT)simple_strtol(arg, 0, 16); + + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscV2Info.ExtraTlv.TlvTag = new_tag; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscExtraTlvTag_Proc::(new_tag=0x%04X)\n",new_tag)); + return TRUE; +} + +INT Set_WscExtraTlvType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR type = (UCHAR)simple_strtol(arg, 0, 10); + + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscV2Info.ExtraTlv.TlvType = type; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscExtraTlvType_Proc::(type=%d)\n",type)); + return TRUE; +} + +INT Set_WscExtraTlvData_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UINT DataLen = (UINT)strlen(arg); + PWSC_TLV pWscTLV = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscV2Info.ExtraTlv; + INT i; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscExtraTlvData_Proc::(DataLen = %d)\n", DataLen)); + + if ((DataLen != 0) && (pWscTLV->TlvType == TLV_HEX)) + { + for(i=0; i < DataLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + } + + if (pWscTLV->pTlvData) + { + os_free_mem(NULL, pWscTLV->pTlvData); + pWscTLV->pTlvData = NULL; + } + + if (DataLen == 0) + return TRUE; + + pWscTLV->TlvLen = 0; + os_alloc_mem(NULL, &pWscTLV->pTlvData, DataLen); + if (pWscTLV->pTlvData) + { + if (pWscTLV->TlvType == TLV_ASCII) + { + NdisMoveMemory(pWscTLV->pTlvData, arg, DataLen); + pWscTLV->TlvLen = DataLen; + } + else + { + pWscTLV->TlvLen = DataLen/2; + AtoH(arg, pWscTLV->pTlvData, pWscTLV->TlvLen); + } + return TRUE; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscExtraTlvData_Proc::os_alloc_mem fail\n")); + + return FALSE; +} + +INT Set_WscMaxPinAttack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR MaxPinAttack = (UCHAR)simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMaxPinAttack_Proc::(MaxPinAttack=%d)\n", MaxPinAttack)); + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.MaxPinAttack = MaxPinAttack; + return TRUE; +} + + +INT Set_WscSetupLockTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UINT SetupLockTime = (UINT)simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscSetupLockTime_Proc::(SetupLockTime=%d)\n", SetupLockTime)); + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.SetupLockTime = SetupLockTime; + return TRUE; +} + +#endif /* WSC_V2_SUPPORT */ + +INT Set_WscAutoTriggerDisable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR bEnable = (UCHAR)simple_strtol(arg, 0, 10); + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + + if (bEnable == 0) + pWscCtrl->bWscAutoTriggerDisable = FALSE; + else + pWscCtrl->bWscAutoTriggerDisable = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscAutoTriggerDisable_Proc::(bWscAutoTriggerDisable=%d)\n", + pWscCtrl->bWscAutoTriggerDisable)); + return TRUE; +} + +#endif /* WSC_AP_SUPPORT */ + + + +#ifdef IAPP_SUPPORT +INT Set_IappPID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + unsigned long IappPid; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IappPid = simple_strtol(arg, 0, 10); + // TODO: correct the following line + /*RTMP_GET_OS_PID(pObj->IappPid, IappPid);*/ + pObj->IappPid_nr = IappPid; + +/* DBGPRINT(RT_DEBUG_TRACE, ("pObj->IappPid = %d", GET_PID_NUMBER(pObj->IappPid))); */ + return TRUE; +} /* End of Set_IappPID_Proc */ +#endif /* IAPP_SUPPORT */ + + +INT Set_DisConnectSta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + PSTRING value; + INT i; + MAC_TABLE_ENTRY *pEntry = NULL; + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, (UCHAR *)&macAddr[i++], 1); + } + + pEntry = MacTableLookup(pAd, macAddr); + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); +/* MacTableDeleteEntry(pAd, pEntry->wcid, Addr); */ + } + + return TRUE; +} + +INT Set_DisConnectAllSta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef DOT11W_PMF_SUPPORT + CHAR value = simple_strtol(arg, 0, 10); + + if (value == 2) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT i; + + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s:: apidx=%d\n", __FUNCTION__, pObj->ioctl_if)); + APMlmeKickOutAllSta(pAd, pObj->ioctl_if, REASON_DEAUTH_STA_LEAVING); + for (i=1; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: MacTableDeleteEntry %x:%x:%x:%x:%x:%x\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + } else +#endif /* DOT11W_PMF_SUPPORT */ + { + UINT idx = 0; + + /* find all the associated clients in MAC table */ + for (idx=1; idxMacTab.Content[idx]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) { +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) { + UCHAR apCliIdx = 0, CliIdx = 0; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, pEntry->Addr, TRUE, &isLinkValid); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) { + apCliIdx = pReptEntry->MatchApCliIdx; + CliIdx = pReptEntry->MatchLinkIdx; +#ifdef DOT11_N_SUPPORT + /* free BA resources */ + BASessionTearDownALL(pAd, pReptEntry->MacTabWCID); +#endif /* DOT11_N_SUPPORT */ + RTMPRemoveRepeaterDisconnectEntry(pAd, apCliIdx, CliIdx); + RTMPRemoveRepeaterEntry(pAd, apCliIdx, CliIdx); + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + } + } + } + + return TRUE; +} + + +#ifdef DOT1X_SUPPORT +/* + ========================================================================== + Description: + Set IEEE8021X. + This parameter is 1 when 802.1x-wep turn on, otherwise 0 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_IEEE8021X_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG ieee8021x; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + ieee8021x = simple_strtol(arg, 0, 10); + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if (ieee8021x == 1) + wdev->IEEE8021X = TRUE; + else if (ieee8021x == 0) + wdev->IEEE8021X = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_IEEE8021X_Proc::(IEEE8021X=%d)\n", pObj->ioctl_if, wdev->IEEE8021X)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set pre-authentication enable or disable when WPA/WPA2 turn on + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PreAuth_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG PreAuth; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + PreAuth = simple_strtol(arg, 0, 10); + + if (PreAuth == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PreAuth = TRUE; + else if (PreAuth == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PreAuth = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_PreAuth_Proc::(PreAuth=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PreAuth)); + + return TRUE; +} + +INT Set_OwnIPAddr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 ip_addr; + + if (rtinet_aton(arg, &ip_addr)) + { + pAd->ApCfg.own_ip_addr = ip_addr; + DBGPRINT(RT_DEBUG_TRACE, ("own_ip_addr=%s(%x)\n", arg, pAd->ApCfg.own_ip_addr)); + } + return TRUE; +} + +INT Set_EAPIfName_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + PSTRING macptr; + + for (i=0, macptr = rstrtok(arg,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (strlen(macptr) > 0) + { + pAd->ApCfg.EAPifname_len[i] = strlen(macptr); + NdisMoveMemory(pAd->ApCfg.EAPifname[i], macptr, strlen(macptr)); + DBGPRINT(RT_DEBUG_TRACE, ("NO.%d EAPifname=%s, len=%d\n", i, + pAd->ApCfg.EAPifname[i], + pAd->ApCfg.EAPifname_len[i])); + } + } + return TRUE; +} + +INT Set_PreAuthIfName_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + PSTRING macptr; + + for (i=0, macptr = rstrtok(arg,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (strlen(macptr) > 0) + { + pAd->ApCfg.PreAuthifname_len[i] = strlen(macptr); + NdisMoveMemory(pAd->ApCfg.PreAuthifname[i], macptr, strlen(macptr)); + DBGPRINT(RT_DEBUG_TRACE, ("NO.%d PreAuthifname=%s, len=%d\n", i, + pAd->ApCfg.PreAuthifname[i], + pAd->ApCfg.PreAuthifname_len[i])); + } + } + return TRUE; + +} + +INT Set_RADIUS_Server_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PSTRING macptr; + INT count; + UINT32 ip_addr; + INT srv_cnt = 0; + + for (count = 0, macptr = rstrtok(arg,";"); (macptr && count < MAX_RADIUS_SRV_NUM); macptr = rstrtok(NULL,";"), count++) + { + if (rtinet_aton(macptr, &ip_addr)) + { + PRADIUS_SRV_INFO pSrvInfo = &pAd->ApCfg.MBSSID[apidx].radius_srv_info[srv_cnt]; + + pSrvInfo->radius_ip = ip_addr; + srv_cnt++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_ip(seq-%d)=%s(%x)\n", + apidx, srv_cnt, macptr, + pSrvInfo->radius_ip)); + } + } + + if (srv_cnt > 0) + pAd->ApCfg.MBSSID[apidx].radius_srv_num = srv_cnt; + + return TRUE; +} + +INT Set_RADIUS_Port_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PSTRING macptr; + INT count; + INT srv_cnt = 0; + + for (count = 0, macptr = rstrtok(arg,";"); (macptr && count < MAX_RADIUS_SRV_NUM); macptr = rstrtok(NULL,";"), count++) + { + if (srv_cnt < pAd->ApCfg.MBSSID[apidx].radius_srv_num) + { + PRADIUS_SRV_INFO pSrvInfo = &pAd->ApCfg.MBSSID[apidx].radius_srv_info[srv_cnt]; + + pSrvInfo->radius_port = (UINT32) simple_strtol(macptr, 0, 10); + srv_cnt ++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_port(seq-%d)=%d\n", + apidx, srv_cnt, pSrvInfo->radius_port)); + } + } + + return TRUE; +} + +INT Set_RADIUS_Key_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PSTRING macptr; + INT count; + INT srv_cnt = 0; + + for (count = 0, macptr = rstrtok(arg,";"); (macptr && count < MAX_RADIUS_SRV_NUM); macptr = rstrtok(NULL,";"), count++) + { + if (strlen(macptr) > 0 && srv_cnt < pAd->ApCfg.MBSSID[apidx].radius_srv_num) + { + PRADIUS_SRV_INFO pSrvInfo = &pAd->ApCfg.MBSSID[apidx].radius_srv_info[srv_cnt]; + + pSrvInfo->radius_key_len = strlen(macptr); + NdisMoveMemory(pSrvInfo->radius_key, macptr, pSrvInfo->radius_key_len); + srv_cnt ++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_key(seq-%d)=%s, len=%d\n", + apidx, srv_cnt, + pSrvInfo->radius_key, + pSrvInfo->radius_key_len)); + } + } + return TRUE; +} +#endif /* DOT1X_SUPPORT */ + +#ifdef UAPSD_SUPPORT +INT Set_UAPSD_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR IdMbss = pObj->ioctl_if; + + if (simple_strtol(arg, 0, 10) != 0) + pAd->ApCfg.MBSSID[IdMbss].UapsdInfo.bAPSDCapable = TRUE; + else + pAd->ApCfg.MBSSID[IdMbss].UapsdInfo.bAPSDCapable = FALSE; + + return TRUE; +} /* End of Set_UAPSD_Proc */ +#endif /* UAPSD_SUPPORT */ + + + +#ifdef MCAST_RATE_SPECIFIC +INT Set_McastPhyMode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR PhyMode = simple_strtol(arg, 0, 10); + + //pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; + switch (PhyMode) + { + case MCAST_DISABLE: /* disable */ + NdisMoveMemory(&pAd->CommonCfg.MCastPhyMode, &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + break; + + case MCAST_CCK: /* CCK */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_CCK; + pAd->CommonCfg.MCastPhyMode.field.BW = BW_20; + break; + + case MCAST_OFDM: /* OFDM */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_OFDM; + pAd->CommonCfg.MCastPhyMode.field.BW = BW_20; + break; +#ifdef DOT11_N_SUPPORT + case MCAST_HTMIX: /* HTMIX */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_HTMIX; + if (pAd->CommonCfg.BBPCurrentBW > BW_20) + pAd->CommonCfg.MCastPhyMode.field.BW = BW_40; + else + pAd->CommonCfg.MCastPhyMode.field.BW = BW_20; + break; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + case MCAST_VHT: /* VHT */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_VHT; + pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.BBPCurrentBW; + break; +#endif /* DOT11_VHT_AC */ + default: + DBGPRINT(RT_DEBUG_OFF, ("Unknown Muticast PhyMode %d\n", PhyMode)); + DBGPRINT(RT_DEBUG_OFF, ("0:Disabled, 1:CCK, 2:OFDM, 3:HTMIX, 4:VHT\n")); + break; + } + + return TRUE; +} + +INT Set_McastMcs( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR Mcs = simple_strtol(arg, 0, 10); + + switch (pAd->CommonCfg.MCastPhyMode.field.MODE) + { + case MODE_CCK: + if ((Mcs <= 3) || (Mcs >= 8 && Mcs <= 11)) + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + else + DBGPRINT(RT_DEBUG_ERROR, ("MCS must in range of 0 ~ 3 and 8 ~ 11 for CCK mode\n")); + break; + + case MODE_OFDM: + if (Mcs > 7) + DBGPRINT(RT_DEBUG_ERROR, ("MCS must in range from 0 to 7 for OFDM mode\n")); + else + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + break; + + default: + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + break; + } + + return TRUE; +} + +INT Show_McastRate( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("Mcast PhyMode = %d\n", pAd->CommonCfg.MCastPhyMode.field.MODE)); + DBGPRINT(RT_DEBUG_OFF, ("Mcast MCS = %d\n", pAd->CommonCfg.MCastPhyMode.field.MCS)); + + return TRUE; +} +#endif /* MCAST_RATE_SPECIFIC */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +INT Set_OBSSScanParam_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ObssScanValue; + UINT Idx; + PSTRING thisChar; + + Idx = 0; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + ObssScanValue = (INT) simple_strtol(thisChar, 0, 10); + switch (Idx) + { + case 0: + if (ObssScanValue < 5 || ObssScanValue > 1000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanPassiveDwell(%d), should in range 5~1000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanPassiveDwell = ObssScanValue; /* Unit : TU. 5~1000 */ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanPassiveDwell=%d\n", ObssScanValue)); + } + break; + case 1: + if (ObssScanValue < 10 || ObssScanValue > 1000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanActiveDwell(%d), should in range 10~1000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanActiveDwell = ObssScanValue; /* Unit : TU. 10~1000 */ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanActiveDwell=%d\n", ObssScanValue)); + } + break; + case 2: + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = ObssScanValue; /* Unit : Second */ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthTriggerScanInt=%d\n", ObssScanValue)); + break; + case 3: + if (ObssScanValue < 200 || ObssScanValue > 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanPassiveTotalPerChannel(%d), should in range 200~10000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = ObssScanValue; /* Unit : TU. 200~10000 */ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanPassiveTotalPerChannel=%d\n", ObssScanValue)); + } + break; + case 4: + if (ObssScanValue < 20 || ObssScanValue > 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanActiveTotalPerChannel(%d), should in range 20~10000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = ObssScanValue; /* Unit : TU. 20~10000 */ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanActiveTotalPerChannel=%d\n", ObssScanValue)); + } + break; + case 5: + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = ObssScanValue; + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelayFactor=%d\n", ObssScanValue)); + break; + case 6: + pAd->CommonCfg.Dot11OBssScanActivityThre = ObssScanValue; /* Unit : percentage */ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelayFactor=%d\n", ObssScanValue)); + break; + } + Idx++; + } + + if (Idx != 7) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong OBSSScanParamtetrs format in ioctl cmd!!!!! Use default value\n")); + + pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; /* Unit : TU. 5~1000 */ + pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; /* Unit : TU. 10~1000 */ + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; /* Unit : Second */ + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; /* Unit : TU. 200~10000 */ + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; /* Unit : TU. 20~10000 */ + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; + pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; /* Unit : percentage */ + } + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelay=%ld\n", pAd->CommonCfg.Dot11BssWidthChanTranDelay)); + + return TRUE; +} + + +INT Set_AP2040ReScan_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + APOverlappingBSSScan(pAd); + + /* apply setting */ + SetCommonHT(pAd); + AsicBBPAdjust(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP2040ReScan_Proc() Trigger AP ReScan !!!\n")); + + return TRUE; +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +INT Set_EntryLifeCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG LifeCheckCnt = (ULONG) simple_strtol(arg, 0, 10); + + if (LifeCheckCnt <= 65535) + pAd->ApCfg.EntryLifeCheck = LifeCheckCnt; + else + printk("LifeCheckCnt must in range of 0 to 65535\n"); + + printk("EntryLifeCheck Cnt = %ld.\n", pAd->ApCfg.EntryLifeCheck); + return TRUE; +} + +/* + ========================================================================== + Description: + Set Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT ApCfg_Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PSTRING arg) +{ + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + wdev->AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + else if ((strcmp(arg, "WPAPSKWPA2PSK") == 0) || (strcmp(arg, "wpapskwpa2psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; +#ifdef DOT1X_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2; + else if ((strcmp(arg, "WPA1WPA2") == 0) || (strcmp(arg, "wpa1wpa2") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA1WPA2; +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "WAICERT") == 0) || (strcmp(arg, "waicert") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWAICERT; + else if ((strcmp(arg, "WAIPSK") == 0) || (strcmp(arg, "waipsk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d)::AuthMode=%d\n", apidx, wdev->AuthMode)); + + return TRUE; +} + +INT ApCfg_Set_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PSTRING arg) +{ + pAd->ApCfg.MBSSID[apidx].MaxStaNum = (UCHAR)simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(MaxStaNum=%d)\n", + apidx, __FUNCTION__, pAd->ApCfg.MBSSID[apidx].MaxStaNum)); + return TRUE; +} + +INT ApCfg_Set_IdleTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG idle_time; + + idle_time = simple_strtol(arg, 0, 10); + + if (idle_time < MAC_TABLE_MIN_AGEOUT_TIME) + pAd->ApCfg.StaIdleTimeout = MAC_TABLE_MIN_AGEOUT_TIME; + else + pAd->ApCfg.StaIdleTimeout = idle_time; + + DBGPRINT(RT_DEBUG_TRACE, ("%s : IdleTimeout=%d\n", __FUNCTION__, pAd->ApCfg.StaIdleTimeout)); + + return TRUE; +} + +#ifdef RTMP_RBUS_SUPPORT +#ifdef LED_CONTROL_SUPPORT +INT Set_WlanLed_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bWlanLed; +#ifdef CONFIG_SWMCU_SUPPORT + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; +#endif /* CONFIG_SWMCU_SUPPORT */ + + bWlanLed = (BOOLEAN) simple_strtol(arg, 0, 10); + +#ifdef CONFIG_SWMCU_SUPPORT + if (bWlanLed != pSWMCULedCntl->bWlanLed) +#endif /* CONFIG_SWMCU_SUPPORT */ + { + if (bWlanLed) + RTMPStartLEDMode(pAd); + else + RTMPExitLEDMode(pAd); + }; + + return TRUE; +} +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + + + + + +INT Set_MemDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef VENDOR_FEATURE2_SUPPORT + printk("Number of Packet Allocated = %lu\n", OS_NumOfPktAlloc); + printk("Number of Packet Freed = %lu\n", OS_NumOfPktFree); + printk("Offset of Packet Allocated/Freed = %lu\n", OS_NumOfPktAlloc - OS_NumOfPktFree); +#endif /* VENDOR_FEATURE2_SUPPORT */ + return TRUE; +} + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +VOID RTMPApCliAddKey( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PNDIS_APCLI_802_11_KEY pKey) +{ + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + INT ifIndex,BssIdx; + PAPCLI_STRUCT pApCliEntry; + MAC_TABLE_ENTRY *pMacEntry=(MAC_TABLE_ENTRY *)NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPApCliAddKey ------>\n")); + + ifIndex=apidx; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; + + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + { + if (pKey->KeyIndex & 0x80000000) + { + if (pApCliEntry->AuthMode == Ndis802_11AuthModeWPANone) + { + NdisZeroMemory(pApCliEntry->PMK, 32); + NdisMoveMemory(pApCliEntry->PMK, pKey->KeyMaterial, pKey->KeyLength); + goto end; + } + /* Update PTK */ + NdisZeroMemory(&pMacEntry->PairwiseKey, sizeof(CIPHER_KEY)); + pMacEntry->PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(pMacEntry->PairwiseKey.Key, pKey->KeyMaterial, LEN_TK); + + if (pApCliEntry->PairCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pMacEntry->PairwiseKey.RxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pMacEntry->PairwiseKey.TxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + else + + { + NdisMoveMemory(pMacEntry->PairwiseKey.TxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pMacEntry->PairwiseKey.RxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + + /* Decide its ChiperAlg */ + if (pApCliEntry->PairCipher == Ndis802_11Encryption2Enabled) + pMacEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pApCliEntry->PairCipher == Ndis802_11Encryption3Enabled) + pMacEntry->PairwiseKey.CipherAlg = CIPHER_AES; + else + pMacEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pMacEntry->Aid, + &pMacEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + 0, + pMacEntry->PairwiseKey.CipherAlg, + (UCHAR)pMacEntry->Aid, + PAIRWISEKEYTABLE); + + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + { + /* set 802.1x port control */ + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + } + else + { + /* Update GTK */ + pApCliEntry->DefaultKeyId = (pKey->KeyIndex & 0xFF); + NdisZeroMemory(&pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId], sizeof(CIPHER_KEY)); + pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].KeyLen = LEN_TK; + NdisMoveMemory(pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].Key, pKey->KeyMaterial, LEN_TK); + + if (pApCliEntry->GroupCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + else + + { + NdisMoveMemory(pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pApCliEntry->GroupCipher == Ndis802_11Encryption2Enabled) + pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pApCliEntry->GroupCipher == Ndis802_11Encryption3Enabled) + pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].CipherAlg = CIPHER_AES; + + /* Update group key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BssIdx, + pApCliEntry->DefaultKeyId, + &pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId]); + + + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, + BssIdx, + pApCliEntry->DefaultKeyId, + pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].CipherAlg, + NULL); + + + /* set 802.1x port control */ + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + { + /* set 802.1x port control */ + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + } + } + else /* dynamic WEP from wpa_supplicant */ + { + UCHAR CipherAlg; + PUCHAR Key; + + if(pKey->KeyLength == 32) + goto end; + + KeyIdx = pKey->KeyIndex & 0x0fffffff; + + if (KeyIdx < 4) + { + /* it is a default shared key, for Pairwise key setting */ + if (pKey->KeyIndex & 0x80000000) + { + pEntry = MacTableLookup(pAd, pKey->BSSID); + + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n")); + + /* set key material and key length */ + pEntry->PairwiseKey.KeyLen = (UCHAR )pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* set Cipher type */ + if (pKey->KeyLength == 5) + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + else + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + } + } + else + { + /* Default key for tx (shared key) */ + pApCliEntry->DefaultKeyId = (UCHAR) KeyIdx; + + /*/ set key material and key length */ + pApCliEntry->SharedKey[KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(pApCliEntry->SharedKey[KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* Set Ciper type */ + if (pKey->KeyLength == 5) + pApCliEntry->SharedKey[KeyIdx].CipherAlg = CIPHER_WEP64; + else + pApCliEntry->SharedKey[KeyIdx].CipherAlg = CIPHER_WEP128; + + CipherAlg = pApCliEntry->SharedKey[KeyIdx].CipherAlg; + Key = pApCliEntry->SharedKey[KeyIdx].Key; + + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, BssIdx, KeyIdx, &pApCliEntry->SharedKey[KeyIdx]); + + /* STA doesn't need to set WCID attribute for group key */ + + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPAddWcidAttributeEntry(pAd, BssIdx, KeyIdx, CipherAlg, NULL); + + } + } + } +end: + + DBGPRINT(RT_DEBUG_INFO, ("<------ RTMPApCliAddKey\n")); + + return; +} +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + +#ifdef CONFIG_AP_SUPPORT +/* +======================================================================== +Routine Description: + Set power save life time. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Set_PowerSaveLifeTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->MacTab.MsduLifeTime = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Set new life time = %d\n", pAd->MacTab.MsduLifeTime)); + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef MBSS_SUPPORT +/* +======================================================================== +Routine Description: + Show MBSS information. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Show_MbssInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 IdBss; + UCHAR PhyMode; + CHAR *mod_str = NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("\n\tBSS Idx\t\tPhy Mode\n")); + + for(IdBss=0; IdBss<=pAd->ApCfg.BssidNum; IdBss++) + { + if (IdBss == 0) + { + PhyMode = pAd->CommonCfg.PhyMode; + DBGPRINT(RT_DEBUG_ERROR, ("\tMAX\t\t")); + } + else + { + PhyMode = pAd->ApCfg.MBSSID[IdBss-1].wdev.PhyMode; + DBGPRINT(RT_DEBUG_ERROR, ("\t%d\t\t", IdBss-1)); + } /* End of if */ + + switch(PhyMode) + { + case (WMODE_B | WMODE_G): + mod_str = "BG Mixed"; + break; + + case (WMODE_B): + mod_str = "B Only"; + break; + + case (WMODE_A): + mod_str = "A Only"; + break; + + case (WMODE_A | WMODE_B | WMODE_G): + mod_str = "ABG Mixed ==> BG Mixed"; + break; + + case (WMODE_G): + mod_str = "G Only"; + break; + +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_B | WMODE_G | WMODE_AN | WMODE_GN): + mod_str = "ABGN Mixed ==> BGN Mixed"; + break; + + case (WMODE_GN): + mod_str = "2.4G N Only"; + break; + + case (WMODE_G | WMODE_GN): + mod_str = "GN Mixed"; + break; + + case (WMODE_A | WMODE_AN): + mod_str = "AN Mixed"; + break; + + case (WMODE_B | WMODE_G | WMODE_GN): + mod_str = "BGN Mixed"; + break; + + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): + mod_str = "AGN Mixed"; + break; + + case (WMODE_AN): + mod_str = "5G N Only"; + break; +#endif /* DOT11_N_SUPPORT */ + } + } + + if (mod_str) + DBGPRINT(RT_DEBUG_ERROR, ("%s\n", mod_str)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + return TRUE; +} /* End of Show_MbssInfo_Display_Proc */ +#endif /* MBSS_SUPPORT */ + + +#ifdef HOSTAPD_SUPPORT +VOID RtmpHostapdSecuritySet( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrqin) +{ + if(wrqin->u.data.length > 20 && MAX_LEN_OF_RSNIE > wrqin->u.data.length && wrqin->u.data.pointer) + { + UCHAR RSNIE_Len[2]; + UCHAR RSNIe[2]; + int offset_next_ie=0; + + DBGPRINT(RT_DEBUG_TRACE,("ioctl SIOCSIWGENIE pAd->IoctlIF=%d\n",apidx)); + + RSNIe[0]=*(UINT8 *)wrqin->u.data.pointer; + if(IE_WPA != RSNIe[0] && IE_RSN != RSNIe[0] ) + { + DBGPRINT(RT_DEBUG_TRACE,("IE %02x != 0x30/0xdd\n",RSNIe[0])); + Status = -EINVAL; + break; + } + RSNIE_Len[0]=*((UINT8 *)wrqin->u.data.pointer + 1); + if(wrqin->u.data.length != RSNIE_Len[0]+2) + { + DBGPRINT(RT_DEBUG_TRACE,("IE use WPA1 WPA2\n")); + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[1], MAX_LEN_OF_RSNIE); + RSNIe[1]=*(UINT8 *)wrqin->u.data.pointer; + RSNIE_Len[1]=*((UINT8 *)wrqin->u.data.pointer + 1); + DBGPRINT(RT_DEBUG_TRACE,( "IE1 %02x %02x\n",RSNIe[1],RSNIE_Len[1])); + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1] = RSNIE_Len[1]; + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[1], (UCHAR *)(wrqin->u.data.pointer)+2, RSNIE_Len[1]); + offset_next_ie=RSNIE_Len[1]+2; + } + else + DBGPRINT(RT_DEBUG_TRACE,("IE use only %02x\n",RSNIe[0])); + + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[0], MAX_LEN_OF_RSNIE); + RSNIe[0]=*(((UINT8 *)wrqin->u.data.pointer)+offset_next_ie); + RSNIE_Len[0]=*(((UINT8 *)wrqin->u.data.pointer) + offset_next_ie + 1); + if(IE_WPA != RSNIe[0] && IE_RSN != RSNIe[0] ) + { + Status = -EINVAL; + break; + } + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0] = RSNIE_Len[0]; + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[0], ((UCHAR *)(wrqin->u.data.pointer))+2+offset_next_ie, RSNIE_Len[0]); + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + } +} +#endif /* HOSTAPD_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Driver Ioctl for AP. + +Arguments: + pAdSrc - WLAN control block pointer + wrq - the IOCTL parameters + cmd - the command ID + subcmd - the sub-command ID + pData - the IOCTL private data pointer + Data - the IOCTL private data + +Return Value: + NDIS_STATUS_SUCCESS - IOCTL OK + Otherwise - IOCTL fail + +Note: +======================================================================== +*/ +INT RTMP_AP_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT Status = NDIS_STATUS_SUCCESS; + + + switch(cmd) + { + case CMD_RTPRIV_IOCTL_SET: + Status = RTMPAPPrivIoctlSet(pAd, wrq); + break; + + case CMD_RT_PRIV_IOCTL: + if (subcmd & OID_GET_SET_TOGGLE) + Status = RTMPAPSetInformation(pAd, wrq, (INT)subcmd); + else + { +#ifdef LLTD_SUPPORT + if (subcmd == RT_OID_GET_PHY_MODE) + { + if(pData != NULL) + { + UINT modetmp = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get phy mode (%02X) \n", pAd->CommonCfg.PhyMode)); + modetmp = (UINT)wmode_2_cfgmode(pAd->CommonCfg.PhyMode); + wrq->u.data.length = 1; + if (copy_to_user(pData, &modetmp, wrq->u.data.length)) + Status = -EFAULT; + } + else + Status = -EFAULT; + } + else +#endif /* LLTD_SUPPORT */ + Status = RTMPAPQueryInformation(pAd, wrq, (INT)subcmd); + } + break; + + case CMD_RTPRIV_IOCTL_SHOW: + Status = RTMPAPPrivIoctlShow(pAd, wrq); + break; + +#ifdef WSC_AP_SUPPORT + case CMD_RTPRIV_IOCTL_SET_WSCOOB: + RTMPIoctlSetWSCOOB(pAd); + break; +#endif/*WSC_AP_SUPPORT*/ + + case CMD_RTPRIV_IOCTL_GET_MAC_TABLE: + RTMPIoctlGetMacTable(pAd,wrq); + break; + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) + case CMD_RTPRIV_IOCTL_GSITESURVEY: + RTMPIoctlGetSiteSurvey(pAd,wrq); + break; +#endif /* AP_SCAN_SUPPORT */ + + case CMD_RTPRIV_IOCTL_STATISTICS: + RTMPIoctlStatistics(pAd, wrq); + break; + +#ifdef WSC_AP_SUPPORT + case CMD_RTPRIV_IOCTL_WSC_PROFILE: + RTMPIoctlWscProfile(pAd, wrq); + break; +#endif /* WSC_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + case CMD_RTPRIV_IOCTL_QUERY_BATABLE: + RTMPIoctlQueryBaTable(pAd, wrq); + break; +#endif /* DOT11_N_SUPPORT */ + + case CMD_RTPRIV_IOCTL_E2P: + RTMPAPIoctlE2PROM(pAd, wrq); + break; + +#if defined (DBG) || defined (RALINK_ATE) + case CMD_RTPRIV_IOCTL_BBP: + RTMPAPIoctlBBP(pAd, wrq); + break; + + case CMD_RTPRIV_IOCTL_MAC: + RTMPAPIoctlMAC(pAd, wrq); + break; + +#ifdef RTMP_RF_RW_SUPPORT + case CMD_RTPRIV_IOCTL_RF: + RTMPAPIoctlRF(pAd, wrq); + break; +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /* defined(DBG) || defined (RALINK_ATE) */ + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT + case CMD_RTPRIV_IOCTL_GET_AR9_SHOW: + Status = RTMPAPPrivIoctlAR9Show(pAd, wrq); + break; +#endif /*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ + + case CMD_RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT: + RTMPIoctlGetMacTableStaInfo(pAd, wrq); + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIFHWADDR: + if (pObj->ioctl_if < MAX_MBSSID_NUM(pAd)) + NdisCopyMemory((PSTRING) wrq->u.name, (PSTRING) pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bssid, 6); + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIWESSID: + { + RT_CMD_AP_IOCTL_SSID *pSSID = (RT_CMD_AP_IOCTL_SSID *)pData; + +#ifdef APCLI_SUPPORT + if (pSSID->priv_flags == INT_APCLI) + { + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].Valid == TRUE) + { + pSSID->length = pAd->ApCfg.ApCliTab[pObj->ioctl_if].SsidLen; + pSSID->pSsidStr = (char *)&pAd->ApCfg.ApCliTab[pObj->ioctl_if].Ssid; + } + else { + pSSID->length = 0; + pSSID->pSsidStr = NULL; + } + } + else +#endif /* APCLI_SUPPORT */ + { + pSSID->length = pAd->ApCfg.MBSSID[pSSID->apidx].SsidLen; + pSSID->pSsidStr = (char *)pAd->ApCfg.MBSSID[pSSID->apidx].Ssid; + } + } + break; + +#ifdef MBSS_SUPPORT + case CMD_RTPRIV_IOCTL_MBSS_BEACON_UPDATE: + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + break; + + case CMD_RTPRIV_IOCTL_MBSS_OPEN: + if (MBSS_Open(pData) != 0) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_MBSS_CLOSE: + MBSS_Close(pData); + break; + + case CMD_RTPRIV_IOCTL_MBSS_INIT: + MBSS_Init(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_MBSS_REMOVE: + MBSS_Remove(pAd); + break; +#endif /* MBSS_SUPPORT */ + + case CMD_RTPRIV_IOCTL_WSC_INIT: + { +#ifdef APCLI_SUPPORT +#ifdef WSC_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + PWSC_V2_INFO pWscV2Info; +#endif /* WSC_V2_SUPPORT */ + APCLI_STRUCT *pApCliEntry = (APCLI_STRUCT *)pData; + WscGenerateUUID(pAd, &pApCliEntry->WscControl.Wsc_Uuid_E[0], + &pApCliEntry->WscControl.Wsc_Uuid_Str[0], 0, FALSE); + pApCliEntry->WscControl.bWscFragment = FALSE; + pApCliEntry->WscControl.WscFragSize = 128; + pApCliEntry->WscControl.WscRxBufLen = 0; + pApCliEntry->WscControl.pWscRxBuf = NULL; + os_alloc_mem(pAd, &pApCliEntry->WscControl.pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + if (pApCliEntry->WscControl.pWscRxBuf) + NdisZeroMemory(pApCliEntry->WscControl.pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + pApCliEntry->WscControl.WscTxBufLen = 0; + pApCliEntry->WscControl.pWscTxBuf = NULL; + os_alloc_mem(pAd, &pApCliEntry->WscControl.pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + if (pApCliEntry->WscControl.pWscTxBuf) + NdisZeroMemory(pApCliEntry->WscControl.pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + initList(&pApCliEntry->WscControl.WscPeerList); + NdisAllocateSpinLock(pAd, &pApCliEntry->WscControl.WscPeerListSemLock); + pApCliEntry->WscControl.PinAttackCount = 0; + pApCliEntry->WscControl.bSetupLock = FALSE; +#ifdef WSC_V2_SUPPORT + pWscV2Info = &pApCliEntry->WscControl.WscV2Info; + pWscV2Info->bWpsEnable = TRUE; + pWscV2Info->ExtraTlv.TlvLen = 0; + pWscV2Info->ExtraTlv.TlvTag = 0; + pWscV2Info->ExtraTlv.pTlvData = NULL; + pWscV2Info->ExtraTlv.TlvType = TLV_ASCII; + pWscV2Info->bEnableWpsV2 = TRUE; +#endif /* WSC_V2_SUPPORT */ + WscInit(pAd, TRUE, Data); +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ + } + break; + +#ifdef APCLI_SUPPORT + case CMD_RTPRIV_IOCTL_APC_UP: + ApCliIfUp(pAd); + break; + + case CMD_RTPRIV_IOCTL_APC_DISCONNECT: + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, Data); + RTMP_MLME_HANDLER(pAd); + break; + + case CMD_RTPRIV_IOCTL_APC_INIT: + APCli_Init(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_APC_OPEN: + if (ApCli_Open(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_APC_CLOSE: + if (ApCli_Close(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_APC_REMOVE: + ApCli_Remove(pAd); + break; +#endif /* APCLI_SUPPORT */ + + case CMD_RTPRIV_IOCTL_MAIN_OPEN: +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) +#endif /* AIRPLAY_SUPPORT */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = TRUE; + break; + + case CMD_RTPRIV_IOCTL_PREPARE: + { + RT_CMD_AP_IOCTL_CONFIG *pConfig = (RT_CMD_AP_IOCTL_CONFIG *)pData; + pConfig->Status = RTMP_AP_IoctlPrepare(pAd, pData); + if (pConfig->Status != 0) + return NDIS_STATUS_FAILURE; + } + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIWAP: + { + UCHAR *pBssidDest = (UCHAR *)pData; + PCHAR pBssidStr; + +#ifdef APCLI_SUPPORT + if (Data == INT_APCLI) + { + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].Valid == TRUE) + pBssidStr = (PCHAR)&APCLI_ROOT_BSSID_GET(pAd, pAd->ApCfg.ApCliTab[pObj->ioctl_if].MacTabWCID); + else + pBssidStr = NULL; + } + else +#endif /* APCLI_SUPPORT */ + { + pBssidStr = (PCHAR) &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bssid[0]; + } + + if (pBssidStr != NULL) + { + memcpy(pBssidDest, pBssidStr, ETH_ALEN); + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pBssidStr))); + } + else + { + memset(pBssidDest, 0, ETH_ALEN); + } + } + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ: + /* handle for SIOCGIWRATEQ */ + { + RT_CMD_IOCTL_RATE *pRate = (RT_CMD_IOCTL_RATE *)pData; + HTTRANSMIT_SETTING HtPhyMode; + +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.HTPhyMode; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].wdev.HTPhyMode; + else +#endif /* WDS_SUPPORT */ + { + HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.HTPhyMode; + +#ifdef MBSS_SUPPORT + /* reset phy mode for MBSS */ + MBSS_PHY_MODE_RESET(pObj->ioctl_if, HtPhyMode); +#endif /* MBSS_SUPPORT */ + } + + RtmpDrvRateGet(pAd, HtPhyMode.field.MODE, HtPhyMode.field.ShortGI, + HtPhyMode.field.BW, HtPhyMode.field.MCS, + pAd->Antenna.field.TxPath, + (UINT32 *)&pRate->BitRate); + } + break; + +#ifdef HOSTAPD_SUPPORT + case CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ: + RtmpHostapdSecuritySet(pAd, wrq); + break; +#endif /* HOSTAPD_SUPPORT */ + + + default: + Status = RTMP_COM_IoctlHandle(pAd, wrq, cmd, subcmd, pData, Data); + break; + } + + return Status; +} + +#if defined(MICROWAVE_OVEN_SUPPORT) +INT Set_MO_FalseCCATh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG th; + + th = simple_strtol(arg, 0, 10); + + if (th > 65535) + th = 65535; + + pAd->CommonCfg.MO_Cfg.nFalseCCATh = th; + + DBGPRINT(RT_DEBUG_OFF, ("%s: set falseCCA threshold %lu for microwave oven application!!\n", __FUNCTION__, th)); + + return TRUE; +} +#endif + +#ifdef DYNAMIC_VGA_SUPPORT + +INT Set_SkipLongRangeVga_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + + Enable = simple_strtol(arg, 0, 10); + + pAd->chipCap.skip_long_range_dync_vga = (Enable != 0)?TRUE:FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_SkipLongRangeVga_Proc::(skip = %d)\n", pAd->chipCap.skip_long_range_dync_vga)); + + return TRUE; +} + +INT Set_AP_DyncVgaEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + UINT32 bbp_val; + + Enable = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = (Enable > 0) ? TRUE : FALSE; + + if (pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable == FALSE) + { +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val); + bbp_val = (bbp_val & 0xffff80ff) | (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val); + + if (pAd->CommonCfg.RxStream >= 2) { + RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val); + bbp_val = (bbp_val & 0xffff80ff) | (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val); + } + } +#endif /* MT76x2 */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) { + rt6352_dynamic_vga_disable(pAd); + } +#endif /* RT6352 */ + } + else { +#ifdef RT6352 + if (IS_RT6352(pAd)) { + rt6352_dynamic_vga_enable(pAd); + } +#endif /* RT6352 */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DyncVgaEnable_Proc::(enable = %d)\n", pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable)); + + return TRUE; +} + +INT set_dynamic_lna_trigger_timer_proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 val = simple_strtol(arg, 0, 10); + + pAd->chipCap.dynamic_lna_trigger_timer = (val <= 0) ? 1 : val; + + DBGPRINT(RT_DEBUG_OFF, ("%s::(lna trigger timer = %d)\n", + __FUNCTION__, pAd->chipCap.dynamic_lna_trigger_timer)); + + return TRUE; +} + +INT set_agc_vga_clamp_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT32 val = simple_strtol(arg, 0, 10); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + UCHAR agc_vga_ori = 0x48; // default value for most fw + + switch (val) + { + case 1: + agc_vga_ori = 0x3e; + break; + case 2: + agc_vga_ori = 0x34; + break; + case 3: + agc_vga_ori = 0x2a; + break; + case 4: + agc_vga_ori = 0x20; + break; + } + pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 = agc_vga_ori; + pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_1 = agc_vga_ori; + pAd->chipCap.dynamic_chE_mode = 0xEE; // force update VGA + RTMP_ASIC_DYNAMIC_VGA_GAIN_CONTROL(pAd); + } +#endif /* MT76x2 */ + + return TRUE; +} + +INT set_false_cca_hi_th(PRTMP_ADAPTER pAd, PSTRING arg) +{ + INT32 val = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = (val <= 0) ? 800 : val; + +#ifdef RT6352 + if (IS_RT6352(pAd)) { + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = (val <= 0) ? 600 : val; + } +#endif /* RT6352 */ + + DBGPRINT(RT_DEBUG_OFF, ("%s::(false cca high threshould = %d)\n", + __FUNCTION__, pAd->CommonCfg.lna_vga_ctl.nFalseCCATh)); + + return TRUE; +} + +INT Set_Enable_Channel_Timer_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + + UCHAR timer_enable; + UCHAR bbp_val; + UINT32 mac_val; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + timer_enable = (UCHAR) simple_strtol(arg, 0, 10); + + if(timer_enable == 0) { + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val &= (~0x01); + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + } + else { +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= (0x11f); + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + } + else +#endif /* MT76x2 */ + { + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= (0x1f); + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + } + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s() Timer(%s)\n", __FUNCTION__ ,(timer_enable)?"Enable":"Disable")); + + return TRUE; +} + +INT set_false_cca_low_th(PRTMP_ADAPTER pAd, PSTRING arg) +{ + INT32 val = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh = (val <= 0) ? 10 : val; + + DBGPRINT(RT_DEBUG_OFF, ("%s::(false cca low threshould = %d)\n", + __FUNCTION__, pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh)); + + return TRUE; +} +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef THERMAL_PROTECT_SUPPORT +INT set_thermal_protection_criteria_proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + +#ifdef MT76x2 + UINT8 HighEn = 0, LowEn = 0; + CHAR HighTempTh = 0, LowTempTh = 0; + CHAR *Pos = NULL; + + if (IS_MT76x2(pAd)) + { + Pos = arg; + Pos = rtstrstr(Pos, "h_en-"); + if (Pos != NULL) { + Pos = Pos + 5; + HighEn = simple_strtol(Pos, 0, 10); + } + else + goto error; + + Pos = rtstrstr(Pos, "h_th-"); + if (Pos != NULL) { + Pos = Pos + 5; + HighTempTh = simple_strtol(Pos, 0, 10); + } + else + goto error; + + Pos = rtstrstr(Pos, "l_en-"); + if (Pos != NULL) { + Pos = Pos + 5; + LowEn = simple_strtol(Pos, 0, 10); + } + else + goto error; + + Pos = rtstrstr(Pos, "l_th-"); + if (Pos != NULL) { + Pos = Pos + 5; + LowTempTh = simple_strtol(Pos, 0, 10); + } + else + goto error; + + pAd->thermal_HighEn = HighEn; + pAd->thermal_HighTempTh = HighTempTh; + pAd->thermal_LowEn = LowEn; + pAd->thermal_LowTempTh = LowTempTh; + + return TRUE; + } +#endif /* MT76x2 */ + + INT32 criteria = simple_strtol(arg, 0, 10); + + pAd->thermal_pro_criteria = (criteria <= 0) ? 80 : criteria; + + DBGPRINT(RT_DEBUG_ERROR, ("%s::criteria=%d\n", __FUNCTION__, pAd->thermal_pro_criteria)); + + return TRUE; + +error: + DBGPRINT(RT_DEBUG_ERROR, ("%s:: CmdFormat Error\n", __FUNCTION__)); + return TRUE; + +} +#endif /* THERMAL_PROTECT_SUPPORT */ + +#ifdef CONFIG_HOTSPOT +static INT Set_AP_HS_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 EID, + IN PSTRING IE, + IN UINT32 IELen) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; + + switch (EID) + { + case IE_INTERWORKING: + os_alloc_mem(NULL, &pHSCtrl->InterWorkingIE, IELen); + NdisMoveMemory(pHSCtrl->InterWorkingIE, IE, IELen); + pHSCtrl->InterWorkingIELen = IELen; + pHSCtrl->AccessNetWorkType = (*(IE + 2)) & 0x0F; + if (IELen > 3) + { + pHSCtrl->IsHessid = TRUE; + if (IELen == 7) + NdisMoveMemory(pHSCtrl->Hessid, IE + 3, MAC_ADDR_LEN); + else + NdisMoveMemory(pHSCtrl->Hessid, IE + 5 , MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set Interworking IE\n")); + break; + case IE_ADVERTISEMENT_PROTO: + os_alloc_mem(NULL, &pHSCtrl->AdvertisementProtoIE, IELen); + NdisMoveMemory(pHSCtrl->AdvertisementProtoIE, IE, IELen); + pHSCtrl->AdvertisementProtoIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Advertisement Protocol IE\n")); + break; + case IE_QOS_MAP_SET: + { + int tmp = 0; + char *pos = (char *)(IE+2); + os_alloc_mem(NULL, &pHSCtrl->QosMapSetIE, IELen); + NdisMoveMemory(pHSCtrl->QosMapSetIE, IE, IELen); + pHSCtrl->QosMapSetIELen = IELen; + for(tmp = 0;tmp<(IELen-16-2)/2;tmp++) + { + pHSCtrl->DscpException[tmp] = *pos & 0xff; + pHSCtrl->DscpException[tmp] |= (*(pos+1) & 0xff) << 8; + pos += 2; + } + for(tmp = 0;tmp<8;tmp++) + { + pHSCtrl->DscpRange[tmp] = *pos & 0xff; + pHSCtrl->DscpRange[tmp] |= (*(pos+1) & 0xff) << 8; + pos += 2; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set Qos MAP Set IE\n")); + break; + } + case IE_ROAMING_CONSORTIUM: + os_alloc_mem(NULL, &pHSCtrl->RoamingConsortiumIE, IELen); + NdisMoveMemory(pHSCtrl->RoamingConsortiumIE, IE, IELen); + pHSCtrl->RoamingConsortiumIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Roaming Consortium IE\n")); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown IE(EID = %d)\n", __FUNCTION__, EID)); + break; + } + + return TRUE; +} +#endif + +static INT Set_AP_VENDOR_SPECIFIC_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 OUIType, + IN PSTRING IE, + IN UINT32 IELen) +{ +#ifdef CONFIG_HOTSPOT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; +#endif + + switch (OUIType) { +#ifdef CONFIG_HOTSPOT + case OUI_P2P: + os_alloc_mem(NULL, &pHSCtrl->P2PIE, IELen); + NdisMoveMemory(pHSCtrl->P2PIE, IE, IELen); + pHSCtrl->P2PIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set P2P IE\n")); + break; + case OUI_HS2_INDICATION: + os_alloc_mem(NULL, &pHSCtrl->HSIndicationIE, IELen); + NdisMoveMemory(pHSCtrl->HSIndicationIE, IE, IELen); + pHSCtrl->HSIndicationIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set HS2.0 Indication IE\n")); + break; +#endif + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown OUIType = %d\n", __FUNCTION__, OUIType)); + break; + + } + + return TRUE; +} + +#ifdef CONFIG_DOT11V_WNM +static INT Set_AP_WNM_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 EID, + IN PSTRING IE, + IN UINT32 IELen) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[apidx].WNMCtrl; + + switch (EID) + { + case IE_TIME_ADVERTISEMENT: + os_alloc_mem(NULL, &pWNMCtrl->TimeadvertisementIE, IELen); + NdisMoveMemory(pWNMCtrl->TimeadvertisementIE, IE, IELen); + pWNMCtrl->TimeadvertisementIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Time Advertisement IE\n")); + break; + case IE_TIME_ZONE: + os_alloc_mem(NULL, &pWNMCtrl->TimezoneIE, IELen); + NdisMoveMemory(pWNMCtrl->TimezoneIE, IE, IELen); + pWNMCtrl->TimezoneIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Time Zone IE\n")); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown IE(EID = %d)\n", __FUNCTION__, EID)); + break; + } + + return TRUE; +} +#endif + +INT Set_AP_IE( + IN PRTMP_ADAPTER pAd, + IN PSTRING IE, + IN UINT32 IELen) +{ + UINT8 EID; + UINT8 OUIType; + + EID = *IE; + + switch (EID) + { +#ifdef CONFIG_HOTSPOT + case IE_INTERWORKING: + case IE_ADVERTISEMENT_PROTO: + case IE_QOS_MAP_SET: + case IE_ROAMING_CONSORTIUM: + Set_AP_HS_IE(pAd, EID, IE, IELen); + break; +#endif + +#ifdef CONFIG_DOT11V_WNM + case IE_TIME_ADVERTISEMENT: + case IE_TIME_ZONE: + Set_AP_WNM_IE(pAd, EID, IE, IELen); + break; +#endif + case IE_VENDOR_SPECIFIC: + OUIType = *(IE + 5); + Set_AP_VENDOR_SPECIFIC_IE(pAd, OUIType, IE, IELen); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown IE(EID = %d)\n", __FUNCTION__, EID)); + break; + } + + return TRUE; +} + +#ifdef CONFIG_HOTSPOT +INT Send_ANQP_Rsp( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING ANQPRsp, + IN UINT32 ANQPRspLen) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[apidx].GASCtrl; + GAS_EVENT_DATA *Event; + GAS_PEER_ENTRY *GASPeerEntry; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *Tmp; + UINT32 Len = 0, i, QueryRspOffset = 0; + BOOLEAN Cancelled; + BOOLEAN IsFound = FALSE; + + printk("%s\n", __FUNCTION__); + + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Cancel PostReply timer after receiving daemon response */ + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) + { + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + + break; + } + } + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + ANQPRspLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error0; + } + + NdisZeroMemory(Buf, sizeof(*Event) + ANQPRspLen); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = apidx; + Len += 1; + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + if (ANQPRspLen <= pHSCtrl->MMPDUSize) + { + Event->EventType = GAS_RSP; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + printk("GAS RSP DialogToken = %x\n", GASPeerEntry->DialogToken); + Event->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + } + break; + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find peer address in GASPeerList\n", __FUNCTION__)); + goto error1; + } + + Event->u.GAS_RSP_DATA.StatusCode = 0; + Len += 2; + Event->u.GAS_RSP_DATA.GASComebackDelay = 0; + Len += 2; + Event->u.GAS_RSP_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; + Len += 1; + Event->u.GAS_RSP_DATA.QueryRspLen = ANQPRspLen; + Len += 2; + + NdisMoveMemory(Event->u.GAS_RSP_DATA.QueryRsp, ANQPRsp, ANQPRspLen); + Len += ANQPRspLen; + + GASPeerEntry->CurrentState = WAIT_GAS_RSP; + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf,0); + RTMP_MLME_HANDLER(pAd); + } + else + { + Event->EventType = GAS_RSP_MORE; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + + Event->u.GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + + if ((ANQPRspLen % pHSCtrl->MMPDUSize) == 0) + GASPeerEntry->GASRspFragNum = ANQPRspLen / pHSCtrl->MMPDUSize; + else + GASPeerEntry->GASRspFragNum = (ANQPRspLen / pHSCtrl->MMPDUSize) + 1; + + GASPeerEntry->CurrentGASFragNum = 0; + + for (i = 0; i < GASPeerEntry->GASRspFragNum; i++) + { + os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag, sizeof(*GASQueryRspFrag)); + + if (!GASQueryRspFrag) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + goto error1; + } + GASPeerEntry->AllocResource++; + + NdisZeroMemory(GASQueryRspFrag, sizeof(*GASQueryRspFrag)); + + GASQueryRspFrag->GASRspFragID = i; + + if (i < (GASPeerEntry->GASRspFragNum - 1)) + GASQueryRspFrag->FragQueryRspLen = pHSCtrl->MMPDUSize; + else + GASQueryRspFrag->FragQueryRspLen = ANQPRspLen - (pHSCtrl->MMPDUSize * i); + + os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + GASPeerEntry->AllocResource++; + + if (!GASQueryRspFrag->FragQueryRsp) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + goto error2; + } + + NdisMoveMemory(GASQueryRspFrag->FragQueryRsp, &ANQPRsp[QueryRspOffset], + GASQueryRspFrag->FragQueryRspLen); + + QueryRspOffset += GASQueryRspFrag->FragQueryRspLen; + + DlListAddTail(&GASPeerEntry->GASQueryRspFragList, + &GASQueryRspFrag->List); + } + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find peer address in GASPeerList\n", __FUNCTION__)); + goto error1; + } + + Event->u.GAS_RSP_MORE_DATA.StatusCode = 0; + Len += 2; + Event->u.GAS_RSP_MORE_DATA.GASComebackDelay = 1000; + Len += 2; + Event->u.GAS_RSP_MORE_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; + Len += 1; + + GASPeerEntry->CurrentState = WAIT_GAS_RSP; + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP_MORE, Len, Buf, 0); + RTMP_MLME_HANDLER(pAd); + } + + os_free_mem(NULL, Buf); + + return TRUE; + +error2: + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEachSafe(GASQueryRspFrag, Tmp, &GASPeerEntry->GASQueryRspFragList, + GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag); + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); +error1: + os_free_mem(NULL, Buf); +error0: + return FALSE; +} + +#endif + +INT set_power_compensate(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR input = simple_strtol(arg, 0, 10); +#ifdef MT76x2 + if(input!=0) + { + mt76x2_ePA_per_rate_compensate_init(pAd, TRUE); + } + else + { + mt76x2_ePA_per_rate_compensate_init(pAd, FALSE); + } +#endif /* MT76x2 */ + return TRUE; +} + +#ifdef CONFIG_DOT11V_WNM +INT Send_BTM_Req( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING BTMReq, + IN UINT32 BTMReqLen) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + BTM_EVENT_DATA *Event; + BTM_PEER_ENTRY *BTMPeerEntry; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) + { + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error0; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->ControlIndex = APIndex; + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + BTMPeerEntry->DialogToken = 1; + BTMPeerEntry->Priv = pAd; + + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMRspTimer, + GET_TIMER_FUNCTION(WaitPeerBTMRspTimeout), BTMPeerEntry, FALSE); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + BTMReqLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error1; + } + + NdisZeroMemory(Buf, sizeof(*Event) + BTMReqLen); + + Event = (BTM_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = BTM_REQ; + Len += 2; + + Event->u.BTM_REQ_DATA.DialogToken = BTMPeerEntry->DialogToken; + Len += 1; + + Event->u.BTM_REQ_DATA.BTMReqLen = BTMReqLen; + Len += 2; + + NdisMoveMemory(Event->u.BTM_REQ_DATA.BTMReq, BTMReq, BTMReqLen); + Len += BTMReqLen; + + MlmeEnqueue(pAd, BTM_STATE_MACHINE, BTM_REQ, Len, Buf, 0); + + os_free_mem(NULL, Buf); + + return TRUE; + +error1: + if (!IsFound) + os_free_mem(NULL, BTMPeerEntry); +error0: + return FALSE; +} + +#ifdef CONFIG_HOTSPOT_R2 +INT Send_WNM_Notify_Req( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING WNMNotifyReq, + IN UINT32 WNMNotifyReqLen, + IN UINT32 type) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + WNM_NOTIFY_EVENT_DATA *Event; + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + printk("*%d\n", IsFound); + if (!IsFound) + { + os_alloc_mem(NULL, (UCHAR **)&WNMNotifyPeerEntry, sizeof(*WNMNotifyPeerEntry)); + + if (!WNMNotifyPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error0; + } + + NdisZeroMemory(WNMNotifyPeerEntry, sizeof(*WNMNotifyPeerEntry)); + + WNMNotifyPeerEntry->CurrentState = WNM_NOTIFY_REQ; + WNMNotifyPeerEntry->ControlIndex = APIndex; + NdisMoveMemory(WNMNotifyPeerEntry->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + WNMNotifyPeerEntry->DialogToken = 1; + WNMNotifyPeerEntry->Priv = pAd; + + RTMPInitTimer(pAd, &WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, + GET_TIMER_FUNCTION(WaitPeerWNMNotifyRspTimeout), WNMNotifyPeerEntry, FALSE); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->WNMNotifyPeerList, &WNMNotifyPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + WNMNotifyReqLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error1; + } + + //RTMPusecDelay(200000); //200ms + + NdisZeroMemory(Buf, sizeof(*Event) + WNMNotifyReqLen); + + Event = (WNM_NOTIFY_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = type; //WNM_NOTIFY_REQ; + Len += 2; + + Event->u.WNM_NOTIFY_REQ_DATA.DialogToken = WNMNotifyPeerEntry->DialogToken; + Len += 1; + + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen = WNMNotifyReqLen; + Len += 2; + + NdisMoveMemory(Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, WNMNotifyReq, WNMNotifyReqLen); + Len += WNMNotifyReqLen; + + MlmeEnqueue(pAd, WNM_NOTIFY_STATE_MACHINE, WNM_NOTIFY_REQ, Len, Buf, 0); + + os_free_mem(NULL, Buf); + + return TRUE; + +error1: + if (!IsFound) + os_free_mem(NULL, WNMNotifyPeerEntry); +error0: + return FALSE; +} + +INT Send_QOSMAP_Configure( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING QosMapBuf, + IN UINT32 QosMapLen, + IN UINT8 Apidx) +{ + MLME_QOS_ACTION_STRUCT QosMapConfig; + QOSMAP_SET *pQOSMap = &QosMapConfig.QOSMap; + + NdisZeroMemory(&QosMapConfig, sizeof(MLME_QOS_ACTION_STRUCT)); + COPY_MAC_ADDR(QosMapConfig.Addr, PeerMACAddr); + QosMapConfig.ActionField = ACTION_QOSMAP_CONFIG; + QosMapConfig.apidx = Apidx; + pQOSMap->DSCP_Field_Len = QosMapLen; + NdisMoveMemory(pQOSMap->DSCP_Field, QosMapBuf, QosMapLen); + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_QOS_CATE, sizeof(MLME_QOS_ACTION_STRUCT), (PVOID)&QosMapConfig, 0); + RTMP_MLME_HANDLER(pAd); + + return TRUE; +} +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* CONFIG_DOT11V_WNM */ + +#ifdef AIRPLAY_SUPPORT +/* +======================================================================== +Routine Description: + Set airplay function enable. +Arguments: + pAd - WLAN control block pointer + arg - 1: Open airplay function; + - 0: Close airplay function. +Return Value: + 0 :NDIS_STATUS_SUCCESS + 1 :NDIS_STATUS_FAILURE +Note: +======================================================================== +*/ +INT Set_Airplay_Enable(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT enable = 0, apidx = 0; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + + /* + Test IE: + UCHAR AirplayIEFixed[9] = {0xdd, 0x07, 0x00, 0x03, 0x93, 0x01, 0x73, 0x0B, 0x22}; + */ + + enable = simple_strtol(arg, 0, 16); + + if (enable) + { + /*Enable boolean flag*/ + pAd->bAirplayEnable = 1; + pAd->ApCfg.MBSSID[apidx].bBcnSntReq = TRUE; + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + DBGPRINT(RT_DEBUG_OFF, ("###Set_Airplay_Enable...\n")); + } + else /* Disable Airplay*/ + { + /* Close airplay flag*/ + pAd->bAirplayEnable = 0; + DBGPRINT(RT_DEBUG_OFF, ("###Set_Airplay_Enable closed!!!\n")); + } + + return NDIS_STATUS_SUCCESS; +} + +#endif /* AIRPLAY_SUPPORT*/ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_connect.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_connect.c new file mode 100644 index 000000000..cbf925f7f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_connect.c @@ -0,0 +1,1478 @@ +/**************************************************************************** + * 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: + connect.c + + Abstract: + Routines to deal Link UP/DOWN and build/update BEACON frame contents + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 08-04-2003 created for 11g soft-AP + */ + +#include "rt_config.h" + +UCHAR PowerConstraintIE[3] = {IE_POWER_CONSTRAINT, 1, 3}; + + +/* + ========================================================================== + Description: + Used to check the necessary to send Beancon. + return value + 0: mean no necessary. + 0: mean need to send Beacon for the service. + ========================================================================== +*/ +BOOLEAN BeaconTransmitRequired(RTMP_ADAPTER *pAd, INT apidx, MULTISSID_STRUCT *pMbss) +{ +#ifdef WDS_SUPPORT + UCHAR idx; +#endif /* WDS_SUPPORT */ + BOOLEAN result = FALSE; + + do + { +#ifdef WDS_SUPPORT + if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) + break; +#endif /* WDS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + if (isCarrierDetectExist(pAd) == TRUE) + break; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#ifdef QUIET_SUPPORT + if ((apidx < pAd->ApCfg.BssidNum) + && IS_RRM_QUIET(pAd, apidx)) + break; +#endif /* QUIET_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + + if (pMbss->BcnBufIdx >= HW_BEACON_MAX_NUM) + break; + if (pAd->BeaconOffset[pMbss->BcnBufIdx] == 0) + break; + + if (apidx == MAIN_MBSSID) + { + if (pMbss->bBcnSntReq == TRUE) + { + result = TRUE; + break; + } +#ifdef WDS_SUPPORT + for (idx = 0; idx < MAX_WDS_ENTRY; idx++) + { + if ((pAd->WdsTab.WdsEntry[idx].wdev.if_dev != NULL) + && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[idx].wdev.if_dev))) + { + result = TRUE; + break; + } + } +#endif /* WDS_SUPPORT */ + } + else + { + if (pMbss->bBcnSntReq == TRUE) + result = TRUE; + } + } + while (FALSE); + + return result; +} + + +/* + ========================================================================== + Description: + Pre-build a BEACON frame in the shared memory + ========================================================================== +*/ +VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) +{ + UCHAR DsLen = 1, SsidLen; + HEADER_802_11 BcnHdr; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; +#if defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) + UINT i; +#endif /* defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) */ + HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + UCHAR PhyMode, SupRateLen; + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + if(!BeaconTransmitRequired(pAd, apidx, pMbss)) + return; + + PhyMode = pMbss->wdev.PhyMode; + + if (pMbss->bHideSsid) + SsidLen = 0; + else + SsidLen = pMbss->SsidLen; + + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + + /* for update framelen to TxWI later. */ + SupRateLen = pAd->CommonCfg.SupRateLen; + if (PhyMode == WMODE_B) + SupRateLen = 4; + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pMbss->CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pMbss->Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pAd->CommonCfg.SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + END_OF_ARGS); + + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) + { + ULONG TmpLen; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += TmpLen; + } + + + /* add country IE, power constraint IE */ + if (pAd->CommonCfg.bCountryFlag) + { + ULONG TmpLen, TmpLen2=0; + UCHAR *TmpFrame = NULL; + UCHAR CountryIe = IE_COUNTRY; + + os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); + if (TmpFrame != NULL) + { + NdisZeroMemory(TmpFrame, 256); + + /* prepare channel information */ +#ifdef EXT_BUILD_CHANNEL_LIST + BuildBeaconChList(pAd, TmpFrame, &TmpLen2); +#else + { + UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx) + && (pAd->CommonCfg.RegulatoryClass[0] != 0)) + { + TmpLen2 = 0; + NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); + RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); + } +#endif /* DOT11K_RRM_SUPPORT */ + + /* need to do the padding bit check, and concatenate it */ + if ((TmpLen2%2) == 0) + { + UCHAR TmpLen3 = TmpLen2+4; + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 3, pAd->CommonCfg.CountryCode, + TmpLen2+1, TmpFrame, + END_OF_ARGS); + } + else + { + UCHAR TmpLen3 = TmpLen2+3; + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 3, pAd->CommonCfg.CountryCode, + TmpLen2, TmpFrame, + END_OF_ARGS); + } + FrameLen += TmpLen; + + os_free_mem(NULL, TmpFrame); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { + InsertTpcReportIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); + RRM_InsertRRMEnCapIE(pAd, pBeaconFrame+FrameLen, &FrameLen, apidx); + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* AP Channel Report */ +#ifdef DOT11K_RRM_SUPPORT + for (i=0; iCommonCfg.RegulatoryClass[i] == 0) + break; + + InsertChannelRepIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + (PSTRING)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[i]); + + } +#else + { + UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; + ULONG TmpLen; + + /* + 802.11n D2.0 Annex J, USA regulatory + class 32, channel set 1~7 + class 33, channel set 5-11 + */ + UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; + UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; + UCHAR rclasslen = 8; /*sizeof(rclass32); */ + if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass32, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass33, + END_OF_ARGS); + FrameLen += TmpLen; + } + } +#endif + +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + /* The Mobility Domain information element (MDIE) is present in Beacon + ** frame when dot11FastBssTransitionEnable is set to true. */ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + FT_CAP_AND_POLICY FtCap; + NdisZeroMemory(&FtCap, sizeof(FT_CAP_AND_POLICY)); + FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + FT_InsertMdIE(pAd, pBeaconFrame + FrameLen, &FrameLen, + pFtCfg->FtMdId, FtCap); + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef SPECIFIC_TX_POWER_SUPPORT + /* Specific Power for Long-Range Beacon */ + if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && + (BeaconTransmit.field.MODE == MODE_CCK)*/) + { + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + BeaconTransmit.word = 0; + + RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, + FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, &BeaconTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT +#ifdef RTMP_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) + pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) + pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; +#endif /* RLT_MAC */ +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* + step 6. move BEACON TXD and frame content to on-chip memory + */ + updateAllBeacon(pAd, apidx, FrameLen); + + pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; + pMbss->CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; +} + +void updateAllBeacon(RTMP_ADAPTER *pAd, INT apidx, ULONG FrameLen) +{ + UCHAR *ptr = NULL; + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + UINT32 longValue, reg_base; + UINT i = 0; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + ptr = (PUCHAR)&pAd->BeaconTxWI; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif + + + reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx]; + for (i=0; i < TXWISize; i+=4) + { + longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); + ptr += 4; + } + + /* update BEACON frame content. start right after the TXWI field. */ + ptr = (PUCHAR)pMbss->BeaconBuf; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + + reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx] + TXWISize; + for (i= 0; i< FrameLen; i+=4) + { + longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); + ptr += 4; + } + +} +/* + ========================================================================== + Description: + Update the BEACON frame in the shared memory. Because TIM IE is variable + length. other IEs after TIM has to shift and total frame length may change + for each BEACON period. + Output: + pAd->ApCfg.MBSSID[apidx].CapabilityInfo + pAd->ApCfg.ErpIeContent + ========================================================================== +*/ +VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) +{ + UCHAR *pBeaconFrame; + UCHAR *ptr; + ULONG FrameLen; + ULONG UpdatePos; + UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; + UCHAR ID_1B, TimFirst, TimLast, *pTim; + MULTISSID_STRUCT *pMbss; + COMMON_CONFIG *pComCfg; + UCHAR PhyMode; + BOOLEAN bHasWpsIE = FALSE; + UINT i; + HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + struct wifi_dev *wdev; +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + pComCfg = &pAd->CommonCfg; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + + pBeaconFrame = (UCHAR *)&pMbss->BeaconBuf[0]; + FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; + PhyMode = wdev->PhyMode; + + if(!BeaconTransmitRequired(pAd, apidx, pMbss)) + return; + + /* + step 1 - update BEACON's Capability + */ + ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; + *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); + *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); + + /* + step 2 - update TIM IE + TODO: enlarge TIM bitmap to support up to 64 STAs + TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time + */ + ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; + *ptr = IE_TIM; + *(ptr + 2) = pAd->ApCfg.DtimCount; + *(ptr + 3) = pAd->ApCfg.DtimPeriod; + + /* find the smallest AID (PS mode) */ + TimFirst = 0; /* record first TIM byte != 0x00 */ + TimLast = 0; /* record last TIM byte != 0x00 */ + pTim = pMbss->TimBitmaps; + + for(ID_1B=0; ID_1BApCfg.DtimCount == 0) + *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); + + /* adjust BEACON length according to the new TIM */ + FrameLen += (2 + *(ptr+1)); + + /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ + /* sync the order with BRCM's AP. */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + RSNIe = IE_WPA; + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + RSNIe = IE_WPA2; +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || + (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + RSNIe = IE_WAPI; +#endif /* WAPI_SUPPORT */ + + /* Append RSN_IE when WPA OR WPAPSK, */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + ULONG TmpLen; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pMbss->RSNIE_Len[0], + pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], + 1, &RSNIe2, + 1, &pMbss->RSNIE_Len[1], + pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], + END_OF_ARGS); + FrameLen += TmpLen; + } + else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + ULONG TmpLen; +#ifdef CONFIG_HOTSPOT_R2 + extern UCHAR OSEN_IE[]; + extern UCHAR OSEN_IELEN; + + if ((pMbss->HotSpotCtrl.HotSpotEnable == 0) && (pMbss->HotSpotCtrl.bASANEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2)) + { + RSNIe = IE_WPA; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &OSEN_IELEN, + OSEN_IELEN, OSEN_IE, + END_OF_ARGS); + FrameLen += TmpLen; + } + else +#endif /* CONFIG_HOTSPOT_R2 */ + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pMbss->RSNIE_Len[0], + pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], + END_OF_ARGS); + FrameLen += TmpLen; + } + } + +#ifdef HOSTAPD_SUPPORT + if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) + bHasWpsIE = TRUE; +#endif + +#ifdef WSC_AP_SUPPORT + /* add Simple Config Information Element */ + if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) + bHasWpsIE = TRUE; +#endif /* WSC_AP_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(pMbss->SmartMeshCfg.bSupportHiddenWPS) + { + bHasWpsIE = FALSE; + if(pMbss->WscControl.bRunningHiddenWPS) + Set_HiddenWps_State(&pMbss->SmartMeshCfg, HIDDEN_WPS_STATE_RUNNING); + else + Set_HiddenWps_State(&pMbss->SmartMeshCfg, HIDDEN_WPS_STATE_STOP); + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + if (bHasWpsIE) + { + ULONG WscTmpLen = 0; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, + pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } + +#ifdef WSC_AP_SUPPORT + if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) +#ifdef DOT1X_SUPPORT + && (pMbss->wdev.IEEE8021X == FALSE) +#endif /* DOT1X_SUPPORT */ + && (pMbss->wdev.WepStatus == Ndis802_11WEPEnabled) +#ifdef SMART_MESH_HIDDEN_WPS + && !pMbss->SmartMeshCfg.bSupportHiddenWPS +#endif /* SMART_MESH_HIDDEN_WPS */ + ) + { + /* + Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based + or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP + network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't + receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and + prompt user for the WEP key. <> + A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. + The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) + http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp + */ + ULONG TempLen = 0; + UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, + 7, PROVISION_SERVICE_IE, + END_OF_ARGS); + FrameLen += TempLen; + } +#endif /* WSC_AP_SUPPORT */ + + + /* Update ERP */ + if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) + { + /* fill ERP IE */ + ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ + *ptr = IE_ERP; + *(ptr + 1) = 1; + *(ptr + 2) = pAd->ApCfg.ErpIeContent; + FrameLen += 3; + } + +#ifdef A_BAND_SUPPORT + /* fill up Channel Switch Announcement Element */ + if (((pComCfg->Channel > 14) + && (pComCfg->bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) +#ifdef CUSTOMER_DCC_FEATURE + || (pComCfg->channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) +#endif + ) + { + ptr = pBeaconFrame + FrameLen; + *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + *(ptr + 1) = 3; + *(ptr + 2) = 1; + *(ptr + 3) = pComCfg->Channel; +#ifdef CUSTOMER_DCC_FEATURE + if(pComCfg->channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) + *(ptr + 4) = (pComCfg->channelSwitch.CHSWPeriod - pComCfg->channelSwitch.CHSWCount); + else +#endif + *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); + ptr += 5; + FrameLen += 5; + +#ifdef DOT11_N_SUPPORT + /* Extended Channel Switch Announcement Element */ + if (pComCfg->bExtChannelSwitchAnnouncement) + { + HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; + build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); + NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); + ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); + FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode)) { + INT tp_len, wb_len = 0; + UCHAR *ch_sw_wrapper; + VHT_TXPWR_ENV_IE txpwr_env; + + + *ptr = IE_CH_SWITCH_WRAPPER; + ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length + ptr += 2; // skip len + + if (pComCfg->RegTransmitSetting.field.BW == BW_40) { + WIDE_BW_CH_SWITCH_ELEMENT wb_info; + + *ptr = IE_WIDE_BW_CH_SWITCH; + //*(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); + *(ptr + 1) = 3; + ptr += 2; + NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); + if (pComCfg->vht_bw == VHT_BW_2040) + wb_info.new_ch_width = 0; + else + wb_info.new_ch_width = 1; + + if (pComCfg->vht_bw == VHT_BW_80) { + wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); + wb_info.center_freq_2 = 0; + } + NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); + //wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); + wb_len = 3; + ptr += wb_len; + wb_len += 2; + } + + *ptr = IE_VHT_TXPWR_ENV; + NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); + tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); + *(ptr + 1) = tp_len; + ptr += 2; + NdisMoveMemory(ptr, &txpwr_env, tp_len); + ptr += tp_len; + tp_len += 2; + *ch_sw_wrapper = wb_len + tp_len; + + FrameLen += (2 + wb_len + tp_len); + } +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* step 5. Update HT. Since some fields might change in the same BSS. */ + if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + /*UCHAR i; */ + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +/* USHORT b2lTmp, b2lTmp2; // no use */ +#endif + + /* add HT Capability IE */ + HtLen = sizeof(pComCfg->HtCapability); + HtLen1 = sizeof(pComCfg->AddHTInfo); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pComCfg->HtCapability, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pComCfg->AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + +#ifdef SMART_MESH + SMART_MESH_INSERT_IE(pAd->ApCfg.MBSSID[apidx].SmartMeshCfg, + pBeaconFrame, + FrameLen, + SM_IE_BEACON); +#endif /* SMART_MESH */ + +#ifdef DOT11N_DRAFT3 + /* + P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE + */ + if ((pComCfg->Channel <= 14) && + (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) + { + OVERLAP_BSS_SCAN_IE OverlapScanParam; + ULONG TmpLen; + UCHAR OverlapScanIE, ScanIELen; + + OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; + ScanIELen = 14; + OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); + OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); + OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); + OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); + OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); + OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); + OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &OverlapScanIE, + 1, &ScanIELen, + ScanIELen, &OverlapScanParam, + END_OF_ARGS); + + FrameLen += TmpLen; + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + { + ULONG TmpLen; + + /* Indication element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.HSIndicationIELen, + pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Interworking element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.InterWorkingIELen, + pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Advertisement Protocol element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.AdvertisementProtoIELen, + pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Roaming Consortium element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.RoamingConsortiumIELen, + pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* P2P element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.P2PIELen, + pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); + + FrameLen += TmpLen; + + } +#endif + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) + { + int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); + FrameLen += _len; + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + + /* 7.3.2.27 Extended Capabilities IE */ + { + ULONG TmpLen, infoPos; + PUCHAR pInfo; + UCHAR extInfoLen; + BOOLEAN bNeedAppendExtIE = FALSE; + EXT_CAP_INFO_ELEMENT extCapInfo; + + + extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D1.10, HT Information Exchange Support */ + if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && + (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && + (pComCfg->bBssCoexEnable == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + if (pMbss->WNMCtrl.ProxyARPEnable) + extCapInfo.proxy_arp = 1; +#ifdef CONFIG_HOTSPOT_R2 + if (pMbss->WNMCtrl.WNMNotifyEnable) + extCapInfo.wnm_notification = 1; + + if (pMbss->HotSpotCtrl.QosMapEnable) + extCapInfo.qosmap= 1; +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* CONFIG_DOT11V_WNM */ + +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + extCapInfo.interworking = 1; +#endif /* CONFIG_HOTSPOT */ + +#ifdef DOT11V_WNM_SUPPORT + if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, apidx)) + { + extCapInfo.BssTransitionManmt = 1; + } + if (IS_WNMDMS_SUPPORT(pAd, apidx)) + { + extCapInfo.DMSSupport = 1; + } +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14)) + extCapInfo.operating_mode_notification = 1; +#endif /* DOT11_VHT_AC */ + + pInfo = (PUCHAR)(&extCapInfo); + for (infoPos = 0; infoPos < extInfoLen; infoPos++) + { + if (pInfo[infoPos] != 0) + { + bNeedAppendExtIE = TRUE; + break; + } + } + + if (bNeedAppendExtIE == TRUE) + { +#ifdef RT_BIG_ENDIAN + *((UINT32*)(pInfo)) = SWAP32(*((UINT32*)(pInfo))); + *((UINT32*)(pInfo+4)) = SWAP32(*((UINT32*)(pInfo+4))) +#endif + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + +#ifdef WFA_VHT_PF + if (pAd->force_vht_op_mode == TRUE) + { + ULONG TmpLen; + UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; + OPERATING_MODE operating_mode; + + operating_mode.rx_nss_type = 0; + operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); + operating_mode.ch_width = pAd->vht_pf_op_bw; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &operating_ie, + 1, &operating_len, + 1, &operating_mode, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* WFA_VHT_PF */ + + /* add WMM IE here */ + if (pMbss->wdev.bWmmCapable) + { + ULONG TmpLen; + UCHAR i; + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + UINT8 AIFSN[4]; + + WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; + +#ifdef UAPSD_SUPPORT + UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); +#endif /* UAPSD_SUPPORT */ + + NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); + + + for (i=QID_AC_BE; i<=QID_AC_VO; i++) + { + WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ + ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ + (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ + WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ + (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ + WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ + WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ + } + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 26, WmeParmIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef AP_QLOAD_SUPPORT + if (pAd->phy_ctrl.FlgQloadEnable != 0) + { +#ifdef CONFIG_HOTSPOT_R2 + if (pMbss->HotSpotCtrl.QLoadTestEnable == 1) + FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pBeaconFrame+FrameLen, apidx); + else if (pMbss->HotSpotCtrl.QLoadTestEnable == 0) +#endif + FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); + } +#endif /* AP_QLOAD_SUPPORT */ + +#ifdef A_BAND_SUPPORT + /* + Only 802.11a APs that comply with 802.11h are required to include a + Power Constrint Element(IE=32) in beacons and probe response frames + */ + if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) +#ifdef DOT11K_RRM_SUPPORT + || IS_RRM_ENABLE(pAd, apidx) +#endif /* DOT11K_RRM_SUPPORT */ + ) + { + ULONG TmpLen; + UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; + UINT8 PwrConstraintLen = 1; + UINT8 PwrConstraint = pComCfg->PwrConstraint; + + /* prepare power constraint IE */ + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &PwrConstraintIE, + 1, &PwrConstraintLen, + 1, &PwrConstraint, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode)) { + ULONG TmpLen; + UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; + UINT8 ie_len; + VHT_TXPWR_ENV_IE txpwr_env; + + ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &vht_txpwr_env_ie, + 1, &ie_len, + ie_len, &txpwr_env, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_VHT_AC */ + + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { + PRRM_QUIET_CB pQuietCB = &pMbss->RrmCfg.QuietCB; + RRM_InsertQuietIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + pQuietCB->QuietCnt ,pQuietCB->QuietPeriod, + pQuietCB->QuietDuration, pQuietCB->QuietOffset); + +#ifndef APPLE_11K_IOT + /* Insert BSS AC Access Delay IE. */ + RRM_InsertBssACDelayIE(pAd, pBeaconFrame+FrameLen, &FrameLen); + + /* Insert BSS Available Access Capacity IE. */ + RRM_InsertBssAvailableACIE(pAd, pBeaconFrame+FrameLen, &FrameLen); +#endif /* !APPLE_11K_IOT */ + + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(PhyMode) && + (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + /* add HT Capability IE */ + HtLen = sizeof(pComCfg->HtCapability); + HtLen1 = sizeof(pComCfg->AddHTInfo); + + if (pAd->bBroadComHT == TRUE) + { + UCHAR epigram_ie_len; + UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; + UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; + + + epigram_ie_len = HtLen + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &pComCfg->HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + + epigram_ie_len = HtLen1 + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &pComCfg->AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + } + } +#endif /* DOT11_N_SUPPORT */ + + /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ +{ + ULONG TmpLen; + UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; + + if (pComCfg->bAggregationCapable) + RalinkSpecificIe[5] |= 0x1; + if (pComCfg->bPiggyBackCapable) + RalinkSpecificIe[5] |= 0x2; +#ifdef DOT11_N_SUPPORT + if (pComCfg->bRdg) + RalinkSpecificIe[5] |= 0x4; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) + RalinkSpecificIe[5] |= 0x8; +#endif /* DOT11_VHT_AC */ + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + +} + +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + { + ULONG AirplayTmpLen = 0; + + /*User user setting IE*/ + if (pAd->pAirplayIe && (pAd->AirplayIeLen != 0)) + { + //hex_dump("[BCN]IE:", pAd->pAirplayIe , pAd->AirplayIeLen); + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &AirplayTmpLen, + pAd->AirplayIeLen, pAd->pAirplayIe, + END_OF_ARGS); + FrameLen += AirplayTmpLen; + } + + } +#endif /* AIRPLAY_SUPPORT*/ + + /* add Mediatek-specific IE here */ + { + ULONG TmpLen = 0; + UCHAR MediatekSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0xe7, 0x00, 0x00, 0x00, 0x00}; + +#ifdef DOT11_VHT_AC + if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) + MediatekSpecificIe[5] |= 0x8; +#endif /* DOT11_VHT_AC */ + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 9, MediatekSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + + /* step 6. Since FrameLen may change, update TXWI. */ +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) { + BeaconTransmit.field.MODE = MODE_OFDM; + BeaconTransmit.field.MCS = MCS_RATE_6; + } +#endif /* A_BAND_SUPPORT */ + +#ifdef SPECIFIC_TX_POWER_SUPPORT + /* Specific Power for Long-Range Beacon */ + if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && + (BeaconTransmit.field.MODE == MODE_CCK)*/) + { + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, RESERVED_WCID, + FrameLen, PID_MGMT, 0 /*QID_MGMT*/, 0, IFS_HTTXOP, &BeaconTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT +#ifdef RTMP_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) + pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) + pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; +#endif /* RLT_MAC */ +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* step 7. move BEACON TXWI and frame content to on-chip memory */ + RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); + +#ifdef CUSTOMER_DCC_FEATURE + { + HTTRANSMIT_SETTING HTSetting; + UINT32 Index; + MULTISSID_STRUCT *pMbss = NULL; + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = BeaconTransmit.field.MODE; + HTSetting.field.BW = BeaconTransmit.field.BW; + HTSetting.field.ShortGI = BeaconTransmit.field.ShortGI; + HTSetting.field.MCS = BeaconTransmit.field.MCS; + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + (RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev))) + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + GetMultShiftFactorIndex(HTSetting, &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, FrameLen, pMbss, NULL); + } + } +#endif +} + + +/* + ========================================================================== + Description: + Pre-build All BEACON frame in the shared memory + ========================================================================== +*/ +static UCHAR GetBcnNum(RTMP_ADAPTER *pAd) +{ + int i; + int NumBcn; + + NumBcn = 0; + for (i=0; iApCfg.BssidNum; i++) + { + if (pAd->ApCfg.MBSSID[i].bBcnSntReq) + { + pAd->ApCfg.MBSSID[i].BcnBufIdx = NumBcn; + NumBcn ++; + } + } + + + return NumBcn; +} + + +VOID APMakeAllBssBeacon(RTMP_ADAPTER *pAd) +{ + INT i, j; + UINT32 regValue; + UCHAR NumOfMacs; + UCHAR NumOfBcns; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + /* before MakeBssBeacon, clear all beacon TxD's valid bit */ + /* Note: can not use MAX_MBSSID_NUM here, or + 1. when MBSS_SUPPORT is enabled; + 2. MAX_MBSSID_NUM will be 8; + 3. if HW_BEACON_OFFSET is 0x0200, + we will overwrite other shared memory SRAM of chip */ + /* use pAd->ApCfg.BssidNum to avoid the case is best */ + + /* choose the Beacon number */ + NumOfBcns = GetBcnNum(pAd); + + for (i=0; iBeaconOffset[i] + j, 0, 4); + } + } + + + for(i=0; iApCfg.BssidNum; i++) + { + APMakeBssBeacon(pAd, i); + } + + RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); + regValue &= 0x0000FFFF; + + + /* + Note: + 1.The MAC address of Mesh and AP-Client link are different from Main BSSID. + 2.If the Mesh link is included, its MAC address shall follow the last MBSSID's MAC by increasing 1. + 3.If the AP-Client link is included, its MAC address shall follow the Mesh interface MAC by increasing 1. + */ + NumOfMacs = pAd->ApCfg.BssidNum + MAX_MESH_NUM + MAX_APCLI_NUM; + + + /* set Multiple BSSID mode */ + if (NumOfMacs <= 1) + { + pAd->ApCfg.MacMask = ~(1-1); + /*regValue |= 0x0; */ + } + else if (NumOfMacs <= 2) + { +#ifndef NEW_MBSSID_MODE + if ((pAd->CurrentAddress[5] % 2 != 0) + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); +#endif + regValue |= (1<<16); + pAd->ApCfg.MacMask = ~(2-1); + } + else if (NumOfMacs <= 4) + { +#ifndef NEW_MBSSID_MODE + if (pAd->CurrentAddress[5] % 4 != 0) + DBGPRINT(RT_DEBUG_ERROR, ("The 4-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 4\n")); +#endif + regValue |= (2<<16); + pAd->ApCfg.MacMask = ~(4-1); + } + else if (NumOfMacs <= 8) + { +#ifndef NEW_MBSSID_MODE + if (pAd->CurrentAddress[5] % 8 != 0) + DBGPRINT(RT_DEBUG_ERROR, ("The 8-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 8\n")); +#endif + regValue |= (3<<16); + pAd->ApCfg.MacMask = ~(8-1); + } + else if (NumOfMacs <= 16) + { + /* Set MULTI_BSSID_MODE_BIT4 in MAC register 0x1014 */ + regValue |= (1<<22); + pAd->ApCfg.MacMask = ~(16-1); + } + + /* set Multiple BSSID Beacon number */ + if (NumOfBcns > 1) + { + if (NumOfBcns > 8) + regValue |= (((NumOfBcns - 1) >> 3) << 23); + regValue |= (((NumOfBcns - 1) & 0x7) << 18); + } + + /* set as 0/1 bit-21 of MAC_BSSID_DW1(offset: 0x1014) + to disable/enable the new MAC address assignment. */ + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + regValue |= (1 << 21); +#ifdef ENHANCE_NEW_MBSSID_MODE + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE2) + regValue |= (1 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE3) + regValue |= (2 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE4) + regValue |= (3 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE5) + regValue |= (4 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE6) + regValue |= (5 << 24); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); + +#ifdef HDR_TRANS_SUPPORT + /* + point WCID MAC table to 0x1800 + This is for debug. + But HDR_TRANS doesn't work if you remove it. + Check after IC formal release. + */ + regValue |= 0x18000000; + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, regValue); +#endif /* HDR_TRANS_SUPPORT */ + + +} + + +/* + ========================================================================== + Description: + Pre-build All BEACON frame in the shared memory + ========================================================================== +*/ +VOID APUpdateAllBeaconFrame(RTMP_ADAPTER *pAd) +{ + INT i; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + BOOLEAN FlgQloadIsAlarmIssued = FALSE; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + if (pAd->ApCfg.DtimCount == 0) + pAd->ApCfg.DtimCount = pAd->ApCfg.DtimPeriod - 1; + else + pAd->ApCfg.DtimCount -= 1; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* QLOAD ALARM */ +#ifdef AP_QLOAD_SUPPORT + FlgQloadIsAlarmIssued = QBSS_LoadIsAlarmIssued(pAd); +#endif /* AP_QLOAD_SUPPORT */ + + if ((pAd->ApCfg.DtimCount == 0) && + (((pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_INFO_SYNC) && + (pAd->CommonCfg.bForty_Mhz_Intolerant == FALSE)) || + (FlgQloadIsAlarmIssued == TRUE))) + { + UCHAR prevBW, prevExtChOffset; + DBGPRINT(RT_DEBUG_TRACE, ("DTIM Period reached, BSS20WidthReq=%d, Intolerant40=%d!\n", + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq, pAd->CommonCfg.LastBSSCoexist2040.field.Intolerant40)); + pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_INFO_SYNC); + + prevBW = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + prevExtChOffset = pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset; + + if (pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq || + pAd->CommonCfg.LastBSSCoexist2040.field.Intolerant40 || + (pAd->MacTab.fAnyStaFortyIntolerant == TRUE) || + (FlgQloadIsAlarmIssued == TRUE)) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + } + else + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = pAd->CommonCfg.RegTransmitSetting.field.BW; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + } + DBGPRINT(RT_DEBUG_TRACE,("\tNow RecomWidth=%d, ExtChanOffset=%d, prevBW=%d, prevExtOffset=%d\n", + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset, + prevBW, prevExtChOffset)); + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_NOTIFY; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + for(i=0; iApCfg.BssidNum; i++) + { + APUpdateBeaconFrame(pAd, i); + } +} + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_data.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_data.c new file mode 100644 index 000000000..cc981bd82 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_data.c @@ -0,0 +1,6637 @@ +/* + *************************************************************************** + * 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_data.c + + Abstract: + Data path subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + +#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) +#define IS_BROADCAST_MAC_ADDR(Addr) ((((Addr[0]) & 0xff) == 0xff)) + +#ifdef CONFIG_HOTSPOT +extern BOOLEAN hotspot_rx_handler(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk); +#endif /* CONFIG_HOTSPOT */ + + +INT ApAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + IN UCHAR *pWcid) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + MAC_TABLE_ENTRY *pEntry = NULL; +#ifdef MBSS_SUPPORT + UCHAR IdBss; +#endif /* MBSS_SUPPORT */ + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + +#ifdef MBSS_SUPPORT + /* 0 is main BSS, FIRST_MBSSID = 1 */ + // TODO: shiang-6590, for old coding, will RTMP_SET_PACKET_NET_DEVICE_MBSSID(), how about now?? + for(IdBss= MAIN_MBSSID; IdBss < pAd->ApCfg.BssidNum; IdBss++) + { + if (wdev == &pAd->ApCfg.MBSSID[IdBss].wdev) + { + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, IdBss); + break; + } + } + + ASSERT(IdBss < pAd->ApCfg.BssidNum); +#endif /* MBSS_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + //CFG_TODO: POS NO GOOD + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP) + { + RTMP_SET_PACKET_OPMODE(pPacket, OPMODE_AP); + } +#endif /* RT_CFG80211_SUPPORT */ + + if (MAC_ADDR_IS_GROUP(pSrcBufVA)) /* mcast & broadcast address */ + { +#ifdef MWDS + /* If we check an ethernet source move to this device, we should remove it. */ + MWDSProxyEntryDelete(pAd, (pSrcBufVA + MAC_ADDR_LEN)); +#endif /* MWDS */ + *pWcid = MCAST_WCID; + return TRUE; + } + else /* unicast address */ + { + pEntry = MacTableLookup(pAd, pSrcBufVA); + if (pEntry && (pEntry->Sst == SST_ASSOC)) + { + *pWcid = (UCHAR)pEntry->wcid; + return TRUE; + } + +#ifdef CLIENT_WDS + if (pEntry == NULL) { + SST Sst; + USHORT Aid; + UCHAR PsMode, Rate; + + PUCHAR pEntryAddr = CliWds_ProxyLookup(pAd, pSrcBufVA); + if (pEntryAddr != NULL) { + pEntry = APSsPsInquiry(pAd, pEntryAddr, &Sst, &Aid, &PsMode, &Rate); + if ((pEntry && (pEntry->Sst == SST_ASSOC)) { + *pWcid = (UCHAR)Aid; + return TRUE; + } + } + } +#endif /* CLIENT_WDS */ + +#ifdef MWDS + if (pEntry == NULL) { + UCHAR Wcid; + /* If we check an ethernet source move to this device, we should remove it. */ + MWDSProxyEntryDelete(pAd, (pSrcBufVA + MAC_ADDR_LEN)); + if (MWDSProxyLookup(pAd, pSrcBufVA, FALSE, &Wcid)) { + if (VALID_WCID(Wcid)) + pEntry = &pAd->MacTab.Content[Wcid]; + + if (pEntry && (pEntry->Sst == SST_ASSOC)){ + *pWcid = Wcid; + return TRUE; + } + } + } +#endif /* MWDS */ + } + + return FALSE; +} + + +enum pkt_tx_status{ + PKT_SUCCESS = 0, + INVALID_PKT_LEN = 1, + INVALID_TR_WCID = 2, + INVALID_TR_ENTRY = 3, + INVALID_WDEV = 4, + INVALID_ETH_TYPE = 5, + DROP_PORT_SECURE = 6, + DROP_PSQ_FULL = 7, + DROP_TXQ_FULL = 8, + DROP_TX_JAM = 9, + DROP_TXQ_ENQ_FAIL = 10, +}; + +struct reason_id_str{ + INT id; + PSTRING code_str; +}; + +/* + ======================================================================== + Routine Description: + This routine is used to do packet parsing and classification for Tx packet + to AP device, and it will en-queue packets to our TxSwQ depends on AC + class. + + Arguments: + pAd Pointer to our adapter + pPacket Pointer to send packet + + Return Value: + NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQ. + NDIS_STATUS_FAILURE If failed to do en-queue. + + pre: Before calling this routine, caller should have filled the following fields + + pPacket->MiniportReserved[6] - contains packet source + pPacket->MiniportReserved[5] - contains RA's WDS index (if RA on WDS link) or AID + (if RA directly associated to this AP) + post:This routine should decide the remaining pPacket->MiniportReserved[] fields + before calling APHardTransmit(), such as: + + pPacket->MiniportReserved[4] - Fragment # and User PRiority + pPacket->MiniportReserved[7] - RTS/CTS-to-self protection method and TX rate + + Note: + You only can put OS-indepened & AP related code in here. +======================================================================== +*/ +INT APSendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen, AllowFragSize; + UCHAR NumberOfFrag; + UCHAR QueIdx; + UCHAR UserPriority, PsMode = PWR_ACTIVE; + UCHAR Wcid; + unsigned long IrqFlags; +#ifdef IGMP_SNOOP_SUPPORT + INT InIgmpGroup = IGMP_NONE; + MULTICAST_FILTER_TABLE_ENTRY *pGroupEntry = NULL; +#endif /* IGMP_SNOOP_SUPPORT */ + MAC_TABLE_ENTRY *pMacEntry = NULL; + struct wifi_dev *wdev; + +#ifdef APCLI_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[0]; +#endif + BOOLEAN is_mcast = FALSE; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if ((pSrcBufVA == NULL) || (SrcBufLen <= 14)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_ERROR, ("%s():pkt error(%p, %d)\n", + __FUNCTION__, pSrcBufVA, SrcBufLen)); + return NDIS_STATUS_FAILURE; + } + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + pMacEntry = &pAd->MacTab.Content[Wcid]; + + if (Wcid != MCAST_WCID) + { + wdev = pMacEntry->wdev; + } + else // don't pass pMacEntry->wdev to RTMPCheckEtherType(), when Wcid is MCAST_WCID + { + UCHAR IfIdx = 0; + IfIdx = RTMP_GET_PACKET_WDEV(pPacket); + if ((IfIdx < WDEV_NUM_MAX) && (pAd->wdev_list[IfIdx] != NULL)) { + wdev = pAd->wdev_list[IfIdx]; + } + else + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } + + /* + Check the Ethernet Frame type, and set RTMP_SET_PACKET_SPECIFIC flags + Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). + */ + UserPriority = 0; + QueIdx = QID_AC_BE; + if (RTMPCheckEtherType(pAd, pPacket, pMacEntry, wdev, &UserPriority, &QueIdx) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + +#ifdef CONFIG_HOTSPOT + if (wdev->wdev_type == WDEV_TYPE_AP) + { + /* + Re-check the wcid, it maybe broadcast to unicast by RTMPCheckEtherType. + */ + if (Wcid != RTMP_GET_PACKET_WCID(pPacket)) + { + Wcid = RTMP_GET_PACKET_WCID(pPacket); + pMacEntry = &pAd->MacTab.Content[Wcid]; + wdev = pMacEntry->wdev; + } + } +#endif /* CONFIG_HOTSPOT */ + + if (IS_VALID_ENTRY(pMacEntry) || (Wcid == MCAST_WCID)) + { + PsMode = pMacEntry->PsMode; + + // TODO: shiang-6590, how to disinguish the MCAST/BCAST from different BSS if we don't have RTMP_GET_PACKET_NET_DEVICE_MBSSID?? + // TODO: shiang-6590, use wdev->allow_data_tx replace (pAd->ApCfg.EntryClientCount == 0)! + if (0 /*Wcid == MCAST_WCID*/) + { + if (pAd->ApCfg.EntryClientCount == 0) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } + +#ifdef CONFIG_HOTSPOT + /* Drop broadcast/multicast packet if disable dgaf */ + if (wdev->wdev_type == WDEV_TYPE_AP) + { + MULTISSID_STRUCT *pMbss = (MULTISSID_STRUCT *)wdev->func_dev; + + if (pMbss && (Wcid == MCAST_WCID) && + (pMbss->HotSpotCtrl.HotSpotEnable || pMbss->HotSpotCtrl.bASANEnable) && + pMbss->HotSpotCtrl.DGAFDisable) { + DBGPRINT(RT_DEBUG_INFO, ("Drop broadcast/multicast packet when dgaf disable\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } +#endif /* CONFIG_HOTSPOT */ + + /* AP does not send packets before port secured. */ + if (((wdev->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif /* DOT1X_SUPPORT */ + ) && + (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE) +#ifdef WAPI_SUPPORT + && (RTMP_GET_PACKET_WAI(pPacket) == FALSE) +#endif /* WAPI_SUPPORT */ + ) + { + /* Process for multicast or broadcast frame */ + if (Wcid == MCAST_WCID) + { + if (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED) { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } + else + { /* Process for unicast frame */ + if (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } + } + +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry->bReptCli) + pMacEntry->ReptCliIdleCount = 0; +#endif /* MAC_REPEATER_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(%s):Drop unknow packet\n", + __FUNCTION__, RtmpOsGetNetDevName(wdev->if_dev))); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + if (*pSrcBufVA & 0x01) + is_mcast = TRUE; + +#ifdef IGMP_SNOOP_SUPPORT + if (is_mcast && pAd->ApCfg.IgmpSnoopEnable && + (wdev->wdev_type == WDEV_TYPE_AP || wdev->wdev_type == WDEV_TYPE_WDS) + ) + { + if (IgmpPktInfoQuery(pAd, pSrcBufVA, pPacket, wdev, + &InIgmpGroup, &pGroupEntry) != NDIS_STATUS_SUCCESS) + return NDIS_STATUS_FAILURE; + } +#endif /* IGMP_SNOOP_SUPPORT */ + + + /* + STEP 1. Decide number of fragments required to deliver this MSDU. + The estimation here is not very accurate because difficult to + take encryption overhead into consideration here. The result + "NumberOfFrag" is then just used to pre-check if enough free + TXD are available to hold this MSDU. + */ + if (is_mcast /* fragmentation not allowed on multicast & broadcast */ +#ifdef IGMP_SNOOP_SUPPORT + /* multicast packets in IgmpSn table should never send to Power-Saving queue. */ + && (InIgmpGroup == IGMP_NONE) +#endif /* IGMP_SNOOP_SUPPORT */ + ) + NumberOfFrag = 1; + else if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) + && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE)) + { + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ + } + else + { + /* + The calculated "NumberOfFrag" is a rough estimation because of various + encryption/encapsulation overhead not taken into consideration. This number is just + used to make sure enough free TXD are available before fragmentation takes place. + In case the actual required number of fragments of an NDIS packet + excceeds "NumberOfFrag"caculated here and not enough free TXD available, the + last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of + resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should + rarely happen and the penalty is just like a TX RETRY fail. Affordable. + */ + UINT32 Size; + + AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + Size = PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H; + if (Size >= AllowFragSize) + NumberOfFrag = (Size / AllowFragSize) + 1; + else + NumberOfFrag = 1; + } + + /* Save fragment number to Ndis packet reserved field */ + RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + + + /* detect AC Category of tx packets to tune AC0(BE) TX_OP (MAC reg 0x1300) */ + // TODO: shiang-usw, check this for REG access +#ifdef APCLI_CERT_SUPPORT + if (pApCliEntry->wdev.bWmmCapable == FALSE) +#endif /* APCLI_CERT_SUPPORT */ + detect_wmm_traffic(pAd, UserPriority, 1); + + RTMP_SET_PACKET_UP(pPacket, UserPriority); + RTMP_SET_PACKET_MGMT_PKT(pPacket, 0x00); /* mark as non-management frame */ + +#ifdef INF_AMAZON_SE + pAd->BulkOutDataSizeCount[QueIdx]+=SrcBufLen; +#endif /* INF_AMAZON_SE */ + + /* + 4. put to corrsponding TxSwQueue or Power-saving queue + + WDS/ApClient/Mesh link should never go into power-save mode; just send out the frame + */ + if (pMacEntry && (IS_ENTRY_WDS(pMacEntry) || IS_ENTRY_APCLI(pMacEntry) || IS_ENTRY_MESH(pMacEntry))) + { +#ifdef WDS_SUPPORT + ULONG Now32; + NdisGetSystemUpTime(&Now32); +#endif /* WDS_SUPPORT */ + +#ifdef DATA_QUEUE_RESERVE + if (!(RTMP_GET_PACKET_DHCP(pPacket) || RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_ICMP(pPacket)) + && (pAd->TxSwQueue[QueIdx].Number >= (pAd->TxSwQMaxLen - pAd->TxRsvLen))) +#else /* DATA_QUEUE_RESERVE */ + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) +#endif /* !DATA_QUEUE_RESERVE */ + { +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pPacket); +#endif /* BLOCK_NET_IF */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } +#ifdef WDS_SUPPORT + else if(IS_ENTRY_WDS(pMacEntry) /* when WDS Jam happen, drop following 1min to SWQueue Pkts */ + && (pMacEntry->LockEntryTx == TRUE) + && RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } +#endif /* WDS_SUPPORT */ + else + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + } + /* M/BCAST frames are put to PSQ as long as there's any associated STA in power-save mode */ + else if (is_mcast && pAd->MacTab.fAnyStationInPsm +#ifdef IGMP_SNOOP_SUPPORT + /* multicast packets in IgmpSn table should never send to Power-Saving queue. */ + && (InIgmpGroup == IGMP_NONE) +#endif /* IGMP_SNOOP_SUPPORT */ + ) + { + /* + we don't want too many MCAST/BCAST backlog frames to eat up all buffers. + So in case number of backlog MCAST/BCAST frames exceeds a pre-defined + watermark within a DTIM period, simply drop coming new MCAST/BCAST frames. + This design is similiar to "BROADCAST throttling in most manageable + Ethernet Switch chip. + */ + if (pAd->MacTab.McastPsQueue.Number >= MAX_PACKETS_IN_MCAST_PS_QUEUE) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_TRACE, ("M/BCAST PSQ(=%u) full, drop it!\n", pAd->MacTab.McastPsQueue.Number)); + return NDIS_STATUS_FAILURE; + } + else + { + // TODO: shiang-6590, remove the apidx!!!! + UCHAR apidx; + if (Wcid == MCAST_WCID) + apidx = RTMP_GET_PACKET_NET_DEVICE_MBSSID(pPacket); + else + apidx = pMacEntry->apidx; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + InsertHeadQueue(&pAd->MacTab.McastPsQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + WLAN_MR_TIM_BCMC_SET(apidx); /* mark MCAST/BCAST TIM bit */ + + } + } + /* else if the associted STA in power-save mode, frame also goes to PSQ */ + else if ((PsMode == PWR_SAVE) && pMacEntry && + IS_ENTRY_CLIENT(pMacEntry) && (pMacEntry->Sst == SST_ASSOC)) + { + if (APInsertPsQueue(pAd, pPacket, pMacEntry, QueIdx) != NDIS_STATUS_SUCCESS) + return NDIS_STATUS_FAILURE; + } + /* 3. otherwise, transmit the frame */ + else /* (PsMode == PWR_ACTIVE) || (PsMode == PWR_UNKNOWN) */ + { + +#ifdef DOT11V_WNM_SUPPORT + if (DMSPktInfoQuery(pAd, pSrcBufVA, pPacket, apidx, QueIdx ,UserPriority) != NDIS_STATUS_SUCCESS) + { + return NDIS_STATUS_FAILURE; + } +#endif /* DOT11V_WNM_SUPPORT */ +#ifdef IGMP_SNOOP_SUPPORT + /* if it's a mcast packet in igmp gourp. */ + /* ucast clone it for all members in the gourp. */ + if (((InIgmpGroup == IGMP_IN_GROUP) && pGroupEntry && (IgmpMemberCnt(&pGroupEntry->MemberList) > 0)) || + (InIgmpGroup == IGMP_PKT)) + { + NDIS_STATUS PktCloneResult = IgmpPktClone(pAd, pPacket, InIgmpGroup, pGroupEntry, QueIdx, UserPriority); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + return PktCloneResult; + } + else +#endif /* IGMP_SNOOP_SUPPORT */ + { + +#ifdef DATA_QUEUE_RESERVE + if (!(RTMP_GET_PACKET_DHCP(pPacket) || RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_ICMP(pPacket)) + && (pAd->TxSwQueue[QueIdx].Number >= (pAd->TxSwQMaxLen - pAd->TxRsvLen))) +#else /* DATA_QUEUE_RESERVE */ + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) +#endif /* !DATA_QUEUE_RESERVE */ + { + { +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pPacket); +#endif /* BLOCK_NET_IF */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } + } + else + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + } + } + +#ifdef DOT11_N_SUPPORT + RTMP_BASetup(pAd, pMacEntry, UserPriority); +#endif /* DOT11_N_SUPPORT */ +#ifdef APCLI_CERT_SUPPORT + pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; +#endif /* APCLI_CERT_SUPPORT */ + return NDIS_STATUS_SUCCESS; +} + + +/* + -------------------------------------------------------- + FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM + Find the WPA key, either Group or Pairwise Key + LEAP + TKIP also use WPA key. + -------------------------------------------------------- + Decide WEP bit and cipher suite to be used. + Same cipher suite should be used for whole fragment burst + In Cisco CCX 2.0 Leap Authentication + WepStatus is Ndis802_11WEPEnabled but the key will use PairwiseKey + Instead of the SharedKey, SharedKey Length may be Zero. +*/ +static inline VOID APFindCipherAlgorithm(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + CIPHER_KEY *pKey = NULL; + UCHAR KeyIdx = 0, CipherAlg = CIPHER_NONE; + UCHAR apidx = pTxBlk->apidx; + UCHAR RAWcid = pTxBlk->Wcid; + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + MULTISSID_STRUCT *pMbss; + struct wifi_dev *wdev; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + +#ifdef APCLI_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { + APCLI_STRUCT *pApCliEntry = pTxBlk->pApCliEntry; + wdev = &pApCliEntry->wdev; + + if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + { + /* These EAPoL frames must be clear before 4-way handshaking is completed. */ + if ((!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))) && + (pMacEntry->PairwiseKey.CipherAlg) && + (pMacEntry->PairwiseKey.KeyLen)) + { + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + if (CipherAlg) + pKey = &pMacEntry->PairwiseKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } +#ifdef WPA_SUPPLICANT_SUPPORT + else if (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP && + (pMacEntry->WepStatus == Ndis802_11WEPEnabled) && + (pApCliEntry->wdev.IEEE8021X == TRUE) && + (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + CipherAlg = CIPHER_NONE; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + else if (pMacEntry->WepStatus == Ndis802_11WEPEnabled) + { + CipherAlg = pApCliEntry->SharedKey[wdev->DefaultKeyId].CipherAlg; + if (CipherAlg) + pKey = &pApCliEntry->SharedKey[wdev->DefaultKeyId]; + } + else if (pMacEntry->WepStatus == Ndis802_11TKIPEnable || + pMacEntry->WepStatus == Ndis802_11AESEnable) + { + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + if (CipherAlg) + pKey = &pMacEntry->PairwiseKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk,fTX_bWDSEntry)) + { + wdev = &pAd->WdsTab.WdsEntry[pMacEntry->wdev_idx].wdev; + if (wdev->WepStatus == Ndis802_11WEPEnabled || + wdev->WepStatus == Ndis802_11TKIPEnable || + wdev->WepStatus == Ndis802_11AESEnable) + { + CipherAlg = pAd->WdsTab.WdsEntry[pMacEntry->wdev_idx].WdsKey.CipherAlg; + if (CipherAlg) + pKey = &pAd->WdsTab.WdsEntry[pMacEntry->wdev_idx].WdsKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else +#endif /* WDS_SUPPORT */ +#ifdef WAPI_SUPPORT + if (pMbss->wdev.WepStatus == Ndis802_11EncryptionSMS4Enabled) + { + if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)) + { + /* WAI negotiation packet is always clear. */ + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + else if (!pMacEntry) + { + KeyIdx = pMbss->wdev.DefaultKeyId; /* MSK ID */ + CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + if (CipherAlg == CIPHER_SMS4) + { + pKey = &pAd->SharedKey[apidx][KeyIdx]; +#ifdef SOFT_ENCRYPT + if (pMbss->sw_wpi_encrypt) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + /* TSC increment pre encryption transmittion */ + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 1); + } +#endif /* SOFT_ENCRYPT */ + } + } + else + { + KeyIdx = pTxBlk->pMacEntry->usk_id; /* USK ID */ + CipherAlg = pAd->MacTab.Content[RAWcid].PairwiseKey.CipherAlg; + if (CipherAlg == CIPHER_SMS4) + { + pKey = &pAd->MacTab.Content[RAWcid].PairwiseKey; +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + /* TSC increment pre encryption transmittion */ + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2); + } +#endif /* SOFT_ENCRYPT */ + } + } + } + else +#endif /* WAPI_SUPPORT */ + if ((RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) || +#ifdef DOT1X_SUPPORT + ((wdev->WepStatus == Ndis802_11WEPEnabled) && (wdev->IEEE8021X == TRUE)) || +#endif /* DOT1X_SUPPORT */ + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) + { + DBGPRINT(RT_DEBUG_TRACE,("APHardTransmit --> clear eap frame !!!\n")); + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + else if (!pMacEntry) /* M/BCAST to local BSS, use default key in shared key table */ + { + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + if (CipherAlg) + pKey = &pAd->SharedKey[apidx][KeyIdx]; + } + else /* unicast to local BSS */ + { + CipherAlg = pAd->MacTab.Content[RAWcid].PairwiseKey.CipherAlg; + if (CipherAlg) + pKey = &pAd->MacTab.Content[RAWcid].PairwiseKey; + +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + + /* TSC increment pre encryption transmittion */ + if (pKey == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s pKey == NULL!\n", __FUNCTION__)); + else + { + INC_TX_TSC(pKey->TxTsc, LEN_WPA_TSC); + } + } +#endif /* SOFT_ENCRYPT */ + } + } + else if (wdev->WepStatus == Ndis802_11WEPEnabled) /* WEP always uses shared key table */ + { + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + if (CipherAlg) + pKey = &pAd->SharedKey[apidx][KeyIdx]; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + + pTxBlk->CipherAlg = CipherAlg; + pTxBlk->pKey = pKey; + pTxBlk->KeyIdx = KeyIdx; +} + + +#ifdef DOT11_N_SUPPORT +static inline VOID APBuildCache802_11Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pHeader) +{ + MAC_TABLE_ENTRY *pMacEntry; + PHEADER_802_11 pHeader80211; + + pHeader80211 = (PHEADER_802_11)pHeader; + pMacEntry = pTxBlk->pMacEntry; + + /* + Update the cached 802.11 HEADER + */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + + /* More Bit */ + pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + /* Sequence */ + pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority]; + pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + + /* SA */ +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) + if (FALSE +#ifdef WDS_SUPPORT + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) +#endif /* WDS_SUPPORT */ +#ifdef CLIENT_WDS + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bClientWDSFrame) +#endif /* CLIENT_WDS */ + ) + { /* The addr3 of WDS packet is Destination Mac address and Addr4 is the Source Mac address. */ + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } + else +#endif /* WDS_SUPPORT || CLIENT_WDS */ +#ifdef MWDS + if(TX_BLK_TEST_FLAG(pTxBlk, fTX_bMWDSFrame)) + { + pHeader80211->FC.ToDs = 1; + pHeader80211->FC.FrDs = 1; + if(pTxBlk->pMacEntry) + { +#ifdef APCLI_SUPPORT + if(IS_MWDS_OPMODE_APCLI(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(pHeader80211->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ + COPY_MAC_ADDR(pHeader80211->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); + } + else +#endif /* APCLI_SUPPORT */ + if(IS_MWDS_OPMODE_AP(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pMacEntry->Addr);/* to AP2 */ + COPY_MAC_ADDR(pHeader80211->Addr2, pAd->CurrentAddress); /* from AP1 */ + } + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(pHeader80211->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + } + else +#endif /* MWDS */ +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pMacEntry)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pTxBlk->pMacEntry && (pTxBlk->pMacEntry->bReptCli == TRUE)) + COPY_MAC_ADDR(pHeader80211->Addr2, pTxBlk->pMacEntry->ReptCliAddr); /* from AP1 */ + else +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(pHeader80211->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); /* from AP1 */ + + /* The addr3 of Ap-client packet is Destination Mac address. */ + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); + } + else +#endif /* APCLI_SUPPORT */ + { + /* The addr3 of normal packet send from DS is Src Mac address. */ + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); + } + +#ifdef SMART_MESH + if(pTxBlk->pMacEntry) + Update_CliPktStats(pAd, pTxBlk->pMacEntry, pHeader80211->Sequence, TRUE); +#endif /* SMART_MESH */ +} + + +#ifdef HDR_TRANS_TX_SUPPORT +static inline VOID APBuildCacheWifiInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pWiInfo) +{ + MAC_TABLE_ENTRY *pMacEntry; + + PWIFI_INFO_STRUC pWI; + + pWI = (PWIFI_INFO_STRUC)pWiInfo; + pMacEntry = pTxBlk->pMacEntry; + + /* WIFI INFO size : 4 octets */ + pTxBlk->MpduHeaderLen = WIFI_INFO_SIZE; + + /* More Bit */ + pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + /* Sequence */ + pWI->field.Seq_Num = pMacEntry->TxSeq[pTxBlk->UserPriority]; + pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; +} +#endif /* HDR_TRANS_TX_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + +#ifdef HDR_TRANS_TX_SUPPORT +static inline VOID APBuildWifiInfo( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + PWIFI_INFO_STRUC pWI; + + + /* WIFI INFO size : 4 octets */ + pTxBlk->MpduHeaderLen = WIFI_INFO_SIZE; + + pWI = + (WIFI_INFO_STRUC *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + + NdisZeroMemory(pWI, WIFI_INFO_SIZE); + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + pWI->field.Mode = 2; /* STA */ + else +#endif /* APCLI_SUPPORT */ + pWI->field.Mode = 1; /* AP */ + + pWI->field.QoS = (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? 1 : 0; + + if (pTxBlk->pMacEntry) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) + { + pWI->field.Seq_Num = pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; + } + else + { + pWI->field.Seq_Num = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + } + pWI->field.BssIdx = pTxBlk->pMacEntry->apidx; + } + else + { + pWI->field.Seq_Num = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + } + + pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + if (pTxBlk->CipherAlg != CIPHER_NONE) + pWI->field.WEP = 1; + +#ifdef SMART_MESH + if(pTxBlk->pMacEntry) + Update_CliPktStats(pAd, pTxBlk->pMacEntry, pWI->field.Seq_Num, TRUE); +#endif /* SMART_MESH */ +} +#endif /* HDR_TRANS_TX_SUPPORT */ + + +static inline VOID APBuildCommon802_11Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + /* + MAKE A COMMON 802.11 HEADER + */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + wifi_hdr = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize + TSO_SIZE]; + NdisZeroMemory(wifi_hdr, sizeof(HEADER_802_11)); + + wifi_hdr->FC.FrDs = 1; + wifi_hdr->FC.Type = FC_TYPE_DATA; + wifi_hdr->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); + + if (pTxBlk->pMacEntry) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) + { + wifi_hdr->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; + } + else + { + wifi_hdr->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + } + } + else + { + wifi_hdr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + } + + wifi_hdr->Frag = 0; + wifi_hdr->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + +#ifdef MWDS + if(TX_BLK_TEST_FLAG(pTxBlk, fTX_bMWDSFrame)) + { + wifi_hdr->FC.ToDs = 1; + wifi_hdr->FC.FrDs = 1; + if(pTxBlk->pMacEntry) + { +#ifdef APCLI_SUPPORT + if(IS_MWDS_OPMODE_APCLI(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); + } + else +#endif /* APCLI_SUPPORT */ + if(IS_MWDS_OPMODE_AP(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr);/* to AP2 */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); /* from AP1 */ + } + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(wifi_hdr->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + } + else +#endif /* MWDS*/ +#ifdef APCLI_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { + wifi_hdr->FC.ToDs = 1; + wifi_hdr->FC.FrDs = 0; + COPY_MAC_ADDR(wifi_hdr->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ +#ifdef MAC_REPEATER_SUPPORT + if (pTxBlk->pMacEntry && (pTxBlk->pMacEntry->bReptCli == TRUE)) + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pMacEntry->ReptCliAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); /* from AP1 */ + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + } + else +#endif /* APCLI_SUPPORT */ +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) + if (FALSE +#ifdef WDS_SUPPORT + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) +#endif /* WDS_SUPPORT */ +#ifdef CLIENT_WDS + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bClientWDSFrame) +#endif /* CLIENT_WDS */ + ) + { + wifi_hdr->FC.ToDs = 1; + if (pTxBlk->pMacEntry == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + else + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */ + + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); /* from AP1 */ + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(&wifi_hdr->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } + else +#endif /* WDS_SUPPORT || CLIENT_WDS */ + { + /* TODO: how about "MoreData" bit? AP need to set this bit especially for PS-POLL response */ +#ifdef IGMP_SNOOP_SUPPORT + if (pTxBlk->Wcid != MCAST_WCID) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* DA */ + } + else +#endif /* IGMP_SNOOP_SUPPORT */ +#ifdef DOT11V_WNM_SUPPORT +/*FOR DMS */ + if (pTxBlk->Wcid != MCAST_WCID) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr);/* DA */ + } + else +#endif /* DOT11V_WNM_SUPPORT */ + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pSrcBufHeader); /* DA */ + } + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->ApCfg.MBSSID[pTxBlk->apidx].wdev.bssid); /* BSSID */ + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* SA */ + } + + +#ifdef RT_CFG80211_P2P_SUPPORT + /* To not disturb the Opps test, set psm bit if I use power save mode. */ + /* P2P Test case 7.1.3 */ + if (CFG_P2PCLI_ON(pAd) && pAd->cfg80211_ctrl.bP2pCliPmEnable && + CFG80211_P2P_TEST_BIT(pAd->cfg80211_ctrl.CTWindows, P2P_OPPS_BIT)) + { + wifi_hdr->FC.PwrMgmt = PWR_SAVE; + } +#endif /*RT_CFG80211_P2P_SUPPORT*/ + + if (pTxBlk->CipherAlg != CIPHER_NONE) + wifi_hdr->FC.Wep = 1; + +#ifdef SMART_MESH + if(pTxBlk->pMacEntry) + Update_CliPktStats(pAd, pTxBlk->pMacEntry, wifi_hdr->Sequence, TRUE); +#endif /* SMART_MESH */ +} + + +static inline PUCHAR AP_Build_ARalink_Frame_Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr;/*, pSaveBufPtr; */ + HEADER_802_11 *pHeader_802_11; + PNDIS_PACKET pNextPacket; + UINT32 nextBufLen; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* steal "order" bit to mark "aggregation" */ + pHeader_802_11->FC.Order = 1; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + /* + build QOS Control bytes + */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + /* padding at front of LLC header. LLC header should at 4-bytes aligment. */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + + /* + For RA Aggregation, put the 2nd MSDU length(extra 2-byte field) after + QOS_CONTROL in little endian format + */ + pQEntry = pTxBlk->TxPacketList.Head; + pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + nextBufLen = GET_OS_PKT_LEN(pNextPacket); + if (RTMP_GET_PACKET_VLAN(pNextPacket)) + nextBufLen -= LENGTH_802_1Q; + + *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff; + *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8); + + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + + return pHeaderBufPtr; + +} + + +#ifdef DOT11_N_SUPPORT +static inline BOOLEAN BuildHtcField( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN MAC_TABLE_ENTRY *pMacEntry, + IN PUCHAR pHeaderBufPtr) +{ + BOOLEAN bHTCPlus = FALSE; + + + return bHTCPlus; +} + + +static inline PUCHAR AP_Build_AMSDU_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + UCHAR *pHeaderBufPtr; +#ifdef TXBF_SUPPORT + HEADER_802_11 *pHeader_802_11; +#endif /* TXBF_SUPPORT */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; +#ifdef TXBF_SUPPORT + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; +#endif /* TXBF_SUPPORT */ + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + + /* A-MSDU packet */ + *pHeaderBufPtr |= 0x80; + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + +#ifdef TXBF_SUPPORT + if (pTxBlk->pMacEntry && pAd->chipCap.FlgHwTxBfCap) + { + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + BOOLEAN bHTCPlus = FALSE; + + pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE; + + NdisAcquireSpinLock(&pMacEntry->TxSndgLock); + if (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + + if (pMacEntry->TxSndgType == SNDG_TYPE_SOUNDING) + { + /* Select compress if supported. Otherwise select noncompress */ + if (pAd->CommonCfg.ETxBfNoncompress==0 && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + /* Clear NDP Announcement */ + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 0; + + } + else if (pMacEntry->TxSndgType == SNDG_TYPE_NDP) + { + /* Select compress if supported. Otherwise select noncompress */ + if (pAd->CommonCfg.ETxBfNoncompress==0 && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) && + (pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8)) + ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + /* Set NDP Announcement */ + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 1; + + pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW; + pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs; + } + + pTxBlk->TxSndgPkt = pMacEntry->TxSndgType; + /* arvin add for julian request send NDP */ + pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; + bHTCPlus = TRUE; + } + NdisReleaseSpinLock(&pMacEntry->TxSndgLock); + +#ifdef MFB_SUPPORT +#if defined(MRQ_FORCE_TX) /* have to replace this by the correct condition!!! */ + pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ; +#endif + + /* + Ignore sounding frame because the signal format of sounding frmae may + be different from normal data frame, which may result in different MFB + */ + if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) && + (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE)) + { + if (bHTCPlus == FALSE) + { + bHTCPlus = TRUE; + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + } + + MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry); + } + + if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ && pMacEntry->toTxMfb == 1) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + + MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry); /* not complete yet!!! */ + pMacEntry->toTxMfb = 0; + } +#endif /* MFB_SUPPORT */ + + if (bHTCPlus == TRUE) + { + pHeader_802_11->FC.Order = 1; + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + } +#endif /* TXBF_SUPPORT */ + + /* + padding at front of LLC header + LLC header should locate at 4-octets aligment + @@@ MpduHeaderLen excluding padding @@@ + */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + return pHeaderBufPtr; + +} + +#ifdef TXBF_SUPPORT +VOID AP_AMPDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR TxSndgTypePerEntry) +#else +VOID AP_AMPDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +#endif +{ + HEADER_802_11 *pHeader_802_11; + UCHAR *pHeaderBufPtr; + USHORT freeCnt = 1; + MAC_TABLE_ENTRY *pMacEntry; + PQUEUE_ENTRY pQEntry; + BOOLEAN bHTCPlus = FALSE; + UINT hdr_offset; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount ++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pMacEntry = pTxBlk->pMacEntry; + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TxDropCount++; + } +#endif +#endif + } +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + hdr_offset = TXINFO_SIZE + TXWISize + TSO_SIZE; + pMacEntry = pTxBlk->pMacEntry; + if ((pMacEntry->isCached) +#ifdef TXBF_SUPPORT + && (TxSndgTypePerEntry == SNDG_TYPE_DISABLE) +#endif /* TXBF_SUPPORT */ + ) + { +#ifndef VENDOR_FEATURE1_SUPPORT + NdisMoveMemory((PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (PUCHAR)(&pMacEntry->CachedBuf[0]), TXWISize + sizeof(HEADER_802_11)); +#else + pTxBlk->HeaderBuf = (UCHAR *)(pMacEntry->HeaderBuf); +#endif /* VENDOR_FEATURE1_SUPPORT */ + pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[hdr_offset]); + APBuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); + +#ifdef SOFT_ENCRYPT + RTMPUpdateSwCacheCipherInfo(pAd, pTxBlk, pHeaderBufPtr); +#endif /* SOFT_ENCRYPT */ + } + else + { + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[hdr_offset]; + } + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + +#ifdef VENDOR_FEATURE1_SUPPORT + if(pMacEntry->isCached + && (pMacEntry->Protocol == (RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket))) +#ifdef SOFT_ENCRYPT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt) +#endif /* SOFT_ENCRYPT */ +#ifdef TXBF_SUPPORT + && (TxSndgTypePerEntry == SNDG_TYPE_DISABLE) +#endif /* TXBF_SUPPORT */ + ) + { + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + pTxBlk->MpduHeaderLen = pMacEntry->MpduHeaderLen; + pHeaderBufPtr = ((PUCHAR)pHeader_802_11) + pTxBlk->MpduHeaderLen; + + pTxBlk->HdrPadLen = pMacEntry->HdrPadLen; + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + } + else +#endif /* VENDOR_FEATURE1_SUPPORT */ + { + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + + /* build HTC control filed after QoS field */ + if ((pAd->CommonCfg.bRdg == TRUE) + && (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) +#ifdef TXBF_SUPPORT + && (TxSndgTypePerEntry != SNDG_TYPE_NDP) +#endif /* TXBF_SUPPORT */ + ) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + ((PHT_CONTROL)pHeaderBufPtr)->RDG = 1; + bHTCPlus = TRUE; + } + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE; + + NdisAcquireSpinLock(&pMacEntry->TxSndgLock); + if (TxSndgTypePerEntry >= SNDG_TYPE_SOUNDING) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + + if (TxSndgTypePerEntry == SNDG_TYPE_SOUNDING) + { + /* Select compress if supported. Otherwise select noncompress */ + if (pAd->CommonCfg.ETxBfNoncompress==0 && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + /* Clear NDP Announcement */ + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 0; + + } + else if (TxSndgTypePerEntry == SNDG_TYPE_NDP) + { + /* Select compress if supported. Otherwise select noncompress */ + if ((pAd->CommonCfg.ETxBfNoncompress==0) && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) && + (pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8)) + ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + /* Set NDP Announcement */ + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 1; + + pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW; + pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs; + } + + pTxBlk->TxSndgPkt = TxSndgTypePerEntry; + //pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; + } + + NdisReleaseSpinLock(&pMacEntry->TxSndgLock); + +#ifdef MFB_SUPPORT +#if defined(MRQ_FORCE_TX) + /* have to replace this by the correct condition!!! */ + pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ; +#endif + + /* + Ignore sounding frame because the signal format of sounding frmae may + be different from normal data frame, which may result in different MFB + */ + if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) && + (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE)) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry); + } + + if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ && + pMacEntry->toTxMfb == 1) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry);/* not complete yet!!! */ + pMacEntry->toTxMfb = 0; + } +#endif /* MFB_SUPPORT */ + } +#endif /* TXBF_SUPPORT */ + + if (bHTCPlus == TRUE) + { + /* mark HTC bit */ + pHeader_802_11->FC.Order = 1; + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + + /*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */ + ASSERT(pTxBlk->MpduHeaderLen >= 24); + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef VENDOR_FEATURE1_SUPPORT + pMacEntry->HdrPadLen = pTxBlk->HdrPadLen; +#endif /* VENDOR_FEATURE1_SUPPORT */ + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + UCHAR iv_offset = 0, ext_offset = 0; + + /* + If original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) + { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, + &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (PUCHAR)pHeader_802_11, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, + &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + + } + else +#endif /* SOFT_ENCRYPT */ + { + + + /* Insert LLC-SNAP encapsulation - 8 octets */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + +#ifdef VENDOR_FEATURE1_SUPPORT + pMacEntry->Protocol = RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket); + pMacEntry->MpduHeaderLen = pTxBlk->MpduHeaderLen; +#endif /* VENDOR_FEATURE1_SUPPORT */ + } + + if ((pMacEntry->isCached) +#ifdef TXBF_SUPPORT + && (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE) +#endif /* TXBF_SUPPORT */ + ) + { + RTMPWriteTxWI_Cache(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + + + NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf)); + NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), + (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), + (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]))); + +#ifdef VENDOR_FEATURE1_SUPPORT + /* use space to get performance enhancement */ + NdisZeroMemory((PUCHAR)(&pMacEntry->HeaderBuf[0]), sizeof(pMacEntry->HeaderBuf)); + NdisMoveMemory((PUCHAR)(&pMacEntry->HeaderBuf[0]), + (PUCHAR)(&pTxBlk->HeaderBuf[0]), + (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[0]))); +#endif /* VENDOR_FEATURE1_SUPPORT */ + + pMacEntry->isCached = TRUE; + + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket)) + pMacEntry->isCached = FALSE; + } + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt != SNDG_TYPE_DISABLE) + pMacEntry->isCached = FALSE; +#endif /* TXBF_SUPPORT */ + +#ifdef STATS_COUNT_SUPPORT + /* calculate Transmitted AMPDU count and ByteCount */ + { + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + } + + /* calculate Tx count and ByteCount per BSS */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pMacEntry) && + pMacEntry->WapiUskRekeyTimerRunning && + pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen; +#endif /* WAPI_SUPPORT */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS +/* increment Tx counts and calculate Tx activity time */ + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TransmittedByteCount += pTxBlk->SrcBufLen; + pMacEntry->TxCount++; + } +#endif + { + UINT32 Index, Length; + Length = pTxBlk->SrcBufLen + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + pMacEntry->OneSecTxBytes += pTxBlk->SrcBufLen; + } + } + +#ifdef WDS_SUPPORT + if (pMacEntry && IS_ENTRY_WDS(pMacEntry)) + { + pAd->WdsTab.WdsEntry[pMacEntry->wdev_idx].WdsCounter.TransmittedFragmentCount++; + pAd->WdsTab.WdsEntry[pMacEntry->wdev_idx].WdsCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (pMacEntry && IS_ENTRY_APCLI(pMacEntry)) + { + pAd->ApCfg.ApCliTab[pMacEntry->wdev_idx].ApCliCounter.TransmittedFragmentCount++; + pAd->ApCfg.ApCliTab[pMacEntry->wdev_idx].ApCliCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* APCLI_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &freeCnt); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +} + + +#ifdef HDR_TRANS_TX_SUPPORT +VOID AP_AMPDU_Frame_Tx_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pWiBufPtr; +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + MAC_TABLE_ENTRY *pMacEntry; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + PWIFI_INFO_STRUC pWI; + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + pMbss->TxDropCount ++; +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_2[index])); + } +*/ + + pMacEntry = pTxBlk->pMacEntry; + if ((pMacEntry->isCached) + ) + { + /* It should be cleared!!! */ + /*NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), sizeof(pTxBlk->HeaderBuf)); */ + NdisMoveMemory((PUCHAR) + (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + (PUCHAR) (&pMacEntry->CachedBuf[0]), + TXWISize + WIFI_INFO_SIZE); + + pWiBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]); + APBuildCacheWifiInfo(pAd, pTxBlk, pWiBufPtr); + } + else + { + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildWifiInfo(pAd, pTxBlk); + + pWiBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + } + + pWI = (PWIFI_INFO_STRUC)pWiBufPtr; + + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader; + + if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) + pWI->field.VLAN = TRUE; + + pWI->field.TID = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) + && TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + pWI->field.EOSP = TRUE; +#endif /* UAPSD_SUPPORT */ + + { + + /* + build HTC+ + HTC control filed following QoS field + */ + if ((pAd->CommonCfg.bRdg == TRUE) + && (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) + ) + { + pWI->field.RDG = 1; + } + + } + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_3[index])); + } +*/ + + if ((pMacEntry->isCached) + ) + { + RTMPWriteTxWI_Cache(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf)); + NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), + (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), + TXWISize + WIFI_INFO_SIZE); + + + pMacEntry->isCached = TRUE; + + } + + +#ifdef STATS_COUNT_SUPPORT + /* calculate Transmitted AMPDU count and ByteCount */ + { + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + } + + /* calculate Tx count and ByteCount per BSS */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pMacEntry) && + pMacEntry->WapiUskRekeyTimerRunning && + pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen; +#endif /* WAPI_SUPPORT */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS + /* increment Tx counts and calculate Tx activity time */ + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TransmittedByteCount += pTxBlk->SrcBufLen; + pMacEntry->TxCount++; + } +#endif + { + UINT32 Index, Length; + Length = pTxBlk->SrcBufLen + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif + +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + } + } + +#endif /* STATS_COUNT_SUPPORT */ + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + + /* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_4[index])); + } +*/ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_5[index])); + if ( pAd->debug_index < 201 ) + { + pAd->debug_index ++; + } else { + pAd->debug_on = 0; + } + } +*/ + +} +#endif /* HDR_TRANS_TX_SUPPORT */ + +VOID AP_AMSDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *pHeaderBufPtr, *subFrameHeader; + USHORT freeCnt = 1; /* no use */ + USHORT subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */ + USHORT totalMPDUSize=0; + UCHAR padding = 0; + USHORT FirstTx = 0, LastTxIdx = 0; + int frameNum = 0; + PQUEUE_ENTRY pQEntry; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT +REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + + ASSERT((pTxBlk->TxPacketList.Number > 1)); + + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TxDropCount++; + } +#endif +#endif + } +#endif /* STATS_COUNT_SUPPORT */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) + { + pHeaderBufPtr = AP_Build_AMSDU_Frame_Header(pAd, pTxBlk); + + /* NOTE: TxWI->TxWIMPDUByteCnt will be updated after final frame was handled. */ +#ifdef WFA_VHT_PF + if (pAd->force_amsdu) + { + UCHAR RABAOriIdx; + + if (pMacEntry) { + RABAOriIdx = pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + if (((pMacEntry->TXBAbitmap & (1<UserPriority)) != 0) && + (pAd->BATable.BAOriEntry[RABAOriIdx].amsdu_cap == TRUE)) + TX_BLK_SET_FLAG (pTxBlk, fTX_AmsduInAmpdu); + } + } +#endif /* WFA_VHT_PF */ + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket)) + if (pMacEntry) + pMacEntry->isCached = FALSE; + } + else + { + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE]; + padding = ROUND_UP(AMSDU_SUBHEAD_LEN + subFramePayloadLen, 4) - (AMSDU_SUBHEAD_LEN + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, padding + AMSDU_SUBHEAD_LEN); + pHeaderBufPtr += padding; + pTxBlk->MpduHeaderLen = padding; + pTxBlk->HdrPadLen += padding; + } + + /* + A-MSDU subframe + DA(6)+SA(6)+Length(2) + LLC/SNAP Encap + */ + subFrameHeader = pHeaderBufPtr; + subFramePayloadLen = pTxBlk->SrcBufLen; + + NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); + +#ifdef APCLI_SUPPORT + if(TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pTxBlk->pMacEntry->bReptCli) + { + pReptEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].RepeaterCli[pTxBlk->pMacEntry->MatchReptCliIdx]; + if (pReptEntry->CliValid) + NdisMoveMemory(&subFrameHeader[6] , pReptEntry->CurrentAddress, 6); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx]; + if (pApCliEntry->Valid) + NdisMoveMemory(&subFrameHeader[6] , pApCliEntry->wdev.if_addr, 6); + } + } +#endif /* APCLI_SUPPORT */ + + + pHeaderBufPtr += AMSDU_SUBHEAD_LEN; + pTxBlk->MpduHeaderLen += AMSDU_SUBHEAD_LEN; + + + + /* Insert LLC-SNAP encapsulation - 8 octets */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + + subFramePayloadLen = pTxBlk->SrcBufLen; + + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + subFramePayloadLen += LENGTH_802_1_H; + } + + /* update subFrame Length field */ + subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; + subFrameHeader[13] = subFramePayloadLen & 0xFF; + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + if (frameNum ==0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + frameNum++; + + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +#ifdef STATS_COUNT_SUPPORT + { + /* calculate Transmitted AMSDU Count and ByteCount */ + pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize; + } + + /* calculate Tx count and ByteCount per BSS */ +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) +#endif /* WAPI_SUPPORT */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + pTxBlk->pMacEntry->wapi_usk_rekey_cnt += totalMPDUSize; +#endif /* WAPI_SUPPORT */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += totalMPDUSize; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + pTxBlk->pMacEntry->TransmittedByteCount += totalMPDUSize; + pTxBlk->pMacEntry->TxCount++; + } +#endif + { + UINT32 Index, Length; + Length = totalMPDUSize; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + pMacEntry->OneSecTxBytes += pTxBlk->SrcBufLen; + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedFragmentCount++; + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + { + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedFragmentCount++; + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* APCLI_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT +VOID AP_Legacy_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR TxSndgTypePerEntry) +#else +VOID AP_Legacy_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +#endif +{ + HEADER_802_11 *wifi_hdr; + UCHAR *pHeaderBufPtr; + USHORT freeCnt = 1; + BOOLEAN bVLANPkt; + QUEUE_ENTRY *pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef CUSTOMER_DCC_FEATURE + MAC_TABLE_ENTRY *pMacEntry = NULL; +#endif + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pMacEntry = pTxBlk->pMacEntry; + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TxDropCount++; + } +#endif +#endif + } +#endif /* STATS_COUNT_SUPPORT */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +#ifdef STATS_COUNT_SUPPORT + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } +#endif /* STATS_COUNT_SUPPORT */ + + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + /* record these MCAST_TX frames for group key rekey */ + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INT idx; + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + if (pAd->ApCfg.MBSSID[idx].REKEYTimerRunning && + pAd->ApCfg.MBSSID[idx].WPAREKEY.ReKeyMethod == PKT_REKEY) + { + pAd->ApCfg.MBSSID[idx].REKEYCOUNTER += (pTxBlk->SrcBufLen); + } + } +#ifdef WAPI_SUPPORT + if (pAd->CommonCfg.WapiMskRekeyTimerRunning && + pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_PKT) + { + pAd->CommonCfg.wapi_msk_rekey_cnt += (pTxBlk->SrcBufLen); + } +#endif /* WAPI_SUPPORT */ + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize + TSO_SIZE]; + wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + /* build QOS Control bytes */ + *pHeaderBufPtr = ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx]<<5)); +#ifdef WFA_VHT_PF + if (pAd->force_noack) + *pHeaderBufPtr |= (1 << 5); +#endif /* WFA_VHT_PF */ + +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap && + (pTxBlk->pMacEntry) && + (pTxBlk->pTransmit->field.MODE >= MODE_HTMIX)) + { + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + BOOLEAN bHTCPlus = FALSE; + + pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE; + + NdisAcquireSpinLock(&pMacEntry->TxSndgLock); + if (TxSndgTypePerEntry >= SNDG_TYPE_SOUNDING) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + + if (TxSndgTypePerEntry == SNDG_TYPE_SOUNDING) + { + /* Select compress if supported. Otherwise select noncompress */ + if ((pAd->CommonCfg.ETxBfNoncompress==0) && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0)) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + /* Clear NDP Announcement */ + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 0; + + } + else if (TxSndgTypePerEntry == SNDG_TYPE_NDP) + { + /* Select compress if supported. Otherwise select noncompress */ + if ((pAd->CommonCfg.ETxBfNoncompress == 0) && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) && + (pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8)) + ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + /* Set NDP Announcement */ + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 1; + + pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW; + pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs; + } + + pTxBlk->TxSndgPkt = TxSndgTypePerEntry; + //pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; + bHTCPlus = TRUE; + } + NdisReleaseSpinLock(&pMacEntry->TxSndgLock); + +#ifdef MFB_SUPPORT +#if defined(MRQ_FORCE_TX) + /* have to replace this by the correct condition!!! */ + pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ; +#endif + + /* + Ignore sounding frame because the signal format of sounding frmae may + be different from normal data frame, which may result in different MFB + */ + if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) && + (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE)) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry); + } + + if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ && + pMacEntry->toTxMfb == 1) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + + MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry);/* not complete yet!!!*/ + pMacEntry->toTxMfb = 0; + } +#endif /* MFB_SUPPORT */ + + if (bHTCPlus == TRUE) + { + /* mark HTC bit */ + wifi_hdr->FC.Order = 1; + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + } +#endif /* TXBF_SUPPORT */ + } + + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + UCHAR iv_offset = 0, ext_offset = 0; + + /* + If original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) + { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, + &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (PUCHAR)wifi_hdr, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, + &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + + } + else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && + IS_ENTRY_CLIENT(pTxBlk->pMacEntry) && + pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && + pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + + pTxBlk->pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen; +#endif /* WAPI_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + if(pMbss == NULL) + { + UINT32 apidx; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + (RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev)) && + NdisEqualMemory(pAd->ApCfg.MBSSID[apidx].wdev.bssid, wifi_hdr->Addr2, MAC_ADDR_LEN)) + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + break; + } + } + } +#endif + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS + if (pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + pTxBlk->pMacEntry->TransmittedByteCount += pTxBlk->SrcBufLen; + pTxBlk->pMacEntry->TxCount++; + } +#endif + { + UINT32 Index, Length; + Length = pTxBlk->SrcBufLen + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry && pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + pMacEntry->OneSecTxBytes += pTxBlk->SrcBufLen; + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedFragmentCount++; + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + { + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedFragmentCount++; + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* APCLI_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + + /* + prepare for TXWI + */ + + /* update Hardware Group Key Index */ + if (!pTxBlk->pMacEntry) + { + /* use Wcid as Hardware Key Index */ + GET_GroupKey_WCID(pAd, pTxBlk->Wcid, pTxBlk->apidx); + } + + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket)) + if (pTxBlk->pMacEntry) + pTxBlk->pMacEntry->isCached = FALSE; + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +#ifdef HDR_TRANS_TX_SUPPORT +VOID AP_Legacy_Frame_Tx_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + PWIFI_INFO_STRUC pWI; + + ASSERT(pTxBlk); + + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + pMbss->TxDropCount++; +#endif /* STATS_COUNT_SUPPORT */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +#ifdef STATS_COUNT_SUPPORT + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } +#endif /* STATS_COUNT_SUPPORT */ + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + APFindCipherAlgorithm(pAd, pTxBlk); + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_2[index])); + } +*/ + + APBuildWifiInfo(pAd, pTxBlk); + + pWI = (PWIFI_INFO_STRUC)&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader; + if (bVLANPkt) + pWI->field.VLAN = TRUE; + + pWI->field.TID = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM) + && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) + && TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + pWI->field.EOSP = TRUE; +#endif /* UAPSD_SUPPORT */ + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) +#endif /* WAPI_SUPPORT */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + pTxBlk->pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen; +#endif /* WAPI_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + if(pMbss == NULL) + { + UINT32 apidx; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + (RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev)) && + NdisEqualMemory(pAd->ApCfg.MBSSID[apidx].wdev.bssid, wifi_hdr->Addr2, MAC_ADDR_LEN)) + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + break; + } + } + } +#endif + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS + /* increment Tx counts and calculate Tx activity time */ + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TransmittedByteCount += pTxBlk->SrcBufLen; + pMacEntry->TxCount++; + } +#endif + { + UINT32 Index, Length; + Length = pTxBlk->SrcBufLen + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif + +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry && pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + } + } + +#endif /* STATS_COUNT_SUPPORT */ + + /* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_3[index])); + } +*/ + + /* + prepare for TXWI + */ + + /* update Hardware Group Key Index */ + if (!pTxBlk->pMacEntry) + { + /* use Wcid as Hardware Key Index */ + GET_GroupKey_WCID(pAd, pTxBlk->Wcid, pTxBlk->apidx); + } + + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_4[index])); + } +*/ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_5[index])); + if ( pAd->debug_index < 201 ) + { + pAd->debug_index ++; + } else { + pAd->debug_on = 0; + } + + } +*/ + +} +#endif /* HDR_TRANS_TX_SUPPORT */ + + +VOID AP_Fragment_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + UCHAR *pHeaderBufPtr; + USHORT freeCnt = 1; /* no use */ + UCHAR fragNum = 0; + USHORT EncryptionOverhead = 0; + UINT32 FreeMpduSize, SrcRemainingBytes; + USHORT AckDuration; + UINT NextMpduSize; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + PACKET_INFO PacketInfo; +#ifdef SOFT_ENCRYPT + UCHAR *tmp_ptr = NULL; + UINT32 buf_offset = 0; +#endif /* SOFT_ENCRYPT */ + HTTRANSMIT_SETTING *pTransmit; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef CUSTOMER_DCC_FEATURE + MAC_TABLE_ENTRY *pMacEntry = NULL; +#endif + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if(RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pMacEntry = pTxBlk->pMacEntry; + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TxDropCount++; + } +#endif +#endif + } +#endif /* STATS_COUNT_SUPPORT */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag)); + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + +#ifdef SOFT_ENCRYPT + /* + Check if the original data has enough buffer + to insert or append extended field. + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + + if (pTxBlk->CipherAlg == CIPHER_TKIP) + { + pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); + if (pTxBlk->pPacket == NULL) + return; + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + } + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (pTxBlk->pMacEntry && + CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + UCHAR iv_offset = 0; + + /* + If original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) + { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, + &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + } + else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + If original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + + /* 1. If TKIP is used and fragmentation is required. Driver has to + append TKIP MIC at tail of the scatter buffer + 2. When TXWI->FRAG is set as 1 in TKIP mode, + MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */ + /* TKIP appends the computed MIC to the MSDU data prior to fragmentation into MPDUs. */ + if (pTxBlk->CipherAlg == CIPHER_TKIP) + { + RTMPCalculateMICValue(pAd, pTxBlk->pPacket, pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, pTxBlk->apidx); + + /* + NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust + to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. + */ + NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8); + pTxBlk->SrcBufLen += 8; + pTxBlk->TotalFrameLen += 8; + } + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && + IS_ENTRY_CLIENT(pTxBlk->pMacEntry) && + pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && + pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + + pTxBlk->pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen; +#endif /* WAPI_SUPPORT */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + pTxBlk->pMacEntry->TransmittedByteCount += pTxBlk->SrcBufLen; + pTxBlk->pMacEntry->TxCount++; + } +#endif +#endif +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry && pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + pMacEntry->OneSecTxBytes += pTxBlk->SrcBufLen; + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedFragmentCount++; + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + { + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedFragmentCount++; + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* APCLI_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + + /* + calcuate the overhead bytes that encryption algorithm may add. This + affects the calculate of "duration" field + */ + if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128)) + EncryptionOverhead = 8; /*WEP: IV[4] + ICV[4]; */ + else if (pTxBlk->CipherAlg == CIPHER_TKIP) + EncryptionOverhead = 12;/*TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */ + else if (pTxBlk->CipherAlg == CIPHER_AES) + EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */ +#ifdef WAPI_SUPPORT + else if (pTxBlk->CipherAlg == CIPHER_SMS4) + EncryptionOverhead = 16; /* SMS4: MIC[16] */ +#endif /* WAPI_SUPPORT */ + else + EncryptionOverhead = 0; + + pTransmit = pTxBlk->pTransmit; + /* Decide the TX rate */ + if (pTransmit->field.MODE == MODE_CCK) + pTxBlk->TxRate = pTransmit->field.MCS; + else if (pTransmit->field.MODE == MODE_OFDM) + pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE; + else + pTxBlk->TxRate = RATE_6_5; + + /* decide how much time an ACK/CTS frame will consume in the air */ + if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE) + AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14); + else + AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14); + /*DBGPRINT(RT_DEBUG_INFO, ("!!!Fragment AckDuration(%d), TxRate(%d)!!!\n", AckDuration, pTxBlk->TxRate)); */ + + /* Init the total payload length of this frame. */ + SrcRemainingBytes = pTxBlk->SrcBufLen; + + pTxBlk->TotalFragNum = 0xff; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + /* store the outgoing frame for calculating MIC per fragmented frame */ + os_alloc_mem(pAd, (PUCHAR *)&tmp_ptr, pTxBlk->SrcBufLen); + if (tmp_ptr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory for SW MIC calculation !!!\n", + __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + NdisMoveMemory(tmp_ptr, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + } +#endif /* SOFT_ENCRYPT */ + + do { + + FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC; + + FreeMpduSize -= pTxBlk->MpduHeaderLen; + + if (SrcRemainingBytes <= FreeMpduSize) + { + /* This is the last or only fragment */ + pTxBlk->SrcBufLen = SrcRemainingBytes; + + pHeader_802_11->FC.MoreFrag = 0; + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration; + + /* Indicate the lower layer that this's the last fragment. */ + pTxBlk->TotalFragNum = fragNum; + } + else + { /* more fragment is required */ + pTxBlk->SrcBufLen = FreeMpduSize; + + NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold)); + pHeader_802_11->FC.MoreFrag = 1; + pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead); + } + + SrcRemainingBytes -= pTxBlk->SrcBufLen; + + if (fragNum == 0) + pTxBlk->FrameGap = IFS_HTTXOP; + else + pTxBlk->FrameGap = IFS_SIFS; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { + UCHAR ext_offset = 0; + + NdisMoveMemory(pTxBlk->pSrcBufData, tmp_ptr + buf_offset, pTxBlk->SrcBufLen); + buf_offset += pTxBlk->SrcBufLen; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (PUCHAR)pHeader_802_11, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, + &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + } +#endif /* SOFT_ENCRYPT */ +#ifdef CUSTOMER_DCC_FEATURE + { + UINT32 Index, Length; + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + + Length = pTxBlk->SrcBufLen + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif + + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) + { +#ifdef WAPI_SUPPORT + if (pTxBlk->CipherAlg == CIPHER_SMS4) + { + /* incease WPI IV for next MPDU */ + inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WAPI_TSC, 2); + /* Construct and insert WPI-SMS4 IV header to MPDU header */ + RTMPConstructWPIIVHdr(pTxBlk->KeyIdx, pTxBlk->pKey->TxTsc, + pHeaderBufPtr - (LEN_WPI_IV_HDR)); + } + else +#endif /* WAPI_SUPPORT */ + if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128)) + { + inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WEP_TSC, 1); + /* Construct and insert 4-bytes WEP IV header to MPDU header */ + RTMPConstructWEPIVHdr(pTxBlk->KeyIdx, pTxBlk->pKey->TxTsc, + pHeaderBufPtr - (LEN_WEP_IV_HDR)); + } + else if (pTxBlk->CipherAlg == CIPHER_TKIP) + ; + else if (pTxBlk->CipherAlg == CIPHER_AES) + { + inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WPA_TSC, 1); + /* Construct and insert 8-bytes CCMP header to MPDU header */ + RTMPConstructCCMPHdr(pTxBlk->KeyIdx, pTxBlk->pKey->TxTsc, + pHeaderBufPtr - (LEN_CCMP_HDR)); + } + } + else +#endif /* SOFT_ENCRYPT */ + { + /* Update the frame number, remaining size of the NDIS packet payload. */ + if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap) + pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; /* space for 802.11 header. */ + } + + fragNum++; + /*SrcRemainingBytes -= pTxBlk->SrcBufLen; */ + pTxBlk->pSrcBufData += pTxBlk->SrcBufLen; + + pHeader_802_11->Frag++; /* increase Frag # */ + + }while(SrcRemainingBytes > 0); + +#ifdef SOFT_ENCRYPT + if (tmp_ptr != NULL) + os_free_mem(pAd, tmp_ptr); +#endif /* SOFT_ENCRYPT */ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + +} + + +VOID AP_ARalink_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *pHeaderBufPtr; + USHORT freeCnt = 1; /* no use */ + USHORT totalMPDUSize=0; + USHORT FirstTx, LastTxIdx; + int frameNum = 0; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; +#ifdef CUSTOMER_DCC_FEATURE + MAC_TABLE_ENTRY *pMacEntry = NULL; +#endif + + + ASSERT(pTxBlk); + ASSERT((pTxBlk->TxPacketList.Number== 2)); + + FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */ + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pMacEntry = pTxBlk->pMacEntry; + if (IS_ENTRY_CLIENT(pMacEntry)) + { + pMacEntry->TxDropCount++; + } +#endif +#endif + } +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) + { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */ + + pHeaderBufPtr = AP_Build_ARalink_Frame_Header(pAd, pTxBlk); + + /* + It's ok write the TxWI here, because the TxWI->TxWIMPDUByteCnt + will be updated after final frame was handled. + */ + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + + /* Insert LLC-SNAP encapsulation - 8 octets */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + else + { + /* + For second aggregated frame, we need create the 802.3 header to + headerBuf, because PCI will copy it to SDPtr0. + */ + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + pTxBlk->MpduHeaderLen = 0; + + /* + A-Ralink sub-sequent frame header is the same as 802.3 header. + DA(6)+SA(6)+FrameType(2) + */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12); + pHeaderBufPtr += 12; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen = ARALINK_SUBHEAD_LEN; + } + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + if (frameNum ==0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + frameNum++; + + pAd->RalinkCounters.OneSecTxAggregationCount++; + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ +#ifdef WAPI_SUPPORT +#endif /* WAPI_SUPPORT */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && + IS_ENTRY_CLIENT(pTxBlk->pMacEntry) && + pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && + pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + pTxBlk->pMacEntry->wapi_usk_rekey_cnt += totalMPDUSize; +#endif /* WAPI_SUPPORT */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount.QuadPart += totalMPDUSize; + pMbss->TxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TxDataCount++; +#ifdef MBSS_802_11_STATISTICS + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + pTxBlk->pMacEntry->TransmittedByteCount += pTxBlk->SrcBufLen; + pTxBlk->pMacEntry->TxCount++; + } +#endif + { + UINT32 Index, Length; + Length = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + GetMultShiftFactorIndex(*(pTxBlk->pTransmit), &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif +#ifdef STATS_COUNT_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->mcPktsTx++; + else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader)) + pMbss->bcPktsTx++; + else + pMbss->ucPktsTx++; +#endif /* STATS_COUNT_SUPPORT */ + } + + if(pMacEntry && pMacEntry->Sst == SST_ASSOC) + { + INC_COUNTER64(pMacEntry->TxPackets); + pMacEntry->TxBytes+=pTxBlk->SrcBufLen; + pMacEntry->OneSecTxBytes += pTxBlk->SrcBufLen; + } + + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedFragmentCount++; + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->wdev_idx].WdsCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + { + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedFragmentCount++; + pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->wdev_idx].ApCliCounter.TransmittedByteCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* APCLI_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + } + + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +#ifdef VHT_TXBF_SUPPORT +VOID AP_NDPA_Frame_Tx(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pMacEntry) + +{ + UCHAR *buf; + VHT_NDPA_FRAME *vht_ndpa; + struct wifi_dev *wdev; + UINT frm_len, sta_cnt, frm_len_tmp = 0; + SNDING_STA_INFO *sta_info; + + + if ((pAd == NULL)) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): pAd is NULL \n", __FUNCTION__)); + } + + if (pMacEntry) + { + wdev = pMacEntry->wdev; + + if (MlmeAllocateMemory(pAd, &buf) != NDIS_STATUS_SUCCESS) + return; + + NdisZeroMemory(buf, MGMT_DMA_BUFFER_SIZE); + + vht_ndpa = (VHT_NDPA_FRAME *)buf; + frm_len = sizeof(VHT_NDPA_FRAME); + vht_ndpa->fc.Type = FC_TYPE_CNTL; + vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA; + COPY_MAC_ADDR(vht_ndpa->ra, pMacEntry->Addr); + COPY_MAC_ADDR(vht_ndpa->ta, wdev->if_addr); + + /* Currnetly we only support 1 STA for a VHT DNPA */ + sta_info = vht_ndpa->sta_info; + for (sta_cnt = 0; sta_cnt < 1; sta_cnt++) { + sta_info->aid12 = pMacEntry->Aid; + sta_info->fb_type = SNDING_FB_SU; + sta_info->nc_idx = 0; + vht_ndpa->token.token_num = pMacEntry->snd_dialog_token; + frm_len_tmp = sta_cnt * sizeof(SNDING_STA_INFO); + sta_info++; + if (frm_len >= (MGMT_DMA_BUFFER_SIZE - sizeof(SNDING_STA_INFO))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): len(%d) too large!cnt=%d\n", + __FUNCTION__, frm_len, sta_cnt)); + break; + } + } + if (pMacEntry->snd_dialog_token & 0xc0) + pMacEntry->snd_dialog_token = 0; + else + pMacEntry->snd_dialog_token++; + + frm_len += frm_len_tmp; + vht_ndpa->duration = 100; + + //DBGPRINT(RT_DEBUG_OFF, ("Send VHT NDPA Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + // PRINT_MAC(pMacEntry->Addr))); + //hex_dump("VHT NDPA Frame", buf, frm_len); + + // NDPA's BW needs to sync with Tx BW + pAd->CommonCfg.MlmeTransmit.field.BW = pMacEntry->HTPhyMode.field.BW; + + MiniportMMRequest(pAd, 0, buf, frm_len); + MlmeFreeMemory(pAd, buf); + } + + //pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; +} +#endif /* VHT_TXBF_SUPPORT */ + + +/* + ======================================================================== + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + pTxBlk Pointer to outgoing TxBlk structure. + QueIdx Queue index for processing + + Return Value: + None + ======================================================================== +*/ +#ifdef TXBF_SUPPORT +NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR QueIdx, UCHAR TxSndgTypePerEntry) +#else +NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR QueIdx) +#endif +{ + PQUEUE_ENTRY pQEntry; + PNDIS_PACKET pPacket; + + if ((pAd->Dot11_H.RDMode != RD_NORMAL_MODE) +#ifdef CARRIER_DETECTION_SUPPORT + ||(isCarrierDetectExist(pAd) == TRUE) +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + { + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + return NDIS_STATUS_FAILURE; + } + + if (pTxBlk->wdev->bVLAN_Tag == TRUE) + { + RTMP_SET_PACKET_VLAN(pTxBlk->pPacket, FALSE); + } + +#ifdef DOT11K_RRM_SUPPORT +#ifdef QUIET_SUPPORT + if ((pTxBlk->apidx < pAd->ApCfg.BssidNum) + && IS_RRM_QUIET(pAd, pTxBlk->apidx)) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } +#endif /* QUIET_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef HDR_TRANS_TX_SUPPORT +#ifdef SOFT_ENCRYPT + if ( TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) /* need LLC, not yet generated */ + pTxBlk->NeedTrans = FALSE; + else +#endif /* SOFT_ENCRYPT */ +#ifdef WDS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry)) + pTxBlk->NeedTrans = FALSE; + else +#endif /* WDS_SUPPORT */ + { + pTxBlk->NeedTrans = TRUE; +#ifdef TXBF_SUPPORT + pTxBlk->NeedTrans = FALSE; +#endif // TXBF_SUPPORT // + } +#endif /* HDR_TRANS_TX_SUPPORT */ + + switch (pTxBlk->TxFrameType) + { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: +#ifdef HDR_TRANS_TX_SUPPORT + if (pTxBlk->NeedTrans) + AP_AMPDU_Frame_Tx_Hdr_Trns(pAd, pTxBlk); + else +#endif /* HDR_TRANS_TX_SUPPORT */ +#ifdef TXBF_SUPPORT + AP_AMPDU_Frame_Tx(pAd, pTxBlk, TxSndgTypePerEntry); +#else + AP_AMPDU_Frame_Tx(pAd, pTxBlk); +#endif + break; +#endif /* DOT11_N_SUPPORT */ + case TX_LEGACY_FRAME: +#ifdef HDR_TRANS_TX_SUPPORT + if (pTxBlk->NeedTrans) + AP_Legacy_Frame_Tx_Hdr_Trns(pAd, pTxBlk); + else +#endif /* HDR_TRANS_TX_SUPPORT */ +#ifdef TXBF_SUPPORT + AP_Legacy_Frame_Tx(pAd, pTxBlk, TxSndgTypePerEntry); +#else + AP_Legacy_Frame_Tx(pAd, pTxBlk); +#endif + break; + case TX_MCAST_FRAME: +#ifdef HDR_TRANS_TX_SUPPORT + pTxBlk->NeedTrans = FALSE; +#endif /* HDR_TRANS_TX_SUPPORT */ +#ifdef TXBF_SUPPORT + AP_Legacy_Frame_Tx(pAd, pTxBlk, TxSndgTypePerEntry); +#else + AP_Legacy_Frame_Tx(pAd, pTxBlk); +#endif + break; +#ifdef DOT11_N_SUPPORT + case TX_AMSDU_FRAME: + AP_AMSDU_Frame_Tx(pAd, pTxBlk); + break; +#endif /* DOT11_N_SUPPORT */ + case TX_RALINK_FRAME: + AP_ARalink_Frame_Tx(pAd, pTxBlk); + break; + case TX_FRAG_FRAME: + AP_Fragment_Frame_Tx(pAd, pTxBlk); + break; + default: + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n")); + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + break; + } + + return (NDIS_STATUS_SUCCESS); + +} + + +/* + ======================================================================== + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error found + ======================================================================== +*/ +INT APCheckRxError(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo, RX_BLK *pRxBlk) +{ + if (pRxInfo->Crc || pRxInfo->CipherErr) + { +#ifdef DBG_DIAGNOSE + if (pRxInfo->Crc) + { + if (pAd->DiagStruct.inited) { + struct dbg_diag_info *diag_info; + diag_info = &pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx]; +#ifdef DBG_RX_MCS + if (pRxBlk->rx_rate.field.MODE == MODE_HTMIX || + pRxBlk->rx_rate.field.MODE == MODE_HTGREENFIELD) { + if (pRxBlk->rx_rate.field.MCS < MAX_MCS_SET) + diag_info->RxCrcErrCnt_HT[pRxBlk->rx_rate.field.MCS]++; + } +#ifdef DOT11_VHT_AC + if (pRxBlk->rx_rate.field.MODE == MODE_VHT) { + INT mcs_idx = ((pRxBlk->rx_rate.field.MCS >> 4) * 10) + + (pRxBlk->rx_rate.field.MCS & 0xf); + if (mcs_idx < MAX_VHT_MCS_SET) + diag_info->RxCrcErrCnt_VHT[mcs_idx]++; + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_RX_MCS */ + } + } +#endif /* DBG_DIAGNOSE */ + + /* + WCID equal to 255 mean MAC couldn't find any matched entry in Asic-MAC table. + The incoming packet mays come from WDS or AP-Client link. + We need them for further process. Can't drop the packet here. + */ + if ((pRxInfo->U2M) + && (pRxInfo->CipherErr) + && (pRxBlk->wcid == 255) +#ifdef WDS_SUPPORT + && (pAd->WdsTab.Mode == WDS_LAZY_MODE) +#endif /* WDS_SUPPORT */ + ) + { + /* pass those packet for further process. */ + return NDIS_STATUS_SUCCESS; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("%s(): pRxInfo:Crc=%d, CipherErr=%d, U2M=%d, Wcid=%d\n", + __FUNCTION__, pRxInfo->Crc, pRxInfo->CipherErr, pRxInfo->U2M, pRxBlk->wcid)); + return NDIS_STATUS_FAILURE; + } + } + + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + Description: + This routine checks if a received frame causes class 2 or class 3 + error, and perform error action (DEAUTH or DISASSOC) accordingly + ======================================================================== +*/ +BOOLEAN APChkCls2Cls3Err(RTMP_ADAPTER *pAd, UCHAR wcid, HEADER_802_11 *hdr) +{ + /* software MAC table might be smaller than ASIC on-chip total size. */ + /* If no mathed wcid index in ASIC on chip, do we need more check??? need to check again. 06-06-2006 */ + if (wcid >= MAX_LEN_OF_MAC_TABLE) + { + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_WARN, ("%s():Rx a frame from %02x:%02x:%02x:%02x:%02x:%02x with WCID(%u) > %d\n", + __FUNCTION__, PRINT_MAC(hdr->Addr2), + wcid, MAX_LEN_OF_MAC_TABLE)); +//+++Add by shiang for debug + pEntry = MacTableLookup(pAd, hdr->Addr2); + if (pEntry) + { + if ((pEntry->Sst == SST_ASSOC) && IS_ENTRY_CLIENT(pEntry)) + { + } + return FALSE; + } +//---Add by shiang for debug + + APCls2errAction(pAd, MAX_LEN_OF_MAC_TABLE, hdr); + return TRUE; + } + + if (pAd->MacTab.Content[wcid].Sst == SST_ASSOC) + ; /* okay to receive this DATA frame */ + else if (pAd->MacTab.Content[wcid].Sst == SST_AUTH) + { + APCls3errAction(pAd, wcid, hdr); + return TRUE; + } + else + { + APCls2errAction(pAd, wcid, hdr); + return TRUE; + } + return FALSE; +} + + +/* + detect AC Category of trasmitting packets + to turn AC0(BE) TX_OP (MAC reg 0x1300) +*/ +/*static UCHAR is_on; */ +VOID detect_wmm_traffic( + IN RTMP_ADAPTER *pAd, + IN UCHAR UserPriority, + IN UCHAR FlgIsOutput) +{ + if (pAd == NULL) + return; + + /* For BE & BK case and TxBurst function is disabled */ + if ((pAd->CommonCfg.bEnableTxBurst == FALSE) +#ifdef DOT11_N_SUPPORT + && (pAd->CommonCfg.bRdg == FALSE) + && (pAd->CommonCfg.bRalinkBurstMode == FALSE) +#endif /* DOT11_N_SUPPORT */ + && (FlgIsOutput == 1) + ) + { + if (WMM_UP2AC_MAP[UserPriority] == QID_AC_BK) + { + /* has any BK traffic */ + if (pAd->flg_be_adjust == 0) + { + /* yet adjust */ +#ifdef RTMP_MAC_PCI + EDCA_AC_CFG_STRUC Ac0Cfg; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Ac0Cfg.word); + Ac0Cfg.field.AcTxop = 0x20; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); +#endif /* RTMP_MAC_PCI */ + pAd->flg_be_adjust = 1; + NdisGetSystemUpTime(&pAd->be_adjust_last_time); + + DBGPRINT(RT_DEBUG_TRACE, ("wmm> adjust be!\n")); + } + } + else + { + if (pAd->flg_be_adjust != 0) + { + PQUEUE_HEADER pQueue; + + /* has adjusted */ + pQueue = &pAd->TxSwQueue[QID_AC_BK]; + + if ((pQueue == NULL) || + ((pQueue != NULL) && (pQueue->Head == NULL))) + { + ULONG now; + NdisGetSystemUpTime(&now); + if ((now - pAd->be_adjust_last_time) > TIME_ONE_SECOND) + { + /* no any BK traffic */ +#ifdef RTMP_MAC_PCI + EDCA_AC_CFG_STRUC Ac0Cfg; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Ac0Cfg.word); + Ac0Cfg.field.AcTxop = 0x00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); +#endif /* RTMP_MAC_PCI */ + pAd->flg_be_adjust = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("wmm> recover be!\n")); + } + } + else + NdisGetSystemUpTime(&pAd->be_adjust_last_time); + } + } + } + + /* count packets which priority is more than BE */ + if (UserPriority > 3) + { + pAd->OneSecondnonBEpackets++; + + if (pAd->OneSecondnonBEpackets > 100 +#ifdef DOT11_N_SUPPORT + && pAd->MacTab.fAnyStationMIMOPSDynamic +#endif /* DOT11_N_SUPPORT */ + ) + { + if (!pAd->is_on) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x005400ca ); +#endif /* RTMP_MAC_PCI */ + pAd->is_on = 1; + } + } + else + { + if (pAd->is_on) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x002400ca ); +#endif /* RTMP_MAC_PCI */ + pAd->is_on = 0; + } + } + } +} + +/* + Wirte non-zero value to AC0 TXOP to boost performace + To pass WMM, AC0 TXOP must be zero. + It is necessary to turn AC0 TX_OP dynamically. +*/ + +VOID dynamic_tune_be_tx_op(RTMP_ADAPTER *pAd, ULONG nonBEpackets) +{ + UINT32 RegValue; + AC_TXOP_CSR0_STRUC csr0; + + if (pAd->CommonCfg.bEnableTxBurst +#ifdef DOT11_N_SUPPORT + || pAd->CommonCfg.bRdg + || pAd->CommonCfg.bRalinkBurstMode +#endif /* DOT11_N_SUPPORT */ + ) + { + + if ( +#ifdef DOT11_N_SUPPORT + (pAd->WIFItestbed.bGreenField && pAd->MacTab.fAnyStationNonGF == TRUE) || + ((pAd->OneSecondnonBEpackets > nonBEpackets) || pAd->MacTab.fAnyStationMIMOPSDynamic) || +#endif /* DOT11_N_SUPPORT */ + (pAd->MacTab.fAnyTxOPForceDisable)) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &RegValue); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE)) + { + RegValue = pAd->CommonCfg.RestoreBurstMode; + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + { + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + } + /* disable AC0(BE) TX_OP */ + RegValue &= 0xFFFFFF00; /* for WMM test */ + /*if ((RegValue & 0x0000FF00) == 0x00004300) */ + /* RegValue += 0x00001100; */ + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, RegValue); + if (pAd->CommonCfg.APEdcaParm.Txop[QID_AC_VO] != 102) + { + csr0.field.Ac0Txop = 0; /* QID_AC_BE */ + } + else + { + /* for legacy b mode STA */ + csr0.field.Ac0Txop = 10; /* QID_AC_BE */ + } + csr0.field.Ac1Txop = 0; /* QID_AC_BK */ + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE); + } + } + else + { + //if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)==0) || + // (pAd->ApCfg.ChangeTxOpClient != pAd->MacTab.Size)) + { + /* enable AC0(BE) TX_OP */ + UCHAR txop_value_burst = 0x20; /* default txop for Tx-Burst */ + UCHAR txop_value = 0; + + pAd->ApCfg.ChangeTxOpClient = pAd->MacTab.Size; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE)) + txop_value = 0x80; + else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + txop_value = 0x80; + else if ((pAd->MacTab.Size == 1) && (pAd->CommonCfg.bEnableTxBurst)) { + MAC_TABLE_ENTRY *pEntry = NULL; + UINT32 i = 0; + + txop_value = txop_value_burst; + + for (i = 1; i< MAX_LEN_OF_MAC_TABLE; i++) { + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + break; + } + + if (pEntry && i < MAX_LEN_OF_MAC_TABLE) { + if (((pEntry->HTPhyMode.field.MODE == MODE_HTMIX || pEntry->HTPhyMode.field.MODE == MODE_HTGREENFIELD) && + (((pAd->CommonCfg.TxStream == 2) && (pEntry->HTPhyMode.field.MCS >= MCS_14)) || + ((pAd->CommonCfg.TxStream == 1) && (pEntry->HTPhyMode.field.MCS >= MCS_6)))) +#ifdef DOT11_VHT_AC + || ((pEntry->HTPhyMode.field.MODE == MODE_VHT) && + (((pAd->CommonCfg.TxStream == 2) && (pEntry->HTPhyMode.field.MCS >= 23)) || + ((pAd->CommonCfg.TxStream == 1) && (pEntry->HTPhyMode.field.MCS >= 7)))) +#endif /* DOT11_VHT_AC */ + ) { + txop_value = 0x60; + DBGPRINT(RT_DEBUG_INFO, ("%s::enable Tx burst to 0x60 under HT/VHT mode\n", __FUNCTION__)); + } + } + } + else if (pAd->CommonCfg.bEnableTxBurst) + txop_value = txop_value_burst; + else + txop_value = 0; + +#ifdef MULTI_CLIENT_SUPPORT + if(pAd->MacTab.Size > 2) /* for Multi-Clients */ + txop_value = 0; +#endif /* MULTI_CLIENT_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP + /* Traffic Base Txop Rule */ + if ((txop_value == txop_value_burst) && + ((pAd->StaTxopAbledCnt >= 1) || (pAd->ApClientTxopAbledCnt >= 1))) { + txop_value = 0x60; + } +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &RegValue); + RegValue &= 0xFFFFFF00; + /*if ((RegValue & 0x0000FF00) == 0x00005400) + RegValue -= 0x00001100; */ + /*txop_value = 0; */ + RegValue |= txop_value; /* for performance, set the TXOP to non-zero */ + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, RegValue); + csr0.field.Ac0Txop = txop_value; /* QID_AC_BE */ + csr0.field.Ac1Txop = 0; /* QID_AC_BK */ + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE); + } + } + } + pAd->OneSecondnonBEpackets = 0; +} + + +VOID APRxErrorHandle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + PCIPHER_KEY pWpaKey; + + UCHAR Wcid; + PHEADER_802_11 pHeader = pRxBlk->pHeader; +#ifdef WPA_SUPPLICANT_SUPPORT + UCHAR FromWhichBSSID = BSS0; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + if (pRxInfo->CipherErr) + INC_COUNTER64(pAd->WlanCounters.WEPUndecryptableCount); + + if (pRxInfo->CipherErr) + { + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + { +#ifdef APCLI_SUPPORT + + Wcid = pRxBlk->wcid; + if (VALID_WCID(Wcid)) + pEntry = ApCliTableLookUpByWcid(pAd, Wcid, pHeader->Addr2); + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + if (pRxInfo->CipherErr == 2) + { + pWpaKey = &pEntry->PairwiseKey; +#ifdef WPA_SUPPLICANT_SUPPORT + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_APCLI; + if (pAd->ApCfg.ApCliTab[pEntry->wdev_idx].wpa_supplicant_info.WpaSupplicantUP) + { + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, pHeader->Addr2, + (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE, + (INT)pRxBlk->key_idx, NULL); + } + if (((pRxInfo->CipherErr & 2) == 2) && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pEntry->Addr, FromWhichBSSID, 0); +#else + ApCliRTMPReportMicError(pAd, pWpaKey, BSS0); +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); + } + } + else +#endif /* APCLI_SUPPORT */ + if (pRxInfo->U2M) + { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + /* + MIC error + Before verifying the MIC, the receiver shall check FCS, ICV and TSC. + This avoids unnecessary MIC failure events. + */ + if ((pEntry->WepStatus == Ndis802_11TKIPEnable) + && (pRxInfo->CipherErr == 2)) + { +#ifdef HOSTAPD_SUPPORT + if(pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == Hostapd_EXT) + ieee80211_notify_michael_failure(pAd, pRxBlk->pHeader, (UINT32)pRxBlk->key_idx, 0); + else +#endif/*HOSTAPD_SUPPORT*/ + { + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } + } + + /* send wireless event - for icv error */ + if ((pRxInfo->CipherErr & 1) == 1) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0); + } + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + pEntry->RxDecryptErrCnt++; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Rx u2me Cipher Err(MPDUsize=%d, WCID=%d, CipherErr=%d)\n", + pRxBlk->MPDUtotalByteCnt, pRxBlk->wcid, pRxInfo->CipherErr)); + + } + + pAd->Counters8023.RxErrors++; +} + +#ifdef RLT_MAC_DBG +static int dump_next_valid = 0; +#endif +BOOLEAN APCheckVaildDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + BOOLEAN isVaild = FALSE; + + do + { +#ifndef APCLI_SUPPORT + /* should not drop Ap-Client packet. */ + if (pHeader->FC.ToDs == 0) + break; +#endif /* APCLI_SUPPORT */ + +#ifdef IDS_SUPPORT + if ((pHeader->FC.FrDs == 0) && (pRxBlk->wcid == RESERVED_WCID)) /* not in RX WCID MAC table */ + { + if (++pAd->ApCfg.RcvdMaliciousDataCount > pAd->ApCfg.DataFloodThreshold) + break; + } +#endif /* IDS_SUPPORT */ + + /* check if Class2 or 3 error */ + if ((pHeader->FC.FrDs == 0) && (APChkCls2Cls3Err(pAd, pRxBlk->wcid, pHeader))) + break; + +//+++Add by shiang for debug +#ifdef RLT_MAC_DBG + if (pAd->chipCap.hif_type == HIF_RLT) { + if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) { + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_WARN, ("ErrWcidPkt: seq=%d, ts=0x%02x%02x%02x%02x\n", + pHeader->Sequence, + pRxBlk->pRxWI->RXWI_N.rssi[0], + pRxBlk->pRxWI->RXWI_N.rssi[1], + pRxBlk->pRxWI->RXWI_N.rssi[2], + pRxBlk->pRxWI->RXWI_N.rssi[3])); + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry && (pEntry->Sst == SST_ASSOC) && (IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry))) + pRxBlk->wcid = pEntry->wcid; + + dump_next_valid = 1; + } + else if (dump_next_valid) + { + DBGPRINT(RT_DEBUG_WARN, ("NextValidWcidPkt: seq=%d, ts=0x%02x%02x%02x%02x\n", + pHeader->Sequence, + pRxBlk->pRxWI->RXWI_N.rssi[0], + pRxBlk->pRxWI->RXWI_N.rssi[1], + pRxBlk->pRxWI->RXWI_N.rssi[2], + pRxBlk->pRxWI->RXWI_N.rssi[3])); + dump_next_valid = 0; + } + } +#endif /* RLT_MAC_DBG */ +//---Add by shiang for debug + + if(pAd->ApCfg.BANClass3Data == TRUE) + break; + + isVaild = TRUE; + } while (0); + + return isVaild; +} + +/* For TKIP frame, calculate the MIC value */ +BOOLEAN APCheckTkipMICValue( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + UCHAR UserPriority = pRxBlk->UserPriority; + PCIPHER_KEY pWpaKey; + UCHAR *pDA, *pSA; + + pWpaKey = &pEntry->PairwiseKey; + + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) + { + pDA = pHeader->Addr3; + pSA = (PUCHAR)pHeader + sizeof(HEADER_802_11); + } + else if (RX_BLK_TEST_FLAG(pRxBlk, fRX_APCLI)) + { + pDA = pHeader->Addr1; + pSA = pHeader->Addr3; + } + else + { + pDA = pHeader->Addr3; + pSA = pHeader->Addr2; + } + + if (RTMPTkipCompareMICValue(pAd, + pData, + pDA, + pSA, + pWpaKey->RxMic, + UserPriority, + DataSize) == FALSE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n")); + +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pAd->ApCfg.ApCliTab[pEntry->wdev_idx].wpa_supplicant_info.WpaSupplicantUP) + { + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, pHeader->Addr2, + (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE, + (INT)pRxBlk->key_idx, NULL); + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + { + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +VOID APRxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + BOOLEAN CheckPktSanity = TRUE; + UCHAR *pTmpBuf; +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT + INT eapcode; +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + do + { + } while (FALSE); + + /* Sanity Check */ + if(pRxBlk->DataSize < (LENGTH_802_1_H + LENGTH_EAPOL_H)) + { + CheckPktSanity = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("Total pkts size is too small.\n")); + } + else if (!RTMPEqualMemory(SNAP_802_1H, pRxBlk->pData, 6)) + { + CheckPktSanity = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("Can't find SNAP_802_1H parameter.\n")); + } + else if (!RTMPEqualMemory(EAPOL, pRxBlk->pData+6, 2)) + { + CheckPktSanity = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("Can't find EAPOL parameter.\n")); + } + else if(*(pRxBlk->pData+9) > EAPOLASFAlert) + { + CheckPktSanity = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("Unknown EAP type(%d).\n", *(pRxBlk->pData+9))); + } + + if(CheckPktSanity == FALSE) + { + goto done; + } + + + +#ifdef HOSTAPD_SUPPORT + if ((pEntry) && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("Indicate_Legacy_Packet\n")); + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif/*HOSTAPD_SUPPORT*/ +#ifdef RT_CFG80211_SUPPORT + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_AP EAPOL Indicate_Legacy_Packet\n")); + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif/*RT_CFG80211_SUPPORT*/ + +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + + eapcode=WpaCheckEapCode(pAd, pRxBlk->pData, + pRxBlk->DataSize, + LENGTH_802_1_H); + + DBGPRINT(RT_DEBUG_TRACE, ("eapcode=%d\n",eapcode)); + if (apcli_entry->wpa_supplicant_info.WpaSupplicantUP && + apcli_entry->wdev.IEEE8021X == TRUE && (EAP_CODE_SUCCESS == eapcode)) + { + PUCHAR Key; + UCHAR CipherAlg; + int idx = 0; + int BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + pEntry->wdev_idx; + WPA_SUPPLICANT_INFO *sup_info = &apcli_entry->wpa_supplicant_info; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); + /* pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + /* STA_PORT_SECURED(pAd); */ + pEntry->PortSecured=WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter=Ndis802_11PrivFilterAcceptAll; + if (sup_info->IEEE8021x_required_keys == FALSE) + { + idx = sup_info->DesireSharedKeyId; + CipherAlg = sup_info->DesireSharedKey[idx].CipherAlg; + Key = sup_info->DesireSharedKey[idx].Key; + + if (sup_info->DesireSharedKey[idx].KeyLen > 0) + { + /* Set key material and cipherAlg to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd,BssIdx, idx, + &sup_info->DesireSharedKey[idx]); + + /* STA doesn't need to set WCID attribute for group key */ + /* Assign pairwise key info */ + RTMP_SET_WCID_SEC_INFO(pAd, BssIdx, idx, CipherAlg, pEntry->wcid, SHAREDKEYTABLE); + + /* RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); */ + /* pAd->ExtraInfo = GENERAL_LINK_UP; */ + + /* For Preventing ShardKey Table is cleared by remove key procedure. */ + apcli_entry->SharedKey[idx].CipherAlg = CipherAlg; + apcli_entry->SharedKey[idx].KeyLen = sup_info->DesireSharedKey[idx].KeyLen; + NdisMoveMemory(apcli_entry->SharedKey[idx].Key, + sup_info->DesireSharedKey[idx].Key, + sup_info->DesireSharedKey[idx].KeyLen); + } + } + } + + if (apcli_entry->wpa_supplicant_info.WpaSupplicantUP && + ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (apcli_entry->wdev.IEEE8021X == TRUE)) + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Indicate_Legacy_Packet\n")); + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + } +#endif/* WPA_SUPPLICANT_SUPPORT */ +#endif/* APCLI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* sent this frame to upper layer TCPIP */ + if ((pEntry) && (pEntry->WpaState < AS_INITPMK) && + ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx == ENTRY_NOT_FOUND)) || + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.IEEE8021X == TRUE)) + { +#ifdef WSC_AP_SUPPORT + if ((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + (!MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, ZERO_MAC_ADDR))) + { + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); +#ifndef CUSTOMER_DCC_FEATURE + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, pTmpBuf, + pRxBlk->DataSize + LENGTH_802_11, + pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, OPMODE_AP); +#else + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, pTmpBuf, + pRxBlk->DataSize + LENGTH_802_11, + pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, 0, 0, OPMODE_AP); +#endif + pRxBlk->pHeader = (PHEADER_802_11)pTmpBuf; + } +#endif /* WSC_AP_SUPPORT */ + + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + else /* sent this frame to WPA state machine */ +#endif /* DOT1X_SUPPORT */ + { + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); +#ifndef CUSTOMER_DCC_FEATURE + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, pTmpBuf, + pRxBlk->DataSize + LENGTH_802_11, + pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, OPMODE_AP); +#else + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, pTmpBuf, + pRxBlk->DataSize + LENGTH_802_11, + pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, 0, 0, OPMODE_AP); +#endif + } + +done: + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + +} + +VOID Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + if (APFowardWirelessStaToWirelessSta(pAd, pPacket, FromWhichBSSID)) + announce_802_3_packet(pAd, pPacket,OPMODE_AP); + else + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} + +#ifdef APCLI_SUPPORT +void rx_get_pn(RX_BLK *pRxBlk,RXINFO_STRUC *pRxInfo) +{ + + UINT32 pn_len_byte; + UINT64 pnv = 0,pnvh = 0,pnvl = 0; + UINT8 *pnb; + + if (!pRxInfo->pn_len) { + DBGPRINT(RT_DEBUG_WARN, ("pn_len is 0.\n")); + return; + } + pn_len_byte = pRxInfo->pn_len << 2; + if (pRxBlk->DataSize <= pn_len_byte) { + DBGPRINT(RT_DEBUG_ERROR, ("DataSize %u <= pn_len %u\n", pRxBlk->DataSize, pn_len_byte)); + return; + } + pnb = pRxBlk->pData; + pRxBlk->pData += pn_len_byte; + pRxBlk->DataSize -= pn_len_byte; + if (unlikely(pn_len_byte != 8)) { + DBGPRINT(RT_DEBUG_OFF, ("abnormal pn_len %u\n", pRxInfo->pn_len)); + return; + } + pnvh = ((pnb[7] << 24) | (pnb[6] << 16) | (pnb[5] << 8)| pnb[4]); + pnvl = ((pnb[1] << 8) | pnb[0]); + pnv = ((pnvh << 16) | pnvl); + pRxBlk->CCMP_PN = pnv; +} + +/* this function ONLY if not allow pn replay attack and drop packet */ +BOOLEAN check_rx_pkt_pn_allowed(RTMP_ADAPTER *pAd, RX_BLK *rx_blk) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + BOOLEAN isAllow = TRUE; + FRAME_CONTROL *pFmeCtrl = (FRAME_CONTROL *)(&(rx_blk->pHeader->FC)); + NDIS_802_11_WEP_STATUS groupcipher; + + if (pFmeCtrl->Wep == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("check_rx_pkt_pn_allowed wep =0\n")); + return TRUE; + } + if (!VALID_WCID(rx_blk->wcid)) + return TRUE; + pEntry = &pAd->MacTab.Content[rx_blk->wcid]; + if (!pEntry || !pEntry->wdev || !IS_ENTRY_APCLI(pEntry)) { + DBGPRINT(RT_DEBUG_WARN, ("check_rx_pkt_pn_allowed pEntry is NULL or not APCLI.\n")); + return TRUE; + } + if (rx_blk->pRxInfo->Mcast || rx_blk->pRxInfo->Bcast) { + WPA_GET_GROUP_CIPHER(pAd,pEntry,groupcipher); + if (groupcipher == Ndis802_11AESEnable) { + if (pEntry->init_ccmp_bc_pn_passed == FALSE) { + if (rx_blk->CCMP_PN < pEntry->CCMP_BC_PN) + isAllow = FALSE; + else { + pEntry->CCMP_BC_PN = rx_blk->CCMP_PN; + pEntry->init_ccmp_bc_pn_passed = TRUE; + } + } else { + if (rx_blk->CCMP_PN <= pEntry->CCMP_BC_PN) + isAllow = FALSE; + else + pEntry->CCMP_BC_PN = rx_blk->CCMP_PN; + } + DBGPRINT(RT_DEBUG_WARN, ("%s:wcid(%d)Seq(%d) %s: come-in the %llu and now is %llu\n", + __func__, pEntry->wcid, rx_blk->pHeader->Sequence, ((isAllow == TRUE) ? "OK" : "Reject"), + rx_blk->CCMP_PN, pEntry->CCMP_BC_PN)); + } + } +#ifdef PN_UC_REPLAY_DETECTION_SUPPORT + if ((rx_blk->pRxInfo->U2M) && + (pEntry->WepStatus == Ndis802_11AESEnable)) { + UCHAR TID = rx_blk->TID; + /*if (pAd->)*/ + if (rx_blk->CCMP_PN < pEntry->CCMP_UC_PN[TID]) { + DBGPRINT(RT_DEBUG_WARN, ("UC, %s (%d) Reject: come-in the %llu and now is %llu\n", + __func__, pEntry->wcid, rx_blk->CCMP_PN, pEntry->CCMP_UC_PN[TID])); + isAllow = FALSE; + } else { + pEntry->CCMP_UC_PN[TID] = rx_blk->CCMP_PN; + } + } +#endif /* PN_UC_REPLAY_DETECTION_SUPPORT */ + + return isAllow; +} +#endif /* APCLI_SUPPORT */ + +VOID APRxDataFrameAnnounce( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + + /* non-EAP frame */ + if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) + { +#ifdef WAPI_SUPPORT + /* report to upper layer if the received frame is WAI frame */ + if (RTMPCheckWAIframe(pRxBlk->pData, pRxBlk->DataSize)) + { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif /* WAPI_SUPPORT */ + +#ifdef MWDS + if (pEntry && IS_ENTRY_MWDS(pEntry)) + { + if (!((pRxBlk->pHeader->FC.FrDs == 1) && (pRxBlk->pHeader->FC.ToDs == 1))) + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if(IS_MWDS_OPMODE_AP(pEntry)) + { + PUCHAR pSrcBuf = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + MWDSARPLookupUpdate(pAd, pSrcBuf); + } + } +#endif /* MWDS */ + + /* + drop all non-EAP DATA frame before + this client's Port-Access-Control is secured + */ + if (pEntry->PrivacyFilter == Ndis802_11PrivFilter8021xWEP) + { + /* + If 1) no any EAP frame is received within 5 sec and + 2) an encrypted non-EAP frame from peer associated STA is received, + AP would send de-authentication to this STA. + */ + if (IS_ENTRY_CLIENT(pEntry) && pRxBlk->pHeader->FC.Wep && + pEntry->StaConnectTime > 5 && pEntry->WpaState < AS_AUTHENTICATION2) + { + DBGPRINT(RT_DEBUG_WARN, ("==> De-Auth this STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pEntry->Addr))); + MlmeDeAuthAction(pAd, pEntry, REASON_NO_LONGER_VALID, FALSE); + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + +#ifdef IGMP_SNOOP_SUPPORT + if (pEntry + && (IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_WDS(pEntry)) + && (pAd->ApCfg.IgmpSnoopEnable) + && IS_MULTICAST_MAC_ADDR(pRxBlk->pHeader->Addr3)) + { + PUCHAR pDA = pRxBlk->pHeader->Addr3; + PUCHAR pSA = pRxBlk->pHeader->Addr2; + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + UINT16 protoType = OS_NTOHS(*((UINT16 *)(pData))); + +#ifdef IGMP_MESH + if (pEntry && IS_MWDS_OPMODE_AP(pEntry)) + pSA = pRxBlk->pHeader->Octet; +#endif /* IGMP_MESH */ + + if (protoType == ETH_P_IP) + IGMPSnooping(pAd, pDA, pSA, pData, get_netdev_from_bssid(pAd, FromWhichBSSID)); + else if (protoType == ETH_P_IPV6) + MLDSnooping(pAd, pDA, pSA, pData, get_netdev_from_bssid(pAd, FromWhichBSSID)); + } +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef CONFIG_HOTSPOT + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->pMbss) && pEntry->pMbss->HotSpotCtrl.HotSpotEnable) { + if (hotspot_rx_handler(pAd, pEntry, pRxBlk) == TRUE) + return; + } +#endif /* CONFIG_HOTSPOT */ + +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU + if (pEntry && (IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry))) + RTMP_RxPacketClassify(pAd, pRxBlk, pEntry); +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + +#ifdef STATS_COUNT_SUPPORT + if (pEntry + && (IS_ENTRY_CLIENT(pEntry)) + && (pEntry->pMbss)) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if(IS_MULTICAST_MAC_ADDR(pRxBlk->pHeader->Addr3) || + IS_MULTICAST_MAC_ADDR(pRxBlk->pHeader->Addr1)) + pMbss->mcPktsRx++; + else if(IS_BROADCAST_MAC_ADDR(pRxBlk->pHeader->Addr3) || + IS_BROADCAST_MAC_ADDR(pRxBlk->pHeader->Addr1)) + { + pMbss->bcPktsRx++; + } + else + pMbss->ucPktsRx++; + } +#endif /* STATS_COUNT_SUPPORT */ + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) + { + /* Normal legacy, AMPDU or AMSDU */ + CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID); + } + else + { + /* ARALINK */ + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } + else + { + RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); + + /* Update the WPA STATE to indicate the EAP handshaking is started */ + if (pEntry->WpaState == AS_AUTHENTICATION) + pEntry->WpaState = AS_AUTHENTICATION2; + +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif /* DOT11_N_SUPPORT */ + { +#ifdef CONFIG_HOTSPOT_R2 + UCHAR *pData = (UCHAR *)pRxBlk->pData; + + if (pEntry) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || + /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL*/ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) + { + pData += 6; + } + + if (NdisEqualMemory(EAPOL, pData, 2)) + pData += 2; + + if ((*(pData+1) == EAPOLStart) && (pMbss->HotSpotCtrl.HotSpotEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->hs_info.ppsmo_exist == 1)) + { + UCHAR HS2_Header[4] = {0x50,0x6f,0x9a,0x12}; + memcpy(&pRxBlk->pData[pRxBlk->DataSize], HS2_Header, 4); + memcpy(&pRxBlk->pData[pRxBlk->DataSize+4], &pEntry->hs_info, sizeof(struct _sta_hs_info)); + printk("rcv eapol start, %x:%x:%x:%x\n",pRxBlk->pData[pRxBlk->DataSize+4], pRxBlk->pData[pRxBlk->DataSize+5],pRxBlk->pData[pRxBlk->DataSize+6], pRxBlk->pData[pRxBlk->DataSize+7]); + pRxBlk->DataSize += 8; + } + } +#endif + /* Determin the destination of the EAP frame */ + /* to WPA state machine or upper layer */ + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } +} + + +#ifdef HDR_TRANS_SUPPORT +VOID APRxDataFrameAnnounce_Hdr_Trns( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + + /* non-EAP frame */ + if (!RTMPCheckWPAframe_Hdr_Trns(pAd, pEntry, pRxBlk->pTransData, pRxBlk->TransDataSize, FromWhichBSSID)) + { +#ifdef WAPI_SUPPORT + /* report to upper layer if the received frame is WAI frame */ + if (RTMPCheckWAIframe(pRxBlk->pData, pRxBlk->DataSize)) + { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif /* WAPI_SUPPORT */ + +#ifdef MWDS + if (pEntry && IS_ENTRY_MWDS(pEntry)) + { + if (!((pRxBlk->pHeader->FC.FrDs == 1) && (pRxBlk->pHeader->FC.ToDs == 1))) + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if(IS_MWDS_OPMODE_AP(pEntry)) + { + PUCHAR pSrcBuf = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + MWDSARPLookupUpdate(pAd, pSrcBuf); + } + } +#endif /* MWDS */ + + /* + drop all non-EAP DATA frame before + this client's Port-Access-Control is secured + */ + if (pEntry->PrivacyFilter == Ndis802_11PrivFilter8021xWEP) + { + /* + If 1) no any EAP frame is received within 5 sec and + 2) an encrypted non-EAP frame from peer associated STA is received, + AP would send de-authentication to this STA. + */ + if (IS_ENTRY_CLIENT(pEntry) && pRxBlk->pHeader->FC.Wep && + pEntry->StaConnectTime > 5 && pEntry->WpaState < AS_AUTHENTICATION2) + { + DBGPRINT(RT_DEBUG_WARN, ("==> De-Auth this STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pEntry->Addr))); + MlmeDeAuthAction(pAd, pEntry, REASON_NO_LONGER_VALID, FALSE); + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + +#ifdef IGMP_SNOOP_SUPPORT + if (pEntry + && (IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_WDS(pEntry)) + && (pAd->ApCfg.IgmpSnoopEnable) + && IS_MULTICAST_MAC_ADDR(pRxBlk->pHeader->Addr3)) + { + PUCHAR pDA = pRxBlk->pHeader->Addr3; + PUCHAR pSA = pRxBlk->pHeader->Addr2; + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + UINT16 protoType = OS_NTOHS(*((UINT16 *)(pData))); +#ifdef MWDS + if(pEntry && IS_MWDS_OPMODE_AP(pEntry)) + pSA = pRxBlk->pHeader->Octet; +#endif /* MWDS */ + + if (protoType == ETH_P_IP) + IGMPSnooping(pAd, pDA, pSA, pData, get_netdev_from_bssid(pAd, FromWhichBSSID)); + else if (protoType == ETH_P_IPV6) + MLDSnooping(pAd, pDA, pSA, pData, get_netdev_from_bssid(pAd, FromWhichBSSID)); + } +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef STATS_COUNT_SUPPORT + if (pEntry + && (IS_ENTRY_CLIENT(pEntry)) + && (pEntry->pMbss)) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if(IS_MULTICAST_MAC_ADDR(pRxBlk->pHeader->Addr3) || IS_MULTICAST_MAC_ADDR(pRxBlk->pHeader->Addr1)) + { + pMbss->mcPktsRx++; + } + else if(IS_BROADCAST_MAC_ADDR(pRxBlk->pHeader->Addr3) || IS_BROADCAST_MAC_ADDR(pRxBlk->pHeader->Addr1)) + { + pMbss->bcPktsRx++; + } + else + { + pMbss->ucPktsRx++; + } + } +#endif /* STATS_COUNT_SUPPORT */ + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) + { + /* Normal legacy, AMPDU or AMSDU */ + CmmRxnonRalinkFrameIndicate_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID); + } + else + { + /* ARALINK */ + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } + else + { + RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); + + /* Update the WPA STATE to indicate the EAP handshaking is started */ + if (pEntry->WpaState == AS_AUTHENTICATION) + pEntry->WpaState = AS_AUTHENTICATION2; + +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* Determin the destination of the EAP frame */ + /* to WPA state machine or upper layer */ + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } +} +#endif /* HDR_TRANS_SUPPORT */ + + +/* + All Rx routines use RX_BLK structure to hande rx events + It is very important to build pRxBlk attributes + 1. pHeader pointer to 802.11 Header + 2. pData pointer to payload including LLC (just skip Header) + 3. set payload size including LLC to DataSize + 4. set some flags with RX_BLK_SET_FLAG() +*/ +VOID APHandleRxDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR FromWhichBSSID = BSS0; + UCHAR OldPwrMgmt = PWR_ACTIVE; /* UAPSD AP SUPPORT */ + UCHAR UserPriority = 0; + INT hdr_len = LENGTH_802_11; + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; + COUNTER_RALINK *pCounter = &pAd->RalinkCounters; +#ifdef APCLI_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[0]; +#endif + +//+++Add by shiang for debug +//---Add by shiangf for debug + + if (APCheckVaildDataFrame(pAd, pRxBlk) != TRUE) + goto err; + +#ifdef IDS_SUPPORT + /* + Replay attack detection + drop it if detect a spoofed data frame from a rogue AP + */ + if (pFmeCtrl->FrDs == 1 && + (RTMPReplayAttackDetection(pAd, pHeader->Addr2, pRxBlk) == TRUE)) + { + goto err; + } +#endif /* IDS_SUPPORT */ + + if (pRxInfo->U2M) + { + Update_Rssi_Sample(pAd, &pAd->ApCfg.RssiSample, pRxWI); + pAd->ApCfg.NumOfAvgRssiSample ++; + +#ifdef DBG_DIAGNOSE + if (pAd->DiagStruct.inited) { + struct dbg_diag_info *diag_info; + diag_info = &pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx]; + diag_info->RxDataCnt++; +#ifdef DBG_RX_MCS + if (pRxBlk->rx_rate.field.MODE == MODE_HTMIX || + pRxBlk->rx_rate.field.MODE == MODE_HTGREENFIELD) { + if (pRxBlk->rx_rate.field.MCS < MAX_MCS_SET) + diag_info->RxMcsCnt_HT[pRxBlk->rx_rate.field.MCS]++; + } +#ifdef DOT11_VHT_AC + if (pRxBlk->rx_rate.field.MODE == MODE_VHT) { + INT mcs_idx = ((pRxBlk->rx_rate.field.MCS >> 4) * 10) + + (pRxBlk->rx_rate.field.MCS & 0xf); + if (mcs_idx < MAX_VHT_MCS_SET) + diag_info->RxMcsCnt_VHT[mcs_idx]++; + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_RX_MCS */ + } +#endif /* DBG_DIAGNOSE */ + } + + /* handle WDS */ + if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 1)) + { + do + { +#ifdef CLIENT_WDS + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry != NULL) + { + if (IS_ENTRY_CLIWDS(pEntry)) + ; + else if (IS_ENTRY_CLIENT(pEntry) + && (pEntry->Sst == SST_ASSOC)) + SET_ENTRY_CLIWDS(pEntry); + else + pEntry = NULL; + } + + if (pEntry != NULL) + { + FromWhichBSSID = pEntry->apidx; + + /* Increase received byte counter per BSS */ + if (FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if (pMbss != NULL) + { + pMbss->ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount ++; + } + } + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + hdr_len = LENGTH_802_11_WITH_ADDR4; + CliWds_ProxyTabUpdate(pAd, pEntry->Aid, pHeader->Octet); + break; + } +#endif /* CLIENT_WDS */ + +#ifdef MWDS + if(VALID_WCID(pRxBlk->wcid)) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if(pEntry && + IS_MWDS_OPMODE_AP(pEntry)) + { + /* + It means this source entry has moved to another one and hidden behind it. + So delete this source entry! + */ + MAC_TABLE_ENTRY *pMovedEntry = MacTableLookup(pAd, pHeader->Octet); + if(pMovedEntry) + MacTableDeleteEntry(pAd, pMovedEntry->wcid, pMovedEntry->Addr); + + FromWhichBSSID = pEntry->apidx; + /* Increase received byte counter per BSS */ + if (FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if (pMbss != NULL) + { + pMbss->ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount++; + } + } + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + hdr_len = LENGTH_802_11_WITH_ADDR4; + MWDSProxyTabUpdate(pAd, pEntry->wcid, pHeader->Octet); + break; + } + else + pEntry = NULL; +#ifdef APCLI_SUPPORT + if (VALID_WCID(pRxBlk->wcid)) + pEntry = ApCliTableLookUpByWcid(pAd, pRxBlk->wcid, pHeader->Addr2); + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if(pEntry && + IS_MWDS_OPMODE_APCLI(pEntry) && + (pEntry->wdev_idx < MAX_APCLI_NUM)) + { + /* + For ApCli, we have to avoid to delete the bridge MAC(SA) and AP MAC(TA) + is the same case. + */ + if(!MAC_ADDR_EQUAL(pHeader->Octet, pEntry->Addr)) + { + /* + It means this source entry has moved to another one and hidden behind it. + So delete this source entry! + */ + MAC_TABLE_ENTRY *pMovedEntry = MacTableLookup(pAd, pHeader->Octet); + if(pMovedEntry) + MacTableDeleteEntry(pAd, pMovedEntry->wcid, pMovedEntry->Addr); + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + if(pApCliEntry) + { + NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); + if(MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr) || + MAC_ADDR_EQUAL(pHeader->Octet, pApCliEntry->wdev.if_addr)) + goto err; + } + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_APCLI; + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + hdr_len = LENGTH_802_11_WITH_ADDR4; + + /* Process broadcast packets */ + if (pRxInfo->Mcast || pRxInfo->Bcast) + { + /* Process the received broadcast frame for AP-Client. */ + if (!ApCliHandleRxBroadcastFrame(pAd, pRxBlk, pEntry, FromWhichBSSID)) + goto err; + return; + } + break; + } + else + pEntry = NULL; +#endif /* APCLI_SUPPORT */ +#endif /* MWDS */ +#ifdef WDS_SUPPORT + /* handle WDS */ + if (!pEntry) + { + /* + The WDS frame only can go here when in auto learning mode and + this is the first trigger frame from peer + + So we check if this is un-registered WDS entry by call function + "FindWdsEntry()" + */ + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxBlk->wcid, pHeader->Addr2, pRxBlk->rx_rate.field.MODE); + + /* have no valid wds entry exist, then discard the incoming packet.*/ + if (!pEntry || !WDS_IF_UP_CHECK(pAd, pEntry->wdev_idx)) + goto err; + + /*receive corresponding WDS packet, disable TX lock state (fix WDS jam issue) */ + if(pEntry->LockEntryTx == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Receive WDS packet, disable TX lock state!\n")); + pEntry->ContinueTxFailCnt = 0; + pEntry->LockEntryTx = FALSE; + } + + } + + if (pEntry) + { +#ifdef STATS_COUNT_SUPPORT + pAd->WdsTab.WdsEntry[pEntry->wdev_idx].WdsCounter.ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pAd->WdsTab.WdsEntry[pEntry->wdev_idx].WdsCounter.ReceivedFragmentCount++; + + if(IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + pAd->WdsTab.WdsEntry[pEntry->wdev_idx].WdsCounter.MulticastReceivedFrameCount++; +#endif + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + hdr_len = LENGTH_802_11_WITH_ADDR4; + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_WDS; + break; + } +#endif /* WDS_SUPPORT */ + } while(FALSE); + + /* have no WDS or MESH support, drop it */ + if (pEntry == NULL) + goto err; + } + else if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 0)) + { +#ifdef APCLI_SUPPORT + /* handle APCLI. */ + if (VALID_WCID(pRxBlk->wcid)) + pEntry = ApCliTableLookUpByWcid(pAd, pRxBlk->wcid, pHeader->Addr2); + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + if (!(APCLI_IF_UP_CHECK(pAd, pEntry->wdev_idx))) + goto err; + + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + + /* ApCli reconnect workaround - update ApCliRcvBeaconTime on RX activity too */ + pApCliEntry->ApCliRcvBeaconTime = pAd->Mlme.Now32; + + if(MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr)) + goto err; + +#ifdef MWDS + if(IS_MWDS_OPMODE_APCLI(pEntry)) + goto err; +#endif /* MWDS */ + +#ifdef STATS_COUNT_SUPPORT + pApCliEntry->ApCliCounter.ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pApCliEntry->ApCliCounter.ReceivedFragmentCount++; +#endif /* STATS_COUNT_SUPPORT */ + + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_APCLI; + RX_BLK_SET_FLAG(pRxBlk, fRX_APCLI); + + /* Process broadcast packets */ + if (pRxInfo->Mcast || pRxInfo->Bcast) + { +#ifdef STATS_COUNT_SUPPORT + pApCliEntry->ApCliCounter.MulticastReceivedFrameCount++; +#endif /* STATS_COUNT_SUPPORT */ + /* Process the received broadcast frame for AP-Client. */ + if (!ApCliHandleRxBroadcastFrame(pAd, pRxBlk, pEntry, FromWhichBSSID)) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } + return; + } + } + else +#endif /* APCLI_SUPPORT */ + { + goto err; + } + } + else + { + pEntry = PACInquiry(pAd, pRxBlk->wcid); + + /* can't find associated STA entry then filter invlid data frame */ + if (!pEntry) + goto err; + + FromWhichBSSID = pEntry->apidx; + +#ifdef STATS_COUNT_SUPPORT + /* Increase received byte counter per BSS */ + if (pHeader->FC.FrDs == 0 && + pRxInfo->U2M && + FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; +#ifdef CUSTOMER_DCC_FEATURE + UCHAR *pDA = pRxBlk->pHeader->Addr3; +#endif + if (pMbss != NULL) + { + pMbss->ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.RxDataCount++; + pAd->RadioStatsCounter.TotalRxCount++; +#ifdef MBSS_802_11_STATISTICS + if (((*pDA) & 0x1) == 0x01) { + if(IS_BROADCAST_MAC_ADDR(pDA)) + pMbss->bcPktsRx++; + else + pMbss->mcPktsRx++; + } + else + pMbss->ucPktsRx++; + if(pEntry->Sst == SST_ASSOC) + { + pEntry->ReceivedByteCount += pRxBlk->MPDUtotalByteCnt; + pEntry->RxCount++; + } + { + UINT32 Length, Index; + HTTRANSMIT_SETTING HTSetting; + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = pRxBlk->rx_rate.field.MODE; + HTSetting.field.BW = pRxBlk->rx_rate.field.BW; + HTSetting.field.ShortGI = pRxBlk->rx_rate.field.ShortGI; + HTSetting.field.MCS = pRxBlk->rx_rate.field.MCS; + Length = pRxBlk->MPDUtotalByteCnt; + GetMultShiftFactorIndex(HTSetting, &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pEntry); + } +#endif +#endif + } + } + + /* update multicast counter */ + if (IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + FromWhichBSSID += MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + } + + ASSERT(pEntry->Aid == pRxBlk->wcid); + + +#ifdef DOT11_N_SUPPORT +#ifndef DOT11_VHT_AC +#ifndef WFA_VHT_PF +// TODO: shiang@PF#2, is this atheros protection still necessary here???? + /* check Atheros Client */ + if (!pEntry->bIAmBadAtheros && (pFmeCtrl->Retry) && + (pRxBlk->rx_rate.field.MODE < MODE_VHT) && + (pRxInfo->AMPDU == 1) && (pAd->CommonCfg.bHTProtect == TRUE) + ) + { + if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE) + RTMP_UPDATE_PROTECT(pAd, 8 , ALLN_SETPROTECT, FALSE, FALSE); + pEntry->bIAmBadAtheros = TRUE; + + if (pEntry->WepStatus != Ndis802_11WEPDisabled) + pEntry->MpduDensity = 6; + } +#endif /* WFA_VHT_PF */ +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + /* update rssi sample */ + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + + if (pAd->ApCfg.MBSSID[pEntry->apidx].RssiLowForStaKickOut != 0) + { + pEntry->curLastDataRssiIndex = pEntry->curLastDataRssiIndex % MAX_LAST_DATA_RSSI_LEN; + pEntry->LastDataRssi[pEntry->curLastDataRssiIndex] = RTMPMaxRssi(pAd, pEntry->RssiSample.LastRssi0, + pEntry->RssiSample.LastRssi1, pEntry->RssiSample.LastRssi2); + //DBGPRINT(RT_DEBUG_TRACE, ("Recored ==> %d:[%d].\n",pEntry->curLastDataRssiIndex, + // pEntry->LastDataRssi[pEntry->curLastDataRssiIndex])); + pEntry->curLastDataRssiIndex++; + } + + + if (pRxInfo->U2M) + { + pEntry->LastRxRate = (ULONG)(pRxBlk->rx_rate.word); +#ifdef SMART_MESH + Update_CliPktStats(pAd, pEntry, pHeader->Sequence, FALSE); +#endif /* SMART_MESH */ + +#ifdef TXBF_SUPPORT + if (pRxBlk->rx_rate.field.ShortGI) + pEntry->OneSecRxSGICount++; + else + pEntry->OneSecRxLGICount++; +#endif // TXBF_SUPPORT // +#ifdef DYNAMIC_VGA_SUPPORT + pEntry->DyncVgaOneSecRxCount++; +#endif /*DYNAMIC_VGA_SUPPORT*/ + } + + pAd->ApCfg.LastSNR0 = (UCHAR)(pRxBlk->snr[0]); + pAd->ApCfg.LastSNR1 = (UCHAR)(pRxBlk->snr[1]); +#ifdef DOT11N_SS3_SUPPORT + pAd->ApCfg.LastSNR2 = (UCHAR)(pRxBlk->snr[2]); +#endif /* DOT11N_SS3_SUPPORT */ + pEntry->freqOffset = (CHAR)(pRxBlk->freq_offset); + pEntry->freqOffsetValid = TRUE; + + + /* Gather PowerSave information from all valid DATA frames. IEEE 802.11/1999 p.461 */ + /* must be here, before no DATA check */ + pRxBlk->pData = (UCHAR *)pHeader; + + /* 1: PWR_SAVE, 0: PWR_ACTIVE */ + OldPwrMgmt = RtmpPsIndicate(pAd, pHeader->Addr2, pEntry->wcid, pFmeCtrl->PwrMgmt); +#ifdef UAPSD_SUPPORT + if (pFmeCtrl->PwrMgmt) + { + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE)) && + (pFmeCtrl->SubType & 0x08)) + { + /* + In IEEE802.11e, 11.2.1.4 Power management with APSD, + If there is no unscheduled SP in progress, the unscheduled SP begins + when the QAP receives a trigger frame from a non-AP QSTA, which is a + QoS data or QoS Null frame associated with an AC the STA has + configured to be trigger-enabled. + + In WMM v1.1, A QoS Data or QoS Null frame that indicates transition + to/from Power Save Mode is not considered to be a Trigger Frame and + the AP shall not respond with a QoS Null frame. + */ + /* Trigger frame must be QoS data or QoS Null frame */ + UCHAR OldUP; + + OldUP = (*(pRxBlk->pData+LENGTH_802_11) & 0x07); + if (OldPwrMgmt == PWR_SAVE) + { +#ifdef DROP_MASK_SUPPORT + /* Disable Drop Mask */ + drop_mask_set_per_client(pAd, pEntry, FALSE); +#endif /* DROP_MASK_SUPPORT */ + + UAPSD_TriggerFrameHandle(pAd, pEntry, OldUP); + } + } + } +#endif /* UAPSD_SUPPORT */ + + /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */ + if ((pFmeCtrl->SubType & 0x04) && (pFmeCtrl->Order == 0)) /* bit 2 : no DATA */ + { + /* Increase received drop packet counter per BSS */ + if (pFmeCtrl->FrDs == 0 && + pRxInfo->U2M && + pRxBlk->bss_idx < pAd->ApCfg.BssidNum) + { + pAd->ApCfg.MBSSID[pRxBlk->bss_idx].RxDropCount ++; + } + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* + update RxBlk->pData, DataSize, 802.11 Header, QOS, HTC, Hw Padding + */ + + /* 1. skip 802.11 HEADER */ + pRxBlk->pData += hdr_len; + pRxBlk->DataSize -= hdr_len; + + /* 2. QOS */ + if (pFmeCtrl->SubType & 0x08) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); + UserPriority = *(pRxBlk->pData) & 0x0f; + + + /* count packets priroity more than BE */ +#ifdef APCLI_CERT_SUPPORT + //if (pAd->bApCliCertTest == FALSE) + if (pApCliEntry->wdev.bWmmCapable == FALSE) +#endif /* APCLI_CERT_SUPPORT */ + detect_wmm_traffic(pAd, UserPriority, 0); + /* bit 7 in QoS Control field signals the HT A-MSDU format */ + if ((*pRxBlk->pData) & 0x80) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); + + /* calculate received AMSDU count and ByteCount */ + pCounter->ReceivedAMSDUCount.u.LowPart ++; + pCounter->ReceivedOctesInAMSDUCount.QuadPart += (pRxBlk->DataSize + hdr_len); + } + + /* skip QOS contorl field */ + pRxBlk->pData += 2; + pRxBlk->DataSize -=2; + } + pRxBlk->UserPriority = UserPriority; + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap && + (pHeader->FC.SubType & 0x08) && pHeader->FC.Order) + { + handleHtcField(pAd, pRxBlk); + } +#endif /* TXBF_SUPPORT */ + + /* 3. Order bit: A-Ralink or HTC+ */ + if (pFmeCtrl->Order) + { +#ifdef AGGREGATION_SUPPORT + if ( +#ifdef DOT11_N_SUPPORT + (pRxBlk->rx_rate.field.MODE < MODE_HTMIX) && +#endif /* DOT11_N_SUPPORT */ + (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE)) + ) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); + } + else +#endif + { + RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); + /* skip HTC control field */ + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; + } + } + + /* 4. skip HW padding */ + if (pRxInfo->L2PAD) + { + /* just move pData pointer because DataSize excluding HW padding */ + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pRxBlk->pData += 2; + } + + if (pRxInfo->BA) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); + + /* incremented by the number of MPDUs */ + /* received in the A-MPDU when an A-MPDU is received. */ + pCounter->MPDUInReceivedAMPDUCount.u.LowPart ++; + } + +#ifdef SOFT_ENCRYPT + /* Use software to decrypt the encrypted frame if necessary. + If a received "encrypted" unicast packet(its WEP bit as 1) + and it's passed to driver with "Decrypted" marked as 0 in RxD. */ + if ((pHeader->FC.Wep == 1) && (pRxInfo->Decrypted == 0)) + { + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, + UserPriority, + &pEntry->PairwiseKey, + pRxBlk->pData, + &(pRxBlk->DataSize)) != NDIS_STATUS_SUCCESS) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + /* Record the Decrypted bit as 1 */ + pRxInfo->Decrypted = 1; + } +#endif /* SOFT_ENCRYPT */ +#ifdef APCLI_SUPPORT + /*unicast frame for apcli get pn.*/ + rx_get_pn(pRxBlk,pRxInfo); +#endif /* APCLI_SUPPORT */ + if (!((pHeader->Frag == 0) && (pFmeCtrl->MoreFrag == 0))) + { + /* + re-assemble the fragmented packets, return complete + frame (pRxPacket) or NULL + */ + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } + + if (pRxPacket) + { + /* process complete frame */ + if (bFragment && (pFmeCtrl->Wep) && (pEntry->WepStatus == Ndis802_11TKIPEnable)) + { + pRxBlk->DataSize -= 8; /* Minus MIC length */ + + /* For TKIP frame, calculate the MIC value */ + if (APCheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) + return; + } + + if (pEntry) + { + pEntry->RxBytes += pRxBlk->MPDUtotalByteCnt; + pEntry->OneSecRxBytes += pRxBlk->MPDUtotalByteCnt; + INC_COUNTER64(pEntry->RxPackets); + } +#ifdef IKANOS_VX_1X0 + RTMP_SET_PACKET_IF(pRxPacket, FromWhichBSSID); +#endif /* IKANOS_VX_1X0 */ + +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + RTMP_SET_PACKET_WCID(pRxPacket, pRxBlk->wcid); +#endif /* MAC_REPEATER_SUPPORT */ + APRxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + else + { + /* + just return because RTMPDeFragmentDataFrame() will release rx + packet, if packet is fragmented + */ + return; + } + return; + +err: + /* Increase received error packet counter per BSS */ + if (pFmeCtrl->FrDs == 0 && + pRxInfo->U2M && + pRxBlk->bss_idx < pAd->ApCfg.BssidNum) + { + pAd->ApCfg.MBSSID[pRxBlk->bss_idx].RxDropCount ++; + pAd->ApCfg.MBSSID[pRxBlk->bss_idx].RxErrorCount ++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + if (pEntry != NULL && IS_ENTRY_CLIENT(pEntry) && pEntry->Sst == SST_ASSOC) + { + pEntry->RxDropCount++; + pEntry->RxErrorCount++; + } +#endif +#endif + } + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + return; +} + + +#ifdef HDR_TRANS_SUPPORT +VOID APHandleRxDataFrame_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR FromWhichBSSID = BSS0; + UCHAR OldPwrMgmt = PWR_ACTIVE; /* UAPSD AP SUPPORT */ + UCHAR UserPriority = 0; +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(MWDS) + BOOLEAN bWdsPacket = FALSE; +#endif /* WDS_SUPPORT || CLIENT_WDS || defined(MWDS) */ + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; + COUNTER_RALINK *pCounter = &pAd->RalinkCounters; + UCHAR *pData; + +#ifdef DBG +//+++Add by shiang for debug +if (0 /*!(pRxInfo->Mcast || pRxInfo->Bcast)*/){ + DBGPRINT(RT_DEBUG_OFF, ("-->%s(%d): Dump Related Info!\n", __FUNCTION__, __LINE__)); + hex_dump("DataFrameHeader", pHeader, 36); + hex_dump("DataFramePayload", pRxBlk->pTransData , pRxBlk->TransDataSize); +} +//---Add by shiangf for debug +#endif + + if (APCheckVaildDataFrame(pAd, pRxBlk) != TRUE) + { + goto err; + } + +#ifdef IDS_SUPPORT + /* + Replay attack detection + Detect a spoofed data frame from a rogue AP, ignore it. + */ + if (pFmeCtrl->FrDs == 1 && + (RTMPReplayAttackDetection(pAd, pHeader->Addr2, pRxBlk) == TRUE)) + { + goto err; + } +#endif /* IDS_SUPPORT */ + + /* handle WDS */ + if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 1)) + { + do + { +#ifdef CLIENT_WDS + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry != NULL) + { + if (IS_ENTRY_CLIWDS(pEntry)) + ; + else if (IS_ENTRY_CLIENT(pEntry) + && (pEntry->Sst == SST_ASSOC)) + SET_ENTRY_CLIWDS(pEntry); + else + pEntry = NULL; + } + + if (pEntry != NULL) + { + FromWhichBSSID = pEntry->apidx; + + /* Increase received byte counter per BSS */ + if (FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if (pMbss != NULL) + { + pMbss->ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount ++; + } + } + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + bWdsPacket = TRUE; + CliWds_ProxyTabUpdate(pAd, pEntry->Aid, pHeader->Octet); + break; + } +#endif /* CLIENT_WDS */ + +#ifdef MWDS + if(VALID_WCID(pRxBlk->wcid)) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if(pEntry && + IS_MWDS_OPMODE_AP(pEntry)) + { + /* + It means this source entry has moved to another one and hidden behind it. + So delete this source entry! + */ + MAC_TABLE_ENTRY *pMovedEntry = MacTableLookup(pAd, pHeader->Octet); + if(pMovedEntry) + MacTableDeleteEntry(pAd, pMovedEntry->wcid, pMovedEntry->Addr); + FromWhichBSSID = pEntry->apidx; + /* Increase received byte counter per BSS */ + if (FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if (pMbss != NULL) + { + pMbss->ReceivedByteCount += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount++; + } + } + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + bWdsPacket = TRUE; + MWDSProxyTabUpdate(pAd, pEntry->wcid, pHeader->Octet); + break; + } + else + pEntry = NULL; +#ifdef APCLI_SUPPORT + if (VALID_WCID(pRxBlk->wcid)) + pEntry = ApCliTableLookUpByWcid(pAd, pRxBlk->wcid, pHeader->Addr2); + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if(pEntry && + IS_MWDS_OPMODE_APCLI(pEntry) && + (pEntry->wdev_idx < MAX_APCLI_NUM)) + { + /* + For ApCli, we have to avoid to delete the bridge MAC(SA) and AP MAC(TA) + is the same case. + */ + if(!MAC_ADDR_EQUAL(pHeader->Octet, pEntry->Addr)) + { + /* + It means this source entry has moved to another one and hidden behind it. + So delete this source entry! + */ + MAC_TABLE_ENTRY *pMovedEntry = MacTableLookup(pAd, pHeader->Octet); + if(pMovedEntry) + MacTableDeleteEntry(pAd, pMovedEntry->wcid, pMovedEntry->Addr); + } + + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + if(pApCliEntry) + { + NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); + if(MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr) || + MAC_ADDR_EQUAL(pHeader->Octet, pApCliEntry->wdev.if_addr)) + goto err; + } + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_APCLI; + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + bWdsPacket = TRUE; + + /* Process broadcast packets */ + if (pRxInfo->Mcast || pRxInfo->Bcast) + { + /* Process the received broadcast frame for AP-Client. */ + if (!ApCliHandleRxBroadcastFrame(pAd, pRxBlk, pEntry, FromWhichBSSID)) + goto err; + return; + } + break; + } + else + pEntry = NULL; +#endif /* APCLI_SUPPORT */ +#endif /* MWDS */ +#ifdef WDS_SUPPORT + /* handle WDS */ + if (!pEntry) + { + /* + The WDS frame only can go here when in auto learning mode and + this is the first trigger frame from peer + + So we check if this is un-registered WDS entry by call function + "FindWdsEntry()" + */ + bWdsPacket = TRUE; + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxBlk->wcid, pHeader->Addr2, pRxBlk->rx_rate.field.MODE); + + + /* have no valid wds entry exist, then discard the incoming packet.*/ + if (!pEntry || !WDS_IF_UP_CHECK(pAd, pEntry->wdev_idx)) + goto err; + + /*receive corresponding WDS packet, disable TX lock state (fix WDS jam issue) */ + if(pEntry && (pEntry->LockEntryTx == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Receive WDS packet, disable TX lock state!\n")); + pEntry->ContinueTxFailCnt = 0; + pEntry->LockEntryTx = FALSE; + } + + } + + if (pEntry) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_WDS; + break; + } +#endif /* WDS_SUPPORT */ + } while(FALSE); + + if (pEntry == NULL) + { + /* have no WDS or MESH support */ + /* drop the packet */ + goto err; + } + } + /* handle APCLI. */ + else if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 0)) + { +#ifdef APCLI_SUPPORT + if (VALID_WCID(pRxBlk->wcid)) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry) + { + // TODO: shiang, add MAC_REPEATER_SUPPORT code here!! + if (!(pEntry && APCLI_IF_UP_CHECK(pAd, pEntry->wdev_idx))) + { + goto err; + } + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx]; + if (pApCliEntry) + { + NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); + if(MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr)) + goto err; + } +#ifdef MWDS + if(IS_MWDS_OPMODE_APCLI(pEntry)) + goto err; +#endif /* MWDS */ + FromWhichBSSID = pEntry->wdev_idx + MIN_NET_DEVICE_FOR_APCLI; + RX_BLK_SET_FLAG(pRxBlk, fRX_APCLI); + + /* Process broadcast packets */ + if (pRxInfo->Mcast || pRxInfo->Bcast) + { + /* Process the received broadcast frame for AP-Client. */ + if (!ApCliHandleRxBroadcastFrame(pAd, pRxBlk, pEntry, FromWhichBSSID)) + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } + return; + } + } + else +#endif /* APCLI_SUPPORT */ + { + /* no APCLI support */ + /* release packet */ + goto err; + } + } + else + { + pEntry = PACInquiry(pAd, pRxBlk->wcid); + + /* can't find associated STA entry then filter invlid data frame */ + if (!pEntry) + { + goto err; + } + + FromWhichBSSID = pEntry->apidx; + +#ifdef STATS_COUNT_SUPPORT + /* Increase received byte counter per BSS */ + if (pHeader->FC.FrDs == 0 && + pRxInfo->U2M && + FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; +#ifdef CUSTOMER_DCC_FEATURE + UCHAR *pDA = pRxBlk->pHeader->Addr3; +#endif + if (pMbss != NULL) + { + pMbss->ReceivedByteCount.QuadPart += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount ++; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.RxDataCount++; + pAd->RadioStatsCounter.TotalRxCount++; +#ifdef MBSS_802_11_STATISTICS + if (((*pDA) & 0x1) == 0x01) { + if(IS_BROADCAST_MAC_ADDR(pDA)) + pMbss->bcPktsRx++; + else + pMbss->mcPktsRx++; + } + else + pMbss->ucPktsRx++; + if (pEntry->Sst == SST_ASSOC) + { + pEntry->ReceivedByteCount += pRxBlk->MPDUtotalByteCnt; + pEntry->RxCount++; + } + { + UINT32 Length, Index; + HTTRANSMIT_SETTING HTSetting; + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = pRxBlk->rx_rate.field.MODE; + HTSetting.field.BW = pRxBlk->rx_rate.field.BW; + HTSetting.field.ShortGI = pRxBlk->rx_rate.field.ShortGI; + HTSetting.field.MCS = pRxBlk->rx_rate.field.MCS; + Length = pRxBlk->MPDUtotalByteCnt; + GetMultShiftFactorIndex(HTSetting, &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pEntry); + } +#endif +#endif + } + } + + /* update multicast counter */ + if (IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ + } + + ASSERT(pEntry->Aid == pRxBlk->wcid); + + + +#ifdef DOT11_N_SUPPORT + /* check Atheros Client */ + // TODO: shiang@PF#2, is this atheros protection still necessary here???? + if (!pEntry->bIAmBadAtheros && (pFmeCtrl->Retry) && + (pRxBlk->rx_rate.field.MODE < MODE_VHT) && + (pRxInfo->AMPDU == 1) && (pAd->CommonCfg.bHTProtect == TRUE) + ) + { + if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE) + RTMP_UPDATE_PROTECT(pAd, 8 , ALLN_SETPROTECT, FALSE, FALSE); + pEntry->bIAmBadAtheros = TRUE; + + } +#endif /* DOT11_N_SUPPORT */ + + /* update rssi sample */ + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + + if (pRxInfo->U2M) + { + pEntry->LastRxRate = pRxBlk->rx_rate.word; +#ifdef SMART_MESH + Update_CliPktStats(pAd, pEntry, pHeader->Sequence, FALSE); +#endif /* SMART_MESH */ + +#ifdef TXBF_SUPPORT + if (pRxBlk->rx_rate.field.ShortGI) + pEntry->OneSecRxSGICount++; + else + pEntry->OneSecRxLGICount++; +#endif // TXBF_SUPPORT // + } + + pAd->ApCfg.LastSNR0 = (UCHAR)(pRxBlk->snr[0]); + pAd->ApCfg.LastSNR1 = (UCHAR)(pRxBlk->snr[1]); +#ifdef DOT11N_SS3_SUPPORT + pAd->ApCfg.LastSNR2 = (UCHAR)(pRxBlk->snr[2]); +#endif /* DOT11N_SS3_SUPPORT */ + pEntry->freqOffset = (CHAR)(pRxBlk->freq_offset); + pEntry->freqOffsetValid = TRUE; + + + /* Gather PowerSave information from all valid DATA frames. IEEE 802.11/1999 p.461 */ + /* must be here, before no DATA check */ + + + pData = (UCHAR *)pHeader; + + + /* 1: PWR_SAVE, 0: PWR_ACTIVE */ + OldPwrMgmt = RtmpPsIndicate(pAd, pHeader->Addr2, pEntry->Aid, pFmeCtrl->PwrMgmt); +#ifdef UAPSD_SUPPORT + if (pFmeCtrl->PwrMgmt) + { + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE)) && + (pFmeCtrl->SubType & 0x08)) + { + /* + In IEEE802.11e, 11.2.1.4 Power management with APSD, + If there is no unscheduled SP in progress, the unscheduled SP begins + when the QAP receives a trigger frame from a non-AP QSTA, which is a + QoS data or QoS Null frame associated with an AC the STA has + configured to be trigger-enabled. + */ + /* + In WMM v1.1, A QoS Data or QoS Null frame that indicates transition + to/from Power Save Mode is not considered to be a Trigger Frame and + the AP shall not respond with a QoS Null frame. + */ + /* Trigger frame must be QoS data or QoS Null frame */ + UCHAR OldUP; + + OldUP = (*(pData+LENGTH_802_11) & 0x07); + if (OldPwrMgmt == PWR_SAVE) + UAPSD_TriggerFrameHandle(pAd, pEntry, OldUP); + /* End of if */ + } + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */ + if ((pFmeCtrl->SubType & 0x04) && (pFmeCtrl->Order == 0)) /* bit 2 : no DATA */ + { + /* Increase received drop packet counter per BSS */ + if (pFmeCtrl->FrDs == 0 && + pRxInfo->U2M && + pRxBlk->bss_idx < pAd->ApCfg.BssidNum) + { + pAd->ApCfg.MBSSID[pRxBlk->bss_idx].RxDropCount++; + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* + update RxBlk->pData, DataSize + 802.11 Header, QOS, HTC, Hw Padding + */ + + /* 1. skip 802.11 HEADER */ +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(MESH_SUPPORT) || defined(MWDS) + if (FALSE +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(MWDS) + || bWdsPacket +#endif /* WDS_SUPPORT || CLIENT_WDS || defined(MWDS) */ + ) + { + pData += LENGTH_802_11_WITH_ADDR4; + } + else +#endif /* WDS_SUPPORT || CLIENT_WDS || MESH_SUPPORT || defined(MWDS) */ + { + pData += LENGTH_802_11; + } + + /* 2. QOS */ + if (pFmeCtrl->SubType & 0x08) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); + UserPriority = *(pData) & 0x0f; + + + /* count packets priroity more than BE */ + detect_wmm_traffic(pAd, UserPriority, 0); + /* bit 7 in QoS Control field signals the HT A-MSDU format */ + if ((*pData) & 0x80) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); + + } + + /* skip QOS contorl field */ + pData += 2; + } + pRxBlk->UserPriority = UserPriority; + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap && + (pHeader->FC.SubType & 0x08) && pHeader->FC.Order) + { + handleHtcField(pAd, pRxBlk); + } +#endif /* TXBF_SUPPORT */ + + /* 3. Order bit: A-Ralink or HTC+ */ + if (pFmeCtrl->Order) + { +#ifdef AGGREGATION_SUPPORT + if ( +#ifdef DOT11_N_SUPPORT + (pRxBlk->rx_rate.field.MODE < MODE_HTMIX) && +#endif /* DOT11_N_SUPPORT */ + (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE)) + ) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); + } + else +#endif + { + RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); + /* skip HTC control field */ + pData += 4; + } + } + + /* 4. skip HW padding */ + if (pRxInfo->L2PAD) + { + /* just move pData pointer */ + /* because DataSize excluding HW padding */ + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pData += 2; + } + + if (pRxInfo->BA) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); + + /* incremented by the number of MPDUs */ + /* received in the A-MPDU when an A-MPDU is received. */ + pCounter->MPDUInReceivedAMPDUCount.u.LowPart ++; + } + +#ifdef SOFT_ENCRYPT + /* Use software to decrypt the encrypted frame if necessary. + If a received "encrypted" unicast packet(its WEP bit as 1) + and it's passed to driver with "Decrypted" marked as 0 in RxD. */ + if ((pHeader->FC.Wep == 1) && (pRxInfo->Decrypted == 0)) + { + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, + UserPriority, + &pEntry->PairwiseKey, + pRxBlk->pTransData + 14, + &(pRxBlk->TransDataSize)) != NDIS_STATUS_SUCCESS) + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + /* Record the Decrypted bit as 1 */ + pRxInfo->Decrypted = 1; + } +#endif /* SOFT_ENCRYPT */ + + if (!((pHeader->Frag == 0) && (pFmeCtrl->MoreFrag == 0))) + { + /* re-assemble the fragmented packets */ + /* return complete frame (pRxPacket) or NULL */ + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } + + if (pRxPacket) + { + /* process complete frame */ + if (bFragment && (pFmeCtrl->Wep) && (pEntry->WepStatus == Ndis802_11TKIPEnable)) + { + /* Minus MIC length */ + pRxBlk->DataSize -= 8; + + /* For TKIP frame, calculate the MIC value */ + if (APCheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) + { + return; + } + } + + if (pEntry) + { + pEntry->RxBytes+=pRxBlk->MPDUtotalByteCnt; + INC_COUNTER64(pEntry->RxPackets); + } +#ifdef IKANOS_VX_1X0 + RTMP_SET_PACKET_IF(pRxPacket, FromWhichBSSID); +#endif /* IKANOS_VX_1X0 */ + APRxDataFrameAnnounce_Hdr_Trns(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + else + { + /* just return */ + /* because RTMPDeFragmentDataFrame() will release rx packet, */ + /* if packet is fragmented */ + return; + } + return; + +err: + /* Increase received error packet counter per BSS */ + if (pFmeCtrl->FrDs == 0 && + pRxInfo->U2M && + pRxBlk->bss_idx < pAd->ApCfg.BssidNum) + { + pAd->ApCfg.MBSSID[pRxBlk->bss_idx].RxDropCount ++; + pAd->ApCfg.MBSSID[pRxBlk->bss_idx].RxErrorCount ++; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + if (pEntry != NULL && IS_ENTRY_CLIENT(pEntry) && pEntry->Sst == SST_ASSOC) + { + pEntry->RxDropCount++; + pEntry->RxErrorCount++; + } +#endif +#endif + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + +} +#endif /* HDR_TRANS_SUPPORT */ + + +BOOLEAN APFowardWirelessStaToWirelessSta( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + BOOLEAN bAnnounce, bDirectForward; + UCHAR *pHeader802_3; + PNDIS_PACKET pForwardPacket; + BOOLEAN bResult; +#ifdef MWDS + UCHAR wcid = 0; + UCHAR *pSrcAddr = NULL; +#endif /* MWDS */ + +#ifdef INF_AMAZON_SE + /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ + RTMP_SET_PACKET_NOBULKOUT(pPacket, FALSE); +#endif /* INF_AMAZON_SE */ + +#ifdef APCLI_SUPPORT + /* have no need to forwad the packet to WM */ + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) + /* need annouce to upper layer */ + return TRUE; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + /* have no need to forwad the packet to WM */ + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) + /* need annouce to upper layer */ + return TRUE; +#endif /* WDS_SUPPORT */ + + pEntry = NULL; + bAnnounce = TRUE; + bDirectForward = FALSE; + + pHeader802_3 = GET_OS_PKT_DATAPTR(pPacket); + + if (pHeader802_3[0] & 0x01) + { + /* + * In the case, the BSS have only one STA behind. + * AP have no necessary to forward the M/Bcase packet back to STA again. + */ + if ( + ((FromWhichBSSID < MAX_MBSSID_NUM(pAd)) && + (FromWhichBSSID < HW_BEACON_MAX_NUM) && + (pAd->ApCfg.MBSSID[FromWhichBSSID].StaCount > 1))) + { + if (pAd->ApCfg.MBSSID[FromWhichBSSID].IsolateInterStaMBCast == FALSE) + { + bDirectForward = TRUE; + } + } + + /* tell caller to deliver the packet to upper layer */ + bAnnounce = TRUE; + } + else + { + /* if destinated STA is a associated wireless STA */ + pEntry = MacTableLookup(pAd, pHeader802_3); + if (pEntry && (pEntry->Sst == SST_ASSOC) && IS_ENTRY_CLIENT(pEntry)) + bDirectForward = TRUE; +#ifdef MWDS + else if(!pEntry) + { + if(MWDSProxyLookup(pAd, pHeader802_3, FALSE, &wcid)) + { + if (VALID_WCID(wcid)) + pEntry = &pAd->MacTab.Content[wcid]; + if(pEntry && (pEntry->Sst == SST_ASSOC) && IS_MWDS_OPMODE_AP(pEntry)) + bDirectForward = TRUE; + } + } +#endif /* MWDS */ + if(bDirectForward) + { + bAnnounce = FALSE; + + if (FromWhichBSSID == pEntry->apidx) + {/* STAs in same SSID */ + if ((pAd->ApCfg.MBSSID[pEntry->apidx].IsolateInterStaTraffic == TRUE)) + { + /* release the packet */ + bDirectForward = FALSE; + bAnnounce = FALSE; + } + } + else + {/* STAs in different SSID */ + if (pAd->ApCfg.IsolateInterStaTrafficBTNBSSID == TRUE || + ((FromWhichBSSID < MAX_MBSSID_NUM(pAd)) && + (FromWhichBSSID < HW_BEACON_MAX_NUM) && + (pAd->ApCfg.MBSSID[pEntry->apidx].wdev.VLAN_VID != pAd->ApCfg.MBSSID[FromWhichBSSID].wdev.VLAN_VID))) + /* destination VLAN ID != source VLAN ID */ + { + /* + Do not need to care WDS mode because packets from a + WDS interface will be passed to upper layer for bridging. + */ + bDirectForward = FALSE; + bAnnounce = FALSE; + } + } + } + else + { + /* announce this packet to upper layer (bridge) */ + bAnnounce = TRUE; + } + } + + if (bDirectForward) + { + /* build an NDIS packet */ + pForwardPacket = RTMP_DUPLICATE_PACKET(pAd, pPacket, FromWhichBSSID); + + if (pForwardPacket == NULL) + { + return bAnnounce; + } + + { + /* 1.1 apidx != 0, then we need set packet mbssid attribute. */ + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pForwardPacket, MAIN_MBSSID); /* set a default value */ + if (pEntry && (pEntry->apidx != 0)) + { + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pForwardPacket, pEntry->apidx); + if ( pEntry && pEntry->wcid != MCAST_WCID) + { + RTMP_SET_PACKET_WDEV(pPacket, pEntry->wdev->wdev_idx); + } + } + + /* send bc/mc frame back to the same bss */ + if (!pEntry) + { + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pForwardPacket, FromWhichBSSID); + + + //also need to send back to same bss + if ((FromWhichBSSID >= 0) && + (FromWhichBSSID < pAd->ApCfg.BssidNum) && + (FromWhichBSSID < MAX_MBSSID_NUM(pAd)) && + (FromWhichBSSID < HW_BEACON_MAX_NUM)) + { + RTMP_SET_PACKET_WDEV(pForwardPacket, pAd->ApCfg.MBSSID[FromWhichBSSID].wdev.wdev_idx); + } + } + + RTMP_SET_PACKET_WCID(pForwardPacket, pEntry ? pEntry->wcid : MCAST_WCID); + RTMP_SET_PACKET_MOREDATA(pForwardPacket, FALSE); + +#ifdef INF_AMAZON_SE + /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ + RTMP_SET_PACKET_NOBULKOUT(pForwardPacket, TRUE); +#endif /* INF_AMAZON_SE */ + +#ifdef REDUCE_TCP_ACK_SUPPORT + ReduceAckUpdateDataCnx(pAd,pForwardPacket); + if (ReduceTcpAck(pAd,pForwardPacket) == FALSE) +#endif /* REDUCE_TCP_ACK_SUPPORT */ + { + bResult = APSendPacket(pAd, pForwardPacket); +#ifdef MWDS + /* send bc/mc frame back to the same bss */ + if (!pEntry && (bResult == NDIS_STATUS_SUCCESS)) + { + pSrcAddr = pHeader802_3+MAC_ADDR_LEN; + MWDSSendClonePacket(pAd,pPacket,pSrcAddr); + } +#endif /* MWDS */ + } + } + + /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + return bAnnounce; +} + +/* + ======================================================================== + 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 APInsertPsQueue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN 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); + 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 + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + } + + /* 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); + } + return NDIS_STATUS_SUCCESS; +} + +#ifdef APCLI_SUPPORT +VOID ApCliRTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN PMAC_TABLE_ENTRY pMacEntry, + IN USHORT PwrMgmt) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; + + pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->wdev_idx]; + wdev = &pApCliEntry->wdev; + + /* WPA 802.1x secured port control */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) || + (wdev->IEEE8021X == TRUE) +#ifdef WAPI_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && + (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + return; + } + + NdisZeroMemory(NullFrame, 48); + Length = sizeof(HEADER_802_11); + + pHeader_802_11 = (PHEADER_802_11) NullFrame; + + pHeader_802_11->FC.Type = FC_TYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_DATA_NULL; + pHeader_802_11->FC.ToDs = 1; + + COPY_MAC_ADDR(pHeader_802_11->Addr1, pMacEntry->Addr); +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry && (pMacEntry->bReptCli == TRUE)) + COPY_MAC_ADDR(pHeader_802_11->Addr2, pMacEntry->ReptCliAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(pHeader_802_11->Addr2, pApCliEntry->wdev.if_addr); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pMacEntry->Addr); + + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = PwrMgmt; + + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + pHeader_802_11->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + + /* Prepare QosNull function frame */ + if (bQosNull) + { + pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + NullFrame[Length] = 0; + NullFrame[Length+1] = 0; + Length += 2;/* if pad with 2 bytes for alignment, APSD will fail */ + } + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); + +} +#endif/*APCLI_SUPPORT*/ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_dls.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_dls.c new file mode 100644 index 000000000..f004620ec --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_dls.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_ftkd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_ftkd.c new file mode 100644 index 000000000..3f14fbda7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_ftkd.c @@ -0,0 +1,1799 @@ +/**************************************************************************** + * 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 Key Distribution Protocol (FT KDP) body. + + Overview: + + 1. A station associates to us, send out a broadcast ADD-Notify packet. + + ASSOC --> + FT_KDP_EVENT_INFORM(FT_KDP_SIG_FT_ASSOCIATION) --> + FT_KDP_EventInform(FT_KDP_SIG_FT_ASSOCIATION) --> + Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> + Send ADD-Notify packet, IAPP_UDP_PacketSend(), IAPP_L2UpdateFrameSend() + + 2. When receiving a ADD-Notify packet, send a unicast SSB packet to + request PMK-R1 key for the station with our R0KH. + + IAPP daemon, IAPP_RcvHandlerUdp() --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + FT_KDP_StationInform() --> + Notify IAPP daemon, FT_KDP_EventInform(FT_KDP_SIG_KEY_REQ_AUTO) --> + Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> + Send SSB packet with R0KHID = 0, by using TCP or UDP based on peerIP + + 3. A station reassociates to us, send out a MOVE-Request packet. + + REASSOC --> + FT_KDP_EVENT_INFORM(FT_KDP_SIG_FT_REASSOCIATION) --> + FT_KDP_EventInform(FT_KDP_SIG_FT_REASSOCIATION) --> + Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> + Send MOVE-Request packet by using TCP or UDP, IAPP_L2UpdateFrameSend() + + 4. When receiving a MOVE-Request packet, delete the STA MAC entry. + + IAPP daemon, IAPP_RcvHandlerUdp()/ IAPP_RcvHandlerTcp() --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + RT_SET_DEL_MAC_ENTRY --> + Send MOVE-Response packet by using TCP, FT_KDP_MoveFrameSend() + + 5. When receiving a MOVE-Response packet, nothing to do. + + 6. When receiving a SSB packet (i.e. key request), send a unicast SAB + packet to response the key to the R1KH. + + IAPP daemon --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + FT_KDP_IOCTL_KEY_REQ() --> + Notify IAPP daemon, FT_KDP_EventInform(FT_KDP_SIG_KEY_RSP_AUTO) --> + Send SAB packet with my R0KHID, FT_KDP_SecurityBlockSend() by using TCP + + 7. When receiving a SAB packet (i.e. key response), set the PMK-R1 key. + + IAPP daemon --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + FT_KDP_KeyResponseToUs() + + 8. Send a information broadcast to the LAN periodically. + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + +#include "rt_config.h" +#include "ft_cmm.h" + +#define TYPE_FUNC +#define FT_KDP_DEBUG +#define FT_KDP_FUNC_TEST +/*#define FT_KDP_EMPTY */ /* empty codes to debug */ + +#define IAPP_SHOW_IP_HTONL(__IP) \ + (htonl(__IP) >> 24) & 0xFF, \ + (htonl(__IP) >> 16) & 0xFF, \ + (htonl(__IP) >> 8) & 0xFF, \ + (htonl(__IP) & 0xFF) + +#define IAPP_DAEMON_CMD_PARSE(__pInfo, __InfoLen, __PeerIP, __pData, __DataLen) \ + NdisMoveMemory(&__PeerIP, __pInfo, FT_IP_ADDRESS_SIZE); \ + __pData = (UCHAR *)(__pInfo + FT_IP_ADDRESS_SIZE); \ + __DataLen = __InfoLen - FT_IP_ADDRESS_SIZE; + +/* private variable */ +UINT32 FT_KDP_MemAllocNum, FT_KDP_MemFreeNum; + +/* extern variable */ +#ifdef FT_KDP_FUNC_TEST +extern UCHAR gFT_MAC_OldAP[]; +#endif /* FT_KDP_FUNC_TEST */ + +/* private function prototype */ +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +BOOLEAN FT_KDP_R0KH_InfoAdd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP); +VOID FT_KDP_R0KH_InfoDel( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP); +static BOOLEAN FT_KDP_R0KH_InfoGet( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pR0KHID, + INOUT UCHAR *pMAC, + OUT UINT32 *pIP); +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + + + +/* public function */ +/* +======================================================================== +Routine Description: + Initialize FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_Init( + IN PRTMP_ADAPTER pAd) +{ +#ifndef FT_KDP_EMPTY + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 1) + return; + /* End of if */ + + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Initialize FT KDP Module...\n")); + + /* allocate control block */ + FT_MEM_ALLOC(pAd, &pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK, sizeof(FT_KDP_CTRL_BLOCK)); + if (pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate control block fail!\n")); + return; + } /* End of if */ + + /* init spin lock */ + NdisAllocateSpinLock(pAd, &(pAd->ApCfg.FtTab.FT_KdpLock)); + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* init event list */ + initList(&(FT_KDP_CB->EventList)); +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + /* init R0KH information record */ + FT_KDP_CB->R0KH_InfoHead = NULL; + FT_KDP_CB->R0KH_InfoTail = NULL; + FT_KDP_CB->R0KH_Size = 0; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + +#ifdef FT_KDP_FUNC_INFO_BROADCAST + RTMPInitTimer(pAd, &FT_KDP_CB->TimerReport, + GET_TIMER_FUNCTION(FT_KDP_InfoBroadcast), + (PVOID)pAd, TRUE); + RTMPSetTimer(&FT_KDP_CB->TimerReport, FT_KDP_INFO_BC_PERIOD_TIME); +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ +#endif /* FT_KDP_EMPTY */ + + pAd->ApCfg.FtTab.FlgIsFtKdpInit = 1; +} /* End of FT_KDP_Init */ + + +/* +======================================================================== +Routine Description: + Release FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_Release( + IN PRTMP_ADAPTER pAd) +{ +#ifndef FT_KDP_EMPTY +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + FT_KDP_R0KH_INFO *pInfoHead, *pInfo; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + return; + /* End of if */ + + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Release FT KDP Module...\n")); + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* free event list */ + FT_KDP_EVT_LIST_EMPTY(pAd, &(FT_KDP_CB->EventList)); +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + /* free all R0KH information */ + pInfoHead = FT_KDP_CB->R0KH_InfoHead; + while(pInfoHead != NULL) + { + pInfo = pInfoHead; + pInfoHead = pInfoHead->pNext; + + FT_MEM_FREE(pAd, pInfo); + } /* End of while */ +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + if (pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK != NULL) + { + FT_MEM_FREE(pAd, pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK); + pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK = NULL; + } /* End of if */ + +#ifdef FT_KDP_FUNC_INFO_BROADCAST +{ + BOOLEAN Status; + RTMPCancelTimer(&FT_KDP_CB->TimerReport, &Status); +} +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + + /* free spin lock */ + NdisFreeSpinLock(&(pAd->ApCfg.FtTab.FT_KdpLock)); +#endif /* FT_KDP_EMPTY */ + + pAd->ApCfg.FtTab.FlgIsFtKdpInit = 0; +} /* End of FT_KDP_Release */ + + +/* +======================================================================== +Routine Description: + Inform us a event occurs. + +Arguments: + pAd - WLAN control block pointer + ApIdx - MBSS ID + EventId - which event, such as FT_KDP_SIG_FT_ASSOCIATION + *pEvent - event body + EventLen - event body length + PeerIP - peer IP address + pCB - for special use (such as FT_KDP_SIG_ACTION) + +Return Value: + None + +Note: + EventId *pEvent + -------------------------------------------------------------------- + FT_KDP_SIG_FT_ASSOCIATION FT_KDP_EVT_ASSOC + FT_KDP_SIG_FT_REASSOCIATION FT_KDP_EVT_REASSOC + FT_KDP_SIG_KEY_TIMEOUT yet implement + FT_KDP_SIG_KEY_REQ FT_KDP_EVT_KEY_ELM + FT_KDP_SIG_ACTION WLAN Frame Body (Start from Category field) + pCB == FT_KDP_EVT_ACTION + +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_EventInform( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + IN UCHAR EventId, + IN VOID *pEvent, + IN UINT16 EventLen, + IN UINT32 PeerIP, + IN VOID *pCB) +{ +#ifndef FT_KDP_EMPTY +#ifndef FT_KDP_FUNC_SOCK_COMM + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR Size; +#endif /* FT_KDP_FUNC_SOCK_COMM */ + FT_KDP_SIGNAL *pFtKdp; + FT_KDP_EVT_HEADER EvtHdr; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + +#ifndef FT_KDP_FUNC_SOCK_COMM + CHECK_PID_LEGALITY(pObj->IappPid) + { + /* valid, can do next step */ + } + else + { + return; + } + /* End of if */ + + FT_KDP_EVT_LIST_SIZE_GET(pAd, &FT_KDP_CB->EventList, Size); + if (Size > FT_KDP_EVENT_MAX) + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Queued Events are too much!\n")); + return; + } /* End of if */ +#endif /* FT_KDP_FUNC_SOCK_COMM */ + + /* make up event content */ + NdisZeroMemory(&EvtHdr, sizeof(FT_KDP_EVT_HEADER)); + FT_MEM_ALLOC(pAd, &pFtKdp, sizeof(FT_KDP_SIGNAL)); + if (pFtKdp == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Allocate signal content fail!\n")); + return; + } /* End of if */ + pFtKdp->Sig = EventId; + + /* handle different event */ + switch(EventId) + { + case FT_KDP_SIG_FT_ASSOCIATION: + { + /* a station associates to us */ + + /* + When a STA uses the 802.11 Association Request, rather than + the Reassociation Request, the IAPP may not be able to notify + the AP at which the STA was previously associated of the new + association. + */ + + FT_KDP_EVT_ASSOC *pEvtAssoc; + + pEvtAssoc = (FT_KDP_EVT_ASSOC *)pEvent; + + pFtKdp->Sequence = pEvtAssoc->SeqNum; + NdisMoveMemory(pFtKdp->MacAddr, pEvtAssoc->MacAddr, MAC_ADDR_LEN); + } + break; + + case FT_KDP_SIG_FT_REASSOCIATION: + { + /* a station reassociates to us */ + + /* + IEEE802.11f, 1.3 Inter-AP recommended practice overview + + In particular, the IAPP entity must be able to find and use + a RADIUS server to look up the IP addresses of other APs in + the ESS when given the Basic Service Set Identifier (BSSIDs) + of those other APs (if a local capability to perform such a + translation is not present), and to obtain security information + to protect the content of certain IAPP packets. + + Here we dont use any Radius server so sometimes we can not + send the MOVE-notify frame. + */ + + /* + The IAPP is not a routing protocol. The IAPP does not deal + directly with the delivery of 802.11 data frames to the STA; + instead the DS utilizes existing network functionality for + data frame delivery. + + When a STA associates or reassociates, the STA must ascertain + that its network layer address(es) is configured such that the + normal routing functions of the network attaching to the BSS + will correctly deliver the STAs traffic to the BSS to which + it is associated. + + Two mechanisms for a STA to accomplish this are to renew a + Dynamic Host Configuration Protocol (DHCP) lease for its IP + address and to use Mobile IP to obtain a local IP address. + */ + + FT_KDP_EVT_REASSOC *pEvtReAssoc; + + pEvtReAssoc = (FT_KDP_EVT_REASSOC *)pEvent; + + pFtKdp->Sequence = pEvtReAssoc->SeqNum; + NdisMoveMemory(pFtKdp->MacAddr, pEvtReAssoc->MacAddr, MAC_ADDR_LEN); + + /* try to get the IP of old AP */ + if (FT_KDP_R0KH_InfoGet(pAd, NULL, + pEvtReAssoc->OldApMacAddr, + &PeerIP) == FALSE) + { + } /* End of if */ + } + break; + + + case FT_KDP_SIG_KEY_TIMEOUT: + /* PMK-R1 Key timeout */ + break; + + + case FT_KDP_SIG_KEY_REQ: + { + FT_KDP_EVT_KEY_ELM *pEvtKeyReq; + + /* PMK-R1 Key Request */ + if (PeerIP != 0) + break; + /* End of if */ + + /* try to find the Peer IP address */ + pEvtKeyReq = (FT_KDP_EVT_KEY_ELM *)pEvent; + + if (FT_KDP_R0KH_InfoGet(pAd, pEvtKeyReq->KeyInfo.R0KHID, + NULL, &PeerIP) == FALSE) + { + + /* send a broadcast key request packet */ + } /* End of if */ + } + break; + + + case FT_KDP_SIG_ACTION: + { + /* forward FT Action frame by using RRB protocol */ + FT_KDP_EVT_ACTION *pActionCB = (FT_KDP_EVT_ACTION *)pCB; + + if (pCB == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> pCB == NULL!\n")); + return; + } /* End of if */ + + pFtKdp->Sequence = pActionCB->RequestType; + NdisMoveMemory(pFtKdp->MacAddr, pActionCB->MacDa, ETH_ALEN); + NdisMoveMemory(pFtKdp->MacAddrSa, pActionCB->MacSa, ETH_ALEN); + NdisMoveMemory(pFtKdp->CurrAPAddr, pActionCB->MacAp, ETH_ALEN); + } + break; + + + case FT_KDP_SIG_KEY_REQ_AUTO: + /* PMK-R1 Key Request */ + break; + + + case FT_KDP_SIG_KEY_RSP_AUTO: + /* PMK-R1 Key Response */ + break; + + + case FT_KDP_SIG_INFO_BROADCAST: + /* broadcast our AP information to neighbor APs */ + break; + + + case FT_KDP_SIG_AP_INFO_REQ: + /* request neighbor AP information */ + break; + + + case FT_KDP_SIG_AP_INFO_RSP: + /* response my information to a AP */ + break; + + + case FT_KSP_SIG_DEBUG_TRACE: + /* change the debug level of IAPP daemon */ + break; + + + case FT_KDP_SIG_TERMINATE: + /* terminate FT KDP daemon */ + break; + + + default: + /* error event */ + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Signal is not supported %d!\n", EventId)); + FT_MEM_FREE(pAd, pFtKdp); + return; + } /* End of switch */ + + /* init event content */ + EvtHdr.PeerIpAddr = PeerIP; + EvtHdr.EventLen = EventLen; + + NdisMoveMemory(pFtKdp->Content, &EvtHdr, sizeof(FT_KDP_EVT_HEADER)); + + if (pEvent != NULL) + { + NdisMoveMemory(pFtKdp->Content+sizeof(FT_KDP_EVT_HEADER), + pEvent, EventLen); + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Event ID = %d, EventLen = %d (%d, %d)\n", + EventId, EventLen, FT_KDP_MemAllocNum, FT_KDP_MemFreeNum)); + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* insert to the event queue */ + FT_KDP_EVT_LIST_INSERT_TAIL(pAd, &FT_KDP_CB->EventList, pFtKdp); + + /* inform FT KDP daemon to handle the event */ + if ((EventId == FT_KDP_SIG_TERMINATE) || + (EventId == FT_KSP_SIG_DEBUG_TRACE) || + (EventId == FT_KDP_SIG_FT_ASSOCIATION) || + (EventId == FT_KDP_SIG_FT_REASSOCIATION) || + (EventId == FT_KDP_SIG_KEY_REQ) || + (EventId == FT_KDP_SIG_KEY_TIMEOUT)) + { + /* + Note: in VxWorks, we can not send any signal to same task + which issues a ioctl path. + */ + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Send signal to ft kdp daemon... (EventLen = %d)\n", + EventLen)); + SendSignalToDaemon(SIGUSR2, pObj->IappPid, pObj->IappPid_nr); + } /* End of if */ +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_SOCK_COMM + /* inform FT KDP daemon to handle the event */ +{ + FT_DRV_ETH_HEADER Hdr8023, *pHdr8023 = &Hdr8023; + NDIS_PACKET *pPktComm; + UINT32 FrameLen; +#ifdef FT_OS_VXWORKS + END_OBJ *pEndEth; +#endif /* FT_OS_VXWORKS */ + + /* allocate a rx packet */ + pPktComm = RtmpOSNetPktAlloc(pAd, sizeof(RT_SIGNAL_STRUC)+LENGTH_802_3); + if (pPktComm != NULL) + { + /* make up 802.3 header */ + NdisMoveMemory(pHdr8023->DA, pAd->ApCfg.MBSSID[ApIdx].wdev.bssid, 6); + + /* can not send a packet with same SA & DA in 5VT board */ +/* NdisMoveMemory(pHdr8023->SA, pAd->ApCfg.MBSSID[ApIdx].Bssid, 6); */ + NdisZeroMemory(pHdr8023->SA, ETH_ALEN); + pHdr8023->SA[5] = 0x01; + pHdr8023->Len = IAPP_ETH_PRO; + + /* convert 802.11 to 802.3 packet */ +#ifdef FT_OS_VXWORKS + pEndEth = endFindByName("mirror", 0); + if (pEndEth != NULL) + { + /* + Sometimes if I use ra0 to send the command packet, daemon + can not receive the command packet! + So I use bridge to do the receive network interface. + + Support IEEE802.11r DS, must have bridge network interface. + */ + SET_OS_PKT_NETDEV(pPktComm, pEndEth->devObject.pDevice); + } + else +#endif /* FT_OS_VXWORKS */ + SET_OS_PKT_NETDEV(pPktComm, get_netdev_from_bssid(pAd, ApIdx)); + + OS_PKT_RESERVE(RTPKT_TO_OSPKT(pPktComm), 2); /* 16 byte align the IP header */ + NdisMoveMemory(OS_PKT_TAIL_BUF_EXTEND(RTPKT_TO_OSPKT(pPktComm), LENGTH_802_3), + pHdr8023, LENGTH_802_3); + + FrameLen = RT_SIGNAL_STRUC_HDR_SIZE+sizeof(FT_KDP_EVT_HEADER)+EventLen; + NdisMoveMemory(OS_PKT_TAIL_BUF_EXTEND(RTPKT_TO_OSPKT(pPktComm), FrameLen), + pFtKdp, FrameLen); + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Send a command (MBSS%d, Frame Len%d) to IAPP daemon.\n", + ApIdx, FrameLen)); + + /* pass this packet to upper layer */ + announce_802_3_packet(pAd, pPktComm, OPMODE_AP); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Allocate signal to ft kdp daemon fail!\n")); + } /* End of if */ +} +#endif + +#ifdef FT_KDP_FUNC_SOCK_COMM + FT_MEM_FREE(pAd, pFtKdp); +#endif /* FT_KDP_FUNC_SOCK_COMM */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_EventInform */ + + +/* +======================================================================== +Routine Description: + Get a event. + +Arguments: + pAd - WLAN control block pointer + **pFtKdp - the queued event; if NULL, no event is queued. + +Return Value: + None + +Note: + Used in IOCTL from FT KDP daemon. +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_EventGet( + IN PRTMP_ADAPTER pAd, + OUT FT_KDP_SIGNAL **pFtKdp) +{ +#ifndef FT_KDP_EMPTY +#ifndef FT_KDP_FUNC_SOCK_COMM + UCHAR Size; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + FT_KDP_EVT_LIST_SIZE_GET(pAd, &FT_KDP_CB->EventList, Size); + + /* check if any event is queued */ + if (Size <= 0) + { + *pFtKdp = NULL; + return; + } /* End of if */ + + /* return a event */ + FT_KDP_EVT_LIST_REMOVE_HEAD(pAd, &FT_KDP_CB->EventList, (*pFtKdp)); +#else + + *pFtKdp = NULL; +#endif /* FT_KDP_FUNC_SOCK_COMM */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_EventGet */ + + +/* +======================================================================== +Routine Description: + Inform us a AP request the key. + +Arguments: + pAd - WLAN control block pointer + PeerIP - the IP of R1KH, must not be 0 + *pNonce - the nonce for key request + *pEvtKeyReq - information for key request + +Return Value: + TRUE - request ok + FALSE - can not find the IP of R0KH + +Note: + If PeerIP == 0, search its IP from our information record. +======================================================================== +*/ +BOOLEAN TYPE_FUNC FT_KDP_KeyRequestToUs( + IN PRTMP_ADAPTER pAd, + IN UINT32 PeerIP, + IN UCHAR *pNonce, + IN FT_KDP_EVT_KEY_ELM *pEvtKeyReq) +{ +#ifndef FT_KDP_EMPTY + UINT32 IDR0KH; + UINT32 ApIdx; + + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return FALSE; + } /* End of if */ + + /* sanity check for PeerIP */ + if (PeerIP == 0) + return FALSE; + /* End of if */ + + /* sanity check for R0KHID */ +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req: R0KH-ID = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyReq->KeyInfo.R0KHID[0], + pEvtKeyReq->KeyInfo.R0KHID[1], + pEvtKeyReq->KeyInfo.R0KHID[2], + pEvtKeyReq->KeyInfo.R0KHID[3], + pEvtKeyReq->KeyInfo.R0KHID[4], + pEvtKeyReq->KeyInfo.R0KHID[5])); +#endif /* FT_KDP_DEBUG */ + + ApIdx = BSS0; + + for(IDR0KH=0; IDR0KHKeyInfo.R0KHID[IDR0KH] != 0x00) + { + /* check if the R0KHID is same as us (MBSS); if not, return FALSE */ + /* yet implement */ + } /* End of if */ + } /* End of for */ + + /* check if the request format is correct */ + if ((pEvtKeyReq->ElmId == FT_KDP_ELM_ID_PRI) && + (pEvtKeyReq->OUI[0] == FT_KDP_ELM_PRI_OUI_0) && + (pEvtKeyReq->OUI[1] == FT_KDP_ELM_PRI_OUI_1) && + (pEvtKeyReq->OUI[2] == FT_KDP_ELM_PRI_OUI_2)) + { +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req: Station MAC = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyReq->MacAddr[0], + pEvtKeyReq->MacAddr[1], + pEvtKeyReq->MacAddr[2], + pEvtKeyReq->MacAddr[3], + pEvtKeyReq->MacAddr[4], + pEvtKeyReq->MacAddr[5])); + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req: R1KH-ID = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyReq->KeyInfo.R1KHID[0], + pEvtKeyReq->KeyInfo.R1KHID[1], + pEvtKeyReq->KeyInfo.R1KHID[2], + pEvtKeyReq->KeyInfo.R1KHID[3], + pEvtKeyReq->KeyInfo.R1KHID[4], + pEvtKeyReq->KeyInfo.R1KHID[5])); +#endif /* FT_KDP_DEBUG */ + + /* calculate the PMK-R1 Key for the station vs. the AP */ + if (FT_QueryKeyInfoForKDP(pAd, ApIdx, pEvtKeyReq) == FALSE) + { + return FALSE; + } + + /* response the requested PMK-R1 Key to the R1KH */ + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp to Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); + + FT_KDP_EventInform(pAd, ApIdx, FT_KDP_SIG_KEY_RSP_AUTO, + (VOID *)pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), + PeerIP, NULL); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req format incorrect!\n")); + } /* End of if */ +#endif /* FT_KDP_EMPTY */ + + return FALSE; +} /* End of FT_KDP_KeyRequestToUs */ + + +/* +======================================================================== +Routine Description: + Inform us a AP response the key. + +Arguments: + pAd - WLAN control block pointer + *pInfo - key information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Nonce (8B) + FT_KDP_EVT_KEY_ELM structure +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_KeyResponseToUs( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen; + UCHAR *pData; + + FT_KDP_EVT_KEY_ELM *pEvtKeyRsp; + UCHAR *pNonce; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + + /* init */ + pNonce = pData; + pEvtKeyRsp = (FT_KDP_EVT_KEY_ELM *)(pNonce + FT_NONCE_SIZE); + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + /* check if the response format is correct */ + if ((pEvtKeyRsp->ElmId == FT_KDP_ELM_ID_PRI) && + (pEvtKeyRsp->OUI[0] == FT_KDP_ELM_PRI_OUI_0) && + (pEvtKeyRsp->OUI[1] == FT_KDP_ELM_PRI_OUI_1) && + (pEvtKeyRsp->OUI[2] == FT_KDP_ELM_PRI_OUI_2)) + { + PFT_R1HK_ENTRY pR1hkEntry; + BOOLEAN bUpdateR1kh = FALSE; + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp: Station MAC = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyRsp->MacAddr[0], + pEvtKeyRsp->MacAddr[1], + pEvtKeyRsp->MacAddr[2], + pEvtKeyRsp->MacAddr[3], + pEvtKeyRsp->MacAddr[4], + pEvtKeyRsp->MacAddr[5])); + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp: R1KH-ID = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyRsp->KeyInfo.R1KHID[0], + pEvtKeyRsp->KeyInfo.R1KHID[1], + pEvtKeyRsp->KeyInfo.R1KHID[2], + pEvtKeyRsp->KeyInfo.R1KHID[3], + pEvtKeyRsp->KeyInfo.R1KHID[4], + pEvtKeyRsp->KeyInfo.R1KHID[5])); + + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr")); + hex_dump("PMKR1Name", pEvtKeyRsp->PMKR1Name, FT_KDP_WPA_NAME_MAX_SIZE); + hex_dump("R0KH_MAC", pEvtKeyRsp->R0KH_MAC, ETH_ALEN); + hex_dump("AKM Suite", pEvtKeyRsp->AkmSuite, 4); + +#endif /* FT_KDP_DEBUG */ + + /* Upon receiving a new PMK-R1 key for a STA, the target AP shall + delete the prior PMK-R1 SA and PTKSAs derived from the prior + PMK-R1 key */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEvtKeyRsp->PMKR1Name); + if (pR1hkEntry == NULL) + { + bUpdateR1kh = TRUE; + } + if (pR1hkEntry && + RTMPEqualMemory(pR1hkEntry->PmkR1Key, pEvtKeyRsp->PMKR1, LEN_PMK) == FALSE) + { + FT_R1khEntryDelete(pAd, pR1hkEntry); + bUpdateR1kh = TRUE; + } + + if (bUpdateR1kh) + { + /* assign the PMK-R1 key to FT kernel */ + FT_R1khEntryInsert(pAd, + pEvtKeyRsp->KeyInfo.PMKR0Name, + pEvtKeyRsp->PMKR1Name, + pEvtKeyRsp->PMKR1, + pEvtKeyRsp->PairwisChipher, + pEvtKeyRsp->AkmSuite, + pEvtKeyRsp->KeyLifeTime, + pEvtKeyRsp->ReassocDeadline, + (PUINT8)pEvtKeyRsp->KeyInfo.R0KHID, + pEvtKeyRsp->KeyInfo.R0KHIDLen, + pEvtKeyRsp->MacAddr); + } + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + /* add the R0KH information */ + FT_KDP_R0KH_InfoAdd(pAd, + pEvtKeyRsp->KeyInfo.R0KHID, + pEvtKeyRsp->R0KH_MAC, + PeerIP); +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp format incorrect!\n")); + } /* End of if */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_KeyResponseToUs */ + + +/* +======================================================================== +Routine Description: + Inform us a FT station joins the BSS domain. + +Arguments: + pAd - WLAN control block pointer + *pInfo - station information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Station MAC (6B) +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_StationInform( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen; + UCHAR *pData; + + FT_KDP_EVT_KEY_ELM EvtKeyReq, *pEvtKeyReq; + UCHAR StaMac[ETH_ALEN]; + UINT32 IdBssNum; + + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + + /* sanity check */ +#ifndef FT_KDP_FUNC_TEST + /* check if we are in security mode; if not, return */ + for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) + { + if (pAd->ApCfg.MBSSID[IdBssNum].WepStatus != Ndis802_11WEPDisabled) + break; + /* End of if */ + } /* End of for */ + + if (IdBssNum == pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> All BSS are open mode!\n")); + return; /* all BSS are open mode */ + } /* End of if */ +#endif + + /* init */ + NdisMoveMemory(StaMac, pData, ETH_ALEN); + + NdisZeroMemory(&EvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM)); + pEvtKeyReq = &EvtKeyReq; + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Station Inform from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif + + /* make up request content */ + pEvtKeyReq->ElmId = FT_KDP_ELM_ID_PRI; + pEvtKeyReq->ElmLen = FT_KDP_ELM_PRI_LEN; + pEvtKeyReq->OUI[0] = FT_KDP_ELM_PRI_OUI_0; + pEvtKeyReq->OUI[1] = FT_KDP_ELM_PRI_OUI_1; + pEvtKeyReq->OUI[2] = FT_KDP_ELM_PRI_OUI_2; + + NdisMoveMemory(pEvtKeyReq->MacAddr, StaMac, ETH_ALEN); + NdisMoveMemory(pEvtKeyReq->KeyInfo.S1KHID, StaMac, FT_KDP_S1KHID_MAX_SIZE); + + /* request PMK-R1 Key (our R1KH vs. the station) from the R0KH */ +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Send Key Req to Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) + { +#ifndef FT_KDP_FUNC_TEST + if (pAd->ApCfg.MBSSID[IdBssNum].WepStatus != Ndis802_11WEPDisabled) +#endif /* FT_KDP_FUNC_TEST */ + { + /* copy our MAC address to be the R1KHID */ + /* different MAC for different BSS in MBSS mode */ + NdisMoveMemory(pEvtKeyReq->KeyInfo.R1KHID, + pAd->ApCfg.MBSSID[IdBssNum].wdev.bssid, + FT_KDP_R1KHID_MAX_SIZE); + + FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_KEY_REQ_AUTO, + (VOID *)pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), + PeerIP, NULL); + } /* End of if */ + } /* End of for */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_StationInform */ + + +/* +======================================================================== +Routine Description: + Set the encryption/decryption key from daemon or driver. + +Arguments: + pAd - WLAN control block pointer + *pKey - the key + KeyLen - the key length + +Return Value: + None + +Note: + Key length can be 8B ~ 64B. + + We support key set from daemon or driver. + + Only one key for multiple BSS mode. +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_CryptKeySet( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pKey, + IN INT32 KeyLen) +{ +#ifndef FT_KDP_EMPTY + UCHAR KeyMaterial[40]; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* key set */ + if ((KeyLen >= 8) && (KeyLen <= 64)) + { + RtmpPasswordHash((PSTRING)pKey, + (PUCHAR)FT_KDP_RALINK_PASSPHRASE, + strlen(FT_KDP_RALINK_PASSPHRASE), + KeyMaterial); + } + else + { + RtmpPasswordHash((PSTRING)FT_KDP_KEY_DEFAULT, + (PUCHAR)FT_KDP_RALINK_PASSPHRASE, + strlen(FT_KDP_RALINK_PASSPHRASE), + KeyMaterial); + } /* End of if */ + + /* use the first 16B of KeyMaterial[] */ + NdisMoveMemory(FT_KDP_CB->CryptKey, KeyMaterial, sizeof(KeyMaterial)); +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_CryptKeySet */ + + +/* +======================================================================== +Routine Description: + Encrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_DataEncrypt( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pData, + IN UINT32 *pDataLen) +{ +#ifndef FT_KDP_EMPTY + UCHAR *pOutputBuf; + UINT OutputLen = 0; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + FT_MEM_ALLOC(pAd, &pOutputBuf, *pDataLen + FT_KDP_KEY_ENCRYPTION_EXTEND); + if (pOutputBuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate encryption buffer fail!\n")); + return; + } /* End of if */ + NdisZeroMemory(pOutputBuf, *pDataLen + FT_KDP_KEY_ENCRYPTION_EXTEND); + + /* encrypt */ + AES_Key_Wrap(pData, *pDataLen, FT_KDP_CB->CryptKey, 16, + pOutputBuf, &OutputLen); + *pDataLen = OutputLen; + + NdisMoveMemory(pData, pOutputBuf, *pDataLen); + + FT_MEM_FREE(pAd, pOutputBuf); +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_DataEncrypt */ + + +/* +======================================================================== +Routine Description: + Decrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_DataDecrypt( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pData, + IN UINT32 *pDataLen) +{ +#ifndef FT_KDP_EMPTY + UCHAR *pOutputBuf; + UINT OutputLen = 0; + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + if ((*pDataLen) <= FT_KDP_KEY_ENCRYPTION_EXTEND) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd>Decryption length is too small!\n")); + return; + } /* End of if */ + + /* init */ + FT_MEM_ALLOC(pAd, &pOutputBuf, *pDataLen); + if (pOutputBuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate decryption buffer fail!\n")); + return; + } /* End of if */ + + /* decrypt */ + AES_Key_Unwrap(pData, *pDataLen, + FT_KDP_CB->CryptKey, 16, + pOutputBuf, &OutputLen); + *pDataLen = OutputLen; + + NdisMoveMemory(pData, pOutputBuf, *pDataLen); + + FT_MEM_FREE(pAd, pOutputBuf); +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_DataDecrypt */ + + + + +/* private function */ +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +/* +======================================================================== +Routine Description: + Add a R0KH Information. + +Arguments: + pAd - WLAN control block pointer + *pR0KHID - R0KH ID + *pMAC - R0KH MAC + IP - R0KH IP + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN TYPE_FUNC FT_KDP_R0KH_InfoAdd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP) +{ +#ifndef FT_KDP_EMPTY + FT_KDP_R0KH_INFO *pInfo; + BOOLEAN FlgIsSameRecordFound; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return FALSE; + } /* End of if */ + + /* sanity check for maximum size */ + if (FT_KDP_CB->R0KH_Size >= FT_KDP_R0KH_INFO_MAX_SIZE) + { + /* delete oldest record first */ + FT_KDP_R0KH_InfoDel(pAd, NULL, NULL, 0); + } /* End of if */ + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + /* sanity check if same information exists */ + FlgIsSameRecordFound = FALSE; + pInfo = FT_KDP_CB->R0KH_InfoHead; + + while(pInfo != NULL) + { + if ((NdisEqualMemory(pInfo->R0KHID, pR0KHID, sizeof(pInfo->R0KHID))) || + (NdisEqualMemory(pInfo->MAC, pMAC, sizeof(pInfo->MAC))) || + (pInfo->IP == IP)) + { + /* need to update the new information to the entry */ + FlgIsSameRecordFound = TRUE; + break; + } /* End of if */ + + pInfo = pInfo->pNext; + } /* End of while */ + + /* init or update */ + if (FlgIsSameRecordFound == FALSE) + { + /* allocate a new record */ + FT_MEM_ALLOC(pAd, &pInfo, sizeof(FT_KDP_R0KH_INFO)); + if (pInfo == NULL) + { + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate R0KH INFO fail!\n")); + return FALSE; + } /* End of if */ + + pInfo->pNext = NULL; + } /* End of if */ + + /* update other R0KH device information */ + NdisMoveMemory(pInfo->R0KHID, pR0KHID, sizeof(pInfo->R0KHID)); + NdisMoveMemory(pInfo->MAC, pMAC, sizeof(pInfo->MAC)); + pInfo->IP = IP; + NdisGetSystemUpTime(&pInfo->TimeUpdate); + + /* append the new information to the information list */ + if (FlgIsSameRecordFound == FALSE) + { + if (FT_KDP_CB->R0KH_InfoTail == NULL) + { + FT_KDP_CB->R0KH_InfoHead = pInfo; + FT_KDP_CB->R0KH_InfoTail = pInfo; + } + else + { + (FT_KDP_CB->R0KH_InfoTail)->pNext = pInfo; + FT_KDP_CB->R0KH_InfoTail = pInfo; + } /* End of if */ + + FT_KDP_CB->R0KH_Size ++; + } /* End of if */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); +#endif /* FT_KDP_EMPTY */ + + return TRUE; +} /* End of FT_KDP_R0KH_InfoAdd */ + + +/* +======================================================================== +Routine Description: + Delete a R0KH Information. + +Arguments: + pAd - WLAN control block pointer + *pR0KHID - R0KH ID + *pMAC - R0KH MAC + IP - R0KH IP + +Return Value: + None + +Note: + If pR0KHID == NULL, pMAC == NULL, and IP = 0, means deleting the oldest. +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_R0KH_InfoDel( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP) +{ +#ifndef FT_KDP_EMPTY + FT_KDP_R0KH_INFO *pInfo; + FT_KDP_R0KH_INFO *pInfoBackup, *pInfoDelPrev, *pInfoDel; + ULONG TimeOldest; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + pInfoDelPrev = NULL; + pInfoDel = NULL; + TimeOldest = 0xFFFFFFFF; + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + /* try to find the one expected to delete */ + pInfo = FT_KDP_CB->R0KH_InfoHead; + if (pInfo == NULL) + { + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + return; + } /* End of if */ + + pInfoBackup = pInfo; + + while(pInfo != NULL) + { + if ((pR0KHID == NULL) && (pMAC == NULL) && (IP == 0)) + { + /* check if the info is the oldest one */ + if (pInfo->TimeUpdate < TimeOldest) + { + TimeOldest = pInfo->TimeUpdate; + + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + } /* End of if */ + } + else + { + /* check if the info is the one expected to delete */ + if ((pR0KHID != NULL) && + (NdisEqualMemory(pR0KHID, pInfo->R0KHID, sizeof(pInfo->R0KHID)))) + { + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + break; + } /* End of if */ + + if ((pMAC != NULL) && + (NdisEqualMemory(pMAC, pInfo->MAC, sizeof(pInfo->MAC)))) + { + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + break; + } /* End of if */ + + if (IP == pInfo->IP) + { + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + break; + } /* End of if */ + } /* End of if */ + + /* check next one */ + pInfoBackup = pInfo; + pInfo = pInfo->pNext; + } /* End of while */ + + /* delete the information record */ + if (pInfoDel != NULL) + { + FT_KDP_CB->R0KH_Size --; + + if (FT_KDP_CB->R0KH_Size == 0) + { + /* list is empty */ + FT_KDP_CB->R0KH_InfoHead = NULL; + FT_KDP_CB->R0KH_InfoTail = NULL; + } + else + { + if (pInfoDelPrev == pInfoDel) + { + /* must be the head one */ + FT_KDP_CB->R0KH_InfoHead = pInfoDel->pNext; + } + else + { + /* must not be the head one */ + pInfoDelPrev->pNext = pInfoDel->pNext; + } /* End of if */ + } /* End of if */ + } + else + { + /* sorry! can not find the one in the list */ + } /* End of if */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + /* free the one */ + if (pInfoDel != NULL) + FT_MEM_FREE(pAd, pInfoDel); + /* End of if */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_R0KH_InfoDel */ + + +/* +======================================================================== +Routine Description: + Get the IP of R0KH by R0KHID or MAC. + +Arguments: + pAd - WLAN control block pointer + *pR0KHID - R0KH ID + *pMAC - R0KH MAC + pIP - R0KH IP + +Return Value: + TRUE - get ok + FALSE - get fail + +Note: +======================================================================== +*/ +static BOOLEAN TYPE_FUNC FT_KDP_R0KH_InfoGet( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pR0KHID, + INOUT UCHAR *pMAC, + OUT UINT32 *pIP) +{ +#ifndef FT_KDP_EMPTY + FT_KDP_R0KH_INFO *pInfo; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return FALSE; + } /* End of if */ + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + pInfo = FT_KDP_CB->R0KH_InfoHead; + + while(pInfo != NULL) + { + /* check if the info is the one expected to get */ + if ((pR0KHID != NULL) && + (NdisEqualMemory(pR0KHID, pInfo->R0KHID, sizeof(pInfo->R0KHID)))) + { + *pIP = pInfo->IP; + goto LabelOk; + } /* End of if */ + + if ((pMAC != NULL) && + (NdisEqualMemory(pMAC, pInfo->MAC, sizeof(pInfo->MAC)))) + { + *pIP = pInfo->IP; + goto LabelOk; + } /* End of if */ + + /* check next one */ + pInfo = pInfo->pNext; + } /* End of while */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + return FALSE; + +LabelOk: + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + return TRUE; +#else + + return FALSE; +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_R0KH_InfoGet */ +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + +/* +======================================================================== +Routine Description: + Broadcast our AP information. + +Arguments: + SystemSpecific1 - no use + FunctionContext - WLAN control block pointer + SystemSpecific2 - no use + SystemSpecific3 - no use + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_InfoBroadcast( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ +#ifndef FT_KDP_EMPTY +#ifdef FT_KDP_FUNC_INFO_BROADCAST + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + UINT32 IdBssNum; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* get my neighbor report element information */ + /* yet implement */ + + for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) + { + /* PeerIP = 0 means destination MAC = 0xFF FF FF FF FF FF */ + FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_INFO_BROADCAST, + "test", 4, 0, NULL); + } /* End of for */ +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_InfoBroadcast */ + + +#ifdef FT_KDP_FUNC_INFO_BROADCAST +/* +======================================================================== +Routine Description: + Receive a neighbor report from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborReportHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen; + UCHAR *pData; + + UINT32 IdBssNum; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Neighbor Report from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + /* yet implememnt */ + +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_NeighborReportHandle */ +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + + +/* +======================================================================== +Routine Description: + Receive a neighbor request from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborRequestHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen; + UCHAR *pData; + + UINT32 IdBssNum; + UINT16 SsidLen; + PSTRING pSSID; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + + SsidLen = DataLen; + pSSID = (PSTRING)pData; + pSSID[SsidLen] = 0x00; + IdBssNum = BSS0; + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Neighbor Request from Peer IP = %d.%d.%d.%d, SSID = %s\n", + IAPP_SHOW_IP_HTONL(PeerIP), pSSID)); +#endif /* FT_KDP_DEBUG */ + + /* check if the requested SSID is for us */ + + /* 11k yet implememnt */ +/* 11K_ApInfoGet(&ApInfo); */ + + /* reponse the neighbor request to the AP */ +/* FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_AP_INFO_RSP, */ +/* &ApInfo, sizeof(ApInfo), PeerIP, NULL); */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_NeighborRequestHandle */ + + +/* +======================================================================== +Routine Description: + Receive a neighbor response from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborResponseHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen; + UCHAR *pData; + + + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Neighbor Response from Peer IP = %d.%d.%d.%d\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + /* 11k yet implememnt */ +/* 11K_ResponseHandle(pData, DataLen); */ +#endif /* FT_KDP_EMPTY */ +} /* End of FT_KDP_NeighborResponseHandle */ + + +/* +======================================================================== +Routine Description: + Handle a RRB frame from DS. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_RRB_ActionHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + /* sanity check */ + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } /* End of if */ + + /* handle it */ + FT_RrbHandler(pAd, pInfo, InfoLen); +#endif /* FT_KDP_EMPTY */ +} /* End of FT_RRB_ActionForward */ + +/* End of ap_ftkd.c */ + +#endif /* DOT11R_FT_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_ids.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_ids.c new file mode 100644 index 000000000..e950a91a9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_ids.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mbss.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mbss.c new file mode 100644 index 000000000..904b92f2c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mbss.c @@ -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; IdBssApCfg.MBSSID[IdBss].wdev.if_dev = NULL; + } + + /* create virtual network interface */ + for(IdBss=FIRST_MBSSID; IdBssMC_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; IdBssApCfg.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; IdBssApCfg.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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mbss_inf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mbss_inf.c new file mode 100644 index 000000000..2afd45215 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mbss_inf.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mlme.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mlme.c new file mode 100644 index 000000000..dba34f6d3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_mlme.c @@ -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 + +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; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_qload.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_qload.c new file mode 100644 index 000000000..4a918d239 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_qload.c @@ -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; StaIdContent[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; IdBssApCfg.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; BusyTimeIdphy_ctrl.QloadBusyCountPri[BusyTimeId])); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n\tSecondary Busy Time\tTimes\n")); + + for(BusyTimeId=0; BusyTimeIdphy_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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_repeater.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_repeater.c new file mode 100644 index 000000000..6d3aafb84 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_repeater.c @@ -0,0 +1,1053 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2012, 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_repeater.c + + Abstract: + Support MAC Repeater function. + + Revision History: + Who When What + -------------- ---------- ---------------------------------------------- + Arvin 11-16-2012 created +*/ + +#ifdef MAC_REPEATER_SUPPORT + +#include "rt_config.h" + +#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) +#define IS_BROADCAST_MAC_ADDR(Addr) ((((Addr[0]) & 0xff) == 0xff)) + +REPEATER_CLIENT_ENTRY *RTMPLookupRepeaterCliEntry( + IN PVOID pData, + IN BOOLEAN bRealMAC, + IN PUCHAR pAddr, + IN BOOLEAN bIsPad, + OUT PUCHAR pIsLinkValid) +{ + ULONG HashIdx; + UCHAR tempMAC[6]; + REPEATER_CLIENT_ENTRY *pEntry = NULL; + REPEATER_CLIENT_ENTRY_MAP *pMapEntry = NULL; + + if (bIsPad == TRUE) { + NdisAcquireSpinLock(&((PRTMP_ADAPTER)pData)->ApCfg.ReptCliEntryLock); + } else { + NdisAcquireSpinLock(((REPEATER_ADAPTER_DATA_TABLE *)pData)->EntryLock); + } + + COPY_MAC_ADDR(tempMAC, pAddr); + HashIdx = MAC_ADDR_HASH_INDEX(tempMAC); + *pIsLinkValid = TRUE; + + if (bRealMAC == TRUE) + { + if (bIsPad == TRUE) { + pMapEntry = ((PRTMP_ADAPTER)pData)->ApCfg.ReptMapHash[HashIdx]; + } else + pMapEntry = *((((REPEATER_ADAPTER_DATA_TABLE *)pData)->MapHash) + HashIdx) ; + + + while (pMapEntry) + { + pEntry = pMapEntry->pReptCliEntry; + + if (MAC_ADDR_EQUAL(pEntry->OriginalAddress, tempMAC)) + { + if (pEntry->CliValid == FALSE) { + *pIsLinkValid = FALSE; + pEntry = NULL; + } + + break; + } + else + { + pEntry = NULL; + pMapEntry = pMapEntry->pNext; + } + } + } + else + { + if (bIsPad == TRUE) { + pEntry = ((PRTMP_ADAPTER)pData)->ApCfg.ReptCliHash[HashIdx]; + } else { + pEntry = *((((REPEATER_ADAPTER_DATA_TABLE *)pData)->CliHash) + HashIdx) ; + } + + while (pEntry) + { + if (MAC_ADDR_EQUAL(pEntry->CurrentAddress, tempMAC)) + { + if (pEntry->CliValid == FALSE) { + *pIsLinkValid = FALSE; + pEntry = NULL; + } + break; + } + else + pEntry = pEntry->pNext; + } + } + + if (bIsPad == TRUE) { + NdisReleaseSpinLock(&((PRTMP_ADAPTER)pData)->ApCfg.ReptCliEntryLock); + } else { + NdisReleaseSpinLock(((REPEATER_ADAPTER_DATA_TABLE *)pData)->EntryLock); + } + + return pEntry; +} + +BOOLEAN RTMPQueryLookupRepeaterCliEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + UCHAR isLinkValid; + + DBGPRINT(RT_DEBUG_INFO, ("%s:: %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, + pAddr[0], + pAddr[1], + pAddr[2], + pAddr[3], + pAddr[4], + pAddr[5])); + + if (RTMPLookupRepeaterCliEntry(pAd, FALSE, pAddr, TRUE, &isLinkValid) == NULL) { + DBGPRINT(RT_DEBUG_INFO, ("%s:: not the repeater client\n", __FUNCTION__)); + return FALSE; + } else { + DBGPRINT(RT_DEBUG_INFO, ("%s:: is the repeater client\n", __FUNCTION__)); + return TRUE; + } +} + +#if defined (CONFIG_WIFI_PKT_FWD) +EXPORT_SYMBOL(RTMPQueryLookupRepeaterCliEntry); +#endif /* CONFIG_WIFI_PKT_FWD */ + +VOID RTMPInsertRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr) +{ + ULONG offset, Addr; + UCHAR tempMAC[MAC_ADDR_LEN]; + + DBGPRINT(RT_DEBUG_WARN, (" %s.\n", __FUNCTION__)); + + COPY_MAC_ADDR(tempMAC, pAddr); + + offset = 0x1480 + (HW_WCID_ENTRY_SIZE * CliIdx); + Addr = tempMAC[0] + (tempMAC[1] << 8) +(tempMAC[2] << 16) +(tempMAC[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = tempMAC[4] + (tempMAC[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); + + DBGPRINT(RT_DEBUG_ERROR, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + tempMAC[0], + tempMAC[1], + tempMAC[2], + tempMAC[3], + tempMAC[4], + tempMAC[5], + CliIdx)); + +} + +VOID RTMPRemoveRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx) +{ + ULONG offset, Addr; + + DBGPRINT(RT_DEBUG_WARN, (" %s.\n", __FUNCTION__)); + + offset = 0x1480 + (HW_WCID_ENTRY_SIZE * CliIdx); + Addr = 0; + RTMP_IO_WRITE32(pAd, offset, Addr); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); +} + +VOID RTMPInsertRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + IN PUCHAR pAddr) +{ + INT CliIdx, idx; + UCHAR HashIdx; + BOOLEAN Cancelled; + UCHAR tempMAC[MAC_ADDR_LEN]; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL, pCurrEntry = NULL; + PREPEATER_CLIENT_ENTRY_MAP pReptCliMap; + UCHAR SPEC_ADDR[6][3] = {{0x02, 0x0F, 0xB5}, {0x02, 0x09, 0x5B}, + {0x02, 0x14, 0x6C}, {0x02, 0x18, 0x4D}, + {0x02, 0x1B, 0x2F}, {0x02, 0x1E, 0x2A}}; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, (" %s.\n", __FUNCTION__)); + + pMacEntry = MacTableLookup(pAd, pAddr); + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)) + { + if (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + { + DBGPRINT(RT_DEBUG_ERROR, (" wireless client is not ready !!!\n")); + return; + } + } + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + if (pAd->ApCfg.RepeaterCliSize >= MAX_EXT_MAC_ADDR_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, (" Repeater Client Full !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + pReptCliEntry = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx]; + + if ((pReptCliEntry->CliEnable) && + (MAC_ADDR_EQUAL(pReptCliEntry->OriginalAddress, pAddr) || MAC_ADDR_EQUAL(pReptCliEntry->CurrentAddress, pAddr))) + { + DBGPRINT(RT_DEBUG_ERROR, ("\n receive mac :%02x:%02x:%02x:%02x:%02x:%02x !!!\n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); + DBGPRINT(RT_DEBUG_ERROR, (" duplicate Insert !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + if (pReptCliEntry->CliEnable == FALSE) + break; + } + + if (CliIdx >= MAX_EXT_MAC_ADDR_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, (" Repeater Client Full !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + pReptCliEntry = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx]; + pReptCliMap = &pAd->ApCfg.ApCliTab[apidx].RepeaterCliMap[CliIdx]; + + /* ENTRY PREEMPTION: initialize the entry */ + RTMPCancelTimer(&pReptCliEntry->ApCliAuthTimer, &Cancelled); + RTMPCancelTimer(&pReptCliEntry->ApCliAssocTimer, &Cancelled); + pReptCliEntry->CtrlCurrState = APCLI_CTRL_DISCONNECTED; + pReptCliEntry->AuthCurrState = APCLI_AUTH_REQ_IDLE; + pReptCliEntry->AssocCurrState = APCLI_ASSOC_IDLE; + pReptCliEntry->CliConnectState = 0; + pReptCliEntry->CliValid = FALSE; + pReptCliEntry->bEthCli = FALSE; + pReptCliEntry->MacTabWCID = 0xFF; + pReptCliEntry->AuthReqCnt = 0; + pReptCliEntry->AssocReqCnt = 0; + pReptCliEntry->CliTriggerTime = 0; + pReptCliEntry->pNext = NULL; + pReptCliMap->pReptCliEntry = pReptCliEntry; + pReptCliMap->pNext = NULL; + + COPY_MAC_ADDR(pReptCliEntry->OriginalAddress, pAddr); + COPY_MAC_ADDR(tempMAC, pAddr); +#ifdef SMART_MESH + NdisZeroMemory(pAd->vMacAddrPrefix,sizeof(pAd->vMacAddrPrefix)); +#endif /* SMART_MESH */ + + if (pAd->ApCfg.MACRepeaterOuiMode == 1) + { + DBGPRINT(RT_DEBUG_ERROR, (" todo !!!\n")); + } + else if (pAd->ApCfg.MACRepeaterOuiMode == 2) + { + INT IdxToUse; + + for (idx = 0; idx < 6; idx++) + { + if (RTMPEqualMemory(SPEC_ADDR[idx], pAddr, 3)) + break; + } + + /* If there is a matched one, use the next one; otherwise, use the first one. */ + if (idx >= 0 && idx < 5) + IdxToUse = idx + 1; + else + IdxToUse = 0; + NdisCopyMemory(tempMAC, SPEC_ADDR[IdxToUse], 3); +#ifdef SMART_MESH + INT vMacIdx; + if (IdxToUse >= 0 && IdxToUse < 5) + vMacIdx = IdxToUse + 1; + else + vMacIdx = 0; + + NdisCopyMemory(pAd->vMacAddrPrefix, SPEC_ADDR[vMacIdx], sizeof(pAd->vMacAddrPrefix)); +#endif /* SMART_MESH */ + } + else + { + NdisCopyMemory(tempMAC, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, 3); + } + + COPY_MAC_ADDR(pReptCliEntry->CurrentAddress, tempMAC); + pReptCliEntry->CliEnable = TRUE; + pReptCliEntry->CliConnectState = 1; + pReptCliEntry->pNext = NULL; + NdisGetSystemUpTime(&pReptCliEntry->CliTriggerTime); + + RTMPInsertRepeaterAsicEntry(pAd, CliIdx, tempMAC); + + HashIdx = MAC_ADDR_HASH_INDEX(tempMAC); + if (pAd->ApCfg.ReptCliHash[HashIdx] == NULL) + { + pAd->ApCfg.ReptCliHash[HashIdx] = pReptCliEntry; + } + else + { + pCurrEntry = pAd->ApCfg.ReptCliHash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pReptCliEntry; + } + + HashIdx = MAC_ADDR_HASH_INDEX(pReptCliEntry->OriginalAddress); + if (pAd->ApCfg.ReptMapHash[HashIdx] == NULL) + pAd->ApCfg.ReptMapHash[HashIdx] = pReptCliMap; + else + { + PREPEATER_CLIENT_ENTRY_MAP pCurrMapEntry; + + pCurrMapEntry = pAd->ApCfg.ReptMapHash[HashIdx]; + + while (pCurrMapEntry->pNext != NULL) + pCurrMapEntry = pCurrMapEntry->pNext; + pCurrMapEntry->pNext = pReptCliMap; + } + + pAd->ApCfg.RepeaterCliSize++; + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + NdisZeroMemory(&ApCliCtrlMsg, sizeof(APCLI_CTRL_MSG_STRUCT)); + ApCliCtrlMsg.Status = MLME_SUCCESS; + COPY_MAC_ADDR(&ApCliCtrlMsg.SrcAddr[0], tempMAC); + ApCliCtrlMsg.BssIdx = apidx; + ApCliCtrlMsg.CliIdx = CliIdx; + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_MT2_AUTH_REQ, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, apidx); + +} + +VOID RTMPRemoveRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apIdx, + IN UCHAR CliIdx) +{ + USHORT HashIdx; + REPEATER_CLIENT_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + REPEATER_CLIENT_ENTRY_MAP *pMapEntry, *pPrevMapEntry, *pProbeMapEntry; + BOOLEAN bVaild; + + DBGPRINT(RT_DEBUG_OFF, (" %s. apIdx=%d CliIdx=%d\n", __FUNCTION__,apIdx,CliIdx)); + + RTMPRemoveRepeaterAsicEntry(pAd, CliIdx); + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + pEntry = &pAd->ApCfg.ApCliTab[apIdx].RepeaterCli[CliIdx]; + + bVaild = TRUE; + HashIdx = MAC_ADDR_HASH_INDEX(pEntry->CurrentAddress); + + pPrevEntry = NULL; + pProbeEntry = pAd->ApCfg.ReptCliHash[HashIdx]; + ASSERT(pProbeEntry); + + if (pProbeEntry == NULL) + { + bVaild = FALSE; + goto done; + } + + if (pProbeEntry != NULL) + { + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pAd->ApCfg.ReptCliHash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + } + /* not found !!!*/ + ASSERT(pProbeEntry != NULL); + + if (pProbeEntry == NULL) + { + bVaild = FALSE; + goto done; + } + + pMapEntry = &pAd->ApCfg.ApCliTab[apIdx].RepeaterCliMap[CliIdx]; + + HashIdx = MAC_ADDR_HASH_INDEX(pEntry->OriginalAddress); + + pPrevMapEntry = NULL; + pProbeMapEntry = pAd->ApCfg.ReptMapHash[HashIdx]; + ASSERT(pProbeMapEntry); + if (pProbeMapEntry != NULL) + { + /* update Hash list*/ + do + { + if (pProbeMapEntry == pMapEntry) + { + if (pPrevMapEntry == NULL) + { + pAd->ApCfg.ReptMapHash[HashIdx] = pMapEntry->pNext; + } + else + { + pPrevMapEntry->pNext = pMapEntry->pNext; + } + break; + } + + pPrevMapEntry = pProbeMapEntry; + pProbeMapEntry = pProbeMapEntry->pNext; + } while (pProbeMapEntry); + } + /* not found !!!*/ + ASSERT(pProbeMapEntry != NULL); + +done: + + pAd->ApCfg.ApCliTab[apIdx].RepeaterCli[CliIdx].CliConnectState = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[apIdx].RepeaterCli[CliIdx].OriginalAddress, MAC_ADDR_LEN); + + if ((bVaild == TRUE) && (pAd->ApCfg.RepeaterCliSize > 0)) + pAd->ApCfg.RepeaterCliSize--; + + /* set the apcli interface be invalid. */ + pAd->ApCfg.ApCliTab[apIdx].RepeaterCli[CliIdx].CliValid = FALSE; + pAd->ApCfg.ApCliTab[apIdx].RepeaterCli[CliIdx].CliEnable = FALSE; + + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return; +} + +MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN struct wifi_dev *wdev, + IN UCHAR apIdx, + IN UCHAR cliIdx, + IN BOOLEAN CleanAll) +{ + UCHAR HashIdx; + int i; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + BOOLEAN Cancelled; + + /* if FULL, return*/ + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + /* allocate one MAC entry*/ + NdisAcquireSpinLock(&pAd->MacTabLock); + + i = (MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * (apIdx - MIN_NET_DEVICE_FOR_APCLI))); + + if (cliIdx != 0xFF) + i = i + cliIdx + 1; + + /* pick up the first available vacancy*/ + pEntry = &pAd->MacTab.Content[i]; + + if (pEntry == NULL) + { + printk("###### %s pEntry == NULL, i = %d\n", __func__, i); + } + + if (pEntry && IS_ENTRY_NONE(pEntry)) + { + /* ENTRY PREEMPTION: initialize the entry */ + if (pEntry->RetryTimer.Valid) + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + if (pEntry->EnqueueStartForPSKTimer.Valid) + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + + if (CleanAll == TRUE) + { + pEntry->MaxSupportedRate = RATE_11; + pEntry->CurrTxRate = RATE_11; + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + } + + SET_ENTRY_APCLI(pEntry); + pEntry->wdev = wdev; + pEntry->wcid = i; + pEntry->isCached = FALSE; + pEntry->bIAmBadAtheros = FALSE; + + RTMPInitTimer(pAd, &pEntry->EnqueueStartForPSKTimer, GET_TIMER_FUNCTION(EnqueueStartForPSKExec), pEntry, FALSE); + RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + RTMPInitTimer(pAd, &pEntry->eTxBfProbeTimer, GET_TIMER_FUNCTION(eTxBfProbeTimerExec), pEntry, FALSE); +#endif /* TXBF_SUPPORT */ + + pEntry->pAd = pAd; + pEntry->CMTimerRunning = FALSE; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + pEntry->RSNIE_Len = 0; + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + pEntry->apidx = (apIdx - MIN_NET_DEVICE_FOR_APCLI); + pEntry->pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + + pEntry->AuthMode = pAd->ApCfg.ApCliTab[pEntry->apidx].wdev.AuthMode; + pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->apidx].wdev.WepStatus; + pEntry->wdev_idx = pEntry->apidx; + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + { + pEntry->WpaState = AS_NOTUSE; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + else + { + pEntry->WpaState = AS_PTKSTART; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + COPY_MAC_ADDR(pEntry->Addr, pAddr); + //COPY_MAC_ADDR(pEntry->HdrAddr1, pAddr); + //COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.ApCliTab[pEntry->apidx].CurrentAddress); + //COPY_MAC_ADDR(pEntry->HdrAddr3, pAddr); + COPY_MAC_ADDR(pEntry->bssid, pAddr); + + pEntry->Sst = SST_NOT_AUTH; + pEntry->AuthState = AS_NOT_AUTH; + pEntry->Aid = (USHORT)i; /*0;*/ + pEntry->CapabilityInfo = 0; + pEntry->PsMode = PWR_ACTIVE; + pEntry->PsQIdleCount = 0; + pEntry->NoDataIdleCount = 0; + pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; + pEntry->ContinueTxFailCnt = 0; + pEntry->TimeStamp_toTxRing = 0; + InitializeQueueHeader(&pEntry->PsQueue); + +#ifdef PS_ENTRY_MAITENANCE + pEntry->continuous_ps_count = 0; +#endif /* PS_ENTRY_MAITENANCE */ + + pAd->MacTab.Size ++; + + /* Set the security mode of this entry as OPEN-NONE in ASIC */ + RTMP_REMOVE_PAIRWISE_KEY_ENTRY(pAd, (UCHAR)i); + + /* Add this entry into ASIC RX WCID search table */ + RTMP_STA_ENTRY_ADD(pAd, pEntry); + +#ifdef WSC_AP_SUPPORT + pEntry->bWscCapable = FALSE; + pEntry->Receive_EapolStart_EapRspId = 0; +#endif /* WSC_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + NdisAllocateSpinLock(pAd, &pEntry->TxSndgLock); +#endif /* TXBF_SUPPORT */ + +#ifdef PEER_DELBA_TX_ADAPT + Peer_DelBA_Tx_Adapt_Init(pAd, pEntry); +#endif /* PEER_DELBA_TX_ADAPT */ +#ifdef DROP_MASK_SUPPORT + drop_mask_init_per_client(pAd, pEntry); +#endif /* DROP_MASK_SUPPORT */ + +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap) + { + UCHAR tblIdx; + + if ((cliIdx != 0xFF) && IsFifoExtTblAvailable(pAd, &tblIdx)) + FifoExtTblUpdateEntry(pAd, tblIdx, i); + } +#endif + DBGPRINT(RT_DEBUG_TRACE, ("%s - allocate entry #%d, Aid = %d, Wcid = %d Addr(%02x:%02x:%02x:%02x:%02x:%02x) Total= %d\n",__FUNCTION__, i, + pEntry->Aid, pEntry->wcid, PRINT_MAC(pEntry->Addr), pAd->MacTab.Size)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - exist entry #%d, Aid = %d, Total= %d\n", __FUNCTION__, i, pEntry->Aid, pAd->MacTab.Size)); + NdisReleaseSpinLock(&pAd->MacTabLock); + return pEntry; + } + + /* add this MAC entry into HASH table */ + if (pEntry) + { + pEntry->pNext = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + if (pAd->MacTab.Hash[HashIdx] == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + return pEntry; +} + +VOID RTMPRepeaterReconnectionCheck( + IN PRTMP_ADAPTER pAd) +{ +#ifdef APCLI_AUTO_CONNECT_SUPPORT + INT i; + PCHAR pApCliSsid, pApCliCfgSsid; + UCHAR CfgSsidLen; + NDIS_802_11_SSID Ssid; + USHORT SiteSurveyPeriod; + + if ((pAd->ApCfg.ApCliAutoConnectRunning == FALSE) +#ifdef AP_PARTIAL_SCAN_SUPPORT + && (pAd->ApCfg.bPartialScanning == FALSE) +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + ) + { + for (i = 0; i < MAX_APCLI_NUM; i++) + { + if (!APCLI_IF_UP_CHECK(pAd, i) || + (pAd->ApCfg.ApCliTab[i].Enable == FALSE)) + continue; + + pApCliSsid = pAd->ApCfg.ApCliTab[i].Ssid; + pApCliCfgSsid = pAd->ApCfg.ApCliTab[i].CfgSsid; + CfgSsidLen = pAd->ApCfg.ApCliTab[i].CfgSsidLen; + SiteSurveyPeriod = pAd->ApCfg.ApCliTab[i].ApCliSiteSurveyPeriod; + + if ((pAd->ApCfg.ApCliTab[i].CtrlCurrState < APCLI_CTRL_AUTH || + !NdisEqualMemory(pApCliSsid, pApCliCfgSsid, CfgSsidLen)) && + (pAd->ApCfg.ApCliTab[i].CfgSsidLen > 0) && + (pAd->Mlme.OneSecPeriodicRound % SiteSurveyPeriod == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, (" %s(): Scan channels for AP (%s)\n", + __FUNCTION__, pApCliCfgSsid)); + pAd->ApCfg.ApCliAutoConnectRunning = TRUE; +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->ApCfg.bPartialScanning = TRUE; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + Ssid.SsidLength = CfgSsidLen; + NdisCopyMemory(Ssid.Ssid, pApCliCfgSsid, CfgSsidLen); + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE); + } + } + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +} + +VOID RTMPRemoveRepeaterDisconnectEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apIdx, + IN UCHAR CliIdx) +{ + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = apIdx; + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + MLME_DEAUTH_REQ_STRUCT DeAuthFrame; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_OFF, ("(%s) disconnect apIdx=%d CliIdx=%d.\n", __FUNCTION__,apIdx, CliIdx)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + + RTMPCancelTimer(&pApCliEntry->RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); + RTMPCancelTimer(&pApCliEntry->RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled); + + if (*pCurrState == APCLI_CTRL_ASSOC) + { + *pCurrState = APCLI_CTRL_DEASSOC; + + DisassocParmFill(pAd, &DisassocReq, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, REASON_DISASSOC_STA_LEAVING); + + MlmeEnqueue(pAd, + APCLI_ASSOC_STATE_MACHINE, + APCLI_MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), + &DisassocReq, + (64 + (MAX_EXT_MAC_ADDR_SIZE*ifIndex) + CliIdx)); + + RTMP_MLME_HANDLER(pAd); + } + else if (*pCurrState == APCLI_CTRL_CONNECTED) + { + DeAuthFrame.Reason = (USHORT)REASON_DEAUTH_STA_LEAVING; + COPY_MAC_ADDR(DeAuthFrame.Addr, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid); + + MlmeEnqueue(pAd, + APCLI_AUTH_STATE_MACHINE, + APCLI_MT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), + &DeAuthFrame, + (64 + (MAX_EXT_MAC_ADDR_SIZE*ifIndex) + CliIdx)); + + RTMP_MLME_HANDLER(pAd); + + if (bValid) + ApCliLinkDown(pAd, (64 + (MAX_EXT_MAC_ADDR_SIZE*ifIndex) + CliIdx)); + + *pCurrState = APCLI_CTRL_DISCONNECTED; + } + else + { + if (bValid) + ApCliLinkDown(pAd, (64 + (MAX_EXT_MAC_ADDR_SIZE*ifIndex) + CliIdx)); + + *pCurrState = APCLI_CTRL_DISCONNECTED; + } + + + return; +} + +BOOLEAN RTMPRepeaterVaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; + + if (pAd->ApCfg.RepeaterCliSize >= MAX_EXT_MAC_ADDR_SIZE) + return FALSE; + + if(IS_MULTICAST_MAC_ADDR(pAddr)) + return FALSE; + + if(IS_BROADCAST_MAC_ADDR(pAddr)) + return FALSE; + + pEntry = RepeaterInvaildMacLookup(pAd, pAddr); + + if (pEntry) + return FALSE; + else + return TRUE; +} + +INVAILD_TRIGGER_MAC_ENTRY *RepeaterInvaildMacLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + ULONG HashIdx; + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; + + while (pEntry) + { + if (MAC_ADDR_EQUAL(pEntry->MacAddr, pAddr)) + { + break; + } + else + pEntry = pEntry->pNext; + } + + if (pEntry && pEntry->bInsert) + return pEntry; + else + return NULL; +} + +VOID RTMPRepeaterInsertInvaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + UCHAR HashIdx, idx = 0; + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; + INVAILD_TRIGGER_MAC_ENTRY *pCurrEntry = NULL; + + if (pAd->ApCfg.ReptControl.ReptInVaildMacSize >= 32) + return; + + if (MAC_ADDR_EQUAL(pAddr, ZERO_MAC_ADDR)) + return; + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + for (idx = 0; idx< 32; idx++) + { + pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; + + if (MAC_ADDR_EQUAL(pEntry->MacAddr, pAddr)) + { + if (pEntry->bInsert) + { + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return; + } + else + { + pEntry->bInsert = TRUE; + break; + } + } + + /* pick up the first available vacancy*/ + if (pEntry->bInsert == FALSE) + { + NdisZeroMemory(pEntry->MacAddr, MAC_ADDR_LEN); + COPY_MAC_ADDR(pEntry->MacAddr, pAddr); + pEntry->bInsert = TRUE; + break; + } + } + + /* add this entry into HASH table */ + if (pEntry) + { + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry->pNext = NULL; + + if (pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] == NULL) + { + pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + DBGPRINT(RT_DEBUG_ERROR, (" Store Invaild MacAddr = %02x:%02x:%02x:%02x:%02x:%02x. !!!\n", + PRINT_MAC(pEntry->MacAddr))); + + pAd->ApCfg.ReptControl.ReptInVaildMacSize++; + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return; +} + +BOOLEAN RTMPRepeaterRemoveInvaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx, + IN PUCHAR pAddr) +{ + USHORT HashIdx; + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; + INVAILD_TRIGGER_MAC_ENTRY *pPrevEntry, *pProbeEntry; + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; + + if (pEntry && pEntry->bInsert) + { + pPrevEntry = NULL; + pProbeEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; + ASSERT(pProbeEntry); + if (pProbeEntry != NULL) + { + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + } + /* not found !!!*/ + ASSERT(pProbeEntry != NULL); + + pAd->ApCfg.ReptControl.ReptInVaildMacSize--; + } + + NdisZeroMemory(pEntry->MacAddr, MAC_ADDR_LEN); + pEntry->bInsert = FALSE; + + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return TRUE; +} + +INT Show_Repeater_Cli_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + UINT32 RegValue; + UINT32 DataRate=0; + + if (!pAd->ApCfg.bMACRepeaterEn) + return TRUE; + + printk("\n"); + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08x\n", + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED) ? "short" : "long", + RegValue); + +#ifdef DOT11_N_SUPPORT + printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); + printk("\n"); +#endif /* DOT11_N_SUPPORT */ + + printk("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s%-7s%-7s\n", + "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", + "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate"); + + for (i = MAX_NUMBER_OF_MAC; i < MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * MAX_APCLI_NUM); i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + if (pEntry && IS_ENTRY_APCLI(pEntry)&& (pEntry->Sst == SST_ASSOC) && (pEntry->bReptCli)) + { + DataRate=0; + RtmpDrvRateGet(pAd, pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.BW,pEntry->HTPhyMode.field.MCS, + newRateGetAntenna(pEntry->HTPhyMode.field.MCS, pEntry->HTPhyMode.field.MODE),&DataRate); + DataRate /= 500000; + DataRate /= 2; + + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->ReptCliAddr[0], pEntry->ReptCliAddr[1], pEntry->ReptCliAddr[2], + pEntry->ReptCliAddr[3], pEntry->ReptCliAddr[4], pEntry->ReptCliAddr[5]); + + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->apidx); + printk("%-4d", (int)pEntry->PsMode); + printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)); +#ifdef DOT11_N_SUPPORT + printk("%-8d", (int)pEntry->MmpsMode); +#endif /* DOT11_N_SUPPORT */ + printk("%-7d", pEntry->RssiSample.AvgRssi0); + printk("%-7d", pEntry->RssiSample.AvgRssi1); + printk("%-7d", pEntry->RssiSample.AvgRssi2); + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + printk("%-7d", (int)DataRate); + printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + printk("\n"); + } + } + + return TRUE; +} + +INT Show_Repeater_Cli_Dump_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT CliIdx; + + printk("\n%-19s%-19s%-12s%-12s%-12s%-12s%-12s\n", + "C_MAC","O_MAC", "CliEnable", "CliValid", "bEthCli", "MacTabWCID","MatchLinkIdx"); + + + for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + pReptEntry = &pAd->ApCfg.ApCliTab[0].RepeaterCli[CliIdx]; + + { + + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pReptEntry->CurrentAddress[0], pReptEntry->CurrentAddress[1], pReptEntry->CurrentAddress[2], + pReptEntry->CurrentAddress[3], pReptEntry->CurrentAddress[4], pReptEntry->CurrentAddress[5]); + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pReptEntry->OriginalAddress[0], pReptEntry->OriginalAddress[1], pReptEntry->OriginalAddress[2], + pReptEntry->OriginalAddress[3], pReptEntry->OriginalAddress[4], pReptEntry->OriginalAddress[5]); + + printk("%-12d", (int)pReptEntry->CliEnable); + printk("%-12d", (int)pReptEntry->CliValid); + printk("%-12d", (int)pReptEntry->bEthCli); + printk("%-12d", (int)pReptEntry->MacTabWCID); + printk("%-12d", (int)pReptEntry->MatchLinkIdx); + printk("\n"); + } + } +} +#endif /* MAC_REPEATER_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_sanity.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_sanity.c new file mode 100644 index 000000000..b6214db6b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_sanity.c @@ -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; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_sync.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_sync.c new file mode 100644 index 000000000..d73902633 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_sync.c @@ -0,0 +1,2525 @@ +/**************************************************************************** + * 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: + sync.c + + Abstract: + Synchronization state machine related services + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 08-04-2003 created for 11g soft-AP + + */ + +#include "rt_config.h" + +#define OBSS_BEACON_RSSI_THRESHOLD (-85) + + +/* + ========================================================================== + Description: + Process the received ProbeRequest from clients + Parameters: + Elem - msg containing the ProbeReq frame + ========================================================================== + */ +VOID APPeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PEER_PROBE_REQ_PARAM ProbeReqParam; + HEADER_802_11 ProbeRspHdr; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0, TmpLen; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1; + UCHAR ErpIeLen = 1; + UCHAR apidx = 0, PhyMode, SupRateLen; + UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; + MULTISSID_STRUCT *mbss; + struct wifi_dev *wdev; + CHAR rssi = 0, idx = 0; +#ifdef BAND_STEERING + BOOLEAN bBndStrgCheck = TRUE; +#endif /* BAND_STEERING */ + UCHAR Addr2[MAC_ADDR_LEN]; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; +#ifdef WSC_AP_SUPPORT + UCHAR Addr3[MAC_ADDR_LEN]; + COPY_MAC_ADDR(Addr3, pFrame->Hdr.Addr3); +#endif /* WSC_AP_SUPPORT */ + COPY_MAC_ADDR(Addr2, pFrame->Hdr.Addr2); + +#ifdef WDS_SUPPORT + /* if in bridge mode, no need to reply probe req. */ + if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) + return; +#endif /* WDS_SUPPORT */ + + if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &ProbeReqParam)) + return; + + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + mbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &mbss->wdev; + RSNIe = IE_WPA; + + if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev)))) + { + /* the interface is down, so we can not send probe response */ + continue; + } + +#ifdef AIRPLAY_SUPPORT + if (mbss->bBcnSntReq == FALSE) + continue; +#endif /* AIRPLAY_SUPPORT */ + + PhyMode = wdev->PhyMode; + + if ( ((((ProbeReqParam.SsidLen == 0) && (!mbss->bHideSsid)) || + ((ProbeReqParam.SsidLen == mbss->SsidLen) && NdisEqualMemory(ProbeReqParam.Ssid, mbss->Ssid, (ULONG) ProbeReqParam.SsidLen))) +#ifdef CONFIG_HOTSPOT + && ProbeReqforHSAP(pAd, apidx, &ProbeReqParam) +#endif + ) +#ifdef WSC_AP_SUPPORT + /* buffalo WPS testbed STA send ProbrRequest ssid length = 32 and ssid are not AP , but DA are AP. for WPS test send ProbeResponse */ + || ((ProbeReqParam.SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, wdev->bssid) && (mbss->bHideSsid == 0)) +#endif /* WSC_AP_SUPPORT */ + ) + ; + else + continue; /* check next BSS */ + + rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, (CHAR)Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, (CHAR)Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, (CHAR)Elem->Rssi2, RSSI_2)); + + if ((mbss->ProbeRspRssiThreshold != 0) && (rssi < mbss->ProbeRspRssiThreshold)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: PROBE_RSP Threshold = %d , PROBE RSSI = %d\n", + wdev->if_dev->name, mbss->ProbeRspRssiThreshold, rssi)); + continue; + } + +#ifdef SMART_MESH + BOOLEAN bProbeNoRsp = TRUE; + if((ProbeReqParam.VIEFlag & 0x7)) + { + bProbeNoRsp = FALSE; + } + else + { + if (!ApCheckAccessControlList(pAd, ProbeReqParam.Addr2, apidx)) + DBGPRINT(RT_DEBUG_ERROR,("Reject this PROBE_REQ due to ACL rule.\n")); + else + bProbeNoRsp = FALSE; + } + + if(bProbeNoRsp) + { + DBGPRINT(RT_DEBUG_ERROR, + ("Reject this PROBE_REQ due to probe resp filtering. (MAC:%02X:%02X:%02X:%02X:%02X:%02X)\n", + PRINT_MAC(ProbeReqParam.Addr2))); + goto done; + } +#endif /* SMART_MESH */ + +#ifdef BAND_STEERING + BND_STRG_CHECK_CONNECTION_REQ( pAd, + NULL, + ProbeReqParam.Addr2, + Elem->MsgType, + Elem->Rssi0, + Elem->Rssi1, + Elem->Rssi2, + &bBndStrgCheck); + if (bBndStrgCheck == FALSE) + return; +#endif /* BAND_STEERING */ + + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, ProbeReqParam.Addr2, + wdev->if_addr, wdev->bssid); + + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + RSNIe = IE_WPA; + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) ||(wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + RSNIe = IE_WPA2; +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + RSNIe = IE_WAPI; +#endif /* WAPI_SUPPORT */ + + { + SupRateLen = pAd->CommonCfg.SupRateLen; + if (PhyMode == WMODE_B) + SupRateLen = 4; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &mbss->CapabilityInfo, + 1, &SsidIe, + 1, &mbss->SsidLen, + mbss->SsidLen, mbss->Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pAd->CommonCfg.SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + END_OF_ARGS); + } + + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ErpIe, + 1, &ErpIeLen, + 1, &pAd->ApCfg.ErpIeContent, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef A_BAND_SUPPORT + /* add Channel switch announcement IE */ + if (((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) +#ifdef CUSTOMER_DCC_FEATURE + || (pAd->CommonCfg.channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) +#endif + ) + { + UCHAR CSAIe = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + UCHAR CSALen = 3; + UCHAR CSAMode = 1; + UCHAR Period; +#ifdef CUSTOMER_DCC_FEATURE + if(pAd->CommonCfg.channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) + { + Period = (pAd->CommonCfg.channelSwitch.CHSWPeriod - pAd->CommonCfg.channelSwitch.CHSWCount); + } + else +#endif + Period = pAd->Dot11_H.CSCount; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CSAIe, + 1, &CSALen, + 1, &CSAMode, + 1, &pAd->CommonCfg.Channel, + 1, &Period, + END_OF_ARGS); + FrameLen += TmpLen; +#if defined (DOT11_N_SUPPORT) && defined (CUSTOMER_DCC_FEATURE) + if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) + { + HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; + + build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) { + WIDE_BW_CH_SWITCH_ELEMENT wb_info; + UCHAR CSWIe = IE_CH_SWITCH_WRAPPER; + UCHAR ch_sw_wrapper = 5; + UCHAR WBCSIe = IE_WIDE_BW_CH_SWITCH; + UCHAR WBCSLen = 3; + + NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); + if (pAd->CommonCfg.vht_bw == VHT_BW_2040) + wb_info.new_ch_width = 0; + else + wb_info.new_ch_width = 1; + + if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + wb_info.center_freq_2 = 0; + } + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CSWIe, + 1, &ch_sw_wrapper, + 1, &WBCSIe, + 1, &WBCSLen, + 3, &wb_info, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_VHT_AC */ + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(PhyMode) && + (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, AddHtLen; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + +/* YF@20120419: Fix IOT Issue with Atheros STA on Windows 7 When IEEE80211H flag turn on. */ + + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &AddHtLen, + sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &AddHtLen, + AddHtLen, &addHTInfoTmp, + END_OF_ARGS); + +#endif + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ + + /* Append RSN_IE when WPA OR WPAPSK, */ + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + ; /* enough information */ + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &mbss->RSNIE_Len[0], + mbss->RSNIE_Len[0], mbss->RSN_IE[0], + 1, &RSNIe2, + 1, &mbss->RSNIE_Len[1], + mbss->RSNIE_Len[1], mbss->RSN_IE[1], + END_OF_ARGS); + FrameLen += TmpLen; + } + else + { + +#ifdef CONFIG_HOTSPOT_R2 + PHOTSPOT_CTRL pHSCtrl = &mbss->HotSpotCtrl; + extern UCHAR OSEN_IE[]; + extern UCHAR OSEN_IELEN; + + if ((pHSCtrl->HotSpotEnable == 0) && (pHSCtrl->bASANEnable == 1) && (wdev->AuthMode == Ndis802_11AuthModeWPA2)) + { + RSNIe = IE_WPA; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &OSEN_IELEN, + OSEN_IELEN, OSEN_IE, + END_OF_ARGS); + } + else +#endif + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &mbss->RSNIE_Len[0], + mbss->RSNIE_Len[0], mbss->RSN_IE[0], + END_OF_ARGS); + } + + FrameLen += TmpLen; + } + +#ifdef CONFIG_HOTSPOT + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable) + { + ULONG TmpLen; + + /* Hotspot 2.0 Indication */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HSIndicationIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HSIndicationIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Interworking element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.InterWorkingIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.InterWorkingIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Advertisement Protocol element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.AdvertisementProtoIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Roaming Consortium element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.RoamingConsortiumIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* P2P element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.P2PIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.P2PIE, END_OF_ARGS); + + FrameLen += TmpLen; + } +#endif + + /* Extended Capabilities IE */ + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D1.10, HT Information Exchange Support */ + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && + (pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.bBssCoexEnable == TRUE)) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.ProxyARPEnable) + extCapInfo.proxy_arp = 1; +#ifdef CONFIG_HOTSPOT_R2 + if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.WNMNotifyEnable) + extCapInfo.wnm_notification= 1; + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QosMapEnable) + extCapInfo.qosmap= 1; +#endif +#endif + +#ifdef CONFIG_HOTSPOT + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable) + extCapInfo.interworking = 1; +#endif + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + + FrameLen += TmpLen; + } + +#ifdef AP_QLOAD_SUPPORT + if (pAd->phy_ctrl.FlgQloadEnable != 0) + { +#ifdef CONFIG_HOTSPOT_R2 + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadTestEnable == 1) + FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pOutBuffer+FrameLen, apidx); + else if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadTestEnable == 0) +#endif + FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); + } +#endif /* AP_QLOAD_SUPPORT */ + + /* add WMM IE here */ + if (mbss->wdev.bWmmCapable) + { + UCHAR i; + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; +#ifdef UAPSD_SUPPORT + UAPSD_MR_IE_FILL(WmeParmIe[8], &mbss->UapsdInfo); +#endif /* UAPSD_SUPPORT */ + for (i=QID_AC_BE; i<=QID_AC_VO; i++) + { + WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ + ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ + (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ + WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ + (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ + WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ + WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ + } + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 26, WmeParmIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { + InsertTpcReportIE(pAd, pOutBuffer+FrameLen, &FrameLen, + RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); + RRM_InsertRRMEnCapIE(pAd, pOutBuffer+FrameLen, &FrameLen, apidx); + } + + + { + INT loop; + for (loop=0; loopCommonCfg.RegulatoryClass[loop] == 0) + break; + InsertChannelRepIE(pAd, pOutBuffer+FrameLen, &FrameLen, + (PSTRING)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[loop]); + } + } + +#ifndef APPLE_11K_IOT + /* Insert BSS AC Access Delay IE. */ + RRM_InsertBssACDelayIE(pAd, pOutBuffer+FrameLen, &FrameLen); + + /* Insert BSS Available Access Capacity IE. */ + RRM_InsertBssAvailableACIE(pAd, pOutBuffer+FrameLen, &FrameLen); +#endif /* !APPLE_11K_IOT */ + +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ + if (WMODE_CAP_N(PhyMode) && + (pAd->CommonCfg.Channel <= 14) && + (wdev->DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + OVERLAP_BSS_SCAN_IE OverlapScanParam; + ULONG TmpLen; + UCHAR OverlapScanIE, ScanIELen; + + OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; + ScanIELen = 14; + OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); + OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); + OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); + OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); + OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); + OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &OverlapScanIE, + 1, &ScanIELen, + ScanIELen, &OverlapScanParam, + END_OF_ARGS); + + FrameLen += TmpLen; + } + + /* 7.3.2.27 Extended Capabilities IE */ + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen; + + + extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + + /* P802.11n_D1.10, HT Information Exchange Support */ + if (WMODE_CAP_N(PhyMode) && (pAd->CommonCfg.Channel <= 14) && + (pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.bBssCoexEnable == TRUE)) + { + extCapInfo.BssCoexistMgmtSupport = 1; + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + + FrameLen += TmpLen; + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + /* add country IE, power constraint IE */ + if (pAd->CommonCfg.bCountryFlag) + { + ULONG TmpLen2=0; + UCHAR TmpFrame[256]; + UCHAR CountryIe = IE_COUNTRY; + UCHAR MaxTxPower=16; + +#ifdef A_BAND_SUPPORT + /* + Only 802.11a APs that comply with 802.11h are required to include + a Power Constrint Element(IE=32) in beacons and probe response frames + */ + if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE) + { + /* prepare power constraint IE */ + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 3, PowerConstraintIE, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode)) { + ULONG TmpLen; + UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; + UINT8 ie_len; + VHT_TXPWR_ENV_IE txpwr_env; + + ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &vht_txpwr_env_ie, + 1, &ie_len, + ie_len, &txpwr_env, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_VHT_AC */ + } +#endif /* A_BAND_SUPPORT */ + + NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); + + /* prepare channel information */ + MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx) + && (pAd->CommonCfg.RegulatoryClass[0] != 0)) + { + TmpLen2 = 0; + NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); + RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); + } +#endif /* DOT11K_RRM_SUPPORT */ + + /* need to do the padding bit check, and concatenate it */ + if ((TmpLen2%2) == 0) + { + UCHAR TmpLen3 = TmpLen2+4; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 3, pAd->CommonCfg.CountryCode, + TmpLen2+1, TmpFrame, + END_OF_ARGS); + } + else + { + UCHAR TmpLen3 = TmpLen2+3; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 3, pAd->CommonCfg.CountryCode, + TmpLen2, TmpFrame, + END_OF_ARGS); + } + FrameLen += TmpLen; + }/* Country IE - */ + +#ifdef A_BAND_SUPPORT + /* add Channel switch announcement IE */ + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) + { + UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; + UCHAR CSALen=3; + UCHAR CSAMode=1; + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CSAIe, + 1, &CSALen, + 1, &CSAMode, + 1, &pAd->CommonCfg.Channel, + 1, &pAd->Dot11_H.CSCount, + END_OF_ARGS); + FrameLen += TmpLen; +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) + { + HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; + + build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(PhyMode) && + (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, AddHtLen;/*, NewExtLen; */ +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + + if (pAd->bBroadComHT == TRUE) + { + UCHAR epigram_ie_len; + UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; + UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; + + + epigram_ie_len = HtLen + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + + epigram_ie_len = AddHtLen + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + AddHtLen, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + AddHtLen, &addHTInfoTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14)) { + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer+FrameLen), SUBTYPE_PROBE_RSP); + } +#endif /* DOT11_VHT_AC */ + + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(!mbss->SmartMeshCfg.bSupportHiddenWPS) +#endif /* SMART_MESH_HIDDEN_WPS */ + { + /* for windows 7 logo test */ + if ((mbss->WscControl.WscConfMode != WSC_DISABLE) && +#ifdef DOT1X_SUPPORT + (wdev->IEEE8021X == FALSE) && +#endif /* DOT1X_SUPPORT */ + (wdev->WepStatus == Ndis802_11WEPEnabled)) + { + /* + Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based + or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP + network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't + receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and + prompt user for the WEP key. <> + A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. + The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) + http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp + */ + ULONG TempLen1 = 0; + UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TempLen1, + 7, PROVISION_SERVICE_IE, + END_OF_ARGS); + FrameLen += TempLen1; + } + + /* add Simple Config Information Element */ + if ((mbss->WscControl.WscConfMode > WSC_DISABLE) && (mbss->WscIEProbeResp.ValueLen)) + { + ULONG WscTmpLen = 0; + MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen, + mbss->WscIEProbeResp.ValueLen, mbss->WscIEProbeResp.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } + } +#ifdef SMART_MESH_HIDDEN_WPS + else + { + if((ProbeReqParam.VIEFlag & 0x4) && + (ProbeReqParam.vendor_ie[2] & HIDDEN_WPS_STATE_RUNNING)) + WscPBC_DPID_FromSTA(pAd, ProbeReqParam.Addr2); + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + +#ifdef DOT11R_FT_SUPPORT + /* The Mobility Domain information element (MDIE) is present in Probe- + ** Request frame when dot11FastBssTransitionEnable is set to true. */ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + FT_CAP_AND_POLICY FtCap; + FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, + pFtCfg->FtMdId, FtCap); + } +#endif /* DOT11R_FT_SUPPORT */ + + +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + { + ULONG AirplayTmpLen = 0; + + /*User user setting IE*/ + if (pAd->pAirplayIe && (pAd->AirplayIeLen != 0)) + { + //printk("AIRPLAY IE setting : MakeOutgoingFrame IeLen=%d\n",pAd->AirplayIeLen); + //hex_dump("APPLE IE:", pAd->pAirplayIe , pAd->AirplayIeLen); + MakeOutgoingFrame(pOutBuffer+FrameLen, &AirplayTmpLen, + pAd->AirplayIeLen, pAd->pAirplayIe, + END_OF_ARGS); + FrameLen += AirplayTmpLen; + } + } +#endif /* AIRPLAY_SUPPORT*/ + + /* + add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back + Byte0.b3=1 for rssi-feedback + */ + { + ULONG TmpLen; + UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; + + if (pAd->CommonCfg.bAggregationCapable) + RalinkSpecificIe[5] |= 0x1; + if (pAd->CommonCfg.bPiggyBackCapable) + RalinkSpecificIe[5] |= 0x2; +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.bRdg) + RalinkSpecificIe[5] |= 0x4; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.b256QAM_2G && WMODE_2G_ONLY(pAd->CommonCfg.PhyMode)) + RalinkSpecificIe[5] |= 0x8; +#endif /* DOT11_VHT_AC */ + +#ifdef RSSI_FEEDBACK + if (ProbeReqParam.bRequestRssi == TRUE) + { + MAC_TABLE_ENTRY *pEntry=NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", + PRINT_MAC(ProbeReqParam.Addr2))); + + RalinkSpecificIe[5] |= 0x8; + pEntry = MacTableLookup(pAd, ProbeReqParam.Addr2); + + if (pEntry != NULL) + { + RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi0; + RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; + RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; + } + } +#endif /* RSSI_FEEDBACK */ + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + + } + +#ifdef SMART_MESH + SMART_MESH_INSERT_IE(pAd->ApCfg.MBSSID[apidx].SmartMeshCfg, + pOutBuffer, + FrameLen, + SM_IE_PROBE_RSP); +#endif /* SMART_MESH */ + + /* add Mediatek-specific IE here */ + { + ULONG TmpLen = 0; + UCHAR MediatekSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0xe7, 0x00, 0x00, 0x00, 0x00}; + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.b256QAM_2G && WMODE_2G_ONLY(pAd->CommonCfg.PhyMode)) + MediatekSpecificIe[5] |= 0x8; +#endif /* DOT11_VHT_AC */ + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, MediatekSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ + for (idx = 0; idx < mbss->ProbeRspTimes; idx++) + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef SMART_MESH_MONITOR +done: + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.probereq.type = NSMPIF_DRVEVNT_STA_PROBE_REQ; + drvevnt.data.probereq.rate = pAd->LastMgmtRxRate; + drvevnt.data.probereq.channel = pAd->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.probereq.sta_mac, Addr2, MAC_ADDR_LEN); + drvevnt.data.probereq.rssi = rssi; + drvevnt.data.probereq.snr = ConvertToSnr(pAd, Elem->Signal); +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if (IS_RT6352(pAd)) + { + if ((42 - drvevnt.data.probereq.snr) >= 0) + drvevnt.data.probereq.snr = (42 - drvevnt.data.probereq.snr); + else + drvevnt.data.probereq.snr = 0; + } + } +#endif /* RTMP_MAC */ + drvevnt.data.probereq.is_ucast = (ProbeReqParam.SsidLen!=0)?1:0; + drvevnt.data.probereq.cap = 0; +#ifdef DOT11_N_SUPPORT + if(ProbeReqParam.ie_list.ht_cap_len > 0) + drvevnt.data.probereq.cap |= NSMP_WLCAP_80211_N; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + if (ProbeReqParam.ie_list.vht_cap_len > 0) + drvevnt.data.probereq.cap |= NSMP_WLCAP_80211_AC; +#endif /* DOT11_VHT_AC */ + // Bandwdith + if (ProbeReqParam.ie_list.HTCapability.HtCapInfo.ChannelWidth == BW_40) + { +#ifdef DOT11_VHT_AC + if(ProbeReqParam.ie_list.vht_op_len > 0 && ProbeReqParam.ie_list.vht_op.vht_op_info.ch_width >= 1) + drvevnt.data.probereq.cap |= NSMP_WLCAP_HT80; + else +#endif /* DOT11_VHT_AC */ + drvevnt.data.probereq.cap |= NSMP_WLCAP_HT40; + } + + // RX/TX STREAM + drvevnt.data.probereq.cap |= \ + (ProbeReqParam.ie_list.HTCapability.MCSSet[3] != 0x00) ? (NSMP_WLCAP_RX_4_STREAMS|NSMP_WLCAP_TX_4_STREAMS) :\ + (ProbeReqParam.ie_list.HTCapability.MCSSet[2] != 0x00) ? (NSMP_WLCAP_RX_3_STREAMS|NSMP_WLCAP_TX_3_STREAMS) :\ + (ProbeReqParam.ie_list.HTCapability.MCSSet[1] != 0x00) ? (NSMP_WLCAP_RX_2_STREAMS|NSMP_WLCAP_TX_2_STREAMS) : 0; + + /* Vendor information element */ + drvevnt.data.probereq.ntgr_vie_len = ProbeReqParam.vendor_ie_len; + NdisZeroMemory(drvevnt.data.probereq.ntgr_vie,sizeof(drvevnt.data.probereq.ntgr_vie)); + if(ProbeReqParam.vendor_ie_len > 0) + NdisCopyMemory(drvevnt.data.probereq.ntgr_vie,ProbeReqParam.vendor_ie,ProbeReqParam.vendor_ie_len); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_PROBE_REQ, + NULL, (PUCHAR)&drvevnt.data.probereq, sizeof(drvevnt.data.probereq)); + } +#endif /* SMART_MESH_MONITOR */ + } +} + + +/* + ========================================================================== + Description: + parse the received BEACON + + NOTE: + The only thing AP cares about received BEACON frames is to decide + if there's any overlapped legacy BSS condition (OLBC). + If OLBC happened, this AP should set the ERP->Use_Protection bit in its + outgoing BEACON. The result is to tell all its clients to use RTS/CTS + or CTS-to-self protection to protect B/G mixed traffic + ========================================================================== + */ + + +typedef struct +{ + ULONG count; + UCHAR bssid[MAC_ADDR_LEN]; +} BSSIDENTRY; + + +VOID APPeerBeaconAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES], *pRates = NULL, RatesLen; + BOOLEAN LegacyBssExist; + CHAR RealRssi; + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + UCHAR MaxSupportedRate = 0; + + BCN_IE_LIST *ie_list = NULL; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + + /* Init Variable IE structure */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate VarIE fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + + + pRates = (PUCHAR)Rates; + + ie_list->Channel = Elem->Channel; + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + ie_list, + &LenVIE, + pVIE)) + { + + /* ignore BEACON not in this channel */ + if (ie_list->Channel != pAd->CommonCfg.Channel +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + && (!RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + ) + { + goto __End_Of_APPeerBeaconAction; + } + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + RTMPConflictSsidDetection(pAd, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, + (CHAR)Elem->Rssi0, (CHAR)Elem->Rssi1, (CHAR)Elem->Rssi2); +#endif /* IDS_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + if(ie_list->Channel == pAd->CommonCfg.Channel && pAd->ApEnableBeaconTable == TRUE) + { + ULONG Idx; + CHAR Rssi = -127; + UCHAR Snr0 = 0; + UCHAR Snr1 = 0; + UCHAR SNR0 = 0; + UCHAR SNR1 = 0; + SNR0 = ConvertToSnr(pAd,Elem->Snr0); + SNR1 = ConvertToSnr(pAd,Elem->Snr1); + Idx = BssTableSearch(&pAd->AvailableBSS, ie_list->Bssid, ie_list->Channel); + if (Idx != BSS_NOT_FOUND) + { + Rssi = pAd->AvailableBSS.BssEntry[Idx].Rssi; + Snr0 = pAd->AvailableBSS.BssEntry[Idx].Snr0; + Snr1 = pAd->AvailableBSS.BssEntry[Idx].Snr1; + } + // TODO: 2005-03-04 dirty patch. we should change all RSSI related variables to SIGNED SHORT for easy/efficient reading and calaulation + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + RealRssi = RealRssi + pAd->BbpRssiToDbmDelta; + if(Rssi == -127) + Rssi = RealRssi; + else + Rssi = (((Rssi * (MOV_AVG_CONST - 1)) + RealRssi) >> MOV_AVG_CONST_SHIFT); + + if(Snr0 == 0) + Snr0 = SNR0; + else + Snr0 = (((Snr0 * (MOV_AVG_CONST - 1)) + SNR0) >> MOV_AVG_CONST_SHIFT); + + if(Snr1 == 0) + Snr1 = SNR1; + else + Snr1 = (((Snr1 * (MOV_AVG_CONST - 1)) + SNR1) >> MOV_AVG_CONST_SHIFT); + + + Idx = BssTableSetEntry(pAd, &pAd->AvailableBSS, ie_list, Rssi, LenVIE, pVIE, Snr0, Snr1); + + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->AvailableBSS.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->AvailableBSS.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->AvailableBSS.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + } + } +#endif + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* 40Mhz BSS Width Trigger events Intolerant devices */ + if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (ie_list->HtCapability.HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ + ) + { + if (pAd->CommonCfg.Channel<=14) + { +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) + if(OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED) && + RTMP_CFG80211_VIF_P2P_CLI_ON(pAd) + ) + { + if (ie_list->Channel != pAd->CommonCfg.Channel) + { + DBGPRINT(RT_DEBUG_INFO, ("Channel=%d is not equal as CommonCfg.Channel = %d.\n", ie_list->Channel, pAd->CommonCfg.Channel)); +// goto __End_Of_APPeerBeaconAction; + } + } + else +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_CONCURRENT_DEVICE */ + if (((pAd->CommonCfg.CentralChannel+2) != ie_list->Channel) && + ((pAd->CommonCfg.CentralChannel-2) != ie_list->Channel)) + { +/* + DBGPRINT(RT_DEBUG_TRACE, ("%02x:%02x:%02x:%02x:%02x:%02x is a legacy BSS (%d) \n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5], Channel)); +*/ + goto __End_Of_APPeerBeaconAction; + } + } + else + { + if (ie_list->Channel != pAd->CommonCfg.Channel) + goto __End_Of_APPeerBeaconAction; + } + } +#endif /* DOT11_N_SUPPORT */ + + SupportRate(ie_list->SupRate, ie_list->SupRateLen, ie_list->ExtRate, ie_list->ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); + + if ((ie_list->Erp & 0x01) || (RatesLen <= 4)) + LegacyBssExist = TRUE; + else + LegacyBssExist = FALSE; + + if (LegacyBssExist && pAd->CommonCfg.DisableOLBCDetect == 0) + { + pAd->ApCfg.LastOLBCDetectTime = pAd->Mlme.Now32; + + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.bHTProtect) + && (ie_list->HtCapabilityLen == 0) && (RealRssi > OBSS_BEACON_RSSI_THRESHOLD)) + { + + pAd->ApCfg.LastNoneHTOLBCDetectTime = pAd->Mlme.Now32; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef APCLI_SUPPORT + ApCliCheckPeerExistence(pAd, ie_list->Ssid, ie_list->SsidLen, ie_list->Channel); + + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) + { + PMAC_TABLE_ENTRY pEntry = NULL; + UINT ifIndex = 0; + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + if (pEntry && IS_ENTRY_APCLI(pEntry) && (pEntry->wdev_idx < MAX_APCLI_NUM)) + { + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].ApCliRcvBeaconTime = pAd->Mlme.Now32; + ifIndex = pEntry->wdev_idx; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* what time dose the NoA on ? It should be Conneted on. */ + if (RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) + { + CFG80211_PeerP2pBeacon(pAd, ie_list->Addr2, Elem, ie_list->TimeStamp); + if(ie_list->MessageToMe && + NdisEqualMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, ie_list->Bssid, MAC_ADDR_LEN)) + { + MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->ApCfg.ApCliTab[0].PsPollFrame, sizeof(PSPOLL_FRAME)); + } + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + /* Check if root-ap change BW to 20 */ + if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_NONE) && + (ie_list->AddHtInfo.AddHtInfo.RecomWidth == 0)) + { +#ifdef MAC_REPEATER_SUPPORT + PMAC_TABLE_ENTRY pMacEntry = NULL; + UCHAR CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + pEntry->HTPhyMode.field.BW = 0; +#ifdef MAC_REPEATER_SUPPORT + + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx]; + + if ((pReptEntry->CliEnable) && (pReptEntry->CliValid)) + { + pMacEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID]; + if (pMacEntry) + pMacEntry->HTPhyMode.field.BW = 0; + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + DBGPRINT(RT_DEBUG_INFO, ("FallBack APClient BW to 20MHz\n")); + } + + /* Check if root-ap change BW to 40 */ + if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) && + (ie_list->HtCapabilityLen > 0) && + (ie_list->HtCapability.HtCapInfo.ChannelWidth == 1)) + { +#ifdef MAC_REPEATER_SUPPORT + PMAC_TABLE_ENTRY pMacEntry = NULL; + UCHAR CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + pEntry->HTPhyMode.field.BW = 1; +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx]; + + if ((pReptEntry->CliEnable) && (pReptEntry->CliValid)) + { + pMacEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID]; + if (pMacEntry) + pMacEntry->HTPhyMode.field.BW = 1; + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + DBGPRINT(RT_DEBUG_INFO, ("FallBack APClient BW to 40MHz\n")); + } + } +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + UCHAR RegClass; + OVERLAP_BSS_SCAN_IE BssScan; + BOOLEAN brc; + + brc = PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &BssScan, &RegClass); + if (brc == TRUE) + { + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = le2cpu16(BssScan.TriggerScanInt); /*APBssScan.TriggerScanInt[1] * 256 + APBssScan.TriggerScanInt[0];*/ + /*DBGPRINT(RT_DEBUG_ERROR,("Update Dot11BssWidthTriggerScanInt=%d \n", pAd->CommonCfg.Dot11BssWidthTriggerScanInt)); */ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11BssWidthTriggerScanInt < 10) ||(pAd->CommonCfg.Dot11BssWidthTriggerScanInt > 900)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11BssWidthTriggerScanInt out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = 900; + } + } +#ifdef DOT11_VHT_AC + if (ie_list->operating_mode.rx_nss_type == 0) { + pEntry->force_op_mode = TRUE; + NdisMoveMemory(&pEntry->operating_mode, &ie_list->operating_mode, 1); + //printk("recv notify\n"); + } +#endif /* DOT11_VHT_AC */ + } +#endif /* APCLI_CERT_SUPPORT */ + if (/*(ApCliWaitProbRsp(pAd, ifIndex) == TRUE) &&*/ + (NdisEqualMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, ie_list->Bssid, MAC_ADDR_LEN))) + { + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PEER_BEACON, Elem->MsgLen, Elem->Msg, ifIndex); + } + if ( (pAd->CommonCfg.bIEEE80211H == 1) && + ie_list->NewChannel != 0 && + pAd->CommonCfg.Channel != ie_list->NewChannel && + pAd->Dot11_H.RDMode != RD_SWITCHING_MODE) + { + pAd->CommonCfg.Channel = ie_list->NewChannel; + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + DBGPRINT(RT_DEBUG_TRACE, + ("[APCLI] Following root AP to switch channel to ch%u\n", + pAd->CommonCfg.Channel)); + } + } + } +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + do + { + MAC_TABLE_ENTRY *pEntry; + BOOLEAN bWmmCapable; + + /* check BEACON does in WDS TABLE. */ + pEntry = WdsTableLookup(pAd, ie_list->Addr2, FALSE); + bWmmCapable = ie_list->EdcaParm.bValid ? TRUE : FALSE; + + if (pEntry) + { + WdsPeerBeaconProc(pAd, pEntry, ie_list->CapabilityInfo, + MaxSupportedRate, RatesLen, bWmmCapable, + ie_list->RalinkIe, +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len, + &ie_list->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &ie_list->HtCapability, + ie_list->HtCapabilityLen); + } + } while(FALSE); +#endif /* WDS_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.bOverlapScanning == TRUE) + { + INT index,secChIdx; + ADD_HTINFO *pAdd_HtInfo; + + for (index = 0; index < pAd->ChannelListNum; index++) + { + /* found the effected channel, mark that. */ + if(pAd->ChannelList[index].Channel == ie_list->Channel) + { + secChIdx = -1; + if (ie_list->HtCapabilityLen > 0 && ie_list->AddHtInfoLen > 0) + { /* This is a 11n AP. */ + pAd->ChannelList[index].bEffectedChannel |= EFFECTED_CH_PRIMARY; /* 2; // 2 for 11N 20/40MHz AP with primary channel set as this channel. */ + pAdd_HtInfo = &ie_list->AddHtInfo.AddHtInfo; + if (pAdd_HtInfo->ExtChanOffset == EXTCHA_BELOW) + { +#ifdef A_BAND_SUPPORT + if (ie_list->Channel > 14) + secChIdx = ((index > 0) ? (index - 1) : -1); + else +#endif /* A_BAND_SUPPORT */ + secChIdx = ((index >= 4) ? (index - 4) : -1); + } + else if (pAdd_HtInfo->ExtChanOffset == EXTCHA_ABOVE) + { +#ifdef A_BAND_SUPPORT + if (ie_list->Channel > 14) + secChIdx = (((index+1) < pAd->ChannelListNum) ? (index + 1) : -1); + else +#endif /* A_BAND_SUPPORT */ + secChIdx = (((index+4) < pAd->ChannelListNum) ? (index + 4) : -1); + } + + if (secChIdx >=0) + pAd->ChannelList[secChIdx].bEffectedChannel |= EFFECTED_CH_SECONDARY; /* 1; */ + + if ((pAd->CommonCfg.Channel != ie_list->Channel) || + (pAdd_HtInfo->ExtChanOffset != pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset) + ) + pAd->CommonCfg.BssCoexApCnt++; + } + else + { + /* This is a legacy AP. */ + pAd->ChannelList[index].bEffectedChannel |= EFFECTED_CH_LEGACY; /* 4; 1 for legacy AP. */ + pAd->CommonCfg.BssCoexApCnt++; + } + } + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + } + /* sanity check fail, ignore this frame */ + +__End_Of_APPeerBeaconAction: +#ifdef CONFIG_AP_SUPPORT +IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +{ + if (ie_list->Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, ie_list->Bssid, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + AutoChBssInsertEntry(pAd, ie_list->Bssid, ie_list->Ssid, ie_list->SsidLen, ie_list->Channel, ie_list->NewExtChannelOffset, RealRssi); + } +} +#endif /* CONFIG_AP_SUPPORT */ + +LabelErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} + +#ifdef AP_SCAN_SUPPORT +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID APInvalidStateWhenScan(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.ApSyncMachine.CurrState)); +} + +/* + ========================================================================== + Description: + Scan timeout handler, executed in timer thread + ========================================================================== + */ +VOID APScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - Scan Timeout \n")); + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_SCAN_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Scan timeout procedure. basically add channel index by 1 and rescan + ========================================================================== + */ +VOID APScanTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + if(pAd->MlmeAux.ScanGivenChannel == TRUE) + { + pAd->MlmeAux.Channel = 0; + pAd->MlmeAux.ScanGivenChannel = FALSE; + } + else +#endif +#endif +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->MlmeAux.Channel = RTMPFindScanChannel(pAd, pAd->MlmeAux.Channel); +#else + pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + iwpriv set auto channel selection + update the current index of the channel + */ +#ifndef CUSTOMER_DCC_FEATURE + if (pAd->ApCfg.bAutoChannelAtBootup == TRUE) +#endif + { + /* update current channel info */ + UpdateChannelInfo(pAd, pAd->ApCfg.current_channel_index, pAd->ApCfg.AutoChannelAlg); + + /* move to next channel */ + pAd->ApCfg.current_channel_index++; +#ifdef SMART_MESH + pAd->ApCfg.scan_channel_index++; +#endif /* SMART_MESH */ + if (pAd->ApCfg.current_channel_index < pAd->ChannelListNum) + { + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[pAd->ApCfg.current_channel_index].Channel; + } + } +#ifdef SMART_MESH + else + { + Set_Scan_False_CCA(pAd, pAd->ApCfg.scan_channel_index, CCA_STORE); + pAd->ApCfg.scan_channel_index++; + } +#endif /* SMART_MESH */ + } +#endif /* CONFIG_AP_SUPPORT */ + ScanNextChannel(pAd, OPMODE_AP, pAd->MlmeAux.ScanInfType); +} + +#ifdef CON_WPS +VOID APMlmeScanCompleteAction(PRTMP_ADAPTER pAd, MLME_QUEUE_ELEM *Elem) +{ + PWSC_CTRL pWscControl; + PWSC_CTRL pApCliWscControl; + UCHAR apidx; + INT IsAPConfigured; + + DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - APMlmeScanCompleteAction\n")); + + /* If We catch the SR=TRUE in last scan_res, stop the AP Wsc SM */ + pApCliWscControl = &pAd->ApCfg.ApCliTab[BSS0].WscControl; + WscPBCBssTableSort(pAd, pApCliWscControl); + + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + IsAPConfigured = pWscControl->WscConfStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS[%d]: info %d, %d\n", apidx, pWscControl->WscState, pWscControl->bWscTrigger)); + if ((pWscControl->WscConfMode != WSC_DISABLE) && + (pWscControl->bWscTrigger == TRUE) && + (pApCliWscControl->WscPBCBssCount > 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS[%d]: Stop the AP Wsc Machine\n", apidx)); + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + WscStop(pAd, FALSE, pWscControl); + /* AP: For stop the other side of the band with WSC SM */ + WscConWpsStop(pAd, FALSE, pWscControl); + continue; + } + } + +} +#endif /* CON_WPS*/ + +/* + ========================================================================== + Description: + MLME SCAN req state machine procedure + ========================================================================== + */ +VOID APMlmeScanReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType; +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + UINT Channel = 0; + UINT Timeout = 0; +#endif +#endif + + /* Suspend MSDU transmission here */ + RTMPSuspendMsduTransmission(pAd); + + /* first check the parameter sanity */ +#ifdef CUSTOMER_DCC_FEATURE + if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType, &Channel, &Timeout)) +#else + if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType)) +#endif + { + DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - MlmeScanReqAction\n")); + NdisGetSystemUpTime(&pAd->ApCfg.LastScanTime); + + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + + /* record desired BSS parameters */ + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.ScanType = ScanType; + pAd->MlmeAux.SsidLen = SsidLen; + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); +#ifdef CUSTOMER_DCC_FEATURE + pAd->MlmeAux.ScanGivenChannel = FALSE; + pAd->MlmeAux.ScanTime = Timeout; + if( Channel != 0) + { + pAd->MlmeAux.Channel = Channel; + pAd->MlmeAux.ScanGivenChannel = TRUE; + } + else +#endif + { + /* start from the first channel */ +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->MlmeAux.Channel = RTMPFindScanChannel(pAd, 0); +#else + pAd->MlmeAux.Channel = FirstChannel(pAd); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + } + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.bAutoChannelAtBootup == TRUE)/* iwpriv set auto channel selection */ + { + APAutoChannelInit(pAd); + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[0].Channel; + } +#ifdef SMART_MESH + Set_Scan_False_CCA(pAd, 0, CCA_RESET); +#endif /* SMART_MESH */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + { + UINT32 mac_val; + RTMP_IO_READ32(pAd, CH_BUSY_STA, &mac_val); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &mac_val); + } +#endif + ScanNextChannel(pAd, OPMODE_AP, INT_MAIN); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("AP SYNC - MlmeScanReqAction() sanity check fail. BUG!!!\n")); + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + } +} + + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID APPeerBeaconAtScanAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFrame; + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + CHAR RealRssi = -127; + + BCN_IE_LIST *ie_list = NULL; +#ifdef CUSTOMER_DCC_FEATURE + UCHAR Snr0 = Elem->Snr0; + UCHAR Snr1 = Elem->Snr1; + + Snr0 = ConvertToSnr(pAd, Snr0); + Snr1 = ConvertToSnr(pAd, Snr1); +#endif + + os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (!ie_list) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Alloc memory for ie_list fail!!!\n", __FUNCTION__)); + return; + } + NdisZeroMemory((UCHAR *)ie_list, sizeof(BCN_IE_LIST)); + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + pFrame = (PFRAME_802_11) Elem->Msg; + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, Elem->MsgLen, Elem->Channel, + ie_list, &LenVIE, pVIE)) + { + ULONG Idx; + CHAR Rssi = -127; + + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + + + /* ignore BEACON not in this channel */ + if (ie_list->Channel != pAd->MlmeAux.Channel +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + ) + { + //CFG_TODO + goto __End_Of_APPeerBeaconAtScanAction; + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (ie_list->HtCapability.HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + if (ie_list->Channel == pAd->CommonCfg.Channel) + RTMPConflictSsidDetection(pAd, ie_list->Ssid, ie_list->SsidLen, Elem->Rssi0, Elem->Rssi1, Elem->Rssi2); +#endif /* IDS_SUPPORT */ + + /* + This correct im-proper RSSI indication during SITE SURVEY issue. + Always report bigger RSSI during SCANNING when receiving multiple BEACONs from the same AP. + This case happens because BEACONs come from adjacent channels, so RSSI become weaker as we + switch to more far away channels. + */ + Idx = BssTableSearch(&pAd->ScanTab, ie_list->Bssid, ie_list->Channel); + if (Idx != BSS_NOT_FOUND) + Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; + + + + /* TODO: 2005-03-04 dirty patch. we should change all RSSI related variables to SIGNED SHORT for easy/efficient reading and calaulation */ + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + if ((RealRssi + pAd->BbpRssiToDbmDelta) > Rssi) + Rssi = RealRssi + pAd->BbpRssiToDbmDelta; + + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + Snr0, + Snr1 +#endif + ); +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Check if this scan channel is the effeced channel */ + if (APCLI_IF_UP_CHECK(pAd, 0) && pAd->bApCliCertTest == TRUE + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + && ((ie_list->Channel > 0) && (ie_list->Channel <= 14))) + { + int chListIdx; + + /* + First we find the channel list idx by the channel number + */ + for (chListIdx = 0; chListIdx < pAd->ChannelListNum; chListIdx++) + { + if (ie_list->Channel == pAd->ChannelList[chListIdx].Channel) + break; + } + + if (chListIdx < pAd->ChannelListNum) + { + /* + If this channel is effected channel for the 20/40 coex operation. Check the related IEs. + */ + if (pAd->ChannelList[chListIdx].bEffectedChannel == TRUE) + { + UCHAR RegClass; + OVERLAP_BSS_SCAN_IE BssScan; + + /* Read Beacon's Reg Class IE if any. */ + PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &BssScan, &RegClass); + //printk("\x1b[31m TriEventTableSetEntry \x1b[m\n"); + TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, ie_list->Bssid, &ie_list->HtCapability, ie_list->HtCapabilityLen, RegClass, ie_list->Channel ); + } + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + } + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (RTMPEqualMemory(ie_list->Ssid, "DIRECT-", 7)) + DBGPRINT(RT_DEBUG_OFF, ("%s P2P_SCANNING: %s [%d], channel =%u\n", __FUNCTION__, ie_list->Ssid, Idx,Elem->Channel)); + + DBGPRINT(RT_DEBUG_TRACE, ("APPeerBeaconAtScanAction : Update the SSID %s in Kernel Table, Elem->Channel=%u\n", ie_list->Ssid,Elem->Channel)); + RT_CFG80211_SCANNING_INFORM(pAd, Idx, /*ie_list->Channel*/Elem->Channel, (UCHAR *)Elem->Msg, Elem->MsgLen, RealRssi); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#ifdef APCLI_SUPPORT +#ifdef SMART_MESH + if(Idx != BSS_NOT_FOUND) + { + pAd->ScanTab.BssEntry[Idx].VIEFlag = ie_list->VIEFlag; + if(APCLI_IF_UP_CHECK(pAd, MAIN_MBSSID)) + { + PSMART_MESH_CFG pSmartMeshCfg = NULL; + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[MAIN_MBSSID].SmartMeshCfg; + + if(((pSmartMeshCfg->HiFiFlagMask != 0) && (pSmartMeshCfg->HiFiFlagValue != 0)) && + ((ie_list->VIEFlag & pSmartMeshCfg->HiFiFlagMask) == pSmartMeshCfg->HiFiFlagValue)) + pAd->ScanTab.BssEntry[Idx].bHyperFiPeer = TRUE; + else + pAd->ScanTab.BssEntry[Idx].bHyperFiPeer = FALSE; + + if(pAd->ScanTab.BssEntry[Idx].bSupportSmartMesh != ie_list->bSupportSmartMesh) + pAd->ScanTab.BssEntry[Idx].bSupportSmartMesh = ie_list->bSupportSmartMesh; + } + } +#endif /* SMART_MESH */ +#endif /* APCLI_SUPPORT */ +#ifdef MWDS + if (Idx != BSS_NOT_FOUND) + { + if(pAd->ScanTab.BssEntry[Idx].bSupportMWDS != ie_list->bSupportMWDS) + pAd->ScanTab.BssEntry[Idx].bSupportMWDS = ie_list->bSupportMWDS; + } +#endif /* MWDS */ + +#ifdef SMART_MESH_MONITOR + if(pFrame && (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_RSP)) + { + struct nsmpif_drvevnt_buf drvevnt; + + drvevnt.data.proberesp.type = NSMPIF_DRVEVNT_AP_PROBE_RESP; + drvevnt.data.proberesp.channel = ie_list->Channel; + COPY_MAC_ADDR(drvevnt.data.proberesp.ap_mac, ie_list->Addr2); + drvevnt.data.proberesp.is_ucast = 1; + drvevnt.data.proberesp.rate = pAd->LastMgmtRxRate; + drvevnt.data.proberesp.rssi = RealRssi; + drvevnt.data.proberesp.snr = ConvertToSnr(pAd, Elem->Signal); +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if (IS_RT6352(pAd)) + { + if ((42 - drvevnt.data.proberesp.snr) >= 0) + drvevnt.data.proberesp.snr = (42 - drvevnt.data.proberesp.snr); + else + drvevnt.data.proberesp.snr = 0; + } + } +#endif /* RTMP_MAC */ + NdisZeroMemory(drvevnt.data.proberesp.ssid,sizeof(drvevnt.data.proberesp.ssid)); + NdisCopyMemory(drvevnt.data.proberesp.ssid,ie_list->Ssid,ie_list->SsidLen); + drvevnt.data.proberesp.cap = 0; +#ifdef DOT11_N_SUPPORT + if(ie_list->HtCapabilityLen > 0) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_80211_N; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len > 0) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_80211_AC; +#endif /* DOT11_VHT_AC */ + // Bandwdith + if (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) + { +#ifdef DOT11_VHT_AC + if(ie_list->vht_op_len > 0 && ie_list->vht_op_ie.vht_op_info.ch_width >= 1) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_HT80; + else +#endif /* DOT11_VHT_AC */ + drvevnt.data.proberesp.cap |= NSMP_WLCAP_HT40; + } + // RX/TX STREAM + drvevnt.data.proberesp.cap |= \ + (ie_list->HtCapability.MCSSet[3] != 0x00) ? (NSMP_WLCAP_RX_4_STREAMS|NSMP_WLCAP_TX_4_STREAMS) :\ + (ie_list->HtCapability.MCSSet[2] != 0x00) ? (NSMP_WLCAP_RX_3_STREAMS|NSMP_WLCAP_TX_3_STREAMS) :\ + (ie_list->HtCapability.MCSSet[1] != 0x00) ? (NSMP_WLCAP_RX_2_STREAMS|NSMP_WLCAP_TX_2_STREAMS) : 0; + + /* Vendor information element */ + drvevnt.data.proberesp.ntgr_vie_len = ie_list->vendor_ie_len; + NdisZeroMemory(drvevnt.data.proberesp.ntgr_vie,sizeof(drvevnt.data.proberesp.ntgr_vie)); + if(ie_list->vendor_ie_len > 0) + NdisCopyMemory(drvevnt.data.proberesp.ntgr_vie,ie_list->vendor_ie,ie_list->vendor_ie_len); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_AP_PROBE_RESP, + NULL, (PUCHAR)&drvevnt.data.proberesp, sizeof(drvevnt.data.proberesp)); + } +#endif /* SMART_MESH_MONITOR */ + } + + /* sanity check fail, ignored */ +__End_Of_APPeerBeaconAtScanAction: + /*scan beacon in pastive */ +#ifdef CONFIG_AP_SUPPORT +IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +{ + if (ie_list->Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, ie_list->Bssid, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + + AutoChBssInsertEntry(pAd, ie_list->Bssid, (CHAR *)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel, ie_list->NewExtChannelOffset, RealRssi); + } +} +#endif /* CONFIG_AP_SUPPORT */ + +LabelErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + +} + +/* + ========================================================================== + Description: + MLME Cancel the SCAN req state machine procedure + ========================================================================== + */ +VOID APScanCnclAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_AP, INT_MAIN); + + return; +} + +/* + ========================================================================== + Description: + if ChannelSel is false, + AP scans channels and lists the information of channels. + if ChannelSel is true, + AP scans channels and selects an optimal channel. + + NOTE: + ========================================================================== +*/ +VOID ApSiteSurvey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_SSID pSsid, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + BOOLEAN bResetBssTable = TRUE; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, ignore this scan. + */ + DBGPRINT(RT_DEBUG_TRACE, ("ApSiteSurvey:: Scanning now\n")); + return; + } + + AsicDisableSync(pAd); + +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (((pAd->ApCfg.bPartialScanning == TRUE) && (pAd->ApCfg.LastPartialScanChannel != 0))) + bResetBssTable = FALSE; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#ifdef WSC_INCLUDED + if(ScanType == SCAN_WSC_ACTIVE) + bResetBssTable = TRUE; +#endif /* WSC_INCLUDED */ + if(bResetBssTable) + BssTableInit(&pAd->ScanTab); +#ifdef CUSTOMER_DCC_FEATURE + ChannelInfoResetNew(pAd); + RTMPZeroMemory(&ScanReq, sizeof(ScanReq)); +#endif + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + + RTMPZeroMemory(ScanReq.Ssid, MAX_LEN_OF_SSID); + ScanReq.SsidLen = 0; + if (pSsid) + { + ScanReq.SsidLen = pSsid->SsidLength; + NdisMoveMemory(ScanReq.Ssid, pSsid->Ssid, pSsid->SsidLength); + } + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = ScanType; + pAd->ApCfg.bAutoChannelAtBootup = ChannelSel; + + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + RTMP_MLME_HANDLER(pAd); +} + +#ifdef CUSTOMER_DCC_FEATURE +UCHAR Channel2Index( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + UCHAR i; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (channel == pAd->ChannelList[i].Channel) + return i; + } + return -1; +} + +VOID ApSiteSurveyNew( + IN PRTMP_ADAPTER pAd, + IN UINT channel, + IN UINT timeout, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + NdisZeroMemory(&ScanReq, sizeof(MLME_SCAN_REQ_STRUCT)); + AsicDisableSync(pAd); + //printk("%s , %u, %u, %u",__func__,channel,timeout,ScanType); + BssTableInit(&pAd->ScanTab); + ChannelInfoResetNew(pAd); + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = ScanType; + ScanReq.Channel = channel; + ScanReq.Timeout = timeout; + pAd->ApCfg.bAutoChannelAtBootup = ChannelSel; + pAd->ApCfg.current_channel_index = Channel2Index (pAd, channel); + pAd->ChannelInfo.ChannelNo = channel; + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + RTMP_MLME_HANDLER(pAd); +} + +VOID RemoveOldBssEntry( + IN PRTMP_ADAPTER pAd) +{ + INT32 i; + + if(pAd->AvailableBSS.BssNr > 0) + { + for(i = 0; i < pAd->AvailableBSS.BssNr; i++) + { + if((jiffies_to_msecs(jiffies) - pAd->AvailableBSS.BssEntry[i].LastBeaconRxTime) >= 300000) + { + NdisZeroMemory(&pAd->AvailableBSS.BssEntry[i],sizeof(BSS_ENTRY)); + if(i != (pAd->AvailableBSS.BssNr - 1)) + { + NdisCopyMemory(&pAd->AvailableBSS.BssEntry[i], &pAd->AvailableBSS.BssEntry[pAd->AvailableBSS.BssNr - 1], sizeof(BSS_ENTRY)); + NdisZeroMemory( &pAd->AvailableBSS.BssEntry[pAd->AvailableBSS.BssNr - 1],sizeof(BSS_ENTRY)); + } + pAd->AvailableBSS.BssNr--; + } + } + } +} + +VOID APResetStreamingStatus( + IN PRTMP_ADAPTER pAd) +{ + UINT64 Time = jiffies_to_msecs(jiffies); + + if((Time - pAd->StreamingTypeStatus.BE_Time) > 1000) + pAd->StreamingTypeStatus.BE = FALSE; + + if((Time - pAd->StreamingTypeStatus.BK_Time) > 1000) + pAd->StreamingTypeStatus.BK = FALSE; + + if((Time - pAd->StreamingTypeStatus.VI_Time) > 1000) + pAd->StreamingTypeStatus.VI = FALSE; + + if((Time - pAd->StreamingTypeStatus.VO_Time) > 1000) + pAd->StreamingTypeStatus.VO= FALSE; +} + +VOID RemoveOldStaList( + IN PRTMP_ADAPTER pAd) +{ + + INT32 i; + + if(pAd->AllowedStaList.StaCount > 0) + { + for(i = 0; i < pAd->AllowedStaList.StaCount; i++) + { + if((jiffies_to_msecs(jiffies) - pAd->AllowedStaList.AllowedSta[i].DissocTime) >= 30000) + { + NdisZeroMemory(&pAd->AllowedStaList.AllowedSta[i],sizeof(ALLOWED_STA)); + if(i != (pAd->AllowedStaList.StaCount - 1)) + { + NdisCopyMemory(&pAd->AllowedStaList.AllowedSta[i], &pAd->AllowedStaList.AllowedSta[pAd->AllowedStaList.StaCount - 1], sizeof(ALLOWED_STA)); + NdisZeroMemory( &pAd->AllowedStaList.AllowedSta[pAd->AllowedStaList.StaCount - 1], sizeof(ALLOWED_STA)); + } + pAd->AllowedStaList.StaCount--; + } + } + } +} + +VOID ReadChannelStats( + IN UINT32 Ch_Busy_Time, + IN PRTMP_ADAPTER pAd) +{ + UINT32 mac_val; + UINT64 Time; + UINT32 TimeDiff; + UINT64 temp; + RX_STA_CNT1_STRUC RxStaCnt1; + + TIMESTAMP_GET(pAd, Time); + + TimeDiff = Time - pAd->ChannelStats.LastReadTime; + pAd->ChannelStats.TotalDuration += TimeDiff; + pAd->ChannelStats.LastReadTime = Time; + pAd->ChannelStats.msec100counts ++; + + pAd->ChannelStats.ChBusytime += Ch_Busy_Time; + pAd->ChannelStats.ChBusyTime1secValue += Ch_Busy_Time; + + RTMP_IO_READ32(pAd, CCA_BUSY_TIME, &mac_val); + pAd->ChannelStats.CCABusytime += mac_val; + pAd->ChannelStats.CCABusyTime1secValue += mac_val; + + + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + pAd->ChannelStats.FalseCCACount += RxStaCnt1.field.FalseCca; + pAd->ChannelStats.FalseCCACount1secValue += RxStaCnt1.field.FalseCca; + + /* Update RX PLCP error counter*/ + pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; + /* Update False CCA counter for Ralink counter*/ + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + + if((pAd->ChannelStats.msec100counts % 10) == 0) + { + if(pAd->ChannelStats.ChBusyTimeAvg == 0) + pAd->ChannelStats.ChBusyTimeAvg = pAd->ChannelStats.ChBusyTime1secValue; + else + pAd->ChannelStats.ChBusyTimeAvg = (((pAd->ChannelStats.ChBusyTimeAvg * (MOV_AVG_CONST - 1)) + pAd->ChannelStats.ChBusyTime1secValue) >> MOV_AVG_CONST_SHIFT); + + if(pAd->ChannelStats.CCABusyTimeAvg == 0) + pAd->ChannelStats.CCABusyTimeAvg = pAd->ChannelStats.CCABusyTime1secValue; + else + pAd->ChannelStats.CCABusyTimeAvg = (((pAd->ChannelStats.CCABusyTimeAvg * (MOV_AVG_CONST - 1)) + pAd->ChannelStats.CCABusyTime1secValue) >> MOV_AVG_CONST_SHIFT); + + if(pAd->ChannelStats.FalseCCACountAvg == 0) + pAd->ChannelStats.FalseCCACountAvg = pAd->ChannelStats.FalseCCACount1secValue; + else + pAd->ChannelStats.FalseCCACountAvg = (((pAd->ChannelStats.FalseCCACountAvg * (MOV_AVG_CONST - 1)) + pAd->ChannelStats.FalseCCACount1secValue) >> MOV_AVG_CONST_SHIFT); + + if(pAd->ChannelStats.ChannelApActivityAvg == 0) + pAd->ChannelStats.ChannelApActivityAvg = pAd->ChannelStats.ChannelApActivity1secValue; + else + { + temp = (UINT64)((pAd->ChannelStats.ChannelApActivityAvg * (MOV_AVG_CONST - 1)) + pAd->ChannelStats.ChannelApActivity1secValue); + do_div(temp , MOV_AVG_CONST); + pAd->ChannelStats.ChannelApActivityAvg = temp; + } + pAd->ChannelStats.ChBusyTime1secValue = 0; + pAd->ChannelStats.CCABusyTime1secValue = 0; + pAd->ChannelStats.FalseCCACount1secValue = 0; + pAd->ChannelStats.ChannelApActivity1secValue = 0; + pAd->ChannelStats.msec100counts = 10; /* restart 1 sec counter for AVG value */ + } +} + +VOID ClearChannelStats( + IN PRTMP_ADAPTER pAd) +{ + UINT32 mac_val; + UINT32 Time; + + TIMESTAMP_GET(pAd, Time); + + pAd->ChannelStats.LastReadTime = Time; + + //RTMP_IO_READ32(pAd, CH_BUSY_STA, &mac_val); + + RTMP_IO_READ32(pAd, CCA_BUSY_TIME, &mac_val); + + RTMP_IO_READ32(pAd, RX_STA_CNT1, &mac_val); +} + +VOID ResetChannelStatus( + IN PRTMP_ADAPTER pAd) +{ + pAd->ChannelStats.LastReadTime = 0; + pAd->ChannelStats.TotalDuration = 0; + pAd->ChannelStats.CCABusytime = 0; + pAd->ChannelStats.ChBusytime = 0; + pAd->ChannelStats.FalseCCACount = 0; + pAd->ChannelStats.ChannelApActivity = 0; +} +#endif + +BOOLEAN ApScanRunning(RTMP_ADAPTER *pAd) +{ + return (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE; +} + +#ifdef AP_PARTIAL_SCAN_SUPPORT +/* + ========================================================================== + Description: + + Return: + scan_channel - channel to scan. + Note: + return 0 if no more next channel + ========================================================================== + */ +UCHAR FindPartialScanChannel( + IN PRTMP_ADAPTER pAd) +{ + UCHAR scan_channel = 0; + if (pAd->ApCfg.PartialScanChannelNum > 0) + { + pAd->ApCfg.PartialScanChannelNum--; + + if (pAd->ApCfg.LastPartialScanChannel == 0) + scan_channel = FirstChannel(pAd); + else + scan_channel = NextChannel(pAd, pAd->ApCfg.LastPartialScanChannel); + + /* update last scanned channel */ + pAd->ApCfg.LastPartialScanChannel = scan_channel; + if (scan_channel == 0) + { + pAd->ApCfg.bPartialScanning = FALSE; + pAd->ApCfg.PartialScanChannelNum = DEFLAUT_PARTIAL_SCAN_CH_NUM; + } + } + else + { + /* Pending for next partial scan */ + scan_channel = 0; + pAd->ApCfg.PartialScanChannelNum = DEFLAUT_PARTIAL_SCAN_CH_NUM; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s, %u, scan_channel = %u, PartialScanChannelNum = %u, LastPartialScanChannel = %u, bPartialScanning = %u\n", + __FUNCTION__, __LINE__, + scan_channel, + pAd->ApCfg.PartialScanChannelNum, + pAd->ApCfg.LastPartialScanChannel, + pAd->ApCfg.bPartialScanning)); + return scan_channel; +} +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* AP_SCAN_SUPPORT */ + + +/* + ========================================================================== + Description: + The sync state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + + AP_SYNC_IDLE + APMT2_PEER_PROBE_REQ peer_probe_req_action + ========================================================================== + */ +VOID APSyncStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC *)Trans, AP_MAX_SYNC_STATE, AP_MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, AP_SYNC_IDLE, AP_SYNC_MACHINE_BASE); + + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)APPeerProbeReqAction); + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAction); +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_SUPPORT) || defined(SMART_MESH_MONITOR) + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); +#endif /* P2P_SUPPORT || RT_CFG80211_SUPPORT || SMART_MESH_MONITOR */ +#ifdef AP_SCAN_SUPPORT + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APMlmeScanReqAction); +#ifdef CON_WPS + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_MLME_SCAN_COMPLETE, (STATE_MACHINE_FUNC)APMlmeScanCompleteAction); +#endif /* CON_WPS */ + + /* scan_listen state */ + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APInvalidStateWhenScan); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)APScanTimeoutAction); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_MLME_SCAN_CNCL, (STATE_MACHINE_FUNC)APScanCnclAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.APScanTimer, GET_TIMER_FUNCTION(APScanTimeout), pAd, FALSE); +#endif /* AP_SCAN_SUPPORT */ +} + + +VOID SupportRate( + IN PUCHAR SupRate, + IN UCHAR SupRateLen, + IN PUCHAR ExtRate, + IN UCHAR ExtRateLen, + OUT PUCHAR *ppRates, + OUT PUCHAR RatesLen, + OUT PUCHAR pMaxSupportRate) +{ + INT i; + + *pMaxSupportRate = 0; + + if ((SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) && (SupRateLen > 0)) + { + NdisMoveMemory(*ppRates, SupRate, SupRateLen); + *RatesLen = SupRateLen; + } + else + { + /* HT rate not ready yet. return true temporarily. rt2860c */ + /*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */ + *RatesLen = 8; + *(*ppRates + 0) = 0x82; + *(*ppRates + 1) = 0x84; + *(*ppRates + 2) = 0x8b; + *(*ppRates + 3) = 0x96; + *(*ppRates + 4) = 0x12; + *(*ppRates + 5) = 0x24; + *(*ppRates + 6) = 0x48; + *(*ppRates + 7) = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("SUPP_RATES., Len=%d\n", SupRateLen)); + } + + if (ExtRateLen + *RatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory((*ppRates + (ULONG)*RatesLen), ExtRate, ExtRateLen); + *RatesLen = (*RatesLen) + ExtRateLen; + } + else + { + NdisMoveMemory((*ppRates + (ULONG)*RatesLen), ExtRate, MAX_LEN_OF_SUPPORTED_RATES - (*RatesLen)); + *RatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + + + + for (i = 0; i < *RatesLen; i++) + { + if(*pMaxSupportRate < (*(*ppRates + i) & 0x7f)) + *pMaxSupportRate = (*(*ppRates + i) & 0x7f); + } + + return; +} + +#ifdef DOT11_N_SUPPORT +/* Regulatory classes in the USA */ + +typedef struct +{ + UCHAR regclass; /* regulatory class */ + UCHAR spacing; /* 0: 20Mhz, 1: 40Mhz */ + UCHAR channelset[16]; /* max 15 channels, use 0 as terminator */ +} REG_CLASS; + +REG_CLASS reg_class[] = +{ + { 1, 0, {36, 40, 44, 48, 0}}, + { 2, 0, {52, 56, 60, 64, 0}}, + { 3, 0, {149, 153, 157, 161, 0}}, + { 4, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}}, + { 5, 0, {165, 0}}, + { 22, 1, {36, 44, 0}}, + { 23, 1, {52, 60, 0}}, + { 24, 1, {100, 108, 116, 124, 132, 0}}, + { 25, 1, {149, 157, 0}}, + { 26, 1, {149, 157, 0}}, + { 27, 1, {40, 48, 0}}, + { 28, 1, {56, 64, 0}}, + { 29, 1, {104, 112, 120, 128, 136, 0}}, + { 30, 1, {153, 161, 0}}, + { 31, 1, {153, 161, 0}}, + { 32, 1, {1, 2, 3, 4, 5, 6, 7, 0}}, + { 33, 1, {5, 6, 7, 8, 9, 10, 11, 0}}, + { 0, 0, {0}} /* end */ +}; + + +UCHAR get_regulatory_class(RTMP_ADAPTER *pAd) +{ + int i=0; + UCHAR regclass = 0; + + do + { +#ifdef CUSTOMER_DCC_FEATURE + if (reg_class[i].spacing == pAd->CommonCfg.RegTransmitSetting.field.BW) +#else + if (reg_class[i].spacing == pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth) +#endif + { + int j=0; + + do + { + if (reg_class[i].channelset[j] == pAd->CommonCfg.Channel) + { + regclass = reg_class[i].regclass; + break; + } + j++; + } while (reg_class[i].channelset[j] != 0); + } + i++; + } while (reg_class[i].regclass != 0); + + ASSERT(regclass); + + return regclass; +} + + +void build_ext_channel_switch_ie( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE) +{ + + pIE->ID = IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT; + pIE->Length = 4; + pIE->ChannelSwitchMode = 1; /*no further frames */ + pIE->NewRegClass = get_regulatory_class(pAd); + pIE->NewChannelNum = pAd->CommonCfg.Channel; +#ifdef CUSTOMER_DCC_FEATURE + if (pAd->CommonCfg.channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) + pIE->ChannelSwitchCount = pAd->CommonCfg.channelSwitch.CHSWPeriod - pAd->CommonCfg.channelSwitch.CHSWCount; + else +#endif + pIE->ChannelSwitchCount = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); +} + +#ifdef CUSTOMER_DCC_FEATURE +void build_ext_channel_switch_ie_New( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE*pIE) +{ + pIE->ID = IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT; + pIE->Length = 4; + pIE->ChannelSwitchMode = 1; /*no further frames */ + pIE->NewRegClass = get_regulatory_class(pAd); + pIE->NewChannelNum = pAd->CommonCfg.Channel; + pIE->ChannelSwitchCount = pAd->CommonCfg.channelSwitch.CHSWPeriod - pAd->CommonCfg.channelSwitch.CHSWCount; +} +#endif +#endif /* DOT11_N_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wds.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wds.c new file mode 100644 index 000000000..7849e9629 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wds.c @@ -0,0 +1,1580 @@ + +/* + *************************************************************************** + * 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 + ------ ---------- ---------------------------------------------- +*/ + +#ifdef WDS_SUPPORT + +#include "rt_config.h" + + +#define VAILD_KEY_INDEX( _X ) ((((_X) >= 0) && ((_X) < 4)) ? (TRUE) : (FALSE)) + + +INT ApWdsAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR idx; + INT allowed = FALSE; + + if (!wdev) + return FALSE; + + for (idx = 0; idx < MAX_WDS_ENTRY; idx++) + { + if (ValidWdsEntry(pAd, idx) && + (wdev == (&pAd->WdsTab.WdsEntry[idx].wdev))) + { + RTMP_SET_PACKET_NET_DEVICE_WDS(pPacket, idx); + *pWcid = (UCHAR)pAd->WdsTab.WdsEntry[idx].MacTabMatchWCID; + allowed = TRUE; + + break; + } + } + + return allowed; +} + + +LONG WdsEntryAlloc(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + INT i; + LONG WdsTabIdx = -1; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + if ((pAd->WdsTab.Mode >= WDS_LAZY_MODE) && !WDS_IF_UP_CHECK(pAd, i)) + continue; + + if (pAd->WdsTab.WdsEntry[i].Valid == FALSE) + { + pAd->WdsTab.WdsEntry[i].Valid = TRUE; + pAd->WdsTab.Size ++; + COPY_MAC_ADDR(pAd->WdsTab.WdsEntry[i].PeerWdsAddr, pAddr); + WdsTabIdx = i; + break; + } + else if (MAC_ADDR_EQUAL(pAd->WdsTab.WdsEntry[i].PeerWdsAddr, pAddr)) + { + WdsTabIdx = i; + break; + } + } + NdisReleaseSpinLock(&pAd->WdsTabLock); + + if (i == MAX_WDS_ENTRY) + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to allocate WdsEntry.\n", __FUNCTION__)); + + return WdsTabIdx; +} + + +VOID WdsEntryDel(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + INT i; + + /* delete one WDS entry */ + NdisAcquireSpinLock(&pAd->WdsTabLock); + + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + if (MAC_ADDR_EQUAL(pAddr, pAd->WdsTab.WdsEntry[i].PeerWdsAddr) + && (pAd->WdsTab.WdsEntry[i].Valid == TRUE)) + { + pAd->WdsTab.WdsEntry[i].Valid = FALSE; + NdisZeroMemory(pAd->WdsTab.WdsEntry[i].PeerWdsAddr, MAC_ADDR_LEN); + pAd->WdsTab.Size--; + break; + } + } + + NdisReleaseSpinLock(&pAd->WdsTabLock); +} + + +/* + ========================================================================== + Description: + Delete all WDS Entry in pAd->MacTab + ========================================================================== + */ +BOOLEAN MacTableDeleteWDSEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + if (wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + else + return MacTableDeleteEntry(pAd, wcid, pAddr); +} + + +/* +================================================================ +Description : because WDS and CLI share the same WCID table in ASIC. +WDS entry also insert to pAd->MacTab.content[]. +Also fills the pairwise key. +Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert WDS +from index MAX_AID_BA. +================================================================ +*/ +MAC_TABLE_ENTRY *MacTableInsertWDSEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + UINT WdsTabIdx) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + HTTRANSMIT_SETTING HTPhyMode; + RT_802_11_WDS_ENTRY *wds_entry; + struct wifi_dev *wdev; + + + /* if FULL, return */ + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + if((pEntry = WdsTableLookup(pAd, pAddr, TRUE)) != NULL) + return pEntry; + + wds_entry = &pAd->WdsTab.WdsEntry[WdsTabIdx]; + wdev = &wds_entry->wdev; + + /* allocate one WDS entry */ + do + { + /* allocate one MAC entry */ + pEntry = MacTableInsertEntry(pAd, pAddr, wdev, (WdsTabIdx + MIN_NET_DEVICE_FOR_WDS), OPMODE_AP, TRUE); + if (pEntry) + { + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + /* specific Max Tx Rate for Wds link. */ + NdisZeroMemory(&HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + switch (wdev->PhyMode) + { + case 0xff: /* user doesn't specific a Mode for WDS link. */ + case MODE_OFDM: /* specific OFDM mode. */ + HTPhyMode.field.MODE = MODE_OFDM; + HTPhyMode.field.MCS = 7; + pEntry->RateLen = 8; + break; + + case MODE_CCK: + HTPhyMode.field.MODE = MODE_CCK; + HTPhyMode.field.MCS = 3; + pEntry->RateLen = 4; + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + HTPhyMode.field.MCS = 7; + HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = wdev->HTPhyMode.field.BW; + HTPhyMode.field.STBC = wdev->HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_HTMIX; + pEntry->RateLen = 12; + break; + + case MODE_HTGREENFIELD: + HTPhyMode.field.MCS = 7; + HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = wdev->HTPhyMode.field.BW; + HTPhyMode.field.STBC = wdev->HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_HTGREENFIELD; + pEntry->RateLen = 12; + break; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + case MODE_VHT: + HTPhyMode.field.MCS = 9 ;// below case will modified it again + HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = wdev->HTPhyMode.field.BW; + HTPhyMode.field.STBC = wdev->HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_VHT; + pEntry->RateLen = 12; //seems useless + break; +#endif /* DOT11_VHT_AC */ + + default: + break; + } + + pEntry->MaxHTPhyMode.word = HTPhyMode.word; + pEntry->MinHTPhyMode.word = wdev->MinHTPhyMode.word; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + +#ifdef DOT11_N_SUPPORT + /* default */ + pEntry->MpduDensity = 5; + pEntry->MaxRAmpduFactor = 3; + + if (wdev->PhyMode >= MODE_HTMIX) + { + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-wds%d : Desired MCS = %d\n", WdsTabIdx, + wdev->DesiredTransmitSetting.field.MCS)); + + set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + } + + pEntry->MmpsMode = MMPS_DISABLE; + NdisMoveMemory(&pEntry->HTCapability, &pAd->CommonCfg.HtCapability, sizeof(HT_CAPABILITY_IE)); + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + if (pEntry->HTCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pEntry->HTCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pEntry->HTCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pEntry->HTCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pEntry->HTCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && pEntry->HTCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (pEntry->HTCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + +#ifdef DOT11_VHT_AC + //copy from update_associated_mac_entry() + if ((wdev->PhyMode == MODE_VHT) && + (pAd->CommonCfg.Channel > 14)) + { + VHT_CAP_IE vht_cap; + VHT_CAP_INFO *vht_cap_info; + build_vht_cap_ie(pAd, (UCHAR *)&vht_cap); + + vht_cap_info = (VHT_CAP_INFO *)&vht_cap; + + + pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; + if ((pEntry->MaxHTPhyMode.field.BW== BW_40) && (wdev->DesiredHtPhyInfo.vht_bw == VHT_BW_80)) + pEntry->MaxHTPhyMode.field.BW = BW_80; + + /* TODO: implement get_vht_max_mcs to get peer max MCS */ + if (vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = 8; + else + pEntry->MaxHTPhyMode.field.MCS = 9; + } else if (vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = 8; + } else if (vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = 7; + } + + if (vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + else + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 9); + } else if (vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + } else if (vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 7); + } + + + DBGPRINT(RT_DEBUG_OFF, ("%s(): Peer's PhyCap=>Mode:%s, BW:%s\n", + __FUNCTION__, + get_phymode_str(pEntry->MaxHTPhyMode.field.MODE), + get_bw_str(pEntry->MaxHTPhyMode.field.BW))); + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (vht_cap_info->rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE); + } + + if (vht_cap_info->sgi_80M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE); + + if (vht_cap_info->sgi_160M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE); + + if (pAd->CommonCfg.vht_stbc) + { + if (vht_cap_info->tx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE); + if (vht_cap_info->rx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE); + } + NdisMoveMemory(&pEntry->vht_cap_ie, &vht_cap, sizeof(VHT_CAP_IE)); + } + else + { + NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); + } + pEntry->force_op_mode = FALSE; +#endif /* DOT11_VHT_AC */ + + + + + } +#endif /* DOT11_N_SUPPORT */ + else + { + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + } + + // for now, we set this by default! + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + + /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ + if (wdev->bAutoTxRateSwitch == FALSE) + { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + else + { + pEntry->bAutoTxRateSwitch = TRUE; + } + + wds_entry->MacTabMatchWCID = (UCHAR)pEntry->wcid; + pEntry->wdev_idx = WdsTabIdx; + pEntry->wdev = wdev; + COPY_MAC_ADDR(&wdev->bssid[0], &pEntry->Addr[0]); + + AsicUpdateWdsEncryption(pAd, pEntry->wcid); + + DBGPRINT(RT_DEBUG_OFF, ("%s() - allocate entry #%d(link to WCID %d), Total= %d\n", + __FUNCTION__, WdsTabIdx, wds_entry->MacTabMatchWCID, pAd->WdsTab.Size)); + break; + } + }while(FALSE); + + return pEntry; +} + + +MAC_TABLE_ENTRY *WdsTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG WdsIndex; + MAC_TABLE_ENTRY *pCurEntry = NULL, *pEntry = NULL; + + if (wcid <=0 || wcid >= MAX_LEN_OF_MAC_TABLE ) + return NULL; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + WdsIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_WDS(pCurEntry)) + WdsIndex = pCurEntry->wdev_idx; + + if (WdsIndex == 0xff) + break; + + if (pAd->WdsTab.WdsEntry[WdsIndex].Valid != TRUE) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pCurEntry->NoDataIdleCount = 0; + pEntry = pCurEntry; + break; + } + } while(FALSE); + + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + return pEntry; +} + + +MAC_TABLE_ENTRY *WdsTableLookup(RTMP_ADAPTER *pAd, UCHAR *addr, BOOLEAN bResetIdelCount) +{ + USHORT HashIdx; + PMAC_TABLE_ENTRY pEntry = NULL; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(addr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry) + { + if (IS_ENTRY_WDS(pEntry) && MAC_ADDR_EQUAL(pEntry->Addr, addr)) + { + if(bResetIdelCount) + pEntry->NoDataIdleCount = 0; + break; + } + else + pEntry = pEntry->pNext; + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + return pEntry; +} + + +MAC_TABLE_ENTRY *FindWdsEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR *pAddr, + IN UINT32 PhyMode) +{ + MAC_TABLE_ENTRY *pEntry; + + /* lookup the match wds entry for the incoming packet. */ + pEntry = WdsTableLookupByWcid(pAd, Wcid, pAddr, TRUE); + if (pEntry == NULL) + pEntry = WdsTableLookup(pAd, pAddr, TRUE); + + /* Only Lazy mode will auto learning, match with FrDs=1 and ToDs=1 */ + if((pEntry == NULL) && (pAd->WdsTab.Mode >= WDS_LAZY_MODE)) + { + LONG WdsIdx = WdsEntryAlloc(pAd, pAddr); + if (WdsIdx >= 0) + { + /* user doesn't specific a phy mode for WDS link. */ + if (pAd->WdsTab.WdsEntry[WdsIdx].wdev.PhyMode == 0xff) + pAd->WdsTab.WdsEntry[WdsIdx].wdev.PhyMode = PhyMode; + + pEntry = MacTableInsertWDSEntry(pAd, pAddr, (UCHAR)WdsIdx); + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, + pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.ExtRate, + pAd->CommonCfg.ExtRateLen, +#ifdef DOT11_VHT_AC + sizeof(VHT_CAP_IE), + &pEntry->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); + } + else + pEntry = NULL; + } + + return pEntry; +} + + +/* + ========================================================================== + Description: + This routine is called by APMlmePeriodicExec() every second to check if + 1. any WDS client being idle for too long and should be aged-out from MAC table + ========================================================================== +*/ +VOID WdsTableMaintenance(RTMP_ADAPTER *pAd) +{ + UCHAR idx; + + if (pAd->WdsTab.Mode != WDS_LAZY_MODE) + return; + + for (idx = 0; idx < pAd->WdsTab.Size; idx++) + { + UCHAR wcid = pAd->WdsTab.WdsEntry[idx].MacTabMatchWCID; + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[wcid]; + + if(!IS_ENTRY_WDS(pEntry)) + continue; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->NoDataIdleCount ++; + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + /* delete those MAC entry that has been idle for a long time */ + if (pEntry->NoDataIdleCount >= MAC_TABLE_AGEOUT_TIME) + { + DBGPRINT(RT_DEBUG_TRACE, ("ageout %02x:%02x:%02x:%02x:%02x:%02x from WDS #%d after %d-sec silence\n", + PRINT_MAC(pEntry->Addr), idx, MAC_TABLE_AGEOUT_TIME)); + WdsEntryDel(pAd, pEntry->Addr); + MacTableDeleteWDSEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + +} + + +VOID RT28xx_WDS_Close(RTMP_ADAPTER *pAd) +{ + UINT index; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].wdev.if_dev) + RtmpOSNetDevClose(pAd->WdsTab.WdsEntry[index].wdev.if_dev); + } + return; +} + + + + +VOID WdsDown(RTMP_ADAPTER *pAd) +{ + int i; + + for (i=0; iWdsTab.WdsEntry[i].PeerWdsAddr, TRUE)) + MacTableDeleteWDSEntry(pAd, pAd->WdsTab.WdsEntry[i].MacTabMatchWCID, + pAd->WdsTab.WdsEntry[i].PeerWdsAddr); + } +} + + +VOID AsicUpdateWdsRxWCIDTable(RTMP_ADAPTER *pAd) +{ + UINT index; + MAC_TABLE_ENTRY *pEntry = NULL; + RT_802_11_WDS_ENTRY *wds_entry; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + wds_entry = &pAd->WdsTab.WdsEntry[index]; + if (wds_entry->Valid != TRUE) + continue; + + pEntry = MacTableInsertWDSEntry(pAd, wds_entry->PeerWdsAddr, index); + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, + pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.ExtRate, + pAd->CommonCfg.ExtRateLen, +#ifdef DOT11_VHT_AC + sizeof(VHT_CAP_IE), + &pEntry->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); + + switch (wds_entry->wdev.PhyMode) + { + case 0xff: /* user doesn't specific a Mode for WDS link. */ + case MODE_OFDM: /* specific OFDM mode. */ + pEntry->SupportRateMode = SUPPORT_OFDM_MODE; + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; + + case MODE_CCK: + pEntry->SupportRateMode = SUPPORT_CCK_MODE; + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + case MODE_HTGREENFIELD: + pEntry->SupportRateMode = (SUPPORT_HT_MODE | SUPPORT_OFDM_MODE); + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + case MODE_VHT: + pEntry->SupportRateMode = (SUPPORT_VHT_MODE| SUPPORT_HT_MODE | SUPPORT_OFDM_MODE); + break; +#endif /* DOT11_VHT_AC */ + + default: + break; + } + } + + return; +} + + +VOID AsicUpdateWdsEncryption(RTMP_ADAPTER *pAd, UCHAR wcid) +{ + UINT WdsIdex; + PMAC_TABLE_ENTRY pEntry = NULL; + RT_802_11_WDS_ENTRY *wds_entry; + struct wifi_dev *wdev; + + do + { + if (wcid >= MAX_LEN_OF_MAC_TABLE) + break; + + pEntry = &pAd->MacTab.Content[wcid]; + if (pAd->WdsTab.WdsEntry[pEntry->wdev_idx].Valid != TRUE) + break; + + if (!IS_ENTRY_WDS(pEntry)) + break; + + WdsIdex = pEntry->wdev_idx; + wds_entry = &pAd->WdsTab.WdsEntry[WdsIdex]; + wdev = &wds_entry->wdev; + if (((wdev->WepStatus == Ndis802_11WEPEnabled) || + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable)) + && (wds_entry->WdsKey.KeyLen > 0)) + { + + INT DefaultKeyId = 0; + + if (wdev->WepStatus == Ndis802_11WEPEnabled) + DefaultKeyId = wds_entry->KeyIdx; + + if (!VAILD_KEY_INDEX(DefaultKeyId)) + break; + + /* Update key into Asic Pairwise key table */ + RTMP_ASIC_PAIRWISE_KEY_TABLE( + pAd, + pEntry->wcid, + &wds_entry->WdsKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMP_SET_WCID_SEC_INFO( + pAd, + MAIN_MBSSID + MIN_NET_DEVICE_FOR_WDS, + DefaultKeyId, + wds_entry->WdsKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEY); + } + } while (FALSE); + + return; +} + + +VOID WdsPeerBeaconProc( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR MaxSupportedRateLen, + IN BOOLEAN bWmmCapable, + IN ULONG ClientRalinkIe, +#ifdef DOT11_VHT_AC + IN UCHAR vht_cap_len, + IN VHT_CAP_IE *vht_cap, +#endif /* DOT11_VHT_AC */ + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen) +{ + UCHAR MaxSupportedRate = RATE_11; + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + + if (pEntry && IS_ENTRY_WDS(pEntry)) + { + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + pEntry->RateLen = MaxSupportedRateLen; + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; +#ifdef BB_SOC + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; +#endif + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; +#ifdef BB_SOC + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; +#endif + } + + + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + pEntry->CapabilityInfo = CapabilityInfo; + + if (ClientRalinkIe & 0x00000004) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + } + + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && (ClientRalinkIe & 0x00000003) == 3) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + /*RTMPSetPiggyBack(pAd, TRUE); */ + + } + else if (ClientRalinkIe & 0x00000001) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + } + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + if ((pAd->CommonCfg.bPiggyBackCapable) && (ClientRalinkIe & 0x00000002) == 2) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + /*RTMPSetPiggyBack(pAd, TRUE); */ + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -PiggyBack2= 1\n")); + } + else + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + } + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) + && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ht_mode_adjust(pAd, pEntry, pHtCapability, &pAd->CommonCfg.DesiredHtPhy); + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &pAd->WdsTab.WdsEntry[pEntry->wdev_idx].wdev.DesiredHtPhyInfo.MCSSet[0], + &pHtCapability->MCSSet[0]); + + if ((pEntry->MaxHTPhyMode.field.MCS > pAd->WdsTab.WdsEntry[pEntry->wdev_idx].wdev.HTPhyMode.field.MCS) && (pAd->WdsTab.WdsEntry[pEntry->wdev_idx].wdev.HTPhyMode.field.MCS != MCS_AUTO)) + pEntry->MaxHTPhyMode.field.MCS = pAd->WdsTab.WdsEntry[pEntry->wdev_idx].wdev.HTPhyMode.field.MCS; + pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pHtCapability->ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + else + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); + + +#ifdef DOT11_VHT_AC + //copy from update_associated_mac_entry() + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + vht_cap_len ) + { + VHT_CAP_INFO *vht_cap_info = (VHT_CAP_INFO *)vht_cap; + + pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; + if ((pEntry->MaxHTPhyMode.field.BW== BW_40) && (pAd->WdsTab.WdsEntry[pEntry->wdev_idx].wdev.DesiredHtPhyInfo.vht_bw == VHT_BW_80)) + pEntry->MaxHTPhyMode.field.BW = BW_80; + + /* TODO: implement get_vht_max_mcs to get peer max MCS */ + if (vht_cap->mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = 8; + else + pEntry->MaxHTPhyMode.field.MCS = 9; + } else if (vht_cap->mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = 8; + } else if (vht_cap->mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = 7; + } + + if (vht_cap->mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + else + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 9); + } else if (vht_cap->mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + } else if (vht_cap->mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 7); + } + + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (vht_cap_info->rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE); + } + + if (vht_cap_info->sgi_80M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE); + + if (vht_cap_info->sgi_160M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE); + + if (pAd->CommonCfg.vht_stbc) + { + if (vht_cap_info->tx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE); + if (vht_cap_info->rx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE); + } + NdisMoveMemory(&pEntry->vht_cap_ie, &vht_cap, sizeof(VHT_CAP_IE)); + } + else + { + NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); + } + pEntry->force_op_mode = FALSE; +#endif /* DOT11_VHT_AC */ + + + } + else + { + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + pAd->MacTab.fAnyStationIsLegacy = TRUE; + +#ifdef DOT11_VHT_AC + NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); +#endif /* DOT11_VHT_AC */ + +#endif /* DOT11_N_SUPPORT */ + + } +#endif /* DOT11_N_SUPPORT */ + + if (bWmmCapable +#ifdef DOT11_N_SUPPORT + || (pEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) +#endif /* DOT11_N_SUPPORT */ + ) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + + pEntry->HTPhyMode.field.MODE = pEntry->MaxHTPhyMode.field.MODE; + pEntry->HTPhyMode.field.STBC = pEntry->MaxHTPhyMode.field.STBC; + pEntry->HTPhyMode.field.ShortGI = pEntry->MaxHTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.BW = pEntry->MaxHTPhyMode.field.BW; + + switch (pEntry->HTPhyMode.field.MODE) + { + case MODE_OFDM: /* specific OFDM mode. */ + pEntry->SupportRateMode = SUPPORT_OFDM_MODE; + break; + + case MODE_CCK: + pEntry->SupportRateMode = SUPPORT_CCK_MODE; + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + case MODE_HTGREENFIELD: + pEntry->SupportRateMode = (SUPPORT_HT_MODE | SUPPORT_OFDM_MODE | SUPPORT_CCK_MODE); + break; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + case MODE_VHT: + pEntry->SupportRateMode = (SUPPORT_VHT_MODE| SUPPORT_HT_MODE | SUPPORT_OFDM_MODE /*| SUPPORT_CCK_MODE*/); + break; +#endif /* DOT11_VHT_AC */ + + default: + break; + } + } +} + + +VOID APWdsInitialize(RTMP_ADAPTER *pAd) +{ + INT i; + + pAd->WdsTab.Mode = WDS_DISABLE_MODE; + pAd->WdsTab.Size = 0; + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + pAd->WdsTab.WdsEntry[i].wdev.PhyMode = 0xff; + pAd->WdsTab.WdsEntry[i].Valid = FALSE; + pAd->WdsTab.WdsEntry[i].MacTabMatchWCID = 0; + pAd->WdsTab.WdsEntry[i].wdev.WepStatus = Ndis802_11EncryptionDisabled; + pAd->WdsTab.WdsEntry[i].KeyIdx = 0; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + + pAd->WdsTab.WdsEntry[i].wdev.bAutoTxRateSwitch = TRUE; + pAd->WdsTab.WdsEntry[i].wdev.DesiredTransmitSetting.field.MCS = MCS_AUTO; + } + return; +} + + +INT Show_WdsTable_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT i; +#ifdef RTMP_MAC_PCI + UCHAR QueIdx=0; +#endif /* RTMP_MAC_PCI */ + + for(i = 0; i < MAX_WDS_ENTRY; i++) + { + DBGPRINT(RT_DEBUG_OFF, ("IF/WDS%d-%02x:%02x:%02x:%02x:%02x:%02x(%s) ,%s, KeyId=%d\n", i, + PRINT_MAC(pAd->WdsTab.WdsEntry[i].PeerWdsAddr), + pAd->WdsTab.WdsEntry[i].Valid == 1 ? "Valid" : "Invalid", + GetEncryptType(pAd->WdsTab.WdsEntry[i].wdev.WepStatus), + pAd->WdsTab.WdsEntry[i].KeyIdx)); + + if (pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen > 0) + hex_dump("Wds Key", pAd->WdsTab.WdsEntry[i].WdsKey.Key, pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen); + } + +#ifdef RTMP_MAC_PCI + for (QueIdx=0; QueIdx < NUM_OF_TX_RING; QueIdx++) + { + DBGPRINT(RT_DEBUG_OFF, ("[Tx:%d]: SwFreeIdx=%d, CpuIdx=%d, DmaIdx=%d\n", + QueIdx,pAd->TxRing[QueIdx].TxSwFreeIdx, + pAd->TxRing[QueIdx].TxCpuIdx, + pAd->TxRing[QueIdx].TxDmaIdx)); + } + DBGPRINT(RT_DEBUG_OFF, ("[Rx]: SwRedIdx=%d, CpuIdx=%d, DmaIdx=%d\n", + pAd->RxRing[0].RxSwReadIdx, + pAd->RxRing[0].RxCpuIdx, + pAd->RxRing[0].RxDmaIdx)); +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", + "MAC", "IDX", "AID", "PSM", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC")); + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_WDS(pEntry)) + { + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->Addr))); + DBGPRINT(RT_DEBUG_OFF,("%-4d", (int)pEntry->wdev_idx)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode)); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi0)); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi1)); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi2)); + DBGPRINT(RT_DEBUG_OFF, ("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW))); + +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + DBGPRINT(RT_DEBUG_OFF, ("%dS-M%-2d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf))); + else +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d\n", pEntry->HTPhyMode.field.STBC)); + +//+++Add by shiang for debug + DBGPRINT(RT_DEBUG_OFF, (" MaxCap:%-10s", get_phymode_str(pEntry->MaxHTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", get_bw_str(pEntry->MaxHTPhyMode.field.BW))); +#ifdef DOT11_VHT_AC + if (pEntry->MaxHTPhyMode.field.MODE == MODE_VHT) + DBGPRINT(RT_DEBUG_OFF, ("%dS-M%d", ((pEntry->MaxHTPhyMode.field.MCS>>4) + 1), (pEntry->MaxHTPhyMode.field.MCS & 0xf))); + else +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->MaxHTPhyMode.field.MCS)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->MaxHTPhyMode.field.ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d\n", pEntry->MaxHTPhyMode.field.STBC)); +//---Add by shiang for debug + } + } + + return TRUE; +} + + +VOID rtmp_read_wds_from_file(RTMP_ADAPTER *pAd, PSTRING tmpbuf, PSTRING buffer) +{ + PSTRING macptr; + INT i=0, j; + STRING tok_str[16]; + BOOLEAN bUsePrevFormat = FALSE; + UCHAR macAddress[MAC_ADDR_LEN]; + UCHAR keyMaterial[40]; + UCHAR KeyLen, CipherAlg = CIPHER_NONE, KeyIdx; + PRT_802_11_WDS_ENTRY pWdsEntry; + struct wifi_dev *wdev; + + + /*WdsPhyMode */ + if (RTMPGetKeyParameter("WdsPhyMode", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + if ((strncmp(macptr, "CCK", 3) == 0) || (strncmp(macptr, "cck", 3) == 0)) + wdev->PhyMode = MODE_CCK; + else if ((strncmp(macptr, "OFDM", 4) == 0) || (strncmp(macptr, "ofdm", 4) == 0)) + wdev->PhyMode = MODE_OFDM; +#ifdef DOT11_N_SUPPORT + else if ((strncmp(macptr, "HTMIX", 5) == 0) || (strncmp(macptr, "htmix", 5) == 0)) + wdev->PhyMode = MODE_HTMIX; + else if ((strncmp(macptr, "GREENFIELD", 10) == 0) || (strncmp(macptr, "greenfield", 10) == 0)) + wdev->PhyMode = MODE_HTGREENFIELD; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + else if ((strncmp(macptr, "VHT", 3) == 0) || (strncmp(macptr, "vht", 3) == 0)) + wdev->PhyMode = MODE_VHT; +#endif /* DOT11_VHT_AC */ + else + wdev->PhyMode = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - WdsPhyMode=%d\n", i, wdev->PhyMode)); + } + } + + /*WdsList */ + if (RTMPGetKeyParameter("WdsList", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + if (pAd->WdsTab.Mode != WDS_LAZY_MODE) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + continue; + if(strcmp(macptr,"00:00:00:00:00:00") == 0) + continue; + if(i >= MAX_WDS_ENTRY) + break; + + for (j=0; jWdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + + if ((strncmp(macptr, "NONE", 4) == 0) || (strncmp(macptr, "none", 4) == 0)) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0)) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0)) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0)) + wdev->WepStatus = Ndis802_11AESEnable; + else + wdev->WepStatus = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("WdsEncrypType[%d]=%d(%s)\n", + i, wdev->WepStatus, GetEncryptType(wdev->WepStatus))); + } + + /* Previous WDS only supports single encryption type. */ + /* For backward compatible, other wds link encryption type shall be the same with the first. */ + if (i == 1) + { + for (j = 1; j < MAX_WDS_ENTRY; j++) + { + wdev = &pAd->WdsTab.WdsEntry[j].wdev; + wdev->WepStatus = pAd->WdsTab.WdsEntry[0].wdev.WepStatus; + DBGPRINT(RT_DEBUG_TRACE, ("@WdsEncrypType[%d]=%d(%s)\n", + j, wdev->WepStatus, GetEncryptType(wdev->WepStatus))); + } + } + + } + /* WdsKey */ + /* This is a previous parameter and it only stores WPA key material, not WEP key */ + if (RTMPGetKeyParameter("WdsKey", tmpbuf, 255, buffer, FALSE)) + { + for (i = 0; i < MAX_WDS_ENTRY; i++) + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + + if (strlen(tmpbuf) > 0) + bUsePrevFormat = TRUE; + + wdev = &pAd->WdsTab.WdsEntry[0].wdev; + pWdsEntry = &pAd->WdsTab.WdsEntry[0]; + /* check if the wds-0 link key material is valid */ + if (((wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable)) + && (strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64)) + { + RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR)RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial); + if (wdev->WepStatus == Ndis802_11AESEnable) + pWdsEntry->WdsKey.CipherAlg = CIPHER_AES; + else + pWdsEntry->WdsKey.CipherAlg = CIPHER_TKIP; + + NdisMoveMemory(&pWdsEntry->WdsKey.Key, keyMaterial, 16); + pWdsEntry->WdsKey.KeyLen = 16; + NdisMoveMemory(&pWdsEntry->WdsKey.RxMic, keyMaterial+16, 8); + NdisMoveMemory(&pWdsEntry->WdsKey.TxMic, keyMaterial+16, 8); + } + + /* Previous WDS only supports single key-material. */ + /* For backward compatible, other wds link key-material shall be the same with the first. */ + if (pAd->WdsTab.WdsEntry[0].WdsKey.KeyLen == 16) + { + for (j = 1; j < MAX_WDS_ENTRY; j++) + { + NdisMoveMemory(&pAd->WdsTab.WdsEntry[j].WdsKey, &pAd->WdsTab.WdsEntry[0].WdsKey, sizeof(CIPHER_KEY)); + } + } + + } + + /* The parameters can provide different key information for each WDS-Link */ + /* no matter WEP or WPA */ + if (!bUsePrevFormat) + { + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + AP_WDS_KeyNameMakeUp(tok_str, sizeof(tok_str), i); + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + /* WdsXKey (X=0~MAX_WDS_ENTRY-1) */ + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + if (wdev->WepStatus == Ndis802_11WEPEnabled) + { + /* Ascii type */ + if (strlen(tmpbuf) == 5 || strlen(tmpbuf) == 13) + { + KeyLen = strlen(tmpbuf); + pWdsEntry->WdsKey.KeyLen = KeyLen; + NdisMoveMemory(pWdsEntry->WdsKey.Key, tmpbuf, KeyLen); + if (KeyLen == 5) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + pWdsEntry->WdsKey.CipherAlg = CipherAlg; + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s ,type=Ascii, CipherAlg(%s)\n", + i, tmpbuf, (CipherAlg == CIPHER_WEP64 ? "wep64" : "wep128"))); + } + /* Hex type */ + else if (strlen(tmpbuf) == 10 || strlen(tmpbuf) == 26) + { + KeyLen = strlen(tmpbuf); + pWdsEntry->WdsKey.KeyLen = KeyLen / 2; + AtoH(tmpbuf, pWdsEntry->WdsKey.Key, KeyLen / 2); + if (KeyLen == 10) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + pWdsEntry->WdsKey.CipherAlg = CipherAlg; + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s ,type=Hex, CipherAlg(%s)\n", + i, tmpbuf, (CipherAlg == CIPHER_WEP64 ? "wep64" : "wep128"))); + } + /* Invalid type */ + else + { + wdev->WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pWdsEntry->WdsKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WEP, reset encryption to OPEN\n", i)); + } + } + else if ((wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable)) + { + if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64)) + { + RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR) RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial); + if (wdev->WepStatus == Ndis802_11AESEnable) + pWdsEntry->WdsKey.CipherAlg = CIPHER_AES; + else + pWdsEntry->WdsKey.CipherAlg = CIPHER_TKIP; + + NdisMoveMemory(&pWdsEntry->WdsKey.Key, keyMaterial, 16); + pWdsEntry->WdsKey.KeyLen = 16; + NdisMoveMemory(&pWdsEntry->WdsKey.RxMic, keyMaterial+16, 8); + NdisMoveMemory(&pWdsEntry->WdsKey.TxMic, keyMaterial+16, 8); + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s, CipherAlg(%s)\n", i, tmpbuf, (CipherAlg == CIPHER_AES ? "AES" : "TKIP"))); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WPA, reset encryption to OPEN\n", i)); + wdev->WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pWdsEntry->WdsKey, sizeof(CIPHER_KEY)); + } + + } + else + { + wdev->WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pWdsEntry->WdsKey, sizeof(CIPHER_KEY)); + } + } + } + } + + /* WdsDefaultKeyID */ + if(RTMPGetKeyParameter("WdsDefaultKeyID", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + + KeyIdx = (UCHAR) simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pWdsEntry->KeyIdx = (UCHAR) (KeyIdx - 1); + else + pWdsEntry->KeyIdx = 0; + + if ((wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable)) + pWdsEntry->KeyIdx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d - WdsDefaultKeyID(0~3)=%d\n", + i, pWdsEntry->KeyIdx)); + } + } + + /* WdsTxMode */ + if (RTMPGetKeyParameter("WdsTxMode", tmpbuf, 25, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->WdsTab.WdsEntry[i].wdev; + + wdev->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(macptr); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx Mode = %d\n", i, + wdev->DesiredTransmitSetting.field.FixedTxMode)); + } + } + + /* WdsTxMcs */ + if (RTMPGetKeyParameter("WdsTxMcs", tmpbuf, 50, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->WdsTab.WdsEntry[i].wdev; + + wdev->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(macptr, &wdev->bAutoTxRateSwitch); + + if (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx MCS = AUTO\n", i)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx MCS = %d\n", i, + wdev->DesiredTransmitSetting.field.MCS)); + } + } + } + + /*WdsEnable */ + if(RTMPGetKeyParameter("WdsEnable", tmpbuf, 10, buffer, TRUE)) + { + RT_802_11_WDS_ENTRY *pWdsEntry; + switch(simple_strtol(tmpbuf, 0, 10)) + { + case WDS_BRIDGE_MODE: /* Bridge mode, DisAllow association(stop Beacon generation and Probe Req. */ + pAd->WdsTab.Mode = WDS_BRIDGE_MODE; + break; + case WDS_RESTRICT_MODE: + case WDS_REPEATER_MODE: /* Repeater mode */ + pAd->WdsTab.Mode = WDS_REPEATER_MODE; + break; + case WDS_LAZY_MODE: /* Lazy mode, Auto learn wds entry by same SSID, channel, security policy */ + for(i = 0; i < MAX_WDS_ENTRY; i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + if (pWdsEntry->Valid) + WdsEntryDel(pAd, pWdsEntry->PeerWdsAddr); + + /* When Lazy mode is enabled, the all wds-link shall share the same encryption type and key material */ + if (i > 0) + { + pWdsEntry->wdev.WepStatus = pAd->WdsTab.WdsEntry[0].wdev.WepStatus; + pWdsEntry->KeyIdx = pAd->WdsTab.WdsEntry[0].KeyIdx; + NdisMoveMemory(&pWdsEntry->WdsKey, &pAd->WdsTab.WdsEntry[0].WdsKey, sizeof(CIPHER_KEY)); + } + } + pAd->WdsTab.Mode = WDS_LAZY_MODE; + break; + case WDS_DISABLE_MODE: /* Disable mode */ + default: + APWdsInitialize(pAd); + pAd->WdsTab.Mode = WDS_DISABLE_MODE; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WDS-Enable mode=%d\n", pAd->WdsTab.Mode)); + + } + +#ifdef WDS_VLAN_SUPPORT + /* WdsVlan */ + if (RTMPGetKeyParameter("WDS_VLANID", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pAd->WdsTab.WdsEntry[i].wdev.VLAN_VID = simple_strtol(macptr, 0, 10); + pAd->WdsTab.WdsEntry[i].wdev.VLAN_Priority = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - WdsVlanId=%d\n", i, pAd->WdsTab.WdsEntry[i].wdev.VLAN_VID)); + } + } +#endif /* WDS_VLAN_SUPPORT */ +} + + +VOID WdsPrepareWepKeyFromMainBss(RTMP_ADAPTER *pAd) +{ + INT i; + + /* Prepare WEP key for each wds-link if necessary */ + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + /* For WDS backward compatible, refer to the WEP key of Main BSS in WEP mode */ + if (pAd->WdsTab.WdsEntry[i].wdev.WepStatus == Ndis802_11WEPEnabled && + pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen == 0) + { + UCHAR main_bss_keyid = pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId; + + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.WepStatus == Ndis802_11WEPEnabled && + (pAd->SharedKey[MAIN_MBSSID][main_bss_keyid].KeyLen == 5 || + pAd->SharedKey[MAIN_MBSSID][main_bss_keyid].KeyLen == 13)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Duplicate IF/WDS%d wep key from main_bssid \n", (UCHAR)i)); + pAd->WdsTab.WdsEntry[i].KeyIdx = main_bss_keyid; + NdisMoveMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, &pAd->SharedKey[MAIN_MBSSID][main_bss_keyid], sizeof(CIPHER_KEY)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("No available wep key for IF/WDS%d, reset its encryption as OPEN \n", (UCHAR)i)); + pAd->WdsTab.WdsEntry[i].wdev.WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + } + } + } + +} + + +VOID WDS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ + INT index; + PNET_DEV pWdsNetDev; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_wds_init != FALSE) + return; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + UINT32 MC_RowID = 0, IoctlIF = 0; + RT_802_11_WDS_ENTRY *wds_entry; + struct wifi_dev *wdev; + 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 */ + + dev_name = get_dev_name_prefix(pAd, INT_WDS); + pWdsNetDev = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_WDS, index, sizeof(struct mt_dev_priv), dev_name); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + wds_entry = &pAd->WdsTab.WdsEntry[index]; + wdev = &wds_entry->wdev; + + if (pWdsNetDev == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (WDS)...\n")); + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("The new WDS interface MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + PRINT_MAC(pAd->MacTab.Content[wds_entry->MacTabMatchWCID].Addr))); + + NdisZeroMemory(&wds_entry->WdsCounter, sizeof(WDS_COUNTER)); + + wdev->wdev_type = WDEV_TYPE_WDS; + wdev->func_dev = wds_entry; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = pWdsNetDev; + wdev->tx_pkt_allowed = ApWdsAllowToSendPacket; + wdev->PhyMode = 0xff; + wdev->allow_data_tx = TRUE; // let tx_pkt_allowed() to check it! + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + NdisMoveMemory(&wdev->if_addr[0], &pNetDevOps->devAddr[0], MAC_ADDR_LEN); + + RTMP_OS_NETDEV_SET_PRIV(pWdsNetDev, pAd); + RTMP_OS_NETDEV_SET_WDEV(pWdsNetDev, wdev); + + 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(pWdsNetDev))); + RtmpOSNetDevFree(pWdsNetDev); + break; + } + + pNetDevOps->priv_flags = INT_WDS; + pNetDevOps->needProtcted = TRUE; + pNetDevOps->wdev = wdev; + /* Register this device */ + RtmpOSNetDevAttach(pAd->OpMode, pWdsNetDev, pNetDevOps); + } + + if (index > 0) + pAd->flg_wds_init = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Total allocated %d WDS interfaces!\n", index)); + +} + + +VOID WDS_Remove(RTMP_ADAPTER *pAd) +{ + UINT index; + struct wifi_dev *wdev; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + wdev = &pAd->WdsTab.WdsEntry[index].wdev; + if (wdev->if_dev) + { + RtmpOSNetDevProtect(1); + RtmpOSNetDevDetach(wdev->if_dev); + RtmpOSNetDevProtect(0); + rtmp_wdev_idx_unreg(pAd, wdev); + RtmpOSNetDevFree(wdev->if_dev); + + /* Clear it as NULL to prevent latter access error. */ + wdev->if_dev = NULL; + } + } +} + +BOOLEAN WDS_StatsGet(RTMP_ADAPTER *pAd, RT_CMD_STATS64 *pStats) +{ + INT WDS_apidx = 0,index; + RT_802_11_WDS_ENTRY *pWdsEntry; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].wdev.if_dev == pStats->pNetDev) + { + WDS_apidx = index; + break; + } + } + + if(index >= MAX_WDS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): can not find wds I/F\n", __FUNCTION__)); + return FALSE; + } + + pWdsEntry = &pAd->WdsTab.WdsEntry[WDS_apidx]; + + pStats->rx_bytes = pWdsEntry->WdsCounter.ReceivedByteCount.QuadPart; + pStats->tx_bytes = pWdsEntry->WdsCounter.TransmittedByteCount.QuadPart; + + pStats->rx_packets = pWdsEntry->WdsCounter.ReceivedFragmentCount; + pStats->tx_packets = pWdsEntry->WdsCounter.TransmittedFragmentCount; + + pStats->rx_errors = pWdsEntry->WdsCounter.RxErrors; + pStats->multicast = pWdsEntry->WdsCounter.MulticastReceivedFrameCount; + + return TRUE; +} + +#endif /* WDS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wds_inf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wds_inf.c new file mode 100644 index 000000000..ec37a3da6 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wds_inf.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wpa.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wpa.c new file mode 100644 index 000000000..405de78d8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/ap_wpa.c @@ -0,0 +1,1634 @@ +/* + *************************************************************************** + * 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: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Rory Chen 04-11-29 Add WPA2PSK +*/ +#include "rt_config.h" + +extern UCHAR EAPOL[]; + +/* + ========================================================================== + Description: + Port Access Control Inquiry function. Return entry's Privacy and Wpastate. + Return: + pEntry + ========================================================================== +*/ +MAC_TABLE_ENTRY *PACInquiry(RTMP_ADAPTER *pAd, UCHAR Wcid) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &(pAd->MacTab.Content[Wcid]); + + return pEntry; +} + +/* + ========================================================================== + Description: + Check sanity of multicast cipher selector in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckMcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR apidx; + struct wifi_dev *wdev; + + + ASSERT(pEntry); + ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); + + apidx = pEntry->apidx; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + pEntry->AuthMode = wdev->AuthMode; + + if (eid_ptr->Len >= 6) + { + /* WPA and WPA2 format not the same in RSN_IE */ + if (eid_ptr->Eid == IE_WPA) + { + if (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) + pEntry->AuthMode = Ndis802_11AuthModeWPA; + else if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + pEntry->AuthMode = Ndis802_11AuthModeWPAPSK; + + if (NdisEqualMemory(&eid_ptr->Octet[6], &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][6], 4)) + return TRUE; + } + else if (eid_ptr->Eid == IE_WPA2) + { + UCHAR IE_Idx = 0; + + /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + if (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) + pEntry->AuthMode = Ndis802_11AuthModeWPA2; + else if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + pEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + + if (NdisEqualMemory(&eid_ptr->Octet[2], &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][2], 4)) + return TRUE; + } + } + + return FALSE; +} + +/* + ========================================================================== + Description: + Check sanity of unicast cipher selector in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckUcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pStaTmp; + USHORT Count; + UCHAR apidx; + struct wifi_dev *wdev; + + ASSERT(pEntry); + ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); + + apidx = pEntry->apidx; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + pEntry->WepStatus = wdev->WepStatus; + + if (eid_ptr->Len < 16) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : the length is too short(%d) \n", eid_ptr->Len)); + return FALSE; + } + + /* Store STA RSN_IE capability */ + pStaTmp = (PUCHAR)&eid_ptr->Octet[0]; + if(eid_ptr->Eid == IE_WPA2) + { + /* skip Version(2),Multicast cipter(4) 2+4==6 */ + /* point to number of unicast */ + pStaTmp +=6; + } + else if (eid_ptr->Eid == IE_WPA) + { + /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ + /* point to number of unicast */ + pStaTmp += 10; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : invalid IE=%d\n", eid_ptr->Eid)); + return FALSE; + } + + /* Store unicast cipher count */ + NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + + /* pointer to unicast cipher */ + pStaTmp += sizeof(USHORT); + + if (eid_ptr->Len >= 16) + { + if (eid_ptr->Eid == IE_WPA) + { + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + {/* multiple cipher (TKIP/CCMP) */ + + while (Count > 0) + { + /* TKIP */ + if (MIX_CIPHER_WPA_TKIP_ON(wdev->WpaMixPairCipher)) + { + /* Compare if peer STA uses the TKIP as its unicast cipher */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + { + pEntry->WepStatus = Ndis802_11TKIPEnable; + return TRUE; + } + + /* Our AP uses the AES as the secondary cipher */ + /* Compare if the peer STA use AES as its unicast cipher */ + if (MIX_CIPHER_WPA_AES_ON(wdev->WpaMixPairCipher)) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + } + else + { + /* AES */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + + pStaTmp += 4; + Count--; + } + } + else + {/* single cipher */ + while (Count > 0) + { + if (RTMPEqualMemory(pStaTmp , &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + } + else if (eid_ptr->Eid == IE_WPA2) + { + UCHAR IE_Idx = 0; + + /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + {/* multiple cipher (TKIP/CCMP) */ + + while (Count > 0) + { + /* WPA2 TKIP */ + if (MIX_CIPHER_WPA2_TKIP_ON(wdev->WpaMixPairCipher)) + { + /* Compare if peer STA uses the TKIP as its unicast cipher */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + { + pEntry->WepStatus = Ndis802_11TKIPEnable; + return TRUE; + } + + /* Our AP uses the AES as the secondary cipher */ + /* Compare if the peer STA use AES as its unicast cipher */ + if (MIX_CIPHER_WPA2_AES_ON(wdev->WpaMixPairCipher)) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + } + else + { + /* AES */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + + pStaTmp += 4; + Count--; + } + } + else + {/* single cipher */ + while (Count > 0) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + } + } + + return FALSE; +} + + +/* + ========================================================================== + Description: + Check invalidity of authentication method selection in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckAKM(PUCHAR sta_akm, PUCHAR ap_rsn_ie, INT iswpa2) +{ + PUCHAR pTmp; + USHORT Count; + + pTmp = ap_rsn_ie; + + if(iswpa2) + /* skip Version(2),Multicast cipter(4) 2+4==6 */ + pTmp +=6; + else + /*skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ + pTmp += 10;/*point to number of unicast */ + + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT);/*pointer to unicast cipher */ + + /* Skip all unicast cipher suite */ + while (Count > 0) + { + /* Skip OUI */ + pTmp += 4; + Count--; + } + + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT);/*pointer to AKM cipher */ + while (Count > 0) + { + /*rtmp_hexdump(RT_DEBUG_TRACE,"MBSS WPA_IE AKM ",pTmp,4); */ + if(RTMPEqualMemory(sta_akm,pTmp,4)) + return TRUE; + else + { + pTmp += 4; + Count--; + } + } + return FALSE;/* do not match the AKM */ + +} + + +/* + ========================================================================== + Description: + Check sanity of authentication method selector in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckAUTH( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pStaTmp; + USHORT Count; + UCHAR apidx; + + ASSERT(pEntry); + ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); + + apidx = pEntry->apidx; + + if (eid_ptr->Len < 16) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> WPAIE len is too short(%d) \n", eid_ptr->Len)); + return FALSE; + } + + /* Store STA RSN_IE capability */ + pStaTmp = (PUCHAR)&eid_ptr->Octet[0]; + if(eid_ptr->Eid == IE_WPA2) + { + /* skip Version(2),Multicast cipter(4) 2+4==6 */ + /* point to number of unicast */ + pStaTmp +=6; + } + else if (eid_ptr->Eid == IE_WPA) + { + /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ + /* point to number of unicast */ + pStaTmp += 10; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> Unknown WPAIE, WPAIE=%d\n", eid_ptr->Eid)); + return FALSE; + } + + /* Store unicast cipher count */ + NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + /* pointer to unicast cipher */ + pStaTmp += sizeof(USHORT); + + /* Skip all unicast cipher suite */ + while (Count > 0) + { + /* Skip OUI */ + pStaTmp += 4; + Count--; + } + + /* Store AKM count */ + NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + /*pointer to AKM cipher */ + pStaTmp += sizeof(USHORT); + + if (eid_ptr->Len >= 16) + { + if (eid_ptr->Eid == IE_WPA) + { + while (Count > 0) + { + if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0],0)) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + else if (eid_ptr->Eid == IE_WPA2) + { + UCHAR IE_Idx = 0; + + /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ + if ((pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + while (Count > 0) + { + if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][0],1)) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + } + + return FALSE; +} + +/* + ========================================================================== + Description: + Check validity of the received RSNIE. + + Return: + status code + ========================================================================== +*/ +UINT APValidateRSNIE( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pRsnIe, + IN UCHAR rsnie_len) +{ + UINT StatusCode = MLME_SUCCESS; + PEID_STRUCT eid_ptr; + INT apidx; + PMULTISSID_STRUCT pMbss; + + if (rsnie_len == 0) + return MLME_SUCCESS; + + eid_ptr = (PEID_STRUCT)pRsnIe; + if ((eid_ptr->Len + 2) != rsnie_len) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : the len is invalid !!!\n")); + return MLME_UNSPECIFY_FAIL; + } + + apidx = pEntry->apidx; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + +#ifdef WAPI_SUPPORT + if (eid_ptr->Eid == IE_WAPI) + return MLME_SUCCESS; +#endif /* WAPI_SUPPORT */ + + /* check group cipher */ + if (!RTMPCheckMcast(pAd, eid_ptr, pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid group cipher !!!\n")); + StatusCode = MLME_INVALID_GROUP_CIPHER; + } + /* Check pairwise cipher */ + else if (!RTMPCheckUcast(pAd, eid_ptr, pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid pairwise cipher !!!\n")); + StatusCode = MLME_INVALID_PAIRWISE_CIPHER; + } + /* Check AKM */ + else if (!RTMPCheckAUTH(pAd, eid_ptr, pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid AKM !!!\n")); + StatusCode = MLME_INVALID_AKMP; + } +#ifdef DOT11W_PMF_SUPPORT + else if (PMF_RsnCapableValidation(pAd, pRsnIe, rsnie_len, + pMbss->PmfCfg.MFPC, pMbss->PmfCfg.MFPR, pEntry) != PMF_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Invalid PMF Capability !!!\n", __FUNCTION__)); + StatusCode = MLME_ROBUST_MGMT_POLICY_VIOLATION; + } +#endif /* DOT11W_PMF_SUPPORT */ + + if (StatusCode != MLME_SUCCESS) + { + /* send wireless event - for RSN IE sanity check fail */ + RTMPSendWirelessEvent(pAd, IW_RSNIE_SANITY_FAIL_EVENT_FLAG, pEntry->Addr, 0, 0); + DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid status code(%d) !!!\n", __FUNCTION__, StatusCode)); + } + else + { + UCHAR CipherAlg = CIPHER_NONE; + + if (pEntry->WepStatus == Ndis802_11WEPEnabled) + CipherAlg = CIPHER_WEP64; + else if (pEntry->WepStatus == Ndis802_11TKIPEnable) + CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11AESEnable) + CipherAlg = CIPHER_AES; + DBGPRINT(RT_DEBUG_TRACE, ("%s : (AID#%d WepStatus=%s)\n", __FUNCTION__, pEntry->Aid, CipherName[CipherAlg])); + } + + + + return StatusCode; + +} + +/* + ========================================================================== + Description: + Function to handle countermeasures active attack. Init 60-sec timer if necessary. + Return: + ========================================================================== +*/ +VOID HandleCounterMeasure(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + INT i; + BOOLEAN Cancelled; + + if (!pEntry) + return; + + /* Todo by AlbertY - Not support currently in ApClient-link */ + if (IS_ENTRY_APCLI(pEntry)) + return; + + /* if entry not set key done, ignore this RX MIC ERROR */ + if ((pEntry->WpaState < AS_PTKINITDONE) || (pEntry->GTKState != REKEY_ESTABLISHED)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("HandleCounterMeasure ===> \n")); + + /* record which entry causes this MIC error, if this entry sends disauth/disassoc, AP doesn't need to log the CM */ + pEntry->CMTimerRunning = TRUE; + pAd->ApCfg.MICFailureCounter++; + + /* send wireless event - for MIC error */ + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0); + + if (pAd->ApCfg.CMTimerRunning == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive CM Attack Twice within 60 seconds ====>>> \n")); + + /* send wireless event - for counter measures */ + RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pEntry->Addr, 0, 0); + ApLogEvent(pAd, pEntry->Addr, EVENT_COUNTER_M); + + /* renew GTK */ + GenRandom(pAd, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, pAd->ApCfg.MBSSID[pEntry->apidx].GNonce); + + /* Cancel CounterMeasure Timer */ + RTMPCancelTimer(&pAd->ApCfg.CounterMeasureTimer, &Cancelled); + pAd->ApCfg.CMTimerRunning = FALSE; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + /* happened twice within 60 sec, AP SENDS disaccociate all associated STAs. All STA's transition to State 2 */ + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i])) + { + MlmeDeAuthAction(pAd, &pAd->MacTab.Content[i], REASON_MIC_FAILURE, FALSE); + } + } + + /* + Further, ban all Class 3 DATA transportation for a period 0f 60 sec + disallow new association , too + */ + pAd->ApCfg.BANClass3Data = TRUE; + + /* check how many entry left... should be zero */ + /*pAd->ApCfg.MBSSID[pEntry->apidx].GKeyDoneStations = pAd->MacTab.Size; */ + /*DBGPRINT(RT_DEBUG_TRACE, ("GKeyDoneStations=%d \n", pAd->ApCfg.MBSSID[pEntry->apidx].GKeyDoneStations)); */ + } + + RTMPSetTimer(&pAd->ApCfg.CounterMeasureTimer, 60 * MLME_TASK_EXEC_INTV * MLME_TASK_EXEC_MULTIPLE); + pAd->ApCfg.CMTimerRunning = TRUE; + pAd->ApCfg.PrevaMICFailTime = pAd->ApCfg.aMICFailTime; + RTMP_GetCurrentSystemTime(&pAd->ApCfg.aMICFailTime); +} + + +/* + ========================================================================== + Description: + countermeasures active attack timer execution + Return: + ========================================================================== +*/ +VOID CMTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UINT i,j=0; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + + pAd->ApCfg.BANClass3Data = FALSE; + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) + && (pAd->MacTab.Content[i].CMTimerRunning == TRUE)) + { + pAd->MacTab.Content[i].CMTimerRunning =FALSE; + j++; + } + } + + if (j > 1) + DBGPRINT(RT_DEBUG_ERROR, ("Find more than one entry which generated MIC Fail .. \n")); + + pAd->ApCfg.CMTimerRunning = FALSE; +} + + +VOID WPARetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + + if ((pEntry) && IS_ENTRY_CLIENT(pEntry)) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + pEntry->ReTryCounter++; + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec---> ReTryCounter=%d, WpaState=%d \n", pEntry->ReTryCounter, pEntry->WpaState)); + + switch (pEntry->AuthMode) + { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + /* 1. GTK already retried, give up and disconnect client. */ + if (pEntry->ReTryCounter > (GROUP_MSG1_RETRY_TIMER_CTR + 3)) + { + /* send wireless event - for group key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_GROUP_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::Group Key HS exceed retry count, Disassociate client, pEntry->ReTryCounter %d\n", pEntry->ReTryCounter)); + MlmeDeAuthAction(pAd, pEntry, REASON_GROUP_KEY_HS_TIMEOUT, FALSE); + } + /* 2. Retry GTK. */ + else if (pEntry->ReTryCounter > GROUP_MSG1_RETRY_TIMER_CTR) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry 2-way group-key Handshake \n")); + if (pEntry->GTKState == REKEY_NEGOTIATING) + { + WPAStart2WayGroupHS(pAd, pEntry); + } + } + /* 3. 4-way message 3 retried more than three times. Disconnect client */ + else if (pEntry->ReTryCounter > (PEER_MSG3_RETRY_TIMER_CTR + 3)) + { + /* send wireless event - for pairwise key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::MSG3 timeout, pEntry->ReTryCounter = %d\n", pEntry->ReTryCounter)); + MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE); + + } + /* 4. Retry 4 way message 3 */ + else if (pEntry->ReTryCounter >= PEER_MSG3_RETRY_TIMER_CTR) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry MSG3 of 4-way Handshake\n")); + WPAPairMsg3Retry(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + /* 5. 4-way message 1 retried more than three times. Disconnect client */ + else if (pEntry->ReTryCounter > (PEER_MSG1_RETRY_TIMER_CTR + 3)) + { + /* send wireless event - for pairwise key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::MSG1 timeout, pEntry->ReTryCounter = %d\n", pEntry->ReTryCounter)); + MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE); + } + /* 6. Retry 4 way message 1, the last try, the timeout is 3 sec for EAPOL-Start */ + else if (pEntry->ReTryCounter == (PEER_MSG1_RETRY_TIMER_CTR + 3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::Retry MSG1, the last try\n")); + WPAStart4WayHS(pAd , pEntry, PEER_MSG3_RETRY_EXEC_INTV); + } + /* 7. Retry 4 way message 1 */ + else if (pEntry->ReTryCounter < (PEER_MSG1_RETRY_TIMER_CTR + 3)) + { + if ((pEntry->WpaState == AS_PTKSTART) || (pEntry->WpaState == AS_INITPSK) || (pEntry->WpaState == AS_INITPMK)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry MSG1 of 4-way Handshake\n")); + WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } + break; + + default: + break; + } + } +#ifdef APCLI_SUPPORT + else if ((pEntry) && IS_ENTRY_APCLI(pEntry)) + { + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) + { + PRTMP_ADAPTER pAd __maybe_unused = (PRTMP_ADAPTER)pEntry->pAd; + + if (pEntry->wdev_idx < MAX_APCLI_NUM) + { +#ifdef MAC_REPEATER_SUPPORT + UCHAR ifIndex = pEntry->wdev_idx; + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex)); + if ((pEntry->bReptCli) && (pAd->ApCfg.bMACRepeaterEn == TRUE)) + ifIndex = (64 + ifIndex*MAX_EXT_MAC_ADDR_SIZE + pEntry->MatchReptCliIdx); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if ( (pAd->ApCfg.bMACRepeaterEn == TRUE) && (pEntry->bReptCli)) + { + + RTMPRemoveRepeaterDisconnectEntry(pAd, pEntry->wdev_idx, pEntry->MatchReptCliIdx); + RTMPRemoveRepeaterEntry(pAd, pEntry->wdev_idx, pEntry->MatchReptCliIdx); + } + else + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); +#endif /* MAC_REPEATER_SUPPORT */ + } + } + } +#endif /* APCLI_SUPPORT */ +} + + +/* + ========================================================================== + Description: + Timer execution function for periodically updating group key. + Return: + ========================================================================== +*/ +VOID GREKEYPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UINT i, apidx; + ULONG temp_counter = 0; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + MULTISSID_STRUCT *pMbss = NULL; + struct wifi_dev *wdev; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (&pAd->ApCfg.MBSSID[apidx].REKEYTimer == pTimer) + break; + } + + if (apidx == pAd->ApCfg.BssidNum) + return; + else + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + wdev = &pMbss->wdev; + if (wdev->AuthMode < Ndis802_11AuthModeWPA || + wdev->AuthMode > Ndis802_11AuthModeWPA1PSKWPA2PSK) + return; + + if ((pMbss->WPAREKEY.ReKeyMethod == TIME_REKEY) && (pMbss->REKEYCOUNTER < 0xffffffff)) + temp_counter = (++pMbss->REKEYCOUNTER); + /* REKEYCOUNTER is incremented every MCAST packets transmitted, */ + /* But the unit of Rekeyinterval is 1K packets */ + else if (pMbss->WPAREKEY.ReKeyMethod == PKT_REKEY) + temp_counter = pMbss->REKEYCOUNTER/1000; + else + { + return; + } + + if (temp_counter > (pMbss->WPAREKEY.ReKeyInterval)) + { + pMbss->REKEYCOUNTER = 0; + pMbss->RekeyCountDown = 3; + DBGPRINT(RT_DEBUG_TRACE, ("Rekey Interval Excess, GKeyDoneStations=%d\n", pMbss->StaCount)); + + /* take turn updating different groupkey index, */ + if ((pMbss->StaCount) > 0) + { + /* change key index */ + wdev->DefaultKeyId = (wdev->DefaultKeyId == 1) ? 2 : 1; + + /* Generate GNonce randomly */ + GenRandom(pAd, wdev->bssid, pMbss->GNonce); + + /* Update GTK */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + wdev->bssid, pMbss->GTK, LEN_TKIP_GTK); + + /* Process 2-way handshaking */ + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && + (pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->apidx == apidx)) + { +#ifdef MWDS + if(IS_MWDS_OPMODE_AP(pEntry)) + continue; +#endif /* MWDS */ + + pEntry->GTKState = REKEY_NEGOTIATING; + +#ifdef DROP_MASK_SUPPORT + /* Disable Drop Mask */ + drop_mask_set_per_client(pAd, pEntry, FALSE); +#endif /* DROP_MASK_SUPPORT */ + + WPAStart2WayGroupHS(pAd, pEntry); + pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + DBGPRINT(RT_DEBUG_TRACE, ("Rekey interval excess, Update Group Key for %x %x %x %x %x %x , DefaultKeyId= %x \n",\ + PRINT_MAC(pEntry->Addr), wdev->DefaultKeyId)); + } + } + } + } + + /* Use countdown to ensure the 2-way handshaking had completed */ + if (pMbss->RekeyCountDown > 0) + { + pMbss->RekeyCountDown--; + if (pMbss->RekeyCountDown == 0) + { + USHORT Wcid; + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* Install shared key table */ + WPAInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + apidx, + wdev->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + } + } + +} + + +#ifdef DOT1X_SUPPORT +/* + ======================================================================== + + Routine Description: + Sending EAP Req. frame to station in authenticating state. + These frames come from Authenticator deamon. + + Arguments: + pAdapter Pointer to our adapter + pPacket Pointer to outgoing EAP frame body + 8023 Header + Len length of pPacket + + Return Value: + None + ======================================================================== +*/ +VOID WpaSend(RTMP_ADAPTER *pAdapter, UCHAR *pPacket, ULONG Len) +{ + PEAP_HDR pEapHdr; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR Header802_3[LENGTH_802_3]; + MAC_TABLE_ENTRY *pEntry; + PUCHAR pData; + + + NdisMoveMemory(Addr, pPacket, 6); + NdisMoveMemory(Header802_3, pPacket, LENGTH_802_3); + pEapHdr = (EAP_HDR*)(pPacket + LENGTH_802_3); + pData = (pPacket + LENGTH_802_3); + + if ((pEntry = MacTableLookup(pAdapter, Addr)) == NULL) + { + return; + } + + /* Send EAP frame to STA */ + if (((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEapHdr->ProType != EAPOLKey)) || + (pAdapter->ApCfg.MBSSID[pEntry->apidx].wdev.IEEE8021X == TRUE)) + RTMPToWirelessSta(pAdapter, + pEntry, + Header802_3, + LENGTH_802_3, + pData, + Len - LENGTH_802_3, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + + if (RTMPEqualMemory((pPacket+12), EAPOL, 2)) + { + switch (pEapHdr->code) + { + case EAP_CODE_REQUEST: + if ((pEntry->WpaState >= AS_PTKINITDONE) && (pEapHdr->ProType == EAPPacket)) + { + pEntry->WpaState = AS_AUTHENTICATION; + DBGPRINT(RT_DEBUG_TRACE, ("Start to re-authentication by 802.1x daemon\n")); + } + break; + + /* After receiving EAP_SUCCESS, trigger state machine */ + case EAP_CODE_SUCCESS: + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEapHdr->ProType != EAPOLKey)) + { + DBGPRINT(RT_DEBUG_TRACE,("Send EAP_CODE_SUCCESS\n\n")); + if (pEntry->Sst == SST_ASSOC) + { + pEntry->WpaState = AS_INITPMK; + /* Only set the expire and counters */ + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + WPAStart4WayHS(pAdapter, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } + else + { + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->WpaState = AS_PTKINITDONE; + pAdapter->ApCfg.MBSSID[pEntry->apidx].wdev.PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef WSC_AP_SUPPORT + if (pAdapter->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) + WscInformFromWPA(pEntry); +#endif /* WSC_AP_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE,("IEEE8021X-WEP : Send EAP_CODE_SUCCESS\n\n")); + } + break; + + case EAP_CODE_FAILURE: + break; + + default: + break; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Send Deauth, Reason : REASON_NO_LONGER_VALID\n")); + MlmeDeAuthAction(pAdapter, pEntry, REASON_NO_LONGER_VALID, FALSE); + } +} + + +VOID RTMPAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK) +{ + INT i, CacheIdx; + + /* Update PMKID status */ + if ((CacheIdx = RTMPSearchPMKIDCache(pAd, apidx, pAddr)) != -1) + { + NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[CacheIdx].RefreshTime)); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[CacheIdx].PMKID, PMKID, LEN_PMKID); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[CacheIdx].PMK, PMK, PMK_LEN); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPAddPMKIDCache update %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n", + PRINT_MAC(pAddr), CacheIdx, apidx)); + + return; + } + + /* Add a new PMKID */ + for (i = 0; i < MAX_PMKID_COUNT; i++) + { + if (!pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid) + { + pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid = TRUE; + NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime)); + COPY_MAC_ADDR(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].MAC, pAddr); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].PMKID, PMKID, LEN_PMKID); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].PMK, PMK, PMK_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache add %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n", + PRINT_MAC(pAddr), i, apidx)); + break; + } + } + + if (i == MAX_PMKID_COUNT) + { + ULONG timestamp = 0, idx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache(IF(%d) Cache full\n", apidx)); + for (i = 0; i < MAX_PMKID_COUNT; i++) + { + if (pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid) + { + if (((timestamp == 0) && (idx == 0)) || ((timestamp != 0) && timestamp < pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime)) + { + timestamp = pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime; + idx = i; + } + } + } + pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].Valid = TRUE; + NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].RefreshTime)); + COPY_MAC_ADDR(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].MAC, pAddr); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].PMKID, PMKID, LEN_PMKID); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].PMK, PMK, PMK_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache add %02x:%02x:%02x:%02x:%02x:%02x cache(%ld) from IF(ra%d)\n", + PRINT_MAC(pAddr), idx, apidx)); + } +} + +INT RTMPSearchPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr) +{ + INT i = 0; + + for (i = 0; i < MAX_PMKID_COUNT; i++) + { + if ((pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid) + && MAC_ADDR_EQUAL(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].MAC, pAddr)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSearchPMKIDCache %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n", + PRINT_MAC(pAddr), i, apidx)); + break; + } + } + + if (i == MAX_PMKID_COUNT) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSearchPMKIDCache - IF(%d) not found\n", apidx)); + return -1; + } + + return i; +} + +VOID RTMPDeletePMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN INT idx) +{ + PAP_BSSID_INFO pInfo = &pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx]; + + if (pInfo->Valid) + { + pInfo->Valid = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPDeletePMKIDCache(IF(%d), del PMKID CacheIdx=%d\n", apidx, idx)); + } +} + +VOID RTMPMaintainPMKIDCache( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + ULONG Now; + for (i = 0; i < MAX_MBSSID_NUM(pAd); i++) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[i]; + + for (j = 0; j < MAX_PMKID_COUNT; j++) + { + PAP_BSSID_INFO pBssInfo = &pMbss->PMKIDCache.BSSIDInfo[j]; + + NdisGetSystemUpTime(&Now); + + if ((pBssInfo->Valid) + && /*((Now - pBssInfo->RefreshTime) >= pMbss->PMKCachePeriod)*/ + (RTMP_TIME_AFTER(Now, (pBssInfo->RefreshTime + pMbss->PMKCachePeriod)))) + { + RTMPDeletePMKIDCache(pAd, i, j); + } + } + } +} +#endif /* DOT1X_SUPPORT */ + + +/* + ========================================================================== + Description: + Set group re-key timer + + Return: + + ========================================================================== +*/ +VOID WPA_APSetGroupRekeyAction( + IN PRTMP_ADAPTER pAd) +{ + UINT8 apidx = 0; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + struct wifi_dev *wdev = &pMbss->wdev; + + if ((wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) + { + /* Group rekey related */ + if ((pMbss->WPAREKEY.ReKeyInterval != 0) + && ((pMbss->WPAREKEY.ReKeyMethod == TIME_REKEY) || ( + pMbss->WPAREKEY.ReKeyMethod == PKT_REKEY))) + { + /* Regularly check the timer */ + if (pMbss->REKEYTimerRunning == FALSE) + { + RTMPSetTimer(&pMbss->REKEYTimer, GROUP_KEY_UPDATE_EXEC_INTV); + + pMbss->REKEYTimerRunning = TRUE; + pMbss->REKEYCOUNTER = 0; + } + DBGPRINT(RT_DEBUG_TRACE, (" %s : Group rekey method= %ld , interval = 0x%lx\n", + __FUNCTION__, pMbss->WPAREKEY.ReKeyMethod, + pMbss->WPAREKEY.ReKeyInterval)); + } + else + pMbss->REKEYTimerRunning = FALSE; + } + } +} + +#ifdef QOS_DLS_SUPPORT +VOID RTMPHandleSTAKey( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + extern UCHAR OUI_WPA2_WEP40[]; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pOutPacket; + PEAPOL_PACKET pSTAKey; + PHEADER_802_11 pHeader; + UCHAR Offset = 0; + ULONG MICMsgLen; + UCHAR DA[MAC_ADDR_LEN]; + UCHAR Key_Data[512]; + UCHAR key_length; + UCHAR mic[LEN_KEY_DESC_MIC]; + UCHAR rcv_mic[LEN_KEY_DESC_MIC]; + UCHAR digest[80]; + UCHAR temp[64]; + PMAC_TABLE_ENTRY pDaEntry; + + /*Benson add for big-endian 20081016--> */ + KEY_INFO peerKeyInfo; + /*Benson add 20081016 <-- */ + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleSTAKey\n")); + + if (!pEntry) + return; + + if ((pEntry->WpaState != AS_PTKINITDONE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here")); + return; + } + + pHeader = (PHEADER_802_11) Elem->Msg; + + /* QoS control field (2B) is took off */ +/* if (pHeader->FC.SubType & 0x08) */ +/* Offset += 2; */ + + pSTAKey = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + Offset]; + /*Benson add for big-endian 20081016--> */ + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pSTAKey->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); + /*Benson add 20081016 <-- */ + + /* Check Replay Counter */ + if (!RTMPEqualMemory(pSTAKey->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in STAKey handshake!! \n")); + DBGPRINT(RT_DEBUG_ERROR, ("Receive : %d %d %d %d \n", + pSTAKey->KeyDesc.ReplayCounter[0], + pSTAKey->KeyDesc.ReplayCounter[1], + pSTAKey->KeyDesc.ReplayCounter[2], + pSTAKey->KeyDesc.ReplayCounter[3])); + DBGPRINT(RT_DEBUG_ERROR, ("Current : %d %d %d %d \n", + pEntry->R_Counter[4],pEntry->R_Counter[5], + pEntry->R_Counter[6],pEntry->R_Counter[7])); + return; + } + + /* Check MIC, if not valid, discard silently */ + NdisMoveMemory(DA, &pSTAKey->KeyDesc.KeyData[6], MAC_ADDR_LEN); + + if (peerKeyInfo.KeyMic && peerKeyInfo.Secure && peerKeyInfo.Request)/*Benson add for big-endian 20081016 --> */ + { + pEntry->bDlsInit = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("STAKey Initiator: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + } + + + MICMsgLen = pSTAKey->Body_Len[1] | ((pSTAKey->Body_Len[0]<<8) && 0xff00); + MICMsgLen += LENGTH_EAPOL_H; + if (MICMsgLen > (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive wrong format EAPOL packets \n")); + return; + } + + /* This is proprietary DLS protocol, it will be adhered when spec. is finished. */ + NdisZeroMemory(temp, 64); + NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, sizeof(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK)); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + + WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, temp, + pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK); + DBGPRINT(RT_DEBUG_TRACE, ("PTK-%x %x %x %x %x %x %x %x \n", + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7])); + + + /* Record the received MIC for check later */ + NdisMoveMemory(rcv_mic, pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + { + RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, mic, MD5_DIGEST_SIZE); + } + else + { + RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + + if (!RTMPEqualMemory(rcv_mic, mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in STAKey handshake!! \n")); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in STAKey handshake!! \n")); + + /* Receive init STA's STAKey Message-2, and terminate the handshake */ + /*if (pEntry->bDlsInit && !pSTAKey->KeyDesc.KeyInfo.Request) */ + if (pEntry->bDlsInit && !peerKeyInfo.Request) /*Benson add for big-endian 20081016 --> */ + { + pEntry->bDlsInit = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Receive init STA's STAKey Message-2, STAKey handshake finished \n")); + return; + } + + /* Receive init STA's STAKey Message-2, and terminate the handshake */ + if (RTMPEqualMemory(&pSTAKey->KeyDesc.KeyData[2], OUI_WPA2_WEP40, 3)) + { + DBGPRINT(RT_DEBUG_WARN, ("Receive a STAKey message which not support currently, just drop it \n")); + return; + } + + do + { + pDaEntry = MacTableLookup(pAd, DA); + if (!pDaEntry) + break; + + if ((pDaEntry->WpaState != AS_PTKINITDONE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here \n")); + break; + } + + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /* allocate memory */ + if(pOutBuffer == NULL) + break; + + MAKE_802_3_HEADER(Header802_3, pDaEntry->Addr, pAd->ApCfg.MBSSID[pDaEntry->apidx].wdev.bssid, EAPOL); + + /* Increment replay counter by 1 */ + ADD_ONE_To_64BIT_VAR(pDaEntry->R_Counter); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pOutPacket = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pOutPacket, TX_EAPOL_BUFFER); + + /* 0. init Packet and Fill header */ + pOutPacket->ProVer = EAPOL_VER; + pOutPacket->ProType = EAPOLKey; + pOutPacket->Body_Len[1] = 0x5f; + + /* 1. Fill replay counter */ +/* NdisMoveMemory(pDaEntry->R_Counter, pAd->ApCfg.R_Counter, sizeof(pDaEntry->R_Counter)); */ + NdisMoveMemory(pOutPacket->KeyDesc.ReplayCounter, pDaEntry->R_Counter, LEN_KEY_DESC_REPLAY); + + /* 2. Fill key version, keyinfo, key len */ + pOutPacket->KeyDesc.KeyInfo.KeyDescVer= GROUP_KEY; + pOutPacket->KeyDesc.KeyInfo.KeyType = GROUPKEY; + pOutPacket->KeyDesc.KeyInfo.Install = 1; + pOutPacket->KeyDesc.KeyInfo.KeyAck = 1; + pOutPacket->KeyDesc.KeyInfo.KeyMic = 1; + pOutPacket->KeyDesc.KeyInfo.Secure = 1; + pOutPacket->KeyDesc.KeyInfo.EKD_DL = 1; + DBGPRINT(RT_DEBUG_TRACE, ("STAKey handshake for peer STA %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(DA))); + + if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pOutPacket->KeyDesc.Type = WPA1_KEY_DESC; + + DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA/WPAPSK\n")); + } + else if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pOutPacket->KeyDesc.Type = WPA2_KEY_DESC; + pOutPacket->KeyDesc.KeyDataLen[1] = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA2/WPA2PSK\n")); + } + + pOutPacket->KeyDesc.KeyLength[1] = LEN_TKIP_TK; + pOutPacket->KeyDesc.KeyDataLen[1] = LEN_TKIP_TK; + pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_TKIP; + if (pDaEntry->WepStatus == Ndis802_11AESEnable) + { + pOutPacket->KeyDesc.KeyLength[1] = LEN_AES_TK; + pOutPacket->KeyDesc.KeyDataLen[1] = LEN_AES_TK; + pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_AES; + } + + /* Key Data Encapsulation format, use Ralink OUI to distinguish proprietary and standard. */ + Key_Data[0] = 0xDD; + Key_Data[1] = 0x00; /* Length (This field will be filled later) */ + Key_Data[2] = 0x00; /* OUI */ + Key_Data[3] = 0x0C; /* OUI */ + Key_Data[4] = 0x43; /* OUI */ + Key_Data[5] = 0x02; /* Data Type (STAKey Key Data Encryption) */ + + /* STAKey Data Encapsulation format */ + Key_Data[6] = 0x00; /*Reserved */ + Key_Data[7] = 0x00; /*Reserved */ + + /* STAKey MAC address */ + NdisMoveMemory(&Key_Data[8], pEntry->Addr, MAC_ADDR_LEN); /* initiator MAC address */ + + /* STAKey (Handle the difference between TKIP and AES-CCMP) */ + if (pDaEntry->WepStatus == Ndis802_11AESEnable) + { + Key_Data[1] = 0x1E; /* 4+2+6+16(OUI+Reserved+STAKey_MAC_Addr+STAKey) */ + NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_AES_TK); + } + else + { + Key_Data[1] = 0x2E; /* 4+2+6+32(OUI+Reserved+STAKey_MAC_Addr+STAKey) */ + NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_TK); + NdisMoveMemory(&Key_Data[14+LEN_TK], pEntry->PairwiseKey.TxMic, LEN_TKIP_MIC); + NdisMoveMemory(&Key_Data[14+LEN_TK+LEN_TKIP_MIC], pEntry->PairwiseKey.RxMic, LEN_TKIP_MIC); + } + + key_length = Key_Data[1]; + pOutPacket->Body_Len[1] = key_length + 0x5f; + + /* This is proprietary DLS protocol, it will be adhered when spec. is finished. */ + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, temp, DA, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK); + + DBGPRINT(RT_DEBUG_TRACE, ("PTK-0-%x %x %x %x %x %x %x %x \n", + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6], + pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7])); + + NdisMoveMemory(pOutPacket->KeyDesc.KeyData, Key_Data, key_length); + NdisZeroMemory(mic, sizeof(mic)); + + *(USHORT *)(&pOutPacket->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pOutPacket->KeyDesc.KeyInfo)); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + pOutPacket->Body_Len[1] + 4, pOutPacket, + END_OF_ARGS); + + /* Calculate MIC */ + if (pDaEntry->WepStatus == Ndis802_11AESEnable) + { + RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); + } + else + { + RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, mic, MD5_DIGEST_SIZE); + NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); + } + + RTMPToWirelessSta(pAd, pDaEntry, Header802_3, LENGTH_802_3, (PUCHAR)pOutPacket, pOutPacket->Body_Len[1] + 4, FALSE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(NULL, mpool); + }while(FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleSTAKey: FrameLen=%ld\n", FrameLen)); +} +#endif /* QOS_DLS_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT +/*for sending an event to notify hostapd about michael failure. */ +VOID ieee80211_notify_michael_failure( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN UINT keyix, + IN INT report) +{ + static const char *tag = "MLME-MICHAELMICFAILURE.indication"; +/* struct net_device *dev = pAd->net_dev; */ +/* union iwreq_data wrqu; */ + char buf[128]; /* XXX */ + + + /* TODO: needed parameters: count, keyid, key type, src address, TSC */ + if(report)/*station reports a mic error to this ap. */ + { + snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag, + keyix, "uni", + ether_sprintf(pHeader->Addr2)); + } + else/*ap itself receives a mic error. */ + { + snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag, + keyix, IEEE80211_IS_MULTICAST(pHeader->Addr1) ? "broad" : "uni", + ether_sprintf(pHeader->Addr2)); + } + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, -1, NULL, NULL, 0); +/* NdisZeroMemory(&wrqu, sizeof(wrqu)); */ +/* wrqu.data.length = strlen(buf); */ +/* wireless_send_event(dev, RT_WLAN_EVENT_CUSTOM, &wrqu, buf); */ +} + + +const CHAR* ether_sprintf(const UINT8 *mac) +{ + static char etherbuf[18]; + snprintf(etherbuf,sizeof(etherbuf),"%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac)); + return etherbuf; +} +#endif /* HOSTAPD_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT +VOID ApcliWpaSendEapolStart( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN PMAC_TABLE_ENTRY pMacEntry, + IN PAPCLI_STRUCT pApCliEntry) +{ + IEEE8021X_FRAME Packet; + UCHAR Header802_3[14]; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> ApCliWpaSendEapolStart\n")); + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + MAKE_802_3_HEADER(Header802_3, pBssid, &pApCliEntry->wdev.if_addr[0], EAPOL); + + // Zero message 2 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.Version = EAPOL_VER; + Packet.Type = EAPOLStart; + Packet.Length = cpu2be16(0); + + // Copy frame to Tx ring + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)&Packet, 4, TRUE); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaSendEapolStart\n")); +} +#endif /* WPA_SUPPLICANT_SUPPORT */ +VOID ApCliRTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey, + IN INT ifIndex) +{ + ULONG Now; + UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); + PAPCLI_STRUCT pApCliEntry = NULL; + DBGPRINT(RT_DEBUG_TRACE, (" ApCliRTMPReportMicError <---\n")); + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + /* Record Last MIC error time and count */ + NdisGetSystemUpTime(&Now); + if (pAd->ApCfg.ApCliTab[ifIndex].MicErrCnt == 0) + { + pAd->ApCfg.ApCliTab[ifIndex].MicErrCnt++; + pAd->ApCfg.ApCliTab[ifIndex].LastMicErrorTime = Now; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ReplayCounter, 8); + } + else if (pAd->ApCfg.ApCliTab[ifIndex].MicErrCnt == 1) + { + if ((pAd->ApCfg.ApCliTab[ifIndex].LastMicErrorTime + (60 * OS_HZ)) < Now) + { + /* Update Last MIC error time, this did not violate two MIC errors within 60 seconds */ + pAd->ApCfg.ApCliTab[ifIndex].LastMicErrorTime = Now; + } + else + { + + /* RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); */ + + pAd->ApCfg.ApCliTab[ifIndex].LastMicErrorTime = Now; + /* Violate MIC error counts, MIC countermeasures kicks in */ + pAd->ApCfg.ApCliTab[ifIndex].MicErrCnt++; + /* + We shall block all reception + We shall clean all Tx ring and disassoicate from AP after next EAPOL frame + + No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets + if pAd->StaCfg.MicErrCnt greater than 2. + */ + } + } + else + { + /* MIC error count >= 2 */ + /* This should not happen */ + ; + } + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_MIC_FAILURE_REPORT_FRAME, 1, &unicastKey, ifIndex); + + if (pAd->ApCfg.ApCliTab[ifIndex].MicErrCnt == 2) + { + DBGPRINT(RT_DEBUG_TRACE, (" MIC Error count = 2 Trigger Block timer....\n")); + DBGPRINT(RT_DEBUG_TRACE, (" pAd->ApCfg.ApCliTab[%d].LastMicErrorTime = %ld\n",ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].LastMicErrorTime)); + + RTMPSetTimer(&pApCliEntry->MlmeAux.WpaDisassocAndBlockAssocTimer, 100); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliRTMPReportMicError --->\n")); + +} +VOID ApCliWpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + PAPCLI_STRUCT pApCliEntry; + + pAd->ApCfg.ApCliTab[0].bBlockAssoc = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) disassociate with current AP after sending second continuous EAPOL frame.\n", __FUNCTION__)); + + + pApCliEntry = &pAd->ApCfg.ApCliTab[0]; + + DisassocParmFill(pAd, &DisassocReq, pApCliEntry->MlmeAux.Bssid, REASON_MIC_FAILURE); + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + + pApCliEntry->MicErrCnt = 0; +} +#endif/*APCLI_SUPPORT*/ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_assoc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_assoc.c new file mode 100644 index 000000000..d435077c5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_assoc.c @@ -0,0 +1,1213 @@ +/* + *************************************************************************** + * 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_assoc.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2006-6-23 modified for rt61-APClinent +*/ + +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + +static VOID ApCliAssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef MAC_REPEATER_SUPPORT +static VOID ApCliAssocTimeoutExt( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* MAC_REPEATER_SUPPORT */ + +static VOID ApCliMlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliAssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliAssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT IfIndex, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +DECLARE_TIMER_FUNCTION(ApCliAssocTimeout); +BUILD_TIMER_FUNCTION(ApCliAssocTimeout); +#ifdef MAC_REPEATER_SUPPORT +DECLARE_TIMER_FUNCTION(ApCliAssocTimeoutExt); +BUILD_TIMER_FUNCTION(ApCliAssocTimeoutExt); +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + ========================================================================== + */ +VOID ApCliAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; +#ifdef MAC_REPEATER_SUPPORT + UCHAR j; +#endif /* MAC_REPEATER_SUPPORT */ + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, + APCLI_MAX_ASSOC_STATE, APCLI_MAX_ASSOC_MSG, + (STATE_MACHINE_FUNC)Drop, APCLI_ASSOC_IDLE, + APCLI_ASSOC_MACHINE_BASE); + + /* first column */ + StateMachineSetAction(S, APCLI_ASSOC_IDLE, APCLI_MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)ApCliMlmeAssocReqAction); + StateMachineSetAction(S, APCLI_ASSOC_IDLE, APCLI_MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDisassocReqAction); + StateMachineSetAction(S, APCLI_ASSOC_IDLE, APCLI_MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliPeerDisassocAction); + + /* second column */ + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenAssoc); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenDisassociate); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliPeerDisassocAction); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)ApCliPeerAssocRspAction); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ApCliAssocTimeoutAction); + + for (i=0; i < MAX_APCLI_NUM; i++) + { + pAd->ApCfg.ApCliTab[i].AssocCurrState = APCLI_ASSOC_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ApCliAssocTimer, + GET_TIMER_FUNCTION(ApCliAssocTimeout), pAd, FALSE); + + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.WpaDisassocAndBlockAssocTimer, + GET_TIMER_FUNCTION(ApCliWpaDisassocApAndBlockAssoc), 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].AssocCurrState = APCLI_ASSOC_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].RepeaterCli[j].ApCliAssocTimer, + GET_TIMER_FUNCTION(ApCliAssocTimeoutExt), &pAd->ApCfg.ApCliTab[i].RepeaterCli[j], FALSE); + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + return; +} + +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID ApCliAssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - enqueue APCLI_MT2_ASSOC_TIMEOUT \n")); + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_ASSOC_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + + return; +} + +#ifdef MAC_REPEATER_SUPPORT +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID ApCliAssocTimeoutExt( + 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 ASSOC - enqueue APCLI_MT2_ASSOC_TIMEOUT\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_ASSOC_STATE_MACHINE, APCLI_MT2_ASSOC_TIMEOUT, 0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + + return; +} +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + Description: + mlme assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored in the config + -# SSID + -# supported rates and their length + Post : + -# An association request frame is generated and sent to the air + -# Association timer starts + -# Association state -> ASSOC_WAIT_RSP + + ========================================================================== + */ +static VOID ApCliMlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + NDIS_STATUS NStatus; + BOOLEAN Cancelled; + UCHAR ApAddr[6]; + HEADER_802_11 AssocHdr; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT ListenIntv; + ULONG Timeout; + USHORT CapabilityInfo; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG tmp; + UCHAR SsidIe = IE_SSID; + UCHAR SupRateIe = IE_SUPP_RATES; + UCHAR ExtRateIe = IE_EXT_SUPP_RATES; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef WPA_SUPPLICANT_SUPPORT + USHORT VarIesOffset = 0; +#endif /* WPA_SUPPLICANT_SUPPORT */ + UCHAR RSNIe = IE_WPA; + APCLI_STRUCT *apcli_entry; + struct wifi_dev *wdev; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + UCHAR PhyMode = pAd->CommonCfg.PhyMode; + + 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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = wdev->PhyMode; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + /* Block all authentication request durning WPA block period */ + if (apcli_entry->bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Block Auth request durning WPA block period!\n")); + *pCurrState = APCLI_ASSOC_IDLE; + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + //RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, &Cancelled); +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPCancelTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, &Cancelled); + + /* allocate and send out AssocRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeAssocReqAction() allocate memory failed \n")); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Send ASSOC request...\n")); + ApCliMgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr, ifIndex); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(AssocHdr.Addr2, apcli_entry->RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &apcli_entry->MlmeAux.SsidLen, + apcli_entry->MlmeAux.SsidLen, apcli_entry->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &apcli_entry->MlmeAux.SupRateLen, + apcli_entry->MlmeAux.SupRateLen, apcli_entry->MlmeAux.SupRate, + END_OF_ARGS); + + if(apcli_entry->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &apcli_entry->MlmeAux.ExtRateLen, + apcli_entry->MlmeAux.ExtRateLen, apcli_entry->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + /* HT */ + if ((apcli_entry->MlmeAux.HtCapabilityLen > 0) && + WMODE_CAP_N(PhyMode)) + { + ULONG TmpLen; + HT_CAPABILITY_IE HtCapabilityTmp; + + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &apcli_entry->MlmeAux.HtCapability, apcli_entry->MlmeAux.HtCapabilityLen); +#ifdef DOT11N_SS3_SUPPORT + HtCapabilityTmp.MCSSet[2] = (apcli_entry->MlmeAux.HtCapability.MCSSet[2] & apcli_entry->RxMcsSet[2]); +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef RT_BIG_ENDIAN + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* RT_BIG_ENDINA */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &apcli_entry->MlmeAux.HtCapabilityLen, + apcli_entry->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (apcli_entry->MlmeAux.vht_cap_len)) + { + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_ASSOC_REQ); + } +#endif /* DOT11_VHT_AC */ + } + +#ifdef DOT11N_DRAFT3 + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen; + + extInfoLen = sizeof (EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef APCLI_CERT_SUPPORT + if ((pAd->CommonCfg.bBssCoexEnable == TRUE) && + (PhyMode >= PHY_11ABGN_MIXED) + && (pAd->CommonCfg.Channel <= 14) + && (pAd->bApCliCertTest == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + DBGPRINT(RT_DEBUG_TRACE, ("%s: BssCoexistMgmtSupport = 1\n", __FUNCTION__)); + } +#endif /* APCLI_CERT_SUPPORT */ +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14)) + extCapInfo.operating_mode_notification = 1; +#endif /* DOT11_VHT_AC */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef AGGREGATION_SUPPORT + /* + add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION + Case I: (Aggregation + Piggy-Back) + 1. user enable aggregation, AND + 2. Mac support piggy-back + 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON + Case II: (Aggregation) + 1. user enable aggregation, AND + 2. AP annouces it's AGGREGATION-capable in BEACON + */ + if (pAd->CommonCfg.bAggregationCapable) + { +#ifdef PIGGYBACK_SUPPORT + if ((pAd->CommonCfg.bPiggyBackCapable) && ((apcli_entry->MlmeAux.APRalinkIe & 0x00000003) == 3)) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } else +#endif /* PIGGYBACK_SUPPORT */ + if (apcli_entry->MlmeAux.APRalinkIe & 0x00000001) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* AGGREGATION_SUPPORT */ + + if (apcli_entry->MlmeAux.APEdcaParm.bValid) + { + if (apcli_entry->UapsdInfo.bAPSDCapable && + apcli_entry->MlmeAux.APEdcaParm.bAPSDCapable) + { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR)&QosInfo; + } + else + { + /* The Parameter Set Count is set to 0 in the association request frames */ + /* WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); */ + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + apcli_entry->ReqVarIELen = 0; + NdisZeroMemory(apcli_entry->ReqVarIEs, MAX_VIE_LEN); + + if ((apcli_entry->wpa_supplicant_info.WpaSupplicantUP & 0x7F ) == WPA_SUPPLICANT_ENABLE) + { + DBGPRINT(RT_DEBUG_TRACE,("%s:: APCLI WPA_ASSOC_IE FROM SUPPLICANT\n", __FUNCTION__)); + ULONG TmpWpaAssocIeLen = 0; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpWpaAssocIeLen, + apcli_entry->wpa_supplicant_info.WpaAssocIeLen, apcli_entry->wpa_supplicant_info.pWpaAssocIe, + END_OF_ARGS); + + FrameLen += TmpWpaAssocIeLen; + + VarIesOffset = 0; + NdisMoveMemory(apcli_entry->ReqVarIEs + VarIesOffset, + apcli_entry->wpa_supplicant_info.pWpaAssocIe, apcli_entry->wpa_supplicant_info.WpaAssocIeLen); + VarIesOffset += apcli_entry->wpa_supplicant_info.WpaAssocIeLen; + + // Set Variable IEs Length + apcli_entry->ReqVarIELen = VarIesOffset; + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + /* Append RSN_IE when WPAPSK OR WPA2PSK, */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) +#ifdef WPA_SUPPLICANT_SUPPORT + || (wdev->AuthMode >= Ndis802_11AuthModeWPA) +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WSC_AP_SUPPORT + && ((apcli_entry->WscControl.WscConfMode == WSC_DISABLE) + || ((apcli_entry->WscControl.WscConfMode != WSC_DISABLE) + && !(apcli_entry->WscControl.bWscTrigger))) +#endif /* WSC_AP_SUPPORT */ + ) + { + RSNIe = IE_WPA; + + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + ||(wdev->AuthMode == Ndis802_11AuthModeWPA2) +#endif /* WPA_SUPPLICANT_SUPPORT */ + ) + RSNIe = IE_WPA2; + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (wdev->AuthMode == Ndis802_11AuthModeWPA2) + { + INT idx; + BOOLEAN FoundPMK = FALSE; + /* Search chched PMKID, append it if existed */ + for (idx = 0; idx < PMKID_NO; idx++) + { + if (NdisEqualMemory(ApAddr, &apcli_entry->SavedPMK[idx].BSSID, 6)) + { + FoundPMK = TRUE; + break; + } + } + + /* + When AuthMode is WPA2-Enterprise and AP reboot or STA lost AP, + AP would not do PMK cache with STA after STA re-connect to AP again. + In this case, driver doesn't need to send PMKID to AP and WpaSupplicant. + */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory(pAd->MlmeAux.Bssid, pAd->CommonCfg.LastBssid, MAC_ADDR_LEN))) + { + FoundPMK = FALSE; + } + + if (FoundPMK) + { + // Set PMK number + *(PUSHORT) &apcli_entry->RSN_IE[apcli_entry->RSNIE_Len] = 1; + NdisMoveMemory(&apcli_entry->RSN_IE[apcli_entry->RSNIE_Len + 2], &apcli_entry->SavedPMK[idx].PMKID, 16); + apcli_entry->RSNIE_Len += 18; + } + } + +#ifdef SIOCSIWGENIE + if ((apcli_entry->wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) && + (apcli_entry->wpa_supplicant_info.bRSN_IE_FromWpaSupplicant == TRUE)) + { + ; + } + else +#endif +#endif /* WPA_SUPPLICANT_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &apcli_entry->RSNIE_Len, + apcli_entry->RSNIE_Len, apcli_entry->RSN_IE, + END_OF_ARGS); + + FrameLen += tmp; + } +#ifdef WSC_AP_SUPPORT + /* Add WSC IE if we are connecting to WSC AP */ + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + BOOLEAN bHasWscIe = TRUE; + +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg.bSupportHiddenWPS) + bHasWscIe = FALSE; +#endif /* SMART_MESH_HIDDEN_WPS */ + if(bHasWscIe) + { + os_alloc_mem(pAd, (UCHAR **) & pWscBuf, 512); + if (pWscBuf != NULL) { + NdisZeroMemory(pWscBuf, 512); + WscBuildAssocReqIE(&pAd->ApCfg.ApCliTab[ifIndex].WscControl, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(pOutBuffer + FrameLen, + &WscTmpLen, WscIeLen, pWscBuf,END_OF_ARGS); + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN,("%s:: WscBuf Allocate failed!\n",__FUNCTION__)); + } + } +#endif /* WSC_AP_SUPPORT */ + +#ifdef SMART_MESH + SMART_MESH_INSERT_IE(apcli_entry->SmartMeshCfg, + pOutBuffer, + FrameLen, + SM_IE_ASSOC_REQ); +#endif /* SMART_MESH */ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPSetTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAssocTimer, Timeout); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPSetTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, Timeout); + *pCurrState = APCLI_ASSOC_WAIT_RSP; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + + return; +} + +/* + ========================================================================== + Description: + Upper layer issues disassoc request + Parameters: + Elem - + ========================================================================== + */ +static VOID ApCliMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_DISASSOC_REQ_STRUCT pDisassocReq; + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + 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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + /* skip sanity check */ + pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); + + /* allocate and send out DeassocReq frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeDisassocReqAction() allocate memory failed\n")); + *pCurrState = APCLI_ASSOC_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_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Send DISASSOC request [BSSID::%02x:%02x:%02x:%02x:%02x:%02x] \n", + pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2], + pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5])); + ApCliMgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr, ifIndex); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(DisassocHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &pDisassocReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_SUCCESS; + +#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_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + /*send disassociate event to wpa_supplicant*/ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); + } + RtmpOSWrielessEventSend(pAd->net_dev, SIOCGIWAP, -1, NULL, NULL, 0); + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, NULL, BSS0, 0); +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + RT_CFG80211_LOST_GO_INFORM(pAd); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + return; +} + + +/* + ========================================================================== + Description: + peer sends assoc rsp back + Parameters: + Elme - MLME message containing the received frame + ========================================================================== + */ +static VOID ApCliPeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + USHORT CapabilityInfo, Status, Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + EDCA_PARM EdcaParm; + UCHAR CkipFlag; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *pCurrState = NULL; + PAPCLI_STRUCT pApCliEntry = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + IE_LISTS *ie_list = NULL; + UCHAR PhyMode = pAd->CommonCfg.PhyMode; + + 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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = pApCliEntry->wdev.PhyMode; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(IE_LISTS)); + if (ie_list == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("%s():mem alloc failed!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory((UCHAR *)ie_list, sizeof(IE_LISTS)); + + if (ApCliPeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability, &AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag, ie_list)) + { + /* The frame is for me ? */ + if(MAC_ADDR_EQUAL(Addr2, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* Store the AssocRsp Frame to wpa_supplicant via CFG80211 */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ResVarIEs, MAX_VIE_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ResVarIELen = 0; + + PFRAME_802_11 pFrame = (PFRAME_802_11) (Elem->Msg); + pAd->ApCfg.ApCliTab[ifIndex].ResVarIELen = Elem->MsgLen - 6 - sizeof (HEADER_802_11); + NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].ResVarIEs, &pFrame->Octet[6], pAd->ApCfg.ApCliTab[ifIndex].ResVarIELen); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAssocTimer, &Cancelled); + if(Status == MLME_SUCCESS) + { + /* go to procedure listed on page 376 */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + ApCliAssocPostProc(pAd, Addr2, CapabilityInfo, ifIndex, SupRate, SupRateLen, + ExtRate, ExtRateLen, &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); + pAd->ApCfg.ApCliTab[0].MlmeAux.Aid = Aid; + +#ifdef DOT11_VHT_AC + RTMPZeroMemory(&pApCliEntry->MlmeAux.vht_cap, sizeof(VHT_CAP_IE)); + RTMPZeroMemory(&pApCliEntry->MlmeAux.vht_op, sizeof(VHT_OP_IE)); + pApCliEntry->MlmeAux.vht_cap_len = 0; + pApCliEntry->MlmeAux.vht_op_len = 0; + if (WMODE_CAP_AC(PhyMode) && ie_list->vht_cap_len && ie_list->vht_op_len) + { + DBGPRINT(RT_DEBUG_TRACE, ("There is vht le at Assoc Rsp ifIndex=%d vht_cap_len=%d\n", ifIndex,ie_list->vht_cap_len)); + NdisMoveMemory(&pApCliEntry->MlmeAux.vht_cap, &(ie_list->vht_cap), ie_list->vht_cap_len); + pApCliEntry->MlmeAux.vht_cap_len = ie_list->vht_cap_len; + NdisMoveMemory(&pApCliEntry->MlmeAux.vht_op, &(ie_list->vht_op), ie_list->vht_op_len); + pApCliEntry->MlmeAux.vht_op_len = ie_list->vht_op_len; + } +#endif /* DOT11_VHT_AC */ + } + + ApCliCtrlMsg.Status = MLME_SUCCESS; +#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_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else + { + ApCliCtrlMsg.Status = Status; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + + *pCurrState = APCLI_ASSOC_IDLE; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliPeerAssocRspAction() sanity check fail\n")); + } + + if (ie_list) + os_free_mem(pAd, ie_list); + + return; +} + +/* + ========================================================================== + Description: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + ========================================================================== + */ +static VOID ApCliPeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + +#ifdef MAC_REPEATER_SUPPORT + DBGPRINT(RT_DEBUG_WARN, (" (%s) ifIndex = %d, CliIdx = %d !!!\n", __FUNCTION__, ifIndex, CliIdx)); +#endif /* MAC_REPEATER_SUPPORT */ + + if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, Addr2)) + { + *pCurrState = APCLI_ASSOC_IDLE; + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && (CliIdx != 0xFF)) + { +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID); +#endif /* DOT11_N_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_ASSOC - ApCliPeerDisassocAction() sanity check fail\n")); + } + + return; +} + +/* + ========================================================================== + Description: + what the state machine will do after assoc timeout + ========================================================================== + */ +static VOID ApCliAssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliAssocTimeoutAction\n")); + + 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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + *pCurrState = APCLI_ASSOC_IDLE; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_REQ_TIMEOUT, 0, NULL, ifIndex); + + return; +} + +static VOID ApCliInvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN 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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliInvalidStateWhenAssoc(state=%ld), reset APCLI_ASSOC state machine\n", *pCurrState)); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; +} + +static VOID ApCliInvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *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].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - InvalidStateWhenApCliDisassoc(state=%ld), reset APCLI_ASSOC state machine\n", *pCurrState)); + *pCurrState = APCLI_ASSOC_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_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + procedures on IEEE 802.11/1999 p.376 + Parametrs: + ========================================================================== + */ +static VOID ApCliAssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT IfIndex, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ + APCLI_STRUCT *pApCliEntry = NULL; + UCHAR PhyMode = pAd->CommonCfg.PhyMode; + + if (IfIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = pApCliEntry->wdev.PhyMode; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + pApCliEntry->MlmeAux.BssType = BSS_INFRA; + pApCliEntry->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + NdisMoveMemory(&pApCliEntry->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + + /* filter out un-supported rates */ + pApCliEntry->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.SupRate, &(pApCliEntry->MlmeAux.SupRateLen)); + + /* filter out un-supported rates */ + pApCliEntry->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.ExtRate, &(pApCliEntry->MlmeAux.ExtRateLen)); + + DBGPRINT(RT_DEBUG_TRACE, (HtCapabilityLen ? "%s===> 11n HT STA\n" : "%s===> legacy STA\n", __FUNCTION__)); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0 && WMODE_CAP_N(PhyMode)) + ApCliCheckHt(pAd, IfIndex, pHtCapability, pAddHtInfo); +#endif /* DOT11_N_SUPPORT */ + +} + +#ifdef WPA_SUPPLICANT_SUPPORT +VOID ApcliSendAssocIEsToWpaSupplicant( + IN RTMP_ADAPTER *pAd, + IN UINT ifIndex) +{ + STRING custom[IW_CUSTOM_MAX] = {0}; + + if ((pAd->ApCfg.ApCliTab[ifIndex].ReqVarIELen + 17) <= IW_CUSTOM_MAX) + { + sprintf(custom, "ASSOCINFO_ReqIEs="); + NdisMoveMemory(custom+17, pAd->ApCfg.ApCliTab[ifIndex].ReqVarIEs, pAd->ApCfg.ApCliTab[ifIndex].ReqVarIELen); + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_REQIE_EVENT_FLAG, NULL, (PUCHAR)custom, pAd->ApCfg.ApCliTab[ifIndex].ReqVarIELen + 17); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_ASSOCINFO_EVENT_FLAG, NULL, NULL, 0); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.ApCliTab[%d].ReqVarIELen + 17 > MAX_CUSTOM_LEN\n",ifIndex)); + + return; +} +#endif /*WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_auth.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_auth.c new file mode 100644 index 000000000..17fbcc17f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_auth.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_ctrl.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_ctrl.c new file mode 100644 index 000000000..ec3d9ca58 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_ctrl.c @@ -0,0 +1,2095 @@ +/* + *************************************************************************** + * 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_ctrl.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2006-06-23 modified for rt61-APClinent +*/ +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + + +static VOID ApCliCtrlJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlJoinReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlProbeRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlAuthRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlAuth2RspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlAuthReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlAuth2ReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlDeAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlAssocReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlDisconnectReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlPeerDeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlDeAssocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliCtrlDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliWpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef APCLI_CERT_SUPPORT +static VOID ApCliCtrlScanDoneAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* APCLI_CERT_SUPPORT */ + +#ifdef APCLI_CONNECTION_TRIAL +static VOID ApCliCtrlTrialConnectAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliTrialConnectTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID ApCliTrialConnectPhase2Timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID ApCliTrialConnectRetryTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +DECLARE_TIMER_FUNCTION(ApCliTrialConnectTimeout); +BUILD_TIMER_FUNCTION(ApCliTrialConnectTimeout); +DECLARE_TIMER_FUNCTION(ApCliTrialConnectPhase2Timeout); +BUILD_TIMER_FUNCTION(ApCliTrialConnectPhase2Timeout); +DECLARE_TIMER_FUNCTION(ApCliTrialConnectRetryTimeout); +BUILD_TIMER_FUNCTION(ApCliTrialConnectRetryTimeout); +#endif /* APCLI_CONNECTION_TRIAL */ + +/* + ========================================================================== + Description: + The apcli ctrl state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ +VOID ApCliCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; +#ifdef MAC_REPEATER_SUPPORT + UCHAR j; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef APCLI_CONNECTION_TRIAL + PAPCLI_STRUCT pApCliEntry; +#endif /* APCLI_CONNECTION_TRIAL */ + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, + APCLI_MAX_CTRL_STATE, APCLI_MAX_CTRL_MSG, + (STATE_MACHINE_FUNC)Drop, APCLI_CTRL_DISCONNECTED, + APCLI_CTRL_MACHINE_BASE); + + /* disconnected state */ + StateMachineSetAction(Sm, APCLI_CTRL_DISCONNECTED, APCLI_CTRL_JOIN_REQ, (STATE_MACHINE_FUNC)ApCliCtrlJoinReqAction); + + /* probe state */ + StateMachineSetAction(Sm, APCLI_CTRL_PROBE, APCLI_CTRL_PROBE_RSP, (STATE_MACHINE_FUNC)ApCliCtrlProbeRspAction); + StateMachineSetAction(Sm, APCLI_CTRL_PROBE, APCLI_CTRL_JOIN_REQ_TIMEOUT, (STATE_MACHINE_FUNC)ApCliCtrlJoinReqTimeoutAction); + StateMachineSetAction(Sm, APCLI_CTRL_PROBE, APCLI_CTRL_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); + + /* auth state */ + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_AUTH_RSP, (STATE_MACHINE_FUNC)ApCliCtrlAuthRspAction); + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_AUTH_REQ_TIMEOUT, (STATE_MACHINE_FUNC)ApCliCtrlAuthReqTimeoutAction); + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_PEER_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlPeerDeAssocReqAction); + + /* auth2 state */ + StateMachineSetAction(Sm, APCLI_CTRL_AUTH_2, APCLI_CTRL_AUTH_RSP, (STATE_MACHINE_FUNC)ApCliCtrlAuth2RspAction); + StateMachineSetAction(Sm, APCLI_CTRL_AUTH_2, APCLI_CTRL_AUTH_REQ_TIMEOUT, (STATE_MACHINE_FUNC)ApCliCtrlAuth2ReqTimeoutAction); + StateMachineSetAction(Sm, APCLI_CTRL_AUTH_2, APCLI_CTRL_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); + StateMachineSetAction(Sm, APCLI_CTRL_AUTH_2, APCLI_CTRL_PEER_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlPeerDeAssocReqAction); + + /* assoc state */ + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_ASSOC_RSP, (STATE_MACHINE_FUNC)ApCliCtrlAssocRspAction); + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_ASSOC_REQ_TIMEOUT, (STATE_MACHINE_FUNC)ApCliCtrlAssocReqTimeoutAction); + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlDeAssocAction); + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_PEER_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlPeerDeAssocReqAction); + + /* deassoc state */ + StateMachineSetAction(Sm, APCLI_CTRL_DEASSOC, APCLI_CTRL_DEASSOC_RSP, (STATE_MACHINE_FUNC)ApCliCtrlDeAssocRspAction); + + /* connected state */ + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlDeAuthAction); + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_PEER_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlPeerDeAssocReqAction); + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_MT2_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliCtrlProbeRspAction); + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_MIC_FAILURE_REPORT_FRAME, (STATE_MACHINE_FUNC)ApCliWpaMicFailureReportFrame); +#ifdef APCLI_CERT_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_SCAN_DONE, (STATE_MACHINE_FUNC)ApCliCtrlScanDoneAction); +#endif /* APCLI_CERT_SUPPORT */ +#ifdef APCLI_CONNECTION_TRIAL + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_TRIAL_CONNECT, (STATE_MACHINE_FUNC)ApCliCtrlTrialConnectAction); + StateMachineSetAction(Sm, APCLI_CTRL_DISCONNECTED, APCLI_CTRL_TRIAL_CONNECT, (STATE_MACHINE_FUNC)ApCliCtrlTrialConnectAction); + StateMachineSetAction(Sm, APCLI_CTRL_TRIAL_TRIGGERED, APCLI_CTRL_JOIN_REQ_TIMEOUT, (STATE_MACHINE_FUNC)ApCliCtrlTrialConnectAction);//for retry +#endif /* APCLI_CONNECTION_TRIAL */ + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pAd->ApCfg.ApCliTab[i].CtrlCurrState = APCLI_CTRL_DISCONNECTED; + +#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].CtrlCurrState = APCLI_CTRL_DISCONNECTED; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliConnectState = 0; + } +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef APCLI_CONNECTION_TRIAL + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + /* timer init */ + + printk("woody init pApCliEntry->TrialConnectTimer\n"); + RTMPInitTimer(pAd, + &pApCliEntry->TrialConnectTimer, + GET_TIMER_FUNCTION(ApCliTrialConnectTimeout), + (PVOID)pApCliEntry, + FALSE); + + RTMPInitTimer(pAd, + &pApCliEntry->TrialConnectPhase2Timer, + GET_TIMER_FUNCTION(ApCliTrialConnectPhase2Timeout), + (PVOID)pApCliEntry, + FALSE); + + RTMPInitTimer(pAd, + &pApCliEntry->TrialConnectRetryTimer, + GET_TIMER_FUNCTION(ApCliTrialConnectRetryTimeout), + pApCliEntry, + FALSE); +#endif /* APCLI_CONNECTION_TRIAL */ + } + + return; +} + +#ifdef APCLI_CONNECTION_TRIAL +static VOID ApCliTrialConnectTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PAPCLI_STRUCT pApCliEntry = (APCLI_STRUCT *)FunctionContext; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pApCliEntry->pAd; + + UCHAR ifIndex = pApCliEntry->ifIndex; + UCHAR BBPValue; + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - TrialConnectTimeout, Jump back to original Channel\n")); + + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, TRUE); + AsicEnableBssSync(pAd);//jump back to origin channel, regenerate beacon. + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + } + + if (*pCurrState == APCLI_CTRL_ASSOC) { + //trialConnectTimeout, and currect status is ASSOC, + //it means we got Auth Resp from new root AP already, + //we shall serve the origin channel traffic first, + //and jump back to trial channel to issue Assoc Req later, + //and finish four way-handshake if need. + DBGPRINT(RT_DEBUG_TRACE, ("%s, ApCliTrialConnectTimeout APCLI_CTRL_ASSOC set TrialConnectPhase2Timer\n", __func__)); + RTMPSetTimer(&(pApCliEntry->TrialConnectPhase2Timer), TRIAL_TIMEOUT); + } + else { + //RTMPCancelTimer(&(pApCliEntry->ApCliMlmeAux.ProbeTimer), &Cancelled); + pApCliEntry->NewRootApRetryCnt++; + + if (pApCliEntry->NewRootApRetryCnt >= 10) { + DBGPRINT(RT_DEBUG_TRACE, ("%s, RetryCnt:%d, pCurrState = %d, \n", __func__, pApCliEntry->NewRootApRetryCnt, *pCurrState)); + pApCliEntry->TrialCh=0; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, MAX_LEN_OF_SSID);//cleanup CfgSsid. + pApCliEntry->CfgSsidLen = 0; + pApCliEntry->NewRootApRetryCnt = 0;//cleanup retry count + pApCliEntry->Enable = FALSE; + } + else + *pCurrState = APCLI_CTRL_DISCONNECTED;//Disconnected State will bring the next probe req, auth req. + } + + return; +} + +static VOID ApCliTrialConnectPhase2Timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PAPCLI_STRUCT pApCliEntry = (APCLI_STRUCT *)FunctionContext; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pApCliEntry->pAd; + MLME_ASSOC_REQ_STRUCT AssocReq; + UCHAR ifIndex = pApCliEntry->ifIndex; + UCHAR BBPValue; + struct wifi_dev *wdev; + wdev = &pApCliEntry->wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - %s,\n \ + Jump back to trial channel:%d\n \ + to issue Assoc Req to new root AP\n", + __func__, pApCliEntry->TrialCh)); + + if (pApCliEntry->TrialCh != pAd->CommonCfg.CentralChannel) { + /* Let BBP register at 20MHz */ + AsicDisableSync(pAd);//disable beacon + AsicSwitchChannel(pAd, pApCliEntry->TrialCh, TRUE); + //andes_switch_channel(pAd, pApCliEntry->TrialCh, 0, 0, 0x202, 0);//woody + } + ApCliLinkDown(pAd, ifIndex); + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + RTMPSetTimer(&(pApCliEntry->TrialConnectRetryTimer), 800); + else + RTMPSetTimer(&(pApCliEntry->TrialConnectRetryTimer), TRIAL_TIMEOUT); + + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[pApCliEntry->ifIndex].MlmeAux.Bssid, pAd->ApCfg.ApCliTab[pApCliEntry->ifIndex].MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, 5); + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, pApCliEntry->ifIndex); + RTMP_MLME_HANDLER(pAd); + + return; +} + +static VOID ApCliTrialConnectRetryTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PAPCLI_STRUCT pApCliEntry = (APCLI_STRUCT *)FunctionContext; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pApCliEntry->pAd; + PULONG pCurrState = &pAd->ApCfg.ApCliTab[pApCliEntry->ifIndex].CtrlCurrState; + int i; + UCHAR ifIndex = pApCliEntry->ifIndex; + UCHAR tempBuf[10] = {}; + UCHAR BBPValue; + + PMAC_TABLE_ENTRY pMacEntry; + //PMAC_TABLE_ENTRY pOldRootAp = &pApCliEntry->oldRootAP; + + pMacEntry = MacTableLookup(pAd, pApCliEntry->MlmeAux.Bssid); + //find rootAp that is under connecting if exists in mactable. + + if (pMacEntry == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("ApCli_SYNC - %s, no CfgApCliBssid in mactable!\n", __func__)); + *pCurrState = APCLI_CTRL_DISCONNECTED; + pApCliEntry->NewRootApRetryCnt++; + + if (pApCliEntry->NewRootApRetryCnt >= 10) { + DBGPRINT(RT_DEBUG_TRACE, ("%s, RetryCnt:%d, pCurrState = %d, \n", __func__, pApCliEntry->NewRootApRetryCnt, *pCurrState)); + pApCliEntry->TrialCh=0; + ApCliLinkDown(pAd, ifIndex); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, MAX_LEN_OF_SSID);//cleanup CfgSsid. + pApCliEntry->CfgSsidLen = 0; + pApCliEntry->NewRootApRetryCnt = 0;//cleanup retry count + pApCliEntry->Enable = FALSE; + } + + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, TRUE); + AsicEnableBssSync(pAd);//jump back to origin channel, regenerate beacon. + return; + } + + if ((pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED) && (*pCurrState == APCLI_CTRL_CONNECTED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - %s, new rootAP connected!!\n", __func__)); + /* connected to new ap ok, change common channel to new channel */ + + //AsicSetApCliBssid(pAd, pApCliEntry->ApCliMlmeAux.Bssid, 1); + + //MacTableDeleteEntry(pAd, pApCliEntry->MacTabWCID, APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)); + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - %s, jump back to origin channel to wait for User's operation!\n", __func__)); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, TRUE); + AsicEnableBssSync(pAd);//jump back to origin channel, regenerate beacon. + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, MAX_LEN_OF_SSID);//cleanup CfgSsid. + pApCliEntry->CfgSsidLen = 0; + pApCliEntry->NewRootApRetryCnt = 0;//cleanup retry count + pApCliEntry->Enable = FALSE; + + // sprintf(tempBuf, "%d", pApCliEntry->TrialCh); + // DBGPRINT(RT_DEBUG_TRACE, ("Follow new rootAP Switch to channel :%s\n", tempBuf)); + // Set_Channel_Proc(pAd, tempBuf);//APStartUp will regenerate beacon. + pApCliEntry->TrialCh=0; + } + else + { + /* + Apcli does not connect to new root ap successfully yet, + jump back to origin channel to serve old rootap traffic. + re-issue assoc_req to go later. + */ + //pApCliEntry->MacTabWCID = pOldRootAp->Aid; + pApCliEntry->NewRootApRetryCnt++; + + if (pApCliEntry->NewRootApRetryCnt < 10) + RTMPSetTimer(&(pApCliEntry->TrialConnectPhase2Timer), TRIAL_TIMEOUT); + else { + DBGPRINT(RT_DEBUG_TRACE, ("%s, RetryCnt:%d, pCurrState = %d, \n", __func__, pApCliEntry->NewRootApRetryCnt, *pCurrState)); + pApCliEntry->TrialCh=0; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, MAX_LEN_OF_SSID);//cleanup CfgSsid. + pApCliEntry->CfgSsidLen = 0; + pApCliEntry->NewRootApRetryCnt = 0;//cleanup retry count + pApCliEntry->Enable = FALSE; + ApCliLinkDown(pAd, ifIndex); + } + + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, TRUE); + AsicEnableBssSync(pAd);//jump back to origin channel, regenerate beacon. + } + return; +} +#endif /* APCLI_CONNECTION_TRIAL */ + +/* + ========================================================================== + Description: + APCLI MLME JOIN req state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_MLME_JOIN_REQ_STRUCT JoinReq; + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; +#ifdef WSC_AP_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[ifIndex].WscControl; +#endif /* WSC_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Start Probe Req.\n", __FUNCTION__)); + if (ifIndex >= MAX_APCLI_NUM) + return; + + if (ApScanRunning(pAd) == TRUE) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + NdisZeroMemory(&JoinReq, sizeof(APCLI_MLME_JOIN_REQ_STRUCT)); + + if (!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } + +#ifdef WSC_AP_SUPPORT + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pWpsCtrl->bWscTrigger == TRUE)) + { + ULONG bss_idx = 0; + NdisZeroMemory(JoinReq.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(JoinReq.Ssid, MAX_LEN_OF_SSID); + JoinReq.SsidLen = pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.SsidLength; + NdisMoveMemory(JoinReq.Ssid, pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.Ssid, JoinReq.SsidLen); + if (pWpsCtrl->WscMode == 1) /* PIN */ + { + bss_idx = BssSsidTableSearchBySSID(&pAd->ScanTab, (PUCHAR)(JoinReq.Ssid), JoinReq.SsidLen); + if (bss_idx == BSS_NOT_FOUND) + { + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE); + return; + } + else + { + INT old_conf_mode = pWpsCtrl->WscConfMode; + ADD_HTINFO RootApHtInfo, ApHtInfo; + UCHAR channel = pAd->CommonCfg.Channel, RootApChannel = pAd->ScanTab.BssEntry[bss_idx].Channel; + UCHAR RootApCentralChannel = pAd->ScanTab.BssEntry[bss_idx].CentralChannel; + ApHtInfo = pAd->CommonCfg.AddHTInfo.AddHtInfo; + RootApHtInfo = pAd->ScanTab.BssEntry[bss_idx].AddHtInfo.AddHtInfo; + + if ((RootApChannel != channel) || + ((RootApCentralChannel != RootApChannel) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (ApHtInfo.ExtChanOffset != RootApHtInfo.ExtChanOffset))) + { + STRING ChStr[5] = {0}; + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if (RootApHtInfo.ExtChanOffset == EXTCHA_ABOVE) + Set_HtExtcha_Proc(pAd, "1"); + else + Set_HtExtcha_Proc(pAd, "0"); + } + snprintf(ChStr, sizeof(ChStr), "%d", pAd->ScanTab.BssEntry[bss_idx].Channel); + Set_Channel_Proc(pAd, ChStr); + /* + ApStop will call WscStop, we need to reset WscConfMode, WscMode & bWscTrigger here. + */ + + pWpsCtrl->WscState = WSC_STATE_START; + pWpsCtrl->WscStatus = STATUS_WSC_START_ASSOC; + pWpsCtrl->WscMode = 1; + pWpsCtrl->WscConfMode = old_conf_mode; + pWpsCtrl->bWscTrigger = TRUE; + return; + } + } + } +#ifdef SMART_MESH + else if((pWpsCtrl->WscMode == 2) && (pWpsCtrl->bWscPBCAddrMode == TRUE)) //PBC + { + bss_idx = Get_BssSsidTableSearchByMAC(&pAd->ScanTab, pWpsCtrl->WscPBCAddr); + if ((bss_idx == BSS_NOT_FOUND) +#ifdef SMART_MESH_HIDDEN_WPS + || (pApCliEntry->SmartMeshCfg.bSupportHiddenWPS && + !pAd->ScanTab.BssEntry[bss_idx].bRunningHiddenWPS) +#endif /* SMART_MESH_HIDDEN_WPS */ + ) + { + return; + } + else + { + /* Follow found AP's ssid and ignore WscSsid setting. */ + NdisZeroMemory(JoinReq.Ssid, MAX_LEN_OF_SSID); + JoinReq.SsidLen = pAd->ScanTab.BssEntry[bss_idx].SsidLen; + NdisMoveMemory(JoinReq.Ssid, pAd->ScanTab.BssEntry[bss_idx].Ssid, JoinReq.SsidLen); + NdisZeroMemory(pWpsCtrl->WscSsid.Ssid, MAX_LEN_OF_SSID); + pWpsCtrl->WscSsid.SsidLength = JoinReq.SsidLen; + NdisMoveMemory(pWpsCtrl->WscSsid.Ssid, JoinReq.Ssid, JoinReq.SsidLen); + COPY_MAC_ADDR(JoinReq.Bssid, pAd->ScanTab.BssEntry[bss_idx].Bssid); + + pWpsCtrl->WscState = WSC_STATE_START; + pWpsCtrl->WscStatus = STATUS_WSC_START_ASSOC; + pWpsCtrl->WscMode = 2; + pWpsCtrl->bWscTrigger = TRUE; + } + } +#endif /* SMART_MESH */ + } + else +#endif /* WSC_AP_SUPPORT */ + if (pApCliEntry->CfgSsidLen != 0) + { + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + + ULONG bss_idx = BSS_NOT_FOUND; + bss_idx = BssSsidTableSearchBySSID(&pAd->ScanTab, (PCHAR)pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen); + + if (bss_idx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s:: can't find SSID[%s] in ScanTab.\n", __FUNCTION__, pApCliEntry->CfgSsid)); + *pCurrState = APCLI_CTRL_PROBE; + + CFG80211_checkScanTable(pAd); + RT_CFG80211_P2P_CLI_CONN_RESULT_INFORM(pAd, JoinReq.Bssid, NULL, 0, NULL, 0, 0); + + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: find SSID[%ld][%s] channel[%d-%d] in ScanTab.\n", __FUNCTION__, + bss_idx, pApCliEntry->CfgSsid, pAd->ScanTab.BssEntry[bss_idx].Channel, + pAd->ScanTab.BssEntry[bss_idx].CentralChannel)); + +//TODO + /* BssSearch Table has found the pEntry, send Prob Req. directly */ + if (pAd->CommonCfg.Channel != pAd->ScanTab.BssEntry[bss_idx].Channel) + { + pAd->CommonCfg.Channel = pAd->ScanTab.BssEntry[bss_idx].Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + if (JoinReq.SsidLen <= MAX_LEN_OF_SSID) + { + char SSID[MAX_LEN_OF_SSID + 1] = {0}; + + snprintf(SSID, JoinReq.SsidLen + 1, "%s", JoinReq.Ssid); + printk(KERN_INFO "AP-Client probe: SSID=%s, BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + SSID, PRINT_MAC(JoinReq.Bssid)); + } + + *pCurrState = APCLI_CTRL_PROBE; + + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_MLME_PROBE_REQ, + sizeof(APCLI_MLME_JOIN_REQ_STRUCT), &JoinReq, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME JOIN req timeout state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlJoinReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_MLME_JOIN_REQ_STRUCT JoinReq; + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Req Timeout.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + if (ApScanRunning(pAd) == TRUE) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + return; + } + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + pApCliEntry->ProbeReqCnt++; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Req Timeout. ProbeReqCnt=%d\n", + __FUNCTION__, pApCliEntry->ProbeReqCnt)); + + if (pApCliEntry->ProbeReqCnt > APCLI_MAX_PROBE_RETRY_NUM) + { + /* + if exceed the APCLI_MAX_PROBE_RETRY_NUM, + switch to try next candidate AP. + */ + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->ProbeReqCnt = 0; + + if (pAd->ApCfg.ApCliAutoConnectRunning == TRUE) + ApCliSwitchCandidateAP(pAd, ifIndex); + + if ((pAd->ApCfg.ApCliAutoConnectRunning == FALSE) && (pApCliEntry->AutoConnectFlag == TRUE)) + ApCliAutoConnectStart(pAd, ifIndex); + + return; + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + /* stay in same state. */ + *pCurrState = APCLI_CTRL_PROBE; + + /* retry Probe Req. */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Retry Probe Req.\n", __FUNCTION__)); + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + NdisZeroMemory(&JoinReq, sizeof(APCLI_MLME_JOIN_REQ_STRUCT)); + + if (!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } + +#ifdef WSC_AP_SUPPORT + if ((pApCliEntry->WscControl.WscConfMode != WSC_DISABLE) && + (pApCliEntry->WscControl.bWscTrigger == TRUE)) + { +#ifdef SMART_MESH + if((pApCliEntry->WscControl.WscMode == 2) && (pApCliEntry->WscControl.bWscPBCAddrMode == TRUE)) + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->WscControl.WscPBCAddr); +#endif /* SMART_MESH */ + NdisZeroMemory(JoinReq.Ssid, MAX_LEN_OF_SSID); + JoinReq.SsidLen = pApCliEntry->WscControl.WscSsid.SsidLength; + NdisMoveMemory(JoinReq.Ssid, pApCliEntry->WscControl.WscSsid.Ssid, JoinReq.SsidLen); + } + else +#endif /* WSC_AP_SUPPORT */ + if (pApCliEntry->CfgSsidLen != 0) + { + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + if (JoinReq.SsidLen <= MAX_LEN_OF_SSID) + { + char SSID[MAX_LEN_OF_SSID + 1] = {0}; + + snprintf(SSID, JoinReq.SsidLen + 1, "%s", JoinReq.Ssid); + printk(KERN_INFO "AP-Client probe: SSID=%s, BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + SSID, PRINT_MAC(JoinReq.Bssid)); + } + + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_MLME_PROBE_REQ, + sizeof(APCLI_MLME_JOIN_REQ_STRUCT), &JoinReq, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Probe Rsp state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlProbeRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + PAPCLI_STRUCT pApCliEntry; + MLME_AUTH_REQ_STRUCT AuthReq; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + struct wifi_dev *wdev; +#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); + } + + if (Info->CliIdx != 0xFF) + CliIdx = Info->CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrState = &pApCliEntry->RepeaterCli[CliIdx].CtrlCurrState; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pApCliEntry->CtrlCurrState; + + if (Status == MLME_SUCCESS) + { + if (pApCliEntry->MlmeAux.SsidLen <= MAX_LEN_OF_SSID) + { + char SSID[MAX_LEN_OF_SSID + 1] = {0}; + + snprintf(SSID, pApCliEntry->MlmeAux.SsidLen + 1, "%s", pApCliEntry->MlmeAux.Ssid); + printk(KERN_INFO "AP-Client probe response: SSID=%s, BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + SSID, PRINT_MAC(pApCliEntry->MlmeAux.Bssid)); + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.Channel < 14) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { + ADD_HTINFO RootApHtInfo = pApCliEntry->MlmeAux.AddHtInfo.AddHtInfo; + + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40 && + RootApHtInfo.ExtChanOffset != pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset && + RootApHtInfo.RecomWidth) + { + if (RootApHtInfo.ExtChanOffset == EXTCHA_ABOVE) { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + pApCliEntry->MlmeAux.CentralChannel = pApCliEntry->MlmeAux.Channel + 2; + } else { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + pApCliEntry->MlmeAux.CentralChannel = pApCliEntry->MlmeAux.Channel - 2; + } + + pAd->CommonCfg.Channel = pApCliEntry->MlmeAux.Channel; + pAd->CommonCfg.CentralChannel = pApCliEntry->MlmeAux.CentralChannel; +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.Bss2040NeedFallBack = 0; + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 0; +#endif /* DOT11N_DRAFT3 */ + SetCommonHT(pAd); + AsicBBPAdjust(pAd); + + pAd->hw_cfg.cent_ch = pAd->CommonCfg.CentralChannel; + AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE); + AsicLockChannel(pAd, pAd->hw_cfg.cent_ch); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ch(%d), cent_ch(%d), extcha(%d), bbp bw(%d)\n", + __FUNCTION__, + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.BBPCurrentBW)); +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; +#endif /* DOT11N_DRAFT3 */ + } + } +#endif /* DOT11_N_SUPPORT */ + + *pCurrState = APCLI_CTRL_AUTH; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AuthReqCnt = 0; + + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + + /* start Authentication Req. */ + /* If AuthMode is Auto, try shared key first */ + if ((wdev->AuthMode == Ndis802_11AuthModeShared) || + (wdev->AuthMode == Ndis802_11AuthModeAutoSwitch)) + AuthReq.Alg = Ndis802_11AuthModeShared; + else + AuthReq.Alg = Ndis802_11AuthModeOpen; + + AuthReq.Timeout = AUTH_TIMEOUT; +#ifdef MAC_REPEATER_SUPPORT + AuthReq.BssIdx = ifIndex; + AuthReq.CliIdx = CliIdx; + if (CliIdx != 0xFF) + { + ifIndex = (64 + 16*ifIndex + CliIdx); + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Repeater Cli Trigger Auth Req ifIndex = %d, CliIdx = %d !!!\n", + __FUNCTION__, ifIndex, CliIdx)); + } +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq, ifIndex); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe respond fail.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_DISCONNECTED; +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME AUTH Rsp state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAuthRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + PAPCLI_STRUCT pApCliEntry; + 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); + } +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Repeater Cli Receive ifIndex = %d, CliIdx = %d !!!\n", + __FUNCTION__, ifIndex, CliIdx)); + + pCurrState = &pApCliEntry->RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pApCliEntry->CtrlCurrState; + + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AssocReqCnt = 0; + +#ifdef APCLI_CONNECTION_TRIAL + //if connection trying, wait until trialtimeout and enqueue Assoc REQ then. + //TrialCh == 0 means trial has not been triggered. + if (pApCliEntry->TrialCh == 0) { +#endif /* APCLI_CONNECTION_TRIAL */ + + AssocParmFill(pAd, &AssocReq, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, 5); +#ifdef APCLI_CONNECTION_TRIAL + } +#endif /* APCLI_CONNECTION_TRIAL */ + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef APCLI_CONNECTION_TRIAL + //if connection trying, wait until trialtimeout and enqueue Assoc REQ then. + //TrialCh == 0 means trial has not been triggered. + if (pApCliEntry->TrialCh == 0) { +#endif /* APCLI_CONNECTION_TRIAL */ + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); +#ifdef APCLI_CONNECTION_TRIAL + } +#endif /* APCLI_CONNECTION_TRIAL */ + } + else + { + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeAutoSwitch) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Rsp Failure.\n", __FUNCTION__)); + + *pCurrState = APCLI_CTRL_AUTH_2; + + /* start Second Authentication Req. */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Start Second Auth Rep.\n", __FUNCTION__)); + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + AuthReq.Alg = Ndis802_11AuthModeOpen; + AuthReq.Timeout = AUTH_TIMEOUT; +#ifdef MAC_REPEATER_SUPPORT + AuthReq.BssIdx = ifIndex; + AuthReq.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq, ifIndex); + } + else + { +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt = 0; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; + } + *pCurrState = APCLI_CTRL_DISCONNECTED; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } + } + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME AUTH2 Rsp state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAuth2RspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + MLME_ASSOC_REQ_STRUCT AssocReq; + PAPCLI_STRUCT pApCliEntry; + 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); + } +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrState = &pApCliEntry->RepeaterCli[CliIdx].CtrlCurrState; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pApCliEntry->CtrlCurrState; + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth2 Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AssocReqCnt = 0; + + AssocParmFill(pAd, &AssocReq, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, 5); + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); + } + else + { + printk(KERN_WARNING "AP-Client: authentication failed!\n"); + + *pCurrState = APCLI_CTRL_DISCONNECTED; +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Auth Req timeout state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAuthReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_AUTH_REQ_STRUCT AuthReq; + PAPCLI_STRUCT pApCliEntry; + 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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Req Timeout.\n", __FUNCTION__)); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt++; + + if (pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt = 0; + return; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->AuthReqCnt++; + + if (pApCliEntry->AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + return; + } + } + + /* stay in same state. */ + *pCurrState = APCLI_CTRL_AUTH; + + /* retry Authentication. */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Retry Auth Req.\n", __FUNCTION__)); + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + AuthReq.Alg = pApCliEntry->MlmeAux.Alg; /*Ndis802_11AuthModeOpen; */ + AuthReq.Timeout = AUTH_TIMEOUT; +#ifdef MAC_REPEATER_SUPPORT + AuthReq.BssIdx = ifIndex; + AuthReq.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Auth2 Req timeout state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAuth2ReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + return; +} + +/* + ========================================================================== + Description: + APCLI MLME ASSOC RSP state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + 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); + + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Repeater Cli Receive Assoc Rsp ifIndex = %d, CliIdx = %d.\n", + __FUNCTION__, ifIndex, CliIdx)); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) apCliIf = %d, Receive Assoc Rsp Success.\n", __FUNCTION__, ifIndex)); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.WpaSupplicantUP) + { + ApcliSendAssocIEsToWpaSupplicant(pAd,ifIndex); + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + RT_ASSOC_EVENT_FLAG, + NULL, NULL, 0); + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + if (ApCliLinkUp(pAd, ifIndex)) + { + *pCurrState = APCLI_CTRL_CONNECTED; +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + CFG80211_checkScanTable(pAd); + RT_CFG80211_P2P_CLI_CONN_RESULT_INFORM(pAd, pApCliEntry->MlmeAux.Bssid, + pApCliEntry->ReqVarIEs, pApCliEntry->ReqVarIELen, + pApCliEntry->ResVarIEs, pApCliEntry->ResVarIELen, TRUE); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) apCliIf = %d, Insert Remote AP to MacTable failed.\n", __FUNCTION__, ifIndex)); + /* Reset the apcli interface as disconnected and Invalid. */ + *pCurrState = APCLI_CTRL_DISCONNECTED; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->Valid = FALSE; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + CFG80211_checkScanTable(pAd); + RT_CFG80211_P2P_CLI_CONN_RESULT_INFORM(pAd, pApCliEntry->MlmeAux.Bssid, + NULL, 0, NULL, 0, 0); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) apCliIf = %d, Receive Assoc Rsp Failure.\n", __FUNCTION__, ifIndex)); + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + /* set the apcli interface be valid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->Valid = FALSE; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + CFG80211_checkScanTable(pAd); + RT_CFG80211_P2P_CLI_CONN_RESULT_INFORM(pAd, pApCliEntry->MlmeAux.Bssid, + NULL, 0, NULL, 0, 0); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + } + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME DeASSOC RSP state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDeAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Receive DeAssoc Rsp Success.\n", __FUNCTION__)); + } else + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Receive DeAssoc Rsp Failure.\n", __FUNCTION__)); + } + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Assoc Req timeout state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAssocReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_ASSOC_REQ_STRUCT AssocReq; + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Assoc Req Timeout.\n", __FUNCTION__)); + + 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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* give up to retry authentication req after retry it 5 times. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx !=0xFF) + { + pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt++; + if (pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt = 0; + return; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->AssocReqCnt++; + if (pApCliEntry->AssocReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AssocReqCnt = 0; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd, ifIndex); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + return; + } + } + + /* stay in same state. */ + *pCurrState = APCLI_CTRL_ASSOC; + + /* retry Association Req. */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Retry Association Req.\n", __FUNCTION__)); + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, 5); + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Disconnect Rsp state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDisconnectReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request disconnect.\n", __FUNCTION__)); + + 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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_ERROR, ("(%s) 2. Before do ApCliLinkDown.\n", __FUNCTION__)); + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Peer DeAssoc Req state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlPeerDeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + printk(KERN_INFO "AP-Client: disconnected by peer\n"); + + 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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) + { + UCHAR index; + + for(index = 0; index < MAX_EXT_MAC_ADDR_SIZE; index++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].CliEnable) + { + RTMPRemoveRepeaterDisconnectEntry(pAd, ifIndex, index); + RTMPRemoveRepeaterEntry(pAd, ifIndex, index); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + if (bValid) + ApCliLinkDown(pAd, ifIndex); + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { + PMAC_TABLE_ENTRY pMacEntry; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + if (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + ApCliSwitchCandidateAP(pAd, ifIndex); + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Disconnect Req state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDeAssocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request Disconnect.\n", __FUNCTION__)); + + 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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + DisassocParmFill(pAd, &DisassocReq, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, REASON_DISASSOC_STA_LEAVING); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, ifIndex); + + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable = FALSE; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + + *pCurrState = APCLI_CTRL_DEASSOC; + + return; +} + + +/* + ========================================================================== + Description: + APCLI MLME Disconnect Req state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + MLME_DEAUTH_REQ_STRUCT DeAuthFrame; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request Disconnect.\n", __FUNCTION__)); + + 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].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Fill in the related information */ + DeAuthFrame.Reason = (USHORT)REASON_DEAUTH_STA_LEAVING; + COPY_MAC_ADDR(DeAuthFrame.Addr, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, + APCLI_AUTH_STATE_MACHINE, + APCLI_MT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), + &DeAuthFrame, + ifIndex); + + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable = FALSE; + //RTMPDelRepeaterCliAsicEntry(pAd, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + + +VOID ApCliWpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + UCHAR *mpool; + PEAPOL_PACKET pPacket; + UCHAR Mic[16]; + BOOLEAN bUnicast; + UCHAR Wcid; + PMAC_TABLE_ENTRY pMacEntry = NULL; + USHORT ifIndex = (USHORT)(Elem->Priv); + APCLI_STRUCT *apcli_entry; + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliWpaMicFailureReportFrame ----->\n")); + + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); + pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); + + + /* init 802.3 header and Fill Packet */ + pMacEntry = &pAd->MacTab.Content[apcli_entry->MacTabWCID]; + if (!IS_ENTRY_APCLI(pMacEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : !IS_ENTRY_APCLI(pMacEntry)\n", __FUNCTION__)); + return; + } + + Wcid = apcli_entry->MacTabWCID; + MAKE_802_3_HEADER(Header802_3, pAd->MacTab.Content[Wcid].Addr, wdev->if_addr, EAPOL); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pPacket = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pPacket, TX_EAPOL_BUFFER); + + pPacket->ProVer = EAPOL_VER; + pPacket->ProType = EAPOLKey; + + pPacket->KeyDesc.Type = WPA1_KEY_DESC; + + /* Request field presented */ + pPacket->KeyDesc.KeyInfo.Request = 1; + + if(wdev->WepStatus == Ndis802_11Encryption3Enabled) + { + pPacket->KeyDesc.KeyInfo.KeyDescVer = 2; + } + else /* TKIP */ + { + pPacket->KeyDesc.KeyInfo.KeyDescVer = 1; + } + + pPacket->KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); + + /* KeyMic field presented */ + pPacket->KeyDesc.KeyInfo.KeyMic = 1; + + /* Error field presented */ + pPacket->KeyDesc.KeyInfo.Error = 1; + + /* Update packet length after decide Key data payload */ + SET_UINT16_TO_ARRARY(pPacket->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG) + + /* Key Replay Count */ + NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, apcli_entry->ReplayCounter, LEN_KEY_DESC_REPLAY); + inc_byte_array(apcli_entry->ReplayCounter, 8); + + /* Convert to little-endian format. */ + *((USHORT *)&pPacket->KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&pPacket->KeyDesc.KeyInfo)); + + + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /* allocate memory */ + if(pOutBuffer == NULL) + { + os_free_mem(NULL, mpool); + return; + } + + /* + Prepare EAPOL frame for MIC calculation + Be careful, only EAPOL frame is counted for MIC calculation + */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, pPacket, + END_OF_ARGS); + + /* Prepare and Fill MIC value */ + NdisZeroMemory(Mic, sizeof(Mic)); + if(wdev->WepStatus == Ndis802_11Encryption3Enabled) + { /* AES */ + UCHAR digest[20] = {0}; + RT_HMAC_SHA1(apcli_entry->PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { /* TKIP */ + RT_HMAC_MD5(apcli_entry->PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); + } + NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + /* copy frame to Tx ring and send MIC failure report frame to authenticator */ + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[Wcid], + Header802_3, LENGTH_802_3, + (PUCHAR)pPacket, + CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, FALSE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliWpaMicFailureReportFrame <-----\n")); +} + +#ifdef APCLI_CERT_SUPPORT +static VOID ApCliCtrlScanDoneAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + +#ifdef DOT11N_DRAFT3 + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR i; + /* AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone. */ + if ((pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) { + DBGPRINT(RT_DEBUG_TRACE, ("Update2040CoexistFrameAndNotify @%s \n", __FUNCTION__)); + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].apidx == ifIndex)) + { + Update2040CoexistFrameAndNotify(pAd, i, TRUE); + } + } + } +#endif /* DOT11N_DRAFT3 */ +} +#endif /* APCLI_CERT_SUPPORT */ + +#ifdef APCLI_CONNECTION_TRIAL +/* + ========================================================================== + Description: + APCLI trigger JOIN req state machine procedure + for connect the another rootAP + ========================================================================== + */ +static VOID ApCliCtrlTrialConnectAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_MLME_JOIN_REQ_STRUCT JoinReq; + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + BOOLEAN Cancelled; + PMAC_TABLE_ENTRY pMacEntry; + + UCHAR BBPValue; + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Start Probe Req Trial.\n", __func__)); + if (ifIndex >= MAX_APCLI_NUM || ifIndex == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Index: %d error!!\n", __func__, ifIndex)); + return; + } + + if (ApScanRunning(pAd) == TRUE) { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Ap Scanning.....\n", __func__)); + return; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + if (!(pApCliEntry->TrialCh)) { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Didn't assign the RootAP channel\n", __func__)); + return; + } + else { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) channel TrialConnectTimer\n", __func__)); + RTMPCancelTimer(&(pApCliEntry->TrialConnectTimer), &Cancelled); + + if (pApCliEntry->TrialCh != pAd->CommonCfg.CentralChannel) { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Jump to CH:%d\n", __func__, pApCliEntry->TrialCh)); + /* Let BBP register at 20MHz*/ + AsicDisableSync(pAd);//disable beacon + AsicSwitchChannel(pAd, pApCliEntry->TrialCh, TRUE); + DBGPRINT(RT_DEBUG_ERROR, ("(%s) set TrialConnectTimer(%d ms)\n", __func__,TRIAL_TIMEOUT)); + RTMPSetTimer(&(pApCliEntry->TrialConnectTimer), TRIAL_TIMEOUT); + } + } + + NdisZeroMemory(&JoinReq, sizeof(APCLI_MLME_JOIN_REQ_STRUCT)); + + if (!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } + + if (pApCliEntry->CfgSsidLen != 0) + { + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + if (JoinReq.SsidLen <= MAX_LEN_OF_SSID) + { + char SSID[MAX_LEN_OF_SSID + 1] = {0}; + + snprintf(SSID, JoinReq.SsidLen + 1, "%s", JoinReq.Ssid); + printk(KERN_INFO "AP-Client probe: SSID=%s, BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + SSID, PRINT_MAC(JoinReq.Bssid)); + } + + *pCurrState = APCLI_CTRL_PROBE; + + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_MLME_PROBE_REQ, + sizeof(APCLI_MLME_JOIN_REQ_STRUCT), &JoinReq, ifIndex); + + return; +} +#endif /* APCLI_CONNECTION_TRIAL */ +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_sync.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_sync.c new file mode 100644 index 000000000..c83cfc7e3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/ap/apcli_sync.c @@ -0,0 +1,1234 @@ +/* + *************************************************************************** + * 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: + sta_sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2006-06-23 modified for rt61-APClinent +*/ + +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + +static VOID ApCliProbeTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID ApCliMlmeProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerProbeRspAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliProbeTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliEnqueueProbeRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR SsidLen, + IN PCHAR Ssid, + IN PCHAR Bssid, + IN USHORT ifIndex); + +static VOID ApCliMlmeScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef SMART_MESH_MONITOR +static VOID ApCliPeerProbeRspAtScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* SMART_MESH_MONITOR */ + +DECLARE_TIMER_FUNCTION(ApCliProbeTimeout); +BUILD_TIMER_FUNCTION(ApCliProbeTimeout); + +/* + ========================================================================== + Description: + The sync state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ +VOID ApCliSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; +#ifdef APCLI_CONNECTION_TRIAL + PAPCLI_STRUCT pApCliEntry; +#endif /*APCLI_CONNECTION_TRIAL*/ + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, + APCLI_MAX_SYNC_STATE, APCLI_MAX_SYNC_MSG, + (STATE_MACHINE_FUNC)Drop, APCLI_SYNC_IDLE, + APCLI_SYNC_MACHINE_BASE); + + /* column 1 */ + StateMachineSetAction(Sm, APCLI_SYNC_IDLE, APCLI_MT2_MLME_PROBE_REQ, (STATE_MACHINE_FUNC)ApCliMlmeProbeReqAction); + StateMachineSetAction(Sm, APCLI_SYNC_IDLE, APCLI_MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)ApCliMlmeScanReqAction); +#ifdef SMART_MESH_MONITOR + StateMachineSetAction(Sm, APCLI_SYNC_IDLE, APCLI_MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)ApCliPeerProbeRspAtScanReqAction); +#endif /* SMART_MESH_MONITOR */ + + /*column 2 */ + StateMachineSetAction(Sm, APCLI_JOIN_WAIT_PROBE_RSP, APCLI_MT2_MLME_PROBE_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenJoin); + StateMachineSetAction(Sm, APCLI_JOIN_WAIT_PROBE_RSP, APCLI_MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)ApCliPeerProbeRspAtJoinAction); + StateMachineSetAction(Sm, APCLI_JOIN_WAIT_PROBE_RSP, APCLI_MT2_PROBE_TIMEOUT, (STATE_MACHINE_FUNC)ApCliProbeTimeoutAtJoinAction); + StateMachineSetAction(Sm, APCLI_JOIN_WAIT_PROBE_RSP, APCLI_MT2_PEER_BEACON, (STATE_MACHINE_FUNC)ApCliPeerProbeRspAtJoinAction); + + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + /* timer init */ +#ifdef APCLI_CONNECTION_TRIAL + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; +#endif /*APCLI_CONNECTION_TRIAL*/ + +#ifdef APCLI_CONNECTION_TRIAL + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ProbeTimer, GET_TIMER_FUNCTION(ApCliProbeTimeout), (PVOID)pApCliEntry, FALSE); +#else + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ProbeTimer, GET_TIMER_FUNCTION(ApCliProbeTimeout), pAd, FALSE); +#endif /* APCLI_CONNECTION_TRIAL */ + pAd->ApCfg.ApCliTab[i].SyncCurrState = APCLI_SYNC_IDLE; + } + + return; +} + +/* + ========================================================================== + Description: + Becaon timeout handler, executed in timer thread + ========================================================================== + */ +static VOID ApCliProbeTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ +#ifdef APCLI_CONNECTION_TRIAL + PAPCLI_STRUCT pApCliEntry = (APCLI_STRUCT *)FunctionContext; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pApCliEntry->pAd; +#else + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; +#endif /*APCLI_CONNECTION_TRIAL*/ + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - ProbeReqTimeout\n")); +#ifndef APCLI_CONNECTION_TRIAL + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PROBE_TIMEOUT, 0, NULL, 0); +#else + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PROBE_TIMEOUT, 0, NULL, pApCliEntry->ifIndex); +#endif /* APCLI_CONNECTION_TRIAL */ + RTMP_MLME_HANDLER(pAd); + + return; +} + +/* + ========================================================================== + Description: + MLME PROBE req state machine procedure + ========================================================================== + */ +static VOID ApCliMlmeProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + APCLI_MLME_JOIN_REQ_STRUCT *Info = (APCLI_MLME_JOIN_REQ_STRUCT *)(Elem->Msg); + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + APCLI_STRUCT *pApCliEntry = NULL; + struct wifi_dev *wdev; + ULONG bss_idx = BSS_NOT_FOUND; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - ApCliMlmeProbeReqAction(Ssid %s)\n", Info->Ssid)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + + /* reset all the timers */ + RTMPCancelTimer(&(pApCliEntry->MlmeAux.ProbeTimer), &Cancelled); + + pApCliEntry->MlmeAux.Rssi = -9999; + bss_idx = BssSsidTableSearchBySSID(&pAd->ScanTab, (PCHAR)Info->Ssid, Info->SsidLen); + if (bss_idx == BSS_NOT_FOUND) + { +#ifdef APCLI_CONNECTION_TRIAL + if (pApCliEntry->TrialCh ==0) + pApCliEntry->MlmeAux.Channel = pAd->CommonCfg.Channel; + else + pApCliEntry->MlmeAux.Channel = pApCliEntry->TrialCh; +#else + pApCliEntry->MlmeAux.Channel = pAd->CommonCfg.Channel; +#endif /* APCLI_CONNECTION_TRIAL */ + } + else + { +#ifdef APCLI_CONNECTION_TRIAL + if (pApCliEntry->TrialCh ==0) + pApCliEntry->MlmeAux.Channel = pAd->CommonCfg.Channel; + else + pApCliEntry->MlmeAux.Channel = pApCliEntry->TrialCh; +#else + DBGPRINT(RT_DEBUG_TRACE, ("%s, Found %s in scanTable , goto channel %d\n", + __FUNCTION__, pAd->ScanTab.BssEntry[bss_idx].Ssid, + pAd->ScanTab.BssEntry[bss_idx].Channel)); + + pApCliEntry->MlmeAux.Channel = pAd->ScanTab.BssEntry[bss_idx].Channel; +#endif /* APCLI_CONNECTION_TRIAL */ + } + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + pApCliEntry->MlmeAux.SupRateLen = pAd->cfg80211_ctrl.P2pSupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, pAd->cfg80211_ctrl.P2pSupRate, pAd->cfg80211_ctrl.P2pSupRateLen); + + pApCliEntry->MlmeAux.ExtRateLen = pAd->cfg80211_ctrl.P2pExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, pAd->cfg80211_ctrl.P2pExtRate, pAd->cfg80211_ctrl.P2pExtRateLen); +#else +#ifdef APCLI_AUTO_BW_SUPPORT + pApCliEntry->MlmeAux.SupRateLen = wdev->SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, wdev->SupRate, wdev->SupRateLen); + + /* Prepare the default value for extended rate */ + pApCliEntry->MlmeAux.ExtRateLen = wdev->ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, wdev->ExtRate, wdev->ExtRateLen); +#else + pApCliEntry->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, pAd->CommonCfg.SupRate, pAd->CommonCfg.SupRateLen); + + /* Prepare the default value for extended rate */ + pApCliEntry->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, pAd->CommonCfg.ExtRateLen); +#endif /* APCLI_AUTO_BW_SUPPORT */ +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + RTMPSetTimer(&(pApCliEntry->MlmeAux.ProbeTimer), PROBE_TIMEOUT); + +#ifdef APCLI_CONNECTION_TRIAL + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, Info->Bssid, MAC_ADDR_LEN); + NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, Info->Ssid, Info->SsidLen); +#endif /* APCLI_CONNECTION_TRIAL */ + + ApCliEnqueueProbeRequest(pAd, Info->SsidLen, (PCHAR)Info->Ssid, (PCHAR)Info->Bssid, ifIndex); + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - Start Probe the SSID %s on channel =%d\n", Info->Ssid, pApCliEntry->MlmeAux.Channel)); + + *pCurrState = APCLI_JOIN_WAIT_PROBE_RSP; + + return; +} + + +/* + ========================================================================== + Description: + When waiting joining the (I)BSS, beacon received from external + ========================================================================== + */ +static VOID ApCliPeerProbeRspAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT LenVIE; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; +#endif /* DOT11_N_SUPPORT */ + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *pCurrState; + BCN_IE_LIST *ie_list = NULL; + UCHAR PhyMode = pAd->CommonCfg.PhyMode; + PFRAME_802_11 pFrame = NULL; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* Init Variable IE structure */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + pFrame = (PFRAME_802_11)Elem->Msg; + + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + ie_list, + &LenVIE, + pVIE)) + { + /* + BEACON from desired BSS/IBSS found. We should be able to decide most + BSS parameters here. + Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? + Do we need to receover back all parameters belonging to previous BSS? + A. Should be not. There's no back-door recover to previous AP. It still need + a new JOIN-AUTH-ASSOC sequence. + */ + INT ssidEqualFlag = FALSE; + INT ssidEmptyFlag = FALSE; + INT bssidEqualFlag = FALSE; + INT bssidEmptyFlag = FALSE; + INT matchFlag = FALSE; + + ULONG Bssidx; + LONG RealRssi = -127; +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + RealRssi = (LONG)(RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2))); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* Update ScanTab */ + Bssidx = BssTableSearch(&pAd->ScanTab, ie_list->Bssid, ie_list->Channel); + if (Bssidx == BSS_NOT_FOUND) + { + /* discover new AP of this network, create BSS entry */ +#ifdef CUSTOMER_DCC_FEATURE + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, -127, LenVIE, pVIE, Elem->Snr0, Elem->Snr1); +#else + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, -127, LenVIE, pVIE); +#endif + if (Bssidx == BSS_NOT_FOUND) /* return if BSS table full */ + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: Driver ScanTable Full In Apcli ProbeRsp Join\n")); + goto LabelErr; + } + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + pAd->ScanTab.BssEntry[Bssidx].MinSNR = Elem->Signal % 10; + if (pAd->ScanTab.BssEntry[Bssidx].MinSNR == 0) + pAd->ScanTab.BssEntry[Bssidx].MinSNR = -5; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].MacAddr, ie_list->Addr2, MAC_ADDR_LEN); + } + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + DBGPRINT(RT_DEBUG_TRACE, ("Info: Update the SSID %s in Kernel Table\n", ie_list->Ssid)); + RT_CFG80211_SCANNING_INFORM(pAd, Bssidx, ie_list->Channel, (UCHAR *)Elem->Msg, Elem->MsgLen, RealRssi); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + + /* Check the Probe-Rsp's Ssid. */ +#ifdef WSC_AP_SUPPORT + if ((pApCliEntry->WscControl.WscConfMode != WSC_DISABLE) && + (pApCliEntry->WscControl.bWscTrigger == TRUE)) + { +#ifdef SMART_MESH + if((pApCliEntry->WscControl.WscMode == 2) && + (pApCliEntry->WscControl.bWscPBCAddrMode == TRUE)) + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->WscControl.WscPBCAddr, ie_list->Bssid); + else +#endif /* SMART_MESH */ + { + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ie_list->Bssid); + else + bssidEmptyFlag = TRUE; + } + + if(pApCliEntry->WscControl.WscSsid.SsidLength != 0) + ssidEqualFlag = SSID_EQUAL(pApCliEntry->WscControl.WscSsid.Ssid, + pApCliEntry->WscControl.WscSsid.SsidLength,ie_list->Ssid, ie_list->SsidLen); + else + ssidEmptyFlag = TRUE; + } + else +#endif /* WSC_AP_SUPPORT */ + { + /* Check the Probe-Rsp's Bssid. */ + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ie_list->Bssid); + else + bssidEmptyFlag = TRUE; + + if(pApCliEntry->CfgSsidLen != 0) + ssidEqualFlag = SSID_EQUAL(pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, ie_list->Ssid, ie_list->SsidLen); + else + ssidEmptyFlag = TRUE; + } + + /* bssid and ssid, Both match. */ + if (bssidEqualFlag && ssidEqualFlag) + matchFlag = TRUE; + + /* ssid match but bssid doesn't be indicate. */ + else if(ssidEqualFlag && bssidEmptyFlag) + matchFlag = TRUE; + + /* user doesn't indicate any bssid or ssid. AP-Clinet will auto pick a AP to join by most strong siganl strength. */ + else if (bssidEmptyFlag && ssidEmptyFlag) + { + matchFlag = TRUE; +#ifdef SMART_MESH + matchFlag = FALSE; +#endif /* SMART_MESH */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - bssidEqualFlag=%d, ssidEqualFlag=%d, matchFlag=%d\n", + bssidEqualFlag, ssidEqualFlag, matchFlag)); + if (matchFlag) + { + /* Validate RSN IE if necessary, then copy store this information */ + if ((LenVIE > 0) +#ifdef WSC_AP_SUPPORT + && ((pApCliEntry->WscControl.WscConfMode == WSC_DISABLE) || + (pApCliEntry->WscControl.bWscTrigger == FALSE)) +#endif /* WSC_AP_SUPPORT */ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* When using CFG80211 and trigger WPS, do not check security. */ + && ! (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + ) + { + if (ApCliValidateRSNIE(pAd, (PEID_STRUCT)pVIE, LenVIE, ifIndex)) + { + pApCliEntry->MlmeAux.VarIELen = LenVIE; + NdisMoveMemory(pApCliEntry->MlmeAux.VarIEs, pVIE, pApCliEntry->MlmeAux.VarIELen); + } + else + { + /* ignore this response */ + pApCliEntry->MlmeAux.VarIELen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The RSN IE of this received Probe-resp is dis-match !!!!!!!!!! \n")); + goto LabelErr; + } + } + else + { + if (pApCliEntry->wdev.AuthMode >= Ndis802_11AuthModeWPA +#ifdef WSC_AP_SUPPORT + && ((pApCliEntry->WscControl.WscConfMode == WSC_DISABLE) || + (pApCliEntry->WscControl.bWscTrigger == FALSE)) +#endif /* WSC_AP_SUPPORT */ + ) + { + /* ignore this response */ + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The received Probe-resp has empty RSN IE !!!!!!!!!! \n")); + goto LabelErr; + } + + pApCliEntry->MlmeAux.VarIELen = 0; + } + +#ifdef SMART_MESH + PSMART_MESH_CFG pSmartMeshCfg = NULL; + pSmartMeshCfg = &pApCliEntry->SmartMeshCfg; + + if(((pSmartMeshCfg->HiFiFlagMask != 0) && (pSmartMeshCfg->HiFiFlagValue != 0)) && + ((ie_list->VIEFlag & pSmartMeshCfg->HiFiFlagMask) == pSmartMeshCfg->HiFiFlagValue)) + { + pAd->ScanTab.BssEntry[Bssidx].bHyperFiPeer = TRUE; + pApCliEntry->MlmeAux.bHyperFiPeer = TRUE; + } + else + { + pAd->ScanTab.BssEntry[Bssidx].bHyperFiPeer = FALSE; + pApCliEntry->MlmeAux.bHyperFiPeer = FALSE; + } + + if((pSmartMeshCfg->bHiFiPeerFilter == TRUE) && + (pAd->ScanTab.BssEntry[Bssidx].bHyperFiPeer == FALSE)) + { + DBGPRINT(RT_DEBUG_OFF, ("Reject this PROBE_RSP due to not desired Hyper-Fi peer(%02X:%02X:%02X:%02X:%02X:%02X).\n",PRINT_MAC(pAd->ScanTab.BssEntry[Bssidx].Bssid))); + goto LabelErr; + } + + if(pAd->ScanTab.BssEntry[Bssidx].bSupportSmartMesh != ie_list->bSupportSmartMesh) + pAd->ScanTab.BssEntry[Bssidx].bSupportSmartMesh = ie_list->bSupportSmartMesh; + + if(pAd->ScanTab.BssEntry[Bssidx].bSupportSmartMesh) + { + pApCliEntry->MlmeAux.bSupportSmartMesh = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("AP supports SMART MESH\n")); + } + else + pApCliEntry->MlmeAux.bSupportSmartMesh = FALSE; + + if(pAd->ScanTab.BssEntry[Bssidx].bHyperFiPeer) + DBGPRINT(RT_DEBUG_OFF, ("AP is Hyper-Fi device\n")); +#endif /* SMART_MESH */ +#ifdef MWDS + if(pAd->ScanTab.BssEntry[Bssidx].bSupportMWDS != ie_list->bSupportMWDS) + pAd->ScanTab.BssEntry[Bssidx].bSupportMWDS = ie_list->bSupportMWDS; + + if(pAd->ScanTab.BssEntry[Bssidx].bSupportMWDS) + { + pApCliEntry->MlmeAux.bSupportMWDS = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("AP supports MWDS\n")); + } + else + pApCliEntry->MlmeAux.bSupportMWDS = FALSE; +#endif /* MWDS */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ScanTab.BssEntry[Bssidx].bSupportHiddenWPS != ie_list->bSupportHiddenWPS) + pAd->ScanTab.BssEntry[Bssidx].bSupportHiddenWPS = ie_list->bSupportHiddenWPS; + + if(pAd->ScanTab.BssEntry[Bssidx].bSupportHiddenWPS) + DBGPRINT(RT_DEBUG_OFF, ("AP supports HiddenWPS\n")); + + if(pAd->ScanTab.BssEntry[Bssidx].bRunningHiddenWPS != ie_list->bRunningHiddenWPS) + pAd->ScanTab.BssEntry[Bssidx].bRunningHiddenWPS = ie_list->bRunningHiddenWPS; + + if(pAd->ScanTab.BssEntry[Bssidx].bRunningHiddenWPS) + DBGPRINT(RT_DEBUG_OFF, ("AP is running HiddenWPS\n")); +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired PROBE_RSP at JoinWaitProbeRsp... Channel = %d\n", + ie_list->Channel)); + + /* if the Bssid doesn't be indicated then you need to decide which AP to connect by most strong Rssi signal strength. */ + if (bssidEqualFlag == FALSE) + { + /* caculate real rssi value. */ + CHAR Rssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); + CHAR Rssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); + CHAR Rssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); + LONG RealMaxRssi = (LONG)(RTMPMaxRssi(pAd, Rssi0, Rssi1, Rssi2)); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - previous Rssi = %ld current Rssi=%ld\n", pApCliEntry->MlmeAux.Rssi, (LONG)RealMaxRssi)); + if (pApCliEntry->MlmeAux.Rssi > (LONG)RealMaxRssi) + goto LabelErr; + else + pApCliEntry->MlmeAux.Rssi = RealMaxRssi; + } + else + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pApCliEntry->MlmeAux.ProbeTimer, &Cancelled); + } + + NdisMoveMemory(pApCliEntry->MlmeAux.Ssid, ie_list->Ssid, ie_list->SsidLen); + pApCliEntry->MlmeAux.SsidLen = ie_list->SsidLen; + + NdisMoveMemory(pApCliEntry->MlmeAux.Bssid, ie_list->Bssid, MAC_ADDR_LEN); + pApCliEntry->MlmeAux.CapabilityInfo = ie_list->CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pApCliEntry->MlmeAux.BssType = ie_list->BssType; + pApCliEntry->MlmeAux.BeaconPeriod = ie_list->BeaconPeriod; + pApCliEntry->MlmeAux.Channel = ie_list->Channel; + pApCliEntry->MlmeAux.CentralChannel = ie_list->Channel; /* by default */ + pApCliEntry->MlmeAux.AtimWin = ie_list->AtimWin; + pApCliEntry->MlmeAux.CfpPeriod = ie_list->CfParm.CfpPeriod; + pApCliEntry->MlmeAux.CfpMaxDuration = ie_list->CfParm.CfpMaxDuration; + pApCliEntry->MlmeAux.APRalinkIe = ie_list->RalinkIe; + + /* Copy AP's supported rate to MlmeAux for creating assoication request */ + /* Also filter out not supported rate */ + pApCliEntry->MlmeAux.SupRateLen = ie_list->SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, ie_list->SupRate, ie_list->SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.SupRate, &pApCliEntry->MlmeAux.SupRateLen); + pApCliEntry->MlmeAux.ExtRateLen = ie_list->ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, ie_list->ExtRate, ie_list->ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.ExtRate, &pApCliEntry->MlmeAux.ExtRateLen); +#ifdef APCLI_CERT_SUPPORT + /* Get the ext capability info element */ + if (pAd->bApCliCertTest == TRUE +#ifdef DOT11N_DRAFT3 + && pAd->CommonCfg.bBssCoexEnable == TRUE +#endif /* DOT11N_DRAFT3 */ + ) + { + NdisMoveMemory(&pApCliEntry->MlmeAux.ExtCapInfo, &ie_list->ExtCapInfo,sizeof(ie_list->ExtCapInfo)); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("\x1b[31m ApCliMlmeAux.ExtCapInfo=%d \x1b[m\n", pApCliEntry->MlmeAux.ExtCapInfo.BssCoexistMgmtSupport)); //zero debug 210121122 + pAd->CommonCfg.ExtCapIE.BssCoexistMgmtSupport = 1; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + } +#endif /* APCLI_CERT_SUPPORT */ +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(pApCliEntry->RxMcsSet,sizeof(pApCliEntry->RxMcsSet)); + +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = pApCliEntry->wdev.PhyMode; + DBGPRINT(RT_DEBUG_OFF, ("%s: check HT Rule --> %d %d %d %d\n", __FUNCTION__, (ie_list->HtCapabilityLen > 0), + (pApCliEntry->wdev.DesiredHtPhyInfo.bHtEnable), WMODE_CAP_N(pApCliEntry->wdev.PhyMode), + !(pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(wdev->WepStatus)))); +#endif /* APCLI_AUTO_BW_SUPPORT */ + + /* filter out un-supported ht rates */ + if ((ie_list->HtCapabilityLen > 0) && + (pApCliEntry->wdev.DesiredHtPhyInfo.bHtEnable) && + WMODE_CAP_N(PhyMode) && + /* For Dissallow TKIP rule on STA */ + !(pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(wdev->WepStatus))) + { + RTMPZeroMemory(&pApCliEntry->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + pApCliEntry->MlmeAux.NewExtChannelOffset = ie_list->NewExtChannelOffset; + pApCliEntry->MlmeAux.HtCapabilityLen = ie_list->HtCapabilityLen; + ApCliCheckHt(pAd, ifIndex, &ie_list->HtCapability, &ie_list->AddHtInfo); + + if (ie_list->AddHtInfoLen > 0) + { + CentralChannel = ie_list->AddHtInfo.ControlChan; + /* Check again the Bandwidth capability of this AP. */ + CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo, + &ie_list->HtCapability); + pApCliEntry->MlmeAux.CentralChannel = CentralChannel; + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>CentralCh = %d, ControlCh = %d\n", + CentralChannel, ie_list->AddHtInfo.ControlChan)); + } + } + else +#endif /* DOT11_N_SUPPORT */ + { + RTMPZeroMemory(&pApCliEntry->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPZeroMemory(&pApCliEntry->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + pApCliEntry->MlmeAux.HtCapabilityLen = 0; + } + ApCliUpdateMlmeRate(pAd, ifIndex); + +#ifdef DOT11_N_SUPPORT + /* copy QOS related information */ + if (WMODE_CAP_N(PhyMode)) + { + NdisMoveMemory(&pApCliEntry->MlmeAux.APEdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pApCliEntry->MlmeAux.APQbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pApCliEntry->MlmeAux.APQosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + NdisZeroMemory(&pApCliEntry->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pApCliEntry->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pApCliEntry->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.ExtRateLen)); + + if (ie_list->AironetCellPowerLimit != 0xFF) + { + /* We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, ie_list->AironetCellPowerLimit); + } + else /* Used the default TX Power Percentage. */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + +#ifdef APCLI_AUTO_BW_SUPPORT + if ((ie_list->HtCapabilityLen > 0) && + (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + ApCliAutoBwAction(pAd, ifIndex); + } +#endif /* APCLI_AUTO_BW_SUPPORT */ + + if(bssidEqualFlag == TRUE) + { + *pCurrState = APCLI_SYNC_IDLE; + + ApCliCtrlMsg.Status = MLME_SUCCESS; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PROBE_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + +#ifdef SMART_MESH_MONITOR + if(pFrame && (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_RSP)) + { + struct nsmpif_drvevnt_buf drvevnt; + + drvevnt.data.proberesp.type = NSMPIF_DRVEVNT_AP_PROBE_RESP; + drvevnt.data.proberesp.channel = ie_list->Channel; + COPY_MAC_ADDR(drvevnt.data.proberesp.ap_mac, ie_list->Addr2); + drvevnt.data.proberesp.is_ucast = 1; + drvevnt.data.proberesp.rate = pAd->LastMgmtRxRate; + drvevnt.data.proberesp.rssi = RealRssi; + drvevnt.data.proberesp.snr = ConvertToSnr(pAd, Elem->Signal); +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if (IS_RT6352(pAd)) + { + if ((42 - drvevnt.data.proberesp.snr) >= 0) + drvevnt.data.proberesp.snr = (42 - drvevnt.data.proberesp.snr); + else + drvevnt.data.proberesp.snr = 0; + } + } +#endif /* RTMP_MAC */ + + NdisZeroMemory(drvevnt.data.proberesp.ssid,sizeof(drvevnt.data.proberesp.ssid)); + NdisCopyMemory(drvevnt.data.proberesp.ssid,ie_list->Ssid,ie_list->SsidLen); + drvevnt.data.proberesp.cap = 0; +#ifdef DOT11_N_SUPPORT + if(ie_list->HtCapabilityLen > 0) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_80211_N; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len > 0) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_80211_AC; +#endif /* DOT11_VHT_AC */ + // Bandwdith + if (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) + { +#ifdef DOT11_VHT_AC + if(ie_list->vht_op_len > 0 && ie_list->vht_op_ie.vht_op_info.ch_width >= 1) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_HT80; + else +#endif /* DOT11_VHT_AC */ + drvevnt.data.proberesp.cap |= NSMP_WLCAP_HT40; + } + // RX/TX STREAM + drvevnt.data.proberesp.cap |= \ + (ie_list->HtCapability.MCSSet[3] != 0x00) ? (NSMP_WLCAP_RX_4_STREAMS|NSMP_WLCAP_TX_4_STREAMS) :\ + (ie_list->HtCapability.MCSSet[2] != 0x00) ? (NSMP_WLCAP_RX_3_STREAMS|NSMP_WLCAP_TX_3_STREAMS) :\ + (ie_list->HtCapability.MCSSet[1] != 0x00) ? (NSMP_WLCAP_RX_2_STREAMS|NSMP_WLCAP_TX_2_STREAMS) : 0; + + /* Vendor information element */ + drvevnt.data.proberesp.ntgr_vie_len = ie_list->vendor_ie_len; + NdisZeroMemory(drvevnt.data.proberesp.ntgr_vie,sizeof(drvevnt.data.proberesp.ntgr_vie)); + if(ie_list->vendor_ie_len > 0) + NdisCopyMemory(drvevnt.data.proberesp.ntgr_vie,ie_list->vendor_ie,ie_list->vendor_ie_len); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_AP_PROBE_RESP, + NULL, (PUCHAR)&drvevnt.data.proberesp, sizeof(drvevnt.data.proberesp)); + } +#endif /* SMART_MESH_MONITOR */ + } + } + +LabelErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} + +static VOID ApCliProbeTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + APCLI_STRUCT *pApCliEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_SYNC - ProbeTimeoutAtJoinAction\n")); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + *pCurrState = SYNC_IDLE; + +#ifdef APCLI_CONNECTION_TRIAL + if (ifIndex == 1) + *pCurrState = APCLI_CTRL_DISCONNECTED; +#endif /* APCLI_CONNECTION_TRIAL */ + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_SYNC - MlmeAux.Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pApCliEntry->MlmeAux.Bssid))); + + if(!MAC_ADDR_EQUAL(pApCliEntry->MlmeAux.Bssid, ZERO_MAC_ADDR)) + { + ApCliCtrlMsg.Status = MLME_SUCCESS; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PROBE_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } else + { + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + } + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliInvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + + *pCurrState = APCLI_SYNC_IDLE; + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PROBE_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_AYNC - ApCliInvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", *pCurrState)); + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliEnqueueProbeRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR SsidLen, + IN PCHAR Ssid, + IN PCHAR Bssid, + IN USHORT ifIndex) +{ + NDIS_STATUS NState; + PUCHAR pOutBuffer; + ULONG FrameLen = 0; + HEADER_802_11 Hdr80211; + UCHAR SsidIe = IE_SSID; + UCHAR SupRateIe = IE_SUPP_RATES; + UCHAR ssidLen; + CHAR ssid[MAX_LEN_OF_SSID]; + APCLI_STRUCT *pApCliEntry = NULL; + BOOLEAN bHasWscIe = FALSE; + UCHAR PhyMode = pAd->CommonCfg.PhyMode; + + DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef APCLI_AUTO_BW_SUPPORT + PhyMode = pApCliEntry->wdev.PhyMode; +#endif /* APCLI_AUTO_BW_SUPPORT */ + + NState = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if(NState != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("EnqueueProbeRequest() allocate memory fail\n")); + return; + } + else + { + if(MAC_ADDR_EQUAL(Bssid, ZERO_MAC_ADDR)) + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + BROADCAST_ADDR, BROADCAST_ADDR, ifIndex); + else + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + Bssid, Bssid, ifIndex); + + ssidLen = SsidLen; + NdisZeroMemory(ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(ssid, Ssid, ssidLen); + + /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &ssidLen, + ssidLen, ssid, + 1, &SupRateIe, + 1, &pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRate, + END_OF_ARGS); + + /* Add the extended rate IE */ + if (pApCliEntry->MlmeAux.ExtRateLen != 0) + { + ULONG tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pApCliEntry->MlmeAux.ExtRateLen, + pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef SMART_MESH + SMART_MESH_INSERT_IE(pApCliEntry->SmartMeshCfg, + pOutBuffer, + FrameLen, + SM_IE_PROBE_REQ); +#endif /* SMART_MESH */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14)) + { + + build_vht_cap_ie(pAd, (UCHAR *)&pApCliEntry->MlmeAux.vht_cap); + pApCliEntry->MlmeAux.vht_cap_len = sizeof(VHT_CAP_IE); + + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_PROBE_REQ); + } +#endif /* DOT11_VHT_AC */ +#ifdef WSC_AP_SUPPORT +/* Append WSC information in probe request if WSC state is running */ + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) + { + bHasWscIe = TRUE; + } +#ifdef WSC_V2_SUPPORT + else if (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscV2Info.bEnableWpsV2) + { + bHasWscIe = TRUE; + } +#endif /* WSC_V2_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg.bSupportHiddenWPS) + bHasWscIe = FALSE; +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + if (bHasWscIe) + { + UCHAR /* WscBuf[256], */ WscIeLen = 0; + UCHAR *WscBuf = NULL; + ULONG WscTmpLen = 0; + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&WscBuf, 512); + if (WscBuf != NULL) + { + NdisZeroMemory(WscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, WscBuf, &WscIeLen); + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, WscBuf, + END_OF_ARGS); + FrameLen += WscTmpLen; + os_free_mem(NULL, WscBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } +#endif /*WSC_AP_SUPPORT*/ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->cfg80211_ctrl.ExtraIeLen != 0)) + { + ULONG ExtraIeTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &ExtraIeTmpLen, + pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, + END_OF_ARGS); + + FrameLen += ExtraIeTmpLen; + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE*/ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + return; +} + +VOID ApCliSiteSurvey( + IN RTMP_ADAPTER *pAd, + IN UCHAR ifIndex, + IN NDIS_802_11_SSID *pSsid, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, ignore this scan. + */ + DBGPRINT(RT_DEBUG_TRACE, ("ApCliSiteSurvey:: scanning now\n")); + return; + } + + if(ifIndex >= MAX_APCLI_NUM) + return; + +#ifdef WSC_AP_SUPPORT + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Stop scanning due to WPS triggered!\n",__FUNCTION__)); + return; + } +#endif /* WSC_AP_SUPPORT */ + + AsicDisableSync(pAd); + +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (((pAd->ApCfg.bPartialScanning == TRUE) && (pAd->ApCfg.LastPartialScanChannel == 0)) || + (pAd->ApCfg.bPartialScanning == FALSE)) +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + { + BssTableInit(&pAd->ScanTab); + } + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState = APCLI_SYNC_IDLE; + + RTMPZeroMemory(ScanReq.Ssid, MAX_LEN_OF_SSID); + ScanReq.SsidLen = 0; + if (pSsid) + { + ScanReq.SsidLen = pSsid->SsidLength; + NdisMoveMemory(ScanReq.Ssid, pSsid->Ssid, pSsid->SsidLength); + } + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = ScanType; + pAd->ApCfg.bAutoChannelAtBootup = ChannelSel; + + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + RTMP_MLME_HANDLER(pAd); +} + +static VOID ApCliMlmeScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType; + + /* Suspend MSDU transmission here */ + RTMPSuspendMsduTransmission(pAd); + + /* first check the parameter sanity */ + if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): mlme scan req action!\n", __FUNCTION__)); + NdisGetSystemUpTime(&pAd->ApCfg.LastScanTime); + + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + + /* record desired BSS parameters */ + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.ScanType = ScanType; + pAd->MlmeAux.SsidLen = SsidLen; + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + + /* start from the first channel */ +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->MlmeAux.Channel = RTMPFindScanChannel(pAd, 0); +#else + pAd->MlmeAux.Channel = FirstChannel(pAd); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.bAutoChannelAtBootup == TRUE)/* iwpriv set auto channel selection */ + { + APAutoChannelInit(pAd); + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[0].Channel; + } +#ifdef SMART_MESH + Set_Scan_False_CCA(pAd, 0, CCA_RESET); +#endif /* SMART_MESH */ + } +#endif /* CONFIG_AP_SUPPORT */ + ScanNextChannel(pAd, OPMODE_AP, INT_APCLI); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): sanity check fail. BUG!!!!\n", __FUNCTION__)); + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + } +} + +#ifdef SMART_MESH_MONITOR +static VOID ApCliPeerProbeRspAtScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT LenVIE; + UCHAR *VarIE = NULL; + PFRAME_802_11 pFrame = NULL; + PAPCLI_STRUCT pApCliEntry = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + USHORT ifIndex = (USHORT)(Elem->Priv); + BCN_IE_LIST *ie_list = NULL; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* Init Variable IE structure */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto lblErr; + } + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__)); + goto lblErr; + } + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + pFrame = (PFRAME_802_11)Elem->Msg; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + ie_list, + &LenVIE, + pVIE)) + { + CHAR RealRssi = -127; + + RealRssi = (LONG)(RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2))); + if(pFrame && (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_RSP)) + { + struct nsmpif_drvevnt_buf drvevnt; + + drvevnt.data.proberesp.type = NSMPIF_DRVEVNT_AP_PROBE_RESP; + drvevnt.data.proberesp.channel = ie_list->Channel; + COPY_MAC_ADDR(drvevnt.data.proberesp.ap_mac, ie_list->Addr2); + drvevnt.data.proberesp.is_ucast = 1; + drvevnt.data.proberesp.rate = pAd->LastMgmtRxRate; + drvevnt.data.proberesp.rssi = RealRssi; + drvevnt.data.proberesp.snr = ConvertToSnr(pAd, Elem->Signal); +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if (IS_RT6352(pAd)) + { + if ((42 - drvevnt.data.proberesp.snr) >= 0) + drvevnt.data.proberesp.snr = (42 - drvevnt.data.proberesp.snr); + else + drvevnt.data.proberesp.snr = 0; + } + } +#endif /* RTMP_MAC */ + NdisZeroMemory(drvevnt.data.proberesp.ssid,sizeof(drvevnt.data.proberesp.ssid)); + NdisCopyMemory(drvevnt.data.proberesp.ssid,ie_list->Ssid,ie_list->SsidLen); + drvevnt.data.proberesp.cap = 0; +#ifdef DOT11_N_SUPPORT + if(ie_list->HtCapabilityLen > 0) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_80211_N; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len > 0) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_80211_AC; +#endif /* DOT11_VHT_AC */ + // Bandwdith + if (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) + { +#ifdef DOT11_VHT_AC + if(ie_list->vht_op_len > 0 && ie_list->vht_op_ie.vht_op_info.ch_width >= 1) + drvevnt.data.proberesp.cap |= NSMP_WLCAP_HT80; + else +#endif /* DOT11_VHT_AC */ + drvevnt.data.proberesp.cap |= NSMP_WLCAP_HT40; + } + // RX/TX STREAM + drvevnt.data.proberesp.cap |= \ + (ie_list->HtCapability.MCSSet[3] != 0x00) ? (NSMP_WLCAP_RX_4_STREAMS|NSMP_WLCAP_TX_4_STREAMS) :\ + (ie_list->HtCapability.MCSSet[2] != 0x00) ? (NSMP_WLCAP_RX_3_STREAMS|NSMP_WLCAP_TX_3_STREAMS) :\ + (ie_list->HtCapability.MCSSet[1] != 0x00) ? (NSMP_WLCAP_RX_2_STREAMS|NSMP_WLCAP_TX_2_STREAMS) : 0; + + /* Vendor information element */ + drvevnt.data.proberesp.ntgr_vie_len = ie_list->vendor_ie_len; + NdisZeroMemory(drvevnt.data.proberesp.ntgr_vie,sizeof(drvevnt.data.proberesp.ntgr_vie)); + if(ie_list->vendor_ie_len > 0) + NdisCopyMemory(drvevnt.data.proberesp.ntgr_vie,ie_list->vendor_ie,ie_list->vendor_ie_len); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_AP_PROBE_RESP, + NULL, (PUCHAR)&drvevnt.data.proberesp, sizeof(drvevnt.data.proberesp)); + } + } + +lblErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} +#endif /* SMART_MESH_MONITOR */ +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/mt76x2.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/mt76x2.c new file mode 100644 index 000000000..39664b326 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/mt76x2.c @@ -0,0 +1,6405 @@ +#include "rt_config.h" + +#include "mcu/mt7662_rom_patch.h" +#include "mcu/mt7662_firmware.h" + +#ifdef MT7662TU +#include "mcu/mt7662t_rom_patch.h" +#include "mcu/mt7662t_firmware.h" +#endif /* MT7662TU */ + +#include "eeprom/mt76x2_e2p.h" + +#define MT7662_EFUSE_CTRL 0x0024 +static RTMP_REG_PAIR mt76x2_mac_cr_table[] = { + {PBF_SYS_CTRL, 0x80c00}, + {RLT_PBF_CFG, 0x1efebcff}, + {FCE_PSE_CTRL, 0x1}, + {MAC_SYS_CTRL, 0x0C}, + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x003E3000}, + {AMPDU_MAX_LEN_20M1S_MCS0_7, 0xAAA99887}, + {AMPDU_MAX_LEN_20M1S_MCS8_9, 0xAA}, + {XIFS_TIME_CFG, 0x33A40D0A}, + {BKOFF_SLOT_CFG, 0x209}, + {TBTT_SYNC_CFG, 0x422010}, + {PWR_PIN_CFG, 0x0}, + {0x1238, 0x001700C8}, + {TX_SW_CFG0, 0x00101001}, + {TX_SW_CFG1, 0x00010000}, + {TX_SW_CFG2, 0x0}, + {TXOP_CTRL_CFG, 0x0400583F}, + {TX_RTS_CFG, 0x00092B20}, + {TX_TIMEOUT_CFG, 0x000A2290}, + {TX_RTY_CFG, 0x47D01F0F}, + {EXP_ACK_TIME, 0x002C00DC}, + {TX_PROT_CFG6, 0xE3F42004}, + {TX_PROT_CFG7, 0xE3F42084}, + {TX_PROT_CFG8, 0xE3F42104}, + {PIFS_TX_CFG, 0x00060FFF}, + {RX_FILTR_CFG, 0x00015F97}, + {LEGACY_BASIC_RATE, 0x0000017F}, + {HT_BASIC_RATE, 0x00004003}, + {HT_CTRL_CFG, 0x000001FF}, + {0x150C, 0x00000002}, /* Enable TX length > 4095 bytes */ + {0x1608, 0x00000002}, + {0xa44, 0x0}, +#ifdef HDR_TRANS_SUPPORT + {HEADER_TRANS_CTRL_REG, 0x2}, /* 0x1: TX, 0x2: RX */ + {TSO_CTRL, 0x7050}, + {0x148, 0x15000001}, +#else + {HEADER_TRANS_CTRL_REG, 0x0}, + {TSO_CTRL, 0x0}, +#endif /* HDR_TRANS_SUPPORT */ + {AUX_CLK_CFG, 0x0}, + {DACCLK_EN_DLY_CFG, 0x0}, /* MAC dynamic control TX 960MHZ */ + {TX_ALC_CFG_4, 0x00000000}, + {TX_ALC_VGA3, 0x0}, + {TX_PWR_CFG_0, 0x3A3A3A3A}, + {TX_PWR_CFG_1, 0x3A3A3A3A}, + {TX_PWR_CFG_2, 0x3A3A3A3A}, + {TX_PWR_CFG_3, 0x3A3A3A3A}, + {TX_PWR_CFG_4, 0x3A3A3A3A}, + {TX_PWR_CFG_7, 0x3A3A3A3A}, + {TX_PWR_CFG_8, 0x3A}, + {TX_PWR_CFG_9, 0x3A}, + {MT7662_EFUSE_CTRL, 0xD000}, + {PER_PORT_PAUSE_ENABLE_CONTROL1, 0xA}, + {0x824, 0x60401c18}, //change the FCE threshold from 0x60402c28 to 0x60401c18 +#ifdef TXBF_SUPPORT + {TX_TXBF_CFG_0, 0x4002FC21}, /* Force MCS2 for sounding response*/ + {TX_TXBF_CFG_1, 0xFE23727F}, + {TX_TXBF_CFG_2, 0xFFFFFFFF}, /* The explicit TxBF feedback is applied only when the value of (local TSF timer) - + (TSF timestamp of the feedback frame) is greater then or equal to 0xFFFFFFFF */ +#endif + {0x210, 0x94ff0000}, + {0x1478, 0x00000004}, + {0x1384, 0x00001818}, + {0x1358, 0xEDCBA980}, + {0x1648, 0x00830083}, /* default use 2 stream to Tx HW auto gened packets */ +}; +static UCHAR mt76x2_mac_cr_nums = (sizeof(mt76x2_mac_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_g_band_cr_table[] = { + {BB_PA_MODE_CFG0, 0x010055FF}, + {BB_PA_MODE_CFG1, 0x00550055}, + {RF_PA_MODE_CFG0, 0x010055FF}, + {RF_PA_MODE_CFG1, 0x00550055}, + {TX_ALC_CFG_2, 0x35160A00}, + {TX_ALC_CFG_3, 0x35160A06}, + {TX_ALC_CFG_4, 0x00000606}, +}; +UCHAR mt76x2_mac_g_band_cr_nums = (sizeof(mt76x2_mac_g_band_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_g_band_internal_pa_cr_table[] = { + {TX0_RF_GAIN_CORR, 0x0F3C3C3C}, + {TX1_RF_GAIN_CORR, 0x0F3C3C3C}, + {TX0_BB_GAIN_ATTEN, 0x00000606}, + {PAMODE_PWR_ADJ0, 0xF4000200}, + {PAMODE_PWR_ADJ1, 0xFA000200}, +}; +UCHAR mt76x2_mac_g_band_internal_pa_cr_nums = (sizeof(mt76x2_mac_g_band_internal_pa_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_g_band_external_pa_cr_table[] = { + {TX0_RF_GAIN_CORR, 0x3C3C023C}, + {TX1_RF_GAIN_CORR, 0x3C3C023C}, + {TX0_BB_GAIN_ATTEN, 0x00001818}, + {PAMODE_PWR_ADJ0, 0x0000EC00}, + {PAMODE_PWR_ADJ1, 0x0000EC00}, +}; +UCHAR mt76x2_mac_g_band_external_pa_cr_nums = (sizeof(mt76x2_mac_g_band_external_pa_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_g_band_external_pa_low_temp_cr_table[] = { + {TX0_RF_GAIN_CORR, 0x3C3C023C}, + {TX1_RF_GAIN_CORR, 0x3C3C023C}, + {TX0_BB_GAIN_ATTEN, 0x00001F1F}, +}; +UCHAR mt76x2_mac_g_band_external_pa_low_temp_cr_nums = (sizeof(mt76x2_mac_g_band_external_pa_low_temp_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_a_band_cr_table[] = { + {BB_PA_MODE_CFG0, 0x0000FFFF}, + {BB_PA_MODE_CFG1, 0x00FF00FF}, + {RF_PA_MODE_CFG0, 0x0000FFFF}, + {RF_PA_MODE_CFG1, 0x00FF00FF}, + {TX_ALC_CFG_4, 0x00000000}, +}; +UCHAR mt76x2_mac_a_band_cr_nums = (sizeof(mt76x2_mac_a_band_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_a_band_internal_pa_cr_table[] = { + {TX0_RF_GAIN_CORR, 0x383C023C}, + {TX1_RF_GAIN_CORR, 0x24282E28}, + {TX0_BB_GAIN_ATTEN, 0x00000000}, + {PAMODE_PWR_ADJ0, 0x00000000}, + {PAMODE_PWR_ADJ1, 0x00000000}, + {TX_ALC_CFG_2, 0x1B0F0400}, + {TX_ALC_CFG_3, 0x1B0F0476}, +}; +UCHAR mt76x2_mac_a_band_internal_pa_cr_nums = (sizeof(mt76x2_mac_a_band_internal_pa_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_a_band_external_pa_cr_table[] = { + {TX0_RF_GAIN_CORR, 0x363C023C}, + {TX1_RF_GAIN_CORR, 0x363C023C}, + {TX0_BB_GAIN_ATTEN, 0x00001818}, + {PAMODE_PWR_ADJ0, 0x04000000}, + {PAMODE_PWR_ADJ1, 0x04000000}, + {TX_ALC_CFG_2, 0x2F0F0400}, + {TX_ALC_CFG_3, 0x2F0F0476}, +}; +UCHAR mt76x2_mac_a_band_external_pa_cr_nums = (sizeof(mt76x2_mac_a_band_external_pa_cr_table) / sizeof(RTMP_REG_PAIR)); + +RTMP_REG_PAIR mt76x2_mac_a_band_external_pa_low_temp_cr_table[] = { + {TX0_RF_GAIN_CORR, 0x363C023C}, + {TX1_RF_GAIN_CORR, 0x363C023C}, + {TX0_BB_GAIN_ATTEN, 0x00001F1F}, + {TX_ALC_CFG_2, 0x2F0F0400}, + {TX_ALC_CFG_3, 0x2F0F0476}, +}; +UCHAR mt76x2_mac_a_band_external_pa_low_temp_cr_nums = (sizeof(mt76x2_mac_a_band_external_pa_low_temp_cr_table) / sizeof(RTMP_REG_PAIR)); + +struct RF_INDEX_OFFSET mt76x2_rf_index_offset[] = { + {0, 0x0000, 0x033c}, + {1, 0x0000, 0x033c}, +}; + +#ifdef CONFIG_CALIBRATION_COLLECTION +void record_calibration_info(RTMP_ADAPTER *pAd, u32 cal_id) +{ + switch(cal_id) + { + case RXDCOC_CALIBRATION_7662: + //RF0 214 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_214] = 0x214; + mt_rf_read(pAd, 0, 0x214, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_214]); + //RF0 218 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_218] = 0x218; + mt_rf_read(pAd, 0, 0x218, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_218]); + //RF0 21C + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_21C] = 0x21C; + mt_rf_read(pAd, 0, 0x21C, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_21C]); + //RF0 220 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_220] = 0x220; + mt_rf_read(pAd, 0, 0x220, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_220]); + //RF0 224 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_224] = 0x224; + mt_rf_read(pAd, 0, 0x224, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_224]); + //RF0 228 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_228] = 0x228; + mt_rf_read(pAd, 0, 0x228, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_228]); + //RF1 214 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_214] = 0x214; + mt_rf_read(pAd, 1, 0x214, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_214]); + //RF1 218 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_218] = 0x218; + mt_rf_read(pAd, 1, 0x218, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_218]); + //RF1 21C + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_21C] = 0x21C; + mt_rf_read(pAd, 1, 0x21C, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_21C]); + //RF1 220 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_220] = 0x220; + mt_rf_read(pAd, 1, 0x220, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_220]); + //RF1 224 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_224] = 0x224; + mt_rf_read(pAd, 1, 0x224, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_224]); + //RF1 228 + pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_228] = 0x228; + mt_rf_read(pAd, 1, 0x228, &pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_228]); + break; + case RC_CALIBRATION_7662: + //RF0 24C + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_24C] = 0x24C; + mt_rf_read(pAd, 0, 0x24C, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_24C]); + //RF0 250 + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_250] = 0x250; + mt_rf_read(pAd, 0, 0x250, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_250]); + //RF0 264 + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_264] = 0x264; + mt_rf_read(pAd, 0, 0x264, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_264]); + //RF0 278 + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_278] = 0x278; + mt_rf_read(pAd, 0, 0x278, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_278]); + //RF1 24C + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_24C] = 0x24C; + mt_rf_read(pAd, 1, 0x24C, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_24C]); + //RF1 250 + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_250] = 0x250; + mt_rf_read(pAd, 1, 0x250, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_250]); + //RF1 264 + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_264] = 0x264; + mt_rf_read(pAd, 1, 0x264, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_264]); + //RF1 278 + pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_278] = 0x278; + mt_rf_read(pAd, 1, 0x278, &pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_278]); + break; + case LC_CALIBRATION_7662: + //BBP 2774 + pAd->calibration_info[LC_CALIBRATION_7662].addr[BBP_2774] = 0x2774; + RTMP_BBP_IO_READ32(pAd, 0x2774, &pAd->calibration_info[LC_CALIBRATION_7662].value[BBP_2774]); + break; + case TX_LOFT_CALIBRATION_7662: + //BBP 2780 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2780] = 0x2780; + RTMP_BBP_IO_READ32(pAd, 0x2780, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2780]); + //BBP 2784 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2784] = 0x2784; + RTMP_BBP_IO_READ32(pAd, 0x2784, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2784]); + //BBP 2788 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2788] = 0x2788; + RTMP_BBP_IO_READ32(pAd, 0x2788, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2788]); + //BBP 278C + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_278C] = 0x278C; + RTMP_BBP_IO_READ32(pAd, 0x278C, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_278C]); + //BBP 2790 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2790] = 0x2790; + RTMP_BBP_IO_READ32(pAd, 0x2790, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2790]); + //BBP 2794 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2794] = 0x2794; + RTMP_BBP_IO_READ32(pAd, 0x2794, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2794]); + //BBP 27A8 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27A8] = 0x27A8; + RTMP_BBP_IO_READ32(pAd, 0x27A8, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27A8]); + //BBP 27AC + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27AC] = 0x27AC; + RTMP_BBP_IO_READ32(pAd, 0x27AC, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27AC]); + //BBP 27B0 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27B0] = 0x27B0; + RTMP_BBP_IO_READ32(pAd, 0x27B0, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B0]); + //BBP 27B4 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27B4] = 0x27B4; + RTMP_BBP_IO_READ32(pAd, 0x27B4, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B4]); + //BBP 27B8 + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27B8] = 0x27B8; + RTMP_BBP_IO_READ32(pAd, 0x27B8, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B8]); + //BBP 27BC + pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27BC] = 0x27BC; + RTMP_BBP_IO_READ32(pAd, 0x27BC, &pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27BC]); + break; + case TXIQ_CALIBRATION_7662: + //BBP 2798 + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_2798] = 0x2798; + RTMP_BBP_IO_READ32(pAd, 0x2798, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_2798]); + //BBP 279C + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_279C] = 0x279C; + RTMP_BBP_IO_READ32(pAd, 0x279C, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_279C]); + //BBP 27A0 + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27A0] = 0x27A0; + RTMP_BBP_IO_READ32(pAd, 0x27A0, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27A0]); + //BBP 27A4 + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27A4] = 0x27A4; + RTMP_BBP_IO_READ32(pAd, 0x27A4, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27A4]); + //BBP 27C0 + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27C0] = 0x27C0; + RTMP_BBP_IO_READ32(pAd, 0x27C0, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C0]); + //BBP 27C4 + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27C4] = 0x27C4; + RTMP_BBP_IO_READ32(pAd, 0x27C4, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C4]); + //BBP 27C8 + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27C8] = 0x27C8; + RTMP_BBP_IO_READ32(pAd, 0x27C8, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C8]); + //BBP 27CC + pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27CC] = 0x27CC; + RTMP_BBP_IO_READ32(pAd, 0x27CC, &pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27CC]); + break; + case TSSI_CALIBRATION_7662: + //BBP 208C + pAd->calibration_info[TSSI_CALIBRATION_7662].addr[BBP_208C] = 0x208C; + RTMP_BBP_IO_READ32(pAd, 0x208C, &pAd->calibration_info[TSSI_CALIBRATION_7662].value[BBP_208C]); + break; + case DPD_CALIBRATION_7662: + //BBP 2720 + pAd->calibration_info[DPD_CALIBRATION_7662].addr[BBP_2720] = 0x2720; + RTMP_BBP_IO_READ32(pAd, 0x2720, &pAd->calibration_info[DPD_CALIBRATION_7662].value[BBP_2720]); + break; + case RXIQC_FI_CALIBRATION_7662: + //BBP 2C60 + pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C60] = 0x2C60; + RTMP_BBP_IO_READ32(pAd, 0x2C60, &pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C60]); + //BBP 2C64 + pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C64] = 0x2C64; + RTMP_BBP_IO_READ32(pAd, 0x2C64, &pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C64]); + //BBP 2C70 + pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C70] = 0x2C70; + RTMP_BBP_IO_READ32(pAd, 0x2C70, &pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C70]); + //BBP 2C74 + pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C74] = 0x2C74; + RTMP_BBP_IO_READ32(pAd, 0x2C74, &pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C74]); + break; + case RXIQC_FD_CALIBRATION_7662: + //BBP 2818 + pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2818] = 0x2818; + RTMP_BBP_IO_READ32(pAd, 0x2818, &pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2818]); + //BBP 281C + pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_281C] = 0x281C; + RTMP_BBP_IO_READ32(pAd, 0x281C, &pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_281C]); + //BBP 2820 + pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2820] = 0x2820; + RTMP_BBP_IO_READ32(pAd, 0x2820, &pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2820]); + //BBP 2824 + pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2824] = 0x2824; + RTMP_BBP_IO_READ32(pAd, 0x2824, &pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2824]); + //BBP 2828 + pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2828] = 0x2828; + RTMP_BBP_IO_READ32(pAd, 0x2828, &pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2828]); + //BBP 282C + pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_282C] = 0x282C; + RTMP_BBP_IO_READ32(pAd, 0x282C, &pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_282C]); + break; + default: + break; + } +} + +void dump_calibration_info_for_robust(RTMP_ADAPTER *pAd, UINT32 cal_id) +{ + switch(cal_id) { + case RXDCOC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_214], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_218], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_21C], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_220], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_224], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_228], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_214], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_218], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_21C], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_220], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_224], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_228])); + break; + case RC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_24C], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_250], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_264], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_278], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_24C], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_250], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_264], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_278])); + break; + case LC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x\n", pAd->calibration_info[LC_CALIBRATION_7662].value[BBP_2774])); + + break; + case TX_LOFT_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2780], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2784], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2788], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_278C], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2790], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2794], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27A8], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27AC], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B0], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B4], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B8], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27BC])); + break; + case TXIQ_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_2798], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_279C], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27A0], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27A4], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C0], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C4], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C8], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27CC])); + break; + case TSSI_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x\n", pAd->calibration_info[TSSI_CALIBRATION_7662].value[BBP_208C])); + + break; + case DPD_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x\n", pAd->calibration_info[DPD_CALIBRATION_7662].value[BBP_2720])); + break; + case RXIQC_FI_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x 0x%08x 0x%08x 0x%08x\n", pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C60], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C64], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C70], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C74])); + break; + case RXIQC_FD_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2818], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_281C], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2820], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2824], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2828], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_282C])); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("unknbow cal id = %d\n", cal_id)); + break; + } + +} + +void do_calibrtion_info_for_robust(RTMP_ADAPTER *ad, UINT32 cal_id, UINT8 channel) +{ + UINT32 i; + + switch(cal_id) { + case RXDCOC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nRXDCOC_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("RF0_214 RF0_218 RF0_21C RF0_220 RF0_224 RF0_228 RF1_214 RF1_218 RF1_21C RF1_220 RF1_224 RF1_228\n")); + for (i = 0; i < 100; i++) { + CHIP_CALIBRATION(ad, RXDCOC_CALIBRATION_7662, channel); + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + + break; + case RC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nRC_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("RF0_24C RF0_250 RF0_264 RF0_278 RF1_24C RF1_250 RF1_264 RF1_278\n")); + for (i = 0; i < 100; i++) { + CHIP_CALIBRATION(ad, RC_CALIBRATION_7662, 0x00); + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + break; + case LC_CALIBRATION_7662: + if (channel > 14) { + DBGPRINT(RT_DEBUG_OFF, ("\nLC_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("BBP2774\n")); + for (i = 0; i < 100; i++) { + CHIP_CALIBRATION(ad, LC_CALIBRATION_7662, 0x00); + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + } + break; + case TX_LOFT_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nTXLOFT_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("BBP2780 BBP2784 BBP2788 BBP278C BBP2790 BBP2794 BBP27A8 BBP27AC BBP27B0 BBP27B4 BBP27B8 BBP27BC\n")); + for (i = 0; i < 100; i++) { + if (channel > 14) { + CHIP_CALIBRATION(ad, TX_LOFT_CALIBRATION_7662, 0x1); + } else { + CHIP_CALIBRATION(ad, TX_LOFT_CALIBRATION_7662, 0x0); + } + + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + break; + case TXIQ_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nTXIQ_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("BBP2798 BBP279C BBP27A0 BBP27A4 BBP27C0 BBP27C4 BBP27C8 BBP27CC\n")); + for (i = 0; i < 100; i++) { + if (channel > 14) { + CHIP_CALIBRATION(ad, TXIQ_CALIBRATION_7662, 0x1); + } else { + CHIP_CALIBRATION(ad, TXIQ_CALIBRATION_7662, 0x0); + } + + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + break; + case TSSI_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nTSSI_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("BBP208C\n")); + for (i = 0; i < 100; i++) { + mt76x2_tssi_calibration(ad, channel); + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + break; + case DPD_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nDPD_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("BBP2720\n")); + for (i = 0; i < 100; i++) { + CHIP_CALIBRATION(ad, DPD_CALIBRATION_7662, channel); + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + break; + case RXIQC_FI_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nRXIQC_FI_Calibration\n")); + DBGPRINT(RT_DEBUG_OFF, ("BBP2C60 BBP2C64 BBP2C70 BBP2C74\n")); + for (i = 0; i < 100; i++) { + if (channel > 14) { + CHIP_CALIBRATION(ad, RXIQC_FI_CALIBRATION_7662, 0x1); + } else { + CHIP_CALIBRATION(ad, RXIQC_FI_CALIBRATION_7662, 0x0); + } + record_calibration_info(ad, cal_id); + dump_calibration_info_for_robust(ad, cal_id); + } + break; + case RXIQC_FD_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_OFF, ("\nnot supoort RXIQC_FD_CALIBRATION_7662 yet\n")); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("\nunknbow cal id = %d\n", cal_id)); + break; + } +} + +void dump_calibration_info(RTMP_ADAPTER *pAd, u32 cal_id) +{ + switch(cal_id) + { + case RXDCOC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nRXDCOC_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_214], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_214])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_218], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_218])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_21C], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_21C])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_220], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_220])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_224], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_224])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF0_228], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF0_228])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_214], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_214])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_218], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_218])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_21C], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_21C])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_220], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_220])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_224], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_224])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RXDCOC_CALIBRATION_7662].addr[RF1_228], pAd->calibration_info[RXDCOC_CALIBRATION_7662].value[RF1_228])); + break; + case RC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nRC_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_24C], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_24C])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_250], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_250])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_264], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_264])); + DBGPRINT(RT_DEBUG_ERROR, ("RF0[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF0_278], pAd->calibration_info[RC_CALIBRATION_7662].value[RF0_278])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_24C], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_24C])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_250], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_250])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_264], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_264])); + DBGPRINT(RT_DEBUG_ERROR, ("RF1[0x%04x]=0x%08x\n", pAd->calibration_info[RC_CALIBRATION_7662].addr[RF1_278], pAd->calibration_info[RC_CALIBRATION_7662].value[RF1_278])); + break; + case LC_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nLC_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[LC_CALIBRATION_7662].addr[BBP_2774], pAd->calibration_info[LC_CALIBRATION_7662].value[BBP_2774])); + break; + case TX_LOFT_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nTX_LOFT_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2780], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2780])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2784], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2784])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2788], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2788])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_278C], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_278C])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2790], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2790])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_2794], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_2794])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27A8], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27A8])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27AC], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27AC])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27B0], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B0])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27B4], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B4])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27B8], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27B8])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TX_LOFT_CALIBRATION_7662].addr[BBP_27BC], pAd->calibration_info[TX_LOFT_CALIBRATION_7662].value[BBP_27BC])); + break; + case TXIQ_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nTXIQ_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_2798], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_2798])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_279C], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_279C])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27A0], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27A0])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27A4], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27A4])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27C0], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C0])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27C4], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C4])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27C8], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27C8])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TXIQ_CALIBRATION_7662].addr[BBP_27CC], pAd->calibration_info[TXIQ_CALIBRATION_7662].value[BBP_27CC])); + break; + case TSSI_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nTSSI_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[TSSI_CALIBRATION_7662].addr[BBP_208C], pAd->calibration_info[TSSI_CALIBRATION_7662].value[BBP_208C])); + break; + case DPD_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nDPD_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[DPD_CALIBRATION_7662].addr[BBP_2720], pAd->calibration_info[DPD_CALIBRATION_7662].value[BBP_2720])); + break; + case RXIQC_FI_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nRXIQC_FI_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C60], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C60])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C64], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C64])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C70], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C70])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].addr[BBP_2C74], pAd->calibration_info[RXIQC_FI_CALIBRATION_7662].value[BBP_2C74])); + break; + case RXIQC_FD_CALIBRATION_7662: + DBGPRINT(RT_DEBUG_ERROR, ("\nRXIQC_FD_CALIBRATION_7662\n")); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2818], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2818])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_281C], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_281C])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2820], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2820])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2824], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2824])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_2828], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_2828])); + DBGPRINT(RT_DEBUG_ERROR, ("BBP[0x%04x]=0x%08x\n", pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].addr[BBP_282C], pAd->calibration_info[RXIQC_FD_CALIBRATION_7662].value[BBP_282C])); + break; + default: + break; + } +} +#endif + +static VOID mt76x2_bbp_adjust(RTMP_ADAPTER *pAd) +{ + static char *ext_str[]={"extNone", "extAbove", "", "extBelow"}; + UCHAR 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; + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_AC) && + (pAd->CommonCfg.Channel > 14) && + (rf_bw == BW_40) && + (pAd->CommonCfg.vht_bw == VHT_BW_80) && + (pAd->CommonCfg.vht_cent_ch != pAd->CommonCfg.CentralChannel)) + { + rf_bw = BW_80; + pAd->CommonCfg.vht_cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + } + + DBGPRINT(RT_DEBUG_OFF, ("%s():rf_bw=%d, ext_ch=%d, PrimCh=%d, HT-CentCh=%d, VHT-CentCh=%d\n", + __FUNCTION__, rf_bw, ext_ch, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel, pAd->CommonCfg.vht_cent_ch)); +#endif /* DOT11_VHT_AC */ + + bbp_set_bw(pAd, rf_bw); + + /* TX/Rx : control channel setting */ + rtmp_mac_set_ctrlch(pAd, ext_ch); + bbp_set_ctrlch(pAd, ext_ch); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s() : %s, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + __FUNCTION__, ext_str[ext_ch], + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ +} + +int get_chl_grp(u8 channel) +{ + int chl_grp = A_BAND_GRP0_CHL; + + if (channel >= 184 && channel <= 196) + chl_grp = A_BAND_GRP0_CHL; + else if (channel >= 36 && channel <= 48) + chl_grp = A_BAND_GRP1_CHL; + else if (channel >= 52 && channel <= 64) + chl_grp = A_BAND_GRP2_CHL; + else if (channel >= 98 && channel <= 114) + chl_grp = A_BAND_GRP3_CHL; + else if (channel >= 116 && channel <= 144) + chl_grp = A_BAND_GRP4_CHL; + else if (channel >= 149 && channel <= 165) + chl_grp = A_BAND_GRP5_CHL; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:illegal channel (%d)\n", __FUNCTION__, channel)); + + return chl_grp; +} + +int get_low_mid_hi_index(u8 channel) +{ + int index = G_BAND_LOW; + + if (channel <= 14) { + if (channel >= 1 && channel <= 5) + index = G_BAND_LOW; + else if (channel >= 6 && channel <= 10) + index = G_BAND_MID; + else if (channel >= 11 && channel <= 14) + index = G_BAND_HI; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:illegal channel(%d)\n", __FUNCTION__, channel)); + } else { + if (channel >= 184 && channel <= 188) + index = A_BAND_LOW; + else if (channel >= 192 && channel <= 196) + index = A_BAND_HI; + else if (channel >= 36 && channel <= 42) + index = A_BAND_LOW; + else if (channel >= 44 && channel <= 48) + index = A_BAND_HI; + else if (channel >= 52 && channel <= 56) + index = A_BAND_LOW; + else if (channel >= 58 && channel <= 64) + index = A_BAND_HI; + else if (channel >= 98 && channel <= 104) + index = A_BAND_LOW; + else if (channel >= 106 && channel <= 114) + index = A_BAND_HI; + else if (channel >= 116 && channel <= 128) + index = A_BAND_LOW; + else if (channel >= 130 && channel <= 144) + index = A_BAND_HI; + else if (channel >= 149 && channel <= 156) + index = A_BAND_LOW; + else if (channel >= 157 && channel <= 165) + index = A_BAND_HI; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:illegal channel(%d)\n", __FUNCTION__, channel)); + } + + return index; +} + +void mt76x2_adjust_per_rate_pwr_delta(RTMP_ADAPTER *ad, u8 channel, char delta_pwr) +{ + u32 value; + RTMP_CHIP_CAP *cap = &ad->chipCap; + unsigned int band; + DBGPRINT(RT_DEBUG_TRACE, ("\n%s ========> \n",__FUNCTION__)); + if (channel > 14) + band = _A_BAND; + else + band = _G_BAND; + + RTMP_IO_READ32(ad, TX_PWR_CFG_0, &value); + + value &= ~TX_PWR_CCK_1_2_MASK; + value |= TX_PWR_CCK_1_2(cap->tx_pwr_cck_1_2 + delta_pwr + cap->tx_pwr_cck_1_2_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_cck_1_2_compensate %d \n",cap->tx_pwr_cck_1_2_compensate)); + + value &= ~TX_PWR_CCK_5_11_MASK; + value |= TX_PWR_CCK_5_11(cap->tx_pwr_cck_5_11 + delta_pwr + cap->tx_pwr_cck_5_11_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_cck_5_11_compensate %d \n",cap->tx_pwr_cck_5_11_compensate)); + + value &= ~TX_PWR_OFDM_6_9_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_OFDM_6_9(cap->tx_pwr_g_band_ofdm_6_9 + delta_pwr + cap->tx_pwr_g_band_ofdm_6_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_g_band_ofdm_6_9_compensate %d \n",cap->tx_pwr_g_band_ofdm_6_9_compensate)); + } + else + { + value |= TX_PWR_OFDM_6_9(cap->tx_pwr_a_band_ofdm_6_9 + delta_pwr + cap->tx_pwr_a_band_ofdm_6_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_a_band_ofdm_6_9_compensate %d \n",cap->tx_pwr_a_band_ofdm_6_9_compensate)); + } + + value &= ~TX_PWR_OFDM_12_18_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_OFDM_12_18(cap->tx_pwr_g_band_ofdm_12_18 + delta_pwr + cap->tx_pwr_g_band_ofdm_12_18_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_g_band_ofdm_12_18_compensate %d \n",cap->tx_pwr_g_band_ofdm_12_18_compensate)); + } + else + { + value |= TX_PWR_OFDM_12_18(cap->tx_pwr_a_band_ofdm_12_18 + delta_pwr + cap->tx_pwr_a_band_ofdm_12_18_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_a_band_ofdm_12_18_compensate %d \n",cap->tx_pwr_a_band_ofdm_12_18_compensate)); + } + RTMP_IO_WRITE32(ad, TX_PWR_CFG_0, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_1, &value); + value &= ~TX_PWR_OFDM_24_36_MASK; + if (band == _G_BAND) + value |= TX_PWR_OFDM_24_36(cap->tx_pwr_g_band_ofdm_24_36 + delta_pwr); + else + value |= TX_PWR_OFDM_24_36(cap->tx_pwr_a_band_ofdm_24_36 + delta_pwr); + + value &= ~TX_PWR_OFDM_48_MASK; + if (band == _G_BAND) + value |= TX_PWR_OFDM_48(cap->tx_pwr_g_band_ofdm_48_54 + delta_pwr); + else + value |= TX_PWR_OFDM_48(cap->tx_pwr_a_band_ofdm_48_54 + delta_pwr); + + value &= ~TX_PWR_HT_VHT_1SS_MCS_0_1_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_HT_VHT_1SS_MCS_0_1(cap->tx_pwr_ht_mcs_0_1 + delta_pwr + cap->tx_pwr_g_band_ht_mcs_0_1_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_g_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_g_band_ht_mcs_0_1_compensate)); + } + else + { + value |= TX_PWR_HT_VHT_1SS_MCS_0_1(cap->tx_pwr_ht_mcs_0_1 + delta_pwr + cap->tx_pwr_a_band_ht_mcs_0_1_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_a_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_a_band_ht_mcs_0_1_compensate)); + } + + value &= ~TX_PWR_HT_VHT_1SS_MCS_2_3_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_HT_VHT_1SS_MCS_2_3(cap->tx_pwr_ht_mcs_2_3 + delta_pwr + cap->tx_pwr_g_band_ht_mcs_2_3_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_g_band_ht_mcs_2_3_compensate %d \n",cap->tx_pwr_g_band_ht_mcs_2_3_compensate)); + } + else + { + value |= TX_PWR_HT_VHT_1SS_MCS_2_3(cap->tx_pwr_ht_mcs_2_3 + delta_pwr + cap->tx_pwr_a_band_ht_mcs_2_3_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("cap->tx_pwr_a_band_ht_mcs_2_3_compensate %d \n",cap->tx_pwr_a_band_ht_mcs_2_3_compensate)); + } + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_1, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_2, &value); + value &= ~TX_PWR_HT_VHT_1SS_MCS_4_5_MASK; + value |= TX_PWR_HT_VHT_1SS_MCS_4_5(cap->tx_pwr_ht_mcs_4_5 + delta_pwr); + + value &= ~TX_PWR_HT_VHT_1SS_MCS_6_MASK; + value |= TX_PWR_HT_VHT_1SS_MCS_6(cap->tx_pwr_ht_mcs_6_7 + delta_pwr); + + value &= ~TX_PWR_HT_MCS_8_9_VHT_2SS_0_1_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_HT_MCS_8_9_VHT_2SS_0_1(cap->tx_pwr_ht_mcs_8_9 + delta_pwr + cap->tx_pwr_g_band_ht_mcs_0_1_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_MCS_8_9_VHT_2SS_0_1 cap->tx_pwr_g_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_g_band_ht_mcs_0_1_compensate)); + } + else + { + value |= TX_PWR_HT_MCS_8_9_VHT_2SS_0_1(cap->tx_pwr_ht_mcs_8_9 + delta_pwr + cap->tx_pwr_a_band_ht_mcs_0_1_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_MCS_8_9_VHT_2SS_0_1 cap->tx_pwr_a_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_a_band_ht_mcs_0_1_compensate)); + } + + value &= ~TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3(cap->tx_pwr_ht_mcs_10_11 + delta_pwr + cap->tx_pwr_g_band_ht_mcs_2_3_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_MCS_8_9_VHT_2SS_0_1 cap->tx_pwr_g_band_ht_mcs_2_3_compensate %d \n",cap->tx_pwr_g_band_ht_mcs_2_3_compensate)); + } + else + { + value |= TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3(cap->tx_pwr_ht_mcs_10_11 + delta_pwr + cap->tx_pwr_a_band_ht_mcs_2_3_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_MCS_8_9_VHT_2SS_0_1 cap->tx_pwr_a_band_ht_mcs_2_3_compensate %d \n",cap->tx_pwr_a_band_ht_mcs_2_3_compensate)); + } + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_2, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_3, &value); + value &= ~TX_PWR_HT_MCS_12_13_VHT_2SS_MCS_4_5_MASK; + value |= TX_PWR_HT_MCS_12_13_VHT_2SS_MCS_4_5(cap->tx_pwr_ht_mcs_12_13 + delta_pwr); + + value &= ~TX_PWR_HT_MCS_14_VHT_2SS_MCS_6_MASK; + value |= TX_PWR_HT_MCS_14_VHT_2SS_MCS_6(cap->tx_pwr_ht_mcs_14_15 + delta_pwr); + + value &= ~TX_PWR_HT_VHT_STBC_MCS_0_1_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_HT_VHT_STBC_MCS_0_1(cap->tx_pwr_ht_mcs_0_1 + delta_pwr + cap->tx_pwr_g_band_ht_mcs_0_1_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_VHT_STBC_MCS_0_1 cap->tx_pwr_g_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_g_band_ht_mcs_0_1_compensate)); + } + else + { + value |= TX_PWR_HT_VHT_STBC_MCS_0_1(cap->tx_pwr_ht_mcs_0_1 + delta_pwr + cap->tx_pwr_a_band_ht_mcs_0_1_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_VHT_STBC_MCS_0_1 cap->tx_pwr_a_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_a_band_ht_mcs_0_1_compensate)); + } + + value &= ~TX_PWR_HT_VHT_STBC_MCS_2_3_MASK; + if (band == _G_BAND) + { + value |= TX_PWR_HT_VHT_STBC_MCS_2_3(cap->tx_pwr_ht_mcs_2_3 + delta_pwr + cap->tx_pwr_g_band_ht_mcs_2_3_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_VHT_STBC_MCS_2_3 cap->tx_pwr_g_band_ht_mcs_0_1_compensate %d \n",cap->tx_pwr_g_band_ht_mcs_2_3_compensate)); + } + else + { + value |= TX_PWR_HT_VHT_STBC_MCS_2_3(cap->tx_pwr_ht_mcs_2_3 + delta_pwr + cap->tx_pwr_a_band_ht_mcs_2_3_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_HT_VHT_STBC_MCS_2_3 cap->tx_pwr_a_band_ht_mcs_2_3_compensate %d \n",cap->tx_pwr_a_band_ht_mcs_2_3_compensate)); + } + RTMP_IO_WRITE32(ad, TX_PWR_CFG_3, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_4, &value); + value &= ~TX_PWR_HT_VHT_STBC_MCS_4_5_MASK; + value |= TX_PWR_HT_VHT_STBC_MCS_4_5(cap->tx_pwr_ht_mcs_4_5 + delta_pwr); + + value &= ~TX_PWR_HT_VHT_STBC_MCS_6_MASK; + value |= TX_PWR_HT_VHT_STBC_MCS_6(cap->tx_pwr_ht_mcs_6_7 + delta_pwr); + RTMP_IO_WRITE32(ad, TX_PWR_CFG_4, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_7, &value); + value &= ~TX_PWR_OFDM_54_MASK; + if (band == _G_BAND) + value |= TX_PWR_OFDM_54(cap->tx_pwr_g_band_ofdm_48_54 + delta_pwr); + else + value |= TX_PWR_OFDM_54(cap->tx_pwr_a_band_ofdm_48_54 + delta_pwr); + + value &= ~TX_PWR_VHT_2SS_MCS_8_MASK; + if (band == _G_BAND) + value |= TX_PWR_VHT_2SS_MCS_8(cap->tx_pwr_2g_vht_mcs_8_9 + delta_pwr); + else + { + value |= TX_PWR_VHT_2SS_MCS_8(cap->tx_pwr_5g_vht_mcs_8_9 + delta_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_VHT_2SS_MCS_8 cap->tx_pwr_5g_vht_mcs_8_9_compensate %d \n",cap->tx_pwr_5g_vht_mcs_8_9_compensate)); + } + + value &= ~TX_PWR_HT_MCS_7_VHT_1SS_MCS_7_MASK; + value |= TX_PWR_HT_MCS_7_VHT_1SS_MCS_7(cap->tx_pwr_ht_mcs_6_7 + delta_pwr); + + value &= ~TX_PWR_VHT_2SS_MCS_9_MASK; + if (band == _G_BAND) + value |= TX_PWR_VHT_2SS_MCS_9(cap->tx_pwr_2g_vht_mcs_8_9 + delta_pwr); + else + { + value |= TX_PWR_VHT_2SS_MCS_9(cap->tx_pwr_5g_vht_mcs_8_9 + delta_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_VHT_2SS_MCS_9 cap->tx_pwr_5g_vht_mcs_8_9_compensate %d \n",cap->tx_pwr_5g_vht_mcs_8_9_compensate)); + } + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_7, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_8, &value); + value &= ~TX_PWR_HT_MCS_15_VHT_2SS_MCS7_MASK; + value |= TX_PWR_HT_MCS_15_VHT_2SS_MCS7(cap->tx_pwr_ht_mcs_14_15 + delta_pwr); + + value &= ~TX_PWR_VHT_1SS_MCS_8_MASK; + if (band == _G_BAND) + value |= TX_PWR_VHT_1SS_MCS_8(cap->tx_pwr_2g_vht_mcs_8_9 + delta_pwr); + else + { + value |= TX_PWR_VHT_1SS_MCS_8(cap->tx_pwr_5g_vht_mcs_8_9 + delta_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_VHT_1SS_MCS_8 cap->tx_pwr_5g_vht_mcs_8_9_compensate %d \n",cap->tx_pwr_5g_vht_mcs_8_9_compensate)); + } + + value &= ~TX_PWR_VHT_1SS_MCS_9_MASK; + if (band == _G_BAND) + value |= TX_PWR_VHT_1SS_MCS_9(cap->tx_pwr_2g_vht_mcs_8_9 + delta_pwr); + else + { + value |= TX_PWR_VHT_1SS_MCS_9(cap->tx_pwr_5g_vht_mcs_8_9 + delta_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_VHT_1SS_MCS_8 cap->tx_pwr_5g_vht_mcs_8_9_compensate %d \n",cap->tx_pwr_5g_vht_mcs_8_9_compensate)); + } + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_8, value); + + RTMP_IO_READ32(ad, TX_PWR_CFG_9, &value); + value &= ~TX_PWR_HT_VHT_STBC_MCS_7_MASK; + value |= TX_PWR_HT_VHT_STBC_MCS_7(cap->tx_pwr_ht_mcs_6_7 + delta_pwr); + + value &= ~TX_PWR_VHT_STBC_MCS_8_MASK; + if (band == _G_BAND) + value |= TX_PWR_VHT_STBC_MCS_8(cap->tx_pwr_2g_vht_mcs_8_9 + delta_pwr); + else + { + value |= TX_PWR_VHT_STBC_MCS_8(cap->tx_pwr_5g_vht_mcs_8_9 + delta_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_VHT_STBC_MCS_8 cap->tx_pwr_5g_vht_mcs_8_9_compensate %d \n",cap->tx_pwr_5g_vht_mcs_8_9_compensate)); + } + + value &= ~TX_PWR_VHT_STBC_MCS_9_MASK; + if (band == _G_BAND) + value |= TX_PWR_VHT_STBC_MCS_9(cap->tx_pwr_2g_vht_mcs_8_9 + delta_pwr); + else + { + value |= TX_PWR_VHT_STBC_MCS_9(cap->tx_pwr_5g_vht_mcs_8_9 + delta_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate); + DBGPRINT(RT_DEBUG_TRACE, ("TX_PWR_VHT_STBC_MCS_9 cap->tx_pwr_5g_vht_mcs_8_9_compensate %d \n",cap->tx_pwr_5g_vht_mcs_8_9_compensate)); + } + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_9, value); +} + +void mt76x2_tx_pwr_gain(RTMP_ADAPTER *ad, u8 channel, u8 bw) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + CHAR tx_0_pwr, tx_1_pwr; + UINT32 value; + + /* set 54Mbps target power */ + if (channel <= 14) { + tx_0_pwr = cap->tx_0_target_pwr_g_band; + tx_0_pwr += cap->tx_0_chl_pwr_delta_g_band[get_low_mid_hi_index(channel)]; + if (bw == BW_40) + tx_0_pwr += cap->delta_tx_pwr_bw40_g_band; + + tx_1_pwr = cap->tx_1_target_pwr_g_band; + tx_1_pwr += cap->tx_1_chl_pwr_delta_g_band[get_low_mid_hi_index(channel)]; + if (bw == BW_40) + tx_1_pwr += cap->delta_tx_pwr_bw40_g_band; + + } else { + tx_0_pwr = cap->tx_0_target_pwr_a_band[get_chl_grp(channel)]; + tx_0_pwr += cap->tx_0_chl_pwr_delta_a_band[get_chl_grp(channel)][get_low_mid_hi_index(channel)]; + + if (bw == BW_40) + tx_0_pwr += cap->delta_tx_pwr_bw40_a_band; + else if (bw == BW_80) + tx_0_pwr += cap->delta_tx_pwr_bw80; + + tx_1_pwr = cap->tx_1_target_pwr_a_band[get_chl_grp(channel)]; + tx_1_pwr += cap->tx_1_chl_pwr_delta_a_band[get_chl_grp(channel)][get_low_mid_hi_index(channel)]; + + if (bw == BW_40) + tx_1_pwr += cap->delta_tx_pwr_bw40_a_band; + else if (bw == BW_80) + tx_1_pwr += cap->delta_tx_pwr_bw80; + } + + /* range 0~23.5 db */ + if (tx_0_pwr >= 0x2f) + tx_0_pwr = 0x2f; + + if (tx_0_pwr < 0) + tx_0_pwr = 0; + + if (tx_1_pwr >= 0x2f) + tx_1_pwr = 0x2f; + + if (tx_1_pwr < 0) + tx_1_pwr = 0; + + /* TX0 channel initial transmission gain setting */ + RTMP_IO_READ32(ad, TX_ALC_CFG_0, &value); + value = value & (~TX_ALC_CFG_0_CH_INT_0_MASK); + value |= TX_ALC_CFG_0_CH_INT_0(tx_0_pwr); + //value |= TX_ALC_CFG_0_CH_INT_0(0x7); + DBGPRINT(RT_DEBUG_INFO, ("tx_0_pwr = %d\n", tx_0_pwr)); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_0, value); + + /* TX1 channel initial transmission gain setting */ + RTMP_IO_READ32(ad, TX_ALC_CFG_0, &value); + value = value & (~TX_ALC_CFG_0_CH_INT_1_MASK); + value |= TX_ALC_CFG_0_CH_INT_1(tx_1_pwr); + //value |= TX_ALC_CFG_0_CH_INT_1(0x7); + DBGPRINT(RT_DEBUG_INFO, ("tx_1_pwr = %d\n", tx_1_pwr)); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_0, value); +} + +#define EXT_CH_NONE 0x00 +#define EXT_CH_ABOVE 0X01 +#define EXT_CH_BELOW 0x03 + +static void mt76x2_switch_channel(RTMP_ADAPTER *ad, u8 channel, BOOLEAN scan) +{ + unsigned int latch_band, band, bw, tx_rx_setting; + UINT32 i, value, value1, restore_value, loop = 0; + UINT16 e2p_value; + UCHAR bbp_ch_idx; + BOOLEAN band_change = FALSE; + UINT32 RegValue = 0; + UINT32 eLNA_gain_from_e2p = 0; + BOOLEAN bEdcca = FALSE; + UINT32 mac_val = 0; + + +#ifdef DOT11_VHT_AC + if (ad->CommonCfg.BBPCurrentBW == BW_80) { + bbp_ch_idx = vht_prim_ch_idx(channel, ad->CommonCfg.Channel); + } else +#endif /* DOT11_VHT_AC */ + if (ad->CommonCfg.BBPCurrentBW == BW_40) { + if (ad->CommonCfg.CentralChannel > ad->CommonCfg.Channel) + bbp_ch_idx = EXT_CH_ABOVE; + else + bbp_ch_idx = EXT_CH_BELOW; + } else { + bbp_ch_idx = EXT_CH_NONE; + } + + RTMP_IO_READ32(ad, EXT_CCA_CFG, &RegValue); + RegValue &= ~(0xFFF); +#ifdef DOT11_VHT_AC + if (ad->CommonCfg.BBPCurrentBW == BW_80) + { + if (bbp_ch_idx == 0) + { + RegValue |= 0x1e4; + } + else if (bbp_ch_idx == 1) + { + RegValue |= 0x2e1; + } + else if (bbp_ch_idx == 2) + { + RegValue |= 0x41e; + } + else if (bbp_ch_idx == 3) + { + RegValue |= 0x81b; + } + } else +#endif /* DOT11_VHT_AC */ + if (ad->CommonCfg.BBPCurrentBW == BW_40) + { + if (ad->CommonCfg.CentralChannel > ad->CommonCfg.Channel) + RegValue |= 0x1e4; + else + RegValue |= 0x2e1; + } + else + { + RegValue |= 0x1e4; + } + RTMP_IO_WRITE32(ad, EXT_CCA_CFG, RegValue); + + /* determine channel flags */ + if (channel > 14) + band = _A_BAND; + else + band = _G_BAND; + + if (!ad->MCUCtrl.power_on) { + band_change = TRUE; + } else { + if (ad->LatchRfRegs.Channel > 14) + latch_band = _A_BAND; + else + latch_band = _G_BAND; + + if (band != latch_band) + band_change = TRUE; + else + band_change = FALSE; + } + + if (ad->CommonCfg.BBPCurrentBW == BW_80) + bw = 2; + else if (ad->CommonCfg.BBPCurrentBW == BW_40) + bw = 1; + else + bw = 0; + + /* Change MAC OFDM SIFS according to BW */ + RTMP_IO_READ32(ad, XIFS_TIME_CFG, &RegValue); + RegValue = RegValue & (~XIFS_TIME_OFDM_SIFS_MASK); + if ( +#ifdef DOT11_VHT_AC + (WMODE_CAP_AC(ad->CommonCfg.PhyMode) && (ad->CommonCfg.vht_ldpc == TRUE)) || +#endif + (WMODE_CAP_N(ad->CommonCfg.PhyMode) && (ad->CommonCfg.ht_ldpc == TRUE))) + { + if (bw == 0) + RegValue |= XIFS_TIME_OFDM_SIFS(0x0D); + else /* 40/80Mhz */ + RegValue |= XIFS_TIME_OFDM_SIFS(0x0E); + } + else + RegValue |= XIFS_TIME_OFDM_SIFS(0x0C); + RTMP_IO_WRITE32(ad, XIFS_TIME_CFG, RegValue); + + + if ((ad->CommonCfg.TxStream == 1) && (ad->CommonCfg.RxStream == 1)) + tx_rx_setting = 0x101; + else if ((ad->CommonCfg.TxStream == 2) && (ad->CommonCfg.RxStream == 2)) + tx_rx_setting = 0x202; + else + tx_rx_setting = 0x202; + + +#ifdef RTMP_PCI_SUPPORT + /* mac setting per band */ + if (IS_PCI_INF(ad)) { + if (band_change) { + if (band == _G_BAND) { + for(i = 0; i < mt76x2_mac_g_band_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_g_band_cr_table[i].Register, + mt76x2_mac_g_band_cr_table[i].Value); + } + if ( ad->chipCap.PAType & INT_PA_2G ) { + for(i = 0; i < mt76x2_mac_g_band_internal_pa_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_g_band_internal_pa_cr_table[i].Register, + mt76x2_mac_g_band_internal_pa_cr_table[i].Value); + } + } else { + for(i = 0; i < mt76x2_mac_g_band_external_pa_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_g_band_external_pa_cr_table[i].Register, + mt76x2_mac_g_band_external_pa_cr_table[i].Value); + } + } + } else { + for(i = 0; i < mt76x2_mac_a_band_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_a_band_cr_table[i].Register, + mt76x2_mac_a_band_cr_table[i].Value); + } + if ( ad->chipCap.PAType & INT_PA_5G ) { + for(i = 0; i < mt76x2_mac_a_band_internal_pa_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_a_band_internal_pa_cr_table[i].Register, + mt76x2_mac_a_band_internal_pa_cr_table[i].Value); + } + } else { + for(i = 0; i < mt76x2_mac_a_band_external_pa_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_a_band_external_pa_cr_table[i].Register, + mt76x2_mac_a_band_external_pa_cr_table[i].Value); + } + } + } + } + } +#endif + +#ifdef DYNAMIC_VGA_SUPPORT + ad->chipCap.dynamic_chE_mode = 0xEE; +#endif /* DYNAMIC_VGA_SUPPORT */ + + /* Fine tune tx power ramp on time based on BBP Tx delay */ + if (isExternalPAMode(ad, channel)) + { + if (bw == 0) + RTMP_IO_WRITE32(ad, TX_SW_CFG0, 0x00101101); + else + RTMP_IO_WRITE32(ad, TX_SW_CFG0, 0x000B0C01); + + RTMP_IO_WRITE32(ad, TX_SW_CFG1, 0x00011414); + } + else + { + if (bw == 0) + RTMP_IO_WRITE32(ad, TX_SW_CFG0, 0x00101001); + else + RTMP_IO_WRITE32(ad, TX_SW_CFG0, 0x000B0B01); + + RTMP_IO_WRITE32(ad, TX_SW_CFG1, 0x00021414); + } + + /* tx pwr gain setting */ + mt76x2_tx_pwr_gain(ad, channel, bw); + + /* per-rate power delta */ + mt76x2_adjust_per_rate_pwr_delta(ad, channel, 0); + + andes_switch_channel(ad, channel, scan, bw, tx_rx_setting, bbp_ch_idx); + + eLNA_gain_from_e2p = ((ad->ALNAGain2 & 0xFF) << 24) | ((ad->ALNAGain1 & 0xFF) << 16) | ((ad->ALNAGain0 & 0xFF) << 8) | (ad->BLNAGain & 0xFF); + andes_init_gain(ad, channel, TRUE, eLNA_gain_from_e2p); + + RTMP_BBP_IO_READ32(ad, AGC1_R8, &value); + DBGPRINT(RT_DEBUG_INFO, ("%s::BBP 0x2320=0x%08x\n", __FUNCTION__, value)); + RTMP_BBP_IO_READ32(ad, AGC1_R9, &value); + DBGPRINT(RT_DEBUG_INFO, ("%s::BBP 0x2324=0x%08x\n", __FUNCTION__, value)); + RTMP_BBP_IO_READ32(ad, AGC1_R4, &value); + DBGPRINT(RT_DEBUG_INFO, ("%s::BBP 0x2310=0x%08x\n", __FUNCTION__, value)); + RTMP_BBP_IO_READ32(ad, AGC1_R5, &value); + DBGPRINT(RT_DEBUG_INFO, ("%s::BBP 0x2314=0x%08x\n", __FUNCTION__, value)); + + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + /* LDPC RX */ + RTMP_BBP_IO_READ32(ad, 0x2934, &value); + value |= (1 << 10); + RTMP_BBP_IO_WRITE32(ad, 0x2934, value); + } + + + /* disable prim/second EDCCA before disable mac TX/RX */ + RTMP_IO_READ32(ad, TXOP_CTRL_CFG, &mac_val); + if ((mac_val & 0x100000) == 0x100000) + { + ad->chipCap.ed_cca_enable = TRUE; + mac_val &= ~(1<<20); + RTMP_IO_WRITE32(ad, TXOP_CTRL_CFG, mac_val); + + RTMP_IO_READ32(ad, TXOP_HLDR_ET, &mac_val); + mac_val &= ~2; + RTMP_IO_WRITE32(ad, TXOP_HLDR_ET, mac_val); + } + + + /* backup mac 1004 value */ + RTMP_IO_READ32(ad, 0x1004, &restore_value); + + /* Backup the original RTS retry count and then set to 0 */ + RTMP_IO_READ32(ad, 0x1344, &ad->rts_tx_retry_num); + + /* disable mac tx/rx */ + value = restore_value; + value &= ~0xC; + RTMP_IO_WRITE32(ad, 0x1004, value); + + /* set RTS retry count = 0 */ + RTMP_IO_WRITE32(ad, 0x1344, 0x00092B00); + + /* wait mac 0x1200, bbp 0x2130 idle */ + do { + RTMP_IO_READ32(ad, 0x1200, &value); + value &= 0x1; + RTMP_BBP_IO_READ32(ad, 0x2130, &value1); + DBGPRINT(RT_DEBUG_INFO,("%s:: Wait until MAC 0x1200 bit0 and BBP 0x2130 become 0\n", __FUNCTION__)); + RtmpusecDelay(1); + loop++; + } while (((value != 0) || (value1 != 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__)); + + if ((value == 0) && (value1 != 0)) { + DBGPRINT(RT_DEBUG_OFF, ("%s:: doing IBI and core soft progress\n", __FUNCTION__)); + + RTMP_BBP_IO_READ32(ad, CORE_R4, &value1); + value1 |= 0x2; + RTMP_BBP_IO_WRITE32(ad, CORE_R4, value1); + + RTMP_BBP_IO_READ32(ad, CORE_R4, &value1); + value1 &= ~0x2; + RTMP_BBP_IO_WRITE32(ad, CORE_R4, value1); + + RTMP_BBP_IO_READ32(ad, CORE_R4, &value1); + value1 |= 0x1; + RTMP_BBP_IO_WRITE32(ad, CORE_R4, value1); + + RTMP_BBP_IO_READ32(ad, CORE_R4, &value1); + value1 &= ~0x1; + RTMP_BBP_IO_WRITE32(ad, CORE_R4, value1); + } + } + + if (!ad->MCUCtrl.power_on) { + RT28xx_EEPROM_READ16(ad, BT_RCAL_RESULT, e2p_value); + + if ((e2p_value & 0xff) != 0xff) { + DBGPRINT(RT_DEBUG_OFF, ("r-cal result = %d\n", e2p_value & 0xff)); + CHIP_CALIBRATION(ad, R_CALIBRATION_7662, 0x00); + } + } + + /* RXDCOC calibration */ + CHIP_CALIBRATION(ad, RXDCOC_CALIBRATION_7662, channel); + + if (!ad->MCUCtrl.power_on) { + /* RX LPF calibration */ + CHIP_CALIBRATION(ad, RC_CALIBRATION_7662, 0x00); + } + + +#ifdef RTMP_PCI_SUPPORT + if(IS_PCI_INF(ad)) { + NdisAcquireSpinLock(&ad->tssi_lock); + } +#endif + + /* TSSI Clibration */ + if (!IS_DOT11_H_RADAR_STATE(ad, RD_SILENCE_MODE) && !ad->chipCap.temp_tx_alc_enable && + !(ScanRunning(ad) == TRUE)) + mt76x2_tssi_calibration(ad, channel); + + /* enable TX/RX */ + RTMP_IO_WRITE32(ad, 0x1004, 0xc); + + + /* enable prim/second EDCCA after mac TX/RX enabled */ + if (ad->chipCap.ed_cca_enable) + { + mac_val = 0; + + RTMP_IO_READ32(ad, TXOP_CTRL_CFG, &mac_val); + mac_val |= (1<<20); + RTMP_IO_WRITE32(ad, TXOP_CTRL_CFG, mac_val); + } + + RTMP_IO_READ32(ad, TXOP_HLDR_ET, &mac_val); + mac_val |= 2; + RTMP_IO_WRITE32(ad, TXOP_HLDR_ET, mac_val); + + + + /* Restore RTS retry count */ + RTMP_IO_WRITE32(ad, 0x1344, ad->rts_tx_retry_num); + + if (!ad->MCUCtrl.power_on && ad->chipCap.tssi_enable && !ad->chipCap.temp_tx_alc_enable) { + RTMP_IO_READ32(ad, TX_ALC_CFG_1, &value); + value = value & (~TX_ALC_CFG_1_TX0_TEMP_COMP_MASK); + value |= TX_ALC_CFG_1_TX0_TEMP_COMP(0x38); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_1, value); + DBGPRINT(RT_DEBUG_OFF, ("TX0 power compensation = 0x%x\n", value & 0x3f)); + RTMP_IO_READ32(ad, TX_ALC_CFG_2, &value); + value = value & (~TX_ALC_CFG_2_TX1_TEMP_COMP_MASK); + value |= TX_ALC_CFG_2_TX1_TEMP_COMP(0x38); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_2, value); + DBGPRINT(RT_DEBUG_OFF, ("TX1 power compensation = 0x%x\n", value & 0x3f)); + } + +#ifdef RTMP_PCI_SUPPORT + if (IS_PCI_INF(ad)) { + NdisReleaseSpinLock(&ad->tssi_lock); + } +#endif + + + + /* Channel latch */ + ad->LatchRfRegs.Channel = channel; + + if (!ad->MCUCtrl.power_on) + ad->MCUCtrl.power_on = TRUE; + + + + +#ifdef ED_MONITOR + bEdcca = GetEDCCASupport(ad); + if(bEdcca) + mt7612_set_ed_cca(ad,bEdcca); + else +#endif /* ED_MONITOR */ + RTMP_BBP_IO_WRITE32(ad, AGC1_R2, 0x00007070); /* initial ED CCA threshold */ + + +#ifdef SINGLE_SKU_V2 + mt76x2_single_sku(ad, channel); +#endif /* SINGLE_SKU_V2 */ + + + percentage_delta_pwr(ad); + +#ifdef DYNAMIC_VGA_SUPPORT +#ifdef CONFIG_AP_SUPPORT + RTMP_BBP_IO_READ32(ad, AGC1_R35, &ad->chipCap.agc1_r35_backup); + RTMP_BBP_IO_READ32(ad, AGC1_R39, &ad->chipCap.agc1_r39_backup); + RTMP_BBP_IO_READ32(ad, AGC1_R41, &ad->chipCap.agc1_r41_backup); +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_BBP_IO_WRITE32(ad, AGC1_R61, 0xFF64A4E2); /* microwave's function initial gain */ + RTMP_BBP_IO_WRITE32(ad, AGC1_R7, 0x08081010); /* microwave's ED CCA threshold */ + RTMP_BBP_IO_WRITE32(ad, AGC1_R11, 0x00000404); /* microwave's ED CCA threshold */ +#endif /* DYNAMIC_VGA_SUPPORT */ + + if (ad->CommonCfg.BBPCurrentBW == BW_80) + RTMP_BBP_IO_WRITE32(ad, RXO_R14, 0x00560211); + else + RTMP_BBP_IO_WRITE32(ad, RXO_R14, 0x00560423); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Switch to Ch#%d(%dT%dR), BBP_BW=%d, bbp_ch_idx=%d)\n", + __FUNCTION__, + channel, + ad->CommonCfg.TxStream, + ad->CommonCfg.RxStream, + ad->CommonCfg.BBPCurrentBW, + bbp_ch_idx)); +} + +void mt76x2_external_pa_rf_dac_control(RTMP_ADAPTER *ad, u8 channel) +{ + if (isExternalPAMode(ad, channel)) { + if (!strncmp((PSTRING)ad->CommonCfg.CountryCode, "US", 2) + && (channel >= 36 && channel <= 48)) { + mt_rf_write(ad, 0, 0x058, 0x226C6000); + mt_rf_write(ad, 1, 0x058, 0x226C6000); + DBGPRINT(RT_DEBUG_OFF,("%s::change MT7612E's RF DAC control range since in US band 1 frequency range\n", + __FUNCTION__)); + } + } +} + +void mt76x2_tssi_calibration(RTMP_ADAPTER *ad, u8 channel) +{ + /* TSSI Clibration */ + if (ad->chipCap.tssi_enable) { + ad->chipCap.tssi_stage = TSSI_CAL_STAGE; + if (channel > 14) { + if (ad->chipCap.PAType == EXT_PA_2G_5G) + CHIP_CALIBRATION(ad, TSSI_CALIBRATION_7662, 0x0101); + else if (ad->chipCap.PAType == EXT_PA_5G_ONLY) + CHIP_CALIBRATION(ad, TSSI_CALIBRATION_7662, 0x0101); + else + CHIP_CALIBRATION(ad, TSSI_CALIBRATION_7662, 0x0001); + } else { + if (ad->chipCap.PAType == EXT_PA_2G_5G) + CHIP_CALIBRATION(ad, TSSI_CALIBRATION_7662, 0x0100); + else if ((ad->chipCap.PAType == EXT_PA_5G_ONLY) || + (ad->chipCap.PAType == INT_PA_2G_5G)) + CHIP_CALIBRATION(ad, TSSI_CALIBRATION_7662, 0x0000); + else if (ad->chipCap.PAType == EXT_PA_2G_ONLY) + CHIP_CALIBRATION(ad, TSSI_CALIBRATION_7662, 0x0100); + else + DBGPRINT(RT_DEBUG_ERROR, ("illegal PA Type(%d)\n", ad->chipCap.PAType)); + } + ad->chipCap.tssi_stage = TSSI_TRIGGER_STAGE; + } +} + +void mt76x2_tssi_compensation(RTMP_ADAPTER *ad, u8 channel) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + ANDES_CALIBRATION_PARAM param; + UINT32 pa_mode = 0, tssi_slope_offset = 0, value = 0; + + +#ifdef RTMP_PCI_SUPPORT +// if (IS_PCI_INF(ad)) { +// NdisAcquireSpinLock(&ad->tssi_lock); +// } +#endif + + if (ad->chipCap.tssi_stage <= TSSI_CAL_STAGE) + goto done; + + if (cap->tssi_stage == TSSI_TRIGGER_STAGE) { + DBGPRINT(RT_DEBUG_INFO, ("%s:TSS_TRIGGER(channel = %d)\n", __FUNCTION__, channel)); + param.mt76x2_tssi_comp_param.pa_mode = (1 << 8); + param.mt76x2_tssi_comp_param.tssi_slope_offset = 0; + + /* TSSI Trigger */ + if(ad->chipOps.Calibration != NULL) + ad->chipOps.Calibration(ad, TSSI_COMPENSATION_7662, ¶m); + else + goto done; + + cap->tssi_stage = TSSI_COMP_STAGE; + + goto done; + } + + /* Check 0x2088[4] = 0 */ + RTMP_BBP_IO_READ32(ad, CORE_R34, &value); + + if ((value & (1 << 4)) == 0) { + + DBGPRINT(RT_DEBUG_INFO, ("%s:TSSI_COMP(channel = %d)\n", __FUNCTION__, channel)); + + if (channel > 14) { + if (ad->chipCap.PAType == EXT_PA_2G_5G) + pa_mode = 1; + else if (ad->chipCap.PAType == EXT_PA_5G_ONLY) + pa_mode = 1; + else + pa_mode = 0; + } else { + if (ad->chipCap.PAType == EXT_PA_2G_5G) + pa_mode = 1; + else if ((ad->chipCap.PAType == EXT_PA_5G_ONLY) || + (ad->chipCap.PAType == INT_PA_2G_5G)) + pa_mode = 0; + else if (ad->chipCap.PAType == EXT_PA_2G_ONLY) + pa_mode = 1; + } + + if (channel <= 14) { + tssi_slope_offset &= ~TSSI_PARAM2_SLOPE0_MASK; + tssi_slope_offset |= TSSI_PARAM2_SLOPE0(cap->tssi_0_slope_g_band); + tssi_slope_offset &= ~TSSI_PARAM2_SLOPE1_MASK; + tssi_slope_offset |= TSSI_PARAM2_SLOPE1(cap->tssi_1_slope_g_band); + tssi_slope_offset &= ~TSSI_PARAM2_OFFSET0_MASK; + tssi_slope_offset |= TSSI_PARAM2_OFFSET0(cap->tssi_0_offset_g_band); + tssi_slope_offset &= ~TSSI_PARAM2_OFFSET1_MASK; + tssi_slope_offset |= TSSI_PARAM2_OFFSET1(cap->tssi_1_offset_g_band); + } else { + tssi_slope_offset &= ~TSSI_PARAM2_SLOPE0_MASK; + tssi_slope_offset |= TSSI_PARAM2_SLOPE0(cap->tssi_0_slope_a_band[get_chl_grp(channel)]); + tssi_slope_offset &= ~TSSI_PARAM2_SLOPE1_MASK; + tssi_slope_offset |= TSSI_PARAM2_SLOPE1(cap->tssi_1_slope_a_band[get_chl_grp(channel)]); + tssi_slope_offset &= ~TSSI_PARAM2_OFFSET0_MASK; + tssi_slope_offset |= TSSI_PARAM2_OFFSET0(cap->tssi_0_offset_a_band[get_chl_grp(channel)]); + tssi_slope_offset &= ~TSSI_PARAM2_OFFSET1_MASK; + tssi_slope_offset |= TSSI_PARAM2_OFFSET1(cap->tssi_1_offset_a_band[get_chl_grp(channel)]); + } + + param.mt76x2_tssi_comp_param.pa_mode = (pa_mode | ((0x1) << 9)); + param.mt76x2_tssi_comp_param.tssi_slope_offset = tssi_slope_offset; + + /* TSSI Compensation */ + if(ad->chipOps.Calibration != NULL) + ad->chipOps.Calibration(ad, TSSI_COMPENSATION_7662, ¶m); + + cap->tssi_stage = TSSI_TRIGGER_STAGE; + + if (!ad->MCUCtrl.dpd_on +#ifdef ED_MONITOR + && (ad->ed_tx_stoped == FALSE) +#endif /* ED_MONITOR */ +#ifdef DFS_SUPPORT + && (!IS_DOT11_H_RADAR_STATE(ad, RD_SILENCE_MODE)) +#endif /* DFS_SUPPORT */ + ) { +#ifdef RTMP_PCI_SUPPORT + RtmpOsMsDelay(10); +#endif + /* DPD Calibration */ + if ( (ad->chipCap.PAType== INT_PA_2G_5G) + || ((ad->chipCap.PAType == INT_PA_5G) && ( channel > 14 ) ) + || ((ad->chipCap.PAType == INT_PA_2G) && ( channel <= 14 ) ) + ) + CHIP_CALIBRATION(ad, DPD_CALIBRATION_7662, channel); + ad->MCUCtrl.dpd_on = TRUE; + } + } + +done: +; +#ifdef RTMP_PCI_SUPPORT + //if (IS_PCI_INF(ad)) { + // NdisReleaseSpinLock(&ad->tssi_lock); + //} +#endif + +} + +void mt76x2_calibration(RTMP_ADAPTER *ad, u8 channel) +{ + UINT32 value, value1, restore_value, loop = 0; + UINT32 mac_val = 0; + + if ( IS_DOT11_H_RADAR_STATE(ad, RD_SILENCE_MODE)) + { + DBGPRINT(RT_DEBUG_OFF, + ("%s():RDMode is in Silent State, do not calibration.\n", __FUNCTION__)); + return; + } + + /* disable prim/second EDCCA before calibration */ + RTMP_IO_READ32(ad, TXOP_CTRL_CFG, &mac_val); + if ((mac_val & 0x100000) == 0x100000) + { + ad->chipCap.ed_cca_enable = TRUE; + mac_val &= ~(1<<20); + RTMP_IO_WRITE32(ad, TXOP_CTRL_CFG, mac_val); + + RTMP_IO_READ32(ad, TXOP_HLDR_ET, &mac_val); + mac_val &= ~2; + RTMP_IO_WRITE32(ad, TXOP_HLDR_ET, mac_val); + } + + + DBGPRINT(RT_DEBUG_OFF, ("%s(channel = %d)\n", __FUNCTION__, channel)); + + /* backup mac 1004 value */ + RTMP_IO_READ32(ad, 0x1004, &restore_value); + + /* Backup the original RTS retry count and then set to 0 */ + RTMP_IO_READ32(ad, 0x1344, &ad->rts_tx_retry_num); + + /* disable mac tx/rx */ + value = restore_value; + value &= ~0xC; + RTMP_IO_WRITE32(ad, 0x1004, value); + + /* set RTS retry count = 0 */ + RTMP_IO_WRITE32(ad, 0x1344, 0x00092B00); + + /* wait mac 0x1200, bbp 0x2130 idle */ + do { + RTMP_IO_READ32(ad, 0x1200, &value); + value &= 0x1; + RTMP_BBP_IO_READ32(ad, 0x2130, &value1); + DBGPRINT(RT_DEBUG_INFO, ("%s:: Wait until MAC 0x1200 bit0 and BBP 0x2130 become 0\n", __FUNCTION__)); + RtmpusecDelay(1); + loop++; + } while (((value != 0) || (value1 != 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__)); + } + + /* LC Calibration */ + if (channel > 14) { + CHIP_CALIBRATION(ad, LC_CALIBRATION_7662, 0x00); + } + + /* TX LOFT */ + if (channel > 14) { + CHIP_CALIBRATION(ad, TX_LOFT_CALIBRATION_7662, 0x1); + } else { + CHIP_CALIBRATION(ad, TX_LOFT_CALIBRATION_7662, 0x0); + } + + /* TXIQ Clibration */ + if (channel > 14) { + CHIP_CALIBRATION(ad, TXIQ_CALIBRATION_7662, 0x1); + } else { + CHIP_CALIBRATION(ad, TXIQ_CALIBRATION_7662, 0x0); + } + + + /* RXIQC-FI */ + if (channel > 14) { + CHIP_CALIBRATION(ad, RXIQC_FI_CALIBRATION_7662, 0x1); + } else { + CHIP_CALIBRATION(ad, RXIQC_FI_CALIBRATION_7662, 0x0); + } + + + /* TEMP SENSOR */ + CHIP_CALIBRATION(ad, TEMP_SENSOR_CALIBRATION_7662, 0x00); + +#ifdef TXBF_SUPPORT + /* Do a Divider Calibration and update BBP registers */ + //if (ad->CommonCfg.RegTransmitSetting.field.ITxBfEn) + { + ULONG stTimeChk0, stTimeChk1; + UCHAR i; + + NdisGetSystemUpTime(&stTimeChk0); + + /* Disable TX Phase Compensation */ + RTMP_IO_READ32(ad, TXBE_R12, &value); + RTMP_IO_WRITE32(ad, TXBE_R12, value & (~0x28)); + + /* Clear Tx/Rx Phase compensated values */ + RTMP_IO_READ32(ad, CAL_R0, &value); + value &= ~0x60; + + // Clear Tx phase + RTMP_IO_WRITE32(ad, CAL_R0, value); + RTMP_IO_WRITE32(ad, TXBE_R13, 0); + + // Clear Rx phase + for (i=0; i<3; i++) + { + RTMP_IO_WRITE32(ad, CAL_R0, value | (i << 5)); + RTMP_IO_WRITE32(ad, RXFE_R3, 0); + } + + /* Start to do the divider calibration */ + if (channel > 14) //iBF only apply on A band + { + ad->chipOps.fITxBfDividerCalibration(ad, 3, 0, NULL); + } + NdisGetSystemUpTime(&stTimeChk1); + + DBGPRINT(RT_DEBUG_INFO,("%s : Divider calibration duration = %d ms\n", __FUNCTION__, (stTimeChk1 - stTimeChk0)*1000/OS_HZ)); + } +#endif /* TXBF_SUPPORT */ + + /* Trigger TX-Shaping */ + CHIP_CALIBRATION(ad, TX_SHAPING_CALIBRATION_7662, 0x00); + + /* enable TX/RX */ + RTMP_IO_WRITE32(ad, 0x1004, restore_value); + + /* Restore RTS retry count */ + RTMP_IO_WRITE32(ad, 0x1344, ad->rts_tx_retry_num); + +#ifdef CONFIG_CALIBRATION_COLLECTION + RtmpOsMsDelay(200); + + UCHAR i = 0; + for (i = R_CALIBRATION_7662; i <= RXIQC_FD_CALIBRATION_7662; i++) + { + switch(i) + { + case RXDCOC_CALIBRATION_7662: + record_calibration_info(ad, RXDCOC_CALIBRATION_7662); + break; + case RC_CALIBRATION_7662: + record_calibration_info(ad, RC_CALIBRATION_7662); + break; + case LC_CALIBRATION_7662: + record_calibration_info(ad, LC_CALIBRATION_7662); + break; + case TX_LOFT_CALIBRATION_7662: + record_calibration_info(ad, TX_LOFT_CALIBRATION_7662); + break; + case TXIQ_CALIBRATION_7662: + record_calibration_info(ad, TXIQ_CALIBRATION_7662); + break; + case TSSI_CALIBRATION_7662: + record_calibration_info(ad, TSSI_CALIBRATION_7662); + break; + case DPD_CALIBRATION_7662: + record_calibration_info(ad, DPD_CALIBRATION_7662); + break; + case RXIQC_FI_CALIBRATION_7662: + record_calibration_info(ad, RXIQC_FI_CALIBRATION_7662); + break; + case RXIQC_FD_CALIBRATION_7662: + record_calibration_info(ad, RXIQC_FD_CALIBRATION_7662); + break; + default: + break; + } + } +#endif /* CONFIG_CALIBRATION_COLLECTION */ +} + +static void mt76x2_cal_test(RTMP_ADAPTER *ad, UINT32 type) +{ +#ifdef CONFIG_CALIBRATION_COLLECTION + UCHAR cent_ch; + +#ifdef DOT11_VHT_AC + if(ad->CommonCfg.BBPCurrentBW == BW_80) + cent_ch = ad->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + cent_ch = ad->CommonCfg.CentralChannel; + + if (type == CAL_ROBUST_TEST) { + do_calibrtion_info_for_robust(ad, RXDCOC_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, RC_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, LC_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, TX_LOFT_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, TXIQ_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, TSSI_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, DPD_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, RXIQC_FI_CALIBRATION_7662, cent_ch); + do_calibrtion_info_for_robust(ad, RXIQC_FD_CALIBRATION_7662, cent_ch); + } +#endif /* CONFIG_CALIBRATION_COLLECTION */ +} + +/* + * Initialize FCE + */ +VOID init_fce(RTMP_ADAPTER *ad) +{ + L2_STUFFING_STRUC reg; + + reg.word = 0; + +#ifdef RTMP_PCI_SUPPORT + + /* test the TP on MT7620/ MT7621 platform, the TP is not degrade */ + RTMP_IO_WRITE32(ad, 0x708, 0x1401); + RTMP_IO_READ32(ad, FCE_L2_STUFF, ®.word); + reg.field.FS_WR_MPDU_LEN_EN = 0; + RTMP_IO_WRITE32(ad, FCE_L2_STUFF, reg.word); +#endif + +} + +static void mt76x2_init_mac_cr(RTMP_ADAPTER *ad) +{ + u32 i; + u32 value = 0; + u16 e2p_value; + char xtal_freq_offset = 0; + + /* + Enable PBF and MAC clock + SYS_CTRL[11:10] = 0x3 + */ +#ifdef RTMP_PCI_SUPPORT + if (IS_PCI_INF(ad)) { + for(i = 0; i < mt76x2_mac_cr_nums; i++) { + RTMP_IO_WRITE32(ad, mt76x2_mac_cr_table[i].Register, + mt76x2_mac_cr_table[i].Value); + } + } +#endif + + +#ifdef HDR_TRANS_TX_SUPPORT + /* + * Enable Header Translation TX + */ + RTMP_IO_READ32(ad, HEADER_TRANS_CTRL_REG, &value); + value |= 0x1; /* 0x1: TX, 0x2: RX */ + RTMP_IO_WRITE32(ad, HEADER_TRANS_CTRL_REG, value); +#endif /* HDR_TRANS_TX_SUPPORT */ + + /* + * Release BBP and MAC reset + * MAC_SYS_CTRL[1:0] = 0x0 + */ + RTMP_IO_READ32(ad, MAC_SYS_CTRL, &value); + value &= ~(0x3); + RTMP_IO_WRITE32(ad, MAC_SYS_CTRL, value); + + if (IS_MT7612(ad)) + { + /* + * Disable COEX_EN + */ + RTMP_IO_READ32(ad, COEXCFG0, &value); + value &= 0xFFFFFFFE; + RTMP_IO_WRITE32(ad, COEXCFG0, value); + } + + /* + Set 0x141C[15:12]=0xF + */ + RTMP_IO_READ32(ad, EXT_CCA_CFG, &value); + value |= (0x0000F000); + RTMP_IO_WRITE32(ad, EXT_CCA_CFG, value); + + + /* + * Set 0x13C0[31] = 0x0 + */ + RTMP_IO_READ32(ad, TX_ALC_CFG_4, &value); + value &= ~WL_LOWGAIN_CH_EN; + RTMP_IO_WRITE32(ad, TX_ALC_CFG_4, value); +#ifdef APCLI_SUPPORT + RTMP_IO_READ32(ad, PN_PAD_MODE, &value); + value |= PN_PAD_MODE_OFFSET; + RTMP_IO_WRITE32(ad, PN_PAD_MODE, value); +#endif /* APCLI_SUPPORT */ + /* + * Check crystal trim2 first + */ + RT28xx_EEPROM_READ16(ad, G_BAND_BANDEDGE_PWR_BACK_OFF, e2p_value); + + if (((e2p_value & 0xff) == 0x00) || ((e2p_value & 0xff) == 0xff)) + xtal_freq_offset = 0; + else if ((e2p_value & 0x80) == 0x80) + xtal_freq_offset = 0 - (e2p_value & 0x7f); + else if ((e2p_value & 0x80) == 0x00) + xtal_freq_offset = (e2p_value & 0x7f); + + if ((((e2p_value >> 8) & 0xff) == 0x00) || (((e2p_value >> 8) & 0xff) == 0xff)) + { + /* + * Compesate crystal trim1 + */ + RT28xx_EEPROM_READ16(ad, XTAL_TRIM1, e2p_value); + + /* crystal trim default value set to 0x14 */ + if (((e2p_value & 0xff) == 0x00) || ((e2p_value & 0xff) == 0xff)) + e2p_value = 0x14; + + /* Set crystal trim1 */ + read_reg(ad, 0x40, XO_CTRL5, &value); + value &= 0xffff80ff; + value |= ((((e2p_value & XTAL_TRIM1_MASK) + xtal_freq_offset) & XTAL_TRIM1_MASK) << 8); + write_reg(ad, 0x40, XO_CTRL5, value); + + /* Enable */ + read_reg(ad, 0x40, XO_CTRL6, &value); + value &= 0xffff80ff; + value |= (0x7f << 8); + write_reg(ad, 0x40, XO_CTRL6, value); + } else { + /* Set crystal trim2 */ + read_reg(ad, 0x40, XO_CTRL5, &value); + value &= 0xffff80ff; + value |= (((e2p_value & XTAL_TRIM2_MASK) + (xtal_freq_offset << 8)) & XTAL_TRIM2_MASK); + write_reg(ad, 0x40, XO_CTRL5, value); + + /* Enable */ + read_reg(ad, 0x40, XO_CTRL6, &value); + value &= 0xffff80ff; + value |= (0x7f << 8); + write_reg(ad, 0x40, XO_CTRL6, value); + } + + /* + * add 504, 50c value per ben kao suggestion for rx receivce packet, need to revise this bit + * only mt7662u do not this setting + */ + if (IS_MT76x2E(ad) || IS_MT76x2U(ad)) { + RTMP_IO_WRITE32(ad, 0x504, 0x06000000); + RTMP_IO_WRITE32(ad, 0x50c, 0x08800000); + RtmpOsMsDelay(5); + RTMP_IO_WRITE32(ad, 0x504, 0x0); + } + + /* Decrease MAC OFDM SIFS from 16 to 13us */ + RTMP_IO_READ32(ad, XIFS_TIME_CFG, &value); + value = value & (~XIFS_TIME_OFDM_SIFS_MASK); + value |= XIFS_TIME_OFDM_SIFS(0x0D); + RTMP_IO_WRITE32(ad, XIFS_TIME_CFG, value); + + RTMP_IO_READ32(ad, BKOFF_SLOT_CFG, &value); + value &= ~(BKOFF_SLOT_CFG_CC_DELAY_TIME_MASK); + value |= BKOFF_SLOT_CFG_CC_DELAY_TIME(0x01); + RTMP_IO_WRITE32(ad, BKOFF_SLOT_CFG, value); + + init_fce(ad); + +#ifdef MCS_LUT_SUPPORT + RTMP_IO_READ32(ad, TX_FBK_LIMIT, &value); + if (RTMP_TEST_MORE_FLAG(ad, fASIC_CAP_MCS_LUT)) + value |= 0x40000; + else + value &= (~0x40000); + RTMP_IO_WRITE32(ad, TX_FBK_LIMIT, value); +#endif /* MCS_LUT_SUPPORT */ + + /* + For co-clock image + 00 : one crystal , disable co-clock out + 01 : One crystal, enable co-clock out + 10 : Two crystal (Default) + */ + RTMP_IO_READ32(ad, 0x11C, &value); + if (ad->NicConfig3.field.XtalOption == 0x0) + value = 0x5C1FEE80; + else if (ad->NicConfig3.field.XtalOption == 0x1) + value = 0x5C1FEED0; + RTMP_IO_WRITE32(ad, 0x11C, value); + + +#ifdef RTMP_PCI_SUPPORT + if (IS_PCI_INF(ad)) { + /* ASPM: set rg_ssusb_g1_cdr_bir_ltr = 0x9 */ + read_reg(ad, 0x40, 0x5A10, &value); + value &= 0xFFE0FFFF; + value |= (0x9 << 16); + write_reg(ad, 0x40, 0x5A10, value); + + /* ASPM: set rg_ssusb_g1_cdr_bic_ltr = 0xF */ + read_reg(ad, 0x40, 0x5A0C, &value); + value &= 0x0FFFFFFF; + value |= (0xF << 28); + write_reg(ad, 0x40, 0x5A0C, value); + + /* ASPM: set RG_SSUSB_CDR_BR_PE1D = 0x3 */ + read_reg(ad, 0x40, 0x5C58, &value); + value &= 0xFFFFFE3F; + value |= (0x3 << 6); + write_reg(ad, 0x40, 0x5C58, value); + } +#endif /* RTMP_PCI_SUPPORT */ +} + +static void mt76x2_init_rf_cr(RTMP_ADAPTER *ad) +{ + andes_load_cr(ad, RF_BBP_CR, 0, 0); +} + +void mt76x2_get_external_lna_gain(RTMP_ADAPTER *ad) +{ + USHORT e2p_val = 0; + UINT8 lna_type = 0; + + /* b'00: 2.4G+5G external LNA, b'01: 5G external LNA, b'10: 2.4G external LNA, b'11: Internal LNA */ + RT28xx_EEPROM_READ16(ad, 0x36, e2p_val); + lna_type = e2p_val & 0xC; + if (lna_type == 0xC) + ad->chipCap.LNA_type = 0x0; + else if (lna_type == 0x8) + ad->chipCap.LNA_type = 0x1; + else if (lna_type == 0x4) + ad->chipCap.LNA_type = 0x10; + else if (lna_type == 0x0) + ad->chipCap.LNA_type = 0x11; + + RT28xx_EEPROM_READ16(ad, 0x44, e2p_val); + ad->BLNAGain = (e2p_val & 0xFF); /* store external LNA gain for 2.4G on EEPROM 0x44h */ + ad->ALNAGain0 = (e2p_val & 0xFF00) >> 8; /* store external LNA gain for 5G ch#36 ~ ch#64 on EEPROM 0x45h */ + + RT28xx_EEPROM_READ16(ad, 0x48, e2p_val); + ad->ALNAGain1 = (e2p_val & 0xFF00) >> 8; /* store external LNA gain for 5G ch#100 ~ ch#128 on EEPROM 0x49h */ + + RT28xx_EEPROM_READ16(ad, 0x4C, e2p_val); + ad->ALNAGain2 = (e2p_val & 0xFF00) >> 8; /* store external LNA gain for 5G ch#132 ~ ch#165 on EEPROM 0x4Dh */ + + DBGPRINT(RT_DEBUG_ERROR, ("%s::LNA type=0x%x, BLNAGain=0x%x, ALNAGain0=0x%x, ALNAGain1=0x%x, ALNAGain2=0x%x\n", + __FUNCTION__, ad->chipCap.LNA_type, ad->BLNAGain, ad->ALNAGain0, ad->ALNAGain1, ad->ALNAGain2)); +} + +void mt76x2_get_agc_gain(RTMP_ADAPTER *ad, BOOLEAN init_phase) +{ + UCHAR val; + USHORT val16; + UINT32 bbp_val; + + RTMP_BBP_IO_READ32(ad, AGC1_R8, &bbp_val); + val = ((bbp_val & (0x00007f00)) >> 8) & 0x7f; + ad->CommonCfg.lna_vga_ctl.agc_vga_init_0 = val; + ad->CommonCfg.lna_vga_ctl.agc1_r8_backup = bbp_val; + if (init_phase == TRUE) { + ad->CommonCfg.lna_vga_ctl.agc_vga_ori_0 = ad->CommonCfg.lna_vga_ctl.agc_vga_init_0; + DBGPRINT(RT_DEBUG_OFF, ("original vga value(chain0) = %x\n", ad->CommonCfg.lna_vga_ctl.agc_vga_ori_0)); + } + val16 = ((bbp_val & (0xffff0000)) >> 16) & (0xffff); + ad->CommonCfg.lna_vga_ctl.agc_0_vga_set1_2 = val16; + DBGPRINT(RT_DEBUG_TRACE, ("initial vga value(chain0) = %x\n", ad->CommonCfg.lna_vga_ctl.agc_vga_init_0)); + + if (ad->CommonCfg.RxStream >= 2) { + RTMP_BBP_IO_READ32(ad, AGC1_R9, &bbp_val); + val = ((bbp_val & (0x00007f00)) >> 8) & 0x7f; + ad->CommonCfg.lna_vga_ctl.agc_vga_init_1 = val; + ad->CommonCfg.lna_vga_ctl.agc1_r9_backup = bbp_val; + if (init_phase == TRUE) { + ad->CommonCfg.lna_vga_ctl.agc_vga_ori_1= ad->CommonCfg.lna_vga_ctl.agc_vga_init_1; + DBGPRINT(RT_DEBUG_OFF, ("original vga value(chain1) = %x\n", ad->CommonCfg.lna_vga_ctl.agc_vga_ori_1)); + } + val16 = ((bbp_val & (0xffff0000)) >> 16) & (0xffff); + ad->CommonCfg.lna_vga_ctl.agc_1_vga_set1_2 = val16; + + DBGPRINT(RT_DEBUG_TRACE, ("initial vga value(chain1) = %x\n", ad->CommonCfg.lna_vga_ctl.agc_vga_init_1)); + } + + ad->CommonCfg.lna_vga_ctl.bDyncVgaEnable = TRUE; +} + +int mt76x2_reinit_agc_gain(RTMP_ADAPTER *ad, u8 channel) +{ + UINT32 value0, value1; + CHAR agc_vga0, agc_vga1; + UINT8 chl_grp; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + RTMP_BBP_IO_READ32(ad, AGC1_R8, &value0); + agc_vga0 = ((value0 & (0x00007f00)) >> 8) & 0x7f; + + RTMP_BBP_IO_READ32(ad, AGC1_R9, &value1); + agc_vga1 = ((value1 & (0x00007f00)) >> 8) & 0x7f; + + DBGPRINT(RT_DEBUG_OFF, ("%s:original agc_vga0 = 0x%x, agc_vga1 = 0x%x\n", __FUNCTION__, agc_vga0, agc_vga1)); + + if (channel > 14) { + chl_grp = get_chl_grp(channel); + switch (chl_grp) { + case A_BAND_GRP0_CHL: + agc_vga0 += cap->rf0_5g_grp0_rx_high_gain; + agc_vga1 += cap->rf1_5g_grp0_rx_high_gain; + break; + case A_BAND_GRP1_CHL: + agc_vga0 += cap->rf0_5g_grp1_rx_high_gain; + agc_vga1 += cap->rf1_5g_grp1_rx_high_gain; + break; + case A_BAND_GRP2_CHL: + agc_vga0 += cap->rf0_5g_grp2_rx_high_gain; + agc_vga1 += cap->rf1_5g_grp2_rx_high_gain; + break; + case A_BAND_GRP3_CHL: + agc_vga0 += cap->rf0_5g_grp3_rx_high_gain; + agc_vga1 += cap->rf1_5g_grp3_rx_high_gain; + break; + case A_BAND_GRP4_CHL: + agc_vga0 += cap->rf0_5g_grp4_rx_high_gain; + agc_vga1 += cap->rf1_5g_grp4_rx_high_gain; + break; + case A_BAND_GRP5_CHL: + agc_vga0 += cap->rf0_5g_grp5_rx_high_gain; + agc_vga1 += cap->rf1_5g_grp5_rx_high_gain; + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("illegal channel group(%d)\n", chl_grp)); + break; + } + } else { + agc_vga0 += cap->rf0_2g_rx_high_gain; + agc_vga1 += cap->rf1_2g_rx_high_gain; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s:updated agc_vga0 = 0x%x, agc_vga1 = 0x%x\n", __FUNCTION__, agc_vga0, agc_vga1)); + + value0 &= 0xffff80ff; + value0 |= ((0x7f & agc_vga0) << 8); + + value1 &= 0xffff80ff; + value1 |= ((0x7f & agc_vga1) << 8); + + RTMP_BBP_IO_WRITE32(ad, AGC1_R8, value0); + RTMP_BBP_IO_WRITE32(ad, AGC1_R9, value1); + + return 0; +} + +int mt76x2_reinit_hi_lna_gain(RTMP_ADAPTER *ad, u8 channel) +{ + UINT32 value0, value1; + CHAR hi_lna0, hi_lna1; + UINT8 chl_grp; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + RTMP_BBP_IO_READ32(ad, AGC1_R4, &value0); + hi_lna0 = ((value0 & (0x003f0000)) >> 16) & 0x3f; + + RTMP_BBP_IO_READ32(ad, AGC1_R5, &value1); + hi_lna1 = ((value1 & (0x003f0000)) >> 16) & 0x3f; + + DBGPRINT(RT_DEBUG_OFF, ("%s:original hi_lna0 = 0x%x, hi_lna1 = 0x%x\n", __FUNCTION__, hi_lna0, hi_lna1)); + + if (channel > 14) { + chl_grp = get_chl_grp(channel); + switch (chl_grp) { + case A_BAND_GRP0_CHL: + hi_lna0 -= (cap->rf0_5g_grp0_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_5g_grp0_rx_high_gain / 2); + break; + case A_BAND_GRP1_CHL: + hi_lna0 -= (cap->rf0_5g_grp1_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_5g_grp1_rx_high_gain / 2); + break; + case A_BAND_GRP2_CHL: + hi_lna0 -= (cap->rf0_5g_grp2_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_5g_grp2_rx_high_gain / 2); + break; + case A_BAND_GRP3_CHL: + hi_lna0 -= (cap->rf0_5g_grp3_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_5g_grp3_rx_high_gain / 2); + break; + case A_BAND_GRP4_CHL: + hi_lna0 -= (cap->rf0_5g_grp4_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_5g_grp4_rx_high_gain / 2); + break; + case A_BAND_GRP5_CHL: + hi_lna0 -= (cap->rf0_5g_grp5_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_5g_grp5_rx_high_gain / 2); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("illegal channel group(%d)\n", chl_grp)); + break; + } + } else { + hi_lna0 -= (cap->rf0_2g_rx_high_gain / 2); + hi_lna1 -= (cap->rf1_2g_rx_high_gain / 2); + } + + DBGPRINT(RT_DEBUG_OFF, ("%s:updated hi_lna0 = 0x%x, hi_lna1 = 0x%x\n", __FUNCTION__, hi_lna0, hi_lna1)); + + value0 &= 0xffc0ffff; + value0 |= ((0x3f & hi_lna0) << 16); + + value1 &= 0xffc0ffff; + value1 |= ((0x3f & hi_lna1) << 16); + + RTMP_BBP_IO_WRITE32(ad, AGC1_R4, value0); + RTMP_BBP_IO_WRITE32(ad, AGC1_R5, value1); + + return 0; +} + +#ifdef DBG +void mt76x2_get_rx_high_gain(RTMP_ADAPTER *ad) +{ + UINT16 value; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + RT28xx_EEPROM_READ16(ad, RF_2G_RX_HIGH_GAIN, value); + if ((value & 0xff00) == 0x0000 || ((value & 0xff00) == 0xff00)) { + cap->rf0_2g_rx_high_gain = 0; + cap->rf1_2g_rx_high_gain = 0; + } else { + if (value & RF0_2G_RX_HIGH_GAIN_SIGN) + cap->rf0_2g_rx_high_gain = ((value & RF0_2G_RX_HIGH_GAIN_MASK) >> 8); + else + cap->rf0_2g_rx_high_gain = -((value & RF0_2G_RX_HIGH_GAIN_MASK) >> 8); + + if (value & RF1_2G_RX_HIGH_GAIN_SIGN) + cap->rf1_2g_rx_high_gain = ((value & RF1_2G_RX_HIGH_GAIN_MASK) >> 12); + else + cap->rf1_2g_rx_high_gain = -((value & RF1_2G_RX_HIGH_GAIN_MASK) >> 12); + } + + RT28xx_EEPROM_READ16(ad, RF_5G_GRP0_1_RX_HIGH_GAIN, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->rf0_5g_grp0_rx_high_gain = 0; + cap->rf1_5g_grp0_rx_high_gain = 0; + } else { + if (value & RF0_5G_GRP0_RX_HIGH_GAIN_SIGN) + cap->rf0_5g_grp0_rx_high_gain = (value & RF0_5G_GRP0_RX_HIGH_GAIN_MASK); + else + cap->rf0_5g_grp0_rx_high_gain = -(value & RF0_5G_GRP0_RX_HIGH_GAIN_MASK); + + if (value & RF1_5G_GRP0_RX_HIGH_GAIN_SIGN) + cap->rf1_5g_grp0_rx_high_gain = ((value & RF1_5G_GRP0_RX_HIGH_GAIN_MASK) >> 4); + else + cap->rf1_5g_grp0_rx_high_gain = -((value & RF1_5G_GRP0_RX_HIGH_GAIN_MASK) >> 4); + } + + if ((value & 0xff00) == 0x0000 || ((value & 0xff00) == 0xff00)) { + cap->rf0_5g_grp1_rx_high_gain = 0; + cap->rf1_5g_grp1_rx_high_gain = 0; + } else { + if (value & RF0_5G_GRP1_RX_HIGH_GAIN_SIGN) + cap->rf0_5g_grp1_rx_high_gain = ((value & RF0_5G_GRP1_RX_HIGH_GAIN_MASK) >> 8); + else + cap->rf0_5g_grp1_rx_high_gain = -((value & RF0_5G_GRP1_RX_HIGH_GAIN_MASK) >> 8); + + if (value & RF1_5G_GRP1_RX_HIGH_GAIN_SIGN) + cap->rf1_5g_grp1_rx_high_gain = ((value & RF1_5G_GRP1_RX_HIGH_GAIN_MASK) >> 12); + else + cap->rf1_5g_grp1_rx_high_gain = -((value & RF1_5G_GRP1_RX_HIGH_GAIN_MASK) >> 12); + + } + + RT28xx_EEPROM_READ16(ad, RF_5G_GRP2_3_RX_HIGH_GAIN, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->rf0_5g_grp2_rx_high_gain = 0; + cap->rf1_5g_grp2_rx_high_gain = 0; + } else { + if (value & RF0_5G_GRP2_RX_HIGH_GAIN_SIGN) + cap->rf0_5g_grp2_rx_high_gain = (value & RF0_5G_GRP2_RX_HIGH_GAIN_MASK); + else + cap->rf0_5g_grp2_rx_high_gain = -(value & RF0_5G_GRP2_RX_HIGH_GAIN_MASK); + + if (value & RF1_5G_GRP2_RX_HIGH_GAIN_SIGN) + cap->rf1_5g_grp2_rx_high_gain = ((value & RF1_5G_GRP2_RX_HIGH_GAIN_MASK) >> 4); + else + cap->rf1_5g_grp2_rx_high_gain = -((value & RF1_5G_GRP2_RX_HIGH_GAIN_MASK) >> 4); + } + + if ((value & 0xff00) == 0x0000 || ((value & 0xff00) == 0xff00)) { + cap->rf0_5g_grp3_rx_high_gain = 0; + cap->rf1_5g_grp3_rx_high_gain = 0; + } else { + if (value & RF0_5G_GRP3_RX_HIGH_GAIN_SIGN) + cap->rf0_5g_grp3_rx_high_gain = ((value & RF0_5G_GRP3_RX_HIGH_GAIN_MASK) >> 8); + else + cap->rf0_5g_grp3_rx_high_gain = -((value & RF0_5G_GRP3_RX_HIGH_GAIN_MASK) >> 8); + + if (value & RF1_5G_GRP3_RX_HIGH_GAIN_SIGN) + cap->rf1_5g_grp3_rx_high_gain = ((value & RF1_5G_GRP3_RX_HIGH_GAIN_MASK) >> 12); + else + cap->rf1_5g_grp3_rx_high_gain = -((value & RF1_5G_GRP3_RX_HIGH_GAIN_MASK) >> 12); + } + + RT28xx_EEPROM_READ16(ad, RF_5G_GRP4_5_RX_HIGH_GAIN, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->rf0_5g_grp4_rx_high_gain = 0; + cap->rf1_5g_grp4_rx_high_gain = 0; + } else { + if (value & RF0_5G_GRP4_RX_HIGH_GAIN_SIGN) + cap->rf0_5g_grp4_rx_high_gain = (value & RF0_5G_GRP4_RX_HIGH_GAIN_MASK); + else + cap->rf0_5g_grp4_rx_high_gain = -(value & RF0_5G_GRP4_RX_HIGH_GAIN_MASK); + + if (value & RF1_5G_GRP4_RX_HIGH_GAIN_SIGN) + cap->rf1_5g_grp4_rx_high_gain = ((value & RF1_5G_GRP4_RX_HIGH_GAIN_MASK) >> 4); + else + cap->rf1_5g_grp4_rx_high_gain = -((value & RF1_5G_GRP4_RX_HIGH_GAIN_MASK) >> 4); + } + + if ((value & 0xff00) == 0x0000 || ((value & 0xff00) == 0xff00)) { + cap->rf0_5g_grp5_rx_high_gain = 0; + cap->rf1_5g_grp5_rx_high_gain = 0; + } else { + if (value & RF0_5G_GRP5_RX_HIGH_GAIN_SIGN) + cap->rf0_5g_grp5_rx_high_gain = ((value & RF0_5G_GRP5_RX_HIGH_GAIN_MASK) >> 8); + else + cap->rf0_5g_grp5_rx_high_gain = -((value & RF0_5G_GRP5_RX_HIGH_GAIN_MASK) >> 8); + + if (value & RF1_5G_GRP5_RX_HIGH_GAIN_SIGN) + cap->rf1_5g_grp5_rx_high_gain = ((value & RF1_5G_GRP5_RX_HIGH_GAIN_MASK) >> 12); + else + cap->rf1_5g_grp5_rx_high_gain = -((value & RF1_5G_GRP5_RX_HIGH_GAIN_MASK) >> 12); + } +} +#endif + +static void mt76x2_get_tx_pwr_info(RTMP_ADAPTER *ad) +{ + u16 value; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + RT28xx_EEPROM_READ16(ad, G_BAND_20_40_BW_PWR_DELTA, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->delta_tx_pwr_bw40_g_band = 0; + } else { + if (value & G_BAND_20_40_BW_PWR_DELTA_EN) { + if (value & G_BAND_20_40_BW_PWR_DELTA_SIGN) + cap->delta_tx_pwr_bw40_g_band = (value & G_BAND_20_40_BW_PWR_DELTA_MASK); + else + cap->delta_tx_pwr_bw40_g_band = -(value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } else { + cap->delta_tx_pwr_bw40_g_band = 0; + } + } + + if (((value & 0xff00) == 0x0000) || ((value & 0xff00) == 0xff00)) { + cap->delta_tx_pwr_bw40_a_band = 0; + } else { + if (value & A_BAND_20_40_BW_PWR_DELTA_EN) { + if (value & A_BAND_20_40_BW_PWR_DELTA_SIGN) + cap->delta_tx_pwr_bw40_a_band = ((value & A_BAND_20_40_BW_PWR_DELTA_MASK) >> 8); + else + cap->delta_tx_pwr_bw40_a_band = -((value & A_BAND_20_40_BW_PWR_DELTA_MASK) >> 8); + } else { + cap->delta_tx_pwr_bw40_a_band = 0; + } + } + + RT28xx_EEPROM_READ16(ad, A_BAND_20_80_BW_PWR_DELTA, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->delta_tx_pwr_bw80 = 0; + } else { + if (value & A_BAND_20_80_BW_PWR_DELTA_EN) { + if (value & A_BAND_20_80_BW_PWR_DELTA_SIGN) + cap->delta_tx_pwr_bw80 = (value & A_BAND_20_80_BW_PWR_DELTA_MASK); + else + cap->delta_tx_pwr_bw80 = -(value & A_BAND_20_80_BW_PWR_DELTA_MASK); + } else { + cap->delta_tx_pwr_bw80 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX0_G_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tssi_0_slope_g_band = TSSI_0_SLOPE_G_BAND_DEFAULT_VALUE; + } else { + cap->tssi_0_slope_g_band = (value & TX0_G_BAND_TSSI_SLOPE_MASK); + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tssi_0_offset_g_band = TSSI_0_OFFSET_G_BAND_DEFAULT_VALUE; + } else { + cap->tssi_0_offset_g_band = ((value & TX0_G_BAND_TSSI_OFFSET_MASK) >> 8); + } + + RT28xx_EEPROM_READ16(ad, TX0_G_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_target_pwr_g_band = TX_TARGET_PWR_DEFAULT_VALUE; + } else { + cap->tx_0_target_pwr_g_band = (value & TX0_G_BAND_TARGET_PWR_MASK); + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } else { + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX0_G_BAND_CHL_PWR_DELTA_MID, value); + + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } else { + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } else { + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX1_G_BAND_TSSI_SLOPE, value); + + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_slope_g_band = TSSI_1_SLOPE_G_BAND_DEFAULT_VALUE; + else + cap->tssi_1_slope_g_band = (value & TX1_G_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_offset_g_band = TSSI_1_OFFSET_G_BAND_DEFAULT_VALUE; + else + cap->tssi_1_offset_g_band = ((value & TX1_G_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, TX1_G_BAND_TARGET_PWR, value); + + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_1_target_pwr_g_band = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_g_band = (value & TX1_G_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } else { + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX1_G_BAND_CHL_PWR_DELTA_MID, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } else { + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN) + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + else + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } else { + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP0_TX0_A_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_0_slope_a_band[A_BAND_GRP0_CHL] = TSSI_0_SLOPE_A_BAND_GRP0_DEFAULT_VALUE; + else + cap->tssi_0_slope_a_band[A_BAND_GRP0_CHL] = (value & GRP0_TX0_A_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_0_offset_a_band[A_BAND_GRP0_CHL] = TSSI_0_OFFSET_A_BAND_GRP0_DEFAULT_VALUE; + else + cap->tssi_0_offset_a_band[A_BAND_GRP0_CHL] = ((value & GRP0_TX0_A_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP0_TX0_A_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_0_target_pwr_a_band[A_BAND_GRP0_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_0_target_pwr_a_band[A_BAND_GRP0_CHL] = (value & GRP0_TX0_A_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = ((value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = -((value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = (value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = -(value & GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_0_slope_a_band[A_BAND_GRP1_CHL] = TSSI_0_SLOPE_A_BAND_GRP1_DEFAULT_VALUE; + else + cap->tssi_0_slope_a_band[A_BAND_GRP1_CHL] = ((value & GRP1_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8); + + + RT28xx_EEPROM_READ16(ad, GRP1_TX0_A_BAND_TSSI_OFFSET, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_0_offset_a_band[A_BAND_GRP1_CHL] = TSSI_0_OFFSET_A_BAND_GRP1_DEFAULT_VALUE; + else + cap->tssi_0_offset_a_band[A_BAND_GRP1_CHL] = (value & GRP1_TX0_A_BAND_TSSI_OFFSET_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tx_0_target_pwr_a_band[A_BAND_GRP1_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_0_target_pwr_a_band[A_BAND_GRP1_CHL] = ((value & GRP1_TX0_A_BAND_TARGET_PWR_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = (value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = -(value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = ((value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = -((value & GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP0_TX0_A_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_0_slope_a_band[A_BAND_GRP2_CHL] = TSSI_0_SLOPE_A_BAND_GRP2_DEFAULT_VALUE; + else + cap->tssi_0_slope_a_band[A_BAND_GRP2_CHL] = (value & GRP2_TX0_A_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_0_offset_a_band[A_BAND_GRP2_CHL] = TSSI_0_OFFSET_A_BAND_GRP2_DEFAULT_VALUE; + else + cap->tssi_0_offset_a_band[A_BAND_GRP2_CHL] = ((value & GRP2_TX0_A_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP2_TX0_A_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_0_target_pwr_a_band[A_BAND_GRP2_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_0_target_pwr_a_band[A_BAND_GRP2_CHL] = (value & GRP2_TX0_A_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = ((value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = -((value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = (value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = -(value & GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_0_slope_a_band[A_BAND_GRP3_CHL] = TSSI_0_SLOPE_A_BAND_GRP3_DEFAULT_VALUE; + else + cap->tssi_0_slope_a_band[A_BAND_GRP3_CHL] = ((value & GRP3_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP3_TX0_A_BAND_TSSI_OFFSET, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_0_offset_a_band[A_BAND_GRP3_CHL] = TSSI_0_OFFSET_A_BAND_GRP3_DEFAULT_VALUE; + else + cap->tssi_0_offset_a_band[A_BAND_GRP3_CHL] = (value & GRP3_TX0_A_BAND_TSSI_OFFSET_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tx_0_target_pwr_a_band[A_BAND_GRP3_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_0_target_pwr_a_band[A_BAND_GRP3_CHL] = ((value & GRP3_TX0_A_BAND_TARGET_PWR_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = (value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = -(value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = ((value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = -((value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP4_TX0_A_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_0_slope_a_band[A_BAND_GRP4_CHL] = TSSI_0_SLOPE_A_BAND_GRP4_DEFAULT_VALUE; + else + cap->tssi_0_slope_a_band[A_BAND_GRP4_CHL] = (value & GRP4_TX0_A_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_0_offset_a_band[A_BAND_GRP4_CHL] = TSSI_0_OFFSET_A_BAND_GRP4_DEFAULT_VALUE; + else + cap->tssi_0_offset_a_band[A_BAND_GRP4_CHL] = ((value & GRP4_TX0_A_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP4_TX0_A_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_0_target_pwr_a_band[A_BAND_GRP4_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_0_target_pwr_a_band[A_BAND_GRP4_CHL] = (value & GRP4_TX0_A_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = ((value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = -((value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = (value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = -(value & GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_0_slope_a_band[A_BAND_GRP5_CHL] = TSSI_0_SLOPE_A_BAND_GRP5_DEFAULT_VALUE; + else + cap->tssi_0_slope_a_band[A_BAND_GRP5_CHL] = ((value & GRP5_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP5_TX0_A_BAND_TSSI_OFFSET, value); + + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_0_offset_a_band[A_BAND_GRP5_CHL] = TSSI_0_OFFSET_A_BAND_GRP5_DEFAULT_VALUE; + else + cap->tssi_0_offset_a_band[A_BAND_GRP5_CHL] = (value & GRP5_TX0_A_BAND_TSSI_OFFSET_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tx_0_target_pwr_a_band[A_BAND_GRP5_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_0_target_pwr_a_band[A_BAND_GRP5_CHL] = ((value & GRP5_TX0_A_BAND_TARGET_PWR_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = (value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = -(value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = ((value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = -((value & GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = 0; + } + } + + /* 5G TX1 chl pwr */ + RT28xx_EEPROM_READ16(ad, GRP0_TX1_A_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_slope_a_band[A_BAND_GRP0_CHL] = TSSI_1_SLOPE_A_BAND_GRP0_DEFAULT_VALUE; + else + cap->tssi_1_slope_a_band[A_BAND_GRP0_CHL] = (value & GRP0_TX1_A_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_offset_a_band[A_BAND_GRP0_CHL] = TSSI_1_OFFSET_A_BAND_GRP0_DEFAULT_VALUE; + else + cap->tssi_1_offset_a_band[A_BAND_GRP0_CHL] = ((value & GRP0_TX1_A_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP0_TX1_A_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_1_target_pwr_a_band[A_BAND_GRP0_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_a_band[A_BAND_GRP0_CHL] = (value & GRP0_TX1_A_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = ((value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = -((value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = (value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = -(value & GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_slope_a_band[A_BAND_GRP1_CHL] = TSSI_1_SLOPE_A_BAND_GRP1_DEFAULT_VALUE; + else + cap->tssi_1_slope_a_band[A_BAND_GRP1_CHL] = ((value & GRP1_TX1_A_BAND_TSSI_SLOPE_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP1_TX1_A_BAND_TSSI_OFFSET, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_offset_a_band[A_BAND_GRP1_CHL] = TSSI_1_OFFSET_A_BAND_GRP1_DEFAULT_VALUE; + else + cap->tssi_1_offset_a_band[A_BAND_GRP1_CHL] = (value & GRP1_TX1_A_BAND_TSSI_OFFSET_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tx_1_target_pwr_a_band[A_BAND_GRP1_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_a_band[A_BAND_GRP1_CHL] = ((value & GRP1_TX1_A_BAND_TARGET_PWR_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = (value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = -(value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = ((value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = -((value & GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP0_TX1_A_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_slope_a_band[A_BAND_GRP2_CHL] = TSSI_1_SLOPE_A_BAND_GRP2_DEFAULT_VALUE; + else + cap->tssi_1_slope_a_band[A_BAND_GRP2_CHL] = (value & GRP2_TX1_A_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_offset_a_band[A_BAND_GRP2_CHL] = TSSI_1_OFFSET_A_BAND_GRP2_DEFAULT_VALUE; + else + cap->tssi_1_offset_a_band[A_BAND_GRP2_CHL] = ((value & GRP2_TX1_A_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP2_TX1_A_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_1_target_pwr_a_band[A_BAND_GRP2_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_a_band[A_BAND_GRP2_CHL] = (value & GRP2_TX1_A_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = ((value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = -((value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = (value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = -(value & GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_slope_a_band[A_BAND_GRP3_CHL] = TSSI_1_SLOPE_A_BAND_GRP3_DEFAULT_VALUE; + else + cap->tssi_1_slope_a_band[A_BAND_GRP3_CHL] = ((value & GRP3_TX1_A_BAND_TSSI_SLOPE_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP3_TX1_A_BAND_TSSI_OFFSET, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_offset_a_band[A_BAND_GRP3_CHL] = TSSI_1_OFFSET_A_BAND_GRP3_DEFAULT_VALUE; + else + cap->tssi_1_offset_a_band[A_BAND_GRP3_CHL] = (value & GRP3_TX1_A_BAND_TSSI_OFFSET_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tx_1_target_pwr_a_band[A_BAND_GRP3_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_a_band[A_BAND_GRP3_CHL] = ((value & GRP3_TX1_A_BAND_TARGET_PWR_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = (value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = -(value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = ((value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = -((value & GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = 0; + } + } + + + RT28xx_EEPROM_READ16(ad, GRP4_TX1_A_BAND_TSSI_SLOPE, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_slope_a_band[A_BAND_GRP4_CHL] = TSSI_1_SLOPE_A_BAND_GRP4_DEFAULT_VALUE; + else + cap->tssi_1_slope_a_band[A_BAND_GRP4_CHL] = (value & GRP4_TX1_A_BAND_TSSI_SLOPE_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_offset_a_band[A_BAND_GRP4_CHL] = TSSI_1_OFFSET_A_BAND_GRP4_DEFAULT_VALUE; + else + cap->tssi_1_offset_a_band[A_BAND_GRP4_CHL] = ((value & GRP4_TX1_A_BAND_TSSI_OFFSET_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP4_TX1_A_BAND_TARGET_PWR, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tx_1_target_pwr_a_band[A_BAND_GRP4_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_a_band[A_BAND_GRP4_CHL] = (value & GRP4_TX1_A_BAND_TARGET_PWR_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = ((value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = -((value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = 0; + } + } + + RT28xx_EEPROM_READ16(ad, GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = (value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = -(value & GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tssi_1_slope_a_band[A_BAND_GRP5_CHL] = TSSI_1_SLOPE_A_BAND_GRP5_DEFAULT_VALUE; + else + cap->tssi_1_slope_a_band[A_BAND_GRP5_CHL] = ((value & GRP5_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP5_TX1_A_BAND_TSSI_OFFSET, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) + cap->tssi_1_offset_a_band[A_BAND_GRP5_CHL] = TSSI_1_OFFSET_A_BAND_GRP5_DEFAULT_VALUE; + else + cap->tssi_1_offset_a_band[A_BAND_GRP5_CHL] = (value & GRP5_TX1_A_BAND_TSSI_OFFSET_MASK); + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) + cap->tx_1_target_pwr_a_band[A_BAND_GRP5_CHL] = TX_TARGET_PWR_DEFAULT_VALUE; + else + cap->tx_1_target_pwr_a_band[A_BAND_GRP5_CHL] = ((value & GRP5_TX1_A_BAND_TARGET_PWR_MASK) >> 8); + + RT28xx_EEPROM_READ16(ad, GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = 0; + } else { + if (value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = (value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = -(value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = 0; + } else { + if (value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = ((value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = -((value & GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = 0; + } + } + + /* check tssi if enable */ + RT28xx_EEPROM_READ16(ad, NIC_CONFIGURE_1, value); + if (value & INTERNAL_TX_ALC_EN) + cap->tssi_enable = TRUE; + else + cap->tssi_enable = FALSE; + + /* check PA type combination */ + RT28xx_EEPROM_READ16(ad, EEPROM_NIC1_OFFSET, value); + cap->PAType= GET_PA_TYPE(value); +} + +static u8 mt76x2_txpwr_chlist[] = { + 1, 2,3,4,5,6,7,8,9,10,11,12,13,14, + 36,38,40,44,46,48,52,54,56,60,62,64, + 100,102,104,108,110,112,116,118,120,124,126,128,132,134,136,140,144, + 149,151,153,157,159,161,165,167,169,171,173, + 42, 58, 106, 122, 155, +}; + +int mt76x2_read_chl_pwr(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + u32 i, choffset; + + mt76x2_get_tx_pwr_info(ad); + + /* Read Tx power value for all channels*/ + /* Value from 1 - 0x7f. Default value is 24.*/ + /* Power value : 2.4G 0x00 (0) ~ 0x1F (31)*/ + /* : 5.5G 0xF9 (-7) ~ 0x0F (15)*/ + + DBGPRINT(RT_DEBUG_TRACE, ("%s()--->\n", __FUNCTION__)); + + for (i = 0; i < sizeof(mt76x2_txpwr_chlist); i++) { + ad->TxPower[i].Channel = mt76x2_txpwr_chlist[i]; + ad->TxPower[i].Power = TX_TARGET_PWR_DEFAULT_VALUE; + ad->TxPower[i].Power2 = TX_TARGET_PWR_DEFAULT_VALUE; + } + + /* 0. 11b/g, ch1 - ch 14, 2SS */ + for (i = 0; i < 14; i++) { + ad->TxPower[i].Power = cap->tx_0_target_pwr_g_band; + ad->TxPower[i].Power2 = cap->tx_1_target_pwr_g_band; + } + + /* 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)*/ + choffset = 14; + ASSERT((ad->TxPower[choffset].Channel == 36)); + + for (i = 0; i < 40; i++) { + ad->TxPower[i + choffset].Power = cap->tx_0_target_pwr_a_band[get_chl_grp(ad->TxPower[i+choffset].Channel)]; + ad->TxPower[i + choffset].Power2 = cap->tx_1_target_pwr_a_band[get_chl_grp(ad->TxPower[i+choffset].Channel)]; + } + + choffset = 14 + 12 + 17 + 11; + +#ifdef DOT11_VHT_AC + ASSERT((ad->TxPower[choffset].Channel == 42)); + + // TODO: shiang-6590, fix me for the TxPower setting code here! + /* For VHT80MHz, we need assign tx power for central channel 42, 58, 106, 122, and 155 */ + DBGPRINT(RT_DEBUG_TRACE, ("%s: Update Tx power control of the central channel (42, 58, 106, 122 and 155) for VHT BW80\n", __FUNCTION__)); + + NdisMoveMemory(&ad->TxPower[choffset], &ad->TxPower[16], sizeof(CHANNEL_TX_POWER)); // channel 42 = channel 40 + NdisMoveMemory(&ad->TxPower[choffset+1], &ad->TxPower[22], sizeof(CHANNEL_TX_POWER)); // channel 58 = channel 56 + NdisMoveMemory(&ad->TxPower[choffset+2], &ad->TxPower[28], sizeof(CHANNEL_TX_POWER)); // channel 106 = channel 104 + NdisMoveMemory(&ad->TxPower[choffset+3], &ad->TxPower[34], sizeof(CHANNEL_TX_POWER)); // channel 122 = channel 120 + NdisMoveMemory(&ad->TxPower[choffset+4], &ad->TxPower[45], sizeof(CHANNEL_TX_POWER)); // channel 155 = channel 153 + + ad->TxPower[choffset].Channel = 42; + ad->TxPower[choffset+1].Channel = 58; + ad->TxPower[choffset+2].Channel = 106; + ad->TxPower[choffset+3].Channel = 122; + ad->TxPower[choffset+4].Channel = 155; + + choffset = MAX_NUM_OF_CHANNELS; +#endif /* DOT11_VHT_AC */ + + /* 4. Print and Debug*/ + for (i = 0; i < choffset; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: TxPower[%03d], Channel=%d, Power[Tx0:%d, Tx1:%d]\n", + i, ad->TxPower[i].Channel, ad->TxPower[i].Power, ad->TxPower[i].Power2 )); + } + + return TRUE; +} + + +void mt76x2_get_tx_pwr_per_rate(RTMP_ADAPTER *ad) +{ + u16 value; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + RT28xx_EEPROM_READ16(ad, TX_PWR_CCK_1_2M, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_cck_1_2 = 0; + } else { + if (value & TX_PWR_CCK_1_2M_EN) { + if (value & TX_PWR_CCK_1_2M_SIGN) + cap->tx_pwr_cck_1_2 = (value & TX_PWR_CCK_1_2M_MASK); + else + cap->tx_pwr_cck_1_2 = -(value & TX_PWR_CCK_1_2M_MASK); + } else { + cap->tx_pwr_cck_1_2 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_cck_5_11 = 0; + } else { + if (value & TX_PWR_CCK_5_11M_EN) { + if (value & TX_PWR_CCK_5_11M_SIGN) + cap->tx_pwr_cck_5_11 = ((value & TX_PWR_CCK_5_11M_MASK) >> 8); + else + cap->tx_pwr_cck_5_11 = -((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } else { + cap->tx_pwr_cck_5_11 = 0; + } + + + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_G_BAND_OFDM_6_9M, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + } else { + if (value & TX_PWR_G_BAND_OFDM_6_9M_EN) { + if (value & TX_PWR_G_BAND_OFDM_6_9M_SIGN) + cap->tx_pwr_g_band_ofdm_6_9 = (value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + else + cap->tx_pwr_g_band_ofdm_6_9 = -(value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } else { + if (value & TX_PWR_G_BAND_OFDM_12_18M_EN) { + if (value & TX_PWR_G_BAND_OFDM_12_18M_SIGN) + cap->tx_pwr_g_band_ofdm_12_18 = ((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + else + cap->tx_pwr_g_band_ofdm_12_18 = -((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_G_BAND_OFDM_24_36M, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + } else { + if (value & TX_PWR_G_BAND_OFDM_24_36M_EN) { + if (value & TX_PWR_G_BAND_OFDM_24_36M_SIGN) + cap->tx_pwr_g_band_ofdm_24_36 = (value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + else + cap->tx_pwr_g_band_ofdm_24_36 = -(value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_g_band_ofdm_48_54 = 0; + } else { + if (value & TX_PWR_G_BAND_OFDM_48_54M_EN) { + if (value & TX_PWR_G_BAND_OFDM_48_54M_SIGN) + cap->tx_pwr_g_band_ofdm_48_54 = ((value & TX_PWR_G_BAND_OFDM_48_54M_MASK) >> 8); + else + cap->tx_pwr_g_band_ofdm_48_54 = -((value & TX_PWR_G_BAND_OFDM_48_54M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_48_54 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_HT_MCS_0_1, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_ht_mcs_0_1 = (value & TX_PWR_HT_MCS_0_1_MASK); + } else { + if (value & TX_PWR_HT_MCS_0_1_EN) { + if (value & TX_PWR_HT_MCS_0_1_SIGN) + cap->tx_pwr_ht_mcs_0_1 = (value & TX_PWR_HT_MCS_0_1_MASK); + else + cap->tx_pwr_ht_mcs_0_1 = -(value & TX_PWR_HT_MCS_0_1_MASK); + } else { + cap->tx_pwr_ht_mcs_0_1 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_ht_mcs_2_3 = ((value & TX_PWR_HT_MCS_2_3_MASK) >> 8); + } else { + if (value & TX_PWR_HT_MCS_2_3_EN) { + if (value & TX_PWR_HT_MCS_2_3_SIGN) + cap->tx_pwr_ht_mcs_2_3 = ((value & TX_PWR_HT_MCS_2_3_MASK) >> 8); + else + cap->tx_pwr_ht_mcs_2_3 = -((value & TX_PWR_HT_MCS_2_3_MASK) >> 8); + } else { + cap->tx_pwr_ht_mcs_2_3 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_HT_MCS_4_5, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_ht_mcs_4_5 = 0; + } else { + if (value & TX_PWR_HT_MCS_4_5_EN) { + if (value & TX_PWR_HT_MCS_4_5_SIGN) + cap->tx_pwr_ht_mcs_4_5 = (value & TX_PWR_HT_MCS_4_5_MASK); + else + cap->tx_pwr_ht_mcs_4_5 = -(value & TX_PWR_HT_MCS_4_5_MASK); + } else { + cap->tx_pwr_ht_mcs_4_5 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_ht_mcs_6_7 = 0; + } else { + if (value & TX_PWR_HT_MCS_6_7_EN) { + if (value & TX_PWR_HT_MCS_6_7_SIGN) + cap->tx_pwr_ht_mcs_6_7 = ((value & TX_PWR_HT_MCS_6_7_MASK) >> 8); + else + cap->tx_pwr_ht_mcs_6_7 = -((value & TX_PWR_HT_MCS_6_7_MASK) >> 8); + } else { + cap->tx_pwr_ht_mcs_6_7 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_HT_MCS_8_9, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_ht_mcs_8_9 = 0; + } else { + if (value & TX_PWR_HT_MCS_8_9_EN) { + if (value & TX_PWR_HT_MCS_8_9_SIGN) + cap->tx_pwr_ht_mcs_8_9 = (value & TX_PWR_HT_MCS_8_9_MASK); + else + cap->tx_pwr_ht_mcs_8_9 = -(value & TX_PWR_HT_MCS_8_9_MASK); + } else { + cap->tx_pwr_ht_mcs_8_9 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_ht_mcs_10_11 = 0; + } else { + if (value & TX_PWR_HT_MCS_10_11_EN) { + if (value & TX_PWR_HT_MCS_10_11_SIGN) + cap->tx_pwr_ht_mcs_10_11 = ((value & TX_PWR_HT_MCS_10_11_MASK) >> 8); + else + cap->tx_pwr_ht_mcs_10_11 = -((value & TX_PWR_HT_MCS_10_11_MASK) >> 8); + } else { + cap->tx_pwr_ht_mcs_10_11 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_HT_MCS_12_13, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_ht_mcs_12_13 = 0; + } else { + if (value & TX_PWR_HT_MCS_12_13_EN) { + if (value & TX_PWR_HT_MCS_12_13_SIGN) + cap->tx_pwr_ht_mcs_12_13 = (value & TX_PWR_HT_MCS_12_13_MASK); + else + cap->tx_pwr_ht_mcs_12_13 = -(value & TX_PWR_HT_MCS_12_13_MASK); + } else { + cap->tx_pwr_ht_mcs_12_13 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_ht_mcs_14_15 = 0; + } else { + if (value & TX_PWR_HT_MCS_14_15_EN) { + if (value & TX_PWR_HT_MCS_14_15_SIGN) + cap->tx_pwr_ht_mcs_14_15 = ((value & TX_PWR_HT_MCS_14_15_MASK) >> 8); + else + cap->tx_pwr_ht_mcs_14_15 = -((value & TX_PWR_HT_MCS_14_15_MASK) >> 8); + } else { + cap->tx_pwr_ht_mcs_14_15 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_A_BAND_OFDM_6_9M, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_a_band_ofdm_6_9 = 0; + } else { + if (value & TX_PWR_A_BAND_OFDM_6_9M_EN) { + if (value & TX_PWR_A_BAND_OFDM_6_9M_SIGN) + cap->tx_pwr_a_band_ofdm_6_9 = (value & TX_PWR_A_BAND_OFDM_6_9M_MASK); + else + cap->tx_pwr_a_band_ofdm_6_9 = -(value & TX_PWR_A_BAND_OFDM_6_9M_MASK); + } else { + cap->tx_pwr_a_band_ofdm_6_9 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_a_band_ofdm_12_18 = 0; + } else { + if (value & TX_PWR_A_BAND_OFDM_12_18M_EN) { + if (value & TX_PWR_A_BAND_OFDM_12_18M_SIGN) + cap->tx_pwr_a_band_ofdm_12_18 = ((value & TX_PWR_A_BAND_OFDM_12_18M_MASK) >> 8); + else + cap->tx_pwr_a_band_ofdm_12_18 = -((value & TX_PWR_A_BAND_OFDM_12_18M_MASK) >> 8); + } else { + cap->tx_pwr_a_band_ofdm_12_18 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_A_BAND_OFDM_24_36M, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_a_band_ofdm_24_36 = 0; + } else { + if (value & TX_PWR_A_BAND_OFDM_24_36M_EN) { + if (value & TX_PWR_A_BAND_OFDM_24_36M_SIGN) + cap->tx_pwr_a_band_ofdm_24_36 = (value & TX_PWR_A_BAND_OFDM_24_36M_MASK); + else + cap->tx_pwr_a_band_ofdm_24_36 = -(value & TX_PWR_A_BAND_OFDM_24_36M_MASK); + } else { + cap->tx_pwr_a_band_ofdm_24_36 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_a_band_ofdm_48_54 = 0; + } else { + if (value & TX_PWR_A_BAND_OFDM_48_54M_EN) { + if (value & TX_PWR_A_BAND_OFDM_48_54M_SIGN) + cap->tx_pwr_a_band_ofdm_48_54 = ((value & TX_PWR_A_BAND_OFDM_48_54M_MASK) >> 8); + else + cap->tx_pwr_a_band_ofdm_48_54 = -((value & TX_PWR_A_BAND_OFDM_48_54M_MASK) >> 8); + } else { + cap->tx_pwr_a_band_ofdm_48_54 = 0; + } + } + + + RT28xx_EEPROM_READ16(ad, TX_PWR_VHT_MCS_0_1, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_vht_mcs_0_1 = 0; + } else { + if (value & TX_PWR_VHT_MCS_0_1_EN) { + if (value & TX_PWR_VHT_MCS_0_1_SIGN) + cap->tx_pwr_vht_mcs_0_1 = (value & TX_PWR_VHT_MCS_0_1_MASK); + else + cap->tx_pwr_vht_mcs_0_1 = -(value & TX_PWR_VHT_MCS_0_1_MASK); + } else { + cap->tx_pwr_vht_mcs_0_1 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_vht_mcs_2_3 = 0; + } else { + if (value & TX_PWR_VHT_MCS_2_3_EN) { + if (value & TX_PWR_VHT_MCS_2_3_SIGN) + cap->tx_pwr_vht_mcs_2_3 = ((value & TX_PWR_VHT_MCS_2_3_MASK) >> 8); + else + cap->tx_pwr_vht_mcs_2_3 = -((value & TX_PWR_VHT_MCS_2_3_MASK) >> 8); + } else { + cap->tx_pwr_vht_mcs_2_3 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_VHT_MCS_4_5, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_vht_mcs_4_5 = 0; + } else { + if (value & TX_PWR_VHT_MCS_4_5_EN) { + if (value & TX_PWR_VHT_MCS_4_5_SIGN) + cap->tx_pwr_vht_mcs_4_5 = (value & TX_PWR_VHT_MCS_4_5_MASK); + else + cap->tx_pwr_vht_mcs_4_5 = -(value & TX_PWR_VHT_MCS_4_5_MASK); + } else { + cap->tx_pwr_vht_mcs_4_5 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_vht_mcs_6_7 = 0; + } else { + if (value & TX_PWR_VHT_MCS_6_7_EN) { + if (value & TX_PWR_VHT_MCS_6_7_SIGN) + cap->tx_pwr_vht_mcs_6_7 = ((value & TX_PWR_VHT_MCS_6_7_MASK) >> 8); + else + cap->tx_pwr_vht_mcs_6_7 = -((value & TX_PWR_VHT_MCS_6_7_MASK) >> 8); + } else { + cap->tx_pwr_vht_mcs_6_7 = 0; + } + } + + RT28xx_EEPROM_READ16(ad, TX_PWR_5G_VHT_MCS_8_9, value); + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + cap->tx_pwr_5g_vht_mcs_8_9 = 0; + } else { + if (value & TX_PWR_5G_VHT_MCS_8_9_EN) { + if (value & TX_PWR_5G_VHT_MCS_8_9_SIGN) + cap->tx_pwr_5g_vht_mcs_8_9 = (value & TX_PWR_5G_VHT_MCS_8_9_MASK); + else + cap->tx_pwr_5g_vht_mcs_8_9 = -(value & TX_PWR_5G_VHT_MCS_8_9_MASK); + } else { + cap->tx_pwr_5g_vht_mcs_8_9 = 0; + } + } + + if (((value & 0xff00) == 0x00) || ((value & 0xff00) == 0xff00)) { + cap->tx_pwr_2g_vht_mcs_8_9 = 0; + } else { + if (value & TX_PWR_2G_VHT_MCS_8_9_EN) { + if (value & TX_PWR_2G_VHT_MCS_8_9_SIGN) + cap->tx_pwr_2g_vht_mcs_8_9 = ((value & TX_PWR_2G_VHT_MCS_8_9_MASK) >> 8); + else + cap->tx_pwr_2g_vht_mcs_8_9 = -((value & TX_PWR_2G_VHT_MCS_8_9_MASK) >> 8); + } else { + cap->tx_pwr_2g_vht_mcs_8_9 = 0; + } + } +} + +static void mt76x2_show_pwr_info(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + UINT32 value; + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel info related to power\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + + if (ad->LatchRfRegs.Channel < 14) { + DBGPRINT(RT_DEBUG_OFF, ("central channel = %d, low_mid_hi = %d\n", ad->LatchRfRegs.Channel, + get_low_mid_hi_index(ad->LatchRfRegs.Channel))); + + } else { + DBGPRINT(RT_DEBUG_OFF, ("central channel = %d, group = %d, low_mid_hi = %d\n", + ad->LatchRfRegs.Channel, + get_chl_grp(ad->LatchRfRegs.Channel), + get_low_mid_hi_index(ad->LatchRfRegs.Channel))); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power(unit: 0.5dbm)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_g_band = 0x%x\n", cap->tx_0_target_pwr_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_g_band = 0x%x\n", cap->tx_1_target_pwr_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_a_band[A_BAND_GRP0_CHL] = 0x%x\n", cap->tx_0_target_pwr_a_band[A_BAND_GRP0_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_a_band[A_BAND_GRP1_CHL] = 0x%x\n", cap->tx_0_target_pwr_a_band[A_BAND_GRP1_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_a_band[A_BAND_GRP2_CHL] = 0x%x\n", cap->tx_0_target_pwr_a_band[A_BAND_GRP2_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_a_band[A_BAND_GRP3_CHL] = 0x%x\n", cap->tx_0_target_pwr_a_band[A_BAND_GRP3_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_a_band[A_BAND_GRP4_CHL] = 0x%x\n", cap->tx_0_target_pwr_a_band[A_BAND_GRP4_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_a_band[A_BAND_GRP5_CHL] = 0x%x\n", cap->tx_0_target_pwr_a_band[A_BAND_GRP5_CHL])); + + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_a_band[A_BAND_GRP0_CHL] = 0x%x\n", cap->tx_1_target_pwr_a_band[A_BAND_GRP0_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_a_band[A_BAND_GRP1_CHL] = 0x%x\n", cap->tx_1_target_pwr_a_band[A_BAND_GRP1_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_a_band[A_BAND_GRP2_CHL] = 0x%x\n", cap->tx_1_target_pwr_a_band[A_BAND_GRP2_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_a_band[A_BAND_GRP3_CHL] = 0x%x\n", cap->tx_1_target_pwr_a_band[A_BAND_GRP3_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_a_band[A_BAND_GRP4_CHL] = 0x%x\n", cap->tx_1_target_pwr_a_band[A_BAND_GRP4_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_a_band[A_BAND_GRP5_CHL] = 0x%x\n", cap->tx_1_target_pwr_a_band[A_BAND_GRP5_CHL])); + + /* channel power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power deltai(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI])); + + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP0_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP1_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP2_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP3_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP4_CHL][A_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI] = %d\n\n", cap->tx_1_chl_pwr_delta_a_band[A_BAND_GRP5_CHL][A_BAND_HI])); + + + /* bw power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("bw power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("delta_tx_pwr_bw40_a_band = %d\n", cap->delta_tx_pwr_bw40_a_band)); + DBGPRINT(RT_DEBUG_OFF, ("delta_tx_pwr_bw80 = %d\n", cap->delta_tx_pwr_bw80)); + + /* 54Mbps target power in MAC 0x13b0[5:0] and 0x13b0[13:8] */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("54Mbps target power(unit: 0.5dbm) MAC 0x13b0[5:0] and 0x13b0[13:8]\n"); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + + RTMP_IO_READ32(ad, TX_ALC_CFG_0, &value); + value = value & TX_ALC_CFG_0_CH_INT_0_MASK; + DBGPRINT(RT_DEBUG_OFF, ("tx_0_pwr(0x13b0[5:0])= 0x%x\n", value)); + + RTMP_IO_READ32(ad, TX_ALC_CFG_0, &value); + value = (value & TX_ALC_CFG_0_CH_INT_1_MASK) >> 8); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_pwr(0x13b0[13:8]) = 0x%x\n", value)); + + + /* per-rate power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_48_54 = %d\n", cap->tx_pwr_g_band_ofdm_48_54)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_0_1 = %d\n", cap->tx_pwr_ht_mcs_0_1)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_2_3 = %d\n", cap->tx_pwr_ht_mcs_2_3)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_4_5 = %d\n", cap->tx_pwr_ht_mcs_4_5)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_6_7 = %d\n", cap->tx_pwr_ht_mcs_6_7)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_8_9 = %d\n", cap->tx_pwr_ht_mcs_8_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_10_11 = %d\n", cap->tx_pwr_ht_mcs_10_11)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_12_13 = %d\n", cap->tx_pwr_ht_mcs_12_13)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_mcs_14_15 = %d\n", cap->tx_pwr_ht_mcs_14_15)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_a_band_ofdm_6_9 = %d\n", cap->tx_pwr_a_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_a_band_ofdm_12_18 = %d\n", cap->tx_pwr_a_band_ofdm_12_18)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_a_band_ofdm_24_36 = %d\n", cap->tx_pwr_a_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_a_band_ofdm_48_54 = %d\n", cap->tx_pwr_a_band_ofdm_48_54)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_vht_mcs_0_1 = %d\n", cap->tx_pwr_vht_mcs_0_1)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_vht_mcs_2_3 = %d\n", cap->tx_pwr_vht_mcs_2_3)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_vht_mcs_4_5 = %d\n", cap->tx_pwr_vht_mcs_4_5)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_vht_mcs_6_7 = %d\n", cap->tx_pwr_vht_mcs_6_7)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_5g_vht_mcs_8_9 = %d\n", cap->tx_pwr_5g_vht_mcs_8_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_2g_vht_mcs_8_9 = %d\n", cap->tx_pwr_2g_vht_mcs_8_9)); + + /* per rate delta in mac 0x1314 ~ 0x13DC */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta in MAC 0x1314 ~ 0x13DC\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + RTMP_IO_READ32(ad, TX_PWR_CFG_0, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_0 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_1, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_1 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_2, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_2 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_3, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_3 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_4, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_4 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_7, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_7 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_8, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_8 = 0x%x\n", value)); + RTMP_IO_READ32(ad, TX_PWR_CFG_9, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX_PWR_CFG_9 = 0x%x\n", value)); + + /* TSSI info */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI info\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("PA type = %d\n", cap->PAType)); + DBGPRINT(RT_DEBUG_OFF, ("TSSI enable = %d\n", cap->tssi_enable)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_slope_g_band = 0x%x\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_slope_g_band = 0x%x\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_offset_g_band = 0x%x\n", cap->tssi_0_offset_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_offset_g_band = 0x%x\n", cap->tssi_1_offset_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_slope_a_band[A_BAND_GRP0_CHL] = 0x%x\n", cap->tssi_0_slope_a_band[A_BAND_GRP0_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_slope_a_band[A_BAND_GRP1_CHL] = 0x%x\n", cap->tssi_0_slope_a_band[A_BAND_GRP1_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_slope_a_band[A_BAND_GRP2_CHL] = 0x%x\n", cap->tssi_0_slope_a_band[A_BAND_GRP2_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_slope_a_band[A_BAND_GRP3_CHL] = 0x%x\n", cap->tssi_0_slope_a_band[A_BAND_GRP3_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_slope_a_band[A_BAND_GRP4_CHL] = 0x%x\n", cap->tssi_0_slope_a_band[A_BAND_GRP4_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_slope_a_band[A_BAND_GRP5_CHL] = 0x%x\n", cap->tssi_0_slope_a_band[A_BAND_GRP5_CHL])); + + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_offset_a_band[A_BAND_GRP0_CHL] = 0x%x\n", cap->tssi_0_offset_a_band[A_BAND_GRP0_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_offset_a_band[A_BAND_GRP1_CHL] = 0x%x\n", cap->tssi_0_offset_a_band[A_BAND_GRP1_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_offset_a_band[A_BAND_GRP2_CHL] = 0x%x\n", cap->tssi_0_offset_a_band[A_BAND_GRP2_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_offset_a_band[A_BAND_GRP3_CHL] = 0x%x\n", cap->tssi_0_offset_a_band[A_BAND_GRP3_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_offset_a_band[A_BAND_GRP4_CHL] = 0x%x\n", cap->tssi_0_offset_a_band[A_BAND_GRP4_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_0_offset_a_band[A_BAND_GRP5_CHL] = 0x%x\n", cap->tssi_0_offset_a_band[A_BAND_GRP5_CHL])); + + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_slope_a_band[A_BAND_GRP0_CHL] = 0x%x\n", cap->tssi_1_slope_a_band[A_BAND_GRP0_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_slope_a_band[A_BAND_GRP1_CHL] = 0x%x\n", cap->tssi_1_slope_a_band[A_BAND_GRP1_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_slope_a_band[A_BAND_GRP2_CHL] = 0x%x\n", cap->tssi_1_slope_a_band[A_BAND_GRP2_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_slope_a_band[A_BAND_GRP3_CHL] = 0x%x\n", cap->tssi_1_slope_a_band[A_BAND_GRP3_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_slope_a_band[A_BAND_GRP4_CHL] = 0x%x\n", cap->tssi_1_slope_a_band[A_BAND_GRP4_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_slope_a_band[A_BAND_GRP5_CHL] = 0x%x\n", cap->tssi_1_slope_a_band[A_BAND_GRP5_CHL])); + + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_offset_a_band[A_BAND_GRP0_CHL] = 0x%x\n", cap->tssi_1_offset_a_band[A_BAND_GRP0_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_offset_a_band[A_BAND_GRP1_CHL] = 0x%x\n", cap->tssi_1_offset_a_band[A_BAND_GRP1_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_offset_a_band[A_BAND_GRP2_CHL] = 0x%x\n", cap->tssi_1_offset_a_band[A_BAND_GRP2_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_offset_a_band[A_BAND_GRP3_CHL] = 0x%x\n", cap->tssi_1_offset_a_band[A_BAND_GRP3_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_offset_a_band[A_BAND_GRP4_CHL] = 0x%x\n", cap->tssi_1_offset_a_band[A_BAND_GRP4_CHL])); + DBGPRINT(RT_DEBUG_OFF, ("cap->tssi_1_offset_a_band[A_BAND_GRP5_CHL] = 0x%x\n", cap->tssi_1_offset_a_band[A_BAND_GRP5_CHL])); + + /* TSSI compensation value */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI compensation value(unit: 0.5db) in mac 0x13B4 and 0x13A8\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + RTMP_IO_READ32(ad, TX_ALC_CFG_1, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX0 power compensation = 0x%x\n", value & 0x3f)); + RTMP_IO_READ32(ad, TX_ALC_CFG_2, &value); + DBGPRINT(RT_DEBUG_OFF, ("TX1 power compensation = 0x%x\n", value & 0x3f)); +} + +static void mt76x2_antenna_default_reset(struct _RTMP_ADAPTER *pAd, + EEPROM_ANTENNA_STRUC *pAntenna) +{ + pAntenna->word = 0; + /* field.RfIcType is only 4 bits, RFIC_7662 is 19, doesn't fit! */ + /* pAntenna->field.RfIcType = RFIC_7662; */ + pAntenna->field.RfIcType = 0xf; + pAntenna->field.TxPath = 2; + pAntenna->field.RxPath = 2; +} + +void percentage_delta_pwr(RTMP_ADAPTER *ad) +{ + CHAR mac_drop_pwr = 0, tx_alc_ch_init_0 = 0, tx_alc_ch_init_1 = 0; + UINT32 mac_val = 0; + + /* + Calculate delta power based on the percentage specified from UI. + EEPROM setting is calibrated for maximum Tx power (i.e. 100%). + Here lower Tx power according to the percentage specified from UI. + */ + + if (ad->CommonCfg.TxPowerPercentage > 90) { + /* 91 ~ 100% & auto, treat as 100% in terms of mW */ + ; + } else if (ad->CommonCfg.TxPowerPercentage > 60) { + /* 61 ~ 90%, treat as 75% in terms of mW */ + mac_drop_pwr -= 1; + } else if (ad->CommonCfg.TxPowerPercentage > 30) { + /* 31 ~ 60%, treat as 50% in terms of mW */ + mac_drop_pwr -= 3; + } else if (ad->CommonCfg.TxPowerPercentage > 15) { + /* 16 ~ 30%, treat as 25% in terms of mW */ + mac_drop_pwr -= 6; + } else if (ad->CommonCfg.TxPowerPercentage > 9) { + /* 10 ~ 15%, treat as 12.5% in terms of mW */ + mac_drop_pwr -= 9; + } else { + /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW */ + mac_drop_pwr -= 12; + } + + RTMP_IO_READ32(ad, TX_ALC_CFG_0, &mac_val); + tx_alc_ch_init_0 = (mac_val & 0x3F) + mac_drop_pwr*2; + if (tx_alc_ch_init_0 <= 0) + tx_alc_ch_init_0 = 0; + tx_alc_ch_init_1 = ((mac_val & 0x3F00) >> 8) + mac_drop_pwr*2; + if (tx_alc_ch_init_1<= 0) + tx_alc_ch_init_1 = 0; + DBGPRINT(RT_DEBUG_INFO, ("%s:: TX_ALC_CFG_0=0x%0x, tx_alc_ch_init_0=0x%0x, tx_alc_ch_init_1=0x%0x\n", + __FUNCTION__, mac_val, tx_alc_ch_init_0, tx_alc_ch_init_1)); + + mac_val = mac_val & (~TX_ALC_CFG_0_CH_INT_0_MASK); + mac_val |= TX_ALC_CFG_0_CH_INT_0(tx_alc_ch_init_0); + mac_val = mac_val & (~TX_ALC_CFG_0_CH_INT_1_MASK); + mac_val |= TX_ALC_CFG_0_CH_INT_1(tx_alc_ch_init_1); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_0, mac_val); + + DBGPRINT(RT_DEBUG_INFO, ("%s:: TX_ALC_CFG_0=0x%0x\n", + __FUNCTION__, mac_val)); +} + +void mt76x2_update_tx_power_percentage(RTMP_ADAPTER *ad) +{ + if (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_RADIO_OFF)) + return; + + mt76x2_tx_pwr_gain(ad, ad->CommonCfg.Channel, ad->CommonCfg.BBPCurrentBW); + percentage_delta_pwr(ad); +} + +void mt76x2_get_current_temp(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *pChipCap = &ad->chipCap; + INT32 temp_val = 0; + + read_reg(ad, 0x40, 0xD000, &temp_val); + pChipCap->temp_val = temp_val; + temp_val &= 0x7F; + + if ( pChipCap->temp_25_ref == 0 ) + pChipCap->current_temp = 25; + else + if (temp_val > pChipCap->temp_25_ref) { + pChipCap->current_temp = ((temp_val -pChipCap->temp_25_ref)*18/10) + 25; /* 1.789 */ + } else if (temp_val < pChipCap->temp_25_ref) { + pChipCap->current_temp = 25 - ((pChipCap->temp_25_ref - temp_val)*18/10); + } + else + pChipCap->current_temp = 25; + + DBGPRINT(RT_DEBUG_INFO, ("%s::read_temp=%d (0x%x), current_temp=%d (0x%x)\n", + __FUNCTION__, temp_val, temp_val, pChipCap->current_temp, pChipCap->current_temp)); +} + +void mt76x2_read_temp_info_from_eeprom(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *pChipCap = &ad->chipCap; + BOOLEAN is_temp_tx_alc= FALSE; + USHORT e2p_value = 0; + + RT28xx_EEPROM_READ16(ad, 0x36, e2p_value); + if ((e2p_value & 0x2) == 0x2) + is_temp_tx_alc = TRUE; + else + is_temp_tx_alc = FALSE; + + RT28xx_EEPROM_READ16(ad, 0x54, e2p_value); + pChipCap->temp_25_ref = (e2p_value & 0x7F00) >> 8; + if (((e2p_value & 0x8000) == 0x8000) && is_temp_tx_alc) + pChipCap->temp_tx_alc_enable = TRUE; + else + pChipCap->temp_tx_alc_enable = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: is_temp_tx_alc=%d, temp_tx_alc_enable=%d\n", + __FUNCTION__, is_temp_tx_alc, pChipCap->temp_tx_alc_enable)); +} + +#ifdef RTMP_TEMPERATURE_TX_ALC +void mt76x2_read_tx_alc_info_from_eeprom(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *pChipCap = &ad->chipCap; + BOOLEAN is_ePA_mode = FALSE; + USHORT e2p_value = 0, ePA_type = 3; + + + RT28xx_EEPROM_READ16(ad, 0x34, e2p_value); + /* + 00: 2.4G+5G external PA + 01: 5G external PA + 10: 2.4G external PA + 11: disable + */ + if ((e2p_value & 0x300) != 0x300) { + is_ePA_mode = TRUE; + ePA_type = ((e2p_value & 0x300) >> 8); + } else { + is_ePA_mode = FALSE; + ePA_type = 3; + } + + if ((ePA_type == 0) || (ePA_type == 1)) { + /* get 5G ePA NT to high and low temperature slope, the values are all positive numbers */ + RT28xx_EEPROM_READ16(ad, 0xF2, e2p_value); + pChipCap->high_temp_slope_a_band = e2p_value & 0xFF; + pChipCap->low_temp_slope_a_band = (e2p_value & 0xFF00) >> 8; + if ((e2p_value == 0xFFFF) || (e2p_value == 0)) + pChipCap->temp_tx_alc_enable = FALSE; + + /* get 5G temperature compensation upper and lower limit, the values are all positive numbers */ + RT28xx_EEPROM_READ16(ad, 0x54, e2p_value); + pChipCap->tc_lower_bound_a_band = 0 - (e2p_value & 0xF); + pChipCap->tc_upper_bound_a_band = (e2p_value & 0xF0) >> 4; + if (((e2p_value & 0xFF) == 0xFF) || ((e2p_value & 0xFF) == 0)) + pChipCap->temp_tx_alc_enable = FALSE; + } + + if ((ePA_type == 0) || (ePA_type == 2)) { + /* get 2G ePA NT to high and low temperature slope, the values are all positive numbers */ + RT28xx_EEPROM_READ16(ad, 0xF4, e2p_value); + pChipCap->high_temp_slope_g_band = e2p_value & 0xFF; + pChipCap->low_temp_slope_g_band = (e2p_value & 0xFF00) >> 8; + if ((e2p_value == 0xFFFF) || (e2p_value == 0)) + pChipCap->temp_tx_alc_enable = FALSE; + + /* get 2G temperature compensation upper and lower limit, the values are all positive numbers */ + RT28xx_EEPROM_READ16(ad, 0x52, e2p_value); + pChipCap->tc_lower_bound_g_band = 0 - ((e2p_value & 0x0F00) >> 8); + pChipCap->tc_upper_bound_g_band = (e2p_value & 0xF000) >> 12; + if (((e2p_value & 0xFF00) == 0xFF00) || ((e2p_value & 0xFF00) == 0)) + pChipCap->temp_tx_alc_enable = FALSE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: is_ePA_mode=%d, ePA_type=%d\n", + __FUNCTION__, is_ePA_mode, ePA_type)); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [5G band] high_temp_slope=%d, low_temp_slope=%d\n", + __FUNCTION__, pChipCap->high_temp_slope_a_band, pChipCap->low_temp_slope_a_band)); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [2G band] high_temp_slope=%d, low_temp_slope=%d\n", + __FUNCTION__, pChipCap->high_temp_slope_g_band, pChipCap->low_temp_slope_g_band)); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [5G band] tc_lower_bound=%d, tc_upper_bound=%d\n", + __FUNCTION__, pChipCap->tc_lower_bound_a_band, pChipCap->tc_upper_bound_a_band)); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [2G band] tc_lower_bound=%d, tc_upper_bound=%d\n", + __FUNCTION__, pChipCap->tc_lower_bound_g_band, pChipCap->tc_upper_bound_g_band)); +} + +void mt76x2_temp_tx_alc(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *pChipCap = &ad->chipCap; + INT32 temp_diff = 0, dB_diff = 0, tx0_temp_comp = 0, tx1_temp_comp = 0; + UCHAR tc_init_val = 0; + +#ifdef SINGLE_SKU_V2 + tc_init_val = ad->tc_init_val; + + if (ad->sku_init_done == FALSE) + return; +#endif /* SINGLE_SKU_V2 */ + + if (pChipCap->temp_tx_alc_enable) { + temp_diff = pChipCap->current_temp - 25; + + if (ad->CommonCfg.Channel > 14) { + if (temp_diff > 0) + dB_diff = (temp_diff / pChipCap->high_temp_slope_a_band); + else if (temp_diff < 0) + dB_diff = 0 - ((0 - temp_diff) / pChipCap->low_temp_slope_a_band); + else + dB_diff = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::[5G] temp_diff=%d (0x%x), dB_diff=%d (0x%x)\n", + __FUNCTION__, temp_diff, temp_diff, dB_diff, dB_diff)); + + /* temperature compensation boundary check and limit */ + dB_diff = (dB_diff > pChipCap->tc_upper_bound_a_band) ? pChipCap->tc_upper_bound_a_band : dB_diff; + dB_diff = (dB_diff < pChipCap->tc_lower_bound_a_band) ? pChipCap->tc_lower_bound_a_band : dB_diff; + } else { + if (temp_diff > 0) + dB_diff = (temp_diff / pChipCap->high_temp_slope_g_band); + else if (temp_diff < 0) + dB_diff = 0 - ((0 - temp_diff) / pChipCap->low_temp_slope_g_band); + else + dB_diff = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::[2G] temp_diff=%d (0x%x), dB_diff=%d (0x%x)\n", + __FUNCTION__, temp_diff, temp_diff, dB_diff, dB_diff)); + + /* temperature compensation boundary check and limit */ + dB_diff = (dB_diff > pChipCap->tc_upper_bound_g_band) ? pChipCap->tc_upper_bound_g_band : dB_diff; + dB_diff = (dB_diff < pChipCap->tc_lower_bound_g_band) ? pChipCap->tc_lower_bound_g_band : dB_diff; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::temp_diff=%d (0x%x), dB_diff=%d (0x%x)\n", + __FUNCTION__, temp_diff, temp_diff, dB_diff, dB_diff)); + + RTMP_IO_READ32(ad, TX_ALC_CFG_1, &tx0_temp_comp); + tx0_temp_comp &= ~TX_ALC_CFG_1_TX0_TEMP_COMP_MASK; + tx0_temp_comp |= ((tc_init_val + dB_diff*2) & TX_ALC_CFG_1_TX0_TEMP_COMP_MASK); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_1, tx0_temp_comp); + DBGPRINT(RT_DEBUG_TRACE, ("%s::Tx0 power compensation = 0x%x\n", + __FUNCTION__, tx0_temp_comp & 0x3f)); + + RTMP_IO_READ32(ad, TX_ALC_CFG_2, &tx1_temp_comp); + tx1_temp_comp &= ~TX_ALC_CFG_2_TX1_TEMP_COMP_MASK; + tx1_temp_comp |= ((tc_init_val + dB_diff*2) & TX_ALC_CFG_2_TX1_TEMP_COMP_MASK); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_2, tx1_temp_comp); + DBGPRINT(RT_DEBUG_TRACE, ("%s::Tx1 power compensation = 0x%x\n", + __FUNCTION__, tx1_temp_comp & 0x3f)); + } +} +#endif /* RTMP_TEMPERATURE_TX_ALC */ + +#ifdef SINGLE_SKU_V2 +void mt76x2_single_sku(RTMP_ADAPTER *ad, u8 channel) +{ + CHAR sku_base_pwr = 0, ch_pwr_adj = 0; + CHAR delta_power = 0; + UINT32 reg_val = 0; + + if (channel > 14) { + if ((ad->chipCap.temp_tx_alc_enable == FALSE) && (ad->chipCap.tssi_enable == TRUE)) { + if ((channel >= 36) && (channel <= 48)) + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_a_band[A_BAND_GRP1_CHL]; + else if ((channel >= 52) && (channel <= 64)) + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_a_band[A_BAND_GRP2_CHL]; + else if ((channel >= 98) && (channel <= 114)) + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_a_band[A_BAND_GRP3_CHL]; + else if ((channel >= 116) && (channel <= 144)) + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_a_band[A_BAND_GRP4_CHL]; + else if ((channel >= 149) && (channel <= 165)) + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_a_band[A_BAND_GRP5_CHL]; + else + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_a_band[A_BAND_GRP0_CHL]; + } else + ad->DefaultTargetPwr = ad->chipCap.tssi_off_54m_target_pwr_a_band; +#ifdef DOT11_VHT_AC + if (ad->CommonCfg.BBPCurrentBW == BW_80) + delta_power = ad->chipCap.delta_tx_pwr_bw80; + else +#endif /* DOT11_VHT_AC */ + delta_power = ad->chipCap.delta_tx_pwr_bw40_a_band; + } else { + if ((ad->chipCap.temp_tx_alc_enable == FALSE) && (ad->chipCap.tssi_enable == TRUE)) + ad->DefaultTargetPwr = ad->chipCap.tssi_54m_target_pwr_g_band; + else + ad->DefaultTargetPwr = ad->chipCap.tssi_off_54m_target_pwr_g_band; + delta_power = ad->chipCap.delta_tx_pwr_bw40_g_band; + } + + if ((ad->DefaultTargetPwr == 0x00) || (ad->DefaultTargetPwr == 0xFF)) { + ad->DefaultTargetPwr = 0x20; + DBGPRINT(RT_DEBUG_ERROR, ("%s::failed to get the target power, and turn to use default = %d\n", + __FUNCTION__, ad->DefaultTargetPwr)); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultTargetPwr = %d\n", + __FUNCTION__, ad->DefaultTargetPwr)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultTargetPwr = 0x%x, delta_power = 0x%x\n", + __FUNCTION__, ad->DefaultTargetPwr, delta_power)); + + if ((ad->chipCap.temp_tx_alc_enable == TRUE) && (ad->chipCap.tssi_enable == FALSE)) { + sku_base_pwr = mt76x2_get_sku_channel_base_pwr(ad, channel); + + if (ad->DefaultTargetPwr > sku_base_pwr) + ch_pwr_adj = sku_base_pwr - ad->DefaultTargetPwr; + else + ch_pwr_adj = 0; + + if (ch_pwr_adj > 31) + ch_pwr_adj = 31; + if (ch_pwr_adj < -32) + ch_pwr_adj = -32; + + RTMP_IO_READ32(ad, TX_ALC_CFG_1, ®_val); + reg_val = (reg_val & ~0x3F) | (ch_pwr_adj & 0x3F); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_1, reg_val); + + RTMP_IO_READ32(ad, TX_ALC_CFG_2, ®_val); + reg_val = (reg_val & ~0x3F) | (ch_pwr_adj & 0x3F); + RTMP_IO_WRITE32(ad, TX_ALC_CFG_2, reg_val); + + ad->tc_init_val = ch_pwr_adj & 0x3F; + + DBGPRINT(RT_DEBUG_ERROR, ("%s::sku_base_pwr = 0x%x, DefaultTargetPwr = 0x%x, ch_pwr_adj = 0x%x(%d), 0x13B4: 0x%x\n", + __FUNCTION__, sku_base_pwr, ad->DefaultTargetPwr, ch_pwr_adj, ch_pwr_adj, reg_val)); + } + + mt76x2_update_sku_pwr(ad, channel); + + ad->sku_init_done = TRUE; +} + +void mt76x2_read_single_sku_info_from_eeprom(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *pChipCap = &ad->chipCap; + USHORT ee_val = 0; + UCHAR delta_power = 0; + + /* TSSI off 2.4G Tx power SKU */ + RT28xx_EEPROM_READ16(ad, 0xF7, ee_val); + pChipCap->tssi_off_54m_target_pwr_g_band = ee_val & 0xFF; + + /* TSSI off 5G Tx power SKU */ + RT28xx_EEPROM_READ16(ad, 0xF8, ee_val); + pChipCap->tssi_off_54m_target_pwr_a_band = ee_val & 0xFF; + + /* TSSI on 2.4G Tx power */ + RT28xx_EEPROM_READ16(ad, 0x58, ee_val); + pChipCap->tssi_54m_target_pwr_g_band = ee_val & 0xFF; + + /* TSSI on 5G Tx power (Group0) */ + RT28xx_EEPROM_READ16(ad, 0x64, ee_val); + pChipCap->tssi_54m_target_pwr_a_band[A_BAND_GRP0_CHL] = ee_val & 0xFF; + + /* TSSI on 5G Tx power (Group1) */ + RT28xx_EEPROM_READ16(ad, 0x69, ee_val); + pChipCap->tssi_54m_target_pwr_a_band[A_BAND_GRP1_CHL] = ee_val & 0xFF; + + /* TSSI on 5G Tx power (Group2) */ + RT28xx_EEPROM_READ16(ad, 0x6E, ee_val); + pChipCap->tssi_54m_target_pwr_a_band[A_BAND_GRP2_CHL] = ee_val & 0xFF; + + /* TSSI on 5G Tx power (Group3) */ + RT28xx_EEPROM_READ16(ad, 0x73, ee_val); + pChipCap->tssi_54m_target_pwr_a_band[A_BAND_GRP3_CHL] = ee_val & 0xFF; + + /* TSSI on 5G Tx power (Group4) */ + RT28xx_EEPROM_READ16(ad, 0x78, ee_val); + pChipCap->tssi_54m_target_pwr_a_band[A_BAND_GRP4_CHL] = ee_val & 0xFF; + + /* TSSI on 5G Tx power (Group5) */ + RT28xx_EEPROM_READ16(ad, 0x7D, ee_val); + pChipCap->tssi_54m_target_pwr_a_band[A_BAND_GRP5_CHL] = ee_val & 0xFF; +} + +void mt76x2_make_up_rate_pwr_table(RTMP_ADAPTER *ad) +{ + UINT32 reg_val = 0; + + RTMP_IO_READ32(ad, TX_PWR_CFG_0, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_0, reg_val)); + ad->chipCap.rate_pwr_table.CCK[0].mcs_pwr= (CHAR)(reg_val & 0x3F); /* CCK 1M */ + if (ad->chipCap.rate_pwr_table.CCK[0].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.CCK[0].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.CCK[1].mcs_pwr = ad->chipCap.rate_pwr_table.CCK[0].mcs_pwr; /* CCK 2M */ + + ad->chipCap.rate_pwr_table.CCK[2].mcs_pwr = (CHAR)((reg_val & 0x3F00) >> 8); /* CCK 5.5M */ + if (ad->chipCap.rate_pwr_table.CCK[2].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.CCK[2].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.CCK[3].mcs_pwr = ad->chipCap.rate_pwr_table.CCK[2].mcs_pwr; /* CCK 11M */ + + ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr = (CHAR)((reg_val & 0x3F0000) >> 16); /* OFDM 6M */ + if (ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.OFDM[1].mcs_pwr = ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr; /* OFDM 9M */ + + ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr = (CHAR)((reg_val & 0x3F000000) >> 24); /* OFDM 12M */ + if (ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.OFDM[3].mcs_pwr = ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr; /* OFDM 18M */ + + RTMP_IO_READ32(ad, TX_PWR_CFG_1, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_1, reg_val)); + ad->chipCap.rate_pwr_table.OFDM[4].mcs_pwr = (CHAR)(reg_val & 0x3F); /* OFDM 24M */ + if (ad->chipCap.rate_pwr_table.OFDM[4].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.OFDM[4].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.OFDM[5].mcs_pwr = ad->chipCap.rate_pwr_table.OFDM[4].mcs_pwr; /* OFDM 36M */ + + ad->chipCap.rate_pwr_table.OFDM[6].mcs_pwr = (CHAR)((reg_val & 0x3F00) >> 8); /* OFDM 48M */ + if (ad->chipCap.rate_pwr_table.OFDM[6].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.OFDM[6].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.HT[0].mcs_pwr = (CHAR)((reg_val&0x3F0000) >> 16); /* HT/VHT1SS MCS0 */ + if (ad->chipCap.rate_pwr_table.HT[0].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[0].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT1SS[0].mcs_pwr = ad->chipCap.rate_pwr_table.HT[0].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[1].mcs_pwr = ad->chipCap.rate_pwr_table.HT[0].mcs_pwr; /* HT/VHT1SS MCS1 */ + ad->chipCap.rate_pwr_table.VHT1SS[1].mcs_pwr = ad->chipCap.rate_pwr_table.VHT1SS[0].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[2].mcs_pwr = (CHAR)((reg_val & 0x3F000000) >> 24); /* HT/VHT1SS MCS2 */ + if (ad->chipCap.rate_pwr_table.HT[2].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[2].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT1SS[2].mcs_pwr = ad->chipCap.rate_pwr_table.HT[2].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[3].mcs_pwr = ad->chipCap.rate_pwr_table.HT[2].mcs_pwr; /* HT/VHT1SS MCS3 */ + ad->chipCap.rate_pwr_table.VHT1SS[3].mcs_pwr = ad->chipCap.rate_pwr_table.VHT1SS[2].mcs_pwr; + + RTMP_IO_READ32(ad, TX_PWR_CFG_2, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_2, reg_val)); + ad->chipCap.rate_pwr_table.HT[4].mcs_pwr = (CHAR)(reg_val & 0x3F); /* HT/VHT1SS MCS4 */ + if (ad->chipCap.rate_pwr_table.HT[4].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[4].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT1SS[4].mcs_pwr = ad->chipCap.rate_pwr_table.HT[4].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[5].mcs_pwr = ad->chipCap.rate_pwr_table.HT[4].mcs_pwr; /* HT/VHT1SS MCS5 */ + ad->chipCap.rate_pwr_table.VHT1SS[5].mcs_pwr = ad->chipCap.rate_pwr_table.VHT1SS[4].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[6].mcs_pwr = (CHAR)((reg_val & 0x3F00) >> 8); /* HT/VHT1SS MCS6 */ + if (ad->chipCap.rate_pwr_table.HT[6].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[6].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT1SS[6].mcs_pwr = ad->chipCap.rate_pwr_table.HT[6].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[8].mcs_pwr = (CHAR)((reg_val & 0x3F0000) >> 16); /* HT MCS8 / VHT2SS MCS0 */ + if (ad->chipCap.rate_pwr_table.HT[8].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[8].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT2SS[0].mcs_pwr = ad->chipCap.rate_pwr_table.HT[8].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[9].mcs_pwr = ad->chipCap.rate_pwr_table.HT[8].mcs_pwr; /* HT MCS9 / VHT2SS MCS1 */ + ad->chipCap.rate_pwr_table.VHT2SS[1].mcs_pwr = ad->chipCap.rate_pwr_table.VHT2SS[0].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[10].mcs_pwr = (CHAR)((reg_val&0x3F000000) >> 24); /* HT MCS10 / VHT2SS MCS2 */ + if (ad->chipCap.rate_pwr_table.HT[10].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[10].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT2SS[2].mcs_pwr = ad->chipCap.rate_pwr_table.HT[10].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[11].mcs_pwr = ad->chipCap.rate_pwr_table.HT[10].mcs_pwr; /* HT MCS11 / VHT2SS MCS3 */ + ad->chipCap.rate_pwr_table.VHT2SS[3].mcs_pwr = ad->chipCap.rate_pwr_table.VHT2SS[2].mcs_pwr; + + RTMP_IO_READ32(ad, TX_PWR_CFG_3, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_3, reg_val)); + ad->chipCap.rate_pwr_table.HT[12].mcs_pwr = (CHAR)(reg_val & 0x3F); /* HT MCS12 / VHT2SS MCS4 */ + if (ad->chipCap.rate_pwr_table.HT[12].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[12].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT2SS[4].mcs_pwr = ad->chipCap.rate_pwr_table.HT[12].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[13].mcs_pwr = ad->chipCap.rate_pwr_table.HT[12].mcs_pwr; /* HT MCS13 / VHT2SS MCS5 */ + ad->chipCap.rate_pwr_table.VHT2SS[5].mcs_pwr = ad->chipCap.rate_pwr_table.VHT2SS[4].mcs_pwr; + + ad->chipCap.rate_pwr_table.HT[14].mcs_pwr = (CHAR)((reg_val & 0x3F00) >> 8); /* HT MCS14 / VHT2SS MCS6 */ + if (ad->chipCap.rate_pwr_table.HT[14].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[14].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT2SS[6].mcs_pwr = ad->chipCap.rate_pwr_table.HT[14].mcs_pwr; + + ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr = (CHAR)((reg_val & 0x3F0000) >> 16); /* HT/VHT STBC MCS0 */ + if (ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.STBC[1].mcs_pwr = ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr; /* HT/VHT STBC MCS1 */ + + ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr = (CHAR)((reg_val&0x3F000000) >> 24); /* HT/VHT STBC MCS2 */ + if (ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.STBC[3].mcs_pwr = ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr; /* HT/VHT STBC MCS3 */ + + RTMP_IO_READ32(ad, TX_PWR_CFG_4, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_4, reg_val)); + ad->chipCap.rate_pwr_table.STBC[4].mcs_pwr = (CHAR)(reg_val & 0x3F); /* HT/VHT STBC MCS4 */ + if (ad->chipCap.rate_pwr_table.STBC[4].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[4].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.STBC[5].mcs_pwr = ad->chipCap.rate_pwr_table.STBC[4].mcs_pwr; /* HT/VHT STBC MCS5 */ + + ad->chipCap.rate_pwr_table.STBC[6].mcs_pwr = (CHAR)((reg_val & 0x3F00) >> 8); /* HT/VHT STBC MCS6 */ + if (ad->chipCap.rate_pwr_table.STBC[6].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[6].mcs_pwr -= 64; + + RTMP_IO_READ32(ad, TX_PWR_CFG_7, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_7, reg_val)); + ad->chipCap.rate_pwr_table.OFDM[7].mcs_pwr = (CHAR)(reg_val & 0x3F); /* OFDM 54M */ + if (ad->chipCap.rate_pwr_table.OFDM[7].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.OFDM[7].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.VHT2SS[8].mcs_pwr = (CHAR)((reg_val & 0x3F00) >> 8); /* VHT2SS MCS8 */ + if (ad->chipCap.rate_pwr_table.VHT2SS[8].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.VHT2SS[8].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.HT[7].mcs_pwr = (CHAR)((reg_val & 0x3F0000) >> 16); /* HT/VHT1SS MCS7 */ + if (ad->chipCap.rate_pwr_table.HT[7].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[7].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT1SS[7].mcs_pwr = ad->chipCap.rate_pwr_table.HT[7].mcs_pwr; + + ad->chipCap.rate_pwr_table.VHT2SS[9].mcs_pwr = (CHAR)((reg_val&0x3F000000) >> 24); /* VHT2SS MCS9 */ + if (ad->chipCap.rate_pwr_table.VHT2SS[9].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.VHT2SS[9].mcs_pwr -= 64; + + RTMP_IO_READ32(ad, TX_PWR_CFG_8, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_8, reg_val)); + ad->chipCap.rate_pwr_table.HT[15].mcs_pwr = (CHAR)(reg_val & 0x3F); /* HT MCS15 / VHT2SS MCS7 */ + if (ad->chipCap.rate_pwr_table.HT[15].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.HT[15].mcs_pwr -= 64; + ad->chipCap.rate_pwr_table.VHT2SS[7].mcs_pwr = ad->chipCap.rate_pwr_table.HT[15].mcs_pwr; + + ad->chipCap.rate_pwr_table.VHT1SS[8].mcs_pwr = (CHAR)((reg_val & 0x3F0000) >> 16); /* VHT1SS MCS8 */ + if (ad->chipCap.rate_pwr_table.VHT1SS[8].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.VHT1SS[8].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.VHT1SS[9].mcs_pwr = (CHAR)((reg_val & 0x3F000000) >> 24); /* VHT1SS MCS9 */ + if (ad->chipCap.rate_pwr_table.VHT1SS[9].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.VHT1SS[9].mcs_pwr -= 64; + + RTMP_IO_READ32(ad, TX_PWR_CFG_9, ®_val); + DBGPRINT(RT_DEBUG_TRACE, ("0x%x: 0x%x\n", TX_PWR_CFG_9, reg_val)); + ad->chipCap.rate_pwr_table.STBC[7].mcs_pwr = (CHAR)(reg_val & 0x3F); /* HT/VHT STBC MCS7 */ + if (ad->chipCap.rate_pwr_table.STBC[7].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[7].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.STBC[8].mcs_pwr = (CHAR)((reg_val & 0x3F0000) >> 16); /* VHT STBC MCS8 */ + if (ad->chipCap.rate_pwr_table.STBC[8].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[8].mcs_pwr -= 64; + + ad->chipCap.rate_pwr_table.STBC[9].mcs_pwr = (CHAR)((reg_val&0x3F000000) >> 24); /* VHT STBC MCS9 */ + if (ad->chipCap.rate_pwr_table.STBC[9].mcs_pwr & 0x20) + ad->chipCap.rate_pwr_table.STBC[9].mcs_pwr -= 64; + + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.CCK[0].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.CCK[0].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.CCK[1].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.CCK[1].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.CCK[2].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.CCK[2].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.CCK[3].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.CCK[3].mcs_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[0].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[1].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[1].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[2].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[3].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[3].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[4].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[4].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[5].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[5].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[6].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[6].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.OFDM[7].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.OFDM[7].mcs_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[0].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[0].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[1].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[1].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[2].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[2].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[3].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[3].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[4].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[4].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[5].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[5].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[6].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[6].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[7].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[7].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[8].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[8].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[9].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[9].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[10].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[10].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[11].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[11].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[12].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[12].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[13].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[13].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[14].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[14].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.HT[15].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.HT[15].mcs_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[0].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[0].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[1].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[1].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[2].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[2].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[3].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[3].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[4].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[4].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[5].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[5].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[6].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[6].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[7].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[7].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[8].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[8].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT1SS[9].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT1SS[9].mcs_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[0].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[0].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[1].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[1].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[2].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[2].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[3].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[3].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[4].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[4].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[5].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[5].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[6].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[6].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[7].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[7].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[8].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[8].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.VHT2SS[9].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.VHT2SS[9].mcs_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[0].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[1].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[1].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[2].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[3].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[3].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[4].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[4].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[5].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[5].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[6].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[6].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[7].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[7].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[8].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[8].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.STBC[9].MCS_Power = %d\n", ad->chipCap.rate_pwr_table.STBC[9].mcs_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr_table.MCS32.MCS_Power = %d\n", ad->chipCap.rate_pwr_table.MCS32.mcs_pwr)); +} + +UCHAR mt76x2_get_sku_channel_base_pwr(RTMP_ADAPTER *ad, u8 channel) +{ + CH_POWER *ch, *ch_temp; + UCHAR start_ch = 0, base_pwr = ad->DefaultTargetPwr; + UINT8 i = 0, j = 0; + + DlListForEachSafe(ch, ch_temp, &ad->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + + if (channel >= start_ch) { + for (j = 0; j < ch->num; j++) + { + if (channel == ch->Channel[j]) { + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> channel = %d, ch->channel = %d\n", + __FUNCTION__, channel, ch->Channel[j])); + + if (channel <= 14) { + for (i = 0; i < SINGLE_SKU_TABLE_CCK_LENGTH; i++) + { + if (base_pwr > ch->PwrCCK[i]) + base_pwr = ch->PwrCCK[i]; + } + } + + for (i = 0; i < SINGLE_SKU_TABLE_OFDM_LENGTH; i++) + { + if (base_pwr > ch->PwrOFDM[i]) + base_pwr = ch->PwrOFDM[i]; + } + + if (ad->CommonCfg.BBPCurrentBW == BW_20) { + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + if (ch->PwrHT20[i] == 0) + break; + + if (base_pwr > ch->PwrHT20[i]) + base_pwr = ch->PwrHT20[i]; + } + } + + if (ad->CommonCfg.BBPCurrentBW == BW_40) { + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + if (ch->PwrHT40[i] == 0) + break; + + if (base_pwr > ch->PwrHT40[i]) + base_pwr = ch->PwrHT40[i]; + } + } + + if (ad->CommonCfg.BBPCurrentBW == BW_80) { + for (i = 0; i < SINGLE_SKU_TABLE_VHT_LENGTH; i++) + { + if (ch->PwrVHT80[i] == 0) + break; + + if (base_pwr > ch->PwrVHT80[i]) + base_pwr = ch->PwrVHT80[i]; + } + } + + break; + } + } + } + } + + return base_pwr; +} + +void mt76x2_update_per_rate_pwr(RTMP_ADAPTER *ad) +{ + UINT32 data = 0; + UCHAR t1 = 0, t2 = 0, t3 = 0, t4 = 0; + UINT band; + UCHAR channel=0; + RTMP_CHIP_CAP *cap = &ad->chipCap; +#ifdef RALINK_ATE + if(ATE_ON(ad)) + channel = ad->ate.Channel; + else +#endif /* RALINK_ATE */ + channel = ad->CommonCfg.Channel; + + if (channel > 14) + band = _A_BAND; + else + band = _G_BAND; + + /* + Bit 29:24 -> OFDM 12M/18M + Bit 21:16 -> OFDM 6M/9M + Bit 13:8 -> CCK 5.5M/11M + Bit 5:0 -> CCK 1M/2M + */ + t1 = ad->chipCap.rate_pwr_table.CCK[0].mcs_pwr + cap->tx_pwr_cck_1_2_compensate; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t2 = ad->chipCap.rate_pwr_table.CCK[2].mcs_pwr + cap->tx_pwr_cck_5_11_compensate; + t2 = (t2 & 0x80) ? ((t2 & 0x1f) | 0x20) : (t2 & 0x3f); + + if(band == _G_BAND) + t3 = ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr + cap->tx_pwr_g_band_ofdm_6_9_compensate; + else + t3 = ad->chipCap.rate_pwr_table.OFDM[0].mcs_pwr + cap->tx_pwr_a_band_ofdm_6_9_compensate; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + if(band == _G_BAND) + t4 = ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr + cap->tx_pwr_g_band_ofdm_12_18_compensate; + else + t4 = ad->chipCap.rate_pwr_table.OFDM[2].mcs_pwr + cap->tx_pwr_a_band_ofdm_12_18_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + data = (t4 << 24) | (t3 << 16) | (t2 << 8) | t1; + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_0, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_0, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_0, data)); + + /* + Bit 29:24 -> HT/VHT1SS MCS 2/3 + Bit 21:16 -> HT/VHT1SS MCS 0/1 + Bit 13:8 -> OFDM 48M + Bit 5:0 -> OFDM 24M/36M + */ + t1 = ad->chipCap.rate_pwr_table.OFDM[4].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t2 = ad->chipCap.rate_pwr_table.OFDM[6].mcs_pwr; + t2 = (t2 & 0x80) ? ((t2 & 0x1f) | 0x20) : (t2 & 0x3f); + + if(band == _G_BAND) + t3 = ad->chipCap.rate_pwr_table.HT[0].mcs_pwr + cap->tx_pwr_g_band_ht_mcs_0_1_compensate; + else + t3 = ad->chipCap.rate_pwr_table.HT[0].mcs_pwr + cap->tx_pwr_a_band_ht_mcs_0_1_compensate; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + if(band == _G_BAND) + t4 = ad->chipCap.rate_pwr_table.HT[2].mcs_pwr + cap->tx_pwr_g_band_ht_mcs_2_3_compensate; + else + t4 = ad->chipCap.rate_pwr_table.HT[2].mcs_pwr + cap->tx_pwr_a_band_ht_mcs_2_3_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + data = (t4 << 24) | (t3 << 16) | (t2 << 8) | t1; + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_1, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_1, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_1, data)); + + /* + Bit 29:24 -> HT MCS 10/11 / VHT2SS MCS 2/3 + Bit 21:16 -> HT MCS 8/9 / VHT2SS MCS 0/1 + Bit 13:8 -> HT/VHT1SS MCS 6 + Bit 5:0 -> HT/VHT1SS MCS 4/5 + */ + RTMP_IO_READ32(ad, TX_PWR_CFG_2, &data); + t1 = ad->chipCap.rate_pwr_table.HT[4].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t2 = ad->chipCap.rate_pwr_table.HT[6].mcs_pwr; + t2 = (t2 & 0x80) ? ((t2 & 0x1f) | 0x20) : (t2 & 0x3f); + + if(band == _G_BAND) + t3 = ad->chipCap.rate_pwr_table.HT[8].mcs_pwr + cap->tx_pwr_g_band_ht_mcs_0_1_compensate; + else + t3 = ad->chipCap.rate_pwr_table.HT[8].mcs_pwr + cap->tx_pwr_a_band_ht_mcs_0_1_compensate; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + if(band == _G_BAND) + t4 = ad->chipCap.rate_pwr_table.HT[10].mcs_pwr + cap->tx_pwr_g_band_ht_mcs_2_3_compensate; + else + t4 = ad->chipCap.rate_pwr_table.HT[10].mcs_pwr + cap->tx_pwr_a_band_ht_mcs_2_3_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + data = (t4 << 24) | (t3 << 16) | (t2 << 8) | t1; + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_2, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_2, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_2, data)); + + /* + Bit 29:24 -> HT/VHT STBC MCS 2/3 + Bit 21:16 -> HT/VHT STBC MCS 0/1 + Bit 13:8 -> HT MCS 14 / VHT2SS MCS 6 + Bit 5:0 -> HT MCS 12/13 / VHT2SS MCS 4/5 + */ + RTMP_IO_READ32(ad, TX_PWR_CFG_3, &data); + t1 = ad->chipCap.rate_pwr_table.HT[12].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t2 = ad->chipCap.rate_pwr_table.HT[14].mcs_pwr; + t2 = (t2 & 0x80) ? ((t2 & 0x1f) | 0x20) : (t2 & 0x3f); + + if(band == _G_BAND) + t3 = ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr + cap->tx_pwr_g_band_ht_mcs_0_1_compensate; + else + t3 = ad->chipCap.rate_pwr_table.STBC[0].mcs_pwr + cap->tx_pwr_a_band_ht_mcs_0_1_compensate; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + if(band == _G_BAND) + t4 = ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr + cap->tx_pwr_g_band_ht_mcs_2_3_compensate; + else + t4 = ad->chipCap.rate_pwr_table.STBC[2].mcs_pwr + cap->tx_pwr_a_band_ht_mcs_2_3_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + data = (t4 << 24) | (t3 << 16) | (t2 << 8) | t1; + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_3, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_3, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_3, data)); + + /* + Bit 13:8 -> HT/VHT STBC MCS 6 + Bit 5:0 -> HT/VHT STBC MCS 4/5 + */ + RTMP_IO_READ32(ad, TX_PWR_CFG_4, &data); + t1 = ad->chipCap.rate_pwr_table.STBC[4].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t2 = ad->chipCap.rate_pwr_table.STBC[6].mcs_pwr; + t2 = (t2 & 0x80) ? ((t2 & 0x1f) | 0x20) : (t2 & 0x3f); + + data &= 0xFFFF0000; + data = (t2 << 8) | t1; + RTMP_IO_WRITE32(ad, TX_PWR_CFG_4, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_4, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_4, data)); + + /* + Bit 29:24 -> VHT2SS MCS 9 + Bit 21:16 -> HT/VHT1SS MCS 7 + Bit 13:8 -> VHT2SS MCS 8 + Bit 5:0 -> OFDM 54M + */ + RTMP_IO_READ32(ad, TX_PWR_CFG_7, &data); + t1 = ad->chipCap.rate_pwr_table.OFDM[7].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t2 = ad->chipCap.rate_pwr_table.VHT2SS[8].mcs_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate; + t2 = (t2 & 0x80) ? ((t2 & 0x1f) | 0x20) : (t2 & 0x3f); + + t3 = ad->chipCap.rate_pwr_table.HT[7].mcs_pwr; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + t4 = ad->chipCap.rate_pwr_table.VHT2SS[9].mcs_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + data = (t4 << 24) | (t3 << 16) | (t2 << 8) | t1; + + RTMP_IO_WRITE32(ad, TX_PWR_CFG_7, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_7, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_7, data)); + + /* + Bit 29:24 -> VHT1SS MCS 9 + Bit 21:16 -> VHT1SS MCS 8 + Bit 5:0 -> HT MCS 15 / VHT2SS MCS 7 + */ + RTMP_IO_READ32(ad, TX_PWR_CFG_8, &data); + t1 = ad->chipCap.rate_pwr_table.HT[15].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t3 = ad->chipCap.rate_pwr_table.VHT1SS[8].mcs_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + t4 = ad->chipCap.rate_pwr_table.VHT1SS[9].mcs_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + + data &= 0xFF00; + data = (t4 << 24) | (t3 << 16) | t1; + RTMP_IO_WRITE32(ad, TX_PWR_CFG_8, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_8, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_8, data)); + + /* + Bit 29:24 -> VHT STBC MCS 9 + Bit 21:16 -> VHT STBC MCS 8 + Bit 5:0 -> HT/VHT STBC MCS 7 + */ + RTMP_IO_READ32(ad, TX_PWR_CFG_9, &data); + t1= ad->chipCap.rate_pwr_table.STBC[7].mcs_pwr; + t1 = (t1 & 0x80) ? ((t1 & 0x1f) | 0x20) : (t1 & 0x3f); + + t3 = ad->chipCap.rate_pwr_table.STBC[8].mcs_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate; + t3 = (t3 & 0x80) ? ((t3 & 0x1f) | 0x20) : (t3 & 0x3f); + + t4 = ad->chipCap.rate_pwr_table.STBC[9].mcs_pwr + cap->tx_pwr_5g_vht_mcs_8_9_compensate; + t4 = (t4 & 0x80) ? ((t4 & 0x1f) | 0x20) : (t4 & 0x3f); + + data &= 0xFF00; + data = (t4 << 24) | (t3 << 16) | t1; + RTMP_IO_WRITE32(ad, TX_PWR_CFG_9, data); + RTMP_IO_READ32(ad, TX_PWR_CFG_9, &data); + DBGPRINT(RT_DEBUG_TRACE, ("%s - 0x%x: 0x%08X\n", __FUNCTION__, TX_PWR_CFG_9, data)); +} + +UCHAR mt76x2_update_sku_pwr(RTMP_ADAPTER *ad, u8 channel) +{ + CH_POWER *ch, *ch_temp; + INT32 i = 0, j = 0, pwr_delta = 0; + UINT32 reg_val = 0; + CHAR ch_delta_pwr = 0; + INT32 rate_pwr = 0, rate_pwr_before_adjust = 0, sku_pwr = 0; + BOOLEAN bFound = FALSE; + UCHAR start_ch = 0; + const CHAR DefaultTargetPwr = ad->DefaultTargetPwr; + UCHAR currentBW = ad->CommonCfg.BBPCurrentBW; + +#ifdef CONFIG_STA_SUPPORT + /* + for STA mode & ATE_ON , follow ATE BW + because BBPCurrentBW of STA maybe BW20 due to sitesurvey, + will lead to inaccuracy if ATESTART & try to kick BW40 pkt + */ + if(ad->OpMode == OPMODE_STA && ATE_ON(ad)) + { + currentBW = (UCHAR)ad->ate.TxWI.TXWI_N.BW; + DBGPRINT(RT_DEBUG_ERROR, ("%s - FOLLOWING ATE BW : %d\n",__FUNCTION__,currentBW)); + } +#endif /*CONFIG_STA_SUPPORT*/ + + if ((ad->chipCap.temp_tx_alc_enable == TRUE) && (ad->chipCap.tssi_enable == FALSE)) { + /* + Get power temperature compensation + Format: 6-bit, signed value + Unit: 0.5dB, range: -10 ~ 10dB + */ + RTMP_IO_READ32(ad, TX_ALC_CFG_1, ®_val); + ch_delta_pwr = (UCHAR)(reg_val & 0x3F); + if (ch_delta_pwr & 0x20) + ch_delta_pwr -= 64; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> 0x%08X = 0x%08X, ch_delta_pwr = %d\n", + __FUNCTION__, TX_ALC_CFG_1, reg_val, ch_delta_pwr)); + } else + ch_delta_pwr = 0; + + /* + Get per rate power delta + */ + mt76x2_make_up_rate_pwr_table(ad); + + DlListForEachSafe(ch, ch_temp, &ad->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + + if (channel >= start_ch) { + for (j = 0; j < ch->num; j++) + { + if (channel == ch->Channel[j]) { + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> channel = %d, ch->channel = %d\n", + __FUNCTION__, channel, ch->Channel[j])); + + for (i = 0; i < SINGLE_SKU_TABLE_CCK_LENGTH; i++) + { + pwr_delta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> CCK[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.CCK[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.CCK[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + sku_pwr = (ch->PwrCCK[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrCCK[i]; + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.CCK[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.CCK[i].sku_pwr = sku_pwr; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> sku_pwr (%d) - rate_pwr (%d) = rate_delta (%d)\n", + __FUNCTION__, sku_pwr, rate_pwr, pwr_delta)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new CCK[%d].MCS_Power = %d\n\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.CCK[i].mcs_pwr)); + } + + for (i = 0; i < SINGLE_SKU_TABLE_OFDM_LENGTH; i++) + { + pwr_delta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> OFDM[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.OFDM[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.OFDM[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + sku_pwr = (ch->PwrOFDM[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrOFDM[i]; + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.OFDM[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.OFDM[i].sku_pwr = sku_pwr; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> sku_pwr (%d) - rate_pwr (%d) = rate_delta (%d)\n", + __FUNCTION__, sku_pwr, rate_pwr, pwr_delta)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new OFDM[%d].MCS_Power = %d\n\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.OFDM[i].mcs_pwr)); + } + + if (currentBW != BW_80) { + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + pwr_delta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> HT[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.HT[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.HT[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + + if (currentBW == BW_40) + { + //store HT20 sku_pwr for TXWI + ad->chipCap.rate_pwr_table.HT20[i].sku_pwr = (ch->PwrHT20[i] > rate_pwr_before_adjust)? \ + rate_pwr_before_adjust : ch->PwrHT20[i]; + //store HT40 sku_pwr for TXWI + ad->chipCap.rate_pwr_table.HT40[i].sku_pwr = (ch->PwrHT40[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrHT40[i]; + } + + if (currentBW == BW_20) + { + sku_pwr = (ch->PwrHT20[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrHT20[i]; + } else if (currentBW == BW_40) + { + sku_pwr = (ch->PwrHT40[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrHT40[i]; + } + + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.HT[i].mcs_pwr += pwr_delta; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> sku_pwr (%d) - rate_pwr (%d) = rate_delta (%d)\n", + __FUNCTION__, sku_pwr, rate_pwr, pwr_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new HT[%d].MCS_Power = %d\n\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.HT[i].mcs_pwr)); + } + + for (i = 8; i < SINGLE_SKU_TABLE_VHT_LENGTH; i++) + { + pwr_delta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> VHT1SS[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> VHT2SS[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + + pwr_delta = rate_pwr - ch->PwrVHT80[i]; + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + sku_pwr = (ch->PwrVHT80[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrVHT80[i]; + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.VHT1SS[i].sku_pwr = sku_pwr; + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + sku_pwr = (ch->PwrVHT80[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrVHT80[i]; + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.VHT2SS[i].sku_pwr = sku_pwr; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> sku_pwr (%d) - rate_pwr (%d) = rate_delta (%d)\n", + __FUNCTION__, sku_pwr, rate_pwr, pwr_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new VHT1SS[%d].MCS_Power = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new VHT2SS[%d].MCS_Power = %d\n\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr)); + } + } + else if (currentBW == BW_80) { + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + pwr_delta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> HT[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.HT[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.HT[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + + //store HT20 sku_pwr for TXWI + sku_pwr = (ch->PwrHT20[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrHT20[i]; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ############ rate_pwr_before_adjust = %d, ch->PwrHT20[i] = %d\n", + __FUNCTION__, rate_pwr_before_adjust, ch->PwrHT20[i])); + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.HT[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.HT20[i].sku_pwr = sku_pwr; + + //store HT40 sku_pwr for TXWI + sku_pwr = (ch->PwrHT40[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrHT40[i]; + ad->chipCap.rate_pwr_table.HT40[i].sku_pwr = sku_pwr; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> sku_pwr (%d) - rate_pwr (%d) = rate_delta (%d)\n", + __FUNCTION__, sku_pwr, rate_pwr, pwr_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new HT[%d].MCS_Power = %d\n\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.HT[i].mcs_pwr)); + } + + for (i = 0; i < SINGLE_SKU_TABLE_VHT_LENGTH; i++) + { + pwr_delta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> VHT1SS[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> VHT2SS[%d].MCS_Power = %d, DefaultTargetPwr = %d, ch_delta_pwr = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr, DefaultTargetPwr, ch_delta_pwr)); + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + sku_pwr = (ch->PwrVHT80[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrVHT80[i]; + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.VHT1SS[i].sku_pwr = sku_pwr; + + rate_pwr_before_adjust = ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr + DefaultTargetPwr; + rate_pwr = rate_pwr_before_adjust + ch_delta_pwr; + sku_pwr = (ch->PwrVHT80[i] > rate_pwr_before_adjust) ? \ + rate_pwr_before_adjust : ch->PwrVHT80[i]; + pwr_delta = sku_pwr - rate_pwr; + ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr += pwr_delta; + ad->chipCap.rate_pwr_table.VHT2SS[i].sku_pwr = sku_pwr; + + if (i < 8) { + ad->chipCap.rate_pwr_table.HT[i].mcs_pwr = ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr; + ad->chipCap.rate_pwr_table.HT[i + 8].mcs_pwr = ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> sku_pwr (%d) - rate_pwr (%d) = rate_delta (%d)\n", + __FUNCTION__, sku_pwr, rate_pwr, pwr_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new VHT1SS[%d].MCS_Power = %d\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT1SS[i].mcs_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> new VHT2SS[%d].MCS_Power = %d\n\n", + __FUNCTION__, i, ad->chipCap.rate_pwr_table.VHT2SS[i].mcs_pwr)); + } + } + + bFound = TRUE; + break; + } + } + } + } + + if (bFound) { + mt76x2_update_per_rate_pwr(ad); + return TRUE; + } + else + return FALSE; +} + +INT32 mt76x2_sku_calculate_TxPwrAdj(RTMP_ADAPTER *ad,struct _TXWI_NMAC *txwi_n) +{ + INT32 bw_delta = 0, sku_table_delta = 0; + INT32 result = 0, PwrAdj = 0; + UCHAR currentBW = ad->CommonCfg.BBPCurrentBW; + +#ifdef CONFIG_STA_SUPPORT + if(ad->OpMode == OPMODE_STA && ATE_ON(ad)) + currentBW = (UCHAR)ad->ate.TxWI.TXWI_N.BW; +#endif /*CONFIG_STA_SUPPORT*/ + + if(txwi_n->PHYMODE == MODE_HTMIX || txwi_n->PHYMODE == MODE_HTGREENFIELD || txwi_n->PHYMODE == MODE_VHT) + { + if(currentBW == BW_40 && txwi_n->BW == BW_20) + { + INT32 sku_pwr_HT20 = ad->chipCap.rate_pwr_table.HT20[txwi_n->MCS].sku_pwr; + INT32 sku_pwr_HT40 = ad->chipCap.rate_pwr_table.HT40[txwi_n->MCS].sku_pwr; + //get efuse BW delta + if(ad->CommonCfg.Channel < 14) + bw_delta = -ad->chipCap.delta_tx_pwr_bw40_g_band; + else + bw_delta = -ad->chipCap.delta_tx_pwr_bw40_a_band; + //get sku table delta + sku_table_delta = sku_pwr_HT20 - sku_pwr_HT40; + } + else if(currentBW == BW_80) + { + INT32 sku_pwr_HT20 = ad->chipCap.rate_pwr_table.HT20[txwi_n->MCS].sku_pwr; + INT32 sku_pwr_HT40 = ad->chipCap.rate_pwr_table.HT40[txwi_n->MCS].sku_pwr; + //get efuse BW delta + if (txwi_n->BW == BW_20) + bw_delta = -ad->chipCap.delta_tx_pwr_bw80; + else if (txwi_n->BW == BW_40) + bw_delta = -(ad->chipCap.delta_tx_pwr_bw80 - ad->chipCap.delta_tx_pwr_bw40_a_band); + //get sku table delta + if(txwi_n->MCS <= 9) + { + if (txwi_n->BW == BW_40) + sku_table_delta = sku_pwr_HT40 - ad->chipCap.rate_pwr_table.VHT1SS[txwi_n->MCS].sku_pwr; + else if (txwi_n->BW == BW_20) + sku_table_delta = sku_pwr_HT20 - ad->chipCap.rate_pwr_table.VHT1SS[txwi_n->MCS].sku_pwr; + } + else + { + if (txwi_n->BW == BW_40) + sku_table_delta = sku_pwr_HT40 - ad->chipCap.rate_pwr_table.VHT2SS[txwi_n->MCS-16].sku_pwr; + else if (txwi_n->BW == BW_20) + sku_table_delta = sku_pwr_HT20 - ad->chipCap.rate_pwr_table.VHT2SS[txwi_n->MCS-16].sku_pwr; + } + if(ad->bSingleSkuDebug) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s HT%s[%d] SKU PWR: %d VHT[%d] SKU PWR: %d\n" + , __FUNCTION__,(txwi_n->BW == BW_40)?"40":"20",txwi_n->MCS + ,(txwi_n->BW == BW_40)?sku_pwr_HT40:sku_pwr_HT20 + ,(txwi_n->MCS <= 9)?txwi_n->MCS:txwi_n->MCS-16 + ,(txwi_n->MCS <= 9)?ad->chipCap.rate_pwr_table.VHT1SS[txwi_n->MCS].sku_pwr:ad->chipCap.rate_pwr_table.VHT2SS[txwi_n->MCS-16].sku_pwr)); + } + } + //result = min(bw_delta,sku_table_delta)/2; + result = sku_table_delta/2; + if(result > 7){PwrAdj=7;} + else if(result >= 0){PwrAdj=result;} + else + { + switch(result) + { + case -1: + case -2: + PwrAdj = 15; + break; + + case -3: + case -4: + PwrAdj = 14; + break; + + case -5: + case -6: + PwrAdj = 13; + break; + case -7: + case -8: + PwrAdj = 12; + break; + + case -9: + case -10: + PwrAdj = 11; + break; + + case -11: + case -12: + PwrAdj = 10; + break; + + case -13: + case -14: + PwrAdj = 9; + break; + + case -15: + case -16: + PwrAdj = 8; + break; + } + } + if(ad->bSingleSkuDebug) //&&PwrAdj != 0 + { + DBGPRINT(RT_DEBUG_ERROR, ("%s txwi_n->BW:%d mcs: %d phymode:%d bw_delta:%d sku_table_delta:%d result:%d PwrAdj:%d\n" + , __FUNCTION__,txwi_n->BW,txwi_n->MCS,txwi_n->PHYMODE,bw_delta,sku_table_delta,result,PwrAdj)); + } + } + return PwrAdj; +} + +#endif /* SINGLE_SKU_V2 */ + +/*char *obtw_delta_str[]= +{ + "ofdm6m_", "ofdm9m_", "ofdm12m_", "ofdm18m_", + "ht20mcs0_", "ht20mcs1_", "ht20mcs2_", + "ht40mcs0_", "ht40mcs1_", "ht40mcs2_", "ht40mcs32_", + "vht80mcs0_", "vht80mcs1_", "vht80mcs2_" +};*/ + +extern char *obtw_delta_str[]; + +INT32 mt76x2_tx_pwr_boost(RTMP_ADAPTER *ad,struct _TXWI_NMAC *txwi_n) +{ + INT32 result=0; + + if(ad->obtw_anyEnable == FALSE) + return 0; + + switch(txwi_n->BW) + { + case BW_20: + switch(txwi_n->MCS) + { + case MCS_0: /*OFDM 6M | HT MCS0*/ + case MCS_8: + result = (txwi_n->PHYMODE == MODE_OFDM)?\ + ad->obtw_delta_array[0]:ad->obtw_delta_array[4]; + break; + case MCS_1: /*OFDM 9M | HT MCS1*/ + case MCS_9: + result = (txwi_n->PHYMODE == MODE_OFDM)?\ + ad->obtw_delta_array[1]:ad->obtw_delta_array[5]; + break; + case MCS_2: /*OFDM 12M | HT MCS2*/ + case MCS_10: + result = (txwi_n->PHYMODE == MODE_OFDM)?\ + ad->obtw_delta_array[2]:ad->obtw_delta_array[6]; + break; + case MCS_3: /*OFDM 18M | HT MCS3*/ + result = (txwi_n->PHYMODE == MODE_OFDM)?\ + ad->obtw_delta_array[3]:0; + break; + } + break; + case BW_40: + switch(txwi_n->MCS) + { + case MCS_0: + case MCS_8: + result = ad->obtw_delta_array[7]; + break; + case MCS_1: + case MCS_9: + result = ad->obtw_delta_array[8]; + break; + case MCS_2: + case MCS_10: + result = ad->obtw_delta_array[9]; + break; + case MCS_32: + result = ad->obtw_delta_array[10]; + break; + } + break; + case BW_80: + switch(txwi_n->MCS) + { + case MCS_0: + case 0x10: /*2SS MCS0*/ + result = ad->obtw_delta_array[11]; + break; + case MCS_1: + case 0x11: /*2SS MCS1*/ + result = ad->obtw_delta_array[12]; + break; + case MCS_2: + case 0x12: /*2SS MCS2*/ + result = ad->obtw_delta_array[13]; + break; + } + break; + default: + if(ad->obtw_debug_on) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s UNKNOWN case!!! txwi_n->BW:%d mcs: %d phymode:%d obtw_delta:%d\n" + , __FUNCTION__,txwi_n->BW,txwi_n->MCS,txwi_n->PHYMODE,result/2)); + } + } + + if(ad->obtw_debug_on) + DBGPRINT(RT_DEBUG_ERROR, ("%s txwi_n->BW:%d mcs: %d phymode:%d obtw_delta:%d\n" + , __FUNCTION__,txwi_n->BW,txwi_n->MCS,txwi_n->PHYMODE,result/2)); + + return result/2; +} + +#ifdef CONFIG_STA_SUPPORT +static VOID mt76x2_init_dev_nick_name(RTMP_ADAPTER *ad) +{ +#ifdef RTMP_MAC_PCI + if (IS_MT7662E(ad)) + snprintf((PSTRING) ad->nickname, sizeof(ad->nickname), "mt7662e_sta"); + else if (IS_MT7632E(ad)) + snprintf((PSTRING) ad->nickname, sizeof(ad->nickname), "mt7632e_sta"); + else if (IS_MT7612E(ad)) + snprintf((PSTRING) ad->nickname, sizeof(ad->nickname), "mt7612e_sta"); +#endif + +} +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CAL_FREE_IC_SUPPORT +static BOOLEAN mt76x2_is_cal_free_ic(RTMP_ADAPTER *ad) +{ + UINT16 NicConfig, FrequencyOffset; + UINT16 PowerDelta, TssiSlope, TxPower; + UINT EfuseFreeBlock=0; + + eFuseGetFreeBlockCount(ad, &EfuseFreeBlock); + + if ( EfuseFreeBlock < ad->chipCap.EFUSE_RESERVED_SIZE ) + return FALSE; + + eFuseReadRegisters(ad, XTAL_TRIM1, 2, &FrequencyOffset); + eFuseReadRegisters(ad, NIC_CONFIGURE_0, 2, &NicConfig); + + if ( !((NicConfig == 0x0) && ( FrequencyOffset != 0xFFFF ))) { + return FALSE; + } + + eFuseReadRegisters(ad, G_BAND_20_40_BW_PWR_DELTA, 2, &PowerDelta); + eFuseReadRegisters(ad, TX0_G_BAND_TSSI_SLOPE, 2, &TssiSlope); + + if ( !((PowerDelta == 0x0) && ( TssiSlope != 0xFFFF ))) { + return FALSE; + } + + eFuseReadRegisters(ad, GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW, 2, &TxPower); + eFuseReadRegisters(ad, GRP4_TX0_A_BAND_TSSI_SLOPE, 2, &TssiSlope); + + if ( !((TxPower == 0x0) && ( TssiSlope != 0xFFFF ))) { + return FALSE; + } + + return TRUE; + +} + + +static VOID mt76x2_cal_free_data_get(RTMP_ADAPTER *ad) +{ + UINT16 value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + /* 0x3A */ + eFuseReadRegisters(ad, XTAL_TRIM1, 2, &value); + ad->EEPROMImage[XTAL_TRIM1] = value & 0xFF; + + /* 0x55 0x56 0x57 0x5C 0x5D */ + eFuseReadRegisters(ad, A_BAND_EXT_PA_SETTING, 2, &value); + ad->EEPROMImage[A_BAND_EXT_PA_SETTING + 1] = (value >> 8) & 0xFF; + eFuseReadRegisters(ad, TX0_G_BAND_TSSI_SLOPE, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[TX0_G_BAND_TSSI_SLOPE]) = value; + eFuseReadRegisters(ad, TX1_G_BAND_TSSI_SLOPE, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[TX1_G_BAND_TSSI_SLOPE]) = value; + + /* 0x62 0x63 0x67 0x68 0x6C 0x6D */ + eFuseReadRegisters(ad, GRP0_TX0_A_BAND_TSSI_SLOPE, 2, &value); + if ( value != 0 ) + *(UINT16 *)(&ad->EEPROMImage[GRP0_TX0_A_BAND_TSSI_SLOPE]) = value; + eFuseReadRegisters(ad, GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI, 2, &value); + ad->EEPROMImage[GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI + 1] = (value & GRP1_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8; + eFuseReadRegisters(ad, GRP1_TX0_A_BAND_TSSI_OFFSET, 2, &value); + ad->EEPROMImage[GRP1_TX0_A_BAND_TSSI_OFFSET] = value & GRP1_TX0_A_BAND_TSSI_OFFSET_MASK; + eFuseReadRegisters(ad, GRP2_TX0_A_BAND_TSSI_SLOPE, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[GRP2_TX0_A_BAND_TSSI_SLOPE]) = value; + + /* 0x71 0x72 0x76 0x77 0x7B 0x7C */ + eFuseReadRegisters(ad, GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI, 2, &value); + ad->EEPROMImage[GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI + 1] = (value & GRP3_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8; + eFuseReadRegisters(ad, GRP3_TX0_A_BAND_TSSI_OFFSET, 2, &value); + ad->EEPROMImage[GRP3_TX0_A_BAND_TSSI_OFFSET] = value & GRP3_TX0_A_BAND_TSSI_OFFSET_MASK; + eFuseReadRegisters(ad, GRP4_TX0_A_BAND_TSSI_SLOPE, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[GRP4_TX0_A_BAND_TSSI_SLOPE]) = value; + eFuseReadRegisters(ad, GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI, 2, &value); + ad->EEPROMImage[GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI + 1] = (value & GRP5_TX0_A_BAND_TSSI_SLOPE_MASK) >> 8; + eFuseReadRegisters(ad, GRP5_TX0_A_BAND_TSSI_OFFSET, 2, &value); + ad->EEPROMImage[GRP5_TX0_A_BAND_TSSI_OFFSET] = value & GRP5_TX0_A_BAND_TSSI_OFFSET_MASK; + + /* 0x80 0x81 0x85 0x86 0x8A 0x8B 0x8F */ + eFuseReadRegisters(ad, GRP0_TX1_A_BAND_TSSI_SLOPE, 2, &value); + if ( value != 0 ) + *(UINT16 *)(&ad->EEPROMImage[GRP0_TX1_A_BAND_TSSI_SLOPE]) = value; + eFuseReadRegisters(ad, GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI, 2, &value); + ad->EEPROMImage[GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI + 1] = (value & GRP1_TX1_A_BAND_TSSI_SLOPE_MASK) >> 8; + eFuseReadRegisters(ad, GRP1_TX1_A_BAND_TSSI_OFFSET, 2, &value); + ad->EEPROMImage[GRP1_TX1_A_BAND_TSSI_OFFSET] = value & GRP1_TX1_A_BAND_TSSI_OFFSET_MASK; + eFuseReadRegisters(ad, GRP2_TX1_A_BAND_TSSI_SLOPE, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[GRP2_TX1_A_BAND_TSSI_SLOPE]) = value; + eFuseReadRegisters(ad, GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI, 2, &value); + ad->EEPROMImage[GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI + 1] = (value & GRP3_TX1_A_BAND_TSSI_SLOPE_MASK) >> 8; + + /* 0x90 0x94 0x95 0x99 0x9A */ + eFuseReadRegisters(ad, GRP3_TX1_A_BAND_TSSI_OFFSET, 2, &value); + ad->EEPROMImage[GRP3_TX1_A_BAND_TSSI_OFFSET] = value & GRP3_TX1_A_BAND_TSSI_OFFSET_MASK; + eFuseReadRegisters(ad, GRP4_TX1_A_BAND_TSSI_SLOPE, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[GRP4_TX1_A_BAND_TSSI_SLOPE]) = value; + eFuseReadRegisters(ad, GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI, 2, &value); + ad->EEPROMImage[GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI + 1] = (value & GRP5_TX1_A_BAND_TSSI_SLOPE_MASK) >> 8; + eFuseReadRegisters(ad, GRP5_TX1_A_BAND_TSSI_OFFSET, 2, &value); + ad->EEPROMImage[GRP5_TX1_A_BAND_TSSI_OFFSET] = value & GRP5_TX1_A_BAND_TSSI_OFFSET_MASK; + + /* 0xF6 */ + eFuseReadRegisters(ad, CP_FT_VERSION, 2, &value); + ad->EEPROMImage[CP_FT_VERSION] = value & CP_FT_VERSION_MASK; + + /* 0xF9 0xFA 0xFB 0xFC 0xFD 0xFE 0xFF */ + eFuseReadRegisters(ad, RF_2G_RX_HIGH_GAIN, 2, &value); + ad->EEPROMImage[RF_2G_RX_HIGH_GAIN+1] = (value >> 8) & 0xFF; + eFuseReadRegisters(ad, RF_5G_GRP0_1_RX_HIGH_GAIN, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[RF_5G_GRP0_1_RX_HIGH_GAIN]) = value; + eFuseReadRegisters(ad, RF_5G_GRP2_3_RX_HIGH_GAIN, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[RF_5G_GRP2_3_RX_HIGH_GAIN]) = value; + eFuseReadRegisters(ad, RF_5G_GRP4_5_RX_HIGH_GAIN, 2, &value); + *(UINT16 *)(&ad->EEPROMImage[RF_5G_GRP4_5_RX_HIGH_GAIN]) = value; + + /* BT: 0x138 0x13D 0x13E 0x13F */ + eFuseReadRegisters(ad, BT_RCAL_RESULT, 2, &value); + if ( value != 0xFFFF ) + ad->EEPROMImage[BT_RCAL_RESULT] = value & 0xFF; + eFuseReadRegisters(ad, BT_VCDL_CALIBRATION, 2, &value); + if ( value != 0xFFFF ) + ad->EEPROMImage[BT_VCDL_CALIBRATION+1] = (value >> 8) & 0xFF; + eFuseReadRegisters(ad, BT_PMUCFG, 2, &value); + if ( value != 0xFFFF ) + *(UINT16 *)(&ad->EEPROMImage[BT_PMUCFG]) = value; + +} +#endif /* CAL_FREE_IC_SUPPORT */ + +#ifdef ED_MONITOR +void mt7612_set_ed_cca(RTMP_ADAPTER *ad, BOOLEAN enable) +{ + UINT32 mac_val = 0; + UINT32 bbp_val; + UCHAR ED_TH = (ad->CommonCfg.Channel > 14)?0x0e:0x20; + /* A band 0x0e , G band 0x20 , 20150331 */ + + if (enable) { + RTMP_IO_READ32(ad, CH_TIME_CFG, &mac_val); + mac_val |= 0x40; + RTMP_IO_WRITE32(ad, CH_TIME_CFG, mac_val); + + RTMP_IO_READ32(ad, TXOP_CTRL_CFG, &mac_val); + mac_val |= (1 << 20); + RTMP_IO_WRITE32(ad, TXOP_CTRL_CFG, mac_val); + + RTMP_IO_READ32(ad, CH_TIME_CFG, &mac_val); + mac_val |= 0x05; // enable channel status check + RTMP_IO_WRITE32(ad, CH_TIME_CFG, mac_val); + + RTMP_BBP_IO_READ32(ad, AGC1_R2, &bbp_val); + bbp_val = (bbp_val & 0xFFFF0000) | (ED_TH << 8) | ED_TH; + RTMP_BBP_IO_WRITE32(ad, AGC1_R2, bbp_val); + } else { + RTMP_IO_READ32(ad, TXOP_CTRL_CFG, &mac_val); + mac_val &= ~(1 << 20); + RTMP_IO_WRITE32(ad, TXOP_CTRL_CFG, mac_val); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::0x%x: 0x%08X\n", __FUNCTION__, TXOP_CTRL_CFG, mac_val)); +} +#endif /* ED_MONITOR */ +#ifdef DYNAMIC_VGA_SUPPORT +void dynamic_ed_cca_threshold_adjust(RTMP_ADAPTER * pAd) +{ + UINT32 reg_val = 0; + CHAR high_gain = 0, mid_gain = 0, low_gain = 0, ulow_gain = 0, lna_gain_mode = 0; + UCHAR lna_gain = 0, vga_gain = 0, y = 0, z = 0; + + RTMP_BBP_IO_READ32(pAd, AGC1_R4, ®_val); + high_gain = ((reg_val & (0x3F0000)) >> 16) & 0x3F; + mid_gain = ((reg_val & (0x3F00)) >> 8) & 0x3F; + low_gain = reg_val & 0x3F; + + RTMP_BBP_IO_READ32(pAd, AGC1_R6, ®_val); + ulow_gain = reg_val & 0x3F; + + RTMP_BBP_IO_READ32(pAd, AGC1_R8, ®_val); + lna_gain_mode = ((reg_val & 0xC0) >> 6) & 0x3; + vga_gain = ((reg_val & 0x7E00) >> 9) & 0x3F; + + if (lna_gain_mode == 0) + lna_gain = ulow_gain; + else if (lna_gain_mode == 1) + lna_gain = low_gain; + else if (lna_gain_mode == 2) + lna_gain = mid_gain; + else if (lna_gain_mode == 3) + lna_gain = high_gain; + + if ((vga_gain + lna_gain) > 64) + y = ((vga_gain + lna_gain) - 64) / 3; + else + y = 0; + + if (y > 1) + z = min((1 << (y - 2)), 14); + else + z = 1; + + RTMP_BBP_IO_READ32(pAd, AGC1_R2, ®_val); + reg_val = (reg_val & 0xFFFF0000) | (z << 8) | z; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R2, reg_val); + + DBGPRINT(RT_DEBUG_INFO, ("%s:: lna_gain(%d), vga_gain(%d), lna_gain_mode(%d), y=%d, z=%d, 0x2308=0x%08x\n", + __FUNCTION__, lna_gain, vga_gain, lna_gain_mode, y, z, reg_val)); +} + +void MT76x2_UpdateRssiForChannelModel(RTMP_ADAPTER * pAd) +{ + INT32 rx0_rssi, rx1_rssi; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + rx0_rssi = (CHAR)(pAd->StaCfg.RssiSample.LastRssi0); + rx1_rssi = (CHAR)(pAd->StaCfg.RssiSample.LastRssi1); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + rx0_rssi = (CHAR)(pAd->ApCfg.RssiSample.LastRssi0); + rx1_rssi = (CHAR)(pAd->ApCfg.RssiSample.LastRssi1); + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("%s:: rx0_rssi(%d), rx1_rssi(%d)\n", + __FUNCTION__, rx0_rssi, rx1_rssi)); + + /* + RSSI_DUT(n) = RSSI_DUT(n-1)*15/16 + RSSI_R2320_100ms_sample*1/16 + */ + pAd->chipCap.avg_rssi_0 = ((pAd->chipCap.avg_rssi_0) * 15)/16 + (rx0_rssi << 8)/16; + pAd->chipCap.avg_rssi_1 = ((pAd->chipCap.avg_rssi_1) * 15)/16 + (rx1_rssi << 8)/16; + + if (pAd->MacTab.Size == 0) + pAd->chipCap.avg_rssi_all = -75; + else + pAd->chipCap.avg_rssi_all = (pAd->chipCap.avg_rssi_0 + pAd->chipCap.avg_rssi_1)/512; + + DBGPRINT(RT_DEBUG_INFO, ("%s:: update rssi all(%d)\n", + __FUNCTION__, pAd->chipCap.avg_rssi_all)); +} + + +void dynamic_cck_mrc(RTMP_ADAPTER * pAd) +{ + UINT32 bbp_val = 0; + + /* CCK MRC PER bump at larger power ~-30dBm */ + if (pAd->CommonCfg.RxStream >= 2) { + if (pAd->chipCap.avg_rssi_all > -70) { + RTMP_BBP_IO_READ32(pAd, AGC1_R30, &bbp_val); + bbp_val &= 0xfffffffb; /* disable CCK MRC */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R30, bbp_val); + } else if (pAd->chipCap.avg_rssi_all < -80) { + RTMP_BBP_IO_READ32(pAd, AGC1_R30, &bbp_val); + bbp_val = (bbp_val & 0xfffffffb) | (1 << 2); /* enable CCK MRC */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R30, bbp_val); + } + } +} + +static void mt76x2_long_range_dync_vga(RTMP_ADAPTER * pAd) +{ + UCHAR val1; + UINT32 bbp_val1; + + RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val1); + /* start with initial gain in this phase */ + val1 = pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 - pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level; + + if (pAd->RalinkCounters.OneSecFalseCCACnt > pAd->CommonCfg.lna_vga_ctl.nFalseCCATh) { + if (val1 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 - 0x04)) { + val1 -= 0x02; + if ((pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level + 0x02) <= 0x04) + pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level += 0x02; + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); + if (pAd->CommonCfg.RxStream >= 2) { + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val1); + } +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE; +#endif + } + } else if (pAd->RalinkCounters.OneSecFalseCCACnt < pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh) { + if (val1 < pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0) { + val1 += 0x02; + if (pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level < 2) + pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level = 0; + else + pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level -= 0x02; + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); + if (pAd->CommonCfg.RxStream >= 2) { + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val1); + } +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE; +#endif + } + } + + DBGPRINT(RT_DEBUG_WARN, + ("MT76x2 long range one second False CCA=%d, fixed agc_vga_0:0%x, fixed agc_vga_1:0%x\n" + , pAd->RalinkCounters.OneSecFalseCCACnt, bbp_val1, bbp_val1)); + +} + + +#define shift_left16(x) ((x) << 16) +#define shift_left8(x) ((x) << 8) + +static BOOLEAN dynamic_channel_model_adjust(RTMP_ADAPTER *pAd) +{ + UCHAR mode = 0, default_init_vga = 0, eLNA_lower_init_vga = 0, iLNA_lower_init_vga = 0; + UINT32 value = 0; + BOOLEAN no_dynamic_vga = FALSE; + + /* dynamic_chE_mode: + bit7 0:average RSSI <= threshold 1:average RSSI > threshold + bit4:6 0:BW_20 1:BW_40 2:BW_80 3~7:Reserved + bit1:3 Reserved + bit0 0: eLNA 1: iLNA + */ + + /* search if long STA has traffic , disable dyncVGA */ + if(pAd->OpMode == OPMODE_AP && pAd->MacTab.Size > 0) + { + INT k = 0; + UINT64 one_sec_total_traffic = pAd->RalinkCounters.OneSecRxOkCnt+pAd->RalinkCounters.OneSecTxFailCount+pAd->RalinkCounters.OneSecTxNoRetryOkCount+pAd->RalinkCounters.OneSecTxRetryOkCount; + + for(k=0;kMacTab.Content[k]; + if (IS_ENTRY_CLIENT(pEntry) || (IS_ENTRY_APCLI(pEntry))) + { + CHAR avg_rssi = 0; + //UINT32 one_sec_total_trafficA = 0,one_sec_total_trafficB = 0,one_sec_total_trafficC = 0; + UINT32 one_sec_total_trafficB = 0; + + avg_rssi = (pEntry->RssiSample.AvgRssi0 + pEntry->RssiSample.AvgRssi1)/2; + //one_sec_total_trafficA = pEntry->DyncVgaOneSecTxCount; + one_sec_total_trafficB = pEntry->DyncVgaOneSecRxCount; + //one_sec_total_trafficC = pEntry->DyncVgaOneSecTxCount + pEntry->DyncVgaOneSecRxCount; + + pEntry->DyncVgaOneSecTxCount = 0; + pEntry->DyncVgaOneSecRxCount = 0; + + if(avg_rssi <= -76 && one_sec_total_trafficB > 20) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s: long range sta %02X:%02X:%02X:%02X:%02X:%02X rssi (%d) & one_sec_RX_traffic %d >20 change AVG RSSI to (%d)\n" + ,__FUNCTION__,PRINT_MAC(pEntry->Addr), avg_rssi,one_sec_total_trafficB,avg_rssi)); + + pAd->chipCap.avg_rssi_all = avg_rssi; + } + + } + } + } + + + DBGPRINT(RT_DEBUG_INFO, ("%s:: pAd->chipCap.avg_rssi_all (%d)\n", + __FUNCTION__, pAd->chipCap.avg_rssi_all)); + + if (((pAd->chipCap.avg_rssi_all > -62) && (pAd->CommonCfg.BBPCurrentBW == BW_80)) + || ((pAd->chipCap.avg_rssi_all > -65) && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + || ((pAd->chipCap.avg_rssi_all > -68) && (pAd->CommonCfg.BBPCurrentBW == BW_20))) + { + RTMP_BBP_IO_WRITE32(pAd, RXO_R18, 0xF000A990); + if (pAd->CommonCfg.BBPCurrentBW == BW_80) { + if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel)) + mode = 0xA0; /* BW80::eLNA lower VGA/PD */ + else + mode = 0xA1; /* BW80::iLNA lower VGA/PD */ + + RTMP_BBP_IO_READ32(pAd, AGC1_R26, &value); + value = (value & ~0xF) | 0x3; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R26, value); + } else if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel)) + mode = 0x90; /* BW40::eLNA lower VGA/PD */ + else + mode = 0x91; /* BW40::iLNA lower VGA/PD */ + } else if (pAd->CommonCfg.BBPCurrentBW == BW_20) { + if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel)) + mode = 0x80; /* BW20::eLNA lower VGA/PD */ + else + mode = 0x81; /* BW20::iLNA lower VGA/PD */ + } + } else { + RTMP_BBP_IO_WRITE32(pAd, RXO_R18, 0xF000A991); + if (pAd->CommonCfg.BBPCurrentBW == BW_80) { + if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel)) + mode = 0x20; /* BW80::eLNA default */ + else + mode = 0x21; /* BW80::iLNA default */ + + RTMP_BBP_IO_READ32(pAd, AGC1_R26, &value); + value = (value & ~0xF) | 0x5; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R26, value); + } else if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel)) + mode = 0x10; /* BW40::eLNA default */ + else + mode = 0x11; /* BW40::iLNA default */ + } else if (pAd->CommonCfg.BBPCurrentBW == BW_20) { + if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel)) + mode = 0x00; /* BW20::eLNA default */ + else + mode = 0x01; /* BW20::iLNA default */ + } + } + + DBGPRINT(RT_DEBUG_INFO, ("%s:: dynamic ChE mode(0x%x)\n", + __FUNCTION__, mode)); + + if (((pAd->chipCap.avg_rssi_all <= -76) && (pAd->CommonCfg.BBPCurrentBW == BW_80)) + || ((pAd->chipCap.avg_rssi_all <= -79) && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + || ((pAd->chipCap.avg_rssi_all <= -82) && (pAd->CommonCfg.BBPCurrentBW == BW_20))) + { + /* MT7662_SW_based_solution_20151202_longestDist_FalseCCA_reduceGain2db_tradeoff.pptx */ + /* workaround for init gain falseCCA too high issue , 20151202 modify this phase to do 2dB dync vga */ + no_dynamic_vga = TRUE; /* keep this TRUE to skip original dync vga flow */ + + if(pAd->chipCap.skip_long_range_dync_vga != TRUE) + { + mt76x2_long_range_dync_vga(pAd); + } + else + { + pAd->chipCap.dynamic_chE_mode = 0xEE; /* to restore to initial */ + } + } + + if ((mode & 0xFF) != pAd->chipCap.dynamic_chE_mode) { + pAd->chipCap.dynamic_chE_trigger = TRUE; + default_init_vga = pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0; + eLNA_lower_init_vga = pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 - 10; + iLNA_lower_init_vga = pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 - 14; + + /* the following has to be done by firmware,thus it is a temporary way to support this */ + if (pAd->CommonCfg.BBPCurrentBW == BW_80) + RTMP_BBP_IO_WRITE32(pAd, RXO_R14, 0x00560211); + else + RTMP_BBP_IO_WRITE32(pAd, RXO_R14, 0x00560423); + + /* VGA settings : MT7612e_RSSI_dynamic_VGA_CSD20141203 */ + switch (mode & 0xFF) + { + case 0xA0: /* BW80::eLNA lower VGA/PD */ + pAd->chipCap.dynamic_chE_mode = 0xA0; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x08080808); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x08080808); /* BBP 0x2394 */ + value = shift_left16(0x1836) | shift_left8(eLNA_lower_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0xA1: /* BW80::iLNA lower VGA/PD */ + pAd->chipCap.dynamic_chE_mode = 0xA1; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x08080808); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x08080808); /* BBP 0x2394 */ + value = shift_left16(0x1E42) | shift_left8(iLNA_lower_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x90: /* BW40::eLNA lower VGA/PD */ + pAd->chipCap.dynamic_chE_mode = 0x90; + if (pAd->CommonCfg.Channel > 14) { + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x08080808); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x08080808); /* BBP 0x2394 */ + } + value = shift_left16(0x1836) | shift_left8(eLNA_lower_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x91: /* BW40::iLNA lower VGA/PD */ + pAd->chipCap.dynamic_chE_mode = 0x91; + if (pAd->CommonCfg.Channel > 14) { + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x08080808); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x08080808); /* BBP 0x2394 */ + } + value = shift_left16(0x1E42) | shift_left8(iLNA_lower_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x80: /* BW20::eLNA lower VGA/PD */ + pAd->chipCap.dynamic_chE_mode = 0x80; + if (pAd->CommonCfg.Channel > 14){ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x08080808); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x08080808); /* BBP 0x2394 */ + value = shift_left16(0x1836) | shift_left8(eLNA_lower_init_vga) | 0xF8; + } + else{ + value = shift_left16(0x0F36) | shift_left8(eLNA_lower_init_vga) | 0xF8; + } + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + + break; + + case 0x81: /* BW20::iLNA lower VGA/PD */ + pAd->chipCap.dynamic_chE_mode = 0x81; + if (pAd->CommonCfg.Channel > 14) { + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x08080808); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x08080808); /* BBP 0x2394 */ + } + value = shift_left16(0x1836) | shift_left8(iLNA_lower_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x20: /* BW80::eLNA default */ + pAd->chipCap.dynamic_chE_mode = 0x20; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x10101014); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + value = shift_left16(0x1836) | shift_left8(default_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x21: /* BW80::iLNA default */ + pAd->chipCap.dynamic_chE_mode = 0x21; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x10101014); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + value = shift_left16(0x1E42) | shift_left8(default_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x10: /* BW40::eLNA default */ + pAd->chipCap.dynamic_chE_mode = 0x10; + if (pAd->CommonCfg.Channel > 14){ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111116); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + else{ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111516); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + value = shift_left16(0x1836) | shift_left8(default_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x11: /* BW40::iLNA default */ + pAd->chipCap.dynamic_chE_mode = 0x11; + if (pAd->CommonCfg.Channel > 14){ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111116); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + else{ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111516); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + value = shift_left16(0x1E42) | shift_left8(default_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x00: /* BW20::eLNA default */ + pAd->chipCap.dynamic_chE_mode = 0x00; + if (pAd->CommonCfg.Channel > 14){ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111116); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + else{ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111516); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + if (pAd->CommonCfg.Channel > 14){ + value = shift_left16(0x1836) | shift_left8(default_init_vga) | 0xF8; + } + else{ + value = shift_left16(0x0F36) | shift_left8(default_init_vga) | 0xF8; + } + + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + + case 0x01: /* BW20::iLNA default */ + pAd->chipCap.dynamic_chE_mode = 0x01; + if (pAd->CommonCfg.Channel > 14){ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111116); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + else{ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R35, 0x11111516); /* BBP 0x238C */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R37, 0x2121262C); /* BBP 0x2394 */ + } + value = shift_left16(0x1836) | shift_left8(default_init_vga) | 0xF8; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, value); /* BBP 0x2320 */ + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, value); /* BBP 0x2324 */ + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s:: no such dynamic ChE mode(0x%x)\n", + __FUNCTION__, mode)); + break; + } + + DBGPRINT(RT_DEBUG_WARN, ("%s:: updated dynamic_chE_mode(0x%x), dynamic_chE_trigger(%d), agc_vga: 0%x\n", + __FUNCTION__, pAd->chipCap.dynamic_chE_mode, pAd->chipCap.dynamic_chE_trigger, value)); + } else + pAd->chipCap.dynamic_chE_trigger = FALSE; + + return no_dynamic_vga; +} + + +void MT76x2_AsicDynamicVgaGainControl(RTMP_ADAPTER *pAd) +{ + if ((pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable) && + //(pAd->MacTab.Size > 0) && + /* needs to do dync VGA even without any STA - MT7662_SW_based_solution_20150206_EnDyncVGAWhenNoLink */ + (pAd->chipCap.dynamic_vga_support) && + OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) { + + UCHAR val1, val2; + UINT32 bbp_val1, bbp_val2; + UCHAR VgaGainLowerBound = 0x10; + + if (dynamic_channel_model_adjust(pAd) == TRUE) { + DBGPRINT(RT_DEBUG_INFO, ("%s:: no need to do dynamic vga\n", __FUNCTION__)); + return; + } + + if (pAd->chipCap.dynamic_chE_trigger == TRUE) { + mt76x2_get_agc_gain(pAd, FALSE); /* real time update init values */ + bbp_val1 = pAd->CommonCfg.lna_vga_ctl.agc1_r8_backup; + val1 = ((((bbp_val1 & (0x00007f00)) >> 8) & 0x7f) - pAd->chipCap.compensate_level); + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); + + bbp_val2 = pAd->CommonCfg.lna_vga_ctl.agc1_r9_backup; + val2 = ((((bbp_val2 & (0x00007f00)) >> 8) & 0x7f) - pAd->chipCap.compensate_level); + bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2); + } else { + RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val1); + val1 = ((bbp_val1 & (0x00007f00)) >> 8) & 0x7f; + RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val2); + val2 = ((bbp_val2 & (0x00007f00)) >> 8) & 0x7f; + } + + DBGPRINT(RT_DEBUG_INFO, ("vga_init_0 = %x, vga_init_1 = %x\n", pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0, pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1)); + DBGPRINT(RT_DEBUG_INFO, ("ori AGC1_R8 = %x, ori AGC1_R9 = %x\n", pAd->CommonCfg.lna_vga_ctl.agc1_r8_backup, pAd->CommonCfg.lna_vga_ctl.agc1_r9_backup)); + DBGPRINT(RT_DEBUG_TRACE, + ("MT76x2 one second False CCA=%d, fixed agc_vga_0:0%x, fixed agc_vga_1:0%x\n", pAd->RalinkCounters.OneSecFalseCCACnt, val1, val2)); + DBGPRINT(RT_DEBUG_INFO, ("compensate level = %x\n", pAd->chipCap.compensate_level)); + + + if (pAd->RalinkCounters.OneSecFalseCCACnt > pAd->CommonCfg.lna_vga_ctl.nFalseCCATh) { + if (val1 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 - VgaGainLowerBound)) { + val1 -= 0x02; + pAd->chipCap.compensate_level += 0x02; + if (pAd->chipCap.compensate_level >= VgaGainLowerBound) + pAd->chipCap.compensate_level = VgaGainLowerBound; + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE; +#endif + } + + if (pAd->CommonCfg.RxStream >= 2) { + if (val2 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 - VgaGainLowerBound)) { + val2 -= 0x02; + bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2); + } + } + } else if (pAd->RalinkCounters.OneSecFalseCCACnt < + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh) { + if (val1 < pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0) { + val1 += 0x02; + pAd->chipCap.compensate_level -= 0x02; + if (pAd->chipCap.compensate_level < 0) + pAd->chipCap.compensate_level = 0; + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE; +#endif + } + + if (pAd->CommonCfg.RxStream >= 2) { + if (val2 < pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1) { + val2 += 0x02; + bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2); + } + } + } + +#ifdef ED_MONITOR + //dynamic_ed_cca_threshold_adjust(pAd); + if (val1 == (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 - VgaGainLowerBound)) + pAd->ed_vga_at_lowest_gain = TRUE; + else + pAd->ed_vga_at_lowest_gain = FALSE; +#endif + + } +} + + +#endif /* DYNAMIC_VGA_SUPPORT */ + +VOID mt76x2_antenna_sel_ctl( + IN RTMP_ADAPTER *ad) +{ +/* Antenna selection control in 76x2 is controlled by fw/rom_patch */ +} + +static const RTMP_CHIP_CAP MT76x2_ChipCap = { + .max_nss = 2, +#ifdef DOT11_VHT_AC + .max_vht_mcs = VHT_MCS_CAP_9, + .ac_off_mode = 0, +#endif /* DOT11_VHT_AC */ + .TXWISize = 20, + .RXWISize = 28, +#ifdef RTMP_MAC_PCI + .WPDMABurstSIZE = 3, +#endif /* RTMP_MAC_PCI */ + .SnrFormula = SNR_FORMULA3, + .FlgIsHwWapiSup = TRUE, + .VcoPeriod = 10, + .FlgIsVcoReCalMode = VCO_CAL_DISABLE, + .FlgIsHwAntennaDiversitySup = FALSE, + .Flg7662ChipCap = TRUE, +#ifdef STREAM_MODE_SUPPORT + .FlgHwStreamMode = FALSE, +#endif /* STREAM_MODE_SUPPORT */ +#ifdef TXBF_SUPPORT + .FlgHwTxBfCap = TRUE, + .FlgITxBfBinWrite = FALSE, +#endif /* TXBF_SUPPORT */ +#ifdef FIFO_EXT_SUPPORT + .FlgHwFifoExtCap = TRUE, +#endif /* FIFO_EXT_SUPPORT */ + .asic_caps = (fASIC_CAP_PMF_ENC | fASIC_CAP_MCS_LUT), + .phy_caps = (fPHY_CAP_24G | fPHY_CAP_5G | fPHY_CAP_HT | fPHY_CAP_VHT | fPHY_CAP_LDPC), + .MaxNumOfRfId = MAX_RF_ID, + .pRFRegTable = NULL, + .MaxNumOfBbpId = 200, + .pBBPRegTable = NULL, + .bbpRegTbSize = 0, +#ifdef DFS_SUPPORT + .DfsEngineNum = 4, +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + .carrier_func = TONE_RADAR_V3, +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef NEW_MBSSID_MODE +#ifdef ENHANCE_NEW_MBSSID_MODE + .MBSSIDMode = MBSSID_MODE4, +#else + .MBSSIDMode = MBSSID_MODE1, +#endif /* ENHANCE_NEW_MBSSID_MODE */ +#else + .MBSSIDMode = MBSSID_MODE0, +#endif /* NEW_MBSSID_MODE */ +#ifdef RTMP_EFUSE_SUPPORT + .EFUSE_USAGE_MAP_START = 0x1e0, + .EFUSE_USAGE_MAP_END = 0x1fc, + .EFUSE_USAGE_MAP_SIZE = 29, + .EFUSE_RESERVED_SIZE = 21, // Cal-Free is 22 free block +#endif /* RTMP_EFUSE_SUPPORT */ + .EEPROM_DEFAULT_BIN = MT76x2_E2PImage, + .EEPROM_DEFAULT_BIN_SIZE = sizeof(MT76x2_E2PImage), +#ifdef CONFIG_ANDES_SUPPORT + .WlanMemmapOffset = 0x410000, + .InbandPacketMaxLen = 192, + .CmdRspRxRing = RX_RING1, + .IsComboChip = TRUE, + .need_load_fw = TRUE, + .need_load_rom_patch = TRUE, + .ram_code_protect = FALSE, + .rom_code_protect = TRUE, + .load_iv = FALSE, + .ilm_offset = 0x80000, + .dlm_offset = 0x110000, + .rom_patch_offset = 0x90000, +#endif /* CONFIG_ANDES_SUPPORT */ + .MCUType = ANDES, + .cmd_header_len = 4, +#ifdef RTMP_PCI_SUPPORT + .cmd_padding_len = 0, +#endif + .fw_header_image = MT7662_FirmwareImage, + .fw_bin_file_name = "mtk/WIFI_RAM_CODE_ALL.bin", + .fw_len = sizeof(MT7662_FirmwareImage), + .rom_patch_header_image = mt7662_rom_patch, + .rom_patch_len = sizeof(mt7662_rom_patch), + .rom_patch_bin_file_name = "mtk/mt7662_patch_e1_hdr.bin", + .load_code_method = HEADER_METHOD, + .MACRegisterVer = "", + .BBPRegisterVer = "MT7662E1_BBP_CR_20130116.xls", + .RFRegisterVer = "", +#ifdef CONFIG_WIFI_TEST + .MemMapStart = 0x0000, + .MemMapEnd = 0xffff, + .MacMemMapOffset = 0x1000, + .MacStart = 0x0000, + .MacEnd = 0x0600, + .BBPMemMapOffset = 0x2000, + .BBPStart = 0x0000, + .BBPEnd = 0x0f00, + .RFIndexNum = sizeof(mt76x2_rf_index_offset) / sizeof(struct RF_INDEX_OFFSET), + .RFIndexOffset = mt76x2_rf_index_offset, + .E2PStart = 0x0000, + .E2PEnd = 0x00fe, +#endif + .hif_type = HIF_RLT, + .rf_type = RF_MT, +#ifdef DYNAMIC_VGA_SUPPORT + .dynamic_vga_support = TRUE, + .compensate_level = 0, + .dynamic_chE_mode = 0xEE, + .dynamic_chE_trigger = FALSE, + .avg_rssi_all = -90, + .avg_rssi_0 = -90, + .avg_rssi_1 = -90, + .skip_long_range_dync_vga = FALSE, +#ifdef CONFIG_AP_SUPPORT + .dynamic_lna_trigger_timer = 1, + .microwave_enable = TRUE, +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DYNAMIC_VGA_SUPPORT */ + .chl_smth_enable = TRUE, + .ed_cca_enable = FALSE, +#ifdef DOT11W_PMF_SUPPORT + .FlgPMFEncrtptMode = PMF_ENCRYPT_MODE_1, +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ +#ifdef THERMAL_PROTECT_SUPPORT + .ThermalProtectSup = TRUE, +#endif /* THERMAL_PROTECT_SUPPORT */ +}; + +static const RTMP_CHIP_OP MT76x2_ChipOp = { + .ChipBBPAdjust = mt76x2_bbp_adjust, + .ChipSwitchChannel = mt76x2_switch_channel, + .AsicMacInit = mt76x2_init_mac_cr, + .AsicRfInit = mt76x2_init_rf_cr, + .AsicAntennaDefaultReset = mt76x2_antenna_default_reset, + + // ITxBf phase calibration +#ifdef TXBF_SUPPORT + .fITxBfDividerCalibration = ITxBFDividerCalibrationStartUp, + .fITxBfLNAPhaseCompensate = mt76x2_ITxBFLoadLNAComp, + .fITxBfCal = mt76x2_Set_ITxBfCal_Proc, + .fITxBfLNACalibration = ITxBFLNACalibrationStartUp, +#endif + + .ChipAGCInit = NULL, +#ifdef CONFIG_STA_SUPPORT + .ChipAGCAdjust = NULL, +#endif + .AsicRfTurnOn = NULL, + .AsicHaltAction = NULL, + .AsicRfTurnOff = NULL, + .AsicReverseRfFromSleepMode = NULL, + .AsicResetBbpAgent = NULL, + .InitDesiredTSSITable = NULL, + .ATETssiCalibration = NULL, + .ATETssiCalibrationExtend = NULL, + .AsicTxAlcGetAutoAgcOffset = NULL, + .ATEReadExternalTSSI = NULL, + .TSSIRatio = NULL, +#ifdef CONFIG_STA_SUPPORT + .NetDevNickNameInit = mt76x2_init_dev_nick_name, +#endif +#ifdef CARRIER_DETECTION_SUPPORT + .ToneRadarProgram = ToneRadarProgram_v3, +#endif + .RxSensitivityTuning = NULL, + .DisableTxRx = RT65xxDisableTxRx, +#ifdef RTMP_PCI_SUPPORT + .AsicRadioOn = RT28xxPciAsicRadioOn, + .AsicRadioOff = RT28xxPciAsicRadioOff, +#endif +#ifdef CAL_FREE_IC_SUPPORT + .is_cal_free_ic = mt76x2_is_cal_free_ic, + .cal_free_data_get = mt76x2_cal_free_data_get, +#endif /* CAL_FREE_IC_SUPPORT */ + .show_pwr_info = mt76x2_show_pwr_info, + .cal_test = mt76x2_cal_test, +#ifdef RTMP_TEMPERATURE_TX_ALC + .TemperCompensation = mt76x2_temp_tx_alc, +#endif /* RTMP_TEMPERATURE_TX_ALC */ +#ifdef ED_MONITOR + .ChipSetEDCCA = mt7612_set_ed_cca, +#else + .ChipSetEDCCA = NULL, +#endif /* ED_MONITOR */ + +#ifdef DYNAMIC_VGA_SUPPORT + .AsicDynamicVgaGainControl = MT76x2_AsicDynamicVgaGainControl, + .UpdateRssiForDynamicVga = MT76x2_UpdateRssiForChannelModel, +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + .SkuTxPwrAdj = mt76x2_sku_calculate_TxPwrAdj, +#else + .SkuTxPwrAdj = NULL, +#endif + .TxPwrBoost = mt76x2_tx_pwr_boost, + +}; +VOID mt76x2_ePA_per_rate_compensate_init(RTMP_ADAPTER *pAd , BOOLEAN is_ePA) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + if(is_ePA) + { + pChipCap->tx_pwr_cck_1_2_compensate = -2; + pChipCap->tx_pwr_cck_5_11_compensate = -2; + pChipCap->tx_pwr_g_band_ofdm_6_9_compensate = -3; + pChipCap->tx_pwr_g_band_ofdm_12_18_compensate = -3; + pChipCap->tx_pwr_a_band_ofdm_6_9_compensate = -2; + pChipCap->tx_pwr_a_band_ofdm_12_18_compensate = -2; + pChipCap->tx_pwr_g_band_ht_mcs_0_1_compensate = -3; /*cover 8_9*/ + pChipCap->tx_pwr_g_band_ht_mcs_2_3_compensate = -3; /*cover 10_11*/ + pChipCap->tx_pwr_a_band_ht_mcs_0_1_compensate = -2; /*cover 8_9*/ + pChipCap->tx_pwr_a_band_ht_mcs_2_3_compensate = -2; /*cover 10_11*/ + pChipCap->tx_pwr_5g_vht_mcs_8_9_compensate = 1; + } + else + { + pChipCap->tx_pwr_cck_1_2_compensate = 0; + pChipCap->tx_pwr_cck_5_11_compensate = 0; + pChipCap->tx_pwr_g_band_ofdm_6_9_compensate = 0; + pChipCap->tx_pwr_g_band_ofdm_12_18_compensate = 0; + pChipCap->tx_pwr_a_band_ofdm_6_9_compensate = 0; + pChipCap->tx_pwr_a_band_ofdm_12_18_compensate = 0; + pChipCap->tx_pwr_g_band_ht_mcs_0_1_compensate = 0; /*cover 8_9*/ + pChipCap->tx_pwr_g_band_ht_mcs_2_3_compensate = 0; /*cover 10_11*/ + pChipCap->tx_pwr_a_band_ht_mcs_0_1_compensate = 0; /*cover 8_9*/ + pChipCap->tx_pwr_a_band_ht_mcs_2_3_compensate = 0; /*cover 10_11*/ + pChipCap->tx_pwr_5g_vht_mcs_8_9_compensate = 0; + } + DBGPRINT(RT_DEBUG_ERROR, ("====> %s: %d is_ePA: %d\n",__FUNCTION__, __LINE__,is_ePA)); +} + + +VOID mt76x2_init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + memcpy(&pAd->chipCap, &MT76x2_ChipCap, sizeof(RTMP_CHIP_CAP)); + memcpy(&pAd->chipOps, &MT76x2_ChipOp, sizeof(RTMP_CHIP_OP)); + + rlt_phy_probe(pAd); + + if (IS_MT7612(pAd)) { + pChipCap->IsComboChip = FALSE; + pChipCap->rom_code_protect = FALSE; + } + + if (IS_MT7632(pAd)) + pChipCap->phy_caps = (fPHY_CAP_24G | fPHY_CAP_5G | fPHY_CAP_HT | fPHY_CAP_LDPC); + +#ifdef MT7662TU + if (IS_MT76x2T(pAd)) { + DBGPRINT(RT_DEBUG_OFF, ("MT76x2T chip!\n")); + pChipCap->rom_patch_offset = 0xBC000; + pChipCap->dlm_offset = 0x115800; + pChipCap->fw_header_image = MT7662T_FirmwareImage; + pChipCap->fw_len = sizeof(MT7662T_FirmwareImage), + pChipCap->fw_bin_file_name = "mt7662t_firmware_e1.bin"; + pChipCap->rom_patch_header_image = mt7662t_rom_patch; + pChipCap->rom_patch_len = sizeof(mt7662t_rom_patch), + pChipCap->rom_patch_bin_file_name = "mt7662t_patch_e1_hdr.bin"; + } +#endif /* MT7662TU */ + +#ifdef DOT11_VHT_AC + { + UINT32 mac_val = 0; + RTMP_IO_READ32(pAd, 0x38, &mac_val); + + if ((mac_val & 0x80000) == 0x80000) + pChipCap->ac_off_mode = 1; + } +#endif /* DOT11_VHT_AC */ + + + + pChipCap->asic_caps |= (fASIC_CAP_MCS_LUT); + + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_GRP); +#ifdef CUSTOMER_DCC_FEATURE + pAd->EnableChannelStatsCheck = FALSE; + pAd->ApEnableBeaconTable = FALSE; + pAd->CommonCfg.channelSwitch.CHSWMode = NORMAL_MODE; + pAd->CommonCfg.channelSwitch.CHSWCount = 0; + pAd->CommonCfg.channelSwitch.CHSWPeriod = 5; + NdisZeroMemory(&pAd->RadioStatsCounter, sizeof(RADIO_STATS_COUNTER)); +#endif + + rlt_bcn_buf_init(pAd); + +#ifdef HDR_TRANS_SUPPORT + UINT8 cnt = HT_RX_WCID_SIZE/HT_RX_WCID_OFFSET; + UINT32 RegVal; + + /* enable TX/RX Header Translation */ + RTMP_IO_WRITE32(pAd, HT_RX_WCID_EN_BASE , 0xFF); /* all RX WCID enable */ + + /* black list - skip EAP-888e/DLS-890d */ + RTMP_IO_WRITE32(pAd, HT_RX_BL_BASE, 0x888e890d); +#endif /* HDR_TRANS_SUPPORT */ + + pChipCap->tssi_stage = TSSI_INIT_STAGE; + + + if (pChipCap->PAType != INT_PA_2G_5G) + mt76x2_ePA_per_rate_compensate_init(pAd, TRUE); + else + mt76x2_ePA_per_rate_compensate_init(pAd, FALSE); +} + +static void patch_BBPL_on(RTMP_ADAPTER *pAd) +{ + UINT32 value = 0; + + read_reg(pAd, 0x40, 0x130, &value); + value |= ((1<<16) | (1<<0)); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(1); + + read_reg(pAd, 0x40, 0x64, &value); + if ((value >> 29) & 0x1) + { + read_reg(pAd, 0x40, 0x1c, &value); + value &= 0xFFFFFF00; + write_reg(pAd, 0x40, 0x1c, value); + + read_reg(pAd, 0x40, 0x1c, &value); + value |= 0x30; + write_reg(pAd, 0x40, 0x1c, value); + } + else + { + read_reg(pAd, 0x40, 0x1c, &value); + value &= 0xFFFFFF00; + write_reg(pAd, 0x40, 0x1c, value); + + read_reg(pAd, 0x40, 0x1c, &value); + value |= 0x30; + write_reg(pAd, 0x40, 0x1c, value); + } + value = 0x0000484F; + write_reg(pAd, 0x40, 0x14, value); + + RtmpusecDelay(1); + + read_reg(pAd, 0x40, 0x130, &value); + value |= (1<<17); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(125); + + read_reg(pAd, 0x40, 0x130, &value); + value &= ~(1<<16); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(50); + + read_reg(pAd, 0x40, 0x14C, &value); + value |= ((1<<20) | (1<<19)); + write_reg(pAd, 0x40, 0x14C, value); +} + +static VOID WF_CTRL(RTMP_ADAPTER *pAd, UINT8 wfID, UINT8 isON) +{ + UINT32 value = 0; + if(wfID == 0) + { + if(isON == 1) /* WIFI ON mode */ + { + /* Enable WF0 BG */ + read_reg(pAd, 0x40, 0x130, &value); + value |= (1<<0); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(10); + + /* Enable RFDIG LDO/AFE/ABB/ADDA */ + read_reg(pAd, 0x40, 0x130, &value); + value |= ((1<<1)|(1<<3)|(1<<4)|(1<<5)); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(10); + + /* Switch WF0 RFDIG power to internal LDO */ + read_reg(pAd, 0x40, 0x130, &value); + value &= ~(1<<2); + write_reg(pAd, 0x40, 0x130, value); + + patch_BBPL_on(pAd); + + RTMP_IO_READ32(pAd, 0x530, &value); + value |= 0xF; + RTMP_IO_WRITE32(pAd, 0x530, value); + } + } + else + { + if(isON == 1) /* WIFI ON mode */ + { + /* Enable WF1 BG */ + read_reg(pAd, 0x40, 0x130, &value); + value |= (1<<8); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(10); + + /* Enable RFDIG LDO/AFE/ABB/ADDA */ + read_reg(pAd, 0x40, 0x130, &value); + value |= ((1<<9)|(1<<11)|(1<<12)|(1<<13)); + write_reg(pAd, 0x40, 0x130, value); + + RtmpusecDelay(10); + /* Switch WF1 RFDIG power to internal LDO */ + read_reg(pAd, 0x40, 0x130, &value); + value &= ~(1<<10); + write_reg(pAd, 0x40, 0x130, value); + + patch_BBPL_on(pAd); + + RTMP_IO_READ32(pAd, 0x530, &value); + value |= 0xF; + RTMP_IO_WRITE32(pAd, 0x530, value); + } + } +} + +static void WL_POWER_ON(RTMP_ADAPTER *pAd) +{ + UINT32 cnt = 0; + UINT32 regval = 0; + UINT32 value = 0; + + read_reg(pAd, 0x40, 0x148, &value); + value |= 0x1; + write_reg(pAd, 0x40, 0x148, value); // turn on WL MTCMOS + do{ + read_reg(pAd, 0x40, 0x148, ®val); + if((((regval>>28) & 0x1) == 0x1) && (((regval>>12) & 0x3) == 0x3)) + break; + RtmpusecDelay(10); + cnt++; + }while(cnt < 100); + + read_reg(pAd, 0x40, 0x148, &value); + value &= ~(0x7F<<16); + write_reg(pAd, 0x40, 0x148, value); + + RtmpusecDelay(10); + read_reg(pAd, 0x40, 0x148, &value); + value &= ~(0xF<<24); + write_reg(pAd, 0x40, 0x148, value); + RtmpusecDelay(10); + + read_reg(pAd, 0x40, 0x148, &value); + value |= (0xF<<24); + write_reg(pAd, 0x40, 0x148, value); + + read_reg(pAd, 0x40, 0x148, &value); + value &= ~(0xFFF); + write_reg(pAd, 0x40, 0x148, value); + + /* Set 1'b0 to turn on AD/DA power down */ + read_reg(pAd, 0x40, 0x1204, &value); + value &= ~(0x1<<3); + write_reg(pAd, 0x40, 0x1204, value); + + /* WLAN function enable */ + read_reg(pAd, 0x40, 0x80, &value); + value |= (0x1<<0); + write_reg(pAd, 0x40, 0x80, value); + + /* release "BBP software reset */ + read_reg(pAd, 0x40, 0x64, &value); + value &= ~(0x1<<18); + write_reg(pAd, 0x40, 0x64, value); +} + +void mt76x2_pwrOn(RTMP_ADAPTER *pAd) +{ + /* Radio On */ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + WL_POWER_ON(pAd); + WF_CTRL(pAd, 0, 1); + WF_CTRL(pAd, 1, 1); +} + + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT +VOID WlanResetB(RTMP_ADAPTER *pAd) +{ + UINT32 MacValue, Value, loop, WMMCtrlBackup; + WPDMA_GLO_CFG_STRUC DMACfg; + ULONG WLANResetCounter = 0; + UINT32 mac_val = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> \n", __FUNCTION__)); + + /* disable prim/second EDCCA before disable mac TX/RX */ + RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val); + if ((mac_val & 0x100000) == 0x100000) + { + 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_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); + + //step 0. + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + + + //step1. + //Disable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + + DBGPRINT(RT_DEBUG_TRACE, ("%s 111 MAC_SYS_CTRL =%08x \n", __FUNCTION__,MacValue)); + + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + //step2. + //Clear PDMA_INT_MASK + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + + //step3. + // Disable PDMA Tx/Rx + RTMP_IO_FORCE_READ32(pAd, WPDMA_GLO_CFG, &MacValue); + MacValue = MacValue & 0xfffffffa; + RTMP_IO_FORCE_WRITE32(pAd, WPDMA_GLO_CFG, MacValue); + + + //step4. + //poll MAC Tx to idle + /* wait mac 0x1200 idle */ + do { + RTMP_IO_READ32(pAd, 0x1200, &Value); + Value &= 0x1; + DBGPRINT(RT_DEBUG_TRACE,("%s:: Wait until MAC 0x1200 bit0 become 0\n", __FUNCTION__)); + RtmpusecDelay(1); + loop++; + } while ((Value != 0) && (loop < 5000)); + + if (loop >= 5000) { + DBGPRINT(RT_DEBUG_OFF, ("%s:: Wait until MAC 0x1200 bit0 become 0 > 5000 times\n", __FUNCTION__)); + } + + + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); // clear garbage interrupts + + + //let f/w to reset DMA + RTMP_IO_READ32(pAd, 0x734, &MacValue); + MacValue |= 0x03; + RTMP_IO_WRITE32(pAd, 0x734, MacValue); + + //step5. + //set MCU to standby mode + RTMP_IO_WRITE32(pAd, INT_LEVEL, 0x01); + + + + + + + + //step8. load f/w + andes_pci_erasefw(pAd); + andes_pci_loadfw(pAd); + + RTMP_IO_WRITE32(pAd, FCE_PSE_CTRL, 0x01); + + + + + +#if 0 + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + printk("k1\n"); + // step5. re-init DMA/FCE/PBF/MAC/BBP + //NICReadEEPROMParameters(pAd, NULL); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + printk("k2\n"); + //NICInitializeAdapter(pAd, TRUE); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + printk("k3\n"); + //NICInitAsicFromEEPROM(pAd); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + printk("k4\n"); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + printk("k5\n"); +#endif + + //step 9. restart all PDMA ring & enable PDMA_INT_MASK + rlt_asic_init_txrx_ring(pAd); + + { + //also clean RX done bit in follow functions + WPDMA_GLO_CFG_STRUC GloCfg; + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); + GloCfg.field.EnTXWriteBackDDONE = 0; + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + 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); + } + + RTMPEnableRxTx(pAd); + + + //RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); // clear garbage interrupts + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + + //step 14, Enable MAC Tx/Rx + + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + + DBGPRINT(RT_DEBUG_TRACE, ("%s 444 MAC_SYS_CTRL =%08x \n", __FUNCTION__,MacValue)); + + + +{ + //struct MCU_CTRL *ctl = &pAd->MCUCtrl; + //ctl->power_on= FALSE; + //ctl->dpd_on= FALSE; + + mt76x2_switch_channel(pAd, pAd->hw_cfg.cent_ch, FALSE); + //AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE); + //AsicLockChannel(pAd, pAd->hw_cfg.cent_ch); +} + + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + RTMP_OS_NETDEV_START_QUEUE((pAd->net_dev)); + + + /* enable prim/second EDCCA after mac TX/RX enabled */ + if (pAd->chipCap.ed_cca_enable) + { + mac_val = 0; + + 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); + + + DBGPRINT(RT_DEBUG_TRACE, ("<== %s, \n",__FUNCTION__)); + + +} +#endif /* RTMP_PCI_SUPPORT */ +#endif /*DMA_BUSY_RESET*/ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rt6352.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rt6352.c new file mode 100644 index 000000000..ecfdafc93 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rt6352.c @@ -0,0 +1,6029 @@ +/* + *************************************************************************** + * 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: + rt6352.c + + Abstract: + Specific funcitons and variables for RT6352 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT6352 + +#include "rt_config.h" + +#ifndef RTMP_RF_RW_SUPPORT +#error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" +#endif // RTMP_RF_RW_SUPPORT // + +UCHAR RT6352_EeBuffer[EEPROM_SIZE] = { + 0x20, 0x76, 0x04, 0x01, 0x00, 0x0c, 0x43, 0x76, 0x20, 0x58, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0c, 0x43, 0x76, 0x20, 0x77, 0x00, 0x0c, + 0x43, 0x76, 0x20, 0x66, 0x22, 0x0c, 0x20, 0x00, 0xff, 0xff, 0x3f, 0x01, 0x55, 0x77, 0xa8, 0xaa, + 0x8c, 0x88, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0xff, + 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, + 0x02, 0x02, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + } ; + +RT635x_FREQUENCY_ITEM FreqItems6352[] = +{ + /**************************************************/ + /* ISM : 2.4 to 2.483 GHz */ + /**************************************************/ + /*-CH--Rdiv----N---- -K----D-----Ksd------*/ + {1, 3, 0x50, 0, 0, 0x19999}, + {2, 3, 0x50, 0, 0, 0x24444}, + {3, 3, 0x50, 0, 0, 0x2EEEE}, + {4, 3, 0x50, 0, 0, 0x39999}, + {5, 3, 0x51, 0, 0, 0x04444}, + {6, 3, 0x51, 0, 0, 0x0EEEE}, + {7, 3, 0x51, 0, 0, 0x19999}, + {8, 3, 0x51, 0, 0, 0x24444}, + {9, 3, 0x51, 0, 0, 0x2EEEE}, + {10, 3, 0x51, 0, 0, 0x39999}, + {11, 3, 0x52, 0, 0, 0x04444}, + {12, 3, 0x52, 0, 0, 0x0EEEE}, + {13, 3, 0x52, 0, 0, 0x19999}, + {14, 3, 0x52, 0, 0, 0x33333}, +}; +UCHAR NUM_OF_6352_CHNL = (sizeof(FreqItems6352) / sizeof(RT635x_FREQUENCY_ITEM)); + + +REG_PAIR RT6352_RFCentralRegTable[] = { + {RF_R00, 0x02}, + {RF_R01, 0x03}, + {RF_R02, 0x33}, + {RF_R03, 0xFF}, + //{RF_R04, 0x0E}, + {RF_R04, 0x0C}, + {RF_R05, 0x40}, /* Read only */ + {RF_R06, 0x00}, + {RF_R07, 0x00}, + {RF_R08, 0x00}, + {RF_R09, 0x00}, + {RF_R10, 0x00}, + {RF_R11, 0x00}, + //{RF_R12, 0x43}, /* EEPROM */ + {RF_R13, 0x00}, + {RF_R14, 0x40}, + {RF_R15, 0x22}, + {RF_R16, 0x4C}, + {RF_R17, 0x00}, + {RF_R18, 0x00}, + {RF_R19, 0x00}, + {RF_R20, 0xA0}, + {RF_R21, 0x12}, + {RF_R22, 0x07}, + {RF_R23, 0x13}, + {RF_R24, 0xFE}, + {RF_R25, 0x24}, + {RF_R26, 0x7A}, + {RF_R27, 0x00}, + {RF_R28, 0x00}, + {RF_R29, 0x05}, + {RF_R30, 0x00}, + {RF_R31, 0x00}, + {RF_R32, 0x00}, + {RF_R33, 0x00}, + {RF_R34, 0x00}, + {RF_R35, 0x00}, + {RF_R36, 0x00}, + {RF_R37, 0x00}, + {RF_R38, 0x00}, + {RF_R39, 0x00}, + {RF_R40, 0x00}, + {RF_R41, 0xD0}, + {RF_R42, 0x5B}, + {RF_R43, 0x00}, +}; + +REG_PAIR RT6352_RFChannelRegTable[] = { + {RF_R00, 0x03}, + {RF_R01, 0x00}, + {RF_R02, 0x00}, + {RF_R03, 0x00}, + {RF_R04, 0x00}, + {RF_R05, 0x08}, + {RF_R06, 0x00}, + {RF_R07, 0x51}, + {RF_R08, 0x53}, + {RF_R09, 0x16}, + {RF_R10, 0x61}, + {RF_R11, 0x53}, + {RF_R12, 0x22}, + {RF_R13, 0x3D}, + {RF_R14, 0x06}, + {RF_R15, 0x13}, + {RF_R16, 0x22}, + {RF_R17, 0x27}, + {RF_R18, 0x02}, + {RF_R19, 0xA7}, + {RF_R20, 0x01}, + {RF_R21, 0x52}, + {RF_R22, 0x80}, + {RF_R23, 0xB3}, + {RF_R24, 0x00}, + {RF_R25, 0x00}, + {RF_R26, 0x00}, + {RF_R27, 0x00}, + {RF_R28, 0x5C}, + {RF_R29, 0x6B}, + {RF_R30, 0x6B}, + {RF_R31, 0x31}, + {RF_R32, 0x5D}, + {RF_R33, 0x00}, + {RF_R34, 0xE6}, + {RF_R35, 0x55}, + {RF_R36, 0x00}, + {RF_R37, 0xBB}, + {RF_R38, 0xB3}, + {RF_R39, 0xB3}, + {RF_R40, 0x03}, + {RF_R41, 0x00}, + {RF_R42, 0x00}, + {RF_R43, 0xB3}, + {RF_R44, 0xD3}, + {RF_R45, 0xD5}, + {RF_R46, 0x07}, + {RF_R47, 0x68}, + {RF_R48, 0xEF}, + {RF_R49, 0x1C}, + {RF_R54, 0x07}, + {RF_R55, 0xA8}, + {RF_R56, 0x85}, + {RF_R57, 0x10}, + {RF_R58, 0x07}, + {RF_R59, 0x6A}, + {RF_R60, 0x85}, + {RF_R61, 0x10}, + {RF_R62, 0x1C}, + {RF_R63, 0x00}, +}; + +REG_PAIR RT6352_RFChannelRegE2Table[] = { + {RF_R09, 0x47}, + {RF_R10, 0x71}, + {RF_R11, 0x33}, + {RF_R14, 0x0E}, + {RF_R17, 0x23}, + {RF_R19, 0xA4}, + {RF_R20, 0x02}, + {RF_R21, 0x12}, + {RF_R28, 0x1C}, + {RF_R29, 0xEB}, + {RF_R32, 0x7D}, + {RF_R34, 0xD6}, + {RF_R36, 0x08}, + {RF_R38, 0xB4}, + {RF_R43, 0xD3}, + {RF_R44, 0xB3}, + {RF_R45, 0xD5}, + {RF_R46, 0x27}, + {RF_R47, 0x67}, + {RF_R48, 0xFF}, + {RF_R54, 0x27}, + {RF_R55, 0x66}, + {RF_R56, 0xFF}, + {RF_R57, 0x1C}, + {RF_R58, 0x20}, + {RF_R59, 0x6B}, + {RF_R60, 0xF7}, + {RF_R61, 0x09}, +}; + +REG_PAIR RT6352_RFDCCalRegTable[] = { + {RF_R00, 0x47}, + {RF_R01, 0x00}, + {RF_R02, 0x00}, + {RF_R03, 0x00}, + {RF_R04, 0x00}, + {RF_R05, 0x00}, + {RF_R06, 0x10}, + {RF_R07, 0x10}, + {RF_R08, 0x04}, + {RF_R09, 0x00}, + {RF_R10, 0x07}, + {RF_R11, 0x01}, + {RF_R12, 0x07}, + {RF_R13, 0x07}, + {RF_R14, 0x07}, + {RF_R15, 0x20}, + {RF_R16, 0x22}, + {RF_R17, 0x00}, + {RF_R18, 0x00}, + {RF_R19, 0x00}, + {RF_R20, 0x00}, + {RF_R21, 0xF1}, + {RF_R22, 0x11}, + {RF_R23, 0x02}, + {RF_R24, 0x41}, + {RF_R25, 0x20}, + {RF_R26, 0x00}, + {RF_R27, 0xD7}, + {RF_R28, 0xA2}, + {RF_R29, 0x20}, + {RF_R30, 0x49}, + {RF_R31, 0x20}, + {RF_R32, 0x04}, + {RF_R33, 0xF1}, + {RF_R34, 0xA1}, + {RF_R35, 0x01}, + {RF_R41, 0x00}, + {RF_R42, 0x00}, + {RF_R43, 0x00}, + {RF_R44, 0x00}, + {RF_R45, 0x00}, + {RF_R46, 0x00}, + {RF_R47, 0x3E}, + {RF_R48, 0x3D}, + {RF_R49, 0x3E}, + {RF_R50, 0x3D}, + {RF_R51, 0x3E}, + {RF_R52, 0x3D}, + {RF_R53, 0x00}, + {RF_R54, 0x00}, + {RF_R55, 0x00}, + {RF_R56, 0x00}, + {RF_R57, 0x00}, + {RF_R58, 0x10}, + {RF_R59, 0x10}, + {RF_R60, 0x0A}, + {RF_R61, 0x00}, + {RF_R62, 0x00}, + {RF_R63, 0x00}, +}; + +/* RF Channel Register for DRQFN */ +REG_PAIR RT6352_RF_CHANNEL_REG_DRQFN[] = +{ + {RF_R43, 0xD3}, + {RF_R44, 0xE3}, + {RF_R45, 0xE5}, + {RF_R47, 0x28}, + {RF_R55, 0x68}, + {RF_R56, 0xF7}, + {RF_R58, 0x02}, + {RF_R60, 0xC7}, +}; + +UCHAR RT6352_NUM_RF_CENTRAL_REG_PARMS = (sizeof(RT6352_RFCentralRegTable) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_RF_CHANNEL_REG_PARMS = (sizeof(RT6352_RFChannelRegTable) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_RF_CHANNEL_E2_REG_PARMS = (sizeof(RT6352_RFChannelRegE2Table) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_RF_CHANNEL_REG_DRQFN_PARMS = (sizeof(RT6352_RF_CHANNEL_REG_DRQFN) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_RF_DCCAL_REG_PARMS = (sizeof(RT6352_RFDCCalRegTable) / sizeof(REG_PAIR)); + +REG_PAIR RT6352_BBPRegTable[] = { + //{BBP_R1, 0x44}, + {BBP_R3, 0x08}, + {BBP_R4, 0x00}, + {BBP_R6, 0x08}, + {BBP_R14, 0x09}, + {BBP_R15, 0xFF}, + {BBP_R16, 0x01}, + {BBP_R20, 0x06}, + {BBP_R21, 0x00}, + {BBP_R22, 0x00}, + {BBP_R27, 0x00}, + {BBP_R28, 0x00}, + {BBP_R30, 0x00}, + {BBP_R31, 0x48}, + {BBP_R47, 0x40}, + {BBP_R62, 0x00}, + {BBP_R63, 0x00}, + {BBP_R64, 0x00}, + {BBP_R65, 0x2C}, + {BBP_R66, 0x1C}, + {BBP_R67, 0x20}, + {BBP_R68, 0xDD}, + {BBP_R69, 0x10}, + {BBP_R70, 0x05}, + {BBP_R73, 0x18}, + {BBP_R74, 0x0F}, + {BBP_R75, 0x60}, + {BBP_R76, 0x44}, + {BBP_R77, 0x59}, + {BBP_R78, 0x1E}, + {BBP_R79, 0x1C}, + {BBP_R80, 0x0C}, + {BBP_R81, 0x3A}, + {BBP_R82, 0xB6}, + {BBP_R83, 0x9A}, + {BBP_R84, 0x9A}, + {BBP_R86, 0x38}, + {BBP_R88, 0x90}, + {BBP_R91, 0x04}, + {BBP_R92, 0x02}, + {BBP_R95, 0x9A}, + {BBP_R96, 0x00}, + {BBP_R103, 0xC0}, + {BBP_R104, 0x92}, + {BBP_R105, 0x3C}, + {BBP_R106, 0x12}, + {BBP_R109, 0x00}, + {BBP_R134, 0x10}, + {BBP_R135, 0xA6}, + {BBP_R137, 0x04}, + {BBP_R142, 0x30}, + {BBP_R143, 0xF7}, + {BBP_R160, 0xEC}, + {BBP_R161, 0xC4}, + {BBP_R162, 0x77}, + {BBP_R163, 0xF9}, + {BBP_R164, 0x00}, + {BBP_R165, 0x00}, + {BBP_R186, 0x00}, + {BBP_R187, 0x00}, + {BBP_R188, 0x00}, + {BBP_R186, 0x00}, + {BBP_R187, 0x01}, + {BBP_R188, 0x00}, + {BBP_R189, 0x00}, +}; + +REG_PAIR RT6352_BBP_DCOC[] = +{ + {BBP_R140, 0x0C}, + {BBP_R141, 0x00}, + {BBP_R142, 0x10}, + {BBP_R143, 0x10}, + {BBP_R144, 0x10}, + {BBP_R145, 0x10}, + {BBP_R146, 0x08}, + {BBP_R147, 0x40}, + {BBP_R148, 0x04}, + {BBP_R149, 0x04}, + {BBP_R150, 0x08}, + {BBP_R151, 0x08}, + {BBP_R152, 0x03}, + {BBP_R153, 0x03}, + {BBP_R154, 0x03}, + {BBP_R155, 0x02}, + {BBP_R156, 0x40}, + {BBP_R157, 0x40}, + {BBP_R158, 0x64}, + {BBP_R159, 0x64}, +}; + +/* BBP for G band GLRT function(BBP_128 ~ BBP_221) */ +REG_PAIR RT6352_BBP_GLRT[] = +{ + {BBP_R0, 0x00}, + {BBP_R1, 0x14}, + {BBP_R2, 0x20}, + {BBP_R3, 0x0A}, + {BBP_R10, 0x16}, + {BBP_R11, 0x06}, + {BBP_R12, 0x02}, + {BBP_R13, 0x07}, + {BBP_R14, 0x05}, + {BBP_R15, 0x09}, + {BBP_R16, 0x20}, + {BBP_R17, 0x08}, + {BBP_R18, 0x4A}, + {BBP_R19, 0x00}, + {BBP_R20, 0x00}, + {BBP_R128, 0xE0}, + {BBP_R129, 0x1F}, + {BBP_R130, 0x4F}, + {BBP_R131, 0x32}, + {BBP_R132, 0x08}, + {BBP_R133, 0x28}, + {BBP_R134, 0x19}, + {BBP_R135, 0x0A}, + {BBP_R138, 0x16}, + {BBP_R139, 0x10}, + {BBP_R140, 0x10}, + {BBP_R141, 0x1A}, + {BBP_R142, 0x36}, + {BBP_R143, 0x2C}, + {BBP_R144, 0x26}, + {BBP_R145, 0x24}, + {BBP_R146, 0x42}, + {BBP_R147, 0x40}, + {BBP_R148, 0x30}, + {BBP_R149, 0x29}, + {BBP_R150, 0x4C}, + {BBP_R151, 0x46}, + {BBP_R152, 0x3D}, + {BBP_R153, 0x40}, + {BBP_R154, 0x3E}, + {BBP_R155, 0x38}, + {BBP_R156, 0x3D}, + {BBP_R157, 0x2F}, + {BBP_R158, 0x3C}, + {BBP_R159, 0x34}, + {BBP_R160, 0x2C}, + {BBP_R161, 0x2F}, + {BBP_R162, 0x3C}, + {BBP_R163, 0x35}, + {BBP_R164, 0x2E}, + {BBP_R165, 0x2F}, + {BBP_R166, 0x49}, + {BBP_R167, 0x41}, + {BBP_R168, 0x36}, + {BBP_R169, 0x39}, + {BBP_R170, 0x30}, + {BBP_R171, 0x30}, + {BBP_R172, 0x0E}, + {BBP_R173, 0x0D}, + {BBP_R174, 0x28}, + {BBP_R175, 0x21}, + {BBP_R176, 0x1C}, + {BBP_R177, 0x16}, + {BBP_R178, 0x50}, + {BBP_R179, 0x4A}, + {BBP_R180, 0x43}, + {BBP_R181, 0x50}, + {BBP_R182, 0x10}, + {BBP_R183, 0x10}, + {BBP_R184, 0x10}, + {BBP_R185, 0x10}, + {BBP_R200, 0x7D}, + {BBP_R201, 0x14}, + {BBP_R202, 0x32}, + {BBP_R203, 0x2C}, + {BBP_R204, 0x36}, + {BBP_R205, 0x4C}, + {BBP_R206, 0x43}, + {BBP_R207, 0x2C}, + {BBP_R208, 0x2E}, + {BBP_R209, 0x36}, + {BBP_R210, 0x30}, + {BBP_R211, 0x6E}, +}; + +/* BBP for G band BW */ +REG_PAIR_BW RT6352_BBP_GLRT_BW[] = +{ + {BBP_R141, BW_20, 0x1A}, + {BBP_R141, BW_40, 0x10}, + {BBP_R157, BW_20, 0x40}, + {BBP_R157, BW_40, 0x2F}, +}; + +/* RF for G band BW */ +REG_PAIR_BW RT6352_RFDCCal_BW[] = { + {RF_R06, BW_20, 0x20}, + {RF_R06, BW_40, 0x10}, + {RF_R07, BW_20, 0x20}, + {RF_R07, BW_40, 0x10}, + {RF_R08, BW_20, 0x00}, + {RF_R08, BW_40, 0x04}, + {RF_R58, BW_20, 0x20}, + {RF_R58, BW_40, 0x10}, + {RF_R59, BW_20, 0x20}, + {RF_R59, BW_40, 0x10}, + +}; + +UCHAR RT6352_NUM_BBP_REG_PARMS = (sizeof(RT6352_BBPRegTable) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_BBP_GLRT = (sizeof(RT6352_BBP_GLRT) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_BBP_GLRT_BW = (sizeof(RT6352_BBP_GLRT_BW) / sizeof(REG_PAIR_BW)); +UCHAR RT6352_NUM_BBP_DCOC = (sizeof(RT6352_BBP_DCOC) / sizeof(REG_PAIR)); +UCHAR RT6352_NUM_RF_DCCAL_BW = (sizeof(RT6352_RFDCCal_BW) / sizeof(REG_PAIR_BW)); + +RTMP_REG_PAIR RT6352_MACRegTable[] = { + {TX_SW_CFG0, 0x0401}, // Jason,2012-08-27 + {TX_SW_CFG1, 0x000C0001}, // Jason,2012-09-13, 2015-10-08 + {TX_SW_CFG2, 0x00}, // Jason,2012-08-27 + {MIMO_PS_CFG, 0x02}, // Jason,2012-09-13 + + /* enable HW to autofallback to legacy rate to prevent ping fail in long range */ + {HT_FBK_TO_LEGACY, 0x1818}, // HT_FBK_TO_LEGACY = OFDM_6 +}; + +UCHAR RT6352_NUM_MAC_REG_PARMS = (sizeof(RT6352_MACRegTable) / sizeof(RTMP_REG_PAIR)); + + +#ifdef RTMP_INTERNAL_TX_ALC +TX_POWER_TUNING_ENTRY_STRUCT RT6352_TxPowerTuningTable[] = +{ +/* idxTxPowerTable Tx power control over RF Tx power control over MAC */ +/* (zero-based array) { RT3350: RF_R12[4:0]: Tx0 ALC}, {MAC 0x1314~0x1320} */ +/* { RT3352: RF_R47[4:0]: Tx0 ALC} */ +/* { RT3352: RF_R48[4:0]: Tx1 ALC} */ +/* 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 */ {0x10, 0}, +/* 47 */ {0x11, 0}, +/* 48 */ {0x12, 0}, +/* 49 */ {0x13, 0}, +/* 50 */ {0x14, 0}, +/* 51 */ {0x15, 0}, +/* 52 */ {0x16, 0}, +/* 53 */ {0x17, 0}, +/* 54 */ {0x18, 0}, +/* 55 */ {0x19, 0}, +/* 56 */ {0x1A, 0}, +/* 57 */ {0x1B, 0}, +/* 58 */ {0x1C, 0}, +/* 59 */ {0x1D, 0}, +/* 60 */ {0x1E, 0}, +/* 61 */ {0x1F, 0}, +/* 62 */ {0x1e, 1}, +/* 63 */ {0x1F, 1}, +/* 64 */ {0x1e, 2}, +/* 65 */ {0x1F, 2}, +/* 66 */ {0x1e, 3}, +/* 67 */ {0x1F, 3}, +/* 68 */ {0x1e, 4}, +/* 69 */ {0x1F, 4}, +/* 70 */ {0x1e, 5}, +/* 71 */ {0x1F, 5}, +/* 72 */ {0x1e, 6}, +/* 73 */ {0x1F, 6}, +/* 74 */ {0x1e, 7}, +/* 75 */ {0x1F, 7}, +/* 76 */ {0x1e, 8}, +/* 77 */ {0x1F, 8}, +/* 78 */ {0x1e, 9}, +/* 79 */ {0x1F, 9}, +/* 80 */ {0x1e, 10}, +/* 81 */ {0x1F, 10}, +/* 82 */ {0x1e, 11}, +/* 83 */ {0x1F, 11}, +/* 84 */ {0x1e, 12}, +/* 85 */ {0x1F, 12}, +/* 86 */ {0x1e, 13}, +/* 87 */ {0x1F, 13}, +/* 88 */ {0x1e, 14}, +/* 89 */ {0x1F, 14}, +/* 90 */ {0x1e, 15}, +/* 91 */ {0x1F, 15}, +}; + +/* The desired TSSI over CCK */ +CHAR desiredTSSIOverCCK[4] = {0}; + +/* The desired TSSI over OFDM */ +CHAR desiredTSSIOverOFDM[8] = {0}; + +/* The desired TSSI over HT */ +CHAR desiredTSSIOverHT[16] = {0}; + +/* The desired TSSI over HT using STBC */ +CHAR desiredTSSIOverHTUsingSTBC[8] = {0}; +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef SINGLE_SKU_V2 +/* The minimum power of every channel from the power table @ BW 40 */ +UCHAR sku_min_pwr_40bw[11] = +/* ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch9 ch10 ch11 */ +{ 14, 16, 11, 12, 14, 14, 14, 12, 10, 14, 13 }; + +/* The minimum power of every channel from the power table @ BW 20 */ +UCHAR sku_min_pwr_20bw[11] = +/* ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch9 ch10 ch11 */ +{ 14, 16, 16, 16, 16, 16, 16, 16, 16, 14, 13 }; +#endif /* SINGLE_SKU_V2 */ + +INT32 pa_mode_table[4] = +{ + 0, /* PA mode = 0 : 0 * 8192 pa_mode_00*/ + 4915, /* PA mode = 1 : 0.6 * 8192 pa_mode_01*/ + -6554, /* PA mode = 2 : -0.6 * 8192 pa_mode_10*/ + -6554, /* PA mode = 3 : -0.8 * 8192 pa_mode_11*/ +}; + +#define AMPDU_MAX_LEN_20M1S 0x1030 +#define AMPDU_MAX_LEN_40M1S 0x1038 +#define TXRX_MICS_CTRL 0x1608 + +/* +======================================================================== +Routine Description: + Initialize specific MAC registers for RT6352. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID NICInitRT6352MacRegisters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 IdReg; + UINT32 Value = 0; +#ifdef APCLI_SUPPORT + UINT32 pn_mode_value = 0; +#endif /* APCLI_SUPPORT */ +#ifdef DESC_32B_SUPPORT + WPDMA_GLO_CFG_STRUC GloCfg; +#endif /* DESC_32B_SUPPORT */ + + for(IdReg=0; IdRegCommonCfg.Chip_VerID <= 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("Initialize MAC Registers for E1 !!!\n")); + RTMP_IO_WRITE32(pAd, TX_ALC_VGA3, 0x00); /* Gary,2012-03-15 */ + RTMP_IO_WRITE32(pAd, BB_PA_MODE_CFG0, 0x000055FF); + RTMP_IO_WRITE32(pAd, BB_PA_MODE_CFG1, 0x00550055); + RTMP_IO_WRITE32(pAd, RF_PA_MODE_CFG0, 0x000055FF); + RTMP_IO_WRITE32(pAd, RF_PA_MODE_CFG1, 0x00550055); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x00150F0F); + RTMP_IO_WRITE32(pAd, TX_ALC_VGA3, 0x06060606); /* WH, 2012-10-30 */ + RTMP_IO_WRITE32(pAd, TX0_BB_GAIN_ATTEN, 0x0); + RTMP_IO_WRITE32(pAd, TX1_BB_GAIN_ATTEN, 0x0); + RTMP_IO_WRITE32(pAd, TX0_RF_GAIN_ATTEN, 0x6C6C666C); /* WH, 2012-12-26 */ + RTMP_IO_WRITE32(pAd, TX1_RF_GAIN_ATTEN, 0x6C6C666C); /* WH, 2012-12-26 */ + RTMP_IO_WRITE32(pAd, TX0_RF_GAIN_CORRECT, 0x3630363A); /* WH, 2012-12-05 */ + RTMP_IO_WRITE32(pAd, TX1_RF_GAIN_CORRECT, 0x3630363A); /* WH, 2012-12-05 */ + } + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &Value); + Value = Value & (~0x80000000); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, Value); +#ifdef APCLI_SUPPORT + /* + *bit 0 : R/W PN_PAD_MODE Padding IV/EIV in RX MPDU when packet is decrypted + *0 : Disable 1: Enable + */ + RTMP_IO_READ32(pAd, PN_PAD_MODE, &pn_mode_value); + pn_mode_value |= PN_PAD_MODE_OFFSET; + RTMP_IO_WRITE32(pAd, PN_PAD_MODE, pn_mode_value); +#endif /* APCLI_SUPPORT */ +#ifdef DESC_32B_SUPPORT + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); + GloCfg.field.Desc32BEn =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); +#endif /* DESC_32B_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Initialize specific BBP registers for RT6352. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID NICInitRT6352BbpRegisters( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpReg = 0; + UINT32 i; + //USHORT k_count = 0; + //UINT32 MacValue = 0, MacValue1 = 0; + BBP_R105_STRUC BBPR105 = { { 0 } }; + + DBGPRINT(RT_DEBUG_TRACE, ("--> %s\n", __FUNCTION__)); + + /* The channel estimation updates based on remodulation of L-SIG and HT-SIG symbols. */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R105, &BBPR105.byte); + + /* Apply Maximum Likelihood Detection (MLD) for 2 stream case (reserved field if single RX) */ + if (pAd->Antenna.field.RxPath == 1) /* Single RX */ + BBPR105.field.MLDFor2Stream = 0; + else + BBPR105.field.MLDFor2Stream = 1; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, BBPR105.byte); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: BBP_R105: BBPR105.field.EnableSIGRemodulation = %d, BBPR105.field.MLDFor2Stream = %d\n", + __FUNCTION__, + BBPR105.field.EnableSIGRemodulation, + BBPR105.field.MLDFor2Stream)); + + /* Avoid data lost and CRC error */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpReg); + BbpReg = ((BbpReg & ~0x40) | 0x40); /* MAC interface control (MAC_IF_80M, 1: 80 MHz) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpReg); + + /* Fix I/Q swap issue */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpReg); + BbpReg |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpReg); + + /* BBP for G band */ + for (i = 0; i < RT6352_NUM_BBP_REG_PARMS; i++) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, RT6352_BBPRegTable[i].Register, RT6352_BBPRegTable[i].Value); + + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R91, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R92, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R93, 0x54); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R99, 0x50); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R148, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R167, 0x80); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R178, 0xFF); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R106, 0x13); /* James 2013/01/30 */ + } + + /* BBP for G band GLRT function */ + for (i = 0; i < RT6352_NUM_BBP_GLRT; i++) + { + /* Write index into BBP_R195 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, RT6352_BBP_GLRT[i].Register); + + /* Write value into BBP_R196 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, RT6352_BBP_GLRT[i].Value); + } + + /* BBP for G band DCOC function */ + for (i = 0; i < RT6352_NUM_BBP_DCOC; i++) + { + /* Write index into BBP_R158 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, RT6352_BBP_DCOC[i].Register); + + /* Write value into BBP_R159 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, RT6352_BBP_DCOC[i].Value); + } + + /* Avoid data lost and CRC error */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpReg); + BbpReg = ((BbpReg & ~0x40) | 0x40); /* MAC interface control (MAC_IF_80M, 1: 80 MHz) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpReg); + +#ifdef MICROWAVE_OVEN_SUPPORT + /* Backup BBP_R65 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &BbpReg); + pAd->CommonCfg.MO_Cfg.Stored_BBP_R65 = BbpReg; + DBGPRINT(RT_DEBUG_TRACE, ("Stored_BBP_R65=%x @%s \n", pAd->CommonCfg.MO_Cfg.Stored_BBP_R65, __FUNCTION__)); +#endif /* MICROWAVE_OVEN_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<-- %s\n", __FUNCTION__)); +} + + +/* +======================================================================== +Routine Description: + Initialize specific RF registers for RT6352. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID NICInitRT6352RFRegisters( + IN PRTMP_ADAPTER pAd) +{ + UCHAR RFValue = 0; + int i; + UINT32 SysCfgReg; + + DBGPRINT(RT_DEBUG_TRACE, ("--> %s\n", __FUNCTION__)); + + // Initialize RF central register to default value + for (i = 0; i < RT6352_NUM_RF_CENTRAL_REG_PARMS; i++) + { + RT635xWriteRFRegister(pAd, RF_BANK0, RT6352_RFCentralRegTable[i].Register, RT6352_RFCentralRegTable[i].Value); + } + + if (pAd->CommonCfg.Chip_VerID > 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF Central Registers for E2 !!!\n")); + RTMP_SYS_IO_READ32(0xb0000010, &SysCfgReg); + SysCfgReg &= (1 << 6); /* XTAL_FREQ_SEL */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R11, 0x21); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R13, (SysCfgReg) ? 0x00:0x03); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R14, 0x7C); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R16, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R17, 0x99); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R18, 0x99); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R19, 0x09); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R20, 0x50); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R21, 0xB0); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R22, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R23, 0x06); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R24, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R25, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R26, 0x5D); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R27, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R28, 0x61); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R29, 0xB5); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R43, 0x02); + } + + if ((pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number >= 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF Central Registers for E3 !!!\n")); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R28, 0x62); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R29, 0xAD); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, 0x80); +#ifdef RTMP_TEMPERATURE_CALIBRATION + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R34, 0x23); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x01); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } + + /* it is old RF_R17 */ + RFValue = pAd->RfFreqOffset & 0xFF; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R12, RFValue); + + // Initialize RF channel register to default value + for (i = 0; i < RT6352_NUM_RF_CHANNEL_REG_PARMS; i++) + { + RT635xWriteRFRegister(pAd, RF_BANK4, RT6352_RFChannelRegTable[i].Register, RT6352_RFChannelRegTable[i].Value); + RT635xWriteRFRegister(pAd, RF_BANK6, RT6352_RFChannelRegTable[i].Register, RT6352_RFChannelRegTable[i].Value); + } + + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R45, 0xC5); + + if (pAd->CommonCfg.Chip_VerID > 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF Channel Registers for E2 !!!\n")); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R09, 0x47); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R09, 0x47); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R10, 0x71); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R10, 0x71); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R11, 0x33); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R11, 0x33); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R14, 0x0E); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R14, 0x0E); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R17, 0x23); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R17, 0x23); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R20, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R20, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R21, 0x12); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R21, 0x12); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R28, 0x1C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R28, 0x1C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R29, 0xEB); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R29, 0xEB); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R32, 0x7D); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R32, 0x7D); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R34, 0xD6); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R34, 0xD6); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R36, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R36, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R38, 0xB4); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R38, 0xB4); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R43, 0xD3); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R43, 0xD3); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R44, 0xB3); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R44, 0xB3); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R45, 0xD5); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R45, 0xD5); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R46, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R46, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x67); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0x69); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R48, 0xFF); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R48, 0xFF); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R54, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R55, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R55, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R56, 0xFF); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R56, 0xFF); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R57, 0x1C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R57, 0x1C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R58, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R58, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R59, 0x6B); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R59, 0x6B); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R60, 0xF7); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R60, 0xF7); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R61, 0x09); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R61, 0x09); + } + + if ((pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number >= 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF Channel Registers for E3 !!!\n")); + + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R10, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R10, 0x51); + + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R14, 0x06); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R14, 0x06); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, 0xA7); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, 0xA7); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R28, 0x2C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R28, 0x2C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R55, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R55, 0x64); + + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R08, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R08, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R09, 0x36); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R09, 0x36); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R11, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R11, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R14, 0x16); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R14, 0x16); + + //RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x27); + //RT635xWriteRFRegister(pAd, RF_BANK4, RF_R49, 0x1F); + + //RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x2B); + //RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0x2B); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x6C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0x6C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R48, 0xFC); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R48, 0xFC); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R49, 0x1F); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R49, 0x1F); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R55, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R55, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R59, 0x6B); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R59, 0x6B); + } + + if ((pAd->CommonCfg.PKG_ID == 0) && (pAd->CommonCfg.Chip_VerID == 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF Channel Registers for DRQFN !!!\n")); + + // Initialize RF channel register for DRQFN + for (i = 0; i < RT6352_NUM_RF_CHANNEL_REG_DRQFN_PARMS; i++) + { + RT635xWriteRFRegister(pAd, RF_BANK4, RT6352_RF_CHANNEL_REG_DRQFN[i].Register, RT6352_RF_CHANNEL_REG_DRQFN[i].Value); + RT635xWriteRFRegister(pAd, RF_BANK6, RT6352_RF_CHANNEL_REG_DRQFN[i].Register, RT6352_RF_CHANNEL_REG_DRQFN[i].Value); + } + } + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + { + DBGPRINT(RT_DEBUG_TRACE, ("Reduce Power Consumption Support !!!\n")); + + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R43, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R43, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R44, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R44, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R45, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R45, 0x53); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x24); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R48, 0x4F); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R48, 0x4F); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R49, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R49, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R55, 0x24); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R55, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R56, 0x4F); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R56, 0x4F); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R57, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R57, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R58, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R58, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R59, 0x24); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R59, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R60, 0x4F); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R60, 0x4F); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R61, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R61, 0x02); + } +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + + // Initialize RF DC calibration register to default value + for (i = 0; i < RT6352_NUM_RF_DCCAL_REG_PARMS; i++) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RT6352_RFDCCalRegTable[i].Register, RT6352_RFDCCalRegTable[i].Value); + RT635xWriteRFRegister(pAd, RF_BANK7, RT6352_RFDCCalRegTable[i].Register, RT6352_RFDCCalRegTable[i].Value); + } + + if (pAd->CommonCfg.Chip_VerID > 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF DCCal Registers for E2 !!!\n")); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x04); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x04); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R05, 0x20); + } + + if ((pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number >= 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Initialize RF DCCal Registers for E3 !!!\n")); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R05, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x7C); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, 0x7C); +#ifdef RTMP_TEMPERATURE_CALIBRATION + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x07); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x07); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- %s\n", __FUNCTION__)); +} + +#ifdef CONFIG_STA_SUPPORT +static UCHAR RT6352_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) + R66 = 0x04 + 2 * GET_LNA_GAIN(pAd); + + if (OrigR66Value != R66) + bbp_set_agc(pAd, R66, RX_CHAIN_ALL); + + return R66; +} +#endif // CONFIG_STA_SUPPORT // + +static VOID RT6352_ChipBBPAdjust( + IN RTMP_ADAPTER *pAd) +{ + UINT32 Value; + UCHAR byteValue = 0; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)) + { + pAd->CommonCfg.BBPCurrentBW = BW_40; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x1); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* RX : control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &byteValue); + byteValue &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, byteValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + DBGPRINT(RT_DEBUG_TRACE, ("ApStartUp : ExtAbove, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); + } + else if ((pAd->CommonCfg.Channel > 2) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + pAd->CommonCfg.BBPCurrentBW = BW_40; + + if (pAd->CommonCfg.Channel == 14) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + + /* TX : control channel at upper */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value |= (0x1); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* RX : control channel at upper */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &byteValue); + byteValue |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, byteValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + DBGPRINT(RT_DEBUG_TRACE, ("ApStartUp : ExtBlow, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x1); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("ApStartUp : 20MHz, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ + } +} + +static VOID RT6352_AsicAntennaDefaultReset( + IN PRTMP_ADAPTER pAd, + IN EEPROM_ANTENNA_STRUC *pAntenna) +{ + pAntenna->word = 0; + pAntenna->field.RfIcType = RFIC_6352; + pAntenna->field.TxPath = 2; + pAntenna->field.RxPath = 2; +} + +static VOID RT6352_ChipSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan) +{ + CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; + UCHAR index; + UINT32 Value = 0; //BbpReg, Value; + UCHAR RFValue; + UINT32 i = 0; + + i = i; /* avoid compile warning */ + RFValue = 0; + // Search Tx power value + +#ifdef SINGLE_SKU_V2 + pAd->CommonCfg.SkuChannel = Channel; +#endif /* SINGLE_SKU_V2 */ + /* + We can't use ChannelList to search channel, since some central channl's txpowr doesn't list + in ChannelList, so use TxPower array instead. + */ + for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) + { + if (Channel == pAd->TxPower[index].Channel) + { + TxPwer = pAd->TxPower[index].Power; + TxPwer2 = pAd->TxPower[index].Power2; + break; + } + } + + if (index == MAX_NUM_OF_CHANNELS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Can't find the Channel#%d \n", __FUNCTION__, Channel)); + } + + for (index = 0; index < NUM_OF_6352_CHNL; index++) + { + if (Channel == FreqItems6352[index].Channel) + { + UINT32 macStatus, saveMacSysCtrl, SysCfgReg; + USHORT k_count = 0; + + /* Frequeny plan setting */ + /* + * Rdiv setting + * R13[1:0] + */ + RTMP_SYS_IO_READ32(0xb0000010, &SysCfgReg); + SysCfgReg &= (1 << 6); /* XTAL_FREQ_SEL */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R13, &RFValue); + RFValue = RFValue & (~0x03); + if (!SysCfgReg) + RFValue |= (FreqItems6352[index].Rdiv & 0x3); + RT635xWriteRFRegister(pAd, RF_BANK0,RF_R13, RFValue); + + /* + * N setting + * R21[0], R20[7:0] + */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R20, &RFValue); + RFValue = (FreqItems6352[index].N & 0x00ff); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R20, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R21, &RFValue); + RFValue = RFValue & (~0x01); + RFValue |= ((FreqItems6352[index].N & 0x0100) >> 8); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R21, RFValue); + + + /* + * K setting + * R16[3:0] (RF PLL freq selection) + */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R16, &RFValue); + RFValue = RFValue & (~0x0f); + RFValue |= (FreqItems6352[index].K & 0x0f); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R16, RFValue); + + /* + * D setting + * R22[2:0] (D=15, R22[2:0]=<111>) + */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R22, &RFValue); + RFValue = RFValue & (~0x07); + RFValue |= (FreqItems6352[index].D & 0x07); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R22, RFValue); + + /* + * Ksd setting + * Ksd: R19<1:0>,R18<7:0>,R17<7:0> + */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R17, &RFValue); + RFValue = (FreqItems6352[index].Ksd & 0x000000ff); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R17, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R18, &RFValue); + RFValue = ((FreqItems6352[index].Ksd & 0x0000ff00) >> 8); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R18, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R19, &RFValue); + RFValue = RFValue & (~0x03); + RFValue |= ((FreqItems6352[index].Ksd & 0x00030000) >> 16); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R19, RFValue); + + if (pAd->CommonCfg.Chip_VerID > 1) + { + /* Default: XO=20MHz , SDM mode */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R16, &RFValue); + RFValue = RFValue & (~0xE0); + RFValue |= 0x80; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R16, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R21, &RFValue); + RFValue |= 0x80; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R21, RFValue); + } + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &RFValue); + if (pAd->Antenna.field.TxPath == 1) + RFValue &= (~0x2); + else + RFValue |= 0x2; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &RFValue); + if (pAd->Antenna.field.TxPath == 1) + RFValue &= (~0x20); + else + RFValue |= 0x20; + + if (pAd->Antenna.field.RxPath == 1) + RFValue &= (~0x02); + else + RFValue |= 0x02; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFValue); + if (pAd->Antenna.field.TxPath == 1) + RFValue &= (~0x40); + else + RFValue |= 0x40; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFValue); + + /* RF for DC Cal BW */ + for (i = 0; i < RT6352_NUM_RF_DCCAL_BW; i++) + { + if(pAd->CommonCfg.BBPCurrentBW == RT6352_RFDCCal_BW[i].BW) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RT6352_RFDCCal_BW[i].Register, RT6352_RFDCCal_BW[i].Value); + RT635xWriteRFRegister(pAd, RF_BANK7, RT6352_RFDCCal_BW[i].Register, RT6352_RFDCCal_BW[i].Value); + } + } + + if (pAd->CommonCfg.Chip_VerID > 1) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, 0x28); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R58, 0x28); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, 0x28); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R59, 0x28); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R58, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, 0x08); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R59, 0x08); + } + } + + if ((pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number == 2)) + { + RT635xReadRFRegister(pAd, RF_BANK0, RF_R28, &RFValue); + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && (Channel == 11)) + RFValue |= 0x4; + else + RFValue &= (~0x4); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R28, RFValue); + } + + if (bScan == FALSE) + { + /* BandWidth Filter Calibration */ + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, RFValue); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R06, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R06, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R07, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R07, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, RFValue); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R58, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R58, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R59, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[0]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R59, RFValue); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, RFValue); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R06, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R06, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R07, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->rx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R07, RFValue); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, RFValue); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R58, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R58, RFValue); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R59, &RFValue); + RFValue &= (~0x3F); + RFValue |= pAd->tx_bw_cal[1]; + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R59, RFValue); + } + } + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &Value); + Value = Value & (~0x3F3F); + Value |= TxPwer; + Value |= (TxPwer2 << 8); + Value |= (0x2F << 16); + Value |= (0x2F << 24); + +#ifdef RTMP_INTERNAL_TX_ALC + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE) && (bScan == FALSE)) + { + UCHAR target_power; + //USHORT E2pValue; + + /* init base power by e2p target power */ + //RT28xx_EEPROM_READ16(pAd, 0xD0, E2pValue); + target_power = (pAd->E2p_D0_Value & 0x3F); + Value = Value & (~0x3F3F); + Value |= target_power; + Value |= (target_power << 8); + } +#endif /* RTMP_INTERNAL_TX_ALC */ + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, Value); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &Value); + Value = Value & (~0x3F); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, Value); + +#ifdef RTMP_INTERNAL_TX_ALC + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE)&& (bScan == FALSE)) + { + RT635xTssiDcCalibration(pAd); + } +#endif /* RTMP_INTERNAL_TX_ALC */ + + if (bScan == FALSE) + { + /* Save MAC SYS CTRL registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + + /* Disable Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + + if (k_count == 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Wait MAC Status to MAX !!!\n", __FUNCTION__)); + } + + if ((pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number >= 2)) + { + UINT8 BBPValue; + + /* ADC clcok selection */ + DBGPRINT(RT_DEBUG_TRACE, ("ADC clcok selection for E3 !!!\n")); + { + if (Channel > 10) + { + DBGPRINT(RT_DEBUG_TRACE, ("Apr clock selection !!!\n")); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R30, &BBPValue); + BBPValue = 0x40; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R30, BBPValue); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, 0x00); +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0xFB); + } + else +#endif /* RT6352_EL_SUPPORT */ + { + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0x7B); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Shielding clock selection !!!\n")); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R30, &BBPValue); + BBPValue = 0x1F; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R30, BBPValue); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, 0x80); +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0xDB); + } + else +#endif /* RT6352_EL_SUPPORT */ + { + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0x5B); + } + } + } + } + + /* Restore MAC SYS CTRL registers */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + } + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R05, 0x40); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R04, 0x0C); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R04, &RFValue); + RFValue = ((RFValue & ~0x80) | 0x80); /* vcocal_en (initiate VCO calibration (reset after completion)) - It should be at the end of RF configuration. */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R04, RFValue); + RtmpOsMsDelay(2); + + /* latch channel for future usage.*/ + pAd->LatchRfRegs.Channel = Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("RT6352: SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), Rdiv=0x%02X, N=0x%02X, K=0x%02X, D=0x%02X, Ksd=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems6352[index].Rdiv, + FreqItems6352[index].N, + FreqItems6352[index].K, + FreqItems6352[index].D, + FreqItems6352[index].Ksd)); + break; + } + } + + if (bScan == FALSE) + { + pAd->Tx0_DPD_ALC_tag0 = 0; + pAd->Tx0_DPD_ALC_tag1 = 0; + pAd->Tx1_DPD_ALC_tag0 = 0; + pAd->Tx1_DPD_ALC_tag1 = 0; + + pAd->Tx0_DPD_ALC_tag0_flag = 0x0; + pAd->Tx0_DPD_ALC_tag1_flag = 0x0; + pAd->Tx1_DPD_ALC_tag0_flag = 0x0; + pAd->Tx1_DPD_ALC_tag1_flag = 0x0; + + + /* DPD_Calibration */ +#ifdef RT6352_EP_SUPPORT + if (pAd->bExtPA == FALSE) +#endif /* RT6352_EP_SUPPORT */ + { + DoDPDCalibration(pAd); + pAd->DoDPDCurrTemperature = 0x7FFFFFFF; + } + + /* Rx DCOC Calibration */ + RxDCOC_Calibration(pAd); + +#ifdef MICROWAVE_OVEN_SUPPORT + /* B5.R6 and B5.R7 */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &RFValue); + pAd->CommonCfg.MO_Cfg.Stored_RF_B5_R6 = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &RFValue); + pAd->CommonCfg.MO_Cfg.Stored_RF_B5_R7 = RFValue; +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + RT635xReadRFRegister(pAd, RF_BANK7, RF_R06, &RFValue); + pAd->CommonCfg.MO_Cfg.Stored_RF_B7_R6 = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R07, &RFValue); + pAd->CommonCfg.MO_Cfg.Stored_RF_B7_R7 = RFValue; + } +#endif /* RT6352 */ + DBGPRINT(RT_DEBUG_TRACE,("%s: Stored_RF_B5_R6=%x, and Stored_RF_B5_R7=%x \n", __FUNCTION__, + pAd->CommonCfg.MO_Cfg.Stored_RF_B5_R6, pAd->CommonCfg.MO_Cfg.Stored_RF_B5_R7)); +#endif /* MICROWAVE_OVEN_SUPPORT */ + + } + + /* BBP setting */ + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00150F0F;/* Gary 2007/08/09 0x050A0A */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* Turn off unused PA or LNA when only 1T or 1R */ + if (pAd->Antenna.field.TxPath == 1) + TxPinCfg &= 0xFFFFFFF3; + if (pAd->Antenna.field.RxPath == 1) + TxPinCfg &= 0xFFFFF3FF; + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + filter_coefficient_ctrl(pAd, Channel); + } + + /* BBP for GLRT BW */ + for (i = 0; i < RT6352_NUM_BBP_GLRT_BW; i++) + { + if(pAd->CommonCfg.BBPCurrentBW == RT6352_BBP_GLRT_BW[i].BW) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, RT6352_BBP_GLRT_BW[i].Register); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, RT6352_BBP_GLRT_BW[i].Value); + } + } + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + if(pAd->CommonCfg.BBPCurrentBW == BW_20) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R141); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x15); + } + } +#endif /* RT6352_EL_SUPPORT */ + + if (pAd->Antenna.field.RxPath == 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R91, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R128); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0xA0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R170); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x12); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R171); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x10); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R91, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, 0x9A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R128); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0xE0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R170); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x30); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R171); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x30); + } + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + /*bbp_set_agc(pAd, (0x2E + lanGain), RX_CHAIN_ALL);*/ + if (bScan) + RTMPSetAGCInitValue(pAd, BW_20); + else + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + /* On 11A, We should delay and wait RF/BBP to be stable*/ + /* and the appropriate time should be 1000 micro seconds */ + /* 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.*/ + RtmpusecDelay(1000); +} + +static VOID RT6352_RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66 = 0; + + if (pAd->LatchRfRegs.Channel <= 14) + R66 = 0x04 + 2 * GET_LNA_GAIN(pAd); + bbp_set_agc(pAd, R66, RX_CHAIN_ALL); + +#ifdef DYNAMIC_VGA_SUPPORT + /* Backup BBP_R66 */ + pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 = R66; + pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_1 = R66; +#endif /* DYNAMIC_VGA_SUPPORT */ + +} + +#ifdef RTMP_INTERNAL_TX_ALC +INT16 RT6352_lin2dBd( + IN unsigned short linearValue) +{ + short exp; + unsigned int mantisa; + int app,dBd; + + /* Default backoff ; to enhance leading bit searching time */ + mantisa = linearValue << DEFAULT_BO; + exp = -(DEFAULT_BO); + + /* Leading bit searching */ + if (mantisa < (0x8000)) + { + while (mantisa < (0x8000)) + { + mantisa = mantisa << 1; /* no need saturation */ + exp--; + if (exp < -20) + { + DBGPRINT_ERR(("input too small\n")); + DBGPRINT_ERR(("exponent = %d\n",exp)); + + return LIN2DB_ERROR_CODE; + } + } + } + else + { + while (mantisa > (0xFFFF)) + { + mantisa = mantisa >> 1; /* no need saturation */ + exp ++; + if (exp > 20) + { + DBGPRINT_ERR(("input too large\n")); + DBGPRINT_ERR(("exponent = %d\n",exp)); + + return LIN2DB_ERROR_CODE; + } + } + } +/* printk("exp=0d%d,mantisa=0x%x\n",exp,mantisa); */ + + if (mantisa <= 47104) + { + app=(mantisa+(mantisa>>3)+(mantisa>>4)-38400); /* S(15,0) */ + if (app<0) + { + app=0; + } + } + else + { + app=(mantisa-(mantisa>>3)-(mantisa>>6)-23040); /* S(15,0) */ + if (app<0) + { + app=0; + } + } + + dBd=((15+exp)<<15)+app; /*since 2^15=1 here */ +/* printk("dBd1=%d\n",dBd); */ + dBd=(dBd<<2)+(dBd<<1)+(dBd>>6)+(dBd>>7); + dBd=(dBd>>10); /* S10.5 */ +/* printk("app=%d,dBd=%d,dBdF=%f\n",app,dBd,(double)dBd/32); */ + + return(dBd); +} + +CHAR SignedExtension6To8( + IN CHAR org_value) +{ + /* 6-bit ---> 8-bit */ + CHAR value = org_value; + + DBGPRINT(RT_DEBUG_INFO, ("%s: original value is 0x%02x\n", __FUNCTION__, value)); + + if ((value & 0x20) == 0x00) /* positive */ + { + value = (value & ~0xE0); + } + else /* 0x20: negative number */ + { + value = (value | 0xC0); + } + + DBGPRINT(RT_DEBUG_INFO, ("%s: extended value is 0x%02x\n", __FUNCTION__, value)); + + return value; +} + +static INT32 rt635x_tssi_slope[2]; +static INT32 rt635x_tssi_offset[3][2]; +static INT32 rt635x_ant_pwr_offset[2]; + +/* read tssi_slope and tssi_offset from eeprom/efuse */ +VOID RT635xGetTssiInfo( + IN PRTMP_ADAPTER pAd) +{ + USHORT offset, value; + CHAR temp; + + /* get tssi slope 0 */ + offset = 0x6E; + RT28xx_EEPROM_READ16(pAd, offset, value); + rt635x_tssi_slope[0] = (INT32)(value & 0x00FF); + + /* get tssi_offset 0 */ + temp = (CHAR)((value & 0xFF00)>>8); + rt635x_tssi_offset[GROUP1_2G][0] = (INT32)temp; + + offset = 0x70; + RT28xx_EEPROM_READ16(pAd, offset, value); + temp = (CHAR)(value & 0x00FF); + rt635x_tssi_offset[GROUP2_2G][0] = (INT32)temp; + temp = (CHAR)((value & 0xFF00)>>8); + rt635x_tssi_offset[GROUP3_2G][0] = (INT32)temp; + + /* get tssi slope 1 */ + offset = 0x72; + RT28xx_EEPROM_READ16(pAd, offset, value); + rt635x_tssi_slope[1] = (INT32)(value & 0x00FF); + + /* get tssi_offset 1 */ + temp = (CHAR)((value & 0xFF00)>>8); + rt635x_tssi_offset[GROUP1_2G][1] = (INT32)temp; + + offset = 0x74; + RT28xx_EEPROM_READ16(pAd, offset, value); + temp = (CHAR)(value & 0x00FF); + rt635x_tssi_offset[GROUP2_2G][1] = (INT32)temp; + temp = (CHAR)((value & 0xFF00)>>8); + rt635x_tssi_offset[GROUP3_2G][1] = (INT32)temp; + + /* get tx0/tx1 power offset */ + offset = 0x76; + RT28xx_EEPROM_READ16(pAd, offset, value); + temp = (CHAR)(value & 0x00FF); + rt635x_ant_pwr_offset[0] = (INT32)(temp * 1024); /* 8192/8 */ + temp = (CHAR)((value & 0xFF00)>>8); + rt635x_ant_pwr_offset[1] = (INT32)(temp * 1024); /* 8192/8 */ + + if((rt635x_tssi_slope[0] < 0x66) || (rt635x_tssi_slope[0] > 0x99)){ + rt635x_tssi_slope[0] = 0x80; + rt635x_tssi_offset[GROUP1_2G][0] = 0x0; + rt635x_tssi_offset[GROUP2_2G][0] = 0x0; + rt635x_tssi_offset[GROUP3_2G][0] = 0x0; + } + + if((rt635x_tssi_slope[1] < 0x66) || (rt635x_tssi_slope[1] > 0x99)){ + rt635x_tssi_slope[1] = 0x80; + rt635x_tssi_offset[GROUP1_2G][1] = 0x0; + rt635x_tssi_offset[GROUP2_2G][1] = 0x0; + rt635x_tssi_offset[GROUP3_2G][1] = 0x0; + } + + return; +} + +/* results of TSSI DC calibration */ +INT32 rt635x_tssi0_dc; +INT32 rt635x_tssi1_dc; +INT32 rt635x_tssi0_dc_hvga; +INT32 rt635x_tssi1_dc_hvga; +INT32 rt635x_tssi0_db_hvga; +INT32 rt635x_tssi1_db_hvga; + +INT RT635xTssiDcCalibration( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RALINK_ATE + PATE_INFO pATEInfo = &(pAd->ate); +#endif /* RALINK_ATE */ + UINT32 MacValue = 0; + INT32 MacValue_tmp = 0; + UINT32 Mac1004_Org = 0; + UINT32 index; + UINT32 ant_idx; + INT32 tssi0_linear = 0, tssi1_linear = 0; + INT32 tssi0_db = 0, tssi1_db = 0, pwr=0, pwr1=0; + CHAR BBPR49; + UCHAR RFB5R3_Org, RFB7R3_Org, RFB4R39_Org, RFB6R39_Org,use_ant = 0; + UCHAR RFValue, BBPValue, BBPR1_Org; + CHAR bbp49_read, wait = 0, max_recal = 0; + UCHAR ch_group, channel; + UCHAR RFB0R42_Org, RFB0R2_Org, RFB0R1_Org; + UCHAR BBPTXGAIN[2]; + UCHAR agc_loop_cnt; + RT635xGetTssiInfo(pAd); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &RFB0R1_Org); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &RFB0R2_Org); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFB0R42_Org); + + RFValue = 0x03; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, RFValue); + RFValue = 0x33; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFValue); + RFValue = RFB0R42_Org | 0x50; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFValue); + + /* MAC Bypass */ + MacValue = 0x0004; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacValue); + MacValue = 0x3366; + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MacValue); + + MacValue = 0x0; /* ALC control */ + RTMP_IO_WRITE32(pAd, RF_CONTROL3, MacValue); + MacValue = 0xf1f1; + RTMP_IO_WRITE32(pAd, RF_BYPASS3, MacValue); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Mac1004_Org); + MacValue = 0x0; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1_Org); + BBPValue = BBPR1_Org; + BBPValue &= ~((1<<4)|(1<<3)); + BBPValue |= ((1<<4)|(0<<3)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPValue); + + /* set VGA gain */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFB5R3_Org); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFB7R3_Org); + RFValue = 0x08; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + + /* mixer disable */ + RT635xReadRFRegister(pAd, RF_BANK4, RF_R39, &RFB4R39_Org); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R39, &RFB6R39_Org); + RFValue = 0x00; + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R39, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R39, RFValue); + +redo: + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + + /* step 4 */ + for(ant_idx = 0; ant_idx < 2; ant_idx = ant_idx + 1){ + if(ant_idx == 0) + BBPTXGAIN[0]= 0x8; + else + BBPTXGAIN[1]= 0x8; + agc_loop_cnt = 0; + + for (index = 0; index < 4; index++) + { + switch(ant_idx){ + case 0: + RFValue = 0x01; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, RFValue); + RFValue = 0x11; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFValue); + // DAC 0 only + RFValue = RFB0R42_Org & (~0x50); + RFValue = RFB0R42_Org | 0x10; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFValue); + MacValue = 0x1004; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacValue); + break; + case 1: + RFValue = 0x02; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, RFValue); + RFValue = 0x22; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFValue); + // DAC 1 only + RFValue = RFB0R42_Org & (~0x50); + RFValue = RFB0R42_Org | 0x40; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFValue); + MacValue = 0x2004; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacValue); + break; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + /* a */ + switch (index) + { + case 0: + case 1: + RFValue = 0x00; + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R39, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R39, RFValue); + break; + default: + RFValue = 0xB3; + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R39, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R39, RFValue); + break; + } + RT635xReadRFRegister(pAd, RF_BANK4, RF_R39, &RFValue); + DBGPRINT(RT_DEBUG_TRACE, ("RF_B4R39 %08x\n", RFValue)); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R39, &RFValue); + DBGPRINT(RT_DEBUG_TRACE, ("RF_B6R39 %08x\n", RFValue)); + + /* b */ + switch (index) + { + case 0: + RFValue = 0x08;/* low tssi vga gain */ + break; + case 1: + RFValue = 0x11;/* high tssi vga gain */ + break; + case 2: + RFValue = 0x08; + break; + case 3: + RFValue = 0x11; + break; + } + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + + /* c */ + /* BBP TSSI initial and soft reset */ + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R58, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BBPValue); + BBPValue |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BBPValue); + RtmpusecDelay(1); /* wait 1 usec */ + BBPValue &= ~(0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BBPValue); + + /* d */ + /* TSSI measurement */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, 0x50); + + switch (index) + { + case 0: + case 1: + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x40); + break; + case 2: + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x31); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, BBPTXGAIN[0]); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BBPTXGAIN[1]); + break; + default: + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x31); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, BBPTXGAIN[0]-0x6); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BBPTXGAIN[1]-0x6); + break; + } + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R244, &BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R244 is 0x%02x\n", BBPValue)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R22 is 0x%02x\n", BBPValue)); + + for (wait=0; wait < 100; wait++) + { + RtmpusecDelay(2000); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (BBPValue != 0x50) + break; + } + + if ((wait >= 100) && (max_recal < 10)) + { + ASSERT(wait < 100); + max_recal++; + goto redo; + } + + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R47 is 0x%02x\n", BBPValue)); + + /* e */ + /* TSSI read */ + + BBPValue = (ant_idx == 0) ? 0x40 : 0x45; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + RtmpusecDelay(10); /* wait 10 usec */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if((index==2) && (agc_loop_cnt < 10)) + { + DBGPRINT( RT_DEBUG_ERROR, + ("BBPR49 %x BBPTXgain0 %x, BBPTXgain1 %x, loop cnt %d \n", BBPR49, BBPTXGAIN[0], BBPTXGAIN[1], agc_loop_cnt)); + agc_loop_cnt = agc_loop_cnt + 1; + tssi0_linear = (INT32)BBPR49; + tssi0_linear = tssi0_linear - ((ant_idx ==0) ? rt635x_tssi0_dc : rt635x_tssi1_dc); + if(BBPTXGAIN[ant_idx]> 0xf) + { + tssi0_linear = tssi0_linear; + } + else if(tssi0_linear < 0x4) + { + BBPTXGAIN[ant_idx]= BBPTXGAIN[ant_idx]+6; + if(BBPTXGAIN[ant_idx]> 0x10) + BBPTXGAIN[ant_idx]= 0x10; + index = index - 1; + continue; + } + else if(tssi0_linear < 0x8) + { + BBPTXGAIN[ant_idx]= BBPTXGAIN[ant_idx]+3; + if(BBPTXGAIN[ant_idx]> 0x10) + BBPTXGAIN[ant_idx]= 0x10; + index = index - 1; + continue; + } + else if(tssi0_linear < 0x10) + { + BBPTXGAIN[ant_idx]= BBPTXGAIN[ant_idx]+1; + if(BBPTXGAIN[ant_idx]> 0x10) + BBPTXGAIN[ant_idx] = 0x10; + index = index - 1; + continue; + } + } + + if(index==2) + { + DBGPRINT(RT_DEBUG_ERROR, ("BBPTXgain0 %x, BBPTXgain1 %x, loop cnt %d \n", BBPTXGAIN[0], BBPTXGAIN[1], agc_loop_cnt)); + } +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + + if(ant_idx == 0){ + switch (index){ + case 0: + rt635x_tssi0_dc = (INT32)BBPR49; + /* don't remove it ,for TSSI Calibration */ + printk("rt635x_tssi0_dc is 0x%08x\n", rt635x_tssi0_dc); + break; + case 1: + rt635x_tssi0_dc_hvga = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc_hvga is 0x%08x\n", rt635x_tssi0_dc_hvga)); + break; + case 2: + tssi0_linear = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("index %d: tssi0_linear is 0x%08x\n", index, tssi0_linear)); + + tssi0_db = RT6352_lin2dBd(tssi0_linear - rt635x_tssi0_dc); + DBGPRINT(RT_DEBUG_TRACE, ("tssi0_db is %d\n", tssi0_db)); + break; + case 3: + tssi0_linear = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("index %d: tssi0_linear hvga is 0x%08x\n", index, tssi0_linear)); + + tssi0_linear = tssi0_linear - rt635x_tssi0_dc_hvga; + tssi0_linear = tssi0_linear * 4; + rt635x_tssi0_db_hvga = RT6352_lin2dBd(tssi0_linear) - tssi0_db; + + DBGPRINT(RT_DEBUG_TRACE, ("tssi0_db_hvga is %d\n", rt635x_tssi0_db_hvga)); + break; + } + } + else{ + switch (index){ + case 0: + rt635x_tssi1_dc = (INT32)BBPR49; + /* don't remove it ,for TSSI Calibration */ + printk("rt635x_tssi1_dc is 0x%08x\n", rt635x_tssi1_dc); + break; + case 1: + rt635x_tssi1_dc_hvga = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc_hvga is 0x%08x\n", rt635x_tssi1_dc_hvga)); + break; + case 2: + tssi1_linear = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("index %d: tssi1_linear is 0x%08x\n", index, tssi1_linear)); + + tssi1_db = RT6352_lin2dBd(tssi1_linear - rt635x_tssi1_dc); + DBGPRINT(RT_DEBUG_TRACE, ("tssi1_db is %d\n", tssi1_db)); + break; + case 3: + tssi1_linear = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("index %d: tssi1_linear hvga is 0x%08x\n", index, tssi1_linear)); + + tssi1_linear = tssi1_linear - rt635x_tssi1_dc_hvga; + tssi1_linear = tssi1_linear*4; + + rt635x_tssi1_db_hvga = RT6352_lin2dBd(tssi1_linear) - tssi1_db; + DBGPRINT(RT_DEBUG_TRACE, ("tssi1_db_hvga is %d\n", rt635x_tssi1_db_hvga)); + break; + } + } + + MacValue = 0x0004; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacValue); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + } + +#ifdef DOT11_N_SUPPORT + channel = pAd->CommonCfg.CentralChannel; +#else + channel = pAd->CommonCfg.Channel; +#endif /* DOT11_N_SUPPORT */ + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + if (pATEInfo->TxAntennaSel == 0) // 2 antenna + use_ant = 0; + else if(pATEInfo->TxAntennaSel == 1) // 1st antenna + use_ant = 1; + else // 2nd antenna + use_ant = 2; + } + else +#endif /* RALINK_ATE */ + { + if(pAd->Antenna.field.TxPath == 2) // 2 antenna + use_ant = 0; + else // 1st antenna + use_ant = 1; + } + + ch_group = GET_2G_CHANNEL_GROUP(channel); + if(use_ant == 2) // only 2nd Tx + pwr = (tssi1_db*(rt635x_tssi_slope[1])) + (rt635x_tssi_offset[ch_group][1] << 9); + else // only 1st Tx or all Tx + pwr = (tssi0_db*(rt635x_tssi_slope[0])) + (rt635x_tssi_offset[ch_group][0] << 9); + + pwr = (pwr + 2048) / 4096; + pwr = -pwr+6; +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + pwr = pwr+(BBPTXGAIN[0]-8)*2; +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + if(pwr > 0x1f) + pwr = 0x1f; // + max + else if(pwr < -0x1f) + pwr = -0x1f; // - max + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue = MacValue & (~0x3f); + MacValue = MacValue | (pwr & 0x3f); + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B4 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + + if (use_ant == 0){ // All Tx + pwr1 = (tssi1_db*(rt635x_tssi_slope[1])) + (rt635x_tssi_offset[ch_group][1] << 9); + pwr1 = (pwr1+ 2048) / 4096; + pwr1 = -pwr1+6; + if(pwr1 > 0x1f) + pwr1 = 0x1f; // + max + else if(pwr1 < -0x1f) + pwr1 = -0x1f; // - max + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B0 is 0x%08x\n", MacValue)); + MacValue_tmp = (MacValue >> 8) & 0x3f; + MacValue_tmp = MacValue_tmp + pwr1 - pwr; + + if(MacValue_tmp > 0x3f) + MacValue_tmp = 0x3f; + else if(MacValue_tmp < 0x0) + MacValue_tmp = 0x0; + + MacValue_tmp = MacValue_tmp & 0x3f; + MacValue = MacValue & (~0x3f00); + MacValue = MacValue | (MacValue_tmp << 8); + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B0 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + } + + /* recover */ + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, BBPValue); + /* BBP soft reset */ + BBPValue = 0x01; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BBPValue); + RtmpusecDelay(1); /* wait 1 usec */ + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BBPValue); + + /* recover MAC */ + MacValue = 0x0; + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MacValue); + RTMP_IO_WRITE32(pAd, RF_BYPASS3, MacValue); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacValue); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, MacValue); /* ALC control */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Mac1004_Org); + + /* recover BBP */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1_Org); + + /* recover RF */ + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, RFB0R1_Org); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFB0R2_Org); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFB0R42_Org); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFB5R3_Org); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFB7R3_Org); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R39, RFB4R39_Org); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R39, RFB6R39_Org); + + return TRUE; +} + +/* TSSI tables */ +INT32 RT635x_McsPowerOverCCK[4] = {0}; +INT32 RT635x_McsPowerOverOFDM[8] = {0}; +INT32 RT635x_McsPowerOverHT[16] = {0}; +INT32 RT635x_McsPowerOverHTSTBC[8] = {0}; +UCHAR RT635x_RfPaModeOverCCK[4] = {0}; +UCHAR RT635x_RfPaModeOverOFDM[8] = {0}; +UCHAR RT635x_RfPaModeOverHT[16] = {0}; +//UCHAR RT635x_RfPaModeOverHTSTBC[8] = {0}; + +VOID RT635xInitMcsPowerTable( + IN PRTMP_ADAPTER pAd) +{ + UINT32 MacValue; + CHAR temp0, temp1, temp2, temp3; + + + /* CCK */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_0, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + /* bit[13:8] */ + temp1 = (CHAR)((MacValue & 0x00003F00) >> 8); + /* bit[21:16] */ + temp2 = (CHAR)((MacValue & 0x003F0000) >> 16); + /* bit[29:24] */ + temp3 = (CHAR)((MacValue & 0x3F000000) >> 24); + + RT635x_McsPowerOverCCK[0] = (INT32)SignedExtension6To8(temp0); + RT635x_McsPowerOverCCK[1] = RT635x_McsPowerOverCCK[0]; + RT635x_McsPowerOverCCK[2] = (INT32)SignedExtension6To8(temp1); + RT635x_McsPowerOverCCK[3] = RT635x_McsPowerOverCCK[2]; + + /* OFDM */ + RT635x_McsPowerOverOFDM[0] = (INT32)SignedExtension6To8(temp2); + RT635x_McsPowerOverOFDM[1] = RT635x_McsPowerOverOFDM[0]; + RT635x_McsPowerOverOFDM[2] = (INT32)SignedExtension6To8(temp3); + RT635x_McsPowerOverOFDM[3] = RT635x_McsPowerOverOFDM[2]; + + RTMP_IO_READ32(pAd, TX_PWR_CFG_1, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + /* bit[13:8] */ + temp1 = (CHAR)((MacValue & 0x00003F00) >> 8); + /* bit[21:16] */ + temp2 = (CHAR)((MacValue & 0x003F0000) >> 16); + /* bit[29:24] */ + temp3 = (CHAR)((MacValue & 0x3F000000) >> 24); + RT635x_McsPowerOverOFDM[4] = (INT32)SignedExtension6To8(temp0); + RT635x_McsPowerOverOFDM[5] = RT635x_McsPowerOverOFDM[4]; + RT635x_McsPowerOverOFDM[6] = (INT32)SignedExtension6To8(temp1); + + /* MCS */ + RT635x_McsPowerOverHT[0] = (INT32)SignedExtension6To8(temp2); + RT635x_McsPowerOverHT[1] = RT635x_McsPowerOverHT[0]; + RT635x_McsPowerOverHT[2] = (INT32)SignedExtension6To8(temp3); + RT635x_McsPowerOverHT[3] = RT635x_McsPowerOverHT[2]; + + RTMP_IO_READ32(pAd, TX_PWR_CFG_2, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + /* bit[13:8] */ + temp1 = (CHAR)((MacValue & 0x00003F00) >> 8); + /* bit[21:16] */ + temp2 = (CHAR)((MacValue & 0x003F0000) >> 16); + /* bit[29:24] */ + temp3 = (CHAR)((MacValue & 0x3F000000) >> 24); + RT635x_McsPowerOverHT[4] = (INT32)SignedExtension6To8(temp0); + RT635x_McsPowerOverHT[5] = RT635x_McsPowerOverHT[4]; + RT635x_McsPowerOverHT[6] = (INT32)SignedExtension6To8(temp1); + + RT635x_McsPowerOverHT[8] = (INT32)SignedExtension6To8(temp2); + RT635x_McsPowerOverHT[9] = RT635x_McsPowerOverHT[8]; + RT635x_McsPowerOverHT[10] = (INT32)SignedExtension6To8(temp3); + RT635x_McsPowerOverHT[11] = RT635x_McsPowerOverHT[10]; + + RTMP_IO_READ32(pAd, TX_PWR_CFG_3, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + /* bit[13:8] */ + temp1 = (CHAR)((MacValue & 0x00003F00) >> 8); + /* bit[21:16] */ + temp2 = (CHAR)((MacValue & 0x003F0000) >> 16); + /* bit[29:24] */ + temp3 = (CHAR)((MacValue & 0x3F000000) >> 24); + RT635x_McsPowerOverHT[12] = (INT32)SignedExtension6To8(temp0); + RT635x_McsPowerOverHT[13] = RT635x_McsPowerOverHT[12]; + RT635x_McsPowerOverHT[14] = (INT32)SignedExtension6To8(temp1); + + /* HT STBC */ + RT635x_McsPowerOverHTSTBC[0] = (INT32)SignedExtension6To8(temp2); + RT635x_McsPowerOverHTSTBC[1] = RT635x_McsPowerOverHTSTBC[0]; + RT635x_McsPowerOverHTSTBC[2] = (INT32)SignedExtension6To8(temp3); + RT635x_McsPowerOverHTSTBC[3] = RT635x_McsPowerOverHTSTBC[2]; + + RTMP_IO_READ32(pAd, TX_PWR_CFG_4, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + /* bit[13:8] */ + temp1 = (CHAR)((MacValue & 0x00003F00) >> 8); + RT635x_McsPowerOverHTSTBC[4] = (INT32)SignedExtension6To8(temp0); + RT635x_McsPowerOverHTSTBC[5] = RT635x_McsPowerOverHTSTBC[4]; + RT635x_McsPowerOverHTSTBC[6] = (INT32)SignedExtension6To8(temp1); + + /* extra */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_7, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + /* bit[21:16] */ + temp2 = (CHAR)((MacValue & 0x003F0000) >> 16); + RT635x_McsPowerOverOFDM[7] = (INT32)SignedExtension6To8(temp0); + RT635x_McsPowerOverHT[7] = (INT32)SignedExtension6To8(temp2); + + RTMP_IO_READ32(pAd, TX_PWR_CFG_8, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + RT635x_McsPowerOverHT[15] = (INT32)SignedExtension6To8(temp0); + + RTMP_IO_READ32(pAd, TX_PWR_CFG_9, &MacValue); + /* bit[5:0] */ + temp0 = (CHAR)((MacValue & 0x0000003F)); + RT635x_McsPowerOverHTSTBC[7] = (INT32)SignedExtension6To8(temp0); + + return; +} + + +VOID RT635xInitRfPaModeTable( + IN PRTMP_ADAPTER pAd) +{ + UINT32 MacValue; + UCHAR temp, bit; + + RTMP_IO_READ32(pAd, RF_PA_MODE_CFG0, &MacValue); /* MAC 0x121C */ + + /* CCK */ + for (bit = 0; bit < 8; bit += 2) + { + temp = (UCHAR)((MacValue >> bit) & (0x03)); + RT635x_RfPaModeOverCCK[bit/2] = temp; + } + + /* OFDM */ + for (bit = 8; bit < 24; bit += 2) + { + temp = (UCHAR)((MacValue >> bit) & (0x03)); + RT635x_RfPaModeOverOFDM[(bit-8)/2] = temp; + } + +// TODO:MCS 32 + + RTMP_IO_READ32(pAd, RF_PA_MODE_CFG1, &MacValue); /* MAC 0x1220 */ + /* HT */ + for (bit = 0; bit < 32; bit += 2) + { + temp = (UCHAR)((MacValue >> bit) & (0x03)); + RT635x_RfPaModeOverHT[bit/2] = temp; + } + + return; +} + +static VOID RT6352_InitDesiredTSSITable( + IN PRTMP_ADAPTER pAd) +{ + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("internal ALC is not enabled in NVM !\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + RT635xInitMcsPowerTable(pAd); + RT635xInitRfPaModeTable(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s\n", __FUNCTION__)); + + return; +} + +static INT32 rt635x_pwr_diff_pre[2]; + +VOID RT635xTssiCompensation( + IN PRTMP_ADAPTER pAd, + IN CHAR percent_delta) +{ + UINT32 MacValue; + INT32 base_power[max_ant]; + INT32 tssi_read[max_ant]; + INT32 pa_mode_00, pa_mode_01, pa_mode_11, pa_mode_used; + INT32 target_power = 0, mcs_power = 0, _comp_power = 0, bbp_6db_power = 0; + INT32 tssi_dc, tssi_m_dc, tssi_db; + INT32 pwr, pwr_diff[max_ant], pwr_diff_pre, pkt_type_delta; + INT32 comp_power[max_ant]; + INT32 cur_comp_power; + UCHAR RFValue, BBPValue, BBPR4, tssi_use_hvga[max_ant]; + UCHAR wait, ch_group, mcs, pa_mode, chain, channel; + CHAR temp[max_ant]; + CHAR BBPR49; + UCHAR max_stream = 1; + +#ifdef DOT11_N_SUPPORT + channel = pAd->CommonCfg.CentralChannel; +#else + channel = pAd->CommonCfg.Channel; +#endif /* DOT11_N_SUPPORT */ + + /* TSSI compensation */ + RT635xInitMcsPowerTable(pAd); + RT635xInitRfPaModeTable(pAd); + +#ifndef SINGLE_SKU_V2 + /* init base power by e2p target power */ + //RT28xx_EEPROM_READ16(pAd, 0xD0, E2pValue); + target_power = (INT32)(pAd->E2p_D0_Value & 0xFF); + + /* reduce target power if not 100% specified from UI */ + //target_power += (INT32)(percent_delta*2); + target_power += (INT32)(percent_delta); + target_power = (target_power < 0x0A) ? (0x0A) : target_power; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); + if ((MacValue & 0x3f) != target_power) + { + MacValue = MacValue & (~0x3F3F); + MacValue |= target_power; + MacValue |= (target_power << 8); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + } +#endif /* SINGLE_SKU_V2 */ + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + if (pAd->CommonCfg.TxStream == 2) + max_stream = 2; + } + else +#endif /* DOT11_N_SUPPORT */ + { + max_stream = 1; + } + +#ifdef GREENAP_SUPPORT + if ((pAd->ApCfg.bGreenAPEnable == TRUE) && + (pAd->ApCfg.GreenAPLevel!= GREENAP_11BGN_STAS)) + { + max_stream = 1; + } +#endif /* GREENAP_SUPPORT */ + + /* 0. get base power from 0x13B0 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); + + /* bit[5:0] */ + base_power[0] = (MacValue & 0x0000003F); + /* bit[13:8] */ + base_power[1] = (MacValue & 0x00003F00) >> 8; + + for (chain=0; chain < max_stream; chain++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\nchain %d: base_power is %d\n", chain, base_power[chain])); + + if (base_power[0] <= 20) + { + tssi_use_hvga[chain] = 1; + } + else + { + tssi_use_hvga[chain] = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("\ntssi_use_hvga %d \n", tssi_use_hvga[chain])); + } + + /* 1. set TSSI mode */ + if (tssi_use_hvga[0] == 1) + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x11); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x08); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + } + + /* for 2T2R */ + if (tssi_use_hvga[1] == 1) + { + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x11); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x08); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= ~((1<<6)|(1<<5)); + BBPValue |= ((1<<6)|(0<<5)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R58, 0x00); + + /* enable TSSI for next reading */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + BBPValue |= (1<<4); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + } + +/* RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); */ + + /* 3. polling BBP_R47 */ + for (wait=0; wait<200; wait++) + { + RtmpusecDelay(2000); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + break; + } + } + + ASSERT(wait < 200); + ASSERT((BBPValue & 0x10) == 0); + if ((BBPValue & 0x10) != 0) + return; + + /* 4. read TSSI */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi0_linear */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[0] = (INT32)BBPR49; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x05; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi1_linear */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[1] = (INT32)BBPR49; + + /* 5. read temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + pAd->CurrTemperature = (INT32)BBPR49; + + /* 6. estimate the target power */ + /* get packet type */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* read BBP_R178 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &BBPValue); + /* read BBP_R4 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + switch ((BBPR49 & 0x03)) + { + case 0: /* CCK */ + mcs = (UCHAR)((BBPR49 >> 4) & 0x03); + mcs_power = RT635x_McsPowerOverCCK[mcs]; + pa_mode = RT635x_RfPaModeOverCCK[mcs]; + + if (BBPValue == 0) /* BBP_R178 == 0 */ + { + if (BBPR4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + pkt_type_delta = 9831; /* 1.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + pkt_type_delta = 3 * 8192; + } + } + else /* BBP_R178 != 0 */ + { + if (BBPR4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + pkt_type_delta = 18023; /* 2.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + pkt_type_delta = 819; /* 0.1 x 8192 */ + } + } + break; + case 1: /* OFDM */ + mcs = (UCHAR)((BBPR49 >> 4) & 0x0F); + switch (mcs) + { + case 0xb: mcs = 0; break; + case 0xf: mcs = 1; break; + case 0xa: mcs = 2; break; + case 0xe: mcs = 3; break; + case 0x9: mcs = 4; break; + case 0xd: mcs = 5; break; + case 0x8: mcs = 6; break; + case 0xc: mcs = 7; break; + } + mcs_power = RT635x_McsPowerOverOFDM[mcs]; + pa_mode = RT635x_RfPaModeOverOFDM[mcs]; + pkt_type_delta = 0; + break; + default: // TODO:STBC + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + mcs = (UCHAR)(BBPR49 & 0x7F); + mcs_power = RT635x_McsPowerOverHT[mcs]; + pa_mode = RT635x_RfPaModeOverHT[mcs]; + pkt_type_delta = 0; + break; + } + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (((BBPR49 & 0x03) == 0) && (mcs == 0)) + return; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* 7. estimate delta power */ + /* read tssi_slope and tssi_offset from efuse */ + RT635xGetTssiInfo(pAd); + + ch_group = GET_2G_CHANNEL_GROUP(channel); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + cur_comp_power = MacValue & 0x3f; + if(cur_comp_power & 0x20) + cur_comp_power = cur_comp_power - 0x40; + + for (chain=0; chain < max_stream; chain++) + { +// if ((base_power[chain] + cur_comp_power) >= 0) + { + pa_mode_00 = 0; + pa_mode_01 = 4915; /* 0.6 * 8192 */ + pa_mode_11 = -6554; /* -0.8 * 8192 */ + } + pa_mode_used = (pa_mode == 0x00) ? pa_mode_00 : + (pa_mode == 0x01) ? pa_mode_01 : + pa_mode_11; /* pa_mode_11 is just default */ + + DBGPRINT(RT_DEBUG_TRACE, ("\n============chain %u============\n", chain)); + + if (chain == 0) + { + if (tssi_use_hvga[chain] == 1) + tssi_dc = rt635x_tssi0_dc_hvga; + else + tssi_dc = rt635x_tssi0_dc; + } + else + { + if (tssi_use_hvga[chain] == 1) + tssi_dc = rt635x_tssi1_dc_hvga; + else + tssi_dc = rt635x_tssi1_dc; + } + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc %x\n", rt635x_tssi0_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc %x\n", rt635x_tssi1_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc_hvga %x\n", rt635x_tssi0_dc_hvga)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc_hvga %x\n", rt635x_tssi1_dc_hvga)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_dc %x\n", tssi_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_linear %x\n", tssi_read[chain])); + tssi_m_dc = tssi_read[chain] - tssi_dc; + tssi_db = RT6352_lin2dBd(tssi_m_dc); + + if (tssi_use_hvga[chain]) + { + if (chain == 0) + tssi_db = tssi_db - rt635x_tssi0_db_hvga; + else + tssi_db = tssi_db - rt635x_tssi1_db_hvga; + } + + pwr = (tssi_db*(rt635x_tssi_slope[chain])) + + (rt635x_tssi_offset[ch_group][chain] << 9); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_slope %x\n", rt635x_tssi_slope[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("tssi offset %x\n", rt635x_tssi_offset[ch_group][chain])); + DBGPRINT(RT_DEBUG_TRACE, ("\npwr is %d \n", pwr)); + + /* read BBP_R1 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPValue); + switch ((BBPValue & 0x03)) + { + case 0: bbp_6db_power = 0; break; + case 1: bbp_6db_power = -49152; break; /* -6dB x 8192 */ + case 2: bbp_6db_power = -98304; break; /* -12dB x 8192 */ + case 3: bbp_6db_power = 49152; break; /* 6dB x 8192 */ + } + DBGPRINT(RT_DEBUG_TRACE, ("mcs_power %8d\n", mcs_power)); + DBGPRINT(RT_DEBUG_TRACE, ("pkt_type_delta %8d\n", pkt_type_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode %8d\n", pa_mode)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode used %8d\n", pa_mode_used)); + + target_power = base_power[0] + mcs_power; + target_power = target_power * 4096; + target_power = target_power + pa_mode_used + pkt_type_delta + + bbp_6db_power + rt635x_ant_pwr_offset[chain]; + DBGPRINT(RT_DEBUG_TRACE, ("target_power %d, pwr %d\n", target_power, pwr)); + pwr_diff[chain] = target_power - pwr; + + if ((tssi_read[chain] > 126) && (pwr_diff[chain] > 0)) /* upper saturation */ + pwr_diff[chain] = 0; + if (((tssi_read[chain] - tssi_dc) < 1) && (pwr_diff[chain] < 0)) /* lower saturation */ + pwr_diff[chain] = 0; + + pwr_diff_pre = rt635x_pwr_diff_pre[chain]; + + if (((pwr_diff_pre ^ pwr_diff[chain]) < 0) + && ((pwr_diff[chain] < 4096) && (pwr_diff[chain] > - 4096)) + && ((pwr_diff_pre < 4096) && (pwr_diff_pre > - 4096))) + { + if ((pwr_diff[chain] > 0) && ((pwr_diff[chain] + pwr_diff_pre) >= 0)) + pwr_diff[chain] = 0; + else if ((pwr_diff[chain] < 0) && ((pwr_diff[chain] + pwr_diff_pre) < 0)) + pwr_diff[chain] = 0; + else + pwr_diff_pre = pwr_diff[chain]; + } + else + { + pwr_diff_pre = pwr_diff[chain]; + } + + rt635x_pwr_diff_pre[chain] = pwr_diff_pre; + + pwr_diff[chain] = pwr_diff[chain] + ((pwr_diff[chain] > 0) ? 2048 : -2048); + pwr_diff[chain] = pwr_diff[chain] / 4096; + + if ((rt635x_tssi_slope[chain] > 0xa0) && (rt635x_tssi_slope[chain] < 0x60)) + pwr_diff[chain] = 0; + + /* get previous comp_power from 0x13B4 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + /* chain == 0 ? bit[5:0] : bit[13:8] */ + temp[chain] = MacValue & 0x0000003F; + DBGPRINT(RT_DEBUG_TRACE, ("temp[%d] is 0x%02x\n", chain, temp[chain])); + _comp_power = (INT32)SignedExtension6To8(temp[chain]); + + if(chain == 0) + _comp_power = _comp_power + pwr_diff[chain]; + else + _comp_power = base_power[chain] + pwr_diff[chain] - pwr_diff[0]; + + DBGPRINT(RT_DEBUG_TRACE, ("pwr_diff is %d\n", pwr_diff[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("_comp_power is 0x%08x\n", _comp_power)); + if (chain == 0) + { + if (_comp_power > 31) + _comp_power = 31; + else if(_comp_power < -31) + _comp_power = -31; + } + else + { + if(_comp_power < 0) + _comp_power = 0; + else if(_comp_power > 0x3f) + _comp_power = 0x3f; + } + comp_power[chain] = _comp_power; + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[%d] is 0x%08x\n", chain, comp_power[chain])); + } + + /* 8. write compensation value back */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue = MacValue & (~0x3f); + + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[0] is 0x%08x\n", comp_power[0])); + if (max_stream == 2) + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[1] is 0x%08x\n", comp_power[1])); + + MacValue = MacValue | (comp_power[0] & 0x3f); + + DBGPRINT(RT_DEBUG_TRACE, ("\n================================\n")); + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B4 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + MacValue = MacValue & (~0xff00); + if (max_stream == 2) + { + MacValue = MacValue | ((comp_power[1] & 0x3f) << 8); + } + else + { + MacValue = MacValue | ((base_power[0] & 0x3f) << 8); + } + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B0 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + + return; +} + +BOOLEAN RT635xTriggerTssiCompensation( + IN PRTMP_ADAPTER pAd, + IN CHAR percent_delta) +{ + UINT32 MacValue; + INT32 base_power[max_ant]; + INT32 tssi_read[max_ant]; + INT32 pa_mode_00, pa_mode_01, pa_mode_11, pa_mode_used; + INT32 target_power = 0, mcs_power = 0, _comp_power = 0, bbp_6db_power = 0; + INT32 tssi_dc, tssi_m_dc, tssi_db; + INT32 pwr, pwr_diff[max_ant], pwr_diff_pre, pkt_type_delta; + INT32 comp_power[max_ant]; + INT32 cur_comp_power; + UCHAR RFValue, BBPValue, BBPR4, tssi_use_hvga[max_ant]; + UCHAR wait, ch_group, mcs, pa_mode, chain, channel; + CHAR temp[max_ant]; + CHAR BBPR49; + UCHAR max_stream = 1; + + pAd->CommonCfg.bEnTemperatureTrack = FALSE; +#ifdef DOT11_N_SUPPORT + channel = pAd->CommonCfg.CentralChannel; +#else + channel = pAd->CommonCfg.Channel; +#endif /* DOT11_N_SUPPORT */ + + /* TSSI compensation */ + RT635xInitMcsPowerTable(pAd); + RT635xInitRfPaModeTable(pAd); + +#ifndef SINGLE_SKU_V2 + /* init base power by e2p target power */ + target_power = (INT32)(pAd->E2p_D0_Value & 0xFF); + + /* reduce target power if not 100% specified from UI */ + target_power += (INT32)(percent_delta); + target_power = (target_power < 0x0A) ? (0x0A) : target_power; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); + if ((MacValue & 0x3f) != target_power) + { + MacValue = MacValue & (~0x3F3F); + MacValue |= target_power; + MacValue |= (target_power << 8); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + } +#endif /* SINGLE_SKU_V2 */ + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + if (pAd->CommonCfg.TxStream == 2) + max_stream = 2; + } + else +#endif /* DOT11_N_SUPPORT */ + { + max_stream = 1; + } + +#ifdef GREENAP_SUPPORT + if ((pAd->ApCfg.bGreenAPEnable == TRUE) && + (pAd->ApCfg.GreenAPLevel!= GREENAP_11BGN_STAS)) + { + max_stream = 1; + } +#endif /* GREENAP_SUPPORT */ + + /* 0. get base power from 0x13B0 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); + + /* bit[5:0] */ + base_power[0] = (MacValue & 0x0000003F); + /* bit[13:8] */ + base_power[1] = (MacValue & 0x00003F00) >> 8; + + for (chain=0; chain < max_stream; chain++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\nchain %d: base_power is %d\n", chain, base_power[chain])); + + if (base_power[0] <= 20) + { + tssi_use_hvga[chain] = 1; + } + else + { + tssi_use_hvga[chain] = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("\ntssi_use_hvga %d \n", tssi_use_hvga[chain])); + } + + /* 1. set TSSI mode */ + if (tssi_use_hvga[0] == 1) + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x11); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x08); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + } + + /* for 2T2R */ + if (tssi_use_hvga[1] == 1) + { + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x11); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x08); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= ~((1<<6)|(1<<5)); + BBPValue |= ((1<<6)|(0<<5)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R58, 0x00); + + /* enable TSSI for next reading */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + BBPValue |= (1<<4); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + } + + /* 3. polling BBP_R47 */ + for (wait=0; wait < 2; wait++) + { + RtmpusecDelay(1000); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + break; + } + } + + if ((BBPValue & 0x10) != 0) + { + pAd->CommonCfg.bEnTemperatureTrack = TRUE; + return FALSE; + } + + /* 4. read TSSI */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi0_linear */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[0] = (INT32)BBPR49; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x05; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi1_linear */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[1] = (INT32)BBPR49; + + /* 5. read temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + pAd->CurrTemperature = (INT32)BBPR49; + + /* 6. estimate the target power */ + /* get packet type */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* read BBP_R178 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &BBPValue); + /* read BBP_R4 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + switch ((BBPR49 & 0x03)) + { + case 0: /* CCK */ + mcs = (UCHAR)((BBPR49 >> 4) & 0x03); + mcs_power = RT635x_McsPowerOverCCK[mcs]; + pa_mode = RT635x_RfPaModeOverCCK[mcs]; + + if (BBPValue == 0) /* BBP_R178 == 0 */ + { + if (BBPR4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + pkt_type_delta = 9831; /* 1.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + pkt_type_delta = 3 * 8192; + } + } + else /* BBP_R178 != 0 */ + { + if (BBPR4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + pkt_type_delta = 18023; /* 2.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + pkt_type_delta = 819; /* 0.1 x 8192 */ + } + } + break; + + case 1: /* OFDM */ + mcs = (UCHAR)((BBPR49 >> 4) & 0x0F); + switch (mcs) + { + case 0xb: mcs = 0; break; + case 0xf: mcs = 1; break; + case 0xa: mcs = 2; break; + case 0xe: mcs = 3; break; + case 0x9: mcs = 4; break; + case 0xd: mcs = 5; break; + case 0x8: mcs = 6; break; + case 0xc: mcs = 7; break; + } + mcs_power = RT635x_McsPowerOverOFDM[mcs]; + pa_mode = RT635x_RfPaModeOverOFDM[mcs]; + pkt_type_delta = 0; + break; + + default: // TODO:STBC + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + mcs = (UCHAR)(BBPR49 & 0x7F); + mcs_power = RT635x_McsPowerOverHT[mcs]; + pa_mode = RT635x_RfPaModeOverHT[mcs]; + pkt_type_delta = 0; + break; + } + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (((BBPR49 & 0x03) == 0) && (mcs == 0)) + return TRUE; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* 7. estimate delta power */ + /* read tssi_slope and tssi_offset from efuse */ + RT635xGetTssiInfo(pAd); + + ch_group = GET_2G_CHANNEL_GROUP(channel); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + cur_comp_power = MacValue & 0x3f; + if(cur_comp_power & 0x20) + cur_comp_power = cur_comp_power - 0x40; + + for (chain=0; chain < max_stream; chain++) + { + pa_mode_00 = 0; + pa_mode_01 = 4915; /* 0.6 * 8192 */ + pa_mode_11 = -6554; /* -0.8 * 8192 */ + + pa_mode_used = (pa_mode == 0x00) ? pa_mode_00 : + (pa_mode == 0x01) ? pa_mode_01 : + pa_mode_11; /* pa_mode_11 is just default */ + + DBGPRINT(RT_DEBUG_TRACE, ("\n============chain %u============\n", chain)); + + if (chain == 0) + { + if (tssi_use_hvga[chain] == 1) + tssi_dc = rt635x_tssi0_dc_hvga; + else + tssi_dc = rt635x_tssi0_dc; + } + else + { + if (tssi_use_hvga[chain] == 1) + tssi_dc = rt635x_tssi1_dc_hvga; + else + tssi_dc = rt635x_tssi1_dc; + } + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc %x\n", rt635x_tssi0_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc %x\n", rt635x_tssi1_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc_hvga %x\n", rt635x_tssi0_dc_hvga)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc_hvga %x\n", rt635x_tssi1_dc_hvga)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_dc %x\n", tssi_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_linear %x\n", tssi_read[chain])); + tssi_m_dc = tssi_read[chain] - tssi_dc; + tssi_db = RT6352_lin2dBd(tssi_m_dc); + + if (tssi_use_hvga[chain]) + { + if (chain == 0) + tssi_db = tssi_db - rt635x_tssi0_db_hvga; + else + tssi_db = tssi_db - rt635x_tssi1_db_hvga; + } + + pwr = (tssi_db*(rt635x_tssi_slope[chain])) + + (rt635x_tssi_offset[ch_group][chain] << 9); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_slope %x\n", rt635x_tssi_slope[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("tssi offset %x\n", rt635x_tssi_offset[ch_group][chain])); + DBGPRINT(RT_DEBUG_TRACE, ("\npwr is %d \n", pwr)); + + /* read BBP_R1 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPValue); + switch ((BBPValue & 0x03)) + { + case 0: bbp_6db_power = 0; break; + case 1: bbp_6db_power = -49152; break; /* -6dB x 8192 */ + case 2: bbp_6db_power = -98304; break; /* -12dB x 8192 */ + case 3: bbp_6db_power = 49152; break; /* 6dB x 8192 */ + } + DBGPRINT(RT_DEBUG_TRACE, ("mcs_power %8d\n", mcs_power)); + DBGPRINT(RT_DEBUG_TRACE, ("pkt_type_delta %8d\n", pkt_type_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode %8d\n", pa_mode)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode used %8d\n", pa_mode_used)); + + target_power = base_power[0] + mcs_power; + target_power = target_power * 4096; + target_power = target_power + pa_mode_used + pkt_type_delta + + bbp_6db_power + rt635x_ant_pwr_offset[chain]; + DBGPRINT(RT_DEBUG_TRACE, ("target_power %d, pwr %d\n", target_power, pwr)); + pwr_diff[chain] = target_power - pwr; + + if ((tssi_read[chain] > 126) && (pwr_diff[chain] > 0)) /* upper saturation */ + pwr_diff[chain] = 0; + + if (((tssi_read[chain] - tssi_dc) < 1) && (pwr_diff[chain] < 0)) /* lower saturation */ + pwr_diff[chain] = 0; + + pwr_diff_pre = rt635x_pwr_diff_pre[chain]; + + if (((pwr_diff_pre ^ pwr_diff[chain]) < 0) + && ((pwr_diff[chain] < 4096) && (pwr_diff[chain] > - 4096)) + && ((pwr_diff_pre < 4096) && (pwr_diff_pre > - 4096))) + { + if ((pwr_diff[chain] > 0) && ((pwr_diff[chain] + pwr_diff_pre) >= 0)) + pwr_diff[chain] = 0; + else if ((pwr_diff[chain] < 0) && ((pwr_diff[chain] + pwr_diff_pre) < 0)) + pwr_diff[chain] = 0; + else + pwr_diff_pre = pwr_diff[chain]; + } + else + { + pwr_diff_pre = pwr_diff[chain]; + } + + rt635x_pwr_diff_pre[chain] = pwr_diff_pre; + + pwr_diff[chain] = pwr_diff[chain] + ((pwr_diff[chain] > 0) ? 2048 : -2048); + pwr_diff[chain] = pwr_diff[chain] / 4096; + + if ((rt635x_tssi_slope[chain] > 0xa0) && (rt635x_tssi_slope[chain] < 0x60)) + pwr_diff[chain] = 0; + + /* get previous comp_power from 0x13B4 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + /* chain == 0 ? bit[5:0] : bit[13:8] */ + temp[chain] = MacValue & 0x0000003F; + DBGPRINT(RT_DEBUG_TRACE, ("temp[%d] is 0x%02x\n", chain, temp[chain])); + _comp_power = (INT32)SignedExtension6To8(temp[chain]); + + if(chain == 0) + _comp_power = _comp_power + pwr_diff[chain]; + else + _comp_power = base_power[chain] + pwr_diff[chain] - pwr_diff[0]; + + DBGPRINT(RT_DEBUG_TRACE, ("pwr_diff is %d\n", pwr_diff[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("_comp_power is 0x%08x\n", _comp_power)); + if (chain == 0) + { + if (_comp_power > 31) + _comp_power = 31; + else if(_comp_power < -31) + _comp_power = -31; + } + else + { + if(_comp_power < 0) + _comp_power = 0; + else if(_comp_power > 0x3f) + _comp_power = 0x3f; + } + comp_power[chain] = _comp_power; + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[%d] is 0x%08x\n", chain, comp_power[chain])); + } + + /* 8. write compensation value back */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue = MacValue & (~0x3f); + + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[0] is 0x%08x\n", comp_power[0])); + if (max_stream == 2) + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[1] is 0x%08x\n", comp_power[1])); + + MacValue = MacValue | (comp_power[0] & 0x3f); + + DBGPRINT(RT_DEBUG_TRACE, ("\n================================\n")); + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B4 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + MacValue = MacValue & (~0xff00); + if (max_stream == 2) + { + MacValue = MacValue | ((comp_power[1] & 0x3f) << 8); + } + else + { + MacValue = MacValue | ((base_power[0] & 0x3f) << 8); + } + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B0 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + + return TRUE; +} + +BOOLEAN RT635xCheckTssiCompensation( + IN PRTMP_ADAPTER pAd) +{ + UINT32 MacValue; + INT32 base_power[max_ant]; + INT32 tssi_read[max_ant]; + INT32 pa_mode_00, pa_mode_01, pa_mode_11, pa_mode_used; + INT32 target_power = 0, mcs_power = 0, _comp_power = 0, bbp_6db_power = 0; + INT32 tssi_dc, tssi_m_dc, tssi_db; + INT32 pwr, pwr_diff[max_ant], pwr_diff_pre, pkt_type_delta; + INT32 comp_power[max_ant]; + INT32 cur_comp_power; + UCHAR BBPValue, BBPR4, tssi_use_hvga[max_ant]; + UCHAR ch_group, mcs, pa_mode, chain, channel; + CHAR temp[max_ant]; + CHAR BBPR49; + UCHAR max_stream = 1; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + if ((BBPValue & 0x10) != 0) + return FALSE; + + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + +#ifdef DOT11_N_SUPPORT + channel = pAd->CommonCfg.CentralChannel; +#else + channel = pAd->CommonCfg.Channel; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + if (pAd->CommonCfg.TxStream == 2) + max_stream = 2; + } + else +#endif /* DOT11_N_SUPPORT */ + { + max_stream = 1; + } + +#ifdef GREENAP_SUPPORT + if ((pAd->ApCfg.bGreenAPEnable == TRUE) && + (pAd->ApCfg.GreenAPLevel!= GREENAP_11BGN_STAS)) + { + max_stream = 1; + } +#endif /* GREENAP_SUPPORT */ + + /* 0. get base power from 0x13B0 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); + + /* bit[5:0] */ + base_power[0] = (MacValue & 0x0000003F); + /* bit[13:8] */ + base_power[1] = (MacValue & 0x00003F00) >> 8; + + for (chain=0; chain < max_stream; chain++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\nchain %d: base_power is %d\n", chain, base_power[chain])); + + if (base_power[0] <= 20) + { + tssi_use_hvga[chain] = 1; + } + else + { + tssi_use_hvga[chain] = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("\ntssi_use_hvga %d \n", tssi_use_hvga[chain])); + } + + /* 4. read TSSI */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi0_linear */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[0] = (INT32)BBPR49; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x05; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi1_linear */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[1] = (INT32)BBPR49; + + /* 5. read temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + pAd->CurrTemperature = (INT32)BBPR49; + + /* 6. estimate the target power */ + /* get packet type */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* read BBP_R178 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &BBPValue); + /* read BBP_R4 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + switch ((BBPR49 & 0x03)) + { + case 0: /* CCK */ + mcs = (UCHAR)((BBPR49 >> 4) & 0x03); + mcs_power = RT635x_McsPowerOverCCK[mcs]; + pa_mode = RT635x_RfPaModeOverCCK[mcs]; + + if (BBPValue == 0) /* BBP_R178 == 0 */ + { + if (BBPR4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + pkt_type_delta = 9831; /* 1.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + pkt_type_delta = 3 * 8192; + } + } + else /* BBP_R178 != 0 */ + { + if (BBPR4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + pkt_type_delta = 18023; /* 2.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + pkt_type_delta = 819; /* 0.1 x 8192 */ + } + } + break; + + case 1: /* OFDM */ + mcs = (UCHAR)((BBPR49 >> 4) & 0x0F); + switch (mcs) + { + case 0xb: mcs = 0; break; + case 0xf: mcs = 1; break; + case 0xa: mcs = 2; break; + case 0xe: mcs = 3; break; + case 0x9: mcs = 4; break; + case 0xd: mcs = 5; break; + case 0x8: mcs = 6; break; + case 0xc: mcs = 7; break; + } + mcs_power = RT635x_McsPowerOverOFDM[mcs]; + pa_mode = RT635x_RfPaModeOverOFDM[mcs]; + pkt_type_delta = 0; + break; + + default: // TODO:STBC + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + mcs = (UCHAR)(BBPR49 & 0x7F); + mcs_power = RT635x_McsPowerOverHT[mcs]; + pa_mode = RT635x_RfPaModeOverHT[mcs]; + pkt_type_delta = 0; + break; + } + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (((BBPR49 & 0x03) == 0) && (mcs == 0)) + return TRUE; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* 7. estimate delta power */ + /* read tssi_slope and tssi_offset from efuse */ + RT635xGetTssiInfo(pAd); + + ch_group = GET_2G_CHANNEL_GROUP(channel); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + cur_comp_power = MacValue & 0x3f; + if(cur_comp_power & 0x20) + cur_comp_power = cur_comp_power - 0x40; + + for (chain=0; chain < max_stream; chain++) + { + pa_mode_00 = 0; + pa_mode_01 = 4915; /* 0.6 * 8192 */ + pa_mode_11 = -6554; /* -0.8 * 8192 */ + + pa_mode_used = (pa_mode == 0x00) ? pa_mode_00 : + (pa_mode == 0x01) ? pa_mode_01 : + pa_mode_11; /* pa_mode_11 is just default */ + + DBGPRINT(RT_DEBUG_TRACE, ("\n============chain %u============\n", chain)); + + if (chain == 0) + { + if (tssi_use_hvga[chain] == 1) + tssi_dc = rt635x_tssi0_dc_hvga; + else + tssi_dc = rt635x_tssi0_dc; + } + else + { + if (tssi_use_hvga[chain] == 1) + tssi_dc = rt635x_tssi1_dc_hvga; + else + tssi_dc = rt635x_tssi1_dc; + } + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc %x\n", rt635x_tssi0_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc %x\n", rt635x_tssi1_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi0_dc_hvga %x\n", rt635x_tssi0_dc_hvga)); + DBGPRINT(RT_DEBUG_TRACE, ("rt635x_tssi1_dc_hvga %x\n", rt635x_tssi1_dc_hvga)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_dc %x\n", tssi_dc)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_linear %x\n", tssi_read[chain])); + tssi_m_dc = tssi_read[chain] - tssi_dc; + tssi_db = RT6352_lin2dBd(tssi_m_dc); + + if (tssi_use_hvga[chain]) + { + if (chain == 0) + tssi_db = tssi_db - rt635x_tssi0_db_hvga; + else + tssi_db = tssi_db - rt635x_tssi1_db_hvga; + } + + pwr = (tssi_db*(rt635x_tssi_slope[chain])) + + (rt635x_tssi_offset[ch_group][chain] << 9); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_slope %x\n", rt635x_tssi_slope[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("tssi offset %x\n", rt635x_tssi_offset[ch_group][chain])); + DBGPRINT(RT_DEBUG_TRACE, ("\npwr is %d \n", pwr)); + + /* read BBP_R1 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPValue); + switch ((BBPValue & 0x03)) + { + case 0: bbp_6db_power = 0; break; + case 1: bbp_6db_power = -49152; break; /* -6dB x 8192 */ + case 2: bbp_6db_power = -98304; break; /* -12dB x 8192 */ + case 3: bbp_6db_power = 49152; break; /* 6dB x 8192 */ + } + DBGPRINT(RT_DEBUG_TRACE, ("mcs_power %8d\n", mcs_power)); + DBGPRINT(RT_DEBUG_TRACE, ("pkt_type_delta %8d\n", pkt_type_delta)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode %8d\n", pa_mode)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode used %8d\n", pa_mode_used)); + + target_power = base_power[0] + mcs_power; + target_power = target_power * 4096; + target_power = target_power + pa_mode_used + pkt_type_delta + + bbp_6db_power + rt635x_ant_pwr_offset[chain]; + DBGPRINT(RT_DEBUG_TRACE, ("target_power %d, pwr %d\n", target_power, pwr)); + pwr_diff[chain] = target_power - pwr; + + if ((tssi_read[chain] > 126) && (pwr_diff[chain] > 0)) /* upper saturation */ + pwr_diff[chain] = 0; + + if (((tssi_read[chain] - tssi_dc) < 1) && (pwr_diff[chain] < 0)) /* lower saturation */ + pwr_diff[chain] = 0; + + pwr_diff_pre = rt635x_pwr_diff_pre[chain]; + + if (((pwr_diff_pre ^ pwr_diff[chain]) < 0) + && ((pwr_diff[chain] < 4096) && (pwr_diff[chain] > - 4096)) + && ((pwr_diff_pre < 4096) && (pwr_diff_pre > - 4096))) + { + if ((pwr_diff[chain] > 0) && ((pwr_diff[chain] + pwr_diff_pre) >= 0)) + pwr_diff[chain] = 0; + else if ((pwr_diff[chain] < 0) && ((pwr_diff[chain] + pwr_diff_pre) < 0)) + pwr_diff[chain] = 0; + else + pwr_diff_pre = pwr_diff[chain]; + } + else + { + pwr_diff_pre = pwr_diff[chain]; + } + + rt635x_pwr_diff_pre[chain] = pwr_diff_pre; + + pwr_diff[chain] = pwr_diff[chain] + ((pwr_diff[chain] > 0) ? 2048 : -2048); + pwr_diff[chain] = pwr_diff[chain] / 4096; + + if ((rt635x_tssi_slope[chain] > 0xa0) && (rt635x_tssi_slope[chain] < 0x60)) + pwr_diff[chain] = 0; + + /* get previous comp_power from 0x13B4 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + /* chain == 0 ? bit[5:0] : bit[13:8] */ + temp[chain] = MacValue & 0x0000003F; + DBGPRINT(RT_DEBUG_TRACE, ("temp[%d] is 0x%02x\n", chain, temp[chain])); + _comp_power = (INT32)SignedExtension6To8(temp[chain]); + + if(chain == 0) + _comp_power = _comp_power + pwr_diff[chain]; + else + _comp_power = base_power[chain] + pwr_diff[chain] - pwr_diff[0]; + + DBGPRINT(RT_DEBUG_TRACE, ("pwr_diff is %d\n", pwr_diff[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("_comp_power is 0x%08x\n", _comp_power)); + if (chain == 0) + { + if (_comp_power > 31) + _comp_power = 31; + else if(_comp_power < -31) + _comp_power = -31; + } + else + { + if(_comp_power < 0) + _comp_power = 0; + else if(_comp_power > 0x3f) + _comp_power = 0x3f; + } + comp_power[chain] = _comp_power; + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[%d] is 0x%08x\n", chain, comp_power[chain])); + } + + /* 8. write compensation value back */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue = MacValue & (~0x3f); + + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[0] is 0x%08x\n", comp_power[0])); + if (max_stream == 2) + DBGPRINT(RT_DEBUG_TRACE, ("comp_power[1] is 0x%08x\n", comp_power[1])); + + MacValue = MacValue | (comp_power[0] & 0x3f); + + DBGPRINT(RT_DEBUG_TRACE, ("\n================================\n")); + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B4 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); /* MAC 0x13B0 */ + MacValue = MacValue & (~0xff00); + if (max_stream == 2) + { + MacValue = MacValue | ((comp_power[1] & 0x3f) << 8); + } + else + { + MacValue = MacValue | ((base_power[0] & 0x3f) << 8); + } + DBGPRINT(RT_DEBUG_TRACE, ("Mac 0x13B0 is 0x%08x\n", MacValue)); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + + return TRUE; +} + +#endif /* RTMP_INTERNAL_TX_ALC */ + +/* + ======================================================================== + + Routine Description: + Read initial Tx power per MCS and BW from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RT6352_RTMPReadTxPwrPerRate( + IN PRTMP_ADAPTER pAd) +{ + ULONG data, Gdata; + USHORT i, value, value2; + USHORT value_1, value_3; + INT Gpwrdelta; + USHORT t1,t3; + BOOLEAN bGpwrdeltaMinus = TRUE; + CHAR value_1_plus, value_3_plus; + + /* Get power delta for 20MHz and 40MHz.*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); + + Gpwrdelta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x .\n", Gpwrdelta)); + + /* Get Txpower per MCS for 20MHz in 2.4G.*/ + + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); + data = value; + + /* use value_1 ~ value_4 for code size reduce */ + value_1 = value&0x3f; + value_3 = (value&0x3f00)>>8; + + if (value_1 > 31) + value_1_plus = value_1 - 64; + else + value_1_plus = value_1; + + if (value_3 > 31) + value_3_plus = value_3 - 64; + else + value_3_plus = value_3; + + if (bGpwrdeltaMinus == FALSE) + { + value_1_plus = value_1_plus + (Gpwrdelta); + + if (value_1_plus < 0) + t1 = value_1_plus + 64; + else + { + t1 = value_1_plus; + + if (t1 > 0x1f) + t1 = 0x1f; + } + + if (t1 > 0x3f) + { + t1 = 0x3f; + } + + value_3_plus = value_3_plus + (Gpwrdelta); + + if (value_3_plus < 0) + t3 = value_3_plus + 64; + else + { + t3 = value_3_plus; + + if (t3 > 0x1f) + t3 = 0x1f; + } + + if (t3 > 0x3f) + { + t3 = 0x3f; + } + } + else + { + if ((value_1_plus - Gpwrdelta) <= -31) + t1 = 0x21; + else + { + value_1_plus = (value_1_plus - Gpwrdelta); + + if (value_1_plus < 0) + t1 = value_1_plus + 64; + else + t1 = value_1_plus; + } + + if ((value_3_plus - Gpwrdelta) <= -31) + t3 = 0x21; + else + { + value_3_plus = (value_3_plus - Gpwrdelta); + + if (value_3_plus < 0) + t3 = value_3_plus + 64; + else + t3 = value_3_plus; + } + } + Gdata = t1 + (t3<<8); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); + + /* use value_1 ~ value_4 for code size reduce */ + value_1 = value&0x3f; + value_3 = (value&0x3f00)>>8; + + if (value_1 > 31) + value_1_plus = value_1 - 64; + else + value_1_plus = value_1; + + if (value_3 > 31) + value_3_plus = value_3 - 64; + else + value_3_plus = value_3; + + if (bGpwrdeltaMinus == FALSE) + { + value_1_plus = value_1_plus + (Gpwrdelta); + + if (value_1_plus < 0) + t1 = value_1_plus + 64; + else + { + t1 = value_1_plus; + + if (t1 > 0x1f) + t1 = 0x1f; + } + + if (t1 > 0x3f) + { + t1 = 0x3f; + } + + value_3_plus = value_3_plus + (Gpwrdelta); + + if (value_3_plus < 0) + t3 = value_3_plus + 64; + else + { + t3 = value_3_plus; + + if (t3 > 0x1f) + t3 = 0x1f; + } + + if (t3 > 0x3f) + { + t3 = 0x3f; + } + } + else + { + if ((value_1_plus - Gpwrdelta) <= -31) + t1 = 0x21; + else + { + value_1_plus = (value_1_plus - Gpwrdelta); + if (value_1_plus < 0) + t1 = value_1_plus + 64; + else + t1 = value_1_plus; + } + + if ((value_3_plus - Gpwrdelta) <= -31) + t3 = 0x21; + else + { + value_3_plus = (value_3_plus - Gpwrdelta); + if (value_3_plus < 0) + t3 = value_3_plus + 64; + else + t3 = value_3_plus; + } + } + Gdata |= ((t1<<16) + (t3<<24)); + data |= (value<<16); + + /* For 20M/40M Power Delta issue */ + pAd->Tx20MPwrCfgGBand[i] = data; + pAd->Tx40MPwrCfgGBand[i] = Gdata; + + if (data != 0xffffffff) + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Gdata = %lx \n", data, Gdata)); + } + + /* Extra set MAC registers to compensate Tx power if any */ + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); +} + +static VOID RT6352_AsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd) +{ + ULONG ExtraPwrOverMAC = 0; + ULONG ExtraPwrOverTxPwrCfg7 = 0, ExtraPwrOverTxPwrCfg8 = 0, ExtraPwrOverTxPwrCfg9 = 0; + + /* For OFDM_54 and HT_MCS_7, extra fill the corresponding register value into MAC 0x13D4 */ + RTMP_IO_READ32(pAd, 0x1318, &ExtraPwrOverMAC); + ExtraPwrOverTxPwrCfg7 |= (ExtraPwrOverMAC & 0x0000FF00) >> 8; /* Get Tx power for OFDM 54 */ + RTMP_IO_READ32(pAd, 0x131C, &ExtraPwrOverMAC); + ExtraPwrOverTxPwrCfg7 |= (ExtraPwrOverMAC & 0x0000FF00) << 8; /* Get Tx power for HT MCS 7 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, ExtraPwrOverTxPwrCfg7); + + /* For STBC_MCS_7, extra fill the corresponding register value into MAC 0x13DC */ + RTMP_IO_READ32(pAd, 0x1324, &ExtraPwrOverMAC); + ExtraPwrOverTxPwrCfg9 |= (ExtraPwrOverMAC & 0x0000FF00) >> 8; /* Get Tx power for STBC MCS 7 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, ExtraPwrOverTxPwrCfg9); + + /* For HT_MCS_15, extra fill the corresponding register value into MAC 0x13DC */ + RTMP_IO_READ32(pAd, 0x1320, &ExtraPwrOverMAC); + ExtraPwrOverTxPwrCfg8 |= (ExtraPwrOverMAC & 0x0000FF00) >> 8; /* Get Tx power for HT MCS 15 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, ExtraPwrOverTxPwrCfg8); + + DBGPRINT(RT_DEBUG_INFO, ("Offset =0x13D8, TxPwr = 0x%08X, ", (UINT)ExtraPwrOverTxPwrCfg8)); + + DBGPRINT(RT_DEBUG_INFO, ("Offset = 0x13D4, TxPwr = 0x%08X, Offset = 0x13DC, TxPwr = 0x%08X\n", + (UINT)ExtraPwrOverTxPwrCfg7, + (UINT)ExtraPwrOverTxPwrCfg9)); +} + +#ifdef SINGLE_SKU_V2 +#define SKU_PHYMODE_CCK_1M_2M 0 +#define SKU_PHYMODE_CCK_5M_11M 1 +#define SKU_PHYMODE_OFDM_6M_9M 2 +#define SKU_PHYMODE_OFDM_12M_18M 3 +#define SKU_PHYMODE_OFDM_24M_36M 4 +#define SKU_PHYMODE_OFDM_48M_54M 5 +#define SKU_PHYMODE_HT_MCS0_MCS1 6 +#define SKU_PHYMODE_HT_MCS2_MCS3 7 +#define SKU_PHYMODE_HT_MCS4_MCS5 8 +#define SKU_PHYMODE_HT_MCS6_MCS7 9 +#define SKU_PHYMODE_HT_MCS8_MCS9 10 +#define SKU_PHYMODE_HT_MCS10_MCS11 11 +#define SKU_PHYMODE_HT_MCS12_MCS13 12 +#define SKU_PHYMODE_HT_MCS14_MCS15 13 +#define SKU_PHYMODE_STBC_MCS0_MCS1 14 +#define SKU_PHYMODE_STBC_MCS2_MCS3 15 +#define SKU_PHYMODE_STBC_MCS4_MCS5 16 +#define SKU_PHYMODE_STBC_MCS6_MCS7 17 + +VOID RT6352_InitSkuRateDiffTable( + IN PRTMP_ADAPTER pAd ) +{ + USHORT i, value; + CHAR BasePwr, Pwr; + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 4, value); + BasePwr = (value >> 8) & 0xFF; + BasePwr = (BasePwr > 0x1F ) ? BasePwr - 0x40: BasePwr; + + for ( i = 0 ; i < 9; i++ ) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*2, value); + Pwr = value & 0xFF ; + Pwr = (Pwr > 0x1F ) ? Pwr - 0x40: Pwr; + pAd->SingleSkuRatePwrDiff[i *2] = Pwr - BasePwr; + Pwr = (value >> 8) & 0xFF; + Pwr = (Pwr > 0x1F ) ? Pwr - 0x40: Pwr; + pAd->SingleSkuRatePwrDiff[i *2 + 1] = Pwr - BasePwr; + } +} + +UCHAR RT6352_GetSkuChannelBasePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + CH_POWER *ch, *ch_temp; + UCHAR start_ch; + UCHAR base_pwr = pAd->DefaultTargetPwr; + UINT8 i, j; + CHAR tx_pwr1; + CHAR max_tx1_pwr; + UINT16 TargetPwr = 0; + UINT32 MacReg; + + if (IS_RT6352(pAd)) + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacReg); + max_tx1_pwr = (MacReg >> 16) & 0x3F; + + tx_pwr1 = (pAd->E2p_D0_Value & 0x3F); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: EEPROM 0xD0 = 0x%x\n", __FUNCTION__, tx_pwr1)); + + if ((tx_pwr1 == 0x0) || (tx_pwr1 > max_tx1_pwr) ) + { + tx_pwr1 = 0x1E; + DBGPRINT(RT_DEBUG_ERROR, ("%s: EEPROM 0xD0 Error! Use Default Target Power = 0x%x\n", __FUNCTION__, tx_pwr1)); + } + + base_pwr = tx_pwr1; + } + + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + + if ( channel >= start_ch ) + { + for ( j = 0; j < ch->num; j++ ) + { + if ( channel == ch->Channel[j] ) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ ) + { + if ( base_pwr > ch->PwrCCK[i] ) + base_pwr = ch->PwrCCK[i]; + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ ) + { + if ( base_pwr > ch->PwrOFDM[i] ) + base_pwr = ch->PwrOFDM[i]; + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + if ( base_pwr > ch->PwrHT20[i] ) + base_pwr = ch->PwrHT20[i]; + } + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + if ( ch->PwrHT40[i] == 0 ) + break; + + if ( base_pwr > ch->PwrHT40[i] ) + base_pwr = ch->PwrHT40[i]; + } + } + break; + } + } + } + } + + return base_pwr; + +} + +CHAR RT6352_AdjustChannelPwr( + IN RTMP_ADAPTER *pAd, + IN CHAR TotalDeltaPower, + OUT CHAR *PreDiff) +{ + CHAR target_power; + UCHAR sku_min_pwr = 0; + UINT32 mac_value; + USHORT e2p_data; + + //RT28xx_EEPROM_READ16(pAd, 0xD0, e2p_data); + target_power = (pAd->E2p_D0_Value & 0x3F); + sku_min_pwr = RT6352_GetSkuChannelBasePwr(pAd, pAd->CommonCfg.SkuChannel); + + /* Get delta power based on the percentage specified from UI */ + //target_power += TotalDeltaPower; + +#ifdef RTMP_INTERNAL_TX_ALC + /* TSSI mode */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + CHAR bw_delta = 0; + CHAR target_power_ori = 0; + target_power = (target_power > sku_min_pwr) ? sku_min_pwr : target_power; + + target_power_ori = target_power; + target_power += TotalDeltaPower; + + if (target_power < 0) + target_power = 0; + if(pAd->bSingleSkuDebug) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::channel_power =%d, TotalDeltaPower=%d, sku_min_pwr=%d\n", + __FUNCTION__, target_power, TotalDeltaPower, sku_min_pwr)); + } + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &mac_value); + if ((mac_value & 0x3f) != target_power) + { + mac_value &= 0xFFFFC0C0; + mac_value |= (target_power & 0x3F); + mac_value |= (target_power & 0x3F) << 8; + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, mac_value); + } + if(pAd->bSingleSkuDebug) + DBGPRINT(RT_DEBUG_TRACE, ("%s::mac 0x13B0 is 0x%08x\n", __FUNCTION__, mac_value)); + + target_power = target_power_ori; + } + else /* Manual/Temperature mode */ +#endif /* RTMP_INTERNAL_TX_ALC */ + { + INT32 diff = 0; + + if(pAd->bSingleSkuDebug) + DBGPRINT(RT_DEBUG_TRACE, ("target_power=%d, sku_min_pwr=%d\n", target_power, sku_min_pwr)); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &mac_value); + mac_value &= 0xFFFFFFC0; + + diff = sku_min_pwr - target_power; + + diff += TotalDeltaPower; + if (target_power > sku_min_pwr) + target_power = sku_min_pwr; + + if (diff > 31) + diff = 31; + else if(diff < -31) + diff = -31; + + mac_value |= (diff & 0x3F); +#ifdef RTMP_TEMPERATURE_COMPENSATION + if (pAd->bAutoTxAgcG) + { + *PreDiff = (CHAR)diff; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::diff is 0x%x\n", __FUNCTION__, *PreDiff)); + } + else +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + { + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, mac_value); + if(pAd->bSingleSkuDebug) + DBGPRINT(RT_DEBUG_TRACE, ("%s::mac 0x13B4 is 0x%08x\n", __FUNCTION__, mac_value)); + } + } + + if (target_power > 0) + return target_power; + else + return 0; +} + +VOID RT6352_AdjustPerRatePwr( + IN PRTMP_ADAPTER pAd, + IN CHAR channelpower) +{ + INT i, j; + INT32 channel_power = channelpower; + CHAR bbp_reg, bbp_r4; + INT32 mcs_digpwr_diff; + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC mcs_pwr_table = {0}; + + /* Get mcs_pwr_table from EEPROM 0xDEh ~ 0xEFh, unit 0.5 dBm */ + RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&mcs_pwr_table); + + /* Calculate mcs_digpwr_diff from MCS digital power diff table */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &bbp_reg); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbp_r4); + + if (bbp_reg == 0) /* BBP_R178 == 0 */ + { + if (bbp_r4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + mcs_digpwr_diff = 9831; /* 1.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + mcs_digpwr_diff = 3 * 8192; + } + } + else /* BBP_R178 != 0 */ + { + if (bbp_r4 & (1 << 5)) /* BBP_R4[5] == 1 */ + { + mcs_digpwr_diff = 18023; /* 2.2 x 8192 */ + } + else /* BBP_R4[5] == 0 */ + { + mcs_digpwr_diff = 819; /* 0.1 x 8192 */ + } + } + + if(pAd->bSingleSkuDebug) + DBGPRINT(RT_DEBUG_TRACE, ("%s::mcs_digpwr_diff is %d\n", __FUNCTION__, mcs_digpwr_diff)); + + for (i = 0; i < mcs_pwr_table.NumOfEntries; i++) + { + TX_POWER_CONTROL_OVER_MAC_ENTRY *per_rate_entry; + ULONG reg_val; + + per_rate_entry = &mcs_pwr_table.TxPwrCtrlOverMAC[i]; + reg_val = per_rate_entry->RegisterValue; + + if (reg_val != 0xFFFFFFFF) + { + for (j = 0; j < 8; j += 2) + { + CHAR diff = 0, mcs_pwr_value; + INT32 rate_pwr = 0, rate_pwr_ori = 0, sku_rate_pwr, pa_mode = 0; + + rate_pwr_ori = rate_pwr = (INT32)((reg_val >> j*4) & 0x000000FF); + rate_pwr = ((rate_pwr + channel_power) << 12); + + /* Append mcs_digpwr_diff and PA_MODE to the corresponding rate power */ + switch (0x1314 + (i * 4)) + { + case 0x1314: + rate_pwr += ((j == 0) || (j == 2)) ? mcs_digpwr_diff : 0; + pa_mode = ((j < 4)) ? + pAd->rf_pa_mode_over_cck[j] : pAd->rf_pa_mode_over_ofdm[j - 4]; + break; + + case 0x1318: + pa_mode = ((j < 4)) ? + pAd->rf_pa_mode_over_ofdm[j + 4] : pAd->rf_pa_mode_over_ht[j - 4]; + break; + + case 0x131C: + pa_mode = pAd->rf_pa_mode_over_ht[j + 4]; + break; + + case 0x1320: + pa_mode = ((j < 4)) ? pAd->rf_pa_mode_over_ht[j + 12] : 0; + break; + + case 0x1324: + break; + + default: + /* Do nothing */ + DBGPRINT(RT_DEBUG_ERROR, ("%s::unknown register = 0x%x\n", __FUNCTION__, (0x1314 + (i * 4)))); + break; + } + + rate_pwr = (rate_pwr + pa_mode_table[pa_mode]) >> 12; + + sku_rate_pwr = (INT32)GetSkuPerRatePwr(pAd, (i * 4) + (j / 2), pAd->CommonCfg.SkuChannel, pAd->CommonCfg.BBPCurrentBW, pa_mode_table[pa_mode]); + /* Adjust the per rate power if enabling Single-SKU */ + diff = (CHAR)(sku_rate_pwr - rate_pwr); + + mcs_pwr_value = (CHAR)rate_pwr_ori + diff; + if(pAd->bSingleSkuDebug) + { + DBGPRINT(RT_DEBUG_TRACE, + ("[%d, %d] channel_power(%d) + mcs_pwr_table(%d) + pa_mode(%d, %d) = rate_pwr(%d)\n", + i, j, channel_power, mcs_pwr_value, pa_mode, pa_mode_table[pa_mode], rate_pwr)); + + DBGPRINT(RT_DEBUG_TRACE, + ("[%d, %d] sku_rate_pwr(%d) - rate_pwr(%d) = diff(%d). rate_pwr_ori(%d)\n", + i, j, sku_rate_pwr, rate_pwr, diff, rate_pwr_ori)); + } + /* 8-bit representation ==> 6-bit representation (2's complement) */ + if ((mcs_pwr_value & 0x80) == 0x00) /* Positive number */ + mcs_pwr_value &= 0x3F; + else /* 0x80: Negative number */ + mcs_pwr_value = (mcs_pwr_value & 0x1F) | 0x20; + + /* Write mcs_pwr_table to the corresponding MAC */ + if ((j % 2) == 0) + per_rate_entry->RegisterValue = (per_rate_entry->RegisterValue & ~(0x000000FF << (j * 4))) | (mcs_pwr_value << (j * 4)); + } + + RTMP_IO_WRITE32(pAd, per_rate_entry->MACRegisterOffset, per_rate_entry->RegisterValue); + + } + } + + /* Extra set MAC registers to compensate Tx power if any */ + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); +} + +UCHAR GetSkuPerRatePwr( + IN PRTMP_ADAPTER pAd, + IN CHAR phymode, + IN UCHAR channel, + IN UCHAR bw, + IN INT32 paValue) +{ + INT i = 0; + CH_POWER *ch, *ch_temp; + UCHAR start_ch, end_ch; + UCHAR rate_pwr, rate_pwr1; + CHAR tx_pwr1; + CHAR max_tx1_pwr; + UINT16 TargetPwr = 0; + UINT32 MacReg; + INT32 pwr_diff = 0; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacReg); + max_tx1_pwr = (MacReg >> 16) & 0x3F; + + tx_pwr1 = (pAd->E2p_D0_Value & 0x3F); + + if(pAd->bSingleSkuDebug) + DBGPRINT(RT_DEBUG_TRACE, ("%s: EEPROM 0xD0 = 0x%x\n", __FUNCTION__, tx_pwr1)); + + if ((tx_pwr1 == 0x0) || (tx_pwr1 > max_tx1_pwr) ) + { + tx_pwr1 = 0x1E; + DBGPRINT(RT_DEBUG_ERROR, ("%s: EEPROM 0xD0 Error! Use Default Target Power = 0x%x\n", __FUNCTION__, tx_pwr1)); + } + + rate_pwr1 = rate_pwr = tx_pwr1; + + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + end_ch = start_ch + ch->num -1; + + if ( (channel >= start_ch) && ( channel <= end_ch ) ) + { + switch ( phymode ) + { + case SKU_PHYMODE_CCK_1M_2M: + rate_pwr = ch->PwrCCK[0]; + break; + case SKU_PHYMODE_CCK_5M_11M: + rate_pwr = ch->PwrCCK[2]; + break; + case SKU_PHYMODE_OFDM_6M_9M: + rate_pwr = ch->PwrOFDM[0]; + break; + case SKU_PHYMODE_OFDM_12M_18M: + rate_pwr = ch->PwrOFDM[2]; + break; + case SKU_PHYMODE_OFDM_24M_36M: + rate_pwr = ch->PwrOFDM[4]; + break; + case SKU_PHYMODE_OFDM_48M_54M: + rate_pwr = ch->PwrOFDM[6]; + break; + case SKU_PHYMODE_HT_MCS0_MCS1: + case SKU_PHYMODE_STBC_MCS0_MCS1: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[0]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[0]; + break; + case SKU_PHYMODE_HT_MCS2_MCS3: + case SKU_PHYMODE_STBC_MCS2_MCS3: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[2]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[2]; + break; + case SKU_PHYMODE_HT_MCS4_MCS5: + case SKU_PHYMODE_STBC_MCS4_MCS5: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[4]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[4]; + break; + case SKU_PHYMODE_HT_MCS6_MCS7: + case SKU_PHYMODE_STBC_MCS6_MCS7: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[6]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[6]; + break; + case SKU_PHYMODE_HT_MCS8_MCS9: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[8]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[8]; + break; + case SKU_PHYMODE_HT_MCS10_MCS11: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[10]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[10]; + break; + case SKU_PHYMODE_HT_MCS12_MCS13: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[12]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[12]; + break; + case SKU_PHYMODE_HT_MCS14_MCS15: + if ( bw == BW_20 ) + rate_pwr = ch->PwrHT20[14]; + else if ( bw == BW_40 ) + rate_pwr = ch->PwrHT40[14]; + break; + default: + break; + } + + break; + } + } + + pwr_diff = paValue + (pAd->SingleSkuRatePwrDiff[phymode] << 12) + 2048; + pwr_diff = pwr_diff >> 12; + + if(pAd->bSingleSkuDebug) + DBGPRINT(RT_DEBUG_TRACE, ("%s: pwr_diff = 0x%x, rate_pwr = 0x%x, rate_pwr1 = 0x%x !!!\n", + __FUNCTION__, pwr_diff, rate_pwr, rate_pwr1)); + return rate_pwr; + +} +#endif /* SINGLE_SKU_V2 */ + + +#ifdef RTMP_TEMPERATURE_COMPENSATION +static BOOLEAN RT6352_AsicGetTssiReport( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bResetTssiInfo, + OUT PINT32 pTssiReport) +{ + INT wait; + UINT8 bbpval; + CHAR BBPR49; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + + if (bResetTssiInfo == TRUE) + { + /* set BBP R47[4]=1 to enable TSSI for next reading */ + //RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + { + bbpval |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + } + + for (wait=0; wait < 4; wait++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + break; + RtmpusecDelay(500); + } + } + + if ((bbpval & 0x10) != 0) + { + /* Get temperature infomation failed */ + return FALSE; + } + else + { + bbpval &= 0xf8; + bbpval |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + *pTssiReport = (INT32) BBPR49; + + DBGPRINT(RT_DEBUG_TRACE, ("TSSI report from BBP_R49=0x%x\n", *pTssiReport)); + } + return TRUE; +} + + +/* MaxBoundaryLevel MUST not be greater than the array size of TssiBoundarys */ +static BOOLEAN RT6352_GetTemperatureCompensationLevel( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bAutoTxAgc, + IN CHAR TssiRef, /* e2p[75h]: the zero reference */ + IN PCHAR pTssiMinusBoundary, + IN PCHAR pTssiPlusBoundary, + IN UINT8 MaxBoundaryLevel, + IN UINT8 TxAgcStep, + IN INT32 CurrTemperature, + OUT PCHAR pCompensationLevel) +{ + INT idx; + + /* Sanity Check */ + if (pTssiMinusBoundary == NULL || + pTssiPlusBoundary == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): pTssiBoundary is NULL!\n", + __FUNCTION__)); + return FALSE; + } + + ASSERT(TssiRef == pAd->TssiCalibratedOffset); + + if (bAutoTxAgc) + { + if (CurrTemperature < pTssiMinusBoundary[1]) + { + /* Reading is larger than the reference value check + for how large we need to decrease the Tx power */ + for (idx = 1; idx < MaxBoundaryLevel; idx++) + { + if (CurrTemperature >= pTssiMinusBoundary[idx]) + break; /* level range found */ + } + + /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */ + *pCompensationLevel = -(TxAgcStep * (idx-1)); + DBGPRINT(RT_DEBUG_TRACE, + ("-- Tx Power, CurrTemperature=%x, TssiRef=%x, TxAgcStep=%x, step = -%d, CompensationLevel = %d\n", + CurrTemperature, TssiRef, TxAgcStep, idx-1, *pCompensationLevel)); + } + else if (CurrTemperature > pTssiPlusBoundary[1]) + { + /* Reading is smaller than the reference value check + for how large we need to increase the Tx power */ + for (idx = 1; idx < MaxBoundaryLevel; idx++) + { + if (CurrTemperature <= pTssiPlusBoundary[idx]) + break; /* level range found */ + } + + /* The index is the step we should increase, idx = 0 means there is nothing to compensate */ + *pCompensationLevel = TxAgcStep * (idx-1); + DBGPRINT(RT_DEBUG_TRACE, + ("++ Tx Power, CurrTemperature=%x, TssiRef=%x, TxAgcStep=%x, step = +%d, , CompensationLevel = %d\n", + CurrTemperature, TssiRef, TxAgcStep, idx-1, *pCompensationLevel)); + } + else + { + *pCompensationLevel = 0; + DBGPRINT(RT_DEBUG_TRACE, + (" Tx Power, CurrTemperature=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + CurrTemperature, TssiRef, TxAgcStep, 0)); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): bAutoTxAgc = %s\n", + __FUNCTION__, + (bAutoTxAgc) == TRUE ? "TRUE" : "FALSE")); + return FALSE; + } + + return TRUE; +} + + +BOOLEAN RT6352_TemperatureCompensation( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bResetTssiInfo) +{ + BOOLEAN bCanDoRegAdjustment = FALSE; + + if (pAd->bCalibrationDone) + { + if (RT6352_AsicGetTssiReport(pAd, + bResetTssiInfo, + &pAd->CurrTemperature) == TRUE) + { + if (pAd->bAutoTxAgcG) + { + if (RT6352_GetTemperatureCompensationLevel( + pAd, + pAd->bAutoTxAgcG, + pAd->TssiRefG, + &pAd->TssiMinusBoundaryG[0], + &pAd->TssiPlusBoundaryG[0], + 8, /* to do: make a definition */ + 2/* pAd->TxAgcStepG; */, /* the unit of MAC 0x13B4 is 0.5 dB */ + pAd->CurrTemperature, + &pAd->TxAgcCompensateG) == TRUE) + { + UINT32 MacValue; + CHAR delta_pwr = 0; + + /* adjust compensation value by MP temperature readings(i.e., e2p[77h]) */ + delta_pwr = pAd->TxAgcCompensateG - pAd->mp_delta_pwr; + delta_pwr += pAd->DeltaPwrBeforeTempComp; + /* 8-bit representation ==> 6-bit representation (2's complement) */ + delta_pwr = (delta_pwr & 0x80) ? \ + ((delta_pwr & 0x1f) | 0x20) : (delta_pwr & 0x3f); + /* write compensation value into TX_ALG_CFG_1, + delta_pwr (unit: 0.5dB) will be compensated by TX_ALG_CFG_1 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + MacValue = (MacValue & (~0x3f)) | delta_pwr; + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + + bCanDoRegAdjustment = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s - delta_pwr = %d, TssiCalibratedOffset = %d," + " TssiMpOffset = %d, Mac 0x13B4 = 0x%08x\n", + __FUNCTION__, + (delta_pwr & 0x20) ? (delta_pwr | 0x0c) : (delta_pwr), + pAd->TssiCalibratedOffset, + pAd->mp_delta_pwr, + MacValue)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Failed to get a compensation level!\n", + __FUNCTION__)); + return FALSE; + } + } + else + bCanDoRegAdjustment = TRUE; + } + else + { + /* Failed to get current temperature */ + pAd->CommonCfg.bEnTemperatureTrack = TRUE; + return FALSE; + } + } + +#ifdef RTMP_TEMPERATURE_CALIBRATION + if (bCanDoRegAdjustment == TRUE) + RT6352_TemperatureCalibration(pAd); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + + return TRUE; +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + +VOID RT6352_AsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + //INT i, j; + //CHAR Value; + CHAR Rssi = -127; + CHAR DeltaPwr = 0; + CHAR DeltaPowerByBbpR1 = 0; + CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0}; + + +#ifdef CONFIG_STA_SUPPORT + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) + return; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || +#ifdef RTMP_MAC_PCI + (pAd->bPCIclkOff == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || +#endif /* RTMP_MAC_PCI */ + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(INFRA_ON(pAd)) + { + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Get Tx rate offset table which from EEPROM 0xDEh ~ 0xEFh */ + RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&CfgOfTxPwrCtrlOverMAC); + + /* Power will be compensated each 4 sec. */ + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { +#ifdef SINGLE_SKU_V2 + CHAR PreDiff; +#endif /* SINGLE_SKU_V2 */ + + /* Get delta power based on the percentage specified from UI */ + AsicPercentageDeltaPower(pAd, Rssi, &DeltaPwr,&DeltaPowerByBbpR1); + + /* The transmit power controlled by the BBP */ + TotalDeltaPower += DeltaPowerByBbpR1; + + /* The transmit power controlled by the MAC */ + TotalDeltaPower += DeltaPwr; + TotalDeltaPower = (TotalDeltaPower * 2); // because unit = 0.5 dbm + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + TotalDeltaPower += pAd->BW_Power_Delta; + +#ifdef SINGLE_SKU_V2 + if ((pAd->bCalibrationDone) && (pAd->bOpenFileSuccess)) + { + CHAR channel_power = 0; + + channel_power = RT6352_AdjustChannelPwr(pAd, TotalDeltaPower, &PreDiff); + + RT6352_AdjustPerRatePwr(pAd, channel_power); + } +#endif /* SINGLE_SKU_V2 */ + +#ifdef RTMP_INTERNAL_TX_ALC + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + if (pAd->bCalibrationDone) + { + if (RT635xTriggerTssiCompensation(pAd, TotalDeltaPower)) + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + RT6352_TemperatureCalibration(pAd); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } + } + + return; + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + if (pAd->bAutoTxAgcG) + { + pAd->DeltaPwrBeforeTempComp = TotalDeltaPower; +#ifdef SINGLE_SKU_V2 + if (pAd->bOpenFileSuccess) + pAd->DeltaPwrBeforeTempComp = PreDiff; +#endif /* SINGLE_SKU_V2 */ + if (pAd->bCalibrationDone) + RT6352_TemperatureCompensation(pAd, TRUE); + + return; + } + else +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + if (pAd->bCalibrationDone) + { + UINT8 bbpval; + CHAR BBPR49; + int wait; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + { + bbpval |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + } + + for (wait = 0; wait < 2; wait++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + break; + RtmpusecDelay(1000); + } + + if ((bbpval & 0x10) != 0) + { + pAd->CommonCfg.bEnTemperatureTrack = TRUE; + } + else + { + bbpval &= 0xf8; + bbpval |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + pAd->CurrTemperature = (INT32) BBPR49; + + DBGPRINT(RT_DEBUG_TRACE, ("Current Temperature from BBP_R49=0x%x\n", pAd->CurrTemperature)); + RT6352_TemperatureCalibration(pAd); + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + } + } +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } + +#ifdef SINGLE_SKU_V2 + if (pAd->bOpenFileSuccess) + return; +#endif /* SINGLE_SKU_V2 */ + + { + INT32 Diff; + UINT32 MacValue; + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue &= 0xffffffc0; + + Diff = TotalDeltaPower; + if (Diff > 31) + Diff = 31; + else if(Diff < -31) + Diff = -31; + + MacValue |= (Diff & 0x3F); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + + DBGPRINT(RT_DEBUG_TRACE, ("TotalDeltaPower=%d, Mac 0x13B4 is 0x%08x\n", TotalDeltaPower, MacValue)); + } + + /* Extra set MAC registers to compensate Tx power if any */ + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); + } + +} + +#ifdef MICROWAVE_OVEN_SUPPORT +static VOID RT6352_AsicMeasureFalseCCA( + IN PRTMP_ADAPTER pAd +) +{ + UINT32 reg; + + /* Set to high gain LAN */ + //printk("Stored_BBP_R65=%x @%s \n", pAd->CommonCfg.MO_Cfg.Stored_BBP_R65, __FUNCTION__); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, pAd->CommonCfg.MO_Cfg.Stored_BBP_R65); + + /* clear false cca counter */ + RTMP_IO_READ32(pAd, RX_STA_CNT1, ®); + + /* reset false CCA counter */ + pAd->CommonCfg.MO_Cfg.nFalseCCACnt = 0; +} + +static VOID RT6352_AsicMitigateMicrowave( + IN PRTMP_ADAPTER pAd) +{ + UINT8 RegValue; + + DBGPRINT(RT_DEBUG_OFF, ("Detect Microwave...\n")); + + /* set middle gain */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &RegValue); + RegValue |= 0x08; + RegValue &= 0xfd; /*BBP_R65[3:2] from 3 into 2 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, 0x28); +} +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef RTMP_TEMPERATURE_CALIBRATION +VOID RT6352_Temperature_Init ( + IN PRTMP_ADAPTER pAd) +{ + int wait; + UINT8 bbpval; + CHAR BBPR49; + UINT32 orig_RF_CONTROL0 = 0; // 0x0518 + UINT32 orig_RF_BYPASS0 = 0; // 0x051c + + RTMP_IO_READ32(pAd, RF_CONTROL0, &orig_RF_CONTROL0); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &orig_RF_BYPASS0); + + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + /* MAC Bypass */ + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x0004); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x3366); + + if (pAd->bRef25CVaild == FALSE) + { + UINT8 RfB0R35Value; + UINT8 RfB5R04Value,RfB5R17Value,RfB5R18Value; + UINT8 RfB5R19Value, RfB5R20Value; + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R35, &RfB0R35Value); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &RfB5R04Value); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &RfB5R17Value); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &RfB5R18Value); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &RfB5R19Value); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &RfB5R20Value); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x0); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0x83); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x20); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + bbpval |= 0x50; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x40); + + for (wait=0; wait<200; wait++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + break; + RtmpusecDelay(2000); + } + ASSERT(wait < 200); + + bbpval &= 0xf8; + bbpval |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + DBGPRINT(RT_DEBUG_ERROR, ("%s : BBPR49 = 0x%x\n", __FUNCTION__, BBPR49)); + pAd->TemperatureRef25C = BBPR49 - 0x0A; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, RfB0R35Value); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, RfB5R04Value); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, RfB5R17Value); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, RfB5R18Value); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, RfB5R19Value); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, RfB5R20Value); + pAd->bRef25CVaild = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("%s : TemperatureRef25C = 0x%x\n", __FUNCTION__, pAd->TemperatureRef25C)); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + { + bbpval |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x31); + + for (wait=0; wait<200; wait++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if (!(bbpval & 0x10)) + break; + RtmpusecDelay(1000); + } + ASSERT(wait < 200); + + bbpval &= 0xf8; + bbpval |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + pAd->CurrTemperature = (INT32)BBPR49; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x0); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbpval); + bbpval |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + bbpval &= 0xfe; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + + // recover + if (wait >= 200) { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + bbpval &= 0xef; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + } + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0 , orig_RF_CONTROL0); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , orig_RF_BYPASS0); + + pAd->bLowTemperatureTrigger = FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("Current Temperature from BBP_R49=0x%x\n", pAd->CurrTemperature)); +} + +VOID RT6352_TemperatureCalibration( + IN PRTMP_ADAPTER pAd) +{ + INT32 CurrentTemper = pAd->CurrTemperature; + + CurrentTemper = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19; // 319 * 10 + + // HT -> LT + //B4/B6.R04=0x00->0x06 + //B4/B6.R10=0x51->0x41 + if (CurrentTemper < -50) // (20 - 25) * 10 = -50 + { + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R04, 0x06); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R04, 0x06); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R10, 0x41); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R10, 0x41); + pAd->bLowTemperatureTrigger = TRUE; + DBGPRINT(RT_DEBUG_INFO, ("%s:: CurrentTemper < 20 \n", __FUNCTION__)); + } + else + { + if (pAd->bLowTemperatureTrigger) + { + if ( CurrentTemper > 50) + { + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R04, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R04, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R10, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R10, 0x51); + pAd->bLowTemperatureTrigger = FALSE; + DBGPRINT(RT_DEBUG_INFO, ("%s::CurrentTemper > 30\n", __FUNCTION__)); + } + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R04, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R04, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R10, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R10, 0x51); + DBGPRINT(RT_DEBUG_INFO, ("%s::CurrentTemper > 20\n", __FUNCTION__)); + } + } +} +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +/* + This procedure adjusts the boundary table by pAd->TssiCalibratedOffset. + + pAd->TssiCalibratedOffset: + production line temperature(e2p[77h]) - reference temperature(e2p[D1h]) +*/ +VOID RT6352_TssiTableAdjust( + IN PRTMP_ADAPTER pAd) +{ + INT idx; + CHAR upper_bound = 127, lower_bound = -128; + + DBGPRINT(RT_DEBUG_OFF,("%s: upper_bound = 0x%02X decimal: %d\n", + __FUNCTION__, upper_bound, upper_bound)); + DBGPRINT(RT_DEBUG_OFF,("%s: lower_bound = 0x%02X decimal: %d\n", + __FUNCTION__, lower_bound, lower_bound)); + + DBGPRINT(RT_DEBUG_OFF,("*** %s: G Tssi[-7 .. +7] = %d %d %d %d %d %d %d\n - %d - %d %d %d %d %d %d %d, offset=%d, tuning=%d\n", + __FUNCTION__, + pAd->TssiMinusBoundaryG[7], pAd->TssiMinusBoundaryG[6], pAd->TssiMinusBoundaryG[5], + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TssiPlusBoundaryG[5], pAd->TssiPlusBoundaryG[6], pAd->TssiPlusBoundaryG[7], + pAd->TssiCalibratedOffset, pAd->bAutoTxAgcG)); + + for (idx = 0; idx < 8; idx++ ) + { + if ((lower_bound - pAd->TssiMinusBoundaryG[idx]) <= pAd->TssiCalibratedOffset) + { + pAd->TssiMinusBoundaryG[idx] += pAd->TssiCalibratedOffset; + } + else + { + pAd->TssiMinusBoundaryG[idx] = lower_bound; + } + + if ((upper_bound - pAd->TssiPlusBoundaryG[idx]) >= pAd->TssiCalibratedOffset) + { + pAd->TssiPlusBoundaryG[idx] += pAd->TssiCalibratedOffset; + } + else + { + pAd->TssiPlusBoundaryG[idx] = upper_bound; + } + + ASSERT(pAd->TssiMinusBoundaryG[idx] >= lower_bound); + ASSERT(pAd->TssiPlusBoundaryG[idx] <= upper_bound); + } + + pAd->TssiRefG = pAd->TssiMinusBoundaryG[0]; + + DBGPRINT(RT_DEBUG_OFF,("%s: G Tssi[-7 .. +7] = %d %d %d %d %d %d %d - %d - %d %d %d %d %d %d %d, offset=%d, tuning=%d\n", + __FUNCTION__, + pAd->TssiMinusBoundaryG[7], pAd->TssiMinusBoundaryG[6], pAd->TssiMinusBoundaryG[5], + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TssiPlusBoundaryG[5], pAd->TssiPlusBoundaryG[6], pAd->TssiPlusBoundaryG[7], + pAd->TssiCalibratedOffset, pAd->bAutoTxAgcG)); + + return; +} + + +VOID RT6352_TssiMpAdjust( + IN PRTMP_ADAPTER pAd) +{ + PCHAR pTssiMinusBoundary, pTssiPlusBoundary; + EEPROM_TX_PWR_STRUC e2p_value; + CHAR mp_temperature, idx, TxAgcMpOffset = 0; + + RT28xx_EEPROM_READ16(pAd, (EEPROM_G_TSSI_BOUND5), e2p_value.word); + mp_temperature = e2p_value.field.Byte1; + + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + + if (mp_temperature < pTssiMinusBoundary[1]) + { + /* mp_temperature is larger than the reference value */ + /* check for how large we need to adjust the Tx power */ + for (idx = 1; idx < 8; idx++) + { + if (mp_temperature >= pTssiMinusBoundary[idx]) /* the range has been found */ + break; + } + + /* The index is the step we should decrease, idx = 0 means there is nothing to adjust */ + TxAgcMpOffset = -(2 * (idx-1)); + pAd->mp_delta_pwr = (TxAgcMpOffset); + DBGPRINT(RT_DEBUG_OFF, ("mp_temperature=0x%02x, step = -%d\n", + mp_temperature, idx-1)); + } + else if (mp_temperature > pTssiPlusBoundary[1]) + { + /* mp_temperature is smaller than the reference value */ + /* check for how large we need to adjust the Tx power */ + for (idx = 1; idx < 8; idx++) + { + if (mp_temperature <= pTssiPlusBoundary[idx]) /* the range has been found */ + break; + } + + /* The index is the step we should increase, idx = 0 means there is nothing to adjust */ + TxAgcMpOffset = 2 * (idx-1); + pAd->mp_delta_pwr = (TxAgcMpOffset); + DBGPRINT(RT_DEBUG_OFF, ("mp_temperature=0x%02x, step = +%d\n", + mp_temperature, idx-1)); + } + else + { + pAd->mp_delta_pwr = 0; + DBGPRINT(RT_DEBUG_OFF, ("mp_temperature=0x%02x, step = +%d\n", + mp_temperature, 0)); + } + + return; +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#if defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) +VOID RT6352_Init_ExtPA_ExtLNA( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN ReInit) +{ + ULONG GpioMode; + + /* Check the gpio setting first */ + RTMP_SYS_IO_READ32(0xb0000060, &GpioMode); + if ((GpioMode & 0x100000) == 0x100000) + { + GpioMode &= (~0x100000); + RTMP_SYS_IO_WRITE32(0xb0000060, GpioMode); + + DBGPRINT(RT_DEBUG_ERROR,("Change as Normal Mode(0x%x)\n", GpioMode)); + RTMP_SYS_IO_READ32(0xb0000060, &GpioMode); + DBGPRINT(RT_DEBUG_ERROR,("After Change, now GPIO_MODE value is 0x%x\n", GpioMode)); + } + +#ifdef RT6352_EP_SUPPORT + if (pAd->bExtPA) + { + UINT32 MacValue; + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Enable Ext-PA. init MAC \n", __FUNCTION__)); + RTMP_IO_READ32(pAd, RF_CONTROL3, &MacValue); + MacValue |= 0x00000101; + RTMP_IO_WRITE32(pAd, RF_CONTROL3, MacValue); + + RTMP_IO_READ32(pAd, RF_BYPASS3, &MacValue); + MacValue |= 0x00000101; + RTMP_IO_WRITE32(pAd, RF_BYPASS3, MacValue); + } +#endif /* RT6352_EP_SUPPORT */ + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Enable Ext-LNA. \n", __FUNCTION__)); + + /* TFBGA Ext-LNA */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R14, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R14, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R17, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R17, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R18, 0x42); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R18, 0x42); + } +#endif /* RT6352_EL_SUPPORT */ + +#ifdef RT6352_EP_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->bExtPA)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Enable Ext-PA. \n", __FUNCTION__)); + + /* TFBGA Ext-PA */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R43, 0x73); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R43, 0x73); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R44, 0x73); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R44, 0x73); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R45, 0x73); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R45, 0x73); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R46, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R46, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0xC8); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0xC8); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R48, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R48, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R49, 0x05); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R49, 0x05); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R55, 0xC8); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R55, 0xC8); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R56, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R56, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R57, 0x05); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R57, 0x05); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R58, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R58, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R59, 0xC8); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R59, 0xC8); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R60, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R60, 0xA4); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R61, 0x05); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R61, 0x05); + } +#endif /* RT6352_EP_SUPPORT */ + +#ifdef RT6352_EP_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->bExtPA)) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R05, 0x00); + + } +#endif /* RT6352_EP_SUPPORT */ + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Init Ext-LNA BBP. \n", __FUNCTION__)); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x68); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R76, 0x4C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x1C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xB6); + } +#endif /* RT6352_EL_SUPPORT */ + +#ifdef RT6352_EP_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->bExtPA)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Init Ext-PA MAC. \n", __FUNCTION__)); + + RTMP_IO_WRITE32(pAd, TX0_RF_GAIN_CORRECT, 0x36303636); /* WH, 2012-12-28 */ + RTMP_IO_WRITE32(pAd, TX0_RF_GAIN_ATTEN, 0x6C6C6B6C); /* WH, 2012-12-28 */ + RTMP_IO_WRITE32(pAd, TX1_RF_GAIN_ATTEN, 0x6C6C6B6C); /* WH, 2012-12-28 */ + } +#endif /* RT6352_EP_SUPPORT */ + + return; +} + +VOID RT6352_Restore_RF_BBP( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RT6352_EP_SUPPORT + if (pAd->bExtPA) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Restore Ext-PA. init MAC \n", __FUNCTION__)); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS3, 0x0); + } +#endif /* RT6352_EP_SUPPORT */ + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Restore Ext-LNA. \n", __FUNCTION__)); + + /* TFBGA Ext-LNA */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R14, 0x16); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R14, 0x16); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R17, 0x23); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R17, 0x23); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R18, 0x02); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R18, 0x02); + } +#endif /* RT6352_EL_SUPPORT */ + +#ifdef RT6352_EP_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->bExtPA)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Restore Ext-PA. \n", __FUNCTION__)); + + /* TFBGA Ext-PA */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R43, 0xD3); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R43, 0xD3); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R44, 0xB3); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R44, 0xB3); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R45, 0xD5); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R45, 0xD5); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R46, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R46, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x6C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0x6C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R48, 0xFC); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R48, 0xFC); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R49, 0x1F); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R49, 0x1F); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R54, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R55, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R55, 0x66); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R56, 0xFF); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R56, 0xFF); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R57, 0x1C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R57, 0x1C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R58, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R58, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R59, 0x6B); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R59, 0x6B); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R60, 0xF7); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R60, 0xF7); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R61, 0x09); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R61, 0x09); + } +#endif /* RT6352_EP_SUPPORT */ + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Restore Ext-LNA BBP. \n", __FUNCTION__)); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x60); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R76, 0x44); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x1C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xB6); + + if(pAd->CommonCfg.BBPCurrentBW == BW_20) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R141); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x1A); + } + } +#endif /* RT6352_EL_SUPPORT */ + +#ifdef RT6352_EP_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->bExtPA)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s: Restore Ext-PA MAC. \n", __FUNCTION__)); + + RTMP_IO_WRITE32(pAd, TX0_RF_GAIN_CORRECT, 0x3630363A); /* WH, 2012-12-28 */ + RTMP_IO_WRITE32(pAd, TX0_RF_GAIN_ATTEN, 0x6C6C666C); /* WH, 2012-12-28 */ + RTMP_IO_WRITE32(pAd, TX1_RF_GAIN_ATTEN, 0x6C6C666C); /* WH, 2012-12-28 */ + } +#endif /* RT6352_EP_SUPPORT */ +} + +VOID RT6352_ReCalibration( + IN PRTMP_ADAPTER pAd) +{ + UINT32 MTxCycle = 0; + UINT32 MacValue = 0, MacSysCtrl = 0; + UCHAR BBPR30Value, RFB0_R39, RFB0_R42, RFValue; + + DBGPRINT(RT_DEBUG_TRACE, (" Do ReCalibration !!!\n")); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacSysCtrl); + + /* MAC Tx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + MacValue &= (~0x04); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue); + if (MacValue & 0x1) + RtmpusecDelay(50); + else + break; + } + + if (MTxCycle >= 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Count MAC TX idle to MAX !!!\n")); + } + + /* MAC Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + MacValue &= (~0x08); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue); + if (MacValue & 0x2) + RtmpusecDelay(50); + else + break; + } + + if (MTxCycle >= 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Count MAC RX idle to MAX !!!\n")); + } + + /* Backup ADC clcok selection */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R30, &BBPR30Value); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R39, &RFB0_R39); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFB0_R42); + + /* change to Shielding clock */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R30, 0x1F); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0x5B); + + RT6352_Restore_RF_BBP(pAd); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R05, 0x40); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R04, 0x0C); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R04, &RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en*/ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R04, RFValue); + RtmpOsMsDelay(2); + + /* Do LOFT and IQ Calibration */ + LOFT_IQ_Calibration(pAd); + + /* Do RXIQ Calibration */ + RXIQ_Calibration(pAd); + + RT6352_Init_ExtPA_ExtLNA(pAd, TRUE); + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + if(pAd->CommonCfg.BBPCurrentBW == BW_20) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R141); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x15); + } + } +#endif /* RT6352_EL_SUPPORT */ + + /* restore ADC clcok selection */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R30, BBPR30Value); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, RFB0_R39); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFB0_R42); + + //RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + //MacValue |= 0xC; + //RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacSysCtrl); + + return; +} +#endif /* defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) */ + +#ifdef DYNAMIC_VGA_SUPPORT +void RT6352_UpdateRssiForChannelModel(RTMP_ADAPTER * pAd) +{ + INT32 rx0_rssi, rx1_rssi; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + rx0_rssi = (CHAR)(pAd->StaCfg.RssiSample.LastRssi0); + rx1_rssi = (CHAR)(pAd->StaCfg.RssiSample.LastRssi1); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + rx0_rssi = (CHAR)(pAd->ApCfg.RssiSample.LastRssi0); + rx1_rssi = (CHAR)(pAd->ApCfg.RssiSample.LastRssi1); + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("%s:: rx0_rssi(%d), rx1_rssi(%d)\n", + __FUNCTION__, rx0_rssi, rx1_rssi)); + + /* + RSSI_DUT(n) = RSSI_DUT(n-1)*15/16 + RSSI_R2320_100ms_sample*1/16 + */ + pAd->chipCap.avg_rssi_0 = ((pAd->chipCap.avg_rssi_0) * 15)/16 + (rx0_rssi << 8)/16; + pAd->chipCap.avg_rssi_1 = ((pAd->chipCap.avg_rssi_1) * 15)/16 + (rx1_rssi << 8)/16; + + if (pAd->MacTab.Size == 0) + pAd->chipCap.avg_rssi_all = -75; + else + pAd->chipCap.avg_rssi_all = (pAd->chipCap.avg_rssi_0 + pAd->chipCap.avg_rssi_1)/512; + + DBGPRINT(RT_DEBUG_INFO, ("%s:: update rssi all(%d)\n", + __FUNCTION__, pAd->chipCap.avg_rssi_all)); +} + +static VOID RT6352_AsicDynamicVgaGainControl( + IN PRTMP_ADAPTER pAd) +{ + if ((pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable) && + (pAd->chipCap.dynamic_vga_support) && + (pAd->bCalibrationDone) + ) + { + UCHAR BbpReg = 0; + UCHAR VgaGainLowerBound = 0x10; + + + if (((pAd->chipCap.avg_rssi_all <= -76) && (pAd->CommonCfg.BBPCurrentBW == BW_80)) + || ((pAd->chipCap.avg_rssi_all <= -79) && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + || ((pAd->chipCap.avg_rssi_all <= -82) && (pAd->CommonCfg.BBPCurrentBW == BW_20))) + { + DBGPRINT(RT_DEBUG_INFO,("pAd->chipCap.avg_rssi_all = %d , no dync vga\n", pAd->chipCap.avg_rssi_all)); + return; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &BbpReg); + + DBGPRINT(RT_DEBUG_INFO, + ("RT6352 one second False CCA=%d, fixed R66 at 0x%x\n", pAd->RalinkCounters.OneSecFalseCCACnt, BbpReg)); + + if (pAd->RalinkCounters.OneSecFalseCCACnt > pAd->CommonCfg.lna_vga_ctl.nFalseCCATh) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0xAD); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x28); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0xB1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x20); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x8D); + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { +#ifdef RT6352_EL_SUPPORT + if (pAd->NicConfig2.field.ExternalLNAForG) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x15); + else +#endif /* RT6352_EL_SUPPORT */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x1A); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x10); + } + + if (BbpReg < (pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 + VgaGainLowerBound)) + { + BbpReg += 4; + bbp_set_agc(pAd, BbpReg, RX_CHAIN_ALL); + } + else if (BbpReg == (pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 + VgaGainLowerBound)) + { + if (pAd->RalinkCounters.OneSecFalseCCACnt > 1500) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x3D); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9D); + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x40); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x2F); + } + } + } + else if (pAd->RalinkCounters.OneSecFalseCCACnt < pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x27); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x27); + + if (BbpReg > pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0) + { + BbpReg -= 4; + bbp_set_agc(pAd, BbpReg, RX_CHAIN_ALL); + } + else if (BbpReg == pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0xAD); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x0D); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0xB1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x16); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x8D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x0C); + } + } + else + { + if (BbpReg == pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x8D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x0C); + } + } +#ifdef ED_MONITOR + if(BbpReg >= (pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0 + VgaGainLowerBound)) + pAd->ed_vga_at_lowest_gain = TRUE; + else + pAd->ed_vga_at_lowest_gain = FALSE; +#endif + } +} + +VOID rt6352_dynamic_vga_enable(RTMP_ADAPTER *pAd) +{ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x83); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x70); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x86); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x70); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9c); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x27); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9d); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x27); +} + + +VOID rt6352_dynamic_vga_disable(RTMP_ADAPTER *pAd) +{ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x83); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x32); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x86); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x19); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9c); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x3d); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9d); + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x40); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x2F); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x8D); + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { +#ifdef RT6352_EL_SUPPORT + if (pAd->NicConfig2.field.ExternalLNAForG) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x15); + else +#endif /* RT6352_EL_SUPPORT */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x1A); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x10); + } + + + bbp_set_agc(pAd, pAd->CommonCfg.lna_vga_ctl.agc_vga_ori_0, RX_CHAIN_ALL); +} + +#endif /* DYNAMIC_VGA_SUPPORT */ + +UINT32 rt6352_get_current_temp( + IN RTMP_ADAPTER *pAd) +{ + UINT32 current_temp = 0; + current_temp = (19*(pAd->CurrTemperature - pAd->TemperatureRef25C))/10 + 25; + return current_temp; +} + +#ifdef THERMAL_PROTECT_SUPPORT +VOID thermal_pro_default_cond( + IN RTMP_ADAPTER *pAd) +{ + UINT32 mac_val = 0; + + DBGPRINT(RT_DEBUG_OFF, ("----->%s\n", __FUNCTION__)); + + /* Default A-MPDU length */ + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M1S, 0x77777777); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M1S, 0x77777777); + + /* 2SS */ + RTMP_IO_READ32(pAd, TXRX_MICS_CTRL, &mac_val); + mac_val &= ~(0x00000008); + RTMP_IO_WRITE32(pAd, TXRX_MICS_CTRL, mac_val); + + pAd->force_one_tx_stream = FALSE; +} + +VOID thermal_pro_1st_cond( + IN RTMP_ADAPTER *pAd) +{ + UINT32 mac_val = 0; + + DBGPRINT(RT_DEBUG_OFF, ("----->%s\n", __FUNCTION__)); + + /* Default A-MPDU length */ + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M1S, 0x77777777); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M1S, 0x77777777); + + /* 2SS -> 1SS */ + RTMP_IO_READ32(pAd, TXRX_MICS_CTRL, &mac_val); + mac_val |= 0x00000008; + RTMP_IO_WRITE32(pAd, TXRX_MICS_CTRL, mac_val); + + pAd->force_one_tx_stream = TRUE; +} + +VOID thermal_pro_2nd_cond( + IN RTMP_ADAPTER *pAd) +{ + UINT32 mac_val = 0; + + DBGPRINT(RT_DEBUG_OFF, ("----->%s\n", __FUNCTION__)); + + /* Reduce A-MPDU length */ + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M1S, 0x33222222); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M1S, 0x33222222); + + /* 1SS */ + RTMP_IO_READ32(pAd, TXRX_MICS_CTRL, &mac_val); + mac_val |= 0x00000008; + RTMP_IO_WRITE32(pAd, TXRX_MICS_CTRL, mac_val); + + pAd->force_one_tx_stream = TRUE; +} +#endif /* THERMAL_PROTECT_SUPPORT */ + +#ifdef ED_MONITOR +VOID RT6352_set_ed_cca(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 mac_val; + UCHAR bbp_val; + + if (enable) + { + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val &= (~0x01); + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + + RTMP_IO_READ32(pAd, CH_IDLE_STA, &mac_val); + RTMP_IO_READ32(pAd, CH_BUSY_STA, &mac_val); + RTMP_IO_READ32(pAd, CH_BUSY_STA_SEC, &mac_val); + RTMP_IO_READ32(pAd, 0x1140, &mac_val); + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= 0x05; // enable channel status check + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + + bbp_val = 0x1C; // bit 0~7 for high threshold + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R61, bbp_val); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R87, &bbp_val); + bbp_val |= 0x84; // bit 0~2 for low threshold, bit 7 for enable ED_CCA + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R87, bbp_val); + + // enable bbp for ED_2nd_CCA status check + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R83, &bbp_val); + bbp_val = 0x9a; // bit 0~3 for threshold + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, bbp_val); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &bbp_val); + bbp_val &= (~0x02); // bit 1 for eanble/disable ED_2nd_CCA, 0: enable, 1: disable + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, bbp_val); + + RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val); + mac_val |= ((1<<20) | (1<<7)); + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R87, &bbp_val); + bbp_val &= (~0x80); // bit 7 for enable/disable ED_CCA + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R87, bbp_val); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &bbp_val); + bbp_val |= (0x02); // bit 1 for eanble/disable ED_2nd_CCA, 0: enable, 1: disable + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, bbp_val); + RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val); + mac_val &= (~((1<<20) | (1<<7))); + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val); + } +} +#endif /* ED_MONITOR */ + + +/* +======================================================================== +Routine Description: + Initialize RT6352. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT6352_Init( + IN PRTMP_ADAPTER pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + pChipCap->hif_type = HIF_RTMP; + pChipCap->rf_type = RF_RT; + + pAd->RfIcType = RFIC_UNKNOWN; + rtmp_phy_probe(pAd); + + /* + Init chip capabilities + */ + pChipCap->MCUType = SWMCU; +#ifdef MCS_LUT_SUPPORT + pChipCap->asic_caps |= (fASIC_CAP_MCS_LUT); +#endif /* MCS_LUT_SUPPORT */ + pChipCap->phy_caps = (fPHY_CAP_24G); + pChipCap->phy_caps |= (fPHY_CAP_HT); + pChipCap->max_nss = 2; + pChipCap->ba_max_cnt = 21; + pChipCap->TXWISize = 20; + pChipCap->RXWISize = 24; + pChipCap->WPDMABurstSIZE = 2; + pChipCap->DPDCalPassThres = 5; + + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_LEGACY); + + pChipCap->MaxNumOfRfId = 64; + pChipCap->MaxNumOfBbpId = 255; + pChipCap->bbpRegTbSize = 0; + pChipCap->FlgIsVcoReCalMode = VCO_CAL_MODE_3; + pChipCap->SnrFormula = SNR_FORMULA2; + pChipCap->RfReg17WtMethod = RF_REG_WT_METHOD_NONE; + pChipOps->AsicGetTxPowerOffset = AsicGetTxPowerOffset; + pChipOps->AsicExtraPowerOverMAC = RT6352_AsicExtraPowerOverMAC; + pChipOps->AsicAdjustTxPower = RT6352_AsicAdjustTxPower; + +#ifdef RTMP_INTERNAL_TX_ALC + pChipCap->TxAlcTxPowerUpperBound_2G = 61; + pChipCap->TxPowerTuningTable_2G = NULL /* RT6352_TxPowerTuningTable */; + pChipOps->InitDesiredTSSITable = RT6352_InitDesiredTSSITable; + pChipOps->AsicTxAlcGetAutoAgcOffset = NULL /*RT6352_AsicTxAlcGetAutoAgcOffset*/; +#endif /* RTMP_INTERNAL_TX_ALC */ + + pChipOps->ChipGetCurrentTemp = rt6352_get_current_temp; + +#ifdef THERMAL_PROTECT_SUPPORT + pChipCap->ThermalProtectSup = TRUE; + pChipOps->ThermalProDefaultCond = thermal_pro_default_cond; + pChipOps->ThermalPro1stCond = thermal_pro_1st_cond; + pChipOps->ThermalPro2ndCond = thermal_pro_2nd_cond; +#endif /* THERMAL_PROTECT_SUPPORT */ + + pChipCap->FlgIsHwWapiSup = TRUE; + pChipCap->DPDCalPassLowThresTX0 = -999; + pChipCap->DPDCalPassLowThresTX1 = 0; + pChipCap->DPDCalPassHighThresTX0 = 5; + pChipCap->DPDCalPassHighThresTX1 = 15; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->EEPROM_DEFAULT_BIN = RT6352_EeBuffer; +#endif /* RTMP_FLASH_SUPPORT */ + +#ifdef NEW_MBSSID_MODE +#ifdef ENHANCE_NEW_MBSSID_MODE + pChipCap->MBSSIDMode = MBSSID_MODE4; +#else + pChipCap->MBSSIDMode = MBSSID_MODE1; +#endif /* ENHANCE_NEW_MBSSID_MODE */ +#else + pChipCap->MBSSIDMode = MBSSID_MODE0; +#endif /* NEW_MBSSID_MODE */ + +#ifdef FIFO_EXT_SUPPORT + pChipCap->FlgHwFifoExtCap = TRUE; +#endif /* FIFO_EXT_SUPPORT */ + + /* init operator */ + pChipOps->AsicRfInit = NICInitRT6352RFRegisters; + pChipOps->AsicBbpInit = NICInitRT6352BbpRegisters; + pChipOps->AsicMacInit = NICInitRT6352MacRegisters; + +#ifdef GREENAP_SUPPORT + pChipOps->EnableAPMIMOPS = EnableAPMIMOPSv2; + pChipOps->DisableAPMIMOPS = DisableAPMIMOPSv2; +#endif /* GREENAP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + pChipOps->ChipAGCAdjust = RT6352_ChipAGCAdjust; +#endif /* CONFIG_STA_SUPPORT */ + pChipOps->ChipBBPAdjust = RT6352_ChipBBPAdjust; + pChipOps->AsicAntennaDefaultReset = RT6352_AsicAntennaDefaultReset; + pChipOps->ChipSwitchChannel = RT6352_ChipSwitchChannel; +#ifdef ED_MONITOR + pChipOps->ChipSetEDCCA = RT6352_set_ed_cca; +#else + pChipOps->ChipSetEDCCA= NULL; +#endif /* ED_MONITOR */ + + pChipOps->ChipAGCInit = RT6352_RTMPSetAGCInitValue; +#ifdef CARRIER_DETECTION_SUPPORT + pAd->chipCap.carrier_func = TONE_RADAR_V2; + pChipOps->ToneRadarProgram = ToneRadarProgram_v2; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef MICROWAVE_OVEN_SUPPORT + pChipOps->AsicMeasureFalseCCA = RT6352_AsicMeasureFalseCCA; + pChipOps->AsicMitigateMicrowave = RT6352_AsicMitigateMicrowave; +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + pChipCap->dynamic_vga_support = TRUE; + pChipCap->avg_rssi_all = -90; + pChipCap->avg_rssi_0 = -90; + pChipCap->avg_rssi_1 = -90; + pChipOps->AsicDynamicVgaGainControl = RT6352_AsicDynamicVgaGainControl; + pChipOps->UpdateRssiForDynamicVga = RT6352_UpdateRssiForChannelModel; +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef SPECIFIC_BCN_BUF_SUPPORT + RtmpChipBcnSpecInit(pAd); +#else + RtmpChipBcnInit(pAd); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +} +#endif /* RT6352 */ +/* End of rt3352.c */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rt65xx.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rt65xx.c new file mode 100644 index 000000000..2abe3e7b8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rt65xx.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rtmp_chip.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rtmp_chip.c new file mode 100644 index 000000000..bccd6f151 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rtmp_chip.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rtxx_dft.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rtxx_dft.c new file mode 100644 index 000000000..d43db9007 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/chips/rtxx_dft.c @@ -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 */ +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/action.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/action.c new file mode 100644 index 000000000..84936b68f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/action.c @@ -0,0 +1,1482 @@ +/**************************************************************************** + * 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: + action.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2006 created for rt2860 + */ + +#include "rt_config.h" +#include "action.h" + +extern UCHAR ZeroSsid[32]; +#ifdef IWSC_SUPPORT +extern UCHAR IWSC_ACTION_OUI[]; +#endif // IWSC_SUPPORT // + +static VOID ReservedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + + ASSOC_IDLE + MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action + MT2_PEER_DISASSOC_REQ peer_disassoc_action + MT2_PEER_ASSOC_REQ drop + MT2_PEER_REASSOC_REQ drop + MT2_CLS3ERR cls3err_action + ========================================================================== + */ +VOID ActionStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); +#ifdef QOS_DLS_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); +#ifdef DOT11_VHT_AC + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_VHT_CATE, (STATE_MACHINE_FUNC)PeerVHTAction); +#endif /* DOT11_VHT_AC */ + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); +#endif /* DOT11_N_SUPPORT */ + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11R_FT_SUPPORT + StateMachineSetAction(S, ACT_IDLE, FT_CATEGORY_BSS_TRANSITION, (STATE_MACHINE_FUNC)FT_FtAction); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PMF_CATE, (STATE_MACHINE_FUNC)PMF_PeerAction); +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + StateMachineSetAction(S, ACT_IDLE, WNM_CATEGORY_BSS_TRANSITION, (STATE_MACHINE_FUNC)WNM_Action); +#endif /* DOT11V_WNM_SUPPORT */ + +} + + +#ifdef DOT11_N_SUPPORT +VOID MlmeADDBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_ADDBA_REQ_STRUCT *pInfo; + UCHAR Addr[6]; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_ADDBA_REQ Frame; + ULONG FrameLen; + /*BA_ORI_ENTRY *pBAEntry = NULL;*/ + MAC_TABLE_ENTRY *pEntry = NULL; + struct wifi_dev *wdev; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; + NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); + + if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr) && + VALID_WCID(pInfo->Wcid)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + /* 1. find entry */ + pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + ASSERT((pEntry->wdev != NULL)); + wdev = pEntry->wdev; + + Idx = pEntry->BAOriWcidArray[pInfo->TID]; + if (Idx == 0) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); + return; + } + else + { + /*pBAEntry =&pAd->BATable.BAOriEntry[Idx];*/ + } + +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE)) { + INT idx = pAd->MacTab.Content[pInfo->Wcid].wdev_idx; + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, + pAd->ApCfg.ApCliTab[idx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, + pInfo->pAddr); + } + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, wdev->if_addr, wdev->bssid); + + Frame.Category = CATEGORY_BA; + Frame.Action = ADDBA_REQ; + Frame.BaParm.AMSDUSupported = 0; +#ifdef WFA_VHT_PF + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + Frame.BaParm.AMSDUSupported = 1; +#endif /* WFA_VHT_PF */ + Frame.BaParm.BAPolicy = IMMED_BA; + Frame.BaParm.TID = pInfo->TID; + Frame.BaParm.BufSize = pInfo->BaBufSize; + Frame.Token = pInfo->Token; + Frame.TimeOutValue = pInfo->TimeOutValue; + Frame.BaStartSeq.field.FragNum = 0; + Frame.BaStartSeq.field.StartSeq = pEntry->TxSeq[pInfo->TID]; + +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&Frame.BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&Frame.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&(Frame.BaParm)) = cpu2le16((*(USHORT *)(&(Frame.BaParm)))); +#endif /* UNALIGNMENT_SUPPORT */ + + Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); + Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_REQ), &Frame, + END_OF_ARGS); + + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | WMM_UP2AC_MAP[pInfo->TID]), pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, + ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", + Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); + } +} + + +/* + ========================================================================== + Description: + send DELBA and delete BaEntry if any + Parametrs: + Elem - MLME message MLME_DELBA_REQ_STRUCT + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDELBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL, pOutBuffer2 = NULL; + FRAME_DELBA_REQ Frame; + ULONG FrameLen; + FRAME_BAR FrameBar; + MAC_TABLE_ENTRY *pEntry = NULL; + struct wifi_dev *wdev; + + + pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; + /* must send back DELBA */ + NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); + + if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen) && + VALID_WCID(pInfo->Wcid)) + { + if(MlmeAllocateMemory(pAd, &pOutBuffer) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); + return; + } + + if(MlmeAllocateMemory(pAd, &pOutBuffer2) != NDIS_STATUS_SUCCESS) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); + return; + } + + /* SEND BAR (Send BAR to refresh peer reordering buffer.) */ + pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + if (!pEntry->wdev) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():No binding wdev for wcid(%d)\n", __FUNCTION__, pInfo->Wcid)); + MlmeFreeMemory(pAd, pOutBuffer); + MlmeFreeMemory(pAd, pOutBuffer2); + return; + } + + wdev = pEntry->wdev; +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pEntry->bReptCli) + { + UINT apidx = pAd->MacTab.Content[pInfo->Wcid].wdev_idx; + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, + pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + } + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, wdev->if_addr); + + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.TID = pInfo->TID; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.ACKPolicy = IMMED_BA; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.Compressed = 1; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.MTID = 0; /* make sure sequence not clear in DEL funciton.*/ + + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer2); + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); + + /* SEND DELBA FRAME*/ + FrameLen = 0; +//CFG_TODO +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pEntry->bReptCli) + { + UINT apidx = pEntry->wdev_idx; + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, + pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + } + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, + pEntry->Addr, + pEntry->wdev->if_addr, + pEntry->wdev->bssid); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd) +#ifdef QOS_DLS_SUPPORT + || (IS_ENTRY_DLS(pEntry)) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(pEntry)) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, pAd->StaCfg.wdev.if_addr, pAd->StaCfg.wdev.bssid); + else + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, pAd->StaCfg.wdev.if_addr, pAd->StaCfg.wdev.bssid); + } +#endif /* CONFIG_STA_SUPPORT */ + + Frame.Category = CATEGORY_BA; + Frame.Action = DELBA; + Frame.DelbaParm.Initiator = pInfo->Initiator; + Frame.DelbaParm.TID = pInfo->TID; + Frame.ReasonCode = 39; /* Time Out*/ + *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); + Frame.ReasonCode = cpu2le16(Frame.ReasonCode); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_DELBA_REQ), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + { + int tid=0; + MAC_TABLE_ENTRY *pEntry; + pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + for (tid=0; tidTxBarSeq[tid] = -1; + } + DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); + } +} +#endif /* DOT11_N_SUPPORT */ + + +VOID MlmeQOSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) + MLME_QOS_ACTION_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + pInfo = (MLME_QOS_ACTION_STRUCT *)Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - MlmeQOSAction() allocate memory failed \n")); + return; + } + + if (pInfo->ActionField == ACTION_QOSMAP_CONFIG) + { + UCHAR OosMapIE = IE_QOS_MAP_SET; + QOSMAP_SET *pQosMapBuf = &pInfo->QOSMap; + MULTISSID_STRUCT *mbss = &pAd->ApCfg.MBSSID[pInfo->apidx]; + UCHAR ielen = 0; + + ActHeaderInit(pAd, &Frame.Hdr, pInfo->Addr, pAd->ApCfg.MBSSID[pInfo->apidx].wdev.bssid, pAd->ApCfg.MBSSID[pInfo->apidx].wdev.bssid); + + Frame.Category = CATEGORY_QOS; + Frame.Action = ACTION_QOSMAP_CONFIG; + + ielen = pQosMapBuf->DSCP_Field_Len; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + 1, &OosMapIE, + 1, &ielen, + ielen, pQosMapBuf->DSCP_Field, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + } + + MlmeFreeMemory(pAd, pOutBuffer); +#endif /* defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) */ + +} + + +VOID MlmeDLSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +} + + +VOID MlmeInvalidAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + /*PUCHAR pOutBuffer = NULL;*/ + /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11*/ +} + + +VOID PeerQOSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +} + + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ACTION_DLS_REQUEST: +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APPeerDlsReqAction(pAd, Elem); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsReqAction(pAd, Elem); +#endif /* CONFIG_STA_SUPPORT */ + break; + + case ACTION_DLS_RESPONSE: +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APPeerDlsRspAction(pAd, Elem); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsRspAction(pAd, Elem); +#endif /* CONFIG_STA_SUPPORT */ + break; + + case ACTION_DLS_TEARDOWN: +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APPeerDlsTearDownAction(pAd, Elem); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsTearDownAction(pAd, Elem); +#endif /* CONFIG_STA_SUPPORT */ + break; + } +} +#endif /* QOS_DLS_SUPPORT */ + + + + +#ifdef DOT11_N_SUPPORT +VOID PeerBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ADDBA_REQ: + PeerAddBAReqAction(pAd,Elem); + break; + case ADDBA_RESP: + PeerAddBARspAction(pAd,Elem); + break; + case DELBA: + PeerDelBAAction(pAd,Elem); + break; + } +} + + +#ifdef DOT11N_DRAFT3 +#ifdef CONFIG_AP_SUPPORT +extern UCHAR get_regulatory_class(IN PRTMP_ADAPTER pAd); + +VOID SendBSS2040CoexistMgmtAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq) +{ + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + BSS_2040_COEXIST_ELEMENT BssCoexistInfo; + BSS_2040_INTOLERANT_CH_REPORT BssIntolerantInfo; + UCHAR *pAddr1; + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("SendBSS2040CoexistMgmtAction(): Wcid=%d, apidx=%d, InfoReq=%d!\n", Wcid, apidx, InfoReq)); + + NdisZeroMemory((PUCHAR)&BssCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT)); + NdisZeroMemory((PUCHAR)&BssIntolerantInfo, sizeof(BSS_2040_INTOLERANT_CH_REPORT)); + + BssCoexistInfo.ElementID = IE_2040_BSS_COEXIST; + BssCoexistInfo.Len = 1; + BssCoexistInfo.BssCoexistIe.word = pAd->CommonCfg.LastBSSCoexist2040.word; + BssCoexistInfo.BssCoexistIe.field.InfoReq = InfoReq; + BssIntolerantInfo.ElementID = IE_2040_BSS_INTOLERANT_REPORT; + BssIntolerantInfo.Len = 1; + BssIntolerantInfo.RegulatoryClass = get_regulatory_class(pAd); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction() allocate memory failed \n")); + return; + } + + if (Wcid == MCAST_WCID) + pAddr1 = &BROADCAST_ADDR[0]; + else + pAddr1 = pAd->MacTab.Content[Wcid].Addr; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, wdev->if_addr, wdev->bssid); + + Frame.Category = CATEGORY_PUBLIC; + Frame.Action = ACTION_BSS_2040_COEXIST; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + sizeof(BSS_2040_COEXIST_ELEMENT), &BssCoexistInfo, + sizeof(BSS_2040_INTOLERANT_CH_REPORT), &BssIntolerantInfo, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction(BSSCoexist2040=0x%x)\n", BssCoexistInfo.BssCoexistIe.word)); + +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +VOID StaPublicAction(RTMP_ADAPTER *pAd, BSS_2040_COEXIST_IE *pBssCoexIE) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + + DBGPRINT(RT_DEBUG_TRACE,("ACTION - StaPeerPublicAction Bss2040Coexist = %x\n", *((PUCHAR)pBssCoexIE))); + + /* AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame */ + if ((pBssCoexIE->field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))) + { + /* Clear record first. After scan , will update those bit and send back to transmiter.*/ + pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1; + pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0; + pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0; + /* Clear Trigger event table*/ + TriEventInit(pAd); + /* Fill out stuff for scan request and kick to scan*/ + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + RTMP_MLME_HANDLER(pAd); + } +} + +VOID UpdateBssScanParm( + IN PRTMP_ADAPTER pAd, + IN OVERLAP_BSS_SCAN_IE APBssScan) +{ + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = le2cpu16(APBssScan.DelayFactor); /*APBssScan.DelayFactor[1] * 256 + APBssScan.DelayFactor[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor <5) || (pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor > 100)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11BssWidthChanTranDelayFactor out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = 5; + } + + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = le2cpu16(APBssScan.TriggerScanInt); /*APBssScan.TriggerScanInt[1] * 256 + APBssScan.TriggerScanInt[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11BssWidthTriggerScanInt < 10) ||(pAd->CommonCfg.Dot11BssWidthTriggerScanInt > 900)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11BssWidthTriggerScanInt out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = 900; + } + + pAd->CommonCfg.Dot11OBssScanPassiveDwell = le2cpu16(APBssScan.ScanPassiveDwell); /*APBssScan.ScanPassiveDwell[1] * 256 + APBssScan.ScanPassiveDwell[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11OBssScanPassiveDwell < 5) ||(pAd->CommonCfg.Dot11OBssScanPassiveDwell > 1000)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanPassiveDwell out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11OBssScanPassiveDwell = 20; + } + + pAd->CommonCfg.Dot11OBssScanActiveDwell = le2cpu16(APBssScan.ScanActiveDwell); /*APBssScan.ScanActiveDwell[1] * 256 + APBssScan.ScanActiveDwell[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11OBssScanActiveDwell < 10) ||(pAd->CommonCfg.Dot11OBssScanActiveDwell > 1000)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanActiveDwell out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11OBssScanActiveDwell = 10; + } + + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = le2cpu16(APBssScan.PassiveTalPerChannel); /*APBssScan.PassiveTalPerChannel[1] * 256 + APBssScan.PassiveTalPerChannel[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel < 200) ||(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel > 10000)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanPassiveTotalPerChannel out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = 200; + } + + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = le2cpu16(APBssScan.ActiveTalPerChannel); /*APBssScan.ActiveTalPerChannel[1] * 256 + APBssScan.ActiveTalPerChannel[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if ((pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel < 20) ||(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel > 10000)) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanActiveTotalPerChannel out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = 20; + } + + pAd->CommonCfg.Dot11OBssScanActivityThre = le2cpu16(APBssScan.ScanActThre); /*APBssScan.ScanActThre[1] * 256 + APBssScan.ScanActThre[0];*/ + /* out of range defined in MIB... So fall back to default value.*/ + if (pAd->CommonCfg.Dot11OBssScanActivityThre > 100) + { + /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanActivityThre out of range !!!!) \n"));*/ + pAd->CommonCfg.Dot11OBssScanActivityThre = 25; + } + + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + /*DBGPRINT(RT_DEBUG_LOUD,("ACT - UpdateBssScanParm( Dot11BssWidthTriggerScanInt = %d ) \n", pAd->CommonCfg.Dot11BssWidthTriggerScanInt));*/ +} + +#endif /* CONFIG_STA_SUPPORT */ + +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) + +/* +Description : Build Intolerant Channel Rerpot from Trigger event table. +return : how many bytes copied. +*/ +ULONG BuildIntolerantChannelRep(RTMP_ADAPTER *pAd, UCHAR *pDest) +{ + ULONG FrameLen = 0; + ULONG ReadOffset = 0; + UCHAR i, j, k, idx = 0; + /*UCHAR LastRegClass = 0xff;*/ + UCHAR ChannelList[MAX_TRIGGER_EVENT]; + UCHAR TmpRegClass; + UCHAR RegClassArray[7] = {0, 11,12, 32, 33, 54,55}; /* Those regulatory class has channel in 2.4GHz. See Annex J.*/ + + + RTMPZeroMemory(ChannelList, MAX_TRIGGER_EVENT); + + /* Find every regulatory class*/ + for ( k = 0;k < 7;k++) + { + TmpRegClass = RegClassArray[k]; + + idx = 0; + /* Find Channel report with the same regulatory class in 2.4GHz.*/ + for ( i = 0;i < pAd->CommonCfg.TriggerEventTab.EventANo;i++) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == TmpRegClass) + { + for (j = 0;j < idx;j++) + { + if (ChannelList[j] == (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel) + break; + } + if ((j == idx)) + { + ChannelList[idx] = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; + idx++; + } + pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; + } + DBGPRINT(RT_DEBUG_ERROR,("ACT - BuildIntolerantChannelRep , Total Channel number = %d \n", idx)); + } + } + + /* idx > 0 means this regulatory class has some channel report and need to copy to the pDest.*/ + if (idx > 0) + { + /* For each regaulatory IE report, contains all channels that has the same regulatory class.*/ + *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; /* IE*/ + *(pDest + ReadOffset + 1) = 1+ idx; /* Len = RegClass byte + channel byte.*/ + *(pDest + ReadOffset + 2) = TmpRegClass; /* Len = RegClass byte + channel byte.*/ + RTMPMoveMemory(pDest + ReadOffset + 3, ChannelList, idx); + + FrameLen += (3 + idx); + ReadOffset += (3 + idx); + } + + } + + DBGPRINT(RT_DEBUG_ERROR,("ACT-BuildIntolerantChannelRep(Size=%ld)\n", FrameLen)); + hex_dump("ACT-pDestMsg", pDest, FrameLen); + + return FrameLen; +} + + +/* + ========================================================================== + Description: + After scan, Update 20/40 BSS Coexistence IE and send out. + According to 802.11n D3.03 11.14.10 + + Parameters: + ========================================================================== + */ +VOID Update2040CoexistFrameAndNotify( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + /*BSS_2040_COEXIST_IE OldValue;*/ + + DBGPRINT(RT_DEBUG_ERROR,("%s(): ACT -BSSCoexist2040 = %x. EventANo = %d. \n", + __FUNCTION__, pAd->CommonCfg.BSSCoexist2040.word, + pAd->CommonCfg.TriggerEventTab.EventANo)); + + /*OldValue.word = pAd->CommonCfg.BSSCoexist2040.word;*/ + /* Reset value.*/ + pAd->CommonCfg.BSSCoexist2040.word = 0; + + if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0) + pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1; + + /* Need to check !!!!*/ + /* How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first!!!!!*/ + /* So Only check BSS20WidthReq change.*/ + /*if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq)*/ + { + Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha); + } +} + + +/* +Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered. +*/ +VOID Send2040CoexistAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + UINT32 IntolerantChaRepLen; + UCHAR HtLen = 1; +#ifdef APCLI_SUPPORT + UCHAR apidx; +#endif /* APCLI_SUPPORT */ + IntolerantChaRepLen = 0; + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n")); + return; + } + +#ifdef DOT11V_WNM_SUPPORT + /* Not complete yet. Ignore for compliing successfully.*/ +#else +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid])) + { + apidx = pAd->MacTab.Content[Wcid].apidx; + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, pAd->MacTab.Content[Wcid].Addr); + DBGPRINT(RT_DEBUG_OFF, ("\x1b[31m\n%02x:%02x:%02x:%02x:%02x:%02x \x1b[m\n", + pAd->MacTab.Content[Wcid].Addr[0], pAd->MacTab.Content[Wcid].Addr[1], pAd->MacTab.Content[Wcid].Addr[2], + pAd->MacTab.Content[Wcid].Addr[3], pAd->MacTab.Content[Wcid].Addr[4], pAd->MacTab.Content[Wcid].Addr[5])); + } + else +#endif /* APCLI_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); +#endif /* DOT11V_WNM_SUPPORT */ + + Frame.Category = CATEGORY_PUBLIC; + Frame.Action = ACTION_BSS_2040_COEXIST; /*COEXIST_2040_ACTION;*/ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + 1, &BssCoexistIe, + 1, &HtLen, + 1, &pAd->CommonCfg.BSSCoexist2040.word, + END_OF_ARGS); + + if (bAddIntolerantCha == TRUE) + IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen); + + /*2009 PF#3: IOT issue with Motorola AP. It will not check the field of BSSCoexist2040.*/ + /*11.14.12 Switching between 40 MHz and 20 MHz*/ + DBGPRINT(RT_DEBUG_TRACE, ("IntolerantChaRepLen=%d, BSSCoexist2040=0x%x!\n", + IntolerantChaRepLen, pAd->CommonCfg.BSSCoexist2040.word)); + if (!((IntolerantChaRepLen == 0) && (pAd->CommonCfg.BSSCoexist2040.word == 0))) + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word)); +} + + + + +#endif /* defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) */ + + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR i; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + if ((NewChannel > 7) && (Secondary == 1)) + return FALSE; + + if ((NewChannel < 5) && (Secondary == 3)) + return FALSE; + + /* 0. Check if new channel is in the channellist.*/ + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == NewChannel) + { + break; + } + } + + if (i == pAd->ChannelListNum) + return FALSE; + + return TRUE; +} + + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR rf_channel = 0, rf_bw; + + DBGPRINT(RT_DEBUG_TRACE,("%s(): NewChannel=%d, Secondary=%d\n", + __FUNCTION__, NewChannel, Secondary)); + + if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) + return; + + pAd->CommonCfg.Channel = NewChannel; + if (Secondary == EXTCHA_NONE) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + + rf_bw = BW_20; + rf_channel = pAd->CommonCfg.Channel; + } + /* 1. Switches to BW = 40 And Station supports BW = 40.*/ + else if (((Secondary == EXTCHA_ABOVE) || (Secondary == EXTCHA_BELOW)) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1) + ) + { + rf_bw = BW_40; +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + { + rf_bw = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } + else +#endif /* GREENAP_SUPPORT */ + if (Secondary == EXTCHA_ABOVE) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + + rf_channel = pAd->CommonCfg.CentralChannel; + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; + } + + if (rf_channel != 0) { + AsicSetChannel(pAd, rf_channel, rf_bw, Secondary, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): %dMHz LINK UP, CtrlChannel=%d, CentralChannel= %d \n", + __FUNCTION__, (rf_bw == BW_40 ? 40 : 20), + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); +#ifdef SMART_MESH_MONITOR + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.channel_change.type = NSMPIF_DRVEVNT_CHANNEL_CHANGE; + drvevnt.data.channel_change.channel = pAd->CommonCfg.Channel; + NdisZeroMemory(drvevnt.data.channel_change.op_channels,sizeof(drvevnt.data.channel_change.op_channels)); + drvevnt.data.channel_change.op_channels[0] = pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + if(rf_bw == BW_40) + drvevnt.data.channel_change.op_channels[1] = N_GetSecondaryChannel(pAd); +#endif /* DOT11_N_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_CHANNEL_CHANGE, + NULL, (PUCHAR)&drvevnt.data.channel_change, sizeof(drvevnt.data.channel_change)); + } +#endif /* SMART_MESH_MONITOR */ + } +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + +VOID PeerPublicAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + if (!HotSpotEnable(pAd, Elem, ACTION_STATE_MESSAGES)) +#endif + if ((Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) +#ifdef DOT11Z_TDLS_SUPPORT + && (Action != ACTION_TDLS_DISCOVERY_RSP) +#endif // DOT11Z_TDLS_SUPPORT // + ) + return; + + + switch(Action) + { +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + case ACTION_BSS_2040_COEXIST: /* Format defined in IEEE 7.4.7a.1 in 11n Draf3.03*/ + { + /*UCHAR BssCoexist;*/ + BSS_2040_COEXIST_ELEMENT *pCoexistInfo; + BSS_2040_COEXIST_IE *pBssCoexistIe; + BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL; + + if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen)); + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n")); + hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen); + + + pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2]; + /*hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));*/ + if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT))) + { + pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT)); + } + /*hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));*/ + + if(pAd->CommonCfg.bBssCoexEnable == FALSE || (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("20/40 BSS CoexMgmt=%d, bForty_Mhz_Intolerant=%d, ignore this action!!\n", + pAd->CommonCfg.bBssCoexEnable, + pAd->CommonCfg.bForty_Mhz_Intolerant)); + break; + } + + pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + if (!IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid])) + { +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + BOOLEAN bNeedFallBack = FALSE; + + /*ApPublicAction(pAd, Elem);*/ + if ((pBssCoexistIe->field.BSS20WidthReq ==1) || (pBssCoexistIe->field.Intolerant40 == 1)) + { + bNeedFallBack = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("BSS_2040_COEXIST: BSS20WidthReq=%d, Intolerant40=%d!\n", pBssCoexistIe->field.BSS20WidthReq, pBssCoexistIe->field.Intolerant40)); + } + else if ((pIntolerantReport) && (pIntolerantReport->Len > 1) + /*&& (pIntolerantReport->RegulatoryClass == get_regulatory_class(pAd))*/) + { + int i; + UCHAR *ptr; + INT retVal; + BSS_COEX_CH_RANGE coexChRange; + + ptr = pIntolerantReport->ChList; + bNeedFallBack = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("The pIntolerantReport len = %d, chlist=", pIntolerantReport->Len)); + for(i =0 ; i < (pIntolerantReport->Len -1); i++, ptr++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d,", *ptr)); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + + retVal = GetBssCoexEffectedChRange(pAd, &coexChRange); + if (retVal == TRUE) + { + ptr = pIntolerantReport->ChList; + bNeedFallBack = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Check IntolerantReport Channel List in our effectedChList(%d~%d)\n", + pAd->ChannelList[coexChRange.effectChStart].Channel, + pAd->ChannelList[coexChRange.effectChEnd].Channel)); + for(i =0 ; i < (pIntolerantReport->Len -1); i++, ptr++) + { + UCHAR chEntry; + + chEntry = *ptr; + if (chEntry >= pAd->ChannelList[coexChRange.effectChStart].Channel && + chEntry <= pAd->ChannelList[coexChRange.effectChEnd].Channel) + { + DBGPRINT(RT_DEBUG_TRACE, ("Found Intolerant channel in effect range=%d!\n", *ptr)); + bNeedFallBack = TRUE; + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("After CoexChRange Check, bNeedFallBack=%d!\n", bNeedFallBack)); + } + + if (bNeedFallBack) + { + pBssCoexistIe->field.Intolerant40 = 1; + pBssCoexistIe->field.BSS20WidthReq = 1; + } + } + + if (bNeedFallBack) + { + int apidx; + + NdisMoveMemory((PUCHAR)&pAd->CommonCfg.LastBSSCoexist2040, (PUCHAR)pBssCoexistIe, sizeof(BSS_2040_COEXIST_IE)); + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; + + if (!(pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_TIMER_FIRED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Fire the Bss2040CoexistTimer with timeout=%ld!\n", + pAd->CommonCfg.Dot11BssWidthChanTranDelay)); + + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_TIMER_FIRED; + /* More 5 sec for the scan report of STAs.*/ + RTMPSetTimer(&pAd->CommonCfg.Bss2040CoexistTimer, (pAd->CommonCfg.Dot11BssWidthChanTranDelay + 5) * 1000); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Already fallback to 20MHz, Extend the timeout of Bss2040CoexistTimer!\n")); + /* More 5 sec for the scan report of STAs.*/ + RTMPModTimer(&pAd->CommonCfg.Bss2040CoexistTimer, (pAd->CommonCfg.Dot11BssWidthChanTranDelay + 5) * 1000); + } + + apidx = pAd->MacTab.Content[Elem->Wcid].apidx; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0); + } +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + } +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (INFRA_ON(pAd)) + { + StaPublicAction(pAd, pBssCoexistIe); + } + } +#endif /* CONFIG_STA_SUPPORT */ + } + break; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + case ACTION_GAS_INIT_REQ: + if (HotSpotEnable(pAd, Elem, ACTION_STATE_MESSAGES)) + { + ReceiveGASInitReq(pAd, Elem); +} + break; + case ACTION_GAS_CB_REQ: + if (HotSpotEnable(pAd, Elem, ACTION_STATE_MESSAGES)) + ReceiveGASCBReq(pAd, Elem); + break; +#endif + case ACTION_WIFI_DIRECT: +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + NdisEqualMemory(&(Elem->Msg[LENGTH_802_11+2]), IWSC_ACTION_OUI, 4)) + { + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_PEER_ACTION_FRAME, Elem->MsgLen, Elem->Msg, 0); + RTMP_MLME_HANDLER(pAd); + break; + } +#endif // IWSC_SUPPORT // + + break; + +#ifdef DOT11Z_TDLS_SUPPORT + case ACTION_TDLS_DISCOVERY_RSP: + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (INFRA_ON(pAd)) + { + TDLS_DiscoveryRspPublicAction(pAd, Elem, Elem->Msg, Elem->MsgLen); + } + } + break; +#endif // DOT11Z_TDLS_SUPPORT // + + default: + break; + } + +} + + +static VOID ReservedAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Category; + + if (Elem->MsgLen <= LENGTH_802_11) + { + return; + } + + Category = Elem->Msg[LENGTH_802_11]; + DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category)); + hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); +} + + +VOID PeerRMAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11K_RRM_SUPPORT + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (VALID_WCID(Elem->Wcid)) + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + else + return; + + if ((pEntry->apidx < pAd->ApCfg.BssidNum) && + !IS_RRM_ENABLE(pAd, pEntry->apidx)) + return; + + switch(Action) + { + case RRM_MEASURE_REP: + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get RRM Measure report.\n", + __FUNCTION__)); + + RRM_PeerMeasureRepAction(pAd, Elem); + break; + + case RRM_NEIGHTBOR_REQ: + RRM_PeerNeighborReqAction(pAd, Elem); + break; + } +#endif /* DOT11K_RRM_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + return; +} + + +#ifdef DOT11_N_SUPPORT + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID SendNotifyBWActionFrame(RTMP_ADAPTER *pAd, UCHAR Wcid, UCHAR apidx) +{ + UCHAR *pOutBuffer = NULL, *pAddr1; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + struct wifi_dev *wdev; + + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n")); + return; + } + + if (Wcid == MCAST_WCID) + pAddr1 = &BROADCAST_ADDR[0]; + else + pAddr1 = pAd->MacTab.Content[Wcid].Addr; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, wdev->if_addr, wdev->bssid); + Frame.Category = CATEGORY_HT; + Frame.Action = NOTIFY_BW_ACTION; + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + FrameLen++; + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth)); + +} +#endif /* DOT11N_DRAFT3 */ +#endif /* CONFIG_AP_SUPPORT */ + + +VOID PeerHTAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + MAC_TABLE_ENTRY *pEntry; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + switch(Action) + { + case NOTIFY_BW_ACTION: + DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n")); +#ifdef CONFIG_STA_SUPPORT + if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + { + /* Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps */ + /* sending BW_Notify Action frame, and cause us to linkup and linkdown. */ + /* In legacy mode, don't need to parse HT action frame.*/ + DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", + Elem->Msg[LENGTH_802_11+2] )); + break; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (Elem->Msg[LENGTH_802_11+2] == 0) /* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */ + pEntry->HTPhyMode.field.BW = 0; + else + { + pEntry->HTPhyMode.field.BW = pEntry->MaxHTPhyMode.field.BW & + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth; + } + break; + + case SMPS_ACTION: + /* 7.3.1.25*/ + DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); + if (((Elem->Msg[LENGTH_802_11+2] & 0x1) == 0)) + pEntry->MmpsMode = MMPS_DISABLE; + else if (((Elem->Msg[LENGTH_802_11+2] & 0x2) == 0)) + pEntry->MmpsMode = MMPS_STATIC; + else + pEntry->MmpsMode = MMPS_DYNAMIC; + + DBGPRINT(RT_DEBUG_TRACE,("Wcid(%d) MIMO PS = %d\n", Elem->Wcid, pEntry->MmpsMode)); + /* rt2860c : add something for smps change.*/ + break; + + case SETPCO_ACTION: + break; + + case MIMO_CHA_MEASURE_ACTION: + break; + + default: + DBGPRINT(RT_DEBUG_WARN,("%s(): Unknown HT Action:%d\n", __FUNCTION__, Action)); + break; + } +} + + +#ifdef DOT11_VHT_AC +VOID PeerVHTAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + switch(Action) + { + case ACT_VHT_OPMODE_NOTIFY: + { + OPERATING_MODE *op_mode = (OPERATING_MODE *)&Elem->Msg[LENGTH_802_11+2]; + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + DBGPRINT(RT_DEBUG_TRACE,("ACTION - Operating Mode Notification action---->\n")); + hex_dump("OperatingModeNotify", &Elem->Msg[0], Elem->MsgLen); + DBGPRINT(RT_DEBUG_TRACE, ("\t RxNssType=%d, RxNss=%d, ChBW=%d\n", + op_mode->rx_nss_type, op_mode->rx_nss, op_mode->ch_width)); + + if (op_mode->rx_nss_type == 0) { + pEntry->force_op_mode = TRUE; + NdisMoveMemory(&pEntry->operating_mode, op_mode, 1); + } + } + break; +#ifdef VHT_TXBF_SUPPORT + case ACT_VHT_COMPRESS_BF: + { + //DBGPRINT(RT_DEBUG_OFF,("ACTION - VHT Compressed Beamforming action---->\n")); + //hex_dump("VHT Compressed BF", &Elem->Msg[0], Elem->MsgLen); + break; + } +#endif /* VHT_TXBF_SUPPORT */ + default: + break; + } +} +#endif /* DOT11_VHT_AC */ + + + + +VOID SendRefreshBAR(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + FRAME_BAR FrameBar; + ULONG FrameLen; + NDIS_STATUS NStatus; + UCHAR *pOutBuffer = NULL, i, TID; + USHORT Sequence, idx; + BA_ORI_ENTRY *pBAEntry; + + for (i = 0; i BAOriWcidArray[i]; + if (idx == 0) + continue; + + pBAEntry = &pAd->BATable.BAOriEntry[idx]; + + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + TID = pBAEntry->TID; + + if (pEntry->TxBarSeq[TID] == pEntry->TxSeq[TID]) + { + continue; + } + + ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + + Sequence = pEntry->TxSeq[TID]; + + pEntry->TxBarSeq[TID] = pEntry->TxSeq[TID]; + +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pEntry->bReptCli) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pEntry->wdev->if_addr); + + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function.*/ + FrameBar.StartingSeq.field.StartSeq = Sequence; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.TID = TID; /* make sure sequence not clear in DEL funciton.*/ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | WMM_UP2AC_MAP[TID]), pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} +#endif /* DOT11_N_SUPPORT */ + + +VOID ActHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR *da, + IN UCHAR *sa, + IN UCHAR *bssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SUBTYPE_ACTION; + + COPY_MAC_ADDR(pHdr80211->Addr1, da); + COPY_MAC_ADDR(pHdr80211->Addr2, sa); + COPY_MAC_ADDR(pHdr80211->Addr3, bssid); +} + + +VOID BarHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA) +{ +/* USHORT Duration;*/ + + NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); + pCntlBar->FC.Type = FC_TYPE_CNTL; + pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; + pCntlBar->BarControl.MTID = 0; + pCntlBar->BarControl.Compressed = 1; + pCntlBar->BarControl.ACKPolicy = 0; + + + pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); + + COPY_MAC_ADDR(pCntlBar->Addr1, pDA); + COPY_MAC_ADDR(pCntlBar->Addr2, pSA); +} + + +/* + ========================================================================== + Description: + Insert Category and action code into the action frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. category code of the frame. + 4. action code of the frame. + + Return : None. + ========================================================================== + */ +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &Category, + 1, &ActCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ba_action.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ba_action.c new file mode 100644 index 000000000..e1cf702d5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ba_action.c @@ -0,0 +1,2378 @@ +#ifdef DOT11_N_SUPPORT + +#include "rt_config.h" + + + +#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /* 1 : inital sequence number of BA session*/ + +#define ORI_SESSION_MAX_RETRY 8 +#define ORI_BA_SESSION_TIMEOUT (2000) /* ms */ +#define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */ + +#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms*/ +#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms*/ + + +#define RESET_RCV_SEQ (0xFFFF) + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk); + +#ifdef PEER_DELBA_TX_ADAPT +static VOID Peer_DelBA_Tx_Adapt_Enable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +static VOID Peer_DelBA_Tx_Adapt_Disable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); +#endif /* PEER_DELBA_TX_ADAPT */ + +BA_ORI_ENTRY *BATableAllocOriEntry(RTMP_ADAPTER *pAd, USHORT *Idx); +BA_REC_ENTRY *BATableAllocRecEntry(RTMP_ADAPTER *pAd, USHORT *Idx); + +VOID BAOriSessionSetupTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); +BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); + +#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ + Announce_Reordering_Packet(_pAd, _mpdu_blk); + +VOID BA_MaxWinSizeReasign( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntryPeer, + OUT UCHAR *pWinSize) +{ + UCHAR MaxSize; + UCHAR MaxPeerRxSize; + + if (CLIENT_STATUS_TEST_FLAG(pEntryPeer, fCLIENT_STATUS_RALINK_CHIPSET)) + MaxPeerRxSize = (1 << (pEntryPeer->MaxRAmpduFactor + 3)); /* (2^(13 + exp)) / 2048 bytes */ + else + MaxPeerRxSize = (((1 << (pEntryPeer->MaxRAmpduFactor + 3)) * 10) / 16) -1; + + if(WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.Channel > 14) + && pEntryPeer->VhtMaxRAmpduFactor != 0) + { + MaxPeerRxSize = (((1 << (pEntryPeer->VhtMaxRAmpduFactor + 3)) * 10) / 16) -1; + } + +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + + if (IS_MT76x2(pAd)) + MaxSize = 47; + else + MaxSize = 31; + + if (((pEntryPeer->MaxHTPhyMode.field.MODE == MODE_HTMIX) || + (pEntryPeer->MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)) && + (pEntryPeer->HTCapability.MCSSet[2] != 0xff)) { + MaxSize = 31; + } + } + else +#endif /* RT65xx */ +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + MaxSize = 21; + } + else +#endif /* RT6352 */ + if (pAd->Antenna.field.TxPath == 3 && + (pEntryPeer->HTCapability.MCSSet[2] != 0)) + MaxSize = 31; /* for 3x3, MaxSize use ((48KB/1.5KB) -1) = 31 */ + else + MaxSize = 20; /* for not 3x3, MaxSize use ((32KB/1.5KB) -1) ~= 20 */ + + DBGPRINT(RT_DEBUG_TRACE, ("ba>WinSize=%d, MaxSize=%d, MaxPeerRxSize=%d, \ + pEntryPeer->MaxRAmpduFactor=%d, pEntryPeer->VhtMaxRAmpduFactor=%d\n", + *pWinSize, MaxSize, MaxPeerRxSize + , pEntryPeer->MaxRAmpduFactor, pEntryPeer->VhtMaxRAmpduFactor)); + + MaxSize = min(MaxPeerRxSize, MaxSize); + if ((*pWinSize) > MaxSize) + { + DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n", + *pWinSize, MaxSize)); + + *pWinSize = MaxSize; + } +} + + +void Announce_Reordering_Packet(RTMP_ADAPTER *pAd, struct reordering_mpdu *mpdu) +{ + PNDIS_PACKET pPacket; + + pPacket = mpdu->pPacket; + if (mpdu->bAMSDU) + { + /*ASSERT(0);*/ + BA_Reorder_AMSDU_Annnounce(pAd, pPacket, mpdu->OpMode); + } + else + { + + /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (IS_OPMODE_AP(mpdu)) + { + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); + } + else + { + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +/* Insert a reordering mpdu into sorted linked list by sequence no. */ +BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu) +{ + + struct reordering_mpdu **ppScan = &list->next; + + while (*ppScan != NULL) + { + if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) + { + ppScan = &(*ppScan)->next; + } + else if ((*ppScan)->Sequence == mpdu->Sequence) + { + /* give up this duplicated frame */ + return(FALSE); + } + else + { + /* find position */ + break; + } + } + + mpdu->next = *ppScan; + *ppScan = mpdu; + list->qlen++; + return TRUE; +} + + +/* Caller lock critical section if necessary */ +static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk) +{ + list->qlen++; + mpdu_blk->next = list->next; + list->next = mpdu_blk; +} + + +/* caller lock critical section if necessary */ +static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list) +{ + struct reordering_mpdu *mpdu_blk = NULL; + + ASSERT(list); + + if (list->qlen) + { + list->qlen--; + mpdu_blk = list->next; + if (mpdu_blk) + { + list->next = mpdu_blk->next; + mpdu_blk->next = NULL; + } + } + return mpdu_blk; +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list) +{ + return(ba_dequeue(list)); +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list) +{ + ASSERT(list); + + return(list->next); +} + + +/* free all resource for reordering mechanism */ +void ba_reordering_resource_release(RTMP_ADAPTER *pAd) +{ + BA_TABLE *Tab; + BA_REC_ENTRY *pBAEntry; + struct reordering_mpdu *mpdu_blk; + int i; + + Tab = &pAd->BATable; + + /* I. release all pending reordering packet */ + NdisAcquireSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry = &Tab->BARecEntry[i]; + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + ASSERT(mpdu_blk->pPacket); + RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + } + } + NdisReleaseSpinLock(&pAd->BATabLock); + + ASSERT(pBAEntry->list.qlen == 0); + /* II. free memory of reordering mpdu table */ + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + +/* + * Allocate all resource for reordering mechanism + */ +BOOLEAN ba_reordering_resource_init(RTMP_ADAPTER *pAd, int num) +{ + int i; + PUCHAR mem; + struct reordering_mpdu *mpdu_blk; + struct reordering_list *freelist; + + /* allocate spinlock */ + NdisAllocateSpinLock(pAd, &pAd->mpdu_blk_pool.lock); + + /* initialize freelist */ + freelist = &pAd->mpdu_blk_pool.freelist; + freelist->next = NULL; + freelist->qlen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu)))); + + /* allocate number of mpdu_blk memory */ + os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu))); + + pAd->mpdu_blk_pool.mem = mem; + + if (mem == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n")); + return(FALSE); + } + + /* build mpdu_blk free list */ + for (i=0; impdu_blk_pool.lock); + mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); + if (mpdu_blk) + { + /* reset mpdu_blk */ + NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); + } + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); + return mpdu_blk; +} + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk) +{ + ASSERT(mpdu_blk); + + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + +static USHORT ba_indicate_reordering_mpdus_in_order( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT StartSeq) +{ + struct reordering_mpdu *mpdu_blk; + USHORT LastIndSeq = RESET_RCV_SEQ; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) + break; + + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + if(mpdu_blk == NULL) + { + break; + } + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* move to next sequence */ + StartSeq = mpdu_blk->Sequence; + LastIndSeq = StartSeq; + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + + /* update last indicated sequence */ + return LastIndSeq; +} + +static void ba_indicate_reordering_mpdus_le_seq( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT Sequence) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) + { + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + if(mpdu_blk == NULL) + { + break; + } + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + else + { + break; + } + } + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +static void ba_refresh_reordering_mpdus(RTMP_ADAPTER *pAd, BA_REC_ENTRY *pBAEntry) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + /* dequeue in-order frame from reodering list */ + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + + pBAEntry->LastIndSeq = mpdu_blk->Sequence; + ba_mpdu_blk_free(pAd, mpdu_blk); + + /* update last indicated sequence */ + } + ASSERT(pBAEntry->list.qlen == 0); + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +/* static */ +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32) + +{ + USHORT Sequence; + + if ((pBAEntry == NULL) || (pBAEntry->list.qlen <= 0)) + return; + +/* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&*/ +/* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) ||*/ +/* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&*/ +/* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))*/ + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6))) + &&(pBAEntry->list.qlen > 1) + ) + { + DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), + (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT, + pBAEntry->LastIndSeq)); + ba_refresh_reordering_mpdus(pAd, pBAEntry); + pBAEntry->LastIndSeqAtTimer = Now32; + } + else + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) + && (pBAEntry->list.qlen > 0) + ) + { +/* + DBGPRINT(RT_DEBUG_OFF, ("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), + (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT, + pBAEntry->LastIndSeq)); +*/ + + /* force LastIndSeq to shift to LastIndSeq+1*/ + Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + pBAEntry->LastIndSeqAtTimer = Now32; + pBAEntry->LastIndSeq = Sequence; + + /* indicate in-order mpdus*/ + Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence); + if (Sequence != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = Sequence; + } + + DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq)); + + } +} + + +/* + * generate ADDBA request to + * set up BA agreement + */ +VOID BAOriSessionSetUp( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + USHORT Idx; + BOOLEAN Cancelled; + UCHAR BAWinSize = 0; + + ASSERT(TID < NUM_OF_TID); + if (TID >= NUM_OF_TID) + { + DBGPRINT(RT_DEBUG_TRACE, ("Wrong TID %d!\n", TID)); + return; + } + + if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) + return; + + /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */ + if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) + return; + + if ((pEntry->BADeclineBitmap & (1<BAOriWcidArray[TID]; + if (Idx == 0) + { + /* allocate a BA session*/ + pBAEntry = BATableAllocOriEntry(pAd, &Idx); + if (pBAEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE,("%s(): alloc BA session failed\n", + __FUNCTION__)); + return; + } + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + + if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) + return; + + pEntry->BAOriWcidArray[TID] = Idx; + + BAWinSize = pAd->CommonCfg.BACapability.field.TxBAWinLimit; + + + /* Initialize BA session */ + pBAEntry->ORI_BA_Status = Originator_WaitRes; + pBAEntry->Wcid = pEntry->wcid; + pBAEntry->BAWinSize = BAWinSize; + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0*/ + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = TimeOut; + pBAEntry->pAdapter = pAd; + + if (!(pEntry->TXBAbitmap & (1<ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); + } + else + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + + /* set timer to send ADDBA request */ + RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); +} + + +VOID BAOriSessionAdd( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN FRAME_ADDBA_RSP *pFrame) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + BOOLEAN Cancelled; + UCHAR TID; + USHORT Idx; + UCHAR *pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + FRAME_BAR FrameBar; + UCHAR MaxPeerBufSize; + MAC_TABLE_ENTRY *mac_entry; + + TID = pFrame->BaParm.TID; + Idx = pEntry->BAOriWcidArray[TID]; + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + MaxPeerBufSize = 0; + + /* Start fill in parameters.*/ + if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) + { + MaxPeerBufSize = (UCHAR)pFrame->BaParm.BufSize; + + { + if (MaxPeerBufSize > 0) + MaxPeerBufSize -= 1; + else + MaxPeerBufSize = 0; + + pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, MaxPeerBufSize); + BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); + } + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->amsdu_cap = pFrame->BaParm.AMSDUSupported; + pBAEntry->ORI_BA_Status = Originator_Done; + pAd->BATable.numDoneOriginator ++; + + /* reset sequence number */ + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + /* Set Bitmap flag.*/ + pEntry->TXBAbitmap |= (1<ORIBATimer, &Cancelled); + + pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("%s():TXBAbitmap=%x, AMSDUCap=%d, BAWinSize=%d, TimeOut=%ld\n", + __FUNCTION__, pEntry->TXBAbitmap, pBAEntry->amsdu_cap, + pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); + + /* SEND BAR */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory*/ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n")); + return; + } + + // TODO: shiang, is the mac_entry and pEntry the same one?? + mac_entry = &pAd->MacTab.Content[pBAEntry->Wcid]; +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(mac_entry)) + { +#ifdef MAC_REPEATER_SUPPORT + UINT apidx = mac_entry->wdev_idx; + if (pEntry->bReptCli) + BarHeaderInit(pAd, &FrameBar, mac_entry->Addr, + pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + else +#endif /* MAC_REPEATER_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, mac_entry->Addr, mac_entry->wdev->if_addr); + } + else +#endif /* APCLI_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, mac_entry->Addr, mac_entry->wdev->if_addr); + + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function.*/ + FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton.*/ + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer2); + + if (pBAEntry->ORIBATimer.TimerValue) + RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */ + } + +} + + +BOOLEAN BARecSessionAdd( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN FRAME_ADDBA_REQ *pFrame) +{ + BA_REC_ENTRY *pBAEntry = NULL; + BOOLEAN Status = TRUE, Cancelled; + USHORT Idx; + UCHAR TID, BAWinSize; + + + ASSERT(pEntry); + + /* find TID*/ + TID = pFrame->BaParm.TID; + + BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + + /* Intel patch*/ + if (BAWinSize == 0) + BAWinSize = 64; + + /* get software BA rec array index, Idx*/ + Idx = pEntry->BARecWcidArray[TID]; + + + if (Idx == 0) + { + /* allocate new array entry for the new session*/ + pBAEntry = BATableAllocRecEntry(pAd, &Idx); + } + else + { + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + /* flush all pending reordering mpdus*/ + ba_refresh_reordering_mpdus(pAd, pBAEntry); + } + + DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", + __FUNCTION__, pAd->BATable.numAsRecipient, Idx, + pFrame->BaParm.BufSize, BAWinSize)); + + /* Start fill in parameters.*/ + if (pBAEntry != NULL) + { + ASSERT(pBAEntry->list.qlen == 0); + + pBAEntry->REC_BA_Status = Recipient_HandleRes; + pBAEntry->BAWinSize = BAWinSize; + pBAEntry->Wcid = pEntry->wcid; + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->REC_BA_Status = Recipient_Accept; + /* initial sequence number */ + pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq;*/ + + DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq)); + + if (pEntry->RXBAbitmap & (1<RECBATimer, &Cancelled); + else + RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); + + /* Set Bitmap flag.*/ + pEntry->RXBAbitmap |= (1<BARecWcidArray[TID] = Idx; + pEntry->BADeclineBitmap &= ~(1<wcid, TID); + + DBGPRINT(RT_DEBUG_TRACE, ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", + pEntry->wcid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); + } + else + { + Status = FALSE; + DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", + PRINT_MAC(pEntry->Addr), TID)); + } + return(Status); +} + + +BA_REC_ENTRY *BATableAllocRecEntry(RTMP_ADAPTER *pAd, USHORT *Idx) +{ + int i; + BA_REC_ENTRY *pBAEntry = NULL; + + + NdisAcquireSpinLock(&pAd->BATabLock); + + if (pAd->BATable.numAsRecipient >= (MAX_LEN_OF_BA_REC_TABLE - 1)) + { + DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n", + pAd->BATable.numAsRecipient, (MAX_LEN_OF_BA_REC_TABLE - 1))); + goto done; + } + + /* reserve idx 0 to identify BAWcidArray[TID] as empty*/ + for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry =&pAd->BATable.BARecEntry[i]; + if ((pBAEntry->REC_BA_Status == Recipient_NONE)) + { + /* get one */ + pAd->BATable.numAsRecipient++; + pBAEntry->REC_BA_Status = Recipient_USED; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + + +BA_ORI_ENTRY *BATableAllocOriEntry(RTMP_ADAPTER *pAd, USHORT *Idx) +{ + int i; + BA_ORI_ENTRY *pBAEntry = NULL; + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE - 1)) + goto done; + + /* reserve idx 0 to identify BAWcidArray[TID] as empty*/ + for (i=1; iBATable.BAOriEntry[i]; + if ((pBAEntry->ORI_BA_Status == Originator_NONE)) + { + /* get one */ + pAd->BATable.numAsOriginator++; + pBAEntry->ORI_BA_Status = Originator_USED; + pBAEntry->pAdapter = pAd; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + + +VOID BATableFreeOriEntry(RTMP_ADAPTER *pAd, ULONG Idx) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + return; + + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAEntry->ORI_BA_Status != Originator_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BAOriWcidArray[pBAEntry->TID] = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Wcid = %d, TID = %d\n", __FUNCTION__, pBAEntry->Wcid, pBAEntry->TID)); + + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + pAd->BATable.numDoneOriginator -= 1; + pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); + DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); + /* Erase Bitmap flag.*/ + } + + ASSERT(pAd->BATable.numAsOriginator != 0); + + pAd->BATable.numAsOriginator -= 1; + + pBAEntry->ORI_BA_Status = Originator_NONE; + pBAEntry->Token = 0; + } + NdisReleaseSpinLock(&pAd->BATabLock); +} + + +VOID BATableFreeRecEntry(RTMP_ADAPTER *pAd, ULONG Idx) +{ + BA_REC_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) + return; + + pBAEntry =&pAd->BATable.BARecEntry[Idx]; + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BARecWcidArray[pBAEntry->TID] = 0; + + ASSERT(pAd->BATable.numAsRecipient != 0); + + pAd->BATable.numAsRecipient -= 1; + + pBAEntry->REC_BA_Status = Recipient_NONE; + } + NdisReleaseSpinLock(&pAd->BATabLock); +} + + +VOID BAOriSessionTearDown( + INOUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend) +{ + UINT Idx = 0; + BA_ORI_ENTRY *pBAEntry; + BOOLEAN Cancelled; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).*/ + Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + { + if (bForceSend == TRUE) + { + /* force send specified TID DelBA*/ + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem; + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = ORIGINATOR; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + os_free_mem(NULL, Elem); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__)); + } + } + + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %d, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); + + /* Prepare DelBA action frame and send to the peer.*/ + if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem; + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = pBAEntry->TID; + DelbaReq.Initiator = ORIGINATOR; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + os_free_mem(NULL, Elem); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); + return; + } + } + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + BATableFreeOriEntry(pAd, Idx); + + if (bPassive) + { + /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);*/ + } +} + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive) +{ + ULONG Idx = 0; + BA_REC_ENTRY *pBAEntry; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).*/ + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); + + /* Prepare DelBA action frame and send to the peer.*/ + if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + BOOLEAN Cancelled; + + RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); + + + /* 1. Send DELBA Action Frame*/ + if (bPassive == FALSE) + { + MLME_QUEUE_ELEM *Elem; + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = RECIPIENT; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + os_free_mem(NULL, Elem); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); + return; + } + } + + + + /* 2. Free resource of BA session*/ + /* flush all pending reordering mpdus */ + ba_refresh_reordering_mpdus(pAd, pBAEntry); + + NdisAcquireSpinLock(&pAd->BATabLock); + + /* Erase Bitmap flag.*/ + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + pBAEntry->BAWinSize = 0; + /* Erase Bitmap flag at software mactable*/ + pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID))); + pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; + + RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); + + NdisReleaseSpinLock(&pAd->BATabLock); + + } + + BATableFreeRecEntry(pAd, Idx); +} + + +VOID BASessionTearDownALL(RTMP_ADAPTER *pAd, UCHAR Wcid) +{ + int i; + + for (i=0; ipAdapter; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Do nothing if monitor mode is on*/ + if (MONITOR_ON(pAd)) + return; + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode. */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + + if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) + { + MLME_ADDBA_REQ_STRUCT AddbaReq; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (INFRA_ON(pAd) && + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))) + { + /* In scan progress and have no chance to send out, just re-schedule to another time period */ + RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); + return; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); + COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); + AddbaReq.Wcid = pEntry->wcid; + AddbaReq.TID = pBAEntry->TID; + AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + AddbaReq.TimeOutValue = 0; + AddbaReq.Token = pBAEntry->Token; + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq, 0); + RTMP_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token)); + + pBAEntry->Token++; + RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); + } + else + { + BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); + } +} + + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + ULONG Now32; + + if (pBAEntry == NULL) + return; + + if ((pBAEntry->REC_BA_Status == Recipient_Accept)) + { + NdisGetSystemUpTime(&Now32); + + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) + { + pAd = pBAEntry->pAdapter; + /* flush all pending reordering mpdus */ + ba_refresh_reordering_mpdus(pAd, pBAEntry); + DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32)); + } + } +} + + +VOID PeerAddBAReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Status = 1; + UCHAR pAddr[6]; + FRAME_ADDBA_RSP ADDframe; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PFRAME_ADDBA_REQ pAddreqFrame = NULL; + ULONG FrameLen; + MAC_TABLE_ENTRY *pMacEntry; +#ifdef CONFIG_AP_SUPPORT + INT apidx; +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); + + /*ADDBA Request from unknown peer, ignore this.*/ + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + +#ifdef SMART_MESH_MONITOR +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + To avoid control frames captured by sniffer confusing due to lack of Addr 3 + */ + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + if(!IsValidUnicastToMe(pAd, Elem->Wcid, pAddreqFrame->Hdr.Addr1)) + return; + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_MONITOR */ + + pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); + + if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) + { + + if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) + { + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); + if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) + { +#ifdef PEER_DELBA_TX_ADAPT + Peer_DelBA_Tx_Adapt_Disable(pAd, &pAd->MacTab.Content[Elem->Wcid]); +#endif /* PEER_DELBA_TX_ADAPT */ + Status = 0; + } + else + Status = 38; /* more parameters have invalid values*/ + } + else + { + Status = 37; /* the request has been declined.*/ + } + } + + if (IS_ENTRY_CLIENT(pMacEntry)) + ASSERT(pMacEntry->Sst == SST_ASSOC); + + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + /* 2. Always send back ADDBA Response */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); + return; + } + + NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); + /* 2-1. Prepare ADDBA Response frame.*/ +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (pMacEntry) + { +#ifdef CONFIG_STA_SUPPORT + if (ADHOC_ON(pAd) +#ifdef QOS_DLS_SUPPORT + || (IS_ENTRY_DLS(pMacEntry)) +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || (IS_ENTRY_TDLS(pMacEntry)) +#endif /* DOT11Z_TDLS_SUPPORT || CFG_TDLS_SUPPORT */ + ) + { + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->StaCfg.wdev.if_addr, pAd->CommonCfg.Bssid); + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pMacEntry->wdev->if_addr, pMacEntry->wdev->bssid); + } + } +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pMacEntry)) + { + apidx = pMacEntry->wdev_idx; +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry && pMacEntry->bReptCli) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pMacEntry->MatchReptCliIdx].CurrentAddress, pAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, pAddr); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pMacEntry)) + { + apidx = pMacEntry->wdev_idx; + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.if_addr, pAddr); + } + else +#endif /* WDS_SUPPORT */ + { + apidx = pMacEntry->apidx; + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd) +#ifdef QOS_DLS_SUPPORT + || (IS_ENTRY_DLS(pMacEntry)) +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || (IS_ENTRY_TDLS(pMacEntry)) +#endif /* DOT11Z_TDLS_SUPPORT || CFG_TDLS_SUPPORT */ + ) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->StaCfg.wdev.if_addr, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->StaCfg.wdev.if_addr, pAddr); + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + ADDframe.Category = CATEGORY_BA; + ADDframe.Action = ADDBA_RESP; + ADDframe.Token = pAddreqFrame->Token; + /* What is the Status code?? need to check.*/ + ADDframe.StatusCode = Status; + ADDframe.BaParm.BAPolicy = IMMED_BA; +#ifdef DOT11_VHT_AC + if (pMacEntry && IS_VHT_STA(pMacEntry) && (Status == 0)) + ADDframe.BaParm.AMSDUSupported = pAddreqFrame->BaParm.AMSDUSupported; + else +#endif /* DOT11_VHT_AC */ + ADDframe.BaParm.AMSDUSupported = 0; + +#ifdef WFA_VHT_PF + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + ADDframe.BaParm.AMSDUSupported = 1; +#endif /* WFA_VHT_PF */ + ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; + ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + if (ADDframe.BaParm.BufSize == 0) + ADDframe.BaParm.BufSize = 64; + ADDframe.TimeOutValue = 0; /* pAddreqFrame->TimeOutValue; */ + +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&ADDframe.BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&ADDframe.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); +#endif /* UNALIGNMENT_SUPPORT */ + + ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); + ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_RSP), &ADDframe, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, + ADDframe.BaParm.BufSize)); +} + + +VOID PeerAddBARspAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + PFRAME_ADDBA_RSP pFrame = NULL; + + /*ADDBA Response from unknown peer, ignore this.*/ + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); + + /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);*/ + + if (PeerAddBARspActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) + { + pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); + + DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); + switch (pFrame->StatusCode) + { + case 0: + /* I want a BAsession with this peer as an originator. */ + BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); +#ifdef PEER_DELBA_TX_ADAPT + Peer_DelBA_Tx_Adapt_Disable(pAd, &pAd->MacTab.Content[Elem->Wcid]); +#endif /* PEER_DELBA_TX_ADAPT */ + break; + default: + /* check status == USED ??? */ + BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); + break; + } + /* Rcv Decline StatusCode*/ + if ((pFrame->StatusCode == 37) +#ifdef CONFIG_STA_SUPPORT + || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0)) +#endif /* CONFIG_STA_SUPPORT */ + ) + { + pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<BaParm.TID; + } + } +} + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PFRAME_DELBA_REQ pDelFrame = NULL; + + DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); + /*DELBA Request from unknown peer, ignore this.*/ + if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) + { + pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); + +#ifdef PEER_DELBA_TX_ADAPT + if (pDelFrame->DelbaParm.TID == 0) + Peer_DelBA_Tx_Adapt_Enable(pAd, &pAd->MacTab.Content[Elem->Wcid]); +#endif /* PEER_DELBA_TX_ADAPT */ + + if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); + BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); + /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);*/ + BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); + } + } +} + + +BOOLEAN CntlEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg) +{ + PFRAME_BA_REQ pFrame = pMsg; + PBA_REC_ENTRY pBAEntry; + ULONG Idx; + UCHAR TID; + + TID = (UCHAR)pFrame->BARControl.TID; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID)); + /*hex_dump("BAR", (PCHAR) pFrame, MsgLen);*/ + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) /* 1600B */ + { + DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + + if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) + { + /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.*/ + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); + + if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) + { + /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));*/ + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); + pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); + } + /*ba_refresh_reordering_mpdus(pAd, pBAEntry);*/ + return TRUE; +} + + +/* Description : Send SMPS Action frame If SMPS mode switches. */ +VOID SendSMPSAction(RTMP_ADAPTER *pAd, UCHAR Wcid, UCHAR smps) +{ + struct wifi_dev *wdev; + MAC_TABLE_ENTRY *pEntry; + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_SMPS_ACTION Frame; + ULONG FrameLen; + + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + + if (!VALID_WCID(Wcid)) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("BA - Invalid WCID(%d)\n", Wcid)); + return; + } + + pEntry = &pAd->MacTab.Content[Wcid]; + wdev = pEntry->wdev; + if (!wdev) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("BA - wdev is null\n")); + return; + } + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { +#ifdef MAC_REPEATER_SUPPORT + UINT apidx = pEntry->wdev_idx; + if (pEntry->bReptCli) + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, wdev->bssid); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, wdev->if_addr, wdev->bssid); + } + else +#endif /* APCLI_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, wdev->if_addr, wdev->bssid); + Frame.Category = CATEGORY_HT; + Frame.Action = SMPS_ACTION; + switch (smps) + { + case MMPS_DISABLE: + Frame.smps = 0; + break; + case MMPS_DYNAMIC: + Frame.smps = 3; + break; + case MMPS_STATIC: + Frame.smps = 1; + break; + } + + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_SMPS_ACTION), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("HT - %s( %d ) \n", __FUNCTION__, Frame.smps)); +} + + +#define RADIO_MEASUREMENT_REQUEST_ACTION 0 + +typedef struct GNU_PACKED _BEACON_REQUEST { + UCHAR RegulatoryClass; + UCHAR ChannelNumber; + USHORT RandomInterval; + USHORT MeasurementDuration; + UCHAR MeasurementMode; + UCHAR BSSID[MAC_ADDR_LEN]; + UCHAR ReportingCondition; + UCHAR Threshold; + UCHAR SSIDIE[2]; /* 2 byte*/ +} BEACON_REQUEST; + +typedef struct GNU_PACKED _MEASUREMENT_REQ +{ + UCHAR ID; + UCHAR Length; + UCHAR Token; + UCHAR RequestMode; + UCHAR Type; +} MEASUREMENT_REQ; + + +#ifdef CONFIG_AP_SUPPORT +VOID SendBeaconRequest(RTMP_ADAPTER *pAd, UCHAR Wcid) +{ + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_RM_REQ_ACTION Frame; + ULONG FrameLen; + BEACON_REQUEST BeaconReq; + MEASUREMENT_REQ MeasureReg; + UCHAR apidx; + + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid])) + return; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("Radio - SendBeaconRequest() allocate memory failed \n")); + return; + } + apidx = pAd->MacTab.Content[Wcid].apidx; + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + + Frame.Category = CATEGORY_RM; + Frame.Action = RADIO_MEASUREMENT_REQUEST_ACTION /*RRM_MEASURE_REQ*/; + Frame.Token = 1; + Frame.Repetition = 0; /* executed once*/ + + BeaconReq.RegulatoryClass = 32; /* ?????*/ + BeaconReq.ChannelNumber = 255; /* all channels*/ + BeaconReq.RandomInterval = 0; + BeaconReq.MeasurementDuration = 10; /* 10 TU*/ + BeaconReq.MeasurementMode = 1; /* Active mode */ + COPY_MAC_ADDR(BeaconReq.BSSID, BROADCAST_ADDR); + BeaconReq.ReportingCondition = 254; /* report not necesssary*/ + BeaconReq.Threshold = 0; /* minimum RCPI*/ + BeaconReq.SSIDIE[0] = 0; + BeaconReq.SSIDIE[1] = 0; /* wildcard SSID zero length */ + + + MeasureReg.ID = IE_MEASUREMENT_REQUEST; + MeasureReg.Token = 0; + MeasureReg.RequestMode = 0; + MeasureReg.Type = 5; /* Beacon Request*/ + MeasureReg.Length = sizeof(MEASUREMENT_REQ)+sizeof(BEACON_REQUEST)-2; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_RM_REQ_ACTION), &Frame, + sizeof(MEASUREMENT_REQ), &MeasureReg, + sizeof(BEACON_REQUEST), &BeaconReq, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE,("Radio - SendBeaconRequest\n")); +} +#endif /* CONFIG_AP_SUPPORT */ + + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPkt; + UCHAR Header802_3[LENGTH_802_3]; + +/* + 1. get 802.3 Header + 2. remove LLC + a. pointer pRxBlk->pData to payload + b. modify pRxBlk->DataSize +*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (IS_PKT_OPMODE_AP(pRxBlk)) + { + RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); + } + else + { + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + ASSERT(pRxBlk->pRxPacket); + + pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + RTMP_OS_PKT_INIT(pRxBlk->pRxPacket, + get_netdev_from_bssid(pAd, FromWhichBSSID), + pRxBlk->pData, pRxBlk->DataSize); + + + /* copy 802.3 header, if necessary*/ + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* maybe insert VLAN tag to the received packet */ + UCHAR VLAN_Size = 0; + UCHAR *data_p; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + + /* VLAN related */ + MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); + +#ifdef WDS_VLAN_SUPPORT + if (VLAN_VID == 0) /* maybe WDS packet */ + WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#endif /* WDS_VLAN_SUPPORT */ + + if (VLAN_VID != 0) + VLAN_Size = LENGTH_802_1Q; + + data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3+VLAN_Size); + RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority, + Header802_3, LENGTH_802_3, + data_p, FromWhichBSSID, TPID); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef LINUX + UCHAR *data_p; + data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3); + NdisMoveMemory(data_p, Header802_3, LENGTH_802_3); +#endif + } +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ + do \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ + { \ + Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ + { \ + Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else \ + { \ + Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + } while (0); + +#ifdef HDR_TRANS_SUPPORT +#define INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(_pAd, _pRxBlk, _fromWhichBSSID) \ + do \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ + { \ + Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ + { \ + Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else \ + { \ + Indicate_Legacy_Packet_Hdr_Trns(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + } while (0); +#endif /* HDR_TRANS_SUPPORT */ + + +static VOID ba_enqueue_reordering_packet( + IN RTMP_ADAPTER *pAd, + IN BA_REC_ENTRY *pBAEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + struct reordering_mpdu *mpdu_blk; + UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; + + mpdu_blk = ba_mpdu_blk_alloc(pAd); + if ((mpdu_blk != NULL) && + (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) + { + /* Write RxD buffer address & allocated buffer length */ + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + mpdu_blk->Sequence = Sequence; + mpdu_blk->OpMode = pRxBlk->OpMode; + + mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); + + convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + + /* it is necessary for reordering packet to record + which BSS it come from + */ + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + + mpdu_blk->pPacket = pRxBlk->pRxPacket; + + if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) + { + /* had been already within reordering list don't indicate */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", + pBAEntry->list.qlen)); + /* + * flush all pending reordering mpdus + * and receving mpdu to upper layer + * make tcp/ip to take care reordering mechanism + */ + /*ba_refresh_reordering_mpdus(pAd, pBAEntry);*/ + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + } +} + + +#ifdef HDR_TRANS_SUPPORT +static VOID ba_enqueue_reordering_packet_hdr_trns( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + struct reordering_mpdu *mpdu_blk; + UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; + + mpdu_blk = ba_mpdu_blk_alloc(pAd); + if ((mpdu_blk != NULL) && + (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) + { + + /* Write RxD buffer address & allocated buffer length */ + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + mpdu_blk->Sequence = Sequence; + mpdu_blk->OpMode = pRxBlk->OpMode; + + mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); + + convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); + + + RTMP_OS_PKT_INIT(pRxBlk->pRxPacket, + get_netdev_from_bssid(pAd, FromWhichBSSID), + pRxBlk->pTransData, pRxBlk->TransDataSize); + + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + + /* it is necessary for reordering packet to record + which BSS it come from + */ + //RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + + + mpdu_blk->pPacket = pRxBlk->pRxPacket; + + if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) + { + /* had been already within reordering list don't indicate */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", + pBAEntry->list.qlen)); + /* + * flush all pending reordering mpdus + * and receving mpdu to upper layer + * make tcp/ip to take care reordering mechanism + */ + /*ba_refresh_reordering_mpdus(pAd, pBAEntry);*/ + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID); + } +} +#endif /* HDR_TRANS_SUPPORT */ + + +/* + ========================================================================== + Description: + Indicate this packet to upper layer or put it into reordering buffer + + Parametrs: + pRxBlk : carry necessary packet info 802.11 format + FromWhichBSSID : the packet received from which BSS + + Return : + none + + Note : + the packet queued into reordering buffer need to cover to 802.3 format + or pre_AMSDU format + ========================================================================== +*/ +VOID Indicate_AMPDU_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR FromWhichBSSID) +{ + USHORT Idx; + PBA_REC_ENTRY pBAEntry = NULL; + UINT16 Sequence = pRxBlk->pHeader->Sequence; + ULONG Now32; + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) + { + static int err_size; + + err_size++; + if (err_size > 20) { + DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize)); + hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24); + hex_dump("Payload", pRxBlk->pData, 64); + err_size = 0; + } + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + { + Idx = pAd->MacTab.Content[pRxBlk->wcid].BARecWcidArray[pRxBlk->TID]; + if (Idx == 0) + { + /* Rec BA Session had been torn down */ + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; + } + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + /* impossible !!! release packet*/ + ASSERT(0); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(pBAEntry); + + /* update last rx time*/ + NdisGetSystemUpTime(&Now32); + + pBAEntry->rcvSeq = Sequence; + + + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + pBAEntry->LastIndSeqAtTimer = Now32; + + + /* Reset Last Indicate Sequence*/ + if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) + { + ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); + + /* reset rcv sequence of BA session */ + pBAEntry->LastIndSeq = Sequence; + pBAEntry->LastIndSeqAtTimer = Now32; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; + } + + + /* I. Check if in order.*/ + if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + USHORT LastIndSeq; + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (LastIndSeq != RESET_RCV_SEQ) + pBAEntry->LastIndSeq = LastIndSeq; + + pBAEntry->LastIndSeqAtTimer = Now32; + } + + /* II. Drop Duplicated Packet*/ + else if (Sequence == pBAEntry->LastIndSeq) + { + + pBAEntry->nDropPacket++; +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU + if (pRxBlk->CriticalPkt) + { + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + }else +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + + } + + /* III. Drop Old Received Packet*/ + else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + + pBAEntry->nDropPacket++; +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU + if (pRxBlk->CriticalPkt) + { + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + } else +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + + } + + /* IV. Receive Sequence within Window Size*/ + else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) + { + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + } + + /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer*/ + else + { + LONG WinStartSeq, TmpSeq; + + + TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; + if (TmpSeq < 0) + TmpSeq = (MAXSEQ+1) + TmpSeq; + + WinStartSeq = (TmpSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); + pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */ + + pBAEntry->LastIndSeqAtTimer = Now32; + + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + + TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (TmpSeq != RESET_RCV_SEQ) + pBAEntry->LastIndSeq = TmpSeq; + } +} + + +#ifdef HDR_TRANS_SUPPORT +VOID Indicate_AMPDU_Packet_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + USHORT Idx; + PBA_REC_ENTRY pBAEntry = NULL; + UINT16 Sequence = pRxBlk->pHeader->Sequence; + ULONG Now32; + UCHAR Wcid = pRxBlk->wcid; + UCHAR TID = pRxBlk->TID; + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->TransDataSize > 1514)) + { + static int err_size; + + err_size++; + if (err_size > 20) { + DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize)); + hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24); + hex_dump("Payload", pRxBlk->pData, 64); + err_size = 0; + } + + /* release packet*/ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) + { + /* Rec BA Session had been torn down */ + INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID); + return; + } + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + /* impossible !!!*/ + ASSERT(0); + /* release packet*/ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(pBAEntry); + + /* update last rx time*/ + NdisGetSystemUpTime(&Now32); + + pBAEntry->rcvSeq = Sequence; + + + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + pBAEntry->LastIndSeqAtTimer = Now32; + + + /* Reset Last Indicate Sequence*/ + /* */ + if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) + { + ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); + + /* reset rcv sequence of BA session */ + pBAEntry->LastIndSeq = Sequence; + pBAEntry->LastIndSeqAtTimer = Now32; + INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID); + return; + } + + /* I. Check if in order.*/ + if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + USHORT LastIndSeq; + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID); + LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (LastIndSeq != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = LastIndSeq; + } + pBAEntry->LastIndSeqAtTimer = Now32; + } + + /* II. Drop Duplicated Packet*/ + else if (Sequence == pBAEntry->LastIndSeq) + { + + /* drop and release packet*/ + pBAEntry->nDropPacket++; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + + /* III. Drop Old Received Packet*/ + else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + + /* drop and release packet*/ + pBAEntry->nDropPacket++; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + + /* IV. Receive Sequence within Window Size*/ + else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) + { + ba_enqueue_reordering_packet_hdr_trns(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + } + + /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer*/ + else + { + LONG WinStartSeq, TmpSeq; + + + TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; + if (TmpSeq < 0) + { + TmpSeq = (MAXSEQ+1) + TmpSeq; + } + WinStartSeq = (TmpSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); + pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */ + + pBAEntry->LastIndSeqAtTimer = Now32; + + ba_enqueue_reordering_packet_hdr_trns(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + + TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (TmpSeq != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = TmpSeq; + } + } +} +#endif /* HDR_TRANS_SUPPORT */ + + +VOID BaReOrderingBufferMaintain(RTMP_ADAPTER *pAd) +{ + ULONG Now32; + UCHAR Wcid; + USHORT Idx; + UCHAR TID; + PBA_REC_ENTRY pBAEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + /* update last rx time*/ + NdisGetSystemUpTime(&Now32); + + for (Wcid = 1; Wcid < MAX_LEN_OF_MAC_TABLE; Wcid++) + { + pEntry = &pAd->MacTab.Content[Wcid]; + if (IS_ENTRY_NONE(pEntry)) + continue; + + for (TID= 0; TID < NUM_OF_TID; TID++) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + } + } +} + + +#ifdef PEER_DELBA_TX_ADAPT +VOID Peer_DelBA_Tx_Adapt_Init( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + pEntry->bPeerDelBaTxAdaptEn = 0; + RTMPInitTimer(pAd, &pEntry->DelBA_tx_AdaptTimer, GET_TIMER_FUNCTION(PeerDelBATxAdaptTimeOut), pEntry, FALSE); +} + +static VOID Peer_DelBA_Tx_Adapt_Enable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ +#ifdef MCS_LUT_SUPPORT + if ((pAd->CommonCfg.bBADecline == TRUE) || + (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) + { + /* we should not do this if bBADecline is TRUE or RGD is ON */ + return; + } + + if(!RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) || !(pEntry->wcid < 128)) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! This chip does not support HW Tx rate lookup.\n", + __FUNCTION__)); + return; + } + + if (pEntry) + { + UINT32 MacReg = 0; + BOOLEAN Cancelled; + + pEntry->bPeerDelBaTxAdaptEn = 1; + RTMPCancelTimer(&pEntry->DelBA_tx_AdaptTimer, &Cancelled); + + /* Enable Tx Mac look up table */ + RTMP_IO_READ32(pAd, TX_FBK_LIMIT, &MacReg); + if ((MacReg & (1 << 18)) == 0) { + MacReg |= (1 << 18); + RTMP_IO_WRITE32(pAd, TX_FBK_LIMIT, MacReg); + } + + /* OFDM54 / BW20 / LGI / no STBC/ Legacy OFDM */ + set_lut_phy_rate(pAd, pEntry->Aid, 7, 0, 0, 0, 1); + RTMPSetTimer(&pEntry->DelBA_tx_AdaptTimer, 1000); /* 1000ms */ + DBGPRINT(RT_DEBUG_TRACE, + ("%s():MacReg = 0x%08x, bPeerDelBaTxAdaptEn = 0x%x\n", + __FUNCTION__, MacReg, pEntry->bPeerDelBaTxAdaptEn)); + } +#endif /* MCS_LUT_SUPPORT */ +} + +static VOID Peer_DelBA_Tx_Adapt_Disable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ +#ifdef MCS_LUT_SUPPORT + if ((pAd == NULL) || (pEntry == NULL)) { + DBGPRINT(RT_DEBUG_WARN, ("%s(): Warning! Null pointer.\n", __FUNCTION__)); + return; + } + + if(!RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) || !(pEntry->wcid < 128)) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! This chip does not support HW Tx rate lookup.\n", + __FUNCTION__)); + return; + } + + if (pEntry && pEntry->bPeerDelBaTxAdaptEn) { + BOOLEAN Cancelled; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + UINT32 MacReg = 0; + /* Disable Tx Mac look up table (Ressume original setting) */ + RTMP_IO_READ32(pAd, TX_FBK_LIMIT, &MacReg); + MacReg &= ~(1 << 18); + RTMP_IO_WRITE32(pAd, TX_FBK_LIMIT, MacReg); + DBGPRINT(RT_DEBUG_TRACE, + ("%s():TX_FBK_LIMIT = 0x%08x\n", + __FUNCTION__, MacReg)); + } +#endif + + pEntry->bPeerDelBaTxAdaptEn = 0; + RTMPCancelTimer(&pEntry->DelBA_tx_AdaptTimer, &Cancelled); + asic_mcs_lut_update(pAd, pEntry); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s():bPeerDelBaTxAdaptEn = 0x%x\n", + __FUNCTION__, pEntry->bPeerDelBaTxAdaptEn)); + } +#endif /* MCS_LUT_SUPPORT */ +} + +VOID PeerDelBATxAdaptTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PMAC_TABLE_ENTRY pEntry = (PMAC_TABLE_ENTRY) FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("%s()\n", __FUNCTION__)); + + /* Disable Tx Mac look up table (Ressume original setting) */ + Peer_DelBA_Tx_Adapt_Disable(pEntry->pAd, pEntry); +} +#endif /* PEER_DELBA_TX_ADAPT */ +#endif /* DOT11_N_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/client_wds.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/client_wds.c new file mode 100644 index 000000000..b5edbfc31 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/client_wds.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_aes.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_aes.c new file mode 100644 index 000000000..734482d36 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_aes.c @@ -0,0 +1,1149 @@ +/* + *************************************************************************** + * 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_aes.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 02-25-02 Initial +*/ + +#include "rt_config.h" + + + +/*****************************/ +/******** SBOX Table *********/ +/*****************************/ + +UCHAR SboxTable[256] = +{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<4; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<16; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +UCHAR RTMPCkipSbox( + IN UCHAR a) +{ + return SboxTable[(int)a]; +} + +VOID next_key( + IN PUCHAR key, + IN INT round) +{ + UCHAR rcon; + UCHAR sbox_key[4]; + UCHAR rcon_table[12] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x36, 0x36 + }; + + sbox_key[0] = RTMPCkipSbox(key[13]); + sbox_key[1] = RTMPCkipSbox(key[14]); + sbox_key[2] = RTMPCkipSbox(key[15]); + sbox_key[3] = RTMPCkipSbox(key[12]); + + rcon = rcon_table[round]; + + xor_32(&key[0], sbox_key, &key[0]); + key[0] = key[0] ^ rcon; + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + + for (i=0; i< 16; i++) + { + out[i] = RTMPCkipSbox(in[i]); + } +} + +/************************************/ +/* bitwise_xor() */ +/* A 128 bit, bitwise exclusive or */ +/************************************/ + +void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) +{ + int i; + for (i=0; i<16; i++) + { + out[i] = ina[i] ^ inb[i]; + } +} + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + UCHAR add1b[4]; + UCHAR add1bf7[4]; + UCHAR rotl[4]; + UCHAR swap_halfs[4]; + UCHAR andf7[4]; + UCHAR rotr[4]; + UCHAR temp[4]; + UCHAR tempb[4]; + + for (i=0 ; i<4; i++) + { + if ((in[i] & 0x80)== 0x80) + add1b[i] = 0x1b; + else + add1b[i] = 0x00; + } + + swap_halfs[0] = in[2]; /* Swap halfs */ + swap_halfs[1] = in[3]; + swap_halfs[2] = in[0]; + swap_halfs[3] = in[1]; + + rotl[0] = in[3]; /* Rotate left 8 bits */ + rotl[1] = in[0]; + rotl[2] = in[1]; + rotl[3] = in[2]; + + andf7[0] = in[0] & 0x7f; + andf7[1] = in[1] & 0x7f; + andf7[2] = in[2] & 0x7f; + andf7[3] = in[3] & 0x7f; + + for (i = 3; i>0; i--) /* logical shift left 1 bit */ + { + andf7[i] = andf7[i] << 1; + if ((andf7[i-1] & 0x80) == 0x80) + { + andf7[i] = (andf7[i] | 0x01); + } + } + andf7[0] = andf7[0] << 1; + andf7[0] = andf7[0] & 0xfe; + + xor_32(add1b, andf7, add1bf7); + + xor_32(in, add1bf7, rotr); + + temp[0] = rotr[0]; /* Rotate right 8 bits */ + rotr[0] = rotr[1]; + rotr[1] = rotr[2]; + rotr[2] = rotr[3]; + rotr[3] = temp[0]; + + xor_32(add1bf7, rotr, temp); + xor_32(swap_halfs, rotl,tempb); + xor_32(temp, tempb, out); +} + + +/************************************************/ +/* construct_mic_header1() */ +/* Builds the first MIC header block from */ +/* header fields. */ +/************************************************/ + +void construct_mic_header1( + unsigned char *mic_header1, + int header_length, + unsigned char *mpdu) +{ + mic_header1[0] = (unsigned char)((header_length - 2) / 256); + mic_header1[1] = (unsigned char)((header_length - 2) % 256); + mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ + mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ + mic_header1[4] = mpdu[4]; /* A1 */ + mic_header1[5] = mpdu[5]; + mic_header1[6] = mpdu[6]; + mic_header1[7] = mpdu[7]; + mic_header1[8] = mpdu[8]; + mic_header1[9] = mpdu[9]; + mic_header1[10] = mpdu[10]; /* A2 */ + mic_header1[11] = mpdu[11]; + mic_header1[12] = mpdu[12]; + mic_header1[13] = mpdu[13]; + mic_header1[14] = mpdu[14]; + mic_header1[15] = mpdu[15]; +} + +/************************************************/ +/* construct_mic_header2() */ +/* Builds the last MIC header block from */ +/* header fields. */ +/************************************************/ + +void construct_mic_header2( + unsigned char *mic_header2, + unsigned char *mpdu, + int a4_exists, + int qc_exists) +{ + int i; + + for (i = 0; i<16; i++) mic_header2[i]=0x00; + + mic_header2[0] = mpdu[16]; /* A3 */ + mic_header2[1] = mpdu[17]; + mic_header2[2] = mpdu[18]; + mic_header2[3] = mpdu[19]; + mic_header2[4] = mpdu[20]; + mic_header2[5] = mpdu[21]; + + /* In Sequence Control field, mute sequence numer bits (12-bit) */ + mic_header2[6] = mpdu[22] & 0x0f; /* SC */ + mic_header2[7] = 0x00; /* mpdu[23]; */ + + if ((!qc_exists) & a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + } + + if (qc_exists && (!a4_exists)) + { + mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ + mic_header2[9] = mpdu[25] & 0x00; + } + + if (qc_exists && a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + mic_header2[14] = mpdu[30] & 0x0f; + mic_header2[15] = mpdu[31] & 0x00; + } +} + + +/************************************************/ +/* construct_mic_iv() */ +/* Builds the MIC IV from header fields and PN */ +/************************************************/ + +void construct_mic_iv( + unsigned char *mic_iv, + int qc_exists, + int a4_exists, + unsigned char *mpdu, + unsigned int payload_length, + unsigned char *pn_vector) +{ + int i; + + mic_iv[0] = 0x59; + if (qc_exists && a4_exists) + mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ + if (qc_exists && !a4_exists) + mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ + if (!qc_exists) + mic_iv[1] = 0x00; + for (i = 2; i < 8; i++) + mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ +#endif + i = (payload_length / 256); + i = (payload_length % 256); + mic_iv[14] = (unsigned char) (payload_length / 256); + mic_iv[15] = (unsigned char) (payload_length % 256); + +} + +/****************************************/ +/* aes128k128d() */ +/* Performs a 128 bit AES encrypt with */ +/* 128 bit data. */ +/****************************************/ +void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext) +{ + int round; + int i; + unsigned char intermediatea[16]; + unsigned char intermediateb[16]; + unsigned char round_key[16]; + + for(i=0; i<16; i++) round_key[i] = key[i]; + + for (round = 0; round < 11; round++) + { + if (round == 0) + { + xor_128(round_key, data, ciphertext); + next_key(round_key, round); + } + else if (round == 10) + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + xor_128(intermediateb, round_key, ciphertext); + } + else /* 1 - 9 */ + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + mix_column(&intermediateb[0], &intermediatea[0]); + mix_column(&intermediateb[4], &intermediatea[4]); + mix_column(&intermediateb[8], &intermediatea[8]); + mix_column(&intermediateb[12], &intermediatea[12]); + xor_128(intermediatea, round_key, ciphertext); + next_key(round_key, round); + } + } + +} + +void construct_ctr_preload( + unsigned char *ctr_preload, + int a4_exists, + int qc_exists, + unsigned char *mpdu, + unsigned char *pn_vector, + int c) +{ + + int i = 0; + for (i=0; i<16; i++) ctr_preload[i] = 0x00; + i = 0; + + ctr_preload[0] = 0x01; /* flag */ + if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ + if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; + + for (i = 2; i < 8; i++) + ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ +#endif + ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */ + ctr_preload[15] = (unsigned char) (c % 256); + +} + +BOOLEAN RTMPSoftDecryptAES( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pWpaKey) +{ + UINT HeaderLen; + UCHAR PN[6]; + UINT payload_len; + UINT num_blocks; + UINT payload_remainder; + UCHAR fc0; + UCHAR fc1; + UINT frame_subtype; + UINT from_ds; + UINT to_ds; + INT a4_exists; + INT qc_exists; + UCHAR aes_out[16]; + int payload_index; + UINT i; + UCHAR ctr_preload[16]; + UCHAR chain_buffer[16]; + UCHAR padded_buffer[16]; + UCHAR mic_iv[16]; + UCHAR mic_header1[16]; + UCHAR mic_header2[16]; + UCHAR MIC[8]; + UCHAR TrailMIC[8]; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + fc0 = *pData; + fc1 = *(pData + 1); + + frame_subtype = ((fc0 >> 4) & 0x0f); + + from_ds = (fc1 & 0x2) >> 1; + to_ds = (fc1 & 0x1); + + a4_exists = (from_ds & to_ds); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || + (frame_subtype == 0x0b) + ); + + HeaderLen = 24; + + if (a4_exists) + HeaderLen += 6; + + if (qc_exists) + HeaderLen += 2; + + if (pWpaKey->KeyLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(the Length can not be 0)\n")); + return FALSE; + } + + PN[0] = *(pData+ HeaderLen); + PN[1] = *(pData+ HeaderLen + 1); + PN[2] = *(pData+ HeaderLen + 4); + PN[3] = *(pData+ HeaderLen + 5); + PN[4] = *(pData+ HeaderLen + 6); + PN[5] = *(pData+ HeaderLen + 7); + + payload_len = DataByteCnt - HeaderLen - 8 - 8; /* 8 bytes for CCMP header , 8 bytes for MIC*/ + payload_remainder = (payload_len) % 16; + num_blocks = (payload_len) / 16; + + + + /* Find start of payload*/ + payload_index = HeaderLen + 8; /*IV+EIV*/ + + for (i=0; i< num_blocks; i++) + { + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + i+1 ); + + aes128k128d(pWpaKey->Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, pData + payload_index, chain_buffer); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16); + payload_index += 16; + } + + + /* If there is a short final block, then pad it*/ + /* encrypt it and copy the unpadded part back */ + + if (payload_remainder > 0) + { + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + num_blocks + 1); + + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + + aes128k128d(pWpaKey->Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder); + payload_index += payload_remainder; + } + + + /* Descrypt the MIC*/ + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + 0); + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, 8); + + aes128k128d(pWpaKey->Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + + NdisMoveMemory(TrailMIC, chain_buffer, 8); + + + + /* Calculate MIC*/ + + + /*Force the protected frame bit on*/ + *(pData + 1) = *(pData + 1) | 0x40; + + /* Find start of payload*/ + /* Because the CCMP header has been removed*/ + payload_index = HeaderLen; + + construct_mic_iv( + mic_iv, + qc_exists, + a4_exists, + pData, + payload_len, + PN); + + construct_mic_header1( + mic_header1, + HeaderLen, + pData); + + construct_mic_header2( + mic_header2, + pData, + a4_exists, + qc_exists); + + aes128k128d(pWpaKey->Key, mic_iv, aes_out); + bitwise_xor(aes_out, mic_header1, chain_buffer); + aes128k128d(pWpaKey->Key, chain_buffer, aes_out); + bitwise_xor(aes_out, mic_header2, chain_buffer); + aes128k128d(pWpaKey->Key, chain_buffer, aes_out); + + /* iterate through each 16 byte payload block */ + for (i = 0; i < num_blocks; i++) + { + bitwise_xor(aes_out, pData + payload_index, chain_buffer); + payload_index += 16; + aes128k128d(pWpaKey->Key, chain_buffer, aes_out); + } + + /* Add on the final payload block if it needs padding */ + if (payload_remainder > 0) + { + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + aes128k128d(pWpaKey->Key, chain_buffer, aes_out); + } + + /* aes_out contains padded mic, discard most significant*/ + /* 8 bytes to generate 64 bit MIC*/ + for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i]; + + if (!NdisEqualMemory(MIC, TrailMIC, 8)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); /* MIC error. */ + return FALSE; + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Construct AAD of CCMP. + + Arguments: + + Return Value: + + Note: + It's described in IEEE Std 802.11-2007. + The AAD is constructed from the MPDU header. + + ======================================================================== +*/ +VOID RTMPConstructCCMPAAD( + IN PUCHAR pHdr, + IN BOOLEAN isDataFrame, + IN UINT8 a4_exists, + IN UINT8 qc_exists, + OUT UCHAR *aad_hdr, + OUT UINT *aad_len) +{ + UINT len = 0; + + /* Frame control - + Subtype bits (bits 4 5 6) in a Data MPDU masked to 0 + Retry bit (bit 11) masked to 0 + PwrMgt bit (bit 12) masked to 0 + MoreData bit (bit 13) masked to 0 + Protected Frame bit (bit 14) always set to 1 */ + if (isDataFrame) + aad_hdr[0] = (*pHdr) & 0x8f; + else + aad_hdr[0] = (*pHdr); + aad_hdr[1] = (*(pHdr + 1)) & 0xc7; + aad_hdr[1] = aad_hdr[1] | 0x40; + len = 2; + + /* Append Addr 1, 2 & 3 */ + NdisMoveMemory(&aad_hdr[len], pHdr + 4, 3 * MAC_ADDR_LEN); + len += (3 * MAC_ADDR_LEN); + + /* SC - + MPDU Sequence Control field, with the Sequence Number + subfield (bits 4-15 of the Sequence Control field) + masked to 0. The Fragment Number subfield is not modified. */ + aad_hdr[len] = (*(pHdr + 22)) & 0x0f; + aad_hdr[len + 1] = 0x00; + len += 2; + + + /* Append the Addr4 field if present. */ + if (a4_exists) + { + NdisMoveMemory(&aad_hdr[len], pHdr + 24, MAC_ADDR_LEN); + len += MAC_ADDR_LEN; + } + + /* QC - + QoS Control field, if present, a 2-octet field that includes + the MSDU priority. The QC TID field is used in the + construction of the AAD and the remaining QC fields are + set to 0 for the AAD calculation (bits 4 to 15 are set to 0). */ + if (qc_exists & a4_exists) + { + aad_hdr[len] = (*(pHdr + 30)) & 0x0f; /* Qos_TC */ + aad_hdr[len + 1] = 0x00; + len += 2; + } + else if (qc_exists & !a4_exists) + { + aad_hdr[len] = (*(pHdr + 24)) & 0x0f; /* Qos_TC */ + aad_hdr[len + 1] = 0x00; + len += 2; + } + + *aad_len = len; +} + +/* + ======================================================================== + + Routine Description: + Construct NONCE header of CCMP. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPConstructCCMPNonce( + IN PUCHAR pHdr, + IN UINT8 a4_exists, + IN UINT8 qc_exists, + IN BOOLEAN isMgmtFrame, + IN UCHAR *pn, + OUT UCHAR *nonce_hdr, + OUT UINT *nonce_hdr_len) +{ + UINT n_offset = 0; + INT i; + + /* Decide the Priority Octet + The Priority sub-field of the Nonce Flags field shall + be set to the fixed value 0 when there is no QC field + present in the MPDU header. When the QC field is present, + bits 0 to 3 of the Priority field shall be set to the + value of the QC TID (bits 0 to 3 of the QC field).*/ + if (qc_exists && a4_exists) + nonce_hdr[0] = (*(pHdr + 30)) & 0x0f; + if (qc_exists && !a4_exists) + nonce_hdr[0] = (*(pHdr + 24)) & 0x0f; + +#ifdef DOT11W_PMF_SUPPORT + /* When Management Frame Protection is negotiated, the Management + field of the Nonce Flags field shall be set to 1 if the Type + field of the Frame Control field is 00 (Management frame); otherwise it + is set to 0. */ + if (isMgmtFrame) + nonce_hdr[0] = nonce_hdr[0] | 0x10; +#endif /* DOT11W_PMF_SUPPORT */ + n_offset += 1; + + /* Fill in MPDU Address A2 field */ + NdisMoveMemory(&nonce_hdr[n_offset], pHdr + 10, MAC_ADDR_LEN); + n_offset += MAC_ADDR_LEN; + + /* Fill in the PN. The PN field occupies octets 7V12. + The octets of PN shall be ordered so that PN0 is at octet index 12 + and PN5 is at octet index 7. */ + for (i = 0; i < 6; i++) + nonce_hdr[n_offset + i] = pn[5 - i]; + n_offset += LEN_PN; + + *nonce_hdr_len = n_offset; + +} + +/* + ======================================================================== + + Routine Description: + Construct CCMP header. + + Arguments: + + Return Value: + + Note: + It's a 8-octets header. + + ======================================================================== +*/ +VOID RTMPConstructCCMPHdr( + IN UINT8 key_idx, + IN UCHAR *pn, + OUT UCHAR *ccmp_hdr) +{ + NdisZeroMemory(ccmp_hdr, LEN_CCMP_HDR); + + ccmp_hdr[0] = pn[0]; + ccmp_hdr[1] = pn[1]; + ccmp_hdr[3] = (key_idx <<6) | 0x20; + ccmp_hdr[4] = pn[2]; + ccmp_hdr[5] = pn[3]; + ccmp_hdr[6] = pn[4]; + ccmp_hdr[7] = pn[5]; +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftEncryptCCMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN PUCHAR pIV, + IN PUCHAR pKey, + INOUT PUCHAR pData, + IN UINT32 DataLen) +{ + UINT8 frame_type, frame_subtype; + UINT8 from_ds, to_ds; + UINT8 a4_exists, qc_exists; + UINT8 aad_hdr[30]; + UINT aad_len = 0; + UINT8 nonce_hdr[13]; + UINT32 nonce_hdr_len = 0; + UINT32 out_len = DataLen + 8; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + /* Initial variable */ + NdisZeroMemory(aad_hdr, 30); + NdisZeroMemory(nonce_hdr, 13); + + /* Indicate type and subtype of Frame Control field */ + frame_type = (((*pHdr) >> 2) & 0x03); + frame_subtype = (((*pHdr) >> 4) & 0x0f); + + /* Indicate the fromDS and ToDS */ + from_ds = ((*(pHdr + 1)) & 0x2) >> 1; + to_ds = ((*(pHdr + 1)) & 0x1); + + /* decide if the Address 4 exist or QoS exist */ + a4_exists = (from_ds & to_ds); + qc_exists = 0; + if (frame_type == FC_TYPE_DATA) + { + qc_exists = ((frame_subtype == SUBTYPE_QDATA) || + (frame_subtype == SUBTYPE_QDATA_CFACK) || + (frame_subtype == SUBTYPE_QDATA_CFPOLL) || + (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL)); + } + + /* Construct AAD header */ + RTMPConstructCCMPAAD(pHdr, + (frame_type == FC_TYPE_DATA), + a4_exists, + qc_exists, + aad_hdr, + &aad_len); + + /* Construct NONCE header */ + RTMPConstructCCMPNonce(pHdr, + a4_exists, + qc_exists, + (frame_type == FC_TYPE_MGMT), + pIV, + nonce_hdr, + &nonce_hdr_len); + + /* CCM originator processing - + Use the temporal key, AAD, nonce, and MPDU data to + form the cipher text and MIC. */ + if (AES_CCM_Encrypt(pData, DataLen, + pKey, 16, + nonce_hdr, nonce_hdr_len, + aad_hdr, aad_len, LEN_CCMP_MIC, + pData, &out_len)) + return FALSE; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + return TRUE; +} + +/* + ======================================================================== + + Routine Description: + Decrypt data with CCMP. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftDecryptCCMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataLen) +{ + UINT8 frame_type, frame_subtype; + UINT8 from_ds, to_ds; + UINT8 a4_exists, qc_exists; + UINT8 aad_hdr[30]; + UINT aad_len = 0; + UINT8 pn[LEN_PN]; + PUCHAR cipherData_ptr; + UINT32 cipherData_len; + UINT8 nonce_hdr[13]; + UINT32 nonce_hdr_len = 0; + UINT32 out_len = *DataLen; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + /* Check the key is valid */ + if (pKey->KeyLen == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is not available !\n", __FUNCTION__)); + return FALSE; + } + + /* Initial variable */ + NdisZeroMemory(aad_hdr, 30); + NdisZeroMemory(nonce_hdr, 13); + + /* Indicate type and subtype of Frame Control field */ + frame_type = (((*pHdr) >> 2) & 0x03); + frame_subtype = (((*pHdr) >> 4) & 0x0f); + + /* Indicate the fromDS and ToDS */ + from_ds = ((*(pHdr + 1)) & 0x2) >> 1; + to_ds = ((*(pHdr + 1)) & 0x1); + + /* decide if the Address 4 exist or QoS exist */ + a4_exists = (from_ds & to_ds); + qc_exists = 0; + if (frame_type == FC_TYPE_DATA) + { + qc_exists = ((frame_subtype == SUBTYPE_QDATA) || + (frame_subtype == SUBTYPE_QDATA_CFACK) || + (frame_subtype == SUBTYPE_QDATA_CFPOLL) || + (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL)); + } + + /* Extract PN and from CCMP header */ + pn[0] = pData[0]; + pn[1] = pData[1]; + pn[2] = pData[4]; + pn[3] = pData[5]; + pn[4] = pData[6]; + pn[5] = pData[7]; + + /* skip ccmp header */ + cipherData_ptr = pData + LEN_CCMP_HDR; + cipherData_len = *DataLen - LEN_CCMP_HDR; + + /*skip payload length is zero*/ + if ((*DataLen ) <= LEN_CCMP_HDR) + return FALSE; + + /* Construct AAD header */ + RTMPConstructCCMPAAD(pHdr, + (frame_type == FC_TYPE_DATA), + a4_exists, + qc_exists, + aad_hdr, + &aad_len); + + /* Construct NONCE header */ + RTMPConstructCCMPNonce(pHdr, + a4_exists, + qc_exists, + (frame_type == FC_TYPE_MGMT), + pn, + nonce_hdr, + &nonce_hdr_len); + + /* CCM recipient processing - + uses the temporal key, AAD, nonce, MIC, + and MPDU cipher text data */ + if (AES_CCM_Decrypt(cipherData_ptr, cipherData_len, + pKey->Key, 16, + nonce_hdr, nonce_hdr_len, + aad_hdr, aad_len, LEN_CCMP_MIC, + pData, &out_len)) + return FALSE; + + *DataLen = out_len; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + return TRUE; +} + +#ifdef DBG +/* + ======================================================================== + + Routine Description: + CCMP test vector + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID CCMP_test_vector( + IN PRTMP_ADAPTER pAd, + IN INT input) +{ + UINT8 Key_ID = 0; + /*UINT8 A1[6] = {0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c};*/ + /*UINT8 A2[6] = {0x50, 0x30, 0xf1, 0x84, 0x44, 0x08};*/ + /*UINT8 A3[6] = {0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba};*/ + UINT8 TK[16] = {0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, + 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f}; + UINT8 PN[6] = {0x0C, 0xE7, 0x76, 0x97, 0x03, 0xB5}; + UINT8 HDR[24]= {0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, + 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, + 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33}; + UINT8 AAD[22] = {0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c, + 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae, + 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00}; + UINT8 CCMP_HDR[8] = {0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5}; + UINT8 CCM_NONCE[13] = {0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5, + 0x03, 0x97, 0x76, 0xe7, 0x0c}; + UINT8 P_TEXT_DATA[20] = {0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, + 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, + 0x7e, 0x78, 0xa0, 0x50}; + UINT8 C_TEXT_DATA[28] = {0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, + 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, + 0x3c, 0x04, 0xd0, 0x19, 0x78, 0x45, 0xce, 0x0b, + 0x16, 0xf9, 0x76, 0x23}; + UINT8 res_buf[100]; + UINT res_len = 0; + + printk("== CCMP test vector == \n"); + + /* Check AAD */ + NdisZeroMemory(res_buf, 100); + res_len = 0; + RTMPConstructCCMPAAD(HDR, TRUE, 0, 0, res_buf, &res_len); + if (res_len == 22 && NdisEqualMemory(res_buf, AAD, res_len)) + printk("Construct AAD is OK!!!\n"); + else + { + printk("\n!!!Construct AAD is FAILURE!!!\n\n"); + hex_dump("Calculate AAD", res_buf, res_len); + } + /* Check NONCE */ + NdisZeroMemory(res_buf, 100); + res_len = 0; + RTMPConstructCCMPNonce(HDR, 0, 0, FALSE, PN, res_buf, &res_len); + if (res_len == 13 && NdisEqualMemory(res_buf, CCM_NONCE, res_len)) + printk("Construct NONCE is OK!!!\n"); + else + { + printk("\n!!!Construct NONCE is FAILURE!!!\n\n"); + hex_dump("Calculate NONCE", res_buf, res_len); + } + /* Check CCMP-Header */ + NdisZeroMemory(res_buf, 100); + res_len = 0; + RTMPConstructCCMPHdr(Key_ID, PN, res_buf); + if (NdisEqualMemory(res_buf, CCMP_HDR, 8)) + printk("Construct CCMP_HDR is OK!!!\n"); + else + { + printk("\n!!!Construct CCMP_HDR is FAILURE!!!\n\n"); + hex_dump("Calculate CCMP_HDR", res_buf, 8); + } + + /* Encrypt action */ + NdisZeroMemory(res_buf, 100); + NdisMoveMemory(res_buf, P_TEXT_DATA, sizeof(P_TEXT_DATA)); + res_len = sizeof(C_TEXT_DATA); + if (AES_CCM_Encrypt(res_buf, sizeof(P_TEXT_DATA), + TK, sizeof(TK), + CCM_NONCE, sizeof(CCM_NONCE), + AAD, sizeof(AAD), 8, + res_buf, &res_len) == 0) + { + if (res_len == sizeof(C_TEXT_DATA) && + NdisEqualMemory(res_buf, C_TEXT_DATA, res_len)) + printk("CCM_Encrypt is OK!!!\n"); + else + { + printk("\n!!!CCM_Encrypt is FAILURE!!!\n\n"); + hex_dump("CCM_Encrypt", res_buf, res_len); + } + } + + /* Decrypt action */ + NdisZeroMemory(res_buf, 100); + NdisMoveMemory(res_buf, C_TEXT_DATA, sizeof(C_TEXT_DATA)); + res_len = sizeof(P_TEXT_DATA); + if (AES_CCM_Decrypt(res_buf, sizeof(C_TEXT_DATA), TK, 16, + CCM_NONCE, sizeof(CCM_NONCE), + AAD, sizeof(AAD), 8, + res_buf, &res_len) == 0) + { + if (res_len == sizeof(P_TEXT_DATA) && + NdisEqualMemory(res_buf, P_TEXT_DATA, res_len)) + printk("CCM_Decrypt is OK!!!\n"); + else + { + printk("\n!!!CCM_Decrypt is FAILURE!!!\n\n"); + hex_dump("CCM_Decrypt", res_buf, res_len); + } + } + + printk("== CCMP test vector == \n"); +} +#endif + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_asic.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_asic.c new file mode 100644 index 000000000..8fb0b0a9d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_asic.c @@ -0,0 +1,4088 @@ +/* + *************************************************************************** + * 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_asic.c + + Abstract: + Functions used to communicate with ASIC + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +#ifdef CONFIG_STA_SUPPORT +VOID AsicUpdateAutoFallBackTable( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRateTable) +{ + UCHAR i; + HT_FBK_CFG0_STRUC HtCfg0; + HT_FBK_CFG1_STRUC HtCfg1; + LG_FBK_CFG0_STRUC LgCfg0; + LG_FBK_CFG1_STRUC LgCfg1; +#ifdef DOT11N_SS3_SUPPORT + TX_FBK_CFG_3S_0_STRUC Ht3SSCfg0; + TX_FBK_CFG_3S_1_STRUC Ht3SSCfg1; +#endif /* DOT11N_SS3_SUPPORT */ + RTMP_RA_LEGACY_TB *pCurrTxRate, *pNextTxRate; + +#ifdef AGS_SUPPORT + RTMP_RA_AGS_TB *pCurrTxRate_AGS, *pNextTxRate_AGS; + BOOLEAN bUseAGS = FALSE; + + if (AGS_IS_USING(pAd, pRateTable)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Use AGS\n", __FUNCTION__)); + + bUseAGS = TRUE; + + Ht3SSCfg0.word = 0x1211100f; + Ht3SSCfg1.word = 0x16151413; + } +#endif /* AGS_SUPPORT */ + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT3883(pAd)) + { + Ht3SSCfg0.word = 0x12111008; + Ht3SSCfg1.word = 0x16151413; + } +#endif /* DOT11N_SS3_SUPPORT */ + + /* set to initial value*/ + HtCfg0.word = 0x65432100; + HtCfg1.word = 0xedcba980; + LgCfg0.word = 0xedcba988; + LgCfg1.word = 0x00002100; + + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + LgCfg1.word = 0x87872100; +#endif + +#ifdef NEW_RATE_ADAPT_SUPPORT + /* Use standard fallback if using new rate table */ + if (ADAPT_RATE_TABLE(pRateTable)) + goto skipUpdate; +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + if (bUseAGS) + { + pNextTxRate_AGS = (RTMP_RA_AGS_TB *)pRateTable+1; + pNextTxRate = (RTMP_RA_LEGACY_TB *)pNextTxRate_AGS; + } + else +#endif /* AGS_SUPPORT */ + pNextTxRate = (RTMP_RA_LEGACY_TB *)pRateTable+1; + + for (i = 1; i < *((PUCHAR) pRateTable); i++) + { +#ifdef AGS_SUPPORT + if (bUseAGS) + { + pCurrTxRate_AGS = (RTMP_RA_AGS_TB *)pRateTable+1+i; + pCurrTxRate = (RTMP_RA_LEGACY_TB *)pCurrTxRate_AGS; + } + else +#endif /* AGS_SUPPORT */ + pCurrTxRate = (RTMP_RA_LEGACY_TB *)pRateTable+1+i; + + switch (pCurrTxRate->Mode) + { + case 0: /* CCK */ + break; + case 1: /* OFDM */ + { + switch(pCurrTxRate->CurrMCS) + { + case 0: + LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 1: + LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 2: + LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 3: + LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 4: + LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 5: + LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 6: + LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 7: + LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + } + } + break; +#ifdef DOT11_N_SUPPORT + case 2: /* HT-MIX */ + case 3: /* HT-GF */ + { + if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS)) + { + if (pCurrTxRate->CurrMCS <= 15) + { + switch(pCurrTxRate->CurrMCS) + { + case 0: + HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS; + break; + case 1: + HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS; + break; + case 2: + HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS; + break; + case 3: + HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS; + break; + case 4: + HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS; + break; + case 5: + HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS; + break; + case 6: + HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS; + break; + case 7: + HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS; + break; + case 8: + HtCfg1.field.HTMCS8FBK = 0;//pNextTxRate->CurrMCS; + break; + case 9: + HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS; + break; + case 10: + HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS; + break; + case 11: + HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS; + break; + case 12: + HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS; + break; + case 13: + HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS; + break; + case 14: + HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS; + break; + case 15: + HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS; + break; + } + } + else +#ifdef AGS_SUPPORT + if ((bUseAGS == TRUE) && + (pCurrTxRate->CurrMCS >= 16) && (pCurrTxRate->CurrMCS <= 23)) + { + switch(pCurrTxRate->CurrMCS) + { + case 16: + Ht3SSCfg0.field.HTMCS16FBK = pNextTxRate->CurrMCS; + break; + case 17: + Ht3SSCfg0.field.HTMCS17FBK = pNextTxRate->CurrMCS; + break; + case 18: + Ht3SSCfg0.field.HTMCS18FBK = pNextTxRate->CurrMCS; + break; + case 19: + Ht3SSCfg0.field.HTMCS19FBK = pNextTxRate->CurrMCS; + break; + case 20: + Ht3SSCfg1.field.HTMCS20FBK = pNextTxRate->CurrMCS; + break; + case 21: + Ht3SSCfg1.field.HTMCS21FBK = pNextTxRate->CurrMCS; + break; + case 22: + Ht3SSCfg1.field.HTMCS22FBK = pNextTxRate->CurrMCS; + break; + case 23: + Ht3SSCfg1.field.HTMCS23FBK = pNextTxRate->CurrMCS; + break; + } + } + else +#endif /* AGS_SUPPORT */ + DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS)); + } + } + break; +#endif /* DOT11_N_SUPPORT */ + } + + pNextTxRate = pCurrTxRate; + } + +#ifdef AGS_SUPPORT + if (bUseAGS == TRUE) + { + Ht3SSCfg0.field.HTMCS16FBK = 0x8; // MCS 16 -> MCS 8 + HtCfg1.field.HTMCS8FBK = 0x0; // MCS 8 -> MCS 0 + + LgCfg0.field.OFDMMCS2FBK = 0x3; // OFDM 12 -> CCK 11 + LgCfg0.field.OFDMMCS1FBK = 0x2; // OFDM 9 -> CCK 5.5 + LgCfg0.field.OFDMMCS0FBK = 0x2; // OFDM 6 -> CCK 5.5 + } +#endif /* AGS_SUPPORT */ + +#ifdef NEW_RATE_ADAPT_SUPPORT +skipUpdate: +#endif /* NEW_RATE_ADAPT_SUPPORT */ + + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd) +#ifdef AGS_SUPPORT + || (bUseAGS == TRUE) +#endif /* AGS_SUPPORT */ + ) + { + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_0, Ht3SSCfg0.word); + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_1, Ht3SSCfg1.word); + DBGPRINT(RT_DEBUG_TRACE, ("AsicUpdateAutoFallBackTable: Ht3SSCfg0=0x%x, Ht3SSCfg1=0x%x\n", Ht3SSCfg0.word, Ht3SSCfg1.word)); + } +#endif /* DOT11N_SS3_SUPPORT */ + +} +#endif /* CONFIG_STA_SUPPORT */ + + +INT AsicSetAutoFallBack(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + TX_RTY_CFG_STRUC tx_rty_cfg = {.word = 0}; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.TxautoFBEnable = ((enable == TRUE) ? 1 : 0); + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + + return TRUE; +} + + +INT AsicAutoFallbackInit(RTMP_ADAPTER *pAd) +{ +#ifdef RANGE_EXTEND + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xedcba980); +#endif // RANGE_EXTEND // +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + { + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_0, 0x12111008); + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_1, 0x16151413); + } +#endif /* DOT11N_SS3_SUPPORT */ + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Set MAC register value according operation mode. + OperationMode AND bNonGFExist are for MM and GF Proteciton. + If MM or GF mask is not set, those passing argument doesn't not take effect. + + Operation mode meaning: + = 0 : Pure HT, no preotection. + = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. + = 0x10: No Transmission in 40M is protected. + = 0x11: Transmission in both 40M and 20M shall be protected + if (bNonGFExist) + we should choose not to use GF. But still set correct ASIC registers. + ======================================================================== +*/ +typedef enum _PROT_REG_IDX_{ + REG_IDX_CCK = 0, /* 0x1364 */ + REG_IDX_OFDM = 1, /* 0x1368 */ + REG_IDX_MM20 = 2, /* 0x136c */ + REG_IDX_MM40 = 3, /* 0x1370 */ + REG_IDX_GF20 = 4, /* 0x1374 */ + REG_IDX_GF40 = 5, /* 0x1378 */ +}PROT_REG_IDX; + + +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperationMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6], PhyMode = 0x4000; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; +#ifdef DOT11_VHT_AC +#ifdef RT65xx + PROT_CFG_STRUC vht_port_cfg = {.word = 0}; + UINT16 protect_rate = 0; +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ +#ifdef APCLI_CERT_SUPPORT +#ifdef DOT11_VHT_AC + BOOLEAN bStaConnect = FALSE; +#endif /* DOT11_VHT_AC */ +#endif /* APCLI_CERT_SUPPORT */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + +#ifdef DOT11_N_SUPPORT + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) + return; + + if (pAd->BATable.numDoneOriginator) + { + /* enable the RTS/CTS to avoid channel collision*/ + SetMask |= ALLN_SETPROTECT; + OperationMode = 8; + } +#endif /* DOT11_N_SUPPORT */ + + /* Config ASIC RTS threshold register*/ + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + /* If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096*/ + if (( +#ifdef DOT11_N_SUPPORT + (pAd->CommonCfg.BACapability.field.AmsduEnable) || +#endif /* DOT11_N_SUPPORT */ + (pAd->CommonCfg.bAggregationCapable == TRUE)) + && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) + { + MacReg |= (0x1000 << 8); + } + else + { + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + } + + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + /* Initial common protection settings*/ + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + // TODO: shiang, is that a correct way to set 0x2000 here?? + if (IS_RT65XX(pAd)) + PhyMode = 0x2000; /* Bit 15:13, 0:Legacy CCK, 1: Legacy OFDM, 2: HT mix mode, 3: HT green field, 4: VHT mode, 5-7: Reserved */ +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + + /* update PHY mode and rate*/ + if (pAd->OpMode == OPMODE_AP) + { + /* update PHY mode and rate*/ + if (pAd->CommonCfg.Channel > 14) + ProtCfg.field.ProtectRate = PhyMode; + ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; + } + else if (pAd->OpMode == OPMODE_STA) + { + // Decide Protect Rate for Legacy packet + if (pAd->CommonCfg.Channel > 14) + { + ProtCfg.field.ProtectRate = PhyMode; // OFDM 6Mbps + } + else + { + ProtCfg.field.ProtectRate = 0x0000; // CCK 1Mbps + if (pAd->CommonCfg.MinTxRate > RATE_11) + ProtCfg.field.ProtectRate |= PhyMode; // OFDM 6Mbps + } + } + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + if (IS_RT65XX(pAd)) + protect_rate = ProtCfg.field.ProtectRate; +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_FPGA_MODE +//+++Add by shiang for debug + if (pAd->fpga_ctl.fpga_on & 0x8) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():RtsRate=%d\n", + __FUNCTION__, pAd->CommonCfg.RtsRate)); + } +//---Add by shiang for debug +#endif /* CONFIG_FPGA_MODE */ + + /* Handle legacy(B/G) protection*/ + if (bDisableBGProtect) + { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/ + ProtCfg.field.ProtectCtrl = 0; + Protect[REG_IDX_CCK] = ProtCfg.word; + Protect[REG_IDX_OFDM] = ProtCfg.word; + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } + else + { + if (pAd->CommonCfg.Channel <= 14) { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/ + ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected*/ + Protect[REG_IDX_CCK] = ProtCfg.word; + ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect*/ + Protect[REG_IDX_OFDM] = ProtCfg.word; + pAd->FlgCtsEnabled = 1; /* CTS-self is used */ + } else { + ProtCfg.field.ProtectCtrl = 0; + Protect[REG_IDX_CCK] = ProtCfg.word; + Protect[REG_IDX_OFDM] = ProtCfg.word; + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } + } + +#ifdef DOT11_N_SUPPORT + /* Decide HT frame protection.*/ + if ((SetMask & ALLN_SETPROTECT) != 0) + { + switch(OperationMode) + { + case 0x0: + /* NO PROTECT */ + /* 1.All STAs in the BSS are 20/40 MHz HT*/ + /* 2. in ai 20/40MHz BSS*/ + /* 3. all STAs are 20MHz in a 20MHz BSS*/ + /* Pure HT. no protection.*/ + + /* MM20_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 010111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None)*/ + /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M)*/ + Protect[2] = 0x01744004; + + /* MM40_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 111111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None) */ + /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)*/ + Protect[3] = 0x03f44084; + + /* CF20_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 010111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None)*/ + /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M)*/ + Protect[4] = 0x01744004; + + /* CF40_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 111111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None)*/ + /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)*/ + Protect[5] = 0x03f44084; + + if (bNonGFExist) + { + /* PROT_NAV(19:18) -- 01 (Short NAV protectiion)*/ + /* PROT_CTRL(17:16) -- 01 (RTS/CTS)*/ + Protect[REG_IDX_GF20] = 0x01754004; + Protect[REG_IDX_GF40] = 0x03f54084; + } + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + // TODO: shiang-6590, fix me for this protection mechanism + if (IS_RT65XX(pAd)) + { + RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = 0; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = 0; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = 0; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word); + } +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + break; + + case 1: + /* This is "HT non-member protection mode."*/ + /* If there may be non-HT STAs my BSS*/ + ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None)*/ + ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */ + } + /*Assign Protection method for 20&40 MHz packets*/ + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[REG_IDX_MM20] = ProtCfg.word; + Protect[REG_IDX_MM40] = ProtCfg4.word; + Protect[REG_IDX_GF20] = ProtCfg.word; + Protect[REG_IDX_GF40] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + // TODO: shiang-6590, fix me for this protection mechanism + if (IS_RT65XX(pAd)) + { + // Temporary tuen on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8 + PROT_CFG_STRUC vht_port_cfg; + + RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word); + } +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + + break; + + case 2: + /* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets*/ + ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None)*/ + ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */ + } + /*Assign Protection method for 40MHz packets*/ + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[REG_IDX_MM20] = ProtCfg.word; + Protect[REG_IDX_MM40] = ProtCfg4.word; + if (bNonGFExist) + { + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + } + Protect[REG_IDX_GF20] = ProtCfg.word; + Protect[REG_IDX_GF40] = ProtCfg4.word; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + // TODO: shiang-6590, fix me for this protection mechanism + if (IS_RT65XX(pAd)) + { + RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = 0; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word); + } +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + break; + + case 3: + /* HT mixed mode. PROTECT ALL!*/ + /* Assign Rate*/ + ProtCfg.word = 0x01744004; /*duplicaet legacy 24M. BW set 1.*/ + ProtCfg4.word = 0x03f44084; + /* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083*/ + } + /*Assign Protection method for 20&40 MHz packets*/ + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[REG_IDX_MM20] = ProtCfg.word; + Protect[REG_IDX_MM40] = ProtCfg4.word; + Protect[REG_IDX_GF20] = ProtCfg.word; + Protect[REG_IDX_GF40] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + // TODO: shiang-6590, fix me for this protection mechanism + if (IS_RT65XX(pAd)) + { + // Temporary turn on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8 + RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word); + } +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + break; + + case 8: + /* Special on for Atheros problem n chip.*/ + ProtCfg.word = 0x01754004; /*duplicaet legacy 24M. BW set 1.*/ + ProtCfg4.word = 0x03f54084; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01750003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/ + ProtCfg4.word = 0x03f50003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083*/ + } + +#ifdef APCLI_CERT_SUPPORT // for TGAC 5.2.35 +#ifdef DOT11_VHT_AC + if (pAd->MacTab.Size > 0) { + MAC_TABLE_ENTRY *pEntry = NULL; + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + bStaConnect = TRUE; + } + } + } +#endif /* DOT11_VHT_AC */ +#endif /* APCLI_CERT_SUPPORT */ + + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + if (IS_RT65XX(pAd) +#ifdef APCLI_CERT_SUPPORT + &&(bStaConnect) +#endif + ) + { + // Temporary tuen on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8 + PROT_CFG_STRUC vht_port_cfg; + + RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word); + + RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word); + vht_port_cfg.field.ProtectCtrl = ASIC_RTS; + vht_port_cfg.field.ProtectNav = ASIC_SHORTNAV; + vht_port_cfg.field.ProtectRate = protect_rate; + RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word); + } +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ + + Protect[REG_IDX_MM20] = ProtCfg.word; /*0x01754004;*/ + Protect[REG_IDX_MM40] = ProtCfg4.word; /*0x03f54084;*/ + Protect[REG_IDX_GF20] = ProtCfg.word; /*0x01754004;*/ + Protect[REG_IDX_GF40] = ProtCfg4.word; /*0x03f54084;*/ + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + } + } +#endif /* DOT11_N_SUPPORT */ + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + { + if ((SetMask & (1<< i))) + { +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + if ((Protect[i] & 0x4000) == 0x4000) + Protect[i] = ((Protect[i] & (~0x4000)) | 0x2000); + } +#endif /* RT65xx */ + } + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + } + +#ifdef DOT11_VHT_AC +#ifdef RT65xx + if (IS_RT65XX(pAd)) + { + UINT32 cfg_reg; + for (cfg_reg = TX_PROT_CFG6; cfg_reg <= TX_PROT_CFG8; cfg_reg += 4) + { + RTMP_IO_READ32(pAd, cfg_reg, &MacReg); + MacReg &= (~0x18000000); + if (pAd->CommonCfg.vht_bw_signal) + { + if (pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_STATIC) /* static */ + MacReg |= 0x08000000; + else if (pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_DYNAMIC)/* dynamic */ + MacReg |= 0x18000000; + } + RTMP_IO_WRITE32(pAd, cfg_reg, MacReg); + } + } +#endif /* RT65xx */ +#endif /* DOT11_VHT_AC */ +} + + +VOID AsicBBPAdjust(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-6590, now this function only used for AP mode, why we need this differentation? + if (pAd->chipOps.ChipBBPAdjust != NULL) + pAd->chipOps.ChipBBPAdjust(pAd); +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSwitchChannel(RTMP_ADAPTER *pAd, UCHAR Channel, BOOLEAN bScan) +{ + UCHAR bw; +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ +#endif /* CONFIG_STA_SUPPORT */ + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + + if( (RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): autopm_resume success\n", __FUNCTION__)); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + } + else if ((RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == (-1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): autopm_resume fail\n", __FUNCTION__)); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("%s(): autopm_resume do nothing\n", __FUNCTION__)); + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + /* later need to move this BssTableInit to other place */ + BssTableInit(&pAd->AvailableBSS); +#endif +#ifdef AP_QLOAD_SUPPORT + /* clear all statistics count for QBSS Load */ + QBSS_LoadStatusClear(pAd); +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + if (pAd->chipOps.ChipSwitchChannel) + pAd->chipOps.ChipSwitchChannel(pAd, Channel, bScan); + else + DBGPRINT(RT_DEBUG_ERROR, ("For this chip, no specified channel switch function!\n")); + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + if (bScan) + bw = BW_20; + else { + bw = pAd->CommonCfg.BBPCurrentBW; + } + RTMPSetAGCInitValue(pAd, bw); + +#ifdef TXBF_SUPPORT + rtmp_asic_set_bf(pAd); // FW will initialize TxBf HW status. Re-calling this AP could recover previous status + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + UINT32 value32; + // Disable BF HW to apply profile to packets when nSS == 2. + // Maybe it can be initialized at chip init but removing the same CR initialization from FW will be better + RTMP_IO_READ32(pAd, TXO_R4, &value32); + value32 |= 0x2000000; + RTMP_IO_WRITE32(pAd, TXO_R4, value32); + } +#endif /* MT76x2 */ +#endif /* TXBF_SUPPORT */ + +#ifdef SMART_MESH_MONITOR + if (!bScan) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.channel_change.type = NSMPIF_DRVEVNT_CHANNEL_CHANGE; + drvevnt.data.channel_change.channel = pAd->CommonCfg.Channel; + NdisZeroMemory(drvevnt.data.channel_change.op_channels,sizeof(drvevnt.data.channel_change.op_channels)); + drvevnt.data.channel_change.op_channels[0] = pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + if(bw == BW_40) + drvevnt.data.channel_change.op_channels[1] = N_GetSecondaryChannel(pAd); +#endif /* DOT11_N_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_CHANNEL_CHANGE, + NULL, (PUCHAR)&drvevnt.data.channel_change, sizeof(drvevnt.data.channel_change)); + } +#endif /* SMART_MESH_MONITOR */ +} + + +/* + ========================================================================== + Description: + This function is required for 2421 only, and should not be used during + site survey. It's only required after NIC decided to stay at a channel + for a longer period. + When this function is called, it's always after AsicSwitchChannel(). + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + + +VOID AsicResetBBPAgent(RTMP_ADAPTER *pAd) +{ + BBP_CSR_CFG_STRUC BbpCsr; + + /* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */ + /* IF chipOps.AsicResetBbpAgent == NULL, run "else" part */ + if (pAd->chipOps.AsicResetBbpAgent != NULL) + pAd->chipOps.AsicResetBbpAgent(pAd); + else if (pAd->chipCap.MCUType != ANDES) + { + DBGPRINT(RT_DEBUG_INFO, ("Reset BBP Agent busy bit.!! \n")); + RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); + BbpCsr.field.Busy = 0; + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); + } +} + + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup + automatically. Instead, MCU will issue a TwakeUpInterrupt to host after + the wakeup timer timeout. Driver has to issue a separate command to wake + PHY up. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp) +{ + RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever manual wakeup is required + AsicForceSleep() should only be used when not in INFRA BSS. When + in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. + ========================================================================== + */ +VOID AsicForceSleep( + IN PRTMP_ADAPTER pAd) +{ + +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) + expired. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +VOID AsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx) +{ + DBGPRINT(RT_DEBUG_INFO, ("--> AsicForceWakeup \n")); + RTMP_STA_FORCE_WAKEUP(pAd, bFromTx); +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ========================================================================== + Description: + Set My BSSID + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + /* CFG_TODO */ +VOID AsicSetBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid) +{ + UINT32 Addr4; +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + UINT32 regValue; +#endif /* defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> AsicSetBssid %x:%x:%x:%x:%x:%x\n", + PRINT_MAC(pBssid))); + + Addr4 = (UINT32)(pBssid[0]) | + (UINT32)(pBssid[1] << 8) | + (UINT32)(pBssid[2] << 16) | + (UINT32)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW0, Addr4); +#endif /* HDR_TRANS_SUPPORT */ + + Addr4 = 0; + /* always one BSSID in STA mode*/ + Addr4 = (UINT32)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); + +#ifdef HDR_TRANS_SUPPORT + Addr4 |= 0x18000000; + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, Addr4); +#endif /* HDR_TRANS_SUPPORT */ + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) + { + PUCHAR pP2PBssid = &pAd->CurrentAddress[0]; + + Addr4 = (UINT32)(pP2PBssid[0]) | + (UINT32)(pP2PBssid[1] << 8) | + (UINT32)(pP2PBssid[2] << 16) | + (UINT32)(pP2PBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW0, Addr4); +#endif /* HDR_TRANS_SUPPORT */ + + Addr4 = 0; + + /* always one BSSID in STA mode */ + Addr4 = (UINT32)(pP2PBssid[4]) | (ULONG)(pP2PBssid[5] << 8); + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); + + RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); + regValue &= 0x0000FFFF; + regValue |= (1 << 16); + + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE0) + { + if ((pAd->CurrentAddress[5] % 2 != 0) + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); + + } + else + { + /*set as 0/1 bit-21 of MAC_BSSID_DW1(offset: 0x1014) + to disable/enable the new MAC address assignment. */ + regValue |= (1 << 21); + } + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); +#ifdef HDR_TRANS_SUPPORT + /* + point WCID MAC table to 0x1800 + This is for debug. + But HDR_TRANS doesn't work if you remove it. + Check after IC formal release. + */ + regValue |= 0x18000000; + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, regValue); +#endif /* HDR_TRANS_SUPPORT */ + } +#endif /* P2P_SUPPORT */ +} + + +INT AsicSetDevMac(RTMP_ADAPTER *pAd, UCHAR *addr) +{ + MAC_DW0_STRUC csr2; + MAC_DW1_STRUC csr3; + + csr2.field.Byte0 = addr[0]; + csr2.field.Byte1 = addr[1]; + csr2.field.Byte2 = addr[2]; + csr2.field.Byte3 = addr[3]; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); + + csr3.word = 0; + csr3.field.Byte4 = addr[4]; + { + csr3.field.Byte5 = addr[5]; + csr3.field.U2MeMask = 0xff; + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("SetDevMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(addr))); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW0, csr2.word); + csr3.word &= 0xff00ffff; + csr3.word |= 0x00410000; // HW test code + RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW1, csr3.word); +#endif /* HDR_TRANS_SUPPORT */ + + return TRUE; +} + +#ifdef CONFIG_AP_SUPPORT +VOID AsicSetMbssMode(RTMP_ADAPTER *pAd, UCHAR NumOfBcns) +{ + UCHAR NumOfMacs; + UINT32 regValue; + + RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); + regValue &= 0x0000FFFF; + + /* + Note: + 1.The MAC address of Mesh and AP-Client link are different from Main BSSID. + 2.If the Mesh link is included, its MAC address shall follow the last MBSSID's MAC by increasing 1. + 3.If the AP-Client link is included, its MAC address shall follow the Mesh interface MAC by increasing 1. + */ + NumOfMacs = pAd->ApCfg.BssidNum + MAX_MESH_NUM + MAX_APCLI_NUM; + + + /* set Multiple BSSID mode */ + if (NumOfMacs <= 1) + { + pAd->ApCfg.MacMask = ~(1-1); + /*regValue |= 0x0; */ + } + else if (NumOfMacs <= 2) + { +#ifndef NEW_MBSSID_MODE + if ((pAd->CurrentAddress[5] % 2 != 0) + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); +#endif + regValue |= (1<<16); + pAd->ApCfg.MacMask = ~(2-1); + } + else if (NumOfMacs <= 4) + { +#ifndef NEW_MBSSID_MODE + if (pAd->CurrentAddress[5] % 4 != 0) + DBGPRINT(RT_DEBUG_ERROR, ("The 4-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 4\n")); +#endif + regValue |= (2<<16); + pAd->ApCfg.MacMask = ~(4-1); + } + else if (NumOfMacs <= 8) + { +#ifndef NEW_MBSSID_MODE + if (pAd->CurrentAddress[5] % 8 != 0) + DBGPRINT(RT_DEBUG_ERROR, ("The 8-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 8\n")); +#endif + regValue |= (3<<16); + pAd->ApCfg.MacMask = ~(8-1); + } + else if (NumOfMacs <= 16) + { + /* Set MULTI_BSSID_MODE_BIT4 in MAC register 0x1014 */ + regValue |= (1<<22); + pAd->ApCfg.MacMask = ~(16-1); + } + + /* set Multiple BSSID Beacon number */ + if (NumOfBcns > 1) + { + if (NumOfBcns > 8) + regValue |= (((NumOfBcns - 1) >> 3) << 23); + regValue |= (((NumOfBcns - 1) & 0x7) << 18); + } + + /* set as 0/1 bit-21 of MAC_BSSID_DW1(offset: 0x1014) + to disable/enable the new MAC address assignment. */ + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + regValue |= (1 << 21); +#ifdef ENHANCE_NEW_MBSSID_MODE + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE2) + regValue |= (1 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE3) + regValue |= (2 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE4) + regValue |= (3 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE5) + regValue |= (4 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE6) + regValue |= (5 << 24); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); + +#ifdef HDR_TRANS_SUPPORT + /* + point WCID MAC table to 0x1800 + This is for debug. + But HDR_TRANS doesn't work if you remove it. + Check after IC formal release. + */ + regValue |= 0x18000000; + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, regValue); +#endif /* HDR_TRANS_SUPPORT */ +} +#endif /* CONFIG_AP_SUPPORT */ + + +INT AsicSetRxFilter(RTMP_ADAPTER *pAd) +{ + UINT32 rx_filter_flag = APNORMAL; + + /* enable RX of MAC block*/ + if ((pAd->OpMode == OPMODE_AP) + ) + { + rx_filter_flag = APNORMAL; + +#ifdef CONFIG_AP_SUPPORT +#ifdef IDS_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.IdsEnable) + rx_filter_flag &= (~0x4); /* Don't drop those not-U2M frames*/ + } +#endif /* IDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } +#ifdef CONFIG_STA_SUPPORT + else + { +#ifdef XLINK_SUPPORT + if (pAd->StaCfg.PSPXlink) + rx_filter_flag = PSPXLINK; + else +#endif /* XLINK_SUPPORT */ + rx_filter_flag = STANORMAL; /* Staion not drop control frame will fail WiFi Certification.*/ + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT + /* Enable Rx with promiscuous reception */ + if ((MONITOR_ON(pAd)) && + (pAd->monitor_ctrl.current_monitor_mode == MONITOR_MODE_FULL || pAd->monitor_ctrl.current_monitor_mode == MONITOR_MODE_FULL_NO_CLONE)) + rx_filter_flag = 0x3; +#endif + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); + + return TRUE; +} + + +#ifdef DOT11_N_SUPPORT +INT AsicSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = (bEnable ? 1 : 0); + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + if (bEnable) { + Data |= 0x80; + } else { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) + && (pAd->CommonCfg.bEnableTxBurst == TRUE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif /* DOT11_N_SUPPORT */ + ) + Data |= 0x20; + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + + if (bEnable) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + else + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ======================================================================== + Routine Description: + Set/reset MAC registers according to bPiggyBack parameter + + Arguments: + pAd - Adapter pointer + bPiggyBack - Enable / Disable Piggy-Back + + Return Value: + None + + ======================================================================== +*/ +VOID RTMPSetPiggyBack(RTMP_ADAPTER *pAd, BOOLEAN bPiggyBack) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + + TxLinkCfg.field.TxCFAckEn = bPiggyBack; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); +} + +VOID AsicCtrlBcnMask(PRTMP_ADAPTER pAd, INT mask) +{ + BCN_BYPASS_MASK_STRUC bms; + + RTMP_IO_READ32(pAd, TX_BCN_BYPASS_MASK, &bms.word); + bms.field.BeaconDropMask = mask; + RTMP_IO_WRITE32(pAd, TX_BCN_BYPASS_MASK, bms.word); +} + +static INT AsicSetIntTimerEn(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 type, UINT32 timeout) +{ + UINT32 val = 0, mask = 0, time_mask = 0; + + if (type == INT_TIMER_EN_PRE_TBTT) { + mask = 0x1; + timeout = (timeout & 0xffff); + time_mask = 0xffff; + } + else if (type == INT_TIMER_EN_GP_TIMER) { + mask = 0x2; + timeout = (timeout & 0xffff) << 16; + time_mask = (0xffff << 16); + } + else + mask = 0x3; + + RTMP_IO_READ32(pAd, INT_TIMER_EN, &val); + if (enable == FALSE) + val &= (~mask); + else + val |= mask; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, val); + + if (enable) { + RTMP_IO_READ32(pAd, INT_TIMER_CFG, &val); + val = (val & (~time_mask)) | timeout; + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, val); + } + + return TRUE; +} + + +INT AsicSetPreTbtt(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 timeout = 0; + + if (enable == TRUE) + timeout = 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */ + + return AsicSetIntTimerEn(pAd, enable, INT_TIMER_EN_PRE_TBTT, timeout); +} + + +INT AsicSetGPTimer(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 timeout) +{ + return AsicSetIntTimerEn(pAd, enable, INT_TIMER_EN_GP_TIMER, timeout); +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + + pAd->TbttTickCount = 0; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + csr.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableBssSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; +#ifdef APCLI_SUPPORT + UCHAR apidx; + BOOLEAN bMaskBcn; +#endif /* APCLI_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + +#ifdef APCLI_SUPPORT + // for apcli DFS, if ra0 not up, don,t send bcn + bMaskBcn = TRUE; + + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + if(BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) + { + bMaskBcn = FALSE; + break; + } + } + + if (bMaskBcn && APCLI_IF_UP_CHECK(pAd, 0)) { + DBGPRINT(RT_DEBUG_OFF, ("Apcli DFS need mask beacon!!!\n")); + AsicCtrlBcnMask(pAd, 0xFF); + } + else { + AsicCtrlBcnMask(pAd, 0x0); + } +#endif /* APCLI_SUPPORT */ + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); +/* RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/ + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 3; /* sync TSF similar as in ADHOC mode?*/ + csr.field.bBeaconGen = 1; /* AP should generate BEACON*/ + csr.field.bTBTTEnable = 1; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/ + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 1; /* sync TSF in INFRASTRUCTURE mode*/ + csr.field.bBeaconGen = 0; /* do NOT generate BEACON*/ + csr.field.bTBTTEnable = 1; + } +#endif /* CONFIG_STA_SUPPORT */ + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +/*CFG_TODO*/ +VOID AsicEnableApBssSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + + csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/ + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 3; /* sync TSF similar as in ADHOC mode?*/ + csr.field.bBeaconGen = 1; /* AP should generate BEACON*/ + csr.field.bTBTTEnable = 1; + + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + Note: + BEACON frame in shared memory should be built ok before this routine + can be called. Otherwise, a garbage frame maybe transmitted out every + Beacon period. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableIbssSync(RTMP_ADAPTER *pAd) +{ + BCN_TIME_CFG_STRUC csr9; + UCHAR *ptr; + UINT i; + ULONG beaconBaseLocation = 0; + USHORT beaconLen = 0; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT32 longptr; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + beaconLen = pAd->BeaconTxWI.TXWI_N.MPDUtotalByteCnt; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + beaconLen = pAd->BeaconTxWI.TXWI_O.MPDUtotalByteCnt; +#endif /* RTMP_MAC */ + +#ifdef RT_BIG_ENDIAN + { + TXWI_STRUC localTxWI; + + NdisMoveMemory((PUCHAR)&localTxWI, (PUCHAR)&pAd->BeaconTxWI, TXWISize); + RTMPWIEndianChange(pAd, (PUCHAR)&localTxWI, TYPE_TXWI); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + beaconLen = localTxWI.TXWI_N.MPDUtotalByteCnt; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + beaconLen = localTxWI.TXWI_O.MPDUtotalByteCnt; +#endif /* RTMP_MAC */ + } +#endif /* RT_BIG_ENDIAN */ + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode, beaconLen=%d)\n", + beaconLen)); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); + csr9.field.bBeaconGen = 0; + csr9.field.bTBTTEnable = 0; + csr9.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); + beaconBaseLocation = HW_BEACON_BASE0(pAd); + +#ifdef RTMP_MAC_PCI + /* move BEACON TXD and frame content to on-chip memory*/ + ptr = (PUCHAR)&pAd->BeaconTxWI; + for (i=0; i < TXWISize; i+=4) + { + longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, HW_BEACON_BASE0(pAd) + i, longptr, 4); + ptr += 4; + } + + /* start right after the 16-byte TXWI field*/ + ptr = pAd->BeaconBuf; + for (i=0; i< beaconLen; i+=4) + { + longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, HW_BEACON_BASE0(pAd) + TXWISize + i, longptr, 4); + ptr +=4; + } +#endif /* RTMP_MAC_PCI */ + + + /* + For Wi-Fi faily generated beacons between participating stations. + Set TBTT phase adaptive adjustment step to 8us (default 16us) + */ + /* don't change settings 2006-5- by Jerry*/ + /*RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);*/ + + /* start sending BEACON*/ + csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/ + csr9.field.bTsfTicking = 1; +#ifdef IWSC_SUPPORT + /* + SYNC with nobody + If Canon loses our Beacon over 5 seconds, Canon will delete us silently. + */ + csr9.field.TsfSyncMode = 3; // sync TSF in IBSS mode +#else /* IWSC_SUPPORT */ + /* + (STA ad-hoc mode) Upon the reception of BEACON frame from associated BSS, + local TSF is updated with remote TSF only if the remote TSF is greater than local TSF + */ + csr9.field.TsfSyncMode = 2; /* sync TSF in IBSS mode*/ +#endif /* !IWSC_SUPPORT */ + csr9.field.bTBTTEnable = 1; + csr9.field.bBeaconGen = 1; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetEdcaParm(RTMP_ADAPTER *pAd, PEDCA_PARM pEdcaParm) +{ + EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; + AC_TXOP_CSR0_STRUC csr0; + AC_TXOP_CSR1_STRUC csr1; + AIFSN_CSR_STRUC AifsnCsr; + CWMIN_CSR_STRUC CwminCsr; + CWMAX_CSR_STRUC CwmaxCsr; + int i; + + Ac0Cfg.word = 0; + Ac1Cfg.word = 0; + Ac2Cfg.word = 0; + Ac3Cfg.word = 0; + if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); + for (i=0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) || IS_ENTRY_APCLI(&pAd->MacTab.Content[i])) + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); + } + + /*========================================================*/ + /* MAC Register has a copy .*/ + /*========================================================*/ + if( pAd->CommonCfg.bEnableTxBurst ) + { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/ + Ac0Cfg.field.AcTxop = 0x20; /* Suggest by John for TxBurst in HT Mode*/ + } + else + Ac0Cfg.field.AcTxop = 0; /* QID_AC_BE*/ + + Ac0Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac0Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac0Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + + Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK*/ + Ac1Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac1Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac1Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + { + Ac2Cfg.field.AcTxop = 192; /* AC_VI: 192*32us ~= 6ms*/ + Ac3Cfg.field.AcTxop = 96; /* AC_VO: 96*32us ~= 3ms*/ + } + else + { + Ac2Cfg.field.AcTxop = 96; /* AC_VI: 96*32us ~= 3ms*/ + Ac3Cfg.field.AcTxop = 48; /* AC_VO: 48*32us ~= 1.5ms*/ + } + Ac2Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac2Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac2Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + Ac3Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac3Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac3Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + /*========================================================*/ + /* DMA Register has a copy too.*/ + /*========================================================*/ + csr0.field.Ac0Txop = 0; /* QID_AC_BE*/ + csr0.field.Ac1Txop = 0; /* QID_AC_BK*/ + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + { + csr1.field.Ac2Txop = 192; /* AC_VI: 192*32us ~= 6ms*/ + csr1.field.Ac3Txop = 96; /* AC_VO: 96*32us ~= 3ms*/ + } + else + { + csr1.field.Ac2Txop = 96; /* AC_VI: 96*32us ~= 3ms*/ + csr1.field.Ac3Txop = 48; /* AC_VO: 48*32us ~= 1.5ms*/ + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = pAd->wmm_cw_min; + CwminCsr.field.Cwmin1 = pAd->wmm_cw_min; + CwminCsr.field.Cwmin2 = pAd->wmm_cw_min; + CwminCsr.field.Cwmin3 = pAd->wmm_cw_min; + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = pAd->wmm_cw_max; + CwmaxCsr.field.Cwmax1 = pAd->wmm_cw_max; + CwmaxCsr.field.Cwmax2 = pAd->wmm_cw_max; + CwmaxCsr.field.Cwmax3 = pAd->wmm_cw_max; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); + + NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); + + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); + /*========================================================*/ + /* MAC Register has a copy.*/ + /*========================================================*/ + + /* Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27*/ + /* To degrade our VIDEO Queue's throughput for WiFi WMM S3T07 Issue.*/ + + /*pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; rt2860c need this */ + + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; + Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; + Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; /*+1;*/ + + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; /*+2; */ + Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; /*+1;*/ + + + Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; +#ifdef RTMP_RBUS_SUPPORT + if(pAd->Antenna.field.TxPath == 1) + { + Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI] + 1; + Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI] + 1; + } + else +#endif + { + Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; + Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; + } + /*sync with window 20110524*/ + Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1; /* 5.2.27 T6 Pass Tx VI+BE, but will impack 5.2.27/28 T7. Tx VI*/ + +#ifdef INF_AMAZON_SE +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + Ac2Cfg.field.Aifsn = 0x3; /*for WiFi WMM A1-T07.*/ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* INF_AMAZON_SE */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Tuning for Wi-Fi WMM S06*/ + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + Ac2Cfg.field.Aifsn -= 1; + + /* Tuning for TGn Wi-Fi 5.2.32*/ + /* STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta*/ + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + Ac0Cfg.field.Aifsn = 3; + Ac2Cfg.field.AcTxop = 5; + } + + } +#endif /* CONFIG_STA_SUPPORT */ + + Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; + Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; + Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; + Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; + + if (pAd->CommonCfg.bWiFiTest) + { + if (Ac3Cfg.field.AcTxop == 102) + { + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; + Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; + } + } + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI + /* STA TestBed changes in this item: for sta wifitest 5.2.32, 2011/04/11 */ + /* just for 5390 5392 pci, 5370 5372 not need this patch */ + if((IS_RT5390(pAd) || IS_RT5392(pAd)) && pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + Ac0Cfg.field.AcTxop = 38; + } +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_STA_SUPPORT */ + + + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + + /*========================================================*/ + /* DMA Register has a copy too.*/ + /*========================================================*/ + csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; + csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + + csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; + csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; + CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; + CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO]; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; /*for TGn wifi test*/ +#endif /* CONFIG_STA_SUPPORT */ + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; + CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; + CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; + CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + AifsnCsr.word = 0; + AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BE];*/ + AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BK];*/ +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VI];*/ +#ifdef INF_AMAZON_SE +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VO]*/ + AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; for WiFi WMM A1-T07.*/ + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* INF_AMAZON_SE */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Tuning for Wi-Fi WMM S06*/ + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; + + /* Tuning for TGn Wi-Fi 5.2.32*/ + /* STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta*/ + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + AifsnCsr.field.Aifsn0 = 3; + AifsnCsr.field.Aifsn2 = 7; + } + + if (INFRA_ON(pAd)) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VO]*/ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; /*pEdcaParm->Aifsn[QID_AC_VO]; for TGn wifi test*/ + + /* TODO: Is this modification also suitable for RT3052/RT3050 ???*/ + if (0 + ) + { + AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; for WiFi WMM S4-T04.*/ + } + } +#endif /* CONFIG_STA_SUPPORT */ + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); + + NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + if (!ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount)); + DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[0], + pEdcaParm->Cwmin[0], + pEdcaParm->Cwmax[0], + pEdcaParm->Txop[0]<<5, + pEdcaParm->bACM[0])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[1], + pEdcaParm->Cwmin[1], + pEdcaParm->Cwmax[1], + pEdcaParm->Txop[1]<<5, + pEdcaParm->bACM[1])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[2], + pEdcaParm->Cwmin[2], + pEdcaParm->Cwmax[2], + pEdcaParm->Txop[2]<<5, + pEdcaParm->bACM[2])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[3], + pEdcaParm->Cwmin[3], + pEdcaParm->Cwmax[3], + pEdcaParm->Txop[3]<<5, + pEdcaParm->bACM[3])); + } + + } + + pAd->CommonCfg.RestoreBurstMode = Ac0Cfg.word; +} + + + +INT AsicSetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type, UINT32 limit) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + if (type == TX_RTY_CFG_RTY_LIMIT_SHORT) + tx_rty_cfg.field.ShortRtyLimit = limit; + else if (type == TX_RTY_CFG_RTY_LIMIT_LONG) + tx_rty_cfg.field.LongRtyLimit = limit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + + return TRUE; +} + + +UINT32 AsicGetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type) +{ + TX_RTY_CFG_STRUC tx_rty_cfg = {.word = 0}; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + if (type == TX_RTY_CFG_RTY_LIMIT_SHORT) + return tx_rty_cfg.field.ShortRtyLimit; + else if (type == TX_RTY_CFG_RTY_LIMIT_LONG) + return tx_rty_cfg.field.LongRtyLimit; + + return 0; +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime) +{ + ULONG SlotTime; + UINT32 RegValue = 0; + +#ifdef CONFIG_STA_SUPPORT + if (pAd->CommonCfg.Channel > 14) + bUseShortSlotTime = TRUE; +#endif /* CONFIG_STA_SUPPORT */ + + if (bUseShortSlotTime && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) + return; + else if ((!bUseShortSlotTime) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))) + return; + + if (bUseShortSlotTime) + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + else + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + + SlotTime = (bUseShortSlotTime)? 9 : 20; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* force using short SLOT time for FAE to demo performance when TxBurst is ON*/ + if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) +#ifdef DOT11_N_SUPPORT + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)) +#endif /* DOT11_N_SUPPORT */ + ) + { + /* In this case, we will think it is doing Wi-Fi test*/ + /* And we will not set to short slot when bEnableTxBurst is TRUE.*/ + } + else if (pAd->CommonCfg.bEnableTxBurst) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + SlotTime = 9; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + + /* For some reasons, always set it to short slot time.*/ + /* ToDo: Should consider capability with 11B*/ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + SlotTime = 20; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + RegValue = RegValue & 0xFFFFFF00; + + RegValue |= SlotTime; + + RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); +} + + +#ifdef CONFIG_AP_SUPPORT +VOID RTMPGetTxTscFromAsic(RTMP_ADAPTER *pAd, UCHAR apidx, UCHAR *pTxTsc) +{ + USHORT Wcid; + USHORT offset; + UCHAR IvEiv[8]; + INT i; + + /* Sanity check of apidx */ + if (apidx >= MAX_MBSSID_NUM(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPGetTxTscFromAsic : invalid apidx(%d)\n", apidx)); + return; + } + + /* Initial value */ + NdisZeroMemory(IvEiv, 8); + NdisZeroMemory(pTxTsc, 6); + + /* Get apidx for this BSSID */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* When the group rekey action is triggered, a count-down(3 seconds) is started. + During the count-down, use the initial PN as TSC. + Otherwise, get the IVEIV from ASIC. */ + if (pAd->ApCfg.MBSSID[apidx].RekeyCountDown > 0) + { + /* + In IEEE 802.11-2007 8.3.3.4.3 described : + The PN shall be implemented as a 48-bit monotonically incrementing + non-negative integer, initialized to 1 when the corresponding + temporal key is initialized or refreshed. */ + IvEiv[0] = 1; + } + else + { + UINT32 temp1, temp2; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + /* Read IVEIV from Asic */ + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + + /* Use Read32 to avoid endian problem */ + RTMP_IO_READ32(pAd, offset, &temp1); + RTMP_IO_READ32(pAd, offset+4, &temp2); + for ( i=0; i<4; i++) + { + IvEiv[i] = (UCHAR)(temp1 >> (i*8)); + IvEiv[i+4] = (UCHAR)(temp2 >> (i*8)); + } + } + + /* Record current TxTsc */ + if (pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus == Ndis802_11AESEnable) + { /* AES */ + *pTxTsc = IvEiv[0]; + *(pTxTsc+1) = IvEiv[1]; + *(pTxTsc+2) = IvEiv[4]; + *(pTxTsc+3) = IvEiv[5]; + *(pTxTsc+4) = IvEiv[6]; + *(pTxTsc+5) = IvEiv[7]; + } + else + { /* TKIP */ + *pTxTsc = IvEiv[2]; + *(pTxTsc+1) = IvEiv[0]; + *(pTxTsc+2) = IvEiv[4]; + *(pTxTsc+3) = IvEiv[5]; + *(pTxTsc+4) = IvEiv[6]; + *(pTxTsc+5) = IvEiv[7]; + } + DBGPRINT(RT_DEBUG_TRACE, ("RTMPGetTxTscFromAsic : WCID(%d) TxTsc 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x \n", + Wcid, *pTxTsc, *(pTxTsc+1), *(pTxTsc+2), *(pTxTsc+3), *(pTxTsc+4), *(pTxTsc+5))); + + +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* + ======================================================================== + Description: + Add Shared key information into ASIC. + Update shared key, TxMic and RxMic to Asic Shared key table + Update its cipherAlg to Asic Shared key Mode. + + Return: + ======================================================================== +*/ +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey) +{ + ULONG offset; /*, csr0;*/ + SHAREDKEY_MODE_STRUC csr1; + UCHAR org_bssindex; +#ifdef RTMP_MAC_PCI + INT i; +#endif /* RTMP_MAC_PCI */ + + PUCHAR pKey = pCipherKey->Key; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); +/*============================================================================================*/ + + DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +/*============================================================================================*/ + + org_bssindex = BssIndex; + if (BssIndex >= 8) + BssIndex -= 8; + + { + /* fill key material - key + TX MIC + RX MIC*/ + UINT32 share_key_base = 0, share_key_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + if (org_bssindex >= 8) + share_key_base = RLT_SHARED_KEY_TABLE_BASE_EXT; + else + share_key_base = RLT_SHARED_KEY_TABLE_BASE; + share_key_size = RLT_HW_KEY_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + if (org_bssindex >= 8) + share_key_base = SHARED_KEY_TABLE_BASE_EXT; + else + share_key_base = SHARED_KEY_TABLE_BASE; + share_key_size = HW_KEY_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = share_key_base + (4*BssIndex + KeyIdx)*share_key_size; +#ifdef RTMP_MAC_PCI + { + for (i=0; ichipCap.hif_type == HIF_RLT) { + if (org_bssindex >= 8) + share_key_mode_base = RLT_SHARED_KEY_MODE_BASE_EXT; + else + share_key_mode_base= RLT_SHARED_KEY_MODE_BASE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + if (org_bssindex >= 8) + share_key_mode_base = SHARED_KEY_MODE_BASE_EXT; + else + share_key_mode_base = SHARED_KEY_MODE_BASE; + } +#endif /* RTMP_MAC */ + + /* Update cipher algorithm. WSTA always use BSS0*/ + RTMP_IO_READ32(pAd, share_key_mode_base + 4 * (BssIndex/2), &csr1.word); + DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, share_key_mode_base+ 4 * (BssIndex/2), csr1.word); + } +} + + +/* IRQL = DISPATCH_LEVEL*/ +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx) +{ + /*ULONG SecCsr0;*/ + SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); + + { + UINT32 share_key_mode_base = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + share_key_mode_base= RLT_SHARED_KEY_MODE_BASE; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + share_key_mode_base = SHARED_KEY_MODE_BASE; +#endif /* RTMP_MAC */ + + RTMP_IO_READ32(pAd, share_key_mode_base+4*(BssIndex/2), &csr1.word); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = 0; + else + csr1.field.Bss0Key3CipherAlg = 0; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = 0; + else + csr1.field.Bss1Key3CipherAlg = 0; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, share_key_mode_base+4*(BssIndex/2), csr1.word); + } + ASSERT(BssIndex < 4); + ASSERT(KeyIdx < 4); + +} + + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV) +{ + ULONG offset; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = iveiv_tb_base + (WCID * iveiv_tb_size); + + RTMP_IO_WRITE32(pAd, offset, uIV); + RTMP_IO_WRITE32(pAd, offset + 4, uEIV); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: wcid(%d) 0x%08lx, 0x%08lx \n", + __FUNCTION__, WCID, uIV, uEIV)); +} + + +VOID AsicUpdateRxWCIDTable( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN PUCHAR pAddr) +{ + ULONG offset; + ULONG Addr; + + offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); + Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = pAddr[4] + (pAddr[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); +} + + +/* + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. + Return: + + Note : + The key table selection rule : + 1. Wds-links and Mesh-links always use Pair-wise key table. + 2. When the CipherAlg is TKIP, AES, SMS4 or the dynamic WEP is enabled, + it needs to set key into Pair-wise Key Table. + 3. The pair-wise key security mode is set NONE, it means as no security. + 4. In STA Adhoc mode, it always use shared key table. + 5. Otherwise, use shared key table + + ======================================================================== +*/ +VOID AsicUpdateWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN UINT8 Wcid, + IN UINT8 KeyTabFlag) +{ + WCID_ATTRIBUTE_STRUC WCIDAttri; + USHORT offset; + UINT32 wcid_attr_base = 0, wcid_attr_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + } +#endif /* RTMP_MAC */ + + /* Initialize the content of WCID Attribue */ + WCIDAttri.word = 0; + + /* The limitation of HW WCID table */ + if (Wcid > 254) + { + DBGPRINT(RT_DEBUG_WARN, ("%s:Invalid wcid(%d)\n", __FUNCTION__, Wcid)); + return; + } + + /* Update the pairwise key security mode. + Use bit10 and bit3~1 to indicate the pairwise cipher mode */ + WCIDAttri.field.PairKeyModeExt = ((CipherAlg & 0x08) >> 3); + WCIDAttri.field.PairKeyMode = (CipherAlg & 0x07); + + /* Update the MBSS index. + Use bit11 and bit6~4 to indicate the BSS index */ + WCIDAttri.field.BSSIdxExt = ((BssIdx & 0x08) >> 3); + WCIDAttri.field.BSSIdx = (BssIdx & 0x07); + +#ifdef WAPI_SUPPORT + /* Update WAPI related information */ + if (CipherAlg == CIPHER_SMS4) + { + if (KeyTabFlag == SHAREDKEYTABLE) + WCIDAttri.field.WAPI_MCBC = 1; + WCIDAttri.field.WAPIKeyIdx = ((KeyIdx == 0) ? 0 : 1); + } +#endif /* WAPI_SUPPORT */ + + /* Assign Key Table selection */ + WCIDAttri.field.KeyTab = KeyTabFlag; + + /* Update related information to ASIC */ + offset = wcid_attr_base + (Wcid * wcid_attr_size); + RTMP_IO_WRITE32(pAd, offset, WCIDAttri.word); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:WCID #%d, KeyIdx #%d, WCIDAttri=0x%x, Alg=%s\n", + __FUNCTION__, Wcid, KeyIdx, WCIDAttri.word, CipherName[CipherAlg])); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDelWcidTab(RTMP_ADAPTER *pAd, UCHAR wcid_idx) +{ + UINT32 offset; + UCHAR cnt, cnt_s, cnt_e; +#ifdef MCS_LUT_SUPPORT + UINT32 mcs_tb_offset = 0; +#endif /* MCS_LUT_SUPPORT */ + + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>wcid_idx = 0x%x\n",wcid_idx)); + if (wcid_idx == WCID_ALL) { + cnt_s = 0; + cnt_e = (WCID_ALL - 1); + } else { +#ifdef MCS_LUT_SUPPORT + if (RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT)) + mcs_tb_offset = 0x400; +#endif /* MCS_LUT_SUPPORT */ + cnt_s = cnt_e = wcid_idx; + } + + for (cnt = cnt_s; cnt_s <= cnt_e; cnt_s++) + { + offset = MAC_WCID_BASE + cnt * HW_WCID_ENTRY_SIZE; + RTMP_IO_WRITE32(pAd, offset, 0x0); + RTMP_IO_WRITE32(pAd, offset + 4, 0x0); +#ifdef MCS_LUT_SUPPORT + if (mcs_tb_offset) { + offset += mcs_tb_offset; + RTMP_IO_WRITE32(pAd, offset, 0x0); + RTMP_IO_WRITE32(pAd, offset + 4, 0x0); + } +#endif /* MCS_LUT_SUPPORT */ + } +} + + +/* + ======================================================================== + Description: + Add Pair-wise key material into ASIC. + Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + + Return: + ======================================================================== +*/ +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PCIPHER_KEY pCipherKey) +{ + INT i; + ULONG offset; + UINT32 pairwise_key_base = 0, pairwise_key_len = 0; + UCHAR *pKey = pCipherKey->Key; + UCHAR *pTxMic = pCipherKey->TxMic; + UCHAR *pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; +#ifdef RTMP_MAC +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + unsigned long irqFlag = 0; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + pairwise_key_base = RLT_PAIRWISE_KEY_TABLE_BASE; + pairwise_key_len = RLT_HW_KEY_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pairwise_key_base = PAIRWISE_KEY_TABLE_BASE; + pairwise_key_len = HW_KEY_ENTRY_SIZE; +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + RTMP_MAC_SHR_MSEL_LOCK(pAd, LOWER_SHRMEM, irqFlag); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + } +#endif /* RTMP_MAC */ + + /* EKEY */ + offset = pairwise_key_base + (WCID * pairwise_key_len); +#ifdef RTMP_MAC_PCI + for (i=0; ichipCap.hif_type == HIF_RTMP) { + RTMP_MAC_SHR_MSEL_UNLOCK(pAd, LOWER_SHRMEM, irqFlag); + } +#endif /* SPECIFIC_BCN_BUF_SUPPORT*/ +#endif /* RTMP_MAC_PCI */ +#endif /* RTMP_MAC */ + DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +} + + +/* + ======================================================================== + Description: + Remove Pair-wise key material from ASIC. + + Return: + ======================================================================== +*/ +VOID AsicRemovePairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + /* Set the specific WCID attribute entry as OPEN-NONE */ + AsicUpdateWcidAttributeEntry(pAd, + BSS0, + 0, + CIPHER_NONE, + Wcid, + PAIRWISEKEYTABLE); +} + + +BOOLEAN AsicSendCommandToMcu( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic) +{ +#ifdef RT65xx + // TODO: shiang-6590, fix me, currently firmware is not ready yet, so ignore it! + if (IS_RT65XX(pAd)) + return TRUE; +#endif /* RT65xx */ + + +#ifdef RTMP_PCI_SUPPORT + if (IS_PCI_INF(pAd)) + in_atomic = TRUE; +#endif /* RTMP_USB_SUPPORT */ + if (pAd->chipOps.sendCommandToMcu) + return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + else + return FALSE; +} + + +BOOLEAN AsicSendCmdToMcuAndWait( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic) +{ + BOOLEAN cmd_done = TRUE; + + AsicSendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + +#ifdef RTMP_MAC_PCI + cmd_done = AsicCheckCommanOk(pAd, Token); +#endif /* RTMP_MAC_PCI */ + + return cmd_done; +} + + +BOOLEAN AsicSendCommandToMcuBBP( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked) +{ +#ifdef RT65xx + // TODO: shiang-6590, fix me, currently firmware is not ready yet, so ignore it! + if (IS_RT65XX(pAd)) + return TRUE; +#endif /* RT65xx */ + + + if (pAd->chipOps.sendCommandToMcu) + return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, FlgIsNeedLocked); + else + return FALSE; +} + +/* + ======================================================================== + Description: + For 1x1 chipset : 2070 / 3070 / 3090 / 3370 / 3390 / 5370 / 5390 + Usage : 1. Set Default Antenna as initialize + 2. Antenna Diversity switching used + 3. iwpriv command switch Antenna + + Return: + ======================================================================== + */ +VOID AsicSetRxAnt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ant) +{ + if (pAd->chipOps.SetRxAnt) + pAd->chipOps.SetRxAnt(pAd, Ant); +} + + +VOID AsicTurnOffRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + if (pAd->chipOps.AsicRfTurnOff) + { + pAd->chipOps.AsicRfTurnOff(pAd); + } + else + { +#if defined(RT28xx) || defined(RT2880) || defined(RT2883) + /* RF R2 bit 18 = 0*/ + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + + RFRegTable = RF2850RegTable; +#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */ + + switch (pAd->RfIcType) + { +#if defined(RT28xx) || defined(RT2880) || defined(RT2883) +#if defined(RT28xx) || defined(RT2880) + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: +#endif /* defined(RT28xx) || defined(RT2880) */ + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R1 = RFRegTable[index].R1 & 0xffffdfff; + R2 = RFRegTable[index].R2 & 0xfffbffff; + R3 = RFRegTable[index].R3 & 0xfff3ffff; + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + + /* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */ + /* Set RF R2 bit18=0, R3 bit[18:19]=0*/ + /*if (pAd->StaCfg.bRadio == FALSE)*/ + if (1) + { + RTMP_RF_IO_WRITE32(pAd, R3); + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", + Channel, pAd->RfIcType, R2, R3)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", + Channel, pAd->RfIcType, R2)); + break; + } + } + break; +#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d : Unkonwn RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } +} + + +#ifdef WAPI_SUPPORT +VOID AsicUpdateWAPIPN( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG pn_low, + IN ULONG pn_high) +{ + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 offset; + UINT32 wapi_pn_base = 0, wapi_pn_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wapi_pn_base = RLT_WAPI_PN_TABLE_BASE; + wapi_pn_size = RLT_WAPI_PN_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wapi_pn_base = WAPI_PN_TABLE_BASE; + wapi_pn_size = WAPI_PN_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = wapi_pn_base + (WCID * wapi_pn_size); + + RTMP_IO_WRITE32(pAd, offset, pn_low); + RTMP_IO_WRITE32(pAd, offset + 4, pn_high); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n", + __FUNCTION__)); + } + +} +#endif /* WAPI_SUPPORT */ + + + +#ifdef VCORECAL_SUPPORT +VOID AsicVCORecalibration( + IN PRTMP_ADAPTER pAd) +{ + UCHAR RFValue = 0; + UINT32 TxPinCfg = 0; + UINT8 mode = pAd->chipCap.FlgIsVcoReCalMode; + + if (mode == VCO_CAL_DISABLE) + return; + +#ifdef RT6352 + if (IS_RT6352(pAd) && (pAd->bCalibrationDone == FALSE)) + return; +#endif /* RT6352 */ + + +#ifdef RTMP_INTERNAL_TX_ALC +#endif /* RTMP_INTERNAL_TX_ALC */ + + RTMP_IO_READ32(pAd, TX_PIN_CFG, &TxPinCfg); + TxPinCfg &= 0xFCFFFFF0; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + switch (mode) + { + case VCO_CAL_MODE_1: + RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x01; /* bit 0 = vcocal_en */ + RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue); + break; + + case VCO_CAL_MODE_2: + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7 = vcocal_en */ + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + break; + + case VCO_CAL_MODE_3: +#ifdef RT6352 + if (IS_RT6352(pAd)) { + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R05, 0x40); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R04, 0x0C); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R04, &RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en*/ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R04, RFValue); + } +#endif /* RT6352 */ +#ifdef RT8592 + if (IS_RT8592(pAd)) + { + RT30xxReadRFRegister(pAd, RF_R05, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7 = vcocal_en */ + RT30xxWriteRFRegister(pAd, RF_R05, (UCHAR)RFValue); + } +#endif /* RT8592 */ + break; + + default: + return; + } + + if (mode == VCO_CAL_MODE_3 && (!IS_RT6352(pAd))) + RtmpusecDelay(100); + else + RtmpOsMsDelay(1); + + RTMP_IO_READ32(pAd, TX_PIN_CFG, &TxPinCfg); + if (pAd->CommonCfg.Channel <= 14) + { + if (pAd->Antenna.field.TxPath == 1 +#ifdef GREENAP_SUPPORT + || pAd->ApCfg.bGreenAPActive == TRUE /* avoid to corrupt GreenAP operation */ +#endif /* GREENAP_SUPPORT */ + ) + TxPinCfg |= 0x2; + else if (pAd->Antenna.field.TxPath == 2) + TxPinCfg |= 0xA; + else if (pAd->Antenna.field.TxPath == 3) + TxPinCfg |= 0x0200000A; + } + else + { + if (pAd->Antenna.field.TxPath == 1 +#ifdef GREENAP_SUPPORT + || pAd->ApCfg.bGreenAPActive == TRUE /* avoid to corrupt GreenAP operation */ +#endif /* GREENAP_SUPPORT */ + ) + TxPinCfg |= 0x1; + else if (pAd->Antenna.field.TxPath == 2) + TxPinCfg |= 0x5; + else if (pAd->Antenna.field.TxPath == 3) + TxPinCfg |= 0x01000005; + } + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + +#ifdef TXBF_SUPPORT + // Do a Divider Calibration and update BBP registers + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_DISABLE_CAL)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + { + pAd->chipOps.fITxBfDividerCalibration(pAd, 2, 0, NULL); + } + + if (pAd->CommonCfg.ETxBfEnCond) + { + INT idx; + + for (idx = 1; idx < MAX_LEN_OF_MAC_TABLE; idx++) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = &pAd->MacTab.Content[idx]; + if ((IS_ENTRY_CLIENT(pEntry)) && (pEntry->eTxBfEnCond)) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pEntry->eTxBfProbeTimer, &Cancelled); + pEntry->bfState = READY_FOR_SNDG0; + eTxBFProbing(pAd, pEntry); + } + } + } +#endif // TXBF_SUPPORT // +} +#endif /* VCORECAL_SUPPORT */ + + +#ifdef STREAM_MODE_SUPPORT +// StreamModeRegVal - return MAC reg value for StreamMode setting +UINT32 StreamModeRegVal( + IN RTMP_ADAPTER *pAd) +{ + UINT32 streamWord; + + switch (pAd->CommonCfg.StreamMode) + { + case 1: + streamWord = 0x030000; + break; + case 2: + streamWord = 0x0c0000; + break; + case 3: + streamWord = 0x0f0000; + break; + default: + streamWord = 0x0; + break; + } + + return streamWord; +} + + +/* + ======================================================================== + Description: + configure the stream mode of specific MAC or all MAC and set to ASIC. + + Prameters: + pAd --- + pMacAddr --- + bClear --- disable the stream mode for specific macAddr when + (pMacAddr!=NULL) + + Return: + ======================================================================== +*/ +VOID AsicSetStreamMode( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddr, + IN INT chainIdx, + IN BOOLEAN bEnabled) +{ + UINT32 streamWord; + UINT32 regAddr, regVal; + + + if (!pAd->chipCap.FlgHwStreamMode) + return; + + streamWord = StreamModeRegVal(pAd); + if (!bEnabled) + streamWord = 0; + + regAddr = TX_CHAIN_ADDR0_L + chainIdx * 8; + RTMP_IO_WRITE32(pAd, regAddr, + (UINT32)(pMacAddr[0]) | + (UINT32)(pMacAddr[1] << 8) | + (UINT32)(pMacAddr[2] << 16) | + (UINT32)(pMacAddr[3] << 24)); + + RTMP_IO_READ32(pAd, regAddr + 4, ®Val); + regVal &= (~0x000f0000); + RTMP_IO_WRITE32(pAd, regAddr + 4, + (regVal | streamWord) | + (UINT32)(pMacAddr[4]) | + (UINT32)(pMacAddr[5] << 8)); + +} + + +VOID RtmpStreamModeInit(RTMP_ADAPTER *pAd) +{ + int chainIdx; + UCHAR *pMacAddr; + + if (pAd->chipCap.FlgHwStreamMode == FALSE) + return; + + for (chainIdx = 0; chainIdx < STREAM_MODE_STA_NUM; chainIdx++) + { + pMacAddr = &pAd->CommonCfg.StreamModeMac[chainIdx][0]; + AsicSetStreamMode(pAd, pMacAddr, chainIdx, TRUE); + } +} +#endif // STREAM_MODE_SUPPORT // + + +VOID AsicSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble) +{ + AUTO_RSP_CFG_STRUC csr4; + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + if (TxPreamble == Rt802_11PreambleLong) + csr4.field.AutoResponderPreamble = 0; + else + csr4.field.AutoResponderPreamble = 1; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} + + +#ifdef DOT11_N_SUPPORT +INT AsicSetRalinkBurstMode(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + if (enable) + { + pAd->CommonCfg.RestoreBurstMode = Data; + Data &= 0xFFF00000; + Data |= 0x86380; + } else { + Data = pAd->CommonCfg.RestoreBurstMode; + Data &= 0xFFFFFF00; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif // DOT11_N_SUPPORT // + ) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + Data |= 0x80; + else if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + if (enable) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + else + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + + + + +#ifdef MICROWAVE_OVEN_SUPPORT +VOID AsicMeasureFalseCCA( + IN PRTMP_ADAPTER pAd +) +{ + if (pAd->chipOps.AsicMeasureFalseCCA) + pAd->chipOps.AsicMeasureFalseCCA(pAd); +} + +VOID AsicMitigateMicrowave( + IN PRTMP_ADAPTER pAd +) +{ + if (pAd->chipOps.AsicMitigateMicrowave) + pAd->chipOps.AsicMitigateMicrowave(pAd); +} +#endif /* MICROWAVE_OVEN_SUPPORT */ + + +INT AsicSetPreTbttInt(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 val; + + RTMP_IO_READ32(pAd, INT_TIMER_CFG, &val); + val &= 0xffff0000; + val |= 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */ + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, val); + /* Enable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &val); + val |=0x1; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, val); + + return TRUE; +} + + +BOOLEAN AsicWaitPDMAIdle(struct _RTMP_ADAPTER *pAd, INT round, INT wait_us) +{ + INT i = 0; + WPDMA_GLO_CFG_STRUC GloCfg; + + + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) { + DBGPRINT(RT_DEBUG_TRACE, ("==> DMAIdle, GloCfg=0x%x\n", GloCfg.word)); + return TRUE; + } + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + RtmpusecDelay(wait_us); + }while ((i++) < round); + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy, GloCfg=0x%x\n", GloCfg.word)); + + return FALSE; +} + + +INT rtmp_asic_top_init(RTMP_ADAPTER *pAd) +{ + UINT32 mac_val; + +#ifdef RLT_MAC +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + UINT32 MacValue; + RTMP_IO_READ32(pAd, MAC_CSR0, &MacValue); + pAd->MACVersion = MacValue; + + if ((pAd->MACVersion == 0xffffffff) || (pAd->MACVersion == 0)) + mt76x2_pwrOn(pAd); + } +#endif + + if (IS_MT76x0(pAd) || IS_MT76x2(pAd) || IS_MT7601(pAd)) { + if (pAd->WlanFunCtrl.field.WLAN_EN == 0) + rlt_wlan_chip_onoff(pAd, TRUE, FALSE); + } +#endif /* RLT_MAC */ + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* If dirver doesn't wake up firmware here,*/ + /* NICLoadFirmware will hang forever when interface is up again.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + AsicForceWakeup(pAd, TRUE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + } + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + /* Make sure MAC gets ready.*/ + if (WaitForAsicReady(pAd) != TRUE) + return FALSE; + +#ifdef RTMP_MAC_PCI + +#if defined(RT65xx) || defined(MT7601) + if (IS_RT65XX(pAd) || IS_MT7601(pAd)) + mac_val = 0x0; + else +#endif /* defined(RT65xx) || defined(MT7601) */ + mac_val = 0x2; /* To fix driver disable/enable hang issue when radio off*/ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, mac_val); +#endif /* RTMP_MAC_PCI */ + + return TRUE; +} + + +INT StopDmaRx(RTMP_ADAPTER *pAd, UCHAR Level) +{ + PNDIS_PACKET pRxPacket; + RX_BLK RxBlk, *pRxBlk; + UINT32 RxPending = 0, MacReg = 0, MTxCycle = 0; + BOOLEAN bReschedule = FALSE; + BOOLEAN bCmdRspPacket = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + /* + process whole rx ring + */ + while (1) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return 0; + pRxBlk = &RxBlk; + pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending, &bCmdRspPacket, 0); + if ((RxPending == 0) && (bReschedule == FALSE)) + { + if (pRxPacket) + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + + break; + } + else + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + } + + /* + Check DMA Rx idle + */ + for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++) + { +#ifdef RTMP_MAC_PCI + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + if (MacReg & 0x8) + { + RtmpusecDelay(50); + } + else + break; + +#endif + + + if (MacReg == 0xFFFFFFFF) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + return 0; + } + } + + if (MTxCycle >= 2000) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:RX DMA busy!! DMA_CFG = 0x%08x\n", __FUNCTION__, MacReg)); + } + + if (Level == RTMP_HALT) + { + /* Disable DMA RX */ +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + MacReg &= ~(0x4); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, MacReg); +#endif + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + + return 0; +} + + +INT StopDmaTx(RTMP_ADAPTER *pAd, UCHAR Level) +{ + UINT32 MacReg = 0, MTxCycle = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + if ((MacReg & 0x2) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("==> DMA Tx Idle, MacReg=0x%x\n", MacReg)); + break; + } +#endif + + + if (MacReg == 0xFFFFFFFF) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + return 0; + } + } + + if (MTxCycle >= 2000) + { + DBGPRINT(RT_DEBUG_ERROR, ("TX DMA busy!! DMA_CFG(%x)\n", MacReg)); + } + + if (Level == RTMP_HALT) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + MacReg &= ~(0x00000001); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, MacReg); +#endif + + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + + return 0; +} + + +#ifdef DOT11_N_SUPPORT +#ifdef MT76x2 +#define MAX_AGG_CNT 48 +#elif defined(RT65xx) || defined(MT7601) +#define MAX_AGG_CNT 32 +#elif defined(RT2883) || defined(RT3883) +#define MAX_AGG_CNT 16 +#else +#define MAX_AGG_CNT 8 +#endif +INT AsicReadAggCnt(RTMP_ADAPTER *pAd, ULONG *aggCnt, int cnt_len) +{ + UINT32 reg_addr; + TX_AGG_CNT_STRUC reg_val; + int i, cnt, seg; + static USHORT aggReg[] = { + TX_AGG_CNT, TX_AGG_CNT3, +#if MAX_AGG_CNT > 8 + TX_AGG_CNT4, TX_AGG_CNT7, +#endif +#if MAX_AGG_CNT > 16 + TX_AGG_CNT8, TX_AGG_CNT15, +#endif +#if MAX_AGG_CNT > 32 + TX_AGG_CNT16, TX_AGG_CNT23, +#endif + }; + + + NdisZeroMemory(aggCnt, cnt_len * sizeof(ULONG)); + seg = (sizeof(aggReg) /sizeof(USHORT)); + + cnt = 0; + for (i = 0; i < seg; i += 2) + { + for (reg_addr = aggReg[i] ; reg_addr <= aggReg[i+1] ; reg_addr += 4) + { + RTMP_IO_READ32(pAd, reg_addr, ®_val.word); + if (cnt < (cnt_len -1)) { + aggCnt[cnt] = reg_val.field.AggCnt_x; + aggCnt[cnt+1] = reg_val.field.AggCnt_y; + DBGPRINT(RT_DEBUG_TRACE, ("%s():Get AggSize at Reg(0x%x) with val(0x%08x) [AGG_%d=>%ld, AGG_%d=>%ld]\n", + __FUNCTION__, reg_addr, reg_val.word, cnt, aggCnt[cnt], cnt+1, aggCnt[cnt+1])); + cnt += 2; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("%s():Get AggSize at Reg(0x%x) failed, no enough buffer(cnt_len=%d, cnt=%d)\n", + __FUNCTION__, reg_addr, cnt_len, cnt)); + } + } + } + + return TRUE; +} + +#endif /* DOT11_N_SUPPORT */ + + +INT AsicSetChannel(RTMP_ADAPTER *pAd, UCHAR ch, UINT8 bw, UINT8 ext_ch, BOOLEAN bScan) +{ + bbp_set_bw(pAd, bw); + + /* Tx/RX : control channel setting */ + bbp_set_ctrlch(pAd, ext_ch); + rtmp_mac_set_ctrlch(pAd, ext_ch); + + /* Let BBP register at 20MHz to do scan */ + AsicSwitchChannel(pAd, ch, bScan); + AsicLockChannel(pAd, ch); + +#ifdef RT28xx + RT28xx_ch_tunning(pAd, bw); +#endif /* RT28xx */ + + return 0; +} + + +#ifdef MAC_APCLI_SUPPORT +/* + ========================================================================== + Description: + Set BSSID of Root AP + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetApCliBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN UCHAR index) +{ + UINT32 Addr4 = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():%x:%x:%x:%x:%x:%x\n", + __FUNCTION__, PRINT_MAC(pBssid))); + + Addr4 = (UINT32)(pBssid[0]) | + (UINT32)(pBssid[1] << 8) | + (UINT32)(pBssid[2] << 16) | + (UINT32)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_APCLI_BSSID_DW0, Addr4); + + Addr4 = 0; + Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + /* Enable APCLI mode */ + Addr4 |= 0x10000; + + RTMP_IO_WRITE32(pAd, MAC_APCLI_BSSID_DW1, Addr4); +} +#endif /* MAC_APCLI_SUPPORT */ + +#ifdef NEW_WOW_SUPPORT +VOID RT28xxAndesWOWEnable( + IN PRTMP_ADAPTER pAd) +{ + NEW_WOW_MASK_CFG_STRUCT mask_cfg; + NEW_WOW_SEC_CFG_STRUCT sec_cfg; + NEW_WOW_INFRA_CFG_STRUCT infra_cfg; + NEW_WOW_P2P_CFG_STRUCT p2p_cfg; + NEW_WOW_PARAM_STRUCT wow_param; + struct CMD_UNIT CmdUnit; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + INT32 Ret; + MAC_TABLE_ENTRY *pEntry = NULL; + + + NdisZeroMemory(&CmdUnit, sizeof(CmdUnit)); + + /* WOW enable */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + + wow_param.Parameter = WOW_ENABLE; /* WOW enable */ + wow_param.Value = TRUE; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + /* mask configuration */ + NdisZeroMemory(&mask_cfg, sizeof(mask_cfg)); + + mask_cfg.Config_Type = WOW_MASK_CFG; /* detect mask config */ + mask_cfg.Function_Enable = TRUE; + mask_cfg.Detect_Mask = 1UL << WOW_MAGIC_PKT; /* magic packet */ + mask_cfg.Event_Mask = 0; + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_MASK_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&mask_cfg; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!(%d/%d)\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, mask_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + + /* security configuration */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPAPSK) + { + NdisZeroMemory(&sec_cfg, sizeof(sec_cfg)); + + sec_cfg.Config_Type = WOW_SEC_CFG; /* security config */ + + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + sec_cfg.WPA_Ver = 0; + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + sec_cfg.WPA_Ver = 1; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + NdisCopyMemory(sec_cfg.PTK, pEntry->PTK, 64); + NdisCopyMemory(sec_cfg.R_COUNTER, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + + sec_cfg.Key_Id = pAd->StaCfg.DefaultKeyId; + sec_cfg.Cipher_Alg = pEntry->WepStatus; + printk("\x1b[31m%s: wep status %d\x1b[m\n", __FUNCTION__, pEntry->WepStatus); + sec_cfg.Group_Cipher = pAd->StaCfg.GroupCipher; + printk("\x1b[31m%s: group status %d\x1b[m\n", __FUNCTION__, sec_cfg.Group_Cipher); + printk("\x1b[31m%s: aid %d\x1b[m\n", __FUNCTION__, pEntry->Aid); + sec_cfg.WCID = BSSID_WCID; + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_SEC_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&sec_cfg; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, sec_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + } + + /* Infra configuration */ + + NdisZeroMemory(&infra_cfg, sizeof(infra_cfg)); + + infra_cfg.Config_Type = WOW_INFRA_CFG; /* infra config */ + + COPY_MAC_ADDR(infra_cfg.STA_MAC, pAd->CurrentAddress); + COPY_MAC_ADDR(infra_cfg.AP_MAC, pAd->CommonCfg.Bssid); + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_INFRA_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&infra_cfg; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + infra_cfg.AP_Status = TRUE; + else + infra_cfg.AP_Status = FALSE; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, infra_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + + + /* P2P configuration */ + + /* Wakeup Option */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + + wow_param.Parameter = WOW_WAKEUP; /* Wakeup Option */ + if (pAd->WOW_Cfg.bInBand) + { +#ifdef RTMP_MAC_PCI + wow_param.Value = WOW_WAKEUP_BY_PCIE; +#else + wow_param.Value = WOW_WAKEUP_BY_USB; +#endif /* RTMP_MAC_PCI */ + } + else + { + INT32 Value; + + wow_param.Value = WOW_WAKEUP_BY_GPIO; + + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */ + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + } + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + + + /* traffic to Andes */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + wow_param.Parameter = WOW_TRAFFIC; /* Traffic switch */ + wow_param.Value = WOW_PKT_TO_ANDES; /* incoming packet to FW */ + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param.Parameter; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); +} + +VOID RT28xxAndesWOWDisable( + IN PRTMP_ADAPTER pAd) +{ + NEW_WOW_PARAM_STRUCT param; + struct CMD_UNIT CmdUnit; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + INT32 Ret; + UINT32 Value; + MAC_TABLE_ENTRY *pEntry = NULL; + + printk("\x1b[31m%s: ...\x1b[m", __FUNCTION__); + + /* clean BulkIn Reset flag */ + //pAd->Flags &= ~0x80000; + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + NdisZeroMemory(&CmdUnit, sizeof(CmdUnit)); + + /* WOW disable */ + NdisZeroMemory(¶m, sizeof(param)); + param.Parameter = WOW_ENABLE; + param.Value = FALSE; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* WOW enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)¶m; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__); + return; + } + + RtmpOsMsDelay(1); + + + /* traffic to Host */ + NdisZeroMemory(¶m, sizeof(param)); + param.Parameter = WOW_TRAFFIC; + param.Value = WOW_PKT_TO_HOST; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)¶m; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__); + return; + } + + RtmpOsMsDelay(1); + + + /* Restore MAC TX/RX */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= 0xC; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + + RTUSBBulkReceive(pAd); + RTUSBBulkCmdRspEventReceive(pAd); + + //printk("\x1b[31m%s: pendingRx %d\x1b[m\n", __FUNCTION__, pAd->PendingRx); + //printk("\x1b[31m%s: BulkInReq %d\x1b[m\n", __FUNCTION__, pAd->BulkInReq); + + /* restore hardware remote wakeup flag */ + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 %08x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x80; + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + + if (pAd->WOW_Cfg.bInBand == FALSE) + { + INT32 Value; + + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */ + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + } +} + +#endif /* NEW_WOW_SUPPORT */ + +#ifdef THERMAL_PROTECT_SUPPORT +VOID thermal_protection( + IN RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + INT32 temp_diff = 0, current_temp = 0; +#ifdef CONFIG_STA_SUPPORT +#endif /* RTMP_MAC_USB */ + + if (pAd->chipCap.ThermalProtectSup == FALSE) + return; + + /* If MT7662U go into suspend mode, thermal clock will also be disabled. + After resume, MCU will hang if driver retrieve thermal value without calibration. */ +#ifdef CONFIG_STA_SUPPORT +#endif /* RTMP_MAC_USB */ + +#ifdef MT76x2 + UINT32 mac_reg = 0; + if (IS_MT76x2(pAd)) + { + current_temp = pAd->chipCap.current_temp; + /* 2T2R to 1T2R */ + if (pAd->thermal_HighEn == TRUE) + { + if ((current_temp > pAd->thermal_HighTempTh) && + (pAd->force_one_tx_stream == FALSE)) + { + pAd->force_one_tx_stream = TRUE; + + /* 0x504: Trun on BIT[13][14] */ + RTMP_IO_READ32(pAd, RLT_RF_BYPASS_0, &mac_reg); + mac_reg |= (3 << 13); + RTMP_IO_WRITE32(pAd, RLT_RF_BYPASS_0, mac_reg); + + /* 0x50C: Trun off BIT[13][14] */ + RTMP_IO_READ32(pAd, RLT_RF_SETTING_0, &mac_reg); + mac_reg &= ~(3 << 13); + RTMP_IO_WRITE32(pAd, RLT_RF_SETTING_0, mac_reg); + + DBGPRINT(RT_DEBUG_OFF, ("%s - current temp=%d > HighTempTh =%d switch to 1T\n", + __FUNCTION__, current_temp, pAd->thermal_HighTempTh)); + } + } + + /* 1T2R to 2T2R */ + if (pAd->thermal_LowEn == TRUE) + { + if ((current_temp < pAd->thermal_LowTempTh) && + (pAd->force_one_tx_stream == TRUE)) + { + + /* 0x504: Trun off BIT[13][14] */ + RTMP_IO_READ32(pAd, RLT_RF_BYPASS_0, &mac_reg); + mac_reg &= ~(3 << 13); + RTMP_IO_WRITE32(pAd, RLT_RF_BYPASS_0, mac_reg); + + /* 0x50C: Trun off BIT[13][14] */ + RTMP_IO_READ32(pAd, RLT_RF_SETTING_0, &mac_reg); + mac_reg &= ~(3 << 13); + RTMP_IO_WRITE32(pAd, RLT_RF_SETTING_0, mac_reg); + + DBGPRINT(RT_DEBUG_OFF, ("%s - current temp=%d > HighTempTh =%d switch to 1T\n", + __FUNCTION__, current_temp, pAd->thermal_HighTempTh)); + + pAd->force_one_tx_stream = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s - current temp=%d < HighTempTh =%d restore to 2T\n", + __FUNCTION__, current_temp, pAd->thermal_LowTempTh)); + } + } + + return; + } +#endif /* MT76x2 */ + + RTMP_CHIP_GET_CURRENT_TEMP(pAd, current_temp); + temp_diff = current_temp - pAd->last_thermal_pro_temp; + pAd->last_thermal_pro_temp = current_temp; + + DBGPRINT(RT_DEBUG_INFO, ("%s - current temp=%d, temp diff=%d\n", + __FUNCTION__, current_temp, temp_diff)); + + if (temp_diff > 0) { + if (current_temp > (pAd->thermal_pro_criteria + 10) /* 90 */) + RTMP_CHIP_THERMAL_PRO_2nd_COND(pAd); + else if (current_temp > pAd->thermal_pro_criteria /* 80 */) + RTMP_CHIP_THERMAL_PRO_1st_COND(pAd); + else + RTMP_CHIP_THERMAL_PRO_DEFAULT_COND(pAd); + } else if (temp_diff < 0) { + if (current_temp < (pAd->thermal_pro_criteria - 5) /* 75 */) + RTMP_CHIP_THERMAL_PRO_DEFAULT_COND(pAd); + else if (current_temp < (pAd->thermal_pro_criteria + 5) /* 85 */) + RTMP_CHIP_THERMAL_PRO_1st_COND(pAd); + else + RTMP_CHIP_THERMAL_PRO_2nd_COND(pAd); + } +} +#endif /* THERMAL_PROTECT_SUPPORT */ + +#ifdef DROP_MASK_SUPPORT +VOID asic_set_drop_mask( + PRTMP_ADAPTER ad, + USHORT wcid, + BOOLEAN enable) +{ + UINT32 mac_reg = 0, mac_old, reg_id, group_index; + UINT32 drop_mask = (1U << (wcid % 32)); + + /* each group has 32 entries */ + group_index = (wcid - (wcid % 32)) >> 5 /* divided by 32 */; + reg_id = (TX_WCID_DROP_MASK0 + 4*group_index); + + NdisAcquireSpinLock(&ad->drop_mask_lock); + + RTMP_IO_READ32(ad, reg_id, &mac_reg); + mac_old = mac_reg; + mac_reg = (enable ? (mac_reg | drop_mask) : (mac_reg & ~drop_mask)); + if (mac_reg != mac_old) + RTMP_IO_WRITE32(ad, reg_id, mac_reg); + + NdisReleaseSpinLock(&ad->drop_mask_lock); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%u):, wcid = %u, reg_id = 0x%08x, mac_reg = 0x%08x, group_index = %u, drop_mask = 0x%08x\n", + __FUNCTION__, enable, wcid, reg_id, mac_reg, group_index, drop_mask)); +} + + +VOID asic_drop_mask_reset( + PRTMP_ADAPTER ad) +{ + UINT32 i, reg_id; + + NdisAcquireSpinLock(&ad->drop_mask_lock); + + for ( i = 0; i < 8 /* num of drop mask group */; i++) + { + reg_id = (TX_WCID_DROP_MASK0 + i*4); + RTMP_IO_WRITE32(ad, reg_id, 0); + } + + NdisReleaseSpinLock(&ad->drop_mask_lock); + + DBGPRINT(RT_DEBUG_TRACE, ("%s()\n", __FUNCTION__)); +} +#endif /* DROP_MASK_SUPPORT */ + +#ifdef MULTI_CLIENT_SUPPORT +VOID asic_change_tx_retry( + IN PRTMP_ADAPTER pAd, + IN USHORT num) +{ + UINT32 TxRtyCfg, MacReg = 0; + + if (num < 3) + { + /* Tx data retry 31/15 (thres 2000) */ + RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg); + TxRtyCfg &= 0xf0000000; + TxRtyCfg |= 0x07d01f0f; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg); + + /* Tx RTS retry default 32, disable RTS fallback */ + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFEFFFF00; + MacReg |= 0x20; + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + } + else + { + /* Tx data retry 8/10 (thres 256) */ + RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg); + TxRtyCfg &= 0xf0000000; + TxRtyCfg |= 0x0100080A; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg); + + /* Tx RTS retry 3, enable RTS fallback */ + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFEFFFF00; + MacReg |= 0x01000003; + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + } +} + +VOID pkt_aggr_num_change( + IN PRTMP_ADAPTER pAd, + IN USHORT num) +{ +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + if (num < 5) + { + /* use default */ + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M1S, 0x77777777); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M2S, 0x77777777); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M1S, 0x77777777); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M2S, 0x77777777); + } + else + { + /* modify by MCS */ + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M1S, 0x77754433); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_20M2S, 0x77765543); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M1S, 0x77765544); + RTMP_IO_WRITE32(pAd, AMPDU_MAX_LEN_40M2S, 0x77765544); + } + } +#endif +} + +VOID asic_tune_be_wmm( + IN PRTMP_ADAPTER pAd, + IN USHORT num) +{ + UCHAR bssCwmin = 4, apCwmin = 4, apCwmax = 6; + + if (num <= 4) + { + /* use profile cwmin */ + if (pAd->CommonCfg.APCwmin > 0 && pAd->CommonCfg.BSSCwmin > 0 && pAd->CommonCfg.APCwmax > 0) + { + apCwmin = pAd->CommonCfg.APCwmin; + apCwmax = pAd->CommonCfg.APCwmax; + bssCwmin = pAd->CommonCfg.BSSCwmin; + } + } + else if (num > 4 && num <= 8) + { + apCwmin = 4; + apCwmax = 6; + bssCwmin = 5; + } + else if (num > 8 && num <= 16) + { + apCwmin = 4; + apCwmax = 6; + bssCwmin = 6; + } + else if (num > 16 && num <= 64) + { + apCwmin = 4; + apCwmax = 6; + bssCwmin = 7; + } + else if (num > 64 && num <= 128) + { + apCwmin = 4; + apCwmax = 6; + bssCwmin = 8; + } + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = apCwmin; + pAd->CommonCfg.APEdcaParm.Cwmax[0] = apCwmax; + pAd->ApCfg.BssEdcaParm.Cwmin[0] = bssCwmin; + + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); +} +#endif /* MULTI_CLIENT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cfg.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cfg.c new file mode 100644 index 000000000..88c83d659 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cfg.c @@ -0,0 +1,3087 @@ +/**************************************************************************** + * 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_cfg.c + + Abstract: + Ralink WiFi Driver configuration related subroutines + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + + + +#include "rt_config.h" + +static BOOLEAN RT_isLegalCmdBeforeInfUp( + IN PSTRING SetCmd); + + +INT ComputeChecksum( + IN UINT PIN) +{ + INT digit_s; + UINT accum = 0; + + PIN *= 10; + accum += 3 * ((PIN / 10000000) % 10); + accum += 1 * ((PIN / 1000000) % 10); + accum += 3 * ((PIN / 100000) % 10); + accum += 1 * ((PIN / 10000) % 10); + accum += 3 * ((PIN / 1000) % 10); + accum += 1 * ((PIN / 100) % 10); + accum += 3 * ((PIN / 10) % 10); + + digit_s = (accum % 10); + return ((10 - digit_s) % 10); +} /* ComputeChecksum*/ + +UINT GenerateWpsPinCode( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApcli, + IN UCHAR apidx) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + UINT iPin; + UINT checksum; + + NdisZeroMemory(macAddr, MAC_ADDR_LEN); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (bFromApcli) + NdisMoveMemory(&macAddr[0], pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + else +#endif /* APCLI_SUPPORT */ + NdisMoveMemory(&macAddr[0], pAd->ApCfg.MBSSID[apidx].wdev.if_addr, MAC_ADDR_LEN); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(&macAddr[0], pAd->CurrentAddress, MAC_ADDR_LEN); +#endif /* CONFIG_STA_SUPPORT */ + + iPin = macAddr[3] * 256 * 256 + macAddr[4] * 256 + macAddr[5]; + + iPin = iPin % 10000000; + + + checksum = ComputeChecksum( iPin ); + iPin = iPin*10 + checksum; + + return iPin; +} + + +static char *phy_mode_str[]={"CCK", "OFDM", "HTMIX", "GF", "VHT"}; +char* get_phymode_str(int Mode) +{ + if (Mode >= MODE_CCK && Mode <= MODE_VHT) + return phy_mode_str[Mode]; + else + return "N/A"; +} + + +static UCHAR *phy_bw_str[] = {"20M", "40M", "80M", "10M"}; +char* get_bw_str(int bandwidth) +{ + if (bandwidth >= BW_20 && bandwidth <= BW_10) + return phy_bw_str[bandwidth]; + else + return "N/A"; +} + + +/* + ========================================================================== + Description: + Set Country Region to pAd->CommonCfg.CountryRegion. + This command will not work, if the field of CountryRegion in eeprom is programmed. + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetCountryRegion( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN INT band) +{ + LONG region; + UCHAR *pCountryRegion; + + region = simple_strtol(arg, 0, 10); + + if (band == BAND_24G) + pCountryRegion = &pAd->CommonCfg.CountryRegion; + else + pCountryRegion = &pAd->CommonCfg.CountryRegionForABand; + + /* + 1. If this value is set before interface up, do not reject this value. + 2. Country can be set only when EEPROM not programmed + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE) && (*pCountryRegion & EEPROM_IS_PROGRAMMED)) + { + DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():CountryRegion in eeprom was programmed\n")); + return FALSE; + } + + if((region >= 0) && + (((band == BAND_24G) &&((region <= REGION_MAXIMUM_BG_BAND) || + (region == REGION_31_BG_BAND) || (region == REGION_32_BG_BAND) || (region == REGION_33_BG_BAND) )) || + ((band == BAND_5G) && (region <= REGION_MAXIMUM_A_BAND) )) + ) + { + *pCountryRegion= (UCHAR) region; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():region(%ld) out of range!\n", region)); + return FALSE; + } + + return TRUE; + +} + + +static UCHAR CFG_WMODE_MAP[]={ + PHY_11BG_MIXED, (WMODE_B | WMODE_G), /* 0 => B/G mixed */ + PHY_11B, (WMODE_B), /* 1 => B only */ + PHY_11A, (WMODE_A), /* 2 => A only */ + PHY_11ABG_MIXED, (WMODE_A | WMODE_B | WMODE_G), /* 3 => A/B/G mixed */ + PHY_11G, WMODE_G, /* 4 => G only */ + PHY_11ABGN_MIXED, (WMODE_B | WMODE_G | WMODE_GN | WMODE_A | WMODE_AN), /* 5 => A/B/G/GN/AN mixed */ + PHY_11N_2_4G, (WMODE_GN), /* 6 => N in 2.4G band only */ + PHY_11GN_MIXED, (WMODE_G | WMODE_GN), /* 7 => G/GN, i.e., no CCK mode */ + PHY_11AN_MIXED, (WMODE_A | WMODE_AN), /* 8 => A/N in 5 band */ + PHY_11BGN_MIXED, (WMODE_B | WMODE_G | WMODE_GN), /* 9 => B/G/GN mode*/ + PHY_11AGN_MIXED, (WMODE_G | WMODE_GN | WMODE_A | WMODE_AN), /* 10 => A/AN/G/GN mode, not support B mode */ + PHY_11N_5G, (WMODE_AN), /* 11 => only N in 5G band */ +#ifdef DOT11_VHT_AC + PHY_11VHT_N_ABG_MIXED, (WMODE_B | WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC), /* 12 => B/G/GN/A/AN/AC mixed*/ + PHY_11VHT_N_AG_MIXED, (WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC), /* 13 => G/GN/A/AN/AC mixed , no B mode */ + PHY_11VHT_N_A_MIXED, (WMODE_A | WMODE_AN | WMODE_AC), /* 14 => A/AC/AN mixed */ + PHY_11VHT_N_MIXED, (WMODE_AN | WMODE_AC), /* 15 => AC/AN mixed, but no A mode */ +#endif /* DOT11_VHT_AC */ + PHY_MODE_MAX, WMODE_INVALID /* default phy mode if not match */ +}; + + +static PSTRING BAND_STR[] = {"Invalid", "2.4G", "5G", "2.4G/5G"}; +static PSTRING WMODE_STR[]= {"", "A", "B", "G", "gN", "aN", "AC"}; + +UCHAR *wmode_2_str(UCHAR wmode) +{ + UCHAR *str; + INT idx, pos, max_len; + + max_len = WMODE_COMP * 3; + if (os_alloc_mem(NULL, &str, max_len) == NDIS_STATUS_SUCCESS) + { + NdisZeroMemory(str, max_len); + pos = 0; + for (idx = 0; idx < WMODE_COMP; idx++) + { + if (wmode & (1 << idx)) { + if ((strlen(str) + strlen(WMODE_STR[idx + 1])) >= (max_len - 1)) + break; + if (strlen(str)) { + NdisMoveMemory(&str[pos], "/", 1); + pos++; + } + NdisMoveMemory(&str[pos], WMODE_STR[idx + 1], strlen(WMODE_STR[idx + 1])); + pos += strlen(WMODE_STR[idx + 1]); + } + if (strlen(str) >= max_len) + break; + } + + return str; + } + else + return NULL; +} + + +RT_802_11_PHY_MODE wmode_2_cfgmode(UCHAR wmode) +{ + INT i, mode_cnt = sizeof(CFG_WMODE_MAP) / sizeof(UCHAR); + + for (i = 1; i < mode_cnt; i+=2) + { + if (CFG_WMODE_MAP[i] == wmode) + return CFG_WMODE_MAP[i - 1]; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Cannot get cfgmode by wmode(%x)\n", + __FUNCTION__, wmode)); + + return 0; +} + + +UCHAR cfgmode_2_wmode(UCHAR cfg_mode) +{ + DBGPRINT(RT_DEBUG_OFF, ("cfg_mode=%d\n", cfg_mode)); + if (cfg_mode >= PHY_MODE_MAX) + cfg_mode = PHY_MODE_MAX; + + return CFG_WMODE_MAP[cfg_mode * 2 + 1]; +} + + +BOOLEAN wmode_valid(RTMP_ADAPTER *pAd, enum WIFI_MODE wmode) +{ + if ((WMODE_CAP_5G(wmode) && (!PHY_CAP_5G(pAd->chipCap.phy_caps))) || + (WMODE_CAP_2G(wmode) && (!PHY_CAP_2G(pAd->chipCap.phy_caps))) || + (WMODE_CAP_N(wmode) && RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N)) + ) + return FALSE; + else + return TRUE; +} + + +BOOLEAN wmode_band_equal(UCHAR smode, UCHAR tmode) +{ + BOOLEAN eq = FALSE; + UCHAR *str1, *str2; + + if ((WMODE_CAP_5G(smode) == WMODE_CAP_5G(tmode)) && + (WMODE_CAP_2G(smode) == WMODE_CAP_2G(tmode))) + eq = TRUE; + + str1 = wmode_2_str(smode); + str2 = wmode_2_str(tmode); + if (str1 && str2) + { + DBGPRINT(RT_DEBUG_TRACE, + ("Old WirelessMode:%s(0x%x), " + "New WirelessMode:%s(0x%x)!\n", + str1, smode, str2, tmode)); + } + if (str1) + os_free_mem(NULL, str1); + if (str2) + os_free_mem(NULL, str2); + + return eq; +} + + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg) +{ + LONG cfg_mode; + UCHAR wmode, *mode_str; +#ifdef MT76x2 + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; +#endif /* MT76x2 */ + + cfg_mode = simple_strtol(arg, 0, 10); + + /* check if chip support 5G band when WirelessMode is 5G band */ + wmode = cfgmode_2_wmode((UCHAR)cfg_mode); + if ((wmode == WMODE_INVALID) || (!wmode_valid(pAd, wmode))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Invalid wireless mode(%ld, wmode=0x%x), ChipCap(%s)\n", + __FUNCTION__, cfg_mode, wmode, + BAND_STR[pAd->chipCap.phy_caps & 0x3])); + return FALSE; + } + +#ifdef MT76x2 +#ifdef DOT11_VHT_AC + if (pChipCap->ac_off_mode && WMODE_CAP_AC(wmode)) { + DBGPRINT(RT_DEBUG_ERROR, ("it doesn't support VHT AC!\n")); + wmode &= ~(WMODE_AC); + } +#endif /* DOT11_VHT_AC */ +#endif /* MT76x2 */ + + if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE) + DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Equal!\n")); + else + DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Not Equal!\n")); + + pAd->CommonCfg.PhyMode = wmode; + pAd->CommonCfg.cfg_wmode = wmode; + + mode_str = wmode_2_str(wmode); + if (mode_str) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set WMODE=%s(0x%x)\n", + __FUNCTION__, mode_str, wmode)); + os_free_mem(NULL, mode_str); + } + + return TRUE; +} + + +/* maybe can be moved to GPL code, ap_mbss.c, but the code will be open */ +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +static UCHAR RT_CfgMbssWirelessModeMaxGet(RTMP_ADAPTER *pAd) +{ + UCHAR wmode = 0, *mode_str; + INT idx; + struct wifi_dev *wdev; + + for(idx = 0; idx < pAd->ApCfg.BssidNum; idx++) { + wdev = &pAd->ApCfg.MBSSID[idx].wdev; + mode_str = wmode_2_str(wdev->PhyMode); + if (mode_str) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(BSS%d): wmode=%s(0x%x)\n", + __FUNCTION__, idx, mode_str, wdev->PhyMode)); + os_free_mem(pAd, mode_str); + } + wmode |= wdev->PhyMode; + } + + mode_str = wmode_2_str(wmode); + if (mode_str) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Combined WirelessMode = %s(0x%x)\n", + __FUNCTION__, mode_str, wmode)); + os_free_mem(pAd, mode_str); + } + return wmode; +} + + +/* + ========================================================================== + Description: + Set Wireless Mode for MBSS + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetMbssWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT cfg_mode; + UCHAR wmode; +#ifdef MT76x2 + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; +#endif /* MT76x2 */ + + cfg_mode = simple_strtol(arg, 0, 10); + + wmode = cfgmode_2_wmode((UCHAR)cfg_mode); + if ((wmode == WMODE_INVALID) || (!wmode_valid(pAd, wmode))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Invalid wireless mode(%d, wmode=0x%x), ChipCap(%s)\n", + __FUNCTION__, cfg_mode, wmode, + BAND_STR[pAd->chipCap.phy_caps & 0x3])); + return FALSE; + } + + if (WMODE_CAP_5G(wmode) && WMODE_CAP_2G(wmode)) + { + DBGPRINT(RT_DEBUG_ERROR, ("AP cannot support 2.4G/5G band mxied mode!\n")); + return FALSE; + } + + +#ifdef MT76x2 +#ifdef DOT11_VHT_AC + if (pChipCap->ac_off_mode && WMODE_CAP_AC(wmode)) { + DBGPRINT(RT_DEBUG_ERROR, ("it doesn't support VHT AC!\n")); + wmode &= ~(WMODE_AC); + } +#endif /* DOT11_VHT_AC */ +#endif /* MT76x2 */ + + if (pAd->ApCfg.BssidNum > 1) + { + /* pAd->CommonCfg.PhyMode = maximum capability of all MBSS */ + if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE) + { + wmode = RT_CfgMbssWirelessModeMaxGet(pAd); + + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Maximum phy mode = %d!\n", wmode)); + } + else + { + UINT32 IdBss; + + /* replace all phy mode with the one with different band */ + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Different band with the current one!\n")); + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Reset band of all BSS to the new one!\n")); + + for(IdBss=0; IdBssApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].wdev.PhyMode = wmode; + } + } + + pAd->CommonCfg.PhyMode = wmode; + pAd->CommonCfg.cfg_wmode = wmode; + return TRUE; +} +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +static BOOLEAN RT_isLegalCmdBeforeInfUp( + IN PSTRING SetCmd) +{ + BOOLEAN TestFlag; + TestFlag = !strcmp(SetCmd, "Debug") || +#ifdef CONFIG_APSTA_MIXED_SUPPORT + !strcmp(SetCmd, "OpMode") || +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#ifdef EXT_BUILD_CHANNEL_LIST + !strcmp(SetCmd, "CountryCode") || + !strcmp(SetCmd, "DfsType") || + !strcmp(SetCmd, "ChannelListAdd") || + !strcmp(SetCmd, "ChannelListShow") || + !strcmp(SetCmd, "ChannelListDel") || +#endif /* EXT_BUILD_CHANNEL_LIST */ +#ifdef SINGLE_SKU + !strcmp(SetCmd, "ModuleTxpower") || +#endif /* SINGLE_SKU */ + FALSE; /* default */ + return TestFlag; +} + + +INT RT_CfgSetShortSlot( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG ShortSlot; + + ShortSlot = simple_strtol(arg, 0, 10); + + if (ShortSlot == 1) + pAd->CommonCfg.bUseShortSlotTime = TRUE; + else if (ShortSlot == 0) + pAd->CommonCfg.bUseShortSlotTime = FALSE; + else + return FALSE; /*Invalid argument */ + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WEP KEY base on KeyIdx + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetWepKey( + IN PRTMP_ADAPTER pAd, + IN PSTRING keyString, + IN CIPHER_KEY *pSharedKey, + IN INT keyIdx) +{ + INT KeyLen; + INT i; + /*UCHAR CipherAlg = CIPHER_NONE;*/ + BOOLEAN bKeyIsHex = FALSE; + + /* TODO: Shall we do memset for the original key info??*/ + memset(pSharedKey, 0, sizeof(CIPHER_KEY)); + KeyLen = strlen(keyString); + switch (KeyLen) + { + case 5: /*wep 40 Ascii type*/ + case 13: /*wep 104 Ascii type*/ + bKeyIsHex = FALSE; + pSharedKey->KeyLen = KeyLen; + NdisMoveMemory(pSharedKey->Key, keyString, KeyLen); + break; + + case 10: /*wep 40 Hex type*/ + case 26: /*wep 104 Hex type*/ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(keyString+i)) ) + return FALSE; /*Not Hex value;*/ + } + bKeyIsHex = TRUE; + pSharedKey->KeyLen = KeyLen/2 ; + AtoH(keyString, pSharedKey->Key, pSharedKey->KeyLen); + break; + + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWepKey(keyIdx=%d):Invalid argument (arg=%s)\n", keyIdx, keyString)); + return FALSE; + } + + pSharedKey->CipherAlg = ((KeyLen % 5) ? CIPHER_WEP128 : CIPHER_WEP64); + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWepKey:(KeyIdx=%d,type=%s, Alg=%s)\n", + keyIdx, (bKeyIsHex == FALSE ? "Ascii" : "Hex"), CipherName[pSharedKey->CipherAlg])); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WPA PSK key + + Arguments: + pAdapter Pointer to our adapter + keyString WPA pre-shared key string + pHashStr String used for password hash function + hashStrLen Lenght of the hash string + pPMKBuf Output buffer of WPAPSK key + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetWPAPSKKey( + IN RTMP_ADAPTER *pAd, + IN PSTRING keyString, + IN INT keyStringLen, + IN UCHAR *pHashStr, + IN INT hashStrLen, + OUT PUCHAR pPMKBuf) +{ + UCHAR keyMaterial[40]; + + if ((keyStringLen < 8) || (keyStringLen > 64)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK Key length(%d) error, required 8 ~ 64 characters!(keyStr=%s)\n", + keyStringLen, keyString)); + return FALSE; + } + + NdisZeroMemory(pPMKBuf, 32); + if (keyStringLen == 64) + { + AtoH(keyString, pPMKBuf, 32); + } + else + { + RtmpPasswordHash(keyString, pHashStr, hashStrLen, keyMaterial); + NdisMoveMemory(pPMKBuf, keyMaterial, 32); + } + + return TRUE; +} + +INT RT_CfgSetFixedTxPhyMode(PSTRING arg) +{ + INT fix_tx_mode = FIXED_TXMODE_HT; + ULONG value; + + + if (rtstrcasecmp(arg, "OFDM") == TRUE) + fix_tx_mode = FIXED_TXMODE_OFDM; + else if (rtstrcasecmp(arg, "CCK") == TRUE) + fix_tx_mode = FIXED_TXMODE_CCK; + else if (rtstrcasecmp(arg, "HT") == TRUE) + fix_tx_mode = FIXED_TXMODE_HT; + else if (rtstrcasecmp(arg, "VHT") == TRUE) + fix_tx_mode = FIXED_TXMODE_VHT; + else + { + value = simple_strtol(arg, 0, 10); + switch (value) + { + case FIXED_TXMODE_CCK: + case FIXED_TXMODE_OFDM: + case FIXED_TXMODE_HT: + case FIXED_TXMODE_VHT: + fix_tx_mode = value; + break; + default: + fix_tx_mode = FIXED_TXMODE_HT; + } + } + + return fix_tx_mode; + +} + +INT RT_CfgSetMacAddress( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i, mac_len; + + /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + mac_len = strlen(arg); + if(mac_len != 17) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid length (%d)\n", __FUNCTION__, mac_len)); + return FALSE; + } + + if(strcmp(arg, "00:00:00:00:00:00") == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid mac setting \n", __FUNCTION__)); + return FALSE; + } + + for (i = 0; i < MAC_ADDR_LEN; i++) + { + AtoH(arg, &pAd->CurrentAddress[i], 1); + arg = arg + 3; + } + + pAd->bLocalAdminMAC = TRUE; + return TRUE; +} + +INT RT_CfgSetTxMCSProc(PSTRING arg, BOOLEAN *pAutoRate) +{ + INT Value = simple_strtol(arg, 0, 10); + INT TxMcs; + + if ((Value >= 0 && Value <= 23) || (Value == 32)) /* 3*3*/ + { + TxMcs = Value; + *pAutoRate = FALSE; + } + else + { + TxMcs = MCS_AUTO; + *pAutoRate = TRUE; + } + + return TxMcs; + +} + +INT RT_CfgSetAutoFallBack( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR AutoFallBack = (UCHAR)simple_strtol(arg, 0, 10); + + if (AutoFallBack) + AutoFallBack = TRUE; + else + AutoFallBack = FALSE; + + AsicSetAutoFallBack(pAd, (AutoFallBack) ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetAutoFallBack::(AutoFallBack=%d)\n", AutoFallBack)); + return TRUE; +} + +#ifdef WSC_INCLUDED +INT RT_CfgSetWscPinCode( + IN RTMP_ADAPTER *pAd, + IN PSTRING pPinCodeStr, + OUT PWSC_CTRL pWscControl) +{ + UINT pinCode; + + pinCode = (UINT) simple_strtol(pPinCodeStr, 0, 10); /* When PinCode is 03571361, return value is 3571361.*/ + if (strlen(pPinCodeStr) == 4) + { + pWscControl->WscEnrolleePinCode = pinCode; + pWscControl->WscEnrolleePinCodeLen = 4; + } + else if ( ValidateChecksum(pinCode) ) + { + pWscControl->WscEnrolleePinCode = pinCode; + pWscControl->WscEnrolleePinCodeLen = 8; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWscPinCode(): invalid Wsc PinCode (%d)\n", pinCode)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWscPinCode():Wsc PinCode=%d\n", pinCode)); + + return TRUE; + +} +#endif /* WSC_INCLUDED */ + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWNAME. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_giwname( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + UCHAR CurOpMode = OPMODE_AP; + + if (CurOpMode == OPMODE_AP) + { + strcpy(pData, "RTWIFI SoftAP"); + } + + return NDIS_STATUS_SUCCESS; +} + + +INT RTMP_COM_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT Status = NDIS_STATUS_SUCCESS, i; + + + pObj = pObj; /* avoid compile warning */ + + switch(cmd) + { + case CMD_RTPRIV_IOCTL_NETDEV_GET: + /* get main net_dev */ + { + VOID **ppNetDev = (VOID **)pData; + *ppNetDev = (VOID *)(pAd->net_dev); + } + break; + + case CMD_RTPRIV_IOCTL_NETDEV_SET: + { + struct wifi_dev *wdev = NULL; + /* set main net_dev */ + pAd->net_dev = pData; + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) { + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.if_dev = (void *)pData; + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.func_dev = (void *)&pAd->ApCfg.MBSSID[MAIN_MBSSID]; + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.sys_handle = (void *)pAd; + RTMP_OS_NETDEV_SET_WDEV(pData, &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev); + wdev = &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) { + pAd->StaCfg.wdev.if_dev = pData; + pAd->StaCfg.wdev.func_dev = (void *)&pAd->StaCfg; + pAd->StaCfg.wdev.sys_handle = (void *)pAd; + RTMP_OS_NETDEV_SET_WDEV(pData, &pAd->StaCfg.wdev); + wdev = &pAd->StaCfg.wdev; + } +#endif /* CONFIG_STA_SUPPORT */ + if (wdev) { + 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(pAd->net_dev))); + RtmpOSNetDevFree(pAd->net_dev); + } + } + break; + } + case CMD_RTPRIV_IOCTL_OPMODE_GET: + /* get Operation Mode */ + *(ULONG *)pData = pAd->OpMode; + break; + + + case CMD_RTPRIV_IOCTL_TASK_LIST_GET: + /* get all Tasks */ + { + RT_CMD_WAIT_QUEUE_LIST *pList = (RT_CMD_WAIT_QUEUE_LIST *)pData; + + pList->pMlmeTask = &pAd->mlmeTask; +#ifdef RTMP_TIMER_TASK_SUPPORT + pList->pTimerTask = &pAd->timerTask; +#endif /* RTMP_TIMER_TASK_SUPPORT */ + pList->pCmdQTask = &pAd->cmdQTask; +#ifdef WSC_INCLUDED + pList->pWscTask = &pAd->wscTask; +#endif /* WSC_INCLUDED */ + } + break; + +#ifdef RTMP_MAC_PCI + case CMD_RTPRIV_IOCTL_IRQ_INIT: + /* init IRQ */ + rtmp_irq_init(pAd); + break; +#endif /* RTMP_MAC_PCI */ + + case CMD_RTPRIV_IOCTL_IRQ_RELEASE: + /* release IRQ */ + RTMP_OS_IRQ_RELEASE(pAd, pAd->net_dev); + break; + +#ifdef RTMP_MAC_PCI + case CMD_RTPRIV_IOCTL_MSI_ENABLE: + /* enable MSI */ + RTMP_MSI_ENABLE(pAd); + *(ULONG **)pData = (ULONG *)(pObj->pci_dev); + break; +#endif /* RTMP_MAC_PCI */ + + case CMD_RTPRIV_IOCTL_NIC_NOT_EXIST: + /* set driver state to fRTMP_ADAPTER_NIC_NOT_EXIST */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + break; + + case CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR: + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP); + break; + +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + case CMD_RTPRIV_IOCTL_USB_DEV_GET: + /* get USB DEV */ + { + VOID **ppUsb_Dev = (VOID **)pData; + *ppUsb_Dev = (VOID *)(pObj->pUsb_Dev); + } + break; + + case CMD_RTPRIV_IOCTL_USB_INTF_GET: + /* get USB INTF */ + { + VOID **ppINTF = (VOID **)pData; + *ppINTF = (VOID *)(pObj->intf); + } + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET: + /* set driver state to fRTMP_ADAPTER_SUSPEND */ + RTMP_SET_FLAG(pAd,fRTMP_ADAPTER_SUSPEND); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR: + /* clear driver state to fRTMP_ADAPTER_SUSPEND */ + RTMP_CLEAR_FLAG(pAd,fRTMP_ADAPTER_SUSPEND); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_SEND_DISSASSOCIATE: + /* clear driver state to fRTMP_ADAPTER_SUSPEND */ + if (INFRA_ON(pAd) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + MLME_QUEUE_ELEM *MsgElem; + os_alloc_mem(NULL, (UCHAR **)&MsgElem, sizeof(MLME_QUEUE_ELEM)); + if (MsgElem) + { + COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DEAUTH_STA_LEAVING; + MsgElem->Machine = ASSOC_STATE_MACHINE; + MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + /* Prevent to connect AP again in STAMlmePeriodicExec*/ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, MsgElem); + os_free_mem(NULL, MsgElem); + } + /* RtmpusecDelay(1000);*/ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CGIWAP, -1, NULL, NULL, 0); + } + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_TEST: + /* test driver state to fRTMP_ADAPTER_SUSPEND */ + *(UCHAR *)pData = RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_SUSPEND); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_IDLE_RADIO_OFF_TEST: + /* test driver state to fRTMP_ADAPTER_IDLE_RADIO_OFF */ + *(UCHAR *)pData = RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_IDLE_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_OFF: + ASIC_RADIO_OFF(pAd, SUSPEND_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON: + ASIC_RADIO_ON(pAd, RESUME_RADIO_ON); + break; + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_STATUS: + *(UCHAR *)pData = (UCHAR)pAd->WOW_Cfg.bEnable; + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_ENABLE: + ASIC_WOW_ENABLE(pAd); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_DISABLE: + ASIC_WOW_DISABLE(pAd); + break; +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ +#endif /* CONFIG_PM */ + + case CMD_RTPRIV_IOCTL_AP_BSSID_GET: + if (pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + NdisCopyMemory(pData, pAd->MlmeAux.Bssid, 6); + else + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET: + /* set driver state to fRTMP_ADAPTER_SUSPEND */ + RTMP_SET_FLAG(pAd,fRTMP_ADAPTER_SUSPEND); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR: + /* clear driver state to fRTMP_ADAPTER_SUSPEND */ + RTMP_CLEAR_FLAG(pAd,fRTMP_ADAPTER_SUSPEND); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_OFF: + /* RT28xxUsbAsicRadioOff */ + //RT28xxUsbAsicRadioOff(pAd); + ASIC_RADIO_OFF(pAd, SUSPEND_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON: + /* RT28xxUsbAsicRadioOn */ + //RT28xxUsbAsicRadioOn(pAd); + ASIC_RADIO_ON(pAd, RESUME_RADIO_ON); + break; +#endif /* CONFIG_STA_SUPPORT */ + + case CMD_RTPRIV_IOCTL_SANITY_CHECK: + /* sanity check before IOCTL */ + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) +#ifdef IFUP_IN_PROBE + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) +#endif /* IFUP_IN_PROBE */ + ) + { + if(pData == NULL || RT_isLegalCmdBeforeInfUp((PSTRING) pData) == FALSE) + return NDIS_STATUS_FAILURE; + } + break; + + case CMD_RTPRIV_IOCTL_SIOCGIWFREQ: + /* get channel number */ + *(ULONG *)pData = pAd->CommonCfg.Channel; + break; +#ifdef CONFIG_SNIFFER_SUPPORT + case CMD_RTPRIV_IOCTL_SNIFF_INIT: + Monitor_Init(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_SNIFF_OPEN: + if (Monitor_Open(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_SNIFF_CLOSE: + if (Monitor_Close(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_SNIFF_REMOVE: + Monitor_Remove(pAd); + break; +#endif /*CONFIG_SNIFFER_SUPPORT*/ + + + + case CMD_RTPRIV_IOCTL_BEACON_UPDATE: + /* update all beacon contents */ +#ifdef CONFIG_AP_SUPPORT + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + break; + + case CMD_RTPRIV_IOCTL_RXPATH_GET: + /* get the number of rx path */ + *(ULONG *)pData = pAd->Antenna.field.RxPath; + break; + + case CMD_RTPRIV_IOCTL_CHAN_LIST_NUM_GET: + *(ULONG *)pData = pAd->ChannelListNum; + break; + + case CMD_RTPRIV_IOCTL_CHAN_LIST_GET: + { + UINT32 i; + UCHAR *pChannel = (UCHAR *)pData; + + for (i = 1; i <= pAd->ChannelListNum; i++) + { + *pChannel = pAd->ChannelList[i-1].Channel; + pChannel ++; + } + } + break; + + case CMD_RTPRIV_IOCTL_FREQ_LIST_GET: + { + UINT32 i; + UINT32 *pFreq = (UINT32 *)pData; + UINT32 m; + + for (i = 1; i <= pAd->ChannelListNum; i++) + { + m = 2412000; + MAP_CHANNEL_ID_TO_KHZ(pAd->ChannelList[i-1].Channel, m); + (*pFreq) = m; + pFreq ++; + } + } + break; + +#ifdef EXT_BUILD_CHANNEL_LIST + case CMD_RTPRIV_SET_PRECONFIG_VALUE: + /* Set some preconfigured value before interface up*/ + pAd->CommonCfg.DfsType = MAX_RD_REGION; + break; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + + +#ifdef RTMP_PCI_SUPPORT + case CMD_RTPRIV_IOCTL_PCI_SUSPEND: + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_PCI_RESUME: + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_PCI_CSR_SET: + pAd->CSRBaseAddress = (PUCHAR)Data; + DBGPRINT(RT_DEBUG_ERROR, ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n", (ULONG)pAd->CSRBaseAddress, (ULONG)Data)); + break; + + case CMD_RTPRIV_IOCTL_PCIE_INIT: + RTMPInitPCIeDevice(pData, pAd); + break; +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + case CMD_RTPRIV_IOCTL_CFG80211_CFG_START: + RT_CFG80211_REINIT(pAd); + RT_CFG80211_CRDA_REG_RULE_APPLY(pAd); + break; +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef INF_PPA_SUPPORT + case CMD_RTPRIV_IOCTL_INF_PPA_INIT: + os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB)); + break; + + case CMD_RTPRIV_IOCTL_INF_PPA_EXIT: + if (ppa_hook_directpath_register_dev_fn && (pAd->PPAEnable == TRUE)) + { + UINT status; + status = ppa_hook_directpath_register_dev_fn(&pAd->g_if_id, pAd->net_dev, NULL, 0); + DBGPRINT(RT_DEBUG_TRACE, ("Unregister PPA::status=%d, if_id=%d\n", status, pAd->g_if_id)); + } + os_free_mem(NULL, pAd->pDirectpathCb); + break; +#endif /* INF_PPA_SUPPORT*/ + + case CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP: + /* interface up */ + { + RT_CMD_INF_UP_DOWN *pInfConf = (RT_CMD_INF_UP_DOWN *)pData; + + if (VIRTUAL_IF_NUM(pAd) == 0) + { +#ifdef DBG + ULONG start, end, diff_ms; + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&start); +#endif /* DBG */ + if (pInfConf->rt28xx_open(pAd->net_dev) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_open return fail!\n")); + return NDIS_STATUS_FAILURE; + } +#ifdef DBG + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&end); diff_ms = (end-start)*1000/OS_HZ; + DBGPRINT(RT_DEBUG_OFF, ("WiFi Interface Up Time (%s): %lu.%03lus\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev),diff_ms/1000,diff_ms%1000)); +#endif /* DBG */ + } + else + { +#ifdef CONFIG_AP_SUPPORT + extern VOID APMakeAllBssBeacon(IN PRTMP_ADAPTER pAd); + extern VOID APUpdateAllBeaconFrame(IN PRTMP_ADAPTER pAd); + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + } + VIRTUAL_IF_INC(pAd); + } + break; + + case CMD_RTPRIV_IOCTL_VIRTUAL_INF_DOWN: + /* interface down */ + { + RT_CMD_INF_UP_DOWN *pInfConf = (RT_CMD_INF_UP_DOWN *)pData; + + VIRTUAL_IF_DEC(pAd); + if (VIRTUAL_IF_NUM(pAd) == 0) + { +#ifdef DBG + ULONG start, end, diff_ms; + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&start); +#endif /* DBG */ + pInfConf->rt28xx_close(pAd->net_dev); +#ifdef DBG + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&end); diff_ms = (end-start)*1000/OS_HZ; + DBGPRINT(RT_DEBUG_OFF, ("WiFi Interface Down Time (%s): %lu.%03lus\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev),diff_ms/1000,diff_ms%1000)); +#endif /* DBG */ + } + } + break; + + case CMD_RTPRIV_IOCTL_VIRTUAL_INF_GET: + /* get virtual interface number */ + *(ULONG *)pData = VIRTUAL_IF_NUM(pAd); + break; + + case CMD_RTPRIV_IOCTL_INF_TYPE_GET: + /* get current interface type */ + *(ULONG *)pData = pAd->infType; + break; + + case CMD_RTPRIV_IOCTL_INF_STATS_GET: + /* get statistics */ + { + RT_CMD_STATS64 *pStats = (RT_CMD_STATS64 *)pData; +#ifdef CONFIG_AP_SUPPORT + if(pAd->OpMode == OPMODE_AP) + { + INT index; + MULTISSID_STRUCT *pMBSSID; + + for(index = 0; index < MAX_MBSSID_NUM(pAd); index++) + { + if (pAd->ApCfg.MBSSID[index].wdev.if_dev == (PNET_DEV)(pStats->pNetDev)) + { + break; + } + } + + if(index >= MAX_MBSSID_NUM(pAd)) + { + //reset counters + NdisZeroMemory(pStats, sizeof(RT_CMD_STATS64)); + + DBGPRINT(RT_DEBUG_ERROR, ("CMD_RTPRIV_IOCTL_INF_STATS_GET: can not find mbss I/F\n")); + return NDIS_STATUS_FAILURE; + } + + pMBSSID = &pAd->ApCfg.MBSSID[index]; + + pStats->rx_bytes = pMBSSID->ReceivedByteCount.QuadPart; + pStats->tx_bytes = pMBSSID->TransmittedByteCount.QuadPart; + pStats->rx_packets = pMBSSID->RxCount; + pStats->tx_packets = pMBSSID->TxCount; + pStats->rx_errors = pMBSSID->RxErrorCount; + pStats->tx_errors = 0; + pStats->multicast = pMBSSID->mcPktsRx; /* multicast packets received */ + pStats->collisions = 0; + pStats->rx_over_errors = 0; + pStats->rx_crc_errors = 0; + pStats->rx_frame_errors = 0; + pStats->rx_fifo_errors = 0; + } +#endif +#ifdef CONFIG_STA_SUPPORT + if(pAd->OpMode == OPMODE_STA) + { + pStats->rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + pStats->tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; + pStats->rx_bytes = pAd->RalinkCounters.ReceivedByteCount; + pStats->tx_bytes = pAd->RalinkCounters.TransmittedByteCount; + pStats->rx_errors = pAd->Counters8023.RxErrors; + pStats->tx_errors = pAd->Counters8023.TxErrors; + pStats->multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; /* multicast packets received*/ + pStats->collisions = 0; /* Collision packets*/ + pStats->rx_over_errors = pAd->Counters8023.RxNoBuffer; /* receiver ring buff overflow*/ + pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; recved pkt with crc error*/ + pStats->rx_frame_errors = 0; /* recv'd frame alignment error*/ + pStats->rx_fifo_errors = pAd->Counters8023.RxNoBuffer; /* recv'r fifo overrun*/ + } +#endif + } + break; + + case CMD_RTPRIV_IOCTL_INF_IW_STATUS_GET: + /* get wireless statistics */ + { + UCHAR CurOpMode = OPMODE_AP; +#ifdef CONFIG_AP_SUPPORT + PMAC_TABLE_ENTRY pMacEntry = NULL; +#endif /* CONFIG_AP_SUPPORT */ + RT_CMD_IW_STATS *pStats = (RT_CMD_IW_STATS *)pData; + + pStats->qual = 0; + pStats->level = 0; + pStats->noise = 0; + pStats->pStats = pAd->iw_stats; + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + { + CurOpMode = OPMODE_STA; + } +#endif /* CONFIG_STA_SUPPORT */ + + /*check if the interface is down*/ + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + return NDIS_STATUS_FAILURE; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == OPMODE_AP) + { +#ifdef APCLI_SUPPORT + if ((pStats->priv_flags == INT_APCLI) + ) + { + INT ApCliIdx = ApCliIfLookUp(pAd, (PUCHAR)pStats->dev_addr); + if ((ApCliIdx >= 0) && VALID_WCID(pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID)) + pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID]; + } + else +#endif /* APCLI_SUPPORT */ + { + /* + only AP client support wireless stats function. + return NULL pointer for all other cases. + */ + pMacEntry = NULL; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == OPMODE_STA) + pStats->qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10); +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == OPMODE_AP) + { + if (pMacEntry != NULL) + pStats->qual = ((pMacEntry->ChannelQuality * 12)/10 + 10); + else + pStats->qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10); + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pStats->qual > 100) + pStats->qual = 100; + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == OPMODE_STA) + { + pStats->level = + RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == OPMODE_AP) + { + if (pMacEntry != NULL) + pStats->level = + RTMPMaxRssi(pAd, pMacEntry->RssiSample.AvgRssi0, + pMacEntry->RssiSample.AvgRssi1, + pMacEntry->RssiSample.AvgRssi2); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + pStats->noise = RTMPMaxRssi(pAd, pAd->ApCfg.RssiSample.AvgRssi0, + pAd->ApCfg.RssiSample.AvgRssi1, + pAd->ApCfg.RssiSample.AvgRssi2) - + RTMPMinSnr(pAd, pAd->ApCfg.RssiSample.AvgSnr0, + pAd->ApCfg.RssiSample.AvgSnr1); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + pStats->noise = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2) - + RTMPMinSnr(pAd, pAd->StaCfg.RssiSample.AvgSnr0, + pAd->StaCfg.RssiSample.AvgSnr1); +#endif /* CONFIG_STA_SUPPORT */ + } + break; + + case CMD_RTPRIV_IOCTL_INF_MAIN_CREATE: + *(VOID **)pData = RtmpPhyNetDevMainCreate(pAd); + break; + + case CMD_RTPRIV_IOCTL_INF_MAIN_ID_GET: + *(ULONG *)pData = INT_MAIN; + break; + + case CMD_RTPRIV_IOCTL_INF_MAIN_CHECK: + if (Data != INT_MAIN) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_INF_P2P_CHECK: + if (Data != INT_P2P) + return NDIS_STATUS_FAILURE; + break; + +#ifdef WDS_SUPPORT + case CMD_RTPRIV_IOCTL_WDS_INIT: + WDS_Init(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_WDS_REMOVE: + WDS_Remove(pAd); + break; + + case CMD_RTPRIV_IOCTL_WDS_STATS_GET: + if (Data == INT_WDS) + { + if (WDS_StatsGet(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + } + else + return NDIS_STATUS_FAILURE; + break; +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + case CMD_RTPRIV_IOCTL_APCLI_STATS_GET: + if (Data == INT_APCLI) + { + if (ApCli_StatsGet(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + } + else + return NDIS_STATUS_FAILURE; + break; +#endif /* APCLI_SUPPORT */ + +#ifdef RALINK_ATE +#ifdef RALINK_QA + case CMD_RTPRIV_IOCTL_ATE: + RtmpDoAte(pAd, wrq, pData); + break; +#endif /* RALINK_QA */ +#endif /* RALINK_ATE */ + + case CMD_RTPRIV_IOCTL_MAC_ADDR_GET: + { + UCHAR mac_addr[MAC_ADDR_LEN]; + USHORT Addr01, Addr23, Addr45; + + RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); + + mac_addr[0] = (UCHAR)(Addr01 & 0xff); + mac_addr[1] = (UCHAR)(Addr01 >> 8); + mac_addr[2] = (UCHAR)(Addr23 & 0xff); + mac_addr[3] = (UCHAR)(Addr23 >> 8); + mac_addr[4] = (UCHAR)(Addr45 & 0xff); + mac_addr[5] = (UCHAR)(Addr45 >> 8); + + for(i=0; i<6; i++) + *(UCHAR *)(pData+i) = mac_addr[i]; + break; + } +#ifdef CONFIG_AP_SUPPORT + case CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ: + /* handle for SIOCGIWRATEQ */ + { + RT_CMD_IOCTL_RATE *pRate = (RT_CMD_IOCTL_RATE *)pData; + HTTRANSMIT_SETTING HtPhyMode; + UINT8 BW = 0, GI = 0; + +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + memcpy(&HtPhyMode, &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + memcpy(&HtPhyMode, &pAd->WdsTab.WdsEntry[pObj->ioctl_if].wdev.HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + else +#endif /* WDS_SUPPORT */ + { + memcpy(&HtPhyMode, &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.HTPhyMode, sizeof(HTTRANSMIT_SETTING)); +#ifdef MBSS_SUPPORT + /* reset phy mode for MBSS */ + MBSS_PHY_MODE_RESET(pObj->ioctl_if, HtPhyMode); +#endif /* MBSS_SUPPORT */ + } + +#ifdef DOT11_VHT_AC + if (HtPhyMode.field.BW == BW_40 && pAd->CommonCfg.vht_bw == VHT_BW_80 && HtPhyMode.field.MODE >= MODE_VHT) { + BW = 2; + GI = pAd->CommonCfg.vht_sgi_80; + } + else +#endif /* DOT11_VHT_AC */ + { + BW = HtPhyMode.field.BW; + GI = HtPhyMode.field.ShortGI; + } + + RtmpDrvRateGet(pAd, HtPhyMode.field.MODE, GI, + BW, HtPhyMode.field.MCS, + pAd->Antenna.field.TxPath, + (UINT32 *)&pRate->BitRate); + } + break; +#endif /* CONFIG_AP_SUPPORT */ + + case CMD_RTPRIV_IOCTL_SIOCGIWNAME: + RtmpIoctl_rt_ioctl_giwname(pAd, pData, 0); + break; + + } + +#ifdef RT_CFG80211_SUPPORT + if ((CMD_RTPRIV_IOCTL_80211_START <= cmd) && + (cmd <= CMD_RTPRIV_IOCTL_80211_END)) + { + Status = CFG80211DRV_IoctlHandle(pAd, wrq, cmd, subcmd, pData, Data); + } +#endif /* RT_CFG80211_SUPPORT */ + + if (cmd >= CMD_RTPRIV_IOCTL_80211_COM_LATEST_ONE) + return NDIS_STATUS_FAILURE; + + return Status; +} + +/* + ========================================================================== + Description: + Issue a site survey command to driver + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set site_survey + ========================================================================== +*/ +INT Set_SiteSurvey_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + NDIS_802_11_SSID Ssid; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + //check if the interface is down + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (MONITOR_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + return -EINVAL; + } + } +#endif // CONFIG_STA_SUPPORT // + + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((strlen(arg) != 0) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } +#ifdef CUSTOMER_DCC_FEATURE + { + UINT32 mac_val; + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= 0x11f; + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + } +#endif + +#ifdef AIRPLAY_SUPPORT + if(arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) + { + int ii,jj; + CHAR temp[MAX_LEN_OF_SSID*2+1]; + + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + for(ii=2; ii= '0' && arg[ii] <= '9') + temp[ii-2] = arg[ii] - '0'; + else if(arg[ii] >= 'A' && arg[ii] <= 'F') + temp[ii-2] = arg[ii] - 'A' + 10; + else if(arg[ii] >= 'a' && arg[ii] <= 'f') + temp[ii-2] = arg[ii] - 'a' + 10; + } + + temp[strlen(arg)-2]= '\0'; + DBGPRINT(RT_DEBUG_TRACE,("%s=>arg:",__FUNCTION__)); + for(ii=0; ii MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s=> unicode SSID len error.",__FUNCTION__)); + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + goto ret; + } + + Ssid.Ssid[jj++] = (UCHAR)(temp[ii]*16+temp[ii+1]); + } + Ssid.Ssid[jj] = '\0'; + Ssid.SsidLength = jj; + +ret: + + DBGPRINT(RT_DEBUG_TRACE, ("%s=>SSID:",__FUNCTION__)); + for(ii=0; iiioctl_if_type == INT_APCLI) + { + ApCliSiteSurvey(pAd, pObj->ioctl_if, &Ssid, SCAN_ACTIVE, FALSE); + } + else +#endif /* APCLI_SUPPORT */ + { + if (Ssid.SsidLength == 0) + ApSiteSurvey(pAd, &Ssid, SCAN_PASSIVE, FALSE); + else + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE); + } +#else + /*for shorter scan time. use active scan and send probe req.*/ + DBGPRINT(RT_DEBUG_TRACE, ("!!! Fast Scan for connection trial !!!\n")); + ApSiteSurvey(pAd, &Ssid, FAST_SCAN_ACTIVE, FALSE); +#endif /* APCLI_CONNECTION_TRIAL */ + + return TRUE; + } +#endif /* AP_SCAN_SUPPORT */ +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Ssid.SsidLength = 0; + if ((arg != NULL) && + (strlen(arg) <= MAX_LEN_OF_SSID)) + { + RTMPMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + + pAd->StaCfg.bSkipAutoScanConn = TRUE; + StaSiteSurvey(pAd, &Ssid, SCAN_ACTIVE); + } +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_SiteSurvey_Proc\n")); + + return TRUE; +} + +INT Set_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ANT_DIVERSITY_TYPE UsedAnt; + int i; + DBGPRINT(RT_DEBUG_OFF, ("==> Set_Antenna_Proc *******************\n")); + + for (i = 0; i < strlen(arg); i++) + if (!isdigit(arg[i])) + return -EINVAL; + + UsedAnt = simple_strtol(arg, 0, 10); + + switch (UsedAnt) + { + /* 2: Fix in the PHY Antenna CON1*/ + case ANT_FIX_ANT0: + AsicSetRxAnt(pAd, 0); + DBGPRINT(RT_DEBUG_OFF, ("<== Set_Antenna_Proc(Fix in Ant CON1), (%d,%d)\n", + pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); + break; + /* 3: Fix in the PHY Antenna CON2*/ + case ANT_FIX_ANT1: + AsicSetRxAnt(pAd, 1); + DBGPRINT(RT_DEBUG_OFF, ("<== %s(Fix in Ant CON2), (%d,%d)\n", + __FUNCTION__, pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("<== %s(N/A cmd: %d), (%d,%d)\n", __FUNCTION__, UsedAnt, + pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); + break; + } + + return TRUE; +} + + + + +#ifdef RT6352 +INT Set_RfBankSel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG RfBank; + + RfBank = simple_strtol(arg, 0, 10); + + pAd->RfBank = RfBank; + + return TRUE; +} + +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT Set_TemperatureCAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + RT6352_Temperature_Init(pAd); + return TRUE; +} +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#endif /* RT6352 */ + +#ifdef MAC_REPEATER_SUPPORT +#ifdef MULTI_MAC_ADDR_EXT_SUPPORT +INT Set_EnMultiMacAddrExt_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UCHAR Enable; + UINT32 MacReg; + + Enable = simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAd, MAC_ADDR_EXT_EN, &MacReg); + if (Enable) + { + MacReg |= 0x1; + pAd->bUseMultiMacAddrExt = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("==>UseMultiMacAddrExt (ON)\n")); + } + else + { + MacReg &= (~0x1); + pAd->bUseMultiMacAddrExt = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("==>UseMultiMacAddrExt (OFF)\n")); + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_EXT_EN, MacReg); + + DBGPRINT(RT_DEBUG_WARN, ("UseMultiMacAddrExt = %d \n", pAd->bUseMultiMacAddrExt)); + + return TRUE; +} + +INT Set_MultiMacAddrExt_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR tempMAC[6], idx; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + ULONG offset, Addr; + INT i; + + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + idx = (UCHAR) simple_strtol((token+1), 0, 10); + + if (idx > 15) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&tempMAC[i]), 1); + } + + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + tempMAC[0], tempMAC[1], tempMAC[2], tempMAC[3], tempMAC[4], tempMAC[5], idx)); + + offset = 0x1480 + (HW_WCID_ENTRY_SIZE * idx); + Addr = tempMAC[0] + (tempMAC[1] << 8) +(tempMAC[2] << 16) +(tempMAC[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = tempMAC[4] + (tempMAC[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); + + return TRUE; + } + + return FALSE; +} +#endif /* MULTI_MAC_ADDR_EXT_SUPPORT */ +#endif /* MAC_REPEATER_SUPPORT */ + +INT set_tssi_enable(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT8 tssi_enable = 0; + + tssi_enable = simple_strtol(arg, 0, 10); + + if (tssi_enable == 1) { + pAd->chipCap.tssi_enable = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("turn on TSSI mechanism\n")); + } else if (tssi_enable == 0) { + pAd->chipCap.tssi_enable = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("turn off TSS mechanism\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal param(%u)\n", tssi_enable)); + return FALSE; + } + return TRUE; +} + +#ifdef CONFIG_WIFI_TEST +INT set_pbf_loopback(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT8 enable = 0; + UINT32 value; + + enable = simple_strtol(arg, 0, 10); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &value); + + if (enable == 1) { + pAd->chipCap.pbf_loopback = TRUE; + value |= PBF_LOOP_EN; + DBGPRINT(RT_DEBUG_OFF, ("turn on pbf loopback\n")); + } else if(enable == 0) { + pAd->chipCap.pbf_loopback = FALSE; + value &= ~PBF_LOOP_EN; + DBGPRINT(RT_DEBUG_OFF, ("turn off pbf loopback\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal param(%d)\n")); + return FALSE; + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, value); + + return TRUE; +} + +INT set_pbf_rx_drop(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT8 enable = 0; + UINT32 value; + + enable = simple_strtol(arg, 0, 10); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &value); +#endif + + if (enable == 1) { + pAd->chipCap.pbf_rx_drop = TRUE; + value |= RX_DROP_MODE; + DBGPRINT(RT_DEBUG_OFF, ("turn on pbf loopback\n")); + } else if (enable == 0) { + pAd->chipCap.pbf_rx_drop = FALSE; + value &= ~RX_DROP_MODE; + DBGPRINT(RT_DEBUG_OFF, ("turn off pbf loopback\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal param(%d)\n")); + return FALSE; + } + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, value); +#endif + + return TRUE; +} +#endif + +#ifdef CONFIG_ANDES_SUPPORT +INT set_fw_debug(RTMP_ADAPTER *ad, PSTRING arg) +{ + UINT8 fw_debug_param; + + fw_debug_param = simple_strtol(arg, 0, 10); + + andes_fun_set(ad, LOG_FW_DEBUG_MSG, fw_debug_param); + + return TRUE; +} +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef CUSTOMER_DCC_FEATURE +VOID EnableRadioChstats( + IN PRTMP_ADAPTER pAd, + IN UINT32 mac_val) +{ + mac_val |= 0x15f; // enable channel status check + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + /* Clear previous status */ + RTMP_IO_READ32(pAd, CH_BUSY_STA, &mac_val); + RTMP_IO_READ32(pAd, CCA_BUSY_TIME, &mac_val); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &mac_val); +} + +INT Set_ApEnableRadioChStats( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 enable; + static UINT32 save_mac_val=0; + UINT32 mac_val; + + if(strlen(arg) > 1) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong argument type \n")); + return FALSE; + } + enable = simple_strtol(arg, 0, 10); + if((enable != 1) && (enable != 0)) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong argument value \n")); + return FALSE; + } + + if(enable == 1) + { + + /* set the EnableChannelStatsCheck value to true and initialize the values to zero */ + pAd->EnableChannelStatsCheck = TRUE; + + pAd->ChannelStats.LastReadTime = 0; + pAd->ChannelStats.TotalDuration = 0; + pAd->ChannelStats.msec100counts = 0; + + pAd->ChannelStats.CCABusytime = 0; + pAd->ChannelStats.ChBusytime = 0; + pAd->ChannelStats.FalseCCACount = 0; + pAd->ChannelStats.ChannelApActivity = 0; + + pAd->ChannelStats.ChBusyTimeAvg = 0; + pAd->ChannelStats.CCABusyTimeAvg = 0; + pAd->ChannelStats.FalseCCACountAvg = 0; + pAd->ChannelStats.ChannelApActivityAvg = 0; + + pAd->ChannelStats.ChBusyTime1secValue = 0; + pAd->ChannelStats.CCABusyTime1secValue = 0; + pAd->ChannelStats.FalseCCACount1secValue = 0; + pAd->ChannelStats.ChannelApActivity1secValue = 0; + + /* enable the radio channel stats and save the current status value */ + RTMP_IO_READ32(pAd, CH_TIME_CFG, &save_mac_val); + mac_val = save_mac_val; + EnableRadioChstats(pAd, mac_val); + + return TRUE; + } + else if(enable == 0) + { + if(pAd->EnableChannelStatsCheck) + { + /* set the old values of register before enabling the radio chanel stats and set the EnableChannelStatsCheck to FALSE*/ + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, save_mac_val); + pAd->EnableChannelStatsCheck = FALSE; + } + /* set all channel stats values to zero */ + pAd->ChannelStats.TotalDuration = 0; + pAd->ChannelStats.msec100counts = 0; + + pAd->ChannelStats.CCABusytime = 0; + pAd->ChannelStats.ChBusytime = 0; + pAd->ChannelStats.FalseCCACount = 0; + pAd->ChannelStats.ChannelApActivity = 0; + + pAd->ChannelStats.ChBusyTimeAvg = 0; + pAd->ChannelStats.CCABusyTimeAvg = 0; + pAd->ChannelStats.FalseCCACountAvg = 0; + pAd->ChannelStats.ChannelApActivityAvg = 0; + + return TRUE; + } + + return FALSE; +} + + +INT Set_ApDisableSTAConnect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 flag; + if(strlen(arg) > 1) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong argument type \n")); + return FALSE; + } + flag = simple_strtol(arg, 0, 10); + if((flag == 0) || (flag == 1)) + { + pAd->ApDisableSTAConnectFlag = flag; + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("wrong argument value \n")); + return FALSE; + } +} + +INT Set_ApEnableBeaconTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 flag; + if(strlen(arg) > 1) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong argument type \n")); + return FALSE; + } + flag = simple_strtol(arg, 0, 10); + if((flag == 0) || (flag == 1)) + { + BssTableInit(&pAd->AvailableBSS); + pAd->ApEnableBeaconTable = flag; + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("wrong argument value \n")); + return FALSE; + } +} + +INT Set_ApScan_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT channel =0; + UINT timeout =0; + INT32 i,j,count; + CHAR scantype[8]; + CHAR temp[33]; + UINT32 mac_val; + + //check if the interface is down + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + i = 0; + j = 0; + count = 0; + while(arg[j] != '\0') + { + temp[i] = arg[j]; + j++; + if(temp[i] == ':' || arg[j] == '\0' ) + { + if(temp[i] == ':') + { + count++; + switch(count) + { + case 1: + temp[i]= '\0'; + if ((strlen(temp) != 0) && (strlen(temp) <= 7)) + { + strcpy(scantype,temp); + if(strcmp(scantype,"active") && strcmp(scantype,"passive")) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong scan type argument \n")); + return FALSE; + } + } + else if(strlen(temp) > 7) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong scan type argument \n")); + return FALSE; + } + i = -1; + break; + case 2: + temp[i] = '\0'; + if((strlen(temp) != 0) && (strlen(temp) <= 3)) + { + channel=simple_strtol(temp, 0, 10); + if(!ChannelSanity(pAd, channel)) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong channel number \n")); + return FALSE; + } + } + else if(strlen(temp) > 3) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong channel number \n")); + return FALSE; + } + i = -1; + break; + default: + if(count > 2) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong number of arguments \n")); + return FALSE; + } + break; + } + } + else if(arg[j] == '\0') + { + temp[i+1] = '\0'; + if((strlen(temp) != 0) && (strlen(temp) <= 10) && ( simple_strtol(temp, 0, 10) < 0xffffffff)) + { + timeout = simple_strtol(temp, 0, 10); + } + else if(strlen(temp)) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong Timeout value \n")); + return FALSE; + } + } + } + i++; + + } + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= 0x11f; + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + //printk("%s %u %u \n", scantype, channel, timeout); + if (!strcmp(scantype, "passive")) + ApSiteSurveyNew(pAd,channel,timeout, SCAN_PASSIVE, FALSE); + else if(!strcmp(scantype, "active")) + ApSiteSurveyNew(pAd,channel, timeout, SCAN_ACTIVE, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ApScan_Proc\n")); + + return TRUE; +} + +#ifdef MBSS_802_11_STATISTICS +VOID RTMPIoctlQueryMbssStat( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + int apidx; + UINT64 temp; + RT_MBSS_STATISTICS_TABLE *mbss_stat; + + os_alloc_mem(NULL, (UCHAR **)&mbss_stat, sizeof(RT_MBSS_STATISTICS_TABLE)); + if (mbss_stat == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + NdisZeroMemory(mbss_stat, sizeof(RT_MBSS_STATISTICS_TABLE)); + mbss_stat->Num = pAd->ApCfg.BssidNum; + + for (apidx=0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + mbss_stat->MbssEntry[apidx].RxCount = pAd->ApCfg.MBSSID[apidx].RxCount; + mbss_stat->MbssEntry[apidx].TxCount = pAd->ApCfg.MBSSID[apidx].TxCount; + mbss_stat->MbssEntry[apidx].ReceivedByteCount = pAd->ApCfg.MBSSID[apidx].ReceivedByteCount; + mbss_stat->MbssEntry[apidx].TransmittedByteCount = pAd->ApCfg.MBSSID[apidx].TransmittedByteCount; + mbss_stat->MbssEntry[apidx].RxErrorCount = pAd->ApCfg.MBSSID[apidx].RxErrorCount; + mbss_stat->MbssEntry[apidx].RxDropCount = pAd->ApCfg.MBSSID[apidx].RxDropCount; + mbss_stat->MbssEntry[apidx].TxRetriedPktCount = pAd->ApCfg.MBSSID[apidx].TxRetriedPktCount; +#ifdef STATS_COUNT_SUPPORT + mbss_stat->MbssEntry[apidx].TxErrorCount = pAd->ApCfg.MBSSID[apidx].TxErrorCount; + mbss_stat->MbssEntry[apidx].TxDropCount = pAd->ApCfg.MBSSID[apidx].TxDropCount; + mbss_stat->MbssEntry[apidx].UnicastPktsRx = pAd->ApCfg.MBSSID[apidx].ucPktsRx; + mbss_stat->MbssEntry[apidx].UnicastPktsTx = pAd->ApCfg.MBSSID[apidx].ucPktsTx; + mbss_stat->MbssEntry[apidx].MulticastPktsRx = pAd->ApCfg.MBSSID[apidx].mcPktsRx; + mbss_stat->MbssEntry[apidx].MulticastPktsTx = pAd->ApCfg.MBSSID[apidx].mcPktsTx; + mbss_stat->MbssEntry[apidx].BroadcastPktsRx = pAd->ApCfg.MBSSID[apidx].bcPktsRx; + mbss_stat->MbssEntry[apidx].BroadcastPktsTx = pAd->ApCfg.MBSSID[apidx].bcPktsTx; +#endif // STATS_COUNT_SUPPORT // + mbss_stat->MbssEntry[apidx].MGMTRxCount = pAd->ApCfg.MBSSID[apidx].MGMTRxCount; + mbss_stat->MbssEntry[apidx].MGMTTxCount = pAd->ApCfg.MBSSID[apidx].MGMTTxCount; + mbss_stat->MbssEntry[apidx].MGMTReceivedByteCount = pAd->ApCfg.MBSSID[apidx].MGMTReceivedByteCount; + mbss_stat->MbssEntry[apidx].MGMTTransmittedByteCount = pAd->ApCfg.MBSSID[apidx].MGMTTransmittedByteCount; + mbss_stat->MbssEntry[apidx].MGMTRxErrorCount = pAd->ApCfg.MBSSID[apidx].MGMTRxErrorCount; + mbss_stat->MbssEntry[apidx].MGMTRxDropCount = pAd->ApCfg.MBSSID[apidx].MGMTRxDropCount; + mbss_stat->MbssEntry[apidx].MGMTTxErrorCount = pAd->ApCfg.MBSSID[apidx].MGMTTxErrorCount; + mbss_stat->MbssEntry[apidx].MGMTTxDropCount = pAd->ApCfg.MBSSID[apidx].MGMTTxDropCount; + + temp = pAd->ApCfg.MBSSID[apidx].ChannelUseTime; + do_div(temp, 1000); + mbss_stat->MbssEntry[apidx].ChannelUseTime = temp; + + pAd->ApCfg.MBSSID[apidx].RxCount = 0; + pAd->ApCfg.MBSSID[apidx].TxCount = 0; + pAd->ApCfg.MBSSID[apidx].ReceivedByteCount = 0; + pAd->ApCfg.MBSSID[apidx].TransmittedByteCount = 0; + pAd->ApCfg.MBSSID[apidx].RxErrorCount = 0; + pAd->ApCfg.MBSSID[apidx].RxDropCount = 0; + pAd->ApCfg.MBSSID[apidx].TxRetriedPktCount = 0; + pAd->ApCfg.MBSSID[apidx].TxErrorCount = 0; + pAd->ApCfg.MBSSID[apidx].TxDropCount = 0; + pAd->ApCfg.MBSSID[apidx].ucPktsRx = 0; + pAd->ApCfg.MBSSID[apidx].ucPktsTx = 0; + pAd->ApCfg.MBSSID[apidx].mcPktsRx = 0; + pAd->ApCfg.MBSSID[apidx].mcPktsTx = 0; + pAd->ApCfg.MBSSID[apidx].bcPktsRx = 0; + pAd->ApCfg.MBSSID[apidx].bcPktsTx = 0; + pAd->ApCfg.MBSSID[apidx].MGMTRxCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTTxCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTReceivedByteCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTTransmittedByteCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTRxErrorCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTRxDropCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTTxErrorCount = 0; + pAd->ApCfg.MBSSID[apidx].MGMTTxDropCount = 0; + pAd->ApCfg.MBSSID[apidx].ChannelUseTime = 0; + + } + + wrq->u.data.length = sizeof(RT_MBSS_STATISTICS_TABLE); + if (copy_to_user(wrq->u.data.pointer, mbss_stat, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + if (mbss_stat != NULL) + os_free_mem(NULL, mbss_stat); +} + +VOID RTMPIoctlQuerySTAStat( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + int i; + UINT64 temp; + PMAC_TABLE_ENTRY pEntry = NULL; + RT_STA_STATISTICS_TABLE *sta_stat = NULL; + + os_alloc_mem(NULL, (UCHAR **)&sta_stat, sizeof(RT_STA_STATISTICS_TABLE)); + if (sta_stat == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(sta_stat, sizeof(RT_STA_STATISTICS_TABLE)); + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) && pEntry->Sst == SST_ASSOC) + { + sta_stat->STAEntry[sta_stat->Num].ApIdx = pEntry->apidx; + COPY_MAC_ADDR(sta_stat->STAEntry[sta_stat->Num].Addr, pEntry->Addr); + sta_stat->STAEntry[sta_stat->Num].RxCount = pEntry->RxCount; + sta_stat->STAEntry[sta_stat->Num].TxCount = pEntry->TxCount; + sta_stat->STAEntry[sta_stat->Num].ReceivedByteCount = pEntry->ReceivedByteCount; + sta_stat->STAEntry[sta_stat->Num].TransmittedByteCount = pEntry->TransmittedByteCount; + sta_stat->STAEntry[sta_stat->Num].RxErrorCount = pEntry->RxErrorCount; + sta_stat->STAEntry[sta_stat->Num].RxDropCount = pEntry->RxDropCount; + sta_stat->STAEntry[sta_stat->Num].TxErrorCount = pEntry->TxErrorCount; + sta_stat->STAEntry[sta_stat->Num].TxDropCount = pEntry->TxDropCount; + sta_stat->STAEntry[sta_stat->Num].TxRetriedPktCount = pEntry->TxRetriedPktCount; + temp = pEntry->ChannelUseTime; + do_div(temp, 1000); + sta_stat->STAEntry[sta_stat->Num].ChannelUseTime = temp; + sta_stat->Num++; + + // clear STA Stats + pEntry->RxCount = 0; + pEntry->TxCount = 0; + pEntry->ReceivedByteCount = 0; + pEntry->TransmittedByteCount = 0; + pEntry->RxErrorCount = 0; + pEntry->RxDropCount = 0; + pEntry->TxErrorCount = 0; + pEntry->TxDropCount = 0; + pEntry->TxRetriedPktCount = 0; + pEntry->ChannelUseTime = 0; + } + } + + wrq->u.data.length = sizeof(RT_STA_STATISTICS_TABLE); + if (copy_to_user(wrq->u.data.pointer, sta_stat, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + if (sta_stat != NULL) + os_free_mem(NULL, sta_stat); +} +#endif +#endif + +char *obtw_delta_str[]= +{ + "ofdm6m_", "ofdm9m_", "ofdm12m_", "ofdm18m_", + "ht20mcs0_", "ht20mcs1_", "ht20mcs2_", + "ht40mcs0_", "ht40mcs1_", "ht40mcs2_", "ht40mcs32_", + "vht80mcs0_", "vht80mcs1_", "vht80mcs2_" +}; + +#ifdef MT76x2 +INT set_obtw_delta_proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR *Pos = NULL; + UINT8 DeltaVal = 0; + int i; + pAd->obtw_anyEnable = FALSE; + memset(pAd->obtw_delta_array, 0, sizeof(pAd->obtw_delta_array)); + + if (arg && strlen(arg)) { + Pos = strstr(arg, "disable"); + if (Pos != NULL) { + DBGPRINT(RT_DEBUG_OFF, ("%s: disable\n", __FUNCTION__)); + } + } + + for (i = 0; i < OBTW_DELTA_ELEMENT; i++) + { + if (arg && strlen(arg)) + Pos = strstr(arg, obtw_delta_str[i]); + else + DBGPRINT(RT_DEBUG_OFF, ("%s: input arguments error , missing %s\n", __FUNCTION__ , obtw_delta_str[i])); + + if (Pos != NULL) { + Pos = Pos + strlen(obtw_delta_str[i]); + DeltaVal = simple_strtol(Pos, 0, 10); + pAd->obtw_delta_array[i] = DeltaVal; + DBGPRINT(RT_DEBUG_OFF, ("%s: found %s, DeltaVal = %d\n", __FUNCTION__, obtw_delta_str[i], DeltaVal)); + if (DeltaVal > 0) + pAd->obtw_anyEnable = TRUE; + } + } + + DBGPRINT(RT_DEBUG_OFF, ("%s: anyEnable=%d\n", __FUNCTION__, pAd->obtw_anyEnable)); + + for(i=0;iobtw_delta_array[i])); + + + return TRUE; +} + +INT set_obtw_debug_proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT8 debug_on; + + debug_on = simple_strtol(arg, 0, 10); + if(debug_on!=0) + pAd->obtw_debug_on = TRUE; + else + pAd->obtw_debug_on = FALSE; + + return TRUE; +} + + +#endif /* MT76x2 */ + +#ifdef ED_MONITOR +INT edcca_tx_stop_start(RTMP_ADAPTER *pAd, BOOLEAN stop) +{ + UINT32 macCfg, macCfg_2, macStatus,MacValue; + UINT32 MTxCycle; + ULONG stTime, mt_time, mr_time; +#ifdef CONFIG_STA_SUPPORT + static BOOLEAN orig_auto_reconnect_setting; +#endif /* CONFIG_STA_SUPPORT */ + + /* Disable MAC Tx and wait MAC Tx/Rx status in idle state or direcyl enable tx */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &macCfg); + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &macCfg_2); + + if (stop == TRUE) + { + macCfg &= (~0x04); + macCfg_2 &= (~0x01); + + /* Disable PA. */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MacValue); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, (MacValue & 0xfffff0f0)); + +#ifdef CONFIG_STA_SUPPORT + orig_auto_reconnect_setting = pAd->StaCfg.bAutoReconnect; + pAd->StaCfg.bAutoReconnect = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + }else + { + macCfg |= 0x04; + macCfg_2 |= 0x01; + + + /* Enable PA */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MacValue); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, (MacValue | 0x00050f0f)); + +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.bAutoReconnect = orig_auto_reconnect_setting; +#endif /* CONFIG_STA_SUPPORT */ + + } + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, macCfg); + + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, macCfg_2); + + + if (stop == TRUE) + { + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x1) + RtmpusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&mt_time); + mt_time -= stTime; + if (MTxCycle == 10000) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(cnt=%d,time=0x%lx):stop MTx,macStatus=0x%x!\n", + __FUNCTION__, MTxCycle, mt_time, macStatus)); + } + } + + DBGPRINT(RT_DEBUG_OFF, ("%s():%s tx\n", + __FUNCTION__, ((stop == TRUE) ? "stop" : "start"))); + + return TRUE; +} + +#ifdef ED_SMART +INT ed_state_judge(RTMP_ADAPTER *pAd) +{ + if((pAd->ed_trigger_cnt > pAd->ed_learning_time_threshold) + && (pAd->ed_false_cca_cnt > pAd->ed_learning_time_threshold) + && pAd->ed_vga_at_lowest_gain + ) + { + if( pAd->ed_current_state == ED_OFF_AND_LEARNING ) + { + UINT32 mac_val; + RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val); + mac_val |= ((1<<20) | (1<<7)); + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val); + + pAd->ed_current_state = ED_TESTING; + + DBGPRINT(RT_DEBUG_OFF,("\n\n@@@@@@ %s : ed_testing !!\n\n",__FUNCTION__)); + RTMPSetTimer(&pAd->ed_timer, 1200000); + } + else if( pAd->ed_current_state == ED_TESTING ) + { + //reset timer to 20 mins + BOOLEAN cancelled; + RTMPCancelTimer(&pAd->ed_timer, &cancelled); + RTMPSetTimer(&pAd->ed_timer, 1200000); + DBGPRINT(RT_DEBUG_TRACE,("\n\n@@@@@@ %s : reset ed_timer to 20 mins !!\n\n",__FUNCTION__)); + } + } + + return TRUE; +} + +VOID ed_testing_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + DBGPRINT(RT_DEBUG_OFF, ("%s : reset pAd->ed_current_state: %d\n", __FUNCTION__, pAd->ed_current_state)); + pAd->ed_current_state = ED_OFF_AND_LEARNING; +} +#endif /* ED_SMART */ + +INT ed_status_read(RTMP_ADAPTER *pAd) +{ + UINT32 period_us = pAd->ed_chk_period * 1000; + ULONG irqflag; + BOOLEAN stop_edcca = FALSE; + BOOLEAN stop_tx = FALSE; + + INT percent; + RX_STA_CNT1_STRUC RxStaCnt1; + UINT32 ch_idle_stat=0, ch_busy_stat=0, ed_2nd_stat=0, ed_stat=0; + + RTMP_IO_READ32(pAd, CH_IDLE_STA, &ch_idle_stat); + RTMP_IO_READ32(pAd, 0x1140, &ed_stat); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + + pAd->ch_idle_stat[pAd->ed_stat_lidx] = ch_idle_stat; + pAd->ch_busy_stat[pAd->ed_stat_lidx] = ch_busy_stat; + pAd->ed_2nd_stat[pAd->ed_stat_lidx] = ed_2nd_stat; + pAd->ed_stat[pAd->ed_stat_lidx] = ed_stat; + + pAd->false_cca_stat[pAd->ed_stat_lidx] += RxStaCnt1.field.FalseCca; + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + + + NdisGetSystemUpTime(&pAd->chk_time[pAd->ed_stat_lidx]); + + if ((pAd->ed_threshold > 0) && (period_us > 0) && (pAd->ed_block_tx_threshold > 0)) { + percent = (pAd->ed_stat[pAd->ed_stat_lidx] * 100 ) / period_us; + if (percent > 100) + percent = 100; + + if (pAd->false_cca_stat[pAd->ed_stat_lidx] > pAd->ed_false_cca_threshold) + { + pAd->ed_false_cca_cnt ++; + } + else + { + pAd->ed_false_cca_cnt = 0; + } + + + if (percent > pAd->ed_threshold) + { + pAd->ed_trigger_cnt++; + pAd->ed_silent_cnt = 0; + } + else + { + pAd->ed_trigger_cnt = 0; + pAd->ed_silent_cnt++; + } + + if(pAd->ed_debug) + { + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: false_cca_stat[%u]=%03u, ed_false_cca_cnt=%d vga_at_lowest_gain=%d one sec cca=%d !!\n", + __FUNCTION__, pAd->ed_stat_lidx, pAd->false_cca_stat[pAd->ed_stat_lidx] + , pAd->ed_false_cca_cnt,pAd->ed_vga_at_lowest_gain,pAd->RalinkCounters.OneSecFalseCCACnt)); + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: pAd->ed_trigger_cnt=%d, pAd->ed_silent_cnt=%u, percent=%d !!\n", + __FUNCTION__, pAd->ed_trigger_cnt, pAd->ed_silent_cnt + , percent)); + } + } + pAd->ed_trigger_stat[pAd->ed_stat_lidx] = pAd->ed_trigger_cnt; + pAd->ed_silent_stat[pAd->ed_stat_lidx] = pAd->ed_silent_cnt; + + + INC_RING_INDEX(pAd->ed_stat_lidx, ED_STAT_CNT); + pAd->false_cca_stat[pAd->ed_stat_lidx] = 0; + if (pAd->ed_stat_sidx == pAd->ed_stat_lidx) { + INC_RING_INDEX(pAd->ed_stat_sidx, ED_STAT_CNT); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + + if(pAd->ed_chk == EDCCA_ON + #ifdef ED_SMART + || (pAd->ed_chk == EDCCA_SMART && pAd->ed_current_state == ED_TESTING) + #endif + ) + + { + if (pAd->ed_trigger_cnt > pAd->ed_block_tx_threshold) { + if (pAd->ed_tx_stoped == FALSE) { + pAd->ed_tx_stoped = TRUE; + edcca_tx_stop_start(pAd, TRUE); + } + } + + if (pAd->ed_silent_cnt > pAd->ed_block_tx_threshold) { + if (pAd->ed_tx_stoped == TRUE) { + pAd->ed_tx_stoped = FALSE; + edcca_tx_stop_start(pAd, FALSE); + } + } + } + return TRUE; +} + + +//this function will be called in multi entry +INT ed_monitor_exit(RTMP_ADAPTER *pAd) +{ + ULONG irqflag; + BOOLEAN old_ed_tx_stoped, old_ed_chk; + BOOLEAN cancelled; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : ===>\n", __FUNCTION__)); + +#ifdef ED_SMART + RTMPCancelTimer(&pAd->ed_timer, &cancelled); +#endif /*ED_SMART*/ + + NdisZeroMemory(&pAd->ed_stat[0], sizeof(pAd->ed_stat)); + NdisZeroMemory(&pAd->ch_idle_stat[0], sizeof(pAd->ch_idle_stat)); + NdisZeroMemory(&pAd->ch_busy_stat[0], sizeof(pAd->ch_busy_stat)); + NdisZeroMemory(&pAd->chk_time[0], sizeof(pAd->chk_time)); + NdisZeroMemory(&pAd->ed_trigger_stat[0], sizeof(pAd->ed_trigger_stat)); + NdisZeroMemory(&pAd->ed_silent_stat[0], sizeof(pAd->ed_silent_stat)); + NdisZeroMemory(&pAd->false_cca_stat[0], sizeof(pAd->false_cca_stat)); + + pAd->ed_stat_lidx = pAd->ed_stat_sidx = 0; + pAd->ed_trigger_cnt = 0; + pAd->ed_silent_cnt = 0; + //ignore fisrt time's incorrect false cca + pAd->ed_false_cca_cnt = 0; + + old_ed_tx_stoped = pAd->ed_tx_stoped; + old_ed_chk = pAd->ed_chk; + + pAd->ed_tx_stoped = FALSE; + //also clear top level flags + pAd->ed_chk = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : <===\n", __FUNCTION__)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + + + if (old_ed_tx_stoped) + { + edcca_tx_stop_start(pAd, FALSE); + } + + if (old_ed_chk) + { + RTMP_CHIP_ASIC_SET_EDCCA(pAd,FALSE); + } + + return TRUE; +} + + +// open & muanl cmd will call +INT ed_monitor_init(RTMP_ADAPTER *pAd) +{ + ULONG irqflag; + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : ===>\n", __FUNCTION__)); + NdisZeroMemory(&pAd->ed_stat[0], sizeof(pAd->ed_stat)); + NdisZeroMemory(&pAd->ch_idle_stat[0], sizeof(pAd->ch_idle_stat)); + NdisZeroMemory(&pAd->ch_busy_stat[0], sizeof(pAd->ch_busy_stat)); + NdisZeroMemory(&pAd->chk_time[0], sizeof(pAd->chk_time)); + NdisZeroMemory(&pAd->ed_trigger_stat[0], sizeof(pAd->ed_trigger_stat)); + NdisZeroMemory(&pAd->ed_silent_stat[0], sizeof(pAd->ed_silent_stat)); + NdisZeroMemory(&pAd->false_cca_stat[0], sizeof(pAd->false_cca_stat)); + + pAd->ed_stat_lidx = pAd->ed_stat_sidx = 0; + pAd->ed_trigger_cnt = 0; + pAd->ed_silent_cnt = 0; + + // ignore fisrt time's incorrect false cca + pAd->ed_false_cca_cnt = 0; + + pAd->ed_tx_stoped = FALSE; + //also set top level flags + if(pAd->ed_chk == 0) //turn on if disabled , otherwise decide by profile + pAd->ed_chk = 1; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + TxLinkCfg.field.TxCFAckEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + +#ifdef ED_SMART + RTMPInitTimer(pAd, &(pAd->ed_timer), GET_TIMER_FUNCTION(ed_testing_timeout), pAd, FALSE); +#endif /* ED_SMART */ + + + + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : <===\n", __FUNCTION__)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + + RTMP_CHIP_ASIC_SET_EDCCA(pAd,TRUE); + + return TRUE; +} + +INT set_ed_block_tx_thresh(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT block_tx_threshold = simple_strtol(arg, 0, 10); + + pAd->ed_block_tx_threshold = block_tx_threshold; + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_block_tx_threshold=%d\n", + __FUNCTION__, pAd->ed_block_tx_threshold)); + + return TRUE; +} + + +INT set_ed_threshold(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG percent = simple_strtol(arg, 0, 10); + + if (percent > 100) + pAd->ed_threshold = (percent % 100); + else + pAd->ed_threshold = percent; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_threshold=%d\n", + __FUNCTION__, pAd->ed_threshold)); + + return TRUE; +} +INT set_ed_learn_threshold(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG learn_th = simple_strtol(arg, 0, 10); + + pAd->ed_learning_time_threshold = learn_th; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): learn_th=%d * 100ms\n", + __FUNCTION__, pAd->ed_learning_time_threshold)); + + return TRUE; +} + + +INT set_ed_false_cca_threshold(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG false_cca_threshold = simple_strtol(arg, 0, 10); + + pAd->ed_false_cca_threshold = false_cca_threshold > 0 ? false_cca_threshold : 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_false_cca_threshold=%d\n", + __FUNCTION__, pAd->ed_false_cca_threshold)); + + return TRUE; +} + + +//let run-time turn on/off +INT set_ed_chk_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT ed_chk; + + ed_chk = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_chk=%d\n", + __FUNCTION__, ed_chk)); + + if (ed_chk == EDCCA_OFF) { + pAd->ed_chk = ed_chk; + ed_monitor_exit(pAd); + } +#ifdef ED_SMART + else if(ed_chk == EDCCA_ON || ed_chk == EDCCA_SMART){ + pAd->ed_chk = ed_chk; + ed_monitor_init(pAd); + } +#endif + else + { + pAd->ed_chk = EDCCA_ON; + ed_monitor_init(pAd); + } + + + return TRUE; +} + +#ifdef CONFIG_AP_SUPPORT +INT set_ed_sta_count_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT ed_sta_th; + + ed_sta_th = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_sta_th=%d\n", + __FUNCTION__, ed_sta_th)); + + pAd->ed_sta_threshold = ed_sta_th; + + return TRUE; +} + + +INT set_ed_ap_count_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT ed_ap_th; + + ed_ap_th = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_ap_th=%d\n", + __FUNCTION__, ed_ap_th)); + + pAd->ed_ap_threshold = ed_ap_th; + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +INT set_ed_ap_scaned_count_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT ed_ap_scaned; + + ed_ap_scaned = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_ap_scaned=%d\n", + __FUNCTION__, ed_ap_scaned)); + + pAd->ed_ap_scaned = ed_ap_scaned; + + return TRUE; +} + + +INT set_ed_current_ch_ap_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT ed_current_ch_aps; + + ed_current_ch_aps = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_current_ch_aps=%d\n", + __FUNCTION__, ed_current_ch_aps)); + + pAd->ed_current_ch_aps = ed_current_ch_aps; + + return TRUE; +} +#endif /* CONFIG_STA_SUPPORT */ + + + +INT set_ed_current_rssi_threhold_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT ed_rssi_threshold; + + ed_rssi_threshold = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_rssi_threshold=%d\n", + __FUNCTION__, ed_rssi_threshold)); + + pAd->ed_rssi_threshold = ed_rssi_threshold; + + return TRUE; +} +INT set_ed_debug_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT ed_debug; + + ed_debug = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): ed_debug=%d\n", + __FUNCTION__, ed_debug)); + + pAd->ed_debug = ed_debug; + + return TRUE; +} + +INT show_ed_stat_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + unsigned long irqflags; + UINT32 ed_stat[ED_STAT_CNT], ed_2nd_stat[ED_STAT_CNT], false_cca_stat[ED_STAT_CNT]; + UINT32 silent_stat[ED_STAT_CNT], trigger_stat[ED_STAT_CNT]; + UINT32 busy_stat[ED_STAT_CNT], idle_stat[ED_STAT_CNT]; + ULONG chk_time[ED_STAT_CNT]; + INT period_us; + UCHAR start, end, idx; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflags); + start = pAd->ed_stat_sidx; + end = pAd->ed_stat_lidx; + NdisMoveMemory(&ed_stat[0], &pAd->ed_stat[0], sizeof(ed_stat)); + NdisMoveMemory(&ed_2nd_stat[0], &pAd->ed_2nd_stat[0], sizeof(ed_2nd_stat)); + NdisMoveMemory(&busy_stat[0], &pAd->ch_busy_stat[0], sizeof(busy_stat)); + NdisMoveMemory(&idle_stat[0], &pAd->ch_idle_stat[0], sizeof(idle_stat)); + NdisMoveMemory(&chk_time[0], &pAd->chk_time[0], sizeof(chk_time)); + NdisMoveMemory(&trigger_stat[0], &pAd->ed_trigger_stat[0], sizeof(trigger_stat)); + NdisMoveMemory(&silent_stat[0], &pAd->ed_silent_stat[0], sizeof(silent_stat)); + NdisMoveMemory(&false_cca_stat[0], &pAd->false_cca_stat[0], sizeof(false_cca_stat)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflags); + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("Dump ChannelBusy Counts, ed_chk=%u, ed_current_state = %d, ed_ap_threshold=%u, false_cca_threshold=%u, ChkPeriod=%dms, ED_Threshold=%d%%, HitCntForBlockTx=%d\n", + pAd->ed_chk,pAd->ed_current_state, pAd->ed_ap_threshold, pAd->ed_false_cca_threshold, + pAd->ed_chk_period, pAd->ed_threshold, pAd->ed_block_tx_threshold)); +#endif + +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("Dump ChannelBusy Counts, ed_chk=%u, ed_ap_scaned=%u, ed_current_ch_aps=%u, ed_rssi_threshold=%d, false_cca_threshold=%u, ChkPeriod=%dms, ED_Threshold=%d%%, HitCntForBlockTx=%d\n", + pAd->ed_chk, pAd->ed_ap_scaned, pAd->ed_current_ch_aps, pAd->ed_rssi_threshold, pAd->ed_false_cca_threshold, + pAd->ed_chk_period, pAd->ed_threshold, pAd->ed_block_tx_threshold)); +#endif + + + period_us = pAd->ed_chk_period * 1000; + DBGPRINT(RT_DEBUG_OFF, ("TimeSlot:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%ld ", chk_time[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Dump ED_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", ed_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (ed_stat[idx] * 100) / period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("FalseCCA:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", false_cca_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("TriggerCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", trigger_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + + DBGPRINT(RT_DEBUG_OFF, ("SilentCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", silent_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + + DBGPRINT(RT_DEBUG_OFF, ("Dump ED_2nd_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", ed_2nd_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (ed_2nd_stat[idx] * 100) / period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + + DBGPRINT(RT_DEBUG_OFF, ("Dump CH_IDLE_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", idle_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (idle_stat[idx] *100)/ period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Dump CH_BUSY_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", busy_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (busy_stat[idx] *100 )/ period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + return TRUE; +} + +INT report_ed_count(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT period_us = 0; + INT irqflags = 0; + UINT32 ed_stat, percentage = 0; + + + period_us = pAd->ed_chk_period * 1000; + ed_stat = pAd->ed_stat[pAd->ed_stat_lidx - 1]; + /* report previous 100ms ed count, avoid incomplete data */ + percentage = (ed_stat * 100) / period_us; + percentage = (percentage >= 100)?100:percentage; + + DBGPRINT(RT_DEBUG_OFF, ("=====> %s \n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_OFF, ("ed_raw_count_in_100ms : %d ed_percentage_in_100ms : %d \n" + ,ed_stat, percentage)); + return TRUE; +} + +#endif /* ED_MONITOR */ + +INT set_channel_ed_monitor_enable(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR ED_TH = (pAd->CommonCfg.Channel > 14)?0x0e:0x20; + /* A band 0x0e , G band 0x20 , 20150331 */ + UINT32 mac_val = 0; + UINT32 bbp_val; + + DBGPRINT(RT_DEBUG_OFF, ("=====> %s \n", __FUNCTION__)); + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= 0x40; + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + + RTMP_IO_READ32(pAd, CH_TIME_CFG, &mac_val); + mac_val |= 0x05; // enable channel status check + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + +#ifdef RLT_BBP + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) { + RTMP_BBP_IO_READ32(pAd, AGC1_R2, &bbp_val); + bbp_val = (bbp_val & 0xFFFF0000) | (ED_TH << 8) | ED_TH; + RTMP_BBP_IO_WRITE32(pAd, AGC1_R2, bbp_val); + } +#endif + + RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val); + mac_val &= ~(1 << 20); + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val); + + return TRUE; +} + +INT show_ed_cnt_for_channel_quality(RTMP_ADAPTER *pAd, PSTRING arg) +{ + if(pAd->ed_chk == FALSE) + { + set_channel_ed_monitor_enable(pAd, arg); + } + else + { +#ifdef ED_MONITOR + report_ed_count(pAd, arg); +#else + DBGPRINT(RT_DEBUG_OFF, ("%s : unexpected ed_chk = %d without ED_MONITOR compile flag\n", __FUNCTION__,pAd->ed_chk)); + pAd->ed_chk = 0; +#endif /* ED_MONITOR */ + } + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cmd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cmd.c new file mode 100644 index 000000000..6fddedee5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cmd.c @@ -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); +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cs.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cs.c new file mode 100644 index 000000000..4a160fdd6 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_cs.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_data.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_data.c new file mode 100644 index 000000000..d55ed38ff --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_data.c @@ -0,0 +1,5700 @@ +/**************************************************************************** + * 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_data.c + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + + +#include "rt_config.h" + +#ifdef LED_SOFT_SUPPORT +#include +#endif + +#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) +#define IS_BROADCAST_MAC_ADDR(Addr) ((((Addr[0]) & 0xff) == 0xff)) + +UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; +UCHAR EAPOL[] = {0x88, 0x8e}; +UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ + +UCHAR IPX[] = {0x81, 0x37}; +UCHAR APPLE_TALK[] = {0x80, 0xf3}; + + +// UserPriority To AccessCategory mapping +UCHAR WMM_UP2AC_MAP[8] = {QID_AC_BE, QID_AC_BK, + QID_AC_BK, QID_AC_BE, + QID_AC_VI, QID_AC_VI, + QID_AC_VO, QID_AC_VO}; + +#ifdef DBG +VOID dump_rxinfo(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo) +{ + hex_dump("RxInfo Raw Data", (UCHAR *)pRxInfo, sizeof(RXINFO_STRUC)); + + DBGPRINT(RT_DEBUG_OFF, ("RxInfo Fields:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tBA=%d\n", pRxInfo->BA)); + DBGPRINT(RT_DEBUG_OFF, ("\tDATA=%d\n", pRxInfo->DATA)); + DBGPRINT(RT_DEBUG_OFF, ("\tNULLDATA=%d\n", pRxInfo->NULLDATA)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", pRxInfo->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tU2M=%d\n", pRxInfo->U2M)); + DBGPRINT(RT_DEBUG_OFF, ("\tMcast=%d\n", pRxInfo->Mcast)); + DBGPRINT(RT_DEBUG_OFF, ("\tBcast=%d\n", pRxInfo->Bcast)); + DBGPRINT(RT_DEBUG_OFF, ("\tMyBss=%d\n", pRxInfo->MyBss)); + DBGPRINT(RT_DEBUG_OFF, ("\tCrc=%d\n", pRxInfo->Crc)); + DBGPRINT(RT_DEBUG_OFF, ("\tCipherErr=%d\n", pRxInfo->CipherErr)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMSDU=%d\n", pRxInfo->AMSDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tHTC=%d\n", pRxInfo->HTC)); + DBGPRINT(RT_DEBUG_OFF, ("\tRSSI=%d\n", pRxInfo->RSSI)); + DBGPRINT(RT_DEBUG_OFF, ("\tL2PAD=%d\n", pRxInfo->L2PAD)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", pRxInfo->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tDecrypted=%d\n", pRxInfo->Decrypted)); + DBGPRINT(RT_DEBUG_OFF, ("\tBssIdx3=%d\n", pRxInfo->BssIdx3)); + DBGPRINT(RT_DEBUG_OFF, ("\twapi_kidx=%d\n", pRxInfo->wapi_kidx)); + DBGPRINT(RT_DEBUG_OFF, ("\tpn_len=%d\n", pRxInfo->pn_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw_fc_type0=%d\n", pRxInfo->action_wanted)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw_fc_type1=%d\n", pRxInfo->sw_fc_type1)); + DBGPRINT(RT_DEBUG_OFF, ("\tprobe_rsp=%d\n", pRxInfo->probe_rsp)); + DBGPRINT(RT_DEBUG_OFF, ("\tbeacon=%d\n", pRxInfo->beacon)); + DBGPRINT(RT_DEBUG_OFF, ("\tdisasso=%d\n", pRxInfo->disasso)); + DBGPRINT(RT_DEBUG_OFF, ("\tdeauth=%d\n", pRxInfo->deauth)); + DBGPRINT(RT_DEBUG_OFF, ("\taction_wanted=%d\n", pRxInfo->action_wanted)); + DBGPRINT(RT_DEBUG_OFF, ("\trsv=%d\n", pRxInfo->rsv)); + +#ifdef RTMP_MAC + DBGPRINT(RT_DEBUG_OFF, ("\t")); +#endif /* RTMP_MAC */ +} + + +VOID dump_txinfo(RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo) +{ + hex_dump("TxInfo Raw Data: ", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC)); + + DBGPRINT(RT_DEBUG_OFF, ("TxInfo Fields:\n")); + +#ifdef RLT_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_RLT) + dump_rlt_txinfo(pAd, pTxInfo); +#endif +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#endif /* RTMP_MAC */ +} + + +VOID dump_txwi(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI) +{ + hex_dump("TxWI Raw Data: ", (UCHAR *)pTxWI, pAd->chipCap.TXWISize); + + DBGPRINT(RT_DEBUG_OFF, ("TxWI Fields:\n")); +#ifdef RLT_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_RLT) + dump_rlt_txwi(pAd, pTxWI); +#endif +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_RTMP) + dump_rtmp_txwi(pAd, pTxWI); +#endif +#endif /* RTMP_MAC */ +} + + +VOID dump_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI) +{ + hex_dump("RxWI Raw Data", (UCHAR *)pRxWI, pAd->chipCap.RXWISize); + + DBGPRINT(RT_DEBUG_OFF, ("RxWI Fields:\n")); +#ifdef RLT_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_RLT) + dump_rlt_rxwi(pAd, pRxWI); +#endif +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_RTMP) + dump_rtmp_rxwi(pAd, pRxWI); +#endif +#endif /* RTMP_MAC */ +} +#endif /* DBG */ + +#ifdef DBG_DIAGNOSE +static VOID dump_txblk(TX_BLK *pTxBlk) +{ + NDIS_PACKET *pPacket; + int i, frameNum; + PQUEUE_ENTRY pQEntry; + + DBGPRINT(RT_DEBUG_TRACE,("Dump TX_BLK Structure:\n")); + DBGPRINT(RT_DEBUG_TRACE,("\tTxFrameType=%d!\n", pTxBlk->TxFrameType)); + DBGPRINT(RT_DEBUG_TRACE,("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen)); + DBGPRINT(RT_DEBUG_TRACE,("\tTotalFrameNum=%d!\n", pTxBlk->TxPacketList.Number)); + DBGPRINT(RT_DEBUG_TRACE,("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum)); + DBGPRINT(RT_DEBUG_TRACE,("\tpPacketList=\n")); + + frameNum = pTxBlk->TxPacketList.Number; + + for(i=0; i < frameNum; i++) + { int j; + UCHAR *pBuf; + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + { + pBuf = GET_OS_PKT_DATAPTR(pPacket); + DBGPRINT(RT_DEBUG_TRACE,("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket))); + DBGPRINT(RT_DEBUG_TRACE,("\t\t")); + for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++) + { + DBGPRINT(RT_DEBUG_TRACE,("%02x ", (pBuf[j] & 0xff))); + if (j == 16) + break; + } + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + } + } + DBGPRINT(RT_DEBUG_TRACE,("\tWcid=%d!\n", pTxBlk->Wcid)); + DBGPRINT(RT_DEBUG_TRACE,("\tapidx=%d!\n", pTxBlk->apidx)); + DBGPRINT(RT_DEBUG_TRACE,("----EndOfDump\n")); +} + +VOID dump_rxblk(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + DBGPRINT(RT_DEBUG_TRACE,("Dump RX_BLK Structure:\n")); + + DBGPRINT(RT_DEBUG_TRACE,("\tHW rx info:\n")); + hex_dump("RawData", &pRxBlk->hw_rx_info[0], RXD_SIZE); + + DBGPRINT(RT_DEBUG_TRACE,("\tData Pointer info:\n")); + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxInfo=0x%p\n", pRxBlk->pRxInfo)); + dump_rxinfo(pAd, pRxBlk->pRxInfo); +#ifdef RLT_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxFceInfo=0x%p\n", pRxBlk->pRxFceInfo)); + dumpRxFCEInfo(pAd, pRxBlk->pRxFceInfo); + } +#endif +#endif /* RLT_MAC */ + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxWI=0x%p\n", pRxBlk->pRxWI)); + dump_rxwi(pAd, pRxBlk->pRxWI); + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxPacket=0x%p, len=%d\n", pRxBlk->pRxPacket, pRxBlk->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tpHeader=0x%p\n", pRxBlk->pHeader)); + hex_dump("Dump RxPacket in dump_rxblk", (UCHAR *)pRxBlk->pHeader, pRxBlk->MPDUtotalByteCnt > 48 ? 48 : pRxBlk->MPDUtotalByteCnt); + DBGPRINT(RT_DEBUG_TRACE,("\t\tpData=0x%p\n", pRxBlk->pData)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tDataSize=%d\n", pRxBlk->DataSize)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tFlags=0x%x\n", pRxBlk->Flags)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tUserPriority=%d\n", pRxBlk->UserPriority)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tOpMode=%d\n", pRxBlk->OpMode)); + + DBGPRINT(RT_DEBUG_TRACE,("\tMirror Info from RXWI:\n")); + DBGPRINT(RT_DEBUG_TRACE,("\t\tWCID=%d\n", pRxBlk->wcid)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tPhyMode=%d(%s)\n", pRxBlk->rx_rate.field.MODE, get_phymode_str(pRxBlk->rx_rate.field.MODE))); + DBGPRINT(RT_DEBUG_TRACE,("\t\tMCS=%d\n", pRxBlk->rx_rate.field.MCS)); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + DBGPRINT(RT_DEBUG_TRACE,("\t\tldpc=%d\n", pRxBlk->rx_rate.field.ldpc)); +#endif /* RLT_MAC */ + DBGPRINT(RT_DEBUG_TRACE,("\t\tBW=%d\n", pRxBlk->rx_rate.field.BW)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tSGI=%d\n", pRxBlk->rx_rate.field.ShortGI)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tMPDUtotalByteCnt=%d\n", pRxBlk->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tTID=%d\n", pRxBlk->TID)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tSTBC=%d\n", pRxBlk->rx_rate.field.STBC)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tkey_idx=%d\n", pRxBlk->key_idx)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tBSS_IDX=%d\n", pRxBlk->bss_idx)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tRSSI=%d:%d:%d\n", pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2])); + DBGPRINT(RT_DEBUG_TRACE,("\t\tSNR=%d:%d:%d\n", pRxBlk->snr[0], pRxBlk->snr[1], pRxBlk->snr[2])); + DBGPRINT(RT_DEBUG_TRACE,("\t\tFreqOffset=%d\n", pRxBlk->freq_offset)); +} +#endif /* DBG_DIAGNOSE */ + + +#ifdef DOT11_N_SUPPORT +VOID RTMP_BASetup(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UINT8 UPriority) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pEntry && (pEntry->NoBADataCountDown == 0) && IS_HT_STA(pEntry)) + { + BOOLEAN isRalink = FALSE; + /* Don't care the status of the portSecured status. */ +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + if (pEntry->apidx < MAX_APCLI_NUM) { + if (pAd->ApCfg.ApCliTab[pEntry->apidx].MlmeAux.APRalinkIe != 0) + isRalink = TRUE; + } + } +#endif /* APCLI_SUPPORT */ + + if (((pEntry->TXBAbitmap & (1<PortSecured == WPA_802_1X_PORT_SECURED) + && ((IS_ENTRY_CLIENT(pEntry) && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)) || + IS_ENTRY_MESH(pEntry) || IS_ENTRY_WDS(pEntry) || + (IS_ENTRY_APCLI(pEntry) && (isRalink == TRUE) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) || + (pEntry->WepStatus == Ndis802_11WEPDisabled || + pEntry->WepStatus == Ndis802_11AESEnable +#ifdef WAPI_SUPPORT + || pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled +#endif /* WAPI_SUPPORT */ + )) + ) + { + BAOriSessionSetUp(pAd, pEntry, UPriority, 0, 10, FALSE); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) && (pEntry->NoBADataCountDown == 0) && IS_HT_STA(pEntry)) + { + if (((pEntry->TXBAbitmap & (1 << UPriority)) == 0) && + ((pEntry->BADeclineBitmap & (1 << UPriority)) == 0) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + && + ((IS_ENTRY_CLIENT(pEntry) && pAd->MlmeAux.APRalinkIe != 0x0) || (pEntry->WepStatus != Ndis802_11WEPEnabled && pEntry->WepStatus != Ndis802_11TKIPEnable)) + && + (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + ) + { + BAOriSessionSetUp(pAd, pEntry, UPriority, 0, 10, FALSE); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + API for MLME to transmit management frame to AP (BSS Mode) + or station (IBSS Mode) + + Arguments: + pAd Pointer to our adapter + pData Pointer to the outgoing 802.11 frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MiniportMMRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN UCHAR *pData, + IN UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG FreeNum; +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags = 0; +#endif /* RTMP_MAC_PCI */ + BOOLEAN bUseDataQ = FALSE, FlgDataQForce = FALSE, FlgIsLocked = FALSE; + int retryCnt = 0; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + PHEADER_802_11 pHdr80211 = NULL; + MULTISSID_STRUCT *pMbss = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; +#endif // MBSS_802_11_STATISTICS // +#endif + BOOLEAN FlgIsCheckPS = FALSE; + + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) + { + bUseDataQ = TRUE; + QueIdx &= (~MGMT_USE_QUEUE_FLAG); + } + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x1) { + if (pAd->fpga_ctl.tx_kick_cnt > 0) { + if (pAd->fpga_ctl.tx_kick_cnt < 0xffff) + pAd->fpga_ctl.tx_kick_cnt--; + } + else + return NDIS_STATUS_FAILURE; + + QueIdx = 0; + bUseDataQ = TRUE; + } +#endif /* CONFIG_FPGA_MODE */ + if ((QueIdx & MGMT_USE_PS_FLAG) == MGMT_USE_PS_FLAG) + { + FlgIsCheckPS = TRUE; + QueIdx &= (~MGMT_USE_PS_FLAG); + } + +#ifdef RTMP_MAC_PCI + if (pAd->MACVersion == 0x28600100) + { + /* do not care about the version */ + QueIdx = (bUseDataQ ==TRUE ? QueIdx : 3); + bUseDataQ = TRUE; + } + + if (bUseDataQ) + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + FlgIsLocked = TRUE; + retryCnt = MAX_DATAMM_RETRY; + } +#endif /* RTMP_MAC_PCI */ +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + // get MBSS for management frame TX counter per BSS + pHdr80211 = (PHEADER_802_11) pData; + pEntry = MacTableLookup(pAd, pHdr80211->Addr1); + if (pEntry != NULL && (pEntry->apidx < pAd->ApCfg.BssidNum)) + pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + else + { + UCHAR apidx; + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev == NULL) || ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev)))) + { + /* the interface is down */ + continue; + } + if(RTMPEqualMemory(pAd->ApCfg.MBSSID[apidx].wdev.bssid, pHdr80211->Addr2,MAC_ADDR_LEN)) + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + } + } + } +#endif +#endif + + do + { + /* Reset is in progress, stop immediately*/ + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_RADIO_OFF)) || + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) +#ifdef RT_CFG80211_P2P_SUPPORT + || IS_CFG80211_P2P_ABSENCE(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + ) + { + Status = NDIS_STATUS_FAILURE; + break; + } + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + /* Check Free priority queue*/ + /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.*/ +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + { + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + if (FreeNum <= 5) + { + /* free Tx(QueIdx) resources*/ + RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); + } + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + } + else +#endif /* RTMP_MAC_PCI */ + { + FreeNum = GET_MGMTRING_FREENO(pAd); + } + + if ((FreeNum > 0)) + { + INT hw_len = TXINFO_SIZE + pAd->chipCap.TXWISize + TSO_SIZE; + UCHAR rtmpHwHdr[40]; + + ASSERT((sizeof(rtmpHwHdr) > hw_len)); + + /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870*/ + NdisZeroMemory(&rtmpHwHdr, hw_len); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr[0], hw_len, pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + +#ifdef DOT11W_PMF_SUPPORT +#ifdef CONFIG_STA_SUPPORT + if (INFRA_ON(pAd)) +#endif /* CONFIG_STA_SUPPORT */ + PMF_PerformTxFrameAction(pAd, pPacket); +#endif /* DOT11W_PMF_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT +#ifdef RT_CFG80211_P2P_SUPPORT + if (RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + { + UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket); + } +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + { + FlgDataQForce = TRUE; + retryCnt--; + } +#endif /* RTMP_MAC_PCI */ + + Status = MlmeHardTransmit(pAd, QueIdx, pPacket, FlgDataQForce, FlgIsLocked, FlgIsCheckPS); + if (Status == NDIS_STATUS_SUCCESS) + retryCnt = 0; + else + RELEASE_NDIS_PACKET(pAd, pPacket, Status); + } + else + { + pAd->RalinkCounters.MgmtRingFullCount++; +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + { + retryCnt--; + DBGPRINT(RT_DEBUG_TRACE, ("retryCnt %d\n", retryCnt)); + if (retryCnt == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", + QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); + } + } +#endif /* RTMP_MAC_PCI */ + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", + QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); + } + } while (retryCnt > 0); +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + // management frame TX counter per BSS + if (pMbss != NULL) + { + if (Status == NDIS_STATUS_SUCCESS) + { + pMbss->MGMTTxCount++; + pMbss->MGMTTransmittedByteCount += Length; + } + else + { + pMbss->MGMTTxDropCount++; + pMbss->MGMTTxErrorCount++; + } + } +#endif +#endif + + +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + + return Status; +} + + +#ifdef CONFIG_AP_SUPPORT +/* + ======================================================================== + + 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 + pBuffer Pointer to memory of outgoing frame + Length Size of outgoing management frame + FlgIsDeltsFrame 1: the frame is a DELTS frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void AP_QueuePsActionPacket( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pMacEntry, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgIsDeltsFrame, + IN BOOLEAN FlgIsLocked, + IN UCHAR MgmtQid) +{ +#ifdef UAPSD_SUPPORT +#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY + PNDIS_PACKET DuplicatePkt = NULL; +#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */ +#endif /* UAPSD_SUPPORT */ + + /* Note: for original mode of 4 AC are UAPSD, if station want to change + the mode of a AC to legacy PS, we dont know where to put the + response; + 1. send the response; + 2. but the station is in ps mode, so queue the response; + 3. we should queue the reponse to UAPSD queue because the station + is not yet change its mode to legacy ps AC; + 4. so AP should change its mode to legacy ps AC only when the station + sends a trigger frame and we send out the reponse; + 5. the mechanism is too complicate; */ + +#ifdef UAPSD_SUPPORT + /* + If the frame is action frame and the VO is UAPSD, we can not send the + frame to VO queue, we need to send to legacy PS queue; or the frame + maybe not got from QSTA. + */ +/* if ((pMacEntry->bAPSDDeliverEnabledPerAC[MgmtQid]) &&*/ +/* (FlgIsDeltsFrame == 0))*/ + if (pMacEntry->bAPSDDeliverEnabledPerAC[MgmtQid]) + { + /* queue the management frame to VO queue if VO is deliver-enabled */ + DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to UAPSD queue %d ... (IsDelts: %d)\n", + MgmtQid, FlgIsDeltsFrame)); + +#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY + if (!pMacEntry->bAPSDAllAC) + { + /* duplicate one packet to legacy PS queue */ + RTMP_SET_PACKET_UAPSD(pPacket, 0, MgmtQid); + DuplicatePkt = RTMP_DUPLICATE_PACKET(pAd, pPacket, pMacEntry->apidx); + } + else +#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */ + { + RTMP_SET_PACKET_UAPSD(pPacket, 1, MgmtQid); + } + + UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, MgmtQid); + + if (pMacEntry->bAPSDAllAC) + { + /* mark corresponding TIM bit in outgoing BEACON frame*/ + WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid); + } + else + { +#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY + /* duplicate one packet to legacy PS queue */ + + /* + Sometimes AP will send DELTS frame to STA but STA will not + send any trigger frame to get the DELTS frame. + We must force to send it so put another one in legacy PS + queue. + */ + if (DuplicatePkt != NULL) + { + pPacket = DuplicatePkt; + goto Label_Legacy_PS; + } +#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */ + } + } + else +#endif /* UAPSD_SUPPORT */ + { + /* DuplicatePkt = DuplicatePacket(get_netdev_from_bssid(pAd, pMacEntry->apidx), pPacket, pMacEntry->apidx);*/ + +#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY +Label_Legacy_PS: +#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */ + if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES); + return; + } + else + { + ULONG IrqFlags=0; + + DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to legacy ps queue... (%d)\n", FlgIsDeltsFrame)); + + if (FlgIsLocked == FALSE) + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + if (FlgIsLocked == FALSE) + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + + /* mark corresponding TIM bit in outgoing BEACON frame*/ + WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid); + } +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* + ======================================================================== + + 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 + pBuffer Pointer to memory of outgoing frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MlmeHardTransmit( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgDataQForce, + IN BOOLEAN FlgIsLocked, + IN BOOLEAN FlgIsCheckPS) +{ +#ifdef CONFIG_AP_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; + HEADER_802_11 *pHeader_802_11; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#endif /* CONFIG_AP_SUPPORT */ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + + if ((pAd->Dot11_H.RDMode != RD_NORMAL_MODE) +#ifdef CARRIER_DETECTION_SUPPORT +#ifdef CONFIG_AP_SUPPORT + ||(isCarrierDetectExist(pAd) == TRUE) +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + { + return NDIS_STATUS_FAILURE; + } + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NDIS_STATUS_FAILURE; + +#ifdef CONFIG_AP_SUPPORT + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize + TSO_SIZE); + + /* + Section 11.2.1.1 STA Power Management modes of IEEE802.11-2007: + The Power Managment bit shall not be set in any management frame, + except an Action frame. + + So in the 'baseline' test plan + (Wi-Fi 802.11 WPA2, WPA, WEP Interoperability Test Plan), + Section 2.2.6, the following Requirement: + APs shall ignore the power save bit in any received Authenticate and + (Re) Associate, and shall assume that the station is awake for the + response. + */ + + /* + IEEE802.11, 11.2.1.4 AP operation during the contention period f) + A single buffered MSDU or management frame for a STA in the PS mode shall + be forwarded to the STA after a PS-Poll has been received from that STA. + The More Data field shall be set to indicate the presence of further + buffered MSDUs or "management frames" for the polling STA. + */ + + /* + IEEE802.11e, 11.2.1.4 Power management with APSD, + An unscheduled SP ends after the QAP has attempted to transmit at least + one MSDU or MMPDU associated with a delivery-enabled AC and destined for + the non-AP QSTA, but no more than the number indicated in the Max SP + Length field if the field has a nonzero value. + */ + + if ((pHeader_802_11->FC.Type == FC_TYPE_DATA) || + (pHeader_802_11->FC.Type == FC_TYPE_MGMT)) + { + if ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) || (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + +#ifdef DOT11K_RRM_SUPPORT +#ifdef QUIET_SUPPORT + if ((pEntry != NULL) + && (pEntry->apidx < pAd->ApCfg.BssidNum) + && IS_RRM_QUIET(pAd, pEntry->apidx)) + { + return NDIS_STATUS_FAILURE; + } +#endif /* QUIET_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + + + if ((pEntry != NULL) && + (pEntry->PsMode == PWR_SAVE) && + (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + (pHeader_802_11->FC.SubType != SUBTYPE_DATA_NULL) && + (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION_NO_ACK)) || + (FlgIsCheckPS == 1))) + { + /* the peer is in PS mode, we need to queue the management frame */ + UINT8 FlgIsDeltsFrame = 0, MgmtQid = QID_AC_VO; + + /* + 1. Data & Not QoS Null, or + 2. Management & Action, or + 3. Management & Action No ACK; + */ + DBGPRINT(RT_DEBUG_TRACE, ("STA in ps mode, queue the mgmt frame\n")); + RTMP_SET_PACKET_WCID(pPacket, pEntry->wcid); + RTMP_SET_PACKET_MGMT_PKT(pPacket, 1); /* is management frame */ + RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 0); /* default to management queue */ + + +#ifdef RT_CFG80211_P2P_SUPPORT + if(pEntry->wdev->wdev_type == WDEV_TYPE_AP) + { + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); + RTMP_SET_PACKET_OPMODE(pPacket, OPMODE_AP); + } +#endif /* RT_CFG80211_P2P_SUPPORT */ + + if (FlgDataQForce == TRUE) + RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 1); /* force to data queue */ + + if ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) + { + FRAME_ADDBA_REQ *pFrameBa = (FRAME_ADDBA_REQ *)pHeader_802_11; + if (pFrameBa->Category == CATEGORY_BA) + MgmtQid = QueIdx; + } +#ifdef CONFIG_HOTSPOT_R2 + if (((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DISASSOC)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DEAUTH))) + { + RTMP_SET_PACKET_DISASSOC(pPacket, 1); + pEntry->IsKeep = 1; + } +#endif /* CONFIG_HOTSPOT_R2 */ + + AP_QueuePsActionPacket(pAd, pEntry, pPacket, FlgIsDeltsFrame, + FlgIsLocked, MgmtQid); + return NDIS_STATUS_SUCCESS; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { +#ifdef RTMP_MAC_PCI + if (FlgDataQForce == TRUE) + return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); + else +#endif /* RTMP_MAC_PCI */ + return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); + } +} + + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + HEADER_802_11 *pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + UCHAR MlmeRate; + TXWI_STRUC *pFirstTxWI; + MAC_TABLE_ENTRY *pMacEntry = NULL; + UCHAR PID, wcid/*, tx_rate*/; + HTTRANSMIT_SETTING *transmit; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + /* Make sure MGMT ring resource won't be used by other threads*/ + RTMP_SEM_LOCK(&pAd->MgmtRingLock); + if (pSrcBufVA == NULL) + { + /* The buffer shouldn't be NULL*/ + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_FAILURE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* outgoing frame always wakeup PHY to prevent frame lost*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } +#endif /* CONFIG_STA_SUPPORT */ + + pFirstTxWI = (TXWI_STRUC *)(pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TSO_SIZE + TXWISize); + + if (pHeader_802_11->Addr1[0] & 0x01) + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + else + MlmeRate = pAd->CommonCfg.MlmeRate; + + /* Verify Mlme rate for a / g bands.*/ + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band*/ + MlmeRate = RATE_6; + + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) || + ((pHeader_802_11->FC.Type == FC_TYPE_CNTL) && + (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA))) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.*/ + // TODO: shiang-6590, why we need this condition check here? + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_A | WMODE_B | WMODE_G) +#ifdef DOT11_N_SUPPORT + || WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_A | WMODE_B | WMODE_G | WMODE_AN | WMODE_GN) +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + || WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_AC) +#endif /* DOT11_VHT_AC*/ + ) + { + if (pAd->LatchRfRegs.Channel > 14) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_0; + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + +//CFG_TODO YF + + + /* + Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) + Snice it's been set to 0 while on MgtMacHeaderInit + By the way this will cause frame to be send on PWR_SAVE failed. + */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* We are in scan progress, just let the PwrMgmt bit keep as it orginally should be.*/ + } + else +#endif /* CONFIG_STA_SUPPORT */ + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; +#ifdef CONFIG_STA_SUPPORT + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + /* + In WMM-UAPSD, mlme frame should be set psm as power saving but probe + request frame, Data-Null packets alse pass through MMRequest in RT2860, + however, we hope control the psm bit to pass APSD + */ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || + ((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) || + (pHeader_802_11->FC.SubType == SUBTYPE_DATA_NULL)))) + { + if (RtmpPktPmBitCheck(pAd) == TRUE) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + INFRA_ON(pAd) && + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* We are in scan progress, just let the PwrMgmt bit keep as it orginally should be */ + } + else + { + pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + pHeader_802_11->FC.MoreData = RTMP_GET_PACKET_MOREDATA(pPacket); +#endif /* CONFIG_AP_SUPPORT */ + + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == FC_TYPE_CNTL) /* must be PS-POLL*/ + { +#ifdef CONFIG_STA_SUPPORT + /*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.*/ + if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } +#endif /* CONFIG_STA_SUPPORT */ + bAckRequired = FALSE; + +#ifdef VHT_TXBF_SUPPORT + if (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA) + { + pHeader_802_11->Duration = 100; + //DBGPRINT(RT_DEBUG_OFF, ("%s(): VHT_NDPA frame, rate=%d, len=%d, duration=%d\n", + // __FUNCTION__, MlmeRate, SrcBufLen, pHeader_802_11->Duration)); + //hex_dump("VHT_NDPA after update Duration", (UCHAR *)pHeader_802_11, SrcBufLen); + + } +#endif /* VHT_TXBF_SUPPORT */ + } + else /* FC_TYPE_MGMT or FC_TYPE_DATA(must be NULL frame)*/ + { + if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST*/ + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { +#ifdef SOFT_SOUNDING + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + && pMacEntry && (pMacEntry->snd_reqired == TRUE)) + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else +#endif /* SOFT_SOUNDING */ + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == FC_TYPE_MGMT)) + { + bInsertTimestamp = TRUE; + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response*/ +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + { + /* Find which MBSSID to be send this probeRsp */ + UINT32 apidx = get_apidx_by_addr(pAd, pHeader_802_11->Addr2); + + if ( !(apidx >= pAd->ApCfg.BssidNum) && + (pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && + (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_CCK) && + (pAd->CommonCfg.MlmeTransmit.field.MCS == RATE_1)*/) + { + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; + } + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == FC_TYPE_MGMT)) + { + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request*/ + } + else if ((pHeader_802_11->FC.SubType == SUBTYPE_DEAUTH) && + (MacTableLookup(pAd, pHeader_802_11->Addr1) == NULL)) + { + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Deauth */ + } + } + } + } + + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence >0xfff) + pAd->Sequence = 0; + + /* + Before radar detection done, mgmt frame can not be sent but probe req + Because we need to use probe req to trigger driver to send probe req in passive scan + */ + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE)) + { + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_FAILURE; + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#endif + + + /* + fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET + should always has only one physical buffer, and the whole frame size equals + to the first scatter buffer size + */ + + + /* + Initialize TX Descriptor + For inter-frame gap, the number is for this frame and next frame + For MLME rate, we will fix as 2Mb to match other vendor's implement + */ + /*pAd->CommonCfg.MlmeTransmit.field.MODE = 1;*/ + + /* + management frame doesn't need encryption. + so use RESERVED_WCID no matter u are sending to specific wcid or not + */ + PID = PID_MGMT; + + + if (pMacEntry == NULL) + { + wcid = RESERVED_WCID; + /*tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS;*/ + transmit = &pAd->CommonCfg.MlmeTransmit; +#ifdef VHT_TXBF_SUPPORT + if (pAd->NDPA_Request) + { + transmit->field.MODE = MODE_VHT; + transmit->field.MCS = MCS_RATE_6; + } +#endif + } + else + { +//#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + /* P2P Test Case 6.1.12, only OFDM rate can be captured by sniffer */ + if( +#ifdef RT_CFG80211_P2P_SUPPORT + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)) && +#endif /* RT_CFG80211_P2P_SUPPORT */ + ((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))) + { + + HTTRANSMIT_SETTING NullFramePhyMode; + NdisZeroMemory(&NullFramePhyMode, sizeof(NullFramePhyMode)); + NdisCopyMemory(&NullFramePhyMode, &pMacEntry->HTPhyMode, sizeof(NullFramePhyMode)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Using Low Rate to send QOS NULL!!\n", __FUNCTION__)); + + if ((pAd->LatchRfRegs.Channel > 14) + ) + { + NullFramePhyMode.field.MODE = MODE_OFDM; + NullFramePhyMode.field.MCS = MCS_RATE_24; + } + else + { + NullFramePhyMode.field.MODE = MODE_CCK; + NullFramePhyMode.field.MCS = MCS_1; + } + + wcid = pMacEntry->wcid; + /*tx_rate = (UCHAR)NullFramePhyMode.field.MCS;*/ + transmit = &NullFramePhyMode; + + } + else +//#endif /* P2P_SUPPORT || RT_CFG80211_SUPPORT */ + { + /* dont use low rate to send QoS Null data frame */ + wcid = pMacEntry->wcid; + /*tx_rate = (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS;*/ + transmit = &pMacEntry->MaxHTPhyMode; + } + } + +#ifdef SOFT_SOUNDING + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + && pMacEntry && (pMacEntry->snd_reqired == TRUE)) + { + wcid = RESERVED_WCID; + tx_rate = (UCHAR)pMacEntry->snd_rate.field.MCS; + transmit = &pMacEntry->snd_rate; + + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, wcid, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE), PID, 0, + tx_rate, IFS_PIFS, transmit); + pMacEntry->snd_reqired = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s():Kick Sounding to %02x:%02x:%02x:%02x:%02x:%02x, dataRate(PhyMode:%s, BW:%sHz, %dSS, MCS%d)\n", + __FUNCTION__, PRINT_MAC(pMacEntry->Addr), + get_phymode_str(transmit->field.MODE), + get_bw_str(transmit->field.BW), + (transmit->field.MCS>>4) + 1, (transmit->field.MCS & 0xf))); + } + else +#endif /* SOFT_SOUNDING */ + { +#ifdef VHT_TXBF_SUPPORT + if ((pHeader_802_11->FC.Type == FC_TYPE_CNTL) && (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA)) + { + UINT8 PrevMcs, PrevMode; + + PrevMcs = transmit->field.MCS; + PrevMode = transmit->field.MODE; + + transmit->field.MODE = MODE_OFDM; + transmit->field.MCS = MCS_RATE_24; + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, + bAckRequired, FALSE, 0, wcid, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE), + PID, 0, SNDG_TYPE_NDP, IFS_BACKOFF, transmit); + + transmit->field.MCS = PrevMcs; + transmit->field.MODE = PrevMode; + } + else +#endif + { + //set tx_rate be zero for eBF with iPhone6 IOT issue + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, wcid, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE), PID, 0, + 0, IFS_BACKOFF, transmit); + } + +#ifdef SPECIFIC_TX_POWER_SUPPORT +#ifdef RTMP_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && + (pAd->chipCap.hif_type == HIF_RTMP) && (pMacEntry == NULL)) + pFirstTxWI->TXWI_O.TxPwrAdj = TxPwrAdj; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && + (pAd->chipCap.hif_type == HIF_RLT) && (pMacEntry == NULL)) + pFirstTxWI->TXWI_N.TxPwrAdj = TxPwrAdj; +#endif /* RLT_MAC */ +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + } + +//+++Add by shiang for debug +//---Add by shiang for debug + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif + + + /* Now do hardware-depened kick out.*/ + HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); +#ifdef CONFIG_HOTSPOT_R2 + if (RTMP_GET_PACKET_DISASSOC(pPacket)) + { + if (((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DISASSOC)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DEAUTH))) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + if ((pMacEntry) && (pMacEntry->IsKeep == 1)) + MacTableDeleteEntry(pAd, pMacEntry->Aid, pMacEntry->Addr); + } +#endif /* CONFIG_HOTSPOT_R2 */ + +#ifdef CUSTOMER_DCC_FEATURE + if(!(ApScanRunning(pAd))) + { + UINT32 Index, Length; + HTTRANSMIT_SETTING HTSetting; + MULTISSID_STRUCT *pMbss = NULL; + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = transmit->field.MODE; + HTSetting.field.BW = transmit->field.BW; + HTSetting.field.ShortGI = transmit->field.ShortGI; + HTSetting.field.MCS = transmit->field.MCS; + Length = SrcBufLen - TXINFO_SIZE - TXWISize; + GetMultShiftFactorIndex(HTSetting, &Index); + if ((pMacEntry != NULL) && (pMacEntry->apidx < pAd->ApCfg.BssidNum)) + pMbss = &pAd->ApCfg.MBSSID[pMacEntry->apidx]; + else + { + UCHAR apidx; + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev == NULL) || ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev)))) + { + /* the interface is down */ + continue; + } + if(RTMPEqualMemory(pAd->ApCfg.MBSSID[apidx].wdev.bssid, pHeader_802_11->Addr2,MAC_ADDR_LEN)) + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + } + } + } + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif + + /* Make sure to release MGMT ring resource*/ +/* if (!IrqState)*/ + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_SUCCESS; +} + + +/******************************************************************************** + + New DeQueue Procedures. + + ********************************************************************************/ +#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ + RTMP_IRQ_LOCK((lock), IrqFlags) + +#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ + RTMP_IRQ_UNLOCK((lock), IrqFlags) + + +/* + ======================================================================== + Tx Path design algorithm: + Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), + Specific Packet Type. Following show the classification rule and policy for each kinds of packets. + Classification Rule=> + Multicast: (*addr1 & 0x01) == 0x01 + Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. + 11N Rate : If peer support HT + (1).AMPDU -- If TXBA is negotiated. + (2).AMSDU -- If AMSDU is capable for both peer and ourself. + *). AMSDU can embedded in a AMPDU, but now we didn't support it. + (3).Normal -- Other packets which send as 11n rate. + + B/G Rate : If peer is b/g only. + (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 + (2).Normal -- Other packets which send as b/g rate. + Fragment: + The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. + + Classified Packet Handle Rule=> + Multicast: + No ACK, pTxBlk->bAckRequired = FALSE; + No WMM, pTxBlk->bWMM = FALSE; + No piggyback, pTxBlk->bPiggyBack = FALSE; + Force LowRate, pTxBlk->bForceLowRate = TRUE; + Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use + the same policy to handle it. + Force LowRate, pTxBlk->bForceLowRate = TRUE; + + 11N Rate : + No piggyback, pTxBlk->bPiggyBack = FALSE; + + (1).AMSDU + pTxBlk->bWMM = TRUE; + (2).AMPDU + pTxBlk->bWMM = TRUE; + (3).Normal + + B/G Rate : + (1).ARALINK + + (2).Normal + ======================================================================== +*/ +#ifdef VHT_TXBF_SUPPORT +static UCHAR TxPktClassification(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket, TX_BLK *pTxBlk, PUCHAR pTxSndgTypePerEntry) +#else +static UCHAR TxPktClassification(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket, TX_BLK *pTxBlk) +#endif +{ + UCHAR TxFrameType = TX_UNKOWN_FRAME; + UCHAR Wcid; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (Wcid == MCAST_WCID) + { /* Handle for RA is Broadcast/Multicast Address.*/ +#ifdef CONFIG_AP_SUPPORT +#ifdef RT_CFG80211_P2P_SUPPORT + //CFG_TODO: sigh... + if (pTxBlk->OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + { + // TODO: shiang-6590, fix me! + UCHAR apidx = RTMP_GET_PACKET_NET_DEVICE_MBSSID(pPacket); + if (apidx < pAd->ApCfg.BssidNum) + pTxBlk->wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s(%d): WARN! pTxBlk->wdev not assigned!\n", __FUNCTION__, __LINE__)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + return TX_MCAST_FRAME; + } + + /* Handle for unicast packets*/ + pMacEntry = &pAd->MacTab.Content[Wcid]; + pTxBlk->wdev = pMacEntry->wdev; + if (RTMP_GET_PACKET_LOWRATE(pPacket)) + { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame*/ + TxFrameType = TX_LEGACY_FRAME; + } +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + else if (RTMP_GET_PACKET_TDLS(pPacket)) + { + TxFrameType = TX_LEGACY_FRAME; + } +#endif /* DOT11Z_TDLS_SUPPORT */ +#ifdef DOT11_N_SUPPORT + else if (IS_HT_RATE(pMacEntry)) + { /* it's a 11n capable packet*/ + + /* Depends on HTPhyMode to check if the peer support the HTRate transmission.*/ + /* Currently didn't support A-MSDU embedded in A-MPDU*/ + TxFrameType = TX_UNKOWN_FRAME; + +#ifdef VHT_TXBF_SUPPORT + // Because MT7621 is the multi-core MCU, it will have multi-thread program execution. + // Timer interrupt will be executed in one CPU and driver will be executed in other CPUs. + // pMacEntry->TxSndgType is set in the timer interrupt and it will also be refered in + // driver. There is no problem in MT7620 but pMacEntry->TxSndgType will have asynchronous + // problem in MT7621. For example, + // When pMacEntry->TxSndgType is in SNDG_TYPE_DISABLE state and refered by driver at the beginning. + // At the meanwhile of program execution, the status of pMacEntry->TxSndgType is changed suddenly. + // It will make wrong status between enqueued packet and TXWI, and will also make MAC HW to be crashed. + // How to solve this problem ? Driver could read pMacEntry->TxSndgType before packet enqueue process + // and copy it with a local variable. By this local variable, it can avoid the asynchronous problem. + //iPhone6 IOT patch + if (!IS_VHT_RATE(pMacEntry)) + { + *pTxSndgTypePerEntry = pMacEntry->TxSndgType; + pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; + } +#endif + + if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) + TxFrameType |= TX_LEGACY_FRAME; +#ifdef UAPSD_SUPPORT + else if (RTMP_GET_PACKET_EOSP(pPacket)) + TxFrameType |= TX_LEGACY_FRAME; +#endif /* UAPSD_SUPPORT */ +#ifdef WFA_VHT_PF + else if (pAd->force_amsdu == TRUE) + return (TxFrameType | TX_AMSDU_FRAME); +#endif /* WFA_VHT_PF */ + else if ((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) + return (TxFrameType | TX_AMPDU_FRAME); + else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED) + ) + return (TxFrameType | TX_AMSDU_FRAME); + else + TxFrameType |= TX_LEGACY_FRAME; + + } +#endif /* DOT11_N_SUPPORT */ + else + { /* it's a legacy b/g packet.*/ + + if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && + (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && + (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))) + ) + { /* if peer support Ralink Aggregation, we use it.*/ + TxFrameType |= TX_RALINK_FRAME; + } + else + { + TxFrameType |= TX_LEGACY_FRAME; + + } + } + + /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.*/ + + if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) + && (TxFrameType == TX_LEGACY_FRAME +#ifdef VHT_TXBF_SUPPORT + || TxFrameType == (TX_LEGACY_FRAME | TX_NDPA_FRAME) +#endif + ) +#ifdef DOT11_N_SUPPORT + && ((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) == 0) +#endif /* DOT11_N_SUPPORT */ + ) + TxFrameType = TX_FRAG_FRAME; + + return TxFrameType; +} + + +BOOLEAN RTMP_FillTxBlkInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + PNDIS_PACKET pPacket; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + pPacket = pTxBlk->pPacket; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); +#ifdef TX_PKT_SG + NdisMoveMemory( &pTxBlk->pkt_info, &PacketInfo, sizeof(PacketInfo)); +#endif /* TX_PKT_SG */ + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); + pTxBlk->wdev_idx = RTMP_GET_PACKET_WDEV(pPacket); + + pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); + pTxBlk->FrameGap = IFS_HTTXOP; +#ifdef CONFIG_AP_SUPPORT + pTxBlk->pMbss = NULL; +#endif /* CONFIG_AP_SUPPORT */ + + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); + + /* Default to clear this flag*/ + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); + +#ifdef WAPI_SUPPORT + /* Check if this is an WPI data frame*/ + if ((RTMPIsWapiCipher(pAd, pTxBlk->apidx) == TRUE) && + (RTMP_GET_PACKET_WAI(pTxBlk->pPacket) == FALSE)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWPIDataFrame); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWPIDataFrame); +#endif /* WAPI_SUPPORT */ + + if (pTxBlk->Wcid == MCAST_WCID) + { + pTxBlk->pMacEntry = NULL; + { +#ifdef MCAST_RATE_SPECIFIC + PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); + if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) + pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; + else +#endif /* MCAST_RATE_SPECIFIC */ + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + } + + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode.*/ + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } +#ifdef ETH_CONVERT_SUPPORT + if (ADHOC_ON(pAd)) + { + /* If we are running as Ethernet Converter, update MAT DataBase and duplicant the packet if necessary.*/ + if (pAd->EthConvert.ECMode & ETH_CONVERT_MODE_DONGLE) + { + PNDIS_PACKET donglePkt; + + if(!NdisEqualMemory(pAd->CurrentAddress, (GET_OS_PKT_DATAPTR(pPacket) + 6), MAC_ADDR_LEN)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bDonglePkt); + } + + /* For each tx packet, update our MAT convert engine databases.*/ + donglePkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, 0, pTxBlk->OpMode); + if(donglePkt) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + pPacket = donglePkt; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + pTxBlk->pPacket = donglePkt; + } + } + } +#endif /* ETH_CONVERT_SUPPORT */ + } + else + { + pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; + pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; + + pMacEntry = pTxBlk->pMacEntry; +#ifdef CONFIG_AP_SUPPORT + pTxBlk->pMbss = pMacEntry->pMbss; +#endif /* CONFIG_AP_SUPPORT */ + + /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.*/ + if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); + else + TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); + +#ifdef CONFIG_STA_SUPPORT +#ifdef XLINK_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (ADHOC_ON(pAd)) /*&& + (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))*/) + { + if(pAd->StaCfg.PSPXlink) + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); + } +#endif /* XLINK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + { +#ifdef CONFIG_AP_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (pTxBlk->OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT*/ + { +#ifdef WDS_SUPPORT + if(IS_ENTRY_WDS(pMacEntry)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bWDSEntry); + } + else +#endif /* WDS_SUPPORT */ +#ifdef MWDS + if(IS_ENTRY_MWDS(pMacEntry)) + { +#ifdef APCLI_SUPPORT + if(IS_MWDS_OPMODE_APCLI(pMacEntry)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket); + if(!RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bMWDSFrame); + + pTxBlk->pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->wdev_idx]; + } + else +#endif /* APCLI_SUPPORT */ + if(IS_MWDS_OPMODE_AP(pMacEntry)) + { + if (VALID_MBSS(pAd, pMacEntry->apidx) && !RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bMWDSFrame); + } + } + else +#endif /* MWDS */ +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pMacEntry)) + { +#ifdef MAT_SUPPORT + PNDIS_PACKET apCliPkt = NULL; + UCHAR tmpIdx = pMacEntry->wdev_idx; + BOOLEAN bNeedMATHandle = TRUE; + +#ifdef MAC_REPEATER_SUPPORT + if ((pMacEntry->bReptCli) && (pAd->ApCfg.bMACRepeaterEn)) + { + pAd->MatCfg.bMACRepeaterEn = pAd->ApCfg.bMACRepeaterEn; + if(pAd->ApCfg.MACRepeaterOuiMode != 1) + tmpIdx = (64 + (MAX_EXT_MAC_ADDR_SIZE * pMacEntry->wdev_idx) + pMacEntry->MatchReptCliIdx); + else + bNeedMATHandle = FALSE; + } +#endif /* MAC_REPEATER_SUPPORT */ + if(bNeedMATHandle) + { + /* For each tx packet, update our MAT convert engine databases.*/ + apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, tmpIdx, pTxBlk->OpMode); + if(apCliPkt) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + pPacket = apCliPkt; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + pTxBlk->pPacket = apCliPkt; + } + } +#endif /* MAT_SUPPORT */ + pTxBlk->pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->wdev_idx]; + TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket); + + } + else +#endif /* APCLI_SUPPORT */ +#ifdef CLIENT_WDS + if (IS_ENTRY_CLIWDS(pMacEntry)) + { + PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); + PUCHAR pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN; + if (((pMacEntry->apidx < MAX_MBSSID_NUM(pAd)) + && !MAC_ADDR_EQUAL(pSA, pAd->ApCfg.MBSSID[pMacEntry->apidx].Bssid)) + || !MAC_ADDR_EQUAL(pDA, pMacEntry->Addr) + ) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bClientWDSFrame); + } + } + else +#endif /* CLIENT_WDS */ + if (IS_ENTRY_CLIENT(pMacEntry)) + { } + else + return FALSE; + + /* If both of peer and us support WMM, enable it.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (pTxBlk->OpMode == OPMODE_STA) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if(IS_ENTRY_TDLS(pMacEntry)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bTdlsEntry); + } +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef ETH_CONVERT_SUPPORT + /* If we are running as Ethernet Converter, update MAT DataBase and duplicant the packet if necessary.*/ + if (pAd->EthConvert.ECMode & ETH_CONVERT_MODE_DONGLE) + { + PNDIS_PACKET donglePkt; + + if(!NdisEqualMemory(pAd->CurrentAddress, (GET_OS_PKT_DATAPTR(pPacket) + 6), MAC_ADDR_LEN)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bDonglePkt); + } + + /* For each tx packet, update our MAT convert engine databases.*/ + donglePkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, 0, pTxBlk->OpMode); + if(donglePkt) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + pPacket = donglePkt; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + pTxBlk->pPacket = donglePkt; + } + } +#endif /* ETH_CONVERT_SUPPORT */ + + /* If support WMM, enable it.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && + CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + } +#endif /* CONFIG_STA_SUPPORT */ + } + + if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) + { + if ( ((RTMP_GET_PACKET_LOWRATE(pPacket)) +#ifdef UAPSD_SUPPORT + && (!(pMacEntry && (pMacEntry->bAPSDFlagSPStart))) +#endif /* UAPSD_SUPPORT */ + ) || + ((pAd->OpMode == OPMODE_AP) && + (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)) + ) + { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.*/ + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + +#ifdef WAPI_SUPPORT + /* According to WAPIA certification description, WAI packets can not + include QoS header */ + if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)) + { + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); + } +#endif /* WAPI_SUPPORT */ +#ifdef DOT11_N_SUPPORT + /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it? */ + if (IS_HT_STA(pTxBlk->pMacEntry) && + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && + ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) + { + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); + } +#endif /* DOT11_N_SUPPORT */ + } + +#ifdef DOT11_N_SUPPORT + if ( (IS_HT_RATE(pMacEntry) == FALSE) && + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) + { /* Currently piggy-back only support when peer is operate in b/g mode.*/ + TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); + } +#endif /* DOT11_N_SUPPORT */ + + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } +#ifdef UAPSD_SUPPORT + if (RTMP_GET_PACKET_EOSP(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); + } +#endif /* UAPSD_SUPPORT */ + } + else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); + } + + pMacEntry->DebugTxCount++; + } + + + pAd->LastTxRate = (USHORT)pTxBlk->pTransmit->word; + + return TRUE; +} + + +BOOLEAN CanDoAggregateTransmit( + IN RTMP_ADAPTER *pAd, + IN NDIS_PACKET *pPacket, + IN TX_BLK *pTxBlk) +{ + int minLen = LENGTH_802_3; + + /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));*/ + + if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) + return FALSE; + + if (RTMP_GET_PACKET_DHCP(pPacket) || + RTMP_GET_PACKET_EAPOL(pPacket) || + RTMP_GET_PACKET_WAI(pPacket) + ) + return FALSE; + + /* Make sure the first packet has non-zero-length data payload */ + if (RTMP_GET_PACKET_VLAN(pPacket)) + minLen += LENGTH_802_1Q; /* VLAN tag */ + else if (RTMP_GET_PACKET_LLCSNAP(pPacket)) + minLen += 8; /* SNAP hdr Len*/ + if (minLen >= GET_OS_PKT_LEN(pPacket)) + return FALSE; + + if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && + ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) + { /* For AMSDU, allow the packets with total length < max-amsdu size*/ + return FALSE; + } + + if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && + (pTxBlk->TxPacketList.Number == 2)) + { /* For RALINK-Aggregation, allow two frames in one batch.*/ + return FALSE; + } + +#ifdef CONFIG_STA_SUPPORT + if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP*/ + return TRUE; + else +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + /* CFG_TODO */ + if ((MAC_ADDR_EQUAL(GET_OS_PKT_DATAPTR(pTxBlk->pPacket), GET_OS_PKT_DATAPTR(pPacket))) + && (pAd->OpMode == OPMODE_AP)) /* unicast to same STA*/ + return TRUE; + else +#endif /* CONFIG_AP_SUPPORT */ + return FALSE; + +} + + +#ifdef RTMP_MAC_PCI +VOID TxDoneCleanupExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + unsigned long IrqFlags = 0; + ULONG FreeNum; + int NeedCleanupTimer = 0; + UCHAR QueIdx; + + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS))) + return; + + DEQUEUE_LOCK(&pAd->irq_lock, FALSE, IrqFlags); + for (QueIdx=0; QueIdxirq_lock, FALSE, IrqFlags); + + if (NeedCleanupTimer) + RTMPModTimer(&pAd->TxDoneCleanupTimer, 50); +} +#endif /* RTMP_MAC_PCI */ + + +/* + ======================================================================== + + Routine Description: + To do the enqueue operation and extract the first item of waiting + list. If a number of available shared memory segments could meet + the request of extracted item, the extracted item will be fragmented + into shared memory segments. + + Arguments: + pAd Pointer to our adapter + pQueue Pointer to Waiting Queue + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPDeQueuePacket( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bIntContext, + IN UCHAR QIdx, + IN INT Max_Tx_Packets) +{ + PQUEUE_ENTRY pEntry = NULL; + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR Count=0; + PQUEUE_HEADER pQueue; + ULONG FreeNumber[NUM_OF_TX_RING]; + CHAR QueIdx, sQIdx, eQIdx; + unsigned long IrqFlags = 0; + BOOLEAN hasTxDesc = FALSE; + TX_BLK TxBlk, *pTxBlk; + UCHAR RAWcid; +#ifdef TXBF_SUPPORT + UCHAR TxSndgType = SNDG_TYPE_DISABLE; +#endif /* TXBF_SUPPORT */ + MAC_TABLE_ENTRY *pMacEntry = NULL; + +#ifdef DBG_DIAGNOSE + BOOLEAN firstRound; + RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; +#endif +#if defined (LED_SOFT_SUPPORT) + ULONG HardTxTotal = 0; +#endif + + if (QIdx == NUM_OF_TX_RING) + { + sQIdx = 3; + eQIdx = 0; /* 4 ACs, start from 0.*/ + } + else + { + sQIdx = eQIdx = QIdx; + } + + for (QueIdx=sQIdx; QueIdx >= eQIdx; QueIdx--) + { + Count=0; + + RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); + +#ifdef DBG_DIAGNOSE + firstRound = ((QueIdx == sQIdx) ? TRUE : FALSE); +#endif /* DBG_DIAGNOSE */ + + while (1) + { + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET))) +#ifdef RT_CFG80211_P2P_SUPPORT + || IS_CFG80211_P2P_ABSENCE(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + { + RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + return; + } + + if (Count >= Max_Tx_Packets) + break; + + DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); + if (&pAd->TxSwQueue[QueIdx] == NULL) + { +#ifdef DBG_DIAGNOSE +#ifdef DBG_TXQ_DEPTH + if (firstRound == TRUE) + pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; +#endif /* DBG_TXQ_DEPTH */ +#endif /* DBG_DIAGNOSE */ + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + +#ifdef RTMP_MAC_PCI + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + +#ifdef DBG_DIAGNOSE +#ifdef DBG_TX_RING_DEPTH + if (firstRound == TRUE) + { + UCHAR txDescNumLevel, txSwQNumLevel; + + txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); /* Number of occupied hw desc.*/ + txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15); + pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++; + + txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8); + pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++; + + firstRound = FALSE; + } +#endif /* DBG_TX_RING_DEPTH */ +#endif /* DBG_DIAGNOSE */ + +#ifdef CONFIG_ARCH_MT7623 + if (1) +#else + /* We should never let more than 64kBytes of tx data not be + * cleaned up, or the TCP TX throughput will suffer as the + * window will not fill and so expand. 64kBytes ~ 44 full + * size ethernet packets. Use 32 as a nice constant. There + * is also a timer function which prevents packets getting + * "stuck" when data stops flowing + */ + + if ((TX_RING_SIZE - FreeNumber[QueIdx]) > 32) +#endif + { + /* free Tx(QueIdx) resources*/ + RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + } +#endif /* RTMP_MAC_PCI */ + + /* probe the Queue Head*/ + pQueue = &pAd->TxSwQueue[QueIdx]; + if ((pEntry = pQueue->Head) == NULL) + { + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + pTxBlk = &TxBlk; + NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); + + pTxBlk->QueIdx = QueIdx; + +#ifdef VENDOR_FEATURE1_SUPPORT + pTxBlk->HeaderBuf = (UCHAR *)pTxBlk->HeaderBuffer; +#endif /* VENDOR_FEATURE1_SUPPORT */ + + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + +#ifdef CONFIG_AP_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (RTMP_GET_PACKET_OPMODE(pPacket)) + { +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1) + { + /* this is a management frame */ + NDIS_STATUS status; + + pEntry = RemoveHeadQueue(pQueue); + +#ifdef RTMP_MAC_PCI + if ((pAd->MACVersion == 0x28600100) || + (RTMP_GET_PACKET_MGMT_PKT_DATA_QUE(pPacket) == 1)) + status = MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); + else +#endif /* RTMP_MAC_PCI */ + status = MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); + + if (status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("tx queued mgmt frame error!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + Count++; + continue; + } + else + { + /*when WDS Jam happen, drop following 1min to HW TxRing Pkts*/ + RAWcid = RTMP_GET_PACKET_WCID(pPacket); + pMacEntry = &pAd->MacTab.Content[RAWcid]; + +#ifdef WDS_SUPPORT + /* + It WDS life checking. + WDS need to check the peer is come back or not + by sending few (2 ~3) WDS Packet out to peer. + It must be checked first. + */ + if(IS_ENTRY_WDS(pMacEntry)) + { + ULONG Now32; + NdisGetSystemUpTime(&Now32); + if(pMacEntry->LockEntryTx && RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL)) + { + pEntry = RemoveHeadQueue(pQueue); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + Count++; + continue; + } + else + NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing); + } + else +#endif /* WDS_SUPPORT */ + if (!IS_ENTRY_NONE(pMacEntry) + && (pMacEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck)) + { + /* + Sample Lin, 20100412 + + For non-WDS interface, we need to send packet to detect + the link periodically; Or when + pMacEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck, + no any chance to clear pMacEntry->ContinueTxFailCnt. + + EX: When pMacEntry->ContinueTxFailCnt >= + pAd->ApCfg.EntryLifeCheck, the condition will not be + removed and we will drop all packets for the pEntry. + But maybe the signal becomes better. + So we try to send a packet periodically and we will + get the tx status in tx done interrupt. + If the tx status is success, pMacEntry->ContinueTxFailCnt + will be cleared to 0. + */ +#define ENTRY_RETRY_INTERVAL (100 * OS_HZ / 1000) + ULONG Now32; + NdisGetSystemUpTime(&Now32); + if(RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + ENTRY_RETRY_INTERVAL)) + { + pEntry = RemoveHeadQueue(pQueue); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + Count++; + continue; + } + else + NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing); + } + } +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + } +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT*/ +#endif /* CONFIG_AP_SUPPORT */ + + /* Early check to make sure we have enoguh Tx Resource.*/ + hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if (!hasTxDesc) + { + pAd->PrivateInfo.TxRingFullCnt++; + + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + + break; + } + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + pTxBlk->OpMode = RTMP_GET_PACKET_OPMODE(pPacket); +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ +#ifdef VHT_TXBF_SUPPORT + pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket, pTxBlk, &TxSndgType); +#else + pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket, pTxBlk); +#endif + pEntry = RemoveHeadQueue(pQueue); + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/ + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + pTxBlk->pPacket = pPacket; + + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + + if (pTxBlk->TxFrameType & (TX_RALINK_FRAME | TX_AMSDU_FRAME)) + { + // Enhance SW Aggregation Mechanism + if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) + { + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + } + + + if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) + { + // Enhance SW Aggregation Mechanism + if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) + { + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + do{ + if((pEntry = pQueue->Head) == NULL) + break; + + /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.*/ + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) + break; + + /*Remove the packet from the TxSwQueue and insert into pTxBlk*/ + pEntry = RemoveHeadQueue(pQueue); + ASSERT(pEntry); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + + + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/ + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + }while(1); + + if (pTxBlk->TxPacketList.Number == 1) + pTxBlk->TxFrameType = TX_LEGACY_FRAME; + } + + + Count += pTxBlk->TxPacketList.Number; + + /* Do HardTransmit now.*/ +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + if(pTxBlk->TxFrameType != TX_MCAST_FRAME) + APGetStreamingStatus(pAd, QueIdx, *pTxBlk); +#endif + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#ifdef TXBF_SUPPORT + Status = APHardTransmit(pAd, pTxBlk, QueIdx, TxSndgType); +#else + Status = APHardTransmit(pAd, pTxBlk, QueIdx); +#endif +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + //if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) + if (RTMP_GET_PACKET_OPMODE(pPacket)) +#ifdef TXBF_SUPPORT + Status = APHardTransmit(pAd, pTxBlk, QueIdx, TxSndgType); +#else + Status = APHardTransmit(pAd, pTxBlk, QueIdx); +#endif + else +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ +#ifdef TXBF_SUPPORT + Status = STAHardTransmit(pAd, pTxBlk, QueIdx, TxSndgType); +#else + Status = STAHardTransmit(pAd, pTxBlk, QueIdx); +#endif + } +#endif /* CONFIG_STA_SUPPORT */ + + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("Errror!! APHardTransmit() failed. ErrorCode = %d\n", Status)); + } + +#ifdef RTMP_MAC_PCI + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + /* static rate also need NICUpdateFifoStaCounters() function.*/ + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/ + if (++pAd->FifoUpdateDone >= FIFO_STAT_READ_PERIOD) + { + // TODO: shiang-usw, check this because of REG access here!! + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#endif /* RTMP_MAC_PCI */ + +#if defined (LED_SOFT_SUPPORT) + HardTxTotal++; +#endif + } + + RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + + +#ifdef BLOCK_NET_IF + if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) + && (pAd->TxSwQueue[QueIdx].Number < 1)) + { + releaseNetIf(&pAd->blockQueueTab[QueIdx]); + } +#endif /* BLOCK_NET_IF */ + } + +#if defined (LED_SOFT_SUPPORT) + if (HardTxTotal > 0 && pAd->MacTab.Size > 0) { +#if defined (DRIVER_HAS_MULTI_DEV) && (LED_SOFT_BLINK_GPIO_DEV1 >= 0) && (LED_SOFT_BLINK_GPIO_DEV1 != LED_SOFT_BLINK_GPIO) + if (pAd->dev_idx == 1) + ralink_gpio_led_blink(LED_SOFT_BLINK_GPIO_DEV1); + else +#endif + ralink_gpio_led_blink(LED_SOFT_BLINK_GPIO); + } +#endif +} + +#ifdef CUSTOMER_DCC_FEATURE +/* Get the status of the current Streaming stataus ( BE, BK, VI, VO) which is getting transmitted throught the AP */ +VOID APGetStreamingStatus( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN TX_BLK TxBlk) +{ + UINT64 Time = jiffies_to_msecs(jiffies); + static UCHAR packet_count[4] = {0}; + + switch(QueIdx) + { + case 0: + if((pAd->StreamingTypeStatus.BE == FALSE) && ((Time - pAd->StreamingTypeStatus.BE_Time ) > 1000)) + packet_count[0] = 0; + + packet_count[0] += (TxBlk.TotalFragNum > TxBlk.TotalFrameNum ? TxBlk.TotalFragNum : TxBlk.TotalFrameNum); + + if(packet_count[0] > 5) + pAd->StreamingTypeStatus.BE = TRUE; + + pAd->StreamingTypeStatus.BE_Time = Time; + break; + + case 1: + if((pAd->StreamingTypeStatus.BK == FALSE) && ((Time - pAd->StreamingTypeStatus.BK_Time ) > 1000)) + packet_count[1] = 0; + + packet_count[1] += (TxBlk.TotalFragNum > TxBlk.TotalFrameNum ? TxBlk.TotalFragNum : TxBlk.TotalFrameNum); + + if(packet_count[1] > 5) + pAd->StreamingTypeStatus.BK = TRUE; + + pAd->StreamingTypeStatus.BK_Time = Time; + break; + + case 2: + if((pAd->StreamingTypeStatus.VI == FALSE) && ((Time - pAd->StreamingTypeStatus.VI_Time ) > 1000)) + packet_count[2] = 0; + + packet_count[2] += (TxBlk.TotalFragNum > TxBlk.TotalFrameNum ? TxBlk.TotalFragNum : TxBlk.TotalFrameNum); + + if(packet_count[2] > 5) + pAd->StreamingTypeStatus.VI = TRUE; + + pAd->StreamingTypeStatus.VI_Time = Time; + break; + + case 3: + if((pAd->StreamingTypeStatus.VO == FALSE) && ((Time - pAd->StreamingTypeStatus.VO_Time ) > 1000)) + packet_count[3] = 0; + + packet_count[3] += (TxBlk.TotalFragNum > TxBlk.TotalFrameNum ? TxBlk.TotalFragNum : TxBlk.TotalFrameNum); + + if(packet_count[3] > 5) + pAd->StreamingTypeStatus.VO = TRUE; + + pAd->StreamingTypeStatus.VO_Time = Time; + break; + + default: + /* nothing to do */ + break; + } +} + +VOID RTMPCalculateAPTxRxActivityTime( + IN PRTMP_ADAPTER pAd, + IN UINT32 Index, + IN UINT32 Length, + IN PMULTISSID_STRUCT pMbss, + IN PMAC_TABLE_ENTRY pMacEntry) +{ + UINT64 Time; + + //Time = ((Length * 1000 * 1000 * 1000) / (Rate * 125000)); + Time = ((UINT64)Length * RateMultiplicationShiftFactor[Index].Multiplication) >> RateMultiplicationShiftFactor[Index].Shift; + // printk("index %u length %u time %llu \n", Index, Length, Time); + if(pAd->EnableChannelStatsCheck) + { + pAd->ChannelStats.ChannelApActivity1secValue += Time; + pAd->ChannelStats.ChannelApActivity += Time; + } + if (pMbss != NULL) + { + pMbss->ChannelUseTime +=Time; + if ((pMacEntry != NULL) && (IS_ENTRY_CLIENT(pMacEntry))) + { + pMacEntry->ChannelUseTime += Time; + } + } +} +#endif + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pAd Pointer to our adapter + Rate Transmit rate + Size Frame size in units of byte + + Return Value: + Duration number in units of usec + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +USHORT RTMPCalcDuration( + IN PRTMP_ADAPTER pAd, + IN UCHAR Rate, + IN ULONG Size) +{ + ULONG Duration = 0; + + if (Rate < RATE_FIRST_OFDM_RATE) /* CCK*/ + { + if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + Duration = 96; /* 72+24 preamble+plcp*/ + else + Duration = 192; /* 144+48 preamble+plcp*/ + + Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); + if ((Size << 4) % RateIdTo500Kbps[Rate]) + Duration ++; + } + else if (Rate <= RATE_LAST_OFDM_RATE)/* OFDM rates*/ + { + Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension*/ + Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); + if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) + Duration += 4; + } + else /*mimo rate*/ + { + Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension*/ + } + + return (USHORT)Duration; +} + + +/* + ======================================================================== + + Routine Description: + Suspend MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPSuspendMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */ + /* no carrier detection when scanning */ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStop(pAd); +#endif +#endif /* CONFIG_AP_SUPPORT */ + + /* + Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and + use Lowbound as R66 value on ScanNextChannel(...) + */ + bbp_get_agc(pAd, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + + pAd->hw_cfg.bbp_bw = pAd->CommonCfg.BBPCurrentBW; + + RTMPSetAGCInitValue(pAd, BW_20); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + /* abort all TX rings */ + /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); */ +} + + +/* + ======================================================================== + + Routine Description: + Resume MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + /* no carrier detection when scanning*/ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStart(pAd); +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* + After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value + R66 should not be 0 + */ + if (pAd->BbpTuning.R66CurrentValue == 0) + { + pAd->BbpTuning.R66CurrentValue = 0x38; + DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); + } + bbp_set_agc(pAd, pAd->BbpTuning.R66CurrentValue, RX_CHAIN_ALL); + + pAd->CommonCfg.BBPCurrentBW = pAd->hw_cfg.bbp_bw; + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +/* sample, for IRQ LOCK to SEM LOCK */ +/* + IrqState = pAd->irq_disabled; + if (IrqState) + RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); + else +*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} + + +#ifdef DOT11_N_SUPPORT +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR OpMode) +{ + USHORT PayloadSize; + USHORT SubFrameSize; + PHEADER_802_3 pAMSDUsubheader; + UINT nMSDU; + UCHAR Header802_3[14]; + + PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; + PNDIS_PACKET pClonePacket; + +#ifdef CONFIG_AP_SUPPORT + UCHAR FromWhichBSSID = RTMP_GET_PACKET_IF(pPacket); + UCHAR VLAN_Size; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + + + if ((FromWhichBSSID < pAd->ApCfg.BssidNum) + ) + VLAN_Size = (pAd->ApCfg.MBSSID[FromWhichBSSID].wdev.VLAN_VID != 0) ? LENGTH_802_1Q : 0; +#ifdef WDS_VLAN_SUPPORT + else if ((FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) && + (FromWhichBSSID < (MIN_NET_DEVICE_FOR_WDS + MAX_WDS_ENTRY))) + { + VLAN_Size = (pAd->WdsTab.WdsEntry[FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].wdev.VLAN_VID != 0) ? LENGTH_802_1Q : 0; + } +#endif /* WDS_VLAN_SUPPORT */ + else /* only MBssid support VLAN.*/ + VLAN_Size = 0; +#endif /* CONFIG_AP_SUPPORT */ + + nMSDU = 0; + + while (DataSize > LENGTH_802_3) + { + nMSDU++; + + /*hex_dump("subheader", pData, 64);*/ + pAMSDUsubheader = (PHEADER_802_3)pData; + /*pData += LENGTH_802_3;*/ + PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); + SubFrameSize = PayloadSize + LENGTH_802_3; + + if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) + break; + + /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize));*/ + pPayload = pData + LENGTH_802_3; + pDA = pData; + pSA = pData + MAC_ADDR_LEN; + + /* convert to 802.3 header*/ + CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); + +#ifdef CONFIG_STA_SUPPORT + if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) + ) + { + MLME_QUEUE_ELEM *Elem; + + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); + Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; + REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0, OPMODE_STA); + os_free_mem(NULL, Elem); + Elem = NULL; + } + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef APCLI_SUPPORT + if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) + { + /* avoid local heap overflow, use dyanamic allocation */ + MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/ + + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid, pSA)) + { + APCLI_STRUCT *apcli_entry; + apcli_entry = &pAd->ApCfg.ApCliTab[0]; + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + if (pRxBlk != NULL) + { + memmove(Elem->Msg, pRxBlk->pHeader, LENGTH_802_11); + memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); + Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; +#ifdef CUSTOMER_DCC_FEATURE + REPORT_MGMT_FRAME_TO_MLME(pAd, apcli_entry->MacTabWCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0, 0, 0, OPMODE_AP); +#else + REPORT_MGMT_FRAME_TO_MLME(pAd, apcli_entry->MacTabWCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0, OPMODE_AP); +#endif + } + os_free_mem(NULL, Elem); + } + } + /* A-MSDU has padding to multiple of 4 including subframe header.*/ + /* align SubFrameSize up to multiple of 4*/ + SubFrameSize = (SubFrameSize+3)&(~0x3); + + + if (SubFrameSize > 1528 || SubFrameSize < 32) + break; + + if (DataSize > SubFrameSize) + { + pData += SubFrameSize; + DataSize -= SubFrameSize; + } + else + { + /* end of A-MSDU*/ + DataSize = 0; + } + continue; + } +#endif + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR WhichBSSID = FromWhichBSSID; + if (pRemovedLLCSNAP) + { + pPayload -= (LENGTH_802_3 + VLAN_Size); + PayloadSize += (LENGTH_802_3 + VLAN_Size); + /*NdisMoveMemory(pPayload, &Header802_3, LENGTH_802_3);*/ + } + else + { + pPayload -= VLAN_Size; + PayloadSize += VLAN_Size; + } + + MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, WhichBSSID); + +#ifdef WDS_VLAN_SUPPORT + if (VLAN_VID == 0) /* maybe WDS packet */ + WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#endif /* WDS_VLAN_SUPPORT */ + + RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority, + Header802_3, LENGTH_802_3, pPayload, + FromWhichBSSID, TPID); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pRemovedLLCSNAP) + { + pPayload -= LENGTH_802_3; + PayloadSize += LENGTH_802_3; + NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); + if (pClonePacket) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); +#endif /* CONFIG_STA_SUPPORT */ + } + + + /* A-MSDU has padding to multiple of 4 including subframe header.*/ + /* align SubFrameSize up to multiple of 4*/ + SubFrameSize = (SubFrameSize+3)&(~0x3); + + + if (SubFrameSize > 1528 || SubFrameSize < 32) + break; + + if (DataSize > SubFrameSize) + { + pData += SubFrameSize; + DataSize -= SubFrameSize; + } + else + { + /* end of A-MSDU*/ + DataSize = 0; + } + } + + /* finally release original rx packet*/ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + + return nMSDU; +} + + +UINT BA_Reorder_AMSDU_Annnounce( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode) +{ + PUCHAR pData; + USHORT DataSize; + UINT nMSDU = 0; + + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + + nMSDU = deaggregate_AMSDU_announce(pAd, NULL, pPacket, pData, DataSize, OpMode); + + return nMSDU; +} + +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ +#ifdef APCLI_SUPPORT + if (check_rx_pkt_pn_allowed(pAd, pRxBlk) == FALSE) { + DBGPRINT(RT_DEBUG_WARN, ("%s:drop packet by PN mismatch!\n", __func__)); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +#endif /* APCLI_SUPPORT */ + RTMP_UPDATE_OS_PACKET_INFO(pAd, pRxBlk, FromWhichBSSID); + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + deaggregate_AMSDU_announce(pAd, pRxBlk, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize, pRxBlk->OpMode); +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID AssocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv) +{ + COPY_MAC_ADDR(AssocReq->Addr, pAddr); + /* Add mask to support 802.11b mode only */ + AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request*/ + AssocReq->Timeout = Timeout; + AssocReq->ListenIntv = ListenIntv; +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID DisassocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason) +{ + COPY_MAC_ADDR(DisassocReq->Addr, pAddr); + DisassocReq->Reason = Reason; +} + + +/* + NOTE: we do have an assumption here, that Byte0 and Byte1 + always reasid at the same scatter gather buffer + */ +static inline VOID Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER buf, + IN UCHAR offset, + OUT UCHAR *p0, + OUT UCHAR *p1) +{ + UCHAR *ptr = (UCHAR *)(buf + offset); + *p0 = *ptr; + *p1 = *(ptr + 1); +} + + +#define ETH_TYPE_VLAN 0x8100 +#define ETH_TYPE_IPv4 0x0800 +#define ETH_TYPE_IPv6 0x86dd +#define ETH_TYPE_ARP 0x0806 +#define ETH_TYPE_EAPOL 0x888e +#define ETH_TYPE_WAI 0x88b4 + +#define IP_VER_CODE_V4 0x40 +#define IP_VER_CODE_V6 0x60 +#define IP_PROTO_UDP 0x11 +#define IP_HDR_LEN 20 +#define ETH_HDR_LEN 14 + +VOID CheckQosMapUP(PMAC_TABLE_ENTRY pEntry, UCHAR DSCP, PUCHAR pUserPriority) +{ +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) + UCHAR i = 0, find_up = 0, dscpL = 0, dscpH = 0; + MULTISSID_STRUCT *pMbss = NULL; + RTMP_ADAPTER *pAd = NULL; + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: %d Entry is NULL\n",__FUNCTION__, __LINE__)); + return; + } + + if(IS_ENTRY_CLIENT(pEntry)) + pMbss = pEntry->pMbss; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: %d Entry is not client\n",__FUNCTION__, __LINE__)); + return; + } + + if (pEntry->QosMapSupport && pMbss->HotSpotCtrl.QosMapEnable) { + for (i=0;i<(pEntry->DscpExceptionCount/2);i++) { + if ((pEntry->DscpException[i] & 0xff) == DSCP) { + *pUserPriority = (pEntry->DscpException[i]>>8) & 0xff; + find_up = 1; + break; + } + } + + if (!find_up) { + for (i=0;i<8;i++) { + dscpL = pEntry->DscpRange[i] & 0xff; + dscpH = (pEntry->DscpRange[i]>>8) & 0xff; + if ((DSCP <= dscpH) && (DSCP >= dscpL)) { + *pUserPriority = i; + break; + } + } + } + } +#endif /* defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) */ +} + +#if defined (CONFIG_WIFI_PKT_FWD) +BOOLEAN is_gratuitous_arp(UCHAR *pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UCHAR *SenderIP; + UCHAR *TargetIP; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_ARP) + { + /* + * Check if Gratuitous ARP, Sender IP equal Target IP + */ + SenderIP = Pos + 14; + TargetIP = Pos + 24; + if (NdisCmpMemory(SenderIP, TargetIP, 4) == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is GratuitousARP\n")); + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN is_dad_packet(RTMP_ADAPTER *pAd, UCHAR *pData) +{ + //UCHAR *Pos = pData; + //UINT16 ProtoType; + UCHAR isLinkValid; + UCHAR *pSenderIP = pData + 16; + //UCHAR *pTargetIP = pData + 26; + UCHAR *pSourceMac = pData + 10; + UCHAR *pDestMac = pData + 20; + UCHAR ZERO_IP_ADDR[4] = {0x00, 0x00, 0x00, 0x00}; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + /* + * Check if DAD packet + */ + if ((RTMPLookupRepeaterCliEntry(pAd, FALSE, pSourceMac, TRUE, &isLinkValid) != NULL) && + ((MAC_ADDR_EQUAL(pDestMac, BROADCAST_ADDR) == TRUE) || + (MAC_ADDR_EQUAL(pDestMac, ZERO_MAC_ADDR) == TRUE)) && + (RTMPEqualMemory(pSenderIP, ZERO_IP_ADDR, 4) == TRUE)) { + DBGPRINT(RT_DEBUG_TRACE, ("DAD found, and do not send this packet\n")); + return TRUE; + } + + return FALSE; +} +#endif /* CONFIG_WIFI_PKT_FWD */ + +BOOLEAN RTMPCheckEtherType( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN struct wifi_dev *wdev, + OUT UCHAR *pUserPriority, + OUT UCHAR *pQueIdx) +{ + UINT16 TypeLen; + UCHAR Byte0, Byte1, *pSrcBuf, up = 0; +#ifdef CONFIG_AP_SUPPORT + BOOLEAN isMcast = FALSE; +#endif /* CONFIG_AP_SUPPORT */ + + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + ASSERT(pSrcBuf); + + RTMP_SET_PACKET_SPECIFIC(pPacket, 0); + +#ifdef CONFIG_AP_SUPPORT + if(IS_MULTICAST_MAC_ADDR(pSrcBuf)) + isMcast = TRUE; +#endif /* CONFIG_AP_SUPPORT */ + + /* get Ethernet protocol field and skip the Ethernet Header */ + TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; + pSrcBuf += LENGTH_802_3; + if (TypeLen <= 1500) + { /* 802.3, 802.3 LLC*/ + /* + DestMAC(6) + SrcMAC(6) + Lenght(2) + + DSAP(1) + SSAP(1) + Control(1) + + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. + => + SNAP (5, OriginationID(3) + etherType(2)) + else + => It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it + */ + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) + { + Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1); + RTMP_SET_PACKET_LLCSNAP(pPacket, 1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + pSrcBuf += 8; /* Skip this LLC/SNAP header*/ + } else { + return FALSE; + } + } + + /* If it's a VLAN packet, get the real Type/Length field.*/ + if (TypeLen == ETH_TYPE_VLAN) + { +#ifdef CONFIG_AP_SUPPORT + USHORT VLAN_VID = 0; + + /* + 802.3 VLAN packets format: + + DstMAC(6B) + SrcMAC(6B) + + 802.1Q Tag Type (2B = 0x8100) + Tag Control Information (2-bytes) + + Length/Type(2B) + + data payload (42-1500 bytes) + + FCS(4B) + + VLAN tag: 3-bit UP + 1-bit CFI + 12-bit VLAN ID + */ + + /* No matter unicast or multicast, discard it if not my VLAN packet. */ + VLAN_VID = wdev->VLAN_VID; + if (VLAN_VID != 0) + { + /* check if the packet is my VLAN */ + /* VLAN tag: 3-bit UP + 1-bit CFI + 12-bit VLAN ID */ + USHORT vlan_id = *(USHORT *)pSrcBuf; + + vlan_id = cpu2be16(vlan_id); + vlan_id = vlan_id & 0x0FFF; /* 12 bit */ + if (vlan_id != VLAN_VID) /* not my VLAN packet, discard it */ + return FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SET_PACKET_VLAN(pPacket, 1); + Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + + /* only use VLAN tag as UserPriority setting */ + up = (*pSrcBuf & 0xe0) >> 5; + + CheckQosMapUP(pMacEntry, (*pSrcBuf & 0xfc) >> 2, &up); + + pSrcBuf += 4; /* Skip the VLAN Header.*/ + } + else if (TypeLen == ETH_TYPE_IPv4) + { + /* + 0 4 8 14 15 31(Bits) + +---+----+-----+----+---------------+ + |Ver | IHL |DSCP |ECN | TotalLen | + +---+----+-----+----+---------------+ + Ver - 4bit Internet Protocol version number. + IHL - 4bit Internet Header Length + DSCP - 6bit Differentiated Services Code Point(TOS) + ECN - 2bit Explicit Congestion Notification + TotalLen - 16bit IP entire packet length(include IP hdr) + */ + up = (*(pSrcBuf + 1) & 0xe0) >> 5; + CheckQosMapUP(pMacEntry, (*(pSrcBuf+1) & 0xfc) >> 2, &up); + + } + else if (TypeLen == ETH_TYPE_IPv6) + { + /* + 0 4 8 12 16 31(Bits) + +---+----+----+----+---------------+ + |Ver | TrafficClas | Flow Label | + +---+----+----+--------------------+ + Ver - 4bit Internet Protocol version number. + TrafficClas - 8bit traffic class field, the 6 most-significant bits used for DSCP + */ + up = ((*pSrcBuf) & 0x0e) >> 1; + CheckQosMapUP(pMacEntry, ((*pSrcBuf & 0x0f) << 2)|((*(pSrcBuf+1)) & 0xc0) >> 6, &up); + } + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + if (pAd->VideoTurbine.Enable) + { + /* Ralink_VideoTurbine Out-band QoS */ + struct sk_buff *pSkbPkt = RTPKT_TO_OSPKT(pPacket); + + if(pSkbPkt->cb[40]==0x0E) + up = (pSkbPkt->cb[41] & 0xe0) >> 5; + } +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (wdev->wdev_type == WDEV_TYPE_AP) + { + MULTISSID_STRUCT *pMbss = (MULTISSID_STRUCT *)wdev->func_dev; + if ((pMbss->FilterUnusedPacket & FILTER_IPV6_MC) == FILTER_IPV6_MC) + { + if (isMcast && (TypeLen == ETH_TYPE_IPv6)) + return FALSE; + } + + if ((pMbss->FilterUnusedPacket & FILTER_IPV4_MC) == FILTER_IPV4_MC) + { + if (isMcast && (TypeLen == ETH_TYPE_IPv4)) + return FALSE; + } + + if ((pMbss->FilterUnusedPacket & FILTER_IPV6_ALL) == FILTER_IPV6_ALL) + { + if (TypeLen == ETH_TYPE_IPv6) + return FALSE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + switch (TypeLen) + { + case ETH_TYPE_IPv4: + { + UINT8 ipv4_proto = *(pSrcBuf + 9); + + ASSERT((GET_OS_PKT_LEN(pPacket) > (ETH_HDR_LEN + IP_HDR_LEN))); /* 14 for ethernet header, 20 for IP header*/ + RTMP_SET_PACKET_IPV4(pPacket, 1); + +#ifdef DATA_QUEUE_RESERVE + if (ipv4_proto == 0x01) + { + RTMP_SET_PACKET_ICMP(pPacket, 1); + } + else +#endif /* DATA_QUEUE_RESERVE */ + if (ipv4_proto == IP_PROTO_UDP) + { + UINT16 srcPort, dstPort; + + pSrcBuf += IP_HDR_LEN; + srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf))); + dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2))); + + if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) + { + /*It's a BOOTP/DHCP packet*/ + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + +#ifdef AIRPLAY_SUPPORT + if ((srcPort==5353 && dstPort==5353)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: this is mDns packet from upper layer ..... on V4\n", __FUNCTION__)); + RTMP_SET_PACKET_EAPOL(pPacket, 1); + } +#endif /* AIRPLAY_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (wdev->wdev_type == WDEV_TYPE_AP) + { +#ifdef CONFIG_DOT11V_WNM + WNMIPv4ProxyARPCheck(pAd, pPacket, srcPort, dstPort, pSrcBuf); +#endif /* CONFIG_DOT11V_WNM */ +#ifdef CONFIG_HOTSPOT + { + USHORT Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (!HSIPv4Check(pAd, &Wcid, pPacket, pSrcBuf, srcPort, dstPort)) + return FALSE; + } +#endif /* CONFIG_HOTSPOT */ + } +#endif /* CONFIG_AP_SUPPORT */ + } + } + break; + case ETH_TYPE_ARP: + { +#ifdef CONFIG_AP_SUPPORT + if (wdev->wdev_type == WDEV_TYPE_AP) + { +#ifdef CONFIG_DOT11V_WNM + MULTISSID_STRUCT *pMbss = (MULTISSID_STRUCT *)wdev->func_dev; + if (pMbss->WNMCtrl.ProxyARPEnable) + { + /* Check if IPv4 Proxy ARP Candidate from DS */ + if (IsIPv4ProxyARPCandidate(pAd, pSrcBuf - 2)) + { + BOOLEAN FoundProxyARPEntry; + FoundProxyARPEntry = IPv4ProxyARP(pAd, pMbss, pSrcBuf - 2, TRUE); + if (!FoundProxyARPEntry) + DBGPRINT(RT_DEBUG_TRACE, ("Can not find proxy entry\n")); + + return FALSE; + } + } +#endif /* CONFIG_DOT11V_WNM */ +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + { + if (!pMbss->HotSpotCtrl.DGAFDisable) + { + if (IsGratuitousARP(pAd, pSrcBuf - 2, pSrcBuf-14, pMbss)) + return FALSE; + } + } +#endif /* CONFIG_HOTSPOT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#if defined (CONFIG_WIFI_PKT_FWD) + if (wdev->wdev_type == WDEV_TYPE_AP) { + /* AP's tx shall check DAD.*/ + if (is_dad_packet(pAd, pSrcBuf - 2) || is_gratuitous_arp(pSrcBuf - 2)) + return FALSE; + } +#endif /* CONFIG_WIFI_PKT_FWD */ + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + break; + case ETH_P_IPV6: + { +#ifdef CONFIG_AP_SUPPORT + if (wdev->wdev_type == WDEV_TYPE_AP) + { +#ifdef CONFIG_DOT11V_WNM + MULTISSID_STRUCT *pMbss = (MULTISSID_STRUCT *)wdev->func_dev; + WNMIPv6ProxyARPCheck(pAd, pPacket, pSrcBuf); + if (pMbss->WNMCtrl.ProxyARPEnable) + { + /* Check if IPv6 Proxy ARP Candidate from DS */ + if (IsIPv6ProxyARPCandidate(pAd, pSrcBuf - 2)) + { + BOOLEAN FoundProxyARPEntry; + FoundProxyARPEntry = IPv6ProxyARP(pAd, pMbss, pSrcBuf - 2, TRUE); + if (!FoundProxyARPEntry) + DBGPRINT(RT_DEBUG_TRACE, ("Can not find IPv6 proxy entry\n")); + + return FALSE; + } + } +#endif /* CONFIG_DOT11V_WNM */ +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + { + if (!pMbss->HotSpotCtrl.DGAFDisable) + { + if (IsUnsolicitedNeighborAdver(pAd, pSrcBuf - 2)) + return FALSE; + } + } +#endif /* CONFIG_HOTSPOT */ + } + /* + Check if DHCPv6 Packet, and Convert group-address DHCP + packets to individually-addressed 802.11 frames + */ +#endif /* CONFIG_AP_SUPPORT */ + /* return AC_BE if packet is not IPv6 */ + if ((*pSrcBuf & 0xf0) != 0x60) + up = 0; + +#ifdef AIRPLAY_SUPPORT + + /* point to the Next Header */ + if (*(pSrcBuf + 6) == IP_PROTO_UDP) + { + UINT16 srcPort = 0, dstPort = 0; + + pSrcBuf += 40; /* IPV6 Header */ + srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf))); + dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2))); + + if ((srcPort==5353 && dstPort==5353)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: this is mDns packet from upper layer ..... on V6\n", __FUNCTION__)); + RTMP_SET_PACKET_EAPOL(pPacket, 1); + } + } + +#endif /* AIRPLAY_SUPPORT */ + + } + break; + case ETH_TYPE_EAPOL: + RTMP_SET_PACKET_EAPOL(pPacket, 1); + break; +#ifdef WAPI_SUPPORT + case ETH_TYPE_WAI: + RTMP_SET_PACKET_WAI(pPacket, 1); + break; +#endif /* WAPI_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + case 0x890d: + { + RTMP_SET_PACKET_TDLS(pPacket, 1); + up = 5; + } + break; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef SMART_MESH + case ETH_TYPE_SMART_MESH: + if(pMacEntry && IS_ENTRY_APCLI(pMacEntry)) + return FALSE; + break; +#endif /* SMART_MESH */ + + default: + break; + } + +#ifdef VENDOR_FEATURE1_SUPPORT + RTMP_SET_PACKET_PROTOCOL(pPacket, TypeLen); +#endif /* VENDOR_FEATURE1_SUPPORT */ + + /* have to check ACM bit. downgrade UP & QueIdx before passing ACM*/ + /* NOTE: AP doesn't have to negotiate TSPEC. ACM is controlled purely via user setup, not protocol handshaking*/ + /* + Under WMM ACM control, we dont need to check the bit; + Or when a TSPEC is built for VO but we will change priority to + BE here and when we issue a BA session, the BA session will + be BE session, not VO session. + */ + if (pAd->CommonCfg.APEdcaParm.bACM[WMM_UP2AC_MAP[up]]) + up = 0; + + + /* + Set WMM when + 1. wdev->bWmmCapable == TRUE + 2. Receiver's capability + a). bc/mc packets + ->Need to get UP for IGMP use + b). unicast packets + -> CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE) + 3. has VLAN tag or DSCP fields in IPv4/IPv6 hdr + */ + if ((wdev->bWmmCapable == TRUE) && (up <= 7)) + { + *pUserPriority = up; + *pQueIdx = WMM_UP2AC_MAP[up]; + } + + return TRUE; +} + +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU +VOID RTMP_RxPacketClassify( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + UINT16 protoType = OS_NTOHS(*((UINT16 *)(pData))); + + if (protoType == ETH_P_ARP) + { + pRxBlk->CriticalPkt = 1; // ARP + + DBGPRINT(RT_DEBUG_TRACE, ("rx path arp #(aid=%d,wcid=%d, pHeader seq=%d, ampdu = %d)\n", + pEntry->Aid, pRxBlk->wcid, pRxBlk->pHeader->Sequence, RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU))); + } + else if (protoType == ETH_P_IP) + { + + UINT8 protocol = *(pData + 11); + //UINT8 icmp_type = *(pData + 22); + + if (protocol == 0x1) + { + pRxBlk->CriticalPkt = 1; // ICMP + + DBGPRINT(RT_DEBUG_TRACE, ("rx path PING #(aid=%d,wcid=%d, pHeader seq=%d, ampdu = %d)\n", + pEntry->Aid, pRxBlk->wcid, pRxBlk->pHeader->Sequence, RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU))); + } +#if 0 + else if (protocol == IP_PROTO_UDP) + { + PUCHAR pUdpHdr = pData + 22; + UINT16 srcPort, dstPort; + + srcPort = OS_NTOHS(get_unaligned((PUINT16)(pUdpHdr))); + dstPort = OS_NTOHS(get_unaligned((PUINT16)(pUdpHdr+2))); + if ((srcPort==67 && dstPort==68)||(srcPort==68 && dstPort==67)) /*It's a DHCP packet */ + { + pRxBlk->CriticalPkt = 1; // DHCP + + DBGPRINT(RT_DEBUG_TRACE, ("rx path dhcp #(aid=%d,wcid=%d, pHeader seq=%d, ampdu = %d)\n", + pEntry->Aid, pRxBlk->wcid, pRxBlk->pHeader->Sequence, RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU))); + } + } +#endif + } +} +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + +VOID Update_Rssi_Sample( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi, + IN RXWI_STRUC *pRxWI) +{ + CHAR rssi[3] = {0}; + UCHAR snr[3] = {0}; + BOOLEAN bInitial = FALSE; + CHAR Phymode = get_pkt_phymode_by_rxwi(pAd, pRxWI); + + if (!(pRssi->AvgRssi0 | pRssi->AvgRssi0X8 | pRssi->LastRssi0)) + bInitial = TRUE; + + get_pkt_rssi_by_rxwi(pAd, pRxWI, 3, &rssi[0]); + get_pkt_snr_by_rxwi(pAd, pRxWI, 3, &snr[0]); + + if (snr[0] != 0) + { + pRssi->LastSnr0 = ConvertToSnr(pAd, (UCHAR)snr[0]); + if (bInitial) + { + pRssi->AvgSnr0X8 = pRssi->LastSnr0 << 3; + pRssi->AvgSnr0 = pRssi->LastSnr0; + } + else + pRssi->AvgSnr0X8 = (pRssi->AvgSnr0X8 - pRssi->AvgSnr0) + pRssi->LastSnr0; + + pRssi->AvgSnr0 = pRssi->AvgSnr0X8 >> 3; + } + + if (rssi[0] != 0) + { + pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi[0], RSSI_0); + +#ifdef RLT_MAC + if (IS_MT76x2(pAd)) { + if (Phymode == MODE_CCK) { + pRssi->LastRssi0 -= 2; + } + } +#endif /* RLT_MAC */ + + if (bInitial) + { + pRssi->AvgRssi0X8 = pRssi->LastRssi0 << 3; + pRssi->AvgRssi0 = pRssi->LastRssi0; + } + else + pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; + + pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; + } + + if (snr[1] != 0) + { + pRssi->LastSnr1 = ConvertToSnr(pAd, (UCHAR)snr[1]); + if (bInitial) + { + pRssi->AvgSnr1X8 = pRssi->LastSnr1 << 3; + pRssi->AvgSnr1 = pRssi->LastSnr1; + } + else + pRssi->AvgSnr1X8 = (pRssi->AvgSnr1X8 - pRssi->AvgSnr1) + pRssi->LastSnr1; + + pRssi->AvgSnr1 = pRssi->AvgSnr1X8 >> 3; + } + + if (rssi[1] != 0) + { + pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi[1], RSSI_1); + +#ifdef RLT_MAC + if (IS_MT76x2(pAd)) { + if (Phymode == MODE_CCK) { + pRssi->LastRssi1 -= 2; + } + } +#endif /* RLT_MAC */ + + if (bInitial) + { + pRssi->AvgRssi1X8 = pRssi->LastRssi1 << 3; + pRssi->AvgRssi1 = pRssi->LastRssi1; + } + else + pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; + + pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; + } + + if (rssi[2] != 0) + { + pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi[2], RSSI_2); + + if (bInitial) + { + pRssi->AvgRssi2X8 = pRssi->LastRssi2 << 3; + pRssi->AvgRssi2 = pRssi->LastRssi2; + } + else + pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; + + pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; + } +} + + + +/* Normal legacy Rx packet indication*/ +VOID Indicate_Legacy_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR Header802_3[LENGTH_802_3]; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + +#ifdef DBG +//+++Add by shiang for debug +if (0) { + hex_dump("Indicate_Legacy_Packet", pRxBlk->pData, pRxBlk->DataSize); + hex_dump("802_11_hdr", (UCHAR *)pRxBlk->pHeader, LENGTH_802_11); +} +//---Add by shiang for debug +#endif + +#ifdef APCLI_SUPPORT + if (check_rx_pkt_pn_allowed(pAd, pRxBlk) == FALSE) { + DBGPRINT(RT_DEBUG_WARN, ("%s:drop packet by PN mismatch!\n", __func__)); + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } +#endif /* APCLI_SUPPORT */ + + /* + 1. get 802.3 Header + 2. remove LLC + a. pointer pRxBlk->pData to payload + b. modify pRxBlk->DataSize + */ +#ifdef RT_CFG80211_SUPPORT + CFG80211_Convert802_3Packet(pAd, pRxBlk, Header802_3); +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RT_CFG80211_SUPPORT */ + + if (pRxBlk->DataSize > MAX_RX_PKT_LEN) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + +#ifdef CONFIG_AP_SUPPORT + MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); + +#ifdef WDS_VLAN_SUPPORT + if (VLAN_VID == 0) /* maybe WDS packet */ + WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#endif /* WDS_VLAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DBG +//+++Add by shiang for debug +if (0) { + hex_dump("Before80211_2_8023", pRxBlk->pData, pRxBlk->DataSize); + hex_dump("header802_3", &Header802_3[0], LENGTH_802_3); +} +//---Add by shiang for debug +#endif + + RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority, + pRxBlk, Header802_3, FromWhichBSSID, TPID); + +#ifdef DBG +//+++Add by shiang for debug +if (0) { + hex_dump("After80211_2_8023", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), GET_OS_PKT_LEN(pRxBlk->pRxPacket)); +} +//---Add by shiang for debug +#endif + + + /* pass this 802.3 packet to upper layer or forward this packet to WM directly*/ +#ifdef RT_CFG80211_SUPPORT + CFG80211_Announce802_3Packet(pAd, pRxBlk, FromWhichBSSID); +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MAC_REPEATER_SUPPORT /* This should be moved to some where else */ + if (pRxBlk->pRxInfo->Bcast && (pAd->ApCfg.bMACRepeaterEn) && (pAd->ApCfg.MACRepeaterOuiMode != 1)) + { + PUCHAR pPktHdr, pLayerHdr; + + pPktHdr = GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket); + 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; + UCHAR isLinkValid; + + bootpHdr = pUdpHdr + 8; + pCliHwAddr = (bootpHdr+28); + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pCliHwAddr, TRUE, &isLinkValid); + if (pReptEntry) + NdisMoveMemory(pCliHwAddr, pReptEntry->OriginalAddress, MAC_ADDR_LEN); +#if defined (CONFIG_WIFI_PKT_FWD) + else + { + REPEATER_ADAPTER_DATA_TABLE *opp_band_tbl = NULL; + REPEATER_ADAPTER_DATA_TABLE *band_tbl = NULL; + + if (wf_fwd_feedback_map_table) + wf_fwd_feedback_map_table(pAd, &band_tbl, &opp_band_tbl); + + if (opp_band_tbl != NULL) { + /* + check the ReptTable of the opposite band due to dhcp packet (BC) + may come-in 2/5G band when STA send dhcp broadcast to Root AP + */ + + pReptEntry = RTMPLookupRepeaterCliEntry(opp_band_tbl, FALSE, pCliHwAddr, FALSE, &isLinkValid); + if (pReptEntry) + NdisMoveMemory(pCliHwAddr, pReptEntry->OriginalAddress, MAC_ADDR_LEN); + } + else + DBGPRINT(RT_DEBUG_INFO, ("cannot find the adapter of the oppsite band\n")); + } +#endif /* CONFIG_WIFI_PKT_FWD */ + bHdrChanged = TRUE; + } + + if (bHdrChanged == TRUE) + NdisZeroMemory((pUdpHdr+6), 2); /*modify the UDP chksum as zero */ + } + } +#endif /* MAC_REPEATER_SUPPORT */ + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RT_CFG80211_SUPPORT */ +} + + +#ifdef HDR_TRANS_SUPPORT +/* Normal legacy Rx packet indication*/ +VOID Indicate_Legacy_Packet_Hdr_Trns( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR Header802_3[LENGTH_802_3]; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + + struct sk_buff *pOSPkt; + +#ifdef DBG +//+++Add by shiang for debug +if (0) { + hex_dump("Indicate_Legacy_Packet", pRxBlk->pTransData, pRxBlk->TransDataSize); + hex_dump("802_11_hdr", pRxBlk->pHeader, LENGTH_802_11); +} +//---Add by shiang for debug +#endif + + /* + 1. get 802.3 Header + 2. remove LLC + a. pointer pRxBlk->pData to payload + b. modify pRxBlk->DataSize + */ + + if (pRxBlk->TransDataSize > 1514 ) + { + + /* release packet*/ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + +#ifdef CONFIG_AP_SUPPORT + MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); + +#ifdef WDS_VLAN_SUPPORT + if (VLAN_VID == 0) /* maybe WDS packet */ + WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#endif /* WDS_VLAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DBG +//+++Add by shiang for debug +if (0) { + hex_dump("Before80211_2_8023", pRxBlk->pData, pRxBlk->TransDataSize); + hex_dump("header802_3", &Header802_3[0], LENGTH_802_3); +} +//---Add by shiang for debug +#endif + + { + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + + /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pOSPkt->data = pRxBlk->pTransData; + pOSPkt->len = pRxBlk->TransDataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; + //printk("\x1b[31m%s: rx trans ...%d\x1b[m\n", __FUNCTION__, __LINE__); + } + +#ifdef DBG +//+++Add by shiang for debug +if (0) { + hex_dump("After80211_2_8023", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), GET_OS_PKT_LEN(pRxBlk->pRxPacket)); +} +//---Add by shiang for debug +#endif + + /* pass this 802.3 packet to upper layer or forward this packet to WM directly*/ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); +#endif /* CONFIG_STA_SUPPORT */ + +} +#endif /* HDR_TRANS_SUPPORT */ + + +/* Normal, AMPDU or AMSDU*/ +VOID CmmRxnonRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif /* DOT11_N_SUPPORT */ + { +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); + else +#endif /* DOT11_N_SUPPORT */ + { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + } + } +} + + +/* Normal, AMPDU or AMSDU*/ +#ifdef HDR_TRANS_SUPPORT +VOID CmmRxnonRalinkFrameIndicate_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif /* DOT11_N_SUPPORT */ + { +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); + else +#endif /* DOT11_N_SUPPORT */ + { + Indicate_Legacy_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID); + } + } +} +#endif /* HDR_TRANS_SUPPORT */ + + +VOID CmmRxRalinkFrameIndicate( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UCHAR Header802_3[LENGTH_802_3]; + UINT16 Msdu2Size; + UINT16 Payload1Size, Payload2Size; + PUCHAR pData2; + PNDIS_PACKET pPacket2 = NULL; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + + + Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); + if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) + { + /* skip two byte MSDU2 len */ + pRxBlk->pData += 2; + pRxBlk->DataSize -= 2; + } + else + { + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* get 802.3 Header and remove LLC*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif /* CONFIG_STA_SUPPORT */ + + + ASSERT(pRxBlk->pRxPacket); + + /* Ralink Aggregation frame*/ + pAd->RalinkCounters.OneSecRxAggregationCount ++; + Payload1Size = pRxBlk->DataSize - Msdu2Size; + Payload2Size = Msdu2Size - LENGTH_802_3; + + pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + USHORT VLAN_VID = 0, VLAN_Priority = 0; + + MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#ifdef WDS_VLAN_SUPPORT + if (VLAN_VID == 0) /* maybe WDS packet */ + WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#endif /* WDS_VLAN_SUPPORT */ + + RT_VLAN_PKT_DUPLICATE(pPacket2, pAd, VLAN_VID, VLAN_Priority, + (pData2-LENGTH_802_3), LENGTH_802_3, pData2, + Payload2Size, FromWhichBSSID, TPID); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pPacket2 = duplicate_pkt(get_netdev_from_bssid(pAd, FromWhichBSSID), + (pData2-LENGTH_802_3), LENGTH_802_3, pData2, + Payload2Size, FromWhichBSSID); +#endif /* CONFIG_STA_SUPPORT */ + + if (!pPacket2) + { + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* update payload size of 1st packet*/ + pRxBlk->DataSize = Payload1Size; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); + +#ifdef WDS_VLAN_SUPPORT + if (VLAN_VID == 0) /* maybe WDS packet */ + WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID); +#endif /* WDS_VLAN_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + + RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority, + pRxBlk, Header802_3, FromWhichBSSID, TPID); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); +#endif /* CONFIG_STA_SUPPORT */ + + if (pPacket2) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +#define RESET_FRAGFRAME(_fragFrame) \ + { \ + _fragFrame.RxSize = 0; \ + _fragFrame.Sequence = 0; \ + _fragFrame.LastFrag = 0; \ + _fragFrame.Flags = 0; \ + } + + +PNDIS_PACKET RTMPDeFragmentDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + PNDIS_PACKET pRetPacket = NULL; + UCHAR *pFragBuffer = NULL; + BOOLEAN bReassDone = FALSE; + UCHAR HeaderRoom = 0; + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + UINT8 RXWISize = pAd->chipCap.RXWISize; + + ASSERT(pHeader); + + HeaderRoom = pData - (UCHAR *)pHeader; + + /* Re-assemble the fragmented packets*/ + if (pHeader->Frag == 0) + { /* Frag. Number is 0 : First frag or only one pkt*/ + /* the first pkt of fragment, record it.*/ + if (pHeader->FC.MoreFrag) + { + ASSERT(pAd->FragFrame.pFragPacket); + pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + /* Fix MT5396 crash issue when Rx fragmentation frame for Wi-Fi TGn 5.2.4 & 5.2.13 test items. + Copy RxWI content to pFragBuffer. + */ + //pAd->FragFrame.RxSize = DataSize + HeaderRoom; + //NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); + pAd->FragFrame.RxSize = DataSize + HeaderRoom + RXWISize; + NdisMoveMemory(pFragBuffer, pRxWI, RXWISize); + NdisMoveMemory(pFragBuffer + RXWISize, pHeader, pAd->FragFrame.RxSize - RXWISize); + pAd->FragFrame.Sequence = pHeader->Sequence; + pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0*/ + ASSERT(pAd->FragFrame.LastFrag == 0); + goto done; /* end of processing this frame*/ + } + } + else + { /*Middle & End of fragment*/ + if ((pHeader->Sequence != pAd->FragFrame.Sequence) || + (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) + { + /* Fragment is not the same sequence or out of fragment number order*/ + /* Reset Fragment control blk*/ + RESET_FRAGFRAME(pAd->FragFrame); + DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); + goto done; + } + /* Fix MT5396 crash issue when Rx fragmentation frame for Wi-Fi TGn 5.2.4 & 5.2.13 test items. */ + //else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) + else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE + RXWISize) + { + /* Fragment frame is too large, it exeeds the maximum frame size.*/ + /* Reset Fragment control blk*/ + RESET_FRAGFRAME(pAd->FragFrame); + DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); + goto done; + } + + + /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.*/ + /* In this case, we will drop it.*/ + if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); + goto done; + } + + pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + + /* concatenate this fragment into the re-assembly buffer*/ + NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); + pAd->FragFrame.RxSize += DataSize; + pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number*/ + + /* Last fragment*/ + if (pHeader->FC.MoreFrag == FALSE) + bReassDone = TRUE; + } + +done: + /* always release rx fragmented packet*/ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + /* return defragmented packet if packet is reassembled completely*/ + /* otherwise return NULL*/ + if (bReassDone) + { + PNDIS_PACKET pNewFragPacket; + + /* allocate a new packet buffer for fragment*/ + pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pNewFragPacket) + { + /* update RxBlk*/ + pRetPacket = pAd->FragFrame.pFragPacket; + pAd->FragFrame.pFragPacket = pNewFragPacket; + /* Fix MT5396 crash issue when Rx fragmentation frame for Wi-Fi TGn 5.2.4 & 5.2.13 test items. */ + //pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); + //pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; + //pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; + //pRxBlk->pRxPacket = pRetPacket; + pRxBlk->pRxWI = (RXWI_STRUC *) GET_OS_PKT_DATAPTR(pRetPacket); + pRxBlk->pHeader = (PHEADER_802_11) ((UCHAR *)pRxBlk->pRxWI + RXWISize); + pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; + pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom - RXWISize; + pRxBlk->pRxPacket = pRetPacket; + } + else + { + RESET_FRAGFRAME(pAd->FragFrame); + } + } + + return pRetPacket; +} + + +VOID Indicate_EAPOL_Packet( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: invalid wcid.\n")); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +#ifdef APCLI_SUPPORT + if (check_rx_pkt_pn_allowed(pAd, pRxBlk) == FALSE) { + DBGPRINT(RT_DEBUG_WARN, ("%s:drop packet by PN mismatch!\n", __func__)); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +#endif /* APCLI_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#if defined(P2P_APCLI_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (IS_PKT_OPMODE_AP(pRxBlk)) + { + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + else +#endif /* P2P_SUPPORT */ + { + ASSERT((pRxBlk->wcid == BSSID_WCID)); + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + } +#endif /* CONFIG_STA_SUPPORT */ + +} + + +#ifdef SOFT_ENCRYPT +BOOLEAN RTMPExpandPacketForSwEncrypt( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + UINT32 ex_head = 0, ex_tail = 0; + UCHAR NumberOfFrag = RTMP_GET_PACKET_FRAGMENTS(pTxBlk->pPacket); + +#ifdef WAPI_SUPPORT + if (pTxBlk->CipherAlg == CIPHER_SMS4) + ex_tail = LEN_WPI_MIC; + else +#endif /* WAPI_SUPPORT */ + if (pTxBlk->CipherAlg == CIPHER_AES) + ex_tail = LEN_CCMP_MIC; + + ex_tail = (NumberOfFrag * ex_tail); + + pTxBlk->pPacket = ExpandPacket(pAd, pTxBlk->pPacket, ex_head, ex_tail); + if (pTxBlk->pPacket == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: out of resource.\n", __FUNCTION__)); + return FALSE; + } + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + + return TRUE; +} + + +VOID RTMPUpdateSwCacheCipherInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pHdr) +{ + HEADER_802_11 *pHeader_802_11; + MAC_TABLE_ENTRY *pMacEntry; + + pHeader_802_11 = (HEADER_802_11 *) pHdr; + pMacEntry = pTxBlk->pMacEntry; + + if (pMacEntry && pHeader_802_11->FC.Wep && + CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + PCIPHER_KEY pKey = &pMacEntry->PairwiseKey; + + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + + pTxBlk->CipherAlg = pKey->CipherAlg; + pTxBlk->pKey = pKey; +#ifdef WAPI_SUPPORT + pTxBlk->KeyIdx = pMacEntry->usk_id; + + /* TSC increment pre encryption transmittion */ + if (pKey->CipherAlg == CIPHER_SMS4) + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2); + else +#endif /* WAPI_SUPPORT */ + if ((pKey->CipherAlg == CIPHER_WEP64) || (pKey->CipherAlg == CIPHER_WEP128)) + inc_iv_byte(pKey->TxTsc, LEN_WEP_TSC, 1); + else if ((pKey->CipherAlg == CIPHER_TKIP) || (pKey->CipherAlg == CIPHER_AES)) + inc_iv_byte(pKey->TxTsc, LEN_WPA_TSC, 1); + + } + +} + +#endif /* SOFT_ENCRYPT */ + +/* + ========================================================================== + Description: + Send out a NULL frame to a specified STA at a higher TX rate. The + purpose is to ensure the designated client is okay to received at this + rate. + ========================================================================== + */ +VOID RtmpEnqueueNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR TxRate, + IN UCHAR AID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP) +{ + NDIS_STATUS NState; + HEADER_802_11 *pNullFr; + UCHAR *pFrame; + UINT frm_len; + MAC_TABLE_ENTRY *pEntry; + + NState = MlmeAllocateMemory(pAd, (UCHAR **)&pFrame); + pNullFr = (PHEADER_802_11) pFrame; + + if (NState == NDIS_STATUS_SUCCESS) + { + frm_len = sizeof(HEADER_802_11); + + pEntry = MacTableLookup(pAd, pAddr); +#ifdef CONFIG_AP_SUPPORT + if ((pEntry != NULL) && (IS_ENTRY_CLIENT(pEntry))) + { + MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_DATA_NULL, 0, pAddr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + pNullFr->FC.FrDs = 1; + pNullFr->FC.ToDs = 0; + + goto body; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { + pNullFr->FC.FrDs = 0; + pNullFr->FC.ToDs = 1; + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if ((pEntry != NULL) && (IS_ENTRY_TDLS(pEntry))) + { + pNullFr->FC.FrDs = 0; + pNullFr->FC.ToDs = 0; + + COPY_MAC_ADDR(pNullFr->Addr1, pAddr); + COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pNullFr->Addr3, pAd->CommonCfg.Bssid); + } +#endif /* DOT11Z_TDLS_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + +body: + pNullFr->FC.Type = FC_TYPE_DATA; + + if (bQosNull) + { + UCHAR *qos_p = ((UCHAR *)pNullFr) + frm_len; + + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP; + qos_p[1] = 0; + frm_len += 2; + } else + pNullFr->FC.SubType = SUBTYPE_DATA_NULL; + + /* since TxRate may change, we have to change Duration each time */ + pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, frm_len); + + DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], AID & 0x3f)); + MiniportMMRequest(pAd, WMM_UP2AC_MAP[7], (PUCHAR)pNullFr, frm_len); + + MlmeFreeMemory(pAd, pFrame); + } +} + + +VOID RtmpPrepareHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP, + IN UCHAR OpMode, + IN UCHAR PwrMgmt, + IN BOOLEAN bWaitACK, + IN CHAR Index) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + TXWI_STRUC *pTxWI = &pAd->NullTxWI; + PUCHAR pNullFrame; + NDIS_STATUS NState; + HEADER_802_11 *pNullFr; + ULONG Length; + UCHAR *ptr; + UINT i; + UINT32 longValue; + + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pNullFrame); + + NdisZeroMemory(pNullFrame, 48); + NdisZeroMemory(pTxWI, TXWISize); + + if (NState == NDIS_STATUS_SUCCESS) + { + pNullFr = (PHEADER_802_11) pNullFrame; + Length = sizeof(HEADER_802_11); + + pNullFr->FC.Type = FC_TYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_DATA_NULL; + if (Index == 1) + pNullFr->FC.ToDs = 0; + else + pNullFr->FC.ToDs = 1; + pNullFr->FC.FrDs = 0; + + COPY_MAC_ADDR(pNullFr->Addr1, pEntry->Addr); + { + COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pNullFr->Addr3, pAd->CommonCfg.Bssid); + } + + pNullFr->FC.PwrMgmt = PwrMgmt; + + pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, pAd->CommonCfg.TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + pNullFr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + + if (bQosNull) + { + UCHAR *qos_p = ((UCHAR *)pNullFr) + Length; + + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP; + qos_p[1] = 0; + Length += 2; + } + + if (Index == 1) + { + HTTRANSMIT_SETTING Transmit; + + Transmit.word = pEntry->MaxHTPhyMode.word; + Transmit.field.BW = 0; + if (Transmit.field.MCS > 7) + Transmit.field.MCS = 7; + + RTMPWriteTxWI(pAd, + pTxWI, + FALSE, + FALSE, + FALSE, + FALSE, + TRUE, + TRUE, + 0, + pEntry->Aid, + Length, + (UCHAR)Transmit.field.MCS, + 0, + (UCHAR)Transmit.field.MCS, + IFS_HTTXOP, + &Transmit); + } + else + { + RTMPWriteTxWI(pAd, + pTxWI, + FALSE, + FALSE, + FALSE, + FALSE, + TRUE, + 0, + 0, + pEntry->Aid, + Length, + (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, + 0, + (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, + IFS_HTTXOP, + &pAd->CommonCfg.MlmeTransmit); + } + + if (bWaitACK) { +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + pTxWI->TXWI_O.TXRPT = 1; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + // TODO: shiang, how about RT65xx series?? +#endif /* RLT_MAC */ + + } + + ptr = (PUCHAR)&pAd->NullTxWI; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif /* RT_BIG_ENDIAN */ + for (i=0; i < TXWISize; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + if (Index == 0) + RTMP_IO_WRITE32(pAd, pAd->chipCap.BcnBase[14] + i, longValue); + else if (Index == 1) + RTMP_IO_WRITE32(pAd, pAd->chipCap.BcnBase[15] + i, longValue); + + ptr += 4; + } + + ptr = pNullFrame; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif /* RT_BIG_ENDIAN */ + for (i= 0; i< Length; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + if (Index == 0) //for ra0 + RTMP_IO_WRITE32(pAd, pAd->chipCap.BcnBase[14] + TXWISize+ i, longValue); + else if (Index == 1) //for p2p0 + RTMP_IO_WRITE32(pAd, pAd->chipCap.BcnBase[15] + TXWISize+ i, longValue); + + ptr += 4; + } + } + + if (pNullFrame) + MlmeFreeMemory(pAd, pNullFrame); + +} + + +// TODO: shiang-usw, modify the op_mode assignment for this function!!! +VOID dev_rx_mgmt_frm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + INT op_mode = pRxBlk->OpMode; + BOOLEAN bPassTheBcastPkt = FALSE; + +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; +#endif /* APCLI_CERT_SUPPOR */ +#endif /* APCLI_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + if (CFG80211_HandleP2pMgmtFrame(pAd, pRxBlk, op_mode)) + goto done; +#endif /* RT_CFG80211_SUPPORT */ + + +#ifdef DOT11W_PMF_SUPPORT + if (PMF_PerformRxFrameAction(pAd, pRxBlk) == FALSE) + goto done; +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + + op_mode = OPMODE_AP; +#ifdef IDS_SUPPORT + /* + Check if a rogue AP impersonats our mgmt frame to spoof clients + drop it if it's a spoofed frame + */ + if (RTMPSpoofedMgmtDetection(pAd, pHeader, pRxBlk)) + goto done; + + /* update sta statistics for traffic flooding detection later */ + RTMPUpdateStaMgmtCounter(pAd, pHeader->FC.SubType); +#endif /* IDS_SUPPORT */ + + if (!pRxInfo->U2M) + { + if ((pHeader->FC.SubType != SUBTYPE_BEACON) && (pHeader->FC.SubType != SUBTYPE_PROBE_REQ)) + { + + if (pHeader->FC.SubType == SUBTYPE_ACTION) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + INT i; + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + if (MAC_ADDR_EQUAL(pApCliEntry->wdev.if_addr, pHeader->Addr1)) + bPassTheBcastPkt = TRUE; /* Let this Action Frame pass */ + } + } +#endif /* APCLI_CERT_SUPPOR */ +#endif /* APCLI_SUPPORT */ + + if (!bPassTheBcastPkt) + goto done; /* Skip this packet */ + } + else + goto done; /* Skip this packet */ + } + } + + if (pAd->ApCfg.BANClass3Data == TRUE) + { + /* disallow new association */ + if ((pHeader->FC.SubType == SUBTYPE_ASSOC_REQ) || (pHeader->FC.SubType == SUBTYPE_AUTH)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disallow new Association\n")); + goto done; + } + } + + /* Software decrypts WEP data during shared WEP negotiation */ + if ((pHeader->FC.SubType == SUBTYPE_AUTH) && + (pHeader->FC.Wep == 1) && (pRxInfo->Decrypted == 0)) + { + UCHAR *pMgmt = (PUCHAR)pHeader; + UINT16 mgmt_len = pRxBlk->MPDUtotalByteCnt; + MAC_TABLE_ENTRY *pEntry = NULL; + + /* Skip 802.11 headre */ + pMgmt += LENGTH_802_11; + mgmt_len -= LENGTH_802_11; + + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: SW decrypt WEP data fails - the Entry is empty.\n")); + goto done; + } + + /* handle WEP decryption */ + if (RTMPSoftDecryptWEP(pAd, + &pAd->SharedKey[pEntry->apidx][pRxBlk->key_idx], + pMgmt, + &mgmt_len) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: SW decrypt WEP data fails.\n")); + goto done; + } +#ifdef RT_BIG_ENDIAN + /* swap 16 bit fields - Auth Alg No. field */ + *(USHORT *)pMgmt = SWAP16(*(USHORT *)pMgmt); + + /* swap 16 bit fields - Auth Seq No. field */ + *(USHORT *)(pMgmt + 2) = SWAP16(*(USHORT *)(pMgmt + 2)); + + /* swap 16 bit fields - Status Code field */ + *(USHORT *)(pMgmt + 4) = SWAP16(*(USHORT *)(pMgmt + 4)); +#endif /* RT_BIG_ENDIAN */ + + DBGPRINT(RT_DEBUG_TRACE, ("Decrypt AUTH seq#3 successfully\n")); + + /* Update the total length */ + pRxBlk->DataSize -= (LEN_WEP_IV_HDR + LEN_ICV); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + op_mode = OPMODE_STA; + +#ifdef RT_CFG80211_P2P_SUPPORT + /* CFG_TODO */ + op_mode = pRxBlk->OpMode; +#endif /* RT_CFG80211_P2P_SUPPORT */ + + /* check if need to resend PS Poll when received packet with MoreData = 1 */ + if ((RtmpPktPmBitCheck(pAd) == TRUE) && (pHeader->FC.MoreData == 1)) { + /* for UAPSD, all management frames will be VO priority */ + if (pAd->CommonCfg.bAPSDAC_VO == 0) { + /* non-UAPSD delivery-enabled AC */ + RTMP_PS_POLL_ENQUEUE(pAd); + } + } + + /* TODO: if MoreData == 0, station can go to sleep */ + + /* We should collect RSSI not only U2M data but also my beacon */ + if ((pHeader->FC.SubType == SUBTYPE_BEACON) + && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) + && (pAd->RxAnt.EvaluatePeriod == 0)) { + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxBlk->pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR) (pRxBlk->snr[0]); + pAd->StaCfg.LastSNR1 = (UCHAR) (pRxBlk->snr[1]); +#ifdef DOT11N_SS3_SUPPORT + pAd->StaCfg.LastSNR2 = (UCHAR) (pRxBlk->snr[2]); +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef PRE_ANT_SWITCH +#endif /* PRE_ANT_SWITCH */ + } + + if ((pHeader->FC.SubType == SUBTYPE_BEACON) && + (ADHOC_ON(pAd)) && + (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE)) { + MAC_TABLE_ENTRY *pEntry = NULL; + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + if (pEntry) + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxBlk->pRxWI); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pRxBlk->DataSize > MAX_RX_PKT_LEN) { + DBGPRINT(RT_DEBUG_TRACE, ("DataSize=%d\n", pRxBlk->DataSize)); + hex_dump("MGMT ???", (UCHAR *)pHeader, pRxBlk->pData - (UCHAR *) pHeader); + goto done; + } + +#if defined(CONFIG_AP_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (pHeader->FC.SubType == SUBTYPE_ACTION) + { + MAC_TABLE_ENTRY *pMacEntry = NULL; + + /* only PM bit of ACTION frame can be set */ + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + pMacEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + if (pMacEntry && ((op_mode == OPMODE_AP && IS_ENTRY_CLIENT(pMacEntry)) +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || (op_mode == OPMODE_STA && IS_ENTRY_TDLS(pMacEntry)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + )) + RtmpPsIndicate(pAd, pHeader->Addr2, pRxBlk->wcid, pHeader->FC.PwrMgmt); + + /* + In IEEE802.11, 11.2.1.1 STA Power Management modes, + The Power Managment bit shall not be set in any management + frame, except an Action frame. + + In IEEE802.11e, 11.2.1.4 Power management with APSD, + If there is no unscheduled SP in progress, the unscheduled SP + begins when the QAP receives a trigger frame from a non-AP QSTA, + which is a QoS data or QoS Null frame associated with an AC the + STA has configured to be trigger-enabled. + So a management action frame is not trigger frame. + */ + } +#endif /* defined(CONFIG_AP_SUPPORT) defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ +#ifdef SMART_MESH_MONITOR + HTTRANSMIT_SETTING HTSetting; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + HTSetting.field.MODE = pRxBlk->pRxWI->RXWI_N.phy_mode; + HTSetting.field.MCS = pRxBlk->pRxWI->RXWI_N.mcs; + HTSetting.field.BW = pRxBlk->pRxWI->RXWI_N.bw; + HTSetting.field.ShortGI = pRxBlk->pRxWI->RXWI_N.sgi; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + HTSetting.field.MODE = pRxBlk->pRxWI->RXWI_O.phy_mode; + HTSetting.field.MCS = pRxBlk->pRxWI->RXWI_O.mcs; + HTSetting.field.BW = pRxBlk->pRxWI->RXWI_O.bw; + HTSetting.field.ShortGI = pRxBlk->pRxWI->RXWI_O.sgi; + } +#endif /* RTMP_MAC */ + getRate(HTSetting, &pAd->LastMgmtRxRate); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + if (IS_MT76x2(pAd)) + { + pRxBlk->snr[0] = pRxBlk->pRxWI->RXWI_N.bbp_rxinfo[2]; + pRxBlk->snr[1] = pRxBlk->pRxWI->RXWI_N.bbp_rxinfo[2]; + } + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if (IS_RT6352(pAd)) + { + pRxBlk->snr[1] = pRxBlk->snr[0]; + } + } +#endif /* RTMP_MAC */ +#endif /*SMART_MESH_MONITOR*/ + +#ifdef CUSTOMER_DCC_FEATURE + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, pHeader, + pRxBlk->DataSize, + pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2], + pRxBlk->snr[0], pRxBlk->snr[1], min((CHAR)pRxBlk->snr[0], (CHAR)pRxBlk->snr[1]), + op_mode); +#else + /* Signal in MLME_QUEUE isn't used, therefore take this item to save min SNR. */ + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, pHeader, + pRxBlk->DataSize, + pRxBlk->rssi[0], pRxBlk->rssi[1], pRxBlk->rssi[2], + min((CHAR)pRxBlk->snr[0], (CHAR)pRxBlk->snr[1]), + op_mode); +#endif +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + if (pHeader->FC.Order) + { + handleHtcField(pAd, pRxBlk); + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; + } + + /* Check for compressed or non-compressed Sounding Response */ + if (((pHeader->FC.SubType == SUBTYPE_ACTION) || (pHeader->FC.SubType == SUBTYPE_ACTION_NO_ACK)) + && (pRxBlk->pData[0] == CATEGORY_HT) + && ((pRxBlk->pData[1] == MIMO_N_BEACONFORM) || (pRxBlk ->pData[1] == MIMO_BEACONFORM)) + ) + { + handleBfFb(pAd, pRxBlk); + } + } +#endif /* TXBF_SUPPORT */ + +done: +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + // management frame RX counter per BSS + if(!(ApScanRunning(pAd))) + { + MAC_TABLE_ENTRY *pEntry = NULL; + pEntry = PACInquiry(pAd, pRxBlk->wcid); + pAd->RadioStatsCounter.TotalRxCount++; + if (pEntry != NULL) + { + if (pHeader->FC.FrDs == 0 && (pEntry->apidx < pAd->ApCfg.BssidNum)) + { + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + if (pMbss != NULL) + { + pMbss->MGMTReceivedByteCount += pRxBlk->MPDUtotalByteCnt; + pMbss->MGMTRxCount++; + { + UINT32 Length, Index; + HTTRANSMIT_SETTING HTSetting; + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = pRxBlk->rx_rate.field.MODE; + HTSetting.field.BW = pRxBlk->rx_rate.field.BW; + HTSetting.field.ShortGI = pRxBlk->rx_rate.field.ShortGI; + HTSetting.field.MCS = pRxBlk->rx_rate.field.MCS; + Length = pRxBlk->MPDUtotalByteCnt; + GetMultShiftFactorIndex(HTSetting, &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pEntry); + } + } + } + } + } +#endif +#endif + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); +} + + +VOID dev_rx_ctrl_frm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + +#ifdef CUSTOMER_DCC_FEATURE + if(!(ApScanRunning(pAd))) + { + MAC_TABLE_ENTRY *pEntry = NULL; + pEntry = PACInquiry(pAd,pRxBlk->wcid); + + pAd->RadioStatsCounter.TotalRxCount++; + + if (pEntry != NULL) + { + if (pHeader->FC.FrDs == 0 && (pEntry->apidx < pAd->ApCfg.BssidNum)) + { + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + if (pMbss != NULL) + { + UINT32 Length, Index; + HTTRANSMIT_SETTING HTSetting; + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = pRxBlk->rx_rate.field.MODE; + HTSetting.field.BW = pRxBlk->rx_rate.field.BW; + HTSetting.field.ShortGI = pRxBlk->rx_rate.field.ShortGI; + HTSetting.field.MCS = pRxBlk->rx_rate.field.MCS; + Length = pRxBlk->MPDUtotalByteCnt; + GetMultShiftFactorIndex(HTSetting, &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pEntry); + } + } + } + } +#endif + + switch (pHeader->FC.SubType) + { +#ifdef DOT11_N_SUPPORT + case SUBTYPE_BLOCK_ACK_REQ: + { + FRAME_BA_REQ *bar = (FRAME_BA_REQ *)pHeader; +#ifdef SMART_MESH_MONITOR +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + To avoid control frames captured by sniffer confusing due to lack of Addr 3 + */ + if(!IsValidUnicastToMe(pAd, pRxBlk->wcid, bar->Addr1)) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + return; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_MONITOR */ + CntlEnqueueForRecv(pAd, pRxBlk->wcid, (pRxBlk->MPDUtotalByteCnt), (PFRAME_BA_REQ)pHeader); + if (bar->BARControl.Compressed == 0) { + UCHAR tid = bar->BARControl.TID; + BARecSessionTearDown(pAd, pRxBlk->wcid, tid, FALSE); + } + } + break; +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + case SUBTYPE_PS_POLL: +#ifdef RT_CFG80211_P2P_SUPPORT +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (IS_PKT_OPMODE_AP(pRxBlk)) +#else + /* SINGLE Device: TBD */ +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + { + USHORT Aid = pHeader->Duration & 0x3fff; + PUCHAR pAddr = pHeader->Addr2; + MAC_TABLE_ENTRY *pEntry; + + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + if (Aid == 0) + { + Aid = pEntry->Aid; + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Aid == 0 (pkt:%d, But Entry:%d)!\n", + __FUNCTION__, Aid, pEntry->Aid)); + } + + if (pEntry->Aid == Aid) + RtmpHandleRxPsPoll(pAd, pAddr, pRxBlk->wcid, FALSE); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Aid mismatch(pkt:%d, Entry:%d)!\n", + __FUNCTION__, Aid, pEntry->Aid)); + } + } + } + break; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WFA_VHT_PF + case SUBTYPE_RTS: + if (pAd->CommonCfg.vht_bw_signal && pRxBlk->wcid <= MAX_LEN_OF_MAC_TABLE) + { + PLCP_SERVICE_FIELD *srv_field; + RTS_FRAME *rts = (RTS_FRAME *)pRxBlk->pHeader; + + if ((rts->Addr1[0] & 0x1) == 0x1) { + srv_field = (PLCP_SERVICE_FIELD *)&pRxBlk->pRxWI->RXWI_N.bbp_rxinfo[15]; + if (srv_field->dyn_bw == 1) { + DBGPRINT(RT_DEBUG_TRACE, ("%02x:%02x:%02x:%02x:%02x:%02x, WCID:%d, DYN,BW=%d\n", + PRINT_MAC(rts->Addr1), pRxBlk->wcid, srv_field->cbw_in_non_ht)); + } + } + } + break; + + case SUBTYPE_CTS: + break; +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_N_SUPPORT + case SUBTYPE_BLOCK_ACK: +#endif /* DOT11_N_SUPPORT */ + case SUBTYPE_ACK: + default: + break; + } + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); +} + + +/* + ======================================================================== + Routine Description: + Process RxDone interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + This routine has to maintain Rx ring read pointer. + ======================================================================== +*/ + + +#undef MAX_RX_PROCESS_CNT +#define MAX_RX_PROCESS_CNT (256) + +BOOLEAN rtmp_rx_done_handle(RTMP_ADAPTER *pAd) +{ + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + RXD_STRUC *pRxD; + RXINFO_STRUC *pRxInfo; + UCHAR *pData; + RXWI_STRUC *pRxWI; + PNDIS_PACKET pRxPacket; + HEADER_802_11 *pHeader; + RX_BLK rxblk, *pRxBlk; + BOOLEAN bCmdRspPacket = FALSE; + +#ifdef LINUX +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#if defined(CONFIG_RA_CLASSIFIER) ||defined(CONFIG_RA_CLASSIFIER_MODULE) +#if defined(CONFIG_RALINK_EXTERNAL_TIMER) + classifier_cur_cycle = (*((volatile u32 *)(0xB0000D08))&0x0FFFF); +#else + classifier_cur_cycle = read_c0_count(); +#endif /* CONFIG_RALINK_EXTERNAL_TIMER */ +#endif /* CONFIG_RA_CLASSIFIER */ + } +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* LINUX */ + + RxProcessed = RxPending = 0; + + /* process whole rx ring */ + while (1) + { + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)) || + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + ) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE))) + { + break; + } + +#ifdef RTMP_MAC_PCI +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD_INDEX(RxProcessed); +#endif /* UAPSD_SUPPORT */ + + if (RxProcessed++ > MAX_RX_PROCESS_CNT) + { + bReschedule = TRUE; + pAd->rx_tasklet_resche_counter++; + break; + } + +#ifdef UAPSD_SUPPORT + /* static rate also need NICUpdateFifoStaCounters() function. */ + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ + UAPSD_MR_SP_SUSPEND(pAd); +#endif /* UAPSD_SUPPORT */ + + /* + Note: + + Can not take off the NICUpdateFifoStaCounters(); Or the + FIFO overflow rate will be high, i.e. > 3% + (see the rate by "iwpriv ra0 show stainfo") + + Based on different platform, try to find the best value to + replace '4' here (overflow rate target is about 0%). + */ + if (++pAd->FifoUpdateDone >= FIFO_STAT_READ_PERIOD) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#endif /* RTMP_MAC_PCI */ + + /* + 1. allocate a new data packet into rx ring to replace received packet + then processing the received packet + 2. the callee must take charge of release of packet + 3. As far as driver is concerned, the rx packet must + a. be indicated to upper layer or + b. be released if it is discarded + */ + +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU + rxblk.CriticalPkt = 0; +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + + pRxBlk = &rxblk; + pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending, &bCmdRspPacket, 0); + if ((pRxPacket == NULL) && !bCmdRspPacket) + break; + + if ((pRxPacket == NULL) && bCmdRspPacket) + continue; + + /* get rx descriptor and data buffer */ + pRxD = (RXD_STRUC *)&pRxBlk->hw_rx_info[0]; + pRxInfo = rxblk.pRxInfo; + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (RXWI_STRUC *)pData; + pHeader = rxblk.pHeader;// (PHEADER_802_11)(pData + RXWISize); + +#ifdef SMART_MESH_MONITOR + MAC_TABLE_ENTRY *pEntry = NULL; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if(pAd->MntEnable && !pRxInfo->CipherErr && !pRxInfo->Crc) + { + if(VALID_WCID(pRxBlk->wcid)) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + if(pEntry && IS_VALID_ENTRY(pEntry)) + { + // One who has been authenticated needs to do report to upper. + if(pEntry->MonitorWCID >= WCID_OF_MONITOR_STA_BASE && pEntry->MonitorWCID <= MAX_WCID_OF_MONITOR_STA) + Smart_Mesh_Pkt_Report_Action(pAd, pEntry->MonitorWCID, pRxWI, (PUCHAR)pHeader); + } + else if (pRxBlk->wcid >= WCID_OF_MONITOR_STA_BASE && pRxBlk->wcid <= MAX_WCID_OF_MONITOR_STA) + { + // One who matchs range of monitor wcid needs to do report to upper. + DBGPRINT(RT_DEBUG_TRACE, ("Monitor pRxWI->wcid=%d\n",pRxBlk->wcid)); + + Smart_Mesh_Pkt_Report_Action(pAd, pRxBlk->wcid, pRxWI, (PUCHAR)pHeader); + if(!((pHeader->FC.Type == FC_TYPE_MGMT) && (pHeader->FC.SubType == SUBTYPE_PROBE_REQ))) + { + if (!MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_MONITOR */ + +#ifndef HDR_TRANS_SUPPORT +#ifdef RLT_MAC + // TODO: shiang-6590, handle packet from other ports + if (pAd->chipCap.hif_type == HIF_RLT) + { + RXFCE_INFO *pFceInfo = rxblk.pRxFceInfo; +#ifdef RTMP_MAC_PCI +#ifdef MT76x2 + + if (pFceInfo->info_type == CMD_PACKET) + { + pci_rx_cmd_msg_complete(pAd, pFceInfo, (PUCHAR)pRxInfo); + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } + else +#endif /* MT76x2 */ +#endif /* RTMP_MAC_PCI */ + if ((pFceInfo->info_type != 0) || (pFceInfo->pkt_80211 != 1)) + { +#ifdef DBG + DBGPRINT(RT_DEBUG_OFF, ("==>%s(): GetFrameFromOtherPorts!\n", __FUNCTION__)); + hex_dump("hw_rx_info", &rxblk.hw_rx_info[0], sizeof(rxblk.hw_rx_info)); + DBGPRINT(RT_DEBUG_TRACE, ("Dump the RxD, RxFCEInfo and RxInfo:\n")); + hex_dump("RxD", (UCHAR *)pRxD, sizeof(RXD_STRUC)); +#ifdef RTMP_MAC_PCI + dump_rxd(pAd, pRxD); +#endif /* RTMP_MAC_PCI */ + dumpRxFCEInfo(pAd, pFceInfo); + dump_rxinfo(pAd, pRxInfo); + hex_dump("RxFrame", (UCHAR *)pData, (pFceInfo->pkt_len)); + DBGPRINT(RT_DEBUG_OFF, ("<==\n")); +#endif + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } + } +#endif /* RLT_MAC */ +#endif /* HDR_TRANS_SUPPORT */ + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); + RTMPWIEndianChange(pAd , (PUCHAR)pRxWI, TYPE_RXWI); +#endif + +//+++Add by shiang for debug +//---Add by shiang for debug + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_RXWI) + dbQueueEnqueueRxFrame(pData, (UCHAR *)pHeader, pAd->CommonCfg.DebugFlags); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* build RX_BLK */ + rxblk.pRxWI = pRxWI; + rxblk.pHeader = pHeader; + rxblk.pRxPacket = pRxPacket; + rxblk.pData = (UCHAR *)pHeader; + rxblk.DataSize = pRxBlk->MPDUtotalByteCnt; + rxblk.Flags = 0; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + SET_PKT_OPMODE_AP(&rxblk); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + SET_PKT_OPMODE_STA(&rxblk); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RT_CFG80211_P2P_SUPPORT +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + + if (RTMP_CFG80211_VIF_P2P_GO_ON(pAd) && + (NdisEqualMemory(pAd->cfg80211_ctrl.P2PCurrentAddress, pHeader->Addr1, MAC_ADDR_LEN) || + (pHeader->FC.SubType == SUBTYPE_PROBE_REQ))) + { + SET_PKT_OPMODE_AP(&rxblk); + } + else if (RTMP_CFG80211_VIF_P2P_CLI_ON(pAd) && + (((pHeader->FC.SubType == SUBTYPE_BEACON || pHeader->FC.SubType == SUBTYPE_PROBE_RSP) && + NdisEqualMemory(pAd->ApCfg.ApCliTab[MAIN_MBSSID].CfgApCliBssid, pHeader->Addr2, MAC_ADDR_LEN)) || + (pHeader->FC.SubType == SUBTYPE_PROBE_REQ) || + NdisEqualMemory(pAd->ApCfg.ApCliTab[MAIN_MBSSID].MlmeAux.Bssid, pHeader->Addr2, MAC_ADDR_LEN))) + { + + SET_PKT_OPMODE_AP(&rxblk); + } + else + { + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP) + SET_PKT_OPMODE_AP(&rxblk); + else + SET_PKT_OPMODE_STA(&rxblk); + } +#else + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP) + SET_PKT_OPMODE_AP(&rxblk); + else + SET_PKT_OPMODE_STA(&rxblk); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#ifdef HDR_TRANS_SUPPORT + rxblk.bHdrRxTrans = pRxInfo->ip_sum_err; /* RXINFO bit 31 */ + rxblk.bHdrVlanTaged = pRxInfo->tcp_sum_err; /* RXINFO bit 30 */ + rxblk.pTransData = (UCHAR *) pHeader + 36; /* 36 byte - 802.11 MAC header (RX Wifi Info */ + rxblk.TransDataSize = pRxBlk->MPDUtotalByteCnt; +#endif /* HDR_TRANS_SUPPORT */ + + /* Increase Total receive byte counter after real data received no mater any error or not */ + pAd->RalinkCounters.ReceivedByteCount += rxblk.DataSize; + pAd->RalinkCounters.OneSecReceivedByteCount += rxblk.DataSize; + pAd->RalinkCounters.RxCount++; + pAd->RalinkCounters.OneSecRxCount++; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); + + pAd->ate.RxCntPerSec++; + ATESampleRssi(pAd, pRxWI); + +#ifdef RALINK_QA + if ((pAd->ate.bQARxStart == TRUE) || (pAd->ate.Mode & ATE_RXFRAME)) + { + /* GetPacketFromRxRing() has copy the endian-changed RxD if it is necessary. */ + ATE_QA_Statistics(pAd, pRxWI, pRxInfo, pHeader); + } + +#ifdef TXBF_SUPPORT + /* Check sounding frame */ + if ((pAd->chipCap.FlgHwTxBfCap) && (pHeader->FC.Type == FC_TYPE_MGMT)) + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + + if (pHeader->FC.Order) { + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; + } + + if ((((pHeader->FC.SubType == SUBTYPE_ACTION) || (pHeader->FC.SubType == SUBTYPE_ACTION_NO_ACK)) + && (pRxBlk ->pData)[ 0] == CATEGORY_HT + && ((pRxBlk ->pData)[ 1] == MIMO_N_BEACONFORM /*non-compressed beamforming report */ + || (pRxBlk ->pData)[1] == MIMO_BEACONFORM) )) /*compressed beamforming report */ + { + /* sounding frame */ + if (pAd->ate.sounding == 1) { + int i, Nc = ((pRxBlk ->pData)[2] & 0x3) + 1; + pAd->ate.soundingSNR[0] = (CHAR)((pRxBlk ->pData)[8]); + pAd->ate.soundingSNR[1] = (Nc<2)? 0: (CHAR)((pRxBlk ->pData)[9]); + pAd->ate.soundingSNR[2] = (Nc<3)? 0: (CHAR)((pRxBlk ->pData)[10]); + pAd->ate.sounding = 2; + pAd->ate.soundingRespSize = pRxBlk->DataSize; + for (i=0; iDataSize && iate.soundingResp[i] = pRxBlk->pData[i]; + } + } + /* Roger Debug : Fix Me */ + else + { + if (pHeader->FC.Order) + DBGPRINT( RT_DEBUG_WARN, ("fcsubtype=%x\ndata[0]=%x\ndata[1]=%x\n", + pHeader->FC.SubType, (pRxBlk ->pData)[0], (pRxBlk ->pData)[1])); + } + } + +#ifdef MT76x2 +#ifdef RTMP_MAC_PCI + + if ((pHeader->FC.Type == FC_TYPE_DATA)) + { + if ((pAd->chipCap.FlgHwTxBfCap) && (pAd->ate.bITxBf_Cal == TRUE)) + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + + if (pHeader->FC.Order) { + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; + } + + if (((pRxBlk ->pData)[0] == 0xC0) && ((pRxBlk ->pData)[1] == 0x01)) { + RtmpOsMsDelay(1); // Delay 1ms + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); + //ATESendNullFrame(pAd, 0, 0, 0); + mt76x2_ate_SendNullFrame(pAd); + } + + } + } +#endif /* RTMP_MAC_PCI */ +#endif /* MT76x2 */ +#endif /* TXBF_SUPPORT */ +#endif /* RALINK_QA */ + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } +#endif /* RALINK_ATE */ + +#ifdef STATS_COUNT_SUPPORT + INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); +#endif /* STATS_COUNT_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT + if (MONITOR_ON(pAd) && pAd->monitor_ctrl.current_monitor_mode != MONITOR_MODE_OFF) + { + PNDIS_PACKET pClonePacket; + PNDIS_PACKET pTmpRxPacket; + + if(pAd->monitor_ctrl.current_monitor_mode == MONITOR_MODE_REGULAR_RX) + { + /* only report Probe_Req */ + if((pHeader->FC.Type == FC_TYPE_MGMT) && (pHeader->FC.SubType == SUBTYPE_PROBE_REQ)) + { + pTmpRxPacket = rxblk.pRxPacket; + pClonePacket = ClonePacket(pAd, rxblk.pRxPacket, rxblk.pData, rxblk.DataSize); + rxblk.pRxPacket = pClonePacket; + STA_MonPktSend(pAd, &rxblk); + + rxblk.pRxPacket = pTmpRxPacket; + } + } + else if(pAd->monitor_ctrl.current_monitor_mode == MONITOR_MODE_FULL) + { + pTmpRxPacket = rxblk.pRxPacket; + pClonePacket = ClonePacket(pAd, rxblk.pRxPacket, rxblk.pData, rxblk.DataSize); + rxblk.pRxPacket = pClonePacket; + STA_MonPktSend(pAd, &rxblk); + //RELEASE_NDIS_PACKET(pAd, rxblk.pRxPacket , NDIS_STATUS_SUCCESS); + rxblk.pRxPacket = pTmpRxPacket; + } + else if(pAd->monitor_ctrl.current_monitor_mode == MONITOR_MODE_FULL_NO_CLONE) + { + STA_MonPktSend(pAd, &rxblk); + continue; + } + + } + + if (rxblk.DataSize < 14) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + continue; + } +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* Check for all RxD errors */ + if (APCheckRxError(pAd, pRxInfo, pRxBlk) != NDIS_STATUS_SUCCESS) + { + APRxErrorHandle(pAd, &rxblk); + + /* Increase received error packet counter per BSS */ + if (pHeader->FC.FrDs == 0 && + pRxInfo->U2M && + pRxBlk->bss_idx < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pRxBlk->bss_idx]; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + if (pHeader->FC.Type == FC_TYPE_DATA) + { + pMbss->RxDropCount ++; + pMbss->RxErrorCount ++; + } + else if (pHeader->FC.Type == FC_TYPE_MGMT) + { + pMbss->MGMTRxDropCount++; + pMbss->MGMTRxErrorCount++; + } +#endif +#else + pMbss->RxDropCount ++; + pMbss->RxErrorCount ++; +#endif + } + +#ifdef WDS_SUPPORT +#ifdef STATS_COUNT_SUPPORT + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) + { + MAC_TABLE_ENTRY *pEntry = NULL; + + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxBlk->wcid, pHeader->Addr2, pRxBlk->rx_rate.field.MODE); + if(pEntry) + pAd->WdsTab.WdsEntry[pEntry->wdev_idx].WdsCounter.RxErrors++; + } +#endif /* STATS_COUNT_SUPPORT */ +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef STATS_COUNT_SUPPORT + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 0) && (pRxInfo->U2M)) + { + MAC_TABLE_ENTRY *pEntry = NULL; + + if (VALID_WCID(pRxBlk->wcid)) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry && IS_ENTRY_APCLI(pEntry)) + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].ApCliCounter.RxErrors++; + } +#endif /* STATS_COUNT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (!pRxInfo->Crc) + DBGPRINT(RT_DEBUG_TRACE, ("%s(): CheckRxError!\n", __FUNCTION__)); +#endif + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + continue; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef APCLI_SUPPORT + /* When root AP is Open WEP, it will cause a fake connection state if user keys in wrong password. */ + if(pHeader->FC.Wep == 1) + { + if(pRxInfo->Decrypted == 1) + ApCliRxOpenWEPCheck(pAd,pRxBlk,TRUE); + else + ApCliRxOpenWEPCheck(pAd,pRxBlk,FALSE); + } +#endif /* APCLI_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef RT_CFG80211_P2P_SUPPORT + //CFG_TOOD : NO GOOD + if (IS_PKT_OPMODE_STA(pRxBlk)) +#endif /* RT_CFG80211_P2P_SUPPORT */ + /* Check for all RxD errors */ + if (RTMPCheckRxError(pAd, pHeader, &rxblk, pRxInfo) != NDIS_STATUS_SUCCESS) + { + pAd->Counters8023.RxErrors++; + /* discard this frame */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + continue; + } + + } +#endif /* CONFIG_STA_SUPPORT */ + + + // TODO: shiang-usw, for P2P, we original has following code, need to check it and merge to correct place!!! + + switch (pHeader->FC.Type) + { + case FC_TYPE_DATA: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + } +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef HDR_TRANS_SUPPORT + rxblk.bHdrRxTrans = pRxInfo->ip_sum_err; /* RXINFO bit 31 */ + //printk("sn - rxblk.bHdrRxTrans = %d\n", rxblk.bHdrRxTrans); + if ( rxblk.bHdrRxTrans) + { + rxblk.bHdrVlanTaged = pRxInfo->tcp_sum_err; /* RXINFO bit 30 */ + rxblk.pTransData = (UCHAR *) pHeader + 36; /* 36 byte - RX WIFI Size ( 802.11 Header ) */ + rxblk.TransDataSize = pRxBlk->MPDUtotalByteCnt; + rxblk.DataSize += 36; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + STAHandleRxDataFrame_Hdr_Trns(pAd, &rxblk); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APHandleRxDataFrame_Hdr_Trns(pAd, &rxblk); + } +#endif /* CONFIG_AP_SUPPORT */ + } + else +#endif /* HDR_TRANS_SUPPORT */ + { +#ifdef RT_CFG80211_P2P_SUPPORT + if (IS_PKT_OPMODE_AP(pRxBlk)) + { + APHandleRxDataFrame(pAd, &rxblk); + break; + } +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + STAHandleRxDataFrame(pAd, &rxblk); + break; + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APHandleRxDataFrame(pAd, &rxblk); + break; + } +#endif /* CONFIG_AP_SUPPORT */ + } + break; + + case FC_TYPE_MGMT: + dev_rx_mgmt_frm(pAd, &rxblk); + break; + + case FC_TYPE_CNTL: + dev_rx_ctrl_frm(pAd, &rxblk); + break; + + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + } + +#ifdef UAPSD_SUPPORT +#ifdef CONFIG_AP_SUPPORT +#ifdef RT_CFG80211_P2P_SUPPORT + if (IS_PKT_OPMODE_AP(pRxBlk)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + { + /* dont remove the function or UAPSD will fail */ + UAPSD_MR_SP_RESUME(pAd); + UAPSD_SP_CloseInRVDone(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* UAPSD_SUPPORT */ + +#ifdef RTMP_PCI_SUPPORT + //if (pAd->int_cpu_analysis > 0) { + //DBGPRINT(RT_DEBUG_OFF, ("APRxDoneInterruptHandle:: RxProcessed=%d\n", RxProcessed)); + pAd->rx_packet_counter += RxProcessed; + + if (RxProcessed == 1) + pAd->rx_packet_1_counter++; + else if (RxProcessed == 2) + pAd->rx_packet_2_counter++; + else if (RxProcessed == 3) + pAd->rx_packet_3_counter++; + else if (RxProcessed == 4) + pAd->rx_packet_4_counter++; + else if (RxProcessed == 5) + pAd->rx_packet_5_counter++; + else if ((RxProcessed > 5) && (RxProcessed <= 10)) + pAd->rx_packet_6_10_counter++; + else if ((RxProcessed > 10) && (RxProcessed <= 15)) + pAd->rx_packet_11_15_counter++; + else if ((RxProcessed > 15) && (RxProcessed <= 20)) + pAd->rx_packet_16_20_counter++; + else if ((RxProcessed > 20) && (RxProcessed <= 25)) + pAd->rx_packet_21_25_counter++; + else if ((RxProcessed > 25) && (RxProcessed <= 31)) + pAd->rx_packet_26_31_counter++; + else if ((RxProcessed > 31) && (RxProcessed <= (MAX_RX_PROCESS_CNT - 1))) + pAd->rx_packet_32_max_counter++; + //} +#endif + + return bReschedule; +} + +#ifdef DROP_MASK_SUPPORT +VOID drop_mask_init_per_client( + PRTMP_ADAPTER ad, + PMAC_TABLE_ENTRY entry) +{ + BOOLEAN cancelled = FALSE; + + if (entry->dropmask_timer.Valid) + RTMPCancelTimer(&entry->dropmask_timer, &cancelled); + + RTMPInitTimer(ad, &entry->dropmask_timer, GET_TIMER_FUNCTION(drop_mask_timer_action), entry, FALSE); + + asic_set_drop_mask(ad, entry->Aid, FALSE); + +#ifdef NOISE_TEST_ADJUST + if ((ad->ApCfg.EntryClientCount >= 3) && IS_ENTRY_CLIENT(entry)) + entry->pMbss->WPAREKEY.ReKeyMethod |= MAX_REKEY; +#endif /* NOISE_TEST_ADJUST */ +} + +VOID drop_mask_release_per_client( + PRTMP_ADAPTER ad, + PMAC_TABLE_ENTRY entry) +{ + BOOLEAN cancelled = FALSE; + + RTMPCancelTimer(&entry->dropmask_timer, &cancelled); + RTMPReleaseTimer(&entry->dropmask_timer, &cancelled); +} + +VOID drop_mask_set_per_client( + PRTMP_ADAPTER ad, + PMAC_TABLE_ENTRY entry, + BOOLEAN enable) +{ + BOOLEAN cancelled = FALSE; + +#ifdef NOISE_TEST_ADJUST + if (ad->ApCfg.EntryClientCount < 3) + return; +#endif /* NOISE_TEST_ADJUST */ + + RTMPCancelTimer(&entry->dropmask_timer, &cancelled); + + asic_set_drop_mask(ad, entry->Aid, enable); + + if (enable) + RTMPSetTimer(&entry->dropmask_timer, 1000); +} + +VOID drop_mask_timer_action( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PMAC_TABLE_ENTRY entry = (MAC_TABLE_ENTRY *)FunctionContext; + PRTMP_ADAPTER ad = (PRTMP_ADAPTER)entry->pAd; + + /* Disable drop mask */ + asic_set_drop_mask(ad, entry->Aid, FALSE); +} + +#endif /* DROP_MASK_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_data_pci.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_data_pci.c new file mode 100644 index 000000000..a356bb867 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_data_pci.c @@ -0,0 +1,2117 @@ +/**************************************************************************** + * 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_data_pci.c + + Abstract: + + Note: + All functions in this file must be PCI-depended, or you should move + your functions to other files. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +#ifdef RT_SECURE_DMA +# ifdef NO_CONSISTENT_MEM_SUPPORT +# error NO_CONSISTENT_MEM_SUPPORT and RT_SECURE_DMA is not supported +# endif +# ifdef WLAN_SKB_RECYCLE +# error WLAN_SKB_RECYCLE and RT_SECURE_DMA is not supported +# endif +#else +//# error No RT_SECURE_DMA +#endif +#ifdef DBG +VOID dump_txd(RTMP_ADAPTER *pAd, TXD_STRUC *pTxD) +{ + DBGPRINT(RT_DEBUG_OFF, ("TxD:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr0=0x%x\n", pTxD->SDPtr0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDLen0=0x%x\n", pTxD->SDLen0)); + DBGPRINT(RT_DEBUG_OFF, ("\tLastSec0=0x%x\n", pTxD->LastSec0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr1=0x%x\n", pTxD->SDPtr1)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDLen1=0x%x\n", pTxD->SDLen1)); + DBGPRINT(RT_DEBUG_OFF, ("\tLastSec1=0x%x\n", pTxD->LastSec1)); + DBGPRINT(RT_DEBUG_OFF, ("\tDMADONE=0x%x\n", pTxD->DMADONE)); + DBGPRINT(RT_DEBUG_OFF, ("\tBurst=0x%x\n", pTxD->Burst)); +} + + +VOID dump_rxd(RTMP_ADAPTER *pAd, RXD_STRUC *pRxD) +{ + DBGPRINT(RT_DEBUG_OFF, ("RxD:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr0=0x%x\n", pRxD->SDP0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDLen0=0x%x\n", pRxD->SDL0)); + DBGPRINT(RT_DEBUG_OFF, ("\tLastSec0=0x%x\n", pRxD->LS0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr1=0x%x\n", pRxD->SDP1)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDLen1=0x%x\n", pRxD->SDL1)); + DBGPRINT(RT_DEBUG_OFF, ("\tLastSec1=0x%x\n", pRxD->LS1)); + DBGPRINT(RT_DEBUG_OFF, ("\tDDONE=0x%x\n", pRxD->DDONE)); +} + + +VOID dumpTxRing(RTMP_ADAPTER *pAd, INT ring_idx) +{ + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; + + int index; + + ASSERT(ring_idx < NUM_OF_TX_RING); + + pTxRing = &pAd->TxRing[ring_idx]; + for (index = 0; index < TX_RING_SIZE; index++) + { + pTxD = (TXD_STRUC *)pTxRing->Cell[index].AllocVa; + hex_dump("Dump TxDesc", (UCHAR *)pTxD, sizeof(TXD_STRUC)); + dump_txd(pAd, pTxD); + pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[index].AllocVa + sizeof(TXD_STRUC)); + hex_dump("Dump TxInfo", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC)); + dump_txinfo(pAd, pTxInfo); + } +} + + +VOID dumpRxRing(RTMP_ADAPTER *pAd, INT ring_idx) +{ + RTMP_RX_RING *pRxRing; + RXD_STRUC *pRxD; + int index; + int RxRingSize = (ring_idx == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + pRxRing = &pAd->RxRing[ring_idx]; + for (index = 0; index < RxRingSize; index++) + { + pRxD = (RXD_STRUC *)pRxRing->Cell[index].AllocVa; + hex_dump("Dump RxDesc", (UCHAR *)pRxD, sizeof(TXD_STRUC)); + dump_rxd(pAd, pRxD); + } +} +#endif /* DBG */ + +#ifdef DMA_BUSY_RESET +BOOLEAN MonitorTxRing(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + WPDMA_GLO_CFG_STRUC GloCfg; + + if (pAd->TxDMACheckTimes < 10) + { + /* Check if TX DMA busy */ + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + + if (GloCfg.field.TxDMABusy) + { + if (pAd->PDMAWatchDogDbg) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: check point 0: value = %x\n", __FUNCTION__, GloCfg.word)); + } + + pAd->TxDMACheckTimes++; // the counter will be clean by any of Tx INT + return FALSE; + } + else + { + pAd->TxDMACheckTimes = 0; + return FALSE; + } + } + else // reach the trigger threshold + { + pAd->TxDMACheckTimes = 0; + return TRUE; + } +} + + +BOOLEAN MonitorRxRing(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + WPDMA_GLO_CFG_STRUC GloCfg; + + if (pAd->RxDMACheckTimes < 10) + { + /* Check if RX DMA busy */ + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + + if (GloCfg.field.RxDMABusy) + { + if (pAd->PDMAWatchDogDbg) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: check point 0, Value = %x\n", __FUNCTION__, GloCfg.word)); + } + + pAd->RxDMACheckTimes++; // the counter will be clean by any of Rx INT + return FALSE; + } + else + { + pAd->RxDMACheckTimes = 0; + return FALSE; + } + } + else + { + pAd->RxDMACheckTimes = 0; + return TRUE; + } +} +#endif /* DMA_BUSY_RESET */ + +static VOID ral_write_txinfo( + IN RTMP_ADAPTER *pAd, + IN TXINFO_STRUC *pTxInfo, + IN BOOLEAN bWiv, + IN UCHAR QueueSel) +{ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXINFO_NMAC_PKT *nmac_info = (struct _TXINFO_NMAC_PKT *)pTxInfo; + +#ifdef HDR_TRANS_SUPPORT + if (pTxBlk && pTxBlk->NeedTrans) + nmac_info->pkt_80211 = 0; /* 802.3 MAC header */ + else +#endif /* HDR_TRANS_SUPPORT */ + nmac_info->pkt_80211 = 1; + nmac_info->info_type = 0; + nmac_info->d_port = 0; + nmac_info->cso = 0; + nmac_info->tso = 0; + nmac_info->wiv = (bWiv) ? 1: 0; + nmac_info->QSEL = (pAd->bGenOneHCCA == TRUE) ? FIFO_HCCA : QueueSel; + + } +#endif /* RLT_MAC */ + + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXINFO_OMAC *omac_info = (struct _TXINFO_OMAC *)pTxInfo; + + omac_info->WIV = (bWiv) ? 1: 0; + omac_info->QSEL = (pAd->bGenOneHCCA == TRUE) ? FIFO_HCCA : QueueSel; + + } +#endif /* RTMP_MAC */ +} + + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxD Pointer to transmit descriptor + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID ral_write_txd( + IN RTMP_ADAPTER *pAd, + IN TXD_STRUC *pTxD, + IN TXINFO_STRUC *pTxInfo, + IN BOOLEAN bWIV, + IN UCHAR QueueSEL) +{ + /* Always use Long preamble before verifiation short preamble functionality works well.*/ + /* Todo: remove the following line if short preamble functionality works*/ + + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + + ral_write_txinfo(pAd, pTxInfo, bWIV, QueueSEL); + + pTxD->DMADONE = 0; +} + +#ifdef RLT_MAC +#endif /* RLT_MAC */ + + +#ifdef CONFIG_STA_SUPPORT +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->PsPollFrame, sizeof (PSPOLL_FRAME)); + pAd->PsPollFrame.FC.Type = FC_TYPE_CNTL; + pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; + pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000; + COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress); +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* IRQL = DISPATCH_LEVEL */ +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->NullFrame, sizeof (HEADER_802_11)); + pAd->NullFrame.FC.Type = FC_TYPE_DATA; + pAd->NullFrame.FC.SubType = SUBTYPE_DATA_NULL; + pAd->NullFrame.FC.ToDs = 1; + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); +} + + +USHORT RtmpPCI_WriteSingleTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; + /*TXWI_STRUC *pTxWI;*/ +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; + UINT8 *temp; +#endif + UINT32 BufBasePaLow; + RTMP_TX_RING *pTxRing; + USHORT hwHeaderLen, inf_hdr_len; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + /* get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/ + /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen + TSO_SIZE; + inf_hdr_len = TXWISize + hwHeaderLen; + NdisMoveMemory(pDMAHeaderBufVA, + (UCHAR *)(pTxBlk->HeaderBuf + TXINFO_SIZE), + inf_hdr_len); + /*pTxWI = (TXWI_STRUC *)pDMAHeaderBufVA;*/ + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + /* build Tx Descriptor*/ +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); +#endif + //pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = inf_hdr_len; /* include padding*/ +#ifndef RT_SECURE_DMA + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); +#else + NdisMoveMemory(pAd->TxSecureDMA[pTxBlk->QueIdx].AllocVa + (TxIdx * 4096), pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + pTxD->SDPtr1 = pAd->TxSecureDMA[pTxBlk->QueIdx].AllocPa + (TxIdx * 4096); +#endif + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; + pTxD->Burst = 0; + + + if ((pAd->CommonCfg.bMcastTest == TRUE) && + (pTxBlk->TxFrameType == TX_MCAST_FRAME)) + ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_HCCA); + else + ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); + +//+++Add by shiang for debug +//---Add by shiang for debug + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXWISize), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + RetTxIdx = TxIdx; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); +#ifndef RT_SECURE_DMA + RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); +#else + RTMP_DCACHE_FLUSH(pTxD->SDPtr1, pTxBlk->SrcBufLen); +#endif + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); + + /* Update Tx index*/ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +USHORT RtmpPCI_WriteMultiTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber) +{ + BOOLEAN bIsLast; + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; + //TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + RTMP_TX_RING *pTxRing; + USHORT hwHdrLen; + UINT32 firstDMALen; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); + + + /* get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + if (frameNum == 0) + { + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/ + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-AMSDU_SUBHEAD_LEN, 4)+AMSDU_SUBHEAD_LEN;*/ + hwHdrLen = pTxBlk->MpduHeaderLen - AMSDU_SUBHEAD_LEN + pTxBlk->HdrPadLen + AMSDU_SUBHEAD_LEN; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-ARALINK_HEADER_LEN, 4)+ARALINK_HEADER_LEN;*/ + hwHdrLen = pTxBlk->MpduHeaderLen - ARALINK_HEADER_LEN + pTxBlk->HdrPadLen + ARALINK_HEADER_LEN; + + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXWISize + hwHdrLen; + } + else + { + firstDMALen = pTxBlk->MpduHeaderLen; + } + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf + TXINFO_SIZE, firstDMALen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + /* build Tx Descriptor*/ +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); +#endif + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding*/ +#ifndef RT_SECURE_DMA + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); +#else + NdisMoveMemory(pAd->TxSecureDMA[pTxBlk->QueIdx].AllocVa + (TxIdx * 4096), pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + pTxD->SDPtr1 = pAd->TxSecureDMA[pTxBlk->QueIdx].AllocPa + (TxIdx * 4096); +#endif + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; + pTxD->Burst = 0; + + if ((pAd->CommonCfg.bMcastTest == TRUE) && + (pTxBlk->TxFrameType == TX_MCAST_FRAME)) + ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_HCCA); + else + ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); + +#ifdef RT_BIG_ENDIAN + if (frameNum == 0) + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXWISize), DIR_WRITE, FALSE); + + if (frameNum != 0) + RTMPWIEndianChange(pAd, (PUCHAR)pDMAHeaderBufVA, TYPE_TXWI); + + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + RetTxIdx = TxIdx; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); + RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); + + /* Update Tx index*/ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +VOID RtmpPCI_FinalWriteTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx) +{ + TXWI_STRUC *pTxWI; + RTMP_TX_RING *pTxRing; + + /* get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + pTxWI = (TXWI_STRUC *) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + pTxWI->TXWI_N.MPDUtotalByteCnt = totalMPDUSize; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + pTxWI->TXWI_O.MPDUtotalByteCnt = totalMPDUSize; +#endif /* RTMP_MAC */ +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); +#endif /* RT_BIG_ENDIAN */ + +} + + +USHORT RtmpPCI_WriteFragTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber) +{ + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; + //TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + RTMP_TX_RING *pTxRing; + USHORT hwHeaderLen; + UINT32 firstDMALen; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + /* Get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + + /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/ + + /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXWISize + hwHeaderLen; + NdisMoveMemory(pDMAHeaderBufVA, (UCHAR *)(pTxBlk->HeaderBuf + TXINFO_SIZE), firstDMALen); + + /* Build Tx Descriptor*/ +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); +#endif + + if (fragNum == pTxBlk->TotalFragNum) + { + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + } + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding*/ +#ifndef RT_SECURE_DMA + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); +#else + NdisMoveMemory(pAd->TxSecureDMA[pTxBlk->QueIdx].AllocVa + (TxIdx * 4096), pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + pTxD->SDPtr1 = pAd->TxSecureDMA[pTxBlk->QueIdx].AllocPa + (TxIdx * 4096); +#endif + pTxD->SDLen1 = pTxBlk->SrcBufLen; + if (pTxD->SDLen1 > 0) + { + pTxD->LastSec0 = 0; + pTxD->LastSec1 = 1; + } + else + { + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + } + pTxD->Burst = 0; + ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, pDMAHeaderBufVA, TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXWISize), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + RetTxIdx = TxIdx; + pTxBlk->Priv += pTxBlk->SrcBufLen; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); + RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); + + /* Update Tx index*/ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +/* + Must be run in Interrupt context + This function handle PCI specific TxDesc and cpu index update and kick the packet out. + */ +int RtmpPCIMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN UCHAR *pSrcBufVA, + IN UINT SrcBufLen) +{ + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + UCHAR tx_hw_info[TXD_SIZE]; + TXD_STRUC *pDestTxD; +#endif + TXINFO_STRUC *pTxInfo; + ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; + INT pkt_len = SrcBufLen - TXINFO_SIZE; + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *)pAd->MgmtRing.Cell[SwIdx].AllocVa; +#endif + pTxInfo = (TXINFO_STRUC *)(((UCHAR *)pTxD) + sizeof(TXD_STRUC)); + + pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; + pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen1 = 0; +#ifndef RT_SECURE_DMA + pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, (pSrcBufVA + TXINFO_SIZE), pkt_len, 0, RTMP_PCI_DMA_TODEVICE); +#else + NdisMoveMemory(pAd->MgmtSecureDMA.AllocVa + (SwIdx * 4096), pSrcBufVA + TXINFO_SIZE, pkt_len); + pTxD->SDPtr0 = pAd->MgmtSecureDMA.AllocPa + (SwIdx * 4096); +#endif + pTxD->SDLen0 = pkt_len; + pTxD->Burst = 0; + + ral_write_txd(pAd, pTxD, pTxInfo, TRUE, FIFO_MGMT); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((UCHAR *)pTxD, TYPE_TXD); + WriteBackToDescriptor((UCHAR *)pDestTxD, (UCHAR *)pTxD, FALSE, TYPE_TXD); +#endif + +//+++Add by shiang for debug +//---Add by shiang for debug + + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pSrcBufVA, SrcBufLen); + RTMP_DCACHE_FLUSH(pAd->MgmtRing.Cell[SwIdx].AllocPa, TXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + return 0; +} + + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx) +{ + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; + UCHAR FREE = 0; + BOOLEAN bReschedule = FALSE; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef RALINK_ATE +#ifdef TXBF_SUPPORT + ULONG stTimeChk; + PATE_INFO pATEInfo = &(pAd->ate); +#endif /* TXBF_SUPPORT */ +#endif /* RALINK_ATE */ + + ASSERT(QueIdx < NUM_OF_TX_RING); + if (QueIdx >= NUM_OF_TX_RING) + return FALSE; + + pTxRing = &pAd->TxRing[QueIdx]; + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); +#ifdef RALINK_ATE +#ifdef TXBF_SUPPORT + if (pAd->ceBfCertificationFlg == TRUE) + { + pATEInfo->TxDoneCount = 0; + + /* ATE special mode: Every 500ms, insert one sounding packet into TX ring. + After the packet is sent out, revert the packet back to normal packet */ + + NdisGetSystemUpTime(&stTimeChk); // get system time + + //if TxDmaIdx overflow happens, reset sounding packet + if ((pTxRing->TxDmaIdx < pAd->txDmaIdx_backup) && + (pAd->timeout_flg == FALSE) && (pAd->ceBfCertificationFlg == TRUE)) + { + + if ( pTxRing->TxDmaIdx > 30) + { + pAd->timeout_flg = TRUE; + pATEInfo->TxLength = pAd->txLengthBackup;////2050; + pATEInfo->txSoundingMode =0; + } + } + + if ((((stTimeChk - pAd->sounding_periodic_count)*1000/OS_HZ) >= 500) && //500ms period + (pTxRing->TxDmaIdx >= (TX_RING_SIZE - 10))) + { + pAd->timeout_flg = FALSE; + NdisGetSystemUpTime(&pAd->sounding_periodic_count); //get and save system time + + pATEInfo->TxLength = 258; + pATEInfo->txSoundingMode = pAd->soundingMode; + + //if ( pAd->soundingPacketDone == 0) + { + pAd->soundingPacketDone = 1; + /* Abort Tx, Rx DMA. */ + RtmpSoundingDmaEnable(pAd, 0); + + if (pATEInfo->TxWI.TXWI_N.PHYMODE == MODE_VHT && pATEInfo->bTxBF == TRUE && pATEInfo->txSoundingMode != 0) + { + if (ATESetUpNDPAFrame(pAd, TX_RING_SIZE-1) != 0) + return NDIS_STATUS_FAILURE; + + if (ATESetUpNDPAFrame(pAd, 100) != 0) + return NDIS_STATUS_FAILURE; + } + else + { + if (ATESetUpFrame(pAd, TX_RING_SIZE-1) != 0) + return NDIS_STATUS_FAILURE; + + if (ATESetUpFrame(pAd, 100) != 0) + return NDIS_STATUS_FAILURE; + } + + /* Start Tx, Rx DMA. */ + RtmpSoundingDmaEnable(pAd, 1); + } + + pAd->txDmaIdx_backup = pTxRing->TxDmaIdx; + + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + //DBGPRINT(RT_DEBUG_OFF, ("****[7]TxDmaIdx =%d,TxCpuIdx =%d, Put Sounding Packet[%d]\n", pTxRing->TxDmaIdx, pTxRing->TxCpuIdx,TX_RING_SIZE-1)); + } + } +#endif +#endif + while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) + { + RTMP_DMACB *dma_cb = &pTxRing->Cell[pTxRing->TxSwFreeIdx]; + + pAd->tx_packet_counter++; +#ifdef RALINK_ATE +#ifdef RALINK_QA + if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE) && (pAd->ate.QID == QueIdx)) + { + HEADER_802_11 *pHeader80211; + + pAd->ate.TxDoneCount++; + pAd->RalinkCounters.KickTxCount++; + + /* always use QID_AC_BE and FIFO_EDCA */ + ASSERT(pAd->ate.QID == 0); + pAd->ate.TxAc0++; + + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) (dma_cb->AllocVa); +#else + pDestTxD = (PTXD_STRUC) (dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (PTXD_STRUC)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif +/* pTxD->DMADONE = 0; */ + + pHeader80211 = (PHEADER_802_11)((UCHAR *)(dma_cb->DmaBuf.AllocVa) + TXWISize); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); +#endif + pHeader80211->Sequence = ++pAd->ate.seq; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); +#endif + + if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) + { + pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(dma_cb->AllocPa, RXD_SIZE); + + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + + /* get TX_DTX_IDX again */ + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + goto kick_out; + } + else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount)) + { + DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); + + /* Tx status enters idle mode.*/ + pAd->ate.TxStatus = 0; + } + else if (!(pAd->ate.Mode & ATE_TXFRAME)) + { + /* not complete sending yet, but someone press the Stop TX botton */ + DBGPRINT(RT_DEBUG_INFO,("not complete sending yet, but someone pressed the Stop TX bottom\n")); + DBGPRINT(RT_DEBUG_INFO,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); + } + else + { + DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + NdisMoveMemory(pDestTxD, pTxD, TXD_SIZE); +#endif /* RT_BIG_ENDIAN */ + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(dma_cb->AllocPa, RXD_SIZE); + + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + continue; + } +#endif /* RALINK_QA */ +#endif /* RALINK_ATE */ + + /* + Note: + + Can not take off the NICUpdateFifoStaCounters(); Or the + FIFO overflow rate will be high, i.e. > 3% + (see the rate by "iwpriv ra0 show stainfo") + + Based on different platform, try to find the best value to + replace '4' here (overflow rate target is about 0%). + */ + if (++pAd->FifoUpdateRx >= FIFO_STAT_READ_PERIOD) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateRx = 0; + } + + /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *) (dma_cb->AllocVa); +#else + pDestTxD = (PTXD_STRUC) (dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (PTXD_STRUC)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif +/* pTxD->DMADONE = 0; */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_SP_PacketCheck(pAd, + dma_cb->pNdisPacket, + ((UCHAR *)dma_cb->DmaBuf.AllocVa) + TXWISize); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UAPSD_SP_PacketCheck(pAd, + dma_cb->pNdisPacket, + ((UCHAR *)dma_cb->DmaBuf.AllocVa) + TXWISize); + } +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef RALINK_ATE + /* Execution of this block is not allowed when ATE is running. */ + if (!(ATE_ON(pAd))) +#endif /* RALINK_ATE */ + { + pPacket = dma_cb->pNdisPacket; + if (pPacket) + { + dma_cb->pNdisPacket = NULL; + +#ifdef CONFIG_5VT_ENHANCE + if (RTMP_GET_PACKET_5VT(pPacket)) + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, RTMP_PCI_DMA_TODEVICE); + else +#endif /* CONFIG_5VT_ENHANCE */ + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + +#ifdef WLAN_SKB_RECYCLE + if (skb_queue_len(&pAd->rx0_recycle) < NUM_RX_DESC && + skb_recycle_check(RTPKT_TO_OSPKT(pPacket), RX_BUFFER_NORMSIZE)) + __skb_queue_head(&pAd->rx0_recycle, RTPKT_TO_OSPKT(pPacket)); + else +#endif /* WLAN_SKB_RECYCLE */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + pPacket = dma_cb->pNextNdisPacket; + if (pPacket) + { + dma_cb->pNextNdisPacket = NULL; +#ifdef CONFIG_5VT_ENHANCE + if (RTMP_GET_PACKET_5VT(pPacket)) + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, RTMP_PCI_DMA_TODEVICE); + else +#endif /* CONFIG_5VT_ENHANCE */ + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + +#ifdef WLAN_SKB_RECYCLE + if (skb_queue_len(&pAd->rx0_recycle) < NUM_RX_DESC && + skb_recycle_check(RTPKT_TO_OSPKT(pPacket), RX_BUFFER_NORMSIZE )) + __skb_queue_head(&pAd->rx0_recycle, RTPKT_TO_OSPKT(pPacket)); + else +#endif /* WLAN_SKB_RECYCLE */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + } + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(dma_cb->AllocPa, TXD_SIZE); + + pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + + /* get tx_tdx_idx again */ + //if (pTxRing->TxSwFreeIdx == pTxRing->TxDmaIdx) + // RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + + +#ifdef RALINK_ATE +#ifdef RALINK_QA +kick_out: +#endif /* RALINK_QA */ + + /* + ATE_TXCONT mode also need to send some normal frames, so let it in. + ATE_STOP must be changed not to be 0xff + to prevent it from running into this block. + */ + if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) + { + /* TxDoneCount++ has been done if QA is used.*/ + if (pAd->ate.bQATxStart == FALSE) + { + pAd->ate.TxDoneCount++; + } + if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) + { + /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */ + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[pTxRing->TxCpuIdx].AllocPa, RXD_SIZE); + + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (PTXD_STRUC)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + NdisMoveMemory(pDestTxD, pTxD, TXD_SIZE); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[pTxRing->TxCpuIdx].AllocPa, RXD_SIZE); + + /* kick Tx-Ring*/ + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); + + pAd->RalinkCounters.KickTxCount++; + } + } +#endif /* RALINK_ATE */ + } + + + return bReschedule; + +} + + +/* + ======================================================================== + + Routine Description: + Process TX Rings DMA Done interrupt, running in DPC level + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( + IN RTMP_ADAPTER *pAd, + IN RTMP_TX_DONE_MASK tx_mask) +{ + BOOLEAN bReschedule = FALSE; + + + /* Dequeue outgoing frames from TxSwQueue[] and process it*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + + return bReschedule; +} + + +/* + ======================================================================== + + Routine Description: + Process MGMT ring DMA done interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPHandleMgmtRingDmaDoneInterrupt(RTMP_ADAPTER *pAd) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; +/* int i;*/ + UCHAR FREE = 0; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, pMgmtRing->hw_didx_addr, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) + { + RTMP_DMACB *dma_cb = &pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx]; + + FREE++; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) (dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (PTXD_STRUC)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (dma_cb->AllocVa); +#endif + + //pTxD->DMADONE = 0; + pPacket = dma_cb->pNdisPacket; + if (pPacket == NULL) + { + INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); + continue; + } + +#define LMR_FRAME_GET() (GET_OS_PKT_DATAPTR(pPacket) + TXWISize) + +#ifdef UAPSD_SUPPORT +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, + pPacket, + LMR_FRAME_GET()); +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, + pPacket, LMR_FRAME_GET()); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + if (pPacket) + { + HEADER_802_11 *pHeader; + pHeader = (HEADER_802_11 *)(GET_OS_PKT_DATAPTR(pPacket)+ TXINFO_SIZE + pAd->chipCap.TXWISize); + CFG80211_SendMgmtFrameDone(pAd, pHeader->Sequence); + } +#endif /* RT_CFG80211_SUPPORT */ + + if (pPacket) + { + dma_cb->pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + pPacket = dma_cb->pNextNdisPacket; + if (pPacket) + { + dma_cb->pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(dma_cb->AllocPa, TXD_SIZE); + + INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + /* TxD no change. */ + //RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + //WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + NdisReleaseSpinLock(&pAd->MgmtRingLock); + +} + + +/* + ======================================================================== + + Routine Description: + Arguments: + Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTBTTInterrupt(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd->OpMode == OPMODE_AP) + { + ReSyncBeaconTime(pAd); + + RTMP_OS_TASKLET_SCHE(&pObj->tbtt_task); +#ifdef CUSTOMER_DCC_FEATURE + if(pAd->CommonCfg.channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt::Channel Switching...(%d/%d)\n", pAd->CommonCfg.channelSwitch.CHSWCount, pAd->CommonCfg.channelSwitch.CHSWPeriod)); + + pAd->CommonCfg.channelSwitch.CHSWCount++; + if(pAd->CommonCfg.channelSwitch.CHSWCount >= pAd->CommonCfg.channelSwitch.CHSWPeriod) + { + APStop(pAd); + APStartUp(pAd); + } + } +#endif + + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) + { + ChannelSwitchingCountDownProc(pAd); + } + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + } + } +} + + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter. Rewrite beacon content before next send-out. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandlePreTBTTInterrupt(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP +#ifdef RT_CFG80211_SUPPORT + && (pAd->ApCfg.MBSSID[0].wdev.Hostapd == Hostapd_CFG) +#endif /*RT_CFG80211_SUPPORT*/ + ) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_BEACON_TIM_UPDATE(pAd); +#else + APUpdateAllBeaconFrame(pAd); +#endif /* RT_CFG80211_SUPPORT */ + + if (pAd->CommonCfg.bMcastTest == TRUE) { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->pretbtt_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->pretbtt_task); +#endif /* WORKQUEUE_BH */ + } + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s()...\n", __FUNCTION__)); + } + } + +} + + +VOID RTMPHandleRxCoherentInterrupt(RTMP_ADAPTER *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); + GloCfg.field.EnTXWriteBackDDONE = 0; + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + RTMPEnableRxTx(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); +} + + +#ifdef CONFIG_AP_SUPPORT +VOID RTMPHandleMcuInterrupt(RTMP_ADAPTER *pAd) +{ + UINT32 McuIntSrc = 0; + RTMP_IO_READ32(pAd, 0x7024, &McuIntSrc); + + /* check mac 0x7024 */ +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->infType == RTMP_DEV_INF_PCIE && + (McuIntSrc & (1<<1)) && /*bit_1: carr_status interrupt */ + (pAd->CommonCfg.CarrierDetect.Enable == TRUE)) + { + RTMPHandleRadarInterrupt(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ + + /* clear MCU Int source register.*/ + RTMP_IO_WRITE32(pAd, 0x7024, 0); + +} +#endif /* CONFIG_AP_SUPPORT */ + + +PNDIS_PACKET GetPacketFromRxRing( + IN RTMP_ADAPTER *pAd, + OUT RX_BLK *pRxBlk, + OUT BOOLEAN *pbReschedule, + INOUT UINT32 *pRxPending, + BOOLEAN *bCmdRspPacket, + UCHAR RxRingNo) +{ + RXD_STRUC *pRxD; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD; + UCHAR rx_hw_info[RXD_SIZE]; + RXINFO_STRUC *pRxInfo; + RXINFO_STRUC RxInfo; +#endif + RTMP_RX_RING *pRxRing; + NDIS_SPIN_LOCK *pRxRingLock; + PNDIS_PACKET pRxPacket = NULL, pNewPacket; + VOID *AllocVa; + NDIS_PHYSICAL_ADDRESS AllocPa; + BOOLEAN bReschedule = FALSE; + RTMP_DMACB *pRxCell; + UINT8 RXWISize = pAd->chipCap.RXWISize; + UINT16 RxRingSize = (RxRingNo == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + pRxRing = &pAd->RxRing[RxRingNo]; + pRxRingLock = &pAd->RxRingLock[RxRingNo]; + RTMP_SEM_LOCK(pRxRingLock); + + if (*pRxPending == 0) + { + /* Get how may packets had been received*/ + RTMP_IO_READ32(pAd, pRxRing->hw_didx_addr, &pRxRing->RxDmaIdx); + + if (pRxRing->RxSwReadIdx == pRxRing->RxDmaIdx) + { + bReschedule = FALSE; + goto done; + } + + /* get rx pending count*/ + if (pRxRing->RxDmaIdx > pRxRing->RxSwReadIdx) + *pRxPending = pRxRing->RxDmaIdx - pRxRing->RxSwReadIdx; + else + *pRxPending = pRxRing->RxDmaIdx + RxRingSize - pRxRing->RxSwReadIdx; + } + + pRxCell = &pRxRing->Cell[pRxRing->RxSwReadIdx]; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *)pRxCell->AllocVa; + /* RxD = *pDestRxD; */ + NdisMoveMemory(&rx_hw_info[0], pDestRxD, RXD_SIZE); + pRxD = (RXD_STRUC *)&rx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor*/ + pRxD = (PRXD_STRUC) pRxCell->AllocVa; +#endif + + if (pRxD->DDONE == 0) + { + *pRxPending = 0; + DBGPRINT(RT_DEBUG_INFO, ("DDONE=0!\n")); + /* DMAIndx had done but DDONE bit not ready*/ + bReschedule = TRUE; + goto done; + } + + /* return rx descriptor*/ + NdisMoveMemory(&pRxBlk->hw_rx_info[0], pRxD, RXD_SIZE); + +#ifdef WLAN_SKB_RECYCLE + { + struct sk_buff *skb = __skb_dequeue_tail(&pAd->rx0_recycle); + + if (unlikely(skb==NULL)) + pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); + else + { + pNewPacket = OSPKT_TO_RTPKT(skb); + AllocVa = GET_OS_PKT_DATAPTR(pNewPacket); + AllocPa = PCI_MAP_SINGLE_DEV(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, AllocVa, RX_BUFFER_AGGRESIZE, -1, RTMP_PCI_DMA_FROMDEVICE); + } + } +#else + pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); +#endif /* WLAN_SKB_RECYCLE */ + + if (pNewPacket) + { + /* unmap the rx buffer*/ + PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, + pRxCell->DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize); + + pRxPacket = pRxCell->pNdisPacket; +#ifdef RT_SECURE_DMA + /* Copy the header from secure buffer to packet */ + pRxBlk->pRxInfo = (RXINFO_STRUC *)GET_OS_PKT_DATAPTR(pRxPacket); + NdisMoveMemory(GET_OS_PKT_DATAPTR(pRxPacket), + pAd->RxSecureDMA[RxRingNo].AllocVa + (pRxRing->RxSwReadIdx * 4096), + RXINFO_SIZE + sizeof(struct _RXWI_NMAC)); +#endif +#ifdef RLT_MAC + /* get rx descriptor and data buffer */ + if (pAd->chipCap.hif_type == HIF_RLT) + { + struct _RXWI_NMAC *rxwi_n; + + pRxBlk->pRxFceInfo = (RXFCE_INFO *)&pRxBlk->hw_rx_info[RXINFO_OFFSET]; + pRxBlk->pRxInfo = (RXINFO_STRUC *)GET_OS_PKT_DATAPTR(pRxPacket); +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&RxInfo, pRxBlk->pRxInfo, RXINFO_SIZE); + pRxInfo = &RxInfo; + (*(UINT32*)pRxInfo) = le2cpu32(*(UINT32*)pRxInfo); + NdisMoveMemory(pRxBlk->pRxInfo, pRxInfo, RXINFO_SIZE); +#endif /* RT_BIG_ENDIAN */ + + SET_OS_PKT_DATAPTR(pRxPacket, GET_OS_PKT_DATAPTR(pRxPacket) + RXINFO_SIZE); + SET_OS_PKT_LEN(pRxPacket, GET_OS_PKT_LEN(pRxPacket) - RXINFO_SIZE); + rxwi_n = (struct _RXWI_NMAC *)(GET_OS_PKT_DATAPTR(pRxPacket)); + pRxBlk->pRxWI = (RXWI_STRUC *)(GET_OS_PKT_DATAPTR(pRxPacket)); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd , (PUCHAR)rxwi_n, TYPE_RXWI); +#endif + pRxBlk->MPDUtotalByteCnt = rxwi_n->MPDUtotalByteCnt; + pRxBlk->wcid = rxwi_n->wcid; + pRxBlk->key_idx = rxwi_n->key_idx; + pRxBlk->bss_idx = rxwi_n->bss_idx; + pRxBlk->TID = rxwi_n->tid; + pRxBlk->DataSize = rxwi_n->MPDUtotalByteCnt; + + pRxBlk->rx_rate.field.MODE = rxwi_n->phy_mode; + pRxBlk->rx_rate.field.MCS = rxwi_n->mcs; + pRxBlk->rx_rate.field.ldpc = rxwi_n->ldpc; + pRxBlk->rx_rate.field.BW = rxwi_n->bw; + pRxBlk->rx_rate.field.STBC = rxwi_n->stbc; + pRxBlk->rx_rate.field.ShortGI = rxwi_n->sgi; + pRxBlk->rssi[0] = rxwi_n->rssi[0]; + pRxBlk->rssi[1] = rxwi_n->rssi[1]; + pRxBlk->rssi[2] = rxwi_n->rssi[2]; + pRxBlk->snr[0] = rxwi_n->bbp_rxinfo[0]; + pRxBlk->snr[1] = rxwi_n->bbp_rxinfo[1]; + pRxBlk->snr[2] = rxwi_n->bbp_rxinfo[2]; + pRxBlk->freq_offset = rxwi_n->bbp_rxinfo[4]; + pRxBlk->ldpc_ex_sym = rxwi_n->ldpc_ex_sym; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + struct _RXWI_OMAC *rxwi_o = (struct _RXWI_OMAC *)(GET_OS_PKT_DATAPTR(pRxPacket)); + + pRxBlk->pRxInfo = (RXINFO_STRUC *)(&pRxBlk->hw_rx_info[RXINFO_OFFSET]); + pRxBlk->pRxWI = (RXWI_STRUC *)rxwi_o; + + pRxBlk->MPDUtotalByteCnt = rxwi_o->MPDUtotalByteCnt; + pRxBlk->wcid = rxwi_o->wcid; + pRxBlk->key_idx = rxwi_o->key_idx; + pRxBlk->bss_idx = rxwi_o->bss_idx; + pRxBlk->TID = rxwi_o->tid; + pRxBlk->DataSize = rxwi_o->MPDUtotalByteCnt; + + pRxBlk->rx_rate.field.MODE = rxwi_o->phy_mode; + pRxBlk->rx_rate.field.MCS = rxwi_o->mcs; + pRxBlk->rx_rate.field.ldpc = 0; + pRxBlk->rx_rate.field.BW = rxwi_o->bw; + pRxBlk->rx_rate.field.STBC = rxwi_o->stbc; + pRxBlk->rx_rate.field.ShortGI = rxwi_o->sgi; + pRxBlk->rssi[0] = rxwi_o->RSSI0; + pRxBlk->rssi[1] = rxwi_o->RSSI1; + pRxBlk->rssi[2] = rxwi_o->RSSI2; + pRxBlk->snr[0] = rxwi_o->SNR0; + pRxBlk->snr[1] = rxwi_o->SNR1; + pRxBlk->snr[2] = rxwi_o->SNR2; + pRxBlk->freq_offset = rxwi_o->FOFFSET; + } +#endif /* RTMP_MAC */ + +#ifdef RT_SECURE_DMA + /* Copy rest of packet data - Data ptr has been shifted by 4 -> rxinfo size. Length needs 4 added, or data missing */ + NdisMoveMemory(GET_OS_PKT_DATAPTR(pRxPacket), + pAd->RxSecureDMA[RxRingNo].AllocVa + (pRxRing->RxSwReadIdx * 4096) + RXINFO_SIZE, + sizeof(struct _RXWI_NMAC) + pRxBlk->DataSize + 4); +#endif + pRxBlk->pRxPacket = pRxPacket; + pRxBlk->pData = (UCHAR *)GET_OS_PKT_DATAPTR(pRxPacket); + pRxBlk->pHeader = (HEADER_802_11 *)(pRxBlk->pData + RXWISize); + pRxBlk->Flags = 0; + + pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; + pRxCell->pNdisPacket = (PNDIS_PACKET) pNewPacket; + pRxCell->DmaBuf.AllocVa = AllocVa; + pRxCell->DmaBuf.AllocPa = AllocPa; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize); + + /* update SDP0 to new buffer of rx packet */ +#ifndef RT_SECURE_DMA + pRxD->SDP0 = AllocPa; +#else + pRxD->SDP0 = pAd->RxSecureDMA[RxRingNo].AllocPa + (pRxRing->RxSwReadIdx * 4096); +#endif + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; + } + else + { + pRxPacket = NULL; + bReschedule = TRUE; + } + + *pRxPending = *pRxPending - 1; + +#ifndef CACHE_LINE_32B + pRxD->DDONE = 0; + + /* update rx descriptor and kick rx */ +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + + INC_RING_INDEX(pRxRing->RxSwReadIdx, RxRingSize); + + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RxRingSize-1) : (pRxRing->RxSwReadIdx-1); + + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + +#else /* CACHE_LINE_32B */ + + /* + Because our RXD_SIZE is 16B, but if the cache line size is 32B, we + will suffer a problem as below: + + 1. We flush RXD 0, start address of RXD 0 is 32B-align. + Nothing occurs. + 2. We flush RXD 1, start address of RXD 1 is 16B-align. + Because cache line size is 32B, cache must flush 32B, cannot flush + 16B only, so RXD0 and RXD1 will be flushed. + But when traffic is busy, maybe RXD0 is updated by MAC, i.e. + DDONE bit is 1, so when the cache flushs RXD0, the DDONE bit will + be cleared to 0. + 3. Then when we handle RXD0 in the future, we will find the DDONE bit + is 0 and we will wait for MAC to set it to 1 forever. + */ + if (pRxRing->RxSwReadIdx & 0x01) + { + RTMP_DMACB *pRxCellLast; +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxDLast; +#endif + /* 16B-align */ + + /* update last BD 32B-align, DMA Done bit = 0 */ + pRxCell->LastBDInfo.DDONE = 0; +#ifdef RT_BIG_ENDIAN + pRxCellLast = &pRxRing->Cell[pRxRing->RxSwReadIdx - 1]; + pDestRxDLast = (PRXD_STRUC) pRxCellLast->AllocVa; + RTMPDescriptorEndianChange((PUCHAR)&pRxCell->LastBDInfo, TYPE_RXD); + WriteBackToDescriptor((UCHAR *)pDestRxDLast, (UCHAR *)&pRxCell->LastBDInfo, FALSE, TYPE_RXD); +#endif + + /* update current BD 16B-align, DMA Done bit = 0 */ + pRxD->DDONE = 0; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + + /* flush cache from last BD */ + RTMP_DCACHE_FLUSH(pRxCellLast->AllocPa, 32); /* use RXD_SIZE should be OK */ + + /* update SW read and CPU index */ + INC_RING_INDEX(pRxRing->RxSwReadIdx, RxRingSize); + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RxRingSize-1) : (pRxRing->RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + } + else + { + /* 32B-align */ + /* do not set DDONE bit and backup it */ + if (pRxRing->RxSwReadIdx >= (RxRingSize-1)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("Please change RX_RING_SIZE to mutiple of 2!\n")); + + /* flush cache from current BD */ + RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); + + /* update SW read and CPU index */ + INC_RING_INDEX(pRxRing->RxSwReadIdx, RxRingSize); + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RxRingSize-1) : (pRxRing->RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + } + else + { + /* backup current BD */ + pRxCell = &pRxRing->Cell[pRxRing->RxSwReadIdx + 1]; + pRxCell->LastBDInfo = *pRxD; + + /* update CPU index */ + INC_RING_INDEX(pRxRing->RxSwReadIdx, RxRingSize); + } + } +#endif /* CACHE_LINE_32B */ + +done: + RTMP_SEM_UNLOCK(pRxRingLock); + *pbReschedule = bReschedule; + return pRxPacket; +} + + +NDIS_STATUS MlmeHardTransmitTxRing(RTMP_ADAPTER *pAd, UCHAR QueIdx, PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR hw_hdr_info[TXD_SIZE]; +#endif + PHEADER_802_11 pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + ULONG SrcBufPA; + UCHAR MlmeRate, wcid, tx_rate; + UINT32 SwIdx; + TXWI_STRUC *pFirstTxWI; + ULONG FreeNum; + MAC_TABLE_ENTRY *pMacEntry = NULL; + UINT8 TXWISize = pAd->chipCap.TXWISize; + HTTRANSMIT_SETTING *transmit; +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NDIS_STATUS_FAILURE; + + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + if (FreeNum == 0) + return NDIS_STATUS_FAILURE; + + SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; + NdisMoveMemory(&hw_hdr_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&hw_hdr_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; +#endif + pTxInfo = (TXINFO_STRUC *)((UCHAR *)pTxD + sizeof(TXD_STRUC)); + + if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) + { + DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); + return NDIS_STATUS_FAILURE; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* outgoing frame always wakeup PHY to prevent frame lost*/ + /* if (pAd->StaCfg.Psm == PWR_SAVE)*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } +#endif /* CONFIG_STA_SUPPORT */ + + pFirstTxWI =(TXWI_STRUC *)(pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (HEADER_802_11 *)(pSrcBufVA + TXINFO_SIZE + TXWISize + TSO_SIZE); + if (pHeader_802_11->Addr1[0] & 0x01) + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + else + MlmeRate = pAd->CommonCfg.MlmeRate; + + if ((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + + /* Verify Mlme rate for a/g bands.*/ + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band*/ + MlmeRate = RATE_6; + + /* + Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) + Snice it's been set to 0 while on MgtMacHeaderInit + By the way this will cause frame to be send on PWR_SAVE failed. + */ + + /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ +#ifdef CONFIG_STA_SUPPORT + /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD*/ + if (pHeader_802_11->FC.Type != FC_TYPE_DATA) + { + if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || + !(pAd->StaCfg.UapsdInfo.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + else + pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; + } +#endif /* CONFIG_STA_SUPPORT */ + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == FC_TYPE_CNTL) /* must be PS-POLL */ + { + bAckRequired = FALSE; +#ifdef VHT_TXBF_SUPPORT + if (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA) + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE)); +#endif /* VHT_TXBF_SUPPORT*/ + } + else /* FC_TYPE_MGMT or FC_TYPE_DATA(must be NULL frame)*/ + { + if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) + { + bInsertTimestamp = TRUE; +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + { + /* Find which MBSSID to be send this probeRsp */ + UINT32 apidx = get_apidx_by_addr(pAd, pHeader_802_11->Addr2); + + if (!(apidx >= pAd->ApCfg.BssidNum) && + (pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && + (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_CCK) && + (pAd->CommonCfg.MlmeTransmit.field.MCS == RATE_1)*/) + { + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; + } + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + } + } + + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence > 0xfff) + pAd->Sequence = 0; + + /* Before radar detection done, mgmt frame can not be sent but probe req*/ + /* Because we need to use probe req to trigger driver to send probe req in passive scan*/ + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE)) + { + DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); + return (NDIS_STATUS_FAILURE); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#endif + + /* + Fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET + should always has only one ohysical buffer, and the whole frame size equals + to the first scatter buffer size + */ + + + /* + Initialize TX Descriptor + For inter-frame gap, the number is for this frame and next frame + For MLME rate, we will fix as 2Mb to match other vendor's implement + */ +/* pAd->CommonCfg.MlmeTransmit.field.MODE = 1;*/ + +/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not */ + /* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.*/ + if (pMacEntry == NULL) + { + wcid = RESERVED_WCID; + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + } + else + { + wcid = pMacEntry->Aid; + tx_rate = (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS; + transmit = &pMacEntry->MaxHTPhyMode; + } + + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, wcid, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE), PID_MGMT, 0, + tx_rate, IFS_BACKOFF, transmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT +#ifdef RTMP_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && + (pAd->chipCap.hif_type == HIF_RTMP) && (pMacEntry == NULL)) + pFirstTxWI->TXWI_O.TxPwrAdj = TxPwrAdj; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && + (pAd->chipCap.hif_type == HIF_RLT) && (pMacEntry == NULL)) + pFirstTxWI->TXWI_N.TxPwrAdj = TxPwrAdj; +#endif /* RLT_MAC */ +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; + pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif +#ifndef RT_SECURE_DMA + SrcBufPA = PCI_MAP_SINGLE(pAd, (pSrcBufVA + TXINFO_SIZE), (SrcBufLen - TXINFO_SIZE), 0, RTMP_PCI_DMA_TODEVICE); +#else + NdisMoveMemory(pAd->TxSecureDMA[QueIdx].AllocVa + (SwIdx * 4096), pSrcBufVA + TXINFO_SIZE, SrcBufLen); + SrcBufPA = pAd->TxSecureDMA[QueIdx].AllocPa + (SwIdx * 4096); +#endif +#ifdef CUSTOMER_DCC_FEATURE + if(!(ApScanRunning(pAd))) + { + UINT32 Index, Length; + HTTRANSMIT_SETTING HTSetting; + MULTISSID_STRUCT *pMbss = NULL; + + NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); + HTSetting.field.MODE = transmit->field.MODE; + HTSetting.field.BW = transmit->field.BW; + HTSetting.field.ShortGI = transmit->field.ShortGI; + HTSetting.field.MCS = transmit->field.MCS; + Length = SrcBufLen - TXWISize; + if (pMacEntry != NULL && (pMacEntry->apidx < pAd->ApCfg.BssidNum)) + pMbss = &pAd->ApCfg.MBSSID[pMacEntry->apidx]; + else + { + + UCHAR apidx; + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev == NULL) || ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev)))) + { + /* the interface is down */ + continue; + } + if(RTMPEqualMemory(pAd->ApCfg.MBSSID[apidx].wdev.bssid, pHeader_802_11->Addr2,MAC_ADDR_LEN)) + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + } + } + } + GetMultShiftFactorIndex(HTSetting, &Index); + RTMPCalculateAPTxRxActivityTime(pAd, Index, Length, pMbss, pMacEntry); + } +#endif + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 1; + pTxD->SDLen0 = (SrcBufLen - TXINFO_SIZE); + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = SrcBufPA; + //pTxD->DMADONE = 0; + ral_write_txd(pAd, pTxD, pTxInfo, TRUE, FIFO_EDCA); + +#ifdef VHT_TXBF_SUPPORT +#ifdef DBG + if (pHeader_802_11->FC.Type == FC_TYPE_CNTL && pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Send VhtNDPA to peer(wcid=%d, pMacEntry=%p) with dataRate(PhyMode:%s, BW:%sHz, %dSS, MCS%d)\n", + __FUNCTION__, wcid, pMacEntry, get_phymode_str(transmit->field.MODE), + get_bw_str(transmit->field.BW), + (transmit->field.MCS>>4) + 1, (transmit->field.MCS & 0xf))); + + hex_dump("VHT NDPA frame raw data", pSrcBufVA, SrcBufLen); + dump_txwi(pAd, pFirstTxWI); + + DBGPRINT(RT_DEBUG_OFF, ("%s():pTxD->SDPtr0=0x%x, SrcBufPtr=0x%p, TxRing=%d, SwIdx=%d\n", + __FUNCTION__, pTxD->SDPtr0, + (UCHAR *)(pSrcBufVA + TXINFO_SIZE), QueIdx, SwIdx)); + + hex_dump("MgmtTxDInfo", pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa, TXD_SIZE); + dump_txd(pAd, (TXD_STRUC *)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa); + dump_txinfo(pAd, (TXINFO_STRUC *)(pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa + sizeof(TXD_STRUC))); + hex_dump("MgmtPktInfo", (pSrcBufVA + TXINFO_SIZE), pTxD->SDLen0); + } +#endif +#endif /* VHT_TXBF_SUPPORT */ + +//+++Add by shiang for debug +//---Add by shiang for debug + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen); + RTMP_DCACHE_FLUSH(pAd->TxRing[QueIdx].Cell[SwIdx].AllocPa, TXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); + + RTMP_IO_WRITE32(pAd, pAd->TxRing[QueIdx].hw_cidx_addr, pAd->TxRing[QueIdx].TxCpuIdx); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef CONFIG_ANDES_SUPPORT +BOOLEAN RxRing1DoneInterruptHandle(RTMP_ADAPTER *pAd) +{ + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + RXINFO_STRUC *pRxInfo = NULL; + PNDIS_PACKET pRxPacket = NULL; + RX_BLK rxblk, *pRxBlk = NULL; + RXFCE_INFO *pFceInfo; + BOOLEAN bCmdRspPacket = FALSE; + + RxProcessed = RxPending = 0; + + /* process whole rx ring */ + while (1) + { + + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) + { + break; + } + +#ifdef RTMP_MAC_PCI + if (RxProcessed++ > 32) + { + bReschedule = TRUE; + break; + } +#endif /* RTMP_MAC_PCI */ + + /* + 1. allocate a new data packet into rx ring to replace received packet + then processing the received packet + 2. the callee must take charge of release of packet + 3. As far as driver is concerned, the rx packet must + a. be indicated to upper layer or + b. be released if it is discarded + */ + + pRxBlk = &rxblk; + + pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending, &bCmdRspPacket, 1); + if ((pRxPacket == NULL)) + break; + + /* get rx descriptor and data buffer */ + pFceInfo = rxblk.pRxFceInfo; + pRxInfo = rxblk.pRxInfo; + + if (pFceInfo->info_type == CMD_PACKET) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: Receive command packet.\n", __FUNCTION__)); + pci_rx_cmd_msg_complete(pAd, pFceInfo, (PUCHAR) pRxInfo); + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } else { + DBGPRINT(RT_DEBUG_ERROR,("%s: Receive non-command packet.\n", __FUNCTION__)); + } + + } + return bReschedule; +} + + +VOID RTMPHandleTxRing8DmaDoneInterrupt(RTMP_ADAPTER *pAd) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + UCHAR hw_hdr_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; +/* int i;*/ + UCHAR FREE = 0; + RTMP_CTRL_RING *pCtrlRing = &pAd->CtrlRing; + + NdisAcquireSpinLock(&pAd->CtrlRingLock); + + RTMP_IO_READ32(pAd, pCtrlRing->hw_didx_addr, &pCtrlRing->TxDmaIdx); + while (pCtrlRing->TxSwFreeIdx!= pCtrlRing->TxDmaIdx) + { + RTMP_DMACB *dma_cb = &pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx]; + + FREE++; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) (dma_cb->AllocVa); + NdisMoveMemory(&hw_hdr_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&hw_hdr_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (dma_cb->AllocVa); +#endif + + + pPacket = dma_cb->pNdisPacket; + if (pPacket == NULL) + { + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + continue; + } + + if (pPacket) + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + + dma_cb->pNdisPacket = NULL; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(dma_cb->AllocPa, TXD_SIZE); + + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + pci_kick_out_cmd_msg_complete(pPacket); + } + NdisReleaseSpinLock(&pAd->CtrlRingLock); +} + +#endif /* CONFIG_ANDES_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_dfs.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_dfs.c new file mode 100644 index 000000000..0420dbc80 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_dfs.c @@ -0,0 +1,3289 @@ +/* + *************************************************************************** + * 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_dfs.c + + Abstract: + Support DFS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +#ifdef DFS_SUPPORT +#ifdef CONFIG_AP_SUPPORT + +#ifdef DFS_ATP_SUPPORT +extern INT Set_AP_SSID_Proc(IN PRTMP_ADAPTER, IN PSTRING); +#endif /* DFS_ATP_SUPPORT */ + +NewDFSValidRadar NewDFSValidTable[] = +{ + /* FCC-1 && (Japan W53 Radar 1 / W56 Radar 2)*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP | NEW_DFS_JAP_W53), + 7, + 10, 1000, + 0, + 4, + 0, 0, + 28570 - 70, + 150 + }, + /* FCC-2*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP), + 7, + 13, 1000, + 0, + 1, + 3000, 4600 - 20, + 0, + 25 + }, + /* FCC-3 & FCC-4*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP), + 7, + /*120, 200, FCC-3 */ + /*220, 400, FCC-4*/ + 100, 1500, + 0, + 1, + 4000, 10000 - 40, + 0, + 60 + }, + /* FCC-6*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP), + 7, + 12, 1000, + 0, + 1, + 0, 0, + 6660-10, + 35 + }, + /* Japan W53 Radar 2*/ + { + NEW_DFS_JAP_W53, + 7, + 40, 1000, + 0, + 1, + 0, 0, + 76923 - 30, + 180 + }, + /* Japan W56 Radar 1*/ + { + NEW_DFS_JAP, + 7, + 5, 500, + 0, + 2, + 0, 0, + 27777 - 30, + 70 + }, + /* Japan W56 Radar 3*/ + { + NEW_DFS_JAP, + 7, + 30, 1000, + 0, + 1, + 0, 0, + 80000 - 50, + 200 + }, + +/* CE Staggered radar*/ + + { + /* EN-1*/ + /* width 0.8 - 5 us*/ + /* PRF 200 - 1000 Hz*/ + /* PRI 5000 - 1000 us (T: 20000 - 100000)*/ + /* */ + NEW_DFS_EU, + 0xf, + 10, 1000, + 0, + 1, + 20000-15, 100000-70, + 0, + 120 + }, + /* EN-2*/ + /* width 0.8 - 15 us*/ + /* PRF 200 - 1600 Hz*/ + /* PRI 5000 - 625 us (T: 12500 - 100000)*/ + { + NEW_DFS_EU, + 0xf, + 10, 2000, + 0, + 1, + 12500 - 10, 100000 - 70, + 0, + 120 + }, + + /* EN-3*/ + /* width 0.8 - 15 us*/ + /* PRF 2300 - 4000 Hz*/ + /* PRI 434 - 250 us (T: 5000 - 8695)*/ + { + NEW_DFS_EU, + 0xf, + 21, 2000, + 0, + 1, + 5000 - 4, 8695 - 7, + 0, + 50 + }, + /* EN-4*/ + /* width 20 - 30 us*/ + /* PRF 2000 - 4000 Hz*/ + /* PRI 500 - 250 us (T: 5000 - 10000)*/ + /* Note : with Chirp Modulation +- 2,5Mhz*/ + { + NEW_DFS_EU, + 0xf, + 380, 3000, + 0, + 4, + 5000 - 4, 10000 - 8, + 0, + 60 + }, + /* EN-5*/ + /* width 0.8 - 2 us*/ + /* PRF 300 - 400 Hz*/ + /* PRI 3333 - 2500 us (T: 50000 - 66666)*/ + /* Staggered PRF, 20 - 50 pps*/ + { + NEW_DFS_EU, + 0xf, + 10, 800, + 0, + 1, + 50000 - 35, 66666 + 50, + 0, + 30 + }, + /* EN-6*/ + /* width 0.8 - 2 us*/ + /* PRF 400 - 1200 Hz*/ + /* PRI 2500 - 833 us (T: 16666 - 50000)*/ + /* Staggered PRF, 80 - 400 pps*/ + { + NEW_DFS_EU, + 0xf, + 10, 800, + 0, + 1, + 16666 - 13, 50000 + 35, + 0, + 30 + }, + + { + NEW_DFS_END, + 0, + 0, 0, + 0, + 0, + 0, 0, + 0, + 0, + }, +}; + +static NewDFSTable NewDFSTable1[] = +{ + { + /* ch, mode(0~7), M(~511), el, eh(~4095), wl, wh(~4095), err_w, tl, th, err_t, bl, bh, ee, pj*/ + NEW_DFS_FCC, + { + {0, 0, 10, 8, 16, 6, 2000, 5, 2900, 29000, 5, 0, 0, 0x1000000, 0}, + {1, 0, 70, 42, 126, 20, 5000, 5, 2900, 29000, 10, 0, 0, 0x1000000, 0}, + {2, 0, 100, 42, 160, 20, 5000, 25, 2900, 10100, 20, 0, 0, 0x1000000, 0}, + {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999, 0x10000000, 0}, + } + }, + + { + NEW_DFS_EU, + { + {0, 0, 10, 10, 18, 4, 4095, 5, 7800, 101000, 5, 0, 0, 0x1000000, 0}, + {1, 0, 70, 42, 90, 20, 4095, 3, 4900, 101000, 10, 0, 0, 0x1000000, 0}, + {2, 0, 100, 42, 160, 20, 4095, 5, 4900, 101000, 20, 0, 0, 0x1000000, 0}, + {3, 3, 200, 20, 150, 200, 4095, 100, 4900, 11000, 200, 0, 0, 0x1000000, 0}, + {4, 8, 0, 8, 17, 7, 70, 2, 32500, 200500, 10, 0, 0, 0x1000000, 0}, + /*{5, 1, 0, 12, 16, 8, 700, 5, 33000, 135000, 100, 0, 0, 0x1000000, 0},*/ + } + }, + + { + NEW_DFS_JAP, + { + {0, 0, 10, 8, 16, 4, 2000, 5, 2900, 85000, 5, 0, 0, 0x1000000, 0}, + {1, 0, 70, 48, 126, 20, 5000, 5, 2900, 85000, 10, 0, 0, 0x1000000, 0}, + {2, 0, 100, 48, 160, 20, 5000, 25, 2900, 85000, 20, 0, 0, 0x1000000, 0}, + {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999, 0x10000000, 0}, + } + }, + + { + NEW_DFS_JAP_W53, + { + {0, 0, 10, 8, 16, 8, 2000, 5, 28000, 85000, 10, 0x1000000, 0}, + {1, 0, 32, 24, 64, 20, 2000, 5, 28000, 85000, 10, 0x1000000, 0}, + {2, 0, 100, 42, 160, 20, 2000, 25, 28000, 85000, 10, 0x1000000, 0}, + /*{3, 2, 200, 20, 150, 300, 2000, 50, 15000, 45000, 200},*/ + } + }, +}; + +/* 7610/7662 DFS table */ +static NewDFSTable NewDFSTable2_BW20[] = { + { + NEW_DFS_FCC, + { + {0, 0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0, 2147483647, 0xfe808, 0x13dc}, + {1, 0, 8, 2, 7, 106, 140, 5,27600, 27900, 5, 0, 2147483647, 0xfe808, 0x19dd}, + {2, 0,40, 4,44, 96, 480,150, 2900, 80100, 40, 0, 2147483647, 0xfe808, 0x12cc}, + {3, 2,60,15,48, 640,2080, 32,19600, 40200, 32, 0, 60000000, 0x57BCF00, 0x1289}, + } + }, + + { + NEW_DFS_EU, + { + {0, 0, 8, 2, 9, 106, 150, 10, 4900, 100096, 10, 0, 2147483647, 0x155cc0, 0x19cc}, + {1, 0,40, 4, 44, 96, 380,150, 4900, 100096, 40, 0, 2147483647, 0x155cc0, 0x19cc}, + {2, 3,60,20, 46, 300, 640, 80, 4900, 10100, 80, 0, 2147483647, 0x155cc0, 0x19dd}, + {3, 8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0, 2147483647, 0x2191c0, 0x15cc}, + } + }, + + { + NEW_DFS_JAP_W53, + { + {0, 0, 8, 2, 9, 106, 150, 20,28400, 77000, 20, 0, 2147483647, 0x14c080, 0x16cc}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 0,40, 4,44, 96, 200,150,28400, 77000, 60, 0, 2147483647, 0x14c080, 0x16cc}, + {3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + } + }, + + { + NEW_DFS_JAP, + { + {0, 0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0, 2147483647, 0x14c080, 0x13dc}, + {1, 0, 8, 2, 7, 106, 140, 5,27600, 27900, 5, 0, 2147483647, 0x14c080, 0x19dd}, + {2, 0,40, 4,44, 96, 480,150, 2900, 80100, 40, 0, 2147483647, 0x14c080, 0x12cc}, + {3, 2,60,15,48, 940,2080, 32,19600, 40200, 32, 0, 60000000, 0x57BCF00, 0x1289}, + } + }, +}; + +static NewDFSTable NewDFSTable2_BW40[] = { + { + NEW_DFS_FCC, + { + {0, 0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0, 2147483647, 0xfe808, 0x13dc}, + {1, 0, 8, 2, 7, 106, 140, 5,27600, 27900, 5, 0, 2147483647, 0xfe808, 0x19dd}, + {2, 0,40, 4,44, 96, 480,150, 2900, 80100, 40, 0, 2147483647, 0xfe808, 0x12cc}, + {3, 2,60,15,48, 640,2080, 32,19600, 40200, 32, 0, 60000000, 0x57BCF00, 0x1289}, + } + }, + + { + NEW_DFS_EU, + { + {0, 0, 8, 2, 9, 106, 150, 10, 4900, 100096, 10, 0, 2147483647, 0x155cc0, 0x19cc}, + {1, 0,40, 4, 44, 96, 380,150, 4900, 100096, 40, 0, 2147483647, 0x155cc0, 0x19cc}, + {2, 3,60,20, 46, 300, 640, 80, 4900, 10100, 80, 0, 2147483647, 0x155cc0, 0x19dd}, + {3, 8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0, 2147483647, 0x2191c0, 0x15cc}, + } + }, + + { + NEW_DFS_JAP_W53, + { + {0, 0, 8, 2, 9, 106, 150, 20,28400, 77000, 20, 0, 2147483647, 0x14c080, 0x16cc}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 0,40, 4,44, 96, 200,150,28400, 77000, 60, 0, 2147483647, 0x14c080, 0x16cc}, + {3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + } + }, + + { + NEW_DFS_JAP, + { + {0, 0, 8, 2, 7, 106, 150, 5,2900, 80100, 5, 0, 2147483647, 0x14c080, 0x13dc}, + {1, 0, 8, 2, 7, 106, 140, 5,27600, 27900, 5, 0, 2147483647, 0x14c080, 0x19dd}, + {2, 0,40, 4,44, 96, 480,150, 2900, 80100, 40, 0, 2147483647, 0x14c080, 0x12cc}, + {3, 2,60,15,48, 940,2080, 32,19600, 40200, 32, 0, 60000000, 0x57BCF00, 0x1289}, + } + }, +}; + +static NewDFSTable NewDFSTable2_BW80[] = { + { + NEW_DFS_FCC, + { + {0, 0, 8, 2, 9, 106, 150, 15, 2900, 80100, 15, 0, 2147483647, 0xfe808, 0x16cc}, + {1, 0, 8, 2, 7, 106, 140, 5,27600, 27900, 5, 0, 2147483647, 0xfe808, 0x19dd}, + {2, 0,40, 4,44, 96, 480,150, 2900, 80100, 40, 0, 2147483647, 0xfe808, 0x12cc}, + {3, 2,60,15,48, 640,2080, 32,19600, 40200, 32, 0, 60000000, 0x57BCF00, 0x1289}, + } + }, + + { + NEW_DFS_EU, + { + {0, 0, 8, 2, 9, 106, 150, 10, 4900, 100096, 10, 0, 2147483647, 0x155cc0, 0x19cc}, + {1, 0,40, 4, 44, 96, 380,150, 4900, 100096, 40, 0, 2147483647, 0x155cc0, 0x19cc}, + {2, 3,60,20, 46, 300, 640, 80, 4900, 10100, 80, 0, 2147483647, 0x155cc0, 0x19dd}, + {3, 8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0, 2147483647, 0x2191c0, 0x15cc}, + } + }, + + { + NEW_DFS_JAP_W53, + { + {0, 0, 8, 2, 9, 106, 150, 20,28400, 77000, 20, 0, 2147483647, 0x14c080, 0x16cc}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 0,40, 4,44, 96, 200,150,28400, 77000, 60, 0, 2147483647, 0x14c080, 0x16cc}, + {3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + } + }, + + { + NEW_DFS_JAP, + { + {0, 0, 8, 2, 9, 106, 150, 15, 2900, 80100, 15, 0, 2147483647, 0x14c080, 0x16cc}, + {1, 0, 8, 2, 7, 106, 140, 5,27600, 27900, 5, 0, 2147483647, 0x14c080, 0x19dd}, + {2, 0,40, 4,44, 96, 480,150, 2900, 80100, 40, 0, 2147483647, 0x14c080, 0x12cc}, + {3, 2,60,15,48, 940,2080, 32,19600, 40200, 32, 0, 60000000, 0x57BCF00, 0x1289}, + } + }, +}; + +static void dfs_sw_init( + IN PRTMP_ADAPTER pAd); + +static BOOLEAN StagerRadarCheck( + IN PRTMP_ADAPTER pAd, + UINT8 dfs_channel); + +static BOOLEAN ChirpRadarCheck( + IN PRTMP_ADAPTER pAd); + +#ifdef RLT_BBP +static BOOLEAN MT7650DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PRADAR_DETECT_STRUCT pRadarDetect, + OUT PDFS_EVENT pDfsEvent); +#else +static BOOLEAN DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PRADAR_DETECT_STRUCT pRadarDetect, + OUT PDFS_EVENT pDfsEvent); +#endif /* MT76x0 */ +static BOOLEAN DfsChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 DfsChannel); + +static VOID ChannelSelectOnRadarDetection( + IN PRTMP_ADAPTER pAd); + +static BOOLEAN DfsEventDrop( + IN PRTMP_ADAPTER pAd, + IN PDFS_EVENT pDfsEvent); + +static inline BOOLEAN NewRadarDetectionMcuStart(PRTMP_ADAPTER pAd) +{ + /* + 8051 firmware don't care parameter Token, Arg0 and Arg1 + */ + return AsicSendCommandToMcu(pAd, DFS_ONOFF_MCU_CMD, 0xff, 0x01, 0x01, FALSE); +} + +static inline BOOLEAN NewRadarDetectionMcuStop(PRTMP_ADAPTER pAd) +{ + /* + 8051 firmware don't care parameter Token, Arg0 and Arg1 + */ + return AsicSendCommandToMcu(pAd, DFS_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE); +} + + +static inline VOID DfsHwDetectionStatusGet(PRTMP_ADAPTER pAd, + PUINT8 pDetectedChannels) +{ +#ifdef RLT_BBP + RTMP_BBP_IO_READ32(pAd, DFS_R1, pDetectedChannels); +#else + RTMP_DFS_IO_READ8(pAd, 0x2, pDetectedChannels); +#endif /* MT76x0 */ +} + +static inline VOID DfsResetHwDetectionStatus(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + +#ifdef RLT_BBP + RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask); +#else + RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask); +#endif /* MT76x0 */ +} + +static inline VOID DfsCaptureModeControl(PRTMP_ADAPTER pAd, + BOOLEAN bEnable, + BOOLEAN bPowerUp, + BOOLEAN bCapLastEvents) +{ + UINT8 bbp_val = 0; + + bbp_val = (bEnable == TRUE) | + ((bPowerUp == TRUE) <<1) | + ((bCapLastEvents == TRUE) << 2); + +#ifdef RLT_BBP + RTMP_BBP_IO_WRITE32(pAd, DFS_R36, (UINT32) bbp_val); +#else + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, bbp_val); +#endif /* MT76x0 */ +} + +static inline VOID DfsDetectionEnable(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + +#ifdef RLT_BBP + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, (pRadarDetect->EnabledChMask << 16)); +#else + RTMP_DFS_IO_WRITE8(pAd, pRadarDetect->EnabledChMask, 1); +#endif /* MT76x0 */ +} + +static inline VOID DfsDetectionDisable(PRTMP_ADAPTER pAd) +{ +#ifdef RLT_BBP + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, 0); +#else + RTMP_DFS_IO_WRITE8(pAd, 0x1, 0); +#endif /* MT76x0 */ +} + +static inline VOID StagerRadarGetPRIs(PRTMP_ADAPTER pAd, + UINT8 dfs_channel, + PUINT32 pT1, + PUINT32 pT2, + PUINT32 pT3) +{ + UINT32 T_all = 0; +#ifdef RLT_BBP + UINT32 bbp_val = 0; + PDFS_PROGRAM_PARAM pDfsProgramParam = \ + &pAd->CommonCfg.RadarDetect.DfsProgramParam; +#else + UINT8 bbp_val = 0; +#endif /* MT76x0 */ + +#ifdef RLT_BBP + /* select channel */ + bbp_val = (pDfsProgramParam->ChEnable << 16) | dfs_channel; + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val); + + RTMP_BBP_IO_READ32(pAd, DFS_R19, &T_all); + RTMP_BBP_IO_READ32(pAd, DFS_R22, pT1); + RTMP_BBP_IO_READ32(pAd, DFS_R25, pT2); +#else + /* select channel */ + RTMP_DFS_IO_WRITE8(pAd, 0x0, dfs_channel); + + /*0. Select dfs channel 4 and read out T1/T2/T3, 50 ns unit; 32bits */ + RTMP_DFS_IO_READ8(pAd, 0x2d, &bbp_val); + T_all += bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x2e, &bbp_val); + T_all += bbp_val<<8; + RTMP_DFS_IO_READ8(pAd, 0x2f, &bbp_val); + T_all += bbp_val<<16; + RTMP_DFS_IO_READ8(pAd, 0x30, &bbp_val); + T_all += bbp_val<<24; + + RTMP_DFS_IO_READ8(pAd, 0x33, &bbp_val); + *pT1 += bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x34, &bbp_val); + *pT1 += bbp_val<<8; + RTMP_DFS_IO_READ8(pAd, 0x35, &bbp_val); + *pT1 += bbp_val<<16; + RTMP_DFS_IO_READ8(pAd, 0x36, &bbp_val); + *pT1 += bbp_val<<24; + + RTMP_DFS_IO_READ8(pAd, 0x3d, &bbp_val); + *pT2 += bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x3e, &bbp_val); + *pT2 += bbp_val<<8; + RTMP_DFS_IO_READ8(pAd, 0x3f, &bbp_val); + *pT2 += bbp_val<<16; + RTMP_DFS_IO_READ8(pAd, 0x40, &bbp_val); + *pT2 += bbp_val<<24; +#endif /* MT76x0 */ + + *pT3 = T_all - *pT1 -*pT2; +} + +static inline VOID DfsHwDetectionGetPulseInfo(PRTMP_ADAPTER pAd, + UINT8 ChannelIndex, + PUINT32 pPeriod, + PUINT32 pWidth1, + PUINT32 pWidth2, + PUINT32 pBurst) +{ +#ifdef RLT_BBP + UINT32 bbp_val = 0; + PDFS_PROGRAM_PARAM pDfsProgramParam = \ + &pAd->CommonCfg.RadarDetect.DfsProgramParam; +#else + UINT8 bbp_val = 0; +#endif /* MT76x0 */ + + *pPeriod = *pWidth1 = *pWidth2 = *pBurst = 0; + +#ifdef RLT_BBP + /* select channel */ + bbp_val = (pDfsProgramParam->ChEnable << 16) | ChannelIndex; + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val); + + /* Read reports - Period */ + RTMP_BBP_IO_READ32(pAd, DFS_R19, pPeriod); + + /* Read reports - Width */ + RTMP_BBP_IO_READ32(pAd, DFS_R20, pWidth1); + RTMP_BBP_IO_READ32(pAd, DFS_R23, pWidth2); + + /* Read reports - Burst Number */ + RTMP_BBP_IO_READ32(pAd, DFS_R22, pBurst); +#else + /* select channel*/ + RTMP_DFS_IO_WRITE8(pAd, 0x0, ChannelIndex); + + /* Read reports - Period */ + RTMP_DFS_IO_READ8(pAd, 0x2d, &bbp_val); + *pPeriod = bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x2e, &bbp_val); + *pPeriod += (bbp_val << 8); + RTMP_DFS_IO_READ8(pAd, 0x2f, &bbp_val); + *pPeriod += (bbp_val << 16); + RTMP_DFS_IO_READ8(pAd, 0x30, &bbp_val); + *pPeriod += (bbp_val << 24); + + /* Read reports - Width */ + RTMP_DFS_IO_READ8(pAd, 0x31, &bbp_val); + *pWidth1 = bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x32, &bbp_val); + *pWidth1 += (bbp_val << 8); + + RTMP_DFS_IO_READ8(pAd, 0x37, &bbp_val); + *pWidth2 = bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x38, &bbp_val); + *pWidth2 += (bbp_val << 8); + + /* Read reports - Burst Number */ + RTMP_DFS_IO_READ8(pAd, 0x33, &bbp_val); + *pBurst = bbp_val; + RTMP_DFS_IO_READ8(pAd, 0x34, &bbp_val); + *pBurst += (bbp_val << 8); + RTMP_DFS_IO_READ8(pAd, 0x35, &bbp_val); + *pBurst += (bbp_val << 16); + RTMP_DFS_IO_READ8(pAd, 0x36, &bbp_val); + *pBurst += (bbp_val << 24); +#endif /* MT76x0 */ +} + +static inline VOID DfsProgramBbpValues(PRTMP_ADAPTER pAd, + pNewDFSTable pDfsTable) +{ + UINT8 idx, DfsInputControl; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + +#ifdef RLT_BBP + { + UINT32 bbp_val = 0; + + DfsInputControl = pDfsProgramParam->Symmetric_Round << 4; + + /* Delta Delay*/ + DfsInputControl |= (pDfsProgramParam->DeltaDelay & 0xf); + DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DfsInputControl)); + + /* VGA Mask*/ + DBGPRINT(RT_DEBUG_TRACE,("VGA_Mask = 0x%x\n", pDfsProgramParam->VGA_Mask)); + + /* Input Control 0 */ + bbp_val = (pDfsProgramParam->VGA_Mask << 16) | (DfsInputControl); + + bbp_val |= (pDfsProgramParam->PwrDown_Hold_Time << 8); + bbp_val |= (pDfsProgramParam->PwrGain_Offset << 12); + + RTMP_BBP_IO_WRITE32(pAd, DFS_R2, bbp_val); + + /* packet end Mask*/ + DBGPRINT(RT_DEBUG_TRACE,("Packet_End_Mask = 0x%x\n", pDfsProgramParam->Packet_End_Mask)); + + /* Rx PE Mask*/ + DBGPRINT(RT_DEBUG_TRACE,("Rx_PE_Mask = 0x%x\n", pDfsProgramParam->Rx_PE_Mask)); + + /* Input Control 1 */ + bbp_val = (pDfsProgramParam->Rx_PE_Mask << 16) | (pDfsProgramParam->Packet_End_Mask); + RTMP_BBP_IO_WRITE32(pAd, DFS_R3, bbp_val); + + /* AGC Input Control */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R32, 0x00040071); + MT7650_ADJUST_AGC(pAd); + MT7650_ADJUST_DFS_AGC(pAd); + /* program each channel*/ + for (idx = 0; idx < DfsEngineNum; idx++) + { + /* select channel*/ + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, idx); + + DBGPRINT(RT_DEBUG_TRACE, ("write DFS Channle[%d] configuration \n", idx)); + + /* Detection Mode */ + bbp_val = (pDfsTable->entry[idx].mode & 0xf); + + if (pAd->chipCap.DfsEngineNum > 4 && (idx==4 || idx==5)) + bbp_val |= ((pDfsTable->entry[idx].avgLen & 0x3) << 28); + else + bbp_val |= ((pDfsTable->entry[idx].avgLen & 0x1ff) << 16); + + /* DFS Mode */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R4, bbp_val); + + /* DFS Energy */ + bbp_val = ((pDfsTable->entry[idx].EHigh & 0x0fff) << 16) | (pDfsTable->entry[idx].ELow & 0x0fff); + RTMP_BBP_IO_WRITE32(pAd, DFS_R5, bbp_val); + + /* DFS Period Low */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R7, pDfsTable->entry[idx].TLow); + + /* DFS Period High */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R9, pDfsTable->entry[idx].THigh); + + /* DFS Burst Low */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R11, pDfsTable->entry[idx].BLow); + + /* DFS Burst High */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R13, pDfsTable->entry[idx].BHigh); + + /* DFS Width */ + bbp_val = ((pDfsTable->entry[idx].WHigh & 0x0fff) << 16) | (pDfsTable->entry[idx].WLow & 0x0fff); + RTMP_BBP_IO_WRITE32(pAd, DFS_R14, bbp_val); + + + /* DFS Measurement Uncertainty */ + bbp_val = (pDfsTable->entry[idx].EpsilonW << 16) | (pDfsTable->entry[idx].EpsilonT); + RTMP_BBP_IO_WRITE32(pAd, DFS_R15, bbp_val); + + /* DFS Event Expiration */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R17, pDfsTable->entry[idx].EventExpiration); + + /* DFS Power Jump */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R30, pDfsTable->entry[idx].PwrJump); + } + + /* Reset status */ + RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask); + + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + RTMP_BBP_IO_WRITE32(pAd, DFS_R36, 0x00000003); + + /* Enable detection*/ + bbp_val = (pDfsProgramParam->ChEnable << 16); + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val); + RTMP_IO_WRITE32(pAd, 0x212C, 0x0c350001); + } +#else + DfsInputControl = pDfsProgramParam->Symmetric_Round << 4; + + /* Full 40Mhz*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + /* BW 40*/ + DfsInputControl |= 0x80; + } + + /* Delta Delay*/ + DfsInputControl |= (pDfsProgramParam->DeltaDelay & 0xf); + RTMP_DFS_IO_WRITE8(pAd, 0x3, DfsInputControl); + DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DfsInputControl)); + + /* VGA Mask*/ + RTMP_DFS_IO_WRITE8(pAd, 0x4, pDfsProgramParam->VGA_Mask); + DBGPRINT(RT_DEBUG_TRACE,("VGA_Mask = 0x%x\n", pDfsProgramParam->VGA_Mask)); + + /* packet end Mask*/ + RTMP_DFS_IO_WRITE8(pAd, 0x5, pDfsProgramParam->Packet_End_Mask); + DBGPRINT(RT_DEBUG_TRACE,("Packet_End_Mask = 0x%x\n", pDfsProgramParam->Packet_End_Mask)); + + /* Rx PE Mask*/ + RTMP_DFS_IO_WRITE8(pAd, 0x6, pDfsProgramParam->Rx_PE_Mask); + DBGPRINT(RT_DEBUG_TRACE,("Rx_PE_Mask = 0x%x\n", pDfsProgramParam->Rx_PE_Mask)); + + /* program each channel*/ + for (idx = 0; idx < DfsEngineNum; idx++) + { + /* select channel*/ + RTMP_DFS_IO_WRITE8(pAd, 0x0, idx); + + DBGPRINT(RT_DEBUG_TRACE, ("write DFS Channle[%d] configuration \n",idx)); + /* start programing*/ + + /* reg 0x10, Detection Mode[2:0]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x10, (pDfsTable->entry[idx].mode & 0xf)); + + /* reg 0x11~0x12, M[7:0] & M[8]*/ + + if (pAd->chipCap.DfsEngineNum > 4 && + (idx==4 || idx==5)) + { + /* Ch 4 and Ch5 use indirect M which taking the M value of another channel (one of 0~3) */ + RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDfsTable->entry[idx].avgLen << 4) & 0x30)); + } + else + { + RTMP_DFS_IO_WRITE8(pAd, 0x11, (pDfsTable->entry[idx].avgLen & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDfsTable->entry[idx].avgLen >> 8) & 0x1)); + } + + /* reg 0x13~0x14, Energy Low[7:0] & Energy Low[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x13, (pDfsTable->entry[idx].ELow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x14, ((pDfsTable->entry[idx].ELow >> 8) & 0xf)); + + + /* reg 0x15~0x16, Energy High[7:0] & Energy High[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x15, (pDfsTable->entry[idx].EHigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x16, ((pDfsTable->entry[idx].EHigh >> 8) & 0xf)); + + + /* reg 0x28~0x29, Width Low[7:0] & Width Low[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x28, (pDfsTable->entry[idx].WLow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x29, ((pDfsTable->entry[idx].WLow >> 8) & 0xf)); + + /* reg 0x2a~0x2b, Width High[7:0] & Width High[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x2a, (pDfsTable->entry[idx].WHigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x2b, ((pDfsTable->entry[idx].WHigh >> 8) & 0xf)); + + /* reg 0x2c, Width Delta[7:0], (Width Measurement Uncertainty)*/ + RTMP_DFS_IO_WRITE8(pAd, 0x2c, (pDfsTable->entry[idx].EpsilonW & 0xff)); + + /* reg 0x17~0x1a, Period Low[7:0] & Period Low[15:8] & Period Low[23:16] & Period Low[31:24]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x17, (pDfsTable->entry[idx].TLow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x18, ((pDfsTable->entry[idx].TLow >> 8) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x19, ((pDfsTable->entry[idx].TLow >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1a, ((pDfsTable->entry[idx].TLow >> 24) & 0xff)); + + /* reg 0x1b~0x1e, Period High[7:0] & Period High[15:8] & Period High[23:16] & Period High[31:24]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x1b, (pDfsTable->entry[idx].THigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1c, ((pDfsTable->entry[idx].THigh >> 8) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1d, ((pDfsTable->entry[idx].THigh >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1e, ((pDfsTable->entry[idx].THigh >> 24) & 0xff)); + + /* reg 0x27, Period Delt[7:0], (Period Measurement Uncertainty)*/ + RTMP_DFS_IO_WRITE8(pAd, 0x27, (pDfsTable->entry[idx].EpsilonT & 0xff)); + + if (pDfsProgramParam->RadarEventExpire[idx] != 0) + { + RTMP_DFS_IO_WRITE8(pAd,0x39, (pDfsTable->entry[idx].EventExpiration & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((pDfsTable->entry[idx].EventExpiration >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((pDfsTable->entry[idx].EventExpiration >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((pDfsTable->entry[idx].EventExpiration >> 24) & 0xff)); + } + + } + + /* reset status */ + RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask); + /* Enable detection*/ + RTMP_DFS_IO_WRITE8(pAd, 0x1, (pDfsProgramParam->ChEnable)); +#endif /* MT76x0 */ +} + +#ifdef RTMP_MAC_PCI +static VOID SwCheckDfsEvent( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_MAC_PCI */ + + +/* + ======================================================================== + Routine Description: + Radar wave detection. The API should be invoke each second. + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID ApRadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + INT i; + + if (ScanRunning(pAd) == TRUE) + return; + + if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + pAd->Dot11_H.InServiceMonitorCount++; + + for (i=0; iChannelListNum; i++) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + pAd->ChannelList[i].RemainingTimeForUse --; + if ((pAd->Mlme.PeriodicRound%5) == 0) + { + DBGPRINT(RT_DEBUG_INFO, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", + pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); + } + } + } + /*radar detect*/ + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + RadarDetectPeriodic(pAd); + } + return; +} + + +/* 0 = Switch Channel when Radar Hit (Normal mode) + 1 = Don't Switch Channel when Radar Hit */ +INT Set_RadarDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->McuRadarDebug = simple_strtol(arg, 0, 16); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT) + printk("Show raw data of the event buffer.\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT) + { + if (pRadarDetect->bDfsSwDisable == 1) + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Warning!! DfsSwDisable is 1\n", __FUNCTION__)); + printk("Show effective event\n"); + } + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SILENCE) + printk("Silence\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH) + printk("Dont Switch Channel\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_BUSY) + printk("Dont Check Channel Busy\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_RSSI) + printk("Dont Check RSSI\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE) + printk("Simulate a radar detection\n"); + + return TRUE; +} + +INT Set_ResetRadarHwDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + DfsResetHwDetectionStatus(pAd); + return TRUE; +} + +INT Set_DfsSwDisable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->bDfsSwDisable = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("pRadarDetect->bDfsSwDisable = %u\n", pRadarDetect->bDfsSwDisable)); + return TRUE; +} + +INT Set_DfsEnvtDropAdjTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->EvtDropAdjTime = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("EventDropAdjTime = %u\n", pDfsSwParam->EvtDropAdjTime)); + return TRUE; +} + +INT Set_RadarStart_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + if (simple_strtol(arg, 0, 10) == 0) + { + NewRadarDetectionStart(pAd); + } + else if ((simple_strtol(arg, 0, 10) >= 1) && (simple_strtol(arg, 0, 10) <= pAd->CommonCfg.RadarDetect.EnabledChMask)) + { + pDfsProgramParam->ChEnable = simple_strtol(arg, 0, 10); + printk("Ch Enable == 0x%x\n", pDfsProgramParam->ChEnable); + NewRadarDetectionStart(pAd); + } + + return TRUE; +} + +INT Set_RadarStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + NewRadarDetectionStop(pAd); + return TRUE; +} + +#ifdef DFS_ATP_SUPPORT +INT Set_DfsAtpStart_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg) +{ + INT ret; + + if (simple_strtol(arg, 0, 10) == 1) { + /* To set the HtBw... */ + ret = Set_AP_SSID_Proc(pAd, pAd->CommonCfg.Ssid); + /* reset the flag */ + pAd->CommonCfg.RadarDetect.atp_radar_detect = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s: reset atp_radar_detect\n", __FUNCTION__)); + /* set not switch channel */ + pAd->CommonCfg.RadarDetect.McuRadarDebug = RADAR_DONT_SWITCH; + DBGPRINT(RT_DEBUG_TRACE, ("%s: channel do not switch\n", __FUNCTION__)); + if (ret) { + printk ("AP ATP DFS ready\n"); + } + } + else if (simple_strtol(arg, 0, 10) == 0) { + /* reset the flag */ + pAd->CommonCfg.RadarDetect.atp_radar_detect = FALSE; + pAd->CommonCfg.RadarDetect.atp_set_ht_bw = FALSE; + pAd->CommonCfg.RadarDetect.atp_set_vht_bw = FALSE; + pAd->CommonCfg.RadarDetect.atp_set_channel_ready = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s: reset atp_radar_detect\n", __FUNCTION__)); + pAd->CommonCfg.RadarDetect.McuRadarDebug = 0x0; + DBGPRINT(RT_DEBUG_TRACE, ("%s: channel do not switch\n", __FUNCTION__)); + } + else { + printk ("%s: wrong arg. 1->start, 0->stop\n", __FUNCTION__); + } + + return TRUE; +} + +INT Set_DfsAtpReset_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 1) { + /* reset the flag */ + pAd->CommonCfg.RadarDetect.atp_radar_detect = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s: reset atp_radar_detect\n", __FUNCTION__)); + printk ("AP ATP DFS ready\n"); + } + + return TRUE; +} + +INT Set_DfsAtpReport_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg) +{ + printk ("%s\n", __FUNCTION__); + if (pAd->CommonCfg.RadarDetect.atp_radar_detect == TRUE) { + printk ("DfsAtpDetected\n"); + } + else { + printk ("DfsAtp Not Detected\n"); + } + return TRUE; +} +#endif /* DFS_ATP_SUPPORT */ + +INT Set_RadarSetTbl1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PUCHAR p2 = arg; + ULONG idx, value; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Dec(idx, arg); + A2Dec(value, p2+ 1); + if (idx == 0) + { + pDfsProgramParam->DeltaDelay = value; + printk("Delta_Delay = %d\n", pDfsProgramParam->DeltaDelay); + } + else + modify_table1(pAd, idx, value); + + if (pAd->CommonCfg.RadarDetect.pDFSTable) + NewRadarDetectionProgram(pAd, pAd->CommonCfg.RadarDetect.pDFSTable); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Table not initialized.\n", __FUNCTION__)); + } + else + printk("please enter iwpriv ra0 set RadarT1=xxx:yyy\n"); + + return TRUE; +} + +INT Set_RadarSetTbl2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PUCHAR p2 = arg; + ULONG idx, value; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Dec(idx, arg); + A2Dec(value, p2+ 1); + modify_table2(pAd, idx, value); + } + else + printk("please enter iwpriv ra0 set RadarT2=xxx:yyy\n"); + + return TRUE; +} + +INT Set_PollTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->PollTime = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_PrintBusyIdle_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->print_ch_busy_sta = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_BusyIdleRatio_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->ch_busy_idle_ratio = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_DfsRssiHigh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->DfsRssiHigh = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_DfsRssiLow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->DfsRssiLow = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Show_BlockCh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int i; + + for (i=0; iChannelListNum; i++) + { + if (pAd->ChannelList[i].RemainingTimeForUse != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Ch%d: RemainingTimeForUse:%d sec;\n", + pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); + } + } + return TRUE; +} + + +VOID DFSInit(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + pRadarDetect->ch_busy_countdown = -1; + pRadarDetect->EnabledChMask = ((1 << pAd->chipCap.DfsEngineNum) -1); +#ifdef RLT_BBP + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + /* + Do NOT enable Radar Channel 1. (MT7650 DFS programming guide_v2_20121012.docx) + */ + pRadarDetect->EnabledChMask = 0xF; + pRadarDetect->bAdjustDfsAgc = FALSE; + pDfsProgramParam->PwrDown_Hold_Time = 0xf; + pDfsProgramParam->PwrGain_Offset = 0x3; + } +#endif /* MT76x0 */ + pRadarDetect->PollTime = 3; + pRadarDetect->DfsRssiHigh = -30; + pRadarDetect->DfsRssiLow = -90; + pRadarDetect->use_tasklet = 1; + pRadarDetect->McuRadarDebug = 0; + pRadarDetect->radarDeclared = 0; + pDfsProgramParam->ChEnable = pRadarDetect->EnabledChMask; + +#ifdef RLT_BBP + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + pDfsProgramParam->VGA_Mask = 0; + pDfsProgramParam->Packet_End_Mask = 0; + pDfsProgramParam->Rx_PE_Mask = (IS_MT76x2(pAd)) ? 0xFF : 0x0; + pDfsProgramParam->DeltaDelay = 0x2; + pDfsProgramParam->Symmetric_Round = 0; + } + else +#endif /* MT76x0 */ + { + pDfsProgramParam->VGA_Mask = 45; + pDfsProgramParam->Packet_End_Mask = 45; + pDfsProgramParam->Rx_PE_Mask = 45; + pDfsProgramParam->DeltaDelay = 0x3; + pDfsProgramParam->Symmetric_Round = 1; + } + /* + s/w detection needs event buffer. + */ + if (pAd->chipCap.DfsEngineNum > 4) + pRadarDetect->bDfsSwDisable = TRUE; /* Default close s/w detection for new DFS*/ + + dfs_sw_init(pAd); +} + +void NewRadarDetectionStart(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pNewDFSTable *ppDFSTable = &pRadarDetect->pDFSTable; + + pRadarDetect->bDfsInit = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("--->NewRadarDetectionStart()\n")); + + DFSInit(pAd); + + + RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd); + + if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd)) + pAd->Dot11_H.ChMovingTime = 605; + else + pAd->Dot11_H.ChMovingTime = 65; + + if (pAd->CommonCfg.RDDurRegion == FCC) + { + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 2; + + *ppDFSTable = &NewDFSTable1[0]; + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use FCC table\n")); + } + else if (pAd->CommonCfg.RDDurRegion == CE) + { + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 3; + + *ppDFSTable = &NewDFSTable1[1]; + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use CE table\n")); + } + else /* JAP*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + *ppDFSTable = &NewDFSTable1[3]; + + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 3; + } + else + { + *ppDFSTable = &NewDFSTable1[2]; + + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 2; + } + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use JAP table\n")); + } + +#ifdef RLT_BBP + if (IS_MT7610E(pAd) || IS_MT76x2(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_80) { + // New update: 20130606 + if (pAd->CommonCfg.RDDurRegion == CE) { + *ppDFSTable = &NewDFSTable2_BW80[1]; + } + else if (pAd->CommonCfg.RDDurRegion == FCC) { + *ppDFSTable = &NewDFSTable2_BW80[0]; + } + else if ((pAd->CommonCfg.Channel >= 52) + && (pAd->CommonCfg.Channel <= 64)) { + /* JAP_W53 */ + *ppDFSTable = &NewDFSTable2_BW80[2]; + } + else { + /* JAP_W56 */ + *ppDFSTable = &NewDFSTable2_BW80[3]; + } + } + else if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + // New update: 20130606 + if (pAd->CommonCfg.RDDurRegion == CE) { + *ppDFSTable = &NewDFSTable2_BW40[1]; + } + else if (pAd->CommonCfg.RDDurRegion == FCC) { + *ppDFSTable = &NewDFSTable2_BW40[0]; + } + else if ((pAd->CommonCfg.Channel >= 52) + && (pAd->CommonCfg.Channel <= 64)) { + /* JAP_W53 */ + *ppDFSTable = &NewDFSTable2_BW40[2]; + } + else { + /* JAP_W56 */ + *ppDFSTable = &NewDFSTable2_BW40[3]; + } + } + else if (pAd->CommonCfg.BBPCurrentBW == BW_20){ + if (pAd->CommonCfg.RDDurRegion == CE) { + *ppDFSTable = &NewDFSTable2_BW20[1]; + } + else if (pAd->CommonCfg.RDDurRegion == FCC) { + *ppDFSTable = &NewDFSTable2_BW20[0]; + } + else if ((pAd->CommonCfg.Channel >= 52) + && (pAd->CommonCfg.Channel <= 64)) { + /* JAP_W53 */ + *ppDFSTable = &NewDFSTable2_BW20[2]; + } + else { + /* JAP_W56 */ + *ppDFSTable = &NewDFSTable2_BW20[3]; + } + } + else + {} + } +#endif /* MT76x0 */ + + NewRadarDetectionProgram(pAd, (*ppDFSTable)); + +#ifdef RTMP_MAC_PCI + /* enable debug mode*/ + DfsCaptureModeControl(pAd, TRUE, TRUE, FALSE); + + RTMP_HW_TIMER_INT_SET(pAd, HW_TIMER_INTERVAL); /* 1ms Timer interrupt */ + RTMP_HW_TIMER_INT_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + pRadarDetect->bDfsInit = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("Poll Time=%d\n", pRadarDetect->PollTime)); +} + +VOID NewRadarDetectionStop( + IN PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + DBGPRINT(RT_DEBUG_TRACE, ("NewRadarDetectionStop\n")); + + /* set init bit = false to prevent dfs rotines */ + pRadarDetect->bDfsInit = FALSE; + pRadarDetect->radarDeclared = 0; + + /* Disable detection*/ + DfsDetectionDisable(pAd); + + /* Clear status */ + DfsResetHwDetectionStatus(pAd); + +#ifdef RTMP_MAC_PCI + RTMP_HW_TIMER_INT_SET(pAd, 0); + RTMP_HW_TIMER_INT_DISABLE(pAd); +#endif /* RTMP_MAC_PCI */ +#ifdef CARRIER_DETECTION_SUPPORT + if ((pAd->chipCap.carrier_func == TONE_RADAR_V3) && + pAd->CommonCfg.CarrierDetect.Enable == 0) +#endif + { + RTMP_IO_WRITE32(pAd, 0x212C, 0x00); + } +} + + +/* the debug port have timestamp 22 digit, the max number is 0x3fffff, each unit is 25ns for 40Mhz mode and 50ns for 20Mhz mode*/ +/* so a round of timestamp is about 25 * 0x3fffff / 1000 = 104857us (about 100ms) or*/ +/* 50 * 0x3fffff / 1000 = 209715us (about 200ms) in 20Mhz mode*/ +/* 3ms = 3000,000 ns / 25ns = 120000 -- a unit */ +/* 0x3fffff/120000 = 34.9 ~= 35*/ +/* CE Staggered radar check*/ +/* At beginning, the goal is to detect staggered radar, now, we also detect regular radar with this function.*/ + + +int SWRadarCheck( + IN PRTMP_ADAPTER pAd, USHORT id) +{ + int i, j, start_idx, end_idx; + pNewDFSDebugPort pCurrent, p1, pEnd; + ULONG period; + int radar_detected = 0; + USHORT widthsum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + /*ENTRY_PLUS could be replace by (pDfsSwParam->sw_idx[id]+1)%128*/ + USHORT Total, SwIdxPlus = ENTRY_PLUS(pDfsSwParam->sw_idx[id], 1, NEW_DFS_DBG_PORT_ENT_NUM); + UCHAR CounterToCheck; + +#ifdef RLT_BBP + /* only engine 0 and engine2 support event buffer */ + if (id == 1) + return 0; +#endif /* MT76x0 */ + + if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) || + (SwIdxPlus == pDfsSwParam->hw_idx[id])) /* no entry to process*/ + return 0; + + /* process how many entries?? total NEW_DFS_DBG_PORT_ENT_NUM*/ + if (pDfsSwParam->hw_idx[id] > SwIdxPlus) + Total = pDfsSwParam->hw_idx[id] - SwIdxPlus; + else + Total = pDfsSwParam->hw_idx[id] + NEW_DFS_DBG_PORT_ENT_NUM - SwIdxPlus; + + if (Total > NEW_DFS_DBG_PORT_ENT_NUM) + pDfsSwParam->pr_idx[id] = ENTRY_PLUS(pDfsSwParam->sw_idx[id], MAX_PROCESS_ENTRY, NEW_DFS_DBG_PORT_ENT_NUM); + else + pDfsSwParam->pr_idx[id] = ENTRY_PLUS(pDfsSwParam->sw_idx[id], Total, NEW_DFS_DBG_PORT_ENT_NUM); + + + start_idx = ENTRY_PLUS(pDfsSwParam->pr_idx[id], 1, NEW_DFS_DBG_PORT_ENT_NUM); + end_idx = pDfsSwParam->pr_idx[id]; + + pEnd = &pDfsSwParam->DFS_W[id][end_idx]; + + if (start_idx > end_idx) + end_idx += NEW_DFS_DBG_PORT_ENT_NUM; + + + pDfsSwParam->sw_idx[id] = pDfsSwParam->pr_idx[id]; + + /* FCC && Japan*/ + + if (pAd->CommonCfg.RDDurRegion != CE) + { + ULONG minPeriod = (3000 << 1); + /* Calculate how many counters to check*/ + /* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/ + /* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/ + /* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/ + /* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/ + /* the max period to check for 40Mhz for FCC is 28650 * 2*/ + /* the max period to check for 40Mhz for Japan is 80000 * 2*/ + /* 0x40000 = 4194304 / 57129 = 73.xxx*/ + /* 0x40000 = 4194304 / 160000 = 26.2144*/ + /* 53/73 < 1 (1+1)*/ + /* 53/26.2144 = 2.02... (2+1)*/ + /* 27/26.2144 = 1.02... (1+1)*/ + /* 20M should use the same value as 40Mhz mode*/ + + if (pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53) + { + minPeriod = 28500 << 1; + } + + if (pAd->CommonCfg.RDDurRegion == FCC) + { + CounterToCheck = 1+1; + } + else /* if (pAd->CommonCfg.RDDurRegion == JAP)*/ + { + if (pRadarDetect->PollTime <= 2) + CounterToCheck = 2+1; + else + CounterToCheck = 1+1; + } + + /* First Loop for FCC/JAP*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + + pCurrent->start_idx = 0xffff; + + /* calculate if any two pulse become a valid period, add it in period table,*/ + for (j = i - 1; j > start_idx; j--) + { + p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK]; + + /* check period, must within max period*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (widthsum < 600) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + else + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + } + else if (id == 1) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift; + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + if ((period >= (minPeriod - 2)) && (period <= pDfsSwParam->dfs_max_period)) + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > pDfsSwParam->dfs_max_period) + break; + } + } + else + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (widthsum < 600) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + else + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + } + else if (id == 1) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift; + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + if ((period >= ((minPeriod >> 1) - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1))) + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > (pDfsSwParam->dfs_max_period >> 1)) + break; + } + } + } /* for (j = i - 1; j > start_idx; j--)*/ + } /* for (i = end_idx; i > start_idx; i--)*/ + + /* Second Loop for FCC/JAP*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + if (pCurrent->start_idx != 0xffff) + { + /*pNewDFSDebugPort p2, p3, p4, p5, p6;*/ + pNewDFSDebugPort p2, p3; + pNewDFSMPeriod pCE_T; + ULONG idx[10], T[10]; + + for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++) + { + pCE_T = &pDfsSwParam->DFS_T[id][idx[0]]; + + p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + if (p2->start_idx == 0xffff) + continue; + + T[0] = pCE_T->period; + + for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++) + { + + pCE_T = &pDfsSwParam->DFS_T[id][idx[1]]; + + p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + if (idx[0] == idx[1]) + continue; + + if (p3->start_idx == 0xffff) + continue; + + T[1] = pCE_T->period; + + if ( PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err)) + { + if (id <= 2) /* && (id >= 0)*/ + { + /*if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > minPeriod)) ||*/ + /* ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > (minPeriod >> 1))) )*/ + { + unsigned int loop, PeriodMatched = 0, idx1; + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop); + if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err)) + PeriodMatched++; + } + + if (PeriodMatched > pDfsSwParam->dfs_declare_thres) + { + { + pNewDFSValidRadar pDFSValidRadar; + ULONG T1 = (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)? (T[1]>>1) : T[1]; + + pDFSValidRadar = &NewDFSValidTable[0]; + + while (pDFSValidRadar->type != NEW_DFS_END) + { + if ((pDFSValidRadar->type & pRadarDetect->MCURadarRegion) == 0) + { + pDFSValidRadar++; + continue; + } + + if (pDFSValidRadar->TLow) + { + if ( (T1 > (pDFSValidRadar->TLow - pDFSValidRadar->TMargin)) && + (T1 < (pDFSValidRadar->THigh + pDFSValidRadar->TMargin)) ) + { + radar_detected = 1; + } + } + else + { + if ( (T1 > (pDFSValidRadar->T - pDFSValidRadar->TMargin)) && + (T1 < (pDFSValidRadar->T + pDFSValidRadar->TMargin)) ) + { + radar_detected = 1; + break; + } + } + + pDFSValidRadar++; + } + if (radar_detected == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched)); + printk("SWRadarCheck: Radar Detected\n"); + return radar_detected; + } + else if (pRadarDetect->MCURadarRegion != NEW_DFS_JAP_W53) + DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched)); + } + } + } + } /* if (id <= 2) && (id >= 0)*/ + } + } /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/ + + /* increase FCC-1 detection*/ + if (id <= 2) + { + if (IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0])) + { + int loop, idx1, PeriodMatched_fcc1 = 0; + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop); + if ( IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) ) + { + /*printk("%d %d %d\n", PeriodMatched_fcc1, pDfsSwParam->DFS_T[id][idx1].period, loop);*/ + PeriodMatched_fcc1++; + } + } + + if (PeriodMatched_fcc1 > 3) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_fcc1 = %d (%d)\n", PeriodMatched_fcc1, id)); + radar_detected = 1; + return radar_detected; + } + } + } + + + /* increase W56-3 detection*/ + if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP) && (id <= 2)) + { + if (IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0])) + { + int loop, idx1, PeriodMatched_w56_3 = 0; + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop); + if ( IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) ) + { + /*printk("%d %d %d\n", PeriodMatched_w56_3, pDfsSwParam->DFS_T[id][idx1].period, loop);*/ + PeriodMatched_w56_3++; + } + } + + if (PeriodMatched_w56_3 > 3) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_w56_3 = %d (%d)\n", PeriodMatched_w56_3, id)); + radar_detected = 1; + return radar_detected; + } + } + } + + if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53) && (id <= 2) && IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0])) + { + int loop, idx1, PeriodMatched_W56_2 = 0; + + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop); + if ( IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) ) + { + /*printk("%d %d %d\n", PeriodMatched_W56_2, pDfsSwParam->DFS_T[id][idx1].period, loop);*/ + PeriodMatched_W56_2++; + } + } + + if (PeriodMatched_W56_2 >= 3) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_W56_2 = %d(%d)\n", PeriodMatched_W56_2, id)); + radar_detected = 1; + return radar_detected; + } + } + } /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/ + } /* if (pCurrent->start_idx != 0xffff)*/ + } /* for (i = end_idx; i > start_idx; i--)*/ + + return radar_detected; + } + + /* CE have staggered radar */ + + /* Calculate how many counters to check*/ + /* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/ + /* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/ + /* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/ + /* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/ + /* if pRadarDetect->PollTime is 8ms, a round of timestamp is ?? for 20Mhz, 12 for 40Mhz*/ + /* the max period to check for 40Mhz is 133333 + 125000 + 117647 = 375980*/ + /* 0x40000 = 4194304 / 375980 = 11.1556*/ + /* 53/11.1556 = 4.75...*/ + /* 35/11.1556 = 3.1374, (4+1) is safe, (3+1) to save CPU power, but may lost some data*/ + /* 27/11.1556 = 2.42, (3+1) is OK*/ + /* 21/11.1556 = 1.88, (2+1) is OK*/ + /* 20M should use the same value as 40Mhz mode*/ + if (pRadarDetect->PollTime == 1) + CounterToCheck = 5+1; + else if (pRadarDetect->PollTime == 2) + CounterToCheck = 4+1; + else if (pRadarDetect->PollTime == 3) + CounterToCheck = 3+1; + else if (pRadarDetect->PollTime <= 8) + CounterToCheck = 2+1; + else + CounterToCheck = 1+1; + + /* First Loop for CE*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + + pCurrent->start_idx = 0xffff; + + /* calculate if any two pulse become a valid period, add it in period table,*/ + for (j = i - 1; j > start_idx; j--) + { + p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK]; + + + /* check period, must within 16666 ~ 66666*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (((p1->width > 310) && (pCurrent->width < 300)) || ((pCurrent->width > 310) && ((p1->width < 300))) ) + continue; + if (widthsum < 620) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H; + else + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + + } + else if (id == 1) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift; + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + /*if ((period >= (33333 - 20)) && (period <= (133333 + 20)))*/ + if ((period >= (33333 - 20)) && (period <= pDfsSwParam->dfs_max_period)) + //if ((period >= (10000 - 2)) && (period <= pDfsSwParam->dfs_max_period)) + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > pDfsSwParam->dfs_max_period) /* to allow miss a pulse*/ + break; + } + + } + else + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (((p1->width > 300) && (pCurrent->width < 300)) || ((pCurrent->width > 300) && ((p1->width < 300))) ) + continue; + if (widthsum < 620) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H; + else + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + } + else if (id == 1) + { + pDfsSwParam->dfs_width_diff = widthsum >> 3; /* for 20M verified */ + //printk("dfs_width_diff = %u\n",pDfsSwParam->dfs_width_diff); + } + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> 6; + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + //if ((period >= (5000 - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1))) + if ((period >= (16666 - 20)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))//neil modify for ce 5-1 + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > (pDfsSwParam->dfs_max_period >> 1)) + break; + } + } + } /* for (j = i - 1; j > start_idx; j--)*/ + } + + /* Second Loop for CE*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + + /* Check Staggered radar*/ + if (pCurrent->start_idx != 0xffff) + { + pNewDFSDebugPort p2, p3; + pNewDFSMPeriod pCE_T; + ULONG idx[10], T[10]; + + /*printk("pCurrent=%d, idx=%d~%d\n", pCurrent->timestamp, pCurrent->start_idx, pCurrent->end_idx);*/ + + for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++) + { + pCE_T = &pDfsSwParam->DFS_T[id][idx[0]]; + + p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + /*printk("idx[0]= %d, idx=%d p2=%d, idx=%d~%d\n", idx[0], pCE_T->idx2, p2->timestamp, p2->start_idx, p2->end_idx);*/ + + if (p2->start_idx == 0xffff) + continue; + + T[0] = pCE_T->period; + + + for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++) + { + + pCE_T = &pDfsSwParam->DFS_T[id][idx[1]]; + + p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + /*printk("p3=%d, idx=%d~%d\n", p3->timestamp, p3->start_idx, p3->end_idx);*/ + + if (idx[0] == idx[1]) + continue; + + if (p3->start_idx == 0xffff) + continue; + + + + T[1] = pCE_T->period; + + + if (PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err)) + { + if (id <= 2) /* && (id >= 0)*/ + { + + + if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > 66666)) || + ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > 33333)) ) + { + unsigned int loop, PeriodMatched = 0, idx1; + + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop); + if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err)) + { + /*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/ + PeriodMatched++; + } + } + + if (PeriodMatched > pDfsSwParam->dfs_declare_thres) + { + printk("Radar Detected(CE), W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T[1], (unsigned int)id, PeriodMatched); + + if (PeriodMatched > (pDfsSwParam->dfs_declare_thres + 1)) + radar_detected = 1; + return radar_detected; + } + } + } + } + } /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/ + } /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/ + } + } /* for (i = end_idx; i < start_idx; i--)*/ + + return radar_detected; +} + +/* + ========================================================================== + Description: + Recheck DFS radar of stager type. + Arguments: + pAdapter Pointer to our adapter + dfs_channel DFS detect channel + Return Value: + "TRUE" if check pass, "FALSE" otherwise. + Note: + ========================================================================== + */ +static BOOLEAN StagerRadarCheck(IN PRTMP_ADAPTER pAd, UINT8 dfs_channel) +{ + UINT T1=0, T2=0, T3=0, F1, F2, F3 = 0, Fmax = 0, freq_diff_min, freq_diff_max; + UINT8 dfs_stg2=0; + UINT F_MAX, F_MID, F_MIN; + + DBGPRINT(RT_DEBUG_TRACE, ("--->StagerRadarCheck()\n")); + StagerRadarGetPRIs(pAd, dfs_channel, &T1, &T2, &T3); + + if (T3 < 5) + T3 = 0; + + /*1. Check radar stagger2 or stagger3*/ + if (T3 == 0 || ((T3 > (T1 + T2) ? (T3 - T1 - T2) : (T1 + T2 - T3)) < 25)) + { + DBGPRINT(RT_DEBUG_TRACE, ("stg2 confirmed\n")); + dfs_stg2 =1; + F1 = 20000000/T1; /*hz*/ + F2 = 20000000/T2; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("stg3 confirmed\n")); + F1 = 20000000/T1; /*hz*/ + F2 = 20000000/T2; + F3 = 20000000/T3; + } + + F_MAX = (F1 > F2) ? ( (F1 > F3) ? F1 : F3 ) : ( (F2 > F3) ? F2 : F3 ); + F_MIN = (F1 < F2) ? ( (F1 < F3) ? F1 : F3 ) : ( (F2 < F3) ? F2 : F3 ); + F_MID = (F1 > F2) ? ((F1 < F3) ? F1 : ( (F2 > F3) ? F2 : F3 )) : ( F2 < F3 ? F2 : ((F1 > F3) ? F1 :F3) ); + + DBGPRINT(RT_DEBUG_TRACE, ("F_MAX=%d F_MID=%d F_MIN=%d\n", F_MAX, F_MID, F_MIN)); + + F1 = F_MAX; + F2 = F_MID; + F3 = F_MIN; + + Fmax = F1; + + /*2. Check radar type 5 or type6*/ + if (Fmax>295 && Fmax<=405) + { + DBGPRINT(RT_DEBUG_TRACE, ("type5 confirmed\n")); + freq_diff_min = 20; + freq_diff_max = 50; + } + else if (Fmax>405 && Fmax<=1205) /* tolerate more range for looser type6 */ + { + DBGPRINT(RT_DEBUG_TRACE, ("type6 confirmed\n")); + freq_diff_min = 80; + freq_diff_max = 400; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, T1=%d, T2=%d, T3=%d\n", T1, T2, T3)); + return FALSE; + } + + /*3. According to decision of stagger and type do period check */ + if (dfs_stg2 == 1) + { + UINT freq_diff = (F1 - F2); + + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck freq_diff_min=%d freq_diff_max=%d \n", freq_diff_min, freq_diff_max)); + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck dfs_stg2, dff=%d \n", freq_diff)); + + if ((freq_diff >= freq_diff_min) && (freq_diff <= freq_diff_max)) + return TRUE; /* S/W check success */ + else + { + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, F1=%d, F2=%d\n", F1, F2)); + DBGPRINT(RT_DEBUG_TRACE, ("stg2 fail on S/W Freq confirmed\n")); + return FALSE; /* S/W check fail */ + } + } + else /* dfs_stg3 */ + { + UINT freq_diff_1 = (F1 - F2); + UINT freq_diff_2 = (F2 - F3); + + + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck freq_diff_min=%d freq_diff_max=%d \n", freq_diff_min, freq_diff_max)); + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck dfs_stg3, dff_1=%d, dff_2=%d \n", freq_diff_1, freq_diff_2)); + + + if( (freq_diff_1 >= freq_diff_min) && (freq_diff_1 <= freq_diff_max) && (freq_diff_2 >= freq_diff_min) && (freq_diff_2 <= freq_diff_max) ) + return TRUE; /* S/W check success */ + else + { + DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, F1=%d, F2=%d, F3=%d\n", F1, F2, F3)); + DBGPRINT(RT_DEBUG_TRACE, ("stg3 fail on S/W Freq confirmed\n")); + return FALSE; /* S/W check fail */ + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<---StagerRadarCheck()\n")); +} + + +/* + ========================================================================== + Description: + Recheck DFS radar of chrp type. + Arguments: + pAdapter Pointer to our adapter + dfs_channel DFS detect channel + Return Value: + "TRUE" if check pass, "FALSE" otherwise. + Note: + ========================================================================== + */ +static BOOLEAN ChirpRadarCheck(IN PRTMP_ADAPTER pAd) +{ + UINT32 CurrentTime, delta; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + + RTMP_IO_READ32(pAd, PBF_LIFE_TIMER, &CurrentTime); + delta = CurrentTime - pRadarDetect->TimeStamp; + pRadarDetect->TimeStamp = CurrentTime; + + /* ChirpCheck = 0 means the very first detection since start up*/ + if (pRadarDetect->ChirpCheck++ == 0) + return FALSE; + + if (delta <= (12*(1<<20))) /* 12 sec */ + { + if (pRadarDetect->ChirpCheck >= 2) + { + /* Anouce the radar on any mutiple detection within 12 sec*/ + DBGPRINT(RT_DEBUG_TRACE, ("ChirpRadarCheck OK.\n")); + return TRUE; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ChirpRadarCheck failed, discard previous detection.\n")); + pRadarDetect->ChirpCheck = 1; + return FALSE; + } + /* default */ + return FALSE; +} + + +static BOOLEAN DfsChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 DfsChannel) +{ + pNewDFSTable pDFSTable; + UINT8 i; + UINT32 T, W, W2, B; + BOOLEAN radarDeclared = 0; + + T = W = W2 = B = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("DFS HW check channel = 0x%x\n", DfsChannel)); + /*Select the DFS table based on radar country region*/ + if (pAd->CommonCfg.RDDurRegion == FCC) + pDFSTable = &NewDFSTable1[0]; + else if (pAd->CommonCfg.RDDurRegion == CE) + { + pDFSTable = &NewDFSTable1[1]; + } + else /* Japan*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFSTable = &NewDFSTable1[3]; + } + else + { + pDFSTable = &NewDFSTable1[2]; + } + } + /*check which channe(0~3) is detecting radar signals*/ + for (i = 0; i < pAd->chipCap.DfsEngineNum; i++) + { + + if (DfsChannel & (0x1 << i)) + { + DfsHwDetectionGetPulseInfo(pAd, i, &T, &W, &W2, &B); + + if (DfsSwCheckOnHwDetection(pAd, pDFSTable, i, T, W) == FALSE) + continue; + + DBGPRINT(RT_DEBUG_OFF, ("T = %u, W= %u detected by ch %d\n", T, W, i)); + + /*set this variable to 1 for announcing that we find the radar signals.*/ + radarDeclared = 1; + + if ( ((i == 3) || (i == 2)) && (pDFSTable->entry[i].mode != 0) ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Burst = %u(0x%x)\n", B, B)); + DBGPRINT(RT_DEBUG_TRACE, ("The second Width = %u(0x%x)\n", W2, W2)); + } + } + } + return radarDeclared; +} + + +#ifdef RLT_BBP +static BOOLEAN MT7650DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PRADAR_DETECT_STRUCT pRadarDetect, + OUT PDFS_EVENT pDfsEvent) +{ + UINT8 idx; + UINT32 EventBuff[DFS_EVENT_SIZE] = {0}; + UINT32 bbp_val; + + /* Read a event from event buffer */ + for (idx = 0; idx < DFS_EVENT_SIZE; idx++) + { + /* + 1st read - DFS_R37[31] = 0(engine0)/1(engine2), if no events ==> DFS_R37[31:0] = 0xFFFF_FFFF + 2nd read - DFS_R37[21:0] = pulse time + 3rd read - DFS_R37[25:16] = phase, DFS_R37[11:0] = pulse width + 4th read - DFS_R37[21:16] = power stable counter + DFS_R37[12:0] = current power + */ + RTMP_BBP_IO_READ32(pAd, DFS_R37, &bbp_val); + EventBuff[idx] = bbp_val; + } + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT) + { + MT7650_DFS_EVENT_BUFF_PRINT(0, EventBuff, DFS_EVENT_SIZE); + } + + /* No events */ + if (EventBuff[0] == 0xFFFFFFFF) + return FALSE; + + /* + Total 64 events: 32 events for engine0 and 32 event2 for engine2. + */ + pDfsEvent->EngineId = (EventBuff[0] & 0x80000000) ? 2:0; + pDfsEvent->TimeStamp = EventBuff[1] & 0x003FFFFF; + pDfsEvent->Width = EventBuff[2] & 0x0FFF; + pDfsEvent->phase = (EventBuff[2] >> 16) & 0x03FF; + pDfsEvent->power_stable_counter = (EventBuff[3] >> 16) & 0x003F; + pDfsEvent->current_power = EventBuff[3] & 0x1FFF; + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT) + { + DBGPRINT(RT_DEBUG_TRACE, ("EngineId = %d\n", pDfsEvent->EngineId)); + DBGPRINT(RT_DEBUG_TRACE, ("TimeStamp = 0x%x\n", pDfsEvent->TimeStamp)); + DBGPRINT(RT_DEBUG_TRACE, ("Width = 0x%x\n", pDfsEvent->Width)); + DBGPRINT(RT_DEBUG_TRACE, ("phase = 0x%x\n", pDfsEvent->phase)); + DBGPRINT(RT_DEBUG_TRACE, ("power_stable_counter = 0x%x\n", pDfsEvent->power_stable_counter)); + DBGPRINT(RT_DEBUG_TRACE, ("current_power = 0x%x\n\n", pDfsEvent->current_power)); + } + + /* Check if event is valid */ + if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: This event is invalid\n", __FUNCTION__)); + return FALSE; + } + + return TRUE; +} +#else +static BOOLEAN DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PRADAR_DETECT_STRUCT pRadarDetect, + OUT PDFS_EVENT pDfsEvent) +{ + UINT8 idx; + UINT8 EventBuff[DFS_EVENT_SIZE] = {0}; + UINT32 bbp_val; + + /* Read a event from event buffer */ + for (idx = 0; idx < DFS_EVENT_SIZE; idx++) + { + RTMP_BBP_IO_READ32(pAd, BBP_R127, &bbp_val); + EventBuff[idx] = bbp_val; + } + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT) + { + DFS_EVENT_BUFF_PRINT(0, EventBuff, DFS_EVENT_SIZE); + } + + pDfsEvent->EngineId = EventBuff[0]; + if (pDfsEvent->EngineId == 0xff) /* end of event */ + return FALSE; + + pDfsEvent->TimeStamp = EventBuff[1]; + pDfsEvent->TimeStamp |= (EventBuff[2] << 8); + pDfsEvent->TimeStamp |= (EventBuff[3] << 16); + + pDfsEvent->Width = EventBuff[4]; + pDfsEvent->Width |= (EventBuff[5] << 8); + + /* Check if event is valid */ + if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent)) + return FALSE; + + return TRUE; +} +#endif /* MT76x0 */ + +VOID NewRadarDetectionProgram(PRTMP_ADAPTER pAd, pNewDFSTable pDFSTable) +{ + UINT8 idx, TalbeIdx; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + pRadarDetect->bDfsInit = FALSE; + + /* Get Table index*/ + for (TalbeIdx = 0; !((1<type); TalbeIdx++) + { + if (TalbeIdx > MAX_RD_REGION) + { + DBGPRINT(RT_DEBUG_ERROR, ("Table index out of range.\n")); + return; + } + } + + for(idx = 0; idxDFSParamFromConfig & (0x1<NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].valid) + { + pDFSTable->entry[idx].mode = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].mode; + pDFSTable->entry[idx].avgLen = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].avgLen; + pDFSTable->entry[idx].ELow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].ELow; + pDFSTable->entry[idx].EHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EHigh; + pDFSTable->entry[idx].WLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WLow; + pDFSTable->entry[idx].WHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WHigh; + pDFSTable->entry[idx].EpsilonW = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonW; + pDFSTable->entry[idx].TLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].TLow; + pDFSTable->entry[idx].THigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].THigh; + pDFSTable->entry[idx].EpsilonT = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonT; + pDFSTable->entry[idx].BLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BLow; + pDFSTable->entry[idx].BHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BHigh; + pDFSTable->entry[idx].EventExpiration= pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EventExpiration; + pDFSTable->entry[idx].PwrJump= pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].PwrJump; + + DBGPRINT(RT_DEBUG_TRACE, ("TalbeIdx = %d; idx = %d; DFSParam = %2d; %3d; %3d; %3d; %3d; %4d; %3d; %6lu; %7lu; %4d; %2lu; %2lu, %d, 0x%04x\n", TalbeIdx, idx, + pDFSTable->entry[idx].mode, pDFSTable->entry[idx].avgLen, pDFSTable->entry[idx].ELow, + pDFSTable->entry[idx].EHigh, pDFSTable->entry[idx].WLow, pDFSTable->entry[idx].WHigh, + pDFSTable->entry[idx].EpsilonW, pDFSTable->entry[idx].TLow, pDFSTable->entry[idx].THigh, + pDFSTable->entry[idx].EpsilonT, pDFSTable->entry[idx].BLow, pDFSTable->entry[idx].BHigh, + pDFSTable->entry[idx].EventExpiration, pDFSTable->entry[idx].PwrJump)); + } + } + + /* Symmetric round*/ + if(pRadarDetect->SymRoundFromCfg != 0) + { + pDfsProgramParam->Symmetric_Round = pRadarDetect->SymRoundFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("Symmetric_Round = %d\n", pDfsProgramParam->Symmetric_Round)); + } + + /* BusyIdleRatio*/ + if(pRadarDetect->BusyIdleFromCfg != 0) + { + pRadarDetect->ch_busy_idle_ratio = pRadarDetect->BusyIdleFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("ch_busy_idle_ratio = %d\n", pRadarDetect->ch_busy_idle_ratio)); + } + /* DfsRssiHigh*/ + if(pRadarDetect->DfsRssiHighFromCfg != 0) + { + pRadarDetect->DfsRssiHigh = pRadarDetect->DfsRssiHighFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh)); + } + /* DfsRssiLow*/ + if(pRadarDetect->DfsRssiLowFromCfg != 0) + { + pRadarDetect->DfsRssiLow = pRadarDetect->DfsRssiLowFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow)); + } + + /*pRadarDetect->MCURadarRegion = pAd->CommonCfg.RDDurRegion;*/ + pRadarDetect->MCURadarRegion = pDFSTable->type; + + DfsProgramBbpValues(pAd, pDFSTable); + + pRadarDetect->bDfsInit = TRUE; + +} + +BOOLEAN DfsSwCheckOnHwDetection( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFSTable, + IN UINT8 DfsChannel, + IN ULONG RadarPeriod, + IN ULONG RadarWidth) +{ + BOOLEAN bRadarCheck = TRUE; + if (!RadarPeriod || !RadarWidth) + { + DBGPRINT(RT_DEBUG_TRACE, ("Block eception on zero RadarPeriod or RadarWidth\n")); + return FALSE; + } + + if (pDFSTable->type == NEW_DFS_JAP) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + /*check short pulse*/ + if (RadarWidth < 120) /* pulse width less than 6.4us is report is 6.4us */ + { + /* block the illegal period */ + if ((RadarPeriod < 2900) || + (RadarPeriod > 4700 && RadarPeriod < 6400) || + (RadarPeriod > 6800 && RadarPeriod < 27560)|| + (RadarPeriod > 27960 && RadarPeriod < 28360) || + (RadarPeriod > 28700 && RadarPeriod < 79900) || + (RadarPeriod > 80100)) + { + /*(0~145), (235~320us), (340~1378us), (1398~1418), (1435~3995us) and (4005us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + else if (RadarWidth < 130) /* 120~130 over lap range */ + { + /* block the illegal period */ + if ((RadarPeriod < 2900) || + (RadarPeriod > 10100 && RadarPeriod < 27560) || + (RadarPeriod > 27960 && RadarPeriod < 28360) || + (RadarPeriod > 28700 && RadarPeriod < 79900) || + (RadarPeriod > 80100)) + { + /*(0~145), (505~1378us), (1398~1418), (1435~3995us) and (4005us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + else if (RadarWidth >= 130)// pulse width over 6.4us is accuracy + { + if ((RadarPeriod<3900) || (RadarPeriod>10100)) + { + /* block the illegal period */ + /*(0~195) and (505us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + } + else if (DfsChannel == 3) + { + bRadarCheck = ChirpRadarCheck(pAd); + } + } + else if (pDFSTable->type == NEW_DFS_EU) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + + /* block the illegal period */ + if ((RadarPeriod < 4900) || + (RadarPeriod > 10200 && RadarPeriod < 12400) || + (RadarPeriod > 100100)) + { + /*(0~245), (510~620us), (5005us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + else if (DfsChannel == 4) /* to do: check dfs mode 8or9*/ + { + if (StagerRadarCheck(pAd, DfsChannel) == FALSE) + bRadarCheck = FALSE; + } + } + else if (pDFSTable->type == NEW_DFS_FCC) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + /*check short pulse*/ + if (RadarWidth < 120) /* pulse width less than 6.4us is report is 6.4us */ + { + /* block the illegal period */ + if ((RadarPeriod < 2900) || + (RadarPeriod > 4700 && RadarPeriod < 6400) || + (RadarPeriod > 6800 && RadarPeriod < 10200)|| + (RadarPeriod > 61600)) + { + /*(0~145), (235~320us), (340~510), (3080us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + else if (RadarWidth < 130) //120~130 over lap range + { + if ((RadarPeriod < 2900) || + (RadarPeriod > 61600)) + { + /* block the illegal period */ + /*(0~145) and (3080us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + else if (RadarWidth >= 130) + { + if ((RadarPeriod<3900) || (RadarPeriod>10100)) + { + /* block the illegal period */ + /*(0~195) and (505us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + } + else if (DfsChannel == 3) + { + bRadarCheck = ChirpRadarCheck(pAd); + } + } + else if (pDFSTable->type == NEW_DFS_JAP_W53) + { + if (RadarWidth > 130) // pulse width less than 6.4us is report is 6.4us + { + /*block W53 very large and short width*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + else{ + if ((RadarPeriod < 28360) || + (RadarPeriod > 28700 && RadarPeriod < 76900) || + (RadarPeriod > 76940)) + { + /*(0~1418), (1435~3845us) and (3847us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + } + + return bRadarCheck; +} + +static VOID ChannelSelectOnRadarDetection( + IN PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + UINT i; + + if (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE) + return; + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW == BW_80) + { + for (i=0; iChannelListNum; i++) + { + if ((pAd->CommonCfg.Channel >= 52 && pAd->CommonCfg.Channel <= 64) && + (pAd->ChannelList[i].Channel >= 52 && pAd->ChannelList[i].Channel <= 64)) + { + pAd->ChannelList[i].RemainingTimeForUse = 1800; + } + else if ((pAd->CommonCfg.Channel >= 100 && pAd->CommonCfg.Channel <= 112) && + (pAd->ChannelList[i].Channel >= 100 && pAd->ChannelList[i].Channel <= 112)) + { + pAd->ChannelList[i].RemainingTimeForUse = 1800; + } + else if ((pAd->CommonCfg.Channel >= 116 && pAd->CommonCfg.Channel <= 128) && + (pAd->ChannelList[i].Channel >= 116 && pAd->ChannelList[i].Channel <= 128)) + { + pAd->ChannelList[i].RemainingTimeForUse = 1800; + } + } + } +#endif /* DOT11_VHT_AC */ + + for (i=0; iChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + { + if(pAd->ChannelList[i].RemainingTimeForUse != 0) + DBGPRINT(RT_DEBUG_TRACE, ("From block channel = %u Jump!!!\n", pAd->ChannelList[i].Channel)); + else + DBGPRINT(RT_DEBUG_TRACE, ("From unblock channel = %u Jump!!!\n", pAd->ChannelList[i].Channel)); + + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if ((pAd->ChannelList[i].Channel >> 2) & 1) + { + if ((pAd->ChannelList[i+1].Channel - pAd->ChannelList[i].Channel) == 4 ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Find extend channel = %u\n", pAd->ChannelList[i+1].Channel)); + pAd->ChannelList[i+1].RemainingTimeForUse = 1800; + } + } + else + { + if ((pAd->ChannelList[i].Channel - pAd->ChannelList[i-1].Channel) == 4 ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Find extend channel = %u\n", pAd->ChannelList[i-1].Channel)); + pAd->ChannelList[i-1].RemainingTimeForUse = 1800; + } + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("BW is not 40.\n")); + + pAd->ChannelList[i].RemainingTimeForUse = 1800;/*30 min = 1800 sec*/ + break; + } + } + + /*when find an radar, the ChMovingTime will be set to announce how many seconds to sending software radar detection time.*/ + if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd)) + pAd->Dot11_H.ChMovingTime = 605; + else + pAd->Dot11_H.ChMovingTime = 65; + + /*if the Radar country region is JAP, we need find a new clear channel */ + if (pAd->CommonCfg.RDDurRegion == JAP_W56) + { + for (i = 0; i < pAd->ChannelListNum ; i++) + { + pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE); + if ((pAd->CommonCfg.Channel >= 100) && (pAd->CommonCfg.Channel <= 140)) + break; + } + } + else if (pAd->CommonCfg.RDDurRegion == JAP_W53) + { + for (i = 0; i < pAd->ChannelListNum ; i++) + { + pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE); + if ((pAd->CommonCfg.Channel >= 36) && (pAd->CommonCfg.Channel <= 60)) + break; + } + } + else + pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE); + +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + for (i=0; iChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + { + if(pAd->ChannelList[i].RemainingTimeForUse != 0) + DBGPRINT(RT_DEBUG_TRACE, ("Channel Switch to block channel = %u \n", pAd->ChannelList[i].Channel)); + else + DBGPRINT(RT_DEBUG_TRACE, ("Channel Switch to unblock channel = %u \n", pAd->ChannelList[i].Channel)); + break; + } + } + + /*ApSelectChannelCheck(pAd);*/ + if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + { + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + /* Prepare a count-down for channel switching */ + pAd->Dot11_H.CSCount = 0; + } + else if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + /*set this flag to 1 and the AP will restart to switch into new channel */ + pRadarDetect->DFSAPRestart = 1; + schedule_dfs_task(pAd); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error! Unexpected radar state.\n", __FUNCTION__)); + } + pRadarDetect->radarDeclared = 0; +} + +static BOOLEAN DfsEventDrop( + IN PRTMP_ADAPTER pAd, + IN PDFS_EVENT pDfsEvent) +{ + UINT32 TimeDiff = 0; /* unit: 50ns */ + UINT16 PreEnvtWidth = 0; + BOOLEAN RetVal = FALSE; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + PDFS_EVENT pPreDfsEvent = &pDfsSwParam->PreDfsEvent; + + if (pDfsEvent->EngineId != pPreDfsEvent->EngineId) + { + /* update prevoius event record then leave */ + NdisCopyMemory(pPreDfsEvent, pDfsEvent, DFS_EVENT_SIZE); + return FALSE; + } + + if (pDfsEvent->EngineId == 0x01 || pDfsEvent->EngineId == 0x02) + { + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + TimeDiff = ((pDfsEvent->TimeStamp - pPreDfsEvent->TimeStamp) >> 1); /* 25ns to 50ns*/ + PreEnvtWidth = pPreDfsEvent->Width >> 1; + } + else + { + TimeDiff = (pDfsEvent->TimeStamp - pPreDfsEvent->TimeStamp); + PreEnvtWidth = pPreDfsEvent->Width; + } + + if (TimeDiff < pDfsSwParam->EvtDropAdjTime && + PreEnvtWidth >= 200) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): EngineId = %x, Width = %u, TimeStamp = %u\n", + __FUNCTION__, + pDfsEvent->EngineId, + pDfsEvent->Width, + pDfsEvent->TimeStamp)); + RetVal = TRUE; + } + } + + /* update prevoius event record */ + NdisCopyMemory(pPreDfsEvent, pDfsEvent, DFS_EVENT_SIZE); + + return RetVal; +} + +static void dfs_sw_init(PRTMP_ADAPTER pAd) +{ + int j, k; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + + pDfsSwParam->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP; + pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT; + pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT; + pDfsSwParam->PreDfsEvent.EngineId = 0xff; + pDfsSwParam->EvtDropAdjTime = 2000; + + pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR; + if (pAd->CommonCfg.RDDurRegion == CE) { + pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2); + pDfsSwParam->dfs_width_ch0_err_H = CE_STAGGERED_RADAR_CH0_H_ERR; + pDfsSwParam->dfs_declare_thres = CE_STAGGERED_RADAR_DECLARE_THRES; + pDfsSwParam->dfs_max_period = CE_STAGGERED_RADAR_PERIOD_MAX; + } + else { + pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR; + if (pAd->CommonCfg.RDDurRegion == FCC) { + pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX; + } + else if (pAd->CommonCfg.RDDurRegion == JAP) { + pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX; + } + } + + pDfsSwParam->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP; + pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT; + pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT; + pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR; + if (pAd->CommonCfg.RDDurRegion == CE) + { + pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2); + pDfsSwParam->dfs_width_ch0_err_H = CE_STAGGERED_RADAR_CH0_H_ERR; + pDfsSwParam->dfs_declare_thres = CE_STAGGERED_RADAR_DECLARE_THRES; + pDfsSwParam->dfs_max_period = CE_STAGGERED_RADAR_PERIOD_MAX; + } + else + { + pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR; + if (pAd->CommonCfg.RDDurRegion == FCC) + pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX; + else if (pAd->CommonCfg.RDDurRegion == JAP) + pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX; + } + + if (pRadarDetect->use_tasklet) + pRadarDetect->PollTime = NEW_DFS_CHECK_TIME_TASKLET; + else + pRadarDetect->PollTime = NEW_DFS_CHECK_TIME; + + for (k = 0; k < pAd->chipCap.DfsEngineNum; k++) + { + for (j = 0; j < NEW_DFS_DBG_PORT_ENT_NUM; j++) + { + pDfsSwParam->DFS_W[k][j].start_idx = 0xffff; + } + } + + for (k = 0; k < pAd->chipCap.DfsEngineNum; k++) + { + pDfsSwParam->sw_idx[k] = NEW_DFS_DBG_PORT_ENT_NUM - 1; + pDfsSwParam->hw_idx[k] = 0; + } + + NdisZeroMemory(pDfsSwParam->DFS_T, sizeof(pDfsSwParam->DFS_T)); + NdisZeroMemory(pDfsSwParam->DFS_W, sizeof(pDfsSwParam->DFS_W)); +} + +void modify_table1(PRTMP_ADAPTER pAd, ULONG idx, ULONG value) +{ + pNewDFSTable pDFSTable; + ULONG x, y; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + if (pAd->CommonCfg.RDDurRegion == FCC) + pDFSTable = &NewDFSTable1[0]; + else if (pAd->CommonCfg.RDDurRegion == CE) + { + pDFSTable = &NewDFSTable1[1]; + } + else /* Japan*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFSTable = &NewDFSTable1[3]; + } + else + { + pDFSTable = &NewDFSTable1[2]; + } + } + +#ifdef RLT_BBP + if (IS_MT7610E(pAd) || IS_MT76x2(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_80) { + if (pAd->CommonCfg.RDDurRegion == CE) { + pDFSTable = &NewDFSTable2_BW80[1]; + } + else if (pAd->CommonCfg.RDDurRegion == FCC) { + pDFSTable = &NewDFSTable2_BW80[0]; + } + else if ((pAd->CommonCfg.Channel >= 52) + && (pAd->CommonCfg.Channel <= 64)) { + /* JAP_W53 */ + pDFSTable = &NewDFSTable2_BW80[2]; + } + else { + /* JAP_W56 */ + pDFSTable = &NewDFSTable2_BW80[3]; + } + } + else if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + // New update: 20130606 + if (pAd->CommonCfg.RDDurRegion == CE) { + pDFSTable = &NewDFSTable2_BW40[1]; + } + else if (pAd->CommonCfg.RDDurRegion == FCC) { + pDFSTable = &NewDFSTable2_BW40[0]; + } + else if ((pAd->CommonCfg.Channel >= 52) + && (pAd->CommonCfg.Channel <= 64)) { + /* JAP_W53 */ + pDFSTable = &NewDFSTable2_BW40[2]; + } + else { + /* JAP_W56 */ + pDFSTable = &NewDFSTable2_BW40[3]; + } + } + else if (pAd->CommonCfg.BBPCurrentBW == BW_20){ + if (pAd->CommonCfg.RDDurRegion == CE) { + pDFSTable = &NewDFSTable2_BW20[1]; + } + else if (pAd->CommonCfg.RDDurRegion == FCC) { + pDFSTable = &NewDFSTable2_BW20[0]; + } + else if ((pAd->CommonCfg.Channel >= 52) + && (pAd->CommonCfg.Channel <= 64)) { + /* JAP_W53 */ + pDFSTable = &NewDFSTable2_BW20[2]; + } + else { + /* JAP_W56 */ + pDFSTable = &NewDFSTable2_BW20[3]; + } + } + else + {} + } +#endif /* MT76x0 */ + + if (idx == 0) + { + pDfsProgramParam->DeltaDelay = value; + } + else if (idx <= (DfsEngineNum*16)) + { + x = idx / 16; + y = idx % 16; + pRadarDetect->DFSParamFromConfig = 0; /* to prevent table be loaded from config file again */ + switch (y) + { + case 1: + pDFSTable->entry[x].mode = (UCHAR)value; + break; + case 2: + pDFSTable->entry[x].avgLen = (USHORT)value; + break; + case 3: + pDFSTable->entry[x].ELow = (USHORT)value; + break; + + case 4: + pDFSTable->entry[x].EHigh = (USHORT)value; + break; + + case 5: + pDFSTable->entry[x].WLow = (USHORT)value; + break; + + case 6: + pDFSTable->entry[x].WHigh = (USHORT)value; + break; + + case 7: + pDFSTable->entry[x].EpsilonW = (UCHAR)value; + break; + + case 8: + pDFSTable->entry[x].TLow = (ULONG)value; + break; + + case 9: + pDFSTable->entry[x].THigh = (ULONG)value; + break; + + case 0xa: + pDFSTable->entry[x].EpsilonT = (UCHAR)value; + break; + + case 0xb: + pDFSTable->entry[x].BLow= (ULONG)value; + break; + + case 0xc: + pDFSTable->entry[x].BHigh = (ULONG)value; + break; + + case 0xd: + pDFSTable->entry[x].EventExpiration= (UINT32)value; + break; + + case 0xe: + pDFSTable->entry[x].PwrJump= (UINT16)value; + break; + + default: + break; + } + + } + else if (idx == (DfsEngineNum*16 +1)) + { + pDfsProgramParam->Symmetric_Round = (UCHAR)value; + } + else if (idx == (DfsEngineNum*16 +2)) + { + pDfsProgramParam->VGA_Mask = (UCHAR)value; + } + else if (idx == (DfsEngineNum*16 +3)) + { + pDfsProgramParam->Packet_End_Mask = (UCHAR)value; + } + else if (idx == (DfsEngineNum*16 +4)) + { + pDfsProgramParam->Rx_PE_Mask = (UCHAR)value; + } + + printk("Delta_Delay(0) = %d\n", pDfsProgramParam->DeltaDelay); + + for (x = 0; x < DfsEngineNum; x++) + { + printk("Channel %lu\n", x); + printk("\t\tmode(%02lu)=%d, M(%02lu)=%03d, EL(%02lu)=%03d EH(%02lu)=%03d, WL(%02lu)=%03d WH(%02lu)=%04d, eW(%02lu)=%02d\n" + "\t\tTL(%02lu)=%05u TH(%02lu)=%06u, eT(%02lu)=%03d, BL(%02lu)=%u, BH(%02lu)=%u\n" + "\t\tEE(%02lu) = %06u, PJ(%02lu) = 0x%02x\n", + (x*16+0x1), (unsigned int)pDFSTable->entry[x].mode, + (x*16+0x2), (unsigned int)pDFSTable->entry[x].avgLen, + (x*16+0x3), (unsigned int)pDFSTable->entry[x].ELow, + (x*16+0x4), (unsigned int)pDFSTable->entry[x].EHigh, + (x*16+0x5), (unsigned int)pDFSTable->entry[x].WLow, + (x*16+0x6), (unsigned int)pDFSTable->entry[x].WHigh, + (x*16+0x7), (unsigned int)pDFSTable->entry[x].EpsilonW, + (x*16+0x8), (unsigned int)pDFSTable->entry[x].TLow, + (x*16+0x9), (unsigned int)pDFSTable->entry[x].THigh, + (x*16+0xa), (unsigned int)pDFSTable->entry[x].EpsilonT, + (x*16+0xb), (unsigned int)pDFSTable->entry[x].BLow, + (x*16+0xc), (unsigned int)pDFSTable->entry[x].BHigh, + (x*16+0xd), (unsigned int)pDFSTable->entry[x].EventExpiration, + (x*16+0xe), (unsigned int)pDFSTable->entry[x].PwrJump ); + } + + printk("Symmetric_Round(%02d) = %d\n", (DfsEngineNum*16 +1), pDfsProgramParam->Symmetric_Round); + printk("VGA_Mask(%02d) = %d\n", (DfsEngineNum*16 +2), pDfsProgramParam->VGA_Mask); + printk("Packet_End_Mask(%02d) = %d\n", (DfsEngineNum*16 +3), pDfsProgramParam->Packet_End_Mask); + printk("Rx_PE_Mask(%02d) = %d\n", (DfsEngineNum*16 +4), pDfsProgramParam->Rx_PE_Mask); + +} + + +void modify_table2(PRTMP_ADAPTER pAd, ULONG idx, ULONG value) +{ + pNewDFSValidRadar pDFSValidRadar; + ULONG x, y; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + idx--; + + x = idx / 17; + y = idx % 17; + + pDFSValidRadar = &NewDFSValidTable[0]; + + while (pDFSValidRadar->type != NEW_DFS_END) + { + if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion) + { + if (x == 0) + break; + else + { + x--; + pDFSValidRadar++; + } + } + else + pDFSValidRadar++; + } + + if (pDFSValidRadar->type == NEW_DFS_END) + { + printk("idx=%d exceed max number\n", (unsigned int)idx); + return; + } + switch(y) + { + case 0: + pDFSValidRadar->channel = value; + break; + case 1: + pDFSValidRadar->WLow = value; + break; + case 2: + pDFSValidRadar->WHigh = value; + break; + case 3: + pDFSValidRadar->W = value; + break; + case 8: + pDFSValidRadar->WMargin = value; + break; + case 9: + pDFSValidRadar->TLow = value; + break; + case 10: + pDFSValidRadar->THigh = value; + break; + case 11: + pDFSValidRadar->T = value; + break; + case 16: + pDFSValidRadar->TMargin = value; + break; + } + + pDFSValidRadar = &NewDFSValidTable[0]; + while (pDFSValidRadar->type != NEW_DFS_END) + { + if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion) + { + printk("ch = %x --- ", pDFSValidRadar->channel); + printk("wl:wh = %d:%d ", pDFSValidRadar->WLow, pDFSValidRadar->WHigh); + printk("W = %u --- ", pDFSValidRadar->W); + printk("W Margin = %d\n", pDFSValidRadar->WMargin); + printk("Tl:Th = %d:%d ", (unsigned int)pDFSValidRadar->TLow, (unsigned int)pDFSValidRadar->THigh); + printk("T = %lu --- ", pDFSValidRadar->T); + printk("T Margin = %d\n", pDFSValidRadar->TMargin); + } + pDFSValidRadar++; + } + +} + +#ifdef RTMP_MAC_PCI +VOID NewTimerCB_Radar( + IN PRTMP_ADAPTER pAd) +{ + UCHAR channel=0; + UCHAR radarDeclared = 0; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) || + (pRadarDetect->PollTime == 0)) + return; + + /* to prevent possible re-entries*/ + pRadarDetect->bDfsInit = FALSE; + + pRadarDetect->RadarTimeStampLow++; + + + /*if ((pRadarDetect->McuRadarTick++ >= pRadarDetect->PollTime) &&*/ + if ((pRadarDetect->McuRadarTick++ >= 3) && /* 30ms */ + (!pRadarDetect->bDfsSwDisable)) + { + SwCheckDfsEvent(pAd); + } + + /*The following codes is used to check if the hardware find the Radar Signal + * Read the 0~3 channel which had detected radar signals + */ + DfsHwDetectionStatusGet(pAd, &channel); + + /*Check if any interrupt trigger by Radar Global Status(Radar Signals)*/ + if ((channel & pRadarDetect->EnabledChMask) + //&& (!pRadarDetect->ch_busy) + ) { + radarDeclared = DfsChannelCheck(pAd, channel); +#ifdef DFS_ATP_SUPPORT + if ((radarDeclared == TRUE) && + (pRadarDetect->atp_radar_detect == FALSE)) + { + pRadarDetect->atp_radar_detect = TRUE; + } +#endif /* DFS_ATP_SUPPORT */ + } + + /*reset the radar channel for new counting (Write clear) */ + if (channel & pRadarDetect->EnabledChMask) + DfsResetHwDetectionStatus(pAd); + + if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE) + { + radarDeclared = 1; + pRadarDetect->McuRadarDebug &= ~RADAR_SIMULATE; + } + + if ((radarDeclared || pRadarDetect->radarDeclared) + && (pRadarDetect->ch_busy_countdown == -1) + ) { + pRadarDetect->ch_busy_countdown = 5; + } + else if (pRadarDetect->ch_busy_countdown >= 0) { + pRadarDetect->ch_busy_countdown--; + } + + /*Now, find an Radar signal*/ + //if ((!pRadarDetect->ch_busy) && (pRadarDetect->ch_busy_countdown == 0)) + if ((pRadarDetect->ch_busy_countdown == 0)) + { + /* Radar found!!!*/ + pRadarDetect->ch_busy_countdown = -1; + + /*Announce that this channel could not use in 30 minutes if we need find a clear channel*/ + if (!(pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH)) + ChannelSelectOnRadarDetection(pAd); + else + pRadarDetect->radarDeclared = 0; + } + pRadarDetect->bDfsInit = TRUE; +} + +#ifdef RLT_BBP +#define DFS_EVENT_DATA_FETCH(__pAd, __pRadarDetect, __DfsEvent) \ + MT7650DfsEventDataFetch(__pAd, __pRadarDetect, &__DfsEvent) +#else +#define DFS_EVENT_DATA_FETCH(__pAd, __pRadarDetect, __DfsEvent) \ + DfsEventDataFetch(__pAd, __pRadarDetect, &__DfsEvent) +#endif /* MT76x0 */ + +static VOID SwCheckDfsEvent( + IN PRTMP_ADAPTER pAd) +{ + INT k, limit = 64; + UCHAR id = 0; + DFS_EVENT DfsEvent; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + + pRadarDetect->McuRadarTick = 0; + + /* disable debug mode to read debug port */ + DfsCaptureModeControl(pAd, FALSE, TRUE, FALSE); + + pDfsSwParam->dfs_w_counter++; + + for (k = 0; k < limit; k++) + { + /* fetch event data */ + if (DFS_EVENT_DATA_FETCH(pAd, pRadarDetect, DfsEvent) == FALSE) + break; + + if (DfsEventDrop(pAd, &DfsEvent) == TRUE) + continue; + + if (pRadarDetect->use_tasklet) + { + id = DfsEvent.EngineId; + + if (id < pAd->chipCap.DfsEngineNum) + { + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter; + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = DfsEvent.TimeStamp; + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = DfsEvent.Width; + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT) + { + printk("counter = %lu ", pDfsSwParam->dfs_w_counter); + DFS_EVENT_PRINT(DfsEvent); + } + + pDfsSwParam->dfs_w_last_idx[id] = pDfsSwParam->dfs_w_idx[id]; + pDfsSwParam->dfs_w_idx[id]++; + if (pDfsSwParam->dfs_w_idx[id] >= NEW_DFS_DBG_PORT_ENT_NUM) + pDfsSwParam->dfs_w_idx[id] = 0; + } + } + } + + if (pRadarDetect->use_tasklet) + { + /* set hw_idx*/ + pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0]; + pDfsSwParam->hw_idx[1] = pDfsSwParam->dfs_w_idx[1]; + pDfsSwParam->hw_idx[2] = pDfsSwParam->dfs_w_idx[2]; + pDfsSwParam->hw_idx[3] = pDfsSwParam->dfs_w_idx[3]; + /*dfs tasklet will call SWRadarCheck*/ + schedule_dfs_task(pAd); + } + + /* enable debug mode*/ + DfsCaptureModeControl(pAd, TRUE, TRUE, FALSE); +} +#endif /* RTMP_MAC_PCI */ + +#endif /*CONFIG_AP_SUPPORT*/ +#endif /* DFS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_info.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_info.c new file mode 100644 index 000000000..5be652b83 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_info.c @@ -0,0 +1,10496 @@ +/**************************************************************************** + * 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_info.c + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#include "rt_config.h" + +#ifdef CUSTOMER_DCC_FEATURE +MultiplicationShiftFactor RateMultiplicationShiftFactor[224]; +#endif + + +INT SetManualTxOPThreshold(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->CommonCfg.ManualTxopThreshold = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP TP Threshold = %lu (Mbps)\n", + pAd->CommonCfg.ManualTxopThreshold)); + + return TRUE; +} + + +INT SetManualTxOPUpBound(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->CommonCfg.ManualTxopUpBound = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP Traffic Upper Bound = %d (Ratio)\n", + pAd->CommonCfg.ManualTxopUpBound)); + + return TRUE; +} + +INT SetManualTxOPLowBound(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->CommonCfg.ManualTxopLowBound = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP Traffic Low Bound = %d (Ratio)\n", + pAd->CommonCfg.ManualTxopLowBound)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Get Driver version. + + Return: + ========================================================================== +*/ +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DBGPRINT(RT_DEBUG_OFF, ("Driver version-%s %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__)); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->chipCap.MCUType == ANDES) { + UINT32 loop = 0; + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + if (pAd->chipCap.need_load_fw) { + USHORT fw_ver, build_ver; + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + DBGPRINT(RT_DEBUG_OFF, ("fw version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_OFF, ("build:%x\n", build_ver)); + DBGPRINT(RT_DEBUG_OFF, ("build time:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + if (pAd->chipCap.need_load_rom_patch) { + DBGPRINT(RT_DEBUG_OFF, ("rom patch version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 24 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("build time = \n")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + } +#endif /* CONFIG_ANDES_SUPPORT */ + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Country Region. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int retval; + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + retval = RT_CfgSetCountryRegion(pAd, arg, BAND_24G); + if (retval == FALSE) + return FALSE; + + /* if set country region, driver needs to be reset*/ + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Country Region for A band. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int retval; + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + retval = RT_CfgSetCountryRegion(pAd, arg, BAND_5G); + if (retval == FALSE) + return FALSE; + + /* if set country region, driver needs to be reset*/ + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand)); + + return TRUE; +} + + +INT Set_Cmm_WirelessMode_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg, + IN BOOLEAN FlgIsDiffMbssModeUsed) +{ + INT success = TRUE; +#ifdef CONFIG_AP_SUPPORT + UINT32 i = 0; +#ifdef MBSS_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (FlgIsDiffMbssModeUsed) { + LONG cfg_mode = simple_strtol(arg, 0, 10); + + /* assign wireless mode for the BSS */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PhyMode = + cfgmode_2_wmode((UCHAR)cfg_mode); + + /* + If the band is different with other BSS, we will correct it in + RT_CfgSetMbssWirelessMode() + */ + success = RT_CfgSetMbssWirelessMode(pAd, arg); + } + else +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + success = RT_CfgSetWirelessMode(pAd, arg); + + if (success) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* recover Wmm Capable for "each" BSS */ + /* all phy mode of MBSS are the same */ + for(i=0; iApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable = \ + pAd->ApCfg.MBSSID[i].bWmmCapableOrg; + +#ifdef MBSS_SUPPORT + /* In Same-MBSS Mode, all phy modes are the same */ + if (FlgIsDiffMbssModeUsed == 0) + pAd->ApCfg.MBSSID[i].wdev.PhyMode = pAd->CommonCfg.PhyMode; +#endif /* MBSS_SUPPORT */ + } + + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* clean up previous SCAN result */ + BssTableInit(&pAd->ScanTab); + pAd->StaCfg.LastScanTime = 0; + + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE; + } +#endif /* DOT11_N_SUPPORT */ + /* Set AdhocMode rates*/ + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); /* re-build BEACON frame*/ + AsicEnableIbssSync(pAd); /* copy to on-chip memory*/ + } + } +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_Cmm_WirelessMode_Proc::(=%d)\n", pAd->CommonCfg.PhyMode)); + DBGPRINT(RT_DEBUG_TRACE, ("Set_Cmm_WirelessMode_Proc::(BSS%d=%d)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PhyMode)); + + for(i=0; iApCfg.BssidNum; i++) + { + /* + When last mode is not 11B-only, new mode is 11B, we need to re-make + beacon frame content. + + Because we put support rate/extend support rate element in + APMakeBssBeacon(), not APUpdateBeaconFrame(). + */ + APMakeBssBeacon(pAd, i); + } +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n")); + } + + return success; +} + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +/* + ========================================================================== + Description: + Set Wireless Mode for MBSS + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_MBSS_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Cmm_WirelessMode_Proc(pAd, arg, 1); +} +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WirelessMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + return Set_Cmm_WirelessMode_Proc(pAd, arg, 0); +} + +#ifdef RT_CFG80211_SUPPORT +INT Set_DisableCfg2040Scan_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->cfg80211_ctrl.FlgCfg8021Disable2040Scan = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("pAd->cfg80211_ctrl.FlgCfg8021Disable2040Scan %d \n",pAd->cfg80211_ctrl.FlgCfg8021Disable2040Scan )); + return TRUE; +} +#endif + + + +/* + ========================================================================== + Description: + Set Channel + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Channel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef CONFIG_AP_SUPPORT + INT i; +#endif /* CONFIG_AP_SUPPORT */ + INT success = TRUE; + UCHAR Channel; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return FALSE; + + Channel = (UCHAR) simple_strtol(arg, 0, 10); + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if (pAd->ApCfg.ApCliAutoConnectChannelSwitching == FALSE) + pAd->ApCfg.ApCliAutoConnectChannelSwitching = TRUE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + /* check if this channel is valid*/ + if (ChannelSanity(pAd, Channel) == TRUE) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->CommonCfg.Channel = Channel; + /* Save the channel on MlmeAux for CntlOidRTBssidProc used. */ + pAd->MlmeAux.Channel = Channel; + + if (MONITOR_ON(pAd)) + { + UCHAR rf_channel; + +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + rf_channel = N_SetCenCh(pAd, pAd->CommonCfg.Channel); + else +#endif /* DOT11_N_SUPPORT */ + rf_channel = pAd->CommonCfg.Channel; + + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): CtrlChannel(%d), CentralChannel(%d) \n", + __FUNCTION__, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + } + } +#endif /* CONFIG_STA_SUPPORT */ + success = TRUE; + } + else + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + Channel = FirstChannel(pAd); + DBGPRINT(RT_DEBUG_WARN,("This channel is out of channel list, set as the first channel(%d) \n ", Channel)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + success = FALSE; + DBGPRINT(RT_DEBUG_WARN,("This channel is out of channel list, nothing to do!\n ")); +#endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == Channel) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: previous detection of a radar on this channel(Channel=%d)\n", Channel)); + success = FALSE; + break; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("RemainingTimeForUse %d ,Channel %d\n", + pAd->ChannelList[i].RemainingTimeForUse, Channel)); + } + } + } + } + + if (success == TRUE) + { + + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + pAd->Dot11_H.org_ch = pAd->CommonCfg.Channel; + } + + pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + APStop(pAd); + APStartUp(pAd); + } + else + { + NotifyChSwAnnToPeerAPs(pAd, ZERO_MAC_ADDR, pAd->CurrentAddress, 1, pAd->CommonCfg.Channel); + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.new_channel = Channel; + } + } + else + { + APStop(pAd); + APStartUp(pAd); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if (success == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", + pAd->CommonCfg.Channel)); +#ifdef DFS_ATP_SUPPORT + pAd->CommonCfg.RadarDetect.atp_set_channel_ready = TRUE; + if ((pAd->CommonCfg.RadarDetect.atp_set_ht_bw + || pAd->CommonCfg.RadarDetect.atp_set_vht_bw) + && pAd->CommonCfg.RadarDetect.atp_set_channel_ready) { + printk ("BW and Channel is ready\n"); + } +#endif /* DFS_ATP_SUPPORT */ + } + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + return success; +} + +#ifdef CUSTOMER_DCC_FEATURE +INT Set_ApChannelSwitch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR Channel = 0; + UCHAR offset = 0; + INT32 i,j,count; + CHAR temp[5]; + + i = 0; + j = 0; + count = 0; + while(arg[j] != '\0') + { + temp[i] = arg[j]; + j++; + if(temp[i] == ':' || arg[j] == '\0' ) + { + if(temp[i] == ':') + { + temp[i] = '\0'; + if((strlen(temp) != 0) && (strlen(temp) <= 3)) + { + Channel = simple_strtol(temp, 0, 10); + if(!ChannelSanity(pAd, Channel)) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong channel number \n")); + return FALSE; + } + } + else if(strlen(temp) > 3) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong channel number \n")); + return FALSE; + } + + count++; + i = -1; + } + else if(arg[j] == '\0') + { + temp[i+1] = '\0'; + if((strlen(temp) != 0) && (strlen(temp) <= 1)) + { + offset = simple_strtol(temp, 0, 10); + if(offset != 0 && offset != 1 && offset != 2) + return FALSE; + if((WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) && (offset == 2)) + offset = EXTCHA_BELOW; + } + else if(strlen(temp)) + { + DBGPRINT(RT_DEBUG_ERROR,("wrong offset value \n")); + return FALSE; + } + count ++; + } + } + i++; + if(count > 2) + return FALSE; + } + printk("%s: channel: %u offset: %u \n",__func__, Channel, offset); + pAd->CommonCfg.Channel = Channel; + + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 0; +#ifdef DOT11_VHT_AC + pAd->CommonCfg.vht_bw = VHT_BW_2040; +#endif +#ifdef DOT11_N_SUPPORT + if ((WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + switch (offset) + { + case 1: + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + break; + case 2: + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + pAd->CommonCfg.vht_bw = VHT_BW_80; + else + pAd->CommonCfg.vht_bw = VHT_BW_2040; +#endif + break; + } + N_ChannelCheck(pAd); + if(pAd->CommonCfg.RegTransmitSetting.field.BW != BW_20) + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + } +#endif +#ifdef DOT11_N_SUPPORT + if((WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + do{ + UCHAR ExtCh; + UCHAR Dir = offset; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; + + if (Dir == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == ExtCh) + break; + } + + if (i != pAd->ChannelListNum) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + break; + } + + Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + + if (Dir == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == ExtCh) + break; + } + + if (i != pAd->ChannelListNum) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + break; + } + + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 0; + } while(FALSE); + + if (Channel == 14) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 0; + } + } +#endif /* DOT11_N_SUPPORT */ + + NotifyChSwAnnToConnectedSTAs(pAd, CHANNEL_SWITCHING_MODE , pAd->CommonCfg.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); + return TRUE; +} +#endif + +/* + ========================================================================== + Description: + Set Short Slot Time Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ShortSlot_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int retval; + + retval = RT_CfgSetShortSlot(pAd, arg); + if (retval == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime)); + + return retval; +} + + +/* + ========================================================================== + Description: + Set Tx power + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG TxPower; + INT success = FALSE; + + TxPower = simple_strtol(arg, 0, 10); + if (TxPower <= 100) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pAd->CommonCfg.TxPowerPercentage = TxPower; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->CommonCfg.TxPowerDefault = TxPower; + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + } +#endif /* CONFIG_STA_SUPPORT */ + success = TRUE; +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + mt76x2_update_tx_power_percentage(pAd); + } +#endif + } + else + success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); + + return success; +} + +/* + ========================================================================== + Description: + Set 11B/11G Protection + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + switch (simple_strtol(arg, 0, 10)) + { + case 0: /*AUTO*/ + pAd->CommonCfg.UseBGProtection = 0; + break; + case 1: /*Always On*/ + pAd->CommonCfg.UseBGProtection = 1; + break; + case 2: /*Always OFF*/ + pAd->CommonCfg.UseBGProtection = 2; + break; + default: /*Invalid argument */ + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APUpdateCapabilityAndErpIe(pAd); +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set TxPreamble + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + RT_802_11_PREAMBLE Preamble; + + Preamble = (RT_802_11_PREAMBLE)simple_strtol(arg, 0, 10); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + if (Preamble == Rt802_11PreambleAuto) + return FALSE; +#endif /* CONFIG_AP_SUPPORT */ + + switch (Preamble) + { + case Rt802_11PreambleShort: + pAd->CommonCfg.TxPreamble = Preamble; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); +#endif /* CONFIG_STA_SUPPORT */ + break; + case Rt802_11PreambleLong: +#ifdef CONFIG_STA_SUPPORT + case Rt802_11PreambleAuto: + /* + If user wants AUTO, initialize to LONG here, then change according to AP's + capability upon association + */ +#endif /* CONFIG_STA_SUPPORT */ + pAd->CommonCfg.TxPreamble = Preamble; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); +#endif /* CONFIG_STA_SUPPORT */ + break; + default: /*Invalid argument */ + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set RTS Threshold + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + NDIS_802_11_RTS_THRESHOLD RtsThresh; + + RtsThresh = simple_strtol(arg, 0, 10); + + if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD)) + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; +#ifdef CONFIG_STA_SUPPORT + else if (RtsThresh == 0) + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; +#endif /* CONFIG_STA_SUPPORT */ + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Fragment Threshold + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + + FragThresh = simple_strtol(arg, 0, 10); + + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { + /*Illegal FragThresh so we set it to default*/ + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + } + else if (FragThresh % 2 == 1) + { + /* + The length of each fragment shall always be an even number of octets, + except for the last fragment of an MSDU or MMPDU, which may be either + an even or an odd number of octets. + */ + pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD) + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + else + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set TxBurst + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG TxBurst; + + TxBurst = simple_strtol(arg, 0, 10); + if (TxBurst == 1) + pAd->CommonCfg.bEnableTxBurst = TRUE; + else if (TxBurst == 0) + pAd->CommonCfg.bEnableTxBurst = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst)); + + return TRUE; +} + + +#ifdef RTMP_MAC_PCI +INT Set_ShowRF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int ShowRF = simple_strtol(arg, 0, 10); + + if (ShowRF == 1) + pAd->ShowRf = TRUE; + else + pAd->ShowRf = FALSE; + + return TRUE; +} +#endif /* RTMP_MAC_PCI */ + + +#ifdef AGGREGATION_SUPPORT +/* + ========================================================================== + Description: + Set TxBurst + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG aggre; + + aggre = simple_strtol(arg, 0, 10); + + if (aggre == 1) + pAd->CommonCfg.bAggregationCapable = TRUE; + else if (aggre == 0) + pAd->CommonCfg.bAggregationCapable = FALSE; + else + return FALSE; /*Invalid argument */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef PIGGYBACK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; + RTMPSetPiggyBack(pAd, pAd->CommonCfg.bPiggyBackCapable); + } +#endif /* PIGGYBACK_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable)); + + return TRUE; +} +#endif + + +#ifdef INF_PPA_SUPPORT +INT Set_INF_AMAZON_SE_PPA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT status; + UCHAR aggre; + UINT32 g_if_id; + NDIS_STATUS re_val; + + aggre = simple_strtol(arg, 0, 10); + + if (ppa_hook_directpath_register_dev_fn == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::There is no PPA module\n", __FUNCTION__)); + return FALSE; + } + + if (aggre == 1) + { + if (pAd->PPAEnable == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("PPA already enabled\n")); + } + else + { + if (pAd->pDirectpathCb == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate memory for pDirectpathCb\n")); + re_val = os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB)); + + if (re_val != NDIS_STATUS_SUCCESS) + return FALSE; + } + + /* Register callback */ + pAd->pDirectpathCb->rx_fn = ifx_ra_start_xmit; + pAd->pDirectpathCb->stop_tx_fn = NULL; + pAd->pDirectpathCb->start_tx_fn = NULL; + + status = ppa_hook_directpath_register_dev_fn( + &g_if_id, pAd->net_dev, pAd->pDirectpathCb, PPA_F_DIRECTPATH_REGISTER|PPA_F_DIRECTPATH_ETH_IF); + + if (status == IFX_SUCCESS) + { + pAd->g_if_id = g_if_id; + pAd->PPAEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Register PPA success::ret=%d, id=%d\n", status, pAd->g_if_id)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Register PPA fail::ret=%d\n", status)); + } + } + else if (aggre == 0) + { + if (pAd->PPAEnable == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("PPA already disabled\n")); + } + else + { + g_if_id = pAd->g_if_id; + status = ppa_hook_directpath_register_dev_fn(&g_if_id, pAd->net_dev, NULL, 0 /*PPA_F_DIRECTPATH_REGISTER*/); + + if (status == IFX_SUCCESS) + { + pAd->g_if_id = 0; + pAd->PPAEnable = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Unregister PPA success::ret=%d, if_id=%d\n", status, pAd->g_if_id)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Unregister PPA fail::ret=%d\n", status)); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Invalid argument=%d\n", __FUNCTION__, aggre)); + return FALSE; + } + + return TRUE; +} +#endif /* INF_PPA_SUPPORT */ + + +/* + ========================================================================== + Description: + Set IEEE80211H. + This parameter is 1 when needs radar detection, otherwise 0 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG ieee80211h; + + ieee80211h = simple_strtol(arg, 0, 10); + + if (ieee80211h == 1) + pAd->CommonCfg.bIEEE80211H = TRUE; + else if (ieee80211h == 0) + pAd->CommonCfg.bIEEE80211H = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H)); + + return TRUE; +} + +#ifdef EXT_BUILD_CHANNEL_LIST +/* + ========================================================================== + Description: + Set Country Code. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ExtCountryCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__)); + return TRUE; + } + + if(strlen(arg) == 2) + { + NdisMoveMemory(pAd->CommonCfg.CountryCode, arg, 2); + pAd->CommonCfg.bCountryFlag = TRUE; + } + else + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + pAd->CommonCfg.bCountryFlag = FALSE; + } + + { + UCHAR CountryCode[3] = {0}; + NdisMoveMemory(CountryCode, pAd->CommonCfg.CountryCode, 2); + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryCode_Proc::(bCountryFlag=%d, CountryCode=%s)\n", + pAd->CommonCfg.bCountryFlag, + CountryCode)); + } + return TRUE; +} +/* + ========================================================================== + Description: + Set Ext DFS Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ExtDfsType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR *pDfsType = &pAd->CommonCfg.DfsType; + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__)); + return TRUE; + } + + if (!strcmp(arg, "CE")) + *pDfsType = CE; + else if (!strcmp(arg, "FCC")) + *pDfsType = FCC; + else if (!strcmp(arg, "JAP")) + *pDfsType = JAP; + else + DBGPRINT(RT_DEBUG_TRACE, ("Unsupported DFS type:%s (Legal types are: CE, FCC, JAP)\n", arg)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Add new channel list + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ChannelListAdd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CH_DESP inChDesp; + PCH_REGION pChRegion = NULL; + + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__)); + return TRUE; + } + + /* Get Channel Region (CountryCode)*/ + { + INT loop = 0; + + while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((PSTRING) ChRegion[loop].CountReg, pAd->CommonCfg.CountryCode, 2) == 0) + { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + if (pChRegion == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("CountryCode is not configured or not valid\n")); + return TRUE; + } + } + + /* Parsing the arg, IN:arg; OUT:inChRegion */ + { + UCHAR strBuff[64], count = 0; + PUCHAR pStart, pEnd, tempIdx, tempBuff[5]; + + if (strlen(arg) <64) + NdisCopyMemory(strBuff, arg, strlen(arg)); + + if ((pStart = rtstrchr(strBuff, '[')) != NULL) + { + if ((pEnd = rtstrchr(pStart++, ']')) != NULL) + { + tempBuff[count++] = pStart; + for(tempIdx = pStart ;tempIdx != pEnd; tempIdx++) + { + if(*tempIdx == ',') + { + *tempIdx = '\0'; + tempBuff[count++] = ++tempIdx; + } + } + *(pEnd) = '\0'; + + if (count != 5) + { + DBGPRINT(RT_DEBUG_TRACE, ("Input Error. Too more or too less parameters.\n")); + return TRUE; + } + else + { + inChDesp.FirstChannel = (UCHAR) simple_strtol(tempBuff[0], 0, 10); + inChDesp.NumOfCh = (UCHAR) simple_strtol(tempBuff[1], 0, 10); + inChDesp.MaxTxPwr = (UCHAR) simple_strtol(tempBuff[2], 0, 10); + inChDesp.Geography = (!strcmp(tempBuff[3], "BOTH") ? BOTH: (!strcmp(tempBuff[3], "IDOR") ? IDOR : ODOR)); + inChDesp.DfsReq= (!strcmp(tempBuff[4], "TRUE") ? TRUE : FALSE); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Missing End \"]\"\n")); + return TRUE; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Invalid input format.\n", __FUNCTION__)); + return TRUE; + } + } + + /* Add entry to Channel List*/ + { + UCHAR EntryIdx; + PCH_DESP pChDesp = NULL; + UCHAR CountryCode[3] = {0}; + if (pAd->CommonCfg.pChDesp == NULL) + { + os_alloc_mem(pAd, &pAd->CommonCfg.pChDesp, MAX_PRECONFIG_DESP_ENTRY_SIZE*sizeof(CH_DESP)); + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + if (pChDesp) + { + for (EntryIdx= 0; pChRegion->pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++) + { + if (EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table*/ + { + DBGPRINT(RT_DEBUG_TRACE, ("Table is full.\n")); + return TRUE; + } + NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP)); + } + /* Copy the NULL entry*/ + NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("os_alloc_mem failded.\n")); + return FALSE; + } + } + else + { + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + for (EntryIdx= 0; pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++) + { + if(EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table*/ + { + DBGPRINT(RT_DEBUG_TRACE, ("Table is full.\n")); + return TRUE; + } + } + } + NdisMoveMemory(CountryCode, pAd->CommonCfg.CountryCode, 2); + DBGPRINT(RT_DEBUG_TRACE, ("Add channel lists {%u, %u, %u, %s, %s} to %s.\n", + inChDesp.FirstChannel, + inChDesp.NumOfCh, + inChDesp.MaxTxPwr, + (inChDesp.Geography == BOTH) ? "BOTH" : (inChDesp.Geography == IDOR) ? "IDOR" : "ODOR", + (inChDesp.DfsReq == TRUE) ? "TRUE" : "FALSE", + CountryCode)); + NdisCopyMemory(&pChDesp[EntryIdx], &inChDesp, sizeof(CH_DESP)); + pChDesp[++EntryIdx].FirstChannel = 0; + } + return TRUE; +} + +INT Set_ChannelListShow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PCH_REGION pChRegion = NULL; + UCHAR EntryIdx, CountryCode[3]={0}; + + /* Get Channel Region (CountryCode)*/ + { + INT loop = 0; + + while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((PSTRING) ChRegion[loop].CountReg, pAd->CommonCfg.CountryCode, 2) == 0) + { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + if (pChRegion == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("CountryCode is not configured or not valid\n")); + return TRUE; + } + } + + NdisMoveMemory(CountryCode, pAd->CommonCfg.CountryCode, 2); + if (pAd->CommonCfg.DfsType == MAX_RD_REGION) + pAd->CommonCfg.DfsType = pChRegion->DfsType; + DBGPRINT(RT_DEBUG_ERROR, ("=========================================\n")); + DBGPRINT(RT_DEBUG_ERROR, ("CountryCode:%s\n", CountryCode)); + DBGPRINT(RT_DEBUG_ERROR, ("DfsType:%s\n", + (pAd->CommonCfg.DfsType == JAP) ? "JAP" : + ((pAd->CommonCfg.DfsType == FCC) ? "FCC" : "CE" ))); + + if (pAd->CommonCfg.pChDesp != NULL) + { + PCH_DESP pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + for (EntryIdx = 0; pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++) + { + DBGPRINT(RT_DEBUG_ERROR, ("%u. {%3u, %2u, %2u, %s, %5s}.\n", + EntryIdx, + pChDesp[EntryIdx].FirstChannel, + pChDesp[EntryIdx].NumOfCh, + pChDesp[EntryIdx].MaxTxPwr, + (pChDesp[EntryIdx].Geography == BOTH) ? "BOTH" : (pChDesp[EntryIdx].Geography == IDOR) ? "IDOR" : "ODOR", + (pChDesp[EntryIdx].DfsReq == TRUE) ? "TRUE" : "FALSE")); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Default channel list table:\n")); + for (EntryIdx = 0; pChRegion->pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++) + { + DBGPRINT(RT_DEBUG_ERROR, ("%u. {%3u, %2u, %2u, %s, %5s}.\n", + EntryIdx, + pChRegion->pChDesp[EntryIdx].FirstChannel, + pChRegion->pChDesp[EntryIdx].NumOfCh, + pChRegion->pChDesp[EntryIdx].MaxTxPwr, + (pChRegion->pChDesp[EntryIdx].Geography == BOTH) ? "BOTH" : (pChRegion->pChDesp[EntryIdx].Geography == IDOR) ? "IDOR" : "ODOR", + (pChRegion->pChDesp[EntryIdx].DfsReq == TRUE) ? "TRUE" : "FALSE")); + } + } + DBGPRINT(RT_DEBUG_ERROR, ("=========================================\n")); + return TRUE; +} + +INT Set_ChannelListDel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR EntryIdx, TargetIdx, NumOfEntry; + PCH_REGION pChRegion = NULL; + PCH_DESP pChDesp = NULL; + TargetIdx = simple_strtol(arg, 0, 10); + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__)); + return TRUE; + } + + /* Get Channel Region (CountryCode)*/ + { + INT loop = 0; + while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((PSTRING) ChRegion[loop].CountReg, pAd->CommonCfg.CountryCode, 2) == 0) + { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + if (pChRegion == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("CountryCode is not configured or not valid\n")); + return TRUE; + } + } + + if (pAd->CommonCfg.pChDesp == NULL) + { + os_alloc_mem(pAd, &pAd->CommonCfg.pChDesp, MAX_PRECONFIG_DESP_ENTRY_SIZE*sizeof(CH_DESP)); + if (pAd->CommonCfg.pChDesp) + { + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + for (EntryIdx= 0; pChRegion->pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++) + { + if (EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table*/ + { + DBGPRINT(RT_DEBUG_TRACE, ("Table is full.\n")); + return TRUE; + } + NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP)); + } + /* Copy the NULL entry*/ + NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("os_alloc_mem failded.\n")); + return FALSE; + } + } + else + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + + if (!strcmp(arg, "default")) + { + DBGPRINT(RT_DEBUG_TRACE, ("Default table used.\n" )); + if (pAd->CommonCfg.pChDesp != NULL) + os_free_mem(NULL, pAd->CommonCfg.pChDesp); + pAd->CommonCfg.pChDesp = NULL; + pAd->CommonCfg.DfsType = MAX_RD_REGION; + } + else if (!strcmp(arg, "all")) + { + DBGPRINT(RT_DEBUG_TRACE, ("Remove all entries.\n" )); + for (EntryIdx = 0; EntryIdx < MAX_PRECONFIG_DESP_ENTRY_SIZE; EntryIdx++) + NdisZeroMemory(&pChDesp[EntryIdx], sizeof(CH_DESP)); + } + else if (TargetIdx < (MAX_PRECONFIG_DESP_ENTRY_SIZE-1)) + { + for (EntryIdx= 0; pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++) + { + if(EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table */ + { + DBGPRINT(RT_DEBUG_TRACE, ("Last entry should be NULL.\n")); + pChDesp[EntryIdx].FirstChannel = 0; + return TRUE; + } + } + NumOfEntry = EntryIdx; + if (TargetIdx >= NumOfEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("Out of table range.\n")); + return TRUE; + } + for (EntryIdx = TargetIdx; EntryIdx < NumOfEntry; EntryIdx++) + NdisCopyMemory(&pChDesp[EntryIdx], &pChDesp[EntryIdx+1], sizeof(CH_DESP)); + NdisZeroMemory(&pChDesp[EntryIdx], sizeof(CH_DESP)); /*NULL entry*/ + DBGPRINT(RT_DEBUG_TRACE, ("Entry %u deleted.\n", TargetIdx)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Entry not found.\n")); + + return TRUE; +} +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef WSC_INCLUDED +INT Set_WscGenPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscGenPinCode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscGenPinCode_Proc:: This command is from ra interface now.\n", apidx)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +{ + pWscControl = &pAd->StaCfg.WscControl; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pWscControl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__)); + return TRUE; + } + + if (pWscControl->WscEnrollee4digitPinCode) + { + pWscControl->WscEnrolleePinCodeLen = 4; + pWscControl->WscEnrolleePinCode = WscRandomGen4digitPinCode(pAd); + } + else + { + pWscControl->WscEnrolleePinCodeLen = 8; +#ifdef P2P_SSUPPORT +#endif /* P2P_SUPPORT */ + pWscControl->WscEnrolleePinCode = WscRandomGeneratePinCode(pAd, apidx); + } + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGenPinCode_Proc:: Enrollee PinCode\t\t%08u\n", pWscControl->WscEnrolleePinCode)); + + return TRUE; +} + +#ifdef BB_SOC +INT Set_WscResetPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscResetPinCode_Proc:: This command is from ra interface now.\n", apidx)); + } + + pWscControl->WscEnrolleePinCode = GenerateWpsPinCode(pAd, 0, apidx); + } +#endif // CONFIG_AP_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscResetPinCode_Proc:: Enrollee PinCode\t\t%08u\n", pWscControl->WscEnrolleePinCode)); + + return TRUE; +} +#endif + +INT Set_WscVendorPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef CONFIG_AP_SUPPORT +/* POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;*/ +/* UCHAR apidx = pObj->ioctl_if;*/ + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVendorPinCode_Proc() for apcli(%d)\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVendorPinCode_Proc() for ra%d!\n", apidx)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pWscControl = &pAd->StaCfg.WscControl; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (!pWscControl) + return FALSE; + else + return RT_CfgSetWscPinCode(pAd, arg, pWscControl); +} +#endif /* WSC_INCLUDED */ + + +#ifdef DBG +INT rx_temp_dbg = 0; + +/* + ========================================================================== + Description: + For Debug information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Debug_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG dbg; + + DBGPRINT_S(RT_DEBUG_TRACE, ("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + if( dbg <= RT_DEBUG_LOUD) + RTDebugLevel = dbg; + + DBGPRINT_S(RT_DEBUG_TRACE, ("<==%s(RTDebugLevel = %ld)\n", + __FUNCTION__, RTDebugLevel)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + For DebugFunc information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_DebugFunc_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + DBGPRINT_S(RT_DEBUG_TRACE, ("==>%s()\n", __FUNCTION__)); + RTDebugFunc = simple_strtol(arg, 0, 10); + DBGPRINT_S(RT_DEBUG_TRACE, ("Set RTDebugFunc = 0x%lx\n", RTDebugFunc)); + + return TRUE; +} +#endif + + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef RTMP_MAC_PCI + INT i, QueIdx=0; + RXD_STRUC *pRxD; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD, RxD; + TXD_STRUC *pDestTxD, TxD; +#endif /* RT_BIG_ENDIAN */ + RTMP_TX_RING *pTxRing = &pAd->TxRing[QueIdx]; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + RTMP_RX_RING *pRxRing = &pAd->RxRing[0]; + + for(i=0;iCell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + hex_dump("Tx Descriptor", (PUCHAR)pTxD, 16); + DBGPRINT(RT_DEBUG_OFF, ("pTxD->DMADONE = %x\n", pTxD->DMADONE)); + } + DBGPRINT(RT_DEBUG_OFF, ("---------------------------------------------------\n")); + for(i=0;iCell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pMgmtRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + hex_dump("Mgmt Descriptor", (PUCHAR)pTxD, 16); + DBGPRINT(RT_DEBUG_OFF, ("pMgmt->DMADONE = %x\n", pTxD->DMADONE)); + } + DBGPRINT(RT_DEBUG_OFF, ("---------------------------------------------------\n")); + for(i=0;iCell[i].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (RXD_STRUC *)pRxRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + hex_dump("Rx Descriptor", (PUCHAR)pRxD, 16); + DBGPRINT(RT_DEBUG_OFF, ("pRxD->DDONE = %x\n", pRxD->DDONE)); + } +#endif /* RTMP_MAC_PCI */ + + return TRUE; +} + +/* + ========================================================================== + Description: + Reset statistics counter + + Arguments: + pAd Pointer to our adapter + arg + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ResetStatCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n")); + + /* add the most up-to-date h/w raw counters into software counters*/ + NICUpdateRawCounters(pAd); + + NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); + +#ifdef RALINK_ATE +#ifdef RALINK_QA + pAd->ate.U2M = 0; + pAd->ate.OtherCount = 0; + pAd->ate.OtherData = 0; +#endif /* RALINK_QA */ +#endif /* RALINK_ATE */ + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + int i; + for (i=0; iMacTab.Content[i].TxBFCounters, sizeof(pAd->MacTab.Content[i].TxBFCounters)); + } +#endif /* TXBF_SUPPORT */ + + return TRUE; +} + + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen) +{ + UCHAR i=0; + + for (i=0; i 0x7E)) + return FALSE; + } + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Remove WPA Key process + + Arguments: + pAd Pointer to our adapter + pBuf Pointer to the where the key stored + + Return Value: + NDIS_SUCCESS Add key successfully + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#ifdef CONFIG_STA_SUPPORT +VOID RTMPSetDesiredRates(RTMP_ADAPTER *pAd, LONG Rates) +{ + NDIS_802_11_RATES aryRates; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); + switch (pAd->CommonCfg.PhyMode) + { + case (WMODE_A): /* A only*/ + switch (Rates) + { + case 6000000: /*6M*/ + aryRates[0] = 0x0c; /* 6M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: /*9M*/ + aryRates[0] = 0x12; /* 9M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: /*12M*/ + aryRates[0] = 0x18; /* 12M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: /*18M*/ + aryRates[0] = 0x24; /* 18M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: /*24M*/ + aryRates[0] = 0x30; /* 24M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: /*36M*/ + aryRates[0] = 0x48; /* 36M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: /*48M*/ + aryRates[0] = 0x60; /* 48M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: /*54M*/ + aryRates[0] = 0x6c; /* 54M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: /*Auto*/ + default: + aryRates[0] = 0x6c; /* 54Mbps*/ + aryRates[1] = 0x60; /* 48Mbps*/ + aryRates[2] = 0x48; /* 36Mbps*/ + aryRates[3] = 0x30; /* 24Mbps*/ + aryRates[4] = 0x24; /* 18M*/ + aryRates[5] = 0x18; /* 12M*/ + aryRates[6] = 0x12; /* 9M*/ + aryRates[7] = 0x0c; /* 6M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + case (WMODE_B | WMODE_G): /* B/G Mixed*/ + case (WMODE_B): /* B only*/ + case (WMODE_A | WMODE_B | WMODE_G): /* A/B/G Mixed*/ + default: + switch (Rates) + { + case 1000000: /*1M*/ + aryRates[0] = 0x02; + wdev->DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 2000000: /*2M*/ + aryRates[0] = 0x04; + wdev->DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 5000000: /*5.5M*/ + aryRates[0] = 0x0b; /* 5.5M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 11000000: /*11M*/ + aryRates[0] = 0x16; /* 11M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 6000000: /*6M*/ + aryRates[0] = 0x0c; /* 6M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: /*9M*/ + aryRates[0] = 0x12; /* 9M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: /*12M*/ + aryRates[0] = 0x18; /* 12M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: /*18M*/ + aryRates[0] = 0x24; /* 18M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: /*24M*/ + aryRates[0] = 0x30; /* 24M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: /*36M*/ + aryRates[0] = 0x48; /* 36M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: /*48M*/ + aryRates[0] = 0x60; /* 48M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: /*54M*/ + aryRates[0] = 0x6c; /* 54M*/ + wdev->DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: /*Auto*/ + default: + if (pAd->CommonCfg.PhyMode == WMODE_B) + { /*B Only*/ + aryRates[0] = 0x16; /* 11Mbps*/ + aryRates[1] = 0x0b; /* 5.5Mbps*/ + aryRates[2] = 0x04; /* 2Mbps*/ + aryRates[3] = 0x02; /* 1Mbps*/ + } + else + { /*(B/G) Mixed or (A/B/G) Mixed*/ + aryRates[0] = 0x6c; /* 54Mbps*/ + aryRates[1] = 0x60; /* 48Mbps*/ + aryRates[2] = 0x48; /* 36Mbps*/ + aryRates[3] = 0x30; /* 24Mbps*/ + aryRates[4] = 0x16; /* 11Mbps*/ + aryRates[5] = 0x0b; /* 5.5Mbps*/ + aryRates[6] = 0x04; /* 2Mbps*/ + aryRates[7] = 0x02; /* 1Mbps*/ + } + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + } + + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAd->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAd->CommonCfg.DesireRate[0], pAd->CommonCfg.DesireRate[1], + pAd->CommonCfg.DesireRate[2], pAd->CommonCfg.DesireRate[3], + pAd->CommonCfg.DesireRate[4], pAd->CommonCfg.DesireRate[5], + pAd->CommonCfg.DesireRate[6], pAd->CommonCfg.DesireRate[7] )); + /* Changing DesiredRate may affect the MAX TX rate we used to TX frames out*/ + MlmeUpdateTxRates(pAd, FALSE, 0); +} +#endif /* CONFIG_STA_SUPPORT */ + + +#if defined(CONFIG_STA_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) +NDIS_STATUS RTMPWPARemoveKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf) +{ + PNDIS_802_11_REMOVE_KEY pKey; + ULONG KeyIdx; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + BOOLEAN bTxKey; /* Set the key as transmit key*/ + BOOLEAN bPairwise; /* Indicate the key is pairwise key*/ + BOOLEAN bKeyRSC; /* indicate the receive SC set by KeyRSC value.*/ + /* Otherwise, it will set by the NIC.*/ + BOOLEAN bAuthenticator; /* indicate key is set by authenticator.*/ + INT i; +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT + UCHAR ifIndex; + BOOLEAN apcliEn=FALSE; + INT idx, BssIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif/*WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n")); + + pKey = (PNDIS_802_11_REMOVE_KEY) pBuf; + KeyIdx = pKey->KeyIndex & 0xff; + /* Bit 31 of Add-key, Tx Key*/ + bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE; + /* Bit 30 of Add-key PairwiseKey*/ + bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE; + /* Bit 29 of Add-key KeyRSC*/ + bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; + /* Bit 28 of Add-key Authenticator*/ + bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; + + /* 1. If bTx is TRUE, return failure information*/ + if (bTxKey == TRUE) + return(NDIS_STATUS_INVALID_DATA); + + /* 2. Check Pairwise Key*/ + if (bPairwise) + { + /* a. If BSSID is broadcast, remove all pairwise keys.*/ + /* b. If not broadcast, remove the pairwise specified by BSSID*/ + for (i = 0; i < SHARE_KEY_NUM; i++) + { +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + /*if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].SharedKey[i].BssId, pKey->BSSID)) */ + { + ifIndex = pObj->ioctl_if; + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; + DBGPRINT(RT_DEBUG_TRACE,("APCLI RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i)); + pAd->ApCfg.ApCliTab[ifIndex].SharedKey[i].KeyLen = 0; + pAd->ApCfg.ApCliTab[ifIndex].SharedKey[i].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BssIdx, (UCHAR)i); + Status = NDIS_STATUS_SUCCESS; + break; + } + } + else +#endif/*WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + { +#ifdef CONFIG_STA_SUPPORT + if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID)) + { + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i)); + pAd->SharedKey[BSS0][i].KeyLen = 0; + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i); + Status = NDIS_STATUS_SUCCESS; + break; + } +#endif/*CONFIG_STA_SUPPORT*/ + } + } + } + /* 3. Group Key*/ + else + { + /* a. If BSSID is broadcast, remove all group keys indexed*/ + /* b. If BSSID matched, delete the group key indexed.*/ + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx)); + pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx); + Status = NDIS_STATUS_SUCCESS; + } + + return (Status); +} +#endif /* defined(CONFIG_STA_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) */ + + +#ifdef CONFIG_STA_SUPPORT +/* + ======================================================================== + + Routine Description: + Remove All WPA Keys + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPWPARemoveAllKeys(RTMP_ADAPTER *pAd) +{ + UCHAR i; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", + wdev->AuthMode, wdev->WepStatus)); + /* + For WEP/CKIP/WPA-None, there is no need to remove it, since WinXP won't set it + again after Link up. And it will be replaced if user changed it. + */ + if (wdev->AuthMode < Ndis802_11AuthModeWPA || + wdev->AuthMode == Ndis802_11AuthModeWPANone) + return; + +#ifdef PCIE_PS_SUPPORT + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ + + /* set BSSID wcid entry of the Pair-wise Key table as no-security mode*/ + AsicRemovePairwiseKeyEntry(pAd, BSSID_WCID); + + /* set all shared key mode as no-security. */ + for (i = 0; i < SHARE_KEY_NUM; i++) + { + DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); + NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY)); + + AsicRemoveSharedKeyEntry(pAd, BSS0, i); + } +#ifdef PCIE_PS_SUPPORT + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ + +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ======================================================================== + Routine Description: + Change NIC PHY mode. Re-association may be necessary + + Arguments: + pAd - Pointer to our adapter + phymode - + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPSetPhyMode(RTMP_ADAPTER *pAd, ULONG phymode) +{ + INT i; + /* the selected phymode must be supported by the RF IC encoded in E2PROM*/ + + pAd->CommonCfg.PhyMode = (UCHAR)phymode; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); +#ifdef EXT_BUILD_CHANNEL_LIST + BuildChannelListEx(pAd); +#else + BuildChannelList(pAd); +#endif /* EXT_BUILD_CHANNEL_LIST */ + + /* sanity check user setting*/ + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + break; + } + + if (i == pAd->ChannelListNum) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pAd->CommonCfg.Channel = FirstChannel(pAd); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->CommonCfg.Channel = FirstChannel(pAd); +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel)); + } + + NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + switch (phymode) { + case (WMODE_B): + pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRateLen = 4; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps*/ + /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; This MODE is only FYI. not use*/ + break; + + /* + In current design, we will put supported/extended rate element in + beacon even we are 11n-only mode. + Or some 11n stations will not connect to us if we do not put + supported/extended rate element in beacon. + */ + case (WMODE_B | WMODE_G): + case (WMODE_A | WMODE_B | WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): + case (WMODE_B | WMODE_G | WMODE_GN): +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + case (WMODE_B | WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ + pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[4] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[5] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[6] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRate[1] = 0x18; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRate[2] = 0x30; /* 24 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRate[3] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRateLen = 4; + pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[4] = 12; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[5] = 18; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[6] = 24; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[7] = 36; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[8] = 48; /* 24 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[9] = 72; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[10] = 96; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[11] = 108; /* 54 mbps, in units of 0.5 Mbps*/ + break; + + case (WMODE_A): + case (WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_AN): + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): + case (WMODE_G | WMODE_GN): + case (WMODE_GN): + case (WMODE_AN): +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + case (WMODE_A | WMODE_AN | WMODE_AC): + case (WMODE_AN | WMODE_AC): + case (WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ + pAd->CommonCfg.SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 12; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[1] = 18; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[2] = 24; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[3] = 36; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[4] = 48; /* 24 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[5] = 72; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[6] = 96; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[7] = 108; /* 54 mbps, in units of 0.5 Mbps*/ + /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; This MODE is only FYI. not use*/ + break; + + default: + break; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UINT apidx; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + MlmeUpdateTxRates(pAd, FALSE, apidx); + } +#ifdef WDS_SUPPORT + for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++) + { + MlmeUpdateTxRates(pAd, FALSE, apidx + MIN_NET_DEVICE_FOR_WDS); + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + MlmeUpdateTxRates(pAd, FALSE, apidx + MIN_NET_DEVICE_FOR_APCLI); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + printk("%s: Update for STA\n", __FUNCTION__); + MlmeUpdateTxRates(pAd, FALSE, BSS0); + } +#endif /* CONFIG_STA_SUPPORT */ + + +//CFG_TODO +#ifdef RT_CFG80211_P2P_SUPPORT + NdisZeroMemory(pAd->cfg80211_ctrl.P2pSupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->cfg80211_ctrl.P2pExtRate, MAX_LEN_OF_SUPPORTED_RATES); + + pAd->cfg80211_ctrl.P2pSupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->cfg80211_ctrl.P2pSupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->cfg80211_ctrl.P2pSupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->cfg80211_ctrl.P2pSupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->cfg80211_ctrl.P2pSupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->cfg80211_ctrl.P2pSupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->cfg80211_ctrl.P2pSupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->cfg80211_ctrl.P2pSupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/ + pAd->cfg80211_ctrl.P2pSupRateLen = 8; + + pAd->cfg80211_ctrl.P2pExtRateLen = 0; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + MlmeUpdateTxRates(pAd, FALSE, MAIN_MBSSID + MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO); + + MlmeUpdateTxRates(pAd, FALSE, MAIN_MBSSID + MIN_NET_DEVICE_FOR_APCLI); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + SetCommonVHT(pAd); +#endif /* DOT11_VHT_AC */ +} + + +/* + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. + Return: + ======================================================================== +*/ +VOID RTMPAddWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry) +{ + UINT32 WCIDAttri = 0; + USHORT offset; + UCHAR IVEIV = 0; + USHORT Wcid = 0; +#ifdef CONFIG_AP_SUPPORT + BOOLEAN IEEE8021X = FALSE; +#endif /* CONFIG_AP_SUPPORT */ + + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (BssIdx >= MIN_NET_DEVICE_FOR_APCLI) + { + if (pEntry) + BssIdx -= MIN_NET_DEVICE_FOR_APCLI; + else + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: AP-Client link doesn't need to set Group WCID Attribute. \n")); + return; + } + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (BssIdx >= MIN_NET_DEVICE_FOR_WDS) + { + if (pEntry) + BssIdx = BSS0; + else + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: WDS link doesn't need to set Group WCID Attribute. \n")); + return; + } + } + else +#endif /* WDS_SUPPORT */ + { + if (BssIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for MBSSID link. \n", BssIdx)); + return; + } + } + + /* choose wcid number*/ + if (pEntry) + Wcid = pEntry->wcid; + else + GET_GroupKey_WCID(pAd, Wcid, BssIdx); + +#ifdef DOT1X_SUPPORT + if ((BssIdx < pAd->ApCfg.BssidNum) && (BssIdx < MAX_MBSSID_NUM(pAd)) && (BssIdx < HW_BEACON_MAX_NUM)) + IEEE8021X = pAd->ApCfg.MBSSID[BssIdx].wdev.IEEE8021X; +#endif /* DOT1X_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (BssIdx > BSS0) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx)); + return; + } + + /* + 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. + 2. In Infra mode, the AID:1 MUST be wcid of infra STA. + the AID:2~ assign to mesh link entry. + */ + if (pEntry) + Wcid = pEntry->wcid; + else + Wcid = MCAST_WCID; + } +#endif /* CONFIG_STA_SUPPORT */ + } + + /* Update WCID attribute table*/ + { + UINT32 wcid_attr_base = 0, wcid_attr_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + } +#endif /* RTMP_MAC */ + + offset = wcid_attr_base + (Wcid * wcid_attr_size); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + 1. Wds-links and Mesh-links always use Pair-wise key table. + 2. When the CipherAlg is TKIP, AES or the dynamic WEP is enabled, + it needs to set key into Pair-wise Key Table. + 3. The pair-wise key security mode is set NONE, it means as no security. + */ + if (pEntry && (IS_ENTRY_WDS(pEntry) || IS_ENTRY_MESH(pEntry))) + WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | PAIRWISEKEYTABLE; + else if ((pEntry) && + ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_AES) || + (CipherAlg == CIPHER_NONE) || + (IEEE8021X == TRUE))) + WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | PAIRWISEKEYTABLE; + else + WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | SHAREDKEYTABLE; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pEntry && IS_ENTRY_MESH(pEntry)) + WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; +#if defined(DOT11Z_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + else if ((pEntry) && (IS_ENTRY_DLS(pEntry) || IS_ENTRY_TDLS(pEntry)) && + ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_AES) || + (CipherAlg == CIPHER_NONE))) + WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) */ + else + WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE; + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); + } + + /* Update IV/EIV table*/ + { + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + + /* WPA mode*/ + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_AES)) + { + /* Eiv bit on. keyid always is 0 for pairwise key */ + IVEIV = (KeyIdx <<6) | 0x20; + } + else + { + /* WEP KeyIdx is default tx key. */ + IVEIV = (KeyIdx << 6); + } + + /* For key index and ext IV bit, so only need to update the position(offset+3).*/ +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE8(pAd, offset+3, IVEIV); +#endif /* RTMP_MAC_PCI */ + } + DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); + +} + +/* + ========================================================================== + Description: + Parse encryption type +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + ========================================================================== +*/ +PSTRING GetEncryptType(CHAR enc) +{ + if(enc == Ndis802_11WEPDisabled) + return "NONE"; + if(enc == Ndis802_11WEPEnabled) + return "WEP"; + if(enc == Ndis802_11TKIPEnable) + return "TKIP"; + if(enc == Ndis802_11AESEnable) + return "AES"; + if(enc == Ndis802_11TKIPAESMix) + return "TKIPAES"; +#ifdef WAPI_SUPPORT + if(enc == Ndis802_11EncryptionSMS4Enabled) + return "SMS4"; +#endif /* WAPI_SUPPORT */ + else + return "UNKNOW"; +} + +PSTRING GetAuthMode(CHAR auth) +{ + if(auth == Ndis802_11AuthModeOpen) + return "OPEN"; + if(auth == Ndis802_11AuthModeShared) + return "SHARED"; + if(auth == Ndis802_11AuthModeAutoSwitch) + return "AUTOWEP"; + if(auth == Ndis802_11AuthModeWPA) + return "WPA"; + if(auth == Ndis802_11AuthModeWPAPSK) + return "WPAPSK"; + if(auth == Ndis802_11AuthModeWPANone) + return "WPANONE"; + if(auth == Ndis802_11AuthModeWPA2) + return "WPA2"; + if(auth == Ndis802_11AuthModeWPA2PSK) + return "WPA2PSK"; + if(auth == Ndis802_11AuthModeWPA1WPA2) + return "WPA1WPA2"; + if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) + return "WPA1PSKWPA2PSK"; +#ifdef WAPI_SUPPORT + if(auth == Ndis802_11AuthModeWAICERT) + return "WAI-CERT"; + if(auth == Ndis802_11AuthModeWAIPSK) + return "WAI-PSK"; +#endif /* WAPI_SUPPORT */ + + return "UNKNOW"; +} + + +/* + ========================================================================== + Description: + Get site survey results + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) UI needs to wait 4 seconds after issue a site survey command + 2.) iwpriv ra0 get_site_survey + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +#define LINE_LEN (4+33+20+23+9+7+7+3) /* Channel+SSID+Bssid+Security+Signal+WiressMode+ExtCh+NetworkType*/ +#ifdef AIRPLAY_SUPPORT +#define IS_UNICODE_SSID_LEN (4) +#endif /* AIRPLAY_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT +#define WPS_LINE_LEN (4+5) /* WPS+DPID*/ +#endif /* WSC_STA_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT +#define DOT11R_LINE_LEN (5+9+10) /* MDId+FToverDS+RsrReqCap*/ +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +VOID RTMPCommSiteSurveyData( + IN PSTRING msg, + IN BSS_ENTRY *pBss, + IN UINT32 MsgLen) +{ + INT Rssi = 0; + UINT Rssi_Quality = 0; + NDIS_802_11_NETWORK_TYPE wireless_mode; + CHAR Ssid[MAX_LEN_OF_SSID +1]; + STRING SecurityStr[32] = {0}; + NDIS_802_11_ENCRYPTION_STATUS ap_cipher = Ndis802_11EncryptionDisabled; + NDIS_802_11_AUTHENTICATION_MODE ap_auth_mode = Ndis802_11AuthModeOpen; +#ifdef AIRPLAY_SUPPORT + BOOLEAN isUniCodeSsid = FALSE; +#endif /* AIRPLAY_SUPPORT */ + + /*Channel*/ + sprintf(msg+strlen(msg),"%-4d", pBss->Channel); + + + /*SSID*/ + NdisZeroMemory(Ssid, (MAX_LEN_OF_SSID +1)); + if (RTMPCheckStrPrintAble((PCHAR)pBss->Ssid, pBss->SsidLen)) + NdisMoveMemory(Ssid, pBss->Ssid, pBss->SsidLen); + else + { + INT idx = 0; + +#ifdef AIRPLAY_SUPPORT + isUniCodeSsid = TRUE; +#endif /* AIRPLAY_SUPPORT */ + + sprintf(Ssid, "0x"); + for (idx = 0; (idx < 15) && (idx < pBss->SsidLen); idx++) + sprintf(Ssid + 2 + (idx*2), "%02X", (UCHAR)pBss->Ssid[idx]); + } + sprintf(msg+strlen(msg),"%-33s", Ssid); + +#ifdef AIRPLAY_SUPPORT + /* IsUniCode SSID */ + if (isUniCodeSsid == TRUE) + sprintf(msg+strlen(msg),"%-4s", "Y"); + else + sprintf(msg+strlen(msg),"%-4s", "N"); +#endif /* AIRPLAY_SUPPORT */ + + /*BSSID*/ + sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ", + pBss->Bssid[0], + pBss->Bssid[1], + pBss->Bssid[2], + pBss->Bssid[3], + pBss->Bssid[4], + pBss->Bssid[5]); + + /*Security*/ + RTMPZeroMemory(SecurityStr, 32); + if ((Ndis802_11AuthModeWPA <= pBss->AuthMode) && + (pBss->AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + if (pBss->AuthMode == Ndis802_11AuthModeWPANone) + { + ap_auth_mode = pBss->AuthMode; + ap_cipher = pBss->WPA.PairCipher; + } + else if ((pBss->AuthModeAux == Ndis802_11AuthModeOpen) || (pBss->AuthModeAux == Ndis802_11AuthModeMax)) + { + ap_auth_mode = pBss->AuthMode; + if ((ap_auth_mode == Ndis802_11AuthModeWPA) || + (ap_auth_mode == Ndis802_11AuthModeWPAPSK)) + { + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + ap_cipher = pBss->WPA.PairCipher; + else + ap_cipher = Ndis802_11TKIPAESMix; + } + else if ((ap_auth_mode == Ndis802_11AuthModeWPA2) || + (ap_auth_mode == Ndis802_11AuthModeWPA2PSK)) + { + if (pBss->WPA2.PairCipherAux == Ndis802_11WEPDisabled) + ap_cipher = pBss->WPA2.PairCipher; + else + ap_cipher = Ndis802_11TKIPAESMix; + } + } + else if ((pBss->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pBss->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + if ((pBss->AuthModeAux == Ndis802_11AuthModeWPAPSK) || + (pBss->AuthModeAux == Ndis802_11AuthModeWPA2PSK)) + ap_auth_mode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + else + ap_auth_mode = pBss->AuthMode; + +#ifdef DOT11W_PMF_SUPPORT + if ((pBss->AuthMode == Ndis802_11AuthModeWPA2PSK) && + (pBss->AuthModeAux == Ndis802_11AuthModeWPA2PSK)) + ap_auth_mode = pBss->AuthMode; +#endif /* DOT11W_PMF_SUPPORT */ + + if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) + { +#ifdef DOT11W_PMF_SUPPORT + if ((pBss->AuthMode == Ndis802_11AuthModeWPA2PSK) && (pBss->AuthModeAux == Ndis802_11AuthModeWPA2PSK)) + ap_cipher = pBss->WPA2.PairCipher; + else +#endif /* DOT11W_PMF_SUPPORT */ + ap_cipher = Ndis802_11TKIPAESMix; + } + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)) + ap_cipher = pBss->WPA.PairCipher; + } + else if ((pBss->AuthMode == Ndis802_11AuthModeWPA) || + (pBss->AuthMode == Ndis802_11AuthModeWPA2)) + { + if ((pBss->AuthModeAux == Ndis802_11AuthModeWPA) || + (pBss->AuthModeAux == Ndis802_11AuthModeWPA2)) + ap_auth_mode = Ndis802_11AuthModeWPA1WPA2; + else + ap_auth_mode = pBss->AuthMode; + + if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)) + ap_cipher = pBss->WPA.PairCipher; + } + + sprintf(SecurityStr, "%s/%s", GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); + } + else + { + ap_auth_mode = pBss->AuthMode; + ap_cipher = pBss->WepStatus; + if (ap_cipher == Ndis802_11WEPDisabled) + sprintf(SecurityStr, "NONE"); + else if (ap_cipher == Ndis802_11WEPEnabled) + sprintf(SecurityStr, "WEP"); + else + sprintf(SecurityStr, "%s/%s", GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); + } + + sprintf(msg+strlen(msg), "%-23s", SecurityStr); + + /* Rssi*/ + Rssi = (INT)pBss->Rssi; + if (Rssi >= -50) + Rssi_Quality = 100; + else if (Rssi >= -80) /* between -50 ~ -80dbm*/ + Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10); + else if (Rssi >= -90) /* between -80 ~ -90dbm*/ + Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10); + else /* < -84 dbm*/ + Rssi_Quality = 0; + sprintf(msg+strlen(msg),"%-9d", Rssi_Quality); + + /* Wireless Mode*/ + wireless_mode = NetworkTypeInUseSanity(pBss); + if (wireless_mode == Ndis802_11FH || + wireless_mode == Ndis802_11DS) + sprintf(msg+strlen(msg),"%-9s", "11b"); + else if (wireless_mode == Ndis802_11OFDM5) + sprintf(msg+strlen(msg),"%-9s", "11a"); + else if (wireless_mode == Ndis802_11OFDM5_N) + sprintf(msg+strlen(msg),"%-9s", "11a/n"); + else if (wireless_mode == Ndis802_11OFDM5_AC) + sprintf(msg+strlen(msg),"%-9s", "11a/n/ac"); + else if (wireless_mode == Ndis802_11OFDM24) + sprintf(msg+strlen(msg),"%-9s", "11b/g"); + else if (wireless_mode == Ndis802_11OFDM24_N) + sprintf(msg+strlen(msg),"%-9s", "11b/g/n"); + else + sprintf(msg+strlen(msg),"%-9s", "unknow"); + + /* Ext Channel*/ + if (pBss->AddHtInfoLen > 0) + { + if (pBss->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) + sprintf(msg+strlen(msg),"%-7s", " ABOVE"); + else if (pBss->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) + sprintf(msg+strlen(msg),"%-7s", " BELOW"); + else + sprintf(msg+strlen(msg),"%-7s", " NONE"); + } + else + { + sprintf(msg+strlen(msg),"%-7s", " NONE"); + } + + /*Network Type */ + if (pBss->BssType == BSS_ADHOC) + sprintf(msg+strlen(msg),"%-3s", " Ad"); + else + sprintf(msg+strlen(msg),"%-3s", " In"); + + sprintf(msg+strlen(msg),"\n"); + + return; +} + +#ifdef CUSTOMER_DCC_FEATURE +#define BSS_LOAD_LEN (11 + 10) +#define SNR_LEN (6 + 7) +#define CHANNEL_STATS_LEN (8 + 11 + 16) +#define N_SS_Len 3 +VOID RTMPIoctlGetApTable( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UINT32 i; + BEACON_TABLE *beaconTable = NULL; + + os_alloc_mem(NULL, (UCHAR **)&beaconTable, sizeof(BEACON_TABLE)); + if (beaconTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(beaconTable, sizeof(BEACON_TABLE)); + beaconTable->Num = pAdapter->AvailableBSS.BssNr; + for(i = 0; i < beaconTable->Num; i++) + { + COPY_MAC_ADDR(beaconTable->BssTable[i].Bssid, pAdapter->AvailableBSS.BssEntry[i].Bssid); + beaconTable->BssTable[i].SsidLen = pAdapter->AvailableBSS.BssEntry[i].SsidLen; + + if(beaconTable->BssTable[i].SsidLen) + strcpy(beaconTable->BssTable[i].Ssid, pAdapter->AvailableBSS.BssEntry[i].Ssid); + + beaconTable->BssTable[i].Channel = pAdapter->AvailableBSS.BssEntry[i].Channel; + if(pAdapter->AvailableBSS.BssEntry[i].HtCapabilityLen) + beaconTable->BssTable[i].ChannelWidth = pAdapter->AvailableBSS.BssEntry[i].HtCapability.HtCapInfo.ChannelWidth + 1; + else + beaconTable->BssTable[i].ChannelWidth = 1; + + if (pAdapter->AvailableBSS.BssEntry[i].AddHtInfoLen > 0) + { + beaconTable->BssTable[i].ExtChannel = pAdapter->AvailableBSS.BssEntry[i].AddHtInfo.AddHtInfo.ExtChanOffset; + } + else + { + beaconTable->BssTable[i].ExtChannel = 0; + } +#ifdef DOT11_VHT_AC + if (pAdapter->AvailableBSS.BssEntry[i].vht_op_len > 0) { + if (pAdapter->AvailableBSS.BssEntry[i].vht_op_ie.vht_op_info.ch_width > 0) + beaconTable->BssTable[i].ChannelWidth = 3; + } +#endif + beaconTable->BssTable[i].RSSI = pAdapter->AvailableBSS.BssEntry[i].Rssi; + beaconTable->BssTable[i].SNR = (pAdapter->AvailableBSS.BssEntry[i].Snr0 + pAdapter->AvailableBSS.BssEntry[i].Snr1) / 2; + beaconTable->BssTable[i].PhyMode = NetworkTypeInUseSanity(&pAdapter->AvailableBSS.BssEntry[i]); + + if(pAdapter->AvailableBSS.BssEntry[i].HtCapabilityLen) + beaconTable->BssTable[i].NumSpatialStream = GetNumberofSpatialStreams(pAdapter->AvailableBSS.BssEntry[i].HtCapability); + else + beaconTable->BssTable[i].NumSpatialStream = 1; + } + + wrq->u.data.length = sizeof(BEACON_TABLE); + if (copy_to_user(wrq->u.data.pointer, beaconTable, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + BssTableInit(&pAdapter->AvailableBSS); + if (beaconTable != NULL) + os_free_mem(NULL, beaconTable); +} + + +VOID RTMPIoctlGetStreamType( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + + INT Status; + + NdisZeroMemory(&Status, sizeof(INT)); + + if(pAdapter->StreamingTypeStatus.VO && pAdapter->StreamingTypeStatus.VI) + Status = 4; + else if(pAdapter->StreamingTypeStatus.VO) + Status = 3; + else if (pAdapter->StreamingTypeStatus.VI) + Status = 2; + else + Status = 1; + + wrq->u.data.length = sizeof(INT); + if (copy_to_user(wrq->u.data.pointer, &Status, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +} + +UINT32 GetNumberofSpatialStreams(HT_CAPABILITY_IE htCapabilityIE) +{ + UCHAR mcsset[77] = {0}; + UCHAR nss; + UINT32 i, j, k; + UCHAR c; + UCHAR Tx_mcs_set_defined; + UCHAR Tx_mcs_set_not_equal; + // printk("%s: Debug Start \n",__func__); + +#ifdef RT_BIG_ENDIAN + nss = (0x03 & (4 >> htCapabilityIE.MCSSet[3])); + Tx_mcs_set_defined = (0x01 & (7 >> htCapabilityIE.MCSSet[3])); + Tx_mcs_set_not_equal = (0x01 & (6 >> htCapabilityIE.MCSSet[3])); + + for(i = 52; i <= 128; i++) + { + j = (i / 8); + k = (i % 8); + c = htCapabilityIE.MCSSet[j]; + c = (c & (1 << k)); + if(c !=0 ) + mcsset[i - 52] = 1; + } +#else + //printk(" %s: Little %x \n",__func__,htCapabilityIE.MCSSet[12]); + nss = (0x03 & (2 >> htCapabilityIE.MCSSet[12])); + Tx_mcs_set_defined = (0x01 & htCapabilityIE.MCSSet[12]); + Tx_mcs_set_not_equal = (0x01 & (1 >> htCapabilityIE.MCSSet[12])); + + for(i = 0; i < 77; i++) + { + j = (i / 8); + k = (i % 8); + c = htCapabilityIE.MCSSet[j]; + c = (c & (1 << k)); + // printk("%s: MCS %x i= %u j=%u k=%u c=%x \n",__func__,htCapabilityIE.MCSSet[j],i,j,k,c); + if(c !=0 ) + mcsset[i] = 1; + } +#endif + if((Tx_mcs_set_defined == 1) && (Tx_mcs_set_not_equal == 1)) + { + nss = nss + 1; + } + else /* if((Tx_mcs_set_defined == 1) && (Tx_mcs_set_not_equal == 0)) */ + { + for(i = 31; i >= 0; i--) + { + if(mcsset[i] == 1) + break; + } + nss = ((i/8) + 1); + } + return nss; +} + +VOID RTMPIoctlGetScanResults( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UINT32 i; + INT32 channel_idx; + SCAN_RESULTS *scanResult = NULL; + PCHANNELINFO pChannelInfo = &pAdapter->ChannelInfo; + + os_alloc_mem(NULL, (UCHAR **)&scanResult, sizeof(SCAN_RESULTS)); + if (scanResult == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(scanResult, sizeof(SCAN_RESULTS)); + + if(pChannelInfo->ChannelNo != 0 && pChannelInfo->GetChannelInfo) + { + channel_idx = Channel2Index (pAdapter, pChannelInfo->ChannelNo); + scanResult->cca_err_cnt = pChannelInfo->FalseCCA[channel_idx]; + scanResult->ch_busy_time = pChannelInfo->chanbusytime[channel_idx]; + scanResult->num_ap = pAdapter->ScanTab.BssNr; + + for(i = 0; i < scanResult->num_ap; i++) + { + COPY_MAC_ADDR(scanResult->BssTable[i].Bssid, pAdapter->ScanTab.BssEntry[i].Bssid); + scanResult->BssTable[i].SsidLen = pAdapter->ScanTab.BssEntry[i].SsidLen; + + if(scanResult->BssTable[i].SsidLen) + strcpy(scanResult->BssTable[i].Ssid, pAdapter->ScanTab.BssEntry[i].Ssid); + + scanResult->BssTable[i].Channel = pAdapter->ScanTab.BssEntry[i].Channel; + + if(pAdapter->ScanTab.BssEntry[i].HtCapabilityLen) + scanResult->BssTable[i].ChannelWidth = pAdapter->ScanTab.BssEntry[i].HtCapability.HtCapInfo.ChannelWidth + 1; + else + scanResult->BssTable[i].ChannelWidth = 1; + + if (pAdapter->ScanTab.BssEntry[i].AddHtInfoLen > 0) + { + scanResult->BssTable[i].ExtChannel = pAdapter->ScanTab.BssEntry[i].AddHtInfo.AddHtInfo.ExtChanOffset; + } + else + { + scanResult->BssTable[i].ExtChannel = 0; + } +#ifdef DOT11_VHT_AC + if (pAdapter->ScanTab.BssEntry[i].vht_op_len > 0) { + if (pAdapter->ScanTab.BssEntry[i].vht_op_ie.vht_op_info.ch_width > 0) + scanResult->BssTable[i].ChannelWidth = 3; + } +#endif + scanResult->BssTable[i].RSSI = pAdapter->ScanTab.BssEntry[i].Rssi; + scanResult->BssTable[i].SNR = (pAdapter->ScanTab.BssEntry[i].Snr0 + pAdapter->ScanTab.BssEntry[i].Snr1) / 2; + scanResult->BssTable[i].PhyMode = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]); + + if(pAdapter->ScanTab.BssEntry[i].HtCapabilityLen) + scanResult->BssTable[i].NumSpatialStream = GetNumberofSpatialStreams(pAdapter->ScanTab.BssEntry[i].HtCapability); + else + scanResult->BssTable[i].NumSpatialStream = 1; + } + + pChannelInfo->GetChannelInfo = 0; + } + + wrq->u.data.length = sizeof(SCAN_RESULTS); + if (copy_to_user(wrq->u.data.pointer, scanResult, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + BssTableInit(&pAdapter->ScanTab); + if (scanResult != NULL) + os_free_mem(NULL, scanResult); +} + +VOID RTMPIoctlGetRadioStatsCount( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RADIO_STATS_COUNTER radioStatsCounter; + + NdisZeroMemory(&radioStatsCounter, sizeof(RADIO_STATS_COUNTER)); + + NdisCopyMemory(&radioStatsCounter, &pAdapter->RadioStatsCounter, sizeof(RADIO_STATS_COUNTER)); + + NdisZeroMemory(&pAdapter->RadioStatsCounter, sizeof(RADIO_STATS_COUNTER)); + + wrq->u.data.length = sizeof(RADIO_STATS_COUNTER); + if (copy_to_user(wrq->u.data.pointer, &radioStatsCounter, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +} +#endif + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING msg; + INT i=0; + INT WaitCnt; + INT max_len = LINE_LEN; + BSS_ENTRY *pBss; + UINT32 TotalLen, BufLen = IW_SCAN_MAX_DATA; + BSS_TABLE *pScanTab; +#ifdef AIRPLAY_SUPPORT + UCHAR TargetSsid[MAX_LEN_OF_SSID+1]; + UCHAR TargetSsidLen = 0; +#endif /* AIRPLAY_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT + max_len += WPS_LINE_LEN; +#endif /* WSC_STA_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT + max_len += DOT11R_LINE_LEN; +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + max_len += BSS_LOAD_LEN + SNR_LEN + N_SS_Len; +#endif + +#ifdef AIRPLAY_SUPPORT + max_len += IS_UNICODE_SSID_LEN; +#endif /* AIRPLAY_SUPPORT */ + + TotalLen = sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len) + 100; +#ifdef CUSTOMER_DCC_FEATURE + TotalLen += sizeof(CHAR)*((pAdapter->ChannelListNum)* CHANNEL_STATS_LEN) + 50; +#endif + +#ifdef AIRPLAY_SUPPORT + if (wrq->u.data.length > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - INPUT SSID LEN NOT CORRECT\n")); + return; + } + + if (wrq->u.data.length > 0) + { + NdisZeroMemory(TargetSsid, sizeof(TargetSsid)); + copy_from_user(TargetSsid, wrq->u.data.pointer, wrq->u.data.length); + TargetSsidLen = strlen(TargetSsid); + DBGPRINT(RT_DEBUG_TRACE, ("Filter the ScanRes by SSID --> %s (%d)\n", TargetSsid, TargetSsidLen)); + } + + +#else + if (wrq->u.data.length == 0) + BufLen = IW_SCAN_MAX_DATA; + else + BufLen = wrq->u.data.length; +#endif /* AIRPLAY_SUPPORT */ + + os_alloc_mem(NULL, (PUCHAR *)&msg, TotalLen); + + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n")); + return; + } + + memset(msg, 0 , TotalLen); + sprintf(msg,"%s","\n"); + +#ifdef AIRPLAY_SUPPORT + sprintf(msg+strlen(msg),"%-4s%-33s%-4s%-20s%-23s%-9s%-7s%-7s%-3s\n", + "Ch", "SSID", "UN", "BSSID", "Security", "Signal(%)", "W-Mode", " ExtCH"," NT"); +#else + sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-23s%-9s%-9s%-7s%-3s\n", + "Ch", "SSID", "BSSID", "Security", "Signal(%)", "W-Mode", " ExtCH"," NT"); +#endif /* AIRPLAY_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + sprintf(msg+strlen(msg)-1,"%-11s%-10s%-6s%-7s\n", " STA_COUNT", " MED_UTIL", " SNR0", " SNR1"); + sprintf(msg+strlen(msg)-1,"%-4s\n"," Nss"); +#endif + +#ifdef WSC_INCLUDED + sprintf(msg+strlen(msg)-1,"%-4s%-5s\n", " WPS", " DPID"); +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11R_FT_SUPPORT + sprintf(msg+strlen(msg)-1,"%-5s%-9s%-10s\n", " MDId", " FToverDS", " RsrReqCap"); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + WaitCnt = 0; +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bSkipAutoScanConn = TRUE; +#endif /* CONFIG_STA_SUPPORT */ + + while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); + + pScanTab = &pAdapter->ScanTab; + BssTableSortByRssi(pScanTab,FALSE); + + for(i=0; iScanTab.BssNr ;i++) + { + pBss = &pAdapter->ScanTab.BssEntry[i]; + + if( pBss->Channel==0) + break; + + if((strlen(msg)+100 ) >= BufLen) + break; + +#ifdef AIRPLAY_SUPPORT + if (TargetSsidLen > 0) + { + if (strcmp(pBss->Ssid, TargetSsid) != 0) + continue; + } +#endif /* AIRPLAY_SUPPORT */ + + RTMPCommSiteSurveyData(msg, pBss, TotalLen); +#ifdef CUSTOMER_DCC_FEATURE + if(pBss->QbssLoad.bValid) + { + sprintf(msg+strlen(msg)-1," %-10u",pBss->QbssLoad.StaNum); + sprintf(msg+strlen(msg)," %-9u\n",pBss->QbssLoad.ChannelUtilization); + } + else + { + sprintf(msg+strlen(msg)-1,"%-11s"," NA "); + sprintf(msg+strlen(msg),"%-10s\n"," NA "); + } + sprintf(msg+strlen(msg)-1," %-6u%-6u\n", pBss->Snr0, pBss->Snr1); + if(pBss->HtCapabilityLen) + { + if(GetNumberofSpatialStreams(pBss->HtCapability)) + sprintf(msg+strlen(msg)-1," %-3u\n",GetNumberofSpatialStreams(pBss->HtCapability)); + } + else + sprintf(msg+strlen(msg)-1," %-3s\n","1"); +#endif +#ifdef WSC_INCLUDED + /*WPS*/ + if (pBss->WpsAP & 0x01) + sprintf(msg+strlen(msg)-1,"%-4s", " YES"); + else + sprintf(msg+strlen(msg)-1,"%-4s", " NO"); + + if (pBss->WscDPIDFromWpsAP == DEV_PASS_ID_PIN) + sprintf(msg+strlen(msg),"%-5s\n", " PIN"); + else if (pBss->WscDPIDFromWpsAP == DEV_PASS_ID_PBC) + sprintf(msg+strlen(msg),"%-5s\n", " PBC"); + else + sprintf(msg+strlen(msg),"%-5s\n", " "); +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11R_FT_SUPPORT + if (pBss->bHasMDIE) + { + sprintf(msg+strlen(msg)-1," %02x%02x", pBss->FT_MDIE.MdId[0], pBss->FT_MDIE.MdId[1]); + if (pBss->FT_MDIE.FtCapPlc.field.FtOverDs) + sprintf(msg+strlen(msg),"%-9s", " TRUE"); + else + sprintf(msg+strlen(msg),"%-9s", " FALSE"); + if (pBss->FT_MDIE.FtCapPlc.field.RsrReqCap) + sprintf(msg+strlen(msg),"%-10s\n", " TRUE"); + else + sprintf(msg+strlen(msg),"%-10s\n", " FALSE"); + } +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + } +#ifdef CUSTOMER_DCC_FEATURE + { + INT32 channel_idx; + PCHANNELINFO pChannelInfo = &pAdapter->ChannelInfo; + sprintf(msg+strlen(msg),"\n%s\n\n", "Channel Statics:"); + sprintf(msg+strlen(msg),"%-8s%-11s%-16s\n","Channel", "FALSE_CCA", "ChannelBusyTime"); + if(pChannelInfo->ChannelNo == 0 && pChannelInfo->GetChannelInfo) + { + for (channel_idx = 0; channel_idx < pAdapter->ChannelListNum; channel_idx++) + { + sprintf(msg+strlen(msg),"%-8u%-11u%-16u\n", pAdapter->ChannelList[channel_idx].Channel, pChannelInfo->FalseCCA[channel_idx], pChannelInfo->chanbusytime[channel_idx]); + } + } + else if(pChannelInfo->GetChannelInfo) + { + channel_idx = pChannelInfo->ChannelNo - 1; + sprintf(msg+strlen(msg),"%-8u%-11u%-16u\n", pAdapter->ChannelList[channel_idx].Channel, pChannelInfo->FalseCCA[channel_idx], pChannelInfo->chanbusytime[channel_idx]); + } + pChannelInfo->GetChannelInfo = 0; + } +#endif + +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bSkipAutoScanConn = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length)); + os_free_mem(NULL, (PUCHAR)msg); +} +#endif + + +static VOID +copy_mac_table_entry(RT_802_11_MAC_ENTRY *pDst, MAC_TABLE_ENTRY *pEntry) +{ + COPY_MAC_ADDR(pDst->Addr, &pEntry->Addr); + pDst->Aid = (UCHAR)pEntry->Aid; + pDst->Psm = pEntry->PsMode; + +#ifdef DOT11_N_SUPPORT + pDst->MimoPs = pEntry->MmpsMode; +#endif /* DOT11_N_SUPPORT */ + + /* Fill in RSSI per entry*/ + pDst->AvgRssi0 = pEntry->RssiSample.AvgRssi0; + pDst->AvgRssi1 = pEntry->RssiSample.AvgRssi1; + pDst->AvgRssi2 = pEntry->RssiSample.AvgRssi2; + + /* the connected time per entry*/ + pDst->ConnectedTime = pEntry->StaConnectTime; + + pDst->TxRate.word = pEntry->HTPhyMode.word; + pDst->LastRxRate = pEntry->LastRxRate; +} + + +VOID RTMPIoctlGetMacTableStaInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i, MacTabWCID; + UINT16 wrq_len = wrq->u.data.length; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + RT_802_11_MAC_TABLE *pMacTab = NULL; + PRT_802_11_MAC_ENTRY pDst; + MAC_TABLE_ENTRY *pEntry; + + wrq->u.data.length = 0; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + if (wrq_len < sizeof(RT_802_11_MAC_ENTRY)) + return; + if (pObj->ioctl_if >= MAX_APCLI_NUM) + return; + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].CtrlCurrState != APCLI_CTRL_CONNECTED) + return; + MacTabWCID = pAd->ApCfg.ApCliTab[pObj->ioctl_if].MacTabWCID; + if (!VALID_WCID(MacTabWCID)) + return; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + if (IS_ENTRY_APCLI(pEntry) && (pEntry->Sst == SST_ASSOC) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + RT_802_11_MAC_ENTRY MacEntry; + + pDst = &MacEntry; + pDst->ApIdx = pObj->ioctl_if; + copy_mac_table_entry(pDst, pEntry); + + wrq->u.data.length = sizeof(RT_802_11_MAC_ENTRY); + copy_to_user(wrq->u.data.pointer, pDst, wrq->u.data.length); + } + + return; + } +#endif + +#ifdef WDS_SUPPORT + if (pObj->ioctl_if_type == INT_WDS) + { + if (wrq_len < sizeof(RT_802_11_MAC_ENTRY)) + return; + if (pObj->ioctl_if >= MAX_WDS_ENTRY) + return; + if (pAd->WdsTab.WdsEntry[pObj->ioctl_if].Valid != TRUE) + return; + MacTabWCID = pAd->WdsTab.WdsEntry[pObj->ioctl_if].MacTabMatchWCID; + if (!VALID_WCID(MacTabWCID)) + return; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + if (IS_ENTRY_WDS(pEntry)) + { + RT_802_11_MAC_ENTRY MacEntry; + + pDst = &MacEntry; + pDst->ApIdx = pObj->ioctl_if; + copy_mac_table_entry(pDst, pEntry); + + wrq->u.data.length = sizeof(RT_802_11_MAC_ENTRY); + copy_to_user(wrq->u.data.pointer, pDst, wrq->u.data.length); + } + + return; + } +#endif + + if (wrq_len < sizeof(RT_802_11_MAC_TABLE)) + return; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pMacTab, sizeof(RT_802_11_MAC_TABLE)); + if (pMacTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(pMacTab, sizeof(RT_802_11_MAC_TABLE)); + for (i=0; iMacTab.Content[i]); + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + pDst = &pMacTab->Entry[pMacTab->Num]; + pDst->ApIdx = (UCHAR)pEntry->apidx; + copy_mac_table_entry(pDst, pEntry); + pMacTab->Num += 1; + } + } + + wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); + if (copy_to_user(wrq->u.data.pointer, pMacTab, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + os_free_mem(NULL, pMacTab); +} + + +#define MAC_LINE_LEN (1+14+4+4+4+4+10+10+10+6+6) /* "\n"+Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate+"\n" */ +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i; + UINT16 wrq_len = wrq->u.data.length; + RT_802_11_MAC_TABLE *pMacTab = NULL; + RT_802_11_MAC_ENTRY *pDst; + MAC_TABLE_ENTRY *pEntry; +#ifdef DBG + char *msg; +#endif + + wrq->u.data.length = 0; + + if (wrq_len < sizeof(RT_802_11_MAC_TABLE)) + return; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pMacTab, sizeof(RT_802_11_MAC_TABLE)); + if (pMacTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(pMacTab, sizeof(RT_802_11_MAC_TABLE)); + for (i=0; iMacTab.Content[i]); + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + pDst = &pMacTab->Entry[pMacTab->Num]; + pDst->ApIdx = (UCHAR)pEntry->apidx; + copy_mac_table_entry(pDst, pEntry); + pMacTab->Num += 1; + } + } + + wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); + if (copy_to_user(wrq->u.data.pointer, pMacTab, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + +#ifdef DBG + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + goto LabelOK; + } + + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-4s%-4s%-6s%-6s%-10s%-10s%-10s\n", + "MAC", "AP", "AID", "PSM", "AUTH", "CTxR", "LTxR","LDT", "RxB", "TxB"); + + for (i=0; iMacTab.Content[i]); + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) + break; + sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", PRINT_MAC(pEntry->Addr)); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->apidx); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->AuthState); + sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); + sprintf(msg+strlen(msg),"%-6d",0/*RateIdToMbps[pAd->MacTab.Content[i].HTPhyMode.word]*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d\n",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); /* ToDo*/ + + } + } + /* for compatible with old API just do the printk to console*/ + + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + os_free_mem(NULL, msg); + +LabelOK: +#endif + os_free_mem(NULL, pMacTab); +} + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +#ifdef CONFIG_AP_SUPPORT +VOID RTMPAR9IoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i; + char *msg; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-4s%-4s%-6s%-6s%-10s%-10s%-10s\n", + "MAC", "AP", "AID", "PSM", "AUTH", "CTxR", "LTxR","LDT", "RxB", "TxB"); + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) + break; + sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->apidx); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->AuthState); + sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); + sprintf(msg+strlen(msg),"%-6d",0/*RateIdToMbps[pAd->MacTab.Content[i].HTPhyMode.word]*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d\n",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); /* ToDo*/ + + } + } + /* for compatible with old API just do the printk to console*/ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlGetSTAT2( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + PMULTISSID_STRUCT pMbss; + INT apidx; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128))); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128)); + sprintf(msg,"%s","\n"); + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + pMbss=&pAd->ApCfg.MBSSID[apidx]; + + sprintf(msg+strlen(msg),"ra%d\n",apidx); + sprintf(msg+strlen(msg),"bytesTx = %llu\n",pMbss->TransmittedByteCount.QuadPart); + sprintf(msg+strlen(msg),"bytesRx = %llu\n",pMbss->ReceivedByteCount.QuadPart); + sprintf(msg+strlen(msg),"pktsTx = %lu\n",pMbss->TxCount); + sprintf(msg+strlen(msg),"pktsRx = %lu\n",pMbss->RxCount); + sprintf(msg+strlen(msg),"errorsTx = %lu\n",pMbss->TxErrorCount); + sprintf(msg+strlen(msg),"errorsRx = %lu\n",pMbss->RxErrorCount); + sprintf(msg+strlen(msg),"discardPktsTx = %lu\n",pMbss->TxDropCount); + sprintf(msg+strlen(msg),"discardPktsRx = %lu\n",pMbss->RxDropCount); + sprintf(msg+strlen(msg),"ucPktsTx = %lu\n",pMbss->ucPktsTx); + sprintf(msg+strlen(msg),"ucPktsRx = %lu\n",pMbss->ucPktsRx); + sprintf(msg+strlen(msg),"mcPktsTx = %lu\n",pMbss->mcPktsTx); + sprintf(msg+strlen(msg),"mcPktsRx = %lu\n",pMbss->mcPktsRx); + sprintf(msg+strlen(msg),"bcPktsTx = %lu\n",pMbss->bcPktsTx); + sprintf(msg+strlen(msg),"bcPktsRx = %lu\n",pMbss->bcPktsRx); + } + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} + + +VOID RTMPIoctlGetRadioDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + PMULTISSID_STRUCT pMbss; + INT status,bandwidth,ShortGI; + struct wifi_dev *wdev; + +/* msg = kmalloc(sizeof(CHAR)*(4096), MEM_ALLOC_FLAG);*/ + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(4096)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,4096); + sprintf(msg,"%s","\n"); + + + pMbss=&pAd->ApCfg.MBSSID[0]; + wdev = &pMbss->wdev; + if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + status = 0; + else + status = 1; + + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + bandwidth = 1; + else + bandwidth = 0; + + if(pAd->CommonCfg.RegTransmitSetting.field.ShortGI == GI_800) + ShortGI = 1; + else + ShortGI = 0; + + + sprintf(msg+strlen(msg),"status = %d\n",status); + sprintf(msg+strlen(msg),"channelsInUse = %d\n",pAd->ChannelListNum); + sprintf(msg+strlen(msg),"channel = %d\n",pAd->CommonCfg.Channel); + sprintf(msg+strlen(msg),"chanWidth = %d\n",bandwidth); + sprintf(msg+strlen(msg),"guardIntvl = %d\n",ShortGI); + sprintf(msg+strlen(msg),"MCS = %d\n",wdev->DesiredTransmitSetting.field.MCS); + + wrq->u.data.length = strlen(msg); + + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} +#endif/*CONFIG_AP_SUPPORT*/ +#endif/*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR mac[6], tid; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + +/* + The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ + + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = (UCHAR) simple_strtol((token+1), 0, 10); + /* tid is 0 ~ 7; Or kernel will crash in BAOriSessionSetUp() */ + if (tid > (NUM_OF_TID-1)) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nSetup BA Session: Tid = %d\n", tid)); + BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG bBADecline; + + bBADecline = simple_strtol(arg, 0, 10); + + if (bBADecline == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else if (bBADecline == 1) + { + pAd->CommonCfg.bBADecline = TRUE; + } + else + { + return FALSE; /*Invalid argument*/ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline)); + + return TRUE; +} + +INT Set_BAOriTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR mac[6], tid; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ +/* + The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + /* tid will be 0 ~ 7; Or kernel will crash in BAOriSessionTearDown() */ + if (tid > (NUM_OF_TID-1)) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", + PRINT_MAC(mac), tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nTear down Ori BA Session: Tid = %d\n", tid)); + BAOriSessionTearDown(pAd, pEntry->wcid, tid, FALSE, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BARecTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR mac[6], tid; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + /* tid will be 0 ~ 7; Or kernel will crash in BARecSessionTearDown() */ + if (tid > (NUM_OF_TID-1)) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", + PRINT_MAC(mac), tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nTear down Rec BA Session: Tid = %d\n", tid)); + BARecSessionTearDown(pAd, pEntry->wcid, tid, FALSE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG HtBw; + + HtBw = simple_strtol(arg, 0, 10); + + if (HtBw == BW_40) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + else if (HtBw == BW_20) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + else + return FALSE; /*Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); + +#ifdef DFS_ATP_SUPPORT + pAd->CommonCfg.RadarDetect.atp_set_ht_bw = TRUE; + if (pAd->CommonCfg.RadarDetect.atp_set_channel_ready) { + printk ("BW and Channel is ready\n"); + } +#endif /* DFS_ATP_SUPPORT */ + + return TRUE; +} + + +INT Set_HtMcs_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bAutoRate = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + UCHAR HtMcs = MCS_AUTO, Mcs_tmp, ValidMcs = 15; +#ifdef DOT11_VHT_AC + PSTRING mcs_str, ss_str; + UCHAR ss = 0, mcs = 0; +#endif /* DOT11_VHT_AC */ + struct wifi_dev *wdev; + +#ifdef DOT11_VHT_AC + ss_str = arg; + if ((mcs_str = rtstrchr(arg, ':'))!= NULL) + { + *mcs_str = 0; + mcs_str++; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): ss_str=%s, mcs_str=%s\n", + __FUNCTION__, ss_str, mcs_str)); + + if (strlen(ss_str) && strlen(mcs_str)) { + mcs = simple_strtol(mcs_str, 0, 10); + ss = simple_strtol(ss_str, 0, 10); + + if ((ss <= pAd->CommonCfg.TxStream) && (mcs <= 9)) + HtMcs = ((ss - 1) <<4) | mcs; + else { + HtMcs = MCS_AUTO; + ss = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s(): %dSS-MCS%d, Auto=%s\n", + __FUNCTION__, ss, mcs, + (HtMcs == MCS_AUTO && ss == 0) ? "TRUE" : "FALSE")); + Set_FixedTxMode_Proc(pAd, "VHT"); + } + } + else +#endif /* DOT11_VHT_AC */ + { +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + ValidMcs = 23; +#endif /* DOT11N_SS3_SUPPORT */ + + Mcs_tmp = simple_strtol(arg, 0, 10); + if (Mcs_tmp <= ValidMcs || Mcs_tmp == 32) + HtMcs = Mcs_tmp; + else + HtMcs = MCS_AUTO; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + + wdev->DesiredTransmitSetting.field.MCS = HtMcs; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d) for ra%d\n", + wdev->DesiredTransmitSetting.field.MCS, pObj->ioctl_if)); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + wdev = &pAd->StaCfg.wdev; + + wdev->DesiredTransmitSetting.field.MCS = HtMcs; + wdev->bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n", + wdev->DesiredTransmitSetting.field.MCS, wdev->bAutoTxRateSwitch)); + + if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX)) + { + if ((wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs <= 3) && + (wdev->DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000)); + } + else if ((wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs <= 7) && + (wdev->DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000)); + } + else + bAutoRate = TRUE; + + if (bAutoRate) + { + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + RTMPSetDesiredRates(pAd, -1); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n", + wdev->DesiredTransmitSetting.field.FixedTxMode)); + } + if (ADHOC_ON(pAd)) + return TRUE; + } +#endif /* CONFIG_STA_SUPPORT */ + + SetCommonHT(pAd); + +#ifdef WFA_VHT_PF +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT idx; + + NdisAcquireSpinLock(&pAd->MacTabLock); + for (idx = 1; idx < MAX_LEN_OF_MAC_TABLE; idx++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[idx]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->apidx == pObj->ioctl_if)) { + if ((HtMcs == MCS_AUTO) && ss == 0) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + MlmeNewTxRate(pAd, pEntry); + + pEntry->bAutoTxRateSwitch = TRUE; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (! ADAPT_RATE_TABLE(pEntry->pTable)) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pEntry->HTPhyMode.field.ShortGI = GI_800; + } + else + { + pEntry->HTPhyMode.field.MCS = pMbss->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pMbss->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + } + } + NdisReleaseSpinLock(&pAd->MacTabLock); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WFA_VHT_PF */ + + return TRUE; +} + +INT Set_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG HtGi; + + HtGi = simple_strtol(arg, 0, 10); + + if ( HtGi == GI_400) + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + else if ( HtGi == GI_800 ) + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + else + return FALSE; /* Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI)); + + return TRUE; +} + + +INT Set_HtTxBASize_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR Size; + + Size = simple_strtol(arg, 0, 10); + + if (Size <=0 || Size >=64) + { + Size = 8; + } + pAd->CommonCfg.TxBASize = Size-1; + DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size)); + + return TRUE; +} + +INT Set_HtDisallowTKIP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 1) + { + pAd->CommonCfg.HT_DisallowTKIP = TRUE; + } + else + { + pAd->CommonCfg.HT_DisallowTKIP = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtDisallowTKIP_Proc ::%s\n", + (pAd->CommonCfg.HT_DisallowTKIP == TRUE) ? "enabled" : "disabled")); + + return TRUE; +} + +INT Set_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == HTMODE_GF) + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + else if ( Value == HTMODE_MM ) + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + else + return FALSE; /*Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE)); + + return TRUE; + +} + +INT Set_HtStbc_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == STBC_USE) + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; + else if ( Value == STBC_NONE ) + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; + else + return FALSE; /*Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC)); + + return TRUE; +} + +INT Set_HtHtc_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->HTCEnable = FALSE; + else if ( Value ==1 ) + pAd->HTCEnable = TRUE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable)); + + return TRUE; +} + +INT Set_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + else if ( Value ==1 ) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + else + return FALSE; /*Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); + + return TRUE; +} + +INT Set_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value <=7) + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + else + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity)); + + return TRUE; +} + +INT Set_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + +#ifdef CONFIG_AP_SUPPORT + /* Intel IOT*/ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + Value = 64; +#endif /* CONFIG_AP_SUPPORT */ + + if (Value >=1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; + } + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + return TRUE; +} + +INT Set_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bRdg = FALSE; + else if ( Value ==1 ) + { + pAd->HTCEnable = TRUE; + pAd->CommonCfg.bRdg = TRUE; + } + else + return FALSE; /*Invalid argument*/ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg)); + + return TRUE; +} + +INT Set_HtLinkAdapt_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->bLinkAdapt = FALSE; + else if ( Value ==1 ) + { + pAd->HTCEnable = TRUE; + pAd->bLinkAdapt = TRUE; + } + else + return FALSE; /*Invalid argument*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt)); + + return TRUE; +} + +INT Set_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + pAd->CommonCfg.BACapability.field.AmsduEnable = (Value == 0) ? FALSE : TRUE; + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable)); + + return TRUE; +} + +INT Set_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + } + else if (Value == 1) + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + } + else + return FALSE; /*Invalid argument*/ + + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA)); + + return TRUE; + +} + +INT Set_HtProtect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bHTProtect = FALSE; + else if (Value == 1) + pAd->CommonCfg.bHTProtect = TRUE; + else + return FALSE; /*Invalid argument*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect)); + + return TRUE; +} + +INT Set_SendSMPSAction_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR mac[6], mode; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the mode value. +*/ + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + mode = simple_strtol((token+1), 0, 10); + if (mode > MMPS_DISABLE) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", + PRINT_MAC(mac), mode)); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nSendSMPSAction SMPS mode = %d\n", mode)); + SendSMPSAction(pAd, pEntry->wcid, mode); + } + + return TRUE; + } + + return FALSE; + + +} + +INT Set_HtMIMOPSmode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value <=3) + pAd->CommonCfg.BACapability.field.MMPSmode = Value; + else + pAd->CommonCfg.BACapability.field.MMPSmode = 3; + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode)); + + return TRUE; +} + +#ifdef CONFIG_AP_SUPPORT +/* + ========================================================================== + Description: + Set Tx Stream number + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_HtTxStream_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if ((Value <= 3) && (Value >= 1) && (Value <= pAd->Antenna.field.TxPath)) /* 3*3*/ + pAd->CommonCfg.TxStream = Value; + else + pAd->CommonCfg.TxStream = pAd->Antenna.field.TxPath; + + if ((pAd->MACVersion < RALINK_2883_VERSION) && + (pAd->CommonCfg.TxStream > 2)) + { + pAd->CommonCfg.TxStream = 2; /* only 2 TX streams for RT2860 series*/ + } + + SetCommonHT(pAd); + + APStop(pAd); + APStartUp(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtTxStream_Proc::(Tx Stream=%d)\n",pAd->CommonCfg.TxStream)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Rx Stream number + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_HtRxStream_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if ((Value <= 3) && (Value >= 1) && (Value <= pAd->Antenna.field.RxPath)) + pAd->CommonCfg.RxStream = Value; + else + pAd->CommonCfg.RxStream = pAd->Antenna.field.RxPath; + + if ((pAd->MACVersion < RALINK_2883_VERSION) && + (pAd->CommonCfg.RxStream > 2)) /* 3*3*/ + { + pAd->CommonCfg.RxStream = 2; /* only 2 RX streams for RT2860 series*/ + } + + SetCommonHT(pAd); + + APStop(pAd); + APStartUp(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRxStream_Proc::(Rx Stream=%d)\n",pAd->CommonCfg.RxStream)); + + return TRUE; +} + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT +INT Set_GreenAP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + { + pAd->ApCfg.bGreenAPActive=FALSE; + pAd->ApCfg.bGreenAPEnable = FALSE; + } + else if (Value == 1) + pAd->ApCfg.bGreenAPEnable = TRUE; + else + return FALSE; /*Invalid argument*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_GreenAP_Proc::(bGreenAPEnable=%d)\n",pAd->ApCfg.bGreenAPEnable)); + + return TRUE; +} +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT Set_ForceShortGI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->WIFItestbed.bShortGI = FALSE; + else if (Value == 1) + pAd->WIFItestbed.bShortGI = TRUE; + else + return FALSE; /*Invalid argument*/ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI)); + + return TRUE; +} + + + +INT Set_ForceGF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->WIFItestbed.bGreenField = FALSE; + else if (Value == 1) + pAd->WIFItestbed.bGreenField = TRUE; + else + return FALSE; /*Invalid argument*/ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField)); + + return TRUE; +} + +INT Set_HtMimoPs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bMIMOPSEnable = FALSE; + else if (Value == 1) + pAd->CommonCfg.bMIMOPSEnable = TRUE; + else + return FALSE; /*Invalid argument*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable)); + + return TRUE; +} + + +#ifdef DOT11N_DRAFT3 +INT Set_HT_BssCoex_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING pParam) +{ + UCHAR bBssCoexEnable = simple_strtol(pParam, 0, 10); + + pAd->CommonCfg.bBssCoexEnable = ((bBssCoexEnable == 1) ? TRUE: FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("Set bBssCoexEnable=%d!\n", pAd->CommonCfg.bBssCoexEnable)); + + if ((pAd->CommonCfg.bBssCoexEnable == FALSE) + && pAd->CommonCfg.bRcvBSSWidthTriggerEvents) + { + /* switch back 20/40 */ + DBGPRINT(RT_DEBUG_TRACE, ("Set bBssCoexEnable: Switch back 20/40. \n")); + pAd->CommonCfg.bRcvBSSWidthTriggerEvents = FALSE; + 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; + } + } + return TRUE; +} + + +INT Set_HT_BssCoexApCntThr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING pParam) +{ + pAd->CommonCfg.BssCoexApCntThr = simple_strtol(pParam, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set BssCoexApCntThr=%d!\n", pAd->CommonCfg.BssCoexApCntThr)); + + return TRUE; +} +#endif /* DOT11N_DRAFT3 */ + +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC +INT Set_VhtBw_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + ULONG vht_cw; + UCHAR cent_ch; + vht_cw = simple_strtol(arg, 0, 10); + + + if (vht_cw == VHT_BW_80) + pAd->CommonCfg.vht_bw = VHT_BW_80; + else + pAd->CommonCfg.vht_bw = VHT_BW_2040; + + if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + goto direct_done; + + SetCommonHT(pAd); + if(pAd->CommonCfg.BBPCurrentBW == BW_80) + cent_ch = pAd->CommonCfg.vht_cent_ch; + else + cent_ch = pAd->CommonCfg.CentralChannel; + + AsicSwitchChannel(pAd, cent_ch, FALSE); + AsicLockChannel(pAd, cent_ch); + + DBGPRINT(RT_DEBUG_TRACE, ("BW_%s, PrimaryChannel(%d), %s CentralChannel = %d, apply it immediately\n", + (pAd->CommonCfg.BBPCurrentBW == BW_80 ? "80": + (pAd->CommonCfg.BBPCurrentBW == BW_40 ? "40" : + "20")), + pAd->CommonCfg.Channel, + (pAd->CommonCfg.BBPCurrentBW == BW_80 ? "VHT" : "HT"), cent_ch)); + +direct_done: + DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtBw_Proc::(VHT_BW=%d)\n", pAd->CommonCfg.vht_bw)); + +#ifdef DFS_ATP_SUPPORT + pAd->CommonCfg.RadarDetect.atp_set_vht_bw = TRUE; + if (pAd->CommonCfg.RadarDetect.atp_set_channel_ready) { + printk ("BW and Channel is ready\n"); + } +#endif /* DFS_ATP_SUPPORT */ + + return TRUE; +} + + +INT set_VhtBwSignal_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG bw_signal = simple_strtol(arg, 0, 10); + + if (bw_signal <= 2) + pAd->CommonCfg.vht_bw_signal = bw_signal; + else + pAd->CommonCfg.vht_bw_signal = BW_SIGNALING_DISABLE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vht_bw_signal=%d(%s)\n", + __FUNCTION__, pAd->CommonCfg.vht_bw_signal, + (pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_DYNAMIC ? "Dynamic" : + (pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_STATIC ? "Static" : "Disable")))); + + return TRUE; +} + + +INT Set_VhtStbc_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == STBC_USE) + pAd->CommonCfg.vht_stbc = STBC_USE; + else if ( Value == STBC_NONE ) + pAd->CommonCfg.vht_stbc = STBC_NONE; + else + return FALSE; /*Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtStbc_Proc::(VhtStbc=%d)\n", pAd->CommonCfg.vht_stbc)); + + return TRUE; +} + +INT Set_VhtDisallowNonVHT_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bNonVhtDisallow = FALSE; + else + pAd->CommonCfg.bNonVhtDisallow = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtDisallowNonVHT_Proc::(bNonVhtDisallow=%d)\n", pAd->CommonCfg.bNonVhtDisallow)); + + return TRUE; +} +#endif /* DOT11_VHT_AC */ + + +#ifdef ETH_CONVERT_SUPPORT +INT Set_EthConvertMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + /* + Dongle mode: it means use our default MAC address to connect to AP, and + support multiple internal PCs connect to Internet via this default MAC + Clone mode : it means use one specific MAC address to connect to remote AP, and + just the node who owns the MAC address can connect to Internet. + Hybrid mode: it means use some specific MAC address to connecto to remote AP, and + support mulitple internal PCs connect to Internet via this specified MAC address. + */ + if (rtstrcasecmp(arg, "dongle") == TRUE) + { + pAd->EthConvert.ECMode = ETH_CONVERT_MODE_DONGLE; + NdisMoveMemory(&pAd->EthConvert.EthCloneMac[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + pAd->EthConvert.CloneMacVaild = TRUE; + } + else if (rtstrcasecmp(arg, "clone") == TRUE) + { + pAd->EthConvert.ECMode = ETH_CONVERT_MODE_CLONE; + pAd->EthConvert.CloneMacVaild = FALSE; + } + else if (rtstrcasecmp(arg, "hybrid") == TRUE) + { + pAd->EthConvert.ECMode = ETH_CONVERT_MODE_HYBRID; + pAd->EthConvert.CloneMacVaild = FALSE; + } + else + { + pAd->EthConvert.ECMode = ETH_CONVERT_MODE_DISABLE; + pAd->EthConvert.CloneMacVaild = FALSE; + } + pAd->EthConvert.macAutoLearn = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_EthConvertMode_Proc(): EthConvertMode=%d!\n", pAd->EthConvert.ECMode)); + + return TRUE; +} + + +INT Set_EthCloneMac_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; + extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; + + /* + If the input is the zero mac address, it means use our default(from EEPROM) MAC address as out-going + MAC address. + If the input is the broadcast MAC address, it means use the source MAC of first packet forwarded by + our device as the out-going MAC address. + If the input is any other specific valid MAC address, use it as the out-going MAC address. + */ + + pAd->EthConvert.macAutoLearn = FALSE; + if (strlen(arg) == 0) + { + NdisZeroMemory(&pAd->EthConvert.EthCloneMac[0], MAC_ADDR_LEN); + goto done; + } + + if (rtstrmactohex(arg, (PSTRING) &pAd->EthConvert.EthCloneMac[0]) == FALSE) + goto fail; + +done: + DBGPRINT(RT_DEBUG_TRACE, ("Set_EthCloneMac_Proc(): CloneMac = %02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->EthConvert.EthCloneMac[0], pAd->EthConvert.EthCloneMac[1], pAd->EthConvert.EthCloneMac[2], + pAd->EthConvert.EthCloneMac[3], pAd->EthConvert.EthCloneMac[4], pAd->EthConvert.EthCloneMac[5])); + + if (NdisEqualMemory(&pAd->EthConvert.EthCloneMac[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Use our default Mac address for cloned MAC!\n")); + NdisMoveMemory(&pAd->EthConvert.EthCloneMac[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + pAd->EthConvert.CloneMacVaild = TRUE; + } + else if (NdisEqualMemory(&pAd->EthConvert.EthCloneMac[0], &BROADCAST_ADDR[0], MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Use first frowarded Packet's source Mac for cloned MAC!\n")); + NdisMoveMemory(&pAd->EthConvert.EthCloneMac[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + pAd->EthConvert.CloneMacVaild = FALSE; + pAd->EthConvert.macAutoLearn = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Use user assigned spcific Mac address for cloned MAC!\n")); + pAd->EthConvert.CloneMacVaild = TRUE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_EthCloneMac_Proc(): After ajust, CloneMac = %02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->EthConvert.EthCloneMac[0], pAd->EthConvert.EthCloneMac[1], pAd->EthConvert.EthCloneMac[2], + pAd->EthConvert.EthCloneMac[3], pAd->EthConvert.EthCloneMac[4], pAd->EthConvert.EthCloneMac[5])); + + return TRUE; + +fail: + DBGPRINT(RT_DEBUG_ERROR, ("Set_EthCloneMac_Proc: wrong Mac Address format or length!\n")); + NdisMoveMemory(&pAd->EthConvert.EthCloneMac[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + + return FALSE; + +} +#endif /* ETH_CONVERT_SUPPORT */ + +INT Set_FixedTxMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* CONFIG_AP_SUPPORT */ + INT fix_tx_mode = RT_CfgSetFixedTxPhyMode(arg); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + wdev = &pAd->StaCfg.wdev; +#endif /* CONFIG_STA_SUPPORT */ + + if (wdev) + wdev->DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():(FixedTxMode=%d)\n", + __FUNCTION__, fix_tx_mode)); + + return TRUE; +} + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + +#ifdef RTMP_MAC_PCI + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) +#endif /* RTMP_MAC_PCI */ + { + DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n")); + return FALSE; + } + + if (Value == 0) + pAd->OpMode = OPMODE_STA; + else if (Value == 1) + pAd->OpMode = OPMODE_AP; + else + return FALSE; /*Invalid argument*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode")); + + return TRUE; +} +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE +/* ---------------------- DEBUG QUEUE ------------------------*/ + +#define DBQ_LENGTH 512 +#define DBQ_DATA_LENGTH 8 + +/* Define to include TX and RX HT Control field in log */ +/* #define DBQ_INCLUDE_HTC */ + +typedef +struct { + UCHAR type; /* type of data*/ + ULONG timestamp; /* sec/usec timestamp from gettimeofday*/ + UCHAR data[DBQ_DATA_LENGTH]; /* data*/ +} DBQUEUE_ENTRY; + +/* Type field definitions */ +#define DBQ_TYPE_EMPTY 0 +#define DBQ_TYPE_TXWI 0x70 /* TXWI*/ +#define DBQ_TYPE_TXHDR 0x72 /* TX Header*/ +#define DBQ_TYPE_TXFIFO 0x73 /* TX Stat FIFO*/ +#define DBQ_TYPE_RXWI 0x78 /* RXWI uses 0x78 to 0x7A for 5 longs*/ +#define DBQ_TYPE_RXHDR 0x7B /* RX Header*/ +#define DBQ_TYPE_TXQHTC 0x7c /* RX Qos+HT Control field*/ +#define DBQ_TYPE_RXQHTC 0x7d /* RX Qos+HT Control field */ +#define DBQ_TYPE_RALOG 0x7e /* RA Log */ + +#define DBQ_INIT_SIG 0x4442484E /* 'DBIN' - dbqInit initialized flag*/ +#define DBQ_ENA_SIG 0x4442454E /* 'DBEN' - dbqEnable enabled flag*/ + +static DBQUEUE_ENTRY dbQueue[DBQ_LENGTH]; +static ULONG dbqTail=0; +static ULONG dbqEnable=0; +static ULONG dbqInit=0; + +/* dbQueueInit - initialize Debug Queue variables and clear the queue*/ +void dbQueueInit(void) +{ + int i; + + for (i=0; i=DBQ_LENGTH) + dbQueueInit(); + + oldTail = &dbQueue[dbqTail]; + + /* Advance tail and mark as empty*/ + if (dbqTail >= DBQ_LENGTH-1) + dbqTail = 0; + else + dbqTail++; + dbQueue[dbqTail].type = DBQ_TYPE_EMPTY; + + /* Enqueue data*/ + oldTail->type = type; + do_gettimeofday(&tval); + oldTail->timestamp = tval.tv_sec*1000000L + tval.tv_usec; + memcpy(oldTail->data, data, DBQ_DATA_LENGTH); +} + +void dbQueueEnqueueTxFrame(UCHAR *pTxWI, UCHAR *pHeader_802_11) +{ + dbQueueEnqueue(DBQ_TYPE_TXWI, pTxWI); + + /* 802.11 Header */ + if (pHeader_802_11 != NULL) { + dbQueueEnqueue(DBQ_TYPE_TXHDR, pHeader_802_11); +#ifdef DBQ_INCLUDE_HTC + /* Qos+HT Control field */ + if ((pHeader_802_11[0] & 0x08) && (pHeader_802_11[1] & 0x80)) + dbQueueEnqueue(DBQ_TYPE_TXQHTC, pHeader_802_11+24); +#endif /* DBQ_INCLUDE_HTC */ + } +} + +void dbQueueEnqueueRxFrame(UCHAR *pRxWI, UCHAR *pHeader_802_11, ULONG flags) +{ + /* Ignore Beacons if disabled */ + if ((flags & DBF_DBQ_NO_BCN) && (pHeader_802_11[0] & 0xfc)==0x80) + return; + + /* RXWI */ + dbQueueEnqueue(DBQ_TYPE_RXWI, pRxWI); + if (flags & DBF_DBQ_RXWI_FULL) { + dbQueueEnqueue(DBQ_TYPE_RXWI+1, pRxWI+8); + dbQueueEnqueue(DBQ_TYPE_RXWI+2, pRxWI+16); + } + + /* 802.11 Header */ + dbQueueEnqueue(DBQ_TYPE_RXHDR, (UCHAR *)pHeader_802_11); + +#ifdef DBQ_INCLUDE_HTC + /* Qos+HT Control field */ + if ((pHeader_802_11[0] & 0x08) && + (pHeader_802_11[1] & 0x80)) + dbQueueEnqueue(DBQ_TYPE_RXQHTC, pHeader_802_11+24); +#endif /* DBQ_INCLUDE_HTC */ +} + + +/* dbQueueDisplayPhy - Display PHY rate */ +static void dbQueueDisplayPHY(USHORT phyRate) +{ + static CHAR *mode[4] = {" C", "oM","mM", "gM"}; + + DBGPRINT(RT_DEBUG_OFF, ("%2s%02d %c%c%c%c", + //(phyRate>>8) & 0xFF, phyRate & 0xFF, + mode[(phyRate>>14) & 0x3], // Mode: c, o, m, g + phyRate & 0x7F, // MCS + (phyRate & 0x0100)? 'S': 'L', // Guard Int: S or L + (phyRate & 0x0080)? '4': '2', // BW: 4 or 2 + (phyRate & 0x0200)? 'S': 's', // STBC: S or s + (phyRate & 0x2000)? 'I': ((phyRate & 0x800)? 'E': '_') // Beamforming: E or I or _ + ) ); +} + +/* dbQueueDump - dump contents of debug queue*/ +static void dbQueueDump( + IN PRTMP_ADAPTER pAd, + BOOLEAN decode) +{ + DBQUEUE_ENTRY *oldTail; + int i, origMCS, succMCS; + ULONG lastTimestamp=0; + BOOLEAN showTimestamp; + USHORT phyRate; + + if (dbqInit!=DBQ_INIT_SIG || dbqTail>=DBQ_LENGTH) + return; + + oldTail = &dbQueue[dbqTail]; + + for (i=0; i= &dbQueue[DBQ_LENGTH]) + oldTail = dbQueue; + + /* Skip empty entries*/ + if (oldTail->type == DBQ_TYPE_EMPTY) + continue; + + showTimestamp = FALSE; + + switch (oldTail->type) { + case 0x70: /* TXWI - 2 longs, MSB to LSB */ + case 0x78: /* RXWI - 2 longs, MSB to LSB */ + showTimestamp = TRUE; + + if (decode && oldTail->type==0x70) { + DBGPRINT(RT_DEBUG_OFF, ("\nTxWI ") ); + dbQueueDisplayPHY(oldTail->data[3]*256 + oldTail->data[2]); + DBGPRINT(RT_DEBUG_OFF, ("%c s=%03X %02X %s-", + (oldTail->data[0] & 0x10)? 'A': '_', // AMPDU + (oldTail->data[7]*256 + oldTail->data[6]) & 0xFFF, // Size + oldTail->data[5], // WCID + (oldTail->data[4] & 0x01)? "AK": "NA" )); // ACK/NACK + } + else if (decode && oldTail->type==0x78) { + DBGPRINT(RT_DEBUG_OFF, ("\nRxWI ") ); + dbQueueDisplayPHY(oldTail->data[7]*256 + oldTail->data[6]); + DBGPRINT(RT_DEBUG_OFF, (" s=%03X %02X %02X%01X-", + (oldTail->data[3]*256 + oldTail->data[2]) & 0xFFF, // Size + oldTail->data[0], // WCID + oldTail->data[5], oldTail->data[4]>>4 )); // Seq Number + } + else + DBGPRINT(RT_DEBUG_OFF, ("\n%cxWI %02X%02X %02X%02X-%02X%02X %02X%02X----", + oldTail->type==0x70? 'T': 'R', + oldTail->data[3], oldTail->data[2], oldTail->data[1], oldTail->data[0], + oldTail->data[7], oldTail->data[6], oldTail->data[5], oldTail->data[4]) ); + break; + + case 0x79: /* RXWI - next 2 longs, MSB to LSB */ + if (decode) { + DBGPRINT(RT_DEBUG_OFF, ("Rx2 %2d %2d %2d S:%d %d %d ", + ConvertToRssi(pAd, (CHAR)oldTail->data[0], RSSI_0), + ConvertToRssi(pAd, (CHAR)oldTail->data[1], RSSI_1), + ConvertToRssi(pAd, (CHAR)oldTail->data[2], RSSI_2), + (oldTail->data[4]*3 + 8)/16, + (oldTail->data[5]*3 + 8)/16, + (oldTail->data[6]*3 + 8)/16) ); + } + else + DBGPRINT(RT_DEBUG_OFF, ("Rx2 %02X%02X %02X%02X-%02X%02X %02X%02X ", + oldTail->data[3], oldTail->data[2], oldTail->data[1], oldTail->data[0], + oldTail->data[7], oldTail->data[6], oldTail->data[5], oldTail->data[4]) ); + break; + +#ifdef RTMP_RBUS_SUPPORT +#endif /* RTMP_RBUS_SUPPORT */ + + case 0x7c: /* TX HTC+QoS, 6 bytes, MSB to LSB */ + case 0x7d: /* RX HTC+QoS, 6 bytes, MSB to LSB */ + DBGPRINT(RT_DEBUG_OFF, ("%cxHTC H:%02X%02X%02X%02X Q:%02X%02X ", + oldTail->type==0x7c? 'T': 'R', + oldTail->data[5], oldTail->data[4], oldTail->data[3], oldTail->data[2], + oldTail->data[1], oldTail->data[0]) ); + break; + + case 0x72: /* Tx 802.11 header, MSB to LSB, translate type/subtype*/ + case 0x7b: /* Rx*/ + { + UCHAR tCode; + struct _typeTableEntry { + UCHAR code; /* Type/subtype*/ + CHAR str[4]; + } *pTab; + static struct _typeTableEntry typeTable[] = { + {0x00, "mARq"}, {0x01, "mARp"}, {0x02, "mRRq"}, {0x03, "mRRp"}, + {0x04, "mPRq"}, {0x05, "mPRp"}, {0x08, "mBcn"}, {0x09, "mATI"}, + {0x0a, "mDis"}, {0x0b, "mAut"}, {0x0c, "mDAu"}, {0x0d, "mAct"}, + {0x0e, "mANA"}, + {0x17, "cCWr"}, {0x18, "cBAR"}, {0x19, "cBAc"}, {0x1a, "cPSP"}, + {0x1b, "cRTS"}, {0x1c, "cCTS"}, {0x1d, "cACK"}, {0x1e, "cCFE"}, + {0x1f, "cCEA"}, + {0x20, "dDat"}, {0x21, "dDCA"}, {0x22, "dDCP"}, {0x23, "dDAP"}, + {0x24, "dNul"}, {0x25, "dCFA"}, {0x26, "dCFP"}, {0x27, "dCAP"}, + {0x28, "dQDa"}, {0x29, "dQCA"}, {0x2a, "dQCP"}, {0x2b, "dQAP"}, + {0x2c, "dQNu"}, {0x2e, "dQNP"}, {0x2f, "dQNA"}, + {0xFF, "RESV"}}; + + tCode = ((oldTail->data[0]<<2) & 0x30) | ((oldTail->data[0]>>4) & 0xF); + for (pTab=typeTable; pTab->code!=0xFF; pTab++) { + if (pTab->code == tCode) + break; + } + + DBGPRINT(RT_DEBUG_OFF, ("%cxH %c%c%c%c [%02X%02X %02X%02X] \n", + oldTail->type==0x72? 'T': 'R', + pTab->str[0], pTab->str[1], pTab->str[2], pTab->str[3], + oldTail->data[3], oldTail->data[2], oldTail->data[1], oldTail->data[0]) ); + } + break; + + case 0x73: /* TX STAT FIFO*/ + showTimestamp = TRUE; + + /* origMCS is limited to 4 bits. Check for case of MCS16 to 23*/ + origMCS = (oldTail->data[0]>>1) & 0xF; + succMCS = (oldTail->data[2] & 0x7F); + if (succMCS>origMCS && origMCS<8) + origMCS += 16; + phyRate = (oldTail->data[3]<<8) + oldTail->data[2]; + + DBGPRINT(RT_DEBUG_OFF, ("TxFI %02X%02X%02X%02X=%c%c%c%c%c M%02d/%02d%c%c", + oldTail->data[3], oldTail->data[2], + oldTail->data[1], oldTail->data[0], + (phyRate & 0x0100)? 'S': 'L', /* Guard Int: S or L */ + (phyRate & 0x0080)? '4': '2', /* BW: 4 or 2 */ + (phyRate & 0x0200)? 'S': 's', /* STBC: S or s */ + (phyRate & 0x2000)? 'I': ((phyRate & 0x0800)? 'E': '_'), /* Beamforming: E or I or _ */ + (oldTail->data[0] & 0x40)? 'A': '_', /* Aggregated: A or _ */ + succMCS, origMCS, /* MCS: / */ + succMCS==origMCS? ' ': '*', /* Retry: '*' if MCS doesn't match */ + (oldTail->data[0] & 0x20)? ' ': 'F') ); /* Success/Fail _ or F */ + break; + case 0x7E: /* RA Log info */ + { + struct {USHORT phy; USHORT per; USHORT tp; USHORT bfPer;} *p = (void*)(oldTail->data); + DBGPRINT(RT_DEBUG_OFF, ("RALog %02X%02X %d %d %d ", + (p->phy>>8) & 0xFF, p->phy & 0xFF, p->per, p->tp, p->bfPer) ); + } + break; + + default: + DBGPRINT(RT_DEBUG_OFF, ("%02X %02X%02X %02X%02X %02X%02X %02X%02X ", oldTail->type, + oldTail->data[0], oldTail->data[1], oldTail->data[2], oldTail->data[3], + oldTail->data[4], oldTail->data[5], oldTail->data[6], oldTail->data[7]) ); + break; + } + + if (showTimestamp) + { + ULONG t = oldTail->timestamp; + ULONG dt = oldTail->timestamp-lastTimestamp; + + DBGPRINT(RT_DEBUG_OFF, ("%lu.%06lu ", t/1000000L, t % 1000000L) ); + + if (dt>999999L) + DBGPRINT(RT_DEBUG_OFF, ("+%lu.%06lu s\n", dt/1000000L, dt % 1000000L) ); + else + DBGPRINT(RT_DEBUG_OFF, ("+%lu us\n", dt) ); + lastTimestamp = oldTail->timestamp; + } + } +} + +/* + Set_DebugQueue_Proc - Control DBQueue + iwpriv ra0 set DBQueue=dd. + dd: 0=>disable, 1=>enable, 2=>dump, 3=>clear, 4=>dump & decode +*/ +INT Set_DebugQueue_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG argValue = simple_strtol(arg, 0, 10); + + switch (argValue) { + case 0: + dbqEnable = 0; + break; + case 1: + dbqEnable = DBQ_ENA_SIG; + break; + case 2: + dbQueueDump(pAd, FALSE); + break; + case 3: + dbQueueInit(); + break; + case 4: + dbQueueDump(pAd, TRUE); + break; + default: + return FALSE; + } + + return TRUE; +} +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT +/* + ======================================================================== + Routine Description: + Set the enable/disable the stream mode + + Arguments: + 1: enable for 1SS + 2: enable for 2SS + 3: enable for 1SS and 2SS + 0: disable + + Notes: + Currently only support 1SS + ======================================================================== +*/ +INT Set_StreamMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 streamWord, reg, regAddr; + + if (pAd->chipCap.FlgHwStreamMode == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("chip not supported feature\n")); + return FALSE; + } + + pAd->CommonCfg.StreamMode = (simple_strtol(arg, 0, 10) & 0x3); + DBGPRINT(RT_DEBUG_TRACE, ("%s():StreamMode=%d\n", __FUNCTION__, pAd->CommonCfg.StreamMode)); + + streamWord = StreamModeRegVal(pAd); + for (regAddr = TX_CHAIN_ADDR0_H; regAddr <= TX_CHAIN_ADDR3_H; regAddr += 8) + { + RTMP_IO_READ32(pAd, regAddr, ®); + reg &= (~0x000F0000); + RTMP_IO_WRITE32(pAd, regAddr, streamWord | reg); + } + + return TRUE; +} + + +INT Set_StreamModeMac_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return FALSE; +} + + +INT Set_StreamModeMCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.StreamModeMCS = simple_strtol(arg, 0, 16); + DBGPRINT(RT_DEBUG_TRACE, ("%s():StreamModeMCS=%02X\n", + __FUNCTION__, pAd->CommonCfg.StreamModeMCS)); + + return TRUE; +} +#endif /* STREAM_MODE_SUPPORT */ + + +#ifdef PRE_ANT_SWITCH +/* + Set_PreAntSwitch_Proc - enable/disable Preamble Antenna Switch + usage: iwpriv ra0 set PreAntSwitch=[0 | 1] +*/ +INT Set_PreAntSwitch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.PreAntSwitch = simple_strtol(arg, 0, 10)!=0; + DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitch=%d)\n", + __FUNCTION__, pAd->CommonCfg.PreAntSwitch)); + return TRUE; +} + + +/* + Set_PreAntSwitchRSSI_Proc - set Preamble Antenna Switch RSSI threshold + usage: iwpriv ra0 set PreAntSwitchRSSI= +*/ +INT Set_PreAntSwitchRSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.PreAntSwitchRSSI = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitchRSSI=%d)\n", + __FUNCTION__, pAd->CommonCfg.PreAntSwitchRSSI)); + return TRUE; +} + +/* + Set_PreAntSwitchTimeout_Proc - set Preamble Antenna Switch Timeout threshold + usage: iwpriv ra0 set PreAntSwitchTimeout=disabled> +*/ +INT Set_PreAntSwitchTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.PreAntSwitchTimeout = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitchTimeout=%d)\n", + __FUNCTION__, pAd->CommonCfg.PreAntSwitchTimeout)); + return TRUE; +} +#endif /* PRE_ANT_SWITCH */ + + + + +#ifdef CFO_TRACK +/* + Set_CFOTrack_Proc - enable/disable CFOTrack + usage: iwpriv ra0 set CFOTrack=[0..8] +*/ +INT Set_CFOTrack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.CFOTrack = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():(CFOTrack=%d)\n", + __FUNCTION__, pAd->CommonCfg.CFOTrack)); + return TRUE; +} +#endif /* CFO_TRACK */ + + +#ifdef DBG_CTRL_SUPPORT +INT Set_DebugFlags_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.DebugFlags = simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DebugFlags_Proc::(DebugFlags=%02lX)\n", pAd->CommonCfg.DebugFlags)); + return TRUE; +} +#endif /* DBG_CTRL_SUPPORT */ + + + + + + +INT Set_LongRetryLimit_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + return TRUE; +} + +INT Set_ShortRetryLimit_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + return TRUE; +} + +INT Set_AutoFallBack_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return RT_CfgSetAutoFallBack(pAdapter, arg); +} + + + +PSTRING RTMPGetRalinkAuthModeStr( + IN NDIS_802_11_AUTHENTICATION_MODE authMode) +{ + switch(authMode) + { + case Ndis802_11AuthModeOpen: + return "OPEN"; + case Ndis802_11AuthModeWPAPSK: + return "WPAPSK"; + case Ndis802_11AuthModeShared: + return "SHARED"; + case Ndis802_11AuthModeAutoSwitch: + return "WEPAUTO"; + case Ndis802_11AuthModeWPA: + return "WPA"; + case Ndis802_11AuthModeWPA2: + return "WPA2"; + case Ndis802_11AuthModeWPA2PSK: + return "WPA2PSK"; + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + return "WPAPSKWPA2PSK"; + case Ndis802_11AuthModeWPA1WPA2: + return "WPA1WPA2"; + case Ndis802_11AuthModeWPANone: + return "WPANONE"; + default: + return "UNKNOW"; + } +} + +PSTRING RTMPGetRalinkEncryModeStr( + IN USHORT encryMode) +{ + switch(encryMode) + { + case Ndis802_11WEPDisabled: + return "NONE"; + case Ndis802_11WEPEnabled: + return "WEP"; + case Ndis802_11TKIPEnable: + return "TKIP"; + case Ndis802_11AESEnable: + return "AES"; + case Ndis802_11TKIPAESMix: + return "TKIPAES"; + default: + return "UNKNOW"; + } +} + + +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + UCHAR ssid_str[33]; + + + NdisZeroMemory(&ssid_str[0], 33); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + NdisMoveMemory(&ssid_str[0], + pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, + pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NdisMoveMemory(&ssid_str[0], + pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen); + } +#endif /* CONFIG_STA_SUPPORT */ + + snprintf(pBuf, BufLen, "\t%s", ssid_str); + return 0; +} + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + + switch(pAd->CommonCfg.PhyMode) + { + case (WMODE_B | WMODE_G): + snprintf(pBuf, BufLen, "\t11B/G"); + break; + case (WMODE_B): + snprintf(pBuf, BufLen, "\t11B"); + break; + case (WMODE_A): + snprintf(pBuf, BufLen, "\t11A"); + break; + case (WMODE_A | WMODE_B | WMODE_G): + snprintf(pBuf, BufLen, "\t11A/B/G"); + break; + case (WMODE_G): + snprintf(pBuf, BufLen, "\t11G"); + break; +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): + snprintf(pBuf, BufLen, "\t11A/B/G/N"); + break; + case (WMODE_GN): + snprintf(pBuf, BufLen, "\t11N only with 2.4G"); + break; + case (WMODE_G | WMODE_GN): + snprintf(pBuf, BufLen, "\t11G/N"); + break; + case (WMODE_A | WMODE_AN): + snprintf(pBuf, BufLen, "\t11A/N"); + break; + case (WMODE_B | WMODE_G | WMODE_GN): + snprintf(pBuf, BufLen, "\t11B/G/N"); + break; + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): + snprintf(pBuf, BufLen, "\t11A/G/N"); + break; + case (WMODE_AN): + snprintf(pBuf, BufLen, "\t11N only with 5G"); + break; +#endif /* DOT11_N_SUPPORT */ + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode); + break; + } + + return 0; +} + + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE"); + return 0; +} + +INT Show_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->CommonCfg.TxPreamble) + { + case Rt802_11PreambleShort: + snprintf(pBuf, BufLen, "\tShort"); + break; + case Rt802_11PreambleLong: + snprintf(pBuf, BufLen, "\tLong"); + break; + case Rt802_11PreambleAuto: + snprintf(pBuf, BufLen, "\tAuto"); + break; + default: + snprintf(pBuf, BufLen, "\tUnknown Value(%lu)", pAd->CommonCfg.TxPreamble); + break; + } + + return 0; +} + +INT Show_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%lu", pAd->CommonCfg.TxPowerPercentage); + return 0; +} + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.Channel); + return 0; +} + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->CommonCfg.UseBGProtection) + { + case 1: /*Always On*/ + snprintf(pBuf, BufLen, "\tON"); + break; + case 2: /*Always OFF*/ + snprintf(pBuf, BufLen, "\tOFF"); + break; + case 0: /*AUTO*/ + snprintf(pBuf, BufLen, "\tAuto"); + break; + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection); + break; + } + return 0; +} + +INT Show_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.RtsThreshold); + return 0; +} + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.FragmentThreshold); + return 0; +} + +#ifdef DOT11_N_SUPPORT +INT Show_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + snprintf(pBuf, BufLen, "\t40 MHz"); + } + else + { + snprintf(pBuf, BufLen, "\t20 MHz"); + } + return 0; +} + +INT Show_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + wdev = &pAd->StaCfg.wdev; +#endif /* CONFIG_STA_SUPPORT */ + if (wdev) + snprintf(pBuf, BufLen, "\t%u", wdev->DesiredTransmitSetting.field.MCS); + return 0; +} + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI) + { + case GI_400: + snprintf(pBuf, BufLen, "\tGI_400"); + break; + case GI_800: + snprintf(pBuf, BufLen, "\tGI_800"); + break; + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI); + break; + } + return 0; +} + +INT Show_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE) + { + case HTMODE_GF: + snprintf(pBuf, BufLen, "\tGF"); + break; + case HTMODE_MM: + snprintf(pBuf, BufLen, "\tMM"); + break; + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE); + break; + } + return 0; +} + +INT Show_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA) + { + case EXTCHA_BELOW: + snprintf(pBuf, BufLen, "\tBelow"); + break; + case EXTCHA_ABOVE: + snprintf(pBuf, BufLen, "\tAbove"); + break; + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA); + break; + } + return 0; +} + + +INT Show_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity); + return 0; +} + +INT Show_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit); + return 0; +} + +INT Show_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE"); + return 0; +} + +INT Show_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE"); + return 0; +} + +INT Show_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE"); + return 0; +} +#endif /* DOT11_N_SUPPORT */ + +INT Show_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.CountryRegion); + return 0; +} + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.CountryRegionForABand); + return 0; +} + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.CountryCode); + return 0; +} + +#ifdef AGGREGATION_SUPPORT +INT Show_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE"); + return 0; +} +#endif /* AGGREGATION_SUPPORT */ + +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + snprintf(pBuf, BufLen, "\t%s", pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable ? "TRUE":"FALSE"); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE"); +#endif /* CONFIG_STA_SUPPORT */ + + return 0; +} + + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE"); + return 0; +} + +#ifdef CONFIG_STA_SUPPORT +INT Show_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->StaCfg.BssType) + { + case BSS_ADHOC: + snprintf(pBuf, BufLen, "\tAdhoc"); + break; + case BSS_INFRA: + snprintf(pBuf, BufLen, "\tInfra"); + break; + case BSS_ANY: + snprintf(pBuf, BufLen, "\tAny"); + break; + case BSS_MONITOR: + snprintf(pBuf, BufLen, "\tMonitor"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType); + break; + } + return 0; +} + +#ifdef WSC_STA_SUPPORT +INT Show_WpsPbcBand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + switch(pAd->StaCfg.WscControl.WpsApBand) + { + case PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST: + snprintf(pBuf, BufLen, "\t2.4G"); + break; + case PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST: + snprintf(pBuf, BufLen, "\t5G"); + break; + case PREFERRED_WPS_AP_PHY_TYPE_AUTO_SELECTION: + snprintf(pBuf, BufLen, "\tAuto"); + break; + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", pAd->StaCfg.WscControl.WpsApBand); + break; + } + return 0; +} +#endif /* WSC_STA_SUPPORT */ + +INT Show_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + if ((pAd->StaCfg.WpaPassPhraseLen >= 8) && + (pAd->StaCfg.WpaPassPhraseLen < 64)) + snprintf(pBuf, BufLen, "\tWPAPSK = %s", pAd->StaCfg.WpaPassPhrase); + else + { + INT idx; + snprintf(pBuf, BufLen, "\tWPAPSK = "); + for (idx = 0; idx < 32; idx++) + snprintf(pBuf+strlen(pBuf), BufLen-strlen(pBuf), "%02X", pAd->StaCfg.WpaPassPhrase[idx]); + } + + return 0; +} + +INT Show_AutoReconnect_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\tAutoReconnect = %d", pAd->StaCfg.bAutoReconnect); + return 0; +} + +#endif /* CONFIG_STA_SUPPORT */ + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen; + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + wdev = &pAd->StaCfg.wdev; + +#endif /* CONFIG_STA_SUPPORT */ + + if (!wdev) + return -1; + + AuthMode = wdev->AuthMode; + if ((AuthMode >= Ndis802_11AuthModeOpen) && + (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + snprintf(pBuf, BufLen, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode)); +#ifdef WAPI_SUPPORT + else if (AuthMode == Ndis802_11AuthModeWAICERT) + snprintf(pBuf, BufLen, "\t%s", "WAI_CERT"); + else if (AuthMode == Ndis802_11AuthModeWAIPSK) + snprintf(pBuf, BufLen, "\t%s", "WAI_PSK"); +#endif /* WAPI_SUPPORT */ + else + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", AuthMode); + + return 0; +} + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + struct wifi_dev *wdev = NULL; + NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + wdev = &pAd->StaCfg.wdev; +#endif /* CONFIG_STA_SUPPORT */ + + if (!wdev) + return -1; + + WepStatus = wdev->WepStatus; + if ((WepStatus >= Ndis802_11WEPEnabled) && + (WepStatus <= Ndis802_11Encryption4KeyAbsent)) + snprintf(pBuf, BufLen, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus)); +#ifdef WAPI_SUPPORT + else if (WepStatus == Ndis802_11EncryptionSMS4Enabled) + snprintf(pBuf, BufLen, "\t%s", "WPI_SMS4"); +#endif /* WAPI_SUPPORT */ + else + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", WepStatus); + + return 0; +} + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + wdev = &pAd->StaCfg.wdev; +#endif /* CONFIG_STA_SUPPORT */ + + if (!wdev) + return -1; + + snprintf(pBuf, BufLen, "\t%d", wdev->DefaultKeyId); + + return 0; +} + + +INT Show_WepKey_Proc( + IN PRTMP_ADAPTER pAd, + IN INT KeyIdx, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + UCHAR Key[16] = {0}, KeyLength = 0; + INT index = BSS0; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + index = pObj->ioctl_if; +#endif /* CONFIG_AP_SUPPORT */ + + KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen; + NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength); + + /*check key string is ASCII or not*/ + if (RTMPCheckStrPrintAble((PCHAR)Key, KeyLength)) + sprintf(pBuf, "\t%s", Key); + else + { + int idx; + sprintf(pBuf, "\t"); + for (idx = 0; idx < KeyLength; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]); + } + return 0; +} + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 0, pBuf, BufLen); + return 0; +} + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 1, pBuf, BufLen); + return 0; +} + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 2, pBuf, BufLen); + return 0; +} + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 3, pBuf, BufLen); + return 0; +} + +INT Show_PMK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + INT idx; + UCHAR PMK[32] = {0}; + +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + NdisMoveMemory(PMK, pAd->ApCfg.MBSSID[pObj->ioctl_if].PMK, 32); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32); +#endif /* CONFIG_STA_SUPPORT */ + + sprintf(pBuf, "\tPMK = "); + for (idx = 0; idx < 32; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]); + + return 0; +} + + +INT Show_STA_RAInfo_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + sprintf(pBuf, "\n"); +#ifdef PRE_ANT_SWITCH + sprintf(pBuf+strlen(pBuf), "PreAntSwitch: %d\n", pAd->CommonCfg.PreAntSwitch); + sprintf(pBuf+strlen(pBuf), "PreAntSwitchRSSI: %d\n", pAd->CommonCfg.PreAntSwitchRSSI); +#endif /* PRE_ANT_SWITCH */ + + +#ifdef NEW_RATE_ADAPT_SUPPORT + sprintf(pBuf+strlen(pBuf), "LowTrafficThrd: %d\n", pAd->CommonCfg.lowTrafficThrd); + sprintf(pBuf+strlen(pBuf), "TrainUpRule: %d\n", pAd->CommonCfg.TrainUpRule); + sprintf(pBuf+strlen(pBuf), "TrainUpRuleRSSI: %d\n", pAd->CommonCfg.TrainUpRuleRSSI); + sprintf(pBuf+strlen(pBuf), "TrainUpLowThrd: %d\n", pAd->CommonCfg.TrainUpLowThrd); + sprintf(pBuf+strlen(pBuf), "TrainUpHighThrd: %d\n", pAd->CommonCfg.TrainUpHighThrd); +#endif // NEW_RATE_ADAPT_SUPPORT // + +#ifdef STREAM_MODE_SUPPORT + sprintf(pBuf+strlen(pBuf), "StreamMode: %d\n", pAd->CommonCfg.StreamMode); + sprintf(pBuf+strlen(pBuf), "StreamModeMCS: 0x%04x\n", pAd->CommonCfg.StreamModeMCS); +#endif // STREAM_MODE_SUPPORT // +#ifdef TXBF_SUPPORT + sprintf(pBuf+strlen(pBuf), "ITxBfEn: %d\n", pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn); + sprintf(pBuf+strlen(pBuf), "ITxBfTimeout: %ld\n", pAd->CommonCfg.ITxBfTimeout); + sprintf(pBuf+strlen(pBuf), "ETxBfTimeout: %ld\n", pAd->CommonCfg.ETxBfTimeout); + sprintf(pBuf+strlen(pBuf), "ETxBfEnCond: %ld\n", pAd->CommonCfg.ETxBfEnCond); + sprintf(pBuf+strlen(pBuf), "ETxBfNoncompress: %d\n", pAd->CommonCfg.ETxBfNoncompress); + sprintf(pBuf+strlen(pBuf), "ETxBfIncapable: %d\n", pAd->CommonCfg.ETxBfIncapable); +#endif // TXBF_SUPPORT // + +#ifdef DBG_CTRL_SUPPORT + sprintf(pBuf+strlen(pBuf), "DebugFlags: 0x%lx\n", pAd->CommonCfg.DebugFlags); +#endif /* DBG_CTRL_SUPPORT */ + return 0; +} + +#ifdef CONFIG_AP_SUPPORT +INT Show_TxInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT i; + + printk("BSS%d\n", apidx); + printk("TX Retry Count: %7lu\n", pAd->ApCfg.MBSSID[apidx].StatTxRetryOkCount); + printk("TX Fail Count: %7lu\n", pAd->ApCfg.MBSSID[apidx].StatTxFailCount); + printk("--------------------------------------\n"); + for (i=0; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry)) && (pEntry->apidx == apidx) && (pEntry->Sst == SST_ASSOC)) + { + printk("%02X:%02X:%02X:%02X:%02X:%02X ==>", PRINT_MAC(pEntry->Addr)); + printk("TX Retry(%7d), Tx Fail(%7d)\n", pEntry->StatTxRetryOkCount, pEntry->StatTxFailCount); + } + } + + return 0; +} +#endif /* CONFIG_AP_SUPPORT */ + +INT Show_MacTable_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT i; + UINT32 RegValue; + UINT32 DataRate=0; + + printk("\n"); + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08x\n", + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED) ? "short" : "long", + RegValue); + +#ifdef DOT11_N_SUPPORT + printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); + printk("\n"); +#endif /* DOT11_N_SUPPORT */ + + printk("\n%-19s%-4s%-4s%-4s%-4s%-8s", + "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS"); + + if (pAd->CommonCfg.RxStream == 3) + printk("%-7s%-7s%-7s","RSSI0", "RSSI1","RSSI2"); + else if (pAd->CommonCfg.RxStream == 2) + printk("%-7s%-7s", "RSSI0", "RSSI1"); + else + printk("%-7s", "RSSI0"); + + printk("%-10s%-6s%-6s%-6s%-6s%-7s%-7s%-7s%-7s\n", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate", "TIME", "QosMap"); + + for (i=0; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || (IS_ENTRY_APCLI(pEntry) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + )) + && (pEntry->Sst == SST_ASSOC)) + { + DataRate=0; + RtmpDrvRateGet(pAd, pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.BW, pEntry->HTPhyMode.field.MCS, + newRateGetAntenna(pEntry->MaxHTPhyMode.field.MCS, pEntry->HTPhyMode.field.MODE),&DataRate); + DataRate /= 500000; + DataRate /= 2; + + printk("%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->Addr)); + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->apidx); + printk("%-4d", (int)pEntry->PsMode); + printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)); +#ifdef DOT11_N_SUPPORT + printk("%-8d", (int)pEntry->MmpsMode); +#endif /* DOT11_N_SUPPORT */ + + if (pAd->CommonCfg.RxStream == 3) + printk("%-7d%-7d%-7d", pEntry->RssiSample.AvgRssi0, pEntry->RssiSample.AvgRssi1, pEntry->RssiSample.AvgRssi2); + else if (pAd->CommonCfg.RxStream == 2) + printk("%-7d%-7d", pEntry->RssiSample.AvgRssi0, pEntry->RssiSample.AvgRssi1); + else + printk("%-7d", pEntry->RssiSample.AvgRssi0); + + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%-2d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + printk("%-7d", (int)DataRate); + +#ifdef CONFIG_AP_SUPPORT + printk("%-7d", (int)pEntry->StaConnectTime); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + printk("%-7d", (int)pEntry->QosMapSupport); +#endif + printk("\t\t\t\t\t\t\t%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry->QosMapSupport) + { + int k =0; + printk("DSCP Exception:\n"); + for(k=0;kDscpExceptionCount/2;k++) + { + printk("[Value: %4d] [UP: %4d]\n", pEntry->DscpException[k] & 0xff, (pEntry->DscpException[k] >> 8) & 0xff); + } + printk("DSCP Range:\n"); + for(k=0;k<8;k++) + { + printk("[UP :%3d][Low Value: %4d] [High Value: %4d]\n", k, pEntry->DscpRange[k] & 0xff, (pEntry->DscpRange[k] >> 8) & 0xff); + } + } +#endif +//+++Add by shiang for debug + printk(" MaxCap:%-10s", get_phymode_str(pEntry->MaxHTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->MaxHTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->MaxHTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->MaxHTPhyMode.field.MCS>>4) + 1), (pEntry->MaxHTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk("%-6d", pEntry->MaxHTPhyMode.field.MCS); + printk("%-6d", pEntry->MaxHTPhyMode.field.ShortGI); + +#ifdef PS_ENTRY_MAITENANCE + printk("%-6d", pEntry->MaxHTPhyMode.field.STBC); + printk("\tcontinuous_ps_count = %u\n", pEntry->continuous_ps_count); +#else + printk("%-6d\n", pEntry->MaxHTPhyMode.field.STBC); +#endif /* PS_ENTRY_MAITENANCE */ +//---Add by shiang for debug + printk("\n"); + } + } + + return TRUE; +} + + +INT show_stainfo_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT i; + UINT32 DataRate=0; + UCHAR mac_addr[MAC_ADDR_LEN]; + PSTRING token; + CHAR sep[1] = {':'}; + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): Input string=%s\n", + __FUNCTION__, arg)); + for (i = 0, token = rstrtok(arg, &sep[0]); token; token = rstrtok(NULL, &sep[0]), i++) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): token(len=%d) =%s\n", + __FUNCTION__, strlen(token), token)); + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac_addr[i]), 1); + } + + DBGPRINT(RT_DEBUG_OFF, ("%s(): i= %d\n", + __FUNCTION__, i)); + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\nAddr %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(mac_addr))); + + pEntry = MacTableLookup(pAd, (UCHAR *)mac_addr); + if (!pEntry) + return FALSE; + + if (IS_ENTRY_NONE(pEntry)) { + DBGPRINT(RT_DEBUG_OFF, ("Invalid MAC address!\n")); + return FALSE; + } + + printk("\n"); + + printk("EntryType : %d\n", pEntry->EntryType); + printk("Entry Capability:\n"); + printk("\tPhyMode:%-10s\n", get_phymode_str(pEntry->MaxHTPhyMode.field.MODE)); + printk("\tBW:%-6s\n", get_bw_str(pEntry->MaxHTPhyMode.field.BW)); + printk("\tDataRate: \n"); +#ifdef DOT11_VHT_AC + if (pEntry->MaxHTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->MaxHTPhyMode.field.MCS>>4) + 1), (pEntry->MaxHTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk(" %-6d", pEntry->MaxHTPhyMode.field.MCS); + printk(" %-6d", pEntry->MaxHTPhyMode.field.ShortGI); + printk(" %-6d\n", pEntry->MaxHTPhyMode.field.STBC); + + printk("Entry Operation Features\n"); + printk("\t%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s%-7s%-7s\n", + "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", + "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate"); + + DataRate=0; + RtmpDrvRateGet(pAd, pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.BW, pEntry->HTPhyMode.field.MCS, + newRateGetAntenna(pEntry->MaxHTPhyMode.field.MCS, pEntry->HTPhyMode.field.MODE), &DataRate); + DataRate /= 500000; + DataRate /= 2; + + printk("\t%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->apidx); + printk("%-4d", (int)pEntry->PsMode); + printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)); +#ifdef DOT11_N_SUPPORT + printk("%-8d", (int)pEntry->MmpsMode); +#endif /* DOT11_N_SUPPORT */ + printk("%-7d", pEntry->RssiSample.AvgRssi0); + printk("%-7d", pEntry->RssiSample.AvgRssi1); + printk("%-7d", pEntry->RssiSample.AvgRssi2); + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + printk("%-7d", (int)DataRate); + printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + + printk("\n"); + + return TRUE; +} + + +INT show_devinfo_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR *pstr; + int i, wcid; + + DBGPRINT(RT_DEBUG_OFF, ("Device MAC\n")); + if (pAd->OpMode == OPMODE_AP) + pstr = "AP"; + else if (pAd->OpMode == OPMODE_STA) + pstr = "STA"; + else + pstr = "Unknown"; + DBGPRINT(RT_DEBUG_OFF, ("Operation Mode: %s\n", pstr)); + + pstr = wmode_2_str(pAd->CommonCfg.PhyMode); + if (pstr) { + DBGPRINT(RT_DEBUG_OFF, ("WirelessMode: %s(%d)\n", pstr, pAd->CommonCfg.PhyMode)); + os_free_mem(pAd, pstr); + } + +#ifdef APCLI_AUTO_BW_SUPPORT + pstr = wmode_2_str(pAd->CommonCfg.cfg_wmode); + if (pstr) { + DBGPRINT(RT_DEBUG_OFF, ("CFG WirelessMode: %s(%d)\n", pstr, pAd->CommonCfg.PhyMode)); + os_free_mem(pAd, pstr); + } + + for (i = 0; i < WDEV_NUM_MAX; i++) { + if (pAd->wdev_list[i]) { + pstr = wmode_2_str(pAd->wdev_list[i]->PhyMode); + if (pstr) { + DBGPRINT(RT_DEBUG_OFF, ("wdev%d: PhyMode[%s] Bandwidth[%d]\n", i, + pstr, pAd->wdev_list[i]->bw)); + os_free_mem(pAd, pstr); + } + } + } +#endif /* APCLI_AUTO_BW_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("Channel: %d\n", pAd->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_OFF, ("\tCentralChannel: %d\n", pAd->CommonCfg.CentralChannel)); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + DBGPRINT(RT_DEBUG_OFF, ("\tVHT CentralChannel: %d\n", pAd->CommonCfg.vht_cent_ch)); +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_OFF, ("\tRF Channel: %d\n", pAd->LatchRfRegs.Channel)); + + DBGPRINT(RT_DEBUG_OFF, ("Bandwidth\n")); + pstr = (pAd->CommonCfg.RegTransmitSetting.field.BW) ? "20/40" : "20"; + DBGPRINT(RT_DEBUG_OFF, ("\tHT-BW: %s\n", pstr)); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + { + if (pAd->CommonCfg.vht_bw) + pstr = "80"; + DBGPRINT(RT_DEBUG_OFF, ("\tVHT-BW: %s\n", pstr)); + } +#endif /* DOT11_VHT_AC */ + +#ifdef RT65xx + if (IS_RT65XX(pAd)) + { + dump_bw_info(pAd); +#ifdef RT8592 + if (IS_RT8592(pAd)) + dump_pwr_info(pAd); +#endif /* RT8592 */ + } +#endif /* RT65xx */ + + DBGPRINT(RT_DEBUG_OFF, ("Security\n")); + + DBGPRINT(RT_DEBUG_OFF, ("MAX_LEN_OF_MAC_TABLE: %d\n", MAX_LEN_OF_MAC_TABLE)); + DBGPRINT(RT_DEBUG_OFF, ("MAX_NUMBER_OF_MAC: %d\n", MAX_NUMBER_OF_MAC)); + DBGPRINT(RT_DEBUG_OFF, ("HW_RESERVED_WCID: %d\n", HW_RESERVED_WCID(pAd))); + DBGPRINT(RT_DEBUG_OFF, ("LAST_SPECIFIC_WCID: %d\n", LAST_SPECIFIC_WCID(pAd))); + DBGPRINT(RT_DEBUG_OFF, ("MAX_AVAILABLE_CLIENT_WCID: %d\n", MAX_AVAILABLE_CLIENT_WCID(pAd))); + for (i=0;iwdev_list[idx]) + { + UCHAR *str = NULL; + + wdev = pAd->wdev_list[idx]; + DBGPRINT(RT_DEBUG_OFF, ("\n\t\tName/Type:%s/%s\n", + RTMP_OS_NETDEV_GET_DEVNAME(wdev->if_dev), + wdev_type2str(wdev->wdev_type))); + DBGPRINT(RT_DEBUG_OFF, ("\t\tListIdx:%d\n", wdev->wdev_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tMacAddr:%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(wdev->if_addr))); + DBGPRINT(RT_DEBUG_OFF, ("\t\tBSSID:%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(wdev->bssid))); + str = wmode_2_str(wdev->PhyMode); + if (str) { + DBGPRINT(RT_DEBUG_OFF, ("\t\tPhyMode:%s\n", str)); + os_free_mem(pAd, str); + } + DBGPRINT(RT_DEBUG_OFF, ("\t\tChannel:%d\n", wdev->channel)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tPortSecured/AllowTx: %d:%d\n", + wdev->PortSecured, wdev->allow_data_tx)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_pkt_checker:%p\n", wdev->tx_pkt_allowed)); + + DBGPRINT(RT_DEBUG_OFF, ("\t\tif_dev:0x%p \tfunc_dev:0x%p \tsys_handle:0x%p\n", + wdev->if_dev, wdev->func_dev, wdev->sys_handle)); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + } + + DBGPRINT(RT_DEBUG_OFF, ("Memory Statistics:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tsize>\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tpAd = \t\t%d bytes\n\n", sizeof(*pAd))); + + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tCommonCfg = \t%d bytes\n", sizeof(pAd->CommonCfg))); + total_size += sizeof(pAd->CommonCfg); +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tApCfg = \t%d bytes\n", sizeof(pAd->ApCfg))); + total_size += sizeof(pAd->ApCfg); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\t\tMBSSID = \t%d B (PerMBSS =%d B, Total MBSS Num= %d)\n", + sizeof(pAd->ApCfg.MBSSID), sizeof(struct _MULTISSID_STRUCT), HW_BEACON_MAX_NUM)); +#ifdef APCLI_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\t\t\tAPCLI = \t%d bytes (PerAPCLI =%d bytes, Total APCLI Num= %d)\n", + sizeof(pAd->ApCfg.ApCliTab), sizeof(struct _APCLI_STRUCT), MAX_APCLI_NUM)); +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RTMP_MAC_PCI + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tTxRing = \t%d bytes\n", sizeof(pAd->TxRing))); + total_size += sizeof(pAd->TxRing); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tRxRing = \t%d bytes\n", sizeof(pAd->RxRing))); + total_size += sizeof(pAd->RxRing); +#ifdef CONFIG_ANDES_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tCtrlRing = \t%d bytes\n", sizeof(pAd->CtrlRing))); + total_size += sizeof(pAd->CtrlRing); +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMgmtRing = \t%d bytes\n", sizeof(pAd->MgmtRing))); + total_size += sizeof(pAd->MgmtRing); + + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMlme = \t%d bytes\n", sizeof(pAd->Mlme))); + total_size += sizeof(pAd->Mlme); +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMlmeAux = \t%d bytes\n", sizeof(pAd->MlmeAux))); + total_size += sizeof(pAd->MlmeAux); +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMacTab = \t%d bytes\n", sizeof(pAd->MacTab))); + total_size += sizeof(pAd->MacTab); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tBATable = \t%d bytes\n", sizeof(pAd->BATable))); + total_size += sizeof(pAd->BATable); +#endif /* DOT11_N_SUPPORT */ + + cntr_size = sizeof(pAd->Counters8023) + sizeof(pAd->WlanCounters) + + sizeof(pAd->RalinkCounters) + /* sizeof(pAd->DrsCounters) */+ + sizeof(pAd->PrivateInfo); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tCounter** = \t%d bytes\n", cntr_size)); + total_size += cntr_size; + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tScanTab = \t%d bytes\n", sizeof(pAd->ScanTab))); + total_size += sizeof(pAd->ScanTab); +#endif + DBGPRINT(RT_DEBUG_OFF, ("\tsize> Total = \t\t%d bytes, Others = %d bytes\n\n", + total_size, sizeof(*pAd)-total_size)); + + return TRUE; +} + + +INT show_trinfo_proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_RBUS_SUPPORT) + if (IS_RBUS_INF(pAd) || IS_PCI_INF(pAd)) + { + ULONG irq_flags; + UINT32 tbase[NUM_OF_TX_RING], tcnt[NUM_OF_TX_RING]; + UINT32 tcidx[NUM_OF_TX_RING], tdidx[NUM_OF_TX_RING]; + UINT32 rbase[NUM_OF_RX_RING], rcnt[NUM_OF_RX_RING]; + UINT32 rcidx[NUM_OF_RX_RING], rdidx[NUM_OF_RX_RING]; + UINT32 mbase[2] = {0}, mcnt[2] = {0}, mcidx[2] = {0}, mdidx[2] = {0}; + UINT32 sys_ctrl[3]; +#ifdef RLT_MAC + UINT32 pbf_val = 0, pcnt[6] = {0}; +#endif /* RLT_MAC */ + INT idx; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irq_flags); + for (idx = 0; idx < NUM_OF_TX_RING; idx++) + { + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_desc_base, &tbase[idx]); + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_cnt_addr, &tcnt[idx]); + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_cidx_addr, &tcidx[idx]); + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_didx_addr, &tdidx[idx]); + } + + for (idx = 0; idx < NUM_OF_RX_RING; idx++) + { + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_desc_base, &rbase[idx]); + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_cnt_addr, &rcnt[idx]); + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_cidx_addr, &rcidx[idx]); + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_didx_addr, &rdidx[idx]); + } + + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_desc_base, &mbase[0]); + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_cnt_addr, &mcnt[0]); + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_cidx_addr, &mcidx[0]); + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_didx_addr, &mdidx[0]); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { +#ifdef CONFIG_ANDES_SUPPORT + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_desc_base, &mbase[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_cnt_addr, &mcnt[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_cidx_addr, &mcidx[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_didx_addr, &mdidx[1]); +#endif /* CONFIG_ANDES_SUPPORT */ + + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &pbf_val); + RTMP_IO_READ32(pAd, TX_MAX_PCNT, &pcnt[0]); + RTMP_IO_READ32(pAd, RX_MAX_PCNT, &pcnt[1]); + RTMP_IO_READ32(pAd, TXQ_STA, &pcnt[2]); + RTMP_IO_READ32(pAd, RXQ_STA, &pcnt[3]); + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &pcnt[4]); + RTMP_IO_READ32(pAd, PBF_DBG, &pcnt[5]); + } +#endif /* RLT_MAC */ + + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &sys_ctrl[0]); + RTMP_IO_READ32(pAd, INT_MASK_CSR, &sys_ctrl[1]); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &sys_ctrl[2]); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &sys_ctrl[2]); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irq_flags); + + DBGPRINT(RT_DEBUG_OFF, ("TxRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \tCnt \tCIDX \tDIDX\n")); + for (idx = 0; idx < NUM_OF_TX_RING; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x\n", + idx, pAd->TxRing[idx].hw_desc_base, tbase[idx], tcnt[idx], tcidx[idx], tdidx[idx])); + } + + DBGPRINT(RT_DEBUG_OFF, ("\nRxRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \tCnt \tCIDX \tDIDX\n")); + for (idx = 0; idx < NUM_OF_RX_RING; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x\n", + idx, pAd->RxRing[idx].hw_desc_base, rbase[idx], rcnt[idx], rcidx[idx], rdidx[idx])); + } + + DBGPRINT(RT_DEBUG_OFF, ("\nMgmtRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \tCnt \tCIDX \tDIDX\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x\n", + 0, pAd->MgmtRing.hw_desc_base, mbase[0], mcnt[0], mcidx[0], mdidx[0])); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { +#ifdef CONFIG_ANDES_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\nCtrlRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \tCnt \tCIDX \tDIDX\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x\n", + 1, pAd->CtrlRing.hw_desc_base, mbase[1], mcnt[1], mcidx[1], mdidx[1])); +#endif /* CONFIG_ANDES_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("\nPBF Configuration\n" + "\tRLT_PBF_CFG: 0x%08x\n", pbf_val)); + DBGPRINT(RT_DEBUG_OFF, ("\tPCNT_CFG:\n" + "\t\tTxMax[0x%04x] -0x%08x\n", TX_MAX_PCNT, pcnt[0])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tTxStat[0x%04x] -0x%08x\n", RX_MAX_PCNT, pcnt[2])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tTxUsed[0x%04x] -0x%08x\n", TXRXQ_PCNT, pcnt[4])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tRxMax[0x%04x] -0x%08x\n", RX_MAX_PCNT, pcnt[1])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tRxStat[0x%04x] -0x%08x\n", RXQ_STA, pcnt[3])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tFreCNT[0x%04x] -0x%08x\n", PBF_DBG, pcnt[5])); + } +#endif /* RLT_MAC */ + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("PDMA Info\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tPDMAMonitorEn=%d, TxRCounter = %lu, RxRCounter = %lu, TxDMACheckTimes=%d, RxDMACheckTimes=%d\n", pAd->PDMAWatchDogEn, pAd->TxDMAResetCount, pAd->RxDMAResetCount, pAd->TxDMACheckTimes,pAd->RxDMACheckTimes)); +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } +#endif /* defined(RTMP_PCI_SUPPORT) || defined(RTMP_RBUS_SUPPORT) */ + + + + return TRUE; +} + + +#ifdef WSC_STA_SUPPORT +INT Show_WpsManufacturer_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, +IN ULONG BufLen) +{ + sprintf(pBuf, "\tManufacturer = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.Manufacturer); + return 0; +} + +INT Show_WpsModelName_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + sprintf(pBuf, "\tModelName = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.ModelName); + return 0; +} + +INT Show_WpsDeviceName_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + sprintf(pBuf, "\tDeviceName = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.DeviceName); + return 0; +} + +INT Show_WpsModelNumber_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + sprintf(pBuf, "\tModelNumber = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.ModelNumber); + return 0; +} + +INT Show_WpsSerialNumber_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + sprintf(pBuf, "\tSerialNumber = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.SerialNumber); + return 0; +} +#endif /* WSC_STA_SUPPORT */ + + +#ifdef SINGLE_SKU +INT Show_ModuleTxpower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\tModuleTxpower = %d", pAd->CommonCfg.ModuleTxpower); + return 0; +} +#endif /* SINGLE_SKU */ + +#ifdef APCLI_SUPPORT + INT RTMPIoctlConnStatus( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + INT i=0; + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN bConnect=FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlConnStatus\n")); + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + DBGPRINT(RT_DEBUG_OFF, ("=============================================================\n")); + if((pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState == APCLI_CTRL_CONNECTED) + && (pAd->ApCfg.ApCliTab[ifIndex].SsidLen != 0)) + { + for (i=0; iMacTab.Content[i]; + + if ( IS_ENTRY_APCLI(pEntry) + && (pEntry->Sst == SST_ASSOC) + && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : %02X:%02X:%02X:%02X:%02X:%02X SSID:%s\n", + ifIndex, PRINT_MAC(pEntry->Addr), pAd->ApCfg.ApCliTab[ifIndex].Ssid)); + bConnect=TRUE; + } + } + + if (!bConnect) + DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : Disconnect\n",ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : Disconnect\n",ifIndex)); + } + DBGPRINT(RT_DEBUG_OFF, ("=============================================================\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlConnStatus\n")); + return TRUE; +} +#endif/*APCLI_SUPPORT*/ + +#ifdef CUSTOMER_DCC_FEATURE +VOID GetMultShiftFactorIndex( + IN HTTRANSMIT_SETTING HTSetting, + IN INT32 *Index ) +{ + INT32 index = 0; + INT32 rate_count = 224; + UCHAR MCS; + UCHAR NSS; + + /* refer the MCSMappingRateTable[] in the function InitRateMultiplicationAndShiftFactor for the below index calculation */ +#ifdef DOT11_VHT_AC + if (HTSetting.field.MODE >= MODE_VHT) + { + MCS = (UCHAR)HTSetting.field.MCS & 0xF; + NSS = (UCHAR)HTSetting.field.MCS >> 4; + if (HTSetting.field.BW == 0/*20Mhz*/) { + if (MCS > 8) + MCS = 8; + index = 108 + ((UCHAR)HTSetting.field.ShortGI * 58) + ((UCHAR)NSS * 9) + ((UCHAR)MCS); + } + else if ((UCHAR)HTSetting.field.BW == 1/*40Mhz*/) { + index = 126 + ((UCHAR)HTSetting.field.ShortGI * 58) + ((UCHAR)NSS * 10) + ((UCHAR)MCS); + } + else if ((UCHAR)HTSetting.field.BW == 2/*80Mhz*/) { + index = 146 + ((UCHAR)HTSetting.field.ShortGI * 58) + ((UCHAR)NSS * 10) + ((UCHAR)MCS); + } + } + else +#endif /* DOT11_VHT_AC */ +#ifdef DOT11_N_SUPPORT + if ((HTSetting.field.MODE >= MODE_HTMIX) && (HTSetting.field.MODE < MODE_VHT)) + { + index = 12 + ((UCHAR)HTSetting.field.BW *24) + ((UCHAR)HTSetting.field.ShortGI *48) + ((UCHAR)HTSetting.field.MCS); + } + else +#endif /* DOT11_N_SUPPORT */ + if (HTSetting.field.MODE == MODE_OFDM) + index = (UCHAR)(HTSetting.field.MCS) + 4; + else if (HTSetting.field.MODE == MODE_CCK) { + index = (UCHAR)(HTSetting.field.MCS & 0xF); + } + if (index < 0) + { + index = 0; + DBGPRINT(RT_DEBUG_ERROR, ("ERROR::Wrong Value of Index!\n")); + } + + if (index >= rate_count) + { + index = rate_count-1; + DBGPRINT(RT_DEBUG_ERROR, ("ERROR::Wrong Value of Index!\n")); + } + + *Index = index; + return; +} + +VOID InitRateMultiplicationAndShiftFactor( + IN PRTMP_ADAPTER pAd) +{ + INT MCSMappingRateTable[] = + {2, 4, 11, 22, /* CCK*/ + 12, 18, 24, 36, 48, 72, 96, 108, /* OFDM*/ + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, /* 20MHz, 800ns GI, MCS: 0 ~ 15*/ + 39, 78, 117, 156, 234, 312, 351, 390, /* 20MHz, 800ns GI, MCS: 16 ~ 23*/ + 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, /* 40MHz, 800ns GI, MCS: 0 ~ 15*/ + 81, 162, 243, 324, 486, 648, 729, 810, /* 40MHz, 800ns GI, MCS: 16 ~ 23*/ + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, /* 20MHz, 400ns GI, MCS: 0 ~ 15*/ + 43, 87,130, 173, 260, 317, 390, 433, /* 20MHz, 400ns GI, MCS: 16 ~ 23*/ + 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, /* 40MHz, 400ns GI, MCS: 0 ~ 15*/ + 90, 180, 270, 360, 540, 720, 810, 900, /* 40MHz, 400ns GI, MCS: 16 ~ 23*/ + 13, 26, 39, 52, 78, 104, 117, 130, 156, /* 11ac: 20Mhz, 800ns GI, NSS 0, MCS: 0~8 */ + 26, 52, 78, 104, 156, 208, 234, 260, 312, /* 11ac: 20Mhz, 800ns GI, NSS 1, MCS: 0~8 */ + 27, 54, 81, 108, 162, 216, 243, 270, 324, 360, /*11ac: 40Mhz, 800ns GI, NSS 0, MCS: 0~9 */ + 54, 108, 162, 216, 324, 432, 486, 540, 648, 720, /*11ac: 40Mhz, 800ns GI, NSS 1, MCS: 0~9 */ + 59, 117, 176, 234, 351, 468, 527, 585, 702, 780, /*11ac: 80Mhz, 800ns GI, NSS 0, MCS: 0~9 */ + 117, 234, 351, 468, 702, 936, 1053, 1179, 1404, 1560, /*11ac: 80Mhz, 800ns GI, NSS 1, MCS: 0~9 */ + 14, 29, 43, 57, 87, 115, 130, 144, 173, /* 11ac: 20Mhz, 400ns GI, NSS 0, MCS: 0~8 */ + 29, 57, 87, 115, 173, 231, 261, 289, 347, /* 11ac: 20Mhz, 400ns GI, NSS 1, MCS: 0~8 */ + 30, 60, 90, 120, 180, 240, 270, 300, 360, 400, /*11ac: 40Mhz, 400ns GI, NSS 0, MCS: 0~9 */ + 60, 120, 180, 240, 360, 480, 540, 600, 720, 800, /*11ac: 40Mhz, 400ns GI, NSS 1, MCS: 0~9 */ + 65, 130, 195, 260, 390, 520, 585, 650, 780, 867, /*11ac: 80Mhz, 400ns GI, NSS 0, MCS: 0~9 */ + 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1733 /*11ac: 80Mhz, 400ns GI, NSS 1, MCS: 0~9 */ + }; + + UINT32 rate_count = sizeof(MCSMappingRateTable)/sizeof(int); + UINT32 rate_index = 0; + UINT32 multemp, mul, rem; + UINT32 j, div,shift; + UINT32 remtemp = 0; + + for(rate_index = 0; rate_index < rate_count; rate_index++) + { + mul = 0; + shift = 0; + /* insted of 125000 used 1250 to convert in bytes so below use 10000000 insted of 1000000000 to convert in microseconds */ + div = (MCSMappingRateTable[rate_index] * 5 * 1250)/10; + rem = div; + for(j = 30; j > 0; j--) + { + multemp = (1 << j); + remtemp = multemp % div; + + if( (remtemp < rem) && (multemp >= div)) + { + rem = remtemp; + mul = multemp / div; + shift = j; + } + } + + RateMultiplicationShiftFactor[rate_index].Multiplication = (UINT64)mul * 10000000; + RateMultiplicationShiftFactor[rate_index].Shift = shift; + + // printk("%s: rate_index: %u mul: %llu shift: %llu \n",__func__,rate_index, RateMultiplicationShiftFactor[rate_index].Multiplication, RateMultiplicationShiftFactor[rate_index].Shift); + } + return; +} +#endif + +void getRate(HTTRANSMIT_SETTING HTSetting, UINT32* fLastTxRxRate) + +{ + VOID *pAd = NULL; + RtmpDrvRateGet(pAd, HTSetting.field.MODE,HTSetting.field.ShortGI, + HTSetting.field.BW,HTSetting.field.MCS, + newRateGetAntenna(HTSetting.field.MCS, HTSetting.field.MODE), fLastTxRxRate); + *(fLastTxRxRate) /= 500000; + *(fLastTxRxRate) /= 2; + return; +} + + +#ifdef TXBF_SUPPORT + + +/* + Set_InvTxBfTag_Proc - Invalidate BF Profile Tags + usage: "iwpriv ra0 set InvTxBfTag=n" + Reset Valid bit and zero out MAC address of each profile. The next profile will be stored in profile 0 +*/ +INT Set_InvTxBfTag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int profileNum; + UCHAR row[EXP_MAX_BYTES]; + UCHAR r163Value = 0; + UINT rValue; + + /* Disable Profile Updates during access */ +#ifndef MT76x2 + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R163, &r163Value); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value & ~0x88); + + /* Invalidate Implicit tags */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0); + for (profileNum=0; profileNum<4; profileNum++) { + Read_TagField(pAd, row, profileNum); + row[0] &= 0x7F; + row[1] = row[2] = row[3] = row[4] = row[5] = row[6] = 0xAA; + Write_TagField(pAd, row, profileNum); + } + + /* Invalidate Explicit tags */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 4); + for (profileNum=0; profileNum<4; profileNum++) { + Read_TagField(pAd, row, profileNum); + row[0] &= 0x7F; + row[1] = row[2] = row[3] = row[4] = row[5] = row[6] = 0x55; + Write_TagField(pAd, row, profileNum); + } + + /* Restore Profile Updates */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value); +#else + PFMU_PROFILE *prof; + + if (os_alloc_mem(pAd, (UCHAR **)&prof, sizeof(PROFILE_DATA))!= NDIS_STATUS_SUCCESS) + { + return -3; + } + + RTMP_IO_READ32(pAd, PFMU_R1, &rValue); + RTMP_IO_WRITE32(pAd, PFMU_R1, rValue & ~0x330); + + for (profileNum=0; profileNum<8; profileNum++) { + // Clear the profile valid bit + prof->validFlg = 0; + TxBfProfileTagValid(pAd, prof, profileNum); + + // Clear the mac address + TxBfProfileTagRead(pAd, prof, profileNum); + prof->DMAC[0] = prof->DMAC[1] = prof->DMAC[2] = 0xFF; + prof->DMAC[3] = prof->DMAC[4] = prof->DMAC[5] = 0xFF; + prof->CMDInIdx = 2; + TxBfProfileTagWrite(pAd, prof, profileNum); + } + + /* Restore Profile Updates */ + RTMP_IO_WRITE32(pAd, PFMU_R1, rValue); + + os_free_mem(pAd, prof); +#endif + + return TRUE; +} + + + + +/* + Set_ETxBfCodebook_Proc - Set ETxBf Codebook + usage: iwpriv ra0 set ETxBfCodebook=0 to 3 +*/ +INT Set_ETxBfCodebook_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + TX_TXBF_CFG_0_STRUC regValue; + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 3) { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfCodebook_Proc: value > 3!\n")); + return FALSE; + } + + RTMP_IO_READ32(pAd, TX_TXBF_CFG_0, ®Value.word); + regValue.field.EtxbfFbkCode = t; + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_0, regValue.word); + return TRUE; +} + + +/* + Set_ETxBfCoefficient_Proc - Set ETxBf Coefficient + usage: iwpriv ra0 set ETxBfCoefficient=0 to 3 +*/ +INT Set_ETxBfCoefficient_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + TX_TXBF_CFG_0_STRUC regValue; + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 3) { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfCoefficient_Proc: value > 3!\n")); + return FALSE; + } + + RTMP_IO_READ32(pAd, TX_TXBF_CFG_0, ®Value.word); + regValue.field.EtxbfFbkCoef = t; + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_0, regValue.word); + return TRUE; +} + + +/* + Set_ETxBfGrouping_Proc - Set ETxBf Grouping + usage: iwpriv ra0 set ETxBfGrouping=0 to 2 +*/ +INT Set_ETxBfGrouping_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + TX_TXBF_CFG_0_STRUC regValue; + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 2) { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfGrouping_Proc: value > 2!\n")); + return FALSE; + } + + RTMP_IO_READ32(pAd, TX_TXBF_CFG_0, ®Value.word); + regValue.field.EtxbfFbkNg = t; + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_0, regValue.word); + return TRUE; +} + + +/* + Set_ETxBfNoncompress_Proc - Set ETxBf Noncompress option + usage: iwpriv ra0 set ETxBfNoncompress=0 or 1 +*/ +INT Set_ETxBfNoncompress_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 1) { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfNoncompress_Proc: value > 1!\n")); + return FALSE; + } + + pAd->CommonCfg.ETxBfNoncompress = t; + return TRUE; +} + + +/* + Set_ETxBfIncapable_Proc - Set ETxBf Incapable option + usage: iwpriv ra0 set ETxBfIncapable=0 or 1 +*/ +INT Set_ETxBfIncapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 1) + return FALSE; + + pAd->CommonCfg.ETxBfIncapable = t; + setETxBFCap(pAd, &pAd->CommonCfg.HtCapability.TxBFCap); + + return TRUE; +} + + +/* + Set_ITxBfDivCal_Proc - Calculate ITxBf Divider Calibration parameters + usage: iwpriv ra0 set ITxBfDivCal=dd + 0=>display calibration parameters + 1=>update EEPROM values + 2=>update BBP R176 + 10=>display calibration parameters and dump capture data + 11=>Skip divider calibration, just capture and dump capture data +*/ +INT Set_ITxBfDivCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int calFunction; + + calFunction = simple_strtol(arg, 0, 10); + + return pAd->chipOps.fITxBfDividerCalibration(pAd, calFunction, 0, NULL); +} + + +/* + Set_ITxBfLNACal_Proc - Calculate ITxBf LNA Calibration parameters + usage: iwpriv ra0 set ITxBfLnaCal=dd + 0=>display calibration parameters + 1=>update EEPROM values + 2=>update BBP R174 + 10=>display calibration parameters and dump capture data +*/ +INT Set_ITxBfLnaCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR channel = pAd->CommonCfg.Channel; + int calFunction; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + calFunction = simple_strtol(arg, 0, 10); + + return pAd->chipOps.fITxBfLNACalibration(pAd, calFunction, 0, channel<=14); +} + + + + +#ifdef MT76x2 +INT mt76x2_Set_ITxBfCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int calFunction = simple_strtol(arg, 0, 10); + int calParams[2], idx; + int ret; + UINT value32, r27Value = 0, r173Value = 0; + ITXBF_PHASE_PARAMS phaseParams; + UCHAR divPhase[2] = {0}, phaseValues[2] = {0}; + UCHAR channel = pAd->CommonCfg.Channel; + UCHAR LoPhase; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + ret = iCalcCalibration(pAd, calParams, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("######### DebugKK[3],ProfiePhase= 0x%02x\n", calParams[0])); + + if (ret < 0) { + if (ret == -3) + DBGPRINT(RT_DEBUG_OFF, ("Set_ITxBfCal_Proc: kmalloc failed\n")); + else if (ret == -2) + DBGPRINT(RT_DEBUG_OFF, ("Set_ITxBfCal_Proc: MAC Address mismatch\n")); + else + DBGPRINT(RT_DEBUG_OFF, ("Set_ITxBfCal_Proc: Invalid profiles\n")); + + return FALSE; + } + + /* Update BBP R176 and EEPROM for Ant 0 and 2 */ + switch (calFunction) + { + case 0: //Verification Flow + + phaseValues[0] = calParams[0]; + + DBGPRINT(RT_DEBUG_TRACE, ("ITxBfCal Result_case0 = [0x%02x]\n", phaseValues[0])); +#ifdef RALINK_ATE + pAd->ate.calParams[0] = (UCHAR)phaseValues[0]; + + /* Update EEPROM */ + ITxBFGetEEPROM(pAd, &phaseParams, 0, 0, 0); + + idx = ate_txbf_get_chan_idx(pAd, channel, 1); + + if(idx >=0) + phaseParams.E1aPhaseErr[idx] = pAd->ate.calParams[0]; + + pAd->iBFPhaseErrorBackup = pAd->ate.calParams[0]; + + ITxBFSetEEPROM(pAd, &phaseParams, 0, 0, 0); + + /* Double check */ + DBGPRINT((calFunction==0? RT_DEBUG_OFF: RT_DEBUG_WARN), + ("ITxBfCal Verify Result in ATE = [0x%02x], Channel= %d\n", pAd->ate.calParams[0], channel)); +#endif /* RALINK_ATE */ + break; + + case 1: + /* Display result */ + //DBGPRINT(RT_DEBUG_OFF, ("ITxBfCal Result_case1 = [0x%02x]\n", calParams[0])); +#ifdef RALINK_ATE + pAd->ate.calParams[0] = (UCHAR)calParams[0]; + + /* Double check */ + DBGPRINT((calFunction==0? RT_DEBUG_OFF: RT_DEBUG_WARN), + ("ITxBfCal Result in ATE = [0x%02x]\n", pAd->ate.calParams[0])); +#endif /* RALINK_ATE */ + + //mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, 0x28585); // Auto LNA gain + //mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, 0x28585); // Auto LNA gain + //RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000001); // core soft reset enable + //RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000000); // core soft reset disable + + /* Select Ant 0 */ + RTMP_IO_WRITE32(pAd, CAL_R0, 0); + + /* Update TXBE_R13 */ + //phaseValues[0] = 0x64; + RTMP_IO_WRITE32(pAd, TXBE_R13, calParams[0]); + + /* Remove Divider phase */ + // restore back up divPhase calibrated result + phaseValues[0] = calParams[0] - (pAd->divPhaseBackup[0]); + + DBGPRINT(RT_DEBUG_OFF, ( + "%s : \n" + "Phase compensated value = 0x%x\n" + "Residual phase = 0x%x\n", + __FUNCTION__, calParams[0], phaseValues[0])); + + /* Update EEPROM */ + ITxBFGetEEPROM(pAd, &phaseParams, 0, 0, 0); + + idx = ate_txbf_get_chan_idx(pAd, channel, 1); + + if(idx >=0) + phaseParams.E1aPhase[idx] = phaseValues[0]; + + ITxBFSetEEPROM(pAd, &phaseParams, 0, 0, 0); + + DBGPRINT(RT_DEBUG_TRACE, ( + " ============================================================ \n" + " Save Resphase to efuse[%d], value = 0x%x\n" + " ============================================================ \n", + idx, phaseValues[0])); + + DBGPRINT(RT_DEBUG_WARN, ("Set_ITxBfCal_Proc: Calibration Parameters updated\n")); + + break; + default: + break; + } + + return TRUE; +} + +#endif // MT76x2 + + +/* + Set_ETxBfEnCond_Proc - enable/disable ETxBF + usage: iwpriv ra0 set ETxBfEnCond=dd + 0=>disable, 1=>enable + Note: After use this command, need to re-run apStartup()/LinkUp() operations to sync all status. + If ETxBfIncapable!=0 then we don't need to reassociate. +*/ +INT Set_ETxBfEnCond_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i, enableETxBf; + MAC_TABLE_ENTRY *pEntry; + UINT8 byteValue; + + enableETxBf = simple_strtol(arg, 0, 10); + + if (enableETxBf > 1) + return FALSE; + + pAd->CommonCfg.ETxBfEnCond = enableETxBf && (pAd->Antenna.field.TxPath > 1); + pAd->CommonCfg.RegTransmitSetting.field.TxBF = enableETxBf==0? 0: 1; + + setETxBFCap(pAd, &pAd->CommonCfg.HtCapability.TxBFCap); +#ifdef VHT_TXBF_SUPPORT + setVHTETxBFCap(pAd, &pAd->CommonCfg.vht_cap_ie.vht_cap); +#endif + rtmp_asic_set_bf(pAd); + + if (enableETxBf) + { + RTMP_IO_WRITE32(pAd,PFMU_R54, 0x150); // Solve the MCS8 and MCS9 TP degradation when PN on + } + else + { + RTMP_IO_WRITE32(pAd,PFMU_R54, 0x100); + } + + + for (i=0; iMacTab.Content[i]; + if (!IS_ENTRY_NONE(pEntry)) + { +#ifdef VHT_TXBF_SUPPORT + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + pEntry->eTxBfEnCond = clientSupportsVHTETxBF(pAd, &pEntry->vht_cap_ie.vht_cap) ? enableETxBf: 0; + else +#endif + pEntry->eTxBfEnCond = clientSupportsETxBF(pAd, &pEntry->HTCapability.TxBFCap)? enableETxBf: 0; + pEntry->bfState = READY_FOR_SNDG0; + pEntry->HTPhyMode.field.eTxBF = pEntry->eTxBfEnCond; + pEntry->phyETxBf = pEntry->eTxBfEnCond; +#ifdef MCS_LUT_SUPPORT + asic_mcs_lut_update(pAd, pEntry); +#endif /* MCS_LUT_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set ETxBfEn=%d, Final ETxBF status =%d!\n", + enableETxBf , pEntry->eTxBfEnCond)); + } + + +#ifndef MT76x2 + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn || enableETxBf) + { + RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue); + byteValue |= 0x40; + RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue); + + RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue); + byteValue |= 0x20; + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue); + } + else + { + /* depends on Gary Tsao's comments. we shall disable it */ + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn == 0) + { + RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue); + byteValue &= (~0x40); + RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue); + + RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue); + byteValue &= (~0x20); + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue); + } + } +#endif + + return TRUE; +} + + +/* + Set_StaETxBfEnCond_Proc - enable/disable ETxBF + usage: iwpriv ra0 set StaETxBfEnCond=dd + 0=>disable, 1=>enable + Note: After use this command, need to re-run StaStartup()/LinkUp() operations to sync all status. + If ETxBfIncapable!=0 then we don't need to reassociate. +*/ +INT Set_StaETxBfEnCond_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i, enableETxBf; + MAC_TABLE_ENTRY *pEntry; + UINT8 byteValue; + + enableETxBf = simple_strtol(arg, 0, 10); + + if (enableETxBf > 1) + return FALSE; + + pAd->CommonCfg.ETxBfEnCond = enableETxBf && (pAd->Antenna.field.TxPath > 1); + pAd->CommonCfg.RegTransmitSetting.field.TxBF = enableETxBf==0? 0: 1; + + setETxBFCap(pAd, &pAd->CommonCfg.HtCapability.TxBFCap); +#ifdef VHT_TXBF_SUPPORT + setVHTETxBFCap(pAd, &pAd->CommonCfg.vht_cap_ie.vht_cap); +#endif + rtmp_asic_set_bf(pAd); + + if (enableETxBf) + { + RTMP_IO_WRITE32(pAd,PFMU_R54, 0x150); // Solve the MCS8 and MCS9 TP degradation when PN on + } + else + { + RTMP_IO_WRITE32(pAd,PFMU_R54, 0x100); + } + +#ifdef VHT_TXBF_SUPPORT + + DBGPRINT(RT_DEBUG_TRACE, ("802.11 mode =%d, Channel =%d!\n", + pAd->CommonCfg.PhyMode , pAd->CommonCfg.Channel)); + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + if (!IS_ENTRY_NONE(pEntry)) + { + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + { + pEntry->eTxBfEnCond = clientSupportsVHTETxBF(pAd, &pEntry->vht_cap_ie.vht_cap) ? enableETxBf: 0; + DBGPRINT(RT_DEBUG_TRACE, ("VHT mode!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("AP Bfee Cap =%d, AP Bfer Cap =%d!\n", + pEntry->vht_cap_ie.vht_cap.bfee_cap_su , pEntry->vht_cap_ie.vht_cap.bfer_cap_su)); + } + else + { + pEntry->eTxBfEnCond = clientSupportsETxBF(pAd, &pEntry->HTCapability.TxBFCap)? enableETxBf: 0; + DBGPRINT(RT_DEBUG_TRACE, ("HT mode!\n")); + } + } +#else + pEntry->eTxBfEnCond = clientSupportsETxBF(pAd, &pEntry->HTCapability.TxBFCap)? enableETxBf: 0; + DBGPRINT(RT_DEBUG_TRACE, ("HT mode!\n")); +#endif + pEntry->bfState = READY_FOR_SNDG0; + pEntry->HTPhyMode.field.eTxBF = pEntry->eTxBfEnCond; + pEntry->phyETxBf = pEntry->eTxBfEnCond; +#ifdef MCS_LUT_SUPPORT + asic_mcs_lut_update(pAd, pEntry); +#endif /* MCS_LUT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set ETxBfEn=%d, Final ETxBF status =%d!\n", + enableETxBf , pEntry->eTxBfEnCond)); + + return TRUE; +} + + + + +INT Set_NoSndgCntThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i; + for (i=0; iMacTab.Content[i].noSndgCntThrd = simple_strtol(arg, 0, 10); + } + return TRUE; +} + +INT Set_NdpSndgStreams_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i; + for (i=0; iMacTab.Content[i].ndpSndgStreams = simple_strtol(arg, 0, 10); + } + return TRUE; +} + + +INT Set_Trigger_Sounding_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + CHAR *value; + INT i; + MAC_TABLE_ENTRY *pEntry = NULL; + + /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + if(strlen(arg) != 17) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &macAddr[i++], 1); + } + + /*DBGPRINT(RT_DEBUG_TRACE, ("TriggerSounding=%02x:%02x:%02x:%02x:%02x:%02x\n",*/ + /* macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5], macAddr[6]) );*/ + pEntry = MacTableLookup(pAd, macAddr); + if (pEntry==NULL) + return FALSE; + + Trigger_Sounding_Packet(pAd, SNDG_TYPE_SOUNDING, 0, pEntry->sndgMcs, pEntry); + + return TRUE; +} + +/* + Set_ITxBfEn_Proc - enable/disable ITxBF + usage: iwpriv ra0 set ITxBfEn=dd + 0=>disable, 1=>enable +*/ +#ifndef MT76x2 +INT Set_ITxBfEn_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i; + UCHAR enableITxBF; + BOOLEAN bCalibrated; + UINT8 byteValue; + + enableITxBF = simple_strtol(arg, 0, 10); + + if (enableITxBF > 1) + return FALSE; + + bCalibrated = rtmp_chk_itxbf_calibration(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("Set ITxBfEn=%d, calibration of ITxBF=%d, so enableITxBF=%d!\n", + enableITxBF , bCalibrated, (enableITxBF & bCalibrated))); + + enableITxBF &= bCalibrated; + + pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn = enableITxBF && (pAd->Antenna.field.TxPath > 1); + + rtmp_asic_set_bf(pAd); + + for (i=0; iMacTab.Content[i]; + if ((!IS_ENTRY_NONE(pMacEntry)) && (pAd->Antenna.field.TxPath> 1)) + pMacEntry->iTxBfEn = enableITxBF; + + } + + if (enableITxBF || pAd->CommonCfg.ETxBfEnCond) + { + RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue); + byteValue |= 0x40; + RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue); + + RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue); + byteValue |= 0x20; + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue); + } + + /* If enabling ITxBF then set LNA compensation, do a Divider Calibration and update BBP registers */ + if (enableITxBF) { + pAd->chipOps.fITxBfLNAPhaseCompensate(pAd); + pAd->chipOps.fITxBfDividerCalibration(pAd, 2, 0, NULL); + } + else + { + /* depends on Gary Tsao's comments. */ + if (pAd->CommonCfg.ETxBfEnCond == 0) + { + RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue); + byteValue &= (~0x40); + RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue); + + RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue); + byteValue &= (~0x20); + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, 0); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &byteValue); + byteValue &= ~0x60; + for ( i = 0; i < 3; i++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue & (i << 5))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R174, 0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, 0); + } + } + return TRUE; +} + +#else +INT Set_ITxBfEn_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 i; + UCHAR enableITxBF; + BOOLEAN bCalibrated; + UINT8 byteValue; + UINT value32; + ULONG irq_flags; + + + enableITxBF = simple_strtol(arg, 0, 10); + + if (enableITxBF > 1) + return FALSE; + + bCalibrated = rtmp_chk_itxbf_calibration(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("Set ITxBfEn=%d, calibration of ITxBF=%d, so enableITxBF=%d!\n", + enableITxBF , bCalibrated, (enableITxBF & bCalibrated))); + + enableITxBF &= bCalibrated; + + pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn = enableITxBF && (pAd->Antenna.field.TxPath > 1); + + rtmp_asic_set_bf(pAd); + + if (enableITxBF) + { + RTMP_IO_WRITE32(pAd,PFMU_R54, 0x150); // Solve the MCS8 and MCS9 TP degradation when PN on + } + else + { + RTMP_IO_WRITE32(pAd,PFMU_R54, 0x100); + } + + /* Check how many clients could be applied ITxBf */ + for (i=0; iMacTab.Content[i]; + if ((!IS_ENTRY_NONE(pMacEntry)) && (pAd->Antenna.field.TxPath> 1)) + { + pMacEntry->iTxBfEn = enableITxBF; + pMacEntry->HTPhyMode.field.iTxBF = enableITxBF; + +#ifdef MCS_LUT_SUPPORT + asic_mcs_lut_update(pAd, pMacEntry); +#endif /* MCS_LUT_SUPPORT */ + } + } + + /* If enabling ITxBF then set LNA and TX phase compensation */ + if (enableITxBF) { + /* Enable TX/Rx Phase Compensation */ + //mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, 0x28585); + //mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, 0x28585); + //pAd->chipOps.fITxBfLNAPhaseCompensate(pAd); + + /* Enable TX Phase Compensation */ + RTMP_IO_READ32(pAd, TXBE_R12, &value32); + RTMP_IO_WRITE32(pAd, TXBE_R12, value32 | 0x08); + + RtmpOsMsDelay(10); // waiting 10ms + } + else + { + /* Disable Tx/Rx Phase Compensation */ + RTMP_IO_READ32(pAd, TXBE_R12, &value32); + RTMP_IO_WRITE32(pAd, TXBE_R12, value32 & (~0x0FF)); + } + + return TRUE; +} + +#endif + + +/* + Default iBF calibrated channel number is 5 channel, + if Set_ITxBf_Set_Mode_Proc = 2 , then iBF will use 13 channel interpolation mode +*/ +INT Set_ITxBf_Calib_Mode_Proc( + RTMP_ADAPTER *pAd, + PSTRING arg) +{ + UCHAR iBFmode; + iBFmode = simple_strtol(arg, 0, 10); + + if ((iBFmode == 1)||(iBFmode == 2)) + { + pAd->CommonCfg.ITxBfCalibMode = iBFmode; + return TRUE; + } + + return FALSE; +} +#endif /* TXBF_SUPPORT */ + + +#ifdef VHT_TXBF_SUPPORT +/* + The VhtNDPA sounding inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the MCS value. +*/ +INT Set_VhtNDPA_Sounding_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR mac[6]; + UINT mcs; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg)); + + /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and MCS value in decimal format.*/ + if(strlen(arg) < 19) + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + mcs = (UINT)simple_strtol((token+1), 0, 10); + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if (i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + PRINT_MAC(mac), mcs)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + if (pEntry) { +#ifdef SOFT_SOUNDING + pEntry->snd_rate.field.MODE = MODE_VHT; + pEntry->snd_rate.field.BW = (mcs / 100) > BW_80 ? BW_80 : (mcs / 100); + mcs %= 100; + pEntry->snd_rate.field.MCS = ((mcs / 10) << 4 | (mcs % 10)); + + DBGPRINT(RT_DEBUG_OFF, ("%s():Trigger VHT NDPA Sounding=%02x:%02x:%02x:%02x:%02x:%02x, snding rate=VHT-%sHz, %dSS-MCS%d\n", + __FUNCTION__, PRINT_MAC(mac), + get_bw_str(pEntry->snd_rate.field.BW), + (pEntry->snd_rate.field.MCS >> 4) + 1, + pEntry->snd_rate.field.MCS & 0xf)); +#endif + trigger_vht_ndpa(pAd, pEntry); + } + + return TRUE; + } + + return FALSE; +} +#endif /* VHT_TXBF_SUPPORT */ + +#ifdef MT76x2 +#ifdef TXBF_SUPPORT +USHORT PFMU_TimeOut; +UCHAR MatrixForm[5]; +UCHAR StsSnr[2]; +UCHAR TxScale[4]; +UCHAR macAddr[MAC_ADDR_LEN]; +UCHAR FlgStatus[4]; +USHORT CMDInIdx = 0, dCMDInIdx = 0; +UCHAR psi21; +UCHAR phill; + + + +INT Set_TxBfProfileTag_Help( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + printk("========================================================================================================================\n" + "TxBfProfile Tag setting example :\n" + "iwpriv ra0 set TxBfProfileTagMatrix=ng:cw:nrow:nol:LM\n" + "iwpriv ra0 set TxBfProfileTagMac=xx:xx:xx:xx:xx:xx\n" + "iwpriv ra0 set TxBfProfileTagTxScale=Tx1_scale_2ss[7:0]:Tx0_scale_2ss[7:0]:Tx1_scale_1ss[7:0]:Tx0_scale_1ss[7:0]\n" + "iwpriv ra0 set TxBfProfileTagSNR=STS1_SNR[7:0]:STS0_SNR[7:0]\n" + "iwpriv ra0 set TxBfProfileTagTimeOut=timeout[15:0]\n" + "iwpriv ra0 set TxBfProfileTagFlg=LD:EO:IO:I/E\n" + "\n\n" + "iwpriv ra0 set ATETXBF=xx (0:no BF; 1:ETxBF, 2:ITxBF, 3:Enable TXBF support, 4:Disable TXBF support)\n" + "iwpriv ra0 set TxBfProfileTagValid=0/1:profile index\n" + "\n" + "Read TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagRead=xx (select a profile only)\n" + "\n" + "Write TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagWrite=xx (select a profile only)\n" + "\n\n" + "Read TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataRead=xx:xx (select a profile and subcarrier to load seting)\n" + "iwpriv ra0 set TxBfProfileDataReadAll=TxBfType:subcarrier:BW (TxBfType : 0x00 (IxBf), 0x01 (ETxBf)\n" + " (BW : 0x00 (20M) , 0x01 (40M), 0x02 (80M)\n" + "\n" + "Write TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataWrite=profile:subcarrier:psi21:pill\n" + "iwpriv ra0 set TxBfProfileDataWriteAll=TxBfType:subcarrier:BW (TxBfType : 0x00 (IxBf), 0x01 (ETxBf)\n" + " (BW : 0x00 (20M) , 0x01 (40M), 0x02 (80M)\n" + "========================================================================================================================\n"); + + CMDInIdx = 0; // Clear index + return TRUE; +} + + +INT Set_TxBfProfileTagValid( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx, validFlg; + UCHAR Input[2]; + CHAR *value; + UINT value32, readValue32[5]; + INT i; + + /* Profile Select : Subcarrier Select */ + if(strlen(arg) != 5) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &Input[i++], 1); + } + + validFlg = Input[0]; + profileIdx = Input[1]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Read PFMU_R11 ~ R15 + RTMP_IO_READ32(pAd, PFMU_R11, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R12, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R13, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R14, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R15, &readValue32[4]); + + + /* + Update the valid bit + */ + readValue32[0] &= ~(1 << 7); + readValue32[0] |= validFlg << 7; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Write PFMU_R11 ~ R15 + RTMP_IO_WRITE32(pAd, PFMU_R15, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R14, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R13, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R12, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R11, readValue32[0]); + + return TRUE; +} + + +INT Set_TxBfProfileTagRead( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG value64; + UCHAR profileIdx, subcarrierIdx; + UCHAR Input[2]; + CHAR *value, value8; + UINT value32, readValue32[5]; + INT i; + UCHAR validFlg; + + profileIdx = simple_strtol(arg, 0, 10); + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R11, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R12, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R13, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R14, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R15, &readValue32[4]); + + /* + Bit 63:62 ng[1:0] + 61:60 cw[1:0] + 59:58 nrow[1:0] + 57:56 ncol[1:0] + 1 : 0 LM[1:0] + */ + MatrixForm[0] = (UCHAR)((readValue32[1] >> 30) & 0x3); + MatrixForm[1] = (UCHAR)((readValue32[1] >> 28) & 0x3); + MatrixForm[2] = (UCHAR)((readValue32[1] >> 26) & 0x3); + MatrixForm[3] = (UCHAR)((readValue32[1] >> 24) & 0x3); + MatrixForm[4] = (UCHAR)(readValue32[0] & 0x3); + + /* + Bit 55 : 8 Mac Adress [47:0] + */ + macAddr[0] = (UCHAR)((readValue32[1] >> 16) & 0x0FF); + macAddr[1] = (UCHAR)((readValue32[1] >> 8) & 0x0FF); + macAddr[2] = (UCHAR)((readValue32[1]) & 0x0FF); + macAddr[3] = (UCHAR)((readValue32[0] >> 24) & 0x0FF); + macAddr[4] = (UCHAR)((readValue32[0] >> 16) & 0x0FF); + macAddr[5] = (UCHAR)((readValue32[0] >> 8) & 0x0FF); + + /* + Bit 63 : 56 Tx1_scale_2ss[7:0] + 55 : 48 Tx0_scale_2ss[7:0] + 47 : 40 Tx1_scale_1ss[7:0] + 36 : 32 Tx0_scale_2ss[7:0] + */ + TxScale[0] = (UCHAR)((readValue32[3] >> 24) & 0x0FF); + TxScale[1] = (UCHAR)((readValue32[3] >> 16) & 0x0FF); + TxScale[2] = (UCHAR)((readValue32[3] >> 8) & 0x0FF); + TxScale[3] = (UCHAR)((readValue32[3] >> 0) & 0x0FF); + + /* + Bit 31 : 24 STS1_SNR[7:0] + 23 : 16 STS0_SNR[7:0] + */ + StsSnr[0] = (UCHAR)((readValue32[2] >> 24) & 0x0FF); + StsSnr[1] = (UCHAR)((readValue32[2] >> 16) & 0x0FF); + + /* + Bit 15 : 0 PFMU_TimeOut[15:0] + */ + PFMU_TimeOut = (USHORT)(readValue32[2] & 0x0FFFF); + + /* + LD, EO, IO, I/E + */ + FlgStatus[0] = (UCHAR)((readValue32[4] >> 8) & 0x1); + FlgStatus[1] = (UCHAR)((readValue32[4] >> 7) & 0x1); + FlgStatus[2] = (UCHAR)((readValue32[4] >> 6) & 0x1); + FlgStatus[3] = (UCHAR)((readValue32[4] >> 5) & 0x1); + + /* + Check profile valid staus + */ + validFlg = (readValue32[0] >> 7) & 0x1; + + printk("============================= TxBf profile Tage Info ==============================\n" + "Pofile valid status = %d\n" + "Profile index = %d\n\n" + "PFMU_11 = 0x%x, PFMU_R12=0x%x, PFMU_R13=0x%x, PFMU_R14=0x%x\n\n" + "ng[1:0]=%d, cw[1:0]=%d, nrow[1:0]=%d, ncol[1:0]=%d, LM[1:0]=%d\n\n" + "Destimation MAC Address=%x:%x:%x:%x:%x:%x\n\n" + "Tx1_scal_2ss=0x%x, Tx0_scale_2ss=0x%x, Tx1_scal_1ss=0x%x, Tx0_scale_1ss=0x%x\n\n" + "STS1_SNR=0x%x, STS0_SNR=0x%x\n" + "timeout[15:0]=0x%x\n" + "LD=%d, EO=%d, IO=%d, I/E=%d\n" + "===================================================================================\n", + validFlg, + profileIdx, + readValue32[0], readValue32[1], readValue32[2], readValue32[3], + MatrixForm[0], MatrixForm[1], MatrixForm[2], MatrixForm[3], MatrixForm[4], + macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5], + TxScale[0], TxScale[1], TxScale[2], TxScale[3], + StsSnr[0], StsSnr[1], + PFMU_TimeOut, + FlgStatus[0], FlgStatus[1], FlgStatus[2], FlgStatus[3]); + + return TRUE; +} + + +INT Set_TxBfProfileTagWrite( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx, subcarrierIdx; + UCHAR Input[2]; + CHAR *value; + UINT value32, readValue32[5]; + INT i; + + profileIdx = simple_strtol(arg, 0, 10); + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R11, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R12, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R13, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R14, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R15, &readValue32[4]); + + DBGPRINT(RT_DEBUG_TRACE, ("============================= TxBf profile Tage Write ==============================\n" + "Profile index = %d\n\n", + profileIdx)); + + /* + Bit 63:62 ng[1:0] + 61:60 cw[1:0] + 59:58 nrow[1:0] + 57:56 ncol[1:0] + 1 : 0 LM[1:0] + */ + if (CMDInIdx & 1) + { + value32 = (LONG)MatrixForm[0] << 30; + value32 |= (LONG)MatrixForm[1] << 28; + value32 |= (LONG)MatrixForm[2] << 26; + value32 |= (LONG)MatrixForm[3] << 24; + readValue32[1] &= 0x00FFFFFF; + readValue32[1] |= value32; + + readValue32[0] &= ~(0x3); + readValue32[0] |= MatrixForm[4]; + + DBGPRINT(RT_DEBUG_TRACE, ("ng[1:0]=%d, cw[1:0]=%d, nrow[1:0]=%d, ncol[1:0]=%d, LM[1:0]=%d\n\n", + MatrixForm[0], MatrixForm[1], MatrixForm[2], MatrixForm[3], MatrixForm[4])); + } + + /* + Bit 55 : 8 Mac Adress [47:0] + */ + if (CMDInIdx & 2) + { + value32 = (LONG)macAddr[0] << 16; + value32 |= (LONG)macAddr[1] << 8; + value32 |= (LONG)macAddr[2] << 0; + readValue32[1] &= 0xFF000000; + readValue32[1] |= value32; + + value32 = (LONG)macAddr[3] << 24; + value32 |= (LONG)macAddr[4] << 16; + value32 |= (LONG)macAddr[5] << 8; + readValue32[0] &= 0x000000FF; + readValue32[0] |= value32; + + DBGPRINT(RT_DEBUG_TRACE, ("Destimation MAC Address=%x:%x:%x:%x:%x:%x\n\n", + macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5])); + } + + /* + Bit 63 : 56 Tx1_scale_2ss[7:0] + 55 : 48 Tx0_scale_2ss[7:0] + 47 : 40 Tx1_scale_1ss[7:0] + 36 : 32 Tx0_scale_2ss[7:0] + */ + if (CMDInIdx & 4) + { + value32 = (LONG)TxScale[0] << 24; + value32 |= (LONG)TxScale[1] << 16; + value32 |= (LONG)TxScale[2] << 8; + value32 |= (LONG)TxScale[3] << 0; + readValue32[3] = value32; + + DBGPRINT(RT_DEBUG_TRACE, ("Tx1_scal_2ss=0x%x, Tx0_scale_2ss=0x%x, Tx1_scal_1ss=0x%x, Tx0_scale_1ss=0x%x\n\n", + TxScale[0], TxScale[1], TxScale[2], TxScale[3])); + } + + /* + Bit 31 : 24 STS1_SNR[7:0] + 23 : 16 STS0_SNR[7:0] + */ + if (CMDInIdx & 8) + { + value32 = (LONG)StsSnr[0] << 24; + value32 |= (LONG)StsSnr[1] << 16; + readValue32[2] &= 0x0000FFFF; + readValue32[2] |= value32; + + DBGPRINT(RT_DEBUG_TRACE, ("STS1_SNR=0x%x, STS0_SNR=0x%x\n", StsSnr[0], StsSnr[1])); + } + + /* + Bit 15 : 0 timeout[15:0] + */ + if (CMDInIdx & 16) + { + readValue32[2] &= 0xFFFF0000; + readValue32[2] |= (ULONG)PFMU_TimeOut; + + DBGPRINT(RT_DEBUG_TRACE, ("timeout[15:0]=0x%x\n", PFMU_TimeOut)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("PFMU_11 = 0x%x, PFMU_R12=0x%x, PFMU_R13=0x%x, PFMU_R14=0x%x\n\n", + readValue32[0], readValue32[1], readValue32[2], readValue32[3])); + + /* + Bit 15 : 0 timeout[15:0] + */ + if (CMDInIdx & 32) + { + readValue32[4] &= 0xFFFFFE00; + readValue32[4] |= FlgStatus[0] << 8; + readValue32[4] |= FlgStatus[1] << 7; + readValue32[4] |= FlgStatus[2] << 6; + readValue32[4] |= FlgStatus[3] << 5; + + DBGPRINT(RT_DEBUG_TRACE, ("LD=%d, EO=%d, IO=%d, I/E=%d\n" + "===================================================================================\n", + FlgStatus[0], FlgStatus[1], FlgStatus[2], FlgStatus[3])); + } + + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Write PFMU_R11 ~ R15 + RTMP_IO_WRITE32(pAd, PFMU_R15, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R14, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R13, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R12, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R11, readValue32[0]); + + CMDInIdx = 0; // clear tag indicator + + return TRUE; +} + + + +INT Set_TxBfProfileDataRead( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx, subcarrierIdx; + UCHAR Input[2]; + CHAR *value; + UINT value32, readValue32[5]; + INT i; + + printk("arg length=%d\n", strlen(arg)); + + /* Profile Select : Subcarrier Select */ + if(strlen(arg) != 5) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &Input[i++], 1); + } + + profileIdx = Input[0]; + subcarrierIdx = Input[1]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|subcarrierIdx)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + psi21 = (readValue32[0] >> 16) & 0x00FF; + phill = (readValue32[0] >> 0) & 0x00FF; + + printk("============================= TxBf profile Data Info ==============================\n" + "Profile index = %d, subcarrierIdx = %d\n\n" + "PFMU_19 = 0x%x, PFMU_R20=0x%x, PFMU_R21=0x%x, PFMU_R22=0x%x\n\n" + "psi21 = 0x%x\n\n" + "phill = 0x%x\n\n" + "===================================================================================\n", + profileIdx, subcarrierIdx, + readValue32[0], readValue32[1], readValue32[2], readValue32[3], + psi21, phill); + + return TRUE; +} + + + +INT Set_TxBfProfileDataWrite( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx, subcarrierIdx; + UCHAR Input[4]; + CHAR *value; + UINT value32, readValue32[5]; + INT i; + + /* Profile Select : Subcarrier Select */ + if(strlen(arg) != 11) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &Input[i++], 1); + } + + profileIdx = Input[0]; + subcarrierIdx = Input[1]; + + psi21 = Input[2]; + phill = Input[3]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|subcarrierIdx)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + readValue32[0] = (psi21 << 16) | phill; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|subcarrierIdx)); + // Wite PFMU_R19 ~ R23 + RTMP_IO_WRITE32(pAd, PFMU_R23, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R22, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R21, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R20, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R19, readValue32[0]); + + dCMDInIdx = 0; // clear profile data write indicator + + return TRUE; +} + + +static SC_TABLE_ENTRY impSCTable[3] = { {228, 255, 1, 28}, {198, 254, 2, 58}, {134, 254, 2, 122} }; +static SC_TABLE_ENTRY expSCTable[3] = { {228, 255, 1, 28}, {198, 254, 2, 58}, {134, 254, 2, 122} }; + + +INT Set_TxBfProfileDataWriteAll( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx; + USHORT scIndex; + UCHAR TxBfType, BW, psi21_I, phill_I; + CHAR *value; + UINT value32, readValue32[5]; + SC_TABLE_ENTRY *pTab; + UCHAR Input[3]; + INT i; + + + /* Profile Select : Subcarrier Select */ + if(strlen(arg) != 8) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &Input[i++], 1); + } + + TxBfType = Input[0]; + profileIdx = Input[1]; + BW = Input[2]; + + psi21_I = 0x00; + phill_I = 0xFF; + + if (TxBfType == 0) // ITxBf + pTab = &impSCTable[BW]; + else + pTab = &expSCTable[BW]; + + + /* Negative subcarriers */ + for (scIndex = pTab->lwb1; scIndex <= pTab->upb1; scIndex++) + { + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + readValue32[0] = (psi21_I << 16) | phill_I; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Wite PFMU_R19 ~ R23 + RTMP_IO_WRITE32(pAd, PFMU_R23, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R22, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R21, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R20, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R19, readValue32[0]); + + } + + /* Positive subcarriers */ + for (scIndex = pTab->lwb2; scIndex <= pTab->upb2; scIndex++) + { + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + readValue32[0] = (psi21_I << 16) | phill_I; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Wite PFMU_R19 ~ R23 + RTMP_IO_WRITE32(pAd, PFMU_R23, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R22, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R21, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R20, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R19, readValue32[0]); + } + + return TRUE; +} + +INT Set_TxBfProfileDataWriteAllValue( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx; + USHORT scIndex; + UCHAR TxBfType, BW, psi21_I, phill_I; + CHAR *value; + UINT value32, readValue32[5]; + SC_TABLE_ENTRY *pTab; + UCHAR Input[5]; + INT i; + + + /* Profile Select : Subcarrier Select */ + if(strlen(arg) != 8) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &Input[i++], 1); + } + + TxBfType = Input[0]; + profileIdx = Input[1]; + BW = Input[2]; + + psi21_I = Input[3]; + phill_I = Input[4]; + + if (TxBfType == 0) // ITxBf + pTab = &impSCTable[BW]; + else + pTab = &expSCTable[BW]; + + + /* Negative subcarriers */ + for (scIndex = pTab->lwb1; scIndex <= pTab->upb1; scIndex++) + { + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + readValue32[0] = (psi21_I << 16) | phill_I; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Wite PFMU_R19 ~ R23 + RTMP_IO_WRITE32(pAd, PFMU_R23, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R22, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R21, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R20, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R19, readValue32[0]); + + } + + /* Positive subcarriers */ + for (scIndex = pTab->lwb2; scIndex <= pTab->upb2; scIndex++) + { + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + readValue32[0] = (psi21_I << 16) | phill_I; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Wite PFMU_R19 ~ R23 + RTMP_IO_WRITE32(pAd, PFMU_R23, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R22, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R21, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R20, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R19, readValue32[0]); + } + + return TRUE; +} + + + +INT Set_TxBfProfileDataReadAll( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR profileIdx; + UCHAR TxBfType, BW, psi21_I, phill_I; + CHAR *value; + UINT value32, readValue32[5]; + UCHAR Input[3]; + SC_TABLE_ENTRY *pTab; + INT i, scIndex, idx; + + + + /* Profile Select : Subcarrier Select */ + if(strlen(arg) != 8) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &Input[i++], 1); + } + + TxBfType = Input[0]; + profileIdx = Input[1]; + BW = Input[2]; + + if (TxBfType == 0) // ITxBf + pTab = &impSCTable[BW]; + else + pTab = &expSCTable[BW]; + + + /* Negative subcarriers */ + idx = 0; + for (scIndex = pTab->lwb1; scIndex <= pTab->upb1; scIndex++) + { + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + phill_I = readValue32[0] & 0x0FF; + psi21_I = (readValue32[0] >> 16) & 0x0FF; + + if ((idx & 0x7) == 0) + { + printk("\n"); + printk("(%x, %x) ", psi21_I, phill_I); + } + else + printk("(%x, %x) ", psi21_I, phill_I); + + idx++; + } + + printk("\n"); + + /* Positive subcarriers */ + idx = 0; + for (scIndex = pTab->lwb2; scIndex <= pTab->upb2; scIndex++) + { + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|scIndex)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + phill_I = readValue32[0] & 0x0FF; + psi21_I = (readValue32[0] >> 16) & 0x0FF; + + if ((idx & 0x7) == 0) + { + printk("\n"); + printk("(%x, %x) ", psi21_I, phill_I); + } + else + printk("(%x, %x) ", psi21_I, phill_I); + + idx++; + } + + return TRUE; +} + + + +INT Set_TxBfProfileTag_TimeOut( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PFMU_TimeOut = simple_strtol(arg, 0, 10); + + CMDInIdx |= 16; + + return TRUE; +} + + +INT Set_TxBfProfileTag_Matrix( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR *value; + INT i; + + /* ng[1:0], cw[1:0], nrow[1:0], ncol[1:0] */ + if(strlen(arg) != 14) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &MatrixForm[i++], 1); + } + + CMDInIdx |= 1; + + DBGPRINT(RT_DEBUG_TRACE, ("ng[1:0]=%x\n" "cw[1:0]=%x\n" "nrow[1:0]=%x\n" "nol[1:0]=%x\n" "LM[1:0]=%x\n", + MatrixForm[0], MatrixForm[1], MatrixForm[2], MatrixForm[3], MatrixForm[4])); + + return TRUE; +} + + +INT Set_TxBfProfileTag_SNR( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR *value; + INT i; + + /* STS1_SNR: STS0_SNR */ + if(strlen(arg) != 5) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &StsSnr[i++], 1); + } + + CMDInIdx |= 8; + + DBGPRINT(RT_DEBUG_TRACE, ("STS1_SNR=0x%x\n" "STS1_SNR=0x%x\n", + StsSnr[0], StsSnr[1])); + + return TRUE; +} + + +INT Set_TxBfProfileTag_TxScale( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR *value; + INT i; + + /* Tx1_scale_2ss: Tx0_scale_2ss: Tx1_scale_1ss: Tx0_scale_1ss*/ + if(strlen(arg) != 11) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &TxScale[i++], 1); + } + + CMDInIdx |= 4; + + DBGPRINT(RT_DEBUG_TRACE, ("Tx1_scale_2ss=0x%x\n" "Tx0_scale_2ss=0x%x\n" "Tx1_scale_1ss=0x%x\n" "Tx0_scale_1ss=0x%x\n", + TxScale[0], TxScale[1], TxScale[2], TxScale[3])); + + return TRUE; +} + + + +INT Set_TxBfProfileTag_MAC( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR *value; + INT i; + + /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + if(strlen(arg) != 17) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &macAddr[i++], 1); + } + + CMDInIdx |= 2; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBfProfileTage_MAC\n" "DS MAC=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x \n", + macAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5])); + + return TRUE; +} + + +INT Set_TxBfProfileTag_Flg( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR *value; + INT i; + + /* LD, EO, IO, I/E */ + if(strlen(arg) != 11) + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid*/ + + AtoH(value, &FlgStatus[i++], 1); + } + + CMDInIdx |= 32; + + DBGPRINT(RT_DEBUG_TRACE, ("LD=%d\n" "EO=%d\n" "IO=%d\n" "I/E=%d\n", + FlgStatus[0], FlgStatus[1], FlgStatus[2], FlgStatus[3])); + + return TRUE; +} +#endif //TXBF_SUPPORT +#endif //MT76x2 + +#if defined (CONFIG_WIFI_PKT_FWD) +INT Set_WifiFwd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_pro_halt_hook) + wf_fwd_pro_halt_hook(); + } else { + if (wf_fwd_pro_active_hook) + wf_fwd_pro_active_hook(); + } + + return TRUE; +} + +INT Set_WifiFwdAccessSchedule_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_access_schedule_halt_hook) + wf_fwd_access_schedule_halt_hook(); + } else { + if (wf_fwd_access_schedule_active_hook) + wf_fwd_access_schedule_active_hook(); + } + + return TRUE; +} + +INT Set_WifiFwdHijack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_hijack_halt_hook) + wf_fwd_hijack_halt_hook(); + } else { + if (wf_fwd_hijack_active_hook) + wf_fwd_hijack_active_hook(); + } + + return TRUE; +} + +INT Set_WifiFwdRepDevice( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int rep = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::rep=%d\n", __FUNCTION__, rep)); + + if (wf_fwd_get_rep_hook) + wf_fwd_get_rep_hook(rep); + + return TRUE; +} + +INT Set_WifiFwdShowEntry( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (wf_fwd_show_entry_hook) + wf_fwd_show_entry_hook(); + + return TRUE; +} + +INT Set_WifiFwdDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int idx = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::idx=%d\n", __FUNCTION__, idx)); + + if (wf_fwd_delete_entry_hook) + wf_fwd_delete_entry_hook(idx); + + return TRUE; +} + +INT Set_PacketSourceShowEntry( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (packet_source_show_entry_hook) + packet_source_show_entry_hook(); + + return TRUE; +} + +INT Set_PacketSourceDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int idx = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::idx=%d\n", __FUNCTION__, idx)); + + if (packet_source_delete_entry_hook) + packet_source_delete_entry_hook(idx); + + return TRUE; +} +#endif /* CONFIG_WIFI_PKT_FWD */ + +#ifdef DOT11_N_SUPPORT +void assoc_ht_info_debugshow( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR ht_cap_len, + IN HT_CAPABILITY_IE *pHTCapability) +{ + HT_CAP_INFO *pHTCap; + HT_CAP_PARM *pHTCapParm; + EXT_HT_CAP_INFO *pExtHT; +#ifdef TXBF_SUPPORT + HT_BF_CAP *pBFCap; +#endif /* TXBF_SUPPORT */ + + + if (pHTCapability && (ht_cap_len > 0)) + { + pHTCap = &pHTCapability->HtCapInfo; + pHTCapParm = &pHTCapability->HtCapParm; + pExtHT = &pHTCapability->ExtHtCapInfo; +#ifdef TXBF_SUPPORT + pBFCap = &pHTCapability->TxBFCap; +#endif /* TXBF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Peer - 11n HT Info\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tHT Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t HT_RX_LDPC(%d), BW(%d), MIMOPS(%d), GF(%d), ShortGI_20(%d), ShortGI_40(%d)\n", + pHTCap->ht_rx_ldpc, pHTCap->ChannelWidth, pHTCap->MimoPs, pHTCap->GF, + pHTCap->ShortGIfor20, pHTCap->ShortGIfor40)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t TxSTBC(%d), RxSTBC(%d), DelayedBA(%d), A-MSDU(%d), CCK_40(%d)\n", + pHTCap->TxSTBC, pHTCap->RxSTBC, pHTCap->DelayedBA, pHTCap->AMsduSize, pHTCap->CCKmodein40)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t PSMP(%d), Forty_Mhz_Intolerant(%d), L-SIG(%d)\n", + pHTCap->PSMP, pHTCap->Forty_Mhz_Intolerant, pHTCap->LSIGTxopProSup)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tHT Parm Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t MaxRx A-MPDU Factor(%d), MPDU Density(%d)\n", + pHTCapParm->MaxRAmpduFactor, pHTCapParm->MpduDensity)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tHT MCS set: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t RxMCS(%02x %02x %02x %02x %02x) MaxRxMbps(%d) TxMCSSetDef(%02x)\n", + pHTCapability->MCSSet[0], pHTCapability->MCSSet[1], pHTCapability->MCSSet[2], + pHTCapability->MCSSet[3], pHTCapability->MCSSet[4], + (pHTCapability->MCSSet[11]<<8) + pHTCapability->MCSSet[10], + pHTCapability->MCSSet[12])); + + DBGPRINT(RT_DEBUG_TRACE, ("\tExt HT Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t PCO(%d), TransTime(%d), MCSFeedback(%d), +HTC(%d), RDG(%d)\n", + pExtHT->Pco, pExtHT->TranTime, pExtHT->MCSFeedback, pExtHT->PlusHTC, pExtHT->RDGSupport)); + +#ifdef TXBF_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\tTX BF Cap: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t ImpRxCap(%d), RXStagSnd(%d), TXStagSnd(%d), RxNDP(%d), TxNDP(%d) ImpTxCap(%d)\n", + pBFCap->TxBFRecCapable, pBFCap->RxSoundCapable, pBFCap->TxSoundCapable, + pBFCap->RxNDPCapable, pBFCap->TxNDPCapable, pBFCap->ImpTxBFCapable)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t Calibration(%d), ExpCSICapable(%d), ExpComSteerCapable(%d), ExpCSIFbk(%d), ExpNoComBF(%d) ExpComBF(%d)\n", + pBFCap->Calibration, pBFCap->ExpCSICapable, pBFCap->ExpComSteerCapable, + pBFCap->ExpCSIFbk, pBFCap->ExpNoComBF, pBFCap->ExpComBF)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t MinGrouping(%d), CSIBFAntSup(%d), NoComSteerBFAntSup(%d), ComSteerBFAntSup(%d), CSIRowBFSup(%d) ChanEstimation(%d)\n", + pBFCap->MinGrouping, pBFCap->CSIBFAntSup, pBFCap->NoComSteerBFAntSup, + pBFCap->ComSteerBFAntSup, pBFCap->CSIRowBFSup, pBFCap->ChanEstimation)); +#endif /* TXBF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("\nPeer - MODE=%d, BW=%d, MCS=%d, ShortGI=%d, MaxRxFactor=%d, MpduDensity=%d, MIMOPS=%d, AMSDU=%d\n", + pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.BW, + pEntry->HTPhyMode.field.MCS, pEntry->HTPhyMode.field.ShortGI, + pEntry->MaxRAmpduFactor, pEntry->MpduDensity, + pEntry->MmpsMode, pEntry->AMsduSize)); + +#ifdef DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("\tExt Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBss2040CoexistMgmt=%d\n", pEntry->BSS2040CoexistenceMgmtSupport)); +#endif /* DOT11N_DRAFT3 */ + } +} + + +INT Set_BurstMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + pAd->CommonCfg.bRalinkBurstMode = ((Value == 1) ? TRUE : FALSE); + + AsicSetRalinkBurstMode(pAd, pAd->CommonCfg.bRalinkBurstMode); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BurstMode_Proc ::%s\n", + (pAd->CommonCfg.bRalinkBurstMode == TRUE) ? "enabled" : "disabled")); + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC +VOID assoc_vht_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op) +{ + VHT_CAP_INFO *cap_info; + VHT_MCS_SET *mcs_set; + VHT_OP_INFO *op_info; + VHT_MCS_MAP *mcs_map; + + + if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Peer - 11AC VHT Info\n")); + if (vht_cap) + { + cap_info = &vht_cap->vht_cap; + mcs_set = &vht_cap->mcs_set; + + hex_dump("peer vht_cap raw data", (UCHAR *)cap_info, sizeof(VHT_CAP_INFO)); + hex_dump("peer vht_mcs raw data", (UCHAR *)mcs_set, sizeof(VHT_MCS_SET)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tVHT Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tMaxMpduLen(%d), BW(%d), SGI_80M(%d), RxLDPC(%d), TxSTBC(%d), RxSTBC(%d), +HTC-VHT(%d)\n", + cap_info->max_mpdu_len, cap_info->ch_width, cap_info->sgi_80M, cap_info->rx_ldpc, cap_info->tx_stbc, + cap_info->rx_stbc, cap_info->htc_vht_cap)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tMaxAmpduExp(%d), VhtLinkAdapt(%d), RxAntConsist(%d), TxAntConsist(%d)\n", + cap_info->max_ampdu_exp, cap_info->vht_link_adapt, cap_info->rx_ant_consistency, cap_info->tx_ant_consistency)); + mcs_map = &mcs_set->rx_mcs_map; + DBGPRINT(RT_DEBUG_TRACE, ("\t\tRxMcsSet: HighRate(%d), RxMCSMap(%d,%d,%d,%d,%d,%d,%d)\n", + mcs_set->rx_high_rate, mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3, + mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, mcs_map->mcs_ss7)); + mcs_map = &mcs_set->tx_mcs_map; + DBGPRINT(RT_DEBUG_TRACE, ("\t\tTxMcsSet: HighRate(%d), TxMcsMap(%d,%d,%d,%d,%d,%d,%d)\n", + mcs_set->tx_high_rate, mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3, + mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, mcs_map->mcs_ss7)); +#ifdef VHT_TXBF_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\t\tETxBfCap: Bfer(%d), Bfee(%d), SndDim(%d)\n", + cap_info->bfer_cap_su, cap_info->bfee_cap_su, cap_info->num_snd_dimension)); +#endif + } + + if (vht_op) + { + op_info = &vht_op->vht_op_info; + mcs_map = &vht_op->basic_mcs_set; + DBGPRINT(RT_DEBUG_TRACE, ("\tVHT OP Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tChannel Width(%d), CenteralFreq1(%d), CenteralFreq2(%d)\n", + op_info->ch_width, op_info->center_freq_1, op_info->center_freq_2)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBasicMCSSet(SS1:%d, SS2:%d, SS3:%d, SS4:%d, SS5:%d, SS6:%d, SS7:%d)\n", + mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3, + mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, + mcs_map->mcs_ss7)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + +} +#endif /* DOT11_VHT_AC */ + + +INT Set_RateAdaptInterval( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UINT32 ra_time, ra_qtime; + PSTRING token; + char sep = ':'; + ULONG irqFlags; + +/* + The ra_interval inupt string format should be d:d, in units of ms. + =>The first decimal number indicates the rate adaptation checking period, + =>The second decimal number indicates the rate adaptation quick response checking period. +*/ + DBGPRINT(RT_DEBUG_TRACE,("%s():%s\n", __FUNCTION__, arg)); + + token = strchr(arg, sep); + if (token != NULL) + { + *token = '\0'; + + if (strlen(arg) && strlen(token+1)) + { + ra_time = simple_strtol(arg, 0, 10); + ra_qtime = simple_strtol(token+1, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("%s():Set RateAdaptation TimeInterval as(%d:%d) ms\n", + __FUNCTION__, ra_time, ra_qtime)); + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); + pAd->ra_interval = ra_time; + pAd->ra_fast_interval = ra_qtime; +#ifdef CONFIG_AP_SUPPORT + if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + return TRUE; + } + } + + return FALSE; + +} + +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_MonitorMode_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UINT32 Value = 0; + + pAd->monitor_ctrl.current_monitor_mode = simple_strtol(arg, 0, 10); + if(pAd->monitor_ctrl.current_monitor_mode > MONITOR_MODE_FULL_NO_CLONE || pAd->monitor_ctrl.current_monitor_mode < MONITOR_MODE_OFF) + pAd->monitor_ctrl.current_monitor_mode = MONITOR_MODE_OFF; + + DBGPRINT(RT_DEBUG_ERROR, + ("set Current Monitor Mode = %d , range(%d ~ %d)\n" + , pAd->monitor_ctrl.current_monitor_mode,MONITOR_MODE_OFF,MONITOR_MODE_FULL_NO_CLONE)); + + switch(pAd->monitor_ctrl.current_monitor_mode) + { + case MONITOR_MODE_OFF: //reset to normal +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.BssType = BSS_INFRA; +#else + pAd->ApCfg.BssType = BSS_INFRA; +#endif + AsicSetRxFilter(pAd); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + break; + case MONITOR_MODE_REGULAR_RX: //report probe_request only , normal rx filter +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.BssType = BSS_MONITOR; +#else + pAd->ApCfg.BssType = BSS_MONITOR; +#endif + + /* ASIC supporsts sniffer function with replacing RSSI with timestamp. */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + break; + + case MONITOR_MODE_FULL: //fully report, Enable Rx with promiscuous reception + case MONITOR_MODE_FULL_NO_CLONE: +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.BssType = BSS_MONITOR; +#else + pAd->ApCfg.BssType = BSS_MONITOR; +#endif + AsicSetRxFilter(pAd); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + break; + } + return TRUE; +} +#endif /* CONFIG_SNIFFER_SUPPORT */ + + +INT Set_VcoPeriod_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + pAd->chipCap.VcoPeriod = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, + ("VCO Period = %d seconds\n", pAd->chipCap.VcoPeriod)); + return TRUE; +} + +#ifdef SINGLE_SKU +INT Set_ModuleTxpower_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UINT16 Value; + + if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Do NOT accept this command after interface is up.\n")); + return FALSE; + } + + Value = (UINT16)simple_strtol(arg, 0, 10); + pAd->CommonCfg.ModuleTxpower = Value; + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ModuleTxpower_Proc::(ModuleTxpower=%d)\n", pAd->CommonCfg.ModuleTxpower)); + return TRUE; +} +#endif /* SINGLE_SKU */ + +#ifdef SINGLE_SKU_V2 +INT Set_Single_Sku_Debug_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR input = simple_strtol(arg, 0, 10); + if(input!=0) + { + pAd->bSingleSkuDebug = TRUE; + } + else + { + pAd->bSingleSkuDebug = FALSE; + } + + return TRUE; +} +#endif /* SINGLE_SKU_V2 */ + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE +INT set_cap_dump(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG seg = simple_strtol(arg, 0, 10); + CHAR *buf1, *buf2; + UINT32 offset = 0; + + seg = ((seg > 0 && seg <= 4) ? seg : 1); + if (pAd->cap_done == TRUE && (pAd->cap_buf != NULL)) { + switch (seg) + { + case 1: + offset = 0; + break; + case 2: + offset = 0x2000; + break; + case 3: + offset = 0x4000; + break; + case 4: + offset = 0x6000; + break; + } + cap_dump(pAd, (pAd->cap_buf + offset), (pAd->cap_buf + 0x8000 + offset), 0x2000); + } + + return TRUE; +} + + +INT set_cap_start(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG cap_start; + BOOLEAN do_cap; + BOOLEAN cap_done; /* 1: capture done, 0: capture not finish yet */ + + + cap_start = simple_strtol(arg, 0, 10); + do_cap = cap_start == 1 ? TRUE : FALSE; + + if (!pAd->cap_support) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): cap mode is not support yet!\n", __FUNCTION__)); + return FALSE; + } + + if (do_cap) + { + /* + start to do cap, + if auto =>will triggered depends on trigger condition, + if manual =>start immediately + */ + if (pAd->do_cap == FALSE) + asic_cap_start(pAd); + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): alreay in captureing\n", __FUNCTION__)); + } + } + else + { + + if (pAd->do_cap == TRUE) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): force stop captureing\n", __FUNCTION__)); + // TODO: force stop capture! + asic_cap_stop(pAd); + } + else + { + + } + pAd->do_cap = FALSE; + } + return TRUE; +} + + +INT set_cap_trigger_offset(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG trigger_offset; /* in unit of us */ + + trigger_offset = simple_strtol(arg, 0, 10); + + pAd->trigger_offset = (UINT32)trigger_offset; + DBGPRINT(RT_DEBUG_OFF, ("%s():set trigger_offset=%d\n", __FUNCTION__, pAd->trigger_offset)); + + return TRUE; +} + + + +INT set_cap_trigger(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG trigger; /* 1: manual trigger, 2: auto trigger */ + + + trigger = simple_strtol(arg, 0, 10); + pAd->cap_trigger = trigger <= 2 ? trigger : 0; + DBGPRINT(RT_DEBUG_OFF, ("%s():set cap_trigger=%s trigger\n", __FUNCTION__, + (pAd->cap_trigger == 0 ? "Invalid" : + (pAd->cap_trigger == 1 ? "Manual" : "Auto")))); + + return TRUE; +} + + +INT set_cap_type(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG cap_type; /* 1: ADC6, 2: ADC8, 3: FEQ */ + + cap_type = simple_strtol(arg, 0, 10); + + pAd->cap_type = cap_type <= 3 ? cap_type : 0; + DBGPRINT(RT_DEBUG_OFF, ("%s():set cap_type=%s\n", + __FUNCTION__, + pAd->cap_type == 1 ? "ADC6" :\ + (pAd->cap_type == 2 ? "ADC8" : "FEQ"))); + + return TRUE; +} + + +INT set_cap_support(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR cap_support; /* 0: no cap mode; 1: cap mode enable */ + + cap_support = simple_strtol(arg, 0, 10); + pAd->cap_support = (cap_support == 1 ? TRUE : FALSE); + + DBGPRINT(RT_DEBUG_OFF, ("%s():set cap_support=%s\n", + __FUNCTION__, + (pAd->cap_support == TRUE ? "TRUE" : "FALSE"))); + + return TRUE; +} +#endif /* CAPTURE_MODE */ + + +INT set_vco_cal(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR vco_cal; + + vco_cal = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.vco_cal = vco_cal ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vco_cal=%s\n", + __FUNCTION__, (pAd->fpga_ctl.vco_cal ? "Enabled" : "Stopped"))); + + return TRUE; + +} + +INT set_tr_stop(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR stop; + + stop = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.fpga_tr_stop = (stop <= 4 ? stop : 0); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fpga_tr_stop=0x%x\n", __FUNCTION__, pAd->fpga_ctl.fpga_tr_stop)); + + return TRUE; +} + + +INT set_tx_kickcnt(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->fpga_ctl.tx_kick_cnt = (INT)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():tx_kick_cnt=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_kick_cnt)); + + return TRUE; +} + + +INT set_data_phy_mode(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->fpga_ctl.tx_data_phy = (INT)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_phy=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_phy)); + + return TRUE; +} + + +INT set_data_bw(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->fpga_ctl.tx_data_bw = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_bw=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_bw)); + + return TRUE; +} + + +INT set_data_mcs(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR mcs = (UCHAR)simple_strtol(arg, 0, 10); + + pAd->fpga_ctl.tx_data_mcs = mcs; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_mcs=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_mcs)); + + return TRUE; +} + +INT set_data_ldpc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->fpga_ctl.tx_data_ldpc = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_ldpc=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_ldpc)); + + return TRUE; +} + +INT set_data_gi(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->fpga_ctl.tx_data_gi = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_gi=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_gi)); + + return TRUE; +} + + +INT set_data_basize(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->fpga_ctl.data_basize = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_basize=%d\n", __FUNCTION__, pAd->fpga_ctl.data_basize)); + + return TRUE; +} + + +INT set_fpga_mode(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG fpga_on; +#ifdef CONFIG_AP_SUPPORT + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[0].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + fpga_on = simple_strtol(arg, 0, 10); + + if (fpga_on & 2) + pAd->fpga_ctl.tx_data_mcs = 7; + + if (fpga_on & 4) + pAd->fpga_ctl.tx_data_mcs = (1 << 4) | 7; + +#ifdef CONFIG_AP_SUPPORT + if (fpga_on & 0x6) { + pAd->fpga_ctl.tx_data_phy = MODE_VHT; + pAd->fpga_ctl.tx_data_ldpc = 0; + pAd->fpga_ctl.tx_data_bw = BW_80; + pAd->fpga_ctl.tx_data_gi = 1; + pAd->fpga_ctl.data_basize = 31; + wdev->bAutoTxRateSwitch = FALSE; + } + else + { + wdev->bAutoTxRateSwitch = TRUE; + } +#endif /* CONFIG_AP_SUPPORT */ + + pAd->fpga_ctl.fpga_on = fpga_on; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fpga_on=%d\n", __FUNCTION__, pAd->fpga_ctl.fpga_on)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_phy=%d\n", pAd->fpga_ctl.tx_data_phy)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_bw=%d\n", pAd->fpga_ctl.tx_data_bw)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_mcs=%d\n", pAd->fpga_ctl.tx_data_mcs)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_gi=%d\n", pAd->fpga_ctl.tx_data_gi)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_basize=%d\n", pAd->fpga_ctl.data_basize)); + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\tbAutoTxRateSwitch=%d\n", + wdev->bAutoTxRateSwitch)); +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} +#endif /* CONFIG_FPGA_MODE */ + + +#ifdef WFA_VHT_PF +INT set_vht_nss_mcs_cap(RTMP_ADAPTER *pAd, PSTRING arg) +{ + CHAR *token, sep[2] = {':', '-'}; + UCHAR val[3] = {0}, ss, mcs_l, mcs_h, mcs_cap, status = FALSE; + INT idx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string=%s\n", __FUNCTION__, arg)); + ss = mcs_l = mcs_h = 0; + + while (arg) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string[len=%d]=%s\n", __FUNCTION__, strlen(arg), arg)); + if (idx < 2) { + token = rtstrchr(arg, sep[idx]); + if (!token) { + DBGPRINT(RT_DEBUG_TRACE, ("cannot found token '%c' in string \"%s\"!\n", sep[idx], arg)); + return FALSE; + } + *token++ = 0; + } else + token = NULL; + + if (strlen(arg)) { + val[idx] = (UCHAR)simple_strtoul(arg, NULL, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():token string[len=%d]=%s, val[%d]=%d\n", + __FUNCTION__, strlen(arg), arg, idx, val[idx])); + idx++; + } + arg = token; + if (idx == 3) + break; + } + + if (idx <3) + return FALSE; + + ss = val[0]; + mcs_l = val[1]; + mcs_h = val[2]; + DBGPRINT(RT_DEBUG_TRACE, ("ss=%d, mcs_l=%d, mcs_h=%d\n", ss, mcs_l, mcs_h)); + if (ss && mcs_h) + { + if (ss <= pAd->chipCap.max_nss) + pAd->CommonCfg.vht_nss_cap = ss; + else + pAd->CommonCfg.vht_nss_cap = pAd->chipCap.max_nss; + + switch (mcs_h) + { + case 7: + mcs_cap = VHT_MCS_CAP_7; + break; + case 8: + mcs_cap = VHT_MCS_CAP_8; + break; + case 9: + mcs_cap = VHT_MCS_CAP_9; + break; + default: + mcs_cap = VHT_MCS_CAP_9; + break; + } + + if (mcs_h <= pAd->chipCap.max_vht_mcs) + pAd->CommonCfg.vht_mcs_cap = mcs_cap; + else + pAd->CommonCfg.vht_mcs_cap = pAd->chipCap.max_vht_mcs; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():ss=%d, mcs_cap=%d, vht_nss_cap=%d, vht_mcs_cap=%d\n", + __FUNCTION__, ss, mcs_cap, + pAd->CommonCfg.vht_nss_cap, + pAd->CommonCfg.vht_mcs_cap)); + status = TRUE; + } + + return status; +} + + +INT set_vht_nss_mcs_opt(RTMP_ADAPTER *pAd, PSTRING arg) +{ + + + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string=%s\n", __FUNCTION__, arg)); + + return Set_HtMcs_Proc(pAd, arg); +} + + +INT set_vht_opmode_notify_ie(RTMP_ADAPTER *pAd, PSTRING arg) +{ + CHAR *token; + UINT ss, bw; + BOOLEAN status = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string=%s\n", __FUNCTION__, arg)); + token = rtstrchr(arg, ':'); + if (!token) + return FALSE; + + *token = 0; + token++; + if (strlen(arg) && strlen(token)) + { + ss = simple_strtoul(arg, NULL, 10); + bw = simple_strtoul(token, NULL, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("%s():ss=%d, bw=%d\n", __FUNCTION__, ss, bw)); + if (ss > 0 && ss <= 2) + pAd->vht_pf_op_ss = ss; + else + pAd->vht_pf_op_ss = pAd->Antenna.field.RxPath; + + switch (bw) { + case 20: + pAd->vht_pf_op_bw = BAND_WIDTH_20; + break; + case 40: + pAd->vht_pf_op_bw = BAND_WIDTH_40; + break; + case 80: + default: + pAd->vht_pf_op_bw = BAND_WIDTH_80; + break; + } + status = TRUE; + } + + pAd->force_vht_op_mode = status; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():force_vht_op_mode=%d, vht_pf_op_ss=%d, vht_pf_op_bw=%d\n", + __FUNCTION__, pAd->force_vht_op_mode, pAd->vht_pf_op_ss, pAd->vht_pf_op_bw)); + + return status; +} + + +INT set_force_operating_mode(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->force_vht_op_mode = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + + if (pAd->force_vht_op_mode == TRUE) { + pAd->vht_pf_op_ss = 1; // 1SS + pAd->vht_pf_op_bw = BAND_WIDTH_20; // 20M + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_operating_mode=%d\n", + __FUNCTION__, pAd->force_vht_op_mode)); + if (pAd->force_vht_op_mode == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("\tforce_operating_mode as %dSS in 20MHz BW\n", + pAd->vht_pf_op_ss)); + } + + return TRUE; +} + + +INT set_force_noack(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->force_noack = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_noack=%d\n", + __FUNCTION__, pAd->force_noack)); + + return TRUE; +} + + +INT set_force_amsdu(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->force_amsdu = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_amsdu=%d\n", + __FUNCTION__, pAd->force_amsdu)); + return TRUE; +} + + +INT set_force_vht_sgi(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->vht_force_sgi = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vht_force_sgi=%d\n", + __FUNCTION__, pAd->vht_force_sgi)); + + return TRUE; +} + + +INT set_force_vht_tx_stbc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + pAd->vht_force_tx_stbc = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + if (pAd->CommonCfg.TxStream < 2) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): TxStream=%d is not enough for TxSTBC!\n", + __FUNCTION__, pAd->CommonCfg.TxStream)); + pAd->vht_force_tx_stbc = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vht_force_tx_stbc=%d\n", + __FUNCTION__, pAd->vht_force_tx_stbc)); + + return TRUE; +} + + +INT set_force_ext_cca(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG cca_cfg; + UINT32 mac_val; + + cca_cfg = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + if (cca_cfg) + mac_val = 0x04101b3f; + else + mac_val = 0x583f; + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val); + + return TRUE; +} + + +INT set_rx_rts_cts(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT32 do_rx, i; + UINT32 mac_val, mask; + PSTRING cmds[4]={"no", "rts", "cts", "all"}; + + for (i =0 ; i < 4; i++) { + if (strcmp(arg, cmds[i]) ==0) + break; + } + + if (i >= 4) + i = 0; + + RTMP_IO_READ32(pAd, RX_FILTR_CFG, &mac_val); + switch (i) + { + case 1: // receive rts + mac_val &= (~0x1000); + break; + case 2: // receive cts + mac_val &= (~0x0800); + break; + case 3: // receive both + mac_val &= (~0x1800); + break; + case 0: // filter out both rts/cts + default: + mac_val |= 0x1800; + break; + } + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, mac_val); + + RTMP_IO_READ32(pAd, RX_FILTR_CFG, &mac_val); + DBGPRINT(RT_DEBUG_TRACE, ("%s():Configure the RTS/CTS filter as receive %s(0x%x)\n", + __FUNCTION__, cmds[i], mac_val)); + + return TRUE; +} +#endif /* WFA_VHT_PF */ + +INT set_cal_test(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR cal_test_type; + + cal_test_type = simple_strtol(arg, 0, 10); + + if (pAd->chipOps.cal_test) { + pAd->chipOps.cal_test(pAd, cal_test_type); + } + + return 0; + + +} + + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT + +INT Set_PDMAWatchDog_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT32 Dbg; + + Dbg = simple_strtol(arg, 0, 10); + + if (Dbg == 1) + { + pAd->PDMAWatchDogEn = 1; + } + else if (Dbg == 0) + { + pAd->PDMAWatchDogEn = 0; + } + else if (Dbg == 2) + { + WlanResetB(pAd); + } + else if (Dbg == 3) + { + pAd->PDMAWatchDogDbg = 0; + } + else if (Dbg == 4) + { + pAd->PDMAWatchDogDbg = 1; + } + + return TRUE; +} + + +INT Set_WlanResetB_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + ULONG reset; + + reset = simple_strtol(arg, 0, 10); + + if (reset == 1) + WlanResetB(pAd); + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WlanResetB_Proc::(reset=%d)\n", reset)); + + return TRUE; +} +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + + +#ifdef RTMP_PCI_SUPPORT +INT set_cpu_int_analysis(RTMP_ADAPTER *pAd, PSTRING arg) +{ + ULONG total_counter = 0; + pAd->int_cpu_analysis = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): int_cpu_analysis=%d\n", __FUNCTION__, pAd->int_cpu_analysis)); + + if (pAd->int_cpu_analysis == 0) { + pAd->fake_int_counter = 0; + pAd->rx_coherent_counter = 0; + pAd->tx_coherent_counter = 0; + pAd->fifo_int_counter = 0; + pAd->hcca_int_counter = 0; + pAd->tx_ac3_int_counter = 0; + pAd->tx_ac2_int_counter = 0; + pAd->tx_ac1_int_counter = 0; + + /* tx ac0 tasklet related */ + pAd->tx_tasklet_counter = 0; + pAd->tx_int_counter = 0; + pAd->tx_packet_counter = 0; + + /* rx tasklet related */ + pAd->rx_tasklet_counter = 0; + pAd->rx_int_counter = 0; + pAd->rx_packet_counter = 0; + pAd->rx_tasklet_resche_counter = 0; + pAd->rx_packet_1_counter = 0; + pAd->rx_packet_2_counter = 0; + pAd->rx_packet_3_counter = 0; + pAd->rx_packet_4_counter = 0; + pAd->rx_packet_5_counter = 0; + pAd->rx_packet_6_10_counter = 0; + pAd->rx_packet_11_15_counter = 0; + pAd->rx_packet_16_20_counter = 0; + pAd->rx_packet_21_25_counter = 0; + pAd->rx_packet_26_31_counter = 0; + pAd->rx_packet_32_max_counter = 0; + } else if (pAd->int_cpu_analysis == 1) { + unsigned long irqFlags; + ULONG time1, time2, diff; + UINT32 idx = 0, mac_val = 0; + OS_IRQ_LOCK(&pAd->irq_lock, irqFlags); + time1 = jiffies; + + for (idx = 0; idx < 10000000; idx++) + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &mac_val); + + time2 = jiffies; + diff = (time2 - time1) * 1000 / OS_HZ; + DBGPRINT(RT_DEBUG_OFF, ("********* IO read 10000000 round spent %ldms, time1=%ld, time2=%ld\n", diff, time1, time2)); + OS_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + } else if (pAd->int_cpu_analysis == 2) { + unsigned long irqFlags; + ULONG time1, time2, diff; + UINT32 idx = 0; + OS_IRQ_LOCK(&pAd->irq_lock, irqFlags); + time1 = jiffies; + + for (idx = 0; idx < 10000000; idx++) + RTMP_IO_WRITE32(pAd, 0x1314, 0); + + time2 = jiffies; + diff = (time2 - time1) * 1000 / OS_HZ; + DBGPRINT(RT_DEBUG_OFF, ("********* IO write 10000000 round spent %ldms, time1=%ld, time2=%ld\n", diff, time1, time2)); + OS_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + } else if (pAd->int_cpu_analysis == 3) { + total_counter = pAd->rx_packet_1_counter + + pAd->rx_packet_2_counter + + pAd->rx_packet_3_counter + + pAd->rx_packet_4_counter + + pAd->rx_packet_5_counter + + pAd->rx_packet_6_10_counter + + pAd->rx_packet_11_15_counter + + pAd->rx_packet_16_20_counter + + pAd->rx_packet_21_25_counter + + pAd->rx_packet_26_31_counter + + pAd->rx_packet_32_max_counter; + + DBGPRINT(RT_DEBUG_OFF, ("********* Rx tasklet schedule time = %ld\n", pAd->rx_tasklet_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* Rx interrupt time = %ld\n", pAd->rx_int_counter)); + if (pAd->rx_tasklet_counter != 0) + DBGPRINT(RT_DEBUG_OFF, ("********* Rx average packet numbers/tasklet schedule time = %ld\n", + (pAd->rx_packet_counter/pAd->rx_tasklet_counter))); + + DBGPRINT(RT_DEBUG_OFF, ("********* Rx total counter = %ld\n", total_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_tasklet_resche_counter = %ld\n", pAd->rx_tasklet_resche_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_1_counter = %ld\n", pAd->rx_packet_1_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_2_counter = %ld\n", pAd->rx_packet_2_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_3_counter = %ld\n", pAd->rx_packet_3_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_4_counter = %ld\n", pAd->rx_packet_4_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_5_counter = %ld\n", pAd->rx_packet_5_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_6_10_counter = %ld\n", pAd->rx_packet_6_10_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_11_15_counter = %ld\n", pAd->rx_packet_11_15_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_16_20_counter = %ld\n", pAd->rx_packet_16_20_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_21_25_counter = %ld\n", pAd->rx_packet_21_25_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_26_31_counter = %ld\n", pAd->rx_packet_26_31_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx_packet_32_max_counter = %ld\n", pAd->rx_packet_32_max_counter)); + + DBGPRINT(RT_DEBUG_OFF, ("********* fake interrupt counter = %ld\n", pAd->fake_int_counter)); + } else if (pAd->int_cpu_analysis == 4) { + DBGPRINT(RT_DEBUG_OFF, ("********* Tx ac0 tasklet schedule time = %ld\n", pAd->tx_tasklet_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* Tx ac0 interrupt time = %ld\n", pAd->tx_int_counter)); + if (pAd->tx_tasklet_counter != 0) + DBGPRINT(RT_DEBUG_OFF, ("********* Tx average packet numbers/tasklet schedule time = %ld\n", + (pAd->tx_packet_counter/pAd->tx_tasklet_counter))); + DBGPRINT(RT_DEBUG_OFF, ("********* fake interrupt counter = %ld\n", pAd->fake_int_counter)); + } else if (pAd->int_cpu_analysis == 5) { + DBGPRINT(RT_DEBUG_OFF, ("********* Rx tasklet schedule time = %ld\n", pAd->rx_tasklet_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* Rx interrupt time = %ld\n", pAd->rx_int_counter)); + if (pAd->rx_tasklet_counter != 0) + DBGPRINT(RT_DEBUG_OFF, ("********* Rx average packet numbers/tasklet schedule time = %ld\n\n", + (pAd->rx_packet_counter/pAd->rx_tasklet_counter))); + + DBGPRINT(RT_DEBUG_OFF, ("********* Tx ac0 tasklet schedule time = %ld\n", pAd->tx_tasklet_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* Tx ac0 interrupt time = %ld\n", pAd->tx_int_counter)); + if (pAd->tx_tasklet_counter != 0) + DBGPRINT(RT_DEBUG_OFF, ("********* Tx average packet numbers/tasklet schedule time = %ld\n\n", + (pAd->tx_packet_counter/pAd->tx_tasklet_counter))); + + DBGPRINT(RT_DEBUG_OFF, ("********* fake interrupt counter = %ld\n", pAd->fake_int_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* tx coherent counter = %ld\n", pAd->tx_coherent_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* rx coherent counter = %ld\n", pAd->rx_coherent_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* fifo interrupt counter = %ld\n", pAd->fifo_int_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* hcca interrupt counter = %ld\n", pAd->hcca_int_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* tx ac3 interrupt counter = %ld\n", pAd->tx_ac3_int_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* tx ac2 interrupt counter = %ld\n", pAd->tx_ac2_int_counter)); + DBGPRINT(RT_DEBUG_OFF, ("********* tx ac1 interrupt counter = %ld\n", pAd->tx_ac1_int_counter)); + } + + return TRUE; +} +#endif + +#ifdef DOT11_N_SUPPORT + +#ifdef MT76x2 +#define MAX_AGG_CNT 48 +#elif defined(RT65xx) || defined(MT7601) +#define MAX_AGG_CNT 32 +#elif defined(RT2883) || defined(RT3883) +#define MAX_AGG_CNT 16 +#else +#define MAX_AGG_CNT 8 +#endif + +/* DisplayTxAgg - display Aggregation statistics from MAC */ +void DisplayTxAgg (RTMP_ADAPTER *pAd) +{ + ULONG totalCount; + ULONG aggCnt[MAX_AGG_CNT + 2]; + int i; + + AsicReadAggCnt(pAd, aggCnt, sizeof(aggCnt) / sizeof(ULONG)); + totalCount = aggCnt[0] + aggCnt[1]; + if (totalCount > 0) + for (i=0; ichipCap.rf_type == RF_RLT) + ret = set_rlt_rf(pAd, arg); +#endif /* RLT_RF*/ + +#ifdef MT_RF + if (pAd->chipCap.rf_type == RF_MT) + ret = set_mt_rf(pAd, arg); +#endif /* MT_RF */ + +#ifdef RT6352 + if (pAd->chipCap.rf_type == RF_RT) + ret = set_rtmp_rf(pAd, arg); +#endif /* RT6352 */ + + return ret; +} + + +INT set_rf_bit(RTMP_ADAPTER *pAd, PSTRING arg) +{ + INT ret; + +#ifdef MT_RF + if (pAd->chipCap.rf_type == RF_MT) + ret = set_mt_rf_bit(pAd, arg); +#endif /* MT_RF */ + + return ret; +} + + +static struct { + PSTRING name; + INT (*show_proc)(RTMP_ADAPTER *pAd, PSTRING arg, ULONG BufLen); +} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = { +#ifdef DBG + {"SSID", Show_SSID_Proc}, + {"WirelessMode", Show_WirelessMode_Proc}, + {"TxBurst", Show_TxBurst_Proc}, + {"TxPreamble", Show_TxPreamble_Proc}, + {"TxPower", Show_TxPower_Proc}, + {"Channel", Show_Channel_Proc}, + {"BGProtection", Show_BGProtection_Proc}, + {"RTSThreshold", Show_RTSThreshold_Proc}, + {"FragThreshold", Show_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Show_HtBw_Proc}, + {"HtMcs", Show_HtMcs_Proc}, + {"HtGi", Show_HtGi_Proc}, + {"HtOpMode", Show_HtOpMode_Proc}, + {"HtExtcha", Show_HtExtcha_Proc}, + {"HtMpduDensity", Show_HtMpduDensity_Proc}, + {"HtBaWinSize", Show_HtBaWinSize_Proc}, + {"HtRdg", Show_HtRdg_Proc}, + {"HtAmsdu", Show_HtAmsdu_Proc}, + {"HtAutoBa", Show_HtAutoBa_Proc}, +#endif /* DOT11_N_SUPPORT */ + {"CountryRegion", Show_CountryRegion_Proc}, + {"CountryRegionABand", Show_CountryRegionABand_Proc}, + {"CountryCode", Show_CountryCode_Proc}, +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Show_PktAggregate_Proc}, +#endif + + {"WmmCapable", Show_WmmCapable_Proc}, + + {"IEEE80211H", Show_IEEE80211H_Proc}, +#ifdef CONFIG_STA_SUPPORT + {"NetworkType", Show_NetworkType_Proc}, +#ifdef WSC_STA_SUPPORT + {"WpsApBand", Show_WpsPbcBand_Proc}, + {"Manufacturer", Show_WpsManufacturer_Proc}, + {"ModelName", Show_WpsModelName_Proc}, + {"DeviceName", Show_WpsDeviceName_Proc}, + {"ModelNumber", Show_WpsModelNumber_Proc}, + {"SerialNumber", Show_WpsSerialNumber_Proc}, +#endif /* WSC_STA_SUPPORT */ + {"WPAPSK", Show_WPAPSK_Proc}, + {"AutoReconnect", Show_AutoReconnect_Proc}, +#endif /* CONFIG_STA_SUPPORT */ + {"AuthMode", Show_AuthMode_Proc}, + {"EncrypType", Show_EncrypType_Proc}, + {"DefaultKeyID", Show_DefaultKeyID_Proc}, + {"Key1", Show_Key1_Proc}, + {"Key2", Show_Key2_Proc}, + {"Key3", Show_Key3_Proc}, + {"Key4", Show_Key4_Proc}, + {"PMK", Show_PMK_Proc}, +#ifdef SINGLE_SKU + {"ModuleTxpower", Show_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ +#endif /* DBG */ + {"rainfo", Show_STA_RAInfo_Proc}, + {NULL, NULL} +}; + + +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN PSTRING pName, + IN PSTRING pBuf, + IN UINT32 MaxLen) +{ + INT Status = 0; + + for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) + { + if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) + { + if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf, MaxLen)) + Status = -EINVAL; + break; /*Exit for loop.*/ + } + } + + if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL) + { + snprintf(pBuf, MaxLen, "\n"); + for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) + { + if ((strlen(pBuf) + strlen(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) >= MaxLen) + break; + sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name); + } + } + + return Status; +} + + +INT show_pwr_info(RTMP_ADAPTER *ad, PSTRING arg) +{ + if (ad->chipOps.show_pwr_info) { + ad->chipOps.show_pwr_info(ad); + } + + return 0; +} + +#ifdef DBG_DIAGNOSE +INT Show_Diag_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + RtmpDiagStruct *pDiag = NULL; + UCHAR i, start, stop, McsIdx, SwQNumLevel, TxDescNumLevel; + unsigned long irqFlags; + UCHAR McsMaxIdx = MAX_MCS_SET; +#ifdef DOT11_VHT_AC + UCHAR vht_mcs_max_idx = MAX_VHT_MCS_SET; +#endif /* DOT11_VHT_AC */ + + os_alloc_mem(pAd, (PUCHAR *)&pDiag, sizeof(RtmpDiagStruct)); + if (!pDiag) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():AllocMem failed!\n", __FUNCTION__)); + return FALSE; + } + +#ifdef RTMP_PCI_SUPPORT + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); +#endif + NdisMoveMemory(pDiag, &pAd->DiagStruct, sizeof(RtmpDiagStruct)); + +#ifdef RTMP_PCI_SUPPORT + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); +#endif + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + McsMaxIdx = 24; +#endif /* DOT11N_SS3_SUPPORT */ + + if (pDiag->inited == FALSE) + goto done; + + start = pDiag->ArrayStartIdx; + stop = pDiag->ArrayCurIdx; + printk("Start=%d, stop=%d!\n\n", start, stop); + printk(" %-12s", "Time(Sec)"); + for(i=1; i< DIAGNOSE_TIME; i++) + { + printk("%-7d", i); + } + printk("\n -------------------------------------------------------------------------------\n"); + printk("Tx Info:\n"); + printk(" %-12s", "TxDataCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].TxDataCnt); + } + printk("\n %-12s", "TxFailCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].TxFailCnt); + } + +#ifdef DBG_TX_AGG_CNT + printk("\n %-12s", "TxAggCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].TxAggCnt); + } + printk("\n"); +#endif /* DBG_TX_AGG_CNT */ + +#ifdef DBG_TXQ_DEPTH + printk("\n %-12s\n", "Sw-Queued TxSwQCnt"); + for (SwQNumLevel = 0 ; SwQNumLevel < 9; SwQNumLevel++) + { + if (SwQNumLevel == 8) + printk("\t>%-5d", SwQNumLevel); + else + printk("\t%-6d", SwQNumLevel); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxSWQueCnt[SwQNumLevel]); + + printk("\n"); + } +#endif /* DBG_TXQ_DEPTH */ + +#ifdef DBG_TX_RING_DEPTH + printk("\n %-12s\n", "DMA-Queued TxDescCnt"); + for(TxDescNumLevel = 0; TxDescNumLevel < 16; TxDescNumLevel++) + { + if (TxDescNumLevel == 15) + printk("\t>%-5d", TxDescNumLevel); + else + printk("\t%-6d", TxDescNumLevel); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxDescCnt[TxDescNumLevel]); + + printk("\n"); + } +#endif /* DBG_TX_RING_DEPTH */ + +#ifdef DOT11_N_SUPPORT +#ifdef DBG_TX_AGG_CNT + printk("\n %-12s\n", "Tx-Agged AMPDUCnt"); + for (McsIdx =0 ; McsIdx < 16; McsIdx++) + { + printk("\t%-6d", (McsIdx+1)); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%d(%d%%) ", pDiag->diag_info[i].TxAMPDUCnt[McsIdx], + pDiag->diag_info[i].TxAMPDUCnt[McsIdx] ? (pDiag->diag_info[i].TxAMPDUCnt[McsIdx] * 100 / pDiag->diag_info[i].TxAggCnt) : 0); + } + printk("\n"); + } +#endif /* DBG_TX_AGG_CNT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_TX_MCS + printk("\n %-12s\n", "TxMcsCnt_HT"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxMcsCnt_HT[McsIdx]); + printk("\n"); + } + +#ifdef DOT11_VHT_AC + printk("\n %-12s\n", "TxMcsCnt_VHT"); + for (McsIdx =0 ; McsIdx < vht_mcs_max_idx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxMcsCnt_VHT[McsIdx]); + printk("\n"); + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + + + + printk("Rx Info\n"); + printk(" %-12s", "RxDataCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].RxDataCnt); + } + printk("\n %-12s", "RxCrcErrCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].RxCrcErrCnt); + } + +#ifdef DBG_RX_MCS + printk("\n %-12s\n", "RxMcsCnt_HT"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("(%d,%d)\t", pDiag->diag_info[i].RxCrcErrCnt_HT[McsIdx], pDiag->diag_info[i].RxMcsCnt_HT[McsIdx] + pDiag->diag_info[i].RxCrcErrCnt_HT[McsIdx]); + } + printk("\n"); + } + +#ifdef DOT11_VHT_AC + printk("\n %-12s\n", "RxMcsCnt_VHT"); + for (McsIdx =0 ; McsIdx < vht_mcs_max_idx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("(%d,%d)\t", pDiag->diag_info[i].RxCrcErrCnt_VHT[McsIdx], pDiag->diag_info[i].RxMcsCnt_VHT[McsIdx] + pDiag->diag_info[i].RxCrcErrCnt_VHT[McsIdx]); + } + printk("\n"); + } +#endif /* DOT11_VHT_AC */ + +#endif /* DBG_RX_MCS */ + + printk("\n-------------\n"); + +done: + os_free_mem(pAd, pDiag); + return TRUE; +} +#endif /* DBG_DIAGNOSE */ + +#ifdef CONFIG_CALIBRATION_COLLECTION +INT Show_Cal_Info(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR i = 0; + for (i=R_CALIBRATION_7662;i<=RXIQC_FD_CALIBRATION_7662;i++) + dump_calibration_info(pAd, i); + + return TRUE; +} +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_loft_cal.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_loft_cal.c new file mode 100644 index 000000000..93afcbb23 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_loft_cal.c @@ -0,0 +1,1203 @@ +/* + *************************************************************************** + * 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: + cmm_loft_cal.c + + Abstract: + Tx LOFT calibration and profile related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#include "rt_config.h" + +#ifdef RT6352 +#define I_PATH 0x0 +#define Q_PATH 0x1 + +#define CHAIN_0 0x0 +#define CHAIN_1 0x1 + +#define RF_ALC_NUM 6 +#define CHAIN_NUM 2 +#define _BBP_REG_NUM 168 + +typedef struct _RF_REG_PAIR +{ + UCHAR Bank; + UCHAR Register; + UCHAR Value; +} RF_REG_PAIR, *PRF_REG_PAIR; + +static VOID RFConfigStore( + IN RTMP_ADAPTER *pAd, + OUT RF_REG_PAIR rf_reg_record[][13], + IN UCHAR chain) +{ + UCHAR RFValue = 0; + + if (chain == CHAIN_0) + { + /* save before config */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &RFValue); + rf_reg_record[CHAIN_0][0].Bank = RF_BANK0; + rf_reg_record[CHAIN_0][0].Register = RF_R01; + rf_reg_record[CHAIN_0][0].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &RFValue); + rf_reg_record[CHAIN_0][1].Bank = RF_BANK0; + rf_reg_record[CHAIN_0][1].Register = RF_R02; + rf_reg_record[CHAIN_0][1].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK0, RF_R35, &RFValue); + rf_reg_record[CHAIN_0][2].Bank = RF_BANK0; + rf_reg_record[CHAIN_0][2].Register = RF_R35; + rf_reg_record[CHAIN_0][2].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFValue); + rf_reg_record[CHAIN_0][3].Bank = RF_BANK0; + rf_reg_record[CHAIN_0][3].Register = RF_R42; + rf_reg_record[CHAIN_0][3].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK4, RF_R00, &RFValue); + rf_reg_record[CHAIN_0][4].Bank = RF_BANK4; + rf_reg_record[CHAIN_0][4].Register = RF_R00; + rf_reg_record[CHAIN_0][4].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK4, RF_R02, &RFValue); + rf_reg_record[CHAIN_0][5].Bank = RF_BANK4; + rf_reg_record[CHAIN_0][5].Register = RF_R02; + rf_reg_record[CHAIN_0][5].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK4, RF_R34, &RFValue); + rf_reg_record[CHAIN_0][6].Bank = RF_BANK4; + rf_reg_record[CHAIN_0][6].Register = RF_R34; + rf_reg_record[CHAIN_0][6].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFValue); + rf_reg_record[CHAIN_0][7].Bank = RF_BANK5; + rf_reg_record[CHAIN_0][7].Register = RF_R03; + rf_reg_record[CHAIN_0][7].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &RFValue); + rf_reg_record[CHAIN_0][8].Bank = RF_BANK5; + rf_reg_record[CHAIN_0][8].Register = RF_R04; + rf_reg_record[CHAIN_0][8].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &RFValue); + rf_reg_record[CHAIN_0][9].Bank = RF_BANK5; + rf_reg_record[CHAIN_0][9].Register = RF_R17; + rf_reg_record[CHAIN_0][9].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &RFValue); + rf_reg_record[CHAIN_0][10].Bank = RF_BANK5; + rf_reg_record[CHAIN_0][10].Register = RF_R18; + rf_reg_record[CHAIN_0][10].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &RFValue); + rf_reg_record[CHAIN_0][11].Bank = RF_BANK5; + rf_reg_record[CHAIN_0][11].Register = RF_R19; + rf_reg_record[CHAIN_0][11].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &RFValue); + rf_reg_record[CHAIN_0][12].Bank = RF_BANK5; + rf_reg_record[CHAIN_0][12].Register = RF_R20; + rf_reg_record[CHAIN_0][12].Value = RFValue; + + } + else if (chain == CHAIN_1) + { + /* save before config */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &RFValue); + rf_reg_record[CHAIN_1][0].Bank = RF_BANK0; + rf_reg_record[CHAIN_1][0].Register = RF_R01; + rf_reg_record[CHAIN_1][0].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &RFValue); + rf_reg_record[CHAIN_1][1].Bank = RF_BANK0; + rf_reg_record[CHAIN_1][1].Register = RF_R02; + rf_reg_record[CHAIN_1][1].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK0, RF_R35, &RFValue); + rf_reg_record[CHAIN_1][2].Bank = RF_BANK0; + rf_reg_record[CHAIN_1][2].Register = RF_R35; + rf_reg_record[CHAIN_1][2].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFValue); + rf_reg_record[CHAIN_1][3].Bank = RF_BANK0; + rf_reg_record[CHAIN_1][3].Register = RF_R42; + rf_reg_record[CHAIN_1][3].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK6, RF_R00, &RFValue); + rf_reg_record[CHAIN_1][4].Bank = RF_BANK6; + rf_reg_record[CHAIN_1][4].Register = RF_R00; + rf_reg_record[CHAIN_1][4].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK6, RF_R02, &RFValue); + rf_reg_record[CHAIN_1][5].Bank = RF_BANK6; + rf_reg_record[CHAIN_1][5].Register = RF_R02; + rf_reg_record[CHAIN_1][5].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK6, RF_R34, &RFValue); + rf_reg_record[CHAIN_1][6].Bank = RF_BANK6; + rf_reg_record[CHAIN_1][6].Register = RF_R34; + rf_reg_record[CHAIN_1][6].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFValue); + rf_reg_record[CHAIN_1][8].Bank = RF_BANK7; + rf_reg_record[CHAIN_1][8].Register = RF_R03; + rf_reg_record[CHAIN_1][8].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R04, &RFValue); + rf_reg_record[CHAIN_1][7].Bank = RF_BANK7; + rf_reg_record[CHAIN_1][7].Register = RF_R04; + rf_reg_record[CHAIN_1][7].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R17, &RFValue); + rf_reg_record[CHAIN_1][9].Bank = RF_BANK7; + rf_reg_record[CHAIN_1][9].Register = RF_R17; + rf_reg_record[CHAIN_1][9].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R18, &RFValue); + rf_reg_record[CHAIN_1][10].Bank = RF_BANK7; + rf_reg_record[CHAIN_1][10].Register = RF_R18; + rf_reg_record[CHAIN_1][10].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R19, &RFValue); + rf_reg_record[CHAIN_1][11].Bank = RF_BANK7; + rf_reg_record[CHAIN_1][11].Register = RF_R19; + rf_reg_record[CHAIN_1][11].Value = RFValue; + RT635xReadRFRegister(pAd, RF_BANK7, RF_R20, &RFValue); + rf_reg_record[CHAIN_1][12].Bank = RF_BANK7; + rf_reg_record[CHAIN_1][12].Register = RF_R20; + rf_reg_record[CHAIN_1][12].Value = RFValue; + + } + else + { + DBGPRINT_ERR(("%s: Unknown chain = %u\n", __FUNCTION__, chain)); + return; + } + + return; +} + + +static VOID RFConfigRecover(RTMP_ADAPTER *pAd, RF_REG_PAIR RF_record[][13]) +{ + UCHAR chain_index = 0, record_index = 0; + UCHAR bank = 0, rf_register = 0, value = 0; + + for (chain_index = 0; chain_index < 2; chain_index++) + { + for (record_index = 0; record_index < 13; record_index++) + { + bank = RF_record[chain_index][record_index].Bank; + rf_register = RF_record[chain_index][record_index].Register; + value = RF_record[chain_index][record_index].Value; + RT635xWriteRFRegister(pAd, bank, rf_register, value); + DBGPRINT(RT_DEBUG_TRACE, ("bank: %d, rf_register: %d, value: %x\n", + bank, rf_register, value)); + } + } + + + return; +} + + +static VOID SetBbpToneGenerator( + IN RTMP_ADAPTER *pAd) +{ + UCHAR BBPValue = 0; + + /* choose FFT tone generator index (to 0) */ + BBPValue = 0xaa; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + /* set subcarrier index (subsample ratio to 10 * 0.3125MHz) */ + BBPValue = 0xab; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x0a; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + /* I/Q amplitude of tone gen0 */ + BBPValue = 0xac; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); /* I signal */ + BBPValue = 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + BBPValue = 0xad; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); /* Q signal */ + BBPValue = 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + /* enable tone gen */ + BBPValue = 0x40; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, BBPValue); + + return; +} + + +UINT32 Do_FFT_Accumulation(IN RTMP_ADAPTER *pAd, UCHAR tone_idx, UCHAR read_neg) +{ + UINT32 MacValue = 0; + int fftout_i = 0, fftout_q = 0; + UINT32 power_tmp=0, power_int = 0; + UCHAR BBPValue = 0; + UCHAR tone_idx_int; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x9b); + + BBPValue = 0x9b; + + while(BBPValue == 0x9b) + { + RtmpusecDelay(10); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BBPValue); + BBPValue = BBPValue &0xff; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xba); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx); + + RTMP_IO_READ32(pAd, 0x057C, &MacValue); + + fftout_i = (MacValue >> 16); + fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i; + fftout_q = (MacValue & 0xffff); + fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q; + power_tmp = (fftout_i * fftout_i); + power_tmp = power_tmp + (fftout_q * fftout_q); + power_int = power_tmp; + DBGPRINT(RT_DEBUG_TRACE, ("I = %d, Q = %d, power = %x\n", fftout_i, fftout_q, power_int)); + if(read_neg){ + power_int = power_int >> 1; + tone_idx_int = 0x40 - tone_idx; + tone_idx_int = tone_idx_int & 0x3f; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xba); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx_int); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx_int); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx_int); + + RTMP_IO_READ32(pAd, 0x057C, &MacValue); + + fftout_i = (MacValue >> 16); + fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i; + fftout_q = (MacValue & 0xffff); + fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q; + power_tmp = (fftout_i * fftout_i); + power_tmp = power_tmp + (fftout_q * fftout_q); + power_tmp = power_tmp >> 1; + power_int = power_int + power_tmp; + + } + + return power_int; +} + +#ifdef RT6352_EP_SUPPORT +UINT32 Read_FFT_Accumulation(IN RTMP_ADAPTER *pAd, UCHAR tone_idx) +{ + UINT32 MacValue = 0; + int fftout_i = 0, fftout_q = 0; + UINT32 power_tmp=0, power_int = 0; + UCHAR BBPValue = 0; + UCHAR tone_idx_int; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xba); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, tone_idx); + + RTMP_IO_READ32(pAd, 0x057C, &MacValue); + + fftout_i = (MacValue >> 16); + fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i; + fftout_q = (MacValue & 0xffff); + fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q; + power_tmp = (fftout_i * fftout_i); + power_tmp = power_tmp + (fftout_q * fftout_q); + power_int = power_tmp; + DBGPRINT(RT_DEBUG_TRACE, ("I = %d, Q = %d, power = %x\n", fftout_i, fftout_q, power_int)); + + return power_int; +} +#endif /* RT6352_EP_SUPPORT */ + +static VOID Write_DC( + RTMP_ADAPTER *pAd, + UCHAR chain_idx, + UCHAR alc, + UCHAR iorq, + UCHAR dc) +{ + UCHAR BBPValue = 0; + + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb0); + BBPValue = alc | 0x80; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + if (chain_idx == 0) + BBPValue = (iorq == 0) ? 0xb1: 0xb2; + else + BBPValue = (iorq == 0) ? 0xb8: 0xb9; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = dc; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + return; +} + + +static VOID LOFT_Search( + IN RTMP_ADAPTER *pAd, + IN UCHAR chain_idx, + IN UCHAR alc_idx, + OUT UCHAR dc_result[][RF_ALC_NUM][2]) +{ + UINT32 pwr0 = 0, pwr1 = 0, pwr_final = 0; + CHAR index0 = 0,index1 = 0; + UCHAR index_final[] = {0x00, 0x00}; + UCHAR inverted_bit = 0x20; + UCHAR iorq; + CHAR bit_index; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x80); + + for (bit_index = 5; bit_index >= 0; bit_index--) + { + for (iorq = 0; iorq <= 1; iorq++) + { + DBGPRINT(RT_DEBUG_INFO, ("========================================================\n")); + + if (index_final[iorq] == 0x20) + { + index0 = 0x20; + pwr0 = pwr_final; + } + else + { + index0 = index_final[iorq] - inverted_bit; + index0 = index0 & 0x3f; + Write_DC(pAd, chain_idx, 0, iorq, index0); + pwr0 = Do_FFT_Accumulation(pAd,0xa,0); + } + + index1 = index_final[iorq] + ((bit_index == 5) ? 0 : inverted_bit); + index1 = index1 & 0x3f; + Write_DC(pAd, chain_idx, 0, iorq, index1); + pwr1 = Do_FFT_Accumulation(pAd, 0xa,0); + + DBGPRINT(RT_DEBUG_INFO, ("alc=%u, IorQ=%u, idx_final=%2x\n", alc_idx, iorq, index_final[iorq])); + DBGPRINT(RT_DEBUG_INFO, ("pwr0=%x, pwr1=%x, pwr_final=%x, idx_0=%x, idx_1=%x, inverted_bit=%x !\n" + ,pwr0, pwr1, pwr_final, index0, index1, inverted_bit)); + + if ((bit_index != 5) && (pwr_final <= pwr0) && (pwr_final < pwr1)) + { + pwr_final = pwr_final; + index_final[iorq] = index_final[iorq]; + } + else if (pwr0 < pwr1) + { + pwr_final = pwr0; + index_final[iorq] = index0 & 0x3f; + } + else + { + pwr_final = pwr1; + index_final[iorq] = index1 & 0x3f; + } + DBGPRINT(RT_DEBUG_INFO, ("IorQ=%u, idx_final[%u]:%x, pwr_final:%8x\n" + , iorq, iorq, index_final[iorq], pwr_final)); + + Write_DC(pAd, chain_idx, 0, iorq, index_final[iorq]); + + } + inverted_bit = inverted_bit >> 1; + } + dc_result[chain_idx][alc_idx][0] = index_final[0]; + dc_result[chain_idx][alc_idx][1] = index_final[1]; + + return; +} + + +static VOID IQ_Search( + IN RTMP_ADAPTER *pAd, + IN UCHAR chain_idx, + OUT UCHAR *gain_error_store, + OUT UCHAR *phase_error_store) +{ + UINT32 pwr0 = 0, pwr1 = 0, pwr_final = 0; + CHAR phase_err = 0, gain_err = 0, iq_err = 0; + CHAR phase_err_fine = 0, gain_err_fine = 0; + CHAR phase_st,phase_end; + CHAR gain_st,gain_end; + + UCHAR inverted_bit = 0x20; + UCHAR first_search = 0x00, touch_neg_max = 0x00; + UCHAR index0 = 0, index1 = 0; + UCHAR gain_or_phase; + UCHAR BBPValue = 0; + CHAR bit_index; + + DBGPRINT(RT_DEBUG_ERROR, ("IQCalibration Start!\n")); + for (bit_index = 5; bit_index >= 1; bit_index--) + { + for (gain_or_phase = 0; gain_or_phase < 2; gain_or_phase++) + { + DBGPRINT(RT_DEBUG_INFO, ("========================================================\n")); + + if ((gain_or_phase == 1) || (bit_index < 4)) + { + if (gain_or_phase == 0) + iq_err = gain_err; + else + iq_err = phase_err; + + first_search = (gain_or_phase == 0) ? (bit_index == 3) : (bit_index == 5); + touch_neg_max = (gain_or_phase) ? ((iq_err & 0x0f) == 0x8) : ((iq_err & 0x3f) == 0x20); + + if (touch_neg_max) + { + pwr0 = pwr_final; + index0 = iq_err; + } + else + { + index0 = iq_err - inverted_bit; + BBPValue = (chain_idx == 0) ? + ((gain_or_phase == 0) ? 0x28 : 0x29): + ((gain_or_phase == 0) ? 0x46 : 0x47); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, index0); + + pwr0 = Do_FFT_Accumulation(pAd,0x14,1); + } + + index1 = iq_err + (first_search ? 0 : inverted_bit); + index1 = (gain_or_phase == 0) ? (index1 & 0xf) : (index1 & 0x3f); + + BBPValue = (chain_idx == 0) ? + (gain_or_phase == 0) ? 0x28 : 0x29 : + (gain_or_phase == 0) ? 0x46 : 0x47; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, index1); + + pwr1 = Do_FFT_Accumulation(pAd,0x14,1); + + DBGPRINT(RT_DEBUG_INFO, ("pwr0=%x, pwr1=%x, pwer_final=%x, index0=%x, index1=%x, iq_err=%x, gain_or_phase=%d, inverted_bit=%x !\n", + pwr0, pwr1, pwr_final, index0, index1, iq_err, gain_or_phase, inverted_bit)); + + if ((!first_search) && (pwr_final <= pwr0) && (pwr_final < pwr1)) + { + pwr_final = pwr_final; + } + else if (pwr0 < pwr1) + { + pwr_final = pwr0; + iq_err = index0; + } + else + { + pwr_final = pwr1; + iq_err = index1; + } + + BBPValue = (chain_idx == 0) ? + (gain_or_phase == 0) ? 0x28 : 0x29 : + (gain_or_phase == 0) ? 0x46 : 0x47; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, iq_err); + + if (gain_or_phase == 0) + gain_err = iq_err; + else + phase_err = iq_err; + + DBGPRINT(RT_DEBUG_INFO, ("IQCalibration pwr_final=%8x (%2x, %2x) !\n" + , pwr_final, gain_err & 0xf, phase_err & 0x3f)); + + } /* end if */ + } /* end gain_or_phase */ + + if(bit_index > 0) + inverted_bit = (inverted_bit >> 1); + } + gain_err = (gain_err & 0x8 ) ? (gain_err & 0xf ) - 0x10 : (gain_err & 0xf ); + phase_err = (phase_err & 0x20) ? (phase_err & 0x3f) - 0x40 : (phase_err & 0x3f); + + gain_err = (gain_err < -0x7) ? -0x7 : + (gain_err > 0x5) ? 0x5 : + gain_err; + gain_st = gain_err - 1; + gain_end = gain_err + 2; + + phase_err =(phase_err < -0x1f) ? -0x1f : + (phase_err > 0x1d) ? 0x1d : + phase_err; + phase_st = phase_err - 1; + phase_end = phase_err + 2; + + for(gain_err_fine = gain_st; gain_err_fine <= gain_end; gain_err_fine = gain_err_fine + 1) + for(phase_err_fine = phase_st; phase_err_fine <= phase_end; phase_err_fine = phase_err_fine + 1){ + BBPValue = (chain_idx == 0) ? 0x28 : 0x46; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, gain_err_fine & 0xf); + + BBPValue = (chain_idx == 0) ? 0x29 : 0x47; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, phase_err_fine & 0x3f); + + pwr1 = Do_FFT_Accumulation(pAd,0x14,1); + if((gain_err_fine == gain_st) && (phase_err_fine == phase_st)){ + pwr_final = pwr1; + gain_err = gain_err_fine; + phase_err = phase_err_fine; + } + else if(pwr_final > pwr1){ + pwr_final = pwr1; + gain_err = gain_err_fine; + phase_err = phase_err_fine; + } + DBGPRINT(RT_DEBUG_INFO, ("Fine IQCalibration pwr1=%8x pwr_final=%8x (%2x, %2x) !\n", + pwr1, pwr_final, gain_err_fine & 0xf, phase_err_fine & 0x3f)); + } + + gain_error_store[chain_idx] = gain_err & 0xf; + phase_error_store[chain_idx] = phase_err & 0x3f; + + DBGPRINT(RT_DEBUG_ERROR, ("IQCalibration Done! CH = %u, (gain=%2x, phase=%2x)\n" + , chain_idx, gain_err & 0xf, phase_err & 0x3f)); + + return; +} + + +static VOID RF_AUX_TX0_LOOPBACK(RTMP_ADAPTER *pAd) +{ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x21); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, 0x10); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0x1b); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R00, 0x81); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R02, 0x81); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R34, 0xee); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, 0x2d); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x2d); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xd7); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0xa2); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x20); +} + +static VOID RF_AUX_TX1_LOOPBACK(RTMP_ADAPTER *pAd) +{ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x22); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0x4b); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R00, 0x81); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R02, 0x81); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R34, 0xee); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, 0x2d); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x2d); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, 0xd7); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, 0xa2); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, 0x20); +} + +VOID LOFT_IQ_Calibration(RTMP_ADAPTER *pAd) +{ + RF_REG_PAIR RF_Store[CHAIN_NUM][13]; + UINT32 MacOrg1 = 0; /* TX_PIN_CFG */ + UINT32 MacOrg2 = 0; /* RF_CONTROL0 */ + UINT32 MacOrg3 = 0; /* RTMP_RF_BYPASS0 */ + UINT32 MacOrg4 = 0; /* RF_CONTROL3 */ + UINT32 MacOrg5 = 0; /* RF_BYPASS3 */ + UINT32 ORIG528 = 0; + UINT32 ORIG52C = 0; + + UINT32 saveMacSysCtrl = 0,MTxCycle = 0; + UINT32 MacValue = 0; + UINT32 Mac13b8 = 0; +// UINT32 table_dc_i0 = 0; +// UINT32 table_dc_q0 = 0; +// UINT32 table_dc_i1 = 0; +// UINT32 table_dc_q1 = 0; + UINT32 pwr0 = 0, pwr1 = 0; +#ifdef RT6352_EP_SUPPORT + UINT32 pwr0_idx10= 0, pwr1_idx10 = 0; +#endif /* RT6352_EP_SUPPORT */ + + UCHAR RFValue; + UCHAR LOFT_DC_Search_Result[CHAIN_NUM][RF_ALC_NUM][2]; /* 0: I_PATH; 1: Q_PATH */ + UCHAR gain_error_result[CHAIN_NUM], phase_error_result[CHAIN_NUM]; + UCHAR RF_gain[] = {0x0, 0x1, 0x2, 0x4,0x8,0xc}; + UCHAR RFVGA_gain_table[]= + { 0x24, 0x25, 0x26, 0x27, //[0:2:6] + 0x28, 0x2c, 0x2d, 0x2e, //[8:2:14] + 0x2f, 0x30, 0x31, 0x38, //[16:2:22] + 0x39, 0x3a, 0x3b, 0x3c, //[24:2:30] + 0x3d, 0x3e, 0x3f }; //[32:2:36] + +// UCHAR VGA_gain[] = {0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3bi; + CHAR VGA_gain[] = {14, 14}; + UCHAR BBP_2324gain[] = {0x16, 0x14, 0x12, 0x10, 0xc, 0x8}; + UCHAR BBPValue = 0, chain_idx = 0, rf_alc_idx = 0, idx = 0; + UCHAR BBPR30Value, RFB0_R39, RFB0_R42; +#ifdef RT6352_EP_SUPPORT + UCHAR BBP_R1_Value; + UCHAR BBP_R4_Value; + UCHAR BBPR241, BBPR242; +#endif /* RT6352_EP_SUPPORT */ + UCHAR count_step; + + //RF self Tx DC calibration + //RF_SELF_TXDC_CAL(pAd); + /* backup before MAC RF Interface config */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MacOrg1); + RTMP_IO_READ32(pAd, RF_CONTROL0, &MacOrg2); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0, &MacOrg3); + RTMP_IO_READ32(pAd, RF_CONTROL3, &MacOrg4); + RTMP_IO_READ32(pAd, RF_BYPASS3, &MacOrg5); + RTMP_IO_READ32(pAd, 0x13b8 , &Mac13b8); + RTMP_IO_READ32(pAd, RF_CONTROL2, &ORIG528); + RTMP_IO_READ32(pAd, RF_BYPASS2, &ORIG52C); + + /* MAC Tx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + MacValue &= (~0x04); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue); + if (MacValue & 0x1) + RtmpusecDelay(50); + else + break; + } + + /* MAC Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + MacValue &= (~0x08); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue); + if (MacValue & 0x2) + RtmpusecDelay(50); + else + break; + } + + /* + step 1: manually turn on ADC8, ADC6, PA, Tx, Rx, + and bypass ALC control + */ + + /* backup RF registers before config */ + for (chain_idx = 0; chain_idx < 2; chain_idx++) + { + RFConfigStore(pAd, RF_Store, chain_idx); + } + + /* Backup ADC clcok selection */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R30, &BBPR30Value); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R39, &RFB0_R39); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFB0_R42); + + /* change to Shielding clock */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R30, 0x1F); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, 0x5B); + + /* step 7: set BBP tone generator */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + + SetBbpToneGenerator(pAd); + + for( chain_idx = 0; chain_idx < 2; chain_idx ++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x0000000f); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000004); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x00003306); + RTMP_IO_WRITE32(pAd, 0x13b8 , 0x10); + RtmpusecDelay(1); + + if (chain_idx == 0) + { + /* step 2: set RF loopback for ANT0 */ + RF_AUX_TX0_LOOPBACK(pAd); + } + else + { + /* step 4: set RF loopback for ANT1 */ + RF_AUX_TX1_LOOPBACK(pAd); + } + RtmpusecDelay(1); + if(chain_idx == 0) + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00001004); + } + else + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00002004); + } + + /* step 8: set accumulation length */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + + /* step 9: set chain index */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + if(chain_idx == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); /* for pair 0 */ + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x01); /* for pair 0 */ + + /* step 10: for loop of chain 0 with rf_alc_idx */ + VGA_gain[chain_idx] = 18; + for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) + { + /* step 13: manually set BBP digital power control */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, BBP_2324gain[rf_alc_idx]); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BBP_2324gain[rf_alc_idx]); + + /* step 11: manually set RF ALC code */ + RTMP_IO_READ32(pAd, RF_CONTROL3, &MacValue); /* fix RF ALC */ + MacValue &= (~0x0000f1f1); + MacValue |= (RF_gain[rf_alc_idx] << 4); + MacValue |= (RF_gain[rf_alc_idx] << 12); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, MacValue); + MacValue = (0x0000f1f1); + RTMP_IO_WRITE32(pAd, RF_BYPASS3, MacValue); + + /* step 12: manually set RF VGA gain */ + if(rf_alc_idx == 0) { + Write_DC(pAd, chain_idx, 0, 1, 0x21); + for(;VGA_gain[chain_idx] > 0;VGA_gain[chain_idx] = VGA_gain[chain_idx] -2){ + RFValue = RFVGA_gain_table[VGA_gain[chain_idx]]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, RFValue); + Write_DC(pAd, chain_idx, 0, 1, 0x0); + Write_DC(pAd, chain_idx, 0, 0, 0x0); + pwr0 = Do_FFT_Accumulation(pAd, 0xa,0); + Write_DC(pAd, chain_idx, 0, 0, 0x21); + pwr1 = Do_FFT_Accumulation(pAd, 0xa,0); + DBGPRINT(RT_DEBUG_TRACE, ("LOFT AGC %d %d\n",pwr0,pwr1)); + if((pwr0 < 7000*7000) && (pwr1 < (7000*7000))){ + break; + } + } + /* for alc = 0 calibration, clean the dc value */ + Write_DC(pAd, chain_idx, 0, 0, 0x0); + Write_DC(pAd, chain_idx, 0, 1, 0x0); + + DBGPRINT(RT_DEBUG_TRACE, ("Used VGA %d %x\n",VGA_gain[chain_idx], RFVGA_gain_table[VGA_gain[chain_idx]])); + + if(VGA_gain[chain_idx] < 0) + VGA_gain[chain_idx] = 0; + + } + + RFValue = RFVGA_gain_table[VGA_gain[chain_idx]]; + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, RFValue); + + /* step 14, step 15, and step 16: search */ + LOFT_Search(pAd, chain_idx, rf_alc_idx, LOFT_DC_Search_Result); + } + + } + + /* step 19: write back compensate value */ + for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) + { +// DBGPRINT(RT_DEBUG_OFF, ("dc_result[0][%u][0]=%x, dc_result[0][%u][1]=%x\n" +// , rf_alc_idx, LOFT_DC_Search_Result[0][rf_alc_idx][0], rf_alc_idx +// , LOFT_DC_Search_Result[0][rf_alc_idx][1])); +// DBGPRINT(RT_DEBUG_OFF, ("dc_result[1][%u][0]=%x, dc_result[1][%u][1]=%x\n" +// , rf_alc_idx, LOFT_DC_Search_Result[1][rf_alc_idx][0], rf_alc_idx +// , LOFT_DC_Search_Result[1][rf_alc_idx][1])); + + + for (idx = 0; idx < 4; idx++) + { +// table_dc_i0 = LOFT_DC_Search_Result[0][(idx == 0) ? 0 : (idx+2)][0] - LOFT_DC_Search_Result[0][0][0]; +// table_dc_q0 = LOFT_DC_Search_Result[0][(idx == 0) ? 0 : (idx+2)][1] - LOFT_DC_Search_Result[0][0][1]; +// table_dc_i1 = LOFT_DC_Search_Result[1][(idx == 0) ? 0 : (idx+2)][0] - LOFT_DC_Search_Result[1][0][0]; +// table_dc_q1 = LOFT_DC_Search_Result[1][(idx == 0) ? 0 : (idx+2)][1] - LOFT_DC_Search_Result[1][0][1]; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb0); + BBPValue = (idx<<2) + rf_alc_idx; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, (" ALC %2x,", BBPValue)); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb1); + BBPValue = LOFT_DC_Search_Result[CHAIN_0][rf_alc_idx][I_PATH]; + BBPValue = BBPValue & 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, (" I0 %2x,", BBPValue)); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb2); + BBPValue = LOFT_DC_Search_Result[CHAIN_0][rf_alc_idx][Q_PATH]; + BBPValue = BBPValue & 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, (" Q0 %2x,", BBPValue)); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb8); + BBPValue = LOFT_DC_Search_Result[CHAIN_1][rf_alc_idx][I_PATH]; + BBPValue = BBPValue & 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, (" I1 %2x,", BBPValue)); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb9); + BBPValue = LOFT_DC_Search_Result[CHAIN_1][rf_alc_idx][Q_PATH]; + BBPValue = BBPValue & 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, (" Q1 %2x\n", BBPValue)); + + } + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x04); + /* change BBP Tx to normal state */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x00); + /* BBP soft reset */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x01); + RtmpusecDelay(1); /* wait 1 usec */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x00); + + /* recover RF registers */ + RFConfigRecover(pAd, RF_Store); + + /* recover MAC registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacOrg1); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x04); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacOrg2); + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MacOrg3); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, MacOrg4); + RTMP_IO_WRITE32(pAd, RF_BYPASS3, MacOrg5); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, ORIG528); + RTMP_IO_WRITE32(pAd, RF_BYPASS2, ORIG52C); + RTMP_IO_WRITE32(pAd, 0x13b8 , Mac13b8); + + DBGPRINT(RT_DEBUG_ERROR, ("LOFT Calibration Done!\n")); + + /*************************************************************************/ + /* start I/Q calibration */ + + /* backup before MAC RF Interface config */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MacOrg1); + RTMP_IO_READ32(pAd, RF_CONTROL0, &MacOrg2); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0, &MacOrg3); + RTMP_IO_READ32(pAd, RF_CONTROL3, &MacOrg4); + RTMP_IO_READ32(pAd, RF_BYPASS3, &MacOrg5); + +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBP_R1_Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBP_R4_Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R241, &BBPR241); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R242, &BBPR242); +#endif /* RT6352_EP_SUPPORT */ + RTMP_IO_READ32(pAd, 0x13b8 , &Mac13b8); + + /* MAC Tx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + MacValue &= (~0x04); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue); + if (MacValue & 0x1) + RtmpusecDelay(50); + else + break; + } + + /* MAC Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + MacValue &= (~0x08); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue); + if (MacValue & 0x2) + RtmpusecDelay(50); + else + break; + } + + /* + step 1: manually turn on ADC8, ADC6, PA, Tx, Rx, + and bypass ALC control + */ +#ifdef RT6352_EP_SUPPORT + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x00000101); + RTMP_IO_WRITE32(pAd, RF_BYPASS3 , 0x0000f1f1); +#endif /* RT6352_EP_SUPPORT */ + + /* manually set RF ALC code */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBP_R4_Value & (~0x18)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x1); + RtmpusecDelay(1); /* wait 1 usec */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x0); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, 0x14); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, 0x80); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x31); +#else + SetBbpToneGenerator(pAd); +#endif /* RT6352_EP_SUPPORT */ + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000004); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x00003306); + RtmpusecDelay(1); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG , 0x0000000f); +#ifndef RT6352_EP_SUPPORT + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x00000000); + RTMP_IO_WRITE32(pAd, RF_BYPASS3 , 0x0000f1f1); +#endif /* RT6352_EP_SUPPORT */ + RTMP_IO_WRITE32(pAd, 0x13b8, 0x00000010); + + /* backup before RF registers before config */ + for (chain_idx = 0; chain_idx < 2; chain_idx++) + { + RFConfigStore(pAd, RF_Store, chain_idx); + } + + /* step 3: set BBP tone generator */ + + /* step 6: manually set RF VGA gain */ + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, 0x3b); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x3b); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, 0x3b); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x3b); + + + /* step 9: enable Amp/Phase IQ compensation & LOFT compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x60); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x80); + + for (chain_idx = 0; chain_idx < 2; chain_idx ++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + + if (chain_idx == 0) + { + /* step 2: set RF loopback for ANT0 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); /* for pair 0 */ +#ifdef RT6352_EP_SUPPORT + // BBP only Tx0 + BBPValue = BBP_R1_Value & (~ 0x18); + BBPValue = BBPValue | 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPValue); +#endif /* RT6352_EP_SUPPORT */ + RF_AUX_TX0_LOOPBACK(pAd); + } + else + { + /* step 2: set RF loopback for ANT1 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x01); /* for pair 0 */ +#ifdef RT6352_EP_SUPPORT + // BBP only Tx1 + BBPValue = BBP_R1_Value & (~ 0x18); + BBPValue = BBPValue | 0x08; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPValue); +#endif /* RT6352_EP_SUPPORT */ + RF_AUX_TX1_LOOPBACK(pAd); + } + + if(chain_idx == 0) + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00001004); + } + else + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00002004); + } + + /* step 8: set calibration length */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x04); + + /* step 10: search for chain 0 */ + // clear gain value + BBPValue = (chain_idx == 0) ? 0x28 : 0x46; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x0); + +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x6); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x6); +#else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x1F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x1F); +#endif /* RT6352_EP_SUPPORT */ + +#ifdef RT6352_EP_SUPPORT + count_step = 1; +#else + count_step = 2; +#endif /* RT6352_EP_SUPPORT */ + + for(;VGA_gain[chain_idx] < 19; VGA_gain[chain_idx]=(VGA_gain[chain_idx]+ count_step)){ + RFValue = RFVGA_gain_table[VGA_gain[chain_idx]]; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFValue); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, RFValue); + + BBPValue = (chain_idx == 0) ? 0x29 : 0x47; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x0); + pwr0 = Do_FFT_Accumulation(pAd,0x14,0); +#ifdef RT6352_EP_SUPPORT + pwr0_idx10 = Read_FFT_Accumulation(pAd,0xa); +#endif /* RT6352_EP_SUPPORT */ + BBPValue = (chain_idx == 0) ? 0x29 : 0x47; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x21); + pwr1 = Do_FFT_Accumulation(pAd,0x14,0); +#ifdef RT6352_EP_SUPPORT + pwr1_idx10 = Read_FFT_Accumulation(pAd,0xa); +#endif /* RT6352_EP_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("IQ AGC %d %d\n",pwr0,pwr1)); +#ifdef RT6352_EP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("IQ AGC IDX 10 %d %d\n",pwr0_idx10,pwr1_idx10)); + if((pwr0_idx10 > 7000*7000) ||(pwr1_idx10 > 7000*7000)){ + if(VGA_gain[chain_idx]!=0) + VGA_gain[chain_idx] = VGA_gain[chain_idx]-1; + break; + } +#endif /* RT6352_EP_SUPPORT */ + + if((pwr0 >2500*2500) || (pwr1 > 2500*2500)){ + break; + } + } + + if (VGA_gain[chain_idx] > 18) + VGA_gain[chain_idx] = 18; + DBGPRINT(RT_DEBUG_TRACE, ("Used VGA %d %x\n",VGA_gain[chain_idx], RFVGA_gain_table[VGA_gain[chain_idx]])); + + BBPValue = (chain_idx == 0) ? 0x29 : 0x47; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x0); + + + IQ_Search(pAd, chain_idx, gain_error_result, phase_error_result); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x04); + + /* step 19: write back compensate value */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x28); + BBPValue = gain_error_result[CHAIN_0] & 0x0f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x29); + BBPValue = phase_error_result[CHAIN_0] & 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x46); + BBPValue = gain_error_result[CHAIN_1] & 0x0f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x47); + BBPValue = phase_error_result[CHAIN_1] & 0x3f; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBP_R1_Value); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, BBPR241); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, BBPR242); +#endif /* RT6352_EP_SUPPORT */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x00); + + /* change BBP Tx to normal state */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0xb0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + + /* restore ADC clcok selection */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R30, BBPR30Value); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R39, RFB0_R39); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFB0_R42); + +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBP_R4_Value); +#endif /* RT6352_EP_SUPPORT */ + + /* BBP soft reset */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x01); + RtmpusecDelay(1); /* wait 1 usec */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x00); + + /* recover RF registers */ + RFConfigRecover(pAd, RF_Store); + + /* recover MAC registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacOrg1); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x0); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacOrg2); + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MacOrg3); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, MacOrg4); + RTMP_IO_WRITE32(pAd, RF_BYPASS3, MacOrg5); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, 0x13b8 , Mac13b8); + + DBGPRINT(RT_DEBUG_ERROR, ("TX IQ Calibration Done!\n")); + + return; +} +#endif /* RT6352 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mac_pci.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mac_pci.c new file mode 100644 index 000000000..f30877c3d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mac_pci.c @@ -0,0 +1,2908 @@ +/**************************************************************************** + * 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. + ***************************************************************************/ + + + +#ifdef RTMP_MAC_PCI +#include "rt_config.h" + + +static INT desc_ring_alloc(RTMP_ADAPTER *pAd, RTMP_DMABUF *pDescRing, INT size) +{ + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + pDescRing->AllocSize = size; + RtmpAllocDescBuf(pci_dev, + 0, + pDescRing->AllocSize, + FALSE, + &pDescRing->AllocVa, + &pDescRing->AllocPa); + + if (pDescRing->AllocVa == NULL) + { + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + return ERRLOG_OUT_OF_SHARED_MEMORY; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pDescRing->AllocVa, size); + + return 0; +} + + +static INT desc_ring_free(RTMP_ADAPTER *pAd, RTMP_DMABUF *pDescRing) +{ + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + if (pDescRing->AllocVa) + { + RtmpFreeDescBuf(pci_dev, + pDescRing->AllocSize, + pDescRing->AllocVa, + pDescRing->AllocPa); + } + NdisZeroMemory(pDescRing, sizeof(RTMP_DMABUF)); + + return TRUE; +} + + +#ifdef RESOURCE_PRE_ALLOC +VOID RTMPResetTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + int index, j; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; + RTMP_DMACB *dma_cb; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket; + ULONG IrqFlags; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + /* Free TxSwQueue Packet*/ + for (index=0; index TxSwQueue[index]; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + + /* Free Tx Ring Packet*/ + for (index=0;index< NUM_OF_TX_RING;index++) + { + pTxRing = &pAd->TxRing[index]; + for (j=0; j< TX_RING_SIZE; j++) + { + dma_cb = &pTxRing->Cell[j]; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)(dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (dma_cb->AllocVa); +#endif /* RT_BIG_ENDIAN */ + pPacket = dma_cb->pNdisPacket; + + if (pPacket) + { + dma_cb->pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + pPacket = dma_cb->pNextNdisPacket; + if (pPacket) + { + dma_cb->pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + } + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + for (index=0;index< NUM_OF_RX_RING;index++) + { + UINT16 RxRingSize = (index == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + RTMP_IRQ_LOCK(&pAd->RxRingLock[index], IrqFlags); + + for (j = RxRingSize - 1 ; j >= 0; j--) + { + dma_cb = &pAd->RxRing[index].Cell[j]; + if ((dma_cb->DmaBuf.AllocVa) && (dma_cb->pNdisPacket)) + { + PCI_UNMAP_SINGLE(pAd, dma_cb->DmaBuf.AllocPa, dma_cb->DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, dma_cb->pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing[index].Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + + RTMP_IRQ_UNLOCK(&pAd->RxRingLock[index], IrqFlags); + } + + if (pAd->FragFrame.pFragPacket) + { + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + pAd->FragFrame.pFragPacket = NULL; + } + + NdisFreeSpinLock(&pAd->CmdQLock); +} + + +VOID RTMPFreeTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + INT num; + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + + /* Free Rx/Mgmt Desc buffer*/ + for (num = 0; num < NUM_OF_RX_RING; num++) + { +#ifdef RT_SECURE_DMA + if (pAd->RxSecureDMA[num].AllocVa) + { + + NdisZeroMemory(pAd->RxSecureDMA[num].AllocVa, pAd->RxSecureDMA[num].AllocSize); + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->RxSecureDMA[num].AllocSize, + FALSE, pAd->RxSecureDMA[num].AllocVa, + pAd->RxSecureDMA[num].AllocPa); + } +#endif + desc_ring_free(pAd, &pAd->RxDescRing[num]); + } + + +#ifdef RT_SECURE_DMA + if (pAd->MgmtSecureDMA.AllocVa) + { + + NdisZeroMemory(pAd->MgmtSecureDMA.AllocVa, pAd->MgmtSecureDMA.AllocSize); + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->MgmtSecureDMA.AllocSize, + FALSE, pAd->MgmtSecureDMA.AllocVa, + pAd->MgmtSecureDMA.AllocPa); + } +#endif + desc_ring_free(pAd, &pAd->MgmtDescRing); +#ifdef CONFIG_ANDES_SUPPORT +#ifdef RT_SECURE_DMA + if (pAd->CtrlSecureDMA.AllocVa) + { + + NdisZeroMemory(pAd->CtrlSecureDMA.AllocVa, pAd->CtrlSecureDMA.AllocSize); + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->CtrlSecureDMA.AllocSize, + FALSE, pAd->CtrlSecureDMA.AllocVa, + pAd->CtrlSecureDMA.AllocPa); + } +#endif + desc_ring_free(pAd, &pAd->CtrlDescRing); +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Free 1st TxBufSpace and TxDesc buffer*/ + for (num = 0; num < NUM_OF_TX_RING; num++) + { + if (pAd->TxBufSpace[num].AllocVa) + { + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->TxBufSpace[num].AllocSize, + FALSE, pAd->TxBufSpace[num].AllocVa, + pAd->TxBufSpace[num].AllocPa); + } + NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); + +#ifdef RT_SECURE_DMA + if (pAd->TxSecureDMA[num].AllocVa) + { + + NdisZeroMemory(pAd->TxSecureDMA[num].AllocVa, pAd->TxSecureDMA[num].AllocSize); + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->TxSecureDMA[num].AllocSize, + FALSE, pAd->TxSecureDMA[num].AllocVa, + pAd->TxSecureDMA[num].AllocPa); + } +#endif + desc_ring_free(pAd, &pAd->TxDescRing[num]); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + + +NDIS_STATUS RTMPInitTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + INT num, index; + ULONG RingBasePaHigh, RingBasePaLow; + VOID *RingBaseVa; + RTMP_TX_RING *pTxRing; + RTMP_RX_RING *pRxRing; + RTMP_DMABUF *pDmaBuf, *pDescRing; + RTMP_DMACB *dma_cb; + PNDIS_PACKET pPacket; + TXD_STRUC *pTxD; + RXD_STRUC *pRxD; + ULONG ErrorValue = 0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + + /* Init the CmdQ and CmdQLock*/ + NdisAllocateSpinLock(pAd, &pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + /* Initialize All Tx Ring Descriptors and associated buffer memory*/ + /* (5 TX rings = 4 ACs + 1 HCCA)*/ + for (num = 0; num < NUM_OF_TX_RING; num++) + { + ULONG BufBasePaHigh, BufBasePaLow; + VOID *BufBaseVa; + + /* memory zero the Tx ring descriptor's memory */ + pDescRing = &pAd->TxDescRing[num]; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + + /* Zero init all 1st TXBuf's memory for this TxRing*/ + NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); + /* Save PA & VA for further operation */ + BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); + BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); + BufBaseVa = pAd->TxBufSpace[num].AllocVa; + + if (BufBasePaHigh == 0) + {/* empty address high */} + + /* linking Tx Ring Descriptor and associated buffer memory */ + pTxRing = &pAd->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) + { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (PTXD_STRUC)dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry initialized\n", num, index)); + } + + /* Initialize MGMT Ring and associated buffer memory */ + pDescRing = &pAd->MgmtDescRing; + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + + if (RingBasePaHigh == 0) + {/* empty address high */} + + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->MgmtRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (PTXD_STRUC)dma_cb->AllocVa; + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case */ + } + +#ifdef CONFIG_ANDES_SUPPORT + /* Initialize CTRL Ring and associated buffer memory */ + pDescRing = &pAd->CtrlDescRing; + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->CtrlRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Ctrl Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (PTXD_STRUC)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in CtrlRing for scatter-gather case */ + } +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Initialize Rx Ring and associated buffer memory */ + for (num = 0; num < NUM_OF_RX_RING; num++) + { + UINT16 RxRingSize = (num == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + pDescRing = &pAd->RxDescRing[num]; + pRxRing = &pAd->RxRing[num]; + + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP && num > 0) + { + /* RTMP has one RX ring, skip skb allocation for second ring (save RAM) */ + NdisZeroMemory(pRxRing->Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + continue; + } +#endif /* RTMP_MAC */ + + DBGPRINT(RT_DEBUG_OFF, ("RX[%d] DESC %p size = %ld\n", + num, pDescRing->AllocVa, pDescRing->AllocSize)); + + /* Save PA & VA for further operation */ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + + /* Linking Rx Ring and associated buffer memory */ + for (index = 0; index < RxRingSize; index++) + { + dma_cb = &pRxRing->Cell[index]; + /* Init RX Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = RXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += RXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; + + /* Setup Rx associated Buffer size & allocate share memory */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; + pPacket = RTMP_AllocateRxPacketBuffer( + pAd, + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pDmaBuf->AllocSize, + FALSE, + &pDmaBuf->AllocVa, + &pDmaBuf->AllocPa); + + /* keep allocated rx packet */ + dma_cb->pNdisPacket = pPacket; + + /* Error handling*/ + if (pDmaBuf->AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block */ + //NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + /* Write RxD buffer address & allocated buffer length */ + pRxD = (PRXD_STRUC)dma_cb->AllocVa; +#ifndef RT_SECURE_DMA + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); +#else + pRxD->SDP0 = pAd->RxSecureDMA[num].AllocPa + (index * 4096); +#endif + pRxD->DDONE = 0; + pRxD->SDL0 = pDmaBuf->AllocSize; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxD, dma_cb->AllocSize); + } + } + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pAd->FragFrame.pFragPacket == NULL) + Status = NDIS_STATUS_RESOURCES; + + /* Initialize all transmit related software queues */ + for(index = 0; index < NUM_OF_TX_RING; index++) + { + InitializeQueueHeader(&pAd->TxSwQueue[index]); + /* Init TX rings index pointer */ + pAd->TxRing[index].TxSwFreeIdx = 0; + pAd->TxRing[index].TxCpuIdx = 0; + } + + /* Init RX Ring index pointer */ + for (index = 0; index < NUM_OF_RX_RING; index++) { + UINT16 RxRingSize = (index == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + pAd->RxRing[index].RxSwReadIdx = 0; + pAd->RxRing[index].RxCpuIdx = RxRingSize - 1; + } + + /* init MGMT ring index pointer */ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer */ + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; +#endif /* CONFIG_ANDES_SUPPORT */ + + pAd->PrivateInfo.TxRingFullCnt = 0; + /* Init timer to flush completed packets from TX queues */ + RTMPInitTimer(pAd, &pAd->TxDoneCleanupTimer, GET_TIMER_FUNCTION(TxDoneCleanupExec), pAd, FALSE); + + return Status; + +} + + +/* + ======================================================================== + + Routine Description: + Allocate DMA memory blocks for send, receive + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT num; + ULONG ErrorValue = 0; + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPAllocTxRxRingMemory\n")); + do + { + /* + Allocate all ring descriptors, include TxD, RxD, MgmtD. + Although each size is different, to prevent cacheline and alignment + issue, I intentional set them all to 64 bytes. + */ + for (num = 0; num < NUM_OF_TX_RING; num++) + { + /* Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)*/ + desc_ring_alloc(pAd, &pAd->TxDescRing[num], + TX_RING_SIZE * TXD_SIZE); + if (pAd->TxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d bytes allocated\n", + num, (INT)pAd->TxDescRing[num].AllocSize)); + + /* Allocate all 1st TXBuf's memory for this TxRing */ + pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + pci_dev, + num, + pAd->TxBufSpace[num].AllocSize, + FALSE, + &pAd->TxBufSpace[num].AllocVa, + &pAd->TxBufSpace[num].AllocPa); + + if (pAd->TxBufSpace[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } +#ifdef RT_SECURE_DMA + /* Get DMA buffers, to be put into desriptors later */ + pAd->TxSecureDMA[num].AllocSize = TX_RING_SIZE * 4096; + RTMP_AllocateFirstTxBuffer( + pci_dev, + num, + pAd->TxSecureDMA[num].AllocSize, + FALSE, + &pAd->TxSecureDMA[num].AllocVa, + &pAd->TxSecureDMA[num].AllocPa); + if (pAd->TxSecureDMA[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } +#endif + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + + /* Alloc MGMT ring desc buffer except Tx ring allocated eariler */ + desc_ring_alloc(pAd, &pAd->MgmtDescRing, + MGMT_RING_SIZE * TXD_SIZE); + if (pAd->MgmtDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d bytes allocated\n", + (INT)pAd->MgmtDescRing.AllocSize)); + +#ifdef RT_SECURE_DMA + /* Get DMA buffers, to be put into desriptors later */ + pAd->MgmtSecureDMA.AllocSize = MGMT_RING_SIZE * 4096; + RTMP_AllocateFirstTxBuffer( + pci_dev, + num, + pAd->MgmtSecureDMA.AllocSize, + FALSE, + &pAd->MgmtSecureDMA.AllocVa, + &pAd->MgmtSecureDMA.AllocPa); + if (pAd->MgmtSecureDMA.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } +#endif +#ifdef CONFIG_ANDES_SUPPORT + /* Alloc CTRL ring desc buffer except Tx ring allocated eariler */ + desc_ring_alloc(pAd, &pAd->CtrlDescRing, + MGMT_RING_SIZE * TXD_SIZE); + if (pAd->CtrlDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("CTRL Ring: total %d bytes allocated\n", + (INT)pAd->CtrlDescRing.AllocSize)); +#ifdef RT_SECURE_DMA + /* Get DMA buffers, to be put into desriptors later */ + pAd->CtrlSecureDMA.AllocSize = MGMT_RING_SIZE * 4096; + RTMP_AllocateFirstTxBuffer( + pci_dev, + num, + pAd->CtrlSecureDMA.AllocSize, + FALSE, + &pAd->CtrlSecureDMA.AllocVa, + &pAd->CtrlSecureDMA.AllocPa); + if (pAd->CtrlSecureDMA.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } +#endif +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Alloc RX ring desc memory except Tx ring allocated eariler */ + for (num = 0; num < NUM_OF_RX_RING; num++) { + UINT16 RxRingSize = (num == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + desc_ring_alloc(pAd, &pAd->RxDescRing[num], RxRingSize * RXD_SIZE); + if (pAd->RxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Rx[%d] Ring: total %d bytes allocated\n", + num, (INT)pAd->RxDescRing[num].AllocSize)); +#ifdef RT_SECURE_DMA + /* Get DMA buffers, to be put into desriptors later */ + pAd->RxSecureDMA[num].AllocSize = RX_RING_SIZE * 4096; + RTMP_AllocateFirstTxBuffer( + pci_dev, + num, + pAd->RxSecureDMA[num].AllocSize, + FALSE, + &pAd->RxSecureDMA[num].AllocVa, + &pAd->RxSecureDMA[num].AllocPa); + if (pAd->RxSecureDMA[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } +#endif + } + } while (FALSE); + + + if (Status != NDIS_STATUS_SUCCESS) + { + /* Log error inforamtion*/ + NdisWriteErrorLogEntry( + pAd->AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 1, + ErrorValue); + } + + DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + +#else +/* + ======================================================================== + + Routine Description: + Allocate DMA memory blocks for send, receive + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG RingBasePaHigh, RingBasePaLow; + PVOID RingBaseVa; + INT index, num; + TXD_STRUC *pTxD; + RXD_STRUC *pRxD; + ULONG ErrorValue = 0; + RTMP_TX_RING *pTxRing; + RTMP_DMABUF *pDmaBuf; + RTMP_DMACB *dma_cb; + PNDIS_PACKET pPacket; + + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + + /* Init the CmdQ and CmdQLock*/ + NdisAllocateSpinLock(pAd, &pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + do + { + /* + Allocate all ring descriptors, include TxD, RxD, MgmtD. + Although each size is different, to prevent cacheline and alignment + issue, I intentional set them all to 64 bytes + */ + for (num=0; numTxDescRing[num], TX_RING_SIZE * TXD_SIZE); + if (pAd->TxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + + pDmaBuf = &pAd->TxDescRing[num]; + DBGPRINT(RT_DEBUG_TRACE, ("TxDescRing[%p]: total %d bytes allocated\n", + pDmaBuf->AllocVa, (INT)pDmaBuf->AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDmaBuf->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + RingBaseVa = pDmaBuf->AllocVa; + + /* + Allocate all 1st TXBuf's memory for this TxRing + */ + pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + num, + pAd->TxBufSpace[num].AllocSize, + FALSE, + &pAd->TxBufSpace[num].AllocVa, + &pAd->TxBufSpace[num].AllocPa); + + if (pAd->TxBufSpace[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer, ErrorValue = %lu\n", ErrorValue)); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); + + /* Save PA & VA for further operation*/ + BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); + BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); + BufBaseVa = pAd->TxBufSpace[num].AllocVa; + + /* + Initialize Tx Ring Descriptor and associated buffer memory + */ + pTxRing = &pAd->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) + { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space*/ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (PTXD_STRUC)dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + /* + Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler + */ + desc_ring_alloc(pAd, &pAd->MgmtDescRing, MGMT_RING_SIZE * TXD_SIZE); + if (pAd->MgmtDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("MgmtDescRing[%p]: total %d bytes allocated\n", + pAd->MgmtDescRing.AllocVa, (INT)pAd->MgmtDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow(pAd->MgmtDescRing.AllocPa); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + + /* + Initialize MGMT Ring and associated buffer memory + */ + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->MgmtRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address*/ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD*/ + pTxD = (PTXD_STRUC)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); + +#ifdef CONFIG_ANDES_SUPPORT + /* + Allocate CTRL ring descriptor's memory except Tx ring which allocated eariler + */ + desc_ring_alloc(pAd, &pAd->CtrlDescRing, MGMT_RING_SIZE * TXD_SIZE); + if (pAd->CtrlDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("CtrlDescRing[%p]: total %d bytes allocated\n", + pAd->CtrlDescRing.AllocVa, (INT)pAd->CtrlDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->CtrlDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->CtrlDescRing.AllocPa); + RingBaseVa = pAd->CtrlDescRing.AllocVa; + + /* + Initialize CTRL Ring and associated buffer memory + */ + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->CtrlRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init CTRL Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow(dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address*/ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD*/ + pTxD = (PTXD_STRUC)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in CtrlRing for scatter-gather case*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("CTRL Ring: total %d entry allocated\n", index)); +#endif /* CONFIG_ANDES_SUPPORT */ + + + for (num = 0; num < NUM_OF_RX_RING; num++) + { + UINT16 RxRingSize = (num == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + /* Alloc RxRingDesc memory except Tx ring allocated eariler */ + desc_ring_alloc(pAd, &pAd->RxDescRing[num], RxRingSize * RXD_SIZE); + if (pAd->RxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP && num > 0) + { + /* RTMP has one RX ring, skip skb allocation for second ring (save RAM) */ + NdisZeroMemory(pAd->RxRing[num].Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + continue; + } +#endif /* RTMP_MAC */ + DBGPRINT(RT_DEBUG_OFF, ("RxDescRing[%p]: total %d bytes allocated\n", + pAd->RxDescRing[num].AllocVa, (INT)pAd->RxDescRing[num].AllocSize)); + + /* Initialize Rx Ring and associated buffer memory */ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing[num].AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing[num].AllocPa); + RingBaseVa = pAd->RxDescRing[num].AllocVa; + for (index = 0; index < RxRingSize; index++) + { + dma_cb = &pAd->RxRing[num].Cell[index]; + /* Init RX Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = RXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += RXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; + + /* Setup Rx associated Buffer size & allocate share memory*/ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; + pPacket = RTMP_AllocateRxPacketBuffer( + pAd, + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pDmaBuf->AllocSize, + FALSE, + &pDmaBuf->AllocVa, + &pDmaBuf->AllocPa); + + /* keep allocated rx packet */ + dma_cb->pNdisPacket = pPacket; + if (pDmaBuf->AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + /* Write RxD buffer address & allocated buffer length*/ + pRxD = (PRXD_STRUC)dma_cb->AllocVa; + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->SDL0 = pDmaBuf->AllocSize; + pRxD->DDONE = 0; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxD, dma_cb->AllocSize); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Rx[%d] Ring: total %d entry allocated\n", num, index)); + } + } while (FALSE); + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pAd->FragFrame.pFragPacket == NULL) + Status = NDIS_STATUS_RESOURCES; + + if (Status != NDIS_STATUS_SUCCESS) + { + /* Log error inforamtion*/ + NdisWriteErrorLogEntry( + pAd->AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 1, + ErrorValue); + } + + /* + Initialize all transmit related software queues + */ + + /* Init TX rings index pointer*/ + for(index = 0; index < NUM_OF_TX_RING; index++) + { + InitializeQueueHeader(&pAd->TxSwQueue[index]); + pAd->TxRing[index].TxSwFreeIdx = 0; + pAd->TxRing[index].TxCpuIdx = 0; + } + + /* init MGMT ring index pointer*/ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer*/ + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Init RX Ring index pointer*/ + for(index = 0; index < NUM_OF_RX_RING; index++) { + UINT16 RxRingSize = (index == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + pAd->RxRing[index].RxSwReadIdx = 0; + pAd->RxRing[index].RxCpuIdx = RxRingSize - 1; + } + + pAd->PrivateInfo.TxRingFullCnt = 0; + + DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + + +VOID RTMPFreeTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + int index, num , j; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket; + ULONG IrqFlags; + RTMP_DMACB *dma_cb; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + /* Free TxSwQueue Packet*/ + for (index=0; index TxSwQueue[index]; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + + /* Free Tx Ring Packet*/ + for (index=0;index< NUM_OF_TX_RING;index++) + { + pTxRing = &pAd->TxRing[index]; + + for (j=0; j< TX_RING_SIZE; j++) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); +#endif /* RT_BIG_ENDIAN */ + + pPacket = pTxRing->Cell[j].pNdisPacket; + if (pPacket) + { + pTxRing->Cell[j].pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + pPacket = pTxRing->Cell[j].pNextNdisPacket; + if (pPacket) + { + pTxRing->Cell[j].pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + } + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + { + RTMP_MGMT_RING *pMgmtRing = &pAd->MgmtRing; + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, pMgmtRing->hw_didx_addr, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) + { + RTMP_DMACB *dma_cb = &pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx]; + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) (dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (dma_cb->AllocVa); +#endif + pTxD->DMADONE = 0; + pPacket = dma_cb->pNdisPacket; + if (pPacket) + { + dma_cb->pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + pPacket = dma_cb->pNextNdisPacket; + if (pPacket) + { + dma_cb->pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + NdisReleaseSpinLock(&pAd->MgmtRingLock); + } + +#ifdef CONFIG_ANDES_SUPPORT + { + PRTMP_MGMT_RING pCtrlRing = &pAd->CtrlRing; + + RTMP_IO_READ32(pAd, TX_CTRL_DIDX, &pCtrlRing->TxDmaIdx); + + while (pCtrlRing->TxSwFreeIdx!= pCtrlRing->TxDmaIdx) + { + RTMP_DMACB *dma_cb = &pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx]; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) (dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (dma_cb->AllocVa); +#endif /* RT_BIG_ENDIAN */ + pTxD->DMADONE = 0; + + pPacket = dma_cb->pNdisPacket; + if (pPacket) + { + dma_cb->pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + pPacket = dma_cb->pNextNdisPacket; + if (pPacket) + { + dma_cb->pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + NdisReleaseSpinLock(&pAd->CtrlRingLock); + } +#endif /* CONFIG_ANDES_SUPPORT */ + + for (j = 0; j < NUM_OF_RX_RING; j++) + { + UINT16 RxRingSize = (j == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + for (index = RxRingSize - 1 ; index >= 0; index--) + { + dma_cb = &pAd->RxRing[j].Cell[index]; + if ((dma_cb->DmaBuf.AllocVa) && (dma_cb->pNdisPacket)) + { + PCI_UNMAP_SINGLE(pAd, dma_cb->DmaBuf.AllocPa, + dma_cb->DmaBuf.AllocSize, + RTMP_PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, dma_cb->pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing[j].Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + + if (pAd->RxDescRing[j].AllocVa) + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->RxDescRing[j].AllocSize, + pAd->RxDescRing[j].AllocVa, + pAd->RxDescRing[j].AllocPa); + + NdisZeroMemory(&pAd->RxDescRing[j], sizeof(RTMP_DMABUF)); + } + + if (pAd->MgmtDescRing.AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); + } + NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); + +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->CtrlDescRing.AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->CtrlDescRing.AllocSize, pAd->CtrlDescRing.AllocVa, pAd->CtrlDescRing.AllocPa); + } + NdisZeroMemory(&pAd->CtrlDescRing, sizeof(RTMP_DMABUF)); +#endif /* CONFIG_ANDES_SUPPORT */ + + for (num = 0; num < NUM_OF_TX_RING; num++) + { + if (pAd->TxBufSpace[num].AllocVa) + { + RTMP_FreeFirstTxBuffer(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->TxBufSpace[num].AllocSize, FALSE, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa); + } + NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); + + if (pAd->TxDescRing[num].AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa); + } + NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF)); + } + + if (pAd->FragFrame.pFragPacket) + { + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + pAd->FragFrame.pFragPacket = NULL; + } + + NdisFreeSpinLock(&pAd->CmdQLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + +#endif /* RESOURCE_PRE_ALLOC */ + + +VOID AsicInitTxRxRing(RTMP_ADAPTER *pAd) +{ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + rlt_asic_init_txrx_ring(pAd); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + rtmp_asic_init_txrx_ring(pAd); +#endif /* RTMP_MAC */ +} + + +#ifdef DMA_BUSY_RESET +//reference MT7603E's watchdog body +VOID PDMAWatchDog(RTMP_ADAPTER *pAd) +{ + BOOLEAN NoDataOut = FALSE, NoDataIn = FALSE; + + /* Tx DMA unchaged detect */ + NoDataOut = MonitorTxRing(pAd); + + if (NoDataOut) + { + DBGPRINT(RT_DEBUG_OFF, ("TXDMA Reset\n")); + pAd->TxDMAResetCount++; + goto reset; + } + + + return; + +reset: + + WlanResetB(pAd); +} +#endif /* DMA_BUSY_RESET */ + +/* + ======================================================================== + + Routine Description: + Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPRingCleanUp(RTMP_ADAPTER *pAd, UCHAR RingType) +{ + TXD_STRUC *pTxD; + RXD_STRUC *pRxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD, TxD; + RXD_STRUC *pDestRxD, RxD; +#endif /* RT_BIG_ENDIAN */ + QUEUE_ENTRY *pEntry; + PNDIS_PACKET pPacket; + RTMP_TX_RING *pTxRing; + ULONG IrqFlags; + int i, ring_id; + + /* + We have to clean all descriptors in case some error happened with reset + */ + DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount)); + switch (RingType) + { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + case QID_HCCA: + + pTxRing = &pAd->TxRing[RingType]; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + for (i=0; iCell[i].AllocVa; + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + pTxRing->Cell[i].pNdisPacket = NULL; + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + pTxRing->Cell[i].pNextNdisPacket = NULL; + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); + + while (pAd->TxSwQueue[RingType].Head != NULL) + { + pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n")); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + break; + + case QID_MGMT: + RTMP_IRQ_LOCK(&pAd->MgmtRingLock, IrqFlags); + for (i=0; iMgmtRing.Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket; + /* rlease scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + pAd->MgmtRing.Cell[i].pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_didx_addr, &pAd->MgmtRing.TxDmaIdx); + pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; + pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->MgmtRingLock, IrqFlags); + pAd->RalinkCounters.MgmtRingFullCount = 0; + break; + + case QID_RX: + for (ring_id =0; ring_id < NUM_OF_RX_RING; ring_id++) + { + UINT16 RxRingSize = (ring_id == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + RTMP_RX_RING *pRxRing; + NDIS_SPIN_LOCK *lock; + + pRxRing = &pAd->RxRing[ring_id]; + lock = &pAd->RxRingLock[ring_id]; + + RTMP_IRQ_LOCK(lock, IrqFlags); + for (i=0; iCell[i].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor*/ + pRxD = (PRXD_STRUC)pRxRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pRxD->DDONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif /* RT_BIG_ENDIAN */ + } + + RTMP_IO_READ32(pAd, pRxRing->hw_didx_addr, &pRxRing->RxDmaIdx); + pRxRing->RxSwReadIdx = pRxRing->RxDmaIdx; + pRxRing->RxCpuIdx = ((pRxRing->RxDmaIdx == 0) ? (RxRingSize-1) : (pRxRing->RxDmaIdx-1)); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + + RTMP_IRQ_UNLOCK(lock, IrqFlags); + } + break; + +#ifdef CONFIG_ANDES_SUPPORT + case QID_CTRL: + RTMP_IRQ_LOCK(&pAd->CtrlRingLock, IrqFlags); + + for (i=0; iCtrlRing.Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pAd->CtrlRing.Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pPacket = (PNDIS_PACKET) pAd->CtrlRing.Cell[i].pNdisPacket; + /* rlease scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + pAd->CtrlRing.Cell[i].pNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + pPacket = (PNDIS_PACKET) pAd->CtrlRing.Cell[i].pNextNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + pAd->CtrlRing.Cell[i].pNextNdisPacket = NULL; + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_didx_addr, &pAd->CtrlRing.TxDmaIdx); + pAd->CtrlRing.TxSwFreeIdx = pAd->CtrlRing.TxDmaIdx; + pAd->CtrlRing.TxCpuIdx = pAd->CtrlRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->CtrlRingLock, IrqFlags); + break; +#endif /* CONFIG_ANDES_SUPPORT */ + default: + break; + } +} + + +/*************************************************************************** + * + * register related procedures. + * + **************************************************************************/ +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMADisable(RTMP_ADAPTER *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); +} + + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMAEnable(RTMP_ADAPTER *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + AsicWaitPDMAIdle(pAd, 200, 1000); + + RtmpusecDelay(50); + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = pAd->chipCap.WPDMABurstSIZE; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnableTxDMA = 1; + + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x, WPDMABurstSIZE = %d\n", GloCfg.word, pAd->chipCap.WPDMABurstSIZE)); +} + + +BOOLEAN AsicCheckCommanOk(RTMP_ADAPTER *pAd, UCHAR Command) +{ + UINT32 CmdStatus = 0, CID = 0, i; + UINT32 ThisCIDMask = 0; +#ifdef SPECIFIC_BCN_BUF_SUPPORT + ULONG IrqFlags = 0; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + +#ifdef RT65xx + if (IS_RT65XX(pAd)) + return TRUE; +#endif /* RT65xx */ + + +#ifdef SPECIFIC_BCN_BUF_SUPPORT + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + i = 0; + do + { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); + /* Find where the command is. Because this is randomly specified by firmware.*/ + if ((CID & CID0MASK) == Command) + { + ThisCIDMask = CID0MASK; + break; + } + else if ((((CID & CID1MASK)>>8) & 0xff) == Command) + { + ThisCIDMask = CID1MASK; + break; + } + else if ((((CID & CID2MASK)>>16) & 0xff) == Command) + { + ThisCIDMask = CID2MASK; + break; + } + else if ((((CID & CID3MASK)>>24) & 0xff) == Command) + { + ThisCIDMask = CID3MASK; + break; + } + + RtmpusecDelay(100); + i++; + }while (i < 200); + + /* Get CommandStatus Value*/ + RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); + + /* This command's status is at the same position as command. So AND command position's bitmask to read status. */ + if (i < 200) + { + /* If Status is 1, the comamnd is success.*/ + if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100) + || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); +#ifdef SPECIFIC_BCN_BUF_SUPPORT + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + return TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus)); + } + /* Clear Command and Status.*/ + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); +#ifdef SPECIFIC_BCN_BUF_SUPPORT + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + return FALSE; +} + + +/* +======================================================================== +Routine Description: + Write Beacon buffer to Asic. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN ULONG FrameLen, + IN ULONG UpdatePos) +{ + ULONG CapInfoPos = 0; + UCHAR *ptr, *ptr_update, *ptr_capinfo; + UINT i; + BOOLEAN bBcnReq = FALSE; + UCHAR bcn_idx = 0; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef CONFIG_AP_SUPPORT + MULTISSID_STRUCT *pMbss; +#endif + INT wr_bytes = 1; + + if (IS_MT76x2(pAd)) + wr_bytes = 4; + +#ifdef CONFIG_AP_SUPPORT + if (apidx < pAd->ApCfg.BssidNum && + apidx < HW_BEACON_MAX_NUM && + (pAd->OpMode == OPMODE_AP) + ) + { + //MULTISSID_STRUCT *pMbss; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + bcn_idx = pMbss->BcnBufIdx; + CapInfoPos = pMbss->CapabilityInfoLocationInBeacon; + bBcnReq = BeaconTransmitRequired(pAd, apidx, pMbss); + + ptr_capinfo = (PUCHAR)&pMbss->BeaconBuf[CapInfoPos]; + ptr_update = (PUCHAR)&pMbss->BeaconBuf[UpdatePos]; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __FUNCTION__)); + return; + } + + if (bBcnReq == FALSE) + { + /* when the ra interface is down, do not send its beacon frame */ + /* clear all zero */ + for(i=0; i < TXWISize; i+=4) + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00, 4); + } + else + { + ptr = (PUCHAR)&pAd->BeaconTxWI; + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif + for (i=0; i < TXWISize; i+=4) /* 16-byte TXWI field*/ + { + UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + i, longptr, 4); + ptr += 4; + } + + /* Update CapabilityInfo in Beacon*/ +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Update CapabilityInfo in Beacon*/ + for (i = CapInfoPos; i < (CapInfoPos+2); i++) + { + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, *ptr_capinfo, 1); + ptr_capinfo ++; + } + + if (FrameLen > UpdatePos) + { + for (i= UpdatePos; i< (FrameLen); i++) + { + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, *ptr_update, 1); + ptr_update ++; + } + } + } + else +#endif + { + if (wr_bytes > 1) + CapInfoPos = (CapInfoPos & (~(wr_bytes - 1))); +#ifdef CONFIG_AP_SUPPORT + ptr_capinfo = (PUCHAR)&pMbss->BeaconBuf[CapInfoPos]; +#endif /* CONFIG_AP_SUPPORT */ + for (i = CapInfoPos; i < (CapInfoPos+2); i += wr_bytes) + { +#ifdef RT_BIG_ENDIAN + UINT32 longptr = *ptr_capinfo + (*(ptr_capinfo+1)<<8) + (*(ptr_capinfo+2)<<16) + (*(ptr_capinfo+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, longptr, wr_bytes); +#else + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, *((UINT32 *)ptr_capinfo), wr_bytes); +#endif /* RT_BIG_ENDIAN */ + ptr_capinfo += wr_bytes; + } + + if (FrameLen > UpdatePos) + { + if (wr_bytes > 1) + UpdatePos = (UpdatePos & (~(wr_bytes - 1))); +#ifdef CONFIG_AP_SUPPORT + ptr_update = (PUCHAR)&pMbss->BeaconBuf[UpdatePos]; +#endif /* CONFIG_AP_SUPPORT */ + for (i = UpdatePos; i < (FrameLen); i += wr_bytes) + { + UINT32 longptr = *ptr_update + (*(ptr_update+1)<<8) + (*(ptr_update+2)<<16) + (*(ptr_update+3)<<24); + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, longptr); + ptr_update += wr_bytes; + } + } + } + } +} + + +#ifdef CONFIG_STA_SUPPORT +VOID RT28xxPciStaAsicForceWakeup(RTMP_ADAPTER *pAd, BOOLEAN bFromTx) +{ + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) + return; + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + + /* RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);*/ +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + { + /* Support PCIe Advance Power Save*/ + if (bFromTx == TRUE + &&(pAd->Mlme.bPsPollTimerRunning == TRUE)) + { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + RtmpusecDelay(3000); + DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n")); + } + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) + { + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd, FALSE); + else + { + UCHAR rf_channel; + + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.*/ + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + rf_channel = pAd->CommonCfg.CentralChannel; + else + rf_channel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); + + } + } + } + else +#endif /* PCIE_PS_SUPPORT */ + { + BOOLEAN Canceled; + + /* PCI, 2860-PCIe*/ + DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n")); +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + PWR_SAVING_OP(pAd, RADIO_ON, 0, 0, 0, 0, 0); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + if (pAd->Mlme.bPsPollTimerRunning) + { + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Canceled); + pAd->Mlme.bPsPollTimerRunning = FALSE; + } + } + else +#endif /* MT76x2 */ + { + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02, FALSE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + } + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); +} + + +VOID RT28xxPciStaAsicSleepThenAutoWakeup( + IN RTMP_ADAPTER *pAd, + IN USHORT TbttNumToNextWakeUp) +{ +#ifdef PCIE_PS_SUPPORT + BOOLEAN brc; +#endif /* PCIE_PS_SUPPORT */ + + if ((pAd->StaCfg.bRadio == FALSE) || + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) || + (pAd->CountDowntoPsm > 0)) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + { + ULONG Now = 0; + + NdisGetSystemUpTime(&Now); + /* If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.*/ + /* Because Some AP can't queuing outgoing frames immediately.*/ + if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); + return; + } + else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); + return; + } + + brc = RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp); + if (brc==TRUE) + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); + } + else +#endif /* PCIE_PS_SUPPORT */ + { +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + UINT32 WakeUpTime = AUTO_WAKEUP_TIMEOUT; /*unit: msec */ + UINT32 LeadTimeRatio = 30; /* % */ + UINT32 LeadTime = 0; /* unit: msec */ + UINT32 pwr_level = 5; + + if(TbttNumToNextWakeUp == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("give up this sleep. \n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + + if(!pAd->Mlme.bPsPollTimerRunning) + { + WakeUpTime = (TbttNumToNextWakeUp*pAd->CommonCfg.BeaconPeriod); + LeadTime = (pAd->CommonCfg.BeaconPeriod*LeadTimeRatio)/100; + if(WakeUpTime >= LeadTime) + WakeUpTime -= LeadTime; + + RTMPSetTimer(&pAd->Mlme.PsPollTimer, WakeUpTime); + pAd->Mlme.bPsPollTimerRunning = TRUE; + } + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + PWR_SAVING_OP(pAd, RADIO_OFF, pwr_level, 0, 0, 0, 0); + } + else +#endif /* MT76x2 */ + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + /* we have decided to SLEEP, so at least do it for a BEACON period. */ + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = 5; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00, FALSE); /* send POWER-SAVE command to MCU. Timeout 40us.*/ + } + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); + DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __FUNCTION__, TbttNumToNextWakeUp)); + } + +} + +VOID PsPollWakeExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + unsigned long flags; + + DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n")); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); +#ifdef PCIE_PS_SUPPORT + if (pAd->Mlme.bPsPollTimerRunning) + { + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + pAd->Mlme.bPsPollTimerRunning = FALSE; + } +#endif /* PCIE_PS_SUPPORT */ + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + AsicForceWakeup(pAd,FALSE); +#endif /* MT76x2 */ +} + +#ifdef PCIE_PS_SUPPORT +VOID RadioOnExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + WPDMA_GLO_CFG_STRUC DmaCfg; + BOOLEAN Cancelled; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + return; + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); + + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + return; + } + +if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } + + + if (pAd->StaCfg.bRadio == TRUE) + { + UCHAR rf_channel; + + pAd->bPCIclkOff = FALSE; + 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); + + /* 2. Send wake up command and wait for command done. */ + AsicSendCmdToMcuAndWait(pAd, 0x31, PowerWakeCID, 0x00, 0x02, FALSE); + + /* When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.*/ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + /* 3. Enable Tx DMA.*/ + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableTxDMA = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.*/ + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + rf_channel = pAd->CommonCfg.CentralChannel; + else + rf_channel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); + + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd, FALSE); + + /* Clear Radio off flag*/ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED*/ + RTMPSetLED(pAd, LED_RADIO_ON); +#endif /* LED_CONTROL_SUPPORT */ + + if (RtmpPktPmBitCheck(pAd) == FALSE) + { +#ifdef RTMP_BBP + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); +#endif /* RTMP_BBP */ + } + } + else + { + RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); + } +} +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to wake up mode from power save mode. + Both RadioOn and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. + Level = other value : normal wake up function. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOn(RTMP_ADAPTER *pAd, UCHAR Level) +{ +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + BOOLEAN Cancelled; +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE) + return FALSE; + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } + if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)&& + (((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE)) + ||(RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)))) + { + /* Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore*/ + /* return condition here.*/ + /* + if (((pAd->MACVersion&0xffff0000) != 0x28600000) + && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID) + ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID))) + */ + { + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n")); + /* 1. Set PCI Link Control in Configuration Space.*/ + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + RtmpusecDelay(6000); + } + } + } + + { + pAd->bPCIclkOff = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff)); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + /* 2. Send wake up command.*/ + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02, FALSE); + pAd->bPCIclkOff = FALSE; + /* 2-1. wait command ok.*/ + AsicCheckCommanOk(pAd, PowerWakeCID); + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + if (Level == GUI_IDLE_POWER_SAVE) + { + /*2009/06/09: AP and stations need call the following function*/ + #ifndef RTMP_RBUS_SUPPORT + /* add by johnli, RF power sequence setup, load RF normal operation-mode setup*/ + + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + + if (pChipOps->AsicReverseRfFromSleepMode) + { + pChipOps->AsicReverseRfFromSleepMode(pAd, FALSE); +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + /* 3090 MCU Wakeup command needs more time to be stable.*/ + /* Before stable, don't issue other MCU command to prevent from firmware error. */ + + if ( pAd->chipCap.HW_PCIE_PS_L3_ENABLE==TRUE) + { + RTMP_SEM_LOCK(&pAd->McuCmdLock); + pAd->brt30xxBanMcuCmd = FALSE; + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + } + else +#endif /* RTMP_RBUS_SUPPORT */ + { + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.*/ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + UCHAR rf_channel; + + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + rf_channel = pAd->CommonCfg.CentralChannel; + else + rf_channel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } +#endif /* CONFIG_AP_SUPPORT */ + } + } + return TRUE; + +} + + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to power save mode. + Both RadioOff and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : GUI Radio Off mode + Level = DOT11POWERSAVE : 802.11 power save mode + Level = RTMP_HALT : When Disable device. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOff( + IN RTMP_ADAPTER *pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp) +{ +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_BBP + UCHAR tempBBP_R3 = 0; +#endif /* RTMP_BBP */ +#ifdef PCIE_PS_SUPPORT + UCHAR i; + ULONG BeaconPeriodTime; + UINT32 PsPollTime = 0/*, MACValue*/; + UINT32 TbTTTime = 0; + BOOLEAN Cancelled; +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#if (defined(CONFIG_STA_SUPPORT) && defined(PCIE_PS_SUPPORT)) || defined(RT2860) + BOOLEAN brc = FALSE; +#endif /*(defined(CONFIG_STA_SUPPORT) && defined(PCIE_PS_SUPPORT)) || defined(RT2860) */ + + + UINT32 RxDmaIdx, RxCpuIdx; + DBGPRINT(RT_DEBUG_TRACE, ("%s ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", + __FUNCTION__, Level,pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, + pAd->RxRing[0].RxCpuIdx, pAd->RxRing[0].RxDmaIdx)); + + if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE) + return FALSE; + + if (Level == DOT11POWERSAVE) + { + /* Check Rx DMA busy status, if more than half is occupied, give up this radio off.*/ + RTMP_IO_READ32(pAd, pAd->RxRing[0].hw_didx_addr, &RxDmaIdx); + RTMP_IO_READ32(pAd, pAd->RxRing[0].hw_cidx_addr, &RxCpuIdx); + if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): return1. RxDmaIdx=%d, RxCpuIdx=%d\n", + __FUNCTION__, RxDmaIdx, RxCpuIdx)); + return FALSE; + } + else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): return2. RxDmaIdx=%d, RxCpuIdx=%d\n", + __FUNCTION__, RxDmaIdx, RxCpuIdx)); + return FALSE; + } + } + + + /* Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.*/ + /*pAd->bPCIclkOffDisableTx = TRUE;*/ +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + && pAd->OpMode == OPMODE_STA + &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE + ) + { + + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + + if (Level == DOT11POWERSAVE) + { + RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); + TbTTTime &= 0x1ffff; + /* 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep.*/ + /* TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms*/ + if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime)); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + /*pAd->bPCIclkOffDisableTx = FALSE;*/ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); + return FALSE; + } + else + { + PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000; + PsPollTime -= 3; + + BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100; + if (TbttNumToNextWakeUp > 0) + PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime); + + pAd->Mlme.bPsPollTimerRunning = TRUE; + RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n")); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + /*pAd->bPCIclkOffDisableTx = FALSE;*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + +#ifdef CONFIG_STA_SUPPORT + /* Set to 1R.*/ + if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA) + { +#ifdef RTMP_BBP + if (pAd->chipCap.hif_type == HIF_RTMP) { + tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); + } +#endif /* RTMP_BBP */ + // TODO: shiang, how about RLT_BBP for this?? + } +#endif /* CONFIG_STA_SUPPORT */ + + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.*/ + if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + else + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + + if (Level != RTMP_HALT) + { + UINT32 AutoWakeupInt = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + AutoWakeupInt = RLT_AutoWakeupInt; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + AutoWakeupInt = RTMP_AutoWakeupInt; +#endif /* RTMP_MAC */ + /* + Change Interrupt bitmask. + When PCI clock is off, don't want to service interrupt. + */ + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + + RTMP_IO_WRITE32(pAd, pAd->RxRing[0].hw_cidx_addr, pAd->RxRing[0].RxCpuIdx); + /* 2. Send Sleep command */ + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + /* send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power*/ + AsicSendCommandToMcu(pAd, SLEEP_MCU_CMD, PowerSafeCID, 0xff, 0x1, FALSE); + + +#ifdef CONFIG_STA_SUPPORT + /* 1. Wait DMA not busy*/ + AsicWaitPDMAIdle(pAd, 50, 20); +#endif /* CONFIG_STA_SUPPORT */ + +/* Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment.*/ +/*RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280);*/ +/*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ);*/ + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + if (Level == DOT11POWERSAVE) + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + /*RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);*/ + + /* we have decided to SLEEP, so at least do it for a BEACON period.*/ + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + /* 1. Set auto wake up timer.*/ + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + } + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + + /* 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.*/ + if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA) + { + if ((brc == TRUE) && (i < 50)) + RTMPPCIeLinkCtrlSetting(pAd, 1); + } + /* 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function*/ + else if (pAd->OpMode == OPMODE_STA) + { + if ((brc == TRUE) && (i < 50)) + RTMPPCIeLinkCtrlSetting(pAd, 3); + } + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + /*pAd->bPCIclkOffDisableTx = FALSE;*/ + + return TRUE; +} + + +VOID RT28xxPciMlmeRadioOn(RTMP_ADAPTER *pAd) +{ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + +#if defined(MT76x0) || defined(MT76x2) + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + MT76xx_PciMlmeRadioOn(pAd); + return; + } +#endif /* defined(MT76x0) || defined(MT76x2) */ + + if ((pAd->OpMode == OPMODE_AP) || + ((pAd->OpMode == OPMODE_STA) +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + ||pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + #endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + )) + { + 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); + + /* Clear Radio off flag (need before call AsicSwitchChannel()) */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + NICResetFromError(pAd); +#endif /* RTMP_RBUS_SUPPORT */ +#ifdef RTMP_PCI_SUPPORT +#ifdef RT65xx + if (IS_RT8592(pAd)) + { +#ifdef RT8592 + if (IS_RT8592(pAd)) { + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + } +#endif /* RT8592 */ +#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); + } + else +#endif /* RT65xx */ + { + if (pAd->infType == RTMP_DEV_INF_PCI || pAd->infType == RTMP_DEV_INF_PCIE) + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } +#endif /* RTMP_PCI_SUPPORT */ + + /* Enable Tx/Rx*/ + RTMPEnableRxTx(pAd); + + /* 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 + /* Set LED*/ + RTMPSetLED(pAd, LED_RADIO_ON); +#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 */ +#endif /* LED_CONTROL_SUPPORT */ + } + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + + if ((pAd->OpMode == OPMODE_STA) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) + { + BOOLEAN Cancelled; + + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +} + + +VOID RT28xxPciMlmeRadioOFF(RTMP_ADAPTER *pAd) +{ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + +#if defined(MT76x0) || defined(MT76x2) + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + MT76xx_PciMlmeRadioOFF(pAd); + return; + } +#endif /* MT76x0 */ + + /* Set Radio off flag*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); +#ifdef BB_SOC + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE); +#endif /* BB_SOC */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + BOOLEAN Cancelled; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + } + +#ifdef RTMP_PCI_SUPPORT +#ifdef PCIE_PS_SUPPORT + /* If during power safe mode. */ + if ((pAd->StaCfg.bRadio == TRUE) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)&&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n")); + return; + } +#endif /* PCIE_PS_SUPPORT */ + + /* Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).*/ + if ((pAd->infType == RTMP_DEV_INF_PCI) || + (pAd->infType == RTMP_DEV_INF_PCIE)) + { + if (IDLE_ON(pAd) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } + } + +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)&&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + { + BOOLEAN Cancelled; + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_PCI_SUPPORT */ + + /* Link down first if any association exists */ + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + LinkDown(pAd, FALSE); + + RtmpusecDelay(10000); + + /*========================================== */ + /* Clean up old bss table */ + BssTableInit(&pAd->ScanTab); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + } +#endif /* AP_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_RADIO_OFF); +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RTMP_PCI_SUPPORT +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT +/*Q:Does all PCIe devices need to use timer to execute radio off function? or only if the device is PCIe and EnableNewPS is true ?*/ +/*A:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer*/ +/*to avoid the deadlock with PCIe Power saving function. */ + if (pAd->OpMode == OPMODE_STA&& + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)&& + pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + { + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + } + else +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + if (pAd->infType == RTMP_DEV_INF_PCI || pAd->infType == RTMP_DEV_INF_PCIE) + { +#ifdef RT8592 + if (IS_RT8592(pAd)) + { + DISABLE_TX_RX(pAd, GUIRADIO_OFF); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + } + else +#endif /* RT8592 */ + { + if (RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0) ==FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__)); + } + } + } +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { + WPDMA_GLO_CFG_STRUC GloCfg; + + /* Disable Tx/Rx DMA*/ + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnableRxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings*/ + + + /* MAC_SYS_CTRL => value = 0x0 => 40mA*/ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0); + + /* PWR_PIN_CFG => value = 0x0 => 40mA*/ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0); + + /* TX_PIN_CFG => value = 0x0 => 20mA*/ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x00010000); + + // TODO: shiang-6590, here we need to make sure the CentralChannel is the same as Channel. + if (pAd->CommonCfg.CentralChannel) + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + else + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + + /* Waiting for DMA idle*/ + AsicWaitPDMAIdle(pAd, 100, 1000); + } +#endif /* RTMP_RBUS_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Get a pci map buffer. + +Arguments: + pAd - WLAN control block pointer + *ptr - Virtual address or TX control block + size - buffer size + sd_idx - 1: the ptr is TX control block + direction - RTMP_PCI_DMA_TODEVICE or RTMP_PCI_DMA_FROMDEVICE + +Return Value: + the PCI map buffer + +Note: +======================================================================== +*/ +ra_dma_addr_t RtmpDrvPciMapSingle( + IN RTMP_ADAPTER *pAd, + IN VOID *ptr, + IN size_t size, + IN INT sd_idx, + IN INT direction) +{ + if (sd_idx == 1) + { + TX_BLK *pTxBlk = (TX_BLK *)(ptr); + return (pTxBlk->SrcBufLen) ? linux_pci_map_single(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, 0, direction):(ra_dma_addr_t)NULL; + } + else + return linux_pci_map_single(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + ptr, size, 0, direction); +} + + +int write_reg(RTMP_ADAPTER *ad, UINT32 base, UINT16 offset, UINT32 value) +{ + if (base == 0x40) + RTMP_IO_WRITE32(ad, 0x10000 + offset, value); + else if (base == 0x41) + RTMP_IO_WRITE32(ad, offset, value); + else + DBGPRINT(RT_DEBUG_OFF, ("illegal base = %x\n", base)); + + return 0; +} + + +int read_reg(RTMP_ADAPTER *ad, UINT32 base, UINT16 offset, UINT32 *value) +{ + if (base == 0x40) { + RTMP_IO_READ32(ad, 0x10000 + offset, value); + } else if (base == 0x41) { + RTMP_IO_READ32(ad, offset, value); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal base = %x\n", base)); + } + return 0; +} + +INT rtmp_irq_init(RTMP_ADAPTER *pAd) +{ + unsigned long _irqFlags; + UINT32 reg_mask = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + if(IS_MT76x2(pAd)) + reg_mask = (RLT_DELAYINTMASK) |(RLT_RxINT|RLT_76x2TxDataInt|RLT_TxMgmtInt); + else + reg_mask = (RLT_DELAYINTMASK) |(RLT_RxINT|RLT_TxDataInt|RLT_TxMgmtInt); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + reg_mask = ((RTMP_DELAYINTMASK) |(RTMP_RxINT|RTMP_TxDataInt|RTMP_TxMgmtInt)) & ~(0x03); +#endif /* RTMP_MAC */ + + RTMP_INT_LOCK(&pAd->irq_lock, _irqFlags); + pAd->int_enable_reg = reg_mask; + pAd->int_disable_mask = 0; + pAd->int_pending = 0; + RTMP_INT_UNLOCK(&pAd->irq_lock, _irqFlags); + + return 0; +} + +#endif /* RTMP_MAC_PCI */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat.c new file mode 100644 index 000000000..4d8278999 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat.c @@ -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;iPointer 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; irx!=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(iApCfg.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; iexit!=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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_iparp.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_iparp.c new file mode 100644 index 000000000..c820a84b7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_iparp.c @@ -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; ihash[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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_ipv6.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_ipv6.c new file mode 100644 index 000000000..44df51702 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_ipv6.c @@ -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 */ +/*#include */ + +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; ihash[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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_pppoe.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_pppoe.c new file mode 100644 index 000000000..a7a88c370 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_mat_pppoe.c @@ -0,0 +1,1069 @@ +/* + *************************************************************************** + * 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_pppoe.c + + Abstract: + MAT convert engine subroutine for PPPoE protocol.Due to the difference + of characteristic of PPPoE discovery stage and session stage, we seperate + that as two parts and used different stretegy to handle it. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Shiang 02/26/07 Init version +*/ + +#ifdef MAT_SUPPORT + +#include "rt_config.h" + +static NDIS_STATUS MATProto_PPPoEDis_Init(MAT_STRUCT *pMatStruct); +static NDIS_STATUS MATProto_PPPoEDis_Exit(MAT_STRUCT *pMatStruct); +static PUCHAR MATProto_PPPoEDis_Rx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr); +static PUCHAR MATProto_PPPoEDis_Tx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr); + +static NDIS_STATUS MATProto_PPPoESes_Init(MAT_STRUCT *pMatStruct); +static NDIS_STATUS MATProto_PPPoESes_Exit(MAT_STRUCT *pMatStruct); +static PUCHAR MATProto_PPPoESes_Rx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr); +static PUCHAR MATProto_PPPoESes_Tx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr); + + +/* + 1 2 3 4 + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | VER | TYPE | CODE | SESSION_ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | LENGTH | payload ~ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + VER = 0x1, TYPE =0x1 + +PPPoE Discovery Stage(Ethernet protocol type = 0x8863): + PADI: + DESTINATION_ADDR = 0xffffffff + CODE = 0x09, SESSION_ID = 0x0000 + LENGTH = payload length + + PADO: + DESTINATION_ADDR = Unicast Ethernet address of sender + CODE = 0x07, SESSION_ID = 0x0000 + LENGTH = payload length + NEcessary TAGS: AC-NAME(0x0102), Sevice-Name(0x0101), and other service names. + + Note: if the PPPoE server cannot serve the PADI it MUST NOT respond with a PADO + + + PADR: + DESTINATION_ADDR = unicast Ethernet address + CODE = 0x19, SESSION_ID = 0x0000 + LENGTH = payload length + Necessary TAGS: Service-Name(0x0101) + Optional TAGS: .... + + PADS: + If success: + DESTINATION_ADDR = unicast Ethernet address + CODE = 0x65, SESSION_ID = unique value for this pppoe session.(16 bits) + LENGHT - payload length + Necessary TAGS: Service-Name(0x0101) + + if failed: + SESSION_ID = 0x0000 + Necessary TAGS: Service-Name-Error(0x0201). + + PADT: + DESTINATION_ADDR = unicast Ethernet address + CODE = 0xa7, SESSION_ID = previous assigned 16 bits session ID. + Necessary TAGS: NO. + +PPPoE Session Stage(Ethernet protocol type = 0x8864): + PPP data: + DESTINATION_ADDR = unicast Ethernet address + CODE = 0x00, + LCP: + DESTINATION_ADDR = unicast Ethernet address + CODE = 0x00, + +*/ + +#define PPPOE_CODE_PADI 0x09 +#define PPPOE_CODE_PADO 0x07 +#define PPPOE_CODE_PADR 0x19 +#define PPPOE_CODE_PADS 0x65 +#define PPPOE_CODE_PADT 0xa7 +#define PPPOE_TAG_ID_HOST_UNIQ 0x0103 +#define PPPOE_TAG_ID_AC_COOKIE 0x0104 + +#define PPPoE_SES_ENTRY_AGEOUT_TIME 3000 + +/* Data structure used for PPPoE discovery stage */ +#define PPPOE_DIS_UID_LEN 6 +typedef struct _UidMacMappingEntry +{ + UCHAR isServer; + UCHAR uIDAddByUs; /* If the host-uniq or AC-cookie is add by our driver, set it as 1, else set as 0. */ + UCHAR uIDStr[PPPOE_DIS_UID_LEN]; /* String used for identify who sent this pppoe packet in discovery stage. */ + UCHAR macAddr[MAC_ADDR_LEN]; /* Mac address associated to this uid string. */ + ULONG lastTime; + struct _UidMacMappingEntry *pNext; /*Pointer to next entry in link-list of Uid hash table. */ +}UidMacMappingEntry, *PUidMacMappingEntry; + +typedef struct _UidMacMappingTable +{ + BOOLEAN valid; + UidMacMappingEntry *uidHash[MAT_MAX_HASH_ENTRY_SUPPORT]; +}UidMacMappingTable; + +/* "Host-Uniq <-> Mac Address" Mapping table used for PPPoE Discovery stage */ + +/* Data struct used for PPPoE session stage */ +typedef struct _SesMacMappingEntry +{ + UINT16 sessionID; /* In network order */ + UCHAR outMacAddr[MAC_ADDR_LEN]; + UCHAR inMacAddr[MAC_ADDR_LEN]; + ULONG lastTime; + struct _SesMacMappingEntry *pNext; +}SesMacMappingEntry, *PSesMacMappingEntry; + +typedef struct _SesMacMappingTable +{ + BOOLEAN valid; + SesMacMappingEntry *sesHash[MAT_MAX_HASH_ENTRY_SUPPORT]; +}SesMacMappingTable; + +/* Declaration of protocol handler for PPPoE Discovery stage */ +struct _MATProtoOps MATProtoPPPoEDisHandle = +{ + .init = MATProto_PPPoEDis_Init, + .tx = MATProto_PPPoEDis_Tx, + .rx = MATProto_PPPoEDis_Rx, + .exit = MATProto_PPPoEDis_Exit, +}; + +/* Declaration of protocol handler for PPPoE Session stage */ +struct _MATProtoOps MATProtoPPPoESesHandle = +{ + .init = MATProto_PPPoESes_Init, + .tx = MATProto_PPPoESes_Tx, + .rx = MATProto_PPPoESes_Rx, + .exit =MATProto_PPPoESes_Exit, +}; + + +NDIS_STATUS dumpSesMacTb( + IN MAT_STRUCT *pMatCfg, + IN int hashIdx) +{ + SesMacMappingTable *pSesMacTable; + SesMacMappingEntry *pHead; + int startIdx, endIdx; + + + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + if ((!pSesMacTable) || (!pSesMacTable->valid)) + { + DBGPRINT(RT_DEBUG_OFF, ("SesMacTable not init yet, so cannot do dump!\n")); + return FALSE; + } + + if(hashIdx < 0) + { /* dump all. */ + startIdx = 0; + endIdx = MAT_MAX_HASH_ENTRY_SUPPORT - 1; + } + else + { /* dump specific hash index. */ + startIdx = endIdx = hashIdx; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__)); + for (; startIdx<= endIdx; startIdx++) + { + pHead = pSesMacTable->sesHash[startIdx]; + while(pHead) + { + DBGPRINT(RT_DEBUG_OFF, ("SesMac[%d]:\n", startIdx)); + DBGPRINT(RT_DEBUG_OFF, ("\tsesID=%d,inMac=%02x:%02x:%02x:%02x:%02x:%02x,outMac=%02x:%02x:%02x:%02x:%02x:%02x,lastTime=0x%lx, pNext=%p\n", + pHead->sessionID, PRINT_MAC(pHead->inMacAddr), PRINT_MAC(pHead->outMacAddr), pHead->lastTime, pHead->pNext)); + pHead = pHead->pNext; + } + } + DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n")); + + return TRUE; + +} + + +NDIS_STATUS dumpUidMacTb(MAT_STRUCT *pMatCfg, int hashIdx) +{ + UidMacMappingTable *pUidMacTable; + UidMacMappingEntry *pHead; + int i; + int startIdx, endIdx; + + + pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable; + if ((!pUidMacTable) || (!pUidMacTable->valid)) + { + DBGPRINT(RT_DEBUG_OFF, ("UidMacTable not init yet, so cannot do dump!\n")); + return FALSE; + } + + if(hashIdx < 0) + { /* dump all. */ + startIdx = 0; + endIdx = MAT_MAX_HASH_ENTRY_SUPPORT-1; + } + else + { /* dump specific hash index. */ + startIdx = endIdx = hashIdx; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__)); + for (; startIdx<= endIdx; startIdx++) + { + pHead = pUidMacTable->uidHash[startIdx]; + while(pHead) + { + DBGPRINT(RT_DEBUG_OFF, ("UidMac[%d]:\n", startIdx)); + DBGPRINT(RT_DEBUG_OFF, ("\tisSrv=%d, uIDAddbyUs=%d, Mac=%02x:%02x:%02x:%02x:%02x:%02x, lastTime=0x%lx, pNext=%p\n", + pHead->isServer, pHead->uIDAddByUs, PRINT_MAC(pHead->macAddr), pHead->lastTime, pHead->pNext)); + DBGPRINT(RT_DEBUG_OFF, ("\tuIDStr=")); + for(i=0; i< PPPOE_DIS_UID_LEN; i++) + DBGPRINT(RT_DEBUG_OFF, ("%02x", pHead->uIDStr[i])); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + pHead = pHead->pNext; + } + } + DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n")); + + return TRUE; +} + + +static NDIS_STATUS UidMacTable_RemoveAll( + IN MAT_STRUCT *pMatCfg) +{ + UidMacMappingTable *pUidMacTable; + UidMacMappingEntry *pEntry; + INT i; + + pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable; + + if(!pUidMacTable) + return TRUE; + + if (pUidMacTable->valid) + { + pUidMacTable->valid = FALSE; + for (i=0; iuidHash[i]) != NULL) + { + pUidMacTable->uidHash[i] = pEntry->pNext; + MATDBEntryFree(pMatCfg, (PUCHAR)pEntry); + } + } + } + +/* kfree(pMatCfg->MatTableSet.UidMacTable); */ + os_free_mem(NULL, pMatCfg->MatTableSet.UidMacTable); + pMatCfg->MatTableSet.UidMacTable = NULL; + + return TRUE; +} + + +static NDIS_STATUS SesMacTable_RemoveAll( + IN MAT_STRUCT *pMatCfg) +{ + SesMacMappingTable *pSesMacTable; + SesMacMappingEntry *pEntry; + INT i; + + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + if (!pSesMacTable) + return TRUE; + + if (pSesMacTable->valid) + { + pSesMacTable->valid = FALSE; + for (i=0; isesHash[i]) != NULL) + { + pSesMacTable->sesHash[i] = pEntry->pNext; + MATDBEntryFree(pMatCfg, (PUCHAR)pEntry); + } + } + } + +/* kfree(pMatCfg->MatTableSet.SesMacTable); */ + os_free_mem(NULL, pMatCfg->MatTableSet.SesMacTable); + pMatCfg->MatTableSet.SesMacTable = NULL; + + return TRUE; + +} + + +static PUidMacMappingEntry UidMacTableUpdate( + IN MAT_STRUCT *pMatCfg, + IN PUCHAR pInMac, + IN PUCHAR pOutMac, + IN PUCHAR pTagInfo, + IN UINT16 tagLen, + IN UINT16 isServer) +{ + UINT hashIdx, i=0, uIDAddByUs = 0; + UidMacMappingTable *pUidMacTable; + UidMacMappingEntry *pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL; + UCHAR hashVal = 0; + PUCHAR pUIDStr= NULL; + ULONG now; + + + pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable; + if ((!pUidMacTable) || (!pUidMacTable->valid)) + return NULL; + + if (pTagInfo && tagLen >0) + { + pUIDStr = pTagInfo; + uIDAddByUs = 0; + tagLen = (tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen); + } + else + { + /* + We assume the station just have one role,i.e., just a PPPoE server or just a PPPoE client. + For a packet send by server, we use the destination MAC as our uIDStr + For a packet send by client, we use the source MAC as our uIDStr. + */ + pUIDStr = isServer ? pOutMac: pInMac; + tagLen = MAC_ADDR_LEN; + uIDAddByUs = 1; + } + + for (i=0; iuidHash[hashIdx]; + while(pEntry) + { + NdisGetSystemUpTime(&now); + + /* Find the existed UidMac Mapping entry */ + if (NdisEqualMemory(pUIDStr, pEntry->uIDStr, tagLen) && IS_EQUAL_MAC(pEntry->macAddr, pInMac)) + { + /* Update info of this entry */ + pEntry->isServer = isServer; + pEntry->uIDAddByUs = uIDAddByUs; + pEntry->lastTime = now; + + return pEntry; + } + else + { /* handle the age-out situation */ + if (RTMP_TIME_AFTER(now, (pEntry->lastTime + MAT_TB_ENTRY_AGEOUT_TIME))) + { + /* Remove the aged entry from the uidHash */ + if (pEntry == pUidMacTable->uidHash[hashIdx]) + { + pUidMacTable->uidHash[hashIdx]= pEntry->pNext; + pPrev = pUidMacTable->uidHash[hashIdx]; + } + else + { + pPrev->pNext = pEntry->pNext; + } + + /*After remove this entry from macHash list and uidHash list, now free it! */ + MATDBEntryFree(pMatCfg, (PUCHAR)pEntry); + pMatCfg->nodeCount--; + pEntry = (pPrev == NULL ? NULL: pPrev->pNext); + } + 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 UidMacMapping entry and insert into the double-hash */ + pNewEntry = (UidMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(UidMacMappingEntry)); + if (pNewEntry) + { + NdisZeroMemory(pNewEntry, sizeof(UidMacMappingEntry)); + + pNewEntry->isServer = isServer; + pNewEntry->uIDAddByUs = uIDAddByUs; + NdisMoveMemory(pNewEntry->macAddr, pInMac, MAC_ADDR_LEN); + NdisMoveMemory(pNewEntry->uIDStr, pUIDStr, tagLen); + pNewEntry->pNext = NULL; + NdisGetSystemUpTime(&pNewEntry->lastTime); + + /* Update mac-side hash link list */ + if (pUidMacTable->uidHash[hashIdx] == NULL) + { /* Hash list is empty, directly assign it. */ + pUidMacTable->uidHash[hashIdx] = pNewEntry; + } + else + { + /* Ok, we insert the new entry into the root of uidHash[hashIdx] */ + pNewEntry->pNext = pUidMacTable->uidHash[hashIdx]; + pUidMacTable->uidHash[hashIdx] = pNewEntry; + } + /*dumpUidMacTb(pMatCfg, hashIdx); //for debug */ + + pMatCfg->nodeCount++; + + return pNewEntry; + } + + return NULL; +} + + +static PUidMacMappingEntry UidMacTableLookUp( + IN MAT_STRUCT *pMatCfg, + IN PUCHAR pTagInfo, + IN UINT16 tagLen) +{ + UINT hashIdx; + UINT16 len; + UCHAR hashValue = 0; + UidMacMappingEntry *pEntry = NULL; + UidMacMappingTable *pUidMacTable; + + pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable; + if ((!pUidMacTable) || (!pUidMacTable->valid)) + return NULL; + + /* Use hash to find out the location of that entry and get the Mac address. */ + len = tagLen; + while(len) + hashValue ^= pTagInfo[--len]; + hashIdx = hashValue % MAT_MAX_HASH_ENTRY_SUPPORT; + + pEntry = pUidMacTable->uidHash[hashIdx]; + while(pEntry) + { + if (NdisEqualMemory(pEntry->uIDStr, pTagInfo, tagLen)) + { +/* 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; + } + else + pEntry = pEntry->pNext; + } + + /* We didn't find any matched Mac address. */ + return NULL; + +} + + +static PUCHAR getInMacByOutMacFromSesMacTb( + IN MAT_STRUCT *pMatCfg, + IN PUCHAR outMac, + IN UINT16 sesID) +{ + UINT16 hashIdx; + SesMacMappingEntry *pEntry = NULL; + SesMacMappingTable *pSesMacTable; + + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + + if (!pSesMacTable->valid) + return NULL; + + /* Use hash to find out the location of that entry and get the Mac address. */ + hashIdx = sesID % MAT_MAX_HASH_ENTRY_SUPPORT; + + pEntry = pSesMacTable->sesHash[hashIdx]; + while(pEntry) + { + if ((pEntry->sessionID == sesID) && IS_EQUAL_MAC(pEntry->outMacAddr, outMac)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): find it! dstMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, pEntry->inMacAddr[0],pEntry->inMacAddr[1],pEntry->inMacAddr[2], + pEntry->inMacAddr[3],pEntry->inMacAddr[4],pEntry->inMacAddr[5])); + + /*Update the lastTime to prevent the aging before pDA processed! */ + NdisGetSystemUpTime(&pEntry->lastTime); + + return pEntry->inMacAddr; + } + else + { + pEntry = pEntry->pNext; + } + } + + /* We didn't find any matched Mac address, just return and didn't do any modification */ + return NULL; +} + + +/* This function used to maintain the pppoe convert table which incoming node + is a pppoe client and want to connect to use inner pppoe server. +*/ +static NDIS_STATUS SesMacTableUpdate( + IN MAT_STRUCT *pMatCfg, + IN PUCHAR inMacAddr, + IN UINT16 sesID, + IN PUCHAR outMacAddr) +{ + UINT16 hashIdx; + SesMacMappingEntry *pEntry, *pPrev, *pNewEntry; + SesMacMappingTable *pSesMacTable; + ULONG now; + + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + if ((!pSesMacTable) || (!pSesMacTable->valid)) + return FALSE; + + hashIdx = sesID % MAT_MAX_HASH_ENTRY_SUPPORT; + +/* + DBGPRINT(RT_DEBUG_TRACE,("%s():sesID=0x%04x,inMac=%02x%02x:%02x:%02x:%02x:%02x, + outMac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, sesID, + inMacAddr[0],inMacAddr[1],inMacAddr[2],inMacAddr[3],inMacAddr[4],inMacAddr[5], + outMacAddr[0],outMacAddr[1],outMacAddr[2],outMacAddr[3],outMacAddr[4],outMacAddr[5])); +*/ + + pEntry = pPrev = pSesMacTable->sesHash[hashIdx]; + while(pEntry) + { + NdisGetSystemUpTime(&now); + + /* Find a existed IP-MAC Mapping entry */ + if ((sesID == pEntry->sessionID) && + IS_EQUAL_MAC(pEntry->inMacAddr, inMacAddr) && + IS_EQUAL_MAC(pEntry->outMacAddr, outMacAddr)) + { + /* compare is useless. So we directly copy it into the entry. */ + pEntry->lastTime = now; + + return TRUE; + } + else + { /* handle the age-out situation */ + if (RTMP_TIME_AFTER(now, (pEntry->lastTime + PPPoE_SES_ENTRY_AGEOUT_TIME))) + { + /* Remove the aged entry */ + if (pEntry == pSesMacTable->sesHash[hashIdx]) + { + pSesMacTable->sesHash[hashIdx]= pEntry->pNext; + pPrev = pSesMacTable->sesHash[hashIdx]; + } + else + { + pPrev->pNext = pEntry->pNext; + } + MATDBEntryFree(pMatCfg, (PUCHAR)pEntry); + pMatCfg->nodeCount--; + pEntry = (pPrev == NULL ? NULL: pPrev->pNext); + } + 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 = (SesMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(SesMacMappingEntry)); + if (pNewEntry != NULL) + { + pNewEntry->sessionID= sesID; + NdisMoveMemory(pNewEntry->inMacAddr, inMacAddr, MAC_ADDR_LEN); + NdisMoveMemory(pNewEntry->outMacAddr, outMacAddr, MAC_ADDR_LEN); + pNewEntry->pNext = NULL; + NdisGetSystemUpTime(&pNewEntry->lastTime); + + if (pSesMacTable->sesHash[hashIdx] == NULL) + { /* Hash list is empty, directly assign it. */ + pSesMacTable->sesHash[hashIdx] = pNewEntry; + } + else + { + /* Ok, we insert the new entry into the root of hash[hashIdx] */ + pNewEntry->pNext = pSesMacTable->sesHash[hashIdx]; + pSesMacTable->sesHash[hashIdx] = pNewEntry; + } + + /*dumpSesMacTb(pMatCfg, hashIdx); */ + pMatCfg->nodeCount++; + + return TRUE; + } + + return FALSE; +} + + +/* PPPoE discovery stage Rx handler. + When Rx, check if the PPPoE tag "Host-uniq" exists or not. + If exists, we check our database and convert the dstMac to correct one. + */ +static PUCHAR MATProto_PPPoEDis_Rx( + IN MAT_STRUCT *pMatCfg, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + PUCHAR pData, pSrvMac = NULL, pOutMac=NULL, pInMac = NULL, pTagContent = NULL, pPayloadLen; + UINT16 payloadLen, leftLen; + UINT16 tagID, tagLen =0; + UINT16 needUpdateSesTb= 0, sesID=0, isPADT = 0; + UINT16 findTag=0; + PUidMacMappingEntry pEntry = NULL; + + pData = pLayerHdr; + if (*(pData) != 0x11) + return NULL; + + /* Check the Code type. */ + pData++; + switch(*pData) + { + case PPPOE_CODE_PADO: + /*It's a packet send by a PPPoE server which behind of our device. */ + findTag = PPPOE_TAG_ID_HOST_UNIQ; + break; + case PPPOE_CODE_PADS: + needUpdateSesTb = 1; + findTag = PPPOE_TAG_ID_HOST_UNIQ; + pSrvMac = (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb) + 6); + break; + case PPPOE_CODE_PADR: + /*It's a packet send by a PPPoE client which in front of our device. */ + findTag = PPPOE_TAG_ID_AC_COOKIE; + break; + case PPPOE_CODE_PADI: + /*Do nothing! Just forward this packet to upper layer directly. */ + return NULL; + case PPPOE_CODE_PADT: + isPADT = 1; + pOutMac= (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb) + 6); + break; + default: + return NULL; + } + + /* Ignore the Code field(length=1) */ + pData ++; + if (needUpdateSesTb || isPADT) + sesID = OS_NTOHS(get_unaligned((PUINT16)(pData))); + + if (isPADT) + { + pInMac = getInMacByOutMacFromSesMacTb(pMatCfg, pOutMac, sesID); + return pInMac; + } + /* Ignore the session ID field.(length = 2) */ + pData += 2; + + /* Get the payload length, ignore the payload length field.(length = 2) */ + payloadLen = OS_NTOHS(get_unaligned((PUINT16)(pData))); + pPayloadLen = pData; + pData += 2; + + + /* First parsing the PPPoE paylod to find out the required tag(e.g., x0103 or 0x0104) */ + leftLen = payloadLen; + while (leftLen) + { + tagID = OS_NTOHS(get_unaligned((PUINT16)(pData))); + tagLen = OS_NTOHS(get_unaligned((PUINT16)(pData+2))); + + if (tagID== findTag && tagLen>0) + { + + /*shift to the tag value field. */ + pTagContent = pData + 4; + tagLen = tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen; + break; + } + else + { + pData += (tagLen + 4); + leftLen -= (tagLen + 4); + } + } + + + /* Now update our pppoe discovery table "UidMacTable" */ + if (pTagContent) + { + pEntry = UidMacTableLookUp(pMatCfg, pTagContent, tagLen); + + /* Remove the AC-Cookie or host-uniq if we ever add the field for this session. */ + if (pEntry) + { + if (pEntry->uIDAddByUs) + { + PUCHAR tagHead, nextTagHead; + UINT removedTagLen, tailLen; + + removedTagLen = 4 + tagLen; /*The total length tag ID/info we want to remove. */ + tagHead = pTagContent - 4; /*The start address of the tag we want to remove in sk bufffer */ + tailLen = GET_OS_PKT_LEN(pSkb) - (pTagContent - (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb))) - removedTagLen; /*Total left bytes we want to move. */ + if (tailLen) + { + nextTagHead = pTagContent + tagLen; /*The start address of next tag ID/info in sk buffer. */ + memmove(tagHead, nextTagHead, tailLen); + } +/* SET_OS_PKT_DATATAIL(pSkb, GET_OS_PKT_DATATAIL(pSkb), (-removedTagLen)); */ +/* GET_OS_PKT_LEN(pSkb) -= removedTagLen; */ + OS_PKT_TAIL_ADJUST(pSkb, removedTagLen); + + *((UINT16 *)pPayloadLen) = OS_HTONS(payloadLen - removedTagLen); + } + + if (needUpdateSesTb) { + + SesMacTableUpdate(pMatCfg, pEntry->macAddr,sesID, pSrvMac); + } + + return pEntry->macAddr; + } + } + + return NULL; +} + + + +/* PPPoE discovery stage Tx handler. + If the pakcet is PADI/PADR, check if the PPPoE tag "Host-uniq" exists or not. + If exists, we just record it in our table, else we insert the Mac address + of Sender as well as the host-uniq, then forward to the destination. It's + a one(MAC)-to-one(Host-uniq) mapping in our table. + If the packet is PADO/PADS, check if the PPPoE tag "AC-Cookie" exists or not. + If exists, we just record it in our table, else we insert the Mac address + of Sender as well as the AC-Cookie, then forward to the destination. It may + one(MAC)-to-many(AC-Cookie) mapping in our table. + + Host-uniq TAG ID= 0x0103 + AC-Cookie TAG ID= 0x0104 + */ +static PUCHAR MATProto_PPPoEDis_Tx( + IN MAT_STRUCT *pMatStruct, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + PUCHAR pData, pTagContent = NULL, pPayloadLen, pPPPPoETail; + PUCHAR pSrcMac, pDstMac; + UINT16 payloadLen, leftLen, offset; + UINT16 tagID, tagLen =0; + UINT16 isServer = 0, needUpdateSesTb= 0, sesID = 0; + UINT16 findTag=0; + PUidMacMappingEntry pEntry = NULL; + PUCHAR pPktHdr; + PNDIS_PACKET pModSkb = NULL; + + pPktHdr = GET_OS_PKT_DATAPTR(pSkb); + pDstMac = pPktHdr; + pSrcMac = (pPktHdr + 6); + pData = pLayerHdr; + + + /* Check the pppoe version and Type. It should be 0x11 */ + if (*(pData) != 0x11) + return NULL; + + /* Check the Code type. */ + pData++; + switch(*pData) + { + /* Send by pppoe client */ + case PPPOE_CODE_PADI: + case PPPOE_CODE_PADR: + findTag = PPPOE_TAG_ID_HOST_UNIQ; + break; + /* Send by pppoe server */ + case PPPOE_CODE_PADO: + case PPPOE_CODE_PADS: + isServer = 1; + findTag = PPPOE_TAG_ID_AC_COOKIE; + if (*pData == PPPOE_CODE_PADS) /* For PADS, we need record the session ID. */ + needUpdateSesTb = 1; + break; + /* Both server and client can send this packet */ + case PPPOE_CODE_PADT: + /* TODO: + currently we didn't handle PADT packet. We just leave the + session entry and make it age-out automatically. Maybe we + can remove the entry when we receive this packet. + */ + return NULL; + default: + return NULL; + } + + /* + Ignore the Code field(length=1) and if it's a PADS packet, we + should hold the session ID and for latter to update our table. + */ + pData ++; + if (needUpdateSesTb) + sesID = OS_NTOHS(get_unaligned((PUINT16)(pData))); + + /* Ignore the session ID field.(length = 2) */ + pData += 2; + + /* Get the payload length, and shift the payload length field(length = 2) to next field. */ + payloadLen = OS_NTOHS(get_unaligned((PUINT16)(pData))); + pPayloadLen = pData; + offset = pPayloadLen - (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb)); + pData += 2; + + + /* First parsing the PPPoE paylod to find out the required tag(e.g., x0103 or 0x0104) */ + leftLen = payloadLen; + while (leftLen) + { + tagID = OS_NTOHS(get_unaligned((PUINT16)(pData))); + tagLen = OS_NTOHS(get_unaligned((PUINT16)(pData+2))); + + if (tagID== findTag && tagLen>0) + { + + /* Move the pointer to the tag value field. 4 = 2(TAG ID) + 2(TAG_LEN) */ + pTagContent = pData + 4; +/* tagLen = tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen; */ + break; + } + else + { + pData += (tagLen + 4); + leftLen -= (tagLen + 4); + } + } + + + /* Now update our pppoe discovery table "UidMacTable" */ + pEntry = UidMacTableUpdate(pMatStruct, pSrcMac, pDstMac, pTagContent, tagLen, isServer); + + if (pEntry && (pTagContent == NULL)) + { + PUCHAR tailHead; + + if(OS_PKT_CLONED(pSkb)) + { +/* pModSkb = (PNDIS_PACKET)skb_copy(RTPKT_TO_OSPKT(pSkb), MEM_ALLOC_FLAG); */ + pModSkb = (PNDIS_PACKET)OS_PKT_COPY(RTPKT_TO_OSPKT(pSkb)); + } + else + pModSkb = (PNDIS_PACKET)RTPKT_TO_OSPKT(pSkb); + + if(!pModSkb) + return NULL; + +/* tailHead = skb_put(RTPKT_TO_OSPKT(pModSkb), (PPPOE_DIS_UID_LEN + 4)); */ + tailHead = OS_PKT_TAIL_BUF_EXTEND(pModSkb, (PPPOE_DIS_UID_LEN + 4)); + if (tailHead) + { + pPayloadLen = GET_OS_PKT_DATAPTR(pModSkb) + offset; + pPPPPoETail = pPayloadLen + payloadLen; + if(tailHead > pPPPPoETail) + tailHead = pPPPPoETail; + + if (pEntry->isServer) + { /*Append the AC-Cookie tag info in the tail of the pppoe packet. */ + tailHead[0] = 0x01; + tailHead[1] = 0x04; + tailHead[2] = 0x00; + tailHead[3] = PPPOE_DIS_UID_LEN; + tailHead += 4; + NdisMoveMemory(tailHead, pEntry->uIDStr, PPPOE_DIS_UID_LEN); + } + else + { /*Append the host-uniq tag info in the tail of the pppoe packet. */ + tailHead[0] = 0x01; + tailHead[1] = 0x03; + tailHead[2] = 0x00; + tailHead[3] = PPPOE_DIS_UID_LEN; + tailHead += 4; + NdisMoveMemory(tailHead, pEntry->uIDStr, PPPOE_DIS_UID_LEN); + } + *(UINT16 *)pPayloadLen = OS_HTONS(payloadLen + 4 + PPPOE_DIS_UID_LEN); + } + } + + if (needUpdateSesTb) + SesMacTableUpdate(pMatStruct, pSrcMac, sesID, pDstMac); + + return (PUCHAR)pModSkb; +} + + +/* PPPoE discovery stage init function */ +static NDIS_STATUS MATProto_PPPoEDis_Init( + IN MAT_STRUCT *pMatCfg) +{ + UidMacMappingTable *pUidMacTable; + SesMacMappingTable *pSesMacTable; + + pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable; + if (!pUidMacTable) + { +/* pMatCfg->MatTableSet.UidMacTable = (VOID *)kmalloc(sizeof(UidMacMappingTable), GFP_KERNEL); */ + os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.UidMacTable), sizeof(UidMacMappingTable)); + if (pMatCfg->MatTableSet.UidMacTable) + { + pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable; + NdisZeroMemory(pUidMacTable, sizeof(UidMacMappingTable)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MATProto_PPPoEDis_Init(): Allocate memory for UidMacTable failed!\n")); + return FALSE; + } + } + pUidMacTable->valid = TRUE; + + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + if (!pSesMacTable) + { +/* pMatCfg->MatTableSet.SesMacTable = (VOID *)kmalloc(sizeof(SesMacMappingTable), GFP_KERNEL); */ + os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.SesMacTable), sizeof(SesMacMappingTable)); + if (pMatCfg->MatTableSet.SesMacTable) + { + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + NdisZeroMemory(pSesMacTable, sizeof(SesMacMappingTable)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MATProto_PPPoEDis_Init(): Allocate memory for SesMacTable failed!\n")); + return FALSE; + } + + } + pSesMacTable->valid = TRUE; + + return TRUE; +} + + +/* PPPoE discovery stage exit function */ +static NDIS_STATUS MATProto_PPPoEDis_Exit( + IN MAT_STRUCT *pMatCfg) +{ + UidMacTable_RemoveAll(pMatCfg); + SesMacTable_RemoveAll(pMatCfg); + + return TRUE; +} + + +/* PPPoE Session stage Rx handler + When we receive a ppp pakcet, first check if the srcMac is a PPPoE server or not. + if it's a server, check the session ID of specific PPPoEServeryEntry and find out the + correct dstMac Address. + if it's not a server, check the session ID and find out the cor + + */ +static PUCHAR MATProto_PPPoESes_Rx( + IN MAT_STRUCT *pMatCfg, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + PUCHAR srcMac, dstMac = NULL, pData; + UINT16 sesID; + + srcMac = (GET_OS_PKT_DATAPTR(pSkb) + 6); + pData = pLayerHdr; + + /*skip the first two bytes.(version/Type/Code) */ + pData += 2; + + /*get the session ID */ + sesID = OS_NTOHS(get_unaligned((PUINT16)(pData))); + + /* Try to find the dstMac from SesMacHash table. */ + dstMac = getInMacByOutMacFromSesMacTb(pMatCfg, srcMac, sesID); + + return dstMac; +} + +/* PPPoE Session stage Tx handler */ +static PUCHAR MATProto_PPPoESes_Tx( + IN MAT_STRUCT *pMatStruct, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + + /* + For transmit packet, we do nothing. + */ + return NULL; +} + + +/* PPPoE session stage init function */ +static NDIS_STATUS MATProto_PPPoESes_Init( + IN MAT_STRUCT *pMatStruct) +{ + return TRUE; +} + +/* PPPoE session stage exit function */ +static NDIS_STATUS MATProto_PPPoESes_Exit( + IN MAT_STRUCT *pMatStruct) +{ + + return TRUE; +} + +#endif /* MAT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_profile.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_profile.c new file mode 100644 index 000000000..85830e1bb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_profile.c @@ -0,0 +1,5786 @@ +/**************************************************************************** + * 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_profile.c + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#include "rt_config.h" + + +#define ETH_MAC_ADDR_STR_LEN 17 /* in format of xx:xx:xx:xx:xx:xx*/ + +/* We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed.*/ +BOOLEAN rtstrmactohex(PSTRING s1, PSTRING s2) +{ + int i = 0; + PSTRING ptokS = s1, ptokE = s1; + + if (strlen(s1) != ETH_MAC_ADDR_STR_LEN) + return FALSE; + + while((*ptokS) != '\0') + { + if((ptokE = strchr(ptokS, ':')) != NULL) + *ptokE++ = '\0'; + if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1)))) + break; /* fail*/ + AtoH(ptokS, (PUCHAR)&s2[i++], 1); + ptokS = ptokE; + if (ptokS == NULL) + break; + if (i == 6) + break; /* parsing finished*/ + } + + return ( i == 6 ? TRUE : FALSE); + +} + + +#define ASC_LOWER(_x) ((((_x) >= 0x41) && ((_x) <= 0x5a)) ? (_x) + 0x20 : (_x)) +/* we assume the s1 and s2 both are strings.*/ +BOOLEAN rtstrcasecmp(PSTRING s1, PSTRING s2) +{ + PSTRING p1 = s1, p2 = s2; + CHAR c1, c2; + + if (strlen(s1) != strlen(s2)) + return FALSE; + + while(*p1 != '\0') + { + c1 = ASC_LOWER(*p1); + c2 = ASC_LOWER(*p2); + if(c1 != c2) + return FALSE; + p1++; + p2++; + } + + return TRUE; +} + + +/* we assume the s1 (buffer) and s2 (key) both are strings.*/ +PSTRING rtstrstruncasecmp(PSTRING s1, PSTRING s2) +{ + INT l1, l2, i; + char temp1, temp2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + + l1 = strlen(s1); + + while (l1 >= l2) + { + l1--; + + for(i=0; i= l2) + { + l1--; + if (!memcmp(s1,s2,l2)) + return s1; + s1++; + } + + return NULL; +} + +/** + * rstrtok - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture. + */ +PSTRING __rstrtok; +PSTRING rstrtok(PSTRING s,const PSTRING ct) +{ + PSTRING sbegin, send; + + sbegin = s ? s : __rstrtok; + if (!sbegin) + { + return NULL; + } + + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') + { + __rstrtok = NULL; + return( NULL ); + } + + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + + __rstrtok = send; + + return (sbegin); +} + +/** + * delimitcnt - return the count of a given delimiter in a given string. + * @s: The string to be searched. + * @ct: The delimiter to search for. + * Notice : We suppose the delimiter is a single-char string(for example : ";"). + */ +INT delimitcnt(PSTRING s,PSTRING ct) +{ + INT count = 0; + /* point to the beginning of the line */ + PSTRING token = s; + + for ( ;; ) + { + token = strpbrk(token, ct); /* search for delimiters */ + + if ( token == NULL ) + { + /* advanced to the terminating null character */ + break; + } + /* skip the delimiter */ + ++token; + + /* + * Print the found text: use len with %.*s to specify field width. + */ + + /* accumulate delimiter count */ + ++count; + } + return count; +} + +/* + * converts the Internet host address from the standard numbers-and-dots notation + * into binary data. + * returns nonzero if the address is valid, zero if not. + */ +int rtinet_aton(PSTRING cp, unsigned int *addr) +{ + unsigned int val; + int base, n; + STRING c; + unsigned int parts[4]; + unsigned int *pp = parts; + + for (;;) + { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; + base = 10; + if (*cp == '0') + { + if (*++cp == 'x' || *cp == 'X') + base = 16, cp++; + else + base = 8; + } + while ((c = *cp) != '\0') + { + if (isdigit((unsigned char) c)) + { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isxdigit((unsigned char) c)) + { + val = (val << 4) + + (c + 10 - (islower((unsigned char) c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') + { + /* + * Internet format: a.b.c.d a.b.c (with c treated as 16-bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return 0; + *pp++ = val, cp++; + } + else + break; + } + + /* + * Check for trailing junk. + */ + while (*cp) + if (!isspace((unsigned char) *cp++)) + return 0; + + /* + * Concoct the address according to the number of parts specified. + */ + n = pp - parts + 1; + switch (n) + { + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return 0; + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + *addr = OS_HTONL(val); + return 1; + +} + +/* + ======================================================================== + + Routine Description: + Find key section for Get key parameter. + + Arguments: + buffer Pointer to the buffer to start find the key section + section the key of the secion to be find + + Return Value: + NULL Fail + Others Success + ======================================================================== +*/ +PSTRING RTMPFindSection( + IN PSTRING buffer) +{ + STRING temp_buf[32]; + PSTRING ptr; + + strcpy(temp_buf, "Default"); + + if((ptr = rtstrstr(buffer, temp_buf)) != NULL) + return (ptr+strlen("\n")); + else + return NULL; +} + +/* + ======================================================================== + + Routine Description: + Get key parameter. + + Arguments: + key Pointer to key string + dest Pointer to destination + destsize The datasize of the destination + buffer Pointer to the buffer to start find the key + bTrimSpace Set true if you want to strip the space character of the result pattern + + Return Value: + TRUE Success + FALSE Fail + + Note: + This routine get the value with the matched key (case case-sensitive) + For SSID and security key related parameters, we SHALL NOT trim the space(' ') character. + ======================================================================== +*/ +INT RTMPGetKeyParameter( + IN PSTRING key, + OUT PSTRING dest, + IN INT destsize, + IN PSTRING buffer, + IN BOOLEAN bTrimSpace) +{ + PSTRING pMemBuf, temp_buf1 = NULL, temp_buf2 = NULL; + PSTRING start_ptr, end_ptr; + PSTRING ptr; + PSTRING offset = NULL; + INT len; + + os_alloc_mem(NULL, (PUCHAR *)&pMemBuf, MAX_PARAM_BUFFER_SIZE * 2); + if (pMemBuf == NULL) + return (FALSE); + + memset(pMemBuf, 0, MAX_PARAM_BUFFER_SIZE * 2); + temp_buf1 = pMemBuf; + temp_buf2 = (PSTRING)(pMemBuf + MAX_PARAM_BUFFER_SIZE); + + + /*find section*/ + if((offset = RTMPFindSection(buffer)) == NULL) + { + os_free_mem(NULL, (PUCHAR)pMemBuf); + return (FALSE); + } + + strcpy(temp_buf1, "\n"); + strcat(temp_buf1, key); + strcat(temp_buf1, "="); + + /*search key*/ + if((start_ptr=rtstrstr(offset, temp_buf1)) == NULL) + { + os_free_mem(NULL, (PUCHAR)pMemBuf); + return (FALSE); + } + + start_ptr += strlen("\n"); + if((end_ptr = rtstrstr(start_ptr, "\n"))==NULL) + end_ptr = start_ptr+strlen(start_ptr); + + if (end_ptr= pAd->ApCfg.BssidNum) + break; + + KeyIdx = simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->ApCfg.MBSSID[i].wdev.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + pAd->ApCfg.MBSSID[i].wdev.DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DefaultKeyID(0~3)=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.DefaultKeyId)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + KeyIdx = simple_strtol(tmpbuf, 0, 10); + RTMPSetSTADefKeyId(pAd, KeyIdx); + + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.wdev.DefaultKeyId)); + } +#endif /* CONFIG_STA_SUPPORT */ + } + + + for (idx = 0; idx < 4; idx++) + { + snprintf(tok_str, sizeof(tok_str), "Key%dType", idx + 1); + /*Key1Type*/ + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + /* + do sanity check for KeyType length; + or in station mode, the KeyType length > 1, + the code will overwrite the stack of caller + (RTMPSetProfileParameters) and cause srcbuf = NULL + */ + if (i < MAX_MBSSID_NUM(pAd)) + KeyType[i] = simple_strtol(macptr, 0, 10); + } +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (TRUE) + { + BOOLEAN bKeyxStryIsUsed = FALSE; + + //GPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum)); + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "Key%dStr%d", idx + 1, i + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[i], i, idx); + + if (bKeyxStryIsUsed == FALSE) + { + bKeyxStryIsUsed = TRUE; + } + } + } + + if (bKeyxStryIsUsed == FALSE) + { + snprintf(tok_str, sizeof(tok_str), "Key%dStr", idx + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + if (pAd->ApCfg.BssidNum == 1) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); + } + else + { + /* Anyway, we still do the legacy dissection of the whole KeyxStr string.*/ + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + rtmp_parse_key_buffer_from_file(pAd, macptr, KeyType[i], i, idx); + } + } + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + snprintf(tok_str, sizeof(tok_str), "Key%dStr", idx + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); + } + } +#endif /* CONFIG_STA_SUPPORT */ + } + } +} + +#ifdef CONFIG_AP_SUPPORT + +#ifdef APCLI_SUPPORT +static void rtmp_read_ap_client_from_file( + IN PRTMP_ADAPTER pAd, + IN PSTRING tmpbuf, + IN PSTRING buffer) +{ + PSTRING macptr = NULL; + INT i=0, j=0, idx; + UCHAR macAddress[MAC_ADDR_LEN]; + PAPCLI_STRUCT pApCliEntry = NULL; + ULONG KeyIdx; + STRING tok_str[16]; + ULONG KeyType[MAX_APCLI_NUM]; + ULONG KeyLen; + struct wifi_dev *wdev; + + NdisZeroMemory(KeyType, sizeof(KeyType)); + + /*ApCliEnable*/ + if(RTMPGetKeyParameter("ApCliEnable", tmpbuf, 128, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + if ((strncmp(macptr, "0", 1) == 0)) + pApCliEntry->Enable = FALSE; + else if ((strncmp(macptr, "1", 1) == 0)) + pApCliEntry->Enable = TRUE; + else + pApCliEntry->Enable = FALSE; + + if (pApCliEntry->Enable) + { + /*pApCliEntry->WpaState = SS_NOTUSE;*/ + /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/ + /*NdisZeroMemory(pApCliEntry->ReplayCounter, LEN_KEY_DESC_REPLAY); */ + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].Enable=%d\n", i, pApCliEntry->Enable)); + } + } + +#ifdef APCLI_CONNECTION_TRIAL + if(RTMPGetKeyParameter("ApCliTrialCh", tmpbuf, 128, buffer, TRUE)) + { + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + pApCliEntry->TrialCh = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("TrialChannel=%d\n", pApCliEntry->TrialCh)); + } + + } +#endif /* APCLI_CONNECTION_TRIAL */ + +#ifdef APCLI_AUTO_BW_SUPPORT + /* ApCliBw */ + if(RTMPGetKeyParameter("ApCliBw", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, FALSE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + wdev = &pApCliEntry->wdev; + + wdev->bw = (UCHAR)simple_strtol(macptr, 0, 10); + if ((wdev->bw != BW_20) && (wdev->bw != BW_40) && (wdev->bw != BW_80)) + { + DBGPRINT(RT_DEBUG_OFF, ("AUTOBW(%s): unknown ApCliEntry[%d].BW=%d recover to BW_20\n", __FUNCTION__, i, wdev->bw)); + wdev->bw = BW_20; + } + DBGPRINT(RT_DEBUG_OFF, ("AUTOBW(%s): New ApCliEntry[%d].BW=%d \n", __FUNCTION__, i, wdev->bw)); + } + } + + /* ApCliPhyMode */ + if(RTMPGetKeyParameter("ApCliPhyMode", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, FALSE)) + { + UINT wmode = 0; + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wmode = simple_strtol(macptr, 0, 10); + + if (!ApCliSetPhyMode(pAd, i, wmode)) + { + DBGPRINT(RT_DEBUG_OFF, ("AUTOBW(%s): skip unknown ApCliEntry[%d].WMODE=%d\n", __FUNCTION__, i, wmode)); + continue; + } + + DBGPRINT(RT_DEBUG_OFF, ("AUTOBW(%s): New ApCliEntry[%d].WMODE=%d \n", __FUNCTION__, i, wmode)); + } + } +#endif /* APCLI_AUTO_BW_SUPPORT */ + + + /*ApCliSsid*/ + if(RTMPGetKeyParameter("ApCliSsid", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, FALSE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + /*Ssid acceptable strlen must be less than 32 and bigger than 0.*/ + pApCliEntry->CfgSsidLen = (UCHAR)strlen(macptr); + if (pApCliEntry->CfgSsidLen > 32) + { + pApCliEntry->CfgSsidLen = 0; + continue; + } + if(pApCliEntry->CfgSsidLen > 0) + { + memcpy(&pApCliEntry->CfgSsid, macptr, pApCliEntry->CfgSsidLen); + pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/ + } else + { + NdisZeroMemory(&(pApCliEntry->CfgSsid), MAX_LEN_OF_SSID); + continue; + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].CfgSsidLen=%d, CfgSsid=%s\n", i, pApCliEntry->CfgSsidLen, pApCliEntry->CfgSsid)); + } + } + + /*ApCliBssid*/ + if(RTMPGetKeyParameter("ApCliBssid", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + NdisZeroMemory(&(pApCliEntry->CfgApCliBssid), MAC_ADDR_LEN); + + if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/ + continue; + /* + if(strcmp(macptr,"00:00:00:00:00:00") == 0) + continue; + */ + for (j=0; jCfgApCliBssid, &macAddress, MAC_ADDR_LEN); + pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/ + } + } + + /*ApCliAuthMode*/ + if (RTMPGetKeyParameter("ApCliAuthMode", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + wdev = &pApCliEntry->wdev; + wdev->bWpaAutoMode = FALSE; + + if ((strncmp(macptr, "WEPAUTO", 7) == 0) || (strncmp(macptr, "wepauto", 7) == 0)) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strncmp(macptr, "SHARED", 6) == 0) || (strncmp(macptr, "shared", 6) == 0)) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if ((strncmp(macptr, "WPAPSKWPA2PSK", 13) == 0) || (strncmp(macptr, "wpapskwpa2psk", 13) == 0)) + { + wdev->AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + wdev->bWpaAutoMode = TRUE; + } + else if ((strncmp(macptr, "WPAPSK", 6) == 0) || (strncmp(macptr, "wpapsk", 6) == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strncmp(macptr, "WPA2PSK", 7) == 0) || (strncmp(macptr, "wpa2psk", 7) == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCli_AuthMode=%d \n", i, wdev->AuthMode)); + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); + } + + } + + /*ApCliEncrypType*/ + if (RTMPGetKeyParameter("ApCliEncrypType", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + wdev = &pApCliEntry->wdev; + + wdev->WepStatus = Ndis802_11WEPDisabled; + wdev->bEncryptAutoMode = FALSE; + if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0)) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11WEPEnabled; + } + else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0)) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0)) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11Encryption3Enabled; + } + else if ((strncmp(macptr, "TKIPAES", 7) == 0) || (strncmp(macptr, "tkipaes", 7) == 0)) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + wdev->WepStatus = Ndis802_11Encryption4Enabled; + wdev->bEncryptAutoMode = TRUE; + } + } + else + { + wdev->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = wdev->WepStatus; + pApCliEntry->GroupCipher = wdev->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_EncrypType = %d \n", i, wdev->WepStatus)); + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); + } + + } + + /*ApCliWPAPSK*/ + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + if (i == 0) + snprintf(tok_str, sizeof(tok_str), "ApCliWPAPSK"); + else + snprintf(tok_str, sizeof(tok_str), "ApCliWPAPSK%d", i); + + if (RTMPGetKeyParameter(tok_str, tmpbuf, 65, buffer, FALSE)) + { + macptr = tmpbuf; + if((strlen(macptr) < 8) || (strlen(macptr) > 64)) + { + DBGPRINT(RT_DEBUG_ERROR, ("APCli_WPAPSK_KEY, key string required 8 ~ 64 characters!!!\n")); + continue; + } + + NdisMoveMemory(pApCliEntry->PSK, macptr, strlen(macptr)); + pApCliEntry->PSKLen = strlen(macptr); + +#ifdef WSC_AP_SUPPORT + pApCliEntry->WscControl.WpaPskLen = pApCliEntry->PSKLen; + NdisZeroMemory(pApCliEntry->WscControl.WpaPsk, sizeof(pApCliEntry->WscControl.WpaPsk)); + NdisMoveMemory(pApCliEntry->WscControl.WpaPsk, pApCliEntry->PSK, pApCliEntry->PSKLen); +#endif /* WSC_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_WPAPSK_KEY=%s, Len=%d\n", i, pApCliEntry->PSK, pApCliEntry->PSKLen)); + + RT_CfgSetWPAPSKKey(pAd, macptr, strlen(macptr), (PUCHAR)pApCliEntry->CfgSsid, (INT)pApCliEntry->CfgSsidLen, pApCliEntry->PMK); + +#ifdef DBG + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) PMK Material => \n", i)); + for (j = 0; j < 32; j++) + { + DBGPRINT(RT_DEBUG_OFF, ("%02x:", pApCliEntry->PMK[j])); + if ((j%16) == 15) + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + DBGPRINT(RT_DEBUG_OFF,("\n")); +#endif /* DBG */ + } + } + + /*ApCliDefaultKeyID*/ + if (RTMPGetKeyParameter("ApCliDefaultKeyID", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->ApCfg.ApCliTab[i].wdev; + + KeyIdx = simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + wdev->DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + wdev->DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) DefaultKeyID(0~3)=%d\n", i, wdev->DefaultKeyId)); + } + } + + /*ApCliKeyXType, ApCliKeyXStr*/ + for (idx=0; idx<4; idx++) + { + snprintf(tok_str, sizeof(tok_str), "ApCliKey%dType", idx+1); + /*ApCliKey1Type*/ + if(RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + KeyType[i] = simple_strtol(macptr, 0, 10); + } + + snprintf(tok_str, sizeof(tok_str), "ApCliKey%dStr", idx+1); + /*ApCliKey1Str*/ + if(RTMPGetKeyParameter(tok_str, tmpbuf, 512, buffer, FALSE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + KeyLen = strlen(macptr); + if(((KeyType[i] == 0) && (KeyLen != 10) && (KeyLen != 26)) || + ((KeyType[i] != 0) && (KeyLen != 5) && (KeyLen != 13))) + { + DBGPRINT(RT_DEBUG_ERROR, ("I/F(apcli%d) Key%dStr is Invalid key length!\n", i, idx+1)); + } + else + { + if (RT_CfgSetWepKey(pAd, macptr, &pApCliEntry->SharedKey[idx], idx) != TRUE) + DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWepKey fail!\n")); + } + } + } + } + } + + /* ApCliTxMode*/ + if (RTMPGetKeyParameter("ApCliTxMode", tmpbuf, 25, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->ApCfg.ApCliTab[i].wdev; + + wdev->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(macptr); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx Mode = %d\n", i, + wdev->DesiredTransmitSetting.field.FixedTxMode)); + } + } + + /* ApCliTxMcs*/ + if (RTMPGetKeyParameter("ApCliTxMcs", tmpbuf, 50, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->ApCfg.ApCliTab[i].wdev; + + wdev->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(macptr, &wdev->bAutoTxRateSwitch); + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx MCS = %s(%d)\n", i, + (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO ? "AUTO" : ""), + wdev->DesiredTransmitSetting.field.MCS)); + } + } + + +#ifdef WSC_AP_SUPPORT + + /* Wsc4digitPinCode = TRUE use 4-digit Pin code, otherwise 8-digit Pin code */ + if (RTMPGetKeyParameter("ApCli_Wsc4digitPinCode", tmpbuf, 32, buffer, TRUE)) + { + if (simple_strtol(macptr, 0, 10) != 0) //Enable + pAd->ApCfg.ApCliTab[0].WscControl.WscEnrollee4digitPinCode = TRUE; + else //Disable + pAd->ApCfg.ApCliTab[0].WscControl.WscEnrollee4digitPinCode = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCli_Wsc4digitPinCode=%d\n", i, pAd->ApCfg.ApCliTab[0].WscControl.WscEnrollee4digitPinCode)); + } +#endif /* WSC_AP_SUPPORT */ + + +#ifdef UAPSD_SUPPORT + /*APSDCapable*/ + if(RTMPGetKeyParameter("ApCliAPSDCapable", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.FlgApCliIsUapsdInfoUpdated = TRUE; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); + (macptr && i < MAX_APCLI_NUM); + macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + pApCliEntry->UapsdInfo.bAPSDCapable = \ + (UCHAR) simple_strtol(macptr, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliAPSDCapable[%d]=%d\n", i, + pApCliEntry->UapsdInfo.bAPSDCapable)); + } + } +#endif /* UAPSD_SUPPORT */ + + /* ApCliNum */ + if(RTMPGetKeyParameter("ApCliNum", tmpbuf, 10, buffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) <= MAX_APCLI_NUM) + { + pAd->ApCfg.ApCliNum = simple_strtol(tmpbuf, 0, 10); + } + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli) ApCliNum=%d\n", pAd->ApCfg.ApCliNum)); + } +} +#endif /* APCLI_SUPPORT */ + + +static void rtmp_read_acl_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer) +{ + STRING tok_str[32]; + PSTRING macptr; + INT i=0, j=0, idx; + UCHAR macAddress[MAC_ADDR_LEN]; + + + memset(macAddress, 0, MAC_ADDR_LEN); + for (idx=0; idxApCfg.MBSSID[idx].AccessControlList, 0, sizeof(RT_802_11_ACL)); + /* AccessPolicyX*/ + snprintf(tok_str, sizeof(tok_str), "AccessPolicy%d", idx); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 10, buffer, TRUE)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: /* Allow All, and the AccessControlList is positive now.*/ + pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 1; + break; + case 2: /* Reject All, and the AccessControlList is negative now.*/ + pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 2; + break; + case 0: /* Disable, don't care the AccessControlList.*/ + default: + pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s=%ld\n", tok_str, pAd->ApCfg.MBSSID[idx].AccessControlList.Policy)); + } + /* AccessControlListX*/ + snprintf(tok_str, sizeof(tok_str), "AccessControlList%d", idx); + if (RTMPGetKeyParameter(tok_str, tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (strlen(macptr) != 17) /* Mac address acceptable format 01:02:03:04:05:06 length 17*/ + continue; + + ASSERT(pAd->ApCfg.MBSSID[idx].AccessControlList.Num <= MAX_NUM_OF_ACL_LIST); + + for (j=0; jApCfg.MBSSID[idx].AccessControlList.Num == MAX_NUM_OF_ACL_LIST) + { + DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n")); + DBGPRINT(RT_DEBUG_WARN, ("The last entry of ACL is %02x:%02x:%02x:%02x:%02x:%02x\n", + macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5])); + + break; + } + + pAd->ApCfg.MBSSID[idx].AccessControlList.Num++; + NdisMoveMemory(pAd->ApCfg.MBSSID[idx].AccessControlList.Entry[(pAd->ApCfg.MBSSID[idx].AccessControlList.Num - 1)].Addr, macAddress, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s=Get %ld Mac Address\n", tok_str, pAd->ApCfg.MBSSID[idx].AccessControlList.Num)); + } + } +} + +/* + ======================================================================== + + Routine Description: + In kernel mode read parameters from file + + Arguments: + src the location of the file. + dest put the parameters to the destination. + Length size to read. + + Return Value: + None + + Note: + + ======================================================================== +*/ +static void rtmp_read_ap_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer) +{ + PSTRING macptr; + INT i=0; + + /*WmmCapable*/ + if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer, TRUE)) + { + BOOLEAN bEnableWmm = FALSE; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + { + break; + } + + if(simple_strtol(macptr, 0, 10) != 0) + { + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable = TRUE; + bEnableWmm = TRUE; +#ifdef MULTI_CLIENT_SUPPORT + pAd->CommonCfg.bWmm = TRUE; +#endif /* MULTI_CLIENT_SUPPORT */ + } + else + { + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable = FALSE; + } + + if (bEnableWmm) + { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->ApCfg.BssEdcaParm.bValid = TRUE; + } + else + { + pAd->CommonCfg.APEdcaParm.bValid = FALSE; + pAd->ApCfg.BssEdcaParm.bValid = FALSE; + } + + pAd->ApCfg.MBSSID[i].bWmmCapableOrg = \ + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WmmCapable=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.bWmmCapable)); + } + } + /*DLSCapable*/ + if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + { + break; + } + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + { + pAd->ApCfg.MBSSID[i].bDLSCapable = TRUE; + } + else /*Disable*/ + { + pAd->ApCfg.MBSSID[i].bDLSCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DLSCapable=%d\n", i, pAd->ApCfg.MBSSID[i].bDLSCapable)); + } + } + /*APAifsn*/ + if(RTMPGetKeyParameter("APAifsn", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.Aifsn[i] = (UCHAR) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("APAifsn[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Aifsn[i])); + } + } + /*APCwmin*/ + if(RTMPGetKeyParameter("APCwmin", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.Cwmin[i] = (UCHAR) simple_strtol(macptr, 0, 10); + +#ifdef MULTI_CLIENT_SUPPORT + /* record profile cwmin */ + if (i == 0) + pAd->CommonCfg.APCwmin = pAd->CommonCfg.APEdcaParm.Cwmin[0]; +#endif /* MULTI_CLIENT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("APCwmin[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Cwmin[i])); + } + } + /*APCwmax*/ + if(RTMPGetKeyParameter("APCwmax", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.Cwmax[i] = (UCHAR) simple_strtol(macptr, 0, 10); + +#ifdef MULTI_CLIENT_SUPPORT + /* record profile cwmax */ + if (i == 0) + pAd->CommonCfg.APCwmax= pAd->CommonCfg.APEdcaParm.Cwmax[0]; +#endif /* MULTI_CLIENT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("APCwmax[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Cwmax[i])); + } + } + /*APTxop*/ + if(RTMPGetKeyParameter("APTxop", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.Txop[i] = (USHORT) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("APTxop[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Txop[i])); + } + } + /*APACM*/ + if(RTMPGetKeyParameter("APACM", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.bACM[i] = (BOOLEAN) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("APACM[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.bACM[i])); + } + } + /*BSSAifsn*/ + if(RTMPGetKeyParameter("BSSAifsn", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.BssEdcaParm.Aifsn[i] = (UCHAR) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("BSSAifsn[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Aifsn[i])); + } + } + /*BSSCwmin*/ + if(RTMPGetKeyParameter("BSSCwmin", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.BssEdcaParm.Cwmin[i] = (UCHAR) simple_strtol(macptr, 0, 10); + +#ifdef MULTI_CLIENT_SUPPORT + /* record profile cwmin */ + if (i == 0) + pAd->CommonCfg.BSSCwmin = pAd->ApCfg.BssEdcaParm.Cwmin[0]; +#endif /* MULTI_CLIENT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("BSSCwmin[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Cwmin[i])); + } + } + /*BSSCwmax*/ + if(RTMPGetKeyParameter("BSSCwmax", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.BssEdcaParm.Cwmax[i] = (UCHAR) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("BSSCwmax[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Cwmax[i])); + } + } + /*BSSTxop*/ + if(RTMPGetKeyParameter("BSSTxop", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.BssEdcaParm.Txop[i] = (USHORT) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("BSSTxop[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Txop[i])); + } + } + /*BSSACM*/ + if(RTMPGetKeyParameter("BSSACM", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.BssEdcaParm.bACM[i] = (BOOLEAN) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("BSSACM[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.bACM[i])); + } + } + /*AckPolicy*/ + if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.AckPolicy[i] = (UCHAR) simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i])); + } + } +#ifdef UAPSD_SUPPORT + /*APSDCapable*/ + if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer, TRUE)) + { + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i < HW_BEACON_MAX_NUM) + { + pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable = \ + (UCHAR) simple_strtol(macptr, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable[%d]=%d\n", i, + pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable)); + } + } + + if (i == 1) + { + /* + Old format in UAPSD settings: only 1 parameter + i.e. UAPSD for all BSS is enabled or disabled. + */ + for(i=1; iApCfg.MBSSID[i].UapsdInfo.bAPSDCapable = + pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable; + DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable[%d]=%d\n", i, + pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable)); + } + } + +#ifdef APCLI_SUPPORT + if (pAd->ApCfg.FlgApCliIsUapsdInfoUpdated == FALSE) + { + /* + Backward: + All UAPSD for AP Client interface is same as MBSS0 + when we can not find "ApCliAPSDCapable". + When we find "ApCliAPSDCapable" hereafter, we will over-write. + */ + for(i=0; iApCfg.ApCliTab[i].UapsdInfo.bAPSDCapable = \ + pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable; + DBGPRINT(RT_DEBUG_TRACE, ("default ApCliAPSDCapable[%d]=%d\n", + i, pAd->ApCfg.ApCliTab[i].UapsdInfo.bAPSDCapable)); + } + } +#endif /* APCLI_SUPPORT */ + } +#endif /* UAPSD_SUPPORT */ +} + +#ifdef DOT1X_SUPPORT +/* + ======================================================================== + + Routine Description: + In kernel mode read parameters from file + + Arguments: + src the location of the file. + dest put the parameters to the destination. + Length size to read. + + Return Value: + None + + Note: + + ======================================================================== +*/ +static void rtmp_read_radius_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer) +{ + STRING tok_str[16]; + PSTRING macptr; + UINT32 ip_addr; + INT i=0; + BOOLEAN bUsePrevFormat = FALSE; + USHORT offset; + INT count[HW_BEACON_MAX_NUM]; + + /* own_ip_addr*/ + if (RTMPGetKeyParameter("own_ip_addr", tmpbuf, 32, buffer, TRUE)) + { + Set_OwnIPAddr_Proc(pAd, tmpbuf); + } + + + /* session_timeout_interval*/ + if (RTMPGetKeyParameter("session_timeout_interval", tmpbuf, 32, buffer, TRUE)) + { + pAd->ApCfg.session_timeout_interval = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("session_timeout_interval=%d\n", pAd->ApCfg.session_timeout_interval)); + } + + /* quiet_interval*/ + if (RTMPGetKeyParameter("quiet_interval", tmpbuf, 32, buffer, TRUE)) + { + pAd->ApCfg.quiet_interval = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("quiet_interval=%d\n", pAd->ApCfg.quiet_interval)); + } + + /* EAPifname*/ + if (RTMPGetKeyParameter("EAPifname", tmpbuf, 256, buffer, TRUE)) + { + Set_EAPIfName_Proc(pAd, tmpbuf); + } + + /* PreAuthifname*/ + if (RTMPGetKeyParameter("PreAuthifname", tmpbuf, 256, buffer, TRUE)) + { + Set_PreAuthIfName_Proc(pAd, tmpbuf); + } + + /*PreAuth*/ + if(RTMPGetKeyParameter("PreAuth", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->ApCfg.MBSSID[i].PreAuth = TRUE; + else /*Disable*/ + pAd->ApCfg.MBSSID[i].PreAuth = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PreAuth=%d\n", i, pAd->ApCfg.MBSSID[i].PreAuth)); + } + } + + /*IEEE8021X*/ + if(RTMPGetKeyParameter("IEEE8021X", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->ApCfg.MBSSID[i].wdev.IEEE8021X = TRUE; + else /*Disable*/ + pAd->ApCfg.MBSSID[i].wdev.IEEE8021X = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), IEEE8021X=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.IEEE8021X)); + } + } + + /* RADIUS_Server*/ + offset = 0; + /*if (RTMPGetKeyParameter("RADIUS_Server", tmpbuf, 256, buffer, TRUE))*/ + while (RTMPGetKeyParameterWithOffset("RADIUS_Server", tmpbuf, &offset, 256, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (rtinet_aton(macptr, &ip_addr) && pAd->ApCfg.MBSSID[i].radius_srv_num < MAX_RADIUS_SRV_NUM) + { + INT srv_idx = pAd->ApCfg.MBSSID[i].radius_srv_num; + + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_ip = ip_addr; + pAd->ApCfg.MBSSID[i].radius_srv_num++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_ip(seq-%d)=%s(%x)\n", i, pAd->ApCfg.MBSSID[i].radius_srv_num, macptr, pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_ip)); + } + } + } + /* RADIUS_Port*/ + /*if (RTMPGetKeyParameter("RADIUS_Port", tmpbuf, 128, buffer, TRUE))*/ + offset = 0; + memset(&count[0], 0, sizeof(count)); + while (RTMPGetKeyParameterWithOffset("RADIUS_Port", tmpbuf, &offset, 128, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (count[i] < pAd->ApCfg.MBSSID[i].radius_srv_num) + { + INT srv_idx = count[i]; + + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_port = (UINT32) simple_strtol(macptr, 0, 10); + count[i] ++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_port(seq-%d)=%d\n", i, count[i], pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_port)); + } + } + } + /* RADIUS_Key*/ + /*if (RTMPGetKeyParameter("RADIUS_Key", tmpbuf, 640, buffer, FALSE))*/ + offset = 0; + memset(&count[0], 0, sizeof(count)); + while (RTMPGetKeyParameterWithOffset("RADIUS_Key", tmpbuf, &offset, 640, buffer, FALSE)) + { + if (strlen(tmpbuf) > 0) + bUsePrevFormat = TRUE; + + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (strlen(macptr) > 0 && (count[i] < pAd->ApCfg.MBSSID[i].radius_srv_num)) + { + INT srv_idx = count[i]; + + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len = strlen(macptr); + NdisMoveMemory(pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key, macptr, strlen(macptr)); + count[i] ++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_key(seq-%d)=%s, len=%d\n", i, + count[i], + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key, + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len)); + } + } + } + + /* NasIdX, X indicate the interface index(1~8) */ + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "NasId%d", i + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 33, buffer, FALSE)) + { + if (strlen(tmpbuf) > 0) + { + pAd->ApCfg.MBSSID[i].NasIdLen = strlen(tmpbuf); + NdisMoveMemory(pAd->ApCfg.MBSSID[i].NasId, tmpbuf, strlen(tmpbuf)); + DBGPRINT(RT_DEBUG_TRACE, ("IF-ra%d NAS-ID=%s, len=%d\n", i, + pAd->ApCfg.MBSSID[i].NasId, + pAd->ApCfg.MBSSID[i].NasIdLen)); + } + } + } + + if (!bUsePrevFormat) + { + for (i = 0; i < MAX_MBSSID_NUM(pAd); i++) + { + INT srv_idx = 0; + + snprintf(tok_str, sizeof(tok_str), "RADIUS_Key%d", i + 1); + + /* RADIUS_KeyX (X=1~MAX_MBSSID_NUM)*/ + /*if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) */ + offset = 0; + while (RTMPGetKeyParameterWithOffset(tok_str, tmpbuf, &offset, 128, buffer, FALSE)) + { + if (strlen(tmpbuf) > 0 && (srv_idx < pAd->ApCfg.MBSSID[i].radius_srv_num)) + { + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len = strlen(tmpbuf); + NdisMoveMemory(pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key, tmpbuf, strlen(tmpbuf)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), update radius_key(seq-%d)=%s, len=%d\n", i, srv_idx+1, + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key, + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len)); + srv_idx ++; + } + } + } + } +} +#endif /* DOT1X_SUPPORT */ + +static int rtmp_parse_wpapsk_buffer_from_file(IN PRTMP_ADAPTER pAd,IN PSTRING buffer,IN INT BSSIdx) +{ + PSTRING tmpbuf = buffer; + INT i = BSSIdx; + /*UCHAR keyMaterial[40];*/ + ULONG len = strlen(tmpbuf); + int ret = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WPAPSK_KEY=%s\n", i, tmpbuf)); + + ret = RT_CfgSetWPAPSKKey(pAd, tmpbuf, len, (PUCHAR)pAd->ApCfg.MBSSID[i].Ssid, pAd->ApCfg.MBSSID[i].SsidLen, pAd->ApCfg.MBSSID[i].PMK); + if (ret == FALSE) + return FALSE; + + /* Keep this key string */ + strcpy(pAd->ApCfg.MBSSID[i].WPAKeyString, tmpbuf); + +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pAd->ApCfg.MBSSID[i].WscControl.WpaPsk, 64); + pAd->ApCfg.MBSSID[i].WscControl.WpaPskLen = 0; + if ((len >= 8) && (len <= 64)) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[i].WscControl.WpaPsk, tmpbuf, len); + pAd->ApCfg.MBSSID[i].WscControl.WpaPskLen = len; + } +#endif /* WSC_AP_SUPPORT */ + return ret; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +static void rtmp_read_sta_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + PSTRING macptr; + INT i=0; + BOOLEAN bWmmEnable = FALSE; + + /*WmmCapable*/ + if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + { + pAd->CommonCfg.bWmmCapable = TRUE; + bWmmEnable = TRUE; + } + else /*Disable*/ + { + pAd->CommonCfg.bWmmCapable = FALSE; + } + + pAd->StaCfg.wdev.bWmmCapable = pAd->CommonCfg.bWmmCapable; + + DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable)); + } + +#ifdef QOS_DLS_SUPPORT + /*DLSCapable*/ + if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + { + pAd->CommonCfg.bDLSCapable = TRUE; + } + else /*Disable*/ + { + pAd->CommonCfg.bDLSCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("bDLSCapable=%d\n", pAd->CommonCfg.bDLSCapable)); + } +#endif /* QOS_DLS_SUPPORT */ + + /*AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO*/ + if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i])); + } + } + +#ifdef UAPSD_SUPPORT + if (bWmmEnable) + { + /*APSDCapable*/ + if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + pAd->StaCfg.UapsdInfo.bAPSDCapable = TRUE; + else + pAd->StaCfg.UapsdInfo.bAPSDCapable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->StaCfg.UapsdInfo.bAPSDCapable)); + } + + /*MaxSPLength*/ + if(RTMPGetKeyParameter("MaxSPLength", tmpbuf, 10, buffer, TRUE)) + { + pAd->CommonCfg.MaxSPLength = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("MaxSPLength=%d\n", pAd->CommonCfg.MaxSPLength)); + } + + /*APSDAC for AC_BE, AC_BK, AC_VI, AC_VO*/ + if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer, TRUE)) + { + BOOLEAN apsd_ac[4]; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d %d\n", i, apsd_ac[i])); + } + + pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0]; + pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1]; + pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2]; + pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3]; + + pAd->CommonCfg.bACMAPSDTr[0] = apsd_ac[0]; + pAd->CommonCfg.bACMAPSDTr[1] = apsd_ac[1]; + pAd->CommonCfg.bACMAPSDTr[2] = apsd_ac[2]; + pAd->CommonCfg.bACMAPSDTr[3] = apsd_ac[3]; + } + } +#endif /* UAPSD_SUPPORT */ +} + +#ifdef XLINK_SUPPORT +static void rtmp_get_psp_xlink_mode_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + /* Xlink Mode*/ + if (RTMPGetKeyParameter("PSP_XLINK_MODE", tmpbuf, 32, buffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /* enable*/ + pAd->StaCfg.PSPXlink = TRUE; + else /* disable*/ + pAd->StaCfg.PSPXlink = FALSE; + + AsicSetRxFilter(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("PSP_XLINK_MODE=%d\n", pAd->StaCfg.PSPXlink)); + } +} +#endif /* XLINK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef DOT11_VHT_AC +static void VHTParametersHook( + IN RTMP_ADAPTER *pAd, + IN PSTRING pValueStr, + IN PSTRING pInput) +{ + long Value; + + /* Channel Width */ + if (RTMPGetKeyParameter("VHT_BW", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == VHT_BW_80) + pAd->CommonCfg.vht_bw = VHT_BW_80; + else + pAd->CommonCfg.vht_bw = VHT_BW_2040; + +#ifdef MCAST_RATE_SPECIFIC + if (pAd->CommonCfg.vht_bw == VHT_BW_80) + pAd->CommonCfg.MCastPhyMode.field.BW = BW_80; +#endif /* MCAST_RATE_SPECIFIC */ + + DBGPRINT(RT_DEBUG_TRACE, ("VHT: Channel Width = %s\n", + (pAd->CommonCfg.vht_bw == VHT_BW_80) ? "80 MHz" : "20/40 MHz" )); + } + + /* VHT GI setting */ + if (RTMPGetKeyParameter("VHT_SGI", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == GI_800) + pAd->CommonCfg.vht_sgi_80 = GI_800; + else + pAd->CommonCfg.vht_sgi_80 = GI_400; + + DBGPRINT(RT_DEBUG_TRACE, ("VHT: Short GI for 80Mhz = %s\n", + (pAd->CommonCfg.vht_sgi_80==GI_800) ? "Disabled" : "Enable" )); + } + + /* VHT STBC */ + if (RTMPGetKeyParameter("VHT_STBC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + pAd->CommonCfg.vht_stbc = (Value == 1 ? STBC_USE : STBC_NONE); + DBGPRINT(RT_DEBUG_TRACE, ("VHT: STBC = %d\n", + pAd->CommonCfg.vht_stbc)); + } + + /* bandwidth signaling */ + if (RTMPGetKeyParameter("VHT_BW_SIGNAL", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 0 && Value <= 2) + pAd->CommonCfg.vht_bw_signal = Value; + else + pAd->CommonCfg.vht_bw_signal = BW_SIGNALING_DISABLE; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: BW SIGNALING = %d\n", pAd->CommonCfg.vht_bw_signal)); + } + + /* Disallow non-VHT connection */ + if (RTMPGetKeyParameter("VHT_DisallowNonVHT", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bNonVhtDisallow = FALSE; + else + pAd->CommonCfg.bNonVhtDisallow = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: VHT_DisallowNonVHT = %d\n", pAd->CommonCfg.bNonVhtDisallow)); + } + + /* VHT LDPC */ + if (RTMPGetKeyParameter("VHT_LDPC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.vht_ldpc = FALSE; + else + pAd->CommonCfg.vht_ldpc = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: VHT_LDPC = %d\n", pAd->CommonCfg.vht_ldpc)); + } + +#ifdef WFA_VHT_PF + /* VHT highest Tx Rate with LGI */ + if (RTMPGetKeyParameter("VHT_TX_HRATE", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 0 && Value <= 2) + pAd->CommonCfg.vht_tx_hrate = Value; + else + pAd->CommonCfg.vht_tx_hrate = 0; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: TX HighestRate = %d\n", pAd->CommonCfg.vht_tx_hrate)); + } + + if (RTMPGetKeyParameter("VHT_RX_HRATE", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 0 && Value <= 2) + pAd->CommonCfg.vht_rx_hrate = Value; + else + pAd->CommonCfg.vht_rx_hrate = 0; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: RX HighestRate = %d\n", pAd->CommonCfg.vht_rx_hrate)); + } + + if (RTMPGetKeyParameter("VHT_MCS_CAP", pValueStr, 25, pInput, TRUE)) + set_vht_nss_mcs_cap(pAd, pValueStr); +#endif /* WFA_VHT_PF */ + +} + +#endif /* DOT11_VHT_AC */ + + +#ifdef DOT11_N_SUPPORT +static void HTParametersHook( + IN PRTMP_ADAPTER pAd, + IN PSTRING pValueStr, + IN PSTRING pInput) +{ + long Value; +#ifdef CONFIG_AP_SUPPORT + INT i=0; + PSTRING Bufptr; +#endif /* CONFIG_AP_SUPPORT */ + + if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bHTProtect = FALSE; + } + else + { + pAd->CommonCfg.bHTProtect = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value > MMPS_DISABLE) + { + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_DISABLE; + } + else + { + /*TODO: add mimo power saving mechanism*/ + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_DISABLE; + /*pAd->CommonCfg.BACapability.field.MMPSmode = Value;*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", (INT) Value)); + } + + if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else + { + pAd->CommonCfg.bBADecline = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + } + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; + DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + /* Tx_+HTC frame*/ + if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->HTCEnable = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + /* Reverse Direction Mechanism*/ + if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bRdg = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + pAd->CommonCfg.bRdg = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); + } + + + + + /* Tx A-MSUD ?*/ + if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + pAd->CommonCfg.BACapability.field.AmsduEnable = (Value == 0) ? FALSE : TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } + +#ifdef WFA_VHT_PF + if (RTMPGetKeyParameter("FORCE_AMSDU", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + pAd->force_amsdu = (Value == 0) ? FALSE : TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: FORCE A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } +#endif /* WFA_VHT_PF */ + + /* MPDU Density*/ + if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value <=7 && Value >= 0) + { + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", (INT) Value)); + } + else + { + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4)); + } + } + + /* Max Rx BA Window Size*/ + if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + +#ifdef CONFIG_AP_SUPPORT + /* Intel IOT*/ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + Value = 64; +#endif /* CONFIG_AP_SUPPORT */ + if (Value >=1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", (INT) Value)); + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n")); + } + + } + + /* Guard Interval*/ + if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == GI_400) + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" )); + } + + /* HT LDPC */ + if (RTMPGetKeyParameter("HT_LDPC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.ht_ldpc = FALSE; + else + pAd->CommonCfg.ht_ldpc = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: HT_LDPC = %d\n", pAd->CommonCfg.ht_ldpc)); + } + + /* HT Operation Mode : Mixed Mode , Green Field*/ + if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == HTMODE_GF) + { + + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" )); + } + + /* Fixed Tx mode : CCK, OFDM*/ + if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, Bufptr = rstrtok(pValueStr,";"); (Bufptr && i < MAX_MBSSID_NUM(pAd)); Bufptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.MBSSID[i].wdev.DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(Bufptr); + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) Fixed Tx Mode = %d\n", i, + pAd->ApCfg.MBSSID[i].wdev.DesiredTransmitSetting.field.FixedTxMode)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(pValueStr); + DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", + pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode)); + } +#endif /* CONFIG_STA_SUPPORT */ + } + + + /* Channel Width */ + if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == BW_40) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + else + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + +#ifdef DOT11N_DRAFT3 + if (Value == BW_40) + pAd->CommonCfg.ori_bw_before_2040_coex = BW_40; + else + pAd->CommonCfg.ori_bw_before_2040_coex = BW_20; +#endif /* DOT11N_DRAFT3 */ + +#ifdef MCAST_RATE_SPECIFIC + pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; +#endif /* MCAST_RATE_SPECIFIC */ + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" )); + } + + if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + else + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + +#ifdef DOT11N_DRAFT3 + if (Value == 0) + pAd->CommonCfg.ori_ext_channel_before_2040_coex = EXTCHA_BELOW; + else + pAd->CommonCfg.ori_ext_channel_before_2040_coex = EXTCHA_ABOVE; +#endif /* DOT11N_DRAFT3 */ + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" )); + } + + /* MSC*/ + if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, Bufptr = rstrtok(pValueStr,";"); (Bufptr && i < MAX_MBSSID_NUM(pAd)); Bufptr = rstrtok(NULL,";"), i++) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[i].wdev; + Value = simple_strtol(Bufptr, 0, 10); + if ((Value >= 0 && Value <= 23) || (Value == 32)) + wdev->DesiredTransmitSetting.field.MCS = Value; + else + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) HT: MCS = %s(%d)\n", i, + (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO ? "AUTO" : "Fixed"), + wdev->DesiredTransmitSetting.field.MCS)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + Value = simple_strtol(pValueStr, 0, 10); + if ((Value >= 0 && Value <= 23) || (Value == 32)) + { + wdev->DesiredTransmitSetting.field.MCS = Value; + wdev->bAutoTxRateSwitch = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", wdev->DesiredTransmitSetting.field.MCS)); + } + else + { + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + wdev->bAutoTxRateSwitch = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n")); + } + } +#endif /* CONFIG_STA_SUPPORT */ + } + + /* STBC */ + if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == STBC_USE) + { + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC)); + } + +#ifdef DOT11N_DRAFT3 + /* 40_Mhz_Intolerant*/ + if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE; + } + else + { + pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant)); + } +#endif /* DOT11N_DRAFT3 */ + + /*HT_TxStream*/ + if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput, TRUE)) + { + switch (simple_strtol(pValueStr, 0, 10)) + { + case 1: + pAd->CommonCfg.TxStream = 1; + break; + case 2: + pAd->CommonCfg.TxStream = 2; + break; + case 3: /* 3*3*/ + default: + pAd->CommonCfg.TxStream = 3; + + if (pAd->MACVersion < RALINK_2883_VERSION) + pAd->CommonCfg.TxStream = 2; /* only 2 tx streams for RT2860 series*/ + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream)); + } + /*HT_RxStream*/ + if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput, TRUE)) + { + switch (simple_strtol(pValueStr, 0, 10)) + { + case 1: + pAd->CommonCfg.RxStream = 1; + break; + case 2: + pAd->CommonCfg.RxStream = 2; + break; + case 3: + default: + pAd->CommonCfg.RxStream = 3; + + if (pAd->MACVersion < RALINK_2883_VERSION) + pAd->CommonCfg.RxStream = 2; /* only 2 rx streams for RT2860 series*/ + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream)); + } +#ifdef GREENAP_SUPPORT + /*Green AP*/ + if(RTMPGetKeyParameter("GreenAP", pValueStr, 10, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->ApCfg.bGreenAPEnable = FALSE; + } + else + { + pAd->ApCfg.bGreenAPEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Green AP= %d\n", pAd->ApCfg.bGreenAPEnable)); + } +#endif /* GREENAP_SUPPORT */ + /* HT_DisallowTKIP*/ + if (RTMPGetKeyParameter("HT_DisallowTKIP", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 1) + { + pAd->CommonCfg.HT_DisallowTKIP = TRUE; + } + else + { + pAd->CommonCfg.HT_DisallowTKIP = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Disallow TKIP mode = %s\n", (pAd->CommonCfg.HT_DisallowTKIP == TRUE) ? "ON" : "OFF" )); + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (RTMPGetKeyParameter("OBSSScanParam", pValueStr, 32, pInput, TRUE)) + { + int ObssScanValue, idx; + PSTRING macptr; + for (idx = 0, macptr = rstrtok(pValueStr,";"); macptr; macptr = rstrtok(NULL,";"), idx++) + { + ObssScanValue = simple_strtol(macptr, 0, 10); + switch (idx) + { + case 0: + if (ObssScanValue < 5 || ObssScanValue > 1000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanPassiveDwell(%d), should in range 5~1000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanPassiveDwell = ObssScanValue; /* Unit : TU. 5~1000*/ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanPassiveDwell=%d\n", ObssScanValue)); + } + break; + case 1: + if (ObssScanValue < 10 || ObssScanValue > 1000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanActiveDwell(%d), should in range 10~1000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanActiveDwell = ObssScanValue; /* Unit : TU. 10~1000*/ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanActiveDwell=%d\n", ObssScanValue)); + } + break; + case 2: + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = ObssScanValue; /* Unit : Second*/ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthTriggerScanInt=%d\n", ObssScanValue)); + break; + case 3: + if (ObssScanValue < 200 || ObssScanValue > 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanPassiveTotalPerChannel(%d), should in range 200~10000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = ObssScanValue; /* Unit : TU. 200~10000*/ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanPassiveTotalPerChannel=%d\n", ObssScanValue)); + } + break; + case 4: + if (ObssScanValue < 20 || ObssScanValue > 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanActiveTotalPerChannel(%d), should in range 20~10000\n", ObssScanValue)); + } + else + { + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = ObssScanValue; /* Unit : TU. 20~10000*/ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanActiveTotalPerChannel=%d\n", ObssScanValue)); + } + break; + case 5: + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = ObssScanValue; + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelayFactor=%d\n", ObssScanValue)); + break; + case 6: + pAd->CommonCfg.Dot11OBssScanActivityThre = ObssScanValue; /* Unit : percentage*/ + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelayFactor=%d\n", ObssScanValue)); + break; + } + } + + if (idx != 7) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong OBSSScanParamtetrs format in dat file!!!!! Use default value.\n")); + + pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; /* Unit : TU. 5~1000*/ + pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; /* Unit : TU. 10~1000*/ + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; /* Unit : Second */ + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; /* Unit : TU. 200~10000*/ + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; /* Unit : TU. 20~10000*/ + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; + pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; /* Unit : percentage*/ + } + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelay=%ld\n", pAd->CommonCfg.Dot11BssWidthChanTranDelay)); + } + + if (RTMPGetKeyParameter("HT_BSSCoexistence", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + pAd->CommonCfg.bBssCoexEnable = ((Value == 1) ? TRUE : FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("HT: 20/40 BssCoexSupport = %s\n", (pAd->CommonCfg.bBssCoexEnable == TRUE) ? "ON" : "OFF" )); + } + + + if (RTMPGetKeyParameter("HT_BSSCoexApCntThr", pValueStr, 25, pInput, TRUE)) + { + pAd->CommonCfg.BssCoexApCntThr = simple_strtol(pValueStr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("HT: 20/40 BssCoexApCntThr = %d\n", pAd->CommonCfg.BssCoexApCntThr)); + } + +#endif /* DOT11N_DRAFT3 */ + + if (RTMPGetKeyParameter("BurstMode", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + pAd->CommonCfg.bRalinkBurstMode = ((Value == 1) ? 1 : 0); + DBGPRINT(RT_DEBUG_TRACE, ("HT: RaBurstMode= %d\n", pAd->CommonCfg.bRalinkBurstMode)); + } +#endif /* DOT11_N_SUPPORT */ + +} +#endif /* DOT11_N_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +void RTMPSetSTASSID(RTMP_ADAPTER *pAd, PSTRING SSID) +{ + pAd->CommonCfg.SsidLen = (UCHAR) strlen(SSID); + NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->CommonCfg.Ssid, SSID, pAd->CommonCfg.SsidLen); + pAd->CommonCfg.LastSsidLen= pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->CommonCfg.LastSsid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->CommonCfg.LastSsid, SSID, pAd->CommonCfg.LastSsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, SSID, pAd->MlmeAux.AutoReconnectSsidLen); + pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, SSID, pAd->MlmeAux.SsidLen); +} + + +void RTMPSetSTAPassPhrase(RTMP_ADAPTER *pAd, PSTRING PassPh) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + int ret = TRUE; + + PassPh[strlen(PassPh)] = '\0'; /* make STA can process .$^& for WPAPSK input */ + + if ((wdev->AuthMode != Ndis802_11AuthModeWPAPSK) && + (wdev->AuthMode != Ndis802_11AuthModeWPA2PSK) && + (wdev->AuthMode != Ndis802_11AuthModeWPANone) +#ifdef WAPI_SUPPORT + && (wdev->AuthMode != Ndis802_11AuthModeWAICERT) + && (wdev->AuthMode != Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) + { + ret = FALSE; + } + else + { + ret = RT_CfgSetWPAPSKKey(pAd, PassPh, strlen(PassPh), (PUCHAR)pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->StaCfg.PMK); + } + + if (ret == TRUE) + { + RTMPZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + RTMPMoveMemory(pAd->StaCfg.WpaPassPhrase, PassPh, strlen(PassPh)); + pAd->StaCfg.WpaPassPhraseLen= strlen(PassPh); + + if ((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + /* Start STA supplicant state machine*/ + pAd->StaCfg.WpaState = SS_START; + } + else if (wdev->AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->StaCfg.WpaState = SS_NOTUSE; + } +#ifdef WSC_STA_SUPPORT + NdisZeroMemory(pAd->StaCfg.WscControl.WpaPsk, 64); + pAd->StaCfg.WscControl.WpaPskLen = 0; + if ((strlen(PassPh) >= 8) && (strlen(PassPh) <= 64)) + { + NdisMoveMemory(pAd->StaCfg.WscControl.WpaPsk, PassPh, strlen(PassPh)); + pAd->StaCfg.WscControl.WpaPskLen = strlen(PassPh); + } +#endif /* WSC_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __FUNCTION__, PassPh)); + } +} + + +inline void RTMPSetSTACipherSuites(RTMP_ADAPTER *pAd, NDIS_802_11_ENCRYPTION_STATUS WepStatus) +{ + /* Update all wepstatus related*/ + pAd->StaCfg.PairCipher = WepStatus; + pAd->StaCfg.GroupCipher = WepStatus; + pAd->StaCfg.bMixCipher = FALSE; +} + +#ifdef CREDENTIAL_STORE + +/*RECOVER THE OLD CONNECT INFO */ +NDIS_STATUS RecoverConnectInfo( + IN RTMP_ADAPTER *pAd) +{ + INT idx; + char ssidStr[NDIS_802_11_LENGTH_SSID + 1]; + + NdisZeroMemory(&ssidStr[0], sizeof(ssidStr)); + + RTMP_SEM_LOCK(&pAd->StaCtIf.Lock); + if ((pAd->StaCtIf.Changeable== FALSE) || (pAd->StaCtIf.SsidLen > NDIS_802_11_LENGTH_SSID)) + { + DBGPRINT(RT_DEBUG_TRACE, (" DRIVER INIT not need to RecoverConnectInfo() \n")); + RTMP_SEM_UNLOCK(&pAd->StaCtIf.Lock); + return 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("-->RecoverConnectInfo()\n")); + + NdisMoveMemory(ssidStr, pAd->StaCtIf.Ssid, pAd->StaCtIf.SsidLen); + RTMPSetSTASSID(pAd, &ssidStr[0]); + + pAd->StaCfg.AuthMode = pAd->StaCtIf.AuthMode; + pAd->StaCfg.WepStatus = pAd->StaCtIf.WepStatus; +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.wdev.IEEE8021X = pAd->StaCtIf.IEEE8021X; + pAd->StaCfg.wpa_supplicant_info.DesireSharedKeyId = pAd->StaCtIf.DefaultKeyId; +#endif // WPA_SUPPLICANT_SUPPORT // + pAd->StaCfg.DefaultKeyId = pAd->StaCtIf.DefaultKeyId; + NdisMoveMemory( pAd->StaCfg.PMK, pAd->StaCtIf.PMK, 32); + RTMPMoveMemory(pAd->StaCfg.WpaPassPhrase, pAd->StaCtIf.WpaPassPhrase, pAd->StaCfg.WpaPassPhraseLen); + pAd->StaCfg.WpaPassPhraseLen = pAd->StaCtIf.WpaPassPhraseLen; + for (idx = 0; idx < 4; idx++) + { + NdisMoveMemory(&pAd->SharedKey[BSS0][idx], &pAd->StaCtIf.SharedKey[BSS0][idx], sizeof(CIPHER_KEY)); +#ifdef WPA_SUPPLICANT_SUPPORT + NdisMoveMemory(&pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx], &pAd->StaCtIf.SharedKey[BSS0][idx], sizeof(CIPHER_KEY)); +#endif // WPA_SUPPLICANT_SUPPORT // + + } + + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // Start STA supplicant state machine + pAd->StaCfg.WpaState = SS_START; + } + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->StaCfg.WpaState = SS_NOTUSE; + } + RTMP_SEM_UNLOCK(&pAd->StaCtIf.Lock); + + DBGPRINT(RT_DEBUG_TRACE, ("<--RecoverConnectInfo()\n")); + + return 0; +} + + +/*STORE THE CONNECT INFO*/ +NDIS_STATUS StoreConnectInfo( + IN RTMP_ADAPTER *pAd) +{ + INT idx; + DBGPRINT(RT_DEBUG_TRACE, ("-->StoreConnectInfo()\n")); + + RTMP_SEM_LOCK(&pAd->StaCtIf.Lock); + pAd->StaCtIf.Changeable = TRUE; + pAd->StaCtIf.SsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->StaCtIf.Ssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + pAd->StaCtIf.AuthMode = pAd->StaCfg.AuthMode; + pAd->StaCtIf.WepStatus = pAd->StaCfg.WepStatus; + + pAd->StaCtIf.DefaultKeyId = pAd->StaCfg.DefaultKeyId; +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCtIf.wpa_supplicant_info.DefaultKeyId = pAd->StaCfg.DesireSharedKeyId; + pAd->StaCtIf.IEEE8021X = pAd->StaCfg.wdev.IEEE8021X; +#endif // WPA_SUPPLICANT_SUPPORT // + NdisMoveMemory(pAd->StaCtIf.PMK, pAd->StaCfg.PMK, 32); + RTMPMoveMemory(pAd->StaCtIf.WpaPassPhrase, pAd->StaCfg.WpaPassPhrase, pAd->StaCfg.WpaPassPhraseLen); + pAd->StaCtIf.WpaPassPhraseLen = pAd->StaCfg.WpaPassPhraseLen; + + for (idx = 0; idx < 4; idx++) + { + NdisMoveMemory(&pAd->StaCtIf.SharedKey[BSS0][idx], &pAd->SharedKey[BSS0][idx], sizeof(CIPHER_KEY)); + } + + RTMP_SEM_UNLOCK(&pAd->StaCtIf.Lock); + + DBGPRINT(RT_DEBUG_TRACE, ("<--StoreConnectInfo()\n")); + + return 0; +} + +#endif /* CREDENTIAL_STORE */ + +#endif /* CONFIG_STA_SUPPORT */ + + +void RTMPSetCountryCode(RTMP_ADAPTER *pAd, PSTRING CountryCode) +{ + NdisMoveMemory(pAd->CommonCfg.CountryCode, CountryCode , 2); + pAd->CommonCfg.CountryCode[2] = ' '; +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(pAd->StaCfg.StaOriCountryCode, CountryCode , 2); +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ + if (strlen((PSTRING) pAd->CommonCfg.CountryCode) != 0) + pAd->CommonCfg.bCountryFlag = TRUE; + else + pAd->CommonCfg.bCountryFlag = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode)); +} + + +NDIS_STATUS RTMPSetProfileParameters( + IN RTMP_ADAPTER *pAd, + IN PSTRING pBuffer) +{ + PSTRING tmpbuf; + ULONG RtsThresh; + ULONG FragThresh; + PSTRING macptr; + INT i = 0, retval; + + os_alloc_mem(NULL, (UCHAR **)&tmpbuf, MAX_PARAM_BUFFER_SIZE); + if(tmpbuf == NULL) + return NDIS_STATUS_FAILURE; + + do + { + /* set file parameter to portcfg*/ + if (RTMPGetKeyParameter("MacAddress", tmpbuf, 25, pBuffer, TRUE)) + { + retval = RT_CfgSetMacAddress(pAd, tmpbuf); + if (retval) + DBGPRINT(RT_DEBUG_TRACE, ("MacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->CurrentAddress))); + } + /*CountryRegion*/ + if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, pBuffer, TRUE)) + { + retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_24G); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion)); + } + /*CountryRegionABand*/ + if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, pBuffer, TRUE)) + { + retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_5G); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand)); + } + + /* E2pAccessMode */ + if (RTMPGetKeyParameter("E2pAccessMode", tmpbuf, 25, pBuffer, TRUE)) + { + pAd->E2pAccessMode = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("E2pAccessMode=%d\n", pAd->E2pAccessMode)); + } + + /*CountryCode*/ + if (pAd->CommonCfg.bCountryFlag == 0) + { + if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, pBuffer, TRUE)) + RTMPSetCountryCode(pAd, tmpbuf); + } + +#ifdef EXT_BUILD_CHANNEL_LIST + /*ChannelGeography*/ + if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, pBuffer, TRUE)) + { + UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10); + if (Geography <= BOTH) + { + pAd->CommonCfg.Geography = Geography; + pAd->CommonCfg.CountryCode[2] = + (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.StaOriGeography = pAd->CommonCfg.Geography; +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography)); + } + } + else + { + pAd->CommonCfg.Geography = BOTH; + pAd->CommonCfg.CountryCode[2] = ' '; + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MBSS_SUPPORT + /*BSSIDNum; This must read first of other multiSSID field, so list this field first in configuration file*/ + if(RTMPGetKeyParameter("BssidNum", tmpbuf, 25, pBuffer, TRUE)) + { + pAd->ApCfg.BssidNum = (UCHAR) simple_strtol(tmpbuf, 0, 10); + if(pAd->ApCfg.BssidNum > MAX_MBSSID_NUM(pAd)) + { + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("BssidNum=%d(MAX_MBSSID_NUM is %d)\n", pAd->ApCfg.BssidNum,MAX_MBSSID_NUM(pAd))); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("BssidNum=%d\n", pAd->ApCfg.BssidNum)); + } + + if (HW_BEACON_OFFSET > (HW_BEACON_MAX_SIZE(pAd) / pAd->ApCfg.BssidNum)) + { + DBGPRINT(RT_DEBUG_OFF, ("mbss> fatal error! beacon offset is error in driver! " + "Please re-assign HW_BEACON_OFFSET!\n")); + } +#else + pAd->ApCfg.BssidNum = 1; +#endif /* MBSS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* SSID*/ + if (TRUE) + { + STRING tok_str[16]; + UCHAR BssidCountSupposed = 0; + BOOLEAN bSSIDxIsUsed = FALSE; + + //PRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum)); + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "SSID%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 33, pBuffer, FALSE)) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[i].Ssid, tmpbuf , strlen(tmpbuf)); + pAd->ApCfg.MBSSID[i].Ssid[strlen(tmpbuf)] = '\0'; + pAd->ApCfg.MBSSID[i].SsidLen = strlen((PSTRING) pAd->ApCfg.MBSSID[i].Ssid); + if (bSSIDxIsUsed == FALSE) + { + bSSIDxIsUsed = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("SSID[%d]=%s\n", i, pAd->ApCfg.MBSSID[i].Ssid)); + } + } + if (bSSIDxIsUsed == FALSE) + { + if(RTMPGetKeyParameter("SSID", tmpbuf, 256, pBuffer, FALSE)) + { + BssidCountSupposed = delimitcnt(tmpbuf, ";") + 1; + if (pAd->ApCfg.BssidNum != BssidCountSupposed) + { + DBGPRINT_ERR(("Your no. of SSIDs( = %d) does not match your BssidNum( = %d)!\n", BssidCountSupposed, pAd->ApCfg.BssidNum)); + } + if (pAd->ApCfg.BssidNum > 1) + { + /* Anyway, we still do the legacy dissection of the whole SSID string.*/ + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + int apidx = 0; + + if (i < pAd->ApCfg.BssidNum) + { + apidx = i; + } + else + { + break; + } + + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].Ssid, macptr , strlen(macptr)); + pAd->ApCfg.MBSSID[apidx].Ssid[strlen(macptr)] = '\0'; + pAd->ApCfg.MBSSID[apidx].SsidLen = strlen((PSTRING) pAd->ApCfg.MBSSID[apidx].Ssid); + + DBGPRINT(RT_DEBUG_TRACE, ("SSID[%d]=%s\n", i, pAd->ApCfg.MBSSID[apidx].Ssid)); + } + } + else + { + if ((strlen(tmpbuf) > 0) && (strlen(tmpbuf) <= 32)) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[BSS0].Ssid, tmpbuf , strlen(tmpbuf)); + pAd->ApCfg.MBSSID[BSS0].Ssid[strlen(tmpbuf)] = '\0'; + pAd->ApCfg.MBSSID[BSS0].SsidLen = strlen((PSTRING) pAd->ApCfg.MBSSID[BSS0].Ssid); + DBGPRINT(RT_DEBUG_TRACE, ("SSID=%s\n", pAd->ApCfg.MBSSID[BSS0].Ssid)); + } + } + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /*SSID*/ + if (RTMPGetKeyParameter("SSID", tmpbuf, 256, pBuffer, FALSE)) + { + if (strlen(tmpbuf) <= 32) + { + RTMPSetSTASSID(pAd, tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __FUNCTION__, tmpbuf)); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /*NetworkType*/ + if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, pBuffer, TRUE)) + { + pAd->bConfigChanged = TRUE; + if (strcmp(tmpbuf, "Adhoc") == 0) + pAd->StaCfg.BssType = BSS_ADHOC; + else /*Default Infrastructure mode*/ + pAd->StaCfg.BssType = BSS_INFRA; + /* Reset Ralink supplicant to not use, it will be set to start when UI set PMK key*/ + pAd->StaCfg.WpaState = SS_NOTUSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __FUNCTION__, pAd->StaCfg.BssType)); + } + } +#endif /* CONFIG_STA_SUPPORT */ + /*Channel*/ + if(RTMPGetKeyParameter("Channel", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel)); + if (pAd->CommonCfg.Channel > 14) + pAd->Dot11_H.org_ch = pAd->CommonCfg.Channel; + } + + /* EtherTrafficBand */ + if (RTMPGetKeyParameter("EtherTrafficBand", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.EtherTrafficBand = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("EtherTrafficBand=%d\n", pAd->CommonCfg.EtherTrafficBand)); + + if (pAd->CommonCfg.EtherTrafficBand > EtherTrafficBand5G) + pAd->CommonCfg.EtherTrafficBand = EtherTrafficBand5G; + } + + /*WirelessMode*/ + /*Note: BssidNum must be put before WirelessMode in dat file*/ + if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 32, pBuffer, TRUE)) + { + UCHAR cfg_mode; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + cfg_mode = simple_strtol(macptr, 0, 10); +#ifdef CONFIG_AP_SUPPORT + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].wdev.PhyMode = cfgmode_2_wmode(cfg_mode); + DBGPRINT(RT_DEBUG_TRACE, ("BSS%d PhyMode=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.PhyMode)); +#endif /* CONFIG_AP_SUPPORT */ + + if (i == 0) + { +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + /* for first time, update all phy mode is same as ra0 */ + { + UINT32 IdBss; + for(IdBss=1; IdBssApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].wdev.PhyMode = pAd->ApCfg.MBSSID[0].wdev.PhyMode; + } +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + /* set mode for 1st time */ + RT_CfgSetWirelessMode(pAd, macptr); + } +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + else + RT_CfgSetMbssWirelessMode(pAd, macptr); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode)); + } + + /*BasicRate*/ + if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.BasicRateBitmapOld = (ULONG) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap)); + } + /*BeaconPeriod*/ + if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, pBuffer, TRUE)) + { + USHORT bcn_val = (USHORT) simple_strtol(tmpbuf, 0, 10); + + /* The acceptable is 20~1000 ms. Refer to WiFi test plan. */ + if (bcn_val >= 20 && bcn_val <= 1000) + pAd->CommonCfg.BeaconPeriod = bcn_val; + else + pAd->CommonCfg.BeaconPeriod = 100; /* Default value*/ + +#ifdef APCLI_CONNECTION_TRIAL + pAd->CommonCfg.BeaconPeriod = 200; +#endif /* APCLI_CONNECTION_TRIAL */ + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod)); + } + +#ifdef RTMP_RBUS_SUPPORT + /*FreqOffsetDelta*/ + if (pAd->infType == RTMP_DEV_INF_RBUS) + { + if(RTMPGetKeyParameter("FreqDelta", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->RfFreqDelta = (USHORT) simple_strtol(tmpbuf, 0, 10); + + if (pAd->RfFreqDelta > 0x20) + pAd->RfFreqDelta = 0; + DBGPRINT(RT_DEBUG_TRACE, ("FreqDelta=%d\n", pAd->RfFreqDelta)); + } + } +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + WNM_ReadParametersFromFile(pAd, tmpbuf, pBuffer); +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT + /*DFSIndoor*/ + { + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + if (RTMPGetKeyParameter("DfsIndoor", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->Dot11_H.bDFSIndoor = (USHORT) (simple_strtol(tmpbuf, 0, 10) != 0); + DBGPRINT(RT_DEBUG_TRACE, ("DfsIndoor=%d\n", pAd->Dot11_H.bDFSIndoor)); + } + { + INT k=0; + /*SymRoundFromCfg*/ + if (RTMPGetKeyParameter("SymRoundFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->SymRoundFromCfg = (UCHAR) simple_strtol(tmpbuf, 0, 10); + pRadarDetect->SymRoundCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("SymRoundFromCfg=%d\n", pRadarDetect->SymRoundFromCfg)); + } + + /*BusyIdleFromCfg*/ + if (RTMPGetKeyParameter("BusyIdleFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->BusyIdleFromCfg = (UCHAR) simple_strtol(tmpbuf, 0, 10); + pRadarDetect->BusyIdleCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("BusyIdleFromCfg=%d\n", pRadarDetect->BusyIdleFromCfg)); + } + /*DfsRssiHighFromCfg*/ + if (RTMPGetKeyParameter("DfsRssiHighFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->DfsRssiHighFromCfg = simple_strtol(tmpbuf, 0, 10); + pRadarDetect->DfsRssiHighCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHighFromCfg=%d\n", pRadarDetect->DfsRssiHighFromCfg)); + } + + /*DfsRssiLowFromCfg*/ + if (RTMPGetKeyParameter("DfsRssiLowFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->DfsRssiLowFromCfg = simple_strtol(tmpbuf, 0, 10); + pRadarDetect->DfsRssiLowCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLowFromCfg=%d\n", pRadarDetect->DfsRssiLowFromCfg)); + } + + /*DFSParamFromConfig*/ + if (RTMPGetKeyParameter("DFSParamFromConfig", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->DFSParamFromConfig = (UCHAR) simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DFSParamFromConfig=%d\n", pRadarDetect->DFSParamFromConfig)); + } + + /* DFSParam*/ + for(k = 0; k < 4*pAd->chipCap.DfsEngineNum; k++) + { + STRING tok_str[32]; + INT index ; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + index = (k%DfsEngineNum); + if (((k-k%DfsEngineNum)/DfsEngineNum) == 0) + snprintf(tok_str, sizeof(tok_str), "FCCParamCh%d", index); + else if (((k-k%DfsEngineNum)/DfsEngineNum) == 1) + snprintf(tok_str, sizeof(tok_str), "CEParamCh%d", index); + else if (((k-k%DfsEngineNum)/DfsEngineNum) == 2) + snprintf(tok_str, sizeof(tok_str), "JAPParamCh%d", index); + else if (((k-k%DfsEngineNum)/DfsEngineNum) == 3) + snprintf(tok_str, sizeof(tok_str), "JAPW53ParamCh%d", index); + + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, pBuffer, TRUE)) + { + ULONG DfsParam; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + DfsParam = simple_strtol(macptr, 0, 10); + switch (i) + { + case 0: + pDfsProgramParam->NewDFSTableEntry[k].mode = DfsParam; + break; + case 1: + pDfsProgramParam->NewDFSTableEntry[k].avgLen = DfsParam; + pDfsProgramParam->NewDFSTableEntry[k].valid = 1; + break; + case 2: + pDfsProgramParam->NewDFSTableEntry[k].ELow = DfsParam; + break; + case 3: + pDfsProgramParam->NewDFSTableEntry[k].EHigh = DfsParam; + break; + case 4: + pDfsProgramParam->NewDFSTableEntry[k].WLow = DfsParam; + break; + case 5: + pDfsProgramParam->NewDFSTableEntry[k].WHigh = DfsParam; + break; + case 6: + pDfsProgramParam->NewDFSTableEntry[k].EpsilonW = DfsParam; + break; + case 7: + pDfsProgramParam->NewDFSTableEntry[k].TLow = DfsParam; + break; + case 8: + pDfsProgramParam->NewDFSTableEntry[k].THigh = DfsParam; + break; + case 9: + pDfsProgramParam->NewDFSTableEntry[k].EpsilonT = DfsParam; + break; + + case 10: + pDfsProgramParam->NewDFSTableEntry[k].BLow = DfsParam; + break; + case 11: + pDfsProgramParam->NewDFSTableEntry[k].BHigh = DfsParam; + break; + + default: + break; + } + } + } + } + } + } +#endif /* DFS_SUPPORT */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /*DtimPeriod*/ + if(RTMPGetKeyParameter("DtimPeriod", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->ApCfg.DtimPeriod = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("DtimPeriod=%d\n", pAd->ApCfg.DtimPeriod)); + } +#ifdef BAND_STEERING + /* Band Steering Enable/Disable */ + if(RTMPGetKeyParameter("BandSteering", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->ApCfg.BandSteering = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("BandSteering=%d\n", pAd->ApCfg.BandSteering)); + } +#endif /* BAND_STEERING */ + } +#endif /* CONFIG_AP_SUPPORT */ + /*TxPower*/ + if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage; +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage)); + } + /*BGProtection*/ + if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, pBuffer, TRUE)) + { + /*#if 0 #ifndef WIFI_TEST*/ + /* pAd->CommonCfg.UseBGProtection = 2; disable b/g protection for throughput test*/ + /*#else*/ + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: /*Always On*/ + pAd->CommonCfg.UseBGProtection = 1; + break; + case 2: /*Always OFF*/ + pAd->CommonCfg.UseBGProtection = 2; + break; + case 0: /*AUTO*/ + default: + pAd->CommonCfg.UseBGProtection = 0; + break; + } + /*#endif*/ + DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection)); + } + +#ifdef CONFIG_AP_SUPPORT + /*OLBCDetection*/ + if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, pBuffer, TRUE)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: /*disable OLBC Detection*/ + pAd->CommonCfg.DisableOLBCDetect = 1; + break; + case 0: /*enable OLBC Detection*/ + pAd->CommonCfg.DisableOLBCDetect = 0; + break; + default: + pAd->CommonCfg.DisableOLBCDetect= 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect)); + } +#endif /* CONFIG_AP_SUPPORT */ + /*TxPreamble*/ + if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, pBuffer, TRUE)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case Rt802_11PreambleShort: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort; + break; + case Rt802_11PreambleLong: + default: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble)); + } + /*RTSThreshold*/ + if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, pBuffer, TRUE)) + { + RtsThresh = simple_strtol(tmpbuf, 0, 10); + if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) ) + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; + else + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; + + DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold)); + } + /*FragThreshold*/ + if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, pBuffer, TRUE)) + { + FragThresh = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { /*illegal FragThresh so we set it to default*/ + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + } + else if (FragThresh % 2 == 1) + { + /* The length of each fragment shall always be an even number of octets, except for the last fragment*/ + /* of an MSDU or MMPDU, which may be either an even or an odd number of octets.*/ + pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + /*pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;*/ + DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold)); + } + /*TxBurst*/ + if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, pBuffer, TRUE)) + { + /*#ifdef WIFI_TEST*/ + /* pAd->CommonCfg.bEnableTxBurst = FALSE;*/ + /*#else*/ + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + pAd->CommonCfg.bEnableTxBurst = TRUE; + else /*Disable*/ + pAd->CommonCfg.bEnableTxBurst = FALSE; + /*#endif*/ + DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst)); + } + +#ifdef AGGREGATION_SUPPORT + /*PktAggregate*/ + if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + pAd->CommonCfg.bAggregationCapable = TRUE; + else /*Disable*/ + pAd->CommonCfg.bAggregationCapable = FALSE; +#ifdef PIGGYBACK_SUPPORT + pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; +#endif /* PIGGYBACK_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable)); + } +#else + pAd->CommonCfg.bAggregationCapable = FALSE; + pAd->CommonCfg.bPiggyBackCapable = FALSE; +#endif /* AGGREGATION_SUPPORT */ + + /* WmmCapable*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + rtmp_read_ap_wmm_parms_from_file(pAd, tmpbuf, pBuffer); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, pBuffer); +#ifdef XLINK_SUPPORT + rtmp_get_psp_xlink_mode_from_file(pAd, tmpbuf, pBuffer); +#endif /* XLINK_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* MaxStaNum*/ + if (RTMPGetKeyParameter("MaxStaNum", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + ApCfg_Set_MaxStaNum_Proc(pAd, i, macptr); + } + } + + /* IdleTimeout*/ + if(RTMPGetKeyParameter("IdleTimeout", tmpbuf, 10, pBuffer, TRUE)) + { + ApCfg_Set_IdleTimeout_Proc(pAd, tmpbuf); + } + + /*NoForwarding*/ + if(RTMPGetKeyParameter("NoForwarding", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic = TRUE; + else /*Disable*/ + pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) NoForwarding=%d\n", i, pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic)); + } + } + + //NoForwardingMBCast + if (RTMPGetKeyParameter("NoForwardingMBCast", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if (simple_strtol(macptr, 0, 10) != 0) //Enable + pAd->ApCfg.MBSSID[i].IsolateInterStaMBCast = TRUE; + else //Disable + pAd->ApCfg.MBSSID[i].IsolateInterStaMBCast = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) NoForwardingMBCast=%d\n", i, pAd->ApCfg.MBSSID[i].IsolateInterStaMBCast)); + } + } + + /*NoForwardingBTNBSSID*/ + if(RTMPGetKeyParameter("NoForwardingBTNBSSID", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + pAd->ApCfg.IsolateInterStaTrafficBTNBSSID = TRUE; + else /*Disable*/ + pAd->ApCfg.IsolateInterStaTrafficBTNBSSID = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("NoForwardingBTNBSSID=%d\n", pAd->ApCfg.IsolateInterStaTrafficBTNBSSID)); + } + /*HideSSID*/ + if(RTMPGetKeyParameter("HideSSID", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + int apidx = i; + + if (i >= pAd->ApCfg.BssidNum) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + { + pAd->ApCfg.MBSSID[apidx].bHideSsid = TRUE; +#ifdef WSC_V2_SUPPORT + pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bWpsEnable = FALSE; +#endif /* WSC_V2_SUPPORT */ + } + else /*Disable*/ + pAd->ApCfg.MBSSID[apidx].bHideSsid = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) HideSSID=%d\n", i, pAd->ApCfg.MBSSID[apidx].bHideSsid)); + } + } + + /*StationKeepAlive*/ + if(RTMPGetKeyParameter("StationKeepAlive", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + int apidx = i; + + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime = simple_strtol(macptr, 0, 10); +#ifdef NOISE_TEST_ADJUST + if (!pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime) + pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime = 10; + else if (pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime == 0xFF) + pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime = 0; +#endif /* NOISE_TEST_ADJUST */ + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) StationKeepAliveTime=%d\n", i, pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime)); + } + } + + /*AutoChannelSelect*/ + if(RTMPGetKeyParameter("AutoChannelSelect", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + { + ChannelSel_Alg SelAlg=(ChannelSel_Alg)simple_strtol(tmpbuf, 0, 10); + if (SelAlg > 2 || SelAlg < 0) + { + pAd->ApCfg.bAutoChannelAtBootup = FALSE; + } + else /*Enable*/ + { + pAd->ApCfg.bAutoChannelAtBootup = TRUE; + pAd->ApCfg.AutoChannelAlg = SelAlg; + } + } + else /*Disable*/ + pAd->ApCfg.bAutoChannelAtBootup = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("AutoChannelAtBootup=%d\n", pAd->ApCfg.bAutoChannelAtBootup)); + } + + /*AutoChannelSkipList*/ + if (RTMPGetKeyParameter("AutoChannelSkipList", tmpbuf, 50, pBuffer, FALSE)) + { + pAd->ApCfg.AutoChannelSkipListNum = delimitcnt(tmpbuf, ";") + 1; + if ( pAd->ApCfg.AutoChannelSkipListNum > 10 ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Your no. of AutoChannelSkipList( %d ) is larger than 10 (boundary)\n",pAd->ApCfg.AutoChannelSkipListNum)); + pAd->ApCfg.AutoChannelSkipListNum = 10; + } + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr ; macptr = rstrtok(NULL,";"), i++) + { + if (i < pAd->ApCfg.AutoChannelSkipListNum ) + { + pAd->ApCfg.AutoChannelSkipList[i] = simple_strtol(macptr, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, (" AutoChannelSkipList[%d]= %d \n", i, pAd->ApCfg.AutoChannelSkipList[i])); + } + else + { + break; + } + } + } + +#ifdef AP_SCAN_SUPPORT + /*ACSCheckTime*/ + if (RTMPGetKeyParameter("ACSCheckTime", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 Hour = simple_strtol(tmpbuf, 0, 10); + pAd->ApCfg.ACSCheckTime = Hour*3600; /* Hour to second */ + DBGPRINT(RT_DEBUG_TRACE, ("ACSCheckTime = %u (hour) \n", Hour)); + } +#endif /* AP_SCAN_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef ED_MONITOR + +#ifdef CONFIG_AP_SUPPORT + /*For AP connected client's count*/ + if (RTMPGetKeyParameter("EDCCA_AP_STA_TH", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_sta_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_sta_threshold = %u\n", count)); + } + + /*For APs found in working channel*/ + if (RTMPGetKeyParameter("EDCCA_AP_AP_TH", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_ap_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_ap_threshold = %u\n", count)); + } + + /*For APs RSSI found in working channel*/ + if (RTMPGetKeyParameter("EDCCA_AP_RSSI_TH", tmpbuf, 32, pBuffer, TRUE)) + { + CHAR count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_rssi_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_rssi_threshold = %u\n", count)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + /*For STA site survey AP counts*/ + if (RTMPGetKeyParameter("EDCCA_STA_SCANED_AP_TH", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_ap_scaned = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_ap_scaned = %u\n", count)); + } + + /*For STA found APs in working channel*/ + if (RTMPGetKeyParameter("EDCCA_STA_CURRENT_CH_APS_TH", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_current_ch_aps = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_current_ch_aps = %u\n", count)); + } + + /*For STA RSSI threhold when linkup*/ + if (RTMPGetKeyParameter("EDCCA_STA_RSSI_TH", tmpbuf, 32, pBuffer, TRUE)) + { + CHAR count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_rssi_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_rssi_threshold = %u\n", count)); + } +#endif /* CONFIG_STA_SUPPORT */ + + /* common part for EDCCA config */ + if (RTMPGetKeyParameter("EDCCA_ED_TH", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_threshold = %u\n", count)); + } + if (RTMPGetKeyParameter("ED_MODE", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 mode = simple_strtol(tmpbuf, 0, 10); + pAd->ed_chk = mode; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_chk = %u\n", mode)); + } + + if (RTMPGetKeyParameter("EDCCA_FALSE_CCA_TH", tmpbuf, 32, pBuffer, TRUE)) + { + INT count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_false_cca_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_false_cca_threshold = %u\n", count)); + } + + + if (RTMPGetKeyParameter("ED_LEARN_TH", tmpbuf, 32, pBuffer, TRUE)) + { + INT count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_learning_time_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_learning_time_threshold = %u\n", count)); + } + + if (RTMPGetKeyParameter("EDCCA_BLOCK_CHECK_TH", tmpbuf, 32, pBuffer, TRUE)) + { + UINT8 count = simple_strtol(tmpbuf, 0, 10); + pAd->ed_block_tx_threshold = count; + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ed_block_tx_threshold = %u\n", count)); + } +#endif /* ED_MONITOR */ + + /*ShortSlot*/ + if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, pBuffer, TRUE)) + { + RT_CfgSetShortSlot(pAd, tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime)); + } + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { +#if defined(CONFIG_AP_SUPPORT) || defined(STA_ITXBF_SUPPORT) + /*ITxBfEn*/ + if(RTMPGetKeyParameter("ITxBfEn", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn = (simple_strtol(tmpbuf, 0, 10) != 0); + DBGPRINT(RT_DEBUG_TRACE, ("ITxBfEn = %d\n", pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn)); + + rtmp_asic_set_bf(pAd); + } + + /* ITxBfTimeout */ + if(RTMPGetKeyParameter("ITxBfTimeout", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ITxBfTimeout = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ITxBfTimeout = %ld\n", pAd->CommonCfg.ITxBfTimeout)); + } +#endif /* defined(CONFIG_AP_SUPPORT) || defined(STA_ITXBF_SUPPORT) */ + + /* ETxBfEnCond*/ + if(RTMPGetKeyParameter("ETxBfEnCond", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ETxBfEnCond = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ETxBfEnCond = %ld\n", pAd->CommonCfg.ETxBfEnCond)); + + if (pAd->CommonCfg.ETxBfEnCond) + { + pAd->CommonCfg.RegTransmitSetting.field.TxBF = TRUE; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.TxBF = FALSE; + } + rtmp_asic_set_bf(pAd); + } + + /* ITxBfCalibMode*/ + if(RTMPGetKeyParameter("ITxBfCalibMode", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ITxBfCalibMode = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ITxBfCalibMode = %ld\n", pAd->CommonCfg.ITxBfCalibMode)); + } + + /* ETxBfeeEn*/ + if(RTMPGetKeyParameter("ETxBfeeEn", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ETxBfeeEn = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ETxBfeeEn = %d\n", pAd->CommonCfg.ETxBfeeEn)); + } + + /* ETxBfTimeout*/ + if(RTMPGetKeyParameter("ETxBfTimeout", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ETxBfTimeout = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ETxBfTimeout = %ld\n", pAd->CommonCfg.ETxBfTimeout)); + } + + /* ETxBfNoncompress*/ + if(RTMPGetKeyParameter("ETxBfNoncompress", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ETxBfNoncompress = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ETxBfNoncompress = %d\n", pAd->CommonCfg.ETxBfNoncompress)); + } + + /* ETxBfIncapable */ + if(RTMPGetKeyParameter("ETxBfIncapable", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.ETxBfIncapable = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("ETxBfIncapable = %d\n", pAd->CommonCfg.ETxBfIncapable)); + } + } +#endif /* TXBF_SUPPORT */ + + +#ifdef PRE_ANT_SWITCH + /*PreAntSwitch*/ + if(RTMPGetKeyParameter("PreAntSwitch", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.PreAntSwitch = (simple_strtol(tmpbuf, 0, 10) != 0); + DBGPRINT(RT_DEBUG_TRACE, ("PreAntSwitch = %d\n", pAd->CommonCfg.PreAntSwitch)); + } +#endif /* PRE_ANT_SWITCH */ + + + +#ifdef STREAM_MODE_SUPPORT + /* StreamMode*/ + if (pAd->chipCap.FlgHwStreamMode) + { + if(RTMPGetKeyParameter("StreamMode", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.StreamMode = (simple_strtol(tmpbuf, 0, 10) & 0x03); + DBGPRINT(RT_DEBUG_TRACE, ("StreamMode= %d\n", pAd->CommonCfg.StreamMode)); + } + + /* StreamModeMac*/ + for (i = 0; i < STREAM_MODE_STA_NUM; i++) + { + STRING tok_str[32]; + + sprintf(tok_str, "StreamModeMac%d", i); + + if (RTMPGetKeyParameter(tok_str, tmpbuf, MAX_PARAM_BUFFER_SIZE, pBuffer, TRUE)) + { + int j; + if(strlen(tmpbuf) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/ + continue; + + for (j=0; jCommonCfg.StreamModeMac[i][j], 1); + tmpbuf=tmpbuf+3; + } + } + } + + if (NdisEqualMemory(ZERO_MAC_ADDR, &pAd->CommonCfg.StreamModeMac[0][0], MAC_ADDR_LEN)) + { + /* set default broadcast mac to entry 0 if user not set it */ + NdisMoveMemory(&pAd->CommonCfg.StreamModeMac[0][0], BROADCAST_ADDR, MAC_ADDR_LEN); + } + } +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + /*DebugFlags*/ + if(RTMPGetKeyParameter("DebugFlags", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.DebugFlags = simple_strtol(tmpbuf, 0, 16); + DBGPRINT(RT_DEBUG_TRACE, ("DebugFlags = 0x%02lx\n", pAd->CommonCfg.DebugFlags)); + } +#endif /* DBG_CTRL_SUPPORT */ + + /*IEEE80211H*/ + if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->CommonCfg.bIEEE80211H = TRUE; + else /*Disable*/ + pAd->CommonCfg.bIEEE80211H = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H)); + } + } + +#ifdef DFS_SUPPORT + { + /*CSPeriod*/ + if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->Dot11_H.CSPeriod = simple_strtol(tmpbuf, 0, 10); + else + pAd->Dot11_H.CSPeriod = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->Dot11_H.CSPeriod)); + } + + } +#endif /* DFS_SUPPORT */ + + /*RDRegion*/ + if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, pBuffer, TRUE)) + { + if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0)) + { + pAd->CommonCfg.RDDurRegion = JAP_W53; + /*pRadarDetect->DfsSessionTime = 15;*/ + } + else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0)) + { + pAd->CommonCfg.RDDurRegion = JAP_W56; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0)) + { + pAd->CommonCfg.RDDurRegion = JAP; + /*pRadarDetect->DfsSessionTime = 5;*/ + } + else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0)) + { + pAd->CommonCfg.RDDurRegion = FCC; + /*pRadarDetect->DfsSessionTime = 5;*/ + } + else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0)) + { + pAd->CommonCfg.RDDurRegion = CE; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + else + { + pAd->CommonCfg.RDDurRegion = CE; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + + DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RDDurRegion)); + } + else + { + pAd->CommonCfg.RDDurRegion = CE; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + +#ifdef SYSTEM_LOG_SUPPORT + /*WirelessEvent*/ + if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, pBuffer, TRUE)) + { + BOOLEAN FlgIsWEntSup = FALSE; + + if(simple_strtol(tmpbuf, 0, 10) != 0) + FlgIsWEntSup = TRUE; + + RtmpOsWlanEventSet(pAd, &pAd->CommonCfg.bWirelessEvent, FlgIsWEntSup); + DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent)); + } +#endif /* SYSTEM_LOG_SUPPORT */ + + + /*AuthMode*/ + if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, pBuffer, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), i++) + { + ApCfg_Set_AuthMode_Proc(pAd, i, macptr); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (rtstrcasecmp(tmpbuf, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(tmpbuf, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(tmpbuf, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (rtstrcasecmp(tmpbuf, "WPANONE") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPANone; + else if (rtstrcasecmp(tmpbuf, "WPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if (rtstrcasecmp(tmpbuf, "WPA") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if (rtstrcasecmp(tmpbuf, "WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WAPI_SUPPORT + else if (rtstrcasecmp(tmpbuf, "WAICERT") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWAICERT; + else if (rtstrcasecmp(tmpbuf, "WAIPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(AuthMode=%d)\n", + __FUNCTION__, wdev->AuthMode)); + } +#endif /* CONFIG_STA_SUPPORT */ + } + /*EncrypType*/ + if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, pBuffer, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + We need to reset the WepStatus of all interfaces as 1 (Ndis802_11WEPDisabled) first. + Or it may have problem when some interface enabled but didn't configure it. + */ + for ( i= 0; iApCfg.BssidNum; i++) + pAd->ApCfg.MBSSID[i].wdev.WepStatus = Ndis802_11WEPDisabled; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + int apidx; + struct wifi_dev *wdev; + if (i < HW_BEACON_MAX_NUM) + apidx = i; + else + break; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + if ((strncmp(macptr, "NONE", 4) == 0) || (strncmp(macptr, "none", 4) == 0)) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0)) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if ((strncmp(macptr, "TKIPAES", 7) == 0) || (strncmp(macptr, "tkipaes", 7) == 0)) + wdev->WepStatus = Ndis802_11TKIPAESMix; + else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0)) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0)) + wdev->WepStatus = Ndis802_11AESEnable; +#ifdef WAPI_SUPPORT + else if ((strncmp(macptr, "SMS4", 4) == 0) || (strncmp(macptr, "sms4", 4) == 0)) + wdev->WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + wdev->WepStatus = Ndis802_11WEPDisabled; + + /* decide the group key encryption type*/ + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + wdev->GroupKeyWepStatus = Ndis802_11TKIPEnable; + else + wdev->GroupKeyWepStatus = wdev->WepStatus; + + /* move to ap.c::APStartUp to process*/ + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, wdev->WepStatus, apidx);*/ + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) EncrypType=%d\n", i, wdev->WepStatus)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + if (rtstrcasecmp(tmpbuf, "WEP") == TRUE) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if (rtstrcasecmp(tmpbuf, "TKIP") == TRUE) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if (rtstrcasecmp(tmpbuf, "AES") == TRUE) + wdev->WepStatus = Ndis802_11AESEnable; +#ifdef WAPI_SUPPORT + else if (rtstrcasecmp(tmpbuf, "SMS4") == TRUE) + wdev->WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + wdev->WepStatus = Ndis802_11WEPDisabled; + RTMPSetSTACipherSuites(pAd, wdev->WepStatus); + /*RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, 0);*/ + DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, wdev->WepStatus)); + } + #endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* WpaMixPairCipher*/ + if(RTMPGetKeyParameter("WpaMixPairCipher", tmpbuf, 256, pBuffer, TRUE)) + { + /* + In WPA-WPA2 mix mode, it provides a more flexible cipher combination. + - WPA-AES and WPA2-TKIP + - WPA-AES and WPA2-TKIPAES + - WPA-TKIP and WPA2-AES + - WPA-TKIP and WPA2-TKIPAES + - WPA-TKIPAES and WPA2-AES + - WPA-TKIPAES and WPA2-TKIP + - WPA-TKIPAES and WPA2-TKIPAES (default) + */ + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + struct wifi_dev *wdev; + + // TODO: shiang, check about the sequence of this paramter and BssNum!! + if (i >= HW_BEACON_MAX_NUM) + break; + + wdev = &pAd->ApCfg.MBSSID[i].wdev; + if (wdev->AuthMode != Ndis802_11AuthModeWPA1WPA2 && + wdev->AuthMode != Ndis802_11AuthModeWPA1PSKWPA2PSK) + continue; + + if (wdev->WepStatus != Ndis802_11TKIPAESMix) + continue; + + if ((strncmp(macptr, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkipaes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkip", 17) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(macptr, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_aes", 17) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(macptr, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_aes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else /*Default*/ + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + + DBGPRINT(RT_DEBUG_OFF, ("I/F(ra%d) MixWPACipher=0x%02x\n", i, wdev->WpaMixPairCipher)); + } + } + + /*RekeyMethod*/ + if(RTMPGetKeyParameter("RekeyMethod", tmpbuf, 128, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + PRT_WPA_REKEY pRekeyInfo = &pAd->ApCfg.MBSSID[i].WPAREKEY; + + if ((strcmp(macptr, "TIME") == 0) || (strcmp(macptr, "time") == 0)) + pRekeyInfo->ReKeyMethod = TIME_REKEY; + else if ((strcmp(macptr, "PKT") == 0) || (strcmp(macptr, "pkt") == 0)) + pRekeyInfo->ReKeyMethod = PKT_REKEY; + else if ((strcmp(macptr, "DISABLE") == 0) || (strcmp(macptr, "disable") == 0)) + pRekeyInfo->ReKeyMethod = DISABLE_REKEY; + else + pRekeyInfo->ReKeyMethod = DISABLE_REKEY; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyMethod=%ld\n", i, pRekeyInfo->ReKeyMethod)); + } + + /* Apply to remaining MBSS*/ + if (i == 1) + { + for (i = 1; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyMethod = + pAd->ApCfg.MBSSID[0].WPAREKEY.ReKeyMethod; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyMethod=%ld\n", + i, pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyMethod)); + } + } + } + /*RekeyInterval*/ + if(RTMPGetKeyParameter("RekeyInterval", tmpbuf, 255, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ULONG value_interval; + PRT_WPA_REKEY pRekeyInfo = &pAd->ApCfg.MBSSID[i].WPAREKEY; + + value_interval = simple_strtol(macptr, 0, 10); + + if((value_interval >= 10) && (value_interval < MAX_REKEY_INTER)) + pRekeyInfo->ReKeyInterval = value_interval; + else /*Default*/ + pRekeyInfo->ReKeyInterval = 3600; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyInterval=%ld\n", + i, pRekeyInfo->ReKeyInterval)); + } + + /* Apply to remaining MBSS*/ + if (i == 1) + { + for (i = 1; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyInterval = + pAd->ApCfg.MBSSID[0].WPAREKEY.ReKeyInterval; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyInterval=%ld\n", + i, pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyInterval)); + } + } + + } + /*PMKCachePeriod*/ + if(RTMPGetKeyParameter("PMKCachePeriod", tmpbuf, 255, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.MBSSID[i].PMKCachePeriod = + simple_strtol(macptr, 0, 10) * 60 * OS_HZ; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PMKCachePeriod=%ld\n", + i, pAd->ApCfg.MBSSID[i].PMKCachePeriod)); + } + + /* Apply to remaining MBSS*/ + if (i == 1) + { + for (i = 1; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].PMKCachePeriod = + pAd->ApCfg.MBSSID[0].PMKCachePeriod; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PMKCachePeriod=%ld\n", + i, pAd->ApCfg.MBSSID[i].PMKCachePeriod)); + } + } + } + + /*WPAPSK_KEY*/ + if(TRUE) + { + STRING tok_str[16]; + BOOLEAN bWPAPSKxIsUsed = FALSE; + + //DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum)); + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "WPAPSK%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, pBuffer, FALSE)) + { + rtmp_parse_wpapsk_buffer_from_file(pAd, tmpbuf, i); + + if (bWPAPSKxIsUsed == FALSE) + { + bWPAPSKxIsUsed = TRUE; + } + } + } + if (bWPAPSKxIsUsed == FALSE) + { + if (RTMPGetKeyParameter("WPAPSK", tmpbuf, 512, pBuffer, FALSE)) + { + if (pAd->ApCfg.BssidNum == 1) + { + rtmp_parse_wpapsk_buffer_from_file(pAd, tmpbuf, BSS0); + } + else + { + /* Anyway, we still do the legacy dissection of the whole WPAPSK passphrase.*/ + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + rtmp_parse_wpapsk_buffer_from_file(pAd, macptr, i); + } + + } + } + } + +#ifdef DBG + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + int j; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WPAPSK Key => \n", i)); + for (j = 0; j < 32; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%02x:", pAd->ApCfg.MBSSID[i].PMK[j])); + if ((j%16) == 15) + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } +#endif + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(RTMPGetKeyParameter("WPAPSK", tmpbuf, 512, pBuffer, FALSE)) + RTMPSetSTAPassPhrase(pAd, tmpbuf); + } +#endif /* CONFIG_STA_SUPPORT */ + + /*DefaultKeyID, KeyType, KeyStr*/ + rtmp_read_key_parms_from_file(pAd, tmpbuf, pBuffer); + +#ifdef WAPI_SUPPORT + rtmp_read_wapi_parms_from_file(pAd, tmpbuf, pBuffer); +#endif /* WAPI_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /*Access Control List*/ + rtmp_read_acl_parms_from_file(pAd, tmpbuf, pBuffer); + +#ifdef APCLI_SUPPORT + rtmp_read_ap_client_from_file(pAd, tmpbuf, pBuffer); +#endif /* APCLI_SUPPORT */ + +#ifdef IGMP_SNOOP_SUPPORT + /* Igmp Snooping information*/ + rtmp_read_igmp_snoop_from_file(pAd, tmpbuf, pBuffer); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef WDS_SUPPORT + rtmp_read_wds_from_file(pAd, tmpbuf, pBuffer); +#endif /* WDS_SUPPORT */ + +#ifdef DOT1X_SUPPORT + rtmp_read_radius_parms_from_file(pAd, tmpbuf, pBuffer); +#endif /* DOT1X_SUPPORT */ + +#ifdef IDS_SUPPORT + rtmp_read_ids_from_file(pAd, tmpbuf, pBuffer); +#endif /* IDS_SUPPORT */ + +#ifdef SMART_MESH + rtmp_read_smart_mesh_from_file(pAd, tmpbuf, pBuffer); +#ifdef MWDS + rtmp_read_DWDS_from_file(pAd, tmpbuf, pBuffer); +#endif /* MWDS*/ +#endif /* SMART_MESH */ + +#ifdef MWDS + rtmp_read_MWDS_from_file(pAd, tmpbuf, pBuffer); +#endif /* MWDS */ + + +#ifdef MAC_REPEATER_SUPPORT + if (RTMPGetKeyParameter("MACRepeaterEn", tmpbuf, 10, pBuffer, FALSE)) + { + UINT32 MacReg = 0; + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + { + pAd->ApCfg.bMACRepeaterEn = TRUE; + RTMP_IO_READ32(pAd, MAC_ADDR_EXT_EN, &MacReg); + MacReg |= 1; + RTMP_IO_WRITE32(pAd, MAC_ADDR_EXT_EN, MacReg); + } + else /*Disable*/ + { + pAd->ApCfg.bMACRepeaterEn = FALSE; + RTMP_IO_READ32(pAd, MAC_ADDR_EXT_EN, &MacReg); + MacReg &= ~(1); + RTMP_IO_WRITE32(pAd, MAC_ADDR_EXT_EN, MacReg); + } + DBGPRINT(RT_DEBUG_TRACE, ("MACRepeaterEn=%d\n", pAd->ApCfg.bMACRepeaterEn)); + } + + if (RTMPGetKeyParameter("MACRepeaterOuiMode", tmpbuf, 10, pBuffer, FALSE)) + { + INT OuiMode = simple_strtol(tmpbuf, 0, 10); + + if (OuiMode == 1) + pAd->ApCfg.MACRepeaterOuiMode = 1; + else if (OuiMode == 2) + pAd->ApCfg.MACRepeaterOuiMode = 2; /* customer specific */ + else + pAd->ApCfg.MACRepeaterOuiMode = 0; /* use Ap-Client first 3 bytes MAC assress (default) */ + + DBGPRINT(RT_DEBUG_TRACE, ("MACRepeaterOuiMode=%d\n", pAd->ApCfg.MACRepeaterOuiMode)); + + } +#endif /* MAC_REPEATER_SUPPORT */ + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + HTParametersHook(pAd, tmpbuf, pBuffer); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + VHTParametersHook(pAd, tmpbuf, pBuffer); +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + if(RTMPGetKeyParameter("cap_support", tmpbuf, 25, pBuffer, TRUE)) + { + ULONG cap_support = simple_strtol(tmpbuf, 0, 10); + + pAd->cap_support = cap_support > 0 ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s(): CaptureMode=%d\n", + __FUNCTION__, pAd->cap_support)); + } +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WSC_AP_SUPPORT + STRING tok_str[16] = {0}; + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "WscDefaultSSID%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 33, pBuffer, FALSE)) + { + NdisZeroMemory(&pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid, sizeof(NDIS_802_11_SSID)); + NdisMoveMemory(pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid.Ssid, tmpbuf , strlen(tmpbuf)); + pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid.SsidLength = strlen(tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("WscDefaultSSID[%d]=%s\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid.Ssid)); + } + } + + /*WscConfMode*/ + if(RTMPGetKeyParameter("WscConfMode", tmpbuf, 10, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT WscConfMode = simple_strtol(macptr, 0, 10); + + if (i >= pAd->ApCfg.BssidNum) + break; + + if (WscConfMode > 0 && WscConfMode < 8) + { + pAd->ApCfg.MBSSID[i].WscControl.WscConfMode = WscConfMode; + } + else + { + pAd->ApCfg.MBSSID[i].WscControl.WscConfMode = WSC_DISABLE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscConfMode=%d\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscConfMode)); + } + } + + /*WscConfStatus*/ + if(RTMPGetKeyParameter("WscConfStatus", tmpbuf, 10, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].WscControl.WscConfStatus = (INT) simple_strtol(macptr, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscConfStatus=%d\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscConfStatus)); + } + } + /*WscConfMethods*/ + if(RTMPGetKeyParameter("WscConfMethods", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].WscControl.WscConfigMethods = (USHORT)simple_strtol(macptr, 0, 16); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscConfMethods=0x%x\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscConfigMethods)); + } + } + + /*WscKeyASCII (0:Hex, 1:ASCII(random length), others: ASCII length, default 8)*/ + if (RTMPGetKeyParameter("WscKeyASCII", tmpbuf, 10, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT Value; + + if (i >= pAd->ApCfg.BssidNum) + break; + + Value = (INT) simple_strtol(tmpbuf, 0, 10); + if(Value==0 || Value==1) + pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII = Value; + else if(Value >= 8 && Value <=63) + pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII = Value; + else + pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII = 8; + DBGPRINT(RT_DEBUG_WARN, ("WscKeyASCII=%d\n", pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII)); + } + } + + if (RTMPGetKeyParameter("WscSecurityMode", tmpbuf, 50, pBuffer, TRUE)) + { + for (i= 0; iApCfg.BssidNum; i++) + pAd->ApCfg.MBSSID[i].WscSecurityMode = WPAPSKTKIP; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT tmpMode = 0; + + if (i >= pAd->ApCfg.BssidNum) + break; + + tmpMode = (INT) simple_strtol(macptr, 0, 10); + if (tmpMode <= WPAPSKWPA2PSKTKIPAES) + pAd->ApCfg.MBSSID[i].WscSecurityMode = tmpMode; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetProfileParameters I/F(ra%d) WscSecurityMode=%d\n", + i, pAd->ApCfg.MBSSID[i].WscSecurityMode)); + } + } + + /* WCNTest*/ + if(RTMPGetKeyParameter("WCNTest", tmpbuf, 10, pBuffer, TRUE)) + { + BOOLEAN bEn = FALSE; + + if ((strncmp(tmpbuf, "0", 1) == 0)) + bEn = FALSE; + else + bEn = TRUE; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].WscControl.bWCNTest = bEn; + } + DBGPRINT(RT_DEBUG_TRACE, ("WCNTest=%d\n", bEn)); + } + + /*WSC UUID Str*/ + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[i].WscControl; + snprintf(tok_str, sizeof(tok_str), "WSC_UUID_Str%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 40, pBuffer, FALSE)) + { + NdisMoveMemory(&pWpsCtrl->Wsc_Uuid_Str[0], tmpbuf , strlen(tmpbuf)); + DBGPRINT(RT_DEBUG_TRACE, ("UUID_Str[%d]=%s\n", i+1, pWpsCtrl->Wsc_Uuid_Str)); + } + } + + /*WSC UUID Hex*/ + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[i].WscControl; + snprintf(tok_str, sizeof(tok_str), "WSC_UUID_E%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 40, pBuffer, FALSE)) + { + AtoH(tmpbuf, &pWpsCtrl->Wsc_Uuid_E[0], UUID_LEN_HEX); + DBGPRINT(RT_DEBUG_TRACE, ("Wsc_Uuid_E[%d]", i+1)); + hex_dump("", &pWpsCtrl->Wsc_Uuid_E[0], UUID_LEN_HEX); + } + } + + /* WSC AutoTrigger Disable */ + if(RTMPGetKeyParameter("WscAutoTriggerDisable", tmpbuf, 10, pBuffer, TRUE)) + { + BOOLEAN bEn = FALSE; + + if ((strncmp(tmpbuf, "0", 1) == 0)) + bEn = FALSE; + else + bEn = TRUE; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].WscControl.bWscAutoTriggerDisable = bEn; + } + DBGPRINT(RT_DEBUG_TRACE, ("bWscAutoTriggerDisable=%d\n", bEn)); + } + + +#endif /* WSC_AP_SUPPORT */ + + + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + /*CarrierDetect*/ + if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, pBuffer, TRUE)) + { + if ((strncmp(tmpbuf, "0", 1) == 0)) + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + else if ((strncmp(tmpbuf, "1", 1) == 0)) + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + else + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable)); + } + else + pAd->CommonCfg.CarrierDetect.Enable = FALSE; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /*PSMode*/ + if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, pBuffer, TRUE)) + { + if (pAd->StaCfg.BssType == BSS_INFRA) + { + if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0)) + { + /* + 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 ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0) + || (strcmp(tmpbuf, "FAST_PSP") == 0)) + { + /* 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 ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0) + || (strcmp(tmpbuf, "LEGACY_PSP") == 0)) + { + /* 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; + pAd->StaCfg.DefaultListenCount = 3; +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + pAd->StaCfg.DefaultListenCount = 1; +#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; + } + DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode)); + } + } + /* AutoRoaming by RSSI*/ + if (RTMPGetKeyParameter("AutoRoaming", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bAutoRoaming = FALSE; + else + pAd->StaCfg.bAutoRoaming = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("AutoRoaming=%d\n", pAd->StaCfg.bAutoRoaming)); + } + /* RoamThreshold*/ + if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, pBuffer, TRUE)) + { + long lInfo = simple_strtol(tmpbuf, 0, 10); + + if (lInfo > 90 || lInfo < 60) + pAd->StaCfg.dBmToRoam = -70; + else + pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d dBm\n", pAd->StaCfg.dBmToRoam)); + } + + + + + if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bTGnWifiTest = FALSE; + else + pAd->StaCfg.bTGnWifiTest = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest)); + } +#ifdef ETH_CONVERT_SUPPORT + /* Ethernet Converter Operation Mode.*/ + if (RTMPGetKeyParameter("EthConvertMode", tmpbuf, 32, pBuffer, TRUE)) + { + Set_EthConvertMode_Proc(pAd, tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("EthConvertMode=%d\n", pAd->EthConvert.ECMode)); + } + + /* Ethernet Converter Operation Mode.*/ + if (RTMPGetKeyParameter("EthCloneMac", tmpbuf, 32, pBuffer, TRUE)) + { + Set_EthCloneMac_Proc(pAd, tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("EthCloneMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->EthConvert.EthCloneMac[0], pAd->EthConvert.EthCloneMac[1], pAd->EthConvert.EthCloneMac[2], + pAd->EthConvert.EthCloneMac[3], pAd->EthConvert.EthCloneMac[4], pAd->EthConvert.EthCloneMac[5])); + } +#endif /* ETH_CONVERT_SUPPORT */ + + /* Beacon Lost Time*/ + if (RTMPGetKeyParameter("BeaconLostTime", tmpbuf, 32, pBuffer, TRUE)) + { + ULONG lInfo = (ULONG)simple_strtol(tmpbuf, 0, 10); + + if ((lInfo != 0) && (lInfo <= 60)) + pAd->StaCfg.BeaconLostTime = (lInfo * OS_HZ); + DBGPRINT(RT_DEBUG_TRACE, ("BeaconLostTime=%ld \n", pAd->StaCfg.BeaconLostTime)); + } + + /* Auto Connet Setting if no SSID */ + if (RTMPGetKeyParameter("AutoConnect", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bAutoConnectIfNoSSID = FALSE; + else + pAd->StaCfg.bAutoConnectIfNoSSID = TRUE; + } + +#ifdef DOT11R_FT_SUPPORT + /* FtSupport*/ + if (RTMPGetKeyParameter("FtSupport", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.Dot11RCommInfo.bFtSupport = FALSE; + else + pAd->StaCfg.Dot11RCommInfo.bFtSupport = TRUE; + ; + DBGPRINT(RT_DEBUG_TRACE, ("bFtSupport=%d \n", pAd->StaCfg.Dot11RCommInfo.bFtSupport)); + } +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + if(RTMPGetKeyParameter("TDLSCapable", tmpbuf, 32, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/ + { + pAd->StaCfg.TdlsInfo.bTDLSCapable = TRUE; + } + else /*Disable*/ + { + pAd->StaCfg.TdlsInfo.bTDLSCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("bTDLSCapable=%d\n", pAd->StaCfg.TdlsInfo.bTDLSCapable)); + } + +#ifdef TDLS_AUTOLINK_SUPPORT + if (RTMPGetKeyParameter("TDLS_AutoLink", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->StaCfg.TdlsInfo.TdlsAutoLink = TRUE; + else //Disable + pAd->StaCfg.TdlsInfo.TdlsAutoLink = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("TdlsAutoLink=%d\n", pAd->StaCfg.TdlsInfo.TdlsAutoLink)); + } +#endif /* TDLS_AUTOLINK_SUPPORT */ + + if (RTMPGetKeyParameter("TDLS_SwitchChSupp", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) != 0) //Enable + { + pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp = TRUE; + } + else //Disable + { + pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("TdlsSwitchChSupp=%d\n", pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp)); + } + + if (RTMPGetKeyParameter("TDLS_PsmSupp", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) != 0) //Enable + { + pAd->StaCfg.TdlsInfo.TdlsPsmSupp = TRUE; + } + else //Disable + { + pAd->StaCfg.TdlsInfo.TdlsPsmSupp = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("TdlsPsmSupp=%d\n", pAd->StaCfg.TdlsInfo.TdlsPsmSupp)); + } + + //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO + if (RTMPGetKeyParameter("TDLS_APSDAC", tmpbuf, 32, pBuffer, TRUE)) + { + BOOLEAN FlgIsAcUapsdEnabled[4]; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + FlgIsAcUapsdEnabled[i] = (BOOLEAN)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS APSDAC%d %d\n", i, FlgIsAcUapsdEnabled[i])); + } + + pAd->CommonCfg.TDLS_bAPSDAC_BE = FlgIsAcUapsdEnabled[0]; + pAd->CommonCfg.TDLS_bAPSDAC_BK = FlgIsAcUapsdEnabled[1]; + pAd->CommonCfg.TDLS_bAPSDAC_VI = FlgIsAcUapsdEnabled[2]; + pAd->CommonCfg.TDLS_bAPSDAC_VO = FlgIsAcUapsdEnabled[3]; + } + + //MaxSPLength + if (RTMPGetKeyParameter("TDLS_MaxSPLength", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.TDLS_MaxSPLength = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS MaxSPLength=%d\n", pAd->CommonCfg.TDLS_MaxSPLength)); + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + + /* FastConnect*/ + if(RTMPGetKeyParameter("FastConnect", tmpbuf, 32, pBuffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bFastConnect = FALSE; + else + pAd->StaCfg.bFastConnect = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("FastConnect=%d\n", pAd->StaCfg.bFastConnect)); + } + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MCAST_RATE_SPECIFIC + /* McastPhyMode*/ + if (RTMPGetKeyParameter("McastPhyMode", tmpbuf, 32, pBuffer, TRUE)) + { + UCHAR PhyMode = simple_strtol(tmpbuf, 0, 10); + //pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; + switch (PhyMode) + { + case MCAST_DISABLE: /* disable */ + NdisMoveMemory(&pAd->CommonCfg.MCastPhyMode, + &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + break; + + case MCAST_CCK: /* CCK*/ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_CCK; + pAd->CommonCfg.MCastPhyMode.field.BW = BW_20; + break; + + case MCAST_OFDM: /* OFDM*/ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_OFDM; + pAd->CommonCfg.MCastPhyMode.field.BW = BW_20; + break; +#ifdef DOT11_N_SUPPORT + case MCAST_HTMIX: /* HTMIX*/ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_HTMIX; + break; +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + case MCAST_VHT: /* VHT */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_VHT; + break; +#endif /* DOT11_VHT_AC */ + + default: + DBGPRINT(RT_DEBUG_OFF, ("Unknown Muticast PhyMode %d\n", PhyMode)); + DBGPRINT(RT_DEBUG_OFF, ("0:Disable 1:CCK, 2:OFDM, 3:HTMIX, 4:VHT\n")); + break; + } + } + else + NdisMoveMemory(&pAd->CommonCfg.MCastPhyMode, + &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + + /* McastMcs*/ + if (RTMPGetKeyParameter("McastMcs", tmpbuf, 32, pBuffer, TRUE)) + { + UCHAR Mcs = simple_strtol(tmpbuf, 0, 10); + switch(pAd->CommonCfg.MCastPhyMode.field.MODE) + { + case MODE_CCK: + if ((Mcs <= 3) || (Mcs >= 8 && Mcs <= 11)) + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + else + DBGPRINT(RT_DEBUG_OFF, ("MCS must in range of 0 ~ 3 and 8 ~ 11 for CCK Mode.\n")); + break; + + case MODE_OFDM: + if (Mcs > 7) + DBGPRINT(RT_DEBUG_OFF, ("MCS must in range from 0 to 7 for OFDM Mode.\n")); + else + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + break; + + default: + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + break; + } + } + else + pAd->CommonCfg.MCastPhyMode.field.MCS = 0; +#endif /* MCAST_RATE_SPECIFIC */ + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WSC_INCLUDED + + rtmp_read_wsc_user_parms_from_file(pAd, tmpbuf, pBuffer); + + /* Wsc4digitPinCode = TRUE use 4-digit Pin code, otherwise 8-digit Pin code */ + if (RTMPGetKeyParameter("Wsc4digitPinCode", tmpbuf, 32, pBuffer, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if (simple_strtol(macptr, 0, 10) != 0) //Enable + pAd->ApCfg.MBSSID[i].WscControl.WscEnrollee4digitPinCode = TRUE; + else //Disable + pAd->ApCfg.MBSSID[i].WscControl.WscEnrollee4digitPinCode = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Wsc4digitPinCode=%d\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscEnrollee4digitPinCode)); + } + + } +#endif // CONFIG_AP_SUPPORT // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->StaCfg.WscControl.WscEnrollee4digitPinCode = TRUE; + else //Disable + pAd->StaCfg.WscControl.WscEnrollee4digitPinCode = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Wsc4digitPinCode=%d\n", pAd->StaCfg.WscControl.WscEnrollee4digitPinCode)); + } +#endif // CONFIG_STA_SUPPORT // + } + + if (RTMPGetKeyParameter("WscVendorPinCode", tmpbuf, 256, pBuffer, TRUE)) + { + PWSC_CTRL pWscContrl; + int bSetOk; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pWscContrl = &pAd->ApCfg.MBSSID[BSS0].WscControl; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pWscContrl = &pAd->StaCfg.WscControl; + } +#endif /* CONFIG_STA_SUPPORT */ + bSetOk = RT_CfgSetWscPinCode(pAd, tmpbuf, pWscContrl); + if (bSetOk) + DBGPRINT(RT_DEBUG_TRACE, ("%s - WscVendorPinCode= (%d)\n", __FUNCTION__, bSetOk)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s - WscVendorPinCode: invalid pin code(%s)\n", __FUNCTION__, tmpbuf)); + } +#ifdef WSC_V2_SUPPORT + if (RTMPGetKeyParameter("WscV2Support", tmpbuf, 32, pBuffer, TRUE)) + { + UCHAR bEnable; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + bEnable = (UCHAR)simple_strtol(macptr, 0, 10); + pAd->ApCfg.MBSSID[i].WscControl.WscV2Info.bEnableWpsV2 = bEnable; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscV2Support=%d\n", i, bEnable)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + bEnable = (UCHAR)simple_strtol(tmpbuf, 0, 10); + + pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2 = bEnable; + DBGPRINT(RT_DEBUG_TRACE, ("%s - WscV2Support= (%d)\n", __FUNCTION__, bEnable)); + } +#endif /* CONFIG_STA_SUPPORT */ + } +#endif /* WSC_V2_SUPPORT */ + + +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11R_FT_SUPPORT + FT_rtmp_read_parameters_from_file(pAd, tmpbuf, pBuffer); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + rtmp_read_pmf_parameters_from_file(pAd, tmpbuf, pBuffer); +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + /* EntryLifeCheck is used to check */ + if (RTMPGetKeyParameter("EntryLifeCheck", tmpbuf, 256, pBuffer, TRUE)) + { + long LifeCheckCnt = simple_strtol(tmpbuf, 0, 10); + if ((LifeCheckCnt <= 65535) && (LifeCheckCnt != 0)) + pAd->ApCfg.EntryLifeCheck = LifeCheckCnt; + else + pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT; + + DBGPRINT(RT_DEBUG_TRACE, ("EntryLifeCheck=%ld\n", pAd->ApCfg.EntryLifeCheck)); + } + +#ifdef DOT11K_RRM_SUPPORT + RRM_ReadParametersFromFile(pAd, tmpbuf, pBuffer); +#endif /* DOT11K_RRM_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + if (RTMPGetKeyParameter("VideoTurbine", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.Enable = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video Enable=%d\n", pAd->VideoTurbine.Enable)); + } + if (RTMPGetKeyParameter("VideoClassifierEnable", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.ClassifierEnable = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video ClassifierEnable=%d\n", pAd->VideoTurbine.ClassifierEnable)); + } + if (RTMPGetKeyParameter("VideoHighTxMode", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.HighTxMode = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video HighTxMode=%d\n", pAd->VideoTurbine.HighTxMode)); + } + if (RTMPGetKeyParameter("VideoTxPwr", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.TxPwr = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video TxPwr=%d\n", pAd->VideoTurbine.TxPwr)); + } + if (RTMPGetKeyParameter("VideoMCSEnable", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.VideoMCSEnable = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video VideoMCSEnable=%d\n", pAd->VideoTurbine.VideoMCSEnable)); + } + if (RTMPGetKeyParameter("VideoMCS", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.VideoMCS = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video VideoMCS=%d\n", pAd->VideoTurbine.VideoMCS)); + } + if (RTMPGetKeyParameter("VideoTxBASize", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.TxBASize = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video TxBASize=%d\n", pAd->VideoTurbine.TxBASize)); + } + if (RTMPGetKeyParameter("VideoTxLifeTimeMode", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.TxLifeTimeMode = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video TxLifeTimeMode=%d\n", pAd->VideoTurbine.TxLifeTimeMode)); + } + if (RTMPGetKeyParameter("VideoTxLifeTime", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.TxLifeTime = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video TxLifeTime=%d\n", pAd->VideoTurbine.TxLifeTime)); + } + if (RTMPGetKeyParameter("VideoTxRetryLimit", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->VideoTurbine.TxRetryLimit = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Video TxRetryLimit=%d\n", pAd->VideoTurbine.TxRetryLimit)); + } +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* WiFi Mcast Test */ + if (RTMPGetKeyParameter("WiFiMcastTest", tmpbuf, 128, pBuffer, TRUE)) + { + if (strncmp(tmpbuf, "0", 1) == 0) + pAd->CommonCfg.bMcastTest = FALSE; + else if (strncmp(tmpbuf, "1", 1) == 0) + pAd->CommonCfg.bMcastTest = TRUE; + else + pAd->CommonCfg.bMcastTest = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("WiFi Mcast Enable=%d\n", pAd->CommonCfg.bMcastTest)); + } + else + { + pAd->CommonCfg.bMcastTest = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("WiFi Mcast disabled=%d\n", pAd->CommonCfg.bMcastTest)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef SINGLE_SKU + if(RTMPGetKeyParameter("AntGain", tmpbuf, 10, pBuffer, TRUE)) + { + UCHAR AntGain = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.AntGain= AntGain; + + DBGPRINT(RT_DEBUG_TRACE, ("AntGain=%d\n", pAd->CommonCfg.AntGain)); + } + if(RTMPGetKeyParameter("BandedgeDelta", tmpbuf, 10, pBuffer, TRUE)) + { + UCHAR Bandedge = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.BandedgeDelta = Bandedge; + + DBGPRINT(RT_DEBUG_TRACE, ("BandedgeDelta=%d\n", pAd->CommonCfg.BandedgeDelta)); + } +#endif /* SINGLE_SKU */ + + + + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + /* set GPIO pin for wake-up signal */ + if (RTMPGetKeyParameter("WOW_GPIO", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_GPIO(pAd, tmpbuf); + + /* set WOW enable/disable */ + if (RTMPGetKeyParameter("WOW_Enable", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Enable(pAd, tmpbuf); + + /* set delay time for WOW really enable */ + if (RTMPGetKeyParameter("WOW_Delay", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Delay(pAd, tmpbuf); + + /* set GPIO pulse hold time */ + if (RTMPGetKeyParameter("WOW_Hold", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Hold(pAd, tmpbuf); + + /* set wakeup signal type */ + if (RTMPGetKeyParameter("WOW_InBand", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_InBand(pAd, tmpbuf); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +#ifdef MICROWAVE_OVEN_SUPPORT + if (RTMPGetKeyParameter("MO_FalseCCATh", tmpbuf, 10, pBuffer, TRUE)) + Set_MO_FalseCCATh_Proc(pAd, tmpbuf); +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT + if (RTMPGetKeyParameter("SnifferType", tmpbuf, 10, pBuffer, TRUE)) { + pAd->sniffer_ctl.sniffer_type = simple_strtol(tmpbuf, 0, 10); +#ifdef CONFIG_STA_SUPPORT + if(pAd->StaCfg.wdev.if_dev) + set_sniffer_mode(pAd->StaCfg.wdev.if_dev, pAd->sniffer_ctl.sniffer_type); +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("SnifferType = %d\n", pAd->sniffer_ctl.sniffer_type)); + } +#endif /* CONFIG_SNIFFER_SUPPORT */ + + + + }while(0); + + os_free_mem(NULL, tmpbuf); + + return NDIS_STATUS_SUCCESS; +} + +#ifdef MULTIPLE_CARD_SUPPORT +/* record whether the card in the card list is used in the card file*/ +UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD] = {0}; +/* record used card mac address in the card list*/ +static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6]; + +BOOLEAN get_mac_from_eeprom(RTMP_ADAPTER *pAd, UCHAR *mac) +{ + USHORT addr, ee_addr; + INT idx; + + for (ee_addr = 0x04, idx = 0; ee_addr <= 0x08; ee_addr += 2, idx +=2) { + RT28xx_EEPROM_READ16(pAd, ee_addr, addr); + mac[idx] = (UCHAR)(addr & 0xff); + mac[idx + 1] = (UCHAR)(addr >> 8); + } + + return TRUE; +} + + +#ifdef RTMP_FLASH_SUPPORT +#define EEPROM_SEG_IN_NVM 2 /* segments for EEPROM in flash */ +#endif /* RTMP_FLASH_SUPPORT */ + +/* +======================================================================== +Routine Description: + Get card profile path. + +Arguments: + pAd + +Return Value: + TRUE - Find a card profile + FALSE - use default profile + +Note: +======================================================================== +*/ +BOOLEAN RTMP_CardInfoRead( + IN PRTMP_ADAPTER pAd) +{ +#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */ +#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */ +#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */ + +#define LETTER_CASE_TRANSLATE(txt_p, card_id) \ + { UINT32 _len; char _char; \ + for(_len=0; _len Error opening %s\n", CARD_INFO_PATH)); + goto free_resource; + } + + /* card information file exists so reading the card information */ + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); + if (retval < 0) + { + /* read fail */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Read %s error %d\n", CARD_INFO_PATH, -retval)); + } + else + { + /* get card selection method */ + memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE); + card_select_method = MC_SELECT_CARDTYPE; /* default*/ + + if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer, TRUE)) + { + if (strcmp(tmpbuf, "CARDID") == 0) + card_select_method = MC_SELECT_CARDID; + else if (strcmp(tmpbuf, "MAC") == 0) + card_select_method = MC_SELECT_MAC; + else if (strcmp(tmpbuf, "CARDTYPE") == 0) + card_select_method = MC_SELECT_CARDTYPE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> Card Selection = %d\n", card_select_method)); + + /* init*/ + card_free_id = -1; + card_nouse_id = -1; + card_same_mac_id = -1; + card_match_id = -1; + + /* search current card information records*/ + for (card_index=0; card_index Free = %d, Same = %d, NOUSE = %d\n", + card_free_id, card_same_mac_id, card_nouse_id)); + + if ((card_same_mac_id >= 0) && + ((card_select_method == MC_SELECT_CARDID) || + (card_select_method == MC_SELECT_CARDTYPE))) + { + /* same MAC entry is found*/ + card_match_id = card_same_mac_id; + + if (card_select_method == MC_SELECT_CARDTYPE) + { + /* for CARDTYPE*/ + snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDTYPE%s", + card_match_id, RFIC_word); + + if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + /* we found the card ID*/ + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + } + } + } + else + { + /* the card is 1st plug-in, try to find the match card profile*/ + switch(card_select_method) + { + case MC_SELECT_CARDID: /* CARDID*/ + default: + if (card_free_id >= 0) + card_match_id = card_free_id; + else + card_match_id = card_nouse_id; + break; + + case MC_SELECT_MAC: /* MAC*/ +#ifdef RTMP_FLASH_SUPPORT + memcpy(&mac[0], &mac_maybe[segment][0], MAC_ADDR_LEN); +#endif /* RTMP_FLASH_SUPPORT */ + snprintf(card_id_buf, sizeof(card_id_buf), "MAC%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + /* try to find the key word in the card file */ + if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + /* get the row ID (2 ASCII characters) */ + start_ptr -= 2; + card_id_buf[0] = *(start_ptr); + card_id_buf[1] = *(start_ptr+1); + card_id_buf[2] = 0x00; + card_match_id = simple_strtol(card_id_buf, 0, 10); +#ifdef RTMP_FLASH_SUPPORT + if (MC_CardUsed[card_match_id] == 1) + { + /* try again to find the key word in the card file by the other MAC address */ + segment += 1; + memcpy(&mac[0], &mac_maybe[segment][0], MAC_ADDR_LEN); + snprintf(card_id_buf, sizeof(card_id_buf), "MAC%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + /* get the row ID (2 ASCII characters) */ + start_ptr -= 2; + card_id_buf[0] = *(start_ptr); + card_id_buf[1] = *(start_ptr+1); + card_id_buf[2] = 0x00; + card_match_id = simple_strtol(card_id_buf, 0, 10); + } + } +#endif /* RTMP_FLASH_SUPPORT */ + } + break; + + case MC_SELECT_CARDTYPE: /* CARDTYPE*/ + card_nouse_id = -1; + + for(card_index=0; + card_index= 0) + { + /* make up search keyword*/ + switch(card_select_method) + { + case MC_SELECT_CARDID: /* CARDID*/ + snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDID", card_match_id); + break; + + case MC_SELECT_MAC: /* MAC*/ + snprintf(card_id_buf, sizeof(card_id_buf), + "%02dmac%02x:%02x:%02x:%02x:%02x:%02x", + card_match_id, + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + break; + + case MC_SELECT_CARDTYPE: /* CARDTYPE*/ + default: + snprintf(card_id_buf, sizeof(card_id_buf), "%02dcardtype%s", + card_match_id, RFIC_word); + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf)); + + /* read card file path*/ + if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer, TRUE)) + { + if (strlen(tmpbuf) < sizeof(pAd->MC_FileName)) + { + /* backup card information*/ + pAd->MC_RowID = card_match_id; /* base 0 */ + /* + If we are run in Multicard mode, the eeinit shall execute + here instead of NICReadEEPROMParameters() + */ + if (pAd->chipOps.eeinit) + pAd->chipOps.eeinit(pAd); + + get_mac_from_eeprom(pAd, &mac[0]); + MC_CardUsed[card_match_id] = 1; + memcpy(MC_CardMac[card_match_id], mac, sizeof(mac)); + + /* backup card file path*/ + NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf)); + pAd->MC_FileName[strlen(tmpbuf)] = '\0'; + flg_match_ok = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, + ("Card Profile Name = %s\n", pAd->MC_FileName)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Card Profile Name length too large!\n")); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Can not find search key word in card.dat!\n")); + } + + if ((flg_match_ok != TRUE) && + (card_match_id < MAX_NUM_OF_MULTIPLE_CARD)) + { + MC_CardUsed[card_match_id] = 0; + memset(MC_CardMac[card_match_id], 0, sizeof(mac)); + } + } /* if (card_match_id >= 0)*/ + } + + +/* close file*/ +retval = RtmpOSFileClose(srcf); + +free_resource: +RtmpOSFSInfoChange(&osFSInfo, FALSE); +os_free_mem(NULL, buffer); +os_free_mem(NULL, tmpbuf); + +return flg_match_ok; +} +#endif /* MULTIPLE_CARD_SUPPORT */ + + +#ifdef WSC_INCLUDED +void rtmp_read_wsc_user_parms( + PWSC_CTRL pWscControl, + STRING *tmpbuf, + STRING *buffer) +{ + if(RTMPGetKeyParameter("WscManufacturer", tmpbuf, WSC_MANUFACTURE_LEN, buffer,TRUE)) + { + NdisZeroMemory(pWscControl->RegData.SelfInfo.Manufacturer, WSC_MANUFACTURE_LEN); + NdisMoveMemory(pWscControl->RegData.SelfInfo.Manufacturer, tmpbuf, strlen(tmpbuf)); + if(pWscControl->RegData.SelfInfo.Manufacturer[0] != 0x00) + RTMP_SET_FLAG(pWscControl, 0x01); + } + + /*WSC_User_ModelName*/ + if(RTMPGetKeyParameter("WscModelName", tmpbuf, WSC_MODELNAME_LEN, buffer,TRUE)) + { + NdisZeroMemory(pWscControl->RegData.SelfInfo.ModelName, WSC_MODELNAME_LEN); + NdisMoveMemory(pWscControl->RegData.SelfInfo.ModelName, tmpbuf, strlen(tmpbuf)); + if(pWscControl->RegData.SelfInfo.ModelName[0] != 0x00) + RTMP_SET_FLAG(pWscControl, 0x02); + } + + /*WSC_User_DeviceName*/ + if(RTMPGetKeyParameter("WscDeviceName", tmpbuf, WSC_DEVICENAME_LEN, buffer,TRUE)) + { + NdisZeroMemory(pWscControl->RegData.SelfInfo.DeviceName, WSC_DEVICENAME_LEN); + NdisMoveMemory(pWscControl->RegData.SelfInfo.DeviceName, tmpbuf, strlen(tmpbuf)); + if(pWscControl->RegData.SelfInfo.DeviceName[0] != 0x00) + RTMP_SET_FLAG(pWscControl, 0x04); + } + + /*WSC_User_ModelNumber*/ + if(RTMPGetKeyParameter("WscModelNumber", tmpbuf, WSC_MODELNUNBER_LEN, buffer,TRUE)) + { + NdisZeroMemory(pWscControl->RegData.SelfInfo.ModelNumber, WSC_MODELNUNBER_LEN); + NdisMoveMemory(pWscControl->RegData.SelfInfo.ModelNumber, tmpbuf, strlen(tmpbuf)); + if(pWscControl->RegData.SelfInfo.ModelNumber[0] != 0x00) + RTMP_SET_FLAG(pWscControl, 0x08); + } + + /*WSC_User_SerialNumber*/ + if(RTMPGetKeyParameter("WscSerialNumber", tmpbuf, WSC_SERIALNUNBER_LEN, buffer,TRUE)) + { + NdisZeroMemory(pWscControl->RegData.SelfInfo.SerialNumber, WSC_SERIALNUNBER_LEN); + NdisMoveMemory(pWscControl->RegData.SelfInfo.SerialNumber, tmpbuf, strlen(tmpbuf)); + if(pWscControl->RegData.SelfInfo.SerialNumber[0] != 0x00) + RTMP_SET_FLAG(pWscControl, 0x10); + } +} + +void rtmp_read_wsc_user_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + PWSC_CTRL pWscControl; + +#ifdef WSC_AP_SUPPORT + int i=0; + for(i = 0; i < MAX_MBSSID_NUM(pAd); i++) + { + pWscControl = &pAd->ApCfg.MBSSID[i].WscControl; + rtmp_read_wsc_user_parms(pWscControl, tmpbuf, buffer); +} +#ifdef APCLI_SUPPORT + pWscControl = &pAd->ApCfg.ApCliTab[0].WscControl; + rtmp_read_wsc_user_parms(pWscControl, tmpbuf, buffer); +#endif /* APCLI_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + pWscControl = &pAd->StaCfg.WscControl; + rtmp_read_wsc_user_parms(pWscControl, tmpbuf, buffer); +#endif /* WSC_STA_SUPPORT */ + + +} +#endif/*WSC_INCLUDED*/ + + +#ifdef SINGLE_SKU_V2 +NDIS_STATUS RTMPSetSingleSKUParameters( + IN RTMP_ADAPTER *pAd, CHAR *sku_path) +{ + PSTRING buffer; + PSTRING readline, token; + RTMP_OS_FD srcf; + INT retval; + PSTRING ptr; + int index, i; + CH_POWER *StartCh = NULL; + UCHAR MaxPwr; + UCHAR channel, *temp; + RTMP_OS_FS_INFO osFSInfo; + + DlListInit(&pAd->SingleSkuPwrList); + + /* init */ + os_alloc_mem(NULL, (UCHAR **)&buffer, MAX_INI_BUFFER_SIZE); + if (buffer == NULL) + return FALSE; + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + pAd->bOpenFileSuccess = FALSE; + pAd->bSingleSkuDebug = FALSE; + + /* open card information file */ + srcf = RtmpOSFileOpen(sku_path, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) { + /* card information file does not exist */ + DBGPRINT(RT_DEBUG_ERROR, ("--> Error opening %s\n", sku_path)); + goto free_resource; + } + +#ifdef RTMP_INTERNAL_TX_ALC + if (pAd->TxPowerCtrl.bInternalTxALC != TRUE) +#endif /* RTMP_INTERNAL_TX_ALC */ + { + } + + /* card information file exists so reading the card information */ + NdisZeroMemory(buffer, MAX_INI_BUFFER_SIZE); + retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); + + if (retval < 0) { + /* read fail */ + DBGPRINT(RT_DEBUG_ERROR,("--> Read %s error %d\n", sku_path, -retval)); + } else { + for (readline = ptr = buffer, index=0; (ptr = strchr(readline, '\n')) != NULL; readline = ptr + 1, index++) + { + *ptr = '\0'; + + if (readline[0] == '#') + continue; + + if (!strncmp(readline, "ch", 2)) { + CH_POWER *pwr = NULL; + os_alloc_mem(NULL, (UCHAR **)&pwr, sizeof(*pwr)); + NdisZeroMemory(pwr, sizeof(*pwr)); + + token= rstrtok(readline +2 ," "); + channel = simple_strtol(token, 0, 10); + pwr->StartChannel = channel; + + if (pwr->StartChannel <= 14) { + for (i = 0; i < SINGLE_SKU_TABLE_CCK_LENGTH; i++) + { + token = rstrtok(NULL ," "); + if (token == NULL) + break; + pwr->PwrCCK[i] = simple_strtol(token, 0, 10) * 2; + } + } + + for (i = 0; i < SINGLE_SKU_TABLE_OFDM_LENGTH; i++) + { + token = rstrtok(NULL ," "); + if (token == NULL) + break; + pwr->PwrOFDM[i] = simple_strtol(token, 0, 10) *2; + } + + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + token = rstrtok(NULL ," "); + if (token == NULL) + break; + pwr->PwrHT20[i] = simple_strtol(token, 0, 10) *2; + } + + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + token = rstrtok(NULL ," "); + if (token == NULL) + break; + pwr->PwrHT40[i] = simple_strtol(token, 0, 10) *2; + } + +#ifdef DOT11_VHT_AC + for (i = 0; i < SINGLE_SKU_TABLE_VHT_LENGTH; i++) + { + token = rstrtok(NULL ," "); + if (token == NULL) + break; + pwr->PwrVHT80[i] = simple_strtol(token, 0, 10) *2; + } +#endif /* DOT11_VHT_AC */ + + if (StartCh == NULL) { + StartCh = pwr; + DlListAddTail(&pAd->SingleSkuPwrList, &pwr->List); + } else { + BOOLEAN isSame = TRUE; + + for (i = 0; i < SINGLE_SKU_TABLE_CCK_LENGTH; i++) + { + if (StartCh->PwrCCK[i] != pwr->PwrCCK[i]) { + isSame = FALSE; + break; + } + } + + if (isSame == TRUE) { + for (i = 0; i < SINGLE_SKU_TABLE_OFDM_LENGTH; i++) + { + if (StartCh->PwrOFDM[i] != pwr->PwrOFDM[i]) { + isSame = FALSE; + break; + } + } + } + + if (isSame == TRUE) { + for (i = 0 ;i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + if (StartCh->PwrHT20[i] != pwr->PwrHT20[i]) { + isSame = FALSE; + break; + } + } + } + + if (isSame == TRUE) { + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + { + if (StartCh->PwrHT40[i] != pwr->PwrHT40[i]) { + isSame = FALSE; + break; + } + } + } + +#ifdef DOT11_VHT_AC + if (isSame == TRUE) { + for (i = 0; i < SINGLE_SKU_TABLE_VHT_LENGTH; i++) + { + if (StartCh->PwrVHT80[i] != pwr->PwrVHT80[i]) { + isSame = FALSE; + break; + } + } + } +#endif /* DOT11_VHT_AC */ + + if (isSame == TRUE) { + os_free_mem(NULL, pwr); + } else { + StartCh = pwr; + DlListAddTail(&pAd->SingleSkuPwrList, &StartCh->List); + pwr = NULL; + } + } + + StartCh->num ++; + os_alloc_mem(pAd, (PUCHAR *)&temp, StartCh->num); + if (StartCh->Channel != NULL) { + NdisMoveMemory(temp, StartCh->Channel, StartCh->num-1); + os_free_mem(pAd, StartCh->Channel); + } + + StartCh->Channel = temp; + StartCh->Channel[StartCh->num-1] = channel; + } + } + } + + CH_POWER *ch, *ch_temp; + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + int i; + DBGPRINT(RT_DEBUG_TRACE,("start ch = %d, ch->num = %d\n", ch->StartChannel, ch->num)); + + DBGPRINT(RT_DEBUG_TRACE, ("Channel: ")); + for (i = 0; i < ch->num; i++) + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->Channel[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("CCK: ")); + for (i = 0; i < SINGLE_SKU_TABLE_CCK_LENGTH; i++) + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrCCK[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("OFDM: ")); + for (i = 0; i < SINGLE_SKU_TABLE_OFDM_LENGTH; i++) + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrOFDM[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("HT20: ")); + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + DBGPRINT(RT_DEBUG_TRACE, ("%d ", ch->PwrHT20[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("HT40: ")); + for (i = 0; i < SINGLE_SKU_TABLE_HT_LENGTH; i++) + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrHT40[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("VHT80: ")); + for (i = 0; i < SINGLE_SKU_TABLE_VHT_LENGTH; i++) + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrVHT80[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + } + + pAd->bOpenFileSuccess = TRUE; + + /* close file */ + retval = RtmpOSFileClose(srcf); + +free_resource: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + os_free_mem(NULL, buffer); + + return TRUE; +} + +#endif /* SINGLE_SKU_V2 */ + +UINT32 RalinkRate_Legacy [] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; +UINT32 RalinkRate_HT_1NSS[Rate_BW_MAX][Rate_GI_MAX][Rate_MCS] = +{ + { + {13, 26, 39, 52, 78, 104, 117, 130, 0, 0},{14, 29, 43, 57, 87, 115, 130, 144, 0, 0} /*20MHz, 800ns & 400 ns GI, MCS0~9*/ + }, + { + {27, 54, 81, 108, 162, 216, 243, 270, 0, 0},{30, 60, 90, 120, 180, 240, 270, 300, 0, 0} /*40MHz, 800ns & 400 ns GI, MCS0~9*/ + }, + { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /*80MHz, 800ns & 400 ns GI, MCS0~9*/ + }, +}; +UINT32 RalinkRate_VHT_1NSS[Rate_BW_MAX][Rate_GI_MAX][Rate_MCS] = +{ + { + {13, 26, 39, 52, 78, 104, 117, 130, 156, 0} , {14, 29, 43, 57, 87, 115, 130, 144, 173, 0} /*20MHz, 800ns & 400 ns GI, MCS0~9*/ + }, + { + {27, 54, 81, 108, 162, 216, 243, 270, 324, 360}, {30, 60, 90, 120, 180, 240, 270, 300, 360, 400} /*40MHz, 800ns & 400 ns GI, MCS0~9*/ + }, + { + {59, 117, 176, 234, 351, 468, 527, 585, 702, 780}, {65, 130, 195, 260, 390, 520, 585, 650, 780, 867} /*80MHz, 800ns & 400 ns GI, MCS0~9*/ + }, +}; + +UINT8 newRateGetAntenna(UINT8 MCS, UINT8 PhyMode) +{ + if(PhyMode >= MODE_VHT) + return ((MCS>>4) + 1); + else + return ((MCS>>3) + 1); +} + + + +void print_RalinkRate_HT(void) +{ + UINT32 i,j,k; + + for(i=0;i < Rate_BW_MAX;i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("======= BW : %d ============\n", i)); + for(j=0;j < Rate_GI_MAX;j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("======= GI : %d ============\nMCS: ", j)); + for(k=0;k < Rate_MCS;k++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d, ", RalinkRate_HT_1NSS[i][j][k])); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n======= END GI : %d ============\n", j)); + } + DBGPRINT(RT_DEBUG_TRACE, ("======= END BW : %d ============\n", i)); + } + + for(i=0;i < Rate_BW_MAX;i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("======= BW : %d ============\n", i)); + for(j=0;j < Rate_GI_MAX;j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("======= GI : %d ============\nMCS: ", j)); + for(k=0;k < Rate_MCS;k++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d, ", RalinkRate_VHT_1NSS[i][j][k])); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n======= END GI : %d ============\n", j)); + } + DBGPRINT(RT_DEBUG_TRACE, ("======= END BW : %d ============\n", i)); + } +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_radar.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_radar.c new file mode 100644 index 000000000..1e16cf81f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_radar.c @@ -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; iChannelListNum; 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; iChannelListNum; 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; iChannelListNum; 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) */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_rf_cal.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_rf_cal.c new file mode 100644 index 000000000..f093e9e11 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_rf_cal.c @@ -0,0 +1,2996 @@ +/* + *************************************************************************** + * 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: + cmm_rf_cal.c + + Abstract: + RF calibration and profile related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Arvin Tai 2012/05/02 +*/ + +#include "rt_config.h" + +REG_PAIR RT6352_VGA_TABLE[] = +{/* Gain(dB), BBP_R66 */ + {0, 0x10}, + {2, 0x14}, + {4, 0x18}, + {6, 0x1C}, + {8, 0x20}, + {10, 0x30}, + {12, 0x34}, + {14, 0x38}, + {16, 0x3C}, + {18, 0x40}, + {20, 0x44}, + {22, 0x60}, + {24, 0x64}, + {26, 0x68}, + {28, 0x6C}, + {30, 0x70}, + {32, 0x74}, + {34, 0x78}, + {36, 0x7C}, +}; + +REG_PAIR RT6352_RFR3R4_TABLE[] = +{/* Gain(dB), RF_R3R4 */ + { 0, 0x4 }, + { 2, 0x5 }, + { 4, 0x6 }, + { 6, 0x7 }, + { 8, 0x8 }, + {10, 0xc }, + {12, 0xd }, + {14, 0xe }, + {16, 0xf }, + {18, 0x10}, + {20, 0x11}, + {22, 0x18}, + {24, 0x19}, + {26, 0x1a}, + {28, 0x1b}, + {30, 0x1c}, + {32, 0x1d}, + {34, 0x1e}, + {36, 0x1f}, +}; + + +UCHAR RT6352_VGA_TABLE_PARMS = (sizeof(RT6352_VGA_TABLE) / sizeof(REG_PAIR)); + +INT32 CalcRCalibrationCode( + IN PRTMP_ADAPTER pAd, + IN INT32 D1, + IN INT32 D2) +{ + INT32 CalCode; + + CalCode = ((D2 - D1) * 1000) / 43; + if((CalCode%10) >= 5) + CalCode += 10; + + CalCode = (CalCode / 10); + + return CalCode; +} + +/**************************************************************************** + * + * VOID R Calibraton + * + ****************************************************************************/ + +VOID R_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UINT32 saveMacSysCtrl; + UCHAR saveRfB0R1, saveRfB0R34, saveRfB0R35; + UCHAR saveRfB5R4, saveRfB5R17, saveRfB5R18; + UCHAR saveRfB5R19, saveRfB5R20; + UCHAR saveBBPR22, saveBBPR47, saveBBPR49; + UCHAR byteValue = 0; + INT32 RCalCode; + UCHAR R_Cal_Code = 0; + CHAR D1 = 0, D2 = 0; + UCHAR RFValue; + UINT32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG; + + /* Save RF Register */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &saveRfB0R1); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R34, &saveRfB0R34); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R35, &saveRfB0R35); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R4); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &saveRfB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &saveRfB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &saveRfB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &saveRfB5R20); + + /* save BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &saveBBPR22); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &saveBBPR47); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &saveBBPR49); + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0, &MAC_RF_BYPASS0); + RTMP_IO_READ32(pAd, RF_CONTROL0, &MAC_RF_CONTROL0); + RTMP_IO_READ32(pAd, PWR_PIN_CFG, &MAC_PWR_PIN_CFG); + + { + UINT32 macCfg, macStatus; + UINT32 MTxCycle, MRxCycle; + ULONG stTime, mt_time, mr_time; + + /* Disable MAC Tx and MAC Rx and wait MAC Tx/Rx status in idle state */ + /* MAC Tx */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &macCfg); + macCfg &= (~0x04); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, macCfg); + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x1) + RtmpusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&mt_time); + mt_time -= stTime; + if (MTxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop MTx,macStatus=0x%x!\n", + __FUNCTION__, MTxCycle, mt_time, macStatus)); + } + + /* MAC Rx */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &macCfg); + macCfg &= (~0x08); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, macCfg); + for (MRxCycle = 0; MRxCycle < 10000; MRxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x2) + RtmpusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&mr_time); + mr_time -= stTime; + if (MRxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop MRx, macStatus=%d!\n", + __FUNCTION__, MRxCycle, mr_time, macStatus)); + } + } + + /* RF bypass MAC */ + RFValue = (MAC_RF_BYPASS0 | 0x3004); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, RFValue); + RFValue = (MAC_RF_CONTROL0 & (~0x3002)); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, RFValue); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0x83); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x20); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R34, 0x13); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x00); + + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x1); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x80); + RtmpusecDelay(100); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &byteValue); + if (byteValue > 128) + D1= byteValue - 256; + else + D1 = (CHAR)byteValue; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x0); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x01); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x80); + RtmpusecDelay(100); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &byteValue); + if (byteValue > 128) + D2= byteValue - 256; + else + D2 = (CHAR)byteValue; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x0); + + RCalCode = CalcRCalibrationCode(pAd, D1, D2); + if (RCalCode < 0) + R_Cal_Code = 256 + RCalCode; + else + R_Cal_Code = (UCHAR)RCalCode; + + DBGPRINT(RT_DEBUG_ERROR, ("D1 = %d, D2 = %d, CalCode = %d !!!\n", D1, D2, RCalCode)); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R07, R_Cal_Code); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x00); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &byteValue); + byteValue |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, byteValue); + RtmpOsMsDelay(1); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &byteValue); + byteValue &= (~0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, byteValue); + + /* Restore RF Register */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, saveRfB0R1); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R34, saveRfB0R34); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, saveRfB0R35); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R4); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, saveRfB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, saveRfB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, saveRfB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, saveRfB5R20); + + /* Restore BBP registers */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, saveBBPR22); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, saveBBPR47); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, saveBBPR49); + + /* Restore registers */ + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MAC_RF_BYPASS0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MAC_RF_CONTROL0); + + /* Return to normal mode */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, MAC_PWR_PIN_CFG); +} + +INT Set_TestRxIQCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("TestRxIQCalibration !!!\n")); + RXIQ_Calibration(pAd); + + return TRUE; +} + +INT Set_TestLoftTxIQCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("TestLOFTTxIQCalibration !!!\n")); + pAd->bCalibrationDone = FALSE; + LOFT_IQ_Calibration(pAd); + pAd->bCalibrationDone = TRUE; + + return TRUE; +} + +VOID RtmpKickOutHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPrepareContent, + IN BOOLEAN bTransmit) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + TXWI_STRUC NullTxWI, *pTxWI = NULL; + PUCHAR pNullFrame; + NDIS_STATUS NState; + PHEADER_802_11 pNullFr; + ULONG Length; + UCHAR *ptr; + UINT i; + UINT32 longValue, macStatus; + USHORT k_count = 0; + HTTRANSMIT_SETTING MlmeTransmit; + + if (bPrepareContent) + { + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pNullFrame); + + NdisZeroMemory(pNullFrame, 48); + + if (NState == NDIS_STATUS_SUCCESS) + { + pTxWI = &NullTxWI; + NdisZeroMemory(pTxWI, TXWISize); + + pNullFr = (PHEADER_802_11) pNullFrame; + Length = sizeof(HEADER_802_11); + + pNullFr->FC.Type = FC_TYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_DATA_NULL; + pNullFr->FC.ToDs = 0; + pNullFr->FC.FrDs = 1; + + COPY_MAC_ADDR(pNullFr->Addr1, BROADCAST_ADDR); + COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pNullFr->Addr3, pAd->CurrentAddress); + + pNullFr->FC.PwrMgmt = 0; + + pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, pAd->CommonCfg.TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + pNullFr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + + MlmeTransmit.word = 0; + MlmeTransmit.field.MCS = 15; + MlmeTransmit.field.MODE = MODE_HTMIX; + MlmeTransmit.field.BW = 0; + + RTMPWriteTxWI(pAd, + pTxWI, + FALSE, + FALSE, + FALSE, + FALSE, + FALSE, + TRUE, + 0, + 1, + Length, + 15, + 0, + 15, + IFS_HTTXOP, + &MlmeTransmit); + + pTxWI->TXWI_O.MCS = 15; + pTxWI->TXWI_O.PHYMODE = MODE_HTMIX; + pTxWI->TXWI_O.BW = 0; + + ptr = (PUCHAR)&NullTxWI; + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif + for (i=0; i < TXWISize; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + + RTMP_IO_WRITE32(pAd, HW_CS_CTS_BASE + i, longValue); + + ptr += 4; + } + + ptr = pNullFrame; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + for (i= 0; i< Length; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + + RTMP_IO_WRITE32(pAd, HW_CS_CTS_BASE + TXWISize+ i, longValue); + + ptr += 4; + } + } + + if (pNullFrame) + MlmeFreeMemory(pAd, pNullFrame); + } + + if (bTransmit) + { + /* kick NULL frame #0 */ + RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x80); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 200; k_count++) + { + RTMP_IO_READ32(pAd, PBF_CTRL, &macStatus); + if (macStatus & 0x80) + { + RtmpusecDelay(100); + } + else + { + break; + } + } + + if (k_count == 200) + { + DBGPRINT(RT_DEBUG_TRACE, ("Wait Null Frame SendOut to MAX !!!\n")); + } + } + + return; +} + +/**************************************************************************** + * + * VOID DPD Calibraton + * + ****************************************************************************/ + +/* (Workaround for IQ swap introduced AM-PM inversion) + Multiply the AM-PM in LUTs by -1 +*/ +VOID DPD_IQ_Swap_AM_PM_Inversion( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + USHORT k_count = 0, PM_inv_upper = 0, PM_inv_lower = 0; + SHORT PM = 0, PM_inv = 0; + UCHAR PM_upper = 0, PM_lower = 0; + + if (AntIdx == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x02); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x04); + + /* Read out AM-PM one by one, multiply by (-1) and write it back */ + for (k_count = 0; k_count < 64; k_count++) + { + /* Read out the AM-PM value through BBP registers */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 1)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &PM_upper); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 2)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &PM_lower); + PM = (PM_upper * 256) + PM_lower; + + /* unsigned to signed conversion */ + if (PM > 512) + PM -= 1024; + + /* Invert the AM-PM value */ + PM_inv = PM * (-1); + + /* Signed to unsigned conversion */ + if(PM_inv < 0) + PM_inv += 1024; + + DBGPRINT(RT_DEBUG_WARN, ("PM (%d), PM_inv (%d)\n", PM, PM_inv)); + + /* Write back the AM-PM value through BBP registers */ + PM_inv_upper = (PM_inv / 256); + PM_inv_lower = (PM_inv % 256); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 1)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, PM_inv_upper); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 2)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, PM_inv_lower); + + } + + return; +} + +VOID DPD_AM_AM_LUT_Scaling( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + USHORT k_count = 0; + UCHAR AM_temp = 0, AM_scaling = 0; + SHORT AM_Dealta = 0; + UINT32 check_loop = 0; + UCHAR scaling_vector[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10}; + + for (check_loop = 0; check_loop < 2; check_loop++) + { + if (AntIdx == 0) + { + DBGPRINT(RT_DEBUG_INFO, ("DPD Scaling for TX0 !!!\n")); + if (check_loop == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x02); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("DPD Scaling for TX1 !!!\n")); + if (check_loop == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x04); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x05); + } + + /* Read out AM-PM one by one, multiply by (-1) and write it back */ + for (k_count = 0; k_count < 64; k_count++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 3)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &AM_temp); + AM_Dealta = AM_temp - 128; + if (scaling_vector[k_count] > 0) + { + if (AM_Dealta > 0) + AM_scaling = 128 + ((AM_Dealta * scaling_vector[k_count]) / 10); + else + AM_scaling = 128; + } + else + AM_scaling = 128; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, AM_scaling); + RtmpusecDelay(100); + + DBGPRINT(RT_DEBUG_INFO, ("(%d). AM_temp (%d), AM_Dealta (%d), AM_scaling (%d)\n", k_count, AM_temp, AM_Dealta, AM_scaling)); + } + } +} + +UCHAR DPD_Calibration( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + UCHAR index, Max_Retry = 0, Pass_Thres = 0,byteValue = 0; + UINT32 macStatus, macValue; + UINT32 saveMacSysCtrl, saveTxPinCfg, saveTxAlgCfg0; + USHORT AM_SUM =0, AM_10 = 0, k_count = 0; + BOOLEAN DPD_Cal_success = FALSE, bNeedDoDPD = TRUE; + UCHAR saveBbpR27, saveBbpR65; + UCHAR saveBbpR241, saveBbpR242, saveBbpR244; + UCHAR saveRfB0R1, saveRfB5R1, saveRfB7R1; + UCHAR saveRfB4R11, saveRfB4R13; + UCHAR saveRfB6R11, saveRfB6R13; + UCHAR saveRfB4R19, saveRfB4R21, saveRfB4R22; + UCHAR saveRfB5R17, saveRfB5R18, saveRfB5R19, saveRfB5R20; + UCHAR saveRfB6R19, saveRfB6R21, saveRfB6R22; + UCHAR saveRfB7R17, saveRfB7R18, saveRfB7R19, saveRfB7R20; + UCHAR saveRfB5R3, saveRfB5R4; + UCHAR saveRfB7R3, saveRfB7R4; + UCHAR VGA_Upper_Bound, VGA_Lower_Bound, AM_63 = 0, VGA_code = 0; + UCHAR saveBbpR159;//, BBPValue; + CHAR VGA_code_idx = 0, target_power, delta_power; + INT32 txALC_init = 0, txALC_limit = 0; + INT32 temp_comp, tx_alc_txwi = 0; + INT32 txvga2, txvga3, mac_gain_atten; + INT32 gain_atten_bb = 0, gain_atten_rf = 0, txALC_req = 0; + INT32 txALC_req_at, txALC_req_skip2, txALC_req_skip3; + INT32 txALC_req_sat = 0; + UINT32 macValue_Tx_Cfg0 = 0,macValue_2nd, check_loop = 0; + BOOLEAN bInternalTxALC = FALSE; + + /* init base power by e2p target power */ + target_power = ((pAd->E2p_D0_Value & 0xFF) == 0xFF) ? 0x1E : (pAd->E2p_D0_Value & 0x3F); + + switch (AntIdx) + { + case 0: + /* Compute the corresponding signal values + Do exactly what TXALC does: + */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + txALC_init = (macValue & 0x0000003F); + txALC_limit = (macValue & 0x003F0000) >> 16; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + temp_comp = (macValue & 0x0000003F); + if ((temp_comp & 0x20) == 0x20) + temp_comp -= 64; + + tx_alc_txwi = 0; + + RTMP_IO_READ32(pAd, TX_ALC_VGA3, &macValue); + txvga2 = (macValue & 0x001F0000) >> 16; + txvga3 = (macValue & 0x0000001F); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + mac_gain_atten = (macValue & 0x00300000) >> 20; + + if(mac_gain_atten == 1) + { + RTMP_IO_READ32(pAd, TX0_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x00001F00) >> 8; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX0_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x00007F00) >> 8; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 2) + { + RTMP_IO_READ32(pAd, TX0_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x001F0000) >> 16; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX0_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x007F0000) >> 16; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 3) + { + RTMP_IO_READ32(pAd, TX0_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x1F000000) >> 24; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX0_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x7F000000) >> 24; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + + txALC_req = txALC_init + temp_comp + tx_alc_txwi; + + if(txALC_req >= txALC_limit) + txALC_req = txALC_limit; + + if(txALC_req < 0) + txALC_req_at = txALC_req - gain_atten_bb - gain_atten_rf; + else + txALC_req_at = txALC_req; + + if(txALC_req_at > 23) + txALC_req_skip2 = txALC_req_at + txvga2; + else + txALC_req_skip2 = txALC_req_at; + + if(txALC_req_skip2 > 35) + txALC_req_skip3 = txALC_req_skip2 + txvga3; + else + txALC_req_skip3 = txALC_req_skip2; + + if(txALC_req_skip3 < 0) + txALC_req_sat = 0; + else if(txALC_req_skip3 > 47) + txALC_req_sat = 47; + else + txALC_req_sat = txALC_req_skip3; + + + // no dpd when power is less 15 dBm or greater 20 dBm + bInternalTxALC = FALSE; +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->bAutoTxAlc == TRUE) + bInternalTxALC = TRUE; + } + else +#endif /* RALINK_ATE */ + { + if(pAd->TxPowerCtrl.bInternalTxALC == TRUE) + bInternalTxALC = TRUE; + } +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_INTERNAL_TX_ALC + if(bInternalTxALC == TRUE) + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + target_power = (macValue & 0x3F); + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { +#ifdef RALINK_ATE + if (!ATE_ON(pAd)) +#endif /* RALINK_ATE */ + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + delta_power = (macValue & 0x3F); + delta_power = (delta_power & 0x20) ? delta_power - 0x40 : delta_power; + + target_power += delta_power; + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + } + break; + + case 1: + /* Compute the corresponding signal values + Do exactly what TXALC does: + */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + txALC_init = (macValue & 0x00003F00) >> 8; + txALC_limit = (macValue & 0x3F000000) >> 24; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + temp_comp = (macValue & 0x0000003F); + if ((temp_comp & 0x20) == 0x20) + temp_comp -= 64; + + tx_alc_txwi = 0; + + RTMP_IO_READ32(pAd, TX_ALC_VGA3, &macValue); + txvga2 = (macValue & 0x1F000000) >> 24; + txvga3 = (macValue & 0x00001F00) >> 8; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + mac_gain_atten = (macValue & 0x00C00000) >> 22; + + if(mac_gain_atten == 1) + { + RTMP_IO_READ32(pAd, TX1_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x00001F00) >> 8; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX1_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x00007F00) >> 8; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 2) + { + RTMP_IO_READ32(pAd, TX1_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x001F0000) >> 16; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX1_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x007F0000) >> 16; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 3) + { + RTMP_IO_READ32(pAd, TX1_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x1F000000) >> 24; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX1_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x7F000000) >> 24; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + + txALC_req = txALC_init + temp_comp + tx_alc_txwi; + + if(txALC_req >= txALC_limit) + txALC_req = txALC_limit; + + if(txALC_req < 0) + txALC_req_at = txALC_req - gain_atten_bb - gain_atten_rf; + else + txALC_req_at = txALC_req; + + if(txALC_req_at > 23) + txALC_req_skip2 = txALC_req_at + txvga2; + else + txALC_req_skip2 = txALC_req_at; + + if(txALC_req_skip2 > 35) + txALC_req_skip3 = txALC_req_skip2 + txvga3; + else + txALC_req_skip3 = txALC_req_skip2; + + if(txALC_req_skip3 < 0) + txALC_req_sat = 0; + else if(txALC_req_skip3 > 47) + txALC_req_sat = 47; + else + txALC_req_sat = txALC_req_skip3; + + // no dpd when power is less 15 dBm or greater 20 dBm + bInternalTxALC = FALSE; +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->bAutoTxAlc == TRUE) + bInternalTxALC = TRUE; + } + else +#endif /* RALINK_ATE */ + { + if(pAd->TxPowerCtrl.bInternalTxALC == TRUE) + bInternalTxALC = TRUE; + } +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_INTERNAL_TX_ALC + if(bInternalTxALC == TRUE) + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + target_power = (macValue & 0x3F); + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { +#ifdef RALINK_ATE + if (!ATE_ON(pAd)) +#endif /* RALINK_ATE */ + { + /* for single sku */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + delta_power = (macValue & 0x3F); + delta_power = (delta_power & 0x20) ? delta_power - 0x40 : delta_power; + + target_power += delta_power; + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + } + break; + + default: + break; + } + + if (bNeedDoDPD == FALSE) + { + DPD_Cal_success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, + ("Don't need do DPD Calibration !!!, bInternalTxALC = %u\n", + bInternalTxALC)); + + return 0; + } + + if(AntIdx == 0) + { + if((pAd->Tx0_DPD_ALC_tag0 == 0) && (pAd->Tx0_DPD_ALC_tag1 == 0)) + pAd->Tx0_DPD_ALC_tag1 = pAd->Tx0_DPD_ALC_tag1; + else if((txALC_req_sat <= (pAd->Tx0_DPD_ALC_tag1 | 0x3)) && (txALC_req_sat >= (pAd->Tx0_DPD_ALC_tag0 & (~0x3)))) + { + DPD_Cal_success = FALSE; + return 1; + } + } + else + { + if((pAd->Tx1_DPD_ALC_tag0 == 0) && (pAd->Tx1_DPD_ALC_tag1 == 0)) + pAd->Tx1_DPD_ALC_tag1 = pAd->Tx1_DPD_ALC_tag1; + else if((txALC_req_sat <= (pAd->Tx1_DPD_ALC_tag1 | 0x3)) && (txALC_req_sat >= (pAd->Tx1_DPD_ALC_tag0 & (~0x3)))) + { + DPD_Cal_success = FALSE; + return 1; + } + } + + /* Save MAC SYS CTRL registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + + /* Save TX PIN CFG registers */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &saveTxPinCfg); + + /* Save TX_ALG_CFG_0 registers */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &saveTxAlgCfg0); + + /* Save BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &saveBbpR27); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &saveBbpR65); + + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R140); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &saveBbpR159); + + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R241, &saveBbpR241); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R242, &saveBbpR242); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R242, &saveBbpR242); + } + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R244, &saveBbpR244); + + /* Save RF registers */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &saveRfB0R1); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R11, &saveRfB4R11); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R13, &saveRfB4R13); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R19, &saveRfB4R19); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R21, &saveRfB4R21); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R22, &saveRfB4R22); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &saveRfB5R1); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &saveRfB5R3); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R4); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &saveRfB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &saveRfB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &saveRfB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &saveRfB5R20); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R11, &saveRfB6R11); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R13, &saveRfB6R13); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R19, &saveRfB6R19); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R21, &saveRfB6R21); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R22, &saveRfB6R22); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R01, &saveRfB7R1); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &saveRfB7R3); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R04, &saveRfB7R4); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R17, &saveRfB7R17); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R18, &saveRfB7R18); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R19, &saveRfB7R19); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R20, &saveRfB7R20); + + if (AntIdx == 0) + { + /* Setup the MAC to Transmit-Idle Mode through MAC registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x001C0020); + + /* Connect RF loopback through MAC registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x41); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R11, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R13, 0x3C); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xF1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0xA1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x01); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, 0xA0); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R21, 0x12); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R22, 0xA1); + } + else + { + /* Setup the MAC to Transmit-Idle Mode through MAC registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x001C0080); + + /* Connect RF loopback through MAC registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x42); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R11, 0x51); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R13, 0x3C); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, 0xF1); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, 0xA1); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, 0x01); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, 0xA0); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R21, 0x12); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R22, 0xA1); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue_Tx_Cfg0); + if(AntIdx == 0) + { + macValue_2nd = macValue_Tx_Cfg0 & 0x3f; + if((txALC_req_sat & 0x3) > 1) + { + pAd->Tx0_DPD_ALC_tag1 = txALC_req_sat + 4; + pAd->Tx0_DPD_ALC_tag0 = txALC_req_sat; + macValue_2nd = macValue_2nd + 4; + } + else + { + pAd->Tx0_DPD_ALC_tag1 = txALC_req_sat; + pAd->Tx0_DPD_ALC_tag0 = txALC_req_sat - 4; + macValue_2nd = macValue_2nd - 4; + } + macValue_2nd = macValue_2nd | (macValue_Tx_Cfg0 & (~0x3f)); + } + else + { + macValue_2nd = (macValue_Tx_Cfg0 >> 8) & 0x3f; + if((txALC_req_sat & 0x3) > 1) + { + pAd->Tx1_DPD_ALC_tag1 = txALC_req_sat + 4; + pAd->Tx1_DPD_ALC_tag0 = txALC_req_sat; + macValue_2nd = macValue_2nd + 4; + } + else + { + pAd->Tx1_DPD_ALC_tag1 = txALC_req_sat; + pAd->Tx1_DPD_ALC_tag0 = txALC_req_sat - 4; + macValue_2nd = macValue_2nd - 4; + } + macValue_2nd = (macValue_2nd << 8) | (macValue_Tx_Cfg0 & (~0x3f00)); + } + + if(AntIdx == 0) { + pAd->Tx0_DPD_ALC_tag0_flag = 0x0; + pAd->Tx0_DPD_ALC_tag1_flag = 0x0; + } + else { + pAd->Tx1_DPD_ALC_tag0_flag = 0x0; + pAd->Tx1_DPD_ALC_tag1_flag = 0x0; + } + + for (check_loop = 0; check_loop < 2; check_loop++) + { + if(check_loop == 0) + { + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, macValue_Tx_Cfg0); + } + else + { + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, macValue_2nd); + } + /* Disable Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 1000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + + if (k_count == 1000) + { + DBGPRINT(RT_DEBUG_ERROR, ("\nWait MAC Status to MAX !!!\n")); + } + + /* Transmit packet */ + /* ====================================== */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x04); + RtmpKickOutHwNullFrame(pAd, FALSE, TRUE); + + /* Disable Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 500; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + { + RtmpusecDelay(100); + } + else + { + break; + } + } + + if (k_count == 500) + { + DBGPRINT(RT_DEBUG_ERROR, ("\nWait MAC Status to MAX !!!\n")); + } + /* Set BBP DPD parameters through MAC registers */ + if (AntIdx == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x10); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x10); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R109, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R110, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, 0x39); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x03); + + if (AntIdx == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x41); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x21); + } + + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, 0x00); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, 0x10); + } + + Max_Retry = DPD_CAL_MAX_RETRY; + Pass_Thres = DPD_CAL_PASS_THRES; + + /* Init VGA Gain */ + VGA_code_idx = 5; + VGA_Upper_Bound = 245; + VGA_Lower_Bound = 180; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + for (index = 0; index < Max_Retry; index++) + { + while ((VGA_code_idx >= 0) && (VGA_code_idx <= 18)) + { + VGA_code = RT6352_RFR3R4_TABLE[VGA_code_idx].Value; + + DBGPRINT(RT_DEBUG_INFO, ("RF Gain(%d), RF R3/4(%x)\n", RT6352_RFR3R4_TABLE[VGA_code_idx].Register, VGA_code)); + if (AntIdx == 0) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, (0x20 | VGA_code)); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, (0x20 | VGA_code)); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, (0x20 | VGA_code)); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, (0x20 | VGA_code)); + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x08); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + + if (k_count == 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("2. Wait MAC Status to MAX !!!\n")); + } + + /* Turn on debug tone and start DPD calibration through MAC registers */ + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x11); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x2A); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x01); + if (AntIdx == 0) + { + if (check_loop == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x80); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x81); + } + } + else + { + if (check_loop == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x82); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x83); + } + } + + /* Wait up to 1ms for capture buffer to fill */ + for (k_count = 0; k_count < 1000; k_count++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + if ((byteValue & 0x80) == 0) + break; + RtmpusecDelay(50); + } + + if (k_count == 1000) + DBGPRINT(RT_DEBUG_ERROR, ("Wait capture buffer to MAX !!!\n")); + + /* Turn off debug tone */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x00); + + /* Check if VGA is appropriate (signal has large swing but not clipped in ADC) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0xFF); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_63 = byteValue; + DBGPRINT(RT_DEBUG_INFO, ("AM_63 (%d)\n", AM_63)); + + if (AM_63 < VGA_Lower_Bound) + VGA_code_idx++; + else if (AM_63 > VGA_Upper_Bound) + VGA_code_idx--; + else + { + DBGPRINT(RT_DEBUG_INFO, ("Appropriate VGA Gain(%d), R66(%x)\n", RT6352_VGA_TABLE[VGA_code_idx].Register, VGA_code)); + DBGPRINT(RT_DEBUG_INFO, ("AM_63 (%d)\n", AM_63)); + break; + } + } + + /* VGA_code cannot be found, report error and stop DPD calibration */ + if ((VGA_code_idx < 0) || (VGA_code_idx > 18)) + { + DBGPRINT(RT_DEBUG_ERROR, (" VGA Code idx overflow(%d), AM_63(%d) !!!\n", VGA_code_idx, AM_63)); + DPD_Cal_success = FALSE; + break; + } + + AM_SUM = 0; + AM_10 = 0; + + /* DPD calibration protection mechanism */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x01); + + for (k_count = 0; k_count < 11; k_count++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 3)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_SUM += byteValue; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x2B); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_10 = byteValue; + + DBGPRINT(RT_DEBUG_INFO, ("AM_SUM = %d, AM_10 = %d !!!\n", AM_SUM, AM_10)); + DBGPRINT(RT_DEBUG_INFO, ("(AM_SUM - 5.5*AM_10) = (%d) @@\n", (AM_SUM - ((11 * AM_10) / 2)))); + + if (AntIdx == 0) + { + if (((AM_SUM - ((11 * AM_10) / 2)) >= -3) && ((AM_SUM - ((11 * AM_10) / 2)) <= Pass_Thres)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DPD Calibration Pass for TX0 !!!\n")); + + if (check_loop == 0) + pAd->Tx0_DPD_ALC_tag0_flag = 0x1; + else if (check_loop == 1) + pAd->Tx0_DPD_ALC_tag1_flag = 0x1; + + DPD_Cal_success = TRUE; + break; + } + + if (index == 3) + { + Pass_Thres += 3; + } + } + else + { + if (index == 4) + { + if (((AM_SUM - ((11 * AM_10) / 2)) >= -9) && ((AM_SUM - ((11 * AM_10) / 2)) <= 12)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DPD Calibration Pass for TX1 !!!\n")); + + if (check_loop == 0) + pAd->Tx1_DPD_ALC_tag0_flag = 0x1; + else if (check_loop == 1) + pAd->Tx1_DPD_ALC_tag1_flag = 0x1; + + DPD_Cal_success = TRUE; + break; + } + } + else + { + if (((AM_SUM - ((11 * AM_10) / 2)) >= -5) && ((AM_SUM - ((11 * AM_10) / 2)) <= 5)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DPD Calibration Pass for TX1 !!!\n")); + + if (check_loop == 0) + pAd->Tx1_DPD_ALC_tag0_flag = 0x1; + else if (check_loop == 1) + pAd->Tx1_DPD_ALC_tag1_flag = 0x1; + + DPD_Cal_success = TRUE; + break; + } + } + } + } + + } + + /* Restore RF registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, saveRfB0R1); + if (AntIdx == 0) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, saveRfB5R1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, saveRfB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, saveRfB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, saveRfB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, saveRfB5R20); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R11, saveRfB4R11); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R13, saveRfB4R13); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, saveRfB4R19); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R21, saveRfB4R21); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R22, saveRfB4R22); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, saveRfB5R3); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R4); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R01, saveRfB7R1); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, saveRfB7R17); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, saveRfB7R18); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, saveRfB7R19); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, saveRfB7R20); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R11, saveRfB6R11); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R13, saveRfB6R13); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, saveRfB6R19); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R21, saveRfB6R21); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R22, saveRfB6R22); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, saveRfB7R3); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, saveRfB7R4); + } + + /* Restore BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + byteValue |= 0x10; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x1); + RtmpusecDelay(2); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x0); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, saveBbpR27); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, saveBbpR65); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R140); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, saveBbpR159); + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, saveBbpR241); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, saveBbpR242); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, saveBbpR242); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, saveBbpR244); + + /* Restore MAC registers */ + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, saveTxAlgCfg0); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, saveTxPinCfg); +#ifdef ED_MONITOR + if (pAd->ed_tx_stoped == TRUE) { + saveMacSysCtrl &= (~0x04); + DBGPRINT(RT_DEBUG_OFF, ("%s():Already stop tx, not enable MAC_SYS_CTRL!\n", + __FUNCTION__)); + } +#endif /* ED_MONITOR */ + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + + return 2; +} + +VOID DoDPDCalibration( + IN PRTMP_ADAPTER pAd) +{ + UCHAR Ant0 = 0, Ant1 = 0; + UCHAR byteValue = 0; +#ifdef RALINK_ATE + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* RALINK_ATE */ + + DBGPRINT(RT_DEBUG_INFO, (" Do DPD Calibration !!!\n")); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &saveBbpR1); + BBPValue = saveBbpR1; + BBPValue &= (~0x18); + BBPValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &saveRfB0R2); + RFValue = saveRfB0R2; + RFValue |= 0x33; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue); + } +#endif /* RALINK_ATE */ + + Ant0 = DPD_Calibration(pAd, 0); + if (pAd->Antenna.field.TxPath > 1) + Ant1 = DPD_Calibration(pAd, 1); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, saveBbpR1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, saveRfB0R2); + } +#endif /* RALINK_ATE */ + + if ((Ant0 == 2) || (Ant1 == 2)) + { + /* Disable DPD Compensation for Pa_mode 1 and 3 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + if (pAd->Tx0_DPD_ALC_tag0_flag == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + } + else if (pAd->Tx0_DPD_ALC_tag1_flag == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + } + else if (pAd->Tx1_DPD_ALC_tag0_flag == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + } + else if (pAd->Tx1_DPD_ALC_tag1_flag == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x09); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x09); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0B); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0B); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + + if (pAd->CommonCfg.Chip_VerID == 1) + { + DPD_IQ_Swap_AM_PM_Inversion(pAd, 0); + if (pAd->Antenna.field.TxPath > 1) + DPD_IQ_Swap_AM_PM_Inversion(pAd, 1); + } + + if (Ant0 == 2) + DPD_AM_AM_LUT_Scaling(pAd, 0); + if (pAd->Antenna.field.TxPath > 1) + { + if (Ant1 == 2) + DPD_AM_AM_LUT_Scaling(pAd, 1); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + + byteValue &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + byteValue |= 0x10; +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + if ((pAd->Tx0_DPD_ALC_tag0_flag == 0) && + (pAd->Tx0_DPD_ALC_tag1_flag == 0) && + (pAd->Tx1_DPD_ALC_tag0_flag == 0) && + (pAd->Tx1_DPD_ALC_tag1_flag == 0)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, (" Enable DPD Compensation !!!\n")); + DBGPRINT(RT_DEBUG_INFO, (" DPD Calibration Ant00 = %d, Ant01 = %d, Ant10 = %d, Ant11 = %d!!!\n", + pAd->Tx0_DPD_ALC_tag0_flag, pAd->Tx0_DPD_ALC_tag1_flag, + pAd->Tx1_DPD_ALC_tag0_flag, pAd->Tx1_DPD_ALC_tag1_flag)); + + /* Enable DPD Compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x04); +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x10); +#else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x1C); +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x05); +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x10); +#else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x12); +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0xC0); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x0); + } + else + { + DBGPRINT(RT_DEBUG_INFO, (" DPD Calibration Ant0 = %d, Ant1 = %d !!!\n", Ant0, Ant1)); + } + + return; +} + +INT Set_TestDPDCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ +#ifdef RALINK_ATE + PATE_INFO pATEInfo = &(pAd->ate); +#endif /* RALINK_ATE */ + INT bDPDCalibrationEnable = 0; + + DBGPRINT(RT_DEBUG_WARN, (" TestDPDCalibration !!!\n")); + + pAd->bCalibrationDone = FALSE; + + bDPDCalibrationEnable = simple_strtol(arg, 0, 10); + + if (bDPDCalibrationEnable == 0) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = FALSE; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + + pAd->bCalibrationDone = TRUE; + + return TRUE; + } + + if (bDPDCalibrationEnable == 1) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = TRUE; + } +#endif /* RALINK_ATE */ + pAd->Tx0_DPD_ALC_tag0 = 0; + pAd->Tx0_DPD_ALC_tag1 = 0; + pAd->Tx1_DPD_ALC_tag0 = 0; + pAd->Tx1_DPD_ALC_tag1 = 0; + pAd->Tx0_DPD_ALC_tag0_flag = 0x0; + pAd->Tx0_DPD_ALC_tag1_flag = 0x0; + pAd->Tx1_DPD_ALC_tag0_flag = 0x0; + pAd->Tx1_DPD_ALC_tag1_flag = 0x0; + } + + DoDPDCalibration(pAd); + pAd->bCalibrationDone = TRUE; + + return TRUE; +} + +INT Set_TestDPDCalibrationTX0_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UCHAR Ant0 = 0; + UCHAR byteValue = 0; +#ifdef RALINK_ATE + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* RALINK_ATE */ + INT bDPDCalibrationEnable = 0; + + DBGPRINT(RT_DEBUG_WARN, (" TestDPDCalibrationTX0 !!!\n")); + + pAd->bCalibrationDone = FALSE; + + bDPDCalibrationEnable = simple_strtol(arg, 0, 10); + + if (bDPDCalibrationEnable == 0) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = FALSE; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + pAd->bCalibrationDone = TRUE; + + return TRUE; + } + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &saveBbpR1); + BBPValue = saveBbpR1; + BBPValue &= (~0x18); + BBPValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &saveRfB0R2); + RFValue = saveRfB0R2; + RFValue |= 0x33; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue); + } +#endif /* RALINK_ATE */ + + if (bDPDCalibrationEnable == 1) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = TRUE; + } +#endif /* RALINK_ATE */ + pAd->Tx0_DPD_ALC_tag0 = 0; + pAd->Tx0_DPD_ALC_tag1 = 0; + pAd->Tx0_DPD_ALC_tag0_flag = 0x0; + pAd->Tx0_DPD_ALC_tag1_flag = 0x0; + } + + Ant0 = DPD_Calibration(pAd, 0); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, saveBbpR1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, saveRfB0R2); + } +#endif /* RALINK_ATE */ + + if (Ant0 == 2) + { + /* Disable DPD Compensation for Pa_mode 1 and 3 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x09); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x09); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0B); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0B); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + + if (pAd->CommonCfg.Chip_VerID == 1) + DPD_IQ_Swap_AM_PM_Inversion(pAd, 0); + + DPD_AM_AM_LUT_Scaling(pAd, 0); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + byteValue |= 0x10; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + if ((pAd->Tx0_DPD_ALC_tag0_flag == 0) && + (pAd->Tx0_DPD_ALC_tag1_flag == 0)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + } + else + { + DBGPRINT(RT_DEBUG_WARN, (" Enable DPD Compensation !!!\n")); + + /* Enable DPD Compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x1C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x1C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0xC0); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x0); + } + + pAd->bCalibrationDone = TRUE; + + return TRUE; +} + +INT Set_TestDPDCalibrationTX1_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UCHAR Ant1 = 0; + UCHAR byteValue = 0; +#ifdef RALINK_ATE + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* RALINK_ATE */ + INT bDPDCalibrationEnable = 0; + + DBGPRINT(RT_DEBUG_WARN, (" TestDPDCalibrationTX1 !!!\n")); + + pAd->bCalibrationDone = FALSE; + + bDPDCalibrationEnable = simple_strtol(arg, 0, 10); + + if (bDPDCalibrationEnable == 0) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = FALSE; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + pAd->bCalibrationDone = TRUE; + + return TRUE; + } + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &saveBbpR1); + BBPValue = saveBbpR1; + BBPValue &= (~0x18); + BBPValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &saveRfB0R2); + RFValue = saveRfB0R2; + RFValue |= 0x33; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue); + } +#endif /* RALINK_ATE */ + + if (bDPDCalibrationEnable == 1) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = TRUE; + } +#endif /* RALINK_ATE */ + pAd->Tx1_DPD_ALC_tag0 = 0; + pAd->Tx1_DPD_ALC_tag1 = 0; + pAd->Tx1_DPD_ALC_tag0_flag = 0x0; + pAd->Tx1_DPD_ALC_tag1_flag = 0x0; + } + + Ant1 = DPD_Calibration(pAd, 1); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, saveBbpR1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, saveRfB0R2); + } +#endif /* RALINK_ATE */ + + if (Ant1 == 2) + { + /* Disable DPD Compensation for Pa_mode 1 and 3 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x09); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x09); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0B); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0B); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x0D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + + if (pAd->CommonCfg.Chip_VerID == 1) + DPD_IQ_Swap_AM_PM_Inversion(pAd, 1); + + DPD_AM_AM_LUT_Scaling(pAd, 1); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + byteValue |= 0x10; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + if ((pAd->Tx1_DPD_ALC_tag0_flag == 0) && + (pAd->Tx1_DPD_ALC_tag1_flag == 0)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + } + else + { + DBGPRINT(RT_DEBUG_WARN, (" Enable DPD Compensation !!!\n")); + + /* Enable DPD Compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x1C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x12); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0xC0); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x0); + } + + pAd->bCalibrationDone = TRUE; + + return TRUE; +} + +INT Set_DPDCalPassThres_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + pAd->chipCap.DPDCalPassThres = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_INFO, + ("DPD Pass Threshold = %d \n", pAd->chipCap.DPDCalPassThres)); + + return TRUE; +} + +/**************************************************************************** + * + * VOID TX Filter BandWidth Calibraton + * + ****************************************************************************/ +static INT BBP_Core_Soft_Reset( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN set_bw, + IN INT bw) +{ + UINT8 bbp_val; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbp_val); + bbp_val |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbp_val); + RtmpusecDelay(100); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbp_val); + if (set_bw == TRUE) { + bbp_val &= (~0x18); + switch (bw) + { + case BW_40: + bbp_val |= 0x10; + break; + case BW_20: + default: + break; + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbp_val); + RtmpusecDelay(100); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbp_val); + bbp_val &= (~0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbp_val); + RtmpusecDelay(100); + + return 0; +} + +static INT RF_lp_Config( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bTxCal) +{ + UCHAR rf_val; + + if (bTxCal) + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x04); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x06); + } + else + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x02); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x06); + + } + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &rf_val); + rf_val |= 0x80; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, rf_val); + + if (bTxCal) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xC1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x02); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x3F; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x3F; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, rf_val); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, 0x31); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xF1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x02); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x34; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x34; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, rf_val); + } + + return 0; +} + +static CHAR lp_Tx_Filter_BW_Cal( + IN PRTMP_ADAPTER pAd) +{ + INT cnt; + UINT8 bbp_val; + CHAR cal_val; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x82); + + cnt = 0; + do { + RtmpusecDelay(500); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + if (bbp_val == 0x02 || cnt == 20) + break; + cnt++; + }while(cnt < 20); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x39); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + cal_val = bbp_val & 0x7F; + if (cal_val >= 0x40) + cal_val -= 128; + + return cal_val; +} + + +/* RF Bandwidth calibration */ +BOOLEAN BW_Filter_Calibration( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bTxCal) +{ + UINT8 tx_agc_fc = 0, rx_agc_fc = 0, cmm_agc_fc; + UINT8 filter_target; + UINT8 tx_filter_target_20m = 0x09, tx_filter_target_40m = 0x02; + UINT8 rx_filter_target_20m = 0x27, rx_filter_target_40m = 0x31; + INT loop = 0, bw, cnt; + UINT8 bbp_val, rf_val; + CHAR cal_r32_init, cal_r32_val, cal_diff; + UINT8 saveRfB5R00, saveRfB5R01, saveRfB5R03, saveRfB5R04, saveRfB5R05; + UINT8 saveRfB5R06, saveRfB5R07; + UINT8 saveRfB5R08, saveRfB5R17, saveRfB5R18, saveRfB5R19, saveRfB5R20; + UINT8 saveRfB5R37, saveRfB5R38, saveRfB5R39, saveRfB5R40, saveRfB5R41; + UINT8 saveRfB5R42, saveRfB5R43, saveRfB5R44, saveRfB5R45, saveRfB5R46; + UINT8 saveRfB5R58, saveRfB5R59; + UINT8 saveBBP159R0, saveBBP159R2, saveBBPR23; + UINT32 MAC_RF_CONTROL0, MAC_RF_BYPASS0; + + DBGPRINT(RT_DEBUG_ERROR, (" %s BW Filter Calibration !!!\n", (bTxCal == TRUE ? "TX" : "RX"))); + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, RF_CONTROL0, &MAC_RF_CONTROL0); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &MAC_RF_BYPASS0); + + /* save BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R23, &saveBBPR23); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x0); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &saveBBP159R0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x02); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &saveBBP159R2); + + /* Save RF registers */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R00, &saveRfB5R00); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &saveRfB5R01); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &saveRfB5R03); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R04); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R05, &saveRfB5R05); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &saveRfB5R06); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &saveRfB5R07); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R08, &saveRfB5R08); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &saveRfB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &saveRfB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &saveRfB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &saveRfB5R20); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R37, &saveRfB5R37); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R38, &saveRfB5R38); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R39, &saveRfB5R39); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R40, &saveRfB5R40); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R41, &saveRfB5R41); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R42, &saveRfB5R42); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R43, &saveRfB5R43); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R44, &saveRfB5R44); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R45, &saveRfB5R45); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R46, &saveRfB5R46); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &saveRfB5R58); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &saveRfB5R59); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R00, &rf_val); + rf_val |= 0x3; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R00, rf_val); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &rf_val); + rf_val |= 0x1; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, rf_val); + + cnt = 0; + do { + RtmpusecDelay(500); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &rf_val); + DBGPRINT(RT_DEBUG_INFO, ("ABB.R1 = %d, Cnt = %d \n", rf_val, cnt)); + if (((rf_val & 0x1) == 0x00) || (cnt == 40)) + break; + cnt++; + } while(cnt < 40); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R00, &rf_val); + rf_val &= (~0x3); + rf_val |= 0x1; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R00, rf_val); + + /* I-3 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R23, &bbp_val); + bbp_val &= (~0x1F); + bbp_val |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, bbp_val); + + do { + /* I-4,5,6,7,8,9 */ + if (loop == 0) { + bw = BW_20; + + if (bTxCal) + filter_target = tx_filter_target_20m; + else + filter_target = rx_filter_target_20m; + } + else + { + bw = BW_40; + + if (bTxCal) + filter_target = tx_filter_target_40m; + else + filter_target = rx_filter_target_40m; + } + DBGPRINT(RT_DEBUG_INFO, ("%s():Start BW Cal for %dMHz\n", + __FUNCTION__, (bw == BW_20 ? 20 : 40))); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R08, &rf_val); + rf_val &= (~0x04); + if (loop == 1) + rf_val |= 0x4; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R08, rf_val); + + BBP_Core_Soft_Reset(pAd, TRUE, bw); + + RF_lp_Config(pAd, bTxCal); + + if (bTxCal) + { + tx_agc_fc = 0; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, rf_val); + } + else + { + rx_agc_fc = 0; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, rf_val); + } + + RtmpusecDelay(1000); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x2); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + bbp_val &= (~0x6); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, bbp_val); + + BBP_Core_Soft_Reset(pAd, FALSE, bw); + + cal_r32_init = lp_Tx_Filter_BW_Cal(pAd); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x2); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + bbp_val |= 0x6; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, bbp_val); + + +do_cal: + + if (bTxCal) + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &rf_val); + rf_val &= (~0x7F); + rf_val |= tx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &rf_val); + rf_val &= (~0x7F); + rf_val |= tx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, rf_val); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &rf_val); + rf_val &= (~0x7F); + rf_val |= rx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &rf_val); + rf_val &= (~0x7F); + rf_val |= rx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, rf_val); + } + + RtmpusecDelay(500); + + BBP_Core_Soft_Reset(pAd, FALSE, bw); + + cal_r32_val = lp_Tx_Filter_BW_Cal(pAd); + + cal_diff = cal_r32_init - cal_r32_val; + + + if (bTxCal) + cmm_agc_fc = tx_agc_fc; + else + cmm_agc_fc = rx_agc_fc; + + if (((cal_diff > filter_target) && (cmm_agc_fc == 0)) || + ((cal_diff < filter_target) && (cmm_agc_fc == 0x3f))) + { + if (bTxCal) + tx_agc_fc = 0; + else + rx_agc_fc = 0; + } + else if ((cal_diff <= filter_target) && (cmm_agc_fc < 0x3f)) + { + if (bTxCal) + tx_agc_fc++; + else + rx_agc_fc++; + goto do_cal; + } + else + { + /* do nothing */ + } + + + if (bTxCal) + { + if (loop == 0) + pAd->tx_bw_cal[0] = tx_agc_fc; + else + pAd->tx_bw_cal[1] = tx_agc_fc; + } + else + { + if (loop == 0) + pAd->rx_bw_cal[0] = rx_agc_fc; + else + pAd->rx_bw_cal[1] = rx_agc_fc; + } + + loop++; + } while(loop <= 1); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R00, saveRfB5R00); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, saveRfB5R01); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, saveRfB5R03); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R04); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, saveRfB5R05); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, saveRfB5R06); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, saveRfB5R07); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R08, saveRfB5R08); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, saveRfB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, saveRfB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, saveRfB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, saveRfB5R20); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R37, saveRfB5R37); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R38, saveRfB5R38); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R39, saveRfB5R39); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R40, saveRfB5R40); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R41, saveRfB5R41); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R42, saveRfB5R42); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R43, saveRfB5R43); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R44, saveRfB5R44); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R45, saveRfB5R45); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R46, saveRfB5R46); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, saveRfB5R58); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, saveRfB5R59); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, saveBBPR23); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, saveBBP159R0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x2); + //RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + //bbp_val &= (~0x6); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, saveBBP159R2); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbp_val); + bbp_val &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + bbp_val |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbp_val); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MAC_RF_CONTROL0); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MAC_RF_BYPASS0); + + return TRUE; +} + +/* Rx DCOC Calibration */ +VOID RxDCOC_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpReg = 0; + UINT32 MacValue = 0, MacValue1 = 0; + USHORT k_count = 0; + UINT8 saveRfB0R2, saveRfB5R4, saveRfB7R4, RFValue; + + DBGPRINT(RT_DEBUG_WARN, (" RxDCOC_Calibration !!!\n")); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &saveRfB0R2); + RFValue = saveRfB0R2; + RFValue |= 0x03; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFValue); + + /* Write BBP CAL R141 bit[4] = 1. (Enable calibrate MID-GAIN) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R141); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x8); + + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue1); + if (MacValue1 & 0x1) + RtmpusecDelay(50); + else + break; + } + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R4); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R04, &saveRfB7R4); + saveRfB5R4 = saveRfB5R4 & (~0x40); + saveRfB7R4 = saveRfB7R4 & (~0x40); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R4); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, saveRfB7R4); + + /* Write BBP CAL R140 bit [6],[3] to 1 (Start Full,Gainfreeze calibration) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R140); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg = BbpReg & (~0x40); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + BbpReg |= 0x48; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + /* Polling CAL R140 bit[6] = 0 (Cal done) */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + if ((BbpReg & 0x40)==0) + break; + RtmpusecDelay(50); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg = BbpReg & (~0x40); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + /* Write CAL R141 bit[4] = 0 (Disable calibrate MID-GAIN) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R141); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg &= (~0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, saveRfB0R2); +} + +/**************************************************************************** + * + * VOID RXIQCalibraton(VOID) + * + ****************************************************************************/ +static UINT32 do_sqrt_accumulation(UINT32 si) +{ + UINT32 root,root_pre,bit; + CHAR i; + bit = 1 << 15; + root = 0; + for (i=15; i>=0; i=i-1) + { + root_pre = root + bit; + if((root_pre*root_pre) <= si) + root = root_pre; + bit = bit >> 1; + } + + return root; +} + +VOID RXIQ_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UINT8 RFB0R1,RFB0R2,RFB0R42; + UINT8 RFB4R0, RFB4R19; + UINT8 RFB5R3, RFB5R4, RFB5R17, RFB5R18, RFB5R19, RFB5R20; + UINT8 RFB6R0, RFB6R19; + UINT8 RFB7R3, RFB7R4, RFB7R17, RFB7R18, RFB7R19, RFB7R20; + + UINT8 BBP1, BBP4; + UINT8 BBPR241, BBPR242; + UINT32 i; + UINT8 ch_idx; + UINT8 bbpval; + UINT8 rfval, vga_idx=0; + INT32 mi = 0, mq = 0, si = 0, sq = 0, riq = 0; + INT32 Sigma_i, Sigma_q, R_iq, G_rx; + INT32 G_imb; + INT32 Ph_rx; + UINT32 saveMacSysCtrl = 0; + UINT32 orig_RF_CONTROL0 = 0; // 0x0518 + UINT32 orig_RF_BYPASS0 = 0; // 0x051c + UINT32 orig_RF_CONTROL1 = 0; // 0x0520 + UINT32 orig_RF_BYPASS1 = 0; // 0x0524 + UINT32 orig_RF_CONTROL3 = 0; // 0x0530 + UINT32 orig_RF_BYPASS3 = 0; // 0x0534 + UINT32 macStatus, k_count, bbpval1 = 0; + UCHAR rf_vga_table[]={0x20, 0x21, 0x22, + 0x38, 0x39, 0x3a, + 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f}; + + DBGPRINT(RT_DEBUG_INFO, (" RxIQ Calibration !!!\n")); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, RF_CONTROL0 , &orig_RF_CONTROL0); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &orig_RF_BYPASS0 ); + RTMP_IO_READ32(pAd, RF_CONTROL1 , &orig_RF_CONTROL1); + RTMP_IO_READ32(pAd, RF_BYPASS1 , &orig_RF_BYPASS1 ); + RTMP_IO_READ32(pAd, RF_CONTROL3 , &orig_RF_CONTROL3); + RTMP_IO_READ32(pAd, RF_BYPASS3 , &orig_RF_BYPASS3 ); + + // BBP store + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBP1); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBP4); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + + if (k_count == 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wait MAC Status to MAX !!!\n")); + } + + bbpval = BBP4 & (~0x18); + bbpval = BBP4 | 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbpval); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbpval); + bbpval = bbpval | 1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + bbpval = bbpval & 0xFE; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + + + RTMP_IO_WRITE32(pAd, RF_CONTROL1, 0x00000202); // 0x0520 + RTMP_IO_WRITE32(pAd, RF_BYPASS1 , 0x00000303); // 0x0524 +#ifdef RT6352_EP_SUPPORT + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x0101); // 0x0530 +#else + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x0000); // 0x0530 +#endif /* RT6352_EP_SUPPORT */ + RTMP_IO_WRITE32(pAd, RF_BYPASS3 , 0xF1F1); // 0x0534 + + /* B) Store RF Original Setting */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &RFB0R1); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &RFB0R2); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFB0R42); + + RT635xReadRFRegister(pAd, RF_BANK4, RF_R00, &RFB4R0); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R19, &RFB4R19); + /* RF TRx0 VGA gain store */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFB5R3); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &RFB5R4); + /* RF TRx0 Loopback path force */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &RFB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &RFB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &RFB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &RFB5R20); + + RT635xReadRFRegister(pAd, RF_BANK6, RF_R00, &RFB6R0); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R19, &RFB6R19); + /* RF TRx1 VGA gain store */ + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFB7R3); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R04, &RFB7R4); + /* RF TRx1 Loopback path force */ + RT635xReadRFRegister(pAd, RF_BANK7, RF_R17, &RFB7R17); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R18, &RFB7R18); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R19, &RFB7R19); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R20, &RFB7R20); + + /* ) RF Loopback Setting*/ + /* RF common setting */ + + /* TRx 0 loopback setting */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R00, 0x87); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, 0x27); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xC1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x60); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x00); + + /* TRx 1 loopback setting */ + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R00, 0x87); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, 0x27); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, 0xC1); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, 0x60); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, 0x00); + + + /* BBP Tx power control */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x5); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x0); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R241, &BBPR241); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R242, &BBPR242); + + + /* C) Set Debug Tone (need to be disable after calibration) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, 0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x31); + + /* Disable rx iq compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x3); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbpval); + bbpval = bbpval & (~0x7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, bbpval ); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000004); // 0x0518 + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000006); // 0x0518 + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x00003376); // 0x051c + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00001006); // 0x0518 + RtmpusecDelay(1); +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06); +#else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x02); +#endif /* RT6352_EP_SUPPORT */ + + //BBP Rf Rx gain control + for(ch_idx = 0; ch_idx < 2; ch_idx = ch_idx + 1) + { /* Path control */ + if(ch_idx == 0) + { /* only on Tx0 */ + /* RF only Tx0 */ + rfval = RFB0R1 & (~0x3); + rfval = RFB0R1 | 0x1; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, rfval); + rfval = RFB0R2 & (~0x33); + rfval = RFB0R2 | 0x11; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, rfval); + rfval = RFB0R42 & (~0x50); + rfval = RFB0R42 | 0x10; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, rfval); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00001006); // 0x0518 + RtmpusecDelay(1); + + // BBP only Tx0 + bbpval = BBP1 & (~ 0x18); + bbpval = bbpval | 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, bbpval); + + // BBP only Rx0 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + } + else + { + // RF only Tx1 + rfval = RFB0R1 & (~0x3); + rfval = RFB0R1 | 0x2; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, rfval); + rfval = RFB0R2 & (~0x33); + rfval = RFB0R2 | 0x22; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, rfval); + rfval = RFB0R42 & (~0x50); + rfval = RFB0R42 | 0x40; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, rfval); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00002006); // 0x0518 + RtmpusecDelay(1); + + // BBP only Tx1 + bbpval = BBP1 & (~ 0x18); + bbpval = bbpval | 0x08; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, bbpval); + + // BBP only Rx1 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x01); + } + RtmpusecDelay(500); + + /* e) Read mi, mq, si, sq, riq */ + vga_idx = 0; + + while( vga_idx < 11) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, rf_vga_table[vga_idx]); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, rf_vga_table[vga_idx]); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, rf_vga_table[vga_idx]); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, rf_vga_table[vga_idx]); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x93); + + for (i = 0; i < 10000; i++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbpval); + if ((bbpval & 0xff)== 0x93) + RtmpusecDelay(50); + else + break; + } + + if ((bbpval & 0xff)== 0x93) + { + DBGPRINT(RT_DEBUG_ERROR, ("Fatal Error: Calibration doesn't finish")); + goto Restore_Value; + } + + for (i = 0; i < 5; i++) // 0 mi, 1 mq, 2 si, 3 sq, 4 riq + { + UINT32 BBPtemp = 0; + UINT8 value = 0; + INT32 result = 0; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x1E); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, i); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x22); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + (value<<24); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x21); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + (value<<16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x20); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + (value<<8); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x1F); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + value; + + if ((i<2) && (BBPtemp & 0x800000)) // 23:0 + result = (BBPtemp & 0xFFFFFF) - 0x1000000; + else if(i==4) + result = BBPtemp; + else + result = BBPtemp; + + if (i == 0) + mi = result/4096; + else if (i==1) + mq = result/4096; + else if (i==2) + si = BBPtemp/4096; + else if (i==3) + sq = BBPtemp/4096; + else + riq = result/4096; + } + + /* Software AGC */ + bbpval1 = si - mi*mi; + DBGPRINT(RT_DEBUG_TRACE, ("RXIQ si=%d, sq=%d, riq=%d, bbpval %d, vga_idx %d\n", + si, sq, riq, bbpval1, vga_idx)); + + if(bbpval1 >= (100*100)) + break; + + if(bbpval1 <= 100) + vga_idx = vga_idx + 9; + else if(bbpval1 <= 158) + vga_idx = vga_idx + 8; + else if(bbpval1 <= 251) + vga_idx = vga_idx + 7; + else if(bbpval1 <= 398) + vga_idx = vga_idx + 6; + else if(bbpval1 <= 630) + vga_idx = vga_idx + 5; + else if(bbpval1 <= 1000) + vga_idx = vga_idx + 4; + else if(bbpval1 <= 1584) + vga_idx = vga_idx + 3; + else if(bbpval1 <= 2511) + vga_idx = vga_idx + 2; + else + vga_idx = vga_idx + 1; + } + + /* F) Calculate Sigma_i, Sigma_q, R_iq */ + Sigma_i = do_sqrt_accumulation(100*(si - mi*mi)); + Sigma_q = do_sqrt_accumulation(100*(sq - mq*mq)); + R_iq = 10*(riq-(mi*mq)); + + DBGPRINT(RT_DEBUG_TRACE, ("Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", Sigma_i, Sigma_q, R_iq)); + + if(((Sigma_i <= 1400 ) && (Sigma_i >= 1000)) + && ((Sigma_i - Sigma_q) <= 112) + && ((Sigma_i - Sigma_q) >= -112) + && ((mi <= 32) && (mi >= -32)) + && ((mq <= 32) && (mq >= -32))) + { + R_iq = 10*(riq-(mi*mq)); + DBGPRINT(RT_DEBUG_TRACE, ("RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", Sigma_i, Sigma_q, R_iq)); + + /* G) Calculate Gain/ Phase imbalance */ + G_rx = (1000 * Sigma_q) / Sigma_i; + G_imb = ((-2) * 128 * (1000 - G_rx)) / (1000 + G_rx); + Ph_rx = (R_iq * 2292 ) / (Sigma_i * Sigma_q); + DBGPRINT(RT_DEBUG_TRACE, ("RXIQ G_imb=%d, Ph_rx=%d\n", G_imb, Ph_rx)); + + if((Ph_rx > 12 ) || (Ph_rx < -12) ) + { + Ph_rx = 0; + DBGPRINT(RT_DEBUG_ERROR, ("RXIQ calibration FAIL\n")); + } + + if((G_imb > 7) ||(G_imb < -7)) + { + G_imb = 0; + DBGPRINT(RT_DEBUG_ERROR, ("RXIQ calibration FAIL\n")); + } + } + else + { + G_imb = 0; + Ph_rx = 0; + DBGPRINT(RT_DEBUG_ERROR, ("RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", Sigma_i, Sigma_q, R_iq)); + DBGPRINT(RT_DEBUG_ERROR, ("RXIQ calibration FAIL\n")); + } + + /* H) Write back compensation value and disable HW calculation */ + if(ch_idx == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x37); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, G_imb & 0x3F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x35); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, Ph_rx & 0x3F); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x55); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, G_imb & 0x3F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x53); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, Ph_rx & 0x3F); + } + } + +Restore_Value: + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x3); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbpval); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, (bbpval | 0x07)); + + /*BBP Restore */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBP1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBP4); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, BBPR241); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, BBPR242); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x00); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbpval); + bbpval = (bbpval | 0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + RtmpusecDelay(10); + bbpval = (bbpval & 0xFE); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + + /* Bank 0 recover */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, RFB0R1); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFB0R2); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, RFB0R42); + + /* Bank TRx0 recover */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R00 , RFB4R0); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, RFB4R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, RFB5R3); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, RFB5R4); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, RFB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, RFB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, RFB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, RFB5R20); + + /* Bank TRx1 recover */ + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R00 , RFB6R0); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, RFB6R19); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, RFB7R3); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, RFB7R4); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, RFB7R17); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, RFB7R18); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, RFB7R19); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, RFB7R20); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000006); // 0x0518 + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000004); // 0x0518 + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RF_CONTROL0 , orig_RF_CONTROL0); + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , orig_RF_BYPASS0); + RTMP_IO_WRITE32(pAd, RF_CONTROL1 , orig_RF_CONTROL1); + RTMP_IO_WRITE32(pAd, RF_BYPASS1 , orig_RF_BYPASS1); + RTMP_IO_WRITE32(pAd, RF_CONTROL3 , orig_RF_CONTROL3); + RTMP_IO_WRITE32(pAd, RF_BYPASS3 , orig_RF_BYPASS3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , saveMacSysCtrl); +} + +VOID RF_SELF_TXDC_CAL( + IN PRTMP_ADAPTER pAd) +{ + // RF_CONTROL0: 0x0518 + // RTMP_RF_BYPASS0 : 0x051c + // RF_CONTROL2: 0x0528 + // RF_BYPASS2 : 0x052c + UCHAR RfB5R1_Org, RfB7R1_Org, RFValue; + UINT32 mac0518, mac051c,mac0528,mac052c; + CHAR i; + + DBGPRINT(RT_DEBUG_INFO, ("RF Tx_0 self calibration start\n")); + RTMP_IO_READ32(pAd, RF_CONTROL0, &mac0518); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &mac051c); + RTMP_IO_READ32(pAd, RF_CONTROL2, &mac0528); + RTMP_IO_READ32(pAd, RF_BYPASS2 , &mac052c); + + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0x0); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0xC); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x3306); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, 0x3330); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0xfffff); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &RfB5R1_Org); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R01, &RfB7R1_Org); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, 0x4); + for( i=0; i < 100; i = i + 1){ + RtmpusecDelay(50); /* wait 1 usec */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &RFValue); + if((RFValue&0x04)!=0x4) + break; + } + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, RfB5R1_Org); + + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R01, 0x4); + for( i=0; i < 100; i = i + 1){ + RtmpusecDelay(50); /* wait 1 usec */ + RT635xReadRFRegister(pAd, RF_BANK7, RF_R01, &RFValue); + if((RFValue&0x04)!=0x4) + break; + } + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R01, RfB7R1_Org); + + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, mac0518); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , mac051c); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, mac0528); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , mac052c); + + DBGPRINT(RT_DEBUG_INFO, ("RF Tx self calibration end\n")); + +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_sanity.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_sanity.c new file mode 100644 index 000000000..80cc2062b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_sanity.c @@ -0,0 +1,2906 @@ +/* + *************************************************************************** + * 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: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +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 BROADCOM_OUI[]; +extern UCHAR WPS_OUI[]; + + +#ifdef IWSC_SUPPORT +extern UCHAR IWSC_OUI[]; +#endif // IWSC_SUPPORT // + +typedef struct wsc_ie_probreq_data +{ + UCHAR ssid[32]; + UCHAR macAddr[6]; + UCHAR data[2]; +} WSC_IE_PROBREQ_DATA; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PMLME_ADDBA_REQ_STRUCT pInfo; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + /* + if ((pInfo->BaBufSize > MAX_RX_REORDERBUF) || (pInfo->BaBufSize < 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - Rx Reordering buffer too big or too small\n")); + return FALSE; + } + */ + + if ((pInfo->pAddr[0]&0x01) == 0x01) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); + return FALSE; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + if ((pInfo->TID & 0xf0)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); + return FALSE; + } + + if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); + return FALSE; + } + + return TRUE; +} + + +BOOLEAN PeerAddBAReqActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_ADDBA_REQ pAddFrame; + pAddFrame = (PFRAME_ADDBA_REQ)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_REQ))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + /* we support immediate BA.*/ +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); +#endif + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported)); + return FALSE; + } + + return TRUE; +} + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen) +{ + PFRAME_ADDBA_RSP pAddFrame; + + pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): ADDBA Resp frame length incorrect(len=%ld)\n", __FUNCTION__, MsgLen)); + return FALSE; + } + +#ifdef SMART_MESH_MONITOR +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + To avoid control frames captured by sniffer confusing due to lack of Addr 3 + */ + if(!IsValidUnicastToMe(pAd, Wcid, pAddFrame->Hdr.Addr1)) + return FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_MONITOR */ + + /* we support immediate BA.*/ +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); +#endif + pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): ADDBA Resp Ba Policy[%d] not support\n", __FUNCTION__, pAddFrame->BaParm.BAPolicy)); + return FALSE; + } + + return TRUE; + +} + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen ) +{ + PFRAME_DELBA_REQ pDelFrame; + + if (MsgLen != (sizeof(FRAME_DELBA_REQ))) + return FALSE; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + pDelFrame = (PFRAME_DELBA_REQ)(pMsg); + +#ifdef SMART_MESH_MONITOR +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + To avoid control frames captured by sniffer confusing due to lack of Addr 3 + */ + if(!IsValidUnicastToMe(pAd, Wcid, pDelFrame->Hdr.Addr1)) + return FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_MONITOR */ + + *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); + pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); + + return TRUE; +} + + +BOOLEAN PeerBeaconAndProbeRspSanity_Old( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + OUT UCHAR *pPreNHtCapabilityLen, +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + OUT UCHAR *pSelReg, +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + OUT HT_CAPABILITY_IE *pHtCapability, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannelOffset, /* Ht extension channel offset(above or below)*/ + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE) +{ + UCHAR *Ptr; +#ifdef CONFIG_STA_SUPPORT + UCHAR TimLen; +#ifdef IWSC_SUPPORT + BOOLEAN bFoundIWscIe = FALSE; + USHORT PeerConfigMethod = 0; +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR SubType; + UCHAR Sanity; + /*UCHAR ECWMin, ECWMax;*/ + /*MAC_CSR9_STRUC Csr9;*/ + ULONG Length = 0; + UCHAR *pPeerWscIe = NULL; + INT PeerWscIeLen = 0; + BOOLEAN bWscCheck = TRUE; + UCHAR LatchRfChannel = 0; + + + /* + For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel + 1. If the AP is 11n enabled, then check the control channel. + 2. If the AP didn't have any info about channel, use the channel we received this + frame as the channel. (May inaccuracy!!) + */ + UCHAR CtrlChannel = 0; + + + os_alloc_mem(NULL, &pPeerWscIe, 512); + /* Add for 3 necessary EID field check*/ + Sanity = 0; + + *pAtimWin = 0; + *pErp = 0; + *pDtimCount = 0; + *pDtimPeriod = 0; + *pBcastFlag = 0; + *pMessageToMe = 0; + *pExtRateLen = 0; + *pCkipFlag = 0; /* Default of CkipFlag is 0*/ + *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/ + *LengthVIE = 0; /* Set the length of VIE to init value 0*/ + *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/ +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + *pPreNHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/ +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + *pSelReg = 0; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + *AddHtInfoLen = 0; /* Set the length of VIE to init value 0*/ + NdisZeroMemory(pExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)); + *pRalinkIe = 0; + *pNewChannel = 0; + *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/ + pCfParm->bValid = FALSE; /* default: no IE_CF found*/ + pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found*/ + pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found*/ + pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found*/ + + pFrame = (PFRAME_802_11)Msg; + + /* get subtype from header*/ + SubType = (UCHAR)pFrame->Hdr.FC.SubType; + + /* get Addr2 and BSSID from header*/ + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); + +/* hex_dump("Beacon", Msg, MsgLen);*/ + + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + /* get timestamp from payload and advance the pointer*/ + NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); + + pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); + pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); + + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer*/ + NdisMoveMemory(pBeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(*pCapabilityInfo)) + *pBssType = BSS_INFRA; + else + *pBssType = BSS_ADHOC; + + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer*/ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + + /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/ + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + __FUNCTION__, (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } + + switch(pEid->Eid) + { + case IE_SSID: + /* Already has one SSID EID in this beacon, ignore the second one*/ + if (Sanity & 0x1) + break; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + Sanity |= 0x1; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SSID (len=%d), SubType = %u\n", + __FUNCTION__, pEid->Len, SubType)); + goto SanityCheck; + } + break; + + case IE_SUPP_RATES: + if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + Sanity |= 0x2; + NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); + *pSupRateLen = pEid->Len; + + /* + TODO: 2004-09-14 not a good design here, cause it exclude extra + rates from ScanTab. We should report as is. And filter out + unsupported rates in MlmeAux + */ + /* Check against the supported rates*/ + /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SUPP_RATES (len=%d)\n",__FUNCTION__, pEid->Len)); + goto SanityCheck; + } + break; + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/ + { + NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/ + + *(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 */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + *pPreNHtCapabilityLen = 0; /* Now we only support 26 bytes.*/ + + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_HT_CAP. pEid->Len = %d\n", __FUNCTION__, pEid->Len)); + } + + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + /* + This IE allows extension, but we can ignore extra bytes beyond our + knowledge , so only copy first sizeof(ADD_HT_INFO_IE) + */ + NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + + CtrlChannel = AddHtInfo->ControlChan; + + *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); + *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_ADD_HT. \n", __FUNCTION__)); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *NewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__)); + } + + break; + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("%s(IE_FH_PARM) \n", __FUNCTION__)); + break; + + case IE_DS_PARM: + if(pEid->Len == 1) + { + *pChannel = *pEid->Octet; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ChannelSanity(pAd, *pChannel) == 0) + { + + goto SanityCheck; + } + } +#endif /* CONFIG_STA_SUPPORT */ + Sanity |= 0x4; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_DS_PARM (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + + case IE_CF_PARM: + if(pEid->Len == 6) + { + pCfParm->bValid = TRUE; + pCfParm->CfpCount = pEid->Octet[0]; + pCfParm->CfpPeriod = pEid->Octet[1]; + pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; + pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_CF_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if(pEid->Len == 2) + { + NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_IBSS_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + +#ifdef CONFIG_STA_SUPPORT + case IE_TIM: + if(SubType == SUBTYPE_BEACON) + { + + if (INFRA_ON(pAd) && NdisEqualMemory(pBssid, pAd->CommonCfg.Bssid, MAC_ADDR_LEN)) + { + GetTimBit((PCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe); + } + } + break; +#endif /* CONFIG_STA_SUPPORT */ + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if(pEid->Len == 3) + { + *pNewChannel = pEid->Octet[1]; /*extract new channel number*/ + } + break; + + /* + New for WPA + CCX v2 has the same IE, we need to parse that too + Wifi WMM use the same IE vale, need to parse that too + */ + /* case IE_WPA:*/ + case IE_VENDOR_SPECIFIC: + /* Check the OUI version, filter out non-standard usage*/ + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) + { + if (pEid->Octet[3] != 0) + *pRalinkIe = pEid->Octet[3]; + else + *pRalinkIe = 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.*/ + } +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT + /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan.*/ + + /* Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP,*/ + /* Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE*/ + else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) + { + if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0)) + { + NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); + *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; + } + + if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26)) + { + NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + } +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + /* Copy to pVIE which will report to bssid list.*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + /* parsing EDCA parameters*/ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/ + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/ + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/ + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/ + ptr += 4; /* point to next AC*/ + } + } + else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + /* parsing EDCA parameters*/ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + + /* use default EDCA parameter*/ + pEdcaParm->bACM[QID_AC_BE] = 0; + pEdcaParm->Aifsn[QID_AC_BE] = 3; + pEdcaParm->Cwmin[QID_AC_BE] = pAd->wmm_cw_min; + pEdcaParm->Cwmax[QID_AC_BE] = pAd->wmm_cw_max; + pEdcaParm->Txop[QID_AC_BE] = 0; + + pEdcaParm->bACM[QID_AC_BK] = 0; + pEdcaParm->Aifsn[QID_AC_BK] = 7; + pEdcaParm->Cwmin[QID_AC_BK] = pAd->wmm_cw_min; + pEdcaParm->Cwmax[QID_AC_BK] = pAd->wmm_cw_max; + pEdcaParm->Txop[QID_AC_BK] = 0; + + pEdcaParm->bACM[QID_AC_VI] = 0; + pEdcaParm->Aifsn[QID_AC_VI] = 2; + pEdcaParm->Cwmin[QID_AC_VI] = pAd->wmm_cw_min - 1; + pEdcaParm->Cwmax[QID_AC_VI] = pAd->wmm_cw_max; + pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/ + + pEdcaParm->bACM[QID_AC_VO] = 0; + pEdcaParm->Aifsn[QID_AC_VO] = 2; + pEdcaParm->Cwmin[QID_AC_VO] = pAd->wmm_cw_min - 2; + pEdcaParm->Cwmax[QID_AC_VO] = pAd->wmm_cw_max - 1; + pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/ + } + else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) + #ifdef IWSC_SUPPORT + || NdisEqualMemory(pEid->Octet, IWSC_OUI, 4) +#endif // IWSC_SUPPORT // + ) + { + if (pPeerWscIe) + { + /* Ignore old WPS IE fragments, if we get the version 0x10 */ + if (pEid->Octet[4] == 0x10) //First WPS IE will have version 0x10 + { + NdisMoveMemory(pPeerWscIe, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen = (pEid->Len - 4); + } + else // reassembly remanning, other IE fragmentations will not have version 0x10 + { + if ((PeerWscIeLen +(pEid->Len - 4)) <= 512) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen += (pEid->Len - 4); + } + else /* ((PeerWscIeLen +(pEid->Len - 4)) > 512) */ + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! Sum of All PeerWscIeLen = %d (> 512)\n", __FUNCTION__, (PeerWscIeLen +(pEid->Len - 4)))); + } + } + } + else + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! pPeerWscIe is empty!\n", __FUNCTION__)); + } + +#ifdef IWSC_SUPPORT + if (NdisEqualMemory(pEid->Octet, IWSC_OUI, 4)) + bFoundIWscIe = TRUE; +#endif /* IWSC_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + if (SubType == SUBTYPE_BEACON) + { + PUCHAR pData; + INT Len = 0; + USHORT DataLen = 0; + PWSC_IE pWscIE; + + pData = (PUCHAR) pEid->Octet + 4; + Len = (SHORT)(pEid->Len - 4); + + while (Len > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + // Check for WSC IEs + pWscIE = &WscIE; + + if (be2cpu16(pWscIE->Type) == 0x1041 /*WSC_ID_SEL_REGISTRAR*/ ) + { + DataLen = be2cpu16(pWscIE->Length); + NdisMoveMemory(pSelReg, pData + 4, DataLen); + break; + } + + // Set the offset and look for next WSC Tag information + // Since Type and Length are both short type, we need to offset 4, not 2 + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } + + + //WscGetDataFromPeerByTag(pAd, pPeerWscIe, PeerWscIeLen, WSC_ID_SEL_REGISTRAR, &bSelReg, NULL); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + + } + + + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + + /* + TODO: 2004-09-14 not a good design here, cause it exclude extra rates + from ScanTab. We should report as is. And filter out unsupported + rates in MlmeAux + */ + /* Check against the supported rates*/ + /* RTMPCheckRates(pAd, ExtRate, pExtRateLen);*/ + } + break; + + case IE_ERP: + if (pEid->Len == 1) + { + *pErp = (UCHAR)pEid->Octet[0]; + } + break; + + case IE_AIRONET_CKIP: + /* + 0. Check Aironet IE length, it must be larger or equal to 28 + Cisco AP350 used length as 28 + Cisco AP12XX used length as 30 + */ + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + /* 1. Copy CKIP flag byte to buffer for process*/ + *pCkipFlag = *(pEid->Octet + 8); + break; + + case IE_AP_TX_POWER: + /* AP Control of Client Transmit Power*/ + /*0. Check Aironet IE length, it must be 6*/ + if (pEid->Len != 0x06) + break; + + /* Get cell power limit in dBm*/ + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + *pAironetCellPowerLimit = *(pEid->Octet + 4); + break; + + /* WPA2 & 802.11i RSN*/ + case IE_RSN: + /* There is no OUI for version anymore, check the group cipher OUI before copying*/ + if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + /* Copy to pVIE which will report to microsoft bssid list.*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; +#ifdef WAPI_SUPPORT + /* WAPI information element*/ + case IE_WAPI: + if (RTMPEqualMemory(pEid->Octet + 4, WAPI_OUI, 3)) + { + /* Copy to pVIE*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; +#endif /* WAPI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined (EXT_BUILD_CHANNEL_LIST) || defined (RT_CFG80211_SUPPORT) + case IE_COUNTRY: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ + + case IE_QBSS_LOAD: + if (pEid->Len == 5) + { + pQbssLoad->bValid = TRUE; + pQbssLoad->StaNum = pEid->Octet[0] + pEid->Octet[1] * 256; + pQbssLoad->ChannelUtilization = pEid->Octet[2]; + pQbssLoad->RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256; + + /* Copy to pVIE*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; + + +#ifdef DOT11R_FT_SUPPORT + case IE_FT_MDIE: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif /* DOT11R_FT_SUPPORT */ + + case IE_EXT_CAPABILITY: + if (pEid->Len >= 1) + { + UCHAR MaxSize; + UCHAR MySize = sizeof(EXT_CAP_INFO_ELEMENT); + + MaxSize = min(pEid->Len, MySize); + + NdisMoveMemory(pExtCapInfo,&pEid->Octet[0], MaxSize); + } + break; + default: + break; + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + LatchRfChannel = MsgChannel; + + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) + { + if (CtrlChannel != 0) + *pChannel = CtrlChannel; + else + *pChannel = LatchRfChannel; + Sanity |= 0x4; + } + + if (pPeerWscIe && (PeerWscIeLen > 0) && (PeerWscIeLen <= 512) && ( bWscCheck == TRUE)) + { + UCHAR WscIe[] = {0xdd, 0x00, 0x00, 0x50, 0xF2, 0x04}; + Ptr = (PUCHAR) pVIE; + WscIe[1] = PeerWscIeLen + 4; + NdisMoveMemory(Ptr + *LengthVIE, WscIe, 6); + NdisMoveMemory(Ptr + *LengthVIE + 6, pPeerWscIe, PeerWscIeLen); + *LengthVIE += (PeerWscIeLen + 6); +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (SubType == SUBTYPE_PROBE_RSP) && + (bFoundIWscIe == TRUE)) + { + BOOLEAN bSelReg = FALSE; + USHORT DataLen = 0; + + /* re-use this boolean variable */ + bFoundIWscIe = FALSE; + WscGetDataFromPeerByTag(pAd, pPeerWscIe, PeerWscIeLen, WSC_ID_SEL_REGISTRAR, &bSelReg, NULL); + if (bSelReg) + { + bFoundIWscIe = TRUE; + if (WscGetDataFromPeerByTag(pAd, + pPeerWscIe, + PeerWscIeLen, + WSC_ID_MAC_ADDR, + &pAd->StaCfg.WscControl.WscPeerMAC[0], + NULL) == FALSE) + { + NdisMoveMemory(&pAd->StaCfg.WscControl.WscPeerMAC[0], pAddr2, MAC_ADDR_LEN); + } + NdisMoveMemory(&pAd->StaCfg.WscControl.EntryAddr[0], + &pAd->StaCfg.WscControl.WscPeerMAC[0], + MAC_ADDR_LEN); + hex_dump("PeerBeaconAndProbeRspSanity - WscPeerMAC", &pAd->StaCfg.WscControl.WscPeerMAC[0], MAC_ADDR_LEN); + + WscGetDataFromPeerByTag(pAd, + pPeerWscIe, + PeerWscIeLen, + WSC_ID_SEL_REG_CFG_METHODS, + &PeerConfigMethod, + NULL); + } + } +#endif /* IWSC_SUPPORT */ + } + + +SanityCheck: + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + + if ((Sanity != 0x7) || ( bWscCheck == FALSE)) + { + DBGPRINT(RT_DEBUG_LOUD, ("%s() - missing field, Sanity=0x%02x\n", __FUNCTION__, Sanity)); + return FALSE; + } + else + { +#ifdef IWSC_SUPPORT + if (bFoundIWscIe && (pAd->StaCfg.BssType == BSS_ADHOC)) + { + PWSC_CTRL pWscCtrl = &pAd->StaCfg.WscControl; + if ((pWscCtrl->WscConfMode == WSC_ENROLLEE) && + (pWscCtrl->WscMode == WSC_PIN_MODE) && + (pWscCtrl->bWscTrigger == TRUE)) + { + NdisZeroMemory(&pWscCtrl->WscSsid, sizeof(NDIS_802_11_SSID)); + if ((*pSsidLen) <= 32 && (*pSsidLen) != 0) + { + pWscCtrl->WscSsid.SsidLength = *pSsidLen; + NdisMoveMemory(pWscCtrl->WscSsid.Ssid, Ssid, pWscCtrl->WscSsid.SsidLength); + PeerConfigMethod = be2cpu16(PeerConfigMethod); + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_PEER_PROBE_RSP, sizeof(USHORT), &PeerConfigMethod, 0); + } + } + } +#endif /* IWSC_SUPPORT */ + return TRUE; + } + +} + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT BCN_IE_LIST *ie_list, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE) +{ + UCHAR *Ptr; +#ifdef CONFIG_STA_SUPPORT + UCHAR TimLen; +#ifdef IWSC_SUPPORT + BOOLEAN bFoundIWscIe = FALSE; + USHORT PeerConfigMethod = 0; +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR SubType; + UCHAR Sanity; + ULONG Length = 0; + UCHAR *pPeerWscIe = NULL; + INT PeerWscIeLen = 0; + BOOLEAN bWscCheck = TRUE; + UCHAR LatchRfChannel = 0; + + + /* + For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel + 1. If the AP is 11n enabled, then check the control channel. + 2. If the AP didn't have any info about channel, use the channel we received this + frame as the channel. (May inaccuracy!!) + */ + UCHAR CtrlChannel = 0; + + + os_alloc_mem(NULL, &pPeerWscIe, 512); + Sanity = 0; /* Add for 3 necessary EID field check*/ + + ie_list->AironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/ + ie_list->NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/ + *LengthVIE = 0; /* Set the length of VIE to init value 0*/ + + pFrame = (PFRAME_802_11)Msg; + + /* get subtype from header*/ + SubType = (UCHAR)pFrame->Hdr.FC.SubType; + + /* get Addr2 and BSSID from header*/ + COPY_MAC_ADDR(&ie_list->Addr2[0], pFrame->Hdr.Addr2); + COPY_MAC_ADDR(&ie_list->Bssid[0], pFrame->Hdr.Addr3); + + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + /* get timestamp from payload and advance the pointer*/ + NdisMoveMemory(&ie_list->TimeStamp, Ptr, TIMESTAMP_LEN); + + ie_list->TimeStamp.u.LowPart = cpu2le32(ie_list->TimeStamp.u.LowPart); + ie_list->TimeStamp.u.HighPart = cpu2le32(ie_list->TimeStamp.u.HighPart); + + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer*/ + NdisMoveMemory(&ie_list->BeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(&ie_list->CapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(ie_list->CapabilityInfo)) + ie_list->BssType = BSS_INFRA; + else + ie_list->BssType = BSS_ADHOC; + + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer*/ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + + /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/ + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + __FUNCTION__, (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } + + switch(pEid->Eid) + { + case IE_SSID: + /* Already has one SSID EID in this beacon, ignore the second one*/ + if (Sanity & 0x1) + break; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(&ie_list->Ssid[0], pEid->Octet, pEid->Len); + ie_list->SsidLen = pEid->Len; + Sanity |= 0x1; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SSID (len=%d), SubType = %u\n", + __FUNCTION__,pEid->Len, SubType)); + goto SanityCheck; + } + break; + + case IE_SUPP_RATES: + if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + Sanity |= 0x2; + NdisMoveMemory(&ie_list->SupRate[0], pEid->Octet, pEid->Len); + ie_list->SupRateLen = pEid->Len; + + /* + TODO: 2004-09-14 not a good design here, cause it exclude extra + rates from ScanTab. We should report as is. And filter out + unsupported rates in MlmeAux + */ + /* Check against the supported rates*/ + /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SUPP_RATES (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/ + { + NdisMoveMemory(&ie_list->HtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + ie_list->HtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/ + + *(USHORT *)(&ie_list->HtCapability.HtCapInfo) = cpu2le16(*(USHORT *)(&ie_list->HtCapability.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&ie_list->HtCapability.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&ie_list->HtCapability.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&ie_list->HtCapability.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&ie_list->HtCapability.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + ie_list->PreNHtCapabilityLen = 0; /* Now we only support 26 bytes.*/ + + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_HT_CAP. pEid->Len = %d\n", __FUNCTION__, pEid->Len)); + } + + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + /* + This IE allows extension, but we can ignore extra bytes beyond our + knowledge , so only copy first sizeof(ADD_HT_INFO_IE) + */ + NdisMoveMemory(&ie_list->AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + ie_list->AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + + CtrlChannel = ie_list->AddHtInfo.ControlChan; + + *(USHORT *)(&ie_list->AddHtInfo.AddHtInfo2) = cpu2le16(*(USHORT *)(&ie_list->AddHtInfo.AddHtInfo2)); + *(USHORT *)(&ie_list->AddHtInfo.AddHtInfo3) = cpu2le16(*(USHORT *)(&ie_list->AddHtInfo.AddHtInfo3)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_ADD_HT. \n", __FUNCTION__)); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + ie_list->NewExtChannelOffset = pEid->Octet[0]; + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__)); + } + break; + + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("%s(IE_FH_PARM) \n", __FUNCTION__)); + break; + + case IE_DS_PARM: + if(pEid->Len == 1) + { + ie_list->Channel = *pEid->Octet; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ChannelSanity(pAd, ie_list->Channel) == 0) + { + goto SanityCheck; + } + } +#endif /* CONFIG_STA_SUPPORT */ + Sanity |= 0x4; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_DS_PARM (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + + case IE_CF_PARM: + if(pEid->Len == 6) + { + ie_list->CfParm.bValid = TRUE; + ie_list->CfParm.CfpCount = pEid->Octet[0]; + ie_list->CfParm.CfpPeriod = pEid->Octet[1]; + ie_list->CfParm.CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; + ie_list->CfParm.CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_CF_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if(pEid->Len == 2) + { + NdisMoveMemory(&ie_list->AtimWin, pEid->Octet, pEid->Len); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_IBSS_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + +#ifdef CONFIG_STA_SUPPORT + case IE_TIM: + if(SubType == SUBTYPE_BEACON) + { +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if( +#ifdef RT_CFG80211_P2P_SUPPORT + CFG_P2PCLI_ON(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + && NdisEqualMemory(&ie_list->Bssid[0], pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid, MAC_ADDR_LEN)) + { + GetTimBit((PCHAR)pEid, pAd->ApCfg.ApCliTab[0].MlmeAux.Aid, &TimLen, + &ie_list->BcastFlag, &ie_list->DtimCount, + &ie_list->DtimPeriod, &ie_list->MessageToMe); + } +#endif /*defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT)*/ + + if (INFRA_ON(pAd) && NdisEqualMemory(&ie_list->Bssid[0], pAd->CommonCfg.Bssid, MAC_ADDR_LEN)) + { + GetTimBit((PCHAR)pEid, pAd->StaActive.Aid, &TimLen, &ie_list->BcastFlag, + &ie_list->DtimCount, &ie_list->DtimPeriod, &ie_list->MessageToMe); + } + } + break; +#endif /* CONFIG_STA_SUPPORT */ + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if(pEid->Len == 3) + ie_list->NewChannel = pEid->Octet[1]; /*extract new channel number*/ + break; + + /* + New for WPA + CCX v2 has the same IE, we need to parse that too + Wifi WMM use the same IE vale, need to parse that too + */ + /* case IE_WPA:*/ + case IE_VENDOR_SPECIFIC: + /* Check the OUI version, filter out non-standard usage*/ + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) + { + if (pEid->Octet[3] != 0) + ie_list->RalinkIe = pEid->Octet[3]; + else + ie_list->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.*/ + } + + if (NdisEqualMemory(pEid->Octet, MTK_OUI, 3) && (pEid->Len == 7)) + { + if (pEid->Octet[3] != 0) + ie_list->MediatekIe= pEid->Octet[3]; + } +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT + /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan.*/ + + /* Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP,*/ + /* Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE*/ + else if ((ie_list->HtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) + { + if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30) && (ie_list->HtCapabilityLen == 0)) + { + NdisMoveMemory(&ie_list->HtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); + ie_list->PreNHtCapabilityLen = SIZE_HT_CAP_IE; + } + + if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26)) + { + NdisMoveMemory(&ie_list->AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); + ie_list->AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + } +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + /* Copy to pVIE which will report to bssid list.*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#if defined(SMART_MESH) || defined(SMART_MESH_MONITOR) + /* Check the OUI version, filter out non-standard usage*/ + else if ((pEid->Len >= NTGR_OUI_LEN) && NdisEqualMemory(pEid->Octet, NETGEAR_OUI, NTGR_OUI_LEN)) + { +#ifdef SMART_MESH_MONITOR + if(pEid->Len <= NTGR_IE_TOTAL_LEN) + { + ie_list->vendor_ie_len = (pEid->Len - NTGR_OUI_LEN); + if(ie_list->vendor_ie_len > 0) + NdisCopyMemory(ie_list->vendor_ie,&pEid->Octet[NTGR_OUI_LEN], ie_list->vendor_ie_len); /* Skip OUI */ + } +#endif /* SMART_MESH_MONITOR */ +#ifdef SMART_MESH + if(pEid->Len > NTGR_OUI_LEN) + { + ie_list->VIEFlag = pEid->Octet[3]; + if ((pEid->Octet[3] & 0x02)) + ie_list->bSupportSmartMesh = TRUE; + else + ie_list->bSupportSmartMesh = FALSE; +#ifdef MWDS + if ((pEid->Octet[3] & 0x01)) + ie_list->bSupportMWDS = TRUE; + else + ie_list->bSupportMWDS = FALSE; +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if ((pEid->Octet[3] & 0x04)) + ie_list->bSupportHiddenWPS = TRUE; + else + ie_list->bSupportHiddenWPS = FALSE; + + if((pEid->Len - NTGR_OUI_LEN) >= NTGR_CUSTOM_IE_MAX_LEN) + { + ie_list->bRunningHiddenWPS = (pEid->Octet[5] & HIDDEN_WPS_STATE_RUNNING) ? TRUE : FALSE; + ie_list->bHiddenWPSRegistrar = (pEid->Octet[5] & HIDDEN_WPS_ROLE_REGISTRAR) ? TRUE : FALSE; + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + } + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); +#endif /* SMART_MESH */ + } +#endif /* defined(SMART_MESH) || defined(SMART_MESH_MONITOR) */ + else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + /* parsing EDCA parameters*/ + ie_list->EdcaParm.bValid = TRUE; + ie_list->EdcaParm.bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + ie_list->EdcaParm.bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + ie_list->EdcaParm.bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + ie_list->EdcaParm.EdcaUpdateCount = pEid->Octet[6] & 0x0f; + ie_list->EdcaParm.bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/ + ie_list->EdcaParm.bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/ + ie_list->EdcaParm.Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/ + ie_list->EdcaParm.Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/ + ie_list->EdcaParm.Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/ + ie_list->EdcaParm.Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/ + ptr += 4; /* point to next AC*/ + } + } + else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + /* parsing EDCA parameters*/ + ie_list->EdcaParm.bValid = TRUE; + ie_list->EdcaParm.bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + ie_list->EdcaParm.bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + ie_list->EdcaParm.bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + ie_list->EdcaParm.EdcaUpdateCount = pEid->Octet[6] & 0x0f; + ie_list->EdcaParm.bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + + /* use default EDCA parameter*/ + ie_list->EdcaParm.bACM[QID_AC_BE] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_BE] = 3; + ie_list->EdcaParm.Cwmin[QID_AC_BE] = pAd->wmm_cw_min; + ie_list->EdcaParm.Cwmax[QID_AC_BE] = pAd->wmm_cw_max; + ie_list->EdcaParm.Txop[QID_AC_BE] = 0; + + ie_list->EdcaParm.bACM[QID_AC_BK] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_BK] = 7; + ie_list->EdcaParm.Cwmin[QID_AC_BK] = pAd->wmm_cw_min; + ie_list->EdcaParm.Cwmax[QID_AC_BK] = pAd->wmm_cw_max; + ie_list->EdcaParm.Txop[QID_AC_BK] = 0; + + ie_list->EdcaParm.bACM[QID_AC_VI] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_VI] = 2; + ie_list->EdcaParm.Cwmin[QID_AC_VI] = pAd->wmm_cw_min - 1; + ie_list->EdcaParm.Cwmax[QID_AC_VI] = pAd->wmm_cw_max; + ie_list->EdcaParm.Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/ + + ie_list->EdcaParm.bACM[QID_AC_VO] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_VO] = 2; + ie_list->EdcaParm.Cwmin[QID_AC_VO] = pAd->wmm_cw_min - 2; + ie_list->EdcaParm.Cwmax[QID_AC_VO] = pAd->wmm_cw_max - 1; + ie_list->EdcaParm.Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/ + } + else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) +#ifdef IWSC_SUPPORT + || NdisEqualMemory(pEid->Octet, IWSC_OUI, 4) +#endif // IWSC_SUPPORT // + ) + { + if (pPeerWscIe) + { + /* Ignore old WPS IE fragments, if we get the version 0x10 */ + if (pEid->Octet[4] == 0x10) //First WPS IE will have version 0x10 + { + NdisMoveMemory(pPeerWscIe, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen = (pEid->Len - 4); + } + else // reassembly remanning, other IE fragmentations will not have version 0x10 + { + if ((PeerWscIeLen +(pEid->Len - 4)) <= 512) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen += (pEid->Len - 4); + } + else /* ((PeerWscIeLen +(pEid->Len - 4)) > 512) */ + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! Sum of All PeerWscIeLen = %d (> 512)\n", __FUNCTION__, (PeerWscIeLen +(pEid->Len - 4)))); + } + } + } + else + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! pPeerWscIe is empty!\n", __FUNCTION__)); + } + +#ifdef IWSC_SUPPORT + if (NdisEqualMemory(pEid->Octet, IWSC_OUI, 4)) + bFoundIWscIe = TRUE; +#endif /* IWSC_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + if ( SubType == SUBTYPE_BEACON ) + { + PUCHAR pData; + INT Len = 0; + USHORT DataLen = 0; + PWSC_IE pWscIE; + + pData = (PUCHAR) pEid->Octet + 4; + Len = (SHORT)(pEid->Len - 4); + + while (Len > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + // Check for WSC IEs + pWscIE = &WscIE; + + if (be2cpu16(pWscIE->Type) == 0x1041 /*WSC_ID_SEL_REGISTRAR*/ ) + { + DataLen = be2cpu16(pWscIE->Length); + NdisMoveMemory(&ie_list->selReg, pData + 4, sizeof(ie_list->selReg)); + break; + } + + // Set the offset and look for next WSC Tag information + // Since Type and Length are both short type, we need to offset 4, not 2 + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } + + + //WscGetDataFromPeerByTag(pAd, pPeerWscIe, PeerWscIeLen, WSC_ID_SEL_REGISTRAR, &bSelReg, NULL); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + } + + + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&ie_list->ExtRate[0], pEid->Octet, pEid->Len); + ie_list->ExtRateLen = pEid->Len; + + /* + TODO: 2004-09-14 not a good design here, cause it exclude extra rates + from ScanTab. We should report as is. And filter out unsupported + rates in MlmeAux + */ + /* Check against the supported rates*/ + /* RTMPCheckRates(pAd, ExtRate, pExtRateLen);*/ + } + break; + + case IE_ERP: + if (pEid->Len == 1) + ie_list->Erp = (UCHAR)pEid->Octet[0]; + break; + + case IE_AIRONET_CKIP: + /* + 0. Check Aironet IE length, it must be larger or equal to 28 + Cisco AP350 used length as 28 + Cisco AP12XX used length as 30 + */ + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + /* 1. Copy CKIP flag byte to buffer for process*/ + ie_list->CkipFlag = *(pEid->Octet + 8); + break; + + case IE_AP_TX_POWER: + /* AP Control of Client Transmit Power*/ + /*0. Check Aironet IE length, it must be 6*/ + if (pEid->Len != 0x06) + break; + + /* Get cell power limit in dBm*/ + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + ie_list->AironetCellPowerLimit = *(pEid->Octet + 4); + break; + + /* WPA2 & 802.11i RSN*/ + case IE_RSN: + /* There is no OUI for version anymore, check the group cipher OUI before copying*/ + if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + /* Copy to pVIE which will report to microsoft bssid list.*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; + +#ifdef WAPI_SUPPORT + /* WAPI information element*/ + case IE_WAPI: + if (RTMPEqualMemory(pEid->Octet + 4, WAPI_OUI, 3)) + { + /* Copy to pVIE*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; +#endif /* WAPI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined (EXT_BUILD_CHANNEL_LIST) || defined (RT_CFG80211_SUPPORT) + case IE_COUNTRY: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ + + case IE_QBSS_LOAD: + if (pEid->Len == 5) + { + ie_list->QbssLoad.bValid = TRUE; + ie_list->QbssLoad.StaNum = pEid->Octet[0] + pEid->Octet[1] * 256; + ie_list->QbssLoad.ChannelUtilization = pEid->Octet[2]; + ie_list->QbssLoad.RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256; + + /* Copy to pVIE*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; + + +#ifdef DOT11R_FT_SUPPORT + case IE_FT_MDIE: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif /* DOT11R_FT_SUPPORT */ + + case IE_EXT_CAPABILITY: + if (pEid->Len >= 1) + { + UCHAR cp_len, buf_space = sizeof(EXT_CAP_INFO_ELEMENT); + + cp_len = min(pEid->Len, buf_space); + NdisMoveMemory(&ie_list->ExtCapInfo,&pEid->Octet[0], cp_len); + } + break; + +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (pEid->Len == sizeof(VHT_CAP_IE)) { + NdisMoveMemory(&ie_list->vht_cap_ie, &pEid->Octet[0], sizeof(VHT_CAP_IE)); + ie_list->vht_cap_len = pEid->Len; + } + break; + case IE_VHT_OP: + if (pEid->Len == sizeof(VHT_OP_IE)) { + NdisMoveMemory(&ie_list->vht_op_ie, &pEid->Octet[0], sizeof(VHT_OP_IE)); + ie_list->vht_op_len = pEid->Len; + } + break; + case IE_OPERATING_MODE_NOTIFY: + if (pEid->Len == sizeof(OPERATING_MODE)) { +#ifdef CONFIG_STA_SUPPORT + if (!INFRA_ON(pAd)) + break; + + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + OPERATING_MODE op_mode; + + NdisMoveMemory(&op_mode, &pEid->Octet[0], sizeof(OPERATING_MODE)); + + if (op_mode.rx_nss_type == 0) { + pEntry->force_op_mode = TRUE; + NdisMoveMemory(&pEntry->operating_mode, &op_mode, sizeof(OPERATING_MODE)); + } +#endif /* CONFIG_STA_SUPPORT */ + NdisMoveMemory(&ie_list->operating_mode, &pEid->Octet[0], sizeof(OPERATING_MODE)); + + DBGPRINT(RT_DEBUG_INFO, ("%s() - IE_OPERATING_MODE_NOTIFY(=%d)\n", __FUNCTION__, pEid->Eid)); + } + break; +#endif /* DOT11_VHT_AC */ + + default: + break; + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + LatchRfChannel = MsgChannel; + + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) + { + if (CtrlChannel != 0) + ie_list->Channel = CtrlChannel; + else { + if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) +#ifdef DOT11_VHT_AC + || (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_80) +#endif /* DOT11_VHT_AC */ + ) { + if (pAd->MlmeAux.Channel) + ie_list->Channel = pAd->MlmeAux.Channel; + else + ie_list->Channel = pAd->CommonCfg.Channel; + } + else + ie_list->Channel = LatchRfChannel; + } + Sanity |= 0x4; + } + + if (pPeerWscIe && (PeerWscIeLen > 0) && (PeerWscIeLen <= 512) && ( bWscCheck == TRUE)) + { + UCHAR WscIe[] = {0xdd, 0x00, 0x00, 0x50, 0xF2, 0x04}; + Ptr = (PUCHAR) pVIE; + WscIe[1] = PeerWscIeLen + 4; + NdisMoveMemory(Ptr + *LengthVIE, WscIe, 6); + NdisMoveMemory(Ptr + *LengthVIE + 6, pPeerWscIe, PeerWscIeLen); + *LengthVIE += (PeerWscIeLen + 6); +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (SubType == SUBTYPE_PROBE_RSP) && + (bFoundIWscIe == TRUE)) + { + BOOLEAN bSelReg = FALSE; + USHORT DataLen = 0; + + /* re-use this boolean variable */ + bFoundIWscIe = FALSE; + WscGetDataFromPeerByTag(pAd, pPeerWscIe, PeerWscIeLen, WSC_ID_SEL_REGISTRAR, &bSelReg, NULL); + if (bSelReg) + { + bFoundIWscIe = TRUE; + if (WscGetDataFromPeerByTag(pAd, + pPeerWscIe, + PeerWscIeLen, + WSC_ID_MAC_ADDR, + &pAd->StaCfg.WscControl.WscPeerMAC[0], + NULL) == FALSE) + { + NdisMoveMemory(&pAd->StaCfg.WscControl.WscPeerMAC[0], &ie_list->Addr2[0], MAC_ADDR_LEN); + } + NdisMoveMemory(&pAd->StaCfg.WscControl.EntryAddr[0], + &pAd->StaCfg.WscControl.WscPeerMAC[0], + MAC_ADDR_LEN); + hex_dump("PeerBeaconAndProbeRspSanity - WscPeerMAC", &pAd->StaCfg.WscControl.WscPeerMAC[0], MAC_ADDR_LEN); + + WscGetDataFromPeerByTag(pAd, + pPeerWscIe, + PeerWscIeLen, + WSC_ID_SEL_REG_CFG_METHODS, + &PeerConfigMethod, + NULL); + } + } +#endif /* IWSC_SUPPORT */ + } + + +SanityCheck: + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + + if ((Sanity != 0x7) || ( bWscCheck == FALSE)) + { + DBGPRINT(RT_DEBUG_LOUD, ("%s() - missing field, Sanity=0x%02x\n", __FUNCTION__, Sanity)); + return FALSE; + } + else + { +#ifdef IWSC_SUPPORT + if (bFoundIWscIe && (pAd->StaCfg.BssType == BSS_ADHOC)) + { + PWSC_CTRL pWscCtrl = &pAd->StaCfg.WscControl; + if ((pWscCtrl->WscConfMode == WSC_ENROLLEE) && + (pWscCtrl->WscMode == WSC_PIN_MODE) && + (pWscCtrl->bWscTrigger == TRUE)) + { + NdisZeroMemory(&pWscCtrl->WscSsid, sizeof(NDIS_802_11_SSID)); + if ((ie_list->SsidLen) <= 32 && (ie_list->SsidLen) != 0) + { + pWscCtrl->WscSsid.SsidLength = ie_list->SsidLen; + NdisMoveMemory(pWscCtrl->WscSsid.Ssid, &ie_list->Ssid[0], pWscCtrl->WscSsid.SsidLength); + PeerConfigMethod = be2cpu16(PeerConfigMethod); + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_PEER_PROBE_RSP, sizeof(USHORT), &PeerConfigMethod, 0); + } + } + } +#endif /* IWSC_SUPPORT */ + return TRUE; + } +} + + +#ifdef DOT11N_DRAFT3 +/* + ========================================================================== + Description: + MLME message sanity check for some IE addressed in 802.11n d3.03. + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN OVERLAP_BSS_SCAN_IE *BssScan, + OUT UCHAR *RegClass) +{ + CHAR *Ptr; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc; + + pFrame = (PFRAME_802_11)Msg; + + *RegClass = 0; + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + /* get timestamp from payload and advance the pointer*/ + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer*/ + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer*/ + Ptr += 2; + Length += 2; + + pEid = (PEID_STRUCT) Ptr; + brc = FALSE; + + RTMPZeroMemory(BssScan, sizeof(OVERLAP_BSS_SCAN_IE)); + /* get variable fields from payload and advance the pointer*/ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_SUPP_REG_CLASS: + if(pEid->Len > 0) + { + *RegClass = *pEid->Octet; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_REG_CLASS (len=%d)\n",pEid->Len)); + } + break; + case IE_OVERLAPBSS_SCAN_PARM: + if (pEid->Len == sizeof(OVERLAP_BSS_SCAN_IE)) + { + brc = TRUE; + RTMPMoveMemory(BssScan, pEid->Octet, sizeof(OVERLAP_BSS_SCAN_IE)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_OVERLAPBSS_SCAN_PARM (len=%d)\n",pEid->Len)); + } + break; + + case IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT: + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT\n")); + break; + + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return brc; + +} +#endif /* DOT11N_DRAFT3 */ + +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pBssType, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pScanType +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + , + OUT UINT *pChannel, + OUT UINT *pTimeout +#endif +#endif + ) +{ + MLME_SCAN_REQ_STRUCT *Info; + + Info = (MLME_SCAN_REQ_STRUCT *)(Msg); + *pBssType = Info->BssType; + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + *pScanType = Info->ScanType; +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + *pChannel = Info->Channel; + *pTimeout = Info->Timeout; +#endif +#endif + + if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) + && (SCAN_MODE_VALID(*pScanType)) + ) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); + return FALSE; + } +} +#endif + +/* IRQL = DISPATCH_LEVEL*/ +UCHAR ChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + + for (i = 0; i < pAd->ChannelListNum; i ++) + { + if (channel == pAd->ChannelList[i].Channel) + return 1; + } + return 0; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDeauthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr1, + OUT PUCHAR pAddr2, + OUT PUCHAR pAddr3, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr1, pFrame->Hdr.Addr1); + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + COPY_MAC_ADDR(pAddr3, pFrame->Hdr.Addr3); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *pAlg, + OUT USHORT *pSeq, + OUT USHORT *pStatus, + CHAR *pChlgText) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); + NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); + NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); + NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); + + if (*pAlg == AUTH_MODE_OPEN) + { + if (*pSeq == 1 || *pSeq == 2) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } + else if (*pAlg == AUTH_MODE_KEY) + { + if (*pSeq == 1 || *pSeq == 4) + { + return TRUE; + } + else if (*pSeq == 2 || *pSeq == 3) + { + NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } +#ifdef DOT11R_FT_SUPPORT + else if (*pAlg == AUTH_MODE_FT) + { + return TRUE; + } +#endif /* DOT11R_FT_SUPPORT */ + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *pTimeout, + OUT USHORT *pAlg) +{ + MLME_AUTH_REQ_STRUCT *pInfo; + + pInfo = (MLME_AUTH_REQ_STRUCT *)Msg; + COPY_MAC_ADDR(pAddr, pInfo->Addr); + *pTimeout = pInfo->Timeout; + *pAlg = pInfo->Alg; + + if (((*pAlg == AUTH_MODE_KEY) ||(*pAlg == AUTH_MODE_OPEN) +#ifdef DOT11R_FT_SUPPORT + || (*pAlg == AUTH_MODE_FT) +#endif /* DOT11R_FT_SUPPORT */ + ) && + ((*pAddr & 0x01) == 0)) + { +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_INCLUDED + if (pAd->StaCfg.WscControl.bWscTrigger && (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE)) + *pAlg = AUTH_MODE_OPEN; +#endif /* WSC_INCLUDED */ +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *pCapabilityInfo, + OUT ULONG *pTimeout, + OUT USHORT *pListenIntv) +{ + MLME_ASSOC_REQ_STRUCT *pInfo; + + pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg; + *pTimeout = pInfo->Timeout; /* timeout*/ + COPY_MAC_ADDR(pApAddr, pInfo->Addr); /* AP address*/ + *pCapabilityInfo = pInfo->CapabilityInfo; /* capability info*/ + *pListenIntv = pInfo->ListenIntv; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Sanity check NetworkType (11b, 11g or 11a) + + Arguments: + pBss - Pointer to BSS table. + + Return Value: + Ndis802_11DS .......(11b) + Ndis802_11OFDM24....(11g) + Ndis802_11OFDM5.....(11a) + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(BSS_ENTRY *pBss) +{ + NDIS_802_11_NETWORK_TYPE NetWorkType; + UCHAR rate, i; + + NetWorkType = Ndis802_11DS; + + if (pBss->Channel <= 14) + { + + /* First check support Rate.*/ + for (i = 0; i < pBss->SupRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit*/ + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + + /* Otherwise (even rate > 108) means Ndis802_11OFDM24*/ + NetWorkType = Ndis802_11OFDM24; + break; + } + } + + + /* Second check Extend Rate.*/ + if (NetWorkType != Ndis802_11OFDM24) + { + for (i = 0; i < pBss->ExtRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit*/ + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + + /* Otherwise (even rate > 108) means Ndis802_11OFDM24*/ + NetWorkType = Ndis802_11OFDM24; + break; + } + } + } + } + else + { + NetWorkType = Ndis802_11OFDM5; + } + + if (pBss->HtCapabilityLen != 0) + { + if (NetWorkType == Ndis802_11OFDM5) { +#ifdef DOT11_VHT_AC + if (pBss->vht_cap_len != 0) + NetWorkType = Ndis802_11OFDM5_AC; + else +#endif /* DOT11_VHT_AC */ + NetWorkType = Ndis802_11OFDM5_N; + } else + NetWorkType = Ndis802_11OFDM24_N; + } + + return NetWorkType; +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +BOOLEAN MlmeDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason) +{ + MLME_DLS_REQ_STRUCT *pInfo; + + pInfo = (MLME_DLS_REQ_STRUCT *)Msg; + + *pDLS = pInfo->pDLS; + *pReason = pInfo->Reason; + + return TRUE; +} +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef QOS_DLS_SUPPORT +BOOLEAN PeerDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pDlsTimeout, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + PEID_STRUCT eid_ptr; + + /* to prevent caller from using garbage output value*/ + *pCapabilityInfo = 0; + *pDlsTimeout = 0; + *pHtCapabilityLen = 0; + + Ptr = (PCHAR)Fr->Octet; + + /* offset to destination MAC address (Category and Action field)*/ + Ptr += 2; + + /* get DA from payload and advance the pointer*/ + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + /* get SA from payload and advance the pointer*/ + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(pDlsTimeout, Ptr, 2); + Ptr += 2; + + /* Category and Action field + DA + SA + capability + Timeout*/ + eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); + DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); + *pRatesLen = eid_ptr->Len; + } + else + { + *pRatesLen = 8; + Rates[0] = 0x82; + Rates[1] = 0x84; + Rates[2] = 0x8b; + Rates[3] = 0x96; + Rates[4] = 0x12; + Rates[5] = 0x24; + Rates[6] = 0x48; + Rates[7] = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); + *pRatesLen = (*pRatesLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); + *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_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 */ + *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + break; + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN PeerDlsRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + PEID_STRUCT eid_ptr; + + /* to prevent caller from using garbage output value*/ + if (pStatus) + *pStatus = 0; + *pCapabilityInfo = 0; + *pHtCapabilityLen = 0; + + Ptr = (PCHAR)Fr->Octet; + + /* offset to destination MAC address (Category and Action field)*/ + Ptr += 2; + + /* get status code from payload and advance the pointer*/ + if (pStatus) + NdisMoveMemory(pStatus, Ptr, 2); + Ptr += 2; + + /* get DA from payload and advance the pointer*/ + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + /* get SA from payload and advance the pointer*/ + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + if (pStatus == 0) + { + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + } + + /* Category and Action field + status code + DA + SA + capability*/ + eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); + DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); + *pRatesLen = eid_ptr->Len; + } + else + { + *pRatesLen = 8; + Rates[0] = 0x82; + Rates[1] = 0x84; + Rates[2] = 0x8b; + Rates[3] = 0x96; + Rates[4] = 0x12; + Rates[5] = 0x24; + Rates[6] = 0x48; + Rates[7] = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); + *pRatesLen = (*pRatesLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); + *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_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 */ + *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + break; + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN PeerDlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + + /* to prevent caller from using garbage output value*/ + *pReason = 0; + + Ptr = (PCHAR)Fr->Octet; + + /* offset to destination MAC address (Category and Action field)*/ + Ptr += 2; + + /* get DA from payload and advance the pointer*/ + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + /* get SA from payload and advance the pointer*/ + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + /* get reason code from payload and advance the pointer*/ + NdisMoveMemory(pReason, Ptr, 2); + Ptr += 2; + + return TRUE; +} +#endif /* QOS_DLS_SUPPORT */ + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PEER_PROBE_REQ_PARAM *ProbeReqParam) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + UCHAR *Ptr; + UCHAR eid =0, eid_len = 0, *eid_data; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = MAIN_MBSSID; + UCHAR Addr1[MAC_ADDR_LEN]; +#ifdef WSC_INCLUDED + UCHAR *pPeerWscIe = NULL; + UINT PeerWscIeLen = 0; + BOOLEAN bWscCheck = TRUE; +#endif /* WSC_INCLUDED */ +#endif /* CONFIG_AP_SUPPORT */ + UINT total_ie_len = 0; +#ifdef SMART_MESH_MONITOR + ProbeReqParam->vendor_ie_len = 0; + IE_LISTS *ie_lists = &ProbeReqParam->ie_list; +#endif /* SMART_MESH_MONITOR */ + + NdisZeroMemory(ProbeReqParam, sizeof(*ProbeReqParam)); + + /* to prevent caller from using garbage output value*/ +#ifdef CONFIG_AP_SUPPORT + apidx = apidx; /* avoid compile warning */ +#endif /* CONFIG_AP_SUPPORT */ + + COPY_MAC_ADDR(ProbeReqParam->Addr2, &Fr->Hdr.Addr2); + + if (Fr->Octet[0] != IE_SSID || Fr->Octet[1] > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): sanity fail - wrong SSID IE\n", __FUNCTION__)); + return FALSE; + } + + ProbeReqParam->SsidLen = Fr->Octet[1]; + NdisMoveMemory(ProbeReqParam->Ssid, &Fr->Octet[2], ProbeReqParam->SsidLen); + +#ifdef CONFIG_AP_SUPPORT + COPY_MAC_ADDR(Addr1, &Fr->Hdr.Addr1); +#ifdef WSC_AP_SUPPORT + os_alloc_mem(NULL, &pPeerWscIe, 512); +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef SMART_MESH_MONITOR + COPY_MAC_ADDR(ie_lists->Addr2, Fr->Hdr.Addr2); +#endif /* SMART_MESH_MONITOR */ + + Ptr = Fr->Octet; + eid = Ptr[0]; + eid_len = Ptr[1]; + total_ie_len = eid_len + 2; + eid_data = Ptr+2; + +#ifdef RSSI_FEEDBACK + ProbeReqParam->bRequestRssi = FALSE; +#endif /* RSSI_FEEDBACK */ + + /* get variable fields from payload and advance the pointer*/ + while((eid_data + eid_len) <= ((UCHAR*)Fr + MsgLen)) + { + switch(eid) + { + case IE_VENDOR_SPECIFIC: + if (eid_len <= 4) + break; +#ifdef RSSI_FEEDBACK + if (NdisEqualMemory(eid_data, RALINK_OUI, 3) && (eid_len == 7)) + { + if (*(eid_data + 3/* skip RALINK_OUI */) & 0x8) + ProbeReqParam->bRequestRssi = TRUE; + break; + } +#endif /* RSSI_FEEDBACK */ + + if (NdisEqualMemory(eid_data, WPS_OUI, 4) + #ifdef IWSC_SUPPORT + || NdisEqualMemory(eid_data, IWSC_OUI, 4) +#endif // IWSC_SUPPORT // + ) + { +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WSC_INCLUDED + + +#ifdef IWSC_SUPPORT +#ifdef CONFIG_STA_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + if (NdisEqualMemory(eid_data, IWSC_OUI, 4)) + WscCheckPeerDPID(pAd, Fr, eid_data, eid_len); + } + else if (NdisEqualMemory(eid_data, WPS_OUI, 4)) +#endif /* CONFIG_STA_SUPPORT */ +#endif /* IWSC_SUPPORT */ + WscCheckPeerDPID(pAd, Fr, eid_data, eid_len); + +#ifdef CONFIG_AP_SUPPORT + if (pPeerWscIe) + { + /* Ignore old WPS IE fragments, if we get the version 0x10 */ + if (*(eid_data+4) == 0x10) //First WPS IE will have version 0x10 + { + NdisMoveMemory(pPeerWscIe, eid_data+4, eid_len-4); + PeerWscIeLen = (eid_len-4); + } + else // reassembly remanning, other IE fragmentations will not have version 0x10 + { + if ((PeerWscIeLen +(eid_len-4)) <= 512) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, eid_data+4, eid_len-4); + PeerWscIeLen += (eid_len-4); + } + else /* ((PeerWscIeLen +(eid_len-4)) > 512) */ + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! Sum of All PeerWscIeLen = %d (> 512)\n", __FUNCTION__, (PeerWscIeLen +(eid_len-4)))); + } + } + } + else + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! pPeerWscIe is empty!\n", __FUNCTION__)); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + } +#if defined(SMART_MESH) || defined(SMART_MESH_MONITOR) + if ((eid_len >= NTGR_OUI_LEN) && NdisEqualMemory(eid_data, NETGEAR_OUI, NTGR_OUI_LEN)) + { +#ifdef SMART_MESH + if(eid_len > NTGR_OUI_LEN) + ProbeReqParam->VIEFlag = *(eid_data + NTGR_OUI_LEN); +#endif /* SMART_MESH */ + if(eid_len <= NTGR_IE_TOTAL_LEN) + { +#ifdef SMART_MESH_MONITOR + ProbeReqParam->vendor_ie_len = (eid_len - NTGR_OUI_LEN); + NdisMoveMemory(ProbeReqParam->vendor_ie, (eid_data + NTGR_OUI_LEN),ProbeReqParam->vendor_ie_len); +#endif /* SMART_MESH_MONITOR */ + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! vendor infomation element too large!\n", __FUNCTION__)); + } +#endif /* defined(SMART_MESH) || defined(SMART_MESH_MONITOR) */ + break; +#ifdef CONFIG_HOTSPOT + case IE_INTERWORKING: + ProbeReqParam->AccessNetWorkType = (*eid_data) & 0x0F; + + if (eid_len > 3) + { + if (eid_len == 7) + NdisMoveMemory(ProbeReqParam->Hessid, eid_data + 1, MAC_ADDR_LEN); + else + NdisMoveMemory(ProbeReqParam->Hessid, eid_data + 3 , MAC_ADDR_LEN); + + ProbeReqParam->IsHessid = TRUE; + } + + ProbeReqParam->IsIWIE = TRUE; + break; +#endif + case IE_EXT_CAPABILITY: +#ifdef CONFIG_HOTSPOT + if (eid_len >= 4) + { + if (((*(eid_data + 3)) & 0x80) == 0x80) + ProbeReqParam->IsIWCapability = TRUE; + } +#endif + break; +#ifdef SMART_MESH_MONITOR +#ifdef DOT11_N_SUPPORT + case IE_HT_CAP: + case IE_HT_CAP2: + if (eid_len >= SIZE_HT_CAP_IE) + { + NdisMoveMemory(&ie_lists->HTCapability, eid_data, SIZE_HT_CAP_IE); + *(USHORT *)(&ie_lists->HTCapability.HtCapInfo) = cpu2le16(*(USHORT *)(&ie_lists->HTCapability.HtCapInfo)); + *(USHORT *)(&ie_lists->HTCapability.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&ie_lists->HTCapability.ExtHtCapInfo)); + ie_lists->ht_cap_len = SIZE_HT_CAP_IE; + } + else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_HT_CAP\n", __FUNCTION__)); + } + break; +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (eid_len == sizeof(VHT_CAP_IE)) { + NdisMoveMemory(&ie_lists->vht_cap, eid_data, sizeof(VHT_CAP_IE)); + ie_lists->vht_cap_len = sizeof(VHT_CAP_IE); + } + else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP\n", __FUNCTION__)); + } + break; + + case IE_VHT_OP: + if (eid_len == sizeof(VHT_OP_IE)) { + NdisMoveMemory(&ie_lists->vht_op, eid_data, sizeof(VHT_OP_IE)); + ie_lists->vht_op_len = sizeof(VHT_OP_IE); + } + else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_OP\n", __FUNCTION__)); + } + break; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ +#endif /* SMART_MESH_MONITOR */ + default: + break; + } + eid = Ptr[total_ie_len]; + eid_len = Ptr[total_ie_len + 1]; + eid_data = Ptr + total_ie_len + 2; + total_ie_len += (eid_len + 2); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_INCLUDED + if (pPeerWscIe && (PeerWscIeLen > 0) && (bWscCheck == TRUE)) + { + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (NdisEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN)) + break; + } + + /* + Due to Addr1 in Probe Request may be FF:FF:FF:FF:FF:FF + and we need to send out this information to external registrar. + Therefore we choose ra0 to send this probe req when we couldn't find apidx by Addr1. + */ + if (apidx >= pAd->ApCfg.BssidNum) + { + apidx = MAIN_MBSSID; + } + + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode & WSC_PROXY) != WSC_DISABLE) + { + int bufLen = 0; + PUCHAR pBuf = NULL; + WSC_IE_PROBREQ_DATA *pprobreq = NULL; + + /* + PeerWscIeLen: Len of WSC IE without WSC OUI + */ + bufLen = sizeof(WSC_IE_PROBREQ_DATA) + PeerWscIeLen; + os_alloc_mem(NULL, &pBuf, bufLen); + if(pBuf) + { + /*Send WSC probe req to UPnP*/ + NdisZeroMemory(pBuf, bufLen); + pprobreq = (WSC_IE_PROBREQ_DATA*)pBuf; + if (32 >= ProbeReqParam->SsidLen) /*Well, I think that it must be TRUE!*/ + { + NdisMoveMemory(pprobreq->ssid, ProbeReqParam->Ssid, ProbeReqParam->SsidLen); /* SSID*/ + NdisMoveMemory(pprobreq->macAddr, Fr->Hdr.Addr2, 6); /* Mac address*/ + pprobreq->data[0] = PeerWscIeLen>>8; /* element ID*/ + pprobreq->data[1] = PeerWscIeLen & 0xff; /* element Length */ + NdisMoveMemory((pBuf+sizeof(WSC_IE_PROBREQ_DATA)), pPeerWscIe, PeerWscIeLen); /* (WscProbeReqData)*/ + WscSendUPnPMessage(pAd, apidx, + WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_PROBE_REQ, + pBuf, bufLen, 0, 0, &Fr->Hdr.Addr2[0], AP_MODE); + } + os_free_mem(NULL, pBuf); + } + } + } + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); +#endif /* WSC_INCLUDED */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_sync.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_sync.c new file mode 100644 index 000000000..abfcc281a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_sync.c @@ -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; iTxPower[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;iChannelListNum;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;iChannelListNum;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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_tkip.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_tkip.c new file mode 100644 index 000000000..ac22f4c4a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_tkip.c @@ -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); +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_txbf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_txbf.c new file mode 100644 index 000000000..edfbf7c72 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_txbf.c @@ -0,0 +1,1311 @@ +/* + *************************************************************************** + * 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: + cmm_txbf.c + + Abstract: + Tx Beamforming related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Shiang 2009/11/04 +*/ + +#include "rt_config.h" + +#ifdef TXBF_SUPPORT + +#define ETXBF_PROBE_TIME (RA_INTERVAL-100) /* Wait for Sounding Response will time out 100msec before end of RA interval */ + + +#ifdef MFB_SUPPORT + +UCHAR mcsToLowerMcs[] = { +/* originalMfb, newMfb1s, newMfb2s, newMfb3s*/ + 0, 0, 0, 0, + 1, 1, 1, 1, + 2, 2, 2, 2, + 3, 3, 3, 3, + 4, 4, 4, 4, + 5, 5, 5, 5, + 6, 6, 6, 6, + 7, 7, 7, 7, + 8, 0, 8, 8, + 9, 1, 9, 9, + 10, 2, 10, 10, + 11, 3, 11, 11, + 12, 4, 12, 12, + 13, 5, 13, 13, + 14, 6, 14, 14, + 15, 7, 15, 15, + 16, 0, 8, 16, + 17, 1, 9, 17, + 18, 2, 10, 18, + 19, 3, 11, 19, + 20, 4, 12, 20, + 21, 5, 13, 21, + 22, 6, 14, 22, + 23, 7, 15, 23, + 24, 0, 8, 16, + 25, 1, 9, 17, + 26, 2, 10, 18, + 27, 3, 11, 19, + 28, 4, 12, 20, + 29, 5, 13, 21, + 30, 6, 14, 22, + 31, 7, 15, 23, + 32, 0, 0, 0, + 33, 3, 3, 3, + 34, 3, 3, 3, + 35, 3, 11, 11, + 36, 4, 4, 4, + 37, 6, 6, 6, + 38, 6, 12, 12, + 39, 3, 3, 17, + 40, 3, 11, 11, + 41, 3, 3, 17, + 42, 3, 11, 11, + 43, 3, 11, 19, + 44, 3, 11, 11, + 45, 3, 11, 19, + 46, 4, 4, 18, + 47, 4, 12, 12, + 48, 6, 6, 6, + 49, 6, 12, 12, + 50, 6, 12, 20, + 51, 6, 14, 14, + 52, 6, 14, 14, + 53, 3, 3, 17, + 54, 3, 11, 11, + 55, 3, 11, 19, + 56, 3, 3, 17, + 57, 3, 11, 11, + 58, 3, 11, 19, + 59, 3, 11, 19, + 60, 3, 11, 11, + 61, 3, 11, 19, + 62, 3, 11, 19, + 63, 3, 11, 19, + 64, 3, 11, 19, + 65, 4, 4, 18, + 66, 4, 12, 12, + 67, 4, 12, 20, + 68, 6, 6, 6, + 69, 6, 12, 12, + 70, 6, 12, 20, + 71, 6, 12, 20, + 72, 6, 14, 14, + 73, 6, 14, 14, + 74, 6, 14, 14, + 75, 6, 14, 22, + 76, 6, 14, 22 +}; +#endif /* MFB_SUPPORT */ + + +#ifdef ETXBF_EN_COND3_SUPPORT +UCHAR groupShift[] = {4, 4, 4}; +UCHAR groupMethod[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 1, 1, 1, + 0, 0, 1, 0, 1, 1, 1, 1}; +SHORT groupThrd[] = {-8, 4, 20, 32, 52, 68, 80, 88, + -16, 8, 12, 64, 40, 60, 80, 88, + -24, 12, 12, 96, 40, 60, 80, 88}; +UINT dataRate[] = {65, 130, 195, 260, 390, 520, 585, 650, + 130, 260, 390, 520, 780, 1040, 1170, 1300, + 190, 390, 585, 780, 1170, 1560, 1755, 1950}; +#endif /* ETXBF_EN_COND3_SUPPORT */ + + +VOID rtmp_asic_set_bf( + IN RTMP_ADAPTER *pAd) +{ + + UINT Value32; + + +#ifdef MT76x2 + RTMP_IO_READ32(pAd, PFMU_R1, &Value32); + Value32 &= ~0x330; + + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn) + Value32 |= 0x120; + else + Value32 &= (~0x120); + + if (pAd->CommonCfg.ETxBfEnCond > 0) + Value32 |= 0x210; + else + Value32 &= ~0x210; + + RTMP_IO_WRITE32(pAd, PFMU_R1, Value32); + + RTMP_IO_READ32(pAd, PFMU_R0, &Value32); + Value32 &= ~((0x1 << 6) | 0x3); + + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn) + Value32 |= ((0x1 << 6) | 0x1); + else + Value32 &= ~((0x1 << 6) | 0x1); + + if (pAd->CommonCfg.ETxBfEnCond > 0) + { + Value32 |= (0x1 << 6) | 0x2; + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_2, 0xFFFFFFFF); + } + else + Value32 &= ~((0x1 << 6) | 0x2); + + RTMP_IO_WRITE32(pAd, PFMU_R0, Value32); + + //Set eBF profile timeout + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_3, 0xFFFF); //set eBF timeout + RTMP_IO_WRITE32(pAd, PFMU_R8, 0xFFFF); //set iBF timeout + + //Set iBF profile extension enable + RTMP_IO_READ32(pAd, PFMU_R51, &Value32 ); + Value32 |= 0x003F0000; + RTMP_IO_WRITE32(pAd, PFMU_R51, Value32); +#endif +} + +/* + TxBFInit - Intialize TxBF fields in pEntry + supportsETxBF - TRUE if client supports ETxBF +*/ +VOID TxBFInit( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN BOOLEAN supportsETxBF) +{ + pEntry->bfState = READY_FOR_SNDG0; + pEntry->sndgMcs = 0; + pEntry->sndg0Snr0 = 0; + pEntry->sndg0Snr1 = 0; + pEntry->sndg0Snr2 = 0; + pEntry->sndg0Mcs = 0; +#ifdef ETXBF_EN_COND3_SUPPORT + pEntry->sndgRateIdx = 0; + pEntry->sndg0RateIdx = 0; + pEntry->sndg1Mcs = 0; + pEntry->sndg1RateIdx = 0; + pEntry->sndg1Snr0 = 0; + pEntry->sndg1Snr1 = 0; + pEntry->sndg1Snr2 = 0; + pEntry->bf0Mcs = 0; + pEntry->bf0RateIdx = 0; + pEntry->bf1Mcs = 0; + pEntry->bf1RateIdx = 0; +#endif /* EXTBF_EN_COND3_SUPPORT */ + pEntry->noSndgCnt = 0; + pEntry->eTxBfEnCond = supportsETxBF? pAd->CommonCfg.ETxBfEnCond: 0; + pEntry->noSndgCntThrd = NO_SNDG_CNT_THRD; + pEntry->ndpSndgStreams = pAd->Antenna.field.TxPath; + + /* If client supports ETxBf and ITxBF then give ETxBF priority over ITxBF */ + pEntry->iTxBfEn = pEntry->eTxBfEnCond> 0 ? 0 : pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn; + +} + +BOOLEAN rtmp_chk_itxbf_calibration( + IN RTMP_ADAPTER *pAd) +{ +#ifndef MT76x2 + INT calIdx, calCnt; + USHORT offset, eeVal, *calptr; + UINT32 ee_sum; + USHORT g_caladdr[] = {0x1a0, 0x1a2, 0x1b0, 0x1b2, 0x1b6, 0x1b8}; + USHORT a_caladdr[] = {0x1a4, 0x1a6, 0x1a8, 0x1aa, 0x1ac, 0x1ae, 0x1b4, 0x1ba, 0x1bc, 0x1be, 0x1c0, 0x1c2, 0x1c4, 0x1c6, 0x1c8}; +#else + ITXBF_PHASE_PARAMS phaseParams; + +#endif + BOOLEAN bCalibrated = TRUE; + +#ifndef MT76x2 + if (pAd->CommonCfg.Channel <= 14) + { + calCnt = sizeof(g_caladdr) / sizeof(USHORT); + calptr = &g_caladdr[0] ; + } + else + { + calCnt = sizeof(a_caladdr) / sizeof(USHORT); + calptr = &a_caladdr[0]; + } + + ee_sum = 0; + for (calIdx = 0; calIdx < calCnt; calIdx++) + { + offset = *(calptr + calIdx); + RT28xx_EEPROM_READ16(pAd, offset, eeVal); + ee_sum += eeVal; + DBGPRINT(RT_DEBUG_INFO, ("Check EEPROM(offset=0x%x, eeVal=0x%x, ee_sum=0x%x)!\n", + offset, eeVal, ee_sum)); + if (eeVal!=0xffff && eeVal!=0) + return TRUE; + } + + if ((ee_sum == (0xffff * calCnt)) || (ee_sum == 0x0)) + { + bCalibrated = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM all 0xffff(cnt =%d, sum=0x%x), not valid calibration value!\n", + calCnt, ee_sum)); + } +#else + if (pAd->CommonCfg.Channel <= 14) + { + bCalibrated = FALSE; + } + else + { + bCalibrated = ITxBFGetEEPROM(pAd, &phaseParams, 0, 0, 0); + } + +#endif /*MT76x2*/ + return bCalibrated; +} + + +VOID Trigger_Sounding_Packet( + IN PRTMP_ADAPTER pAd, + IN UCHAR SndgType, + IN UCHAR SndgBW, + IN UCHAR SndgMcs, + IN MAC_TABLE_ENTRY *pEntry) +{ + /* + SngType + 0: disable + 1 : sounding + 2: NDP sounding + */ + NdisAcquireSpinLock(&pEntry->TxSndgLock); + pEntry->TxSndgType = SndgType; + NdisReleaseSpinLock(&pEntry->TxSndgLock); + + RTMPSetTimer(&pEntry->eTxBfProbeTimer, ETXBF_PROBE_TIME); + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in Trigger_Sounding_Packet(): sndgType=%d, bw=%d, mcs=%d\n", SndgType, SndgBW, SndgMcs)); +} + + +/* + eTxBFProbing - called by Rate Adaptation routine each interval. + Initiates a sounding packet if enabled. +*/ +VOID eTxBFProbing( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + if (pEntry->eTxBfEnCond == 0) { + pEntry->bfState = READY_FOR_SNDG0; + } else if (pEntry->noSndgCnt>=pEntry->noSndgCntThrd) { + /* Select NDP sounding, maximum streams */ + pEntry->sndgMcs = (pEntry->ndpSndgStreams==3) ? 16 : 8; + Trigger_Sounding_Packet(pAd, SNDG_TYPE_NDP, 0, pEntry->sndgMcs, pEntry); + + pEntry->bfState = WAIT_SNDG_FB0; + pEntry->noSndgCnt = 0; + } else if (pEntry->bfState == READY_FOR_SNDG0) { + pEntry->noSndgCnt++; + } else pEntry->noSndgCnt = 0; +} + + +/* + clientSupportsETxBF - returns true if client supports compatible Sounding +*/ +BOOLEAN clientSupportsETxBF( + IN PRTMP_ADAPTER pAd, + IN HT_BF_CAP *pTxBFCap) +{ + BOOLEAN compCompat, noncompCompat; + + compCompat = (pTxBFCap->ExpComBF > 0) && + /*(pTxBFCap->ComSteerBFAntSup+1 >= pAd->Antenna.field.TxPath) && */ + (pAd->CommonCfg.ETxBfNoncompress == 0); + + noncompCompat = (pTxBFCap->ExpNoComBF > 0) + /* && (pTxBFCap->NoComSteerBFAntSup+1 >= pAd->Antenna.field.TxPath)*/; + + return pTxBFCap->RxNDPCapable==1 && (compCompat || noncompCompat); +} + + +#ifdef VHT_TXBF_SUPPORT +/* + clientSupportsETxBF - returns true if client supports compatible Sounding +*/ +BOOLEAN clientSupportsVHTETxBF( + IN PRTMP_ADAPTER pAd, + IN VHT_CAP_INFO *pTxBFCap) +{ + return pTxBFCap->bfee_cap_su; +} +#endif + + +/* + setETxBFCap - sets our ETxBF capabilities +*/ +void setETxBFCap(RTMP_ADAPTER *pAd, HT_BF_CAP *pTxBFCap) +{ + if (pAd->CommonCfg.ETxBfIncapable) { + memset(pTxBFCap, 0, sizeof(*pTxBFCap)); + } + else + { + pTxBFCap->RxNDPCapable = TRUE; + pTxBFCap->TxNDPCapable = TRUE; + pTxBFCap->ExpNoComSteerCapable = TRUE; + pTxBFCap->ExpComSteerCapable = !pAd->CommonCfg.ETxBfNoncompress; + pTxBFCap->ExpNoComBF = HT_ExBF_FB_CAP_IMMEDIATE; + pTxBFCap->ExpComBF = pAd->CommonCfg.ETxBfNoncompress? HT_ExBF_FB_CAP_NONE: HT_ExBF_FB_CAP_IMMEDIATE; + pTxBFCap->MinGrouping = 3; +#ifndef MT76x2 + pTxBFCap->NoComSteerBFAntSup = 2; + pTxBFCap->ComSteerBFAntSup = 2; +#else + pTxBFCap->NoComSteerBFAntSup = 1; // 2 Tx antenna sounding + pTxBFCap->ComSteerBFAntSup = 1; // 2 Tx antenna sounding + + pTxBFCap->TxSoundCapable = TRUE; // Support staggered sounding frames +#endif + pTxBFCap->ChanEstimation = pAd->Antenna.field.RxPath-1; + } + + // Disable BFee in AP mode to avoid IOT issue, beacuse MT76x2 can not response to 3x3 or 4x4 sounding +#if defined(CONFIG_AP_SUPPORT) && defined(MT76x2) + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!pAd->CommonCfg.ETxBfeeEn ) + { + pTxBFCap->RxNDPCapable = FALSE; + pTxBFCap->RxSoundCapable = FALSE; + pTxBFCap->ExpNoComBF = HT_ExBF_FB_CAP_NONE; + pTxBFCap->ExpComBF = HT_ExBF_FB_CAP_NONE; + } + } +#endif /*CONFIG_AP_SUPPORT && MT76x2*/ +} + +#ifdef VHT_TXBF_SUPPORT +void setVHTETxBFCap(RTMP_ADAPTER *pAd, VHT_CAP_INFO *pTxBFCap) +{ + if (pAd->CommonCfg.ETxBfIncapable) { + pTxBFCap->num_snd_dimension = 0; + pTxBFCap->bfee_cap_mu = FALSE; + pTxBFCap->bfee_cap_su = FALSE; + pTxBFCap->bfer_cap_mu = FALSE; + pTxBFCap->bfer_cap_su = FALSE; + pTxBFCap->cmp_st_num_bfer = 0; + } + else + { + pTxBFCap->bfee_cap_su = TRUE; + pTxBFCap->bfer_cap_su = TRUE; + pTxBFCap->num_snd_dimension = 1; + pTxBFCap->cmp_st_num_bfer = 1; + } + + // Disable BFee in AP mode to avoid IOT issue, beacuse MT76x2 can not response to 3x3 or 4x4 sounding +#if defined(CONFIG_AP_SUPPORT) && defined(MT76x2) + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!pAd->CommonCfg.ETxBfeeEn ) + { + pTxBFCap->bfee_cap_mu = FALSE; + pTxBFCap->bfee_cap_su = FALSE; + } + } +#endif /*CONFIG_AP_SUPPORT && MT76x2*/ +} +#endif + + +#ifdef ETXBF_EN_COND3_SUPPORT +/* + 4. determine the best method among mfb0, mfb1, snrComb0, snrComb1 + 5. use the best method. if necessary, sndg with the mcs which resulting in the best snrComb. +*/ +/*if mcs is not in group 1 */ +VOID txSndgSameMcs( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR smoothMfb)/*smoothMfb should be the current mcs */ +{ + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx, i, step; + BOOLEAN bWriteEnable; + UCHAR SndgType = SNDG_TYPE_SOUNDING; + + if (pEntry->eTxBfEnCond == 0) + { + pEntry->bfState = READY_FOR_SNDG0; + return; + } + + /*0. write down the current mfb0 */ + pEntry->mfb0 = smoothMfb; + + /* 1. sndg with current mcs, get snrComb0 */ + if (smoothMfb >> 3 > 0 ) + { + pEntry->sndgMcs = smoothMfb; + } + else + { + pEntry->sndgMcs = 8; + SndgType = SNDG_TYPE_NDP; + } + + /* if ndp sndg is forced by iwpriv command */ + if (pEntry->ndpSndgStreams == 2 ||pEntry->ndpSndgStreams == 3) + { + SndgType = SNDG_TYPE_NDP; + if (pEntry->ndpSndgStreams == 3) + pEntry->sndgMcs = 16; + else + pEntry->sndgMcs = 8; + } + + /* + smoothMfb is guaranteed included in the current pTable because + it is converted from received MFB in handleHtcField() + */ + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + step = 10; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + step = 5; + for (i=1; i<=TableSize; i++) + { + if (pTable[i*step+2] >= pEntry->sndgMcs) + break; + } + + if (i > TableSize) + i = TableSize - 1; + +/* + DBGPRINT(RT_DEBUG_TRACE, ("txSndgSameMcs i = %x, step = %x, sndgMcs = %x CurrentMCS = %x \n", + i, step, pEntry->sndgMcs, pTable[i*step+2])); +*/ + + pEntry->sndgRateIdx = pTable[i*step]; + if (pEntry->sndgMcs != pTable[i*step+2]) + { + /*pEntry->sndgMcs = pTable[i*step+2];*/ + + if (pTable[i*step+2] > 16) + pEntry->sndgMcs = 16; + else if (pTable[i*step+2] > 8) + pEntry->sndgMcs = 8; + else + pEntry->sndgMcs = 0; + + SndgType = SNDG_TYPE_NDP; + } + + /* Enable/disable BF matrix writing */ + if (pEntry->eTxBfEnCond == 1 || pEntry->eTxBfEnCond == 2) + { + bWriteEnable = TRUE; + pEntry->HTPhyMode.field.eTxBF = 1; + } + else + { + bWriteEnable = FALSE; + } + rtmp_asic_etxbf_write_change(pAd, bWriteEnable); + + /* send a sounding packet*/ + Trigger_Sounding_Packet(pAd, SndgType, 0, pEntry->sndgMcs, pEntry); + + pEntry->bfState = WAIT_SNDG_FB0; + pEntry->noSndgCnt = 0; +} + + +/* + txSndgOtherGroup - NOTE: currently unused. + Only called when ETxBfEnCond==3 +*/ +VOID txSndgOtherGroup( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx, i, step; + UCHAR byteValue = 0; + UCHAR SndgType = SNDG_TYPE_SOUNDING; + + + /* tx sndg with mcs in the other group */ + if ((pEntry->sndgMcs)>>3 == 2) + { + pEntry->sndgMcs = 8; + SndgType = SNDG_TYPE_NDP; + } + else + { + pEntry->sndgMcs = 16; + SndgType = SNDG_TYPE_NDP; + } + /* copied from txSndgSameMcs() */ + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + step = 10; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + step = 5; + for (i=1; i<=TableSize; i++) + { + if (pTable[i*step+2] >= pEntry->sndgMcs) break; + } + + if (i > TableSize) + i = TableSize - 1; + + pEntry->sndgRateIdx = pTable[i*step]; + + if (pEntry->sndgMcs != pTable[i*step+2]) + { + pEntry->sndgMcs = pTable[i*step+2]; + SndgType = SNDG_TYPE_NDP; + } + /*---copied from txSndgSameMcs() end */ + /* disable BF matrix writing */ + rtmp_asic_etxbf_write_change(pAd, FALSE); + Trigger_Sounding_Packet(pAd, SndgType, 0, pEntry->sndgMcs, pEntry); + + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in txSndgOtherGroup(): tx the second SNDG, enter state WAIT_SNDG_FB1\n" )); + + pEntry->bfState = WAIT_SNDG_FB1; +} + +VOID txMrqInvTxBF( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) + +{ + pEntry->toTxMrq = TRUE; + pEntry->msiToTx = MSI_TOGGLE_BF; + +/* pEntry->HTPhyMode.field.TxBF = ~pEntry->HTPhyMode.field.TxBF;done in another function call*/ + + RTMPSetTimer(&pEntry->eTxBfProbeTimer, ETXBF_PROBE_TIME); + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in txMrqInvTxBF(): tx the second MRQ, enter state WAIT_MFB\n" )); + pEntry->bfState = WAIT_MFB; +} + +UINT convertSnrToThroughput( + IN UCHAR streamsIn, + IN INT snr0, + IN INT snr1, + IN INT snr2, + IN PUCHAR pTable, + OUT UCHAR *bestMcsPtr, + OUT UCHAR *bestRateIdxPtr + + ) +{ + + UCHAR streams; + INT snrTemp; + UCHAR i, j; + SHORT idx; + SHORT group; + INT snrTemp1[3]; + INT snr[] = {snr0, snr1, snr2}; + INT snrSum, tpTemp, bestTp=0; + SHORT thrdTemp; + BOOLEAN isMcsValid[24]; + UCHAR rateIdx[24], step, tableSize; + UCHAR mcs; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + step = 10; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + step = 5; + tableSize = RATE_TABLE_SIZE(pTable); + for (i=0; i<24; i++) + { + isMcsValid[i] = FALSE; + rateIdx[i] = 0; + } + for (i=1; i<=tableSize; i++) + { + isMcsValid[pTable[i*step+2]] = TRUE; + rateIdx[pTable[i*step+2]] = pTable[i*step]; + } + + if (streamsIn > 3) + { + DBGPRINT(RT_DEBUG_TRACE,("convertSnrToThroughput(): %d streams are not supported!!!", streamsIn)); + streams = 3; + } + else + streams = streamsIn; + + for (i=0; i=0; group--) + { + snrTemp1[0] = snr[0]; + snrTemp1[1] = snr[1]; + snrTemp1[2] = snr[2]; + /*SNR processing for each group according to the baseband implementation, for example MRC*/ + switch (group) + { + case 0: + snrTemp1[1] = 0; + snrTemp1[2] = 0; + break; + case 1: + snrTemp1[2] = 0; + break; + case 2: + break; + default: + break; + } + snrSum = snr[0] + snr[1] + snr[2]; + for (idx=7; idx>=0; idx--){ + mcs = group*8+idx; + thrdTemp = groupThrd[mcs]; + tpTemp = 0; + if (groupMethod[mcs] == 0) + { + if (snrSum > thrdTemp) + tpTemp = ((snrSum - thrdTemp) * dataRate[mcs])>>groupShift[group]; + } + else + { + if (group == 1) + snrTemp1[2] = thrdTemp + 1; + if (snrTemp1[0] > thrdTemp && snrTemp1[1] > thrdTemp && snrTemp1[2] > thrdTemp) + tpTemp = ((snrTemp1[0] - thrdTemp)*(snrTemp1[1] - thrdTemp)*(snrTemp1[2] - thrdTemp) * dataRate[mcs])>>groupShift[group];/* have to be revised!!!*/ + } + if (tpTemp > dataRate[mcs]) + tpTemp = dataRate[mcs]; + if (tpTemp > bestTp && isMcsValid[mcs] == TRUE) + { + bestTp = tpTemp; + (*bestMcsPtr) = mcs; + (*bestRateIdxPtr) = rateIdx[mcs]; + DBGPRINT(RT_DEBUG_TRACE,("convertSnrToThroughput(): new candidate snr0=%d, snr1=%d, snr2=%d, tp=%d, best MCS=%d\n", snrTemp1[0], snrTemp1[1], snrTemp1[2], tpTemp, *bestMcsPtr)); + } + } + } + DBGPRINT(RT_DEBUG_TRACE,("convertSnrToThroughput(): snr0=%d, snr1=%d, snr2=%d, tp=%d, best MCS=%d\n", snr0, snr1, snr2, bestTp, *bestMcsPtr)); + return bestTp; +} + + +/* + NOTE: currently unused. Only called when ETxBfEnCond==3 +*/ +VOID chooseBestMethod( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR mfb) +{ +/* UCHAR bestMethod;0:original, 1:inverted TxBF, 2:first sndg, 3:second sndg*/ + UINT tp[4], bestTp; + UCHAR streams, i; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx; + UCHAR byteValue = 0; + + pEntry->mfb1 = mfb; + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): received the second MFB %d, noted as mfb1\n", pEntry->mfb1 )); + + if ((pEntry->HTCapability.MCSSet[2] == 0xff) && (pAd->CommonCfg.TxStream == 3)) + { + streams = 3; + } + else if (pEntry->HTCapability.MCSSet[0] == 0xff && pEntry->HTCapability.MCSSet[1] == 0xff && pAd->CommonCfg.TxStream > 1 + && (pAd->CommonCfg.TxStream == 2 || pEntry->HTCapability.MCSSet[2] == 0x0)) + { + streams = 2; + } + else + { + streams = 1; + } + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + + tp[2] = convertSnrToThroughput(streams, pEntry->sndg0Snr0, pEntry->sndg0Snr1, pEntry->sndg0Snr2, pTable, &(pEntry->bf0Mcs), &(pEntry->bf0RateIdx)); + tp[3] = convertSnrToThroughput(streams, pEntry->sndg1Snr0, pEntry->sndg1Snr1, pEntry->sndg1Snr2, pTable, &(pEntry->bf1Mcs), &(pEntry->bf1RateIdx)); + tp[0] = dataRate[pEntry->mfb0]; + tp[1] = dataRate[pEntry->mfb1]; + bestTp = 0; + for (i=0; i<4; i++) + { + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): predicted throughput of method %d = %d\n", i, tp[i] )); + if (tp[i] > bestTp) + { + bestTp = tp[i]; + pEntry->bestMethod = i; + } + } + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): method %d is chosen\n", pEntry->bestMethod )); + switch (pEntry->bestMethod) + { + case 0:/*do nothing*/ + pEntry->bfState = READY_FOR_SNDG0; + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): do nothing, and enter state READY_FOR_SNDG0\n" )); + break; + case 1: + pEntry->HTPhyMode.field.eTxBF = ~pEntry->HTPhyMode.field.eTxBF; + pEntry->bfState = READY_FOR_SNDG0; + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): invert the ETxBF status, and enter state READY_FOR_SNDG0\n" )); + break; + case 2: + pEntry->sndgMcs = pEntry->sndg0Mcs; + pEntry->sndgRateIdx = pEntry->sndg0RateIdx; + /* enable BF matrix writing */ + rtmp_asic_etxbf_write_change(pAd, TRUE); + if (pEntry->sndgRateIdx == pEntry->CurrTxRateIndex) + Trigger_Sounding_Packet(pAd, SNDG_TYPE_SOUNDING, 0, pEntry->sndgMcs, pEntry); + else + Trigger_Sounding_Packet(pAd, SNDG_TYPE_NDP, 0, pEntry->sndgMcs, pEntry); + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): tx the SNDG of the best method, enter state WAIT_BEST_SNDG\n" )); + pEntry->bfState = WAIT_BEST_SNDG; + break; + case 3: + /* tx sndg with mcs in the other group */ + pEntry->sndgMcs = pEntry->sndg1Mcs; + pEntry->sndgRateIdx = pEntry->sndg1RateIdx; + /* enable BF matrix writing */ + rtmp_asic_etxbf_write_change(pAd, TRUE); + if (pEntry->sndgRateIdx == pEntry->CurrTxRateIndex) + Trigger_Sounding_Packet(pAd, SNDG_TYPE_SOUNDING, 0, pEntry->sndgMcs, pEntry); + else + Trigger_Sounding_Packet(pAd, SNDG_TYPE_NDP, 0, pEntry->sndgMcs, pEntry); + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in chooseBestMethod(): tx the SNDG of the best method, enter state WAIT_BEST_SNDG\n" )); + pEntry->bfState = WAIT_BEST_SNDG; + break; + } +} + + +/* + NOTE: currently unused. Only called when ETxBfEnCond==3 +*/ +VOID rxBestSndg( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + /*set the best mcs of this BF matrix*/ + if (pEntry->bestMethod == 2) + { + pEntry->CurrTxRate = pEntry->bf0Mcs; + pEntry->CurrTxRateIndex = pEntry->bf0RateIdx; + } + else if (pEntry->bestMethod == 3) + { + pEntry->CurrTxRate = pEntry->bf1Mcs; + pEntry->CurrTxRateIndex = pEntry->bf1RateIdx; + } + pEntry->HTPhyMode.field.eTxBF = 1; + + /*must sync the timing of using new BF matrix and its bfRateIdx!!!*/ + /*need to reset counter for rateAdapt and may have to skip one adaptation when the new BF matrix is applied!!!*/ + + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in rxBestSndg(): received the feedback of the best SNDG, and enter state READY_FOR_SNDG0\n" )); + + pEntry->bfState = READY_FOR_SNDG0; +} +#endif /* ETXBF_EN_COND3_SUPPORT */ + +VOID handleBfFb( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + pEntry = &(pAd->MacTab.Content[pRxBlk->wcid]); + + /* + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF :(%02x:%02x:%02x:%02x:%02x:%02x)\n", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2], + pEntry->Addr[3],pEntry->Addr[4], pEntry->Addr[5])); + */ + + if (pEntry->bfState == WAIT_SNDG_FB0) + { + int Nc = ((pRxBlk ->pData)[2] & 0x3) + 1; + /*record the snr comb*/ + pEntry->sndg0Snr0 = 88+(CHAR)(pRxBlk ->pData[8]); + pEntry->sndg0Snr1 = (Nc<2)? 0: 88+(CHAR)(pRxBlk ->pData[9]); + pEntry->sndg0Snr2 = (Nc<3)? 0: 88+(CHAR)(pRxBlk ->pData[10]); + pEntry->sndg0Mcs = pEntry->sndgMcs; + + DBGPRINT(RT_DEBUG_INFO,(" ETxBF: aid=%d snr %d.%02d %d.%02d %d.%02d\n", + pRxBlk->wcid, + pEntry->sndg0Snr0/4, 25*(pEntry->sndg0Snr0 & 0x3), + pEntry->sndg0Snr1/4, 25*(pEntry->sndg0Snr1 & 0x3), + pEntry->sndg0Snr2/4, 25*(pEntry->sndg0Snr2 & 0x3)) ); +#ifdef ETXBF_EN_COND3_SUPPORT + if (pEntry->eTxBfEnCond == 1 ||pEntry->eTxBfEnCond == 2) + pEntry->bfState = READY_FOR_SNDG0; + /* 2. sndg with current mcs+8 or -8, get snrComb1*/ + else if (pEntry->eTxBfEnCond == 3) + txSndgOtherGroup(pAd, pEntry); +#else + pEntry->bfState = READY_FOR_SNDG0; +#endif + } +#ifdef ETXBF_EN_COND3_SUPPORT + else if (pEntry->bfState == WAIT_SNDG_FB1) + { + /* 3. mrq with inverted TxBF status, get mfb1*/ + if (TRUE) + { + int Nc = ((pRxBlk ->pData)[2] & 0x3) + 1; + /* record the snr comb */ + pEntry->sndg1Snr0 = 88+(CHAR)(pRxBlk ->pData[8]); + pEntry->sndg1Snr1 = (Nc<2)? 0: 88+(CHAR)(pRxBlk ->pData[9]); + pEntry->sndg1Snr2 = (Nc<3)? 0: 88+(CHAR)(pRxBlk ->pData[10]); + pEntry->sndg1Mcs = pEntry->sndgMcs; + + DBGPRINT(RT_DEBUG_INFO,(" ETxBF: mcs%d, snr %d %d %d\n", pEntry->sndg1Mcs, pEntry->sndg1Snr0, pEntry->sndg1Snr1, pEntry->sndg1Snr2 )); + txMrqInvTxBF(pAd, pEntry); + } + else + chooseBestMethod(pAd, pEntry, 0); + } + else if (pEntry->bfState == WAIT_USELESS_RSP) + { + int Nc = ((pRxBlk ->pData)[2] & 0x3) + 1; + pEntry->sndg0Snr0 = 88+(CHAR)(pRxBlk ->pData[8]); + pEntry->sndg0Snr1 = (Nc<2)? 0: 88+(CHAR)(pRxBlk ->pData[9]); + pEntry->sndg0Snr2 = (Nc<3)? 0: 88+(CHAR)(pRxBlk ->pData[10]); + DBGPRINT(RT_DEBUG_INFO,(" ETxBF: mcs%d, snr %d %d %d\n", pEntry->sndg1Mcs, pEntry->sndg1Snr0, pEntry->sndg1Snr1, pEntry->sndg1Snr2 )); + txSndgSameMcs(pAd, pEntry, /*pRxBlk,*/ pEntry->lastLegalMfb); + } + else if (pEntry->bfState == WAIT_BEST_SNDG) + { + rxBestSndg(pAd, pEntry); + } +#endif /* ETXBF_EN_COND3_SUPPORT */ +} + + +VOID handleHtcField(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ +#ifdef MFB_SUPPORT + UCHAR mfb = ((PHT_CONTROL)(pRxBlk->pData))-> MFBorASC; + UCHAR mfsi = ((PHT_CONTROL)(pRxBlk->pData))-> MFSI; + UCHAR legalMfb = 0, legalMfbIdx=0, smoothMfb = 0; + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR i, j; + UCHAR *pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx; + UCHAR snr[] = {pRxWI->SNR0, pRxWI->SNR1, pRxWI->SNR2}; + UCHAR snrTemp1[3]; + UCHAR snrTemp; + UCHAR streams; + UINT tpTemp, bestTp = 0, snrSum; + SHORT thrdTemp; + SHORT group, idx; + UCHAR mcs; + RTMP_RA_GRP_TB *pLegalMfbRS3S = NULL; + RTMP_RA_LEGACY_TB *pLegalMfbRS = NULL; + + if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + pEntry = &(pAd->MacTab.Content[pRxBlk->wcid]); + + /* if MFB is received, have to rule out the case when mai==14 */ + if (!(((PHT_CONTROL)(pRxBlk->pData))->MRQ == 0 && ((PHT_CONTROL)(pRxBlk->pData))->MSI == 7) + && mfb != 127) + {/* need a timer in case there is no mfb with this mfsi */ + DBGPRINT(RT_DEBUG_INFO, (" MFB in handleHtcField(): MFB %d is received\n", mfb)); + /* check if the mfb is valid. if not, convert to a valid mcs */ + if (mfb > 76) + DBGPRINT(RT_DEBUG_TRACE, ("Error in handleHtcField: received MFB > 76\n")); + + if (pEntry->HTCapability.MCSSet[0] == 0xff && pEntry->HTCapability.MCSSet[1] == 0xff + && pEntry->HTCapability.MCSSet[2] == 0xff && pAd->CommonCfg.TxStream == 3) + legalMfb = mcsToLowerMcs[4*mfb + 3]; + else if (pEntry->HTCapability.MCSSet[0] == 0xff && pEntry->HTCapability.MCSSet[1] == 0xff && pAd->CommonCfg.TxStream > 1 + && (pAd->CommonCfg.TxStream == 2 || pEntry->HTCapability.MCSSet[2] == 0x0)) + legalMfb = mcsToLowerMcs[4*mfb + 2]; + else if (pEntry->HTCapability.MCSSet[0] == 0xff &&( pAd->CommonCfg.TxStream == 1 ||pEntry->HTCapability.MCSSet[1] == 0x0)) + legalMfb = mcsToLowerMcs[4*mfb + 1]; + else + DBGPRINT(RT_DEBUG_TRACE, ("no available MFB mapping for the received MFB\n")); + /* + have to rule out the mfb that the Rx shouldn't be able to suggest??? + for example, mrq was sent with 2 streams but the Rx suggests MCS + with 3 streams + */ + +#ifdef ETXBF_EN_COND3_SUPPORT + if (mfsi == MSI_TOGGLE_BF) + { + if (pEntry->bfState == WAIT_MFB) + chooseBestMethod(pAd, pEntry, legalMfb); + else if (pEntry->bfState == WAIT_USELESS_RSP) + txSndgSameMcs(pAd, pEntry,/* pRxBlk,*/ legalMfb); + } +#endif + } + + if (!(((PHT_CONTROL)(pRxBlk->pData))->MRQ == 0 && ((PHT_CONTROL)(pRxBlk->pData))->MSI == 7 && mfsi != MSI_TOGGLE_BF) + && mfb != 127) + { + /* the main body of algorithm */ + /* legalMfb smoothing */ + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + { + for (i=1; i<=RATE_TABLE_SIZE(pTable); i++) + { + if (legalMfb == pTable[i*10+2]) + { + legalMfbIdx = pTable[i*10]; + pLegalMfbRS3S = (RTMP_RA_GRP_TB *) &pTable[i*10]; + pLegalMfbRS = (RTMP_RA_LEGACY_TB *) &pTable[i*10]; + break; + } + } + /* pLegalMfbRS3S may be null if pLegalMfbRS3S is not found!!! */ + if (pEntry->lastLegalMfb == pTable[(pLegalMfbRS3S->downMcs+1)*10+2] ||pEntry->lastLegalMfb == pTable[(pLegalMfbRS3S->upMcs1+1)*10+2] + ||pEntry->lastLegalMfb == pTable[(pLegalMfbRS3S->upMcs2+1)*10+2] ||pEntry->lastLegalMfb == pTable[(pLegalMfbRS3S->upMcs3+1)*10+2]) + smoothMfb = pEntry->lastLegalMfb; + else + smoothMfb = legalMfb; + } + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + { + for (i=1; i<=RATE_TABLE_SIZE(pTable); i++) + { + if (legalMfb == pTable[i*5+2]) + { + legalMfbIdx = pTable[i*5]; + pLegalMfbRS = (RTMP_RA_LEGACY_TB *) &pTable[i*5]; + break; + } + } + if ((pEntry->lastLegalMfb <= legalMfb+1 || pEntry->lastLegalMfb+1 >= legalMfb) && ((legalMfb>>3) == (pEntry->lastLegalMfb >>3))) + smoothMfb = pEntry->lastLegalMfb; + else + smoothMfb = legalMfb; + } + + + if (smoothMfb != pEntry->lastLegalMfb && smoothMfb != pTable[(pEntry->CurrTxRateIndex+1)*10+2]) + {/* if mfb changes and mfb is different from current mcs: means channel change */ +#ifdef NEW_RATE_ADAPT_SUPPORT + if ((ADAPT_RATE_TABLE(pTable))) + MlmeSetMcsGroup(pAd, pEntry); +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pEntry->CurrTxRateIndex = legalMfbIdx; + MlmeClearTxQuality(pEntry);/* clear all history, same as train up, purpose??? */ + NdisAcquireSpinLock(&pEntry->fLastChangeAccordingMfbLock); + NdisMoveMemory(pEntry->LegalMfbRS, pLegalMfbRS, sizeof(RTMP_RA_LEGACY_TB)); + pEntry->fLastChangeAccordingMfb = TRUE; + /* reset all OneSecTx counters */ + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + NdisReleaseSpinLock(&pEntry->fLastChangeAccordingMfbLock); + DBGPRINT(RT_DEBUG_INFO,(" MFB in handleHtcField(): MFB changes and use the new mfb=%d, mfbIdx=%d\n", legalMfb, legalMfbIdx)); + /* pEntry->isMfbChanged = TRUE; */ + + if ((pEntry->HTCapability.TxBFCap.ExpNoComBF && pAd->CommonCfg.HtCapability.TxBFCap.TxSoundCapable + && pAd->CommonCfg.HtCapability.TxBFCap.ExpNoComSteerCapable)) + {/* support ETxBF. what's the correct criterion???? */ + /* the process is triggered by channel change here. have to add the mechanism where the process is triggered by timer expiration!!! */ +#ifdef ETXBF_EN_COND3_SUPPORT + if (pEntry->eTxBfEnCond == 3) + { + if (pEntry->bfState == READY_FOR_SNDG0) + { + DBGPRINT(RT_DEBUG_OFF,("ETxBF in handleHtcField(): detect MFB change, set pEntry->mfb0=%d\n", pEntry->mfb0 )); + txSndgSameMcs(pAd, pEntry, /*pRxBlk,*/ legalMfb); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("ETxBF in handleHtcField(): detect channel change before enter the ETxBF probe process is complete, enter state WAIT_USELESS_RSP\n" )); + pEntry->bfState = WAIT_USELESS_RSP; + } + } +#endif + /* write down the current MFB and ixTxBF. currentMFB is recorded in lastLegalMfb */ + /* send one packet with reverse TxBF, 2 stream sounding */ + } + } + + /* post-prossessing */ + if (pEntry->fLastChangeAccordingMfb) + pEntry->lastLegalMfb = legalMfb; + } + + + /*if mrq is received*/ + if (((PHT_CONTROL)(pRxBlk->pData))->MRQ == 1) + { + DBGPRINT(RT_DEBUG_INFO, (" MFB in handleHtcField(): MRQ is received\n")); + /* + Assumption: + snr are not sorted, wait for John or Julian's answer as to + the SNR values of unused streams + */ + if ((pEntry->HTCapability.MCSSet[2] == 0xff && pAd->CommonCfg.TxStream == 3)) + { + streams = 3; + } + else if (pEntry->HTCapability.MCSSet[0] == 0xff && pEntry->HTCapability.MCSSet[1] == 0xff && pAd->CommonCfg.TxStream > 1 + && (pAd->CommonCfg.TxStream == 2 || pEntry->HTCapability.MCSSet[2] == 0x0)) + { + streams = 2; + } + else + { + streams = 1; + } + /*sort such that snr[0]>=snr[1]>=snr[2]. sorting is required for group 2 so that the best 2 streams are used.*/ + for (i=0; i=0; group--) + { + snrTemp1[0] = snr[0]; + snrTemp1[1] = snr[1]; + snrTemp1[2] = snr[2]; + /*SNR processing for each group according to the baseband implementation, for example MRC*/ + switch (group) + { + case 0: + snrTemp1[1] = 0; + snrTemp1[2] = 0; + break; + case 1: + snrTemp1[2] = 0; + break; + case 2: + break; + default: + break; + } + snrSum = snr[0] + snr[1] + snr[2]; + for (idx=8; idx>=1; idx--){ + mcs = group*8+idx-1; + thrdTemp = groupThrd[mcs]; + tpTemp = 0; + if (groupMethod[mcs] == 0) + { + if (snrSum > thrdTemp) + tpTemp = ((snrSum - thrdTemp) * dataRate[mcs])>>groupShift[group]; + } + else + { + if (group == 1) + snrTemp1[2] = thrdTemp + 1; + if (snrTemp1[0] > thrdTemp && snrTemp1[1] > thrdTemp && snrTemp1[2] > thrdTemp) + tpTemp = ((snrTemp1[0] - thrdTemp)*(snrTemp1[1] - thrdTemp)*(snrTemp1[2] - thrdTemp) * dataRate[mcs])>>groupShift[group];/* have to be revised!!! */ + } + if (tpTemp > dataRate[mcs]) + tpTemp = dataRate[mcs]; + if (tpTemp > bestTp) + { + bestTp = tpTemp; + pEntry->mfbToTx = mcs; + } + + } + } + pEntry->toTxMfb = 1;/*should be reset to 0 when mfb is actually sent out!!!*/ + DBGPRINT(RT_DEBUG_INFO,(" MFB in handleHtcField(): MFB %d is going to be sent\n", pEntry->mfbToTx)); + } +#endif /* MFB_SUPPORT */ +} + + +void eTxBfProbeTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (PMAC_TABLE_ENTRY) FunctionContext; +#ifdef ETXBF_EN_COND3_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; +#endif + + if (pEntry->bfState == WAIT_SNDG_FB0) + { + /*record the snr comb*/ + pEntry->sndg0Snr0 = -128; + pEntry->sndg0Snr1 = -128; + pEntry->sndg0Snr2 = -128; + pEntry->sndg0Mcs = pEntry->sndgMcs; + //DBGPRINT(RT_DEBUG_TRACE,(" ETxBF: timer of WAIT_SNDG_FB0 expires\n" )); +#ifdef ETXBF_EN_COND3_SUPPORT + if (pEntry->eTxBfEnCond == 1 || pEntry->eTxBfEnCond == 2) + pEntry->bfState =READY_FOR_SNDG0; + else if (pEntry->eTxBfEnCond == 3) + txSndgOtherGroup(pAd, pEntry); +#else + pEntry->bfState =READY_FOR_SNDG0; +#endif + } +#ifdef ETXBF_EN_COND3_SUPPORT + else if (pEntry->bfState == WAIT_SNDG_FB1) + { + /*record the snr comb*/ + pEntry->sndg1Snr0 = -128; + pEntry->sndg1Snr1 = -128; + pEntry->sndg1Snr2 = -128; + pEntry->sndg1Mcs = pEntry->sndgMcs; + //DBGPRINT(RT_DEBUG_TRACE,(" ETxBF: timer of WAIT_SNDG_FB1 expires, run txMrqInvTxBF()\n" )); + txMrqInvTxBF(pAd, pEntry); + } + else if (pEntry->bfState == WAIT_MFB) + { + DBGPRINT(RT_DEBUG_TRACE,(" ETxBF: timer of WAIT_MFB expires, run chooseBestMethod()\n" )); + chooseBestMethod(pAd, pEntry, 0); + } + else if (pEntry->bfState == WAIT_BEST_SNDG) + { + DBGPRINT(RT_DEBUG_TRACE,(" ETxBF: timer of WAIT_BEST_SNDG expires, run rxBestSndg()\n" )); + rxBestSndg(pAd, pEntry); + } +#endif /* ETXBF_EN_COND3_SUPPORT */ +} + + +#ifdef MFB_SUPPORT +VOID MFB_PerPareMRQ( + IN PRTMP_ADAPTER pAd, + OUT VOID* pBuf, + IN PMAC_TABLE_ENTRY pEntry) +{ + PHT_CONTROL pHT_Control; + +/* DBGPRINT(RT_DEBUG_TRACE, ("-----> MFB_PerPareMRQ\n"));*/ + if (pEntry->HTCapability.ExtHtCapInfo.MCSFeedback >= MCSFBK_MRQ) + { + pHT_Control = (HT_CONTROL *)pBuf; + + pHT_Control->MRQ = 1; + + if (pEntry->msiToTx == MSI_TOGGLE_BF) { + if (pEntry->mrqCnt == 0) + pEntry->mrqCnt = TOGGLE_BF_PKTS; + else + { + (pEntry->mrqCnt)--; + if (pEntry->mrqCnt == 0) + pEntry->msiToTx = 0; + } + } + pHT_Control->MSI = pEntry->msiToTx; + + /*update region*/ + if (pEntry->msiToTx == MSI_TOGGLE_BF-1)/*MSI_TOGGLE_BF==6 is used to indicate the TxBF status is inverted for this packet*/ + pEntry->msiToTx = 0; + else if (pEntry->msiToTx != MSI_TOGGLE_BF) + pEntry->msiToTx++; + + } + +/* DBGPRINT(RT_DEBUG_TRACE, ("<----- MFB_PerPareMRQ\n"));*/ +} + + +/* + Need to be completed!!!!!!!!!!!!!!!!! +*/ +VOID MFB_PerPareMFB( + IN PRTMP_ADAPTER pAd, + OUT VOID* pBuf, + IN PMAC_TABLE_ENTRY pEntry) +{ +/* DBGPRINT(RT_DEBUG_TRACE, ("-----> MFB_PerPareMRQ\n")); */ +/* DBGPRINT(RT_DEBUG_TRACE, ("<----- MFB_PerPareMRQ\n"));*/ +} +#endif /* MFB_SUPPORT */ + + +/* MlmeTxBfAllowed - returns true if ETxBF or ITxBF is supported and pTxRate is a valid BF mode */ +BOOLEAN MlmeTxBfAllowed( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_LEGACY_TB *pTxRate) +{ + /* ETxBF */ + if ((pEntry->eTxBfEnCond > 0) && + (pTxRate->Mode == MODE_HTMIX || pTxRate->Mode == MODE_HTGREENFIELD) +#ifdef DBG_CTRL_SUPPORT + && (!((pAd->CommonCfg.DebugFlags & DBF_NO_TXBF_3SS) && pTxRate->CurrMCS>20)) +#endif /* DBG_CTRL_SUPPORT */ + ) + return TRUE; + + /* ITxBF */ + if (pEntry->iTxBfEn && pTxRate->CurrMCS<16 && pTxRate->Mode!=MODE_CCK) + return TRUE; + + return FALSE; +} +#endif /* TXBF_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_txbf_cal.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_txbf_cal.c new file mode 100644 index 000000000..d40d90e92 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_txbf_cal.c @@ -0,0 +1,3819 @@ +/* + *************************************************************************** + * 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: + cmm_txbf_cal.c + + Abstract: + Tx Beamforming calibration and profile related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Shiang 2010/07/12 +*/ + +#include "rt_config.h" + + +/* + iAtan2 - fixed point atan2. Returns +/-pi. Scaled so pi=0x1000 + Code was taken from MyCordic: + int MyCordic(int y, int x, int shift, int iter, int *alpha) + Parameters are hard coded so it's equivalent to MyCordic(y, x, 0, 11, alpha10); +*/ +static int iAtan2(int y, int x) +{ + int z = 0, xtemp, i; + int onepi, halfpi; + int shift=0; + int iter=11; + static int alpha[11] = {0x400, 0x25c, 0x13f, 0x0a2, + 0x051, 0x028, 0x014, 0x00a, + 0x005, 0x002, 0x001}; + + onepi = (alpha[0]<<2), + halfpi = (alpha[0]<<1); + + if (x == 0) { + if (y == 0) + z = 0; + else if (y > 0) + z = halfpi; + else + z = -halfpi; + } + else if ((x < 0) && (y == 0)){ + z = -onepi; + } + else if ((x > 0) && (y == 0)){ + z = 0; + } + else{ + x <<= shift; + y <<= shift; + xtemp = x; + if ((x < 0) && (y > 0)){ + x = y; + y = -xtemp; + z = halfpi; + } + else if ((x < 0) && (y < 0)){ + x = -y; + y = xtemp; + z = -halfpi; + } + for (i = 0; i < iter; i++){ + /* printf("%d %d %x\n", x, y, z); */ + if (y == 0) + break; + if (y < 0) { + z -= alpha[i]; + xtemp = x - (y>>i); + y = y + (x>>i); + x = xtemp; + } + else { + z += alpha[i]; + xtemp = x + (y>>i); + y = y - (x>>i); + x = xtemp; + } + } + } + + if (z == alpha[0]*4) + z = -(alpha[0]*4); + + return z; +} + + +/* + isqrt - fixed point sqrt + x - unsigned value +*/ +static UINT32 isqrt (UINT32 x) +{ + UINT32 base, y; + + if (x & 0xF0000000) + base = 1<<15; + else if (x & 0x0F000000) + base = 1<<13; + else if (x & 0x00F00000) + base = 1<<11; + else if (x & 0x000F0000) + base = 1<<9; + else + base = 1<<7; + + y = 0; + while (base) { + y += base; + if ((y * y) > x) + y -= base; + base >>= 1; + } + return y; +} + + +/* + icexp - fixed point complex exponential + phase - 0 to 255 representing 0 to 2pi + return cos and sin in 1p10 format +*/ +static void icexp(short c[2], int phase) +{ + /* cosine table generated with Matlab: round(1024*cos(2*pi*[0:255]/256) */ + static short cosTable[256] = { + 1024, 1024, 1023, 1021, 1019, 1016, 1013, 1009, + 1004, 999, 993, 987, 980, 972, 964, 955, + 946, 936, 926, 915, 903, 891, 878, 865, + 851, 837, 822, 807, 792, 775, 759, 742, + 724, 706, 688, 669, 650, 630, 610, 590, + 569, 548, 526, 505, 483, 460, 438, 415, + 392, 369, 345, 321, 297, 273, 249, 224, + 200, 175, 150, 125, 100, 75, 50, 25, + 0, -25, -50, -75, -100, -125, -150, -175, + -200, -224, -249, -273, -297, -321, -345, -369, + -392, -415, -438, -460, -483, -505, -526, -548, + -569, -590, -610, -630, -650, -669, -688, -706, + -724, -742, -759, -775, -792, -807, -822, -837, + -851, -865, -878, -891, -903, -915, -926, -936, + -946, -955, -964, -972, -980, -987, -993, -999, + -1004, -1009, -1013, -1016, -1019, -1021, -1023, -1024, + -1024, -1024, -1023, -1021, -1019, -1016, -1013, -1009, + -1004, -999, -993, -987, -980, -972, -964, -955, + -946, -936, -926, -915, -903, -891, -878, -865, + -851, -837, -822, -807, -792, -775, -759, -742, + -724, -706, -688, -669, -650, -630, -610, -590, + -569, -548, -526, -505, -483, -460, -438, -415, + -392, -369, -345, -321, -297, -273, -249, -224, + -200, -175, -150, -125, -100, -75, -50, -25, + 0, 25, 50, 75, 100, 125, 150, 175, + 200, 224, 249, 273, 297, 321, 345, 369, + 392, 415, 438, 460, 483, 505, 526, 548, + 569, 590, 610, 630, 650, 669, 688, 706, + 724, 742, 759, 775, 792, 807, 822, 837, + 851, 865, 878, 891, 903, 915, 926, 936, + 946, 955, 964, 972, 980, 987, 993, 999, + 1004, 1009, 1013, 1016, 1019, 1021, 1023, 1024}; + c[0] = cosTable[phase & 0xFF]; + c[1] = cosTable[(phase-64) & 0xFF]; +} + + +/* + icMult - fixed point complex multiply + r = a*b +*/ +static void icMult(INT32 r[2], INT32 a[2], INT32 b0, INT32 b1) +{ + INT32 t; + t = a[0]*b0 - a[1]*b1; + r[1] = a[0]*b1 + a[1]*b0; + r[0] = t; +} + + +/* + ------------ DIVIDER AND LNA CALIBRATION -------- +*/ +typedef struct { + LONG i:8; + LONG q:8; +} COMPLEX_VALUE; /* Signed 8-bit complex values */ + +#define CALC_LENGTH 1024 /* Number of samples used to perform phase calculation for LNA or Divider Calibration */ +#define CALC_LENGTH_DC (CALC_LENGTH+512) /* Number of samples used for DC removal */ +#define MAX_CAPTURE_LENGTH 4096 /* Maximum number of samples to capture */ +#define DIVCAL_CAPTURE_LENGTH (CALC_LENGTH+1024) /* Length of capture for Divider or LNA Calibration */ + +#define FIXED_M_PI 0x1000 /* Scaling for fixed point PI */ +#define DEG(rad) (radToDeg180(rad-FIXED_M_PI)+180) /* Convert fixed radians (0x1000=pi) to degrees range [0 360) */ +#define DEG180(rad) radToDeg180(rad) /* Convert fixed radians (0x1000=pi) to degrees range [-180 180) */ + +#define BYTE_PHASE_SHIFT 5 /* Shift to convert from byte phase (0x80=pi) to normal phase (0x1000=pi) */ +#define CONVERT_TO_BYTE_PHASE(p) (int)(((p)+(1<<(BYTE_PHASE_SHIFT-1)))>>BYTE_PHASE_SHIFT) /* Convert from normal phase to byte phase */ + +#define R65_LNA_LOW 0x4 +#define R65_LNA_MID 0x8 +#define R65_LNA_HIGH 0xC + + +/* + radMod2pi - converts angle in radians to the range [-pi pi) +*/ +static LONG radMod2pi(LONG a) +{ + while (a < -FIXED_M_PI) + a += 2*FIXED_M_PI; + while (a >= FIXED_M_PI) + a -= 2*FIXED_M_PI; + + return a; +} + + +/* + radToDeg180 - converts angle in radians to the deg range [-180 180) +*/ +static int radToDeg180(LONG rad) +{ + return (int)(radMod2pi(rad)*180/FIXED_M_PI); +} + + +/* + avgPhase - computes the average phase. + Phase is adjusted so all values are within the range mPhase[0] +/-pi + mPhase - values to average (radians) + pLength - number of values to average + return average +*/ +static LONG avgPhase(LONG mPhase[], int pLength) +{ + int i; + short cval[2]; + LONG sumCos = 0, sumSin=0; + for (i=0; i 127) + sati = 127; + else if (sati < -128) + sati = -128; + iqData[i][j].i = sati; + + if (satq > 127) + satq = 127; + else if (satq < -128) + satq = -128; + iqData[i][j].q = satq; + + /* Record peak */ + if (peak[j] < iqData[i][j].i) + peak[j] = iqData[i][j].i; + if (peak[j] < iqData[i][j].q) + peak[j] = iqData[i][j].q; + } + } +} + + +/* + CalcRFCalPhase - process RF calibration to calculate phase of the three channels + Parameters: + phase - returns the phase of each channel. Fixed point value scaled so 0x1000 = PI + avgI, avgQ - returns the avg I/Q of each channel. Implied scale factor of 256 + peak - returns the peak value of each channel after DC removal + iqData - the input I/Q data for three channels. DC is removed. + relPhase - If true it returns phase relative to Ant1. Otherwise it returns the + phase relative to the reference signal. + actTx - index of an active TX chain, used to detect start of signal +*/ +static void CalcRFCalPhase( + OUT LONG phase[3], + OUT int avgI[3], + OUT int avgQ[3], + OUT int peak[3], + IN COMPLEX_VALUE (*iqData)[3], + IN BOOLEAN relPhase, + IN int actTx) +{ + int i, j; + LONG sumI[3], sumQ[3]; + static CHAR refSignal[64] = { /* round(sin(-[0:63]*6*pi/64)*127) - three cycles per 64 samples */ + 0, -37, -71, -98, -117, -126, -125, -112, + -90, -60, -25, 12, 49, 81, 106, 122, + 127, 122, 106, 81, 49, 12, -25, -60, + -90, -112, -125, -126, -117, -98, -71, -37, + 0, 37, 71, 98, 117, 126, 125, 112, + 90, 60, 25, -12, -49, -81, -106, -122, + -127, -122, -106, -81, -49, -12, 25, 60, + 90, 112, 125, 126, 117, 98, 71, 37}; + + + /* Skip the first 200 samples to avoid the transient at the beginning */ + iqData += 200; + + /* Remove DC offset to help with low signal levels */ + RemoveDC(peak, iqData, CALC_LENGTH_DC); + + /* Search active channel to find sample with abs>12 */ + for (i=0; i<(CALC_LENGTH_DC-CALC_LENGTH); i++, iqData++) { + if ((iqData[0][actTx].i*iqData[0][actTx].i + iqData[0][actTx].q*iqData[0][actTx].q) >= 144) + break; + } + + /* Move in 16 samples */ + iqData += 16; + + /* Sum the I and Q then calculate the angle of the sum */ + sumI[0] = sumI[1] = sumI[2] = 0; + sumQ[0] = sumQ[1] = sumQ[2] = 0; + + for (i=0; i>6, sumI[i]>>6); + /* Multiplication by refSignal added a scale factor of 128. Shift left by 1 for 256 scale factor */ + avgI[i] = (sumI[i]<<1)/CALC_LENGTH; + avgQ[i] = (sumQ[i]<<1)/CALC_LENGTH; + } + } +} + + +#ifdef MT76x2 +static VOID CalcDividerPhase( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN agcEnable, + IN UCHAR *preVGAGainIdx, + OUT UCHAR *mPhase0 + ) +{ + UCHAR channel = pAd->CommonCfg.Channel; + UINT32 phaseCaliStatus, phaseCaliResult, value32; + UCHAR divPhCalPath[2]={RX0TX0, RX1TX1}; + UCHAR timeOutCount, AGCtimeOutCount; + LONG mCalPhase0[2]; + LONG avgIData, avgQData; + UCHAR peakI[2]; + UCHAR VGAGainIdx[2]; + BOOLEAN gBandFlg = FALSE; + UINT32 agcLoopCnt = 20; + INT i, RF_Path_n = 0; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + // band check + if (channel <= 14) gBandFlg = TRUE; + + /* DPD and TSSI HW off */ + RTMP_IO_READ32(pAd,TXBE_R8, &value32); + value32 &= ~0x08000; + RTMP_IO_WRITE32(pAd,TXBE_R8, value32); // DPD off + + RTMP_IO_READ32(pAd,CORE_R34, &value32); + value32 &= ~0x60; + value32 |= 0x40; + RTMP_IO_WRITE32(pAd,CORE_R34, value32); // TSSI off + + /* Do Calibration */ + /* Divider closeloop settng */ + // RXA IQ CalSetting + if (gBandFlg) + { + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX17, 0x00010170); // set txg gain table = to manual mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX17, 0x00010170); // set txg gain table = to manual mode + mt_rf_write(pAd, RF_Path0, RG_WF0_RXG_TOP, 0x00492016); // TRSWITCH + mt_rf_write(pAd, RF_Path1, RG_WF0_RXG_TOP, 0x00492016); // TRSWITCH + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP1, 0x0004012C); // tx block mode. 0x0 should behind 0x10 + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP1, 0x0004012C); // tx block mode. 0x0 should behind 0x10 + VGAGainIdx[0] = 2; + VGAGainIdx[1] = 2; + } + else + { + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX17, 0x000101D0); // set txg gain table = to manual mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX17, 0x000101D0); // set txg gain table = to manual mode + VGAGainIdx[0] = 4; + VGAGainIdx[1] = 4; + } + + // DCOC for RXA IQ Cal + RTMP_IO_WRITE32(pAd,CORE_R1, 0x00000000); // BW=20MHz ADC=40MHz + RTMP_IO_WRITE32(pAd,CORE_R33, 0x00021E00); // RF/BBP DAC clock control + + // Send single tone + RTMP_IO_WRITE32(pAd,DACCLK_EN_DLY_CFG, 0x80008000); // DAC Clock on + RTMP_IO_WRITE32(pAd,TXBE_R6, 0x00000000); // Test format contol : Tx single tone setting + + /* Divider phase calibration process */ + for (i = 0; i < 2; i++) // ANT0, ANT1 + { + //AGCtimeOutCount = (SwAgc1stflg == TRUE) ? 0 : 19; + AGCtimeOutCount = 0; + while (AGCtimeOutCount < agcLoopCnt) // SW AGC update to make sure I peak value can prevent peak value from satuation or too low + { + RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000001); //core soft reset enable + RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000000); //core soft reset disable + RTMP_IO_WRITE32(pAd,TXBE_R1, 0x00001010); //no attenuation, full DAC swing + + RF_Path_n = i; + + // Set LNA to M + if (agcEnable == 1) + { + mt_rf_write(pAd, RF_Path_n, RFDIGI_TRX4, ((1<<19)|(2<<16)|(1<<15)|((0 + VGAGainIdx[i])<<8)|(1<<7)|(0 + VGAGainIdx[i]))); + DBGPRINT(RT_DEBUG_WARN,("VGAGainIdx[i] = %d\n", VGAGainIdx[i])); + } + else + { + mt_rf_write(pAd, RF_Path_n, RFDIGI_TRX4, ((1<<19)|(2<<16)|(1<<15)|((0 + preVGAGainIdx[i])<<8)|(1<<7)|(0 + preVGAGainIdx[i]))); + DBGPRINT(RT_DEBUG_WARN,("preVGAGainIdx[i] = %d\n", preVGAGainIdx[i])); + } + + // Internal loopback + RTMP_IO_WRITE32(pAd, TXBE_R4, 0x00000008); // a default setting, 2T + mt_rf_write(pAd, RF_Path_n, RFDIGI_TOP4, 0x304F1047); // tx block mode + + if (gBandFlg) + { + mt_rf_write(pAd, RF_Path_n, RFDIGI_TOP0, 0x80056F53); // manul mode for external loopback(chip mode=5) + } + else + { + mt_rf_write(pAd, RF_Path_n, RFDIGI_TOP0, 0x80056F57); // manul mode for external loopback(chip mode=5) + } + + mt_rf_write(pAd, RF_Path_n, RFDIGI_ABB_TO_AFE5,0x00C211F1); // set ABB config switch + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, 0x00000008); // Adjust SPI clock + mt_rf_write(pAd, RF_Path_n, RFDIGI_TRX0, 0x0500010F); // start rxiq dcoc + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, 0x00000002); // Adjust SPI clock + + DBGPRINT(RT_DEBUG_WARN,("Loop%d\n",i)); + + // Set Tx/Rx index + RTMP_IO_WRITE32(pAd,CAL_R2, divPhCalPath[i]); // Tx0 + RTMP_IO_WRITE32(pAd,TXBE_R6, 0xC0002101); //Test format contol : Tx single tone setting + RTMP_IO_WRITE32(pAd,CAL_R5, 0x0000140F); //set accumulation length + //RTMP_IO_WRITE32(pAd,CAL_R5, 0x000040C); + + //RtmpOsMsDelay(1); // waiting 1ms + + // Enable Divider phase calibration + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000086); + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + timeOutCount = 0; + while (phaseCaliStatus & 0x80) + { + if (timeOutCount == 10) + { + DBGPRINT(RT_DEBUG_WARN,("phaseCaliStatus = %x\n", phaseCaliStatus)); + DBGPRINT(RT_DEBUG_WARN,("LNA HW calibration can't finish process\n")); + break; + } + + timeOutCount++; + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + } + + // 0x2C2C + // Bit 23:16 Correlator Phase + // Bit 15:8 Correlator Q value + // Bit 7:0 Correlator I value + RTMP_IO_READ32(pAd,CAL_R11, &phaseCaliResult); + mPhase0[i] = (INT)((INT)((phaseCaliResult << 8) & 0xFF000000) >> 24); + avgQData = (INT)((INT)((phaseCaliResult << 16) & 0xFF000000) >> 24); + avgIData = (INT)((INT)((phaseCaliResult << 24) & 0xFF000000) >> 24); + mCalPhase0[i] = iAtan2(avgQData, avgIData); + + peakI[i] = (UCHAR)(phaseCaliResult >> 24); + + DBGPRINT(RT_DEBUG_WARN,( + "Divider phase cal : CAL_R11=0x%x\n" + "Peak I value=0x%x\n" + "I value=0x%lx, Q value=0x%lx\n", + phaseCaliResult, + peakI[i], + avgIData, avgQData)); + + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000006); // Disable Calibration + + if (agcEnable == 1) + { + // SW AGC calculation + //if (SwAgc1stflg == TRUE && VGAGainIdx[i] < 128) + if ((VGAGainIdx[i] < 128) && (AGCtimeOutCount < (agcLoopCnt -1))) + { + // Calculate AGC ad check if AGC update is enough or not + if (peakI[i] >= 0x20 && VGAGainIdx[i] > 0) + VGAGainIdx[i]--; + else if (peakI[i] >= 0x10) + { + AGCtimeOutCount = 20; + //SwAgc1stflg = FALSE; + break; + } + //else if (peakI[i] <= 16) + // VGAGainIdx[i] += 5; + //else if (peakI[i] <= 20) + // VGAGainIdx[i] += 4; + //else if (peakI[i] <= 25) + // VGAGainIdx[i] += 3; + //else if (peakI[i] <= 28) + // VGAGainIdx[i] += 2; + else + VGAGainIdx[i]++; + } + + DBGPRINT(RT_DEBUG_WARN,("SW AGC = %d,AGCtimeOutCount = %d\n" + "===================================\n", VGAGainIdx[i], AGCtimeOutCount)); + AGCtimeOutCount++; + } + else + { + AGCtimeOutCount = 20; + //SwAgc1stflg = FALSE; + break; + } + } + + // Backup AGC gain + if (agcEnable == 1) + { + preVGAGainIdx[i] = VGAGainIdx[i]; + DBGPRINT(RT_DEBUG_WARN,("Backup SWAGC = %d\n", preVGAGainIdx[i])); + } + + if (gBandFlg) + { + // RF0 Chip mode release + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056F53); // Turn off the RFDIGI logic clock + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056F50); // Release manual control of top control + RtmpOsMsDelay(1); // waiting 1ms + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x80056F50); // Enable RFDIGI logic clock + //mt_rf_write(pAd, RF_Path0, RFDIGI_TOP4, 0x00001047); // tx block mode, should 0x0 should behind 0x10 + + // RF1 Chip mode release + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F53); // Turn off the RFDIGI logic clock + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F50); // Release manual control of top control + RtmpOsMsDelay(1); // waiting 1ms + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x80056F50); // Release manual control of top control + //mt_rf_write(pAd, RF_Path1, RFDIGI_TOP4, 0x00001047); // tx block mode, should 0x0 should behind 0x10 + } + else + { + // RF0 Chip mode release + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056F57); // Turn off the RFDIGI logic clock + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056F54); // Release manual control of top control + RtmpOsMsDelay(1); // waiting 1ms + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x80056F54); // Enable RFDIGI logic clock + //mt_rf_write(pAd, RF_Path0, RFDIGI_TOP4, 0x00001047); // tx block mode, should 0x0 should behind 0x10 + + // RF1 Chip mode release + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F57); // Turn off the RFDIGI logic clock + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F54); // Release manual control of top control + RtmpOsMsDelay(1); // waiting 1ms + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x80056F54); // Release manual control of top control + //mt_rf_write(pAd, RF_Path1, RFDIGI_TOP4, 0x00001047); // tx block mode, should 0x0 should behind 0x10 + } + } + + DBGPRINT(RT_DEBUG_WARN, ( + "HW Phase vs Driver Phase (deg)\n" + "Peak I:0x%x ANT0/0 :%d %d\n" + "Peak I:0x%x ANT1/1 :%d %d\n" + "divPhase[0] : %d\n", + peakI[0], (360*mPhase0[0])>> 8, DEG180(mCalPhase0[0]), + peakI[1], (360*mPhase0[1])>> 8, DEG180(mCalPhase0[1]), + (360*(mPhase0[0]-mPhase0[1]))>> 8)); + +} +#endif // MT76x2 + + +#ifdef DBG +#ifdef LINUX +/* #define TIMESTAMP_CAL_CAPTURE0 */ +/* #define TIMESTAMP_CAL_CAPTURE1 */ +#endif /* LINUX */ +#endif /* DBG */ + + + +/* + ITxBFSaveData - save MAC data + Returns pointer to allocated buffer containing saved data +*/ +static UINT32 *ITxBFSaveData(PRTMP_ADAPTER pAd) +{ + UINT32 *saveData, *sdPtr, macAddr, maxAddr; + + /* Save 48KB MAC data. */ + if (os_alloc_mem(pAd, (UCHAR **)&saveData, 0xC000)!= NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return NULL; + } + + maxAddr = 0x10000; + + for (sdPtr=saveData, macAddr=0x4000; macAddr= 128) + yDelta -= 256; + else if (yDelta <= -128) + yDelta += 256; + + output = yBeg + yDelta*(x-xBeg)/(xEnd-xBeg); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s : \n" + "x = mapChannelKHz(%d) = %ld\n" + "xBeg = mapChannelKHz(%d) = %ld\n" + "xEnd = mapChannelKHz(%d) = %ld\n" + "yDelta = %ld\n" + "output = %d\n", + __FUNCTION__, + ch, x, + chBeg, xBeg, + chEnd, xEnd, + yDelta, + output)); + + return output; +} +#endif + + +/* + InterpParam - Interpolate calibration parameters + ch - channel to interpolate for + chBeg, chEnd - begining and ending channel + yBeg, yEnd - the hex phase values corresponding to chBeg and chEnd +*/ +static UCHAR InterpParam(int ch, int chBeg, int chEnd, UCHAR yBeg, UCHAR yEnd) +{ + long x, xBeg, xEnd, yDelta; + + x = mapChannelKHz(ch); + xBeg = mapChannelKHz(chBeg); + xEnd = mapChannelKHz(chEnd); + yDelta = yEnd - yBeg; + + /* + Handle the phase wraparound. We always assume the delta phase is in + the range [-180, 180] degrees = [0x80, 0x7f] in hex + */ + if (yDelta >= 128) + yDelta -= 256; + else if (yDelta <= -128) + yDelta += 256; + + return yBeg + yDelta*(x-xBeg)/(xEnd-xBeg); +} + + +/* + ITxBFDivParams - interpolate Divider calibration parameter based on channel and EEPROM + divValues - returns the Divider Calibration values for this channel + channel - the channel to interpolate for + divParams - the Divider Calibration parameters from EEPROM +*/ + +#ifdef MT76x2 +static void mt76x2_ITxBFDivParams(UCHAR divValues[2], int channel, ITXBF_DIV_PARAMS *divParams) +{ + if (channel <= 14) + divValues[0] = InterpParam(channel, 1, 14, divParams->E1gBeg, divParams->E1gEnd); + else if (channel <= 60) + divValues[0] = InterpParam(channel, 36, 64, divParams->E1aLowBeg, divParams->E1aLowEnd); + //else if (channel <= 60) + // divValues[0] = InterpParam(channel, 44, 60, divParams->aLowBeg, divParams->aLowEnd); + else if (channel <= 120) + divValues[0] = InterpParam(channel, 100, 120, divParams->E1aMidBeg, divParams->E1aMidMid); + else if (channel <= 140) + divValues[0] = InterpParam(channel, 120, 140, divParams->E1aMidMid, divParams->E1aMidEnd); + else + divValues[0] = InterpParam(channel, 149, 173, divParams->E1aHighBeg, divParams->E1aHighEnd); +} +#endif + +/* + ITxBFLnaParams - interpolate LNA compensation parameter based on channel and EEPROM. + lnaValues - returns the quantized LNA compensation values for M-L, H-L and H-M + channel - the channel to interpolate for + lnaParams - the LNA Calibration parameters from EEPROM +*/ + +#ifdef MT76x2 +static void mt76x2_ITxBFLnaParams(UCHAR lnaValues[3], int channel, ITXBF_LNA_PARAMS *lnaParams) +{ + int i; + + if (channel <= 14) + { + lnaValues[0] = InterpParam(channel, 1, 14, lnaParams->E1gBeg[0], lnaParams->E1gEnd[0]); + lnaValues[1] = InterpParam(channel, 1, 14, lnaParams->E1gBeg[1], lnaParams->E1gEnd[1]); + lnaValues[2] = InterpParam(channel, 1, 14, lnaParams->E1gBeg[2], lnaParams->E1gEnd[2]); + } + else if (channel <= 64) + { + lnaValues[0] = InterpParam_check(channel, 36, 64, lnaParams->E1aLowBeg[0], lnaParams->E1aLowEnd[0]); + lnaValues[1] = InterpParam_check(channel, 36, 64, lnaParams->E1aLowBeg[1], lnaParams->E1aLowEnd[1]); + lnaValues[2] = InterpParam_check(channel, 36, 64, lnaParams->E1aLowBeg[2], lnaParams->E1aLowEnd[2]); + } + else if (channel <= 120) + { + lnaValues[0] = InterpParam(channel, 100, 120, lnaParams->E1aMidBeg[0], lnaParams->E1aMidMid[0]); + lnaValues[1] = InterpParam(channel, 100, 120, lnaParams->E1aMidBeg[1], lnaParams->E1aMidMid[1]); + lnaValues[2] = InterpParam(channel, 100, 120, lnaParams->E1aMidBeg[2], lnaParams->E1aMidMid[2]); + } + else if (channel <= 140) + { + lnaValues[0] = InterpParam(channel, 120, 140, lnaParams->E1aMidMid[0], lnaParams->E1aMidEnd[0]); + lnaValues[1] = InterpParam(channel, 120, 140, lnaParams->E1aMidMid[1], lnaParams->E1aMidEnd[1]); + lnaValues[2] = InterpParam(channel, 120, 140, lnaParams->E1aMidMid[2], lnaParams->E1aMidEnd[2]); + } + else + { + lnaValues[0] = InterpParam(channel, 149, 173, lnaParams->E1aHighBeg[0], lnaParams->E1aHighEnd[0]); + lnaValues[1] = InterpParam(channel, 149, 173, lnaParams->E1aHighBeg[1], lnaParams->E1aHighEnd[1]); + lnaValues[2] = InterpParam(channel, 149, 173, lnaParams->E1aHighBeg[2], lnaParams->E1aHighEnd[2]); + } +} +#endif + + +/* + ITxBFPhaseParams - interpolate Phase compensation parameters based on channel and EEPROM + phaseValues - returns the Phase compensation values for this channel + channel - the channel to interpolate for + phaseParams - the Phase Calibration parameters from EEPROM +*/ + +#ifdef MT76x2 +static void mt76x2_ITxBFPhaseParams( RTMP_ADAPTER *pAd, UCHAR phaseValues[2], UCHAR channel, ITXBF_PHASE_PARAMS *phaseParams) +{ + INT chanIdx; + INT dbg; + UINT dbg1, dbg2; + + chanIdx = ate_txbf_get_chan_idx(pAd, channel, 1); + + if(pAd->CommonCfg.ITxBfCalibMode!=2) //Use the phase of group center for other channels in the group + { + if (channel <= 48) + { + phaseValues[0] = phaseParams->E1aPhase[1]; //chan44 + } + else if (channel <= 64) + { + phaseValues[0] = phaseParams->E1aPhase[3]; //chan60 + } + else if (channel <= 118) + { + phaseValues[0] = phaseParams->E1aPhase[5]; //chan108 + } + else if (channel <= 144) + { + phaseValues[0] = phaseParams->E1aPhase[8]; //chan132 + } + else + { + phaseValues[0] = phaseParams->E1aPhase[11];//chan157 + } + } + else // interpolate iBF phase from 13 calibrated channels + { + if(chanIdx >=0) + { + phaseValues[0] = phaseParams->E1aPhase[chanIdx]; + DBGPRINT(RT_DEBUG_TRACE, + ("%s : \n" + "Phase idx = %d, Phase = 0x%x\n", + __FUNCTION__,chanIdx, phaseValues[0])); + } + else + { + if (channel <= 48) + { + phaseValues[0] = InterpParam(channel, 36, 44, phaseParams->E1aPhase[0], phaseParams->E1aPhase[1]); + dbg =1 ; dbg1= phaseParams->E1aPhase[0]; dbg2 =phaseParams->E1aPhase[1]; + } + else if (channel <= 64) + { + phaseValues[0] = InterpParam(channel, 52, 60, phaseParams->E1aPhase[2], phaseParams->E1aPhase[3]); + dbg =2 ; dbg1= phaseParams->E1aPhase[2]; dbg2 =phaseParams->E1aPhase[3]; + } + else if (channel <= 108) + { + phaseValues[0] = InterpParam(channel, 100, 108, phaseParams->E1aPhase[4], phaseParams->E1aPhase[5]); + dbg =3 ; dbg1= phaseParams->E1aPhase[4]; dbg2 =phaseParams->E1aPhase[5]; + } + else if (channel <= 118) + { + phaseValues[0] = InterpParam(channel, 108, 116, phaseParams->E1aPhase[5], phaseParams->E1aPhase[6]); + dbg =4 ; dbg1= phaseParams->E1aPhase[5]; dbg2 =phaseParams->E1aPhase[6]; + } + else if (channel <= 132) + { + phaseValues[0] = InterpParam(channel, 120, 132, phaseParams->E1aPhase[7], phaseParams->E1aPhase[8]); + dbg =5 ; dbg1= phaseParams->E1aPhase[7]; dbg2 =phaseParams->E1aPhase[8]; + } + else if (channel <= 144) + { + phaseValues[0] = InterpParam(channel, 132, 140, phaseParams->E1aPhase[8], phaseParams->E1aPhase[9]); + dbg =6 ; dbg1= phaseParams->E1aPhase[8]; dbg2 =phaseParams->E1aPhase[9]; + } + else if (channel <= 157) + { + phaseValues[0] = InterpParam(channel, 149, 157, phaseParams->E1aPhase[10], phaseParams->E1aPhase[11]); + dbg =7 ; dbg1= phaseParams->E1aPhase[10]; dbg2 =phaseParams->E1aPhase[11]; + } + else + { + phaseValues[0] = InterpParam(channel, 157, 165, phaseParams->E1aPhase[11], phaseParams->E1aPhase[12]); + dbg =8 ; dbg1= phaseParams->E1aPhase[11]; dbg2 =phaseParams->E1aPhase[12]; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s : \n" + "dbg_flag = %d\n" + " PHASE_base0 = 0x%x, PHASE base1 = 0x%x\n", + __FUNCTION__,dbg, dbg1,dbg2)); + } + } +} +#endif /*MT76x2*/ + + +#define ITXBF_EEPROM_WORDS 19 /* 38 bytes of ITxBF parameters */ + + + +/* + ITxBFGetEEPROM - Read ITxBF calibration parameters from EEPROM + phaseParams - pointer to BBP Phase calibration parameters. If NULL then parameters are not returned + lnaParams - pointer to BBP LNA calibration parameters. If NULL then parameters are not returned + divParams - divider calibration parameters. If NULL then parameters are not returned +*/ +BOOLEAN ITxBFGetEEPROM( + IN RTMP_ADAPTER *pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams, + IN ITXBF_TANK_PARAMS *tankParams) +{ + USHORT EE_Value[14], andValue,phase_array_size; + INT i; + BOOLEAN EfuseStat; + + for(i=0; i<14; i++) + { + EE_Value[i]=0xFFFF; + } + + EfuseStat = TRUE; + + /* Get Phase parameters */ + if (phaseParams != NULL) + { + /* Read and check for initialized values */ + andValue = 0xFFFF; + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + for(i=0; i<7; i++) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&EE_Value[i]), &(pAd->EEPROMImage[EEPROM1_ITXBF_CAL_RESPHASE + 2*i]),2); + else + RT28xx_EEPROM_READ16(pAd, EEPROM1_ITXBF_CAL_RESPHASE + 2*i, EE_Value[i]); + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) + { + memset(phaseParams, 0xFF, sizeof(*phaseParams)); + EfuseStat = FALSE; + } + else + { + + for(i=0; i<6; i++) + { + phaseParams->E1aPhase[2*i] = (EE_Value[i] & 0x00FF); + phaseParams->E1aPhase[2*i+1]= (EE_Value[i] & 0xFF00)>>8; + } + phaseParams->E1aPhase[12] = (EE_Value[6] & 0x00FF); + } + + //PhaseError + for(i=0; i<7; i++) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&EE_Value[i]), &(pAd->EEPROMImage[EEPROM1_ITXBF_CAL_RESPHASE_ERR + 2*i]),2); + else + RT28xx_EEPROM_READ16(pAd, EEPROM1_ITXBF_CAL_RESPHASE_ERR + 2*i, EE_Value[i]); + andValue &= EE_Value[i]; + } + + for(i=0; i<6; i++) + { + phaseParams->E1aPhaseErr[2*i] = (EE_Value[i] & 0x00FF); + phaseParams->E1aPhaseErr[2*i+1]= (EE_Value[i] & 0xFF00)>>8; + } + phaseParams->E1aPhaseErr[12] = (EE_Value[6] & 0x00FF); + } +#endif /* MT76x2 */ + } + + /* Get Divider Phase parameters */ + if (divParams != NULL) + { + /* Read and check for initialized values */ + andValue = 0xFFFF; + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + for(i=0; i<3; i++) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&EE_Value[i]), &(pAd->EEPROMImage[EEPROM1_ITXBF_CAL_DIVPHASE + 2*i ]),2); + else + RT28xx_EEPROM_READ16(pAd, EEPROM1_ITXBF_CAL_DIVPHASE + 2*i, EE_Value[i]); + + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) + { + memset(divParams, 0xFF, sizeof(*divParams)); + EfuseStat = FALSE; + } + else + { + for(i=0; i<2; i++) + { + divParams->E1aDivPhase[2*i] = (EE_Value[i] & 0x00FF); + divParams->E1aDivPhase[2*i+1]= (EE_Value[i] & 0xFF00)>>8; + } + + divParams->E1aDivPhase[4] = (EE_Value[2] & 0x00FF); + } + }/* IS_MT76x2(pAd) */ +#endif + } + + /* Get LNA Parameters */ + if (lnaParams != NULL) + { + /* Read and check for initialized values */ + andValue = 0xFFFF; + + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + for (i=0; i<14; i++) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&EE_Value[i]), &(pAd->EEPROMImage[EEPROM1_ITXBF_CAL + 20 + 2*i]),2); + else + RT28xx_EEPROM_READ16(pAd, EEPROM1_ITXBF_CAL + 20 + 2*i, EE_Value[i]); + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) + { + memset(lnaParams, 0xFF, sizeof(*lnaParams)); + EfuseStat = FALSE; + } + else + { + lnaParams->E1gBeg[0] = (EE_Value[0] & 0x00FF); + lnaParams->E1gBeg[1] = (EE_Value[0] & 0xFF00)>>8; + lnaParams->E1gBeg[2] = (EE_Value[1] & 0x00FF); + lnaParams->E1gEnd[0] = (EE_Value[1] & 0xFF00)>>8; + lnaParams->E1gEnd[1] = (EE_Value[2] & 0x00FF); + lnaParams->E1gEnd[2] = (EE_Value[2] & 0xFF00)>>8; + + lnaParams->E1aHighBeg[0] = (EE_Value[3] & 0x00FF); + lnaParams->E1aHighBeg[1] = (EE_Value[3] & 0xFF00)>>8; + lnaParams->E1aHighBeg[2] = (EE_Value[4] & 0x00FF); + lnaParams->E1aHighEnd[0] = (EE_Value[4] & 0xFF00)>>8; + lnaParams->E1aHighEnd[1] = (EE_Value[5] & 0x00FF); + lnaParams->E1aHighEnd[2] = (EE_Value[5] & 0xFF00)>>8; + + lnaParams->E1aLowBeg[0] = (EE_Value[6] & 0x00FF); + lnaParams->E1aLowBeg[1] = (EE_Value[6] & 0xFF00)>>8; + lnaParams->E1aLowBeg[2] = (EE_Value[7] & 0x00FF); + lnaParams->E1aLowEnd[0] = (EE_Value[7] & 0xFF00)>>8; + lnaParams->E1aLowEnd[1] = (EE_Value[8] & 0x00FF); + lnaParams->E1aLowEnd[2] = (EE_Value[8] & 0xFF00)>>8; + + lnaParams->E1aMidBeg[0] = (EE_Value[9] & 0x00FF); + lnaParams->E1aMidBeg[1] = (EE_Value[9] & 0xFF00)>>8; + lnaParams->E1aMidBeg[2] = (EE_Value[10] & 0x00FF); + lnaParams->E1aMidMid[0] = (EE_Value[10] & 0xFF00)>>8; + lnaParams->E1aMidMid[1] = (EE_Value[11] & 0x00FF); + lnaParams->E1aMidMid[2] = (EE_Value[11] & 0xFF00)>>8; + lnaParams->E1aMidEnd[0] = (EE_Value[12] & 0x00FF); + lnaParams->E1aMidEnd[1] = (EE_Value[12] & 0xFF00)>>8; + lnaParams->E1aMidEnd[2] = (EE_Value[13] & 0x00FF); + }/* andValue == 0xFFFF */ + }/* IS_MT76x2(pAd) */ +#endif + }/* lnaParams != NULL */ + + /* Get tank code parameters */ + if (tankParams != NULL) + { + /* Read and check for initialized values */ + andValue = 0xFFFF; +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + for(i=0; i<5; i++) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&EE_Value[i]), &(pAd->EEPROMImage[EEPROM1_ITXBF_CAL_TANK + 2*i ]),2); + else + RT28xx_EEPROM_READ16(pAd, EEPROM1_ITXBF_CAL_TANK + 2*i , EE_Value[i]); + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) + { + memset(tankParams, 0xFF, sizeof(*tankParams)); + EfuseStat = FALSE; + } + else + { + for(i=0; i<5; i++) + { + tankParams->TankCode[2*i] = (EE_Value[i] & 0x00FF); //Repeater tank code + tankParams->TankCode[2*i+1]= (EE_Value[i] & 0xFF00)>>8; // IQM tank code + } + } + }/* IS_MT76x2(pAd) */ +#endif + } + + return EfuseStat; + +} + + +/* + ITxBFSetEEPROM - Save ITxBF calibration parameters in EEPROM + phaseParams - pointer to BBP calibration parameters. If NULL then parameters are not written + lnaParams - pointer to BBP LNA calibration parameters. If NULL then parameters are not written + divParams - divider calibration parameters. If NULL then parameters are not written +*/ +void ITxBFSetEEPROM( + IN PRTMP_ADAPTER pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams, + IN ITXBF_TANK_PARAMS *tankParams) +{ + USHORT EE_Value[14], eeTmp; + int i, eeAddr; + + for(i=0; i<14; i++) + { + EE_Value[i]=0xFFFF; + } + /* Set EEPROM parameters */ + + /* Phase parameters */ + if (phaseParams != NULL) + { + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + for (i=0; i<6 ; i++) + { + EE_Value[i] = phaseParams->E1aPhase[2*i] | (phaseParams->E1aPhase[2*i+1]<<8); + } + EE_Value[6] = phaseParams->E1aPhase[12] | 0xFF00; + + for (i=0; i<7; i++) + { + eeAddr = EEPROM1_ITXBF_CAL_RESPHASE + 2*i ; + + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&eeTmp), &(pAd->EEPROMImage[eeAddr]),2); + else + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + + if (eeTmp != EE_Value[i]) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory(&(pAd->EEPROMImage[eeAddr]), (PUCHAR) (&EE_Value[i]),2); + else + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + + DBGPRINT(RT_DEBUG_TRACE, + ("ITxBFGetEEPROM check ::: \n" + "EEPROM origina data =0x%x\n" + "Input data = 0x%x\n" + "Saved low byte data in EEPROM=0x%x\n" + "Saved high byte data in EEPROM=0x%x\n", + eeTmp, + EE_Value[i], + pAd->EEPROMImage[eeAddr], + pAd->EEPROMImage[eeAddr + 1])); + } + + //PhaseError + for (i=0; i<6 ; i++){ + EE_Value[i] = phaseParams->E1aPhaseErr[2*i] | (phaseParams->E1aPhaseErr[2*i+1]<<8); + } + EE_Value[6] = phaseParams->E1aPhaseErr[12] | 0xFF00; + + for (i=0; i<7; i++) + { + eeAddr = EEPROM1_ITXBF_CAL_RESPHASE_ERR + 2*i ; + + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&eeTmp), &(pAd->EEPROMImage[eeAddr]),2); + else + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + + if (eeTmp != EE_Value[i]) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory(&(pAd->EEPROMImage[eeAddr]), (PUCHAR) (&EE_Value[i]),2); + else + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + } + }/* IS_MT76x2(pAd) */ +#endif + }/* phaseParams != NULL */ + + /* Divider Phase parameters */ + if (divParams != NULL) + { + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + EE_Value[0] = divParams->E1aDivPhase[0] | (divParams->E1aDivPhase[1]<<8); + EE_Value[1] = divParams->E1aDivPhase[2] | (divParams->E1aDivPhase[3] <<8); + EE_Value[2] = divParams->E1aDivPhase[4] | 0xFF00; + + for (i=0; i<3; i++) + { + eeAddr = EEPROM1_ITXBF_CAL_DIVPHASE + 2*i; + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&eeTmp), &(pAd->EEPROMImage[eeAddr]),2); + else + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + + if (eeTmp != EE_Value[i]) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory(&(pAd->EEPROMImage[eeAddr]), (PUCHAR) (&EE_Value[i]),2); + else + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + } + }/* IS_MT76x2(pAd) */ +#endif + }/* divParams != NULL*/ + + /* LNA Phase parameters */ + if (lnaParams != NULL) { + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + EE_Value[0] = lnaParams->E1gBeg[0] | (lnaParams->E1gBeg[1]<<8); + EE_Value[1] = lnaParams->E1gBeg[2] | (lnaParams->E1gEnd[0]<<8); + EE_Value[2] = lnaParams->E1gEnd[1] | (lnaParams->E1gEnd[2]<<8); + + EE_Value[3] = lnaParams->E1aHighBeg[0] | (lnaParams->E1aHighBeg[1]<<8); + EE_Value[4] = lnaParams->E1aHighBeg[2] | (lnaParams->E1aHighEnd[0]<<8); + EE_Value[5] = lnaParams->E1aHighEnd[1] | (lnaParams->E1aHighEnd[2]<<8); + EE_Value[6] = lnaParams->E1aLowBeg[0] | (lnaParams->E1aLowBeg[1]<<8); + EE_Value[7] = lnaParams->E1aLowBeg[2] | (lnaParams->E1aLowEnd[0]<<8); + EE_Value[8] = lnaParams->E1aLowEnd[1] | (lnaParams->E1aLowEnd[2]<<8); + EE_Value[9] = lnaParams->E1aMidBeg[0] | (lnaParams->E1aMidBeg[1]<<8); + EE_Value[10] = lnaParams->E1aMidBeg[2] | (lnaParams->E1aMidMid[0]<<8); + EE_Value[11] = lnaParams->E1aMidMid[1] | (lnaParams->E1aMidMid[2]<<8); + EE_Value[12] = lnaParams->E1aMidEnd[0] | (lnaParams->E1aMidEnd[1]<<8); + EE_Value[13] = lnaParams->E1aMidEnd[2] | 0xAA00; + + for (i=0; i<14; i++) + { + eeAddr = EEPROM1_ITXBF_CAL + 20 + 2*i; + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&eeTmp), &(pAd->EEPROMImage[eeAddr]),2); + else + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + + if (eeTmp != EE_Value[i]) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory(&(pAd->EEPROMImage[eeAddr]), (PUCHAR) (&EE_Value[i]),2); + else + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + + DBGPRINT(RT_DEBUG_INFO, + ("ITxBFGetEEPROM check ::: \n" + "EEPROM origina data =0x%x\n" + "Input data = 0x%x\n" + "Saved low byte data in EEPROM=0x%x\n" + "Saved high byte data in EEPROM=0x%x\n", + eeTmp, + pAd->EEPROMImage[eeAddr], + pAd->EEPROMImage[eeAddr + 1], + EE_Value[i])); + } + }/* IS_MT76x2(pAd) */ +#endif + }/* lnaParams != NULL */ + + /* tank code parameters */ + if (tankParams != NULL) + { +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + for (i=0; i<5 ; i++) + { + EE_Value[i] = tankParams->TankCode[2*i] | (tankParams->TankCode[2*i+1]<<8); + } + + for (i=0; i<5; i++) + { + eeAddr = EEPROM1_ITXBF_CAL_TANK + 2*i; + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory((PUCHAR) (&eeTmp), &(pAd->EEPROMImage[eeAddr]),2); + else + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + + if (eeTmp != EE_Value[i]) + { + if (pAd->chipCap.FlgITxBfBinWrite) + NdisMoveMemory(&(pAd->EEPROMImage[eeAddr]), (PUCHAR) (&EE_Value[i]),2); + else + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + + DBGPRINT(RT_DEBUG_INFO, + ("ITxBFGetEEPROM check ::: \n" + "EEPROM origina data =0x%x\n" + "Input data = 0x%x\n" + "Saved low byte data in EEPROM=0x%x\n" + "Saved high byte data in EEPROM=0x%x\n", + eeTmp, + pAd->EEPROMImage[eeAddr], + pAd->EEPROMImage[eeAddr + 1], + EE_Value[i])); + } + + }/* IS_MT76x2(pAd) */ +#endif + }/* phaseParams != NULL */ +} + + +/* + ITxBFLoadLNAComp - load the LNA compensation registers +*/ + +#ifdef MT76x2 +VOID mt76x2_ITxBFLoadLNAComp( + IN RTMP_ADAPTER *pAd) +{ + ITXBF_LNA_PARAMS lnaParams; + UCHAR lnaValues[3]; + UCHAR bbpValue = 0; + int i; + UCHAR channel = pAd->CommonCfg.Channel; + UINT value32; + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + /* Get values */ + ITxBFGetEEPROM(pAd, 0, &lnaParams, 0, 0); + + mt76x2_ITxBFLnaParams(lnaValues, channel, &lnaParams); + + RTMP_IO_READ32(pAd, CAL_R0, &value32); + for (i=0; i < NUM_CHAIN; i++) + { + RTMP_IO_WRITE32(pAd, CAL_R0, value32 | (i<<5)); + RTMP_IO_WRITE32(pAd, RXFE_R3, lnaValues[i]); + } + + DBGPRINT(RT_DEBUG_TRACE, + ("============== Interpolate LNA phase ===============\n" + "lnaValues[0] = %d\n" + "lnaValues[1] = %d\n" + "lnaValues[2] = %d\n" + "====================================================\n", + (360 * lnaValues[0]) >> 8, (360 * lnaValues[1]) >> 8, (360 * lnaValues[2]) >> 8)); + + /* Enable RX Phase Compensation */ + RTMP_IO_READ32(pAd, TXBE_R12, &value32); + RTMP_IO_WRITE32(pAd, TXBE_R12, value32 | 0x20); +} + + +INT ITxBFLoPhaseCalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN eepromUpdateFlg, + OUT UCHAR *LoPhase) +{ + + UINT CR_BK[25]; + BOOLEAN calStatusReport; + ULONG stTimeChk0, stTimeChk1; + + NdisGetSystemUpTime(&stTimeChk0); + // Backup CRs which are used in Divider Caliration + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX17, &CR_BK[0]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX17, &CR_BK[1]); + mt_rf_read(pAd, RF_Path0, RG_WF0_RXG_TOP, &CR_BK[2]); + mt_rf_read(pAd, RF_Path1, RG_WF0_RXG_TOP, &CR_BK[3]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP3, &CR_BK[4]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP3, &CR_BK[5]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP0, &CR_BK[6]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP0, &CR_BK[7]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP1, &CR_BK[6]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP1, &CR_BK[7]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX0, &CR_BK[6]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX0, &CR_BK[7]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX4, &CR_BK[8]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX4, &CR_BK[9]); + + RTMP_IO_READ32(pAd, TXBE_R8, &CR_BK[10]); + RTMP_IO_READ32(pAd, CORE_R34, &CR_BK[11]); + RTMP_IO_READ32(pAd, CORE_R1, &CR_BK[12]); + RTMP_IO_READ32(pAd, RF_BSI_CKDIV, &CR_BK[13]); + RTMP_IO_READ32(pAd, DACCLK_EN_DLY_CFG, &CR_BK[14]); + RTMP_IO_READ32(pAd, PWR_PIN_CFG, &CR_BK[15]); + RTMP_IO_READ32(pAd, CORE_R33, &CR_BK[16]); + RTMP_IO_READ32(pAd, TXBE_R6, &CR_BK[17]); + RTMP_IO_READ32(pAd, CORE_R4, &CR_BK[18]); + RTMP_IO_READ32(pAd, TXBE_R1, &CR_BK[19]); + RTMP_IO_READ32(pAd, AGC1_R0, &CR_BK[20]); + RTMP_IO_READ32(pAd, TXBE_R4, &CR_BK[21]); + RTMP_IO_READ32(pAd, CAL_R2, &CR_BK[22]); + RTMP_IO_READ32(pAd, TXBE_R6, &CR_BK[23]); + RTMP_IO_READ32(pAd, CAL_R5, &CR_BK[24]); + + NdisGetSystemUpTime(&stTimeChk1); + DBGPRINT(RT_DEBUG_INFO, ("%s : Lo Phase calibration duration1 = %ld ms\n", + __FUNCTION__, (stTimeChk1 - stTimeChk0)*1000/OS_HZ)); + + // Do the divider calibration + NdisGetSystemUpTime(&stTimeChk0); + calStatusReport = mt76x2_ITxBFLoPhaseCalibration(pAd, eepromUpdateFlg, LoPhase); + NdisGetSystemUpTime(&stTimeChk1); + DBGPRINT(RT_DEBUG_INFO, ("%s : Lo Phase calibration duration2 = %ld ms\n", + __FUNCTION__, (stTimeChk1 - stTimeChk0)*1000/OS_HZ)); + + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX17, CR_BK[0]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX17, CR_BK[1]); + mt_rf_write(pAd, RF_Path0, RG_WF0_RXG_TOP, CR_BK[2]); + mt_rf_write(pAd, RF_Path1, RG_WF0_RXG_TOP, CR_BK[3]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP3, CR_BK[4]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP3, CR_BK[5]); + //mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, CR_BK[6]); // + //mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, CR_BK[7]); // + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP1, CR_BK[6]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP1, CR_BK[7]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX0, CR_BK[6]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX0, CR_BK[7]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, CR_BK[8]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, CR_BK[9]); + + RTMP_IO_WRITE32(pAd, TXBE_R8, CR_BK[10]); + RTMP_IO_WRITE32(pAd, CORE_R34, CR_BK[11]); + RTMP_IO_WRITE32(pAd, CORE_R1, CR_BK[12]); + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, CR_BK[13]); + RTMP_IO_WRITE32(pAd, DACCLK_EN_DLY_CFG, CR_BK[14]); + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, CR_BK[15]); + RTMP_IO_WRITE32(pAd, CORE_R33, CR_BK[16]); + RTMP_IO_WRITE32(pAd, TXBE_R6, CR_BK[17]); + RTMP_IO_WRITE32(pAd, CORE_R4, CR_BK[18]); + RTMP_IO_WRITE32(pAd, TXBE_R1, CR_BK[19]); + RTMP_IO_WRITE32(pAd, AGC1_R0, CR_BK[20]); + RTMP_IO_WRITE32(pAd, TXBE_R4, CR_BK[21]); + RTMP_IO_WRITE32(pAd, CAL_R2, CR_BK[22]); + RTMP_IO_WRITE32(pAd, TXBE_R6, CR_BK[23]); + RTMP_IO_WRITE32(pAd, CAL_R5, CR_BK[24]); + + return calStatusReport; +} + + +INT mt76x2_ITxBFLoPhaseCalibration( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN eepromUpdateFlg, + OUT UCHAR *LoPhase) +{ + int i; + UINT32 phaseCaliStatus, phaseCaliResult, value32; + UCHAR LoPhCalPath[2]={RX1TX0, RX0TX1}; + //UINT32 LnaVgaSet[2] = {0x000B8F8F, 0x000B9999}, TxgGain[2] = {0x160, 0x150}; + UINT32 LnaVgaSet[2] = {0x000A8585, 0x000A8585}, TxgGain[2] = {0x110, 0x110}; + UCHAR timeOutCount; + INT mPhase[2]; + INT mCalPhase[2]; + INT avgIData, avgQData; + UCHAR peakI[2]; + UCHAR pathIdx[2] = {0, 1}, pathInv[2] = {1, 0}; + ITXBF_DIV_PARAMS LoPhaseParams; + UCHAR channel = pAd->CommonCfg.Channel; + UCHAR LoPhaseOffset; + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + /* DPD and TSSI HW off */ + RTMP_IO_READ32(pAd,TXBE_R8, &value32); + value32 &= ~0x08000; + RTMP_IO_WRITE32(pAd,TXBE_R8, value32); // DPD off + + RTMP_IO_READ32(pAd,CORE_R34, &value32); + value32 &= ~0x60; + value32 |= 0x40; + RTMP_IO_WRITE32(pAd,CORE_R34, value32); // TSSI off + + //for (i = 0; i < 2; i++) // PM01, PM10 + for (i = 1; i < 2; i++) // just need PM10 + { + mt_rf_write(pAd, pathIdx[i], RFDIGI_TRX17, TxgGain[i]); // set txg gain table = to manual mode + mt_rf_write(pAd, pathIdx[i], RG_WF0_RXG_TOP, 0x00492016);// TRSWITCH + + // ********* external llopback ********* + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP3, 0x11C73047); // Force Divider ON + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP3, 0x11C73047); // Force Divider ON + + mt_rf_write(pAd, pathInv[i], RFDIGI_TOP0, 0x80056733); // enable SX/RX/for WF0 + mt_rf_write(pAd, pathInv[i], RFDIGI_TOP1, 0xF0040122); // set TRSW in RX mode for WF0 + mt_rf_write(pAd, pathIdx[i], RFDIGI_TOP0, 0x80056F23); // enable SX/RX/for WF1 + mt_rf_write(pAd, pathIdx[i], RFDIGI_TOP1, 0xF0040123); // set TRSW in RX mode for WF1 + + // ********* cal setting ******** + RTMP_IO_WRITE32(pAd, CORE_R1, 0x00000000); // BW=20MHz ADC=40MHz + + // ********* pre dcoc ******** + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, 0x00000008); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX0, 0x0500010F); + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, 0x00000002); + RTMP_IO_WRITE32(pAd, DACCLK_EN_DLY_CFG, 0x80008000); // DAC Clock on + + // ********* send single tone ****** + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00000000); // to turn off "adda power down" + RTMP_IO_WRITE32(pAd, CORE_R33, 0x00021E00); // RF/BBP clk control + RTMP_IO_WRITE32(pAd, TXBE_R6, 0x40002101); // Test format contol : Tx single tone setting + RTMP_IO_WRITE32(pAd, CORE_R4, 0x00000001); // core soft reset enable + RTMP_IO_WRITE32(pAd, CORE_R4, 0x00000000); // core soft reset enable + RTMP_IO_WRITE32(pAd, TXBE_R1, 0x00000606); // Tx power control + + // ********* LNA VGA setting ****** + mt_rf_write(pAd, pathInv[i], RFDIGI_TRX4, LnaVgaSet[i]); + + // ********* start iBF cal ****** + RTMP_IO_WRITE32(pAd, AGC1_R0, 0x00007408); // 01:1R ADC1, 00 : 1R ADC0 + RTMP_IO_WRITE32(pAd, TXBE_R4, 0x00000008); // a default setting, 2T + RTMP_IO_WRITE32(pAd, CAL_R2, LoPhCalPath[i]); // TR loop setting(0:T0R0,1:T1R0,5:T1R1,4:T0R1) + + RTMP_IO_WRITE32(pAd,TXBE_R6, 0xC0002101); //Test format contol : Tx single tone setting + RTMP_IO_WRITE32(pAd,CAL_R5, 0x000040C); //set accumulation length + + // Enable Divider phase calibration + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000086); + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + timeOutCount = 0; + while (phaseCaliStatus & 0x80) + { + if (timeOutCount == 10) + { + DBGPRINT(RT_DEBUG_TRACE,("phaseCaliStatus = %x\n", phaseCaliStatus)); + DBGPRINT(RT_DEBUG_TRACE,("Lo phase HW calibration can't finish process\n")); + break; + } + + timeOutCount++; + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + } + + // 0x2C2C + // Bit 23:16 Correlator Phase + // Bit 15:8 Correlator Q value + // Bit 7:0 Correlator I value + RTMP_IO_READ32(pAd,CAL_R11, &phaseCaliResult); + mPhase[i] = (INT)((INT)((phaseCaliResult << 8) & 0xFF000000) >> 24); + avgQData = (INT)((INT)((phaseCaliResult << 16) & 0xFF000000) >> 24); + avgIData = (INT)((INT)((phaseCaliResult << 24) & 0xFF000000) >> 24); + mCalPhase[i] = iAtan2(avgQData, avgIData); + + peakI[i] = (UCHAR)(phaseCaliResult >> 24); + + DBGPRINT(RT_DEBUG_TRACE,( + "*****ITxBFLoPhaseCalibration()****\n" + "Lo phase[%d] = 0x%x\n" + "CAL_R11=0x%x\n" + "Peak I value=0x%x\n" + "I value=0x%x, Q value=0x%x\n", + i, + mPhase[i], + phaseCaliResult, + peakI[i], + avgIData, avgQData)); + + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000006); // Disable Calibration + + // ********* Top Manual Release ********** + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056733); // WF0 manul mode + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056730); // WF0 manul mode + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x80056730); // WF0 manul mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F23); // WF0 manul mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F20); // WF0 manul mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x80056F20); // WF0 manul mode + } + + /* Save new reference values in EEPROM and BBP */ + ITxBFGetEEPROM(pAd, 0, 0, &LoPhaseParams, 0); + + if (eepromUpdateFlg == TRUE) + { + + if( channel == 1) + { + LoPhaseParams.E1gBeg= mPhase[1]; + } + else if( channel == 14) + { + LoPhaseParams.E1gEnd= mPhase[1]; + } + + ITxBFSetEEPROM(pAd, 0, 0, &LoPhaseParams, 0); + + *LoPhase = 0; + + DBGPRINT(RT_DEBUG_TRACE,( + "####### DebugKK[2] chan= %d ,LOphase in efuse = 0x%2x\n", + channel,mPhase[1])); + } + else + { + if ( channel == 1) + { + LoPhaseOffset = LoPhaseParams.E1gBeg; + } + else + { + LoPhaseOffset = LoPhaseParams.E1gEnd; + } + + *LoPhase = (mPhase[1] - LoPhaseOffset) & 0xFF; + + DBGPRINT(RT_DEBUG_TRACE,( + "LO phase this time = 0x%x\n" + "Lo Phase difference = 0x%x\n" + "Lo Phase in Efuse = 0x%x\n", + mPhase[1],*LoPhase, LoPhaseOffset)); + } + + return TRUE; +} + +INT ITxBFDividerCalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + OUT UCHAR *divPhase) +{ + + UINT CR_BK[35]; + BOOLEAN calStatusReport; + ULONG stTimeChk0, stTimeChk1; + + NdisGetSystemUpTime(&stTimeChk0); + // Backup CRs which are used in Divider Caliration + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX17, &CR_BK[0]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX38, &CR_BK[1]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX39, &CR_BK[2]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX42, &CR_BK[3]); + mt_rf_read(pAd, RF_Path0, A_BAND_PA, &CR_BK[4]); + mt_rf_read(pAd, RF_Path0, A_BAND_IQM_TSSI_DIV_LPF, &CR_BK[5]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX17, &CR_BK[6]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX38, &CR_BK[7]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX39, &CR_BK[8]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX42, &CR_BK[9]); + mt_rf_read(pAd, RF_Path1, A_BAND_PA, &CR_BK[10]); + mt_rf_read(pAd, RF_Path1, A_BAND_IQM_TSSI_DIV_LPF, &CR_BK[11]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX0, &CR_BK[12]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX0, &CR_BK[13]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX4, &CR_BK[14]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX4, &CR_BK[15]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP1, &CR_BK[16]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP1, &CR_BK[17]); + mt_rf_read(pAd, RF_Path0, RFDIGI_ABB_TO_AFE5,&CR_BK[19]); + mt_rf_read(pAd, RF_Path1, RFDIGI_ABB_TO_AFE5,&CR_BK[20]); + + RTMP_IO_READ32(pAd,CORE_R1, &CR_BK[22]); + RTMP_IO_READ32(pAd,CORE_R33, &CR_BK[23]); + RTMP_IO_READ32(pAd,DACCLK_EN_DLY_CFG, &CR_BK[24]); + RTMP_IO_READ32(pAd,TXBE_R6, &CR_BK[25]); + RTMP_IO_READ32(pAd,CORE_R4, &CR_BK[26]); + RTMP_IO_READ32(pAd,TXBE_R1, &CR_BK[27]); + RTMP_IO_READ32(pAd,AGC1_R0, &CR_BK[28]); + RTMP_IO_READ32(pAd,TXBE_R4, &CR_BK[29]); + RTMP_IO_READ32(pAd,CAL_R2, &CR_BK[30]); + RTMP_IO_READ32(pAd,CAL_R5, &CR_BK[31]); + RTMP_IO_READ32(pAd,CAL_R1, &CR_BK[32]); + RTMP_IO_READ32(pAd,TXBE_R5, &CR_BK[33]); + RTMP_IO_READ32(pAd,PWR_PIN_CFG,&CR_BK[34]); + NdisGetSystemUpTime(&stTimeChk1); + DBGPRINT(RT_DEBUG_INFO, ("%s : Divider calibration duration1 = %ld ms\n", + __FUNCTION__, (stTimeChk1 - stTimeChk0)*1000/OS_HZ)); + + // Do the divider calibration + NdisGetSystemUpTime(&stTimeChk0); + RTMP_IO_WRITE32(pAd, AGC1_R0, 0x7408); + calStatusReport = mt76x2_ITxBFDividerCalibration(pAd, calFunction, calMethod, divPhase); + NdisGetSystemUpTime(&stTimeChk1); + DBGPRINT(RT_DEBUG_INFO, ("%s : Divider calibration duration2 = %ld ms\n", + __FUNCTION__, (stTimeChk1 - stTimeChk0)*1000/OS_HZ)); + + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX17, CR_BK[0]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX38, CR_BK[1]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX39, CR_BK[2]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX42, CR_BK[3]); + mt_rf_write(pAd, RF_Path0, A_BAND_PA, CR_BK[4]); + mt_rf_write(pAd, RF_Path0, A_BAND_IQM_TSSI_DIV_LPF, CR_BK[5]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX17, CR_BK[6]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX38, CR_BK[7]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX39, CR_BK[8]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX42, CR_BK[9]); + mt_rf_write(pAd, RF_Path1, A_BAND_PA, CR_BK[10]); + mt_rf_write(pAd, RF_Path1, A_BAND_IQM_TSSI_DIV_LPF, CR_BK[11]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX0, CR_BK[12]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX0, CR_BK[13]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, CR_BK[14]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, CR_BK[15]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP1, CR_BK[16]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP1, CR_BK[17]); + mt_rf_write(pAd, RF_Path0, RFDIGI_ABB_TO_AFE5,CR_BK[19]); + mt_rf_write(pAd, RF_Path1, RFDIGI_ABB_TO_AFE5,CR_BK[20]); + + RTMP_IO_WRITE32(pAd,CORE_R1, CR_BK[22]); + RTMP_IO_WRITE32(pAd,CORE_R33, CR_BK[23]); + RTMP_IO_WRITE32(pAd,DACCLK_EN_DLY_CFG, CR_BK[24]); + RTMP_IO_WRITE32(pAd,TXBE_R6, CR_BK[25]); + //RTMP_IO_WRITE32(pAd,CORE_R4, CR_BK[26]); + RTMP_IO_WRITE32(pAd,TXBE_R1, CR_BK[27]); + RTMP_IO_WRITE32(pAd,AGC1_R0, CR_BK[28]); + RTMP_IO_WRITE32(pAd,TXBE_R4, CR_BK[29]); + RTMP_IO_WRITE32(pAd,CAL_R2, CR_BK[30]); + RTMP_IO_WRITE32(pAd,CAL_R5, CR_BK[31]); + RTMP_IO_WRITE32(pAd,CAL_R1, CR_BK[32]); + RTMP_IO_WRITE32(pAd,TXBE_R5, CR_BK[33]); + RTMP_IO_WRITE32(pAd,PWR_PIN_CFG,CR_BK[34]); + + //Reset bbp + RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000003); //core soft reset enable + RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000000); //core soft reset disable + + return calStatusReport; +} +#endif + +/* + ITxBFDividerCalibration - perform divider calibration + calFunction - the function to perform + 0=>Display cal param, + 1=>Update EEPROM + 2=>Update BBP + 3=>Just return the quantized divider phase in divPhase + 10=> Display params and dump capture data + calMethod - the calibration method to use. 0=>use default method for the band + divPhase - if not NULL, returns the quantized divider phase (0, +/-90, 180 for 2.4G, 0,180 for 5G) + returns TRUE if no errors +*/ +#define ITXBF_MAX_WAIT_CYCLE 10000 + + +#ifdef MT76x2 +INT mt76x2_ITxBFDividerCalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + OUT UCHAR *divPhase) +{ + + ITXBF_DIV_PARAMS divParams; + UCHAR channel = pAd->CommonCfg.Channel; + UCHAR phase[2]; + UCHAR preVGAGainIdx[2]; + int result = TRUE; + UINT32 value32; + int chanidx,groupIdx; + + UCHAR divPhaseValue[2]; + ITXBF_PHASE_PARAMS phaseParams; + UCHAR i,phaseValues[2]; + +#ifdef TIMESTAMP_CAL_CAPTURE1 + struct timeval tval0, tval1; +#endif +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval0); +#endif + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + /* Handle optional divPhase parameter */ + if (divPhase == NULL) + divPhase = divPhaseValue; + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval1); +#endif + + /* Do Calibration */ + // Optional A-Band or G-Band. RF Cal with each TX active */ + //CalcDividerPhase(pAd, phase); + CalcDividerPhase(pAd, TRUE, preVGAGainIdx, phase); + + /* Calculate difference */ + divPhase[0] = phase[0] - phase[1]; + + DBGPRINT(RT_DEBUG_WARN, ( + "############## DebugKK[0] divderPase=0x%x,divderPase_0=0x%x,divderPase_1=0x%x\n",divPhase[0],phase[0],phase[1])); + + /* Compute the quantized delta phase */ + /* Quantize to 180 deg (0x80) with rounding */ + DBGPRINT(RT_DEBUG_WARN, ( + "HW Phase vs Driver Phase (deg)\n" + "ANT0/0 :%d\n" + "ANT1/1 :%d\n" + "divPhase[0] : %d\n", + (360*phase[0])>> 8, + (360*phase[1])>> 8, + (360*divPhase[0])>> 8)); + + //divPhase[0] = (divPhase[0] + 0x40) & 0x80; + + /* Either display parameters, update EEPROM, update BBP registers or dump capture data */ + switch (calFunction) { + case 0: + break; + + case 1: + /* + Save new reference values in EEPROM. The new reference is just the delta phase + values with the old ref value added back in + */ + ITxBFGetEEPROM(pAd, 0, 0, &divParams, 0); + + /* Only allow calibration on specific channels */ + if (channel == 1) + divParams.E1gBeg = divPhase[0]; + else if (channel == 14) + divParams.E1gEnd = divPhase[0]; + else if (channel == 36) + divParams.E1aLowBeg = divPhase[0]; + else if (channel == 64) + divParams.E1aLowEnd = divPhase[0]; + else if (channel == 100) + divParams.E1aMidBeg = divPhase[0]; + else if (channel == 120) + divParams.E1aMidMid = divPhase[0]; + else if (channel == 140) + divParams.E1aMidEnd = divPhase[0]; + else if (channel == 149) + divParams.E1aHighBeg = divPhase[0]; + else if (channel == 173) + divParams.E1aHighEnd = divPhase[0]; + else { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 64, 100, 120, 140, 149 or 173", channel) ); + result = FALSE; + goto exitDivCal; + } + + ITxBFSetEEPROM(pAd, 0, 0, &divParams, 0); + break; + + case 2: + /* + Update BBP Registers. Quantize DeltaPhase to 90 or 180 depending on band. Then + update original phase calibration values from EEPROM and set R176 for Ant 0 and Ant2 + */ + ITxBFGetEEPROM(pAd, &phaseParams, 0, 0, 0); + mt76x2_ITxBFPhaseParams(pAd, phaseValues, channel, &phaseParams); + + groupIdx = ate_txbf_chan_group_base_idx(pAd, channel); + ITxBFGetEEPROM(pAd, 0, 0, &divParams, 0); + + divPhase[0] -= divParams.E1aDivPhase[groupIdx]; + divPhase[0] = (divPhase[0] + 0x40) & 0x80; + + /* Ant0 */ + RTMP_IO_WRITE32(pAd, CAL_R0, 0); + RTMP_IO_WRITE32(pAd, TXBE_R13, phaseValues[0] + divPhase[0]); // for method1 + //RTMP_IO_WRITE32(pAd, TXBE_R13, 0xC4); + + DBGPRINT(RT_DEBUG_WARN, ( + " ============================================================ \n" + " Divider phase = 0x%x\n" + " Residual phase = 0x%x\n" + " Tx phase compensated value = 0x%x\n" + " ============================================================ \n", + divPhase[0], phaseValues[0], phaseValues[0] + divPhase[0])); + + /* Enable TX Phase Compensation */ + RTMP_IO_READ32(pAd, TXBE_R12, &value32); + RTMP_IO_WRITE32(pAd, TXBE_R12, value32 | 0x08); + break; + + case 3: + /* + Update BBP Registers. Quantize DeltaPhase to 90 or 180 depending on band. Then + update original phase calibration values from EEPROM and set R176 for Ant 0 and Ant2 + */ + ITxBFGetEEPROM(pAd, &phaseParams, 0, 0, 0); + mt76x2_ITxBFPhaseParams(pAd, phaseValues, channel, &phaseParams); + + groupIdx = ate_txbf_chan_group_base_idx(pAd, channel); + ITxBFGetEEPROM(pAd, 0, 0, &divParams, 0); + + divPhase[0] -= divParams.E1aDivPhase[groupIdx]; + divPhase[0] = (divPhase[0] + 0x40) & 0x80; + + /* Ant0 */ + RTMP_IO_WRITE32(pAd, CAL_R0, 0); + RTMP_IO_WRITE32(pAd, TXBE_R13, phaseValues[0] + divPhase[0]); + + DBGPRINT(RT_DEBUG_WARN, ( + " ============================================================ \n" + " Group base [%d] divider phase = 0x%x\n" + " Divider phase = 0x%x\n" + " Residual phase = 0x%x\n" + " Tx phase compensated value = 0x%x\n" + " ============================================================ \n", + groupIdx,divParams.E1aDivPhase[groupIdx],divPhase[0], phaseValues[0], phaseValues[0] + divPhase[0])); + + break; + case 10: + /*Save divPhase in efuse if its a group center channel */ + /* Update EEPROM */ + ITxBFGetEEPROM(pAd, 0, 0, &divParams, 0); + + chanidx = ate_txbf_get_chan_idx(pAd, channel, 0); + groupIdx = ate_txbf_chan_group_base_idx(pAd, channel); + if (chanidx != -1) // group center chan + { + divParams.E1aDivPhase[chanidx] = divPhase[0]; + ITxBFSetEEPROM(pAd, 0, 0, &divParams, 0); + divPhase[0] = 0; + + DBGPRINT(RT_DEBUG_WARN, ( + " ============================================================ \n" + " Save Divider phase to efuse[%d], value = 0x%x\n" + " ============================================================ \n", + chanidx, divParams.E1aDivPhase[chanidx])); + } + else if (groupIdx >= 0) + { + divPhase[0] -= divParams.E1aDivPhase[groupIdx]; + divPhase[0] = (divPhase[0] + 0x40) & 0x80; + + DBGPRINT(RT_DEBUG_WARN, ( + " ============================================================ \n" + " group index = %d\n" + " Base Divider phase = 0x%x\n" + " Diff Divider phase = 0x%x\n" + " ============================================================ \n", + groupIdx, divParams.E1aDivPhase[groupIdx], divPhase[0])); + } + break; + + default: + result = FALSE; + break; + } + +exitDivCal: +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval1); + + DBGPRINT(RT_DEBUG_ERROR, ("%s t1=%ld\n", __FUNCTION__, + tval1.tv_usec - tval0.tv_usec)); +#endif + + return result; +} + +#endif + +#define MAX_LNA_CAPS 10 /* Maximum number of LNA captures per calibration */ + + + +#ifdef MT76x2 +INT ITxBFLNACalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN INT calMethod, + IN BOOLEAN gBand) +{ + + UINT *pCR_BK; + BOOLEAN cal_StatusFlg = FALSE; + + /* Allocate buffer for capture data */ + pCR_BK = kmalloc(67 * 4, MEM_ALLOC_FLAG); + if (pCR_BK == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return FALSE; + } + + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX17, &pCR_BK[0]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX38, &pCR_BK[1]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX39, &pCR_BK[2]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX42, &pCR_BK[3]); + mt_rf_read(pAd, RF_Path0, A_BAND_PA, &pCR_BK[4]); + mt_rf_read(pAd, RF_Path0, A_BAND_IQM_TSSI_DIV_LPF, &pCR_BK[5]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP4, &pCR_BK[6]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP0, &pCR_BK[7]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP1, &pCR_BK[8]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX0, &pCR_BK[9]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX4, &pCR_BK[10]); + mt_rf_read(pAd, RF_Path0, RFDIGI_ABB_TO_AFE5, &pCR_BK[11]); + mt_rf_read(pAd, RF_Path0, 0x034, &pCR_BK[12]); + mt_rf_read(pAd, RF_Path0, 0x044, &pCR_BK[13]); + mt_rf_read(pAd, RF_Path0, 0x04C, &pCR_BK[14]); + mt_rf_read(pAd, RF_Path0, 0x12C, &pCR_BK[15]); + //mt_rf_read(pAd, RF_Path0, 0x284, &pCR_BK[16]); + //mt_rf_read(pAd, RF_Path0, 0x288, &pCR_BK[17]); + //mt_rf_read(pAd, RF_Path0, 0x28C, &pCR_BK[18]); + //mt_rf_read(pAd, RF_Path0, 0x290, &pCR_BK[19]); + mt_rf_read(pAd, RF_Path0, 0x298, &pCR_BK[20]); + mt_rf_read(pAd, RF_Path0, 0x2A0, &pCR_BK[21]); + mt_rf_read(pAd, RF_Path0, 0x26C, &pCR_BK[22]); + mt_rf_read(pAd, RF_Path0, 0x270, &pCR_BK[23]); + mt_rf_read(pAd, RF_Path0, 0x274, &pCR_BK[24]); + mt_rf_read(pAd, RF_Path0, 0x2A4, &pCR_BK[25]); + mt_rf_read(pAd, RF_Path0, 0x03C, &pCR_BK[26]); + + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX17, &pCR_BK[27]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX38, &pCR_BK[28]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX39, &pCR_BK[29]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX42, &pCR_BK[30]); + mt_rf_read(pAd, RF_Path1, A_BAND_PA, &pCR_BK[31]); + mt_rf_read(pAd, RF_Path1, A_BAND_IQM_TSSI_DIV_LPF, &pCR_BK[32]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP4, &pCR_BK[33]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP0, &pCR_BK[34]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP1, &pCR_BK[35]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX0, &pCR_BK[36]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX4, &pCR_BK[37]); + mt_rf_read(pAd, RF_Path1, RFDIGI_ABB_TO_AFE5, &pCR_BK[38]); + mt_rf_read(pAd, RF_Path1, 0x034, &pCR_BK[39]); + mt_rf_read(pAd, RF_Path1, 0x044, &pCR_BK[40]); + mt_rf_read(pAd, RF_Path1, 0x04C, &pCR_BK[41]); + mt_rf_read(pAd, RF_Path1, 0x12C, &pCR_BK[42]); + //mt_rf_read(pAd, RF_Path1, 0x284, &pCR_BK[43]); + //mt_rf_read(pAd, RF_Path1, 0x288, &pCR_BK[44]); + //mt_rf_read(pAd, RF_Path1, 0x28C, &pCR_BK[45]); + //mt_rf_read(pAd, RF_Path1, 0x290, &pCR_BK[46]); + mt_rf_read(pAd, RF_Path1, 0x298, &pCR_BK[47]); + mt_rf_read(pAd, RF_Path1, 0x2A0, &pCR_BK[48]); + mt_rf_read(pAd, RF_Path1, 0x26C, &pCR_BK[49]); + mt_rf_read(pAd, RF_Path1, 0x270, &pCR_BK[50]); + mt_rf_read(pAd, RF_Path1, 0x274, &pCR_BK[51]); + mt_rf_read(pAd, RF_Path1, 0x2A4, &pCR_BK[52]); + mt_rf_read(pAd, RF_Path1, 0x03C, &pCR_BK[53]); + + RTMP_IO_READ32(pAd,CORE_R1, &pCR_BK[54]); + RTMP_IO_READ32(pAd,CORE_R4, &pCR_BK[55]); + RTMP_IO_READ32(pAd,CORE_R33, &pCR_BK[56]); + RTMP_IO_READ32(pAd,DACCLK_EN_DLY_CFG, &pCR_BK[57]); + RTMP_IO_READ32(pAd,TXBE_R1, &pCR_BK[58]); + RTMP_IO_READ32(pAd,TXBE_R5, &pCR_BK[59]); + RTMP_IO_READ32(pAd,TXBE_R6, &pCR_BK[60]); + RTMP_IO_READ32(pAd,AGC1_R0, &pCR_BK[61]); + RTMP_IO_READ32(pAd,CAL_R1, &pCR_BK[62]); + RTMP_IO_READ32(pAd,CAL_R2, &pCR_BK[63]); + RTMP_IO_READ32(pAd,CAL_R5, &pCR_BK[64]); + RTMP_IO_READ32(pAd,PWR_PIN_CFG, &pCR_BK[65]); + RTMP_IO_READ32(pAd,TXBE_R4, &pCR_BK[66]); + + // Do the LNA calibration + cal_StatusFlg = mt76x2_ITxBFLNACalibration(pAd, calFunction, calMethod, gBand); + + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX17, pCR_BK[0]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX38, pCR_BK[1]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX39, pCR_BK[2]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX42, pCR_BK[3]); + mt_rf_write(pAd, RF_Path0, A_BAND_PA, pCR_BK[4]); + mt_rf_write(pAd, RF_Path0, A_BAND_IQM_TSSI_DIV_LPF, pCR_BK[5]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP4, pCR_BK[6]); + //mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, pCR_BK[7]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP1, pCR_BK[8]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX0, pCR_BK[9]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, pCR_BK[10]); + mt_rf_write(pAd, RF_Path0, RFDIGI_ABB_TO_AFE5, pCR_BK[11]); + mt_rf_write(pAd, RF_Path0, 0x034, pCR_BK[12]); + mt_rf_write(pAd, RF_Path0, 0x044, pCR_BK[13]); + mt_rf_write(pAd, RF_Path0, 0x04C, pCR_BK[14]); + mt_rf_write(pAd, RF_Path0, 0x12C, pCR_BK[15]); + //mt_rf_write(pAd, RF_Path0, 0x284, pCR_BK[16]); + //mt_rf_write(pAd, RF_Path0, 0x288, pCR_BK[17]); + //mt_rf_write(pAd, RF_Path0, 0x28C, pCR_BK[18]); + //mt_rf_write(pAd, RF_Path0, 0x290, pCR_BK[19]); + mt_rf_write(pAd, RF_Path0, 0x298, pCR_BK[20]); + mt_rf_write(pAd, RF_Path0, 0x2A0, pCR_BK[21]); + mt_rf_write(pAd, RF_Path0, 0x26C, pCR_BK[22]); + mt_rf_write(pAd, RF_Path0, 0x270, pCR_BK[23]); + mt_rf_write(pAd, RF_Path0, 0x274, pCR_BK[24]); + mt_rf_write(pAd, RF_Path0, 0x2A4, pCR_BK[25]); + mt_rf_write(pAd, RF_Path0, 0x03C, pCR_BK[26]); + + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX17, pCR_BK[27]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX38, pCR_BK[28]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX39, pCR_BK[29]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX42, pCR_BK[30]); + mt_rf_write(pAd, RF_Path1, A_BAND_PA, pCR_BK[31]); + mt_rf_write(pAd, RF_Path1, A_BAND_IQM_TSSI_DIV_LPF, pCR_BK[32]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP4, pCR_BK[33]); + //mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, pCR_BK[34]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP1, pCR_BK[35]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX0, pCR_BK[36]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, pCR_BK[37]); + mt_rf_write(pAd, RF_Path1, RFDIGI_ABB_TO_AFE5, pCR_BK[38]); + mt_rf_write(pAd, RF_Path1, 0x034, pCR_BK[39]); + mt_rf_write(pAd, RF_Path1, 0x044, pCR_BK[40]); + mt_rf_write(pAd, RF_Path1, 0x04C, pCR_BK[41]); + mt_rf_write(pAd, RF_Path1, 0x12C, pCR_BK[42]); + //mt_rf_write(pAd, RF_Path1, 0x284, pCR_BK[43]); + //mt_rf_write(pAd, RF_Path1, 0x288, pCR_BK[44]); + //mt_rf_write(pAd, RF_Path1, 0x28C, pCR_BK[45]); + //mt_rf_write(pAd, RF_Path1, 0x290, pCR_BK[46]); + mt_rf_write(pAd, RF_Path1, 0x298, pCR_BK[47]); + mt_rf_write(pAd, RF_Path1, 0x2A0, pCR_BK[48]); + mt_rf_write(pAd, RF_Path1, 0x26C, pCR_BK[49]); + mt_rf_write(pAd, RF_Path1, 0x270, pCR_BK[50]); + mt_rf_write(pAd, RF_Path1, 0x274, pCR_BK[51]); + mt_rf_write(pAd, RF_Path1, 0x2A4, pCR_BK[52]); + mt_rf_write(pAd, RF_Path1, 0x03C, pCR_BK[53]); + RTMP_IO_WRITE32(pAd,CORE_R1, pCR_BK[54]); + RTMP_IO_WRITE32(pAd,CORE_R4, pCR_BK[55]); + RTMP_IO_WRITE32(pAd,CORE_R33, pCR_BK[56]); + RTMP_IO_WRITE32(pAd,DACCLK_EN_DLY_CFG, pCR_BK[57]); + RTMP_IO_WRITE32(pAd,TXBE_R1, pCR_BK[58]); + RTMP_IO_WRITE32(pAd,TXBE_R5, pCR_BK[59]); + RTMP_IO_WRITE32(pAd,TXBE_R6, pCR_BK[60]); + RTMP_IO_WRITE32(pAd,AGC1_R0, pCR_BK[61]); + RTMP_IO_WRITE32(pAd,CAL_R1, pCR_BK[62]); + RTMP_IO_WRITE32(pAd,CAL_R2, pCR_BK[63]); + RTMP_IO_WRITE32(pAd,CAL_R5, pCR_BK[64]); + RTMP_IO_WRITE32(pAd,PWR_PIN_CFG, pCR_BK[65]); + RTMP_IO_WRITE32(pAd,TXBE_R4, pCR_BK[66]); + + os_free_mem(NULL, pCR_BK); + + return cal_StatusFlg; +} + + +INT avgPhase32[3]; +UCHAR MidVGA[2]; + +INT mt76x2_ITxBFLNACalibration( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN INT calMethod, + IN BOOLEAN gBand) +{ + + UINT32 phaseCaliStatus, phaseCaliResult; + UCHAR AGCtimeOutCount, timeOutCount, agcGain; + INT mPhase0[2], mPhase1[2]; + INT mCalPhase0[2], mCalPhase1[2]; + INT avgIData, avgQData, peakIValue; + UINT32 value32; + UINT32 TRXSel_aband[2] = {0x01FECD28, 0x01FECD28}; + UINT32 RXGainSel[4] = {0x000B8888, 0x000A8888, 0x000A8888, 0x00098888}; + //UINT32 RXGainSel_aBand[4] = {0x000B8888, 0x000A8888, 0x000A8888, 0x00098888}; + UINT32 agcGainSet; + + UINT32 TRSW[2] = {0xF004013B, 0xF004012A}; + UINT32 TRSW_aband[2] = {0x0004012F, 0x0004012A}; + UINT32 TxgGainSel[2] = {0x00010130, 0x00010100}; + UINT32 TXA_TXOpSel[2]= {0x015ACA00, 0x297A3A00}; + UINT32 TXA_PaSel[2] = {0x657C0000, 0x32746000}; + UINT32 TRX_27Sel[2] = {0x00507777, 0x00507757}; + UINT32 TRX_38Sel[2] = {0x02E0A0A4, 0x03030300}; + UINT32 TRX_39Sel[2] = {0x3F10100E, 0x2E1F1F10}; + UINT32 TRX_40Sel[2] = {0x00000000, 0xDC1A0014}; + UINT32 TRX_41Sel[2] = {0x00000700, 0x2020477F}; + UINT32 TRX_42Sel[2] = {0x000002A8, 0x016E1D28}; + UCHAR i, ii; + UCHAR pathIdx[2] = {0, 1}; + UCHAR TRLoopSel[2] = {0x00, 0x05}; + USHORT ADCSel[2] = {0x7400, 0x7401}, DACSel[2] = {0x80, 0x81}; + INT DiffPhase32[3]; + + UCHAR channel = pAd->CommonCfg.Channel; + + ITXBF_LNA_PARAMS lnaParams; + int result = TRUE; + +#ifdef TIMESTAMP_CAL_CAPTURE1 + struct timeval tval0, tval1; +#endif + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval0); +#endif + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + for (i = 0; i < 2; i++) // HM, ML + { + for (ii = 0; ii < 2; ii++) // Path0 and path1 + { + if (gBand) + { + //********* HG LNA Phase cal ********* + mt_rf_write(pAd, pathIdx[ii], 0x0244, 0x00010100); //Set txg gain table = to manual mode + mt_rf_write(pAd, pathIdx[ii], 0x0044, 0x02512016); //TRSWITCH + + if (i == 0) + { + mt_rf_write(pAd, pathIdx[ii], 0x0034, 0x00776058); + mt_rf_write(pAd, pathIdx[ii], 0x004C, 0x6F090293); + mt_rf_write(pAd, pathIdx[ii], 0x012C, 0x08100038); + } + + //********* external llopback ********* + mt_rf_write(pAd, pathIdx[ii], 0x0010, 0x31C70006); // Force Divider ON + mt_rf_write(pAd, pathIdx[ii], 0x0114, 0x00C211F1); // RSV LBpath to RX + mt_rf_write(pAd, pathIdx[ii], 0x0000, 0x80056F53); // enable SX/TX/PA/RX for WF0, force chipmode in RX mode + mt_rf_write(pAd, pathIdx[ii], 0x0004, TRSW[i]); // set TRSW in TX mode for WF0 + } + else + { + //********* HG LNA Phase cal ********* + mt_rf_write(pAd, pathIdx[ii], 0x0244, TxgGainSel[i]); //Set txg gain table = to manual mode + + //********* external llopback ********* + mt_rf_write(pAd, pathIdx[ii], 0x000C, 0x31C73047); // Force Divider ON + mt_rf_write(pAd, pathIdx[ii], 0x0000, 0x80056F37); // enable SX/TX/PA/RX for WF1, force chipmode in RX mode + mt_rf_write(pAd, pathIdx[ii], 0x0004, TRSW_aband[i]); // set TRSW in TX mode for WF1 + } + + //********* external PA Setting******** + if (gBand) + { + mt_rf_write(pAd, pathIdx[ii], 0x0054, TXA_TXOpSel[i]); + mt_rf_write(pAd, pathIdx[ii], 0x0058, TXA_PaSel[i]); + } + else + { + mt_rf_write(pAd, pathIdx[ii], 0x0054, 0x297A3A00); + mt_rf_write(pAd, pathIdx[ii], 0x0058, 0x012C6000); + } + + mt_rf_write(pAd, pathIdx[ii], 0x0298, 0x03030300); + + if (gBand) + { + mt_rf_write(pAd, pathIdx[ii], 0x029C, TRX_39Sel[i]); + } + else + { + mt_rf_write(pAd, pathIdx[ii], 0x027C, 0x00250027); + mt_rf_write(pAd, pathIdx[ii], 0x0280, 0x00670024); + mt_rf_write(pAd, pathIdx[ii], 0x0284, 0x00640065); + mt_rf_write(pAd, pathIdx[ii], 0x0288, 0x00E500E7); + mt_rf_write(pAd, pathIdx[ii], 0x028C, 0x03E700E4); + mt_rf_write(pAd, pathIdx[ii], 0x0290, 0x03E403E5); + mt_rf_write(pAd, pathIdx[ii], 0x0294, 0x03E103E3); + mt_rf_write(pAd, pathIdx[ii], 0x029C, 0x2E1F1F10); + } + + RTMP_IO_WRITE32(pAd, 0x2704, 0x00000000); + + if (gBand) + { + mt_rf_write(pAd, pathIdx[ii], 0x02A0, TRX_40Sel[i]); + mt_rf_write(pAd, pathIdx[ii], 0x02A8, TRX_42Sel[i]); + mt_rf_write(pAd, pathIdx[ii], 0x026c, TRX_27Sel[i]); // Gband Table + mt_rf_write(pAd, pathIdx[ii], 0x0270, 0x0C0D0F04); // Gband Table + mt_rf_write(pAd, pathIdx[ii], 0x0274, 0x13141517); // Gband Table + mt_rf_write(pAd, pathIdx[ii], 0x0298, TRX_38Sel[i]); + mt_rf_write(pAd, pathIdx[ii], 0x02A4, TRX_41Sel[i]); + mt_rf_write(pAd, pathIdx[ii], 0x003C, 0x05B559C5); // set TXG gain for ePA + } + else + { + mt_rf_write(pAd, pathIdx[ii], 0x02A8, TRXSel_aband[i]); + } + + AGCtimeOutCount = 0; + agcGain = RXGainSel[2*i] & 0x3F; + + while (AGCtimeOutCount < 20) // SW AGC update to make sure I peak value can prevent peak value from satuation or too low + { + //********* cal setting ******** + RTMP_IO_WRITE32(pAd, 0x2004, 0x00000000); // BW=20MHz ADC=40MHz + mt_rf_write(pAd, pathIdx[ii], 0x0200, 0x0500010F); // start rxiq dcoc + RTMP_IO_WRITE32(pAd, 0x1264, 0x80008000); // DAC Clock on + RTMP_IO_WRITE32(pAd, 0x1204, 0x00000000); // [3] to turn off "adda power down" + RTMP_IO_WRITE32(pAd, 0x2084, 0x00021E00); // RF/BBP clk control + RTMP_IO_WRITE32(pAd, 0x2010, 0x00000001); // core soft reset enable + RTMP_IO_WRITE32(pAd, 0x2010, 0x00000000); // core soft reset disable + RTMP_IO_WRITE32(pAd, 0x2704, 0x00000000); // Tx power control + + agcGainSet = (RXGainSel[2*i] & 0xF8080)|(agcGain << 8)| agcGain ; + + //********* HG LNA Phase cal ********* + mt_rf_write(pAd, pathIdx[ii], 0x0210, agcGainSet); // Use 2cf4 force RXGAIN, HG(B)/MG(A)/8484 LG(9)/8585 + + //********* start iBF cal + mt_rf_write(pAd, pathIdx[ii], 0x0114, 0x00C211F1); // connecting TxLPF out and RxLPF in, and closing the TIA + RTMP_IO_WRITE32(pAd, 0x2300, ADCSel[ii]); // 01:1R ADC1, 00 : 1R ADC0 + RTMP_IO_WRITE32(pAd, 0x2710, 0x00000008); // a default setting, 2T + RTMP_IO_WRITE32(pAd, 0x2c08, TRLoopSel[ii]); // TR loop setting(0:T0R0,1:T1R0,5:T1R1,4:T0R1) + RTMP_IO_WRITE32(pAd, 0x2714, DACSel[ii]); // 1 : DAC1, 0 : DAC0 + RTMP_IO_WRITE32(pAd, 0x2718, 0xC0002101); // Test format contol : Tx single tone setting + + RtmpOsMsDelay(10); // waiting 10ms + + RTMP_IO_WRITE32(pAd, 0x2c14, 0x0000040c); // set accumulation length + + // Enable LNA phase calibration and polling if HW is ready to read phase result + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000086); + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + timeOutCount = 0; + while (phaseCaliStatus & 0x80) + { + if (timeOutCount == 3) + { + DBGPRINT(RT_DEBUG_WARN, ( + "LNA HW calibration can't finish process\n" + "phaseCaliStatus = %x\n", phaseCaliStatus)); + break; + } + + timeOutCount++; + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + } + + // 0x2C2C + // Bit 23:16 Correlator Phase + // Bit 15:8 Correlator Q value + // Bit 7:0 Correlator I value + RTMP_IO_READ32(pAd,CAL_R11, &phaseCaliResult); + mPhase0[ii] = (INT)((INT)((phaseCaliResult << 8) & 0xFF000000) >> 24); + avgQData = (INT)((INT)((phaseCaliResult << 16) & 0xFF000000) >> 24); + avgIData = (INT)((INT)((phaseCaliResult << 24) & 0xFF000000) >> 24); + mCalPhase0[ii] = iAtan2(avgQData, avgIData); + peakIValue = phaseCaliResult >> 24; + + DBGPRINT(RT_DEBUG_TRACE, ( + " ==========================LNACAL= Loop%d, Path%d, agcCnt %d,agcGain=%d,High ======================== \n" + " agcGainSet = %x\n" + " CAL_R11=0x%x\n" + " Peak I value=0x%x\n" + " I value=0x%x, Q value=0x%x\n" + " mPhase0 = 0x%x\n" + " ============================================================ \n", + i, ii,AGCtimeOutCount,agcGain, + agcGainSet, + phaseCaliResult, + peakIValue, + avgIData, avgQData, + mPhase0[ii])); + + //SW AGC gain control + if ((agcGain < 62) && (AGCtimeOutCount < 19)) // BP_AGC gain 0~63 + { + // Calculate AGC ad check if AGC update is enough or not + if (peakIValue >= 0x40 && agcGain > 0) + agcGain --; + else if (peakIValue >= 0x30) + { + AGCtimeOutCount = 20; + break; + } + else + agcGain++; + } + DBGPRINT(RT_DEBUG_TRACE,("LNA SW AGC = %d\n", agcGain)); + AGCtimeOutCount++; + } + + //********* BBP Soft Reset ********* + RTMP_IO_WRITE32(pAd, 0x2718, 0x40002101); //Test format contol : Tx single tone setting + RTMP_IO_WRITE32(pAd, 0x2010, 0x00000001); // core soft reset enable + RTMP_IO_WRITE32(pAd, 0x2010, 0x00000000); // core soft reset disable + + //********* MG LNA Phase cal ********* + agcGainSet = (RXGainSel[2*i + 1] & 0xF8080)|(agcGain << 8)| agcGain ; + if (gBand) + { + mt_rf_write(pAd, pathIdx[ii], 0x0004, TRSW[i]); // set TRSW in TX mode for WF0 + mt_rf_write(pAd, pathIdx[ii], 0x0210, agcGainSet); // Use 2cf4 force RXGAIN, HG(B)/MG(A)/8484 LG(9)/8585 + //mt_rf_write(pAd, pathIdx[ii], 0x0210, RXGainSel[2*i + 1]); // Use 2cf4 force RXGAIN, HG(B)/MG(A)/8484 LG(9)/8585 + //mt_rf_write(pAd, pathIdx[ii], 0x0210, RXGainSel[2*i + 1]); // Use 2cf4 force RXGAIN, HG(B)/MG(A)/8484 LG(9)/8585 + } + else + { + mt_rf_write(pAd, pathIdx[ii], 0x0004, TRSW_aband[i]); // set TRSW in TX mode for WF0 + mt_rf_write(pAd, pathIdx[ii], 0x0210, agcGainSet); // Use 2cf4 force RXGAIN, HG(B)/MG(A)/8484 LG(9)/8585 + //mt_rf_write(pAd, pathIdx[ii], 0x0210, RXGainSel_aBand[2*i + 1]); // Use 2cf4 force RXGAIN, HG(B)/MG(A)/8484 LG(9)/8585 + } + + //********* start iBF cal ********* + mt_rf_write(pAd, pathIdx[ii], 0x0114, 0x00C211F1); // connecting TxLPF out and RxLPF in, and closing the TIA + RTMP_IO_WRITE32(pAd, 0x2300, ADCSel[ii]); // 01:1R ADC1, 00 : 1R ADC0 + RTMP_IO_WRITE32(pAd, 0x2710, 0x00000008); // a default setting, 2T + RTMP_IO_WRITE32(pAd, 0x2c08, TRLoopSel[ii]); // TR loop setting(0:T0R0,1:T1R0,5:T1R1,4:T0R1) + RTMP_IO_WRITE32(pAd, 0x2714, DACSel[ii]); // 1 : DAC1, 0 : DAC0 + RTMP_IO_WRITE32(pAd, 0x2718, 0xC0002101); // Test format contol : Tx single tone setting + RTMP_IO_WRITE32(pAd, 0x2c14, 0x0000040c); // set accumulation length + + // Enable LNA phase calibration and polling if HW is ready to read phase result + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000086); + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + timeOutCount = 0; + while (phaseCaliStatus & 0x80) + { + if (timeOutCount == 3) + { + DBGPRINT(RT_DEBUG_WARN, ( + "LNA HW calibration can't finish process\n" + "phaseCaliStatus = %x\n", phaseCaliStatus)); + break; + } + + timeOutCount++; + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + } + + // 0x2C2C + // Bit 23:16 Correlator Phase + // Bit 15:8 Correlator Q value + // Bit 7:0 Correlator I value + RTMP_IO_READ32(pAd,CAL_R11, &phaseCaliResult); + mPhase1[ii] = (INT)((INT)((phaseCaliResult << 8) & 0xFF000000) >> 24); + avgQData = (INT)((INT)((phaseCaliResult << 16) & 0xFF000000) >> 24); + avgIData = (INT)((INT)((phaseCaliResult << 24) & 0xFF000000) >> 24); + mCalPhase1[ii] = iAtan2(avgQData, avgIData); + peakIValue = phaseCaliResult >> 24; + + DBGPRINT(RT_DEBUG_TRACE, ( + " ========================LNACAL= Loop%d, Path%d, Low ======================== \n" + " agcGainSet = %x\n" + " CAL_R11=0x%x\n" + " Peak I value=0x%x\n" + " I value=0x%x, Q value=0x%x\n" + " mPhase1 = 0x%x\n" + " ============================================================ \n", + i, ii, + agcGainSet, + phaseCaliResult, + peakIValue, + avgIData, avgQData, + mPhase1[ii])); + + if (gBand) + { + if (ii != 0) + { + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F53); // WF1 manul mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x00056F50); // WF1 manul mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP0, 0x80056F50); // WF1 manul mode + } + else + { + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056F53); // WF0 manul mode + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x00056F50); // WF0 manul mode + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP0, 0x80056F50); // WF0 manul mode + } + } + } + + DiffPhase32[i] = ((INT)(((INT)((mPhase0[0]-mPhase1[0]) << 24)) >> 24) + + (INT)(((INT)((mPhase0[1]-mPhase1[1]) << 24)) >> 24)) >> 1; + + DBGPRINT(RT_DEBUG_OFF, ( + " ============================ Loop%d ======================== \n" + " ((mPhase0[0]-mPhase1[0])+(mPhase0[1]-mPhase1[1])) >> 1\n" + " ((0x%x - 0x%x) + (0x%x - 0x%x)) >> 1 = 0x%x\n" + " ============================================================ \n", + i, + mPhase0[0], mPhase1[0], + mPhase0[1], mPhase1[1], + DiffPhase32[i])); + + } + + avgPhase32[0] = DiffPhase32[0]; + avgPhase32[1] = DiffPhase32[1]; + avgPhase32[2] = DiffPhase32[1]; + + DBGPRINT(RT_DEBUG_TRACE, ( + "Channel%d LNA average phase (deg)\n" + "Ant0\n" + " PHM :%d Avg PHM :%d\n" + " PML :%d Avg PML :%d\n" + " PLUL :%d Avg PLUL :%d\n", + channel, + (360*DiffPhase32[0])>>8,(360*avgPhase32[0])>>8, + (360*DiffPhase32[1])>>8,(360*avgPhase32[1])>>8, + (360*DiffPhase32[1])>>8,(360*avgPhase32[1])>>8)); + + /* Either display parameters, update EEPROM and BBP registers or dump capture data */ + switch (calFunction) { + case 0: + break; + + case 1: + /* Save new reference values in EEPROM and BBP */ + ITxBFGetEEPROM(pAd, 0, &lnaParams, 0, 0); + + /* Only allow calibration on specific channels */ + if (channel == 1) { + lnaParams.E1gBeg[0] = avgPhase32[0]; // H-M + lnaParams.E1gBeg[1] = avgPhase32[1]; // M-L + lnaParams.E1gBeg[2] = avgPhase32[2]; // L-uL = M-L + } + else if (channel == 14) { + lnaParams.E1gEnd[0] = avgPhase32[0]; + lnaParams.E1gEnd[1] = avgPhase32[1]; + lnaParams.E1gEnd[2] = avgPhase32[2]; + } + else if (channel == 36) { + lnaParams.E1aLowBeg[0] = avgPhase32[0]; + lnaParams.E1aLowBeg[1] = avgPhase32[1]; + lnaParams.E1aLowBeg[2] = avgPhase32[2]; + } + else if (channel == 64) { + lnaParams.E1aLowEnd[0] = avgPhase32[0]; + lnaParams.E1aLowEnd[1] = avgPhase32[1]; + lnaParams.E1aLowEnd[2] = avgPhase32[2]; + } + else if (channel == 100) { + lnaParams.E1aMidBeg[0] = avgPhase32[0]; + lnaParams.E1aMidBeg[1] = avgPhase32[1]; + lnaParams.E1aMidBeg[2] = avgPhase32[2]; + } + else if (channel == 120) { + lnaParams.E1aMidMid[0] = avgPhase32[0]; + lnaParams.E1aMidMid[1] = avgPhase32[1]; + lnaParams.E1aMidMid[2] = avgPhase32[2]; + } + else if (channel == 140) { + lnaParams.E1aMidEnd[0] = avgPhase32[0]; + lnaParams.E1aMidEnd[1] = avgPhase32[1]; + lnaParams.E1aMidEnd[2] = avgPhase32[2]; + } + else if (channel == 149) { + lnaParams.E1aHighBeg[0] = avgPhase32[0]; + lnaParams.E1aHighBeg[1] = avgPhase32[1]; + lnaParams.E1aHighBeg[2] = avgPhase32[2]; + } + else if (channel == 173) { + lnaParams.E1aHighEnd[0] = avgPhase32[0]; + lnaParams.E1aHighEnd[1] = avgPhase32[1]; + lnaParams.E1aHighEnd[2] = avgPhase32[2]; + } + else { + DBGPRINT(RT_DEBUG_OFF, + ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 64, 100, 120, 140 ,149 or 173", channel) ); + result = FALSE; + goto exitLnaCal; + } + + ITxBFSetEEPROM(pAd, 0, &lnaParams, 0, 0); + /* FALL THROUGH to update BBP */ + + break; + + case 2: + /* Update LNA phase difference into RXFE_R3 registers */ + RTMP_IO_READ32(pAd, CAL_R0, &value32); + for (i=0; i<2; i++) + { + RTMP_IO_WRITE32(pAd, CAL_R0, value32 | (i<<5)); + RTMP_IO_WRITE32(pAd, RXFE_R3, avgPhase32[i]); + } + + break; + + default: + result = FALSE; + break; + } + +exitLnaCal: + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval1); +#endif + + return result; +} + + +INT ITxBFPhaseCalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN BOOLEAN loOffsetCkFlg, + IN USHORT ch) +{ + UINT32 CR_BK[35]; + + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX17, &CR_BK[0]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX38, &CR_BK[1]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX39, &CR_BK[2]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX42, &CR_BK[3]); + mt_rf_read(pAd, RF_Path0, A_BAND_PA, &CR_BK[4]); + mt_rf_read(pAd, RF_Path0, A_BAND_IQM_TSSI_DIV_LPF, &CR_BK[5]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX0, &CR_BK[6]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TRX4, &CR_BK[7]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP0, &CR_BK[8]); + mt_rf_read(pAd, RF_Path0, RFDIGI_TOP1, &CR_BK[9]); + mt_rf_read(pAd, RF_Path0, RG_WF0_RXG_TOP, &CR_BK[10]); + + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX17, &CR_BK[11]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX38, &CR_BK[12]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX39, &CR_BK[13]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX42, &CR_BK[14]); + mt_rf_read(pAd, RF_Path1, A_BAND_PA, &CR_BK[15]); + mt_rf_read(pAd, RF_Path1, A_BAND_IQM_TSSI_DIV_LPF, &CR_BK[16]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX0, &CR_BK[17]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TRX4, &CR_BK[18]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP0, &CR_BK[19]); + mt_rf_read(pAd, RF_Path1, RFDIGI_TOP1, &CR_BK[20]); + mt_rf_read(pAd, RF_Path1, RG_WF0_RXG_TOP, &CR_BK[21]); + + RTMP_IO_READ32(pAd, CORE_R1, &CR_BK[22]); + RTMP_IO_READ32(pAd, DACCLK_EN_DLY_CFG, &CR_BK[23]); + RTMP_IO_READ32(pAd, PWR_PIN_CFG, &CR_BK[24]); + RTMP_IO_READ32(pAd, CORE_R33, &CR_BK[25]); + RTMP_IO_READ32(pAd, AGC1_R0, &CR_BK[26]); + RTMP_IO_READ32(pAd, TXBE_R4, &CR_BK[27]); + RTMP_IO_READ32(pAd, CORE_R4, &CR_BK[28]); + RTMP_IO_READ32(pAd, TXBE_R1, &CR_BK[29]); + RTMP_IO_READ32(pAd, CAL_R2, &CR_BK[30]); + RTMP_IO_READ32(pAd, TXBE_R5, &CR_BK[31]); + RTMP_IO_READ32(pAd, TXBE_R6, &CR_BK[32]); + RTMP_IO_READ32(pAd, CAL_R5, &CR_BK[33]); + RTMP_IO_READ32(pAd, CAL_R1, &CR_BK[34]); + + // Do the residual phase calibration + mt76x2_ITxBFPhaseCalibration(pAd, calFunction, loOffsetCkFlg, ch); + + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX17, CR_BK[0]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX38, CR_BK[1]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX39, CR_BK[2]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX42, CR_BK[3]); + mt_rf_write(pAd, RF_Path0, A_BAND_PA, CR_BK[4]); + mt_rf_write(pAd, RF_Path0, A_BAND_IQM_TSSI_DIV_LPF, CR_BK[5]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX0, CR_BK[6]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, CR_BK[7]); + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP1, CR_BK[9]); + mt_rf_write(pAd, RF_Path0, RG_WF0_RXG_TOP,CR_BK[10]); + + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX17, CR_BK[11]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX38, CR_BK[12]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX39, CR_BK[13]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX42, CR_BK[14]); + mt_rf_write(pAd, RF_Path1, A_BAND_PA, CR_BK[15]); + mt_rf_write(pAd, RF_Path1, A_BAND_IQM_TSSI_DIV_LPF, CR_BK[16]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX0, CR_BK[17]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, CR_BK[18]); + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP1, CR_BK[20]); + mt_rf_write(pAd, RF_Path1, RG_WF0_RXG_TOP,CR_BK[21]); + + RTMP_IO_WRITE32(pAd, CORE_R1, CR_BK[22]); + RTMP_IO_WRITE32(pAd, DACCLK_EN_DLY_CFG, CR_BK[23]); + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, CR_BK[24]); + RTMP_IO_WRITE32(pAd, CORE_R33, CR_BK[25]); + RTMP_IO_WRITE32(pAd, AGC1_R0, CR_BK[26]); + RTMP_IO_WRITE32(pAd, TXBE_R4, CR_BK[27]); + RTMP_IO_WRITE32(pAd, CORE_R4, CR_BK[28]); + RTMP_IO_WRITE32(pAd, TXBE_R1, CR_BK[29]); + RTMP_IO_WRITE32(pAd, CAL_R2, CR_BK[30]); + RTMP_IO_WRITE32(pAd, TXBE_R5, CR_BK[31]); + RTMP_IO_WRITE32(pAd, TXBE_R6, CR_BK[32]); + RTMP_IO_WRITE32(pAd, CAL_R5, CR_BK[33]); + RTMP_IO_WRITE32(pAd, CAL_R1, CR_BK[34]); + + return TRUE; +} + + +INT mt76x2_ITxBFPhaseCalibration( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN BOOLEAN loOffsetCkFlg, + IN USHORT ch) +{ + ITXBF_PHASE_PARAMS phaseParams; + UINT32 phaseCaliStatus, phaseCaliResult; + UINT32 value32[2]; + UCHAR timeOutCount; + INT mPhase[2]; + INT mCalPhase0; + LONG avgIData, avgQData; + UCHAR i; + UCHAR divPhase[2] = {0}; + INT phaseValues[2] = {0}; + BOOLEAN gBandFlg = FALSE; + CHAR rf_Path[2] = {RF_Path0, RF_Path1}; + CHAR rf_RevPath[2] = {RF_Path1, RF_Path0}; + CHAR trLoopSetting[2] = {4, 1}; + CHAR A_D_Sel[2] = {0x80, 0x81}; + CHAR LoPhase; + +#ifdef RALINK_ATE + ch = pAd->ate.Channel; +#endif + + if (ch <= 14) gBandFlg = TRUE; + + /* DPD and TSSI HW off */ + RTMP_IO_READ32(pAd,TXBE_R8, &value32[0]); + value32[0] &= ~0x08000; + RTMP_IO_WRITE32(pAd,TXBE_R8, value32[0]); // DPD off + + RTMP_IO_READ32(pAd,CORE_R34, &value32[0]); + value32[0] &= ~0x60; + value32[0] |= 0x40; + RTMP_IO_WRITE32(pAd,CORE_R34, value32[0]); // TSSI off + + mt_rf_write(pAd, RF_Path0, RFDIGI_TOP4, 0x30D71047); // tx block mode + mt_rf_write(pAd, RF_Path1, RFDIGI_TOP4, 0x30D71047); // tx block mode + + + + for (i = 0; i < 2; i++) // Tx1Rx0, Tx0RX1 + { + if (gBandFlg) + { + // ********* RXA IQ Cal Setting T0R1 ********* + RTMP_IO_WRITE32(pAd, TXBE_R8, 0x4100000A); // dpd off + RTMP_IO_WRITE32(pAd, CORE_R34, 0x0008AC40); // TSSI off + mt_rf_write(pAd, rf_Path[i], RFDIGI_TRX17, 0x00010170); // Set txg gain table = to manual mode + mt_rf_write(pAd, rf_Path[i], RG_WF0_RXG_TOP, 0x00492016); // TRSWITCH + + // ********* external llopback ********* + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP3, 0x11C73047); // Force Divider ON + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP3, 0x11C73047); // Force Divider ON + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x80056733); // enable SX/RX/for WF0, + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP1, 0xF0040122); // set TRSW in TX mode for WF0 + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x80056F23); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP1, 0xF0040123); // set TRSW in TX mode for WF1 + } + else + { + // ********* external llopback ********* + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX17, 0x000101C0); // Set txg gain table = to manual mode + + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP3, 0x11C73047); // Force Divider ON + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP3, 0x11C73047); // Force Divider ON + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x80056737); // enable SX/RX/for WF0, + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP1, 0xF0040122); // set TRSW in TX mode for WF0 + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x80056F27); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP1, 0xF0040123); // set TRSW in TX mode for WF1 + } + + // ********* cal setting ******** + // DCOC for RXA IQ Cal + RTMP_IO_WRITE32(pAd,CORE_R1, 0x00000000); // BW=20MHz ADC=40MHz + + // ********* pre dcoc ******** + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, 0x00000008); + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX0, 0x0500010F); // start rxiq dcoc keter + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_WRITE32(pAd, RF_BSI_CKDIV, 0x00000002); + RTMP_IO_WRITE32(pAd, DACCLK_EN_DLY_CFG, 0x80008000); //DAC Clock on + + // ********* send single tone ****** + RTMP_IO_WRITE32(pAd,PWR_PIN_CFG, 0x00000000); //[3] to turn off "adda power down" + RTMP_IO_WRITE32(pAd,CORE_R33, 0x00021E00); //RF/BBP clk control + RTMP_IO_WRITE32(pAd,TXBE_R6, 0x40002101); // Test format contol : Tx single tone setting + RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000001); // core soft reset enable + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_WRITE32(pAd,CORE_R4, 0x00000000); // core soft reset disable + RTMP_IO_WRITE32(pAd,TXBE_R1, 0x00000606); // Tx power control + + // ********* LNA VGA setting : MG + //mt_rf_write(pAd, RF_Path0, RFDIGI_TRX4, ((1<<19)|(2<<16)|(1<<15)|(MidVGA[0]<<8)|(1<<7)|MidVGA[0])); + //mt_rf_write(pAd, RF_Path1, RFDIGI_TRX4, ((1<<19)|(2<<16)|(1<<15)|(MidVGA[1]<<8)|(1<<7)|MidVGA[1])); + if (gBandFlg) + { + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX4, ((1<<19)|(2<<16)|(1<<15)|(4<<8)|(1<<7)|4)); + } + else + { + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX4, ((1<<19)|(2<<16)|(1<<15)|(4<<8)|(1<<7)|4)); + } + + // ********* start iBF cal + RTMP_IO_WRITE32(pAd, AGC1_R0, 0x7408); // a default setting, 2R + RTMP_IO_WRITE32(pAd, TXBE_R4, 0x0008); // a default setting, 2T + RTMP_IO_WRITE32(pAd, CAL_R2, trLoopSetting[i]); // TR loop setting(0:T0R0,1:T1R0,5:T1R1,4:T0R1) + RTMP_IO_WRITE32(pAd, TXBE_R5, A_D_Sel[i]); // 1 : DAC1, 0 : DAC0 + RTMP_IO_WRITE32(pAd, TXBE_R6, 0xC0002101); // Test format contol : Tx single tone setting + + RtmpOsMsDelay(1); // waiting 1ms + + if (gBandFlg) + { + RTMP_IO_WRITE32(pAd,CAL_R5, 0x0000040c); // set accumulation length + } + else + { + RTMP_IO_WRITE32(pAd,CAL_R5, 0x00001c0c); // set accumulation length + } + + // Enable phase calibration + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000086); + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + timeOutCount = 0; + while (phaseCaliStatus & 0x80) + { + if (timeOutCount == 3) + { + DBGPRINT(RT_DEBUG_TRACE, ( + "Residual Phase1 HW calibration doesn't finish\n" + "phaseCaliStatus = %x\n", + phaseCaliStatus)); + + break; + } + + timeOutCount++; + + RtmpOsMsDelay(1); // waiting 1ms + + RTMP_IO_READ32(pAd,CAL_R1, &phaseCaliStatus); + } + + // 0x2C2C + // Bit 23:16 Correlator Phase + // Bit 15:8 Correlator Q value + // Bit 7:0 Correlator I value + RTMP_IO_READ32(pAd,CAL_R11, &phaseCaliResult); + mPhase[i] = (INT)((INT)((phaseCaliResult << 8) & 0xFF000000) >> 24); + avgQData = (INT)((INT)((phaseCaliResult << 16) & 0xFF000000) >> 24); + avgIData = (INT)((INT)((phaseCaliResult << 24) & 0xFF000000) >> 24); + mCalPhase0 = iAtan2(avgQData, avgIData); + + DBGPRINT(RT_DEBUG_TRACE, ( + "===============================Path%d==============================\n" + "Tx phase cal : CAL_R11=0x%x\n" + "Phase=0x%x\n" + "Peak I value=0x%x\n" + "I value=0x%lx, Q value=0x%lx\n" + "MidVGA[0] = 0x%x\n", + rf_Path[i], + phaseCaliResult, + //(360*mPhase[i])>>8, + mPhase[i], + phaseCaliResult >> 24, + avgIData, avgQData, + MidVGA[0])); + + RTMP_IO_WRITE32(pAd,CAL_R1, 0x00000006); // Disable Calibration + + if (gBandFlg) + { + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TRX17, 0x00000000); + //mt_rf_write(pAd, rf_Path[i], RG_WF0_RXG_TOP, 0x02512016); + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP3, 0x11C73047); + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP3, 0x11C73047); + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP1, 0x00040120); + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x00056733); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x00056730); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x80056730); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x00056F23); // enable SX/RX/for WF0, + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x00056F20); // enable SX/RX/for WF0, + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x80056F20); // enable SX/RX/for WF0, + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP1, 0x00040120); + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX0, 0x0508000F); + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX4, 0x00000C0C); + } + else + { + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TRX17, 0x00000000); + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP3, 0x11C73047); + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP3, 0x11C73047); + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x00056737); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x00056734); // enable SX/RX/for WF1 + mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP0, 0x80056734); // enable SX/RX/for WF1 + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TOP1, 0x00040120); + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x00056F27); // enable SX/RX/for WF0, + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x00056F24); // enable SX/RX/for WF0, + mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP0, 0x80056F24); // enable SX/RX/for WF0, + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TOP1, 0x00040120); + //mt_rf_write(pAd, rf_Path[i], RFDIGI_TRX0, 0x0508000F); + //mt_rf_write(pAd, rf_RevPath[i], RFDIGI_TRX4, 0x00000C0C); + } + } + + phaseValues[0] = mPhase[0] - mPhase[1]; + + DBGPRINT(RT_DEBUG_TRACE, ("Tx phase : 0x%x\n", phaseValues[0])); + + /* Either display parameters, update EEPROM and BBP registers or dump capture data */ + switch (calFunction) { + case 0: + /* Remove Divider phase */ + ITxBFDividerCalibrationStartUp(pAd, 0, 0, divPhase); + //phaseValues[0] -= divPhase[0]; + + DBGPRINT(RT_DEBUG_TRACE, ( + "Divider phase : 0x%x\n" + "Before Residual phase : 0x%x\n", divPhase[0], phaseValues[0])); + + if (gBandFlg == TRUE) + { + ITxBFLoPhaseCalibrationStartUp(pAd, loOffsetCkFlg, &LoPhase); + printk("Before LoPhase = 0x%x\n", LoPhase); + LoPhase = ABS_One(LoPhase); + + if (LoPhase > 0x20 && LoPhase < 0x60) + { + phaseValues[0] = phaseValues[0] + 0x80; + } + + printk("After LoPhase = 0x%x\n", LoPhase); + } + + DBGPRINT(RT_DEBUG_TRACE, ( + "After Residual phase : 0x%x\n", phaseValues[0])); + + break; + + case 1: + RTMP_IO_WRITE32(pAd, CAL_R0, 0); + RTMP_IO_WRITE32(pAd, TXBE_R13, phaseValues[0]); // for method1 + + DBGPRINT(RT_DEBUG_TRACE, ("Tx phase : 0x%x\n", phaseValues[0])); + + /* Remove Divider phase */ + ITxBFDividerCalibrationStartUp(pAd, 0, 0, divPhase); + phaseValues[0] -= divPhase[0]; + + DBGPRINT(RT_DEBUG_TRACE, ( + "Divider phase : 0x%x\n" + "Residual phase : 0x%x\n", divPhase[0], phaseValues[0])); + + if (gBandFlg == TRUE) + { + ITxBFLoPhaseCalibrationStartUp(pAd, loOffsetCkFlg, &LoPhase); + } + + /* Save new reference values in EEPROM and BBP */ + ITxBFGetEEPROM(pAd, &phaseParams, 0, 0, 0); + + /* Only allow calibration on specific channels */ + if (ch == 1) + phaseParams.E1gBeg = phaseValues[0]; + else if (ch == 14) + phaseParams.E1gEnd = phaseValues[0]; + else if (ch == 36) + phaseParams.E1aLowBeg = phaseValues[0]; + else if (ch == 64) + phaseParams.E1aLowEnd = phaseValues[0]; + else if (ch == 100) + phaseParams.E1aMidBeg = phaseValues[0]; + else if (ch == 120) + phaseParams.E1aMidMid = phaseValues[0]; + else if (ch == 140) + phaseParams.E1aMidEnd = phaseValues[0]; + else if (ch == 149) + phaseParams.E1aHighBeg = phaseValues[0]; + else if (ch == 173) + phaseParams.E1aHighEnd = phaseValues[0]; + else { + DBGPRINT(RT_DEBUG_OFF, + ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 64, 100, 120, 140, 149 or 173", ch) ); + return FALSE; + } + + ITxBFSetEEPROM(pAd, &phaseParams, 0, 0, 0); + + case 2: + /* Remove Divider phase */ + ITxBFDividerCalibrationStartUp(pAd, 0, 0, divPhase); + //phaseValues[0] -= divPhase[0]; + + DBGPRINT(RT_DEBUG_TRACE, ( + "Divider phase : 0x%x\n" + "Before Residual phase : 0x%x\n", divPhase[0], phaseValues[0])); + + if (gBandFlg == TRUE) + { + ITxBFLoPhaseCalibrationStartUp(pAd, loOffsetCkFlg, &LoPhase); + printk("Before LoPhase = 0x%x\n", LoPhase); + LoPhase = ABS_One(LoPhase); + + if (LoPhase > 0x20 && LoPhase < 0x60) + { + phaseValues[0] = phaseValues[0] + 0x80; + } + + printk("After LoPhase = 0x%x\n", LoPhase); + } + + DBGPRINT(RT_DEBUG_TRACE, ("After Residual phase : 0x%x\n", phaseValues[0])); + + RTMP_IO_WRITE32(pAd, CAL_R0, 0); + RTMP_IO_WRITE32(pAd, TXBE_R13, phaseValues[0]); // for method1 + + break; + } + + return TRUE; +} +#endif + + +#ifdef MT76x2 +#ifdef TXBF_SUPPORT +static SC_TABLE_ENTRY impSubCarrierTable[3] = { {228, 255, 1, 28}, {198, 254, 2, 58}, {134, 254, 2, 122} }; +static SC_TABLE_ENTRY expSubCarrierTable[3] = { {228, 255, 1, 28}, {198, 254, 2, 58}, {134, 254, 2, 122} }; + +INT TxBfProfileTagRead( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN UCHAR profileIdx) +{ + UINT value32, readValue32[5]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R11, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R12, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R13, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R14, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R15, &readValue32[4]); + + /* + Bit 63:62 ng[1:0] + 61:60 cw[1:0] + 59:58 nrow[1:0] + 57:56 ncol[1:0] + 1 : 0 LM[1:0] + */ + prof->ng = (UCHAR)((readValue32[1] >> 30) & 0x3); + prof->cw = (UCHAR)((readValue32[1] >> 28) & 0x3); + prof->nrow = (UCHAR)((readValue32[1] >> 26) & 0x3); + prof->ncol = (UCHAR)((readValue32[1] >> 24) & 0x3); + prof->LM = (UCHAR)(readValue32[0] & 0x3); + + /* + Bit 55 : 8 Mac Adress [47:0] + */ + prof->DMAC[0] = (UCHAR)((readValue32[1] >> 16) & 0x0FF); + prof->DMAC[1] = (UCHAR)((readValue32[1] >> 8) & 0x0FF); + prof->DMAC[2] = (UCHAR)((readValue32[1]) & 0x0FF); + prof->DMAC[3] = (UCHAR)((readValue32[0] >> 24) & 0x0FF); + prof->DMAC[4] = (UCHAR)((readValue32[0] >> 16) & 0x0FF); + prof->DMAC[5] = (UCHAR)((readValue32[0] >> 8) & 0x0FF); + + /* + Bit 63 : 56 Tx1_scale_2ss[7:0] + 55 : 48 Tx0_scale_2ss[7:0] + 47 : 40 Tx1_scale_1ss[7:0] + 36 : 32 Tx0_scale_1ss[7:0] + */ + prof->Tx1_scale_2ss = (UCHAR)((readValue32[3] >> 24) & 0x0FF); + prof->Tx0_scale_2ss = (UCHAR)((readValue32[3] >> 16) & 0x0FF); + prof->Tx1_scale_1ss = (UCHAR)((readValue32[3] >> 8) & 0x0FF); + prof->Tx0_scale_1ss = (UCHAR)((readValue32[3] >> 0) & 0x0FF); + + /* + Bit 31 : 24 STS1_SNR[7:0] + 23 : 16 STS0_SNR[7:0] + */ + prof->STS1_SNR = (UCHAR)((readValue32[2] >> 24) & 0x0FF); + prof->STS0_SNR = (UCHAR)((readValue32[2] >> 16) & 0x0FF); + + /* + Bit 15 : 0 PFMU_TimeOut[15:0] + */ + prof->timeout = (USHORT)(readValue32[2] & 0x0FFFF); + + /* + Bit 8 : 5 LD, EO, IO, I/E + */ + prof->LD = (UCHAR)((readValue32[4] >> 8) & 0x1); + prof->EO = (UCHAR)((readValue32[4] >> 7) & 0x1); + prof->IO = (UCHAR)((readValue32[4] >> 6) & 0x1); + prof->I_E= (UCHAR)((readValue32[4] >> 5) & 0x1); + + /* + Check profile valid staus + */ + prof->validFlg = (readValue32[0] >> 7) & 0x1; + + DBGPRINT(RT_DEBUG_TRACE, ("============================= TxBf profile Tage Info ==============================\n" + "Pofile valid status = %d\n" + "Profile index = %d\n\n" + "PFMU_11 = 0x%x, PFMU_R12=0x%x, PFMU_R13=0x%x, PFMU_R14=0x%x\n\n" + "ng[1:0]=%d, cw[1:0]=%d, nrow[1:0]=%d, ncol[1:0]=%d, LM[1:0]=%d\n\n" + "Destimation MAC Address=%x:%x:%x:%x:%x:%x\n\n" + "Tx1_scal_2ss=0x%x, Tx0_scale_2ss=0x%x, Tx1_scal_1ss=0x%x, Tx0_scale_1ss=0x%x\n\n" + "STS1_SNR=0x%x, STS0_SNR=0x%x\n\n" + "timeout[15:0]=0x%x\n\n" + "LD=%d, EO=%d, IO=%d, I/E=%d\n" + "===================================================================================\n", + prof->validFlg, + profileIdx, + readValue32[0], readValue32[1], readValue32[2], readValue32[3], + prof->ng, prof->cw, prof->nrow, prof->ncol, prof->LM, + prof->DMAC[0], prof->DMAC[1], prof->DMAC[2], prof->DMAC[3], prof->DMAC[4], prof->DMAC[5], + prof->Tx1_scale_2ss, prof->Tx0_scale_2ss, prof->Tx1_scale_1ss, prof->Tx0_scale_1ss, + prof->STS1_SNR, prof->STS0_SNR, + prof->timeout, + prof->LD, prof->EO, prof->IO, prof->I_E)); + + return TRUE; +} + + +INT TxBfProfileTagWrite( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN UCHAR profileIdx) +{ + UINT value32, readValue32[5]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R11, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R12, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R13, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R14, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R15, &readValue32[4]); + + DBGPRINT(RT_DEBUG_TRACE, ("============================= TxBf profile Tage Write ==============================\n" + "Profile index = %d\n\n", + profileIdx)); + + /* + Bit 63:62 ng[1:0] + 61:60 cw[1:0] + 59:58 nrow[1:0] + 57:56 ncol[1:0] + 1 : 0 LM[1:0] + */ + if (prof->CMDInIdx & 1) + { + value32 = (LONG)prof->ng << 30; + value32 |= (LONG)prof->cw << 28; + value32 |= (LONG)prof->nrow << 26; + value32 |= (LONG)prof->ncol << 24; + readValue32[1] &= 0x00FFFFFF; + readValue32[1] |= value32; + + readValue32[0] &= ~(0x3); + readValue32[0] |= prof->LM; + + printk("ng[1:0]=%d, cw[1:0]=%d, nrow[1:0]=%d, ncol[1:0]=%d, LM[1:0]=%d\n\n", + prof->ng, prof->cw, prof->nrow, prof->ncol, prof->ncol); + } + + /* + Bit 55 : 8 Mac Adress [47:0] + */ + if (prof->CMDInIdx & 2) + { + value32 = (LONG)prof->DMAC[0] << 16; + value32 |= (LONG)prof->DMAC[1] << 8; + value32 |= (LONG)prof->DMAC[2] << 0; + readValue32[1] &= 0xFF000000; + readValue32[1] |= value32; + + value32 = (LONG)prof->DMAC[3] << 24; + value32 |= (LONG)prof->DMAC[4] << 16; + value32 |= (LONG)prof->DMAC[5] << 8; + readValue32[0] &= 0x000000FF; + readValue32[0] |= value32; + + DBGPRINT(RT_DEBUG_TRACE,("Destimation MAC Address=%x:%x:%x:%x:%x:%x\n\n", + prof->DMAC[0], prof->DMAC[1], prof->DMAC[2], prof->DMAC[3], prof->DMAC[4], prof->DMAC[5])); + } + + /* + Bit 63 : 56 Tx1_scale_2ss[7:0] + 55 : 48 Tx0_scale_2ss[7:0] + 47 : 40 Tx1_scale_1ss[7:0] + 36 : 32 Tx0_scale_1ss[7:0] + */ + if (prof->CMDInIdx & 4) + { + value32 = (LONG)prof->Tx1_scale_2ss << 24; + value32 |= (LONG)prof->Tx0_scale_2ss << 16; + value32 |= (LONG)prof->Tx1_scale_1ss << 8; + value32 |= (LONG)prof->Tx0_scale_1ss << 0; + readValue32[3] = value32; + + printk("Tx1_scal_2ss=0x%x, Tx0_scale_2ss=0x%x, Tx1_scal_1ss=0x%x, Tx0_scale_1ss=0x%x\n\n", + prof->Tx1_scale_2ss, prof->Tx0_scale_2ss, prof->Tx1_scale_1ss, prof->Tx0_scale_1ss); + } + + /* + Bit 31 : 24 STS1_SNR[7:0] + 23 : 16 STS0_SNR[7:0] + */ + if (prof->CMDInIdx & 8) + { + value32 = (LONG)prof->STS1_SNR << 24; + value32 |= (LONG)prof->STS0_SNR << 16; + readValue32[2] &= 0x0000FFFF; + readValue32[2] |= value32; + + printk("STS1_SNR=0x%x, STS0_SNR=0x%x\n\n", prof->STS1_SNR, prof->STS0_SNR); + } + + /* + Bit 15 : 0 timeout[15:0] + */ + if (prof->CMDInIdx & 16) + { + readValue32[2] &= 0xFFFF0000; + readValue32[2] |= (ULONG)prof->timeout; + + printk("timeout[15:0]=0x%x\n\n", prof->timeout); + } + + DBGPRINT(RT_DEBUG_TRACE,("PFMU_11 = 0x%x, PFMU_R12=0x%x, PFMU_R13=0x%x, PFMU_R14=0x%x\n\n", + readValue32[0], readValue32[1], readValue32[2], readValue32[3])); + + /* + Bit 8 : 5 LD, EO, IO, I/E + */ + if (prof->CMDInIdx & 32) + { + readValue32[4] &= 0xFFFFFE00; + readValue32[4] |= prof->LD << 8; + readValue32[4] |= prof->EO << 7; + readValue32[4] |= prof->IO << 6; + readValue32[4] |= prof->I_E<< 5; + + printk("LD=%d, EO=%d, IO=%d, I/E=%d\n" + "===================================================================================\n", + prof->LD, prof->EO, prof->IO, prof->I_E); + } + + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Write PFMU_R11 ~ R15 + RTMP_IO_WRITE32(pAd, PFMU_R15, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R14, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R13, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R12, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R11, readValue32[0]); + + prof->CMDInIdx = 0; // clear tag indicator + + return TRUE; +} + + +INT TxBfProfileDataRead( + IN PRTMP_ADAPTER pAd, + IN PFMU_DATA *pData, + IN UCHAR profileIdx, + IN UCHAR subcarrierIdx) +{ + UINT value32, readValue32[5]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|subcarrierIdx)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + pData->psi21 = (readValue32[0] >> 16) & 0x00FF; + pData->phill = (readValue32[0] >> 0) & 0x00FF; + return TRUE; +} + + +INT TxBfProfileDataWrite( + IN PRTMP_ADAPTER pAd, + IN PFMU_DATA *pData, + IN UCHAR profileIdx, + IN UCHAR subcarrierIdx) +{ + UINT value32, readValue32[5]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|subcarrierIdx)); + // Read PFMU_R19 ~ R23 + RTMP_IO_READ32(pAd, PFMU_R19, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R20, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R21, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R22, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R23, &readValue32[4]); + + pData->psi21 = (readValue32[0] >> 16) & 0x00FF; + pData->phill = (readValue32[0] >> 0) & 0x00FF; + + printk("============================= TxBf profile Data Write ==============================\n" + "Profile index = %d, subcarrierIdx = %d\n\n", + profileIdx, subcarrierIdx); + + if (pData->dCMDInIdx & 1) + { + readValue32[0] &= 0xFF00FFFF; + readValue32[0] |= pData->psi21; + + printk("psi21 = 0x%x\n\n", pData->psi21); + } + + if (pData->dCMDInIdx & 2) + { + readValue32[0] &= 0xFFFFFF00; + readValue32[0] |= pData->phill; + + printk("phill = 0x%x\n\n", pData->phill); + } + + printk("PFMU_19 = 0x%x, PFMU_R20=0x%x, PFMU_R21=0x%x, PFMU_R22=0x%x\n\n" + "===================================================================================\n", + readValue32[0], readValue32[1], readValue32[2], readValue32[3]); + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|subcarrierIdx)); + // Wite PFMU_R19 ~ R23 + RTMP_IO_WRITE32(pAd, PFMU_R23, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R22, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R21, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R20, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R19, readValue32[0]); + + pData->dCMDInIdx = 0; // clear profile data write indicator + + return TRUE; +} + + +INT TxBfProfileTagValid( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN UCHAR profileIdx) +{ + UINT value32, readValue32[5]; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Read PFMU_R11 ~ R15 + RTMP_IO_READ32(pAd, PFMU_R11, &readValue32[0]); + RTMP_IO_READ32(pAd, PFMU_R12, &readValue32[1]); + RTMP_IO_READ32(pAd, PFMU_R13, &readValue32[2]); + RTMP_IO_READ32(pAd, PFMU_R14, &readValue32[3]); + RTMP_IO_READ32(pAd, PFMU_R15, &readValue32[4]); + + /* + Update the valid bit + */ + readValue32[0] &= ~(1 << 7); + readValue32[0] |= prof->validFlg << 7; + + // Read PFMU_R10 (0x2f28) first + RTMP_IO_READ32(pAd, PFMU_R10, &value32); + value32 &= (~0x3C00); + // Wite PFMU_R10 to trigger read command + RTMP_IO_WRITE32(pAd, PFMU_R10, ((profileIdx << 10)|value32)); + // Write PFMU_R11 ~ R15 + RTMP_IO_WRITE32(pAd, PFMU_R15, readValue32[4]); + RTMP_IO_WRITE32(pAd, PFMU_R14, readValue32[3]); + RTMP_IO_WRITE32(pAd, PFMU_R13, readValue32[2]); + RTMP_IO_WRITE32(pAd, PFMU_R12, readValue32[1]); + RTMP_IO_WRITE32(pAd, PFMU_R11, readValue32[0]); + + return TRUE; +} +#endif /* TXBF_SUPPORT */ +#endif /* MT76x2 */ + + +#ifdef MT76x2 +UCHAR Read_PFMUTxBfProfile( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN PFMU_DATA *pData, + IN BOOLEAN implicitProfile) +{ + INT carrierIndex, scIndex; + INT profileNum; + SC_TABLE_ENTRY *pTab = NULL; + INT j, c; + UCHAR r163Value = 0; + UINT32 value32; + UCHAR GrpTab[3] = {1, 2, 4}; + UCHAR GrpInc; + +#ifdef TIMESTAMP_BF_PROFILE + struct timeval tval1, tval2; + do_gettimeofday(&tval1); +#endif + + /* Disable Profile Updates during access */ + RTMP_IO_READ32(pAd, PFMU_R1, &value32); + RTMP_IO_WRITE32(pAd, PFMU_R1, value32 & ~0x330); + + for (profileNum = 0; profileNum < 8; profileNum++) + { + /* Read Tag */ + TxBfProfileTagRead(pAd, prof, profileNum); + + if (implicitProfile == 1 && prof->I_E == 0 && prof->validFlg == 1) + { + DBGPRINT(RT_DEBUG_TRACE,("@@@@@@@@ Valid ITxBf profile is found @@@@@@@@@\n" + "implicitProfile = %d prof->cw = %d \n", + implicitProfile, prof->cw)); + pTab = &impSubCarrierTable[prof->cw]; + break; // While valid implicit profile is found, break the seeking loop + } + + if (implicitProfile == 0 && prof->I_E == 1 && prof->validFlg == 1) + { + DBGPRINT(RT_DEBUG_TRACE,("@@@@@@@@ Valid ETxBf profile is found @@@@@@@@@\n" + "implicitProfile = %d prof->cw = %d \n", + implicitProfile, prof->cw)); + pTab = &expSubCarrierTable[prof->cw]; + break; // While valid explicit profile is found, break the seeking loop + } + } + + if (prof->validFlg != 1) return prof->validFlg; + + /* Negative subcarriers */ + carrierIndex = 0; + GrpInc = GrpTab[prof->ng]; + for (scIndex=pTab->lwb1; scIndex <= pTab->upb1; scIndex++) + { + /* Read subcarrier data */ + TxBfProfileDataRead(pAd, pData, profileNum, scIndex); + pData->data[carrierIndex++][0] = pData->psi21; + pData->data[carrierIndex][1] = pData->phill; + } + + /* Positive subcarriers */ + for (scIndex=pTab->lwb2; scIndex <= pTab->upb2; scIndex++) + { + /* Read subcarrier data */ + TxBfProfileDataRead(pAd, pData, profileNum, scIndex); + pData->data[carrierIndex++][0] = pData->psi21; + pData->data[carrierIndex][1] = pData->phill; + } + + /* Restore Profile Updates */ + RTMP_IO_WRITE32(pAd, PFMU_R1, value32); + +#ifdef TIMESTAMP_BF_PROFILE + do_gettimeofday(&tval2); + DBGPRINT(RT_DEBUG_WARN, ("BF Read elasped = %ld usec\n", tval2.tv_usec - tval1.tv_usec)); +#endif + + return prof->validFlg; +} +#endif // MT76x2 + + +#ifdef DBG +#ifdef LINUX +/* #define TIMESTAMP_CALC_CALIBRATION */ +#endif /* LINUX */ +#endif /* DBG */ + +#define P_RESOLUTION 256 /* Resolution of phase calculation: 2pi/256 */ + +static UCHAR maxCarrTab[3] = {PROFILE_MAX_CARRIERS_20, + PROFILE_MAX_CARRIERS_40, + PROFILE_MAX_CARRIERS_80}; + +INT32 ei0[PROFILE_MAX_CARRIERS_40][2]; +INT32 ei1[PROFILE_MAX_CARRIERS_40][2]; +INT32 ei2[PROFILE_MAX_CARRIERS_40][2]; + +/* + iCalcCalibration - calculate calibration parameters + Returns 0 if successful, -1 if profiles are invalid +*/ + +#ifdef MT76x2 +int iCalcCalibration(PRTMP_ADAPTER pAd, int calParams[2], int profileNum) +{ + int pi, maxCarriers, ii; + short rot[2]; + INT32 c0[2], c1[2]; + INT32 minSum=0; + int di1=0; + INT32 ed[2], id[2]; + PFMU_PROFILE *pExpProf, *pImpProf; + PFMU_DATA *pExpData, *pImpData; + SHORT cos_psi21_e, sin_psi21_e, cos_phill_e, sin_phill_e; + SHORT cos_psi21_i, sin_psi21_i, cos_phill_i, sin_phill_i; + int result = 0; + +#ifdef TIMESTAMP_CALC_CALIBRATION + struct timeval tval1, tval2; +#endif + + if (os_alloc_mem(pAd, (UCHAR **)&pExpData, sizeof(PFMU_DATA)) != NDIS_STATUS_SUCCESS) + { + return -3; + } + + if (os_alloc_mem(pAd, (UCHAR **)&pImpData, sizeof(PFMU_DATA))!= NDIS_STATUS_SUCCESS) + { + os_free_mem(pAd, pExpData); + return -3; + } + + if (os_alloc_mem(pAd, (UCHAR **)&pExpProf, sizeof(PFMU_PROFILE))!= NDIS_STATUS_SUCCESS) + { + os_free_mem(pAd, pImpData); + os_free_mem(pAd, pExpData); + return -3; + } + + if (os_alloc_mem(pAd, (UCHAR **)&pImpProf, sizeof(PFMU_PROFILE)) != NDIS_STATUS_SUCCESS) + { + os_free_mem(pAd, pImpData); + os_free_mem(pAd, pExpData); + os_free_mem(pAd, pExpProf); + return -3; + } + + /* Read Implicit and Explicit data */ + //if (Read_PFMUTxBfProfile(pAd, pImpProf, pImpData, TRUE) != 1) + if (Read_PFMUTxBfProfile(pAd, pImpProf, pImpData, TRUE) != 1) + { + result = -1; + goto exitCalcCal; + } + + maxCarriers = maxCarrTab[pImpProf->cw]; + for (pi=0; pidata[%d][0]=0x%x pImpData->data[%d][1]=0x%x\n", + pi, pImpData->data[pi][0], pi, pImpData->data[pi][1])); + } + if (Read_PFMUTxBfProfile(pAd, pExpProf, pExpData, FALSE) != 1) + { + result = -1; + goto exitCalcCal; + } + + maxCarriers = maxCarrTab[pExpProf->cw]; + for (pi=0; pidata[%d][0]=0x%x pExpData->data[%d][1]=0x%x\n", + pi, pExpData->data[pi][0], pi, pExpData->data[pi][1])); + } + + /* Quit if MAC addresses don't match */ + for (ii=0; ii<6; ii++) { + if (pImpProf->DMAC[ii] != pExpProf->DMAC[ii]) { + result = -2; + printk("MAC Addr in ITxBf and ETxBf tag is different!!!!!!!\n"); + goto exitCalcCal; + } + } + + /* Quit if profiles cannot be used */ + if (pImpProf->nrow > 2 || pExpProf->nrow > 2) { + result = -1; + printk("Profile Matrix size is not correct!!!!!!\n"); + goto exitCalcCal; + } + + /* + If Implicit profile is legacy then zero out the unused carriers so they don't + affect the calculation + */ + if (pImpProf->LM == 0) { + memset(pImpData->data[0], 0x00, sizeof(pImpData->data[0])); + memset(pImpData->data[1], 0x00, sizeof(pImpData->data[0])); + memset(pImpData->data[PROFILE_MAX_CARRIERS_20-2], 0x00, sizeof(pImpData->data[0])); + memset(pImpData->data[PROFILE_MAX_CARRIERS_20-1], 0x00, sizeof(pImpData->data[0])); + } + +#ifdef TIMESTAMP_CALC_CALIBRATION + do_gettimeofday(&tval1); +#endif + + //maxCarriers = maxCarrTab[pImpProf->cw]; + maxCarriers = maxCarrTab[pExpProf->cw]; + + /* Compute Exp .* conj(Imp).*/ + // Combine 2Tx signal to Rx 1st input so just need 2x1 matrix to calculate phase difference + // ITBf vector Vi = |cos(psi21)exp(jphill)| vector Ve = |cos(psi21)exp(jphill)| + // | sin(psi21) | | sin(psi21) | + + for (pi=0; pidata[pi][0] * 256/P_RESOLUTION); + cos_psi21_e = rot[0]; + sin_psi21_e = rot[1]; + icexp(rot, pExpData->data[pi][1] * 256/P_RESOLUTION); + cos_phill_e = rot[0]; + sin_phill_e = rot[1]; + + // 1.20 + ed[0] = cos_psi21_e * cos_phill_e; // real part + ed[1] = cos_psi21_e * sin_phill_e; // image part + + icexp(rot, pImpData->data[pi][0] * 256/P_RESOLUTION); + cos_psi21_i = rot[0]; + sin_psi21_i = rot[1]; + icexp(rot, pImpData->data[pi][1] * 256/P_RESOLUTION); + cos_phill_i = rot[0]; + sin_phill_i = rot[1]; + + //1.09 + id[0] = (cos_psi21_i * cos_phill_i) >> 11; // real part + id[1] = (cos_psi21_i * sin_phill_i) >> 11; // image part + + // ei0[pi] : 2.29 + icMult(ei0[pi], ed, id[0], -id[1]); + + ed[0] = -sin_psi21_e; + ed[1] = 0; + id[0] = -sin_psi21_i; + id[1] = 0; + // ei1[pi] : 1.20 + icMult(ei1[pi], ed, id[0], -id[1]); + + } + + /* Search for best Phase 1 */ + // |ei0| + // |ei1| = Vi .* Ve + // ei0 + ei1 * exp(Phase[ii]) = exp(ei0) (1 + exp(Phase(ei1) - Phase(ei0)) * exp(Phase[ii])) + // Max value should be Phase[ii] = Phase[ei0] - Phase[ei1] + // By the check every phase index and find the min power (if sum -= isqrt(xx)), then you can find Phase[ii] + for (ii=0; ii> 1; + ei[1] = ei1[pi][1] >> 1; + icMult(c1, ei, rot[0], rot[1]); + + // c0 : 2.(29-17) , 2.(29-17) = 3.12 + c0[0] = (ei0[pi][0] + c1[0])>>17; + c0[1] = (ei0[pi][1] + c1[1])>>17; + //sum : 3.12 + 3.12 = 6.24 + sum -= isqrt(c0[0]*c0[0] + c0[1]*c0[1]); + } + + /* Record minimum */ + if (ii==0 || minSum>sum) { + di1 = ii; + minSum = sum; + } + } + + /* Convert to calibration parameters */ + calParams[0] = -di1 & 0xFF; // Max power whe Phase[ii]= Phase[ei0] - Phase[ei1] + calParams[1] = -di1 & 0xFF; // Phase[ii]= Phase[ei2] - Phase[ei1] + // So if we compensate the phase at ANT1, then Phase[ei1] + (Phase[ei0] -Phase[ei1]) = Phase[ei0] + // ANT2, then Phase[ei2] + (Phase[ei0] - Phase[ei2]) = Phase[ei0] + // ANT0, no phase compensate + // Hi = He * exp(Phase[ei0]) -> hi = he(t - delay) + + +#ifdef TIMESTAMP_CALC_CALIBRATION + do_gettimeofday(&tval2); + ATEDBGPRINT(RT_DEBUG_WARN, ("iCalcCal = %ld usec\n", tval2.tv_usec - tval1.tv_usec)); +#endif + +exitCalcCal: + os_free_mem(pAd, pExpData); + os_free_mem(pAd, pImpData); + os_free_mem(pAd, pExpProf); + os_free_mem(pAd, pImpProf); + + + return result; +} + +#endif + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_video.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_video.c new file mode 100644 index 000000000..1e4ec06ac --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_video.c @@ -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 */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wep.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wep.c new file mode 100644 index 000000000..0a2590a2b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wep.c @@ -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; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wpa.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wpa.c new file mode 100644 index 000000000..424a89c2e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wpa.c @@ -0,0 +1,6330 @@ +/* + *************************************************************************** + * 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: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Paul Lin 03-11-28 Modify for supplicant +*/ +#include "rt_config.h" + +/* WPA OUI*/ +UCHAR OUI_WPA[3] = {0x00, 0x50, 0xF2}; +UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; +UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; +UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; +UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05}; +UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; +/* WPA2 OUI*/ +UCHAR OUI_WPA2[3] = {0x00, 0x0F, 0xAC}; +UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; +UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05}; +UCHAR OUI_WPA2_1X_SHA256[4] = {0x00, 0x0F, 0xAC, 0x05}; +UCHAR OUI_WPA2_PSK_SHA256[4] = {0x00, 0x0F, 0xAC, 0x06}; + +#ifdef CONFIG_HOTSPOT_R2 +UCHAR OSEN_IE[] = {0x50,0x6f,0x9a,0x12,0x00,0x0f,0xac,0x07,0x01,0x00,0x00,0x0f,0xac,0x04,0x01,0x00,0x50,0x6f,0x9a,0x01,0x00,0x00}; +UCHAR OSEN_IELEN = sizeof(OSEN_IE); +#endif + +#ifdef DOT11R_FT_SUPPORT +UCHAR OUI_FT_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x03}; +UCHAR OUI_FT_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x04}; +#endif /* DOT11R_FT_SUPPORT */ + +static VOID ConstructEapolKeyData( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR keyDescVer, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + OUT PEAPOL_PACKET pMsg); + +static VOID WpaEAPPacketAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID WpaEAPOLASFAlertAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID WpaEAPOLLogoffAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID WpaEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +VOID WpaStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE); + + StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, (STATE_MACHINE_FUNC)WpaEAPPacketAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, (STATE_MACHINE_FUNC)WpaEAPOLStartAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, (STATE_MACHINE_FUNC)WpaEAPOLLogoffAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, (STATE_MACHINE_FUNC)WpaEAPOLASFAlertAction); +} + +/* + ========================================================================== + Description: + this is state machine function. + When receiving EAP packets which is for 802.1x authentication use. + Not use in PSK case + Return: + ========================================================================== +*/ +VOID WpaEAPPacketAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +VOID WpaEAPOLASFAlertAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +VOID WpaEAPOLLogoffAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +/* + ========================================================================== + Description: + Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c + Return: + ========================================================================== +*/ +VOID WpaEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MAC_TABLE_ENTRY *pEntry; + PHEADER_802_11 pHeader; + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) { + Adhoc_WpaEAPOLStartAction(pAd, Elem); + return; + } + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n")); + + pHeader = (PHEADER_802_11)Elem->Msg; + + /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process.*/ + if (Elem->MsgLen == 6) + pEntry = MacTableLookup(pAd, Elem->Msg); + else + { + pEntry = MacTableLookup(pAd, pHeader->Addr2); +#ifdef WSC_AP_SUPPORT + /* + a WSC enabled AP must ignore EAPOL-Start frames received from clients that associated to + the AP with an RSN IE or SSN IE indicating a WPA2-PSK/WPA-PSK authentication method in + the assication request. <> + */ + if (pEntry && + (pEntry->apidx == MAIN_MBSSID) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + pEntry->bWscCapable) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS enabled AP: Ignore EAPOL-Start frames received from clients.\n")); + return; + } +#endif /* WSC_AP_SUPPORT */ + } + + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx)); + + if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (pEntry->WpaState < AS_PTKSTART) + && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + + WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } +} + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MAC_TABLE_ENTRY *pEntry; + PHEADER_802_11 pHeader; + PEAPOL_PACKET pEapol_packet; + KEY_INFO peerKeyInfo; + UINT eapol_len; +#ifdef MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) { + Adhoc_WpaEAPOLKeyAction(pAd, Elem); + return; + } + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n")); + + pHeader = (PHEADER_802_11)Elem->Msg; + pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + eapol_len = CONV_ARRARY_TO_UINT16(pEapol_packet->Body_Len) + LENGTH_EAPOL_H; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + + *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + } +#endif /* MAC_REPEATER_SUPPORT */ + + do + { +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: CliIdx != 0xFF ifIndex(%d), CliIdx(%d) !!!\n", + __FUNCTION__,ifIndex, CliIdx)); + + UCHAR MacTabMax = MAX_LEN_OF_MAC_TABLE; + + if ((pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid == FALSE) || + (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable == FALSE) || + (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID > (MAX_LEN_OF_MAC_TABLE - 1))) + { + pEntry = NULL; + + DBGPRINT(RT_DEBUG_OFF, ("%s: calculate wrong wcid(%d), ifIndex(%d), CliIdx(%d) !!!\n", + __FUNCTION__, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID, + ifIndex, CliIdx)); + break; + } + else + { + pEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID]; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + DBGPRINT(RT_DEBUG_OFF, ("%s: CliIdx == 0xFF pHeader->Addr2(%02X-%02X-%02X-%02X-%02X-%02X) !!!\n", + __FUNCTION__,PRINT_MAC(pHeader->Addr2))); + pEntry = MacTableLookup(pAd, pHeader->Addr2); + } + + if (!pEntry || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + break; + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) +#ifdef MWDS + && ((pAd->ApCfg.ApCliTab[ifIndex].bSupportMWDS == FALSE) || + (pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.bSupportMWDS == FALSE)) +#endif /* MWDS */ + ) + { + if (IS_ENTRY_APCLI(pEntry) && (ifIndex < MAX_APCLI_NUM) && (CliIdx == 0xFF)) + { + if ((pEntry->Aid) != (MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * (ifIndex)))) + { + USHORT HashIdx; + MAC_TABLE_ENTRY *pProbeEntry; + + HashIdx = MAC_ADDR_HASH_INDEX(pHeader->Addr2); + + pProbeEntry = pAd->MacTab.Hash[HashIdx]; + ASSERT(pProbeEntry); + + if (pProbeEntry != NULL) + { + do + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): apcli: aid=%d !!!\n", __FUNCTION__, pProbeEntry->Aid)); + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + } + } + + pEntry = &pAd->MacTab.Content[MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * (ifIndex))]; + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + break; + + DBGPRINT(RT_DEBUG_OFF, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X wcid(%d)\n", PRINT_MAC(pEntry->Addr), pEntry->wcid)); + + if (eapol_len > Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H) + { + DBGPRINT(RT_DEBUG_ERROR, ("The length of EAPoL packet is invalid \n")); + break; + } + + if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) || + ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); + break; + } + +#ifdef DOT11R_FT_SUPPORT + /* The value 3 shall be used for all EAPOL-Key frames to and from a STA when the negotiated */ + /* AKM is 00-0F-AC:3 or 00-0F-AC:4. It is a FT STA. */ + if (IS_FT_RSN_STA(pEntry)) + { + if (peerKeyInfo.KeyDescVer != KEY_DESC_EXT) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version(%d) not match(FT) \n", peerKeyInfo.KeyDescVer)); + break; + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */ + /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1.*/ + if ((pEntry->WepStatus == Ndis802_11TKIPEnable) && (peerKeyInfo.KeyDescVer != KEY_DESC_TKIP)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n")); + break; + } +#ifdef DOT11W_PMF_SUPPORT + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256) && (peerKeyInfo.KeyDescVer != KEY_DESC_EXT)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES-128)\n")); + } +#endif /* DOT11W_PMF_SUPPORT */ + /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */ + /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2 or 3.*/ + else if ((pEntry->WepStatus == Ndis802_11AESEnable) + && (peerKeyInfo.KeyDescVer != KEY_DESC_AES) + && (peerKeyInfo.KeyDescVer != KEY_DESC_EXT) +#ifdef CONFIG_HOTSPOT_R2 + && (peerKeyInfo.KeyDescVer != KEY_DESC_OSEN) +#endif + ) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) pEntry->WepStatus=%d, peerKeyInfo.KeyDescVer=%d\n", pEntry->WepStatus, peerKeyInfo.KeyDescVer)); + break; + } + + /* Check if this STA is in class 3 state and the WPA state is started */ + if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK)) + { + /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */ + /* or not.*/ + /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL-*/ + /* Key frame from the Authenticator must not have the Ack bit set.*/ + if (peerKeyInfo.KeyAck == 1) + { + /* The frame is snet by Authenticator. */ + /* So the Supplicant side shall handle this.*/ + + if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY)) + { + /* + Process + 1. the message 1 of 4-way HS in WPA or WPA2 + EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) + 2. the message 3 of 4-way HS in WPA + EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) + */ + if (peerKeyInfo.KeyMic == 0) + PeerPairMsg1Action(pAd, pEntry, Elem); + else + PeerPairMsg3Action(pAd, pEntry, Elem); + } + else if ((peerKeyInfo.Secure == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0)) + { + /* + Process + 1. the message 3 of 4-way HS in WPA2 + EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) + 2. the message 1 of group KS in WPA or WPA2 + EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) + */ + if (peerKeyInfo.KeyType == PAIRWISEKEY) + PeerPairMsg3Action(pAd, pEntry, Elem); + else + PeerGroupMsg1Action(pAd, pEntry, Elem); + } + } + else + { + /* + The frame is snet by Supplicant.So the Authenticator + side shall handle this. + */ +#ifdef CONFIG_AP_SUPPORT +#ifdef QOS_DLS_SUPPORT + if ((peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.KeyType == GROUPKEY) && + (pEapol_packet->KeyDesc.KeyDataLen[1] == 12)) + { + /* This is a ralink proprietary DLS STA-Key processing*/ + RTMPHandleSTAKey(pAd, pEntry, Elem); + } + else +#endif /* QOS_DLS_SUPPORT */ + if ((peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Request == 1) && + (peerKeyInfo.Error == 1)) + { + /* The Supplicant uses a single Michael MIC Failure Report frame */ + /* to report a MIC failure event to the Authenticator. */ + /* A Michael MIC Failure Report is an EAPOL-Key frame with */ + /* the following Key Information field bits set to 1: */ + /* MIC bit, Error bit, Request bit, Secure bit.*/ + + DBGPRINT(RT_DEBUG_ERROR, ("Received an Michael MIC Failure Report, active countermeasure \n")); + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } + else +#endif /* CONFIG_AP_SUPPORT */ + if ((peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.KeyMic == 1)) + { + if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY) + { + /* + EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) Process: + 1. message 2 of 4-way HS in WPA or WPA2 + 2. message 4 of 4-way HS in WPA + */ + if (CONV_ARRARY_TO_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0) + PeerPairMsg4Action(pAd, pEntry, Elem); + else + PeerPairMsg2Action(pAd, pEntry, Elem); + } + else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY) + { + /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */ + /* Process message 4 of 4-way HS in WPA2*/ + PeerPairMsg4Action(pAd, pEntry, Elem); + } + else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY) + { + /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0)*/ + /* Process message 2 of Group key HS in WPA or WPA2 */ + PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11)); + } + } +#ifdef CONFIG_AP_SUPPORT + else if ((peerKeyInfo.Request == 1) && (peerKeyInfo.Error == 0)) + { + INT i; + UCHAR apidx = pEntry->apidx; + + /* Need to check KeyType for groupkey or pairwise key update, refer to 8021i P.114, */ + if (peerKeyInfo.KeyType == GROUPKEY) + { + UINT8 Wcid; + MULTISSID_STRUCT *mbss; + struct wifi_dev *wdev; + DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR=0, update group key\n")); + + mbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &mbss->wdev; + + GenRandom(pAd, wdev->bssid, mbss->GNonce); + wdev->DefaultKeyId = (wdev->DefaultKeyId == 1) ? 2 : 1; + WpaDeriveGTK(mbss->GMK, mbss->GNonce, + wdev->bssid, mbss->GTK, LEN_TKIP_GTK); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) + && (pAd->MacTab.Content[i].WpaState == AS_PTKINITDONE) + && (pAd->MacTab.Content[i].apidx == apidx)) + { + pAd->MacTab.Content[i].GTKState = REKEY_NEGOTIATING; + WPAStart2WayGroupHS(pAd, &pAd->MacTab.Content[i]); + pAd->MacTab.Content[i].ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + /* retry timer is set inside WPAStart2WayGroupHS */ + //RTMPModTimer(&pAd->MacTab.Content[i].RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + + } + } + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + WPAInstallSharedKey(pAd, wdev->GroupKeyWepStatus, + apidx, wdev->DefaultKeyId, Wcid, + TRUE, mbss->GTK, LEN_TKIP_GTK); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR= 0, update pairwise key\n")); + + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + + /* clear this entry as no-security mode*/ + AsicRemovePairwiseKeyEntry(pAd, pEntry->wcid); + + pEntry->Sst = SST_ASSOC; + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPA2) + pEntry->WpaState = AS_INITPMK; + else if (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + pEntry->WpaState = AS_INITPSK; + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + + WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + } + }while(FALSE); +} + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN bClearFrame) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status; + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry) +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + && (!IS_ENTRY_TDLS(pEntry)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + )) + return; + + do { + Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + break; + + + if (bClearFrame) + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); + else + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + RTMP_SET_PACKET_NET_DEVICE_APCLI(pPacket, pEntry->apidx); + } + else +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + { + } + + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value*/ + if(pEntry->apidx != 0) + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx); + + RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->wcid); + RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* send out the packet */ + APSendPacket(pAd, pPacket); + + /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* send out the packet*/ + Status = STASendPacket(pAd, pPacket); + if (Status == NDIS_STATUS_SUCCESS) + { + UCHAR Index; + + /* Dequeue one frame from TxSwQueue0..3 queue and process it*/ + /* There are three place calling dequeue for TX ring.*/ + /* 1. Here, right after queueing the frame.*/ + /* 2. At the end of TxRingTxDone service routine.*/ + /* 3. Upon NDIS call RTMPSendPackets*/ + if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + } while (FALSE); +} + +/* + ========================================================================== + Description: + Check the validity of the received EAPoL frame + Return: + TRUE if all parameters are OK, + FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerWpaMessageSanity( + IN PRTMP_ADAPTER pAd, + IN PEAPOL_PACKET pMsg, + IN ULONG MsgLen, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR mic[LEN_KEY_DESC_MIC], digest[80]; /*, KEYDATA[MAX_LEN_OF_RSNIE];*/ + UCHAR *KEYDATA = NULL; + BOOLEAN bReplayDiff = FALSE; + BOOLEAN bWPA2 = FALSE; + KEY_INFO EapolKeyInfo; + UCHAR GroupKeyIndex = 0; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&KEYDATA, MAX_LEN_OF_RSNIE); + if (KEYDATA == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return FALSE; + } + + NdisZeroMemory(mic, sizeof(mic)); + NdisZeroMemory(digest, sizeof(digest)); + NdisZeroMemory(KEYDATA, MAX_LEN_OF_RSNIE); + NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo)); + + NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo)); + + /* Choose WPA2 or not*/ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + /* 0. Check MsgType*/ + if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType)); + goto LabelErr; + } + + /* 1. Replay counter check */ + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant*/ + { + /* First validate replay counter, only accept message with larger replay counter.*/ + /* Let equal pass, some AP start with all zero replay counter*/ + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + { + bReplayDiff = TRUE; + } + } + else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator*/ + { + /* check Replay Counter coresponds to MSG from authenticator, otherwise discard*/ + if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY)) + { + bReplayDiff = TRUE; + } + } + + /* Replay Counter different condition*/ + if (bReplayDiff) + { + /* send wireless event - for replay counter different*/ + RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + DBGPRINT(RT_DEBUG_ERROR, ("pEntry->Addr(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pEntry->Addr))); + DBGPRINT(RT_DEBUG_ERROR, ("pEntry->apidx=%d pEntry->wcid=%d\n", pEntry->apidx, pEntry->wcid)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + goto LabelErr; + } + + /* 2. Verify MIC except Pairwise Msg1*/ + if (MsgType != EAPOL_PAIR_MSG_1) + { + UCHAR rcvd_mic[LEN_KEY_DESC_MIC]; + UINT eapol_len = CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4; + + /* Record the received MIC for check later*/ + NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if (EapolKeyInfo.KeyDescVer == KEY_DESC_TKIP) /* TKIP*/ + { + RT_HMAC_MD5(pEntry->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, mic, MD5_DIGEST_SIZE); + } + else if (EapolKeyInfo.KeyDescVer == KEY_DESC_AES) /* AES */ + { + RT_HMAC_SHA1(pEntry->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + else if (EapolKeyInfo.KeyDescVer == KEY_DESC_EXT) /* AES-128 */ + { + UINT mlen = AES_KEY128_LENGTH; + AES_CMAC((PUCHAR)pMsg, eapol_len, pEntry->PTK, LEN_PTK_KCK, mic, &mlen); + } + else if (EapolKeyInfo.KeyDescVer == KEY_DESC_OSEN) /* AES-128 */ + { + UINT mlen = AES_KEY128_LENGTH; + AES_CMAC((PUCHAR)pMsg, eapol_len, pEntry->PTK, LEN_PTK_KCK, mic, &mlen); + +#ifdef DBG + { + unsigned char *tmp = (unsigned char *)pEntry->PTK; + int k=0; + printk("PTK=>"); + for(k=0;k<32;k++) + printk("%02x", *(tmp+k)); + printk("\n"); + } +#endif + } + + + if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) + { + /* send wireless event - for MIC different*/ + RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); + hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); + + goto LabelErr; + } + } + + /* 1. Decrypt the Key Data field if GTK is included.*/ + /* 2. Extract the context of the Key Data field if it exist. */ + /* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear.*/ + /* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted.*/ + if (CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen) > 0) + { + /* Decrypt this field */ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + if((EapolKeyInfo.KeyDescVer == KEY_DESC_EXT) || (EapolKeyInfo.KeyDescVer == KEY_DESC_AES)) + { + UINT aes_unwrap_len = 0; + + /* AES */ + AES_Key_Unwrap(pMsg->KeyDesc.KeyData, + CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), + &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + KEYDATA, &aes_unwrap_len); + SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, aes_unwrap_len); + } + else + { + TKIP_GTK_KEY_UNWRAP(&pEntry->PTK[LEN_PTK_KCK], + pMsg->KeyDesc.KeyIv, + pMsg->KeyDesc.KeyData, + CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), + KEYDATA); + } + + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + GroupKeyIndex = EapolKeyInfo.KeyIndex; + + } + else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) + { + NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen)); + } + else + { + + goto LabelOK; + } + + /* Parse Key Data field to */ + /* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2)*/ + /* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2*/ + /* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2)*/ + if (!RTMPParseEapolKeyData(pAd, KEYDATA, + CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), + GroupKeyIndex, MsgType, bWPA2, pEntry)) + { + goto LabelErr; + } + } + +LabelOK: + if (KEYDATA != NULL) + os_free_mem(NULL, KEYDATA); + return TRUE; + +LabelErr: + if (KEYDATA != NULL) + os_free_mem(NULL, KEYDATA); +#ifdef SMART_MESH_MONITOR + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.sta_wpa_keyerr.type = NSMPIF_DRVEVNT_STA_WPA_KEYERR; + drvevnt.data.sta_wpa_keyerr.channel = pAd->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.sta_wpa_keyerr.sta_mac, pEntry->Addr, MAC_ADDR_LEN); + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_WPA_KEYERR, + NULL, (PUCHAR)&drvevnt.data.sta_wpa_keyerr, sizeof(drvevnt.data.sta_wpa_keyerr)); + } +#endif /* SMART_MESH_MONITOR */ + return FALSE; +} + + +/* + ========================================================================== + Description: + This is a function to initilize 4-way handshake + + Return: + + ========================================================================== +*/ +VOID WPAStart4WayHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval) +{ + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PUINT8 pBssid = NULL; + UCHAR group_cipher = Ndis802_11WEPDisabled; +#ifdef CONFIG_AP_SUPPORT + MULTISSID_STRUCT *pMbss; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) { + Adhoc_WpaStart4WayHS(pAd, pEntry, TimeInterval); + return; + } + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); + return; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The entry doesn't exist.\n")); + return; + } + + pMbss = (MULTISSID_STRUCT *)pEntry->wdev->func_dev; + + if (pEntry->wdev != &pMbss->wdev) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : cannot get binding wdev(%p).\n", pEntry->wdev)); + return; + } + + /* pointer to the corresponding position*/ + pBssid = pMbss->wdev.bssid; + group_cipher = pMbss->wdev.GroupKeyWepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pBssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); + return; + } + + /* Check the status*/ + if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n")); + return; + } + +#ifdef WSC_AP_SUPPORT + if (MAC_ADDR_EQUAL(pEntry->Addr, pMbss->WscControl.EntryAddr) && + pMbss->WscControl.EapMsgRunning) + { + pEntry->WpaState = AS_NOTUSE; + DBGPRINT(RT_DEBUG_ERROR, ("This is a WSC-Enrollee. Not expect calling WPAStart4WayHS here \n")); + return; + } +#endif /* WSC_AP_SUPPORT */ + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Randomly generate ANonce */ + GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce); + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 1*/ + /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_1, + 0, /* Default key index*/ + pEntry->ANonce, + NULL, /* TxRSC*/ + NULL, /* GTK*/ + NULL, /* RSNIE*/ + 0, /* RSNIE length */ + pEapolFrame); + +#ifdef CONFIG_AP_SUPPORT + /* If PMKID match in WPA2-enterprise mode, fill PMKID into Key data field and update PMK here */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)) + { + /* Fill in value for KDE */ + pEapolFrame->KeyDesc.KeyData[0] = 0xDD; + pEapolFrame->KeyDesc.KeyData[2] = 0x00; + pEapolFrame->KeyDesc.KeyData[3] = 0x0F; + pEapolFrame->KeyDesc.KeyData[4] = 0xAC; + pEapolFrame->KeyDesc.KeyData[5] = 0x04; + + NdisMoveMemory(&pEapolFrame->KeyDesc.KeyData[6], &pMbss->PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMKID, LEN_PMKID); + NdisMoveMemory(&pMbss->PMK, &pMbss->PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMK, PMK_LEN); + + pEapolFrame->KeyDesc.KeyData[1] = 0x14;/* 4+LEN_PMKID*/ + INC_UINT16_TO_ARRARY(pEapolFrame->KeyDesc.KeyDataLen, 6 + LEN_PMKID); + INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID); + } +#ifdef DOT11W_PMF_SUPPORT + else if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + { + UCHAR digest[80], PMK_key[20]; + PKEY_DESCRIPTER pKeyDesc = &pEapolFrame->KeyDesc; + + pKeyDesc->KeyData[0] = 0xDD; + pKeyDesc->KeyData[2] = 0x00; + pKeyDesc->KeyData[3] = 0x0F; + pKeyDesc->KeyData[4] = 0xAC; + pKeyDesc->KeyData[5] = 0x04; + + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pMbss->wdev.bssid, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN); + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256)) + { + DBGPRINT(RT_DEBUG_TRACE, ("[PMF]%s: send Msg1 of 4-way using SHA256\n", __FUNCTION__)); + RT_HMAC_SHA256(pMbss->PMK, PMK_LEN, PMK_key, 20, digest, LEN_PMKID); + } + else { + DBGPRINT(RT_DEBUG_TRACE, ("[PMF]%s: send Msg1 of 4-way using SHA1\n", __FUNCTION__)); + RT_HMAC_SHA1(pMbss->PMK, PMK_LEN, PMK_key, 20, digest, LEN_PMKID); + } + + NdisMoveMemory(&pKeyDesc->KeyData[6], digest, LEN_PMKID); + pKeyDesc->KeyData[1] = 0x14;// 4+LEN_PMKID + INC_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, 6 + LEN_PMKID); + INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID); + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, + LENGTH_802_3, (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + /* Trigger Retry Timer*/ + RTMPModTimer(&pEntry->RetryTimer, TimeInterval); + + /* Update State*/ + pEntry->WpaState = AS_PTKSTART; + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart4WayHS: send Msg1 of 4-way \n")); + +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID PeerPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PTK[80]; + UCHAR Header802_3[14]; + PEAPOL_PACKET pMsg1; + UINT MsgLen; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PUINT8 pCurrentAddr = NULL; + PUINT8 pmk_ptr = NULL; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 rsnie_ptr = NULL; + UCHAR rsnie_len = 0; +#ifdef MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + UINT IfIndex = 0; + + IfIndex = pEntry->wdev_idx; +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + CliIdx = ((ifIndex - 64) % 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if (IfIndex >= MAX_APCLI_NUM) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].RepeaterCli[CliIdx].CurrentAddress; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].wdev.if_addr; + pmk_ptr = pAd->ApCfg.ApCliTab[IfIndex].PMK; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + rsnie_ptr = pAd->ApCfg.ApCliTab[IfIndex].RSN_IE; + rsnie_len = pAd->ApCfg.ApCliTab[IfIndex].RSNIE_Len; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + { + pCurrentAddr = pAd->CurrentAddress; + pmk_ptr = pAd->StaCfg.PMK; + group_cipher = pAd->StaCfg.GroupCipher; + rsnie_ptr = pAd->StaCfg.RSN_IE; + rsnie_len = pAd->StaCfg.RSNIE_Len; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pCurrentAddr == NULL) + return; + + /* Store the received frame*/ + pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 1 - Replay Counter*/ + if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE) + return; + + /* Store Replay counter, it will use to verify message 3 and construct message 2*/ + NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Store ANonce*/ + NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + /* Generate random SNonce*/ + GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce); + pEntry->AllowInsPTK = TRUE; + pEntry->LastGroupKeyId = 0; + pEntry->AllowUpdateRSC = FALSE; + NdisZeroMemory(pEntry->LastGTK, MAX_LEN_GTK); + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + UINT8 ptk_len; + + FT_DerivePMKR0(pmk_ptr, + LEN_PMK, + (PUINT8)pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen, + pAd->StaCfg.Dot11RCommInfo.MdIeInfo.MdId, + pAd->StaCfg.Dot11RCommInfo.R0khId, + pAd->StaCfg.Dot11RCommInfo.R0khIdLen, + pCurrentAddr, + pAd->StaCfg.Dot11RCommInfo.PMKR0, + pAd->StaCfg.Dot11RCommInfo.PMKR0Name); + + FT_DerivePMKR1(pAd->StaCfg.Dot11RCommInfo.PMKR0, + pAd->StaCfg.Dot11RCommInfo.PMKR0Name, + pEntry->Addr, + pCurrentAddr, + pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME); + + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + ptk_len = 32+32; + else + ptk_len = 32+16; + + FT_DerivePTK(pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME, + pEntry->ANonce, + pEntry->SNonce, + pAd->CommonCfg.Bssid, + pCurrentAddr, + ptk_len, + pEntry->PTK, + pEntry->PTK_NAME); + + } +#endif /* CONFIG_STA_SUPPORT */ + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256))) + { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, + pCurrentAddr, + PTK, + LEN_AES_PTK); /* Must is 48 bytes */ + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } + else +#endif /* DOT11W_PMF_SUPPORT */ + { + /* Calculate PTK(ANonce, SNonce)*/ + WpaDerivePTK(pAd, + pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, + pCurrentAddr, + PTK, + LEN_PTK); + + /* Save key to PTK entry*/ + NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); + } + + /* Update WpaState*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 2*/ + /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2)*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_2, + 0, /* DefaultKeyIdx*/ + pEntry->SNonce, + NULL, /* TxRsc*/ + NULL, /* GTK*/ + (UCHAR *)rsnie_ptr, + rsnie_len, + pEapolFrame); + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, TRUE); + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); +} + + +/* + ========================================================================== + Description: + When receiving the second packet of 4-way pairwisekey handshake. + Return: + ========================================================================== +*/ +VOID PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PTK[80]; + BOOLEAN Cancelled; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pMsg2; + UINT MsgLen; + UCHAR Header802_3[LENGTH_802_3]; + UCHAR TxTsc[6]; + PUINT8 pBssid = NULL; + PUINT8 pmk_ptr = NULL; + PUINT8 gtk_ptr = NULL; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 rsnie_ptr = NULL; + UCHAR rsnie_len = 0; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = 0; +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + /* check Entry in valid State*/ + if (pEntry->WpaState < AS_PTKSTART) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + struct wifi_dev *wdev; + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + pBssid = wdev->bssid; + pmk_ptr = pAd->ApCfg.MBSSID[apidx].PMK; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + group_cipher = wdev->GroupKeyWepStatus; + default_key = wdev->DefaultKeyId; + + /* Get Group TxTsc form Asic*/ + RTMPGetTxTscFromAsic(pAd, apidx, TxTsc); + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + else + { + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[1][0]; + } + else + { +#ifdef CONFIG_HOTSPOT_R2 + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.bASANEnable == 1) + { + printk("choose OSEN\n"); + rsnie_len = OSEN_IELEN; + rsnie_ptr = OSEN_IE; + } + else +#endif + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + /* skip 802.11_header(24-byte) and LLC_header(8) */ + pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Store SNonce*/ + NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UINT8 ptk_len; + + FT_DerivePMKR0(pmk_ptr, LEN_PMK, + (PUINT8)pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khIdLen, + pEntry->Addr, + pEntry->FT_PMK_R0, + pEntry->FT_PMK_R0_NAME); + + FT_DerivePMKR1(pEntry->FT_PMK_R0, + pEntry->FT_PMK_R0_NAME, + pAd->ApCfg.MBSSID[apidx].wdev.bssid, /* R1KHID*/ + pEntry->Addr, /* S1KHID*/ + pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME); + + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + ptk_len = 32+32; + else + ptk_len = 32+16; + + FT_DerivePTK(pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME, + pEntry->ANonce, + pEntry->SNonce, + pAd->ApCfg.MBSSID[apidx].wdev.bssid, /* Bssid*/ + pEntry->Addr, /* sta mac*/ + ptk_len, + pEntry->PTK, + pEntry->PTK_NAME); + + } +#endif /* CONFIG_AP_SUPPORT */ + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256))) + { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + (UCHAR *)pBssid, + pEntry->SNonce, + pEntry->Addr, + PTK, + LEN_AES_PTK); /* Must is 48 bytes */ + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } + else +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE)) + { + printk("got msg2 derivePTK\n"); + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + (UCHAR *)pBssid, + pEntry->SNonce, + pEntry->Addr, + PTK, + LEN_AES_PTK); /* Must is 48 bytes */ + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } + else +#endif /* CONFIG_HOTSPOT_R2 */ + { + /* Derive PTK*/ + if ((pmk_ptr == NULL) || (pBssid == NULL)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pmk_ptr or pBssid == NULL!\n", __FUNCTION__)); + return; + } + + WpaDerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, /* ANONCE*/ + (UCHAR *)pBssid, + pEntry->SNonce, /* SNONCE*/ + pEntry->Addr, + PTK, + LEN_PTK); + + NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); + } + + /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE*/ + if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE) + return; + + do + { +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + UCHAR HSClientGTK[32]; +#endif + + /* Allocate memory for input*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* delete retry timer*/ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* Change state*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable && + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.DGAFDisable) + { + // Radom GTK for hotspot sation client */ + GenRandom(pAd, pEntry->Addr, HSClientGTK); + gtk_ptr = HSClientGTK; + + DBGPRINT(RT_DEBUG_OFF, ("%s:Random unique GTK for each mobile device when dgaf disable\n", __FUNCTION__)); + hex_dump("GTK", gtk_ptr, 32); + } +#endif + /* Construct EAPoL message - Pairwise Msg 3*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_3, + default_key, + pEntry->ANonce, + TxTsc, + (UCHAR *)gtk_ptr, + (UCHAR *)rsnie_ptr, + rsnie_len, + pEapolFrame); + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR; + RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG1_RETRY_EXEC_INTV); + + /* Update State*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + os_free_mem(NULL, mpool); + + }while(FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); +} + +VOID WPAPairMsg3Retry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval +) +{ + BOOLEAN Cancelled; + PEAPOL_PACKET pEapolFrame; + UCHAR *mpool; + PUINT8 pBssid = NULL; + PUINT8 gtk_ptr = NULL; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 rsnie_ptr = NULL; + UCHAR rsnie_len = 0; + UCHAR TxTsc[6]; + UCHAR Header802_3[LENGTH_802_3]; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = 0; +#endif /* CONFIG_AP_SUPPORT */ +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + UCHAR HSClientGTK[32]; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s \n",__FUNCTION__)); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + struct wifi_dev *wdev; + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + pBssid = wdev->bssid; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + group_cipher = wdev->GroupKeyWepStatus; + default_key = wdev->DefaultKeyId; + + /* Get Group TxTsc form Asic*/ + RTMPGetTxTscFromAsic(pAd, apidx, TxTsc); + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + else + { + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Allocate memory for input*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* delete retry timer*/ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* Change state*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable && + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.DGAFDisable) + { + // Radom GTK for hotspot sation client */ + GenRandom(pAd, pEntry->Addr, HSClientGTK); + gtk_ptr = HSClientGTK; + + DBGPRINT(RT_DEBUG_OFF, ("%s:Random unique GTK for each mobile device when dgaf disable\n", __FUNCTION__)); + hex_dump("GTK", gtk_ptr, 32); + } +#endif + /* Construct EAPoL message - Pairwise Msg 3*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_3, + default_key, + pEntry->ANonce, + TxTsc, + (UCHAR *)gtk_ptr, + (UCHAR *)rsnie_ptr, + rsnie_len, + pEapolFrame); + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + RTMPSetTimer(&pEntry->RetryTimer, TimeInterval); + + /* Update State*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + os_free_mem(NULL, mpool); + +} +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID PeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pMsg3; + UINT MsgLen; + PUINT8 pCurrentAddr = NULL; + UCHAR group_cipher = Ndis802_11WEPDisabled; +#ifdef MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + UCHAR idx = 0; + BOOLEAN bWPA2 = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + UINT IfIndex = 0; + + IfIndex = pEntry->wdev_idx; +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + CliIdx = ((ifIndex - 64) % 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if (IfIndex >= MAX_APCLI_NUM) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].RepeaterCli[CliIdx].CurrentAddress; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].wdev.if_addr; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + { + pCurrentAddr = pAd->CurrentAddress; + group_cipher = pAd->StaCfg.GroupCipher; + + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pCurrentAddr == NULL) + return; + + /* Record 802.11 header & the received EAPOL packet Msg3*/ + pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE*/ + if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE) + return; + + if (group_cipher == Ndis802_11AESEnable) + bWPA2 = TRUE; + if ((pEntry->AllowInsPTK == TRUE) && bWPA2) { + pEntry->CCMP_BC_PN = 0; + pEntry->init_ccmp_bc_pn_passed = FALSE; + for (idx = 0; idx < LEN_KEY_DESC_RSC; idx++) + pEntry->CCMP_BC_PN += (pMsg3->KeyDesc.KeyRsc[idx] << (idx*8)); + pEntry->AllowUpdateRSC = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): update CCMP_BC_PN to %llu\n", + __func__, pEntry->wcid, pEntry->CCMP_BC_PN )); + } + + /* Save Replay counter, it will use construct message 4*/ + NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Double check ANonce*/ + if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + { + return; + } + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 4*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_4, + 0, /* group key index not used in message 4*/ + NULL, /* Nonce not used in message 4*/ + NULL, /* TxRSC not used in message 4*/ + NULL, /* GTK not used in message 4*/ + NULL, /* RSN IE not used in message 4*/ + 0, + pEapolFrame); + + /* Update WpaState*/ + pEntry->WpaState = AS_PTKINITDONE; + /* Update pairwise key */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) { + if(pEntry->AllowInsPTK == TRUE) { + APCliInstallPairwiseKey(pAd, pEntry); + pEntry->AllowInsPTK = FALSE; + pEntry->AllowUpdateRSC = TRUE; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : the M3 reinstall attack, skip install key\n", + __func__)); + } + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + { + NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); + WPAInstallPairwiseKey(pAd, + BSS0, + pEntry, + FALSE); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* open 802.1x port control and privacy filter*/ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || + pEntry->AuthMode == Ndis802_11AuthModeWPA2) + { + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliConnectState = 2; + } +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Apcli auto connected:PeerPairMsg3Action() \n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef MWDS + if(pEntry && + IS_ENTRY_APCLI(pEntry) && + (pEntry->wdev_idx < MAX_APCLI_NUM)) + { + if(pAd->ApCfg.ApCliTab[pEntry->wdev_idx].MlmeAux.bSupportMWDS && + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].bSupportMWDS) + { + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].bEnableMWDS = TRUE; + pEntry->bEnableMWDS = TRUE; + if((pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + SET_MWDS_OPMODE_APCLI(pEntry); + DBGPRINT(RT_DEBUG_ERROR, ("SET_MWDS_OPMODE_APCLI OK!\n")); + } + } + else + { + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].bEnableMWDS = FALSE; + pEntry->bEnableMWDS = FALSE; + SET_MWDS_OPMODE_NONE(pEntry); + } + } +#endif /* MWDS */ + +#ifdef SMART_MESH_MONITOR + if (IS_ENTRY_APCLI(pEntry) && + (pEntry->wdev_idx < MAX_APCLI_NUM) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.linkstate.type = NSMPIF_DRVEVNT_EXT_UPLINK_STAT; + drvevnt.data.linkstate.link_state = NSMP_UPLINK_STAT_CONNECTED; + NdisCopyMemory(drvevnt.data.linkstate.bssid,pEntry->wdev->bssid,MAC_ADDR_LEN); + drvevnt.data.linkstate.channel = pAd->CommonCfg.Channel; + NdisZeroMemory(drvevnt.data.linkstate.op_channels,sizeof(drvevnt.data.linkstate.op_channels)); + drvevnt.data.linkstate.op_channels[0] = pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + drvevnt.data.linkstate.op_channels[1] = N_GetSecondaryChannel(pAd); +#endif /* DOT11_N_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_EXT_UPLINK_STAT, + NULL, (PUCHAR)&drvevnt.data.linkstate, sizeof(drvevnt.data.linkstate)); + } +#endif /* SMART_MESH_MONITOR */ +#endif /* APLCI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + STA_PORT_SECURED(pAd); +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", + GetAuthMode(pEntry->AuthMode), + GetEncryptType(pEntry->WepStatus), + GetEncryptType(group_cipher))); + } + else + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + /* Patch issue with gateway AP*/ + /* In WPA mode, AP doesn't send out message 1 of group-key HS.*/ + /* So, Supplicant shall maintain a timeout action to disconnect */ + /* this link.*/ + /* Todo - Does it need to apply to STA ?*/ + if (IS_ENTRY_APCLI(pEntry)) + RTMPSetTimer(&pEntry->RetryTimer, PEER_GROUP_KEY_UPDATE_INIV); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* Init 802.3 header and send out*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, TRUE); + + os_free_mem(NULL, mpool); + + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n")); +} + +/* + ========================================================================== + Description: + When receiving the last packet of 4-way pairwisekey handshake. + Initilize 2-way groupkey handshake following. + Return: + ========================================================================== +*/ +VOID PeerPairMsg4Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + PEAPOL_PACKET pMsg4; + UINT MsgLen; + BOOLEAN Cancelled; + UCHAR group_cipher = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n")); + + do + { + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + break; + + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG ) ) + break; + + if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING) + break; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR apidx = 0; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + break; + else + apidx = pEntry->apidx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ + + /* skip 802.11_header(24-byte) and LLC_header(8) */ + pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC*/ + if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE) + break; + + /* 3. Install pairwise key */ + WPAInstallPairwiseKey(pAd, pEntry->apidx, pEntry, TRUE); + + /* 4. upgrade state */ + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->WpaState = AS_PTKINITDONE; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + +#ifdef WSC_AP_SUPPORT + if (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) + WscInformFromWPA(pEntry); +#endif /* WSC_AP_SUPPORT */ + + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + { + pEntry->GTKState = REKEY_ESTABLISHED; + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + PFT_R1HK_ENTRY pR1khEntry; + PUINT8 pUCipher = NULL; + PUINT8 pAkm = NULL; + UINT8 count; + + pUCipher = WPA_ExtractSuiteFromRSNIE(pEntry->RSN_IE, pEntry->RSNIE_Len, PAIRWISE_SUITE, &count); + pAkm = WPA_ExtractSuiteFromRSNIE(pEntry->RSN_IE, pEntry->RSNIE_Len, AKM_SUITE, &count); + + /* Record the PMK-R0 related information */ + RTMPAddPMKIDCache(pAd, + pEntry->apidx, + pEntry->Addr, + pEntry->FT_PMK_R0_NAME, + pEntry->FT_PMK_R0); + + /* Delete previous entry */ + pR1khEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1khEntry != NULL) + { + FT_R1khEntryDelete(pAd, pR1khEntry); + } + /* Update R1KH table */ + if (pUCipher != NULL) + NdisMoveMemory(pEntry->FT_UCipher, pUCipher, 4); + if (pAkm != NULL) + NdisMoveMemory(pEntry->FT_Akm, pAkm, 4); + + FT_R1khEntryInsert(pAd, + pEntry->FT_PMK_R0_NAME, + pEntry->FT_PMK_R1_NAME, + pEntry->FT_PMK_R1, + pUCipher, + pAkm, + (pAd->ApCfg.MBSSID[pEntry->apidx].PMKCachePeriod/OS_HZ), + 20, + pAd->ApCfg.MBSSID[pEntry->apidx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[pEntry->apidx].FtCfg.FtR0khIdLen, + pEntry->Addr); + +#ifdef IAPP_SUPPORT + { + FT_KDP_EVT_ASSOC EvtAssoc; + + EvtAssoc.SeqNum = 0; + NdisMoveMemory(EvtAssoc.MacAddr, pEntry->Addr, MAC_ADDR_LEN); + + FT_KDP_EVENT_INFORM(pAd, + pEntry->apidx, + FT_KDP_SIG_FT_ASSOCIATION, + &EvtAssoc, + sizeof(EvtAssoc), + NULL); + } +#endif /* IAPP_SUPPORT */ + + pR1khEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1khEntry != NULL) + { + pR1khEntry->AuthMode = pEntry->AuthMode; + hex_dump("R1KHTab-R0KHID", pR1khEntry->R0khId, pR1khEntry->R0khIdLen); + hex_dump("R1KHTab-PairwiseCipher", pR1khEntry->PairwisChipher, 4); + hex_dump("R1KHTab-AKM", pR1khEntry->AkmSuite, 4); + hex_dump("R1KHTab-PMKR0Name", pR1khEntry->PmkR0Name, 16); + hex_dump("R1KHTab-PMKR1Name", pR1khEntry->PmkR1Name, 16); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("The entry in R1KH table doesn't exist\n")); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT1X_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2) + { + UCHAR PMK_key[20]; + UCHAR digest[80]; + + /* Calculate PMKID, refer to IEEE 802.11i-2004 8.5.1.2*/ + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN); + RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].PMK, PMK_LEN, PMK_key, 20, digest, SHA1_DIGEST_SIZE); + RTMPAddPMKIDCache(pAd, pEntry->apidx, pEntry->Addr, digest, pAd->ApCfg.MBSSID[pEntry->apidx].PMK); + DBGPRINT(RT_DEBUG_TRACE, ("Calc PMKID=%02x:%02x:%02x:%02x:%02x:%02x\n", digest[0],digest[1],digest[2],digest[3],digest[4],digest[5])); + } +#endif /* DOT1X_SUPPORT */ +#ifdef MWDS + if((pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + MWDSProxyEntryDelete(pAd,pEntry->Addr); + if(pEntry->bEnableMWDS) + { + SET_MWDS_OPMODE_AP(pEntry); + MWDSConnEntryUpdate(pAd,pEntry->wcid); + DBGPRINT(RT_DEBUG_ERROR, ("SET_MWDS_OPMODE_AP OK!\n")); + } + else + SET_MWDS_OPMODE_NONE(pEntry); + } +#endif /* MWDS */ +#ifdef SMART_MESH_MONITOR + if (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.join.type = NSMPIF_DRVEVNT_STA_JOIN; + drvevnt.data.join.channel = pAd->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.join.sta_mac, pEntry->Addr, MAC_ADDR_LEN); + drvevnt.data.join.aid= pEntry->Aid; + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_JOIN, + NULL, (PUCHAR)&drvevnt.data.join, sizeof(drvevnt.data.join)); + } +#endif /* SMART_MESH_MONITOR */ +#endif /* CONFIG_AP_SUPPORT */ + + /* send wireless event - for set key done WPA2*/ + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry->IsWNMReqValid == TRUE) + { + struct wnm_req_data *req_data = pEntry->ReqData; + Send_WNM_Notify_Req(pAd, + req_data->peer_mac_addr, + req_data->wnm_req, + req_data->wnm_req_len, + req_data->type); + + pEntry->IsWNMReqValid = FALSE; + os_free_mem(NULL, req_data); + printk("!!!!msg 4 send wnm req\n"); + } + if (pEntry->IsBTMReqValid == TRUE) + { + struct btm_req_data *req_data = pEntry->ReqbtmData; + Send_BTM_Req(pAd, + req_data->peer_mac_addr, + req_data->btm_req, + req_data->btm_req_len); + + pEntry->IsBTMReqValid = FALSE; + os_free_mem(NULL, req_data); + printk("!!!!msg 4 send btm req\n"); + } +#endif + + + DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), + group_cipher, + GetEncryptType(group_cipher))); + } + else + { + /* 5. init Group 2-way handshake if necessary.*/ + WPAStart2WayGroupHS(pAd, pEntry); + + pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + /* retry timer is set inside WPAStart2WayGroupHS */ + //RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + } + }while(FALSE); + +} + +/* + ========================================================================== + Description: + This is a function to send the first packet of 2-way groupkey handshake + Return: + + ========================================================================== +*/ +VOID WPAStart2WayGroupHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR Header802_3[14]; + UCHAR TxTsc[6]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + UCHAR group_cipher = Ndis802_11WEPDisabled; + UCHAR default_key = 0; + PUINT8 gnonce_ptr = NULL; + PUINT8 gtk_ptr = NULL; + PUINT8 pBssid = NULL; + BOOLEAN Cancelled; + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + /* delete retry timer*/ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR apidx = 0; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; + default_key = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId; + gnonce_ptr = pAd->ApCfg.MBSSID[apidx].GNonce; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + pBssid = pAd->ApCfg.MBSSID[apidx].wdev.bssid; + + /* Get Group TxTsc form Asic*/ + RTMPGetTxTscFromAsic(pAd, apidx, TxTsc); + } +#endif /* CONFIG_AP_SUPPORT */ + + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Construct EAPoL message - Group Msg 1*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_GROUP_MSG_1, + default_key, + (UCHAR *)gnonce_ptr, + TxTsc, + (UCHAR *)gtk_ptr, + NULL, + 0, + pEapolFrame); + + /* Make outgoing frame*/ + if (pBssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBssid == NULL!\n", __FUNCTION__)); + return; + } + + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE); + + os_free_mem(NULL, mpool); + + RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG1_RETRY_EXEC_INTV); + DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n")); + + return; +} + +/* + ======================================================================== + + Routine Description: + Process Group key 2-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID PeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pGroup; + UINT MsgLen; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 pCurrentAddr = NULL; +#ifdef APCLI_SUPPORT + BOOLEAN Cancelled; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + UCHAR idx = 0; + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + CliIdx = ((ifIndex - 64) % 16); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + UINT IfIndex = 0; + + IfIndex = pEntry->wdev_idx; + if (IfIndex >= MAX_APCLI_NUM) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].RepeaterCli[CliIdx].CurrentAddress; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].wdev.if_addr; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + default_key = pAd->ApCfg.ApCliTab[IfIndex].wdev.DefaultKeyId; + + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pCurrentAddr = pAd->CurrentAddress; + group_cipher = pAd->StaCfg.GroupCipher; + default_key = pAd->StaCfg.wdev.DefaultKeyId; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pCurrentAddr == NULL) + return; + + /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)*/ + pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE*/ + if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) == FALSE) + return; + if (pEntry->AllowUpdateRSC == TRUE) { + pEntry->CCMP_BC_PN = 0; + pEntry->init_ccmp_bc_pn_passed = FALSE; + for (idx = 0; idx < LEN_KEY_DESC_RSC; idx++) + pEntry->CCMP_BC_PN += (pGroup->KeyDesc.KeyRsc[idx] << (idx*8)); + pEntry->AllowUpdateRSC = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): update CCMP_BC_PN to %llu\n", + __func__, pEntry->wcid, pEntry->CCMP_BC_PN )); + } + + /* delete retry timer*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + /* Patch issue with gateway AP*/ + /* In WPA mode, AP doesn't send out message 1 of group-key HS.*/ + /* So, Supplicant shall maintain a timeout action to disconnect */ + /* this link.*/ + /* Todo - Does it need to apply to STA ?*/ + if (IS_ENTRY_APCLI(pEntry)) + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Save Replay counter, it will use to construct message 2*/ + NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + + /* Construct EAPoL message - Group Msg 2*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_GROUP_MSG_2, + default_key, + NULL, /* Nonce not used*/ + NULL, /* TxRSC not used*/ + NULL, /* GTK not used*/ + NULL, /* RSN IE not used*/ + 0, + pEapolFrame); + + /* open 802.1x port control and privacy filter*/ + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliConnectState = 2; + } +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Apcli auto connected:PeerGroupMsg1Action() \n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#ifdef MWDS + if(pEntry && + IS_ENTRY_APCLI(pEntry) && + (pEntry->wdev_idx < MAX_APCLI_NUM)) + { + if(pAd->ApCfg.ApCliTab[pEntry->wdev_idx].MlmeAux.bSupportMWDS && + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].bSupportMWDS) + { + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].bEnableMWDS = TRUE; + pEntry->bEnableMWDS = TRUE; + if((pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + SET_MWDS_OPMODE_APCLI(pEntry); + DBGPRINT(RT_DEBUG_ERROR, ("SET_MWDS_OPMODE_APCLI OK!\n")); + } + } + else + { + pAd->ApCfg.ApCliTab[pEntry->wdev_idx].bEnableMWDS = FALSE; + pEntry->bEnableMWDS = FALSE; + SET_MWDS_OPMODE_NONE(pEntry); + } + } +#endif /* MWDS */ + +#ifdef SMART_MESH_MONITOR + if (IS_ENTRY_APCLI(pEntry) && + (pEntry->wdev_idx < MAX_APCLI_NUM) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.linkstate.type = NSMPIF_DRVEVNT_EXT_UPLINK_STAT; + drvevnt.data.linkstate.link_state = NSMP_UPLINK_STAT_CONNECTED; + NdisCopyMemory(drvevnt.data.linkstate.bssid,pEntry->wdev->bssid,MAC_ADDR_LEN); + drvevnt.data.linkstate.channel = pAd->CommonCfg.Channel; + NdisZeroMemory(drvevnt.data.linkstate.op_channels,sizeof(drvevnt.data.linkstate.op_channels)); + drvevnt.data.linkstate.op_channels[0] = pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + drvevnt.data.linkstate.op_channels[1] = N_GetSecondaryChannel(pAd); +#endif /* DOT11_N_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_EXT_UPLINK_STAT, + NULL, (PUCHAR)&drvevnt.data.linkstate, sizeof(drvevnt.data.linkstate)); + } +#endif /* SMART_MESH_MONITOR */ +#endif /* APLCI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + STA_PORT_SECURED(pAd); +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", + GetAuthMode(pEntry->AuthMode), + GetEncryptType(pEntry->WepStatus), + GetEncryptType(group_cipher))); + + /* init header and Fill Packet and send Msg 2 to authenticator */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (pAd->MlmeAux.Channel == pAd->CommonCfg.Channel) + ) + { + /* Now stop the scanning and need to send the rekey packet out */ + pAd->MlmeAux.Channel = 0; + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE); + + os_free_mem(NULL, mpool); + + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: send group message 2\n")); +} + + +VOID EnqueueStartForPSKExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (PMAC_TABLE_ENTRY) FunctionContext; + + if ((pEntry) && IS_ENTRY_CLIENT(pEntry) && (pEntry->WpaState < AS_PTKSTART)) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + switch (pEntry->EnqueueEapolStartTimerRunning) + { + case EAPOL_START_PSK: + DBGPRINT(RT_DEBUG_TRACE, ("Enqueue EAPoL-Start-PSK for sta(%02x:%02x:%02x:%02x:%02x:%02x) \n", PRINT_MAC(pEntry->Addr))); + +#ifdef EAPOL_QUEUE_SUPPORT + EAPMlmeEnqueue(pAd, WPA_STATE_MACHINE, MT2_EAPOLStart, 6, &pEntry->Addr, 0); +#else /* EAPOL_QUEUE_SUPPORT */ + MlmeEnqueue(pAd, WPA_STATE_MACHINE, MT2_EAPOLStart, 6, &pEntry->Addr, 0); +#endif /* !EAPOL_QUEUE_SUPPORT */ + RTMP_MLME_HANDLER(pAd); + break; +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT1X_SUPPORT + case EAPOL_START_1X: + DBGPRINT(RT_DEBUG_TRACE, ("Enqueue EAPoL-Start-1X for sta(%02x:%02x:%02x:%02x:%02x:%02x) \n", PRINT_MAC(pEntry->Addr))); + + DOT1X_EapTriggerAction(pAd, pEntry); + break; +#endif /* DOT1X_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + default: + break; + + } + } + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + +} + + +VOID MlmeDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT Reason, + IN BOOLEAN bDataFrameFirst) +{ + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + HEADER_802_11 DeAuthHdr; + NDIS_STATUS NStatus; + + if (pEntry) + { + /* Send out a Deauthentication request frame*/ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + /* send wireless event - for send disassication */ + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_TRACE, + ("Send DEAUTH frame with ReasonCode(%d) to %02x:%02x:%02x:%02x:%02x:%02x \n", + Reason, PRINT_MAC(pEntry->Addr))); + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, pEntry->wdev->if_addr, pEntry->bssid); +#else +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* P2P_SUPPORT */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + +#ifdef DOT11W_PMF_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + ULONG TmpLen; + UINT res_len = LEN_CCMP_HDR + LEN_CCMP_MIC; + UCHAR res_buf[res_len]; + + /* reserve a buffer for PMF CCMP calculation later */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + res_len, res_buf, + END_OF_ARGS); + FrameLen += TmpLen; + + /* Indicate this is a unicast Robust management frame */ + DeAuthHdr.FC.Wep = 1; + } +#endif /* DOT11_PMF_SUPPORT */ + + + if (bDataFrameFirst) + MiniportMMRequest(pAd, MGMT_USE_QUEUE_FLAG, pOutBuffer, FrameLen); + else + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + /* ApLogEvent(pAd, pEntry->Addr, EVENT_DISASSOCIATED);*/ + +#ifdef CONFIG_HOTSPOT_R2 + if (!pEntry->IsKeep) +#endif /* CONFIG_HOTSPOT_R2 */ + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } +} + + +/* + ========================================================================== + Description: + When receiving the last packet of 2-way groupkey handshake. + Return: + ========================================================================== +*/ +VOID PeerGroupMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN VOID *Msg, + IN UINT MsgLen) +{ + UINT Len; + PUCHAR pData; + BOOLEAN Cancelled; + PEAPOL_PACKET pMsg2; + UCHAR group_cipher = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + if (pEntry->WpaState != AS_PTKINITDONE) + return; + + + do + { + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR apidx = 0; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ + + pData = (PUCHAR)Msg; + pMsg2 = (PEAPOL_PACKET) (pData + LENGTH_802_1_H); + Len = MsgLen - LENGTH_802_1_H; + + /* Sanity Check peer group message 2 - Replay Counter, MIC*/ + if (PeerWpaMessageSanity(pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE) + break; + + /* 3. upgrade state*/ + + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + pEntry->GTKState = REKEY_ESTABLISHED; + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + /* send wireless event - for set key done WPA2*/ + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), + group_cipher, GetEncryptType(group_cipher))); + } + else + { +#ifdef MWDS + if((pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + MWDSProxyEntryDelete(pAd,pEntry->Addr); + if(pEntry->bEnableMWDS) + { + SET_MWDS_OPMODE_AP(pEntry); + MWDSConnEntryUpdate(pAd,pEntry->wcid); + DBGPRINT(RT_DEBUG_ERROR, ("SET_MWDS_OPMODE_AP OK!\n")); + } + else + SET_MWDS_OPMODE_NONE(pEntry); + } +#endif /* MWDS */ + + /* send wireless event - for set key done WPA*/ + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA1_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + +#ifdef SMART_MESH_MONITOR + if (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.join.type = NSMPIF_DRVEVNT_STA_JOIN; + drvevnt.data.join.channel = pAd->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.join.sta_mac, pEntry->Addr, MAC_ADDR_LEN); + drvevnt.data.join.aid= pEntry->Aid; + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_JOIN, + NULL, (PUCHAR)&drvevnt.data.join, sizeof(drvevnt.data.join)); + } +#endif /* SMART_MESH_MONITOR */ + + DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), + group_cipher, GetEncryptType(group_cipher))); + } + }while(FALSE); +} + +/* + ======================================================================== + + Routine Description: + Classify WPA EAP message type + + Arguments: + EAPType Value of EAP message type + MsgType Internal Message definition for MLME state machine + + Return Value: + TRUE Found appropriate message type + FALSE No appropriate message type + + IRQL = DISPATCH_LEVEL + + Note: + All these constants are defined in wpa_cmm.h + For supplicant, there is only EAPOL Key message avaliable + + ======================================================================== +*/ +BOOLEAN WpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType) +{ + switch (EAPType) + { + case EAPPacket: + *MsgType = MT2_EAPPacket; + break; + case EAPOLStart: + *MsgType = MT2_EAPOLStart; + break; + case EAPOLLogoff: + *MsgType = MT2_EAPOLLogoff; + break; + case EAPOLKey: + *MsgType = MT2_EAPOLKey; + break; + case EAPOLASFAlert: + *MsgType = MT2_EAPOLASFAlert; + break; + default: + return FALSE; + } + return TRUE; +} + +/** + * inc_iv_byte - Increment arbitrary length byte array + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the least byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ +void inc_iv_byte(UCHAR *iv, UINT len, UINT cnt) +{ + int pos = 0; + int carry = 0; + UCHAR pre_iv; + + while (pos < len) + { + pre_iv = iv[pos]; + + if (carry == 1) + iv[pos] ++; + else + iv[pos] += cnt; + + if (iv[pos] > pre_iv) + break; + + carry = 1; + pos++; + } + + if (pos >= len) + DBGPRINT(RT_DEBUG_WARN, ("!!! inc_iv_byte overflow !!!\n")); +} + + + +/* + ======================================================================== + + Routine Description: + The pseudo-random function(PRF) that hashes various inputs to + derive a pseudo-random value. To add liveness to the pseudo-random + value, a nonce should be one of the inputs. + + It is used to generate PTK, GTK or some specific random value. + + Arguments: + UCHAR *key, - the key material for HMAC_SHA1 use + INT key_len - the length of key + UCHAR *prefix - a prefix label + INT prefix_len - the length of the label + UCHAR *data - a specific data with variable length + INT data_len - the length of a specific data + INT len - the output lenght + + Return Value: + UCHAR *output - the calculated result + + Note: + 802.11i-2004 Annex H.3 + + ======================================================================== +*/ +VOID PRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *prefix, + IN INT prefix_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len) +{ + INT i; + UCHAR *input; + INT currentindex = 0; + INT total_len; + + /* Allocate memory for input*/ + os_alloc_mem(NULL, (PUCHAR *)&input, 1024); + + if (input == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n")); + return; + } + + /* Generate concatenation input*/ + NdisMoveMemory(input, prefix, prefix_len); + + /* Concatenate a single octet containing 0*/ + input[prefix_len] = 0; + + /* Concatenate specific data*/ + NdisMoveMemory(&input[prefix_len + 1], data, data_len); + total_len = prefix_len + 1 + data_len; + + /* Concatenate a single octet containing 0*/ + /* This octet shall be update later*/ + input[total_len] = 0; + total_len++; + + /* Iterate to calculate the result by hmac-sha-1*/ + /* Then concatenate to last result*/ + for (i = 0; i < (len + 19) / 20; i++) + { + RT_HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], SHA1_DIGEST_SIZE); + currentindex += 20; + + /* update the last octet */ + input[total_len - 1]++; + } + os_free_mem(NULL, input); +} + +/* +* F(P, S, c, i) = U1 xor U2 xor ... Uc +* U1 = PRF(P, S || Int(i)) +* U2 = PRF(P, U1) +* Uc = PRF(P, Uc-1) +*/ + +static void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output) +{ + unsigned char digest[36], digest1[SHA1_DIGEST_SIZE]; + int i, j, len; + + len = strlen(password); + + /* U1 = PRF(P, S || int(i)) */ + memcpy(digest, ssid, ssidlength); + digest[ssidlength] = (unsigned char)((count>>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + RT_HMAC_SHA1((unsigned char*) password, len, digest, ssidlength+4, digest1, SHA1_DIGEST_SIZE); /* for WPA update*/ + + /* output = U1 */ + memcpy(output, digest1, SHA1_DIGEST_SIZE); + for (i = 1; i < iterations; i++) + { + /* Un = PRF(P, Un-1) */ + RT_HMAC_SHA1((unsigned char*) password, len, digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update*/ + memcpy(digest1, digest, SHA1_DIGEST_SIZE); + + /* output = output xor Un */ + for (j = 0; j < SHA1_DIGEST_SIZE; j++) + { + output[j] ^= digest[j]; + } + } +} + +/* +* password - ascii string up to 63 characters in length +* ssid - octet string up to 32 octets +* ssidlength - length of ssid in octets +* output must be 40 octets in length and outputs 256 bits of key +*/ +int RtmpPasswordHash(PSTRING password, PUCHAR ssid, INT ssidlength, PUCHAR output) +{ + if ((strlen(password) > 63) || (ssidlength > 32)) + return 0; + + F(password, ssid, ssidlength, 4096, 1, output); + F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]); + return 1; +} + +/* + ======================================================================== + + Routine Description: + The key derivation function(KDF) is defined in IEEE 802.11r/D9.0, 8.5.1.5.2 + + Arguments: + + Return Value: + + Note: + Output KDF-Length (K, label, Context) where + Input: K, a 256-bit key derivation key + label, a string identifying the purpose of the keys derived using this KDF + Context, a bit string that provides context to identify the derived key + Length, the length of the derived key in bits + Output: a Length-bit derived key + + result "" + iterations (Length+255)/256 + do i = 1 to iterations + result result || HMAC-SHA256(K, i || label || Context || Length) + od + return first Length bits of result, and securely delete all unused bits + + In this algorithm, i and Length are encoded as 16-bit unsigned integers. + + ======================================================================== +*/ +VOID KDF( + IN PUINT8 key, + IN INT key_len, + IN PUINT8 label, + IN INT label_len, + IN PUINT8 data, + IN INT data_len, + OUT PUINT8 output, + IN USHORT len) +{ + USHORT i; + UCHAR *input; + INT currentindex = 0; + INT total_len; + UINT len_in_bits = (len << 3); + + os_alloc_mem(NULL, (PUCHAR *)&input, 1024); + + if (input == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!KDF: no memory!!!\n")); + return; + } + + NdisZeroMemory(input, 1024); + + /* Initial concatenated value (i || label || Context || Length)*/ + /* concatenate 16-bit unsigned integer, its initial value is 1. */ + input[0] = 1; + input[1] = 0; + total_len = 2; + + /* concatenate a prefix string*/ + NdisMoveMemory(&input[total_len], label, label_len); + total_len += label_len; + + /* concatenate the context*/ + NdisMoveMemory(&input[total_len], data, data_len); + total_len += data_len; + + /* concatenate the length in bits (16-bit unsigned integer)*/ + input[total_len] = (len_in_bits & 0xFF); + input[total_len + 1] = (len_in_bits & 0xFF00) >> 8; + total_len += 2; + + for (i = 1; i <= ((len_in_bits + 255) / 256); i++) + { + /* HMAC-SHA256 derives output */ + RT_HMAC_SHA256((UCHAR *)key, key_len, input, total_len, (UCHAR *)&output[currentindex], 32); + + currentindex += 32; /* next concatenation location*/ + input[0]++; /* increment octet count*/ + + } + os_free_mem(NULL, input); +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPDerivePMKID( + IN PUINT8 pAaddr, + IN PUINT8 pSpaddr, + IN PUINT8 pKey, + IN PUINT8 pAkm_oui, + OUT PUINT8 pPMKID) +{ + UCHAR digest[80], text_buf[20]; + UINT8 text_len; + + /* Concatenate the text for PMKID calculation*/ + NdisMoveMemory(&text_buf[0], "PMK Name", 8); + NdisMoveMemory(&text_buf[8], pAaddr, MAC_ADDR_LEN); + NdisMoveMemory(&text_buf[14], pSpaddr, MAC_ADDR_LEN); + text_len = 20; + +#ifdef DOT11W_PMF_SUPPORT +/* todo pmf*/ + /* When the negotiated AKM is 00-0F-AC:5 or 00-0F-AC:6, + HMAC-SHA-256 is used to calculate the PMKID */ + if (NdisEqualMemory(pAkm_oui, OUI_PMF_8021X_AKM, 4) || + NdisEqualMemory(pAkm_oui, OUI_PMF_PSK_AKM, 4)) + { + RT_HMAC_SHA256(pKey, PMK_LEN, text_buf, text_len, digest, SHA256_DIGEST_SIZE); + } + else +#endif /* DOT11W_PMF_SUPPPORT */ + { + RT_HMAC_SHA1(pKey, PMK_LEN, text_buf, text_len, digest, SHA1_DIGEST_SIZE); + } + + /* Truncate the first 128-bit of output result */ + NdisMoveMemory(pPMKID, digest, LEN_PMKID); + +} + + + +/* + ======================================================================== + + Routine Description: + It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. + It shall be called by 4-way handshake processing. + + Arguments: + pAd - pointer to our pAdapter context + PMK - pointer to PMK + ANonce - pointer to ANonce + AA - pointer to Authenticator Address + SNonce - pointer to SNonce + SA - pointer to Supplicant Address + len - indicate the length of PTK (octet) + + Return Value: + Output pointer to the PTK + + Note: + Refer to IEEE 802.11i-2004 8.5.1.2 + + ======================================================================== +*/ +VOID WpaDerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos = 0; + UCHAR temp[32]; + UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; + + /* initiate the concatenation input*/ + NdisZeroMemory(temp, sizeof(temp)); + NdisZeroMemory(concatenation, 76); + + /* Get smaller address*/ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(concatenation, AA, 6); + else + NdisMoveMemory(concatenation, SA, 6); + CurrPos += 6; + + /* Get larger address*/ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(&concatenation[CurrPos], SA, 6); + else + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + + /* store the larger mac address for backward compatible of */ + /* ralink proprietary STA-key issue */ + NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); + CurrPos += 6; + + /* Get smaller Nonce*/ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue*/ + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + CurrPos += 32; + + /* Get larger Nonce*/ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue*/ + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + CurrPos += 32; + + hex_dump("PMK", PMK, LEN_PMK); + hex_dump("concatenation=", concatenation, 76); + + /* Use PRF to generate PTK*/ + PRF(PMK, LEN_PMK, Prefix, 22, concatenation, 76, output, len); + +} + +VOID WpaDeriveGTK( + IN UCHAR *GMK, + IN UCHAR *GNonce, + IN UCHAR *AA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos=0; + UCHAR Prefix[19]; + UCHAR temp[80]; + + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + CurrPos += 6; + + NdisMoveMemory(&concatenation[CurrPos], GNonce , 32); + CurrPos += 32; + + Prefix[0] = 'G'; + Prefix[1] = 'r'; + Prefix[2] = 'o'; + Prefix[3] = 'u'; + Prefix[4] = 'p'; + Prefix[5] = ' '; + Prefix[6] = 'k'; + Prefix[7] = 'e'; + Prefix[8] = 'y'; + Prefix[9] = ' '; + Prefix[10] = 'e'; + Prefix[11] = 'x'; + Prefix[12] = 'p'; + Prefix[13] = 'a'; + Prefix[14] = 'n'; + Prefix[15] = 's'; + Prefix[16] = 'i'; + Prefix[17] = 'o'; + Prefix[18] = 'n'; + + PRF(GMK, PMK_LEN, Prefix, 19, concatenation, 38 , temp, len); + NdisMoveMemory(output, temp, len); +} + +/* + ======================================================================== + + Routine Description: + Generate random number by software. + + Arguments: + pAd - pointer to our pAdapter context + macAddr - pointer to local MAC address + + Return Value: + + Note: + 802.1ii-2004 Annex H.5 + + ======================================================================== +*/ +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random) +{ + INT i, curr; + UCHAR local[80], KeyCounter[32]; + UCHAR result[80]; + ULONG CurrentTime; + UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'}; + + /* Zero the related information*/ + NdisZeroMemory(result, 80); + NdisZeroMemory(local, 80); + NdisZeroMemory(KeyCounter, 32); + + for (i = 0; i < 32; i++) + { + /* copy the local MAC address*/ + COPY_MAC_ADDR(local, macAddr); + curr = MAC_ADDR_LEN; + + /* concatenate the current time*/ + NdisGetSystemUpTime(&CurrentTime); + NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); + curr += sizeof(CurrentTime); + + /* concatenate the last result*/ + NdisMoveMemory(&local[curr], result, 32); + curr += 32; + + /* concatenate a variable */ + NdisMoveMemory(&local[curr], &i, 2); + curr += 2; + + /* calculate the result*/ + PRF(KeyCounter, 32, prefix,12, local, curr, result, 32); + } + + NdisMoveMemory(random, result, 32); +} + +/* + ======================================================================== + + Routine Description: + Build cipher suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + WepStatus - indicate the encryption type + bMixCipher - a boolean to indicate the pairwise cipher and group + cipher are the same or not + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPMakeRsnIeCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT WepStatus, + IN UCHAR apidx, + IN BOOLEAN bMixCipher, + IN UCHAR FlexibleCipher, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + UCHAR PairwiseCnt; + + *rsn_len = 0; + + /* decide WPA2 or WPA1 */ + if (ElementID == Wpa2Ie) + { + RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; + + /* Assign the verson as 1*/ + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + /* TKIP mode*/ + case Ndis802_11TKIPEnable: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + /* AES mode*/ + case Ndis802_11AESEnable: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + /* TKIP-AES mix mode*/ + case Ndis802_11TKIPAESMix: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + + PairwiseCnt = 1; + /* Insert WPA2 TKIP as the first pairwise cipher */ + if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + /* Insert WPA2 AES as the secondary pairwise cipher*/ + if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnIe + sizeof(RSNIE2), OUI_WPA2_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + /* Insert WPA2 AES as the first pairwise cipher */ + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); + break; + } + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.GroupCipher != Ndis802_11TKIPEnable) && + (pAd->StaCfg.GroupCipher != Ndis802_11AESEnable) + ) + { + UINT GroupCipher = pAd->StaCfg.GroupCipher; + switch(GroupCipher) + { + case Ndis802_11GroupWEP40Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4); + break; + case Ndis802_11GroupWEP104Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4); + break; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* swap for big-endian platform*/ + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } + else + { + RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; + + /* Assign OUI and version*/ + NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + /* TKIP mode*/ + case Ndis802_11TKIPEnable: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + *rsn_len = sizeof(RSNIE); + break; + + /* AES mode*/ + case Ndis802_11AESEnable: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + *rsn_len = sizeof(RSNIE); + break; + + /* TKIP-AES mix mode*/ + case Ndis802_11TKIPAESMix: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + + PairwiseCnt = 1; + /* Insert WPA TKIP as the first pairwise cipher */ + if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + /* Insert WPA AES as the secondary pairwise cipher*/ + if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnIe + sizeof(RSNIE), OUI_WPA_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + /* Insert WPA AES as the first pairwise cipher */ + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); + break; + } + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.GroupCipher != Ndis802_11TKIPEnable) && + (pAd->StaCfg.GroupCipher != Ndis802_11AESEnable) + ) + { + UINT GroupCipher = pAd->StaCfg.GroupCipher; + switch(GroupCipher) + { + case Ndis802_11GroupWEP40Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4); + break; + case Ndis802_11GroupWEP104Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4); + break; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* swap for big-endian platform*/ + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } +} + +/* + ======================================================================== + + Routine Description: + Build AKM suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + AuthMode - indicate the authentication mode + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPMakeRsnIeAKM( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT AuthMode, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSNIE_AUTH *pRsnie_auth; + UCHAR AkmCnt = 1; /* default as 1*/ +#ifdef DOT11R_FT_SUPPORT + BOOLEAN bFtEnabled = FALSE; + UINT8 FtAkmOui[8]; +#endif /* DOT11R_FT_SUPPORT */ + + pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); + + /* decide WPA2 or WPA1 */ + if (ElementID == Wpa2Ie) + { +#ifdef DOT11R_FT_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < pAd->ApCfg.BssidNum) + { + /* Indicate the FT is enabld*/ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + bFtEnabled = TRUE; + AkmCnt = 2; + if (AuthMode == Ndis802_11AuthModeWPA2 || + AuthMode == Ndis802_11AuthModeWPA1WPA2) + { + NdisMoveMemory(FtAkmOui, OUI_WPA2_8021X_AKM, 4); + NdisMoveMemory(&FtAkmOui[4], OUI_FT_8021X_AKM, 4); + } + else if (AuthMode == Ndis802_11AuthModeWPA2PSK || + AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + { + NdisMoveMemory(FtAkmOui, OUI_WPA2_PSK_AKM, 4); + NdisMoveMemory(&FtAkmOui[4], OUI_FT_PSK_AKM, 4); + } + else + AkmCnt = 0; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Indicate the FT is enabld*/ + if (pAd->MlmeAux.MdIeInfo.Len > 0) + { + bFtEnabled = TRUE; + if (AuthMode == Ndis802_11AuthModeWPA2) + NdisMoveMemory(&FtAkmOui[0], OUI_FT_8021X_AKM, 4); + else if (AuthMode == Ndis802_11AuthModeWPA2PSK) + NdisMoveMemory(&FtAkmOui[0], OUI_FT_PSK_AKM, 4); + else + AkmCnt = 0; + } + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* DOT11R_FT_SUPPORT */ + + switch (AuthMode) + { + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA1WPA2: +#ifdef DOT11R_FT_SUPPORT + if (bFtEnabled && (AkmCnt > 0)) + { + /* append the primary AKM suite */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, FtAkmOui, 4); + + /* Append the secondary AKM suite if it exists */ + if (AkmCnt == 2) + { + /* Get the offset of the end of 1st AKM suite */ + UCHAR ext_akm_offset = (*rsn_len) + sizeof(RSNIE_AUTH); + + NdisMoveMemory(pRsnIe + ext_akm_offset, &FtAkmOui[4] , 4); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); + +#ifdef DOT11W_PMF_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPR) { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_1X_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert 1X-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } else if ((pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPC) && (pAd->ApCfg.MBSSID[apidx].PmfCfg.PMFSHA256)) { + NdisMoveMemory(pRsnie_auth->auth[0].oui + (4*AkmCnt), OUI_WPA2_1X_SHA256, 4); + AkmCnt++; + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert 1X-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + ULONG BssIdx; + BSS_ENTRY *pInBss = NULL; + + BssIdx = BssTableSearchWithSSID(&pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel); + if (BssIdx != BSS_NOT_FOUND) + { + pInBss = &pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]; + if (CLIENT_STATUS_TEST_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256)) + { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_1X_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert 1X-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* DOT11W_PMF_SUPPORT */ + break; + + case Ndis802_11AuthModeWPA2PSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: +#ifdef DOT11R_FT_SUPPORT + if (bFtEnabled && (AkmCnt > 0)) + { + /* append the primary AKM suite */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, FtAkmOui, 4); + + /* Append the secondary AKM suite if it exists */ + if (AkmCnt == 2) + { + /* Get the offset of the end of 1st AKM suite */ + UCHAR ext_akm_offset = (*rsn_len) + sizeof(RSNIE_AUTH); + + NdisMoveMemory(pRsnIe + ext_akm_offset, &FtAkmOui[4] , 4); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); + +#ifdef DOT11W_PMF_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPR) { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert PSK-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } else if ((pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPC) && (pAd->ApCfg.MBSSID[apidx].PmfCfg.PMFSHA256)) { + NdisMoveMemory(pRsnie_auth->auth[0].oui + (4*AkmCnt), OUI_WPA2_PSK_SHA256, 4); + AkmCnt++; + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert PSK-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + ULONG BssIdx; + BSS_ENTRY *pInBss = NULL; + + BssIdx = BssTableSearchWithSSID(&pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel); + if (BssIdx != BSS_NOT_FOUND) + { + pInBss = &pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]; + if (CLIENT_STATUS_TEST_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256)) + { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert PSK-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* DOT11W_PMF_SUPPORT */ + break; + default: + AkmCnt = 0; + break; + + } + } + else + { + switch (AuthMode) + { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPA1WPA2: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); + break; + + case Ndis802_11AuthModeWPANone: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); + break; + default: + AkmCnt = 0; + break; + } + } + + pRsnie_auth->acount = AkmCnt; + pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); + + /* update current RSNIE length*/ + (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1))); + +} + +/* + ======================================================================== + + Routine Description: + Build capability in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPMakeRsnIeCap( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSN_CAPABILITIES *pRSN_Cap; + + /* it could be ignored in WPA1 mode*/ + if (ElementID == WpaIe) + return; + + pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < pAd->ApCfg.BssidNum) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + +#ifdef DOT1X_SUPPORT + pRSN_Cap->field.PreAuth = (pMbss->PreAuth == TRUE) ? 1 : 0; +#endif /* DOT1X_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + pRSN_Cap->field.MFPC = (pMbss->PmfCfg.MFPC) ? 1 : 0; + pRSN_Cap->field.MFPR = (pMbss->PmfCfg.MFPR) ? 1 : 0; + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: RSNIE Capability MFPC=%d, MFPR=%d\n", __FUNCTION__, pRSN_Cap->field.MFPC, pRSN_Cap->field.MFPR)); +#endif /* DOT11W_PMF_SUPPORT */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pRSN_Cap->field.MFPC = (pAd->StaCfg.PmfCfg.MFPC) ? 1 : 0; + pRSN_Cap->field.MFPR = (pAd->StaCfg.PmfCfg.MFPR) ? 1 : 0; + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: RSNIE Capability MFPC=%d, MFPR=%d\n", __FUNCTION__, pRSN_Cap->field.MFPC, pRSN_Cap->field.MFPR)); + } +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /* CONFIG_STA_SUPPORT */ + + pRSN_Cap->word = cpu2le16(pRSN_Cap->word); + + (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length*/ + +} + +/* + ======================================================================== + + Routine Description: + Build PMKID in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +#ifdef DOT11W_PMF_SUPPORT +static VOID RTMPInsertRsnIeZeroPMKID( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + PUINT8 pBuf; + UCHAR ZeroPmkID[2] = {0x00, 0x00}; + + /* it could be ignored in WPA1 mode*/ + if (ElementID == WpaIe) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < pAd->ApCfg.BssidNum) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + if (pMbss->PmfCfg.MFPC) + goto InsertPMKIDCount; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.PmfCfg.MFPC) + goto InsertPMKIDCount; + } +#endif /* CONFIG_STA_SUPPORT */ + return; + +InsertPMKIDCount: + pBuf = (pRsnIe + (*rsn_len)); + + NdisMoveMemory(pBuf, ZeroPmkID, 2); + (*rsn_len) += 2; /* update current RSNIE length */ +} +#endif /* DOT11W_PMF_SUPPORT */ + +/* + ======================================================================== + + Routine Description: + Build RSN IE context. It is not included element-ID and length. + + Arguments: + pAd - pointer to our pAdapter context + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPMakeRSNIE(RTMP_ADAPTER *pAd, UINT AuthMode, UINT WepStatus, UCHAR apidx) +{ + PUCHAR pRsnIe = NULL; /* primary RSNIE*/ + UCHAR *rsnielen_cur_p = 0; /* the length of the primary RSNIE */ +#ifdef CONFIG_AP_SUPPORT + PUCHAR pRsnIe_ex = NULL; /* secondary RSNIE, it's ONLY used in WPA-mix mode */ + BOOLEAN bMixRsnIe = FALSE; /* indicate WPA-mix mode is on or off*/ + UCHAR s_offset; +#endif /* CONFIG_AP_SUPPORT */ + UCHAR *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */ + UCHAR PrimaryRsnie; + BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different*/ + UCHAR p_offset; + WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode*/ + + rsnielen_cur_p = NULL; + rsnielen_ex_cur_p = NULL; + + do + { + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UINT apcliIfidx = 0; + + /* Only support WPAPSK or WPA2PSK for AP-Client mode */ +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[apcliIfidx].wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + if (AuthMode < Ndis802_11AuthModeWPA) + return; + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + if ((AuthMode != Ndis802_11AuthModeWPAPSK) && + (AuthMode != Ndis802_11AuthModeWPA2PSK)) + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(ApCli)\n")); + + apcliIfidx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + /* Initiate some related information */ + if (apcliIfidx < MAX_APCLI_NUM) + { + pAd->ApCfg.ApCliTab[apcliIfidx].RSNIE_Len = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[apcliIfidx].RSN_IE, MAX_LEN_OF_RSNIE); + rsnielen_cur_p = &pAd->ApCfg.ApCliTab[apcliIfidx].RSNIE_Len; + pRsnIe = pAd->ApCfg.ApCliTab[apcliIfidx].RSN_IE; + + bMixCipher = pAd->ApCfg.ApCliTab[apcliIfidx].bMixCipher; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPMakeRSNIE: invalid apcliIfidx(%d)\n", apcliIfidx)); + return; + } + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* Sanity check for apidx */ + MBSS_MR_APIDX_SANITY_CHECK(pAd, apidx); +#ifdef HOSTAPD_SUPPORT + if(pAd->ApCfg.MBSSID[apidx].Hostapd != Hostapd_Diable) + return; +#endif /* HOSTAPD_SUPPORT */ + + if ((AuthMode != Ndis802_11AuthModeWPA) && + (AuthMode != Ndis802_11AuthModeWPAPSK) && + (AuthMode != Ndis802_11AuthModeWPA2) && + (AuthMode != Ndis802_11AuthModeWPA2PSK) && + (AuthMode != Ndis802_11AuthModeWPA1WPA2) && + (AuthMode != Ndis802_11AuthModeWPA1PSKWPA2PSK) +#ifdef WAPI_SUPPORT + && (AuthMode != Ndis802_11AuthModeWAICERT) + && (AuthMode != Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) + return; + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(AP-ra%d)\n", apidx)); + + /* decide the group key encryption type */ + if (WepStatus == Ndis802_11TKIPAESMix) + { + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus = Ndis802_11TKIPEnable; + FlexibleCipher = pAd->ApCfg.MBSSID[apidx].wdev.WpaMixPairCipher; + } + else + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus = WepStatus; + + /* Initiate some related information */ + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0] = 0; + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1] = 0; + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[0], MAX_LEN_OF_RSNIE); + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[1], MAX_LEN_OF_RSNIE); + + /* Pointer to the first RSNIE context */ + rsnielen_cur_p = &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + pRsnIe = pAd->ApCfg.MBSSID[apidx].RSN_IE[0]; + + /* Pointer to the secondary RSNIE context */ + rsnielen_ex_cur_p = &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1]; + pRsnIe_ex = pAd->ApCfg.MBSSID[apidx].RSN_IE[1]; + + /* Decide whether the authentication mode is WPA1-WPA2 mixed mode */ + if ((AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + bMixRsnIe = TRUE; + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + if (AuthMode < Ndis802_11AuthModeWPA) + return; + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + /* Support WPAPSK or WPA2PSK in STA-Infra mode */ + /* Support WPANone in STA-Adhoc mode */ + if ((AuthMode != Ndis802_11AuthModeWPAPSK) && + (AuthMode != Ndis802_11AuthModeWPA2PSK) && + (AuthMode != Ndis802_11AuthModeWPANone) +#ifdef WAPI_SUPPORT + && (AuthMode != Ndis802_11AuthModeWAICERT) + && (AuthMode != Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n")); + + /* Zero RSNIE context */ + pAd->StaCfg.RSNIE_Len = 0; + NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); + + /* Pointer to RSNIE */ + rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; + pRsnIe = pAd->StaCfg.RSN_IE; + + bMixCipher = pAd->StaCfg.bMixCipher; + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while(FALSE); + + /* indicate primary RSNIE as WPA or WPA2*/ + if ((AuthMode == Ndis802_11AuthModeWPA) || + (AuthMode == Ndis802_11AuthModeWPAPSK) || + (AuthMode == Ndis802_11AuthModeWPANone) || + (AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + PrimaryRsnie = WpaIe; +#ifdef WAPI_SUPPORT + else if ((AuthMode == Ndis802_11AuthModeWAICERT) || + (AuthMode == Ndis802_11AuthModeWAIPSK)) + PrimaryRsnie = WapiIe; +#endif /* WAPI_SUPPORT */ + else + PrimaryRsnie = Wpa2Ie; + +#ifdef WAPI_SUPPORT + if (PrimaryRsnie == WapiIe) + { + RTMPInsertWapiIe(AuthMode, WepStatus, pRsnIe, &p_offset); + } + else +#endif /* WAPI_SUPPORT */ + { + /* Build the primary RSNIE*/ + /* 1. insert cipher suite*/ + RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, apidx, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); + + /* 2. insert AKM*/ + RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); + + /* 3. insert capability*/ + RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + +#ifdef DOT11W_PMF_SUPPORT + /* 4. Insert PMKID */ + RTMPInsertRsnIeZeroPMKID(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + + /* 5. Insert Group Management Cipher*/ + PMF_MakeRsnIeGMgmtCipher(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); +#endif /* DOT11W_PMF_SUPPORT */ + } + + /* 4. update the RSNIE length*/ + if (rsnielen_cur_p == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: rsnielen_cur_p == NULL!\n", __FUNCTION__)); + return; + } + + *rsnielen_cur_p = p_offset; + + hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + /* if necessary, build the secondary RSNIE*/ + if (bMixRsnIe) + { + /* 1. insert cipher suite*/ + RTMPMakeRsnIeCipher(pAd, Wpa2Ie, WepStatus, apidx, bMixCipher, FlexibleCipher, pRsnIe_ex, &s_offset); + + /* 2. insert AKM*/ + RTMPMakeRsnIeAKM(pAd, Wpa2Ie, AuthMode, apidx, pRsnIe_ex, &s_offset); + + /* 3. insert capability*/ + RTMPMakeRsnIeCap(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); + +#ifdef DOT11W_PMF_SUPPORT + /* 4. Insert PMKID */ + RTMPInsertRsnIeZeroPMKID(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); + + /* 5. Insert Group Management Cipher*/ + PMF_MakeRsnIeGMgmtCipher(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); +#endif /* DOT11W_PMF_SUPPORT */ + + /* Update the RSNIE length*/ + *rsnielen_ex_cur_p = s_offset; + + hex_dump("The secondary RSNIE", pRsnIe_ex, (*rsnielen_ex_cur_p)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +} + +/* + ========================================================================== + Description: + Check whether the received frame is EAP frame. + + Arguments: + pAd - pointer to our pAdapter context + pEntry - pointer to active entry + pData - the received frame + DataByteCount - the received frame's length + FromWhichBSSID - indicate the interface index + + Return: + TRUE - This frame is EAP frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckWPAframe( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID) +{ + ULONG Body_len; + BOOLEAN Cancelled; + + do + { + } while (FALSE); + + if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) + return FALSE; + + + /* Skip LLC header */ + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || + /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL*/ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) + { + pData += 6; + } + /* Skip 2-bytes EAPoL type */ + if (NdisEqualMemory(EAPOL, pData, 2)) +/* if (*(UINT16 *)EAPOL == *(UINT16 *)pData)*/ + { + pData += 2; + } + else + return FALSE; + + switch (*(pData+1)) + { + case EAPPacket: + Body_len = (*(pData+2)<<8) | (*(pData+3)); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef IDS_SUPPORT + if((*(pData+4)) == EAP_CODE_REQUEST) + pAd->ApCfg.RcvdEapReqCount ++; +#endif /* IDS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); + break; + case EAPOLStart: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + break; + case EAPOLLogoff: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); + break; + case EAPOLKey: + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); + break; + case EAPOLASFAlert: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); + break; + default: + return FALSE; + + } + return TRUE; +} + + +#ifdef HDR_TRANS_SUPPORT +BOOLEAN RTMPCheckWPAframe_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID) +{ + ULONG Body_len; + BOOLEAN Cancelled; + + do + { + } while (FALSE); + + if(DataByteCount < (LENGTH_802_3 + LENGTH_EAPOL_H)) + return FALSE; + + + /* Skip LLC header */ + + pData += LENGTH_802_3; + + /* Skip 2-bytes EAPoL type */ + if (NdisEqualMemory(EAPOL, pData, 2)) + /* if (*(UINT16 *)EAPOL == *(UINT16 *)pData) */ + { + pData += 2; + } + else + return FALSE; + + switch (*(pData+1)) + { + case EAPPacket: + Body_len = (*(pData+2)<<8) | (*(pData+3)); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef IDS_SUPPORT + if((*(pData+4)) == EAP_CODE_REQUEST) + pAd->ApCfg.RcvdEapReqCount ++; +#endif /* IDS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); + break; + case EAPOLStart: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + break; + case EAPOLLogoff: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); + break; + case EAPOLKey: + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); + break; + case EAPOLASFAlert: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); + break; + default: + return FALSE; + + } + return TRUE; +} +#endif /* HDR_TRANS_SUPPORT */ + + +/* + ========================================================================== + Description: + Report the EAP message type + + Arguments: + msg - EAPOL_PAIR_MSG_1 + EAPOL_PAIR_MSG_2 + EAPOL_PAIR_MSG_3 + EAPOL_PAIR_MSG_4 + EAPOL_GROUP_MSG_1 + EAPOL_GROUP_MSG_2 + + Return: + message type string + + ========================================================================== +*/ +PSTRING GetEapolMsgType(CHAR msg) +{ + if(msg == EAPOL_PAIR_MSG_1) + return "Pairwise Message 1"; + else if(msg == EAPOL_PAIR_MSG_2) + return "Pairwise Message 2"; + else if(msg == EAPOL_PAIR_MSG_3) + return "Pairwise Message 3"; + else if(msg == EAPOL_PAIR_MSG_4) + return "Pairwise Message 4"; + else if(msg == EAPOL_GROUP_MSG_1) + return "Group Message 1"; + else if(msg == EAPOL_GROUP_MSG_2) + return "Group Message 2"; + else + return "Invalid Message"; +} + + +/* + ======================================================================== + + Routine Description: + Check Sanity RSN IE of EAPoL message + + Arguments: + + Return Value: + + + ======================================================================== +*/ +BOOLEAN RTMPCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset) +{ + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + BOOLEAN result = FALSE; + + pVIE = pData; + len = DataLen; + *Offset = 0; + + while (len > sizeof(RSNIE2)) + { + pEid = (PEID_STRUCT) pVIE; + /* WPA RSN IE*/ + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) && + (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && + (pEntry->RSNIE_Len == (pEid->Len + 2))) + { + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + /* WPA2 RSN IE, doesn't need to check RSNIE Capabilities field */ + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) && + (pEid->Eid == pEntry->RSN_IE[0]) && + ((pEid->Len + 2) >= pEntry->RSNIE_Len) && + (NdisEqualMemory(pEid->Octet, &pEntry->RSN_IE[2], pEntry->RSNIE_Len - 4))) + { + + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + else + { + break; + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + + return result; + +} + + +/* + ======================================================================== + + Routine Description: + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 + + Arguments: + + Return Value: + + Note: + 802.11i D10 + + ======================================================================== +*/ +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pMyKeyData = pKeyData; + UCHAR KeyDataLength = KeyDataLen; + UCHAR GTK[MAX_LEN_GTK]; + UCHAR GTKLEN = 0; + UCHAR DefaultIdx = 0; + UCHAR skip_offset = 0; + + + NdisZeroMemory(GTK, MAX_LEN_GTK); + + /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it*/ + if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) + { + { + if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) + { + /*WpaShowAllsuite(pMyKeyData, skip_offset);*/ + + /* skip RSN IE*/ + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); + } + else + return TRUE; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); + /*hex_dump("remain data", pMyKeyData, KeyDataLength);*/ + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + PEID_STRUCT pEid; + + pEid = (PEID_STRUCT)pMyKeyData; + if (pEid->Eid == IE_FT_MDIE) + { + /* Skip MDIE of FT*/ + /* todo - verify it*/ + pMyKeyData += (pEid->Len + 2); + KeyDataLength -= (pEid->Len + 2); + } + } +#endif /* DOT11R_FT_SUPPORT */ + + /* Parse KDE format in pairwise_msg_3_WPA2 && group_msg_1_WPA2*/ + if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) + { + PEID_STRUCT pEid; + + pEid = (PEID_STRUCT) pMyKeyData; + skip_offset = 0; + while ((skip_offset + 2 + pEid->Len) <= KeyDataLength) + { + switch(pEid->Eid) + { + case WPA_KDE_TYPE: + { + PKDE_HDR pKDE; + + pKDE = (PKDE_HDR)pEid; + if (NdisEqualMemory(pKDE->OUI, OUI_WPA2, 3)) + { + if (pKDE->DataType == KDE_GTK) + { + PGTK_KDE pKdeGtk; + + pKdeGtk = (PGTK_KDE) &pKDE->octet[0]; + DefaultIdx = pKdeGtk->Kid; + + /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */ + GTKLEN = pKDE->Len -6; + if (GTKLEN < LEN_WEP64) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); + return FALSE; + } + NdisMoveMemory(GTK, pKdeGtk->GTK, GTKLEN); + DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); + } +#ifdef DOT11W_PMF_SUPPORT + else if (pKDE->DataType == KDE_IGTK + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + if (PMF_ExtractIGTKKDE(pAd, &pKDE->octet[0], pKDE->Len - 4) == FALSE) + return FALSE; + } +#endif /* DOT11W_PMF_SUPPORT */ + } + } + break; + } + skip_offset = skip_offset + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + /* skip KDE Info*/ + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + } + else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) + { + DefaultIdx = GroupKeyIndex; + GTKLEN = KeyDataLength; + NdisMoveMemory(GTK, pMyKeyData, KeyDataLength); + DBGPRINT(RT_DEBUG_TRACE, ("GTK without KDE, DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); + } + + /* Sanity check - shared key index must be 0 ~ 3*/ + if (DefaultIdx > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + /* Prevent the GTK reinstall key attack */ + if (pEntry->LastGroupKeyId != DefaultIdx || + !NdisEqualMemory(pEntry->LastGTK, GTK, MAX_LEN_GTK)) { + /* Set Group key material, TxMic and RxMic for AP-Client*/ + if (!APCliInstallSharedKey(pAd, GTK, GTKLEN, DefaultIdx, pEntry)) + { + return FALSE; + } + pEntry->LastGroupKeyId = DefaultIdx; + NdisMoveMemory(pEntry->LastGTK, GTK, MAX_LEN_GTK); + pEntry->AllowUpdateRSC = TRUE; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : the Group reinstall attack, skip install key\n", + __func__)); + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef ADHOC_WPA2PSK_SUPPORT + if (ADHOC_ON(pAd)) { + if (pAd->StaCfg.GroupCipher == Ndis802_11AESEnable) { + NdisZeroMemory(&pEntry->RxGTK, sizeof(CIPHER_KEY)); + NdisMoveMemory(pEntry->RxGTK.Key, GTK, LEN_TK); + pEntry->RxGTK.CipherAlg = CIPHER_AES; + pEntry->RxGTK.KeyLen= LEN_TK; + } + } else +#endif /* ADHOC_WPA2PSK_SUPPORT */ + { + { + /* set key material, TxMic and RxMic */ + NdisMoveMemory(pAd->StaCfg.GTK, GTK, GTKLEN); + pAd->StaCfg.wdev.DefaultKeyId = DefaultIdx; + + WPAInstallSharedKey(pAd, + pAd->StaCfg.GroupCipher, + BSS0, + pAd->StaCfg.wdev.DefaultKeyId, + MCAST_WCID, + FALSE, + pAd->StaCfg.GTK, + GTKLEN); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Construct KDE common format + Its format is below, + + +--------------------+ + | Type (0xdd) | 1 octet + +--------------------+ + | Length | 1 octet + +--------------------+ + | OUI | 3 octets + +--------------------+ + | Data Type | 1 octet + +--------------------+ + + Arguments: + + Return Value: + + Note: + It's defined in IEEE 802.11-2007 Figure 8-25. + + ======================================================================== +*/ +VOID WPA_ConstructKdeHdr( + IN UINT8 data_type, + IN UINT8 data_len, + OUT PUCHAR pBuf) +{ + PKDE_HDR pHdr; + + pHdr = (PKDE_HDR)pBuf; + + NdisZeroMemory(pHdr, sizeof(KDE_HDR)); + + pHdr->Type = WPA_KDE_TYPE; + + /* The Length field specifies the number of octets in the OUI, Data + Type, and Data fields. */ + pHdr->Len = 4 + data_len; + + NdisMoveMemory(pHdr->OUI, OUI_WPA2, 3); + pHdr->DataType = data_type; + +} + + +/* + ======================================================================== + + Routine Description: + Construct EAPoL message for WPA handshaking + Its format is below, + + +--------------------+ + | Protocol Version | 1 octet + +--------------------+ + | Protocol Type | 1 octet + +--------------------+ + | Body Length | 2 octets + +--------------------+ + | Descriptor Type | 1 octet + +--------------------+ + | Key Information | 2 octets + +--------------------+ + | Key Length | 1 octet + +--------------------+ + | Key Repaly Counter | 8 octets + +--------------------+ + | Key Nonce | 32 octets + +--------------------+ + | Key IV | 16 octets + +--------------------+ + | Key RSC | 8 octets + +--------------------+ + | Key ID or Reserved | 8 octets + +--------------------+ + | Key MIC | 16 octets + +--------------------+ + | Key Data Length | 2 octets + +--------------------+ + | Key Data | n octets + +--------------------+ + + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ConstructEapolMsg( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + OUT PEAPOL_PACKET pMsg) +{ + BOOLEAN bWPA2 = FALSE; + UCHAR KeyDescVer; + + /* Choose WPA2 or not*/ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + /* Init Packet and Fill header */ + pMsg->ProVer = EAPOL_VER; + pMsg->ProType = EAPOLKey; + + /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field*/ + SET_UINT16_TO_ARRARY(pMsg->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG); + + /* Fill in EAPoL descriptor*/ + if (bWPA2) + pMsg->KeyDesc.Type = WPA2_KEY_DESC; + else + pMsg->KeyDesc.Type = WPA1_KEY_DESC; + + /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type*/ +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + /* Todo-AlbertY : use AKM to detemine which Descriptor version is used */ + + /* All EAPOL-Key frames to and from a STA when the negotiated */ + /* AKM is 00-0F-AC:3 or 00-0F-AC:4.*/ + KeyDescVer = KEY_DESC_EXT; + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256)) + { + /* All EAPOL-Key frames to and from a STA when the negotiated */ + /* AKM is 00-0F-AC:3 or 00-0F-AC:4.*/ + KeyDescVer = KEY_DESC_EXT; + } + else +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE)) + { + printk ("OSEN use sha256\n"); + //KeyDescVer = KEY_DESC_EXT; + KeyDescVer = KEY_DESC_OSEN; + } + else +#endif /* CONFIG_HOTSPOT_R2 */ + { + /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */ + /* When either the pairwise or the group cipher is AES, the KEY_DESC_AES shall be used.*/ + KeyDescVer = (((pEntry->WepStatus == Ndis802_11AESEnable) || + (GroupKeyWepStatus == Ndis802_11AESEnable)) ? (KEY_DESC_AES) : (KEY_DESC_TKIP)); + } + + pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer; + + /* Specify Key Type as Group(0) or Pairwise(1)*/ + if (MsgType >= EAPOL_GROUP_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; + else + pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + /* Specify Key Index, only group_msg1_WPA1*/ + if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; + + if (MsgType == EAPOL_PAIR_MSG_3) + pMsg->KeyDesc.KeyInfo.Install = 1; + + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyAck = 1; + + if (MsgType != EAPOL_PAIR_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyMic = 1; + + if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || + (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.Secure = 1; + } + + /* This subfield shall be set, and the Key Data field shall be encrypted, if + any key material (e.g., GTK or SMK) is included in the frame. */ + if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || + (MsgType == EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.EKD_DL = 1; + } + + /* key Information element has done. */ + *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); + + /* Fill in Key Length*/ + if (bWPA2) + { + /* In WPA2 mode, the field indicates the length of pairwise key cipher, */ + /* so only pairwise_msg_1 and pairwise_msg_3 need to fill. */ + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)) + pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11TKIPEnable) ? LEN_TKIP_TK : LEN_AES_TK); + } + else if (!bWPA2) + { + if (MsgType >= EAPOL_GROUP_MSG_1) + { + /* the length of group key cipher*/ + pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11TKIPEnable) ? LEN_TKIP_GTK : LEN_AES_GTK); + } + else + { + /* the length of pairwise key cipher*/ + pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11TKIPEnable) ? LEN_TKIP_TK : LEN_AES_TK); + } + } + + /* Fill in replay counter */ + NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + + /* Fill Key Nonce field */ + /* ANonce : pairwise_msg1 & pairwise_msg3*/ + /* SNonce : pairwise_msg2*/ + /* GNonce : group_msg1_wpa1 */ + if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) + NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); + + /* Fill key IV - WPA2 as 0, WPA1 as random*/ + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + { + /* Suggest IV be random number plus some number,*/ + NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); + pMsg->KeyDesc.KeyIv[15] += 2; + } + + /* Fill Key RSC field */ + /* It contains the RSC for the GTK being installed.*/ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); + } + + /* Clear Key MIC field for MIC calculation later */ + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + ConstructEapolKeyData(pEntry, + GroupKeyWepStatus, + KeyDescVer, + MsgType, + DefaultKeyIdx, + GTK, + RSNIE, + RSNIE_Len, + pMsg); + + /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.*/ + if (MsgType != EAPOL_PAIR_MSG_1) + { + CalculateMIC(KeyDescVer, pEntry->PTK, pMsg); + } + + DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len))); + DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyLength))); + + +} + +/* + ======================================================================== + + Routine Description: + Construct the Key Data field of EAPoL message + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ConstructEapolKeyData( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR keyDescVer, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *mpool, *Key_Data, *eGTK; + ULONG data_offset; + BOOLEAN bWPA2Capable = FALSE; + BOOLEAN GTK_Included = FALSE; +#ifdef DOT11R_FT_SUPPORT +#if defined(CONFIG_APSTA_MIXED_SUPPORT) || defined(CONFIG_STA_SUPPORT) + PRTMP_ADAPTER pAd = pEntry->pAd; +#endif +#endif /* DOT11R_FT_SUPPORT */ + + /* Choose WPA2 or not*/ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2Capable = TRUE; + + if (MsgType == EAPOL_PAIR_MSG_1 || + MsgType == EAPOL_PAIR_MSG_4 || + MsgType == EAPOL_GROUP_MSG_2) + return; + + /* allocate memory pool*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500); + + if (mpool == NULL) + return; + + /* eGTK Len = 512 */ + eGTK = (UCHAR *) ROUND_UP(mpool, 4); + /* Key_Data Len = 512 */ + Key_Data = (UCHAR *) ROUND_UP(eGTK + 512, 4); + + NdisZeroMemory(Key_Data, 512); + SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0); + data_offset = 0; + + /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */ + if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_len = 0; + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + pmkid_ptr = pEntry->FT_PMK_R1_NAME; + pmkid_len = LEN_PMK_NAME; + } +#endif /* DOT11R_FT_SUPPORT */ + + RTMPInsertRSNIE(&Key_Data[data_offset], + &data_offset, + RSNIE, + RSNIE_LEN, + pmkid_ptr, + pmkid_len); + } + +#ifdef DOT11R_FT_SUPPORT + /* Encapsulate MDIE if FT is enabled*/ + if (IS_FT_RSN_STA(pEntry) && bWPA2Capable && + ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + /* The MDIE shall be the same as those provided in + the AP's (Re)association Response frame. */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + NdisMoveMemory(&Key_Data[data_offset], pEntry->InitialMDIE, 5); + data_offset += 5; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + FT_InsertMdIE(pAd, + &Key_Data[data_offset], + &data_offset, + pAd->MlmeAux.MdIeInfo.MdId, + pAd->MlmeAux.MdIeInfo.FtCapPlc); + } +#endif /* CONFIG_STA_SUPPORT */ + } +#endif /* DOT11R_FT_SUPPORT */ + + /* Encapsulate GTK */ + /* Only for pairwise_msg3_WPA2 and group_msg1*/ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) + { + UINT8 gtk_len; + + /* Decide the GTK length */ + if (GroupKeyWepStatus == Ndis802_11AESEnable) + gtk_len = LEN_AES_GTK; + else + gtk_len = LEN_TKIP_GTK; + + /* Insert GTK KDE format in WAP2 mode */ + if (bWPA2Capable) + { + /* Construct the common KDE format */ + WPA_ConstructKdeHdr(KDE_GTK, 2 + gtk_len, &Key_Data[data_offset]); + data_offset += sizeof(KDE_HDR); + + /* GTK KDE format - 802.11i-2004 Figure-43x*/ + Key_Data[data_offset] = (DefaultKeyIdx & 0x03); + Key_Data[data_offset + 1] = 0x00; /* Reserved Byte*/ + data_offset += 2; + } + + /* Fill in GTK */ + NdisMoveMemory(&Key_Data[data_offset], GTK, gtk_len); + data_offset += gtk_len; + +#ifdef DOT11W_PMF_SUPPORT + /* Insert IGTK KDE to Key_Data field */ + if ((bWPA2Capable) + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_WARN, ("[PMF]:%s - Insert IGTK\n", __FUNCTION__)); + PMF_InsertIGTKKDE(pEntry->pAd, pEntry->apidx, &Key_Data[data_offset], &data_offset); + } +#endif /* DOT11W_PMF_SUPPORT */ + + GTK_Included = TRUE; + } + +#ifdef DOT11R_FT_SUPPORT + /* Encapsulate the related IE of FT when FT is enabled */ + if (IS_FT_RSN_STA(pEntry) && bWPA2Capable && + ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + /* Encapsulate FTIE. The MDIE shall be the same + as those provided in the AP's (Re)association Response frame. */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + NdisMoveMemory(&Key_Data[data_offset], pEntry->InitialFTIE, pEntry->InitialFTIE_Len); + data_offset += pEntry->InitialFTIE_Len; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NdisMoveMemory(&Key_Data[data_offset], pAd->MlmeAux.InitialFTIE, pAd->MlmeAux.InitialFTIE_Len); + data_offset += pAd->MlmeAux.InitialFTIE_Len; + } +#endif /* CONFIG_STA_SUPPORT */ + + } +#endif /* DOT11R_FT_SUPPORT */ + + + /* If the Encrypted Key Data subfield (of the Key Information field) + is set, the entire Key Data field shall be encrypted. */ + /* This whole key-data field shall be encrypted if a GTK is included.*/ + /* Encrypt the data material in key data field with KEK*/ + if (GTK_Included) + { + /*hex_dump("GTK_Included", Key_Data, data_offset);*/ + + if ( +#ifdef DOT11R_FT_SUPPORT + (keyDescVer == KEY_DESC_EXT) || +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + (keyDescVer == KEY_DESC_EXT) || +#endif /* DOT11R_FT_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + (keyDescVer == KEY_DESC_OSEN) || +#endif /* CONFIG_HOTSPOT_R2 */ + (keyDescVer == KEY_DESC_AES)) + { + UCHAR remainder = 0; + UCHAR pad_len = 0; + UINT wrap_len =0; + + /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */ + /* shall be used to encrypt the Key Data field using the KEK field from */ + /* the derived PTK.*/ + + /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */ + /* shall be padded before encrypting if the key data length is less than 16 */ + /* octets or if it is not a multiple of 8. The padding consists of appending*/ + /* a single octet 0xdd followed by zero or more 0x00 octets. */ + if ((remainder = data_offset & 0x07) != 0) + { + INT i; + + pad_len = (8 - remainder); + Key_Data[data_offset] = 0xDD; + for (i = 1; i < pad_len; i++) + Key_Data[data_offset + i] = 0; + + data_offset += pad_len; + } + + AES_Key_Wrap(Key_Data, (UINT) data_offset, + &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + eGTK, &wrap_len); + data_offset = wrap_len; + + } + else + { + TKIP_GTK_KEY_WRAP(&pEntry->PTK[LEN_PTK_KCK], + pMsg->KeyDesc.KeyIv, + Key_Data, + data_offset, + eGTK); + } + + NdisMoveMemory(pMsg->KeyDesc.KeyData, eGTK, data_offset); + } + else + { + NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); + } + + /* Update key data length field and total body length*/ + SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset); + INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset); + + os_free_mem(NULL, mpool); + +} + +/* + ======================================================================== + + Routine Description: + Calcaulate MIC. It is used during 4-ways handsharking. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + + Note: + The EAPOL-Key MIC is a MIC of the EAPOL-Key frames, + from and including the EAPOL protocol version field + to and including the Key Data field, calculated with + the Key MIC field set to 0. + + ======================================================================== +*/ +VOID CalculateMIC( + IN UCHAR KeyDescVer, + IN UCHAR *PTK, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *OutBuffer; + ULONG FrameLen = 0; + UCHAR mic[LEN_KEY_DESC_MIC]; + UCHAR digest[80]; + + /* allocate memory for MIC calculation*/ + os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512); + + if (OutBuffer == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n")); + return; + } + + /* make a frame for calculating MIC.*/ + MakeOutgoingFrame(OutBuffer, &FrameLen, + CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4, pMsg, + END_OF_ARGS); + + NdisZeroMemory(mic, sizeof(mic)); + + /* Calculate MIC*/ + if (KeyDescVer == KEY_DESC_AES) + { + RT_HMAC_SHA1(PTK, LEN_PTK_KCK, OutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + else if (KeyDescVer == KEY_DESC_TKIP) + { + RT_HMAC_MD5(PTK, LEN_PTK_KCK, OutBuffer, FrameLen, mic, MD5_DIGEST_SIZE); + } + else if ((KeyDescVer == KEY_DESC_EXT) || (KeyDescVer == KEY_DESC_OSEN)) + { + UINT mlen = AES_KEY128_LENGTH; + AES_CMAC(OutBuffer, FrameLen, PTK, LEN_PTK_KCK, mic, &mlen); + } + + /* store the calculated MIC*/ + NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); + + os_free_mem(NULL, OutBuffer); +} + +UCHAR RTMPExtractKeyIdxFromIVHdr( + IN PUCHAR pIV, + IN UINT8 CipherAlg) +{ + UCHAR keyIdx = 0xFF; + + /* extract the key index from IV header */ + switch (CipherAlg) + { + case Ndis802_11WEPEnabled: + case Ndis802_11TKIPEnable: + case Ndis802_11AESEnable: + case Ndis802_11GroupWEP40Enabled: + case Ndis802_11GroupWEP104Enabled: + keyIdx = (*(pIV + 3) & 0xc0) >> 6; + break; + +#ifdef WAPI_SUPPORT + case Ndis802_11EncryptionSMS4Enabled: + keyIdx = *(pIV) & 0xFF; + break; +#endif /* WAPI_SUPPORT */ + } + + return keyIdx; + +} + +CIPHER_KEY *RTMPSwCipherKeySelection( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pIV, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry) +{ + PCIPHER_KEY pKey = NULL; + UCHAR keyIdx = 0; + UINT8 CipherAlg = Ndis802_11EncryptionDisabled; + + if ((pEntry == NULL) || + (RX_BLK_TEST_FLAG(pRxBlk, fRX_APCLI)) || + (RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) || + (RX_BLK_TEST_FLAG(pRxBlk, fRX_MESH))) + return NULL; + + if (pRxBlk->pRxInfo->U2M) + { + CipherAlg = pEntry->WepStatus; + } + else + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + CipherAlg = pAd->StaCfg.GroupCipher; + } +#endif /* CONFIG_STA_SUPPORT */ + } + + if ((keyIdx = RTMPExtractKeyIdxFromIVHdr(pIV, CipherAlg)) > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Invalid key index(%d) !!!\n", + __FUNCTION__, keyIdx)); + return NULL; + } + + if ((CipherAlg == Ndis802_11WEPEnabled) + || (CipherAlg == Ndis802_11GroupWEP40Enabled) + || (CipherAlg == Ndis802_11GroupWEP104Enabled)) + { + pKey = &pAd->SharedKey[pEntry->apidx][keyIdx]; + } + else if ((CipherAlg == Ndis802_11TKIPEnable) || + (CipherAlg == Ndis802_11AESEnable)) + { + if (pRxBlk->pRxInfo->U2M) + pKey = &pEntry->PairwiseKey; + else { +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + if (ADHOC_ON(pAd)) + pKey = &pEntry->RxGTK; + else +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + pKey = &pAd->SharedKey[pEntry->apidx][keyIdx]; + } + } +#ifdef WAPI_SUPPORT + else if (CipherAlg == Ndis802_11EncryptionSMS4Enabled) + { + if (pRxBlk->pRxInfo->U2M) + pKey = &pEntry->PairwiseKey; + else + pKey = &pAd->SharedKey[pEntry->apidx][keyIdx]; + } +#endif /* WAPI_SUPPORT */ + + return pKey; + +} + +/* + ======================================================================== + + Routine Description: + Some received frames can't decrypt by Asic, so decrypt them by software. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + NDIS_STATUS_SUCCESS - decryption successful + NDIS_STATUS_FAILURE - decryption failure + + ======================================================================== +*/ +NDIS_STATUS RTMPSoftDecryptionAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN UCHAR UserPriority, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt) +{ + NDIS_STATUS NStatus; + NStatus =0; + + switch (pKey->CipherAlg) + { + case CIPHER_WEP64: + case CIPHER_WEP128: + /* handle WEP decryption */ + if (RTMPSoftDecryptWEP(pAd, pKey, pData, &(*DataByteCnt)) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt WEP data fails.\n")); + /* give up this frame*/ + return NDIS_STATUS_FAILURE; + } + break; + + case CIPHER_TKIP: + /* handle TKIP decryption */ + NStatus = RTMPSoftDecryptTKIP(pAd, pHdr, UserPriority, pKey, pData, &(*DataByteCnt)); + if (NStatus == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt TKIP data fails.\n")); + /* give up this frame*/ + return NDIS_STATUS_FAILURE; + } + else if (NStatus == NDIS_STATUS_MICERROR) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt TKIP data mic error.\n")); + /* give up this frame*/ + return NDIS_STATUS_MICERROR; + } + break; + + case CIPHER_AES: + /* handle AES decryption */ + if (RTMPSoftDecryptCCMP(pAd, pHdr, pKey, pData, &(*DataByteCnt)) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt AES data fails.\n")); + /* give up this frame*/ + return NDIS_STATUS_FAILURE; + } + break; +#ifdef WAPI_SUPPORT +#ifdef SOFT_ENCRYPT + case CIPHER_SMS4: + { + INT ret; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE); +#endif + if ((ret = RTMPSoftDecryptSMS4(pHdr, FALSE, pKey, pData, &(*DataByteCnt))) != STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt SMS4 data fails(%d).\n", ret)); + /* give up this frame*/ + return NDIS_STATUS_FAILURE; + } +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE); +#endif + } + break; +#endif /* SOFT_ENCRYPT */ +#endif /* WAPI_SUPPORT */ + default: + /* give up this frame*/ + return NDIS_STATUS_FAILURE; + break; + } + + return NDIS_STATUS_SUCCESS; + +} + +VOID RTMPSoftConstructIVHdr( + IN UCHAR CipherAlg, + IN UCHAR key_id, + IN PUCHAR pTxIv, + OUT PUCHAR pHdrIv, + OUT UINT8 *hdr_iv_len) +{ + *hdr_iv_len = 0; + +#ifdef WAPI_SUPPORT + if (CipherAlg == CIPHER_SMS4) + { + /* Construct and insert WPI-SMS4 IV header to MPDU header */ + RTMPConstructWPIIVHdr(key_id, pTxIv, pHdrIv); + *hdr_iv_len = LEN_WPI_IV_HDR; + } + else +#endif /* WAPI_SUPPORT */ + if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128)) + { + /* Construct and insert 4-bytes WEP IV header to MPDU header */ + RTMPConstructWEPIVHdr(key_id, pTxIv, pHdrIv); + *hdr_iv_len = LEN_WEP_IV_HDR; + } + else if (CipherAlg == CIPHER_TKIP) + ; + else if (CipherAlg == CIPHER_AES) + { + /* Construct and insert 8-bytes CCMP header to MPDU header */ + RTMPConstructCCMPHdr(key_id, pTxIv, pHdrIv); + *hdr_iv_len = LEN_CCMP_HDR; + } + +} + +VOID RTMPSoftEncryptionAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR CipherAlg, + IN PUCHAR pHdr, + IN PUCHAR pSrcBufData, + IN UINT32 SrcBufLen, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pKey, + OUT UINT8 *ext_len) +{ + *ext_len = 0; + +#ifdef WAPI_SUPPORT +#ifdef SOFT_ENCRYPT + if (CipherAlg == CIPHER_SMS4) + { +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE); +#endif + /* Encrypt the MPDU data by software*/ + RTMPSoftEncryptSMS4(pHdr, + pSrcBufData, + SrcBufLen, + KeyIdx, + pKey->Key, + pKey->TxTsc); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE); +#endif + *ext_len = LEN_WPI_MIC; + } + else +#endif /* SOFT_ENCRYPT */ +#endif /* WAPI_SUPPORT */ + if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128)) + { + /* Encrypt the MPDU data by software*/ + RTMPSoftEncryptWEP(pAd, + pKey->TxTsc, + pKey, + pSrcBufData, + SrcBufLen); + + *ext_len = LEN_ICV; + } + else if (CipherAlg == CIPHER_TKIP) + ; + else if (CipherAlg == CIPHER_AES) + { + /* Encrypt the MPDU data by software*/ + RTMPSoftEncryptCCMP(pAd, + pHdr, + pKey->TxTsc, + pKey->Key, + pSrcBufData, + SrcBufLen); + + *ext_len = LEN_CCMP_MIC; + } + +} + +PUINT8 WPA_ExtractSuiteFromRSNIE( + IN PUINT8 rsnie, + IN UINT rsnie_len, + IN UINT8 type, + OUT UINT8 *count) +{ + PEID_STRUCT pEid; + INT len; + PUINT8 pBuf; + INT offset = 0; + + pEid = (PEID_STRUCT)rsnie; + len = rsnie_len - 2; /* exclude IE and length*/ + pBuf = (PUINT8)&pEid->Octet[0]; + + /* set default value*/ + *count = 0; + + /* Check length*/ + if ((len <= 0) || (pEid->Len != len)) + { + DBGPRINT_ERR(("%s : The length is invalid\n", __FUNCTION__)); + goto out; + } + + /* Check WPA or WPA2*/ + if (pEid->Eid == IE_WPA) + { + /* Check the length */ + if (len < sizeof(RSNIE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The length is too short for WPA\n", __FUNCTION__)); + goto out; + } + else + { + PRSNIE pRsnie; + UINT16 u_cnt; + + pRsnie = (PRSNIE)pBuf; + u_cnt = cpu2le16(pRsnie->ucount); + offset = sizeof(RSNIE) + (LEN_OUI_SUITE * (u_cnt - 1)); + + if (len < offset) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) for WPA-RSN \n", + __FUNCTION__, offset, len)); + goto out; + } + else + { + /* Get the group cipher*/ + if (type == GROUP_SUITE) + { + *count = 1; + return pRsnie->mcast; + } + /* Get the pairwise cipher suite*/ + else if (type == PAIRWISE_SUITE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n", + __FUNCTION__, u_cnt)); + *count = u_cnt; + return pRsnie->ucast[0].oui; + } + } + } + } + else if (pEid->Eid == IE_RSN) + { + if (len < sizeof(RSNIE2)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The length is too short for WPA2\n", __FUNCTION__)); + goto out; + } + else + { + PRSNIE2 pRsnie2; + UINT16 u_cnt; + + pRsnie2 = (PRSNIE2)pBuf; + u_cnt = cpu2le16(pRsnie2->ucount); + offset = sizeof(RSNIE2) + (LEN_OUI_SUITE * (u_cnt - 1)); + + if (len < offset) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) for WPA2-RSN \n", + __FUNCTION__, offset, len)); + goto out; + } + else + { + /* Get the group cipher*/ + if (type == GROUP_SUITE) + { + *count = 1; + return pRsnie2->mcast; + } + /* Get the pairwise cipher suite*/ + else if (type == PAIRWISE_SUITE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n", + __FUNCTION__, u_cnt)); + *count = u_cnt; + return pRsnie2->ucast[0].oui; + } + } + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Unknown IE (%d)\n", __FUNCTION__, pEid->Eid)); + goto out; + } + + /* skip group cipher and pairwise cipher suite */ + pBuf += offset; + len -= offset; + + /* Ready to extract the AKM information and its count */ + if (len < sizeof(RSNIE_AUTH)) + { + DBGPRINT_ERR(("%s : The length of AKM of RSN is too short\n", __FUNCTION__)); + goto out; + } + else + { + PRSNIE_AUTH pAkm; + UINT16 a_cnt; + + /* pointer to AKM count */ + pAkm = (PRSNIE_AUTH)pBuf; + a_cnt = cpu2le16(pAkm->acount); + offset = sizeof(RSNIE_AUTH) + (LEN_OUI_SUITE * (a_cnt - 1)); + + if (len < offset) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) for AKM \n", + __FUNCTION__, offset, len)); + goto out; + } + else + { + /* Get the AKM suite */ + if (type == AKM_SUITE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n", + __FUNCTION__, a_cnt)); + *count = a_cnt; + return pAkm->auth[0].oui; + } + } + } + + /* For WPA1, the remaining shall be ignored. */ + if (pEid->Eid == IE_WPA) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The remaining shall be ignored in WPA mode\n", + __FUNCTION__)); + goto out; + } + + /* skip the AKM capability */ + pBuf += offset; + len -= offset; + + /* Parse the RSN Capabilities */ + if (len < sizeof(RSN_CAPABILITIES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The peer RSNIE doesn't include RSN-Cap\n", __FUNCTION__)); + goto out; + } + else + { + /* Report the content of the RSN capabilities */ + if (type == RSN_CAP_INFO) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : Extract RSN Capabilities\n", __FUNCTION__)); + *count = 1; + return pBuf; + } + + /* skip RSN capability (2-bytes) */ + offset = sizeof(RSN_CAPABILITIES); + pBuf += offset; + len -= offset; + } + + /* Extract PMKID-list field */ + if (len < sizeof(UINT16)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The peer RSNIE doesn't include PMKID list Count\n", __FUNCTION__)); + goto out; + } + else + { + UINT16 p_count; + PUINT8 pPmkidList = NULL; + + NdisMoveMemory(&p_count, pBuf, sizeof(UINT16)); + p_count = cpu2le16(p_count); + + /* Get count of the PMKID list */ + if (p_count > 0) + { + PRSNIE_PMKID pRsnPmkid; + + /* the expected length of PMKID-List field */ + offset = sizeof(RSNIE_PMKID) + (LEN_PMKID * (p_count - 1)); + + /* sanity check about the length of PMKID-List field */ + if (len < offset) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) in PMKID-field \n", + __FUNCTION__, offset, len)); + goto out; + } + + /* pointer to PMKID field */ + pRsnPmkid = (PRSNIE_PMKID)pBuf; + pPmkidList = pRsnPmkid->pmkid[0].list; + + } + else + { + /* The PMKID field shall be without PMKID-List */ + offset = sizeof(UINT16); + pPmkidList = NULL; + } + + + /* Extract PMKID list and its count */ + if (type == PMKID_LIST) + { + *count = p_count; + return pPmkidList; + } + + /* skip the PMKID field */ + pBuf += offset; + len -= offset; + + } + +#ifdef DOT11W_PMF_SUPPORT + /* Get group mamagement cipher */ + if (len < LEN_OUI_SUITE) + { + DBGPRINT(RT_DEBUG_TRACE, ("[PMF]%s : The peer RSNIE doesn't include Group_mgmt_cipher_suite\n", __FUNCTION__)); + goto out; + } + else + { + offset = LEN_OUI_SUITE; + + /* Get Group-Mgmt-Cipher_Suite information */ + if (type == G_MGMT_SUITE) + { + *count = 1; + return pBuf; + } + else + { + /* skip the Group-Mgmt-Cipher_Suite field */ + pBuf += offset; + len -= offset; + } + } +#endif /* DOT11W_PMF_SUPPORT */ + +out: + *count = 0; + return NULL; + +} + +VOID WpaShowAllsuite( + IN PUINT8 rsnie, + IN UINT rsnie_len) +{ + PUINT8 pSuite = NULL; + UINT8 count; + + hex_dump("RSNIE", rsnie, rsnie_len); + + /* group cipher*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL) + { + hex_dump("group cipher", pSuite, 4*count); + } + + /* pairwise cipher*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL) + { + hex_dump("pairwise cipher", pSuite, 4*count); + } + + /* AKM*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL) + { + hex_dump("AKM suite", pSuite, 4*count); + } + + /* PMKID*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL) + { + hex_dump("PMKID", pSuite, LEN_PMKID); + } + +} + +VOID RTMPInsertRSNIE( + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 rsnie_ptr, + IN UINT8 rsnie_len, + IN PUINT8 pmkid_ptr, + IN UINT8 pmkid_len) +{ + PUCHAR pTmpBuf; + ULONG TempLen = 0; + UINT8 extra_len = 0; + UINT16 pmk_count = 0; + UCHAR ie_num; + UINT8 total_len = 0; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + + pTmpBuf = pFrameBuf; + + /* PMKID-List Must larger than 0 and the multiple of 16. */ + if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) + { + extra_len = sizeof(UINT16) + pmkid_len; + + pmk_count = (pmkid_len >> 4); + pmk_count = cpu2le16(pmk_count); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : no PMKID-List included(%d).\n", __FUNCTION__, pmkid_len)); + } + + if (rsnie_len != 0) + { + ie_num = IE_WPA; + total_len = rsnie_len; + + if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) + { + ie_num = IE_RSN; + total_len += extra_len; + } + + /* construct RSNIE body */ + MakeOutgoingFrame(pTmpBuf, &TempLen, + 1, &ie_num, + 1, &total_len, + rsnie_len, rsnie_ptr, + END_OF_ARGS); + + pTmpBuf += TempLen; + *pFrameLen = *pFrameLen + TempLen; + + if (ie_num == IE_RSN) + { + /* Insert PMKID-List field */ + if (extra_len > 0) + { + MakeOutgoingFrame(pTmpBuf, &TempLen, + 2, &pmk_count, + pmkid_len, pmkid_ptr, + END_OF_ARGS); + + pTmpBuf += TempLen; + *pFrameLen = *pFrameLen + TempLen; + } + } + } + + return; +} + + +VOID WPAInstallPairwiseKey( + PRTMP_ADAPTER pAd, + UINT8 BssIdx, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE) +{ + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + + /* Assign the pairwise cipher algorithm */ + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11AESEnable) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n", + __FUNCTION__, pEntry->wcid)); + return; + } + + /* Assign key material and its length */ + pEntry->PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], LEN_TK); + if (pEntry->PairwiseKey.CipherAlg == CIPHER_TKIP) + { + if (bAE) + { + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[OFFSET_OF_AP_TKIP_TX_MIC], LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[OFFSET_OF_AP_TKIP_RX_MIC], LEN_TKIP_MIC); + } + else + { + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[OFFSET_OF_STA_TKIP_TX_MIC], LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[OFFSET_OF_STA_TKIP_RX_MIC], LEN_TKIP_MIC); + } + } + +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + DBGPRINT(RT_DEBUG_TRACE, ("===> SW_ENC ON(wcid=%d) \n", pEntry->wcid)); + NdisZeroMemory(pEntry->PairwiseKey.TxTsc, LEN_WPA_TSC); + NdisZeroMemory(pEntry->PairwiseKey.RxTsc, LEN_WPA_TSC); + } + else +#endif /* SOFT_ENCRYPT */ + { + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + 0, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->wcid, + PAIRWISEKEYTABLE); + } + +} + +VOID WPAInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + BOOLEAN bAE, + PUINT8 pGtk, + UINT8 GtkLen) +{ + PCIPHER_KEY pSharedKey; + + if (BssIdx >= MAX_MBSSID_NUM(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The BSS-index(%d) is out of range for MBSSID link. \n", + __FUNCTION__, BssIdx)); + return; + } + + pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx]; + NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); + + /* Set the group cipher */ + if (GroupCipher == Ndis802_11GroupWEP40Enabled) + pSharedKey->CipherAlg = CIPHER_WEP64; + else if (GroupCipher == Ndis802_11GroupWEP104Enabled) + pSharedKey->CipherAlg = CIPHER_WEP128; + else if (GroupCipher == Ndis802_11TKIPEnable) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (GroupCipher == Ndis802_11AESEnable) + pSharedKey->CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n", + __FUNCTION__, BssIdx)); + return; + } + + /* Set the key material and its length */ + if (GroupCipher == Ndis802_11GroupWEP40Enabled || + GroupCipher == Ndis802_11GroupWEP104Enabled) + { + /* Sanity check the length */ + if ((GtkLen != LEN_WEP64) && (GtkLen != LEN_WEP128)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : (IF/ra%d) WEP key invlaid(%d) \n", + __FUNCTION__, BssIdx, GtkLen)); + return; + } + + pSharedKey->KeyLen = GtkLen; + NdisMoveMemory(pSharedKey->Key, pGtk, GtkLen); + } + else + { + /* Sanity check the length */ + if (GtkLen < LEN_TK) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : (IF/ra%d) WPA key invlaid(%d) \n", + __FUNCTION__, BssIdx, GtkLen)); + return; + } + + pSharedKey->KeyLen = LEN_TK; + NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK); + if (pSharedKey->CipherAlg == CIPHER_TKIP) + { + if (bAE) + { + NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC); + } + else + { + NdisMoveMemory(pSharedKey->TxMic, pGtk + 24, LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->RxMic, pGtk + 16, LEN_TKIP_MIC); + } + } + } + + /* Update group key table(0x6C00) and group key mode(0x7000) */ + AsicAddSharedKeyEntry( + pAd, + BssIdx, + KeyIdx, + pSharedKey); + + /* When Wcid isn't zero, it means that this is a Authenticator Role. + Only Authenticator entity needs to set HW IE/EIV table (0x6000) + and WCID attribute table (0x6800) for group key. */ + if (Wcid != 0) + { + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + KeyIdx, + pSharedKey->CipherAlg, + Wcid, + SHAREDKEYTABLE); + } +} + +VOID RTMPSetWcidSecurityInfo( + PRTMP_ADAPTER pAd, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 CipherAlg, + UINT8 Wcid, + UINT8 KeyTabFlag) +{ + UINT32 IV = 0; + UINT8 IV_KEYID = 0; + + /* Prepare initial IV value */ + if (CipherAlg == CIPHER_WEP64 || CipherAlg == CIPHER_WEP128) + { + INT i; + UCHAR TxTsc[LEN_WEP_TSC]; + + /* Generate 3-bytes IV randomly for encryption using */ + for(i = 0; i < LEN_WEP_TSC; i++) + TxTsc[i] = RandomByte(pAd); + + /* Update HW IVEIV table */ + IV_KEYID = (KeyIdx << 6); + IV = (IV_KEYID << 24) | + (TxTsc[2] << 16) | + (TxTsc[1] << 8) | + (TxTsc[0]); + } + else if (CipherAlg == CIPHER_TKIP || CipherAlg == CIPHER_AES) + { + /* Set IVEIV as 1 in Asic - + In IEEE 802.11-2007 8.3.3.4.3 described : + The PN shall be implemented as a 48-bit monotonically incrementing + non-negative integer, initialized to 1 when the corresponding + temporal key is initialized or refreshed. */ + IV_KEYID = (KeyIdx << 6) | 0x20; + IV = (IV_KEYID << 24) | 1; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Unsupport cipher Alg (%d) for Wcid-%d \n", + __FUNCTION__, CipherAlg, Wcid)); + return; + } + /* Update WCID IV/EIV table */ + AsicUpdateWCIDIVEIV(pAd, Wcid, IV, 0); + + /* Update WCID attribute entry */ + AsicUpdateWcidAttributeEntry(pAd, + BssIdx, + KeyIdx, + CipherAlg, + Wcid, + KeyTabFlag); + +} + + +#ifdef WPA_SUPPLICANT_SUPPORT +#define LENGTH_EAP_H 4 +/* If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). */ +INT WpaCheckEapCode( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pFrame, + IN USHORT FrameLen, + IN USHORT OffSet) +{ + + PUCHAR pData; + INT result = 0; + + if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) + return result; + + pData = pFrame + OffSet; /* skip offset bytes */ + + if(*(pData+1) == EAPPacket) /* 802.1x header - Packet Type */ + { + result = *(pData+4); /* EAP header - Code */ + } + + return result; +} + +#endif /* WPA_SUPPLICANT_SUPPORT */ + +/** from wpa_supplicant + * inc_byte_array - Increment arbitrary length byte array by one + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the last byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ +void inc_byte_array(UCHAR *counter, int len) +{ + int pos = len - 1; + while (pos >= 0) { + counter[pos]++; + if (counter[pos] != 0) + break; + pos--; + } +} + +#ifdef RT_CFG80211_SUPPORT +BOOLEAN RTMPIsValidIEs(UCHAR *Ies, INT32 Len) +{ + /* Validate if the IE is in correct format. */ + INT32 Pos = 0; + INT32 IeLen = 0; + while (Pos < Len) + { + if ((IeLen = (INT32)(Ies[Pos+1]) + 2) < 0) + return FALSE; + Pos += IeLen; + } + if (Pos == Len) + return TRUE; + else + return FALSE; +} + +/* Find specific IE Id in a buffer containing multiple IEs */ +const UCHAR *RTMPFindIE(UCHAR Eid, const UCHAR *Ies, INT32 Len) +{ + while (Len > 2 && Ies[0] != Eid) { + Len -= Ies[1] + 2; + Ies += Ies[1] + 2; + } + if (Len < 2) + return NULL; + if (Len < 2 + Ies[1]) + return NULL; + return Ies; +} + +/* Find WPS IE Id in a buffer containing multiple IEs */ +const UCHAR *RTMPFindWPSIE(const UCHAR *Ies, INT32 Len) +{ + const UCHAR *Ptr = Ies; + UCHAR WPSOUI[]={0x00, 0x50, 0xf2, 0x04}; + if (!Ies || ! Len) + return NULL; + while ((Ptr = RTMPFindIE(WLAN_EID_VENDOR_SPECIFIC, Ptr, Len-(Ptr-Ies))) != NULL) + { + if (!NdisCmpMemory(Ptr+2, WPSOUI, 4)) + break; + Ptr += Ptr[1] + 2; + } + return Ptr; +} +#endif /* RT_CFG80211_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wpa_adhoc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wpa_adhoc.c new file mode 100644 index 000000000..9702d4e21 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/cmm_wpa_adhoc.c @@ -0,0 +1,1648 @@ +/* + *************************************************************************** + * 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_wpa_adhoc.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef ADHOC_WPA2PSK_SUPPORT + +#include "rt_config.h" + +VOID Adhoc_RTMPGetTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + OUT PUCHAR pTxTsc) +{ + USHORT Wcid; + USHORT offset; + UCHAR IvEiv[8]; + UINT32 IV = 0, EIV = 0; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + /* Get apidx for this BSSID */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* Read IVEIV from Asic */ + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + NdisZeroMemory(IvEiv, 8); + NdisZeroMemory(pTxTsc, 6); + + RTMP_IO_READ32(pAd, offset, &IV); + RTMP_IO_READ32(pAd, offset + 4, &EIV); + + *pTxTsc = IV & 0x000000ff; + *(pTxTsc+1) = IV & 0x0000ff00; + *(pTxTsc+2) = EIV & 0x000000ff; + *(pTxTsc+3) = EIV & 0x0000ff00; + *(pTxTsc+4) = EIV & 0x00ff0000; + *(pTxTsc+5) = EIV & 0xff000000; + + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_RTMPGetTxTscFromAsic : WCID(%d) TxTsc 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x \n", + Wcid, *pTxTsc, *(pTxTsc+1), *(pTxTsc+2), *(pTxTsc+3), *(pTxTsc+4), *(pTxTsc+5))); + + +} + +/* + ========================================================================== + Description: + Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c + Return: + ========================================================================== +*/ +VOID Adhoc_WpaEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MAC_TABLE_ENTRY *pEntry; + PHEADER_802_11 pHeader; + + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WpaEAPOLStartAction ===> \n")); + + pHeader = (PHEADER_802_11)Elem->Msg; + + /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */ + if (Elem->MsgLen == 6) + pEntry = MacTableLookup(pAd, Elem->Msg); + else + { + pEntry = MacTableLookup(pAd, pHeader->Addr2); + } + + if (pEntry) + { + PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = &pEntry->WPA_Authenticator; + + DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pAuthenticator->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx)); + + if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (pAuthenticator->WpaState < AS_PTKSTART) + && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + /*Added by Eddy */ + pAuthenticator->WpaState = AS_INITPSK; + pAuthenticator->MsgRetryCounter = 4; + Adhoc_WpaStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } +} + + +/* + ========================================================================== + Description: + Check the validity of the received EAPoL frame + Return: + TRUE if all parameters are OK, + FALSE otherwise + ========================================================================== + */ +BOOLEAN Adhoc_PeerWpaMessageSanity ( + IN PRTMP_ADAPTER pAd, + IN PEAPOL_PACKET pMsg, + IN ULONG MsgLen, + IN UCHAR MsgType, + IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; + BOOLEAN bReplayDiff = FALSE; + BOOLEAN bWPA2 = FALSE; + KEY_INFO EapolKeyInfo; + UCHAR GroupKeyIndex = 0; + + + NdisZeroMemory(mic, sizeof(mic)); + NdisZeroMemory(digest, sizeof(digest)); + NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); + NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo)); + + NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo)); + + /* Choose WPA2 or not */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + /* 0. Check MsgType */ + if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType)); + return FALSE; + } + + /* 1. Replay counter check */ + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant */ + { + /* First validate replay counter, only accept message with larger replay counter. */ + /* Let equal pass, some AP start with all zero replay counter */ + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + { + bReplayDiff = TRUE; + } + } + else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator */ + { + /* check Replay Counter coresponds to MSG from authenticator, otherwise discard */ + if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY)) + { + bReplayDiff = TRUE; + } + } + + /* Replay Counter different condition */ + if (bReplayDiff) + { + /* send wireless event - for replay counter different */ + RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + hex_dump("Current replay counter ", p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY); + return FALSE; + } + + /* 2. Verify MIC except Pairwise Msg1 */ + if (MsgType != EAPOL_PAIR_MSG_1) + { + UCHAR rcvd_mic[LEN_KEY_DESC_MIC]; + UINT eapol_len = CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4; + + /* Record the received MIC for check later */ + NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if (EapolKeyInfo.KeyDescVer == KEY_DESC_TKIP) /* TKIP */ + { + RT_HMAC_MD5(p4WayProfile->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, mic, MD5_DIGEST_SIZE); + } + else if (EapolKeyInfo.KeyDescVer == KEY_DESC_AES) /* AES */ + { + RT_HMAC_SHA1(p4WayProfile->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + + if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) + { + /* send wireless event - for MIC different */ + RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); + hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); + + return FALSE; + } + } + + /* 1. Decrypt the Key Data field if GTK is included. */ + /* 2. Extract the context of the Key Data field if it exist. */ + /* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear. */ + /* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. */ + if (CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen) > 0) + { + /* Decrypt this field */ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + if((EapolKeyInfo.KeyDescVer == KEY_DESC_AES)) + { + UINT aes_unwrap_len = 0; + + AES_Key_Unwrap(pMsg->KeyDesc.KeyData, + CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), + &p4WayProfile->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + KEYDATA, &aes_unwrap_len); + SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, aes_unwrap_len); + } + else + { + TKIP_GTK_KEY_UNWRAP(&pEntry->PTK[LEN_PTK_KCK], + pMsg->KeyDesc.KeyIv, + pMsg->KeyDesc.KeyData, + CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), + KEYDATA); + } + + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + GroupKeyIndex = EapolKeyInfo.KeyIndex; + + } + else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) + { + NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen)); + } + else + { + + return TRUE; + } + + /* Parse Key Data field to */ + /* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) */ + /* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 */ + /* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) */ + if (!RTMPParseEapolKeyData(pAd, KEYDATA, + CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), + GroupKeyIndex, MsgType, bWPA2, pEntry)) + { + return FALSE; + } + } + + return TRUE; + +} + + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +VOID Adhoc_WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MAC_TABLE_ENTRY *pEntry; + PHEADER_802_11 pHeader; + PEAPOL_PACKET pEapol_packet; + KEY_INFO peerKeyInfo; + UINT eapol_len; + + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WpaEAPOLKeyAction ===>\n")); + + pHeader = (PHEADER_802_11)Elem->Msg; + pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + eapol_len = CONV_ARRARY_TO_UINT16(pEapol_packet->Body_Len) + LENGTH_EAPOL_H; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); + + do + { + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (!pEntry || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + break; + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + break; + + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr))); + + if (eapol_len > Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H) + { + DBGPRINT(RT_DEBUG_ERROR, ("The length of EAPoL packet is invalid \n")); + break; + } + + if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) || + ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); + break; + } + + /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */ + /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */ + if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) && (peerKeyInfo.KeyDescVer != KEY_DESC_TKIP)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n")); + break; + } + /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */ + /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */ + else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) && (peerKeyInfo.KeyDescVer != KEY_DESC_AES)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) \n")); + break; + } + + /* Check if this STA is in class 3 state and the WPA state is started */ + if (pEntry->Sst == SST_ASSOC) + { + /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */ + /* or not. */ + /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */ + /* Key frame from the Authenticator must not have the Ack bit set. */ + if ((peerKeyInfo.KeyAck == 1) && (pEntry->WPA_Supplicant.WpaState >= AS_INITPSK)) + { + /* The frame is snet by Authenticator. */ + /* So the Supplicant side shall handle this. */ + if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY)) + { + /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */ + /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ + /* 2. the message 3 of 4-way HS in WPA */ + /* EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */ + if (peerKeyInfo.KeyMic == 0) { + Adhoc_PeerPairMsg1Action(pAd, pEntry, Elem); + } else { + Adhoc_PeerPairMsg3Action(pAd, pEntry, Elem); + } + } + else if ((peerKeyInfo.Secure == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0)) + { + /* Process 1. the message 3 of 4-way HS in WPA2 */ + /* EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */ + /* 2. the message 1 of group KS in WPA or WPA2 */ + /* EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */ + if (peerKeyInfo.KeyType == PAIRWISEKEY) { + Adhoc_PeerPairMsg3Action(pAd, pEntry, Elem); + } else { + Adhoc_PeerGroupMsg1Action(pAd, pEntry, Elem); + } + } + } + else if (pEntry->WPA_Authenticator.WpaState >= AS_INITPSK) + { + /* The frame is snet by Supplicant. */ + /* So the Authenticator side shall handle this. */ + if ((peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Request == 1) && + (peerKeyInfo.Error == 1)) + { + /* The Supplicant uses a single Michael MIC Failure Report frame */ + /* to report a MIC failure event to the Authenticator. */ + /* A Michael MIC Failure Report is an EAPOL-Key frame with */ + /* the following Key Information field bits set to 1: */ + /* MIC bit, Error bit, Request bit, Secure bit. */ + + DBGPRINT(RT_DEBUG_ERROR, ("Received an Michael MIC Failure Report, active countermeasure \n")); + } + else if ((peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.KeyMic == 1)) + { + if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY) + { + /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */ + /* Process 1. message 2 of 4-way HS in WPA or WPA2 */ + /* 2. message 4 of 4-way HS in WPA */ + if (CONV_ARRARY_TO_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0) + { + Adhoc_PeerPairMsg4Action(pAd, pEntry, Elem); + } + else + { + Adhoc_PeerPairMsg2Action(pAd, pEntry, Elem); + } + } + else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY) + { + /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */ + /* Process message 4 of 4-way HS in WPA2 */ + Adhoc_PeerPairMsg4Action(pAd, pEntry, Elem); + } + else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY) + { + /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */ + /* Process message 2 of Group key HS in WPA or WPA2 */ +/* Adhoc_PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11)); */ + } + } + } + } + }while(FALSE); +} + + + +/* + ========================================================================== + Description: + This is a function to initilize 4-way handshake + + Return: + + ========================================================================== +*/ +VOID Adhoc_WpaStart4WayHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval) +{ + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PUINT8 pBssid = NULL; + BOOLEAN Cancelled; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_WpaStart4WayHS\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); + return; + } + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The entry doesn't exist.\n")); + return; + } + pAuthenticator = &pEntry->WPA_Authenticator; + pBssid = pAd->CommonCfg.Bssid; + group_cipher = pAd->StaCfg.GroupCipher; + + /* delete retry timer */ + RTMPCancelTimer(&pAuthenticator->MsgRetryTimer, &Cancelled); + + if (pBssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); + return; + } + + /* Check the status */ + if ((pAuthenticator->WpaState > AS_PTKSTART) || (pAuthenticator->WpaState < AS_INITPMK)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling=%d\n", pAuthenticator->WpaState)); + return; + } + + /* Increment replay counter by 1 */ + ADD_ONE_To_64BIT_VAR(pAuthenticator->ReplayCounter); + + /* Randomly generate ANonce */ + GenRandom(pAd, (UCHAR *)pBssid, pAuthenticator->ANonce); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 1 */ + /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ + Adhoc_ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_1, + 0, /* Default key index */ + pAuthenticator->ANonce, + NULL, /* TxRSC */ + NULL, /* GTK */ + NULL, /* RSNIE */ + 0, /* RSNIE length */ + pAuthenticator, + pEapolFrame); + + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + { + UCHAR digest[80], PMK_key[20]; + PKEY_DESCRIPTER pKeyDesc = &pEapolFrame->KeyDesc; + + pKeyDesc->KeyData[0] = 0xDD; + pKeyDesc->KeyData[2] = 0x00; + pKeyDesc->KeyData[3] = 0x0F; + pKeyDesc->KeyData[4] = 0xAC; + pKeyDesc->KeyData[5] = 0x04; + + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pAd->CurrentAddress, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN); + RT_HMAC_SHA1(pAd->StaCfg.PMK, PMK_LEN, PMK_key, 20, digest, LEN_PMKID); + + NdisMoveMemory(&pKeyDesc->KeyData[6], digest, LEN_PMKID); + pKeyDesc->KeyData[1] = 0x14;/* 4+LEN_PMKID */ + INC_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, 6 + LEN_PMKID); + INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID); + } + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, + LENGTH_802_3, (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + /* Trigger Retry Timer */ + pAuthenticator->MsgType = EAPOL_PAIR_MSG_1; + RTMPSetTimer(&pAuthenticator->MsgRetryTimer, TimeInterval); + + /* Update State */ + pAuthenticator->WpaState = AS_PTKSTART; + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== Adhoc_WpaStart4WayHS: send Msg1 of 4-way \n")); + +} + + +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID Adhoc_PeerPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PTK[80]; + UCHAR Header802_3[14]; + PEAPOL_PACKET pMsg1; + UINT MsgLen; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PUINT8 pCurrentAddr = NULL; + PUINT8 pmk_ptr = NULL; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 rsnie_ptr = NULL; + UCHAR rsnie_len = 0; + PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_PeerPairMsg1Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + + if (ADHOC_ON(pAd) && (pEntry->WPA_Supplicant.WpaState == AS_PTKINITDONE)) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DEAUTH_STA_LEAVING, FALSE); + return; + } + + pSupplicant = &pEntry->WPA_Supplicant; + + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + pCurrentAddr = pAd->CurrentAddress; + pmk_ptr = pAd->StaCfg.PMK; + group_cipher = pAd->StaCfg.GroupCipher; + rsnie_ptr = pAd->StaCfg.RSN_IE; + rsnie_len = pAd->StaCfg.RSNIE_Len; + + /* Store the received frame */ + pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 1 - Replay Counter */ + if (Adhoc_PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pSupplicant, pEntry) == FALSE) + return; + + + /* Store Replay counter, it will use to verify message 3 and construct message 2 */ + NdisMoveMemory(pSupplicant->ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Store ANonce */ + NdisMoveMemory(pSupplicant->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + /* Generate random SNonce */ + GenRandom(pAd, (UCHAR *)pCurrentAddr, pSupplicant->SNonce); + + /* Calculate PTK(ANonce, SNonce) */ + WpaDerivePTK(pAd, + pmk_ptr, + pSupplicant->ANonce, + pEntry->Addr, + pSupplicant->SNonce, + pCurrentAddr, + PTK, + LEN_PTK); + + /* Save key to PTK entry */ + NdisMoveMemory(pSupplicant->PTK, PTK, LEN_PTK); + + /* Update WpaState */ + pSupplicant->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 2 */ + /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */ + Adhoc_ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_2, + 0, /* DefaultKeyIdx */ + pSupplicant->SNonce, + NULL, /* TxRsc */ + NULL, /* GTK */ + (UCHAR *)rsnie_ptr, + rsnie_len, + pSupplicant, + pEapolFrame); + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); +} + + +/* + ========================================================================== + Description: + When receiving the second packet of 4-way pairwisekey handshake. + Return: + ========================================================================== +*/ +VOID Adhoc_PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PTK[80]; + BOOLEAN Cancelled; + PHEADER_802_11 pHeader; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pMsg2; + UINT MsgLen; + UCHAR Header802_3[LENGTH_802_3]; + UCHAR TxTsc[6]; + PUINT8 pBssid = NULL; + PUINT8 pmk_ptr = NULL; + PUINT8 gtk_ptr = NULL; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUCHAR rsnie_ptr = NULL; + UCHAR rsnie_len = 0; + PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_PeerPairMsg2Action \n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + pAuthenticator = &pEntry->WPA_Authenticator; + + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + /* check Entry in valid State */ + if (pAuthenticator->WpaState < AS_PTKSTART) + return; + + pBssid = pAd->CommonCfg.Bssid; + + pmk_ptr = pAd->StaCfg.PMK; + gtk_ptr = pAd->StaCfg.GTK; + group_cipher = pAd->StaCfg.GroupCipher; + + default_key = pAd->StaCfg.wdev.DefaultKeyId; + if (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + rsnie_len = pAd->StaCfg.RSNIE_Len; + rsnie_ptr = pAd->StaCfg.RSN_IE; + } + + + /* pointer to 802.11 header */ + pHeader = (PHEADER_802_11)Elem->Msg; + + /* skip 802.11_header(24-byte) and LLC_header(8) */ + pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Store SNonce */ + NdisMoveMemory(pAuthenticator->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + /* Derive PTK */ + WpaDerivePTK(pAd, + (UCHAR *)pmk_ptr, + pAuthenticator->ANonce, /* ANONCE */ + pAd->CurrentAddress, + pAuthenticator->SNonce, /* SNONCE */ + pEntry->Addr, + PTK, + LEN_PTK); + + /* Get Group TxTsc form Asic */ + Adhoc_RTMPGetTxTscFromAsic(pAd, BSS0, TxTsc); + + NdisMoveMemory(pAuthenticator->PTK, PTK, LEN_PTK); + + /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */ + if (Adhoc_PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pAuthenticator, pEntry) == FALSE) + return; + + do + { + /* Allocate memory for input */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* delete retry timer */ + RTMPCancelTimer(&pAuthenticator->MsgRetryTimer, &Cancelled); + + /* Increment replay counter by 1 */ + ADD_ONE_To_64BIT_VAR(pAuthenticator->ReplayCounter); + + /* Construct EAPoL message - Pairwise Msg 3 */ + Adhoc_ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_3, + default_key, + pAuthenticator->ANonce, + TxTsc, + (UCHAR *)gtk_ptr, + (UCHAR *)rsnie_ptr, + rsnie_len, + pAuthenticator, + pEapolFrame); + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + pAuthenticator->MsgType = EAPOL_PAIR_MSG_3; + RTMPSetTimer(&pAuthenticator->MsgRetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + + /* Update State */ + pAuthenticator->WpaState = AS_PTKINIT_NEGOTIATING; + + os_free_mem(NULL, mpool); + + }while(FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); +} + + +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID Adhoc_PeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + PHEADER_802_11 pHeader; + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pMsg3; + UINT MsgLen; + PUINT8 pCurrentAddr = NULL; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("===> Adhoc_PeerPairMsg3Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + + pSupplicant = &pEntry->WPA_Supplicant; + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + pCurrentAddr = pAd->CurrentAddress; + group_cipher = pAd->StaCfg.GroupCipher; + + /* Record 802.11 header & the received EAPOL packet Msg3 */ + pHeader = (PHEADER_802_11) Elem->Msg; + pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */ + if (Adhoc_PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pSupplicant, pEntry) == FALSE) + return; + + /* Save Replay counter, it will use construct message 4 */ + NdisMoveMemory(pSupplicant->ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Double check ANonce */ + if (!NdisEqualMemory(pSupplicant->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + { + return; + } + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 4 */ + Adhoc_ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_4, + 0, /* group key index not used in message 4 */ + NULL, /* Nonce not used in message 4 */ + NULL, /* TxRSC not used in message 4 */ + NULL, /* GTK not used in message 4 */ + NULL, /* RSN IE not used in message 4 */ + 0, + pSupplicant, + pEapolFrame); + + /* open 802.1x port control and privacy filter */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || + pEntry->AuthMode == Ndis802_11AuthModeWPA2) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", + GetAuthMode(pEntry->AuthMode), + GetEncryptType(pEntry->WepStatus), + GetEncryptType(group_cipher))); + } + + /* Init 802.3 header and send out */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + /* Update WpaState */ + pSupplicant->WpaState = AS_PTKINITDONE; + Adhoc_Wpa4WayComplete(pAd, pEntry); + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n")); +} + + +/* + ========================================================================== + Description: + When receiving the last packet of 4-way pairwisekey handshake. + Initilize 2-way groupkey handshake following. + Return: + ========================================================================== +*/ +VOID Adhoc_PeerPairMsg4Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + PEAPOL_PACKET pMsg4; + PHEADER_802_11 pHeader; + UINT MsgLen; + BOOLEAN Cancelled; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_PeerPairMsg4Action\n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + pAuthenticator = &pEntry->WPA_Authenticator; + + do + { + if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG ) ) + break; + + if (pAuthenticator->WpaState < AS_PTKINIT_NEGOTIATING) + break; + + group_cipher = pAd->StaCfg.GroupCipher; + + /* pointer to 802.11 header */ + pHeader = (PHEADER_802_11)Elem->Msg; + + /* skip 802.11_header(24-byte) and LLC_header(8) */ + pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */ + if (Adhoc_PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pAuthenticator, pEntry) == FALSE) + break; + + pAuthenticator->WpaState = AS_PTKINITDONE; + RTMPCancelTimer(&pAuthenticator->MsgRetryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + + Adhoc_Wpa4WayComplete(pAd, pEntry); + + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + { + pEntry->GTKState = REKEY_ESTABLISHED; + + /* send wireless event - for set key done WPA2 */ + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + } + }while(FALSE); + +} + + +VOID Adhoc_PeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pGroup; + UINT MsgLen; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 pCurrentAddr = NULL; + PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("===> Adhoc_PeerGroupMsg1Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + + pSupplicant = &pEntry->WPA_Supplicant; + pCurrentAddr = pAd->CurrentAddress; + group_cipher = pAd->StaCfg.GroupCipher; + default_key = pAd->StaCfg.wdev.DefaultKeyId; + + /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */ + pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */ + if (Adhoc_PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pSupplicant, pEntry) == FALSE) + return; + + /* Save Replay counter, it will use to construct message 2 */ + NdisMoveMemory(pSupplicant->ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + + /* Construct EAPoL message - Group Msg 2 */ + Adhoc_ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_GROUP_MSG_2, + default_key, + NULL, /* Nonce not used */ + NULL, /* TxRSC not used */ + NULL, /* GTK not used */ + NULL, /* RSN IE not used */ + 0, + pSupplicant, + pEapolFrame); + + /* open 802.1x port control and privacy filter */ + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + +#ifdef CONFIG_STA_SUPPORT + STA_PORT_SECURED(pAd); + /* Indicate Connected for GUI */ + pAd->IndicateMediaState = NdisMediaStateConnected; +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", + GetAuthMode(pEntry->AuthMode), + GetEncryptType(pEntry->WepStatus), + GetEncryptType(group_cipher))); + + /* init header and Fill Packet and send Msg 2 to authenticator */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (pAd->MlmeAux.Channel == pAd->CommonCfg.Channel)) + { + /* Now stop the scanning and need to send the rekey packet out */ + pAd->MlmeAux.Channel = 0; + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE); + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: send group message 2\n")); +} + + +VOID Adhoc_Wpa4WayComplete( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL; + PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL; + INT compare_address; + + DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_Wpa4WayComplete\n")); + + if (!pEntry) + return; + + pAuthenticator = &pEntry->WPA_Authenticator; + pSupplicant = &pEntry->WPA_Supplicant; + + compare_address = NdisCmpMemory(pAd->CurrentAddress, pEntry->Addr, MAC_ADDR_LEN); + if ((compare_address > 0) && (pAuthenticator->WpaState == AS_PTKINITDONE)) { + NdisMoveMemory(pEntry->PTK, pAuthenticator->PTK, 64); + } else if ((compare_address < 0) && (pSupplicant->WpaState == AS_PTKINITDONE)) { + NdisMoveMemory(pEntry->PTK, pSupplicant->PTK, 64); + } else + return; + +#ifdef IWSC_SUPPORT + if (pEntry) + { + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PWSC_PEER_ENTRY pWscPeerEntry = NULL; + + RTMP_SEM_LOCK(&pWpsCtrl->WscConfiguredPeerListSemLock); + pWscPeerEntry = WscFindPeerEntry(&pWpsCtrl->WscConfiguredPeerList, pEntry->Addr); + if (pWscPeerEntry) + { + WscDelListEntryByMAC(&pWpsCtrl->WscConfiguredPeerList, pEntry->Addr); + } + RTMP_SEM_UNLOCK(&pWpsCtrl->WscConfiguredPeerListSemLock); + } +#endif /* IWSC_SUPPORT */ + + WPAInstallPairwiseKey(pAd, + BSS0, + pEntry, + FALSE); + + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + STA_PORT_SECURED(pAd); + /* Indicate Connected for GUI */ + pAd->IndicateMediaState = NdisMediaStateConnected; + + DBGPRINT(RT_DEBUG_OFF, ("Adhoc_Wpa4WayComplete - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), + pAd->StaCfg.GroupCipher, + GetEncryptType(pAd->StaCfg.GroupCipher))); +} + + +VOID Adhoc_WpaRetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + + if ((pEntry) && IS_ENTRY_CLIENT(pEntry)) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = &pEntry->WPA_Authenticator; + + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WPARetryExec---> ReTryCounter=%d, WpaState=%d \n", pAuthenticator->MsgRetryCounter, pAuthenticator->WpaState)); + + switch (pEntry->AuthMode) + { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + if (pAuthenticator->MsgRetryCounter == 0) + { + /* send wireless event - for pairwise key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + pEntry->WPA_Authenticator.WpaState = AS_NOTUSE; +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.WscControl.bWscTrigger == FALSE) +#endif // IWSC_SUPPORT // + { + MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE); + DBGPRINT(RT_DEBUG_ERROR, ("Adhoc_WPARetryExec::MSG1 timeout\n")); + } + + } + else if (pAuthenticator->MsgType == EAPOL_PAIR_MSG_1) + { + if ((pAuthenticator->WpaState == AS_PTKSTART) || (pAuthenticator->WpaState == AS_INITPSK) || (pAuthenticator->WpaState == AS_INITPMK)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WPARetryExec::ReTry MSG1 of 4-way Handshake\n")); + Adhoc_WpaStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } + else if (pAuthenticator->MsgType == EAPOL_PAIR_MSG_3) + { + pEntry->WPA_Authenticator.WpaState = AS_INITPSK; +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.WscControl.bWscTrigger == FALSE) +#endif // IWSC_SUPPORT // + { + MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WPARetryExec::Retry MSG3, TIMEOUT\n")); + } + } + break; + default: + break; + } + pAuthenticator->MsgRetryCounter--; + } +} + + +/* + ======================================================================== + + Routine Description: + Construct EAPoL message for WPA handshaking + Its format is below, + + +--------------------+ + | Protocol Version | 1 octet + +--------------------+ + | Protocol Type | 1 octet + +--------------------+ + | Body Length | 2 octets + +--------------------+ + | Descriptor Type | 1 octet + +--------------------+ + | Key Information | 2 octets + +--------------------+ + | Key Length | 1 octet + +--------------------+ + | Key Repaly Counter | 8 octets + +--------------------+ + | Key Nonce | 32 octets + +--------------------+ + | Key IV | 16 octets + +--------------------+ + | Key RSC | 8 octets + +--------------------+ + | Key ID or Reserved | 8 octets + +--------------------+ + | Key MIC | 16 octets + +--------------------+ + | Key Data Length | 2 octets + +--------------------+ + | Key Data | n octets + +--------------------+ + + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID Adhoc_ConstructEapolMsg( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile, + OUT PEAPOL_PACKET pMsg) +{ + BOOLEAN bWPA2 = FALSE; + UCHAR KeyDescVer; + PKEY_DESCRIPTER pKeyDesc = &pMsg->KeyDesc; + PKEY_INFO pKeyInfo = &pMsg->KeyDesc.KeyInfo; + + /* Choose WPA2 or not */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + /* Init Packet and Fill header */ + pMsg->ProVer = EAPOL_VER; + pMsg->ProType = EAPOLKey; + + /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */ + SET_UINT16_TO_ARRARY(pMsg->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG); + + /* Fill in EAPoL descriptor */ + if (bWPA2) + pKeyDesc->Type = WPA2_KEY_DESC; + else + pKeyDesc->Type = WPA1_KEY_DESC; + + /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */ + /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */ + /* When either the pairwise or the group cipher is AES, the KEY_DESC_AES shall be used. */ + KeyDescVer = (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) || + (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (KEY_DESC_AES) : (KEY_DESC_TKIP)); + + pKeyInfo->KeyDescVer = KeyDescVer; + + /* Specify Key Type as Group(0) or Pairwise(1) */ + if (MsgType >= EAPOL_GROUP_MSG_1) + pKeyInfo->KeyType = GROUPKEY; + else + pKeyInfo->KeyType = PAIRWISEKEY; + + /* Specify Key Index, only group_msg1_WPA1 */ + if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) + pKeyInfo->KeyIndex = DefaultKeyIdx; + + if (MsgType == EAPOL_PAIR_MSG_3) + pKeyInfo->Install = 1; + + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) + pKeyInfo->KeyAck = 1; + + if (MsgType != EAPOL_PAIR_MSG_1) + pKeyInfo->KeyMic = 1; + + if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) + pKeyInfo->Secure = 1; + + /* This subfield shall be set, and the Key Data field shall be encrypted, if + any key material (e.g., GTK or SMK) is included in the frame. */ + if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) + pKeyInfo->EKD_DL = 1; + + /* key Information element has done. */ + *(USHORT *)(pKeyInfo) = cpu2le16(*(USHORT *)(pKeyInfo)); + + /* Fill in Key Length */ + if (bWPA2) + { + /* In WPA2 mode, the field indicates the length of pairwise key cipher, */ + /* so only pairwise_msg_1 and pairwise_msg_3 need to fill. */ + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)) + pKeyDesc->KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_TK : LEN_AES_TK); + } + else + { + if (MsgType >= EAPOL_GROUP_MSG_1) + { + /* the length of group key cipher */ + pKeyDesc->KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_GTK : LEN_AES_GTK); + } + else + { + /* the length of pairwise key cipher */ + pKeyDesc->KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_TK : LEN_AES_TK); + } + } + + /* Fill in replay counter */ + NdisMoveMemory(pKeyDesc->ReplayCounter, p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Fill Key Nonce field */ + /* ANonce : pairwise_msg1 & pairwise_msg3 */ + /* SNonce : pairwise_msg2 */ + /* GNonce : group_msg1_wpa1 */ + if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) + NdisMoveMemory(pKeyDesc->KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); + + /* Fill key IV - WPA2 as 0, WPA1 as random */ + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + { + /* Suggest IV be random number plus some number, */ + NdisMoveMemory(pKeyDesc->KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); + pKeyDesc->KeyIv[15] += 2; + } + + /* Fill Key RSC field */ + /* It contains the RSC for the GTK being installed. */ + if ((TxRSC != NULL) && ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))) + { + NdisMoveMemory(pKeyDesc->KeyRsc, TxRSC, 6); + } + + /* Clear Key MIC field for MIC calculation later */ + NdisZeroMemory(pKeyDesc->KeyMic, LEN_KEY_DESC_MIC); + + Adhoc_ConstructEapolKeyData(pEntry, + GroupKeyWepStatus, + KeyDescVer, + MsgType, + DefaultKeyIdx, + GTK, + RSNIE, + RSNIE_Len, + p4WayProfile, + pMsg); + + /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */ + if (MsgType != EAPOL_PAIR_MSG_1) + CalculateMIC(KeyDescVer, p4WayProfile->PTK, pMsg); + + DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len))); + DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", CONV_ARRARY_TO_UINT16(pKeyDesc->KeyLength))); +} + + +/* + ======================================================================== + + Routine Description: + Construct the Key Data field of EAPoL message + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID Adhoc_ConstructEapolKeyData( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR keyDescVer, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *mpool, *Key_Data, *eGTK; + ULONG data_offset; + BOOLEAN bWPA2Capable = FALSE; + BOOLEAN GTK_Included = FALSE; + PKEY_DESCRIPTER pKeyDesc = &pMsg->KeyDesc; + + /* Choose WPA2 or not */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2Capable = TRUE; + + if (MsgType == EAPOL_PAIR_MSG_1 || + MsgType == EAPOL_PAIR_MSG_4 || + MsgType == EAPOL_GROUP_MSG_2) + return; + + /* allocate memory pool */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500); + + if (mpool == NULL) + return; + + /* eGTK Len = 512 */ + eGTK = (UCHAR *) ROUND_UP(mpool, 4); + /* Key_Data Len = 512 */ + Key_Data = (UCHAR *) ROUND_UP(eGTK + 512, 4); + + NdisZeroMemory(Key_Data, 512); + SET_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, 0); + data_offset = 0; + + /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */ + if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_len = 0; + + RTMPInsertRSNIE(&Key_Data[data_offset], + &data_offset, + RSNIE, + RSNIE_LEN, + pmkid_ptr, + pmkid_len); + } + + /* Encapsulate GTK */ + /* Only for pairwise_msg3_WPA2 and group_msg1 */ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) + { + UINT8 gtk_len; + + /* Decide the GTK length */ + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + gtk_len = LEN_AES_GTK; + else + gtk_len = LEN_TKIP_GTK; + + /* Insert GTK KDE format in WAP2 mode */ + if (bWPA2Capable) + { + /* Construct the common KDE format */ + WPA_ConstructKdeHdr(KDE_GTK, 2 + gtk_len, &Key_Data[data_offset]); + data_offset += sizeof(KDE_HDR); + + /* GTK KDE format - 802.11i-2004 Figure-43x */ + Key_Data[data_offset] = (DefaultKeyIdx & 0x03); + Key_Data[data_offset + 1] = 0x00; /* Reserved Byte */ + data_offset += 2; + + } + + /* Fill in GTK */ + NdisMoveMemory(&Key_Data[data_offset], GTK, gtk_len); + data_offset += gtk_len; + + + + GTK_Included = TRUE; + } + + /* If the Encrypted Key Data subfield (of the Key Information field) + is set, the entire Key Data field shall be encrypted. */ + /* This whole key-data field shall be encrypted if a GTK is included. */ + /* Encrypt the data material in key data field with KEK */ + if (GTK_Included) + { + if ((keyDescVer == KEY_DESC_AES)) + { + UCHAR remainder = 0; + UCHAR pad_len = 0; + UINT wrap_len =0; + + /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */ + /* shall be used to encrypt the Key Data field using the KEK field from */ + /* the derived PTK. */ + + /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */ + /* shall be padded before encrypting if the key data length is less than 16 */ + /* octets or if it is not a multiple of 8. The padding consists of appending */ + /* a single octet 0xdd followed by zero or more 0x00 octets. */ + if ((remainder = data_offset & 0x07) != 0) + { + INT i; + + pad_len = (8 - remainder); + Key_Data[data_offset] = 0xDD; + for (i = 1; i < pad_len; i++) + Key_Data[data_offset + i] = 0; + + data_offset += pad_len; + } + AES_Key_Wrap(Key_Data, (UINT) data_offset, + &p4WayProfile->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + eGTK, &wrap_len); + data_offset = wrap_len; + } + else + { + TKIP_GTK_KEY_WRAP(&p4WayProfile->PTK[LEN_PTK_KCK], + pMsg->KeyDesc.KeyIv, + Key_Data, + data_offset, + eGTK); + } + + NdisMoveMemory(pKeyDesc->KeyData, eGTK, data_offset); + } + else + { + NdisMoveMemory(pKeyDesc->KeyData, Key_Data, data_offset); + } + + /* Update key data length field and total body length */ + SET_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, data_offset); + INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset); + + os_free_mem(NULL, mpool); + +} +#endif /* ADHOC_WPA2PSK_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_aes.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_aes.c new file mode 100644 index 000000000..e5050e493 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_aes.c @@ -0,0 +1,1605 @@ +/**************************************************************************** + * 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: + AES + + Abstract: + RFC 3394: Advanced Encryption Standard (AES) Key Wrap Algorithm + RFC 3601: Counter with CBC-MAC (CCM) + RFC 4493: The AES-CMAC Algorithm + FIPS PUBS 197: ADVANCED ENCRYPTION STANDARD (AES) + NIST 800-38A: Recommendation for Block Cipher Modes of Operation + NIST 800-38C: The CCM Mode for Authentication and Confidentiality + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/05/19 Create AES-Key Wrap + Eddy 2009/04/20 Create AES-CMAC, AES-CCM + Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC +***************************************************************************/ + +#include "crypt_aes.h" + + +/* The value given by [x^(i-1),{00},{00},{00}], with x^(i-1) being powers of x in the field GF(2^8). */ +static const UINT32 aes_rcon[] = { + 0x00000000, 0x01000000, 0x02000000, 0x04000000, + 0x08000000, 0x10000000, 0x20000000, 0x40000000, + 0x80000000, 0x1B000000, 0x36000000}; + +static const UINT8 aes_sbox_enc[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7 ,0xab, 0x76, /* 0 */ + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4 ,0x72, 0xc0, /* 1 */ + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8 ,0x31, 0x15, /* 2 */ + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27 ,0xb2, 0x75, /* 3 */ + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3 ,0x2f, 0x84, /* 4 */ + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c ,0x58, 0xcf, /* 5 */ + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c ,0x9f, 0xa8, /* 6 */ + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff ,0xf3, 0xd2, /* 7 */ + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d ,0x19, 0x73, /* 8 */ + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e ,0x0b, 0xdb, /* 9 */ + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95 ,0xe4, 0x79, /* a */ + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a ,0xae, 0x08, /* b */ + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd ,0x8b, 0x8a, /* c */ + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1 ,0x1d, 0x9e, /* d */ + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55 ,0x28, 0xdf, /* e */ + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54 ,0xbb, 0x16, /* f */ +}; + +static const UINT8 aes_sbox_dec[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, /* 0 */ + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, /* 1 */ + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, /* 2 */ + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, /* 3 */ + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, /* 4 */ + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, /* 5 */ + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, /* 6 */ + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, /* 7 */ + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, /* 8 */ + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, /* 9 */ + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, /* a */ + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, /* b */ + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, /* c */ + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, /* d */ + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, /* e */ + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, /* f */ +}; + +/* ArrayIndex*{02} */ +static const UINT8 aes_mul_2[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, /* 0 */ + 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, /* 1 */ + 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, /* 2 */ + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, /* 3 */ + 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, /* 4 */ + 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, /* 5 */ + 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, /* 6 */ + 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, /* 7 */ + 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, /* 8 */ + 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, /* 9 */ + 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, /* a */ + 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, /* b */ + 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, /* c */ + 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, /* d */ + 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, /* e */ + 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, /* f */ +}; + +/* ArrayIndex*{03} */ +static const UINT8 aes_mul_3[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, /* 0 */ + 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, /* 1 */ + 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, /* 2 */ + 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, /* 3 */ + 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, /* 4 */ + 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, /* 5 */ + 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, /* 6 */ + 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, /* 7 */ + 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, /* 8 */ + 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, /* 9 */ + 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, /* a */ + 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, /* b */ + 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, /* c */ + 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, /* d */ + 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, /* e */ + 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a, /* f */ +}; + +/* ArrayIndex*{09} */ +static const UINT8 aes_mul_9[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, /* 0 */ + 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, /* 1 */ + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, /* 2 */ + 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, /* 3 */ + 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, /* 4 */ + 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, /* 5 */ + 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, /* 6 */ + 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, /* 7 */ + 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, /* 8 */ + 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, /* 9 */ + 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, /* a */ + 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, /* b */ + 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, /* c */ + 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, /* d */ + 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, /* e */ + 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, /* f */ +}; + +/* ArrayIndex*{0b} */ +static const UINT8 aes_mul_b[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, /* 0 */ + 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, /* 1 */ + 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, /* 2 */ + 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, /* 3 */ + 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, /* 4 */ + 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, /* 5 */ + 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, /* 6 */ + 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, /* 7 */ + 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, /* 8 */ + 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, /* 9 */ + 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, /* a */ + 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, /* b */ + 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, /* c */ + 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, /* d */ + 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, /* e */ + 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, /* f */ +}; + +/* ArrayIndex*{0d} */ +static const UINT8 aes_mul_d[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, /* 0 */ + 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, /* 1 */ + 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, /* 2 */ + 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, /* 3 */ + 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, /* 4 */ + 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, /* 5 */ + 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, /* 6 */ + 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, /* 7 */ + 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, /* 8 */ + 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, /* 9 */ + 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, /* a */ + 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, /* b */ + 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, /* c */ + 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, /* d */ + 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, /* e */ + 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, /* f */ +}; + +/* ArrayIndex*{0e} */ +static const UINT8 aes_mul_e[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, /* 0 */ + 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, /* 1 */ + 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, /* 2 */ + 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, /* 3 */ + 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, /* 4 */ + 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, /* 5 */ + 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, /* 6 */ + 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, /* 7 */ + 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, /* 8 */ + 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, /* 9 */ + 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, /* a */ + 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, /* b */ + 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, /* c */ + 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, /* d */ + 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, /* e */ + 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, /* f */ +}; + +/* For AES_CMAC */ +#define AES_MAC_LENGTH 16 /* 128-bit string */ +static UINT8 Const_Zero[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 Const_Rb[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; + +/* +======================================================================== +Routine Description: + AES key expansion (key schedule) + +Arguments: + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + paes_ctx Pointer to AES_CTX_STRUC + +Return Value: + paes_ctx Retrun the KeyWordExpansion of AES_CTX_STRUC + +Note: + Pseudo code for key expansion + ------------------------------------------ + Nk = (key length/4); + + while (i < Nk) + KeyWordExpansion[i] = word(key[4*i], key[4*i + 1], key[4*i + 2], key[4*i + 3]); + i++; + end while + + while (i < ((key length/4 + 6 + 1)*4) ) + temp = KeyWordExpansion[i - 1]; + if (i % Nk ==0) + temp = SubWord(RotWord(temp)) ^ Rcon[i/Nk]; + else if ((Nk > 6) && (i % 4 == 4)) + temp = SubWord(temp); + end if + + KeyWordExpansion[i] = KeyWordExpansion[i - Nk]^ temp; + i++; + end while +======================================================================== +*/ +VOID RT_AES_KeyExpansion ( + IN UINT8 Key[], + IN UINT KeyLength, + INOUT AES_CTX_STRUC *paes_ctx) +{ + UINT KeyIndex = 0; + UINT NumberOfWordOfKey, NumberOfWordOfKeyExpansion; + UINT8 TempWord[AES_KEY_ROWS], Temp; + UINT32 Temprcon; + + NumberOfWordOfKey = KeyLength >> 2; + while (KeyIndex < NumberOfWordOfKey) + { + paes_ctx->KeyWordExpansion[0][KeyIndex] = Key[4*KeyIndex]; + paes_ctx->KeyWordExpansion[1][KeyIndex] = Key[4*KeyIndex + 1]; + paes_ctx->KeyWordExpansion[2][KeyIndex] = Key[4*KeyIndex + 2]; + paes_ctx->KeyWordExpansion[3][KeyIndex] = Key[4*KeyIndex + 3]; + KeyIndex++; + } + + NumberOfWordOfKeyExpansion = ((UINT) AES_KEY_ROWS) * ((KeyLength >> 2) + 6 + 1); + while (KeyIndex < NumberOfWordOfKeyExpansion) + { + TempWord[0] = paes_ctx->KeyWordExpansion[0][KeyIndex - 1]; + TempWord[1] = paes_ctx->KeyWordExpansion[1][KeyIndex - 1]; + TempWord[2] = paes_ctx->KeyWordExpansion[2][KeyIndex - 1]; + TempWord[3] = paes_ctx->KeyWordExpansion[3][KeyIndex - 1]; + if ((KeyIndex % NumberOfWordOfKey) == 0) { + Temprcon = aes_rcon[KeyIndex/NumberOfWordOfKey]; + Temp = aes_sbox_enc[TempWord[1]]^((Temprcon >> 24) & 0xff); + TempWord[1] = aes_sbox_enc[TempWord[2]]^((Temprcon >> 16) & 0xff); + TempWord[2] = aes_sbox_enc[TempWord[3]]^((Temprcon >> 8) & 0xff); + TempWord[3] = aes_sbox_enc[TempWord[0]]^((Temprcon ) & 0xff); + TempWord[0] = Temp; + } else if ((NumberOfWordOfKey > 6) && ((KeyIndex % NumberOfWordOfKey) == 4)) { + Temp = aes_sbox_enc[TempWord[0]]; + TempWord[1] = aes_sbox_enc[TempWord[1]]; + TempWord[2] = aes_sbox_enc[TempWord[2]]; + TempWord[3] = aes_sbox_enc[TempWord[3]]; + TempWord[0] = Temp; + } + paes_ctx->KeyWordExpansion[0][KeyIndex] = paes_ctx->KeyWordExpansion[0][KeyIndex - NumberOfWordOfKey]^TempWord[0]; + paes_ctx->KeyWordExpansion[1][KeyIndex] = paes_ctx->KeyWordExpansion[1][KeyIndex - NumberOfWordOfKey]^TempWord[1]; + paes_ctx->KeyWordExpansion[2][KeyIndex] = paes_ctx->KeyWordExpansion[2][KeyIndex - NumberOfWordOfKey]^TempWord[2]; + paes_ctx->KeyWordExpansion[3][KeyIndex] = paes_ctx->KeyWordExpansion[3][KeyIndex - NumberOfWordOfKey]^TempWord[3]; + KeyIndex++; + } +} + + +/* +======================================================================== +Routine Description: + AES encryption + +Arguments: + PlainBlock The block of plain text, 16 bytes(128 bits) each block + PlainBlockSize The length of block of plain text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + CipherBlockSize The length of allocated cipher block in bytes + +Return Value: + CipherBlock Return cipher text + CipherBlockSize Return the length of real used cipher block in bytes + +Note: + Reference to FIPS-PUB 197 + 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + 2. Transfer the plain block to state block + 3. Main encryption rounds + 4. Transfer the state block to cipher block + ------------------------------------------ + NumberOfRound = (key length / 4) + 6; + state block = plain block; + + AddRoundKey(state block, key); + for round = 1 to NumberOfRound + SubBytes(state block) + ShiftRows(state block) + MixColumns(state block) + AddRoundKey(state block, key); + end for + + SubBytes(state block) + ShiftRows(state block) + AddRoundKey(state block, key); + + cipher block = state block; +======================================================================== +*/ +VOID RT_AES_Encrypt ( + IN UINT8 PlainBlock[], + IN UINT PlainBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherBlock[], + INOUT UINT *CipherBlockSize) +{ +/* AES_CTX_STRUC aes_ctx; +*/ + AES_CTX_STRUC *paes_ctx = NULL; + UINT RowIndex, ColumnIndex; + UINT RoundIndex, NumberOfRound = 0; + UINT8 Temp, Row0, Row1, Row2, Row3; + + /* + * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + */ + if (PlainBlockSize != AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n", + PlainBlockSize, AES_BLOCK_SIZES)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (*CipherBlockSize < AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n", + *CipherBlockSize, AES_BLOCK_SIZES)); + return; + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&paes_ctx, sizeof(AES_CTX_STRUC)); + if (paes_ctx == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* + * 2. Transfer the plain block to state block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = PlainBlock[RowIndex + 4*ColumnIndex]; + + /* + * 3. Main encryption rounds + */ + RT_AES_KeyExpansion(Key, KeyLength, paes_ctx); + NumberOfRound = (KeyLength >> 2) + 6; + + /* AES_AddRoundKey */ + RoundIndex = 0; + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + for (RoundIndex = 1; RoundIndex < NumberOfRound;RoundIndex++) + { + /* AES_SubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_enc[paes_ctx->State[RowIndex][ColumnIndex]]; + + /* AES_ShiftRows */ + Temp = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = Temp; + + /* AES_MixColumns */ + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + { + Row0 = paes_ctx->State[0][ColumnIndex]; + Row1 = paes_ctx->State[1][ColumnIndex]; + Row2 = paes_ctx->State[2][ColumnIndex]; + Row3 = paes_ctx->State[3][ColumnIndex]; + paes_ctx->State[0][ColumnIndex] = aes_mul_2[Row0]^aes_mul_3[Row1]^Row2^Row3; + paes_ctx->State[1][ColumnIndex] = Row0^aes_mul_2[Row1]^aes_mul_3[Row2]^Row3; + paes_ctx->State[2][ColumnIndex] = Row0^Row1^aes_mul_2[Row2]^aes_mul_3[Row3]; + paes_ctx->State[3][ColumnIndex] = aes_mul_3[Row0]^Row1^Row2^aes_mul_2[Row3]; + } + + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + } + + /* AES_SubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_enc[paes_ctx->State[RowIndex][ColumnIndex]]; + /* AES_ShiftRows */ + Temp = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = Temp; + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + /* + * 4. Transfer the state block to cipher block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + CipherBlock[RowIndex + 4*ColumnIndex] = paes_ctx->State[RowIndex][ColumnIndex]; + + *CipherBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS); + + if (paes_ctx != NULL) + os_free_mem(NULL, paes_ctx); +} + + +/* +======================================================================== +Routine Description: + AES decryption + +Arguments: + CipherBlock The block of cipher text, 16 bytes(128 bits) each block + CipherBlockSize The length of block of cipher text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + PlainBlockSize The length of allocated plain block in bytes + +Return Value: + PlainBlock Return plain text + PlainBlockSize Return the length of real used plain block in bytes + +Note: + Reference to FIPS-PUB 197 + 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + 2. Transfer the cipher block to state block + 3. Main decryption rounds + 4. Transfer the state block to plain block + ------------------------------------------ + NumberOfRound = (key length / 4) + 6; + state block = cipher block; + + AddRoundKey(state block, key); + for round = NumberOfRound to 1 + InvSubBytes(state block) + InvShiftRows(state block) + InvMixColumns(state block) + AddRoundKey(state block, key); + end for + + InvSubBytes(state block) + InvShiftRows(state block) + AddRoundKey(state block, key); + + plain block = state block; +======================================================================== +*/ +VOID RT_AES_Decrypt ( + IN UINT8 CipherBlock[], + IN UINT CipherBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainBlock[], + INOUT UINT *PlainBlockSize) +{ +/* AES_CTX_STRUC aes_ctx; +*/ + AES_CTX_STRUC *paes_ctx = NULL; + UINT RowIndex, ColumnIndex; + UINT RoundIndex, NumberOfRound = 0; + UINT8 Temp, Row0, Row1, Row2, Row3; + + /* + * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + */ + if (*PlainBlockSize < AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n", + *PlainBlockSize, AES_BLOCK_SIZES)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (CipherBlockSize != AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n", + CipherBlockSize, AES_BLOCK_SIZES)); + return; + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&paes_ctx, sizeof(AES_CTX_STRUC)); + if (paes_ctx == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* + * 2. Transfer the cipher block to state block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = CipherBlock[RowIndex + 4*ColumnIndex]; + + /* + * 3. Main decryption rounds + */ + RT_AES_KeyExpansion(Key, KeyLength, paes_ctx); + NumberOfRound = (KeyLength >> 2) + 6; + + /* AES_AddRoundKey */ + RoundIndex = NumberOfRound; + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + for (RoundIndex = (NumberOfRound - 1); RoundIndex > 0 ;RoundIndex--) + { + /* AES_InvShiftRows */ + Temp = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = Temp; + + /* AES_InvSubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_dec[paes_ctx->State[RowIndex][ColumnIndex]]; + + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + /* AES_InvMixColumns */ + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + { + Row0 = paes_ctx->State[0][ColumnIndex]; + Row1 = paes_ctx->State[1][ColumnIndex]; + Row2 = paes_ctx->State[2][ColumnIndex]; + Row3 = paes_ctx->State[3][ColumnIndex]; + paes_ctx->State[0][ColumnIndex] = aes_mul_e[Row0]^aes_mul_b[Row1]^aes_mul_d[Row2]^aes_mul_9[Row3]; + paes_ctx->State[1][ColumnIndex] = aes_mul_9[Row0]^aes_mul_e[Row1]^aes_mul_b[Row2]^aes_mul_d[Row3]; + paes_ctx->State[2][ColumnIndex] = aes_mul_d[Row0]^aes_mul_9[Row1]^aes_mul_e[Row2]^aes_mul_b[Row3]; + paes_ctx->State[3][ColumnIndex] = aes_mul_b[Row0]^aes_mul_d[Row1]^aes_mul_9[Row2]^aes_mul_e[Row3]; + } + } + + /* AES_InvShiftRows */ + Temp = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = Temp; + /* AES_InvSubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_dec[paes_ctx->State[RowIndex][ColumnIndex]]; + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + /* + * 4. Transfer the state block to plain block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + PlainBlock[RowIndex + 4*ColumnIndex] = paes_ctx->State[RowIndex][ColumnIndex]; + + *PlainBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS); + + if (paes_ctx != NULL) + os_free_mem(NULL, paes_ctx); +} + + + +/* +======================================================================== +Routine Description: + AES-CBCMAC + +Arguments: + Payload Data + PayloadLength The length of data in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + Nonce Nonce + NonceLength The length of nonce in bytes + AAD Additional authenticated data + AADLength The length of AAD in bytes + MACLength The length of MAC in bytes + +Return Value: + MACText The mac + +Note: + Reference to RFC 3601, and NIST 800-38C. +======================================================================== +*/ +VOID AES_CCM_MAC ( + IN UINT8 Payload[], + IN UINT PayloadLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 MACText[]) +{ + UINT8 Block[AES_BLOCK_SIZES], Block_MAC[AES_BLOCK_SIZES]; + UINT Block_Index = 0, ADD_Index = 0, Payload_Index = 0; + UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0; + + /* + * 1. Formatting of the Control Information and the Nonce + */ + NdisZeroMemory(Block, AES_BLOCK_SIZES); + if (AADLength > 0) + Block[0] |= 0x40; /* Set bit 6 to 1 */ + Temp_Value = ((MACLength - 2) >> 1) << 3; /* Set bit 3-5 to (t-2)/2 */ + Block[0] |= Temp_Value; + Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */ + Block[0] |= Temp_Value; + for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++) + Block[Temp_Index + 1] = Nonce[Temp_Index]; + if (NonceLength < 12) + Block[12] = (PayloadLength >> 24) & 0xff; + if (NonceLength < 13) + Block[13] = (PayloadLength >> 16) & 0xff; + Block[14] = (PayloadLength >> 8) & 0xff; + Block[15] = PayloadLength & 0xff; + + NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES); + Temp_Length = sizeof(Block_MAC); + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length); + + /* + * 2. Formatting of the Associated Data + * If 0 < AADLength < (2^16 - 2^8), AData_Length = 2 + * If (2^16 - 2^8) < AADLength < 2^32, AData_Length = 6 + * If 2^32 < AADLength < 2^64, AData_Length = 10 (not implement) + */ + NdisZeroMemory(Block, AES_BLOCK_SIZES); + if ((AADLength > 0) && (AADLength < 0xFF00)) { + Block_Index = 2; + Block[0] = (AADLength >> 8) & 0xff; + Block[1] = AADLength & 0xff; + } else { + Block_Index = 6; + Block[2] = (AADLength >> 24) & 0xff; + Block[3] = (AADLength >> 16) & 0xff; + Block[4] = (AADLength >> 8) & 0xff; + Block[5] = AADLength & 0xff; + } + + while (ADD_Index < AADLength) + { + Copy_Length = AADLength - ADD_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + if ((Copy_Length + Block_Index) > AES_BLOCK_SIZES) { + Copy_Length = AES_BLOCK_SIZES - Block_Index; + } + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + Block[Temp_Index + Block_Index] = AAD[ADD_Index + Temp_Index]; + for (Temp_Index = 0; Temp_Index < AES_BLOCK_SIZES; Temp_Index++) + Block[Temp_Index] ^= Block_MAC[Temp_Index]; + NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES); + Temp_Length = sizeof(Block_MAC); + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length); + ADD_Index += Copy_Length; + Block_Index = 0; + NdisZeroMemory(Block, AES_BLOCK_SIZES); + } + + /* + * 3. Calculate the MAC (MIC) + */ + while (Payload_Index < PayloadLength) + { + NdisZeroMemory(Block, AES_BLOCK_SIZES); + Copy_Length = PayloadLength - Payload_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + Block[Temp_Index] = Payload[Payload_Index + Temp_Index]; + for (Temp_Index = 0; Temp_Index < AES_BLOCK_SIZES; Temp_Index++) + Block[Temp_Index] ^= Block_MAC[Temp_Index]; + NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES); + Temp_Length = sizeof(Block_MAC); + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length); + Payload_Index += Copy_Length; + } + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + MACText[Temp_Index] = Block_MAC[Temp_Index]; +} + + +/* +======================================================================== +Routine Description: + AES-CBCMAC Encryption + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + Nonce Nonce + NonceLength The length of nonce in bytes + AAD Additional authenticated data + AADLength The length of AAD in bytes + MACLength The length of MAC in bytes + CipherTextLength The length of allocated memory spaces in bytes + +Return Value: + CipherText The ciphertext + CipherTextLength Return the length of the ciphertext in bytes + +Function Value: + 0: Success + -1: The key length must be 16 bytes. + -2: A valid nonce length is 7-13 bytes. + -3: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes. + -4: The CipherTextLength is not enough. + +Note: + Reference to RFC 3601, and NIST 800-38C. + Here, the implement of AES_CCM is suitable for WI_FI. +======================================================================== +*/ +INT AES_CCM_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength) +{ + UINT8 Block_MAC[AES_BLOCK_SIZES]; + UINT8 Block_CTR[AES_BLOCK_SIZES], Block_CTR_Cipher[AES_BLOCK_SIZES]; + UINT Cipher_Index = 0; + UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0; + + /* + * 1. Check Input Values + * - Key length must be 16 bytes + * - Nonce length range is form 7 to 13 bytes + * - MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes + * - CipherTextLength > PlainTextLength + MACLength + */ + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The key length must be %d bytes\n", AES_KEY128_LENGTH)); + return -1; + } + + if ((NonceLength < 7) || (NonceLength > 13)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: A valid nonce length is 7-13 bytes\n")); + return -2; + } + + if ((MACLength != 4) && (MACLength != 6) && (MACLength != 8) && (MACLength != 10) + && (MACLength != 12) && (MACLength != 14) && (MACLength != 16)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes\n")); + return -3; + } + + if (*CipherTextLength < (PlainTextLength + MACLength)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The CipherTextLength is not enough.\n")); + return -4; + } + + + /* + * 1. Formatting of the Counter Block + */ + NdisZeroMemory(Block_CTR, AES_BLOCK_SIZES); + Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */ + Block_CTR[0] |= Temp_Value; + for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++) + Block_CTR[Temp_Index + 1] = Nonce[Temp_Index]; + + /* + * 2. Calculate the MAC (MIC) + */ + AES_CCM_MAC(PlainText, PlainTextLength, Key, KeyLength, Nonce, NonceLength, AAD, AADLength, MACLength, Block_MAC); + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + Block_MAC[Temp_Index] ^= Block_CTR_Cipher[Temp_Index]; + + /* + * 3. Cipher Payload + */ + while (Cipher_Index < PlainTextLength) + { + Block_CTR[15] += 1; + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + + Copy_Length = PlainTextLength - Cipher_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + CipherText[Cipher_Index + Temp_Index] = PlainText[Cipher_Index + Temp_Index]^Block_CTR_Cipher[Temp_Index]; + + Cipher_Index += Copy_Length; + } + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + CipherText[PlainTextLength + Temp_Index] = Block_MAC[Temp_Index]; + *CipherTextLength = PlainTextLength + MACLength; + + return 0; +} + + +/* +======================================================================== +Routine Description: + AES-CBCMAC Decryption + +Arguments: + CipherText The ciphertext + CipherTextLength The length of cipher text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + Nonce Nonce + NonceLength The length of nonce in bytes + AAD Additional authenticated data + AADLength The length of AAD in bytes + CipherTextLength The length of allocated memory spaces in bytes + +Return Value: + PlainText Plain text + PlainTextLength Return the length of the plain text in bytes + +Function Value: + 0: Success + -1: The key length must be 16 bytes. + -2: A valid nonce length is 7-13 bytes. + -3: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes. + -4: The PlainTextLength is not enough. + -5: The MIC does not match. + +Note: + Reference to RFC 3601, and NIST 800-38C. + Here, the implement of AES_CCM is suitable for WI_FI. +======================================================================== +*/ +INT AES_CCM_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength) +{ + UINT8 Block_MAC[AES_BLOCK_SIZES], Block_MAC_From_Cipher[AES_BLOCK_SIZES]; + UINT8 Block_CTR[AES_BLOCK_SIZES], Block_CTR_Cipher[AES_BLOCK_SIZES]; + UINT Block_Index = 0, Cipher_Index = 0; + UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0; + + + /* + * 1. Check Input Values + * - Key length must be 16 bytes + * - Nonce length range is form 7 to 13 bytes + */ + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The key length must be %d bytes\n", AES_KEY128_LENGTH)); + return -1; + } + + if ((NonceLength < 7) || (NonceLength > 13)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: A valid nonce length is 7-13 bytes\n")); + return -2; + } + + if ((MACLength != 4) && (MACLength != 6) && (MACLength != 8) && (MACLength != 10) + && (MACLength != 12) && (MACLength != 14) && (MACLength != 16)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes\n")); + return -3; + } + + if (*PlainTextLength < (CipherTextLength - MACLength)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The PlainTextLength is not enough.\n")); + return -4; + } + + /* + * 2. Formatting of the Counter Block + */ + NdisZeroMemory(Block_CTR, AES_BLOCK_SIZES); + Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */ + Block_CTR[0] |= Temp_Value; + for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++) + Block_CTR[Temp_Index + 1] = Nonce[Temp_Index]; + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + + /* + * 3. Catch the MAC (MIC) from CipherText + */ + Block_Index = 0; + for (Temp_Index = (CipherTextLength - MACLength); Temp_Index < CipherTextLength; Temp_Index++, Block_Index++) + Block_MAC_From_Cipher[Block_Index] = CipherText[Temp_Index]^Block_CTR_Cipher[Block_Index]; + + /* + * 4. Decryption the Payload + */ + while (Cipher_Index < (CipherTextLength - MACLength)) + { + Block_CTR[15] += 1; + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + + Copy_Length = (CipherTextLength - MACLength) - Cipher_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + PlainText[Cipher_Index + Temp_Index] = CipherText[Cipher_Index + Temp_Index]^Block_CTR_Cipher[Temp_Index]; + Cipher_Index += Copy_Length; + } + *PlainTextLength = CipherTextLength - MACLength; + + /* + * 5. Calculate the MAC (MIC) from Payload + */ + AES_CCM_MAC(PlainText, *PlainTextLength, Key, KeyLength, Nonce, NonceLength, AAD, AADLength, MACLength, Block_MAC); + + /* + * 6. Check the MIC + */ + if (NdisCmpMemory(Block_MAC_From_Cipher, Block_MAC, MACLength) != 0) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The MIC does not match.\n")); + return -5; + } + + return 0; +} + + +/* +======================================================================== +Routine Description: + AES-CMAC generate subkey + +Arguments: + Key Cipher key 128 bits + KeyLength The length of Cipher key in bytes + +Return Value: + SubKey1 SubKey 1 128 bits + SubKey2 SubKey 2 128 bits + +Note: + Reference to RFC 4493 + + Step 1. L := AES-128(K, const_Zero); + Step 2. if MSB(L) is equal to 0 + then K1 := L << 1; + else K1 := (L << 1) XOR const_Rb; + Step 3. if MSB(K1) is equal to 0 + then K2 := K1 << 1; + else K2 := (K1 << 1) XOR const_Rb; + Step 4. return K1, K2; +======================================================================== +*/ +VOID AES_CMAC_GenerateSubKey ( + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 SubKey1[], + OUT UINT8 SubKey2[]) +{ + UINT8 MSB_L = 0, MSB_K1 = 0, Top_Bit = 0; + UINT SubKey1_Length = 0; + INT Index = 0; + + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC_GenerateSubKey: key length is %d bytes, it must be %d bytes(128 bits).\n", + KeyLength, AES_KEY128_LENGTH)); + return; + } + + /* Step 1: L := AES-128(K, const_Zero); */ + SubKey1_Length = 16; + RT_AES_Encrypt(Const_Zero, sizeof(Const_Zero), Key, KeyLength, SubKey1, &SubKey1_Length); + + /* + * Step 2. if MSB(L) is equal to 0 + * then K1 := L << 1; + * else K1 := (L << 1) XOR const_Rb; + */ + MSB_L = SubKey1[0] & 0x80; + for(Index = 0; Index < 15; Index++) { + Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0; + SubKey1[Index] <<= 1; + SubKey1[Index] |= Top_Bit; + } + SubKey1[15] <<= 1; + if (MSB_L > 0) { + for(Index = 0; Index < 16; Index++) + SubKey1[Index] ^= Const_Rb[Index]; + } + + /* + * Step 3. if MSB(K1) is equal to 0 + * then K2 := K1 << 1; + * else K2 := (K1 << 1) XOR const_Rb; + */ + MSB_K1 = SubKey1[0] & 0x80; + for(Index = 0; Index < 15; Index++) { + Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0; + SubKey2[Index] = SubKey1[Index] << 1; + SubKey2[Index] |= Top_Bit; + } + SubKey2[15] = SubKey1[15] << 1; + if (MSB_K1 > 0) { + for(Index = 0; Index < 16; Index++) + SubKey2[Index] ^= Const_Rb[Index]; + } +} + + +/* +======================================================================== +Routine Description: + AES-CMAC + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + MACTextLength The length of allocated memory spaces in bytes + +Return Value: + MACText Message authentication code (128-bit string) + MACTextLength Return the length of Message authentication code in bytes + +Note: + Reference to RFC 4493 +======================================================================== +*/ +VOID AES_CMAC ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 MACText[], + INOUT UINT *MACTextLength) +{ + UINT PlainBlockStart; + UINT8 X[AES_BLOCK_SIZES], Y[AES_BLOCK_SIZES]; + UINT8 SubKey1[16]; + UINT8 SubKey2[16]; + INT Index; + UINT X_Length; + + if (*MACTextLength < AES_MAC_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: MAC text length is less than %d bytes).\n", + AES_MAC_LENGTH)); + return; + } + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: key length is %d bytes, it must be %d bytes(128 bits).\n", + KeyLength, AES_KEY128_LENGTH)); + return; + } + + /* Step 1. (K1,K2) := Generate_Subkey(K); */ + NdisZeroMemory(SubKey1, 16); + NdisZeroMemory(SubKey2, 16); + AES_CMAC_GenerateSubKey(Key, KeyLength, SubKey1, SubKey2); + + /* + * 2. Main algorithm + * - Plain text divide into serveral blocks (16 bytes/block) + * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text) + * - Execute RT_AES_Encrypt procedure. + */ + PlainBlockStart = 0; + NdisMoveMemory(X, Const_Zero, AES_BLOCK_SIZES); + while ((PlainTextLength - PlainBlockStart) > AES_BLOCK_SIZES) + { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]; + + X_Length = sizeof(X); + RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, X, &X_Length); + PlainBlockStart += ((UINT) AES_BLOCK_SIZES); + } + if ((PlainTextLength - PlainBlockStart) == AES_BLOCK_SIZES) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]^SubKey1[Index]; + } else { + NdisZeroMemory(Y, AES_BLOCK_SIZES); + NdisMoveMemory(Y, &PlainText[PlainBlockStart], (PlainTextLength - PlainBlockStart)); + Y[(PlainTextLength - PlainBlockStart)] = 0x80; + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Y[Index] = Y[Index]^X[Index]^SubKey2[Index]; + } + RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, MACText, MACTextLength); +} + + +/* For AES_Key_Wrap */ +#define AES_KEY_WRAP_IV_LENGTH 8 /* 64-bit */ +#define AES_KEY_WRAP_BLOCK_SIZE 8 /* 64-bit */ +static UINT8 Default_IV[8] = { + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6}; + +/* +======================================================================== +Routine Description: + AES-CBC encryption + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + IV Initialization vector, it may be 16 bytes (128 bits) + IVLength The length of initialization vector in bytes + CipherTextLength The length of allocated cipher text in bytes + +Return Value: + CipherText Return cipher text + CipherTextLength Return the length of real used cipher text in bytes + +Note: + Reference to RFC 3602 and NIST 800-38A +======================================================================== +*/ +VOID AES_CBC_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength) +{ + UINT PaddingSize, PlainBlockStart, CipherBlockStart, CipherBlockSize; + UINT Index; + UINT8 Block[AES_BLOCK_SIZES]; + + /* + * 1. Check the input parameters + * - CipherTextLength > (PlainTextLength + Padding size), Padding size = block size - (PlainTextLength % block size) + * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits) + * - IV length must be 16 bytes(128 bits) + */ + PaddingSize = ((UINT) AES_BLOCK_SIZES) - (PlainTextLength % ((UINT)AES_BLOCK_SIZES)); + if (*CipherTextLength < (PlainTextLength + PaddingSize)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: cipher text length is %d bytes < (plain text length %d bytes + padding size %d bytes).\n", + *CipherTextLength, PlainTextLength, PaddingSize)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (IVLength != AES_CBC_IV_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: IV length is %d bytes, it must be %d bytes(128bits).\n", + IVLength, AES_CBC_IV_LENGTH)); + return; + } + + + /* + * 2. Main algorithm + * - Plain text divide into serveral blocks (16 bytes/block) + * - If plain text is divided with no remainder by block, add a new block and padding size = block(16 bytes) + * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text) + * - Execute RT_AES_Encrypt procedure. + * + * - Padding method: The remainder bytes will be filled with padding size (1 byte) + */ + PlainBlockStart = 0; + CipherBlockStart = 0; + while ((PlainTextLength - PlainBlockStart) >= AES_BLOCK_SIZES) + { + if (CipherBlockStart == 0) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] = PlainText[PlainBlockStart + Index]^IV[Index]; + } else { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] = PlainText[PlainBlockStart + Index]^CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index]; + } + + CipherBlockSize = *CipherTextLength - CipherBlockStart; + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); + + PlainBlockStart += ((UINT) AES_BLOCK_SIZES); + CipherBlockStart += CipherBlockSize; + } + + NdisMoveMemory(Block, (&PlainText[0] + PlainBlockStart), (PlainTextLength - PlainBlockStart)); + NdisFillMemory((Block + (((UINT) AES_BLOCK_SIZES) -PaddingSize)), PaddingSize, (UINT8) PaddingSize); + if (CipherBlockStart == 0) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] ^= IV[Index]; + } else { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] ^= CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index]; + } + CipherBlockSize = *CipherTextLength - CipherBlockStart; + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); + CipherBlockStart += CipherBlockSize; + *CipherTextLength = CipherBlockStart; +} + + +/* +======================================================================== +Routine Description: + AES-CBC decryption + +Arguments: + CipherText Cipher text + CipherTextLength The length of cipher text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + IV Initialization vector, it may be 16 bytes (128 bits) + IVLength The length of initialization vector in bytes + PlainTextLength The length of allocated plain text in bytes + +Return Value: + PlainText Return plain text + PlainTextLength Return the length of real used plain text in bytes + +Note: + Reference to RFC 3602 and NIST 800-38A +======================================================================== +*/ +VOID AES_CBC_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength) +{ + UINT PaddingSize, PlainBlockStart, CipherBlockStart, PlainBlockSize; + UINT Index; + + /* + * 1. Check the input parameters + * - CipherTextLength must be divided with no remainder by block + * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits) + * - IV length must be 16 bytes(128 bits) + */ + if ((CipherTextLength % AES_BLOCK_SIZES) != 0) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: cipher text length is %d bytes, it can't be divided with no remainder by block size(%d).\n", + CipherTextLength, AES_BLOCK_SIZES)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (IVLength != AES_CBC_IV_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: IV length is %d bytes, it must be %d bytes(128bits).\n", + IVLength, AES_CBC_IV_LENGTH)); + return; + } + + + /* + * 2. Main algorithm + * - Cypher text divide into serveral blocks (16 bytes/block) + * - Execute RT_AES_Decrypt procedure. + * - Remove padding bytes, padding size is the last byte of plain text + */ + CipherBlockStart = 0; + PlainBlockStart = 0; + while ((CipherTextLength - CipherBlockStart) >= AES_BLOCK_SIZES) + { + PlainBlockSize = *PlainTextLength - PlainBlockStart; + RT_AES_Decrypt(CipherText + CipherBlockStart, AES_BLOCK_SIZES , Key, KeyLength, PlainText + PlainBlockStart, &PlainBlockSize); + + if (PlainBlockStart == 0) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + PlainText[PlainBlockStart + Index] ^= IV[Index]; + } else { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + PlainText[PlainBlockStart + Index] ^= CipherText[CipherBlockStart + Index - ((UINT) AES_BLOCK_SIZES)]; + } + + CipherBlockStart += AES_BLOCK_SIZES; + PlainBlockStart += PlainBlockSize; + } + + PaddingSize = (UINT8) PlainText[PlainBlockStart -1]; + *PlainTextLength = PlainBlockStart - PaddingSize; + +} + + +/* +======================================================================== +Routine Description: + AES key wrap algorithm + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + +Return Value: + CipherText The ciphertext + CipherTextLength Return the length of the ciphertext in bytes + +Function Value: + 0: Success + -1: The key length must be 16, 24, or 32 bytes + -2: Not enough memory + +Note: + Reference to RFC 3394 +======================================================================== +*/ +INT AES_Key_Wrap ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherText[], + OUT UINT *CipherTextLength) +{ + UINT8 IV[8], Block_B[16], Block_Input[16]; + UINT8 *pResult; + UINT Temp_Length = 0, Number_Of_Block = 0; + INT Index_i = 0, Index_j = 0; + + /* + * 0. Check input parameter + */ + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Wrap: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return -1; + } /* End of if */ + os_alloc_mem(NULL, (UCHAR **)&pResult, sizeof(UINT8)*PlainTextLength); +/* if ((pResult = (UINT8 *) kmalloc(sizeof(UINT8)*PlainTextLength, GFP_ATOMIC)) == NULL) { +*/ + if (pResult == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Wrap: allocate %d bytes memory failure.\n", sizeof(UINT8)*PlainTextLength)); + return -2; + } /* End of if */ + + + /* + * 1. Initialize variables + */ + Number_Of_Block = PlainTextLength / AES_KEY_WRAP_BLOCK_SIZE; /* 64 bits each block +*/ + NdisMoveMemory(IV, Default_IV, AES_KEY_WRAP_IV_LENGTH); + NdisMoveMemory(pResult, PlainText, PlainTextLength); + + + /* + * 2. Calculate intermediate values + */ + for (Index_j = 0;Index_j < 6 ;Index_j++) + { + for (Index_i = 0;Index_i < Number_Of_Block;Index_i++) + { + NdisMoveMemory(Block_Input, IV, 8); + NdisMoveMemory(Block_Input + 8, pResult + (Index_i*8), 8); + Temp_Length = sizeof(Block_B); + RT_AES_Encrypt(Block_Input, AES_BLOCK_SIZES , Key, KeyLength, Block_B, &Temp_Length); + + NdisMoveMemory(IV, Block_B, 8); + IV[7] = Block_B[7] ^ ((Number_Of_Block * Index_j) + Index_i + 1); + NdisMoveMemory(pResult + (Index_i*8), (Block_B + 8), 8); + } /* End of for */ + } /* End of for */ + + + /* + * 3. Output the results + */ + *CipherTextLength = PlainTextLength + AES_KEY_WRAP_IV_LENGTH; + NdisMoveMemory(CipherText, IV, AES_KEY_WRAP_IV_LENGTH); + NdisMoveMemory(CipherText + AES_KEY_WRAP_IV_LENGTH, pResult, PlainTextLength); + +/* kfree(pResult); +*/ + os_free_mem(NULL, pResult); + return 0; +} /* End of AES_Key_Wrap */ + + +/* +======================================================================== +Routine Description: + AES key unwrap algorithm + +Arguments: + CipherText The ciphertext + CipherTextLength The length of cipher text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + +Return Value: + PlainText Plain text + PlainTextLength Return the length of the plain text in bytes + +Function Value: + 0: Success + +Note: + Reference to RFC 3394 +======================================================================== +*/ +INT AES_Key_Unwrap ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainText[], + OUT UINT *PlainTextLength) +{ + UINT8 IV[8], Block_B[16], Block_Input[16]; + UINT8 *pResult; + UINT Temp_Length = 0, Number_Of_Block = 0, PlainLength; + INT Index_i = 0, Index_j = 0; + + /* + * 0. Check input parameter + */ + PlainLength = CipherTextLength - AES_KEY_WRAP_IV_LENGTH; + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Unwrap: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return -1; + } /* End of if */ + os_alloc_mem(NULL, (UCHAR **)&pResult, sizeof(UINT8)*PlainLength); +/* if ((pResult = (UINT8 *) kmalloc(sizeof(UINT8)*PlainLength, GFP_ATOMIC)) == NULL) { +*/ + if (pResult == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Unwrap: allocate %d bytes memory failure.\n", sizeof(UINT8)*PlainLength)); + return -2; + } /* End of if */ + + + /* + * 1. Initialize variables + */ + Number_Of_Block = PlainLength / AES_KEY_WRAP_BLOCK_SIZE; /* 64 bits each block +*/ + NdisMoveMemory(IV, CipherText, AES_KEY_WRAP_IV_LENGTH); + NdisMoveMemory(pResult, CipherText + AES_KEY_WRAP_IV_LENGTH, PlainLength); + + + /* + * 2. Calculate intermediate values + */ + for (Index_j = 5;Index_j >= 0 ;Index_j--) + { + for (Index_i = (Number_Of_Block - 1);Index_i >= 0;Index_i--) + { + IV[7] = IV[7] ^ ((Number_Of_Block * Index_j) + Index_i + 1); + NdisMoveMemory(Block_Input, IV, 8); + NdisMoveMemory(Block_Input + 8, pResult + (Index_i*8), 8); + Temp_Length = sizeof(Block_B); + RT_AES_Decrypt(Block_Input, AES_BLOCK_SIZES , Key, KeyLength, Block_B, &Temp_Length); + + NdisMoveMemory(IV, Block_B, 8); + NdisMoveMemory(pResult + (Index_i*8), (Block_B + 8), 8); + } /* End of for */ + } /* End of for */ + + /* + * 3. Output the results + */ + *PlainTextLength = PlainLength; + NdisMoveMemory(PlainText, pResult, PlainLength); + +/* kfree(pResult); +*/ + os_free_mem(NULL, pResult); + return 0; +} /* End of AES_Key_Unwrap */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_arc4.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_arc4.c new file mode 100644 index 000000000..382b89631 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_arc4.c @@ -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 */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_biginteger.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_biginteger.c new file mode 100644 index 000000000..f15012f72 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_biginteger.c @@ -0,0 +1,1116 @@ +/**************************************************************************** + * 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. + ***************************************************************************/ +#include "crypt_biginteger.h" + + +#ifdef __KERNEL__ +#define DEBUGPRINT(fmt, args...) printk(KERN_ERR fmt, ## args) +#else +#define DEBUGPRINT(fmt, args...) printf(fmt, ## args) +#endif /* __KERNEL__ */ + +#define UINT32_HBITS(value) (((value) >> 0x10) & 0xffff) +#define UINT32_LBITS(value) ((value) & 0xffff) +#define UINT32_GETBYTE(value, index) (((value) >> ((index)*8)) & 0xff) +#define UINT64_HBITS(value) (((value) >> 0x20) & 0xffffffff) +#define UINT64_LBITS(value) ((value) & 0xffffffff) + +static UINT8 WPS_DH_P_VALUE[192] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static UINT8 WPS_DH_R_VALUE[193] = +{ + 0x01, 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, 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, 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, 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, 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, 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 UINT8 WPS_DH_X_VALUE[184] = +{ + 0x36, 0xf0, 0x25, 0x5d, 0xde, 0x97, 0x3d, 0xcb, + 0x3b, 0x39, 0x9d, 0x74, 0x7f, 0x23, 0xe3, 0x2e, + 0xd6, 0xfd, 0xb1, 0xf7, 0x75, 0x98, 0x33, 0x8b, + 0xfd, 0xf4, 0x41, 0x59, 0xc4, 0xec, 0x64, 0xdd, + 0xae, 0xb5, 0xf7, 0x86, 0x71, 0xcb, 0xfb, 0x22, + 0x10, 0x6a, 0xe6, 0x4c, 0x32, 0xc5, 0xbc, 0xe4, + 0xcf, 0xd4, 0xf5, 0x92, 0x0d, 0xa0, 0xeb, 0xc8, + 0xb0, 0x1e, 0xca, 0x92, 0x92, 0xae, 0x3d, 0xba, + 0x1b, 0x7a, 0x4a, 0x89, 0x9d, 0xa1, 0x81, 0x39, + 0x0b, 0xb3, 0xbd, 0x16, 0x59, 0xc8, 0x12, 0x94, + 0xf4, 0x00, 0xa3, 0x49, 0x0b, 0xf9, 0x48, 0x12, + 0x11, 0xc7, 0x94, 0x04, 0xa5, 0x76, 0x60, 0x5a, + 0x51, 0x60, 0xdb, 0xee, 0x83, 0xb4, 0xe0, 0x19, + 0xb6, 0xd7, 0x99, 0xae, 0x13, 0x1b, 0xa4, 0xc2, + 0x3d, 0xff, 0x83, 0x47, 0x5e, 0x9c, 0x40, 0xfa, + 0x67, 0x25, 0xb7, 0xc9, 0xe3, 0xaa, 0x2c, 0x65, + 0x96, 0xe9, 0xc0, 0x57, 0x02, 0xdb, 0x30, 0xa0, + 0x7c, 0x9a, 0xa2, 0xdc, 0x23, 0x5c, 0x52, 0x69, + 0xe3, 0x9d, 0x0c, 0xa9, 0xdf, 0x7a, 0xad, 0x44, + 0x61, 0x2a, 0xd6, 0xf8, 0x8f, 0x69, 0x69, 0x92, + 0x98, 0xf3, 0xca, 0xb1, 0xb5, 0x43, 0x67, 0xfb, + 0x0e, 0x8b, 0x93, 0xf7, 0x35, 0xdc, 0x8c, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + +static UINT8 WPS_DH_RRModP_VALUE[192] = +{ + 0xe3, 0xb3, 0x3c, 0x72, 0x59, 0x54, 0x1c, 0x01, + 0xee, 0x9c, 0x9a, 0x21, 0x6c, 0xc1, 0xeb, 0xd2, + 0xae, 0x59, 0x41, 0x04, 0x79, 0x29, 0xa1, 0xc7, + 0xe9, 0xc3, 0xfa, 0x02, 0xcc, 0x24, 0x56, 0xef, + 0x10, 0x26, 0x30, 0xfa, 0x9a, 0x36, 0xa5, 0x1f, + 0x57, 0xb5, 0x93, 0x48, 0x67, 0x98, 0x44, 0x60, + 0x0b, 0xe4, 0x96, 0x47, 0xa8, 0x7c, 0x7b, 0x37, + 0xf8, 0x05, 0x65, 0x64, 0x96, 0x9b, 0x7f, 0x02, + 0xdc, 0x54, 0x1a, 0x4e, 0xd4, 0x05, 0x3f, 0x54, + 0xd6, 0x2a, 0x0e, 0xea, 0xb2, 0x70, 0x52, 0x1b, + 0x22, 0xc2, 0x96, 0xe9, 0xd4, 0x6f, 0xec, 0x23, + 0x8e, 0x1a, 0xbd, 0x78, 0x02, 0x23, 0xb7, 0x6b, + 0xb8, 0xfe, 0x61, 0x21, 0x19, 0x6b, 0x7e, 0x88, + 0x1c, 0x72, 0x9c, 0x7e, 0x04, 0xb9, 0xf7, 0x96, + 0x07, 0xcd, 0x0a, 0x62, 0x8e, 0x43, 0x41, 0x30, + 0x04, 0xa5, 0x41, 0xff, 0x93, 0xae, 0x1c, 0xeb, + 0xb0, 0x04, 0xa7, 0x50, 0xdb, 0x10, 0x2d, 0x39, + 0xb9, 0x05, 0x2b, 0xb4, 0x7a, 0x58, 0xf1, 0x70, + 0x7e, 0x8c, 0xd2, 0xac, 0x98, 0xb5, 0xfb, 0x62, + 0x8f, 0x23, 0x31, 0xb1, 0x3b, 0x01, 0xe0, 0x18, + 0xf4, 0x66, 0xee, 0x5f, 0xbc, 0xd4, 0x9d, 0x68, + 0xd0, 0xab, 0x92, 0xe1, 0x83, 0x97, 0xf2, 0x45, + 0x8e, 0x0e, 0x3e, 0x21, 0x67, 0x47, 0x8c, 0x73, + 0xf1, 0x15, 0xd2, 0x7d, 0x32, 0xc6, 0x95, 0xe0, +}; + +static UINT8 Value_0[1] = {0x00}; +static UINT8 Value_1[1] = {0x01}; +static PBIG_INTEGER pBI_U = NULL, pBI_S = NULL, pBI_O = NULL; +static UINT Bits_Of_R = 0; + + +VOID BigInteger_Print ( + IN PBIG_INTEGER pBI) +{ + int i = 0, j = 0; + + if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) + return; + + if (strlen(pBI->Name) != 0) + DEBUGPRINT("Name=%s\n", pBI->Name); + DEBUGPRINT("AllocSize=%d, ArrayLength=%d, IntegerLength=%d, Signed=%d\n", pBI->AllocSize, pBI->ArrayLength, pBI->IntegerLength, pBI->Signed); + for (i = (pBI->ArrayLength - 1), j = 0;i >=0;i--,j++) { + DEBUGPRINT("%08x, ", pBI->pIntegerArray[i]); + if ((j%8) == 7) + DEBUGPRINT("\n"); + } /* End od for */ + DEBUGPRINT("\n\n"); +} /* End of BigInteger_Print */ + + +VOID BigInteger_Init ( + INOUT PBIG_INTEGER *pBI) +{ + if (*pBI != NULL) + BigInteger_Free(pBI); + + os_alloc_mem(NULL, (UCHAR **)pBI, sizeof(BIG_INTEGER)); +/* if ((*pBI = (PBIG_INTEGER) kmalloc(sizeof(BIG_INTEGER), GFP_ATOMIC)) == NULL) { */ + if (*pBI == NULL) { + DEBUGPRINT("BigInteger_Init: allocate %d bytes memory failure.\n", (sizeof(BIG_INTEGER))); + return; + } /* End of if */ + + NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); + (*pBI)->pIntegerArray = NULL; + (*pBI)->Signed = 1; +} /* End of BigInteger_Init */ + + +VOID BigInteger_Free_AllocSize ( + IN PBIG_INTEGER *pBI) +{ + if ((*pBI != NULL) && ((*pBI)->pIntegerArray != NULL)) { +/* kfree((*pBI)->pIntegerArray); */ + os_free_mem(NULL, (*pBI)->pIntegerArray); + NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); + (*pBI)->pIntegerArray = NULL; + (*pBI)->Signed = 1; + } /* End of if */ +} /* End of BigInteger_Free_AllocSize */ + + +VOID BigInteger_Free ( + IN PBIG_INTEGER *pBI) +{ + if (*pBI != NULL) { + BigInteger_Free_AllocSize(pBI); +/* kfree(*pBI); */ + os_free_mem(NULL, *pBI); + } /* End of if */ + + *pBI = NULL; +} /* End of BigInteger_Free */ + + +VOID BigInteger_AllocSize ( + IN PBIG_INTEGER *pBI, + IN INT Length) +{ + UINT ArrayLength = 0; + + if (Length <= 0) + return; + + if (*pBI == NULL) + BigInteger_Init(pBI); + + /* Caculate array size */ + ArrayLength = Length >> 0x2; + if ((Length & 0x3) != 0) + ArrayLength++; + + if (((*pBI)->pIntegerArray != NULL) && ((*pBI)->AllocSize < (sizeof(UINT32)*ArrayLength))) + BigInteger_Free_AllocSize(pBI); + + if ((*pBI)->pIntegerArray == NULL) { + os_alloc_mem(NULL, (UCHAR **)&((*pBI)->pIntegerArray), sizeof(UINT32)*ArrayLength); +/* if (((*pBI)->pIntegerArray = (UINT32 *) kmalloc(sizeof(UINT32)*ArrayLength, GFP_ATOMIC)) == NULL) { */ + if ((*pBI)->pIntegerArray == NULL) { + DEBUGPRINT("BigInteger_AllocSize: allocate %d bytes memory failure.\n", (sizeof(UINT32)*ArrayLength)); + return; + } /* End of if */ + (*pBI)->AllocSize = sizeof(UINT32)*ArrayLength; + } /* End of if */ + + NdisZeroMemory((*pBI)->pIntegerArray, (*pBI)->AllocSize); + (*pBI)->ArrayLength = ArrayLength; + (*pBI)->IntegerLength = Length; +} /* End of BigInteger_AllocSize */ + + +VOID BigInteger_ClearHighBits ( + IN PBIG_INTEGER pBI) +{ + INT BIArrayIndex, ShiftIndex = 0; + UINT8 value; + + if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) + return; + + BIArrayIndex = pBI->ArrayLength - 1; + while ((BIArrayIndex >= 0) && (pBI->pIntegerArray[BIArrayIndex] == 0)) + BIArrayIndex--; + + if (BIArrayIndex >= 0) { + value = 0; + ShiftIndex = 4; + while (value == 0) { + ShiftIndex--; + value = UINT32_GETBYTE(pBI->pIntegerArray[BIArrayIndex], ShiftIndex); + } /* End of while */ + } /* End of if */ + + if (BIArrayIndex < 0) { + pBI->IntegerLength = 1; + pBI->ArrayLength = 1; + pBI->Signed = 1; + } else { + pBI->IntegerLength = (BIArrayIndex*4) + ShiftIndex + 1; + pBI->ArrayLength = BIArrayIndex + 1; + } /* End of if */ +} /* End of BigInteger_ClearHighBits */ + + +VOID BigInteger_BI2Bin ( + IN PBIG_INTEGER pBI, + OUT UINT8 *pValue, + OUT UINT *Length) +{ + INT ValueIndex, BIArrayIndex, ShiftIndex; + UINT32 Number; + + if (pBI == NULL) { + DEBUGPRINT("BigInteger_BI2Bin: pBI is NUll\n"); + *Length = 0; + return; + } /* End of if */ + + if (*Length < (sizeof(UINT8) * pBI->IntegerLength)) { + DEBUGPRINT("BigInteger_BI2Bin: length(%d) is not enough.\n", *Length); + *Length = 0; + return; + } /* End of if */ + + if (pBI->pIntegerArray == NULL) { + *Length = 0; + return; + } /* End of if */ + + BigInteger_ClearHighBits(pBI); + if ((ShiftIndex = pBI->IntegerLength & 0x3) == 0) + ShiftIndex = 4; + BIArrayIndex = pBI->ArrayLength - 1; + ValueIndex = 0; + + Number = pBI->pIntegerArray[BIArrayIndex]; + while (ValueIndex < pBI->IntegerLength) + { + pValue[ValueIndex++] = (UINT8) UINT32_GETBYTE(Number, ShiftIndex - 1); + if ((--ShiftIndex) == 0) { + ShiftIndex = 4; + BIArrayIndex--; + Number = pBI->pIntegerArray[BIArrayIndex]; + } /* End of if */ + } /* End of while */ + *Length = pBI->IntegerLength; +} /* End of BigInteger_BI2Bin */ + + +VOID BigInteger_Bin2BI ( + IN UINT8 *pValue, + IN UINT Length, + OUT PBIG_INTEGER *pBI) +{ + INT ValueIndex, BIArrayIndex, ShiftIndex; + UINT32 Number; + + BigInteger_AllocSize(pBI, Length); + + if ((*pBI)->pIntegerArray != NULL) { + Number = 0; + if ((ShiftIndex = Length & 0x3) == 0) + ShiftIndex = 4; + BIArrayIndex = (*pBI)->ArrayLength - 1; + ValueIndex = 0; + while (ValueIndex < Length) + { + Number = (Number << 8) | (UINT8) pValue[ValueIndex++]; + if ((--ShiftIndex) == 0) { + (*pBI)->pIntegerArray[BIArrayIndex] = Number; + ShiftIndex = 4; + BIArrayIndex--; + Number = 0; + } /* End of if */ + } /* End of while */ + } /* End of if */ +} /* End of BigInteger_Bin2BI */ + + +/* Calculate the bits of BigInteger, the highest bit is 1 */ +VOID BigInteger_BitsOfBI ( + IN PBIG_INTEGER pBI, + OUT UINT *Bits_Of_P) +{ + UINT32 Number, Index; + + Number = pBI->pIntegerArray[pBI->ArrayLength - 1]; + Index = 0; + while ((!(Number & 0x80000000)) && (Index < 32)) { + Number <<= 1; + Index++; + } /* End of while */ + *Bits_Of_P = (pBI->ArrayLength*sizeof(UINT32)) - Index; +} /* End of BigInteger_BitsOfBN */ + + +INT BigInteger_GetBitValue ( + IN PBIG_INTEGER pBI, + IN UINT Index) +{ + UINT Array = 0; + UINT Shift = 0; + + if (Index > 0) { + Array = (Index - 1) >> 0x5; + Shift = (Index - 1) & 0x1F; + } + if (Array > pBI->ArrayLength) + return 0; + + return ((pBI->pIntegerArray[Array] >> Shift) & 0x1); +} /* End of BigInteger_GetBitValue */ + + +UINT8 BigInteger_GetByteValue ( + IN PBIG_INTEGER pBI, + IN UINT Index) +{ + UINT Array = 0; + UINT Shift = 0; + + if (Index > 0) { + Array = (Index - 1) >> 0x2; + Shift = (Index - 1) & 0x3; + } + if ((Array > pBI->ArrayLength) || (Index > pBI->IntegerLength)) + return 0; + + + return (UINT8) UINT32_GETBYTE(pBI->pIntegerArray[Array], Shift - 1); +} /* End of BigInteger_GetByteValue */ + + +VOID BigInteger_Copy ( + IN PBIG_INTEGER pBI_Copied, + OUT PBIG_INTEGER *pBI_Result) +{ + BigInteger_AllocSize(pBI_Result, pBI_Copied->IntegerLength); + NdisCopyMemory((*pBI_Result)->pIntegerArray, pBI_Copied->pIntegerArray, (sizeof(UINT32)*(*pBI_Result)->ArrayLength)); + (*pBI_Result)->ArrayLength = pBI_Copied->ArrayLength; + (*pBI_Result)->IntegerLength = pBI_Copied->IntegerLength; + (*pBI_Result)->Signed = pBI_Copied->Signed; +} /* End of BigInteger_Copy */ + + +INT BigInteger_UnsignedCompare ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand) +{ + INT BIArrayIndex; + + if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength) + return 1; + + if (pFirstOperand->IntegerLength < pSecondOperand->IntegerLength) + return -1; + + if (pFirstOperand->IntegerLength == pSecondOperand->IntegerLength) { + for(BIArrayIndex = (pFirstOperand->ArrayLength - 1);BIArrayIndex >= 0 ; BIArrayIndex--) + { + if (pFirstOperand->pIntegerArray[BIArrayIndex] > pSecondOperand->pIntegerArray[BIArrayIndex]) + return 1; + else if (pFirstOperand->pIntegerArray[BIArrayIndex] < pSecondOperand->pIntegerArray[BIArrayIndex]) + return -1; + } /* End of for */ + } /* End of if */ + + return 0; +} /* End of BigInteger_Compare */ + + +VOID BigInteger_Add ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result) +{ + INT CompareResult; + UINT32 BIArrayIndex; + UINT64 Sum, Carry; + PBIG_INTEGER pTempBI = NULL; + + if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) + || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { + DEBUGPRINT("BigInteger_Add: first or second operand is NULL.\n"); + return; + } /* End of if */ + + if (*pBI_Result == NULL) + BigInteger_Init(pBI_Result); + + CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); + if ((CompareResult == 0) & ((pFirstOperand->Signed * pSecondOperand->Signed) < 0)) { + BigInteger_AllocSize(pBI_Result, 1); + return ; + } /* End of if */ + + /* + * Singed table + * A + B || A > B || A < B + * ------------------------ + * + + || + || + + * + - || + || - + * - + || - || + + * - - || - || - + */ + if ((pFirstOperand->Signed * pSecondOperand->Signed) > 0) { + if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength) { + BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength + 1); + } else { + BigInteger_AllocSize(pBI_Result, pSecondOperand->IntegerLength + 1); + } /* End of if */ + + Carry = 0; + for (BIArrayIndex=0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++) + { + + Sum = 0; + if (BIArrayIndex < pFirstOperand->ArrayLength) + Sum += (UINT64) pFirstOperand->pIntegerArray[BIArrayIndex]; + + if (BIArrayIndex < pSecondOperand->ArrayLength) + Sum += (UINT64) pSecondOperand->pIntegerArray[BIArrayIndex]; + + Sum += Carry; + Carry = Sum >> 32; + (*pBI_Result)->pIntegerArray[BIArrayIndex] = (UINT32) (Sum & 0xffffffffUL); + } /* End of for */ + (*pBI_Result)->Signed = pFirstOperand->Signed; + BigInteger_ClearHighBits(*pBI_Result); + } else { + if ((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == -1)) { + BigInteger_Copy(pSecondOperand, &pTempBI); + pTempBI->Signed = 1; + BigInteger_Sub(pFirstOperand, pTempBI, pBI_Result); + } else if ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == 1)) { + BigInteger_Copy(pFirstOperand, &pTempBI); + pTempBI->Signed = 1; + BigInteger_Sub(pSecondOperand, pTempBI, pBI_Result); + } /* End of if */ + } /* End of if */ + + BigInteger_Free(&pTempBI); +} /* End of BigInteger_Add */ + + +VOID BigInteger_Sub ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result) +{ + INT CompareResult; + UINT32 BIArrayIndex, Carry; + PBIG_INTEGER pTempBI = NULL, pTempBI2 = NULL; + + if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) + || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { + DEBUGPRINT("BigInteger_Sub: first or second operand is NULL.\n"); + return; + } /* End of if */ + + if (*pBI_Result == NULL) + BigInteger_Init(pBI_Result); + + CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); + if ((CompareResult == 0) & ((pFirstOperand->Signed * pSecondOperand->Signed) > 0)) { + BigInteger_AllocSize(pBI_Result, 1); + return ; + } /* End of if */ + + BigInteger_Init(&pTempBI); + BigInteger_Init(&pTempBI2); + + /* + * Singed table + * A - B || A > B || A < B + * ------------------------ + * + + || + || - + * + - || + || + + * - + || - || - + * - - || - || + + */ + if ((pFirstOperand->Signed * pSecondOperand->Signed) > 0) { + if (CompareResult == 1) { + BigInteger_Copy(pFirstOperand, &pTempBI); + BigInteger_Copy(pSecondOperand, &pTempBI2); + } else if (CompareResult == -1) { + BigInteger_Copy(pSecondOperand, &pTempBI); + BigInteger_Copy(pFirstOperand, &pTempBI2); + } /* End of if */ + + BigInteger_Copy(pTempBI, pBI_Result); + Carry = 0; + for (BIArrayIndex=0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++) + { + if (BIArrayIndex < pTempBI2->ArrayLength) { + if ((*pBI_Result)->pIntegerArray[BIArrayIndex] >= (pTempBI2->pIntegerArray[BIArrayIndex] - Carry)) { + (*pBI_Result)->pIntegerArray[BIArrayIndex] = (*pBI_Result)->pIntegerArray[BIArrayIndex] - pTempBI2->pIntegerArray[BIArrayIndex] - Carry; + Carry = 0; + } else { + (*pBI_Result)->pIntegerArray[BIArrayIndex] = 0xffffffffUL - pTempBI2->pIntegerArray[BIArrayIndex] - Carry + (*pBI_Result)->pIntegerArray[BIArrayIndex] + 1; + Carry = 1; + } /* End of if */ + } else { + if ((*pBI_Result)->pIntegerArray[BIArrayIndex] >= Carry) { + (*pBI_Result)->pIntegerArray[BIArrayIndex] -= Carry; + Carry = 0; + } else { + (*pBI_Result)->pIntegerArray[BIArrayIndex] = 0xffffffffUL - Carry; + Carry = 1; + } /* End of if */ + } /* End of if */ + } /* End of for */ + + if (((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == 1) & (CompareResult == -1)) + || ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == -1) & (CompareResult == 1))) + (*pBI_Result)->Signed = -1; + + BigInteger_ClearHighBits(*pBI_Result); + } else { + if ((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == -1)) { + BigInteger_Copy(pSecondOperand, &pTempBI); + pTempBI->Signed = 1; + BigInteger_Add(pFirstOperand, pTempBI, pBI_Result); + } else if ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == 1)) { + BigInteger_Copy(pFirstOperand, &pTempBI); + pTempBI->Signed = 1; + BigInteger_Add(pTempBI, pSecondOperand, pBI_Result); + (*pBI_Result)->Signed = -1; + } /* End of if */ + } /* End of if */ + + BigInteger_Free(&pTempBI); + BigInteger_Free(&pTempBI2); +} /* End of BigInteger_Sub */ + + +VOID BigInteger_Mul ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result) +{ + + UINT32 BIFirstIndex, BISecondIndex; + UINT64 FirstValue, SecondValue, Sum, Carry; + + if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) + || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { + DEBUGPRINT("BigInteger_Mul: first or second operand is NULL.\n"); + return; + } /* End of if */ + + /* The first or second operand is zero */ + if (((pFirstOperand->IntegerLength == 1) && (pFirstOperand->pIntegerArray[0] == 0)) + ||((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 0))) { + BigInteger_AllocSize(pBI_Result, 1); + goto output; + } /* End of if */ + + /* The first or second operand is one */ + if ((pFirstOperand->IntegerLength == 1) && (pFirstOperand->pIntegerArray[0] == 1)) { + BigInteger_Copy(pSecondOperand, pBI_Result); + goto output; + } /* End of if */ + if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) { + BigInteger_Copy(pFirstOperand, pBI_Result); + goto output; + } /* End of if */ + + BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength + pSecondOperand->IntegerLength); + + for (BIFirstIndex=0; BIFirstIndex < pFirstOperand->ArrayLength; BIFirstIndex++) + { + Carry = 0; + FirstValue = (UINT64) pFirstOperand->pIntegerArray[BIFirstIndex]; + if (FirstValue == 0) { + continue; + } else { + for (BISecondIndex=0; BISecondIndex < pSecondOperand->ArrayLength; BISecondIndex++) + { + SecondValue = ((UINT64) pSecondOperand->pIntegerArray[BISecondIndex])*FirstValue; + Sum = (UINT64) ((*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] + SecondValue + Carry); + Carry = Sum >> 32; + (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] = (UINT32) (Sum & 0xffffffffUL); + } /* End of for */ + while (Carry != 0) { + Sum = (UINT64) (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex]; + Sum += Carry; + + Carry = Sum >> 32; + (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] = (UINT32) (Sum & 0xffffffffUL); + BISecondIndex++; + } /* End of while */ + } /* End of if */ + } /* End of for */ + +output: + (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; + BigInteger_ClearHighBits(*pBI_Result); +} /* End of BigInteger_Mul */ + + +VOID BigInteger_Square ( + IN PBIG_INTEGER pBI, + OUT PBIG_INTEGER *pBI_Result) +{ + INT BIFirstIndex, BISecondIndex; + UINT32 HBITS_Value, LBITS_Value, Temp1_Value, Temp2_Value, Carry32; + UINT32 *Point_Of_S, *Point_Of_Result, *Point_Of_BI; + UINT64 Result64_1, Result64_2, Carry64, TempValue64; + + if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) { + DEBUGPRINT("\tBigInteger_Square: the operand is NULL.\n"); + return; + } /* End of if */ + + /* The operand is zero */ + if ((pBI->IntegerLength == 1) && (pBI->pIntegerArray[0] == 0)) { + BigInteger_AllocSize(pBI_Result, 1); + goto output; + } /* End of if */ + + BigInteger_AllocSize(pBI_Result, (pBI->IntegerLength*2) + 20); + BigInteger_AllocSize(&pBI_S, (pBI->IntegerLength*2) + 20); + BigInteger_AllocSize(&pBI_O, (pBI->IntegerLength*2) + 20); + + /* + * Input: pBI = {a_0, a_1, a_2, a_3, ..., a_n} + * Step1. calculate a_0^2, a_1^2, a_2^2, a_3^2 ... a_n^2 + */ + Point_Of_S = pBI_S->pIntegerArray; + for (BIFirstIndex=0; BIFirstIndex < pBI->ArrayLength; BIFirstIndex++) + { + HBITS_Value = UINT32_HBITS(pBI->pIntegerArray[BIFirstIndex]); + LBITS_Value = UINT32_LBITS(pBI->pIntegerArray[BIFirstIndex]); + Temp1_Value = HBITS_Value*LBITS_Value; + Temp2_Value = (Temp1_Value & 0x7fff) << 0x11; + Point_Of_S[0] = (LBITS_Value*LBITS_Value) + Temp2_Value; + Point_Of_S[1] = (HBITS_Value*HBITS_Value) + ((Temp1_Value >> 0xf) & 0x1ffff); + if (Point_Of_S[0] < Temp2_Value) + Point_Of_S[1] += 1; + + Point_Of_S += 2; + } /* End of for */ + + /* + * Step2. calculate a_0*{a_1, a_2, a_3, a_4, ..., a_n} + */ + Point_Of_BI = pBI->pIntegerArray; + Point_Of_Result = (*pBI_Result)->pIntegerArray; + Point_Of_Result[0] = 0; + TempValue64 = (UINT64) Point_Of_BI[0]; + Point_Of_Result++; + Carry64 = 0; + for (BIFirstIndex=1; BIFirstIndex < pBI->ArrayLength; BIFirstIndex++) + { + Result64_1 = (UINT64) Point_Of_BI[BIFirstIndex]*TempValue64; + Result64_1 += Carry64; + Carry64 = (Result64_1 >> 32); + Point_Of_Result[0] = (UINT32) (Result64_1 & 0xffffffffUL); + Point_Of_Result++; + } /* End of for */ + if (Carry64 > 0) + Point_Of_Result[0] = (UINT32) (Carry64 & 0xffffffffUL); + + /* + * Step3. calculate + * a_1*{a_2, a_3, a_4, ..., a_n} + * a_2*{a_3, a_4, a_5, ..., a_n} + * a_3*{a_4, a_5, a_6, ..., a_n} + * a_4*{a_5, a_6, a_7, ..., a_n} + * ... + * a_n-1*{a_n} + */ + Point_Of_BI = pBI->pIntegerArray; + for (BIFirstIndex=1; BIFirstIndex < (pBI->ArrayLength - 1); BIFirstIndex++) + { + Point_Of_Result = (*pBI_Result)->pIntegerArray; + Point_Of_Result += (BIFirstIndex*2) + 1; + TempValue64 = (UINT64) Point_Of_BI[BIFirstIndex]; + Carry64 = 0; + for (BISecondIndex=(BIFirstIndex + 1); BISecondIndex < pBI->ArrayLength; BISecondIndex++) + { + Result64_1 = ((UINT64) Point_Of_Result[0]) + Carry64; + Result64_2 = (UINT64) Point_Of_BI[BISecondIndex]*TempValue64; + Carry64 = (Result64_1 >> 32); + Result64_1 = (Result64_1 & 0xffffffffUL); + Result64_1 = Result64_1 + Result64_2; + Carry64 += (Result64_1 >> 32); + Point_Of_Result[0] = (UINT32) (Result64_1 & 0xffffffffUL); + Point_Of_Result++; + } /* End of for */ + if (Carry64 > 0) + Point_Of_Result[0] += (UINT32) (Carry64 & 0xffffffffUL); + } /* End of for */ + + BigInteger_ClearHighBits(*pBI_Result); + BigInteger_Copy(*pBI_Result, &pBI_O); + + Carry32 = 0; + for (BIFirstIndex=0; BIFirstIndex < pBI_O->ArrayLength; BIFirstIndex++) { + pBI_O->pIntegerArray[BIFirstIndex] = (pBI_O->pIntegerArray[BIFirstIndex] << 1) | Carry32; + if (pBI_O->pIntegerArray[BIFirstIndex] < (*pBI_Result)->pIntegerArray[BIFirstIndex]) + Carry32 = 1; + else + Carry32 = 0; + } /* End of for */ + pBI_O->pIntegerArray[BIFirstIndex] = Carry32; + pBI_O->IntegerLength++; + pBI_O->ArrayLength++; + BigInteger_ClearHighBits(pBI_O); + + BigInteger_Add(pBI_O, pBI_S, pBI_Result); +output: + (*pBI_Result)->Signed = 1; + BigInteger_ClearHighBits(*pBI_Result); +} /* End of BigInteger_Square */ + + +VOID BigInteger_Div ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result, + OUT PBIG_INTEGER *pBI_Remainder) +{ + INT CompareResult; + INT Index, MulIndex, ComputeSize; + UINT32 MulStart; + UINT AllocLength, ArrayIndex, ShiftIndex; + PBIG_INTEGER pTempBI = NULL, pTempBI2 = NULL, pMulBI = NULL; + UINT8 SecondHighByte; + + if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) + || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { + DEBUGPRINT("BigInteger_Div: first or second operand is NULL.\n"); + return; + } /* End of if */ + + /* The second operand is zero */ + if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 0)) { + DEBUGPRINT("BigInteger_Div: second operand is zero.\n"); + return; + } /* End of if */ + + if (*pBI_Result == NULL) + BigInteger_Init(pBI_Result); + if (*pBI_Remainder == NULL) + BigInteger_Init(pBI_Remainder); + + /* The second operand is one */ + if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) { + BigInteger_Copy(pFirstOperand, pBI_Result); + BigInteger_Bin2BI(Value_0, 1, pBI_Remainder); + goto output; + } /* End of if */ + + CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); + if (CompareResult == 0) { + BigInteger_Bin2BI(Value_1, 1, pBI_Result); + BigInteger_Bin2BI(Value_0, 1, pBI_Remainder); + goto output; + } else if (CompareResult == -1) { + BigInteger_Bin2BI(Value_0, 1, pBI_Result); + BigInteger_Copy(pFirstOperand, pBI_Remainder); + goto output; + } /* End of if */ + BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength - pSecondOperand->IntegerLength + 1); + BigInteger_AllocSize(pBI_Remainder, pSecondOperand->IntegerLength); + + AllocLength = (UINT) (pFirstOperand->IntegerLength << 1); + BigInteger_AllocSize(&pTempBI, AllocLength); + BigInteger_AllocSize(&pTempBI2, AllocLength); + BigInteger_AllocSize(&pMulBI, AllocLength); + + BigInteger_Copy(pFirstOperand, pBI_Remainder); + SecondHighByte = BigInteger_GetByteValue(pSecondOperand, pSecondOperand->IntegerLength); + ComputeSize = (INT) pFirstOperand->IntegerLength - pSecondOperand->IntegerLength + 1; + for (Index = (INT) ComputeSize;Index >= 0;Index--) { + if (BigInteger_UnsignedCompare(*pBI_Remainder, pSecondOperand) == -1) + break; + + if (((pSecondOperand->IntegerLength + Index) - (*pBI_Remainder)->IntegerLength) <= 1) { + BigInteger_AllocSize(&pMulBI, Index + 1); + ArrayIndex = 0; + if (Index > 0) + ArrayIndex = (UINT) (Index - 1) >> 2 ; + ShiftIndex = (Index & 0x03); + if (ShiftIndex == 0) + ShiftIndex = 4; + ShiftIndex--; + MulStart = 0; + MulStart = (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize + 1) & 0xFF) << 8; + MulStart = MulStart | (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize) & 0xFF); + if (MulStart < (UINT32) SecondHighByte) + continue; + + MulStart = MulStart / (UINT32) SecondHighByte; + + if (MulStart > 0xFF) + MulStart = 0x100; + + for (MulIndex = (INT) MulStart;MulIndex <= 0x101;MulIndex++) { /* 0xFFFF / 0xFF = 0x101 */ + if ((MulIndex > 0xFF) && (ShiftIndex == 3)) + pMulBI->pIntegerArray[ArrayIndex + 1] = 0x01; + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) MulIndex << (8*ShiftIndex)); + BigInteger_Mul(pSecondOperand, pMulBI , &pTempBI); + CompareResult = BigInteger_UnsignedCompare(*pBI_Remainder, pTempBI); + if (CompareResult < 1) { + if (MulIndex > 1) { + if (CompareResult != 0) { + if ((MulIndex == 0x100) && (ShiftIndex == 3)) + pMulBI->pIntegerArray[ArrayIndex + 1] = 0; + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex - 1) << (8*ShiftIndex)); + } /* End of if */ + + BigInteger_Mul(pSecondOperand, pMulBI, &pTempBI); + BigInteger_Sub(*pBI_Remainder, pTempBI, &pTempBI2); + BigInteger_Copy(pTempBI2, pBI_Remainder); + BigInteger_Add(*pBI_Result, pMulBI, &pTempBI2); + BigInteger_Copy(pTempBI2, pBI_Result); + } /* End of if */ + break; + } /* End of if */ + + if ((MulIndex >= 0x100) && (ShiftIndex == 3)) + pMulBI->pIntegerArray[ArrayIndex++] = 0; + pMulBI->pIntegerArray[ArrayIndex] = 0; + } /* End of for */ + } /* End of if */ + } /* End of for */ + + BigInteger_Free(&pTempBI); + BigInteger_Free(&pTempBI2); + BigInteger_Free(&pMulBI); +output: + (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; + (*pBI_Remainder)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; + BigInteger_ClearHighBits(*pBI_Result); + BigInteger_ClearHighBits(*pBI_Remainder); +} /* End of BigInteger_Div */ + + +VOID BigInteger_Montgomery_Reduction ( + IN PBIG_INTEGER pBI_A, + IN PBIG_INTEGER pBI_P, + IN PBIG_INTEGER pBI_R, + OUT PBIG_INTEGER *pBI_Result) +{ + UINT32 *Point_P, *Point_Result; + UINT32 LoopCount; + UINT64 Result64_1, Result64_2, Carry64, TempValue64; + INT FirstLoop, SecondLoop; + + BigInteger_AllocSize(pBI_Result, pBI_A->IntegerLength+ pBI_P->IntegerLength + 20); + BigInteger_Copy(pBI_A, pBI_Result); + + Point_P = pBI_P->pIntegerArray; + Point_Result = (*pBI_Result)->pIntegerArray; + + LoopCount = Bits_Of_R >> 0x5; + for (FirstLoop = 0;FirstLoop < LoopCount;FirstLoop++) { + Carry64 = 0; + TempValue64 = (UINT64) Point_Result[0]; + for (SecondLoop = 0;SecondLoop < pBI_P->ArrayLength;SecondLoop++) { + Result64_1 = ((UINT64) Point_Result[SecondLoop]) + Carry64; + Result64_2 = (UINT64) Point_P[SecondLoop]*TempValue64; + Carry64 = (Result64_1 >> 32); + Result64_1 = (Result64_1 & 0xffffffffUL); + Result64_1 = Result64_1 + Result64_2; + Carry64 += (Result64_1 >> 32); + Point_Result[SecondLoop] = (UINT32) (Result64_1 & 0xffffffffUL); + } /* End of for */ + while (Carry64 != 0) { + Result64_1 = ((UINT64) Point_Result[SecondLoop]) + Carry64; + Carry64 = Result64_1 >> 32; + Point_Result[SecondLoop] = (UINT32) (Result64_1 & 0xffffffffUL); + SecondLoop++; + } /* End of while */ + Point_Result++; + } /* End of for */ + + for (FirstLoop = 0;FirstLoop <= LoopCount;FirstLoop++) { + (*pBI_Result)->pIntegerArray[FirstLoop] = (*pBI_Result)->pIntegerArray[FirstLoop + LoopCount]; + } /* End of for */ + if ((*pBI_Result)->pIntegerArray[LoopCount] != 0) + (*pBI_Result)->ArrayLength = LoopCount + 1; + else + (*pBI_Result)->ArrayLength = LoopCount; + + (*pBI_Result)->IntegerLength = (*pBI_Result)->ArrayLength*4; + BigInteger_ClearHighBits(*pBI_Result); + + if (BigInteger_UnsignedCompare(*pBI_Result, pBI_P) >= 0) { + BigInteger_Sub(*pBI_Result, pBI_P, &pBI_U); + BigInteger_Copy(pBI_U, pBI_Result); + } /* End of if */ + BigInteger_ClearHighBits(*pBI_Result); +} /* End of BigInteger_Montgomery_Reduction */ + + +VOID BigInteger_Montgomery_ExpMod ( + IN PBIG_INTEGER pBI_G, + IN PBIG_INTEGER pBI_E, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + UINT Bits_Of_P; + UINT32 Index, Index2, AllocLength; + UINT32 Sliding_Value , Sliding_HighValue, Sliding_LowValue; + PBIG_INTEGER pBI_Temp1 = NULL, pBI_Temp2 = NULL; + PBIG_INTEGER pBI_X = NULL, pBI_R = NULL, pBI_RR = NULL, pBI_1 = NULL; + BIG_INTEGER *pBI_A[SLIDING_WINDOW]; + UINT8 *pRValue = NULL; + + AllocLength = (pBI_G->IntegerLength + pBI_E->IntegerLength + pBI_P->IntegerLength + 300); + BigInteger_AllocSize(&pBI_Temp1, AllocLength); + BigInteger_AllocSize(&pBI_Temp2, AllocLength); + + /* Calculate the bits of P and E, the highest bit is 1 */ + BigInteger_BitsOfBI(pBI_P, &Bits_Of_P); + + if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 0)) { + BigInteger_Bin2BI(Value_0, 1, pBI_Result); + goto memory_free; + } /* End of if */ + + if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 1)) { + BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); + goto memory_free; + } /* End of if */ + + if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 1)) { + BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); + goto memory_free; + } /* End of if */ + + if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 2)) { + BigInteger_Mul(pBI_G, pBI_G, &pBI_Temp1); + BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, pBI_Result); + goto memory_free; + } /* End of if */ + + /* + * Main algorithm + */ + BigInteger_Init(&pBI_R); + BigInteger_Init(&pBI_RR); + BigInteger_Bin2BI(Value_1, 1, &pBI_1); + BigInteger_AllocSize(&pBI_X, AllocLength); + BigInteger_AllocSize(&pBI_U, AllocLength); /* for BigInteger_Montgomery_Reduction */ + BigInteger_AllocSize(&pBI_S, AllocLength); /* for BigInteger_Square */ + BigInteger_AllocSize(&pBI_O, AllocLength); /* for BigInteger_Square */ + + for (Index = 0; Index < SLIDING_WINDOW; Index++) { + pBI_A[Index] = NULL; + BigInteger_AllocSize(&pBI_A[Index], 193); + } /* End of for */ + BigInteger_Bin2BI(WPS_DH_P_VALUE, 192, &pBI_Temp1); + if (NdisCmpMemory(pBI_P->pIntegerArray, pBI_Temp1->pIntegerArray, pBI_P->IntegerLength) == 0) { + BigInteger_Bin2BI(WPS_DH_X_VALUE, 184, &pBI_X); + BigInteger_Bin2BI(WPS_DH_R_VALUE, 193, &pBI_R); + BigInteger_Bin2BI(WPS_DH_RRModP_VALUE, 192, &pBI_RR); + Bits_Of_R = 1537; + } else { + if ((Bits_Of_P % 8) == 0) { + AllocLength = pBI_P->IntegerLength + 1; + } else { + AllocLength = pBI_P->IntegerLength; + } /* End of if */ +/* pRValue = (UINT8 *) kmalloc(sizeof(UINT8)*AllocLength, GFP_ATOMIC); */ + os_alloc_mem(NULL, (UCHAR **)&pRValue, sizeof(UINT8)*AllocLength); + if (pRValue == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + goto memory_free; + } + NdisZeroMemory(pRValue, sizeof(UINT8)*AllocLength); + pRValue[0] = (UINT8) (1 << (Bits_Of_P & 0x7)); + BigInteger_Bin2BI(pRValue, AllocLength , &pBI_R); + + BigInteger_Mul(pBI_R, pBI_R, &pBI_Temp1); + BigInteger_Div(pBI_Temp1, pBI_P, &pBI_A[1], &pBI_RR); + + /* X = 1*R (mod P) */ + BigInteger_Div(pBI_R, pBI_P, &pBI_Temp2, &pBI_X); + } /* End of if */ + + /* A = G*R (mod P) => A = MonMod(G, R^2 mod P) */ + BigInteger_Mul(pBI_G, pBI_RR, &pBI_Temp1); + BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P , pBI_R, &pBI_A[1]); + for (Index = 2; Index < SLIDING_WINDOW; Index++) { + BigInteger_Mul(pBI_A[Index - 1], pBI_A[1], &pBI_Temp1); + BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_A[Index]); + } /* End of for */ + + for (Index = pBI_E->IntegerLength ; Index > 0 ; Index--) { + for (Index2 = 0; Index2 < 4 ; Index2++) { + BigInteger_Square(pBI_X, &pBI_Temp1); + BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); + } /* End of for */ + + Sliding_Value = BigInteger_GetByteValue(pBI_E, Index); + Sliding_HighValue = (Sliding_Value >> 4); + if (Sliding_HighValue != 0) { + BigInteger_Mul(pBI_A[Sliding_HighValue], pBI_X, &pBI_Temp1); + BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); + } /* End of if */ + + for (Index2 = 0; Index2 < 4 ; Index2++) { + BigInteger_Square(pBI_X, &pBI_Temp1); + BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); + } /* End of for */ + + Sliding_LowValue = Sliding_Value & 0x0f; + if (Sliding_LowValue != 0) { + BigInteger_Mul(pBI_A[Sliding_LowValue], pBI_X, &pBI_Temp1); + BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); + } /* End of if */ + } /* End of for */ + BigInteger_Montgomery_Reduction(pBI_X, pBI_P , pBI_R, pBI_Result); + + BigInteger_Free(&pBI_X); + BigInteger_Free(&pBI_1); + BigInteger_Free(&pBI_U); + BigInteger_Free(&pBI_S); + BigInteger_Free(&pBI_O); + for(Index = 0; Index < SLIDING_WINDOW; Index++) + BigInteger_Free(&pBI_A[Index]); + if (pRValue != NULL) +/* kfree(pRValue); */ + os_free_mem(NULL, pRValue); + +memory_free: + BigInteger_Free(&pBI_R); + BigInteger_Free(&pBI_RR); + BigInteger_Free(&pBI_Temp1); + BigInteger_Free(&pBI_Temp2); +} /* End of BigInteger_Montgomery_ExpMod */ + +/* End of crypt_biginteger.c */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_dh.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_dh.c new file mode 100644 index 000000000..0939143fe --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_dh.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_hmac.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_hmac.c new file mode 100644 index 000000000..2e3a6dcc0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_hmac.c @@ -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 x36 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 x5c 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 x36 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 x5c 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 x36 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 x5c 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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_md5.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_md5.c new file mode 100644 index 000000000..a49c1113d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_md5.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_sha2.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_sha2.c new file mode 100644 index 000000000..75de87cd3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/crypt_sha2.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_efuse.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_efuse.c new file mode 100644 index 000000000..a57961642 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_efuse.c @@ -0,0 +1,1415 @@ +/* + *************************************************************************** + * 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_efuse.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RTMP_EFUSE_SUPPORT + +#include "rt_config.h" + +/* eFuse registers */ +#define EFUSE_CTRL 0x0580 +#define EFUSE_DATA0 0x0590 +#define EFUSE_DATA1 0x0594 +#define EFUSE_DATA2 0x0598 +#define EFUSE_DATA3 0x059c + +#define EFUSE_CTRL_3290 0x24 +#define EFUSE_DATA0_3290 0x28 +#define EFUSE_DATA1_3290 0x2c +#define EFUSE_DATA2_3290 0x30 +#define EFUSE_DATA3_3290 0x34 + +#define EFUSE_TAG 0x2fe + +#ifdef RT_BIG_ENDIAN +typedef union _EFUSE_CTRL_STRUC { + struct { + UINT32 SEL_EFUSE:1; + UINT32 EFSROM_KICK:1; + UINT32 RESERVED:4; + UINT32 EFSROM_AIN:10; + UINT32 EFSROM_LDO_ON_TIME:2; + UINT32 EFSROM_LDO_OFF_TIME:6; + UINT32 EFSROM_MODE:2; + UINT32 EFSROM_AOUT:6; + } field; + UINT32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; +#else +typedef union _EFUSE_CTRL_STRUC { + struct { + UINT32 EFSROM_AOUT:6; + UINT32 EFSROM_MODE:2; + UINT32 EFSROM_LDO_OFF_TIME:6; + UINT32 EFSROM_LDO_ON_TIME:2; + UINT32 EFSROM_AIN:10; + UINT32 RESERVED:4; + UINT32 EFSROM_KICK:1; + UINT32 SEL_EFUSE:1; + } field; + UINT32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + +VOID eFuseReadPhysical( + IN PRTMP_ADAPTER pAd, + IN PUSHORT lpInBuffer, + IN ULONG nInBufferSize, + OUT PUSHORT lpOutBuffer, + IN ULONG nOutBufferSize); + +static VOID eFusePhysicalWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData); + +static NTSTATUS eFuseWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + IN USHORT* pData); + +static VOID eFuseWritePhysical( + IN PRTMP_ADAPTER pAd, + PUSHORT lpInBuffer, + ULONG nInBufferSize, + PUCHAR lpOutBuffer, + ULONG nOutBufferSize); + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +UCHAR eFuseReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + USHORT efuseDataOffset; + UINT32 data; + UINT32 efuse_ctrl_reg = EFUSE_CTRL; + +#if defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) + if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd) || IS_MT76x2(pAd)) + efuse_ctrl_reg = EFUSE_CTRL_3290; +#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) */ + + RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + /*Use the eeprom logical address and covert to address to block number*/ + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0.*/ + eFuseCtrlStruc.field.EFSROM_MODE = 0; + + /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisCopyMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data); + + /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/ + i = 0; + while(i < 500) + { + /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4);*/ + RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + + RtmpusecDelay(200); + i++; + } + + /*if EFSROM_AOUT is not found in physical address, write 0xffff*/ + if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) + { + for(i=0; i> (8*(Offset & 0x3)); +#endif /* RT_BIG_ENDIAN */ + + NdisCopyMemory(pData, &data, Length); + } + + return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT; + +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +VOID eFusePhysicalReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + USHORT efuseDataOffset; + UINT32 data; + UINT32 efuse_ctrl_reg = EFUSE_CTRL; + +#if defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) + if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd) || IS_MT76x2(pAd)) + efuse_ctrl_reg = EFUSE_CTRL_3290; +#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) */ + + RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.*/ + /*Read in physical view*/ + eFuseCtrlStruc.field.EFSROM_MODE = 1; + + /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisCopyMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data); + + /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/ + i = 0; + while(i < 500) + { + RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + + RtmpusecDelay(200); + i++; + } + + /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)*/ + /*Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits.*/ + /*The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes*/ + /*Decide which EFUSE_DATA to read*/ + /*590:F E D C */ + /*594:B A 9 8 */ + /*598:7 6 5 4*/ + /*59C:3 2 1 0*/ +#if defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) + if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd) || IS_MT76x2(pAd)) + efuseDataOffset = EFUSE_DATA0_3290 + (Offset & 0xC) ; + else +#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) */ + efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC) ; + + RTMP_IO_READ32(pAd, efuseDataOffset, &data); + +#ifdef RT_BIG_ENDIAN + data = data << (8*((Offset & 0x3)^0x2)); +#else + data = data >> (8*(Offset & 0x3)); +#endif /* RT_BIG_ENDIAN */ + + NdisCopyMemory(pData, &data, Length); + +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +VOID eFuseReadPhysical( + IN PRTMP_ADAPTER pAd, + IN PUSHORT lpInBuffer, + IN ULONG nInBufferSize, + OUT PUSHORT lpOutBuffer, + IN ULONG nOutBufferSize +) +{ + USHORT* pInBuf = (USHORT*)lpInBuffer; + USHORT* pOutBuf = (USHORT*)lpOutBuffer; + + USHORT Offset = pInBuf[0]; /*addr*/ + USHORT Length = pInBuf[1]; /*length*/ + int i; + + for(i=0; i> 2; + data = pData[0] & 0xffff; + /*The offset should be 0x***10 or 0x***00*/ + if((Offset % 4) != 0) + { + eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16); + } + else + { + eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data; + } + + efuseDataOffset = efuse_data; + for(i=0; i< 4; i++) + { + RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]); +#if defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2) + if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd) || IS_MT76x2(pAd)) + efuseDataOffset += 4; + else +#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) || defined(MT76x2)*/ + efuseDataOffset -= 4; + } + + /*Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + // TODO: shiang, for below line, windows driver didn't have this read, why we have ?? + RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3.*/ + eFuseCtrlStruc.field.EFSROM_MODE = 3; + + /*Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure.*/ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data); + + /*Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. Its done.*/ + i = 0; + + while (i < 500) + { + RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + + RtmpusecDelay(2); + i++; + } +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +static NTSTATUS eFuseWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + IN USHORT* pData) +{ + USHORT i,RetryCount=0, StartBlock=0, EndBlock=0; + USHORT eFuseData; + USHORT LogicalAddress, BlkNum = 0xffff; + UCHAR EFSROM_AOUT; + + USHORT addr,tmpaddr, InBuf[10], tmpOffset; + USHORT buffer[8]; + BOOLEAN bWriteSuccess = TRUE; + UINT NrFreeBlk = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData)); + /*set start block and end block number, start from tail of mapping table*/ + if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0) + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1; + } + else + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END; + } + + if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0) + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1; + } + else + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START; + } + /*Step 0. find the entry in the mapping table*/ + /*The address of EEPROM is 2-bytes alignment.*/ + /*The last bit is used for alignment, so it must be 0.*/ + + tmpOffset = Offset & 0xfffe; + EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData); + if( EFSROM_AOUT == 0x3f) + { /*find available logical address pointer */ + /*the logical address does not exist, find an empty one*/ + /*from the first address of block 45=16*45=0x2d0 to the last address of block 47*/ + /*==>48*16-3(reserved)=2FC*/ + for (i=StartBlock; i >= EndBlock; i-=2) + { + /*Retrive the logical block nubmer form each logical address pointer*/ + /*It will access two logical address pointer each time.*/ + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + /*To avoid the odd byte problem, ex. We read the 21|20 bytes and if 21 is the */ + /* end byte. Then, the EFUSE_USAGE_MAP_END which is 21 is not equal to*/ + /* i which is 20. Therefore, this 21th byte could be used.*/ + /*Otherwise, if 20 is the stop byte, i which is 20 is equal EFUSE_USAGE_MAP_END.*/ + /* It means the 21th byte could not be used.*/ + if(( (LogicalAddress >> 8) & 0xff) == 0) + {/*Not used logical address pointer*/ + if (i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START+1; + break; + } + } + + if( (LogicalAddress & 0xff) == 0) + {/*Not used logical address pointer*/ + if (i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START; + break; + } + } + + } + } + else + { + BlkNum = EFSROM_AOUT; + + //We found the block, check if it is the free block number is 0. If free block number is 0 , we compare the data writen and read back from the block is equal or not. + //We will write to Efuse only the values are equal, otherwise return and not update the value. + eFuseGetFreeBlockCount(pAd,&NrFreeBlk); + if(NrFreeBlk == 0) + { + addr = BlkNum * 0x10 ; + + if( ((Offset % 16) == 0) && (Length == 16) ) + { + //Efuse write by block case + for(i = 0; i < 16; i+=2) + { + InBuf[0] = addr+( (Offset+i) % 16); + InBuf[1] = 2; + InBuf[2] = 0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + if( (pData[i/2] | InBuf[2]) != pData[i/2]) + return FALSE; + } + } + else + { + + InBuf[0] = addr+(Offset % 16); + InBuf[1] = 2; + InBuf[2] = 0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + if( (pData[0] | InBuf[2]) != pData[0]) + return FALSE; + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); + + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + + if( ((Offset % 16) == 0) && (Length == 16) ) + { + //Efuse write by block case + NdisCopyMemory((PVOID) buffer, (PVOID) pData, 16); + } + else + { + /*Step 1. Save data of this block which is pointed by the avaible logical address pointer*/ + /* read and save the original block data*/ + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + buffer[i] = InBuf[2]; + } + + /*Step 2. Update the data in buffer, and write the data to Efuse*/ + buffer[ (Offset >> 1) % 8] = pData[0]; + } + + RetryCount = 0; + do + { + /*Step 3. Write the data to Efuse*/ + if( ((Offset % 16) == 0) && (Length == 16) ) + { + //Efuse write by block case + addr = BlkNum * 0x10 ; + + InBuf[0] = addr; + InBuf[1] = Length; + NdisCopyMemory((PVOID) &InBuf[2], (PVOID) buffer, 16); + eFuseWritePhysical(pAd,&InBuf[0], 4+16, NULL, 2); + } + else + { + if(!bWriteSuccess) + { + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = buffer[i]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + } + else + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+(Offset % 16); + InBuf[1] = 2; + InBuf[2] = pData[0]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + } + + /*Step 4. Write mapping table*/ + addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum; + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + /*convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry*/ + tmpOffset = Offset; + tmpOffset >>= 4; + tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; + tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; + + /* write the logical address*/ + if(tmpaddr%2 != 0) + InBuf[2] = tmpOffset<<8; + else + InBuf[2] = tmpOffset; + + eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); + + /*Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted*/ + bWriteSuccess = TRUE; + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + if(buffer[i] != InBuf[2]) + { + bWriteSuccess = FALSE; + break; + } + } + + /*Step 6. invlidate mapping entry and find a free mapping entry if not succeed*/ + if (!bWriteSuccess) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum)); + + /* the offset of current mapping entry*/ + addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum; + + /*find a new mapping entry*/ + BlkNum = 0xffff; + for (i=StartBlock; i >= EndBlock; i-=2) + { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if(i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + BlkNum = i+1-pAd->chipCap.EFUSE_USAGE_MAP_START; + break; + } + } + + if( (LogicalAddress & 0xff) == 0) + { + if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START; + break; + } + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess and allocate new BlkNum = %d\n", BlkNum)); + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + + /*invalidate the original mapping entry if new entry is not found*/ + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + /* write the logical address*/ + if(tmpaddr%2 != 0) + { + /* Invalidate the high byte*/ + for (i=8; i<15; i++) + { + if( ( (InBuf[2] >> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <>8; + pValueX=OddWriteByteBuf; + + } + + if( ((Offset % 16) == 0) && (length == 16) ) + { +#ifdef RT_BIG_ENDIAN + //Efuse write by block case + for(i=0; ibUseEfuse == FALSE) + return FALSE; + + eFuseGetFreeBlockCount(pAd, &free_num); + DBGPRINT(RT_DEBUG_OFF, ("efuseFreeNumber = %d\n", free_num)); + return TRUE; +} + + +INT set_eFusedump_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT InBuf[3]; + INT i = 0; + + if (pAd->bUseEfuse == FALSE) + return FALSE; + + for (i = 0; i < pAd->chipCap.EFUSE_USAGE_MAP_END/2; i++) + { + InBuf[0] = 2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + if (i%4 == 0) + DBGPRINT(RT_DEBUG_OFF, ("\nBlock %x:", i/8)); + DBGPRINT(RT_DEBUG_OFF, ("%04x ", InBuf[2])); + } + return TRUE; +} + + +INT set_eFuseLoadFromBin_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PSTRING src; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osfsInfo; + INT retval, memSize; + PSTRING buffer, memPtr; + INT TotalByte= 0; + UCHAR SkipData[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + UCHAR *ptr; + USHORT offset = 0; + + memSize = 128 + MAX_EEPROM_BIN_FILE_SIZE + sizeof(USHORT) * 8; +/* memPtr = kmalloc(memSize, MEM_ALLOC_FLAG);*/ + os_alloc_mem(NULL, (UCHAR **)&memPtr, memSize); + if (memPtr == NULL) + return FALSE; + + NdisZeroMemory(memPtr, memSize); + src = memPtr; /* kmalloc(128, MEM_ALLOC_FLAG);*/ + buffer = src + 128; /* kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG);*/ + ptr = buffer; + + if(strlen(arg)>0) + NdisMoveMemory(src, arg, strlen(arg)); + else + NdisMoveMemory(src, BIN_FILE_PATH, strlen(BIN_FILE_PATH)); + DBGPRINT(RT_DEBUG_OFF, ("FileName=%s\n",src)); + + RtmpOSFSInfoChange(&osfsInfo, TRUE); + + srcf = RtmpOSFileOpen(src, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT_ERR(("--> Error opening file %s\n", src)); + retval = FALSE; + goto recoverFS; + } + else + { + /* The object must have a read method*/ + while(RtmpOSFileRead(srcf, &buffer[TotalByte], 1)==1) + { + TotalByte++; + if(TotalByte>MAX_EEPROM_BIN_FILE_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error reading file %s, file size too large[>%d]\n", src, MAX_EEPROM_BIN_FILE_SIZE)); + retval = FALSE; + goto closeFile; + } + } + } + + for ( offset = 0 ; offset < TotalByte ; offset += 16 ) + { + if (memcmp( ptr, SkipData, 16 )) + eFuseWrite(pAd, offset ,(USHORT *)(ptr), 16); + ptr += 16; + } + retval = TRUE; + +closeFile: + if (srcf) + if (RtmpOSFileClose(srcf) != 0) + retval = FALSE; + +recoverFS: + RtmpOSFSInfoChange(&osfsInfo, FALSE); + + if (memPtr) + os_free_mem(NULL, memPtr); + + return retval; +} + + + +int rtmp_ee_efuse_read16( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + OUT USHORT *pValue) +{ + eFuseReadRegisters(pAd, Offset, 2, pValue); + return (*pValue); +} + + +int rtmp_ee_efuse_write16( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT data) +{ + eFuseWrite(pAd,Offset ,&data, 2); + return 0; +} + +int RtmpEfuseSupportCheck( + IN RTMP_ADAPTER *pAd) +{ + USHORT value; + + if (IS_RT30xx(pAd) || IS_RT3593(pAd)) + { + eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); + pAd->EFuseTag = (value & 0xff); + } + return 0; +} + +INT rtmp_ee_write_to_efuse( + IN PRTMP_ADAPTER pAd) +{ + USHORT length = pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE; + UCHAR *ptr = pAd->EEPROMImage; + USHORT offset = 0; + UCHAR SkipData[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + for ( offset = 0 ; offset < length ; offset += 16 ) + { + if (memcmp( ptr, SkipData, 16 )) + eFuseWrite(pAd, offset ,(USHORT *)(ptr), 16); + ptr += 16; + } + + return TRUE; + +} + + +VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd, + PUINT EfuseFreeBlock) +{ + + USHORT i=0, StartBlock=0, EndBlock=0; + USHORT LogicalAddress; + USHORT FirstFreeBlock = 0xffff, LastFreeBlock = 0xffff; + +#ifndef CAL_FREE_IC_SUPPORT + if(!pAd->bUseEfuse) + { + DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount Only supports efuse Mode\n")); + return ; + } +#endif /* CAL_FREE_IC_SUPPORT */ + *EfuseFreeBlock = 0; + /* find first free block*/ + if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0) + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1; + } + else + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_START; + } + + if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0) + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1; + } + else + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_END; + } + + for (i = StartBlock; i <= EndBlock; i+=2) + { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + + if( (LogicalAddress & 0xff) == 0) + { + if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + FirstFreeBlock = i; + break; + } + } + + if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if(i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + FirstFreeBlock = i+1; + break; + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseGetFreeBlockCount, FirstFreeBlock= 0x%x\n", FirstFreeBlock)); + + /*if not find, return free block number = 0*/ + if(FirstFreeBlock == 0xffff) + { + *EfuseFreeBlock = 0; + return; + } + for (i = EndBlock; i >= StartBlock; i-=2) + { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + + if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if(i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + LastFreeBlock = i+1; + break; + } + } + + if( (LogicalAddress & 0xff) == 0) + { + if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + LastFreeBlock = i; + break; + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseGetFreeBlockCount, LastFreeBlock= 0x%x\n", LastFreeBlock)); + + /*if not find last free block, return free block number = 0, this should not happen since we have checked first free block number previously*/ + if(LastFreeBlock == 0xffff) + { + *EfuseFreeBlock = 0; + return; + } + + /* return total free block number, last free block number must >= first free block number*/ + if(LastFreeBlock < FirstFreeBlock) + { + *EfuseFreeBlock = 0; + } + else + { + *EfuseFreeBlock = LastFreeBlock - FirstFreeBlock + 1; + } + + DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount is %d\n",*EfuseFreeBlock)); +} + + +INT eFuse_init(RTMP_ADAPTER *pAd) +{ + UINT EfuseFreeBlock=0; + INT result; +#ifdef CAL_FREE_IC_SUPPORT + BOOLEAN bCalFree; +#endif /* CAL_FREE_IC_SUPPORT */ + + /*RT3572 means 3062/3562/3572*/ + /*3593 means 3593*/ + DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and its size =%x[%x-%x] \n",pAd->chipCap.EFUSE_USAGE_MAP_SIZE,pAd->chipCap.EFUSE_USAGE_MAP_START,pAd->chipCap.EFUSE_USAGE_MAP_END)); + eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); + /*If the used block of efuse is less than 5. We assume the default value*/ + /* of this efuse is empty and change to the buffer mode in odrder to */ + /*bring up interfaces successfully.*/ + + 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, ("Load EEPROM buffer from BIN, and force to use BIN buffer mode\n")); + + pAd->bUseEfuse = FALSE; + result = rtmp_ee_load_from_bin(pAd); + + /* Forse to use BIN eeprom buffer mode */ + pAd->E2pAccessMode = E2P_BIN_MODE; + RtmpChipOpsEepromHook(pAd, pAd->infType); + +#ifdef CAL_FREE_IC_SUPPORT + //pAd->bFroceEEPROMBuffer = TRUE; + RTMP_CAL_FREE_IC_CHECK(pAd, bCalFree); +#endif /* CAL_FREE_IC_SUPPORT */ + + 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")); + } + +#ifdef CAL_FREE_IC_SUPPORT + if ( bCalFree ) + { + RTMP_CAL_FREE_DATA_GET(pAd); + } +#endif /* CAL_FREE_IC_SUPPORT */ + } + + } + + return 0; +} + + +INT efuse_probe(RTMP_ADAPTER *pAd) +{ + UINT32 eFuseCtrl, ctrl_reg; + + + if (WaitForAsicReady(pAd) == FALSE) + return -1; + + pAd->bUseEfuse=FALSE; +#ifdef RT65xx + // TODO: shiang-6590, find a better naming for EFUSE_CTRL_3290!! + if (IS_RT65XX(pAd)) + ctrl_reg = EFUSE_CTRL_3290; + else +#endif /* RT65xx */ + ctrl_reg = EFUSE_CTRL; + RTMP_IO_READ32(pAd, ctrl_reg, &eFuseCtrl); + pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; + + return 0; +} + + +#ifdef RALINK_ATE +INT Set_LoadEepromBufferFromEfuse_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT bEnable = simple_strtol(arg, 0, 10); + UINT free_blk = 0; +#ifdef RT_BIG_ENDIAN + USHORT *pValue, i; +#endif /* RT_BIG_ENDIAN */ + + if (bEnable < 0) + return FALSE; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM buffer from efuse, and change to BIN buffer mode\n")); + + /* If the number of the used block is less than 5, assume the efuse is not well-calibrated, and force to use buffer mode */ + eFuseGetFreeBlockCount(pAd, &free_blk); + if (free_blk > (pAd->chipCap.EFUSE_USAGE_MAP_SIZE - 5)) + return FALSE; + + NdisZeroMemory(pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE); + eFuseRead(pAd, 0, (PUSHORT)&pAd->EEPROMImage[0], MAX_EEPROM_BIN_FILE_SIZE); +#ifdef RT_BIG_ENDIAN + for(i = 0;i < MAX_EEPROM_BIN_FILE_SIZE >> 1; i++) + { + pValue = (PUSHORT)&pAd->EEPROMImage[i << 1]; + *pValue = le2cpu16(*pValue); + //printk("\x1b[31m%s: %x %x --> %x\x1b[m\n", __FUNCTION__, pAd->EEPROMImage[i << 1], pAd->EEPROMImage[(i << 1)+1], *pValue); + } +#endif /* RT_BIG_ENDIAN */ + + /* Change to BIN eeprom buffer mode */ + pAd->E2pAccessMode = E2P_BIN_MODE; + RtmpChipOpsEepromHook(pAd, pAd->infType); + return TRUE; + } +} + +INT set_eFuseBufferModeWriteBack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT bEnable = simple_strtol(arg, 0, 10); + + if (bEnable < 0) + return FALSE; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Write EEPROM buffer back to eFuse\n", __FUNCTION__)); + Set_EepromBufferWriteBack_Proc(pAd, "1"); + return TRUE; + } +} + +#ifdef TXBF_SUPPORT +INT set_BinModeWriteBack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT bEnable = simple_strtol(arg, 0, 10); + + if (bEnable < 0) + return FALSE; + else + { + if (pAd->chipCap.FlgITxBfBinWrite) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Write EEPROM buffer back to BIN\n", __FUNCTION__)); + Set_EepromBufferWriteBack_Proc(pAd, "4"); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Write EEPROM buffer back to flash\n", __FUNCTION__)); + Set_EepromBufferWriteBack_Proc(pAd, "2"); + } + return TRUE; + } +} +#endif /* TXBF SUPPORT */ + +#endif /* RALINK_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_flash.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_flash.c new file mode 100644 index 000000000..b3b123082 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_flash.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_prom.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_prom.c new file mode 100644 index 000000000..cce5e651d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ee_prom.c @@ -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; +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/eeprom.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/eeprom.c new file mode 100644 index 000000000..e0872dcf8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/eeprom.c @@ -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; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/frq_cal.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/frq_cal.c new file mode 100644 index 000000000..ac05d3905 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/frq_cal.c @@ -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 + -------- ---------- ---------------------------------------------- +*/ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft.c new file mode 100644 index 000000000..aad1c3d8d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft.c @@ -0,0 +1,3183 @@ +/**************************************************************************** + * 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.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi Wu 12-19-2008 + */ +#ifdef DOT11R_FT_SUPPORT + +#include "rt_config.h" +#include "ft.h" + +#ifdef CONFIG_AP_SUPPORT + +static VOID FT_RrbEnqueue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN PFT_ACTION pFtAction, + IN UINT16 FtActLen, + IN UINT32 ApIdx); + +static VOID FT_ReqActionParse( + IN PRTMP_ADAPTER pAd, + IN UINT16 Len, + IN PUCHAR Ptr, + OUT PFT_INFO pFtInfo); + +VOID FT_ConstructGTKSubIe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + OUT PFT_FTIE_INFO pFtInfo); + +UINT16 FT_AuthReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_CFG pFtCfg, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out); + +UINT16 FT_AuthConfirmRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in); + +UINT16 FT_AssocReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_EnqueueAuthReply( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT StatusCode, + IN PFT_MDIE_INFO pMdIeInfo, + IN PFT_FTIE_INFO pFtIeInfo, + IN PFT_RIC_INFO pRicInfo, + IN PUCHAR pRsnIe, + IN UCHAR RsnIeLen) +{ + HEADER_802_11 AuthHdr; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUINT8 ftie_ptr = NULL; + UINT8 ftie_len = 0; + PUINT8 mdie_ptr = NULL; + UINT8 mdie_len = 0; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH_RSP - Send FT-AUTH response (%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); + + /* Insert MDIE. */ + if((pMdIeInfo != NULL) && (pMdIeInfo->Len > 0)) + { + mdie_ptr = pOutBuffer + FrameLen; + mdie_len = 5; + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, + pMdIeInfo->MdId, pMdIeInfo->FtCapPlc); + } + + /* Insert FTIE. */ + if ((pFtIeInfo != NULL) && (pFtIeInfo->Len != 0)) + { + ftie_ptr = pOutBuffer+FrameLen; + ftie_len = (2 + pFtIeInfo->Len); + FT_InsertFTIE(pAd, pOutBuffer+FrameLen, &FrameLen, + pFtIeInfo->Len, pFtIeInfo->MICCtr, + pFtIeInfo->MIC, pFtIeInfo->ANonce, + pFtIeInfo->SNonce); + + /* Insert R1KH IE into FTIE. */ + if (pFtIeInfo->R1khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R1KH_ID, pFtIeInfo->R1khId, + pFtIeInfo->R1khIdLen); + + /* Insert R0KH IE into FTIE. */ + if (pFtIeInfo->R0khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R0KH_ID, pFtIeInfo->R0khId, + pFtIeInfo->R0khIdLen); + + } + + /* Insert RSNIE. */ + if ((RsnIeLen != 0) && (pRsnIe != NULL)) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + RsnIeLen, pRsnIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Insert RIC. */ + if ((pRicInfo != NULL) && (pRicInfo->Len != 0)) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + pRicInfo->Len, pRicInfo->pRicInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Calculate MIC in authentication-ACK frame */ + if (pFtIeInfo->MICCtr.field.IECnt) + { + PMAC_TABLE_ENTRY pEntry; + + if ((pEntry = MacTableLookup(pAd, pHdr->Addr2)) != NULL) + { + UINT8 ft_mic[16]; + PFT_FTIE pFtIe; + + FT_CalculateMIC(pHdr->Addr2, + pHdr->Addr1, + pEntry->PTK, + 4, + pRsnIe, + RsnIeLen, + mdie_ptr, + mdie_len, + ftie_ptr, + ftie_len, + pRicInfo->pRicInfo, + pRicInfo->Len, + ft_mic); + + /* Update the MIC field of FTIE */ + pFtIe = (PFT_FTIE)(ftie_ptr + 2); + NdisMoveMemory(pFtIe->MIC, ft_mic, FT_MIC_LEN); + } + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +static VOID FT_ReqActionParse( + IN PRTMP_ADAPTER pAd, + IN UINT16 Len, + IN PUCHAR Ptr, + OUT PFT_INFO pFtInfo) +{ + PEID_STRUCT eid_ptr; + UCHAR WPA1_OUI[4]={0x00,0x50,0xF2,0x01}; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + + eid_ptr = (PEID_STRUCT) Ptr; + + NdisZeroMemory(pFtInfo, sizeof(FT_INFO)); + + /* get variable fields from payload and advance the pointer */ + while(((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)Ptr + Len)) + { + 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*)Ptr + Len) + - (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; + + case IE_RSN: + case IE_WPA: + + if (NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI)) + || 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); + } +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_MakeFtActFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ActType, + IN PUCHAR pStaMac, + IN PUCHAR pTargetApMac, + IN UINT16 StatusCode, + IN PFT_INFO pFtInfo) +{ + ULONG TmpLen = 0; + UCHAR Category = FT_CATEGORY_BSS_TRANSITION; + + if (pFrameBuf == NULL) + return; + + /* Build basic frame first */ + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &TmpLen, + 1, &Category, + 1, &ActType, + 6, pStaMac, + 6, pTargetApMac, + END_OF_ARGS); + + *pFrameLen += TmpLen; + + if ((ActType == FT_ACTION_BT_RSP) + || (ActType == FT_ACTION_BT_ACK)) + { + UINT16 StatusCodeBuf; + + TmpLen = 0; + StatusCodeBuf = cpu2le16(StatusCode); + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &TmpLen, + 2, &StatusCodeBuf, + END_OF_ARGS); + *pFrameLen += TmpLen; + } + + /* Insert MD IE into packet. */ + if (pFtInfo->MdIeInfo.Len != 0) + FT_InsertMdIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pFtInfo->MdIeInfo.MdId, pFtInfo->MdIeInfo.FtCapPlc); + + /* Insert FT IE into packet. */ + if (pFtInfo->FtIeInfo.Len != 0) + FT_InsertFTIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pFtInfo->FtIeInfo.Len, pFtInfo->FtIeInfo.MICCtr, + pFtInfo->FtIeInfo.MIC, pFtInfo->FtIeInfo.ANonce, + pFtInfo->FtIeInfo.SNonce); + + if (pFtInfo->FtIeInfo.R0khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, (pFrameBuf + *pFrameLen), + pFrameLen, FT_R0KH_ID, pFtInfo->FtIeInfo.R0khId, + pFtInfo->FtIeInfo.R0khIdLen); + + if (pFtInfo->FtIeInfo.R1khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, (pFrameBuf + *pFrameLen), + pFrameLen, FT_R1KH_ID, pFtInfo->FtIeInfo.R1khId, + pFtInfo->FtIeInfo.R1khIdLen); + + if (pFtInfo->FtIeInfo.GtkLen!= 0) + FT_FTIE_InsertGTKSubIE(pAd, (pFrameBuf + *pFrameLen), + pFrameLen, pFtInfo->FtIeInfo.GtkSubIE, + pFtInfo->FtIeInfo.GtkLen); + + + /* Insert Ric IE into packet .*/ + if ((ActType == FT_ACTION_BT_CONFIRM) + || (ActType == FT_ACTION_BT_ACK)) + { + TmpLen = 0; + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &TmpLen, + pFtInfo->RicInfo.Len, (PUCHAR)pFtInfo->RicInfo.pRicInfo, + END_OF_ARGS); + *pFrameLen += TmpLen; + } + + return; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ + VOID FT_CfgInitial( + IN PRTMP_ADAPTER pAd) +{ + INT apidx; + PFT_CFG pFtCfg; + STRING R0khIdBuf[50]; + + NdisZeroMemory(R0khIdBuf, 50); + for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++) + { + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + pFtCfg->FtCapFlag.Dot11rFtEnable = FALSE; /* Intel TGn STA cannot connect to AP if Beacon/Probe has 11R IE in security mode. */ + pFtCfg->FtCapFlag.FtOverDs = TRUE; + pFtCfg->FtCapFlag.RsrReqCap = TRUE; + + FT_SET_MDID(pFtCfg->FtMdId, FT_DEFAULT_MDID); + + snprintf(R0khIdBuf, sizeof(R0khIdBuf), "Ralink:%02x:%02x:%02x:%02x:%02x:%02x", + RandomByte(pAd), RandomByte(pAd), RandomByte(pAd), + RandomByte(pAd), RandomByte(pAd), RandomByte(pAd)); + NdisZeroMemory(pFtCfg->FtR0khId, sizeof(pFtCfg->FtR0khId)); + NdisMoveMemory(pFtCfg->FtR0khId, R0khIdBuf, strlen(R0khIdBuf)); + pFtCfg->FtR0khIdLen = strlen(R0khIdBuf); + } +} + +VOID FT_Init( + IN PRTMP_ADAPTER pAd) +{ + FT_KDP_Init(pAd); + FT_RIC_Init(pAd); + FT_R1khEntryTabInit(pAd); +} + +VOID FT_Release( + IN PRTMP_ADAPTER pAd) +{ + FT_KDP_Release(pAd); + FT_RIC_Release(pAd); + FT_R1khEntryTabDestroy(pAd); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +USHORT FT_AuthReqHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf) +{ + USHORT result = MLME_SUCCESS; + UCHAR ApIdx = pEntry->apidx; + PFT_CFG pFtCfg; + FT_CAP_AND_POLICY FtCapPlc; + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s \n", __FUNCTION__)); + + if (ApIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid apidx (%d)\n", \ + __FUNCTION__, ApIdx)); + return MLME_UNSPECIFY_FAIL; + } + + pFtCfg = &pAd->ApCfg.MBSSID[ApIdx].FtCfg; + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + + do + { + if ((pFtInfo->MdIeInfo.Len == 0) + || (!FT_MDID_EQU(pFtInfo->MdIeInfo.MdId, pFtCfg->FtMdId))) + { + DBGPRINT_ERR(("%s : The MDIE is invalid\n", __FUNCTION__)); + result = FT_STATUS_CODE_INVALID_MDIE; + break; + } + + /* FT auth-req in an RSN */ + if (pFtInfo->RSNIE_Len != 0) + { + /* Sanity check */ + result = FT_AuthReqRsnValidation(pAd, + pEntry, + pFtCfg, + pFtInfo, + pFtInfoBuf); + if (result != MLME_SUCCESS) + break; + } + else + { + /* FT auth-req with no RSN Ie (OPEN mode). + reply auth-rsp with success. */ + ; + } + NdisMoveMemory(&pEntry->MdIeInfo, &pFtInfo->MdIeInfo, + pFtInfo->MdIeInfo.Len); + + /* prepare Ft IEs for association response. */ + FT_SET_MDID(pFtInfoBuf->MdIeInfo.MdId, pFtCfg->FtMdId); + FtCapPlc.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCapPlc.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + pFtInfoBuf->MdIeInfo.FtCapPlc.word = + pFtInfo->MdIeInfo.FtCapPlc.word & FtCapPlc.word; + pFtInfoBuf->MdIeInfo.Len = 3; + + result = MLME_SUCCESS; + break; + } while(0); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s done. StatusCode(%d)\n", __FUNCTION__, result)); + + return result; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +USHORT FT_AuthConfirmHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf) +{ + USHORT result = MLME_SUCCESS; + UCHAR ApIdx = pEntry->apidx; + PFT_CFG pFtCfg; + FT_CAP_AND_POLICY FtCapPlc; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:\n", __FUNCTION__)); + + if (ApIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid apidx (%d)\n", __FUNCTION__, ApIdx)); + return MLME_UNSPECIFY_FAIL; + } + + pFtCfg = &pAd->ApCfg.MBSSID[ApIdx].FtCfg; + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + + do + { + if ((pFtInfo->MdIeInfo.Len == 0) + || (!FT_MDID_EQU(pFtInfo->MdIeInfo.MdId, pFtCfg->FtMdId))) + { + /* invalid MDID. reject it. */ + result = FT_STATUS_CODE_INVALID_MDIE; + break; + } + + if (pFtInfo->RSNIE_Len != 0) + { + UINT16 result; + UINT8 rsnie_len = 0; + PUINT8 rsnie_ptr = NULL; + UINT8 ft_len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Fast BSS transition in a RSN \n", __FUNCTION__)); + result = FT_AuthConfirmRsnValidation(pAd, + pEntry, + pFtInfo); + if (result != MLME_SUCCESS) + break; + + /* Prepare RSNIE for outgoing frame */ + if ((pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->apidx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->apidx].RSN_IE[0][0]; + } + + pFtInfoBuf->RSNIE_Len = 0; + RTMPInsertRSNIE(pFtInfoBuf->RSN_IE, + (PULONG)&pFtInfoBuf->RSNIE_Len, + rsnie_ptr, + rsnie_len, + pEntry->FT_PMK_R1_NAME, + LEN_PMK_NAME); + + ft_len = sizeof(FT_FTIE); + + /* Prepare MIC-control and MIC field of FTIE for outgoing frame. */ + pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt = 3; + NdisZeroMemory(pFtInfoBuf->FtIeInfo.MIC, 16); + + /* Prepare ANonce and Snonce field of FTIE for outgoing frame */ + NdisMoveMemory(pFtInfoBuf->FtIeInfo.ANonce, pEntry->ANonce, LEN_NONCE); + NdisMoveMemory(pFtInfoBuf->FtIeInfo.SNonce, pEntry->SNonce, LEN_NONCE); + + /* Prepare in the R0KHID and its length */ + pFtInfoBuf->FtIeInfo.R0khIdLen = pFtCfg->FtR0khIdLen; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R0khId, + pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen); + ft_len += (2 + pFtInfoBuf->FtIeInfo.R0khIdLen); + + /* Prepare in the R1KHID and its length */ + pFtInfoBuf->FtIeInfo.R1khIdLen = MAC_ADDR_LEN; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R1khId, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN); + ft_len += (2 + MAC_ADDR_LEN); + + /* Update the length of FTIE */ + pFtInfoBuf->FtIeInfo.Len = ft_len; + + } + + /* + FT auth-req with no RSN Ie (OPEN mode). + reply auth-rsp with success. + */ + FT_RIC_ResourceRequestHandle(pAd, pEntry, + (PUCHAR)pFtInfo->RicInfo.pRicInfo, + pFtInfo->RicInfo.Len, + (PUCHAR)pFtInfoBuf->RicInfo.pRicInfo, + (PUINT32)&pFtInfoBuf->RicInfo.Len); + + /* In an RSN, The IE count need to include RIC for + MIC calculation */ + if (pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt > 0 && + pFtInfoBuf->RicInfo.Len > 0) + pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt += 1; + + /* prepare Ft IEs for association response. */ + FT_SET_MDID(pFtInfoBuf->MdIeInfo.MdId, pFtCfg->FtMdId); + FtCapPlc.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCapPlc.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + pFtInfoBuf->MdIeInfo.FtCapPlc.word = + pFtInfo->MdIeInfo.FtCapPlc.word & FtCapPlc.word; + pFtInfoBuf->MdIeInfo.Len = 3; + + result = MLME_SUCCESS; + + break; + } while(0); + + return result; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +USHORT FT_AssocReqHandler( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN PFT_CFG pFtCfg, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pPeer_FtInfo, + OUT PFT_INFO pFtInfoBuf) +{ + USHORT statusCode = MLME_SUCCESS; + FT_CAP_AND_POLICY FtCapPlc; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:\n", __FUNCTION__)); + + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + + if ((pFtCfg->FtCapFlag.Dot11rFtEnable) + && (pPeer_FtInfo != NULL) && (pPeer_FtInfo->MdIeInfo.Len != 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: it's FT client \n", __FUNCTION__)); + + /* If the contents of the MDIE received by the AP do not match the + ** contents advertised in the Beacon and Probe Response frames, the + ** AP shall reject the (Re)association Request with status code 54 + ** ("Invalid MDIE"). */ + if (!FT_MDID_EQU(pPeer_FtInfo->MdIeInfo.MdId, pFtCfg->FtMdId)) + statusCode = FT_STATUS_CODE_INVALID_MDIE; + else + { + UINT8 ft_len = 0; + + ft_len = sizeof(FT_FTIE); + + /* Indicate this is a FT Initial Mobility Domain Association procedure */ + if (!IS_FT_STA(pEntry)) + { + NdisMoveMemory(&pEntry->MdIeInfo, &pPeer_FtInfo->MdIeInfo, + pPeer_FtInfo->MdIeInfo.Len); + } + + if (pPeer_FtInfo->RSNIE_Len != 0) + { + + /* This is Fast BSS transition procedure with RSN */ + if (pPeer_FtInfo->FtIeInfo.Len > 0) + { + UINT16 result; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Fast BSS transition in a RSN \n", __FUNCTION__)); + result = FT_AssocReqRsnValidation(pAd, + pEntry, + pPeer_FtInfo, + pFtInfoBuf); + if (result != MLME_SUCCESS) + return result; + + /* Update the length of GTK in FTIE*/ + if (pFtInfoBuf->FtIeInfo.GtkLen) + ft_len += (2 + pFtInfoBuf->FtIeInfo.GtkLen); + } + + /* Prepare in the R0KHID and its length */ + if (isReassoc) + { + pFtInfoBuf->FtIeInfo.R0khIdLen = pPeer_FtInfo->FtIeInfo.R0khIdLen; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R0khId, + pPeer_FtInfo->FtIeInfo.R0khId, pFtInfoBuf->FtIeInfo.R0khIdLen); + } + else + { + pFtInfoBuf->FtIeInfo.R0khIdLen = pFtCfg->FtR0khIdLen; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R0khId, + pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen); + } + ft_len += (2 + pFtInfoBuf->FtIeInfo.R0khIdLen); + + /* Prepare in the R1KHID and its length */ + pFtInfoBuf->FtIeInfo.R1khIdLen = MAC_ADDR_LEN; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R1khId, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN); + ft_len += (2 + MAC_ADDR_LEN); + + /* Update the length of FTIE */ + pFtInfoBuf->FtIeInfo.Len = ft_len; + } + + /* prepare MDIE for association response. */ + FT_SET_MDID(pFtInfoBuf->MdIeInfo.MdId, pFtCfg->FtMdId); + FtCapPlc.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCapPlc.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + pFtInfoBuf->MdIeInfo.FtCapPlc.word = + pPeer_FtInfo->MdIeInfo.FtCapPlc.word & FtCapPlc.word; + pFtInfoBuf->MdIeInfo.Len = 3; + + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: it isn't FT client \n", __FUNCTION__)); + } + + return statusCode; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabInit( + IN PRTMP_ADAPTER pAd) +{ + INT idx; + + /* init spin lock */ + NdisAllocateSpinLock(pAd, &(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + pAd->ApCfg.FtTab.FT_R1khEntryTabSize = 0; + for (idx = 0; idx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; idx++) + { + /* init event list */ + initList(&(pAd->ApCfg.FtTab.FT_R1khEntryTab[idx])); + } + pAd->ApCfg.FtTab.FT_R1khEntryTabReady = TRUE; +} /* End of FT_R1khEntryTabInit */ + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +INT FT_R1khEntryInsert( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPmkR0Name, + IN PUINT8 pPmkR1Name, + IN PUINT8 pPmkR1Key, + IN PUINT8 pPairwisChipher, + IN PUINT8 pAkmSuite, + IN UINT32 KeyLifeTime, + IN UINT32 RassocDeadline, + IN PUINT8 pR0khId, + IN UINT8 R0khIdLen, + IN PUINT8 pStaMac) +{ + UINT8 HashId; + PFT_R1HK_ENTRY pEntry; + + if (pAd->ApCfg.FtTab.FT_R1khEntryTabSize >= FT_R1KH_ENTRY_TABLE_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: FT_R1khEntryTab full.\n", __FUNCTION__)); + return -1; + } + + if(os_alloc_mem(pAd, (PUCHAR *)&pEntry, sizeof(FT_R1HK_ENTRY)) == + NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to alloc memory.\n", __FUNCTION__)); + return -1; + } + + pEntry->pNext = NULL; + if (pStaMac != NULL) + NdisMoveMemory(pEntry->StaMac, pStaMac, MAC_ADDR_LEN); + if (pR0khId != NULL && R0khIdLen > 0) + { + pEntry->R0khIdLen = R0khIdLen; + NdisMoveMemory(pEntry->R0khId, pR0khId, R0khIdLen); + } + if (pPairwisChipher != NULL) + NdisMoveMemory(pEntry->PairwisChipher, pPairwisChipher, 4); + if (pAkmSuite != NULL) + NdisMoveMemory(pEntry->AkmSuite, pAkmSuite, 4); + if (pPmkR0Name != NULL) + NdisMoveMemory(pEntry->PmkR0Name, pPmkR0Name, 16); + if (pPmkR1Name != NULL) + NdisMoveMemory(pEntry->PmkR1Name, pPmkR1Name, 16); + if (pPmkR1Key != NULL) + NdisMoveMemory(pEntry->PmkR1Key, pPmkR1Key, 32); + pEntry->KeyLifeTime = KeyLifeTime; + pEntry->RassocDeadline = RassocDeadline; + HashId = FT_R1KH_HASH_INDEX(pEntry->PmkR1Name); + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + insertTailList(&pAd->ApCfg.FtTab.FT_R1khEntryTab[HashId], + (PLIST_ENTRY)pEntry); + + pAd->ApCfg.FtTab.FT_R1khEntryTabSize++; + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + return 0; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PFT_R1HK_ENTRY pEntry) +{ + UINT8 HashId; + PFT_TAB pFtTab; + + pFtTab = &pAd->ApCfg.FtTab; + HashId = FT_R1KH_HASH_INDEX(pEntry->PmkR1Name); + + RTMP_SEM_LOCK(&(pFtTab->FT_R1khEntryTabLock)); + + delEntryList(&pFtTab->FT_R1khEntryTab[HashId], + (PLIST_ENTRY)pEntry); + + os_free_mem(pAd, pEntry); + + pFtTab->FT_R1khEntryTabSize--; + RTMP_SEM_UNLOCK(&(pFtTab->FT_R1khEntryTabLock)); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabDestroy( + IN PRTMP_ADAPTER pAd) +{ + INT idx; + PFT_R1HK_ENTRY pEntry; + PFT_TAB pFtTab; + + pFtTab = &pAd->ApCfg.FtTab; + pFtTab->FT_R1khEntryTabReady = FALSE; + + RTMP_SEM_LOCK(&(pFtTab->FT_R1khEntryTabLock)); + + for (idx = 0; idx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; idx ++) + { + do + { + pEntry = (PFT_R1HK_ENTRY)removeHeadList( + &(pFtTab->FT_R1khEntryTab[idx])); + if (pEntry != NULL) + os_free_mem(pAd, (PUCHAR)pEntry); + } while (pEntry != NULL); + } + + RTMP_SEM_UNLOCK(&(pFtTab->FT_R1khEntryTabLock)); + NdisFreeSpinLock(&(pFtTab->FT_R1khEntryTabLock)); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +PFT_R1HK_ENTRY FT_R1khEntryTabLookup( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPMKR1Name) +{ + UINT8 HashId; + PFT_R1HK_ENTRY pEntry; + + HashId = FT_R1KH_HASH_INDEX(pPMKR1Name); + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + pEntry = (PFT_R1HK_ENTRY)pAd->ApCfg.FtTab.FT_R1khEntryTab[HashId].pHead; + while(pEntry != NULL) + { + if (RTMPEqualMemory(pPMKR1Name, pEntry->PmkR1Name, FT_KDP_WPA_NAME_MAX_SIZE)) + break; + pEntry = pEntry->pNext; + } + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + return pEntry; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FtAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMAC_TABLE_ENTRY pEntry; + PHEADER_802_11 pHdr; + PFT_ACTION pFtAction; + UINT16 FtActLen; + BOOLEAN IsTerminate; + PFT_INFO pFtInfo = NULL; + PFT_INFO pFtInfoBuf = NULL; + USHORT result; + NDIS_STATUS NStatus; + PUCHAR pFtActFrame = NULL; + ULONG FtActFrameLen = 0; + INT apidx; + PFT_CFG pFtCfg; + + os_alloc_mem(pAd, (UCHAR **)&pFtInfo, sizeof(FT_INFO)); + if (pFtInfo == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):: pFtInfo alloc failed.\n", __FUNCTION__, __LINE__)); + return; + } + + os_alloc_mem(pAd, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO)); + if (pFtInfoBuf == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):: pFtInfoBuf alloc failed.\n", __FUNCTION__, __LINE__)); + goto out; + } + + pHdr = (PHEADER_802_11)Elem->Msg; + pFtAction = (PFT_ACTION)(&Elem->Msg[LENGTH_802_11]); + FtActLen = (Elem->MsgLen - LENGTH_802_11); + + /* Find which MBSSID to be authenticate */ + apidx = get_apidx_by_addr(pAd, pHdr->Addr1); + if (apidx >= pAd->ApCfg.BssidNum) + goto out; + + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + + /* decide self is terminate or not. */ + IsTerminate = (MAC_ADDR_EQUAL(pFtAction->TargetApAddr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid)) ? TRUE : FALSE; + + switch(pFtAction->Action) + { + case FT_ACTION_BT_REQ: + + DBGPRINT(RT_DEBUG_TRACE, + ("Get FT_ACTION_BT_REQ IsTerminate=%d\n", IsTerminate)); + + if (IsTerminate) + { + NStatus = MlmeAllocateMemory(pAd, &pFtActFrame); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + goto out; + } + + if (!pFtCfg->FtCapFlag.Dot11rFtEnable) + goto out; + + pEntry = MacTableLookup(pAd, pHdr->Addr2); + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, pHdr->Addr2, + &pAd->ApCfg.MBSSID[apidx].wdev, apidx, OPMODE_AP, TRUE); + + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + /* Parse FT-Request action frame. */ + FT_ReqActionParse(pAd, (FtActLen - sizeof(PFT_ACTION)), + pFtAction->Oct, pFtInfo); + + /* FT-Request frame Handler. */ + result = FT_AuthReqHandler(pAd, pEntry, pFtInfo, pFtInfoBuf); + + if (result == MLME_SUCCESS) + { + NdisMoveMemory(&pEntry->MdIeInfo, &pFtInfo->MdIeInfo, sizeof(FT_MDIE_INFO)); + + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; + } + + /* Build Ft-Rsp action frame. */ + FtActFrameLen = 0; + FT_MakeFtActFrame(pAd, pFtActFrame, &FtActFrameLen, + FT_ACTION_BT_RSP, pEntry->Addr, pFtAction->TargetApAddr, + result, pFtInfoBuf); + + /* send FT-Rsp action frame to corresponding STA. */ + FT_RrbEnqueue(pAd, pHdr->Addr3, (PFT_ACTION)pFtActFrame, + FtActFrameLen, pEntry->apidx); + + } + else + { + FT_RrbEnqueue(pAd, pFtAction->TargetApAddr, + (PFT_ACTION)pFtAction, FtActLen, apidx); + } + break; + + case FT_ACTION_BT_CONFIRM: + + DBGPRINT(RT_DEBUG_TRACE, + ("Get FT_ACTION_BT_CONFIRM IsTerminate=%d\n", IsTerminate)); + + if (IsTerminate) + { + NDIS_STATUS NStatus = MlmeAllocateMemory(pAd, &pFtActFrame); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + goto out; + } + + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s: invalid STA.\n", __FUNCTION__)); + goto out; + } + + if (pEntry->apidx > pAd->ApCfg.BssidNum) + goto out; + + if (!pFtCfg->FtCapFlag.Dot11rFtEnable) + goto out; + + /* Parse FT-Request action frame. */ + FT_ReqActionParse(pAd, (FtActLen - sizeof(PFT_ACTION)), + pFtAction->Oct, pFtInfo); + + /* FT-Request frame Handler. */ + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + os_alloc_mem(pAd, (UCHAR **)&(pFtInfoBuf->RicInfo.pRicInfo), 512); + if (pFtInfoBuf->RicInfo.pRicInfo != NULL) + { + result = FT_AuthConfirmHandler(pAd, pEntry, pFtInfo, pFtInfoBuf); + + /* Build Ft-Ack action frame. */ + FtActFrameLen = 0; + FT_MakeFtActFrame(pAd, pFtActFrame, &FtActFrameLen, + FT_ACTION_BT_ACK, pEntry->Addr, pHdr->Addr3, result, + pFtInfoBuf); + + /* reply FT-Ack action frame to corresponding STA. */ + FT_RrbEnqueue(pAd, pHdr->Addr3, (PFT_ACTION)pFtActFrame, + FtActFrameLen, pEntry->apidx); + os_free_mem(NULL, pFtInfoBuf->RicInfo.pRicInfo); + } + else + { + goto out; + } + } + else + FT_RrbEnqueue(pAd, pFtAction->TargetApAddr, + pFtAction, FtActLen, apidx); + break; + + case FT_ACTION_BT_RSP: + case FT_ACTION_BT_ACK: + + DBGPRINT(RT_DEBUG_TRACE, + ("Get FT_ACTION_BT_RSP or FT_ACTION_BT_ACK \ + IsTerminate=%d\n", IsTerminate)); + + /* forward it to corrspondign STA. */ + NStatus = MlmeAllocateMemory(pAd, &pFtActFrame); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + goto out; + } + + COPY_MAC_ADDR(pHdr->Addr1, pFtAction->StaMac); + COPY_MAC_ADDR(pHdr->Addr2, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + COPY_MAC_ADDR(pHdr->Addr3, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + pHdr->FC.ToDs = 0; + pHdr->FC.FrDs = 1; + + FtActFrameLen = 0; + MakeOutgoingFrame(pFtActFrame, &FtActFrameLen, + Elem->MsgLen, pHdr, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pFtActFrame, FtActFrameLen); + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow action type (%d).\n", \ + __FUNCTION__, pFtAction->Action)); + break; + } +out: + if (pFtInfo) + os_free_mem(NULL, pFtInfo); + + if (pFtInfoBuf) + os_free_mem(NULL, pFtInfoBuf); + + if (pFtActFrame) + MlmeFreeMemory(pAd, pFtActFrame); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +static VOID FT_RrbEnqueue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN PFT_ACTION pFtAction, + IN UINT16 FtActLen, + IN UINT32 ApIdx) +{ + FT_KDP_EVT_ACTION FtKdpEvtAction; + + COPY_MAC_ADDR(FtKdpEvtAction.MacDa, pDA); + + switch(pFtAction->Action) + { + case FT_ACTION_BT_REQ: + case FT_ACTION_BT_CONFIRM: + FtKdpEvtAction.RequestType = 0; + COPY_MAC_ADDR(FtKdpEvtAction.MacSa, pFtAction->StaMac); + COPY_MAC_ADDR(FtKdpEvtAction.MacAp, + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid); + break; + + case FT_ACTION_BT_RSP: + case FT_ACTION_BT_ACK: + FtKdpEvtAction.RequestType = 1; + COPY_MAC_ADDR(FtKdpEvtAction.MacSa, pFtAction->TargetApAddr); + COPY_MAC_ADDR(FtKdpEvtAction.MacAp, + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid); + break; + } + + FT_KDP_EVENT_INFORM(pAd, ApIdx, FT_KDP_SIG_ACTION, pFtAction, + FtActLen, &FtKdpEvtAction); + +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_RrbHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPktSrc, + IN INT32 PktLen) +{ + PMAC_TABLE_ENTRY pEntry; + NDIS_STATUS Status; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen; + HEADER_802_11 Hdr; + PFT_RRB pRrb = (PFT_RRB)(pPktSrc + LENGTH_802_3); + PUCHAR pDA; + PUCHAR pSA; + PFT_ACTION pFtAction; + ULONG Wcid; + + + Status = MlmeAllocateMemory(pAd, &pOutBuffer); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: allocate auth buffer fail!\n", + __FUNCTION__)); + return; + } /* End of if */ + + pFtAction = (PFT_ACTION)pRrb->Oct; + + pDA = pPktSrc; + pSA = pFtAction->StaMac; + + pEntry = MacTableLookup(pAd, pSA); + if (pEntry) + Wcid = pEntry->wcid; + else + Wcid = RESERVED_WCID; + + /* Make 802.11 header. */ + ActHeaderInit(pAd, &Hdr, pDA, pSA, pRrb->APAdr); + + /* Make ft action frame. */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + pRrb->FTActLen, (PUCHAR)pRrb->Oct, + END_OF_ARGS); + + /* enqueue it into FT action state machine. */ + REPORT_MGMT_FRAME_TO_MLME(pAd, Wcid, pOutBuffer, FrameLen, 0, 0, 0, 0, OPMODE_AP); + + if (pOutBuffer) + os_free_mem(pAd, pOutBuffer); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1KHInfoMaintenance( + IN PRTMP_ADAPTER pAd) +{ + INT HashIdx; + PFT_R1HK_ENTRY pEntry; + PMAC_TABLE_ENTRY pMacEntry; + PFT_TAB pFtTab; + + pFtTab = &pAd->ApCfg.FtTab; + if (pFtTab->FT_R1khEntryTabReady != TRUE) + return; + + RTMP_SEM_LOCK(&pFtTab->FT_R1khEntryTabLock); + for (HashIdx = 0; HashIdx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; HashIdx++) + { + pEntry = (PFT_R1HK_ENTRY)\ + (pFtTab->FT_R1khEntryTab[HashIdx].pHead); + + while (pEntry != NULL) + { + if((pEntry->AuthMode == Ndis802_11AuthModeWPA2) + && ((pEntry->KeyLifeTime--) == 0)) + { + PFT_R1HK_ENTRY pEntryTmp; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + DBGPRINT(RT_DEBUG_OFF, ("%s: PMKCache timeout. Kick out the station and delete FT_R1khEntry!\n", + __FUNCTION__)); + + /* + Kick out the station. + and Info KDP daemon to delete the key. + */ + pMacEntry = MacTableLookup(pAd, pEntry->StaMac); + + if (pMacEntry) + { + DisassocParmFill(pAd, &DisassocReq, pEntry->StaMac, + MLME_UNSPECIFY_FAIL); + MlmeEnqueue(pAd, AP_ASSOC_STATE_MACHINE, APMT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), (PVOID)&DisassocReq, 0); + } + + /* + Indicate IAPP daemon to delete R0KH-SA + relative to the STA + */ + FT_KDP_EVENT_INFORM(pAd, 0, FT_KDP_SIG_KEY_TIMEOUT, + pEntry->StaMac, 6, NULL); + + pEntryTmp = pEntry->pNext; + delEntryList(&pFtTab->FT_R1khEntryTab[HashIdx], + (PLIST_ENTRY)pEntry); + os_free_mem(pAd, pEntry); + pFtTab->FT_R1khEntryTabSize--; + pEntry = pEntryTmp; + } + else + pEntry = pEntry->pNext; + } + } + RTMP_SEM_UNLOCK(&pFtTab->FT_R1khEntryTabLock); +} + +VOID FT_ConstructGTKSubIe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + OUT PFT_FTIE_INFO pFtInfo) +{ + UINT8 gtk_len = 0; + UINT8 pad_len = 0; + UINT8 key_buf[32]; + UINT8 e_key_buf[40]; + UINT8 key_len; + UINT e_key_len; + UCHAR apidx; + UCHAR key_idx; + UCHAR cipher_alg; + PUINT8 gtk; + ULONG TmpLen = 0; + UINT8 remainder; + FT_GTK_KEY_INFO KeyInfo; + UCHAR rsc[8]; + + apidx = pEntry->apidx; + gtk = pAd->ApCfg.MBSSID[apidx].GTK; + key_idx = pAd->ApCfg.MBSSID[pEntry->apidx].wdev.DefaultKeyId; + cipher_alg = pAd->SharedKey[pEntry->apidx][key_idx].CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("%s : key idx(%d) \n", __FUNCTION__, key_idx)); + + switch (cipher_alg) + { + case CIPHER_WEP64: + gtk_len = 5; + break; + case CIPHER_WEP128: + gtk_len = 13; + break; + case CIPHER_TKIP: + gtk_len = 32; + break; + case CIPHER_AES: + gtk_len = 16; + break; + } + + /* The Key field shall be padded before encrypting if the key length + is less than 16 octets or if it is not a multiple of 8. */ + NdisMoveMemory(key_buf, gtk, gtk_len); + key_len = gtk_len; + if ((remainder = gtk_len & 0x07) != 0) + { + INT i; + + pad_len = (8 - remainder); + key_buf[gtk_len] = 0xDD; + for (i = 1; i < pad_len; i++) + key_buf[gtk_len + i] = 0; + + key_len += pad_len; + } + if (key_len < 16) + { + INT i; + + pad_len = 16 - key_len; + for (i = 0; i < pad_len; i++) + key_buf[key_len + i] = 0; + + key_len += pad_len; + } + + NdisZeroMemory(&KeyInfo, sizeof(FT_GTK_KEY_INFO)); + KeyInfo.field.KeyId = key_idx; + KeyInfo.word = cpu2le16(KeyInfo.word); + + /* Get Group RSC form Asic */ + NdisZeroMemory(rsc, 8); + RTMPGetTxTscFromAsic(pAd, apidx, rsc); + + e_key_len = key_len; + AES_Key_Wrap(key_buf, key_len, + &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + e_key_buf, &e_key_len); + + /* Construct FT GTK-IE*/ + + MakeOutgoingFrame(pFtInfo->GtkSubIE, &TmpLen, + sizeof(FT_GTK_KEY_INFO), &KeyInfo, + 1, >k_len, + 8, rsc, + e_key_len, e_key_buf, + END_OF_ARGS); + + pFtInfo->GtkLen = TmpLen; + +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +BOOLEAN FT_QueryKeyInfoForKDP( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + OUT FT_KDP_EVT_KEY_ELM *pEvtKeyReq) +{ + INT CacheIdx; + ULONG Now; + UINT32 alive_tick; + INT remain_time = 0; + PAP_BSSID_INFO pkeyInfo; + PFT_R1HK_ENTRY pR1khEntry; + UCHAR OriPMKR1Name[FT_KDP_WPA_NAME_MAX_SIZE]; + + /* Search PMK Cache */ + CacheIdx = RTMPSearchPMKIDCache(pAd, ApIdx, pEvtKeyReq->MacAddr); + + if (CacheIdx == -1) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The PMKR0 doesn't exist for %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pEvtKeyReq->MacAddr))); + return FALSE; + } + + pkeyInfo = &pAd->ApCfg.MBSSID[ApIdx].PMKIDCache.BSSIDInfo[CacheIdx]; + + /* Derive the PMK-R1 and PMK-R1-Name for this R1KH */ + FT_DerivePMKR1(pkeyInfo->PMK, + pkeyInfo->PMKID, + /*pEvtKeyReq->KeyInfo.R1KHID, */ /* peer R1KH-ID */ + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid, + pEvtKeyReq->MacAddr, + pEvtKeyReq->PMKR1, + OriPMKR1Name); + + pR1khEntry = FT_R1khEntryTabLookup(pAd, OriPMKR1Name); + + if (pR1khEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : No initial association information 2 for %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pEvtKeyReq->MacAddr))); + return FALSE; + } + + FT_DerivePMKR1(pkeyInfo->PMK, + pkeyInfo->PMKID, + pEvtKeyReq->KeyInfo.R1KHID, /* peer R1KH-ID */ + pEvtKeyReq->MacAddr, + pEvtKeyReq->PMKR1, + pEvtKeyReq->PMKR1Name); + + /* calculate the remaine time of PMKR0-Key */ + NdisGetSystemUpTime(&Now); + alive_tick = Now - pkeyInfo->RefreshTime; + if (alive_tick < pAd->ApCfg.MBSSID[ApIdx].PMKCachePeriod) + remain_time = (pAd->ApCfg.MBSSID[ApIdx].PMKCachePeriod - alive_tick)/OS_HZ; + + /* Assign KeyLifeTime and Reassociation Deadline */ + pEvtKeyReq->KeyLifeTime = remain_time; + pEvtKeyReq->ReassocDeadline = FT_REASSOC_DEADLINE; + + /* Assign R0KH-ID */ + pEvtKeyReq->KeyInfo.R0KHIDLen = pAd->ApCfg.MBSSID[ApIdx].FtCfg.FtR0khIdLen; + NdisMoveMemory(pEvtKeyReq->KeyInfo.R0KHID, + pAd->ApCfg.MBSSID[ApIdx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[ApIdx].FtCfg.FtR0khIdLen); + + /* Assign PMK-R0-Name */ + NdisMoveMemory(pEvtKeyReq->KeyInfo.PMKR0Name, pkeyInfo->PMKID, LEN_PMK_NAME); + + /* Assign cipher and AKM */ + NdisMoveMemory(pEvtKeyReq->PairwisChipher, pR1khEntry->PairwisChipher, 4); + NdisMoveMemory(pEvtKeyReq->AkmSuite, pR1khEntry->AkmSuite, 4); + + /* Assign R0KH MAC */ + NdisMoveMemory(pEvtKeyReq->R0KH_MAC, pEvtKeyReq->MacAddr, 6); + + return TRUE; + +} + +UINT16 FT_AuthReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_CFG pFtCfg, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out) +{ + UINT8 count = 0; + PUINT8 pAkmSuite = NULL; + PUINT8 pPmkR0Name = NULL; + PUINT8 pCipher = NULL; + PFT_R1HK_ENTRY pR1hkEntry = NULL; + UINT8 ft_len = 0; + UINT8 ptk_len; + UINT8 rsnie_len = 0; + PUINT8 rsnie_ptr = NULL; + UINT16 result = MLME_SUCCESS; + + /* Check the validity of the received RSNIE */ + if ((result = APValidateRSNIE(pAd, pEntry, pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len)) != MLME_SUCCESS) + { + return result; + } + + /* Extract the PMK-R0-Name from the received RSNIE */ + pPmkR0Name = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PMKID_LIST, &count); + if (pPmkR0Name) + { +#ifdef FT_RSN_DEBUG + hex_dump("FT PMK-R0-NAME", pPmkR0Name, count * LEN_PMK_NAME); +#endif /* FT_RSN_DEBUG */ + + /* The R1KH of the target AP uses the value of PMKR0Name and other + information in the frame to calculate PMKR1Name. */ + FT_DerivePMKR1Name(pPmkR0Name, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, + pEntry->Addr, + pEntry->FT_PMK_R1_NAME); + + hex_dump("pPmkR0Name=", pPmkR0Name, LEN_PMK_NAME); + hex_dump("pAd->ApCfg.MBSSID[pEntry->apidx].Bssid=", pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, 6); + hex_dump("pEntry->Addr=", pEntry->Addr, 6); + hex_dump("pEntry->FT_PMK_R1_NAME=", pEntry->FT_PMK_R1_NAME, sizeof(pEntry->FT_PMK_R1_NAME)); + + /* Look up the R1KH Table */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + + /* If the target AP does not have the key identified by PMKR1Name, + it may retrieve that key from the R0KH identified by the STA. */ + if ((pR1hkEntry == NULL) || + (RTMPEqualMemory(pEntry->FT_PMK_R1_NAME, pR1hkEntry->PmkR1Name, LEN_PMK_NAME) == FALSE)) + { + + /* If the requested R0KH is not reachable, the AP shall respond + to the Authentication Request with status code 28 ("R0KH unreachable"). */ + { + return FT_STATUS_CODE_R0KH_UNREACHABLE; + } + } + + /* If the RSNIE in the Authentication Request frame contains an invalid + PMKR0Name, and the AP has determined that it is an invalid PMKR0Name, + the AP shall reject the Authentication Request with status code 53 + ("Invalid PMKID"). */ + if ((pR1hkEntry == NULL) || + (RTMPEqualMemory(pPmkR0Name, pR1hkEntry->PmkR0Name, LEN_PMK_NAME) == FALSE)) + { + DBGPRINT_ERR(("%s : The PMKID is invalid\n", __FUNCTION__)); + hex_dump("Peer PMKR0Name", pPmkR0Name, LEN_PMK_NAME); + hex_dump("Own PMKR0Name", pR1hkEntry->PmkR0Name, LEN_PMK_NAME); + return FT_STATUS_CODE_INVALID_PMKID; + } + } + else + { + /* reject the Authentication Request with status code 53 ("Invalid PMKID") */ + DBGPRINT_ERR(("%s : The peer PMKID is emtpy\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } + + if (pR1hkEntry == NULL) + { + DBGPRINT_ERR(("%s : The R1KH table doesn't exist\n", __FUNCTION__)); + return FT_STATUS_CODE_R0KH_UNREACHABLE; + } + + /* Update the Reassocation Deadline */ + pEntry->AssocDeadLine = pR1hkEntry->RassocDeadline; + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, AKM_SUITE, &count); + if ((pAkmSuite == NULL) || + (RTMPEqualMemory(pAkmSuite, pR1hkEntry->AkmSuite, 4) == FALSE)) + { + /* It doesn't a negotiated AKM of Fast BSS Transition, the AP + shall reject the Authentication Request with status code 43 ("Invalid AKMP"). */ + DBGPRINT_ERR(("%s : The AKM is invalid\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* Extract the pairwise cipher suite from the received RSNIE */ + pCipher = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PAIRWISE_SUITE, &count); + if ((pCipher == NULL) || + (RTMPEqualMemory(pCipher, pR1hkEntry->PairwisChipher, 4) == FALSE)) + { + /* If the non-AP STA selects a pairwise cipher suite in the RSNIE + that is different than the ones used in the Initial Mobility + Domain association, then the AP shall reject the Authentication + Request with status code 19 ("Invalid Pair-wise Cipher"). */ + DBGPRINT_ERR(("%s : The pairwise-cipher is invalid\n", __FUNCTION__)); + return MLME_INVALID_PAIRWISE_CIPHER; + } + + /* Check the validity of R0KHID */ + if ((pFtInfo_in->FtIeInfo.R0khIdLen != pR1hkEntry->R0khIdLen) || + (RTMPEqualMemory(pFtInfo_in->FtIeInfo.R0khId, + pR1hkEntry->R0khId, + pR1hkEntry->R0khIdLen) == FALSE)) + { + /* If the FTIE in the FT Request frame contains an invalid R0KH-ID, + the AP shall reject the FT Request with status code 55 ("Invalid FTIE"). */ + DBGPRINT_ERR(("%s : The FTIE is invalid\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_FTIE; + } + + /* Get PMK-R1 from R1KH Table */ + NdisMoveMemory(pEntry->FT_PMK_R1, pR1hkEntry->PmkR1Key, LEN_PMK); + + /* Get SNonce from Auth-req */ + NdisMoveMemory(pEntry->SNonce, pFtInfo_in->FtIeInfo.SNonce, LEN_NONCE); + + /* Generate ANonce randomly */ + GenRandom(pAd, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, pEntry->ANonce); + + hex_dump("anonce", pEntry->ANonce, 32); + hex_dump("snonce", pEntry->SNonce, 32); + + if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) + ptk_len = 32+32; + else + ptk_len = 32+16; + + /* Derive FT PTK and PTK-NAME */ + FT_DerivePTK(pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME, + pEntry->ANonce, + pEntry->SNonce, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, + pEntry->Addr, + ptk_len, + pEntry->PTK, + pEntry->PTK_NAME); + + ft_len = sizeof(FT_FTIE); + + /* Prepare some information for authentication response using */ + NdisMoveMemory(pFtInfo_out->FtIeInfo.ANonce, pEntry->ANonce, LEN_NONCE); + NdisMoveMemory(pFtInfo_out->FtIeInfo.SNonce, pEntry->SNonce, LEN_NONCE); + + pFtInfo_out->FtIeInfo.R0khIdLen = pR1hkEntry->R0khIdLen; + NdisMoveMemory(pFtInfo_out->FtIeInfo.R0khId, + pR1hkEntry->R0khId, + pR1hkEntry->R0khIdLen); + ft_len += (2 + pR1hkEntry->R0khIdLen); + + pFtInfo_out->FtIeInfo.R1khIdLen = MAC_ADDR_LEN; + NdisMoveMemory(pFtInfo_out->FtIeInfo.R1khId, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, + MAC_ADDR_LEN); + ft_len += (2 + MAC_ADDR_LEN); + + /* Update the total length for FTIE */ + pFtInfo_out->FtIeInfo.Len = ft_len; + + /* Prepare RSNIE for authentication response */ + if ((pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->apidx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->apidx].RSN_IE[0][0]; + } + + pFtInfo_out->RSNIE_Len = 0; + RTMPInsertRSNIE(pFtInfo_out->RSN_IE, + (PULONG)&pFtInfo_out->RSNIE_Len, + rsnie_ptr, + rsnie_len, + pPmkR0Name, + LEN_PMK_NAME); + + return MLME_SUCCESS; + +} + +UINT16 FT_AuthConfirmRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in) +{ + PFT_FTIE_INFO pPeerFtIe; + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_count = 0; + UINT8 ft_mic[16]; + PFT_R1HK_ENTRY pR1hkEntry = NULL; + PUINT8 pAkmSuite = NULL; + UINT8 count = 0; + + /* The R1KH of the target AP verifies the MIC in the FTIE in + the Reassociation Request frame, and shall discard the + request if the MIC is incorrect. */ + FT_CalculateMIC(pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, + pEntry->PTK, + 3, + pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + pFtInfo_in->MdIeInfo.pMdIe, + pFtInfo_in->MdIeInfo.Len + 2, + pFtInfo_in->FtIeInfo.pFtIe, + pFtInfo_in->FtIeInfo.Len + 2, + pFtInfo_in->RicInfo.RicIEs, + pFtInfo_in->RicInfo.RicIEsLen, + ft_mic); + + if (!RTMPEqualMemory(ft_mic, pFtInfo_in->FtIeInfo.MIC, FT_MIC_LEN)) + { + DBGPRINT_ERR(("%s : MIC is different\n", __FUNCTION__)); + hex_dump("received MIC", pFtInfo_in->FtIeInfo.MIC, FT_MIC_LEN); + hex_dump("desired MIC", ft_mic, FT_MIC_LEN); + return 0xFFFF; + } + + pPeerFtIe = &pFtInfo_in->FtIeInfo; + + /* Look up the R1KH Table */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1hkEntry == NULL) + { + DBGPRINT_ERR(("%s : Invalid R1KH table in target AP\n", __FUNCTION__)); + return FT_STATUS_CODE_RESERVED; + } + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + AKM_SUITE, &count); + + if ((pAkmSuite == NULL) || + (RTMPEqualMemory(pAkmSuite, pR1hkEntry->AkmSuite, 4) == FALSE)) + { + /* It doesn't a negotiated AKM of Fast BSS Transition, the AP + shall reject the Authentication Request with status code 43 + ("Invalid AKMP"). */ + DBGPRINT_ERR(("%s : Invalid AKMP\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* If the FTIE in the Reassociation Request frame contains + a different R0KH-ID, R1KH-ID, ANonce, or SNonce, the AP + shall reject the Reassociation Request with status code + 55 ("Invalid FTIE"). */ + if ((RTMPEqualMemory(pPeerFtIe->R0khId, pR1hkEntry->R0khId, pR1hkEntry->R0khIdLen) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->R1khId, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->ANonce, pEntry->ANonce, 32) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->SNonce, pEntry->SNonce, 32) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid FTIE\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_FTIE; + } + + /* If the RSNIE in the Reassociation Request frame contains an invalid + PMKR1Name, the AP shall reject the Reassociation Request with status + code 53 ("Invalid PMKID"). */ + pmkid_ptr = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PMKID_LIST, &pmkid_count); + if ((pmkid_ptr == NULL) || + (RTMPEqualMemory(pmkid_ptr, pEntry->FT_PMK_R1_NAME, LEN_PMK_NAME) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid PMKID\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } + + return MLME_SUCCESS; + +} + +UINT16 FT_AssocReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out) +{ + PFT_FTIE_INFO pPeerFtIe; + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_count = 0; + UINT8 ft_mic[16]; + UINT8 rsnie_len = 0; + PUINT8 rsnie_ptr = NULL; + PFT_R1HK_ENTRY pR1hkEntry = NULL; + PUINT8 pAkmSuite = NULL; + UINT8 count = 0; + + + /* The R1KH of the target AP verifies the MIC in the FTIE in + the Reassociation Request frame, and shall discard the + request if the MIC is incorrect. */ + FT_CalculateMIC(pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, + pEntry->PTK, + 5, + pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + pFtInfo_in->MdIeInfo.pMdIe, + pFtInfo_in->MdIeInfo.Len + 2, + pFtInfo_in->FtIeInfo.pFtIe, + pFtInfo_in->FtIeInfo.Len + 2, + pFtInfo_in->RicInfo.RicIEs, + pFtInfo_in->RicInfo.RicIEsLen, + ft_mic); + + if (!RTMPEqualMemory(ft_mic, pFtInfo_in->FtIeInfo.MIC, 16)) + { + DBGPRINT_ERR(("%s : MIC is different\n", __FUNCTION__)); + hex_dump("received MIC", pFtInfo_in->FtIeInfo.MIC, 16); + hex_dump("desired MIC", ft_mic, 16); + return 0xFFFF; + } + + pPeerFtIe = &pFtInfo_in->FtIeInfo; + + /* Look up the R1KH Table */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1hkEntry == NULL) + { + DBGPRINT_ERR(("%s : Invalid R1KH table in target AP\n", __FUNCTION__)); + return FT_STATUS_CODE_RESERVED; + } + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + AKM_SUITE, &count); + + if ((pAkmSuite == NULL) || + (RTMPEqualMemory(pAkmSuite, pR1hkEntry->AkmSuite, 4) == FALSE)) + { + /* It doesn't a negotiated AKM of Fast BSS Transition, the AP + shall reject the Authentication Request with status code 43 + ("Invalid AKMP"). */ + DBGPRINT_ERR(("%s : Invalid AKMP\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* If the FTIE in the Reassociation Request frame contains + a different R0KH-ID, R1KH-ID, ANonce, or SNonce, the AP + shall reject the Reassociation Request with status code + 55 ("Invalid FTIE"). */ + if ((RTMPEqualMemory(pPeerFtIe->R0khId, pR1hkEntry->R0khId, pR1hkEntry->R0khIdLen) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->R1khId, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->ANonce, pEntry->ANonce, 32) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->SNonce, pEntry->SNonce, 32) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid FTIE\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_FTIE; + } + + /* If the RSNIE in the Reassociation Request frame contains an invalid + PMKR1Name, the AP shall reject the Reassociation Request with status + code 53 ("Invalid PMKID"). */ + pmkid_ptr = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PMKID_LIST, &pmkid_count); + if ((pmkid_ptr == NULL) || + (RTMPEqualMemory(pmkid_ptr, pEntry->FT_PMK_R1_NAME, LEN_PMK_NAME) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid PMKID\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } + + /* Prepare RSNIE for outgoing frame */ + if ((pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->apidx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->apidx].RSN_IE[0][0]; + } + + pFtInfo_out->RSNIE_Len = 0; + RTMPInsertRSNIE(pFtInfo_out->RSN_IE, + (PULONG)&pFtInfo_out->RSNIE_Len, + rsnie_ptr, + rsnie_len, + pEntry->FT_PMK_R1_NAME, + LEN_PMK_NAME); + + /* Prepare MIC-control and MIC field of FTIE for outgoing frame. */ + pFtInfo_out->FtIeInfo.MICCtr.field.IECnt = 3; + NdisZeroMemory(pFtInfo_out->FtIeInfo.MIC, 16); + + /* Prepare ANonce and Snonce field of FTIE for outgoing frame */ + NdisMoveMemory(pFtInfo_out->FtIeInfo.ANonce, pEntry->ANonce, LEN_NONCE); + NdisMoveMemory(pFtInfo_out->FtIeInfo.SNonce, pEntry->SNonce, LEN_NONCE); + + /* Prepare GTK related information of FTIE for outgoing frame */ + FT_ConstructGTKSubIe(pAd, pEntry, &pFtInfo_out->FtIeInfo); + /*ft_len += (2 + pFtInfo_out->FtIeInfo.GtkLen); */ + + /* Prepare RIC-Response */ + + return MLME_SUCCESS; + +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillMdIeInfo( + PEID_STRUCT eid_ptr, + PFT_MDIE_INFO pMdIeInfo) +{ + PFT_MDIE pMdIe; + + pMdIeInfo->Len = 3; + pMdIeInfo->pMdIe = eid_ptr; /* store the pointer of the original MD-IE for MIC calculating */ + + pMdIe = (PFT_MDIE)(eid_ptr->Octet); + FT_SET_MDID(pMdIeInfo->MdId, pMdIe->MdId); + + NdisMoveMemory(&(pMdIeInfo->FtCapPlc.word), &pMdIe->FtCapPlc.word, + sizeof(FT_CAP_AND_POLICY)); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillFtIeInfo( + PEID_STRUCT eid_ptr, + PFT_FTIE_INFO pFtIeInfo) +{ + PFT_FTIE pFtIe; + PFT_OPTION_FIELD subEidPtr; + UINT16 MicCtrBuf; + INT RemainLen; + PUINT8 ptr; + + RemainLen = eid_ptr->Len; + pFtIeInfo->Len = eid_ptr->Len; + pFtIeInfo->pFtIe = eid_ptr; /* store the pointer of the original FT-IE for MIC calculating */ + + pFtIe = (PFT_FTIE)eid_ptr->Octet; + NdisMoveMemory(&MicCtrBuf, &(pFtIe->MICCtr.word), + sizeof(FT_MIC_CTR_FIELD)); + pFtIeInfo->MICCtr.word = le2cpu16(MicCtrBuf); + RemainLen -= 2; + + NdisMoveMemory(pFtIeInfo->MIC, pFtIe->MIC, 16); + RemainLen -= 16; + + NdisMoveMemory(pFtIeInfo->ANonce, pFtIe->ANonce, 32); + RemainLen -= 32; + + NdisMoveMemory(pFtIeInfo->SNonce, pFtIe->SNonce, 32); + RemainLen -= 32; + + /* Pare sub-element field. */ + /*subEidPtr = (PFT_OPTION_FIELD)(pFtIe->Option); */ + ptr = pFtIe->Option; + while (RemainLen > 0) + { + subEidPtr = (PFT_OPTION_FIELD)ptr; + + switch(subEidPtr->SubElementId) + { + case FT_R0KH_ID: + if ((subEidPtr->Len > 0) && (subEidPtr->Len <=FT_ROKH_ID_LEN)) + { + pFtIeInfo->R0khIdLen = subEidPtr->Len; + NdisMoveMemory(pFtIeInfo->R0khId, subEidPtr->Oct, + pFtIeInfo->R0khIdLen); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Invalid R0KHID Length (%d)\n", + __FUNCTION__, subEidPtr->Len)); + break; + + case FT_R1KH_ID: + if (subEidPtr->Len == FT_R1KH_ID_LEN) + { + pFtIeInfo->R1khIdLen = subEidPtr->Len; + NdisMoveMemory(pFtIeInfo->R1khId, subEidPtr->Oct, + pFtIeInfo->R1khIdLen); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Invalid R1KHID Length (%d)\n", + __FUNCTION__, subEidPtr->Len)); + break; + + case FT_GTK: + if (subEidPtr->Len > 0) + { + pFtIeInfo->GtkLen = subEidPtr->Len; + NdisMoveMemory(pFtIeInfo->GtkSubIE, &subEidPtr->Oct[0], subEidPtr->Len); + } + break; + + default: + break; + } + + ptr += (subEidPtr->Len + 2); + RemainLen -= (subEidPtr->Len + 2); + + /* avoid infinite loop. */ + if (subEidPtr->Len == 0) + break; + } +} + +#ifdef CONFIG_STA_SUPPORT +VOID FT_FTIeParse( + IN UINT8 FtIeLen, + IN PFT_FTIE pFtIe, + OUT PUCHAR pR1KH_Id, + OUT UCHAR *GTKLen, + OUT PUCHAR pGTK, + OUT UCHAR *R0KH_IdLen, + OUT PUCHAR pR0KH_Id) +{ + UCHAR *ptr; + UINT8 RemainLen; + PFT_OPTION_FIELD subEidPtr; + + *GTKLen = 0; + *R0KH_IdLen = 0; + + ptr = (PUCHAR)&pFtIe->Option[0]; + RemainLen = FtIeLen - sizeof(FT_FTIE); + DBGPRINT(RT_DEBUG_TRACE, ("FT_TEMP- FtIeParse ( FtIeLen = %d )\n", FtIeLen)); + DBGPRINT(RT_DEBUG_TRACE, ("FT_TEMP- FtIeParse ( Len that doesn't include subelement = %d )\n", RemainLen)); + + while (RemainLen > 0) + { + subEidPtr = (PFT_OPTION_FIELD)ptr; + + if (subEidPtr->SubElementId == FT_R1KH_ID) + { + RTMPMoveMemory(pR1KH_Id, subEidPtr->Oct, subEidPtr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("%s : R1KHID length(%d)\n", __FUNCTION__, subEidPtr->Len)); + } + else if (subEidPtr->SubElementId == FT_GTK) + { + *GTKLen = subEidPtr->Len; + DBGPRINT(RT_DEBUG_TRACE, ("FT_TEMP- FtIeParse ( *GTKLen = %d )\n", *GTKLen)); + if ((*GTKLen >= 15) && (*GTKLen <= 64)) + { + RTMPMoveMemory(pGTK, subEidPtr->Oct, subEidPtr->Len); + } + else + { + *GTKLen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("FT- FtIeParse ( Invalid GTKLen = %d)\n", *GTKLen)); + } + + } + else if (subEidPtr->SubElementId == FT_R0KH_ID) + { + *R0KH_IdLen = subEidPtr->Len; + DBGPRINT(RT_DEBUG_TRACE, ("FT_TEMP- FtIeParse ( *R0KH_IdLen = %d )\n", *R0KH_IdLen)); + if ((*R0KH_IdLen >= 1) && (*R0KH_IdLen <= 48)) + { + RTMPMoveMemory(pR0KH_Id, subEidPtr->Oct, subEidPtr->Len); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("FT- FtIeParse ( Invalid R0KH_IdLen = %d )\n",*R0KH_IdLen)); + *R0KH_IdLen = 0; + } + + } + + ptr += (subEidPtr->Len + 2); + RemainLen -= (subEidPtr->Len + 2); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s done\n", __FUNCTION__)); + +} + + +/* + ========================================================================== + Description: + + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +BOOLEAN FT_CheckForRoaming( + IN PRTMP_ADAPTER pAd) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + DBGPRINT(RT_DEBUG_TRACE, ("==> FT_CheckForRoaming\n")); + /* put all roaming candidates into RoamTab, and sort in RSSI order */ + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if (pBss->bHasMDIE == FALSE) + continue; /* skip legacy AP */ + + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + { + continue; /* skip current AP */ + } + if (!FT_MDID_EQU(pBss->FT_MDIE.MdId, pAd->StaCfg.Dot11RCommInfo.MdIeInfo.MdId)) + { + continue; /* skip different MDID */ + } + if ((pBss->Rssi <= -85) && (pBss->Channel == pAd->CommonCfg.Channel)) + { + continue; /* skip RSSI too weak at the same channel */ + } + if ((pBss->Channel != pAd->CommonCfg.Channel) && + (pBss->FT_MDIE.FtCapPlc.field.FtOverDs == FALSE)) + { + continue; /* skip AP in different channel without supporting FtOverDs */ + } + + if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) + { + continue; /* skip AP without better RSSI */ + } + + if ((pBss->AuthMode != pAd->StaCfg.AuthMode) || + (pBss->WepStatus != pAd->StaCfg.WepStatus)) + { + continue; /* skip different Security Setting */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); + /* AP passing all above rules is put into roaming candidate table */ + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== FT_CheckForRoaming (BssNr=%d)\n", pRoamTab->BssNr)); + if (pRoamTab->BssNr > 0) + { + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN FT_GetMDIE( + IN PNDIS_802_11_VARIABLE_IEs pVIE, + IN USHORT LengthVIE, + OUT FT_MDIE_INFO *pMdIeInfo) +{ + PEID_STRUCT pEid; + USHORT Length = 0; + + pEid = (PEID_STRUCT) pVIE; + pMdIeInfo->Len = 0; + while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) + { + switch(pEid->Eid) + { + case IE_FT_MDIE: + if (pEid->Len == sizeof(FT_MDIE)) + { + NdisMoveMemory(&pMdIeInfo->MdId[0], &pEid->Octet[0], FT_MDID_LEN); + pMdIeInfo->FtCapPlc.word = pEid->Octet[FT_MDID_LEN]; + pMdIeInfo->Len = pEid->Len; + } + return TRUE; + } + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + return FALSE; +} + + +BOOLEAN FT_ExtractGTKSubIe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_FTIE_INFO pFtInfo) +{ + PFT_GTK_KEY_INFO pKeyInfo; + UCHAR gtk_len; + UINT unwrap_len; + PUINT8 pData; + UINT8 data_offset = 0; + UINT8 key_p[64]; + + if (pFtInfo->GtkLen < 11) + { + DBGPRINT_ERR(("%s : The length is invalid\n", __FUNCTION__)); + return FALSE; + } + + pData = pFtInfo->GtkSubIE; + + /* Extract the Key Info field */ + pKeyInfo = (PFT_GTK_KEY_INFO)pData; + pKeyInfo->word = cpu2le16(pKeyInfo->word); + pAd->StaCfg.DefaultKeyId = pKeyInfo->field.KeyId; + data_offset += sizeof(FT_GTK_KEY_INFO); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : key idx(%d) \n", __FUNCTION__, pAd->StaCfg.DefaultKeyId)); + + /* Extract the Key Length field */ + gtk_len = *(pData + data_offset); + data_offset += 1; + + /* Extract the RSC field */ + data_offset += 8; + + /* Decrypt the Key field by AES Key UNWRAP */ + AES_Key_Unwrap(pData + data_offset, pFtInfo->GtkLen - data_offset, + &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + key_p, &unwrap_len); + + /* Compare the GTK length */ + if (unwrap_len != gtk_len) + { + DBGPRINT_ERR(("%s : The GTK length is unmatched\n", __FUNCTION__)); + return FALSE; + } + + /* set key material, TxMic and RxMic */ + NdisZeroMemory(pAd->StaCfg.GTK, MAX_LEN_GTK); + NdisMoveMemory(pAd->StaCfg.GTK, key_p, gtk_len); + + return TRUE; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_ConstructAuthReqInRsn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + UINT8 FtIeLen = 0; + FT_MIC_CTR_FIELD FtMicCtr; + UINT8 ft_mic[16]; + UINT8 anonce[32]; + + /* Insert RSNIE[PMKR0Name] */ + RTMPInsertRSNIE(pFrameBuf + (*pFrameLen), + pFrameLen, + pAd->StaCfg.RSN_IE, + pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.Dot11RCommInfo.PMKR0Name, + LEN_PMK_NAME); + + /* Insert FTIE[SNonce, R0KH-ID] + R0KH-ID: Optional parameter - Sub-EID(1 byte)+Len(1 byte)+Data(variable bytes) */ + FtIeLen = sizeof(FT_FTIE) + 2 + pAd->StaCfg.Dot11RCommInfo.R0khIdLen; + FtMicCtr.word = 0; + GenRandom(pAd, pAd->CurrentAddress, pAd->MlmeAux.FtIeInfo.SNonce); + NdisZeroMemory(ft_mic, 16); + NdisZeroMemory(anonce, 32); + + FT_InsertFTIE(pAd, + pFrameBuf + (*pFrameLen), + pFrameLen, + FtIeLen, + FtMicCtr, + ft_mic, + anonce, + &pAd->MlmeAux.FtIeInfo.SNonce[0]); + + FT_FTIE_InsertKhIdSubIE(pAd, + pFrameBuf + (*pFrameLen), + pFrameLen, + FT_R0KH_ID, + &pAd->StaCfg.Dot11RCommInfo.R0khId[0], + pAd->StaCfg.Dot11RCommInfo.R0khIdLen); + + +} + +#endif /* CONFIG_STA_SUPPORT */ + +/* + ======================================================================== + + Routine Description: + It is used to derive the first level FT Key Hierarchy key, PMK-R0, + and its identifier PMKR0Name. + (IEEE 802.11r/D9.0, 8.5.1.5.3) + + Arguments: + + Return Value: + + Note: + R0-Key-Data = + KDF-384(XXKey, "FT-R0", + SSIDlength || SSID || MDID || + R0KHlength || R0KH-ID || S0KH-ID) + PMK-R0 = L(R0-Key-Data, 0, 256) + PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) + + PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)) + + ======================================================================== +*/ +VOID FT_DerivePMKR0( + IN PUINT8 xxkey, + IN INT xxkey_len, + IN PUINT8 ssid, + IN INT ssid_len, + IN PUINT8 mdid, + IN PUINT8 r0khid, + IN INT r0khid_len, + IN PUINT8 s0khid, + OUT PUINT8 pmkr0, + OUT PUINT8 pmkr0_name) +{ + const char label_name[] = "FT-R0N"; + UCHAR R0KeyData[96]; + UCHAR PmkR0NameSalt[20]; + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + + /* =========================== */ + /* PMK-R0 derivation */ + /* =========================== */ + + /* construct the concatenated context for PMK-R0 */ + /* SSIDlength(1 byte) */ + /* SSID(0~32 bytes) */ + /* MDID(2 bytes) */ + /* R0KHlength(1 byte) */ + /* R0KH-ID(5~48 bytes) */ + /* S0KH-ID(6 bytes) */ + + hex_dump("xxkey", (PUCHAR)xxkey, xxkey_len); + hex_dump("label", (PUCHAR)label_name, sizeof(label_name)); + hex_dump("ssid", (PUCHAR)ssid, ssid_len); + hex_dump("mdis", (PUCHAR)mdid, 2); + hex_dump("r0khid", (PUCHAR)r0khid, r0khid_len); + hex_dump("s0khid", (PUCHAR)s0khid, MAC_ADDR_LEN); + + /* Initial the related context */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the SSIDlength with a single octet */ + context[0] = ssid_len; + c_len += 1; + + /* concatenate the SSID with its length */ + NdisMoveMemory(&context[c_len], ssid, ssid_len); + c_len += ssid_len; + + /* concatenate the MDID with 2-octets */ + NdisMoveMemory(&context[c_len], mdid, 2); + c_len += 2; + + /* concatenate the R0KHlength with a single octet */ + context[c_len] = r0khid_len; + c_len += 1; + + /* concatenate the R0KH-ID with its length */ + NdisMoveMemory(&context[c_len], r0khid, r0khid_len); + c_len += r0khid_len; + + /* concatenate the S0KH-ID with its length */ + NdisMoveMemory(&context[c_len], s0khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Calculate a 48-bytes key material through FT-KDF */ + KDF(xxkey, xxkey_len, (PUINT8)"FT-R0", 5, context, c_len, R0KeyData, 48); + + /* PMK-R0 key shall be computed as the first 256 bits (bits 0-255) */ + /* of the R0-Key-Data. The latter 128 bits of R0-Key-Data shall */ + /* be used as the PMK-R0Name-Salt to generate the PMKR0Name. */ + NdisMoveMemory(pmkr0, R0KeyData, LEN_PMK); + NdisMoveMemory(PmkR0NameSalt, &R0KeyData[32], LEN_PMK_NAME); + + /* =============================== */ + /* PMK-R0-Name derivation */ + /* =============================== */ + + /* Initial the related parameter for PMK-R0-Name derivation */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the label with its length */ + NdisMoveMemory(context, label_name, strlen(label_name)); + c_len += strlen(label_name); + + /* concatenate the PMK-R0Name-Salt with its length */ + NdisMoveMemory(&context[c_len], PmkR0NameSalt, LEN_PMK_NAME); + c_len += LEN_PMK_NAME; + + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(pmkr0_name, temp_result, LEN_PMK_NAME); + + hex_dump("PMK-R0", (UCHAR *)pmkr0, LEN_PMK); + hex_dump("PMK-R0-Name", (UCHAR *)pmkr0_name, LEN_PMK_NAME); + +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the second level FT Key Hierarchy key + identifier, PMK-R1-NAME. + (IEEE 802.11r/D9.0, 8.5.1.5.4) + + Arguments: + + Return Value: + + Note: + PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || R1KH-ID || S1KH-ID)) + + ======================================================================== +*/ +VOID FT_DerivePMKR1Name( + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1_name) +{ + const char label_name[] = "FT-R1N"; + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len = 0; + + /* =============================== */ + /* PMK-R1-Name derivation */ + /* =============================== */ + + /* Initial the related parameter for PMK-R1-Name derivation */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the label with its length */ + NdisMoveMemory(context, label_name, strlen(label_name)); + c_len += strlen(label_name); + + /* concatenate the PMK-R1-Name with 16-octets */ + NdisMoveMemory(&context[c_len], pmkr0_name, LEN_PMK_NAME); + c_len += LEN_PMK_NAME; + + /* concatenate the R1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], r1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the S1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], s1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* derive PMK-R1-Name */ + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(pmkr1_name, temp_result, LEN_PMK_NAME); + + hex_dump("PMK-R1-Name", (UCHAR *)pmkr1_name, LEN_PMK_NAME); + +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the second level FT Key Hierarchy key, PMK-R1, + and its identifier PMKR1Name. + (IEEE 802.11r/D9.0, 8.5.1.5.4) + + Arguments: + + Return Value: + + Note: + PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) + PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || R1KH-ID || S1KH-ID)) + + ======================================================================== +*/ +VOID FT_DerivePMKR1( + IN PUINT8 pmkr0, + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1, + OUT PUINT8 pmkr1_name) +{ + /*const char label_name[] = "FT-R1N"; */ + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + + /* =========================== */ + /* PMK-R1 derivation */ + /* =========================== */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s:\n", __FUNCTION__)); + hex_dump("pmkr0", pmkr0, 32); + hex_dump("pmkr0_name", pmkr0_name, LEN_PMK_NAME); + hex_dump("r1khid", r1khid, MAC_ADDR_LEN); + hex_dump("s1khid", s1khid, MAC_ADDR_LEN); + hex_dump("pmkr1", pmkr1, 32); + hex_dump("pmkr1_name", pmkr1_name, 16); + + /* construct the concatenated context for PMK-R1 */ + /* R1KH-ID(6 bytes) */ + /* S1KH-ID(6 bytes) */ + + /* Initial the related parameter */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the R1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], r1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the S1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], s1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Calculate a 32-bytes key material through FT-KDF */ + KDF(pmkr0, LEN_PMK, (PUINT8)"FT-R1", 5, context, c_len, temp_result, 32); + NdisMoveMemory(pmkr1, temp_result, LEN_PMK); + + /* =============================== */ + /* PMK-R1-Name derivation */ + /* =============================== */ + FT_DerivePMKR1Name(pmkr0_name, + r1khid, + s1khid, + pmkr1_name); + + hex_dump("PMK-R1", (UCHAR *)pmkr1, LEN_PMK); + hex_dump("PMK-R1-Name", (UCHAR *)pmkr1_name, LEN_PMK_NAME); + +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the third level FT Key Hierarchy key, PTK, + and its identifier PTKName. + (IEEE 802.11r/D9.0, 8.5.1.5.4) + + Arguments: + + Return Value: + + Note: + PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || BSSID || STA-ADDR) + PTKName = + Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || ANonce || BSSID || + STA-ADDR)) + + ======================================================================== +*/ +VOID FT_DerivePTK( + IN PUINT8 pmkr1, + IN PUINT8 pmkr1_name, + IN PUINT8 a_nonce, + IN PUINT8 s_nonce, + IN PUINT8 bssid, + IN PUINT8 sta_mac, + IN UINT key_len, + OUT PUINT8 ptk, + OUT PUINT8 ptk_name) +{ + const char label_name[] = "FT-PTKN"; + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + + /* =============================== */ + /* PTK derivation */ + /* =============================== */ + + /* construct the concatenated context for PTK */ + /* SNonce (32 bytes) */ + /* ANonce (32 bytes) */ + /* BSSID (6 bytes) */ + /* STA-ADDR (6-bytes) */ + + /* Initial the related parameter */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the SNonce with 32-octets */ + NdisMoveMemory(&context[c_len], s_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the ANonce with 32-octets */ + NdisMoveMemory(&context[c_len], a_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the BSSID with 6-octets */ + NdisMoveMemory(&context[c_len], bssid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the STA-ADDR with 6-octets */ + NdisMoveMemory(&context[c_len], sta_mac, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Calculate a key material through FT-KDF */ + KDF(pmkr1, + LEN_PMK, + (PUINT8)"FT-PTK", + 6, + context, + c_len, + temp_result, + key_len); + NdisMoveMemory(ptk, temp_result, key_len); + + /* =============================== */ + /* PTK-Name derivation */ + /* =============================== */ + + /* Initial the related parameter for PTK-Name derivation */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the PMK-R1-Name with 16-octets */ + NdisMoveMemory(&context[c_len], pmkr1_name, LEN_PMK_NAME); + c_len += LEN_PMK_NAME; + + /* concatenate the label with its length */ + NdisMoveMemory(&context[c_len], label_name, strlen(label_name)); + c_len += strlen(label_name); + + /* concatenate the SNonce with 32-octets */ + NdisMoveMemory(&context[c_len], s_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the ANonce with 32-octets */ + NdisMoveMemory(&context[c_len], a_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the BSSID with 6-octets */ + NdisMoveMemory(&context[c_len], bssid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the STA-ADDR with 6-octets */ + NdisMoveMemory(&context[c_len], sta_mac, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Derive PTKName */ + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(ptk_name, temp_result, LEN_PMK_NAME); + + /*hex_dump("ANonce", (UCHAR *)a_nonce, LEN_NONCE); */ + /*hex_dump("SNonce", (UCHAR *)s_nonce, LEN_NONCE); */ + + hex_dump("PTK", (UCHAR *)ptk, key_len); + hex_dump("PTK-Name", (UCHAR *)ptk_name, LEN_PMK_NAME); + +} + + +/* + ======================================================================== + + Routine Description: + Calcaulate FT MIC. It is used during Fast BSS transition. + + Arguments: + + Return Value: + + Note: + It's defined in IEEE 802.11r D9.0 11A.8.4/8.5 + The MIC shall be calculated using the KCK and the AES-128-CMAC + algorithm. The output of the AES-128-CMAC shall be 128 bits. + + The MIC shall be calculated on the concatenation, in the + following order, of: + - non-AP STA MAC address (6 octets) + - Target AP MAC address (6 octets) + - Transaction sequence number (1 octet) + - Contents of the RSN information element. + - Contents of the MDIE. + - Contents of the FTIE, with the MIC field of the FTIE set to 0. + - Contents of the RIC-Request (if present) + + ======================================================================== +*/ +VOID FT_CalculateMIC( + IN PUINT8 sta_addr, + IN PUINT8 ap_addr, + IN PUINT8 kck, + IN UINT8 seq, + IN PUINT8 rsnie, + IN UINT8 rsnie_len, + IN PUINT8 mdie, + IN UINT8 mdie_len, + IN PUINT8 ftie, + IN UINT8 ftie_len, + IN PUINT8 ric, + IN UINT8 ric_len, + OUT PUINT8 mic) +{ + UCHAR *OutBuffer; + ULONG FrameLen = 0; + ULONG TmpLen = 0; + UINT mlen = AES_KEY128_LENGTH; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + NdisZeroMemory(mic, sizeof(mic)); + + /* allocate memory for MIC calculation */ + os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512); + if (OutBuffer == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!FT_CalculateMIC: no memory!!!\n")); + return; + } + + /* make a header frame for calculating MIC. */ + MakeOutgoingFrame(OutBuffer, &TmpLen, + MAC_ADDR_LEN, sta_addr, + MAC_ADDR_LEN, ap_addr, + 1, &seq, + END_OF_ARGS); + FrameLen += TmpLen; + + /* concatenate RSNIE */ + if (rsnie_len != 0) + { + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + rsnie_len, rsnie, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* concatenate MDIE */ + if (mdie_len != 0) + { + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + mdie_len, mdie, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* concatenate FTIE */ + if (ftie != 0) + { + /* The MIC field of the FTIE set to 0 */ + NdisZeroMemory(ftie + 4, 16); + + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + ftie_len, ftie, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* concatenate RIC-Request/Response if present */ + if (ric != 0) + { + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + ric_len, ric, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Calculate MIC */ + AES_CMAC(OutBuffer, FrameLen, kck, LEN_PTK_KCK, mic, &mlen); + + os_free_mem(NULL, OutBuffer); +} + +#ifdef CONFIG_AP_SUPPORT +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +void FT_rtmp_read_parameters_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING pBuffer) +{ + INT Loop; + + /* FtSupport */ + if(RTMPGetKeyParameter("FtSupport", tmpbuf, 32, pBuffer, TRUE)) + { + PSTRING macptr; + for (Loop = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), Loop++) + { + if (Loop >= MAX_MBSSID_NUM(pAd)) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.Dot11rFtEnable = TRUE; + else /*Disable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.Dot11rFtEnable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Dot11rFtEnable=%d\n", + Loop, pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + } + + /* FtRic */ + if(RTMPGetKeyParameter("FtRic", tmpbuf, 32, pBuffer, TRUE)) + { + PSTRING macptr; + for (Loop = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), Loop++) + { + if (Loop >= MAX_MBSSID_NUM(pAd)) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.RsrReqCap = TRUE; + else /*Disable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.RsrReqCap = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Dot11rFtRic=%d\n", + Loop, pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.RsrReqCap)); + } + } + + /* FtOtd */ + if(RTMPGetKeyParameter("FtOtd", tmpbuf, 32, pBuffer, TRUE)) + { + PSTRING macptr; + for (Loop = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), Loop++) + { + if (Loop >= MAX_MBSSID_NUM(pAd)) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.FtOverDs = TRUE; + else /*Disable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.FtOverDs = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Dot11rFtOtd=%d\n", + Loop, pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.FtOverDs)); + } + } + + for (Loop = 0; Loop < MAX_MBSSID_NUM(pAd); Loop++) + { + STRING tok_str[16]; + + /* + FtMdId: + FtMdId shall be a value of two octets. + */ + NdisZeroMemory(tok_str, sizeof(tok_str)); + snprintf(tok_str, sizeof(tok_str), "FtMdId%d", Loop + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, FT_MDID_LEN + 1, pBuffer, FALSE)) + { + if (strlen(tmpbuf) == FT_MDID_LEN) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[Loop].FtCfg.FtMdId, tmpbuf, FT_MDID_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("%s::FtMdid(%d)=%c%c\n", __FUNCTION__, Loop, + pAd->ApCfg.MBSSID[Loop].FtCfg.FtMdId[0], + pAd->ApCfg.MBSSID[Loop].FtCfg.FtMdId[1])); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Invalid MdId=%s\n", __FUNCTION__,tmpbuf)); + } + } + + /* + FtR0khId: + FtR0khId shall be in string of 1 ~ 48 octets. + */ + NdisZeroMemory(tok_str, sizeof(tok_str)); + snprintf(tok_str, sizeof(tok_str), "FtR0khId%d", Loop + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, FT_ROKH_ID_LEN + 1, pBuffer, FALSE)) + { + if (strlen(tmpbuf) <= FT_ROKH_ID_LEN) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[Loop].FtCfg.FtR0khId, tmpbuf, strlen(tmpbuf)); + pAd->ApCfg.MBSSID[Loop].FtCfg.FtR0khId[strlen(tmpbuf)] = '\0'; + DBGPRINT(RT_DEBUG_TRACE, ("%s::FtR0khId(%d)=%s\n", __FUNCTION__, Loop, + pAd->ApCfg.MBSSID[Loop].FtCfg.FtR0khId)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Invalid R0khId(%d)=%s Len=%d\n", + __FUNCTION__, Loop, tmpbuf, strlen(tmpbuf))); + } + } + } +} + +INT Set_FT_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + ULONG Value; + + Value = (UINT) simple_strtol(arg, 0, 10); + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + pFtCfg->FtCapFlag.Dot11rFtEnable = (Value == 0 ? FALSE : TRUE); + + return TRUE; +} + +INT Set_FT_Mdid( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + NdisMoveMemory(pFtCfg->FtMdId, arg, FT_MDID_LEN); + + return TRUE; +} + +INT Set_FT_R0khid( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + if (strlen(arg) > FT_ROKH_ID_LEN) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid R0KHID Length (%d).\n", + __FUNCTION__, strlen(arg))); + DBGPRINT(RT_DEBUG_ERROR, ("%s: The length shall be in range from 1 to 48 octects.\n", + __FUNCTION__)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + NdisMoveMemory(pFtCfg->FtR0khId, arg, strlen(arg)); + pFtCfg->FtR0khIdLen = strlen(arg); + + return TRUE; +} + +INT Set_FT_RIC( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + ULONG Value; + + Value = (UINT) simple_strtol(arg, 0, 10); + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + pFtCfg->FtCapFlag.RsrReqCap = (Value == 0 ? FALSE : TRUE); + + return TRUE; +} + +INT Set_FT_OTD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + ULONG Value; + + Value = (UINT) simple_strtol(arg, 0, 10); + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + pFtCfg->FtCapFlag.FtOverDs = (Value == 0 ? FALSE : TRUE); + + return TRUE; +} + +INT Show_FTConfig_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + + if (apidx >= pAd->ApCfg.BssidNum) + return -1; + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + + DBGPRINT(RT_DEBUG_OFF, ("MDID=%c%c\n", pFtCfg->FtMdId[0], pFtCfg->FtMdId[1])); + DBGPRINT(RT_DEBUG_OFF, ("R0KHID=%s, Len=%d\n", pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen)); + DBGPRINT(RT_DEBUG_OFF, ("FT Enable=%d\n", pFtCfg->FtCapFlag.Dot11rFtEnable)); + DBGPRINT(RT_DEBUG_OFF, ("FT RIC=%d\n", pFtCfg->FtCapFlag.RsrReqCap)); + DBGPRINT(RT_DEBUG_OFF, ("FT OTD=%d\n", pFtCfg->FtCapFlag.FtOverDs)); + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_iocl.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_iocl.c new file mode 100644 index 000000000..4d6887658 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_iocl.c @@ -0,0 +1,1448 @@ +/**************************************************************************** + * 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 IOCTL function body. + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + + + +#include "rt_config.h" + +#define TYPE_FUNC +#define FT_FUNC_SIMULATION + +#ifdef FT_FUNC_SIMULATION +#endif /* FT_FUNC_SIMULATION */ + +/* ----- Private Variable ----- */ +#ifdef FT_FUNC_SIMULATION +static UCHAR gFT_MAC_STA[ETH_ALEN] = { 0x00, 0x0e, 0x2e, 0x82, 0xe7, 0x6d }; +UCHAR gFT_MAC_OldAP[ETH_ALEN] = { 0x00, 0x0e, 0x2e, 0x12, 0x34, 0x56 }; + +#ifdef CONFIG_STA_SUPPORT +#define FT_RIC_SIM_AP_MAX 10 +static FT_RIC_STATUS gFT_RIC_RspStatus[FT_RIC_SIM_AP_MAX]; +static UINT32 gFT_RIC_RspStatusIndex; +#endif /* CONFIG_STA_SUPPORT */ + +#endif /* FT_FUNC_SIMULATION */ + + +/* ----- Extern Function ----- */ +#ifdef CONFIG_AP_SUPPORT +extern BOOLEAN FT_KDP_R0KH_InfoAdd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP); +#endif /* CONFIG_AP_SUPPORT */ + + +/* ----- Private Function ----- */ +#define FT_CMD_INPUT_PARAM_DECLARATION \ + PRTMP_ADAPTER pAd, INT32 Argc, CHAR *pArgv + +#ifdef CONFIG_AP_SUPPORT +#ifndef FT_KDP_FUNC_SOCK_COMM +static VOID FT_KDP_CMD_EventList(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +static VOID FT_KDP_CMD_DbgFlagCtrl(FT_CMD_INPUT_PARAM_DECLARATION); + +#ifdef FT_FUNC_SIMULATION +static VOID FT_KDP_CMD_SimEvtFtAssoc(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_KDP_CMD_SimEvtFtReAssoc(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_KDP_CMD_SimKeyReq(FT_CMD_INPUT_PARAM_DECLARATION); + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +static VOID FT_KDP_CMD_SimR0KH_InfoCreate(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + +static VOID FT_RIC_CMD_SimRscReqHdlTspec(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RIC_CMD_SimRscReqHandle(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RRB_CMD_SimSend(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_11K_CMD_SimInfoReq(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_11K_CMD_SimKeyShow(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_FUNC_SIMULATION */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef FT_FUNC_SIMULATION +static VOID FT_RIC_CMD_StatusDisplay(FT_RIC_STATUS *pRspStatus); +static VOID FT_RIC_CMD_SimRscReqStart(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RIC_CMD_SimRscReq(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RIC_CMD_SimRscReqEnd(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RIC_CMD_SimRscReqRspList(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_FUNC_SIMULATION */ +#endif /* CONFIG_STA_SUPPORT */ + +static UINT32 FT_CMD_UtilHexGet(CHAR **ppArgv); +static UINT32 FT_CMD_UtilNumGet(CHAR **ppArgv); +static VOID FT_CMD_UtilMacGet(CHAR **ppArgv, UCHAR *pDevMac); + + + +#ifdef CONFIG_AP_SUPPORT +void test11r(PRTMP_ADAPTER pAd) +{ + FT_KDP_CMD_SimEvtFtAssoc(pAd, 0, NULL); +} +#endif /* CONFIG_AP_SUPPORT */ + +/* +======================================================================== +Routine Description: + Get argument number value. + +Arguments: + **ppArgv - input parameters + +Return Value: + decimal number + +Note: +======================================================================== +*/ +static UINT32 TYPE_FUNC FT_CMD_UtilHexGet( + IN CHAR **ppArgv) +{ + CHAR buf[3], *pNum; + UINT32 ID; + UCHAR Value; + + + pNum = (*ppArgv); + + buf[0] = 0x30; + buf[1] = 0x30; + buf[2] = 0; + + for(ID=0; ID= 2) + memcpy(buf, (*ppArgv), 2); + else + buf[1] = (**ppArgv); + /* End of if */ + + (*ppArgv) += ID; + if ((**ppArgv) == '_') + (*ppArgv) ++; /* skip _ */ + /* End of if */ + + FT_ARG_ATOH(buf, &Value); + return (UINT32)Value; +} /* End of FT_CMD_UtilHexGet */ + + +/* +======================================================================== +Routine Description: + Get argument number value. + +Arguments: + *pArgv - input parameters + +Return Value: + decimal number + +Note: +======================================================================== +*/ +static UINT32 TYPE_FUNC FT_CMD_UtilNumGet( + IN CHAR **ppArgv) +{ + CHAR buf[20], *pNum; + UINT32 ID; + + + pNum = (*ppArgv); + + for(ID=0; IDApCfg.FtTab.FT_KdpLock)); + + pInfo = FT_KDP_CB->R0KH_InfoHead; + IdInfo = 1; + + while(pInfo != NULL) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n%03d. R0KHID = 0x", IdInfo)); + + for(IdArray=0; IdArrayR0KHID); IdArray++) + { + if (IdArray == (sizeof(pInfo->R0KHID)>>1)) + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n ")); + /* End of if */ + + DBGPRINT_RAW(RT_DEBUG_OFF, (" %02x", pInfo->R0KHID[IdArray])); + } /* End of for */ + + DBGPRINT_RAW(RT_DEBUG_OFF, + ("\n%03d. MAC = 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + IdInfo, pInfo->MAC[0], pInfo->MAC[1], pInfo->MAC[2], + pInfo->MAC[3], pInfo->MAC[4], pInfo->MAC[5])); + + DBGPRINT_RAW(RT_DEBUG_OFF, + ("%03d. IP = %d.%d.%d.%d\n", IdInfo, + (pInfo->IP & 0x000000FF) >> 0, + (pInfo->IP & 0x0000FF00) >> 8, + (pInfo->IP & 0x00FF0000) >> 16, + (pInfo->IP & 0xFF000000) >> 24)); + + pInfo = pInfo->pNext; + IdInfo ++; + } /* End of while */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n")); + return TRUE; +} /* End of FT_KDP_CMD_R0KH_InfoShow */ +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + +#ifndef FT_KDP_FUNC_SOCK_COMM +/* +======================================================================== +Routine Description: + List all queued events. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_EventList( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_SIGNAL *pFtKdp; + ULONG SplFlags; + + + pFtKdp = (FT_KDP_SIGNAL *)FT_KDP_CB->EventList.pHead; + if (pFtKdp == NULL) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("ft_kdp> No any event!\n")); + return; + } /* End of if */ + + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nEvent\n")); + DBGPRINT_RAW(RT_DEBUG_OFF, ("----------------------------------------------------\n")); + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + while(pFtKdp != NULL) + { + switch(pFtKdp->Sig) + { + case FT_KDP_SIG_KEY_TIMEOUT: + DBGPRINT_RAW(RT_DEBUG_OFF, ("KEY TIMEOUT\n")); + break; + + case FT_KDP_SIG_KEY_REQ: + DBGPRINT_RAW(RT_DEBUG_OFF, ("KEY REQUEST\n")); + break; + + case FT_KDP_SIG_FT_ASSOCIATION: + DBGPRINT_RAW(RT_DEBUG_OFF, ("STATION FT ASSOCIATION\n")); + break; + + case FT_KDP_SIG_TERMINATE: + DBGPRINT_RAW(RT_DEBUG_OFF, ("TERMINATE\n")); + break; + + default: + DBGPRINT_RAW(RT_DEBUG_OFF, ("UNKNOWN\n")); + break; + } /* End of switch */ + + pFtKdp = (FT_KDP_SIGNAL *)pFtKdp->pNext; + } /* End of while */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n")); +} /* End of FT_KDP_CMD_EventList */ +#endif /* FT_KDP_FUNC_SOCK_COMM */ + + +/* +======================================================================== +Routine Description: + Change the debug flag of IAPP daemon. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID FT_KDP_CMD_DbgFlagCtrl( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + INT32 DebugLevel; + + + DebugLevel = FT_CMD_UtilNumGet(&pArgv); + + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KSP_SIG_DEBUG_TRACE, + &DebugLevel, sizeof(DebugLevel), NULL); +} /* End of FT_KDP_CMD_DbgFlagCtrl */ + + +#ifdef FT_FUNC_SIMULATION +/* +======================================================================== +Routine Description: + List all queued events. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimEvtFtAssoc( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_ASSOC EvtAssoc; + + + /* fill the station information */ + EvtAssoc.SeqNum = 0x1234; + NdisMoveMemory(EvtAssoc.MacAddr, gFT_MAC_STA, MAC_ADDR_LEN); + + /* inform other APs a station associated to us */ + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_FT_ASSOCIATION, + &EvtAssoc, sizeof(FT_KDP_EVT_ASSOC), NULL); +} /* End of FT_KDP_CMD_SimEvtFtAssoc */ + + +/* +======================================================================== +Routine Description: + List all queued events. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimEvtFtReAssoc( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_REASSOC EvtReAssoc; + + + /* fill the station information */ + EvtReAssoc.SeqNum = 0x1234; + NdisMoveMemory(EvtReAssoc.MacAddr, gFT_MAC_STA, MAC_ADDR_LEN); + NdisMoveMemory(EvtReAssoc.OldApMacAddr, gFT_MAC_OldAP, MAC_ADDR_LEN); + + /* inform other APs a station associated to us */ + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_FT_REASSOCIATION, + &EvtReAssoc, sizeof(FT_KDP_EVT_REASSOC), NULL); +} /* End of FT_KDP_CMD_SimEvtFtReAssoc */ + + +/* +======================================================================== +Routine Description: + Request PMK-R1 Key from R0KH. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [R0KHID 1st byte (HEX)] [R1KHID 1st byte (HEX)] +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimKeyReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_KEY_ELM EvtKeyReq, *pEvtKeyReq; + UCHAR R0KHID_Byte, R1KHID_Byte; + + + /* init */ + memset(&EvtKeyReq, 0, sizeof(FT_KDP_EVT_KEY_ELM)); + pEvtKeyReq = &EvtKeyReq; + + /* fill request content */ + pEvtKeyReq->ElmId = FT_KDP_ELM_ID_PRI; + pEvtKeyReq->ElmLen = FT_KDP_ELM_PRI_LEN; + pEvtKeyReq->OUI[0] = FT_KDP_ELM_PRI_OUI_0; + pEvtKeyReq->OUI[1] = FT_KDP_ELM_PRI_OUI_1; + pEvtKeyReq->OUI[2] = FT_KDP_ELM_PRI_OUI_2; + + memcpy(pEvtKeyReq->MacAddr, gFT_MAC_STA, ETH_ALEN); + + R0KHID_Byte = FT_CMD_UtilHexGet(&pArgv); + memset(pEvtKeyReq->KeyInfo.R0KHID, R0KHID_Byte, FT_KDP_R0KHID_MAX_SIZE); + + R1KHID_Byte = FT_CMD_UtilHexGet(&pArgv); + memset(pEvtKeyReq->KeyInfo.R1KHID, R1KHID_Byte, FT_KDP_R1KHID_MAX_SIZE); + + memcpy(pEvtKeyReq->KeyInfo.S1KHID, gFT_MAC_STA, FT_KDP_S1KHID_MAX_SIZE); + memset(pEvtKeyReq->KeyInfo.RSV, 0x00, sizeof(pEvtKeyReq->KeyInfo.RSV)); + + /* request PMK-R1 Key (our R1KH vs. the station) from the R0KH */ + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_KEY_REQ, + pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), NULL); +} /* End of FT_KDP_CMD_SimKeyReq */ + + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +/* +======================================================================== +Routine Description: + Create a R0KH information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [R0KHID 1st byte (HEX)] [IP1] [IP2] [IP3] [IP4] +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimR0KH_InfoCreate( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + UCHAR R0KHID[FT_KDP_R0KHID_MAX_SIZE]; + UCHAR MAC[ETH_ALEN]; + UCHAR ByteFirst; + UCHAR IP[4]; + + + ByteFirst = FT_CMD_UtilHexGet(&pArgv); + IP[0] = FT_CMD_UtilNumGet(&pArgv); + IP[1] = FT_CMD_UtilNumGet(&pArgv); + IP[2] = FT_CMD_UtilNumGet(&pArgv); + IP[3] = FT_CMD_UtilNumGet(&pArgv); + + memset(R0KHID, ByteFirst, sizeof(R0KHID)); + memset(MAC, ByteFirst, sizeof(MAC)); + MAC[0] = 0x00; + + FT_KDP_R0KH_InfoAdd(pAd, R0KHID, MAC, *(UINT32 *)IP); +} /* End of FT_KDP_CMD_SimR0KH_InfoCreate */ +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + +/* +======================================================================== +Routine Description: + Simulate to make a resource request. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [1-WME] [TID:0~7] [dir:0~3] [access:1~3] [UP:0~7] [ack:0~1] + [nom size:byte] [inact:sec] [mean data rate:bps] [min phy rate:bps] + [surp factor:>=1] [tclas processing:0~1] + 2. dir: 0 - uplink, 1 - dnlink, 2 - bidirectional link, 3 - direct link + access: 1 - EDCA, 2 - HCCA, 3 - EDCA + HCCA + ack: 0 - normal ACK, 1 - no ACK +======================================================================== +*/ +static VOID FT_RIC_CMD_SimRscReqHdlTspec( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ +} /* End of FT_RIC_CMD_SimRscReqHdlTspec */ + + +/* +======================================================================== +Routine Description: + Simulate to handle resource requests. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + Test example: + + iwpriv ra0 set acm=50 + iwpriv ra0 set acm=10_0_0_1_1 + + 1. OK case + iwpriv ra0 set ft=512_1_7_0_1_7_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_6_1_1_6_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_5_0_1_5_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_4_1_1_4_0_500_3000_200000_11000000_10_0 + + 2. Fail case + iwpriv ra0 set ft=512_1_7_0_1_7_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_5_0_1_5_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_6_1_1_6_0_500_3000_11000000_11000000_10_0 + iwpriv ra0 set ft=512_1_4_1_1_4_0_500_3000_11000000_11000000_10_0 + + iwpriv ra0 set ft=510 +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_SimRscReqHandle( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) + { +} /* End of FT_RIC_CMD_SimRscReqHandle */ + + +/* +======================================================================== +Routine Description: + Simulate to send a RRB frame. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [0(REQ)/1(RSP)] [PeerMAC] +======================================================================== +*/ +static VOID TYPE_FUNC FT_RRB_CMD_SimSend( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_ACTION ActionCB, *pActionCB; + UCHAR MacPeer[6]; + + + pActionCB = &ActionCB; + + pActionCB->RequestType = FT_CMD_UtilNumGet(&pArgv); + FT_CMD_UtilMacGet(&pArgv, MacPeer); + + memcpy(pActionCB->MacDa, MacPeer, ETH_ALEN); + memset(pActionCB->MacSa, 0x22, ETH_ALEN); + memset(pActionCB->MacAp, 0x33, ETH_ALEN); + + pActionCB->MacDa[0] = 0x00; + pActionCB->MacSa[0] = 0x00; + pActionCB->MacAp[0] = 0x00; + + FT_KDP_EventInform(pAd, BSS0, FT_KDP_SIG_ACTION, + "testtesttesttesttest", 19, 0, (VOID *)pActionCB); +} /* End of FT_RRB_CMD_SimSend */ + + +/* +======================================================================== +Routine Description: + Simulate to send a 11k neighbor request. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + PeerSSID +======================================================================== +*/ +static VOID TYPE_FUNC FT_11K_CMD_SimInfoReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + if (strlen((PSTRING) pArgv) <= MAX_LEN_OF_SSID) + { + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_AP_INFO_REQ, + pArgv, strlen((PSTRING) pArgv), NULL); + } /* End of if */ +} /* End of FT_11K_CMD_SimInfoReq */ + + +/* +======================================================================== +Routine Description: + Show encryption/decryption key information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_11K_CMD_SimKeyShow( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + hex_dump("Key=", FT_KDP_CB->CryptKey, sizeof(FT_KDP_CB->CryptKey)); +} /* End of FT_11K_CMD_SimInfoReq */ +#endif /* FT_FUNC_SIMULATION */ + + +/* +======================================================================== +Routine Description: + Display a R0KH information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + +======================================================================== +*/ +static VOID TYPE_FUNC FT_R1KH_InfoShow( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + INT i; + INT HashIdx; + PFT_R1HK_ENTRY pEntry; + + RTMP_SEM_LOCK(&pAd->ApCfg.FtTab.FT_R1khEntryTabLock); + for (HashIdx = 0; HashIdx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; HashIdx++) + { + pEntry = (PFT_R1HK_ENTRY)\ + (pAd->ApCfg.FtTab.FT_R1khEntryTab[HashIdx].pHead); + + while (pEntry != NULL) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("StaMac=%02x:%02x:%02x:%02x:%02x:%02x, ", + pEntry->StaMac[0], pEntry->StaMac[1], pEntry->StaMac[2], + pEntry->StaMac[3], pEntry->StaMac[4], pEntry->StaMac[5])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nKeyLifeTime=%d, ", pEntry->KeyLifeTime)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nRassocDeadline=%d\n", + pEntry->RassocDeadline)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("PairwisChipher=")); + for (i=0; i<4; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PairwisChipher[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nAkmSuite=")); + for (i=0; i<4; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->AkmSuite[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nPmkR0Name=")); + for (i=0; i<16; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PmkR0Name[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nPmkR1Key=")); + for (i=0; i<32; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PmkR1Key[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nPmkR1Name=")); + for (i=0; i<16; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PmkR1Name[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n")); + pEntry = pEntry->pNext; + } + } + RTMP_SEM_UNLOCK(&pAd->ApCfg.FtTab.FT_R1khEntryTabLock); +} /* End of FT_R1KH_InfoShow */ + + +static PMAC_TABLE_ENTRY FtEntry = NULL; +static VOID FT_OverDs_SimReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + PUCHAR pOutBuffer = NULL; + ULONG FrameLen; + HEADER_802_11 Hdr; + FT_INFO FtInfoBuf; + NDIS_STATUS NStatus; + + UCHAR StaAddr[MAC_ADDR_LEN] = {0x00,0x0c,0x43,0x00,0x00,0x00}; + UCHAR TargetAddr[MAC_ADDR_LEN] = {0x00,0x0c,0x43,0x28,0x60,0x10}; + + if (FtEntry == NULL) + { + FtEntry = MacTableInsertEntry(pAd, StaAddr, &pAd->ApCfg.MBSSID[0].wdev, 0, OPMODE_AP, TRUE); + FtEntry->Sst = SST_ASSOC; + } + + NdisZeroMemory(&FtInfoBuf, sizeof(FT_INFO)); + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + return; + } + + /* Make 802.11 header. */ + ActHeaderInit(pAd, &Hdr, pAd->ApCfg.MBSSID[FtEntry->apidx].wdev.bssid, + FtEntry->Addr, pAd->ApCfg.MBSSID[FtEntry->apidx].wdev.bssid); + + FrameLen = 0; + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + END_OF_ARGS); + + FtInfoBuf.MdIeInfo.Len = 3; + FT_SET_MDID(FtInfoBuf.MdIeInfo.MdId, FT_DEFAULT_MDID); + FtInfoBuf.MdIeInfo.FtCapPlc.field.FtOverDs = 1; + FtInfoBuf.MdIeInfo.FtCapPlc.field.RsrReqCap = 1; + FT_MakeFtActFrame(pAd, pOutBuffer, &FrameLen, + FT_ACTION_BT_REQ, FtEntry->Addr, TargetAddr, 0, + &FtInfoBuf); + + /* enqueue it into FT action state machine. */ + REPORT_MGMT_FRAME_TO_MLME(pAd, FtEntry->Aid, pOutBuffer, \ + FrameLen, 0, 0, 0, 0, OPMODE_AP); + + if (pOutBuffer) + os_free_mem(pAd, pOutBuffer); + +} + +static VOID FT_OverDs_SimConfirm( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#ifdef FT_FUNC_SIMULATION +/* +======================================================================== +Routine Description: + Display the reponse status for a resource request. + +Arguments: + *pRspStatus - the status + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_StatusDisplay(FT_RIC_STATUS *pRspStatus) +{ + DBGPRINT_RAW(RT_DEBUG_OFF, + ("\nAP MAC = %02x:%02x:%02x:%02x:%02x:%02x\n", + pRspStatus->AP_MAC[0], pRspStatus->AP_MAC[1], + pRspStatus->AP_MAC[2], pRspStatus->AP_MAC[3], + pRspStatus->AP_MAC[4], pRspStatus->AP_MAC[5])); + + if (pRspStatus->FlgHasBaResource == TRUE) + { + if (pRspStatus->FlgIsBaAccepted == TRUE) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tBA Resource is accepted.\n")); + } + else + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tBA Resource is not accepted.\n")); + } /* End of if */ + } /* End of if */ + + if (pRspStatus->TspecNumberOfRequested > 0) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tNumber of requested TSPEC: %d\n", + pRspStatus->TspecNumberOfRequested)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tNumber of accepted TSPEC: %d\n", + pRspStatus->TspecNumberOfAccepted)); + + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tTotal requested Time: %d us\n", + pRspStatus->TspecMediumTimeTotalCur)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tTotal accepted Time: %d us\n", + pRspStatus->TspecMediumTimeTotalNew)); + } /* End of if */ + + if (pRspStatus->UnknownRDIE > 0) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("\tNumber of unknown RDIE: %d\n", + pRspStatus->UnknownRDIE)); + } /* End of if */ +} /* End of FT_RIC_CMD_StatusDisplay */ + + +/* +======================================================================== +Routine Description: + Simulate to start our resource request to the target AP. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + Need to build any TSPEC before. + + EX: Build a simulated TSPEC. + + iwpriv ra0 set acm=69_0_0_1_1 + iwpriv ra0 set acm=65_1_7_0_1_7_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set acm=65_1_6_1_1_6_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set acm=65_1_5_0_1_5_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set acm=65_1_4_1_1_4_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set acm=06_1_0 + iwpriv ra0 set ft=506 + iwpriv ra0 set ft=507_00:11:11:11:11:11_1_0_0_1 + iwpriv ra0 set ft=507_00:22:22:22:22:22_0_0_1_1 + iwpriv ra0 set ft=507_00:33:33:33:33:33_1_1_1_0 + iwpriv ra0 set ft=508_00:22:22:22:22:22 + iwpriv ra0 set ft=509 +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_SimRscReqStart( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_RIC_ResourceRequestStart(pAd); + gFT_RIC_RspStatusIndex = 0; +} /* End of FT_RIC_CMD_SimRscReqStart */ + + +/* +======================================================================== +Routine Description: + Simulate to send our resource request to the target AP. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + Command: [AP MAC] [Status for TSPEC 1] [Status for TSPEC 2] + [Status for TSPEC 3] [Status for TSPEC 4] [Status for TSPEC 5] + [Status for TSPEC 6] [Status for TSPEC 7] [Status for TSPEC 8] +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_SimRscReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) + { + FT_ELM_RIC_DATA_INFO *pElmDataInfoRsp; + UCHAR *pFrame, *pFrameRDIE, *pFrameNextRDIE, *pFrameRSC; + UINT32 FilledLen, RdieLen, RscLen, RspLen = 0; + UCHAR MacPeer[6]; + BOOLEAN RspStatus[8]; + UINT32 IdStatus, RDIE_Index; + + + /* sanity check */ + if (gFT_RIC_RspStatusIndex >= FT_RIC_SIM_AP_MAX) + return; + /* End of if */ + + /* get AP mac address */ + FT_CMD_UtilMacGet(&pArgv, MacPeer); + + if (*(UINT32 *)MacPeer == 0) + memcpy(MacPeer, gFT_MAC_OldAP, 6); + /* End of if */ + + memset(RspStatus, 0, sizeof(RspStatus)); + + for(IdStatus=0; IdStatus<(Argc-1); IdStatus++) + RspStatus[IdStatus] = FT_CMD_UtilNumGet(&pArgv); + /* End of for */ + + /* init */ +/* pFrame = kmalloc(1000, GFP_ATOMIC); */ + os_alloc_mem(pAd, (UCHAR **)&pFrame, 1000); + if (pFrame == NULL) + return; + /* End of if */ + memset(pFrame, 0, 1000); + RspLen = 0; + + /* simulate to request */ + FilledLen = FT_RIC_ResourceRequest(pAd, MacPeer, pFrame, 1000); + + /* modify response status */ + if (Argc > 1) + { + RDIE_Index = 0; + RspLen = 0; + pFrameRDIE = pFrame; + + while(FilledLen > 0) + { + /* update RDIE status */ + pElmDataInfoRsp = (FT_ELM_RIC_DATA_INFO *)pFrameRDIE; + pElmDataInfoRsp->StatusCode = RspStatus[RDIE_Index]; + + RdieLen = FT_ELM_HDR_LEN + *(pFrameRDIE+1); + pFrameRSC = pFrameRDIE + RdieLen; + RscLen = FT_ELM_HDR_LEN + *(pFrameRSC+1); + RspLen += RdieLen; + FilledLen -= (RdieLen + RscLen); + + /* update resource element */ + if (pElmDataInfoRsp->StatusCode != 0) + { + /* delete the following resource TSPEC */ + pElmDataInfoRsp->RD_Count = 0; + + pFrameNextRDIE = pFrameRSC + RscLen; + memcpy(pFrameRSC, pFrameNextRDIE, FilledLen); + pFrameRDIE += (RdieLen); + } + else + { + RspLen += RscLen; + pFrameRDIE += (RdieLen + RscLen); + } /* End of if */ + + /* check next RDIE pair */ + RDIE_Index ++; + } /* End of while */ + } /* End of if */ + + /* simulate to response (Medium Time will be 0) */ + FT_RIC_ResourceResponseHandle(pAd, MacPeer, pFrame, RspLen, + &gFT_RIC_RspStatus[gFT_RIC_RspStatusIndex]); + + /* display status */ + FT_RIC_CMD_StatusDisplay(&gFT_RIC_RspStatus[gFT_RIC_RspStatusIndex]); + + /* free temp use memory */ +/* kfree(pFrame); */ + os_free_mem(NULL, pFrame); + + gFT_RIC_RspStatusIndex++; +} /* End of FT_RIC_CMD_SimRscReq */ + + +/* +======================================================================== +Routine Description: + Simulate to end our resource request to the target AP. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + Command: [Selected AP MAC] +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_SimRscReqEnd( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + UCHAR MacPeer[6]; + + + /* get selected AP mac address */ + FT_CMD_UtilMacGet(&pArgv, MacPeer); + + if (*(UINT32 *)MacPeer == 0) + memcpy(MacPeer, gFT_MAC_OldAP, 6); + /* End of if */ + + /* end resource request mechanism */ + FT_RIC_ResourceRequestEnd(pAd, MacPeer); +} /* End of FT_RIC_CMD_SimRscReqEnd */ + + +/* +======================================================================== +Routine Description: + Simulate to list our resource request response from all APs. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_SimRscReqRspList( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) + { + UINT32 IdRsc; + + + for(IdRsc=0; IdRsc 20)) + break; + /* End of if */ + + pParam++; + } /* End of while */ + + pArgv++; /* skip _ points to arg1 */ + + /* handle the command */ + switch(Command) + { +#ifdef CONFIG_AP_SUPPORT + /* normal commands */ + case FT_KDP_CMD_DAEMON_KILL: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> kill daemon!\n")); + FT_KDP_EventInform(pAd, BSS0, FT_KDP_SIG_TERMINATE, NULL, 0, 0, NULL); + break; + +#ifndef FT_KDP_FUNC_SOCK_COMM + case FT_KDP_CMD_EVENT_LIST: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> event list!\n")); + FT_KDP_CMD_EventList(pAd, Argc, pArgv); + break; +#endif /* FT_KDP_FUNC_SOCK_COMM */ + + case FT_KDP_CMD_DEBUG_FLAG_CTRL: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> IAPP daemon debug flag control!\n")); + FT_KDP_CMD_DbgFlagCtrl(pAd, Argc, pArgv); + break; + +#ifdef FT_FUNC_SIMULATION + /* simulation commands */ + case FT_KDP_CMD_SM_EVT_FT_ASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) ft assoc!\n")); + FT_KDP_CMD_SimEvtFtAssoc(pAd, Argc, pArgv); + break; + + case FT_KDP_CMD_SM_EVT_FT_REASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) ft reassoc!\n")); + FT_KDP_CMD_SimEvtFtReAssoc(pAd, Argc, pArgv); + break; + + case FT_KDP_CMD_SM_EVT_KEY_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) key req!\n")); + FT_KDP_CMD_SimKeyReq(pAd, Argc, pArgv); + break; + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + case FT_KDP_CMD_SM_R0KH_INFO_CREATE: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) R0KH INFO create!\n")); + FT_KDP_CMD_SimR0KH_InfoCreate(pAd, Argc, pArgv); + break; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + case FT_RIC_CMD_SM_REQ_HANDLE: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) handle a resource request!\n")); + FT_RIC_CMD_SimRscReqHandle(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_REQ_HDL_TSPEC: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) make a resource request TSPEC!\n")); + FT_RIC_CMD_SimRscReqHdlTspec(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_RRB_SEND: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) send a RRB frame!\n")); + FT_RRB_CMD_SimSend(pAd, Argc, pArgv); + break; + + case FT_11K_CMD_INFO_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) send a info request frame!\n")); + FT_11K_CMD_SimInfoReq(pAd, Argc, pArgv); + break; + + case FT_KDP_KEY_SHOW: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) show key information!\n")); + FT_11K_CMD_SimKeyShow(pAd, Argc, pArgv); + break; +#endif /* FT_FUNC_SIMULATION */ + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + case FT_KDP_CMD_SM_R0KH_INFO_SHOW: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) R0KH INFO show!\n")); + FT_KDP_CMD_R0KH_InfoShow(pAd, (PSTRING)pArgv); + break; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + case FT_R1KH_INFO_SHOW: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) R1KH INFO show!\n")); + FT_R1KH_InfoShow(pAd, Argc, pArgv); + break; + + case FT_REQ_ACT: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> FT_REQ_ACT!\n")); + FT_OverDs_SimReq(pAd, Argc, pArgv); + break; + + case FT_CONFIRM_ACT: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> FT_CONFIRM_ACT!\n")); + FT_OverDs_SimConfirm(pAd, Argc, pArgv); + break; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef FT_FUNC_SIMULATION + case FT_RIC_CMD_SM_REQ_START: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) Resource Request Start!\n")); + FT_RIC_CMD_SimRscReqStart(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) Resource Request!\n")); + FT_RIC_CMD_SimRscReq(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_REQ_END: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) Resource Request End!\n")); + FT_RIC_CMD_SimRscReqEnd(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_REQ_RSP_LIST: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) Resource Req/Rsp List!\n")); + FT_RIC_CMD_SimRscReqRspList(pAd, Argc, pArgv); + break; + + case FT_ROAMING_ACT: + { + PBSS_TABLE pRoamTab = &pAd->MlmeAux.RoamTab; + UCHAR TargetAp[MAC_ADDR_LEN] = {0x00, 0x0c, 0x43, \ + 0x28, 0x60, 0x10}; + ULONG Idx; + + BssTableInit(pRoamTab); + Idx = BssTableSearch(&pAd->ScanTab, TargetAp, + pAd->CommonCfg.Channel); + if (BSS_NOT_FOUND != Idx) + { + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], + &pAd->ScanTab.BssEntry[Idx], sizeof(BSS_ENTRY)); + pRoamTab->BssNr++; + } + else + DBGPRINT(RT_DEBUG_ERROR, + ("Unkonw BssEntry (%ld):%02x:%02x:%02x:%02x:%02x:%02x\n", + Idx, TargetAp[0], TargetAp[1], TargetAp[2], + TargetAp[3], TargetAp[4], TargetAp[5])); + + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } + break; +#endif /* FT_FUNC_SIMULATION */ +#endif /* CONFIG_STA_SUPPORT */ + + default: /* error command type */ + DBGPRINT(RT_DEBUG_TRACE, + ("ft_iocl> ERROR! No such command %d!\n", Command)); + return -EINVAL; /* input error */ + } /* End of switch */ + + return TRUE; +} /* End of FT_Ioctl */ + +#endif /* DOT11R_FT_SUPPORT */ + +/* End of ft_iocl.c */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_rc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_rc.c new file mode 100644 index 000000000..7c0b95a03 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_rc.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_tlv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_tlv.c new file mode 100644 index 000000000..f9c524b22 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ft_tlv.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/gas.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/gas.c new file mode 100644 index 000000000..13f7e928e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/gas.c @@ -0,0 +1,2041 @@ +/* + *************************************************************************** + * 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: + gas.c + + Abstract: + generic advertisement service(GAS) + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +enum DOT11U_ADVERTISMENT_PROTOCOL_ID dot11GASAdvertisementID[] = +{ + ACCESS_NETWORK_QUERY_PROTOCOL, +}; + +static VOID SendGASIndication( + IN PRTMP_ADAPTER pAd, + GAS_EVENT_DATA *Event); + +#ifdef CONFIG_STA_SUPPORT +void wext_send_anqp_rsp_event(PNET_DEV net_dev, const char *peer_mac_addr, + u16 status, const char *anqp_rsp, u16 anqp_rsp_len) +{ + + struct anqp_rsp_data *rsp_data; + u16 buflen = 0; + UCHAR *buf; + + buflen = sizeof(*rsp_data) + anqp_rsp_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + rsp_data = (struct anqp_rsp_data *)buf; + rsp_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(rsp_data->peer_mac_addr, peer_mac_addr, 6); + rsp_data->status = status; + rsp_data->anqp_rsp_len = anqp_rsp_len; + memcpy(rsp_data->anqp_rsp, anqp_rsp, anqp_rsp_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_HS_ANQP_RSP, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + + +void SendAnqpRspEvent(PNET_DEV net_dev, const char *peer_mac_addr, + u16 status, const char *anqp_rsp, u16 anqp_rsp_len) +{ + wext_send_anqp_rsp_event(net_dev, + peer_mac_addr, + status, + anqp_rsp, + anqp_rsp_len); + +} + + +static VOID SendGASReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + UCHAR *Buf, *Pos; + GAS_FRAME *GASFrame; + UINT32 FrameLen = 0, VarLen = 0; + UINT16 tmpLen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (Event->u.GAS_REQ_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Advertisement protocol element + Query request length field */ + VarLen += 6; + } + + /* Query request field*/ + VarLen += Event->u.GAS_REQ_DATA.QueryReqLen; + + os_alloc_mem(pAd, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen); + + GASFrame = (GAS_FRAME *)Buf; + + ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->CurrentAddress, + Event->PeerMACAddr); + + FrameLen += sizeof(HEADER_802_11); + + GASFrame->Category = CATEGORY_PUBLIC; + GASFrame->u.GAS_INIT_REQ.Action = ACTION_GAS_INIT_REQ; + GASFrame->u.GAS_INIT_REQ.DialogToken = Event->u.GAS_REQ_DATA.DialogToken; + FrameLen += 3; + + Pos = GASFrame->u.GAS_INIT_REQ.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + *Pos++ = Event->u.GAS_REQ_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpLen = cpu2le16(Event->u.GAS_REQ_DATA.QueryReqLen); + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + + NdisMoveMemory(Pos, Event->u.GAS_REQ_DATA.QueryReq, Event->u.GAS_REQ_DATA.QueryReqLen); + FrameLen += Event->u.GAS_REQ_DATA.QueryReqLen; + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_RSP); + + os_free_mem(NULL, Buf); +} + + +void GASCBDelayTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext; + GAS_EVENT_DATA *Event; + PRTMP_ADAPTER pAd; + UCHAR *Buf; + UINT32 Len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (!GASPeerEntry) + return; + + pAd = GASPeerEntry->Priv; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + if (GASPeerEntry->GASCBDelayTimerRunning) + { + GASPeerEntry->GASCBDelayTimerRunning = FALSE; + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event)); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = GASPeerEntry->ControlIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASPeerEntry->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = PEER_GAS_RSP_MORE; + Len += 2; + + Event->u.PEER_GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_RSP_MORE, Len, Buf,0); + + os_free_mem(NULL, Buf); + } +} +BUILD_TIMER_FUNCTION(GASCBDelayTimeout); + + +VOID ReceiveGASInitRsp( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event; + GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg; + GAS_PEER_ENTRY *GASPeerEntry; + PGAS_CTRL pGASCtrl = &pAd->StaCfg.GASCtrl; + UCHAR *Pos, *Buf; + UINT16 VarLen; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (GASFrame->u.GAS_INIT_RSP.GASComebackDelay == 0) + { + VarLen = le2cpu16(*(UINT16 *)(GASFrame->u.GAS_INIT_RSP.Variable + 4)); + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = 0; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = PEER_GAS_RSP; + Len += 2; + + Event->u.PEER_GAS_RSP_DATA.StatusCode = le2cpu16(GASFrame->u.GAS_INIT_RSP.StatusCode); + Len += 2; + Pos = GASFrame->u.GAS_INIT_RSP.Variable + 3; + + Event->u.PEER_GAS_RSP_DATA.AdvertisementProID = *Pos; + Len += 1; + Pos++; + + Event->u.PEER_GAS_RSP_DATA.QueryRspLen = le2cpu16(*(UINT16 *)Pos); + Len += 2; + Pos += 2; + + if (Event->u.PEER_GAS_RSP_DATA.QueryRspLen > 0) + NdisMoveMemory(Event->u.PEER_GAS_RSP_DATA.QueryRsp, Pos, + Event->u.PEER_GAS_RSP_DATA.QueryRspLen); + + Len += Event->u.PEER_GAS_RSP_DATA.QueryRspLen; + + RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + /* Cancel GASResponse Timer */ + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if (GASPeerEntry->GASResponseTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled); + GASPeerEntry->GASResponseTimerRunning = FALSE; + } + + break; + } + } + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_RSP, Len, Buf,0); + + os_free_mem(NULL, Buf); + } + else + { + RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2)) + { + GASPeerEntry->DialogToken = GASFrame->u.GAS_INIT_RSP.DialogToken; + + /* Set a GAS comeback delay timeout timer + * to send out GAS comeback request + */ + GASPeerEntry->Priv = pAd; + if (!GASPeerEntry->GASCBDelayTimerRunning) + { + RTMPSetTimer(&GASPeerEntry->GASCBDelayTimer, + (GASFrame->u.GAS_INIT_RSP.GASComebackDelay * 1024) / 1000); + GASPeerEntry->GASCBDelayTimerRunning = TRUE; + } + + break; + } + } + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + } +} + + +static VOID SendGASCBReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + UCHAR *Buf; + GAS_FRAME *GASFrame; + UINT32 FrameLen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + os_alloc_mem(pAd, (UCHAR **)&Buf, sizeof(*GASFrame)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASFrame)); + + GASFrame = (GAS_FRAME *)Buf; + + ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->CurrentAddress, + Event->PeerMACAddr); + + FrameLen += sizeof(HEADER_802_11); + + GASFrame->Category = CATEGORY_PUBLIC; + GASFrame->u.GAS_CB_REQ.Action = ACTION_GAS_CB_REQ; + + if (Event->EventType == PEER_GAS_RSP_MORE) + GASFrame->u.GAS_CB_REQ.DialogToken = Event->u.PEER_GAS_RSP_MORE_DATA.DialogToken; + else if (Event->EventType == GAS_CB_RSP_MORE) + GASFrame->u.GAS_CB_REQ.DialogToken = Event->u.GAS_CB_RSP_MORE_DATA.DialogToken; + + FrameLen += 3; + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_RSP); + + os_free_mem(NULL, Buf); +} + + +VOID ReceiveGASCBRsp( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event; + GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg; + PGAS_CTRL pGASCtrl = &pAd->StaCfg.GASCtrl; + UINT16 VarLen = 0, QueryRspLen = 0; + GAS_PEER_ENTRY *GASPeerEntry; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag; + UCHAR *Pos, *Buf; + BOOLEAN Cancelled; + INT32 Ret; + UINT32 Len = 0; + UINT16 StatusCode; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + /* GAS comeback response length */ + Pos = GASFrame->u.GAS_CB_RSP.Variable + 4; + QueryRspLen = le2cpu16(*(UINT16 *)(Pos)); + + RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2)) + { + if (QueryRspLen > 0) + { + Pos += 2; + + os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag, sizeof(*GASQueryRspFrag)); + + if (!GASQueryRspFrag) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + return; + } + + NdisZeroMemory(GASQueryRspFrag, sizeof(*GASQueryRspFrag)); + + GASQueryRspFrag->GASRspFragID = + GASFrame->u.GAS_CB_RSP.GASRspFragID & 0x7F; + + GASQueryRspFrag->FragQueryRspLen = QueryRspLen; + + os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + + if (!GASQueryRspFrag->FragQueryRsp) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + goto error0; + } + + NdisMoveMemory(GASQueryRspFrag->FragQueryRsp, Pos, + GASQueryRspFrag->FragQueryRspLen); + + DlListAddTail(&GASPeerEntry->GASQueryRspFragList, + &GASQueryRspFrag->List); + + GASPeerEntry->GASRspFragNum++; + GASPeerEntry->CurrentGASFragNum++; + break; + } + } + } + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + + StatusCode = le2cpu16(GASFrame->u.GAS_CB_RSP.StatusCode); + + if ((StatusCode == RESPONSE_NOT_RECEIVED_FROM_SERVER) || + ((StatusCode == 0) && + ((GASFrame->u.GAS_CB_RSP.GASRspFragID & 0x80) == 0x80))) + { + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error1; + } + + NdisZeroMemory(Buf, sizeof(*Event)); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = 0; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = GAS_CB_RSP_MORE; + Len += 2; + + Event->u.GAS_CB_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + + /* Reset dot11GASResponse timer */ + if (GASPeerEntry->GASResponseTimerRunning) + RTMPModTimer(&GASPeerEntry->GASResponseTimer, dot11GASResponseTimeout); + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_RSP_MORE, Len, Buf,0); + + os_free_mem(NULL, Buf); + + }else if ((StatusCode == TIMEOUT) || + (StatusCode == QUERY_RESPONSE_TOO_LARGE) || + (StatusCode == UNSPECIFIED_FAILURE) || + ((StatusCode == 0) && + ((GASFrame->u.GAS_CB_RSP.GASRspFragID & 0x80) == 0x00))) + { + if (StatusCode == 0) + { + RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + VarLen += GASQueryRspFrag->FragQueryRspLen; + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error1; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = 0; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = GAS_CB_RSP; + Len += 2; + + Event->u.GAS_CB_RSP_DATA.StatusCode = StatusCode; + Len += 2; + + Event->u.GAS_CB_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + if (GASFrame->u.GAS_CB_RSP.StatusCode == 0) + Event->u.GAS_CB_RSP_DATA.QueryRspLen = VarLen; + else + Event->u.GAS_CB_RSP_DATA.QueryRspLen = 0; + + Len += 2; + + if (Event->u.GAS_CB_RSP_DATA.QueryRspLen > 0) + { + Pos = Event->u.GAS_CB_RSP_DATA.QueryRsp; + + RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + Pos += GASQueryRspFrag->FragQueryRspLen; + } + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + } + + Len += Event->u.GAS_CB_RSP_DATA.QueryRspLen; + + if (GASPeerEntry->GASResponseTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled); + GASPeerEntry->GASResponseTimerRunning = FALSE; + } + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_RSP, Len, Buf,0); + os_free_mem(NULL, Buf); + } + + return; + +error1: + if (QueryRspLen > 0) + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); +error0: + os_free_mem(NULL, GASQueryRspFrag); +} + + +static VOID SendGASConfirm( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + PGAS_CTRL pGASCtrl = &pAd->StaCfg.GASCtrl; + GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *GASQueryRspFragTmp; + INT32 Ret; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (Event->EventType == PEER_GAS_RSP) + { + if (Event->u.PEER_GAS_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Send GAS confirm to daemon */ + SendAnqpRspEvent(pAd->net_dev, + Event->PeerMACAddr, + Event->u.PEER_GAS_RSP_DATA.StatusCode, + Event->u.PEER_GAS_RSP_DATA.QueryRsp, + Event->u.PEER_GAS_RSP_DATA.QueryRspLen); + } + } + else if (Event->EventType == GAS_CB_RSP) + { + if (Event->u.GAS_CB_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Send GAS confirm to daemon */ + SendAnqpRspEvent(pAd->net_dev, + Event->PeerMACAddr, + Event->u.GAS_CB_RSP_DATA.StatusCode, + Event->u.GAS_CB_RSP_DATA.QueryRsp, + Event->u.GAS_CB_RSP_DATA.QueryRspLen); + + } + } + + RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, &GASPeerEntry->GASQueryRspFragList, + GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + } + DlListInit(&GASPeerEntry->GASQueryRspFragList); + DlListDel(&GASPeerEntry->List); + if (GASPeerEntry->GASResponseTimerRunning) + RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled); + if (GASPeerEntry->GASCBDelayTimerRunning) + RTMPCancelTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled); + RTMPReleaseTimer(&GASPeerEntry->GASResponseTimer, &Cancelled); + RTMPReleaseTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); +} + + +void GASResponseTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext; + GAS_EVENT_DATA *Event; + IN PRTMP_ADAPTER pAd; + UCHAR *Buf; + UINT32 Len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (!GASPeerEntry) + return; + + pAd = GASPeerEntry->Priv; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + if (GASPeerEntry->GASResponseTimerRunning) + { + GASPeerEntry->GASResponseTimerRunning = FALSE; + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event)); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = GASPeerEntry->ControlIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASPeerEntry->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + if (GASPeerEntry->CurrentState == WAIT_PEER_GAS_RSP) + { + Event->EventType = PEER_GAS_RSP; + Len += 2; + + Event->u.PEER_GAS_RSP_DATA.StatusCode = TIMEOUT; + Len += 2; + + Event->u.PEER_GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + Event->u.PEER_GAS_RSP_DATA.QueryRspLen = 0; + Len += 2; + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_RSP, Len, Buf,0); + } + else if (GASPeerEntry->CurrentState == WAIT_GAS_CB_RSP) + { + Event->EventType = GAS_CB_RSP; + Len += 2; + + Event->u.GAS_CB_RSP_DATA.StatusCode = TIMEOUT; + Len += 2; + + Event->u.GAS_CB_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + Event->u.GAS_CB_RSP_DATA.QueryRspLen = 0; + Len += 2; + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_RSP, Len, Buf,0); + } + + os_free_mem(NULL, Buf); + } +} +BUILD_TIMER_FUNCTION(GASResponseTimeout); +#endif /* CONFIG_STA_SUPPORT */ + + +enum GAS_STATE GASPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PGAS_CTRL pGASCtrl; + PGAS_PEER_ENTRY GASPeerEntry; + PGAS_EVENT_DATA Event = (PGAS_EVENT_DATA)Elem->Msg; + +#ifdef CONFIG_AP_SUPPORT + pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + pGASCtrl = &pAd->StaCfg.GASCtrl; +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + return GASPeerEntry->CurrentState; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + return GAS_UNKNOWN; +} + + +VOID GASSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem, + PGAS_EVENT_DATA Event, + IN enum GAS_STATE State) +{ + + PGAS_CTRL pGASCtrl; + PGAS_PEER_ENTRY GASPeerEntry; + //PGAS_EVENT_DATA Event = (PGAS_EVENT_DATA)Elem->Msg; + +#ifdef CONFIG_AP_SUPPORT + pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + pGASCtrl = &pAd->StaCfg.GASCtrl; +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASPeerEntry->CurrentState = State; + break; + } + + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); +} + + +#ifdef CONFIG_AP_SUPPORT +void wext_send_anqp_req_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *anqp_req, u16 anqp_req_len) +{ + struct anqp_req_data *req_data; + u16 buflen = 0; + char *buf; + + buflen = sizeof(*req_data) + anqp_req_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + req_data = (struct anqp_req_data *)buf; + req_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(req_data->peer_mac_addr, peer_mac_addr, 6); + req_data->anqp_req_len = anqp_req_len; + memcpy(req_data->anqp_req, anqp_req, anqp_req_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_HS_ANQP_REQ, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); + +} + + +void SendAnqpReqEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *anqp_req, u16 anqp_req_len) +{ + wext_send_anqp_req_event(net_dev, + peer_mac_addr, + anqp_req, + anqp_req_len); +} + + +//static VOID SendGASRsp( +// IN PRTMP_ADAPTER pAd, +// IN MLME_QUEUE_ELEM *Elem) +VOID SendGASRsp( + IN PRTMP_ADAPTER pAd, + GAS_EVENT_DATA *Event) +{ + + //GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + UCHAR *Buf, *Pos; + GAS_FRAME *GASFrame; + ULONG FrameLen = 0, VarLen = 0, tmpValue = 0; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; + GAS_PEER_ENTRY *GASPeerEntry; + BOOLEAN Cancelled; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + break; + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (Event->u.GAS_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Advertisement protocol element + Query response length field */ + VarLen += 6; + } + + if (Event->EventType == GAS_RSP) + { + /* Query response field*/ + VarLen += Event->u.GAS_RSP_DATA.QueryRspLen; + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + + //GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_PEER_GAS_REQ); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + + return; + } + + NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen); + + GASFrame = (GAS_FRAME *)Buf; + + ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + GASFrame->Category = CATEGORY_PUBLIC; + FrameLen += 1; + GASFrame->u.GAS_INIT_RSP.Action = ACTION_GAS_INIT_RSP; + FrameLen += 1; + + if (Event->EventType == GAS_RSP) + { + GASFrame->u.GAS_INIT_RSP.DialogToken = Event->u.GAS_RSP_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_INIT_RSP.StatusCode = cpu2le16(Event->u.GAS_RSP_DATA.StatusCode); + FrameLen += 2; + + GASFrame->u.GAS_INIT_RSP.GASComebackDelay = Event->u.GAS_RSP_DATA.GASComebackDelay; + FrameLen += 2; + + Pos = GASFrame->u.GAS_INIT_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_RSP_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpValue = cpu2le16(Event->u.GAS_RSP_DATA.QueryRspLen); + NdisMoveMemory(Pos, &tmpValue, 2); + Pos += 2; + FrameLen += 6; + + if (Event->u.GAS_RSP_DATA.QueryRspLen > 0) + NdisMoveMemory(Pos, Event->u.GAS_RSP_DATA.QueryRsp, Event->u.GAS_RSP_DATA.QueryRspLen); + + FrameLen += Event->u.GAS_RSP_DATA.QueryRspLen; + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_PEER_GAS_REQ); + + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource++; + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->FreeResource++; + + GASPeerEntry->FreeResource++; + os_free_mem(NULL, GASPeerEntry); + + } + else if (Event->EventType == GAS_RSP_MORE) + { + + GASFrame->u.GAS_INIT_RSP.DialogToken = Event->u.GAS_RSP_MORE_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_INIT_RSP.StatusCode = cpu2le16(Event->u.GAS_RSP_MORE_DATA.StatusCode); + FrameLen += 2; + + GASFrame->u.GAS_INIT_RSP.GASComebackDelay = Event->u.GAS_RSP_MORE_DATA.GASComebackDelay; + FrameLen += 2; + + Pos = GASFrame->u.GAS_INIT_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_RSP_MORE_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpValue = 0; + NdisMoveMemory(Pos, &tmpValue, 2); + + Pos += 2; + FrameLen += 6; + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_CB_REQ); + + /* + * Buffer the query response for a minimun of dotGASResponseBufferingTime + * after the expiry of the GAS comeback delay + */ + if (!GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPSetTimer(&GASPeerEntry->GASRspBufferingTimer, dotGASResponseBufferingTime + + GASFrame->u.GAS_INIT_RSP.GASComebackDelay); + GASPeerEntry->GASRspBufferingTimerRunning = TRUE; + } + + } + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + os_free_mem(NULL, Buf); +} + + +VOID ReceiveGASInitReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event; + GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg; + GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp; + PGAS_CTRL pGASCtrl = NULL; + UCHAR APIndex, *Pos, *Buf; + UINT16 VarLen; + UINT32 Len = 0; + BOOLEAN IsFound = FALSE, Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + break; + } + } + + if (!pGASCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2)) + { + IsFound = TRUE; + GASPeerEntry->QueryNum++; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (IsFound) { + + + //if (GASPeerEntry->QueryNum++ >= 15) + { + /* Query too many times, remove the peer address from list */ + DBGPRINT(RT_DEBUG_OFF, ("%s Q %d, old 0x%x, 0x%x, %02x:%02x:%02x:%02x:%02x:%02x remove peer\n", __FUNCTION__, GASPeerEntry->QueryNum, GASPeerEntry->DialogToken, GASFrame->u.GAS_INIT_REQ.DialogToken, GASPeerEntry->PeerMACAddr[0], GASPeerEntry->PeerMACAddr[1], GASPeerEntry->PeerMACAddr[2], GASPeerEntry->PeerMACAddr[3], GASPeerEntry->PeerMACAddr[4], GASPeerEntry->PeerMACAddr[5])); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2)) + { + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->FreeResource++; + + os_free_mem(NULL, GASPeerEntry); + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + } + //return; + } + + + os_alloc_mem(NULL, (UCHAR **)&GASPeerEntry, sizeof(*GASPeerEntry)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(GASPeerEntry, sizeof(*GASPeerEntry)); + GASPeerEntry->AllocResource++; + + GASPeerEntry->CurrentState = WAIT_PEER_GAS_REQ; + GASPeerEntry->QueryNum++; + NdisMoveMemory(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + GASPeerEntry->DialogToken = GASFrame->u.GAS_INIT_REQ.DialogToken; + GASPeerEntry->Priv = pAd; + RTMPInitTimer(pAd, &GASPeerEntry->PostReplyTimer, + GET_TIMER_FUNCTION(PostReplyTimeout), GASPeerEntry, FALSE); + GASPeerEntry->AllocResource++; + RTMPInitTimer(pAd, &GASPeerEntry->GASRspBufferingTimer, + GET_TIMER_FUNCTION(GASRspBufferingTimeout), GASPeerEntry, FALSE); + GASPeerEntry->AllocResource++; + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListAddTail(&pGASCtrl->GASPeerList, &GASPeerEntry->List); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + NdisMoveMemory(&VarLen, GASFrame->u.GAS_INIT_REQ.Variable + 4, 2); + VarLen = le2cpu16(VarLen); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = PEER_GAS_REQ; + Len += 2; + + Event->u.PEER_GAS_REQ_DATA.DialogToken = GASFrame->u.GAS_INIT_REQ.DialogToken; + Len += 1; + + Pos = GASFrame->u.GAS_INIT_REQ.Variable + 3; + Event->u.PEER_GAS_REQ_DATA.AdvertisementProID = *Pos; + GASPeerEntry->AdvertisementProID = *Pos; + Len += 1; + Pos++; + + NdisMoveMemory(&Event->u.PEER_GAS_REQ_DATA.QueryReqLen, Pos, 2); + Event->u.PEER_GAS_REQ_DATA.QueryReqLen = le2cpu16(Event->u.PEER_GAS_REQ_DATA.QueryReqLen); + Len += 2; + Pos += 2; + + NdisMoveMemory(Event->u.PEER_GAS_REQ_DATA.QueryReq, Pos, Event->u.PEER_GAS_REQ_DATA.QueryReqLen); + Len += Event->u.PEER_GAS_REQ_DATA.QueryReqLen; + + + SendGASIndication(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_REQ, Len, Buf,0); + + //RTMP_MLME_HANDLER(pAd); + + + os_free_mem(NULL, Buf); + + return; + +error: + DlListDel(&GASPeerEntry->List); + os_free_mem(NULL, GASPeerEntry); +} + + +static VOID SendGASCBRsp( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem) + GAS_EVENT_DATA *Event) +{ + //GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + UCHAR *Buf, *Pos; + GAS_FRAME *GASFrame; + ULONG FrameLen = 0, VarLen = 0, tmpLen = 0; + GAS_PEER_ENTRY *GASPeerEntry; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag = NULL, *GASQueryRspFragTmp; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; + BOOLEAN bGASQueryRspFragFound = FALSE; + BOOLEAN Cancelled; + + + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if (GASPeerEntry->AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Advertisement protocol element + Query response length field */ + VarLen += 6; + } + + DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList, + GAS_QUERY_RSP_FRAGMENT, List) + { + if (GASPeerEntry->CurrentGASFragNum == + GASQueryRspFrag->GASRspFragID) + { + GASPeerEntry->CurrentGASFragNum++; + VarLen += GASQueryRspFrag->FragQueryRspLen; + bGASQueryRspFragFound = TRUE; + break; + } + } + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen); + + GASFrame = (GAS_FRAME *)Buf; + + ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + GASFrame->Category = CATEGORY_PUBLIC; + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.Action = ACTION_GAS_CB_RSP; + FrameLen += 1; + + if (Event->EventType == GAS_CB_REQ) + { + GASFrame->u.GAS_CB_RSP.DialogToken = Event->u.GAS_CB_REQ_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.StatusCode = cpu2le16(Event->u.GAS_CB_REQ_DATA.StatusCode); + FrameLen += 2; + + if (bGASQueryRspFragFound) + GASFrame->u.GAS_CB_RSP.GASRspFragID = (GASQueryRspFrag->GASRspFragID & 0x7F); + else + GASFrame->u.GAS_CB_RSP.GASRspFragID = 0; + + DBGPRINT(RT_DEBUG_OFF, ("GASRspFragID = %d\n", GASFrame->u.GAS_CB_RSP.GASRspFragID)); + + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.GASComebackDelay = 0; + FrameLen += 2; + + Pos = GASFrame->u.GAS_CB_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_CB_REQ_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + if (Event->u.GAS_CB_REQ_DATA.StatusCode == 0) + { + + tmpLen = cpu2le16(GASQueryRspFrag->FragQueryRspLen); + + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + + NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + + FrameLen += GASQueryRspFrag->FragQueryRspLen; + } + else + { + tmpLen = 0; + + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + } + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + GASPeerEntry->FreeResource += 2; + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource += 1; + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled); + + + os_free_mem(NULL, GASPeerEntry); + } + else if (Event->EventType == GAS_CB_REQ_MORE) + { + + GASFrame->u.GAS_CB_RSP.DialogToken = Event->u.GAS_CB_REQ_MORE_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.StatusCode = cpu2le16(Event->u.GAS_CB_REQ_MORE_DATA.StatusCode); + FrameLen += 2; + + GASFrame->u.GAS_CB_RSP.GASRspFragID = (0x80 | (GASQueryRspFrag->GASRspFragID & 0x7F)); + DBGPRINT(RT_DEBUG_OFF, ("GASRspFragID = %d\n", GASFrame->u.GAS_CB_RSP.GASRspFragID)); + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.GASComebackDelay = 0; + FrameLen += 2; + + Pos = GASFrame->u.GAS_CB_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_CB_REQ_MORE_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpLen = cpu2le16(GASQueryRspFrag->FragQueryRspLen); + + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + + NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + + FrameLen += GASQueryRspFrag->FragQueryRspLen; + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_CB_REQ); + + } + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + os_free_mem(NULL, Buf); +} + + +VOID ReceiveGASCBReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event; + GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg; + GAS_PEER_ENTRY *GASPeerEntry; + PGAS_CTRL pGASCtrl = NULL; + UCHAR APIndex, *Buf; + UINT32 Len = 0; + BOOLEAN IsGASCBReqMore = FALSE; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + break; + } + } + + if (!pGASCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event)); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if ((GASPeerEntry->CurrentGASFragNum + 1) < + GASPeerEntry->GASRspFragNum) + IsGASCBReqMore = TRUE; + + IsFound = TRUE; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (!IsGASCBReqMore) + { + if(IsFound) + { + Event->EventType = GAS_CB_REQ; + Len += 2; + + Event->u.GAS_CB_REQ_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + Len += 1; + + Event->u.GAS_CB_REQ_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + if (pGASCtrl->ExternalANQPServerTest == 2) + Event->u.GAS_CB_REQ_DATA.StatusCode = SERVER_UNREACHABLE; + else + Event->u.GAS_CB_REQ_DATA.StatusCode = 0; + + Len += 2; + + SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + + } + else + { + os_alloc_mem(NULL, (UCHAR **)&GASPeerEntry, sizeof(*GASPeerEntry)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error; + } + + NdisZeroMemory(GASPeerEntry, sizeof(*GASPeerEntry)); + + GASPeerEntry->CurrentState = WAIT_GAS_CB_REQ; + GASPeerEntry->ControlIndex = Event->ControlIndex; + NdisMoveMemory(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + GASPeerEntry->DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + GASPeerEntry->AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; // FIXME + GASPeerEntry->Priv = pAd; + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListAddTail(&pGASCtrl->GASPeerList, &GASPeerEntry->List); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + Event->EventType = GAS_CB_REQ; + Len += 2; + + Event->u.GAS_CB_REQ_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + Len += 1; + + Event->u.GAS_CB_REQ_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; + Len += 1; + + Event->u.GAS_CB_REQ_DATA.StatusCode = UNSPECIFIED_FAILURE; + Len += 2; + + + SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ, Len, Buf, 0); + //RTMP_MLME_HANDLER(pAd); + + } + } + else + { + Event->EventType = GAS_CB_REQ_MORE; + Len += 2; + + Event->u.GAS_CB_REQ_MORE_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + Len += 1; + + Event->u.GAS_CB_REQ_MORE_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + Event->u.GAS_CB_REQ_MORE_DATA.StatusCode = 0; + Len += 2; + + + SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ_MORE, Len, Buf,0); + //RTMP_MLME_HANDLER(pAd); + + } + + +error: + os_free_mem(NULL, Buf); +} + + +static BOOLEAN IsAdvertisementProIDValid( + IN PRTMP_ADAPTER pAd, + IN enum DOT11U_ADVERTISMENT_PROTOCOL_ID AdvertisementProtoID) +{ + INT32 i; + + for (i = 0; i < sizeof(dot11GASAdvertisementID) + / sizeof(enum DOT11U_ADVERTISMENT_PROTOCOL_ID); i++) + { + if (AdvertisementProtoID == dot11GASAdvertisementID[i]) + return TRUE; + } + + return FALSE; +} + + +void PostReplyTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext; + PGAS_CTRL pGASCtrl; + PRTMP_ADAPTER pAd; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: GASPeerEntry is NULL\n", __FUNCTION__)); + return; + } + + pAd = GASPeerEntry->Priv; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return; + } + + pGASCtrl = &pAd->ApCfg.MBSSID[GASPeerEntry->ControlIndex].GASCtrl; + + GASPeerEntry->PostReplyTimerRunning = FALSE; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource += 1; + + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled); + GASPeerEntry->FreeResource += 1; + + GASPeerEntry->FreeResource += 1; + + os_free_mem(NULL, GASPeerEntry); + +} +BUILD_TIMER_FUNCTION(PostReplyTimeout); + + +VOID GASRspBufferingTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + PGAS_CTRL pGASCtrl; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag = NULL, *GASQueryRspFragTmp; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: GASPeerEntry is NULL\n", __FUNCTION__)); + return; + } + + pAd = GASPeerEntry->Priv; + + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return; + } + + pGASCtrl = &pAd->ApCfg.MBSSID[GASPeerEntry->ControlIndex].GASCtrl; + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + GASPeerEntry->FreeResource += 2; + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource += 1; + + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled); + GASPeerEntry->FreeResource += 1; + + GASPeerEntry->FreeResource += 1; + + os_free_mem(NULL, GASPeerEntry); + } +} +BUILD_TIMER_FUNCTION(GASRspBufferingTimeout); + + +static VOID SendGASIndication( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem) + GAS_EVENT_DATA *Event) +{ + PGAS_PEER_ENTRY GASPeerEntry; + //GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + GAS_EVENT_DATA *GASRspEvent; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; + PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + UCHAR *Buf; + UINT32 Len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + /* + * If advertisement protocol ID equals to the value + * contained in any dot11GASAdvertisementID MID objects + */ + if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) && + !pGASCtrl->ExternalANQPServerTest) + { + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Init PostReply timer */ + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if (!GASPeerEntry->PostReplyTimerRunning) + { + RTMPSetTimer(&GASPeerEntry->PostReplyTimer, dot11GASResponseTimeout); + GASPeerEntry->PostReplyTimerRunning = TRUE; + } + + break; + } + } + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + + if (Event->u.PEER_GAS_REQ_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Send anqp request indication to daemon */ + SendAnqpReqEvent(NetDev, + Event->PeerMACAddr, + Event->u.PEER_GAS_REQ_DATA.QueryReq, + Event->u.PEER_GAS_REQ_DATA.QueryReqLen); + } + } + else if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) && + pGASCtrl->ExternalANQPServerTest == 1) /* server not reachable for 2F test */ + { + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASRspEvent)); + + GASRspEvent = (GAS_EVENT_DATA *)Buf; + + GASRspEvent->ControlIndex = Event->ControlIndex; + Len += 1; + NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + GASRspEvent->EventType = GAS_RSP; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASRspEvent->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + GASRspEvent->u.GAS_RSP_DATA.StatusCode = SERVER_UNREACHABLE; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.GASComebackDelay = 0; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + GASRspEvent->u.GAS_RSP_DATA.QueryRspLen = 0; + Len += 2; + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + + + + + os_free_mem(NULL, Buf); + } + else if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) && + pGASCtrl->ExternalANQPServerTest == 2) /* server not reachable for 4F test */ + { + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASRspEvent)); + + GASRspEvent = (GAS_EVENT_DATA *)Buf; + + GASRspEvent->ControlIndex = Event->ControlIndex; + Len += 1; + NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + GASRspEvent->EventType = GAS_RSP_MORE; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASRspEvent->u.GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + GASRspEvent->u.GAS_RSP_MORE_DATA.StatusCode = 0; + Len += 2; + + GASRspEvent->u.GAS_RSP_MORE_DATA.GASComebackDelay = 1; + Len += 2; + + GASRspEvent->u.GAS_RSP_MORE_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP_MORE, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + + + os_free_mem(NULL, Buf); + } + else if (!IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID)) + { + /* Do not support this advertisement protocol, such as MIH */ + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASRspEvent)); + + GASRspEvent = (GAS_EVENT_DATA *)Buf; + + GASRspEvent->ControlIndex = Event->ControlIndex; + Len += 1; + NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + GASRspEvent->EventType = GAS_RSP; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASRspEvent->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + GASRspEvent->u.GAS_RSP_DATA.StatusCode = ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.GASComebackDelay = 0; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + GASRspEvent->u.GAS_RSP_DATA.QueryRspLen = 0; + Len += 2; + + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf, 0); + RTMP_MLME_HANDLER(pAd); + + os_free_mem(NULL, Buf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: should not in this case\n", __FUNCTION__)); +} +#endif /* CONFIG_AP_SUPPORT */ + +static VOID GASCtrlInit(IN PRTMP_ADAPTER pAd) +{ + PGAS_CTRL pGASCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif + +#ifdef CONFIG_STA_SUPPORT + pGASCtrl = &pAd->StaCfg.GASCtrl; + NdisZeroMemory(pGASCtrl, sizeof(*pGASCtrl)); + NdisAllocateSpinLock(pAd, &pGASCtrl->GASPeerListLock); + DlListInit(&pGASCtrl->GASPeerList); +#endif + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + NdisZeroMemory(pGASCtrl, sizeof(*pGASCtrl)); + NdisAllocateSpinLock(pAd, &pGASCtrl->GASPeerListLock); + DlListInit(&pGASCtrl->GASPeerList); + } +#endif +} + +VOID GASCtrlExit(IN PRTMP_ADAPTER pAd) +{ + PGAS_CTRL pGASCtrl; + GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *GASQueryRspFragTmp; + BOOLEAN Cancelled; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif + +#ifdef CONFIG_STA_SUPPORT + pGASCtrl = &pAd->StaCfg.GASCtrl; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Remove all GAS peer entry */ + DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, + &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + if (GASPeerEntry->GASResponseTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled); + GASPeerEntry->GASResponseTimerRunning = FALSE; + } + + if (GASPeerEntry->GASCBDelayTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled); + GASPeerEntry->GASCBDelayTimerRunning = FALSE; + } + + RTMPReleaseTimer(&GASPeerEntry->GASResponseTimer, &Cancelled); + RTMPReleaseTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + + } + + DlListInit(&pGASCtrl->GASPeerList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + NdisFreeSpinLock(&pGASCtrl->GASPeerListLock); +#endif + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Remove all GAS peer entry */ + DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, + &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + } + + DlListInit(&pGASCtrl->GASPeerList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + NdisFreeSpinLock(&pGASCtrl->GASPeerListLock); + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID GASStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + GASCtrlInit(pAd); + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_GAS_STATE, MAX_GAS_MSG, (STATE_MACHINE_FUNC)Drop, GAS_UNKNOWN, GAS_MACHINE_BASE); +#ifdef CONFIG_STA_SUPPORT + StateMachineSetAction(S, WAIT_GAS_REQ, GAS_REQ, (STATE_MACHINE_FUNC)SendGASReq); + StateMachineSetAction(S, WAIT_PEER_GAS_RSP, PEER_GAS_RSP_MORE, (STATE_MACHINE_FUNC)SendGASCBReq); + StateMachineSetAction(S, WAIT_PEER_GAS_RSP, PEER_GAS_RSP, (STATE_MACHINE_FUNC)SendGASConfirm); + StateMachineSetAction(S, WAIT_GAS_CB_RSP, GAS_CB_RSP_MORE, (STATE_MACHINE_FUNC)SendGASCBReq); + StateMachineSetAction(S, WAIT_GAS_CB_RSP, GAS_CB_RSP, (STATE_MACHINE_FUNC)SendGASConfirm); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_PEER_GAS_REQ, PEER_GAS_REQ, (STATE_MACHINE_FUNC)SendGASIndication); + StateMachineSetAction(S, WAIT_GAS_RSP, GAS_RSP, (STATE_MACHINE_FUNC)SendGASRsp); + StateMachineSetAction(S, WAIT_GAS_RSP, GAS_RSP_MORE, (STATE_MACHINE_FUNC)SendGASRsp); + StateMachineSetAction(S, WAIT_GAS_RSP, GAS_CB_REQ, (STATE_MACHINE_FUNC)SendGASCBRsp); + StateMachineSetAction(S, WAIT_GAS_CB_REQ, GAS_CB_REQ, (STATE_MACHINE_FUNC)SendGASCBRsp); + StateMachineSetAction(S, WAIT_GAS_CB_REQ, GAS_CB_REQ_MORE, (STATE_MACHINE_FUNC)SendGASCBRsp); +#endif /* CONFIG_AP_SUPPORT */ +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/hotspot.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/hotspot.c new file mode 100644 index 000000000..573860599 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/hotspot.c @@ -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; +} + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/igmp_snoop.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/igmp_snoop.c new file mode 100644 index 000000000..ef1b5ea35 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/igmp_snoop.c @@ -0,0 +1,1778 @@ +#ifdef IGMP_SNOOP_SUPPORT + +#include "rt_config.h" +#include "ipv6.h" +#include "igmp_snoop.h" + +UINT16 IPv6MulticastFilterExclued[] = +{ + IPV6_NEXT_HEADER_ICMPV6, /* ICMPv6. */ + IPV6_NEXT_HEADER_PIM, /* PIM. */ +}; +#define IPV6_MULTICAST_FILTER_EXCLUED_SIZE \ + (sizeof(IPv6MulticastFilterExclued) / sizeof(UINT16)) + +static inline void initFreeEntryList( + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList) +{ + int i; + + for (i = 0; i < FREE_MEMBER_POOL_SIZE; i++) + insertTailList(pList, (PLIST_ENTRY)&(pMulticastFilterTable->freeMemberPool[i])); + + return; +} + +static inline PMEMBER_ENTRY AllocaGrpMemberEntry( + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable) +{ + PMEMBER_ENTRY pMemberEntry; + + RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); + + pMemberEntry = (PMEMBER_ENTRY)removeHeadList(&pMulticastFilterTable->freeEntryList); + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); + + return (PMEMBER_ENTRY)pMemberEntry; +} + +static inline VOID FreeGrpMemberEntry( + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PMEMBER_ENTRY pEntry) +{ + RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); + + insertTailList(&pMulticastFilterTable->freeEntryList, (PLIST_ENTRY)pEntry); + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); +} + +static VOID IGMPTableDisplay( + IN PRTMP_ADAPTER pAd); + +static BOOLEAN isIgmpMacAddr( + IN PUCHAR pMacAddr); + +static VOID InsertIgmpMember( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList, + IN PUCHAR pMemberAddr); + +static VOID DeleteIgmpMember( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList, + IN PUCHAR pMemberAddr); + +static VOID DeleteIgmpMemberList( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList); + +#ifdef IGMP_MESH +static BOOLEAN isNeedClone( + IN PUSHORT send_table, + IN UCHAR size, + IN USHORT Aid); + +static MAC_TABLE_ENTRY *IgmpMwdsInquiry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate); + +VOID IgmpMeshTabUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac); + +VOID IgmpMwdsEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac); + + +static VOID IgmpMwdsTableReset( + IN PRTMP_ADAPTER pAd); + +#endif /* MWDS */ + +/* + ========================================================================== + Description: + This routine init the entire IGMP table. + ========================================================================== + */ +VOID MulticastFilterTableInit( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable) +{ + /* Initialize MAC table and allocate spin lock */ + os_alloc_mem(NULL, (UCHAR **)ppMulticastFilterTable, sizeof(MULTICAST_FILTER_TABLE)); + if (*ppMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for Multicase filter table, size=%d\n", + __FUNCTION__, sizeof(MULTICAST_FILTER_TABLE))); + return; + } + + NdisZeroMemory(*ppMulticastFilterTable, sizeof(MULTICAST_FILTER_TABLE)); + NdisAllocateSpinLock(pAd, &((*ppMulticastFilterTable)->MulticastFilterTabLock)); + + NdisAllocateSpinLock(pAd, &((*ppMulticastFilterTable)->FreeMemberPoolTabLock)); + initList(&((*ppMulticastFilterTable)->freeEntryList)); + initFreeEntryList(*ppMulticastFilterTable, &((*ppMulticastFilterTable)->freeEntryList)); + return; +} + +/* + ========================================================================== + Description: + This routine reset the entire IGMP table. + ========================================================================== + */ +VOID MultiCastFilterTableReset( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable) +{ + if(*ppMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); + return; + } + + NdisFreeSpinLock(&((*ppMulticastFilterTable)->FreeMemberPoolTabLock)); + NdisFreeSpinLock(&((*ppMulticastFilterTable)->MulticastFilterTabLock)); + os_free_mem(NULL, *ppMulticastFilterTable); + *ppMulticastFilterTable = NULL; +#ifdef IGMP_MESH + IgmpMwdsTableReset(pAd); +#endif /* IGMP_MESH */ +} + +/* + ========================================================================== + Description: + Display all entrys in IGMP table + ========================================================================== + */ +static VOID IGMPTableDisplay( + IN PRTMP_ADAPTER pAd) +{ + int i; + MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL; + PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; + +#ifdef IGMP_MESH + UCHAR DadWcid = 0; + MAC_TABLE_ENTRY *client_entry = NULL; + PROUTING_ENTRY pRoutingEntry =NULL; +#endif /* IGMP_MESH */ + + printk(KERN_INFO "Multicast filter table:\n"); + + if (pMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("Table is not ready!\n")); + return; + } + + /* if FULL, return */ + if (pMulticastFilterTable->Size == 0) + { + printk(KERN_INFO "Table is empty.\n"); + return; + } + +#ifdef IGMP_MESH + printk(KERN_INFO "IGMP Clone Count(%d)\n", pAd->CloneCnt); +#endif /* IGMP_MESH */ + + /* allocate one MAC entry */ + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + for (i = 0; i< MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) + { + /* pick up the first available vacancy */ + if (pMulticastFilterTable->Content[i].Valid == TRUE) + { + PMEMBER_ENTRY pMemberEntry = NULL; + pEntry = &pMulticastFilterTable->Content[i]; + + printk(KERN_INFO "IF(%s) entry #%d, type=%s, GrpId=(%02x:%02x:%02x:%02x:%02x:%02x) memberCnt=%d\n", + RTMP_OS_NETDEV_GET_DEVNAME(pEntry->net_dev), i, (pEntry->type==0 ? "static":"dynamic"), + PRINT_MAC(pEntry->Addr), IgmpMemberCnt(&pEntry->MemberList)); + + pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead; + while (pMemberEntry) + { +#ifdef IGMP_MESH + pRoutingEntry = NULL; + + if(ISMWDSValid(pAd)) + { + pRoutingEntry = RoutingTabLookup(pAd, pMemberEntry->Addr, FALSE, &DadWcid); + + if((pRoutingEntry != NULL) && (VALID_WCID(DadWcid))) { + client_entry = &pAd->MacTab.Content[DadWcid]; + printk(KERN_INFO " Dad mac=(%02x:%02x:%02x:%02x:%02x:%02x) (%s) \n", + PRINT_MAC(client_entry->Addr), + ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, ROUTING_ENTRY_IGMP)?"IGMP":"NO_IGMP"); + + } + } +#endif /* IGMP_MESH */ + printk(KERN_INFO " member mac=(%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pMemberEntry->Addr)); + + pMemberEntry = pMemberEntry->pNext; + } + } + } + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + return; +} + +/* + ========================================================================== + Description: + Add and new entry into MAC table + ========================================================================== + */ +BOOLEAN MulticastFilterTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pGrpId, + IN PUCHAR pMemberAddr, + IN PNET_DEV dev, + IN MulticastFilterEntryType type) +{ + UCHAR HashIdx; + int i; + MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL, *pCurrEntry, *pPrevEntry; + PMEMBER_ENTRY pMemberEntry; + PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; + + if (pMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); + return FALSE; + } + + /* if FULL, return */ + if (pMulticastFilterTable->Size >= MAX_LEN_OF_MULTICAST_FILTER_TABLE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table full. max-entries = %d\n", + __FUNCTION__, MAX_LEN_OF_MULTICAST_FILTER_TABLE)); + return FALSE; + } + + /* check the rule is in table already or not. */ + if ((pEntry = MulticastFilterTableLookup(pAd, pMulticastFilterTable, pGrpId, dev))) + { + + if (pEntry && type == MCAT_FILTER_STATIC) + { + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + pEntry->type = MCAT_FILTER_STATIC; + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + } + + /* doesn't indicate member mac address. */ + if(pMemberAddr == NULL) + { + return FALSE; + } + + pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead; + + while (pMemberEntry) + { + if (MAC_ADDR_EQUAL(pMemberAddr, pMemberEntry->Addr)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: already in Members list.\n", __FUNCTION__)); + return FALSE; + } + + pMemberEntry = pMemberEntry->pNext; + } + } + + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + do + { + ULONG Now; + /* the multicast entry already exist but doesn't include the member yet. */ + if (pEntry != NULL && pMemberAddr != NULL) + { + InsertIgmpMember(pAd, pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); + break; + } + + /* allocate one MAC entry */ + for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) + { + /* pick up the first available vacancy */ + pEntry = &pMulticastFilterTable->Content[i]; + NdisGetSystemUpTime(&Now); + if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC) + && ((Now - pEntry->lastTime) > IGMPMAC_TB_ENTRY_AGEOUT_TIME)) + { + PMULTICAST_FILTER_TABLE_ENTRY pHashEntry; + + HashIdx = MULTICAST_ADDR_HASH_INDEX(pEntry->Addr); + pHashEntry = pMulticastFilterTable->Hash[HashIdx]; + + if ((pEntry->net_dev == pHashEntry->net_dev) + && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr)) + { + pMulticastFilterTable->Hash[HashIdx] = pHashEntry->pNext; + pMulticastFilterTable->Size --; + DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size)); + } else + { + while (pHashEntry->pNext) + { + pPrevEntry = pHashEntry; + pHashEntry = pHashEntry->pNext; + if ((pEntry->net_dev == pHashEntry->net_dev) + && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr)) + { + pPrevEntry->pNext = pHashEntry->pNext; + pMulticastFilterTable->Size --; + DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); + break; + } + } + } + pEntry->Valid = FALSE; + DeleteIgmpMemberList(pAd, pMulticastFilterTable, &pEntry->MemberList); + } + + if (pEntry->Valid == FALSE) + { + NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); + pEntry->Valid = TRUE; + + COPY_MAC_ADDR(pEntry->Addr, pGrpId); + pEntry->net_dev = dev; + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->type = type; + initList(&pEntry->MemberList); + if (pMemberAddr != NULL) + InsertIgmpMember(pAd, pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); + + pMulticastFilterTable->Size ++; + + DBGPRINT(RT_DEBUG_TRACE, ("MulticastFilterTableInsertEntry -IF(%s) allocate entry #%d, Total= %d\n", RTMP_OS_NETDEV_GET_DEVNAME(dev), i, pMulticastFilterTable->Size)); + break; + } + } + + /* add this MAC entry into HASH table */ + if (pEntry) + { + HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId); + if (pMulticastFilterTable->Hash[HashIdx] == NULL) + { + pMulticastFilterTable->Hash[HashIdx] = pEntry; + } else + { + pCurrEntry = pMulticastFilterTable->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + }while(FALSE); + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + return TRUE; +} + +/* + ========================================================================== + Description: + Delete a specified client from MAC table + ========================================================================== + */ +BOOLEAN MulticastFilterTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pGrpId, + IN PUCHAR pMemberAddr, + IN PNET_DEV dev, + IN MulticastFilterEntryType type) +{ + USHORT HashIdx; + MULTICAST_FILTER_TABLE_ENTRY *pEntry, *pPrevEntry; + PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; + + if (pMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); + return FALSE; + } + + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + do + { + HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId); + pPrevEntry = pEntry = pMulticastFilterTable->Hash[HashIdx]; + + while (pEntry && pEntry->Valid) + { + if ((pEntry->net_dev == dev) + && MAC_ADDR_EQUAL(pEntry->Addr, pGrpId)) + break; + else + { + pPrevEntry = pEntry; + pEntry = pEntry->pNext; + } + } + + /* check the rule is in table already or not. */ + if (pEntry && (pMemberAddr != NULL)) + { + DeleteIgmpMember(pAd, pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); + + if (IgmpMemberCnt(&pEntry->MemberList) > 0) + break; + } + + if (pEntry) + { + if ((pEntry->type == MCAT_FILTER_STATIC) && (type != MCAT_FILTER_STATIC)) + break; + + if (pEntry == pMulticastFilterTable->Hash[HashIdx]) + { + pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext; + DeleteIgmpMemberList(pAd, pMulticastFilterTable, &pEntry->MemberList); + NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); + pMulticastFilterTable->Size --; + DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size)); + } + else + { + pPrevEntry->pNext = pEntry->pNext; + DeleteIgmpMemberList(pAd, pMulticastFilterTable, &pEntry->MemberList); + NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); + pMulticastFilterTable->Size --; + DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: the Group doesn't exist.\n", __FUNCTION__)); + } + } while(FALSE); + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + return TRUE; +} + +/* + ========================================================================== + Description: + Look up the MAC address in the IGMP table. Return NULL if not found. + Return: + pEntry - pointer to the MAC entry; NULL is not found + ========================================================================== +*/ +PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PUCHAR pAddr, + IN PNET_DEV dev) +{ + ULONG HashIdx, Now; + PMULTICAST_FILTER_TABLE_ENTRY pEntry = NULL, pPrev = NULL; + + if (pMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + HashIdx = MULTICAST_ADDR_HASH_INDEX(pAddr); + pEntry = pPrev = pMulticastFilterTable->Hash[HashIdx]; + + while (pEntry && pEntry->Valid) + { + if ((pEntry->net_dev == dev) + && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + break; + } + else + { + NdisGetSystemUpTime(&Now); + if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC) + && RTMP_TIME_AFTER(Now, pEntry->lastTime+IGMPMAC_TB_ENTRY_AGEOUT_TIME)) + { + /* Remove the aged entry */ + if (pEntry == pMulticastFilterTable->Hash[HashIdx]) + { + pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext; + pPrev = pMulticastFilterTable->Hash[HashIdx]; + DeleteIgmpMemberList(pAd, pMulticastFilterTable, &pEntry->MemberList); + NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); + pMulticastFilterTable->Size --; + pEntry = pPrev; + DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); + } + else + { + pPrev->pNext = pEntry->pNext; + DeleteIgmpMemberList(pAd,pMulticastFilterTable, &pEntry->MemberList); + NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); + pMulticastFilterTable->Size --; + pEntry = pPrev->pNext; + DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); + } + } + else + { + pPrev = pEntry; + pEntry = pEntry->pNext; + } + } + } + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + return pEntry; +} + + +static inline BOOLEAN isIgmpMacAddr( + IN PUCHAR pMacAddr) +{ + if((pMacAddr[0] == 0x01) + && (pMacAddr[1] == 0x00) + && (pMacAddr[2] == 0x5e)) + return TRUE; + return FALSE; +} + + +BOOLEAN isIgmpPkt( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader) +{ + UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader))); + UCHAR IgmpProtocol; + + if(!isIgmpMacAddr(pDstMacAddr)) + return FALSE; + + if(IpProtocol == ETH_P_IP) + { + IgmpProtocol = (UCHAR)*(pIpHeader + 11); + if(IgmpProtocol == IGMP_PROTOCOL_DESCRIPTOR) + return TRUE; + } + + return FALSE; +} + + +VOID IGMPSnooping( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDstMacAddr, + IN PUCHAR pSrcMacAddr, + IN PUCHAR pIpHeader, + IN PNET_DEV pDev) +{ + INT i; + INT IpHeaderLen; + UCHAR GroupType; + UINT16 numOfGroup; + UCHAR IgmpVerType; + PUCHAR pIgmpHeader; + PUCHAR pGroup; + UCHAR AuxDataLen; + UINT16 numOfSources; + PUCHAR pGroupIpAddr; + UCHAR GroupMacAddr[6]; + PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; + + if(isIgmpPkt(pDstMacAddr, pIpHeader)) + { + IpHeaderLen = (*(pIpHeader + 2) & 0x0f) * 4; + pIgmpHeader = pIpHeader + 2 + IpHeaderLen; + IgmpVerType = (UCHAR)(*(pIgmpHeader)); + + DBGPRINT(RT_DEBUG_TRACE, ("IGMP type=%0x\n", IgmpVerType)); + + switch(IgmpVerType) + { + case IGMP_V1_MEMBERSHIP_REPORT: /* IGMP version 1 membership report. */ + case IGMP_V2_MEMBERSHIP_REPORT: /* IGMP version 2 membership report. */ + pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4); + ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); + DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n", + GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); + MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + + case IGMP_LEAVE_GROUP: /* IGMP version 1 and version 2 leave group. */ + pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4); + ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); + DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n", + GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); + MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + + case IGMP_V3_MEMBERSHIP_REPORT: /* IGMP version 3 membership report. */ + numOfGroup = ntohs(*((UINT16 *)(pIgmpHeader + 6))); + pGroup = (PUCHAR)(pIgmpHeader + 8); + for (i=0; i < numOfGroup; i++) + { + GroupType = (UCHAR)(*pGroup); + AuxDataLen = (UCHAR)(*(pGroup + 1)); + numOfSources = ntohs(*((UINT16 *)(pGroup + 2))); + pGroupIpAddr = (PUCHAR)(pGroup + 4); + DBGPRINT(RT_DEBUG_TRACE, ("IGMPv3 Type=%d, ADL=%d, numOfSource=%d\n", + GroupType, AuxDataLen, numOfSources)); + ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); + DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n", + GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], + GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); + + do + { + if ((GroupType == MODE_IS_EXCLUDE) + || (GroupType == CHANGE_TO_EXCLUDE_MODE) + || (GroupType == ALLOW_NEW_SOURCES)) + { + MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + } + + if ((GroupType == CHANGE_TO_INCLUDE_MODE) + || (GroupType == MODE_IS_INCLUDE) + || (GroupType == BLOCK_OLD_SOURCES)) + { + if(numOfSources == 0) + MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + else + MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + } + } while(FALSE); + pGroup += (8 + (numOfSources * 4) + AuxDataLen); + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("unknow IGMP Type=%d\n", IgmpVerType)); + break; + } + } + + return; +} + +static INT32 IPv6MulticastFilterExcluded( + IN PUCHAR pDstMacAddr); + + +static INT32 IPv4MulticastFilterExcluded( + IN PUCHAR pDstMacAddr) +{ + UINT32 DstIpAddr; + + if(!isIgmpMacAddr(pDstMacAddr)) + return -1; + + /* Check IGMP packet */ + if(*(pDstMacAddr + 23) == IGMP_PROTOCOL_DESCRIPTOR) + return 1; + + /* Get destination Ip address of IP header */ + DstIpAddr = ntohl(*((UINT32*)(pDstMacAddr + 30))); + + /* Check address is local multicast */ + if ((DstIpAddr & 0xffffff00) == 0xe0000000) + return 2; + + /* Check address is SSDP */ + if (DstIpAddr == 0xeffffffa) + return 2; + + return 0; +} + + +static VOID InsertIgmpMember( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList, + IN PUCHAR pMemberAddr) +{ + PMEMBER_ENTRY pMemberEntry; + + if(pList == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); + return; + } + + if (pMemberAddr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__)); + return; + } + + if((pMemberEntry = (PMEMBER_ENTRY)AllocaGrpMemberEntry(pMulticastFilterTable)) != NULL) + { + NdisZeroMemory(pMemberEntry, sizeof(MEMBER_ENTRY)); + COPY_MAC_ADDR(pMemberEntry->Addr, pMemberAddr); + insertTailList(pList, (PLIST_ENTRY)pMemberEntry); + +#ifdef IGMP_MESH + IgmpMeshTabUpdate(pAd, pMemberAddr); +#endif /* IGMP_MESH */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s Member Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, + pMemberEntry->Addr[0], pMemberEntry->Addr[1], pMemberEntry->Addr[2], + pMemberEntry->Addr[3], pMemberEntry->Addr[4], pMemberEntry->Addr[5])); + } + return; +} + +static VOID DeleteIgmpMember( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList, + IN PUCHAR pMemberAddr) +{ + PMEMBER_ENTRY pCurEntry; + + if (pList == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); + return; + } + + if (pList->pHead == NULL) + { + return; + } + + if (pMemberAddr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__)); + return; + } + + pCurEntry = (PMEMBER_ENTRY)pList->pHead; + while (pCurEntry) + { + PMEMBER_ENTRY pCurEntryNext = pCurEntry->pNext; + if(MAC_ADDR_EQUAL(pMemberAddr, pCurEntry->Addr)) + { + delEntryList(pList, (PLIST_ENTRY)pCurEntry); +#ifdef IGMP_MESH + IgmpMwdsEntryDelete(pAd, pMemberAddr); +#endif /* IGMP_MESH */ + FreeGrpMemberEntry(pMulticastFilterTable, pCurEntry); + break; + } + pCurEntry = pCurEntryNext; + } + + return; +} + +static VOID DeleteIgmpMemberList( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList) +{ + PMEMBER_ENTRY pCurEntry, pPrvEntry; + + if (pList == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); + return; + } + + if (pList->pHead == NULL) + { + return; + } + + pPrvEntry = pCurEntry = (PMEMBER_ENTRY)pList->pHead; + while (pCurEntry) + { + delEntryList(pList, (PLIST_ENTRY)pCurEntry); +#ifdef IGMP_MESH + IgmpMwdsEntryDelete(pAd, pCurEntry->Addr); +#endif /* IGMP_MESH */ + + pPrvEntry = pCurEntry; + pCurEntry = pCurEntry->pNext; + FreeGrpMemberEntry(pMulticastFilterTable, pPrvEntry); + } + + initList(pList); + return; +} + + +UCHAR IgmpMemberCnt( + IN PLIST_HEADER pList) +{ + if(pList == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); + return 0; + } + + return getListSize(pList); +} + +VOID IgmpGroupDelMembers( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMemberAddr, + IN PNET_DEV pDev) +{ + INT i; + MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL; + PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; + + for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) + { + /* pick up the first available vacancy */ + pEntry = &pMulticastFilterTable->Content[i]; + if (pEntry->Valid == TRUE) + { + if(pMemberAddr != NULL) + { + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + DeleteIgmpMember(pAd, pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + } + + if((pEntry->type == MCAT_FILTER_DYNAMIC) + && (IgmpMemberCnt(&pEntry->MemberList) == 0)) + MulticastFilterTableDeleteEntry(pAd, pEntry->Addr, pMemberAddr, pDev, MCAT_FILTER_DYNAMIC); + } + } +} + +INT Set_IgmpSn_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + + Enable = (UINT) simple_strtol(arg, 0, 10); + + pAd->ApCfg.IgmpSnoopEnable = (BOOLEAN)(Enable == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: %s\n", __FUNCTION__, Enable == TRUE ? "Enable IGMP Snooping":"Disable IGMP Snooping")); + + return TRUE; +} + +INT Set_IgmpSn_AddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + BOOLEAN bGroupId = 1; + PSTRING value; + PSTRING thisChar; + UCHAR IpAddr[4]; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR GroupId[MAC_ADDR_LEN]; + PUCHAR *pAddr = (PUCHAR *)&Addr; + PNET_DEV pDev; + POS_COOKIE pObj; + UCHAR ifIndex; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].wdev.if_dev); + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + /* refuse the Member if it's not a MAC address. */ + if((bGroupId == 0) && (strlen(thisChar) != 17)) + continue; + + if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &Addr[i++], 1); + } + + if(i != 6) + return FALSE; /*Invalid */ + } + else + { + for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,".")) + { + if((strlen(value) > 0) && (strlen(value) <= 3)) + { + int ii; + for(ii=0; iiOS_Cookie; + ifIndex = pObj->ioctl_if; + + pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].wdev.if_dev); + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + /* refuse the Member if it's not a MAC address. */ + if((bGroupId == 0) && (strlen(thisChar) != 17)) + continue; + + if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &Addr[i++], 1); + } + + if(i != 6) + return FALSE; /*Invalid */ + } + else + { + for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,".")) + { + if((strlen(value) > 0) && (strlen(value) <= 3)) + { + int ii; + for(ii=0; ii 0 ) + MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, Addr, pDev, MCAT_FILTER_STATIC); + + bGroupId = 0; + } + + if(memberCnt == 0) + MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, NULL, pDev, MCAT_FILTER_STATIC); + + DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X)\n", + __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5])); + + return TRUE; +} + +INT Set_IgmpSn_TabDisplay_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + IGMPTableDisplay(pAd); + return TRUE; +} + +void rtmp_read_igmp_snoop_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer) +{ + /*IgmpSnEnable */ + if(RTMPGetKeyParameter("IgmpSnEnable", tmpbuf, 128, buffer, TRUE)) + { + if ((strncmp(tmpbuf, "0", 1) == 0)) + pAd->ApCfg.IgmpSnoopEnable = FALSE; + else if ((strncmp(tmpbuf, "1", 1) == 0)) + pAd->ApCfg.IgmpSnoopEnable = TRUE; + else + pAd->ApCfg.IgmpSnoopEnable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, (" IGMP Snooping Enable=%d\n", pAd->ApCfg.IgmpSnoopEnable)); + } +} + +NDIS_STATUS IgmpPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN struct wifi_dev *wdev, + OUT INT *pInIgmpGroup, + OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry) +{ + if(IS_MULTICAST_MAC_ADDR(pSrcBufVA)) + { + INT32 ExcludedGroupType = -1; + UINT16 EtherType = ntohs(*((UINT16 *)(pSrcBufVA + 12))); + + if (EtherType == ETH_P_IPV6) + { + ExcludedGroupType = IPv6MulticastFilterExcluded(pSrcBufVA); + } + else if(EtherType == ETH_P_IP) + { + ExcludedGroupType = IPv4MulticastFilterExcluded(pSrcBufVA); + } + + if (ExcludedGroupType) + { + *ppGroupEntry = NULL; + + if (ExcludedGroupType == 1) + *pInIgmpGroup = IGMP_PKT; + } + else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd, pAd->pMulticastFilterTable, pSrcBufVA, + wdev->if_dev)) == NULL) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + else + *pInIgmpGroup = IGMP_IN_GROUP; + } + else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA)) + { + PUCHAR pDstIpAddr = pSrcBufVA + 30; /* point to Destination of Ip address of IP header. */ + UCHAR GroupMacAddr[6]; + PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; + + ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); + if ((*ppGroupEntry = MulticastFilterTableLookup(pAd, pAd->pMulticastFilterTable, pGroupMacAddr, + wdev->if_dev)) != NULL) + { + *pInIgmpGroup = IGMP_IN_GROUP; + } + } + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS IgmpPktClone( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN INT IgmpPktInGroup, + IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry, + IN UCHAR QueIdx, + IN UINT8 UserPriority) +{ + PNDIS_PACKET pSkbClone = NULL; + PMEMBER_ENTRY pMemberEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + USHORT Aid; + SST Sst = SST_ASSOC; + UCHAR PsMode = PWR_ACTIVE; + UCHAR Rate; + unsigned long IrqFlags; + INT MacEntryIdx; + BOOLEAN bContinue; + PUCHAR pMemberAddr = NULL; + PUCHAR src_addr = NULL; + PNET_DEV pNetDev = NULL; + BOOLEAN bClone; + +#ifdef IGMP_MESH + int i = 0; + USHORT clone_cnt = 0; + USHORT send_entry[MAX_NUMBER_OF_MAC]={0}; +#endif /* IGMP_MESH */ + + bContinue = FALSE; + bClone = TRUE; + + if (IgmpPktInGroup == IGMP_IN_GROUP) + { + if (!pGroupEntry) + return NDIS_STATUS_FAILURE; + + pMemberEntry = (PMEMBER_ENTRY)pGroupEntry->MemberList.pHead; + if (pMemberEntry != NULL) + { + pMemberAddr = pMemberEntry->Addr; + + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#ifdef IGMP_MESH + if (pMacEntry == NULL) + pMacEntry = IgmpMwdsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#endif /* IGMP_MESH */ + bContinue = TRUE; + } + } + else if (IgmpPktInGroup == IGMP_PKT) + { + pNetDev = GET_OS_PKT_NETDEV(pPacket); + src_addr = GET_OS_PKT_DATAPTR(pPacket) + 6; + + for(MacEntryIdx=1; MacEntryIdxMacTab.Content[MacEntryIdx].Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#ifdef IGMP_MESH + if (pMacEntry == NULL) + pMacEntry = IgmpMwdsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#endif /* IGMP_MESH */ + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) + && (get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev) + && (!NdisEqualMemory(src_addr, pMacEntry->Addr, MAC_ADDR_LEN))) + { + pMemberAddr = pMacEntry->Addr; + bContinue = TRUE; + break; + } + } + } + else + { + return NDIS_STATUS_FAILURE; + } + + /* check all members of the IGMP group. */ + while(bContinue == TRUE) + { + if (pMacEntry && (Sst == SST_ASSOC) && (pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + if (bClone) + { + OS_PKT_CLONE(pAd, pPacket, pSkbClone, MEM_ALLOC_FLAG); + if ((pSkbClone) +#ifdef DOT11V_WNM_SUPPORT + && (pMacEntry->Beclone == FALSE) +#endif /* DOT11V_WNM_SUPPORT */ + ) + { + RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)pMacEntry->Aid); + } + else + { +#ifdef DOT11V_WNM_SUPPORT + pMacEntry->Beclone = FALSE; +#endif /* DOT11V_WNM_SUPPORT */ + goto next_iteration; + } + + if (PsMode == PWR_SAVE) + { + APInsertPsQueue(pAd, pSkbClone, pMacEntry, QueIdx); +#ifdef IGMP_MESH + clone_cnt++; +#endif /* IGMP_MESH */ + } + else + { + /* insert the pkt to TxSwQueue. */ +#ifdef DATA_QUEUE_RESERVE + if (!(RTMP_GET_PACKET_DHCP(pPacket) || RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_ICMP(pPacket)) + && (pAd->TxSwQueue[QueIdx].Number >= (pAd->TxSwQMaxLen - pAd->TxRsvLen))) +#else /* DATA_QUEUE_RESERVE */ + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) +#endif /* !DATA_QUEUE_RESERVE */ + { +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pSkbClone); +#endif /* BLOCK_NET_IF */ +#ifdef IGMP_MESH + clone_cnt = 0xFF; +#endif /* IGMP_MESH */ + RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + else + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pSkbClone)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#ifdef IGMP_MESH + clone_cnt++; + send_entry[i++] = Aid; +#endif /* IGMP_MESH */ + } + } +#ifdef DOT11_N_SUPPORT + RTMP_BASetup(pAd, pMacEntry, UserPriority); +#endif /* DOT11_N_SUPPORT */ + } + } + +next_iteration: + + if (IgmpPktInGroup == IGMP_IN_GROUP) + { + pMemberEntry = pMemberEntry->pNext; + if (pMemberEntry != NULL) + { + pMemberAddr = pMemberEntry->Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#ifdef IGMP_MESH + if (pMacEntry == NULL) + pMacEntry = IgmpMwdsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + + if (Aid != MCAST_WCID) + bClone = isNeedClone(send_entry, pGroupEntry->MemberList.size, Aid); +#endif /* IGMP_MESH */ + bContinue = TRUE; + } + else + bContinue = FALSE; + } + else + { + for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdxMacTab.Content[MacEntryIdx].Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#ifdef IGMP_MESH + if (pMacEntry == NULL) + pMacEntry = IgmpMwdsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); +#endif /* IGMP_MESH */ + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) + && (get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev) + && (!NdisEqualMemory(src_addr, pMacEntry->Addr, MAC_ADDR_LEN))) + { + pMemberAddr = pMacEntry->Addr; + bContinue = TRUE; + bClone = TRUE; + break; + } + } + if (MacEntryIdx == MAX_NUMBER_OF_MAC) + bContinue = FALSE; + } + } + +#ifdef IGMP_MESH + pAd->CloneCnt = clone_cnt; +#endif /* IGMP_MESH */ + + return NDIS_STATUS_SUCCESS; +} + +static inline BOOLEAN isMldMacAddr( + IN PUCHAR pMacAddr) +{ + return ((pMacAddr[0] == 0x33) && (pMacAddr[1] == 0x33)) ? TRUE : FALSE; +} + +static inline BOOLEAN IsSupportedMldMsg( + IN UINT8 MsgType) +{ + BOOLEAN result = FALSE; + switch(MsgType) + { + case MLD_V1_LISTENER_REPORT: + case MLD_V1_LISTENER_DONE: + case MLD_V2_LISTERNER_REPORT: + result = TRUE; + break; + default: + result = FALSE; + break; + } + + return result; +} + +BOOLEAN isMldPkt( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader, + OUT UINT8 *pProtoType, + OUT PUCHAR *pMldHeader) +{ + BOOLEAN result = FALSE; + UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader))); + + if(!isMldMacAddr(pDstMacAddr)) + return FALSE; + + if(IpProtocol != ETH_P_IPV6) + return FALSE; + + /* skip protocol (2 Bytes). */ + pIpHeader += 2; + do + { + PRT_IPV6_HDR pIpv6Hdr = (PRT_IPV6_HDR)(pIpHeader); + UINT8 nextProtocol = pIpv6Hdr->nextHdr; + UINT32 offset = IPV6_HDR_LEN; + + while(nextProtocol != IPV6_NEXT_HEADER_ICMPV6) + { + if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pIpHeader + offset), &nextProtocol, &offset) == FALSE) + break; + } + + if(nextProtocol == IPV6_NEXT_HEADER_ICMPV6) + { + PRT_ICMPV6_HDR pICMPv6Hdr = (PRT_ICMPV6_HDR)(pIpHeader + offset); + if (IsSupportedMldMsg(pICMPv6Hdr->type) == TRUE) + { + if (pProtoType != NULL) + *pProtoType = pICMPv6Hdr->type; + if (pMldHeader != NULL) + *pMldHeader = (PUCHAR)pICMPv6Hdr; + result = TRUE; + } + } + }while(FALSE); + + return result; +} + +static inline int IPv6_Transient_Multicast( + IN PRT_IPV6_ADDR pIpv6Addr) +{ + if ((pIpv6Addr->ipv6_addr32[0] & htonl(0xFF100000)) == htonl(0xFF100000)) + return 1; + + return 0; +} + +static INT32 IPv6MulticastFilterExcluded( + IN PUCHAR pDstMacAddr) +{ + PUCHAR pIpHeader; + PRT_IPV6_HDR pIpv6Hdr; + UINT32 offset; + INT idx; + UINT8 nextProtocol; + + if(!IS_IPV6_MULTICAST_MAC_ADDR(pDstMacAddr)) + return -1; + + pIpHeader = pDstMacAddr + 14; + pIpv6Hdr = (PRT_IPV6_HDR)(pIpHeader); + offset = IPV6_HDR_LEN; + nextProtocol = pIpv6Hdr->nextHdr; + while(nextProtocol == IPV6_NEXT_HEADER_HOP_BY_HOP) + { + if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pIpHeader + offset), &nextProtocol, &offset) == FALSE) + break; + } + + if (nextProtocol == IPV6_NEXT_HEADER_ICMPV6) + { + PRT_ICMPV6_HDR pICMPv6Hdr = (PRT_ICMPV6_HDR)(pIpHeader + offset); + + switch (pICMPv6Hdr->type) + { + case MLD_QUERY: + case MLD_V1_LISTENER_REPORT: + case MLD_V1_LISTENER_DONE: + case MLD_V2_LISTERNER_REPORT: + return 1; + } + } + + for (idx = 0; idx < IPV6_MULTICAST_FILTER_EXCLUED_SIZE; idx++) + { + if (nextProtocol == IPv6MulticastFilterExclued[idx]) + return 2; + } + + /* Check non-transient multicast */ + if (!IPv6_Transient_Multicast(&pIpv6Hdr->dstAddr)) + return 2; + + return 0; +} + +/* MLD v1 messages have the following format: + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Maximum Response Delay | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Multicast Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/* Version 3 Membership Report Message + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type = 143 | Reserved | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | Number of Group Records (M) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Multicast Address Record [1] . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Multicast Address Record [2] . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | . | + . . . + | . | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Multicast Address Record [M] . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + where each Group Record has the following internal format: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Record Type | Aux Data Len | Number of Sources (N) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + * * + | | + * Multicast Address * + | | + * * + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + * * + | | + * Source Address [1] * + | | + * * + | | + +- -+ + | | + * * + | | + * Source Address [2] * + | | + * * + | | + +- -+ + . . . + . . . + . . . + +- -+ + | | + * * + | | + * Source Address [N] * + | | + * * + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Auxiliary Data . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +VOID MLDSnooping( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDstMacAddr, + IN PUCHAR pSrcMacAddr, + IN PUCHAR pIpHeader, + IN PNET_DEV pDev) +{ + INT i; + UCHAR GroupType; + UINT16 numOfGroup; + PUCHAR pGroup; + UCHAR AuxDataLen; + UINT16 numOfSources; + PUCHAR pGroupIpAddr; + UCHAR GroupMacAddr[6]; + PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; + + UINT8 MldType; + PUCHAR pMldHeader; + + if(isMldPkt(pDstMacAddr, pIpHeader, &MldType, &pMldHeader) == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("MLD type=%0x\n", MldType)); + + switch(MldType) + { + case MLD_V1_LISTENER_REPORT: + /* skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes). */ + pGroupIpAddr = (PUCHAR)(pMldHeader + 8); + ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6); + DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n", + GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); + MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + + case MLD_V1_LISTENER_DONE: + /* skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes). */ + pGroupIpAddr = (PUCHAR)(pMldHeader + 8); + ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6); + DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n", + GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); + MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + + case MLD_V2_LISTERNER_REPORT: /* IGMP version 3 membership report. */ + numOfGroup = ntohs(*((UINT16 *)(pMldHeader + 6))); + pGroup = (PUCHAR)(pMldHeader + 8); + for (i=0; i < numOfGroup; i++) + { + GroupType = (UCHAR)(*pGroup); + AuxDataLen = (UCHAR)(*(pGroup + 1)); + numOfSources = ntohs(*((UINT16 *)(pGroup + 2))); + pGroupIpAddr = (PUCHAR)(pGroup + 4); + DBGPRINT(RT_DEBUG_TRACE, ("MLDv2 Type=%d, ADL=%d, numOfSource=%d\n", + GroupType, AuxDataLen, numOfSources)); + ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6); + DBGPRINT(RT_DEBUG_TRACE, ("MLD Group=%02x:%02x:%02x:%02x:%02x:%02x\n", + GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], + GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); + + do + { + if ((GroupType == MODE_IS_EXCLUDE) + || (GroupType == CHANGE_TO_EXCLUDE_MODE) + || (GroupType == ALLOW_NEW_SOURCES)) + { + MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + } + + if ((GroupType == CHANGE_TO_INCLUDE_MODE) + || (GroupType == MODE_IS_INCLUDE) + || (GroupType == BLOCK_OLD_SOURCES)) + { + if(numOfSources == 0) + MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + else + MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); + break; + } + } while(FALSE); + /* skip 4 Bytes (Record Type, Aux Data Len, Number of Sources) + a IPv6 address. */ + pGroup += (4 + IPV6_ADDR_LEN + (numOfSources * 16) + AuxDataLen); + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("unknow MLD Type=%d\n", MldType)); + break; + } + } + + return; +} + +#ifdef IGMP_MESH +static BOOLEAN isNeedClone( + //INOUT PMEMBER_ENTRY entry, + IN PUSHORT send_table, + IN UCHAR size, + IN USHORT Aid) +{ + int i; + BOOLEAN bSent = FALSE; + + for (i = 0; i < size ; i++) + { + if (send_table[i] == Aid) + { + bSent = TRUE; + break; + } + } + + if (!bSent) + return TRUE; + + return FALSE; +} + +VOID IgmpMeshTabUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac) +{ + UCHAR ProxyAPWcid = 0; + BOOLEAN bFound = FALSE; + PROUTING_ENTRY pRoutingEntry = NULL; + + if(!ISMWDSValid(pAd)) + return; + + if(!pMac) + return; + + pRoutingEntry = RoutingTabLookup(pAd, pMac, TRUE, &ProxyAPWcid); + bFound = (pRoutingEntry != NULL)?TRUE:FALSE; + + if(bFound) + { + /* Assign MWDS falg to this one if found. */ + SET_ROUTING_ENTRY(pRoutingEntry, ROUTING_ENTRY_IGMP); + } +} + + + + +VOID IgmpMwdsEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac) +{ + PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; + + if(RoutingTabGetEntryCount(pAd) == 0) + return; + + RoutingTabSetOneFree(pAd, pMac, ROUTING_ENTRY_IGMP); +} + +MAC_TABLE_ENTRY *IgmpMwdsInquiry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR Wcid; + + if (MWDSProxyLookup(pAd, pAddr, FALSE, &Wcid)) + { + if (VALID_WCID(Wcid)) + pEntry = &pAd->MacTab.Content[Wcid]; + } + + if (pEntry) + { + *Sst = pEntry->Sst; + *Aid = pEntry->Aid; + *PsMode = pEntry->PsMode; + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEntry->GTKState != REKEY_ESTABLISHED)) + *Rate = pAd->CommonCfg.MlmeRate; + else + *Rate = pEntry->CurrTxRate; + } + else + { + *Sst = SST_NOT_AUTH; + *Aid = MCAST_WCID; + *PsMode = PWR_ACTIVE; + *Rate = pAd->CommonCfg.MlmeRate; + } + return pEntry; +} + +VOID IgmpMwdsTableReset( + IN PRTMP_ADAPTER pAd) +{ + RoutingTabDestory(pAd, ROUTING_ENTRY_IGMP); +} + + +#endif /* IGMP_MESH */ +#endif /* IGMP_SNOOP_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/misc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/misc.c new file mode 100644 index 000000000..72ca95604 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/misc.c @@ -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" + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/mlme.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/mlme.c new file mode 100644 index 000000000..ff35ec6ed --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/mlme.c @@ -0,0 +1,7553 @@ +/* + *************************************************************************** + * 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: + mlme.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" +#include +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#include "wnm.h" +#endif /* DOT11V_WNM_SUPPORT */ + +UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; +UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; +UCHAR MTK_OUI[] = {0x00, 0x0c, 0xe7}; +UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; +UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac}; +UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72}; +UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; +UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; +UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c}; +UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT +UCHAR IWSC_OUI[] = {0x00, 0x50, 0xf2, 0x10}; +UCHAR IWSC_ACTION_OUI[] = {0x50, 0x6F, 0x9A, 0x10}; +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +UCHAR OfdmRateToRxwiMCS[12] = { + 0, 0, 0, 0, + 0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */ + 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */ +}; + +UCHAR RxwiMCSToOfdmRate[12] = { + RATE_6, RATE_9, RATE_12, RATE_18, + RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */ + 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */ +}; + + + + + +/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.*/ +/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate*/ +ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */, + 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */, + 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */}; + +UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than*/ +/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in*/ +/* clean environment.*/ +/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100*/ +CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; + +UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100}; +USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200}; + +UCHAR SsidIe = IE_SSID; +UCHAR SupRateIe = IE_SUPP_RATES; +UCHAR ExtRateIe = IE_EXT_SUPP_RATES; +#ifdef DOT11_N_SUPPORT +UCHAR HtCapIe = IE_HT_CAP; +UCHAR AddHtInfoIe = IE_ADD_HT; +UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET; +UCHAR BssCoexistIe = IE_2040_BSS_COEXIST; +UCHAR ExtHtCapIe = IE_EXT_CAPABILITY; +#endif /* DOT11_N_SUPPORT */ +UCHAR ExtCapIe = IE_EXT_CAPABILITY; +UCHAR ErpIe = IE_ERP; +UCHAR DsIe = IE_DS_PARM; +UCHAR TimIe = IE_TIM; +UCHAR WpaIe = IE_WPA; +UCHAR Wpa2Ie = IE_WPA2; +UCHAR IbssIe = IE_IBSS_PARM; +UCHAR WapiIe = IE_WAPI; + +extern UCHAR WPA_OUI[]; + +UCHAR SES_OUI[] = {0x00, 0x90, 0x4c}; + +UCHAR 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}; + + + +#ifdef MT76x2 +#ifdef CONFIG_STA_SUPPORT +#ifdef DYNAMIC_VGA_SUPPORT +void periodic_monitor_rssi_adjust_vga(RTMP_ADAPTER *pAd) +{ + if ((pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable) && + (pAd->chipCap.dynamic_vga_support) && INFRA_ON(pAd)) { + UINT32 bbp_val1 = 0, bbp_val2 = 0; + + if(pAd->ed_chk!=FALSE && pAd->chipCap.avg_rssi_all >= -45) + { + andes_dynamic_vga(pAd, pAd->CommonCfg.Channel, FALSE, FALSE, + -46, pAd->RalinkCounters.OneSecFalseCCACnt); + } + else + { + andes_dynamic_vga(pAd, pAd->CommonCfg.Channel, FALSE, FALSE, + pAd->chipCap.avg_rssi_all, pAd->RalinkCounters.OneSecFalseCCACnt); + } + + RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val1); + RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val2); + + DBGPRINT(RT_DEBUG_INFO, ("%s::0x2320=0x%08x, 0x2324=0x%08x\n", + __FUNCTION__, bbp_val1, bbp_val2)); + } +} +#endif /* DYNAMIC_VGA_SUPPORT */ + +void periodic_check_channel_smoothing(RTMP_ADAPTER *ad) +{ + UINT32 bbp_value; + CHAR Rssi = RTMPAvgRssi(ad, &ad->StaCfg.RssiSample); + + if (Rssi < -50) { + if (!ad->chipCap.chl_smth_enable) { + RTMP_BBP_IO_READ32(ad, 0x2948, &bbp_value); + bbp_value &= ~(0x1); + bbp_value |= (0x1); + RTMP_BBP_IO_WRITE32(ad, 0x2948, bbp_value); + + RTMP_BBP_IO_READ32(ad, 0x2944, &bbp_value); + bbp_value &= ~(0x1); + RTMP_BBP_IO_WRITE32(ad, 0x2944, bbp_value); + + ad->chipCap.chl_smth_enable = TRUE; + } + } else { + if (ad->chipCap.chl_smth_enable) { + RTMP_BBP_IO_READ32(ad, 0x2948, &bbp_value); + bbp_value &= ~(0x1); + RTMP_BBP_IO_WRITE32(ad, 0x2948, bbp_value); + + RTMP_BBP_IO_READ32(ad, 0x2944, &bbp_value); + bbp_value &= ~(0x1); + bbp_value |= (0x1); + RTMP_BBP_IO_WRITE32(ad, 0x2944, bbp_value); + + ad->chipCap.chl_smth_enable = FALSE; + } + } +} +#endif +#endif + +VOID set_default_ap_edca_param(RTMP_ADAPTER *pAd) +{ + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = 94; + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID set_default_sta_edca_param(RTMP_ADAPTER *pAd) +{ + pAd->ApCfg.BssEdcaParm.bValid = TRUE; + pAd->ApCfg.BssEdcaParm.Aifsn[0] = 3; + pAd->ApCfg.BssEdcaParm.Aifsn[1] = 7; + pAd->ApCfg.BssEdcaParm.Aifsn[2] = 2; + pAd->ApCfg.BssEdcaParm.Aifsn[3] = 2; + + pAd->ApCfg.BssEdcaParm.Cwmin[0] = 4; + pAd->ApCfg.BssEdcaParm.Cwmin[1] = 4; + pAd->ApCfg.BssEdcaParm.Cwmin[2] = 3; + pAd->ApCfg.BssEdcaParm.Cwmin[3] = 2; + + pAd->ApCfg.BssEdcaParm.Cwmax[0] = 10; + pAd->ApCfg.BssEdcaParm.Cwmax[1] = 10; + pAd->ApCfg.BssEdcaParm.Cwmax[2] = 4; + pAd->ApCfg.BssEdcaParm.Cwmax[3] = 3; + + pAd->ApCfg.BssEdcaParm.Txop[0] = 0; + pAd->ApCfg.BssEdcaParm.Txop[1] = 0; + pAd->ApCfg.BssEdcaParm.Txop[2] = 94; /*96; */ + pAd->ApCfg.BssEdcaParm.Txop[3] = 47; /*48; */ +} +#endif /* CONFIG_AP_SUPPORT */ + + +UCHAR dot11_max_sup_rate(INT SupRateLen, UCHAR *SupRate, INT ExtRateLen, UCHAR *ExtRate) +{ + INT idx; + UCHAR MaxSupportedRateIn500Kbps = 0; + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (idx = 0; idx < SupRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f; + } + + if (ExtRateLen > 0 && ExtRate != NULL) + { + for (idx = 0; idx < ExtRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f; + } + } + + return MaxSupportedRateIn500Kbps; +} + + +UCHAR dot11_2_ra_rate(UCHAR MaxSupportedRateIn500Kbps) +{ + UCHAR MaxSupportedRate; + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + return MaxSupportedRate; +} + + +/* + ========================================================================== + Description: + main loop of the MLME + Pre: + Mlme has to be initialized, and there are something inside the queue + Note: + This function is invoked from MPSetInformation and MPReceive; + This task guarantee only one FSM will run. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeHandler(RTMP_ADAPTER *pAd) +{ + MLME_QUEUE_ELEM *Elem = NULL; +#ifdef APCLI_SUPPORT + SHORT apcliIfIndex; +#endif /* APCLI_SUPPORT */ + + /* Only accept MLME and Frame from peer side, no other (control/data) frame should*/ + /* get into this state machine*/ + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } + else + { + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + + while (!MlmeQueueEmpty(&pAd->Mlme.Queue) +#ifdef EAPOL_QUEUE_SUPPORT + || !(EAPMlmeQueueEmpty(&pAd->Mlme.EAP_Queue)) +#endif /* EAPOL_QUEUE_SUPPORT */ + ) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND)) + { + DBGPRINT(RT_DEBUG_TRACE, ("System halted, removed or MlmeRest, exit MlmeTask!(QNum = %ld)\n", + pAd->Mlme.Queue.Num)); + break; + } + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Driver is in ATE mode\n", __FUNCTION__)); + break; + } +#endif /* RALINK_ATE */ + + /*From message type, determine which state machine I should drive*/ + + Elem = NULL; +#ifdef EAPOL_QUEUE_SUPPORT + if (!EAPMlmeQueueEmpty(&pAd->Mlme.EAP_Queue)) + EAPMlmeDequeue(&pAd->Mlme.EAP_Queue, &Elem); + else if (!MlmeQueueEmpty(&pAd->Mlme.Queue)) +#endif /* EAPOL_QUEUE_SUPPORT */ + MlmeDequeue(&pAd->Mlme.Queue, &Elem); + + if (Elem) + { + + if (Elem->Machine == WPA_STATE_MACHINE && Elem->MsgType == MT2_EAPOLKey) + { + if (((!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) && + ( !OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))) +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + && !(RTMP_CFG80211_VIF_P2P_GO_ON(pAd) || RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + ) + { +#ifdef EAPOL_QUEUE_SUPPORT + EAP_MLME_QUEUE *Queue = (EAP_MLME_QUEUE *)&pAd->Mlme.EAP_Queue; +#else /* EAPOL_QUEUE_SUPPORT */ + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; +#endif /* !EAPOL_QUEUE_SUPPORT */ + ULONG Tail; + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Elem->Machine; + Queue->Entry[Tail].MsgType = Elem->MsgType; + Queue->Entry[Tail].MsgLen = Elem->MsgLen; + Queue->Entry[Tail].Priv = Elem->Priv; + NdisZeroMemory(Queue->Entry[Tail].Msg, MGMT_DMA_BUFFER_SIZE); + if (Elem->Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Elem->Msg, Elem->MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + continue; + + } + } + + + /* if dequeue success*/ + switch (Elem->Machine) + { + /* STA state machines*/ +#ifdef CONFIG_STA_SUPPORT + case ASSOC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, + Elem, pAd->Mlme.AssocMachine.CurrState); + break; + + case AUTH_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, + Elem, pAd->Mlme.AuthMachine.CurrState); + break; + + case AUTH_RSP_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, + Elem, pAd->Mlme.AuthRspMachine.CurrState); + break; + + case SYNC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, + Elem, pAd->Mlme.SyncMachine.CurrState); + break; + + case MLME_CNTL_STATE_MACHINE: + MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem); + break; + + case WPA_PSK_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, + Elem, pAd->Mlme.WpaPskMachine.CurrState); + break; + +#ifdef QOS_DLS_SUPPORT + case DLS_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, + Elem, pAd->Mlme.DlsMachine.CurrState); + break; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + case FT_OTA_AUTH_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.FtOtaAuthMachine, + Elem, pAd->Mlme.FtOtaAuthMachine.CurrState); + break; + + case FT_OTD_ACT_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.FtOtdActMachine, + Elem, pAd->Mlme.FtOtdActMachine.CurrState); + break; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + case TDLS_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.TdlsMachine, + Elem, pAd->Mlme.TdlsMachine.CurrState); + break; +#endif /* DOT11Z_TDLS_SUPPORT */ + + +#endif /* CONFIG_STA_SUPPORT */ + + case ACTION_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, + Elem, pAd->Mlme.ActMachine.CurrState); + break; + +#ifdef CONFIG_AP_SUPPORT + /* AP state amchines*/ + + case AP_ASSOC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ApAssocMachine, + Elem, pAd->Mlme.ApAssocMachine.CurrState); + break; + + case AP_AUTH_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ApAuthMachine, + Elem, pAd->Mlme.ApAuthMachine.CurrState); + break; + + case AP_SYNC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ApSyncMachine, + Elem, pAd->Mlme.ApSyncMachine.CurrState); + break; + +#ifdef APCLI_SUPPORT + case APCLI_AUTH_STATE_MACHINE: + apcliIfIndex = Elem->Priv; +#ifdef MAC_REPEATER_SUPPORT + if (apcliIfIndex >= 64) + apcliIfIndex = ((apcliIfIndex - 64) / 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if(isValidApCliIf(apcliIfIndex)) + { + ULONG AuthCurrState; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0; + + apcliIfIndex = Elem->Priv; + + if (apcliIfIndex >= 64) + { + CliIdx = ((apcliIfIndex - 64) % 16); + apcliIfIndex = ((apcliIfIndex - 64) / 16); + + AuthCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + AuthCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].AuthCurrState; + + StateMachinePerformAction(pAd, &pAd->Mlme.ApCliAuthMachine, + Elem, AuthCurrState); + } + break; + + case APCLI_ASSOC_STATE_MACHINE: + apcliIfIndex = Elem->Priv; +#ifdef MAC_REPEATER_SUPPORT + if (apcliIfIndex >= 64) + apcliIfIndex = ((apcliIfIndex - 64) / 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if(isValidApCliIf(apcliIfIndex)) + { + ULONG AssocCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].AssocCurrState; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0; + + apcliIfIndex = Elem->Priv; + + if (apcliIfIndex >= 64) + { + CliIdx = ((apcliIfIndex - 64) % 16); + apcliIfIndex = ((apcliIfIndex - 64) / 16); + AssocCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].AssocCurrState; + } +#endif /* MAC_REPEATER_SUPPORT */ + StateMachinePerformAction(pAd, &pAd->Mlme.ApCliAssocMachine, + Elem, AssocCurrState); + } + break; + + case APCLI_SYNC_STATE_MACHINE: + apcliIfIndex = Elem->Priv; + if(isValidApCliIf(apcliIfIndex)) + StateMachinePerformAction(pAd, &pAd->Mlme.ApCliSyncMachine, Elem, + (pAd->ApCfg.ApCliTab[apcliIfIndex].SyncCurrState)); + break; + + case APCLI_CTRL_STATE_MACHINE: + apcliIfIndex = Elem->Priv; +#ifdef MAC_REPEATER_SUPPORT + if (apcliIfIndex >= 64) + apcliIfIndex = ((apcliIfIndex - 64) / 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if(isValidApCliIf(apcliIfIndex)) + { + ULONG CtrlCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].CtrlCurrState; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0; + + apcliIfIndex = Elem->Priv; + + if (apcliIfIndex >= 64) + { + CliIdx = ((apcliIfIndex - 64) % 16); + apcliIfIndex = ((apcliIfIndex - 64) / 16); + CtrlCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].CtrlCurrState; + } +#endif /* MAC_REPEATER_SUPPORT */ + StateMachinePerformAction(pAd, &pAd->Mlme.ApCliCtrlMachine, Elem, CtrlCurrState); + } + break; +#endif /* APCLI_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + case WPA_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem, pAd->Mlme.WpaMachine.CurrState); + break; +#ifdef WSC_INCLUDED + case WSC_STATE_MACHINE: + if (pAd->pWscElme) + { + RTMP_SEM_LOCK(&pAd->WscElmeLock); + NdisMoveMemory(pAd->pWscElme, Elem, sizeof(MLME_QUEUE_ELEM)); + RTMP_SEM_UNLOCK(&pAd->WscElmeLock); + RtmpOsTaskWakeUp(&(pAd->wscTask)); + } + break; +#ifdef IWSC_SUPPORT + case IWSC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.IWscMachine, Elem, pAd->Mlme.IWscMachine.CurrState); + break; +#endif /* IWSC_SUPPORT */ +#endif /* WSC_INCLUDED */ + + + +#ifdef CONFIG_HOTSPOT + case HSCTRL_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.HSCtrlMachine, Elem, + HSCtrlCurrentState(pAd, Elem)); + break; +#endif + +#ifdef CONFIG_DOT11U_INTERWORKING + case GAS_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.GASMachine, Elem, + GASPeerCurrentState(pAd, Elem)); + break; +#endif +#ifdef CONFIG_DOT11V_WNM + case BTM_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.BTMMachine, Elem, + BTMPeerCurrentState(pAd, Elem)); + break; +#ifdef CONFIG_HOTSPOT_R2 + case WNM_NOTIFY_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WNMNotifyMachine, Elem, + WNMNotifyPeerCurrentState(pAd, Elem)); + break; +#endif +#endif + + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Illegal SM %ld\n", + __FUNCTION__, Elem->Machine)); + break; + } /* end of switch*/ + + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("%s(): MlmeQ empty\n", __FUNCTION__)); + } + } + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +} + + +/* +======================================================================== +Routine Description: + MLME kernel thread. + +Arguments: + Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +static INT MlmeThread(ULONG Context) +{ + RTMP_ADAPTER *pAd; + RTMP_OS_TASK *pTask; + int status; + status = 0; + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + if (pAd == NULL) + goto LabelExit; + + RtmpOSTaskCustomize(pTask); + + while (!RTMP_OS_TASK_IS_KILLED(pTask)) + { + if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + /* lock the device pointers , need to check if required*/ + /*down(&(pAd->usbdev_semaphore)); */ + + if (!pAd->PM_FlgSuspend) + MlmeHandler(pAd); + } + + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ +LabelExit: + DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + RtmpOSTaskNotifyToExit(pTask); + return 0; + +} + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +static VOID ApCliMlmeInit(RTMP_ADAPTER *pAd) +{ + /* init apcli state machines*/ + ASSERT(APCLI_AUTH_FUNC_SIZE == APCLI_MAX_AUTH_MSG * APCLI_MAX_AUTH_STATE); + ApCliAuthStateMachineInit(pAd, &pAd->Mlme.ApCliAuthMachine, pAd->Mlme.ApCliAuthFunc); + + ASSERT(APCLI_ASSOC_FUNC_SIZE == APCLI_MAX_ASSOC_MSG * APCLI_MAX_ASSOC_STATE); + ApCliAssocStateMachineInit(pAd, &pAd->Mlme.ApCliAssocMachine, pAd->Mlme.ApCliAssocFunc); + + ASSERT(APCLI_SYNC_FUNC_SIZE == APCLI_MAX_SYNC_MSG * APCLI_MAX_SYNC_STATE); + ApCliSyncStateMachineInit(pAd, &pAd->Mlme.ApCliSyncMachine, pAd->Mlme.ApCliSyncFunc); + + ASSERT(APCLI_CTRL_FUNC_SIZE == APCLI_MAX_CTRL_MSG * APCLI_MAX_CTRL_STATE); + ApCliCtrlStateMachineInit(pAd, &pAd->Mlme.ApCliCtrlMachine, pAd->Mlme.ApCliCtrlFunc); +} +#endif /* APCLI_SUPPORT */ + +static VOID ApMlmeInit(RTMP_ADAPTER *pAd) +{ + /* init AP state machines*/ + APAssocStateMachineInit(pAd, &pAd->Mlme.ApAssocMachine, pAd->Mlme.ApAssocFunc); + APAuthStateMachineInit(pAd, &pAd->Mlme.ApAuthMachine, pAd->Mlme.ApAuthFunc); + APSyncStateMachineInit(pAd, &pAd->Mlme.ApSyncMachine, pAd->Mlme.ApSyncFunc); +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ========================================================================== + Description: + initialize the MLME task and its data structure (queue, spinlock, + timer, state machines). + + IRQL = PASSIVE_LEVEL + + Return: + always return NDIS_STATUS_SUCCESS + + ========================================================================== +*/ +NDIS_STATUS MlmeInit(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); + + do + { + +#ifdef EAPOL_QUEUE_SUPPORT + Status = MlmeQueueInit(pAd, &pAd->Mlme.EAP_Queue, &pAd->Mlme.Queue); +#else /* EAPOL_QUEUE_SUPPORT */ + Status = MlmeQueueInit(pAd, &pAd->Mlme.Queue); +#endif /* !EAPOL_QUEUE_SUPPORT */ + + if(Status != NDIS_STATUS_SUCCESS) + break; + + pAd->Mlme.bRunning = FALSE; + NdisAllocateSpinLock(pAd, &pAd->Mlme.TaskLock); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + BssTableInit(&pAd->ScanTab); + + /* init STA state machines*/ + AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc); + AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc); + AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc); + SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc); + +#ifdef QOS_DLS_SUPPORT + DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + TDLS_StateMachineInit(pAd, &pAd->Mlme.TdlsMachine, pAd->Mlme.TdlsFunc); +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef WSC_STA_SUPPORT +#ifdef IWSC_SUPPORT + IWSC_StateMachineInit(pAd, &pAd->Mlme.IWscMachine, pAd->Mlme.IWscFunc); +#endif /* IWSC_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_OTA_AuthStateMachineInit(pAd, &pAd->Mlme.FtOtaAuthMachine, pAd->Mlme.FtOtaAuthFunc); + FT_OTD_StateMachineInit(pAd, &pAd->Mlme.FtOtdActMachine, pAd->Mlme.FtOtdActFunc); +#endif /* DOT11R_FT_SUPPORT */ + + + /* Since we are using switch/case to implement it, the init is different from the above */ + /* state machine init*/ + MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); + +#ifdef RTMP_MAC_PCI + RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE); + pAd->Mlme.bPsPollTimerRunning = FALSE; +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + /* only PCIe cards need these timers*/ + RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, GET_TIMER_FUNCTION(LinkDownExec), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE); + + + + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + ApMlmeInit(pAd); +#ifdef APCLI_SUPPORT + ApCliMlmeInit(pAd); +#endif /* APCLI_SUPPORT */ + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WSC_INCLUDED + /* Init Wsc state machine */ + ASSERT(WSC_FUNC_SIZE == MAX_WSC_MSG * MAX_WSC_STATE); + WscStateMachineInit(pAd, &pAd->Mlme.WscMachine, pAd->Mlme.WscFunc); +#endif /* WSC_INCLUDED */ + + WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc); + +#ifdef CONFIG_HOTSPOT + HSCtrlStateMachineInit(pAd, &pAd->Mlme.HSCtrlMachine, pAd->Mlme.HSCtrlFunc); + GASStateMachineInit(pAd, &pAd->Mlme.GASMachine, pAd->Mlme.GASFunc); +#endif + +#ifdef CONFIG_DOT11V_WNM + WNMCtrlInit(pAd); + BTMStateMachineInit(pAd, &pAd->Mlme.BTMMachine, pAd->Mlme.BTMFunc); +#ifdef CONFIG_HOTSPOT_R2 + WNMNotifyStateMachineInit(pAd, &pAd->Mlme.WNMNotifyMachine, pAd->Mlme.WNMNotifyFunc); +#endif +#endif + + + ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); + + /* Init mlme periodic timer*/ + RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); + + /* Set mlme periodic timer*/ + RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); + + /* software-based RX Antenna diversity*/ + RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* Init APSD periodic timer*/ + RTMPInitTimer(pAd, &pAd->Mlme.APSDPeriodicTimer, GET_TIMER_FUNCTION(APSDPeriodicExec), pAd, TRUE); + RTMPSetTimer(&pAd->Mlme.APSDPeriodicTimer, 50); + + /* Init APQuickResponseForRateUp timer.*/ + RTMPInitTimer(pAd, &pAd->ApCfg.ApQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(APQuickResponeForRateUpExec), pAd, FALSE); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + RTMPInitTimer(pAd, &pAd->Mlme.SoundingTimer, GET_TIMER_FUNCTION(APTxSounding), pAd, TRUE); + RTMPSetTimer(&pAd->Mlme.SoundingTimer, SOUND_PERIOD_TIME); +#endif /* TXBF_SUPPORT*/ + + +#ifdef RT_CFG80211_P2P_SUPPORT + /*CFG_TODO*/ + ApMlmeInit(pAd); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + ApCliMlmeInit(pAd); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + RTMPInitTimer(pAd, &pAd->cfg80211_ctrl.P2pCTWindowTimer, GET_TIMER_FUNCTION(CFG80211_P2PCTWindowTimer), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->cfg80211_ctrl.P2pSwNoATimer, GET_TIMER_FUNCTION(CFG80211_P2pSwNoATimeOut), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->cfg80211_ctrl.P2pPreAbsenTimer, GET_TIMER_FUNCTION(CFG80211_P2pPreAbsenTimeOut), pAd, FALSE); +#endif /* RT_CFG80211_P2P_SUPPORT */ + + } while (FALSE); + + { + RTMP_OS_TASK *pTask; + + /* Creat MLME Thread */ + pTask = &pAd->mlmeTask; + RTMP_OS_TASK_INIT(pTask, "RtmpMlmeTask", pAd); + Status = RtmpOSTaskAttach(pTask, MlmeThread, (ULONG)pTask); + if (Status == NDIS_STATUS_FAILURE) { + DBGPRINT (RT_DEBUG_ERROR, ("%s: unable to start MlmeThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev))); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); + + return Status; +} + + +/* + ========================================================================== + Description: + Destructor of MLME (Destroy queue, state machine, spin lock and timer) + Parameters: + Adapter - NIC Adapter pointer + Post: + The MLME task will no longer work properly + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeHalt(RTMP_ADAPTER *pAd) +{ + BOOLEAN Cancelled; + RTMP_OS_TASK *pTask; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); + + /* Terminate Mlme Thread */ + pTask = &pAd->mlmeTask; + if (RtmpOSTaskKill(pTask) == NDIS_STATUS_FAILURE) { + DBGPRINT(RT_DEBUG_ERROR, ("kill mlme task failed!\n")); + } + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + /* disable BEACON generation and other BEACON related hardware timers*/ + AsicDisableSync(pAd); + } + RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef QOS_DLS_SUPPORT + UCHAR i; +#endif /* QOS_DLS_SUPPORT */ + /* Cancel pending timers*/ + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + +#ifdef DOT11R_FT_SUPPORT + RTMPCancelTimer(&pAd->MlmeAux.FtOtaAuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.FtOtdActTimer, &Cancelled); +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE) + &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) + { + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + } +#endif /* PCIE_PS_SUPPORT */ + +#ifdef QOS_DLS_SUPPORT + for (i=0; iStaCfg.DLSEntry[i].Timer, &Cancelled); + } +#endif /* QOS_DLS_SUPPORT */ + RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled); + + +#ifdef WSC_STA_SUPPORT + if (pAd->StaCfg.WscControl.WscProfileRetryTimerRunning) + { + pAd->StaCfg.WscControl.WscProfileRetryTimerRunning = FALSE; + RTMPCancelTimer(&pAd->StaCfg.WscControl.WscProfileRetryTimer, &Cancelled); + } +#endif /* WSC_STA_SUPPORT */ + + + if (pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + } + RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled); +#ifdef IWSC_SUPPORT + RTMPCancelTimer(&pAd->StaCfg.IWscInfo.IWscT1Timer, &Cancelled); + RTMPCancelTimer(&pAd->StaCfg.IWscInfo.IWscT2Timer, &Cancelled); +#endif /* IWSC_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR idx; + idx = 0; + RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled); + + if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE) + RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled); + +#ifdef APCLI_SUPPORT + for (idx = 0; idx < MAX_APCLI_NUM; idx++) + { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; + RTMPCancelTimer(&pApCliEntry->MlmeAux.ProbeTimer, &Cancelled); + RTMPCancelTimer(&pApCliEntry->MlmeAux.ApCliAssocTimer, &Cancelled); + RTMPCancelTimer(&pApCliEntry->MlmeAux.ApCliAuthTimer, &Cancelled); + RTMPCancelTimer(&pApCliEntry->MlmeAux.WpaDisassocAndBlockAssocTimer, &Cancelled); + +#ifdef WSC_AP_SUPPORT + if (pApCliEntry->WscControl.WscProfileRetryTimerRunning) + { + pApCliEntry->WscControl.WscProfileRetryTimerRunning = FALSE; + RTMPCancelTimer(&pApCliEntry->WscControl.WscProfileRetryTimer, &Cancelled); + } +#endif /* WSC_AP_SUPPORT */ + } +#endif /* APCLI_SUPPORT */ + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + RTMPCancelTimer(&pAd->Mlme.SoundingTimer, &Cancelled); +#endif /* TXBF_SUPPORT */ + + +#ifdef CONFIG_HOTSPOT + HSCtrlHalt(pAd); + HSCtrlExit(pAd); +#endif + +#ifdef CONFIG_DOT11U_INTERWORKING + GASCtrlExit(pAd); +#endif + +#ifdef CONFIG_DOT11V_WNM + WNMCtrlExit(pAd); +#endif + + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + +#ifdef LED_CONTROL_SUPPORT + /* Set LED*/ + RTMPSetLED(pAd, LED_HALT); + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it.*/ +#endif /* LED_CONTROL_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + if (pAd->WOW_Cfg.bEnable == FALSE) +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + if (pChipOps->AsicHaltAction) + pChipOps->AsicHaltAction(pAd); + } + + RtmpusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled*/ + +#ifdef EAPOL_QUEUE_SUPPORT + MlmeQueueDestroy(&pAd->Mlme.EAP_Queue, &pAd->Mlme.Queue); +#else /* EAPOL_QUEUE_SUPPORT */ + MlmeQueueDestroy(&pAd->Mlme.Queue); +#endif /* !EAPOL_QUEUE_SUPPORT */ + NdisFreeSpinLock(&pAd->Mlme.TaskLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); +} + +VOID MlmeResetRalinkCounters(RTMP_ADAPTER *pAd) +{ + pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; + +#ifdef RALINK_ATE + if (!ATE_ON(pAd)) +#endif /* RALINK_ATE */ + /* for performace enchanement */ + NdisZeroMemory(&pAd->RalinkCounters, + (UINT32)&pAd->RalinkCounters.OneSecEnd - + (UINT32)&pAd->RalinkCounters.OneSecStart); + + return; +} + + +/* + ========================================================================== + Description: + This routine is executed periodically to - + 1. Decide if it's a right time to turn on PwrMgmt bit of all + outgoiing frames + 2. Calculate ChannelQuality based on statistics of the last + period, so that TX rate won't toggling very frequently between a + successful TX and a failed TX. + 3. If the calculated ChannelQuality indicated current connection not + healthy, then a ROAMing attempt is tried here. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec*/ +VOID MlmePeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ULONG TxTotalCnt; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + +#ifdef APCLI_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[0]; +#endif + +#ifdef CUSTOMER_DCC_FEATURE + UINT32 ChBusyTime = 0; +#endif + + /* No More 0x84 MCU CMD from v.30 FW*/ + +#ifdef MICROWAVE_OVEN_SUPPORT + if (pAd->CommonCfg.MO_Cfg.bEnable) + { + UINT8 stage = pAd->CommonCfg.MO_Cfg.nPeriod_Cnt%10; + + if (stage == MO_MEAS_PERIOD) + { + ASIC_MEASURE_FALSE_CCA(pAd); + pAd->CommonCfg.MO_Cfg.nPeriod_Cnt = 0; + } + else if (stage == MO_IDLE_PERIOD) + { + RX_STA_CNT1_STRUC RxStaCnt1; + + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + pAd->CommonCfg.MO_Cfg.nFalseCCACnt += RxStaCnt1.field.FalseCca; + + //printk("%s: fales cca1 %d\n", __FUNCTION__, pAd->CommonCfg.MO_Cfg.nFalseCCACnt); + if (pAd->CommonCfg.MO_Cfg.nFalseCCACnt > pAd->CommonCfg.MO_Cfg.nFalseCCATh) + ASIC_MITIGATE_MICROWAVE(pAd); + } + + pAd->CommonCfg.MO_Cfg.nPeriod_Cnt++; + } +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef INF_AMAZON_SE +#endif /* INF_AMAZON_SE */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.*/ + /* Move code to here, because following code will return when radio is off*/ + if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && +/* (pAd->StaCfg.bHardwareRadio == TRUE) &&*/ + ((IDLE_ON(pAd)) || (pAd->StaCfg.Psm == PWR_ACTIVE)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + ((pAd->StaCfg.bHardwareRadio == TRUE)) +/* || (pAd->StaCfg.WscControl.CheckHWPBCState == HWPBCState_GUI)))*/ + /*&&(pAd->bPCIclkOff == FALSE)*/) + { + UINT32 data = 0; + + + /* Read GPIO pin2 as Hardware controlled radio state*/ +/*#ifndef RT3090*/ + /*RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);*/ +/*#endif RT3090 */ +/*KH(PCIE PS):Added based on Jane<--*/ +#ifdef PCIE_PS_SUPPORT + /* Read GPIO pin2 as Hardware controlled radio state*/ + /* We need to Read GPIO if HW said so no mater what advance power saving*/ + if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) + && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) + && (pAd->StaCfg.PSControl.field.EnablePSinIdle == TRUE)) + { + /* Want to make sure device goes to L0 state before reading register.*/ + RTMPPCIeLinkCtrlValueRestore(pAd, 0); + RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); + RTMPPCIeLinkCtrlSetting(pAd, 3); + } + else + RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); +#else + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); +#endif /* defined(RT3090) || defined(RT3592) || defined(RT3390) */ +/*KH(PCIE PS):Added based on Jane-->*/ + + /* Update Radio state from GPIO*/ + if (pAd->StaCfg.bHardwareRadio == TRUE) + { + { + if (data & 0x04) + pAd->StaCfg.bHwRadio = TRUE; + else + pAd->StaCfg.bHwRadio = FALSE; + } +#ifdef RT_CFG80211_SUPPORT +#ifdef RFKILL_HW_SUPPORT + RT_CFG80211_RFKILL_STATUS_UPDATE(pAd, pAd->StaCfg.bHwRadio); +#endif // RFKILL_HW_SUPPORT // +#endif /* RT_CFG80211_SUPPORT */ + } + + /* Always read HW radio configuration.*/ + if (pAd->StaCfg.bHardwareRadio == TRUE) + { + if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAd); + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + MlmeRadioOff(pAd); + pAd->ExtraInfo = HW_RADIO_OFF; + } + } + } + } + } +#endif /* RTMP_MAC_PCI */ + + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMP_MLME_PRE_SANITY_CHECK(pAd); + } + + /* + We go to sleep mode only when count down to zero. + Count down counter is set after link up. So within 10 seconds after link up, we never go to sleep. + 10 seconds period, we can get IP, finish 802.1x authenticaion. and some critical , timing protocol. + */ + if (pAd->CountDowntoPsm > 0) + pAd->CountDowntoPsm--; + +#endif /* CONFIG_STA_SUPPORT */ + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RADIO_MEASUREMENT | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + return; + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + //DBGPRINT(RT_DEBUG_TRACE, ("%s(): StartUp not finish yet!\n", __FUNCTION__)); + return; + } + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + cap_status_chk_and_get(pAd); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Do nothing if monitor mode is on*/ + if (MONITOR_ON(pAd)) + return; + +#ifdef RT8592 + if (IS_RT8592(pAd)) + ; + else +#endif /* RT8592 */ + if ((pAd->Mlme.PeriodicRound & 0x1) && + (STA_TGN_WIFI_ON(pAd)) && + ((pAd->MACVersion & 0xffff) == 0x0101)) + { + UINT32 txop_cfg; + + /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D*/ + if (pAd->CommonCfg.IOTestParm.bToggle == FALSE) + { + txop_cfg = 0x24BF; + pAd->CommonCfg.IOTestParm.bToggle = TRUE; + } + else + { + txop_cfg = 0x243f; + pAd->CommonCfg.IOTestParm.bToggle = FALSE; + } + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, txop_cfg); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + pAd->bUpdateBcnCntDone = FALSE; + +/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);*/ + pAd->Mlme.PeriodicRound ++; + pAd->Mlme.GPIORound++; + +#ifndef WFA_VHT_PF +#ifdef RT8592 + if (IS_RT8592(pAd)) + rt85592_cca_adjust(pAd); +#endif /* RT8592 */ +#endif /* WFA_VHT_PF */ + +#ifdef DYNAMIC_VGA_SUPPORT + RTMP_UPDATE_RSSI_FOR_DYNAMIC_VGA(pAd); + /* dynamic_cck_mrc(pAd); */ +#endif /* DYNAMIC_VGA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable) + CarrierDetectionPeriodicStateCtrl(pAd); +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* by default, execute every 500ms */ + if ((pAd->ra_interval) && + ((pAd->Mlme.PeriodicRound % (pAd->ra_interval / 100)) == 0) && + 1 //RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/ + ) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APMlmeDynamicTxRateSwitching(pAd); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + /* perform dynamic tx rate switching based on past TX history*/ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) +#ifdef RT_CFG80211_SUPPORT + || (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP) + //CFG_TODO: FOR GC +#endif /* RT_CFG80211_SUPPORT */ + ) + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) + MlmeDynamicTxRateSwitching(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DFS_SUPPORT +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable) + CarrierDetectionPeriodicStateCtrl(pAd); +#endif /* CARRIER_DETECTION_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef CUSTOMER_DCC_FEATURE + { + if(!(ApScanRunning(pAd))) { + RTMP_IO_READ32(pAd, CH_BUSY_STA, &ChBusyTime); + pAd->ChannelStats.ChBusyTime100msecValue = ChBusyTime; + } + if(pAd->EnableChannelStatsCheck && !(ApScanRunning(pAd)) && (pAd->ChannelStats.LastReadTime != 0) ) + { + ReadChannelStats(ChBusyTime, pAd); + } + else if(pAd->EnableChannelStatsCheck && !(ApScanRunning(pAd)) && (pAd->ChannelStats.LastReadTime == 0)) + { + ClearChannelStats(pAd); + } + } +#endif + + /* Normal 1 second Mlme PeriodicExec.*/ + if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) + { + pAd->Mlme.OneSecPeriodicRound ++; + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT +#ifdef MT76x2 + if ((pAd->Mlme.OneSecPeriodicRound % 1 == 0) && IS_MT76x2(pAd)) + { + if (pAd->PDMAWatchDogEn) + { + PDMAWatchDog(pAd); + } + } +#endif /* MT76x2 */ +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + +#ifdef MT76x2 + if ((pAd->Mlme.OneSecPeriodicRound % 1 == 0) && IS_MT76x2(pAd)) + mt76x2_get_current_temp(pAd); +#endif /* MT76x2 */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + //if (pAd->bApCliCertTest == FALSE ) + if (pApCliEntry->wdev.bWmmCapable == FALSE) + { +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + dynamic_tune_be_tx_op(pAd, 50); /* change form 100 to 50 for WMM WiFi test @20070504*/ +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + } +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + + NdisGetSystemUpTime(&pAd->Mlme.Now32); + + /* add the most up-to-date h/w raw counters into software variable, so that*/ + /* the dynamic tuning mechanism below are based on most up-to-date information*/ + /* Hint: throughput impact is very serious in the function */ + NICUpdateRawCounters(pAd); + + RTMP_SECOND_CCA_DETECTION(pAd); + + + +#ifdef DYNAMIC_VGA_SUPPORT +#ifdef CONFIG_AP_SUPPORT + if (IS_RT6352(pAd) || (IS_MT76x2(pAd) && pAd->OpMode == OPMODE_AP) || (IS_MT76x0E(pAd) && pAd->OpMode == OPMODE_AP)) + { + if (pAd->Mlme.OneSecPeriodicRound % 1 == 0) { + RTMP_ASIC_DYNAMIC_VGA_GAIN_CONTROL(pAd); + } + } +#endif /*CONFIG_AP_SUPPORT*/ + +#ifdef CONFIG_STA_SUPPORT +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + if (pAd->Mlme.OneSecPeriodicRound % 1 == 0) + periodic_monitor_rssi_adjust_vga(pAd); + + /* only g band need to check if disable channel smoothing */ + //if (pAd->CommonCfg.Channel <= 14) + //periodic_check_channel_smoothing(pAd); + } +#endif /* MT76x2 */ +#endif /* CONFIG_STA_SUPPORT */ +#endif /* DYNAMIC_VGA_SUPPORT */ + + /* + if (pAd->RalinkCounters.MgmtRingFullCount >= 2) + RTMP_SET_FLAG(pAd, fRTMP_HW_ERR); + else + pAd->RalinkCounters.MgmtRingFullCount = 0; + */ + + /* The time period for checking antenna is according to traffic*/ + { + if (pAd->Mlme.bEnableAutoAntennaCheck) + { + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + /* dynamic adjust antenna evaluation period according to the traffic*/ + if (TxTotalCnt > 50) + { + if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) + AsicEvaluateRxAnt(pAd); + } + else + { + if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) + AsicEvaluateRxAnt(pAd); + } + } + } + +#ifdef VIDEO_TURBINE_SUPPORT + /* + VideoTurbineUpdate(pAd); + VideoTurbineDynamicTune(pAd); + */ +#endif /* VIDEO_TURBINE_SUPPORT */ + +#ifdef MT76x0_TSSI_CAL_COMPENSATION + if (IS_MT76x0(pAd) && + (pAd->chipCap.bInternalTxALC) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE)) + { + if ((pAd->Mlme.OneSecPeriodicRound % 1) == 0) + { + /* TSSI compensation */ + MT76x0_IntTxAlcProcess(pAd); + } + } +#endif /* MT76x0_TSSI_CAL_COMPENSATION */ + +#ifdef MT76x2 + if (IS_MT76x2(pAd) && + (pAd->chipCap.tssi_enable) && (!pAd->chipCap.temp_tx_alc_enable) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE)) { + if ((pAd->Mlme.OneSecPeriodicRound % 1) == 0) { +#ifdef CONFIG_AP_SUPPORT + mt76x2_tssi_compensation(pAd, pAd->hw_cfg.cent_ch); +#endif + +#ifdef CONFIG_STA_SUPPORT + if (INFRA_ON(pAd)) + mt76x2_tssi_compensation(pAd, pAd->hw_cfg.cent_ch); +#endif + } + } +#endif /* MT76x2 */ + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 0) + { + { + +#ifdef ED_MONITOR //Don't do VCORECAL while ed is holding tx + if(!pAd->ed_tx_stoped) +#endif + { +#ifdef VCORECAL_SUPPORT + AsicVCORecalibration(pAd); +#endif /* VCORECAL_SUPPORT */ + } + } + } + } + + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APMlmePeriodicExec(pAd); + + if ((pAd->RalinkCounters.OneSecBeaconSentCnt == 0) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + && ((pAd->CommonCfg.bIEEE80211H != 1) + || (pAd->Dot11_H.RDMode != RD_SILENCE_MODE)) +#ifdef WDS_SUPPORT + && (pAd->WdsTab.Mode != WDS_BRIDGE_MODE) +#endif /* WDS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + && (isCarrierDetectExist(pAd) == FALSE) +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef ED_MONITOR + && (pAd->ed_chk == FALSE) +#endif /* ED_MONITOR */ + ) + pAd->macwd ++; + else + pAd->macwd = 0; + + if (pAd->macwd > 1) + { + int count = 0; + BOOLEAN MAC_ready = FALSE; + UINT32 MacCsr12 = 0; + + /* Disable MAC*/ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + /* polling MAC status*/ + while (count < 10) + { + RtmpusecDelay(1000); /* 1 ms*/ + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); + + /* if MAC is idle*/ + if ((MacCsr12 & 0x03) == 0) + { + MAC_ready = TRUE; + break; + } + count ++; + } + + if (MAC_ready) + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + RtmpusecDelay(1); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("Warning, MAC isn't ready \n")); + } + + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); + } + + DBGPRINT(RT_DEBUG_WARN, ("MAC specific condition \n")); + +#ifdef AP_QLOAD_SUPPORT +// Show_QoSLoad_Proc(pAd, NULL); +#endif /* AP_QLOAD_SUPPORT */ + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + RtmpPsActiveExtendCheck(pAd); +#ifdef TDLS_AUTOLINK_SUPPORT + /* TDLS discovery link maintenance */ + if (IS_TDLS_SUPPORT(pAd) && (pAd->StaCfg.TdlsInfo.TdlsAutoLink)) + { + TDLS_MaintainDiscoveryEntryList(pAd); + } +#endif /* TDLS_AUTOLINK_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + STAMlmePeriodicExec(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_SECOND_CCA_DETECTION(pAd); + + MlmeResetRalinkCounters(pAd); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef RTMP_MAC_PCI + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE)) +#endif /* RTMP_MAC_PCI */ +#ifdef RTMP_MAC_PCI + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) +#endif /* RTMP_MAC_PCI */ + { + + + UINT32 MacReg = 0; + + RTMP_IO_READ32(pAd, 0x10F4, &MacReg); + if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20))) + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + RtmpusecDelay(1); + MacReg = 0; + { + MacReg = 0xc; + } + + if (MacReg) + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacReg); + + DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_MLME_HANDLER(pAd); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_PARTIAL_SCAN_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((pAd->ApCfg.bPartialScanning == TRUE) && + (pAd->ApCfg.PartialScanChannelNum == DEFLAUT_PARTIAL_SCAN_CH_NUM))/* pAd->ApCfg.PartialScanChannelNum == DEFLAUT_PARTIAL_SCAN_CH_NUM means that one partial scan is finished */ + { + if (((pAd->ApCfg.PartialScanBreakTime++)%DEFLAUT_PARTIAL_SCAN_BREAK_TIME) == 0) + ApSiteSurvey(pAd, NULL, SCAN_ACTIVE, FALSE); /* To check: when EXT_BUILD_CHANNEL_LIST, is the ScanType switched to SCAN_PASSIVE for DFS channels?*/ + } + } +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) { + if (pAd->CommonCfg.bEnTemperatureTrack == TRUE) + { +#ifdef RTMP_INTERNAL_TX_ALC + if (pAd->TxPowerCtrl.bInternalTxALC) + { + + if (RT635xCheckTssiCompensation(pAd)) + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + RT6352_TemperatureCalibration(pAd); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + DoDPDCalibration(pAd); + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + if (pAd->bAutoTxAgcG) + { + if (RT6352_TemperatureCompensation(pAd, FALSE) == TRUE) + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + } + else +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + UCHAR bbpval; + CHAR BBPR49; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval); + if ((bbpval & 0x10) == 0) + { + bbpval &= 0xf8; + bbpval |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval); + + /* save temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + pAd->CurrTemperature = (INT32) BBPR49; + + DBGPRINT(RT_DEBUG_INFO, ("Current Temperature from BBP_R49=0x%x\n", pAd->CurrTemperature)); + RT6352_TemperatureCalibration(pAd); + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + } +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } + } + } +#endif /* RT6352 */ +#ifdef WSC_INCLUDED + WSC_HDR_BTN_MR_HANDLE(pAd); +#endif /* WSC_INCLUDED */ + + + +#ifdef ED_MONITOR + if(pAd->ed_chk != EDCCA_OFF) + ed_status_read(pAd); +#ifdef ED_SMART + if(pAd->ed_chk == EDCCA_SMART) + ed_state_judge(pAd); +#endif /* ED_SMART */ +#endif /* ED_MONITOR */ + + + pAd->bUpdateBcnCntDone = FALSE; +} + + +/* + ========================================================================== + Validate SSID for connection try and rescan purpose + Valid SSID will have visible chars only. + The valid length is from 0 to 32. + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +BOOLEAN MlmeValidateSSID(UCHAR *pSsid, UCHAR SsidLen) +{ + int index; + + if (SsidLen > MAX_LEN_OF_SSID) + return (FALSE); + + /* Check each character value*/ + for (index = 0; index < SsidLen; index++) + { + if (pSsid[index] < 0x20) + return (FALSE); + } + + /* All checked*/ + return (TRUE); +} + + +#ifdef CONFIG_STA_SUPPORT +VOID STAMlmePeriodicExec(RTMP_ADAPTER *pAd) +{ + ULONG TxTotalCnt; + int i; + BOOLEAN bCheckBeaconLost = TRUE; +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + + RTMP_CHIP_HIGH_POWER_TUNING(pAd, &pAd->StaCfg.RssiSample); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + /* WPA MIC error should block association attempt for 60 seconds*/ + if (pAd->StaCfg.bBlockAssoc && + RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastMicErrorTime + (60*OS_HZ))) + pAd->StaCfg.bBlockAssoc = FALSE; + } + + +#ifdef ETH_CONVERT_SUPPORT + if ((pAd->EthConvert.ECMode & ETH_CONVERT_MODE_CLONE) + && (pAd->EthConvert.CloneMacVaild == TRUE) + && (NdisEqualMemory(pAd->CurrentAddress, pAd->EthConvert.EthCloneMac, MAC_ADDR_LEN) == FALSE)) + { + + MAC_DW0_STRUC csr2; + MAC_DW1_STRUC csr3; + + /* Link down first */ + if (INFRA_ON(pAd)) + { + + if (pAd->MlmeAux.SsidLen){ + NdisZeroMemory(pAd->EthConvert.SSIDStr, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->EthConvert.SSIDStr, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->EthConvert.SSIDStrLen = pAd->MlmeAux.SsidLen; + } + + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_DISASSOCIATE, + 0, + NULL, 0); + /* RTMP_MLME_HANDLER(pAd); */ + } + else if (ADHOC_ON(pAd)) + { + MakeIbssBeacon(pAd); /* re-build BEACON frame*/ + AsicEnableIbssSync(pAd); /* copy to on-chip memory*/ + LinkDown(pAd, FALSE); + } + else + { + /* Copy the new Mac address to ASIC and start to re-connect to AP.*/ + NdisMoveMemory(&pAd->CurrentAddress[0], &pAd->EthConvert.EthCloneMac[0], MAC_ADDR_LEN); + + AsicSetDevMac(pAd, pAd->CurrentAddress); + + DBGPRINT_RAW(RT_DEBUG_TRACE,("Write EthCloneMac to ASIC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->CurrentAddress))); + + if(pAd->EthConvert.SSIDStrLen != 0) + { + /*DBGPRINT_RAW(RT_DEBUG_TRACE, ("copy MlmeAux.Ssid to AutoReconnect!\n"));*/ + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->EthConvert.SSIDStr, pAd->EthConvert.SSIDStrLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->EthConvert.SSIDStrLen; + NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->EthConvert.SSIDStr, pAd->EthConvert.SSIDStrLen); + pAd->MlmeAux.SsidLen= pAd->EthConvert.SSIDStrLen; + } + } + } +#endif /* ETH_CONVERT_SUPPORT */ + + + + if (ADHOC_ON(pAd)) + { + } + else + { + AsicStaBbpTuning(pAd); + } + + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + { + /* update channel quality for Roaming/Fast-Roaming and UI LinkQuality display*/ + /* bImprovedScan True means scan is not completed */ + if (pAd->StaCfg.bImprovedScan) + bCheckBeaconLost = FALSE; + + +#ifdef CONFIG_WIFI_TEST + if (pAd->chipCap.pbf_loopback) + bCheckBeaconLost = FALSE; +#endif /* CONFIG_WIFI_TEST */ + + if (bCheckBeaconLost) + { + /* The NIC may lost beacons during scaning operation.*/ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + MlmeCalculateChannelQuality(pAd, pEntry, pAd->Mlme.Now32); + } + } + + + /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if*/ + /* Radio is currently in noisy environment*/ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + RT6352_AsicAdjustTxPower(pAd); + else +#endif /* RT6352 */ + AsicAdjustTxPower(pAd); + RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(pAd); + } + + + /* + Driver needs to up date value of LastOneSecTotalTxCount here; + otherwise UI couldn't do scanning sometimes when STA doesn't connect to AP or peer Ad-Hoc. + */ + pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; + + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + /* MAC table maintenance */ + if ((pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) && +#ifdef RT_CFG80211_P2P_SUPPORT + (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP) +#else + P2P_GO_ON(pAd) +#endif /* RT_CFG80211_P2P_SUPPORT */ + ) + { + /* one second timer */ +#ifdef RT_CFG80211_P2P_SUPPORT + MacTableMaintenance(pAd); +#else + P2PMacTableMaintenance(pAd); +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.bHTProtect) + { + 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 */ + } +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + + /* resume Improved Scanning*/ + if ((pAd->StaCfg.bImprovedScan) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING)) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + + ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + DBGPRINT(RT_DEBUG_WARN, ("bImprovedScan ............. Resume for bImprovedScan, SCAN_PENDING .............. \n")); + } + + if (INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + /* Check DLS time out, then tear down those session*/ + RTMPCheckDLSTimeOut(pAd); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + /* TDLS link maintenance*/ + if (IS_TDLS_SUPPORT(pAd)) + { + if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) + TDLS_LinkMaintenance(pAd); + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + + /* Is PSM bit consistent with user power management policy?*/ + /* This is the only place that will set PSM bit ON.*/ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); + + /* + When we are connected and do the scan progress, it's very possible we cannot receive + the beacon of the AP. So, here we simulate that we received the beacon. + */ + if ((bCheckBeaconLost == FALSE) && + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ)))) + { + ULONG BPtoJiffies; + LONG timeDiff; + + BPtoJiffies = (((pAd->CommonCfg.BeaconPeriod * 1024 / 1000) * OS_HZ) / 1000); + timeDiff = (pAd->Mlme.Now32 - pAd->StaCfg.LastBeaconRxTime) / BPtoJiffies; + if (timeDiff > 0) + pAd->StaCfg.LastBeaconRxTime += (timeDiff * BPtoJiffies); + + if (RTMP_TIME_AFTER(pAd->StaCfg.LastBeaconRxTime, pAd->Mlme.Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - BeaconRxTime adjust wrong(BeaconRx=0x%lx, Now=0x%lx)\n", + pAd->StaCfg.LastBeaconRxTime, pAd->Mlme.Now32)); + } + } + + if ((RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ))) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (pAd->StaCfg.bImprovedScan == FALSE) && + ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < 600)) + { + RTMPSetAGCInitValue(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd)))); + } + + + + + /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&*/ + /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))*/ + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + { + if (pAd->StaCfg.UapsdInfo.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) + { + /* When APSD is enabled, the period changes as 20 sec*/ + if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + } + } + else + { + /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)*/ + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) + { + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid), + pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + } + } + } + + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + + if (pAd->StaCfg.bAutoConnectByBssid) + pAd->StaCfg.bAutoConnectByBssid = FALSE; + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2)) + pAd->StaCfg.wpa_supplicant_info.bLostAp = TRUE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + /* Lost AP, send disconnect & link down event*/ + LinkDown(pAd, FALSE); + + /* should mark this two function, because link down alse will call this function */ + + /* RTMPPatchMacBbpBug(pAd);*/ +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + MlmeAutoReconnectLastSSID(pAd); + } + else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) + { + pAd->RalinkCounters.BadCQIAutoRecoveryCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + MlmeAutoReconnectLastSSID(pAd); + } + } + + if (pAd->StaCfg.bAutoRoaming) + { + BOOLEAN rv = FALSE; + CHAR dBmToRoam = pAd->StaCfg.dBmToRoam; + CHAR MaxRssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.LastRssi0, + pAd->StaCfg.RssiSample.LastRssi1, + pAd->StaCfg.RssiSample.LastRssi2); + + if (pAd->StaCfg.bAutoConnectByBssid) + pAd->StaCfg.bAutoConnectByBssid = FALSE; + + /* Scanning, ignore Roaming*/ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) && + (MaxRssi <= dBmToRoam)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, (CHAR)dBmToRoam)); + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain) + rv = FT_CheckForRoaming(pAd); +#endif /* DOT11R_FT_SUPPORT */ + + /* Add auto seamless roaming*/ + if (rv == FALSE) + rv = MlmeCheckForFastRoaming(pAd); + + if (rv == FALSE) + { + if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + MlmeAutoScan(pAd); + } + } + } + } + } + else if (ADHOC_ON(pAd)) + { + + /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState*/ + /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can*/ + /* join later.*/ + if (/*(RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + && */OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) +#ifdef IWSC_SUPPORT + /* + 2011/09/05: + Broadcom test bed doesn't broadcast beacon when Broadcom is Enrollee. + */ + && (pAd->StaCfg.WscControl.bWscTrigger == FALSE) +#endif /* IWSC_SUPPORT */ + ) + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + } + + if (pAd->MacTab.Size == 0) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + } + } + + } + else /* no INFRA nor ADHOC connection*/ + { + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) + goto SKIP_AUTO_SCAN_CONN; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + if (pAd->StaCfg.bSkipAutoScanConn && + RTMP_TIME_BEFORE(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (30 * OS_HZ))) + goto SKIP_AUTO_SCAN_CONN; + else + pAd->StaCfg.bSkipAutoScanConn = FALSE; + + if ((pAd->StaCfg.bAutoReconnect == TRUE) + && !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) + && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) + && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) + { + if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + ) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (10 * OS_HZ)) + ||(pAd->StaCfg.bNotFirstScan == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid)); + if (pAd->StaCfg.BssType == BSS_ADHOC) + pAd->StaCfg.bNotFirstScan = TRUE; + ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + /* Reset Missed scan number*/ + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + } + else + MlmeAutoReconnectLastSSID(pAd); + } + else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE + ) + { +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier*/ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1) + MlmeAutoReconnectLastSSID(pAd); + } + else +#endif /* CARRIER_DETECTION_SUPPORT */ + { +#ifdef WPA_SUPPLICANT_SUPPORT + if(pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE) +#endif // WPA_SUPPLICANT_SUPPORT // + MlmeAutoReconnectLastSSID(pAd); + } + } + } + } + +SKIP_AUTO_SCAN_CONN: + +#ifdef DOT11_N_SUPPORT + if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + pAd->MacTab.fAnyBASession = TRUE; + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE); + } + else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + pAd->MacTab.fAnyBASession = FALSE; + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + } +#endif /* DOT11_N_SUPPORT */ + + +//YF_TODO +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) + if (RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) + { + if (pAd->Mlme.OneSecPeriodicRound % 2 == 0) + ApCliIfMonitor(pAd); + + if (pAd->Mlme.OneSecPeriodicRound % 2 == 1) + ApCliIfUp(pAd); + + ApCliSimulateRecvBeacon(pAd); + } +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Perform 20/40 BSS COEX scan every Dot11BssWidthTriggerScanInt */ + 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)) + { + 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); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + /* 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 /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + return; +} + +/* Link down report*/ +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + if (pAd != NULL) + { + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + if ((pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED) && + (INFRA_ON(pAd))) + { + DBGPRINT(RT_DEBUG_TRACE, ("LinkDownExec(): disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + } + } +} + + +VOID MlmeAutoScan(RTMP_ADAPTER *pAd) +{ + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + pAd->MlmeAux.AutoReconnectSsidLen, + pAd->MlmeAux.AutoReconnectSsid, 0); + RTMP_MLME_HANDLER(pAd); + } +} + + +VOID MlmeAutoReconnectLastSSID(RTMP_ADAPTER *pAd) +{ +#ifdef WSC_STA_SUPPORT + PWSC_CTRL pWscControl = &pAd->StaCfg.WscControl; + + if ((pWscControl->WscConfMode != WSC_DISABLE) && + (pWscControl->bWscTrigger) && + (pWscControl->WscMode == WSC_PBC_MODE) && + (pWscControl->WscPBCBssCount != 1)) + return; + + if ((pWscControl->WscConfMode != WSC_DISABLE) && + (pWscControl->WscState >= WSC_STATE_START)) + { + ULONG ApIdx = 0; + + ApIdx = WscSearchWpsApBySSID(pAd, + pWscControl->WscSsid.Ssid, + pWscControl->WscSsid.SsidLength, + pWscControl->WscMode); + + if ((ApIdx != BSS_NOT_FOUND) && + (pAd->StaCfg.BssType == BSS_INFRA)) + { + NdisMoveMemory(pWscControl->WscBssid, pAd->ScanTab.BssEntry[ApIdx].Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.Channel = pAd->ScanTab.BssEntry[ApIdx].Channel; + } + + CntlWscIterate(pAd); + } + else +#endif /* WSC_STA_SUPPORT */ + if (pAd->StaCfg.bAutoConnectByBssid) + { + DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n", + PRINT_MAC(pAd->MlmeAux.Bssid))); + + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + MAC_ADDR_LEN, + pAd->MlmeAux.Bssid, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + + RTMP_MLME_HANDLER(pAd); + } + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/ + else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && + (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) + { + NDIS_802_11_SSID OidSsid; + OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; + NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen)); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + &OidSsid, 0); + RTMP_MLME_HANDLER(pAd); + } +} + + +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when Link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +VOID MlmeCheckForRoaming(RTMP_ADAPTER *pAd, ULONG Now32) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); + /* put all roaming candidates into RoamTab, and sort in RSSI order*/ + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if (RTMP_TIME_AFTER(Now32, pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime)) + continue; /* AP disappear*/ + if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) + continue; /* RSSI too weak. forget it.*/ + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; /* skip current AP*/ + if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) + continue; /* only AP with stronger RSSI is eligible for roaming*/ + + /* AP passing all above rules is put into roaming candidate table */ + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + if (pRoamTab->BssNr > 0) + { + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); +} + + +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +BOOLEAN MlmeCheckForFastRoaming(RTMP_ADAPTER *pAd) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + CHAR max_rssi; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); + /* put all roaming candidates into RoamTab, and sort in RSSI order*/ + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) + continue; /* RSSI too weak. forget it.*/ + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; /* skip current AP*/ + if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + continue; /* skip different SSID*/ + max_rssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); + if (pBss->Rssi < (max_rssi + RSSI_DELTA)) + continue; /* skip AP without better RSSI*/ + + DBGPRINT(RT_DEBUG_TRACE, ("max_rssi = %d, pBss->Rssi = %d\n", max_rssi, pBss->Rssi)); + /* AP passing all above rules is put into roaming candidate table */ + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); + if (pRoamTab->BssNr > 0) + { + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + return TRUE; + } + } + + return FALSE; +} + + +/* + ========================================================================== + Description: + This routine is executed periodically inside MlmePeriodicExec() after + association with an AP. + It checks if StaCfg.Psm is consistent with user policy (recorded in + StaCfg.WindowsPowerMode). If not, enforce user policy. However, + there're some conditions to consider: + 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all + the time when Mibss==TRUE + 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE + if outgoing traffic available in TxRing or MgmtRing. + Output: + 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeCheckPsmChange(RTMP_ADAPTER *pAd, ULONG Now32) +{ + ULONG PowerMode; + + /* + condition - + 1. Psm maybe ON only happen in INFRASTRUCTURE mode + 2. user wants either MAX_PSP or FAST_PSP + 3. but current psm is not in PWR_SAVE + 4. CNTL state machine is not doing SCANning + 5. no TX SUCCESS event for the past 1-sec period + */ + PowerMode = pAd->StaCfg.WindowsPowerMode; + + if (INFRA_ON(pAd) && + (PowerMode != Ndis802_11PowerModeCAM) && + (pAd->StaCfg.Psm == PWR_ACTIVE) && +/* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))*/ + (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) +#ifdef PCIE_PS_SUPPORT + && RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP) +#endif /* PCIE_PS_SUPPORT */ + && (pAd->CountDowntoPsm <= 0) + /*&& + (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && + (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/) + { + NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); + pAd->RalinkCounters.RxCountSinceLastNULL = 0; + RTMP_SET_PSM_BIT(pAd, PWR_SAVE); + + if (!(pAd->StaCfg.UapsdInfo.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + } + else + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + } + + } +} + + +VOID MlmeSetPsmBit(RTMP_ADAPTER *pAd, USHORT psm) +{ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + USHORT PsmOld = pAd->StaCfg.Psm; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + pAd->StaCfg.Psm = psm; + +#ifdef DOT11Z_TDLS_SUPPORT + /* pAd->StaCfg.Psm must be updated before calling the function */ + TDLS_UAPSDP_PsmModeChange(pAd, PsmOld, psm); +#endif /* DOT11Z_TDLS_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ========================================================================== + Description: + This routine calculates TxPER, RxPER of the past N-sec period. And + according to the calculation result, ChannelQuality is calculated here + to decide if current AP is still doing the job. + + If ChannelQuality is not good, a ROAMing attempt may be tried later. + Output: + StaCfg.ChannelQuality - 0..100 + + IRQL = DISPATCH_LEVEL + + NOTE: This routine decide channle quality based on RX CRC error ratio. + Caller should make sure a function call to NICUpdateRawCounters(pAd) + is performed right before this routine, so that this routine can decide + channel quality based on the most up-to-date information + ========================================================================== + */ +VOID MlmeCalculateChannelQuality( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN ULONG Now32) +{ + ULONG TxOkCnt, TxCnt/*, TxPER*/,TxPRR; + ULONG RxCnt, RxPER; + UCHAR NorRssi; + CHAR MaxRssi; + RSSI_SAMPLE *pRssiSample = NULL; + UINT32 OneSecTxNoRetryOkCount = 0; + UINT32 OneSecTxRetryOkCount = 0; + UINT32 OneSecTxFailCount = 0; + UINT32 OneSecRxOkCnt = 0; + UINT32 OneSecRxFcsErrCnt = 0; + ULONG ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming*/ +#ifdef CONFIG_STA_SUPPORT + ULONG LastBeaconRxTime = 0; + ULONG BeaconLostTime = pAd->StaCfg.BeaconLostTime; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier*/ + /* longer beacon lost time when carrier detection enabled*/ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + BeaconLostTime = pAd->StaCfg.BeaconLostTime + (pAd->StaCfg.BeaconLostTime/2); + } +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (pMacEntry && IS_ENTRY_APCLI(pMacEntry) && (pMacEntry->wdev_idx < MAX_APCLI_NUM)) + LastBeaconRxTime = pAd->ApCfg.ApCliTab[pMacEntry->wdev_idx].ApCliRcvBeaconTime; + else +#endif /*APCLI_SUPPORT*/ + LastBeaconRxTime = pAd->StaCfg.LastBeaconRxTime; +#endif /* CONFIG_STA_SUPPORT */ + + + if (pMacEntry != NULL) + { + pRssiSample = &pMacEntry->RssiSample; + OneSecTxNoRetryOkCount = pMacEntry->OneSecTxNoRetryOkCount; + OneSecTxRetryOkCount = pMacEntry->OneSecTxRetryOkCount; + OneSecTxFailCount = pMacEntry->OneSecTxFailCount; + OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt; + OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt; + } + else + { + pRssiSample = &pAd->MacTab.Content[0].RssiSample; + OneSecTxNoRetryOkCount = pAd->RalinkCounters.OneSecTxNoRetryOkCount; + OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount; + OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount; + OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt; + OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt; + } + + if (pRssiSample == NULL) + return; + MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0, + pRssiSample->LastRssi1, + pRssiSample->LastRssi2); + + + /* + calculate TX packet error ratio and TX retry ratio - if too few TX samples, + skip TX related statistics + */ + TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount; + TxCnt = TxOkCnt + OneSecTxFailCount; + if (TxCnt < 5) + { + /*TxPER = 0;*/ + TxPRR = 0; + } + else + { + /*TxPER = (OneSecTxFailCount * 100) / TxCnt;*/ + TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt; + } + + + /* calculate RX PER - don't take RxPER into consideration if too few sample*/ + RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt; + if (RxCnt < 5) + RxPER = 0; + else + RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt; + + + /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER*/ +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + INFRA_ON(pAd) && + (OneSecTxNoRetryOkCount < 2) && /* no heavy traffic*/ + RTMP_TIME_AFTER(Now32, LastBeaconRxTime + BeaconLostTime)) + { + DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime * (1000 / OS_HZ) , TxOkCnt)); + ChannelQuality = 0; + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + /* Normalize Rssi*/ + if (MaxRssi > -40) + NorRssi = 100; + else if (MaxRssi < -90) + NorRssi = 0; + else + NorRssi = (MaxRssi + 90) * 2; + + /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)*/ + ChannelQuality = (RSSI_WEIGHTING * NorRssi + + TX_WEIGHTING * (100 - TxPRR) + + RX_WEIGHTING* (100 - RxPER)) / 100; + } + + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + pAd->Mlme.ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + if (pMacEntry != NULL) + pMacEntry->ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality; + } +#endif /* CONFIG_AP_SUPPORT */ + + +} + + +VOID MlmeSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble) +{ + /* Always use Long preamble before verifiation short preamble functionality works well.*/ + /* Todo: remove the following line if short preamble functionality works*/ + + if (TxPreamble == Rt802_11PreambleLong) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + } + else + { + /* NOTE: 1Mbps should always use long preamble*/ + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + } + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble = %s PREAMBLE\n", + ((TxPreamble == Rt802_11PreambleLong) ? "LONG" : "SHORT"))); + + AsicSetTxPreamble(pAd, TxPreamble); +} + + +/* + ========================================================================== + Description: + Update basic rate bitmap + ========================================================================== +*/ +VOID UpdateBasicRateBitmap(RTMP_ADAPTER *pAdapter) +{ + INT i, j; + /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; + UCHAR *sup_p = pAdapter->CommonCfg.SupRate; + UCHAR *ext_p = pAdapter->CommonCfg.ExtRate; + ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap; + + /* if A mode, always use fix BasicRateBitMap */ + /*if (pAdapter->CommonCfg.Channel == WMODE_A)*/ + if (pAdapter->CommonCfg.Channel > 14) + { + if (pAdapter->CommonCfg.BasicRateBitmap & 0xF) + { + /* no 11b rate in 5G band */ + pAdapter->CommonCfg.BasicRateBitmapOld = \ + pAdapter->CommonCfg.BasicRateBitmap; + pAdapter->CommonCfg.BasicRateBitmap &= (~0xF); /* no 11b */ + } + + /* force to 6,12,24M in a-band */ + pAdapter->CommonCfg.BasicRateBitmap |= 0x150; /* 6, 12, 24M */ + } + else + { + /* no need to modify in 2.4G (bg mixed) */ + pAdapter->CommonCfg.BasicRateBitmap = \ + pAdapter->CommonCfg.BasicRateBitmapOld; + } + + if (pAdapter->CommonCfg.BasicRateBitmap > 4095) + { + /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return; + } + + for(i=0; iCommonCfg.DesireRate[i] & 0x7f) + { + case 2: Rate = RATE_1; num++; break; + case 4: Rate = RATE_2; num++; break; + case 11: Rate = RATE_5_5; num++; break; + case 22: Rate = RATE_11; num++; break; + case 12: Rate = RATE_6; num++; break; + case 18: Rate = RATE_9; num++; break; + case 24: Rate = RATE_12; num++; break; + case 36: Rate = RATE_18; num++; break; + case 48: Rate = RATE_24; num++; break; + case 72: Rate = RATE_36; num++; break; + case 96: Rate = RATE_48; num++; break; + case 108: Rate = RATE_54; num++; break; + /*default: Rate = RATE_1; break;*/ + } + if (MaxDesire < Rate) MaxDesire = Rate; + } + +/*===========================================================================*/ + do + { +#ifdef CONFIG_AP_SUPPORT +#ifdef RT_CFG80211_P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO) + { + wdev = &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev; + break; + } +#endif /* RT_CFG80211_P2P_SUPPORT */ +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + wdev = &pAd->ApCfg.ApCliTab[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx)); + return; + } + } +#endif /* APCLI_SUPPORT */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS; + + if (idx < MAX_WDS_ENTRY) + { + wdev = &pAd->WdsTab.WdsEntry[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + + if ((apidx < pAd->ApCfg.BssidNum) && + (apidx < MAX_MBSSID_NUM(pAd)) && + (apidx < HW_BEACON_MAX_NUM)) + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + wdev = &pAd->StaCfg.wdev; + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B) && + (MaxDesire > RATE_11)) + { + MaxDesire = RATE_11; + } + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while(FALSE); + + if (wdev) + { + pHtPhy = &wdev->HTPhyMode; + pMaxHtPhy = &wdev->MaxHTPhyMode; + pMinHtPhy = &wdev->MinHTPhyMode; + + auto_rate_cur_p = &wdev->bAutoTxRateSwitch; + HtMcs = wdev->DesiredTransmitSetting.field.MCS; + } + + pAd->CommonCfg.MaxDesiredRate = MaxDesire; + + if (pMinHtPhy == NULL) + return; + pMinHtPhy->word = 0; + pMaxHtPhy->word = 0; + pHtPhy->word = 0; + + /* + Auto rate switching is enabled only if more than one DESIRED RATES are + specified; otherwise disabled + */ + if (num <= 1) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + if (HtMcs != MCS_AUTO) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA) + ) + { + pSupRate = &pAd->StaActive.SupRate[0]; + pExtRate = &pAd->StaActive.ExtRate[0]; + SupRateLen = pAd->StaActive.SupRateLen; + ExtRateLen = pAd->StaActive.ExtRateLen; + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + pSupRate = &pAd->CommonCfg.SupRate[0]; + pExtRate = &pAd->CommonCfg.ExtRate[0]; + SupRateLen = pAd->CommonCfg.SupRateLen; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + + /* find max supported rate */ + for (i=0; i Rate) + MinSupport = Rate; + } + + for (i=0; i Rate) + MinSupport = Rate; + } + + RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); + + for (i=0; iCommonCfg.ExpectedACKRate[i] = CurrBasicRate; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s():[MaxSupport = %d] = MaxDesire %d Mbps\n", + __FUNCTION__, RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); + /* max tx rate = min {max desire rate, max supported rate}*/ + if (MaxSupport < MaxDesire) + pAd->CommonCfg.MaxTxRate = MaxSupport; + else + pAd->CommonCfg.MaxTxRate = MaxDesire; + + pAd->CommonCfg.MinTxRate = MinSupport; + /* + 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success + ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending + on average RSSI + 1. RSSI >= -70db, start at 54 Mbps (short distance) + 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) + 3. -75 > RSSI, start at 11 Mbps (long distance) + */ + if (*auto_rate_cur_p) + { + short dbm = 0; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + dbm =0; +#endif /* CONFIG_AP_SUPPORT */ + if (bLinkUp == TRUE) + pAd->CommonCfg.TxRate = RATE_24; + else + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + if (dbm < -75) + pAd->CommonCfg.TxRate = RATE_11; + else if (dbm < -70) + pAd->CommonCfg.TxRate = RATE_24; + + /* should never exceed MaxTxRate (consider 11B-only mode)*/ + if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + pAd->CommonCfg.TxRateIndex = 0; + + } + else + { + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + /* Choose the Desire Tx MCS in CCK/OFDM mode */ + if (num > RATE_6) + { + if (HtMcs <= MCS_7) + MaxDesire = RxwiMCSToOfdmRate[HtMcs]; + else + MaxDesire = MinSupport; + } + else + { + if (HtMcs <= MCS_3) + MaxDesire = HtMcs; + else + MaxDesire = MinSupport; + } + + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; + + } + + if (pAd->CommonCfg.TxRate <= RATE_11) + { + pMaxHtPhy->field.MODE = MODE_CCK; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; + pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pMaxHtPhy->field.MCS = MaxDesire; + } +#endif /* CONFIG_AP_SUPPORT */ + + } + else + { + pMaxHtPhy->field.MODE = MODE_OFDM; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; + if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54)) + pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate]; + else + pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[MaxDesire]; + } +#endif /* CONFIG_AP_SUPPORT */ + + } + + pHtPhy->word = (pMaxHtPhy->word); + if (bLinkUp && (pAd->OpMode == OPMODE_STA)) + { + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; + } + else + { + if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B) && + pAd->CommonCfg.Channel <= 14) + { + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + pAd->CommonCfg.RtsRate = RATE_11; + } + else + { + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + + /* Keep Basic Mlme Rate.*/ + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; + if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) + /* MTK patch fix dhcp issue on new Apple and others buggy clients (use RATE_6 instead of 24) */ + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_6]; + else + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; + pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; + +#ifdef CONFIG_AP_SUPPORT +#ifdef MCAST_RATE_SPECIFIC + { + /* set default value if MCastPhyMode is not initialized */ + HTTRANSMIT_SETTING tPhyMode; + + memset(&tPhyMode, 0, sizeof(HTTRANSMIT_SETTING)); + if (memcmp(&pAd->CommonCfg.MCastPhyMode, &tPhyMode, sizeof(HTTRANSMIT_SETTING)) == 0) + { + memmove(&pAd->CommonCfg.MCastPhyMode, &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, + sizeof(HTTRANSMIT_SETTING)); + } + } +#endif /* MCAST_RATE_SPECIFIC */ +#endif /* CONFIG_AP_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, (" %s(): (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", + __FUNCTION__, RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], + RateIdToMbps[pAd->CommonCfg.MaxTxRate], + RateIdToMbps[pAd->CommonCfg.MinTxRate], + /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); + DBGPRINT(RT_DEBUG_TRACE, (" %s(): (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", + __FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate], + RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", + __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word, + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word, + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word, + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); +} + + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + This function update HT Rate setting. + Input Wcid value is valid for 2 case : + 1. it's used for Station in infra mode that copy AP rate to Mactable. + 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeUpdateHtTxRates(RTMP_ADAPTER *pAd, UCHAR apidx) +{ + /*UCHAR StbcMcs;*/ + RT_HT_CAPABILITY *pRtHtCap = NULL; + RT_PHY_INFO *pActiveHtPhy = NULL; + /*ULONG BasicMCS;*/ + RT_PHY_INFO *pDesireHtPhy = NULL; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + struct wifi_dev *wdev = NULL; + + + DBGPRINT(RT_DEBUG_TRACE,("%s()===> \n", __FUNCTION__)); + + auto_rate_cur_p = NULL; + + do + { +#ifdef CONFIG_AP_SUPPORT + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + wdev = &pAd->ApCfg.ApCliTab[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx)); + return; + } + } +#endif /* APCLI_SUPPORT */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS; + + if (idx < MAX_WDS_ENTRY) + { + wdev = &pAd->WdsTab.WdsEntry[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + + if ((apidx < pAd->ApCfg.BssidNum) && (apidx < HW_BEACON_MAX_NUM)) + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + wdev = &pAd->StaCfg.wdev; + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while (FALSE); + + if (wdev) + { + pDesireHtPhy = &wdev->DesiredHtPhyInfo; + pActiveHtPhy = &wdev->DesiredHtPhyInfo; + pHtPhy = &wdev->HTPhyMode; + pMaxHtPhy = &wdev->MaxHTPhyMode; + pMinHtPhy = &wdev->MinHTPhyMode; + + auto_rate_cur_p = &wdev->bAutoTxRateSwitch; + } + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA) + ) + { + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->StaActive.SupportedHtPhy; + pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; + /*StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;*/ + /*BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);*/ + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + if ((!pDesireHtPhy) || pDesireHtPhy->bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; + /*StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;*/ + /*BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);*/ + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pAd->Antenna.field.TxPath >= 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + + /* Decide MAX ht rate.*/ + if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; + else + pMaxHtPhy->field.MODE = MODE_HTMIX; + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) + pMaxHtPhy->field.BW = BW_40; + else + pMaxHtPhy->field.BW = BW_20; + + if (pMaxHtPhy->field.BW == BW_20) + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); + else + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); + + if (pDesireHtPhy->MCSSet[4] != 0) + { + pMaxHtPhy->field.MCS = 32; + } + + pMaxHtPhy->field.MCS = get_ht_max_mcs(pAd, &pDesireHtPhy->MCSSet[0], + &pActiveHtPhy->MCSSet[0]); + + /* Copy MIN ht rate. rt2860???*/ + pMinHtPhy->field.BW = BW_20; + pMinHtPhy->field.MCS = 0; + pMinHtPhy->field.STBC = 0; + pMinHtPhy->field.ShortGI = 0; + /*If STA assigns fixed rate. update to fixed here.*/ +#ifdef CONFIG_STA_SUPPORT + if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff) + ) + { + CHAR i; + UCHAR j, bitmask; + + if (pDesireHtPhy->MCSSet[4] != 0) + { + pMaxHtPhy->field.MCS = 32; + pMinHtPhy->field.MCS = 32; + DBGPRINT(RT_DEBUG_TRACE,("%s():<=== Use Fixed MCS = %d\n",__FUNCTION__, pMinHtPhy->field.MCS)); + } + + for (i=23; (CHAR)i >= 0; i--) + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask)) + { + pMaxHtPhy->field.MCS = i; + pMinHtPhy->field.MCS = i; + break; + } + if (i==0) + break; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + + /* Decide ht rate*/ + pHtPhy->field.STBC = pMaxHtPhy->field.STBC; + pHtPhy->field.BW = pMaxHtPhy->field.BW; + pHtPhy->field.MODE = pMaxHtPhy->field.MODE; + pHtPhy->field.MCS = pMaxHtPhy->field.MCS; + pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; + + /* use default now. rt2860*/ + if (pDesireHtPhy->MCSSet[0] != 0xff) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, (" %s():<---.AMsduSize = %d \n", __FUNCTION__, pAd->CommonCfg.DesiredHtPhy.AmsduSize )); + DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, + pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); + DBGPRINT(RT_DEBUG_TRACE,("%s():<=== \n", __FUNCTION__)); +} + + +VOID BATableInit(RTMP_ADAPTER *pAd, BA_TABLE *Tab) +{ + int i; + + Tab->numAsOriginator = 0; + Tab->numAsRecipient = 0; + Tab->numDoneOriginator = 0; + NdisAllocateSpinLock(pAd, &pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; + NdisAllocateSpinLock(pAd, &(Tab->BARecEntry[i].RxReRingLock)); + } + for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) + { + Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; + } +} + + +VOID BATableExit(RTMP_ADAPTER *pAd) +{ + int i; + + for(i=0; iBATable.BARecEntry[i].RxReRingLock); + } + NdisFreeSpinLock(&pAd->BATabLock); +} +#endif /* DOT11_N_SUPPORT */ + + +VOID MlmeRadioOff(RTMP_ADAPTER *pAd) +{ + RTMP_MLME_RADIO_OFF(pAd); +} + + +VOID MlmeRadioOn(RTMP_ADAPTER *pAd) +{ + RTMP_MLME_RADIO_ON(pAd); +} + + +/*! \brief initialize BSS table + * \param p_tab pointer to the table + * \return none + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID BssTableInit(BSS_TABLE *Tab) +{ + int i; + + Tab->BssNr = 0; + Tab->BssOverlapNr = 0; + + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) + { + UCHAR *pOldAddr = Tab->BssEntry[i].pVarIeFromProbRsp; + + NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); + + Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */ + if (pOldAddr) + { + RTMPZeroMemory(pOldAddr, MAX_VIE_LEN); + Tab->BssEntry[i].pVarIeFromProbRsp = pOldAddr; + } + } +} + + +/*! \brief search the BSS table by SSID + * \param p_tab pointer to the bss table + * \param ssid SSID string + * \return index of the table, BSS_NOT_FOUND if not in the table + * \pre + * \post + * \note search by sequential search + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSearch(BSS_TABLE *Tab, UCHAR *pBssid, UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + + /* + Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. + We should distinguish this case. + */ + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +//edcca same channel ap count +/* get ap counts from some channel*/ +#ifdef ED_MONITOR +ULONG BssChannelAPCount( + IN PRTMP_ADAPTER pAd, + IN BSS_TABLE *Tab, + IN UCHAR Channel) +{ + UCHAR i; + ULONG ap_count = 0; + + for (i = 0; i < Tab->BssNr; i++) + { + //change to also check rssi threshold + if ((Tab->BssEntry[i].Channel == Channel) && + (Tab->BssEntry[i].Rssi > pAd->ed_rssi_threshold)) + { + ap_count ++; + } + } + return ap_count; +} +#endif /* ED_MONITOR */ + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + + /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.*/ + /* We should distinguish this case.*/ + /* */ + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && + SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && + (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || + (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || + (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +ULONG BssSsidTableSearchBySSID(BSS_TABLE *Tab, UCHAR *pSsid, UCHAR SsidLen) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +VOID BssTableDeleteEntry(BSS_TABLE *Tab, UCHAR *pBssid, UCHAR Channel) +{ + UCHAR i, j; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((Tab->BssEntry[i].Channel == Channel) && + (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) + { + UCHAR *pOldAddr = NULL; + + for (j = i; j < Tab->BssNr - 1; j++) + { + pOldAddr = Tab->BssEntry[j].pVarIeFromProbRsp; + NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); + if (pOldAddr) + { + RTMPZeroMemory(pOldAddr, MAX_VIE_LEN); + NdisMoveMemory(pOldAddr, + Tab->BssEntry[j + 1].pVarIeFromProbRsp, + Tab->BssEntry[j + 1].VarIeFromProbeRspLen); + Tab->BssEntry[j].pVarIeFromProbRsp = pOldAddr; + } + } + + pOldAddr = Tab->BssEntry[Tab->BssNr - 1].pVarIeFromProbRsp; + NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY)); + if (pOldAddr) + { + RTMPZeroMemory(pOldAddr, MAX_VIE_LEN); + Tab->BssEntry[Tab->BssNr - 1].pVarIeFromProbRsp = pOldAddr; + } + + Tab->BssNr -= 1; + return; + } + } +} + + +/*! \brief + * \param + * \return + * \pre + * \post + */ +VOID BssEntrySet( + IN RTMP_ADAPTER *pAd, + OUT BSS_ENTRY *pBss, + IN BCN_IE_LIST *ie_list, + IN CHAR Rssi, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + IN UCHAR Snr0, + IN UCHAR Snr1 +#endif + ) +{ + COPY_MAC_ADDR(pBss->Bssid, ie_list->Bssid); + /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID*/ + pBss->Hidden = 1; + if (ie_list->SsidLen > 0) + { + /* For hidden SSID AP, it might send beacon with SSID len equal to 0*/ + /* Or send beacon /probe response with SSID len matching real SSID length,*/ + /* but SSID is all zero. such as "00-00-00-00" with length 4.*/ + /* We have to prevent this case overwrite correct table*/ + if (NdisEqualMemory(ie_list->Ssid, ZeroSsid, ie_list->SsidLen) == 0) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pBss->Ssid, ie_list->Ssid, ie_list->SsidLen); + pBss->SsidLen = ie_list->SsidLen; + pBss->Hidden = 0; + } + } + else + { + /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ + if (NdisEqualMemory(pBss->Ssid, ZeroSsid, pBss->SsidLen)) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + pBss->SsidLen = 0; + } + } + + pBss->BssType = ie_list->BssType; + pBss->BeaconPeriod = ie_list->BeaconPeriod; + if (ie_list->BssType == BSS_INFRA) + { + if (ie_list->CfParm.bValid) + { + pBss->CfpCount = ie_list->CfParm.CfpCount; + pBss->CfpPeriod = ie_list->CfParm.CfpPeriod; + pBss->CfpMaxDuration = ie_list->CfParm.CfpMaxDuration; + pBss->CfpDurRemaining = ie_list->CfParm.CfpDurRemaining; + } + } + else + { + pBss->AtimWin = ie_list->AtimWin; + } + + NdisGetSystemUpTime(&pBss->LastBeaconRxTime); + pBss->CapabilityInfo = ie_list->CapabilityInfo; + /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES*/ + /* Combine with AuthMode, they will decide the connection methods.*/ + pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); + ASSERT(ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + NdisMoveMemory(pBss->SupRate, ie_list->SupRate, ie_list->SupRateLen); + else + NdisMoveMemory(pBss->SupRate, ie_list->SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pBss->SupRateLen = ie_list->SupRateLen; + ASSERT(ie_list->ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (ie_list->ExtRateLen > MAX_LEN_OF_SUPPORTED_RATES) + ie_list->ExtRateLen = MAX_LEN_OF_SUPPORTED_RATES; + NdisMoveMemory(pBss->ExtRate, ie_list->ExtRate, ie_list->ExtRateLen); + pBss->NewExtChanOffset = ie_list->NewExtChannelOffset; + pBss->ExtRateLen = ie_list->ExtRateLen; + pBss->Erp = ie_list->Erp; + pBss->Channel = ie_list->Channel; + pBss->CentralChannel = ie_list->Channel; + pBss->Rssi = Rssi; +#ifdef CUSTOMER_DCC_FEATURE + pBss->Snr0 = Snr0; + pBss->Snr1 = Snr1; +#endif + /* Update CkipFlag. if not exists, the value is 0x0*/ + pBss->CkipFlag = ie_list->CkipFlag; + + /* New for microsoft Fixed IEs*/ + NdisMoveMemory(pBss->FixIEs.Timestamp, &ie_list->TimeStamp, 8); + pBss->FixIEs.BeaconInterval = ie_list->BeaconPeriod; + pBss->FixIEs.Capabilities = ie_list->CapabilityInfo; +#ifdef CUSTOMER_DCC_FEATURE + pBss->LastBeaconRxTime = jiffies_to_msecs(jiffies); +#endif + /* New for microsoft Variable IEs*/ + if (LengthVIE != 0) + { + pBss->VarIELen = LengthVIE; + NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); + } + else + { + pBss->VarIELen = 0; + } + + pBss->AddHtInfoLen = 0; + pBss->HtCapabilityLen = 0; +#ifdef SMART_MESH + if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_NONE) && + (ie_list->AddHtInfo.AddHtInfo.RecomWidth == 0)) + pBss->BW = BW_20; + + if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) && + (ie_list->HtCapabilityLen > 0) && + (ie_list->HtCapability.HtCapInfo.ChannelWidth == 1)) + pBss->BW = BW_40; +#ifdef DOT11_VHT_AC + if(ie_list->vht_op_len > 0 && ie_list->vht_op_ie.vht_op_info.ch_width == 1) + pBss->BW = BW_80; + + if(ie_list->vht_op_len > 0 && ie_list->vht_cap_ie.vht_cap.ch_width> 0) + pBss->BW = BW_160;/* BW_160 */ +#endif /* DOT11_VHT_AC */ +#endif/* SMART_MESH */ +#ifdef DOT11_N_SUPPORT + if (ie_list->HtCapabilityLen> 0) + { + pBss->HtCapabilityLen = ie_list->HtCapabilityLen; + NdisMoveMemory(&pBss->HtCapability, &ie_list->HtCapability, ie_list->HtCapabilityLen); + if (ie_list->AddHtInfoLen > 0) + { + pBss->AddHtInfoLen = ie_list->AddHtInfoLen; + NdisMoveMemory(&pBss->AddHtInfo, &ie_list->AddHtInfo, ie_list->AddHtInfoLen); + + pBss->CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo, + &ie_list->HtCapability); + } + +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len) { + NdisMoveMemory(&pBss->vht_cap_ie, &ie_list->vht_cap_ie, ie_list->vht_cap_len); + pBss->vht_cap_len = ie_list->vht_cap_len; + } + + if (ie_list->vht_op_len) { + VHT_OP_IE *vht_op; + + NdisMoveMemory(&pBss->vht_op_ie, &ie_list->vht_op_ie, ie_list->vht_op_len); + pBss->vht_op_len = ie_list->vht_op_len; + vht_op = &ie_list->vht_op_ie; + if ((vht_op->vht_op_info.ch_width > 0) && + (ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) && + (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pBss->CentralChannel != ie_list->AddHtInfo.ControlChan)) + { + UCHAR cent_ch; + + cent_ch = vht_cent_ch_freq(pAd, ie_list->AddHtInfo.ControlChan); + DBGPRINT(RT_DEBUG_INFO, ("%s():VHT cent_ch=%d, vht_op_info->center_freq_1=%d, Bss->CentCh=%d, change from CentralChannel to cent_ch!\n", + __FUNCTION__, cent_ch, vht_op->vht_op_info.center_freq_1, pBss->CentralChannel)); + pBss->CentralChannel = vht_op->vht_op_info.center_freq_1; + } + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + + BssCipherParse(pBss); + + /* new for QOS*/ + if (ie_list->EdcaParm.bValid) + NdisMoveMemory(&pBss->EdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM)); + else + pBss->EdcaParm.bValid = FALSE; + if (ie_list->QosCapability.bValid) + NdisMoveMemory(&pBss->QosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); + else + pBss->QosCapability.bValid = FALSE; + if (ie_list->QbssLoad.bValid) + NdisMoveMemory(&pBss->QbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + else + pBss->QbssLoad.bValid = FALSE; + + { + PEID_STRUCT pEid; + USHORT Length = 0; + +#ifdef WSC_INCLUDED + pBss->WpsAP = 0x00; + pBss->WscDPIDFromWpsAP = 0xFFFF; +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT + NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); + NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); + NdisZeroMemory(&pBss->WpsIE.IE[0], MAX_CUSTOM_LEN); + pBss->WpaIE.IELen = 0; + pBss->RsnIE.IELen = 0; + pBss->WpsIE.IELen = 0; +#ifdef WAPI_SUPPORT + NdisZeroMemory(&pBss->WapiIE.IE[0], MAX_CUSTOM_LEN); + pBss->WapiIE.IELen = 0; +#endif /* WAPI_SUPPORT */ +#ifdef EXT_BUILD_CHANNEL_LIST + NdisZeroMemory(&pBss->CountryString[0], 3); + pBss->bHasCountryIE = FALSE; +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) + pBss->bHasMDIE = FALSE; + NdisZeroMemory(&pBss->FT_MDIE, sizeof(FT_MDIE)); +#endif /* defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) */ + + pEid = (PEID_STRUCT) pVIE; + while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) + { +#define WPS_AP 0x01 + switch(pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) +#ifdef IWSC_SUPPORT + || NdisEqualMemory(pEid->Octet, IWSC_OUI, 4) +#endif /* IWSC_SUPPORT */ + ) + { +#ifdef WSC_INCLUDED + pBss->WpsAP |= WPS_AP; + WscCheckWpsIeFromWpsAP(pAd, + pEid, + &pBss->WscDPIDFromWpsAP); +#endif /* WSC_INCLUDED */ +#ifdef CONFIG_STA_SUPPORT + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->WpsIE.IELen = 0; + break; + } + pBss->WpsIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->WpsIE.IE, pEid, pBss->WpsIE.IELen); +#endif /* CONFIG_STA_SUPPORT */ + break; + } +#ifdef SMART_MESH + if ((pEid->Len >= NTGR_OUI_LEN) && NdisEqualMemory(pEid->Octet, NETGEAR_OUI, NTGR_OUI_LEN)) + { + Set_Check_RadarChannelAP(pAd,ie_list->Channel, pBss); + if(pEid->Len > NTGR_OUI_LEN) + { +#ifdef MWDS + pBss->bSupportMWDS = (pEid->Octet[3] & 0x01) ? TRUE : FALSE; +#endif /* MWDS */ + pBss->bSupportSmartMesh = (pEid->Octet[3] & 0x02) ? TRUE : FALSE; +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + pBss->bSupportHiddenWPS = (pEid->Octet[3] & 0x04) ? TRUE : FALSE; + if((pEid->Len - NTGR_OUI_LEN) >= NTGR_CUSTOM_IE_MAX_LEN) + { + pBss->bRunningHiddenWPS = (pEid->Octet[5] & HIDDEN_WPS_STATE_RUNNING) ? TRUE : FALSE; + pBss->bHiddenWPSRegistrar = (pEid->Octet[5] & HIDDEN_WPS_ROLE_REGISTRAR) ? TRUE : FALSE; + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + } + break; + } +#endif /* defined(SMART_MESH) */ +#ifdef CONFIG_STA_SUPPORT + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->WpaIE.IELen = 0; + break; + } + pBss->WpaIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen); + } +#endif /* CONFIG_STA_SUPPORT */ + break; + +#ifdef CONFIG_STA_SUPPORT + case IE_RSN: + if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->RsnIE.IELen = 0; + break; + } + pBss->RsnIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen); + } + break; +#ifdef WAPI_SUPPORT + case IE_WAPI: + if (NdisEqualMemory(pEid->Octet + 4, WAPI_OUI, 3)) + { + UCHAR idx; + snprintf((PSTRING) pBss->WapiIE.IE, sizeof(pBss->WapiIE.IE), "wapi_ie=%02x%02x", pEid->Eid, pEid->Len); + for (idx = 0; idx < pEid->Len; idx++) + { + snprintf((PSTRING) pBss->WapiIE.IE, sizeof(pBss->WapiIE.IE), "%s%02x", pBss->WapiIE.IE, (unsigned char)pEid->Octet[idx]); + } + pBss->WapiIE.IELen = (pEid->Len*2) + 8; /* 2: ID(1 byte), LEN (1 byte), 8: len of "wapi_ie="*/ + } + break; +#endif /* WAPI_SUPPORT */ +#ifdef EXT_BUILD_CHANNEL_LIST + case IE_COUNTRY: + NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3); + pBss->bHasCountryIE = TRUE; + break; +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) + case IE_FT_MDIE: + if (pEid->Len == sizeof(FT_MDIE)) + { + pBss->bHasMDIE = TRUE; + NdisMoveMemory(&pBss->FT_MDIE, pEid->Octet, pEid->Len); + } + break; +#endif /* defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) */ + } + Length = Length + 2 + (USHORT)pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + } +} + + + +/*! + * \brief insert an entry into the bss table + * \param p_tab The BSS table + * \param Bssid BSSID + * \param ssid SSID + * \param ssid_len Length of SSID + * \param bss_type + * \param beacon_period + * \param timestamp + * \param p_cf + * \param atim_win + * \param cap + * \param rates + * \param rates_len + * \param channel_idx + * \return none + * \pre + * \post + * \note If SSID is identical, the old entry will be replaced by the new one + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *Tab, + IN BCN_IE_LIST *ie_list, + IN CHAR Rssi, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + IN UCHAR Snr0, + IN UCHAR Snr1 +#endif + ) +{ + ULONG Idx; +#ifdef APCLI_SUPPORT + BOOLEAN bInsert = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR i; +#endif /* APCLI_SUPPORT */ + + + Idx = BssTableSearch(Tab, ie_list->Bssid, ie_list->Channel); + if (Idx == BSS_NOT_FOUND) + { + if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) + { + /* + It may happen when BSS Table was full. + The desired AP will not be added into BSS Table + In this case, if we found the desired AP then overwrite BSS Table. + */ +#ifdef APCLI_SUPPORT + for (i = 0; i < pAd->ApCfg.ApCliNum; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + if (MAC_ADDR_EQUAL(pApCliEntry->MlmeAux.Bssid, ie_list->Bssid) + || SSID_EQUAL(pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.SsidLen, ie_list->Ssid, ie_list->SsidLen)) + { + bInsert = TRUE; + break; + } + } +#endif /* APCLI_SUPPORT */ + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) || + !OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, ie_list->Bssid) || + SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, ie_list->Ssid, ie_list->SsidLen) +#ifdef APCLI_SUPPORT + || bInsert +#endif /* APCLI_SUPPORT */ +#ifdef RT_CFG80211_SUPPORT + /* YF: Driver ScanTable full but supplicant the SSID exist on supplicant */ + || SSID_EQUAL(pAd->cfg80211_ctrl.Cfg_pending_Ssid, pAd->cfg80211_ctrl.Cfg_pending_SsidLen, ie_list->Ssid, ie_list->SsidLen) +#endif /* RT_CFG80211_SUPPORT */ + ) + { + Idx = Tab->BssOverlapNr; + NdisZeroMemory(&(Tab->BssEntry[Idx]), sizeof(BSS_ENTRY)); + BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + Snr0, + Snr1 +#endif + ); + Tab->BssOverlapNr += 1; + Tab->BssOverlapNr = Tab->BssOverlapNr % MAX_LEN_OF_BSS_TABLE; +#ifdef RT_CFG80211_SUPPORT + pAd->cfg80211_ctrl.Cfg_pending_SsidLen = 0; + NdisZeroMemory(pAd->cfg80211_ctrl.Cfg_pending_Ssid, MAX_LEN_OF_SSID+1); +#endif /* RT_CFG80211_SUPPORT */ + } + return Idx; + } + else + { + return BSS_NOT_FOUND; + } + } + Idx = Tab->BssNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + Snr0, + Snr1 +#endif + ); + Tab->BssNr++; + } + else + { + BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + Snr0, + Snr1 +#endif + ); + } + + return Idx; +} + + +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID TriEventInit(RTMP_ADAPTER *pAd) +{ + UCHAR i; + + for (i = 0;i < MAX_TRIGGER_EVENT;i++) + pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; + + pAd->CommonCfg.TriggerEventTab.EventANo = 0; + pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0; +} + + +INT TriEventTableSetEntry( + IN RTMP_ADAPTER *pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN UCHAR *pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo) +{ + /* Event A, legacy AP exist.*/ + if (HtCapabilityLen == 0) + { + UCHAR index; + + /* + Check if we already set this entry in the Event Table. + */ + for (index = 0; indexEventA[index].bValid == TRUE) && + (Tab->EventA[index].Channel == ChannelNo) && + (Tab->EventA[index].RegClass == RegClass) + ) + { + return 0; + } + } + + /* + If not set, add it to the Event table + */ + if (Tab->EventANo < MAX_TRIGGER_EVENT) + { + RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6); + Tab->EventA[Tab->EventANo].bValid = TRUE; + Tab->EventA[Tab->EventANo].Channel = ChannelNo; + if (RegClass != 0) + { + /* Beacon has Regulatory class IE. So use beacon's*/ + Tab->EventA[Tab->EventANo].RegClass = RegClass; + } + else + { + /* Use Station's Regulatory class instead.*/ + /* If no Reg Class in Beacon, set to "unknown"*/ + /* TODO: Need to check if this's valid*/ + Tab->EventA[Tab->EventANo].RegClass = 0; /* ????????????????? need to check*/ + } + Tab->EventANo ++; + } + } +#ifdef DOT11V_WNM_SUPPORT + /* Not complete yet. Ignore for compliing successfully.*/ +#else + else if (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant) + { + /* Event B. My BSS beacon has Intolerant40 bit set*/ + Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay; + } +#endif /* DOT11V_WNM_SUPPORT */ + + return 0; +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) */ + +#ifdef CONFIG_STA_SUPPORT +VOID BssTableSsidSort( + IN RTMP_ADAPTER *pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + INT i; +#ifdef WSC_STA_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* WSC_STA_SUPPORT */ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + BssTableInit(OutTab); + + if ((SsidLen == 0) && + (pAd->StaCfg.bAutoConnectIfNoSSID == FALSE)) + return; + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; + BOOLEAN bIsHiddenApIncluded = FALSE; + + if ( ((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pInBss->Channel)) +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */ + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + { + if (pInBss->Hidden) + bIsHiddenApIncluded = TRUE; + } + + + if ((pInBss->BssType == pAd->StaCfg.BssType) && + (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x80) + { + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + OutTab->BssNr++; + continue; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && pWpsCtrl->bWscTrigger) + { + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + OutTab->BssNr++; + continue; + } +#endif /* WSC_STA_SUPPORT */ + +#ifdef EXT_BUILD_CHANNEL_LIST + /* If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.*/ + if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) && + (pInBss->bHasCountryIE == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n")); + continue; + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DOT11_N_SUPPORT + /* 2.4G/5G N only mode*/ + if ((pInBss->HtCapabilityLen == 0) && + (WMODE_HT_ONLY(pAd->CommonCfg.PhyMode))) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } + + if ((pAd->CommonCfg.PhyMode == (WMODE_G | WMODE_GN)) && + ((pInBss->SupRateLen + pInBss->ExtRateLen) < 12)) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in GN-only Mode, this AP is in B mode.\n")); + continue; + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11W_PMF_SUPPORT + if (((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + && (pInBss)) + { + CLIENT_STATUS_CLEAR_FLAG(pInBss, fCLIENT_STATUS_PMF_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256); + + RSN_CAPABILITIES RsnCap; + NdisMoveMemory(&RsnCap, &pInBss->WPA2.RsnCapability, sizeof(RSN_CAPABILITIES)); + RsnCap.word = cpu2le16(RsnCap.word); + if ((pAd->StaCfg.PmfCfg.MFPR) && (RsnCap.field.MFPC == FALSE)) + continue; + + if (((pAd->StaCfg.PmfCfg.MFPC == FALSE) && (RsnCap.field.MFPC == FALSE)) + || (pAd->StaCfg.PmfCfg.MFPC && RsnCap.field.MFPC && (pAd->StaCfg.PmfCfg.MFPR == FALSE) && (RsnCap.field.MFPR == FALSE))) + { + if ((pAd->StaCfg.PmfCfg.PMFSHA256) && (pInBss->IsSupportSHA256KeyDerivation == FALSE)) + continue; + } + + if ((pAd->StaCfg.PmfCfg.MFPC) && (RsnCap.field.MFPC)) + CLIENT_STATUS_SET_FLAG(pInBss, fCLIENT_STATUS_PMF_CAPABLE); + + if ((pAd->StaCfg.PmfCfg.PMFSHA256 && pInBss->IsSupportSHA256KeyDerivation) + || (pAd->StaCfg.PmfCfg.MFPC && RsnCap.field.MFPR) + || (pAd->StaCfg.PmfCfg.MFPC && pInBss->IsSupportSHA256KeyDerivation)) + CLIENT_STATUS_SET_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256); + + } +#endif /* DOT11W_PMF_SUPPORT */ + + /* New for WPA2*/ + /* Check the Authmode first*/ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/ + if ((wdev->AuthMode != pInBss->AuthMode) && (wdev->AuthMode != pInBss->AuthModeAux)) + /* None matched*/ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting*/ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA.GroupCipher) + continue; + + /* check group cipher*/ + if ((wdev->WepStatus < pInBss->WPA.GroupCipher) && + (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) && + (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled)) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA.PairCipher) && + (wdev->WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA2.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA2.GroupCipher) + continue; + + /* check group cipher*/ + if ((wdev->WepStatus < pInBss->WPA.GroupCipher) && + (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) && + (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled)) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA2.PairCipher) && + (wdev->WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + /* check cipher algorithm*/ + if ((wdev->WepStatus != pInBss->WAPI.GroupCipher) || + (wdev->WepStatus != pInBss->WAPI.PairCipher)) + continue; + } +#endif /* WAPI_SUPPORT */ + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss*/ + else if (wdev->WepStatus != pInBss->WepStatus) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", wdev->WepStatus, pInBss->WepStatus)); + + /* For the SESv2 case, we will not qualify WepStatus.*/ + + if (!pInBss->bSES) + continue; + } + + /* Since the AP is using hidden SSID, and we are trying to connect to ANY*/ + /* It definitely will fail. So, skip it.*/ + /* CCX also require not even try to connect it!!*/ + if (SsidLen == 0) + continue; + + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } + else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + +#ifdef WSC_STA_SUPPORT + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && pWpsCtrl->bWscTrigger) + { + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + OutTab->BssNr++; + continue; + } +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* 2.4G/5G N only mode*/ + if ((pInBss->HtCapabilityLen == 0) && + WMODE_HT_ONLY(pAd->CommonCfg.PhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } + + if ((pAd->CommonCfg.PhyMode == (WMODE_G | WMODE_GN)) && + ((pInBss->SupRateLen + pInBss->ExtRateLen) < 12)) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in GN-only Mode, this AP is in B mode.\n")); + continue; + } +#endif /* DOT11_N_SUPPORT */ + + /* New for WPA2*/ + /* Check the Authmode first*/ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/ + if ((wdev->AuthMode != pInBss->AuthMode) && (wdev->AuthMode != pInBss->AuthModeAux)) + /* None matched*/ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting*/ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA.GroupCipher) + continue; + + /* check group cipher*/ + if (wdev->WepStatus < pInBss->WPA.GroupCipher) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA.PairCipher) && + (wdev->WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA2.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA2.GroupCipher) + continue; + + /* check group cipher*/ + if (wdev->WepStatus < pInBss->WPA2.GroupCipher) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA2.PairCipher) && + (wdev->WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + /* check cipher algorithm*/ + if ((wdev->WepStatus != pInBss->WAPI.GroupCipher) || + (wdev->WepStatus != pInBss->WAPI.PairCipher)) + continue; + } +#endif /* WAPI_SUPPORT */ + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss*/ + else if (wdev->WepStatus != pInBss->WepStatus) + continue; + + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } +#ifdef WSC_STA_SUPPORT + else if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pWpsCtrl->bWscTrigger) && + MAC_ADDR_EQUAL(pWpsCtrl->WscBssid, pInBss->Bssid)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + /* + Linksys WRT610N WPS AP will change the SSID from linksys to linksys_WPS_ + when the Linksys WRT610N is in the state 'WPS Unconfigured' after set to factory default. + */ + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pInBss->Ssid, pInBss->SsidLen); + pAd->MlmeAux.SsidLen = pInBss->SsidLen; + + + /* Update Reconnect Ssid, that user desired to connect.*/ + + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + + OutTab->BssNr++; + continue; + } +#endif /* WSC_STA_SUPPORT */ + + if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) + break; + } + + BssTableSortByRssi(OutTab, FALSE); +} +#endif /* CONFIG_STA_SUPPORT */ + +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab, + IN BOOLEAN isInverseOrder) +{ + INT i, j; + BSS_ENTRY *pTmpBss = NULL; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pTmpBss, sizeof(BSS_ENTRY)); + if (pTmpBss == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + for (i = 0; i < OutTab->BssNr - 1; i++) + { + for (j = i+1; j < OutTab->BssNr; j++) + { + if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi ? + !isInverseOrder : isInverseOrder) + { + if (OutTab->BssEntry[j].Rssi != OutTab->BssEntry[i].Rssi ) + { + NdisMoveMemory(pTmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[i], pTmpBss, sizeof(BSS_ENTRY)); + } + } + } + } + + if (pTmpBss != NULL) + os_free_mem(NULL, pTmpBss); +} + +VOID BssCipherParse(BSS_ENTRY *pBss) +{ + PEID_STRUCT pEid; + PUCHAR pTmp; + PRSN_IE_HEADER_STRUCT pRsnHeader; + PCIPHER_SUITE_STRUCT pCipher; + PAKM_SUITE_STRUCT pAKM; + USHORT Count; + INT Length; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + + + /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.*/ + + if (pBss->Privacy) + { + pBss->WepStatus = Ndis802_11WEPEnabled; + } + else + { + pBss->WepStatus = Ndis802_11WEPDisabled; + } + /* Set default to disable & open authentication before parsing variable IE*/ + pBss->AuthMode = Ndis802_11AuthModeOpen; + pBss->AuthModeAux = Ndis802_11AuthModeOpen; +#ifdef DOT11W_PMF_SUPPORT + pBss->IsSupportSHA256KeyDerivation = FALSE; +#endif /* DOT11W_PMF_SUPPORT */ + + /* Init WPA setting*/ + pBss->WPA.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA.RsnCapability = 0; + pBss->WPA.bMixMode = FALSE; + + /* Init WPA2 setting*/ + pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA2.RsnCapability = 0; + pBss->WPA2.bMixMode = FALSE; + +#ifdef WAPI_SUPPORT + /* Init WAPI setting*/ + pBss->WAPI.PairCipher = Ndis802_11WEPDisabled; + pBss->WAPI.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WAPI.GroupCipher = Ndis802_11WEPDisabled; + pBss->WAPI.RsnCapability = 0; + pBss->WAPI.bMixMode = FALSE; +#endif /* WAPI_SUPPORT */ + + Length = (INT) pBss->VarIELen; + + while (Length > 0) + { + /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently*/ + pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; + pEid = (PEID_STRUCT) pTmp; + switch (pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) + { + pBss->bSES = TRUE; + break; + } + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) + { + /* if unsupported vendor specific IE*/ + break; + } + /* + Skip OUI, version, and multicast suite + This part should be improved in the future when AP supported multiple cipher suite. + For now, it's OK since almost all APs have fixed cipher suite supported. + */ + /* pTmp = (PUCHAR) pEid->Octet;*/ + pTmp += 11; + + /* + Cipher Suite Selectors from Spec P802.11i/D3.2 P26. + Value Meaning + 0 None + 1 WEP-40 + 2 Tkip + 3 WRAP + 4 AES + 5 WEP-104 + */ + /* Parse group cipher*/ + switch (*pTmp) + { + case 1: + pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled; + break; + case 2: + pBss->WPA.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + pBss->WPA.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + /* number of unicast suite*/ + pTmp += 1; + + /* skip all unicast cipher suites*/ + /*Count = *(PUSHORT) pTmp; */ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + /* Skip OUI*/ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > pBss->WPA.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; + pBss->WPA.PairCipher = TmpCipher; + } + else + { + pBss->WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + + /* 4. get AKM suite counts*/ + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + pTmp += 3; + + switch (*pTmp) + { + case 1: + /* Set AP support WPA-enterprise mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA; + break; + case 2: + /* Set AP support WPA-PSK mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPAPSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + pTmp += 1; + + /* Fixed for WPA-None*/ + if (pBss->BssType == BSS_ADHOC) + { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WepStatus = pBss->WPA.GroupCipher; + /* Patched bugs for old driver*/ + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + else + pBss->WepStatus = pBss->WPA.PairCipher; + + /* Check the Pair & Group, if different, turn on mixed mode flag*/ + if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) + pBss->WPA.bMixMode = TRUE; + + break; + + case IE_RSN: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + /* 0. Version must be 1*/ + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Check group cipher*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + /* Parse group cipher*/ + switch (pCipher->Type) + { + case 1: + pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled; + break; + case 2: + pBss->WPA2.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + pBss->WPA2.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + /* set to correct offset for next parsing*/ + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + /* 2. Get pairwise cipher counts*/ + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* 3. Get pairwise cipher*/ + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + /* Skip OUI*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > pBss->WPA2.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; + pBss->WPA2.PairCipher = TmpCipher; + } + else + { + pBss->WPA2.PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + /* 4. get AKM suite counts*/ + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* 5. Get AKM ciphers*/ + /* Parsing all AKM ciphers*/ + while (Count > 0) + { + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 0: + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPANone; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + break; + case 1: +#ifdef DOT11R_FT_SUPPORT + case 3: +#endif /* DOT11R_FT_SUPPORT */ + /* Set AP support WPA-enterprise mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2; + break; + case 2: +#ifdef DOT11R_FT_SUPPORT + case 4: +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + case 6: +#endif /* DOT11W_PMF_SUPPORT */ + /* Set AP support WPA-PSK mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; + +#ifdef DOT11W_PMF_SUPPORT + if (pAKM->Type == 6) + pBss->IsSupportSHA256KeyDerivation = TRUE; +#endif /* DOT11W_PMF_SUPPORT */ + + break; + default: + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeMax; + else + pBss->AuthModeAux = Ndis802_11AuthModeMax; + break; + } + pTmp += sizeof(AKM_SUITE_STRUCT); + Count--; + } + + /* Fixed for WPA-None*/ + if (pBss->BssType == BSS_ADHOC) + { + pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux; + pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; + pBss->WepStatus = pBss->WPA.GroupCipher; + /* Patched bugs for old driver*/ + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + pBss->WepStatus = pBss->WPA2.PairCipher; + + /* 6. Get RSN capability*/ + /*pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;*/ + pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* Check the Pair & Group, if different, turn on mixed mode flag*/ + if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) + pBss->WPA2.bMixMode = TRUE; + + break; +#ifdef WAPI_SUPPORT + case IE_WAPI: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + /* 0. The version number must be 1*/ + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Get AKM suite counts*/ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + pTmp += sizeof(USHORT); + + /* 2. Get AKM ciphers*/ + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 1: + /* Support WAI certificate authentication*/ + pBss->AuthMode = Ndis802_11AuthModeWAICERT; + break; + case 2: + /* Support WAI PSK*/ + pBss->AuthMode = Ndis802_11AuthModeWAIPSK; + break; + default: + break; + } + pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); + + /* 3. Get pairwise cipher counts*/ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + pTmp += sizeof(USHORT); + + /* 4. Get pairwise cipher*/ + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3)) + break; + + /* Skip OUI*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + TmpCipher = Ndis802_11EncryptionSMS4Enabled; + break; + default: + break; + } + + if (TmpCipher > pBss->WAPI.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + pBss->WAPI.PairCipherAux = pBss->WAPI.PairCipher; + pBss->WAPI.PairCipher = TmpCipher; + } + else + { + pBss->WAPI.PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + /* 5. Check group cipher*/ + if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3)) + break; + + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + /* Parse group cipher*/ + switch (pCipher->Type) + { + case 1: + pBss->WAPI.GroupCipher = Ndis802_11EncryptionSMS4Enabled; + break; + default: + break; + } + /* set to correct offset for next parsing*/ + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + /* update the encryption type*/ + pBss->WepStatus = pBss->WAPI.PairCipher; + + /* update the WAPI capability*/ + pBss->WAPI.RsnCapability = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + break; +#endif /* WAPI_SUPPORT */ + default: + break; + } + Length -= (pEid->Len + 2); + } +} + + +/*! \brief generates a random mac address value for IBSS BSSID + * \param Addr the bssid location + * \return none + * \pre + * \post + */ +VOID MacAddrRandomBssid(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + INT i; + + for (i = 0; i < MAC_ADDR_LEN; i++) + { + pAddr[i] = RandomByte(pAd); + } + + pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx*/ +} + + +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->StaCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + */ +VOID MgtMacHeaderInit( + IN RTMP_ADAPTER *pAd, + INOUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pDA, + IN UCHAR *pSA, + IN UCHAR *pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + COPY_MAC_ADDR(pHdr80211->Addr2, pSA); +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + COPY_MAC_ADDR(pHdr80211->Addr2, pBssid); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + + +VOID MgtMacHeaderInitExt( + IN RTMP_ADAPTER *pAd, + IN OUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pAddr1, + IN UCHAR *pAddr2, + IN UCHAR *pAddr3) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1); + COPY_MAC_ADDR(pHdr80211->Addr2, pAddr2); + COPY_MAC_ADDR(pHdr80211->Addr3, pAddr3); +} + + +/*!*************************************************************************** + * This routine build an outgoing frame, and fill all information specified + * in argument list to the frame body. The actual frame size is the summation + * of all arguments. + * input params: + * Buffer - pointer to a pre-allocated memory segment + * args - a list of pairs. + * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this + * function will FAIL!!! + * return: + * Size of the buffer + * usage: + * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ****************************************************************************/ +ULONG MakeOutgoingFrame(UCHAR *Buffer, ULONG *FrameLen, ...) +{ + UCHAR *p; + int leng; + ULONG TotLeng; + va_list Args; + + /* calculates the total length*/ + TotLeng = 0; + va_start(Args, FrameLen); + do + { + leng = va_arg(Args, int); + if (leng == END_OF_ARGS) + { + break; + } + p = va_arg(Args, PVOID); + NdisMoveMemory(&Buffer[TotLeng], p, leng); + TotLeng = TotLeng + leng; + } while(TRUE); + + va_end(Args); /* clean up */ + *FrameLen = TotLeng; + return TotLeng; +} + + +/*! \brief Initialize The MLME Queue, used by MLME Functions + * \param *Queue The MLME Queue + * \return Always Return NDIS_STATE_SUCCESS in this implementation + * \pre + * \post + * \note Because this is done only once (at the init stage), no need to be locked + + IRQL = PASSIVE_LEVEL + + */ +NDIS_STATUS MlmeQueueInit( + IN RTMP_ADAPTER *pAd, +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *EAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *Queue) +{ + INT i; + + NdisAllocateSpinLock(pAd, &Queue->Lock); + + Queue->Num = 0; + Queue->Head = 0; + Queue->Tail = 0; +#ifdef SMART_MESH + Queue->QueueFullCnt = 0; +#endif /* SMART_MESH */ + + for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) + { + Queue->Entry[i].Occupied = FALSE; + Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); + } + +#ifdef EAPOL_QUEUE_SUPPORT + NdisAllocateSpinLock(pAd, &EAP_Queue->Lock); + + EAP_Queue->Num = 0; + EAP_Queue->Head = 0; + EAP_Queue->Tail = 0; +#ifdef SMART_MESH + EAP_Queue->QueueFullCnt = 0; +#endif /* SMART_MESH */ + + for (i = 0; i < MAX_LEN_OF_EAP_QUEUE; i++) + { + EAP_Queue->Entry[i].Occupied = FALSE; + EAP_Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(EAP_Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); + } +#endif /* EAPOL_QUEUE_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + */ +BOOLEAN MlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 1)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].Priv = Priv; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv) +{ + INT Tail; + EAP_MLME_QUEUE *Queue = (EAP_MLME_QUEUE *)&pAd->Mlme.EAP_Queue; + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("%s: msg too large, size = %ld \n", __FUNCTION__, MsgLen)); + return FALSE; + } + + if (EAPMlmeQueueFull(Queue)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_EAP_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].Priv = Priv; + + if (Msg != NULL) + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + + NdisReleaseSpinLock(&(Queue->Lock)); + + return TRUE; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + + +/*! \brief This function is used when Recv gets a MLME message + * \param *Queue The MLME Queue + * \param TimeStampHigh The upper 32 bit of timestamp + * \param TimeStampLow The lower 32 bit of timestamp + * \param Rssi The receiving RSSI strength + * \param MsgLen The length of the message + * \param *Msg The message pointer + * \return TRUE if everything ok, FALSE otherwise (like Queue Full) + * \pre + * \post + */ +BOOLEAN MlmeEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, +#ifdef CUSTOMER_DCC_FEATURE + IN UCHAR Snr0, + IN UCHAR Snr1, +#endif + IN ULONG MsgLen, + IN VOID *Msg, + IN UCHAR Signal, + IN UCHAR OpMode) +{ + INT Tail, Machine = 0xff; + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + INT MsgType = 0x0; + +#ifdef EAPOL_QUEUE_SUPPORT + BOOLEAN bEAPQueueFull; + EAP_MLME_QUEUE *EAP_Queue = (EAP_MLME_QUEUE *)&pAd->Mlme.EAP_Queue; +#endif /* EAPOL_QUEUE_SUPPORT */ + BOOLEAN bMlmeQueueFull; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; +#ifdef APCLI_SUPPORT + UCHAR ApCliIdx = 0; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0; +#endif /* MAC_REPEATER_SUPPORT */ + + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if(ATE_ON(pAd)) + return FALSE; +#endif /* RALINK_ATE */ + + /* + Do nothing if the driver is starting halt state. + This might happen when timer already been fired before cancel timer with mlmehalt + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT_ERR(("%s(): fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return FALSE; + } + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("%s(): frame too large, size = %ld \n", __FUNCTION__, MsgLen)); + return FALSE; + } + +#ifdef EAPOL_QUEUE_SUPPORT + bEAPQueueFull = (EAPMlmeQueueFull(EAP_Queue))? TRUE : FALSE; +#endif /* EAPOL_QUEUE_SUPPORT */ + bMlmeQueueFull = (MlmeQueueFull(Queue, 0))? TRUE : FALSE; + +#ifdef SMART_MESH +#ifdef EAPOL_QUEUE_SUPPORT + if(bEAPQueueFull) + EAP_Queue->QueueFullCnt++; +#endif /* EAPOL_QUEUE_SUPPORT */ + if(bMlmeQueueFull) + Queue->QueueFullCnt++; +#endif /* SMART_MESH */ + +#ifdef EAPOL_QUEUE_SUPPORT + if (bMlmeQueueFull && bEAPQueueFull) +#else + if (bMlmeQueueFull) +#endif /* EAPOL_QUEUE_SUPPORT */ + { + RTMP_MLME_HANDLER(pAd); + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { + +#ifdef APCLI_SUPPORT + /* + Beacon must be handled by ap-sync state machine. + Probe-rsp must be handled by apcli-sync state machine. + Those packets don't need to check its MAC address + */ + do + { + BOOLEAN bToApCli = FALSE; + UCHAR i; + /* + 1. When P2P GO On and receive Probe Response, preCheckMsgTypeSubset function will + enquene Probe response to APCli sync state machine + Solution: when GO On skip preCheckMsgTypeSubset redirect to APMsgTypeSubst + 2. When P2P Cli On and receive Probe Response, preCheckMsgTypeSubset function will + enquene Probe response to APCli sync state machine + Solution: handle MsgType == APCLI_MT2_PEER_PROBE_RSP on ApCli Sync state machine + when ApCli on idle state. + */ + for (i = 0; i < pAd->ApCfg.ApCliNum; i++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].MlmeAux.Bssid, pFrame->Hdr.Addr2)) + { + bToApCli = TRUE; + + if (pFrame->Hdr.FC.SubType == SUBTYPE_BEACON) + pAd->ApCfg.ApCliTab[i].ApCliRcvBeaconTime = pAd->Mlme.Now32; + + break; + } + } + + if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) && + preCheckMsgTypeSubset(pAd, pFrame, &Machine, &MsgType)) + break; + + if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) && bToApCli) + { + if (ApCliMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + break; + } + else + { + if (APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + break; + } + + DBGPRINT_ERR(("%s(): un-recongnized mgmt->subtype=%d, STA-%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, pFrame->Hdr.FC.SubType, PRINT_MAC(pFrame->Hdr.Addr2))); + return FALSE; + + } while (FALSE); +#else + if (!APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + { + DBGPRINT_ERR(("%s(): un-recongnized mgmt->subtype=%d\n", + __FUNCTION__, pFrame->Hdr.FC.SubType)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (OpMode == OPMODE_STA) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT */ + { + if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + { + DBGPRINT_ERR(("%s(): un-recongnized mgmt->subtype=%d\n", + __FUNCTION__, pFrame->Hdr.FC.SubType)); + return FALSE; + } + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef EAPOL_QUEUE_SUPPORT + if ((Machine == WPA_STATE_MACHINE) || (Machine == WSC_STATE_MACHINE)) + { + if (bEAPQueueFull) + { + RTMP_MLME_HANDLER(pAd); + return FALSE; + } + + /* OK, we got all the informations, it is time to put things into queue*/ + NdisAcquireSpinLock(&(EAP_Queue->Lock)); + Tail = EAP_Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (EAP_Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(EAP_Queue->Lock)); + return FALSE; + } + EAP_Queue->Tail++; + EAP_Queue->Num++; + if (EAP_Queue->Tail == MAX_LEN_OF_EAP_QUEUE) + EAP_Queue->Tail = 0; + + EAP_Queue->Entry[Tail].Occupied = TRUE; + EAP_Queue->Entry[Tail].Machine = Machine; + EAP_Queue->Entry[Tail].MsgType = MsgType; + EAP_Queue->Entry[Tail].MsgLen = MsgLen; + EAP_Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + EAP_Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + EAP_Queue->Entry[Tail].Rssi0 = Rssi0; + EAP_Queue->Entry[Tail].Rssi1 = Rssi1; + EAP_Queue->Entry[Tail].Rssi2 = Rssi2; +#ifdef CUSTOMER_DCC_FEATURE + EAP_Queue->Entry[Tail].Snr0= Snr0; + EAP_Queue->Entry[Tail].Snr1= Snr1; +#endif + EAP_Queue->Entry[Tail].Signal = Signal; + EAP_Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + EAP_Queue->Entry[Tail].OpMode = (ULONG)OpMode; + EAP_Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; + EAP_Queue->Entry[Tail].Priv = 0; +#ifdef APCLI_SUPPORT + EAP_Queue->Entry[Tail].Priv = ApCliIdx; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ApCliIdx].RepeaterCli[CliIdx].CurrentAddress, pFrame->Hdr.Addr1)) + { + EAP_Queue->Entry[Tail].Priv = (64 + (MAX_EXT_MAC_ADDR_SIZE * ApCliIdx) + CliIdx); + break; + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + if (Msg != NULL) + { + NdisMoveMemory(EAP_Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(EAP_Queue->Lock)); + } + else +#endif /* EAPOL_QUEUE_SUPPORT */ + { + if (bMlmeQueueFull) + { + RTMP_MLME_HANDLER(pAd); + return FALSE; + } + + /* OK, we got all the informations, it is time to put things into queue*/ + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + Queue->Entry[Tail].Rssi0 = Rssi0; + Queue->Entry[Tail].Rssi1 = Rssi1; + Queue->Entry[Tail].Rssi2 = Rssi2; +#ifdef CUSTOMER_DCC_FEATURE + Queue->Entry[Tail].Snr0= Snr0; + Queue->Entry[Tail].Snr1= Snr1; +#endif + Queue->Entry[Tail].Signal = Signal; + Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + Queue->Entry[Tail].OpMode = (ULONG)OpMode; + Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; + Queue->Entry[Tail].Priv = 0; +#ifdef APCLI_SUPPORT + Queue->Entry[Tail].Priv = ApCliIdx; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ApCliIdx].RepeaterCli[CliIdx].CurrentAddress, pFrame->Hdr.Addr1)) + { + Queue->Entry[Tail].Priv = (64 + (MAX_EXT_MAC_ADDR_SIZE * ApCliIdx) + CliIdx); + break; + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + } + RTMP_MLME_HANDLER(pAd); + + return TRUE; +} + + +#ifdef WSC_INCLUDED +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param TimeStampLow The lower 32 bit of timestamp, here we used for eventID. + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + */ +BOOLEAN MlmeEnqueueForWsc( + IN RTMP_ADAPTER *pAd, + IN ULONG eventID, + IN LONG senderID, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MlmeEnqueueForWsc\n")); + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueueForWsc: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 1)) + { + + return FALSE; + } + + /* OK, we got all the informations, it is time to put things into queue*/ + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Tail = 0; + } + + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = eventID; + Queue->Entry[Tail].TimeStamp.u.HighPart = senderID; + if (Msg != NULL) + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + + NdisReleaseSpinLock(&(Queue->Lock)); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MlmeEnqueueForWsc\n")); + + return TRUE; +} +#endif /* WSC_INCLUDED */ + + +/*! \brief Dequeue a message from the MLME Queue + * \param *Queue The MLME Queue + * \param *Elem The message dequeued from MLME Queue + * \return TRUE if the Elem contains something, FALSE otherwise + * \pre + * \post + */ +BOOLEAN MlmeDequeue(MLME_QUEUE *Queue, MLME_QUEUE_ELEM **Elem) +{ + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeDequeue( + IN EAP_MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem) +{ + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_EAP_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + +VOID MlmeRestartStateMachine(RTMP_ADAPTER *pAd) +{ +#ifdef RTMP_MAC_PCI + MLME_QUEUE_ELEM *Elem = NULL; +#endif /* RTMP_MAC_PCI */ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN Cancelled; +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); + +#ifdef RTMP_MAC_PCI + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } + else + { + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + +#ifdef EAPOL_QUEUE_SUPPORT + while (!EAPMlmeQueueEmpty(&pAd->Mlme.EAP_Queue)) + { + /*From message type, determine which state machine I should drive*/ + if (EAPMlmeDequeue(&pAd->Mlme.EAP_Queue, &Elem)) + { + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeRestartStateMachine: EAP MlmeQueue empty\n")); + } + } +#endif /* EAPOL_QUEUE_SUPPORT */ + + /* Remove all Mlme queues elements*/ + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) + { + /*From message type, determine which state machine I should drive*/ + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) + { + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); + } + } +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef QOS_DLS_SUPPORT + UCHAR i; +#endif /* QOS_DLS_SUPPORT */ + /* Cancel all timer events*/ + /* Be careful to cancel new added timer*/ + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + +#ifdef QOS_DLS_SUPPORT + for (i=0; iStaCfg.DLSEntry[i].Timer, &Cancelled); + } +#endif /* QOS_DLS_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Change back to original channel in case of doing scan*/ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + + /* Resume MSDU which is turned off durning scan*/ + RTMPResumeMsduTransmission(pAd); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Set all state machines back IDLE*/ + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.ActMachine.CurrState = ACT_IDLE; +#ifdef QOS_DLS_SUPPORT + pAd->Mlme.DlsMachine.CurrState = DLS_IDLE; +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + pAd->Mlme.TdlsMachine.CurrState = TDLS_IDLE; +#endif /* DOT11Z_TDLS_SUPPORT */ + + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RTMP_MAC_PCI + /* Remove running state*/ + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#endif /* RTMP_MAC_PCI */ +} + + +/*! \brief test if the MLME Queue is empty + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueEmpty(MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueEmpty( + IN EAP_MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + +/*! \brief test if the MLME Queue is full + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueFull(MLME_QUEUE *Queue, UCHAR SendId) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + if (SendId == 0) + Ans = ((Queue->Num >= (MAX_LEN_OF_MLME_QUEUE / 2)) || Queue->Entry[Queue->Tail].Occupied); + else + Ans = ((Queue->Num == MAX_LEN_OF_MLME_QUEUE) || Queue->Entry[Queue->Tail].Occupied); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueFull( + IN EAP_MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == MAX_LEN_OF_EAP_QUEUE); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + +/*! \brief The destructor of MLME Queue + * \param + * \return + * \pre + * \post + * \note Clear Mlme Queue, Set Queue->Num to Zero. + + IRQL = PASSIVE_LEVEL + + */ +VOID MlmeQueueDestroy( +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *pEAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *pQueue) +{ + NdisAcquireSpinLock(&(pQueue->Lock)); + pQueue->Num = 0; + pQueue->Head = 0; + pQueue->Tail = 0; +#ifdef SMART_MESH + pQueue->QueueFullCnt = 0; +#endif /* SMART_MESH */ + + NdisReleaseSpinLock(&(pQueue->Lock)); + NdisFreeSpinLock(&(pQueue->Lock)); + +#ifdef EAPOL_QUEUE_SUPPORT + NdisAcquireSpinLock(&(pEAP_Queue->Lock)); + pEAP_Queue->Num = 0; + pEAP_Queue->Head = 0; + pEAP_Queue->Tail = 0; +#ifdef SMART_MESH + pEAP_Queue->QueueFullCnt = 0; +#endif /* SMART_MESH */ + + NdisReleaseSpinLock(&(pEAP_Queue->Lock)); + NdisFreeSpinLock(&(pEAP_Queue->Lock)); +#endif /* EAPOL_QUEUE_SUPPORT */ +} + + +/*! \brief To substitute the message type if the message is coming from external + * \param pFrame 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 + + IRQL = DISPATCH_LEVEL + + */ +#ifdef CONFIG_STA_SUPPORT +BOOLEAN MsgTypeSubst(RTMP_ADAPTER *pAd, FRAME_802_11 *pFrame, INT *Machine, INT *MsgType) +{ + USHORT Seq, Alg; + UCHAR EAPType; + PUCHAR pData; + BOOLEAN bRV = FALSE; +#ifdef WSC_STA_SUPPORT + UCHAR EAPCode; +#endif /* WSC_STA_SUPPORT */ + + /* Pointer to start of data frames including SNAP header*/ + pData = (PUCHAR) pFrame + LENGTH_802_11; + + /* The only data type will pass to this function is EAPOL frame*/ + if (pFrame->Hdr.FC.Type == FC_TYPE_DATA) + { +#ifdef DOT11Z_TDLS_SUPPORT + if (NdisEqualMemory(TDLS_LLC_SNAP_WITH_CATEGORY, pData, LENGTH_802_1_H + 2)) + { + UCHAR TDLSType; + + /* ieee802.11z TDLS SNAP header*/ + *Machine = TDLS_STATE_MACHINE; + TDLSType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 2); + return (TDLS_MsgTypeSubst(TDLSType, (INT *)MsgType)); + } + else +#endif /* DOT11Z_TDLS_SUPPORT */ +#ifdef WSC_STA_SUPPORT + /* check for WSC state machine first*/ + if (pAd->StaCfg.WscControl.WscState >= WSC_STATE_LINK_UP) + { + *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); + + bRV = WscMsgTypeSubst(EAPType, EAPCode, MsgType); + if (bRV) + return bRV; + } +#endif /* WSC_STA_SUPPORT */ + if (bRV == FALSE) + { + *Machine = WPA_STATE_MACHINE; + EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); + return (WpaMsgTypeSubst(EAPType, (INT *) MsgType)); + } + } + + switch (pFrame->Hdr.FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_REQ; + break; + case SUBTYPE_ASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_RSP; + break; + case SUBTYPE_REASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_REQ; + break; + case SUBTYPE_REASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_RSP; + break; + case SUBTYPE_PROBE_REQ: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_REQ; + break; + case SUBTYPE_PROBE_RSP: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_RSP; + break; + case SUBTYPE_BEACON: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_BEACON; + break; + case SUBTYPE_ATIM: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_ATIM; + break; + case SUBTYPE_DISASSOC: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_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)); + NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT)); + if (Seq == 1 || Seq == 3) + { + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_ODD; + } + else if (Seq == 2 || Seq == 4) + { +#ifdef DOT11R_FT_SUPPORT + if (Alg == AUTH_MODE_FT) + { + *Machine = FT_OTA_AUTH_STATE_MACHINE; + *MsgType = FT_OTA_MT2_PEER_AUTH_EVEN; + } + else +#endif /* DOT11R_FT_SUPPORT */ + if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) + { + *Machine = AUTH_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_EVEN; + } + } + else + { + return FALSE; + } + break; + case SUBTYPE_DEAUTH: + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_DEAUTH; + break; + case SUBTYPE_ACTION: + case SUBTYPE_ACTION_NO_ACK: + *Machine = ACTION_STATE_MACHINE; +#ifdef DOT11R_FT_SUPPORT + if ((pFrame->Octet[0]&0x7F) == FT_CATEGORY_BSS_TRANSITION) + { + *Machine = FT_OTD_ACT_STATE_MACHINE; + *MsgType = FT_OTD_MT2_PEER_EVEN; + } + else +#endif /* DOT11R_FT_SUPPORT */ + /* 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; +} +#endif /* CONFIG_STA_SUPPORT */ + + +/*! \brief Initialize the state machine. + * \param *S pointer to the state machine + * \param Trans State machine transition function + * \param StNr number of states + * \param MsgNr number of messages + * \param DefFunc default function, when there is invalid state/message combination + * \param InitState initial state of the state machine + * \param Base StateMachine base, internal use only + * \pre p_sm should be a legal pointer + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineInit( + IN STATE_MACHINE *S, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base) +{ + ULONG i, j; + + /* set number of states and messages*/ + S->NrState = StNr; + S->NrMsg = MsgNr; + S->Base = Base; + + S->TransFunc = Trans; + + /* init all state transition to default function*/ + for (i = 0; i < StNr; i++) + { + for (j = 0; j < MsgNr; j++) + { + S->TransFunc[i * MsgNr + j] = DefFunc; + } + } + + /* set the starting state*/ + S->CurrState = InitState; +} + + +/*! \brief This function fills in the function pointer into the cell in the state machine + * \param *S pointer to the state machine + * \param St state + * \param Msg incoming message + * \param f the function to be executed when (state, message) combination occurs at the state machine + * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + IN ULONG Msg, + IN STATE_MACHINE_FUNC Func) +{ + ULONG MsgIdx; + + MsgIdx = Msg - S->Base; + + if (St < S->NrState && MsgIdx < S->NrMsg) + { + /* boundary checking before setting the action*/ + S->TransFunc[St * S->NrMsg + MsgIdx] = Func; + } +} + + +/*! \brief This function does the state transition + * \param *Adapter the NIC adapter pointer + * \param *S the state machine + * \param *Elem the message to be executed + * \return None + */ +VOID StateMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem, + IN ULONG CurrState) +{ + if (S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base]) + (*(S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); +} + + +/* + ========================================================================== + Description: + The drop function, when machine executes this, the message is simply + ignored. This function does nothing, the message is freed in + StateMachinePerformAction() + ========================================================================== + */ +VOID Drop(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +} + + +/* + ========================================================================== + Description: + ========================================================================== + */ +UCHAR RandomByte(RTMP_ADAPTER *pAd) +{ + ULONG i; + UCHAR R, Result; + + R = 0; + + if (pAd->Mlme.ShiftReg == 0) + NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); + + for (i = 0; i < 8; i++) + { + if (pAd->Mlme.ShiftReg & 0x00000001) + { + pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } + else + { + pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; + Result = 0; + } + R = (R << 1) | Result; + } + + return R; +} + + +UCHAR RandomByte2(RTMP_ADAPTER *pAd) +{ + UINT32 a,b; + UCHAR value, seed = 0; + + /*MAC statistic related*/ + RTMP_IO_READ32(pAd, RX_STA_CNT1, &a); + a &= 0x0000ffff; + RTMP_IO_READ32(pAd, RX_STA_CNT0, &b); + b &= 0x0000ffff; + value = (a<<16)|b; + + /*get seed by RSSI or SNR related info */ + seed = get_random_seed_by_phy(pAd); + + return value ^ seed ^ RandomByte(pAd); +} + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPCheckRates(RTMP_ADAPTER *pAd, UCHAR SupRate[], UCHAR *SupRateLen) +{ + UCHAR RateIdx, i, j; + UCHAR NewRate[12], NewRateLen; + + NewRateLen = 0; + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + RateIdx = 4; + else + RateIdx = 12; + + /* Check for support rates exclude basic rate bit */ + for (i = 0; i < *SupRateLen; i++) + for (j = 0; j < RateIdx; j++) + if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + NewRate[NewRateLen++] = SupRate[i]; + + *SupRateLen = NewRateLen; + NdisMoveMemory(SupRate, NewRate, NewRateLen); +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +BOOLEAN RTMPCheckChannel(RTMP_ADAPTER *pAd, UCHAR CentralCh, UCHAR ch) +{ + UCHAR k; + UCHAR UpperChannel = 0, LowerChannel = 0; + UCHAR NoEffectChannelinList = 0; + + /* Find upper and lower channel according to 40MHz current operation. */ + if (CentralCh < ch) + { + UpperChannel = ch; + if (CentralCh > 2) + LowerChannel = CentralCh - 2; + else + return FALSE; + } + else if (CentralCh > ch) + { + UpperChannel = CentralCh + 2; + LowerChannel = ch; + } + + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel == UpperChannel) + { + NoEffectChannelinList ++; + } + if (pAd->ChannelList[k].Channel == LowerChannel) + { + NoEffectChannelinList ++; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList)); + if (NoEffectChannelinList == 2) + return TRUE; + else + return FALSE; +} + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for HT phy type + + Arguments: + pAd Pointer to our adapter + + Return Value: + FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPCheckHt( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN HT_CAPABILITY_IE *pHtCap, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ + MAC_TABLE_ENTRY *sta; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + sta = &pAd->MacTab.Content[Wcid]; + /* If use AMSDU, set flag.*/ + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_AMSDU_INUSED); + /* Save Peer Capability*/ + if (pAd->CommonCfg.ht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (pHtCap->HtCapInfo.ht_rx_ldpc) + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE); + } + + if (pHtCap->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCap->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCap->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCap->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCap->ExtHtCapInfo.RDGSupport) + { + CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_RDG_CAPABLE); + } + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + sta->MpduDensity = pHtCap->HtCapParm.MpduDensity; + } + + /* Will check ChannelWidth for MCSSet[4] below*/ + NdisZeroMemory(&pAd->MlmeAux.HtCapability.MCSSet[0], 16); + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 3: + pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; + case 2: + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + case 1: + default: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + break; + } + + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; + + /* + If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region + If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, + */ + if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if (RTMPCheckChannel(pAd, pAd->MlmeAux.CentralChannel, pAd->MlmeAux.Channel) == FALSE) + { + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = BW_20; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth, + pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode)); + + pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCap->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; + + /* Send Assoc Req with my HT capability.*/ + pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; + pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs; + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCap->HtCapInfo.ShortGIfor20); + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCap->HtCapInfo.ShortGIfor40); + pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCap->HtCapInfo.RxSTBC); + pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCap->HtCapInfo.TxSTBC); + + if (CLIENT_STATUS_TEST_FLAG(sta, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE)) + pAd->MlmeAux.HtCapability.HtCapInfo.ht_rx_ldpc = 1; + else + pAd->MlmeAux.HtCapability.HtCapInfo.ht_rx_ldpc = 0; + + pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; + pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCap->ExtHtCapInfo.PlusHTC; + sta->HTCapability.ExtHtCapInfo.PlusHTC = pHtCap->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCap->ExtHtCapInfo.RDGSupport; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; + } + + if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32*/ + + COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCap); + return TRUE; +} + + +#ifdef DOT11_VHT_AC +/* + ======================================================================== + + Routine Description: + Verify the support rate for HT phy type + + Arguments: + pAd Pointer to our adapter + + Return Value: + FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPCheckVht( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op) +{ + VHT_CAP_INFO *vht_cap_info = &vht_cap->vht_cap; + MAC_TABLE_ENTRY *pEntry; + + // TODO: shiang-6590, not finish yet!!!! + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + pEntry = &pAd->MacTab.Content[Wcid]; + /* Save Peer Capability*/ + if (vht_cap_info->sgi_80M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE); + if (vht_cap_info->sgi_160M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE); + if (vht_cap_info->tx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE); + if (vht_cap_info->rx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE); + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (vht_cap_info->rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE); + } + + /* Will check ChannelWidth for MCSSet[4] below */ + NdisZeroMemory(&pAd->MlmeAux.vht_cap.mcs_set, sizeof(VHT_MCS_SET)); + pAd->MlmeAux.vht_cap.mcs_set.rx_high_rate = pAd->CommonCfg.RxStream * 325; + pAd->MlmeAux.vht_cap.mcs_set.tx_high_rate = pAd->CommonCfg.TxStream * 325; + + //pAd->MlmeAux.vht_cap.vht_cap.ch_width = vht_cap_info->ch_width; +#ifdef VHT_TXBF_SUPPORT + //Disable beamformee capability in Associate Request with 3x3 AP to avoid throughput drop issue + // MT76x2 only supports up to 2x2 sounding feedback + if(IS_MT76x2(pAd)) + { + if(vht_cap_info->num_snd_dimension >=2 ) + { + pAd->MlmeAux.vht_cap.vht_cap.bfee_cap_su = FALSE; + pAd->MlmeAux.vht_cap.vht_cap.bfee_cap_mu = FALSE; + + } + } +#endif /* TXBF_SUPPORT */ + + return TRUE; +} +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPUpdateMlmeRate(RTMP_ADAPTER *pAd) +{ + UCHAR MinimumRate; + UCHAR ProperMlmeRate; /*= RATE_54; */ + UCHAR i, j, RateIdx = 12; /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + BOOLEAN bMatch = FALSE; + + + switch (pAd->CommonCfg.PhyMode) + { + case (WMODE_B): + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case (WMODE_B | WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_B | WMODE_G | WMODE_GN | WMODE_A |WMODE_AN): + case (WMODE_B | WMODE_G | WMODE_GN): +#ifdef DOT11_VHT_AC + case (WMODE_B | WMODE_G | WMODE_GN | WMODE_A |WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + if ((pAd->MlmeAux.SupRateLen == 4) && + (pAd->MlmeAux.ExtRateLen == 0)) + ProperMlmeRate = RATE_11; /* B only AP */ + else + ProperMlmeRate = RATE_24; + + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case (WMODE_A): +#ifdef DOT11_N_SUPPORT + case (WMODE_GN): + case (WMODE_G | WMODE_GN): + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): + case (WMODE_A |WMODE_AN): + case (WMODE_AN): +#ifdef DOT11_VHT_AC + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case (WMODE_A |WMODE_B | WMODE_G): + ProperMlmeRate = RATE_24; + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + +#ifdef DOT11_VHT_AC + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + { + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + } + else + { + if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B)) + { + if ((pAd->MlmeAux.SupRateLen == 4) && (pAd->MlmeAux.ExtRateLen == 0)) + ProperMlmeRate = RATE_11; /* B only AP */ + else + ProperMlmeRate = RATE_24; + + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + } + else + { + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + } + } +#endif /* DOT11_VHT_AC */ + + for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + } + + if (bMatch == FALSE) + ProperMlmeRate = MinimumRate; + + pAd->CommonCfg.MlmeRate = MinimumRate; + pAd->CommonCfg.RtsRate = ProperMlmeRate; + if (pAd->CommonCfg.MlmeRate >= RATE_6) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s():=>MlmeTransmit=0x%x\n", + __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word)); +} +#endif /* CONFIG_STA_SUPPORT */ + + +CHAR RTMPAvgRssi(RTMP_ADAPTER *pAd, RSSI_SAMPLE *pRssi) +{ + CHAR Rssi; + + if(pAd->Antenna.field.RxPath == 3) + { + Rssi = (pRssi->AvgRssi0 + pRssi->AvgRssi1 + pRssi->AvgRssi2)/3; + } + else if(pAd->Antenna.field.RxPath == 2) + { + Rssi = (pRssi->AvgRssi0 + pRssi->AvgRssi1)>>1; + } + else + { + Rssi = pRssi->AvgRssi0; + } + + return Rssi; +} + + +CHAR RTMPMaxRssi(RTMP_ADAPTER *pAd, CHAR Rssi0, CHAR Rssi1, CHAR Rssi2) +{ + CHAR larger = -127; + + if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) + { + larger = Rssi0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) + { + larger = max(Rssi0, Rssi1); + } + + if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) + { + larger = max(larger, Rssi2); + } + + if (larger == -127) + larger = 0; + + return larger; +} + + +CHAR RTMPMinSnr(RTMP_ADAPTER *pAd, CHAR Snr0, CHAR Snr1) +{ + CHAR smaller = Snr0; + + if (pAd->Antenna.field.RxPath == 1) + { + smaller = Snr0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Snr1 != 0)) + { + smaller = min(Snr0, Snr1); + } + + return smaller; +} + + +/* + ======================================================================== + Routine Description: + Periodic evaluate antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicEvaluateRxAnt(RTMP_ADAPTER *pAd) +{ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) + || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) + ) + return; + + + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +/* if (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_DISABLE)*/ + /* for SmartBit 64-byte stream test */ + if (pAd->MacTab.Size > 0) + APAsicEvaluateRxAnt(pAd); + return; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + + if (pAd->StaCfg.Psm == PWR_SAVE) + return; + + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + { + ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + /* dynamic adjust antenna evaluation period according to the traffic*/ + if (TxTotalCnt > 50) + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); + pAd->Mlme.bLowThroughput = FALSE; + } + else + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); + pAd->Mlme.bLowThroughput = TRUE; + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +/* + ======================================================================== + Routine Description: + After evaluation, check antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; +#ifdef CONFIG_STA_SUPPORT + CHAR larger = -127, rssi0, rssi1, rssi2; +#endif /* CONFIG_STA_SUPPORT */ + + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST) + || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) + ) + return; + + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +/* if (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_DISABLE)*/ + APAsicRxAntEvalTimeout(pAd); + return; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.Psm == PWR_SAVE) + return; + + + /* if the traffic is low, use average rssi as the criteria*/ + if (pAd->Mlme.bLowThroughput == TRUE) + { + rssi0 = pAd->StaCfg.RssiSample.LastRssi0; + rssi1 = pAd->StaCfg.RssiSample.LastRssi1; + rssi2 = pAd->StaCfg.RssiSample.LastRssi2; + } + else + { + rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; + rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; + rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; + } + + if(pAd->Antenna.field.RxPath == 3) + { + larger = max(rssi0, rssi1); +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + { + pAd->Mlme.RealRxPath = 3; + } + else +#endif /* DOT11N_SS3_SUPPORT */ + if (larger > (rssi2 + 20)) + pAd->Mlme.RealRxPath = 2; + else + pAd->Mlme.RealRxPath = 3; + } + else if(pAd->Antenna.field.RxPath == 2) + { + if (rssi0 > (rssi1 + 20)) + pAd->Mlme.RealRxPath = 1; + else + pAd->Mlme.RealRxPath = 2; + } + + bbp_set_rxpath(pAd, pAd->Mlme.RealRxPath); + } +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + !OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) + return; + + pAd->CommonCfg.TriggerTimerCount++; + +/* Driver should not send trigger frame, it should be send by application layer*/ +/* + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable + && (pAd->CommonCfg.bNeedSendTriggerFrame || + (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO)))) + { + DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n")); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; + pAd->CommonCfg.TriggerTimerCount = 0; + pAd->CommonCfg.bInServicePeriod = TRUE; + }*/ +} + +#ifdef TXBF_SUPPORT +/* + ======================================================================== + Routine Description: + the timer interrupt routine for TXBF sounding + + Arguments: + + Return Value: + + ======================================================================== +*/ +VOID APTxSounding( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + USHORT i; + MAC_TABLE_ENTRY *pEntry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + UCHAR mlmeMCS, mlmeBW, mlmeMode; + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): pAd is NULL!!\n", __FUNCTION__)); + return; + } + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_NONE(pEntry)) + continue; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst != SST_ASSOC)) + continue; + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && (pEntry->Sst != SST_ASSOC)) + continue; +#endif /*CONFIG_AP_SUPPORT*/ + + if ((pAd->chipCap.FlgHwTxBfCap) && (pEntry->eTxBfEnCond == 1)) + { + eTxBFProbing(pAd, pEntry); + + if (IS_VHT_RATE(pEntry)) + { + mlmeMCS = pAd->CommonCfg.MlmeTransmit.field.MCS; + mlmeBW = pAd->CommonCfg.MlmeTransmit.field.BW; + mlmeMode = pAd->CommonCfg.MlmeTransmit.field.MODE; + +#ifdef CONFIG_AP_SUPPORT + AP_NDPA_Frame_Tx(pAd, pEntry); +#endif + +#ifdef CONFIG_STA_SUPPORT + STA_NDPA_Frame_Tx(pAd, pEntry); +#endif + //Update TxSndg state by TxSndgType + NdisAcquireSpinLock(&pEntry->TxSndgLock); + pEntry->TxSndgType = SNDG_TYPE_DISABLE; + NdisReleaseSpinLock(&pEntry->TxSndgLock); + + pAd->CommonCfg.MlmeTransmit.field.MCS = mlmeMCS; + pAd->CommonCfg.MlmeTransmit.field.BW = mlmeBW; + pAd->CommonCfg.MlmeTransmit.field.MODE = mlmeMode; + } + } + } +} +#endif /* TXBF_SUPPORT */ +/* + ======================================================================== + Routine Description: + check if this entry need to switch rate automatically + + Arguments: + pAd + pEntry + + Return Value: + TRUE + FALSE + + ======================================================================== +*/ +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + BOOLEAN result = TRUE; + + if ((!pEntry) || (!(pEntry->wdev))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): entry(%p) or wdev(%p) is NULL!\n", + __FUNCTION__, pEntry, pEntry->wdev)); + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + result = pEntry->wdev->bAutoTxRateSwitch; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* only associated STA counts*/ + if ((pEntry && IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) +#ifdef QOS_DLS_SUPPORT + || (pEntry && IS_ENTRY_DLS(pEntry)) +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || (pEntry && IS_ENTRY_TDLS(pEntry)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + ) + { + result = pAd->StaCfg.wdev.bAutoTxRateSwitch; + } + else + result = FALSE; + } +#endif /* CONFIG_STA_SUPPORT */ + + + + return result; +} + + +BOOLEAN RTMPAutoRateSwitchCheck(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT apidx = 0; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (pAd->ApCfg.MBSSID[apidx].wdev.bAutoTxRateSwitch) + return TRUE; + } +#ifdef WDS_SUPPORT + for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++) + { + if (pAd->WdsTab.WdsEntry[apidx].wdev.bAutoTxRateSwitch) + return TRUE; + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + if (pAd->ApCfg.ApCliTab[apidx].wdev.bAutoTxRateSwitch) + return TRUE; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.wdev.bAutoTxRateSwitch) + return TRUE; + } +#endif /* CONFIG_STA_SUPPORT */ + return FALSE; +} + + +/* + ======================================================================== + Routine Description: + check if this entry need to fix tx legacy rate + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +UCHAR RTMPStaFixedTxMode(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + UCHAR tx_mode = FIXED_TXMODE_HT; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + if (pEntry) + { + if (IS_ENTRY_CLIENT(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.MBSSID[pEntry->apidx].wdev.DesiredTransmitSetting.field.FixedTxMode; +#ifdef WDS_SUPPORT + else if (IS_ENTRY_WDS(pEntry)) + tx_mode = (UCHAR)pAd->WdsTab.WdsEntry[pEntry->wdev_idx].wdev.DesiredTransmitSetting.field.FixedTxMode; +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->wdev_idx].wdev.DesiredTransmitSetting.field.FixedTxMode; +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + tx_mode = (UCHAR)pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode; + } +#endif /* CONFIG_STA_SUPPORT */ + + return tx_mode; +} + + +/* + ======================================================================== + Routine Description: + Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +VOID RTMPUpdateLegacyTxSetting(UCHAR fixed_tx_mode, MAC_TABLE_ENTRY *pEntry) +{ + HTTRANSMIT_SETTING TransmitSetting; + + if ((fixed_tx_mode != FIXED_TXMODE_CCK) && + (fixed_tx_mode != FIXED_TXMODE_OFDM) +#ifdef DOT11_VHT_AC + && (fixed_tx_mode != FIXED_TXMODE_VHT) +#endif /* DOT11_VHT_AC */ + ) + return; + + TransmitSetting.word = 0; + + TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; + TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; + +#ifdef DOT11_VHT_AC + if (fixed_tx_mode == FIXED_TXMODE_VHT) + { + TransmitSetting.field.MODE = MODE_VHT; + TransmitSetting.field.BW = pEntry->MaxHTPhyMode.field.BW; + /* CCK mode allow MCS 0~3*/ + if (TransmitSetting.field.MCS > ((1 << 4) + MCS_7)) + TransmitSetting.field.MCS = ((1 << 4) + MCS_7); + } + else +#endif /* DOT11_VHT_AC */ + if (fixed_tx_mode == FIXED_TXMODE_CCK) + { + TransmitSetting.field.MODE = MODE_CCK; + /* CCK mode allow MCS 0~3*/ + if (TransmitSetting.field.MCS > MCS_3) + TransmitSetting.field.MCS = MCS_3; + } + else + { + TransmitSetting.field.MODE = MODE_OFDM; + /* OFDM mode allow MCS 0~7*/ + if (TransmitSetting.field.MCS > MCS_7) + TransmitSetting.field.MCS = MCS_7; + } + + if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) + { + pEntry->HTPhyMode.word = TransmitSetting.word; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", + pEntry->wcid, get_phymode_str(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the fixed TxMode is invalid \n", __FUNCTION__)); + } +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + dynamic tune BBP R66 to find a balance between sensibility and + noise isolation + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicStaBbpTuning(RTMP_ADAPTER *pAd) +{ + UCHAR OrigR66Value = 0, R66;/*, R66UpperBound = 0x30, R66LowerBound = 0x30;*/ + CHAR Rssi; + + /* 2860C did not support Fase CCA, therefore can't tune*/ + if (pAd->MACVersion == 0x28600100) + return; + + + /* work as a STA*/ + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING*/ + return; + + if ((pAd->OpMode == OPMODE_STA) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) +#ifdef RTMP_MAC_PCI + && (pAd->bPCIclkOff == FALSE) +#endif /* RTMP_MAC_PCI */ + ) + { + bbp_get_agc(pAd, &OrigR66Value, RX_CHAIN_0); + R66 = OrigR66Value; + + if (pAd->Antenna.field.RxPath > 1) + Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; + else + Rssi = pAd->StaCfg.RssiSample.AvgRssi0; + + RTMP_CHIP_ASIC_AGC_ADJUST(pAd, Rssi, R66); + + // TODO: shiang,I didn't find AsicAGCAdjust for RT30xx, so I move following code from upper #if case. + + } +} +#endif /* CONFIG_STA_SUPPORT */ + + +VOID RTMPSetAGCInitValue(RTMP_ADAPTER *pAd, UCHAR BandWidth) +{ + if (pAd->chipOps.ChipAGCInit != NULL) + pAd->chipOps.ChipAGCInit(pAd, BandWidth); +} + + +/* +======================================================================== +Routine Description: + Check if the channel has the property. + +Arguments: + pAd - WLAN control block pointer + ChanNum - channel number + Property - channel property, CHANNEL_PASSIVE_SCAN, etc. + +Return Value: + TRUE - YES + FALSE - NO + +Note: +======================================================================== +*/ +BOOLEAN CHAN_PropertyCheck(RTMP_ADAPTER *pAd, UINT32 ChanNum, UCHAR Property) +{ + UINT32 IdChan; + + /* look for all registered channels */ + for(IdChan=0; IdChanChannelListNum; IdChan++) + { + if (pAd->ChannelList[IdChan].Channel == ChanNum) + { + if ((pAd->ChannelList[IdChan].Flags & Property) == Property) + return TRUE; + + break; + } + } + + return FALSE; +} + + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/mwds.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/mwds.c new file mode 100644 index 000000000..a7058a1d3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/mwds.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/netif_block.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/netif_block.c new file mode 100644 index 000000000..8df794e56 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/netif_block.c @@ -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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/nfc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/nfc.c new file mode 100644 index 000000000..d81753cc8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/nfc.c @@ -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 | DataKK + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + + 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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/pmf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/pmf.c new file mode 100644 index 000000000..22d09ba0f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/pmf.c @@ -0,0 +1,1705 @@ +/* + *************************************************************************** + * 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: + IEEE P802.11w + +***************************************************************************/ + +#ifdef DOT11W_PMF_SUPPORT + +#include "rt_config.h" + +/* The definition in IEEE 802.11w - Table 7-32 Cipher suite selectors */ +UCHAR OUI_PMF_BIP_CIPHER[4]= {0x00, 0x0F, 0xAC, 0x06}; + +/* The definition in IEEE 802.11w - Table 7-34 AKM suite selectors */ +UCHAR OUI_PMF_8021X_AKM[4]= {0x00, 0x0F, 0xAC, 0x05}; +UCHAR OUI_PMF_PSK_AKM[4]= {0x00, 0x0F, 0xAC, 0x06}; + +UCHAR PMF_MMIE_BUFFER[18]= {0x4C, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define SAQ_IDLE 0 +#define SAQ_RETRY 1 +#define SAQ_SENDING 2 + + +VOID PMF_PeerAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s : PMF_PeerAction Action=%d\n", __FUNCTION__, Action)); + switch (Action) { + case ACTION_SAQ_REQUEST: + PMF_PeerSAQueryReqAction(pAd, Elem); + break; + case ACTION_SAQ_RESPONSE: + PMF_PeerSAQueryRspAction(pAd, Elem); + break; + } +} + + +VOID PMF_MlmeSAQueryReq( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pOutBuffer = NULL; + HEADER_802_11 SAQReqHdr; + UINT32 FrameLen = 0; + UCHAR SACategoryType, SAActionType; + PPMF_CFG pPmfCfg = NULL; + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is NULL\n", __FUNCTION__)); + return; + } + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pEntry->Addr))); + return; + } + + if (pEntry->SAQueryStatus == SAQ_SENDING) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pPmfCfg = &pAd->ApCfg.MBSSID[pEntry->apidx].PmfCfg; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pPmfCfg = &pAd->StaCfg.PmfCfg; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pPmfCfg) + { + /* Send the SA Query Request */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MgtMacHeaderInit(pAd, &SAQReqHdr, SUBTYPE_ACTION, 0, pEntry->Addr,pAd->ApCfg.MBSSID[pEntry->apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MgtMacHeaderInit(pAd, &SAQReqHdr, SUBTYPE_ACTION, 0, pEntry->Addr, + pAd->CurrentAddress, + pEntry->Addr); + } +#endif /* CONFIG_STA_SUPPORT */ + + pEntry->TransactionID++; + + SACategoryType = CATEGORY_SA; + SAActionType = ACTION_SAQ_REQUEST; + MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, + sizeof(HEADER_802_11), &SAQReqHdr, + 1, &SACategoryType, + 1, &SAActionType, + 2, &pEntry->TransactionID, + END_OF_ARGS); + + if (pEntry->SAQueryStatus == SAQ_IDLE) { + RTMPSetTimer(&pEntry->SAQueryTimer, 1000); /* 1000ms */ + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s -- SAQueryTimer\n", __FUNCTION__)); + } + + pEntry->SAQueryStatus = SAQ_SENDING; + RTMPSetTimer(&pEntry->SAQueryConfirmTimer, 200); /* 200ms */ + + /* transmit the frame */ + MiniportMMRequest(pAd, QID_MGMT, pOutBuffer, FrameLen); + os_free_mem(NULL, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Send SA Query Request to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); + } +} + + +VOID PMF_PeerSAQueryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Action == ACTION_SAQ_REQUEST) + { + PMAC_TABLE_ENTRY pEntry; + PFRAME_802_11 pHeader; + USHORT TransactionID; + PUCHAR pOutBuffer = NULL; + HEADER_802_11 SAQRspHdr; + UINT32 FrameLen = 0; + UCHAR SACategoryType, SAActionType; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Receive SA Query Request\n", __FUNCTION__)); + pHeader = (PFRAME_802_11) Elem->Msg; + + pEntry = MacTableLookup(pAd, pHeader->Hdr.Addr2); + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not found, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + NdisMoveMemory(&TransactionID, &Elem->Msg[LENGTH_802_11+2], sizeof(USHORT)); + + /* Response the SA Query */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MgtMacHeaderInit(pAd, &SAQRspHdr, SUBTYPE_ACTION, 0, pHeader->Hdr.Addr2,pAd->ApCfg.MBSSID[pEntry->apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MgtMacHeaderInit(pAd, &SAQRspHdr, SUBTYPE_ACTION, 0, pHeader->Hdr.Addr2, + pAd->CurrentAddress, + pHeader->Hdr.Addr2); + } +#endif /* CONFIG_STA_SUPPORT */ + + SACategoryType = CATEGORY_SA; + SAActionType = ACTION_SAQ_RESPONSE; + MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, + sizeof(HEADER_802_11), &SAQRspHdr, + 1, &SACategoryType, + 1, &SAActionType, + 2, &TransactionID, + END_OF_ARGS); + + /* transmit the frame */ + MiniportMMRequest(pAd, QID_MGMT, pOutBuffer, FrameLen); + os_free_mem(NULL, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Send SA Query Response to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(SAQRspHdr.Addr1))); + } +} + + +VOID PMF_PeerSAQueryRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Action == ACTION_SAQ_RESPONSE) + { + PMAC_TABLE_ENTRY pEntry; + PFRAME_802_11 pHeader; + USHORT TransactionID; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Receive SA Query Response\n", __FUNCTION__)); + + pHeader = (PFRAME_802_11) Elem->Msg; + + pEntry = MacTableLookup(pAd, pHeader->Hdr.Addr2); + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not found, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + NdisMoveMemory(&TransactionID, &Elem->Msg[LENGTH_802_11+2], sizeof(USHORT)); + + if (pEntry->TransactionID == TransactionID) + { + pEntry->SAQueryStatus = SAQ_IDLE; + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Compare TransactionID correctly, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Compare TransactionID wrong, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + } + } +} + + +VOID PMF_SAQueryTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + + if (pEntry) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + BOOLEAN Cancelled; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof (MLME_DISASSOC_REQ_STRUCT), + &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +VOID PMF_SAQueryConfirmTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + + if (pEntry) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); + pEntry->SAQueryStatus = SAQ_RETRY; + PMF_MlmeSAQueryReq(pAd, pEntry); + } +} + + +VOID PMF_ConstructBIPAad( + IN PUCHAR pHdr, + OUT UCHAR *aad_hdr) +{ + UINT8 aad_len = 0; + + /* Frame control - + Retry bit (bit 11) masked to 0 + PwrMgt bit (bit 12) masked to 0 + MoreData bit (bit 13) masked to 0 */ + aad_hdr[0] = (*pHdr); + aad_hdr[1] = (*(pHdr + 1)) & 0xc7; + aad_len = 2; + + /* Append Addr 1, 2 & 3 */ + NdisMoveMemory(&aad_hdr[aad_len], pHdr + 4, 3 * MAC_ADDR_LEN); + aad_len += (3 * MAC_ADDR_LEN); +} + + +BOOLEAN PMF_CalculateBIPMIC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAadHdr, + IN PUCHAR pFrameBuf, + IN UINT32 FrameLen, + IN PUCHAR pKey, + OUT PUCHAR pBipMic) +{ + UCHAR *m_buf; + UINT32 total_len; + UCHAR cmac_output[16]; + UINT mlen = AES_KEY128_LENGTH; + + /* Allocate memory for MIC calculation */ + os_alloc_mem(NULL, (PUCHAR *)&m_buf, MGMT_DMA_BUFFER_SIZE); + if (m_buf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : out of resource.\n", __FUNCTION__)); + return FALSE; + } + + /* Initialize the buffer */ + NdisZeroMemory(m_buf, MGMT_DMA_BUFFER_SIZE); + + /* Construct the concatenation */ + NdisMoveMemory(m_buf, pAadHdr, LEN_PMF_BIP_AAD_HDR); + total_len = LEN_PMF_BIP_AAD_HDR; + + /* Append the Mgmt frame into the concatenation */ + NdisMoveMemory(&m_buf[total_len], pFrameBuf, FrameLen); + total_len += FrameLen; + + /* Compute AES-128-CMAC over the concatenation */ + AES_CMAC(m_buf, total_len, pKey, 16, cmac_output, &mlen); + + /* Truncate the first 64-bits */ + NdisMoveMemory(pBipMic, cmac_output, LEN_PMF_BIP_MIC); + + os_free_mem(NULL, m_buf); + + return TRUE; + +} + + +VOID PMF_DerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos = 0; + UCHAR temp[32]; + UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; + + /* initiate the concatenation input */ + NdisZeroMemory(temp, sizeof(temp)); + NdisZeroMemory(concatenation, 76); + + /* Get smaller address */ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(concatenation, AA, 6); + else + NdisMoveMemory(concatenation, SA, 6); + CurrPos += 6; + + /* Get larger address */ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(&concatenation[CurrPos], SA, 6); + else + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + + /* store the larger mac address for backward compatible of + ralink proprietary STA-key issue */ + NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); + CurrPos += 6; + + /* Get smaller Nonce */ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + CurrPos += 32; + + /* Get larger Nonce */ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + CurrPos += 32; + + hex_dump("[PMF]PMK", PMK, LEN_PMK); + hex_dump("[PMF]concatenation=", concatenation, 76); + + /* Calculate a key material through FT-KDF */ + KDF(PMK, LEN_PMK, Prefix, 22, concatenation, 76, output, len); +} + + +/* + ======================================================================== + + Routine Description: + Derive IGTK randomly + IGTK, a hierarchy consisting of a single key to provide integrity + protection for broadcast and multicast Robust Management frames + + Arguments: + + Return Value: + + Note: + It's defined in IEEE 802.11w 8.5.1.3a + + ======================================================================== +*/ +VOID PMF_DeriveIGTK( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *output) +{ + INT i; + + for(i = 0; i < LEN_TK; i++) + output[i] = RandomByte(pAd); +} + + +/* + ======================================================================== + + Routine Description: + Insert IGTK KDE. The field shall be included in pair-Msg3-WPA2 and + group-Msg1-WPA2. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID PMF_InsertIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + PPMF_IGTK_KDE igtk_kde_ptr; + UINT8 idx = 0; + PPMF_CFG pPmfCfg = NULL; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pPmfCfg = &pAd->ApCfg.MBSSID[apidx].PmfCfg; +#endif /* CONFIG_AP_SUPPORT */ + + if (!pPmfCfg) + return; + + /* Construct the common KDE format */ + WPA_ConstructKdeHdr(KDE_IGTK, LEN_PMF_IGTK_KDE, pFrameBuf); + + /* Prepare the IGTK KDE */ + igtk_kde_ptr = (PPMF_IGTK_KDE)(pFrameBuf + LEN_KDE_HDR); + NdisZeroMemory(igtk_kde_ptr, LEN_PMF_IGTK_KDE); + + /* Bits 0-11 define a value in the range 0-4095. + Bits 12 - 15 are reserved and set to 0 on transmission and ignored on reception. + The IGTK Key ID is either 4 or 5. The remaining Key IDs are reserved. */ + igtk_kde_ptr->KeyID[0] = pPmfCfg->IGTK_KeyIdx; + idx = (pPmfCfg->IGTK_KeyIdx == 5) ? 1 : 0; + + /* Fill in the IPN field */ + NdisMoveMemory(igtk_kde_ptr->IPN, &pPmfCfg->IPN[idx][0], LEN_WPA_TSC); + + /* Fill uin the IGTK field */ + NdisMoveMemory(igtk_kde_ptr->IGTK, &pPmfCfg->IGTK[idx][0], LEN_AES_GTK); + + /* Update the total output length */ + *pFrameLen = *pFrameLen + LEN_KDE_HDR + LEN_PMF_IGTK_KDE; + + return; +} + + +/* + ======================================================================== + + Routine Description: + Extract IGTK KDE. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN PMF_ExtractIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT buf_len) +{ + PPMF_IGTK_KDE igtk_kde_ptr; + UINT8 idx = 0; + UINT8 offset = 0; + PPMF_CFG pPmfCfg = NULL; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pPmfCfg = &pAd->StaCfg.PmfCfg; +#endif /* CONFIG_STA_SUPPORT */ + + if (pPmfCfg == NULL) + return FALSE; + + igtk_kde_ptr = (PPMF_IGTK_KDE) pBuf; + pPmfCfg->IGTK_KeyIdx = igtk_kde_ptr->KeyID[0]; + if (pPmfCfg->IGTK_KeyIdx == 5) + idx = 1; + offset += 2; + + NdisMoveMemory(&pPmfCfg->IPN[idx][0], igtk_kde_ptr->IPN, LEN_WPA_TSC); + offset += LEN_WPA_TSC; + + if ((buf_len - offset) == LEN_AES_GTK) + { + NdisMoveMemory(&pPmfCfg->IGTK[idx][0], igtk_kde_ptr->IGTK, LEN_AES_GTK); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the IGTK length(%d) is invalid\n", + __FUNCTION__, (buf_len - offset))); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : IGTK_Key_ID=%d\n", + __FUNCTION__, pPmfCfg->IGTK_KeyIdx)); + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Build Group Management Cipher in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID PMF_MakeRsnIeGMgmtCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + PUINT8 pBuf; + BOOLEAN MFP_Enabled = FALSE; + + /* it could be ignored in WPA1 mode */ + if (ElementID == WpaIe) + return; + + pBuf = (pRsnIe + (*rsn_len)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < pAd->ApCfg.BssidNum) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + + MFP_Enabled = pMbss->PmfCfg.MFPC; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MFP_Enabled = pAd->StaCfg.PmfCfg.MFPC; + } +#endif /* CONFIG_STA_SUPPORT */ + + /* default group management cipher suite in an RSNA with + Management Frame Protection enabled. */ + if (MFP_Enabled) + { + NdisMoveMemory(pBuf, OUI_PMF_BIP_CIPHER, LEN_OUI_SUITE); + (*rsn_len) += sizeof(LEN_OUI_SUITE); + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: Insert BIP to the group management cipher of RSNIE\n", __FUNCTION__)); + } +} + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +NTSTATUS PMF_RsnCapableValidation( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pRsnie, + IN UINT rsnie_len, + IN BOOLEAN self_MFPC, + IN BOOLEAN self_MFPR, + IN PMAC_TABLE_ENTRY pEntry) +{ + UINT8 count; + PUINT8 pBuf = NULL; + BOOLEAN peer_MFPC = FALSE, peer_MFPR = FALSE; + + /* Check the peer's MPFC and MPFR - + Refer to Table 8-1a, IEEE 802.11W to check the PMF policy */ + if ((pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, RSN_CAP_INFO, &count)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Peer's MPFC isn't used.\n", __FUNCTION__)); + if (self_MFPR) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation.\n", __FUNCTION__)); + return PMF_POLICY_VIOLATION; + } + } + else + { + RSN_CAPABILITIES RsnCap; + + NdisMoveMemory(&RsnCap, pBuf, sizeof(RSN_CAPABILITIES)); + RsnCap.word = cpu2le16(RsnCap.word); + + peer_MFPC = RsnCap.field.MFPC; + peer_MFPR = RsnCap.field.MFPR; + + if ((self_MFPC == TRUE) && (peer_MFPC == FALSE )) + { + if ((self_MFPR == TRUE) && (peer_MFPR == FALSE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation for case 4\n", __FUNCTION__)); + return PMF_POLICY_VIOLATION; + } + + if (peer_MFPR == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation for case 7\n", __FUNCTION__)); + return PMF_POLICY_VIOLATION; + } + } + + if ((self_MFPC == TRUE) && (peer_MFPC == TRUE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: PMF Connection \n", __FUNCTION__)); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE); + } + } + + /* SHA1 or SHA256 */ + if ((self_MFPC == TRUE) + && (pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, AKM_SUITE, &count)) != NULL) + { + UCHAR OUI_WPA2_1X_SHA256[4] = {0x00, 0x0F, 0xAC, 0x05}; + UCHAR OUI_WPA2_PSK_SHA256[4] = {0x00, 0x0F, 0xAC, 0x06}; + + while (count > 0) + { + if(RTMPEqualMemory(pBuf,OUI_WPA2_1X_SHA256,4) || RTMPEqualMemory(pBuf,OUI_WPA2_PSK_SHA256,4) ) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : SHA256 Support\n", __FUNCTION__)); + } + pBuf += 4; + count--; + } + } + + return PMF_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Decide if the frame is PMF Robust frame + +Arguments: + pHdr : pointer to the 802.11 header + pFrame : point to frame body. It exclude the 802.11 header + frame_len : the frame length without 802.11 header + +Return Value: + NOT_ROBUST_FRAME + UNICAST_ROBUST_FRAME + GROUP_ROBUST_FRAME + +Note: + +======================================================================== +*/ +INT PMF_RobustFrameClassify( + IN PHEADER_802_11 pHdr, + IN PUCHAR pFrame, + IN UINT frame_len, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN IsRx) +{ + if ((pHdr->FC.Type != FC_TYPE_MGMT) || (frame_len <= 0)) + return NORMAL_FRAME; + + /* Classify the frame */ + switch (pHdr->FC.SubType) + { + case SUBTYPE_DISASSOC: + case SUBTYPE_DEAUTH: + break; + case SUBTYPE_ACTION: + { + if ((IsRx == FALSE) + || (IsRx && (pHdr->FC.Wep == 0))) + { + UCHAR Category = (UCHAR) (pHdr->Octet[0]); + + switch (Category) + { + /* Refer to IEEE 802.11w Table7-24 */ + case CATEGORY_SPECTRUM: + case CATEGORY_QOS: + case CATEGORY_DLS: + case CATEGORY_BA: + case CATEGORY_RM: + case CATEGORY_FT: + case CATEGORY_SA: + case CATEGORY_PD: + case CATEGORY_VSP: + break; + default: + return NORMAL_FRAME; + } + } + break; + } + default: + return NORMAL_FRAME; + } + + if (pHdr->Addr1[0] & 0x01) /* Broadcast frame */ + { + UINT8 offset_mmie; + + if (frame_len <= (LEN_PMF_MMIE + 2)) + return NOT_ROBUST_GROUP_FRAME; + + /* The offset of MMIE */ + offset_mmie = frame_len - (LEN_PMF_MMIE + 2); + + /* check if this is a group Robust frame */ + if (((*(pFrame + offset_mmie)) == IE_PMF_MMIE) && + ((*(pFrame + offset_mmie + 1)) == LEN_PMF_MMIE)) + return GROUP_ROBUST_FRAME; + else + return NOT_ROBUST_GROUP_FRAME; + } + + /* Unicast frame */ + else if (pEntry == NULL) + return NORMAL_FRAME; + else if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + return NORMAL_FRAME; + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) && (pHdr->FC.Wep == 0) && IsRx) + return NOT_ROBUST_UNICAST_FRAME; + else if (((IsRx == TRUE) && (pHdr->FC.Wep == 1)) || (IsRx == FALSE)) + return UNICAST_ROBUST_FRAME; + + return ERROR_FRAME; +} + + +INT PMF_EncryptUniRobustFrameAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + PHEADER_802_11 pHdr = (PHEADER_802_11)pMgmtFrame; + INT data_len; + PUCHAR pBuf; + INT Status; + + /* Check if the length is valid */ + data_len = mgmt_len - (LENGTH_802_11 + LEN_CCMP_HDR + LEN_CCMP_MIC); + if (data_len <= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The payload length(%d) is invalid\n", + __FUNCTION__, data_len)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* Look up the entry through Address 1 of 802.11 header */ + pEntry = MacTableLookup(pAd, pHdr->Addr1); + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The entry doesn't exist\n", __FUNCTION__)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* check the PMF capable for this entry */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry no PMF capable !\n", __FUNCTION__)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* Allocate a buffer for building PMF packet */ + Status = MlmeAllocateMemory(pAd, &pBuf); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : allocate PMF buffer fail!\n", __FUNCTION__)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* Construct and insert 8-bytes CCMP header to MPDU header */ + RTMPConstructCCMPHdr(0, pEntry->PmfTxTsc, pBuf); + + NdisMoveMemory(pBuf + LEN_CCMP_HDR, + &pHdr->Octet[0], + data_len); + + // Encrypt the MPDU data by software + RTMPSoftEncryptCCMP(pAd, + (PUCHAR)pHdr, + pEntry->PmfTxTsc, + pEntry->PairwiseKey.Key, + pBuf + LEN_CCMP_HDR, + data_len); + + data_len += (LEN_CCMP_HDR + LEN_CCMP_MIC); + NdisMoveMemory(&pHdr->Octet[0], pBuf, data_len); + + /* TSC increment for next transmittion */ + INC_TX_TSC(pEntry->PmfTxTsc, LEN_WPA_TSC); + + MlmeFreeMemory(pAd, pBuf); + + return PMF_STATUS_SUCCESS; + +} + +INT PMF_DecryptUniRobustFrameAction( + IN PRTMP_ADAPTER pAd, + INOUT PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + PHEADER_802_11 pHeader = (PHEADER_802_11)pMgmtFrame; + PUCHAR pDate = pMgmtFrame + LENGTH_802_11; + UINT16 data_len = mgmt_len - LENGTH_802_11; + + + /* Check if the length is valid */ + if (data_len <= LEN_CCMP_HDR + LEN_CCMP_MIC) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The payload length(%d) is invalid\n", + __FUNCTION__, data_len)); + return PMF_UNICAST_DECRYPT_FAILURE; + } + + /* Look up the entry through Address 2 of 802.11 header */ + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry doesn't exist !\n", __FUNCTION__)); + return PMF_STATUS_SUCCESS; + } + + /* check the PMF capable for this entry */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry no PMF capable !\n", __FUNCTION__)); + return PMF_UNICAST_DECRYPT_FAILURE; + } + +#ifdef RT_BIG_ENDIAN + if ((pHeader->FC.SubType == SUBTYPE_DISASSOC) || (pHeader->FC.SubType == SUBTYPE_DEAUTH)) { + *(USHORT *)pDate = SWAP16(*(USHORT *)pDate); /* swap reason code */ + } +#endif /* RT_BIG_ENDIAN */ + + if (RTMPSoftDecryptCCMP(pAd, + pMgmtFrame, + &pEntry->PairwiseKey, + pDate, + &data_len) == FALSE) + { + return PMF_UNICAST_DECRYPT_FAILURE; + } + + return PMF_STATUS_SUCCESS; +} + + +INT PMF_EncapBIPAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PHEADER_802_11 pHdr = (PHEADER_802_11)pMgmtFrame; + PPMF_CFG pPmfCfg = NULL; + PPMF_MMIE pMMIE; + INT idx = 0; + PUCHAR pKey = NULL; + UCHAR aad_hdr[LEN_PMF_BIP_AAD_HDR]; + UCHAR BIP_MIC[LEN_PMF_BIP_MIC]; + PUCHAR pFrameBody = &pHdr->Octet[0]; + UINT32 body_len = mgmt_len - LENGTH_802_11; +#ifdef RT_BIG_ENDIAN + PUCHAR pMacHdr = NULL; + BOOLEAN bSwaped = FALSE; +#endif + /* Sanity check the total frame body length */ + if (body_len <= (2 + LEN_PMF_MMIE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : the total length(%d) is too short\n", + __FUNCTION__, body_len)); + return PMF_ENCAP_BIP_FAILURE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pPmfCfg = &pAd->ApCfg.MBSSID[MAIN_MBSSID].PmfCfg; + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Sanity check */ + if (pPmfCfg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : No related PMF configuation\n", __FUNCTION__)); + return PMF_ENCAP_BIP_FAILURE; + } + + if (pPmfCfg && pPmfCfg->MFPC == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF is disabled \n", __FUNCTION__)); + return PMF_ENCAP_BIP_FAILURE; + } + + /* Pointer to the position of MMIE */ + pMMIE = (PPMF_MMIE)(pMgmtFrame + (mgmt_len - LEN_PMF_MMIE)); + + /* Select the IGTK currently active for transmission of frames to + the intended group of recipients and construct the MMIE (see 7.3.2.55) + with the MIC field masked to zero and the KeyID field set to the + corresponding IGTK KeyID value. */ + if (pPmfCfg->IGTK_KeyIdx == 5) + idx = 1; + pKey = &pPmfCfg->IGTK[idx][0]; + + NdisZeroMemory(pMMIE, LEN_PMF_MMIE); + + /* Bits 0-11 define a value in the range 0-4095. + Bits 12 - 15 are reserved and set to 0 on transmission and ignored on reception. + The IGTK Key ID is either 4 or 5. The remaining Key IDs are reserved. */ + pMMIE->KeyID[0] = pPmfCfg->IGTK_KeyIdx; + NdisMoveMemory(pMMIE->IPN, &pPmfCfg->IPN[idx][0], LEN_WPA_TSC); + + /* The transmitter shall insert a monotonically increasing non-neg- + ative integer into the MMIE IPN field. */ + INC_TX_TSC(pPmfCfg->IPN[idx], LEN_WPA_TSC); + + /* Compute AAD */ +#ifdef RT_BIG_ENDIAN + if (pHdr->FC.SubType ==SUBTYPE_DISASSOC || pHdr->FC.SubType == SUBTYPE_DEAUTH) + { + pMacHdr = (PUCHAR) pHdr; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); //swap frame-control + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); //swap reason code + bSwaped= TRUE; + } +#endif + PMF_ConstructBIPAad((PUCHAR)pHdr, aad_hdr); + + /* Calculate BIP MIC */ + PMF_CalculateBIPMIC(pAd, aad_hdr, pFrameBody, body_len, pKey, BIP_MIC); + + /* Fill into the MMIE MIC field */ + NdisMoveMemory(pMMIE->MIC, BIP_MIC, LEN_PMF_BIP_MIC); + +#ifdef RT_BIG_ENDIAN + if (bSwaped) + { + pMacHdr = (PUCHAR) pHdr; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + bSwaped= TRUE; + } +#endif + /* BIP doesn't need encrypt frame */ + pHdr->FC.Wep = 0; + + return PMF_STATUS_SUCCESS; +} + +INT PMF_ExtractBIPAction( + IN PRTMP_ADAPTER pAd, + INOUT PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PPMF_CFG pPmfCfg = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + PHEADER_802_11 pHeader = (PHEADER_802_11)pMgmtFrame; + PPMF_MMIE pMMIE; + INT idx = 0; + PUCHAR pKey = NULL; + UCHAR aad_hdr[LEN_PMF_BIP_AAD_HDR]; + UCHAR rcvd_mic[LEN_PMF_BIP_MIC]; + UCHAR cal_mic[LEN_PMF_BIP_MIC]; + UINT32 body_len = mgmt_len - LENGTH_802_11; + + + /* Sanity check the total frame body length */ + if (body_len <= (2 + LEN_PMF_MMIE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the total length(%d) is too short\n", + __FUNCTION__, body_len)); + return PMF_EXTRACT_BIP_FAILURE; + } + + /* Look up the entry through Address 2 of 802.11 header */ + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry doesn't exist !\n", __FUNCTION__)); + return PMF_STATUS_SUCCESS; + } + + /* check the PMF capable for this entry */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry no PMF capable !\n", __FUNCTION__)); + return PMF_EXTRACT_BIP_FAILURE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pPmfCfg = &pAd->ApCfg.MBSSID[pEntry->apidx].PmfCfg; + } +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pPmfCfg = &pAd->StaCfg.PmfCfg; + } +#endif // CONFIG_STA_SUPPORT // + + /* Pointer to the position of MMIE */ + pMMIE = (PPMF_MMIE)(pMgmtFrame + (mgmt_len - LEN_PMF_MMIE)); + + /* Select the IGTK currently active for transmission of frames to + the intended group of recipients and construct the MMIE (see 7.3.2.55) + with the MIC field masked to zero and the KeyID field set to the + corresponding IGTK KeyID value. */ + if (pMMIE->KeyID[0] == 5) + idx = 1; + pKey = &pPmfCfg->IGTK[idx][0]; + + /* store the MIC value of the received frame */ + NdisMoveMemory(rcvd_mic, pMMIE->MIC, LEN_PMF_BIP_MIC); + NdisZeroMemory(pMMIE->MIC, LEN_PMF_BIP_MIC); + + /* Compute AAD */ + PMF_ConstructBIPAad((PUCHAR)pMgmtFrame, aad_hdr); + + /* Calculate BIP MIC */ + PMF_CalculateBIPMIC(pAd, aad_hdr, + pMgmtFrame + LENGTH_802_11, + body_len, pKey, cal_mic); + + if (!NdisEqualMemory(rcvd_mic, cal_mic, LEN_PMF_BIP_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : MIC Different !\n", __FUNCTION__)); + return PMF_EXTRACT_BIP_FAILURE; + } + + return PMF_STATUS_SUCCESS; +} + + +BOOLEAN PMF_PerformTxFrameAction( + IN PRTMP_ADAPTER pAd, + OUT PNDIS_PACKET pPacket) +{ + PHEADER_802_11 pHeader_802_11; + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + UINT8 TXWISize = pAd->chipCap.TXWISize; + INT FrameType; + INT ret = 0; + PMAC_TABLE_ENTRY pEntry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NORMAL_FRAME; + + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize); + + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + + FrameType = PMF_RobustFrameClassify( + (PHEADER_802_11)pHeader_802_11, + (PUCHAR)( ((PUCHAR) pHeader_802_11) + LENGTH_802_11), + (SrcBufLen - LENGTH_802_11 - TXINFO_SIZE - TXWISize), + pEntry, + FALSE); + + switch (FrameType) + { + case ERROR_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case NORMAL_FRAME: + case NOT_ROBUST_GROUP_FRAME: + case NOT_ROBUST_UNICAST_FRAME: + break; + case UNICAST_ROBUST_FRAME: + { + int tailroom =0 ; + + tailroom = GET_OS_PKT_END(pPacket) - GET_OS_PKT_DATATAIL(pPacket); + pHeader_802_11->FC.Wep = 1; + + /* Format: Mac header|CCMP header|Data|MIC|FCS */ + if (tailroom < (LEN_CCMP_HDR + LEN_CCMP_MIC)) + { + int headroom =GET_OS_PKT_DATAPTR(pPacket) - GET_OS_PKT_HEAD(pPacket) ; + pPacket = OS_PKT_COPY_EXPAND(pPacket, headroom, (LEN_CCMP_HDR + LEN_CCMP_MIC)); + } + + OS_PKT_TAIL_BUF_EXTEND(pPacket, (LEN_CCMP_HDR + LEN_CCMP_MIC)); + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NORMAL_FRAME; + + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize); + + ret = PMF_EncryptUniRobustFrameAction(pAd, + (PUCHAR) pHeader_802_11, + (SrcBufLen - TXINFO_SIZE - TXWISize)); + break; + } + case GROUP_ROBUST_FRAME: + { + ret = PMF_EncapBIPAction(pAd, + (PUCHAR) pHeader_802_11, + (SrcBufLen - TXINFO_SIZE - TXWISize)); + break; + } + } + + if (ret == PMF_STATUS_SUCCESS) + return TRUE; + else + return FALSE; +} + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +BOOLEAN PMF_PerformRxFrameAction( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + INT FrameType; + PUCHAR pMgmtFrame; + UINT mgmt_len; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PMAC_TABLE_ENTRY pEntry = NULL; + + pMgmtFrame = (PUCHAR)pHeader; + mgmt_len = pRxBlk->MPDUtotalByteCnt; + + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if(pEntry == NULL) + return TRUE; + + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + return TRUE; + + FrameType = PMF_RobustFrameClassify(pHeader, + (PUCHAR)(pMgmtFrame + LENGTH_802_11), + (mgmt_len - LENGTH_802_11), + pEntry, + TRUE); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + switch (FrameType) + { + case ERROR_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case NORMAL_FRAME: + case NOT_ROBUST_GROUP_FRAME: + break; + case NOT_ROBUST_UNICAST_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case UNICAST_ROBUST_FRAME: + { + if (PMF_DecryptUniRobustFrameAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + /* update the total length */ + pRxBlk->MPDUtotalByteCnt -= (LEN_CCMP_HDR + LEN_CCMP_MIC); + break; + } + case GROUP_ROBUST_FRAME: + { + if (PMF_ExtractBIPAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + /* update the total length */ + pRxBlk->MPDUtotalByteCnt -= (2 + LEN_PMF_MMIE); + break; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + + switch (FrameType) + { + case ERROR_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case NORMAL_FRAME: + break; + case NOT_ROBUST_UNICAST_FRAME: + if (((pHeader->FC.SubType == SUBTYPE_DISASSOC) || (pHeader->FC.SubType == SUBTYPE_DEAUTH)) + && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + PMF_MlmeSAQueryReq(pAd, pEntry); + return FALSE; + } + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case NOT_ROBUST_GROUP_FRAME: + if ((pEntry) && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + return FALSE; + else + break; + case UNICAST_ROBUST_FRAME: + { + if (PMF_DecryptUniRobustFrameAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + /* update the total length */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + pRxWI->RXWI_N.MPDUtotalByteCnt -= (LEN_CCMP_HDR + LEN_CCMP_MIC); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pRxWI->MPDUtotalByteCount -= (LEN_CCMP_HDR + LEN_CCMP_MIC); + } +#endif /* RTMP_MAC */ + break; + } + case GROUP_ROBUST_FRAME: + { + if (PMF_ExtractBIPAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + /* update the total length */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + pRxWI->RXWI_N.MPDUtotalByteCnt -= (2 + LEN_PMF_MMIE); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pRxWI->MPDUtotalByteCount -= (2 + LEN_PMF_MMIE); + } +#endif /* RTMP_MAC */ + break; + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + + + +/* +======================================================================== +Routine Description: + Protection Management Frame Capable + Protection Management Frame Required + +Arguments: + +Return Value: + +Note: +RSNA policy selection in a ESS: IEEE P802.11w Table 8-1a +RSNA policy selection in an IBSS: IEEE P802.11w Table 8-1b +======================================================================== +*/ +void rtmp_read_pmf_parameters_from_file( + IN PRTMP_ADAPTER pAd, + IN PSTRING tmpbuf, + IN PSTRING pBuffer) +{ + PSTRING macptr; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT apidx; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + pAd->ApCfg.MBSSID[apidx].PmfCfg.Desired_MFPC = FALSE; + pAd->ApCfg.MBSSID[apidx].PmfCfg.Desired_MFPR = FALSE; + pAd->ApCfg.MBSSID[apidx].PmfCfg.Desired_PMFSHA256 = FALSE; + } + + /* Protection Management Frame Capable */ + if (RTMPGetKeyParameter("PMFMFPC", tmpbuf, 32, pBuffer, TRUE)) + { + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); (macptr && apidx < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), apidx++) + { + pObj->ioctl_if = apidx; + Set_PMFMFPC_Proc(pAd, macptr); + } + } + + /* Protection Management Frame Required */ + if (RTMPGetKeyParameter("PMFMFPR", tmpbuf, 32, pBuffer, TRUE)) + { + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); (macptr && apidx < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), apidx++) + { + pObj->ioctl_if = apidx; + Set_PMFMFPR_Proc(pAd, macptr); + } + } + + if (RTMPGetKeyParameter("PMFSHA256", tmpbuf, 32, pBuffer, TRUE)) + { + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); (macptr && apidx < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), apidx++) + { + pObj->ioctl_if = apidx; + Set_PMFSHA256_Proc(pAd, macptr); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.PmfCfg.Desired_MFPC = FALSE; + pAd->StaCfg.PmfCfg.Desired_MFPR = FALSE; + pAd->StaCfg.PmfCfg.Desired_PMFSHA256 = FALSE; + + /* Protection Management Frame Capable */ + if (RTMPGetKeyParameter("PMFMFPC", tmpbuf, 32, pBuffer, TRUE)) + Set_PMFMFPC_Proc(pAd, tmpbuf); + + /* Protection Management Frame Required */ + if (RTMPGetKeyParameter("PMFMFPR", tmpbuf, 32, pBuffer, TRUE)) + Set_PMFMFPR_Proc(pAd, tmpbuf); + + if (RTMPGetKeyParameter("PMFSHA256", tmpbuf, 32, pBuffer, TRUE)) + Set_PMFSHA256_Proc(pAd, tmpbuf); + } +#endif /* CONFIG_STA_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: Protection Management Frame Capable + +Arguments: + +Return Value: + +Note: +RSNA policy selection in a ESS: IEEE P802.11w Table 8-1a +RSNA policy selection in an IBSS: IEEE P802.11w Table 8-1b +======================================================================== +*/ +/* chane the cmd depend on security mode first, and update to run time flag */ +INT Set_PMFMFPC_Proc ( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if(strlen(arg) == 0) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPC = TRUE; + else + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPC = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, Desired MFPC=%d\n", __FUNCTION__ + , pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPC)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (simple_strtol(arg, 0, 10)) + pAd->StaCfg.PmfCfg.Desired_MFPC = TRUE; + else + { + pAd->StaCfg.PmfCfg.Desired_MFPC = FALSE; + pAd->StaCfg.PmfCfg.MFPC = FALSE; + pAd->StaCfg.PmfCfg.MFPR = FALSE; + //dont need to clear the SHA256 + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Desired MFPC=%d\n", __FUNCTION__ + , pAd->StaCfg.PmfCfg.Desired_MFPC)); + + + { + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable)) + { + pAd->StaCfg.PmfCfg.PMFSHA256 = pAd->StaCfg.PmfCfg.Desired_PMFSHA256; + if (pAd->StaCfg.PmfCfg.Desired_MFPC) + { + pAd->StaCfg.PmfCfg.MFPC = TRUE; + pAd->StaCfg.PmfCfg.MFPR = pAd->StaCfg.PmfCfg.Desired_MFPR; + + if (pAd->StaCfg.PmfCfg.MFPR) + pAd->StaCfg.PmfCfg.PMFSHA256 = TRUE; + } + } else if (pAd->StaCfg.PmfCfg.Desired_MFPC) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: MFPC=%d, MFPR=%d, SHA256=%d\n", + __FUNCTION__, pAd->StaCfg.PmfCfg.MFPC, pAd->StaCfg.PmfCfg.MFPR, + pAd->StaCfg.PmfCfg.PMFSHA256)); + } + + + } +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + + +/* +======================================================================== +Routine Description: Protection Management Frame Required + +Arguments: + +Return Value: + +Note: +RSNA policy selection in a ESS: IEEE P802.11w Table 8-1a +RSNA policy selection in an IBSS: IEEE P802.11w Table 8-1b +======================================================================== +*/ +/* chane the cmd depend on security mode first, and update to run time flag*/ +INT Set_PMFMFPR_Proc ( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if(strlen(arg) == 0) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPR = TRUE; + else + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPR = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, Desired MFPR=%d\n", __FUNCTION__ + , pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPR)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (simple_strtol(arg, 0, 10)) + pAd->StaCfg.PmfCfg.Desired_MFPR = TRUE; + else + { + pAd->StaCfg.PmfCfg.Desired_MFPR = FALSE; + //only close the MFPR + pAd->StaCfg.PmfCfg.MFPR = FALSE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Desired MFPR=%d\n", __FUNCTION__ + , pAd->StaCfg.PmfCfg.Desired_MFPR)); + + { + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable)) + { + pAd->StaCfg.PmfCfg.PMFSHA256 = pAd->StaCfg.PmfCfg.Desired_PMFSHA256; + if (pAd->StaCfg.PmfCfg.Desired_MFPC) + { + pAd->StaCfg.PmfCfg.MFPC = TRUE; + pAd->StaCfg.PmfCfg.MFPR = pAd->StaCfg.PmfCfg.Desired_MFPR; + + if (pAd->StaCfg.PmfCfg.MFPR) + pAd->StaCfg.PmfCfg.PMFSHA256 = TRUE; + } + } else if (pAd->StaCfg.PmfCfg.Desired_MFPC) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: MFPC=%d, MFPR=%d, SHA256=%d\n", + __FUNCTION__, pAd->StaCfg.PmfCfg.MFPC, pAd->StaCfg.PmfCfg.MFPR, + pAd->StaCfg.PmfCfg.PMFSHA256)); + } + + + } +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + + +INT Set_PMFSHA256_Proc ( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if(strlen(arg) == 0) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256 = TRUE; + else + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256 = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, Desired PMFSHA256=%d\n", __FUNCTION__ + , pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (simple_strtol(arg, 0, 10)) + pAd->StaCfg.PmfCfg.Desired_PMFSHA256 = TRUE; + else + pAd->StaCfg.PmfCfg.Desired_PMFSHA256 = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Desired PMFSHA256=%d\n", __FUNCTION__ + , pAd->StaCfg.PmfCfg.Desired_PMFSHA256)); + } +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + +#endif /* DOT11W_PMF_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ps.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ps.c new file mode 100644 index 000000000..c269fd511 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/ps.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/routing_tab.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/routing_tab.c new file mode 100644 index 000000000..ccb1353d9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/routing_tab.c @@ -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 +#include + + +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 */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm.c new file mode 100644 index 000000000..ee3b838fd --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm.c @@ -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=-------\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=----[--------]\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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm_sanity.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm_sanity.c new file mode 100644 index 000000000..468644c9a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm_sanity.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm_tlv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm_tlv.c new file mode 100644 index 000000000..d8d9cc332 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rrm_tlv.c @@ -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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_channel.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_channel.c new file mode 100644 index 000000000..537ec4900 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_channel.c @@ -0,0 +1,2460 @@ +/* + +*/ +#include "rt_config.h" + + +CH_FREQ_MAP CH_HZ_ID_MAP[]= + { + {1, 2412}, + {2, 2417}, + {3, 2422}, + {4, 2427}, + {5, 2432}, + {6, 2437}, + {7, 2442}, + {8, 2447}, + {9, 2452}, + {10, 2457}, + {11, 2462}, + {12, 2467}, + {13, 2472}, + {14, 2484}, + + /* UNII */ + {36, 5180}, + {40, 5200}, + {44, 5220}, + {48, 5240}, + {52, 5260}, + {56, 5280}, + {60, 5300}, + {64, 5320}, + {149, 5745}, + {153, 5765}, + {157, 5785}, + {161, 5805}, + {165, 5825}, + {167, 5835}, + {169, 5845}, + {171, 5855}, + {173, 5865}, + + /* HiperLAN2 */ + {100, 5500}, + {104, 5520}, + {108, 5540}, + {112, 5560}, + {116, 5580}, + {120, 5600}, + {124, 5620}, + {128, 5640}, + {132, 5660}, + {136, 5680}, + {140, 5700}, + + /* Japan MMAC */ + {34, 5170}, + {38, 5190}, + {42, 5210}, + {46, 5230}, + + /* Japan */ + {184, 4920}, + {188, 4940}, + {192, 4960}, + {196, 4980}, + + {208, 5040}, /* Japan, means J08 */ + {212, 5060}, /* Japan, means J12 */ + {216, 5080}, /* Japan, means J16 */ +}; + +INT CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP)/sizeof(CH_FREQ_MAP)); + +CH_DESC Country_Region0_ChDesc_2GHZ[] = +{ + {1, 11, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region1_ChDesc_2GHZ[] = +{ + {1, 13, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region2_ChDesc_2GHZ[] = +{ + {10, 2, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region3_ChDesc_2GHZ[] = +{ + {10, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region4_ChDesc_2GHZ[] = +{ + {14, 1, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region5_ChDesc_2GHZ[] = +{ + {1, 14, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region6_ChDesc_2GHZ[] = +{ + {3, 7, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region7_ChDesc_2GHZ[] = +{ + {5, 9, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region31_ChDesc_2GHZ[] = +{ + {1, 11, CHANNEL_DEFAULT_PROP}, + {12, 3, CHANNEL_PASSIVE_SCAN}, + {} +}; + +CH_DESC Country_Region32_ChDesc_2GHZ[] = +{ + {1, 11, CHANNEL_DEFAULT_PROP}, + {12, 2, CHANNEL_PASSIVE_SCAN}, + {} +}; + +CH_DESC Country_Region33_ChDesc_2GHZ[] = +{ + {1, 14, CHANNEL_DEFAULT_PROP}, + {} +}; + +COUNTRY_REGION_CH_DESC Country_Region_ChDesc_2GHZ[] = +{ + {REGION_0_BG_BAND, Country_Region0_ChDesc_2GHZ}, + {REGION_1_BG_BAND, Country_Region1_ChDesc_2GHZ}, + {REGION_2_BG_BAND, Country_Region2_ChDesc_2GHZ}, + {REGION_3_BG_BAND, Country_Region3_ChDesc_2GHZ}, + {REGION_4_BG_BAND, Country_Region4_ChDesc_2GHZ}, + {REGION_5_BG_BAND, Country_Region5_ChDesc_2GHZ}, + {REGION_6_BG_BAND, Country_Region6_ChDesc_2GHZ}, + {REGION_7_BG_BAND, Country_Region7_ChDesc_2GHZ}, + {REGION_31_BG_BAND, Country_Region31_ChDesc_2GHZ}, + {REGION_32_BG_BAND, Country_Region32_ChDesc_2GHZ}, + {REGION_33_BG_BAND, Country_Region33_ChDesc_2GHZ}, + {} +}; + +UINT16 const Country_Region_GroupNum_2GHZ = sizeof(Country_Region_ChDesc_2GHZ) / sizeof(COUNTRY_REGION_CH_DESC); + +#ifdef DFS_SUPPORT +CH_DESC Country_Region0_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region1_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region2_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region3_ChDesc_5GHZ[] = +{ + {52, 4, CHANNEL_DEFAULT_PROP}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; +#else +CH_DESC Country_Region0_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region1_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region2_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region3_ChDesc_5GHZ[] = +{ + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; +#endif + +CH_DESC Country_Region4_ChDesc_5GHZ[] = +{ + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region5_ChDesc_5GHZ[] = +{ + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region6_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region7_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region8_ChDesc_5GHZ[] = +{ + {52, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +#ifdef DFS_SUPPORT +CH_DESC Country_Region9_ChDesc_5GHZ[] = +{ + {36, 8 , CHANNEL_DEFAULT_PROP}, + {100, 5, CHANNEL_DEFAULT_PROP}, + {132, 3, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; +#else +CH_DESC Country_Region9_ChDesc_5GHZ[] = +{ + {36, 4 , CHANNEL_DEFAULT_PROP}, + {} +}; +#endif + +CH_DESC Country_Region10_ChDesc_5GHZ[] = +{ + {36,4, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region11_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 6, CHANNEL_DEFAULT_PROP}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +/* for FCC capable of using 144 , mapping of Country_Region1 */ +CH_DESC Country_Region12_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 12, CHANNEL_DEFAULT_PROP}, + {} +}; +/* for FCC capable of using 144 , mapping of Country_Region7 */ +CH_DESC Country_Region13_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 12, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; +/* for FCC capable of using 144 , mapping of Country_Region9 */ +CH_DESC Country_Region14_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 5, CHANNEL_DEFAULT_PROP}, + {132, 4, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region15_ChDesc_5GHZ[] = +{ + {149, 7, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region16_ChDesc_5GHZ[] = +{ + {52, 4, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region17_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region18_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 5, CHANNEL_DEFAULT_PROP}, + {132, 3, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region19_ChDesc_5GHZ[] = +{ + {56, 3, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_DEFAULT_PROP}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region20_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 7, CHANNEL_DEFAULT_PROP}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region21_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_DEFAULT_PROP}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region22_ChDesc_5GHZ[] = +{ + {100, 11, CHANNEL_DEFAULT_PROP}, + {} +}; + +COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[] = +{ + {REGION_0_A_BAND, Country_Region0_ChDesc_5GHZ}, + {REGION_1_A_BAND, Country_Region1_ChDesc_5GHZ}, + {REGION_2_A_BAND, Country_Region2_ChDesc_5GHZ}, + {REGION_3_A_BAND, Country_Region3_ChDesc_5GHZ}, + {REGION_4_A_BAND, Country_Region4_ChDesc_5GHZ}, + {REGION_5_A_BAND, Country_Region5_ChDesc_5GHZ}, + {REGION_6_A_BAND, Country_Region6_ChDesc_5GHZ}, + {REGION_7_A_BAND, Country_Region7_ChDesc_5GHZ}, + {REGION_8_A_BAND, Country_Region8_ChDesc_5GHZ}, + {REGION_9_A_BAND, Country_Region9_ChDesc_5GHZ}, + {REGION_10_A_BAND, Country_Region10_ChDesc_5GHZ}, + {REGION_11_A_BAND, Country_Region11_ChDesc_5GHZ}, + {REGION_12_A_BAND, Country_Region12_ChDesc_5GHZ}, + {REGION_13_A_BAND, Country_Region13_ChDesc_5GHZ}, + {REGION_14_A_BAND, Country_Region14_ChDesc_5GHZ}, + {REGION_15_A_BAND, Country_Region15_ChDesc_5GHZ}, + {REGION_16_A_BAND, Country_Region16_ChDesc_5GHZ}, + {REGION_17_A_BAND, Country_Region17_ChDesc_5GHZ}, + {REGION_18_A_BAND, Country_Region18_ChDesc_5GHZ}, + {REGION_19_A_BAND, Country_Region19_ChDesc_5GHZ}, + {REGION_20_A_BAND, Country_Region20_ChDesc_5GHZ}, + {REGION_21_A_BAND, Country_Region21_ChDesc_5GHZ}, + {REGION_22_A_BAND, Country_Region22_ChDesc_5GHZ}, + {} +}; + +UINT16 const Country_Region_GroupNum_5GHZ = sizeof(Country_Region_ChDesc_5GHZ) / sizeof(COUNTRY_REGION_CH_DESC); + +UINT16 TotalChNum(PCH_DESC pChDesc) +{ + UINT16 TotalChNum = 0; + + while(pChDesc->FirstChannel) + { + TotalChNum += pChDesc->NumOfCh; + pChDesc++; + } + + return TotalChNum; +} + +UCHAR GetChannel_5GHZ(PCH_DESC pChDesc, UCHAR index) +{ + while (pChDesc->FirstChannel) + { + if (index < pChDesc->NumOfCh) + return pChDesc->FirstChannel + index * 4; + else + { + index -= pChDesc->NumOfCh; + pChDesc++; + } + } + + return 0; +} + +UCHAR GetChannel_2GHZ(PCH_DESC pChDesc, UCHAR index) +{ + + while (pChDesc->FirstChannel) + { + if (index < pChDesc->NumOfCh) + return pChDesc->FirstChannel + index; + else + { + index -= pChDesc->NumOfCh; + pChDesc++; + } + } + + return 0; +} + +UCHAR GetChannelFlag(PCH_DESC pChDesc, UCHAR index) +{ + + while (pChDesc->FirstChannel) + { + if (index < pChDesc->NumOfCh) + return pChDesc->ChannelProp; + else + { + index -= pChDesc->NumOfCh; + pChDesc++; + } + } + + return 0; +} + +#ifdef EXT_BUILD_CHANNEL_LIST + +/*Albania*/ +CH_DESP Country_AL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Algeria*/ +CH_DESP Country_DZ_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Argentina*/ +CH_DESP Country_AR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Armenia*/ +CH_DESP Country_AM_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Aruba*/ +CH_DESP Country_AW_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Australia*/ +CH_DESP Country_AU_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Austria*/ +CH_DESP Country_AT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Azerbaijan*/ +CH_DESP Country_AZ_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Bahrain*/ +CH_DESP Country_BH_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Bangladesh*/ +CH_DESP Country_BD_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Barbados*/ +CH_DESP Country_BB_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Belarus*/ +CH_DESP Country_BY_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Belgium*/ +CH_DESP Country_BE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Belize*/ +CH_DESP Country_BZ_ChDesp[] = +{ + { 1, 13, 30, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Bolivia*/ +CH_DESP Country_BO_ChDesp[] = +{ + { 1, 13, 30, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Bosnia and Herzegovina*/ +CH_DESP Country_BA_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Brazil*/ +CH_DESP Country_BR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Brunei Darussalam*/ +CH_DESP Country_BN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Bulgaria*/ +CH_DESP Country_BG_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 2, 23, BOTH, TRUE}, /*5250~5290MHz, Ch 52~56, Max BW: 40 */ + { 100, 11, 30, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Cambodia*/ +CH_DESP Country_KH_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Canada*/ +CH_DESP Country_CA_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 12, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Chile*/ +CH_DESP Country_CL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*China*/ +CH_DESP Country_CN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Colombia*/ +CH_DESP Country_CO_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Costa Rica*/ +CH_DESP Country_CR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Croatia*/ +CH_DESP Country_HR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Cyprus*/ +CH_DESP Country_CY_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Czech Republic*/ +CH_DESP Country_CZ_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2400~2483.5MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, IDOR, FALSE}, /*5150~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5350MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5470~5725MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Denmark*/ +CH_DESP Country_DK_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Dominican Republic*/ +CH_DESP Country_DO_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Ecuador*/ +CH_DESP Country_EC_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Egypt*/ +CH_DESP Country_EG_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 0}, /* end*/ +}; +/*El Salvador*/ +CH_DESP Country_SV_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Estonia*/ +CH_DESP Country_EE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Finland*/ +CH_DESP Country_FI_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*France*/ +CH_DESP Country_FR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Georgia*/ +CH_DESP Country_GE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Germany*/ +CH_DESP Country_DE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2400~2483.5MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5150~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5350MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5470~5725MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Greece*/ +CH_DESP Country_GR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Greenland*/ +CH_DESP Country_GL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Grenada*/ +CH_DESP Country_GD_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Guam*/ +CH_DESP Country_GU_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Guatemala*/ +CH_DESP Country_GT_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Haiti*/ +CH_DESP Country_HT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Honduras*/ +CH_DESP Country_HN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Hong Kong*/ +CH_DESP Country_HK_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Hungary*/ +CH_DESP Country_HU_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Iceland*/ +CH_DESP Country_IS_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*India*/ +CH_DESP Country_IN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Indonesia*/ +CH_DESP Country_ID_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Iran, Islamic Republic of*/ +CH_DESP Country_IR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Ireland*/ +CH_DESP Country_IE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Israel*/ +CH_DESP Country_IL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, IDOR, FALSE}, /*5150~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, IDOR, TRUE}, /*5250~5350MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Italy*/ +CH_DESP Country_IT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Jamaica*/ +CH_DESP Country_JM_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Japan*/ +CH_DESP Country_JP_ChDesp[] = +{ + { 1, 14, 20, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 20 */ + /*2457~2482MHz, Ch10~13, Max BW: 20 */ + /*2474~2494MHz, Ch14, Max BW: 20, No OFDM */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 23, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Jordan*/ +CH_DESP Country_JO_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Kazakhstan*/ +CH_DESP Country_KZ_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Kenya*/ +CH_DESP Country_KE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Korea, Democratic People's Republic of*/ +CH_DESP Country_KP_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, TRUE}, /*5160~5250MHz, Ch 36~48, Max BW: 40 */ + { 36, 8, 20, BOTH, FALSE}, /*5170~5330MHz, Ch 36~64, Max BW: 40 */ + { 100, 7, 30, BOTH, TRUE}, /*5490~5630MHz, Ch 100~124, Max BW: 40 */ + { 149, 4, 30, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Korea, Republic of*/ +CH_DESP Country_KR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 20 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 100, 7, 30, BOTH, TRUE}, /*5490~5630MHz, Ch 100~124, Max BW: 40 */ + { 149, 4, 30, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Kuwait*/ +CH_DESP Country_KW_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Latvia*/ +CH_DESP Country_LV_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Lebanon*/ +CH_DESP Country_LB_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Liechtenstein*/ +CH_DESP Country_LI_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Lithuania*/ +CH_DESP Country_LT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Luxembourg*/ +CH_DESP Country_LU_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Macao*/ +CH_DESP Country_MO_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Macedonia, Republic of*/ +CH_DESP Country_MK_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Malaysia*/ +CH_DESP Country_MY_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 52, 4, 30, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Malta*/ +CH_DESP Country_MT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Mexico*/ +CH_DESP Country_MX_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Monaco*/ +CH_DESP Country_MC_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Morocco*/ +CH_DESP Country_MA_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Nepal*/ +CH_DESP Country_NP_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Netherlands*/ +CH_DESP Country_NL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Netherlands Antilles*/ +CH_DESP Country_AN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*New Zealand*/ +CH_DESP Country_NZ_ChDesp[] = +{ + { 1, 13, 30, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Norway*/ +CH_DESP Country_NO_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Oman*/ +CH_DESP Country_OM_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Pakistan*/ +CH_DESP Country_PK_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Panama*/ +CH_DESP Country_PA_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Papua New Guinea*/ +CH_DESP Country_PG_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Peru*/ +CH_DESP Country_PE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Philippines*/ +CH_DESP Country_PH_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Poland*/ +CH_DESP Country_PL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Portuga*/ +CH_DESP Country_PT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Puerto Rico*/ +CH_DESP Country_PR_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Qatar*/ +CH_DESP Country_QA_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Romania*/ +CH_DESP Country_RO_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Russian Federation*/ +CH_DESP Country_RU_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, FALSE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Saint Barth'elemy*/ +CH_DESP Country_BL_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Saudi Arabia*/ +CH_DESP Country_SA_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Singapore*/ +CH_DESP Country_SG_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Slovakia*/ +CH_DESP Country_SK_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Slovenia*/ +CH_DESP Country_SI_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*South Africa*/ +CH_DESP Country_ZA_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Spain*/ +CH_DESP Country_ES_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Sri Lanka*/ +CH_DESP Country_LK_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 20 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Sweden*/ +CH_DESP Country_SE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Switzerland*/ +CH_DESP Country_CH_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Syrian Arab Republic*/ +CH_DESP Country_SY_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Taiwan*/ +CH_DESP Country_TW_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 56, 3, 17, IDOR, TRUE}, /*5270~5330MHz, Ch 56~64, Max BW: 40 */ + { 149, 4, 30, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Thailand*/ +CH_DESP Country_TH_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Trinidad and Tobago*/ +CH_DESP Country_TT_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Tunisia*/ +CH_DESP Country_TN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Turkey*/ +CH_DESP Country_TR_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */ + { 0}, /* end*/ +}; +/*Ukraine*/ +CH_DESP Country_UA_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*United Arab Emirates*/ +CH_DESP Country_AE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*United Kingdom*/ +CH_DESP Country_GB_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 0}, /* end*/ +}; +/*United States*/ +CH_DESP Country_US_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 5, 20, BOTH, TRUE}, /*5490~5600MHz, Ch 100~116, Max BW: 40 */ + { 132, 4, 20, BOTH, TRUE}, /*5650~5710MHz, Ch 132~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Uruguay*/ +CH_DESP Country_UY_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Uzbekistan*/ +CH_DESP Country_UZ_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */ + { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Venezuela*/ +CH_DESP Country_VE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 149, 4, 23, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Viet Nam*/ +CH_DESP Country_VN_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */ + { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Yemen*/ +CH_DESP Country_YE_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; +/*Zimbabwe*/ +CH_DESP Country_ZW_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */ + { 0}, /* end*/ +}; + +/* Group Region */ +/*Europe*/ +CH_DESP Country_EU_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /* 2.4 G, ch 1~13 */ + { 36, 4, 17, BOTH, FALSE}, /* 5G band 1, ch 36~48*/ + { 0}, /* end*/ +}; +/*North America*/ +CH_DESP Country_NA_ChDesp[] = +{ + { 1, 11, 27, BOTH, FALSE}, /* 2.4 G, ch 1~11*/ + { 36, 4, 17, IDOR, FALSE}, /* 5G band 1, ch 36~48*/ + { 149, 5, 30, BOTH, FALSE}, /* 5G band 4, ch 149~165*/ + { 0}, /* end*/ +}; +/*World Wide*/ +CH_DESP Country_WO_ChDesp[] = +{ + { 1, 13, 20, BOTH, FALSE}, /* 2.4 G, ch 1~13*/ + { 36, 4, 17, BOTH, FALSE}, /* 5G band 1, ch 36~48*/ + { 149, 5, 22, BOTH, FALSE}, /* 5G band 4, ch 149~165*/ + { 0}, /* end*/ +}; + +CH_REGION ChRegion[] = +{ + {"AL", CE, Country_AL_ChDesp, TRUE}, /* Albania */ + {"DZ", CE, Country_DZ_ChDesp, TRUE}, /* Algeria */ + {"AR", CE, Country_AR_ChDesp, TRUE}, /* Argentina */ + {"AM", CE, Country_AM_ChDesp, TRUE}, /* Armenia */ + {"AW", CE, Country_AW_ChDesp, TRUE}, /* Aruba */ + {"AU", CE, Country_AU_ChDesp, FALSE}, /* Australia */ + {"AT", CE, Country_AT_ChDesp, TRUE}, /* Austria */ + {"AZ", CE, Country_AZ_ChDesp, TRUE}, /* Azerbaijan */ + {"BH", CE, Country_BH_ChDesp, TRUE}, /* Bahrain */ + {"BD", CE, Country_BD_ChDesp, TRUE}, /* Bangladesh */ + {"BB", CE, Country_BB_ChDesp, TRUE}, /* Barbados */ + {"BY", CE, Country_BY_ChDesp, TRUE}, /* Belarus */ + {"BE", CE, Country_BE_ChDesp, TRUE}, /* Belgium */ + {"BZ", CE, Country_BZ_ChDesp, TRUE}, /* Belize */ + {"BO", CE, Country_BO_ChDesp, TRUE}, /* Bolivia */ + {"BA", CE, Country_BA_ChDesp, TRUE}, /* Bosnia and Herzegovina */ + {"BR", CE, Country_BR_ChDesp, FALSE}, /* Brazil */ + {"BN", CE, Country_BN_ChDesp, TRUE}, /* Brunei Darussalam */ + {"BG", CE, Country_BG_ChDesp, TRUE}, /* Bulgaria */ + {"KH", CE, Country_KH_ChDesp, TRUE}, /* Cambodia */ + {"CA", FCC,Country_CA_ChDesp, FALSE}, /* Canada */ + {"CL", CE, Country_CL_ChDesp, TRUE}, /* Chile */ + {"CN", CE, Country_CN_ChDesp, FALSE}, /* China */ + {"CO", CE, Country_CO_ChDesp, TRUE}, /* Colombia */ + {"CR", CE, Country_CR_ChDesp, TRUE}, /* Costa Rica */ + {"HR", CE, Country_HR_ChDesp, TRUE}, /* Croatia */ + {"CY", CE, Country_CY_ChDesp, TRUE}, /* Cyprus */ + {"CZ", CE, Country_CZ_ChDesp, TRUE}, /* Czech Republic */ + {"DK", CE, Country_DK_ChDesp, TRUE}, /* Denmark */ + {"DO", CE, Country_DO_ChDesp, TRUE}, /* Dominican Republic */ + {"EC", CE, Country_EC_ChDesp, TRUE}, /* Ecuador */ + {"EG", CE, Country_EG_ChDesp, TRUE}, /* Egypt */ + {"SV", CE, Country_SV_ChDesp, TRUE}, /* El Salvador */ + {"EE", CE, Country_EE_ChDesp, TRUE}, /* Estonia */ + {"FI", CE, Country_FI_ChDesp, TRUE}, /* Finland */ + {"FR", CE, Country_FR_ChDesp, TRUE}, /* France */ + {"GE", CE, Country_GE_ChDesp, TRUE}, /* Georgia */ + {"DE", CE, Country_DE_ChDesp, TRUE}, /* Germany */ + {"GR", CE, Country_GR_ChDesp, TRUE}, /* Greece */ + {"GL", CE, Country_GL_ChDesp, TRUE}, /* Greenland */ + {"GD", CE, Country_GD_ChDesp, TRUE}, /* Grenada */ + {"GU", CE, Country_GU_ChDesp, TRUE}, /* Guam */ + {"GT", CE, Country_GT_ChDesp, TRUE}, /* Guatemala */ + {"HT", CE, Country_HT_ChDesp, TRUE}, /* Haiti */ + {"HN", CE, Country_HN_ChDesp, TRUE}, /* Honduras */ + {"HK", CE, Country_HK_ChDesp, TRUE}, /* Hong Kong */ + {"HU", CE, Country_HU_ChDesp, TRUE}, /* Hungary */ + {"IS", CE, Country_IS_ChDesp, TRUE}, /* Iceland */ + {"IN", CE, Country_IN_ChDesp, TRUE}, /* India */ + {"ID", CE, Country_ID_ChDesp, TRUE}, /* Indonesia */ + {"IR", CE, Country_IR_ChDesp, TRUE}, /* Iran, Islamic Republic of */ + {"IE", CE, Country_IE_ChDesp, TRUE}, /* Ireland */ + {"IL", CE, Country_IL_ChDesp, FALSE}, /* Israel */ + {"IT", CE, Country_IT_ChDesp, TRUE}, /* Italy */ + {"JM", CE, Country_JM_ChDesp, TRUE}, /* Jamaica */ + {"JP", JAP,Country_JP_ChDesp, FALSE}, /* Japan */ + {"JO", CE, Country_JO_ChDesp, TRUE}, /* Jordan */ + {"KZ", CE, Country_KZ_ChDesp, TRUE}, /* Kazakhstan */ + {"KE", CE, Country_KE_ChDesp, TRUE}, /* Kenya */ + {"KP", CE, Country_KP_ChDesp, TRUE}, /* Korea, Democratic People's Republic of */ + {"KR", CE, Country_KR_ChDesp, FALSE}, /* Korea, Republic of */ + {"KW", CE, Country_KW_ChDesp, TRUE}, /* Kuwait */ + {"LV", CE, Country_LV_ChDesp, TRUE}, /* Latvia */ + {"LB", CE, Country_LB_ChDesp, TRUE}, /* Lebanon */ + {"LI", CE, Country_LI_ChDesp, TRUE}, /* Liechtenstein */ + {"LT", CE, Country_LT_ChDesp, TRUE}, /* Lithuania */ + {"LU", CE, Country_LU_ChDesp, TRUE}, /* Luxembourg */ + {"MO", CE, Country_MO_ChDesp, TRUE}, /* Macao */ + {"MK", CE, Country_MK_ChDesp, TRUE}, /* Macedonia, Republic of */ + {"MY", CE, Country_MY_ChDesp, TRUE}, /* Malaysia */ + {"MT", CE, Country_MT_ChDesp, TRUE}, /* Malta */ + {"MX", CE, Country_MX_ChDesp, FALSE}, /* Mexico */ + {"MC", CE, Country_MC_ChDesp, TRUE}, /* Monaco */ + {"MA", CE, Country_MA_ChDesp, TRUE}, /* Morocco */ + {"NP", CE, Country_NP_ChDesp, TRUE}, /* Nepal */ + {"NL", CE, Country_NL_ChDesp, TRUE}, /* Netherlands */ + {"AN", CE, Country_AN_ChDesp, TRUE}, /* Netherlands Antilles */ + {"NZ", CE, Country_NZ_ChDesp, TRUE}, /* New Zealand */ + {"NO", CE, Country_NO_ChDesp, TRUE}, /* Norway */ + {"OM", CE, Country_OM_ChDesp, TRUE}, /* Oman */ + {"PK", CE, Country_PK_ChDesp, TRUE}, /* Pakistan */ + {"PA", CE, Country_PA_ChDesp, TRUE}, /* Panama */ + {"PG", CE, Country_PG_ChDesp, TRUE}, /* Papua New Guinea */ + {"PE", CE, Country_PE_ChDesp, TRUE}, /* Peru */ + {"PH", CE, Country_PH_ChDesp, TRUE}, /* Philippines */ + {"PL", CE, Country_PL_ChDesp, TRUE}, /* Poland */ + {"PT", CE, Country_PT_ChDesp, TRUE}, /* Portuga l*/ + {"PR", CE, Country_PR_ChDesp, TRUE}, /* Puerto Rico */ + {"QA", CE, Country_QA_ChDesp, TRUE}, /* Qatar */ + {"RO", CE, Country_RO_ChDesp, TRUE}, /* Romania */ + {"RU", CE, Country_RU_ChDesp, FALSE}, /* Russian Federation */ + {"BL", CE, Country_BL_ChDesp, TRUE}, /* Saint Barth'elemy */ + {"SA", CE, Country_SA_ChDesp, TRUE}, /* Saudi Arabia */ + {"SG", CE, Country_SG_ChDesp, TRUE}, /* Singapore */ + {"SK", CE, Country_SK_ChDesp, TRUE}, /* Slovakia */ + {"SI", CE, Country_SI_ChDesp, TRUE}, /* Slovenia */ + {"ZA", CE, Country_ZA_ChDesp, FALSE}, /* South Africa */ + {"ES", CE, Country_ES_ChDesp, TRUE}, /* Spain */ + {"LK", CE, Country_LK_ChDesp, TRUE}, /* Sri Lanka */ + {"SE", CE, Country_SE_ChDesp, TRUE}, /* Sweden */ + {"CH", CE, Country_CH_ChDesp, TRUE}, /* Switzerland */ + {"SY", CE, Country_SY_ChDesp, TRUE}, /* Syrian Arab Republic */ + {"TW", FCC,Country_TW_ChDesp, FALSE}, /* Taiwan */ + {"TH", CE, Country_TH_ChDesp, FALSE}, /* Thailand */ + {"TT", CE, Country_TT_ChDesp, TRUE}, /* Trinidad and Tobago */ + {"TN", CE, Country_TN_ChDesp, TRUE}, /* Tunisia */ + {"TR", CE, Country_TR_ChDesp, TRUE}, /* Turkey */ + {"UA", CE, Country_UA_ChDesp, TRUE}, /* Ukraine */ + {"AE", CE, Country_AE_ChDesp, TRUE}, /* United Arab Emirates */ + {"GB", CE, Country_GB_ChDesp, TRUE}, /* United Kingdom */ + {"US", FCC,Country_US_ChDesp, FALSE}, /* United States */ + {"UY", CE, Country_UY_ChDesp, TRUE}, /* Uruguay */ + {"UZ", CE, Country_UZ_ChDesp, TRUE}, /* Uzbekistan */ + {"VE", CE, Country_VE_ChDesp, TRUE}, /* Venezuela */ + {"VN", CE, Country_VN_ChDesp, TRUE}, /* Viet Nam */ + {"YE", CE, Country_YE_ChDesp, TRUE}, /* Yemen */ + {"ZW", CE, Country_ZW_ChDesp, TRUE}, /* Zimbabwe */ + {"EU", CE, Country_EU_ChDesp, TRUE}, /* Europe */ + {"NA", FCC,Country_NA_ChDesp, FALSE}, /* North America */ + {"WO", CE, Country_WO_ChDesp, FALSE}, /* World Wide */ + {"" , 0, NULL, FALSE} , /* End */ +}; + +static PCH_REGION GetChRegion( + IN PUCHAR CntryCode) +{ + INT loop = 0; + PCH_REGION pChRegion = NULL; + + while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((PSTRING) ChRegion[loop].CountReg, (PSTRING) CntryCode, 2) == 0) + { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + + /* Default: use WO*/ + if (pChRegion == NULL) + pChRegion = GetChRegion("WO"); + + return pChRegion; +} + +static VOID ChBandCheck( + IN UCHAR PhyMode, + OUT PUCHAR pChType) +{ + *pChType = 0; + if (WMODE_CAP_5G(PhyMode)) + *pChType |= BAND_5G; + if (WMODE_CAP_2G(PhyMode)) + *pChType |= BAND_24G; + + if (*pChType == 0) + *pChType = BAND_24G; +} + +static UCHAR FillChList( + IN PRTMP_ADAPTER pAd, + IN PCH_DESP pChDesp, + IN UCHAR Offset, + IN UCHAR increment, + IN UCHAR regulatoryDomain) +{ + INT i, j, l; + UCHAR channel; + + j = Offset; + for (i = 0; i < pChDesp->NumOfCh; i++) + { + channel = pChDesp->FirstChannel + i * increment; + if (!strncmp((PSTRING) pAd->CommonCfg.CountryCode, "JP", 2)) + { + /* for JP, ch14 can only be used when PhyMode is "B only" */ + if ( (channel==14) && + (!WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))) + { + pChDesp->NumOfCh--; + break; + } + } +/*New FCC spec restrict the used channel under DFS */ +#ifdef CONFIG_AP_SUPPORT + if ((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->CommonCfg.RDDurRegion == FCC) && + (pAd->Dot11_H.bDFSIndoor == 1)) + { + if (RESTRICTION_BAND_1(pAd)) + continue; + } + else if ((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->CommonCfg.RDDurRegion == FCC) && + (pAd->Dot11_H.bDFSIndoor == 0)) + { + if ((channel >= 100) && (channel <= 140)) + continue; + } + +#endif /* CONFIG_AP_SUPPORT */ + for (l=0; lTxPower[l].Channel) + { + pAd->ChannelList[j].Power = pAd->TxPower[l].Power; + pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2; +#ifdef DOT11N_SS3_SUPPORT + pAd->ChannelList[j].Power3 = pAd->TxPower[l].Power3; +#endif /* DOT11N_SS3_SUPPORT */ + break; + } + } + if (l == MAX_NUM_OF_CHANNELS) + continue; + + pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment; + pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; + pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; + pAd->ChannelList[j].RegulatoryDomain = regulatoryDomain; +#ifdef DOT11_N_SUPPORT + if (N_ChannelGroupCheck(pAd, pAd->ChannelList[j].Channel)) + pAd->ChannelList[j].Flags |= CHANNEL_40M_CAP; +#ifdef DOT11_VHT_AC + if (vht80_channel_group(pAd, pAd->ChannelList[j].Channel)) + pAd->ChannelList[j].Flags |= CHANNEL_80M_CAP; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ +#ifdef SMART_MESH + pAd->ChannelList[j].bDfsAPExist = FALSE; +#endif /* SMART_MESH */ + +#ifdef RT_CFG80211_SUPPORT + CFG80211OS_ChanInfoInit( + pAd->pCfg80211_CB, + j, + pAd->ChannelList[j].Channel, + pAd->ChannelList[j].MaxTxPwr, + WMODE_CAP_N(pAd->CommonCfg.PhyMode), + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20)); +#endif /* RT_CFG80211_SUPPORT */ + + j++; + } + pAd->ChannelListNum = j; + + return j; +} + + +static inline VOID CreateChList( + IN PRTMP_ADAPTER pAd, + IN PCH_REGION pChRegion, + IN UCHAR Geography) +{ + INT i; + UCHAR offset = 0; + PCH_DESP pChDesp; + UCHAR ChType; + UCHAR increment; + UCHAR regulatoryDomain; + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + + if (pAd->CommonCfg.pChDesp != NULL) + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + else + pChDesp = pChRegion->pChDesp; + + for (i = 0; pChDesp[i].FirstChannel != 0; i++) + { + if (pChDesp[i].FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp[i].FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp[i].FirstChannel > 14) + continue; + } + + if ((pChDesp[i].Geography == BOTH) + || (Geography == BOTH) + || (pChDesp[i].Geography == Geography)) + { + if (pChDesp[i].FirstChannel > 14) + increment = 4; + else + increment = 1; + if (pAd->CommonCfg.DfsType != MAX_RD_REGION) + regulatoryDomain = pAd->CommonCfg.DfsType; + else + regulatoryDomain = pChRegion->DfsType; + offset = FillChList(pAd, &pChDesp[i], offset, increment, regulatoryDomain); + } + } +} + + +VOID BuildChannelListEx( + IN PRTMP_ADAPTER pAd) +{ + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); +} + +VOID BuildBeaconChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen) +{ + INT i; + ULONG TmpLen; + PCH_REGION pChRegion; + PCH_DESP pChDesp; + UCHAR ChType; + + pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + *pBufLen = 0; + + if (pAd->CommonCfg.pChDesp != NULL) + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + else + pChDesp = pChRegion->pChDesp; + + for (i=0; pChRegion->pChDesp[i].FirstChannel != 0; i++) + { + if (pChDesp[i].FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp[i].FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp[i].FirstChannel > 14) + continue; + } + + if ((pChDesp[i].Geography == BOTH) || + (pChDesp[i].Geography == pAd->CommonCfg.Geography)) + { + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChDesp[i].FirstChannel, + 1, &pChDesp[i].NumOfCh, + 1, &pChDesp[i].MaxTxPwr, + END_OF_ARGS); + *pBufLen += TmpLen; + } + } +} +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +COUNTRY_PROP CountryProp[]= +{ + {"AL", CE, TRUE}, /* Albania */ + {"DZ", CE, TRUE }, /* Algeria */ + {"AR", CE, TRUE }, /* Argentina */ + {"AM", CE, TRUE }, /* Armenia */ + {"AW", CE, TRUE }, /* Aruba */ + {"AU", CE, FALSE }, /* Australia */ + {"AT", CE, TRUE }, /* Austria */ + {"AZ", CE, TRUE }, /* Azerbaijan */ + {"BH", CE, TRUE }, /* Bahrain */ + {"BD", CE, TRUE }, /* Bangladesh */ + {"BB", CE, TRUE }, /* Barbados */ + {"BY", CE, TRUE }, /* Belarus */ + {"BE", CE, TRUE }, /* Belgium */ + {"BZ", CE, TRUE }, /* Belize */ + {"BO", CE, TRUE }, /* Bolivia */ + {"BA", CE, TRUE }, /* Bosnia and Herzegovina */ + {"BR", CE, FALSE }, /* Brazil */ + {"BN", CE, TRUE }, /* Brunei Darussalam */ + {"BG", CE, TRUE }, /* Bulgaria */ + {"KH", CE, TRUE }, /* Cambodia */ + {"CA", FCC, FALSE}, /* Canada */ + {"CL", CE, TRUE }, /* Chile */ + {"CN", CE, FALSE }, /* China */ + {"CO", CE, TRUE }, /* Colombia */ + {"CR", CE, TRUE }, /* Costa Rica */ + {"HR", CE, TRUE }, /* Croatia */ + {"CY", CE, TRUE }, /* Cyprus */ + {"CZ", CE, TRUE }, /* Czech Republic */ + {"DK", CE, TRUE }, /* Denmark */ + {"DO", CE, TRUE }, /* Dominican Republic */ + {"EC", CE, TRUE }, /* Ecuador */ + {"EG", CE, TRUE }, /* Egypt */ + {"SV", CE, TRUE }, /* El Salvador */ + {"EE", CE, TRUE }, /* Estonia */ + {"FI", CE, TRUE }, /* Finland */ + {"FR", CE, TRUE }, /* France */ + {"GE", CE, TRUE }, /* Georgia */ + {"DE", CE, TRUE }, /* Germany */ + {"GR", CE, TRUE }, /* Greece */ + {"GL", CE, TRUE }, /* Greenland */ + {"GD", CE, TRUE }, /* Grenada */ + {"GU", CE, TRUE }, /* Guam */ + {"GT", CE, TRUE }, /* Guatemala */ + {"HT", CE, TRUE }, /* Haiti */ + {"HN", CE, TRUE }, /* Honduras */ + {"HK", CE, TRUE }, /* Hong Kong */ + {"HU", CE, TRUE }, /* Hungary */ + {"IS", CE, TRUE }, /* Iceland */ + {"IN", CE, TRUE }, /* India */ + {"ID", CE, TRUE }, /* Indonesia */ + {"IR", CE, TRUE }, /* Iran, Islamic Republic of */ + {"IE", CE, TRUE }, /* Ireland */ + {"IL", CE, FALSE }, /* Israel */ + {"IT", CE, TRUE }, /* Italy */ + {"JM", CE, TRUE }, /* Jamaica */ + {"JP", JAP, FALSE}, /* Japan */ + {"JO", CE, TRUE }, /* Jordan */ + {"KZ", CE, TRUE }, /* Kazakhstan */ + {"KE", CE, TRUE }, /* Kenya */ + {"KP", CE, TRUE }, /* Korea, Democratic People's Republic of */ + {"KR", CE, FALSE }, /* Korea, Republic of */ + {"KW", CE, TRUE }, /* Kuwait */ + {"LV", CE, TRUE }, /* Latvia */ + {"LB", CE, TRUE }, /* Lebanon */ + {"LI", CE, TRUE }, /* Liechtenstein */ + {"LT", CE, TRUE }, /* Lithuania */ + {"LU", CE, TRUE }, /* Luxembourg */ + {"MO", CE, TRUE }, /* Macao */ + {"MK", CE, TRUE }, /* Macedonia, Republic of */ + {"MY", CE, TRUE }, /* Malaysia */ + {"MT", CE, TRUE }, /* Malta */ + {"MX", CE, FALSE }, /* Mexico */ + {"MC", CE, TRUE }, /* Monaco */ + {"MA", CE, TRUE }, /* Morocco */ + {"NP", CE, TRUE }, /* Nepal */ + {"NL", CE, TRUE }, /* Netherlands */ + {"AN", CE, TRUE }, /* Netherlands Antilles */ + {"NZ", CE, TRUE }, /* New Zealand */ + {"NO", CE, TRUE }, /* Norway */ + {"OM", CE, TRUE }, /* Oman */ + {"PK", CE, TRUE }, /* Pakistan */ + {"PA", CE, TRUE }, /* Panama */ + {"PG", CE, TRUE }, /* Papua New Guinea */ + {"PE", CE, TRUE }, /* Peru */ + {"PH", CE, TRUE }, /* Philippines */ + {"PL", CE, TRUE }, /* Poland */ + {"PT", CE, TRUE }, /* Portuga l*/ + {"PR", CE, TRUE }, /* Puerto Rico */ + {"QA", CE, TRUE }, /* Qatar */ + {"RO", CE, TRUE }, /* Romania */ + {"RU", CE, FALSE }, /* Russian Federation */ + {"BL", CE, TRUE }, /* Saint Barth'elemy */ + {"SA", CE, TRUE }, /* Saudi Arabia */ + {"SG", CE, TRUE }, /* Singapore */ + {"SK", CE, TRUE }, /* Slovakia */ + {"SI", CE, TRUE }, /* Slovenia */ + {"ZA", CE, FALSE }, /* South Africa */ + {"ES", CE, TRUE }, /* Spain */ + {"LK", CE, TRUE }, /* Sri Lanka */ + {"SE", CE, TRUE }, /* Sweden */ + {"CH", CE, TRUE }, /* Switzerland */ + {"SY", CE, TRUE }, /* Syrian Arab Republic */ + {"TW", FCC, FALSE}, /* Taiwan */ + {"TH", CE, FALSE }, /* Thailand */ + {"TT", CE, TRUE }, /* Trinidad and Tobago */ + {"TN", CE, TRUE }, /* Tunisia */ + {"TR", CE, TRUE }, /* Turkey */ + {"UA", CE, TRUE }, /* Ukraine */ + {"AE", CE, TRUE }, /* United Arab Emirates */ + {"GB", CE, TRUE }, /* United Kingdom */ + {"US", FCC, FALSE}, /* United States */ + {"UY", CE, TRUE }, /* Uruguay */ + {"UZ", CE, TRUE }, /* Uzbekistan */ + {"VE", CE, TRUE }, /* Venezuela */ + {"VN", CE, TRUE }, /* Viet Nam */ + {"YE", CE, TRUE }, /* Yemen */ + {"ZW", CE, TRUE }, /* Zimbabwe */ + {"EU", CE, TRUE }, /* Europe */ + {"NA", FCC, FALSE}, /* North America */ + {"WO", CE, FALSE}, /* World Wide */ + {"" , 0, FALSE} , /* End */ +}; + +static PCOUNTRY_PROP GetCountryProp( + IN PUCHAR CntryCode) +{ + INT loop = 0; + PCOUNTRY_PROP pCountryProp = NULL; + + while (strcmp((PSTRING) CountryProp[loop].CountReg, "") != 0) + { + if (strncmp((PSTRING) CountryProp[loop].CountReg, (PSTRING) CntryCode, 2) == 0) + { + pCountryProp = &CountryProp[loop]; + break; + } + loop++; + } + + /* Default: use WO*/ + if (pCountryProp == NULL) + pCountryProp = GetCountryProp("WO"); + + return pCountryProp; +} +#ifdef ED_MONITOR +BOOLEAN GetEDCCASupport( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN ret = FALSE; + +#ifdef EXT_BUILD_CHANNEL_LIST + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + + if ((pChReg->DfsType == CE) && (pChReg->edcca_on == TRUE) ) + { + // actually need to check PM's table in CE country + ret = TRUE; + } +#else + PCOUNTRY_PROP pCountryProp; + + pCountryProp = GetCountryProp(pAd->CommonCfg.CountryCode); + + if ((pCountryProp->DfsType == CE) && (pCountryProp->edcca_on == TRUE)) + { + // actually need to check PM's table in CE country + ret = TRUE; + } +#endif + + return ret; + +} +#endif /* ED_MONITOR */ + +UCHAR GetCountryRegionFromCountryCode( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ret=FCC; +#ifdef EXT_BUILD_CHANNEL_LIST + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + ret = pChReg->DfsType; + +#else + PCOUNTRY_PROP pCountryProp; + + pCountryProp = GetCountryProp(pAd->CommonCfg.CountryCode); + ret = pCountryProp->DfsType; +#endif + return ret; +} +#ifdef DOT11_N_SUPPORT +static BOOLEAN IsValidChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) + +{ + INT i; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return FALSE; + else + return TRUE; +} + +static UCHAR GetExtCh( + IN UCHAR Channel, + IN UCHAR Direction) +{ + CHAR ExtCh; + + if (Direction == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + return ExtCh; +} + +#ifdef DOT11_VHT_AC +INT get_vht_neighbor_index(IN UCHAR channel) +{ + if ((channel == 36) || (channel == 52) + || (channel == 100) || (channel == 116) + || (channel == 132) || (channel == 149)) { + return 0; + } + else if ((channel == 40) || (channel == 56) + || (channel == 104) || (channel == 120) + || (channel == 136) || (channel == 153)) { + return -1; + } + else if ((channel == 44) || (channel == 60) + || (channel == 108) || (channel == 124) + || (channel == 140) || (channel == 157)) { + return -2; + } + else if ((channel == 48) || (channel == 64) + || (channel == 112) || (channel == 128) + || (channel == 144) || (channel == 161)) { + return -3; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: un-expected case. (channel=%d)\n", + __FUNCTION__, channel)); + return (MAX_NUM_OF_CHANNELS+1); + } +} + +BOOLEAN AC_ChannelGroupCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + BOOLEAN RetVal = FALSE; + UCHAR vht_ch_group[] = { + 36, 40, 44, 48, + 52, 56, 60, 64, + 100, 104, 108, 112, + 116, 120, 124, 128, + 132, 136, 140, 144, + 149, 153, 157, 161 + }; + UINT8 num_ch = sizeof(vht_ch_group)/sizeof(UCHAR); + UINT8 idx; + UCHAR region = GetCountryRegionFromCountryCode(pAd); + + if (Channel > 14) + { /* 5G Band */ + for (idx=0; idx= 132) || ((region == FCC) && vht_ch_group[idx] >= 116 && vht_ch_group[idx] <= 128)) + { + continue; + } + else + { + /* in BW_80 channel group */ + RetVal = TRUE; + break; + } + } + } + } + + return RetVal; +} +#endif /* DOT11_VHT_AC */ + +BOOLEAN N_ChannelGroupCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + BOOLEAN RetVal = FALSE; + + if (Channel > 14) + { + if ((Channel == 36) || (Channel == 44) || (Channel == 52) + || (Channel == 60) || (Channel == 100) || (Channel == 108) + || (Channel == 116) || (Channel == 124) || (Channel == 132) + || (Channel == 149) || (Channel == 157)) + { + RetVal = TRUE; + } + else if ((Channel == 40) || (Channel == 48) || (Channel == 56) + || (Channel == 64) || (Channel == 104) || (Channel == 112) + || (Channel == 120) || (Channel == 128) || (Channel == 136) + || (Channel == 153) || (Channel == 161)) + { + RetVal = TRUE; + } + } + else + { + do + { + UCHAR ExtCh; + + if (Channel == 14) + { + RetVal = FALSE; + break; + } + + ExtCh = GetExtCh(Channel, EXTCHA_ABOVE); + if (IsValidChannel(pAd, ExtCh)) + RetVal = TRUE; + else + { + ExtCh = GetExtCh(Channel, EXTCHA_BELOW); + if (IsValidChannel(pAd, ExtCh)) + RetVal = TRUE; + } + } while(FALSE); + } + + return RetVal; +} + + +VOID N_ChannelCheck(RTMP_ADAPTER *pAd) +{ + INT idx; + UCHAR Channel = pAd->CommonCfg.Channel; + static const UCHAR wfa_ht_ch_ext[] = { + 36, EXTCHA_ABOVE, 40, EXTCHA_BELOW, + 44, EXTCHA_ABOVE, 48, EXTCHA_BELOW, + 52, EXTCHA_ABOVE, 56, EXTCHA_BELOW, + 60, EXTCHA_ABOVE, 64, EXTCHA_BELOW, + 100, EXTCHA_ABOVE, 104, EXTCHA_BELOW, + 108, EXTCHA_ABOVE, 112, EXTCHA_BELOW, + 116, EXTCHA_ABOVE, 120, EXTCHA_BELOW, + 124, EXTCHA_ABOVE, 128, EXTCHA_BELOW, + 132, EXTCHA_ABOVE, 136, EXTCHA_BELOW, + 140, EXTCHA_ABOVE, 144, EXTCHA_BELOW, + 149, EXTCHA_ABOVE, 153, EXTCHA_BELOW, + 157, EXTCHA_ABOVE, 161, EXTCHA_BELOW, + 0, 0}; + + /* channel is not set yet (e.g. AutoChannelSelect > 0) */ + if (Channel == 0) + return; + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.RegTransmitSetting.field.BW >= BW_40)) + { + if (Channel > 14) + { + idx = 0; + while(wfa_ht_ch_ext[idx] != 0) { + if (wfa_ht_ch_ext[idx] == Channel && IsValidChannel(pAd, GetExtCh(Channel, wfa_ht_ch_ext[idx + 1]))) { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = wfa_ht_ch_ext[idx + 1]; + break; + } + idx += 2; + }; + + if (wfa_ht_ch_ext[idx] == 0) { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.vht_bw > VHT_BW_2040)) + pAd->CommonCfg.vht_bw = VHT_BW_2040; +#endif /* DOT11_VHT_AC */ + } + } + else + { + do + { + UCHAR ExtCh; + UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + break; + + Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; + break; + } + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } while(FALSE); + + if (Channel == 14) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + /*pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT()*/ + } + } + } +} + + +UCHAR N_SetCenCh(RTMP_ADAPTER *pAd, UCHAR prim_ch) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + pAd->CommonCfg.CentralChannel = prim_ch + 2; + else + { + if (prim_ch == 14) + pAd->CommonCfg.CentralChannel = prim_ch - 1; + else + pAd->CommonCfg.CentralChannel = prim_ch - 2; + } + } + else + pAd->CommonCfg.CentralChannel = prim_ch; + + return pAd->CommonCfg.CentralChannel; +} + + +#ifdef SMART_MESH_MONITOR +UCHAR N_GetSecondaryChannel(RTMP_ADAPTER *pAd) +{ + INT idx; + UCHAR ExtChaDir,SecondaryChannel; + UCHAR PrimaryChannel = pAd->CommonCfg.Channel; + SecondaryChannel = PrimaryChannel; + static const UCHAR wfa_ht_ch_ext[] = { + 36, EXTCHA_ABOVE, 40, EXTCHA_BELOW, + 44, EXTCHA_ABOVE, 48, EXTCHA_BELOW, + 52, EXTCHA_ABOVE, 56, EXTCHA_BELOW, + 60, EXTCHA_ABOVE, 64, EXTCHA_BELOW, + 100, EXTCHA_ABOVE, 104, EXTCHA_BELOW, + 108, EXTCHA_ABOVE, 112, EXTCHA_BELOW, + 116, EXTCHA_ABOVE, 120, EXTCHA_BELOW, + 124, EXTCHA_ABOVE, 128, EXTCHA_BELOW, + 132, EXTCHA_ABOVE, 136, EXTCHA_BELOW, + 149, EXTCHA_ABOVE, 153, EXTCHA_BELOW, + 157, EXTCHA_ABOVE, 161, EXTCHA_BELOW, + 0, 0}; + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.RegTransmitSetting.field.BW >= BW_40)) + { + if (PrimaryChannel > 14) + { + idx = 0; + while(wfa_ht_ch_ext[idx] != 0) { + if (wfa_ht_ch_ext[idx] == PrimaryChannel) { + ExtChaDir = wfa_ht_ch_ext[idx + 1]; + break; + } + idx += 2; + }; + + if (wfa_ht_ch_ext[idx] != 0) + { + if(ExtChaDir == EXTCHA_ABOVE) + SecondaryChannel = wfa_ht_ch_ext[idx+2]; + else + SecondaryChannel = wfa_ht_ch_ext[idx-2]; + } + } + else + { + do + { + ExtChaDir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + SecondaryChannel = GetExtCh(PrimaryChannel, ExtChaDir); + if (IsValidChannel(pAd, SecondaryChannel)) + break; + + + ExtChaDir = (ExtChaDir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + SecondaryChannel = GetExtCh(PrimaryChannel, ExtChaDir); + if (IsValidChannel(pAd, SecondaryChannel)) + break; + } while(FALSE); + } + } + + return SecondaryChannel; +} +#endif /* SMART_MESH_MONITOR */ + +#endif /* DOT11_N_SUPPORT */ + + +UINT8 GetCuntryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel) +{ + int i; + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return 0xff; +#ifdef SINGLE_SKU + if (pAd->CommonCfg.bSKUMode == TRUE) + { + UINT deltaTxStreamPwr = 0; + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.TxStream == 2)) + deltaTxStreamPwr = 3; /* If 2Tx case, antenna gain will increase 3dBm*/ +#endif /* DOT11_N_SUPPORT */ + + if (pAd->ChannelList[i].RegulatoryDomain == FCC) + { + /* FCC should maintain 20/40 Bandwidth, and without antenna gain */ +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && + (channel == 1 || channel == 11)) + return (pAd->ChannelList[i].MaxTxPwr - pAd->CommonCfg.BandedgeDelta - deltaTxStreamPwr); + else +#endif /* DOT11_N_SUPPORT */ + return (pAd->ChannelList[i].MaxTxPwr - deltaTxStreamPwr); + } + else if (pAd->ChannelList[i].RegulatoryDomain == CE) + { + return (pAd->ChannelList[i].MaxTxPwr - pAd->CommonCfg.AntGain - deltaTxStreamPwr); + } + else + return 0xff; + } + else +#endif /* SINGLE_SKU */ + return pAd->ChannelList[i].MaxTxPwr; +} + + +/* for OS_ABL */ +VOID RTMP_MapChannelID2KHZ( + IN UCHAR Ch, + OUT UINT32 *pFreq) +{ + int chIdx; + for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++) + { + if ((Ch) == CH_HZ_ID_MAP[chIdx].channel) + { + (*pFreq) = CH_HZ_ID_MAP[chIdx].freqKHz * 1000; + break; + } + } + if (chIdx == CH_HZ_ID_MAP_NUM) + (*pFreq) = 2412000; +} + +/* for OS_ABL */ +VOID RTMP_MapKHZ2ChannelID( + IN ULONG Freq, + OUT INT *pCh) +{ + int chIdx; + for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++) + { + if ((Freq) == CH_HZ_ID_MAP[chIdx].freqKHz) + { + (*pCh) = CH_HZ_ID_MAP[chIdx].channel; + break; + } + } + if (chIdx == CH_HZ_ID_MAP_NUM) + (*pCh) = 1; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_led.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_led.c new file mode 100644 index 000000000..c7f726762 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_led.c @@ -0,0 +1,1091 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002-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. + **************************************************************************** + + Module Name: + rt_led.c + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#include "rt_config.h" + +#ifdef LED_CONTROL_SUPPORT + +INT LED_Array[16][12]={ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 2, 1, 0, -1, -1, 0, -1, 5, -1, -1, 17}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 2, -1, -1, -1, -1, 16, 1, 5, -1, -1, 17}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 1, -1, -1, -1, 3, -1, 6, -1, -1, 0}, + { 1, 2, 1, -1, -1, -1, -1, 1, 4, -1, -1, 18} +}; + +#ifdef CONFIG_SWMCU_SUPPORT +INT Show_LedCfg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LED_CFG_T macLedCfg; + ULED_PARAMETER *pLedParameter; + + pLedParameter = &pAd->LedCntl.SWMCULedCntl.LedParameter; + + printk("LedAMode_RadioOnLinkA=%d\n", pLedParameter->LedAgCfg.field.LedAMode_RadioOnLinkA); + printk("LedGMode_RadioOnLinkA=%d\n", pLedParameter->LedAgCfg.field.LedGMode_RadioOnLinkA); + printk("LedAMode_RadioOnLinkG=%d\n", pLedParameter->LedAgCfg.field.LedAMode_RadioOnLinkG); + printk("LedGMode_RadioOnLinkG=%d\n", pLedParameter->LedAgCfg.field.LedGMode_RadioOnLinkG); + printk("LedAMode_RadioOnLinkDown=%d\n", pLedParameter->LedAgCfg.field.LedAMode_RadioOnLinkDown); + printk("LedGMode_RadioOnLinkDown=%d\n", pLedParameter->LedAgCfg.field.LedGMode_RadioOnLinkDown); + printk("LedAMode_RadioOff=%d\n", pLedParameter->LedAgCfg.field.LedAMode_RadioOff); + printk("LedGMode_RadioOff=%d\n", pLedParameter->LedAgCfg.field.LedGMode_RadioOff); + + printk("LedActModeNoTx_RadioOnLinkA=%d\n", pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOnLinkA); + printk("LedActMode_RadioOnLinkA=%d\n", pLedParameter->LedActCfg.field.LedActMode_RadioOnLinkA); + printk("LedActModeNoTx_RadioOnLinkG=%d\n", pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOnLinkG); + printk("LedActMode_RadioOnLinkG=%d\n", pLedParameter->LedActCfg.field.LedActMode_RadioOnLinkG); + printk("LedActModeNoTx_RadioOnLinkDown=%d\n", pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOnLinkDown); + printk("LedActMode_RadioOnLinkDown=%d\n", pLedParameter->LedActCfg.field.LedActMode_RadioOnLinkDown); + printk("LedActModeNoTx_RadioOff=%d\n", pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOff); + printk("LedActMode_RadioOff=%d\n", pLedParameter->LedActCfg.field.LedActMode_RadioOff); + + RTMP_IO_READ32(pAd, MAC_LED_CFG, &macLedCfg.word); + + printk("LED_CFG = %x\n\n", macLedCfg.word); + printk("LED_ON_TIME = %d\n", macLedCfg.field.LED_ON_TIME); + printk("LED_OFF_TIME = %d\n", macLedCfg.field.LED_OFF_TIME); + printk("SLOW_BLK_TIME = %d\n", macLedCfg.field.SLOW_BLK_TIME); + printk("R_LED_MODE (A) = %d\n", macLedCfg.field.R_LED_MODE); + printk("G_LED_MODE (ACT) = %d\n", macLedCfg.field.G_LED_MODE); + printk("Y_LED_MODE (A) = %d\n", macLedCfg.field.Y_LED_MODE); + printk("LED_POL = %d\n", macLedCfg.field.LED_POL); + + return TRUE; +} + + +INT Set_LedCfg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT loop; + PCHAR thisChar; + long polarity=0; + long ledOnTime=0; + long ledOffTime=0; + long slowBlkTime=0; + + loop = 0; + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(loop) + { + case 0: + polarity = simple_strtol(thisChar, 0, 10); + break; + + case 1: + ledOnTime = simple_strtol(thisChar, 0, 10); + break; + + case 2: + ledOffTime = simple_strtol(thisChar, 0, 10); + break; + + case 3: + slowBlkTime = simple_strtol(thisChar, 0, 10); + break; + + default: + break; + } + loop ++; + } + + SetLedCfg(pAd, (INT)polarity, (INT)ledOnTime, (INT)ledOffTime, (INT)slowBlkTime); + + return TRUE; +} + +INT Set_LedCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT loop; + PCHAR thisChar; + long ledSel=0; + long ledMode=0; + + loop = 0; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(loop) + { + case 0: + ledSel = simple_strtol(thisChar, 0, 10); + break; + + case 1: + ledMode = simple_strtol(thisChar, 0, 10); + break; + + default: + break; + } + loop ++; + } + + SetLedMode(pAd, (INT)ledSel, (INT)ledMode); + + return TRUE; +} + +VOID SetLedCfg( + IN PRTMP_ADAPTER pAd, + IN INT ledPolarity, + IN INT ledOnTime, + IN INT ledOffTime, + IN INT slowBlkTime) +{ + LED_CFG_T macLedCfg; + RTMP_IO_READ32(pAd, MAC_LED_CFG, &macLedCfg.word); + + macLedCfg.field.LED_POL = ledPolarity; + macLedCfg.field.LED_ON_TIME = ledOnTime; + macLedCfg.field.LED_OFF_TIME = ledOffTime; + macLedCfg.field.SLOW_BLK_TIME = slowBlkTime; + + RTMP_IO_WRITE32(pAd, MAC_LED_CFG, macLedCfg.word); + + return; +} + +VOID SetLedMode( + IN PRTMP_ADAPTER pAd, + IN INT LedSel, + IN INT LedMode) +{ + LED_CFG_T macLedCfg; + RTMP_IO_READ32(pAd, MAC_LED_CFG, &macLedCfg.word); + + switch(LedSel) + { + case LED_G: /* LED G. */ + macLedCfg.field.Y_LED_MODE = LedMode; + break; + + case LED_A: /* LED A. */ + macLedCfg.field.G_LED_MODE = LedMode; + break; + + case LED_ACT: /* LED ACT. */ + macLedCfg.field.R_LED_MODE = LedMode; + break; + + default: + break; + } + + RTMP_IO_WRITE32(pAd, MAC_LED_CFG, macLedCfg.word); + + return; +} + + +/* + * WPS Type : time of LED on, + * time of LED off, + * time of on/off cycles that LED blink, + * time of on/off cycles that LED rest + * InProgress: 0.2s, 0.1s, infinite, 0s + * Error: 0.1s, 0.1s, infinite, 0s + * Session Overlap Detected: 0.1s, 0.1s, 1s, 0.5s + * Success: 300s, infinite, infinite, 0s + * Pre, Post stage: 0.5s, 0.5s, infinite, 0s + */ +void SetWPSLinkStatus(IN PRTMP_ADAPTER pAd) +{ + PLED_OPERATION_MODE pCurrentLedCfg = &pAd->LedCntl.SWMCULedCntl.CurrentLedCfg; + PWPS_LED_TIME_UNIT pWPSLedTimeUnit = &pAd->LedCntl.SWMCULedCntl.WPSLedTimeUnit; + + switch(pAd->LedCntl.SWMCULedCntl.LinkStatus) + { +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + case LINK_STATUS_WPS_IN_PROCESS: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_IN_PROCESS; + pWPSLedTimeUnit->OnPeriod = 0.2 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = 0.1 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_WPS_ERROR: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_ERROR; + pWPSLedTimeUnit->OnPeriod = 0.1 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = 0.1 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_WPS_SESSION_OVERLAP_DETECTED: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_SESSION_OVERLAP_DETECTED; + pWPSLedTimeUnit->OnPeriod = 0.1 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = 0.1 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->BlinkPeriod = 1 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->RestPeriod = 0.5 * 1000 / LED_CHECK_INTERVAL; + break; + case LINK_STATUS_WPS_SUCCESS_WITH_SECURITY: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_SUCCESS_WITH_SECURITY; + pWPSLedTimeUnit->OnPeriod = 300 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_WPS_SUCCESS_WITHOUT_SECURITY: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_SUCCESS_WITHOUT_SECURITY; + pWPSLedTimeUnit->OnPeriod = 300 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_WPS_TURN_LED_OFF: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_TURN_LED_OFF; + pWPSLedTimeUnit->OnPeriod = 0; + pWPSLedTimeUnit->OffPeriod = 0; + pWPSLedTimeUnit->BlinkPeriod = 0; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_NORMAL_CONNECTION_WITHOUT_SECURITY: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_NORMAL_CONNECTION_WITHOUT_SECURITY; + pWPSLedTimeUnit->OnPeriod = 300 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_NORMAL_CONNECTION_WITH_SECURITY: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_NORMAL_CONNECTION_WITH_SECURITY; + pWPSLedTimeUnit->OnPeriod = 300 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; +#endif /* WSC_INCLUDED */ +#endif /* WSC_LED_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s:(Unknown LinkStatus)%d", __FUNCTION__, pAd->LedCntl.SWMCULedCntl.LinkStatus)); + break; + } + + pWPSLedTimeUnit->LeftOnPeriod = pWPSLedTimeUnit->OnPeriod; + pWPSLedTimeUnit->LeftOffPeriod = pWPSLedTimeUnit->OffPeriod; + pWPSLedTimeUnit->LeftBlinkPeriod = pWPSLedTimeUnit->BlinkPeriod; + pWPSLedTimeUnit->LeftRestPeriod = pWPSLedTimeUnit->RestPeriod; +} + + +void SetLedLinkStatus(IN PRTMP_ADAPTER pAd) +{ + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; + ULED_PARAMETER *pLedParameter = &pAd->LedCntl.SWMCULedCntl.LedParameter; + PLED_OPERATION_MODE pCurrentLedCfg = &pAd->LedCntl.SWMCULedCntl.CurrentLedCfg; + + pAd->LedCntl.SWMCULedCntl.BlinkFor8sTimer = 0; + + switch(pSWMCULedCntl->LinkStatus) + { + case LINK_STATUS_RADIO_OFF: /* Radio off */ + pCurrentLedCfg->field.LedGMode = pLedParameter->LedAgCfg.field.LedGMode_RadioOff; + pCurrentLedCfg->field.LedAMode = pLedParameter->LedAgCfg.field.LedAMode_RadioOff; + pCurrentLedCfg->field.LedActMode = pLedParameter->LedActCfg.field.LedActMode_RadioOff; + pCurrentLedCfg->field.LedActModeNoTx = pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOff; + pCurrentLedCfg->field.LedGPolarity = pLedParameter->LedPolarityCfg.field.LedGPolarity_RadioOff; + pCurrentLedCfg->field.LedAPolarity = pLedParameter->LedPolarityCfg.field.LedAPolarity_RadioOff; + pCurrentLedCfg->field.LedActPolarity = pLedParameter->LedPolarityCfg.field.LedActPolarity_RadioOff; + break; + + case LINK_STATUS_RADIO_ON: /* Radio on but not link up */ + pCurrentLedCfg->field.LedGMode = pLedParameter->LedAgCfg.field.LedGMode_RadioOnLinkDown; + pCurrentLedCfg->field.LedAMode = pLedParameter->LedAgCfg.field.LedAMode_RadioOnLinkDown; + pCurrentLedCfg->field.LedActMode = pLedParameter->LedActCfg.field.LedActMode_RadioOnLinkDown; + pCurrentLedCfg->field.LedActModeNoTx = pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOnLinkDown; + pCurrentLedCfg->field.LedGPolarity = pLedParameter->LedPolarityCfg.field.LedGPolarity_RadioOnLinkDown; + pCurrentLedCfg->field.LedAPolarity = pLedParameter->LedPolarityCfg.field.LedAPolarity_RadioOnLinkDown; + pCurrentLedCfg->field.LedActPolarity = pLedParameter->LedPolarityCfg.field.LedActPolarity_RadioOnLinkDown; + break; + + case LINK_STATUS_GBAND_LINK_UP: /* Radio on and link to G */ + pCurrentLedCfg->field.LedGMode = pLedParameter->LedAgCfg.field.LedGMode_RadioOnLinkG; + pCurrentLedCfg->field.LedAMode = pLedParameter->LedAgCfg.field.LedAMode_RadioOnLinkG; + pCurrentLedCfg->field.LedActMode = pLedParameter->LedActCfg.field.LedActMode_RadioOnLinkG; + pCurrentLedCfg->field.LedActModeNoTx = pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOnLinkG; + pCurrentLedCfg->field.LedGPolarity = pLedParameter->LedPolarityCfg.field.LedGPolarity_RadioOnLinkG; + pCurrentLedCfg->field.LedAPolarity = pLedParameter->LedPolarityCfg.field.LedAPolarity_RadioOnLinkG; + pCurrentLedCfg->field.LedActPolarity = pLedParameter->LedPolarityCfg.field.LedActPolarity_RadioOnLinkG; + break; + + case LINK_STATUS_ABAND_LINK_UP: /* Radio on and link to A */ + pCurrentLedCfg->field.LedGMode = pLedParameter->LedAgCfg.field.LedGMode_RadioOnLinkA; + pCurrentLedCfg->field.LedAMode = pLedParameter->LedAgCfg.field.LedAMode_RadioOnLinkA; + pCurrentLedCfg->field.LedActMode = pLedParameter->LedActCfg.field.LedActMode_RadioOnLinkA; + pCurrentLedCfg->field.LedActModeNoTx = pLedParameter->LedActCfg.field.LedActModeNoTx_RadioOnLinkA; + pCurrentLedCfg->field.LedGPolarity = pLedParameter->LedPolarityCfg.field.LedGPolarity_RadioOnLinkA; + pCurrentLedCfg->field.LedAPolarity = pLedParameter->LedPolarityCfg.field.LedAPolarity_RadioOnLinkA; + pCurrentLedCfg->field.LedActPolarity = pLedParameter->LedPolarityCfg.field.LedActPolarity_RadioOnLinkA; + break; + + case LINK_STATUS_WPS: /* WPS */ + if(pLedParameter->LedMode == LED_MODE_WPS_LOW_POLARITY) + { + pCurrentLedCfg->field.LedActPolarity = ACTIVE_LOW; + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_SOLID_ON; /* Force ACT to solid on/off */ + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_OFF; /* Force ACT to solid on/off */ + } + if(pLedParameter->LedMode == LED_MODE_WPS_HIGH_POLARITY) + { + pCurrentLedCfg->field.LedActPolarity = ACTIVE_HIGH; + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_SOLID_ON; /* Force ACT to solid on/off */ + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_OFF; /* Force ACT to solid on/off */ + } + break; + + case LINK_STATUS_ON_SITE_SURVEY: + if (pLedParameter->LedMode == LED_MODE_8SEC_SCAN) + pSWMCULedCntl->BlinkFor8sTimer = (8000 / LED_CHECK_INTERVAL); + break; + } +} + + +static void ChgSignalStrengthLed( + IN PRTMP_ADAPTER pAd) +{ + RTMP_IO_WRITE32(pAd, GPIO_DIR, 0x00); /* set GPIO to output. */ + RTMP_IO_WRITE32(pAd, GPIO_DAT, (pAd->LedCntl.SWMCULedCntl.GPIOPolarity ? pAd->LedCntl.SWMCULedCntl.SignalStrength : ~pAd->LedCntl.SWMCULedCntl.SignalStrength)); +} + + +static inline int TX_TRAFFIC_EXIST( + IN PRTMP_ADAPTER pAd) +{ + UINT RegValue; + + RTMP_IO_READ32(pAd, MCU_INT_STATUS, &RegValue); + return (RegValue & 0x0e); +} + +static inline int BEN_TC_ACT( + IN PRTMP_ADAPTER pAd) +{ + UINT RegValue; + + RTMP_IO_READ32(pAd, MCU_INT_STATUS, &RegValue); + return (RegValue & 0x10); +} + + + +/* Change LED State according to CurrentLedPolarity, CurrentLedCfg, and Tx activity */ +/* The result is stored in AbstractMacLedCfg (Abstract MacLedCfg). */ +/* AbstractMacLedCfg is an abstract layer. Since MAC's LED_CFG doesn't match firmware requirement totally, */ +/* this abstract layer is to hide these difference. */ +static void ChgMacLedCfg( + IN PRTMP_ADAPTER pAd) +{ + LED_CFG_T LedCfgBuf; + BYTE DataTxActivity, BeaconTxActivity; + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; + PLED_OPERATION_MODE pCurrentLedCfg = &pAd->LedCntl.SWMCULedCntl.CurrentLedCfg; + + /* + ** MCU_INT_STA (offset: 0x0414) + ** bit 1: MTX2_INT, TX2Q to MAC frame transfer complete interrupt. + ** bit 2: MTX1_INT, TX1Q to MAC frame transfer complete interrupt. + ** bit 3: MTX0_INT, TX0Q to MAC frame transfer complete interrupt. + */ + if (TX_TRAFFIC_EXIST(pAd)) /* Check if there is Tx Traffic */ + DataTxActivity = 1; + else + DataTxActivity = 0; + + /* Check if there are beacon */ + BeaconTxActivity = BEN_TC_ACT(pAd); + + /* Clear Tx and beacon Tx complete interrupt */ + RTMP_IO_WRITE32(pAd, MCU_INT_STATUS, 0x1e); + + RTMP_IO_READ32(pAd, MAC_LED_CFG, &LedCfgBuf.word); + + /* For backward compatible issue, + * LedActMode: 0: None, 1: Solid ON, 2: Blink (data/mgr), 3: Blink (data,mgr,beacon) + * =>Solid off = solid on + high polarity + */ + LedCfgBuf.field.LED_POL = pCurrentLedCfg->field.LedActPolarity; + if(pSWMCULedCntl->LedBlinkTimer!=0) + pSWMCULedCntl->LedBlinkTimer--; + else + pSWMCULedCntl->LedBlinkTimer = 0xff; + + /* LED Act. connect to G_LED. */ + if (pSWMCULedCntl->LedParameter.LedMode == LED_MODE_8SEC_SCAN && pSWMCULedCntl->BlinkFor8sTimer) + { + UINT8 LedPolarity = pCurrentLedCfg->field.LedActPolarity ? 0 : 3; + LedCfgBuf.field.G_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 0) ? LedPolarity : ~LedPolarity; + pSWMCULedCntl->BlinkFor8sTimer--; + } + else if (pCurrentLedCfg->field.LedActMode == MCU_LED_ACT_OFF) + { + LedCfgBuf.field.G_LED_MODE = + pCurrentLedCfg->field.LedActPolarity ? MAC_LED_ON : MAC_LED_OFF; + } + else if (pCurrentLedCfg->field.LedActMode == MCU_LED_ACT_SOLID_ON) + { + LedCfgBuf.field.G_LED_MODE = + pCurrentLedCfg->field.LedActPolarity ? MAC_LED_OFF : MAC_LED_ON; + } + else if ((DataTxActivity && pCurrentLedCfg->field.LedActMode > MCU_LED_ACT_SOLID_ON) /* Data packet transmited. */ + || (BeaconTxActivity && pCurrentLedCfg->field.LedActMode == MCU_LED_ACT_BLINK_UPON_TX_DATA_MNG_BEN)) /* Beacon frame transmited. */ + { + LedCfgBuf.field.G_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 0) ? MAC_LED_ON : MAC_LED_OFF; + } + else if (!DataTxActivity && !BeaconTxActivity) + { + if (pCurrentLedCfg->field.LedActModeNoTx == 0) /* solid on when no tx. */ + LedCfgBuf.field.G_LED_MODE = + pCurrentLedCfg->field.LedActPolarity ? MAC_LED_OFF : MAC_LED_ON; + else /* slow blink. */ + LedCfgBuf.field.G_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 4) ? MAC_LED_ON : MAC_LED_OFF; + } + + /* LED G. connect to Y_LED. */ + if (pCurrentLedCfg->field.LedGMode == MCU_LED_G_FAST_BLINK) + LedCfgBuf.field.Y_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 0) ? MAC_LED_ON : MAC_LED_OFF; + else if (pCurrentLedCfg->field.LedGMode == MCU_LED_G_SLOW_BLINK) + LedCfgBuf.field.Y_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 4) ? MAC_LED_ON : MAC_LED_OFF; + else if (pCurrentLedCfg->field.LedGMode == MCU_LED_G_SOLID_ON) + LedCfgBuf.field.Y_LED_MODE = + pCurrentLedCfg->field.LedGPolarity ? MAC_LED_OFF : MAC_LED_ON; + else /* dark */ + LedCfgBuf.field.Y_LED_MODE = + pCurrentLedCfg->field.LedGPolarity ? MAC_LED_ON : MAC_LED_OFF; + + /* LED A. connect to R_LED. */ + if (pCurrentLedCfg->field.LedAMode == MCU_LED_A_FAST_BLINK) + LedCfgBuf.field.R_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 0) ? MAC_LED_ON : MAC_LED_OFF; + else if (pCurrentLedCfg->field.LedAMode == MCU_LED_A_SLOW_BLINK) + LedCfgBuf.field.R_LED_MODE = GetBitX(pSWMCULedCntl->LedBlinkTimer, 4) ? MAC_LED_ON : MAC_LED_OFF; + else if (pCurrentLedCfg->field.LedAMode == MCU_LED_A_SOLID_ON) + LedCfgBuf.field.R_LED_MODE = + pCurrentLedCfg->field.LedAPolarity ? MAC_LED_OFF : MAC_LED_ON; + else + LedCfgBuf.field.R_LED_MODE = + pCurrentLedCfg->field.LedAPolarity ? MAC_LED_ON : MAC_LED_OFF; + + if ((pSWMCULedCntl->bWlanLed) && !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + { + RTMP_IO_WRITE32(pAd, MAC_LED_CFG, LedCfgBuf.word); + } + else + { + { + RTMP_IO_WRITE32(pAd, MAC_LED_CFG, 0); + } + } + + return; +} + + + + +/* Entry for SWMCU Led control. Triggered by timer per LED_CHECK_INTERVAL */ +void SWMCULedCtrlMain( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; + + switch(pSWMCULedCntl->LedParameter.LedMode) + { + case 0: /* Hardware controlled mode. Just ignore it. */ + return; + case LED_MODE_SIGNAL_STREGTH: /* In addition to mode 0, set signal strength LED */ + ChgSignalStrengthLed(pAd); + break; + default: + ChgMacLedCfg(pAd); + break; + } +} +BUILD_TIMER_FUNCTION(SWMCULedCtrlMain); + +#endif /* CONFIG_SWMCU_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Set LED Status + + Arguments: + pAd Pointer to our adapter + Status LED Status + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPSetLEDStatus( + IN PRTMP_ADAPTER pAd, + IN UCHAR Status) +{ + /*ULONG data; */ + UCHAR LinkStatus = 0; + UCHAR LedMode; + UCHAR MCUCmd = 0; + BOOLEAN bIgnored = FALSE; + INT led_cmd = -1; +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + PWSC_CTRL pWscControl = NULL; + +#ifdef CONFIG_AP_SUPPORT + pWscControl = &pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + pWscControl = &pAd->StaCfg.WscControl; +#endif /* CONFIG_STA_SUPPORT */ +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef RALINK_ATE + /* + In ATE mode of RT2860 AP/STA, we have erased 8051 firmware. + So LED mode is not supported when ATE is running. + */ + if (!IS_RT3572(pAd)) + { + if (ATE_ON(pAd)) + return; + } +#endif /* RALINK_ATE */ + + + + LedMode = LED_MODE(pAd); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + if (LedMode < 0 || Status < 0 || LedMode > 15 || Status > 11) + return; + + led_cmd = LED_Array[LedMode][Status]; + } +#endif + + switch (Status) + { + case LED_LINK_DOWN: + LinkStatus = LINK_STATUS_LINK_DOWN; + pAd->LedCntl.LedIndicatorStrength = 0; + MCUCmd = MCU_SET_LED_MODE; + break; + case LED_LINK_UP: + if (pAd->CommonCfg.Channel > 14) + LinkStatus = LINK_STATUS_ABAND_LINK_UP; + else + LinkStatus = LINK_STATUS_GBAND_LINK_UP; + + MCUCmd = MCU_SET_LED_MODE; + break; + case LED_RADIO_ON: + LinkStatus = LINK_STATUS_RADIO_ON; + MCUCmd = MCU_SET_LED_MODE; + break; + case LED_HALT: + LedMode = 0; /* Driver sets MAC register and MAC controls LED */ + case LED_RADIO_OFF: + LinkStatus = LINK_STATUS_RADIO_OFF; + MCUCmd = MCU_SET_LED_MODE; + break; + case LED_WPS: + LinkStatus = LINK_STATUS_WPS; + MCUCmd = MCU_SET_LED_MODE; + break; + case LED_ON_SITE_SURVEY: + LinkStatus = LINK_STATUS_ON_SITE_SURVEY; + MCUCmd = MCU_SET_LED_MODE; + break; + case LED_POWER_UP: + LinkStatus = LINK_STATUS_POWER_UP; + MCUCmd = MCU_SET_LED_MODE; + break; +#ifdef RALINK_ATE +#endif /* RALINK_ATE */ +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + case LED_WPS_IN_PROCESS: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_IN_PROCESS; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_IN_PROCESS; + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_IN_PROCESS\n", __FUNCTION__)); + } + else + bIgnored = TRUE; + break; + case LED_WPS_ERROR: + if (WscSupportWPSLEDMode(pAd)) + { + /* In the case of LED mode 9, the error LED should be turned on only after WPS walk time expiration. */ + if ((pWscControl->bWPSWalkTimeExpiration == FALSE) && + (LED_MODE(pAd) == WPS_LED_MODE_9)) + { + /* do nothing. */ + } + else + { + LinkStatus = LINK_STATUS_WPS_ERROR; + MCUCmd = MCU_SET_WPS_LED_MODE; + } + + pWscControl->WscLEDMode = LED_WPS_ERROR; + pWscControl->WscLastWarningLEDMode = LED_WPS_ERROR; + + } + else + bIgnored = TRUE; + break; + case LED_WPS_SESSION_OVERLAP_DETECTED: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_SESSION_OVERLAP_DETECTED; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SESSION_OVERLAP_DETECTED; + pWscControl->WscLastWarningLEDMode = LED_WPS_SESSION_OVERLAP_DETECTED; + } + else + bIgnored = TRUE; + break; + case LED_WPS_SUCCESS: + if (WscSupportWPSLEDMode(pAd)) + { + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12) + ) + { + /* In the WPS LED mode 7, 11 and 12, the blue LED would last 300 seconds regardless of the AP's security settings. */ + LinkStatus = LINK_STATUS_WPS_SUCCESS_WITH_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + } + else if (LED_MODE(pAd) == WPS_LED_MODE_8) /* The WPS LED mode 8 */ + { + if (WscAPHasSecuritySetting(pAd, pWscControl)) /* The WPS AP has the security setting. */ + { + LinkStatus = LINK_STATUS_WPS_SUCCESS_WITH_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + } + else /* The WPS AP does not have the secuirty setting. */ + { + LinkStatus = LINK_STATUS_WPS_SUCCESS_WITHOUT_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + } + } + else if (LED_MODE(pAd) == WPS_LED_MODE_9) /* The WPS LED mode 9. */ + { + /* Always turn on the WPS blue LED for 300 seconds. */ + LinkStatus = LINK_STATUS_WPS_BLUE_LED; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SUCCESS (Incorrect LED mode = %d)\n", + __FUNCTION__, LED_MODE(pAd))); + ASSERT(FALSE); + } + } + else + bIgnored = TRUE; + break; + case LED_WPS_TURN_LED_OFF: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_TURN_LED_OFF; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_TURN_LED_OFF; + } + else + bIgnored = TRUE; + break; + case LED_WPS_TURN_ON_BLUE_LED: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_BLUE_LED; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + } + else + bIgnored = TRUE; + break; + case LED_NORMAL_CONNECTION_WITHOUT_SECURITY: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_NORMAL_CONNECTION_WITHOUT_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + } + else + bIgnored = TRUE; + break; + case LED_NORMAL_CONNECTION_WITH_SECURITY: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_NORMAL_CONNECTION_WITH_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + } + else + bIgnored = TRUE; + break; + /*WPS LED Mode 10 */ + case LED_WPS_MODE10_TURN_ON: + if(WscSupportWPSLEDMode10(pAd)) + { + LinkStatus = LINK_STATUS_WPS_MODE10_TURN_ON; + MCUCmd = MCU_SET_WPS_LED_MODE; + } + else + bIgnored = TRUE; + break; + case LED_WPS_MODE10_FLASH: + if(WscSupportWPSLEDMode10(pAd)) + { + LinkStatus = LINK_STATUS_WPS_MODE10_FLASH; + MCUCmd = MCU_SET_WPS_LED_MODE; + } + else + bIgnored = TRUE; + break; + case LED_WPS_MODE10_TURN_OFF: + if(WscSupportWPSLEDMode10(pAd)) + { + LinkStatus = LINK_STATUS_WPS_MODE10_TURN_OFF; + MCUCmd = MCU_SET_WPS_LED_MODE;; + } + else + bIgnored = TRUE; + break; +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + default: + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status 0x%x\n", Status)); + break; + } + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + if (led_cmd != -1) { + /* + LED index is related to the layout of GPIO pins. + Since we are not sure the pairing between LED index and GPIO pins, + here it may be necessary to change the input index to meet the requirement of customers. + */ + if (pAd->CommonCfg.Channel > 14) + andes_led_op(pAd, 2, led_cmd); + else + andes_led_op(pAd, 2, led_cmd); + } + } else +#endif + { + if (MCUCmd) { + AsicSendCommandToMcu(pAd, MCUCmd, 0xff, LedMode, LinkStatus, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s: MCUCmd:0x%x, LED Mode:0x%x, LinkStatus:0x%x\n", __FUNCTION__, MCUCmd, LedMode, LinkStatus)); + } + } + + /* */ + /* Keep LED status for LED SiteSurvey mode. */ + /* After SiteSurvey, we will set the LED mode to previous status. */ + /* */ + if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP) && (bIgnored == FALSE)) + pAd->LedCntl.LedStatus = Status; + +} + + +/* + ======================================================================== + + Routine Description: + Set LED Signal Stregth + + Arguments: + pAd Pointer to our adapter + Dbm Signal Stregth + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Can be run on any IRQL level. + + According to Microsoft Zero Config Wireless Signal Stregth definition as belows. + <= -90 No Signal + <= -81 Very Low + <= -71 Low + <= -67 Good + <= -57 Very Good + > -57 Excellent + ======================================================================== +*/ +VOID RTMPSetSignalLED( + IN PRTMP_ADAPTER pAd, + IN NDIS_802_11_RSSI Dbm) +{ + UCHAR nLed = 0; + + + + + if (pAd->LedCntl.MCULedCntl.field.LedMode == LED_MODE_SIGNAL_STREGTH) + { + if (Dbm <= -90) + nLed = 0; + else if (Dbm <= -81) + nLed = 1; + else if (Dbm <= -71) + nLed = 3; + else if (Dbm <= -67) + nLed = 7; + else if (Dbm <= -57) + nLed = 15; + else + nLed = 31; + + /* */ + /* Update Signal Stregth to firmware if changed. */ + /* */ + if (pAd->LedCntl.LedIndicatorStrength != nLed) + { + AsicSendCommandToMcu(pAd, MCU_SET_LED_GPIO_SIGNAL_CFG, 0xff, nLed, pAd->LedCntl.MCULedCntl.field.Polarity, FALSE); + pAd->LedCntl.LedIndicatorStrength = nLed; + } + } +} + + +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT +/* */ +/* LED indication for normal connection start. */ +/* */ +VOID +LEDConnectionStart( + IN PRTMP_ADAPTER pAd) +{ + /* LED indication. */ + /*if (pAd->StaCfg.WscControl.bWPSSession == FALSE) */ + /*if (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE && pAd->StaCfg.WscControl.bWscTrigger) */ + if (pAd->StaCfg.WscControl.WscConfMode == WSC_DISABLE) + { + if (LED_MODE(pAd) == WPS_LED_MODE_9) /* LED mode 9. */ + { + UCHAR WPSLEDStatus = 0; + + /* The AP uses OPEN-NONE. */ + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeOpen) + && (pAd->StaCfg.wdev.WepStatus == Ndis802_11WEPDisabled)) + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + else /* The AP uses an encryption algorithm. */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); + DBGPRINT(RT_DEBUG_TRACE, ("%s: %d\n", __FUNCTION__, WPSLEDStatus)); + } + } +} + + +/* */ +/* LED indication for normal connection completion. */ +/* */ +VOID +LEDConnectionCompletion( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bSuccess) +{ + /* LED indication. */ + /*if (pAd->StaCfg.WscControl.bWPSSession == FALSE) */ + if (pAd->StaCfg.WscControl.WscConfMode == WSC_DISABLE) + { + if (LED_MODE(pAd) == WPS_LED_MODE_9) /* LED mode 9. */ + { + UCHAR WPSLEDStatus = 0; + + if (bSuccess == TRUE) /* Successful connenction. */ + { + /* The AP uses OPEN-NONE. */ + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeOpen) && (pAd->StaCfg.wdev.WepStatus == Ndis802_11WEPDisabled)) + WPSLEDStatus = LED_NORMAL_CONNECTION_WITHOUT_SECURITY; + else /* The AP uses an encryption algorithm. */ + WPSLEDStatus = LED_NORMAL_CONNECTION_WITH_SECURITY; + } + else /* Connection failure. */ + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + + RTMPSetLED(pAd, WPSLEDStatus); + DBGPRINT(RT_DEBUG_TRACE, ("%s: %d\n", __FUNCTION__, WPSLEDStatus)); + } + } +} +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + + +void RTMPGetLEDSetting(IN RTMP_ADAPTER *pAd) +{ + USHORT Value; + PLED_CONTROL pLedCntl = &pAd->LedCntl; +#ifdef RT65xx + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + // TODO: wait TC6008 EEPROM format + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, Value); + pLedCntl->MCULedCntl.word = (Value >> 8); + RT28xx_EEPROM_READ16(pAd, EEPROM_LEDAG_CONF_OFFSET, Value); + pLedCntl->LedAGCfg= Value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LEDACT_CONF_OFFSET, Value); + pLedCntl->LedACTCfg = Value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED_POLARITY_OFFSET, Value); + pLedCntl->LedPolarity = Value; + } + else +#endif /* RT65xx */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, Value); + pLedCntl->MCULedCntl.word = (Value >> 8); + RT28xx_EEPROM_READ16(pAd, EEPROM_LEDAG_CONF_OFFSET, Value); + pLedCntl->LedAGCfg= Value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LEDACT_CONF_OFFSET, Value); + pLedCntl->LedACTCfg = Value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED_POLARITY_OFFSET, Value); + pLedCntl->LedPolarity = Value; + } +} + + +void RTMPStartLEDMode(IN RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_SWMCU_SUPPORT + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; + pSWMCULedCntl->bWlanLed = TRUE; + RTMPInitTimer(pAd, &pSWMCULedCntl->LedCheckTimer, GET_TIMER_FUNCTION(SWMCULedCtrlMain), pAd, TRUE); + RTMPSetTimer(&pSWMCULedCntl->LedCheckTimer, LED_CHECK_INTERVAL); +#endif /* CONFIG_SWMCU_SUPPORT */ +} + + +void RTMPInitLEDMode(IN RTMP_ADAPTER *pAd) +{ + PLED_CONTROL pLedCntl = &pAd->LedCntl; + + if (pLedCntl->MCULedCntl.word == 0xFF) + { + pLedCntl->MCULedCntl.word = 0x01; + pLedCntl->LedAGCfg = 0x5555; + pLedCntl->LedACTCfg= 0x2221; + +#ifdef RTMP_MAC_PCI + pLedCntl->LedPolarity = 0xA9F8; +#endif /* RTMP_MAC_PCI */ + } + + /* override disabled LED control */ + if (pLedCntl->MCULedCntl.word == 0) + pLedCntl->MCULedCntl.word = 0x01; + + AsicSendCommandToMcu(pAd, MCU_SET_LED_AG_CFG, 0xff, (UCHAR)pLedCntl->LedAGCfg, (UCHAR)(pLedCntl->LedAGCfg >> 8), FALSE); + AsicSendCommandToMcu(pAd, MCU_SET_LED_ACT_CFG, 0xff, (UCHAR)pLedCntl->LedACTCfg, (UCHAR)(pLedCntl->LedACTCfg >> 8), FALSE); + AsicSendCommandToMcu(pAd, MCU_SET_LED_POLARITY, 0xff, (UCHAR)pLedCntl->LedPolarity, (UCHAR)(pLedCntl->LedPolarity >> 8), FALSE); + AsicSendCommandToMcu(pAd, MCU_SET_LED_GPIO_SIGNAL_CFG, 0xff, 0, pLedCntl->MCULedCntl.field.Polarity, FALSE); + + pAd->LedCntl.LedIndicatorStrength = 0xFF; + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, before link up */ + + RTMPStartLEDMode(pAd); +} + + +inline void RTMPExitLEDMode(IN RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_SWMCU_SUPPORT + BOOLEAN Cancelled; + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; +#endif /* CONFIG_SWMCU_SUPPORT */ + + RTMPSetLED(pAd, LED_RADIO_OFF); + +#ifdef CONFIG_SWMCU_SUPPORT + pSWMCULedCntl->bWlanLed = FALSE; + OS_WAIT(500); + RTMPCancelTimer(&pSWMCULedCntl->LedCheckTimer, &Cancelled); +#endif /* CONFIG_SWMCU_SUPPORT */ + return; +} + +#endif /* LED_CONTROL_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_os_util.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_os_util.c new file mode 100644 index 000000000..e3c92042c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rt_os_util.c @@ -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 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 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_init.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_init.c new file mode 100644 index 000000000..ca2d3f965 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_init.c @@ -0,0 +1,4910 @@ +/* + *************************************************************************** + * 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_init.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + +#ifdef OS_ABL_FUNC_SUPPORT +/* Os utility link: printk, scanf */ +RTMP_OS_ABL_OPS RaOsOps, *pRaOsOps = &RaOsOps; +#endif /* OS_ABL_FUNC_SUPPORT */ + +UCHAR NUM_BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; +#ifdef DBG +char *CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128","CKIP152","SMS4"}; +#endif + + + +/* + Use the global variable is not a good solution. + But we can not put it to pAd and use the lock in pAd of RALINK_TIMER_STRUCT; + Or when the structure is cleared, we maybe get NULL for pAd and can not lock. + Maybe we can put pAd in RTMPSetTimer/ RTMPModTimer/ RTMPCancelTimer. +*/ +NDIS_SPIN_LOCK TimerSemLock; + + +/* + ======================================================================== + + Routine Description: + Allocate RTMP_ADAPTER data block and do some initialization + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocAdapterBlock(VOID *handle, VOID **ppAdapter) +{ + RTMP_ADAPTER *pAd = NULL; + NDIS_STATUS Status; + INT index; + UCHAR *pBeaconBuf = NULL; + + +#ifdef OS_ABL_FUNC_SUPPORT + /* must put the function before any print message */ + /* init OS utilities provided from UTIL module */ + RtmpOsOpsInit(&RaOsOps); +#endif /* OS_ABL_FUNC_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n")); + + /* init UTIL module */ + RtmpUtilInit(); + + *ppAdapter = NULL; + + do + { + os_alloc_mem(NULL, (UCHAR **)&pBeaconBuf, MAX_BEACON_SIZE); + if (pBeaconBuf == NULL) + { + Status = NDIS_STATUS_FAILURE; + DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n")); + break; + } + NdisZeroMemory(pBeaconBuf, MAX_BEACON_SIZE); + + /* Allocate RTMP_ADAPTER memory block*/ + Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd, sizeof(RTMP_ADAPTER)); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); + break; + } + else + { + /* init resource list (must be after pAd allocation) */ + initList(&pAd->RscTimerMemList); + initList(&pAd->RscTaskMemList); + initList(&pAd->RscLockMemList); + initList(&pAd->RscTaskletMemList); + initList(&pAd->RscSemMemList); + initList(&pAd->RscAtomicMemList); + + initList(&pAd->RscTimerCreateList); + + pAd->OS_Cookie = handle; +#ifdef WORKQUEUE_BH + ((POS_COOKIE)(handle))->pAd_va = (UINT32)pAd; +#endif /* WORKQUEUE_BH */ + } + pAd->BeaconBuf = pBeaconBuf; + DBGPRINT(RT_DEBUG_OFF, ("\n\n=== pAd = %p, size = %d ===\n\n", pAd, sizeof(RTMP_ADAPTER))); + + if (RtmpOsStatsAlloc(&pAd->iw_stats) == FALSE) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + /* Init spin locks*/ + NdisAllocateSpinLock(pAd, &pAd->MgmtRingLock); +#ifdef RTMP_MAC_PCI + for (index = 0; index < NUM_OF_RX_RING; index++) + NdisAllocateSpinLock(pAd, &pAd->RxRingLock[index]); +#ifdef CONFIG_ANDES_SUPPORT + NdisAllocateSpinLock(pAd, &pAd->CtrlRingLock); + NdisAllocateSpinLock(pAd, &pAd->mcu_atomic); +#endif /* CONFIG_ANDES_SUPPORT */ + NdisAllocateSpinLock(pAd, &pAd->tssi_lock); +#endif /* RTMP_MAC_PCI */ + +#if defined(RT3290) || defined(RLT_MAC) + NdisAllocateSpinLock(pAd, &pAd->WlanEnLock); +#endif /* defined(RT3290) || defined(RLT_MAC) */ + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisAllocateSpinLock(pAd, &pAd->TxSwQueueLock[index]); + NdisAllocateSpinLock(pAd, &pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + +#ifdef RESOURCE_PRE_ALLOC + /* + move this function from rt28xx_init() to here. now this function only allocate memory and + leave the initialization job to RTMPInitTxRxRingMemory() which called in rt28xx_init(). + */ + Status = RTMPAllocTxRxRingMemory(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - TxRxRing\n")); + break; + } +#endif /* RESOURCE_PRE_ALLOC */ + + NdisAllocateSpinLock(pAd, &pAd->irq_lock); + +#ifdef RTMP_MAC_PCI + NdisAllocateSpinLock(pAd, &pAd->LockInterrupt); +#endif /* RTMP_MAC_PCI */ + + NdisAllocateSpinLock(pAd, &TimerSemLock); + +#ifdef SPECIFIC_BCN_BUF_SUPPORT +#ifdef RTMP_MAC_PCI + NdisAllocateSpinLock(pAd, &pAd->ShrMemLock); +#endif /* RTMP_MAC_PCI */ +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + +#ifdef RALINK_ATE +#endif /* RALINK_ATE */ + + *ppAdapter = (VOID *)pAd; + } while (FALSE); + + if (Status != NDIS_STATUS_SUCCESS) + { + if (pBeaconBuf) + os_free_mem(NULL, pBeaconBuf); + + if (pAd != NULL) + { + if (pAd->iw_stats != NULL) + os_free_mem(NULL, pAd->iw_stats); + + os_free_mem(NULL, pAd); + } + + return Status; + } + + /* Init ProbeRespIE Table */ + for (index = 0; index < MAX_LEN_OF_BSS_TABLE; index++) + { + if (os_alloc_mem(pAd,&pAd->ProbeRespIE[index].pIe, MAX_VIE_LEN) == NDIS_STATUS_SUCCESS) + RTMPZeroMemory(pAd->ProbeRespIE[index].pIe, MAX_VIE_LEN); + else + pAd->ProbeRespIE[index].pIe = NULL; + } + + DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status)); + return Status; +} + + +static UINT8 NICGetBandSupported(RTMP_ADAPTER *pAd) +{ + if (BOARD_IS_5G_ONLY(pAd)) + { + return RFIC_5GHZ; + } + else if (BOARD_IS_2G_ONLY(pAd)) + { + return RFIC_24GHZ; + } + else if (RFIC_IS_5G_BAND(pAd)) + { + return RFIC_DUAL_BAND; + } + else + return RFIC_24GHZ; +} + + +BOOLEAN RTMPCheckPhyMode(RTMP_ADAPTER *pAd, UINT8 band_cap, UCHAR *pPhyMode) +{ + BOOLEAN RetVal = TRUE; + + if (band_cap == RFIC_24GHZ) + { + if (!WMODE_2G_ONLY(*pPhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Warning! The board type is 2.4G only!\n", + __FUNCTION__)); + RetVal = FALSE; + } + } + else if (band_cap == RFIC_5GHZ) + { + if (!WMODE_5G_ONLY(*pPhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Warning! The board type is 5G only!\n", + __FUNCTION__)); + RetVal = FALSE; + } + } + else if (band_cap == RFIC_DUAL_BAND) + { + RetVal = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Unknown supported band (%u), assume dual band used.\n", + __FUNCTION__, band_cap)); + + RetVal = TRUE; + } + + if (RetVal == FALSE) + { +#ifdef DOT11_N_SUPPORT + if (band_cap == RFIC_5GHZ) /*5G ony: change to A/N mode */ + *pPhyMode = PHY_11AN_MIXED; + else /* 2.4G only or Unknown supported band: change to B/G/N mode */ + *pPhyMode = PHY_11BGN_MIXED; +#else + if (band_cap == RFIC_5GHZ) /*5G ony: change to A mode */ + *pPhyMode = PHY_11A; + else /* 2.4G only or Unknown supported band: change to B/G mode */ + *pPhyMode = PHY_11BG_MIXED; +#endif /* !DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Changed PhyMode to %u\n", + __FUNCTION__, *pPhyMode)); + } + + return RetVal; + +} + + +/* + ======================================================================== + + Routine Description: + Read initial parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICReadEEPROMParameters(RTMP_ADAPTER *pAd, PSTRING mac_addr) +{ + USHORT i, value, value2; + EEPROM_TX_PWR_STRUC Power; + EEPROM_VERSION_STRUC Version; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; +#ifdef READ_MAC_FROM_EEPROM + USHORT Addr01,Addr23,Addr45 ; +#endif + MAC_DW0_STRUC csr2; + MAC_DW1_STRUC csr3; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n")); + + if (pAd->chipOps.eeinit) + { +#ifndef MULTIPLE_CARD_SUPPORT + /* If we are run in Multicard mode, the eeinit shall execute in RTMP_CardInfoRead() */ + pAd->chipOps.eeinit(pAd); +#endif /* MULTIPLE_CARD_SUPPORT */ + } + +#ifdef READ_MAC_FROM_EEPROM + /* Read MAC setting from EEPROM and record as permanent MAC address */ + DBGPRINT(RT_DEBUG_ERROR, ("Initialize MAC Address from E2PROM \n")); + + RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); + + pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff); + pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8); + pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff); + pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8); + pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff); + pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8); + + /*more conveninet to test mbssid, so ap's bssid &0xf1*/ + if (pAd->PermanentAddress[0] == 0xff) + pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8; + + DBGPRINT(RT_DEBUG_ERROR, ("E2PROM MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->PermanentAddress))); + + /* Assign the actually working MAC Address */ + if (pAd->bLocalAdminMAC) + { + DBGPRINT(RT_DEBUG_TRACE, ("Use the MAC address what is assigned from Configuration file(.dat). \n")); +#if defined(BB_SOC)&&!defined(NEW_MBSSID_MODE) + BBUPrepareMAC(pAd, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->PermanentAddress, pAd->CurrentAddress); + printk("now bb MainSsid mac %02x:%02x:%02x:%02x:%02x:%02x\n",PRINT_MAC(pAd->CurrentAddress)); +#endif + } + else +#endif + if (mac_addr && strlen((PSTRING)mac_addr) == 17 && + (strcmp(mac_addr, "00:00:00:00:00:00") != 0)) + { + INT j; + PSTRING macptr; + + macptr = (PSTRING) mac_addr; + for (j=0; jCurrentAddress[j], 1); + macptr=macptr+3; + } + + DBGPRINT(RT_DEBUG_ERROR, ("Use the MAC address what is assigned from Moudle Parameter. \n")); + } +#ifdef READ_MAC_FROM_EEPROM + else + { + COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress); + DBGPRINT(RT_DEBUG_ERROR, ("Use the MAC address what is assigned from EEPROM. \n")); + } +#endif + +#if !defined(NEW_MBSSID_MODE) +#if defined(MBSS_SUPPORT) + /* Test MAC[5] for 4 MAC support */ + if ((pAd->CurrentAddress[5] % 4) != 0) + { + pAd->CurrentAddress[5] &= 0xfc; // Max 4 MBSSID + } +#elif defined(APCLI_SUPPORT) + /* Test MAC[5] for 2 MAC support */ + if ((pAd->CurrentAddress[5] % 2) != 0) + { + pAd->CurrentAddress[5] &= 0xfe; // Max 2 MBSSID + } +#endif +#endif + + /* Set the current MAC to ASIC */ + csr2.field.Byte0 = pAd->CurrentAddress[0]; + csr2.field.Byte1 = pAd->CurrentAddress[1]; + csr2.field.Byte2 = pAd->CurrentAddress[2]; + csr2.field.Byte3 = pAd->CurrentAddress[3]; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); + csr3.word = 0; + csr3.field.Byte4 = pAd->CurrentAddress[4]; + { + csr3.field.Byte5 = pAd->CurrentAddress[5]; + csr3.field.U2MeMask = 0xff; + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW0, csr2.word); + csr3.word &= 0xff00ffff; + csr3.word |= 0x00410000; // HW test code + RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW1, csr3.word); +#endif /* HDR_TRANS_SUPPORT */ + + DBGPRINT_RAW(RT_DEBUG_ERROR,("Current MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->CurrentAddress))); + + /* if not return early. cause fail at emulation.*/ + /* Init the channel number for TX channel power*/ +#ifdef RT8592 + if (IS_RT8592(pAd)) + RT85592_ReadChannelPwr(pAd); + else +#endif /* RT8592 */ +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + mt76x2_read_chl_pwr(pAd); + else +#endif + RTMPReadChannelPwr(pAd); + + /* if E2PROM version mismatch with driver's expectation, then skip*/ + /* all subsequent E2RPOM retieval and set a system error bit to notify GUI*/ + RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); + pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256; + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber)); + + /* Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd */ + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); + pAd->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET] = value; + + /* EEPROM offset 0x36 - NIC Configuration 1 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] = value; + NicConfig2.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET]; + +#if defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(MT76x2) + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC3_OFFSET, value); +#ifdef RT8592 + if (value == 0xffff) + value = 0; +#endif /* RT8592 */ + + pAd->EEPROMDefaultValue[EEPROM_NIC_CFG3_OFFSET] = value; + pAd->NicConfig3.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG3_OFFSET]; +#endif /* defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(MT76x2) */ + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_COUNTRY_REGION, value); /* Country Region*/ + pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] = value; + DBGPRINT(RT_DEBUG_OFF, ("Country Region from e2p = %x\n", value)); + } + + for(i = 0; i < 8; i++) + { +#if defined(RT65xx) || defined(MT7601) /* MT7650 EEPROM doesn't have those BBP setting @20121001 */ + if (IS_RT65XX(pAd) || IS_MT7601(pAd)) + break; +#endif /* defined(RT65xx) || defined(MT7601)*/ + + RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value); + pAd->EEPROMDefaultValue[i+EEPROM_BBP_ARRAY_OFFSET] = value; + } + + /* We have to parse NIC configuration 0 at here.*/ + /* If TSSI did not have preloaded value, it should reset the TxAutoAgc to false*/ + /* Therefore, we have to read TxAutoAgc control beforehand.*/ + /* Read Tx AGC control bit*/ + Antenna.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET]; + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + mt76x2_antenna_sel_ctl(pAd); +#endif /* MT76x2 */ + +#ifdef RT8592 + if (IS_RT8592(pAd)) { + DBGPRINT(RT_DEBUG_OFF, ("RT85592: EEPROM(NicConfig1=0x%04x) - Antenna.RfIcType=%d, TxPath=%d, RxPath=%d\n", + Antenna.word, Antenna.field.RfIcType, Antenna.field.TxPath, Antenna.field.RxPath)); + // TODO: fix me!! + Antenna.word = 0; + Antenna.field.BoardType = 0; + Antenna.field.RfIcType = 0xf; + Antenna.field.TxPath = 2; + Antenna.field.RxPath = 2; + } +#endif /* RT8592 */ + + + + // TODO: shiang, why we only check oxff00?? + if (((Antenna.word & 0xFF00) == 0xFF00) || IS_MT76x2(pAd)) +/* if (Antenna.word == 0xFFFF)*/ + RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(pAd, &Antenna); + + /* Choose the desired Tx&Rx stream.*/ + if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) + pAd->CommonCfg.TxStream = Antenna.field.TxPath; + + if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) + { + pAd->CommonCfg.RxStream = Antenna.field.RxPath; + + if ((pAd->MACVersion != RALINK_3883_VERSION) && + (pAd->MACVersion != RALINK_2883_VERSION) && + (pAd->CommonCfg.RxStream > 2)) + { + /* only 2 Rx streams for RT2860 series*/ + pAd->CommonCfg.RxStream = 2; + } + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s(): AfterAdjust, RxPath = %d, TxPath = %d\n", + __FUNCTION__, Antenna.field.RxPath, Antenna.field.TxPath)); + +#ifdef WSC_INCLUDED + /* WSC hardware push button function 0811 */ + if ((pAd->MACVersion == 0x28600100) || (pAd->MACVersion == 0x28700100)) + WSC_HDR_BTN_MR_HDR_SUPPORT_SET(pAd, NicConfig2.field.EnableWPSPBC); +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (NicConfig2.word == 0xffff) + NicConfig2.word = 0; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((NicConfig2.word & 0x00ff) == 0xff) + NicConfig2.word &= 0xff00; + + if ((NicConfig2.word >> 8) == 0xff) + NicConfig2.word &= 0x00ff; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (NicConfig2.field.DynamicTxAgcControl == 1) { + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; +#ifdef RT8592 + if (IS_RT8592(pAd)) + { + pAd->chipCap.bTempCompTxALC = TRUE; + pAd->chipCap.rx_temp_comp = pAd->NicConfig3.field.rx_temp_comp; + } +#endif /* RT8592 */ + } + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + + /* Save value for future using */ + pAd->NicConfig2.word = NicConfig2.word; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d, RfIcType = %d\n", + Antenna.field.RxPath, Antenna.field.TxPath, Antenna.field.RfIcType)); + + /* Save the antenna for future use*/ + pAd->Antenna.word = Antenna.word; + + /* Set the RfICType here, then we can initialize RFIC related operation callbacks*/ + pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath; + pAd->RfIcType = (UCHAR) Antenna.field.RfIcType; + +#ifdef RT8592 + // TODO: shiang-6590, currently we don't have eeprom value, so directly force to set it as 0xff + if (IS_RT8592(pAd)) { + pAd->Mlme.RealRxPath = 2; + pAd->RfIcType = RFIC_UNKNOWN; + } +#endif /* RT8592 */ + + +#ifdef MT76x2 + if (IS_MT7662(pAd)) + pAd->RfIcType = RFIC_7662; + + if (IS_MT7612(pAd)) + pAd->RfIcType = RFIC_7612; + + if (IS_MT7602(pAd)) + pAd->RfIcType = RFIC_7602; +#endif + + pAd->phy_ctrl.rf_band_cap = NICGetBandSupported(pAd); + + /* check if the chip supports 5G band */ + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + if (!RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s():Err! chip not support 5G band %d!\n", + __FUNCTION__, pAd->RfIcType)); +#ifdef DOT11_N_SUPPORT + /* change to bgn mode */ + Set_WirelessMode_Proc(pAd, "9"); +#else + /* change to bg mode */ + Set_WirelessMode_Proc(pAd, "0"); +#endif /* DOT11_N_SUPPORT */ + pAd->phy_ctrl.rf_band_cap = RFIC_24GHZ; + } + pAd->phy_ctrl.rf_band_cap = RFIC_24GHZ | RFIC_5GHZ; + } + else + { + pAd->phy_ctrl.rf_band_cap = RFIC_24GHZ; + } + + + RTMP_NET_DEV_NICKNAME_INIT(pAd); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + { + mt76x2_read_temp_info_from_eeprom(pAd); +#ifdef RTMP_TEMPERATURE_TX_ALC + mt76x2_read_tx_alc_info_from_eeprom(pAd); +#endif /* RTMP_TEMPERATURE_TX_ALC */ +#ifdef SINGLE_SKU_V2 + mt76x2_read_single_sku_info_from_eeprom(pAd); +#endif /* SINGLE_SKU_V2 */ + } +#endif /* MT76x2 */ + + /* Read TSSI reference and TSSI boundary for temperature compensation. This is ugly */ + /* 0. 11b/g*/ +#ifdef RT65xx + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + ; + } + else +#endif /* RT65xx */ + { + /* these are tempature reference value (0x00 ~ 0xFE) + ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) + + TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND1, Power.word); + pAd->TssiMinusBoundaryG[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND2, Power.word); + pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND3, Power.word); + pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ + pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND4, Power.word); + pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND5, Power.word); + pAd->TssiPlusBoundaryG[4] = Power.field.Byte0; + pAd->TxAgcStepG = Power.field.Byte1; + pAd->TxAgcCompensateG = 0; + pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; + pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; + + /* Disable TxAgc if the based value is not right*/ + if (pAd->TssiRefG == 0xff) + pAd->bAutoTxAgcG = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TxAgcStepG, pAd->bAutoTxAgcG)); + } + + /* 1. 11a*/ +#ifdef RT65xx + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + ; + } + else +#endif /* RT65xx */ + { + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND1, Power.word); + pAd->TssiMinusBoundaryA[0][4] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[0][3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND2, Power.word); + pAd->TssiMinusBoundaryA[0][2] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[0][1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND3, Power.word); + pAd->TssiRefA = Power.field.Byte0; + pAd->TssiPlusBoundaryA[0][1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND4, Power.word); + pAd->TssiPlusBoundaryA[0][2] = Power.field.Byte0; + pAd->TssiPlusBoundaryA[0][3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND5, Power.word); + pAd->TssiPlusBoundaryA[0][4] = Power.field.Byte0; + pAd->TxAgcStepA = Power.field.Byte1; + pAd->TxAgcCompensateA = 0; + pAd->TssiMinusBoundaryA[0][0] = pAd->TssiRefA; + pAd->TssiPlusBoundaryA[0][0] = pAd->TssiRefA; + + /* Disable TxAgc if the based value is not right*/ + if (pAd->TssiRefA == 0xff) + pAd->bAutoTxAgcA = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryA[0][4], pAd->TssiMinusBoundaryA[0][3], pAd->TssiMinusBoundaryA[0][2], pAd->TssiMinusBoundaryA[0][1], + pAd->TssiRefA, + pAd->TssiPlusBoundaryA[0][1], pAd->TssiPlusBoundaryA[0][2], pAd->TssiPlusBoundaryA[0][3], pAd->TssiPlusBoundaryA[0][4], + pAd->TxAgcStepA, pAd->bAutoTxAgcA)); + } + pAd->BbpRssiToDbmDelta = 0x0; + + /* Read frequency offset setting for RF*/ + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + pAd->RfFreqOffset = (ULONG)(value & 0x00FF); + } + else +#endif /* RT6352 */ + { + if ((value & 0x00FF) != 0x00FF) + pAd->RfFreqOffset = (ULONG) (value & 0x00FF); + else + pAd->RfFreqOffset = 0; + } + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { + if (pAd->RfFreqDelta & 0x10) + { + pAd->RfFreqOffset = (pAd->RfFreqOffset >= pAd->RfFreqDelta)? (pAd->RfFreqOffset - (pAd->RfFreqDelta & 0xf)) : 0; + } + else + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + pAd->RfFreqOffset = ((pAd->RfFreqOffset + pAd->RfFreqDelta) < 0xFF)? (pAd->RfFreqOffset + (pAd->RfFreqDelta & 0xf)) : 0xFF; + else +#endif /* RT6352 */ + pAd->RfFreqOffset = ((pAd->RfFreqOffset + pAd->RfFreqDelta) < 0x40)? (pAd->RfFreqOffset + (pAd->RfFreqDelta & 0xf)) : 0x3f; + } + } +#endif /* RTMP_RBUS_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%x \n", pAd->RfFreqOffset)); + +#if !defined(EEPROM_COUNTRY_UNLOCK) + /*CountryRegion byte offset (38h)*/ + { + value = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] >> 8; /* 2.4G band*/ + value2 = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] & 0x00FF; /* 5G band*/ + } + + if ((value <= REGION_MAXIMUM_BG_BAND) || (value == REGION_31_BG_BAND) || (value == REGION_32_BG_BAND) || (value == REGION_33_BG_BAND) ) + pAd->CommonCfg.CountryRegion = ((UCHAR) value) | EEPROM_IS_PROGRAMMED; + + if (value2 <= REGION_MAXIMUM_A_BAND) + pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | EEPROM_IS_PROGRAMMED; +#endif + + /* Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.*/ + /* The valid value are (-10 ~ 10) */ + /* */ +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); + + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + pAd->BGRssiOffset[0] = 0; + } else { + if (value & RSSI0_OFFSET_G_BAND_EN) { + if (value & RSSI0_OFFSET_G_BAND_SIGN) + pAd->BGRssiOffset[0] = (value & RSSI0_OFFSET_G_BAND_MASK); + else + pAd->BGRssiOffset[0] = -(value & RSSI0_OFFSET_G_BAND_MASK); + } else { + pAd->BGRssiOffset[0] = 0; + } + } + + if (((value & 0xff00) == 0x0000) || ((value & 0xff00) == 0xff00)) { + pAd->BGRssiOffset[1] = 0; + } else { + if (value & RSSI1_OFFSET_G_BAND_EN) { + if (value & RSSI1_OFFSET_G_BAND_SIGN) + pAd->BGRssiOffset[1] = ((value & RSSI1_OFFSET_G_BAND_MASK) >> 8); + else + pAd->BGRssiOffset[1] = -((value & RSSI1_OFFSET_G_BAND_MASK) >> 8); + } else { + pAd->BGRssiOffset[1] = 0; + } + } + } + else +#endif /* MT76x2 */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); + pAd->BGRssiOffset[0] = value & 0x00ff; + pAd->BGRssiOffset[1] = (value >> 8); + } + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value); + { +/* if (IS_RT2860(pAd)) RT2860 supports 3 Rx and the 2.4 GHz RSSI #2 offset is in the EEPROM 0x48*/ + pAd->BGRssiOffset[2] = value & 0x00ff; + pAd->ALNAGain1 = (value >> 8); + } + } + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); + pAd->BLNAGain = value & 0x00ff; + /* External LNA gain for 5GHz Band(CH36~CH64) */ + pAd->ALNAGain0 = (value >> 8); + } + + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); + + if (((value & 0xff) == 0x00) || ((value & 0xff) == 0xff)) { + pAd->ARssiOffset[0] = 0; + } else { + if (value & RSSI0_OFFSET_A_BANE_EN) { + if (value & RSSI0_OFFSET_A_BAND_SIGN) + pAd->ARssiOffset[0] = (value & RSSI0_OFFSET_A_BAND_MASK); + else + pAd->ARssiOffset[0] = -(value & RSSI0_OFFSET_A_BAND_MASK); + } else { + pAd->ARssiOffset[0] = 0; + } + } + + if (((value & 0xff00) == 0x0000) || ((value & 0xff00) == 0xff00)) { + pAd->ARssiOffset[1] = 0; + } else { + if (value & RSSI1_OFFSET_A_BAND_EN) { + if (value & RSSI1_OFFSET_A_BAND_SIGN) + pAd->ARssiOffset[1] = ((value & RSSI1_OFFSET_A_BAND_MASK) >> 8); + else + pAd->ARssiOffset[1] = -((value & RSSI1_OFFSET_A_BAND_MASK) >> 8); + } else { + pAd->ARssiOffset[1] = 0; + } + } + } + else +#endif /* MT76x2 */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); + pAd->ARssiOffset[0] = value & 0x00ff; + pAd->ARssiOffset[1] = (value >> 8); + } + { + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); + { + pAd->ARssiOffset[2] = value & 0x00ff; + pAd->ALNAGain2 = (value >> 8); + } + } + + + if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) + pAd->ALNAGain1 = pAd->ALNAGain0; + if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) + pAd->ALNAGain2 = pAd->ALNAGain0; + + DBGPRINT(RT_DEBUG_TRACE, ("ALNAGain0 = %d, ALNAGain1 = %d, ALNAGain2 = %d\n", + pAd->ALNAGain0, pAd->ALNAGain1, pAd->ALNAGain2)); + + /* Validate 11a/b/g RSSI 0/1/2 offset.*/ + for (i =0 ; i < 3; i++) + { + if ((pAd->BGRssiOffset[i] < -10) || (pAd->BGRssiOffset[i] > 10)) + pAd->BGRssiOffset[i] = 0; + + if ((pAd->ARssiOffset[i] < -10) || (pAd->ARssiOffset[i] > 10)) + pAd->ARssiOffset[i] = 0; + } + + /* + Get TX mixer gain setting + 0xff are invalid value + Note: + RT30xx default value is 0x00 and will program to RF_R17 + only when this value is not zero + RT359x default value is 0x02 + */ + if (IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3593(pAd) + || IS_RT5390(pAd) || IS_RT5392(pAd) || IS_RT5592(pAd) + || IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd)) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXMIXER_GAIN_2_4G, value); + pAd->TxMixerGain24G = 0; + value &= 0x00ff; + if (value != 0xff) + { + value &= 0x07; + pAd->TxMixerGain24G = (UCHAR)value; + } + + } + + +#ifdef LED_CONTROL_SUPPORT + /* LED Setting */ + RTMPGetLEDSetting(pAd); +#endif /* LED_CONTROL_SUPPORT */ + + RTMPReadTxPwrPerRate(pAd); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + mt76x2_get_external_lna_gain(pAd); +#endif /* MT76x2 */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* init base power by e2p target power */ + RT28xx_EEPROM_READ16(pAd, 0xD0, pAd->E2p_D0_Value); + DBGPRINT(RT_DEBUG_ERROR, ("E2PROM: D0 target power=0x%x \n", pAd->E2p_D0_Value)); + +#ifdef RTMP_TEMPERATURE_CALIBRATION + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC3_OFFSET, value); + if (value & 0x0800) + { + pAd->bRef25CVaild = FALSE; + } + else + { + pAd->bRef25CVaild = TRUE; + pAd->TemperatureRef25C = (pAd->E2p_D0_Value >> 8) & 0xFF; + DBGPRINT(RT_DEBUG_ERROR, (" pAd->TemperatureRef25C = 0x%x\n", pAd->TemperatureRef25C)); + } +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + + /* Get 40 MW Power Delta */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value); + pAd->BW_Power_Delta = 0; + if ((value & 0xff) != 0xff) + { + if ((value & 0x80)) + pAd->BW_Power_Delta = (value &0xf); + + if ((value & 0x40) == 0) + pAd->BW_Power_Delta = -1* pAd->BW_Power_Delta; + } + DBGPRINT(RT_DEBUG_ERROR, ("E2PROM: 40 MW Power Delta= %d \n", pAd->BW_Power_Delta)); + +#ifdef RT6352_EP_SUPPORT + if ((NicConfig2.word != 0) && (pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] & 0xC000)) + pAd->bExtPA = TRUE; + else +#endif /* RT6352_EP_SUPPORT */ + pAd->bExtPA = FALSE; + } +#endif /* RT6352 */ + +#ifdef SINGLE_SKU + { + RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr); + } + + /* + Some dongle has old EEPROM value, use ModuleTxpower for saving correct value fo DefineMaxTxPwr. + ModuleTxpower will override DefineMaxTxPwr (value from EEPROM) if ModuleTxpower is not zero. + */ + if (pAd->CommonCfg.ModuleTxpower > 0) + pAd->CommonCfg.DefineMaxTxPwr = pAd->CommonCfg.ModuleTxpower; + + DBGPRINT(RT_DEBUG_TRACE, ("TX Power set for SINGLE SKU MODE is : 0x%04x \n", pAd->CommonCfg.DefineMaxTxPwr)); + + pAd->CommonCfg.bSKUMode = FALSE; + if ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF) <= 0x50) + { + if (IS_RT3883(pAd)) + pAd->CommonCfg.bSKUMode = TRUE; + else if ((pAd->CommonCfg.AntGain > 0) && (pAd->CommonCfg.BandedgeDelta >= 0)) + pAd->CommonCfg.bSKUMode = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Single SKU Mode is %s\n", + pAd->CommonCfg.bSKUMode ? "Enable" : "Disable")); +#endif /* SINGLE_SKU */ + +#ifdef SINGLE_SKU_V2 +#ifdef RT6352 + if (IS_RT6352(pAd)) + RT6352_InitSkuRateDiffTable(pAd); +#endif /* RT6352 */ +#endif /* SINGLE_SKU_V2 */ + +#ifdef RTMP_EFUSE_SUPPORT + RtmpEfuseSupportCheck(pAd); +#endif /* RTMP_EFUSE_SUPPORT */ + +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT65xx + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + { + ; // TODO: wait TC6008 EEPROM format + } + else +#endif /* RT65xx */ + { + /* + Internal Tx ALC support is starting from RT3370 / RT3390, which combine PA / LNA in single chip. + The old chipset don't have this, add new feature flag RTMP_INTERNAL_TX_ALC. + */ + value = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET]; + if (value == 0xFFFF) /*EEPROM is empty*/ + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + else if (value & 1<<13) + pAd->TxPowerCtrl.bInternalTxALC = TRUE; + else + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TXALC> bInternalTxALC = %d\n", pAd->TxPowerCtrl.bInternalTxALC)); +#endif /* RTMP_INTERNAL_TX_ALC */ + + + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->Antenna.field.BoardType = %d, IS_MINI_CARD(pAd) = %d, IS_RT5390U(pAd) = %d\n", + __FUNCTION__, + pAd->Antenna.field.BoardType, + IS_MINI_CARD(pAd), + IS_RT5390U(pAd))); + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n")); +} + + +/* + ======================================================================== + + Routine Description: + Set default value from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICInitAsicFromEEPROM(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_STA_SUPPORT + UINT32 data = 0; +#endif /* CONFIG_STA_SUPPORT */ +#if defined(RT30xx) || defined(RTMP_BBP) + USHORT i; +#endif /* defined(RT30xx) || defined(RTMP_BBP) */ +#ifdef RALINK_ATE + USHORT value; +#endif /* RALINK_ATE */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); +#ifdef RTMP_BBP + // TODO: shiang, fix this for some chips which has side-effect (ex: 5572/3572, etc.) + if (pAd->chipCap.hif_type == HIF_RTMP) + { + for (i = EEPROM_BBP_ARRAY_OFFSET; i < NUM_EEPROM_BBP_PARMS; i++) + { + UCHAR BbpRegIdx, BbpValue; + + if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0)) + { + BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8); + BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue); + } + } + } +#endif /* RTMP_BBP */ + + NicConfig2.word = pAd->NicConfig2.word; + + /* finally set primary ant */ + AntCfgInit(pAd); + + RTMP_CHIP_ASIC_INIT_TEMPERATURE_COMPENSATION(pAd); + +#ifdef RTMP_RF_RW_SUPPORT + /*Init RFRegisters after read RFIC type from EEPROM*/ + InitRFRegisters(pAd); +#endif /* RTMP_RF_RW_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Read Hardware controlled Radio state enable bit*/ + if (NicConfig2.field.HardwareRadioControl == 1) + { + BOOLEAN radioOff = FALSE; + pAd->StaCfg.bHardwareRadio = TRUE; + + { + /* Read GPIO pin2 as Hardware controlled radio state*/ + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); + if ((data & 0x04) == 0) + radioOff = TRUE; + } + + if (radioOff) + { + pAd->StaCfg.bHwRadio = FALSE; + pAd->StaCfg.bRadio = FALSE; + /* RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + } + } + else + pAd->StaCfg.bHardwareRadio = FALSE; + +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, pAd->StaCfg.bRadio == FALSE ? LED_RADIO_OFF : LED_RADIO_ON); +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RTMP_MAC_PCI + if (pAd->StaCfg.bRadio == TRUE) + { + AsicSendCmdToMcuAndWait(pAd, 0x30, PowerRadioOffCID, 0xff, 0x02, FALSE); + + /*AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02, FALSE);*/ + AsicSendCmdToMcuAndWait(pAd, 0x31, PowerWakeCID, 0x00, 0x00, FALSE); + } +#endif /* RTMP_MAC_PCI */ + } +#ifdef PCIE_PS_SUPPORT +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WIN_NDIS + /* Turn off patching for cardbus controller */ + /* + if (NicConfig2.field.CardbusAcceleration == 1) + pAd->bTest1 = TRUE; + */ +#endif /* WIN_NDIS */ + + if (NicConfig2.field.DynamicTxAgcControl == 1) + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + +#ifdef RTMP_INTERNAL_TX_ALC + /* + Internal Tx ALC support is starting from RT3370 / RT3390, which combine PA / LNA in single chip. + The old chipset don't have this, add new feature flag RTMP_INTERNAL_TX_ALC. + */ + + /* Internal Tx ALC */ + if (((NicConfig2.field.DynamicTxAgcControl == 1) && + (NicConfig2.field.bInternalTxALC == 1)) || + ((!IS_RT3390(pAd)) && (!IS_RT3350(pAd)) && + (!IS_RT3352(pAd)) && (!IS_RT5350(pAd)) && + (!IS_RT5390(pAd)) && (!IS_RT3290(pAd)) && (!IS_RT6352(pAd)) && (!IS_MT7601(pAd)))) + { + /* + If both DynamicTxAgcControl and bInternalTxALC are enabled, + it is a wrong configuration. + If the chipset does not support Internal TX ALC, we shall disable it. + */ + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + } + else + { + if (NicConfig2.field.bInternalTxALC == 1) + pAd->TxPowerCtrl.bInternalTxALC = TRUE; + else + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + } + + + /* Old 5390 NIC always disables the internal ALC */ + if ((pAd->MACVersion == 0x53900501) +#ifdef RT6352 + && !IS_RBUS_INF(pAd) +#endif /* RT6352 */ + ) + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->TxPowerCtrl.bInternalTxALC = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.bInternalTxALC)); +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RALINK_ATE + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_GAIN_AND_ATTENUATION, value); + value = (value & 0x00FF); + + if (IS_RT5390(pAd)) + pAd->TssiGain = 0x02; /* RT5390 uses 2 as TSSI gain/attenuation default value */ + else + pAd->TssiGain = 0x03; /* RT5392 uses 3 as TSSI gain/attenuation default value */ + + if ((value != 0x00) && (value != 0xFF)) + pAd->TssiGain = (UCHAR) (value & 0x000F); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: EEPROM_TSSI_GAIN_AND_ATTENUATION = 0x%X, pAd->TssiGain=0x%x\n", + __FUNCTION__, + value, + pAd->TssiGain)); +#endif /* RALINK_ATE */ + + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + INT dac = 0; + /* Handle the difference when 1T*/ + { + if(pAd->Antenna.field.TxPath == 1) + dac = 0; + else + dac = 2; + } + bbp_set_txdac(pAd, dac); + DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", + pAd->StaCfg.bHardwareRadio, pAd->StaCfg.bHardwareRadio)); + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_EEPROM_ASIC_INIT(pAd); + + + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d\n", + pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType)); + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n")); +} + + +/* + ======================================================================== + + Routine Description: + Initialize NIC hardware + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAdapter(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UINT rty_cnt = 0; +#ifdef RTMP_MAC_PCI + WPDMA_GLO_CFG_STRUC GloCfg; +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ +retry: + + if (AsicWaitPDMAIdle(pAd, 100, 1000) != TRUE) { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + } + +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); + + /* pbf hardware reset, asic simulation sequence put this ahead before loading firmware */ +#ifdef MT76x2 + // TODO: shiang-usw, check why MT762x don't need to do this! + if (!IS_MT76x2(pAd)) +#endif /* MT76x2 */ + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0xffffffff /*0x1003f*/); + +#ifdef RT8592 + // TODO: shiang-single driver, sync with windows, does 765x need this?? + if (!IS_RT65XX(pAd)) +#endif /* RT8592 */ + { + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); + } +#endif /* RTMP_MAC_PCI */ + +#ifdef RTMP_MAC_PCI + AsicInitTxRxRing(pAd); +#endif + + /* Initialze ASIC for TX & Rx operation*/ + if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + + if (pAd->chipOps.loadFirmware) + { + if (rty_cnt++ == 0) + { + NICLoadFirmware(pAd); + goto retry; + } + } + return NDIS_STATUS_FAILURE; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n")); + return Status; +} + +/* + ======================================================================== + + Routine Description: + Initialize ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAsic(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + ULONG Index = 0; + UINT32 mac_val = 0; + USHORT KeyIdx; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); + + /*@!Release + For MT76x0 series, + PWR_PIN_CFG[2:0]: obsolete, no function + Don't need to change PWR_PIN_CFG here. + */ +#ifdef RTMP_MAC_PCI +#ifdef RT8592 + // TODO:shiang-6590, why we don't need to change PWR_PIN_CFG as 1 here? Windows did it!! + if (IS_RT8592(pAd)) + mac_val = 0x1; + else +#endif /* RT8592 */ +#if defined(MT76x0) || defined(MT76x2) || defined(MT7601) + if (IS_MT76x0(pAd) || IS_MT76x2(pAd) || IS_MT7601(pAd)) { + /* + PWR_PIN_CFG[2:0]: obsolete, no function + Don't need to change PWR_PIN_CFG here. + */ + mac_val = 0x0; + } + else +#endif /* defined(MT76x0) || defined(MT76x2) || defined(MT7601) */ + mac_val = 0x3; /* To fix driver disable/enable hang issue when radio off*/ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, mac_val); + + if (bHardReset == TRUE) + { + mac_val = 0x3; +#ifdef RT6352 + if (IS_RT6352(pAd)) + mac_val = 0x1; +#endif /* RT6352 */ + } + else + mac_val = 0x1; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, mac_val); + +#ifdef RT6352 + if (IS_RT6352(pAd) && (bHardReset == TRUE)) + { + UCHAR BbpReg; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpReg); + BbpReg |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpReg); + RtmpOsMsDelay(1); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpReg); + BbpReg &= (~0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpReg); + } +#endif /* RT6352 */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); +#endif /* RTMP_MAC_PCI */ + +#ifdef RTMP_PCI_SUPPORT + pAd->CommonCfg.bPCIeBus = FALSE; /* PCI bus*/ +#ifdef RTMP_MAC + if ((pAd->chipCap.hif_type == HIF_RTMP) && IS_PCI_INF(pAd)) + { + { + /* PCI and PCIe have different value in US_CYC_CNT*/ + RTMP_IO_READ32(pAd, PCI_CFG, &mac_val); + if ((mac_val & 0x10000) == 0) + { + US_CYC_CNT_STRUC USCycCnt; + + RTMP_IO_READ32(pAd, US_CYC_CNT, &mac_val); + USCycCnt.word = mac_val; + USCycCnt.field.UsCycCnt = 0x7D; + RTMP_IO_WRITE32(pAd, US_CYC_CNT, USCycCnt.word); + + pAd->CommonCfg.bPCIeBus = TRUE; + } + } + } +#endif /* RTMP_MAC */ + DBGPRINT(RT_DEBUG_TRACE, ("%s():device act as PCI%s driver\n", + __FUNCTION__, (pAd->CommonCfg.bPCIeBus ? "-E" : ""))); +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->chipOps.fw_init) + pAd->chipOps.fw_init(pAd); +#endif /* CONFIG_ANDES_SUPPORT */ + rtmp_mac_init(pAd); + + rtmp_mac_bcn_buf_init(pAd); + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + /* Before program BBP, we need to wait BBP/RF get wake up.*/ + Index = 0; + do + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &mac_val); + if ((mac_val & 0x03) == 0) /* if BB.RF is stable*/ + break; + + DBGPRINT(RT_DEBUG_TRACE, ("Check if MAC_STATUS_CFG is busy(=%x)\n", mac_val)); + RtmpusecDelay(1000); + } while (Index++ < 100); + } +#endif /* RTMP_MAC */ + + NICInitBBP(pAd); + +#ifdef RTMP_MAC_PCI + /* TODO: check MACVersion, currently, rbus-based chip use this.*/ + if (pAd->MACVersion == 0x28720200) + { + UINT32 value2; + + /*Maximum PSDU length from 16K to 32K bytes */ + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &value2); + value2 &= ~(0x3<<12); + value2 |= (0x2<<12); + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, value2); + } +#endif /* RTMP_MAC_PCI */ + + if ((IS_RT3883(pAd)) || IS_RT65XX(pAd) || +#ifdef RT6352 + (IS_RT6352(pAd)) || +#endif /* RT6352 */ + ((pAd->MACVersion >= RALINK_2880E_VERSION) && + (pAd->MACVersion < RALINK_3070_VERSION))) /* 3*3*/ + { + UINT32 csr; + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); +#if defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT65xx) || defined(MT7601) + if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3593(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd)) + csr |= 0x3fff; + else +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT65xx) || defined(MT7601) */ +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + csr &= 0xFFF; + csr |= 0x3000; + } + else +#endif /* RT6352 */ + { + csr &= 0xFFF; + csr |= 0x2000; + } + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr); + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Add radio off control*/ + if (pAd->StaCfg.bRadio == FALSE) + { + /* RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818);*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n")); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Clear raw counters*/ + NicResetRawCounters(pAd); + + /* + ASIC will keep garbage value after boot + Clear all shared key table when initial + This routine can be ignored in radio-ON/OFF operation. + */ + if (bHardReset) + { + UINT32 wcid_attr_base = 0, wcid_attr_size = 0, share_key_mode_base = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + share_key_mode_base = RLT_SHARED_KEY_MODE_BASE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + share_key_mode_base = SHARED_KEY_MODE_BASE; + } +#endif /* RTMP_MAC */ + + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, share_key_mode_base + 4*KeyIdx, 0); + } + + /* Clear all pairwise key table when initial*/ + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, wcid_attr_base + (KeyIdx * wcid_attr_size), 1); + } + } + + /* It isn't necessary to clear this space when not hard reset. */ + if (bHardReset == TRUE) + { + /* clear all on-chip BEACON frame space */ +#ifdef CONFIG_AP_SUPPORT + INT i, apidx; + for (apidx = 0; apidx < HW_BEACON_MAX_COUNT(pAd); apidx++) + { + if (pAd->BeaconOffset[apidx] > 0) { + // TODO: shiang-6590, if we didn't define MBSS_SUPPORT, the pAd->BeaconOffset[x] may set as 0 when chipCap.BcnMaxHwNum != HW_BEACON_MAX_COUNT + for (i = 0; i < HW_BEACON_OFFSET; i+=4) + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[apidx] + i, 0x00, 4); + + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + + + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n")); + return NDIS_STATUS_SUCCESS; +} + + +#ifdef RTMP_RBUS_SUPPORT +/* + ======================================================================== + + Routine Description: + Reset NIC from error + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Reset NIC from error state + + ======================================================================== +*/ +VOID NICResetFromError(RTMP_ADAPTER *pAd) +{ + UCHAR rf_channel; + + /* Reset BBP (according to alex, reset ASIC will force reset BBP*/ + /* Therefore, skip the reset BBP*/ + /* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2);*/ + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + /* Remove ASIC from reset state*/ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + NICInitializeAdapter(pAd, FALSE); + NICInitAsicFromEEPROM(pAd); + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + AsicBBPAdjust(pAd); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + AsicStaBbpTuning(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + rf_channel = pAd->CommonCfg.CentralChannel; + else + rf_channel = pAd->CommonCfg.Channel; + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + rf_channel = pAd->CommonCfg.CentralChannel; + } +#endif /* CONFIG_AP_SUPPORT */ + +#if defined(CONFIG_AP_SUPPORT) || defined(CONFIG_STA_SUPPORT) + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); +#endif /* defined(CONFIG_AP_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ +} +#endif /* RTMP_RBUS_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI +/* + ======================================================================== + + Routine Description: + In the case, Client may be silent left without sending DeAuth or DeAssoc. + AP'll continue retry packets for the client since AP doesn't know the STA + is gone. To Minimum affection of exist traffic is disable retransmition for + all those packet relative to the STA. + So decide to change ack required setting of all packet in TX ring + to "no ACK" requirement for specific Client. + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID ClearTxRingClientAck(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + INT index; + USHORT TxIdx; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; + TXWI_STRUC *pTxWI; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; + TXWI_STRUC *pDestTxWI; + TXWI_STRUC TxWI; + UINT8 TXWISize; +#endif /* RT_BIG_ENDIAN */ + + if (!pAd || !pEntry) + return; + +#ifdef RT_BIG_ENDIAN + TXWISize = pAd->chipCap.TXWISize; +#endif /* RT_BIG_ENDIAN */ + + for (index = 3; index >= 0; index--) + { + pTxRing = &pAd->TxRing[index]; + for (TxIdx = 0; TxIdx < TX_RING_SIZE; TxIdx++) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + if (!pTxD->DMADONE) + { +#ifdef RT_BIG_ENDIAN + pDestTxWI = (TXWI_STRUC *) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + NdisMoveMemory((PUCHAR)&TxWI, (PUCHAR)pDestTxWI, TXWISize); + pTxWI = &TxWI; + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); +#else + pTxWI = (TXWI_STRUC *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP && pTxWI->TXWI_O.wcid == pEntry->wcid) + pTxWI->TXWI_O.ACK = FALSE; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT && pTxWI->TXWI_N.wcid == pEntry->wcid) + pTxWI->TXWI_N.ACK = FALSE; +#endif /* RTL_MAC */ + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); + NdisMoveMemory((PUCHAR)pDestTxWI, (PUCHAR)pTxWI, TXWISize); +#endif /* RT_BIG_ENDIAN */ + } + } + } +} +#endif /* RTMP_MAC_PCI */ + +VOID ApTxFailCntUpdate(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, ULONG TxSuccess, ULONG TxRetransmit) +{ +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + if (pAd->MacTab.Size <= 8) { +#ifdef UAPSD_SUPPORT + /* check the EOSP packet by RateCtrl's way */ + UAPSD_SP_AUE_Handle(pAd, pEntry, TRUE); +#endif /* UAPSD_SUPPORT */ + + if ((TxSuccess == 0) && (TxRetransmit > 0)) + { + /* prevent fast drop long range clients */ + if (TxRetransmit > MAC_ENTRY_LIFE_CHECK_CNT / 4) + TxRetransmit = MAC_ENTRY_LIFE_CHECK_CNT / 4; + + /* No TxPkt ok in this period as continue tx fail */ + pEntry->ContinueTxFailCnt += TxRetransmit; + } + else + { + pEntry->ContinueTxFailCnt = 0; + } + + if (TxSuccess > 0) + pEntry->NoDataIdleCount = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s:(OK:%ld, FAIL:%ld, ConFail:%d) \n",__FUNCTION__, + TxSuccess, TxRetransmit, pEntry->ContinueTxFailCnt)); + } + } + else +#endif /* RT65xx */ + { + return; + } +} +#endif /* CONFIG_AP_SUPPORT */ + + +VOID NICUpdateFifoStaCounters(RTMP_ADAPTER *pAd) +{ +#ifdef FIFO_EXT_SUPPORT + TX_STA_FIFO_EXT_STRUC StaFifoExt; +#endif /* FIFO_EXT_SUPPORT */ + TX_STA_FIFO_STRUC StaFifo; + MAC_TABLE_ENTRY *pEntry = NULL; + UINT32 i = 0; + UCHAR pid = 0, wcid = 0; + INT32 reTry; + UCHAR succMCS, PhyMode; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef RT65xx + if (pAd->MacTab.Size <= 8) { + /* mark by UAPSD Accurate Issue */ + if (IS_RT65XX(pAd)) + return; + } +#endif /* RT65xx */ +#endif /* CONFIG_AP_SUPPORT */ + + + do + { +#ifdef FIFO_EXT_SUPPORT + RTMP_IO_READ32(pAd, TX_STA_FIFO_EXT, &StaFifoExt.word); +#endif /* FIFO_EXT_SUPPORT */ + RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); + + if (StaFifo.field.bValid == 0) + break; + + wcid = (UCHAR)StaFifo.field.wcid; + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFIFO) { + dbQueueEnqueue(0x73, (UCHAR *)(&StaFifo.word)); + } +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* ignore NoACK and MGMT frame use 0xFF as WCID */ + if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE)) + { + i++; + continue; + } + + /* PID store Tx MCS Rate */ +#ifdef FIFO_EXT_SUPPORT +#ifdef RT65xx + if (IS_MT76x2(pAd)) + { + PhyMode = StaFifo.field.PhyMode; + if((PhyMode == 2) || (PhyMode == 3)) + { + pid = (UCHAR)StaFifoExt.field.PidType & 0xF; + } + else if(PhyMode == 4) + { + pid = (UCHAR)StaFifoExt.field.PidType & 0xF; + pid += (((UCHAR)StaFifoExt.field.PidType & 0x10) ? 10 : 0); + } + } + else +#endif /* RT65xx */ +#endif /* FIFO_EXT_SUPPORT */ + + pid = (UCHAR)StaFifo.field.PidType; + + pEntry = &pAd->MacTab.Content[wcid]; + + +#ifdef CONFIG_STA_SUPPORT +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (!StaFifo.field.TxSuccess) + { + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(IS_ENTRY_TDLS(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR,(" pEntry->TdlsTxFailCount : %d\n", pEntry->TdlsTxFailCount)); + pEntry->TdlsTxFailCount++; + if (pEntry->TdlsTxFailCount >= 15 && pAd->StaCfg.wpa_supplicant_info.CFG_Tdls_info.bDoingPeriodChannelSwitch == FALSE) + { + DBGPRINT(RT_DEBUG_OFF, ("TDLS: TxFail >= 15 LinkTearDown !!!\n")); + TDLS_TearDownPeerLink(pAd, pEntry->Addr, FALSE); + } + if(pAd->StaCfg.wpa_supplicant_info.CFG_Tdls_info.bDoingPeriodChannelSwitch == TRUE) + pEntry->TdlsTxFailCount=0; + } + } + } + else + { + pEntry->NoDataIdleCount = 0; + pEntry->TdlsTxFailCount=0; + } +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ +#endif /* CONFIG_STA_SUPPORT */ + + + pEntry->DebugFIFOCount++; + + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT + /* Update BF statistics*/ + if (pAd->chipCap.FlgHwTxBfCap) + { + int succMCS = (StaFifo.field.SuccessRate & 0x7F); + int origMCS = pid; + + if (succMCS==32) + origMCS = 32; +#ifdef DOT11N_SS3_SUPPORT + if (succMCS>origMCS && pEntry->HTCapability.MCSSet[2]==0xff) + origMCS += 16; +#endif /* DOT11N_SS3_SUPPORT */ + + if (succMCS>origMCS) + origMCS = succMCS+1; + + /* MCS16 falls back to MCS8*/ + if (origMCS>=16 && succMCS<=8) + succMCS += 8; + + /* MCS8 falls back to 0 */ + if (origMCS >= 8 && succMCS == 0) + succMCS += 7; + + reTry = origMCS-succMCS; + + if (StaFifo.field.eTxBF) { + if (StaFifo.field.TxSuccess) + pEntry->TxBFCounters.ETxSuccessCount++; + else + pEntry->TxBFCounters.ETxFailCount++; + pEntry->TxBFCounters.ETxRetryCount += reTry; + } + else if (StaFifo.field.iTxBF) { + if (StaFifo.field.TxSuccess) + pEntry->TxBFCounters.ITxSuccessCount++; + else + pEntry->TxBFCounters.ITxFailCount++; + pEntry->TxBFCounters.ITxRetryCount += reTry; + } + else { + if (StaFifo.field.TxSuccess) + pEntry->TxBFCounters.TxSuccessCount++; + else + pEntry->TxBFCounters.TxFailCount++; + pEntry->TxBFCounters.TxRetryCount += reTry; + } + } +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef UAPSD_SUPPORT + UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess); +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + continue; +#endif /* CONFIG_STA_SUPPORT */ + + if (!StaFifo.field.TxSuccess) + { + pEntry->FIFOCount++; + pEntry->OneSecTxFailCount++; + pEntry->TotalTxFailCount++; +#ifdef CONFIG_AP_SUPPORT + pEntry->StatTxFailCount += pEntry->OneSecTxFailCount; + pAd->ApCfg.MBSSID[pEntry->apidx].StatTxFailCount += pEntry->StatTxFailCount; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + pEntry->DyncVgaOneSecTxCount++; +#endif /*DYNAMIC_VGA_SUPPORT*/ + + if (pEntry->FIFOCount >= 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("#")); +#ifdef DOT11_N_SUPPORT + //pEntry->NoBADataCountDown = 64; +#endif /* DOT11_N_SUPPORT */ + + /* Update the continuous transmission counter.*/ +#ifdef FIFO_EXT_SUPPORT + if (StaFifoExt.field.txRtyCnt > 0) + pEntry->ContinueTxFailCnt += StaFifoExt.field.txRtyCnt; + else +#endif + pEntry->ContinueTxFailCnt++; + + if(pEntry->PsMode == PWR_ACTIVE) + { +#ifdef DOT11_N_SUPPORT +#ifdef CONFIG_AP_SUPPORT +#ifdef NOISE_TEST_ADJUST + if ((pAd->ApCfg.EntryClientCount > 2) && + (pEntry->HTPhyMode.field.MODE >= MODE_HTMIX) && + (pEntry->lowTrafficCount >= 4 /* 2 sec */)) + pEntry->NoBADataCountDown = 10; +#endif /* NOISE_TEST_ADJUST */ +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DOT11_N_SUPPORT */ + +#ifdef WDS_SUPPORT + /* fix WDS Jam issue*/ + if(IS_ENTRY_WDS(pEntry) + && (pEntry->LockEntryTx == FALSE) + && (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Entry %02x:%02x:%02x:%02x:%02x:%02x Blocked!! (Fail Cnt = %d)\n", + PRINT_MAC(pEntry->Addr), pEntry->ContinueTxFailCnt )); + + pEntry->LockEntryTx = TRUE; + } +#endif /* WDS_SUPPORT */ + } + } +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + /* if Tx fail >= 20, then clear TXWI ack in Tx Ring*/ + if (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck) + ClearTxRingClientAck(pAd, pEntry); +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_AP_SUPPORT */ + } + else + { +#ifdef DOT11_N_SUPPORT + if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0)) + { + pEntry->NoBADataCountDown--; + if (pEntry->NoBADataCountDown==0) + { + DBGPRINT(RT_DEBUG_TRACE, ("@\n")); + } + } +#endif /* DOT11_N_SUPPORT */ + pEntry->FIFOCount = 0; + pEntry->OneSecTxNoRetryOkCount++; + + + /* update NoDataIdleCount when sucessful send packet to STA.*/ + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; +#ifdef WDS_SUPPORT + pEntry->LockEntryTx = FALSE; +#endif /* WDS_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined (DOT11Z_TDLS_SUPPORT) || defined (CFG_TDLS_SUPPORT) + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(IS_ENTRY_TDLS(pEntry)) + pEntry->TdlsTxFailCount = 0; + } +#endif /* DOT11Z_TDLS_SUPPORT || CFG_TDLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef RT65xx + if (IS_MT76x2(pAd)) + { + PhyMode = StaFifo.field.PhyMode; + if((PhyMode == 2) || (PhyMode == 3)) + { + succMCS = StaFifo.field.SuccessRate & 0xF; + +#ifdef DOT11N_SS3_SUPPORT + if (pEntry->HTCapability.MCSSet[2] == 0xff) + { + if (succMCS > pid) + pid = pid + 16; + } +#endif /* DOT11N_SS3_SUPPORT */ + + if (StaFifo.field.TxSuccess) + { + pEntry->TXMCSExpected[pid]++; + if (pid == succMCS) + pEntry->TXMCSSuccessful[pid]++; + else { +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pAd->ApCfg.MBSSID[pEntry->apidx].TxRetriedPktCount++; + pEntry->TxRetriedPktCount++; + pAd->RadioStatsCounter.TxRetriedPktCount++; +#endif +#endif + pEntry->TXMCSAutoFallBack[pid][succMCS]++; + } + } + else + { +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pAd->ApCfg.MBSSID[pEntry->apidx].TxRetriedPktCount++; + pEntry->TxRetriedPktCount++; + pAd->RadioStatsCounter.TxRetriedPktCount++; +#endif +#endif + pEntry->TXMCSFailed[pid]++; + } + +#ifdef DOT11N_SS3_SUPPORT + if (pid >= 16 && succMCS <= 8) + succMCS += (2 - (succMCS >> 3)) * 7; +#endif /* DOT11N_SS3_SUPPORT */ + + reTry = pid - succMCS; + + if (reTry > 0) + { + /* MCS8 falls back to 0 */ + if (pid>=8 && succMCS==0) + reTry -= 7; + //else if ((pid >= 12) && succMCS <=7) + // reTry -= 4; + + pEntry->OneSecTxRetryOkCount += reTry; + +#ifdef CONFIG_AP_SUPPORT + pEntry->StatTxRetryOkCount += pEntry->OneSecTxRetryOkCount; + pAd->ApCfg.MBSSID[pEntry->apidx].StatTxRetryOkCount += pEntry->StatTxRetryOkCount; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + pEntry->DyncVgaOneSecTxCount += reTry; +#endif /*DYNAMIC_VGA_SUPPORT*/ + } + } + else if(PhyMode == 4) + { + succMCS = StaFifo.field.SuccessRate & 0xF; + succMCS += ((StaFifo.field.SuccessRate & 0x10) ? 10 : 0); + //DBGPRINT(0, ("%s()Succ MCS :TxMCS(%d):PHYMode(%d)\n", __FUNCTION__, pid, PhyMode)); + if (StaFifo.field.TxSuccess) + { + pEntry->TXMCSExpected[pid]++; + + if (pid == succMCS) + pEntry->TXMCSSuccessful[pid]++; + else { +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pAd->ApCfg.MBSSID[pEntry->apidx].TxRetriedPktCount++; + pEntry->TxRetriedPktCount++; + pAd->RadioStatsCounter.TxRetriedPktCount++; +#endif +#endif + pEntry->TXMCSAutoFallBack[pid][succMCS]++; + } + } + else + { +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pAd->ApCfg.MBSSID[pEntry->apidx].TxRetriedPktCount++; + pEntry->TxRetriedPktCount++; + pAd->RadioStatsCounter.TxRetriedPktCount++; +#endif +#endif + pEntry->TXMCSFailed[pid]++; + } + + reTry = pid - succMCS; + + if (reTry > 0) + { + /* MCS10 falls back to 0 */ + if (pid >= 10 && succMCS == 0) + reTry -= 9; + + pEntry->OneSecTxRetryOkCount += reTry; +#ifdef DYNAMIC_VGA_SUPPORT + pEntry->DyncVgaOneSecTxCount += reTry; +#endif /*DYNAMIC_VGA_SUPPORT*/ + } + + if(reTry <= 0) + pEntry->DownTxMCSRate[0]++; + else if(reTry > (NUM_OF_SWFB-1)) + pEntry->DownTxMCSRate[NUM_OF_SWFB-1]++; + else + pEntry->DownTxMCSRate[reTry]++; + } + } + else +#endif /* RT65xx */ + { + succMCS = StaFifo.field.SuccessRate & 0x7F; + +#ifdef DOT11N_SS3_SUPPORT + if (pEntry->HTCapability.MCSSet[2] == 0xff) + { + if (succMCS > pid) + pid = pid + 16; + } +#endif /* DOT11N_SS3_SUPPORT */ + + if (StaFifo.field.TxSuccess) + { + pEntry->TXMCSExpected[pid]++; + if (pid == succMCS) + { + pEntry->TXMCSSuccessful[pid]++; + } + else + { +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pAd->ApCfg.MBSSID[pEntry->apidx].TxRetriedPktCount++; + pEntry->TxRetriedPktCount++; + pAd->RadioStatsCounter.TxRetriedPktCount++; +#endif +#endif + pEntry->TXMCSAutoFallBack[pid][succMCS]++; + } + } + else + { +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + pAd->ApCfg.MBSSID[pEntry->apidx].TxRetriedPktCount++; + pEntry->TxRetriedPktCount++; + pAd->RadioStatsCounter.TxRetriedPktCount++; +#endif +#endif + pEntry->TXMCSFailed[pid]++; + } + +#ifdef DOT11N_SS3_SUPPORT + if (pid >= 16 && succMCS <= 8) + succMCS += (2 - (succMCS >> 3)) * 7; +#endif /* DOT11N_SS3_SUPPORT */ + + reTry = pid - succMCS; + + if (reTry > 0) + { + /* MCS8 falls back to 0 */ + if (pid>=8 && succMCS==0) + reTry -= 7; + else if ((pid >= 12) && succMCS <=7) + { + reTry -= 4; + } + + pEntry->OneSecTxRetryOkCount += reTry; +#ifdef DYNAMIC_VGA_SUPPORT + pEntry->DyncVgaOneSecTxCount += reTry; +#endif /*DYNAMIC_VGA_SUPPORT*/ + } + } + + i++; /* ASIC store 16 stack*/ + } while ( i < (TX_RING_SIZE<<1) ); + +} + + +#ifdef FIFO_EXT_SUPPORT +BOOLEAN NicGetMacFifoTxCnt(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + if (pEntry->bUseHwFifoExt) + { + WCID_TX_CNT_STRUC wcidTxCnt; + + RTMP_IO_READ32(pAd, pAd->FifoExtTbl[pEntry->hwFifoExtIdx].hwTxCntCROffset, &wcidTxCnt.word); + + pEntry->fifoTxSucCnt += wcidTxCnt.field.succCnt; + pEntry->fifoTxRtyCnt += wcidTxCnt.field.reTryCnt; + + return TRUE; + } + + return FALSE; +} + + +/* + The 8 entries will be dynamically replaced to apcli-repeater entry, starting from tail of table, at most replace 4 entries: + { CLI, CLI, CLI, CLI, CLI, CLI, CLI, CLI} still 4 vacancy entries + --> { CLI, CLI, CLI, CLI, CLI, CLI, CLI, APCLI} still 3 vacancy entries + --> { CLI, CLI, CLI, CLI, CLI, CLI, APCLI, APCLI} still 2 vacancy entries + --> { CLI, CLI, CLI, CLI, CLI, APCLI, APCLI, APCLI} still 1 vacancy entry + --> { CLI, CLI, CLI, CLI, APCLI, APCLI, APCLI, APCLI} no vacancy entry +*/ +BOOLEAN IsFifoExtTblAvailable(IN RTMP_ADAPTER *pAd, IN UCHAR *pTblIdx) +{ + MAC_TABLE_ENTRY *pEntry; + int vacancy = -1; /* initialized by a invalid value */ + int i; + + for (i = (FIFO_EXT_HW_SIZE - 1); i >= 4; i --) + { + pEntry = &pAd->MacTab.Content[pAd->FifoExtTbl[i].wcid]; + + if (IS_ENTRY_APCLI(pEntry)) + continue; + + /* The first non-ApCli entry (starting from tail) */ + vacancy = i; + break; + } + + if (vacancy == -1) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("FIFO_EXT: find vacancy entry %d\n", vacancy)); + *pTblIdx = (UCHAR)vacancy; + return TRUE; +} + + +VOID FifoExtTblUpdateEntry(IN RTMP_ADAPTER *pAd, IN UCHAR tblIdx, IN UCHAR wcid) +{ + MAC_TABLE_ENTRY *pNewEntry, *pOldEntry; + UCHAR oldWcid; + + if (tblIdx >= FIFO_EXT_HW_SIZE) + return; + + oldWcid = pAd->FifoExtTbl[tblIdx].wcid; + if (oldWcid == wcid) + return; + + pOldEntry = &pAd->MacTab.Content[oldWcid]; + pNewEntry = &pAd->MacTab.Content[wcid]; + + /* Clear the old one */ + pOldEntry->bUseHwFifoExt = FALSE; + + /* Set the new one */ + pNewEntry->hwFifoExtIdx = tblIdx; + pNewEntry->bUseHwFifoExt = TRUE; + + /* Update global setting */ + pAd->FifoExtTbl[tblIdx].wcid = wcid; + RTMP_IO_WRITE8(pAd, WCID_MAPPING_0 + tblIdx, wcid); +} + + +const UCHAR PreDefWcid[] = {1, 2, 3, 4, 5, 6, 7, 8}; + +VOID FifoExtTblRmReptEntry(IN RTMP_ADAPTER *pAd, IN UCHAR wcid) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[wcid]; + UCHAR tblIdx = pEntry->hwFifoExtIdx; + + FifoExtTblUpdateEntry(pAd, tblIdx, PreDefWcid[tblIdx]); +} + +VOID FifoExtTableInit(IN RTMP_ADAPTER *pAd) +{ + if (pAd->chipCap.FlgHwFifoExtCap) + { + UCHAR i, wcid; + + for (i = 0; i < FIFO_EXT_HW_SIZE; i ++) + { + wcid = PreDefWcid[i]; + pAd->FifoExtTbl[i].wcid = wcid; + pAd->FifoExtTbl[i].hwTxCntCROffset = WCID_TX_CNT_0 + (i * 4); + + /* set pEntry */ + pAd->MacTab.Content[wcid].hwFifoExtIdx = i; + pAd->MacTab.Content[wcid].bUseHwFifoExt = TRUE; + } + } +} + + +VOID AsicFifoExtSet(IN RTMP_ADAPTER *pAd) +{ + if (pAd->chipCap.FlgHwFifoExtCap) + { + UCHAR i; + UINT32 WcidSet; + + WcidSet = 0; + for (i = 0; i < 4; i ++) + WcidSet |= (pAd->FifoExtTbl[i].wcid << (i * 8)); + + RTMP_IO_WRITE32(pAd, WCID_MAPPING_0, WcidSet); + + WcidSet = 0; + for (i = 0; i < 4; i ++) + WcidSet |= (pAd->FifoExtTbl[i + 4].wcid << (i * 8)); + + RTMP_IO_WRITE32(pAd, WCID_MAPPING_1, WcidSet); + } +} + + +VOID AsicFifoExtEntryClean(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + WCID_TX_CNT_STRUC wcidTxCnt; + + if (pAd->chipCap.FlgHwFifoExtCap) + { + /* We clean the fifo info when entry Tx Counter is controlled by hw */ + if (pEntry->bUseHwFifoExt) + RTMP_IO_READ32(pAd, pAd->FifoExtTbl[pEntry->hwFifoExtIdx].hwTxCntCROffset, &wcidTxCnt.word); + } +} +#endif /* FIFO_EXT_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Read Tx statistic raw counters from hardware registers and record to + related software variables for later on query + + Arguments: + pAd Pointer to our adapter + pStaTxCnt0 Pointer to record "TX_STA_CNT0" (0x170c) + pStaTxCnt1 Pointer to record "TX_STA_CNT1" (0x1710) + + Return Value: + None + + ======================================================================== +*/ +VOID NicGetTxRawCounters( + IN RTMP_ADAPTER *pAd, + IN TX_STA_CNT0_STRUC *pStaTxCnt0, + IN TX_STA_CNT1_STRUC *pStaTxCnt1) +{ + + RTMP_IO_READ32(pAd, TX_STA_CNT0, &pStaTxCnt0->word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &pStaTxCnt1->word); + + pAd->bUpdateBcnCntDone = TRUE; /* not appear in Rory's code */ + pAd->RalinkCounters.OneSecBeaconSentCnt += pStaTxCnt0->field.TxBeaconCount; + pAd->RalinkCounters.OneSecTxRetryOkCount += pStaTxCnt1->field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += pStaTxCnt1->field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += pStaTxCnt0->field.TxFailCount; + +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += pStaTxCnt1->field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += pStaTxCnt1->field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += pStaTxCnt0->field.TxFailCount; +#endif /* STATS_COUNT_SUPPORT */ + + +} + +/* + ======================================================================== + + Routine Description: + Read Tx RTS counters from hardware registers and record to + related software variables for later on query + + Arguments: + pAd Pointer to our adapter + pRtsTxCnt Pointer to record "RTS_TX_CNT" (0x1744) + + Return Value: + None + + ======================================================================== +*/ +VOID NicGetTxRTSCounters( + IN RTMP_ADAPTER *pAd, + IN RTS_TX_CNT_STRUC *pRtsTxCnt) +{ + + RTMP_IO_READ32(pAd, RTS_TX_CNT, &pRtsTxCnt->word); + +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.RTSSuccessCount.u.LowPart += pRtsTxCnt->field.RtsTxOkCount; + pAd->WlanCounters.RTSFailureCount.u.LowPart += pRtsTxCnt->field.RtsTxFailCount; +#endif /* STATS_COUNT_SUPPORT */ + +} + +/* + ======================================================================== + + Routine Description: + Clean all Tx/Rx statistic raw counters from hardware registers + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + ======================================================================== +*/ +VOID NicResetRawCounters(RTMP_ADAPTER *pAd) +{ + UINT32 Counter; + + RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); +} + + +/* + ======================================================================== + + Routine Description: + Read statistical counters from hardware registers and record them + in software variables for later on query + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID NICUpdateRawCounters(RTMP_ADAPTER *pAd) +{ + UINT32 OldValue;/*, Value2;*/ + /*ULONG PageSum, OneSecTransmitCount;*/ + /*ULONG TxErrorRatio, Retry, Fail;*/ + RX_STA_CNT0_STRUC RxStaCnt0; + RX_STA_CNT1_STRUC RxStaCnt1; + RX_STA_CNT2_STRUC RxStaCnt2; + TX_STA_CNT0_STRUC TxStaCnt0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT2_STRUC StaTx2; +#ifdef STATS_COUNT_SUPPORT + TX_NAG_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + TX_AGG_CNT4_STRUC TxAggCnt4; + TX_AGG_CNT5_STRUC TxAggCnt5; + TX_AGG_CNT6_STRUC TxAggCnt6; + TX_AGG_CNT7_STRUC TxAggCnt7; +#endif /* STATS_COUNT_SUPPORT */ + COUNTER_RALINK *pRalinkCounters; + + + pRalinkCounters = &pAd->RalinkCounters; + + + + RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); + + pAd->RalinkCounters.PhyErrCnt += RxStaCnt0.field.PhyErr; + +#ifdef CUSTOMER_DCC_FEATURE + if(!pAd->EnableChannelStatsCheck && !(ApScanRunning(pAd))) +#endif + { + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + /* Update RX PLCP error counter*/ + pAd->RalinkCounters.PlcpErrCnt += RxStaCnt1.field.PlcpErr; + /* Update False CCA counter*/ + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; +#ifdef ED_MONITOR + if (pAd->ed_chk /*&& pAd->ed_timer_inited == TRUE*/) //no timer now, and the data may not correct before. + pAd->false_cca_stat[pAd->ed_stat_lidx] += RxStaCnt1.field.FalseCca; +#endif /* ED_MONITOR */ + pAd->RalinkCounters.FalseCCACnt += RxStaCnt1.field.FalseCca; +#ifdef SMART_MESH + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /*Still scanning*/ + pAd->ChannelList[pAd->ApCfg.scan_channel_index].FalseCCA += RxStaCnt1.field.FalseCca; + } +#endif /* SMART_MESH */ + } + +#ifdef STATS_COUNT_SUPPORT + /* Update FCS counters*/ + OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart; + pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); /* >> 7);*/ + if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) + pAd->WlanCounters.FCSErrorCount.u.HighPart++; +#endif /* STATS_COUNT_SUPPORT */ + + /* Add FCS error count to private counters*/ + pRalinkCounters->OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; + OldValue = pRalinkCounters->RealFcsErrCount.u.LowPart; + pRalinkCounters->RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; + if (pRalinkCounters->RealFcsErrCount.u.LowPart < OldValue) + pRalinkCounters->RealFcsErrCount.u.HighPart++; + + /* Update Duplicate Rcv check*/ + pRalinkCounters->DuplicateRcv += RxStaCnt2.field.RxDupliCount; +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount; +#endif /* STATS_COUNT_SUPPORT */ + /* Update RX Overflow counter*/ + pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount); + + /*pAd->RalinkCounters.RxCount = 0;*/ + + + /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) || */ + /* (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1)))*/ + if (!pAd->bUpdateBcnCntDone) + { + /* Update BEACON sent count*/ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TotalBeaconSentCount += TxStaCnt0.field.TxBeaconCount; + pAd->RadioStatsCounter.TotalTxCount += (StaTx1.field.TxSuccess + TxStaCnt0.field.TxFailCount + StaTx1.field.TxRetransmit + TxStaCnt0.field.TxBeaconCount); + pAd->RadioStatsCounter.TxRetryCount += StaTx1.field.TxRetransmit; +#endif + } + + + /*if (pAd->bStaFifoTest == TRUE)*/ +#ifdef STATS_COUNT_SUPPORT + { + RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); + pRalinkCounters->TxAggCount += TxAggCnt.field.AggTxCount; + pRalinkCounters->TxNonAggCount += TxAggCnt.field.NonAggTxCount; + pRalinkCounters->TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count; + pRalinkCounters->TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count; + + pRalinkCounters->TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count; + pRalinkCounters->TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count; + pRalinkCounters->TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count; + pRalinkCounters->TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count; + + pRalinkCounters->TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count; + pRalinkCounters->TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count; + pRalinkCounters->TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count; + pRalinkCounters->TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count; + + pRalinkCounters->TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count; + pRalinkCounters->TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count; + pRalinkCounters->TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count; + pRalinkCounters->TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count; + + pRalinkCounters->TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count; + pRalinkCounters->TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count; + + /* Calculate the transmitted A-MPDU count*/ + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count; + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count >> 1); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count >> 2); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count >> 3); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count >> 4); + } +#endif /* STATS_COUNT_SUPPORT */ + +#ifdef DBG_DIAGNOSE + { + RtmpDiagStruct *pDiag; + UCHAR ArrayCurIdx, i; + struct dbg_diag_info *diag_info; + + pDiag = &pAd->DiagStruct; + ArrayCurIdx = pDiag->ArrayCurIdx; + + if (pDiag->inited == 0) + { + NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); + pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; + pDiag->inited = 1; + } + else + { + diag_info = &pDiag->diag_info[ArrayCurIdx]; + + /* Tx*/ + diag_info->TxFailCnt = TxStaCnt0.field.TxFailCount; +#ifdef DBG_TX_AGG_CNT + diag_info->TxAggCnt = TxAggCnt.field.AggTxCount; + diag_info->TxNonAggCnt = TxAggCnt.field.NonAggTxCount; + + diag_info->TxAMPDUCnt[0] = TxAggCnt0.field.AggSize1Count; + diag_info->TxAMPDUCnt[1] = TxAggCnt0.field.AggSize2Count; + diag_info->TxAMPDUCnt[2] = TxAggCnt1.field.AggSize3Count; + diag_info->TxAMPDUCnt[3] = TxAggCnt1.field.AggSize4Count; + diag_info->TxAMPDUCnt[4] = TxAggCnt2.field.AggSize5Count; + diag_info->TxAMPDUCnt[5] = TxAggCnt2.field.AggSize6Count; + diag_info->TxAMPDUCnt[6] = TxAggCnt3.field.AggSize7Count; + diag_info->TxAMPDUCnt[7] = TxAggCnt3.field.AggSize8Count; + diag_info->TxAMPDUCnt[8] = TxAggCnt4.field.AggSize9Count; + diag_info->TxAMPDUCnt[9] = TxAggCnt4.field.AggSize10Count; + diag_info->TxAMPDUCnt[10] = TxAggCnt5.field.AggSize11Count; + diag_info->TxAMPDUCnt[11] = TxAggCnt5.field.AggSize12Count; + diag_info->TxAMPDUCnt[12] = TxAggCnt6.field.AggSize13Count; + diag_info->TxAMPDUCnt[13] = TxAggCnt6.field.AggSize14Count; + diag_info->TxAMPDUCnt[14] = TxAggCnt7.field.AggSize15Count; + diag_info->TxAMPDUCnt[15] = TxAggCnt7.field.AggSize16Count; +#endif /* DBG_TX_AGG_CNT */ + + diag_info->RxCrcErrCnt = RxStaCnt0.field.CrcErr; + + INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); + ArrayCurIdx = pDiag->ArrayCurIdx; + + NdisZeroMemory(&pDiag->diag_info[ArrayCurIdx], sizeof(pDiag->diag_info[ArrayCurIdx])); + + if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) + INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); + } + } +#endif /* DBG_DIAGNOSE */ + + +} + + +int load_patch(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + ULONG Old, New, Diff; + + if (ad->chipOps.load_rom_patch) { + RTMP_GetCurrentSystemTick(&Old); + ret = ad->chipOps.load_rom_patch(ad); + RTMP_GetCurrentSystemTick(&New); + Diff = (New - Old) * 1000 / OS_HZ; + DBGPRINT(RT_DEBUG_TRACE, ("load rom patch spent %ldms\n", Diff)); + } + + return ret; +} + +VOID erase_patch(RTMP_ADAPTER *ad) +{ + if (ad->chipOps.erase_rom_patch) + ad->chipOps.erase_rom_patch(ad); +} + +int NICLoadFirmware(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + ULONG Old, New, Diff; + + if (ad->chipOps.loadFirmware) { + RTMP_GetCurrentSystemTick(&Old); + ret = ad->chipOps.loadFirmware(ad); + RTMP_GetCurrentSystemTick(&New); + Diff = (New - Old) * 1000 / OS_HZ; + DBGPRINT(RT_DEBUG_TRACE, ("load fw spent %ldms\n", Diff)); + } + + return ret; +} + + +VOID NICEraseFirmware(RTMP_ADAPTER *pAd) +{ + if (pAd->chipOps.eraseFirmware) + pAd->chipOps.eraseFirmware(pAd); +} + + +/* + ======================================================================== + + Routine Description: + Compare two memory block + + Arguments: + pSrc1 Pointer to first memory address + pSrc2 Pointer to second memory address + + Return Value: + 0: memory is equal + 1: pSrc1 memory is larger + 2: pSrc2 memory is larger + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +ULONG RTMPCompareMemory(VOID *pSrc1, VOID *pSrc2, ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + ULONG Index = 0; + + pMem1 = (PUCHAR) pSrc1; + pMem2 = (PUCHAR) pSrc2; + + for (Index = 0; Index < Length; Index++) + { + if (pMem1[Index] > pMem2[Index]) + return (1); + else if (pMem1[Index] < pMem2[Index]) + return (2); + } + + /* Equal*/ + return (0); +} + + +/* + ======================================================================== + + Routine Description: + Zero out memory block + + Arguments: + pSrc1 Pointer to memory address + Length Size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPZeroMemory(VOID *pSrc, ULONG Length) +{ + PUCHAR pMem; + ULONG Index = 0; + + pMem = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem[Index] = 0x00; + } +} + + +/* + ======================================================================== + + Routine Description: + Copy data from memory block 1 to memory block 2 + + Arguments: + pDest Pointer to destination memory address + pSrc Pointer to source memory address + Length Copy size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPMoveMemory(VOID *pDest, VOID *pSrc, ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + UINT Index; + + ASSERT((Length==0) || (pDest && pSrc)); + + pMem1 = (PUCHAR) pDest; + pMem2 = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem1[Index] = pMem2[Index]; + } +} + + +VOID UserCfgExit(RTMP_ADAPTER *pAd) +{ +#ifdef RT_CFG80211_SUPPORT + /* Reset the CFG80211 Internal Flag */ + RTMP_DRIVER_80211_RESET(pAd); +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + BATableExit(pAd); +#endif /* DOT11_N_SUPPORT */ + + + NdisFreeSpinLock(&pAd->MacTabLock); + +#ifdef MAC_REPEATER_SUPPORT + NdisFreeSpinLock(&pAd->ApCfg.ReptCliEntryLock); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef BAND_STEERING + BndStrg_Release(pAd); +#endif /* BAND_STEERING */ + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +/* + ======================================================================== + + Routine Description: + Initialize port configuration structure + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID UserCfgInit(RTMP_ADAPTER *pAd) +{ + UINT i; +#ifdef CONFIG_AP_SUPPORT + UINT j; +#endif /* CONFIG_AP_SUPPORT */ + UINT key_index, bss_index; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n")); + + pAd->IndicateMediaState = NdisMediaStateDisconnected; + + /* part I. intialize common configuration */ + pAd->CommonCfg.BasicRateBitmap = 0xF; + pAd->CommonCfg.BasicRateBitmapOld = 0xF; + + + for(key_index=0; key_indexSharedKey[bss_index][key_index].KeyLen = 0; + pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE; + } + } + + pAd->bLocalAdminMAC = FALSE; + pAd->EepromAccess = FALSE; + + pAd->Antenna.word = 0; + pAd->CommonCfg.BBPCurrentBW = BW_20; + +#ifdef RTMP_MAC_PCI +#ifdef LED_CONTROL_SUPPORT + pAd->LedCntl.LedIndicatorStrength = 0; +#endif /* LED_CONTROL_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + pAd->RLnkCtrlOffset = 0; + pAd->HostLnkCtrlOffset = 0; +#endif /* CONFIG_STA_SUPPORT */ + + pAd->int_cpu_analysis = 0; + pAd->fake_int_counter = 0; + pAd->rx_coherent_counter = 0; + pAd->tx_coherent_counter = 0; + pAd->fifo_int_counter = 0; + pAd->hcca_int_counter = 0; + pAd->tx_ac3_int_counter = 0; + pAd->tx_ac2_int_counter = 0; + pAd->tx_ac1_int_counter = 0; + + /* tx ac0 tasklet related */ + pAd->tx_tasklet_counter = 0; + pAd->tx_int_counter = 0; + pAd->tx_packet_counter = 0; + + /* rx tasklet related */ + pAd->rx_tasklet_counter = 0; + pAd->rx_int_counter = 0; + pAd->rx_packet_counter = 0; + pAd->rx_tasklet_resche_counter = 0; + pAd->rx_packet_1_counter = 0; + pAd->rx_packet_2_counter = 0; + pAd->rx_packet_3_counter = 0; + pAd->rx_packet_4_counter = 0; + pAd->rx_packet_5_counter = 0; + pAd->rx_packet_6_10_counter = 0; + pAd->rx_packet_11_15_counter = 0; + pAd->rx_packet_16_20_counter = 0; + pAd->rx_packet_21_25_counter = 0; + pAd->rx_packet_26_31_counter = 0; + pAd->rx_packet_32_max_counter = 0; +#endif /* RTMP_MAC_PCI */ + + pAd->bAutoTxAgcA = FALSE; /* Default is OFF*/ + pAd->bAutoTxAgcG = FALSE; /* Default is OFF*/ + +#ifdef SINGLE_SKU_V2 + pAd->sku_init_done = FALSE; + pAd->tc_init_val = 0; +#endif /* SINGLE_SKU_V2 */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + pAd->TxPowerCtrl.bInternalTxALC = FALSE; /* Off by default */ + pAd->TxPowerCtrl.idxTxPowerTable = 0; + pAd->TxPowerCtrl.idxTxPowerTable2 = 0; +#ifdef RTMP_TEMPERATURE_COMPENSATION + pAd->TxPowerCtrl.LookupTableIndex = 0; +#endif /* RTMP_TEMPERATURE_COMPENSATION */ +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + +#ifdef THERMAL_PROTECT_SUPPORT + pAd->force_one_tx_stream = FALSE; + pAd->last_thermal_pro_temp = 0; + pAd->thermal_pro_criteria = 80; +#endif /* THERMAL_PROTECT_SUPPORT */ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + pAd->TxPowerCtrl.bInternalTxALC = FALSE; /* Off by default */ + pAd->TxPowerCtrl.idxTxPowerTable = 0; + pAd->TxPowerCtrl.idxTxPowerTable2 = 0; +#ifdef RTMP_TEMPERATURE_COMPENSATION + pAd->TxPowerCtrl.LookupTableIndex = 0; +#endif /* RTMP_TEMPERATURE_COMPENSATION */ +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + pAd->RfIcType = RFIC_2820; + + /* Init timer for reset complete event*/ + pAd->CommonCfg.CentralChannel = 1; + pAd->bForcePrintTX = FALSE; + pAd->bForcePrintRX = FALSE; + pAd->bStaFifoTest = FALSE; + pAd->bProtectionTest = FALSE; + pAd->bHCCATest = FALSE; + pAd->bGenOneHCCA = FALSE; + pAd->CommonCfg.Dsifs = 10; /* in units of usec */ + pAd->CommonCfg.TxPower = 100; /* mW*/ + pAd->CommonCfg.TxPowerPercentage = 0xffffffff; /* AUTO*/ + pAd->CommonCfg.TxPowerDefault = 0xffffffff; /* AUTO*/ + pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; /* use Long preamble on TX by defaut*/ + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + pAd->CommonCfg.RtsThreshold = 2347; + pAd->CommonCfg.FragmentThreshold = 2346; + pAd->CommonCfg.UseBGProtection = 0; /* 0: AUTO*/ + pAd->CommonCfg.bEnableTxBurst = TRUE; /* 0; */ + pAd->CommonCfg.PhyMode = 0xff; /* unknown*/ + pAd->CommonCfg.SavedPhyMode = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.BandState = UNKNOWN_BAND; + + pAd->wmm_cw_min = 4; + switch (pAd->OpMode) + { + case OPMODE_AP: + pAd->wmm_cw_max = 6; + break; + case OPMODE_STA: + pAd->wmm_cw_max = 10; + break; + } + + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + pAd->ApCfg.ACSCheckTime = 0; +#endif /* AP_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + pAd->CommonCfg.CarrierDetect.delta = CARRIER_DETECT_DELTA; + pAd->CommonCfg.CarrierDetect.div_flag = CARRIER_DETECT_DIV_FLAG; + pAd->CommonCfg.CarrierDetect.criteria = CARRIER_DETECT_CRITIRIA; + pAd->CommonCfg.CarrierDetect.threshold = CARRIER_DETECT_THRESHOLD; + pAd->CommonCfg.CarrierDetect.recheck1 = CARRIER_DETECT_RECHECK_TIME; + pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold = CARRIER_GONE_TRESHOLD; + pAd->CommonCfg.CarrierDetect.VGA_Mask = CARRIER_DETECT_DEFAULT_MASK; + pAd->CommonCfg.CarrierDetect.Packet_End_Mask = CARRIER_DETECT_DEFAULT_MASK; + pAd->CommonCfg.CarrierDetect.Rx_PE_Mask = CARRIER_DETECT_DEFAULT_MASK; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bDfsInit = FALSE; +#endif /* DFS_SUPPORT */ + + +#ifdef UAPSD_SUPPORT +#ifdef CONFIG_AP_SUPPORT +{ + UINT32 IdMbss; + + for(IdMbss=0; IdMbssApCfg.MBSSID[IdMbss].UapsdInfo); +} +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.UapsdInfo.bAPSDCapable = FALSE; +#endif /* CONFIG_STA_SUPPORT */ +#endif /* UAPSD_SUPPORT */ + pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; + pAd->CommonCfg.TriggerTimerCount = 0; + pAd->CommonCfg.bAPSDForcePowerSave = FALSE; + /*pAd->CommonCfg.bCountryFlag = FALSE;*/ + pAd->CommonCfg.TxStream = 0; + pAd->CommonCfg.RxStream = 0; + + NdisZeroMemory(&pAd->BeaconTxWI, TXWISize); + +#ifdef DOT11_VHT_AC + if (IS_MT76x2(pAd)) + pAd->CommonCfg.b256QAM_2G = TRUE; + else + pAd->CommonCfg.b256QAM_2G = FALSE; +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + pAd->HTCEnable = FALSE; + pAd->bBroadComHT = FALSE; + pAd->CommonCfg.bRdg = FALSE; + +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; /* Unit : TU. 5~1000*/ + pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; /* Unit : TU. 10~1000*/ + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; /* Unit : Second */ + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; /* Unit : TU. 200~10000*/ + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; /* Unit : TU. 20~10000*/ + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; + pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; /* Unit : percentage*/ + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + + pAd->CommonCfg.bBssCoexEnable = TRUE; /* by default, we enable this feature, you can disable it via the profile or ioctl command*/ + pAd->CommonCfg.BssCoexApCntThr = 0; + pAd->CommonCfg.Bss2040NeedFallBack = 0; +#endif /* DOT11N_DRAFT3 */ + + pAd->CommonCfg.bRcvBSSWidthTriggerEvents = FALSE; + + NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_DISABLE; + pAd->CommonCfg.BACapability.field.MpduDensity = 0; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; /*32;*/ + pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; /*32;*/ + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word)); + + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + BATableInit(pAd, &pAd->BATable); + + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + pAd->CommonCfg.bHTProtect = 1; + pAd->CommonCfg.bMIMOPSEnable = TRUE; +#ifdef GREENAP_SUPPORT + pAd->ApCfg.bGreenAPEnable=FALSE; + pAd->ApCfg.bGreenAPActive = FALSE; + pAd->ApCfg.GreenAPLevel= GREENAP_WITHOUT_ANY_STAS_CONNECT; +#endif /* GREENAP_SUPPORT */ + pAd->CommonCfg.bBADecline = FALSE; + pAd->CommonCfg.bDisableReordering = FALSE; + + if (pAd->MACVersion == 0x28720200) + pAd->CommonCfg.TxBASize = 13; /*by Jerry recommend*/ + else + pAd->CommonCfg.TxBASize = 7; + + pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; +#endif /* DOT11_N_SUPPORT */ + + pAd->CommonCfg.TxRate = RATE_6; + + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + + pAd->CommonCfg.BeaconPeriod = 100; /* in mSec*/ + +#ifdef DELAYED_TCP_ACK + pAd->CommonCfg.ACKQEN = 0; + pAd->CommonCfg.AckWaitTime = 40; + pAd->CommonCfg.Acklen = 16; +#endif /* DELAYED_TCP_ACK */ + +#ifdef STREAM_MODE_SUPPORT + if (pAd->chipCap.FlgHwStreamMode) + { + pAd->CommonCfg.StreamMode = 3; + pAd->CommonCfg.StreamModeMCS = 0x0B0B; + NdisMoveMemory(&pAd->CommonCfg.StreamModeMac[0][0], + BROADCAST_ADDR, MAC_ADDR_LEN); + } +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef TXBF_SUPPORT + pAd->CommonCfg.ETxBfNoncompress = 0; + pAd->CommonCfg.ETxBfIncapable = 0; +#endif /* TXBF_SUPPORT */ + +#ifdef NEW_RATE_ADAPT_SUPPORT + pAd->CommonCfg.lowTrafficThrd = 2; + pAd->CommonCfg.TrainUpRule = 2; // 1; + pAd->CommonCfg.TrainUpRuleRSSI = -70; // 0; + pAd->CommonCfg.TrainUpLowThrd = 90; + pAd->CommonCfg.TrainUpHighThrd = 110; +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef PS_ENTRY_MAITENANCE + pAd->ps_timeout = 32; +#endif /* PS_ENTRY_MAITENANCE */ + + + +#ifdef CFO_TRACK +#endif /* CFO_TRACK */ + +#ifdef DBG_CTRL_SUPPORT + pAd->CommonCfg.DebugFlags = 0; +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef WAPI_SUPPORT + pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE; + pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE; + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; +#endif /* WAPI_SUPPORT */ + +#ifdef MCAST_RATE_SPECIFIC + pAd->CommonCfg.MCastPhyMode.word = pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word; +#endif /* MCAST_RATE_SPECIFIC */ + + /* WFA policy - disallow TH rate in WEP or TKIP cipher */ + pAd->CommonCfg.HT_DisallowTKIP = TRUE; + + /* Frequency for rate adaptation */ + pAd->ra_interval = DEF_RA_TIME_INTRVAL; + pAd->ra_fast_interval = DEF_QUICK_RA_TIME_INTERVAL; + +#ifdef AGS_SUPPORT + if (pAd->rateAlg == RATE_ALG_AGS) + pAd->ra_fast_interval = AGS_QUICK_RA_TIME_INTERVAL; +#endif /* AGS_SUPPORT */ + + /* Tx Sw queue length setting */ + pAd->TxSwQMaxLen = MAX_PACKETS_IN_QUEUE; + +#ifdef DATA_QUEUE_RESERVE + pAd->TxRsvLen = FIFO_RSV_FOR_HIGH_PRIORITY; +#endif /* DATA_QUEUE_RESERVE */ + + pAd->CommonCfg.bRalinkBurstMode = FALSE; + +#ifdef CONFIG_STA_SUPPORT + /* part II. intialize STA specific configuration*/ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT); + RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST); + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST); + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST); + + pAd->StaCfg.Psm = PWR_ACTIVE; + + pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled; + pAd->StaCfg.bMixCipher = FALSE; + pAd->StaCfg.wdev.DefaultKeyId = 0; + + /* 802.1x port control*/ + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pAd->StaCfg.wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.LastMicErrorTime = 0; + pAd->StaCfg.MicErrCnt = 0; + pAd->StaCfg.bBlockAssoc = FALSE; + pAd->StaCfg.WpaState = SS_NOTUSE; + + pAd->CommonCfg.NdisRadioStateOff = FALSE; /* New to support microsoft disable radio with OID command*/ + + pAd->StaCfg.RssiTrigger = 0; + NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE)); + pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; + pAd->StaCfg.AtimWin = 0; + pAd->StaCfg.DefaultListenCount = 3;/*default listen count;*/ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + pAd->StaCfg.DefaultListenCount = 1; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + pAd->StaCfg.BssType = BSS_INFRA; /* BSS_INFRA or BSS_ADHOC or BSS_MONITOR*/ + pAd->StaCfg.bSkipAutoScanConn = FALSE; + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + + pAd->StaCfg.wdev.bAutoTxRateSwitch = TRUE; + pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->StaCfg.bAutoConnectIfNoSSID = FALSE; + } + +#ifdef EXT_BUILD_CHANNEL_LIST + pAd->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef RTMP_MAC_PCI + pAd->brt30xxBanMcuCmd = FALSE; + pAd->StaCfg.PSControl.field.EnableNewPS=FALSE; + +#ifdef PCIE_PS_SUPPORT + pAd->StaCfg.PSControl.field.EnableNewPS=TRUE; + pAd->b3090ESpecialChip = FALSE; + /*The value of PowerMode could be 1 or 3. Level 3 could save more power than Level 1. */ + pAd->StaCfg.PSControl.field.rt30xxPowerMode=3; + pAd->StaCfg.PSControl.field.rt30xxForceASPMTest=0; + pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM=1; + + if (IS_SUPPORT_PCIE_PS_L3(pAd)) + { + pAd->chipCap.HW_PCIE_PS_L3_ENABLE=TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Support PCIe PS3 \n")); + } +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_STA_SUPPORT */ + + /* global variables mXXXX used in MAC protocol state machines*/ + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + + /* PHY specification*/ + pAd->CommonCfg.PhyMode = (WMODE_B | WMODE_G); /* default PHY mode*/ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); /* CCK use LONG preamble*/ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* user desired power mode*/ + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.bWindowsACCAMEnable = FALSE; + + pAd->StaCfg.bHwRadio = TRUE; /* Default Hardware Radio status is On*/ + pAd->StaCfg.bSwRadio = TRUE; /* Default Software Radio status is On*/ + pAd->StaCfg.bRadio = TRUE; /* bHwRadio && bSwRadio*/ + pAd->StaCfg.bHardwareRadio = FALSE; /* Default is OFF*/ + pAd->StaCfg.bShowHiddenSSID = FALSE; /* Default no show*/ + + /* Nitro mode control*/ +#if defined(NATIVE_WPA_SUPPLICANT_SUPPORT) || defined(RT_CFG80211_SUPPORT) + pAd->StaCfg.bAutoReconnect = FALSE; +#else + pAd->StaCfg.bAutoReconnect = TRUE; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT || RT_CFG80211_SUPPORT*/ + + /* Save the init time as last scan time, the system should do scan after 2 seconds.*/ + /* This patch is for driver wake up from standby mode, system will do scan right away.*/ + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + if (pAd->StaCfg.LastScanTime > 10 * OS_HZ) + pAd->StaCfg.LastScanTime -= (10 * OS_HZ); + + NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1); +#ifdef PROFILE_STORE + pAd->bWriteDat = FALSE; +#endif /* PROFILE_STORE */ +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.wdev.IEEE8021X = FALSE; + pAd->StaCfg.wpa_supplicant_info.IEEE8021x_required_keys = FALSE; + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant = FALSE; + +#if defined(NATIVE_WPA_SUPPLICANT_SUPPORT) || defined(RT_CFG80211_SUPPORT) + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; +#ifdef PROFILE_STORE + pAd->bWriteDat = TRUE; +#endif /* PROFILE_STORE */ +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT || RT_CFG80211_SUPPORT */ + + pAd->StaCfg.wpa_supplicant_info.bLostAp = FALSE; + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe = NULL; + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen = 0; + pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe = NULL; + pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen = 0; + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantScanCount = 0; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + +#ifdef WSC_STA_SUPPORT + { + INT idx; + PWSC_CTRL pWscControl; +#ifdef WSC_V2_SUPPORT + PWSC_V2_INFO pWscV2Info; +#endif /* WSC_V2_SUPPORT */ + + /* + WscControl cannot be zero here, because WscControl timers are initial in MLME Initialize + and MLME Initialize is called before UserCfgInit. + */ + pWscControl = &pAd->StaCfg.WscControl; + pWscControl->WscConfMode = WSC_DISABLE; + pWscControl->WscMode = WSC_PIN_MODE; + pWscControl->WscConfStatus = WSC_SCSTATE_UNCONFIGURED; +#ifdef WSC_V2_SUPPORT + pWscControl->WscConfigMethods= 0x238C; +#else + pWscControl->WscConfigMethods= 0x008C; +#endif /* WSC_V2_SUPPORT */ + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_NOTUSED; + pWscControl->WscPinCode = 0; + pWscControl->WscLastPinFromEnrollee = 0; + pWscControl->WscEnrollee4digitPinCode = FALSE; + pWscControl->WscEnrolleePinCode = 0; + pWscControl->WscSelReg = 0; + NdisZeroMemory(&pAd->StaCfg.WscControl.RegData, sizeof(WSC_REG_DATA)); + NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE)); + pWscControl->WscUseUPnP = 0; + pWscControl->WscEnAssociateIE = TRUE; + pWscControl->WscEnProbeReqIE = TRUE; + pWscControl->RegData.ReComputePke = 1; + pWscControl->lastId = 1; + pWscControl->EntryIfIdx = BSS0; + pWscControl->pAd = pAd; + pWscControl->WscDriverAutoConnect = 0x02; + pAd->WriteWscCfgToDatFile = 0xFF; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + pWscControl->WpsApBand = PREFERRED_WPS_AP_PHY_TYPE_AUTO_SELECTION; + pWscControl->bCheckMultiByte = FALSE; + pWscControl->bWscAutoTigeer = FALSE; + /* Enrollee Nonce, first generate and save to Wsc Control Block*/ + for (idx = 0; idx < 16; idx++) + { + pWscControl->RegData.SelfNonce[idx] = RandomByte(pAd); + } + pWscControl->WscRxBufLen = 0; + pWscControl->pWscRxBuf = NULL; + os_alloc_mem(pAd, &pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + if (pWscControl->pWscRxBuf) + NdisZeroMemory(pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + pWscControl->WscTxBufLen = 0; + pWscControl->pWscTxBuf = NULL; + os_alloc_mem(pAd, &pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + if (pWscControl->pWscTxBuf) + NdisZeroMemory(pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + pWscControl->bWscFragment = FALSE; + pWscControl->WscFragSize = 128; + initList(&pWscControl->WscPeerList); + NdisAllocateSpinLock(pAd, &pWscControl->WscPeerListSemLock); + +#ifdef WSC_V2_SUPPORT + pWscV2Info = &pWscControl->WscV2Info; + pWscV2Info->bWpsEnable = TRUE; + pWscV2Info->ExtraTlv.TlvLen = 0; + pWscV2Info->ExtraTlv.TlvTag = 0; + pWscV2Info->ExtraTlv.pTlvData = NULL; + pWscV2Info->ExtraTlv.TlvType = TLV_ASCII; + pWscV2Info->bEnableWpsV2 = TRUE; + pWscV2Info->bForceSetAP = FALSE; +#endif /* WSC_V2_SUPPORT */ + + } +#ifdef IWSC_SUPPORT + IWSC_Init(pAd); +#endif /* IWSC_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + +#ifdef DOT11R_FT_SUPPORT + NdisZeroMemory(&pAd->StaCfg.Dot11RCommInfo, sizeof(DOT11R_CMN_STRUC)); +#endif /* DOT11R_FT_SUPPORT */ + + pAd->StaCfg.bAutoConnectByBssid = FALSE; + pAd->StaCfg.BeaconLostTime = BEACON_LOST_TIME; + NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + pAd->StaCfg.WpaPassPhraseLen = 0; + pAd->StaCfg.bAutoRoaming = FALSE; + pAd->StaCfg.bForceTxBurst = FALSE; + pAd->StaCfg.bNotFirstScan = FALSE; + pAd->StaCfg.bImprovedScan = FALSE; +#ifdef DOT11_N_SUPPORT + pAd->StaCfg.bAdhocN = TRUE; +#endif /* DOT11_N_SUPPORT */ + pAd->StaCfg.bFastConnect = FALSE; + pAd->StaCfg.bAdhocCreator = FALSE; + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Default for extra information is not valid*/ + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + + /* Default Config change flag*/ + pAd->bConfigChanged = FALSE; + + /* + part III. AP configurations + */ +#ifdef CONFIG_AP_SUPPORT +#if defined(P2P_APCLI_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_APCLI_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { + /* Set MBSS Default Configurations*/ + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + MULTISSID_STRUCT *mbss = &pAd->ApCfg.MBSSID[j]; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[j].wdev; + + mbss->AssocReqFailRssiThreshold = 0; + mbss->AssocReqNoRspRssiThreshold = 0; + mbss->AuthFailRssiThreshold = 0; + mbss->AuthNoRspRssiThreshold = 0; + mbss->RssiLowForStaKickOut = 0; + mbss->ProbeRspRssiThreshold = 0; + + mbss->StatTxRetryOkCount = 0; + mbss->StatTxFailCount = 0; + + wdev->AuthMode = Ndis802_11AuthModeOpen; + wdev->WepStatus = Ndis802_11EncryptionDisabled; + wdev->GroupKeyWepStatus = Ndis802_11EncryptionDisabled; + wdev->DefaultKeyId = 0; + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + mbss->RekeyCountDown = 0; /* it's used for WPA rekey */ + + mbss->ProbeRspTimes = 3; +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd) || IS_MT76x2(pAd)) + mbss->TxPwrAdj = -1; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +#ifdef DOT1X_SUPPORT + mbss->wdev.IEEE8021X = FALSE; + mbss->PreAuth = FALSE; + + /* PMK cache setting*/ + mbss->PMKCachePeriod = (10 * 60 * OS_HZ); /* unit : tick(default: 10 minute)*/ + NdisZeroMemory(&mbss->PMKIDCache, sizeof(NDIS_AP_802_11_PMKID)); + + /* dot1x related per BSS */ + mbss->radius_srv_num = 0; + mbss->NasIdLen = 0; +#endif /* DOT1X_SUPPORT */ + + /* VLAN related */ + mbss->wdev.VLAN_VID = 0; + + /* Default MCS as AUTO*/ + wdev->bAutoTxRateSwitch = TRUE; + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + + /* Default is zero. It means no limit.*/ + mbss->MaxStaNum = 0; + mbss->StaCount = 0; + +#ifdef WSC_AP_SUPPORT + mbss->WscSecurityMode = 0xff; + { + PWSC_CTRL pWscControl; + INT idx; +#ifdef WSC_V2_SUPPORT + PWSC_V2_INFO pWscV2Info; +#endif /* WSC_V2_SUPPORT */ + /* + WscControl cannot be zero here, because WscControl timers are initial in MLME Initialize + and MLME Initialize is called before UserCfgInit. + */ + pWscControl = &mbss->WscControl; + NdisZeroMemory(&pWscControl->RegData, sizeof(WSC_REG_DATA)); + NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); + pWscControl->WscMode = 1; + pWscControl->WscConfStatus = 1; +#ifdef WSC_V2_SUPPORT + pWscControl->WscConfigMethods= 0x238C; +#else + pWscControl->WscConfigMethods= 0x0084; +#endif /* WSC_V2_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + pWscControl->WscConfigMethods |= WPS_CONFIG_METHODS_ENT; +#endif /* WSC_NFC_SUPPORT */ + pWscControl->RegData.ReComputePke = 1; + pWscControl->lastId = 1; + /* pWscControl->EntryIfIdx = (MIN_NET_DEVICE_FOR_MBSSID | j); */ + pWscControl->pAd = pAd; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + pAd->CommonCfg.WscPBCOverlap = FALSE; + pWscControl->WscConfMode = 0; + pWscControl->WscStatus = 0; + pWscControl->WscState = 0; + pWscControl->WscPinCode = 0; + pWscControl->WscLastPinFromEnrollee = 0; + pWscControl->WscEnrollee4digitPinCode = FALSE; + pWscControl->WscEnrolleePinCode = 0; + pWscControl->WscSelReg = 0; + pWscControl->WscUseUPnP = 0; + pWscControl->bWCNTest = FALSE; + pWscControl->WscKeyASCII = 0; /* default, 0 (64 Hex) */ + + /* + Enrollee 192 random bytes for DH key generation + */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + + /* Enrollee Nonce, first generate and save to Wsc Control Block*/ + for (idx = 0; idx < 16; idx++) + pWscControl->RegData.SelfNonce[idx] = RandomByte(pAd); + + NdisZeroMemory(&pWscControl->WscDefaultSsid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(&pWscControl->Wsc_Uuid_Str[0], UUID_LEN_STR); + NdisZeroMemory(&pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX); + pWscControl->bCheckMultiByte = FALSE; + pWscControl->bWscAutoTigeer = FALSE; + pWscControl->bWscFragment = FALSE; + pWscControl->WscFragSize = 128; + pWscControl->WscRxBufLen = 0; + pWscControl->pWscRxBuf = NULL; + os_alloc_mem(pAd, &pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + if (pWscControl->pWscRxBuf) + NdisZeroMemory(pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + pWscControl->WscTxBufLen = 0; + pWscControl->pWscTxBuf = NULL; + os_alloc_mem(pAd, &pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + if (pWscControl->pWscTxBuf) + NdisZeroMemory(pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + initList(&pWscControl->WscPeerList); + NdisAllocateSpinLock(pAd, &pWscControl->WscPeerListSemLock); + pWscControl->PinAttackCount = 0; + pWscControl->bSetupLock = FALSE; + pWscControl->SetupLockTime = WSC_WPS_AP_SETUP_LOCK_TIME; + pWscControl->MaxPinAttack = WSC_WPS_AP_MAX_PIN_ATTACK; +#ifdef WSC_V2_SUPPORT + pWscV2Info = &pWscControl->WscV2Info; + pWscV2Info->bWpsEnable = TRUE; + pWscV2Info->ExtraTlv.TlvLen = 0; + pWscV2Info->ExtraTlv.TlvTag = 0; + pWscV2Info->ExtraTlv.pTlvData = NULL; + pWscV2Info->ExtraTlv.TlvType = TLV_ASCII; + pWscV2Info->bEnableWpsV2 = TRUE; +#ifdef WSC_NFC_SUPPORT + pWscControl->NfcPasswdCaculate = 2; +#endif /* WSC_NFC_SUPPORT */ + +#endif /* WSC_V2_SUPPORT */ + } +#endif /* WSC_AP_SUPPORT */ + + + for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++) + mbss->TimBitmaps[i] = 0; + } + pAd->ApCfg.DtimCount = 0; + pAd->ApCfg.DtimPeriod = DEFAULT_DTIM_PERIOD; + + pAd->ApCfg.ErpIeContent = 0; + + pAd->ApCfg.StaIdleTimeout = MAC_TABLE_AGEOUT_TIME; + +#ifdef IDS_SUPPORT + /* Default disable IDS threshold and reset all IDS counters*/ + pAd->ApCfg.IdsEnable = FALSE; + pAd->ApCfg.AuthFloodThreshold = 0; + pAd->ApCfg.AssocReqFloodThreshold = 0; + pAd->ApCfg.ReassocReqFloodThreshold = 0; + pAd->ApCfg.ProbeReqFloodThreshold = 0; + pAd->ApCfg.DisassocFloodThreshold = 0; + pAd->ApCfg.DeauthFloodThreshold = 0; + pAd->ApCfg.EapReqFloodThreshold = 0; + RTMPClearAllIdsCounter(pAd); +#endif /* IDS_SUPPORT */ + +#ifdef WDS_SUPPORT + APWdsInitialize(pAd); +#endif /* WDS_SUPPORT*/ + +#ifdef WSC_INCLUDED + pAd->WriteWscCfgToDatFile = 0xFF; + pAd->WriteWscCfgToAr9DatFile = FALSE; +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_RBUS_SUPPORT + pAd->bWscDriverAutoUpdateCfg = FALSE; +#else + pAd->bWscDriverAutoUpdateCfg = TRUE; +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef APCLI_SUPPORT + pAd->ApCfg.FlgApCliIsUapsdInfoUpdated = FALSE; + pAd->ApCfg.ApCliNum = MAX_APCLI_NUM; +#ifdef APCLI_CERT_SUPPORT + pAd->bApCliCertTest = FALSE; +#endif /* APCLI_CERT_SUPPORT */ + for(j = 0; j < MAX_APCLI_NUM; j++) + { + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[j]; + struct wifi_dev *wdev = &apcli_entry->wdev; + + wdev->AuthMode = Ndis802_11AuthModeOpen; + wdev->WepStatus = Ndis802_11WEPDisabled; + wdev->bAutoTxRateSwitch = TRUE; + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + apcli_entry->UapsdInfo.bAPSDCapable = FALSE; + apcli_entry->bPeerExist = FALSE; +#ifdef APCLI_CONNECTION_TRIAL + apcli_entry->TrialCh = 0;//if the channel is 0, AP will connect the rootap is in the same channel with ra0. +#endif /* APCLI_CONNECTION_TRIAL */ + +#ifdef WPA_SUPPLICANT_SUPPORT + apcli_entry->wdev.IEEE8021X=FALSE; + apcli_entry->wpa_supplicant_info.IEEE8021x_required_keys=FALSE; + apcli_entry->wpa_supplicant_info.bRSN_IE_FromWpaSupplicant=FALSE; + apcli_entry->wpa_supplicant_info.bLostAp=FALSE; + apcli_entry->bScanReqIsFromWebUI=FALSE; + apcli_entry->bConfigChanged=FALSE; + apcli_entry->wpa_supplicant_info.DesireSharedKeyId=0; + apcli_entry->wpa_supplicant_info.WpaSupplicantUP=WPA_SUPPLICANT_DISABLE; + apcli_entry->wpa_supplicant_info.WpaSupplicantScanCount=0; + apcli_entry->wpa_supplicant_info.pWpsProbeReqIe=NULL; + apcli_entry->wpa_supplicant_info.WpsProbeReqIeLen=0; + apcli_entry->wpa_supplicant_info.pWpaAssocIe=NULL; + apcli_entry->wpa_supplicant_info.WpaAssocIeLen=0; + apcli_entry->SavedPMKNum=0; + RTMPZeroMemory(apcli_entry->SavedPMK, (PMKID_NO * sizeof(BSSID_INFO))); +#endif/*WPA_SUPPLICANT_SUPPORT*/ +#ifdef APCLI_AUTO_CONNECT_SUPPORT + apcli_entry->ApCliSiteSurveyPeriod = 23; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + apcli_entry->bBlockAssoc=FALSE; + apcli_entry->MicErrCnt=0; + + apcli_entry->Valid = FALSE; + apcli_entry->CfgSsidLen = 0; + NdisZeroMemory(&(apcli_entry->CfgSsid), MAX_LEN_OF_SSID); + NdisZeroMemory(apcli_entry->CfgApCliBssid, MAC_ADDR_LEN); + NdisZeroMemory(apcli_entry->MlmeAux.Bssid, MAC_ADDR_LEN); + } +#endif /* APCLI_SUPPORT */ + pAd->ApCfg.EntryClientCount = 0; + pAd->ApCfg.ChangeTxOpClient = 0; + } + +#ifdef DYNAMIC_VGA_SUPPORT + if (IS_MT76x2(pAd)) { + pAd->CommonCfg.lna_vga_ctl.long_range_compensate_level = 0; + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = FALSE; + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = 800; + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh = 10; + } + +#ifdef RT6352 + if (IS_RT6352(pAd)) { + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = TRUE; + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = 600; + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh = 10; + } +#endif +#endif /* DYNAMIC_VGA_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef ETH_CONVERT_SUPPORT + if (pAd->OpMode == OPMODE_STA) + { + NdisZeroMemory(pAd->EthConvert.EthCloneMac, MAC_ADDR_LEN); + pAd->EthConvert.ECMode = ETH_CONVERT_MODE_DISABLE; + pAd->EthConvert.CloneMacVaild = FALSE; + /*pAd->EthConvert.nodeCount = 0;*/ + NdisZeroMemory(pAd->EthConvert.SSIDStr, MAX_LEN_OF_SSID); + pAd->EthConvert.SSIDStrLen = 0; + pAd->EthConvert.macAutoLearn = FALSE; + pAd->StaCfg.bFragFlag = TRUE; + } +#endif /* ETH_CONVERT_SUPPORT */ + +#ifdef IP_ASSEMBLY + if (pAd->OpMode == OPMODE_STA) + { + pAd->StaCfg.bFragFlag = TRUE; + } +#endif /* IP_ASSEMBLY */ + + /* + part IV. others + */ + + /* dynamic BBP R66:sensibity tuning to overcome background noise*/ + pAd->BbpTuning.bEnable = TRUE; + pAd->BbpTuning.FalseCcaLowerThreshold = 100; + pAd->BbpTuning.FalseCcaUpperThreshold = 512; + pAd->BbpTuning.R66Delta = 4; + pAd->Mlme.bEnableAutoAntennaCheck = TRUE; + + /* Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value.*/ + /* if not initial this value, the default value will be 0.*/ + pAd->BbpTuning.R66CurrentValue = 0x38; + +#ifdef RTMP_BBP + pAd->Bbp94 = BBPR94_DEFAULT; +#endif /* RTMP_BBP */ + pAd->BbpForCCK = FALSE; + + /* initialize MAC table and allocate spin lock*/ + NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + InitializeQueueHeader(&pAd->MacTab.McastPsQueue); + NdisAllocateSpinLock(pAd, &pAd->MacTabLock); + + /*RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE);*/ + /*RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV);*/ + + + pAd->CommonCfg.bWiFiTest = FALSE; + pAd->CommonCfg.bMcastTest = FALSE; +#ifdef RTMP_MAC_PCI + pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT; + +#ifdef DOT11R_FT_SUPPORT + FT_CfgInitial(pAd); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + pAd->StaCfg.TdlsInfo.bTDLSCapable = FALSE; + pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp = TRUE; + pAd->StaCfg.TdlsInfo.TdlsPsmSupp = FALSE; + pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime = TDLS_LEY_LIFETIME; +#ifdef TDLS_AUTOLINK_SUPPORT + initList(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList); + NdisAllocateSpinLock(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + initList(&pAd->StaCfg.TdlsInfo.TdlsBlackList); + NdisAllocateSpinLock(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + + pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold = TDLS_AUTO_SETUP_RSSI_THRESHOLD; + pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold = TDLS_AUTO_TEARDOWN_RSSI_THRESHOLD; + pAd->StaCfg.TdlsInfo.TdlsRssiMeasurementPeriod = TDLS_RSSI_MEASUREMENT_PERIOD; + pAd->StaCfg.TdlsInfo.TdlsDisabledPeriodByTeardown = TDLS_DISABLE_PERIOD_BY_TEARDOWN; + pAd->StaCfg.TdlsInfo.TdlsAutoDiscoveryPeriod = TDLS_AUTO_DISCOVERY_PERIOD; +#endif /* TDLS_AUTOLINK_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + + pAd->RxAnt.EvaluatePeriod = 0; + pAd->RxAnt.RcvPktNumWhenEvaluate = 0; +#ifdef CONFIG_STA_SUPPORT + pAd->RxAnt.Pair1AvgRssi[0] = pAd->RxAnt.Pair1AvgRssi[1] = 0; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + pAd->RxAnt.Pair1AvgRssiGroup1[0] = pAd->RxAnt.Pair1AvgRssiGroup1[1] = 0; + pAd->RxAnt.Pair1AvgRssiGroup2[0] = pAd->RxAnt.Pair1AvgRssiGroup2[1] = 0; +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef TXRX_SW_ANTDIV_SUPPORT + pAd->chipCap.bTxRxSwAntDiv = FALSE; +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + + +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) + { + BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[i]; + + if (pAd->ProbeRespIE[i].pIe) + pBssEntry->pVarIeFromProbRsp = pAd->ProbeRespIE[i].pIe; + else + pBssEntry->pVarIeFromProbRsp = NULL; + } +#endif /* defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ + + +#ifdef WSC_INCLUDED + NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); + pAd->CommonCfg.WscPBCOverlap = FALSE; +#endif /* WSC_INCLUDED */ + + +#ifdef RMTP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + VideoConfigInit(pAd); +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RMTP_RBUS_SUPPORT */ + + +#ifdef WFD_SUPPORT + WfdCfgInit(pAd); +#endif /* WFD_SUPPORT */ + + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + pAd->WOW_Cfg.bEnable = FALSE; + pAd->WOW_Cfg.bWOWFirmware = FALSE; /* load normal firmware */ + pAd->WOW_Cfg.bInBand = TRUE; /* use in-band signal */ + pAd->WOW_Cfg.nSelectedGPIO = 1; + pAd->WOW_Cfg.nDelay = 3; /* (3+1)*3 = 12 sec */ + pAd->WOW_Cfg.nHoldTime = 1; /* 1*10 = 10 ms */ + DBGPRINT(RT_DEBUG_OFF, ("WOW Enable %d, WOWFirmware %d\n", pAd->WOW_Cfg.bEnable, pAd->WOW_Cfg.bWOWFirmware)); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + + /* 802.11H and DFS related params*/ + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.CSPeriod = 10; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; +#endif + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pAd->Dot11_H.RDMode = RD_SILENCE_MODE; +#endif + + pAd->Dot11_H.ChMovingTime = 65; + pAd->Dot11_H.bDFSIndoor = 1; + + +#ifdef MAC_REPEATER_SUPPORT + for (i = 0; i < MAX_APCLI_NUM; i++) + { + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + NdisZeroMemory(pAd->ApCfg.ApCliTab[i].RepeaterCli[j].OriginalAddress, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CurrentAddress, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliConnectState = 0; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliEnable= FALSE; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliValid= FALSE; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].bEthCli = FALSE; + } + } + NdisAllocateSpinLock(pAd, &pAd->ApCfg.ReptCliEntryLock); + pAd->ApCfg.RepeaterCliSize = 0; + + NdisZeroMemory(&pAd->ApCfg.ReptControl, sizeof(REPEATER_CTRL_STRUCT)); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->ApCfg.bPartialScanning = FALSE; + pAd->ApCfg.PartialScanChannelNum = DEFLAUT_PARTIAL_SCAN_CH_NUM; + pAd->ApCfg.LastPartialScanChannel = 0; + pAd->ApCfg.PartialScanBreakTime = 0; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#ifdef SMART_MESH + pAd->ApCfg.ScanTime = 0; +#endif /* SMART_MESH */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) { + pAd->Tx0_DPD_ALC_tag0 = 0; + pAd->Tx0_DPD_ALC_tag1 = 0; + pAd->Tx1_DPD_ALC_tag0 = 0; + pAd->Tx1_DPD_ALC_tag1 = 0; + pAd->Tx0_DPD_ALC_tag0_flag = 0x0; + pAd->Tx0_DPD_ALC_tag1_flag = 0x0; + pAd->Tx1_DPD_ALC_tag0_flag = 0x0; + pAd->Tx1_DPD_ALC_tag1_flag = 0x0; + } +#endif /* RT6352 */ + +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectRunning= FALSE; + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + pAd->fpga_ctl.fpga_on = 0x0; + pAd->fpga_ctl.tx_kick_cnt = 0; + pAd->fpga_ctl.tx_data_phy = 0; + pAd->fpga_ctl.tx_data_ldpc = 0; + pAd->fpga_ctl.tx_data_mcs = 0; + pAd->fpga_ctl.tx_data_bw = 0; + pAd->fpga_ctl.tx_data_gi = 0; + pAd->fpga_ctl.rx_data_phy = 0; + pAd->fpga_ctl.rx_data_ldpc = 0; + pAd->fpga_ctl.rx_data_mcs = 0; + pAd->fpga_ctl.rx_data_bw = 0; + pAd->fpga_ctl.rx_data_gi = 0; +#ifdef CAPTURE_MODE + pAd->fpga_ctl.cap_type = 2; /* CAP_MODE_ADC8; */ + pAd->fpga_ctl.cap_trigger = 2; /* CAP_TRIGGER_AUTO; */ + pAd->fpga_ctl.trigger_offset = 200; + pAd->fpga_ctl.cap_support = 0; +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MICROWAVE_OVEN_SUPPORT + if (pAd->OpMode == OPMODE_AP) + pAd->CommonCfg.MO_Cfg.bEnable = TRUE; + else + pAd->CommonCfg.MO_Cfg.bEnable = FALSE; + pAd->CommonCfg.MO_Cfg.nFalseCCATh = MO_FALSE_CCA_TH; +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef RT6352 + pAd->CommonCfg.bEnTemperatureTrack = FALSE; +#endif /* RT6352 */ + + +#ifdef DOT11_VHT_AC + pAd->CommonCfg.bNonVhtDisallow = FALSE; +#endif /* DOT11_VHT_AC */ + + + + pAd->ed_chk = FALSE; //let country region to turn on +#ifdef ED_MONITOR + pAd->ed_learning_time_threshold = 50; //5 sec + pAd->ed_debug = FALSE; + +#ifdef CONFIG_AP_SUPPORT + pAd->ed_sta_threshold = 1; + pAd->ed_ap_threshold = 1; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + pAd->ed_ap_scaned = 5; + pAd->ed_current_ch_aps = 1; +#endif /* CONFIG_STA_SUPPORT */ + //change to common part + pAd->ed_rssi_threshold = -80; + + pAd->ed_chk_period = 100; + pAd->ed_threshold = 90; + pAd->ed_false_cca_threshold = 180; + pAd->ed_block_tx_threshold = 2; +#endif /* ED_MONITOR */ + +#ifdef CONFIG_SNIFFER_SUPPORT + pAd->monitor_ctrl.current_monitor_mode = 0; +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT + pAd->PDMAWatchDogEn = 0; + pAd->PDMAWatchDogDbg = 0 ; + pAd->TxDMACheckTimes = 0; + pAd->RxDMACheckTimes = 0; + pAd->TxDMAResetCount = 0; + pAd->RxDMAResetCount = 0; +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + + pAd->CommonCfg.ManualTxopThreshold = 10; // Mbps + pAd->CommonCfg.ManualTxopUpBound = 15; // Ratio + pAd->CommonCfg.ManualTxopLowBound = 5; // Ratio + + DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); +} + + +/* IRQL = PASSIVE_LEVEL*/ +UCHAR BtoH(STRING ch) +{ + if (ch >= '0' && ch <= '9') return (ch - '0'); /* Handle numerals*/ + if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); /* Handle capitol hex digits*/ + if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); /* Handle small hex digits*/ + return(255); +} + + +/* + FUNCTION: AtoH(char *, UCHAR *, int) + + PURPOSE: Converts ascii string to network order hex + + PARAMETERS: + src - pointer to input ascii string + dest - pointer to output hex + srclen - size of src + + COMMENTS: + + 2 ascii bytes make a hex byte so must put 1st ascii byte of pair + into upper nibble and 2nd ascii byte of pair into lower nibble. + + IRQL = PASSIVE_LEVEL +*/ +VOID AtoH(PSTRING src, PUCHAR dest, INT srclen) +{ + PSTRING srcptr; + PUCHAR destTemp; + + srcptr = src; + destTemp = (PUCHAR) dest; + + while(srclen--) + { + *destTemp = BtoH(*srcptr++) << 4; /* Put 1st ascii byte in upper nibble.*/ + *destTemp += BtoH(*srcptr++); /* Add 2nd ascii byte to above.*/ + destTemp++; + } +} + + +/* +======================================================================== +Routine Description: + Add a timer to the timer list. + +Arguments: + pAd - WLAN control block pointer + pRsc - the OS resource + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_TimerListAdd(RTMP_ADAPTER *pAd, VOID *pRsc) +{ + LIST_HEADER *pRscList = &pAd->RscTimerCreateList; + LIST_RESOURCE_OBJ_ENTRY *pObj; + + + /* try to find old entry */ + pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead); + while(1) + { + if (pObj == NULL) + break; + if ((ULONG)(pObj->pRscObj) == (ULONG)pRsc) + return; /* exists */ + pObj = pObj->pNext; + } + + /* allocate a timer record entry */ + os_alloc_mem(NULL, (UCHAR **)&(pObj), sizeof(LIST_RESOURCE_OBJ_ENTRY)); + if (pObj == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc timer obj fail!\n", __FUNCTION__)); + return; + } + else + { + pObj->pRscObj = pRsc; + insertTailList(pRscList, (LIST_ENTRY *)pObj); + } +} + +VOID RTMP_TimerListRelease(RTMP_ADAPTER *pAd, VOID *pRsc) +{ + LIST_HEADER *pRscList = &pAd->RscTimerCreateList; + LIST_RESOURCE_OBJ_ENTRY *pObj; + LIST_ENTRY *pListEntry; + + pListEntry = pRscList->pHead; + pObj = (LIST_RESOURCE_OBJ_ENTRY *)pListEntry; + + while (pObj) + { + if ((ULONG)(pObj->pRscObj) == (ULONG)pRsc) + { + pListEntry = (LIST_ENTRY *)pObj; + break; + } + + pListEntry = pListEntry->pNext; + pObj = (LIST_RESOURCE_OBJ_ENTRY *)pListEntry; + } + + if (pListEntry) + { + delEntryList(pRscList, pListEntry); + + /* free a timer record entry */ + DBGPRINT(RT_DEBUG_LOUD, ("%s: release timer obj %lx!\n", __FUNCTION__, (ULONG)pRsc)); + os_free_mem(NULL, pObj); + } +} + +/* +======================================================================== +Routine Description: + Cancel all timers in the timer list. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_AllTimerListRelease(RTMP_ADAPTER *pAd) +{ + LIST_HEADER *pRscList = &pAd->RscTimerCreateList; + LIST_RESOURCE_OBJ_ENTRY *pObj, *pObjOld; + BOOLEAN Cancel; + + /* try to find old entry */ + pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead); + while(1) + { + if (pObj == NULL) + break; + DBGPRINT(RT_DEBUG_LOUD, ("%s: Cancel timer obj %lx!\n", __FUNCTION__, (ULONG)(pObj->pRscObj))); + pObjOld = pObj; + pObj = pObj->pNext; + RTMPReleaseTimer(pObjOld->pRscObj, &Cancel); + + //TODO: It will casued kernel panic on reboot + //os_free_mem(NULL, pObjOld); + } + + /* reset TimerList */ + initList(&pAd->RscTimerCreateList); +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pAd Pointer to our adapter + pTimer Timer structure + pTimerFunc Function to execute when timer expired + Repeat Ture for period timer + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitTimer( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer, + IN VOID *pTimerFunc, + IN VOID *pData, + IN BOOLEAN Repeat) +{ + RTMP_SEM_LOCK(&TimerSemLock); + + RTMP_TimerListAdd(pAd, pTimer); + + + /* Set Valid to TRUE for later used.*/ + /* It will crash if we cancel a timer or set a timer */ + /* that we haven't initialize before.*/ + /* */ + pTimer->Valid = TRUE; + + pTimer->PeriodicType = Repeat; + pTimer->State = FALSE; + pTimer->cookie = (ULONG) pData; + pTimer->pAd = pAd; + + RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer, &pAd->RscTimerMemList); + DBGPRINT(RT_DEBUG_LOUD,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPSetTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value) +{ + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + RTMP_ADAPTER *pAd; + + pAd = (RTMP_ADAPTER *)pTimer->pAd; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT_ERR(("RTMPSetTimer failed, Halt in Progress!\n")); + RTMP_SEM_UNLOCK(&TimerSemLock); + return; + } + + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + pTimer->Repeat = TRUE; + RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); + } + else + { + pTimer->Repeat = FALSE; + RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); + } + + DBGPRINT(RT_DEBUG_LOUD,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n")); + } + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPModTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value) +{ + BOOLEAN Cancel; + + + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + RTMP_SEM_UNLOCK(&TimerSemLock); + RTMPCancelTimer(pTimer, &Cancel); + RTMPSetTimer(pTimer, Value); + } + else + { + RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); + RTMP_SEM_UNLOCK(&TimerSemLock); + } + DBGPRINT(RT_DEBUG_LOUD,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n")); + RTMP_SEM_UNLOCK(&TimerSemLock); + } +} + + +/* + ======================================================================== + + Routine Description: + Cancel timer objects + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + 1.) To use this routine, must call RTMPInitTimer before. + 2.) Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPCancelTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled) +{ + // TODO: shiang-usw, check the purpose of this SemLock! + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + if (pTimer->State == FALSE) + pTimer->Repeat = FALSE; + + RTMP_SEM_UNLOCK(&TimerSemLock); + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + RTMP_SEM_LOCK(&TimerSemLock); + + if (*pCancelled == TRUE) + pTimer->State = TRUE; + +#ifdef RTMP_TIMER_TASK_SUPPORT + /* We need to go-through the TimerQ to findout this timer handler and remove it if */ + /* it's still waiting for execution.*/ + RtmpTimerQRemove(pTimer->pAd, pTimer); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + + DBGPRINT(RT_DEBUG_LOUD,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + DBGPRINT(RT_DEBUG_INFO,("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); + } + + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +VOID RTMPReleaseTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled) +{ + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + if (pTimer->State == FALSE) + pTimer->Repeat = FALSE; + + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + + if (*pCancelled == TRUE) + pTimer->State = TRUE; + +#ifdef RTMP_TIMER_TASK_SUPPORT + /* We need to go-through the TimerQ to findout this timer handler and remove it if */ + /* it's still waiting for execution.*/ + RtmpTimerQRemove(pTimer->pAd, pTimer); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + + /* release timer */ + RTMP_OS_Release_Timer(&pTimer->TimerObj); + + pTimer->Valid = FALSE; + + RTMP_TimerListRelease(pTimer->pAd, pTimer); + + DBGPRINT(RT_DEBUG_LOUD,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + DBGPRINT(RT_DEBUG_INFO,("RTMPReleasefailed, Timer hasn't been initialize!\n")); + } + + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +/* + ======================================================================== + + Routine Description: + Enable RX + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL <= DISPATCH_LEVEL + + Note: + Before Enable RX, make sure you have enabled Interrupt. + ======================================================================== +*/ +VOID RTMPEnableRxTx(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); + + RT28XXDMAEnable(pAd); + + AsicSetRxFilter(pAd); + + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); +//+++Add by shiang for debug for pbf_loopback +// RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2c); +//---Add by shiang for debug +//+++Add by shiang for debug invalid RxWI->WCID +#ifdef RT8592 +#endif /* RT8592 */ +//---Add by shiang for debug invalid RxWI->WCID + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); +} + + +void CfgInitHook(RTMP_ADAPTER *pAd) +{ + /*pAd->bBroadComHT = TRUE;*/ +} + + +static INT RtmpChipOpsRegister(RTMP_ADAPTER *pAd, INT infType) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + int ret = 0; + + NdisZeroMemory(pChipOps, sizeof(RTMP_CHIP_OP)); + NdisZeroMemory(&pAd->chipCap, sizeof(RTMP_CHIP_CAP)); + + ret = RtmpChipOpsHook(pAd); + + if (ret) { + DBGPRINT(RT_DEBUG_ERROR, ("chipOps hook error\n")); + return ret; + } + + /* MCU related */ + ChipOpsMCUHook(pAd, pAd->chipCap.MCUType); + + get_dev_config_idx(pAd); + + /* set eeprom related hook functions */ + ret = RtmpChipOpsEepromHook(pAd, infType); + + return ret; +} + + + + +INT RtmpRaDevCtrlInit(VOID *pAdSrc, RTMP_INF_TYPE infType) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)pAdSrc; + + /* Assign the interface type. We need use it when do register/EEPROM access.*/ + pAd->infType = infType; + +#ifdef CONFIG_STA_SUPPORT + pAd->OpMode = OPMODE_STA; + printk("%s STA Driver version: %s\n", "MT76x2", STA_DRIVER_VERSION); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + pAd->OpMode = OPMODE_AP; + printk("%s AP Driver version: %s\n", "MT76x2", AP_DRIVER_VERSION); +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("pAd->infType=%d\n", pAd->infType)); + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + pAd->OpMode = OPMODE_STA; +#endif /* P2P_SUPPORT */ + +#ifdef MULTIPLE_CARD_SUPPORT +#ifdef RTMP_FLASH_SUPPORT +/* if ((IS_PCIE_INF(pAd))) */ + { + /* specific for RT6855/RT6856 */ + pAd->E2P_OFFSET_IN_FLASH[0] = 0x40000; + pAd->E2P_OFFSET_IN_FLASH[1] = 0x48000; + } +#endif /* RTMP_FLASH_SUPPORT */ +#endif /* MULTIPLE_CARD_SUPPORT */ + + if (RtmpChipOpsRegister(pAd, infType)) + return FALSE; + + +#ifdef MULTIPLE_CARD_SUPPORT +{ + extern BOOLEAN RTMP_CardInfoRead(PRTMP_ADAPTER pAd); + + /* find its profile path*/ + pAd->MC_RowID = -1; /* use default profile path*/ + RTMP_CardInfoRead(pAd); + + if (pAd->MC_RowID == -1) +#ifdef CONFIG_AP_SUPPORT + strcpy(pAd->MC_FileName, AP_PROFILE_PATH); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + strcpy(pAd->MC_FileName, STA_PROFILE_PATH); +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName)); +} +#endif /* MULTIPLE_CARD_SUPPORT */ + + +#ifdef MCS_LUT_SUPPORT + if (pAd->chipCap.asic_caps & fASIC_CAP_MCS_LUT) { + if (MAX_LEN_OF_MAC_TABLE <= 128) { + RTMP_SET_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT); + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s(): MCS_LUT not used becasue MacTb size(%d) > 128!\n", + __FUNCTION__, MAX_LEN_OF_MAC_TABLE)); + } + } +#endif /* MCS_LUT_SUPPORT */ + return 0; +} + + +BOOLEAN RtmpRaDevCtrlExit(IN VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + INT index; + +#ifdef MULTIPLE_CARD_SUPPORT +extern UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD]; + + if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD)) + MC_CardUsed[pAd->MC_RowID] = 0; /* not clear MAC address*/ +#endif /* MULTIPLE_CARD_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef CREDENTIAL_STORE + NdisFreeSpinLock(&pAd->StaCtIf.Lock); +#endif /* CREDENTIAL_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RLT_MAC + if ((IS_MT76x0(pAd) || IS_MT76x2(pAd))&& (pAd->WlanFunCtrl.field.WLAN_EN == 1)) + { + rlt_wlan_chip_onoff(pAd, FALSE, FALSE); + } +#endif /* RLT_MAC */ + + + /* + Free ProbeRespIE Table + */ + for (index = 0; index < MAX_LEN_OF_BSS_TABLE; index++) + { + if (pAd->ProbeRespIE[index].pIe) + os_free_mem(pAd, pAd->ProbeRespIE[index].pIe); + } + +#ifdef RESOURCE_PRE_ALLOC + RTMPFreeTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + + RTMPFreeAdapter(pAd); + + return TRUE; +} + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID RTMP_11N_D3_TimerInit(RTMP_ADAPTER *pAd) +{ + RTMPInitTimer(pAd, &pAd->CommonCfg.Bss2040CoexistTimer, GET_TIMER_FUNCTION(Bss2040CoexistTimeOut), pAd, FALSE); +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef VENDOR_FEATURE3_SUPPORT +VOID RTMP_IO_WRITE32( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT32 Value) +{ + _RTMP_IO_WRITE32(pAd, Offset, Value); +} +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +#ifdef RTMP_MAC_PCI +VOID CMDHandler(RTMP_ADAPTER *pAd) +{ + PCmdQElmt cmdqelmt; + UCHAR *pData; + + while (pAd && pAd->CmdQ.size > 0) + { + NdisAcquireSpinLock(&pAd->CmdQLock); + RTThreadDequeueCmd(&pAd->CmdQ, &cmdqelmt); + NdisReleaseSpinLock(&pAd->CmdQLock); + + if (cmdqelmt == NULL) + break; + + pData = cmdqelmt->buffer; + ASSERT(pData != NULL); + + if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) + { + switch (cmdqelmt->command) + { +#ifdef CONFIG_AP_SUPPORT + case CMDTHREAD_CHAN_RESCAN: + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Re-scan channel! \n")); + + pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, ChannelAlgCCA); + +#ifdef DOT11_N_SUPPORT + /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */ + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Switch to %d! \n", pAd->CommonCfg.Channel)); + APStop(pAd); + APStartUp(pAd); + +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadAlarmResume(pAd); +#endif /* AP_QLOAD_SUPPORT */ + break; +#endif /* CONFIG_AP_SUPPORT */ + + case CMDTHREAD_REG_HINT: +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_CRDA_REG_HINT(pAd, pData, cmdqelmt->bufferlength); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + break; + + case CMDTHREAD_REG_HINT_11D: +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_CRDA_REG_HINT11D(pAd, pData, cmdqelmt->bufferlength); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + break; + + case CMDTHREAD_SCAN_END: +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_SCAN_END(pAd, FALSE); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + break; + + case CMDTHREAD_CONNECT_RESULT_INFORM: +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_CONN_RESULT_INFORM(pAd, + pAd->MlmeAux.Bssid, + pData, cmdqelmt->bufferlength, + pData, cmdqelmt->bufferlength, + 1); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); + break; + } + } + + if (cmdqelmt->CmdFromNdis == TRUE) + { + if (cmdqelmt->buffer != NULL) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } + else + { + if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } + } +} +#endif /* RTMP_MAC_PCI */ + + +VOID AntCfgInit(RTMP_ADAPTER *pAd) +{ + + +#ifdef TXRX_SW_ANTDIV_SUPPORT + /* EEPROM 0x34[15:12] = 0xF is invalid, 0x2~0x3 is TX/RX SW AntDiv */ + DBGPRINT(RT_DEBUG_OFF, ("%s: bTxRxSwAntDiv %d\n", __FUNCTION__, pAd->chipCap.bTxRxSwAntDiv)); + if (pAd->chipCap.bTxRxSwAntDiv) + { + DBGPRINT(RT_DEBUG_OFF, ("Antenna word %X/%d, AntDiv %d\n", + pAd->Antenna.word, pAd->Antenna.field.BoardType, pAd->NicConfig2.field.AntDiversity)); + } +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + + { + if (pAd->NicConfig2.field.AntOpt== 1) /* ant selected by efuse */ + { + if (pAd->NicConfig2.field.AntDiversity == 0) /* main */ + { + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + } + else/* aux */ + { + pAd->RxAnt.Pair1PrimaryRxAnt = 1; + pAd->RxAnt.Pair1SecondaryRxAnt = 0; + } + } + else if (pAd->NicConfig2.field.AntDiversity == 0) /* Ant div off: default ant is main */ + { + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + } + else if (pAd->NicConfig2.field.AntDiversity == 1)/* Ant div on */ + {/* eeprom on, but sw ant div support is not enabled: default ant is main */ + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + } + } + + DBGPRINT(RT_DEBUG_OFF, ("%s: primary/secondary ant %d/%d\n", + __FUNCTION__, + pAd->RxAnt.Pair1PrimaryRxAnt, + pAd->RxAnt.Pair1SecondaryRxAnt)); +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_init_inf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_init_inf.c new file mode 100644 index 000000000..a55b32b8a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_init_inf.c @@ -0,0 +1,1688 @@ +/* + *************************************************************************** + * 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_init_inf.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PROFILE_STORE +NDIS_STATUS WriteDatThread(RTMP_ADAPTER *pAd); +#endif /* PROFILE_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef LINUX +#ifdef OS_ABL_FUNC_SUPPORT +/* Utilities provided from NET module */ +RTMP_NET_ABL_OPS RtmpDrvNetOps, *pRtmpDrvNetOps = &RtmpDrvNetOps; +RTMP_PCI_CONFIG RtmpPciConfig, *pRtmpPciConfig = &RtmpPciConfig; +RTMP_USB_CONFIG RtmpUsbConfig, *pRtmpUsbConfig = &RtmpUsbConfig; + +VOID RtmpDrvOpsInit( + OUT VOID *pDrvOpsOrg, + INOUT VOID *pDrvNetOpsOrg, + IN RTMP_PCI_CONFIG *pPciConfig, + IN RTMP_USB_CONFIG *pUsbConfig) +{ + RTMP_DRV_ABL_OPS *pDrvOps = (RTMP_DRV_ABL_OPS *)pDrvOpsOrg; + + + /* init PCI/USB configuration in different OS */ + if (pPciConfig != NULL) + RtmpPciConfig = *pPciConfig; + + if (pUsbConfig != NULL) + RtmpUsbConfig = *pUsbConfig; + + /* init operators provided from us (DRIVER module) */ + pDrvOps->RTMPAllocAdapterBlock = RTMPAllocAdapterBlock; + pDrvOps->RTMPFreeAdapter = RTMPFreeAdapter; + + pDrvOps->RtmpRaDevCtrlExit = RtmpRaDevCtrlExit; + pDrvOps->RtmpRaDevCtrlInit = RtmpRaDevCtrlInit; +#ifdef RTMP_MAC_PCI + pDrvOps->RTMPHandleInterrupt = RTMPHandleInterrupt; +#endif /* RTMP_MAC_PCI */ + pDrvOps->RTMPSendPackets = RTMPSendPackets; + + pDrvOps->RTMP_COM_IoctlHandle = RTMP_COM_IoctlHandle; +#ifdef CONFIG_AP_SUPPORT + pDrvOps->RTMP_AP_IoctlHandle = RTMP_AP_IoctlHandle; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + pDrvOps->RTMP_STA_IoctlHandle = RTMP_STA_IoctlHandle; +#endif /* CONFIG_STA_SUPPORT */ + + pDrvOps->RTMPDrvOpen = RTMPDrvOpen; + pDrvOps->RTMPDrvClose = RTMPDrvClose; + pDrvOps->RTMPInfClose = RTMPInfClose; + pDrvOps->rt28xx_init = rt28xx_init; + + /* init operators provided from us and netif module */ +} + +RTMP_BUILD_DRV_OPS_FUNCTION_BODY + +#endif /* OS_ABL_FUNC_SUPPORT */ +#endif /* LINUX */ + + +int rt28xx_init(VOID *pAdSrc, PSTRING pDefaultMac, PSTRING pHostName) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + NDIS_STATUS Status; + + if (!pAd) + return FALSE; + + if (rtmp_asic_top_init(pAd) != TRUE) + goto err1; + + DBGPRINT(RT_DEBUG_TRACE, ("MAC[Ver:Rev=0x%08x : 0x%08x]\n", + pAd->MACVersion, pAd->ChipID)); + + RT28XXDMADisable(pAd); + + if (mcu_sys_init(pAd) != TRUE) + goto err1; + +#ifdef RTMP_MAC_PCI + // TODO: shiang-usw, need to check this for RTMP_MAC + /* Disable interrupts here which is as soon as possible*/ + /* This statement should never be true. We might consider to remove it later*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } +#endif /* RTMP_MAC_PCI */ + + /* reset Adapter flags*/ + RTMP_CLEAR_FLAGS(pAd); + + if (MAX_LEN_OF_MAC_TABLE > MAX_AVAILABLE_CLIENT_WCID(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!!\n")); + goto err1; + } + +#ifdef CONFIG_AP_SUPPORT + /* Init BssTab & ChannelInfo tabbles for auto channel select.*/ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + AutoChBssTableInit(pAd); + ChannelInfoInit(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + /* init rate multiplication and shift factor table */ + InitRateMultiplicationAndShiftFactor(pAd); +#endif + +#ifdef DOT11_N_SUPPORT + /* Allocate BA Reordering memory*/ + if (ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM) != TRUE) + goto err1; +#endif /* DOT11_N_SUPPORT */ + +#ifdef RESOURCE_PRE_ALLOC + Status = RTMPInitTxRxRingMemory(pAd); +#else + Status = RTMPAllocTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("RTMPAllocTxRxMemory failed, Status[=0x%08x]\n", Status)); + goto err2; + } + + +#ifdef WLAN_SKB_RECYCLE + skb_queue_head_init(&pAd->rx0_recycle); +#endif /* WLAN_SKB_RECYCLE */ + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + /* initialize MLME*/ +#ifdef RT6352 + if (IS_RT6352(pAd)) + pAd->bCalibrationDone = FALSE; +#endif /* RT6352 */ + + Status = RtmpMgmtTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err3; + + Status = MlmeInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); + goto err4; + } + + /* Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default*/ + UserCfgInit(pAd); + + + Status = RtmpNetTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err5; + + CfgInitHook(pAd); + +#ifdef BLOCK_NET_IF + initblockQueueTab(pAd); +#endif /* BLOCK_NET_IF */ + + Status = MeasureReqTabInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("MeasureReqTabInit failed, Status[=0x%08x]\n",Status)); + goto err6; + } + Status = TpcReqTabInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("TpcReqTabInit failed, Status[=0x%08x]\n",Status)); + goto err6; + } + + /* + WiFi system operation mode setting base on following partitions: + 1. Parameters from config file + 2. Hardware cap from EEPROM + 3. Chip capabilities in code + */ + pAd->RfIcType = RFIC_UNKNOWN; + Status = RTMPReadParametersHook(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("RTMPReadParametersHook failed, Status[=0x%08x]\n",Status)); + goto err6; + } + DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + if (pAd->CommonCfg.bMcastTest == TRUE) + { + UINT32 macValue; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &macValue); + macValue = (macValue | 0x2); + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, macValue); + } + else + { +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + RTMP_IO_READ32(pAd, PBF_CFG, &macValue); + macValue = (macValue | 0x8); + RTMP_IO_WRITE32(pAd, PBF_CFG, macValue); + } +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + } +#endif /* RLT_MAC */ + } + + /* We should read EEPROM for all cases */ + NICReadEEPROMParameters(pAd, (PSTRING)pDefaultMac); +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; + + if ( NdisEqualMemory(&pAd->EthConvert.EthCloneMac[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN)) + { + NdisMoveMemory(&pAd->EthConvert.EthCloneMac[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_OFF, ("Read EEPROM, EthCloneMac is %02x:%02x:%02x:%02x:%02x:%02x!\n", + PRINT_MAC(pAd->EthConvert.EthCloneMac))); + } + } +#endif /* ETH_CONVERT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + /* After operation mode is finialized, init the AP or STA mode */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APInitialize(pAd); + +#ifdef DOT11K_RRM_SUPPORT + RRM_CfgInit(pAd); +#endif /* DOT11K_RRM_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { + STAInitialize(pAd); + +#ifdef CREDENTIAL_STORE + RecoverConnectInfo(pAd); +#endif /* CREDENTIAL_STORE */ + } +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + /*Init Ba Capability parameters.*/ + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + /* UPdata to HT IE*/ + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; +#endif /* DOT11_N_SUPPORT */ + + /* after reading Registry, we now know if in AP mode or STA mode */ + DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + + /* + All settle down, now it's time to init asic related parameters + */ + /* Init the hardware, we need to init asic before read registry, otherwise mac register will be reset */ + Status = NICInitializeAdapter(pAd, TRUE); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); + if (Status != NDIS_STATUS_SUCCESS) + goto err6; + } + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + cap_mode_init(pAd); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + + NICInitAsicFromEEPROM(pAd); + +#ifdef LED_CONTROL_SUPPORT + /* Send LED Setting to MCU */ + RTMPInitLEDMode(pAd); +#endif /* LED_CONTROL_SUPPORT */ + + + /* + Do necessary calibration after ASIC initialized + this's chip variant and may different for different chips + */ +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + RtmpKickOutHwNullFrame(pAd, TRUE, FALSE); + +#if defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) + { + ULONG SysRegValue; + + RTMP_SYS_IO_READ32(0xb0000060, &SysRegValue); + if ((SysRegValue & 0x100000) == 0x0) + { + SysRegValue |= 0x100000; + RTMP_SYS_IO_WRITE32(0xb0000060, SysRegValue); + DBGPRINT(RT_DEBUG_ERROR,("Change as GPIO Mode(0x%x)\n", SysRegValue)); + } + } +#endif /* defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) */ + + /* Do R-Calibration */ + R_Calibration(pAd); + +#ifdef RTMP_TEMPERATURE_CALIBRATION + /* Temperature Init */ + RT6352_Temperature_Init(pAd); + RT6352_TemperatureCalibration(pAd); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION + /* + read out tempature reference value (0x80 ~ 0x7F) + TssiPlusBoundaryG [7] [6] [5] [4] [3] [2] [1] [0] (smaller) + + TssiMinusBoundaryG[0] [1] [2] [3] [4] [5] [6] [7] (larger) + */ + RT6352_EEPROM_TSSI_24G_READ(pAd); + /* + pAd->TssiCalibratedOffset: + reference temperature(e2p[D1h]) + */ + /* adjust the boundary table by pAd->TssiCalibratedOffset */ + RT6352_TssiTableAdjust(pAd); + + /* ATE temperature(e2p[77h]) */ + RT6352_TssiMpAdjust(pAd); + + DBGPRINT(RT_DEBUG_OFF,("E2PROM: G Tssi[-7 .. +7] = %d %d %d %d %d %d %d - %d - %d %d %d %d %d %d %d, offset=%d, tuning=%d\n", + pAd->TssiMinusBoundaryG[7], pAd->TssiMinusBoundaryG[6], pAd->TssiMinusBoundaryG[5], + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TssiPlusBoundaryG[5], pAd->TssiPlusBoundaryG[6], pAd->TssiPlusBoundaryG[7], + pAd->TssiCalibratedOffset, pAd->bAutoTxAgcG)); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, TRUE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + /* RF Self TX DC Calibration */ + RF_SELF_TXDC_CAL(pAd); + + /* Rx DCOC Calibration */ + RxDCOC_Calibration(pAd); + + /* BandWidth Filter Calibration */ + BW_Filter_Calibration(pAd,TRUE); + BW_Filter_Calibration(pAd,FALSE); + + /* Do LOFT and IQ Calibration */ + LOFT_IQ_Calibration(pAd); + + /* DPD_Calibration */ +#ifdef RT6352_EP_SUPPORT + if (pAd->bExtPA == FALSE) +#endif /* RT6352_EP_SUPPORT */ + { + DoDPDCalibration(pAd); + pAd->DoDPDCurrTemperature = 0x7FFFFFFF; + } + + /* Rx DCOC Calibration */ + RxDCOC_Calibration(pAd); + + /* Do RXIQ Calibration */ + RXIQ_Calibration(pAd); + +#if defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) + RT6352_Init_ExtPA_ExtLNA(pAd, FALSE); +#endif /* defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) */ + } +#endif /* RT6352 */ + +#ifdef RALINK_ATE + if (ATEInit(pAd) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): ATE initialization failed !\n", __FUNCTION__)); + goto err6; + } +#endif /* RALINK_ATE */ + + +#ifdef RTMP_INTERNAL_TX_ALC + /* Initialize the desired TSSI table*/ + RTMP_CHIP_ASIC_TSSI_TABLE_INIT(pAd); +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) + InitRfPaModeTable(pAd); +#endif /* RT6352 */ + +#ifdef RT8592 + // TODO: shiang-6590, actually, this operation shall be move to bbp_init + if (IS_RT8592(pAd)) + bw_filter_cal(pAd); +#endif /* RT8592 */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION + /* Temperature compensation, initialize the lookup table */ + DBGPRINT(RT_DEBUG_OFF, ("bAutoTxAgcG = %d\n", pAd->bAutoTxAgcG)); + + if (pAd->chipCap.bTempCompTxALC && pAd->bAutoTxAgcG) + InitLookupTable(pAd); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + + /* Set PHY to appropriate mode and will update the ChannelListNum in this function */ + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + if (pAd->ChannelListNum == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n")); + goto err6; + } + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0], + pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2], + pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4])); +#endif /* DOT11_N_SUPPORT */ + +#ifdef WIN_NDIS + /* Patch cardbus controller if EEPROM said so. */ + if (pAd->bTest1 == FALSE) + RTMPPatchCardBus(pAd); +#endif /* WIN_NDIS */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadInit(pAd); +#endif /* AP_QLOAD_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* APInitialize(pAd);*/ + +#ifdef IKANOS_VX_1X0 + VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress); +#endif /* IKANOS_VX_1X0 */ + + +#ifdef RALINK_ATE +#endif /* RALINK_ATE */ + + +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT6352 + if (IS_RT6352(pAd) && (pAd->TxPowerCtrl.bInternalTxALC == TRUE)) + { + RT635xTssiDcCalibration(pAd); + } +#endif /* RT6352 */ +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* + Some modules init must be called before APStartUp(). + Or APStartUp() will make up beacon content and call + other modules API to get some information to fill. + */ + + + + if (pAd && (Status != NDIS_STATUS_SUCCESS)) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } + } + else if (pAd) + { + /* Microsoft HCT require driver send a disconnect event after driver initialization.*/ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.bAutoChannelAtBootup || (pAd->CommonCfg.Channel == 0)) + { + /* Enable Interrupt first due to we need to scan channel to receive beacons.*/ +#ifdef RTMP_MAC_PCI + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + /* Now Enable RxTx*/ + RTMPEnableRxTx(pAd); +#ifdef MT762x + // TODO: shiang-usw, check why MT76x2 don't need to set this flag here! + if (!IS_MT762x(pAd)) +#endif /* MT762x */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + + /* Now we can receive the beacon and do the listen beacon*/ + /* use default BW to select channel*/ + pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, pAd->ApCfg.AutoChannelAlg); + pAd->ApCfg.bAutoChannelAtBootup = FALSE; + } + +#ifdef DOT11_N_SUPPORT + /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */ + N_ChannelCheck(pAd); + +#ifdef DOT11N_DRAFT3 + /* + We only do this Overlapping BSS Scan when system up, for the + other situation of channel changing, we depends on station's + report to adjust ourself. + */ + if (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable 20/40 BSSCoex Channel Scan(BssCoex=%d, 40MHzIntolerant=%d)\n", + pAd->CommonCfg.bBssCoexEnable, + pAd->CommonCfg.bForty_Mhz_Intolerant)); + } + else if(pAd->CommonCfg.bBssCoexEnable == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Enable 20/40 BSSCoex Channel Scan(BssCoex=%d)\n", + pAd->CommonCfg.bBssCoexEnable)); + APOverlappingBSSScan(pAd); + } + + RTMP_11N_D3_TimerInit(pAd); +/* RTMPInitTimer(pAd, &pAd->CommonCfg.Bss2040CoexistTimer, GET_TIMER_FUNCTION(Bss2040CoexistTimeOut), pAd, FALSE);*/ +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + + APStartUp(pAd); + DBGPRINT(RT_DEBUG_OFF, ("Main bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->ApCfg.MBSSID[BSS0].wdev.bssid))); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + mt76x2_reinit_agc_gain(pAd, pAd->hw_cfg.cent_ch); + mt76x2_reinit_hi_lna_gain(pAd, pAd->hw_cfg.cent_ch); + mt76x2_get_agc_gain(pAd, TRUE); + } +#endif + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { +#ifdef DYNAMIC_VGA_SUPPORT + if (pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable == TRUE) + { + rt6352_dynamic_vga_enable(pAd); + } +#endif /* DYNAMIC_VGA_SUPPORT */ + + pAd->bCalibrationDone = TRUE; + } +#endif /* RT6352 */ + + } + + /* Set up the Mac address*/ +#ifdef CONFIG_AP_SUPPORT + RtmpOSNetDevAddrSet(pAd->OpMode, pAd->net_dev, &pAd->CurrentAddress[0], NULL); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + NdisMoveMemory(&pAd->StaCfg.wdev.if_addr[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + RtmpOSNetDevAddrSet(pAd->OpMode, pAd->net_dev, &pAd->CurrentAddress[0], (PUCHAR)(pAd->StaCfg.dev_name)); + NdisMoveMemory(&pAd->StaCfg.wdev.if_addr[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef UAPSD_SUPPORT + UAPSD_Init(pAd); +#endif /* UAPSD_SUPPORT */ + + /* assign function pointers*/ +#ifdef MAT_SUPPORT + /* init function pointers, used in OS_ABL */ + RTMP_MATOpsInit(pAd); +#endif /* MAT_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#ifdef VIDEO_TURBINE_SUPPORT + VideoTurbineDynamicTune(pAd); +#endif /* VIDEO_TURBINE_SUPPORT */ + +#ifdef RT3XXX_ANTENNA_DIVERSITY_SUPPORT + RT3XXX_AntDiversity_Init(pAd); +#endif /* RT3XXX_ANTENNA_DIVERSITY_SUPPORT */ + } +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MAT_SUPPORT + MATEngineInit(pAd); +#endif /* MAT_SUPPORT */ + +#ifdef CLIENT_WDS + CliWds_ProxyTabInit(pAd); +#endif /* CLIENT_WDS */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef DOT11Z_TDLS_SUPPORT + TDLS_Table_Init(pAd); +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + /* send wireless event to wpa_supplicant for infroming interface up.*/ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_UP, NULL, NULL, 0); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef ETH_CONVERT_SUPPORT + MATEngineInit(pAd); +#endif /* ETH_CONVERT_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + /* auto-fall back settings */ +#ifdef RT6352 + if (IS_RT6352(pAd)) + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xedcba980); +#endif /* RT6352 */ +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + { + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_0, 0x12111008); + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_1, 0x16151413); + } +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + RtmpStreamModeInit(pAd); +#endif /* STREAM_MODE_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT +#ifndef MT76x2 + if (pAd->CommonCfg.ITxBfTimeout) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, pAd->CommonCfg.ITxBfTimeout & 0xFF); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, (pAd->CommonCfg.ITxBfTimeout>>8) & 0xFF); + } +#endif + + if (pAd->CommonCfg.ETxBfTimeout) + { + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_3, pAd->CommonCfg.ETxBfTimeout); + } +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + + +#ifdef CUSTOMER_DCC_FEATURE + pAd->ChannelInfo.GetChannelInfo = FALSE; +#endif + +#ifdef REDUCE_TCP_ACK_SUPPORT + ReduceAckInit(pAd); +#endif /* REDUCE_TCP_ACK_SUPPORT */ + + DBGPRINT_S(Status, ("<==== rt28xx_init, Status=%x\n", Status)); + + return TRUE; + +err6: + +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(pAd, &pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); +err5: + RtmpNetTaskExit(pAd); + UserCfgExit(pAd); +err4: + MlmeHalt(pAd); + RTMP_AllTimerListRelease(pAd); +err3: + RtmpMgmtTaskExit(pAd); +#ifdef RTMP_TIMER_TASK_SUPPORT + NdisFreeSpinLock(&pAd->TimerQLock); +#endif /* RTMP_TIMER_TASK_SUPPORT */ +err2: +#ifdef RESOURCE_PRE_ALLOC + RTMPResetTxRxRingMemory(pAd); +#else + RTMPFreeTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +err1: + + MCU_CTRL_EXIT(pAd); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + /* Free BssTab & ChannelInfo tabbles.*/ + AutoChBssTableDestroy(pAd); + ChannelInfoDestroy(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + if(pAd->mpdu_blk_pool.mem) + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); /* free BA pool*/ +#endif /* DOT11_N_SUPPORT */ + +#ifdef INF_AMAZON_SE +err0: +#endif /* INF_AMAZON_SE */ +#ifdef ST +err0: +#endif /* ST */ + + DBGPRINT(RT_DEBUG_ERROR, ("!!! rt28xx init fail !!!\n")); + return FALSE; +} + + +VOID RTMPDrvOpen(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; +#ifdef BTCOEX_CONCURRENT + BT_COEX_VAL btcoex_val; + UINT32 val; + USHORT ee_tmp; +#endif + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP); +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11R_FT_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + FT_RIC_Init(pAd); + } +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RTMP_MAC + // TODO: shiang-usw, check this for RMTP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { +#ifdef RTMP_MAC_PCI + /* Enable Interrupt*/ + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + /* Now Enable RxTx*/ + RTMPEnableRxTx(pAd); + } +#endif /* RTMP_MAC */ + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMPInitPCIeLinkCtrlValue(pAd); +#endif /* PCIE_PS_SUPPORT */ + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef BG_FT_SUPPORT + BG_FTPH_Init(); +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +//+++Add by shiang for debug + DBGPRINT(RT_DEBUG_OFF, ("%s(1):Check if PDMA is idle!\n", __FUNCTION__)); + AsicWaitPDMAIdle(pAd, 5, 10); +//---Add by shiang for debug + +#ifdef CONFIG_STA_SUPPORT + /* + To reduce connection time, + do auto reconnect here instead of waiting STAMlmePeriodicExec to do auto reconnect. + */ + if (pAd->OpMode == OPMODE_STA) + MlmeAutoReconnectLastSSID(pAd); +#endif /* CONFIG_STA_SUPPORT */ +//+++Add by shiang for debug + DBGPRINT(RT_DEBUG_OFF, ("%s(2):Check if PDMA is idle!\n", __FUNCTION__)); + AsicWaitPDMAIdle(pAd, 5, 10); +//---Add by shiang for debug + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + if (pAd->OpMode == OPMODE_STA) + { + pAd->StaCfg.PmfCfg.MFPC = FALSE; + pAd->StaCfg.PmfCfg.MFPR = FALSE; + pAd->StaCfg.PmfCfg.PMFSHA256 = FALSE; + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable)) + { + pAd->StaCfg.PmfCfg.PMFSHA256 = pAd->StaCfg.PmfCfg.Desired_PMFSHA256; + if (pAd->StaCfg.PmfCfg.Desired_MFPC) + { + pAd->StaCfg.PmfCfg.MFPC = TRUE; + pAd->StaCfg.PmfCfg.MFPR = pAd->StaCfg.PmfCfg.Desired_MFPR; + + if (pAd->StaCfg.PmfCfg.MFPR) + pAd->StaCfg.PmfCfg.PMFSHA256 = TRUE; + } + } else if (pAd->StaCfg.PmfCfg.Desired_MFPC) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: MFPC=%d, MFPR=%d, SHA256=%d\n", + __FUNCTION__, pAd->StaCfg.PmfCfg.MFPC, pAd->StaCfg.PmfCfg.MFPR, + pAd->StaCfg.PmfCfg.PMFSHA256)); + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + INT index; + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[index].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + } + else +#endif /*HOSTAPD_SUPPORT*/ + { + PWSC_CTRL pWscControl; + UCHAR zeros16[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("Generate UUID for apidx(%d)\n", index)); + if (NdisEqualMemory(&pWscControl->Wsc_Uuid_E[0], zeros16, UUID_LEN_HEX)) + WscGenerateUUID(pAd, &pWscControl->Wsc_Uuid_E[0], &pWscControl->Wsc_Uuid_Str[0], index, FALSE); + WscInit(pAd, FALSE, index); + } + } + +#ifdef APCLI_SUPPORT + for(index = 0; index < MAX_APCLI_NUM; index++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[index].WscControl; + + pWpsCtrl->pAd = pAd; + NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN); +#ifdef WSC_V2_SUPPORT + pWpsCtrl->WscConfigMethods= 0x238C; +#else + pWpsCtrl->WscConfigMethods= 0x018C; +#endif /*WSC_V2_SUPPORT*/ + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WSC_INIT, 0, (VOID *)&pAd->ApCfg.ApCliTab[index], index); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + PWSC_CTRL pWscControl = &pAd->StaCfg.WscControl; + + WscGenerateUUID(pAd, &pWscControl->Wsc_Uuid_E[0], &pWscControl->Wsc_Uuid_Str[0], 0, FALSE); + WscInit(pAd, FALSE, BSS0); +#ifdef WSC_V2_SUPPORT + WscInitRegistrarPair(pAd, &pAd->StaCfg.WscControl, BSS0); +#endif /* WSC_V2_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + /* WSC hardware push button function 0811 */ + WSC_HDR_BTN_Init(pAd); +#endif /* WSC_INCLUDED */ + +#ifdef BTCOEX_CONCURRENT + RT28xx_EEPROM_READ16(pAd, 0x22, ee_tmp); + btcoex_val.eeprom23=(ee_tmp & 0xFF00)>>8; + + RT28xx_EEPROM_READ16(pAd, 0x24, ee_tmp); + btcoex_val.eeprom24=(ee_tmp & 0x00FF); + btcoex_val.eeprom25=(ee_tmp & 0xFF00)>>8; + + NdisCopyMemory(&val, &btcoex_val, sizeof(UINT32)); + printk("val = 0x%x\n",val); + andes_fun_set(pAd, 11, val); +#endif +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT + pAd->PDMAWatchDogEn = 1; +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ +#ifdef ED_MONITOR +{ + BOOLEAN bEdcca = FALSE; + + bEdcca = GetEDCCASupport(pAd); + + if (bEdcca) + { + ed_monitor_init(pAd); + } +} +#endif /* ED_MONITOR */ +} + + +VOID RTMPDrvClose(VOID *pAdSrc, VOID *net_dev) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + UINT32 i = 0; + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT + pAd->PDMAWatchDogEn = 0; +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + + +#ifdef LED_CONTROL_SUPPORT + RTMPExitLEDMode(pAd); +#endif // LED_CONTROL_SUPPORT + +#ifdef RT_CFG80211_SUPPORT +#ifdef CONFIG_AP_SUPPORT + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + CFG80211DRV_DisableApInterface(pAd); + pAd->cfg80211_ctrl.isCfgInApMode = RT_CMD_80211_IFTYPE_STATION; + } +#endif /* CONFIG_AP_SUPPORT */ +#endif/*RT_CFG80211_SUPPORT*/ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); +#ifdef BB_SOC + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Radio_ON first....\n")); + MlmeRadioOn(pAd); + } +#endif /* BB_SOC */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef CREDENTIAL_STORE + if (pAd->IndicateMediaState == NdisMediaStateConnected) + StoreConnectInfo(pAd); + else + { + RTMP_SEM_LOCK(&pAd->StaCtIf.Lock); + pAd->StaCtIf.Changeable = FALSE; + RTMP_SEM_UNLOCK(&pAd->StaCtIf.Lock); + } +#endif /* CREDENTIAL_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef BG_FT_SUPPORT + BG_FTPH_Remove(); +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#ifdef RT3XXX_ANTENNA_DIVERSITY_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + RT3XXX_AntDiversity_Fini(pAd); +#endif /* RT3XXX_ANTENNA_DIVERSITY_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef PCIE_PS_SUPPORT + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE); +#endif /* PCIE_PS_SUPPORT */ + + /* If dirver doesn't wake up firmware here,*/ + /* NICLoadFirmware will hang forever when interface is up again.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + AsicForceWakeup(pAd, TRUE); + } + + +#ifdef RTMP_MAC_PCI + pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI */ + } +#endif /* CONFIG_STA_SUPPORT */ + +#if ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) + if (pAd->WOW_Cfg.bEnable == FALSE) +#endif /* ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) */ + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + } + +#ifdef EXT_BUILD_CHANNEL_LIST + if (pAd->CommonCfg.pChDesp != NULL) + os_free_mem(NULL, pAd->CommonCfg.pChDesp); + pAd->CommonCfg.pChDesp = NULL; + pAd->CommonCfg.DfsType = MAX_RD_REGION; + pAd->CommonCfg.bCountryFlag = 0; +#endif /* EXT_BUILD_CHANNEL_LIST */ + pAd->CommonCfg.bCountryFlag = FALSE; + + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + + RtmpOsMsDelay(20); /* wait for disconnect requests transmitted */ + + for (i = 0 ; i < NUM_OF_TX_RING; i++) + { + while (pAd->DeQueueRunning[i] == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Waiting for TxQueue[%d] done..........\n", i)); + RtmpusecDelay(1000); + } + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DOT11N_DRAFT3 + BOOLEAN Cancelled = FALSE; + + if (pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_TIMER_FIRED) + { + RTMPCancelTimer(&pAd->CommonCfg.Bss2040CoexistTimer, &Cancelled); + pAd->CommonCfg.Bss2040CoexistFlag = 0; + } +#endif /* DOT11N_DRAFT3 */ + + /* PeriodicTimer already been canceled by MlmeHalt() API.*/ + /*RTMPCancelTimer(&pAd->PeriodicTimer, &Cancelled);*/ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Stop Mlme state machine*/ + MlmeHalt(pAd); + + /* Close net tasklets*/ + RtmpNetTaskExit(pAd); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MacTableReset(pAd); +#ifdef MAT_SUPPORT + MATEngineExit(pAd); +#endif /* MAT_SUPPORT */ +#if ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) + if (pAd->WOW_Cfg.bEnable == TRUE) + ASIC_WOW_ENABLE(pAd); + else +#endif /* ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) */ + MlmeRadioOff(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MAT_SUPPORT + MATEngineExit(pAd); +#endif /* MAT_SUPPORT */ + +#ifdef CLIENT_WDS + CliWds_ProxyTabDestory(pAd); +#endif /* CLIENT_WDS */ + +#ifdef MWDS + MWDSAPDown(pAd); +#endif /* MWDS */ + + /* Shutdown Access Point function, release all related resources */ + APShutdown(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); + + + + /* Close kernel threads*/ + RtmpMgmtTaskExit(pAd); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* must after RtmpMgmtTaskExit(); Or pAd->pChannelInfo will be NULL */ + /* Free BssTab & ChannelInfo tabbles.*/ + AutoChBssTableDestroy(pAd); + ChannelInfoDestroy(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RTMP_MAC_PCI + { +#if defined(MT76x0) || defined(MT76x2) + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) { + DISABLE_TX_RX(pAd, RTMP_HALT); + } + else +#endif /* MT76x0 */ + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + DISABLE_TX_RX(pAd, RTMP_HALT); + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + } + + /* Receive packets to clear DMA index after disable interrupt. */ + /*RTMPHandleRxDoneInterrupt(pAd);*/ + /* put to radio off to save power when driver unload. After radiooff, can't write /read register. So need to finish all */ + /* register access before Radio off.*/ + +#ifdef RTMP_PCI_SUPPORT + if (pAd->infType == RTMP_DEV_INF_PCI || pAd->infType == RTMP_DEV_INF_PCIE) + { + BOOLEAN brc = TRUE; + +#if defined(MT76x0) || defined(MT76x2) + // TODO: shiang, how about RadioOff for 65xx?? + if (!(IS_MT76x0(pAd) || IS_MT76x2(pAd))) +#endif /* defined(MT76x0) || defined(MT76x2) */ + brc = RT28xxPciAsicRadioOff(pAd, RTMP_HALT, 0); + +/*In solution 3 of 3090F, the bPCIclkOff will be set to TRUE after calling RT28xxPciAsicRadioOff*/ +#ifdef PCIE_PS_SUPPORT + pAd->bPCIclkOff = FALSE; +#endif /* PCIE_PS_SUPPORT */ + + if (brc==FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__)); + } + } +#endif /* RTMP_PCI_SUPPORT */ + } + +#endif /* RTMP_MAC_PCI */ + + /* Free IRQ*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { +#ifdef RTMP_MAC_PCI + /* Deregister interrupt function*/ + RTMP_OS_IRQ_RELEASE(pAd, net_dev); +#endif /* RTMP_MAC_PCI */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } + +#ifdef SINGLE_SKU_V2 + { + CH_POWER *ch, *ch_temp; + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + DlListDel(&ch->List); + os_free_mem(NULL, ch); + } + } +#endif /* SINGLE_SKU_V2 */ + + /* Free Ring or USB buffers*/ +#ifdef RESOURCE_PRE_ALLOC + RTMPResetTxRxRingMemory(pAd); +#else + /* Free Ring or USB buffers*/ + RTMPFreeTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + +#ifdef WLAN_SKB_RECYCLE + skb_queue_purge(&pAd->rx0_recycle); +#endif /* WLAN_SKB_RECYCLE */ + +#ifdef DOT11_N_SUPPORT + /* Free BA reorder resource*/ + ba_reordering_resource_release(pAd); +#endif /* DOT11_N_SUPPORT */ + + UserCfgExit(pAd); /* must after ba_reordering_resource_release */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11R_FT_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + FT_RIC_Release(pAd); + } +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + +/*+++Modify by woody to solve the bulk fail+++*/ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef DOT11Z_TDLS_SUPPORT + TDLS_Table_Destory(pAd); +#ifdef TDLS_AUTOLINK_SUPPORT + TDLS_ClearEntryList(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList); + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_ClearEntryList(&pAd->StaCfg.TdlsInfo.TdlsBlackList); + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); +#endif /* TDLS_AUTOLINK_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + /* clear MAC table */ + /* TODO: do not clear spin lock, such as fLastChangeAccordingMfbLock */ + NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + + /* release all timers */ + RtmpusecDelay(2000); + RTMP_AllTimerListRelease(pAd); + +#ifdef ED_MONITOR + if (pAd->ed_chk) + { + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: go to ed_monitor_exit()!!\n", __FUNCTION__)); + ed_monitor_exit(pAd); + } +#endif /* ED_MONITOR */ + +#ifdef RTMP_TIMER_TASK_SUPPORT + NdisFreeSpinLock(&pAd->TimerQLock); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + cap_mode_deinit(pAd); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef REDUCE_TCP_ACK_SUPPORT + ReduceAckExit(pAd); +#endif /* REDUCE_TCP_ACK_SUPPORT */ +} + + +VOID RTMPInfClose(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = FALSE; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* kick out all STAs behind the bss.*/ + MbssKickOutStas(pAd, MAIN_MBSSID, REASON_DISASSOC_INACTIVE); + } + + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef PROFILE_STORE + WriteDatThread(pAd); + RtmpusecDelay(1000); +#endif /* PROFILE_STORE */ +#ifdef QOS_DLS_SUPPORT + /* send DLS-TEAR_DOWN message, */ + if (pAd->CommonCfg.bDLSCapable) + { + UCHAR i; + + /* tear down local dls table entry*/ + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + + /* tear down peer dls table entry*/ + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + RTMP_MLME_HANDLER(pAd); + } +#endif /* QOS_DLS_SUPPORT */ + + if (INFRA_ON(pAd) && +#if ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) + /* In WOW state, can't issue disassociation reqeust */ + pAd->WOW_Cfg.bEnable == FALSE && +#endif /* ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) */ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + MLME_QUEUE_ELEM *MsgElem; + + os_alloc_mem(NULL, (UCHAR **)&MsgElem, sizeof(MLME_QUEUE_ELEM)); + if (MsgElem) + { + COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DEAUTH_STA_LEAVING; + + MsgElem->Machine = ASSOC_STATE_MACHINE; + MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + /* Prevent to connect AP again in STAMlmePeriodicExec*/ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, MsgElem); + os_free_mem(NULL, MsgElem); + } + + RtmpusecDelay(1000); + } + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + /* send wireless event to wpa_supplicant for infroming interface down.*/ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + + if (pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe) + { + os_free_mem(NULL, pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe); + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe = NULL; + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen = 0; + } + + if (pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe) + { + os_free_mem(NULL, pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe); + pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe = NULL; + pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen = 0; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + + } +#endif /* CONFIG_STA_SUPPORT */ +} + + + + +PNET_DEV RtmpPhyNetDevMainCreate(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + PNET_DEV pDevNew; + 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 */ + + dev_name = get_dev_name_prefix(pAd, INT_MAIN); + pDevNew = RtmpOSNetDevCreate((INT32)MC_RowID, (UINT32 *)&IoctlIF, + INT_MAIN, 0, sizeof(struct mt_dev_priv), dev_name); + +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + return pDevNew; +} + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PROFILE_STORE +static void WriteConfToDatFile(RTMP_ADAPTER *pAd) +{ + char *cfgData = 0, *offset = 0; + PSTRING fileName = NULL, pTempStr = NULL; + RTMP_OS_FD file_r, file_w; + RTMP_OS_FS_INFO osFSInfo; + LONG rv, fileLen = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WriteConfToDatFile\n")); + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + fileName = STA_PROFILE_PATH_RBUS; + else +#endif /* RTMP_RBUS_SUPPORT */ + fileName = STA_PROFILE_PATH; + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + file_r = RtmpOSFileOpen(fileName, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(file_r)) + { + DBGPRINT(RT_DEBUG_TRACE, ("-->1) %s: Error opening file %s\n", __FUNCTION__, fileName)); + return; + } + else + { + char tempStr[64] = {0}; + while((rv = RtmpOSFileRead(file_r, tempStr, 64)) > 0) + { + fileLen += rv; + } + os_alloc_mem(NULL, (UCHAR **)&cfgData, fileLen); + if (cfgData == NULL) + { + RtmpOSFileClose(file_r); + DBGPRINT(RT_DEBUG_TRACE, ("CfgData mem alloc fail. (fileLen = %ld)\n", fileLen)); + goto out; + } + NdisZeroMemory(cfgData, fileLen); + RtmpOSFileSeek(file_r, 0); + rv = RtmpOSFileRead(file_r, (PSTRING)cfgData, fileLen); + RtmpOSFileClose(file_r); + if (rv != fileLen) + { + DBGPRINT(RT_DEBUG_TRACE, ("CfgData mem alloc fail, fileLen = %ld\n", fileLen)); + goto ReadErr; + } + } + + file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_TRUNC, 0); + if (IS_FILE_OPEN_ERR(file_w)) + { + goto WriteFileOpenErr; + } + else + { + offset = (PCHAR) rtstrstr((PSTRING) cfgData, "Default\n"); + offset += strlen("Default\n"); + RtmpOSFileWrite(file_w, (PSTRING)cfgData, (int)(offset-cfgData)); + os_alloc_mem(NULL, (UCHAR **)&pTempStr, 512); + if (!pTempStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pTempStr mem alloc fail. (512)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + + for (;;) + { + int i = 0; + PSTRING ptr; + + NdisZeroMemory(pTempStr, 512); + ptr = (PSTRING) offset; + while(*ptr && *ptr != '\n') + { + pTempStr[i++] = *ptr++; + } + pTempStr[i] = 0x00; + if ((size_t)(offset - cfgData) < fileLen) + { + offset += strlen(pTempStr) + 1; + if (strncmp(pTempStr, "SSID=", strlen("SSID=")) == 0) + { + NdisZeroMemory(pTempStr, 512); + NdisMoveMemory(pTempStr, "SSID=", strlen("SSID=")); + NdisMoveMemory(pTempStr + 5, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + } + else if (strncmp(pTempStr, "AuthMode=", strlen("AuthMode=")) == 0) + { + NdisZeroMemory(pTempStr, 512); + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeOpen) + sprintf(pTempStr, "AuthMode=OPEN"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) + sprintf(pTempStr, "AuthMode=SHARED"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) + sprintf(pTempStr, "AuthMode=WEPAUTO"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + sprintf(pTempStr, "AuthMode=WPAPSK"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + sprintf(pTempStr, "AuthMode=WPA2PSK"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) + sprintf(pTempStr, "AuthMode=WPA"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + sprintf(pTempStr, "AuthMode=WPA2"); + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + sprintf(pTempStr, "AuthMode=WPANONE"); + } + else if (strncmp(pTempStr, "EncrypType=", strlen("EncrypType=")) == 0) + { + NdisZeroMemory(pTempStr, 512); + if (pAd->StaCfg.WepStatus == Ndis802_11WEPDisabled) + sprintf(pTempStr, "EncrypType=NONE"); + else if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) + sprintf(pTempStr, "EncrypType=WEP"); + else if (pAd->StaCfg.WepStatus == Ndis802_11TKIPEnable) + sprintf(pTempStr, "EncrypType=TKIP"); + else if (pAd->StaCfg.WepStatus == Ndis802_11AESEnable) + sprintf(pTempStr, "EncrypType=AES"); + } + RtmpOSFileWrite(file_w, pTempStr, strlen(pTempStr)); + RtmpOSFileWrite(file_w, "\n", 1); + } + else + { + break; + } + } + RtmpOSFileClose(file_w); + } + +WriteErr: + if (pTempStr) + os_free_mem(NULL, pTempStr); +ReadErr: +WriteFileOpenErr: + if (cfgData) + os_free_mem(NULL, cfgData); +out: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WriteConfToDatFile\n")); + return; +} + + +INT write_dat_file_thread ( + IN ULONG Context) +{ + RTMP_OS_TASK *pTask; + RTMP_ADAPTER *pAd; + //int Status = 0; + + pTask = (RTMP_OS_TASK *)Context; + + if (pTask == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: pTask is NULL\n", __FUNCTION__)); + return 0; + } + + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd is NULL\n", __FUNCTION__)); + return 0; + } + + RtmpOSTaskCustomize(pTask); + + /* Update ssid, auth mode and encr type to DAT file */ + WriteConfToDatFile(pAd); + + RtmpOSTaskNotifyToExit(pTask); + + return 0; +} + +NDIS_STATUS WriteDatThread( + IN RTMP_ADAPTER *pAd) +{ + NDIS_STATUS status = NDIS_STATUS_FAILURE; + RTMP_OS_TASK *pTask; + + if (pAd->bWriteDat == FALSE) + return 0; + + DBGPRINT(RT_DEBUG_TRACE, ("-->WriteDatThreadInit()\n")); + + pTask = &pAd->WriteDatTask; + + RTMP_OS_TASK_INIT(pTask, "RtmpWriteDatTask", pAd); + status = RtmpOSTaskAttach(pTask, write_dat_file_thread, (ULONG)&pAd->WriteDatTask); + DBGPRINT(RT_DEBUG_TRACE, ("<--WriteDatThreadInit(), status=%d!\n", status)); + + return status; +} +#endif /* PROFILE_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_swmcu.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_swmcu.c new file mode 100644 index 000000000..02c7277f2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_swmcu.c @@ -0,0 +1,143 @@ +/* + *************************************************************************** + * 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_swmcu.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifdef CONFIG_SWMCU_SUPPORT +#include "rt_config.h" + + + +int RtmpAsicSendCommandToSwMcu( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked) +{ + BBP_CSR_CFG_STRUC BbpCsr, BbpCsr2; + int j, k; +#ifdef LED_CONTROL_SUPPORT + UINT16 Temp; + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; +#endif /* LED_CONTROL_SUPPORT */ + + switch(Command) + { + case 0x80: + RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); + if ((BbpCsr.field.Busy != 1) || (BbpCsr.field.BBP_RW_MODE != 1)) + DBGPRINT(RT_DEBUG_ERROR, ("error read write BBP 1\n")); + + for (j=0; jBbpWriteLatch[BbpCsr.field.RegNum] = BbpCsr2.field.Value; + break; + } + } + + if (j == MAX_BUSY_COUNT) + { + DBGPRINT(RT_DEBUG_ERROR, ("error read write BBP 3\n")); + if (BbpCsr.field.Busy != IDLE) + { + BbpCsr.field.Busy = IDLE; + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); + } + } + break; + case 0x30: + break; + case 0x31: + break; +#ifdef LED_CONTROL_SUPPORT + case MCU_SET_LED_MODE: + pSWMCULedCntl->LedParameter.LedMode = Arg0; + pSWMCULedCntl->LinkStatus = Arg1; + SetLedLinkStatus(pAd); + break; + case MCU_SET_LED_GPIO_SIGNAL_CFG: + pSWMCULedCntl->GPIOPolarity = Arg1; + pSWMCULedCntl->SignalStrength = Arg0; + break; + case MCU_SET_LED_AG_CFG: + Temp = ((UINT16)Arg1 << 8) | (UINT16)Arg0; + NdisMoveMemory(&pSWMCULedCntl->LedParameter.LedAgCfg, &Temp, 2); + break; + case MCU_SET_LED_ACT_CFG: + Temp = ((UINT16)Arg1 << 8) | (UINT16)Arg0; + NdisMoveMemory(&pSWMCULedCntl->LedParameter.LedActCfg, &Temp, 2); + break; + case MCU_SET_LED_POLARITY: + Temp = ((UINT16)Arg1 << 8) | (UINT16)Arg0; + NdisMoveMemory(&pSWMCULedCntl->LedParameter.LedPolarityCfg, &Temp, 2); + break; +#endif /* LED_CONTROL_SUPPORT */ + + default: + break; + } + + return 0; +} + +#endif /* CONFIG_SWMCU_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_timer.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_timer.c new file mode 100644 index 000000000..926ab5cc9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/rtmp_timer.c @@ -0,0 +1,431 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2008, 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_timer.c + + Abstract: + task for timer handling + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Shiang Tu 08-28-2008 init version + +*/ + +#include "rt_config.h" + + +BUILD_TIMER_FUNCTION(MlmePeriodicExec); +/*BUILD_TIMER_FUNCTION(MlmeRssiReportExec);*/ +BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); +BUILD_TIMER_FUNCTION(APSDPeriodicExec); +BUILD_TIMER_FUNCTION(EnqueueStartForPSKExec); + +#ifdef TXBF_SUPPORT +BUILD_TIMER_FUNCTION(APTxSounding); +#endif + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT +BUILD_TIMER_FUNCTION(Adhoc_WpaRetryExec); +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT +BUILD_TIMER_FUNCTION(PMF_SAQueryTimeOut); +BUILD_TIMER_FUNCTION(PMF_SAQueryConfirmTimeOut); +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +extern VOID APDetectOverlappingExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BUILD_TIMER_FUNCTION(APDetectOverlappingExec); + +#ifdef DOT11N_DRAFT3 +BUILD_TIMER_FUNCTION(Bss2040CoexistTimeOut); +#endif /* DOT11N_DRAFT3 */ + +BUILD_TIMER_FUNCTION(GREKEYPeriodicExec); +BUILD_TIMER_FUNCTION(CMTimerExec); +BUILD_TIMER_FUNCTION(WPARetryExec); +#ifdef AP_SCAN_SUPPORT +BUILD_TIMER_FUNCTION(APScanTimeout); +#endif /* AP_SCAN_SUPPORT */ +BUILD_TIMER_FUNCTION(APQuickResponeForRateUpExec); +#ifdef IDS_SUPPORT +BUILD_TIMER_FUNCTION(RTMPIdsPeriodicExec); +#endif /* IDS_SUPPORT */ +#ifdef DROP_MASK_SUPPORT +BUILD_TIMER_FUNCTION(drop_mask_timer_action); +#endif /* DROP_MASK_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +BUILD_TIMER_FUNCTION(FT_KDP_InfoBroadcast); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +BUILD_TIMER_FUNCTION(BeaconTimeout); +BUILD_TIMER_FUNCTION(ScanTimeout); +BUILD_TIMER_FUNCTION(AuthTimeout); +BUILD_TIMER_FUNCTION(AssocTimeout); +BUILD_TIMER_FUNCTION(ReassocTimeout); +BUILD_TIMER_FUNCTION(DisassocTimeout); +BUILD_TIMER_FUNCTION(LinkDownExec); +BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec); +BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); + +#ifdef RTMP_PCI_SUPPORT +BUILD_TIMER_FUNCTION(PsPollWakeExec); +#ifdef PCIE_PS_SUPPORT +BUILD_TIMER_FUNCTION(RadioOnExec); +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_PCI_SUPPORT */ +#ifdef QOS_DLS_SUPPORT +BUILD_TIMER_FUNCTION(DlsTimeoutAction); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +BUILD_TIMER_FUNCTION(TDLS_OffChExpired); +BUILD_TIMER_FUNCTION(TDLS_BaseChExpired); +BUILD_TIMER_FUNCTION(TDLS_LinkTimeoutAction); +BUILD_TIMER_FUNCTION(TDLS_ChannelSwitchTimeAction); +BUILD_TIMER_FUNCTION(TDLS_ChannelSwitchTimeOutAction); +BUILD_TIMER_FUNCTION(TDLS_DisablePeriodChannelSwitchAction); +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +BUILD_TIMER_FUNCTION(FT_OTA_AuthTimeout); +BUILD_TIMER_FUNCTION(FT_OTD_TimeoutAction); +#endif /* DOT11R_FT_SUPPORT */ + + + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_INCLUDED +BUILD_TIMER_FUNCTION(WscEAPOLTimeOutAction); +BUILD_TIMER_FUNCTION(Wsc2MinsTimeOutAction); +BUILD_TIMER_FUNCTION(WscUPnPMsgTimeOutAction); +BUILD_TIMER_FUNCTION(WscM2DTimeOutAction); + +BUILD_TIMER_FUNCTION(WscPBCTimeOutAction); +BUILD_TIMER_FUNCTION(WscScanTimeOutAction); +BUILD_TIMER_FUNCTION(WscProfileRetryTimeout); +#ifdef WSC_LED_SUPPORT +BUILD_TIMER_FUNCTION(WscLEDTimer); +BUILD_TIMER_FUNCTION(WscSkipTurnOffLEDTimer); +#endif /* WSC_LED_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +BUILD_TIMER_FUNCTION(WscUpdatePortCfgTimeout); +BUILD_TIMER_FUNCTION(WscSetupLockTimeout); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IWSC_SUPPORT +BUILD_TIMER_FUNCTION(IWSC_T1TimerAction); +BUILD_TIMER_FUNCTION(IWSC_T2TimerAction); +BUILD_TIMER_FUNCTION(IWSC_EntryTimerAction); +BUILD_TIMER_FUNCTION(IWSC_DevQueryAction); +#endif /* IWSC_SUPPORT */ + +#endif /* WSC_INCLUDED */ + +#if defined(BAND_STEERING) && !defined(BNDSTRG_DAEMON) +BUILD_TIMER_FUNCTION(BndStrg_PeriodicExec); +#endif /* BAND_STEERING && !BNDSTRG_DAEMON */ + + + +#ifdef TXBF_SUPPORT +BUILD_TIMER_FUNCTION(eTxBfProbeTimerExec); +#endif /* TXBF_SUPPORT */ + + +#ifdef RT_CFG80211_P2P_SUPPORT +BUILD_TIMER_FUNCTION(CFG80211_P2PCTWindowTimer); +BUILD_TIMER_FUNCTION(CFG80211_P2pSwNoATimeOut); +BUILD_TIMER_FUNCTION(CFG80211_P2pPreAbsenTimeOut); +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#ifdef RALINK_ATE +BUILD_TIMER_FUNCTION(ATEPeriodicExec); +#endif /* RALINK_ATE */ + +#ifdef APCLI_SUPPORT +BUILD_TIMER_FUNCTION(ApCliWpaDisassocApAndBlockAssoc); +#endif /* APCLI_SUPPORT */ + +#ifdef PEER_DELBA_TX_ADAPT +BUILD_TIMER_FUNCTION(PeerDelBATxAdaptTimeOut); +#endif /* PEER_DELBA_TX_ADAPT */ + +#if defined (ED_MONITOR) && defined (ED_SMART) +BUILD_TIMER_FUNCTION(ed_testing_timeout); +#endif /*ED_MONITOR*/ + +#ifdef RTMP_MAC_PCI +BUILD_TIMER_FUNCTION(TxDoneCleanupExec); +#endif /* RTMP_MAC_PCI */ + +#ifdef RTMP_TIMER_TASK_SUPPORT +static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) +{ + int status; + RALINK_TIMER_STRUCT *pTimer; + RTMP_TIMER_TASK_ENTRY *pEntry; + unsigned long irqFlag; + RTMP_OS_TASK *pTask; + + pTask = &pAd->timerTask; + while(!RTMP_OS_TASK_IS_KILLED(pTask)) + { + pTimer = NULL; + + if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED) + break; + + /* event happened.*/ + while(pAd->TimerQ.pQHead) + { + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag); + pEntry = pAd->TimerQ.pQHead; + if (pEntry) + { + pTimer = pEntry->pRaTimer; + + /* update pQHead*/ + pAd->TimerQ.pQHead = pEntry->pNext; + if (pEntry == pAd->TimerQ.pQTail) + pAd->TimerQ.pQTail = NULL; + + /* return this queue entry to timerQFreeList.*/ + pEntry->pNext = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pEntry; + } + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag); + + if (pTimer) + { + if ((pTimer->handle != NULL) && (!pAd->PM_FlgSuspend)) + pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer); + if ((pTimer->Repeat) && (pTimer->State == FALSE)) + RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); + } + } + + if (status != 0) + { + pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + } +} + + +INT RtmpTimerQThread( + IN ULONG Context) +{ + RTMP_OS_TASK *pTask; + PRTMP_ADAPTER pAd = NULL; + + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,( "%s:: pAd is NULL!\n",__FUNCTION__)); + return 0; + } + + RtmpOSTaskCustomize(pTask); + + RtmpTimerQHandle(pAd); + + DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + RtmpOSTaskNotifyToExit(pTask); + + return 0; + +} + + +RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer) +{ + RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail; + unsigned long irqFlags; + RTMP_OS_TASK *pTask = &pAd->timerTask; + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) + { + if(pAd->TimerQ.pQPollFreeList) + { + pQNode = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pQNode->pNext; + + pQNode->pRaTimer = pTimer; + pQNode->pNext = NULL; + + pQTail = pAd->TimerQ.pQTail; + if (pAd->TimerQ.pQTail != NULL) + pQTail->pNext = pQNode; + pAd->TimerQ.pQTail = pQNode; + if (pAd->TimerQ.pQHead == NULL) + pAd->TimerQ.pQHead = pQNode; + } + } + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); + + if (pQNode) + { + RTMP_OS_TASK_WAKE_UP(pTask); + } + + return pQNode; +} + + +BOOLEAN RtmpTimerQRemove( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer) +{ + RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL; + unsigned long irqFlags; + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) + { + pNode = pAd->TimerQ.pQHead; + while (pNode) + { + if (pNode->pRaTimer == pTimer) + break; + pPrev = pNode; + pNode = pNode->pNext; + } + + /* Now move it to freeList queue.*/ + if (pNode) + { + if (pNode == pAd->TimerQ.pQHead) + pAd->TimerQ.pQHead = pNode->pNext; + if (pNode == pAd->TimerQ.pQTail) + pAd->TimerQ.pQTail = pPrev; + if (pPrev != NULL) + pPrev->pNext = pNode->pNext; + + /* return this queue entry to timerQFreeList.*/ + pNode->pNext = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pNode; + } + } + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); + + return TRUE; +} + + +void RtmpTimerQExit(RTMP_ADAPTER *pAd) +{ + RTMP_TIMER_TASK_ENTRY *pTimerQ; + unsigned long irqFlags; + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + while (pAd->TimerQ.pQHead) + { + pTimerQ = pAd->TimerQ.pQHead; + pAd->TimerQ.pQHead = pTimerQ->pNext; + /* remove the timeQ*/ + } + pAd->TimerQ.pQPollFreeList = NULL; + os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); + pAd->TimerQ.pQTail = NULL; + pAd->TimerQ.pQHead = NULL; +/*#ifndef KTHREAD_SUPPORT*/ + pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; +/*#endif*/ + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); +/* NdisFreeSpinLock(&pAd->TimerQLock); */ +} + + +void RtmpTimerQInit(RTMP_ADAPTER *pAd) +{ + int i; + RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry; + unsigned long irqFlags; + + NdisAllocateSpinLock(pAd, &pAd->TimerQLock); + + NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); + + os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); + if (pAd->TimerQ.pTimerQPoll) + { + pEntry = NULL; + pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll; + NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + for (i = 0 ;i pNext = pEntry; + pEntry = pQNode; + pQNode++; + } + pAd->TimerQ.pQPollFreeList = pEntry; + pAd->TimerQ.pQHead = NULL; + pAd->TimerQ.pQTail = NULL; + pAd->TimerQ.status = RTMP_TASK_STAT_INITED; + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); + } +} +#endif /* RTMP_TIMER_TASK_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/scan.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/scan.c new file mode 100644 index 000000000..eef26bed1 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/scan.c @@ -0,0 +1,1017 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +#ifdef SCAN_SUPPORT +static INT scan_ch_restore(RTMP_ADAPTER *pAd, UCHAR OpMode) +{ +#ifdef CONFIG_STA_SUPPORT + USHORT Status; +#endif /* CONFIG_STA_SUPPORT */ + INT bw, ch; +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + UCHAR ScanType = pAd->MlmeAux.ScanType; +#endif /*APCLI_CERT_SUPPORT*/ +#endif /*APCLI_SUPPORT*/ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_AC) && + (pAd->CommonCfg.Channel > 14) && + (pAd->hw_cfg.bbp_bw == BW_80) && + (pAd->CommonCfg.vht_bw == VHT_BW_80) && + (pAd->CommonCfg.vht_cent_ch != pAd->CommonCfg.CentralChannel)) { + pAd->CommonCfg.vht_cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + } + + if (pAd->hw_cfg.bbp_bw == 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; + + if (pAd->CommonCfg.BBPCurrentBW != pAd->hw_cfg.bbp_bw) + bbp_set_bw(pAd, pAd->hw_cfg.bbp_bw); + + AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE); + AsicLockChannel(pAd, pAd->hw_cfg.cent_ch); + + ch = pAd->hw_cfg.cent_ch; + + switch(pAd->CommonCfg.BBPCurrentBW) + { + case BW_80: + bw = 80; + break; + case BW_40: + bw = 40; + break; + case BW_10: + bw = 10; + break; + case BW_20: + default: + bw =20; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to %dMHz channel %d, Total BSS[%02d]\n", + bw, ch, pAd->ScanTab.BssNr)); + +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + /* + If all peer Ad-hoc clients leave, driver would do LinkDown and LinkUp. + In LinkUp, CommonCfg.Ssid would copy SSID from MlmeAux. + To prevent SSID is zero or wrong in Beacon, need to recover MlmeAux.SSID here. + */ + if (ADHOC_ON(pAd)) + { + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + } + + /* + To prevent data lost. + Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done + */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + DBGPRINT(RT_DEBUG_TRACE, ("%s -- Send null frame\n", __FUNCTION__)); + } + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (pAd->ApCfg.ApCliTab[MAIN_MBSSID].Valid && RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: PWR_ACTIVE SCAN_END\n")); + RT_CFG80211_P2P_CLI_SEND_NULL_FRAME(pAd, PWR_ACTIVE); + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* keep the latest scan channel, could be 0 for scan complete, or other channel*/ + pAd->StaCfg.LastScanChannel = pAd->MlmeAux.Channel; + + pAd->StaCfg.ScanChannelCnt = 0; + + /* Suspend scanning and Resume TxData for Fast Scanning*/ + if ((pAd->MlmeAux.Channel != 0) && + (pAd->StaCfg.bImprovedScan)) /* it is scan pending*/ + { + pAd->Mlme.SyncMachine.CurrState = SCAN_PENDING; + Status = MLME_SUCCESS; + DBGPRINT(RT_DEBUG_WARN, ("bFastRoamingScan ~~~ Get back to send data ~~~\n")); + + RTMPResumeMsduTransmission(pAd); + } + else + { + pAd->StaCfg.BssNr = pAd->ScanTab.BssNr; + pAd->StaCfg.bImprovedScan = FALSE; + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); + RTMP_MLME_HANDLER(pAd); + } + + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef AP_PARTIAL_SCAN_SUPPORT + && (pAd->ApCfg.bPartialScanning == FALSE) +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + ) + { + if (!ApCliAutoConnectExec(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error in %s\n", __FUNCTION__)); + } + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + RTMPResumeMsduTransmission(pAd); + +#ifdef CON_WPS + if (pAd->conWscStatus != CON_WPS_STATUS_DISABLED) + { + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_COMPLETE, 0, NULL,0 ); + RTMP_MLME_HANDLER(pAd); + } +#endif /* CON_WPS*/ + + /* iwpriv set auto channel selection*/ + /* scanned all channels*/ + if (pAd->ApCfg.bAutoChannelAtBootup==TRUE) + { + pAd->CommonCfg.Channel = SelectBestChannel(pAd, pAd->ApCfg.AutoChannelAlg); + pAd->ApCfg.bAutoChannelAtBootup = FALSE; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + APStop(pAd); + APStartUp(pAd); + } + + if (((pAd->CommonCfg.Channel > 14) && + (pAd->CommonCfg.bIEEE80211H == TRUE) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) && + pAd->Dot11_H.RDMode != RD_SWITCHING_MODE) + { + if (pAd->Dot11_H.InServiceMonitorCount) + { + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + AsicEnableBssSync(pAd); + } + else + { + pAd->Dot11_H.RDMode = RD_SILENCE_MODE; + } + } + else + { + AsicEnableBssSync(pAd); + } + } + +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (APCLI_IF_UP_CHECK(pAd, 0) && pAd->bApCliCertTest == TRUE && ScanType == SCAN_2040_BSS_COEXIST) + { + UCHAR Status=1; + DBGPRINT(RT_DEBUG_TRACE, ("@(%s) Scan Done ScanType=%d\n", __FUNCTION__, ScanType)); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_SCAN_DONE, 2, &Status, 0); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CUSTOMER_DCC_FEATURE + pAd->ChannelStats.LastReadTime = 0; +#endif +#ifdef CONFIG_AP_SUPPORT +#ifdef SMART_MESH + if(OpMode == OPMODE_AP) + { +#ifdef AP_PARTIAL_SCAN_SUPPORT + if ((pAd->ApCfg.bPartialScanning == FALSE) && (pAd->ApCfg.LastPartialScanChannel == 0)) +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + Set_Check_RadarChannelAPExist(pAd); + } +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + + +static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType, INT IfType) +{ + UCHAR *frm_buf = NULL; + HEADER_802_11 Hdr80211; + ULONG FrameLen = 0; + UCHAR SsidLen = 0; +#ifdef CONFIG_STA_SUPPORT + USHORT Status; +#endif /* CONFIG_STA_SUPPORT */ + + + if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; +#endif /* CONFIG_AP_SUPPORT */ + return FALSE; + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (ScanType == SCAN_2040_BSS_COEXIST) + { + DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + /* There is no need to send broadcast probe request if active scan is in effect.*/ + SsidLen = 0; +#ifndef APCLI_CONNECTION_TRIAL + if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) +#ifdef WSC_STA_SUPPORT + || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA)) +#endif /* WSC_STA_SUPPORT */ + ) + SsidLen = pAd->MlmeAux.SsidLen; +#endif /* APCLI_CONNECTION_TRIAL */ + + { +#ifdef CONFIG_AP_SUPPORT + /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ + if (OpMode == OPMODE_AP) + { +#ifdef APCLI_SUPPORT +#ifdef WSC_INCLUDED + if ((ScanType == SCAN_WSC_ACTIVE) || (IfType == INT_APCLI)) + { + MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->ApCfg.ApCliTab[0].wdev.if_addr, + BROADCAST_ADDR); + } + else +#endif /* WSC_INCLUDED */ +#endif /* APCLI_SUPPORT */ + { + MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->ApCfg.MBSSID[0].wdev.bssid, + BROADCAST_ADDR); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + /*IF_DEV_CONFIG_OPMODE_ON_STA(pAd) */ + if (OpMode == OPMODE_STA) + { + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->CurrentAddress, + BROADCAST_ADDR); + } +#endif /* CONFIG_STA_SUPPORT */ + + MakeOutgoingFrame(frm_buf, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + if (pAd->CommonCfg.ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + } +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG Tmp; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + if (pAd->bBroadComHT == TRUE) + { + HtLen = pAd->MlmeAux.HtCapabilityLen + 4; +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); +#endif /* RT_BIG_ENDIAN */ + } + else + { + HtLen = sizeof(HT_CAPABILITY_IE); +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#endif /* RT_BIG_ENDIAN */ + } + FrameLen += Tmp; + +#ifdef DOT11N_DRAFT3 + if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) + { + ULONG Tmp; + HtLen = 1; + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &ExtHtCapIe, + 1, &HtLen, + 1, &pAd->CommonCfg.BSSCoexist2040.word, + END_OF_ARGS); + + FrameLen += Tmp; + } +#endif /* DOT11N_DRAFT3 */ + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef WSC_INCLUDED + if ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP)) + { + BOOLEAN bHasWscIe = FALSE; + /* + Append WSC information in probe request if WSC state is running + */ + if (pAd->ApCfg.ApCliTab[0].WscControl.bWscTrigger) + { + bHasWscIe = TRUE; + } +#ifdef WSC_V2_SUPPORT + else if (pAd->ApCfg.ApCliTab[0].WscControl.WscV2Info.bEnableWpsV2) + { + bHasWscIe = TRUE; + } +#endif /* WSC_V2_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.ApCliTab[0].SmartMeshCfg.bSupportHiddenWPS) + bHasWscIe = FALSE; +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + if (bHasWscIe) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); + if (pWscBuf != NULL) + { + NdisZeroMemory(pWscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); + } + } +#endif /* WSC_INCLUDED */ +#endif /* APCLI_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->MlmeAux.Channel > 14)) { + FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); + } +#endif /* DOT11_VHT_AC */ + +#ifdef SMART_MESH + if ((OpMode == OPMODE_AP)) + { + if ((IfType == INT_APCLI) +#ifdef APCLI_SUPPORT +#ifdef WSC_INCLUDED + || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP)) +#endif /* WSC_INCLUDED */ +#endif /* APCLI_SUPPORT */ + ) + { + SMART_MESH_INSERT_IE(pAd->ApCfg.ApCliTab[0].SmartMeshCfg, + frm_buf, + FrameLen, + SM_IE_PROBE_REQ); + } + else + { + SMART_MESH_INSERT_IE(pAd->ApCfg.MBSSID[MAIN_MBSSID].SmartMeshCfg, + frm_buf, + FrameLen, + SM_IE_PROBE_REQ); + } + } +#endif /* SMART_MESH */ + + +#ifdef WSC_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + BOOLEAN bHasWscIe = FALSE; + /* + Append WSC information in probe request if WSC state is running + */ + if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && + (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) + bHasWscIe = TRUE; +#ifdef WSC_V2_SUPPORT + else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && + (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) + bHasWscIe = TRUE; +#endif /* WSC_V2_SUPPORT */ + + + if (bHasWscIe) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); + if (pWscBuf != NULL) + { + NdisZeroMemory(pWscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); + } + } + +#endif /* WSC_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT + if ((OpMode == OPMODE_STA) && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen != 0)) + { + ULONG WpsTmpLen = 0; + + MakeOutgoingFrame(frm_buf + FrameLen, &WpsTmpLen, + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen, + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe, + END_OF_ARGS); + + FrameLen += WpsTmpLen; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef RT_CFG80211_SUPPORT + if ((OpMode == OPMODE_STA) && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + CFG80211DRV_OpsScanRunning(pAd)) + { + ULONG ExtraIeTmpLen = 0; + + MakeOutgoingFrame(frm_buf + FrameLen, &ExtraIeTmpLen, + pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, + END_OF_ARGS); + + FrameLen += ExtraIeTmpLen; + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /*CONFIG_STA_SUPPORT*/ + + + MiniportMMRequest(pAd, 0, frm_buf, FrameLen); + +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + /* + To prevent data lost. + Send an NULL data with turned PSM bit on to current associated AP when SCAN in the channel where + associated AP located. + */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + (INFRA_ON(pAd)) && + (pAd->CommonCfg.Channel == pAd->MlmeAux.Channel)) + { + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + PWR_SAVE); + DBGPRINT(RT_DEBUG_TRACE, ("ScanNextChannel():Send PWA NullData frame to notify the associated AP!\n")); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + MlmeFreeMemory(pAd, frm_buf); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Scan next channel + ========================================================================== + */ +VOID ScanNextChannel(RTMP_ADAPTER *pAd, UCHAR OpMode, INT IfType) +{ + UCHAR ScanType = pAd->MlmeAux.ScanType; + UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; + BOOLEAN ScanPending = FALSE; + RALINK_TIMER_STRUCT *sc_timer = NULL; + UINT stay_time = 0; +#ifdef CONFIG_AP_SUPPORT +#ifdef SMART_MESH + BOOLEAN bRadarChannelAPExist = FALSE; +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode. */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (MONITOR_ON(pAd)) + return; + } + + ScanPending = ((pAd->StaCfg.bImprovedScan) && (pAd->StaCfg.ScanChannelCnt>=7)); +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#ifdef RT_CFG80211_SUPPORT + /* Since the Channel List is from Upper layer */ + if (CFG80211DRV_OpsScanRunning(pAd)) + pAd->MlmeAux.Channel = CFG80211DRV_OpsScanGetNextChannel(pAd); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + if ((pAd->MlmeAux.Channel == 0) || ScanPending) + { + scan_ch_restore(pAd, OpMode); + } + else + { +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + /* BBP and RF are not accessible in PS mode, we has to wake them up first*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + + /* leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON*/ + if (pAd->StaCfg.Psm == PWR_SAVE) + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) { + pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_LISTEN; + } +#endif /* CONFIG_AP_SUPPORT */ + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + + { + BOOLEAN bScanPassive = FALSE; + if (pAd->MlmeAux.Channel > 14) + { + if ((pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) + bScanPassive = TRUE; + } +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + bScanPassive = TRUE; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef SMART_MESH + if(OpMode == OPMODE_AP && IsRadarChannelAPExist(pAd,pAd->MlmeAux.Channel)) + { + bRadarChannelAPExist = TRUE; + bScanPassive = FALSE; + } +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + + if (bScanPassive) + { + ScanType = SCAN_PASSIVE; + ScanTimeIn5gChannel = MIN_CHANNEL_TIME; + } + } +#ifdef CONFIG_AP_SUPPORT +#ifdef SMART_MESH + if(!bRadarChannelAPExist) +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + { + /* Check if channel if passive scan under current regulatory domain */ + if ((CHAN_PropertyCheck(pAd, pAd->MlmeAux.Channel, CHANNEL_PASSIVE_SCAN) == TRUE)) + ScanType = SCAN_PASSIVE; + } + + + if (OpMode == OPMODE_AP) + sc_timer = &pAd->MlmeAux.APScanTimer; + else + sc_timer = &pAd->MlmeAux.ScanTimer; + pAd->MlmeAux.ScanInfType = IfType; + + /* We need to shorten active scan time in order for WZC connect issue */ + /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */ + if (ScanType == FAST_SCAN_ACTIVE) + stay_time = FAST_ACTIVE_SCAN_TIME; + else /* must be SCAN_PASSIVE or SCAN_ACTIVE*/ + { +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.ScanChannelCnt++; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if ((OpMode == OPMODE_AP) && (pAd->ApCfg.bAutoChannelAtBootup)) + stay_time = AUTO_CHANNEL_SEL_TIMEOUT; + else +#endif /* CONFIG_AP_SUPPORT */ + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode) && + WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + if (pAd->MlmeAux.Channel > 14) + { +#ifdef CUSTOMER_DCC_FEATURE + if(pAd->MlmeAux.ScanTime != 0) + { + stay_time = pAd->MlmeAux.ScanTime; + } + else +#endif + stay_time = ScanTimeIn5gChannel; + } + else { +#ifdef CUSTOMER_DCC_FEATURE + if(pAd->MlmeAux.ScanTime != 0) + { + stay_time = pAd->MlmeAux.ScanTime; + } + else +#endif + stay_time = MIN_CHANNEL_TIME; + } + } + else +#ifdef CUSTOMER_DCC_FEATURE + if(pAd->MlmeAux.ScanTime != 0) + { + stay_time = pAd->MlmeAux.ScanTime; + } + else +#endif + stay_time = MAX_CHANNEL_TIME; + } + +#ifdef SMART_MESH + if (pAd->ApCfg.ScanTime != 0) + stay_time = pAd->ApCfg.ScanTime; +#endif /* SMART_MESH */ + RTMPSetTimer(sc_timer, stay_time); + + if (SCAN_MODE_ACT(ScanType)) + { + if (scan_active(pAd, OpMode, ScanType, IfType) == FALSE) + return; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (pAd->ApCfg.bPartialScanning == TRUE) + { + /* Enhance Connectivity & for Hidden Ssid Scanning*/ + CHAR backSsid[MAX_LEN_OF_SSID]; + UCHAR desiredSsidLen, backSsidLen; + + desiredSsidLen= pAd->ApCfg.ApCliTab[0].CfgSsidLen; + + if (desiredSsidLen > 0) + { + //printk("=====================>specific the %s scanning\n", pAd->ApCfg.ApCliTab[0].CfgSsid); + /* 1. backup the original MlmeAux */ + backSsidLen = pAd->MlmeAux.SsidLen; + NdisCopyMemory(backSsid, pAd->MlmeAux.Ssid, backSsidLen); + + /* 2. fill the desried ssid into SM */ + pAd->MlmeAux.SsidLen = desiredSsidLen; + NdisCopyMemory(pAd->MlmeAux.Ssid, pAd->ApCfg.ApCliTab[0].CfgSsid, desiredSsidLen); + + /* 3. scan action */ + scan_active(pAd, OpMode, ScanType, IfType); + + /* 4. restore to MlmeAux */ + pAd->MlmeAux.SsidLen = backSsidLen; + NdisCopyMemory(pAd->MlmeAux.Ssid, backSsid, backSsidLen); + } + } +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + + /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse*/ + +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +BOOLEAN ScanRunning(RTMP_ADAPTER *pAd) +{ + BOOLEAN rv = FALSE; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) || (pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING)) + rv = TRUE; + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + rv = ((pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE); +#endif /* AP_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + return rv; +} + + +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR EChannel[11]; + UCHAR i, j, k; + UCHAR UpperChannel = 0, LowerChannel = 0; + + RTMPZeroMemory(EChannel, 11); + DBGPRINT(RT_DEBUG_TRACE, ("BuildEffectedChannelList:CtrlCh=%d,CentCh=%d,AuxCtrlCh=%d,AuxExtCh=%d\n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel, + pAd->MlmeAux.AddHtInfo.ControlChan, + pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset)); + + /* 802.11n D4 11.14.3.3: If no secondary channel has been selected, all channels in the frequency band shall be scanned. */ + { + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel <=14 ) + pAd->ChannelList[k].bEffectedChannel = TRUE; + } + return; + } + + i = 0; + /* Find upper and lower channel according to 40MHz current operation. */ + if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + { + UpperChannel = pAd->CommonCfg.Channel; + LowerChannel = pAd->CommonCfg.CentralChannel-2; + } + else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + { + UpperChannel = pAd->CommonCfg.CentralChannel+2; + LowerChannel = pAd->CommonCfg.Channel; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("LinkUP 20MHz . No Effected Channel \n")); + /* Now operating in 20MHz, doesn't find 40MHz effected channels */ + return; + } + + DeleteEffectedChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("BuildEffectedChannelList!LowerChannel ~ UpperChannel; %d ~ %d \n", LowerChannel, UpperChannel)); + + /* Find all channels that are below lower channel.. */ + if (LowerChannel > 1) + { + EChannel[0] = LowerChannel - 1; + i = 1; + if (LowerChannel > 2) + { + EChannel[1] = LowerChannel - 2; + i = 2; + if (LowerChannel > 3) + { + EChannel[2] = LowerChannel - 3; + i = 3; + } + } + } + /* Find all channels that are between lower channel and upper channel. */ + for (k = LowerChannel;k <= UpperChannel;k++) + { + EChannel[i] = k; + i++; + } + /* Find all channels that are above upper channel.. */ + if (UpperChannel < 14) + { + EChannel[i] = UpperChannel + 1; + i++; + if (UpperChannel < 13) + { + EChannel[i] = UpperChannel + 2; + i++; + if (UpperChannel < 12) + { + EChannel[i] = UpperChannel + 3; + i++; + } + } + } + /* + Total i channels are effected channels. + Now find corresponding channel in ChannelList array. Then set its bEffectedChannel= TRUE + */ + for (j = 0;j < i;j++) + { + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel == EChannel[j]) + { + pAd->ChannelList[k].bEffectedChannel = TRUE; + DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel[%d]( =%d)\n", k, EChannel[j])); + break; + } + } + } +} + + +VOID DeleteEffectedChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + /*Clear all bEffectedChannel in ChannelList array. */ + for (i = 0; i < pAd->ChannelListNum; i++) + { + pAd->ChannelList[i].bEffectedChannel = FALSE; + } +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +VOID ScanParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN STRING Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType) +{ + NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID); + ScanReq->SsidLen = SsidLen; + NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen); + ScanReq->BssType = BssType; + ScanReq->ScanType = ScanType; +} +#endif /* defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) */ + + +#endif /* SCAN_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/smart_mesh.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/smart_mesh.c new file mode 100644 index 000000000..4a7365446 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/smart_mesh.c @@ -0,0 +1,2555 @@ +#ifdef SMART_MESH +#include "rt_config.h" +UCHAR NETGEAR_OUI[NTGR_OUI_LEN] = {0x00, 0x14, 0x6c}; + +INT smart_mesh_ie_init(PSMART_MESH_CFG pSmartMeshCfg) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + pSmartMeshCfg->ie_ctrl_flags = SM_IE_ALL; + pNtgr_IE->id = IE_VENDOR_SPECIFIC; + pNtgr_IE->len = NTGR_OUI_LEN; + NdisCopyMemory(pNtgr_IE->oui, NETGEAR_OUI, sizeof(NETGEAR_OUI)); + + return TRUE; +} + +INT smart_mesh_init(PSMART_MESH_CFG pSmartMeshCfg) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + pSmartMeshCfg->bSupportSmartMesh = FALSE; + smart_mesh_ie_init(pSmartMeshCfg); + pNtgr_IE->len += 1; /* basic need 1 bytes*/ + return TRUE; +} + +#ifdef MWDS +INT dwds_init(PSMART_MESH_CFG pSmartMeshCfg) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + smart_mesh_ie_init(pSmartMeshCfg); + pNtgr_IE->len += 1; /* basic need 1 bytes*/ + return TRUE; +} +#endif /* MWDS */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT hidden_wps_init(PSMART_MESH_CFG pSmartMeshCfg) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + smart_mesh_ie_init(pSmartMeshCfg); + pNtgr_IE->len += NTGR_CUSTOM_IE_MAX_LEN; /* basic need 3 bytes*/ + return TRUE; +} +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +INT smart_mesh_enable(PSMART_MESH_CFG pSmartMeshCfg, BOOLEAN Enable) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + pSmartMeshCfg->bSupportSmartMesh = Enable; + if(Enable) + { + /* NTGR IE: Set SmartMesh bit */ + pNtgr_IE->private[0] |= 0x2; //SmartMesh bit + + DBGPRINT(RT_DEBUG_TRACE, (" SmartMesh Mode (ON)\n")); + } + else + { + /* Clear SmartMesh bit */ + pNtgr_IE->private[0] &= (~0x2); //SmartMesh bit + DBGPRINT(RT_DEBUG_TRACE, (" SmartMesh Mode (OFF)\n")); + } + + return TRUE; +} + +#ifdef MWDS +INT dwds_enable(PSMART_MESH_CFG pSmartMeshCfg, BOOLEAN Enable) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + if(Enable) + { + /* NTGR IE: Set DWDS bit */ + pNtgr_IE->private[0] |= 0x1; //DWDS bit + DBGPRINT(RT_DEBUG_TRACE, (" DWDS (ON)\n")); + } + else + { + /* Clear DWDS bit */ + pNtgr_IE->private[0] &= (~0x1); //DWDS bit + DBGPRINT(RT_DEBUG_TRACE, (" DWDS (OFF)\n")); + } + + return TRUE; +} +#endif /* MWDS */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT hidden_wps_enable(PSMART_MESH_CFG pSmartMeshCfg, BOOLEAN Enable) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + pSmartMeshCfg->bSupportHiddenWPS = Enable; + if(Enable) + { + /* NTGR IE: Set Hidden WPS bit */ + pNtgr_IE->private[0] |= 0x4; + DBGPRINT(RT_DEBUG_TRACE, (" HiddenWPS (ON)\n")); + } + else + { + /* Clear Hidden WPS bit */ + pNtgr_IE->private[0] &= (~0x4); + DBGPRINT(RT_DEBUG_TRACE, (" HiddenWPS (OFF)\n")); + } + + return TRUE; +} + +INT Set_HiddenWps_State(PSMART_MESH_CFG pSmartMeshCfg, UINT8 state) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + if(pSmartMeshCfg->bSupportHiddenWPS && + (pNtgr_IE->len >= NTGR_CUSTOM_IE_MAX_LEN)) + { + if(state == HIDDEN_WPS_STATE_STOP) + pNtgr_IE->private[NTGR_CUSTOM_IE_MAX_LEN-1] &= (~HIDDEN_WPS_STATE_RUNNING); + else if(state == HIDDEN_WPS_STATE_RUNNING) + pNtgr_IE->private[NTGR_CUSTOM_IE_MAX_LEN-1] |= HIDDEN_WPS_STATE_RUNNING; + } + + return TRUE; +} + +INT Set_HiddenWps_Role(PSMART_MESH_CFG pSmartMeshCfg, UINT8 role) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + + if(pSmartMeshCfg->bSupportHiddenWPS && + (pNtgr_IE->len >= NTGR_CUSTOM_IE_MAX_LEN)) + { + if(role == HIDDEN_WPS_ROLE_ENROLLEE) + pNtgr_IE->private[NTGR_CUSTOM_IE_MAX_LEN-1] &= (~HIDDEN_WPS_ROLE_REGISTRAR); + else if(role == HIDDEN_WPS_ROLE_REGISTRAR) + pNtgr_IE->private[NTGR_CUSTOM_IE_MAX_LEN-1] |= HIDDEN_WPS_ROLE_REGISTRAR; + } + + return TRUE; +} +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +INT Set_Enable_SmartMesh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN BOOLEAN isAP) +{ + UCHAR Enable; + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(isAP) + { + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + } +#ifdef APCLI_SUPPORT + else + { + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + } +#endif /* APCLI_SUPPORT */ + + if(!pSmartMeshCfg) + return FALSE; + + Enable = simple_strtol(arg, 0, 10); + if (Enable) + { + smart_mesh_init(pSmartMeshCfg); + smart_mesh_enable(pSmartMeshCfg,TRUE); + } + else + { + smart_mesh_enable(pSmartMeshCfg,FALSE); + } + DBGPRINT(RT_DEBUG_TRACE, (" SmartMesh Mode = %d \n",pSmartMeshCfg->bSupportSmartMesh)); + + return TRUE; +} + +INT Set_Enable_DWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN BOOLEAN isAP) +{ + UCHAR Enable; + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(isAP) + { + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + } +#ifdef APCLI_SUPPORT + else + { + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + } +#endif /* APCLI_SUPPORT */ + + if(!pSmartMeshCfg) + return FALSE; + + Enable = simple_strtol(arg, 0, 10); +#ifdef MWDS + if (Enable) + { + dwds_init(pSmartMeshCfg); + dwds_enable(pSmartMeshCfg,TRUE); + MWDSEnable(pAd,ifIndex,isAP); + } + else + { + dwds_enable(pSmartMeshCfg,FALSE); + MWDSDisable(pAd,ifIndex,isAP); + } +#endif /* MWDS */ + DBGPRINT(RT_DEBUG_TRACE, (" DWDS mode = %d \n",Enable)); + + return TRUE; +} + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT Set_Enable_HiddenWPS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN BOOLEAN isAP) +{ + UCHAR Enable; + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(isAP) + { + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + } +#ifdef APCLI_SUPPORT + else + { + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + } +#endif /* APCLI_SUPPORT */ + + if(!pSmartMeshCfg) + return FALSE; + + Enable = simple_strtol(arg, 0, 10); + if (Enable) + { + hidden_wps_init(pSmartMeshCfg); + hidden_wps_enable(pSmartMeshCfg,TRUE); + } + else + { + Set_HiddenWps_State(pSmartMeshCfg, HIDDEN_WPS_STATE_STOP); + Set_HiddenWps_Role(pSmartMeshCfg, HIDDEN_WPS_ROLE_ENROLLEE); + hidden_wps_enable(pSmartMeshCfg,FALSE); + } + + DBGPRINT(RT_DEBUG_TRACE, (" HiddenWPS mode = %d \n",Enable)); + + return TRUE; +} +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef APCLI_SUPPORT +INT Set_ApCli_SmartMesh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Enable_SmartMesh_Proc(pAd,arg,FALSE); +} + +INT Set_ApCli_SmartMesh_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PNTGR_IE pNtgr_IE = NULL; + BOOLEAN bEnable; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type == INT_APCLI) && (ifIndex < MAX_APCLI_NUM)) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + else + return FALSE; + + if(pSmartMeshCfg) + { + pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + if(pSmartMeshCfg->bSupportSmartMesh && (pNtgr_IE->private[0]&0x2)) + bEnable = TRUE; + else + bEnable = FALSE; + printk("%d\n",bEnable); + } + + return TRUE; +} + +INT Set_ApCli_DWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Enable_DWDS_Proc(pAd,arg,FALSE); +} + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT Set_ApCli_HiddenWPS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Enable_HiddenWPS_Proc(pAd,arg,FALSE); +} + +INT Set_ApCli_HiddenWPS_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PNTGR_IE pNtgr_IE = NULL; + BOOLEAN bEnable; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type == INT_APCLI) && (ifIndex < MAX_APCLI_NUM)) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + else + return FALSE; + + if(pSmartMeshCfg) + { + pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + if(pSmartMeshCfg->bSupportHiddenWPS && (pNtgr_IE->private[0]&0x4)) + bEnable = TRUE; + else + bEnable = FALSE; + printk("%d\n",bEnable); + } + + return TRUE; +} +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +INT Set_Ap_SmartMesh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Enable_SmartMesh_Proc(pAd,arg,TRUE); +} + +INT Set_Ap_SmartMesh_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PNTGR_IE pNtgr_IE = NULL; + BOOLEAN bEnable; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + else + return FALSE; + + if(pSmartMeshCfg) + { + pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + if(pSmartMeshCfg->bSupportSmartMesh && (pNtgr_IE->private[0]&0x2)) + bEnable = TRUE; + else + bEnable = FALSE; + printk("%d\n",bEnable); + } + + return TRUE; +} + +INT Set_Ap_DWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Enable_DWDS_Proc(pAd,arg,TRUE); +} + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT Set_Ap_HiddenWPS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Enable_HiddenWPS_Proc(pAd,arg,TRUE); +} + +INT Set_Ap_HiddenWPS_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PNTGR_IE pNtgr_IE = NULL; + BOOLEAN bEnable; + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + else + return FALSE; + + if(pSmartMeshCfg) + { + pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + if(pSmartMeshCfg->bSupportHiddenWPS && (pNtgr_IE->private[0]&0x4)) + bEnable = TRUE; + else + bEnable = FALSE; + printk("%d\n",bEnable); + } + + return TRUE; +} +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +INT Set_Ap_SmartMesh_ACL_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + UCHAR Enable = FALSE; + + POS_COOKIE pObj; + UCHAR ifIndex; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + ifIndex = pObj->ioctl_if; + Enable = simple_strtol(arg, 0, 10); + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pAd->ApCfg.MBSSID[ifIndex].bSmartMeshACL = Enable; + break; + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, (" bSmartMeshACL = %d \n",Enable)); + + return TRUE; +} + +INT smart_mesh_set_ie(PRTMP_ADAPTER pAd, PSMART_MESH_CFG pSmartMeshCfg, + PUINT8 value,INT len, BOOLEAN isAP) +{ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + UINT8 CurPrivLen = 0,CustomContent = 0; + + if((value != NULL) && (len > 0)) + { + if(len > NTGR_IE_PRIV_LEN) + { + DBGPRINT(RT_DEBUG_ERROR, + ("The input data length over buffer size! (Maximum is %d)\n",NTGR_IE_PRIV_LEN)); + return FALSE; + } + if(pNtgr_IE->len >= NTGR_OUI_LEN) + CurPrivLen = pNtgr_IE->len - NTGR_OUI_LEN; + + if(CurPrivLen >= NTGR_CUSTOM_IE_MAX_LEN) + CustomContent = pNtgr_IE->private[NTGR_CUSTOM_IE_MAX_LEN-1]; + +#ifdef MWDS + /* DWDS */ + if((*value & 0x1)) + Set_Enable_DWDS_Proc(pAd, "1", isAP); + else + Set_Enable_DWDS_Proc(pAd, "0", isAP); +#endif /* MWDS */ + + /* Smart Mesh */ + if((*value & 0x2)) + Set_Enable_SmartMesh_Proc(pAd, "1", isAP); + else + Set_Enable_SmartMesh_Proc(pAd, "0", isAP); + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + /* Hidden WPS */ + if((*value & 0x4)) + Set_Enable_HiddenWPS_Proc(pAd, "1", isAP); + else + Set_Enable_HiddenWPS_Proc(pAd, "0", isAP); +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + smart_mesh_ie_init(pSmartMeshCfg); + NdisZeroMemory(pNtgr_IE->private,NTGR_IE_PRIV_LEN); + NdisCopyMemory(pNtgr_IE->private, value, len); + pNtgr_IE->len += len; + + if(pNtgr_IE->len >= NTGR_OUI_LEN) + CurPrivLen = pNtgr_IE->len - NTGR_OUI_LEN; + + if(CurPrivLen < NTGR_CUSTOM_IE_MAX_LEN) + pNtgr_IE->len = (NTGR_OUI_LEN + NTGR_CUSTOM_IE_MAX_LEN); + + pNtgr_IE->private[NTGR_CUSTOM_IE_MAX_LEN-1] = CustomContent; + } + + return TRUE; +} + +INT Set_SmartMesh_IE_Proc( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + INT len,private_Len = 0; + POS_COOKIE pObj; + UCHAR ifIndex,buf[256],private[NTGR_IE_PRIV_LEN]; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PNTGR_IE pNtgr_IE; + BOOLEAN isAP = FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + { + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + isAP = TRUE; + } + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if(!pSmartMeshCfg) + return FALSE; + + strncpy(buf,arg,sizeof(buf)); + len = strlen(buf); + if(len > 0) + { + if((len%2 != 0)) + { + buf[len]='0'; + len++; + } + + AtoH(buf, private, len); + private_Len = len/2; + smart_mesh_set_ie(pAd, pSmartMeshCfg, private, private_Len, isAP); + } + return TRUE; +} + + +/* + bit 0 - Beacon + bit 1 - Probe Rsp + bit 2 - Assoc Rsp + bit 3 - Auth Rsp + bit 4 - Probe Req + bit 5 - Assoc Req + Ex iwpriv ra0/apcli0 set SmIeCtrl=1f +*/ +INT Set_SmartMesh_IE_Crtl_Proc( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + UINT32 ie_ctrl_flags; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + ie_ctrl_flags = simple_strtol(arg, 0, 16); + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + pSmartMeshCfg->ie_ctrl_flags = ie_ctrl_flags; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): ie_ctrl_flags = 0x%08x\n",__FUNCTION__, pSmartMeshCfg->ie_ctrl_flags)); + + return TRUE; +} + +INT Set_SmartMesh_IE_Show_Proc( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex,i; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PNTGR_IE pNtgr_IE = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + pNtgr_IE = &pSmartMeshCfg->Ntgr_IE; + for(i=0;iprivate[i]); + printk("\n"); + +#ifdef ACOS_PATCH /* foxconn */ + if (arg && copy_to_user(arg, pNtgr_IE, sizeof(NTGR_IE))) + return FALSE; +#endif + + return TRUE; +} + +INT Set_SmartMesh_Unicast_ProbeReq_SSID_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex,i; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PUNI_PROBE_REQ_CFG pUniProbeReqCfg = NULL; + PNTGR_IE pNtgr_IE = NULL; + UINT8 ssid_len = 0; + + ssid_len = strlen(arg); + if(ssid_len > MAX_LEN_OF_SSID) + return FALSE; + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + pUniProbeReqCfg = &pSmartMeshCfg->UniProbeReqCfg; + + NdisZeroMemory(pUniProbeReqCfg->ssid, sizeof(pUniProbeReqCfg->ssid)); + NdisMoveMemory(pUniProbeReqCfg->ssid, arg, ssid_len); + pUniProbeReqCfg->ssid_len = ssid_len; + + return TRUE; +} + +INT Enqueue_SmartMesh_UnicastProbeReq(RTMP_ADAPTER *pAd, UCHAR ScanType, INT IfType, INT ifIndex) +{ + UCHAR *frm_buf = NULL, SsidLen = 0; + HEADER_802_11 Hdr80211; + ULONG FrameLen = 0; + PUNI_PROBE_REQ_CFG pUniProbeReqCfg = NULL; + + if(IfType == INT_APCLI) + pUniProbeReqCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg.UniProbeReqCfg; + else + pUniProbeReqCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg.UniProbeReqCfg; + + if (!pUniProbeReqCfg) + return FALSE; + + if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): allocate memory fail\n",__func__)); + return FALSE; + } + + if(IfType == INT_APCLI) + pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState = APCLI_SYNC_IDLE; + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + + SsidLen = pUniProbeReqCfg->ssid_len; + MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pUniProbeReqCfg->addr1, + pUniProbeReqCfg->addr2,BROADCAST_ADDR); + + MakeOutgoingFrame(frm_buf, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pUniProbeReqCfg->ssid, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + if (pAd->CommonCfg.ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG Tmp; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + if (pAd->bBroadComHT == TRUE) + { + HtLen = pAd->MlmeAux.HtCapabilityLen + 4; +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); +#endif /* RT_BIG_ENDIAN */ + } + else + { + HtLen = sizeof(HT_CAPABILITY_IE); +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#endif /* RT_BIG_ENDIAN */ + } + FrameLen += Tmp; + +#ifdef DOT11N_DRAFT3 + if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) + { + ULONG Tmp; + HtLen = 1; + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &ExtHtCapIe, + 1, &HtLen, + 1, &pAd->CommonCfg.BSSCoexist2040.word, + END_OF_ARGS); + + FrameLen += Tmp; + } +#endif /* DOT11N_DRAFT3 */ + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef WSC_INCLUDED + if (ScanType == SCAN_WSC_ACTIVE) + { + BOOLEAN bHasWscIe = FALSE; + /* + Append WSC information in probe request if WSC state is running + */ + if (pAd->ApCfg.ApCliTab[0].WscControl.bWscTrigger) + { + bHasWscIe = TRUE; + } +#ifdef WSC_V2_SUPPORT + else if (pAd->ApCfg.ApCliTab[0].WscControl.WscV2Info.bEnableWpsV2) + { + bHasWscIe = TRUE; + } +#endif /* WSC_V2_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg.bSupportHiddenWPS) + bHasWscIe = FALSE; +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + + if (bHasWscIe) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); + if (pWscBuf != NULL) + { + NdisZeroMemory(pWscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); + } + } +#endif /* WSC_INCLUDED */ +#endif /* APCLI_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->MlmeAux.Channel > 14)) { + FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); + } +#endif /* DOT11_VHT_AC */ + + if (IfType == INT_APCLI) + { + SMART_MESH_INSERT_IE(pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg, + frm_buf, + FrameLen, + SM_IE_PROBE_REQ); + } + else + { + SMART_MESH_INSERT_IE(pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg, + frm_buf, + FrameLen, + SM_IE_PROBE_REQ); + } + + MiniportMMRequest(pAd, 0, frm_buf, FrameLen); + + MlmeFreeMemory(pAd, frm_buf); + + return TRUE; +} + +INT Set_SmartMesh_Unicast_ProbeReq_Send_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + PUNI_PROBE_REQ_CFG pUniProbeReqCfg = NULL; + PSTRING value; + INT i; + + if (strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address length! (acceptable format 01:02:03:04:05:06 length 17)\n")); + return FALSE; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + pUniProbeReqCfg = &pSmartMeshCfg->UniProbeReqCfg; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address format or octet!\n")); + /* Do not use "continue" to replace "break" */ + break; + } + AtoH(value, &pUniProbeReqCfg->addr1[i++], 1); + } + + if (i != MAC_ADDR_LEN) + { + DBGPRINT(RT_DEBUG_ERROR, ("MAC address length is wrong!\n")); + return FALSE; + } + + if(pObj->ioctl_if_type == INT_APCLI) + COPY_MAC_ADDR(pUniProbeReqCfg->addr2,pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); + else + COPY_MAC_ADDR(pUniProbeReqCfg->addr2,pAd->ApCfg.MBSSID[ifIndex].wdev.bssid); + + return Enqueue_SmartMesh_UnicastProbeReq(pAd,pAd->MlmeAux.ScanType,pObj->ioctl_if_type,ifIndex); +} + +INT Set_SmartMesh_DFSScanAP_Enable_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + INT i; + BOOLEAN Enable = FALSE; + + if (pAd->CommonCfg.bIEEE80211H == TRUE) + { + Enable = simple_strtol(arg, 0, 10); + /* Reset all DFS channel first */ + for (i=0; i < pAd->ChannelListNum; i++) + { + if(pAd->ChannelList[i].DfsReq) + pAd->ChannelList[i].bDfsAPExist = FALSE; + } + + pAd->ApCfg.bDFSAPScanEnable = Enable; + } + + return TRUE; +} + +INT Set_SmartMesh_DFSScanAP_Show_Proc(PRTMP_ADAPTER pAd,PSTRING arg) +{ + INT i,j,count; + UCHAR Ch = 0; + BSS_TABLE *pTab = &pAd->ScanTab; + BSS_ENTRY *pBss = NULL; + + if(pAd->CommonCfg.bIEEE80211H == TRUE) + { + for (i=0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].DfsReq && + (pAd->ChannelList[i].Channel > 14) && + (pAd->ChannelList[i].bDfsAPExist)) + { + count = 0; + Ch = pAd->ChannelList[i].Channel; + for (j = 0; j < pTab->BssNr; j++) + { + pBss = &pTab->BssEntry[j]; + if ((pBss->Channel == Ch) && pBss->bDfsAP) + count++; + } + printk("Channel:%d\tCount:%d\n",Ch,count); + } + } + } + + return TRUE; +} + +VOID Set_Check_RadarChannelAP(PRTMP_ADAPTER pAd,UCHAR Ch,BSS_ENTRY *pBss) +{ + INT i; + + if(pAd->ApCfg.bDFSAPScanEnable != TRUE) + return; + + if(pBss) + { + if ((Ch > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + for (i=0; i < pAd->ChannelListNum; i++) + { + if (Ch == pAd->ChannelList[i].Channel) + { + if(pAd->ChannelList[i].DfsReq) + pBss->bDfsAP = TRUE; + else + pBss->bDfsAP = FALSE; + break; + } + } + } + } +} + +VOID Set_Check_RadarChannelAPExist(PRTMP_ADAPTER pAd) +{ + INT i,j; + UCHAR Ch = 0; + BSS_TABLE *pTab = &pAd->ScanTab; + BSS_ENTRY *pBss = NULL; + + if(pAd->ApCfg.bDFSAPScanEnable != TRUE) + return; + + if(pAd->CommonCfg.bIEEE80211H == TRUE) + { + for (i=0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].DfsReq && + (pAd->ChannelList[i].Channel > 14)) + { + pAd->ChannelList[i].bDfsAPExist = FALSE; + Ch = pAd->ChannelList[i].Channel; + for (j = 0; j < pTab->BssNr; j++) + { + pBss = &pTab->BssEntry[j]; + if (pBss->bDfsAP) + { + pAd->ChannelList[i].bDfsAPExist = TRUE; + break; + } + } + } + } + } +} + +BOOLEAN IsRadarChannelAPExist(PRTMP_ADAPTER pAd,UCHAR Ch) +{ + INT i; + BOOLEAN result = FALSE; + + if(pAd->ApCfg.bDFSAPScanEnable != TRUE) + return FALSE; + + if ((Ch > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + for (i=0; i < pAd->ChannelListNum; i++) + { + if (Ch == pAd->ChannelList[i].Channel) + { + result = pAd->ChannelList[i].bDfsAPExist; + break; + } + } + } + + return result; +} + +BOOLEAN Set_Scan_False_CCA(PRTMP_ADAPTER pAd,UCHAR ch_index, UCHAR type) +{ + INT i; + + if (type == CCA_RESET) + { + for (i = 0;i < pAd->ChannelListNum;i++) + { + pAd->ChannelList[i].FalseCCA = 0; + } + pAd->ApCfg.scan_channel_index = 0; + } + + if (type == CCA_STORE) + { + RX_STA_CNT1_STRUC RxStaCnt1; + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + pAd->ChannelList[ch_index].FalseCCA += RxStaCnt1.field.FalseCca; + } + + return TRUE; +} + +INT Set_SmartMesh_HyperFiPeer_Filter_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + UCHAR Enable = FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + Enable = simple_strtol(arg, 0, 10); + pSmartMeshCfg->bHiFiPeerFilter = Enable; + + return TRUE; +} + +INT Set_SmartMesh_HyperFiFlagMask_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + pSmartMeshCfg->HiFiFlagMask = simple_strtol(arg, 0, 10); + + return TRUE; +} + +INT Set_SmartMesh_HyperFiFlagValue_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pSmartMeshCfg) + return FALSE; + + pSmartMeshCfg->HiFiFlagValue = simple_strtol(arg, 0, 10); + + return TRUE; +} + +#ifdef WSC_AP_SUPPORT +ULONG Get_BssSsidTableSearchByMAC(BSS_TABLE *Tab, UCHAR *pBssAddr) +{ + UCHAR i; + + if(Tab && pBssAddr) + { + for (i = 0; i < Tab->BssNr; i++) + { + if (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssAddr)) + { + return i; + } + } + } + + return (ULONG)BSS_NOT_FOUND; +} + +INT Set_SmartMesh_WscPBCMAC_Proc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + PWSC_CTRL pWscControl = NULL; + PSTRING value; + INT i; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + pWscControl = &pAd->ApCfg.MBSSID[ifIndex].WscControl; + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + pWscControl = &pAd->ApCfg.ApCliTab[ifIndex].WscControl; + break; +#endif /* APCLI_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR,("%s(): Invalid interface (%u).\n",__FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if (!pWscControl) + return FALSE; + + pWscControl->bWscPBCAddrMode = FALSE; + if (strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address length! (acceptable format 01:02:03:04:05:06 length 17)\n")); + return FALSE; + } + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address format or octet!\n")); + /* Do not use "continue" to replace "break" */ + break; + } + AtoH(value, &pWscControl->WscPBCAddr[i++], 1); + } + + if (i != MAC_ADDR_LEN) + { + DBGPRINT(RT_DEBUG_ERROR, ("MAC address length is wrong!\n")); + return FALSE; + } + + /* Help to change to PBC mode */ + pWscControl->WscMode = WSC_PBC_MODE; + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + + pWscControl->bWscPBCAddrMode = TRUE; + return TRUE; +} +#endif /* WSC_AP_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +INT Set_vMacPrefix_Show_Proc( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + UCHAR i,len; + if(pAd) + { + len = sizeof(pAd->vMacAddrPrefix); + for(i=0;ivMacAddrPrefix[i]); + printk("\n"); + + #ifdef ACOS_PATCH /* foxconn */ + if (arg && copy_to_user(arg, pAd->vMacAddrPrefix, len)) + return FALSE; + #endif + } + + return TRUE; +} +#endif /* MAC_REPEATER_SUPPORT */ + +VOID rtmp_read_smart_mesh_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer) +{ + + PSTRING tmpptr = NULL; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + +#ifdef CONFIG_AP_SUPPORT + /* ApSmartMesh */ + if(RTMPGetKeyParameter("ApSmartMesh", 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; + + pSmartMeshCfg = &pAd->ApCfg.MBSSID[i].SmartMeshCfg; + if (Value == 0) + { + smart_mesh_enable(pSmartMeshCfg,FALSE); + } + else + { + smart_mesh_init(pSmartMeshCfg); + smart_mesh_enable(pSmartMeshCfg,TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApSmartMesh=%d\n", Value)); + } + } +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + /* ApHiddenWPS */ + if(RTMPGetKeyParameter("ApHiddenWPS", 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; + + pSmartMeshCfg = &pAd->ApCfg.MBSSID[i].SmartMeshCfg; + if (Value == 0) + { + hidden_wps_enable(pSmartMeshCfg,FALSE); + } + else + { + hidden_wps_init(pSmartMeshCfg); + hidden_wps_enable(pSmartMeshCfg,TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApSmartMesh=%d\n", Value)); + } + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef APCLI_SUPPORT + /* ApCliSmartMesh */ + if(RTMPGetKeyParameter("ApCliSmartMesh", 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; + + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[i].SmartMeshCfg; + if (Value == 0) + { + smart_mesh_enable(pSmartMeshCfg,FALSE); + } + else + { + smart_mesh_init(pSmartMeshCfg); + smart_mesh_enable(pSmartMeshCfg,TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliSmartMesh=%d\n", Value)); + } + } +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + /* ApCliHiddenWPS */ + if(RTMPGetKeyParameter("ApCliHiddenWPS", 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; + + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[i].SmartMeshCfg; + if (Value == 0) + { + hidden_wps_enable(pSmartMeshCfg,FALSE); + } + else + { + hidden_wps_init(pSmartMeshCfg); + hidden_wps_enable(pSmartMeshCfg,TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliSmartMesh=%d\n", Value)); + } + } +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ +} + +#ifdef MWDS +VOID rtmp_read_DWDS_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer) +{ + PSTRING tmpptr = NULL; + PSMART_MESH_CFG pSmartMeshCfg = NULL; + +#ifdef CONFIG_AP_SUPPORT + /* ApDWDS */ + if(RTMPGetKeyParameter("ApDWDS", 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; + + pSmartMeshCfg = &pAd->ApCfg.MBSSID[i].SmartMeshCfg; + if (Value == 0) + { + dwds_enable(pSmartMeshCfg,FALSE); + MWDSDisable(pAd,i,TRUE); + } + else + { + dwds_init(pSmartMeshCfg); + dwds_enable(pSmartMeshCfg,TRUE); + MWDSEnable(pAd,i,TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApDWDS=%d\n", Value)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef APCLI_SUPPORT + /* ApCliDWDS */ + if(RTMPGetKeyParameter("ApCliDWDS", 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; + + pSmartMeshCfg = &pAd->ApCfg.ApCliTab[i].SmartMeshCfg; + if (Value == 0) + { + dwds_enable(pSmartMeshCfg,FALSE); + MWDSDisable(pAd,i,FALSE); + } + else + { + dwds_init(pSmartMeshCfg); + dwds_enable(pSmartMeshCfg,TRUE); + MWDSEnable(pAd,i,FALSE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliDWDS=%d\n", Value)); + } + } +#endif /* APCLI_SUPPORT */ +} +#endif /* MWDS */ + +INT Set_Cli_Status_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + SMART_MESH_CLI_INFO cli_info; + PMAC_TABLE_ENTRY pEntry = NULL; + HTTRANSMIT_SETTING RX_HTSetting,TX_HTSetting; + + for (i=1; iMacTab.Content[i]; + + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + && (pEntry->Sst == SST_ASSOC)) + { + NdisZeroMemory(&cli_info, sizeof(SMART_MESH_CLI_INFO)); + cli_info.aid = pEntry->Aid; + cli_info.last_rssi[0] = pEntry->RssiSample.LastRssi0; + cli_info.last_rssi[1] = pEntry->RssiSample.LastRssi1; + cli_info.last_rssi[2] = pEntry->RssiSample.LastRssi2; + cli_info.last_snr[0] = pEntry->RssiSample.LastSnr0; + cli_info.last_snr[1] = pEntry->RssiSample.LastSnr1; + cli_info.last_snr[2] = pEntry->RssiSample.LastSnr2; + + /* RX Info */ + NdisCopyMemory(&RX_HTSetting, &pEntry->LastRxRate, sizeof(RX_HTSetting)); +#ifdef DOT11_VHT_AC + if(RX_HTSetting.field.MODE >= MODE_VHT) + cli_info.rx_mcs = RX_HTSetting.field.MCS & 0x0F; + else +#endif /* DOT11_VHT_AC */ + cli_info.rx_mcs = RX_HTSetting.field.MCS; + cli_info.rx_stream = newRateGetAntenna(RX_HTSetting.field.MCS,RX_HTSetting.field.MODE); + + cli_info.rx_bw = RX_HTSetting.field.BW; + cli_info.rx_sgi = RX_HTSetting.field.ShortGI; + cli_info.rx_phymode = RX_HTSetting.field.MODE; + + /* TX Info */ + NdisCopyMemory(&TX_HTSetting, &pEntry->HTPhyMode, sizeof(TX_HTSetting)); +#ifdef DOT11_VHT_AC + if(TX_HTSetting.field.MODE >= MODE_VHT) + cli_info.tx_mcs = TX_HTSetting.field.MCS & 0x0F; + else +#endif /* DOT11_VHT_AC */ + cli_info.tx_mcs = TX_HTSetting.field.MCS; + cli_info.tx_stream = newRateGetAntenna(TX_HTSetting.field.MCS, TX_HTSetting.field.MODE); + + cli_info.tx_bw = TX_HTSetting.field.BW; + cli_info.tx_sgi = TX_HTSetting.field.ShortGI; + cli_info.tx_phymode = TX_HTSetting.field.MODE; + + /* Flow Statistics */ + cli_info.rx_total_packets = pEntry->RxPackets.QuadPart; + cli_info.rx_total_bytes = pEntry->RxBytes; + cli_info.tx_total_packets = pEntry->TxPackets.QuadPart; + cli_info.tx_total_bytes = pEntry->TxBytes; + cli_info.rx_fail_cnt = pEntry->RxDecryptErrCnt; + cli_info.tx_fail_cnt = pEntry->StatTxFailCount; + + DBGPRINT(RT_DEBUG_OFF, + ("Client AID %d: %02X:%02X:%02X:%02X:%02X:%02X\n", cli_info.aid, PRINT_MAC(pEntry->Addr))); + + DBGPRINT(RT_DEBUG_OFF, + ("\tLast Signal Stauts: RSSI = %d/%d/%d, SNR = %d/%d/%d\n", + cli_info.last_rssi[0], cli_info.last_rssi[1], cli_info.last_rssi[2], + cli_info.last_snr[0], cli_info.last_snr[1], cli_info.last_snr[2])); + + DBGPRINT(RT_DEBUG_OFF, + ("\tLast RX Status: MCS = %d, BW = %s, SS = %d, SGI = %d, MODE = %s\n", + cli_info.rx_mcs,get_bw_str(cli_info.rx_bw),cli_info.rx_stream, + cli_info.rx_sgi,get_phymode_str(cli_info.rx_phymode))); + + DBGPRINT(RT_DEBUG_OFF, + ("\tLast TX Status: MCS = %d, BW = %s, SS = %d, SGI = %d, MODE = %s\n", + cli_info.tx_mcs,get_bw_str(cli_info.tx_bw),cli_info.tx_stream, + cli_info.tx_sgi,get_phymode_str(cli_info.tx_phymode))); + + DBGPRINT(RT_DEBUG_OFF, + ("\tRX Flow Statistics: Total Count = %lld, Error Count = %lu, Total Bytes = %lu\n", + cli_info.rx_total_packets, cli_info.rx_fail_cnt, cli_info.rx_total_bytes)); + + DBGPRINT(RT_DEBUG_OFF, + ("\tTX Flow Statistics: Total Count = %lld, Failure Count = %lu, Total Bytes = %lu\n", + cli_info.tx_total_packets, cli_info.tx_fail_cnt, cli_info.tx_total_bytes)); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<==%s\n", __FUNCTION__)); + + return TRUE; +} + +VOID Update_CliPktStats( + IN PRTMP_ADAPTER pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UINT32 MacSeq, + IN BOOLEAN bFromTx) +{ + UINT DataRate = 0; + ULONG CurTime = 0; + PCLINET_PKT_STATS_INFO pCliPktStats = NULL; + HTTRANSMIT_SETTING RX_HTSetting,TX_HTSetting; + + if(!pEntry || !pAd->ApCfg.bCliPktStatEnable) + return; + + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + && (pEntry->Sst == SST_ASSOC)) + { + if(bFromTx) + { + if(pEntry->CliPktStatTxIdx >= MAX_LAST_PKT_STATS) + pEntry->CliPktStatTxIdx = 0; + pCliPktStats = &pEntry->CliPktStat[pEntry->CliPktStatTxIdx++]; + pCliPktStats->bTxValid = TRUE; + } + else + { + if(pEntry->CliPktStatRxIdx >= MAX_LAST_PKT_STATS) + pEntry->CliPktStatRxIdx = 0; + pCliPktStats = &pEntry->CliPktStat[pEntry->CliPktStatRxIdx++]; + pCliPktStats->bRxValid = TRUE; + } + + if(bFromTx) + { + /* TX Info */ + NdisCopyMemory(&TX_HTSetting, &pEntry->HTPhyMode, sizeof(TX_HTSetting)); +#ifdef DOT11_VHT_AC + if(TX_HTSetting.field.MODE >= MODE_VHT) + pCliPktStats->tx_mcs = TX_HTSetting.field.MCS & 0x0F; + else +#endif /* DOT11_VHT_AC */ + pCliPktStats->tx_mcs = TX_HTSetting.field.MCS; + pCliPktStats->tx_stream = newRateGetAntenna(TX_HTSetting.field.MCS, TX_HTSetting.field.MODE); + pCliPktStats->tx_bw = TX_HTSetting.field.BW; + pCliPktStats->tx_sgi = TX_HTSetting.field.ShortGI; + pCliPktStats->tx_phymode = TX_HTSetting.field.MODE; + RtmpDrvRateGet(pAd, pCliPktStats->tx_phymode, pCliPktStats->tx_sgi, + pCliPktStats->tx_bw, pCliPktStats->tx_mcs, + pCliPktStats->tx_stream, &DataRate); + DataRate /= 500000; + DataRate /= 2; + pCliPktStats->tx_rate = DataRate; + pCliPktStats->tx_seq = MacSeq; + NdisGetSystemUpTime(&CurTime); + pCliPktStats->tx_time_sec = (CurTime-INITIAL_JIFFIES)/OS_HZ; + } + else + { + /* RX RSSI */ + pCliPktStats->last_rssi[0] = pEntry->RssiSample.LastRssi0; + pCliPktStats->last_rssi[1] = pEntry->RssiSample.LastRssi1; + pCliPktStats->last_rssi[2] = pEntry->RssiSample.LastRssi2; + + /* RX Info */ + NdisCopyMemory(&RX_HTSetting, &pEntry->LastRxRate, sizeof(RX_HTSetting)); +#ifdef DOT11_VHT_AC + if(RX_HTSetting.field.MODE >= MODE_VHT) + pCliPktStats->rx_mcs = RX_HTSetting.field.MCS & 0x0F; + else +#endif /* DOT11_VHT_AC */ + pCliPktStats->rx_mcs = RX_HTSetting.field.MCS; + pCliPktStats->rx_stream = newRateGetAntenna(RX_HTSetting.field.MCS,RX_HTSetting.field.MODE); + pCliPktStats->rx_bw = RX_HTSetting.field.BW; + pCliPktStats->rx_sgi = RX_HTSetting.field.ShortGI; + pCliPktStats->rx_phymode = RX_HTSetting.field.MODE; + RtmpDrvRateGet(pAd, pCliPktStats->rx_phymode, pCliPktStats->rx_sgi, + pCliPktStats->rx_bw, pCliPktStats->rx_mcs, + pCliPktStats->rx_stream, &DataRate); + DataRate /= 500000; + DataRate /= 2; + pCliPktStats->rx_rate = DataRate; + pCliPktStats->rx_seq = MacSeq; + NdisGetSystemUpTime(&CurTime); + pCliPktStats->rx_time_sec = (CurTime-INITIAL_JIFFIES)/OS_HZ; + } + } +} + +INT Set_Cli_Pkt_Stats_Show( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN BOOLEAN bTx) +{ + INT i,j; + PSTRING value; + UCHAR CliAddr[MAC_ADDR_LEN]; + PMAC_TABLE_ENTRY pEntry = NULL; + PCLINET_PKT_STATS_INFO pCliPktStats = NULL; + BOOLEAN bFirst = TRUE; + + if (strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address length! (acceptable format 01:02:03:04:05:06 length 17)\n")); + return FALSE; + } + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address format or octet!\n")); + /* Do not use "continue" to replace "break" */ + break; + } + AtoH(value, &CliAddr[i++], 1); + } + + if (i != MAC_ADDR_LEN) + { + DBGPRINT(RT_DEBUG_ERROR, ("MAC address length is wrong!\n")); + return FALSE; + } + + for (i=1; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + && (pEntry->Sst == SST_ASSOC) + && MAC_ADDR_EQUAL(pEntry->Addr,CliAddr)) + { + for(j=0; jCliPktStat[j]; + if(bTx) + { + if(!pCliPktStats->bTxValid) + continue; + + if(bFirst) + { + DBGPRINT(RT_DEBUG_OFF, ("\n%-7s%-6s%-8s%-4s%-4s%-3s%-4s%-5s\n", + "TIME","SEQ", "TX_RATE", "MCS", "BW", "SS", "SGI", "MODE")); + bFirst = FALSE; + } + DBGPRINT(RT_DEBUG_OFF, ("%-7lu%-6d%-8d%-4d%-4s%-3d%-4d%-5s\n", + pCliPktStats->tx_time_sec, pCliPktStats->tx_seq, pCliPktStats->tx_rate, + pCliPktStats->tx_mcs, get_bw_str(pCliPktStats->tx_bw), pCliPktStats->tx_stream, + pCliPktStats->tx_sgi, get_phymode_str(pCliPktStats->tx_phymode))); + } + else + { + if(!pCliPktStats->bRxValid) + continue; + + if(bFirst) + { + DBGPRINT(RT_DEBUG_OFF, ("\n%-7s%-6s%-6s%-6s%-8s%-4s%-4s%-3s%-4s%-5s\n", + "TIME","SEQ", "RSSI0", "RSSI1", "RX_RATE", "MCS", + "BW", "SS", "SGI", "MODE")); + bFirst = FALSE; + } + DBGPRINT(RT_DEBUG_OFF, ("%-7lu%-6d%-6d%-6d%-8d%-4d%-4s%-3d%-4d%-5s\n", + pCliPktStats->rx_time_sec,pCliPktStats->rx_seq,pCliPktStats->last_rssi[0], + pCliPktStats->last_rssi[1],pCliPktStats->rx_rate, pCliPktStats->rx_mcs, + get_bw_str(pCliPktStats->rx_bw), pCliPktStats->rx_stream, + pCliPktStats->rx_sgi, get_phymode_str(pCliPktStats->rx_phymode))); + } + } + break; + } + } + + return TRUE; +} + +INT Set_Cli_Pkt_Stats_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + BOOLEAN bEnable = FALSE; + PMAC_TABLE_ENTRY pEntry = NULL; + + bEnable = simple_strtol(arg, 0, 10); + + if(pAd->ApCfg.bCliPktStatEnable != bEnable) + { + pAd->ApCfg.bCliPktStatEnable = bEnable; + + /* Clear all previous collected data*/ + if(bEnable == FALSE) + { + for (i=1; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) +#ifdef MAC_REPEATER_SUPPORT + && (pEntry->bReptCli == FALSE) +#endif /* MAC_REPEATER_SUPPORT */ + && (pEntry->Sst == SST_ASSOC)) + { + pEntry->CliPktStatTxIdx = 0; + pEntry->CliPktStatRxIdx = 0; + NdisZeroMemory(&pEntry->CliPktStat,sizeof(pEntry->CliPktStat)); + } + } + } + } + + return TRUE; +} + +INT Set_Cli_Pkt_Stats_TX_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Cli_Pkt_Stats_Show(pAd, arg, TRUE); +} + +INT Set_Cli_Pkt_Stats_RX_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Cli_Pkt_Stats_Show(pAd, arg, FALSE); +} + +INT Set_MLME_Queue_Full_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + LONG Value = 0; + + if (strlen(arg) == 0) + Value = 1; + else + Value = simple_strtol(arg, 0, 10); + + if(Value >= 1) + { + DBGPRINT(RT_DEBUG_OFF, ("MLME Queue Full Count = %lu\n",pAd->Mlme.Queue.QueueFullCnt)); +#ifdef EAPOL_QUEUE_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("EAP Queue Full Count = %lu\n",pAd->Mlme.EAP_Queue.QueueFullCnt)); +#endif /* EAPOL_QUEUE_SUPPORT */ + } + else + { + pAd->Mlme.Queue.QueueFullCnt = 0; +#ifdef EAPOL_QUEUE_SUPPORT + pAd->Mlme.EAP_Queue.QueueFullCnt = 0; +#endif /* EAPOL_QUEUE_SUPPORT */ + } + + return TRUE; +} +#endif /* SMART_MESH */ + +#ifdef SMART_MESH_MONITOR +INT Set_Enable_Monitor_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = TRUE, i; + UINT reg_offset = 0x1098; + UINT target0, target1, reg; + UCHAR *p,wcid,MntEnable; + MNT_STA_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + MntEnable = (UCHAR) simple_strtol(arg, 0, 10); + + if(pAdapter->MntEnable != MntEnable) + { + if(MntEnable == 0) + { + //Clear all settings + p = ZERO_MAC_ADDR; + target0 = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0]; + target1 = (p[5]<<8) | p[4]; + for (i=0; i< MAX_NUM_OF_MONITOR_STA; i++) + { + pEntry = pAdapter->MntTable + i; + if(pEntry->bValid) + { + wcid = i+WCID_OF_MONITOR_STA_BASE; + reg_offset = 0x1098 + (i << 3); // 8 bytes per-entry + RTMP_IO_WRITE32(pAdapter, reg_offset, target0); + RTMP_IO_WRITE32(pAdapter, reg_offset+4, target1); + AsicUpdateRxWCIDTable(pAdapter, wcid, ZERO_MAC_ADDR); + } + } + pAdapter->MonitrCnt = 0; + NdisZeroMemory(&pAdapter->MntTable,sizeof(pAdapter->MntTable)); + + // 0x1094: bit16 set to 0 + RTMP_IO_READ32(pAdapter, 0x1094, ®); //MAC_APCLI_BSSID_DW1 + reg &= ~(1 << 16); + RTMP_IO_WRITE32(pAdapter, 0x1094, reg); + + // 0x1400: bit3=0 and bit2=1 + RTMP_IO_READ32(pAdapter, RX_FILTR_CFG, ®); + reg &= 0xFFFFFFF3; // clear bit3 and bit2 + reg |= 0x00000004; + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, reg); + + // ECO CR: 0x1328: bit31 set to 0 + RTMP_IO_READ32(pAdapter, 0x1328, ®); + reg &= ~(1<<31); // clear bit31 + RTMP_IO_WRITE32(pAdapter, 0x1328, reg); + + pAdapter->MntEnable = 0; + } + else + { + if(pAdapter->MonitrCnt > 0) + { + // 0x1094: bit16 set to 1 + RTMP_IO_READ32(pAdapter, 0x1094, ®); //MAC_APCLI_BSSID_DW1 + reg |= (1 << 16); + RTMP_IO_WRITE32(pAdapter, 0x1094, reg); + + // 0x1400: bit3=1 and bit2=0 + RTMP_IO_READ32(pAdapter, RX_FILTR_CFG, ®); + reg &= 0xFFFFFFF3; // clear bit3 and bit2 + reg |= 0x00000008; + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, reg); + + // ECO CR: 0x1328: bit31 set to 1 + // STA can associate AP and can receive probe request. + RTMP_IO_READ32(pAdapter, 0x1328, ®); + reg |= (1<<31); + RTMP_IO_WRITE32(pAdapter, 0x1328, reg); + + pAdapter->MntEnable = 1; + } + } + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return success; +} + +INT Set_MonitorTarget_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = TRUE; + PSTRING this_char; + PSTRING value; + INT i; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + while ((this_char = strsep((char **)&arg, ";")) != NULL) + { + if (*this_char == '\0') + { + DBGPRINT(RT_DEBUG_WARN, ("An unnecessary delimiter entered!\n")); + continue; + } + if (strlen(this_char) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address length! (acceptable format 01:02:03:04:05:06 length 17)\n")); + continue; + } + for (i=0, value = rstrtok(this_char,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("illegal MAC address format or octet!\n")); + /* Do not use "continue" to replace "break" */ + break; + } + AtoH(value, &pAdapter->curMntAddr[i++], 1); + } + + if (i != MAC_ADDR_LEN) + { + continue; + } + } + + for (i=0; icurMntAddr[i])); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return success; +} + + +INT Set_MonitorIndex_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = TRUE; + UINT reg_offset = 0x1098; + UINT target0, target1; + UCHAR *p,MntIndex,wcid; + CHAR strTemp[8]; + MNT_STA_ENTRY *pMntEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + MntIndex = (UCHAR) simple_strtol(arg, 0, 10); + if(MntIndex < MAX_NUM_OF_MONITOR_STA) + { + if(!pAdapter->MntTable[MntIndex].bValid) + { + DBGPRINT(RT_DEBUG_ERROR, ("An invalid index of existed monitor entry.\n")); + return FALSE; + } + + pAdapter->MntIdx = MntIndex; + wcid = MntIndex+WCID_OF_MONITOR_STA_BASE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("The index is over the maximum limit.\n")); + return FALSE; + } + + pMntEntry = &pAdapter->MntTable[MntIndex]; + pMacEntry = (MAC_TABLE_ENTRY *)pMntEntry->pMacEntry; + //Clear MonitorWCID for stopping report if exist + if(pMacEntry && IS_VALID_ENTRY(pMacEntry)) + pMacEntry->MonitorWCID = 0; + pMntEntry->pMacEntry = NULL; + + NdisZeroMemory(pMntEntry, sizeof(MNT_STA_ENTRY)); + COPY_MAC_ADDR(pMntEntry->addr, pAdapter->curMntAddr); + if(MAC_ADDR_EQUAL(ZERO_MAC_ADDR,pAdapter->curMntAddr)) + { + if(pAdapter->MonitrCnt > 0) + pAdapter->MonitrCnt--; + pMntEntry->bValid = FALSE; + } + else + { + if(pAdapter->MonitrCnt < MAX_NUM_OF_MONITOR_STA) + pAdapter->MonitrCnt++; + pMntEntry->bValid = TRUE; + UpdateMonitorEntry(pAdapter,wcid,pMntEntry->addr,FALSE); + } + + p = pMntEntry->addr; + DBGPRINT(RT_DEBUG_OFF, ("index: %d\n", MntIndex)); + DBGPRINT(RT_DEBUG_OFF, ("entry: %02X:%02X:%02X:%02X:%02X:%02X\n", p[0], p[1], p[2], p[3], p[4], p[5])); + + target0 = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0]; + target1 = (p[5]<<8) | p[4]; + reg_offset += (MntIndex << 3); // 8 bytes per-entry + RTMP_IO_WRITE32(pAdapter, reg_offset, target0); + RTMP_IO_WRITE32(pAdapter, reg_offset+4, target1); + + DBGPRINT(RT_DEBUG_OFF, ("WriteCR 0x%04X:0x%08X 0x%04X:0x%08X\n", reg_offset, target0, reg_offset+4, target1)); + + AsicUpdateRxWCIDTable(pAdapter, wcid, pAdapter->curMntAddr); + + if(pAdapter->MonitrCnt > 0) + sprintf(strTemp,"%u",1); + else + sprintf(strTemp,"%u",0); + + success = Set_Enable_Monitor_Proc(pAdapter,strTemp); + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return success; +} + + +INT Set_MonitorShowAll_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = TRUE; + MNT_STA_ENTRY *pEntry; + UCHAR i, j; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + DBGPRINT(RT_DEBUG_OFF, (" Monitor Enable: %d\n", pAdapter->MntEnable)); + DBGPRINT(RT_DEBUG_OFF, (" Index last set: %d\n", pAdapter->MntIdx)); + + for (i=0; iMntTable + i; + + DBGPRINT(RT_DEBUG_OFF, (" Monitor STA[%d]\t", i)); + + for (j=0; jaddr[j])); + DBGPRINT(RT_DEBUG_OFF, ("\t")); + + DBGPRINT(RT_DEBUG_OFF, ("Packet Receive Count=%lu\t", pEntry->Count)); + DBGPRINT(RT_DEBUG_OFF, ("RSSI:%d,%d,%d\t", pEntry->RssiSample.AvgRssi0, pEntry->RssiSample.AvgRssi1, pEntry->RssiSample.AvgRssi2)); + DBGPRINT(RT_DEBUG_OFF, ("SNR:%d,%d,%d\n", pEntry->RssiSample.AvgSnr0, pEntry->RssiSample.AvgSnr1, pEntry->RssiSample.AvgSnr2)); + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return success; +} + + +INT Set_MonitorClearCounter_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = TRUE; + MNT_STA_ENTRY *pEntry; + UCHAR i; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + for (i=0; iMntTable + i; + pEntry->Count = 0; + NdisZeroMemory(&pEntry->RssiSample, sizeof(RSSI_SAMPLE)); + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return success; +} + +INT Set_Enable_MonitorTarget_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg, + IN USHORT wcid) +{ + INT success = TRUE; + CHAR strTemp[8]; + UCHAR MntIndex; + + success = Set_MonitorTarget_Proc(pAdapter,arg); + if(!success) + return success; + + MntIndex = (wcid-WCID_OF_MONITOR_STA_BASE); + if(MntIndex < MAX_NUM_OF_MONITOR_STA) + { + pAdapter->MntIdx = MntIndex; + pAdapter->MntTable[MntIndex].bValid = TRUE; + sprintf(strTemp,"%u",MntIndex); + success = Set_MonitorIndex_Proc(pAdapter,strTemp); + } + else + success = FALSE; + + return success; +} + +INT Set_MonitorTarget0_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,WCID_OF_MONITOR_STA_BASE); +} + +INT Set_MonitorTarget1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,(WCID_OF_MONITOR_STA_BASE+1)); +} + +INT Set_MonitorTarget2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,(WCID_OF_MONITOR_STA_BASE+2)); +} + +INT Set_MonitorTarget3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,(WCID_OF_MONITOR_STA_BASE+3)); +} + +INT Set_MonitorTarget4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,(WCID_OF_MONITOR_STA_BASE+4)); +} + +INT Set_MonitorTarget5_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,(WCID_OF_MONITOR_STA_BASE+5)); +} + +INT Set_MonitorTarget6_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + return Set_Enable_MonitorTarget_Proc(pAdapter,arg,(WCID_OF_MONITOR_STA_BASE+6)); +} + +INT Smart_Mesh_Pkt_Report_Action( + IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN RXWI_STRUC *pRxWI, + IN PUCHAR buff) +{ + + SMART_MESH_RAW raw_tmp; + PHEADER_802_11 pHeader = (PHEADER_802_11)buff; + HTTRANSMIT_SETTING HTSetting; + INT apidx = MAIN_MBSSID; + UCHAR s_addr[MAC_ADDR_LEN]; + UCHAR MESH_IE[] = {0x55, 0x72}; + UCHAR FrameBuf[512]; + UINT32 MCS = 0, BW = 0, ShortGI = 0, PHYMODE = 0, frame_len, offset=0; + UCHAR MntIdx = (WCID - WCID_OF_MONITOR_STA_BASE); + MNT_STA_ENTRY *pEntry = pAd->MntTable + MntIdx; + struct sk_buff *skb = NULL; + + if(!pEntry->bValid) + return FALSE; + + switch (pHeader->FC.Type) + { + case BTYPE_DATA: + break; + + case BTYPE_MGMT: + break; + + case BTYPE_CNTL: + break; + + default: + goto done; + break; + } + + /* Update entry's statistic infomation*/ + pEntry->Count++; + Update_Rssi_Sample(pAd,&pEntry->RssiSample,pRxWI); + + /* Init frame buffer */ + NdisZeroMemory(FrameBuf, sizeof(FrameBuf)); + NdisZeroMemory(&raw_tmp, sizeof(raw_tmp)); + + /* Fake a Source Address for transmission */ + COPY_MAC_ADDR(s_addr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr); + if(s_addr[1] == 0xff) + s_addr[1]=0; + else + s_addr[1]++; + + /* Prepare the 802.3 header */ + MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].wdev.if_addr,s_addr, MESH_IE); + offset += LENGTH_802_3; + + //generate radio part +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + MCS = pRxWI->RXWI_N.mcs; + BW = pRxWI->RXWI_N.bw; + ShortGI = pRxWI->RXWI_N.sgi; + PHYMODE = pRxWI->RXWI_N.phy_mode; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + MCS = pRxWI->RXWI_O.mcs; + BW = pRxWI->RXWI_O.bw; + ShortGI = pRxWI->RXWI_O.sgi; + PHYMODE = pRxWI->RXWI_O.phy_mode; + } +#endif /* RTMP_MAC */ + + //for RSSI + raw_tmp.wlan_radio_tap.RSSI0 = pEntry->RssiSample.AvgRssi0; + raw_tmp.wlan_radio_tap.RSSI1 = pEntry->RssiSample.AvgRssi1; + + //for SNR + raw_tmp.wlan_radio_tap.SNR0 = pEntry->RssiSample.AvgSnr0; + raw_tmp.wlan_radio_tap.SNR1 = pEntry->RssiSample.AvgSnr1; + + //for RXWI + raw_tmp.wlan_radio_tap.PHYMODE = PHYMODE; + raw_tmp.wlan_radio_tap.MCS = MCS; + raw_tmp.wlan_radio_tap.BW = BW; + raw_tmp.wlan_radio_tap.ShortGI = ShortGI; + + //for RATE + HTSetting.field.MODE = PHYMODE; + HTSetting.field.MCS = MCS; + HTSetting.field.BW = BW; + HTSetting.field.ShortGI = ShortGI; + getRate(HTSetting, &(raw_tmp.wlan_radio_tap.RATE)); + + if(pHeader->FC.ToDs == 1 && pHeader->FC.FrDs == 1) + NdisCopyMemory((CHAR*)(&raw_tmp.wlan_header), pHeader, sizeof(HEADER_802_11_4_ADDR)); + else + NdisCopyMemory((CHAR*)(&raw_tmp.wlan_header), pHeader, sizeof(HEADER_802_11)); + + /* Prepare the real payload*/ + NdisCopyMemory(&FrameBuf[offset], (CHAR*)&raw_tmp, sizeof(raw_tmp)); + offset += sizeof(raw_tmp); + frame_len = offset; + + /* Create skb */ + skb = dev_alloc_skb(frame_len + 2); + if (!skb) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Error! Can't allocate a skb.\n", __FUNCTION__)); + return FALSE; + } + + SET_OS_PKT_NETDEV(skb, get_netdev_from_bssid(pAd,apidx)); + + /* 16 byte align the IP header */ + skb_reserve(skb, 2); + + /* Insert the frame content */ + NdisMoveMemory(GET_OS_PKT_DATAPTR(skb), FrameBuf, frame_len); + + /* End this frame */ + skb_put(skb, frame_len); + + /* Report to upper layer */ + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); +done: + return TRUE; +} + +INT UpdateMonitorEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR MntWCID, + IN UCHAR *MntAddr, + IN BOOLEAN bClear) +{ + INT i; + UCHAR MntIdx = (MntWCID - WCID_OF_MONITOR_STA_BASE); + MNT_STA_ENTRY *pMntEntry = pAd->MntTable + MntIdx; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + if(!pMntEntry->bValid) + return FALSE; + + if(bClear) + { + pMacEntry = pMntEntry->pMacEntry; + if(pMacEntry != NULL && IS_VALID_ENTRY(pMacEntry)) + pMacEntry->MonitorWCID = 0; + + pMntEntry->pMacEntry = NULL; + } + else + { + for (i=1; iMacTab.Content[i]; + if(!IS_VALID_ENTRY(pMacEntry)) + continue; + + if(MntAddr && MAC_ADDR_EQUAL(MntAddr,pMacEntry->Addr)) + { + pMntEntry->pMacEntry = (VOID*)pMacEntry; + pMacEntry->MonitorWCID = MntWCID; + break; + } + } + } + + return TRUE; +} + +BOOLEAN IsValidUnicastToMe(IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PUCHAR pDA) +{ + BOOLEAN bUToMe = FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!VALID_WCID(WCID)) + bUToMe = FALSE; + + if (MAC_ADDR_EQUAL(pDA, pAd->CurrentAddress)) + bUToMe = TRUE; + + if (!bUToMe) + { +#ifdef APCLI_SUPPORT + UINT index; + PAPCLI_STRUCT pApCliEntry = NULL; + for(index = 0; index < MAX_APCLI_NUM; index++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[index]; + if (pApCliEntry && + (pApCliEntry->Enable && pApCliEntry->Valid)) + { + if (MAC_ADDR_EQUAL(pApCliEntry->wdev.if_addr,pDA)) + { + bUToMe = TRUE; + break; + } + } + } + +#ifdef MAC_REPEATER_SUPPORT + if (!bUToMe && + (pAd->ApCfg.bMACRepeaterEn == TRUE) && + (RTMPQueryLookupRepeaterCliEntry(pAd, pDA) == TRUE)) + bUToMe = TRUE; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + + return bUToMe; +} +#endif /*SMART_MESH_MONITOR*/ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/spectrum.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/spectrum.c new file mode 100644 index 000000000..6a9f7b5ee --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/spectrum.c @@ -0,0 +1,2665 @@ +/**************************************************************************** + * 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: + action.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 2008 created for 802.11h + */ + +#include "rt_config.h" +#include "action.h" + + +/* The regulatory information in the USA (US) */ +DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] = +{ +/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ + {0, {0, 0, {0}}}, /* Invlid entry*/ + {1, {4, 16, {36, 40, 44, 48}}}, + {2, {4, 23, {52, 56, 60, 64}}}, + {3, {4, 29, {149, 153, 157, 161}}}, + {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}}, + {5, {5, 30, {149, 153, 157, 161, 165}}}, + {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}, + {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}, + {8, {5, 17, {11, 13, 15, 17, 19}}}, + {9, {5, 30, {11, 13, 15, 17, 19}}}, + {10, {2, 20, {21, 25}}}, + {11, {2, 33, {21, 25}}}, + {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}} +}; +#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION)) + + +/* The regulatory information in Europe */ +DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] = +{ +/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ + {0, {0, 0, {0}}}, /* Invalid entry*/ + {1, {4, 20, {36, 40, 44, 48}}}, + {2, {4, 20, {52, 56, 60, 64}}}, + {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}}, + {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}} +}; +#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION)) + + +/* The regulatory information in Japan */ +DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] = +{ +/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ + {0, {0, 0, {0}}}, /* Invalid entry*/ + {1, {4, 22, {34, 38, 42, 46}}}, + {2, {3, 24, {8, 12, 16}}}, + {3, {3, 24, {8, 12, 16}}}, + {4, {3, 24, {8, 12, 16}}}, + {5, {3, 24, {8, 12, 16}}}, + {6, {3, 22, {8, 12, 16}}}, + {7, {4, 24, {184, 188, 192, 196}}}, + {8, {4, 24, {184, 188, 192, 196}}}, + {9, {4, 24, {184, 188, 192, 196}}}, + {10, {4, 24, {184, 188, 192, 196}}}, + {11, {4, 22, {184, 188, 192, 196}}}, + {12, {4, 24, {7, 8, 9, 11}}}, + {13, {4, 24, {7, 8, 9, 11}}}, + {14, {4, 24, {7, 8, 9, 11}}}, + {15, {4, 24, {7, 8, 9, 11}}}, + {16, {6, 24, {183, 184, 185, 187, 188, 189}}}, + {17, {6, 24, {183, 184, 185, 187, 188, 189}}}, + {18, {6, 24, {183, 184, 185, 187, 188, 189}}}, + {19, {6, 24, {183, 184, 185, 187, 188, 189}}}, + {20, {6, 17, {183, 184, 185, 187, 188, 189}}}, + {21, {6, 24, {6, 7, 8, 9, 10, 11}}}, + {22, {6, 24, {6, 7, 8, 9, 10, 11}}}, + {23, {6, 24, {6, 7, 8, 9, 10, 11}}}, + {24, {6, 24, {6, 7, 8, 9, 10, 11}}}, + {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, + {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, + {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, + {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, + {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}}}, + {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}}, + {31, {1, 23, {14}}}, + {32, {4, 22, {52, 56, 60, 64}}} +}; +#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION)) + + +UINT8 GetRegulatoryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel) +{ + ULONG RegulatoryClassLoop, ChIdx; + UINT8 RegulatoryClass; + UINT8 MaxRegulatoryClassNum; + PDOT11_REGULATORY_INFORMATION pRegulatoryClass; + PSTRING pCountry = (PSTRING)(pAd->CommonCfg.CountryCode); + + + if (strncmp(pCountry, "US", 2) == 0) + { + MaxRegulatoryClassNum = USA_REGULATORY_INFO_SIZE; + pRegulatoryClass = &USARegulatoryInfo[0]; + } + else if (strncmp(pCountry, "JP", 2) == 0) + { + MaxRegulatoryClassNum = JP_REGULATORY_INFO_SIZE; + pRegulatoryClass = &JapanRegulatoryInfo[0]; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n", + __FUNCTION__, pCountry)); + return 0xff; + } + + for (RegulatoryClassLoop = 0; + RegulatoryClassLoopCommonCfg.RegulatoryClass[RegulatoryClassLoop]; + if (RegulatoryClass >= MaxRegulatoryClassNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: %c%c Unknow Requlatory class (%d)\n", + __FUNCTION__, pCountry[0], pCountry[1], RegulatoryClass)); + return 0xff; + } + pChannelSet = &pRegulatoryClass[RegulatoryClass].ChannelSet; + for (ChIdx=0; ChIdxNumberOfChannels; ChIdx++) + { + if (channel == pChannelSet->ChannelList[ChIdx]) + return pChannelSet->MaxTxPwr; + + } + if (ChIdx == pChannelSet->NumberOfChannels) + return 0xff; + } + + return 0xff; +} + +typedef struct __TX_PWR_CFG +{ + UINT8 Mode; + UINT8 MCS; + UINT16 req; + UINT8 shift; + UINT32 BitMask; +} TX_PWR_CFG; + +/* Note: the size of TxPwrCfg is too large, do not put it to function */ +TX_PWR_CFG TxPwrCfg[] = { + {MODE_CCK, 0, 0, 4, 0x000000f0}, + {MODE_CCK, 1, 0, 0, 0x0000000f}, + {MODE_CCK, 2, 0, 12, 0x0000f000}, + {MODE_CCK, 3, 0, 8, 0x00000f00}, + + {MODE_OFDM, 0, 0, 20, 0x00f00000}, + {MODE_OFDM, 1, 0, 16, 0x000f0000}, + {MODE_OFDM, 2, 0, 28, 0xf0000000}, + {MODE_OFDM, 3, 0, 24, 0x0f000000}, + {MODE_OFDM, 4, 1, 4, 0x000000f0}, + {MODE_OFDM, 5, 1, 0, 0x0000000f}, + {MODE_OFDM, 6, 1, 12, 0x0000f000}, + {MODE_OFDM, 7, 1, 8, 0x00000f00} +#ifdef DOT11_N_SUPPORT + ,{MODE_HTMIX, 0, 1, 20, 0x00f00000}, + {MODE_HTMIX, 1, 1, 16, 0x000f0000}, + {MODE_HTMIX, 2, 1, 28, 0xf0000000}, + {MODE_HTMIX, 3, 1, 24, 0x0f000000}, + {MODE_HTMIX, 4, 2, 4, 0x000000f0}, + {MODE_HTMIX, 5, 2, 0, 0x0000000f}, + {MODE_HTMIX, 6, 2, 12, 0x0000f000}, + {MODE_HTMIX, 7, 2, 8, 0x00000f00}, + {MODE_HTMIX, 8, 2, 20, 0x00f00000}, + {MODE_HTMIX, 9, 2, 16, 0x000f0000}, + {MODE_HTMIX, 10, 2, 28, 0xf0000000}, + {MODE_HTMIX, 11, 2, 24, 0x0f000000}, + {MODE_HTMIX, 12, 3, 4, 0x000000f0}, + {MODE_HTMIX, 13, 3, 0, 0x0000000f}, + {MODE_HTMIX, 14, 3, 12, 0x0000f000}, + {MODE_HTMIX, 15, 3, 8, 0x00000f00} +#endif /* DOT11_N_SUPPORT */ +}; +#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG)) + +CHAR RTMP_GetTxPwr( + IN PRTMP_ADAPTER pAd, + IN HTTRANSMIT_SETTING HTTxMode) +{ + UINT32 Value; + INT Idx; + UINT8 PhyMode; + CHAR CurTxPwr; + UINT8 TxPwrRef = 0; + CHAR DaltaPwr; + ULONG TxPwr[5]; + + +#ifdef SINGLE_SKU + CurTxPwr = pAd->CommonCfg.DefineMaxTxPwr; +#else + CurTxPwr = 19; +#endif /* SINGLE_SKU */ + + /* check Tx Power setting from UI. */ + if (pAd->CommonCfg.TxPowerPercentage > 90) + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ + CurTxPwr -= 1; + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ + CurTxPwr -= 3; + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ + CurTxPwr -= 6; + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ + CurTxPwr -= 9; + else /* reduce Pwr for 12 dB. */ + CurTxPwr -= 12; + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (pAd->CommonCfg.CentralChannel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->CommonCfg.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + + switch(HTTxMode.field.MODE) + { + case MODE_CCK: + case MODE_OFDM: + Value = TxPwr[1]; + TxPwrRef = (Value & 0x00000f00) >> 8; + + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + case MODE_HTGREENFIELD: + if (pAd->CommonCfg.TxStream == 1) + { + Value = TxPwr[2]; + TxPwrRef = (Value & 0x00000f00) >> 8; + } + else if (pAd->CommonCfg.TxStream == 2) + { + Value = TxPwr[3]; + TxPwrRef = (Value & 0x00000f00) >> 8; + } + break; +#endif /* DOT11_N_SUPPORT */ + } + + PhyMode = +#ifdef DOT11_N_SUPPORT + (HTTxMode.field.MODE == MODE_HTGREENFIELD) + ? MODE_HTMIX : +#endif /* DOT11_N_SUPPORT */ + HTTxMode.field.MODE; + + for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) + { + if ((TxPwrCfg[Idx].Mode == PhyMode) + && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) + { + Value = TxPwr[TxPwrCfg[Idx].req]; + DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask) + >> TxPwrCfg[Idx].shift); + CurTxPwr -= DaltaPwr; + break; + } + } + + return CurTxPwr; +} + + +NDIS_STATUS MeasureReqTabInit( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + NdisAllocateSpinLock(pAd, &pAd->CommonCfg.MeasureReqTabLock); + +/* pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);*/ + os_alloc_mem(pAd, (UCHAR **)&(pAd->CommonCfg.pMeasureReqTab), sizeof(MEASURE_REQ_TAB)); + if (pAd->CommonCfg.pMeasureReqTab) + NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB)); + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock); + + if (pAd->CommonCfg.pMeasureReqTab) +/* kfree(pAd->CommonCfg.pMeasureReqTab);*/ + os_free_mem(NULL, pAd->CommonCfg.pMeasureReqTab); + pAd->CommonCfg.pMeasureReqTab = NULL; + + return; +} + +PMEASURE_REQ_ENTRY MeasureReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + UINT HashIdx; + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + + HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (pEntry->DialogToken == DialogToken) + break; + else + { + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + + return pEntry; +} + +PMEASURE_REQ_ENTRY MeasureReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + INT i; + ULONG HashIdx; + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = MeasureReqLookUp(pAd, DialogToken); + if (pEntry == NULL) + { + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT))) + { + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + pTab->Size--; + + break; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_MEASURE_REQ_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->Valid = TRUE; + pEntry->DialogToken = DialogToken; + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __FUNCTION__)); + } + + /* add this Neighbor entry into HASH table*/ + if (pEntry) + { + HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); + if (pTab->Hash[HashIdx] == NULL) + { + pTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + } + + return pEntry; +} + +VOID MeasureReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return; + } + + /* if empty, return*/ + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); + return; + } + + pEntry = MeasureReqLookUp(pAd, DialogToken); + if (pEntry != NULL) + { + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + } + + return; +} + +NDIS_STATUS TpcReqTabInit( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + NdisAllocateSpinLock(pAd, &pAd->CommonCfg.TpcReqTabLock); + +/* pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);*/ + os_alloc_mem(pAd, (UCHAR **)&(pAd->CommonCfg.pTpcReqTab), sizeof(TPC_REQ_TAB)); + if (pAd->CommonCfg.pTpcReqTab) + NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB)); + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + +VOID TpcReqTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock); + + if (pAd->CommonCfg.pTpcReqTab) +/* kfree(pAd->CommonCfg.pTpcReqTab);*/ + os_free_mem(NULL, pAd->CommonCfg.pTpcReqTab); + pAd->CommonCfg.pTpcReqTab = NULL; + + return; +} + +static PTPC_REQ_ENTRY TpcReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + UINT HashIdx; + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + + HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (pEntry->DialogToken == DialogToken) + break; + else + { + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + + return pEntry; +} + + +static PTPC_REQ_ENTRY TpcReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + INT i; + ULONG HashIdx; + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = TpcReqLookUp(pAd, DialogToken); + if (pEntry == NULL) + { + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT))) + { + PTPC_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + pTab->Size--; + + break; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_TPC_REQ_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->Valid = TRUE; + pEntry->DialogToken = DialogToken; + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __FUNCTION__)); + } + + /* add this Neighbor entry into HASH table*/ + if (pEntry) + { + HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); + if (pTab->Hash[HashIdx] == NULL) + { + pTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + } + + return pEntry; +} + +static VOID TpcReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return; + } + + /* if empty, return*/ + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); + return; + } + + pEntry = TpcReqLookUp(pAd, DialogToken); + if (pEntry != NULL) + { + PTPC_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + } + + return; +} + +/* + ========================================================================== + Description: + Get Current TimeS tamp. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT64 GetCurrentTimeStamp( + IN PRTMP_ADAPTER pAd) +{ + /* get current time stamp.*/ + return 0; +} + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT8 GetCurTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 Wcid) +{ + return 16; /* 16 dBm */ +} + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +VOID InsertChannelRepIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PSTRING pCountry, + IN UINT8 RegulatoryClass) +{ + ULONG TempLen; + UINT8 Len; + UINT8 IEId = IE_AP_CHANNEL_REPORT; + PUCHAR pChListPtr = NULL; + PDOT11_CHANNEL_SET pChannelSet = NULL; + + Len = 1; + if (strncmp(pCountry, "US", 2) == 0) + { + if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: USA Unknow Requlatory class (%d)\n", + __FUNCTION__, RegulatoryClass)); + return; + } + pChannelSet = &USARegulatoryInfo[RegulatoryClass].ChannelSet; + } + else if (strncmp(pCountry, "JP", 2) == 0) + { + if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: JP Unknow Requlatory class (%d)\n", + __FUNCTION__, RegulatoryClass)); + return; + } + + pChannelSet = &JapanRegulatoryInfo[RegulatoryClass].ChannelSet; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n", + __FUNCTION__, pCountry)); + return; + } + + /* no match channel set. */ + if (pChannelSet == NULL) + return; + + /* empty channel set. */ + if (pChannelSet->NumberOfChannels == 0) + return; + + Len += pChannelSet->NumberOfChannels; + pChListPtr = pChannelSet->ChannelList; + + if (Len > 1) + { + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + 1, &RegulatoryClass, + Len -1, pChListPtr, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + return; +} + +/* + ========================================================================== + Description: + Insert Dialog Token into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Dialog token. + + Return : None. + ========================================================================== + */ +VOID InsertDialogToken( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 DialogToken) +{ + ULONG TempLen; + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &DialogToken, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert TPC Request IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ + static VOID InsertTpcReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UINT8 Len = 0; + UINT8 ElementID = IE_TPC_REQUEST; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert TPC Report IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Transmit Power. + 4. Link Margin. + + Return : None. + ========================================================================== + */ +VOID InsertTpcReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + ULONG TempLen; + UINT8 Len = sizeof(TPC_REPORT_INFO); + UINT8 ElementID = IE_TPC_REPORT; + TPC_REPORT_INFO TpcReportIE; + + TpcReportIE.TxPwr = TxPwr; + TpcReportIE.LinkMargin = LinkMargin; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &TpcReportIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + + return; +} + +/* + ========================================================================== + Description: + Insert Measure Request IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Measure Token. + 4. Measure Request Mode. + 5. Measure Request Type. + 6. Measure Channel. + 7. Measure Start time. + 8. Measure Duration. + + + Return : None. + ========================================================================== + */ +static VOID InsertMeasureReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN PMEASURE_REQ_INFO pMeasureReqIE) +{ + ULONG TempLen; + UINT8 ElementID = IE_MEASUREMENT_REQUEST; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + sizeof(MEASURE_REQ_INFO), pMeasureReqIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert Measure Report IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Measure Token. + 4. Measure Request Mode. + 5. Measure Request Type. + 6. Length of Report Infomation + 7. Pointer of Report Infomation Buffer. + + Return : None. + ========================================================================== + */ +static VOID InsertMeasureReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PMEASURE_REPORT_INFO pMeasureReportIE, + IN UINT8 ReportLnfoLen, + IN PUINT8 pReportInfo) +{ + ULONG TempLen; + UINT8 Len; + UINT8 ElementID = IE_MEASUREMENT_REPORT; + + Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, pMeasureReportIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) + { + MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, + ReportLnfoLen, pReportInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + return; +} + +/* + ========================================================================== + Description: + Prepare Measurement request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID MakeMeasurementReqFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuffer, + OUT PULONG pFrameLen, + IN UINT8 TotalLen, + IN UINT8 Category, + IN UINT8 Action, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT16 NumOfRepetitions) +{ + ULONG TempLen; + MEASURE_REQ_INFO MeasureReqIE; + + InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken); + + /* fill Number of repetitions. */ + if (Category == CATEGORY_RM) + { + MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen, + 2, &NumOfRepetitions, + END_OF_ARGS); + + *pFrameLen += TempLen; + } + + /* prepare Measurement IE.*/ + NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO)); + MeasureReqIE.Token = MeasureToken; + MeasureReqIE.ReqMode.word = MeasureReqMode; + MeasureReqIE.ReqType = MeasureReqType; + InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen, + TotalLen, &MeasureReqIE); + + return; +} + +/* + ========================================================================== + Description: + Prepare Measurement report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + HEADER_802_11 ActHdr; + MEASURE_REPORT_INFO MeasureRepIE; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + 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; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* prepare Measurement IE.*/ + NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO)); + MeasureRepIE.Token = MeasureToken; + MeasureRepIE.ReportMode = MeasureReqMode; + MeasureRepIE.ReportType = MeasureReqType; + InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + 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; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* Insert TPC Request IE.*/ + InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + 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; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* Insert TPC Request IE.*/ + InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +#ifdef WDS_SUPPORT +/* + ========================================================================== + Description: + Insert Channel Switch Announcement IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. channel switch announcement mode. + 4. new selected channel. + 5. channel switch announcement count. + + Return : None. + ========================================================================== + */ +static VOID InsertChSwAnnIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ChSwMode, + IN UINT8 NewChannel, + IN UINT8 ChSwCnt) +{ + ULONG TempLen; + ULONG Len = sizeof(CH_SW_ANN_INFO); + UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + CH_SW_ANN_INFO ChSwAnnIE; + + ChSwAnnIE.ChSwMode = ChSwMode; + ChSwAnnIE.Channel = NewChannel; + ChSwAnnIE.ChSwCnt = ChSwCnt; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &ChSwAnnIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + + return; +} + +/* + ========================================================================== + Description: + Prepare Channel Switch Announcement action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + 2. Channel switch announcement mode. + 2. a New selected channel. + + Return : None. + ========================================================================== + */ +VOID EnqueueChSwAnn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + 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; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); + + InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} +#endif /* WDS_SUPPORT */ + +static BOOLEAN DfsRequirementCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 Channel) +{ + BOOLEAN Result = FALSE; + INT i; + + do + { + /* check DFS procedure is running.*/ + /* make sure DFS procedure won't start twice.*/ + if (pAd->Dot11_H.RDMode != RD_NORMAL_MODE) + { + Result = FALSE; + break; + } + + /* check the new channel carried from Channel Switch Announcemnet is valid.*/ + for (i=0; iChannelListNum; i++) + { + if ((Channel == pAd->ChannelList[i].Channel) + &&(pAd->ChannelList[i].RemainingTimeForUse == 0)) + { + /* found radar signal in the channel. the channel can't use at least for 30 minutes.*/ + pAd->ChannelList[i].RemainingTimeForUse = 1800;/*30 min = 1800 sec*/ + Result = TRUE; + break; + } + } + } while(FALSE); + + return Result; +} + +VOID NotifyChSwAnnToPeerAPs( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRA, + IN PUCHAR pTA, + IN UINT8 ChSwMode, + IN UINT8 Channel) +{ +#ifdef WDS_SUPPORT + if (!((pRA[0] & 0xff) == 0xff)) /* is pRA a broadcase address.*/ + { + INT i; + /* info neighbor APs that Radar signal found throgh WDS link.*/ + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + if (ValidWdsEntry(pAd, i)) + { + PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr; + + /* DA equal to SA. have no necessary orignal AP which found Radar signal.*/ + if (MAC_ADDR_EQUAL(pTA, pDA)) + continue; + + /* send Channel Switch Action frame to info Neighbro APs.*/ + EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel); + } + } + } +#endif /* WDS_SUPPORT */ +} + +#ifdef CUSTOMER_DCC_FEATURE +#ifdef DOT11_N_SUPPORT +static VOID InsertSecondaryChOffsetIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Offset) +{ + ULONG TempLen; + ULONG Len = sizeof(SEC_CHA_OFFSET_IE); + UINT8 ElementID = IE_SECONDARY_CH_OFFSET; + SEC_CHA_OFFSET_IE SChOffIE; + + SChOffIE.SecondaryChannelOffset = Offset; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &SChOffIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + return; +} +#endif + +#ifdef DOT11_VHT_AC +static VOID InsertWideBandwidthChannelSwitchIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + ULONG Len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); + UINT8 ElementID = IE_WIDE_BW_CH_SWITCH; + WIDE_BW_CH_SWITCH_ELEMENT wb_info; + + if (pAd->CommonCfg.vht_bw == VHT_BW_2040) + wb_info.new_ch_width = 0; + else + wb_info.new_ch_width = 1; + + if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + wb_info.center_freq_2 = 0; + } + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &wb_info, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + return; +} +#endif + +VOID InsertChSwAnnIENew( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ChSwMode, + IN UINT8 NewChannel, + IN UINT8 ChSwCnt) +{ + ULONG TempLen; + ULONG Len = sizeof(CH_SW_ANN_INFO); + UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + CH_SW_ANN_INFO ChSwAnnIE; + + ChSwAnnIE.ChSwMode = ChSwMode; + ChSwAnnIE.Channel = NewChannel; + ChSwAnnIE.ChSwCnt = ChSwCnt; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &ChSwAnnIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + printk("%s \n",__func__); + return; +} + + +VOID NotifyChSwAnnToConnectedSTAs( + IN PRTMP_ADAPTER pAd, + IN UINT8 ChSwMode, + IN UINT8 Channel) +{ + UINT32 i; + MAC_TABLE_ENTRY *pEntry; + + pAd->CommonCfg.channelSwitch.CHSWMode = ChSwMode; + pAd->CommonCfg.channelSwitch.CHSWCount = 0; +// pAd->CommonCfg.channelSwitch.CHSWPeriod = 5; + + for (i=0; iMacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + + EnqueueChSwAnnNew(pAd, pEntry->Addr, ChSwMode, Channel); + + } + } +} + +VOID EnqueueChSwAnnNew( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, pAd->CurrentAddress, pAd->CurrentAddress); + + 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; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); + + InsertChSwAnnIENew(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, pAd->CommonCfg.channelSwitch.CHSWPeriod); + +#ifdef DOT11_N_SUPPORT + InsertSecondaryChOffsetIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pAd->CommonCfg.RegTransmitSetting.field.EXTCHA); +#endif +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.vht_bw == VHT_BW_80)) + { + InsertWideBandwidthChannelSwitchIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + } +#endif + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +#endif + +static VOID StartDFSProcedure( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN UINT8 ChSwMode) +{ + /* start DFS procedure*/ + pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + pAd->Dot11_H.CSCount = 0; +} + +/* + ========================================================================== + Description: + Channel Switch Announcement action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Channel switch announcement infomation buffer. + + + Return : None. + ========================================================================== + */ + +/* + Channel Switch Announcement IE. + +----+-----+-----------+------------+-----------+ + | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt | + +----+-----+-----------+------------+-----------+ + 1 1 1 1 1 +*/ +static BOOLEAN PeerChSwAnnSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PCH_SW_ANN_INFO pChSwAnnInfo) +{ + 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 (pChSwAnnInfo == NULL) + return result; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1); + NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1); + + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Measurement request action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Measurement request infomation buffer. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerMeasureReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REQ_INFO pMeasureReqInfo, + OUT PMEASURE_REQ pMeasureReq) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PUCHAR ptr; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + + /* skip 802.11 header.*/ + MsgLen -= sizeof(HEADER_802_11); + + /* skip category and action code.*/ + pFramePtr += 2; + MsgLen -= 2; + + if (pMeasureReqInfo == 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_REQUEST: + NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1); + ptr = (PUCHAR)(eid_ptr->Octet + 3); + NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1); + NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); + pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime); + NdisMoveMemory(&MeasureDuration, ptr + 9, 2); + pMeasureReq->MeasureDuration = SWAP16(MeasureDuration); + + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Measurement report action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Measurement report infomation buffer. + 4. basic report infomation buffer. + + Return : None. + ========================================================================== + */ + +/* + Measurement Report IE. + +----+-----+-------+-------------+--------------+----------------+ + | ID | Len | Token | Report Mode | Measure Type | Measure Report | + +----+-----+-------+-------------+--------------+----------------+ + 1 1 1 1 1 variable + + Basic Report. + +--------+------------+----------+-----+ + | Ch Num | Start Time | Duration | Map | + +--------+------------+----------+-----+ + 1 8 2 1 + + Map Field Bit Format. + +-----+---------------+---------------------+-------+------------+----------+ + | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved | + +-----+---------------+---------------------+-------+------------+----------+ + 0 1 2 3 4 5-7 +*/ +static BOOLEAN PeerMeasureReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REPORT_INFO pMeasureReportInfo, + OUT PUINT8 pReportBuf) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PUCHAR 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); + if (pMeasureReportInfo->ReportType == RM_BASIC) + { + PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf; + ptr = (PUCHAR)(eid_ptr->Octet + 3); + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->Map, ptr + 11, 1); + + } + else if (pMeasureReportInfo->ReportType == RM_CCA) + { + PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf; + ptr = (PUCHAR)(eid_ptr->Octet + 3); + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1); + + } + else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM) + { + PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf; + ptr = (PUCHAR)(eid_ptr->Octet + 3); + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8); + } + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + TPC Request action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Dialog Token. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerTpcReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + MsgLen -= sizeof(HEADER_802_11); + + /* skip category and action code.*/ + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == 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_TPC_REQUEST: + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + TPC Report action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Dialog Token. + 4. TPC Report IE. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerTpcRepSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PTPC_REPORT_INFO pTpcRepInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + MsgLen -= sizeof(HEADER_802_11); + + /* skip category and action code.*/ + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == 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_TPC_REPORT: + NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); + NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1); + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Channel Switch Announcement action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerChSwAnnAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + CH_SW_ANN_INFO ChSwAnnInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; +#ifdef CONFIG_STA_SUPPORT + UCHAR index = 0, Channel = 0, NewChannel = 0; + ULONG Bssidx = 0; +#endif /* CONFIG_STA_SUPPORT */ + + NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO)); + if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n")); + return; + } + +#ifdef CONFIG_AP_SUPPORT + /* ChSwAnn need check.*/ + if ((pAd->OpMode == OPMODE_AP) && + (DfsRequirementCheck(pAd, ChSwAnnInfo.Channel) == TRUE)) + { + NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, ChSwAnnInfo.ChSwMode, ChSwAnnInfo.Channel); + StartDFSProcedure(pAd, ChSwAnnInfo.Channel, ChSwAnnInfo.ChSwMode); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + { + Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel); + if (Bssidx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel)); + hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6); + + Channel = pAd->CommonCfg.Channel; + NewChannel = ChSwAnnInfo.Channel; + + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) + { + /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).*/ + /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.*/ + AsicSwitchChannel(pAd, 1, FALSE); + AsicLockChannel(pAd, 1); + LinkDown(pAd, FALSE); + MlmeQueueInit(pAd, &pAd->Mlme.Queue); + RtmpusecDelay(1000000); /* use delay to prevent STA do reassoc*/ + + /* channel sanity check*/ + for (index = 0 ; index < pAd->ChannelListNum; index++) + { + if (pAd->ChannelList[index].Channel == NewChannel) + { + pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + pAd->CommonCfg.Channel = NewChannel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + break; + } + } + + if (index >= pAd->ChannelListNum) + { + DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + return; +} + + +/* + ========================================================================== + Description: + Measurement Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + MEASURE_REQ_INFO MeasureReqInfo; + MEASURE_REQ MeasureReq; + MEASURE_REPORT_MODE ReportMode; + + if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq)) + { + ReportMode.word = 0; + ReportMode.field.Incapable = 1; + EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL); + } + + return; +} + +/* + ========================================================================== + Description: + Measurement Report action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MEASURE_REPORT_INFO MeasureReportInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + PUINT8 pMeasureReportInfo; + +/* if (pAd->CommonCfg.bIEEE80211H != TRUE)*/ +/* return;*/ + + os_alloc_mem(pAd, (UCHAR **)&pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); +/* if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)*/ + if (pMeasureReportInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT))); + return; + } + + NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO)); + NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); + if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo)) + { + do { + PMEASURE_REQ_ENTRY pEntry = NULL; + + /* Not a autonomous measure report.*/ + /* check the dialog token field. drop it if the dialog token doesn't match.*/ + if ((DialogToken != 0) + && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL)) + break; + + if (pEntry != NULL) + MeasureReqDelete(pAd, pEntry->DialogToken); + + if (MeasureReportInfo.ReportType == RM_BASIC) + { + PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo; + if ((pBasicReport->Map.field.Radar) + && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE)) + { + NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum); + StartDFSProcedure(pAd, pBasicReport->ChNum, 1); + } + } + } while (FALSE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n")); + +/* kfree(pMeasureReportInfo);*/ + os_free_mem(NULL, pMeasureReportInfo); + + return; +} + +/* + ========================================================================== + Description: + TPC Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerTpcReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + PUCHAR pFramePtr = pFr->Octet; + UINT8 DialogToken; + UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); + UINT8 LinkMargin = 0; + CHAR RealRssi; + + /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The*/ + /* STA may incorporate rate information and channel conditions, including interference, into its computation*/ + /* of link margin.*/ + + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + /* skip Category and action code.*/ + pFramePtr += 2; + + /* Dialog token.*/ + NdisMoveMemory(&DialogToken, pFramePtr, 1); + + LinkMargin = (RealRssi / MIN_RCV_PWR); + if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) + EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin); + + return; +} + +/* + ========================================================================== + Description: + TPC Report action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerTpcRepAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UINT8 DialogToken; + TPC_REPORT_INFO TpcRepInfo; + PTPC_REQ_ENTRY pEntry = NULL; + + NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO)); + if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) + { + if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) + { + TpcReqDelete(pAd, pEntry->DialogToken); + DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", + __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin)); + } + } + + return; +} + +/* + ========================================================================== + Description: + Spectrun action frames Handler such as channel switch annoucement, + measurement report, measurement request actions frames. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +VOID PeerSpectrumAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (pAd->CommonCfg.bIEEE80211H != TRUE) + return; + + switch(Action) + { + case SPEC_MRQ: + /* current rt2860 unable do such measure specified in Measurement Request.*/ + /* reject all measurement request.*/ + PeerMeasureReqAction(pAd, Elem); + break; + + case SPEC_MRP: + PeerMeasureReportAction(pAd, Elem); + break; + + case SPEC_TPCRQ: + PeerTpcReqAction(pAd, Elem); + break; + + case SPEC_TPCRP: + PeerTpcRepAction(pAd, Elem); + break; + + case SPEC_CHANNEL_SWITCH: + +#ifdef DOT11N_DRAFT3 + { + SEC_CHA_OFFSET_IE Secondary; + CHA_SWITCH_ANNOUNCE_IE ChannelSwitch; + + /* 802.11h only has Channel Switch Announcement IE. */ + RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE)); + + /* 802.11n D3.03 adds secondary channel offset element in the end.*/ + if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE))) + { + RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE)); + } + else + { + Secondary.SecondaryChannelOffset = 0; + } + + if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3)) + { + ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset); + } + } +#endif /* DOT11N_DRAFT3 */ + + PeerChSwAnnAction(pAd, Elem); + break; + } + + return; +} + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_MeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT wcid = 1; + UINT ArgIdx; + PSTRING thisChar; + + MEASURE_REQ_MODE MeasureReqMode; + UINT8 MeasureReqToken = RandomByte(pAd); + UINT8 MeasureReqType = RM_BASIC; + UINT8 MeasureCh = 1; + UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd); + MEASURE_REQ MeasureReq; + 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__)); + goto END_OF_MEASURE_REQ; + } + + ArgIdx = 1; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(ArgIdx) + { + case 1: /* Aid.*/ + wcid = (UINT8) simple_strtol(thisChar, 0, 16); + break; + + case 2: /* Measurement Request Type.*/ + MeasureReqType = simple_strtol(thisChar, 0, 16); + if (MeasureReqType > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType)); + goto END_OF_MEASURE_REQ; + } + break; + + case 3: /* Measurement channel.*/ + MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16); + break; + } + ArgIdx++; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", + __FUNCTION__, wcid, MeasureReqType, MeasureCh)); + if (!VALID_WCID(wcid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, wcid)); + goto END_OF_MEASURE_REQ; + } + + MeasureReqMode.word = 0; + MeasureReqMode.field.Enable = 1; + + MeasureReqInsert(pAd, MeasureReqToken); + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[wcid].Addr, + pAd->CurrentAddress, + pAd->CurrentAddress); + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* + according to 802.11h-2003.pdf + Page#26 + Table 19a!XCategory values + Spectrum management (CATEGORY_SPECTRUM) ==> 0 + */ + MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, + sizeof(MEASURE_REQ_INFO), CATEGORY_SPECTRUM, SPEC_MRQ, + MeasureReqToken, MeasureReqMode.word, + MeasureReqType, 1); + + MeasureReq.ChNum = MeasureCh; + MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); + MeasureReq.MeasureDuration = cpu2le16(2000); + + { + ULONG TempLen; + MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen, + sizeof(MEASURE_REQ), &MeasureReq, + END_OF_ARGS); + FrameLen += TempLen; + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen); + +END_OF_MEASURE_REQ: + MlmeFreeMemory(pAd, pOutBuffer); + + return TRUE; +} + +INT Set_TpcReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT wcid; + + UINT8 TpcReqToken = RandomByte(pAd); + + wcid = (UINT) simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::wcid = %d\n", __FUNCTION__, wcid)); + if (!VALID_WCID(wcid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, wcid)); + return TRUE; + } + + TpcReqInsert(pAd, TpcReqToken); + + EnqueueTPCReq(pAd, pAd->MacTab.Content[wcid].Addr, TpcReqToken); + + return TRUE; +} + +#ifdef CONFIG_AP_SUPPORT +INT Set_PwrConstraint( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + +typedef struct __PWR_CONSTRAIN_CFG +{ + CHAR Attenuation; + ULONG TxPowerPercentage; +} PWR_CONSTRAIN_CFG; + + PWR_CONSTRAIN_CFG PwrConstrainTab[] = + { + {0, 100}, + {1, 70}, + {4, 50}, + {6, 20}, + {10, 10}, + {13, 5} + }; +#define PWR_CONSTRAION_TAB_SIZE \ + (sizeof(PwrConstrainTab)/sizeof(PWR_CONSTRAIN_CFG)) + + INT Idx; + LONG Value; + CHAR MaxTxPwr; + CHAR CurTxPwr; + CHAR DaltaPwr; + + Value = (UINT) simple_strtol(arg, 0, 10); + MaxTxPwr = GetRegulatoryMaxTxPwr(pAd, pAd->CommonCfg.Channel) - (CHAR)Value; + CurTxPwr = RTMP_GetTxPwr(pAd, pAd->MacTab.Content[0].HTPhyMode); + DaltaPwr = CurTxPwr - MaxTxPwr; + + if (pAd->CommonCfg.TxPowerPercentage > 90) + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ + DaltaPwr += 1; + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ + DaltaPwr += 3; + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ + DaltaPwr += 6; + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ + DaltaPwr += 9; + else /* reduce Pwr for 12 dB. */ + DaltaPwr += 12; + + DBGPRINT(RT_DEBUG_OFF, ("MaxTxPwr=%d, CurTxPwr=%d, DaltaPwr=%d\n", + MaxTxPwr, CurTxPwr, DaltaPwr)); + + for (Idx = 0; Idx < PWR_CONSTRAION_TAB_SIZE; Idx++) + { + if (DaltaPwr < PwrConstrainTab[Idx].Attenuation) + { + pAd->CommonCfg.PwrConstraint = Value; + pAd->CommonCfg.TxPowerPercentage = + PwrConstrainTab[Idx].TxPowerPercentage; + + break; + } + } + + if (Idx == PWR_CONSTRAION_TAB_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, \ + ("Power constraint value be in range from 0 to 13dB\n")); + } + + + return TRUE; +} + +#ifdef DOT11K_RRM_SUPPORT +INT Set_VoPwrConsTest( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + /* + Set AP Supported Rate Set to signle rate 54Mbps. + */ + pAd->CommonCfg.SupRate[0] = 0x8c; /* 54 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRateLen = 1; + pAd->CommonCfg.ExtRateLen = 0; + + /* + 1. disable AP Dynamic rate switch + 2. and fix it as 54Mbps + 3. set G only mode. + */ + pAd->CommonCfg.VoPwrConstraintTest = TRUE; + APStop(pAd); + APStartUp(pAd); + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.Channel > 14) + pAd->CommonCfg.PhyMode = (WMODE_A | WMODE_AN); + else + pAd->CommonCfg.PhyMode = (WMODE_B | WMODE_G |WMODE_GN); +#endif /* DOT11_N_SUPPORT */ + + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DesiredTransmitSetting.field.FixedTxMode = FIXED_TXMODE_OFDM; + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.DesiredTransmitSetting.field.MCS = 0; + +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + + pAd->MacTab.Content[0].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[0].HTPhyMode.field.iTxBF = 0; + pAd->MacTab.Content[0].HTPhyMode.field.eTxBF = 0; + pAd->MacTab.Content[0].HTPhyMode.field.STBC = 0; + pAd->MacTab.Content[0].HTPhyMode.field.ShortGI = 0; + pAd->MacTab.Content[0].HTPhyMode.field.BW = 0; + pAd->MacTab.Content[0].HTPhyMode.field.MCS = 0; + + pAd->CommonCfg.BasicMlmeRate = RATE_6; + pAd->CommonCfg.MlmeRate = RATE_6; + + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + + /* Stop all auto fall back. */ + RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, 0x08080808); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, 0x08080808); + + return TRUE; +} +#endif /* DOT11K_RRM_SUPPORT */ + +static PDOT11_REGULATORY_INFORMATION GetRugClassRegion( + IN PSTRING pCountryCode, + IN UINT8 RugClass) +{ + PDOT11_REGULATORY_INFORMATION pRugClass; + + pRugClass = NULL; + do + { + if (strncmp(pCountryCode, "US", 2) == 0) + { + if (RugClass >= USA_REGULATORY_INFO_SIZE) + break; + pRugClass = &USARegulatoryInfo[RugClass]; + } + + if (strncmp(pCountryCode, "JP", 2) == 0) + { + if (RugClass >= JP_REGULATORY_INFO_SIZE) + break; + pRugClass = &JapanRegulatoryInfo[RugClass]; + + } + } while (FALSE); + + return pRugClass; +} + +VOID RguClass_BuildBcnChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen) +{ + INT loop; + ULONG TmpLen; + PDOT11_REGULATORY_INFORMATION pRguClassRegion; + PDOT11_CHANNEL_SET pChList; + + for (loop = 0 ;loop < MAX_NUM_OF_REGULATORY_CLASS; loop++) + { + if (pAd->CommonCfg.RegulatoryClass[loop] == 0) + break; + + pRguClassRegion = GetRugClassRegion( + (PSTRING)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[loop]); + + pChList = &pRguClassRegion->ChannelSet; + + if (pRguClassRegion == NULL) + return; + + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChList->ChannelList[0], + 1, &pChList->NumberOfChannels, + 1, &pChList->MaxTxPwr, + END_OF_ARGS); + + *pBufLen += TmpLen; + } + + return; +} +#endif /* CONFIG_AP_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/sys_log.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/sys_log.c new file mode 100644 index 000000000..009504f9b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/sys_log.c @@ -0,0 +1,260 @@ +/* + +*/ + + +#ifdef SYSTEM_LOG_SUPPORT + +#include "rt_config.h" + + +/* for wireless system event message */ +char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { + /* system status event */ + "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ + "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ + "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ + "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ + "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ + "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ + "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ + "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ + "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ + "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ + "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ + "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ + "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ + "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ + "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ + "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ + "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ + "scan completed", /* IW_SCAN_COMPLETED_EVENT_FLAG */ + "scan terminate!! Busy!! Enqueue fail!!", /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ + "channel switch to ", /* IW_CHANNEL_CHANGE_EVENT_FLAG */ + "wireless mode is not support", /* IW_STA_MODE_EVENT_FLAG */ + "blacklisted in MAC filter list", /* IW_MAC_FILTER_LIST_EVENT_FLAG */ + "Authentication rejected because of challenge failure", /* IW_AUTH_REJECT_CHALLENGE_FAILURE */ + "Scanning", /* IW_SCANNING_EVENT_FLAG */ + "Start a new IBSS", /* IW_START_IBSS_FLAG */ + "Join the IBSS", /* IW_JOIN_IBSS_FLAG */ + "Shared WEP fail", /* IW_SHARED_WEP_FAIL*/ + }; + +#ifdef IDS_SUPPORT +/* for wireless IDS_spoof_attack event message */ +char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { + "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ + "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ + "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ + "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ + "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ + "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ + "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ + "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ + "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ + "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ + }; + +/* for wireless IDS_flooding_attack event message */ +char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { + "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ + "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ + "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ + "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ + "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ + "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ + "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ + }; +#endif /* IDS_SUPPORT */ + +#ifdef WSC_INCLUDED +/* for WSC wireless event message */ +char const *pWirelessWscEventText[IW_WSC_EVENT_TYPE_NUM] = { + "PBC Session Overlap", /* IW_WSC_PBC_SESSION_OVERLAP */ + "This WPS Registrar supports PBC", /* IW_WSC_REGISTRAR_SUPPORT_PBC */ + "This WPS Registrar supports PIN", /* IW_WSC_REGISTRAR_SUPPORT_PIN */ + "WPS status success", /* IW_WSC_STATUS_SUCCESS */ + "WPS status fail", /* IW_WSC_STATUS_FAIL */ + "WPS 2 mins time out!", /* IW_WSC_2MINS_TIMEOUT */ + "WPS Send EAPOL_Start!", /* IW_WSC_SEND_EAPOL_START */ + "WPS Send WscStart!", /* IW_WSC_SEND_WSC_START */ + "WPS Send M1!", /* IW_WSC_SEND_M1 */ + "WPS Send M2!", /* IW_WSC_SEND_M2 */ + "WPS Send M3!", /* IW_WSC_SEND_M3 */ + "WPS Send M4!", /* IW_WSC_SEND_M4 */ + "WPS Send M5!", /* IW_WSC_SEND_M5 */ + "WPS Send M6!", /* IW_WSC_SEND_M6 */ + "WPS Send M7!", /* IW_WSC_SEND_M7 */ + "WPS Send M8!", /* IW_WSC_SEND_M8 */ + "WPS Send WscDone!", /* IW_WSC_SEND_DONE */ + "WPS Send WscAck!", /* IW_WSC_SEND_ACK */ + "WPS Send WscNack!", /* IW_WSC_SEND_NACK */ + "WPS Receive WscStart!", /* IW_WSC_RECEIVE_WSC_START */ + "WPS Receive M1!", /* IW_WSC_RECEIVE_M1 */ + "WPS Receive M2!", /* IW_WSC_RECEIVE_M2 */ + "WPS Receive M3!", /* IW_WSC_RECEIVE_M3 */ + "WPS Receive M4!", /* IW_WSC_RECEIVE_M4 */ + "WPS Receive M5!", /* IW_WSC_RECEIVE_M5 */ + "WPS Receive M6!", /* IW_WSC_RECEIVE_M6 */ + "WPS Receive M7!", /* IW_WSC_RECEIVE_M7 */ + "WPS Receive M8!", /* IW_WSC_RECEIVE_M8 */ + "WPS Receive WscDone!", /* IW_WSC_RECEIVE_DONE */ + "WPS Receive WscAck!", /* IW_WSC_RECEIVE_ACK */ + "WPS Receive WscNack!", /* IW_WSC_RECEIVE_NACK */ + "Not only one candidate found" /* IW_WSC_MANY_CANDIDATE */ + }; +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT +// for IWSC wireless event messagechar +const char *pWirelessIWscEventText[IW_IWSC_EVENT_TYPE_NUM] = { + "IWSC - T1 mins time out!", /* IW_IWSC_T1_TIMER_TIMEOUT */ + "IWSC - T2 mins time out!", /* IW_IWSC_T2_TIMER_TIMEOUT */ + "IWSC - Become Registrar", /* IW_IWSC_BECOME_REGISTRAR */ + "IWSC - Become Enrollee", /* IW_IWSC_BECOME_ENROLLEE */ + "IWSC - Entry time out", /* IW_IWSC_ENTRY_TIMER_TIMEOUT */ + }; +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Send log message through wireless event + + Support standard iw_event with IWEVCUSTOM. It is used below. + + iwreq_data.data.flags is used to store event_flag that is defined by user. + iwreq_data.data.length is the length of the event log. + + The format of the event log is composed of the entry's MAC address and + the desired log message (refer to pWirelessEventText). + + ex: 11:22:33:44:55:66 has associated successfully + + p.s. The requirement of Wireless Extension is v15 or newer. + + ======================================================================== +*/ +VOID RtmpDrvSendWirelessEvent( + IN VOID *pAdSrc, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PSTRING pBuf = NULL, pBufPtr = NULL; + USHORT event, type, BufLen; + UCHAR event_table_len = 0; + + if (pAd->CommonCfg.bWirelessEvent == FALSE) + return; + + type = Event_flag & 0xFF00; + event = Event_flag & 0x00FF; + + switch (type) + { + case IW_SYS_EVENT_FLAG_START: + event_table_len = IW_SYS_EVENT_TYPE_NUM; + break; +#ifdef IDS_SUPPORT + case IW_SPOOF_EVENT_FLAG_START: + event_table_len = IW_SPOOF_EVENT_TYPE_NUM; + break; + + case IW_FLOOD_EVENT_FLAG_START: + event_table_len = IW_FLOOD_EVENT_TYPE_NUM; + break; +#endif /* IDS_SUPPORT */ +#ifdef WSC_INCLUDED + case IW_WSC_EVENT_FLAG_START: + event_table_len = IW_WSC_EVENT_TYPE_NUM; + break; +#endif /* WSC_INCLUDED */ +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT + case IW_IWSC_EVENT_FLAG_START: + event_table_len = IW_IWSC_EVENT_TYPE_NUM; + break; +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + } + + if (event_table_len == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type)); + return; + } + + if (event >= event_table_len) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event)); + return; + } + + /*Allocate memory and copy the msg. */ +/* if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) */ + os_alloc_mem(NULL, (UCHAR **)&pBuf, IW_CUSTOM_MAX_LEN); + if(pBuf != NULL) + { + /*Prepare the payload */ + memset(pBuf, 0, IW_CUSTOM_MAX_LEN); + + pBufPtr = pBuf; + + if (pAddr) + pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr)); + else if (BssIdx < MAX_MBSSID_NUM(pAd)) + pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx); + else + pBufPtr += sprintf(pBufPtr, "(RT2860) "); + + if (type == IW_SYS_EVENT_FLAG_START) + { + pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]); + + if (Event_flag == IW_CHANNEL_CHANGE_EVENT_FLAG) + { + pBufPtr += sprintf(pBufPtr, "%3d", Rssi); + } + } +#ifdef IDS_SUPPORT + else if (type == IW_SPOOF_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi); + else if (type == IW_FLOOD_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]); +#endif /* IDS_SUPPORT */ +#ifdef WSC_INCLUDED + else if (type == IW_WSC_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessWscEventText[event]); +#endif /* WSC_INCLUDED */ +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT + else if (type == IW_IWSC_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessIWscEventText[event]); +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + else + pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); + + pBufPtr[pBufPtr - pBuf] = '\0'; + BufLen = pBufPtr - pBuf; + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen); + /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf)); */ + +/* kfree(pBuf); */ + os_free_mem(NULL, pBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__)); +} + +#endif /* SYSTEM_LOG_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/txpower.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/txpower.c new file mode 100644 index 000000000..488f33855 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/txpower.c @@ -0,0 +1,1781 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +INT tx_temp_dbg = 0; + +#ifdef RTMP_TEMPERATURE_COMPENSATION + +/* + Lookup table format: + +ArrayIdx: + 0 1 2 10 11 12 13 14 ...... 46 + +PwrCompen: -12 -11 -10 ...... -2 -1 0 1 2 ....... 31 32 +TempRange: -4 3 10 ....... 114 116 + | + \/ + Temperature reference base + + PwrCompensation in unit of 0.5dB + TempRange in temperature sensor value +*/ + +#define LUT_POSITIVE(_band, _idx) pAd->TxPowerCtrl.LookupTable[(_band)][(_idx) + Offset] +#define LUT_NEGATIVE(_band, _idx) pAd->TxPowerCtrl.LookupTable[(_band)][Offset - (_idx)] +#define LUT_BASE(_band) pAd->TxPowerCtrl.LookupTable[(_band)][Offset] +#define LUT_INDEX(_band, _idx) pAd->TxPowerCtrl.LookupTable[(_band)][(_idx)] + + +VOID InitLookupTable( + IN PRTMP_ADAPTER pAd) +{ + int lut_idx, IdxTmp, pos_idx, pos_bound, neg_idx, neg_bound; + int step_cnt, comp_val; + enum IEEE80211_BAND band; + int band_nums = 1, Offset; + EEPROM_WORD_STRUC WordStruct; + UCHAR PlusStepNum[IEEE80211_BAND_NUMS][8]; + UCHAR MinusStepNum[IEEE80211_BAND_NUMS][8]; + UCHAR Step[IEEE80211_BAND_NUMS]; + + + DBGPRINT(RT_DEBUG_TRACE, ("==> InitLookupTable\n")); + + /* Read from EEPROM, as parameters for lookup table for G band */ + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM\n")); + RT28xx_EEPROM_READ16(pAd, 0x6e, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t6e = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_2G][0] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][2] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x70, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t70 = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_2G][4] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][6] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x72, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t72 = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_2G][0] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][2] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x74, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t74 = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_2G][4] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][6] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x76, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t76 = 0x%x\n", WordStruct.word)); + pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G] = (WordStruct.field.Byte0 & 0x0F); + Step[IEEE80211_BAND_2G] = (WordStruct.field.Byte0 >> 4); + pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G] = (CHAR)WordStruct.field.Byte1; + + DBGPRINT(RT_DEBUG_TRACE, ("\tPlus = %u %u %u %u %u %u %u %u\n", + PlusStepNum[IEEE80211_BAND_2G][0], + PlusStepNum[IEEE80211_BAND_2G][1], + PlusStepNum[IEEE80211_BAND_2G][2], + PlusStepNum[IEEE80211_BAND_2G][3], + PlusStepNum[IEEE80211_BAND_2G][4], + PlusStepNum[IEEE80211_BAND_2G][5], + PlusStepNum[IEEE80211_BAND_2G][6], + PlusStepNum[IEEE80211_BAND_2G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\tMinus = %u %u %u %u %u %u %u %u\n", + MinusStepNum[IEEE80211_BAND_2G][0], + MinusStepNum[IEEE80211_BAND_2G][1], + MinusStepNum[IEEE80211_BAND_2G][2], + MinusStepNum[IEEE80211_BAND_2G][3], + MinusStepNum[IEEE80211_BAND_2G][4], + MinusStepNum[IEEE80211_BAND_2G][5], + MinusStepNum[IEEE80211_BAND_2G][6], + MinusStepNum[IEEE80211_BAND_2G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\ttssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tStep = %u\n", Step[IEEE80211_BAND_2G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tRefTemp = %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G])); + +#ifdef A_BAND_SUPPORT + if (RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM\n")); + /* Read from EEPROM, as parameters for lookup table for A band */ + RT28xx_EEPROM_READ16(pAd, 0xd4, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\td4 = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_5G][0] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][2] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xd6, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\td6 = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_5G][4] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][6] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xd8, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\td8 = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_5G][0] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][2] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xda, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\tda = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_5G][4] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][6] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xdc, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\tdc = 0x%x\n", WordStruct.word)); + pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G] = (WordStruct.field.Byte0 & 0x0F); + Step[IEEE80211_BAND_5G] = (WordStruct.field.Byte0 >> 4); + pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G] = (CHAR)WordStruct.field.Byte1; + + DBGPRINT(RT_DEBUG_TRACE, ("\tPlus = %u %u %u %u %u %u %u %u\n", + PlusStepNum[IEEE80211_BAND_5G][0], + PlusStepNum[IEEE80211_BAND_5G][1], + PlusStepNum[IEEE80211_BAND_5G][2], + PlusStepNum[IEEE80211_BAND_5G][3], + PlusStepNum[IEEE80211_BAND_5G][4], + PlusStepNum[IEEE80211_BAND_5G][5], + PlusStepNum[IEEE80211_BAND_5G][6], + PlusStepNum[IEEE80211_BAND_5G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\tMinus = %u %u %u %u %u %u %u %u\n", + MinusStepNum[IEEE80211_BAND_5G][0], + MinusStepNum[IEEE80211_BAND_5G][1], + MinusStepNum[IEEE80211_BAND_5G][2], + MinusStepNum[IEEE80211_BAND_5G][3], + MinusStepNum[IEEE80211_BAND_5G][4], + MinusStepNum[IEEE80211_BAND_5G][5], + MinusStepNum[IEEE80211_BAND_5G][6], + MinusStepNum[IEEE80211_BAND_5G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\ttssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tStep = %u\n", Step[IEEE80211_BAND_5G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tRefTemp= %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G])); + + band_nums = IEEE80211_BAND_NUMS; + } +#endif /* A_BAND_SUPPORT */ + +#ifdef RT8592 + if (IS_RT8592(pAd)) { + pos_bound = 32; + neg_bound = 12; + Offset = 12; + } + else +#endif /* RT8592 */ + { + pos_bound = 26; + neg_bound = 8; + Offset = 7; + } + + for (band = IEEE80211_BAND_2G; band < band_nums; band++) + { + /* + For positive table, in sequence 0, 1, 2 ...., 31, 32 + F(x) = F(x-1) + Step(x) + with following exception: + F(0) = F(1) - Compensation(x); + F(1) = Step(band) / 2; + + After each step, Compensation value will decrease base on step value and + Compensation(x) = Step(band) - step_cnt; + */ + + LUT_POSITIVE(band,1) = Step[band] / 2; + LUT_BASE(band) = LUT_POSITIVE(band, 1) - Step[band]; + + step_cnt = 0; + IdxTmp = 1; + for (pos_idx = 2; pos_idx <= pos_bound;) + { + comp_val = Step[band] - step_cnt; + LUT_POSITIVE(band, pos_idx) = LUT_POSITIVE(band, pos_idx - 1) + comp_val /* (Step[band] - (step_cnt+1) + 1)*/; + if (PlusStepNum[band][step_cnt] != 0 || step_cnt >= 8) + { + if (pos_idx >= IdxTmp + PlusStepNum[band][step_cnt] && step_cnt < 8) + { + IdxTmp = IdxTmp + PlusStepNum[band][step_cnt]; + step_cnt += 1; + } + pos_idx++; + } + else + { + step_cnt += 1; + } + } + + /* negative */ + step_cnt = 0; + IdxTmp = 1; + for (neg_idx = 1; neg_idx <= neg_bound;) + { + comp_val = Step[band] + step_cnt; + LUT_NEGATIVE(band, neg_idx) = LUT_NEGATIVE(band, (neg_idx - 1)) - comp_val; + if (MinusStepNum[band][step_cnt] != 0 || step_cnt >= 8) + { + if ((neg_idx + 1) >= IdxTmp + MinusStepNum[band][step_cnt] && step_cnt < 8) + { + IdxTmp = IdxTmp + MinusStepNum[band][step_cnt]; + step_cnt += 1; + } + neg_idx++; + } + else + { + step_cnt += 1; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation %sG band(%d)] Lookup table:\n", + (band == 0 ? "2.4" : "5"), band)); + for (lut_idx = 0; lut_idx < LOOKUP_TB_SIZE; lut_idx++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\t%d, %d\n", lut_idx - Offset, LUT_INDEX(band, lut_idx))); + } + } + + bbp_tx_comp_init(pAd, 1, 0); +} + + +VOID AsicGetAutoAgcOffsetForTemperatureSensor( + IN RTMP_ADAPTER *pAd, + IN CHAR *pDeltaPwr, + IN CHAR *pTotalDeltaPwr, + IN CHAR *pAgcCompensate, + IN CHAR *pDeltaPowerByBbpR1) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable; + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry0 = NULL; /* Ant0 */ + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry1 = NULL; /* Ant1 */ + BOOLEAN bAutoTxAgc = FALSE; + PCHAR pTxAgcCompensate = NULL; + UCHAR RFValue = 0; + CHAR TuningTableUpperBound = 0, TuningTableIndex0 = 0, TuningTableIndex1 = 0; + CHAR temper_val, rf_txpwr_bnd; + INT CurrentTemp = 0, RefTemp, lut_base; + INT *LookupTable, LookupTableIndex; + + DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__)); + +#ifdef RT8592 + if (IS_RT8592(pAd)) + lut_base = 12; + else +#endif /* RT8592 */ + lut_base = TEMPERATURE_COMPENSATION_LOOKUP_TABLE_OFFSET; + LookupTableIndex = pAd->TxPowerCtrl.LookupTableIndex + lut_base; + + *pTotalDeltaPwr = 0; + +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { + /* a band channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + TxPowerTuningTable = pChipCap->TxPowerTuningTable_5G; + RefTemp = pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G]; + LookupTable = &pAd->TxPowerCtrl.LookupTable[IEEE80211_BAND_5G][0]; + TuningTableUpperBound = pChipCap->TxAlcTxPowerUpperBound_5G; + rf_txpwr_bnd = 0x2b; + } + else +#endif /* A_BAND_SUPPORT */ + { + /* bg band channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + TxPowerTuningTable = pChipCap->TxPowerTuningTable_2G; + RefTemp = pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G]; + LookupTable = &pAd->TxPowerCtrl.LookupTable[IEEE80211_BAND_2G][0]; + TuningTableUpperBound = pChipCap->TxAlcTxPowerUpperBound_2G; + rf_txpwr_bnd = 0x27; + } + + /* AutoTxAgc in EEPROM means temperature compensation enabled/diablded. */ + if (bAutoTxAgc) + { + /* Current temperature */ + bbp_get_temp(pAd, &temper_val); + CurrentTemp = temper_val; + + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] current temp = %d(0x%x), pAd->curr_temp=%d, temper_val=%d\n", + CurrentTemp, CurrentTemp, pAd->curr_temp, temper_val)); + } + CurrentTemp = pAd->curr_temp; + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] RefTemp = %d\n", RefTemp)); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] index = %d\n", pAd->TxPowerCtrl.LookupTableIndex)); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex - 1, LookupTable[LookupTableIndex - 1])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex, LookupTable[LookupTableIndex])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex + 1, LookupTable[LookupTableIndex + 1])); + } + if (CurrentTemp > RefTemp + LookupTable[LookupTableIndex + 1] + ((LookupTable[LookupTableIndex + 1] - LookupTable[LookupTableIndex]) >> 2) && + LookupTableIndex < (LOOKUP_TB_SIZE - 1)) + { + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] ++\n")); + } + LookupTableIndex++; + pAd->TxPowerCtrl.LookupTableIndex++; + } + else if (CurrentTemp < RefTemp + LookupTable[LookupTableIndex] - ((LookupTable[LookupTableIndex] - LookupTable[LookupTableIndex - 1]) >> 2) && + LookupTableIndex > 0) + { + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] --\n")); + } + LookupTableIndex--; + pAd->TxPowerCtrl.LookupTableIndex--; + } + else + { + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] ==\n")); + } + } + + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] idxTxPowerTable=%d, idxTxPowerTable2=%d, TuningTableUpperBound=%d\n", + pAd->TxPowerCtrl.idxTxPowerTable + pAd->TxPowerCtrl.LookupTableIndex, + pAd->TxPowerCtrl.idxTxPowerTable2 + pAd->TxPowerCtrl.LookupTableIndex, + TuningTableUpperBound)); + } + +#ifdef E3_DBG_FALLBACK + TuningTableIndex0 = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPowerCtrl.LookupTableIndex +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power; +#endif /* DOT11_N_SUPPORT */ +#else + TuningTableIndex0 = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPowerCtrl.LookupTableIndex + + pAd->hw_cfg.cur_ch_pwr[0]; +#endif /* E3_DBG_FALLBACK */ + /* The boundary verification */ + TuningTableIndex0 = (TuningTableIndex0 > TuningTableUpperBound) ? TuningTableUpperBound : TuningTableIndex0; + TuningTableIndex0 = (TuningTableIndex0 < LOWERBOUND_TX_POWER_TUNING_ENTRY) ? + LOWERBOUND_TX_POWER_TUNING_ENTRY : TuningTableIndex0; + TxPowerTuningTableEntry0 = &TxPowerTuningTable[TuningTableIndex0 + TX_POWER_TUNING_ENTRY_OFFSET]; + +#ifdef E3_DBG_FALLBACK + TuningTableIndex1 = pAd->TxPowerCtrl.idxTxPowerTable2 + + pAd->TxPowerCtrl.LookupTableIndex +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power2; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power2; +#endif /* DOT11_N_SUPPORT */ +#else + TuningTableIndex1 = pAd->TxPowerCtrl.idxTxPowerTable2 + + pAd->TxPowerCtrl.LookupTableIndex + + pAd->hw_cfg.cur_ch_pwr[1]; +#endif /* E3_DBG_FALLBACK */ + /* The boundary verification */ + TuningTableIndex1 = (TuningTableIndex1 > TuningTableUpperBound) ? TuningTableUpperBound : TuningTableIndex1; + TuningTableIndex1 = (TuningTableIndex1 < LOWERBOUND_TX_POWER_TUNING_ENTRY) ? + LOWERBOUND_TX_POWER_TUNING_ENTRY : TuningTableIndex1; + TxPowerTuningTableEntry1 = &TxPowerTuningTable[TuningTableIndex1 + TX_POWER_TUNING_ENTRY_OFFSET]; + + /* + Update RF_R49 [0:5], RF_R50[0:5] + The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 + The valid range of the RF R50 (<5:0>tx0_alc<5:0>) is 0x00~0x27 + */ + RT30xxReadRFRegister(pAd, RF_R49, &RFValue); + RFValue &= (~0x3F); + // TODO: Shiang-6590, for a band, the upper bound of RF_R49/RF_R50 shall be 0x2b instead of 0x27!!!! + RFValue |= ((TxPowerTuningTableEntry0->RF_TX_ALC > rf_txpwr_bnd) ? rf_txpwr_bnd : TxPowerTuningTableEntry0->RF_TX_ALC); + RT30xxWriteRFRegister(pAd, RF_R49, RFValue); + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] (tx0)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n", + TxPowerTuningTableEntry0->RF_TX_ALC, TxPowerTuningTableEntry0->MAC_PowerDelta, TuningTableIndex0)); + DBGPRINT(RT_DEBUG_TRACE, ("\tUpdate RF_R49[0:5] to 0x%x\n", (RFValue & 0x3f))); + } + + RT30xxReadRFRegister(pAd, RF_R50, &RFValue); + RFValue &= (~0x3F); + RFValue |= ((TxPowerTuningTableEntry1->RF_TX_ALC > rf_txpwr_bnd) ? rf_txpwr_bnd : TxPowerTuningTableEntry1->RF_TX_ALC); + RT30xxWriteRFRegister(pAd, RF_R50, RFValue); + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] (tx1)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n", + TxPowerTuningTableEntry1->RF_TX_ALC, TxPowerTuningTableEntry1->MAC_PowerDelta, TuningTableIndex1)); + DBGPRINT(RT_DEBUG_TRACE, ("\tUpdate RF_R50[0:5] to 0x%x\n", (RFValue & 0x3f))); + } + + *pTotalDeltaPwr = TxPowerTuningTableEntry0->MAC_PowerDelta; + } + + *pAgcCompensate = *pTxAgcCompensate; + + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("<--%s(): pDeltaPwr=%d, TotalDeltaPwr=%d, AgcCompensate=%d, DeltaPowerByBbpR1=%d\n", + __FUNCTION__, *pDeltaPwr, *pTotalDeltaPwr, *pAgcCompensate, *pDeltaPowerByBbpR1)); +} +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + +#define MDSM_NORMAL_TX_POWER 0x00 +#define MDSM_DROP_TX_POWER_BY_6dBm 0x01 +#define MDSM_DROP_TX_POWER_BY_12dBm 0x02 +#define MDSM_ADD_TX_POWER_BY_6dBm 0x03 +#define MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK 0x03 + + +#ifdef RT6352 +VOID InitRfPaModeTable( + IN PRTMP_ADAPTER pAd) +{ + UINT32 mac_value; + UCHAR bit, pa_value; + + RTMP_IO_READ32(pAd, RF_PA_MODE_CFG0, &mac_value); + + for (bit = 0; bit < 8; bit += 2) /* CCK */ + { + pa_value = (UCHAR)((mac_value >> bit) & (0x03)); + pAd->rf_pa_mode_over_cck[bit/2] = pa_value; + } + + for (bit = 8; bit < 24; bit += 2) /* OFDM */ + { + pa_value = (UCHAR)((mac_value >> bit) & (0x03)); + pAd->rf_pa_mode_over_ofdm[(bit - 8)/2] = pa_value; + } + + RTMP_IO_READ32(pAd, RF_PA_MODE_CFG1, &mac_value); + + for (bit = 0; bit < 32; bit += 2) /* HT */ + { + pa_value = (UCHAR)((mac_value >> bit) & (0x03)); + pAd->rf_pa_mode_over_ht[bit/2] = pa_value; + } +} +#endif /* RT6352 */ + + +VOID AsicGetTxPowerOffset(RTMP_ADAPTER *pAd, ULONG *TxPwr) +{ + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC; + DBGPRINT(RT_DEBUG_INFO, ("-->AsicGetTxPowerOffset\n")); + + NdisZeroMemory(&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + + CfgOfTxPwrCtrlOverMAC.NumOfEntries = 5; /* MAC 0x1314, 0x1318, 0x131C, 0x1320 and 1324 */ + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW == BW_80 && + pAd->CommonCfg.Channel > 14) + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx80MPwrCfgABand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx80MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx80MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx80MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx80MPwrCfgABand[4]; + } + else +#endif /* DOT11_VHT_AC */ + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (pAd->CommonCfg.CentralChannel > 14) + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgABand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx40MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx40MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgABand[4]; + } + else + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgGBand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx40MPwrCfgGBand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgGBand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx40MPwrCfgGBand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->CommonCfg.CentralChannel > 14) + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgABand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx20MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx20MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgABand[4]; + } + else + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgGBand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx20MPwrCfgGBand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgGBand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx20MPwrCfgGBand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgGBand[4]; + } + } + + NdisCopyMemory(TxPwr, (UCHAR *)&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + + DBGPRINT(RT_DEBUG_INFO, ("<--AsicGetTxPowerOffset\n")); +} + + +VOID AsicGetAutoAgcOffsetForExternalTxAlc( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1) +{ + BBP_R49_STRUC BbpR49; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep, idx; + PCHAR pTxAgcCompensate = NULL; + CHAR DeltaPwr = 0; + + DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__)); + + BbpR49.byte = 0; + + /* TX power compensation for temperature variation based on TSSI. Try every 4 second */ + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + if (pAd->CommonCfg.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = (UCHAR *)&pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = (UCHAR *)&pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = (UCHAR *)&pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = (UCHAR *)&pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + bbp_get_temp(pAd, &BbpR49.byte); + + /* TSSI representation */ + if (IS_RT3071(pAd) || IS_RT3390(pAd) || IS_RT3090A(pAd) || IS_RT3572(pAd)) /* 5-bits */ + { + BbpR49.byte = (BbpR49.byte & 0x1F); + } + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49.byte > pTssiMinusBoundary[1]) + { + /* Reading is larger than the reference value */ + /* Check for how large we need to decrease the Tx power */ + for (idx = 1; idx < 5; idx++) + { + if (BbpR49.byte <= pTssiMinusBoundary[idx]) /* Found the range */ + break; + } + /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */ + + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49.byte, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49.byte < pTssiPlusBoundary[1]) + { + /* Reading is smaller than the reference value */ + /* Check for how large we need to increase the Tx power */ + for (idx = 1; idx < 5; idx++) + { + if (BbpR49.byte >= pTssiPlusBoundary[idx]) /* Found the range*/ + break; + } + + /* The index is the step we should increase, idx = 0 means there is nothing to compensate */ + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49.byte, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49.byte, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->CommonCfg.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + + *pDeltaPwr = DeltaPwr; + *pAgcCompensate = *pTxAgcCompensate; + + DBGPRINT(RT_DEBUG_INFO, ("<--%s\n", __FUNCTION__)); +} + + +VOID AsicExtraPowerOverMAC(RTMP_ADAPTER *pAd) +{ + UINT32 txpwr = 0; + UINT32 txpwr7 = 0, txpwr8 = 0, txpwr9 = 0; + + /* For OFDM_54 and HT_MCS_7, extra fill the corresponding register value into MAC 0x13D4 */ + RTMP_IO_READ32(pAd, 0x1318, &txpwr); + txpwr7 |= (txpwr & 0x0000FF00) >> 8; /* Get Tx power for OFDM 54 */ + RTMP_IO_READ32(pAd, 0x131C, &txpwr); + txpwr7 |= (txpwr & 0x0000FF00) << 8; /* Get Tx power for HT MCS 7 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, txpwr7); + + /* For STBC_MCS_7, extra fill the corresponding register value into MAC 0x13DC */ + RTMP_IO_READ32(pAd, 0x1324, &txpwr); + txpwr9 |= (txpwr & 0x0000FF00) >> 8; /* Get Tx power for STBC MCS 7 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, txpwr9); + + if (pAd->CommonCfg.TxStream == 2) + { + /* For HT_MCS_15, extra fill the corresponding register value into MAC 0x13DC */ + RTMP_IO_READ32(pAd, 0x1320, &txpwr); + txpwr8 |= (txpwr & 0x0000FF00) >> 8; /* Get Tx power for HT MCS 15 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, txpwr8); + } + +} + + +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in LINK UP in INFRASTRUCTURE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRatSwitching() + ========================================================================== + */ +VOID AsicAdjustTxPower(RTMP_ADAPTER *pAd) +{ + INT i, j; + CHAR Value; + CHAR Rssi = -127; + CHAR DeltaPwr = 0; + CHAR TxAgcCompensate = 0; + CHAR DeltaPowerByBbpR1 = 0; + CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0}; +#ifdef SINGLE_SKU + CHAR TotalDeltaPowerOri = 0; + UCHAR SingleSKUBbpR1Offset = 0; + ULONG SingleSKUTotalDeltaPwr[MAX_TXPOWER_ARRAY_SIZE] = {0}; +#endif /* SINGLE_SKU */ + + +#ifdef CONFIG_STA_SUPPORT + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) + return; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || +#ifdef RTMP_MAC_PCI + (pAd->bPCIclkOff == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || +#endif /* RTMP_MAC_PCI */ + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(INFRA_ON(pAd)) + { + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Get Tx rate offset table which from EEPROM 0xDEh ~ 0xEFh */ + RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&CfgOfTxPwrCtrlOverMAC); + /* Get temperature compensation delta power value */ + RTMP_CHIP_ASIC_AUTO_AGC_OFFSET_GET( + pAd, &DeltaPwr, &TotalDeltaPower, &TxAgcCompensate, &DeltaPowerByBbpR1); + + DBGPRINT(RT_DEBUG_INFO, ("%s(): DeltaPwr=%d, TotalDeltaPower=%d, TxAgcCompensate=%d, DeltaPowerByBbpR1=%d\n", + __FUNCTION__, + DeltaPwr, + TotalDeltaPower, + TxAgcCompensate, + DeltaPowerByBbpR1)); + +#ifdef RT8592 + // TODO: shiang-6590, fix me for move this ugly function to other place!!! + if (IS_RT8592(pAd) && (pAd->chipCap.rx_temp_comp == TRUE)) { + rx_temp_compensation(pAd); + } +#endif /* RT8592 */ + + + /* Get delta power based on the percentage specified from UI */ + AsicPercentageDeltaPower(pAd, Rssi, &DeltaPwr,&DeltaPowerByBbpR1); + + /* The transmit power controlled by the BBP */ + TotalDeltaPower += DeltaPowerByBbpR1; + /* The transmit power controlled by the MAC */ + TotalDeltaPower += DeltaPwr; + +#ifdef SINGLE_SKU + if (pAd->CommonCfg.bSKUMode == TRUE) + { + /* Re calculate delta power while enabling Single SKU */ + GetSingleSkuDeltaPower(pAd, &TotalDeltaPower, (PULONG)&SingleSKUTotalDeltaPwr, &SingleSKUBbpR1Offset); + + TotalDeltaPowerOri = TotalDeltaPower; + } + else +#endif /* SINGLE_SKU */ + { + AsicCompensatePowerViaBBP(pAd, &TotalDeltaPower); + } + +#if defined(MT7601) || defined(MT76x2) + if (IS_MT7601(pAd) || IS_MT76x2(pAd)) + return; +#endif /* MT7601 */ + + +} + + +#ifdef SINGLE_SKU +VOID GetSingleSkuDeltaPower( + IN RTMP_ADAPTER *pAd, + IN CHAR *pTotalDeltaPower, + INOUT ULONG *pSingleSKUTotalDeltaPwr, + INOUT UCHAR *pSingleSKUBbpR1Offset) +{ + INT i, j; + CHAR Value; + CHAR MinValue = 127; + UCHAR BbpR1 = 0; + UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion; + UCHAR AdjustMaxTxPwr[(MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS * 8)]; + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0}; + + /* Get TX rate offset table which from EEPROM 0xDEh ~ 0xEFh */ + RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&CfgOfTxPwrCtrlOverMAC); + + /* Handle regulatory max. TX power constraint */ + if (pAd->CommonCfg.Channel > 14) + { + TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); /* 5G band */ + } + else + { + TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); /* 2.4G band */ + } + + CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + + /* Use OFDM 6M as the criterion */ + criterion = (UCHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue & 0x000F0000) >> 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d\n", + __FUNCTION__, criterion, TxPwrInEEPROM, CountryTxPwr)); + + /* Adjust max. TX power according to the relationship of TX power in EEPROM */ + for (i=0; i> j*4) & 0x0F); + + if (j < 4) + { + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; /* CCK has 4dBm larger than OFDM */ + } + else + { + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Default)Value=%d, %d\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + } + else + { + for (j=0; j<8; j++) + { + Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F); + + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Default)Value=%d, %d\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + } + } + + /* Adjust TX power according to the relationship */ + for (i=0; i> j*4) & 0x0F); + + /* The TX power is larger than the regulatory, the power should be restrained */ + if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr) + { + Value = (AdjustMaxTxPwr[i*8+j] - CountryTxPwr); + + if (Value > 0xF) + { + /* The output power is larger than Country Regulatory over 15dBm, the origianl design has overflow case */ + DBGPRINT(RT_DEBUG_ERROR,("%s: Value overflow - %d\n", __FUNCTION__, Value)); + } + + *(pSingleSKUTotalDeltaPwr+i) = (*(pSingleSKUTotalDeltaPwr+i) & ~(0x0000000F << j*4)) | (Value << j*4); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Exceed)Value=%d, %d\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, Value=%d, %d, no change\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + } + } + } + + /* Calculate the min. TX power */ + for(i=0; i> j*4) & 0x0F); /* 0 ~ 15 */ + + /* Fix the corner case of Single SKU read eeprom offset 0xF0h ~ 0xFEh which for BBP Instruction configuration */ + if (Value == 0xF) + continue; + + /* Value_offset is current Pwr comapre with Country Regulation and need adjust delta value */ + PwrChange = (CHAR)((*(pSingleSKUTotalDeltaPwr+i) >> j*4) & 0x0F); /* 0 ~ 15 */ + PwrChange -= *pTotalDeltaPower; + + Value -= PwrChange; + + if (MinValue > Value) + MinValue = Value; + } + } + } + + // TODO: shiang, handle this for RLT_BBP!! + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + /* Depend on the min. TX power to adjust and prevent the value of MAC_TX_PWR_CFG less than 0 */ + if ((MinValue < 0) && (MinValue >= -6)) + { + BbpR1 |= MDSM_DROP_TX_POWER_BY_6dBm; + *pSingleSKUBbpR1Offset = 6; + } + else if ((MinValue < -6)&&(MinValue >= -12)) + { + BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm; + *pSingleSKUBbpR1Offset = 12; + } + else if (MinValue < -12) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: ASIC limit..\n", __FUNCTION__)); + BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm; + *pSingleSKUBbpR1Offset = 12; + } +#ifndef E3_DBG_FALLBACK + else { + BbpR1 &= ~MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + *pSingleSKUBbpR1Offset = 0; + } +#endif /* E3_DBG_FALLBACK */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TotalDeltaPower = %d dBm, BbpR1 = 0x%02X \n", __FUNCTION__, *pTotalDeltaPower, BbpR1)); +} +#endif /* SINGLE_SKU */ + + +VOID AsicPercentageDeltaPower( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + INOUT PCHAR pDeltaPwr, + INOUT PCHAR pDeltaPowerByBbpR1) +{ + /* + Calculate delta power based on the percentage specified from UI. + E2PROM setting is calibrated for maximum TX power (i.e. 100%). + We lower TX power here according to the percentage specified from UI. + */ + + if (pAd->CommonCfg.TxPowerPercentage >= 100) /* AUTO TX POWER control */ + { +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) + ) + { + /* To patch high power issue with some APs, like Belkin N1.*/ + if (Rssi > -35) + { + *pDeltaPwr -= 12; + } + else if (Rssi > -40) + { + *pDeltaPwr -= 6; + } + else + ; + } +#endif /* CONFIG_STA_SUPPORT */ + } + else if (pAd->CommonCfg.TxPowerPercentage > 90) /* 91 ~ 100% & AUTO, treat as 100% in terms of mW */ + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* 61 ~ 90%, treat as 75% in terms of mW DeltaPwr -= 1; */ + { + *pDeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* 31 ~ 60%, treat as 50% in terms of mW DeltaPwr -= 3; */ + { + *pDeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* 16 ~ 30%, treat as 25% in terms of mW DeltaPwr -= 6; */ + { + *pDeltaPowerByBbpR1 -= 6; /* -6 dBm */ + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* 10 ~ 15%, treat as 12.5% in terms of mW DeltaPwr -= 9; */ + { + *pDeltaPowerByBbpR1 -= 6; /* -6 dBm */ + *pDeltaPwr -= 3; + } + else /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW DeltaPwr -= 12; */ + { + *pDeltaPowerByBbpR1 -= 12; /* -12 dBm */ + } +} + + +VOID AsicCompensatePowerViaBBP(RTMP_ADAPTER *pAd, CHAR *pTotalDeltaPower) +{ + UCHAR mdsm_drop_pwr; + +#if defined(MT7601) || defined(MT76x2) + if (IS_MT7601(pAd) || IS_MT76x2(pAd)) + { + return; + } +#endif /* MT7601 */ + + DBGPRINT(RT_DEBUG_INFO, ("%s: TotalDeltaPower = %d dBm\n", __FUNCTION__, *pTotalDeltaPower)); + + if (*pTotalDeltaPower <= -12) + { + *pTotalDeltaPower += 12; + mdsm_drop_pwr = MDSM_DROP_TX_POWER_BY_12dBm; + } + else if ((*pTotalDeltaPower <= -6) && (*pTotalDeltaPower > -12)) + { + *pTotalDeltaPower += 6; + mdsm_drop_pwr = MDSM_DROP_TX_POWER_BY_6dBm; + } + else + { + /* Control the the transmit power by using the MAC only */ + mdsm_drop_pwr = MDSM_NORMAL_TX_POWER; + } + + DBGPRINT(RT_DEBUG_INFO, ("%s: Drop the BBP transmit power by %d dBm!\n", + __FUNCTION__, + (mdsm_drop_pwr == MDSM_DROP_TX_POWER_BY_12dBm ? 12 : \ + (mdsm_drop_pwr == MDSM_DROP_TX_POWER_BY_6dBm ? 6 : 0)))); + +#ifdef RT65xx + if (IS_RT65XX(pAd)) + { + UINT32 bbp_val = 0; + + RTMP_BBP_IO_READ32(pAd, TXBE_R4, &bbp_val); + bbp_val &= (~0x3); + bbp_val |= mdsm_drop_pwr; + RTMP_BBP_IO_WRITE32(pAd, TXBE_R4, bbp_val); + DBGPRINT(RT_DEBUG_INFO, ("%s: TotalDeltaPower = %d dBm, TXBE_R4 = 0x%0x\n", __FUNCTION__, *pTotalDeltaPower, bbp_val)); + } +#endif /* RT65xx */ + +#ifdef RTMP_BBP + if (pAd->chipCap.hif_type == HIF_RTMP) + { + UCHAR BbpR1 = 0; + + /* The BBP R1 controls the transmit power for all rates */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + BbpR1 &= ~MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + BbpR1 |= mdsm_drop_pwr; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_INFO, ("%s: TotalDeltaPower = %d dBm, BbpR1 = 0x%02X \n", __FUNCTION__, *pTotalDeltaPower, BbpR1)); + } +#endif /* RTMP_BBP */ +} + + +/* + ======================================================================== + + Routine Description: + Read initial Tx power per MCS and BW from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadTxPwrPerRate(RTMP_ADAPTER *pAd) +{ + ULONG data, Adata, Gdata; + USHORT i, value, value2; + USHORT value_1, value_2, value_3, value_4; + INT Apwrdelta, Gpwrdelta; + UCHAR t1,t2,t3,t4; + BOOLEAN bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; + + + + +#ifdef RT8592 + if (IS_RT8592(pAd)) { + RT85592ReadTxPwrPerRate(pAd); + return; + } +#endif /* RT8592 */ + + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + mt76x2_get_tx_pwr_per_rate(pAd); + return; + } +#endif + + +#ifdef RT6352 + if (IS_RT6352(pAd)) { + RT6352_RTMPReadTxPwrPerRate(pAd); + return; + } +#endif /* RT6352 */ + + + /* For default one, go here!! */ + { + + /* Get power delta for 20MHz and 40MHz.*/ + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); + Apwrdelta = 0; + Gpwrdelta = 0; + + if ((value2 & 0xff) != 0xff) + { + if ((value2 & 0x80)) + Gpwrdelta = (value2&0xf); + + if ((value2 & 0x40)) + bGpwrdeltaMinus = FALSE; + else + bGpwrdeltaMinus = TRUE; + } + if ((value2 & 0xff00) != 0xff00) + { + if ((value2 & 0x8000)) + Apwrdelta = ((value2&0xf00)>>8); + + if ((value2 & 0x4000)) + bApwrdeltaMinus = FALSE; + else + bApwrdeltaMinus = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); + + + /* Get Txpower per MCS for 20MHz in 2.4G.*/ + + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); + data = value; + + /* use value_1 ~ value_4 for code size reduce */ + value_1 = value&0xf; + value_2 = (value&0xf0)>>4; + value_3 = (value&0xf00)>>8; + value_4 = (value&0xf000)>>12; + + if (bApwrdeltaMinus == FALSE) + { + t1 = value_1+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Apwrdelta) + t1 = value_1-(Apwrdelta); + else + t1 = 0; + if (value_2 > Apwrdelta) + t2 = value_2-(Apwrdelta); + else + t2 = 0; + if (value_3 > Apwrdelta) + t3 = value_3-(Apwrdelta); + else + t3 = 0; + if (value_4 > Apwrdelta) + t4 = value_4-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + if (bGpwrdeltaMinus == FALSE) + { + t1 = value_1+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Gpwrdelta) + t1 = value_1-(Gpwrdelta); + else + t1 = 0; + if (value_2 > Gpwrdelta) + t2 = value_2-(Gpwrdelta); + else + t2 = 0; + if (value_3 > Gpwrdelta) + t3 = value_3-(Gpwrdelta); + else + t3 = 0; + if (value_4 > Gpwrdelta) + t4 = value_4-(Gpwrdelta); + else + t4 = 0; + } + Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); + + /* use value_1 ~ value_4 for code size reduce */ + value_1 = value&0xf; + value_2 = (value&0xf0)>>4; + value_3 = (value&0xf00)>>8; + value_4 = (value&0xf000)>>12; + + if (bApwrdeltaMinus == FALSE) + { + t1 = value_1+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Apwrdelta) + t1 = value_1-(Apwrdelta); + else + t1 = 0; + if (value_2 > Apwrdelta) + t2 = value_2-(Apwrdelta); + else + t2 = 0; + if (value_3 > Apwrdelta) + t3 = value_3-(Apwrdelta); + else + t3 = 0; + if (value_4 > Apwrdelta) + t4 = value_4-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + if (bGpwrdeltaMinus == FALSE) + { + t1 = value_1+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Gpwrdelta) + t1 = value_1-(Gpwrdelta); + else + t1 = 0; + if (value_2 > Gpwrdelta) + t2 = value_2-(Gpwrdelta); + else + t2 = 0; + if (value_3 > Gpwrdelta) + t3 = value_3-(Gpwrdelta); + else + t3 = 0; + if (value_4 > Gpwrdelta) + t4 = value_4-(Gpwrdelta); + else + t4 = 0; + } + Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + data |= (value<<16); + + /* For 20M/40M Power Delta issue */ + pAd->Tx20MPwrCfgABand[i] = data; + pAd->Tx20MPwrCfgGBand[i] = data; + pAd->Tx40MPwrCfgABand[i] = Adata; + pAd->Tx40MPwrCfgGBand[i] = Gdata; + + if (data != 0xffffffff) + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata)); + } + } +} + + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadChannelPwr(RTMP_ADAPTER *pAd) +{ + UINT32 i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; +#if (defined(RT30xx) && defined(RTMP_MAC_PCI)) || defined(RT3593) + UCHAR Tx0ALC = 0, Tx1ALC = 0, Tx0FinePowerCtrl = 0, Tx1FinePowerCtrl = 0; +#endif /* (defined(RT30xx) && defined(RTMP_MAC_PCI)) || defined(RT3593) */ + + /* Read Tx power value for all channels*/ + /* Value from 1 - 0x7f. Default value is 24.*/ + /* Power value : 2.4G 0x00 (0) ~ 0x1F (31)*/ + /* : 5.5G 0xF9 (-7) ~ 0x0F (15)*/ + + /* 0. 11b/g, ch1 - ch 14*/ + for (i = 0; i < 7; i++) + { +#if defined(RT5370) || defined(RT5372) || defined(RT5390) || defined(RT5392) || defined(RT5592) || defined(RT3290) || defined(RT65xx) + if (IS_RT5390(pAd) || IS_RT5392(pAd) || IS_RT5592(pAd) || IS_RT3290(pAd) || IS_RT65XX(pAd)) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2,Power.word); + if (IS_RT5392(pAd) || IS_RT5592(pAd)) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2,Power2.word); + } + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + if ((Power.field.Byte0 > 0x27) || (Power.field.Byte0 < 0)) + { + pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; + } + else + { + pAd->TxPower[i * 2].Power = Power.field.Byte0; + } + + if ((Power.field.Byte1 > 0x27) || (Power.field.Byte1 < 0)) + { + pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; + } + else + { + pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; + } + + if (IS_RT5392(pAd) || IS_RT5592(pAd)) + { + if ((Power2.field.Byte0 > 0x27) || (Power2.field.Byte0 < 0)) + { + pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; + } + else + { + pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; + } + + if ((Power2.field.Byte1 > 0x27) || (Power2.field.Byte1 < 0)) + { + pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; + } + else + { + pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TxPower[%d].Power = 0x%02X, TxPower[%d].Power = 0x%02X\n", + __FUNCTION__, + i * 2, + pAd->TxPower[i * 2].Power, + i * 2 + 1, + pAd->TxPower[i * 2 + 1].Power)); + + if (IS_RT5392(pAd) || IS_RT5592(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: TxPower[%d].Power2 = 0x%02X, TxPower[%d].Power2 = 0x%02X\n", + __FUNCTION__, + i * 2, + pAd->TxPower[i * 2].Power2, + i * 2 + 1, + pAd->TxPower[i * 2 + 1].Power2)); + } + } + else +#endif /* defined(RT5370) || defined(RT5372) || defined(RT5390) || defined(RT5392) || defined(RT5592) || defined(RT65xx) */ + { /* Default routine. RT3070 and RT3370 run here. */ + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word); + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + pAd->TxPower[i * 2].Power = Power.field.Byte0; + if(!IS_RT3390(pAd)) // 3370 has different Tx power range + { + if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; + } + + pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; + if(!IS_RT3390(pAd)) // 3370 has different Tx power range + { + if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; + } + + if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; + } + } + + + { + if (IS_RT5592(pAd)) + return; + + /* 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)*/ + /* 1.1 Fill up channel*/ + choffset = 14; + for (i = 0; i < 4; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + + /* 1.2 Fill up power*/ + for (i = 0; i < 6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + /* 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz)*/ + /* 2.1 Fill up channel*/ + choffset = 14 + 12; + for (i = 0; i < 5; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; + pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + /* 2.2 Fill up power*/ + for (i = 0; i < 8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165, 167, 169; 171, 173 (including central frequency in BW 40MHz)*/ + /* 3.1 Fill up channel*/ + choffset = 14 + 12 + 16; + /*for (i = 0; i < 2; i++)*/ + for (i = 0; i < 3; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 3 + choffset + 0].Channel = 171; + pAd->TxPower[3 * 3 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 3 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * 3 + choffset + 1].Channel = 173; + pAd->TxPower[3 * 3 + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 3 + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + /* 3.2 Fill up power*/ + /*for (i = 0; i < 4; i++)*/ + for (i = 0; i < 6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + } + + + /* 4. Print and Debug*/ + /*choffset = 14 + 12 + 16 + 7;*/ + choffset = 14 + 12 + 16 + 11; + + +} + +#ifdef RTMP_TEMPERATURE_COMPENSATION +/* + Note: This function use E2P_OFFSET_START and E2P_OFFSET_END to + determine the table type is minus or plus. +*/ +BOOLEAN LoadTempCompTableFromEEPROM( + IN RTMP_ADAPTER *pAd, + IN const USHORT E2P_OFFSET_START, + IN const USHORT E2P_OFFSET_END, + OUT PUCHAR TssiTable, + IN const INT StartIndex, + IN const UINT32 TABLE_SIZE) +{ + USHORT e2p_value; + INT e2p_index, table_index; + CHAR table_sign; /* +1 for plus table, -1 for minus table */ + + table_sign = (E2P_OFFSET_START < E2P_OFFSET_END) ? 1 : (-1); + + if (StartIndex < TABLE_SIZE) + table_index = StartIndex; + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Error! Wrong starting index (%d).\n", + __FUNCTION__, StartIndex)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Load %s %s table from E2P 0x%x to 0x%x. StartIndex = %d\n", + __FUNCTION__, + pAd->CommonCfg.Channel > 14 ? "5G" : "2.4G", + (table_sign == 1) ? "plus" : "minus", + E2P_OFFSET_START, E2P_OFFSET_END, StartIndex)); + // TODO: Load two bytes + for (e2p_index = E2P_OFFSET_START; + e2p_index != (E2P_OFFSET_END + (1*table_sign)); + e2p_index = e2p_index + (1*table_sign)) + { + RT28xx_EEPROM_READ16(pAd, e2p_index, e2p_value); + TssiTable[table_index] = (UCHAR)(e2p_value & 0xFF); + if ((++table_index) >= TABLE_SIZE) + break; /* table full */ + } + + if (e2p_index != E2P_OFFSET_END) + { + /* Table is full before e2p_offset_end */ + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! EEPROM table may not be completely loaded.\n", + __FUNCTION__)); + return FALSE; + } + else + { + for (table_index = 0; table_index < TABLE_SIZE; table_index++) + DBGPRINT(RT_DEBUG_TRACE, ("\tTable[%d] = %3d (0x%02X)\n", + table_index, (CHAR)TssiTable[table_index], TssiTable[table_index])); + return TRUE; + } + + return TRUE; +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/uapsd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/uapsd.c new file mode 100644 index 000000000..cf2922d44 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/uapsd.c @@ -0,0 +1,2296 @@ +/**************************************************************************** + * 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. + ***************************************************************************/ + + +#define MODULE_WMM_UAPSD +#include "rt_config.h" + +#ifdef UAPSD_SUPPORT +#include "uapsd.h" + +/*#define UAPSD_DEBUG */ + +/* used to enable or disable UAPSD power save queue maintain mechanism */ +UCHAR gUAPSD_FlgNotQueueMaintain; + +#ifdef UAPSD_DEBUG +UINT32 gUAPSD_SP_CloseAbnormalNum; +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_TIMING_RECORD_FUNC +/* all unit: us */ + +UCHAR gUAPSD_TimingFlag; +UINT32 gUAPSD_TimingIndexUapsd; +UINT32 gUAPSD_TimingLoopIndex; + +/* ISR start timestamp */ +UINT64 gUAPSD_TimingIsr[UAPSD_TIMING_RECORD_MAX]; + +/* Tasklet start timestamp */ +UINT64 gUAPSD_TimingTasklet[UAPSD_TIMING_RECORD_MAX]; + +UINT64 gUAPSD_TimingTrgRcv[UAPSD_TIMING_RECORD_MAX]; +UINT64 gUAPSD_TimingMov2Tx[UAPSD_TIMING_RECORD_MAX]; +UINT64 gUAPSD_TimingTx2Air[UAPSD_TIMING_RECORD_MAX]; + +UINT32 gUAPSD_TimingSumIsr2Tasklet; +UINT32 gUAPSD_TimingSumTrig2Txqueue; +UINT32 gUAPSD_TimingSumTxqueue2Air; +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + +#ifdef VENDOR_FEATURE3_SUPPORT +/* +======================================================================== +Routine Description: + Queue packet to a AC software queue. + +Arguments: + pAd Pointer to our adapter + pEntry The station + pQueueHeader The software queue header of the AC + bulkEnPos The packet entry + +Return Value: + None + +Note: + Only for code size reduce purpose. +======================================================================== +*/ +static VOID UAPSD_InsertTailQueueAc( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN QUEUE_HEADER *pQueueHeader, + IN QUEUE_ENTRY *pQueueEntry) +{ + InsertTailQueueAc(pAd, pEntry, pQueueHeader, pQueueEntry); +} +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +/* +======================================================================== +Routine Description: + UAPSD Module Init. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_Init(RTMP_ADAPTER *pAd) +{ + /* allocate a lock resource for SMP environment */ + NdisAllocateSpinLock(pAd, &pAd->UAPSDEOSPLock); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> allocate a spinlock!\n")); +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_DEBUG + gUAPSD_SP_CloseAbnormalNum = 0; +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_TIMING_RECORD_FUNC + gUAPSD_TimingFlag = 0; /* default: DISABLE */ + gUAPSD_TimingIndexUapsd = 0; + gUAPSD_TimingLoopIndex = 0; + + + gUAPSD_TimingSumIsr2Tasklet = 0; + gUAPSD_TimingSumTrig2Txqueue = 0; + gUAPSD_TimingSumTxqueue2Air = 0; +#endif /* UAPSD_TIMING_RECORD_FUNC */ +} + + +/* +======================================================================== +Routine Description: + UAPSD Module Release. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_Release(RTMP_ADAPTER *pAd) +{ + /* free the lock resource for SMP environment */ + NdisFreeSpinLock(&pAd->UAPSDEOSPLock); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> release a spinlock!\n")); +#endif /* UAPSD_DEBUG */ +} /* End of UAPSD_Release */ + + +/* +======================================================================== +Routine Description: + Check if ASIC can enter sleep mode. Not software sleep. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpAsicSleepHandle(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN FlgCanAsicSleep = TRUE; + +#ifdef DOT11Z_TDLS_SUPPORT + /* check TDLS condition */ + FlgCanAsicSleep = TDLS_UAPSDP_AsicCanSleep(pAd); +#endif /* DOT11Z_TDLS_SUPPORT */ + + /* finally, check if we can sleep */ + if (FlgCanAsicSleep == TRUE) + { + /* just mark the flag to FALSE and wait PeerBeacon() to sleep */ + ASIC_PS_CAN_SLEEP(pAd); + } +#endif // CONFIG_STA_SUPPORT // +} + + + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + pEntry Close the SP of the entry + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_SP_Close(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + if ((pEntry != NULL) && (pEntry->PsMode == PWR_SAVE)) + { + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if (pEntry->bAPSDFlagSPStart != 0) + { + /* SP is started for the station */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> [3] close SP!\n")); +#endif /* UAPSD_DEBUG */ + + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* + SP will be closed, should not have EOSP frame + if exists, release it + */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> [3] Free EOSP (UP = %d)!\n", + RTMP_GET_PACKET_UP( + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame)))); +#endif /* UAPSD_DEBUG */ + + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } + + /* re-init SP related parameters */ + pEntry->UAPSDTxNum = 0; + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } +} + + +/* +======================================================================== +Routine Description: + Check if the SP for entry is closed. + +Arguments: + pAd Pointer to our adapter + pEntry the peer entry + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN UAPSD_SP_IsClosed(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + BOOLEAN FlgIsSpClosed = TRUE; + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if ((pEntry) && + (pEntry->PsMode == PWR_SAVE) && + (pEntry->bAPSDFlagSPStart != 0) + ) + FlgIsSpClosed = FALSE; + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + return FlgIsSpClosed; +} + +/* +======================================================================== +Routine Description: + Deliver all queued packets. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + SMP protection by caller for packet enqueue. +======================================================================== +*/ +VOID UAPSD_AllPacketDeliver(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pQueApsd; + PQUEUE_ENTRY pQueEntry; + UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK, + QID_AC_VI, QID_AC_VO }; + INT32 IdAc, QueId; /* must be signed, can not be unsigned */ + + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + /* check if the EOSP frame is yet transmitted out */ + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* queue the EOSP frame to SW queue to be transmitted */ + QueId = RTMP_GET_PACKET_UAPSD_QUE_ID( + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame)); + + if (QueId > QID_AC_VO) + { + /* should not be here, only for sanity */ + QueId = QID_AC_BE; + } + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], + pEntry->pUAPSDEOSPFrame); + + pEntry->pUAPSDEOSPFrame = NULL; + pEntry->UAPSDTxNum = 0; + } + + /* deliver ALL U-APSD packets from AC3 to AC0 (AC0 to AC3 is also ok) */ + for(IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--) + { + pQueApsd = &(pEntry->UAPSDQueue[IdAc]); + QueId = QueIdList[IdAc]; + + while(pQueApsd->Head) + { + pQueEntry = RemoveHeadQueue(pQueApsd); + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], pQueEntry); + } + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); +} + + +/* +======================================================================== +Routine Description: + Parse the UAPSD field in WMM element in (re)association request frame. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + *pElm QoS information field + FlgApsdCapable TRUE: Support UAPSD + +Return Value: + None + +Note: + No protection is needed. + + 1. Association -> TSPEC: + use static UAPSD settings in Association + update UAPSD settings in TSPEC + + 2. Association -> TSPEC(11r) -> Reassociation: + update UAPSD settings in TSPEC + backup static UAPSD settings in Reassociation + + 3. Association -> Reassociation: + update UAPSD settings in TSPEC + backup static UAPSD settings in Reassociation +======================================================================== +*/ +VOID UAPSD_AssocParse( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pElm, + IN BOOLEAN FlgApsdCapable) +{ + PQBSS_STA_INFO_PARM pQosInfo; + UCHAR UAPSD[4]; + UINT32 IdApsd; + + + /* check if the station enables UAPSD function */ + if ((pEntry) && (FlgApsdCapable == TRUE)) + { + /* backup its UAPSD parameters */ + pQosInfo = (PQBSS_STA_INFO_PARM) pElm; + + + UAPSD[QID_AC_BE] = pQosInfo->UAPSD_AC_BE; + UAPSD[QID_AC_BK] = pQosInfo->UAPSD_AC_BK; + UAPSD[QID_AC_VI] = pQosInfo->UAPSD_AC_VI; + UAPSD[QID_AC_VO] = pQosInfo->UAPSD_AC_VO; + + pEntry->MaxSPLength = pQosInfo->MaxSPLength; + + DBGPRINT(RT_DEBUG_TRACE, ("apsd> UAPSD %d %d %d %d!\n", + pQosInfo->UAPSD_AC_BE, pQosInfo->UAPSD_AC_BK, + pQosInfo->UAPSD_AC_VI, pQosInfo->UAPSD_AC_VO)); + DBGPRINT(RT_DEBUG_TRACE, ("apsd> MaxSPLength = %d\n", + pEntry->MaxSPLength)); + + /* use static UAPSD setting of association request frame */ + for(IdApsd=0; IdApsd<4; IdApsd++) + { + pEntry->bAPSDCapablePerAC[IdApsd] = UAPSD[IdApsd]; + pEntry->bAPSDDeliverEnabledPerAC[IdApsd] = UAPSD[IdApsd]; + + } + + if ((pEntry->bAPSDCapablePerAC[QID_AC_BE] == 0) && + (pEntry->bAPSDCapablePerAC[QID_AC_BK] == 0) && + (pEntry->bAPSDCapablePerAC[QID_AC_VI] == 0) && + (pEntry->bAPSDCapablePerAC[QID_AC_VO] == 0)) + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE); + } + else + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE); + } + + if ((pEntry->bAPSDCapablePerAC[QID_AC_BE] == 1) && + (pEntry->bAPSDCapablePerAC[QID_AC_BK] == 1) && + (pEntry->bAPSDCapablePerAC[QID_AC_VI] == 1) && + (pEntry->bAPSDCapablePerAC[QID_AC_VO] == 1)) + { + /* all AC are U-APSD */ + DBGPRINT(RT_DEBUG_TRACE, ("apsd> all AC are UAPSD\n")); + pEntry->bAPSDAllAC = 1; + } + else + { + /* at least one AC is not U-APSD */ + DBGPRINT(RT_DEBUG_TRACE, ("apsd> at least one AC is not UAPSD %d %d %d %d\n", + pEntry->bAPSDCapablePerAC[QID_AC_BE], + pEntry->bAPSDCapablePerAC[QID_AC_BK], + pEntry->bAPSDCapablePerAC[QID_AC_VI], + pEntry->bAPSDCapablePerAC[QID_AC_VO])); + pEntry->bAPSDAllAC = 0; + } + + pEntry->VirtualTimeout = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("apsd> MaxSPLength = %d\n", pEntry->MaxSPLength)); + } +} + + +/* +======================================================================== +Routine Description: + Enqueue a UAPSD packet. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + pPacket UAPSD dnlink packet + IdAc UAPSD AC ID (0 ~ 3) + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_PacketEnqueue( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PNDIS_PACKET pPacket, + IN UINT32 IdAc) +{ + /* + 1. the STATION is UAPSD STATION; + 2. AC ID is legal; + 3. the AC is UAPSD AC. + so we queue the packet to its UAPSD queue + */ + + /* [0] ~ [3], QueIdx base is QID_AC_BE */ + QUEUE_HEADER *pQueUapsd; + + + /* check if current queued UAPSD packet number is too much */ + if (pEntry == NULL) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> pEntry == NULL!\n")); + return; + } /* End of if */ + + pQueUapsd = &(pEntry->UAPSDQueue[IdAc]); + + if (pQueUapsd->Number >= MAX_PACKETS_IN_UAPSD_QUEUE) + { + /* too much queued pkts, free (discard) the tx packet */ + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> many(%u) WCID(%d) AC(%d)\n", + pQueUapsd->Number, + RTMP_GET_PACKET_WCID(pPacket), + IdAc)); + + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + else + { + /* queue the tx packet to the U-APSD queue of the AC */ + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + InsertTailQueue(pQueUapsd, PACKET_TO_QUEUE_ENTRY(pPacket)); + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + +#ifdef UAPSD_DEBUG + if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to uapsd queue...\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("ps> data (0x%08lx) (AC%d) to uapsd queue (num of pkt = %u)...\n", + (ULONG)pPacket, IdAc, + pQueUapsd->Number)); + } +#endif /* UAPSD_DEBUG */ + } +} + + +#ifdef RTMP_MAC_PCI +/* +======================================================================== +Routine Description: + Check if we need to close current SP. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: + 1. We need to call the function in TxDone ISR. + 2. SMP protection by caller for packet enqueue. +======================================================================== +*/ +VOID UAPSD_SP_PacketCheck( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac) +{ + MAC_TABLE_ENTRY *pEntry; + HEADER_802_11 *pHeader; + UINT16 QueId; + UCHAR FlgEosp; + UINT8 TXWISize = pAd->chipCap.TXWISize; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + if (pPacket == NULL) + return; + + /* + NOTE: no aggregation function in U-APSD so dont care about + pTxD->pNextSkb + */ + + /* check if the packet is a U-APSD packet */ + if (RTMP_GET_PACKET_UAPSD_Flag(pPacket) == FALSE) + return; + + /* + Check if all U-APSD packets have been transmitted except + the EOSP packet because we must sure the EOSP packet is + transmitted at last. + */ + + /* get RA STATION entry */ + pEntry = NULL; + if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1) + { + /* + Currently, our QoS Null frame is sent through MMRequest(), + in the function, only SDPtr0 is used, SDPtr1 is not used, + so pDstMac must be got from skb->data + TXWI_SIZE + */ + pDstMac = GET_OS_PKT_DATAPTR(pPacket) + TXWISize; + } + + pHeader = (HEADER_802_11 *)(pDstMac); + + if (pHeader != NULL) + { + if (((pHeader->FC.Type == FC_TYPE_DATA) && + (pHeader->FC.SubType == SUBTYPE_QOS_NULL)) || + ((pHeader->FC.Type == FC_TYPE_MGMT) && + (pHeader->FC.SubType == SUBTYPE_ACTION))) + { + /* the packet is a QoS NULL frame */ + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, pPacket, pDstMac); + return; + } + + /* Addr1 = receiver address */ + pEntry = MacTableLookup(pAd, pHeader->Addr1); + } + + FlgEosp = FALSE; + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if ((pEntry != NULL) && (pEntry->bAPSDFlagSpRoughUse != 0)) + { + /* Note: UAPSDTxNum does NOT include the EOSP packet */ + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> a qos data frame is DMA done (Num = %d)!\n", + pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + + if (pEntry->UAPSDTxNum > 0) + { + /* some UAPSD packets are not yet transmitted */ + if (pEntry->UAPSDTxNum == 1) + { + /* this is the last UAPSD packet */ + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* transmit the EOSP frame */ + PNDIS_PACKET pPkt; + + pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame); + QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt); + + if (QueId > QID_AC_VO) + { + /* should not be here, only for sanity */ + QueId = QID_AC_BE; + } + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], + pEntry->pUAPSDEOSPFrame); + + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + + /* + The EOSP frame will be put into ASIC to tx in + RTMPHandleTxRingDmaDoneInterrupt(), not + the function. + */ + } + } + + /* a UAPSD frame is transmitted so decrease the counter */ + pEntry->UAPSDTxNum --; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + UINT32 IntSrcReg, INT_RX = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_RX = RLT_INT_RX_DATA; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_RX = RTMP_INT_RX; +#endif /* RTMP_MAC */ + /* activate RX Done handle thread */ + + /* + Maybe some uplink packets are received between + EOSP frame start transmission and end + transmssion, we must forward them first or we + will regard them as new trigger frames. + + We will clear all STATION bAPSDFlagSPStart flag + in RX done handler when U-APSD function is + enabled. + + I dont want to use another flag to check if do + the job because I also need a spin lock to + protect the flag, the protection will cause TX + DONE & RX DONE relation. + */ + + /* 1: means EOSP is sent to the peer so we can close current SP */ + + /* + We can not guarantee RTMPHandleRxDoneInterrupt() + will be called before + RTMPHandleTxRingDmaDoneInterrupt() in RTMPIsr() + */ + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSrcReg); + + if ((IntSrcReg & INT_RX) == 0) + { + /* No any received packet exists so no any uplink packet exists. */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } + else + { + /* + A received packet exists we will handle it + in RTMPIsr(), dont worry. + But we only handle max 16 received packets + in RTMPHandleRxDoneInterrupt so risk exists. + */ + pEntry->bAPSDFlagEOSPOK = 1; + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP in SP_PacketCheck()!\n")); +#endif /* UAPSD_DEBUG */ + } + } + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + + /* maybe transmit the EOSP frame */ + if (FlgEosp == TRUE) + { + POS_COOKIE pCookie; + + pCookie = (POS_COOKIE) pAd->OS_Cookie; + + /* + Too many functions call NICUpdateFifoStaCounters() and + NICUpdateFifoStaCounters() will call UAPSD_SP_AUE_Handle(), + if we call RTMPDeQueuePacket() here, double-IRQ LOCK will + occur. so we need to activate a tasklet to send EOSP frame. + + ex: RTMPDeQueuePacket() --> RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() ERROR! or + + RTMPHandleTxRingDmaDoneInterrupt() --> + RTMP_IRQ_LOCK() --> + RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> + UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() --> + DEQUEUE_LOCK() --> + RTMP_IRQ_LOCK() ERROR! + */ + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); + } +} + + +/* +======================================================================== +Routine Description: + Handle QoS Null Frame Tx Done or Management Tx Done interrupt. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: + Only for PCI-based device. +======================================================================== +*/ +VOID UAPSD_QoSNullTxMgmtTxDoneHandle( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac) +{ + HEADER_802_11 *pHeader; + MAC_TABLE_ENTRY *pEntry; + UINT32 IntSrcReg, INT_RX = 0; + + + if (pPacket == NULL) + return; + + /* check if the packet is a U-APSD packet, must be QoS Null frame */ + if (RTMP_GET_PACKET_UAPSD_Flag(pPacket) != TRUE) + return; + + /* check if the packet sub type is QoS Null */ + if (pDstMac == NULL) + return; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_RX = RLT_INT_RX_DATA; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_RX = RTMP_INT_RX; +#endif /* RTMP_MAC */ + + pHeader = (HEADER_802_11 *)pDstMac; + + /* find the destination STATION */ + pEntry = MacTableLookup(pAd, pHeader->Addr1); + + if ((pHeader->FC.Type == FC_TYPE_DATA) && + (pHeader->FC.SubType == SUBTYPE_QOS_NULL)) + { + /* + Currently, QoS Null type is only used in UAPSD mechanism + and no any UAPSD data packet exists + */ + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if ((pEntry != NULL) && + (pEntry->bAPSDFlagSpRoughUse != 0) && + (pEntry->bAPSDFlagSPStart != 0)) + { + /* SP is started for the station */ + + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* SP will be closed, should not have EOSP frame */ + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } + + pEntry->UAPSDTxNum = 0; + + /* check if rx done interrupt exists */ + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSrcReg); + + if ((IntSrcReg & INT_RX) == 0) + { + /* no any new uplink packet is received */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } + else + { + /* + A new uplink packet is received so check if the uplink + packet is transmitted from the station and close SP + in RxDone(). + */ + pEntry->bAPSDFlagEOSPOK = 1; + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP in QoSNullTxDoneHandle()!\n")); +#endif /* UAPSD_DEBUG */ + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } + else if ((pHeader->FC.Type == FC_TYPE_MGMT) && + (pHeader->FC.SubType == SUBTYPE_ACTION)) + { + UINT16 QueId; + + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if ((pEntry != NULL) && + (pEntry->bAPSDFlagSpRoughUse != 0) && + (pEntry->bAPSDFlagSPStart != 0)) + { + BOOLEAN FlgEosp = FALSE; + + + /* Note: UAPSDTxNum does NOT include the EOSP packet */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> a ps mgmt frame is DMA done(Num = %d)!\n", + pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + + if (pEntry->UAPSDTxNum > 0) + { + /* some UAPSD packets are not yet transmitted */ + + if (pEntry->UAPSDTxNum == 1) + { + /* this is the last UAPSD packet */ + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* so transmit its EOSP frame */ + PNDIS_PACKET pPkt; + + + pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame); + QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt); + + if (QueId > QID_AC_VO) + { + /* should not be here, only for sanity */ + QueId = QID_AC_BE; + } + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, + &pAd->TxSwQueue[QueId], + pEntry->pUAPSDEOSPFrame); + + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + + /* + The EOSP frame will be put into ASIC to tx + in RTMPHandleTxRingDmaDoneInterrupt(), + not the function. + */ + } + } + + /* a UAPSD frame is transmitted so counter -- */ + pEntry->UAPSDTxNum --; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + /* + Activate RX Done handle thread + + Maybe some uplink packets are received between + EOSP frame start transmission and end + transmssion, we must forward them first or we + will regard them as new trigger frames. + + We will clear all STATION bAPSDFlagSPStart flag + in RX done handler when U-APSD function is + enabled. + + I dont want to use another flag to check if do + the job because I also need a spin lock to + protect the flag, the protection will cause TX + DONE & RX DONE relation. + + 1: means EOSP is sent to the peer so we can close + current SP. + + We can not guarantee RTMPHandleRxDoneInterrupt() + will be called before + RTMPHandleTxRingDmaDoneInterrupt() in RTMPIsr(). + */ + UINT32 INT_RX = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_RX = RLT_INT_RX_DATA; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_RX = RTMP_INT_RX; +#endif /* RTMP_MAC */ + + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSrcReg); + if ((IntSrcReg & INT_RX) == 0) + { + /* + No any received pkt exists so no any uplink pkt exists. + */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP2 in QoSNullTxMgmtTxDoneHandle()!\n")); +#endif /* UAPSD_DEBUG */ + } + else + { + /* + A received packet exists we will handle it + in RTMPIsr(), dont worry. + But we only handle max 16 received packets + in RTMPHandleRxDoneInterrupt so risk exists. + */ + pEntry->bAPSDFlagEOSPOK = 1; + } + } + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + /* maybe transmit the EOSP frame */ + if (FlgEosp == TRUE) + { + POS_COOKIE pCookie = (POS_COOKIE) pAd->OS_Cookie; + + /* + Too many functions call NICUpdateFifoStaCounters() and + NICUpdateFifoStaCounters() will call UAPSD_SP_AUE_Handle(), + if we call RTMPDeQueuePacket() here, double-IRQ LOCK will + occur. so we need to activate a tasklet to send EOSP frame. + + ex: RTMPDeQueuePacket() --> RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() ERROR! or + + RTMPHandleTxRingDmaDoneInterrupt() --> + RTMP_IRQ_LOCK() --> + RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> + UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() --> + DEQUEUE_LOCK() --> + RTMP_IRQ_LOCK() ERROR! + */ + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); + } + } + else + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } +} +#endif /* RTMP_MAC_PCI */ + + +/* +======================================================================== +Routine Description: + Maintenance our UAPSD PS queue. Release all queued packet if timeout. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + If in RT2870, pEntry can not be removed during UAPSD_QueueMaintenance() +======================================================================== +*/ +VOID UAPSD_QueueMaintenance(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pQue; + UINT32 IdAc; + BOOLEAN FlgUapsdPkt, FlgEospPkt; + + + if (gUAPSD_FlgNotQueueMaintain) + return; + + if (pEntry->PsMode != PWR_SAVE) + return; /* UAPSD packet only for power-save STA, not active STA */ + + /* init */ + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + pQue = pEntry->UAPSDQueue; + FlgUapsdPkt = 0; + FlgEospPkt = 0; + + /* check if more than one U-APSD packets exists */ + for(IdAc=0; IdAcpUAPSDEOSPFrame != NULL) + FlgEospPkt = 1; + + /* check if any queued UAPSD packet exists */ + if (FlgUapsdPkt || FlgEospPkt) + { + + pEntry->UAPSDQIdleCount ++; + if (pEntry->UAPSDQIdleCount > pAd->MacTab.MsduLifeTime) + { + if (FlgUapsdPkt) + { + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> UAPSD queue timeout! clean all queued frames...\n")); + } + + if (FlgEospPkt) + { + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> UAPSD EOSP timeout! clean the EOSP frame!\n")); + } + + /* UAPSDQIdleCount will be 0 after trigger frame is received */ + + /* clear all U-APSD packets */ + if (FlgUapsdPkt) + { + for(IdAc=0; IdAcUAPSDTxNum = 0; + + if (pEntry->pUAPSDEOSPFrame != NULL) + { + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } + + pEntry->bAPSDFlagEOSPOK = 0; + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + + /* clear idle counter */ + pEntry->UAPSDQIdleCount = 0; + +#ifdef CONFIG_AP_SUPPORT + /* check TIM bit */ + if (pEntry->PsQueue.Number == 0) + { + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, pEntry->Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + } + + } + else + { + /* clear idle counter */ + pEntry->UAPSDQIdleCount = 0; + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + /* virtual timeout handle */ + RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(pEntry); +} + + +/* +======================================================================== +Routine Description: + Close SP in Tx Done, not Tx DMA Done. + +Arguments: + pAd Pointer to our adapter + pEntry destination entry + FlgSuccess 0:tx success, 1:tx fail + +Return Value: + None + +Note: + For RT28xx series, for packetID=0 or multicast frame, no statistics + count can be got, ex: ARP response or DHCP packets, we will use + low rate to set (CCK, MCS=0=packetID). + So SP will not be close until UAPSD_EPT_SP_INT timeout. + + So if the tx rate is 1Mbps for a entry, we will use DMA done, not + use UAPSD_SP_AUE_Handle(). +======================================================================== +*/ +VOID UAPSD_SP_AUE_Handle( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FlgSuccess) +{ +#ifdef UAPSD_SP_ACCURATE + USHORT QueId; + + + if (pEntry == NULL) + return; + + if (pEntry->PsMode == PWR_ACTIVE) + { +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: Station actives! Close SP!\n")); +#endif /* UAPSD_DEBUG */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + UAPSD_SP_END(pAd, pEntry); + return; + } + + if (pEntry->PsMode == PWR_SAVE) + { + BOOLEAN FlgEosp; + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if (pEntry->bAPSDFlagSpRoughUse != 0) + { + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return; /* use DMA mechanism, not statistics count mechanism */ + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: Tx Num = %d\n", pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + + FlgEosp = FALSE; + + if (pEntry->bAPSDFlagSPStart == 0) + { + /* + When SP is not started, all packets are from legacy PS queue. + One downlink packet for one PS-Poll packet. + */ + pEntry->bAPSDFlagLegacySent = 0; + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> legacy PS packet is sent!\n")); +#endif /* UAPSD_DEBUG */ + } + else + { +#ifdef UAPSD_TIMING_RECORD_FUNC + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TX2AIR); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + } + + /* record current time */ + UAPSD_TIME_GET(pAd, pEntry->UAPSDTimeStampLast); + + /* Note: UAPSDTxNum does NOT include the EOSP packet */ + if (pEntry->UAPSDTxNum > 0) + { + /* some UAPSD packets are not yet transmitted */ + + if (pEntry->UAPSDTxNum == 1) + { + /* this is the last UAPSD packet */ + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* transmit the EOSP frame */ + PNDIS_PACKET pPkt; + + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: send EOSP frame...\n")); +#endif /* UAPSD_DEBUG */ + + pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame); + QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt); + + if (QueId > QID_AC_VO) + { + /* should not be here, only for sanity */ + QueId = QID_AC_BE; + } + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], + pEntry->pUAPSDEOSPFrame); + + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + } + } + + /* a UAPSD frame is transmitted so decrease the counter */ + pEntry->UAPSDTxNum --; + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + /* maybe transmit the EOSP frame */ + if (FlgEosp == TRUE) + { + POS_COOKIE pCookie = (POS_COOKIE)pAd->OS_Cookie; + + /* + Too many functions call NICUpdateFifoStaCounters() and + NICUpdateFifoStaCounters() will call UAPSD_SP_AUE_Handle(), + if we call RTMPDeQueuePacket() here, double-IRQ LOCK will + occur. so we need to activate a tasklet to send EOSP frame. + + ex: RTMPDeQueuePacket() --> RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() ERROR! or + + RTMPHandleTxRingDmaDoneInterrupt() --> + RTMP_IRQ_LOCK() --> + RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> + UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() --> + DEQUEUE_LOCK() --> + RTMP_IRQ_LOCK() ERROR! + */ + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); + } + /* must return here; Or double unlock UAPSDEOSPLock */ + return; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pAd->bAPSDFlagSPSuspend == 1) + { +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: SP is suspend, keep SP if exists!\n")); +#endif /* UAPSD_DEBUG */ + + /* keep SP, not to close SP */ + pEntry->bAPSDFlagEOSPOK = 1; + } + + if ((pEntry->bAPSDFlagSPStart != 0) && + (pAd->bAPSDFlagSPSuspend == 0)) + { + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + UAPSD_SP_END(pAd, pEntry); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: close a SP.\n\n\n")); +#endif /* UAPSD_DEBUG */ + } + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } +#endif /* UAPSD_SP_ACCURATE */ +} + + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: + When we receive EOSP frame tx done interrupt and a uplink packet + from the station simultaneously, we will regard it as a new trigger + frame because the packet is received when EOSP frame tx done interrupt. + + We can not sure the uplink packet is sent after old SP or in the old SP. + So we must close the old SP in receive done ISR to avoid the problem. +======================================================================== +*/ +VOID UAPSD_SP_CloseInRVDone(RTMP_ADAPTER *pAd) +{ + UINT32 IdEntry; + int FirstWcid = 0; + + + if (pAd->MacTab.fAnyStationInPsm == FALSE) + return; /* no any station is in power save mode */ + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + FirstWcid = 2; +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + + /* check for all CLIENT's UAPSD Service Period */ + for(IdEntry = FirstWcid; IdEntry < MAX_LEN_OF_MAC_TABLE; IdEntry++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[IdEntry]; + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + /* check if SP is started and EOSP is transmitted ok */ + if ((pEntry->bAPSDFlagSPStart != 0) && + (pEntry->bAPSDFlagEOSPOK != 0)) + { + /* + 1. SP is started; + 2. EOSP frame is sent ok. + */ + + /* + We close current SP for the STATION so we can receive new + trigger frame from the STATION again. + */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE,("uapsd> close SP in %s()!\n", + __FUNCTION__)); +#endif /* UAPSD_DEBUG */ + + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } +} + + +#ifdef UAPSD_TIMING_RECORD_FUNC +/* +======================================================================== +Routine Description: + Enable/Disable Timing Record Function. + +Arguments: + pAd Pointer to our adapter + Flag 1 (Enable) or 0 (Disable) + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TimingRecordCtrl(UINT32 Flag) +{ + if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) + return; + + gUAPSD_TimingFlag = Flag; +} + + +/* +======================================================================== +Routine Description: + Record some timings. + +Arguments: + pAd Pointer to our adapter + Type The timing is for what type + +Return Value: + None + +Note: + UAPSD_TIMING_RECORD_ISR + UAPSD_TIMING_RECORD_TASKLET + UAPSD_TIMING_RECORD_TRG_RCV + UAPSD_TIMING_RECORD_MOVE2TX + UAPSD_TIMING_RECORD_TX2AIR +======================================================================== +*/ +VOID UAPSD_TimingRecord(RTMP_ADAPTER *pAd, UINT32 Type) +{ + UINT32 Index; + + if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_STOP) + return; + + if ((gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) && + (Type != UAPSD_TIMING_RECORD_TX2AIR)) + { + return; + } + + Index = gUAPSD_TimingIndexUapsd; + + switch(Type) + { + case UAPSD_TIMING_RECORD_ISR: + /* start to record the timing */ + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingIsr[Index]); + break; + + case UAPSD_TIMING_RECORD_TASKLET: + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingTasklet[Index]); + break; + + case UAPSD_TIMING_RECORD_TRG_RCV: + if (gUAPSD_TimingLoopIndex == 0) + { + /* + The trigger frame is the first received frame. + The received time will be the time recorded in ISR. + */ + gUAPSD_TimingTrgRcv[Index] = gUAPSD_TimingIsr[Index]; + } + else + { + /* + Some packets are handled before the trigger frame so + we record next one. + */ + UAPSD_TIMING_RECORD_STOP(); + } + break; + + case UAPSD_TIMING_RECORD_MOVE2TX: + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingMov2Tx[Index]); + + /* prepare to wait for tx done */ + UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_SUSPEND); + break; + + case UAPSD_TIMING_RECORD_TX2AIR: + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingTx2Air[Index]); + + /* sum the delay */ + gUAPSD_TimingSumIsr2Tasklet += \ + (UINT32)(gUAPSD_TimingTasklet[Index] - gUAPSD_TimingIsr[Index]); + gUAPSD_TimingSumTrig2Txqueue += \ + (UINT32)(gUAPSD_TimingMov2Tx[Index] - gUAPSD_TimingTrgRcv[Index]); + gUAPSD_TimingSumTxqueue2Air += \ + (UINT32)(gUAPSD_TimingTx2Air[Index] - gUAPSD_TimingMov2Tx[Index]); + + /* display average delay */ + if ((Index % UAPSD_TIMING_RECORD_DISPLAY_TIMES) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> Isr2Tasklet=%d, Trig2Queue=%d, Queue2Air=%d micro seconds\n", + gUAPSD_TimingSumIsr2Tasklet/ + UAPSD_TIMING_RECORD_DISPLAY_TIMES, + gUAPSD_TimingSumTrig2Txqueue/ + UAPSD_TIMING_RECORD_DISPLAY_TIMES, + gUAPSD_TimingSumTxqueue2Air/ + UAPSD_TIMING_RECORD_DISPLAY_TIMES)); + gUAPSD_TimingSumIsr2Tasklet = 0; + gUAPSD_TimingSumTrig2Txqueue = 0; + gUAPSD_TimingSumTxqueue2Air = 0; + } + + /* ok, a record is finished; prepare to record the next one */ + gUAPSD_TimingIndexUapsd ++; + + if (gUAPSD_TimingIndexUapsd >= UAPSD_TIMING_RECORD_MAX) + gUAPSD_TimingIndexUapsd = 0; + + /* stop the record */ + gUAPSD_TimingFlag = UAPSD_TIMING_CTRL_STOP; + + DBGPRINT(RT_DEBUG_TRACE, ("sam> Isr->Tasklet:%d, Trig->TxQueue:%d, TxQueue->TxDone:%d\n", + (UINT32)(gUAPSD_TimingTasklet[Index] - gUAPSD_TimingIsr[Index]), + (UINT32)(gUAPSD_TimingMov2Tx[Index] - gUAPSD_TimingTrgRcv[Index]), + (UINT32)(gUAPSD_TimingTx2Air[Index] - gUAPSD_TimingMov2Tx[Index]))); + break; + } +} + + +/* +======================================================================== +Routine Description: + Record the loop index for received packet handle. + +Arguments: + pAd Pointer to our adapter + LoopIndex The RxProcessed in rtmp_rx_done_handle() + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TimeingRecordLoopIndex(UINT32 LoopIndex) +{ + gUAPSD_TimingLoopIndex = LoopIndex; +} +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + +/* +======================================================================== +Routine Description: + Handle PS-Poll Frame. + +Arguments: + pAd Pointer to our adapter + *pEntry the source STATION + +Return Value: + TRUE Handle OK + FALSE Handle FAIL + +Note: +======================================================================== +*/ +BOOLEAN UAPSD_PsPollHandle(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pAcPsQue; + QUEUE_HEADER *pAcSwQue; + PQUEUE_ENTRY pQuedEntry; + PNDIS_PACKET pQuedPkt; + UINT32 AcQueId; + /* + AC ID = VO > VI > BK > BE + so we need to change BE & BK + => AC priority = VO > VI > BE > BK + */ + UINT32 AcPriority[WMM_NUM_OF_AC] = { 1, 0, 2, 3 }; + UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK, + QID_AC_VI, QID_AC_VO }; + BOOLEAN FlgQueEmpty; + INT32 IdAc; /* must be signed, can not use unsigned */ + UINT32 Aid, QueId; + + + if (pEntry == NULL) + return FALSE; + + FlgQueEmpty = TRUE; + pAcSwQue = NULL; + pQuedPkt = NULL; + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if (pEntry->bAPSDAllAC == 0) + { + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return FALSE; /* not all AC are delivery-enabled */ + } + + if (pEntry->bAPSDFlagSPStart != 0) + { + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return FALSE; /* its service period is not yet ended */ + } + + /* from highest priority AC3 --> AC2 --> AC0 --> lowest priority AC1 */ + for (IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--) + { + AcQueId = AcPriority[IdAc]; + + /* + NOTE: get U-APSD queue pointer here to speed up, do NOT use + pEntry->UAPSDQueue[AcQueId] throughout codes because + compiler will compile it to many assembly codes. + */ + pAcPsQue = &pEntry->UAPSDQueue[AcQueId]; + + /* check if any U-APSD packet is queued for the AC */ + if (pAcPsQue->Head == NULL) + continue; + + /* at least one U-APSD packet exists here */ + + /* put U-APSD packets to the AC software queue */ + if ((pAcPsQue->Head != NULL) && (pQuedPkt == NULL)) + { + /* get AC software queue */ + QueId = QueIdList[AcQueId]; + pAcSwQue = &pAd->TxSwQueue[QueId]; + + /* get the U-APSD packet */ + pQuedEntry = RemoveHeadQueue(pAcPsQue); + pQuedPkt = QUEUE_ENTRY_TO_PACKET(pQuedEntry); + + if (pQuedPkt != NULL) + { + /* + WMM Specification V1.1 3.6.1.7 + The More Data bit (b13) of the directed MSDU or MMPDU + associated with delivery-enabled ACs and destined for + that WMM STA indicates that more frames are buffered for + the delivery-enabled ACs. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, TRUE); + + /* set U-APSD flag & its software queue ID */ + RTMP_SET_PACKET_UAPSD(pQuedPkt, TRUE, QueId); + } + } + + if (pAcPsQue->Head != NULL) + { + /* still have packets in queue */ + FlgQueEmpty = FALSE; + break; + } + } + + if (pQuedPkt != NULL) + { + if (FlgQueEmpty == TRUE) + { + /* + No any more queued U-APSD packet so clear More Data bit of + the last frame. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, FALSE); + } + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pAcSwQue, pQuedPkt); + } + + /* clear corresponding TIM bit */ + /* get its AID for the station */ + Aid = pEntry->Aid; + if ((pEntry->bAPSDAllAC == 1) && (FlgQueEmpty == TRUE)) + { + /* all AC are U-APSD and no any U-APSD packet is queued, set TIM */ +#ifdef CONFIG_AP_SUPPORT + /* clear TIM bit */ + if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE)) + { + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* reset idle timeout here whenever a trigger frame is received */ + pEntry->UAPSDQIdleCount = 0; + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Get the queue status for delivery-enabled AC. + +Arguments: + pAd Pointer to our adapter + pEntry the peer entry + pFlgIsAnyPktForBK TRUE: At lease a BK packet is queued + pFlgIsAnyPktForBE TRUE: At lease a BE packet is queued + pFlgIsAnyPktForVI TRUE: At lease a VI packet is queued + pFlgIsAnyPktForVO TRUE: At lease a VO packet is queued + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_QueueStatusGet( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + OUT BOOLEAN *pFlgIsAnyPktForBK, + OUT BOOLEAN *pFlgIsAnyPktForBE, + OUT BOOLEAN *pFlgIsAnyPktForVI, + OUT BOOLEAN *pFlgIsAnyPktForVO) +{ + *pFlgIsAnyPktForBK = FALSE; + *pFlgIsAnyPktForBE = FALSE; + *pFlgIsAnyPktForVI = FALSE; + *pFlgIsAnyPktForVO = FALSE; + + if (pEntry == NULL) + return; + + /* get queue status */ + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + if (pEntry->UAPSDQueue[QID_AC_BK].Head != NULL) + *pFlgIsAnyPktForBK = TRUE; + if (pEntry->UAPSDQueue[QID_AC_BE].Head != NULL) + *pFlgIsAnyPktForBE = TRUE; + if (pEntry->UAPSDQueue[QID_AC_VI].Head != NULL) + *pFlgIsAnyPktForVI = TRUE; + if (pEntry->UAPSDQueue[QID_AC_VO].Head != NULL) + *pFlgIsAnyPktForVO = TRUE; + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); +} + + +/* +======================================================================== +Routine Description: + Handle UAPSD Trigger Frame. + +Arguments: + pAd Pointer to our adapter + *pEntry the source STATION + UpOfFrame the UP of the trigger frame + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TriggerFrameHandle(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR UpOfFrame) +{ + QUEUE_HEADER *pAcPsQue; + QUEUE_HEADER *pAcSwQue, *pLastAcSwQue; + PQUEUE_ENTRY pQuedEntry; + PNDIS_PACKET pQuedPkt; + + UINT32 AcQueId; + UINT32 TxPktNum, SpMaxLen; + /* + AC ID = VO > VI > BK > BE + so we need to change BE & BK + => AC priority = VO > VI > BE > BK + */ + UINT32 AcPriority[WMM_NUM_OF_AC] = { 1, 0, 2, 3 }; + /* 0: deliver all U-APSD packets */ + UINT32 SpLenMap[WMM_NUM_OF_AC] = { 0, 2, 4, 6 }; + UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK, + QID_AC_VI, QID_AC_VO }; + BOOLEAN FlgQueEmpty; + BOOLEAN FlgNullSnd; + BOOLEAN FlgMgmtFrame; + UINT32 Aid, QueId; + INT32 IdAc; /* must be signed, can not use unsigned */ +/* ULONG FlgIrq; */ + +#ifdef UAPSD_SP_ACCURATE + ULONG TimeNow; +#endif /* UAPSD_SP_ACCURATE */ + + + /* sanity check for Service Period of the STATION */ + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("\nuapsd> bAPSDFlagLegacySent = %d!\n", + pEntry->bAPSDFlagLegacySent)); +#endif /* UAPSD_DEBUG */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + /* + reset ContinueTxFailCnt + */ + pEntry->ContinueTxFailCnt = 0; + + /* + WMM Specification V1.1 3.6.1.5 + A Trigger Frame received by the WMM AP from a WMM STA that + already has an USP underway shall not trigger the start of a new + USP. + */ + + /* + Current SP for the STATION is not yet ended so the packet is + normal DATA packet. + */ + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> sorry! SP is not yet closed!\n")); +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_SP_ACCURATE + /* + The interval between the data frame from QSTA and last confirmed + packet from QAP in UAPSD_SP_AUE_Handle() is too large so maybe + we suffer the worse case. + + Currently, if we send any packet with 1Mbps in 2.4GHz and 6Mbps + in 5GHz, no any statistics count for the packet so the SP can + not be closed. + */ + UAPSD_TIME_GET(pAd, TimeNow); + + if ((TimeNow - pEntry->UAPSDTimeStampLast) >= UAPSD_EPT_SP_INT) + { +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> SP period is too large so SP is closed first!" + " (%lu %lu %lu)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", + TimeNow, pEntry->UAPSDTimeStampLast, + (TimeNow - pEntry->UAPSDTimeStampLast))); + + gUAPSD_SP_CloseAbnormalNum ++; +#endif /* UAPSD_DEBUG */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + UAPSD_SP_Close(pAd, pEntry); + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + } + else + { +#endif /* UAPSD_SP_ACCURATE */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return; + +#ifdef UAPSD_SP_ACCURATE + } +#endif /* UAPSD_SP_ACCURATE */ + } + +#ifdef UAPSD_TIMING_RECORD_FUNC + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TRG_RCV); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + +#ifdef UAPSD_DEBUG + if (pEntry->pUAPSDEOSPFrame != NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> EOSP is not NULL!\n")); + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return; + } +#endif /* UAPSD_DEBUG */ + + if (pEntry->MaxSPLength >= 4) + { + /* fatal error, should be 0 ~ 3 so reset it to 0 */ + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> MaxSPLength >= 4 (%d)!\n", pEntry->MaxSPLength)); + pEntry->MaxSPLength = 0; + } + + +#ifdef UAPSD_SP_ACCURATE + /* mark the start time for the SP */ + UAPSD_TIME_GET(pAd, pEntry->UAPSDTimeStampLast); + + + /* check if current rate of the entry is 1Mbps (2.4GHz) or 6Mbps (5GHz) */ +#ifdef RTMP_MAC_PCI + if (((pEntry->HTPhyMode.field.MODE == MODE_CCK) && + (pEntry->HTPhyMode.field.MCS == MCS_0)) || + ((pEntry->HTPhyMode.field.MODE == MODE_OFDM) && + (pEntry->HTPhyMode.field.MCS == MCS_0))) + { + /* + Note: because no any statistics count for CCK, MCS0 so we need + to use old UAPSD DMA mechanism. + */ + pEntry->bAPSDFlagSpRoughUse = 1; + } + else + pEntry->bAPSDFlagSpRoughUse = 0; + + if (pEntry->bAPSDFlagSpRoughUse != 0) + { + /* + Note: because no any indication for UAPSD packet or PS-Poll + packet, we need to use old UAPSD DMA mechanism if part of AC + uses legacy PS mechanism. + */ + if (pEntry->bAPSDAllAC == 0) + pEntry->bAPSDFlagSpRoughUse = 0; + } +#endif /* RTMP_MAC_PCI */ + +#else + + pEntry->bAPSDFlagSpRoughUse = 1; +#endif /* UAPSD_SP_ACCURATE */ + + /* sanity Check for UAPSD condition */ + if (UpOfFrame >= 8) + UpOfFrame = 1; /* shout not be here */ + + /* get the AC ID of incoming packet */ + AcQueId = WMM_UP2AC_MAP[UpOfFrame]; + + /* check whether the AC is trigger-enabled AC */ + if (pEntry->bAPSDCapablePerAC[AcQueId] == 0) + { + /* + WMM Specification V1.1 Page 4 + Trigger Frame: A QoS Data or QoS Null frame from a WMM STA in + Power Save Mode associated with an AC the WMM STA has configured + to be a trigger-enabled AC. + + A QoS Data or QoS Null frame that indicates transition to/from + Power Save Mode is not considered to be a Trigger Frame and the + AP shall not respond with a QoS Null frame. + */ + + /* + ERROR! the AC does not belong to a trigger-enabled AC or + the ACM of the AC is set. + */ + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return; + } + + + /* enqueue U-APSD packets to AC software queues */ + + /* + Protect TxSwQueue0 & McastPsQueue because use them in + interrupt context. + */ +/* RTMP_IRQ_LOCK(FlgIrq); */ + + /* init */ + FlgQueEmpty = TRUE; + TxPktNum = 0; + SpMaxLen = SpLenMap[pEntry->MaxSPLength]; + pAcSwQue = NULL; + pLastAcSwQue = NULL; + pQuedPkt = NULL; + FlgMgmtFrame = 0; + + /* from highest priority AC3 --> AC2 --> AC0 --> lowest priority AC1 */ + for (IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--) + { + AcQueId = AcPriority[IdAc]; + + /* check if the AC is delivery-enable AC */ + if (pEntry->bAPSDDeliverEnabledPerAC[AcQueId] == 0) + continue; + + /* + NOTE: get U-APSD queue pointer here to speed up, do NOT use + pEntry->UAPSDQueue[AcQueId] throughout codes because + compiler will compile it to many assembly codes. + */ + pAcPsQue = &pEntry->UAPSDQueue[AcQueId]; + + /* check if any U-APSD packet is queued for the AC */ + if (pAcPsQue->Head == NULL) + continue; + + /* at least one U-APSD packet exists here */ + + /* get AC software queue */ + QueId = QueIdList[AcQueId]; + pAcSwQue = &pAd->TxSwQueue[QueId]; + + /* put U-APSD packets to the AC software queue */ + while(pAcPsQue->Head) + { + /* check if Max SP Length != 0 */ + if (SpMaxLen != 0) + { + /* + WMM Specification V1.1 3.6.1.7 + At each USP for a WMM STA, the WMM AP shall attempt to + transmit at least one MSDU or MMPDU, but no more than the + value encoded in the Max SP Length field in the QoS Info + Field of a WMM Information Element from delivery-enabled + ACs, that are destined for the WMM STA. + */ + if (TxPktNum >= SpMaxLen) + { + /* + Some queued U-APSD packets still exists so we will + not clear MoreData bit of the packet. + */ + FlgQueEmpty = FALSE; + break; + } + } + + /* count U-APSD packet number */ + TxPktNum ++; + + /* queue last U-APSD packet */ + if (pQuedPkt != NULL) + { + /* + enqueue U-APSD packet to tx software queue + + WMM Specification V1.1 3.6.1.7: + Each buffered frame shall be delivered using the access + parameters of its AC. + */ + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pLastAcSwQue, pQuedPkt); + } + + /* get the U-APSD packet */ + pQuedEntry = RemoveHeadQueue(pAcPsQue); + pQuedPkt = QUEUE_ENTRY_TO_PACKET(pQuedEntry); + if (pQuedPkt != NULL) + { + if (RTMP_GET_PACKET_MGMT_PKT(pQuedPkt) == 1) + FlgMgmtFrame = 1; + + /* + WMM Specification V1.1 3.6.1.7 + The More Data bit (b13) of the directed MSDU or MMPDU + associated with delivery-enabled ACs and destined for + that WMM STA indicates that more frames are buffered for + the delivery-enabled ACs. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, TRUE); + + /* set U-APSD flag & its software queue ID */ + RTMP_SET_PACKET_UAPSD(pQuedPkt, TRUE, QueId); + } + + /* backup its software queue pointer */ + pLastAcSwQue = pAcSwQue; + } + + if (FlgQueEmpty == FALSE) + { + /* FlgQueEmpty will be FALSE only when TxPktNum >= SpMaxLen */ + break; + } + } + + /* + For any mamagement UAPSD frame, we use DMA to do SP check + because no any FIFO statistics for management frame. + */ + if (FlgMgmtFrame) + pEntry->bAPSDFlagSpRoughUse = 1; + + /* + No need to protect EOSP handle code because we will be here + only when last SP is ended. + */ + FlgNullSnd = FALSE; + + if (TxPktNum >= 1) + { + if (FlgQueEmpty == TRUE) + { + /* + No any more queued U-APSD packet so clear More Data bit of + the last frame. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, FALSE); + } + } + + //pEntry->bAPSDFlagSPStart = 1; /* set the SP start flag */ + UAPSD_SP_START(pAd, pEntry); /* set the SP start flag */ + pEntry->bAPSDFlagEOSPOK = 0; + +#ifdef UAPSD_DEBUG +{ + ULONG DebugTimeNow; + + UAPSD_TIME_GET(pAd, DebugTimeNow); + + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> start a SP (Tx Num = %d) (Rough SP = %d) " + "(Has Any Mgmt = %d) (Abnormal = %d) (Time = %lu)\n", + TxPktNum, pEntry->bAPSDFlagSpRoughUse, FlgMgmtFrame, + gUAPSD_SP_CloseAbnormalNum, DebugTimeNow)); +} +#endif /* UAPSD_DEBUG */ + + if (TxPktNum <= 1) + { + /* if no data needs to tx, respond with QosNull for the trigger frame */ + pEntry->pUAPSDEOSPFrame = NULL; + pEntry->UAPSDTxNum = 0; + + if (TxPktNum <= 0) + { + FlgNullSnd = TRUE; + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> No data, send a Qos-Null frame with ESOP bit on and " + "UP=%d to end USP\n", UpOfFrame)); +#endif /* RELEASE_EXCLUDE */ + } + else + { + /* only one packet so send it directly */ + RTMP_SET_PACKET_EOSP(pQuedPkt, TRUE); + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pLastAcSwQue, pQuedPkt); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> Only one packet with UP = %d\n", + RTMP_GET_PACKET_UP(pQuedPkt))); +#endif /* RELEASE_EXCLUDE */ + } + + /* + We will send the QoS Null frame below and we will hande the + QoS Null tx done in RTMPFreeTXDUponTxDmaDone(). + */ + } + else + { + /* more than two U-APSD packets */ + + /* + NOTE: EOSP bit != !MoreData bit because Max SP Length, + we can not use MoreData bit to decide EOSP bit. + */ + + /* + Backup the EOSP frame and + we will transmit the EOSP frame in RTMPFreeTXDUponTxDmaDone(). + */ + RTMP_SET_PACKET_EOSP(pQuedPkt, TRUE); + + pEntry->pUAPSDEOSPFrame = (PQUEUE_ENTRY)pQuedPkt; + pEntry->UAPSDTxNum = TxPktNum-1; /* skip the EOSP frame */ + } + +#ifdef UAPSD_DEBUG + if ((pEntry->pUAPSDEOSPFrame != NULL) && + (RTMP_GET_PACKET_MGMT_PKT(pEntry->pUAPSDEOSPFrame) == 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> The EOSP frame is a management frame.\n")); + } +#endif /* UAPSD_DEBUG */ + + +#ifdef UAPSD_SP_ACCURATE + /* count for legacy PS packet */ + + /* + Note: A worse case for mix mode (UAPSD + legacy PS): + PS-Poll --> legacy ps packet --> trigger frame --> QoS Null frame + (QSTA) (QAP) (QSTA) (QAP) + + where statistics handler is NICUpdateFifoStaCounters(). + + If we receive the trigger frame before the legacy ps packet is sent to + the air, when we call statistics handler in tx done, it maybe the + legacy ps statistics, not the QoS Null frame statistics, so we will + do UAPSD counting fail. + + We need to count the legacy PS here if it is not yet sent to the air. + */ + + /* + Note: in addition, only one legacy PS need to count because one legacy + packet for one PS-Poll packet; if we receive a trigger frame from a + station, it means that only one legacy ps packet is possible not sent + to the air, it is impossible more than 2 legacy packets are not yet + sent to the air. + */ + if ((pEntry->bAPSDFlagSpRoughUse == 0) && + (pEntry->bAPSDFlagLegacySent != 0)) + { + pEntry->UAPSDTxNum ++; + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> A legacy PS is sent! UAPSDTxNum = %d\n", + pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + } +#endif /* UAPSD_SP_ACCURATE */ + + + /* clear corresponding TIM bit */ + + /* get its AID for the station */ + Aid = pEntry->Aid; + + if ((pEntry->bAPSDAllAC == 1) && (FlgQueEmpty == 1)) + { + /* all AC are U-APSD and no any U-APSD packet is queued, set TIM */ + +#ifdef CONFIG_AP_SUPPORT + /* clear TIM bit */ + if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE)) + { + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* reset idle timeout here whenever a trigger frame is received */ + pEntry->UAPSDQIdleCount = 0; + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + + /* check if NULL Frame is needed to be transmitted */ + + /* it will be crashed, when spin locked in kernel 2.6 */ + if (FlgNullSnd) + { + /* bQosNull = bEOSP = TRUE = 1 */ + + /* + Use management queue to tx QoS Null frame to avoid delay so + us_of_frame is not used. + */ + RtmpEnqueueNullFrame(pAd, pEntry->Addr, pEntry->CurrTxRate, + Aid, pEntry->apidx, TRUE, TRUE, UpOfFrame); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> end a SP by a QoS Null frame!\n")); +#endif /* UAPSD_DEBUG */ + } + +#ifdef UAPSD_TIMING_RECORD_FUNC + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_MOVE2TX); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} + + + +#endif /* UAPSD_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/vht.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/vht.c new file mode 100644 index 000000000..4a72e150c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/vht.c @@ -0,0 +1,775 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + +/* some buggy BCM clients can not work with 80MHz */ +#define BAD_VHT80_WORKAROUND + +#ifdef BAD_VHT80_WORKAROUND +static const UCHAR BAD_VHT80_OUI[][3] = { + {0x3C, 0xFA, 0x43}, // Huawei P9 + {0x7C, 0x11, 0xCB}, // Huawei Honor 8 + + /* iPhone 6*/ + {0x74, 0x1B, 0xB2}, + {0x84, 0x89, 0xAD}, + {0xD8, 0x1D, 0x72}, + {0x60, 0xF8, 0x1D}, + {0x60, 0xA3, 0x7D}, + {0x88, 0x66, 0xA5}, + {0x50, 0xA6, 0x7F}, + {0x6C, 0x72, 0xE7}, + {0x2C, 0x61, 0xF6}, + {0x90, 0x8D, 0x6C}, + {0x90, 0x4F, 0xDA}, + + /* MACBOOK */ + {0xAC, 0xBC, 0x32}, + {0xB8, 0xE8, 0x56}, + {0x08, 0x6D, 0x41}, + {0x18, 0x65, 0x90}, + {0xA8, 0x66, 0x7F}, + {0x98, 0x01, 0xA7}, + + /* HUAWEI */ + {0xF0, 0x43, 0x47}, + {0xA8, 0xC8, 0x3A}, + {0x10, 0xB1, 0xF8}, + {0x5C, 0xC3, 0x07}, + {0x0C, 0x8F, 0xFF}, + + /* ONEPLUS */ + {0x94, 0x0E, 0x6B}, +}; +#endif /* BAD_VHT80_WORKAROUND */ + +struct vht_ch_layout{ + UCHAR ch_low_bnd; + UCHAR ch_up_bnd; + UCHAR cent_freq_idx; +}; + +static struct vht_ch_layout vht_ch_80M[]={ + {36, 48, 42}, + {52, 64, 58}, + {100,112, 106}, + {116, 128, 122}, + {132, 144, 138}, + {149, 161, 155}, + {0, 0 ,0}, +}; + + + +#ifdef DBG +VOID dump_vht_cap(RTMP_ADAPTER *pAd, VHT_CAP_IE *vht_ie) +{ + VHT_CAP_INFO *vht_cap = &vht_ie->vht_cap; + VHT_MCS_SET *vht_mcs = &vht_ie->mcs_set; + + DBGPRINT(RT_DEBUG_OFF, ("Dump VHT_CAP IE\n")); + hex_dump("VHT CAP IE Raw Data", (UCHAR *)vht_ie, sizeof(VHT_CAP_IE)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Capabilities Info Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tMaximum MPDU Length=%d\n", vht_cap->max_mpdu_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tSupported Channel Width=%d\n", vht_cap->ch_width)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxLDPC=%d\n", vht_cap->rx_ldpc)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI_80M=%d\n", vht_cap->sgi_80M)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI_160M=%d\n", vht_cap->sgi_160M)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxSTBC=%d\n", vht_cap->tx_stbc)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxSTBC=%d\n", vht_cap->rx_stbc)); + DBGPRINT(RT_DEBUG_OFF, ("\tSU BeamformerCap=%d\n", vht_cap->bfer_cap_su)); + DBGPRINT(RT_DEBUG_OFF, ("\tSU BeamformeeCap=%d\n", vht_cap->bfee_cap_su)); + DBGPRINT(RT_DEBUG_OFF, ("\tCompressedSteeringNumOfBeamformerAnt=%d\n", vht_cap->cmp_st_num_bfer)); + DBGPRINT(RT_DEBUG_OFF, ("\tNumber of Sounding Dimensions=%d\n", vht_cap->num_snd_dimension)); + DBGPRINT(RT_DEBUG_OFF, ("\tMU BeamformerCap=%d\n", vht_cap->bfer_cap_mu)); + DBGPRINT(RT_DEBUG_OFF, ("\tMU BeamformeeCap=%d\n", vht_cap->bfee_cap_mu)); + DBGPRINT(RT_DEBUG_OFF, ("\tVHT TXOP PS=%d\n", vht_cap->vht_txop_ps)); + DBGPRINT(RT_DEBUG_OFF, ("\t+HTC-VHT Capable=%d\n", vht_cap->htc_vht_cap)); + DBGPRINT(RT_DEBUG_OFF, ("\tMaximum A-MPDU Length Exponent=%d\n", vht_cap->max_ampdu_exp)); + DBGPRINT(RT_DEBUG_OFF, ("\tVHT LinkAdaptation Capable=%d\n", vht_cap->vht_link_adapt)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Supported MCS Set Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRx Highest SupDataRate=%d\n", vht_mcs->rx_high_rate)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_1SS=%d\n", vht_mcs->rx_mcs_map.mcs_ss1)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_2SS=%d\n", vht_mcs->rx_mcs_map.mcs_ss2)); + DBGPRINT(RT_DEBUG_OFF, ("\tTx Highest SupDataRate=%d\n", vht_mcs->tx_high_rate)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxMCS Map_1SS=%d\n", vht_mcs->tx_mcs_map.mcs_ss1)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxMCS Map_2SS=%d\n", vht_mcs->tx_mcs_map.mcs_ss2)); +} + + +VOID dump_vht_op(RTMP_ADAPTER *pAd, VHT_OP_IE *vht_ie) +{ + VHT_OP_INFO *vht_op = &vht_ie->vht_op_info; + VHT_MCS_MAP *vht_mcs = &vht_ie->basic_mcs_set; + + DBGPRINT(RT_DEBUG_OFF, ("Dump VHT_OP IE\n")); + hex_dump("VHT OP IE Raw Data", (UCHAR *)vht_ie, sizeof(VHT_OP_IE)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Operation Info Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelWidth=%d\n", vht_op->ch_width)); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelCenterFrequency Seg 1=%d\n", vht_op->center_freq_1)); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelCenterFrequency Seg 1=%d\n", vht_op->center_freq_2)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Basic MCS Set Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_1SS=%d\n", vht_mcs->mcs_ss1)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_2SS=%d\n", vht_mcs->mcs_ss2)); +} +#endif + +#ifdef VHT_TXBF_SUPPORT +VOID trigger_vht_ndpa(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *entry) +{ + UCHAR *buf; + VHT_NDPA_FRAME *vht_ndpa; + struct wifi_dev *wdev = entry->wdev; + UINT frm_len, sta_cnt; + SNDING_STA_INFO *sta_info; + + if (MlmeAllocateMemory(pAd, &buf) != NDIS_STATUS_SUCCESS) + return; + + NdisZeroMemory(buf, MGMT_DMA_BUFFER_SIZE); + + vht_ndpa = (VHT_NDPA_FRAME *)buf; + frm_len = sizeof(VHT_NDPA_FRAME); + vht_ndpa->fc.Type = FC_TYPE_CNTL; + vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA; + COPY_MAC_ADDR(vht_ndpa->ra, entry->Addr); + COPY_MAC_ADDR(vht_ndpa->ta, wdev->if_addr); + + /* Currnetly we only support 1 STA for a VHT DNPA */ + sta_info = vht_ndpa->sta_info; + for (sta_cnt = 0; sta_cnt < 1; sta_cnt++) { + sta_info->aid12 = entry->Aid; + sta_info->fb_type = SNDING_FB_SU; + sta_info->nc_idx = 0; + vht_ndpa->token.token_num = entry->snd_dialog_token; + frm_len += sizeof(SNDING_STA_INFO); + sta_info++; + if (frm_len >= (MGMT_DMA_BUFFER_SIZE - sizeof(SNDING_STA_INFO))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): len(%d) too large!cnt=%d\n", + __FUNCTION__, frm_len, sta_cnt)); + break; + } + } + if (entry->snd_dialog_token & 0xc0) + entry->snd_dialog_token = 0; + else + entry->snd_dialog_token++; + + vht_ndpa->duration = pAd->CommonCfg.Dsifs + + RTMPCalcDuration(pAd, pAd->CommonCfg.MlmeRate, frm_len); + + //DBGPRINT(RT_DEBUG_OFF, ("Send VHT NDPA Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + // PRINT_MAC(entry->Addr))); + //hex_dump("VHT NDPA Frame", buf, frm_len); + MiniportMMRequest(pAd, 0, buf, frm_len); + MlmeFreeMemory(pAd, buf); + +#ifdef SOFT_SOUNDING + if (1) { + HEADER_802_11 *pNullFr; + UCHAR *qos_p; + UCHAR NullFrame[48]; + + NdisZeroMemory(NullFrame, 48); + pNullFr = (PHEADER_802_11)&NullFrame[0]; + frm_len = sizeof(HEADER_802_11); + + pNullFr->FC.Type = FC_TYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + pNullFr->FC.FrDs = 1; + pNullFr->FC.ToDs = 0; + COPY_MAC_ADDR(pNullFr->Addr1, entry->Addr); + COPY_MAC_ADDR(pNullFr->Addr2, wdev->if_addr); + COPY_MAC_ADDR(pNullFr->Addr3, wdev->bssid); + + qos_p = ((UCHAR *)pNullFr) + frm_len; + qos_p[0] = 0; + qos_p[1] = 0; + frm_len += 2; + + entry->snd_reqired = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("Send sounding QoSNULL Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(entry->Addr))); + + hex_dump("VHT NDP Frame(QoSNull)", NullFrame, frm_len); + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, frm_len); + } +#endif /* SOFT_SOUNDING */ + +} +#endif /* VHT_TXBF_SUPPORT */ + + +/* + Get BBP Channel Index by RF channel info + return value: 0~3 +*/ +UCHAR vht_prim_ch_idx(UCHAR vht_cent_ch, UCHAR prim_ch) +{ + INT idx = 0; + UCHAR bbp_idx = 0; + + if (vht_cent_ch == prim_ch) + goto done; + + while (vht_ch_80M[idx].ch_up_bnd != 0) + { + if (vht_cent_ch == vht_ch_80M[idx].cent_freq_idx) + { + if (prim_ch == vht_ch_80M[idx].ch_up_bnd) + bbp_idx = 3; + else if (prim_ch == vht_ch_80M[idx].ch_low_bnd) + bbp_idx = 0; + else { + bbp_idx = prim_ch > vht_cent_ch ? 2 : 1; + } + break; + } + idx++; + } + +done: + DBGPRINT(RT_DEBUG_INFO, ("%s():(VhtCentCh=%d, PrimCh=%d) =>BbpChIdx=%d\n", + __FUNCTION__, vht_cent_ch, prim_ch, bbp_idx)); + return bbp_idx; +} + + +/* + Currently we only consider about VHT 80MHz! +*/ +UCHAR vht_cent_ch_freq(RTMP_ADAPTER *pAd, UCHAR prim_ch) +{ + INT idx = 0, ch_idx = 0; + BOOLEAN ch_support_bw_80 = FALSE; + + if (pAd->CommonCfg.vht_bw < VHT_BW_80 || prim_ch < 36) + { + pAd->CommonCfg.vht_cent_ch = 0; + pAd->CommonCfg.vht_cent_ch2 = 0; + return prim_ch; + } + +#ifdef RT_CFG80211_SUPPORT +#else + /* + sanity check , if this channel has no BW80 capability, use first channel in channel list + ex: when CH144 is not availble , group CH 132~140 won't have BW80 cap , shouldn't be used. + */ + for ( ch_idx = 0; ch_idx < pAd->ChannelListNum; ch_idx++) + { + if ((pAd->ChannelList[ch_idx].Channel == prim_ch) && (pAd->ChannelList[ch_idx].Flags & CHANNEL_80M_CAP)) + ch_support_bw_80 = TRUE; + } + + if(ch_support_bw_80 == FALSE) + { + pAd->CommonCfg.Channel = FirstChannel(pAd); + DBGPRINT(RT_DEBUG_OFF, ("vht_cent_ch_freq: channel(%d) don't have BW80 capability, use first channel in channel list=%d \n" + , prim_ch, pAd->CommonCfg.Channel)); + prim_ch = FirstChannel(pAd); + } +#endif /* RT_CFG80211_SUPPORT */ + + /* choose cent_freq by prim_ch */ + + while (vht_ch_80M[idx].ch_up_bnd != 0) + { + if (prim_ch >= vht_ch_80M[idx].ch_low_bnd && + prim_ch <= vht_ch_80M[idx].ch_up_bnd) + { + pAd->CommonCfg.vht_cent_ch = vht_ch_80M[idx].cent_freq_idx; + return vht_ch_80M[idx].cent_freq_idx; + } + idx++; + } + + return prim_ch; +} + + +INT vht_mode_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, VHT_CAP_IE *cap, VHT_OP_IE *op) +{ + struct wifi_dev *wdev; + INT vht_bw = VHT_BW_80; + + pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + pAd->MacTab.fAnyStationNonGF = TRUE; + + wdev = pEntry->wdev; + if (wdev) + vht_bw = wdev->DesiredHtPhyInfo.vht_bw; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: DesiredHtPhyInfo->vht_bw=%d, ch_width=%d\n", __FUNCTION__, + vht_bw, cap->vht_cap.ch_width)); + + if (pEntry->MaxHTPhyMode.field.BW == BW_40) + { + if (vht_bw == VHT_BW_80) + { + if (cap->vht_cap.ch_width == 0) + { + if (op != NULL) + { + if (op->vht_op_info.ch_width != 0) + { + pEntry->MaxHTPhyMode.field.BW = BW_80; + } + } + else + { + /* can not know peer capability, use it's maximum capability */ + pEntry->MaxHTPhyMode.field.BW = BW_80; +#ifdef BAD_VHT80_WORKAROUND + /* skip DB region */ + if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) != 7) + { + INT i; + + /* some buggy BCM clients can not work with 80MHz */ + for (i = 0; i < sizeof(BAD_VHT80_OUI) / 3; i++) + { + if (NdisEqualMemory(pEntry->Addr, &BAD_VHT80_OUI[i][0], 3)) + { + pEntry->MaxHTPhyMode.field.BW = BW_40; + printk("%s: drop buggy OUI: %02X-%02X-%02X to VHT40!\n", + "mt7612", + BAD_VHT80_OUI[i][0], + BAD_VHT80_OUI[i][1], + BAD_VHT80_OUI[i][2]); + break; + } + } + } +#endif /* BAD_VHT80_WORKAROUND */ + } + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_80; + } + } + } + + pEntry->MaxHTPhyMode.field.STBC = (pAd->CommonCfg.vht_stbc && cap->vht_cap.rx_stbc > 1) ? 1 : 0; + + if (pEntry->MaxHTPhyMode.field.BW == BW_80) + { + pEntry->MaxHTPhyMode.field.ShortGI = (pAd->CommonCfg.vht_sgi_80 && cap->vht_cap.sgi_80M) ? 1 : 0; + } + + return TRUE; +} + + +INT get_vht_op_ch_width(RTMP_ADAPTER *pAd) +{ + + return TRUE; +} + + +/******************************************************************** + Procedures for 802.11 AC Information elements +********************************************************************/ +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_quiet_channel(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0; + + + return len; +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_ext_bss_load(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0; + + + return len; +} + + + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_ext_pwr_constraint(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0; + + + return len; +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_vht_txpwr_envelope(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0, pwr_cnt; + VHT_TXPWR_ENV_IE txpwr_env; + + NdisZeroMemory(&txpwr_env, sizeof(txpwr_env)); + + if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + pwr_cnt = 2; + } else { + if (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 1) + pwr_cnt = 1; + else + pwr_cnt = 0; + } + txpwr_env.tx_pwr_info.max_tx_pwr_cnt = pwr_cnt; + txpwr_env.tx_pwr_info.max_tx_pwr_interpretation = TX_PWR_INTERPRET_EIRP; + +// TODO: fixme, we need the real tx_pwr value for each port. + for (len = 0; len < pwr_cnt; len++) + txpwr_env.tx_pwr_bw[len] = 15; + + len = 2 + pwr_cnt; + NdisMoveMemory(buf, &txpwr_env, len); + + return len; +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, (Re)AssocResp, ProbResp frames +*/ +INT build_vht_op_ie(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + VHT_OP_IE vht_op; + UCHAR cent_ch; +#ifdef RT_BIG_ENDIAN + UINT16 tmp; +#endif /* RT_BIG_ENDIAN */ + + NdisZeroMemory((UCHAR *)&vht_op, sizeof(VHT_OP_IE)); + vht_op.vht_op_info.ch_width = (pAd->CommonCfg.vht_bw == VHT_BW_80 ? 1: 0); + +#ifdef CONFIG_AP_SUPPORT + if (pAd->CommonCfg.Channel > 14 && + (pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) + cent_ch = vht_cent_ch_freq(pAd, pAd->Dot11_H.org_ch); + else +#endif /* CONFIG_AP_SUPPORT */ + cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + + switch (vht_op.vht_op_info.ch_width) + { + case 0: + vht_op.vht_op_info.center_freq_1 = 0; + vht_op.vht_op_info.center_freq_2 = 0; + break; + case 1: + case 2: + vht_op.vht_op_info.center_freq_1 = cent_ch; + vht_op.vht_op_info.center_freq_2 = 0; + break; + case 3: + vht_op.vht_op_info.center_freq_1 = cent_ch; + vht_op.vht_op_info.center_freq_2 = pAd->CommonCfg.vht_cent_ch2; + break; + } + + vht_op.basic_mcs_set.mcs_ss1 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss2 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss3 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss4 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss5 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss6 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss7 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss8 = VHT_MCS_CAP_NA; + switch (pAd->CommonCfg.RxStream) + { + case 2: +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + vht_op.basic_mcs_set.mcs_ss2 = (((pAd->CommonCfg.vht_bw == VHT_BW_2040) + && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20)) ? VHT_MCS_CAP_8 : VHT_MCS_CAP_9); + } else +#endif /* MT76x2 */ + vht_op.basic_mcs_set.mcs_ss2 = VHT_MCS_CAP_7; + case 1: +#if defined(MT76x0) || defined(MT76x2) + if (IS_MT76x0(pAd) || IS_MT76x2(pAd)) + vht_op.basic_mcs_set.mcs_ss1 = (((pAd->CommonCfg.vht_bw == VHT_BW_2040) + && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20)) ? VHT_MCS_CAP_8 : VHT_MCS_CAP_9); + else +#endif + vht_op.basic_mcs_set.mcs_ss1 = VHT_MCS_CAP_7; + break; + } + +#ifdef RT_BIG_ENDIAN + //SWAP16((UINT16)vht_op.basic_mcs_set); + NdisCopyMemory(&tmp,&vht_op.basic_mcs_set, 2); + tmp=SWAP16(tmp); + NdisCopyMemory(&vht_op.basic_mcs_set,&tmp, 2); +#endif /* RT_BIG_ENDIAN */ + NdisMoveMemory((UCHAR *)buf, (UCHAR *)&vht_op, sizeof(VHT_OP_IE)); + + return sizeof(VHT_OP_IE); +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, (Re)AssocReq, (Re)AssocResp, ProbReq/Resp frames +*/ +INT build_vht_cap_ie(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + VHT_CAP_IE vht_cap_ie; + INT rx_nss, tx_nss, mcs_cap; +#ifdef RT_BIG_ENDIAN + UINT32 tmp_1; + UINT64 tmp_2; +#endif /*RT_BIG_ENDIAN*/ + + NdisZeroMemory((UCHAR *)&vht_cap_ie, sizeof(VHT_CAP_IE)); + vht_cap_ie.vht_cap.max_mpdu_len = 0; // TODO: Ask Jerry about hardware limitation. + vht_cap_ie.vht_cap.ch_width = 0; /* not support 160 or 80 + 80 MHz */ + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) + vht_cap_ie.vht_cap.rx_ldpc = 1; + else + vht_cap_ie.vht_cap.rx_ldpc = 0; + + vht_cap_ie.vht_cap.sgi_80M = pAd->CommonCfg.vht_sgi_80; + vht_cap_ie.vht_cap.htc_vht_cap = 1; + vht_cap_ie.vht_cap.max_ampdu_exp = 3; // TODO: Ask Jerry about the hardware limitation, currently set as 64K + + vht_cap_ie.vht_cap.tx_stbc = 0; + vht_cap_ie.vht_cap.rx_stbc = 0; + if (pAd->CommonCfg.vht_stbc) + { + if (pAd->CommonCfg.TxStream >= 2) + vht_cap_ie.vht_cap.tx_stbc = 1; + else + vht_cap_ie.vht_cap.tx_stbc = 0; + + if (pAd->CommonCfg.RxStream >= 1) + vht_cap_ie.vht_cap.rx_stbc = 1; // TODO: is it depends on the number of our antennas? + else + vht_cap_ie.vht_cap.rx_stbc = 0; + } + +#ifdef VHT_TXBF_SUPPORT + + if ((pAd->chipCap.FlgHwTxBfCap) && (pAd->BeaconSndDimensionFlag ==0)) + { + vht_cap_ie.vht_cap.num_snd_dimension = pAd->CommonCfg.vht_cap_ie.vht_cap.num_snd_dimension; + vht_cap_ie.vht_cap.cmp_st_num_bfer= pAd->CommonCfg.vht_cap_ie.vht_cap.cmp_st_num_bfer; + vht_cap_ie.vht_cap.bfee_cap_su=pAd->CommonCfg.vht_cap_ie.vht_cap.bfee_cap_su; + vht_cap_ie.vht_cap.bfer_cap_su=pAd->CommonCfg.vht_cap_ie.vht_cap.bfer_cap_su; + } + pAd->BeaconSndDimensionFlag =0; +#endif + + vht_cap_ie.vht_cap.tx_ant_consistency = 1; + vht_cap_ie.vht_cap.rx_ant_consistency = 1; + + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss2 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss3 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss4 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss5 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss6 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss7 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss8 = VHT_MCS_CAP_NA; + + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss2 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss3 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss4 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss5 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss6 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss7 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss8 = VHT_MCS_CAP_NA; + + mcs_cap = pAd->chipCap.max_vht_mcs; + + rx_nss = pAd->CommonCfg.RxStream; + tx_nss = pAd->CommonCfg.TxStream; +#ifdef WFA_VHT_PF + if ((pAd->CommonCfg.vht_nss_cap > 0) && + (pAd->CommonCfg.vht_nss_cap < pAd->CommonCfg.RxStream)) + rx_nss = pAd->CommonCfg.vht_nss_cap; + + if ((pAd->CommonCfg.vht_nss_cap > 0) && + (pAd->CommonCfg.vht_nss_cap < pAd->CommonCfg.TxStream)) + tx_nss = pAd->CommonCfg.vht_nss_cap; + + if (pAd->CommonCfg.vht_mcs_cap chipCap.max_vht_mcs) + mcs_cap = pAd->CommonCfg.vht_mcs_cap; +#endif /* WFA_VHT_PF */ + + switch (rx_nss) + { + case 1: + vht_cap_ie.mcs_set.rx_high_rate = 292; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = mcs_cap; + break; + case 2: + if (mcs_cap == VHT_MCS_CAP_9) + vht_cap_ie.mcs_set.rx_high_rate = 780; + else + vht_cap_ie.mcs_set.rx_high_rate = 585; + + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = mcs_cap; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss2 = mcs_cap; + break; + default: + vht_cap_ie.mcs_set.rx_high_rate = 0; + break; + } + + switch (tx_nss) + { + case 1: + vht_cap_ie.mcs_set.tx_high_rate = 292; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = mcs_cap; + break; + case 2: + if (mcs_cap == VHT_MCS_CAP_9) + vht_cap_ie.mcs_set.tx_high_rate = 780; + else + vht_cap_ie.mcs_set.tx_high_rate = 585; + + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = mcs_cap; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss2 = mcs_cap; + break; + default: + vht_cap_ie.mcs_set.tx_high_rate = 0; + break; + } + +#ifdef RT_BIG_ENDIAN + NdisCopyMemory(&tmp_1,&vht_cap_ie.vht_cap, 4); + tmp_1 = SWAP32(tmp_1); + NdisCopyMemory(&vht_cap_ie.vht_cap,&tmp_1, 4); + + NdisCopyMemory(&tmp_2,&vht_cap_ie.mcs_set, 8); + tmp_2=SWAP64(tmp_2); + NdisCopyMemory(&vht_cap_ie.mcs_set,&tmp_2, 8); + + //hex_dump("&vht_cap_ie", &vht_cap_ie, sizeof(VHT_CAP_IE)); + //SWAP32((UINT32)vht_cap_ie.vht_cap); + //SWAP32((UINT32)vht_cap_ie.mcs_set); +#endif /* RT_BIG_ENDIAN */ + + NdisMoveMemory(buf, (UCHAR *)&vht_cap_ie, sizeof(VHT_CAP_IE)); + + return sizeof(VHT_CAP_IE); +} + + +INT build_vht_ies(RTMP_ADAPTER *pAd, UCHAR *buf, UCHAR frm) +{ + INT len = 0; + EID_STRUCT eid_hdr; + + + eid_hdr.Eid = IE_VHT_CAP; + eid_hdr.Len = sizeof(VHT_CAP_IE); + NdisMoveMemory(buf, (UCHAR *)&eid_hdr, 2); + len = 2; + + len += build_vht_cap_ie(pAd, (UCHAR *)(buf + len)); + if (frm == SUBTYPE_BEACON || frm == SUBTYPE_PROBE_RSP || + frm == SUBTYPE_ASSOC_RSP || frm == SUBTYPE_REASSOC_RSP) + { + eid_hdr.Eid = IE_VHT_OP; + eid_hdr.Len = sizeof(VHT_OP_IE); + NdisMoveMemory((UCHAR *)(buf + len), (UCHAR *)&eid_hdr, 2); + len +=2; + + len += build_vht_op_ie(pAd, (UCHAR *)(buf + len)); + } + + return len; +} + +BOOLEAN vht80_channel_group( RTMP_ADAPTER *pAd, UCHAR channel) +{ + INT idx = 0; + + if (channel <= 14) + return FALSE; + + while (vht_ch_80M[idx].ch_up_bnd != 0) + { + if (channel >= vht_ch_80M[idx].ch_low_bnd && + channel <= vht_ch_80M[idx].ch_up_bnd) + { + if ( (pAd->CommonCfg.RDDurRegion == JAP || + pAd->CommonCfg.RDDurRegion == JAP_W53 || + pAd->CommonCfg.RDDurRegion == JAP_W56 || + pAd->CommonCfg.RDDurRegion == CE + ) && + vht_ch_80M[idx].cent_freq_idx == 138) + { + idx++; + continue; + } + + return TRUE; + } + idx++; + } + + return FALSE; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi.c new file mode 100644 index 000000000..8507ba3c2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi.c @@ -0,0 +1,1329 @@ +/* + *************************************************************************** + * 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: + wapi.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Albert 2008-4-3 Supoort WAPI protocol +*/ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + +#ifdef WAPI_SUPPORT + +#include "rt_config.h" + +/* WAPI AKM OUI */ +UCHAR OUI_WAI_CERT_AKM[4] = {0x00, 0x14, 0x72, 0x01}; +UCHAR OUI_WAI_PSK_AKM[4] = {0x00, 0x14, 0x72, 0x02}; + +/* WAPI CIPHER OUI */ +UCHAR OUI_WPI_CIPHER_SMS4[4] = {0x00, 0x14, 0x72, 0x01}; + +UCHAR WAPI_TYPE[] = {0x88, 0xb4}; + +/* IV default value */ +UCHAR AE_BCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c}; +UCHAR ASUE_UCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c}; +UCHAR AE_UCAST_PN[LEN_WAPI_TSC] = {0x37, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c}; + +BUILD_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec); +BUILD_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec); + +static void kd_hmac_sha256( + unsigned char *key, + unsigned int key_len, + unsigned char *text, + unsigned int text_len, + unsigned char *output, + unsigned int output_len) +{ + int i; + + for (i = 0; output_len/SHA256_DIGEST_SIZE; i++, output_len -= SHA256_DIGEST_SIZE) + { + RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], SHA256_DIGEST_SIZE); + text = &output[i*SHA256_DIGEST_SIZE]; + text_len = SHA256_DIGEST_SIZE; + } + + if (output_len > 0) + RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], output_len); + +} + + +/* + ======================================================================== + + Routine Description: + Build WAPI IE in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPInsertWapiIe( + IN UINT AuthMode, + IN UINT WepStatus, + OUT PUCHAR pWIe, + OUT UCHAR *w_len) +{ + WAPIIE *pWapiHdr = (WAPIIE*)pWIe; + WAPIIE_UCAST *pWIE_ucast; + WAPIIE_MCAST *pWIE_mcast; + + *w_len = 0; + + /* Assign the verson as 1 */ + pWapiHdr->version = 1; + + /* Set the AKM count and suite */ + pWapiHdr->acount = 1; + switch (AuthMode) + { + case Ndis802_11AuthModeWAICERT: + NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_CERT_AKM, 4); + break; + + case Ndis802_11AuthModeWAIPSK: + NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_PSK_AKM, 4); + break; + } + + /* swap for big-endian platform */ + pWapiHdr->version = cpu2le16(pWapiHdr->version); + pWapiHdr->acount = cpu2le16(pWapiHdr->acount); + + /* update current length */ + (*w_len) += sizeof(WAPIIE); + + /* Set the unicast cipher and count */ + pWIE_ucast = (WAPIIE_UCAST*)(pWIe + (*w_len)); + pWIE_ucast->ucount = 1; + NdisMoveMemory(pWIE_ucast->ucast[0].oui, OUI_WPI_CIPHER_SMS4, 4); + + /* swap for big-endian platform */ + pWIE_ucast->ucount = cpu2le16(pWIE_ucast->ucount); + + /* update current length */ + (*w_len) += sizeof(WAPIIE_UCAST); + + /* Set the multicast cipher and capability */ + pWIE_mcast = (WAPIIE_MCAST*)(pWIe + (*w_len)); + NdisMoveMemory(pWIE_mcast->mcast, OUI_WPI_CIPHER_SMS4, 4); + pWIE_mcast->capability = 0; /* Todo AlbertY - support pre-authentication */ + + /* update current length */ + (*w_len) += sizeof(WAPIIE_MCAST); + +} + +/* + ========================================================================== + Description: + Check whether the received frame is WAPI frame. + + Arguments: + pAd - pointer to our pAdapter context + pData - the received frame + DataByteCount - the received frame's length + + Return: + TRUE - This frame is WAPI frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckWAIframe( + IN PUCHAR pData, + IN ULONG DataByteCount) +{ + if(DataByteCount < (LENGTH_802_1_H + LENGTH_WAI_H)) + return FALSE; + + + /* Skip LLC header */ + if (NdisEqualMemory(SNAP_802_1H, pData, 6)) + { + pData += 6; + } + /* Skip 2-bytes EAPoL type */ + if (NdisEqualMemory(WAPI_TYPE, pData, 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Receive a WAI frame \n")); + pData += 2; + } + else + return FALSE; + + return TRUE; +} + + +/* + ========================================================================== + Description: + Check whether the cipher is SMS4. + + Arguments: + pAd - pointer to our pAdapter context + apidx - interface index + + Return: + TRUE - The cipher is SMS4 + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPIsWapiCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + NDIS_802_11_ENCRYPTION_STATUS cipher_mode = Ndis802_11EncryptionDisabled; + + /* Currently, WAPI only support MBSS */ + if (apidx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < MAX_MBSSID_NUM(pAd)) + cipher_mode = pAd->ApCfg.MBSSID[apidx].wdev.WepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + cipher_mode = pAd->StaCfg.wdev.WepStatus; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (cipher_mode == Ndis802_11EncryptionSMS4Enabled) + return TRUE; + + return FALSE; +} + +/* + ========================================================================== + Description: + Insert the WPI-SMS4 IV header + + +-------+------+-------------+ + | KeyId | resv | sequence PN | + +-------+------+-------------+ + + Arguments: + + Return: + + ========================================================================== +*/ +VOID RTMPConstructWPIIVHdr( + IN UCHAR key_id, + IN UCHAR *tx_iv, + OUT UCHAR *iv_hdr) +{ + iv_hdr[0] = key_id; + iv_hdr[1] = 0x00; + + NdisMoveMemory(&iv_hdr[2], tx_iv, LEN_WAPI_TSC); +} + +VOID RTMPDeriveWapiGTK( + IN PUCHAR nmk, + OUT PUCHAR gtk_ptr) +{ + const char group_context[100] = "multicast or station key expansion for station unicast and multicast and broadcast"; + + NdisZeroMemory(gtk_ptr, 32); + kd_hmac_sha256(nmk, + 16, + (UCHAR *)group_context, + strlen(group_context), + gtk_ptr, + 32); +} + +VOID RT_SMS4_TEST( + IN UINT8 test) +{ + CIPHER_KEY CipherKey; + UINT16 data_len; + UINT8 rcvd_data[50]; + UINT8 mac_hdr_qos[] = {0x88, 0x42, 0x00, 0x00, 0x08, 0xda, 0x75, 0x84, + 0xd0, 0xcc, 0x27, 0xe8, 0x72, 0xaa, 0x2c, 0xb9, + 0x6b, 0xbb, 0xea, 0x35, 0xa4, 0x20, 0x1e, 0xd2, + 0xcf, 0x14}; + + UINT8 payload_qos[] = {0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}; + UINT8 pn[] = {0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, + 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89}; + UINT8 key[] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe, + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, + 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe}; + + RTMPSoftEncryptSMS4(mac_hdr_qos, + payload_qos, + 1, + 1, + key, + pn); + + hex_dump("encrypted payload", payload_qos, 17); + + NdisZeroMemory(&CipherKey, sizeof(CIPHER_KEY)); + NdisMoveMemory(CipherKey.Key, key, 16); + NdisMoveMemory(CipherKey.TxMic, &key[16], 8); + NdisMoveMemory(CipherKey.RxMic, &key[24], 8); + CipherKey.KeyLen = 16; + + + NdisZeroMemory(rcvd_data, 50); + rcvd_data[0] = 1; + data_len = 2; + NdisMoveMemory(&rcvd_data[data_len], pn, 16); + data_len += 16; + NdisMoveMemory(&rcvd_data[data_len], payload_qos, 17); + data_len += 17; + + + if (RTMPSoftDecryptSMS4(mac_hdr_qos, + FALSE, + &CipherKey, + rcvd_data, + &data_len) == 0) + hex_dump("decrypted payload", rcvd_data, data_len); + else + printk("decrypted fail\n"); +} + +/* + ======================================================================== + + Routine Description: + In kernel mode read parameters from file + + Arguments: + src the location of the file. + dest put the parameters to the destination. + Length size to read. + + Return Value: + None + + Note: + + ======================================================================== +*/ +void rtmp_read_wapi_parms_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer) +{ + UINT32 ip_addr; +#ifdef CONFIG_AP_SUPPORT + INT apidx = 0; +#endif /* CONFIG_AP_SUPPORT */ + STRING tok_str[32]; + INT idx; + + PCOMMON_WAPI_INFO pInfo = &pAd->CommonCfg.comm_wapi_info; + + /* wapi interface name */ + if (RTMPGetKeyParameter("Wapiifname", tmpbuf, 32, buffer, TRUE)) + { + if (strlen(tmpbuf) > 0) + { + NdisMoveMemory(pInfo->wapi_ifname, tmpbuf, strlen(tmpbuf)); + pInfo->wapi_ifname_len = strlen(tmpbuf); + + DBGPRINT(RT_DEBUG_TRACE, ("Wapiifname=%s, len=%d\n", + pInfo->wapi_ifname, + pInfo->wapi_ifname_len)); + } + } + + + /* WapiAsCertPath */ + if (RTMPGetKeyParameter("WapiAsCertPath", tmpbuf, 128, buffer, TRUE)) + { + if (strlen(tmpbuf) > 0) + { + NdisMoveMemory(pInfo->as_cert_path[0], tmpbuf, strlen(tmpbuf)); + pInfo->as_cert_path_len[0] = strlen(tmpbuf); + pInfo->as_cert_no = 1; + + DBGPRINT(RT_DEBUG_TRACE, ("WapiAsCertPath=%s, len=%d\n", + pInfo->as_cert_path[0], + pInfo->as_cert_path_len[0])); + } + } + + /* WapiAsCertPath2 ~ WapiAsCertPath10 */ + for (idx = 1; idx < MAX_ID_NO; idx++) + { + sprintf(tok_str, "WapiAsCertPath%d", idx + 1); + + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE)) + { + if (strlen(tmpbuf) > 0) + { + NdisMoveMemory(pInfo->as_cert_path[idx], tmpbuf, strlen(tmpbuf)); + pInfo->as_cert_path_len[idx] = strlen(tmpbuf); + pInfo->as_cert_no++; + + DBGPRINT(RT_DEBUG_TRACE, ("WapiAsCertPath%d=%s, len=%d\n", + idx+1, + pInfo->as_cert_path[idx], + pInfo->as_cert_path_len[idx])); + } + } + } + + /* WapiCaCertPath */ + if (RTMPGetKeyParameter("WapiCaCertPath", tmpbuf, 128, buffer, TRUE)) + { + if (strlen(tmpbuf) > 0) + { + NdisMoveMemory(pInfo->ca_cert_path, tmpbuf, strlen(tmpbuf)); + pInfo->ca_cert_path_len = strlen(tmpbuf); + + DBGPRINT(RT_DEBUG_TRACE, ("WapiCaCertPath=%s, len=%d\n", + pInfo->ca_cert_path, + pInfo->ca_cert_path_len)); + } + } + + /* WapiUserCertPath */ + if (RTMPGetKeyParameter("WapiUserCertPath", tmpbuf, 128, buffer, TRUE)) + { + if (strlen(tmpbuf) > 0) + { + NdisMoveMemory(pInfo->user_cert_path, tmpbuf, strlen(tmpbuf)); + pInfo->user_cert_path_len = strlen(tmpbuf); + + DBGPRINT(RT_DEBUG_TRACE, ("WapiUserCertPath=%s, len=%d\n", + pInfo->user_cert_path, + pInfo->user_cert_path_len)); + } + } + + /* WapiAsIpAddr */ + if (RTMPGetKeyParameter("WapiAsIpAddr", tmpbuf, 32, buffer, TRUE)) + { + if (rtinet_aton(tmpbuf, &ip_addr)) + { + pInfo->wapi_as_ip = ip_addr; + DBGPRINT(RT_DEBUG_TRACE, ("WapiAsIpAddr=%s(%x)\n", tmpbuf, pInfo->wapi_as_ip)); + } + } + + /* WapiAsPort */ + if (RTMPGetKeyParameter("WapiAsPort", tmpbuf, 32, buffer, TRUE)) + { + pInfo->wapi_as_port = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("WapiAsPort=%d\n", pInfo->wapi_as_port)); + } + + /* WapiUskRekeyMethod */ + if (RTMPGetKeyParameter("WapiUskRekeyMethod", tmpbuf, 32, buffer, TRUE)) + { + if ((strcmp(tmpbuf, "TIME") == 0) || (strcmp(tmpbuf, "time") == 0)) + pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_TIME; + else if ((strcmp(tmpbuf, "PKT") == 0) || (strcmp(tmpbuf, "pkt") == 0)) + pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_PKT; + else + pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("WapiUskRekeyMethod=%d\n", pAd->CommonCfg.wapi_usk_rekey_method)); + } + + /* WapiUskRekeyThreshold */ + if (RTMPGetKeyParameter("WapiUskRekeyThreshold", tmpbuf, 32, buffer, TRUE)) + { + pAd->CommonCfg.wapi_usk_rekey_threshold = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("WapiUskRekeyThreshold=%d\n", pAd->CommonCfg.wapi_usk_rekey_threshold)); + } + + /* WapiMskRekeyMethod */ + if (RTMPGetKeyParameter("WapiMskRekeyMethod", tmpbuf, 32, buffer, TRUE)) + { + if ((strcmp(tmpbuf, "TIME") == 0) || (strcmp(tmpbuf, "time") == 0)) + pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_TIME; + else if ((strcmp(tmpbuf, "PKT") == 0) || (strcmp(tmpbuf, "pkt") == 0)) + pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_PKT; + else + pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("WapiMskRekeyMethod=%d\n", pAd->CommonCfg.wapi_msk_rekey_method)); + } + + /* WapiMskRekeyThreshold */ + if (RTMPGetKeyParameter("WapiMskRekeyThreshold", tmpbuf, 32, buffer, TRUE)) + { + pAd->CommonCfg.wapi_msk_rekey_threshold = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("WapiMskRekeyThreshold=%d\n", pAd->CommonCfg.wapi_msk_rekey_threshold)); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + STRING tok_str[16]; + + /* WapiPskX */ + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(tok_str, sizeof(tok_str), "WapiPsk%d", apidx + 1); + + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, 64); + pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = 0; + if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, buffer, FALSE)) + { + if (strlen(tmpbuf) >= 8 && strlen(tmpbuf) <= 64) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, tmpbuf, strlen(tmpbuf)); + pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = strlen(tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) WapiPsk=(%s), len=%d\n", apidx, tmpbuf, strlen(tmpbuf))); + } + else + { + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWAIPSK) + { + pAd->ApCfg.MBSSID[apidx].wdev.AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].wdev.WepStatus = Ndis802_11EncryptionDisabled; + } + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) The length of WAPI PSKPassPhrase is invalid(len=%d). \n", apidx, strlen(tmpbuf))); + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* WapiPsk */ + if (RTMPGetKeyParameter("WapiPsk", tmpbuf, 512, buffer, FALSE)) + { + NdisZeroMemory(pAd->StaCfg.WAPIPassPhrase, 64); + pAd->StaCfg.WAPIPassPhraseLen = 0; + if (strlen(tmpbuf) >= 8 && strlen(tmpbuf) <= 64) + { + NdisMoveMemory(pAd->StaCfg.WAPIPassPhrase, tmpbuf, strlen(tmpbuf)); + pAd->StaCfg.WAPIPassPhraseLen = strlen(tmpbuf); + + DBGPRINT(RT_DEBUG_TRACE, ("WapiPsk=(%s), len=%d\n", tmpbuf, strlen(tmpbuf))); + } + else + { + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAd->StaCfg.WepStatus = Ndis802_11EncryptionDisabled; + } + DBGPRINT(RT_DEBUG_ERROR, ("The length of WAPI PSKPassPhrase is invalid(len=%d). \n", strlen(tmpbuf))); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* WapiPskType */ + if (RTMPGetKeyParameter("WapiPskType", tmpbuf, 32, buffer, TRUE)) + { + INT err; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + PSTRING macptr; + + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), apidx++) + { + err = 0; + + if (apidx >= pAd->ApCfg.BssidNum) + break; + + /* HEX */ + if(simple_strtol(macptr, 0, 10) == 0) + { + pAd->ApCfg.MBSSID[apidx].WapiPskType = HEX_MODE; + + if (pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen % 2 != 0) + { + err = 1; + DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) The WAPI-PSK key length MUST be even in Hex mode\n", apidx)); + } + } + /* ASCII */ + else + { + pAd->ApCfg.MBSSID[apidx].WapiPskType = ASCII_MODE; + } + + if (err) + { + pAd->ApCfg.MBSSID[apidx].wdev.AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].wdev.WepStatus = Ndis802_11EncryptionDisabled; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WapiPskType=%s\n", apidx, (pAd->ApCfg.MBSSID[apidx].WapiPskType == HEX_MODE) ? "HEX" : "ASCII")); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + err = 0; + + /* HEX */ + if(simple_strtol(tmpbuf, 0, 10) == 0) + { + pAd->StaCfg.WapiPskType = HEX_MODE; + + if (pAd->StaCfg.WAPIPassPhraseLen % 2 != 0) + { + err = 1; + DBGPRINT(RT_DEBUG_ERROR, ("The WAPI-PSK key length MUST be even in Hex mode\n")); + } + } + /* ASCII */ + else + { + pAd->StaCfg.WapiPskType = ASCII_MODE; + } + + if (err) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAd->StaCfg.WepStatus = Ndis802_11EncryptionDisabled; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("WapiPskType=%s\n", (pAd->StaCfg.WapiPskType == HEX_MODE) ? "HEX" : "ASCII")); + } +#endif /* CONFIG_STA_SUPPORT */ + + } + + /* Sanity check - USK rekey parameter */ + if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_DISABLE || + pAd->CommonCfg.wapi_usk_rekey_threshold == 0) + { + pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE; + pAd->CommonCfg.wapi_usk_rekey_threshold = 0; + } + + /* Sanity check - MSK rekey parameter */ + if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_DISABLE || + pAd->CommonCfg.wapi_msk_rekey_threshold == 0) + { + pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE; + pAd->CommonCfg.wapi_msk_rekey_threshold = 0; + } + +} + +/* + ========================================================================== + Description: + It only shall be queried by wapi daemon for querying the related + configuration. This routine process the WAPI configuration for per BSS. + + ========================================================================== +*/ +static VOID RTMPQueryWapiConfPerBss( + IN PRTMP_ADAPTER pAd, + IN PWAPI_CONF wapi_conf_ptr, + IN UCHAR apidx) +{ + PMBSS_WAPI_INFO pConf = &wapi_conf_ptr->mbss_wapi_info[apidx]; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + + if (pMbss->wdev.if_dev != NULL) + { + PNET_DEV dev = pMbss->wdev.if_dev; + + NdisMoveMemory(pConf->ifname, RtmpOsGetNetDevName(dev), strlen(RtmpOsGetNetDevName(dev))); + pConf->ifname_len = strlen(RtmpOsGetNetDevName(dev)); + } + else + { + STRING slot_name[IFNAMSIZ]; + + snprintf(slot_name, sizeof(slot_name), "ra%d", apidx); + NdisMoveMemory(pConf->ifname, slot_name, strlen(slot_name)); + pConf->ifname_len = strlen(slot_name); + } + + /* Decide the authentication mode */ + if (pMbss->wdev.AuthMode == Ndis802_11AuthModeWAICERT) + pConf->auth_mode = WAPI_AUTH_CERT; + else if (pMbss->wdev.AuthMode == Ndis802_11AuthModeWAIPSK) + pConf->auth_mode = WAPI_AUTH_PSK; + else + pConf->auth_mode = WAPI_AUTH_DISABLE; + + /* Fill in WAI pre-shared key */ + if (pMbss->WAPIPassPhraseLen > 0) + { + if (pMbss->WapiPskType == HEX_MODE) + { + pConf->psk_len = pMbss->WAPIPassPhraseLen / 2; + AtoH((PSTRING) pMbss->WAPIPassPhrase, (PUCHAR) pConf->psk, pConf->psk_len); + } + else + { + pConf->psk_len = pMbss->WAPIPassPhraseLen; + NdisMoveMemory(pConf->psk, pMbss->WAPIPassPhrase, pConf->psk_len); + } + } + + /* Fill in WIE */ + if (pMbss->RSNIE_Len[0] > 0) + { + pConf->wie_len = pMbss->RSNIE_Len[0] + 2; + + pConf->wie[0] = IE_WAPI; + pConf->wie[1] = pMbss->RSNIE_Len[0]; + NdisMoveMemory(&pConf->wie[2], pMbss->RSN_IE[0], pMbss->RSNIE_Len[0]); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NdisMoveMemory(pConf->ifname, pAd->StaCfg.dev_name, strlen((PSTRING) pAd->StaCfg.dev_name)); + pConf->ifname_len = strlen((PSTRING) pAd->StaCfg.dev_name); + + /* Decide the authentication mode */ + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + pConf->auth_mode = WAPI_AUTH_CERT; + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK) + pConf->auth_mode = WAPI_AUTH_PSK; + else + pConf->auth_mode = WAPI_AUTH_DISABLE; + + /* Fill in WAI pre-shared key */ + if (pAd->StaCfg.WAPIPassPhraseLen > 0) + { + if (pAd->StaCfg.WapiPskType == HEX_MODE) + { + pConf->psk_len = pAd->StaCfg.WAPIPassPhraseLen / 2; + AtoH((PSTRING) pAd->StaCfg.WAPIPassPhrase, (PUCHAR) pConf->psk, pConf->psk_len); + } + else + { + pConf->psk_len = pAd->StaCfg.WAPIPassPhraseLen; + NdisMoveMemory(pConf->psk, pAd->StaCfg.WAPIPassPhrase, pConf->psk_len); + } + } + + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + /* Fill in WIE */ + if (pAd->StaCfg.RSNIE_Len > 0) + { + pConf->wie_len = pAd->StaCfg.RSNIE_Len + 2; + + pConf->wie[0] = IE_WAPI; + pConf->wie[1] = pAd->StaCfg.RSNIE_Len; + NdisMoveMemory(&pConf->wie[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + +} + + +/* + ========================================================================== + Description: + It only shall be queried by wapi daemon for querying the related + configuration. + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlQueryWapiConf( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR apidx; + UCHAR *buf = NULL; + PWAPI_CONF pConf; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlQueryWapiConf==>\n")); + + /* Allocate memory for WAPI configuration */ + os_alloc_mem(NULL, (PUCHAR *)&buf, sizeof(WAPI_CONF)); + + if (buf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: allocate memory fail\n", __FUNCTION__)); + return; + } + + pConf = (PWAPI_CONF)buf; + + NdisZeroMemory((PUCHAR)pConf, sizeof(WAPI_CONF)); + + /* get MBSS number */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pConf->mbss_num = pAd->ApCfg.BssidNum; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pConf->mbss_num = 1; + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Set common configuration */ + NdisMoveMemory(&pConf->comm_wapi_info, &pAd->CommonCfg.comm_wapi_info, sizeof(COMMON_WAPI_INFO)); + + for (apidx = 0; apidx < pConf->mbss_num; apidx++) + { + RTMPQueryWapiConfPerBss(pAd, pConf, apidx); + } + + wrq->u.data.length = sizeof(WAPI_CONF); + if (copy_to_user(wrq->u.data.pointer, pConf, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + os_free_mem(NULL, buf); +} + +/* + ========================================================================== + Description: + Timer execution function for periodically updating WAPI key. + Return: + ========================================================================== +*/ +VOID RTMPWapiUskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UINT32 tmp_cnt = 0; + PMAC_TABLE_ENTRY pEntry = (PMAC_TABLE_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + + if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_TIME) + { + tmp_cnt = (++pEntry->wapi_usk_rekey_cnt); + } + else if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT) + { + /* the unit is 1K packets */ + tmp_cnt = pEntry->wapi_usk_rekey_cnt/1000; + } + else + return; + + /* Trigger rekey procedure */ + if (tmp_cnt > pAd->CommonCfg.wapi_usk_rekey_threshold) + { + pEntry->wapi_usk_rekey_cnt = 0; + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->apidx, + pEntry->Addr, + WAI_MLME_UPDATE_USK); + } + +} + + +/* + ========================================================================== + Description: + Timer execution function for periodically updating WAPI key. + Return: + ========================================================================== +*/ +VOID RTMPWapiMskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UINT i; + UINT32 tmp_cnt = 0; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + + + /* if no any WAPI STA associated, don't do anything. */ + if (pAd->MacTab.fAnyWapiStation == FALSE) + return; + + /* increase counter for TIME method */ + if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_TIME) + { + tmp_cnt = (++pAd->CommonCfg.wapi_msk_rekey_cnt); + } + else if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_PKT) + { + /* the unit is 1K packets */ + tmp_cnt = pAd->CommonCfg.wapi_msk_rekey_cnt/1000; + } + else + return; + + if (tmp_cnt > pAd->CommonCfg.wapi_msk_rekey_threshold) + { + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT apidx = 0; + UINT cnt; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + UINT m_wcid; + + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId == 0 ? 1 : 0; + inc_iv_byte(pAd->ApCfg.MBSSID[apidx].key_announce_flag, LEN_WAPI_TSC, 1); + + /* Generate NMK randomly */ + for (cnt = 0; cnt < 16; cnt++) + pAd->ApCfg.MBSSID[apidx].NMK[cnt] = RandomByte(pAd); + + RTMPDeriveWapiGTK(pAd->ApCfg.MBSSID[apidx].NMK, pAd->ApCfg.MBSSID[apidx].GTK); + + GET_GroupKey_WCID(pAd, m_wcid, apidx); + /* Install Shared key */ + WAPIInstallSharedKey(pAd, + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus, + apidx, + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId, + m_wcid, + pAd->ApCfg.MBSSID[apidx].GTK); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Todo for Adhoc mode */ + } +#endif /* CONFIG_STA_SUPPORT */ + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && + (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->apidx, + pEntry->Addr, + WAI_MLME_UPDATE_MSK); + } + } + } + +} + + +VOID RTMPInitWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, (" RTMPInitWapiRekeyTimerAction : WAPI USK rekey timer (wcid-%d) \n", pEntry->wcid)); + RTMPInitTimer(pAd, &pEntry->WapiUskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec), pEntry, TRUE); + pEntry->WapiUskRekeyTimerRunning = FALSE; + } + else + { + RTMPInitTimer(pAd, &pAd->CommonCfg.WapiMskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec), pAd, TRUE); + pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE; + } +} + +VOID RTMPStartWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + if (pEntry) + { + if ((pAd->CommonCfg.wapi_usk_rekey_method != REKEY_METHOD_DISABLE) && + (pAd->CommonCfg.wapi_usk_rekey_threshold > 0)) + { + /* Regularly check the timer */ + if (pEntry->WapiUskRekeyTimerRunning == FALSE) + { + RTMPSetTimer(&pEntry->WapiUskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV); + + pEntry->WapiUskRekeyTimerRunning = TRUE; + pEntry->wapi_usk_rekey_cnt = 0; + DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI USK rekey timer is started (%d) \n", pAd->CommonCfg.wapi_usk_rekey_threshold)); + } + } + } + else + { + if ((pAd->CommonCfg.wapi_msk_rekey_method != REKEY_METHOD_DISABLE) && + (pAd->CommonCfg.wapi_msk_rekey_threshold > 0)) + { + /* Regularly check the timer */ + if (pAd->CommonCfg.WapiMskRekeyTimerRunning == FALSE) + { + RTMPSetTimer(&pAd->CommonCfg.WapiMskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV); + + pAd->CommonCfg.WapiMskRekeyTimerRunning = TRUE; + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; + DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI MSK rekey timer is started \n")); + } + } + } + +} + +VOID RTMPCancelWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + if(pEntry) + { + if (pEntry->WapiUskRekeyTimerRunning == TRUE) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pEntry->WapiUskRekeyTimer, &Cancelled); + pEntry->wapi_usk_rekey_cnt = 0; + pEntry->WapiUskRekeyTimerRunning = FALSE; + } + } + else + { + if (pAd->CommonCfg.WapiMskRekeyTimerRunning == TRUE) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->CommonCfg.WapiMskRekeyTimer, &Cancelled); + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; + pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE; + } + } + +} + +/* + ======================================================================== + + Routine Description: + Prepare a L2 frame to wapi daemon to trigger WAPI state machine + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN WAPI_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR apidx, + IN PUCHAR pAddr, + IN UCHAR flag) +{ + if ((AuthMode == Ndis802_11AuthModeWAICERT) || + (AuthMode == Ndis802_11AuthModeWAIPSK)) + { + UCHAR WAPI_IE[] = {0x88, 0xb4}; + UINT8 frame_len = LENGTH_802_3 + 12; /* 12 indicates the WAPI internal command length */ + UCHAR FrameBuf[frame_len]; + UINT8 offset = 0; + + /* Init the frame buffer */ + NdisZeroMemory(FrameBuf, frame_len); + + /* Prepare the 802.3 header */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].wdev.bssid, pAddr, WAPI_IE); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MAKE_802_3_HEADER(FrameBuf, pAd->CurrentAddress, pAddr, WAPI_IE); + } +#endif /* CONFIG_STA_SUPPORT */ + offset += LENGTH_802_3; + + /* Prepare the specific WAPI header */ + NdisMoveMemory(&FrameBuf[offset], RALINK_OUI, 3); + offset += 3; + + /* Set the state of this command */ + FrameBuf[offset] = flag; + + DBGPRINT(RT_DEBUG_TRACE, ("Trigger WAPI for this sta(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pAddr))); + + /* Report to upper layer */ + if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE) + return FALSE; + + } + + return TRUE; +} + + +VOID RTMPGetWapiTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UINT Wcid, + OUT UCHAR *tx_tsc) +{ + USHORT offset; + int i; + + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + UINT32 wapi_pn_base = 0, wapi_pn_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + wapi_pn_base = RLT_WAPI_PN_TABLE_BASE; + wapi_pn_size = RLT_WAPI_PN_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + wapi_pn_base = WAPI_PN_TABLE_BASE; + wapi_pn_size = WAPI_PN_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + NdisZeroMemory(tx_tsc, LEN_WAPI_TSC); + + /* Read IVEIV from Asic */ + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + for (i=0 ; i < iveiv_tb_size; i++) + RTMP_IO_READ8(pAd, offset+i, &tx_tsc[i]); + + /* Read WAPI PM from Asic */ + offset = wapi_pn_base + (Wcid * wapi_pn_size); + for (i=0 ; i < wapi_pn_size; i++) + RTMP_IO_READ8(pAd, offset+i, &tx_tsc[iveiv_tb_size + i]); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : WCID(%d) ", __FUNCTION__, Wcid)); + hex_dump("TxTsc", tx_tsc, LEN_WAPI_TSC); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n", + __FUNCTION__)); + } + +} + + +VOID WAPIInstallPairwiseKey( + PRTMP_ADAPTER pAd, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE) +{ + PCIPHER_KEY pKey; + + pKey = &pEntry->PairwiseKey; + NdisZeroMemory(pKey, sizeof(CIPHER_KEY)); + + /* Assign the pairwise cipher algorithm */ + if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) + pKey->CipherAlg = CIPHER_SMS4; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n", + __FUNCTION__, pEntry->wcid)); + return; + } + + /* Prepare pair-wise key material */ + pKey->KeyLen = LEN_TK; + NdisMoveMemory(pKey->Key, &pEntry->PTK[0], 16); + NdisMoveMemory(pKey->TxMic, &pEntry->PTK[16], 8); + NdisMoveMemory(pKey->RxMic, &pEntry->PTK[24], 8); + + /* Initial TSC for unicast */ + if (bAE) + NdisMoveMemory(pKey->TxTsc, AE_UCAST_PN, LEN_WAPI_TSC); + else + NdisMoveMemory(pKey->TxTsc, ASUE_UCAST_PN, LEN_WAPI_TSC); + NdisZeroMemory(pKey->RxTsc, LEN_WAPI_TSC); + + /* HW_WAPI is supported in RT3883 or later */ + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 CONST_WAPI_PN = 0x5C365C36; + + /* Set unicast packet's PN to Asic. */ + if (bAE) + AsicUpdateWCIDIVEIV(pAd, pEntry->wcid, CONST_WAPI_PN + 1, CONST_WAPI_PN); + else + AsicUpdateWCIDIVEIV(pAd, pEntry->wcid, CONST_WAPI_PN, CONST_WAPI_PN); + AsicUpdateWAPIPN(pAd, pEntry->wcid, CONST_WAPI_PN, CONST_WAPI_PN); + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + AsicUpdateWcidAttributeEntry( + pAd, + pEntry->apidx, + pEntry->usk_id, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->wcid, + PAIRWISEKEYTABLE); + } + +} + + +VOID WAPIInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + PUINT8 pGtk) +{ + UINT32 CONST_WAPI_PN = 0x5C365C36; + PCIPHER_KEY pSharedKey; + + if (BssIdx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The BSS-index(%d) is out of range for MBSSID link. \n", + __FUNCTION__, BssIdx)); + return; + } + + pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx]; + NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); + + if (GroupCipher == Ndis802_11EncryptionSMS4Enabled) + pSharedKey->CipherAlg = CIPHER_SMS4; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n", + __FUNCTION__, BssIdx)); + return; + } + + /* Assign key material into SW key table */ + pSharedKey->KeyLen = LEN_TK; + NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK); + NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC); + + /* Initial TSC for B/Mcast */ + NdisMoveMemory(pSharedKey->TxTsc, AE_BCAST_PN, LEN_WAPI_TSC); + NdisZeroMemory(pSharedKey->RxTsc, LEN_WAPI_TSC); + + /* HW_WAPI is supported in RT3883 or later */ + if (IS_HW_WAPI_SUPPORT(pAd)) + { + /* Install Group Key to MAC ASIC */ + AsicAddSharedKeyEntry( + pAd, + BssIdx, + KeyIdx, + pSharedKey); + + /* When Wcid isn't zero, it means that this is a Authenticator Role. + Only Authenticator entity needs to set HW IE/EIV table (0x6000), + WAPI PN table (0x7800) + and WCID attribute table (0x6800) for group key. */ + if (Wcid != 0) + { + /* Set 16-bytes PN to Asic. */ + AsicUpdateWCIDIVEIV(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN); + AsicUpdateWAPIPN(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN); + + /* update Group key information to ASIC */ + AsicUpdateWcidAttributeEntry( + pAd, + BssIdx, + KeyIdx, + pSharedKey->CipherAlg, + Wcid, + SHAREDKEYTABLE); + } + } +} + +#endif /* WAPI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi_crypt.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi_crypt.c new file mode 100644 index 000000000..8542f9a7e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi_crypt.c @@ -0,0 +1,508 @@ + +#ifdef LINUX +#include +#include +#include /* Needed for the macros */ +#endif /* LINUX */ + +#include "rtmp_type.h" +#include "wpa_cmm.h" +#include "wapi_def.h" +#include "wapi_sms4.h" + +void dump_bin(char *name, void *data, int len) +{ + int i = 0; + unsigned char *p = data; + + if(name != NULL) + { + printk("%s(%d): \n", name, len); + } + printk("\t"); + + for(i=0; i pMem2[Index]) + return (1); + else if (pMem1[Index] < pMem2[Index]) + return (2); + } + + /* Equal */ + return (0); +} + +/************************************/ +/* bitwise_xor() */ +/* A 128 bit, bitwise exclusive or */ +/************************************/ + +void bitwise_xor_wpi(unsigned char *ina, unsigned char *inb, unsigned char *out) +{ + int i; + for (i=0; i<16; i++) + { + out[i] = ina[i] ^ inb[i]; + } +} + +/*cbc_mac*/ +int wpi_cbc_mac_engine( + unsigned char * maciv_in, + unsigned char * in_data1, + unsigned int in_data1_len, + unsigned char * in_data2, + unsigned int in_data2_len, + unsigned char * pkey, + unsigned char * mac_out) +{ + unsigned char mactmp[16]; + unsigned int i; + unsigned int num_blocks_1, num_blocks_2; + unsigned int prmackey_in[32]; + + num_blocks_1 = (in_data1_len) >> 4; + num_blocks_2 = (in_data2_len) >> 4; + + if((num_blocks_1 + num_blocks_2 ) < 1) return 1; + if((num_blocks_1 + num_blocks_2 ) > 4096) return 1; + + SMS4KeyExt(pkey, prmackey_in, 0); + SMS4Crypt(maciv_in, mactmp, prmackey_in); + + for (i = 0; i < num_blocks_1; i++) + { + bitwise_xor_wpi(mactmp, in_data1, mactmp); + in_data1 += 16; + SMS4Crypt(mactmp, mactmp, prmackey_in); + } + + for (i = 0; i < num_blocks_2; i++) + { + bitwise_xor_wpi(mactmp, in_data2, mactmp); + in_data2 += 16; + SMS4Crypt(mactmp, mactmp, prmackey_in); + } + memcpy(mac_out, mactmp, 16); + + return 0; +} + +/*ofb encrypt*/ +int wpi_sms4_ofb_engine( + unsigned char * pofbiv_in, + unsigned char * pbw_in, + unsigned int plbw_in, + unsigned char * pkey, + unsigned char * pcw_out) +{ + unsigned char ofbtmp[16]; + /*unsigned int * pint0, * pint1; */ + /*unsigned char * pchar0, * pchar1,* pchar2; */ + unsigned int counter,comp,i; + unsigned int prkey_in[32]; + + + if(plbw_in<1) return 1; + /*if(plbw_in>65536) return 1; */ + + SMS4KeyExt(pkey, prkey_in, 0); + + /* get the multiple of 16 */ + counter = plbw_in >> 4; + /* get the remainder of 16 */ + comp = plbw_in & 0x0f; + + /*get the iv */ + SMS4Crypt(pofbiv_in, ofbtmp, prkey_in); + + for(i = 0; i < counter; i++) + { + bitwise_xor_wpi(pbw_in, ofbtmp, pcw_out); + pbw_in += 16; + pcw_out += 16; + SMS4Crypt(ofbtmp, ofbtmp, prkey_in); + } + + for(i = 0; i < comp; i++) + { + pcw_out[i]=pbw_in[i]^ofbtmp[i]; + } + + return 0; +} + + +/* + ======================================================================== + + Routine Description: + Make the integrity check header for WPI MIC + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + + Note: + + ======================================================================== +*/ +UINT32 wpi_construct_mic_hdr( + IN PUCHAR pHdr, + IN UINT32 data_len, + IN UCHAR keyidx, + OUT UCHAR *mic_hdr) +{ + UINT8 from_ds, to_ds, a4_exists, qc_exists; + UINT8 frame_type; + UINT8 frame_subtype; + UINT8 mhdr_len = 0; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + frame_type = (((*pHdr) >> 2) & 0x03); + frame_subtype = (((*pHdr) >> 4) & 0x0f); + + /* Check if Addr4 is available */ + from_ds = ((*(pHdr + 1)) & 0x2) >> 1; + to_ds = ((*(pHdr + 1)) & 0x1); + a4_exists = (from_ds & to_ds); + + /* Check if Qos is available */ + qc_exists = ((frame_subtype == 0x08) || /* QoS Data */ + (frame_subtype == 0x09) || /* QoS Data + CF-Ack */ + (frame_subtype == 0x0a) || /* QoS Data + CF-Poll */ + (frame_subtype == 0x0b) /* QoS Data + CF-Ack + CF-Poll */ + ); + + /* Frame control */ + /* bit 4,5,6 must be zero */ + /* bit 11,12,13 must be zero */ + /* bit 14 must be 1 */ + mic_hdr[mhdr_len] = (*pHdr) & 0x8f; + mic_hdr[mhdr_len + 1] = (*(pHdr + 1)) & 0xc7; + mhdr_len = 2; + + /* Addr1 & 2 */ + WapiMoveMemory(&mic_hdr[mhdr_len], pHdr + 4, 2 * MAC_ADDR_LEN); + mhdr_len += (2 * MAC_ADDR_LEN); + + /* In Sequence Control field, mute sequence numer bits (12-bit) */ + mic_hdr[mhdr_len] = (*(pHdr + 22)) & 0x0f; + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + + /* Addr3 */ + WapiMoveMemory(&mic_hdr[mhdr_len], pHdr + 16, MAC_ADDR_LEN); + mhdr_len += MAC_ADDR_LEN; + + /* Fill the Addr4 field. */ + /* If the Addr4 is unused, it shall be padded zero. */ + if (a4_exists) + WapiMoveMemory(&mic_hdr[mhdr_len], pHdr + 24, MAC_ADDR_LEN); + else + WapiMoveMemory(&mic_hdr[mhdr_len], ZERO_MAC_ADDR, MAC_ADDR_LEN); + mhdr_len += MAC_ADDR_LEN; + + /* Qos field */ + if (qc_exists & a4_exists) + { + mic_hdr[mhdr_len] = (*(pHdr + 30)) & 0x0f; /* Qos_TC */ + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + } + else if (qc_exists & !a4_exists) + { + mic_hdr[mhdr_len] = (*(pHdr + 24)) & 0x0f; /* Qos_TC */ + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + } + + /* fill the KeyIdx and reserve field */ + mic_hdr[mhdr_len] = keyidx; + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + + /* Fill in data len field */ + mic_hdr[mhdr_len] = (data_len >> 8) & 0xff; + mic_hdr[mhdr_len + 1] = (data_len) & 0xff; + mhdr_len += 2; + + /* the len must be the multiple of 16 */ + /* If the Qos field doesn't exist, the header length shall be 32. */ + /* If the Qos exists, the header is 34. We need to expand it as 48 by padding zero. */ + /*DBGPRINT(RT_DEBUG_TRACE, ("mhdr_len(%d)\n", mhdr_len)); */ + mhdr_len = (mhdr_len > 32) ? 48 : 32; + + return mhdr_len; +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC of WPI data. + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + TRUE - success + FLASE - failure + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPCalculateWpiMic( + IN PUCHAR pHeader, + IN PUCHAR pData, + IN UINT32 data_len, + IN UINT8 key_idx, + IN PUCHAR pKey, + IN PUCHAR pIV, + OUT PUCHAR pOutMic) +{ + UCHAR mic_header[48]; + UINT8 mic_hdr_len = 0; + UINT8 pad_len = 0; + UINT8 remainder = 0; + + WapiZeroMemory(mic_header, 48); + + /* Construct integrity verify data header */ + mic_hdr_len = wpi_construct_mic_hdr(pHeader, data_len, key_idx, mic_header); + + /* calculate the padded length */ + if ((remainder = data_len & 0x0f) != 0) + pad_len = (16 - remainder); + + /* Calculate MIC */ + wpi_cbc_mac_engine(pIV, + mic_header, + mic_hdr_len, + pData, + data_len + pad_len, + pKey, + pOutMic); + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Encrypt WPI-data by software. + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + TRUE - success + FLASE - failure + + Note: + + ======================================================================== +*/ +INT RTMPSoftEncryptSMS4( + IN PUCHAR pHeader, + IN PUCHAR pData, + IN UINT32 data_len, + IN UCHAR key_id, + IN PUCHAR pKey, + IN PUCHAR pIv) +{ + INT i; + UCHAR out_mic[LEN_WPI_MIC]; + UCHAR iv_inv[LEN_WAPI_TSC]; + + /* Inverse IV byte order */ + for (i=0; i < LEN_WAPI_TSC; i++) + { + iv_inv[LEN_WAPI_TSC - 1 - i] = (*(pIv + i)) & 0xFF; + } + + WapiZeroMemory(out_mic, LEN_WPI_MIC); + /* clear enough space for calculating WPI MIC later */ + WapiZeroMemory(pData + data_len, LEN_WPI_MIC); + /* Calculate WPI MIC */ + RTMPCalculateWpiMic(pHeader, + pData, + data_len, + key_id, + pKey + 16, + iv_inv, + out_mic); + + /* append MIC to the data tail */ + WapiMoveMemory(pData + data_len, out_mic, LEN_WPI_MIC); + + /* Encrypt WPI data by software */ + wpi_sms4_ofb_engine(iv_inv, pData, data_len + LEN_WPI_MIC, pKey, pData); + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Decrypt WPI-data by software. + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + TRUE - success + FLASE - failure + + Note: + + ======================================================================== +*/ +INT RTMPSoftDecryptSMS4( + IN PUCHAR pHdr, + IN BOOLEAN bSanityIV, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt) +{ + UCHAR i; + UCHAR key_idx; + PUCHAR iv_ptr; + UCHAR iv_inv[LEN_WAPI_TSC]; + UCHAR MIC[LEN_WPI_MIC]; + UCHAR TrailMIC[LEN_WPI_MIC]; + /*PUCHAR mic_ptr; */ + /*UINT32 mic_data_len; */ + /*PUCHAR buf_ptr = NULL; */ + PUCHAR plaintext_ptr; + UINT16 plaintext_len; + PUCHAR ciphertext_ptr; + UINT16 ciphertext_len; + + /* Check the key is valid */ + if (pKey->KeyLen == 0) + { + return STATUS_WAPI_KEY_INVALID; + } + + /* extract key index from the IV header */ + key_idx = *(pData) & 0xFF; + + /* Skip 2-bytes(key_idx and reserve field) and point to IV field */ + iv_ptr = pData + 2; + + /* IV sanity check */ + if (bSanityIV) + { + if (WapiCompareMemory(iv_ptr, pKey->RxTsc, LEN_WAPI_TSC) > 1) + { + return STATUS_WAPI_IV_MISMATCH; + } + else + { + /* Record the received IV */ + WapiMoveMemory(pKey->RxTsc, iv_ptr, LEN_WAPI_TSC); + } + } + + /* Inverse IV byte order for SMS4 calculation */ + for (i = 0; i < LEN_WAPI_TSC; i++) + { + iv_inv[LEN_WAPI_TSC - 1 - i] = (*(iv_ptr + i)) & 0xFF; + } + + /* Skip the WPI IV header (18-bytes) */ + ciphertext_ptr = pData + LEN_WPI_IV_HDR; + ciphertext_len = *DataByteCnt - LEN_WPI_IV_HDR; + + /* skip payload length is zero */ + if ((*DataByteCnt ) <= LEN_WPI_IV_HDR) + return FALSE; + + /* Decrypt the WPI MPDU. It shall include plaintext and MIC. + The result output would overwrite the original WPI IV header position */ + wpi_sms4_ofb_engine(iv_inv, ciphertext_ptr, ciphertext_len, pKey->Key, pData); + + /* Point to the plainext data frame and its length shall exclude MIC length */ + plaintext_ptr = pData; + plaintext_len = ciphertext_len - LEN_WPI_MIC; + + /* Extract peer's MIC and zero the MIC field of received frame */ + WapiMoveMemory(TrailMIC, plaintext_ptr + plaintext_len, LEN_WPI_MIC); + WapiZeroMemory(plaintext_ptr + plaintext_len, LEN_WPI_MIC); + + /* Calculate WPI MIC */ + WapiZeroMemory(MIC, LEN_WPI_MIC); + RTMPCalculateWpiMic(pHdr, + plaintext_ptr, + plaintext_len, + key_idx, + pKey->TxMic, + iv_inv, + MIC); + + /* Compare the MIC field */ + if (!WapiEqualMemory(MIC, TrailMIC, LEN_WPI_MIC)) + { + return STATUS_WAPI_MIC_DIFF; + } + + /* Update the total data length */ + *DataByteCnt = plaintext_len; + + return STATUS_SUCCESS; +} + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi_sms4.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi_sms4.c new file mode 100644 index 000000000..540dffc34 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wapi_sms4.c @@ -0,0 +1,127 @@ + + +const unsigned char ISbox[256] = { +0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05, +0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99, +0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62, +0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6, +0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8, +0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35, +0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87, +0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e, +0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1, +0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3, +0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f, +0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51, +0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8, +0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0, +0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84, +0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 +}; + +const unsigned int CK[32] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 }; + +#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y)))) +#define getbyte(_x,_y) (((unsigned char *)&(_x))[_y]) + +#define ByteSub(_A) (ISbox[((unsigned int)_A) >> 24 & 0xFF] << 24 ^ \ + ISbox[((unsigned int)_A) >> 16 & 0xFF] << 16 ^ \ + ISbox[((unsigned int)_A) >> 8 & 0xFF] << 8 ^ \ + ISbox[((unsigned int)_A) & 0xFF]) + +#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24)) +#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23)) + +#ifdef RT_BIG_ENDIAN +#define byteReverse(x0, x1, x2, x3) /* Nothing */ +#else +void byteReverse(unsigned int *x0, unsigned int *x1, unsigned int *x2, unsigned int *x3); +void byteReverse(unsigned int *x0, unsigned int *x1, unsigned int *x2, unsigned int *x3) +{ + *x0 = Rotl(*x0, 16); *x0 = ((*x0 & 0x00FF00FF) << 8) ^ ((*x0 & 0xFF00FF00) >> 8); + *x1 = Rotl(*x1, 16); *x1 = ((*x1 & 0x00FF00FF) << 8) ^ ((*x1 & 0xFF00FF00) >> 8); + *x2 = Rotl(*x2, 16); *x2 = ((*x2 & 0x00FF00FF) << 8) ^ ((*x2 & 0xFF00FF00) >> 8); + *x3 = Rotl(*x3, 16); *x3 = ((*x3 & 0x00FF00FF) << 8) ^ ((*x3 & 0xFF00FF00) >> 8); +} +#endif + +#define ENCRYPT 0 +#define DECRYPT 1 + +void SMS4Crypt(unsigned char *Input, unsigned char *Output, unsigned int *rk) +{ + unsigned int r, mid, x0, x1, x2, x3, *p; + p = (unsigned int *)Input; + x0 = p[0]; + x1 = p[1]; + x2 = p[2]; + x3 = p[3]; + + byteReverse(&x0, &x1, &x2, &x3); + for (r = 0; r < 32; r += 4) + { + mid = x1 ^ x2 ^ x3 ^ rk[r + 0]; + mid = ByteSub(mid); + x0 ^= L1(mid); + mid = x2 ^ x3 ^ x0 ^ rk[r + 1]; + mid = ByteSub(mid); + x1 ^= L1(mid); + mid = x3 ^ x0 ^ x1 ^ rk[r + 2]; + mid = ByteSub(mid); + x2 ^= L1(mid); + mid = x0 ^ x1 ^ x2 ^ rk[r + 3]; + mid = ByteSub(mid); + x3 ^= L1(mid); + } + + byteReverse(&x0, &x1, &x2, &x3); + + p = (unsigned int *)Output; + p[0] = x3; + p[1] = x2; + p[2] = x1; + p[3] = x0; + +} + + +void SMS4KeyExt(unsigned char *Key, unsigned int *rk, unsigned int CryptFlag) +{ + unsigned int r, mid, x0, x1, x2, x3, *p; + p = (unsigned int *)Key; + x0 = p[0]; + x1 = p[1]; + x2 = p[2]; + x3 = p[3]; + + byteReverse(&x0, &x1, &x2, &x3); + + x0 ^= 0xa3b1bac6; + x1 ^= 0x56aa3350; + x2 ^= 0x677d9197; + x3 ^= 0xb27022dc; + for (r = 0; r < 32; r += 4) + { + mid = x1 ^ x2 ^ x3 ^ CK[r + 0]; + mid = ByteSub(mid); + rk[r + 0] = x0 ^= L2(mid); + mid = x2 ^ x3 ^ x0 ^ CK[r + 1]; + mid = ByteSub(mid); + rk[r + 1] = x1 ^= L2(mid); + mid = x3 ^ x0 ^ x1 ^ CK[r + 2]; + mid = ByteSub(mid); + rk[r + 2] = x2 ^= L2(mid); + mid = x0 ^ x1 ^ x2 ^ CK[r + 3]; + mid = ByteSub(mid); + rk[r + 3] = x3 ^= L2(mid); + } +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wfd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wfd.c new file mode 100644 index 000000000..794b5f421 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wfd.c @@ -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. + ***************************************************************************/ + + +#include "rt_config.h" +#include "wfd_cmm.h" + +#ifdef WFD_SUPPORT + +UCHAR WIFIDISPLAY_OUI[] = {0x50, 0x6f, 0x9a, 0x0a}; + +INT Set_WfdEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bEnable; + + bEnable = simple_strtol(arg, 0, 10); + + if (bEnable == TRUE) + { + pAd->StaCfg.WfdCfg.bWfdEnable= TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Enable WFD Support!\n", __FUNCTION__)); + } + else + { + pAd->StaCfg.WfdCfg.bWfdEnable= FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Disable WFD Support!\n", __FUNCTION__)); + } + + return TRUE; +} + +INT Set_WfdDeviceType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR DeviceType; + + DeviceType = simple_strtol(arg, 0, 10); + + if (DeviceType <= WFD_SOURCE_PRIMARY_SINK) + { + pAd->StaCfg.WfdCfg.DeviceType = DeviceType; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Device Type Not Support!!\n", __FUNCTION__)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Device Type = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.DeviceType)); + + return TRUE; +} + + +INT Set_WfdCouple_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR coupled; + + if (simple_strtol(arg, 0, 10) == 0) + coupled = WFD_COUPLED_NOT_SUPPORT; + else if (simple_strtol(arg, 0, 10) == 1) + coupled = WFD_COUPLED_SUPPORT; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Coupled out of range!!\n", __FUNCTION__)); + return FALSE; + } + + switch (pAd->StaCfg.WfdCfg.DeviceType) + { + case WFD_SOURCE: + pAd->StaCfg.WfdCfg.SourceCoupled = coupled; + break; + case WFD_PRIMARY_SINK: + case WFD_SECONDARY_SINK: + pAd->StaCfg.WfdCfg.SinkCoupled = coupled; + break; + case WFD_SOURCE_PRIMARY_SINK: + pAd->StaCfg.WfdCfg.SourceCoupled = coupled; + pAd->StaCfg.WfdCfg.SinkCoupled = coupled; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Device Type = %d, Source Coupled = %d, Sink Coupled = %d\n", __FUNCTION__, + pAd->StaCfg.WfdCfg.DeviceType, pAd->StaCfg.WfdCfg.SourceCoupled, pAd->StaCfg.WfdCfg.SinkCoupled)); + + return TRUE; +} + +INT Set_WfdSessionAvailable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.WfdCfg.SessionAvail= WFD_SESSION_NOT_AVAILABLE; + else if (simple_strtol(arg, 0, 10) == 1) + pAd->StaCfg.WfdCfg.SessionAvail = WFD_SESSION_AVAILABLE; + else + { + pAd->StaCfg.WfdCfg.SessionAvail = WFD_SESSION_NOT_AVAILABLE; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Session Available out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.SessionAvail)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Session Available = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.SessionAvail)); + + return TRUE; +} + +INT Set_WfdCP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.WfdCfg.CP = WFD_CP_NOT_SUPPORT; + else if (simple_strtol(arg, 0, 10) == 1) + pAd->StaCfg.WfdCfg.CP = WFD_CP_HDCP20; + else + { + pAd->StaCfg.WfdCfg.CP = WFD_CP_NOT_SUPPORT; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Content Protection out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.CP)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Content Protection = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.CP)); + + return TRUE; +} + + +INT Set_WfdRtspPort_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 RtspPort; + + RtspPort = simple_strtol(arg, 0, 10); + + if ((RtspPort < 0) || (65535 < RtspPort)) + { + pAd->StaCfg.WfdCfg.RtspPort = WFD_RTSP_DEFAULT_PORT; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: RTSP Port out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.RtspPort)); + } + else + pAd->StaCfg.WfdCfg.RtspPort = RtspPort; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: RTSP Port = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.RtspPort)); + + return TRUE; +} + + +INT Set_WfdMaxThroughput_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 Throughput; + + Throughput = simple_strtol(arg, 0, 10); + + if ((Throughput <= 0)|| (65535 < Throughput)) + { + pAd->StaCfg.WfdCfg.MaxThroughput = WFD_MAX_THROUGHPUT_DEFAULT; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Max Throughput out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.MaxThroughput)); + } + else + pAd->StaCfg.WfdCfg.MaxThroughput = Throughput; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Max Throughput = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.MaxThroughput)); + + return TRUE; +} + +INT Set_WfdLocalIp_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg; + UINT32 ip_addr; + + rtinet_aton(arg, &ip_addr); + printk("IP = %04x\n", ip_addr); + pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[0] = WFD_LOCAL_IP_ADDR_VERSION_IPV4; + RTMPMoveMemory(&pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[1], &ip_addr, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: local IP Address = %d.%d.%d.%d\n", __FUNCTION__, + pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[1], + pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[2], + pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[3], + pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[4])); + + return TRUE; +} + +INT Set_PeerRtspPort_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg; + UINT32 ip_addr; + + MAC_TABLE_ENTRY *pEntry; + USHORT RtspPort = WFD_RTSP_DEFAULT_PORT; + UCHAR P2pIdx = P2P_NOT_FOUND; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + INT i; + +#ifdef DOT11Z_TDLS_SUPPORT + i = -1; + if (pAd->StaCfg.TdlsInfo.bTDLSCapable && pAd->StaCfg.WfdCfg.PC == WFD_PC_TDLS) + { + PRT_802_11_TDLS pTDLS = NULL; + DBGPRINT(RT_DEBUG_TRACE, ("%s - TDLS peer rtsp port get...\n", __FUNCTION__)); + for (i = MAX_NUM_OF_TDLS_ENTRY - 1; i >= 0; i--) + { + if ((pAd->StaCfg.TdlsInfo.TDLSEntry[i].Valid) && (pAd->StaCfg.TdlsInfo.TDLSEntry[i].Status == TDLS_MODE_CONNECTED)) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[i]; + RtspPort = pTDLS->WfdEntryInfo.rtsp_port; + DBGPRINT(RT_DEBUG_TRACE, ("TDLS Entry[%d][%02x:%02x:%02x:%02x:%02x:%02x]\n", i, PRINT_MAC(pTDLS->MacAddr))); + DBGPRINT(RT_DEBUG_TRACE, ("RTSP_PORT = %d.\n", pTDLS->WfdEntryInfo.rtsp_port)); + break; + } + } + + if ((RtspPort == 0) && (pTDLS != NULL)) + { + DBGPRINT(RT_DEBUG_ERROR, ("TDLS peer rtsp port is zero, search P2P Entry!\n", RtspPort)); + + P2pIdx = P2pGroupTabSearch(pAd, pTDLS->MacAddr); + if (P2pIdx != P2P_NOT_FOUND) + { + RtspPort = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.rtsp_port; + DBGPRINT(RT_DEBUG_TRACE, ("P2P Entry[%d][%02x:%02x:%02x:%02x:%02x:%02x]\n", P2pIdx, PRINT_MAC(pTDLS->MacAddr))); + DBGPRINT(RT_DEBUG_TRACE, ("RTSP_PORT = %d.\n", pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.rtsp_port)); + if (RtspPort == 0) + RtspPort = WFD_RTSP_DEFAULT_PORT; + } + else + { + RtspPort = WFD_RTSP_DEFAULT_PORT; + DBGPRINT(RT_DEBUG_ERROR, ("OID_802_11_P2P_PEER_RTSP_PORT::P2P not found, use default RTSP port\n")); + } + } + } + if (i < 0) +#endif /* DOT11Z_TDLS_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - P2P peer rtsp port get...\n", __FUNCTION__)); + if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)) + { + for (i=0; iMacTab.Content[i]; + if (IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry)) + { + P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr); + DBGPRINT(RT_DEBUG_TRACE, ("P2P Entry[%d][%02x:%02x:%02x:%02x:%02x:%02x]\n", pEntry->P2pInfo.p2pIndex, PRINT_MAC(pEntry->Addr))); + DBGPRINT(RT_DEBUG_TRACE, ("RTSP_PORT = %d.\n", pAd->P2pTable.Client[pEntry->P2pInfo.p2pIndex].WfdEntryInfo.rtsp_port)); + if (P2pIdx != P2P_NOT_FOUND) + RtspPort = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.rtsp_port; + else + { + RtspPort = WFD_RTSP_DEFAULT_PORT; + DBGPRINT(RT_DEBUG_ERROR, ("OID_802_11_P2P_PEER_RTSP_PORT::P2P not found, use default RTSP port\n")); + } + if (pEntry->P2pInfo.p2pIndex < MAX_P2P_GROUP_SIZE) + P2PPrintP2PEntry(pAd, pEntry->P2pInfo.p2pIndex); + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("OID_802_11_P2P_PEER_RTSP_PORT bssid: %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pP2PCtrl->CurrentAddress))); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_PEER_RTSP_PORT (=%d)\n", RtspPort)); + + return TRUE; +} + + +VOID WfdMakeWfdIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR PacketType, + OUT PUCHAR pOutBuf, + OUT PULONG pIeLen) +{ + PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg; + UCHAR WfdIEFixed[6] = {0xdd, 0x0c, 0x50, 0x6f, 0x9a, 0x0a}; /* Length will be modified later */ + PUCHAR pData, pBuf; + ULONG TempLen; + ULONG Len = 0; + INT i = 0; + + pData = pOutBuf; + *pIeLen = 0; + + if (!pWFDCtrl->bWfdEnable) + return; + + RTMPMoveMemory(pData, &WfdIEFixed[0], 6); + pData += 6; + Len += 6; + + /* To append to WFD Device Information Subelement */ + TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_DEVICE_INFO, NULL, pData, ACTION_WIFI_DIRECT); + DBGPRINT(RT_DEBUG_INFO, ("%s(%d) ---->\n", __FUNCTION__, TempLen)); + for (i=0; i\n", __FUNCTION__, TempLen)); + for (i=0; i\n", __FUNCTION__, TempLen)); + for (i=0; i\n", __FUNCTION__, TempLen)); + for (i=0; iStaCfg.WfdCfg; + PUCHAR pDest; + ULONG Length, tmpValue = 0; + USHORT EidLen = 0; + + pDest = pOutBuffer; + RTMPZeroMemory(pDest, 255); + *pDest = SubId; + pDest += 1; + Length = 0; + + switch (SubId) + { + case SUBID_WFD_DEVICE_INFO: + { + WFD_DEVICE_INFO DevInfo; + PUSHORT pDevInfo = &DevInfo; + + RTMPZeroMemory(&DevInfo, sizeof(WFD_DEVICE_INFO)); + + EidLen = SUBID_WFD_DEVICE_INFO_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + DevInfo.DeviceType = pWFDCtrl->DeviceType; + DevInfo.SourceCoupled = pWFDCtrl->SourceCoupled; + DevInfo.SinkCoupled = pWFDCtrl->SinkCoupled; + DevInfo.SessionAvail = pWFDCtrl->SessionAvail; + DevInfo.WSD = pWFDCtrl->WSD; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + DevInfo.PC = pWFDCtrl->PC; + else + DevInfo.PC = WFD_PC_P2P; + DevInfo.CP = pWFDCtrl->CP; + DevInfo.TimeSync = pWFDCtrl->TimeSync; + /* RTMPMoveMemory(pDest + 1, &DevInfo, sizeof(WFD_DEVICE_INFO)); */ + tmpValue = cpu2be16(*pDevInfo); + RTMPMoveMemory((pDest + 2), &tmpValue, 2); + tmpValue = cpu2be16(pWFDCtrl->RtspPort); + RTMPMoveMemory((pDest + 4), &tmpValue, 2); + tmpValue = cpu2be16(pWFDCtrl->MaxThroughput); + RTMPMoveMemory((pDest + 6), &tmpValue, 2); + Length = 9; + break; + } + case SUBID_WFD_ASSOCIATED_BSSID: + { + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_ASSOCIATED_BSSID_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + if (!NdisEqualMemory(AllZero, pAd->CommonCfg.Bssid, MAC_ADDR_LEN) && + (Action == ACTION_GAS_INITIAL_RSP)) + { + RTMPMoveMemory(pDest + 2, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + } + } + else + { + if (!NdisEqualMemory(AllZero, pAd->CommonCfg.Bssid, MAC_ADDR_LEN)) + { + EidLen = SUBID_WFD_ASSOCIATED_BSSID_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + RTMPMoveMemory(pDest + 2, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + Length = EidLen + 3; + } + } + break; + } + case SUBID_WFD_AUDIO_FORMATS: + { + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_AUDIO_FORMATS_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_VIDEO_FORMATS: + { + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_VIDEO_FORMATS_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_3D_VIDEO_FORMATS: + { + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_3D_VIDEO_FORMATS_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_CONTENT_PROTECTION: + { + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_CONTENT_PROTECTION_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_COUPLED_SINK_INFO: + { +// if ((pWFDCtrl->DeviceType != WFD_SOURCE ) && (pWFDCtrl->SinkCoupled == WFD_COUPLED_SUPPORT)) + { + WFD_COUPLED_SINK_INFO SinkInfo; + + RTMPZeroMemory(&SinkInfo, sizeof(WFD_COUPLED_SINK_INFO)); + EidLen = SUBID_WFD_COUPLED_SINK_INFO_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + SinkInfo.CoupledStat = pWFDCtrl->CoupledSinkStatus.CoupledStat; + RTMPMoveMemory(pDest + 2, &SinkInfo, sizeof(WFD_COUPLED_SINK_INFO)); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_EXTENDED_CAP: + { + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_EXTENDED_CAP_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_LOCAL_IP_ADDR: + { + if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP)) + { + EidLen = SUBID_WFD_LOCAL_IP_ADDR_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + Length = EidLen + 3; + } + else + { + EidLen = SUBID_WFD_LOCAL_IP_ADDR_LEN; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + RTMPMoveMemory(pDest + 2, &pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie, SUBID_WFD_LOCAL_IP_ADDR_LEN); + Length = EidLen + 3; + } + break; + } + case SUBID_WFD_SESSION_INFO: + { + INT i = 0, NumOfDev = 0; + UCHAR P2pIdx = P2P_NOT_FOUND; + PRT_P2P_TABLE Tab = &pAd->P2pTable; + + if (Action == ACTION_WIFI_DIRECT) + { + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr); + + if ((P2pIdx < MAX_P2P_GROUP_SIZE) && (Tab->Client[P2pIdx].WfdEntryInfo.bWfdClient == TRUE)) + NumOfDev++; + } + + EidLen = 24*NumOfDev; + tmpValue = cpu2be16(EidLen); + RTMPMoveMemory(pDest, &tmpValue, 2); + DBGPRINT(RT_DEBUG_INFO, ("%s:: NumOfDev = %d, Len = %d\n", __FUNCTION__, NumOfDev, *pDest)); + + pDest+=2; + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr); + + if ((P2pIdx < MAX_P2P_GROUP_SIZE) && (Tab->Client[P2pIdx].WfdEntryInfo.bWfdClient == TRUE)) + { + INT j = 0; + WFD_SESSION_INFO SessionInfo; + + RTMPZeroMemory(&SessionInfo, sizeof(WFD_SESSION_INFO)); + + SessionInfo.Length = 23; + RTMPMoveMemory(&SessionInfo.DeviceAddr[0], &pAd->P2pTable.Client[P2pIdx].addr[0], MAC_ADDR_LEN); + RTMPMoveMemory(&SessionInfo.Bssid[0], &pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.assoc_addr[0], MAC_ADDR_LEN); + /* Below is the WFD Device Information */ + SessionInfo.WfdDevInfo.DeviceType = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_devive_type; + SessionInfo.WfdDevInfo.SourceCoupled = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.source_coupled; + SessionInfo.WfdDevInfo.SinkCoupled = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.sink_coupled; + SessionInfo.WfdDevInfo.SessionAvail = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.session_avail; + SessionInfo.WfdDevInfo.WSD = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_service_discovery; + SessionInfo.WfdDevInfo.PC = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_PC; + SessionInfo.WfdDevInfo.TimeSync = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_time_sync; + SessionInfo.MaxThroughput = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.max_throughput; + SessionInfo.CoupledSinkInfo = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.coupled_sink_status; + + /* + So far we cannot know the address of coupled devices, + the coupled address will be filled "0" until WiFi Display spec. is ready for this part. + */ + RTMPMoveMemory(&SessionInfo.CoupledPeerAddr[0], &pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.coupled_peer_addr[0], MAC_ADDR_LEN); + RTMPMoveMemory(pDest, &SessionInfo, sizeof(WFD_SESSION_INFO)); + + for (j = 0; j < 24; j++) + DBGPRINT(RT_DEBUG_INFO, ("%02x ", *(pDest+j))); + DBGPRINT(RT_DEBUG_INFO, ("\n")); + + pDest += 24; + } + } + + Length = 24*NumOfDev + 3; + } + break; + } + case SUBID_WFD_ALTERNATE_MAC_ADDR: + { + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + if ((Action == ACTION_GAS_INITIAL_REQ) || + (Action == ACTION_GAS_INITIAL_RSP) || + (Action == ACTION_WIFI_DIRECT)) + { + EidLen = SUBID_WFD_ALTERNATE_MAC_ADDR_LEN; + *((PUSHORT) (pDest)) = cpu2be16(EidLen); + Length = EidLen + 3; + if (!NdisEqualMemory(AllZero, pAd->CurrentAddress, MAC_ADDR_LEN) && + (Action == ACTION_GAS_INITIAL_RSP)) + { + RTMPMoveMemory(pDest + 2, pAd->CurrentAddress, MAC_ADDR_LEN); + } + } + else + { + if (!NdisEqualMemory(AllZero, pAd->CurrentAddress, MAC_ADDR_LEN)) + { + EidLen = SUBID_WFD_ALTERNATE_MAC_ADDR_LEN; + *((PUSHORT) (pDest)) = cpu2be16(EidLen); + RTMPMoveMemory(pDest + 2, pAd->CurrentAddress, MAC_ADDR_LEN); + Length = EidLen + 3; + } + } + break; + } + default: + *pDest = 0; + Length = 0; + break; + } + + return Length; +} + +VOID WfdParseSubElmt( + IN PRTMP_ADAPTER pAd, + IN PWFD_ENTRY_INFO pWfdEntryInfo, + IN VOID *Msg, + IN ULONG MsgLen) +{ + PWFD_COUPLED_SINK_INFO pSinkInfo; + PWFD_DEVICE_INFO pWfd_info; + WFD_DEVICE_INFO DevInfo; + PP2PEID_STRUCT pWfdEid; + PEID_STRUCT pEid; + PUCHAR pWfdIe = NULL; + ULONG AccuWfdIELen; + ULONG AccuIeLen = 0; + ULONG Length = 0; + ULONG AttriLen; + UCHAR offset; + BOOLEAN bTdlsEntry = FALSE; + + DBGPRINT(RT_DEBUG_INFO, ("%s ----->\n", __FUNCTION__)); + +//QQ TBD, p2p widi need to parse rtsp port! + { + if ((!pAd->StaCfg.WfdCfg.bWfdEnable) || (MsgLen == 0)) + return; + } + +// hex_dump("WfdParseSubElmt::", Msg, MsgLen); + pEid = (PEID_STRUCT)Msg; + AccuIeLen = pEid->Len + 2; +// printk("MsgLen = %d. AccuIeLen = %d.\n", MsgLen, AccuIeLen); + while ((ULONG)(AccuIeLen) <= MsgLen) + { + if (RTMPEqualMemory(&pEid->Octet[0], WIFIDISPLAY_OUI, 4)) + { + /* Get Request content capability */ + pWfdIe = pWfdEid = (PP2PEID_STRUCT) &pEid->Octet[4]; + AccuWfdIELen = pEid->Len; +// printk("AccuWfdIeLen = %d. EidLen = %04x\n", AccuWfdIELen, pEid->Len); + /* The value of AccuP2PIELen shall reduce the length of OUI (4) */ + AccuWfdIELen -= 4; + + AttriLen = pWfdEid->Len[1] + (pWfdEid->Len[0] << 8); + Length = 0; +// printk("AttriLen = %d. WfdEid = %d. WfdEidLen = %x %x\n", AttriLen, pWfdEid->Eid, pWfdEid->Len[1], pWfdEid->Len[0]); + pWfdEntryInfo->bWfdClient = TRUE; /* Set the P2P client as the WFD device */ + +// while (Length <=(Length + 3 + AttriLen) <= AccuWfdIELen) + while (Length <= AccuWfdIELen) + { +// printk(">> Eid = %d.\n", pWfdEid->Eid); + switch (pWfdEid->Eid) + { + case SUBID_WFD_DEVICE_INFO: + { + pWfd_info = &(pWfdEid->Octet[0]); + RTMPMoveMemory(&DevInfo, pWfdIe, sizeof(WFD_DEVICE_INFO)); + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_device_info_ie, pWfdEid->Octet, SUBID_WFD_DEVICE_INFO_LEN); + cpu2le16(&DevInfo); + + pWfdEntryInfo->wfd_devive_type = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 0) & 0x3); + pWfdEntryInfo->source_coupled = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 2) & 0x1); + pWfdEntryInfo->sink_coupled = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 3) & 0x1); + pWfdEntryInfo->session_avail = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 4) & 0x3); + pWfdEntryInfo->wfd_service_discovery = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 6) & 0x1); + pWfdEntryInfo->wfd_PC = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 7) & 0x1); + pWfdEntryInfo->wfd_CP = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 8) & 0x1); + pWfdEntryInfo->wfd_time_sync = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 9) & 0x1); + pWfdEntryInfo->sink_audio_unsupport = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 10) & 0x1); + pWfdEntryInfo->source_audio_only= ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 11) & 0x1); + pWfdEntryInfo->tdls_persistent_group = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 12) & 0x1); + pWfdEntryInfo->rtsp_port = be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[2]))); + pWfdEntryInfo->max_throughput = be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[4]))); + + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_DEVICE_INFO\n", __FUNCTION__)); + break; + } + case SUBID_WFD_ASSOCIATED_BSSID: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_associate_bssid_ie, pWfdEid->Octet, SUBID_WFD_ASSOCIATED_BSSID_LEN); + RTMPMoveMemory(&pWfdEntryInfo->assoc_addr, pWfdEid->Octet, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_ASSOCIATED_BSSID\n", __FUNCTION__)); + break; + } + case SUBID_WFD_AUDIO_FORMATS: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_audio_format_ie, pWfdEid->Octet, SUBID_WFD_AUDIO_FORMATS_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_AUDIO_FORMATS\n", __FUNCTION__)); + break; + } + case SUBID_WFD_VIDEO_FORMATS: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_video_format_ie, pWfdEid->Octet, SUBID_WFD_VIDEO_FORMATS_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_VIDEO_FORMATS\n", __FUNCTION__)); + break; + } + case SUBID_WFD_3D_VIDEO_FORMATS: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_3d_video_format_ie, pWfdEid->Octet, SUBID_WFD_3D_VIDEO_FORMATS_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_3D_VIDEO_FORMATS\n", __FUNCTION__)); + break; + } + case SUBID_WFD_CONTENT_PROTECTION: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_content_proctection, pWfdEid->Octet, SUBID_WFD_CONTENT_PROTECTION_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_CONTENT_PROTECTION\n", __FUNCTION__)); + break; + } + case SUBID_WFD_COUPLED_SINK_INFO: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_couple_sink_info_ie, pWfdEid->Octet, SUBID_WFD_COUPLED_SINK_INFO_LEN); + RTMPMoveMemory(&pWfdEntryInfo->coupled_sink_status, pWfdEid->Octet, SUBID_WFD_COUPLED_SINK_INFO_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_COUPLED_SINK_INFO\n", __FUNCTION__)); + break; + } + case SUBID_WFD_EXTENDED_CAP: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_extent_capability_ie, &pWfdEid->Octet, SUBID_WFD_EXTENDED_CAP_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_EXTENDED_CAP\n", __FUNCTION__)); + break; + } + case SUBID_WFD_LOCAL_IP_ADDR: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_local_ip_ie, &pWfdEid->Octet, SUBID_WFD_LOCAL_IP_ADDR_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_LOCAL_IP_ADDR\n", __FUNCTION__)); + break; + } + case SUBID_WFD_SESSION_INFO: + { + /* TODO : allocate memory to store the parsed WFD device tables */ + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_session_info_ie, &pWfdEid->Octet, SUBID_WFD_DEVICE_INFO_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_SESSION_INFO\n", __FUNCTION__)); + break; + } + case SUBID_WFD_ALTERNATE_MAC_ADDR: + { + RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_alternate_mac_addr_ie, &pWfdEid->Octet, SUBID_WFD_ALTERNATE_MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_ALTERNATE_MAC_ADDR\n", __FUNCTION__)); + break; + } + default: + DBGPRINT(RT_DEBUG_ERROR, (" SUBID_WFD_ unknown Eid = %x \n", pWfdEid->Eid)); + hex_dump("WfdParseSubElement::", Msg, MsgLen); + break; + } +// printk("<< Length = %d. AttriLen = %d. AccuWfdIELen = %d.\n", Length, AttriLen, AccuWfdIELen); + Length = Length + 3 + AttriLen; /* Eid[1] + Len[2] + content[Len] */ +// printk(">> Length = %d. AttriLen = %d. AccuWfdIELen = %d.\n", Length, AttriLen, AccuWfdIELen); + if (Length >= AccuWfdIELen) + break; + + pWfdEid = (PP2PEID_STRUCT)((UCHAR*)pWfdEid + 3 + AttriLen); + AttriLen = pWfdEid->Len[1] + (pWfdEid->Len[0] << 8); + } + + } + /* Already reach the final IE and stop finding next Eid. */ + if (AccuIeLen >= MsgLen) + break; + + /* Forward buffer to next pEid */ + if (RTMPEqualMemory(&pEid->Octet[0], WIFIDISPLAY_OUI, 4)) + { + pEid = (PEID_STRUCT)((UCHAR*)pEid + pEid->Len + 2); + } + + /* + Since we get the next pEid, + Predict the accumulated IeLen after adding the next pEid's length. + The accumulated IeLen is for checking length. + */ + if (RTMPEqualMemory(&pEid->Octet[0], WIFIDISPLAY_OUI, 4)) + { + AccuIeLen += (pEid->Len + 2); + } + } + return; +} + +VOID WfdCfgInit( + + IN PRTMP_ADAPTER pAd) +{ + PRT_WFD_CONFIG pWfdcfg = &pAd->StaCfg.WfdCfg; + + RTMPZeroMemory(&pAd->StaCfg.WfdCfg, sizeof(RT_WFD_CONFIG)); + pWfdcfg->bWfdEnable = FALSE; + pWfdcfg->DeviceType = WFD_PRIMARY_SINK; + pWfdcfg->SessionAvail = WFD_SESSION_AVAILABLE; + pWfdcfg->PeerSessionAvail = WFD_SESSION_AVAILABLE; + pWfdcfg->PeerPC = WFD_PC_TDLS; + pWfdcfg->TdlsSecurity = WFD_TDLS_STRONG_SECURITY; + pWfdcfg->RtspPort = WFD_RTSP_DEFAULT_PORT; +} +#endif /* WFD_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wnm.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wnm.c new file mode 100644 index 000000000..df75e382e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wnm.c @@ -0,0 +1,2443 @@ +/* + *************************************************************************** + * 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: + wnm.c + + Abstract: + Wireless Network Management(WNM) + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" +static UCHAR ZERO_IP_ADDR[4] = {0x00, 0x00, 0x00, 0x00}; + +static char SolicitedMulticastAddr[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xff}; +static char AllNodeLinkLocalMulticastAddr[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01}; + +static char link_local[] = {0xfe, 0x80}; +#define IP_PROTO_HOPOPTS 0 /* IP6 hop-by-hop options - RFC1883 */ +#define IP_PROTO_ROUTING 43 /* IP6 routing header */ +#define IP_PROTO_FRAGMENT 44 /* IP6 fragmentation header */ +#define IP_PROTO_AH 51 /* Authentication Header for IPv6 - RFC2402*/ +#define IP_PROTO_DSTOPTS 60 /* IP6 destination options - RFC1883 */ + +#ifndef MAT_SUPPORT +#define IS_UNSPECIFIED_IPV6_ADDR(_addr) \ + (!((_addr).ipv6_addr32[0] | (_addr).ipv6_addr32[1] | (_addr).ipv6_addr32[2] | (_addr).ipv6_addr32[3])) +#endif + +#ifdef CONFIG_AP_SUPPORT +void wext_send_btm_query_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_query, u16 btm_query_len) +{ + struct btm_query_data *query_data; + u16 buflen = 0; + char *buf; + + buflen = sizeof(*query_data) + btm_query_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + query_data = (struct btm_query_data *)buf; + query_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(query_data->peer_mac_addr, peer_mac_addr, 6); + query_data->btm_query_len = btm_query_len; + memcpy(query_data->btm_query, btm_query, btm_query_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_BTM_QUERY, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + +void SendBTMQueryEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_query, UINT16 btm_query_len, UINT8 ipc_type) +{ + if (ipc_type == RA_WEXT) { + wext_send_btm_query_event(net_dev, + peer_mac_addr, + btm_query, + btm_query_len); + } +} + + +void wext_send_btm_cfm_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_rsp, u16 btm_rsp_len) +{ + + struct btm_rsp_data *rsp_data; + u16 buflen = 0; + char *buf; + + + buflen = sizeof(*rsp_data) + btm_rsp_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + rsp_data = (struct btm_rsp_data *)buf; + rsp_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(rsp_data->peer_mac_addr, peer_mac_addr, 6); + rsp_data->btm_rsp_len = btm_rsp_len; + memcpy(rsp_data->btm_rsp, btm_rsp, btm_rsp_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_BTM_RSP, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + +void SendBTMConfirmEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_rsp, UINT16 btm_rsp_len, UINT8 ipc_type) +{ + if (ipc_type == RA_WEXT) { + wext_send_btm_cfm_event(net_dev, + peer_mac_addr, + btm_rsp, + btm_rsp_len); + } +} + +void wext_send_proxy_arp_event(PNET_DEV net_dev, + const char *source_mac_addr, + const char *source_ip_addr, + const char *target_mac_addr, + const char *target_ip_addr, + u8 ip_type, + u8 from_ds, + unsigned char IsDAD) + +{ + struct proxy_arp_entry *arp_entry; + u16 varlen = 0, buflen = 0; + char *buf; + + if (ip_type == IPV4) + varlen += 8; + else if (ip_type == IPV6) + varlen += 32; + + //for IsDAD, add one more byte + varlen++; + + buflen = sizeof(*arp_entry) + varlen; + + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + arp_entry = (struct proxy_arp_entry *)buf; + + arp_entry->ifindex = RtmpOsGetNetIfIndex(net_dev); + arp_entry->ip_type = ip_type; + arp_entry->from_ds = from_ds; + arp_entry->IsDAD = IsDAD; + memcpy(arp_entry->source_mac_addr, source_mac_addr, 6); + memcpy(arp_entry->target_mac_addr, target_mac_addr, 6); + + if (ip_type == IPV4) { + memcpy(arp_entry->ip_addr, source_ip_addr, 4); + memcpy(arp_entry->ip_addr + 4, target_ip_addr, 4); + } else if (ip_type == IPV6) { + memcpy(arp_entry->ip_addr, source_ip_addr, 16); + memcpy(arp_entry->ip_addr + 16, target_ip_addr, 16); + } else + printk("error not such ip type packet\n"); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_PROXY_ARP, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + + +void SendProxyARPEvent(PNET_DEV net_dev, + const char *source_mac_addr, + const char *source_ip_addr, + const char *target_mac_addr, + const char *target_ip_addr, + u8 ip_type, + u8 from_ds, + unsigned char IsDAD) + +{ + wext_send_proxy_arp_event(net_dev, + source_mac_addr, + source_ip_addr, + target_mac_addr, + target_ip_addr, + ip_type, + from_ds, + IsDAD); +} + + +BOOLEAN IsGratuitousARP(IN RTMP_ADAPTER *pAd, + IN UCHAR *pData, + IN UCHAR *DAMacAddr, + IN struct _MULTISSID_STRUCT *pMbss) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UCHAR *SenderIP; + UCHAR *TargetIP; + + UCHAR BroadcastMac[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + UINT16 ARPOperation; + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + PUCHAR SourceMACAddr; + BOOLEAN IsDrop = FALSE; + INT32 Ret; + + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_ARP) + { + /* + * Check if Gratuitous ARP, Sender IP equal Target IP + */ + SourceMACAddr = Pos + 8; + SenderIP = Pos + 14; + TargetIP = Pos + 24; + + if ((NdisCmpMemory(SenderIP, TargetIP, 4) == 0) && (NdisCmpMemory(DAMacAddr, BroadcastMac, 6) == 0)) + + { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is GratuitousARP\n")); + return TRUE; + } + +#ifdef CONFIG_HOTSPOT_R2 + Pos += 6; + NdisMoveMemory(&ARPOperation, Pos, 2); + ARPOperation = OS_NTOHS(ARPOperation); + Pos += 2; + + if (ARPOperation == 0x0002) + { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if ((IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, SenderIP)) && (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, SourceMACAddr) == FALSE)) + { + IsDrop = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (IsDrop == TRUE) + { + printk("Drop pkt, ip not qeual mac\n"); + return TRUE; + } + } +#endif + } + + return FALSE; +} + + +BOOLEAN IsUnsolicitedNeighborAdver(PRTMP_ADAPTER pAd, + PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + Pos += 24; + + if (RTMPEqualMemory(Pos, AllNodeLinkLocalMulticastAddr, 16)) + { + Pos += 16; + + /* Check if neighbor advertisement type */ + if (*Pos == 0x88) + { + Pos += 4; + + /* Check if solicited flag set to 0 */ + if ((*Pos & 0x40) == 0x00) + { + DBGPRINT(RT_DEBUG_OFF, ("The Packet is UnsolicitedNeighborAdver\n")); + Pos += 4; + return TRUE; + } + } + } + + } + + return FALSE; +} + + +BOOLEAN IsIPv4ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UINT16 ARPOperation; + UCHAR *SenderIP; + UCHAR *TargetIP; + + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_ARP) + { + Pos += 6; + NdisMoveMemory(&ARPOperation, Pos, 2); + ARPOperation = OS_NTOHS(ARPOperation); + Pos += 2; + + if (ARPOperation == 0x0001) + { + SenderIP = Pos + 6; + TargetIP = Pos + 16; + /* ARP Request */ + if (NdisCmpMemory(SenderIP, TargetIP, 4) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("IPv4ProxyARPCandidate\n")); + return TRUE; + } + } + } + + return FALSE; +} + + +BOOLEAN IsIpv6DuplicateAddrDetect(PRTMP_ADAPTER pAd, + PUCHAR pData, + PUCHAR pOffset) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + RT_IPV6_ADDR *pIPv6Addr; + UCHAR *pData_offset = Pos; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + + INT32 PayloadLen = 0;//((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + Pos += 8; + pIPv6Addr = (RT_IPV6_ADDR *)Pos; + + if (IS_UNSPECIFIED_IPV6_ADDR(*pIPv6Addr)) + { + Pos += 16; + if (RTMPEqualMemory(Pos, SolicitedMulticastAddr, 13)) + { + Pos += 16; + + if ((NextHeader == IP_PROTO_HOPOPTS) || (NextHeader == IP_PROTO_ROUTING) || (NextHeader == IP_PROTO_FRAGMENT) || (NextHeader == IP_PROTO_AH) || (NextHeader == IP_PROTO_DSTOPTS)) + { + IsExtenHeader = 1; + + do + { + printk("IsIpv6DuplicateAddrDetect: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + + /* Check if neighbor solicitation */ + if (*Pos == 0x87) + { + DBGPRINT(RT_DEBUG_OFF, ("THe Packet is for Ipv6DuplicateAddrDetect\n")); + *pOffset = Pos-pData_offset+8; + return TRUE; + } + } + } + } + + return FALSE; +} + +BOOLEAN IsIPv6ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + + INT32 PayloadLen = 0; //((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + Pos += 8; + + //if (!IS_UNSPECIFIED_IPV6_ADDR(*pIPv6Addr)) + //{ + Pos += 16; + if (RTMPEqualMemory(Pos, SolicitedMulticastAddr, 13)) + { + Pos+= 16; + if ((NextHeader == IP_PROTO_HOPOPTS) || (NextHeader == IP_PROTO_ROUTING) || (NextHeader == IP_PROTO_FRAGMENT) || (NextHeader == IP_PROTO_AH) || (NextHeader == IP_PROTO_DSTOPTS)) + { + IsExtenHeader = 1; + + do + { + printk("IsIPv6ProxyARPCandidate: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + + /* Check if neighbor solicitation */ + if (*Pos == 0x87) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is IPv6ProxyARPCandidate\n")); + return TRUE; + } + } + //} + } + + return FALSE; +} + +//JERRY +BOOLEAN IsIPv6DHCPv6Solicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType, SrcPort, DstPort; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0; //((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + if ((NextHeader != IP_PROTO_HOPOPTS) && (NextHeader != IP_PROTO_ROUTING) && (NextHeader != IP_PROTO_FRAGMENT) && (NextHeader != IP_PROTO_AH) && (NextHeader != IP_PROTO_DSTOPTS)) + { + if (NextHeader == 0x11) + { + Pos += 40; + } + else + return FALSE; + } + else + { + IsExtenHeader = 1; + Pos += 40; + + do + { + printk("IsIPv6DHCPv6Solicitation: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + /* Check if DHCPv6 solicitation */ + { + unsigned char *type = (unsigned char *)(Pos+8); + + if ((*type == 1) || (*type == 4)) + { + NdisMoveMemory(&SrcPort, Pos, 2); + SrcPort = OS_NTOHS(SrcPort); + NdisMoveMemory(&DstPort, Pos+2, 2); + DstPort = OS_NTOHS(DstPort); + + if ((SrcPort == 546) && (DstPort == 547)) + { + DBGPRINT(RT_DEBUG_OFF, ("The Packet is DHCPv6 Solicitation,msg type=%d\n", *type)); + return TRUE; + } + } + } + } + + return FALSE; +} + +BOOLEAN IsIPv6RouterSolicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0; //((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + if ((NextHeader != IP_PROTO_HOPOPTS) && (NextHeader != IP_PROTO_ROUTING) && (NextHeader != IP_PROTO_FRAGMENT) && (NextHeader != IP_PROTO_AH) && (NextHeader != IP_PROTO_DSTOPTS)) + { + Pos += 40; + } + else + { + IsExtenHeader = 1; + Pos += 40; + + do + { + printk("IsIPv6RouterSolicitation: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + + /* Check if router solicitation */ + if (*Pos == 0x85) + { + DBGPRINT(RT_DEBUG_OFF, ("The Packet is IPv6 Router Solicitation\n")); + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN IsIPv6RouterAdvertisement(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN PUCHAR pOffset) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UCHAR *pData_offset = NULL; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + + INT32 PayloadLen = 0; + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + if ((NextHeader != IP_PROTO_HOPOPTS) && + (NextHeader != IP_PROTO_ROUTING) && + (NextHeader != IP_PROTO_FRAGMENT) && + (NextHeader != IP_PROTO_AH) && + (NextHeader != IP_PROTO_DSTOPTS)) + { + Pos += 40; + pData_offset = Pos; + } + else + { + IsExtenHeader = 1; + Pos += 40; + pData_offset = Pos; + + do + { + DBGPRINT(RT_DEBUG_TRACE, ("IsIPv6RouterAdvertisement: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader)); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + + /* Check if router advertisement */ + if (*Pos == 0x86) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is IPv6 Router Advertisement\n")); + *pOffset = Pos-pData_offset; + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN IsTDLSPacket(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == 0x890d) + { + DBGPRINT(RT_DEBUG_TRACE, ("THe Packet is TDLS\n")); + return TRUE; + } + + return FALSE; +} + + +UINT32 IPv4ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss) +{ + + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + UINT32 TableLen = 0; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + TableLen += sizeof(PROXY_ARP_IPV4_UNIT); + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + return TableLen; +} + +UINT32 IPv6ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + UINT32 TableLen = 0; + INT32 Ret; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + TableLen += sizeof(PROXY_ARP_IPV6_UNIT); + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + return TableLen; +} + +BOOLEAN GetIPv4ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + PUCHAR *ProxyARPTable) +{ + + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + PROXY_ARP_IPV4_UNIT *ProxyARPUnit = (PROXY_ARP_IPV4_UNIT *)(*ProxyARPTable); + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + NdisMoveMemory(ProxyARPUnit->TargetMACAddr, ProxyARPEntry->TargetMACAddr, MAC_ADDR_LEN); + NdisMoveMemory(ProxyARPUnit->TargetIPAddr, ProxyARPEntry->TargetIPAddr, 4); + ProxyARPUnit++; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + return TRUE; +} + +BOOLEAN GetIPv6ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + PUCHAR *ProxyARPTable) +{ + + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + PROXY_ARP_IPV6_UNIT *ProxyARPUnit = (PROXY_ARP_IPV6_UNIT *)(*ProxyARPTable); + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + NdisMoveMemory(ProxyARPUnit->TargetMACAddr, ProxyARPEntry->TargetMACAddr, MAC_ADDR_LEN); + ProxyARPUnit->TargetIPType = ProxyARPEntry->TargetIPType; + NdisMoveMemory(ProxyARPUnit->TargetIPAddr, ProxyARPEntry->TargetIPAddr, 16); + ProxyARPUnit++; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + return TRUE; +} + +UINT32 AddIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN MULTISSID_STRUCT *pMbss, + PUCHAR pTargetMACAddr, + PUCHAR pTargetIPAddr) +{ + + int i = 0, find_list = 0; + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if ((pTargetIPAddr[0] == 0) && (pTargetIPAddr[1] == 0)) { + DBGPRINT(RT_DEBUG_ERROR, ("Drop invalid IP Addr:%d.%d.%d.%d\n", pTargetIPAddr[0], pTargetIPAddr[1], pTargetIPAddr[2], pTargetIPAddr[3])); + return FALSE; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr)) + { + //RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + //return FALSE; + find_list = 1; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (find_list == 0) + os_alloc_mem(NULL, (UCHAR **)&ProxyARPEntry, sizeof(*ProxyARPEntry)); + + if (!ProxyARPEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + NdisMoveMemory(ProxyARPEntry->TargetMACAddr, pTargetMACAddr, 6); + NdisMoveMemory(ProxyARPEntry->TargetIPAddr, pTargetIPAddr, 4); + + for (i = 0; i < 4; i++) + printk("pTargetIPv4Addr[%i] = %x\n", i, pTargetIPAddr[i]); + + /* Add ProxyARP Entry to list */ + if (find_list == 0) + { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListAddTail(&pWNMCtrl->IPv4ProxyARPList, &ProxyARPEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + } + + + return TRUE; +} + +VOID RemoveIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN MULTISSID_STRUCT *pMbss, + PUCHAR pTargetMACAddr) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry, *ProxyARPEntryTmp; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + + DlListForEachSafe(ProxyARPEntry, ProxyARPEntryTmp, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (!ProxyARPEntry) + break; + + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr)) + { + //RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + //return FALSE; + DlListDel(&ProxyARPEntry->List); + os_free_mem(NULL, ProxyARPEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); +} + +UINT32 AddIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN MULTISSID_STRUCT *pMbss, + PUCHAR pTargetMACAddr, + PUCHAR pTargetIPAddr) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + INT32 Ret; + UINT8 i; + BOOLEAN IsDAD = FALSE; + PNET_DEV NetDev = pMbss->wdev.if_dev; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr) && + IPV6_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, pTargetIPAddr)) + { + + DBGPRINT(RT_DEBUG_OFF, ("%s, the Mac address and IPv6 Address exactly same as the one in List already!\n", __FUNCTION__)); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + return FALSE; + } + + if ((MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr) == FALSE) && + IPV6_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, pTargetIPAddr)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s, different Mac address use IPv6 address which already in List!\n", __func__)); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + IsDAD = TRUE; + + /*we got IPv6 DAD here, AP shall issue Neighbor Advertisement back to sender in below format */ + /* SenderMAC is the mac which in List, */ + /* DestMAC is multicast address e.g, 33:33:00:00:00:01 */ + /* SourceIP = TargetIP = TentativeIP, in this case is the IP which in List */ + /* DestIP = FF02::1 */ + SendProxyARPEvent(NetDev, + pTargetMACAddr, + ProxyARPEntry->TargetIPAddr, + ProxyARPEntry->TargetMACAddr, + ProxyARPEntry->TargetIPAddr, + IPV6, + FALSE, + IsDAD); + + return FALSE; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + os_alloc_mem(NULL, (UCHAR **)&ProxyARPEntry, sizeof(*ProxyARPEntry)); + + if (!ProxyARPEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + NdisMoveMemory(ProxyARPEntry->TargetMACAddr, pTargetMACAddr, 6); + + if (NdisEqualMemory(link_local, pTargetIPAddr, 2)) + ProxyARPEntry->TargetIPType = IPV6_LINK_LOCAL; + else + ProxyARPEntry->TargetIPType = IPV6_GLOBAL; + + NdisMoveMemory(ProxyARPEntry->TargetIPAddr, pTargetIPAddr, 16); + + for (i = 0; i < 6; i++) + printk("pTargetMACAddr[%i] = %x\n", i, pTargetMACAddr[i]); + + for (i = 0; i < 16; i++) + printk("pTargetIPv6Addr[%i] = %x\n", i, pTargetIPAddr[i]); + + /* Add ProxyARP Entry to list */ + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + DlListAddTail(&pWNMCtrl->IPv6ProxyARPList, &ProxyARPEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + return TRUE; +} + +VOID RemoveIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN MULTISSID_STRUCT *pMbss, + PUCHAR pTargetMACAddr) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry, *ProxyARPEntryTmp; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + + DlListForEachSafe(ProxyARPEntry, ProxyARPEntryTmp, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + if (!ProxyARPEntry) + break; + + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr)) + { + DlListDel(&ProxyARPEntry->List); + os_free_mem(NULL, ProxyARPEntry); + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); +} + +BOOLEAN IPv4ProxyARP(IN PRTMP_ADAPTER pAd, + IN MULTISSID_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PNET_DEV NetDev = pMbss->wdev.if_dev; + BOOLEAN IsFound = FALSE, InTable = FALSE; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + + PUCHAR SourceMACAddr = pData + 10; + PUCHAR SourceIPAddr = pData + 16; + PUCHAR TargetIPAddr = pData + 26; + INT32 Ret; + BOOLEAN IsDAD = FALSE; + PUCHAR TargetMACAddr = pData + 20; + UCHAR ALL_ZERO_BROADCAST_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, TargetIPAddr)) + { + IsFound = TRUE; + if ( + (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, SourceMACAddr) == FALSE) && + ((MAC_ADDR_EQUAL(TargetMACAddr, BROADCAST_ADDR) == TRUE) || + (MAC_ADDR_EQUAL(TargetMACAddr, ALL_ZERO_BROADCAST_ADDR) == TRUE)) && + (IPV4_ADDR_EQUAL(SourceIPAddr, ZERO_IP_ADDR) == TRUE) + ) { + //Mac address is not equal to the one which already in List. + //it's a DAD arp. + IsDAD = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("%s, Found DAD!!!!\n", __FUNCTION__)); + printk("found dad...\n"); + } + + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (IsFound) + { + /* ARP Probe and ARP Entry already Build and not DAD */ + if ((IsDAD == FALSE) && (IPV4_ADDR_EQUAL(SourceIPAddr, ZERO_IP_ADDR) == TRUE)) + return IsFound; + + /* Send proxy arp indication to daemon */ + SendProxyARPEvent(NetDev, + SourceMACAddr, + SourceIPAddr, + ProxyARPEntry->TargetMACAddr, + ProxyARPEntry->TargetIPAddr, + IPV4, + FromDS, + IsDAD); + + if ((IsDAD == FALSE) && (FromDS == FALSE)) { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, SourceIPAddr)) + { + InTable = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + if (InTable == FALSE) { + AddIPv4ProxyARPEntry(pAd, pMbss, SourceMACAddr, SourceIPAddr); + DBGPRINT(RT_DEBUG_ERROR, + ("%s, New Station take arp request, Learning ARP Entry from it\n", __func__)); + } + } + } + else + { + if ( + ((MAC_ADDR_EQUAL(TargetMACAddr, BROADCAST_ADDR) == TRUE) || + (MAC_ADDR_EQUAL(TargetMACAddr, ALL_ZERO_BROADCAST_ADDR) == TRUE)) && (FromDS == FALSE) + ) { + //waht if there is a new mac for List, and take BOARDCAST and ZERO_IP, + //it's a station take DAD packet to ask the network. + //In this case, AP shall learn the mac/ip mapping from it. + if (IPV4_ADDR_EQUAL(SourceIPAddr, ZERO_IP_ADDR) == TRUE) { + AddIPv4ProxyARPEntry(pAd, pMbss, SourceMACAddr, TargetIPAddr); + DBGPRINT(RT_DEBUG_ERROR, + ("%s, New Station take DAD to detect, Learning ARP Entry from it\n", __func__)); + } + else { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, SourceIPAddr)) + { + InTable = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + if (InTable == FALSE) { + AddIPv4ProxyARPEntry(pAd, pMbss, SourceMACAddr, SourceIPAddr); + DBGPRINT(RT_DEBUG_ERROR, + ("%s, New Station take arp request to detect, Learning ARP Entry from it\n", __func__)); + } + } + } + } + + return IsFound; +} + +BOOLEAN IPv6ProxyARP(IN PRTMP_ADAPTER pAd, + IN MULTISSID_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PNET_DEV NetDev = pMbss->wdev.if_dev; + BOOLEAN IsFound = FALSE; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + PUCHAR SourceMACAddr = pData + 68; + PUCHAR SourceIPAddr = pData + 10; + PUCHAR TargetIPAddr = pData + 50; + INT32 Ret; + + + BOOLEAN IsDAD = FALSE; + + //DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + if (IPV6_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, TargetIPAddr)) + { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (IsFound) + { + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* Send proxy arp indication to daemon */ + SendProxyARPEvent(NetDev, + SourceMACAddr, + SourceIPAddr, + ProxyARPEntry->TargetMACAddr, + ProxyARPEntry->TargetIPAddr, + IPV6, + FromDS, + IsDAD); + } + + return IsFound; +} + + +VOID WNMIPv4ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + USHORT srcPort, + USHORT dstPort, + PUCHAR pSrcBuf) +{ + UCHAR apidx = RTMP_GET_PACKET_NET_DEVICE(pPacket); + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + MAC_TABLE_ENTRY *pEntry; + + if (srcPort == 0x43 && dstPort == 0x44) + { + UCHAR *pTargetIPAddr = pSrcBuf + 24; + /* Client hardware address */ + UCHAR *pTargetMACAddr = pSrcBuf + 36; + + if ((pMbss->WNMCtrl.ProxyARPEnable) && (pEntry = MacTableLookup(pAd, pTargetMACAddr))) + { + printk("entry apidx=%d,%d,%d\n",pEntry->apidx, apidx, pMbss->WNMCtrl.ProxyARPEnable); + + if ((pEntry->apidx == apidx) && pMbss->WNMCtrl.ProxyARPEnable) + { + /* Proxy MAC address/IP mapping */ + AddIPv4ProxyARPEntry(pAd, pMbss, pTargetMACAddr, pTargetIPAddr); + } + } + + } +} + + +VOID WNMIPv6ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + PUCHAR pSrcBuf) +{ + UCHAR apidx = RTMP_GET_PACKET_NET_DEVICE(pPacket); + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + UCHAR Offset = 0; + + if (pMbss->WNMCtrl.ProxyARPEnable) + { + /* Check if router advertisement, and add proxy entry */ + + if (IsIPv6RouterAdvertisement(pAd, pSrcBuf - 2, &Offset)) + { + UCHAR *Pos = pSrcBuf + 4; + UCHAR TargetIPAddr[16]; + INT32 PayloadLen; + DBGPRINT(RT_DEBUG_OFF, ("This packet is router advertisement\n")); + + NdisMoveMemory(&PayloadLen, Pos, 2); + PayloadLen = OS_NTOHS(PayloadLen); + + printk("WNMIPv6ProxyARPCheck: offset=%d\n", Offset); + /* IPv6 options */ + Pos += 52 + Offset; + PayloadLen -= (16 + Offset); + + + while (PayloadLen > 0) + { + UINT8 OptionsLen = (*(Pos + 1)) * 8; + + /* Prefix information */ + if (*Pos == 0x03) + { + UCHAR *Prefix; + INT32 Ret; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + + /* Prefix */ + Prefix = (Pos + 16); + + /* Copy global address prefix */ + NdisMoveMemory(TargetIPAddr, Prefix, 8); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, + PROXY_ARP_IPV6_ENTRY, List) + { + if (ProxyARPEntry->TargetIPType == IPV6_LINK_LOCAL) + { + + /* Copy host ipv6 interface identifier */ + NdisMoveMemory(&TargetIPAddr[8], + &ProxyARPEntry->TargetIPAddr[8], 8); + + /* Proxy MAC address/IPv6 mapping for global address */ + AddIPv6ProxyARPEntry(pAd, pMbss, ProxyARPEntry->TargetMACAddr, + TargetIPAddr); + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + } + + Pos += OptionsLen; + PayloadLen -= OptionsLen; + } + } + } +} + +static VOID ReceiveBTMQuery(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BTM_EVENT_DATA *Event; + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + BTM_PEER_ENTRY *BTMPeerEntry; + PWNM_CTRL pWNMCtrl = NULL; + UCHAR APIndex, *Buf; + UINT16 VarLen; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE; + + printk("%s\n", __FUNCTION__); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(WNMFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + break; + } + } + + if (!pWNMCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2)) + IsFound = TRUE; + + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("%s Find peer address in BTMPeerList already\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + BTMPeerEntry->CurrentState = WAIT_PEER_BTM_QUERY; + + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2, MAC_ADDR_LEN); + BTMPeerEntry->DialogToken = WNMFrame->u.BTM_QUERY.DialogToken; + BTMPeerEntry->Priv = pAd; + + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMRspTimer, + GET_TIMER_FUNCTION(WaitPeerBTMRspTimeout), BTMPeerEntry, FALSE); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + VarLen = *(WNMFrame->u.BTM_QUERY.Variable + 2); + VarLen += 3; + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (BTM_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, WNMFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = PEER_BTM_QUERY; + Len += 2; + + Event->u.PEER_BTM_QUERY_DATA.DialogToken = WNMFrame->u.BTM_QUERY.DialogToken; + Len += 1; + + /* FIXME */ + //Event->u.PEER_BTM_QUERY_DATA.BTMQueryLen; + Len += 2; + + NdisMoveMemory(Event->u.PEER_BTM_QUERY_DATA.BTMQuery, WNMFrame->u.BTM_QUERY.Variable, + VarLen); + Len += VarLen; + + MlmeEnqueue(pAd, BTM_STATE_MACHINE, PEER_BTM_QUERY, Len, Buf,0); + + os_free_mem(NULL, Buf); + + return; + +error: + DlListDel(&BTMPeerEntry->List); + os_free_mem(NULL, BTMPeerEntry); +} + + +static VOID ReceiveBTMRsp(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + BTM_EVENT_DATA *Event; + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + BTM_PEER_ENTRY *BTMPeerEntry; + PWNM_CTRL pWNMCtrl = NULL; + UCHAR APIndex, *Buf; + UINT16 VarLen = 0; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE, Cancelled; + + printk("%s\n", __FUNCTION__); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(WNMFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + break; + } + } + + if (!pWNMCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2)) + IsFound = TRUE; + + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("Not found peer entry in list\n")); + return; + } + + /* Cancel Wait peer wnm response frame */ + RTMPCancelTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, &Cancelled); + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, &Cancelled); + + VarLen = 2; + + if (*WNMFrame->u.BTM_RSP.Variable == 0) + VarLen += 6; + + VarLen += *(WNMFrame->u.BTM_RSP.Variable + VarLen + 1); + VarLen += 2; + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (BTM_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, WNMFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = PEER_BTM_RSP; + Len += 2; + + Event->u.PEER_BTM_RSP_DATA.DialogToken = WNMFrame->u.BTM_RSP.DialogToken; + Len += 1; + + /* FIXME */ + //Event->u.PEER_BTM_RSP_DATA.BTMRspLen; + Len += 2; + + NdisMoveMemory(Event->u.PEER_BTM_RSP_DATA.BTMRsp, WNMFrame->u.BTM_RSP.Variable, + VarLen); + Len += VarLen; + + MlmeEnqueue(pAd, BTM_STATE_MACHINE, PEER_BTM_RSP, Len, Buf,0); + + os_free_mem(NULL, Buf); + + return; +} + + +VOID BTMSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN enum BTM_STATE State) +{ + PWNM_CTRL pWNMCtrl; + PBTM_PEER_ENTRY BTMPeerEntry; + PBTM_EVENT_DATA Event = (PBTM_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, + BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + BTMPeerEntry->CurrentState = State; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); +} + +static VOID SendBTMQueryIndication( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + BTM_EVENT_DATA *Event = (BTM_EVENT_DATA *)Elem->Msg; + PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + + printk("%s\n", __FUNCTION__); + + /* Send BTM query indication to daemon */ + SendBTMQueryEvent(NetDev, + Event->PeerMACAddr, + Event->u.PEER_BTM_QUERY_DATA.BTMQuery, + Event->u.PEER_BTM_QUERY_DATA.BTMQueryLen, + RA_WEXT); + + BTMSetPeerCurrentState(pAd, Elem, WAIT_BTM_REQ); +} + + +VOID WaitPeerBTMRspTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + BTM_PEER_ENTRY *BTMPeerEntry = (BTM_PEER_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + PWNM_CTRL pWNMCtrl; + INT32 Ret; + BOOLEAN Cancelled; + + printk("%s\n", __FUNCTION__); + + if (!BTMPeerEntry) + return; + + pAd = BTMPeerEntry->Priv; + + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, &Cancelled); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pWNMCtrl = &pAd->ApCfg.MBSSID[BTMPeerEntry->ControlIndex].WNMCtrl; + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + os_free_mem(NULL, BTMPeerEntry); +} +BUILD_TIMER_FUNCTION(WaitPeerBTMRspTimeout); + + +static VOID SendBTMReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BTM_EVENT_DATA *Event = (BTM_EVENT_DATA *)Elem->Msg; + UCHAR *Buf; + WNM_FRAME *WNMFrame; + BTM_PEER_ENTRY *BTMPeerEntry = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + UINT32 FrameLen = 0, VarLen = Event->u.BTM_REQ_DATA.BTMReqLen; + INT32 Ret; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, + BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*WNMFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*WNMFrame) + VarLen); + + WNMFrame = (WNM_FRAME *)Buf; + + ActHeaderInit(pAd, &WNMFrame->Hdr, Event->PeerMACAddr, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + WNMFrame->Category = CATEGORY_WNM; + FrameLen += 1; + + WNMFrame->u.BTM_REQ.Action = BSS_TRANSITION_REQ; + FrameLen += 1; + + WNMFrame->u.BTM_REQ.DialogToken = Event->u.BTM_REQ_DATA.DialogToken; + FrameLen += 1; + + NdisMoveMemory(WNMFrame->u.BTM_REQ.Variable, Event->u.BTM_REQ_DATA.BTMReq, + Event->u.BTM_REQ_DATA.BTMReqLen); + FrameLen += Event->u.BTM_REQ_DATA.BTMReqLen; + + BTMSetPeerCurrentState(pAd, Elem, WAIT_PEER_BTM_RSP); + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + RTMPSetTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, WaitPeerBTMRspTimeoutVale); + +#ifdef CONFIG_HOTSPOT_R2 + { + MAC_TABLE_ENTRY *pEntry; + + if ((pEntry = MacTableLookup(pAd, Event->PeerMACAddr)) != NULL) + { + UINT8 *BTMData = (UINT8 *)Event->u.BTM_REQ_DATA.BTMReq; + + pEntry->BTMDisassocCount = (((*(BTMData+2) << 8) | (*(BTMData+1)))*pAd->CommonCfg.BeaconPeriod)/1000; + printk("bss discount sec=%d\n", pEntry->BTMDisassocCount); + if (pEntry->BTMDisassocCount < 1) + pEntry->BTMDisassocCount = 1; + } + } +#endif + + os_free_mem(NULL, Buf); +} + + +static VOID SendBTMConfirm( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + PBTM_PEER_ENTRY BTMPeerEntry, BTMPeerEntryTmp; + BTM_EVENT_DATA *Event = (BTM_EVENT_DATA *)Elem->Msg; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + INT32 Ret; + + printk("%s\n", __FUNCTION__); + + /* Send BTM confirm to daemon */ + SendBTMConfirmEvent(NetDev, + Event->PeerMACAddr, + Event->u.PEER_BTM_RSP_DATA.BTMRsp, + Event->u.PEER_BTM_RSP_DATA.BTMRspLen, + RA_WEXT); + + /* Delete BTM peer entry */ + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEachSafe(BTMPeerEntry, BTMPeerEntryTmp, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + DlListDel(&BTMPeerEntry->List); + os_free_mem(NULL, BTMPeerEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +static VOID ReceiveBTMReq(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + + +} + + +static VOID SendBTMQuery( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + +} + + +static VOID SendBTMIndication( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + +} + + +static VOID SendBTMRsp( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + +} +#endif /* CONFIG_STA_SUPPORT */ + +enum BTM_STATE BTMPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PWNM_CTRL pWNMCtrl; + PBTM_PEER_ENTRY BTMPeerEntry; + PBTM_EVENT_DATA Event = (PBTM_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + return BTMPeerEntry->CurrentState; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + return BTM_UNKNOWN; +} + + + +void PeerWNMAction(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { +#ifdef CONFIG_AP_SUPPORT + case BSS_TRANSITION_QUERY: + ReceiveBTMQuery(pAd, Elem); + break; + case BSS_TRANSITION_RSP: + ReceiveBTMRsp(pAd, Elem); + break; +#ifdef CONFIG_HOTSPOT_R2 + case WNM_NOTIFICATION_RSP: + ReceiveWNMNotifyRsp(pAd, Elem); + break; +#endif +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + case BSS_TRANSITION_REQ: + ReceiveBTMReq(pAd, Elem); + break; +#endif /* CONFIG_STA_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("Invalid action field = %d\n", Action)); + break; + } +} + +VOID WNMCtrlInit(IN PRTMP_ADAPTER pAd) +{ + PWNM_CTRL pWNMCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + NdisZeroMemory(pWNMCtrl, sizeof(*pWNMCtrl)); + RTMP_SEM_EVENT_INIT(&pWNMCtrl->BTMPeerListLock, &pAd->RscSemMemList); + RTMP_SEM_EVENT_INIT(&pWNMCtrl->ProxyARPListLock, &pAd->RscSemMemList); + RTMP_SEM_EVENT_INIT(&pWNMCtrl->ProxyARPIPv6ListLock, &pAd->RscSemMemList); + DlListInit(&pWNMCtrl->BTMPeerList); + DlListInit(&pWNMCtrl->IPv4ProxyARPList); + DlListInit(&pWNMCtrl->IPv6ProxyARPList); +#ifdef CONFIG_HOTSPOT_R2 + RTMP_SEM_EVENT_INIT(&pWNMCtrl->WNMNotifyPeerListLock, &pAd->RscSemMemList); + DlListInit(&pWNMCtrl->WNMNotifyPeerList); +#endif + + } +#endif +} + + +static VOID WNMCtrlRemoveAllIE(PWNM_CTRL pWNMCtrl) +{ + if (pWNMCtrl->TimeadvertisementIELen) + { + pWNMCtrl->TimeadvertisementIELen = 0; + os_free_mem(NULL, pWNMCtrl->TimeadvertisementIE); + } + + if (pWNMCtrl->TimezoneIELen) + { + pWNMCtrl->TimezoneIELen = 0; + os_free_mem(NULL, pWNMCtrl->TimezoneIE); + } +} + + +VOID WNMCtrlExit(IN PRTMP_ADAPTER pAd) +{ + PWNM_CTRL pWNMCtrl; + UINT32 Ret; + BTM_PEER_ENTRY *BTMPeerEntry, *BTMPeerEntryTmp; +#ifdef CONFIG_AP_SUPPORT + PROXY_ARP_IPV4_ENTRY *ProxyARPIPv4Entry, *ProxyARPIPv4EntryTmp; + PROXY_ARP_IPV6_ENTRY *ProxyARPIPv6Entry, *ProxyARPIPv6EntryTmp; + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry, *WNMNotifyPeerEntryTmp; +#endif + + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + + /* Remove all btm peer entry */ + DlListForEachSafe(BTMPeerEntry, BTMPeerEntryTmp, + &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + DlListDel(&BTMPeerEntry->List); + os_free_mem(NULL, BTMPeerEntry); + } + + DlListInit(&pWNMCtrl->BTMPeerList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->BTMPeerListLock); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + /* Remove all proxy arp entry */ + DlListForEachSafe(ProxyARPIPv4Entry, ProxyARPIPv4EntryTmp, + &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + DlListDel(&ProxyARPIPv4Entry->List); + os_free_mem(NULL, ProxyARPIPv4Entry); + } + DlListInit(&pWNMCtrl->IPv4ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + DlListForEachSafe(ProxyARPIPv6Entry, ProxyARPIPv6EntryTmp, + &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + DlListDel(&ProxyARPIPv6Entry->List); + os_free_mem(NULL, ProxyARPIPv6Entry); + } + DlListInit(&pWNMCtrl->IPv6ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->ProxyARPListLock); + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->ProxyARPIPv6ListLock); +#ifdef CONFIG_HOTSPOT_R2 + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + + /* Remove all wnm notify peer entry */ + DlListForEachSafe(WNMNotifyPeerEntry, WNMNotifyPeerEntryTmp, + &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + DlListDel(&WNMNotifyPeerEntry->List); + os_free_mem(NULL, WNMNotifyPeerEntry); + } + + DlListInit(&pWNMCtrl->WNMNotifyPeerList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->WNMNotifyPeerListLock); +#endif + + /* Remove all WNM IEs */ + WNMCtrlRemoveAllIE(pWNMCtrl); + } +#endif /* CONFIG_AP_SUPPORT */ + +} + + +#ifdef CONFIG_AP_SUPPORT +VOID Clear_All_PROXY_TABLE(IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl; + UINT32 Ret; + PROXY_ARP_IPV4_ENTRY *ProxyARPIPv4Entry, *ProxyARPIPv4EntryTmp; + PROXY_ARP_IPV6_ENTRY *ProxyARPIPv6Entry, *ProxyARPIPv6EntryTmp; + + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + /* Remove all proxy arp entry */ + DlListForEachSafe(ProxyARPIPv4Entry, ProxyARPIPv4EntryTmp, + &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + DlListDel(&ProxyARPIPv4Entry->List); + os_free_mem(NULL, ProxyARPIPv4Entry); + } + DlListInit(&pWNMCtrl->IPv4ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + DlListForEachSafe(ProxyARPIPv6Entry, ProxyARPIPv6EntryTmp, + &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + DlListDel(&ProxyARPIPv6Entry->List); + os_free_mem(NULL, ProxyARPIPv6Entry); + } + DlListInit(&pWNMCtrl->IPv6ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); +} +#endif + + +VOID BTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_BTM_STATE, MAX_BTM_MSG, (STATE_MACHINE_FUNC)Drop, BTM_UNKNOWN, BTM_MACHINE_BASE); + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_PEER_BTM_QUERY, PEER_BTM_QUERY, (STATE_MACHINE_FUNC)SendBTMQueryIndication); + StateMachineSetAction(S, WAIT_BTM_REQ, BTM_REQ, (STATE_MACHINE_FUNC)SendBTMReq); + StateMachineSetAction(S, WAIT_PEER_BTM_RSP, PEER_BTM_RSP, (STATE_MACHINE_FUNC)SendBTMConfirm); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + StateMachineSetAction(S, WAIT_BTM_QUERY, BTM_QUERY, (STATE_MACHINE_FUNC)SendBTMQuery); + StateMachineSetAction(S, WAIT_PEER_BTM_REQ, PEER_BTM_REQ, (STATE_MACHINE_FUNC)SendBTMIndication); + StateMachineSetAction(S, WAIT_BTM_RSP,BTM_RSP, (STATE_MACHINE_FUNC)SendBTMRsp); +#endif /* CONFIG_STA_SUPPORT */ +} + +#ifdef CONFIG_HOTSPOT_R2 +#ifdef CONFIG_AP_SUPPORT +VOID WNMSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN enum WNM_NOTIFY_STATE State) +{ + PWNM_CTRL pWNMCtrl; + PWNM_NOTIFY_PEER_ENTRY WNMNotifyPeerEntry; + PWNM_NOTIFY_EVENT_DATA Event = (PWNM_NOTIFY_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, + WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + WNMNotifyPeerEntry->CurrentState = State; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); +} + +enum WNM_NOTIFY_STATE WNMNotifyPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PWNM_CTRL pWNMCtrl; + PWNM_NOTIFY_PEER_ENTRY WNMNotifyPeerEntry; + PWNM_NOTIFY_EVENT_DATA Event = (PWNM_NOTIFY_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + return WNMNotifyPeerEntry->CurrentState; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + return WNM_NOTIFY_UNKNOWN; +} + +VOID WaitPeerWNMNotifyRspTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry = (WNM_NOTIFY_PEER_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + PWNM_CTRL pWNMCtrl; + INT32 Ret; + BOOLEAN Cancelled; + + printk("%s\n", __FUNCTION__); + + if (!WNMNotifyPeerEntry) + return; + + pAd = WNMNotifyPeerEntry->Priv; + + RTMPReleaseTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, &Cancelled); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pWNMCtrl = &pAd->ApCfg.MBSSID[WNMNotifyPeerEntry->ControlIndex].WNMCtrl; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListDel(&WNMNotifyPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + os_free_mem(NULL, WNMNotifyPeerEntry); +} +BUILD_TIMER_FUNCTION(WaitPeerWNMNotifyRspTimeout); + +VOID ReceiveWNMNotifyRsp(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + WNM_NOTIFY_EVENT_DATA *Event; + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry; + PWNM_CTRL pWNMCtrl = NULL; + UCHAR APIndex, *Buf; + UINT16 VarLen = 0; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE, Cancelled; + + printk("%s\n", __FUNCTION__); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(WNMFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + break; + } + } + + if (!pWNMCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2)) + IsFound = TRUE; + + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("Not found peer entry in list\n")); + { + unsigned char *tmp1 = (unsigned char *)WNMFrame->Hdr.Addr2; + unsigned char *tmp2; + printk("client mac:%02x:%02x:%02x:%02x:%02x:%02x\n",*(tmp1),*(tmp1+1),*(tmp1+2),*(tmp1+3),*(tmp1+4),*(tmp1+5)); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + tmp2 = (unsigned char *)WNMNotifyPeerEntry->PeerMACAddr; + printk("list=> %02x:%02x:%02x:%02x:%02x:%02x\n",*(tmp2),*(tmp2+1),*(tmp2+2),*(tmp2+3),*(tmp2+4),*(tmp2+5)); + } + printk("\n"); + } + return; + } + + /* Cancel Wait peer wnm response frame */ + RTMPCancelTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, &Cancelled); + RTMPReleaseTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, &Cancelled); + + VarLen = 1; + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (WNM_NOTIFY_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, WNMFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = WNM_NOTIFY_RSP; + Len += 2; + + Event->u.WNM_NOTIFY_RSP_DATA.DialogToken = WNMFrame->u.WNM_NOTIFY_RSP.DialogToken; + Len += 1; + + Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRspLen = 1;// = WNMFrame->u.WNM_NOTIFY_RSP.DialogToken; + Len += 2; + + //NdisMoveMemory(Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRsp, WNMFrame->u.WNM_NOTIFY_RSP.Variable, + // VarLen); + Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRsp[0] = WNMFrame->u.WNM_NOTIFY_RSP.RespStatus; + Len += VarLen; + + MlmeEnqueue(pAd, WNM_NOTIFY_STATE_MACHINE, WNM_NOTIFY_RSP, Len, Buf,0); + + os_free_mem(NULL, Buf); + + return; +} + +static VOID SendWNMNotifyReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + WNM_NOTIFY_EVENT_DATA *Event = (WNM_NOTIFY_EVENT_DATA *)Elem->Msg; + UCHAR *Buf; + WNM_FRAME *WNMFrame; + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + UINT32 FrameLen = 0, VarLen = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + INT32 Ret; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, + WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*WNMFrame) + VarLen + 7); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*WNMFrame) + VarLen); + + WNMFrame = (WNM_FRAME *)Buf; + + ActHeaderInit(pAd, &WNMFrame->Hdr, Event->PeerMACAddr, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + WNMFrame->Category = CATEGORY_WNM; + FrameLen += 1; + + WNMFrame->u.WNM_NOTIFY_REQ.Action = WNM_NOTIFICATION_REQ; + FrameLen += 1; + + WNMFrame->u.WNM_NOTIFY_REQ.DialogToken = Event->u.WNM_NOTIFY_REQ_DATA.DialogToken; + FrameLen += 1; + + WNMFrame->u.WNM_NOTIFY_REQ.Type = 1; + FrameLen += 1; + + if (Event->EventType == 0) //remediation + { + printk("remediation\n"); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[0] = 0xdd; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[1] = 5+Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[2] = 0x50; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[3] = 0x6f; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[4] = 0x9a; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[5] = 0x00; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[6] = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + FrameLen += 7; + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[7], Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen); + FrameLen += Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + } + else if (Event->EventType == 2) //remediation+service method + { + printk("remediation with method\n"); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[0] = 0xdd; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[1] = 5+Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[2] = 0x50; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[3] = 0x6f; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[4] = 0x9a; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[5] = 0x00; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[6] = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-1; + FrameLen += 7; + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[7], Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen); + FrameLen += Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + } + else if (Event->EventType == 1) //deauth imminent notice + { + MAC_TABLE_ENTRY *pEntry; + + printk("deauth imminent: %d\n", Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[0] = 0xdd; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[1] = 5+Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[2] = 0x50; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[3] = 0x6f; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[4] = 0x9a; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[5] = 0x01; + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[6], Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, + 3); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[9] = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-3; + FrameLen += 10; + if (WNMFrame->u.WNM_NOTIFY_REQ.Variable[9] != 0) + { + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[10], &Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq[3], + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-3); + FrameLen += (Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-3); + } + + if ((pEntry = MacTableLookup(pAd, Event->PeerMACAddr)) != NULL) + { + pEntry->BTMDisassocCount = 40; //20; + } + } + else + { + printk("no match event type:%d\n", Event->EventType); + os_free_mem(NULL, Buf); + } + WNMSetPeerCurrentState(pAd, Elem, WAIT_WNM_NOTIFY_RSP); + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + RTMPSetTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, WaitPeerWNMNotifyRspTimeoutVale); + + os_free_mem(NULL, Buf); +} + +VOID SendWNMNotifyConfirm( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + PWNM_NOTIFY_PEER_ENTRY WNMNotifyPeerEntry, WNMNotifyPeerEntryTmp; + WNM_NOTIFY_EVENT_DATA *Event = (WNM_NOTIFY_EVENT_DATA *)Elem->Msg; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + INT32 Ret; + + printk("%s\n", __FUNCTION__); + + printk("Receive WNM Notify Response Status:%d\n", Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRsp[0]); + /* Delete BTM peer entry */ + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + DlListForEachSafe(WNMNotifyPeerEntry, WNMNotifyPeerEntryTmp, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + DlListDel(&WNMNotifyPeerEntry->List); + os_free_mem(NULL, WNMNotifyPeerEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WNMNotifyStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WNM_NOTIFY_STATE, MAX_WNM_NOTIFY_MSG, (STATE_MACHINE_FUNC)Drop, WNM_NOTIFY_UNKNOWN, WNM_NOTIFY_MACHINE_BASE); + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_WNM_NOTIFY_REQ, WNM_NOTIFY_REQ, (STATE_MACHINE_FUNC)SendWNMNotifyReq); + StateMachineSetAction(S, WAIT_WNM_NOTIFY_RSP, WNM_NOTIFY_RSP, (STATE_MACHINE_FUNC)SendWNMNotifyConfirm); +#endif /* CONFIG_AP_SUPPORT */ + +} +#endif /* CONFIG_HOTSPOT_R2 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wnm_tlv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wnm_tlv.c new file mode 100644 index 000000000..60ebe7d80 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wnm_tlv.c @@ -0,0 +1,63 @@ +#include "rt_config.h" + + +VOID InsertDMSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_DMS_REQUEST_ELEMENT DMSReqElement) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 3, &DMSReqElement, + END_OF_ARGS); + +/* *pFrameLen = *pFrameLen + TempLen; */ + + return; +} + + + +VOID WNM_InsertDMS( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN UCHAR DMSID, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr) +{ + ULONG TempLen; + UINT8 DMSIDId = DMSID; + WNM_TCLAS tclas; + UCHAR TCLASElementID = WNM_CATEGORY; + UCHAR TCLASLength = WNM_TCLAS_TYPE_IP_V4_LEN; + + tclas.UserPriority = 0; + tclas.ClassifierType = 1; + tclas.ClassifierMask = 255; + tclas.Clasifier.IPv4.Version = 0; + tclas.Clasifier.IPv4.IpSource = 0; + tclas.Clasifier.IPv4.PortSource = 0; + tclas.Clasifier.IPv4.PortDest = 0; + tclas.Clasifier.IPv4.DSCP = 0; + tclas.Clasifier.IPv4.Protocol = 4; + + tclas.Clasifier.IPv4.IpDest = IpAddr; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &DMSIDId, + 1, &Len, + 1, &TCLASElementID, + 1, &TCLASLength, + WNM_TCLAS_TYPE_IP_V4_LEN, &tclas, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc.c new file mode 100644 index 000000000..667f42b4c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc.c @@ -0,0 +1,11945 @@ +/* + *************************************************************************** + * 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.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 06-08-08 Initial + Snowpin Lee 06-09-12 Do modifications and Add APIs for AP + Snowpin Lee 07-04-19 Do modifications and Add APIs for STA + Snowpin Lee 07-05-17 Do modifications and Add APIs for AP Client +*/ + +#include "rt_config.h" + +#ifdef WSC_INCLUDED +#include "wsc_tlv.h" +/*#ifdef LINUX */ +/*#include */ +/*#endif*/ + +#define WSC_UPNP_MSG_TIMEOUT (150 * OS_HZ) +#define RTMP_WSC_NLMSG_SIGNATURE_LEN 8 +#define MAX_WEPKEYNAME_LEN 20 +#define MAX_WEPKEYTYPE_LEN 20 + +#ifndef PF_NOFREEZE +#define PF_NOFREEZE 0 +#endif + +#ifdef MULTI_INF_SUPPORT +/* Index 0 for 2.4G, 1 for 5Ghz Card */ +extern VOID* pAdGlobalList[2]; +#endif /* MULTI_INF_SUPPORT */ + +char WSC_MSG_SIGNATURE[]={"RAWSCMSG"}; + +extern UCHAR WPS_OUI[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR MTK_OUI[]; + +#ifdef IWSC_SUPPORT +extern UCHAR IWSC_OUI[]; +#endif // IWSC_SUPPORT // + +#if defined(__ECOS) && defined(BRANCH_ADV) +extern int CFG_set(int id, void *val); +extern int CFG_str2id(char * var); +extern int CFG_commit(int id); +#else +#define CFG_set(a, b) {} +#define CFG_str2id(a) {} +#define CFG_commit(a) {} +#endif /*__ECOS && BRANCH_ADV */ + +UINT8 WPS_DH_G_VALUE[1] = {0x02}; +UINT8 WPS_DH_P_VALUE[192] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +/* General used field */ +UCHAR STA_Wsc_Pri_Dev_Type[8] = {0x00, 0x01, 0x00, 0x50, 0xf2, 0x04, 0x00, 0x01}; + +#ifdef CONFIG_AP_SUPPORT +UCHAR AP_Wsc_Pri_Dev_Type[8] = {0x00, 0x06, 0x00, 0x50, 0xf2, 0x04, 0x00, 0x01}; + +VOID WscDelWPARetryTimer( + IN PRTMP_ADAPTER pAd); + +#ifdef APCLI_SUPPORT + +VOID WscApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +BOOLEAN WscCheckNonce( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN BOOLEAN bFlag, + IN PWSC_CTRL pWscControl); + +VOID WscEapActionDisabled( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl); + +VOID WscGetConfigErrFromNack( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *pElem, + OUT USHORT *pConfigError); + +INT WscSetAuthMode( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN PSTRING arg); + +INT WscSetEncrypType( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN PSTRING arg); + +VOID WscSendNACK( + IN PRTMP_ADAPTER pAdapter, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); + +static INT wsc_write_dat_file_thread(IN ULONG data); + +#ifdef CONFIG_STA_SUPPORT +VOID WscLinkDown( + IN PRTMP_ADAPTER pAd); +#endif /* CONFIG_STA_SUPPORT */ + +VOID WscDelListEntryByMAC( + PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr); + +NDIS_802_11_AUTHENTICATION_MODE WscGetAuthMode( + IN USHORT authFlag); + +NDIS_802_11_WEP_STATUS WscGetWepStatus( + IN USHORT encryFlag); + +/* + Standard UUID generation procedure. The UUID format generated by this function is base on UUID std. version 1. + It's a 16 bytes, one-time global unique number. and can show in string format like this: + 550e8400-e29b-41d4-a716-446655440000 + + The format of uuid is: + uuid = "-" + "-" + "-" + + "-" + + time_low = 4* + time_mid = 2* + time_high_and_version = 2* + clock_seq_high_and_reserved = + clock_seq_low = + node = 6* + hex_octet = + hex_digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" + |"a"|"b"|"c"|"d"|"e"|"f" + |"A"|"B"|"C"|"D"|"E"|"F" + Note: + Actually, to IOT with JumpStart, we fix the first 10 bytes of UUID string!!!! +*/ +INT WscGenerateUUID( + RTMP_ADAPTER *pAd, + UCHAR *uuidHexStr, + UCHAR *uuidAscStr, + int apIdx, + BOOLEAN bUseCurrentTime) +{ + + WSC_UUID_T uuid_t; + unsigned long long uuid_time; + int i; + UINT16 clkSeq; + char uuidTmpStr[UUID_LEN_STR+2]; + +#ifdef MULTI_INF_SUPPORT +#ifdef CON_WPS_AP_SAME_UUID + PRTMP_ADAPTER pOpposAd; + PWSC_CTRL pWscControl; + + /* We Assume the 5G init phase after 2.4Ghz */ + if (pAd == pAdGlobalList[1]) + { + pOpposAd = (PRTMP_ADAPTER) pAdGlobalList[0]; + pWscControl = &pOpposAd->ApCfg.MBSSID[apIdx].WscControl; + + NdisCopyMemory(uuidHexStr, &pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX); + NdisCopyMemory(uuidAscStr, &pWscControl->Wsc_Uuid_Str[0], UUID_LEN_STR); + + goto show; + } +#endif /* CON_WPS_AP_SAME_UUID */ +#endif /* MULTI_INF_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +/* for fixed UUID - YYHuang 07/10/09 */ +#define FIXED_UUID +#endif /* RTMP_RBUS_SUPPORT */ + + /* Get the current time. */ + if (bUseCurrentTime) + { + NdisGetSystemUpTime((ULONG *)&uuid_time); + } + else + uuid_time = 2860; /*xtime.tv_sec; // Well, we fix this to make JumpStart happy! */ + uuid_time *= 10000000; + uuid_time += 0x01b21dd213814000LL; + +#ifdef RTMP_RBUS_SUPPORT +#ifdef FIXED_UUID + uuid_time = 0x2880288028802880LL; +#endif +#endif /* RTMP_RBUS_SUPPORT */ + + + uuid_t.timeLow = (UINT32)uuid_time & 0xFFFFFFFF; + uuid_t.timeMid = (UINT16)((uuid_time >>32) & 0xFFFF); + uuid_t.timeHi_Version = (UINT16)((uuid_time >> 48) & 0x0FFF); + uuid_t.timeHi_Version |= (1 << 12); + + /* Get the clock sequence. */ + clkSeq = (UINT16)(0x0601/*jiffies*/ & 0xFFFF); /* Again, we fix this to make JumpStart happy! */ +#ifdef RTMP_RBUS_SUPPORT +#ifdef FIXED_UUID + clkSeq = (UINT16)0x2880; +#endif +#endif /* RTMP_RBUS_SUPPORT */ + + uuid_t.clockSeqLow = clkSeq & 0xFF; + uuid_t.clockSeqHi_Var = (clkSeq & 0x3F00) >> 8; + uuid_t.clockSeqHi_Var |= 0x80; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* copy the Mac address as the value of node */ + NdisMoveMemory(&uuid_t.node[0], &pAd->ApCfg.MBSSID[apIdx].wdev.bssid[0], sizeof(uuid_t.node)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NdisMoveMemory(&uuid_t.node[0], &pAd->CurrentAddress[0], sizeof(uuid_t.node)); + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Create the UUID ASCII string. */ + memset(uuidTmpStr, 0, sizeof(uuidTmpStr)); + snprintf(uuidTmpStr, sizeof(uuidTmpStr), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (unsigned int)uuid_t.timeLow, uuid_t.timeMid, uuid_t.timeHi_Version, uuid_t.clockSeqHi_Var, uuid_t.clockSeqLow, + uuid_t.node[0], uuid_t.node[1], uuid_t.node[2], uuid_t.node[3], uuid_t.node[4], uuid_t.node[5]); + if (strlen(uuidTmpStr) > UUID_LEN_STR) + DBGPRINT(RT_DEBUG_ERROR, ("ERROR:UUID String size too large!\n")); + strncpy((PSTRING)uuidAscStr, uuidTmpStr, UUID_LEN_STR); + + /* Create the UUID Hex format number */ + uuid_t.timeLow = cpu2be32(uuid_t.timeLow); + NdisMoveMemory(&uuidHexStr[0], &uuid_t.timeLow, 4); + uuid_t.timeMid = cpu2be16(uuid_t.timeMid); + NdisMoveMemory(&uuidHexStr[4], &uuid_t.timeMid, 2); + uuid_t.timeHi_Version = cpu2be16(uuid_t.timeHi_Version); + NdisMoveMemory(&uuidHexStr[6], &uuid_t.timeHi_Version, 2); + NdisMoveMemory(&uuidHexStr[8], &uuid_t.clockSeqHi_Var, 1); + NdisMoveMemory(&uuidHexStr[9], &uuid_t.clockSeqLow, 1); + NdisMoveMemory(&uuidHexStr[10], &uuid_t.node[0], 6); + +#ifdef MULTI_INF_SUPPORT +#ifdef CON_WPS_AP_SAME_UUID +show: +#endif /* CON_WPS_AP_SAME_UUID */ +#endif /* MULTI_INF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("The UUID Hex string is:")); + for (i=0; i< 16; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%02x", (uuidHexStr[i] & 0xff))); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + DBGPRINT(RT_DEBUG_TRACE, ("The UUID ASCII string is:%s!\n", uuidAscStr)); + return 0; +} + +VOID WscInitCommonTimers( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl) +{ + WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->EapolTimer, pWscControl->EapolTimerRunning, WscEAPOLTimeOutAction); + WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->Wsc2MinsTimer, pWscControl->Wsc2MinsTimerRunning, Wsc2MinsTimeOutAction); + WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->WscUPnPNodeInfo.UPnPMsgTimer, pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning, WscUPnPMsgTimeOutAction); + pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerPending = FALSE; + WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->M2DTimer, pWscControl->bM2DTimerRunning, WscM2DTimeOutAction); + +#ifdef WSC_LED_SUPPORT + WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->WscLEDTimer, pWscControl->WscLEDTimerRunning, WscLEDTimer); + WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->WscSkipTurnOffLEDTimer, pWscControl->WscSkipTurnOffLEDTimerRunning, WscSkipTurnOffLEDTimer); +#endif /* WSC_LED_SUPPORT */ +} + +VOID WscInitClientTimers( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWScControl) +{ + WSC_TIMER_INIT(pAdapter, pWScControl, &pWScControl->WscPBCTimer, pWScControl->WscPBCTimerRunning, WscPBCTimeOutAction); + WSC_TIMER_INIT(pAdapter, pWScControl, &pWScControl->WscScanTimer, pWScControl->WscScanTimerRunning, WscScanTimeOutAction); + WSC_TIMER_INIT(pAdapter, pWScControl, &pWScControl->WscProfileRetryTimer, pWScControl->WscProfileRetryTimerRunning, WscProfileRetryTimeout); /* add by johnli, fix WPS test plan 5.1.1 */ +} + +/* + ========================================================================== + Description: + wps state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +VOID WscStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + PWSC_CTRL pWScControl; + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WSC_STATE, MAX_WSC_MSG, (STATE_MACHINE_FUNC)Drop, WSC_IDLE, WSC_MACHINE_BASE); + StateMachineSetAction(S, WSC_IDLE, WSC_EAPOL_START_MSG, (STATE_MACHINE_FUNC)WscEAPOLStartAction); + StateMachineSetAction(S, WSC_IDLE, WSC_EAPOL_PACKET_MSG, (STATE_MACHINE_FUNC)WscEAPAction); + StateMachineSetAction(S, WSC_IDLE, WSC_EAPOL_UPNP_MSG, (STATE_MACHINE_FUNC)WscEAPAction); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR apidx; + + for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++) + { + pWScControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + pWScControl->EntryIfIdx= (MIN_NET_DEVICE_FOR_MBSSID | apidx); + WscInitCommonTimers(pAd, pWScControl); + pWScControl->WscUpdatePortCfgTimerRunning = FALSE; + WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscUpdatePortCfgTimer, pWScControl->WscUpdatePortCfgTimerRunning, WscUpdatePortCfgTimeout); + WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscSetupLockTimer, pWScControl->WscSetupLockTimerRunning, WscSetupLockTimeout); + } + +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + pWScControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + pWScControl->EntryIfIdx= (MIN_NET_DEVICE_FOR_APCLI | apidx); + WscInitCommonTimers(pAd, pWScControl); + WscInitClientTimers(pAd, pWScControl); + } +#endif /* APCLI_SUPPORT */ + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pWScControl = &pAd->StaCfg.WscControl; + pWScControl->EntryIfIdx = BSS0; + + WscInitCommonTimers(pAd, pWScControl); + WscInitClientTimers(pAd, pWScControl); + + } +#endif /* CONFIG_STA_SUPPORT */ +} + +void WscM2DTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + /* For each state, we didn't care about the retry issue, we just send control message + to notify the UPnP deamon that some error happened in STATE MACHINE. + */ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd; + WSC_UPNP_NODE_INFO *pWscNodeInfo; +#ifdef CONFIG_AP_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; +/* UCHAR apidx = MAIN_MBSSID; */ +#endif /* CONFIG_AP_SUPPORT */ + BOOLEAN Cancelled; + UCHAR CurOpMode = 0xFF; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pEntry = MacTableLookup(pAd, pWscControl->EntryAddr); +#endif /* CONFIG_AP_SUPPORT */ + pWscNodeInfo = &pWscControl->WscUPnPNodeInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("UPnP StateMachine TimeOut(State=%d!)\n", pWscControl->WscState)); + + if( +#ifdef CONFIG_AP_SUPPORT + (((pEntry == NULL) || (pWscNodeInfo->registrarID != 0)) && (CurOpMode == AP_MODE)) || +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + ((pWscNodeInfo->registrarID != 0) && (CurOpMode == STA_MODE)) || +#endif /* CONFIG_STA_SUPPORT */ + (0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():pEntry maybe gone or already received M2 Packet!\n", __FUNCTION__)); + goto done; + } + + if (pWscControl->M2DACKBalance != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): waiting for M2DACK balance, extend the time!\n", __FUNCTION__)); + /* Waiting for M2DACK balance. */ + RTMPModTimer(&pWscControl->M2DTimer, WSC_EAP_ID_TIME_OUT); + pWscControl->M2DACKBalance = 0; + goto done; + } + else + { + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): send EAP-Fail to wireless Station!\n", __FUNCTION__)); + /* Send EAPFail to Wireless Station and reset the status of Wsc. */ + WscSendEapFail(pAd, pWscControl, TRUE); + /*pEntry->bWscCapable = FALSE; */ + if (pEntry != NULL) + pEntry->Receive_EapolStart_EapRspId = 0; + } +#endif /* CONFIG_AP_SUPPORT */ + pWscControl->EapMsgRunning = FALSE; + pWscControl->WscState = WSC_STATE_OFF; + } + +done: + pWscControl->bM2DTimerRunning = FALSE; + pWscControl->M2DACKBalance = 0; + pWscNodeInfo->registrarID = 0; + + +} + + +VOID WscUPnPMsgTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd; + WSC_UPNP_NODE_INFO *pWscNodeInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscUPnPMsgTimeOutAction\n")); + + /*It shouldn't happened! */ + if (!pWscControl) + return; + + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + pWscNodeInfo = &pWscControl->WscUPnPNodeInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("UPnP StateMachine TimeOut(State=%d!)\n", pWscControl->WscState)); + + if (pWscNodeInfo->bUPnPMsgTimerPending) + { +#define WSC_UPNP_TIMER_PENDIND_WAIT 2000 + + RTMPModTimer(&pWscNodeInfo->UPnPMsgTimer, WSC_UPNP_TIMER_PENDIND_WAIT); + DBGPRINT(RT_DEBUG_TRACE, ("UPnPMsgTimer Pending......\n")); + } + else + { + int dataLen; + UCHAR *pWscData; + + os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN); +/* if( (pWscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) != NULL) */ + if (pWscData != NULL) + { + memset(pWscData, 0, WSC_MAX_DATA_LEN); + dataLen = BuildMessageNACK(pAd, pWscControl, pWscData); + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL, + pWscData, dataLen, 0, 0, &pAd->CurrentAddress[0], AP_MODE); +/* kfree(pWscData); */ + os_free_mem(NULL, pWscData); + } + + pWscNodeInfo->bUPnPInProgress = FALSE; + pWscNodeInfo->bUPnPMsgTimerPending = FALSE; + pWscNodeInfo->bUPnPMsgTimerRunning = FALSE; + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_FAIL; + + RTMPSendWirelessEvent(pAd, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscUPnPMsgTimeOutAction\n")); + +} + +/* + ========================================================================== + Description: + This function processes EapolStart packets from wps stations + or enqueued by self. + + Return: + None + ========================================================================== +*/ +VOID WscEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MAC_TABLE_ENTRY *pEntry; + PWSC_CTRL pWpsCtrl = NULL; + PHEADER_802_11 pHeader; + PWSC_PEER_ENTRY pWscPeer = NULL; + UCHAR CurOpMode = 0xFF; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPOLStartAction\n")); + + pHeader = (PHEADER_802_11)Elem->Msg; + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + /* Cannot find this wps station in MacTable of WPS AP. */ + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("pEntry is NULL.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n")); + return; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWpsCtrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (IWSC_PeerEapolStart(pAd, pEntry) == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rejected by IWSC SM. Ignore EAPOL-Start.\n")); + return; + } +#endif // IWSC_SUPPORT // + pWpsCtrl = &pAd->StaCfg.WscControl; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pWpsCtrl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWpsCtrl == NULL!\n", __FUNCTION__)); + return; + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef CON_WPS + PWSC_CTRL pApCliWpsCtrl = NULL; + pApCliWpsCtrl = &pAd->ApCfg.ApCliTab[BSS0].WscControl; + + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS: Stop the ApCli WPS, state [%d]\n", pApCliWpsCtrl->WscState)); + + if ((pAd->conWscStatus != CON_WPS_STATUS_DISABLED) && + (pApCliWpsCtrl->WscState != WSC_STATE_OFF)) + { + WscStop(pAd, TRUE, pApCliWpsCtrl); + pApCliWpsCtrl->WscConfMode = WSC_DISABLE; + /* APCLI: For stop the other side of the band with WSC SM */ + WscConWpsStop(pAd, TRUE, pApCliWpsCtrl); + + } +#endif /* CON_WPS */ +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock); + WscInsertPeerEntryByMAC(&pWpsCtrl->WscPeerList, pEntry->Addr); + RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock); + + WscMaintainPeerList(pAd, pWpsCtrl); + + /* + Check this STA is first one or not + */ + if (pWpsCtrl->WscPeerList.size != 0) + { + pWscPeer = (PWSC_PEER_ENTRY)pWpsCtrl->WscPeerList.pHead; + if (NdisEqualMemory(pEntry->Addr, pWscPeer->mac_addr, MAC_ADDR_LEN) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("This is not first WSC peer, ignore this EAPOL_Start!\n")); + hex_dump("pEntry->Addr", pEntry->Addr, MAC_ADDR_LEN); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscApShowPeerList(pAd, NULL); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + WscStaShowPeerList(pAd, NULL); +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n")); + return; + } + } + + + + DBGPRINT(RT_DEBUG_TRACE, ("WscState = %d\n", pWpsCtrl->WscState)); + if ((pEntry->Receive_EapolStart_EapRspId == 0) || + (pWpsCtrl->WscState <= WSC_STATE_WAIT_REQ_ID)) + { + /* Receive the first EapolStart packet of this wps station. */ + pEntry->Receive_EapolStart_EapRspId |= WSC_ENTRY_GET_EAPOL_START; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPOLStartAction - receive EAPOL-Start from %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + + /* EapolStart packet is sent by station means this station wants to do wps process with AP. */ + pWpsCtrl->EapMsgRunning = TRUE; + /* Update EntryAddr again */ + NdisMoveMemory(pWpsCtrl->EntryAddr, pEntry->Addr, MAC_ADDR_LEN); + + if (pEntry->bWscCapable == FALSE) + pEntry->bWscCapable = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPOLStartAction(ra%d) - send EAP-Req(Id) to %02x:%02x:%02x:%02x:%02x:%02x\n", + pEntry->apidx, PRINT_MAC(pEntry->Addr))); + + /* Send EAP-Request/Id to station */ + WscSendEapReqId(pAd, pEntry, CurOpMode); + if (!pWpsCtrl->EapolTimerRunning) + { + pWpsCtrl->EapolTimerRunning = TRUE; + /* Set WPS_EAP Messages timeout function. */ + RTMPSetTimer(&pWpsCtrl->EapolTimer, WSC_EAP_ID_TIME_OUT); + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Ignore EAPOL-Start.\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n")); +} + + +/* + ========================================================================== + Description: + This is state machine function when receiving EAP packets + which is WPS Registration Protocol. + + There are two roles at our AP, as an + 1. Enrollee + 2. Internal Registrar + 3. Proxy + + There are two roles at our Station, as an + 1. Enrollee + 2. External Registrar + + Running Scenarios: + ----------------------------------------------------------------- + 1a. Adding an AP as an Enrollee to a station as an External Registrar (EAP) + [External Registrar]<----EAP--->[Enrollee_AP] + ----------------------------------------------------------------- + 2a. Adding a station as an Enrollee to an AP with built-in Registrar (EAP) + [Registrar_AP]<----EAP--->[Enrollee_STA] + ----------------------------------------------------------------- + 3a. Adding an Enrollee with External Registrar (UPnP/EAP) + [External Registrar]<----UPnP--->[Proxy_AP]<---EAP--->[Enrollee_STA] + ----------------------------------------------------------------- + + Return: + None + ========================================================================== +*/ +VOID WscEAPAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR MsgType; + BOOLEAN bUPnPMsg, Cancelled; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR MacAddr[MAC_ADDR_LEN] = {0}; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = MAIN_MBSSID; +#endif /* CONFIG_AP_SUPPORT */ + PWSC_CTRL pWscControl = NULL; + PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo = NULL; + UCHAR CurOpMode = 0xFF; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPAction\n")); + + /* The first 6 bytes in Elem->Msg is the MAC address of wps peer. */ + memmove(MacAddr, Elem->Msg, MAC_ADDR_LEN); + memmove(Elem->Msg, Elem->Msg+6, Elem->MsgLen); + +#ifdef DBG + hex_dump("(WscEAPAction)Elem->MsgLen", Elem->Msg, Elem->MsgLen); +#endif /* DBG */ + + MsgType = WscRxMsgType(pAdapter, Elem); + bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Addr: %02x:%02x:%02x:%02x:%02x:%02x, MsgType: 0x%02X, bUPnPMsg: %s\n", + PRINT_MAC(MacAddr), MsgType, bUPnPMsg ? "TRUE" : "FALSE")); + + if (!bUPnPMsg) + pEntry = MacTableLookup(pAdapter, MacAddr); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (!bUPnPMsg) + { + if (pEntry) + { + if (IS_ENTRY_CLIENT(pEntry) && pEntry->apidx >= pAdapter->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Unknow apidex(=%d).\n", pEntry->apidx)); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); + return; + } + else + { + apidx = pEntry->apidx; + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: apidex=%d.\n", pEntry->apidx)); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: pEntry is NULL.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); + return; + } +#ifdef APCLI_SUPPORT + /* for ap-client packets */ + if (pEntry && IS_ENTRY_APCLI(pEntry)) + pWscControl = &pAdapter->ApCfg.ApCliTab[apidx].WscControl; + else +#endif /* APCLI_SUPPORT */ + pWscControl = &pAdapter->ApCfg.MBSSID[apidx].WscControl; + } + else + { + int i; + for (i = 0 ; i < MAX_MBSSID_NUM(pAdapter); i++) + { + if(NdisEqualMemory(pAdapter->ApCfg.MBSSID[i].wdev.bssid, MacAddr, MAC_ADDR_LEN)) + { + apidx = i; + break; + } + } + pWscControl = &pAdapter->ApCfg.MBSSID[apidx].WscControl; + pWscUPnPNodeInfo = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscUPnPNodeInfo; + pWscUPnPNodeInfo->bUPnPMsgTimerPending = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pWscControl = &pAdapter->StaCfg.WscControl; + pWscUPnPNodeInfo = &pWscControl->WscUPnPNodeInfo; + pWscUPnPNodeInfo->bUPnPMsgTimerPending = TRUE; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pWscControl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__)); + return; + } + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + if ((MsgType == WSC_MSG_EAP_REG_RSP_ID) || (MsgType == WSC_MSG_EAP_ENR_RSP_ID)) + { + if (((pEntry->Receive_EapolStart_EapRspId & WSC_ENTRY_GET_EAP_RSP_ID) == WSC_ENTRY_GET_EAP_RSP_ID) + && (pWscControl->WscState > WSC_STATE_WAIT_M1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Already receive EAP_RSP(Identitry) from this STA, ignore it.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); + return; + } + else + pEntry->Receive_EapolStart_EapRspId |= WSC_ENTRY_GET_EAP_RSP_ID; + } + } + + pWscControl->EapolTimerPending = TRUE; + +#ifdef WSC_V2_SUPPORT + if (MsgType == WSC_MSG_EAP_FRAG_ACK) + { + WscSendEapFragData(pAdapter, pWscControl, pEntry); + return; + } + else +#endif /* WSC_V2_SUPPORT */ + if (MsgType == WSC_MSG_EAP_REG_RSP_ID) + { + /* Receive EAP-Response/Id from external registrar, so the role of AP is enrollee. */ + if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) || + (((pWscControl->WscConfMode & WSC_PROXY) != 0) && bUPnPMsg)) + { + pWscControl->WscActionMode= WSC_ENROLLEE; + pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0; + MsgType = WSC_MSG_EAP_RSP_ID; + WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_RSP_ID, pEntry, pWscControl); + } + } + else if (MsgType == WSC_MSG_EAP_ENR_RSP_ID) + { + /* Receive EAP-Response/Id from wps enrollee station, so the role of AP is Registrar or Proxy. */ + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Rx Identity\n")); + pWscControl->WscActionMode = WSC_REGISTRAR; + if (bUPnPMsg) + { + /* Receive enrollee identity from UPnP */ + } + else + { +#ifdef CONFIG_AP_SUPPORT + /* Receive enrollee identity from EAP */ + if ((pWscControl->WscMode == WSC_PBC_MODE) + ) + { + /* + Some WPS PBC Station select AP from UI directly; doesn't do PBC scan. + Need to check DPID from STA again here. + */ + WscPBC_DPID_FromSTA(pAdapter, pWscControl->EntryAddr); + WscPBCSessionOverlapCheck(pAdapter,pWscControl); + if ((pAdapter->CommonCfg.WscStaPbcProbeInfo.WscPBCStaProbeCount == 1) && + !NdisEqualMemory(pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN) && + (NdisEqualMemory(pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &pWscControl->EntryAddr[0], 6) == FALSE)) + { + pAdapter->CommonCfg.WscPBCOverlap = TRUE; + } + if (pAdapter->CommonCfg.WscPBCOverlap) + { + hex_dump("EntryAddr", pWscControl->EntryAddr, 6); + hex_dump("StaMacAddr0", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], 6); + hex_dump("StaMacAddr1", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[1], 6); + hex_dump("StaMacAddr2", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[2], 6); + hex_dump("StaMacAddr3", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[3], 6); + } + } + + if ((pWscControl->WscMode == WSC_PBC_MODE) && + (pAdapter->CommonCfg.WscPBCOverlap == TRUE)) + { + /* PBC session overlap */ + pWscControl->WscStatus = STATUS_WSC_PBC_SESSION_OVERLAP; + RTMPSendWirelessEvent(pAdapter, IW_WSC_PBC_SESSION_OVERLAP, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: PBC Session Overlap!\n")); +#ifdef CONFIG_AP_SUPPORT + WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_PBC_OVERLAP, + &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], MAC_ADDR_LEN, 0, 0, &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], AP_MODE); +#endif /* CONFIG_AP_SUPPORT */ + } + else +#endif /* CONFIG_AP_SUPPORT */ + if ((pWscControl->WscConfMode & WSC_PROXY_REGISTRAR) != 0) + { + /* Notify UPnP daemon before send Eap-Req(wsc-start) */ + DBGPRINT(RT_DEBUG_TRACE, ("%s: pEntry->Addr=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + WscSendUPnPConfReqMsg(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + (PUCHAR)pAdapter->ApCfg.MBSSID[pEntry->apidx].Ssid, pEntry->Addr, 2, 0, CurOpMode); + /* Reset the UPnP timer and status. */ + if (pWscControl->bM2DTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled); + pWscControl->bM2DTimerRunning = FALSE; + } + pWscControl->WscUPnPNodeInfo.registrarID = 0; + pWscControl->M2DACKBalance = 0; + WscDelWPARetryTimer(pAdapter); + } +#endif /* CONFIG_AP_SUPPORT */ + pWscControl->EapMsgRunning = TRUE; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M1; + /* send EAP WSC_START */ + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + pWscControl->bWscLastOne = TRUE; + if (CurOpMode == AP_MODE) + WscSendMessage(pAdapter, WSC_OPCODE_START, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ); + else + { + if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode == WSC_REGISTRAR)) + WscSendMessage(pAdapter, WSC_OPCODE_START, NULL, 0, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, WSC_OPCODE_START, NULL, 0, pWscControl, STA_MODE, EAP_CODE_RSP); + } + } + } + } + } + else if (MsgType == WSC_MSG_EAP_REQ_ID) + { + /* Receive EAP_Req/Identity from WPS AP or WCN */ + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP_Req/Identity from WPS AP or WCN\n")); + if (bUPnPMsg && (pWscControl->WscConfMode == WSC_ENROLLEE)) + { + pWscControl->WscActionMode = WSC_ENROLLEE; + pWscControl->WscUseUPnP = 1; + WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_REQ_START, pEntry, pWscControl); + } + else + { + /* Receive EAP_Req/Identity from WPS AP */ + if (pEntry != NULL) + WscSendEapRspId(pAdapter, pEntry, pWscControl); + } + + if (!bUPnPMsg) + { + if ((pWscControl->WscState < WSC_STATE_WAIT_M1) || + (pWscControl->WscState > WSC_STATE_WAIT_ACK)) + { + if (pWscControl->WscConfMode == WSC_REGISTRAR) + pWscControl->WscState = WSC_STATE_WAIT_M1; + else + pWscControl->WscState = WSC_STATE_WAIT_WSC_START; + } + } + } + else if (MsgType == WSC_MSG_EAP_REQ_START) + { + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP_Req(Wsc_Start) from WPS AP\n")); + + /* Receive EAP_Req(Wsc_Start) from WPS AP */ + if (pWscControl->WscConfMode == WSC_ENROLLEE) + { + pWscControl->WscActionMode = WSC_ENROLLEE; + pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0; + WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_REQ_START, pEntry, pWscControl); + + if (!pWscControl->EapolTimerRunning) + { + pWscControl->EapolTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->EapolTimer, WSC_EAP_ID_TIME_OUT); + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Ignore EAP_Req(Wsc_Start) from WPS AP\n")); + } + else if (MsgType == WSC_MSG_EAP_FAIL) + { + /* Receive EAP_Fail from WPS AP */ + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP_Fail from WPS AP\n")); + +/*If APClinet wirh registrar configures AP as Inband(EAP)-Enrollee, it will send WSC_MSG_EAP_FAIL to us. */ + if ((pWscControl->WscState >= WSC_STATE_WAIT_EAPFAIL) || + ((pWscControl->WscState == WSC_STATE_WAIT_ACK) && + (pEntry && IS_ENTRY_CLIENT(pEntry)) && + (pWscControl->WscStatus == STATUS_WSC_CONFIGURED) && + ((pWscControl->WscConfMode & WSC_ENROLLEE) != 0))) + { + pWscControl->WscState = WSC_STATE_OFF; +#ifdef CONFIG_AP_SUPPORT + pWscControl->WscConfMode = WSC_DISABLE; +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef CON_WPS + /* ApCli: WPS Done notify the other side of band to stop */ + if (pAdapter->conWscStatus != CON_WPS_STATUS_DISABLED) + { + WscConWpsStop(pAdapter, TRUE, pWscControl); + pAdapter->conWscStatus = CON_WPS_STATUS_DISABLED; + } +#endif /* CON_WPS */ + /* Bring apcli interface down first */ + if(pEntry && IS_ENTRY_APCLI(pEntry) && pAdapter->ApCfg.ApCliTab[BSS0].Enable == TRUE ) + { + pAdapter->ApCfg.ApCliTab[pEntry->apidx].Enable = FALSE; + ApCliIfDown(pAdapter); + pAdapter->ApCfg.ApCliTab[pEntry->apidx].Enable = TRUE; + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { +#ifdef IWSC_SUPPORT + if ((pAdapter->OpMode == OPMODE_STA) && + (pAdapter->StaCfg.BssType == BSS_ADHOC) && + (pAdapter->StaCfg.WscControl.WscConfMode == WSC_ENROLLEE)) + pAdapter->StaCfg.IWscInfo.bReStart = TRUE; +#endif /* IWSC_SUPPORT */ + pWscControl->WscConfMode = WSC_DISABLE; + WscLinkDown(pAdapter); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else if (pWscControl->WscState == WSC_STATE_RX_M2D) + { + /* Wait M2; */ +#ifdef IWSC_SUPPORT + /* + We need to send EAPOL_Start again to trigger WPS process + */ + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + { + pWscControl->WscState = WSC_STATE_LINK_UP; + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + WscSendEapolStart(pAdapter, pWscControl->WscPeerMAC, STA_MODE); + } +#endif /* IWSC_SUPPORT */ + } + else if ((pWscControl->WscState <= WSC_STATE_WAIT_REQ_ID) && + (pWscControl->WscState != WSC_STATE_FAIL)) + { + /* Ignore. D-Link DIR-628 AP sometimes would send EAP_Fail to station after Link UP first then send EAP_Req/Identity. */ + } + else + { + pWscControl->WscStatus = STATUS_WSC_FAIL; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + +#ifdef IWSC_SUPPORT + if ((pAdapter->OpMode == OPMODE_STA) && + (pAdapter->StaCfg.BssType == BSS_ADHOC) && + (pAdapter->StaCfg.WscControl.WscConfMode == WSC_ENROLLEE)) + pAdapter->StaCfg.IWscInfo.bReStart = TRUE; +#endif /* IWSC_SUPPORT */ + + pWscControl->WscConfMode = WSC_DISABLE; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_OFF; + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + WscLinkDown(pAdapter); + + } +#endif /* CONFIG_STA_SUPPORT */ + } + } + else if (MsgType == WSC_MSG_M1) + { +#ifdef CONFIG_STA_SUPPORT + UINT32 rv = 0; +#endif + /* + If Buffalo WPS STA doesn't receive M2D from AP, Buffalo WPS STA will stop to do WPS. + Therefore we need to receive M1 and send M2D without trigger. + */ + if ((pWscControl->WscConfMode & WSC_REGISTRAR) != 0) + { + pWscControl->WscActionMode = WSC_REGISTRAR; + /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP_M1 */ + if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress) + { + DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP M1.\n")); + goto out; + } + else + WscEapRegistrarAction(pAdapter, Elem, MsgType, pEntry, pWscControl); +#ifdef CONFIG_STA_SUPPORT + rv = 1; +#endif + } +#ifdef CONFIG_AP_SUPPORT + if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE)) + { + if ((pWscControl->bWscTrigger + ) + && (pWscControl->WscState >= WSC_STATE_WAIT_M3)) + ; + else + { + pWscControl->WscActionMode = WSC_PROXY; + WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } + } + else if ((!pWscControl->bWscTrigger) && ((pWscControl->WscConfMode & WSC_PROXY) == 0) && (pAdapter->OpMode == OPMODE_AP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscTrigger is FALSE, ignore EAP M1.\n")); + goto out; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + else + { + if ((rv == 0) && (CurOpMode == STA_MODE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("(Line:%d)Ignore EAP M1.\n", __LINE__)); + goto out; + } + } +#endif /* CONFIG_STA_SUPPORT */ + } + else if (MsgType == WSC_MSG_M3 || + MsgType == WSC_MSG_M5 || + MsgType == WSC_MSG_M7 || + MsgType == WSC_MSG_WSC_DONE) + { + BOOLEAN bNonceMatch = WscCheckNonce(pAdapter, Elem, TRUE, pWscControl); + if (((pWscControl->WscConfMode & WSC_REGISTRAR) != 0) && + (pWscControl->bWscTrigger + ) && + bNonceMatch) + { + /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP Messages */ + if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress) + { + DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP Messages.\n")); + goto out; + } + else + { + pWscControl->WscActionMode = WSC_REGISTRAR; + WscEapRegistrarAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } + } +#ifdef CONFIG_AP_SUPPORT + else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE)) + { + pWscControl->WscActionMode = WSC_PROXY; + WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (MsgType == WSC_MSG_M2 || + MsgType == WSC_MSG_M2D || + MsgType == WSC_MSG_M4 || + MsgType == WSC_MSG_M6 || + MsgType == WSC_MSG_M8) + { + BOOLEAN bNonceMatch = WscCheckNonce(pAdapter, Elem, FALSE, pWscControl); + BOOLEAN bGoWPS = FALSE; + + if ((CurOpMode == AP_MODE) || + ((CurOpMode == STA_MODE) && + (pWscControl->bWscTrigger +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + ))) + bGoWPS = TRUE; + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((CurOpMode == AP_MODE) && + ((pWscControl->WscV2Info.bWpsEnable == FALSE) && (pWscControl->WscV2Info.bEnableWpsV2))) + bGoWPS = FALSE; +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) && + bGoWPS && + bNonceMatch) + { + pWscControl->WscActionMode = WSC_ENROLLEE; + pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0; + if (MsgType == WSC_MSG_M2) + { + BOOLEAN bReadOwnPIN = TRUE; +#ifdef CONFIG_AP_SUPPORT + /* WPS Enrollee AP only supports PIN without trigger */ + if (CurOpMode == AP_MODE) + { + if (pWscControl->bWscTrigger == FALSE) + { + pWscControl->WscMode = 1; + WscGetConfWithoutTrigger(pAdapter, pWscControl, FALSE); + } + else + { + WscBuildBeaconIE(pAdapter, + pWscControl->WscConfStatus, + TRUE, + pWscControl->WscMode, + pWscControl->WscConfigMethods, + (pWscControl->EntryIfIdx & 0x0F), + NULL, + 0, + AP_MODE); + WscBuildProbeRespIE(pAdapter, + WSC_MSGTYPE_AP_WLAN_MGR, + pWscControl->WscConfStatus, + TRUE, + pWscControl->WscMode, + pWscControl->WscConfigMethods, + pWscControl->EntryIfIdx, + NULL, + 0, + AP_MODE); + APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IWSC_SUPPORT + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + bReadOwnPIN = FALSE; +#endif /* IWSC_SUPPORT */ + + if (bReadOwnPIN) + { + pWscControl->WscPinCodeLen = pWscControl->WscEnrolleePinCodeLen; + WscGetRegDataPIN(pAdapter, pWscControl->WscEnrolleePinCode, pWscControl); + DBGPRINT(RT_DEBUG_TRACE, ("(%d) WscEnrolleePinCode: %08u\n", bReadOwnPIN, pWscControl->WscEnrolleePinCode)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("WscPinCode: %08u\n", pWscControl->WscPinCode)); + } + /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP Messages */ + if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress) + { + DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP Messages.\n")); + goto out; + } + else + WscEapEnrolleeAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } +#ifdef CONFIG_AP_SUPPORT + else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (bUPnPMsg) && (CurOpMode == AP_MODE)) + { + pWscControl->WscActionMode = WSC_PROXY; + WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (MsgType == WSC_MSG_WSC_ACK) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscState: %d\n", pWscControl->WscState)); + if (((pWscControl->WscConfMode & WSC_REGISTRAR) != 0) && + pWscControl->WscState <= WSC_STATE_SENT_M2D) + { + if (WscCheckNonce(pAdapter, Elem, TRUE, pWscControl)) + { + if (pWscControl->M2DACKBalance > 0) + pWscControl->M2DACKBalance--; + pWscControl->WscState = WSC_STATE_INIT; + pWscControl->EapMsgRunning = FALSE; + } + } + else + { + if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) && + WscCheckNonce(pAdapter, Elem, FALSE, pWscControl)) + { + pWscControl->WscActionMode = WSC_ENROLLEE; + pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0; + WscEapEnrolleeAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } +#ifdef CONFIG_AP_SUPPORT + else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (CurOpMode == AP_MODE)) + { + pWscControl->WscActionMode = WSC_PROXY; + WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } +#endif /* CONFIG_AP_SUPPORT */ + } + } + else if (MsgType == WSC_MSG_WSC_NACK) + { + BOOLEAN bReSetWscIE = FALSE; + if (bUPnPMsg && (pWscControl->WscState == WSC_STATE_WAIT_M8) && + (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED)) + { + // Some external sta will send NACK when AP is configured. + // bWscTrigger should be set FALSE, otherwise Proxy will send NACK to enrollee. + pWscControl->bWscTrigger = FALSE; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + bReSetWscIE = TRUE; + } + if (!bUPnPMsg && + (WscCheckNonce(pAdapter, Elem, FALSE, pWscControl) || WscCheckNonce(pAdapter, Elem, TRUE, pWscControl))) + { + USHORT config_error = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Receive NACK from WPS client.\n")); + WscGetConfigErrFromNack(pAdapter, Elem, &config_error); + /* + If a PIN authentication or communication error occurs, + the Registrar MUST warn the user and MUST NOT automatically reuse the PIN. + Furthermore, if the Registrar detects this situation and prompts the user for a new PIN from the Enrollee device, + it MUST NOT accept the same PIN again without warning the user of a potential attack. + */ + if ((pWscControl->WscState >= WSC_STATE_WAIT_M5) && (config_error != WSC_ERROR_SETUP_LOCKED)) + { + pWscControl->WscRejectSamePinFromEnrollee = TRUE; + pWscControl->WscPinCode = 0; + + if (pWscControl->WscState < WSC_STATE_WAIT_M8) + { + pWscControl->WscStatus = STATUS_WSC_FAIL; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + bReSetWscIE = TRUE; + } + } + +#ifdef CONFIG_AP_SUPPORT + if ((pWscControl->WscState == WSC_STATE_OFF) + && (CurOpMode == AP_MODE) + && (pWscControl->RegData.SelfInfo.ConfigError != WSC_ERROR_NO_ERROR)) + { + bReSetWscIE = TRUE; + } +#endif /* CONFIG_AP_SUPPORT */ + + if ((pWscControl->WscState == WSC_STATE_WAIT_M8) && + (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED)) + { + /* Some external sta will send NACK when AP is configured. */ + /* bWscTrigger should be set FALSE, otherwise Proxy will send NACK to enrollee. */ + pWscControl->bWscTrigger = FALSE; + bReSetWscIE = TRUE; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } +#ifdef CONFIG_AP_SUPPORT + else if ((CurOpMode == AP_MODE) && + (pWscControl->WscState == WSC_STATE_WAIT_DONE) && + (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) && + (pAdapter->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled)) + { + bReSetWscIE = TRUE; + pWscControl->WscStatus = STATUS_WSC_FAIL; + } + + if ((CurOpMode == AP_MODE) && bReSetWscIE) + { + WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F); + if (pWscControl->Wsc2MinsTimerRunning) + { + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + pWscControl->Wsc2MinsTimerRunning = FALSE; + } + if (pWscControl->bWscTrigger) + pWscControl->bWscTrigger = FALSE; + } +#endif // CONFIG_AP_SUPPORT // + + if ((CurOpMode == AP_MODE) + || ((ADHOC_ON(pAdapter)) && (pWscControl->WscConfMode == WSC_REGISTRAR)) + ) + { + WscSendEapFail(pAdapter, pWscControl, TRUE); + pWscControl->WscState = WSC_STATE_FAIL; + } +#ifdef CONFIG_STA_SUPPORT + else if ((CurOpMode == STA_MODE) && INFRA_ON(pAdapter)) + { + WscEapActionDisabled(pAdapter, pWscControl); + pWscControl->WscState = WSC_STATE_WAIT_DISCONN; + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + pWscControl->RegData.ReComputePke = 1; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unsupported Msg Type (%02X)\n", MsgType)); + pWscControl->WscStatus = STATUS_WSC_FAIL; + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR; + WscSendNACK(pAdapter, pEntry, pWscControl); + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, BSS0, 0); + goto out; + } + + if (bUPnPMsg) + { + /* Messages from UPnP */ + if (pWscUPnPNodeInfo->bUPnPMsgTimerRunning) + RTMPModTimer(&pWscUPnPNodeInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT); + } + else + { + if ((pWscControl->EapMsgRunning == TRUE) && + (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + /* Messages from EAP */ + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + pWscControl->EapolTimerRunning = TRUE; + } + } + + if (bUPnPMsg && pWscControl->EapolTimerRunning) + { +#ifdef CONFIG_AP_SUPPORT + if ((pWscControl->WscActionMode == WSC_PROXY) && (CurOpMode == AP_MODE)) + { + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + } + } + +out: + if (bUPnPMsg) + pWscUPnPNodeInfo->bUPnPMsgTimerPending = FALSE; + + pWscControl->EapolTimerPending = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); +} + +/* + ============================================================================ + Enrollee Enrollee Enrollee + ============================================================================ +*/ +VOID WscEapEnrolleeAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + INT DataLen = 0, rv = 0, DH_Len = 0; + UCHAR OpCode/*, bssIdx = 0*/; + PUCHAR WscData = NULL; + BOOLEAN bUPnPMsg, bUPnPStatus = FALSE, Cancelled; + WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + UCHAR CurOpMode = 0xFF; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction Enter!\n")); + + bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE; + OpCode = bUPnPMsg ? WSC_OPCODE_UPNP_MASK : 0; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + /* Early check. */ + if ((pWscControl->WscActionMode != WSC_ENROLLEE) || + (pWscControl->WscUseUPnP && pEntry) || + ((pWscControl->WscUseUPnP == 0) && (!pEntry))) + { + DBGPRINT(RT_DEBUG_TRACE, ("EarlyCheckFailed: pWscControl->WscActionMode=%d, Configured=%d, WscUseUPnP=%d, pEntry=%p!\n", + pWscControl->WscActionMode, pWscControl->WscConfStatus, pWscControl->WscUseUPnP, pEntry)); + goto Fail; + } + /* bssIdx = (pWscControl->EntryIfIdx & 0x0F);*/ + } +#endif /* CONFIG_AP_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("MsgType=0x%x, WscState=%d, bUPnPMsg=%d!\n", MsgType, pWscControl->WscState, bUPnPMsg)); + + if (bUPnPMsg) + { +#ifdef CONFIG_AP_SUPPORT + if ((MsgType == WSC_MSG_EAP_RSP_ID) && (CurOpMode == AP_MODE)) + { + /* let it pass */ + } else +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if ((MsgType ==WSC_MSG_EAP_REQ_START) && (CurOpMode == STA_MODE)) + { + /*let it pass */ + } else + #endif /* CONFIG_STA_SUPPORT */ + if(MsgType ==WSC_MSG_M2 && pWscUPnPInfo->bUPnPInProgress == FALSE) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + MAC_TABLE_ENTRY *tempEntry; + tempEntry = MacTableLookup(pAdapter, &pWscControl->EntryAddr[0]); + if (tempEntry) + { + if((tempEntry->Receive_EapolStart_EapRspId & WSC_ENTRY_GET_EAP_RSP_ID) == WSC_ENTRY_GET_EAP_RSP_ID) + { + goto Done; + } + } + /* else cannot find the pEntry, so we need to handle this msg. */ + } +#endif /* CONFIG_AP_SUPPORT */ + pWscUPnPInfo->bUPnPInProgress = TRUE; + /* Set the WscState as "WSC_STATE_WAIT_RESP_ID" because UPnP start from this state. */ + /* pWscControl->WscState = WSC_STATE_WAIT_RESP_ID; */ + RTMPSetTimer(&pWscUPnPInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT); + pWscUPnPInfo->bUPnPMsgTimerRunning = TRUE; + } + else + { + /* For other messages, we must make sure pWscUPnPInfo->bUPnPInProgress== TRUE */ + if (pWscUPnPInfo->bUPnPInProgress == FALSE) + { + goto Done; + } + } + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); +/* if( (WscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) == NULL) */ + if (WscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n")); + goto Fail; + } + NdisZeroMemory(WscData, MaxWscDataLen); + + switch (MsgType) + { + case WSC_MSG_EAP_RSP_ID: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx Identity(ReComputePke=%d)\n", pWscControl->RegData.ReComputePke)); + case WSC_MSG_EAP_REQ_START: + if (MsgType == WSC_MSG_EAP_REQ_START) + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx Wsc_Start(ReComputePke=%d)\n", pWscControl->RegData.ReComputePke)); + + /* To avoid to receive duplicate WSC_START */ + if(pWscControl->WscState >= WSC_STATE_SENT_M1) + { + DBGPRINT(RT_DEBUG_TRACE, ("Already received this WSC_START, ignore it\n")); + goto Done; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + ; /* Do NOT need to generate EnrolleeRandom and DH public key here. */ + else +#endif /* WSC_NFC_SUPPORT */ + { +#ifdef CONFIG_AP_SUPPORT + /* + We don't need to consider P2P case. + */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + { + if ((pWscControl->bWscAutoTriggerDisable == TRUE) && + (pWscControl->bWscTrigger == FALSE)) + { + if (bUPnPMsg == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%d): WscAutoTrigger is disabled.\n", __FUNCTION__, __LINE__)); + WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart); + os_free_mem(NULL, WscData); + return; + } + else if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%d): WscAutoTrigger is disabled! Send EapFail to STA.\n", __FUNCTION__, __LINE__)); + WscSendEapFail(pAdapter, pWscControl, TRUE); + os_free_mem(NULL, WscData); + return; + } + else + ; /* Keep going. APCLI shall be the else case. */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pWscControl->RegData.ReComputePke == 1) + { + INT idx; + DH_Len = sizeof(pWscControl->RegData.Pke); + /* Enrollee 192 random bytes for DH key generation */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter); + NdisZeroMemory(pWscControl->RegData.Pke, sizeof(pWscControl->RegData.Pke)); + RT_DH_PublicKey_Generate ( + WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE), + WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE), + pWscControl->RegData.EnrolleeRandom, sizeof(pWscControl->RegData.EnrolleeRandom), + pWscControl->RegData.Pke, (UINT *) &DH_Len); + + /* Need to prefix zero padding */ + if((DH_Len != sizeof(pWscControl->RegData.Pke)) && + (DH_Len < sizeof(pWscControl->RegData.Pke))) + { + UCHAR TempKey[192]; + INT DiffCnt; + DiffCnt = sizeof(pWscControl->RegData.Pke) - DH_Len; + + NdisFillMemory(&TempKey, DiffCnt, 0); + NdisCopyMemory(&TempKey[DiffCnt], pWscControl->RegData.Pke, DH_Len); + NdisCopyMemory(pWscControl->RegData.Pke, TempKey, sizeof(TempKey)); + DH_Len += DiffCnt; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Do zero padding!\n", __func__)); + } + pWscControl->RegData.ReComputePke = 0; + } + } + OpCode |= WSC_OPCODE_MSG; + + DataLen = BuildMessageM1(pAdapter, pWscControl, WscData); + if(!bUPnPMsg) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + WscDelWPARetryTimer(pAdapter); + } +#endif /* CONFIG_AP_SUPPORT */ + pWscControl->EapMsgRunning = TRUE; + pWscControl->WscStatus = STATUS_WSC_EAP_M1_SENT; + } + else + /* Sometime out-of-band registrars (ex: Vista) get M1 for collecting information of device. */ + pWscControl->WscStatus = STATUS_WSC_IDLE; + + /* Change the state to next one */ + if (pWscControl->WscState < WSC_STATE_SENT_M1) + pWscControl->WscState = WSC_STATE_SENT_M1; + + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M1, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + break; + + case WSC_MSG_M2: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M2\n")); + + /* Receive M2, if we are at WSC_STATE_WAIT_M2 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_SENT_M1 || + pWscControl->WscState == WSC_STATE_RX_M2D) + { + /* Process M2 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M2_RECEIVED; + + NdisMoveMemory(pWscControl->RegData.PeerInfo.MacAddr, pWscControl->EntryAddr, 6); + if ((rv = ProcessMessageM2(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, (pWscControl->EntryIfIdx & 0x0F), &pWscControl->RegData))) + { + goto Fail; + } + else + { +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock) + { + rv = WSC_ERROR_SETUP_LOCKED; + goto Fail; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER ) + { + /* NFC handover Skip M3~M8 */ + OpCode |= WSC_OPCODE_DONE; + DataLen = BuildMessageDONE(pAdapter, pWscControl, WscData); + //pWscControl->WscStatus = STATUS_WSC_EAP_M3_SENT; + pWscControl->WscState = WSC_STATE_WAIT_ACK; + pWscControl->PinAttackCount = 0; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_DONE, NULL, pWscControl->EntryIfIdx, 0); + } + else +#endif /* WSC_NFC_SUPPORT */ + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM3(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M3_SENT; + + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M4; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M3, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + } + break; + + case WSC_MSG_M2D: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M2D\n")); + + /* Receive M2D, if we are at WSC_STATE_WAIT_M2 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_SENT_M1 || + pWscControl->WscState == WSC_STATE_RX_M2D) + { + BOOLEAN bReplyNack = FALSE; + + if ((rv = ProcessMessageM2D(pAdapter, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + + pWscControl->WscStatus = STATUS_WSC_EAP_M2D_RECEIVED; + + if ((CurOpMode == STA_MODE) + ) + { + bReplyNack = FALSE; + } + else + { + bReplyNack = TRUE; +#ifdef APCLI_SUPPORT + if (pEntry && !IS_ENTRY_APCLI(pEntry)) + bReplyNack = TRUE; + else + bReplyNack = FALSE; +#endif + } + + if (bReplyNack) + { + /* For VISTA SP1 internal registrar test */ + OpCode |= WSC_OPCODE_NACK; + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR; + DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData); + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_NACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + else + { + /* When external registrar is Marvell station, */ + /* wps station sends NACK may confuse or reset Marvell wps state machine. */ + OpCode |= WSC_OPCODE_ACK; + DataLen = BuildMessageACK(pAdapter, pWscControl, WscData); + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_ACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + + + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_RX_M2D; + } + break; + + case WSC_MSG_M4: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M4\n")); + + /* Receive M4, if we are at WSC_STATE_WAIT_M4 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_WAIT_M4) + { + /* Process M4 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M4_RECEIVED; + if ((rv = ProcessMessageM4(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscCheckPinAttackCount(pAdapter, pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + goto Fail; + } + else + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM5(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M5_SENT; + + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M6; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M5, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + break; + + case WSC_MSG_M6: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M6\n")); + + /* Receive M6, if we are at WSC_STATE_WAIT_M6 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_WAIT_M6) + { + /* Process M6 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M6_RECEIVED; + if ((rv=ProcessMessageM6(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscCheckPinAttackCount(pAdapter, pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + goto Fail; + } + else + { + OpCode |= WSC_OPCODE_MSG; + + DataLen = BuildMessageM7(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M7_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M8; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M7, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + /* + Complete WPS with this STA. Delete it from WscPeerList for others STA to do WSC with AP + */ + if (pEntry) + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + } + } + break; + + case WSC_MSG_M8: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M8\n")); + + /* Receive M8, if we are at WSC_STATE_WAIT_M6 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_WAIT_M8) + { + /* Process M8 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M8_RECEIVED; + if ((rv=ProcessMessageM8(pAdapter, Elem->Msg, Elem->MsgLen, pWscControl))) + goto Fail; + else + { + OpCode |= WSC_OPCODE_DONE; + DataLen = BuildMessageDONE(pAdapter, pWscControl, WscData); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + /* Change the state to next one */ +#ifdef APCLI_SUPPORT + /* Ap Client only supports Inband(EAP)-Enrollee. */ + if (!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry)) + pWscControl->WscState = WSC_STATE_WAIT_EAPFAIL; + else +#endif /* APCLI_SUPPORT */ + pWscControl->WscState = WSC_STATE_WAIT_ACK; + +#ifdef CONFIG_AP_SUPPORT + WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_M8, + &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], MAC_ADDR_LEN, 0, 0, &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], AP_MODE); +#endif /* CONFIG_AP_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pWscControl->WscState = WSC_STATE_WAIT_EAPFAIL; + pWscControl->WscStatus = STATUS_WSC_EAP_RSP_DONE_SENT; + } +#endif /* CONFIG_STA_SUPPORT */ + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_DONE, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + break; + +#ifdef CONFIG_AP_SUPPORT + case WSC_MSG_WSC_ACK: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx ACK\n")); + + /* Receive ACK */ + if (pWscControl->WscState == WSC_STATE_WAIT_ACK) + { + /* Process ACK */ + pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_ACK; + /* Send out EAP-Fail */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + pWscControl->WscState = WSC_STATE_CONFIGURED; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + } + break; +#endif /* CONFIG_AP_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Unsupported Msg Type\n")); + break; + } + + if (bUPnPMsg) + { + if ((MsgType == WSC_MSG_M8) && (pWscControl->WscState == WSC_STATE_WAIT_ACK)) + { + pWscControl->EapMsgRunning = FALSE; + pWscControl->WscState = WSC_STATE_CONFIGURED; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + if(pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + pWscUPnPInfo->registrarID = 0; + } + } + else + { + if (((MsgType == WSC_MSG_WSC_ACK) && (pWscControl->WscState == WSC_STATE_CONFIGURED)) || + ((MsgType == WSC_MSG_M8) && (pWscControl->WscState == WSC_STATE_WAIT_ACK))) + { + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + pWscControl->EapMsgRunning = FALSE; + /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */ + } + } + + if(OpCode > WSC_OPCODE_UPNP_MASK) + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), WSC_OPCODE_UPNP_DATA, + WSC_UPNP_DATA_SUB_NORMAL, WscData, DataLen, + Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart, + &pAdapter->CurrentAddress[0], CurOpMode); + else if(OpCode > 0 && OpCode < WSC_OPCODE_UPNP_MASK) + { + if (pWscControl->WscState != WSC_STATE_CONFIGURED) + { +#ifdef WSC_V2_SUPPORT + pWscControl->WscTxBufLen = 0; + pWscControl->pWscCurBufIdx = NULL; + pWscControl->bWscLastOne = TRUE; + if (pWscControl->bWscFragment && (DataLen > pWscControl->WscFragSize)) + { + ASSERT(DataLen < MGMT_DMA_BUFFER_SIZE); + NdisMoveMemory(pWscControl->pWscTxBuf, WscData, DataLen); + pWscControl->WscTxBufLen = DataLen; + NdisZeroMemory(WscData, DataLen); + pWscControl->bWscLastOne = FALSE; + pWscControl->bWscFirstOne = TRUE; + NdisMoveMemory(WscData, pWscControl->pWscTxBuf, pWscControl->WscFragSize); + DataLen = pWscControl->WscFragSize; + pWscControl->WscTxBufLen -= pWscControl->WscFragSize; + pWscControl->pWscCurBufIdx = (pWscControl->pWscTxBuf + pWscControl->WscFragSize); + } +#endif /* WSC_V2_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + else + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_RSP); +#endif /* CONFIG_STA_SUPPORT */ + } + } + else + bUPnPStatus = TRUE; + +Fail: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : rv = %d\n", rv)); + if (rv) + { +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock) + rv = WSC_ERROR_SETUP_LOCKED; +#endif /* CONFIG_AP_SUPPORT */ + + if (rv <= WSC_ERROR_DEV_PWD_AUTH_FAIL) + pWscControl->RegData.SelfInfo.ConfigError = rv; + else if ((rv == WSC_ERROR_HASH_FAIL) || (rv == WSC_ERROR_HMAC_FAIL)) + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_DECRYPT_CRC_FAIL; + + switch(rv) + { + case WSC_ERROR_DEV_PWD_AUTH_FAIL: + pWscControl->WscStatus = STATUS_WSC_ERROR_DEV_PWD_AUTH_FAIL; + break; + default: + pWscControl->WscStatus = STATUS_WSC_FAIL; + break; + } + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + if (bUPnPMsg) + { + if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + } + else + WscSendNACK(pAdapter, pEntry, pWscControl); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl->WscState = WSC_STATE_OFF; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pWscControl->WscState = WSC_STATE_WAIT_DISCONN; + if (pWscControl->WscSsid.SsidLength) + { + pAdapter->MlmeAux.AutoReconnectSsidLen = pWscControl->WscSsid.SsidLength; + NdisZeroMemory(&pAdapter->MlmeAux.AutoReconnectSsid[0], MAX_LEN_OF_SSID); + NdisMoveMemory(&pAdapter->MlmeAux.AutoReconnectSsid[0], + &pWscControl->WscSsid.Ssid[0], + pWscControl->WscSsid.SsidLength); + } + else + pAdapter->MlmeAux.AutoReconnectSsidLen = 0; + } +#endif /* CONFIG_STA_SUPPORT */ + + /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */ + /*pWscControl->WscMode = 1; */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + + bUPnPStatus = FALSE; + if(pWscControl->WscMode == WSC_PBC_MODE) + { +#ifdef SMART_MESH_MONITOR + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.wps_pbc_stat.type = NSMPIF_DRVEVNT_WPS_PBC_STAT; + drvevnt.data.wps_pbc_stat.stat = NSMP_WPS_PBC_STAT_END_TIMEOUT; + drvevnt.data.wps_pbc_stat.reason = 1; + drvevnt.data.wps_pbc_stat.channel = pAdapter->CommonCfg.Channel; +#ifdef SMART_MESH + if(pWscControl->bWscPBCAddrMode) + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->WscPBCAddr); + else +#endif /* SMART_MESH */ + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->EntryAddr); + RtmpOSWrielessEventSend(pAdapter->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_WPS_PBC_STAT, + NULL, (PUCHAR)&drvevnt.data.wps_pbc_stat, sizeof(drvevnt.data.wps_pbc_stat)); + DBGPRINT(RT_DEBUG_OFF, + ("Send Custom Wireless Event. (NSMPIF_DRVEVNT_WPS_PBC_STAT:NSMP_WPS_PBC_STAT_END_TIMEOUT(Reason :%d))\n",drvevnt.data.wps_pbc_stat.reason)); +#endif /* SMART_MESH_MONITOR */ +#ifdef SMART_MESH + pWscControl->bWscPBCAddrMode = FALSE; +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + Set_HiddenWps_State(&pAdapter->ApCfg.ApCliTab[(pWscControl->EntryIfIdx & 0x0F)].SmartMeshCfg, + HIDDEN_WPS_STATE_STOP); +#endif /* APCLI_SUPPORT */ +#endif /* SMART_MESH */ + } + } + +Done: + if(WscData) + os_free_mem(NULL, WscData); + if(bUPnPMsg && (bUPnPStatus == FALSE)) + WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart); + + rv = 0; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (((bUPnPMsg || (pEntry && IS_ENTRY_CLIENT(pEntry))) + && (pWscControl->WscState == WSC_STATE_CONFIGURED || pWscControl->WscState == WSC_STATE_WAIT_ACK)) +#ifdef APCLI_SUPPORT + ||((!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry)) && (pWscControl->WscState == WSC_STATE_WAIT_EAPFAIL || pWscControl->WscState == WSC_STATE_CONFIGURED)) +#endif /* APCLI_SUPPORT */ + ) + { + rv = 1; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if ((pWscControl->WscState == WSC_STATE_WAIT_EAPFAIL) || + (pWscControl->WscState == WSC_STATE_CONFIGURED)) + { + rv = 1; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (rv == 1) + { +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + pWscControl->bWscTrigger = FALSE; + pWscControl->RegData.ReComputePke = 1; + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } +#ifdef IWSC_SUPPORT + if ((pAdapter->OpMode == OPMODE_STA) && (pAdapter->StaCfg.BssType == BSS_ADHOC)) + { + pAdapter->StaCfg.IWscInfo.bReStart = TRUE; + if (pAdapter->StaCfg.IWscInfo.bIWscT1TimerRunning) + { + pAdapter->StaCfg.IWscInfo.bIWscT1TimerRunning = FALSE; + RTMPCancelTimer(&pAdapter->StaCfg.IWscInfo.IWscT1Timer, &Cancelled); + } + pAdapter->StaCfg.IWscInfo.bIWscDevQueryReqTimerRunning = TRUE; + } +#endif /* IWSC_SUPPORT */ + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) +#ifdef CONFIG_AP_SUPPORT + || (pWscControl->bWCNTest == TRUE) + || ((CurOpMode == AP_MODE) && !pWscControl->bSetupLock) +#endif /* CONFIG_AP_SUPPORT */ + ) + { +#ifdef SMART_MESH + pWscControl->bWscPBCAddrMode = FALSE; +#ifdef SMART_MESH_HIDDEN_WPS + pWscControl->bRunningHiddenWPS = FALSE; +#ifdef CONFIG_AP_SUPPORT + if((CurOpMode == AP_MODE) && !bUPnPMsg && pEntry) + { +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pEntry)) + Set_HiddenWps_State(&pAdapter->ApCfg.ApCliTab[(pWscControl->EntryIfIdx & 0x0F)].SmartMeshCfg, + HIDDEN_WPS_STATE_STOP); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* SMART_MESH */ +#ifdef SMART_MESH_MONITOR + if((pWscControl->WscMode == WSC_PBC_MODE)) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.wps_pbc_stat.type = NSMPIF_DRVEVNT_WPS_PBC_STAT; + drvevnt.data.wps_pbc_stat.stat = NSMP_WPS_PBC_STAT_END_SUCCESS; + drvevnt.data.wps_pbc_stat.reason = 0; + drvevnt.data.wps_pbc_stat.channel = pAdapter->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->EntryAddr,MAC_ADDR_LEN); + RtmpOSWrielessEventSend(pAdapter->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_WPS_PBC_STAT, + NULL, (PUCHAR)&drvevnt.data.wps_pbc_stat, sizeof(drvevnt.data.wps_pbc_stat)); + DBGPRINT(RT_DEBUG_OFF, + ("Send Custom Wireless Event. (NSMPIF_DRVEVNT_WPS_PBC_STAT:NSMP_WPS_PBC_STAT_END_SUCCESS)\n")); + } +#endif /* SMART_MESH_MONITOR */ + + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED; + pWscControl->WscMode = 1; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + + + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl->RegData.SelfInfo.ScState = pWscControl->WscConfStatus; +#ifdef APCLI_SUPPORT + if (!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry)) + { + POS_COOKIE pObj = (POS_COOKIE) pAdapter->OS_Cookie; + INT old_if_type = pObj->ioctl_if_type; + pObj->ioctl_if_type = INT_APCLI; + WscWriteConfToApCliCfg(pAdapter, pWscControl, &pWscControl->WscProfile.Profile[0], TRUE); + pObj->ioctl_if_type = old_if_type; +/*#ifdef KTHREAD_SUPPORT */ +/* WAKE_UP(&(pAdapter->wscTask)); */ +/*#else */ +/* RTMP_SEM_EVENT_UP(&(pAdapter->wscTask.taskSema)); */ +/*#endif */ + RtmpOsTaskWakeUp(&(pAdapter->wscTask)); + } + else +#endif /* APCLI_SUPPORT */ + { + RTMPSetTimer(&pWscControl->WscUpdatePortCfgTimer, 1000); + pWscControl->WscUpdatePortCfgTimerRunning = TRUE; + } + + if (bUPnPMsg || (pEntry && IS_ENTRY_CLIENT(pEntry))) + { + WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pWscControl->WscConfMode = WSC_DISABLE; + if (bUPnPMsg) + { + pWscControl->WscState = WSC_STATE_OFF; + WscLinkDown(pAdapter); + } + if (pWscControl->WscDriverAutoConnect != 0) + { + pAdapter->StaCfg.bAutoConnectByBssid = TRUE; + pWscControl->WscProfile.ApplyProfileIdx = 0; /* add by johnli, fix WPS test plan 5.1.1 */ + { + WscWriteConfToPortCfg(pAdapter, pWscControl, &pWscControl->WscProfile.Profile[0], TRUE); + pAdapter->WriteWscCfgToDatFile = (pWscControl->EntryIfIdx & 0x0F); + + RtmpOsTaskWakeUp(&(pAdapter->wscTask)); + } +#ifdef IWSC_SUPPORT + if ((pAdapter->StaCfg.BssType == BSS_ADHOC)&& + (pAdapter->StaCfg.IWscInfo.bIWscDevQueryReqTimerRunning == FALSE)) + { + pAdapter->StaCfg.IWscInfo.bIWscDevQueryReqTimerRunning = TRUE; + RTMPSetTimer(&pAdapter->StaCfg.IWscInfo.IWscDevQueryTimer, 200); + } +#endif /* IWSC_SUPPORT */ + } + } +#endif /* CONFIG_STA_SUPPORT */ + + } +#ifdef WSC_LED_SUPPORT + /* The protocol is finished. */ + WPSLEDStatus = LED_WPS_SUCCESS; + RTMPSetLED(pAdapter, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + } +} + +#ifdef CONFIG_AP_SUPPORT +/* + ============================================================================ + Proxy Proxy Proxy + ============================================================================ +*/ +VOID WscEapApProxyAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + PUCHAR WscData = NULL; + BOOLEAN sendToUPnP = FALSE, bUPnPStatus = FALSE, Cancelled; + int reqID = 0; + WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction Enter!\n")); + + if (Elem->MsgType == WSC_EAPOL_UPNP_MSG) + { + reqID = Elem->TimeStamp.u.LowPart; + if(reqID > 0) + sendToUPnP = TRUE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction():pEntry=%p, ElemMsgType=%ld, MsgType=%d!\n", pEntry, Elem->MsgType, MsgType)); + + if ((pWscControl->WscActionMode != WSC_PROXY) || + ((Elem->MsgType == WSC_EAPOL_PACKET_MSG) && (pEntry == NULL))) + { + DBGPRINT(RT_DEBUG_TRACE, ("EarlyCheckFailed: gWscActionMode=%d, pEntry=%p!\n", pWscControl->WscActionMode, pEntry)); + goto Fail; + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); + if (WscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n")); + goto Fail; + } + NdisZeroMemory(WscData, MaxWscDataLen); + + /* Base on state doing the Msg, State change diagram */ + if (Elem->MsgType == WSC_EAPOL_UPNP_MSG) + { /* WSC message send from UPnP. */ + switch (MsgType) + { + case WSC_MSG_M2: + case WSC_MSG_M4: + case WSC_MSG_M6: + case WSC_MSG_M8: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg(%d) from UPnP, eventID=0x%x!\n", MsgType, reqID)); + WscSendMessage(pAdapter, WSC_OPCODE_MSG, Elem->Msg, Elem->MsgLen, pWscControl, AP_MODE, EAP_CODE_REQ); + + /*Notify the UPnP daemon which remote registar is negotiating with enrollee. */ + if (MsgType == WSC_MSG_M2) + { + pWscUPnPInfo->registrarID = Elem->TimeStamp.u.HighPart; + DBGPRINT(RT_DEBUG_TRACE, ("%s():registrarID=0x%x!\n", __FUNCTION__, pWscUPnPInfo->registrarID)); + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_REG_SELECT, + (PUCHAR)(&pWscUPnPInfo->registrarID), sizeof(UINT), 0, 0, NULL, AP_MODE); + + /*Reset the UPnP timer and status. */ + if (pWscControl->bM2DTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled); + pWscControl->bM2DTimerRunning = FALSE; + } + pWscControl->M2DACKBalance = 0; + pWscUPnPInfo->registrarID = 0; + } + if (MsgType == WSC_MSG_M8) + { + WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F); + } + break; + + case WSC_MSG_M2D: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg M2D(%d) from UPnP, eventID=0x%x!\n", MsgType, reqID)); + + /*If it's send by UPnP Action, response ok directly to remote UPnP Control Point! */ + if (reqID > 0) + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_ACK, + 0, 0, reqID, 0, NULL, AP_MODE); + + /*Send M2D to wireless station. */ + WscSendMessage(pAdapter, WSC_OPCODE_MSG, Elem->Msg, Elem->MsgLen, pWscControl, AP_MODE, EAP_CODE_REQ); + pWscControl->M2DACKBalance++; + if ((pWscUPnPInfo->registrarID == 0) && (pWscControl->bM2DTimerRunning == FALSE)) + { + /* Add M2D timer used to trigger the EAPFail Packet! */ + RTMPSetTimer(&pWscControl->M2DTimer, WSC_UPNP_M2D_TIME_OUT); + pWscControl->bM2DTimerRunning = TRUE; + } + break; + + case WSC_MSG_WSC_NACK: + default: + DBGPRINT(RT_DEBUG_TRACE, ("Recv WscMsg(%d) from UPnP, request EventID=%d! drop it!\n", MsgType, reqID)); + break; + } + } + else + { /*WSC msg send from EAP. */ + switch (MsgType) + { + case WSC_MSG_M1: + case WSC_MSG_M3: + case WSC_MSG_M5: + case WSC_MSG_M7: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg(%d) from EAP\n", MsgType)); + /*This msg send to event-based external registrar */ + if (MsgType == WSC_MSG_M1) + { + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ALL, + Elem->Msg, Elem->MsgLen, 0, 0, &pWscControl->EntryAddr[0], AP_MODE); + pWscControl->WscState = WSC_STATE_SENT_M1; + } + else + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ALL, + Elem->Msg, Elem->MsgLen, 0, pWscUPnPInfo->registrarID, + &pWscControl->EntryAddr[0], AP_MODE); + + break; + + case WSC_MSG_WSC_ACK: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WSC_ACK from EAP\n")); + + /* The M2D must appeared before the ACK, so we just need sub it when (pWscUPnPInfo->M2DACKBalance > 0) */ + if (pWscControl->M2DACKBalance > 0) + pWscControl->M2DACKBalance--; + break; + + case WSC_MSG_WSC_DONE: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WSC_DONE from EAP\n")); + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: send WSC_DONE to UPnP Registrar!\n")); + /*Send msg to event-based external registrar */ + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ONE, + Elem->Msg, Elem->MsgLen, 0, + pWscUPnPInfo->registrarID, &pWscControl->EntryAddr[0], AP_MODE); + + /*Send EAPFail to wireless station to finish the whole process. */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + + pEntry->bWscCapable = FALSE; + pWscControl->EapMsgRunning = FALSE; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Recv WSC Msg(%d) from EAP , it's impossible, drop it!\n", MsgType)); + break; + } + } + +Fail: + if (WscData) + os_free_mem(NULL, WscData); + if (sendToUPnP && (bUPnPStatus == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Need to send UPnP but bUPnPStatus is false!MsgType=%d, regID=0x%x!\n", MsgType, reqID)); + WscUPnPErrHandle(pAdapter, pWscControl, reqID); + } + +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ============================================================================ + Registrar Registrar Registrar + ============================================================================ +*/ +VOID WscEapRegistrarAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + INT DataLen = 0, rv = 0; + UCHAR OpCode = 0; + UCHAR *WscData = NULL; + BOOLEAN bUPnPMsg, bUPnPStatus = FALSE, Cancelled, isApCli = FALSE; + WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + UCHAR CurOpMode = 0xFF; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction Enter!\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + isApCli = TRUE; +#endif /* APCLI_SUPPORT */ +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif // CONFIG_STA_SUPPORT // + + bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE; + + if(bUPnPMsg) + { + if(MsgType == WSC_MSG_M1) + { /* It's a M1 message, we may need to initialize our state machine. */ + if ((pWscControl->WscActionMode == WSC_REGISTRAR) + && (pWscControl->EntryIfIdx == WSC_INIT_ENTRY_APIDX) + && (pWscControl->WscState < WSC_STATE_WAIT_M1) + && (pWscUPnPInfo->bUPnPInProgress == FALSE)) + { + pWscUPnPInfo->bUPnPInProgress = TRUE; + /*Set the WscState as "WSC_STATE_WAIT_RESP_ID" because UPnP start from this state. */ + pWscControl->WscState = WSC_STATE_WAIT_M1; + RTMPSetTimer(&pWscUPnPInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT); + pWscUPnPInfo->bUPnPMsgTimerRunning = TRUE; + } + } + OpCode = WSC_OPCODE_UPNP_MASK; + + } else { + if (pWscControl->EapolTimerRunning) + pWscControl->EapolTimerRunning = FALSE; + + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); + if (WscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n")); + goto Fail; + } + NdisZeroMemory(WscData, MaxWscDataLen); + + /* Base on state doing the Msg, State change diagram */ + switch (MsgType) + { + case WSC_MSG_M1: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M1\n")); + + /* Receive M1, if we are at WSC_STATE_WAIT_M1 start, process it immediately */ + pWscControl->WscStatus = STATUS_WSC_EAP_M1_RECEIVED; + if (pWscControl->WscState == WSC_STATE_WAIT_M1) + { + OpCode |= WSC_OPCODE_MSG; + + /* Process M1 */ + if ((rv=ProcessMessageM1(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + else + { + BOOLEAN bSendM2D = TRUE; + + + if (pWscControl->bWscTrigger && (!pWscControl->bWscAutoTigeer)) + { + if (((pWscControl->WscMode == WSC_PBC_MODE) || (pWscControl->WscMode == WSC_SMPBC_MODE)) + || (pWscControl->WscMode == WSC_PIN_MODE && pWscControl->WscPinCode != 0)) + bSendM2D = FALSE; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + bSendM2D = FALSE; + if (pWscControl->RegData.SelfInfo.ConfigError == WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH) + { + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH ConfigError=%d \n", pWscControl->RegData.SelfInfo.ConfigError)); + bSendM2D = TRUE; + } + } +#endif /* WSC_NFC_SUPPORT */ + + if (bSendM2D) + { + DataLen = BuildMessageM2D(pAdapter, pWscControl, WscData); + pWscControl->WscState = WSC_STATE_SENT_M2D; + pWscControl->M2DACKBalance++; + if (pWscControl->bM2DTimerRunning == FALSE) + { + // Add M2D timer used to trigger the EAPFail Packet! + RTMPSetTimer(&pWscControl->M2DTimer, WSC_UPNP_M2D_TIME_OUT); + pWscControl->bM2DTimerRunning = TRUE; + } + } + else + { + pWscControl->WscStatus = STATUS_WSC_EAP_M2_SENT; + DataLen = BuildMessageM2(pAdapter, pWscControl, WscData); + + /* Change the state to next one */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + pWscControl->WscState = WSC_STATE_WAIT_DONE; /* Skip M3~M8 */ + } + else +#endif /* WSC_NFC_SUPPORT */ + pWscControl->WscState = WSC_STATE_WAIT_M3; +#ifdef CONFIG_STA_SUPPORT + if ((CurOpMode == STA_MODE) && INFRA_ON(pAdapter)) + { + if (!bUPnPMsg) + pWscControl->WscConfStatus = pWscControl->bConfiguredAP ? WSC_SCSTATE_UNCONFIGURED : WSC_SCSTATE_CONFIGURED; + } +#endif /* CONFIG_STA_SUPPORT */ + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M2, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + } + break; + + case WSC_MSG_M3: + /* Receive M3 */ + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M3\n")); + if (pWscControl->WscState == WSC_STATE_WAIT_M3) + { + pWscControl->WscStatus = STATUS_WSC_EAP_M3_RECEIVED; + + if((rv = ProcessMessageM3(pAdapter, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + else + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM4(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M4_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M5; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M4, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + break; + + case WSC_MSG_M5: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M5\n")); + if (pWscControl->WscState == WSC_STATE_WAIT_M5) + { + pWscControl->WscStatus = STATUS_WSC_EAP_M5_RECEIVED; + + if ((rv=ProcessMessageM5(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + else + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM6(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M6_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M7; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M6, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + break; + case WSC_MSG_M7: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M7\n")); + if (pWscControl->WscState == WSC_STATE_WAIT_M7) + { + pWscControl->WscStatus = STATUS_WSC_EAP_M7_RECEIVED; + if ((rv=ProcessMessageM7(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + else + { + if ( +#ifdef CONFIG_AP_SUPPORT + /* Restrict to Normal AP & ApCli not go in */ + ((CurOpMode == AP_MODE) && !isApCli) || + ((CurOpMode == AP_MODE) && isApCli && (pWscControl->bConfiguredAP == FALSE)) || +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + ((CurOpMode == STA_MODE) && ((pWscControl->bConfiguredAP == FALSE) +#ifdef WSC_V2_SUPPORT + /* + Check AP is v2 or v1, Check WscV2 Enabled or not + */ + || (pWscControl->WscV2Info.bForceSetAP + && pWscControl->WscV2Info.bEnableWpsV2 + && (pWscControl->RegData.PeerInfo.Version2!= 0)) +#endif /* WSC_V2_SUPPORT */ + )) || +#endif /* CONFIG_STA_SUPPORT */ + (0)) + { + OpCode |= WSC_OPCODE_MSG; +#ifdef IWSC_SUPPORT + if ((pAdapter->OpMode == OPMODE_STA) && (pAdapter->StaCfg.BssType == BSS_ADHOC)) + pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED; +#endif /* IWSC_SUPPORT */ + DataLen = BuildMessageM8(pAdapter, pWscControl, isApCli, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M8_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_DONE; +#ifdef CONFIG_AP_SUPPORT + /* + If APUT is Registrar + send event to wscd / miniupnpd , to let it query crendential and sync to system's flash & GUI. + */ + WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_WSC_DONE, + &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], MAC_ADDR_LEN, 0, 0, &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], AP_MODE); +#endif /* CONFIG_AP_SUPPORT */ + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M8, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2 && (CurOpMode == AP_MODE) && !isApCli) + WscAddEntryToAclList(pAdapter, pEntry->apidx, pEntry->Addr); +#endif /* WSC_V2_SUPPORT */ + /* + 1. Complete WPS with this STA. Delete it from WscPeerList for others STA to do WSC with AP + 2. Some WPS STA will send dis-assoc close to WSC_DONE + then AP will miss WSC_DONE from STA; hence we need to call WscDelListEntryByMAC here. + */ + if (pEntry && (CurOpMode == AP_MODE) && !isApCli) + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } +#endif /* CONFIG_AP_SUPPORT */ + + } + else if ((FALSE +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +|| ((CurOpMode == AP_MODE) && isApCli) +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +|| (CurOpMode == STA_MODE) +#endif /* CONFIG_STA_SUPPORT */ + ) && (pWscControl->bConfiguredAP == TRUE)) + { + /* Some WPS AP expects to receive WSC_NACK when AP is configured */ + OpCode |= WSC_OPCODE_NACK; + DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->WscState = WSC_STATE_CONFIGURED; + pWscControl->EapMsgRunning = FALSE; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_NACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + } + break; + + case WSC_MSG_WSC_DONE: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx DONE\n")); + if (pWscControl->WscState == WSC_STATE_WAIT_DONE) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_DONE_SENT; + /* Send EAP-Fail */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + +#ifdef CON_WPS + /* AP: stop the other side of band */ + if (pAdapter->conWscStatus != CON_WPS_STATUS_DISABLED) + { + WscConWpsStop(pAdapter, FALSE, pWscControl); + pAdapter->conWscStatus = CON_WPS_STATUS_DISABLED; + } +#endif /* CON_WPS */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if ((CurOpMode == STA_MODE) && ADHOC_ON(pAdapter)) + { + WscSendEapFail(pAdapter, pWscControl, FALSE); + } + else + { + OpCode |= WSC_OPCODE_ACK; + DataLen = BuildMessageACK(pAdapter, pWscControl, WscData); + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_ACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } +#ifdef IWSC_SUPPORT + if ((pAdapter->StaCfg.BssType == BSS_ADHOC) && + (pWscControl->WscMode == WSC_SMPBC_MODE)) + { + pAdapter->StaCfg.IWscInfo.IWscSmpbcAcceptCount--; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + + if (pEntry && pEntry->bIWscSmpbcAccept) + { + pEntry->bIWscSmpbcAccept = FALSE; + WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr); + } + pAdapter->StaCfg.IWscInfo.SmpbcEnrolleeCount++; + } + else +#endif /* IWSC_SUPPORT */ + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + } +#endif /* CONFIG_STA_SUPPORT */ + + pWscControl->WscState = WSC_STATE_CONFIGURED; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + pWscControl->EapMsgRunning = FALSE; + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Unsupported Msg Type\n")); + if (WscData) + os_free_mem(NULL, WscData); + return; + } + + if(OpCode > WSC_OPCODE_UPNP_MASK) + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL, + WscData, DataLen, + Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart, &pWscControl->EntryAddr[0], CurOpMode); + else if(OpCode > 0 && OpCode < WSC_OPCODE_UPNP_MASK) + { +#ifdef WSC_V2_SUPPORT + pWscControl->WscTxBufLen = 0; + pWscControl->pWscCurBufIdx = NULL; + pWscControl->bWscLastOne = TRUE; + if (pWscControl->bWscFragment && (DataLen > pWscControl->WscFragSize)) + { + ASSERT(DataLen < MGMT_DMA_BUFFER_SIZE); + NdisMoveMemory(pWscControl->pWscTxBuf, WscData, DataLen); + pWscControl->WscTxBufLen = DataLen; + NdisZeroMemory(WscData, DataLen); + pWscControl->bWscLastOne = FALSE; + pWscControl->bWscFirstOne = TRUE; + NdisMoveMemory(WscData, pWscControl->pWscTxBuf, pWscControl->WscFragSize); + DataLen = pWscControl->WscFragSize; + pWscControl->WscTxBufLen -= pWscControl->WscFragSize; + pWscControl->pWscCurBufIdx = (pWscControl->pWscTxBuf + pWscControl->WscFragSize); + } +#endif /* WSC_V2_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((pWscControl->WscState != WSC_STATE_CONFIGURED) && (!isApCli)) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); +#ifdef APCLI_SUPPORT + if(isApCli) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAdapter)) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + + } + else + bUPnPStatus = TRUE; + + if(bUPnPMsg) + { + if(pWscControl->WscState == WSC_STATE_SENT_M2D) + { /*After M2D, reset the status of State Machine. */ + pWscControl->WscState = WSC_STATE_WAIT_UPNP_START; + pWscUPnPInfo->bUPnPInProgress = FALSE; + } + } +Fail: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : rv = %d\n", rv)); + if (rv) + { + if (rv <= WSC_ERROR_DEV_PWD_AUTH_FAIL) + { + pWscControl->RegData.SelfInfo.ConfigError = rv; + } + else if ((rv == WSC_ERROR_HASH_FAIL) || (rv == WSC_ERROR_HMAC_FAIL)) + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_DECRYPT_CRC_FAIL; + + switch(rv) + { + case WSC_ERROR_HASH_FAIL: + pWscControl->WscStatus = STATUS_WSC_ERROR_HASH_FAIL; + break; + case WSC_ERROR_HMAC_FAIL: + pWscControl->WscStatus = STATUS_WSC_ERROR_HMAC_FAIL; + break; + default: + pWscControl->WscStatus = STATUS_WSC_FAIL; + break; + } + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + if (bUPnPMsg) + { + if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + } + else + { + DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + pEntry->bWscCapable = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAdapter)) + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + } + /* + If a PIN authentication or communication error occurs after sending message M6, + the Registrar MUST warn the user and MUST NOT automatically reuse the PIN. + Furthermore, if the Registrar detects this situation and prompts the user for a new PIN from the Enrollee device, + it MUST NOT accept the same PIN again without warning the user of a potential attack. + */ + if (pWscControl->WscState >= WSC_STATE_WAIT_M7) + { + pWscControl->WscRejectSamePinFromEnrollee = TRUE; + pWscControl->WscPinCode = 0; + } + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_IDLE; + /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */ + /*pWscControl->WscMode = 1; */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + + bUPnPStatus = FALSE; + if(pWscControl->WscMode == WSC_PBC_MODE) + { +#ifdef SMART_MESH_MONITOR + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.wps_pbc_stat.type = NSMPIF_DRVEVNT_WPS_PBC_STAT; + drvevnt.data.wps_pbc_stat.stat = NSMP_WPS_PBC_STAT_END_TIMEOUT; + drvevnt.data.wps_pbc_stat.reason = 1; + drvevnt.data.wps_pbc_stat.channel = pAdapter->CommonCfg.Channel; +#ifdef SMART_MESH + if(pWscControl->bWscPBCAddrMode) + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->WscPBCAddr); + else +#endif /* SMART_MESH */ + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->EntryAddr); + RtmpOSWrielessEventSend(pAdapter->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_WPS_PBC_STAT, + NULL, (PUCHAR)&drvevnt.data.wps_pbc_stat, sizeof(drvevnt.data.wps_pbc_stat)); + DBGPRINT(RT_DEBUG_OFF, + ("Send Custom Wireless Event. (NSMPIF_DRVEVNT_WPS_PBC_STAT:NSMP_WPS_PBC_STAT_END_TIMEOUT(Reason :%d))\n",drvevnt.data.wps_pbc_stat.reason)); +#endif /* SMART_MESH_MONITOR */ +#ifdef SMART_MESH + pWscControl->bWscPBCAddrMode = FALSE; +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + Set_HiddenWps_State(&pAdapter->ApCfg.ApCliTab[(pWscControl->EntryIfIdx & 0x0F)].SmartMeshCfg, + HIDDEN_WPS_STATE_STOP); +#endif /* APCLI_SUPPORT */ +#endif /* SMART_MESH */ + } + } + + if(WscData) + os_free_mem(NULL, WscData); + + if(bUPnPMsg && (bUPnPStatus == FALSE)) + WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart); + + if (pWscControl->WscState == WSC_STATE_CONFIGURED) + { +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + + pWscControl->bWscTrigger = FALSE; +#ifdef IWSC_SUPPORT + if ((pAdapter->OpMode == OPMODE_STA) && + (pAdapter->StaCfg.BssType == BSS_ADHOC)) + { + if (pAdapter->StaCfg.IWscInfo.bSinglePIN) + { + pAdapter->StaCfg.IWscInfo.bDoNotStop = TRUE; + } + else + pAdapter->StaCfg.IWscInfo.bDoNotStop = FALSE; + RTMP_SEM_LOCK(&pWscControl->WscConfiguredPeerListSemLock); + WscInsertPeerEntryByMAC(&pWscControl->WscConfiguredPeerList, pWscControl->WscPeerMAC); + RTMP_SEM_UNLOCK(&pWscControl->WscConfiguredPeerListSemLock); + NdisZeroMemory(pWscControl->WscPeerMAC, MAC_ADDR_LEN); // We need to clear here for 4-way handshaking + MlmeEnqueue(pAdapter, IWSC_STATE_MACHINE, IWSC_MT2_MLME_STOP, 0, NULL, 0); + RTMP_MLME_HANDLER(pAdapter); + } +#endif /* IWSC_SUPPORT */ + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } + if (bUPnPMsg) + { + if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + pWscUPnPInfo->registrarID = 0; + } +#ifdef CONFIG_AP_SUPPORT + else + { +#ifdef SMART_MESH + pWscControl->bWscPBCAddrMode = FALSE; +#ifdef SMART_MESH_HIDDEN_WPS + pWscControl->bRunningHiddenWPS = FALSE; +#ifdef CONFIG_AP_SUPPORT + if((CurOpMode == AP_MODE)) + { +#ifdef APCLI_SUPPORT + if(isApCli) + Set_HiddenWps_State(&pAdapter->ApCfg.ApCliTab[(pWscControl->EntryIfIdx & 0x0F)].SmartMeshCfg, + HIDDEN_WPS_STATE_STOP); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* SMART_MESH */ + + if (CurOpMode == AP_MODE && !isApCli) + { + WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pEntry->apidx, NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + APUpdateBeaconFrame(pAdapter, pEntry->apidx); + } +#ifdef SMART_MESH_MONITOR + if(pWscControl->WscMode == WSC_PBC_MODE) + { + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.wps_pbc_stat.type = NSMPIF_DRVEVNT_WPS_PBC_STAT; + drvevnt.data.wps_pbc_stat.stat = NSMP_WPS_PBC_STAT_END_SUCCESS; + drvevnt.data.wps_pbc_stat.reason = 0; + drvevnt.data.wps_pbc_stat.channel = pAdapter->CommonCfg.Channel; + NdisCopyMemory(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->EntryAddr,MAC_ADDR_LEN); + RtmpOSWrielessEventSend(pAdapter->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_WPS_PBC_STAT, + NULL, (PUCHAR)&drvevnt.data.wps_pbc_stat, sizeof(drvevnt.data.wps_pbc_stat)); + DBGPRINT(RT_DEBUG_OFF, + ("Send Custom Wireless Event. (NSMPIF_DRVEVNT_WPS_PBC_STAT:NSMP_WPS_PBC_STAT_END_SUCCESS)\n")); + } +#endif /* SMART_MESH_MONITOR */ + } + NdisZeroMemory(&pAdapter->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { +#ifdef IWSC_SUPPORT + if (pAdapter->StaCfg.IWscInfo.bDoNotStop == FALSE) +#endif /* IWSC_SUPPORT */ + pWscControl->WscConfMode = WSC_DISABLE; + + if (pAdapter->StaCfg.BssType == BSS_INFRA) + pWscControl->WscState = WSC_STATE_WAIT_EAPFAIL; + } +#endif /* CONFIG_STA_SUPPORT */ + if (INFRA_ON(pAdapter) || + ( + (pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) && + ((CurOpMode == AP_MODE) || (ADHOC_ON(pAdapter))) + ) + ) + { + pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED; +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (isApCli) + { + DBGPRINT(RT_DEBUG_TRACE,("Write the Config for APCLI\n")); + if (pWscControl->bConfiguredAP) + { + RTMPMoveMemory(&pWscControl->WscProfile, &pWscControl->WscM7Profile, + sizeof(pWscControl->WscM7Profile)); + } + pWscControl->WscConfMode=WSC_DISABLE; + WscWriteConfToApCliCfg(pAdapter, pWscControl, &pWscControl->WscProfile.Profile[0], TRUE); + RtmpOsTaskWakeUp(&(pAdapter->wscTask)); + } + else +#endif /* APCLI_SUPPORT */ + { + /* + Use ApplyProfileIdx to inform WscUpdatePortCfgTimer AP acts registrar. + */ + pWscControl->WscProfile.ApplyProfileIdx |= 0x8000; + RTMPSetTimer(&pWscControl->WscUpdatePortCfgTimer, 1000); + pWscControl->WscUpdatePortCfgTimerRunning = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pAdapter->StaCfg.bAutoConnectByBssid = TRUE; + if ((pWscControl->bConfiguredAP) +#ifdef WSC_V2_SUPPORT + /* + Check AP is v2 or v1, Check WscV2 Enabled or not + */ + && !(pWscControl->WscV2Info.bForceSetAP + && pWscControl->WscV2Info.bEnableWpsV2 + && (pWscControl->RegData.PeerInfo.Version2!= 0)) +#endif /* WSC_V2_SUPPORT */ + ) + RTMPMoveMemory(&pWscControl->WscProfile, &pWscControl->WscM7Profile, sizeof(pWscControl->WscM7Profile)); + + WscWriteConfToPortCfg(pAdapter, pWscControl, &pWscControl->WscProfile.Profile[0], TRUE); + + { +/*#ifdef KTHREAD_SUPPORT */ + /* WAKE_UP(&(pAdapter->wscTask)); */ + /*#else */ + /* RTMP_SEM_EVENT_UP(&(pAdapter->wscTask.taskSema)); */ + /*#endif */ + RtmpOsTaskWakeUp(&(pAdapter->wscTask)); + } +#ifdef IWSC_SUPPORT + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + { + if (pAdapter->StaCfg.IWscInfo.bDoNotStop == FALSE) + { + WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, BSS0, NULL, 0, STA_MODE); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_REGISTRAR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, BSS0, NULL, 0, STA_MODE); + } + pAdapter->StaCfg.IWscInfo.bReStart = TRUE; + WscLinkDown(pAdapter); + if (pAdapter->StaCfg.IWscInfo.bIWscDevQueryReqTimerRunning == FALSE) + { + pAdapter->StaCfg.IWscInfo.bIWscDevQueryReqTimerRunning = TRUE; + RTMPSetTimer(&pAdapter->StaCfg.IWscInfo.IWscDevQueryTimer, 200); + } + } +#endif /* IWSC_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + } +#ifdef WSC_LED_SUPPORT + /* The protocol is finished. */ + WPSLEDStatus = LED_WPS_SUCCESS; + RTMPSetLED(pAdapter, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ +#ifdef IWSC_SUPPORT + if (pAdapter->StaCfg.IWscInfo.bDoNotStop == FALSE) +#endif /* IWSC_SUPPORT */ + { + pWscControl->WscPinCode = 0; + pWscControl->WscMode = 1; + } + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + +#ifdef IWSC_SUPPORT + /* + Some peer doesn't stop beacon and send de-auth, it will cause 4-way failed when our MAC is higher than peer. + After WPS process complete, delete entry here for adding entry to table again for 4-way handshaking. + */ + if (pEntry && (pAdapter->StaCfg.BssType == BSS_ADHOC)) + MacTableDeleteEntry(pAdapter, pEntry->wcid, pEntry->Addr); +#endif /* IWSC_SUPPORT */ + return; + } +} + +VOID WscTimeOutProcess( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN INT nWscState, + IN PWSC_CTRL pWscControl) +{ + INT WscMode; + UCHAR CurOpMode = 0xFF; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif // CONFIG_STA_SUPPORT // + + if (nWscState == WSC_STATE_WAIT_ACK) + pWscControl->WscState = WSC_STATE_CONFIGURED; + else if (nWscState == WSC_STATE_WAIT_RESP_ID) + pWscControl->WscState = WSC_STATE_OFF; + else if (nWscState == WSC_STATE_RX_M2D) + { + pWscControl->WscState = WSC_STATE_FAIL; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + WscSendEapFail(pAd, pWscControl, TRUE); + } +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + WscApCliLinkDown(pAd, pWscControl); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + pWscControl->EapolTimerRunning = FALSE; + pWscControl->WscRetryCount = 0; + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + WscLinkDown(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + + return; + } + else if (nWscState == WSC_STATE_WAIT_EAPFAIL) + { + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->WscConfMode = WSC_DISABLE; + } + else + { +#ifdef CONFIG_AP_SUPPORT + if ((pWscControl->WscActionMode == WSC_PROXY) && (pAd->OpMode == OPMODE_AP)) + { + pWscControl->WscState = WSC_STATE_OFF; + } + else +#endif /* CONFIG_AP_SUPPORT */ + pWscControl->WscState = WSC_STATE_FAIL; + } + + if (nWscState == WSC_STATE_WAIT_M8) + pWscControl->bWscTrigger = FALSE; + pWscControl->WscRetryCount = 0; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + pWscControl->EapolTimerRunning = FALSE; + if (pWscControl->WscMode == 1) + WscMode = DEV_PASS_ID_PIN; + else + WscMode = DEV_PASS_ID_PBC; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) && + ((nWscState == WSC_STATE_WAIT_DONE) || (nWscState == WSC_STATE_WAIT_ACK))) + { + pWscControl->bWscTrigger = FALSE; + pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED; + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + pAd->WriteWscCfgToDatFile = pWscControl->EntryIfIdx; + WscWriteConfToPortCfg(pAd, + pWscControl, + &pWscControl->WscProfile.Profile[0], + FALSE); + { + APStop(pAd); + APStartUp(pAd); + } + +/*#ifdef KTHREAD_SUPPORT */ +/* WAKE_UP(&(pAd->wscTask)); */ +/*#else */ +/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema)); */ +/*#endif */ + RtmpOsTaskWakeUp(&(pAd->wscTask)); + } + else + { + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + pEntry->bWscCapable = FALSE; + WscSendEapFail(pAd, pWscControl, TRUE); + } + + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + } +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + WscApCliLinkDown(pAd, pWscControl); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + WscLinkDown(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("WscTimeOutProcess\n")); +} + +VOID WscEAPOLTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PUCHAR WscData = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + PWSC_CTRL pWscControl = NULL; + PRTMP_ADAPTER pAd = NULL; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + UCHAR CurOpMode = 0xFF; + UCHAR WscMaxRetryCount = 2; + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPOLTimeOutAction\n")); + + if (FunctionContext == 0) + { + return; + } + else + { + pWscControl = (PWSC_CTRL)FunctionContext; + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + if (pAd == NULL) + { + return; + } + pEntry = MacTableLookup(pWscControl->pAd, pWscControl->EntryAddr); +#ifdef SMART_MESH_HIDDEN_WPS + if(pEntry && pEntry->bHyperFiPeer) + WscMaxRetryCount = 5; +#endif /* SMART_MESH_HIDDEN_WPS */ + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif // CONFIG_STA_SUPPORT // + + if ((CurOpMode == AP_MODE) || ADHOC_ON(pAd)) + { + if (pEntry == NULL) + { +#ifdef CONFIG_AP_SUPPORT + /* + Some WPS Client will send dis-assoc close to WSC_DONE. + If AP misses WSC_DONE, WPS Client still sends dis-assoc to AP. + AP driver needs to check wsc_state here for considering WPS process with this client is completed. + */ + if ((CurOpMode == AP_MODE) && + ((pWscControl->WscState == WSC_STATE_WAIT_DONE) || (pWscControl->WscState == WSC_STATE_WAIT_ACK))) + { + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->bWscTrigger = FALSE; + pWscControl->RegData.ReComputePke = 1; + if (pWscControl->Wsc2MinsTimerRunning) + { + BOOLEAN Cancelled; + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } + WscTimeOutProcess(pAd, NULL, pWscControl->WscState, pWscControl); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IWSC_SUPPORT +#ifdef CONFIG_STA_SUPPORT + + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->StaCfg.WscControl.WscConfMode == WSC_ENROLLEE)) + pAd->StaCfg.IWscInfo.bReStart = TRUE; + +#endif // CONFIG_STA_SUPPORT // +#endif // IWSC_SUPPORT // + pWscControl->EapolTimerRunning = FALSE; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("sta is left.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n")); + return; + } + } + + if (!pWscControl->EapolTimerRunning) + { + pWscControl->WscRetryCount = 0; + goto out; + } + + if (pWscControl->EapolTimerPending) + { + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + DBGPRINT(RT_DEBUG_TRACE, ("EapolTimer Pending......\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n")); + return; + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); + if (WscData != NULL) + NdisZeroMemory(WscData, WSC_MAX_DATA_LEN); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && IS_ENTRY_CLIENT(pEntry) && (pWscControl->WscState <= WSC_STATE_CONFIGURED) && (pWscControl->WscActionMode != WSC_PROXY)) + { + /* A timer in the AP should cause to be disconnected after 5 seconds if a */ + /* valid EAP-Rsp/Identity indicating WPS is not received. */ + /* << from WPS EAPoL and RSN handling.doc >> */ + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_RESP_ID, pWscControl); + + /* If do disassocation here, it will affect connection of non-WPS clients. */ + goto out; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("WscState = %d\n", pWscControl->WscState)); + switch(pWscControl->WscState) + { + case WSC_STATE_WAIT_REQ_ID: + /* For IWSC case, keep sending EAPOL_START until 2 mins timeout */ + if ((pWscControl->WscRetryCount >= WscMaxRetryCount) +#ifdef CONFIG_STA_SUPPORT + && (pAd->StaCfg.BssType == BSS_INFRA) +#endif /* CONFIG_STA_SUPPORT */ + ) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_REQ_ID, pWscControl); + else + { + pWscControl->WscRetryCount++; +#ifdef CONFIG_STA_SUPPORT + if ((pAd->StaCfg.BssType == BSS_INFRA) && (CurOpMode == STA_MODE)) + WscSendEapolStart(pAd, pAd->CommonCfg.Bssid, CurOpMode); + else +#endif /* CONFIG_STA_SUPPORT */ + WscSendEapolStart(pAd, pEntry->Addr, CurOpMode); + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_WSC_START: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_WSC_START, pWscControl); + else + { + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M1: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M1, pWscControl); + else + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_START, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + /*WscSendMessage(pWscControl->pAd, WSC_OPCODE_START, NULL, 0, pWscControl, STA_MODE, EAP_CODE_REQ); */ + WscSendEapRspId(pAd, pEntry, pWscControl); + } +#endif /* CONFIG_STA_SUPPORT */ + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_SENT_M1: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M2, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_ENROLLEE) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, STA_MODE, EAP_CODE_RSP); +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_RX_M2D: + if (pWscControl->WscRetryCount >= 2) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_RX_M2D, pWscControl); + else + { + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_PIN: + if (pWscControl->WscRetryCount >= 2) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_PIN, pWscControl); + else + { + pWscControl->WscRetryCount++; + DBGPRINT(RT_DEBUG_TRACE, ("No PIN CODE, cannot send M2 out!\n")); + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M3: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M3, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAd)) + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_REQ); + else + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M4: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M4, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_ENROLLEE) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, STA_MODE, EAP_CODE_RSP); +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M5: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M5, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAd)) + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_REQ); + else + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M6: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M6, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_ENROLLEE) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, STA_MODE, EAP_CODE_RSP); +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M7: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M7, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAd)) + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_REQ); + else + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_M8: + if (pWscControl->WscRetryCount >= WscMaxRetryCount) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M8, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_ENROLLEE) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, STA_MODE, EAP_CODE_RSP); +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; + case WSC_STATE_WAIT_DONE: + if (pWscControl->WscRetryCount >= 2) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_DONE, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (IS_ENTRY_CLIENT(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAd)) + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_REQ); + else + WscSendMessage(pWscControl->pAd, + WSC_OPCODE_MSG, + pWscControl->RegData.LastTx.Data, + pWscControl->RegData.LastTx.Length, + pWscControl, + STA_MODE, + EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + } + } + pWscControl->WscRetryCount++; + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + } + break; +#ifdef CONFIG_AP_SUPPORT + /* Only AP_Enrollee needs to wait EAP_ACK */ + case WSC_STATE_WAIT_ACK: + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_ACK, pWscControl); + break; +#endif /* CONFIG_AP_SUPPORT */ + case WSC_STATE_WAIT_EAPFAIL: + /* Wait 2 seconds */ + if (pWscControl->WscRetryCount >= 1) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_EAPFAIL, pWscControl); + else + { + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_EAP_FAIL_TIME_OUT); + pWscControl->WscRetryCount++; + } + break; + default: + break; + } + +out: + if (WscData) + os_free_mem(NULL, WscData); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n")); +} + +VOID Wsc2MinsTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = NULL; +#ifdef CONFIG_AP_SUPPORT + INT IsAPConfigured = 0; +#endif /* CONFIG_AP_SUPPORT */ + BOOLEAN Cancelled; + UCHAR CurOpMode = 0xFF; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> Wsc2MinsTimeOutAction\n")); + if (pWscControl != NULL) + { + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("pAd is NULL!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- Wsc2MinsTimeOutAction\n")); + return; + } +#ifdef CONFIG_AP_SUPPORT +#ifdef CON_WPS + if (pAd->conWscStatus != CON_WPS_STATUS_DISABLED) + { + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS: Reset the status to default.\n")); + pAd->conWscStatus = CON_WPS_STATUS_DISABLED; + } +#endif /* CON_WPS */ + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Wsc2MinsTimerRunning is %s\n", + pWscControl->Wsc2MinsTimerRunning ? "TRUE, reset WscState to WSC_STATE_OFF":"FALSE")); + +#ifdef WSC_LED_SUPPORT + /* 120 seconds WPS walk time expiration. */ + pWscControl->bWPSWalkTimeExpiration = TRUE; +#endif /* WSC_LED_SUPPORT */ + + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->bWscTrigger = FALSE; + pWscControl->EapolTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef SMART_MESH_HIDDEN_WPS + pWscControl->bRunningHiddenWPS = FALSE; + if(pWscControl->bFromApCli) + Set_HiddenWps_State(&pAd->ApCfg.ApCliTab[(pWscControl->EntryIfIdx & 0x0F)].SmartMeshCfg, + HIDDEN_WPS_STATE_STOP); +#endif /* SMART_MESH_HIDDEN_WPS */ + + IsAPConfigured = pWscControl->WscConfStatus; + if ((pWscControl->EntryIfIdx & 0x0F) < pAd->ApCfg.BssidNum) + { + WscBuildBeaconIE(pWscControl->pAd, IsAPConfigured, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pWscControl->pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + APUpdateBeaconFrame(pWscControl->pAd, pWscControl->EntryIfIdx & 0x0F); + } + if ((pWscControl->WscConfMode & WSC_PROXY) == 0) + { /* Proxy mechanism is disabled */ + pWscControl->WscState = WSC_STATE_OFF; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if(pWscControl->WscMode == WSC_PBC_MODE) + { +#ifdef SMART_MESH_MONITOR + struct nsmpif_drvevnt_buf drvevnt; + drvevnt.data.wps_pbc_stat.type = NSMPIF_DRVEVNT_WPS_PBC_STAT; + drvevnt.data.wps_pbc_stat.stat = NSMP_WPS_PBC_STAT_END_TIMEOUT; + drvevnt.data.wps_pbc_stat.reason = 0; + drvevnt.data.wps_pbc_stat.channel = pAd->CommonCfg.Channel; +#ifdef SMART_MESH + if(pWscControl->bWscPBCAddrMode) + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->WscPBCAddr); + else +#endif /* SMART_MESH */ + COPY_MAC_ADDR(drvevnt.data.wps_pbc_stat.sta_mac,pWscControl->EntryAddr); + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_WPS_PBC_STAT, + NULL, (PUCHAR)&drvevnt.data.wps_pbc_stat, sizeof(drvevnt.data.wps_pbc_stat)); + DBGPRINT(RT_DEBUG_OFF, + ("Send Custom Wireless Event. (NSMPIF_DRVEVNT_WPS_PBC_STAT:NSMP_WPS_PBC_STAT_END_TIMEOUT(Reason :%d))\n",drvevnt.data.wps_pbc_stat.reason)); +#endif /* SMART_MESH_MONITOR */ + } +#ifdef SMART_MESH + pWscControl->bWscPBCAddrMode = FALSE; +#endif /* SMART_MESH */ + + pWscControl->WscMode = 1; + pWscControl->WscRetryCount = 0; + pWscControl->Wsc2MinsTimerRunning = FALSE; + + pWscControl->WscSelReg = 0; + pWscControl->WscStatus = STATUS_WSC_IDLE; + + RTMPSendWirelessEvent(pAd, IW_WSC_2MINS_TIMEOUT, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + +#ifdef CONFIG_AP_SUPPORT + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_WSC_TIMEOUT, + &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], MAC_ADDR_LEN, 0, 0, &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx& 0x0F].wdev.bssid[0], AP_MODE); +#endif /* CONFIG_AP_SUPPORT */ + + if (pWscControl->WscScanTimerRunning) + { + pWscControl->WscScanTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled); + } + if (pWscControl->WscPBCTimerRunning) + { + pWscControl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled); + } +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pAd->StaCfg.bAutoConnectByBssid = FALSE; + RTMPZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; + RTMPMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + if (INFRA_ON(pAd) || + (pWscControl->WscConfMode == WSC_ENROLLEE)) + WscLinkDown(pAd); + else + { + AsicDisableSync(pAd); + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, 0, 0, BSS0, NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_REGISTRAR, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + BSS0, + NULL, + 0, + CurOpMode); + MakeIbssBeacon(pAd); + AsicEnableIbssSync(pAd); + } + pWscControl->WscConfMode = WSC_DISABLE; + pWscControl->WscState = WSC_STATE_OFF; + } +#endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef WSC_LED_SUPPORT + /* if link is up, there shall be nothing wrong */ + /* perhaps we will set another flag to do it */ + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + (pWscControl->WscState == WSC_STATE_OFF) && + (pWscControl->WscStatus == STATUS_WSC_CONFIGURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscConnectTimeout --> Connection OK\n")); + } + else + { + UCHAR WPSLEDStatus; + + pWscControl->WscStatus = STATUS_WSC_FAIL; + pWscControl->WscState = WSC_STATE_OFF; + + /* WPS LED mode 7, 8, 11 or 12. */ + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_8) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12)) + { + pWscControl->bSkipWPSTurnOffLED = FALSE; + + /* Turn off the WPS LED modoe due to the maximum WPS processing time is expired (120 seconds). */ + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + RTMPSetLED(pAd, WPSLEDStatus); + } + else if ((LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */ + ) + { + if (pWscControl->WscMode == WSC_PIN_MODE) /* PIN method. */ + { + /* The NIC using PIN method fails to finish the WPS handshaking within 120 seconds. */ + WPSLEDStatus = LED_WPS_ERROR; + RTMPSetLED(pAd, WPSLEDStatus); + /* Turn off the WPS LED after 15 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_LED_PATTERN_TIMEOUT); + + /* The Ralink UI would make RT_OID_DISCONNECT_REQUEST request while it receive STATUS_WSC_EAP_FAILED. */ + /* Allow the NIC to turn off the WPS LED after WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT seconds. */ + pWscControl->bSkipWPSTurnOffLED = TRUE; + RTMPSetTimer(&pWscControl->WscSkipTurnOffLEDTimer, WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: The NIC using PIN method fails to finish the WPS handshaking within 120 seconds.\n", __FUNCTION__)); + } + else if (pWscControl->WscMode == WSC_PBC_MODE) /* PBC method. */ + { + switch (pWscControl->WscLastWarningLEDMode) /* Based on last WPS warning LED mode. */ + { + case 0: + case LED_WPS_ERROR: + case LED_WPS_SESSION_OVERLAP_DETECTED: + /* Failed to find any partner. */ + WPSLEDStatus = LED_WPS_ERROR; + RTMPSetLED(pAd, WPSLEDStatus); + + /* Turn off the WPS LED after 15 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_LED_PATTERN_TIMEOUT); + + /* The Ralink UI would make RT_OID_DISCONNECT_REQUEST request while it receive STATUS_WSC_EAP_FAILED. */ + /* Allow the NIC to turn off the WPS LED after WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT seconds. */ + pWscControl->bSkipWPSTurnOffLED = TRUE; + RTMPSetTimer(&pWscControl->WscSkipTurnOffLEDTimer, WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Last WPS LED status is LED_WPS_ERROR.\n", __FUNCTION__)); + break; + + default: + /* do nothing. */ + break; + } + } + else + { + /* do nothing. */ + } + } + else + { + /* do nothing. */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("WscConnectTimeout --> Fail to connect\n")); + } +#endif /* WSC_LED_SUPPORT */ + } + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- Wsc2MinsTimeOutAction\n")); +} + +/* + ======================================================================== + + Routine Description: + Classify EAP message type for enrolee + + Arguments: + pAd - NIC Adapter pointer + Elem - The EAP packet + + Return Value: + Received EAP message type + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +UCHAR WscRxMsgType( + IN PRTMP_ADAPTER pAdapter, + IN PMLME_QUEUE_ELEM pElem) +{ + USHORT Length; + PUCHAR pData; + USHORT WscType, WscLen; + STRING id_data[] = {"hello"}; + STRING fail_data[] = {"EAP_FAIL"}; + STRING wsc_start[] = {"WSC_START"}; +#ifdef WSC_V2_SUPPORT + STRING wsc_frag_ack[] = "WSC_FRAG_ACK"; +#endif /* WSC_V2_SUPPORT */ + STRING regIdentity[] = {"WFA-SimpleConfig-Registrar"}; + STRING enrIdentity[] = {"WFA-SimpleConfig-Enrollee"}; + + if (pElem->Msg[0] == 'W' && pElem->Msg[1] == 'F' && pElem->Msg[2] == 'A') + { + /* Eap-Rsp(Identity) */ + if (memcmp(regIdentity, pElem->Msg, strlen(regIdentity)) == 0) + return WSC_MSG_EAP_REG_RSP_ID; + else if (memcmp(enrIdentity, pElem->Msg, strlen(enrIdentity)) == 0) + return WSC_MSG_EAP_ENR_RSP_ID; + } + else if (NdisEqualMemory(id_data, pElem->Msg, pElem->MsgLen)) + { + /* Eap-Req/Identity(hello) */ + return WSC_MSG_EAP_REQ_ID; + } + else if (NdisEqualMemory(fail_data, pElem->Msg, pElem->MsgLen)) + { + /* Eap-Fail */ + return WSC_MSG_EAP_FAIL; + } + else if (NdisEqualMemory(wsc_start, pElem->Msg, pElem->MsgLen)) + { + /* Eap-Req(Wsc_Start) */ + return WSC_MSG_EAP_REQ_START; + } +#ifdef WSC_V2_SUPPORT + else if (NdisEqualMemory(wsc_frag_ack, pElem->Msg, pElem->MsgLen)) + { + /* WSC FRAG ACK */ + return WSC_MSG_EAP_FRAG_ACK; + } +#endif /* WSC_V2_SUPPORT */ + else + { /* Eap-Esp(Messages) */ + pData = pElem->Msg; + Length = (USHORT)pElem->MsgLen; + + /* the first TLV item in EAP Messages must be WSC_IE_VERSION */ + NdisMoveMemory(&WscType, pData, 2); + if (ntohs(WscType) != WSC_ID_VERSION) + goto out; + + /* Not Wsc Start, We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */ + while (Length > 4) + { + /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */ + NdisMoveMemory(&WscType, pData, 2); + NdisMoveMemory(&WscLen, pData + 2, 2); + WscLen = ntohs(WscLen); + if (ntohs(WscType) == WSC_ID_MSG_TYPE) + { + return(*(pData + 4)); /* Found the message type */ + } + else + { + pData += (WscLen + 4); + Length -= (WscLen + 4); + } + } + } + +out: + return WSC_MSG_UNKNOWN; +} + +/* + ======================================================================== + + Routine Description: + Classify WSC message type + + Arguments: + EAPType Value of EAP message type + MsgType Internal Message definition for MLME state machine + + Return Value: + TRUE Found appropriate message type + FALSE No appropriate message type + + Note: + All these constants are defined in wsc.h + For supplicant, there is only EAPOL Key message avaliable + + ======================================================================== +*/ +BOOLEAN WscMsgTypeSubst( + IN UCHAR EAPType, + IN UCHAR EAPCode, + OUT INT *MsgType) +{ + switch (EAPType) + { + case EAPPacket: + *MsgType = WSC_EAPOL_PACKET_MSG; + break; + case EAPOLStart: + *MsgType = WSC_EAPOL_START_MSG; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscMsgTypeSubst : unsupported EAP Type(%d); \n", EAPType)); + return FALSE; + } + + return TRUE; +} + +VOID WscInitRegistrarPair( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN UCHAR apidx) +{ + UCHAR CurOpMode = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscInitRegistrarPair\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif // CONFIG_STA_SUPPORT // + + pWscControl->WscActionMode = 0; + + /* 1. Version */ + /*pWscControl->RegData.SelfInfo.Version = WSC_VERSION; */ + + /* 2. UUID Enrollee, last 6 bytes use MAC */ + NdisMoveMemory(&pWscControl->RegData.SelfInfo.Uuid[0], &pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX); + + /* 3. MAC address */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (apidx >= HW_BEACON_MAX_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: apidx >= HW_BEACON_MAX_NUM!\n", __FUNCTION__)); + apidx = 0; + } + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, pAdapter->ApCfg.MBSSID[apidx].wdev.bssid, 6); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, pAdapter->CurrentAddress, 6); +#endif /* CONFIG_STA_SUPPORT */ + + /* 4. Device Name */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (!RTMP_TEST_FLAG(pWscControl, 0x04)) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.DeviceName, AP_WSC_DEVICE_NAME, sizeof(AP_WSC_DEVICE_NAME)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (!RTMP_TEST_FLAG(pWscControl, 0x04)) + { + NdisMoveMemory(&pWscControl->RegData.SelfInfo.DeviceName, STA_WSC_DEVICE_NAME, sizeof(STA_WSC_DEVICE_NAME)); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* 5. Manufacture woody */ + if (!RTMP_TEST_FLAG(pWscControl, 0x01)) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.Manufacturer, WSC_MANUFACTURE, sizeof(WSC_MANUFACTURE)); + + /* 6. Model Name */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (!RTMP_TEST_FLAG(pWscControl, 0x02)) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.ModelName, AP_WSC_MODEL_NAME, sizeof(AP_WSC_MODEL_NAME)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (!RTMP_TEST_FLAG(pWscControl, 0x02)) + { + NdisMoveMemory(&pWscControl->RegData.SelfInfo.ModelName, STA_WSC_MODEL_NAME, sizeof(STA_WSC_MODEL_NAME)); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* 7. Model Number */ + + if (!RTMP_TEST_FLAG(pWscControl, 0x08)) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.ModelNumber, WSC_MODEL_NUMBER, sizeof(WSC_MODEL_NUMBER)); + + /* 8. Serial Number */ + if (!RTMP_TEST_FLAG(pWscControl, 0x10)) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.SerialNumber, WSC_MODEL_SERIAL, sizeof(WSC_MODEL_SERIAL)); + + /* 9. Authentication Type Flags */ + /* Open(=1), WPAPSK(=2),Shared(=4), WPA2PSK(=20),WPA(=8),WPA2(=10) */ + /* (0x01 | 0x02 | 0x04 | 0x20 | 0x08 | 0x10) = 0x3F */ + /* WCN vista logo will check this flags. */ +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + /* + AuthTypeFlags only needs to include Open and WPA2PSK in WSC 2.0. + */ + pWscControl->RegData.SelfInfo.AuthTypeFlags = cpu2be16(0x0021); + else +#endif /* WSC_V2_SUPPORT */ + pWscControl->RegData.SelfInfo.AuthTypeFlags = cpu2be16(0x003F); + + /* 10. Encryption Type Flags */ + /* None(=1), WEP(=2), TKIP(=4), AES(=8) */ + /* (0x01 | 0x02 | 0x04 | 0x08) = 0x0F */ +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + /* + EncrTypeFlags only needs to include None and AES in WSC 2.0. + */ + pWscControl->RegData.SelfInfo.EncrTypeFlags = cpu2be16(0x0009); + else +#endif /* WSC_V2_SUPPORT */ + pWscControl->RegData.SelfInfo.EncrTypeFlags = cpu2be16(0x000F); + + /* 11. Connection Type Flag */ +#ifdef CONFIG_STA_SUPPORT + if ((pAdapter->StaCfg.BssType == BSS_ADHOC) && + (pAdapter->OpMode == OPMODE_STA)) + { + pWscControl->RegData.SelfInfo.ConnTypeFlags = 0x02; /* IBSS */ + } + else +#endif // CONFIG_STA_SUPPORT // // 11. Connection Type Flag + pWscControl->RegData.SelfInfo.ConnTypeFlags = 0x01; /* ESS */ + + /* 12. Associate state */ + pWscControl->RegData.SelfInfo.AssocState = cpu2be16(0x0000); /* Not associated */ + + /* 13. Configure Error */ + pWscControl->RegData.SelfInfo.ConfigError = cpu2be16(0x0000); /* No error */ + + /* 14. OS Version */ + pWscControl->RegData.SelfInfo.OsVersion = cpu2be32(0x80000000); /* first bit must be 1 */ + + /* 15. RF Band */ + /* Some WPS AP would check RfBand value in M1, ex. D-Link DIR-628 */ + pWscControl->RegData.SelfInfo.RfBand = 0x00; + if (WMODE_CAP_5G(pAdapter->CommonCfg.PhyMode)) + pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_50GHZ; /* 5.0G */ + + if (WMODE_CAP_2G(pAdapter->CommonCfg.PhyMode)) + pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_24GHZ; /* 2.4G */ + + /* 16. Config Method */ + pWscControl->RegData.SelfInfo.ConfigMethods = cpu2be16(pWscControl->WscConfigMethods); + /*pWscControl->RegData.EnrolleeInfo.ConfigMethods = cpu2be16(WSC_CONFIG_METHODS); // Label, Display, PBC */ + /*pWscControl->RegData.EnrolleeInfo.ConfigMethods = cpu2be16(0x0084); // Label, Display, PBC */ + + /* 17. Simple Config State */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWscControl->RegData.SelfInfo.ScState = pWscControl->WscConfStatus; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pWscControl->RegData.SelfInfo.ScState = 0x01; +#endif /* CONFIG_STA_SUPPORT */ + + /* 18. Device Password ID */ + if (pWscControl->WscMode == WSC_PIN_MODE) + { +#ifdef IWSC_SUPPORT + if ((pAdapter->StaCfg.BssType == BSS_ADHOC) && + (pAdapter->StaCfg.IWscInfo.bLimitedUI == FALSE)) + { + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_REG); /* PIN mode */ + } + else +#endif /* IWSC_SUPPORT */ + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); /* PIN mode */ + } +#ifdef IWSC_SUPPORT + else if (pWscControl->WscMode == WSC_SMPBC_MODE) + { + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_SMPBC); // SMPBC mode + } +#endif // IWSC_SUPPORT // + else + { + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PBC); /* PBC */ + } + + /* 19. SSID */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + NdisMoveMemory(pWscControl->RegData.SelfInfo.Ssid, pAdapter->ApCfg.MBSSID[apidx].Ssid, pAdapter->ApCfg.MBSSID[apidx].SsidLen); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + NdisMoveMemory(pWscControl->RegData.SelfInfo.Ssid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); +#endif /* CONFIG_STA_SUPPORT */ + + /* 20. Primary Device Type */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &STA_Wsc_Pri_Dev_Type[0], 8); + else + NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &AP_Wsc_Pri_Dev_Type[0], 8); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &STA_Wsc_Pri_Dev_Type[0], 8); +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscInitRegistrarPair\n")); +} + +VOID WscSendEapReqId( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurOpMode) +{ + UCHAR Header802_3[14]; + USHORT Length; + IEEE8021X_FRAME Ieee_8021x; + EAP_FRAME EapFrame; + UCHAR *pOutBuffer = NULL; + ULONG FrameLen = 0; + UCHAR Data[] = "hello"; + UCHAR Id; + PWSC_CTRL pWpsCtrl = NULL; + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + /* 1. Send EAP-Rsp Id */ + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapReqId\n")); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWpsCtrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl; + MAKE_802_3_HEADER(Header802_3, + &pEntry->Addr[0], + &pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid[0], + EAPOL); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pWpsCtrl = &pAd->StaCfg.WscControl; + MAKE_802_3_HEADER(Header802_3, + &pEntry->Addr[0], + &pAd->CurrentAddress[0], + EAPOL); + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pWpsCtrl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pWpsCtrl == NULL!\n")); + return; + } + + /* Length, -1 NULL pointer of string */ + Length = sizeof(EAP_FRAME) + sizeof(Data) - 1; + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + /* RFC 3748 Ch 4.1: recommended to initalize Identifier with a + * random number */ + Id = RandomByte(pAd); + if (Id == pWpsCtrl->lastId) + Id += 1; + EapFrame.Code = EAP_CODE_REQ; + EapFrame.Id = Id; + EapFrame.Length = cpu2be16(Length); + EapFrame.Type = EAP_TYPE_ID; + pWpsCtrl->lastId = Id; + + /* Out buffer for transmitting EAP-Req(Identity) */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + /* Make Transmitting frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + (sizeof(Data) - 1), Data, + END_OF_ARGS); + + /* Copy frame to Tx ring */ + RTMPToWirelessSta(pAd, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE); + + pWpsCtrl->WscRetryCount = 0; + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapReqId\n")); +} + +/* + ======================================================================== + + Routine Description: + Send EAPoL-Start packet to AP. + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after link up + 1. Change the correct parameters + 2. Send EAPOL - START + + ======================================================================== +*/ +VOID WscSendEapolStart( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pBssid, + IN UCHAR CurOpMode) +{ + IEEE8021X_FRAME Packet; + UCHAR Header802_3[14]; + MAC_TABLE_ENTRY *pEntry; + + pEntry = MacTableLookup(pAdapter, pBssid); + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (pAdapter->StaCfg.WscControl.WscState >= WSC_STATE_WAIT_WSC_START) + return; + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapolStart\n")); + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + /* 1. Change the authentication to open and encryption to none if necessary. */ + + /* init 802.3 header and Fill Packet */ +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, + pBssid, + &pAdapter->ApCfg.ApCliTab[0].wdev.if_addr[0], + EAPOL); + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + MAKE_802_3_HEADER(Header802_3, pBssid, &pAdapter->CurrentAddress[0], EAPOL); +#endif /* CONFIG_STA_SUPPORT */ + + /* Zero message 2 body */ + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.Version = EAPOL_VER; + Packet.Type = EAPOLStart; + Packet.Length = cpu2be16(0); + + if (pEntry) + RTMPToWirelessSta(pAdapter, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)&Packet, 4, TRUE); + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + /* Update WSC status */ + pAdapter->ApCfg.ApCliTab[0].WscControl.WscStatus = STATUS_WSC_EAPOL_START_SENT; + pAdapter->ApCfg.ApCliTab[0].WscControl.WscState = WSC_STATE_WAIT_REQ_ID; + if (!pAdapter->ApCfg.ApCliTab[0].WscControl.EapolTimerRunning) + { + pAdapter->ApCfg.ApCliTab[0].WscControl.EapolTimerRunning = TRUE; + RTMPSetTimer(&pAdapter->ApCfg.ApCliTab[0].WscControl.EapolTimer, WSC_EAPOL_START_TIME_OUT); + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + /* Update WSC status */ + pAdapter->StaCfg.WscControl.WscStatus = STATUS_WSC_EAPOL_START_SENT; + pAdapter->StaCfg.WscControl.WscState = WSC_STATE_WAIT_REQ_ID; + if (!pAdapter->StaCfg.WscControl.EapolTimerRunning) + { + pAdapter->StaCfg.WscControl.EapolTimerRunning = TRUE; + RTMPSetTimer(&pAdapter->StaCfg.WscControl.EapolTimer, 2000); + } + } +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapolStart\n")); +} + + +VOID WscSendEapRspId( + IN PRTMP_ADAPTER pAdapter, + IN PMAC_TABLE_ENTRY pEntry, + IN PWSC_CTRL pWscControl) +{ + UCHAR Header802_3[14]; + USHORT Length = 0; + IEEE8021X_FRAME Ieee_8021x; + EAP_FRAME EapFrame; + UCHAR *pOutBuffer = NULL; + ULONG FrameLen = 0; + UCHAR regIdentity[] = "WFA-SimpleConfig-Registrar-1-0"; + UCHAR enrIdentity[] = "WFA-SimpleConfig-Enrollee-1-0"; + UCHAR CurOpMode = 0xff; + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + /* 1. Send EAP-Rsp Id */ + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapRspId\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, + &pEntry->Addr[0], + &pAdapter->ApCfg.ApCliTab[0].wdev.if_addr[0], + EAPOL); + + if (pWscControl->WscConfMode == WSC_ENROLLEE) + Length = sizeof(EAP_FRAME) + sizeof(enrIdentity) - 1; + else if (pWscControl->WscConfMode == WSC_REGISTRAR) + Length = sizeof(EAP_FRAME) + sizeof(regIdentity) - 1; + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + /* init 802.3 header and Fill Packet */ + if (INFRA_ON(pAdapter)) + { + MAKE_802_3_HEADER(Header802_3, &pAdapter->CommonCfg.Bssid[0], &pAdapter->CurrentAddress[0], EAPOL); + } + else + { + MAKE_802_3_HEADER(Header802_3, &pWscControl->WscPeerMAC[0], &pAdapter->CurrentAddress[0], EAPOL); + } + + /* Length, -1 NULL pointer of string */ + if (pWscControl->WscConfMode == WSC_ENROLLEE) + Length = sizeof(EAP_FRAME) + sizeof(enrIdentity) - 1; + else if (pWscControl->WscConfMode == WSC_REGISTRAR) + Length = sizeof(EAP_FRAME) + sizeof(regIdentity) - 1; + } + +#endif /* CONFIG_STA_SUPPORT */ + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + EapFrame.Code = EAP_CODE_RSP; + EapFrame.Id = pWscControl->lastId; + EapFrame.Length = cpu2be16(Length); + EapFrame.Type = EAP_TYPE_ID; + + /* Out buffer for transmitting EAP-Req(Identity) */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + if (pWscControl->WscConfMode == WSC_REGISTRAR) + { + /* Make tx frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + (sizeof(regIdentity) - 1), regIdentity, + END_OF_ARGS); + } + else if (pWscControl->WscConfMode == WSC_ENROLLEE) + { +#ifdef IWSC_SUPPORT + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + pWscControl->WscConfStatus = WSC_SCSTATE_UNCONFIGURED; +#endif /* IWSC_SUPPORT */ + /* Make Transmitting frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + (sizeof(enrIdentity) - 1), enrIdentity, + END_OF_ARGS); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WscConfMode(%d) is not WSC_REGISTRAR nor WSC_ENROLLEE.\n", pWscControl->WscConfMode)); + goto out; + } + + /* Copy frame to Tx ring */ +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + RTMPToWirelessSta(pAdapter, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE); + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + RTMPToWirelessSta((PRTMP_ADAPTER)pWscControl->pAd, &pAdapter->MacTab.Content[BSSID_WCID], + Header802_3, LENGTH_802_3, (PUCHAR)pOutBuffer, FrameLen, TRUE); +#endif /* CONFIG_STA_SUPPORT */ + + pWscControl->WscRetryCount = 0; + if (!pWscControl->EapolTimerRunning) + { + pWscControl->EapolTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->EapolTimer, WSC_EAP_ID_TIME_OUT); + } +out: + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapRspId\n")); +} + +VOID WscUPnPErrHandle( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN UINT eventID) +{ + int dataLen; + UCHAR *pWscData; + UCHAR CurOpMode; + + DBGPRINT(RT_DEBUG_TRACE, ("Into WscUPnPErrHandle, send WSC_OPCODE_UPNP_CTRL with eventID=0x%x!\n", eventID)); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif // CONFIG_STA_SUPPORT // + + os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN); + if (pWscData != NULL) + { + NdisZeroMemory(pWscData, WSC_MAX_DATA_LEN); + + dataLen = BuildMessageNACK(pAd, pWscControl, pWscData); + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL, + pWscData, dataLen, eventID, 0, NULL, CurOpMode); + + os_free_mem(NULL, pWscData); + } + else + { + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, 0, NULL, 0, eventID, 0, NULL, CurOpMode); + } +} + +/* + Format of iwcustom msg WSC clientJoin message: + 1. SSID which station want to probe(32 bytes): + + *If the length if SSID string is small than 32 bytes, fill 0x0 for remaining bytes. + 2. sender MAC address(6 bytes): + 3. Status: + Set as 1 means change APStatus as 1. + Set as 2 means change STAStatus as 1. + Set as 3 means trigger msg. + + 32 6 1 + +----------+--------+------+ + |SSIDString| SrcMAC |Status| +*/ +int WscSendUPnPConfReqMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR apIdx, + IN PUCHAR ssidStr, + IN PUCHAR macAddr, + IN INT Status, + IN UINT eventID, + IN UCHAR CurOpMode) +{ + UCHAR pData[39] = {0}; + + + strncpy((PSTRING) pData, (PSTRING)ssidStr, strlen((PSTRING) ssidStr)); + NdisMoveMemory(&pData[32], macAddr, MAC_ADDR_LEN); + pData[38] = Status; + WscSendUPnPMessage(pAd, apIdx, WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_CONFIG_REQ, + &pData[0], 39, eventID, 0, NULL, CurOpMode); + + return 0; +} + + +/* + NETLINK tunnel msg format send to WSCUPnP handler in user space: + 1. Signature of following string(Not include the quote, 8 bytes) + "RAWSCMSG" + 2. eID: eventID (4 bytes) + the ID of this message(4 bytes) + 3. aID: ackID (4 bytes) + means that which event ID this mesage was response to. + 4. TL: Message Total Length (4 bytes) + Total length of this message. + 5. F: Flag (2 bytes) + used to notify some specific character of this msg segment. + Bit 1: fragment + set as 1 if netlink layer have more segment of this Msg need to send. + Bit 2~15: reserve, should set as 0 now. + 5. SL: Segment Length(2 bytes) + msg actual length in this segment, The SL may not equal the "TL" field if "F" ==1 + 6. devMac: device mac address(6 bytes) + Indicate the netdevice which this msg belong. For the wscd in user space will + depends this address dispatch the msg to correct UPnP Device instance to handle it. + 7. "WSC_MSG" info: + + 8 4 4 4 2 2 6 variable length(MAXIMUM=232) + +------------+----+----+----+--+--+------+------------------------+ + | Signature |eID |aID | TL | F | SL|devMac| WSC_MSG | + +*/ +int WscSendUPnPMessage( + IN PRTMP_ADAPTER pAd, + IN UCHAR devIfIdx, + IN USHORT msgType, + IN USHORT msgSubType, + IN PUCHAR pData, + IN INT dataLen, + IN UINT eventID, + IN UINT toIPAddr, + IN PUCHAR pMACAddr, + IN UCHAR CurOpMode) +{ +/* union iwreq_data wrqu; */ + RTMP_WSC_NLMSG_HDR *pNLMsgHdr; + RTMP_WSC_MSG_HDR *pWscMsgHdr; + + UCHAR hdrBuf[42]; /*RTMP_WSC_NLMSG_HDR_LEN + RTMP_WSC_MSG_HDR_LEN */ + int leftLen = 0, copyLen; + PUCHAR pBuf = NULL, pBufPtr = NULL, pPos = NULL; + PUCHAR pDevAddr = NULL; +#ifdef CONFIG_AP_SUPPORT + UCHAR bssIdx = devIfIdx; +#endif /* CONFIG_AP_SUPPORT */ + ULONG Now; + + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendUPnPMessage\n")); + + if ((msgType & WSC_OPCODE_UPNP_MASK) != WSC_OPCODE_UPNP_MASK) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (devIfIdx & MIN_NET_DEVICE_FOR_APCLI) + { + bssIdx &= (~MIN_NET_DEVICE_FOR_APCLI); + if (bssIdx >= MAX_APCLI_NUM) + return FALSE; + pDevAddr = &pAd->ApCfg.ApCliTab[bssIdx].wdev.if_addr[0]; + } + else +#endif /* APCLI_SUPPORT */ + pDevAddr = &pAd->ApCfg.MBSSID[bssIdx].wdev.bssid[0]; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pDevAddr = &pAd->CurrentAddress[0]; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pDevAddr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pDevAddr == NULL!\n")); + return FALSE; + } + + /*Prepare the NLMsg header */ + memset(hdrBuf, 0, sizeof(hdrBuf)); + pNLMsgHdr = (RTMP_WSC_NLMSG_HDR *)hdrBuf; + memcpy(pNLMsgHdr, WSC_MSG_SIGNATURE, RTMP_WSC_NLMSG_SIGNATURE_LEN); + + NdisGetSystemUpTime(&Now); + pNLMsgHdr->envID = Now; + pNLMsgHdr->ackID = eventID; + pNLMsgHdr->msgLen = dataLen + RTMP_WSC_MSG_HDR_LEN; + + /* + In order to support multiple wscd, we need this new field to notify + the wscd which interface this msg send from. + */ + NdisMoveMemory(&pNLMsgHdr->devAddr[0], pDevAddr, MAC_ADDR_LEN); + + /*Prepare the WscMsg header */ + pWscMsgHdr = (RTMP_WSC_MSG_HDR *)(hdrBuf + sizeof(RTMP_WSC_NLMSG_HDR)); + switch(msgType) + { + case WSC_OPCODE_UPNP_DATA: + pWscMsgHdr->msgType = WSC_OPCODE_UPNP_DATA; + break; + case WSC_OPCODE_UPNP_MGMT: + pWscMsgHdr->msgType = WSC_OPCODE_UPNP_MGMT; + break; + case WSC_OPCODE_UPNP_CTRL: + pWscMsgHdr->msgType = WSC_OPCODE_UPNP_CTRL; + break; + default: + return FALSE; + } + pWscMsgHdr->msgSubType = msgSubType; + pWscMsgHdr->ipAddr = toIPAddr; + pWscMsgHdr->msgLen = dataLen; + + if ((pWscMsgHdr->msgType == WSC_OPCODE_UPNP_DATA) && + (eventID == 0) && + (pMACAddr != NULL) && + (NdisEqualMemory(pMACAddr, ZERO_MAC_ADDR, MAC_ADDR_LEN) == FALSE)) + { + pWscMsgHdr->msgSubType |= WSC_UPNP_DATA_SUB_INCLUDE_MAC; + pNLMsgHdr->msgLen += MAC_ADDR_LEN; + pWscMsgHdr->msgLen += MAC_ADDR_LEN; + } + + /*Allocate memory and copy the msg. */ + pPos = pData; + os_alloc_mem(NULL, (UCHAR **)&pBuf, IWEVCUSTOM_MSG_MAX_LEN); + if (pBuf != NULL) + { + int firstSeg = 1; + + while(leftLen) + { + /*Prepare the payload */ + memset(pBuf, 0, IWEVCUSTOM_MSG_MAX_LEN); + + pNLMsgHdr->segLen = (leftLen > IWEVCUSTOM_PAYLOD_MAX_LEN ? IWEVCUSTOM_PAYLOD_MAX_LEN : leftLen); + leftLen -= pNLMsgHdr->segLen; + pNLMsgHdr->flags = (leftLen > 0 ? 1 : 0); + + memcpy(pBuf, pNLMsgHdr, RTMP_WSC_NLMSG_HDR_LEN); + pBufPtr = &pBuf[RTMP_WSC_NLMSG_HDR_LEN]; + + if(firstSeg){ + memcpy(pBufPtr, pWscMsgHdr, RTMP_WSC_MSG_HDR_LEN); + pBufPtr += RTMP_WSC_MSG_HDR_LEN; + copyLen = (pNLMsgHdr->segLen - RTMP_WSC_MSG_HDR_LEN); + if ((pWscMsgHdr->msgSubType & WSC_UPNP_DATA_SUB_INCLUDE_MAC) == WSC_UPNP_DATA_SUB_INCLUDE_MAC) + { + NdisMoveMemory(pBufPtr, pMACAddr, MAC_ADDR_LEN); + pBufPtr += MAC_ADDR_LEN; + copyLen -= MAC_ADDR_LEN; + } + NdisMoveMemory(pBufPtr, pPos, copyLen); + pPos += copyLen; + firstSeg = 0; + } else { + NdisMoveMemory(pBufPtr, pPos, pNLMsgHdr->segLen); + pPos += pNLMsgHdr->segLen; + } + + /*Send WSC Msg to wscd, msg length = pNLMsgHdr->segLen + sizeof(RTMP_WSC_NLMSG_HDR) */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_WSC_UPNP_EVENT_FLAG, NULL, pBuf, pNLMsgHdr->segLen + sizeof(RTMP_WSC_NLMSG_HDR)); + } + + os_free_mem(NULL, pBuf); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendUPnPMessage\n")); + return TRUE; +} + + +VOID WscSendMessage( + IN PRTMP_ADAPTER pAdapter, + IN UCHAR OpCode, + IN PUCHAR pData, + IN INT Len, + IN PWSC_CTRL pWscControl, + IN UCHAR OpMode, + IN UCHAR EapType) +{ + /* Inb-EAP Message */ + UCHAR Header802_3[14]; + USHORT Length, MsgLen; + IEEE8021X_FRAME Ieee_8021x; + EAP_FRAME EapFrame; + WSC_FRAME WscFrame; + UCHAR *pOutBuffer = NULL; + ULONG FrameLen = 0; + MAC_TABLE_ENTRY *pEntry; +#ifdef CONFIG_AP_SUPPORT + UCHAR bssIdx = (pWscControl->EntryIfIdx & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ + UCHAR CurOpMode = 0xFF; + + if ((Len <= 0) && (OpCode != WSC_OPCODE_START) && (OpCode != WSC_OPCODE_FRAG_ACK)) + return; + + /* Send message */ + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendMessage\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (OpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->ApCfg.MBSSID[bssIdx].wdev.bssid[0], EAPOL); + } +#ifdef APCLI_SUPPORT + else if (OpMode == AP_CLIENT_MODE) + { + MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->ApCfg.ApCliTab[0].wdev.if_addr[0], EAPOL); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (OpMode == STA_MODE) + { + if (INFRA_ON(pAdapter)) + { + MAKE_802_3_HEADER(Header802_3, &pAdapter->CommonCfg.Bssid[0], &pAdapter->CurrentAddress[0], EAPOL); + } + else + { + MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->CurrentAddress[0], EAPOL); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Length = EAP + WSC_Frame + Payload */ + Length = sizeof(EAP_FRAME) + sizeof(WSC_FRAME) + Len; + + if (pWscControl->bWscFragment && (pWscControl->bWscFirstOne)) + { + Length += 2; + MsgLen = pWscControl->WscTxBufLen + Len; + MsgLen = htons(MsgLen); + } + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + + if (EapType == EAP_CODE_REQ) + { + EapFrame.Code = EAP_CODE_REQ; + EapFrame.Id = ++(pWscControl->lastId); + } + else + { + EapFrame.Code = EAP_CODE_RSP; + EapFrame.Id = pWscControl->lastId; /* same as eap_req id */ + } + + EapFrame.Length = cpu2be16(Length); + EapFrame.Type = EAP_TYPE_WSC; + + /* Zero WSC Frame */ + NdisZeroMemory(&WscFrame, sizeof(WscFrame)); + WscFrame.SMI[0] = 0x00; + WscFrame.SMI[1] = 0x37; + WscFrame.SMI[2] = 0x2A; + WscFrame.VendorType = cpu2be32(WSC_VENDOR_TYPE); + WscFrame.OpCode = OpCode; + WscFrame.Flags = 0x00; + if (pWscControl->bWscFragment && (pWscControl->bWscLastOne == FALSE)) + WscFrame.Flags |= WSC_MSG_FLAG_MF; + + if (pWscControl->bWscFragment && (pWscControl->bWscFirstOne)) + { + WscFrame.Flags |= WSC_MSG_FLAG_LF; + } + + /* Out buffer for transmitting message */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + /* Make Transmitting frame */ + if (pData && (Len > 0)) + { + if (pWscControl->bWscFragment && (pWscControl->bWscFirstOne)) + { + UCHAR LF_Len = 2; + ULONG TmpLen = 0; + + pWscControl->bWscFirstOne = FALSE; + MakeOutgoingFrame(pOutBuffer, &TmpLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + sizeof(WscFrame), &WscFrame, + LF_Len, &MsgLen, + END_OF_ARGS); + + FrameLen += TmpLen; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + Len, pData, + END_OF_ARGS); + + FrameLen += TmpLen; + } + else + { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + sizeof(WscFrame), &WscFrame, + Len, pData, + END_OF_ARGS); + } + } + else + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + sizeof(WscFrame), &WscFrame, + END_OF_ARGS); + + /* Copy frame to Tx ring */ + pEntry = MacTableLookup(pAdapter, &pWscControl->EntryAddr[0]); + + if (pEntry) + { + + UCHAR i,sendMaxCount = 1; +#ifdef SMART_MESH_HIDDEN_WPS + if(pEntry && pEntry->bHyperFiPeer) + sendMaxCount = 3; +#endif /* SMART_MESH_HIDDEN_WPS */ + for(i = 0; i < sendMaxCount; i++) + RTMPToWirelessSta(pAdapter, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE); + } + else + DBGPRINT(RT_DEBUG_WARN, ("pEntry is NULL\n")); + + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendMessage\n")); +} + +VOID WscBuildBeaconIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR b_configured, + IN BOOLEAN b_selRegistrar, + IN USHORT devPwdId, + IN USHORT selRegCfgMethods, + IN UCHAR apidx, + IN UCHAR *pAuthorizedMACs, + IN UCHAR AuthorizedMACsLen, + IN UCHAR CurOpMode) +{ + WSC_IE_HEADER ieHdr; +/* UCHAR Data[256]; */ + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + USHORT tempVal = 0; + PWSC_CTRL pWpsCtrl = NULL; + PWSC_REG_DATA pReg = NULL; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 256); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWpsCtrl = &pAd->ApCfg.MBSSID[apidx & 0x0F].WscControl; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* CONFIG_STA_SUPPORT */ + + pReg = &pWpsCtrl->RegData; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildBeaconIE\n")); + /* WSC IE HEader */ + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; ieHdr.oui[2] = 0xF2; +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_MODE) && + (pAd->StaCfg.BssType == BSS_ADHOC)) + ieHdr.oui[3] = 0x10; + else +#endif /* IWSC_SUPPORT */ + ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Simple Config State */ + templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&b_configured, 0); + pData += templen; + Len += templen; + +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWpsCtrl->bSetupLock) + { + // AP Setup Lock + templen = AppendWSCTLV(WSC_ID_AP_SETUP_LOCKED, pData, (UINT8 *)&pWpsCtrl->bSetupLock, 0); + pData += templen; + Len += templen; + } +#endif /* CONFIG_AP_SUPPORT */ + + if ( b_selRegistrar ) + { + /* 3.Selected Registrar */ + templen = AppendWSCTLV(WSC_ID_SEL_REGISTRAR, pData, (UINT8 *)&b_selRegistrar, 0); + pData += templen; + Len += templen; + + /*4. Device Password ID */ + tempVal = htons(devPwdId); + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 5. Selected Registrar Config Methods */ + tempVal = selRegCfgMethods; +#ifdef IWSC_SUPPORT + if (CurOpMode == STA_MODE) + { + if (pAd->StaCfg.WscControl.WscMode == WSC_PIN_MODE) + { + tempVal &= 0x200F; + } + else + { + tempVal &= 0x02F0; + } + if (pAd->StaCfg.IWscInfo.bLimitedUI) + { + tempVal &= (~WSC_CONFMET_KEYPAD); + } + else + { + tempVal |= WSC_CONFMET_KEYPAD; + } + } +#endif /* IWSC_SUPPORT */ + tempVal = htons(tempVal); + templen = AppendWSCTLV(WSC_ID_SEL_REG_CFG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + } + + /* 6. UUID last 6 bytes use MAC */ + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWpsCtrl->Wsc_Uuid_E[0], 0); + pData += templen; + Len += templen; + + /* 7. RF Bands */ + if (CurOpMode == AP_MODE) + { + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + tempVal = 2; + else + tempVal = 1; + } + else + { + if (pAd->CommonCfg.Channel > 14) + tempVal = 2; + else + tempVal = 1; + } + +#ifdef RT_BIG_ENDIAN + tempVal =SWAP16(tempVal); +#endif /* RT_BIG_ENDIAN */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (CurOpMode == STA_MODE)) + { + UCHAR respType; + + // Connection Type Flag ESS + templen = AppendWSCTLV(WSC_ID_CONN_TYPE, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + +#ifdef IWSC_TEST_SUPPORT + /* + This modification is for Broadcom test bed. + Broadcom test bed use same buffer to record IWSC IE from Beacon and Probe Response. + But the content of IWSC IE in Beacon is different from Probe Response. + */ + if ((pWpsCtrl->WscMode == WSC_SMPBC_MODE) && + (pWpsCtrl->WscConfMode == WSC_REGISTRAR)) + { + BOOLEAN bEntryAcceptable = FALSE; + BOOLEAN bRegistrationReady = TRUE; + PIWSC_INFO pIWscInfo = NULL; + + pIWscInfo = &pAd->StaCfg.IWscInfo; + if (pIWscInfo->bIWscEntryTimerRunning) + bEntryAcceptable = TRUE; + + /* Entry Acceptable (only for IBSS) */ + templen = AppendWSCTLV(WSC_ID_ENTRY_ACCEPTABLE, pData, (UINT8 *)&bEntryAcceptable, 0); + pData += templen; + Len += templen; + + if (pWpsCtrl->EapMsgRunning) + bRegistrationReady = FALSE; + + /* Registration Ready (only for IBSS) */ + templen = AppendWSCTLV(WSC_ID_REGISTRATON_READY, pData, (UINT8 *)&bRegistrationReady, 0); + pData += templen; + Len += templen; + } +#endif /* IWSC_TEST_SUPPORT */ + /* IWSC IP Address Configuration */ + tempVal = htons(pAd->StaCfg.IWscInfo.IpConfMethod); + templen = AppendWSCTLV(WSC_ID_IP_ADDR_CONF_METHOD, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; +#ifdef IWSC_TEST_SUPPORT + /* + This modification is for Broadcom test bed. + Broadcom test bed use same buffer to record IWSC IE from Beacon and Probe Response. + But the content of IWSC IE in Beacon is different from Probe Response. + */ + + /* Response Type WSC_ID_RESP_TYPE */ + if (pAd->StaCfg.WscControl.WscConfMode == WSC_REGISTRAR) + respType = WSC_MSGTYPE_REGISTRAR; + else + respType = WSC_MSGTYPE_ENROLLEE_OPEN_8021X; + templen = AppendWSCTLV(WSC_ID_RESP_TYPE, pData, (UINT8 *)&respType, 0); + pData += templen; + Len += templen; +#endif /* IWSC_TEST_SUPPORT */ + + } +#endif /* IWSC_SUPPORT */ + +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl->WscV2Info.bEnableWpsV2) + { + PWSC_TLV pWscTLV = &pWpsCtrl->WscV2Info.ExtraTlv; + WscGenV2Msg(pWpsCtrl, + b_selRegistrar, + pAuthorizedMACs, + AuthorizedMACsLen, + &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 */ + + + + ieHdr.length = ieHdr.length + Len; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + memcpy(pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, &ieHdr, sizeof(WSC_IE_HEADER)); + memcpy(pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value + sizeof(WSC_IE_HEADER), Data, Len); + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = sizeof(WSC_IE_HEADER) + Len; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + memcpy(pAd->StaCfg.WpsIEBeacon.Value, &ieHdr, sizeof(WSC_IE_HEADER)); + memcpy(pAd->StaCfg.WpsIEBeacon.Value + sizeof(WSC_IE_HEADER), Data, Len); + pAd->StaCfg.WpsIEBeacon.ValueLen = sizeof(WSC_IE_HEADER) + Len; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildBeaconIE\n")); +} + +VOID WscBuildProbeRespIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR respType, + IN UCHAR scState, + IN BOOLEAN b_selRegistrar, + IN USHORT devPwdId, + IN USHORT selRegCfgMethods, + IN UCHAR apidx, + IN UCHAR *pAuthorizedMACs, + IN INT AuthorizedMACsLen, + IN UCHAR CurOpMode) +{ + WSC_IE_HEADER ieHdr; +/* UCHAR Data[512]; */ + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + USHORT tempVal = 0; + PWSC_CTRL pWpsCtrl = NULL; + PWSC_REG_DATA pReg = NULL; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWpsCtrl = &pAd->ApCfg.MBSSID[apidx & 0x0F].WscControl; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* CONFIG_STA_SUPPORT */ + + pReg = &pWpsCtrl->RegData; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildProbeRespIE, apidx = %x\n", apidx)); + + /* WSC IE Header */ + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; ieHdr.oui[2] = 0xF2; +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_MODE) && + (pAd->StaCfg.BssType == BSS_ADHOC)) + ieHdr.oui[3] = 0x10; + else +#endif /* IWSC_SUPPORT */ + ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Simple Config State */ + templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&scState, 0); + pData += templen; + Len += templen; + +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWpsCtrl->bSetupLock) + { + // AP Setup Lock + templen = AppendWSCTLV(WSC_ID_AP_SETUP_LOCKED, pData, (UINT8 *)&pWpsCtrl->bSetupLock, 0); + pData += templen; + Len += templen; + } +#endif /* CONFIG_AP_SUPPORT */ + + if ( b_selRegistrar ) + { + /* 3. Selected Registrar */ + templen = AppendWSCTLV(WSC_ID_SEL_REGISTRAR, pData, (UINT8 *)&b_selRegistrar, 0); + pData += templen; + Len += templen; + + /* 4. Device Password ID */ + tempVal = htons(devPwdId); + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 5. Selected Registrar Config Methods */ +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_MODE) && + (pAd->StaCfg.IWscInfo.bSelRegStart == FALSE)) + { + if (pWpsCtrl->WscMode == WSC_PIN_MODE) + { + selRegCfgMethods &= 0x200F; + if (pAd->StaCfg.IWscInfo.bLimitedUI) + { + selRegCfgMethods &= (~WSC_CONFMET_KEYPAD); + } + else + { + selRegCfgMethods |= WSC_CONFMET_KEYPAD; + } + } + else + { + selRegCfgMethods &= 0x02F0; + } + } +#endif /* IWSC_SUPPORT */ + tempVal = htons(selRegCfgMethods); + templen = AppendWSCTLV(WSC_ID_SEL_REG_CFG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_MODE) && pAd->StaCfg.IWscInfo.bSelRegStart) + { + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pAd->StaCfg.IWscInfo.RegMacAddr, 0); + pData += templen; + Len += templen; + pAd->StaCfg.IWscInfo.bSelRegStart = FALSE; + } +#endif /* IWSC_SUPPORT */ + } + + /* 6. Response Type WSC_ID_RESP_TYPE */ + templen = AppendWSCTLV(WSC_ID_RESP_TYPE, pData, (UINT8 *)&respType, 0); + pData += templen; + Len += templen; + + /* 7. UUID last 6 bytes use MAC */ + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWpsCtrl->Wsc_Uuid_E[0], 0); + pData += templen; + Len += templen; + + /* 8. Manufacturer */ + NdisZeroMemory(pData, 64 + 4); + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* 9. Model Name */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* 10. Model Number */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* 11. Serial Number */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber)); + pData += templen; + Len += templen; + + /* 12. Primary Device Type */ + templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0); + pData += templen; + Len += templen; + + /* 13. Device Name */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* 14. Config Methods */ + /*tempVal = htons(0x008a); */ + /*tempVal = htons(0x0084); */ + { + /* + WSC 1.0 WCN logo testing will check the value of config method in probe response and M1. + Config method shall be identical in probe response and M1. + */ +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl->WscV2Info.bEnableWpsV2) + tempVal = pWpsCtrl->WscConfigMethods & 0xF97F; + else +#endif /* WSC_V2_SUPPORT */ + tempVal = pWpsCtrl->WscConfigMethods & 0x00FF; + } + + tempVal = htons(tempVal); + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + + /* 15. RF Bands */ + if (CurOpMode == AP_MODE) + { + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + tempVal = 2; + else + tempVal = 1; + } + else + { + if (pAd->CommonCfg.Channel > 14) + tempVal = 2; + else + tempVal = 1; + } +#ifdef RT_BIG_ENDIAN + tempVal =SWAP16(tempVal); +#endif /* RT_BIG_ENDIAN */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (CurOpMode == STA_MODE)) + { + /* Connection Type Flag ESS */ + templen = AppendWSCTLV(WSC_ID_CONN_TYPE, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + + if ((pWpsCtrl->WscMode == WSC_SMPBC_MODE) && + (pWpsCtrl->WscConfMode == WSC_REGISTRAR)) + { + BOOLEAN bEntryAcceptable = FALSE; + BOOLEAN bRegistrationReady = TRUE; + PIWSC_INFO pIWscInfo = NULL; + + pIWscInfo = &pAd->StaCfg.IWscInfo; + if (pIWscInfo->bIWscEntryTimerRunning) + bEntryAcceptable = TRUE; + + /* Entry Acceptable (only for IBSS) */ + templen = AppendWSCTLV(WSC_ID_ENTRY_ACCEPTABLE, pData, (UINT8 *)&bEntryAcceptable, 0); + pData += templen; + Len += templen; + + if (pWpsCtrl->EapMsgRunning) + bRegistrationReady = FALSE; + + /* Registration Ready (only for IBSS) */ + templen = AppendWSCTLV(WSC_ID_REGISTRATON_READY, pData, (UINT8 *)&bRegistrationReady, 0); + pData += templen; + Len += templen; + } + + /* IWSC IP Address Configuration */ + tempVal = htons(pAd->StaCfg.IWscInfo.IpConfMethod); + templen = AppendWSCTLV(WSC_ID_IP_ADDR_CONF_METHOD, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + } +#endif /* IWSC_SUPPORT */ + +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl->WscV2Info.bEnableWpsV2) + { + PWSC_TLV pWscTLV = &pWpsCtrl->WscV2Info.ExtraTlv; + WscGenV2Msg(pWpsCtrl, + b_selRegistrar, + pAuthorizedMACs, + AuthorizedMACsLen, + &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 (Len > 251) + { + DBGPRINT(RT_DEBUG_TRACE, ("Len is overflow!\n")); + } + + ieHdr.length = ieHdr.length + Len; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + memcpy(pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.Value, &ieHdr, sizeof(WSC_IE_HEADER)); + memcpy(pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.Value + sizeof(WSC_IE_HEADER), Data, Len); + pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.ValueLen = sizeof(WSC_IE_HEADER) + Len; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + memcpy(pAd->StaCfg.WpsIEProbeResp.Value, &ieHdr, sizeof(WSC_IE_HEADER)); + memcpy(pAd->StaCfg.WpsIEProbeResp.Value + sizeof(WSC_IE_HEADER), Data, Len); + pAd->StaCfg.WpsIEProbeResp.ValueLen = sizeof(WSC_IE_HEADER) + Len; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildProbeRespIE\n")); +} + +/* + ======================================================================== + + Routine Description: + Ap send EAP-Fail to station + + Arguments: + pAd - NIC Adapter pointer + Id - ID between EAP-Req and EAP-Rsp pair + pEntry - The Station Entry information + + Return Value: + None + + ======================================================================== +*/ +VOID WscSendEapFail( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bSendDeAuth) +{ + UCHAR Header802_3[14]; + USHORT Length; + IEEE8021X_FRAME Ieee_8021x; + EAP_FRAME EapFrame; + UCHAR *pOutBuffer = NULL; + ULONG FrameLen = 0; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ + MAC_TABLE_ENTRY *pEntry; + UCHAR CurOpMode = 0xFF; + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + /* 1. Send EAP-Rsp Id */ + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapFail\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, + &pWscControl->EntryAddr[0], + &pAd->ApCfg.MBSSID[apidx].wdev.bssid[0], + EAPOL); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + MAKE_802_3_HEADER(Header802_3, + &pWscControl->EntryAddr[0], + &pAd->CurrentAddress[0], + EAPOL); + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Length, -1 type size, Eap-Fail doesn't need Type item */ + Length = sizeof(EAP_FRAME) - sizeof(UCHAR); + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + EapFrame.Code = EAP_CODE_FAIL; + EapFrame.Id = pWscControl->lastId; + EapFrame.Length = cpu2be16(Length); + + /* Out buffer for transmitting EAP-Req(Identity) */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + /* Make Transmitting frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame)-1, &EapFrame, END_OF_ARGS); + + pEntry = MacTableLookup(pAd, &pWscControl->EntryAddr[0]); + /* Copy frame to Tx ring */ + RTMPToWirelessSta(pAd, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE); + + + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + +#ifdef CONFIG_AP_SUPPORT + if (pEntry && bSendDeAuth && (CurOpMode == AP_MODE)) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DEAUTH_STA_LEAVING, TRUE); + } + if (pEntry == NULL) + { + /* + If STA dis-connect un-normally, reset EntryAddr here. + */ + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapFail\n")); +} + +#ifdef CONFIG_AP_SUPPORT +VOID WscBuildAssocRespIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN UCHAR Reason, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ + WSC_IE_HEADER ieHdr; +/* UCHAR Data[512] = {0}; */ + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + UINT8 tempVal = 0; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pAd->ApCfg.MBSSID[ApIdx].WscControl.RegData; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildAssocRespIE\n")); + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + Data[0] = 0; + + /* WSC IE Header */ + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; + ieHdr.oui[2] = 0xF2; ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* Request Type */ + tempVal = WSC_MSGTYPE_AP_WLAN_MGR; + templen = AppendWSCTLV(WSC_ID_RESP_TYPE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pAd->ApCfg.MBSSID[ApIdx].WscControl.WscV2Info.bEnableWpsV2) + { + WscGenV2Msg(&pAd->ApCfg.MBSSID[ApIdx].WscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + } +#endif /* WSC_V2_SUPPORT */ + + + ieHdr.length = ieHdr.length + Len; + NdisMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + NdisMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); + *pIeLen = sizeof(WSC_IE_HEADER) + Len; + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildAssocRespIE\n")); +} + + +VOID WscSelectedRegistrar( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pReginfo, + IN UINT Length, + IN UCHAR apidx) +{ + PUCHAR pData; + /*INT IsAPConfigured;*/ + UCHAR /*wsc_version, */wsc_sel_reg = 0; + USHORT wsc_dev_pass_id = 0, wsc_sel_reg_conf_mthd = 0; + USHORT WscType, WscLen; + PUCHAR pAuthorizedMACs = NULL; + UCHAR AuthorizedMACsLen = 0; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + pData = (PUCHAR)pReginfo; + + if (Length < 4) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Unknown IE \n")); + return; + } + + hex_dump("WscSelectedRegistrar - Reginfo", pReginfo, Length); + while (Length > 4) + { + /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */ + NdisMoveMemory(&WscType, pData, 2); + NdisMoveMemory(&WscLen, pData + 2, 2); + WscLen = ntohs(WscLen); + pData += 4; + Length -= 4; + switch (ntohs(WscType)) + { + case WSC_ID_VERSION: + /*wsc_version = *pData;*/ + break; + + case WSC_ID_SEL_REGISTRAR: + wsc_sel_reg = *pData; + break; + + case WSC_ID_DEVICE_PWD_ID: + NdisMoveMemory(&wsc_dev_pass_id, pData, sizeof(USHORT)); + wsc_dev_pass_id = be2cpu16(wsc_dev_pass_id); + break; + + case WSC_ID_SEL_REG_CFG_METHODS: + NdisMoveMemory(&wsc_sel_reg_conf_mthd, pData, sizeof(USHORT)); + wsc_sel_reg_conf_mthd = be2cpu16(wsc_sel_reg_conf_mthd); + break; + + case WSC_ID_VENDOR_EXT: +#ifdef WSC_V2_SUPPORT + if (pWscCtrl->WscV2Info.bEnableWpsV2 && (WscLen > 0)) + { + /* + Find WFA_EXT_ID_AUTHORIZEDMACS + */ + os_alloc_mem(NULL, &pAuthorizedMACs, WscLen); + if (pAuthorizedMACs) + { + NdisZeroMemory(pAuthorizedMACs, WscLen); + WscParseV2SubItem(WFA_EXT_ID_AUTHORIZEDMACS, pData, WscLen, pAuthorizedMACs, &AuthorizedMACsLen); + } + } +#endif /* WSC_V2_SUPPORT */ + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /*IsAPConfigured = pWscCtrl->WscConfStatus;*/ + + if (wsc_sel_reg == 0x01) + { + pWscCtrl->WscSelReg = 1; + WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, TRUE, wsc_dev_pass_id, wsc_sel_reg_conf_mthd, apidx, pAuthorizedMACs, AuthorizedMACsLen, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, TRUE, wsc_dev_pass_id, wsc_sel_reg_conf_mthd, pWscCtrl->EntryIfIdx, pAuthorizedMACs, AuthorizedMACsLen, AP_MODE); +#ifdef WSC_V2_SUPPORT + hex_dump("WscSelectedRegistrar - AuthorizedMACs::", pAuthorizedMACs, AuthorizedMACsLen); + if ((AuthorizedMACsLen == 6) && + (NdisEqualMemory(pAuthorizedMACs, BROADCAST_ADDR, MAC_ADDR_LEN) == FALSE) && + (NdisEqualMemory(pAuthorizedMACs, ZERO_MAC_ADDR, MAC_ADDR_LEN) == FALSE) && + (pWscCtrl->WscState <= WSC_STATE_WAIT_M3)) + { + PWSC_PEER_ENTRY pWscPeer = NULL; + NdisMoveMemory(pWscCtrl->EntryAddr, pAuthorizedMACs, MAC_ADDR_LEN); + RTMP_SEM_LOCK(&pWscCtrl->WscPeerListSemLock); + WscClearPeerList(&pWscCtrl->WscPeerList); + os_alloc_mem(pAd, (UCHAR **)&pWscPeer, sizeof(WSC_PEER_ENTRY)); + if (pWscPeer) + { + NdisZeroMemory(pWscPeer, sizeof(WSC_PEER_ENTRY)); + NdisMoveMemory(pWscPeer->mac_addr, pAuthorizedMACs, MAC_ADDR_LEN); + NdisGetSystemUpTime(&pWscPeer->receive_time); + insertTailList(&pWscCtrl->WscPeerList, + (PLIST_ENTRY)pWscPeer); + DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Add this MAC to WscPeerList\n")); + } + ASSERT(pWscPeer != NULL); + RTMP_SEM_UNLOCK(&pWscCtrl->WscPeerListSemLock); + } +#endif /* WSC_V2_SUPPORT */ + } + else + { + pWscCtrl->WscSelReg = 0; + WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscCtrl->EntryIfIdx, NULL, 0, AP_MODE); + } + APUpdateBeaconFrame(pAd, apidx); + +#ifdef WSC_V2_SUPPORT + if (pAuthorizedMACs) + os_free_mem(NULL, pAuthorizedMACs); +#endif /* WSC_V2_SUPPORT */ +} +#endif /* CONFIG_AP_SUPPORT */ + +#if defined(CONFIG_STA_SUPPORT) || defined (APCLI_SUPPORT) +/* + ======================================================================== + + Routine Description: + Make WSC IE for the ProbeReq frame + + Arguments: + pAd - NIC Adapter pointer + pOutBuf - all of WSC IE field + pIeLen - length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + None + + ======================================================================== +*/ +VOID WscBuildProbeReqIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ +/* UCHAR WscIEFixed[] = {0xdd, 0x0e, 0x00, 0x50, 0xf2, 0x04}; // length will modify later */ + WSC_IE_HEADER ieHdr; +/* UCHAR OutMsgBuf[512]; // buffer to create message contents */ + UCHAR *OutMsgBuf = NULL; /* buffer to create message contents */ + INT Len =0, templen = 0; + PUCHAR pData; + USHORT tempVal = 0; +#ifdef APCLI_SUPPORT + PWSC_REG_DATA pReg = (PWSC_REG_DATA)&pAd->ApCfg.ApCliTab[0].WscControl.RegData; +#else + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pAd->StaCfg.WscControl.RegData; +#endif /*APCLI_SUPPORT*/ + + DBGPRINT(RT_DEBUG_INFO, ("-----> WscBuildProbeReqIE\n")); + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&OutMsgBuf, 512); + if (OutMsgBuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* WSC IE Header */ + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; ieHdr.oui[2] = 0xF2; +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_MODE) && (pAd->StaCfg.BssType == BSS_ADHOC)) + ieHdr.oui[3] = 0x10; + else +#endif // IWSC_SUPPORT // + ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &OutMsgBuf[0]; + Len = 0; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Request Type */ +#ifdef APCLI_SUPPORT + if (pAd->ApCfg.ApCliTab[0].WscControl.WscConfMode == WSC_REGISTRAR) + tempVal = WSC_MSGTYPE_REGISTRAR; + else if (pAd->ApCfg.ApCliTab[0].WscControl.WscConfMode == WSC_ENROLLEE) + tempVal = WSC_MSGTYPE_ENROLLEE_OPEN_8021X; + else + tempVal = WSC_MSGTYPE_ENROLLEE_INFO_ONLY; +#else + if (pAd->StaCfg.WscControl.WscConfMode == WSC_REGISTRAR) + tempVal = WSC_MSGTYPE_REGISTRAR; + else if (pAd->StaCfg.WscControl.WscConfMode == WSC_ENROLLEE) + tempVal = WSC_MSGTYPE_ENROLLEE_OPEN_8021X; + else + tempVal = WSC_MSGTYPE_ENROLLEE_INFO_ONLY; +#endif /*APCLI_SUPPORT*/ + + templen = AppendWSCTLV(WSC_ID_REQ_TYPE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 3. Config method */ +#ifdef APCLI_SUPPORT +#ifdef WSC_V2_SUPPORT + if (pAd->ApCfg.ApCliTab[0].WscControl.WscV2Info.bEnableWpsV2) + { + if (pAd->ApCfg.ApCliTab[0].WscControl.bWscTrigger) + { + if (pAd->ApCfg.ApCliTab[0].WscControl.WscMode == WSC_PIN_MODE) + { + tempVal = (pAd->ApCfg.ApCliTab[0].WscControl.WscConfigMethods & 0x200F); + } + else + { + tempVal = (pAd->ApCfg.ApCliTab[0].WscControl.WscConfigMethods & 0x02F0); + } + } + else + tempVal = pAd->ApCfg.ApCliTab[0].WscControl.WscConfigMethods; + } + else +#endif /* WSC_V2_SUPPORT */ + { + tempVal = (pAd->ApCfg.ApCliTab[0].WscControl.WscConfigMethods & 0x00FF); + } +#else +#ifdef WSC_V2_SUPPORT + if (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2) + { + tempVal = pAd->StaCfg.WscControl.WscConfigMethods; + } + else +#endif /* WSC_V2_SUPPORT */ + { + tempVal = (pAd->StaCfg.WscControl.WscConfigMethods & 0x00FF); + } +#endif /* APCLI_SUPPORT */ + +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_MODE) && + (pAd->StaCfg.BssType == BSS_ADHOC)) + { + if (pAd->StaCfg.IWscInfo.bLimitedUI) + { + tempVal &= (~WSC_CONFMET_KEYPAD); + } + else + { + tempVal |= WSC_CONFMET_KEYPAD; + } + } +#endif /* IWSC_SUPPORT */ + + tempVal = cpu2be16(tempVal); + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 4. UUID */ + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, pReg->SelfInfo.Uuid, 0); + pData += templen; + Len += templen; + + /* 5. Primary device type */ + templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0); + pData += templen; + Len += templen; + + /* 6. RF band, shall change based on current channel */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, &pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /* 7. Associate state */ + tempVal = pReg->SelfInfo.AssocState; + templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 8. Config error */ + tempVal = pReg->SelfInfo.ConfigError; + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 9. Device password ID */ + tempVal = pReg->SelfInfo.DevPwdId; + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (CurOpMode == STA_MODE)) + { + /* Connection Type Flag ESS */ + templen = AppendWSCTLV(WSC_ID_CONN_TYPE, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + + /* Connection Type Flag ESS */ + tempVal = htons(pAd->StaCfg.IWscInfo.IpMethod); + templen = AppendWSCTLV(WSC_ID_IP_ADDR_CONF_METHOD, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + } +#endif /* IWSC_SUPPORT */ + +#ifdef WSC_V2_SUPPORT +#ifdef APCLI_SUPPORT + if (pAd->ApCfg.ApCliTab[0].WscControl.WscV2Info.bEnableWpsV2) +#else + if (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2) +#endif /*APCLI_SUPPORT*/ + { + /* 10. Manufacturer */ + NdisZeroMemory(pData, 64 + 4); + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* 11. Model Name */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* 12. Model Number */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* 13. Device Name */ + NdisZeroMemory(pData, 32 + 4); + templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* Version2 */ +#ifdef APCLI_SUPPORT + WscGenV2Msg(&pAd->ApCfg.ApCliTab[0].WscControl, + FALSE, + NULL, + 0, + &pData, + &Len); +#else + WscGenV2Msg(&pAd->StaCfg.WscControl, + FALSE, + NULL, + 0, + &pData, + &Len); +#endif/*APCLI_SUPPORT*/ + } +#endif /* WSC_V2_SUPPORT */ + + + ieHdr.length = ieHdr.length + Len; + RTMPMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + RTMPMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), OutMsgBuf, Len); + *pIeLen = sizeof(WSC_IE_HEADER) + Len; + + if (OutMsgBuf != NULL) + os_free_mem(NULL, OutMsgBuf); + + DBGPRINT(RT_DEBUG_INFO, ("<----- WscBuildProbeReqIE\n")); +} + + +/* + ======================================================================== + + Routine Description: + Make WSC IE for the AssocReq frame + + Arguments: + pAd - NIC Adapter pointer + pOutBuf - all of WSC IE field + pIeLen - length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + None + + ======================================================================== +*/ +VOID WscBuildAssocReqIE( + /*IN PRTMP_ADAPTER pAd,*/ + IN PWSC_CTRL pWscControl, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ + WSC_IE_HEADER ieHdr; +/* UCHAR Data[512]; */ + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + UINT8 tempVal = 0; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + if (pWscControl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("WscBuildAssocReqIE: pWscControl is NULL\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildAssocReqIE\n")); + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* WSC IE Header */ + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; + ieHdr.oui[2] = 0xF2; ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* Request Type */ + if (pWscControl->WscConfMode == WSC_ENROLLEE) + tempVal = WSC_MSGTYPE_ENROLLEE_INFO_ONLY; + else + tempVal = WSC_MSGTYPE_REGISTRAR; + templen = AppendWSCTLV(WSC_ID_REQ_TYPE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + } +#endif /* WSC_V2_SUPPORT */ + + + ieHdr.length = ieHdr.length + Len; + RTMPMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + RTMPMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); + *pIeLen = sizeof(WSC_IE_HEADER) + Len; + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildAssocReqIE\n")); +} +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +VOID WscProfileRetryTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAdapter = NULL; + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + BOOLEAN bReConnect = TRUE; + UCHAR CurOpMode = 0xFF; + + if (pWscControl == NULL) + return; + + pAdapter = pWscControl->pAd; + + if (pAdapter != NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscProfileRetryTimeout:: WSC profile retry timeout index: %d\n", pWscControl->WscProfile.ApplyProfileIdx)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; + +#ifdef APCLI_SUPPORT + if( (CurOpMode == AP_MODE) + && (pAdapter->ApCfg.ApCliTab[BSS0].CtrlCurrState == APCLI_CTRL_CONNECTED) + && (pAdapter->ApCfg.ApCliTab[BSS0].SsidLen != 0)) + { + INT i; + for (i=0; iMacTab.Content[i]; + + if ( IS_ENTRY_APCLI(pEntry) && + (pEntry->Sst == SST_ASSOC) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + bReConnect = FALSE; + } + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + if ((CurOpMode == STA_MODE) && INFRA_ON(pAdapter) && (pAdapter->IndicateMediaState == NdisMediaStateConnected)) + { + pWscControl->WscProfileRetryTimerRunning = FALSE; + bReConnect = FALSE; + } + + if (bReConnect) + { + if (pWscControl->WscProfile.ApplyProfileIdx < pWscControl->WscProfile.ProfileCnt-1) + pWscControl->WscProfile.ApplyProfileIdx++; + else + pWscControl->WscProfile.ApplyProfileIdx = 0; + +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + BOOLEAN apcliEn; + WscWriteConfToApCliCfg(pAdapter, + pWscControl, + &pWscControl->WscProfile.Profile[pWscControl->WscProfile.ApplyProfileIdx], + TRUE); + + apcliEn = pAdapter->ApCfg.ApCliTab[BSS0].Enable; + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAdapter->ApCfg.ApCliTab[BSS0].Enable = FALSE; + ApCliIfDown(pAdapter); + pAdapter->ApCfg.ApCliTab[BSS0].Enable = TRUE; + } + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + WscWriteConfToPortCfg(pAdapter, + pWscControl, + &pWscControl->WscProfile.Profile[pWscControl->WscProfile.ApplyProfileIdx], + TRUE); + } +#endif /* CONFIG_STA_SUPPORT */ + + pAdapter->WriteWscCfgToDatFile = (pWscControl->EntryIfIdx & 0x0F); +/*#ifdef KTHREAD_SUPPORT */ +/* WAKE_UP(&(pAdapter->wscTask)); */ +/*#else */ +/* RTMP_SEM_EVENT_UP(&(pAdapter->wscTask.taskSema)); */ +/*#endif */ + RtmpOsTaskWakeUp(&(pAdapter->wscTask)); + DBGPRINT(RT_DEBUG_TRACE, ("WscProfileRetryTimeout:: WSC profile retry index: %d\n", pWscControl->WscProfile.ApplyProfileIdx)); + } +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bAutoConnectByBssid = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + } +} + +VOID WscPBCTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + RTMP_ADAPTER *pAd = NULL; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_OFF, ("-----> WscPBCTimeOutAction\n")); + + if (pWscControl != NULL) + pAd = pWscControl->pAd; + + if (pAd != NULL) + { + + if (pWscControl->WscPBCTimerRunning) + { + pWscControl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled); + } + + WscPBCExec(pAd, FALSE, pWscControl); + + /* call Mlme handler to execute it */ + RTMP_MLME_HANDLER(pAd); + } + DBGPRINT(RT_DEBUG_OFF, ("<----- WscPBCTimeOutAction\n")); +} + +/* + ======================================================================== + + Routine Description: + Exec scan after scan timer expiration + + Arguments: + FunctionContext NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID WscScanTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = NULL; + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + + if (pWscControl == NULL) + return; + + pAd = pWscControl->pAd; + + if (pAd != NULL) + { + /* call to execute the scan actions */ + WscScanExec(pAd, pWscControl); + + /* register 10 second timer for PBC or PIN connection execution */ + if (pWscControl->WscMode == WSC_PBC_MODE) + { + /* Prevent infinite loop if conncet time out didn't stop the repeat scan */ + if (pWscControl->WscState != WSC_STATE_OFF) + { + RTMPSetTimer(&pWscControl->WscPBCTimer, 10000); + pWscControl->WscPBCTimerRunning = TRUE; + } + } + else if (pWscControl->WscMode == WSC_PIN_MODE) + { + /* Prevent infinite loop if conncet time out didn't stop the repeat scan */ + } + + DBGPRINT(RT_DEBUG_OFF, ("!!! WscScanTimeOutAction !!!\n")); + + /* call Mlme handler to execute it */ + RTMP_MLME_HANDLER(pAd); + } +} + +BOOLEAN ValidateChecksum( + IN UINT PIN) +{ + UINT accum = 0; + + accum += 3 * ((PIN / 10000000) % 10); + accum += 1 * ((PIN / 1000000) % 10); + accum += 3 * ((PIN / 100000) % 10); + accum += 1 * ((PIN / 10000) % 10); + accum += 3 * ((PIN / 1000) % 10); + accum += 1 * ((PIN / 100) % 10); + accum += 3 * ((PIN / 10) % 10); + accum += 1 * ((PIN / 1) % 10); + + return (0 == (accum % 10)); +} /* ValidateChecksum */ + +/* + Generate 4-digit random number, ex:1234 +*/ +UINT WscRandomGen4digitPinCode( + IN PRTMP_ADAPTER pAd) +{ + UINT iPin; + + iPin = RandomByte2(pAd) * 256 * 256 + RandomByte2(pAd) * 256 + RandomByte2(pAd); + iPin = iPin % 10000; + + return iPin; +} + +UINT WscRandomGeneratePinCode( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + UINT iPin; + UINT checksum; + + iPin = RandomByte(pAd) * 256 * 256 + RandomByte(pAd) * 256 + RandomByte(pAd); + + iPin = iPin % 10000000; + + + checksum = ComputeChecksum( iPin ); + iPin = iPin*10 + checksum; + + return iPin; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID WscInformFromWPA( + IN PMAC_TABLE_ENTRY pEntry) +{ + /* WPA_STATE_MACHINE informs this Entry is already WPA_802_1X_PORT_SECURED. */ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)pEntry->pAd; + BOOLEAN Cancelled; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscInformFromWPA\n")); + + if (MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr)) + { + NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, MAC_ADDR_LEN); + RTMPCancelTimer(&pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EapolTimer, &Cancelled); + pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EapolTimerRunning = FALSE; + pEntry->bWscCapable = FALSE; + pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscState = WSC_STATE_CONFIGURED; + + DBGPRINT(RT_DEBUG_TRACE, ("Reset EntryIfIdx to %d\n", WSC_INIT_ENTRY_APIDX)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscInformFromWPA\n")); +} + +VOID WscDelWPARetryTimer( + IN PRTMP_ADAPTER pAd) +{ + PMAC_TABLE_ENTRY pEntry; + UCHAR apidx = MAIN_MBSSID; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscDelWPARetryTimer\n")); + + pEntry = MacTableLookup(pAd, pAd->ApCfg.MBSSID[apidx].WscControl.EntryAddr); + + if (pEntry) + { + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + pEntry->WpaState = AS_NOTUSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscDelWPARetryTimer\n")); +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscStop( + IN PRTMP_ADAPTER pAd, +#ifdef CONFIG_AP_SUPPORT + IN BOOLEAN bFromApCli, +#endif /* CONFIG_AP_SUPPORT */ + IN PWSC_CTRL pWscControl) +{ + PWSC_UPNP_NODE_INFO pWscUPnPInfo; + BOOLEAN Cancelled; +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + MAC_TABLE_ENTRY *pEntry; + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ + UCHAR CurOpMode = 0xff; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; + if (bFromApCli) + pWscControl->bConfiguredAP = FALSE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pWscControl->bConfiguredAP = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + + pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + + if(pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerPending = FALSE; + } + if(pWscControl->bM2DTimerRunning) + { + pWscControl->bM2DTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled); + } + + pWscUPnPInfo->bUPnPInProgress = FALSE; + pWscControl->M2DACKBalance = 0; + pWscUPnPInfo->registrarID = 0; + + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); +#ifdef CONFIG_AP_SUPPORT +#ifdef SMART_MESH + pWscControl->bWscPBCAddrMode = FALSE; +#ifdef SMART_MESH_HIDDEN_WPS + pWscControl->bRunningHiddenWPS = FALSE; +#ifdef APCLI_SUPPORT + if (bFromApCli) + Set_HiddenWps_State(&pAd->ApCfg.ApCliTab[apidx].SmartMeshCfg, HIDDEN_WPS_STATE_STOP); +#endif /* APCLI_SUPPORT */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + } + + if (pWscControl->WscUpdatePortCfgTimerRunning) + { + pWscControl->WscUpdatePortCfgTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscUpdatePortCfgTimer, &Cancelled); + } + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; +#ifdef CONFIG_AP_SUPPORT + if ((pWscControl->EntryIfIdx & 0x0F)< pAd->ApCfg.BssidNum) + { + pEntry = MacTableLookup(pAd, pWscControl->EntryAddr); + + if (CurOpMode == AP_MODE) + { + if (pEntry && !bFromApCli) + { + pEntry->bWscCapable = FALSE; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + + pWscControl->WscSelReg = 0; + if ( (pWscControl->WscStatus == STATUS_WSC_CONFIGURED) || + (pWscControl->WscStatus == STATUS_WSC_FAIL) || + (pWscControl->WscStatus == STATUS_WSC_PBC_TOO_MANY_AP)) + ; + else + pWscControl->WscStatus = STATUS_WSC_NOTUSED; + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->lastId = 1; + pWscControl->EapMsgRunning = FALSE; + pWscControl->EapolTimerPending = FALSE; + pWscControl->bWscTrigger = FALSE; + + if (pWscControl->WscScanTimerRunning) + { + pWscControl->WscScanTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled); + } + + if (pWscControl->WscPBCTimerRunning) + { + pWscControl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled); + } + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + NdisZeroMemory(&pAd->MlmeAux.AutoReconnectSsid[0], MAX_LEN_OF_SSID); + NdisMoveMemory(&pAd->MlmeAux.AutoReconnectSsid[0], &pAd->MlmeAux.Ssid[0], pAd->MlmeAux.SsidLen); + /* YF: Reset to default after active pbc mode */ + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_LED_SUPPORT + if (pWscControl->WscLEDTimerRunning) + { + pWscControl->WscLEDTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscLEDTimer, &Cancelled); + } + if (pWscControl->WscSkipTurnOffLEDTimerRunning) + { + pWscControl->WscSkipTurnOffLEDTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscSkipTurnOffLEDTimer, &Cancelled); + } + /* Reset the WPS walk time. */ + pWscControl->bWPSWalkTimeExpiration = FALSE; + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + +} + +#ifdef CON_WPS +VOID WscConWpsStop( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApCli, + IN PWSC_CTRL pWscControl) +{ + + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscConWpsStop\n")); + + if (pAd->conWscStatus == CON_WPS_STATUS_DISABLED) + return; + +#ifdef MULTI_INF_SUPPORT + /* Single Driver ctrl the WSC SM between the two pAd */ + PRTMP_ADAPTER pOpposAd; + PWSC_CTRL pWpsCtrl = NULL; + INT IsAPConfigured = 0; + UCHAR pAdListInfo[2] = {0, 0}; + INT myBandIdx = 0, opsBandIdx = 0; + + /* Update the Global pAd List Band Info */ + pOpposAd = (PRTMP_ADAPTER)pAdGlobalList[0]; + pAdListInfo[0] = RFIC_IS_5G_BAND(pOpposAd); + + pOpposAd = (PRTMP_ADAPTER)pAdGlobalList[1]; + pAdListInfo[1] = RFIC_IS_5G_BAND(pOpposAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s pAdListInfo is5G---> [%d, %d]\n", + pAdListInfo[0], pAdListInfo[1])); + + /* which band from function in */ + if (RFIC_IS_5G_BAND(pAd) == pAdListInfo[0]) + { + myBandIdx = 0; + opsBandIdx = 1; + } + else if (RFIC_IS_5G_BAND(pAd) == pAdListInfo[1]) + { + myBandIdx = 1; + opsBandIdx = 0; + } + else + ; + + + pOpposAd = (PRTMP_ADAPTER) pAdGlobalList[opsBandIdx]; + + if (bFromApCli) + { + pWpsCtrl = &pOpposAd->ApCfg.ApCliTab[BSS0].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS: Stop the Band[%d] ApCli WPS, state [%d]\n", + opsBandIdx, pWpsCtrl->WscState)); + if (pWpsCtrl->WscState != WSC_STATE_OFF) + { + WscStop(pOpposAd, TRUE, pWpsCtrl); + pWpsCtrl->WscConfMode = WSC_DISABLE; + } + } + else + { + pWpsCtrl = &pOpposAd->ApCfg.MBSSID[apidx].WscControl; + IsAPConfigured = pWpsCtrl->WscConfStatus; + + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pWpsCtrl->bWscTrigger == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS[%d]: Stop the AP Wsc Machine\n", opsBandIdx)); + WscBuildBeaconIE(pOpposAd, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pOpposAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, + apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pOpposAd, apidx); + WscStop(pOpposAd, FALSE, pWpsCtrl); + } + } + + +#else + /* Separate Driver used to MiniUpnpd to comunicate each other. */ + PWSC_UPNP_CTRL_WSC_BAND_STOP pWscUpnpBandStop; + + os_alloc_mem(NULL, (UCHAR **)&pWscUpnpBandStop, sizeof(WSC_UPNP_CTRL_WSC_BAND_STOP)); + + if (pWscUpnpBandStop != NULL) + { + NdisCopyMemory(pWscUpnpBandStop->ifName, pAd->net_dev->name, IFNAMSIZ); + pWscUpnpBandStop->is2gBand = !RFIC_IS_5G_BAND(pAd); + pWscUpnpBandStop->isApCli = bFromApCli; + + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS: WSC_UPNP_CTRL_WSC_BAND_STOP[%s] is2G[%d], isApCli[%d]\n", + pWscUpnpBandStop->ifName, + pWscUpnpBandStop->is2gBand, pWscUpnpBandStop->isApCli)); + + WscSendUPnPMessage(pAd, apidx, WSC_OPCODE_UPNP_CTRL, 99, pWscUpnpBandStop, + sizeof(WSC_UPNP_CTRL_WSC_BAND_STOP), 0, 0, NULL, AP_MODE); + os_free_mem(NULL, pWscUpnpBandStop); + } +#endif /* MULTI_INF_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscConWpsStop\n")); +} +#endif /* CON_WPS */ + +VOID WscInit( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApCli, + IN UCHAR BssIndex) +{ + IN PWSC_CTRL pWscControl = NULL; +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + UCHAR CurOpMode = AP_MODE; + +#ifdef CONFIG_AP_SUPPORT + INT IsAPConfigured; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (bFromApCli) + pWscControl = &pAd->ApCfg.ApCliTab[BssIndex & 0x0F].WscControl; + else +#endif /* APCLI_SUPPORT */ + pWscControl = &pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscControl; + + pWscControl->bFromApCli = bFromApCli; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + { + pWscControl = &pAd->StaCfg.WscControl; + CurOpMode = STA_MODE; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pWscControl == NULL) + return; + + if (pWscControl->WscEnrolleePinCode == 0) + { + if (pWscControl->WscEnrollee4digitPinCode) + { + pWscControl->WscEnrolleePinCodeLen = 4; + pWscControl->WscEnrolleePinCode = WscRandomGen4digitPinCode(pAd); + } + else + { + pWscControl->WscEnrolleePinCode = GenerateWpsPinCode(pAd, bFromApCli, BssIndex); + pWscControl->WscEnrolleePinCodeLen = 8; + } + } + pWscControl->RegData.SelfInfo.Version = WSC_VERSION; +#ifdef WSC_V2_SUPPORT + pWscControl->RegData.SelfInfo.Version2 = WSC_V2_VERSION; +#endif /* WSC_V2_SUPPORT */ + + pWscControl->bWscLastOne = FALSE; + pWscControl->bWscFirstOne = FALSE; + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + pWscControl->WscStatus = STATUS_WSC_IDLE; +#ifdef CONFIG_AP_SUPPORT + if (((CurOpMode == AP_MODE) && + (pWscControl->WscConfMode == WSC_DISABLE)) +#ifdef WSC_V2_SUPPORT + || ((pWscControl->WscV2Info.bWpsEnable == FALSE) && pWscControl->WscV2Info.bEnableWpsV2) +#endif /* WSC_V2_SUPPORT */ + ) + { + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (!bFromApCli) +#endif /* APCLI_SUPPORT */ + { + pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscIEProbeResp.ValueLen = 0; + } + } + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + + WscInitRegistrarPair(pAd, pWscControl, BssIndex); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (!bFromApCli) +#endif /* APCLI_SUPPORT */ + { + IsAPConfigured = pWscControl->WscConfStatus; + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, (BssIndex & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, BssIndex, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; + pWscControl->bRegenPublicKey = FALSE; + NdisZeroMemory(&pWscControl->NfcPasswd[0], NFC_DEV_PASSWD_LEN); +#endif /* WSC_NFC_SUPPORT */ +} + +USHORT WscGetAuthType( + IN NDIS_802_11_AUTHENTICATION_MODE authType) +{ + switch(authType) + { + case Ndis802_11AuthModeOpen: + return WSC_AUTHTYPE_OPEN; + case Ndis802_11AuthModeWPAPSK: + return WSC_AUTHTYPE_WPAPSK; + case Ndis802_11AuthModeShared: + return WSC_AUTHTYPE_SHARED; + case Ndis802_11AuthModeWPANone: + return WSC_AUTHTYPE_WPANONE; + case Ndis802_11AuthModeWPA: + return WSC_AUTHTYPE_WPA; + case Ndis802_11AuthModeWPA1WPA2: + return (WSC_AUTHTYPE_WPA | WSC_AUTHTYPE_WPA2); + case Ndis802_11AuthModeWPA2: + return WSC_AUTHTYPE_WPA2; + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + return (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK); + case Ndis802_11AuthModeWPA2PSK: + return WSC_AUTHTYPE_WPA2PSK; + default: + return WSC_AUTHTYPE_OPEN; + } +} + +USHORT WscGetEncryType( + IN NDIS_802_11_WEP_STATUS encryType) +{ + switch(encryType) + { + case Ndis802_11WEPDisabled: + return WSC_ENCRTYPE_NONE; + case Ndis802_11WEPEnabled: + return WSC_ENCRTYPE_WEP; + case Ndis802_11TKIPEnable: + return WSC_ENCRTYPE_TKIP; + case Ndis802_11TKIPAESMix: + return (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP); + default: + case Ndis802_11AESEnable: + return WSC_ENCRTYPE_AES; + } +} + +PSTRING WscGetAuthTypeStr( + IN USHORT authFlag) +{ + switch(authFlag) + { + case WSC_AUTHTYPE_OPEN: + return "OPEN"; + case WSC_AUTHTYPE_WPAPSK: + return "WPAPSK"; + case WSC_AUTHTYPE_SHARED: + return "SHARED"; + case WSC_AUTHTYPE_WPANONE: + return "WPANONE"; + case WSC_AUTHTYPE_WPA: + return "WPA"; + case WSC_AUTHTYPE_WPA2: + return "WPA2"; + default: + case (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK): + return "WPAPSKWPA2PSK"; + case WSC_AUTHTYPE_WPA2PSK: + return "WPA2PSK"; + case (WSC_AUTHTYPE_OPEN | WSC_AUTHTYPE_SHARED): + return "WEPAUTO"; + } +} + +PSTRING WscGetEncryTypeStr( + IN USHORT encryFlag) +{ + switch(encryFlag) + { + case WSC_ENCRTYPE_NONE: + return "NONE"; + case WSC_ENCRTYPE_WEP: + return "WEP"; + case WSC_ENCRTYPE_TKIP: + return "TKIP"; + default: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + return "TKIPAES"; + case WSC_ENCRTYPE_AES: + return "AES"; + } +} + +NDIS_802_11_AUTHENTICATION_MODE WscGetAuthMode( + IN USHORT authFlag) +{ + switch(authFlag) + { + case WSC_AUTHTYPE_OPEN: + return Ndis802_11AuthModeOpen; + case WSC_AUTHTYPE_WPAPSK: + return Ndis802_11AuthModeWPAPSK; + case WSC_AUTHTYPE_SHARED: + return Ndis802_11AuthModeShared; + case WSC_AUTHTYPE_WPANONE: + return Ndis802_11AuthModeWPANone; + case WSC_AUTHTYPE_WPA: + return Ndis802_11AuthModeWPA; + case WSC_AUTHTYPE_WPA2: + return Ndis802_11AuthModeWPA2; + default: + case (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK): + return Ndis802_11AuthModeWPA1PSKWPA2PSK; + case WSC_AUTHTYPE_WPA2PSK: + return Ndis802_11AuthModeWPA2PSK; + } +} + +NDIS_802_11_WEP_STATUS WscGetWepStatus( + IN USHORT encryFlag) +{ + switch(encryFlag) + { + case WSC_ENCRTYPE_NONE: + return Ndis802_11WEPDisabled; + case WSC_ENCRTYPE_WEP: + return Ndis802_11WEPEnabled; + case WSC_ENCRTYPE_TKIP: + return Ndis802_11TKIPEnable; + default: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + return Ndis802_11TKIPAESMix; + case WSC_ENCRTYPE_AES: + return Ndis802_11AESEnable; + } +} + +void WscWriteConfToPortCfg( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee) +{ + UCHAR CurApIdx = MAIN_MBSSID; + UCHAR CurOpMode = AP_MODE; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToPortCfg\n")); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pWscControl->EntryIfIdx == BSS0) + CurOpMode = STA_MODE; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + CurApIdx = (pWscControl->EntryIfIdx & 0x0F); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (bEnrollee || (CurOpMode == AP_MODE)) + { + if (CurOpMode == AP_MODE) + { + NdisZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + pAd->ApCfg.MBSSID[CurApIdx].SsidLen = pCredential->SSID.SsidLength; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pAd->MlmeAux.AutoReconnectSsidLen = pCredential->SSID.SsidLength; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pCredential->SSID.Ssid, pAd->MlmeAux.AutoReconnectSsidLen); + pAd->MlmeAux.SsidLen = pCredential->SSID.SsidLength; + NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pCredential->SSID.Ssid, pAd->MlmeAux.SsidLen); + if (!NdisEqualMemory(pCredential->MacAddr, pAd->CurrentAddress, MAC_ADDR_LEN)) + { + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisMoveMemory(pAd->MlmeAux.Bssid, pCredential->MacAddr, MAC_ADDR_LEN); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("ra%d - AuthType: %u, EncrType: %u\n", CurApIdx, pCredential->AuthType, pCredential->EncrType)); + if (pCredential->AuthType & (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK | WSC_AUTHTYPE_WPANONE)) + { + if (!(pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))) + { + DBGPRINT(RT_DEBUG_TRACE, ("AuthType is WPAPSK or WPA2PAK.\n" + "Get illegal EncrType(%d) from External Registrar, set EncrType to TKIP\n", + pCredential->EncrType)); + pCredential->EncrType = WSC_ENCRTYPE_TKIP; + } +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.WpaState = SS_START; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((CurOpMode == AP_MODE) && (pWscControl->WscV2Info.bEnableWpsV2)) + { + if (pCredential->AuthType == WSC_AUTHTYPE_WPAPSK) + pCredential->AuthType = (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK); + if (pCredential->EncrType == WSC_ENCRTYPE_TKIP) + pCredential->EncrType = (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES); + } +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + WscSetAuthMode(pAd, CurOpMode, CurApIdx, WscGetAuthTypeStr(pCredential->AuthType)); + WscSetEncrypType(pAd, CurOpMode, CurApIdx, WscGetEncryTypeStr(pCredential->EncrType)); + if (pCredential->EncrType != WSC_ENCRTYPE_NONE) + { + if (pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = 1; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.wdev.DefaultKeyId = 0; +#endif /* CONFIG_STA_SUPPORT */ + + if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64) + { + UCHAR *pPMKBuf = NULL, *pSSIDStr = NULL; + INT ssidLen = 0; + STRING PassphraseStr[65] = {0}; + + pWscControl->WpaPskLen = pCredential->KeyLength; + RTMPZeroMemory(pWscControl->WpaPsk, 64); + RTMPMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen); + RTMPMoveMemory(PassphraseStr, pCredential->Key, pWscControl->WpaPskLen); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pPMKBuf = pAd->ApCfg.MBSSID[CurApIdx].PMK; + pSSIDStr = (PUCHAR)pAd->ApCfg.MBSSID[CurApIdx].Ssid; + ssidLen = pAd->ApCfg.MBSSID[CurApIdx].SsidLen; + RTMPZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].WPAKeyString, 65); + RTMPMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].WPAKeyString, pCredential->Key, pWscControl->WpaPskLen); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + RTMPZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + RTMPMoveMemory(pAd->StaCfg.WpaPassPhrase, pCredential->Key, pWscControl->WpaPskLen); + pAd->StaCfg.WpaPassPhraseLen = pCredential->KeyLength; + pPMKBuf = pAd->StaCfg.PMK; + pSSIDStr = (PUCHAR)pCredential->SSID.Ssid; + ssidLen = pCredential->SSID.SsidLength; + } +#endif /* CONFIG_STA_SUPPORT */ + RT_CfgSetWPAPSKKey(pAd, pCredential->Key, pWscControl->WpaPskLen, pSSIDStr, ssidLen, pPMKBuf); + DBGPRINT(RT_DEBUG_TRACE, ("WpaPskLen = %d\n", pWscControl->WpaPskLen)); + } + else + { + pWscControl->WpaPskLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + } + else if (pCredential->EncrType == WSC_ENCRTYPE_WEP) + { + UCHAR WepKeyId = 0; + USHORT WepKeyLen = pCredential->KeyLength; + + if ((pCredential->KeyIndex >= 1) && (pCredential->KeyIndex <= 4)) + { + WepKeyId = (pCredential->KeyIndex - 1); /* KeyIndex = 1 ~ 4 */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = WepKeyId; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.wdev.DefaultKeyId = WepKeyId; +#endif /* CONFIG_STA_SUPPORT */ + + /* 5 or 13 ASCII characters */ + /* 10 or 26 Hex characters */ + if (WepKeyLen == 5 || WepKeyLen == 13 || WepKeyLen == 10 || WepKeyLen == 26) + { + if (WepKeyLen == 5 || WepKeyLen == 13) + { + pAd->SharedKey[CurApIdx][WepKeyId].KeyLen = (UCHAR)WepKeyLen; + memcpy(pAd->SharedKey[CurApIdx][WepKeyId].Key, + pCredential->Key, + WepKeyLen); + if (WepKeyLen == 5) + pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP128; + } + else + { + pAd->SharedKey[CurApIdx][WepKeyId].KeyLen = (UCHAR)(WepKeyLen/2); + AtoH((PSTRING) pCredential->Key, pAd->SharedKey[CurApIdx][WepKeyId].Key, WepKeyLen/2); + if (WepKeyLen == 10) + pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP128; + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("WEP: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unsupport default key index (%d)\n", WepKeyId)); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = 0; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.wdev.DefaultKeyId = 0; +#endif /* CONFIG_STA_SUPPORT */ + + } + } + } +#ifdef CONFIG_AP_SUPPORT + } + else + { + if (CurOpMode == AP_MODE) + { + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = 1; + WscSetAuthMode(pAd, CurOpMode, CurApIdx, "WPAPSKWPA2PSK"); + WscSetEncrypType(pAd, CurOpMode, CurApIdx, "TKIPAES"); + pWscControl->WpaPskLen = (INT)pCredential->KeyLength; + NdisZeroMemory(pWscControl->WpaPsk, 64); + NdisMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen); + /* Copy SSID */ + NdisZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + pAd->ApCfg.MBSSID[CurApIdx].SsidLen = pCredential->SSID.SsidLength; + /* + Hex Key + */ + if(pWscControl->WscKeyASCII == 0) + { + AtoH((PSTRING) pWscControl->WpaPsk, pAd->ApCfg.MBSSID[CurApIdx].PMK, 32); + } + else + { + UCHAR keyMaterial[40] = {0}; + + RtmpPasswordHash((PSTRING)pWscControl->WpaPsk, + (PUCHAR) pAd->ApCfg.MBSSID[CurApIdx].Ssid, + pAd->ApCfg.MBSSID[CurApIdx].SsidLen, + keyMaterial); + NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].PMK, keyMaterial, 32); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + /* + Atheros WPS Testbed AP will put A-Band BSSID in credential of M7. + To prevent 2.4G only STA would fail to re-connect by BSSID, set profile retry timer here. + */ + if ((pAd->StaCfg.BssType == BSS_INFRA) && + (pWscControl->WscDriverAutoConnect == 2) && + (pWscControl->WscProfile.ProfileCnt >= 1)) + { + pWscControl->WscProfileRetryTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->WscProfileRetryTimer, WSC_PROFILE_RETRY_TIME_OUT); + } + +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->StaCfg.IWscInfo.RegDepth != 0) && + (pAd->StaCfg.IWscInfo.AvaSubMaskListCount != 0)) + { + if ((pCredential->AvaIpv4SubmaskList[0] == 0) && + (pCredential->AvaIpv4SubmaskList[1] == 0) && + (pCredential->AvaIpv4SubmaskList[2] == 0)) + pAd->StaCfg.IWscInfo.AvaSubMaskListCount = 0; + } +#endif /* IWSC_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<----- ra%d - WscWriteConfToPortCfg\n", CurApIdx)); +} + + +VOID WscWriteSsidToDatFile( + IN PRTMP_ADAPTER pAd, + IN PSTRING pTempStr, + IN BOOLEAN bNewFormat, + IN UCHAR CurOpMode) +{ +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx; +#endif /* CONFIG_AP_SUPPORT */ + INT offset = 0; + + if (bNewFormat == FALSE) + { + NdisZeroMemory(pTempStr, 512); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (apidx == 0) + { + NdisMoveMemory(pTempStr, "SSID=", strlen("SSID=")); + offset = strlen(pTempStr); + } + else + { + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, ";", 1); + offset += 1; + } + NdisMoveMemory(pTempStr + offset, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + UINT profile_idx = pAd->StaCfg.WscControl.WscProfile.ApplyProfileIdx; + PWSC_CREDENTIAL pCredential = &pAd->StaCfg.WscControl.WscProfile.Profile[profile_idx]; + NdisMoveMemory(pTempStr, "SSID=", strlen("SSID=")); + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + } +#endif /* CONFIG_STA_SUPPORT */ + } +#ifdef CONFIG_AP_SUPPORT + else + { + STRING item_str[10] = {0}; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(item_str, sizeof(item_str), "SSID%d", (apidx + 1)); + if (rtstrstr(pTempStr, item_str)) + { + NdisZeroMemory(pTempStr, 512); + NdisMoveMemory(pTempStr, item_str, strlen(item_str)); + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, "=", 1); + offset += 1; + NdisMoveMemory(pTempStr + offset, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen); + } + NdisZeroMemory(item_str, 10); + } + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID WscWriteWpaPskToDatFile( + IN PRTMP_ADAPTER pAd, + IN PSTRING pTempStr, + IN BOOLEAN bNewFormat) +{ +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx; +#endif /* CONFIG_AP_SUPPORT */ + PWSC_CTRL pWscControl; + INT offset = 0; + + if (bNewFormat == FALSE) + { + NdisZeroMemory(pTempStr, 512); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + if (apidx == 0) + { + NdisMoveMemory(pTempStr, "WPAPSK=", strlen("WPAPSK=")); + offset = strlen(pTempStr); + } + else + { + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, ";", 1); + offset += 1; + } + NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pWscControl = &pAd->StaCfg.WscControl; + NdisMoveMemory(pTempStr, "WPAPSK=", strlen("WPAPSK=")); + if (pWscControl->WpaPskLen) + { + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen); + } + } +#endif /* CONFIG_STA_SUPPORT */ + } +#ifdef CONFIG_AP_SUPPORT + else + { + STRING item_str[10] = {0}; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(item_str, sizeof(item_str), "WPAPSK%d", (apidx + 1)); + if (rtstrstr(pTempStr, item_str)) + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + NdisZeroMemory(pTempStr, 512); + NdisMoveMemory(pTempStr, item_str, strlen(item_str)); + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, "=", 1); + offset += 1; + NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen); + } + NdisZeroMemory(item_str, 10); + } + } +#endif /* CONFIG_AP_SUPPORT */ +} + +BOOLEAN WscCheckNonce( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *pElem, + IN BOOLEAN bFlag, + IN PWSC_CTRL pWscControl) +{ + USHORT Length; + PUCHAR pData; + USHORT WscType, WscLen, WscId; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscCheckNonce\n")); + + if (bFlag) + { + /* check Registrar Nonce */ + WscId = WSC_ID_REGISTRAR_NONCE; + DBGPRINT(RT_DEBUG_TRACE, ("check Registrar Nonce\n")); + } + else + { + /* check Enrollee Nonce */ + WscId = WSC_ID_ENROLLEE_NONCE; + DBGPRINT(RT_DEBUG_TRACE, ("check Enrollee Nonce\n")); + } + + pData = pElem->Msg; + Length = pElem->MsgLen; + + /* We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */ + while (Length > 4) + { + WSC_IE TLV_Recv; + char ZeroNonce[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + if (WscType == WscId) + { + if (RTMPCompareMemory(pWscControl->RegData.SelfNonce, pData, 16) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Nonce match!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n")); + return TRUE; + } + else if (NdisEqualMemory(pData, ZeroNonce, 16)) + { + /* Intel external registrar will send WSC_NACK with enrollee nonce */ + /* "10 1A 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" */ + /* when AP is configured and user selects not to configure AP. */ + DBGPRINT(RT_DEBUG_TRACE, ("Zero Enrollee Nonce!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n")); + return TRUE; + } + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Nonce mismatch!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n")); + return FALSE; +} + +VOID WscGetRegDataPIN( + IN PRTMP_ADAPTER pAdapter, + IN UINT PinCode, + IN PWSC_CTRL pWscControl) +{ + UCHAR tempPIN[9] = {0}; + + if ((pWscControl->WscMode == WSC_PBC_MODE) || + (pWscControl->WscMode == WSC_SMPBC_MODE)) + pWscControl->WscPinCode = 0; + else + pWscControl->WscPinCode = PinCode; + + memset(pWscControl->RegData.PIN, 0, 8); + + if (pWscControl->WscPinCode == 0) + { + snprintf((PSTRING) tempPIN, sizeof(tempPIN), "00000000"); + memcpy(pWscControl->RegData.PIN, tempPIN, 8); + pWscControl->RegData.PinCodeLen = 8; + } + else + { + if ( pWscControl->WscPinCodeLen == 4) + { + UCHAR temp4PIN[5] = {0}; + snprintf((PSTRING) temp4PIN, sizeof(temp4PIN), "%04u", pWscControl->WscPinCode); + memcpy(pWscControl->RegData.PIN, temp4PIN, 4); + pWscControl->RegData.PinCodeLen = 4; + } + else + { + snprintf((PSTRING) tempPIN, sizeof(tempPIN), "%08u", pWscControl->WscPinCode); + memcpy(pWscControl->RegData.PIN, tempPIN, 8); + pWscControl->RegData.PinCodeLen = 8; + } + } + hex_dump("WscGetRegDataPIN - PIN", pWscControl->RegData.PIN, 8); +} + +VOID WscEapActionDisabled( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl) +{ + INT DataLen = 0; + UCHAR *WscData = NULL; + /*BOOLEAN Cancelled;*/ + + os_alloc_mem(NULL, &WscData, 256); + + if (WscData == NULL) + return; + + DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + { + if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI) + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + else + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + { + if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode & WSC_REGISTRAR)) + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, STA_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + + if (WscData) + os_free_mem(NULL, WscData); + + /* RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); */ + /* pWscControl->EapolTimerRunning = FALSE; */ +} + + +VOID WscGetConfigErrFromNack( + IN RTMP_ADAPTER *pAdapter, + IN MLME_QUEUE_ELEM *pElem, + OUT USHORT *pConfigError) +{ + USHORT Length = 0; + PUCHAR pData; + USHORT WscType, WscLen, ConfigError = 0; + + pData = pElem->Msg; + Length = pElem->MsgLen; + + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + if (WscType == WSC_ID_CONFIG_ERROR) + { + NdisMoveMemory(&ConfigError, pData, sizeof(USHORT)); + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_CONFIG_ERROR: %d\n", ntohs(ConfigError))); + *pConfigError = ntohs(ConfigError); + return; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_CONFIG_ERROR is missing\n")); +} + +INT WscSetAuthMode( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN PSTRING arg) +{ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + UINT32 i; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if (rtstrcasecmp(arg, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(arg, "OPEN") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOpen; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (rtstrcasecmp(arg, "WPA") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if (rtstrcasecmp(arg, "WPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + else if (rtstrcasecmp(arg, "WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2; + else if (rtstrcasecmp(arg, "WPA1WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA1WPA2; + else if (rtstrcasecmp(arg, "WPAPSKWPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + else + { + wdev->AuthMode = Ndis802_11AuthModeOpen; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow AuthMode (%s), set AuthMode to OPEN\n", __FUNCTION__, arg)); + } + + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + pAd->ApCfg.MBSSID[apidx].wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + + wdev->DefaultKeyId = 0; + + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(AuthMode=%d)\n", apidx, __FUNCTION__, wdev->AuthMode)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (strcmp(arg, "WEPAUTO") == 0) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (strcmp(arg, "OPEN") == 0) + wdev->AuthMode = Ndis802_11AuthModeOpen; + else if (strcmp(arg, "SHARED") == 0) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (strcmp(arg, "WPAPSK") == 0) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (strcmp(arg, "WPANONE") == 0) + wdev->AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "WPAPSKWPA2PSK") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if (strcmp(arg, "WPA") == 0) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "WPA1WPA2") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ + else + return FALSE; + + if ((pAd->StaCfg.BssType == BSS_ADHOC) && (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + wdev->AuthMode = Ndis802_11AuthModeWPANone; + + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("WscSetAuthMode::(AuthMode=%d)\n", wdev->AuthMode)); + } +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + +INT WscSetEncrypType( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN PSTRING arg) +{ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if (rtstrcasecmp(arg, "NONE") == TRUE) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if (rtstrcasecmp(arg, "WEP") == TRUE) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if (rtstrcasecmp(arg, "TKIP") == TRUE) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if (rtstrcasecmp(arg, "AES") == TRUE) + wdev->WepStatus = Ndis802_11AESEnable; + else if (rtstrcasecmp(arg, "TKIPAES") == TRUE) + wdev->WepStatus = Ndis802_11TKIPAESMix; + else + { + wdev->WepStatus = Ndis802_11WEPDisabled; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow EncrypType (%s), set EncrypType to NONE\n", __FUNCTION__, arg)); + } + + if (wdev->WepStatus >= Ndis802_11TKIPEnable) + wdev->DefaultKeyId = 0; + + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(EncrypType=%d)\n", apidx, __FUNCTION__, wdev->WepStatus)); + + return TRUE; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (strcmp(arg, "NONE") == 0) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if (strcmp(arg, "WEP") == 0) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11WEPEnabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if (strcmp(arg, "TKIP") == 0) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11TKIPEnable; + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + pAd->StaCfg.GroupCipher = Ndis802_11TKIPEnable; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "TKIPAES") == 0)) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11AESEnable; + pAd->StaCfg.PairCipher = Ndis802_11AESEnable; + pAd->StaCfg.GroupCipher = Ndis802_11AESEnable; + } + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("WscSetEncrypType::(EncrypType=%d)\n", wdev->WepStatus)); + } +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + +#ifdef CONFIG_STA_SUPPORT +USHORT WscGetAuthTypeFromStr(PSTRING arg) +{ + if (rtstrcasecmp(arg, "OPEN") == TRUE) + return WSC_AUTHTYPE_OPEN; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + return WSC_AUTHTYPE_SHARED; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + return WSC_AUTHTYPE_WPAPSK; + else if (rtstrcasecmp(arg, "WPA2PSK") == TRUE) + return WSC_AUTHTYPE_WPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if (rtstrcasecmp(arg, "WPA") == TRUE) + return WSC_AUTHTYPE_WPA; + else if (rtstrcasecmp(arg, "WPA2") == TRUE) + return WSC_AUTHTYPE_WPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ + else + return 0; +} + +USHORT WscGetEncrypTypeFromStr(PSTRING arg) +{ + if (rtstrcasecmp(arg, "NONE") == TRUE) + return WSC_ENCRTYPE_NONE; + else if (rtstrcasecmp(arg, "WEP") == TRUE) + return WSC_ENCRTYPE_WEP; + else if (rtstrcasecmp(arg, "TKIP") == TRUE) + return WSC_ENCRTYPE_TKIP; + else if (rtstrcasecmp(arg, "AES") == TRUE) + return WSC_ENCRTYPE_AES; + else + return 0; +} +#endif /* CONFIG_STA_SUPPORT */ + +/* + ======================================================================== + + Routine Description: + Push PBC from HW/SW Buttton + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ + +VOID WscPushPBCAction( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscPushPBCAction\n")); + + /* 0. PBC mode, disregard the SSID information, we have to get the current AP list */ + /* and check the beacon for Push buttoned AP. */ + + /* 1. Cancel old timer to prevent use push continuously */ + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } + if (pWscControl->WscScanTimerRunning) + { + pWscControl->WscScanTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled); + } + if (pWscControl->WscPBCTimerRunning) + { + pWscControl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled); + } + + /* Set WSC state to WSC_STATE_INIT */ + pWscControl->WscState = WSC_STATE_START; + pWscControl->WscStatus = STATUS_WSC_SCAN_AP; + + /* Init Registrar pair structures */ + WscInitRegistrarPair(pAd, pWscControl, BSS0); + + /* For PBC, the PIN is all '0' */ + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + + /* 2. Set 2 min timout routine */ + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->bWscTrigger = TRUE; /* start work */ + + + /* 3. Call WscScan subroutine */ + WscScanExec(pAd, pWscControl); + + /* 4. Set 10 second timer to invoke PBC connection actions. */ + RTMPSetTimer(&pWscControl->WscPBCTimer, 10000); + pWscControl->WscPBCTimerRunning = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscPushPBCAction\n")); +} + +/* + ======================================================================== + + Routine Description: + Doing an active scan with empty SSID, the scanened list will + be processed in PBCexec or PINexec routines + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID WscScanExec( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ + + /* Prevent infinite loop if conncet time out didn't stop the repeat scan */ + if ((pWscControl->WscStatus == STATUS_WSC_FAIL) || + (pWscControl->WscState == WSC_STATE_OFF)) + return; + + DBGPRINT(RT_DEBUG_OFF, ("!!! WscScanExec !!!\n")); + + pWscControl->WscStatus = STATUS_WSC_SCAN_AP; + +#ifdef WSC_LED_SUPPORT + /* The protocol is connecting to a partner. */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + +#ifdef APCLI_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE); + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.bNotFirstScan = TRUE; + StaSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE); + } +#endif /* CONFIG_STA_SUPPORT */ + +} + +/* + ======================================================================== + + Routine Description: + Doing PBC conenction verification, it will check current BSS list + and find the correct number of PBC AP. If only 1 exists, it will + start to make connection. Otherwise, it will set a scan timer + to perform another scan for next PBC connection execution. + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN WscPBCExec( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromM2, + IN PWSC_CTRL pWscControl) +{ +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ + UCHAR CurOpMode = AP_MODE; + + if (pWscControl == NULL) + return FALSE; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pWscControl->EntryIfIdx == BSS0) + CurOpMode = STA_MODE; + } +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_OFF, ("-----> WscPBCExec !!!\n")); + + /* 1. Search the qualified SSID from current SSID list */ + WscPBCBssTableSort(pAd, pWscControl); + + /* 2. Check the qualified AP for connection, if more than 1 AP avaliable, report error. */ + if (pWscControl->WscPBCBssCount != 1) + { + /* Set WSC state to WSC_FAIL */ + pWscControl->WscState = WSC_STATE_FAIL; + if (pWscControl->WscPBCBssCount== 0) + { + pWscControl->WscStatus = STATUS_WSC_PBC_NO_AP; +#ifdef WSC_LED_SUPPORT + /* Failed to find any partner. */ + WPSLEDStatus = LED_WPS_ERROR; + RTMPSetLED(pAd, WPSLEDStatus); +#ifdef CONFIG_WIFI_LED_SUPPORT + if (LED_MODE(pAd) == WPS_LED_MODE_SHARE) + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_WIFI_LED_TIMEOUT); +#endif /* CONFIG_WIFI_LED_SUPPORT */ + +#endif /* WSC_LED_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("WscPBCExec --> AP list is %d, wait for next time\n", + pWscControl->WscPBCBssCount)); + +#ifdef CONFIG_STA_SUPPORT + /* + P2P PBC CLI doesn't need to check PBC overlapping, + so we don't need to consider P2P case here. + */ + if (pAd->StaCfg.BssType == BSS_INFRA) +#endif /* CONFIG_STA_SUPPORT */ + { + /* 2.1. Set 1 second timer to invoke another scan */ + RTMPSetTimer(&pWscControl->WscScanTimer, 1000); + pWscControl->WscScanTimerRunning = TRUE; + } + } + else + { + pWscControl->WscStatus = STATUS_WSC_PBC_TOO_MANY_AP; + RTMPSendWirelessEvent(pAd, IW_WSC_PBC_SESSION_OVERLAP, NULL, BSS0, 0); + +#ifdef WSC_LED_SUPPORT + if (LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */ + { + /* In case of the WPS LED mode 9, the UI would abort the connection attempt by making the RT_OID_802_11_WSC_SET_WPS_STATE_MACHINE_TERMINATION request. */ + DBGPRINT(RT_DEBUG_TRACE, ("%s: Skip the WPS session overlap detected LED indication.\n", __FUNCTION__)); + } + else /* Other LED mode. */ + { + /* Session overlap detected. */ + WPSLEDStatus = LED_WPS_SESSION_OVERLAP_DETECTED; + RTMPSetLED(pAd, WPSLEDStatus); + + + } +#endif /* WSC_LED_SUPPORT */ + + /* + 20101210 - According to the response from WFA: + The station shall not continue scanning waiting for only one registrar to appear + */ + DBGPRINT(RT_DEBUG_TRACE, ("WscPBCExec --> AP list is %d, stop WPS process!\n", + pWscControl->WscPBCBssCount)); + + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + TRUE, +#endif /* CONFIG_AP_SUPPORT */ + pWscControl); + pWscControl->WscConfMode = WSC_DISABLE; + RTMPZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; + RTMPMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + } + + /* 2.2 We have to quit for now */ + return FALSE; + } + + if (bFromM2) + return TRUE; + + + /* 3. Now we got the intend AP, Set the WSC state and enqueue the SSID connection command */ + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; +#ifdef CONFIG_STA_SUPPORT + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_OFF, ("!!! WscPBCExec --> MLME busy, reset MLME state machine !!!\n")); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + /* 4. Set WSC state to WSC_STATE_START */ + if (CurOpMode == STA_MODE) + { + pWscControl->WscState = WSC_STATE_START; + pWscControl->WscStatus = STATUS_WSC_START_ASSOC; + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_LED_SUPPORT + /* The protocol is connecting to a partner. */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + STRING ChStr[5] = {0}; + + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[BSS0].wdev.if_addr, + MAC_ADDR_LEN); + + // TODO: shiang-usw, check about this Channel setting here? Original it indicate to pAd->MlmeAux.Channel! + snprintf(ChStr, sizeof(ChStr), "%d", pAd->ApCfg.ApCliTab[BSS0].MlmeAux.Channel); + Set_Channel_Proc(pAd, ChStr); + + /* bring apcli interface down first */ + if(pAd->ApCfg.ApCliTab[BSS0].Enable == TRUE) + { + pAd->ApCfg.ApCliTab[BSS0].Enable = FALSE; + ApCliIfDown(pAd); + } + pAd->ApCfg.ApCliTab[BSS0].Enable = TRUE; + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + /* Enqueue BSSID connection command */ + if (CurOpMode == STA_MODE) + { + if (pAd->StaCfg.BssType == BSS_INFRA) + { + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)&pWscControl->WscBssid[0], 0); + } + else + { + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)&pAd->StaCfg.WscControl.WscSsid, 0); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("<----- WscPBCExec !!!\n")); + return TRUE; +} + +BOOLEAN WscBssWpsIESearchForPBC( + RTMP_ADAPTER *pAd, + WSC_CTRL *pWscControl, + BSS_ENTRY *pInBss, + UUID_BSSID_CH_INFO ApUuidBssid[], + INT VarIeLen, + PUCHAR pVar) +{ + INT j = 0, Len = 0, idx = 0; + BOOLEAN bFound, bSameAP, bSelReg; + PUCHAR pData = NULL; + PBEACON_EID_STRUCT pEid; + USHORT DevicePasswordID; + PWSC_IE pWscIE; + UUID_BSSID_CH_INFO TmpInfo; + UCHAR zeros16[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +#ifdef IWSC_SUPPORT + UINT8 RspType = 0; + BOOLEAN bEntryAcceptable = FALSE; +#endif // IWSC_SUPPORT // + + pData = pVar; + bFound = FALSE; + bSameAP = FALSE; + bSelReg = FALSE; + Len = VarIeLen; + NdisZeroMemory(&TmpInfo, sizeof(UUID_BSSID_CH_INFO)); + while ((Len > 0) && (bFound == FALSE)) + { + pEid = (PBEACON_EID_STRUCT) pData; + + /* No match, skip the Eid and move forward, IE_WFA_WSC = 0xdd */ + if (pEid->Eid != IE_WFA_WSC) + { + /* Set the offset and look for next IE */ + pData += (pEid->Len + 2); + Len -= (pEid->Len + 2); + continue; + } + else + { + /* Found IE with 0xdd */ + /* check for WSC OUI -- 00 50 f2 04 */ + if ((NdisEqualMemory(pEid->Octet, WPS_OUI, 4) == FALSE) +#ifdef IWSC_SUPPORT + && (NdisEqualMemory(pEid->Octet, IWSC_OUI, 4) == FALSE) +#endif // IWSC_SUPPORT // + ) + { + /* Set the offset and look for next IE */ + pData += (pEid->Len + 2); + Len -= (pEid->Len + 2); + continue; + } + } + + /* 3. Found AP with WSC IE in beacons, skip 6 bytes = 1 + 1 + 4 */ + pData += 6; + Len -= 6; + + /* 4. Start to look the PBC type within WSC VarIE */ + while (Len > 0) + { + /* Check for WSC IEs */ + pWscIE = (PWSC_IE) pData; + + if (be2cpu16(pWscIE->Type) == WSC_ID_SEL_REGISTRAR) + { + hex_dump("SelReg:", pData, 5); + bSelReg = pWscIE->Data[0]; + DBGPRINT(RT_DEBUG_TRACE, ("bSelReg = %d\n", bSelReg)); + } + +#ifdef IWSC_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.BssType == BSS_ADHOC)) + { + if (be2cpu16(pWscIE->Type) == WSC_ID_RESP_TYPE) + { + RspType = pWscIE->Data[0]; + if (RspType < WSC_MSGTYPE_REGISTRAR) + { + bFound = FALSE; + break; + } + TmpInfo.RspType = RspType; + } + if (be2cpu16(pWscIE->Type) == WSC_ID_MAC_ADDR) + { + UCHAR mac_addr[MAC_ADDR_LEN]; + RTMPMoveMemory(mac_addr, (pData+4), MAC_ADDR_LEN); + if (NdisCmpMemory(pInBss->MacAddr, mac_addr, MAC_ADDR_LEN)) + { + bFound = FALSE; + break; + } + } + if (be2cpu16(pWscIE->Type) == WSC_ID_ENTRY_ACCEPTABLE) + { + hex_dump("EntryAcceptable:", pData, 5); + bEntryAcceptable = pWscIE->Data[0]; + DBGPRINT(RT_DEBUG_TRACE, ("bEntryAcceptable = %d\n", bEntryAcceptable)); + } + } +#endif /* IWSC_SUPPORT */ + + /* Check for device password ID, PBC = 0x0004, SMPBC = 0x0006 */ + if (be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID) + { + /* Found device password ID */ +#ifdef WINBOND + /*The Winbond's platform will fail to retrive 2-bytes data, if use the original */ + /*be2cpu16<-- */ + DevicePasswordID = WINBON_GET16((PUCHAR)&pWscIE->Data[0]); +#else + DevicePasswordID = be2cpu16(get_unaligned((USHORT *)&pWscIE->Data[0])); + /*DevicePasswordID = be2cpu16(*((USHORT *) &pWscIE->Data[0])); */ +#endif /* WINBOND */ + DBGPRINT(RT_DEBUG_TRACE, ("WscPBCBssTableSort : DevicePasswordID = 0x%04x\n", DevicePasswordID)); + if (((pWscControl->WscMode == WSC_PBC_MODE) && (DevicePasswordID == DEV_PASS_ID_PBC)) || + ((pWscControl->WscMode == WSC_SMPBC_MODE) && (DevicePasswordID == DEV_PASS_ID_SMPBC))) + { + /* Found matching PBC AP in current list, add it into table and add the count */ + bFound = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("DPID=PBC Found --> \n")); + DBGPRINT(RT_DEBUG_TRACE, ("# Bssid %02x:%02x:%02x:%02x:%02x:%02x\n", + pInBss->Bssid[0], pInBss->Bssid[1], pInBss->Bssid[2], pInBss->Bssid[3], pInBss->Bssid[4], pInBss->Bssid[5])); + + if (pInBss->Channel > 14) + TmpInfo.Band = WSC_RFBAND_50GHZ; + else + TmpInfo.Band = WSC_RFBAND_24GHZ; + + RTMPMoveMemory(&TmpInfo.Bssid[0], &pInBss->Bssid[0], MAC_ADDR_LEN); + TmpInfo.Channel = pInBss->Channel; + RTMPZeroMemory(&TmpInfo.Ssid[0], MAX_LEN_OF_SSID); + RTMPMoveMemory(&TmpInfo.Ssid[0], &pInBss->Ssid[0], pInBss->SsidLen); + TmpInfo.SsidLen = pInBss->SsidLen; + } + } + + /* UUID_E is optional for beacons, but mandatory for probe-request */ + if (be2cpu16(pWscIE->Type) == WSC_ID_UUID_E) + { + /* Avoid error UUID-E storage from PIN mode */ + RTMPMoveMemory(&TmpInfo.Uuid[0], (UCHAR *)(pData+4), 16); + } + + /* Set the offset and look for PBC information */ + /* Since Type and Length are both short type, we need to offset 4, not 2 */ + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } + +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pWscControl->WscMode == WSC_SMPBC_MODE) && + (bEntryAcceptable == FALSE) && bFound) + { + bFound = FALSE; + } +#endif /* IWSC_SUPPORT */ + + if ((bFound == TRUE) && (bSelReg == TRUE)) + { + if (pWscControl->WscPBCBssCount == 8) + { + break; + } + + if (pWscControl->WscPBCBssCount > 0) + { + for (j = 0; j < pWscControl->WscPBCBssCount; j++) + { + if (RTMPCompareMemory(&ApUuidBssid[j].Uuid[0], &TmpInfo.Uuid[0], 16) == 0) + { + if (RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) != 0) + { + /* + Same UUID, indicate concurrent AP + We can indicate 1 AP only. + */ + bSameAP = TRUE; + break; + } + else if (RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) == 0) + { + if (ApUuidBssid[j].Band != TmpInfo.Band) + { + if (RTMPCompareMemory(&ApUuidBssid[j].Bssid[0], &TmpInfo.Bssid[0], 5) == 0) + { + /* + Zero UUID at different band, and first 5bytes of two BSSIDs are the same. + Indicate concurrent AP, we can indicate 1 AP only. + */ + bSameAP = TRUE; + break; + } + } + } + } + else if ((RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) == 0) || + (RTMPCompareMemory(&ApUuidBssid[j].Uuid[0], zeros16, 16) == 0)) + { + if ((RTMPCompareMemory(&ApUuidBssid[j].Bssid[0], &TmpInfo.Bssid[0], 5) == 0) && + (ApUuidBssid[j].Band != TmpInfo.Band)) + { + INT tmpDiff = (INT)(ApUuidBssid[j].Bssid[5] - TmpInfo.Bssid[5]); + /* + Zero UUID and Non-zero UUID at different band, and two BSSIDs are very close. + Indicate concurrent AP, we can indicate 1 AP only. + */ + if ((tmpDiff <= 4) || + (tmpDiff >= -4)) + { + bSameAP = TRUE; + break; + } + } + } + } + } + + if (bSameAP) + { + if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST) && + (TmpInfo.Band == WSC_RFBAND_24GHZ) && + (ApUuidBssid[j].Band != TmpInfo.Band)) + { + RTMPMoveMemory(&(ApUuidBssid[j].Bssid[0]), &TmpInfo.Bssid[0], MAC_ADDR_LEN); + RTMPZeroMemory(&(ApUuidBssid[j].Ssid[0]), MAX_LEN_OF_SSID); + RTMPMoveMemory(&(ApUuidBssid[j].Ssid[0]), &TmpInfo.Ssid[0], TmpInfo.SsidLen); + ApUuidBssid[j].SsidLen = TmpInfo.SsidLen; + ApUuidBssid[j].Channel = TmpInfo.Channel; + } + else if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST) && + (TmpInfo.Band == WSC_RFBAND_50GHZ) && + (ApUuidBssid[j].Band != TmpInfo.Band)) + { + RTMPMoveMemory(&(ApUuidBssid[j].Bssid[0]), &TmpInfo.Bssid[0], MAC_ADDR_LEN); + RTMPZeroMemory(&(ApUuidBssid[j].Ssid[0]), MAX_LEN_OF_SSID); + RTMPMoveMemory(&(ApUuidBssid[j].Ssid[0]), &TmpInfo.Ssid[0], TmpInfo.SsidLen); + ApUuidBssid[j].SsidLen = TmpInfo.SsidLen; + ApUuidBssid[j].Channel = TmpInfo.Channel; + } + } + + if (bSameAP == FALSE) + { + UCHAR index = pWscControl->WscPBCBssCount; + + /* Store UUID */ + RTMPMoveMemory(&(ApUuidBssid[index].Uuid[0]), &TmpInfo.Uuid[0], 16); + RTMPMoveMemory(&(ApUuidBssid[index].Bssid[0]), &pInBss->Bssid[0], MAC_ADDR_LEN); + RTMPZeroMemory(&(ApUuidBssid[index].Ssid[0]), MAX_LEN_OF_SSID); + RTMPMoveMemory(&(ApUuidBssid[index].Ssid[0]), &pInBss->Ssid[0], pInBss->SsidLen); + ApUuidBssid[index].SsidLen = pInBss->SsidLen; + ApUuidBssid[index].Channel = pInBss->Channel; + if (ApUuidBssid[index].Channel > 14) + ApUuidBssid[index].Band = WSC_RFBAND_50GHZ; + else + ApUuidBssid[index].Band = WSC_RFBAND_24GHZ; + DBGPRINT(RT_DEBUG_ERROR, ("UUID-E= ")); + for(idx=0; idx<16; idx++) + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%02x ", ApUuidBssid[index].Uuid[idx])); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + pWscControl->WscPBCBssCount++; + } + } + } + + return (bFound && bSelReg); +} + +/* + ======================================================================== + + Routine Description: + Find WSC PBC activated AP list + + Arguments: + pAd - NIC Adapter pointer + OutTab - Qualified AP BSS table + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + All these constants are defined in wsc.h + + ======================================================================== +*/ +VOID WscPBCBssTableSort( + IN RTMP_ADAPTER *pAd, + IN WSC_CTRL *pWscControl) +{ + INT i; + BSS_ENTRY *pInBss; + UUID_BSSID_CH_INFO *ApUuidBssid = NULL; + BOOLEAN rv = FALSE; + UCHAR CurOpMode = AP_MODE; + BOOLEAN bNeedWpsIESearch = TRUE; +#ifdef SMART_MESH + BOOLEAN bWscPBCAPFound = FALSE; +#endif /* SMART_MESH */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pWscControl->EntryIfIdx == BSS0) + CurOpMode = STA_MODE; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef APCLI_SUPPORT +if (CurOpMode == AP_MODE) + { + pWscControl = &pAd->ApCfg.ApCliTab[BSS0].WscControl; +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.ApCliTab[BSS0].SmartMeshCfg.bSupportHiddenWPS) + bNeedWpsIESearch = FALSE; +#endif /* SMART_MESH_HIDDEN_WPS */ + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +if (CurOpMode == STA_MODE) + pWscControl = &pAd->StaCfg.WscControl; +#endif /* CONFIG_STA_SUPPORT */ + + if (pWscControl == NULL) + return; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ApUuidBssid, sizeof(UUID_BSSID_CH_INFO)*8); + if (ApUuidBssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(&ApUuidBssid[0], sizeof(UUID_BSSID_CH_INFO)*8); + pWscControl->WscPBCBssCount = 0; + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + /* BSS entry for VarIE processing */ + pInBss = (BSS_ENTRY *) &pAd->ScanTab.BssEntry[i]; + +#ifdef SMART_MESH + bWscPBCAPFound = FALSE; + if((pWscControl->WscMode == 2) && + (pWscControl->bWscPBCAddrMode == TRUE)) + { + if(pWscControl->WscPBCBssCount == 1) + break; + + if(MAC_ADDR_EQUAL(pWscControl->WscPBCAddr,pInBss->Bssid)) + bWscPBCAPFound = TRUE; + + if(!bWscPBCAPFound) + continue; + } +#endif /* SMART_MESH */ + + if(bNeedWpsIESearch) + { + /* 1. Check VarIE length */ + if (pInBss->VarIELen == 0) + continue; + +#ifdef CONFIG_STA_SUPPORT + if ((CurOpMode == STA_MODE) && (pInBss->BssType != pAd->StaCfg.BssType)) + continue; +#endif /* CONFIG_STA_SUPPORT */ + + /* 2. Search for WSC IE - 0xdd xx 00 50 f2 04 */ + rv = WscBssWpsIESearchForPBC(pAd, + pWscControl, + pInBss, + ApUuidBssid, + pInBss->VarIELen, + pInBss->VarIEs); + if (rv == FALSE) + { + WscBssWpsIESearchForPBC(pAd, + pWscControl, + pInBss, + ApUuidBssid, + pInBss->VarIeFromProbeRspLen, + pInBss->pVarIeFromProbRsp); + } + } + else + { +#ifdef SMART_MESH_HIDDEN_WPS + if(pInBss->bRunningHiddenWPS) + { + RTMPMoveMemory(ApUuidBssid[0].Bssid, pInBss->Bssid, MAC_ADDR_LEN); + RTMPMoveMemory(ApUuidBssid[0].Ssid, pInBss->Ssid, pInBss->SsidLen); + ApUuidBssid[0].SsidLen = pInBss->SsidLen; + ApUuidBssid[0].Channel = pInBss->Channel; + + if((pWscControl->WscConfMode & WSC_ENROLLEE) && pInBss->bHiddenWPSRegistrar) + pWscControl->WscPBCBssCount++; + else if((pWscControl->WscConfMode & WSC_REGISTRAR) && !pInBss->bHiddenWPSRegistrar) + pWscControl->WscPBCBssCount++; + } +#endif /* SMART_MESH_HIDDEN_WPS */ + } + } + + if (pWscControl->WscPBCBssCount == 1) + { + RTMPZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + RTMPMoveMemory(pWscControl->WscSsid.Ssid, ApUuidBssid[0].Ssid, ApUuidBssid[0].SsidLen); + pWscControl->WscSsid.SsidLength = ApUuidBssid[0].SsidLen; + RTMPZeroMemory(pWscControl->WscBssid, MAC_ADDR_LEN); + RTMPMoveMemory(pWscControl->WscBssid, ApUuidBssid[0].Bssid, MAC_ADDR_LEN); +#ifdef CONFIG_STA_SUPPORT + RTMPZeroMemory(pWscControl->WscPeerMAC, MAC_ADDR_LEN); + RTMPMoveMemory(pWscControl->WscPeerMAC, ApUuidBssid[0].MacAddr, MAC_ADDR_LEN); + pAd->MlmeAux.Channel = ApUuidBssid[0].Channel; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + pAd->ApCfg.ApCliTab[BSS0].MlmeAux.Channel = ApUuidBssid[0].Channel; + } +#endif /* APCLI_SUPPORT */ + } + + if (ApUuidBssid != NULL) + os_free_mem(NULL, ApUuidBssid); + +#ifdef IWSC_SUPPORT + if (pWscControl->WscMode == WSC_SMPBC_MODE) + DBGPRINT(RT_DEBUG_OFF, ("WscPBCBssTableSort : Total %d SMPBC Registrar Found\n", pWscControl->WscPBCBssCount)); + else +#endif /* IWSC_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("WscPBCBssTableSort : Total %d PBC Registrar Found\n", pWscControl->WscPBCBssCount)); +} + +VOID WscGenRandomKey( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + INOUT PUCHAR pKey, + INOUT PUSHORT pKeyLen) +{ + UCHAR tempRandomByte = 0; + UCHAR idx = 0; + UCHAR keylen = 0; + UCHAR retry = 0; + + NdisZeroMemory(pKey, 64); + + /* + Hex Key 64 digital + */ + if(pWscControl->WscKeyASCII == 0) + { + UCHAR tmpStrB[3]; + for (idx = 0; idx < 32; idx++) + { + NdisZeroMemory(&tmpStrB[0], sizeof(tmpStrB)); + tempRandomByte = RandomByte(pAd); + snprintf((PSTRING) &tmpStrB[0], 3, "%02x", tempRandomByte); + NdisMoveMemory(pKey+(idx*2), &tmpStrB[0], 2); + } + *pKeyLen = 64; + } + else + { + /* + ASCII Key, random length + */ + if(pWscControl->WscKeyASCII == 1) + { + do{ + keylen = RandomByte(pAd); + keylen = keylen % 64; + if(retry++ > 20) + keylen = 8; + }while(keylen < 8); + } + else + keylen = pWscControl->WscKeyASCII; + + /* + Generate printable ASCII (decimal 33 to 126) + */ + for(idx = 0; idx < keylen; idx++) + { + tempRandomByte = RandomByte(pAd)%94+33; + *(pKey+idx) = tempRandomByte; + } + *pKeyLen = keylen; + } +} + +VOID WscCreateProfileFromCfg( + IN PRTMP_ADAPTER pAd, + IN UCHAR OpMode, + IN PWSC_CTRL pWscControl, + OUT PWSC_PROFILE pWscProfile) +{ + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); + USHORT authType = 0, encyType = 0; + UCHAR WepKeyId = 0; + PWSC_CREDENTIAL pCredential = NULL; + UCHAR CurOpMode = AP_MODE; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pWscControl->EntryIfIdx == BSS0) + CurOpMode = STA_MODE; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((OpMode & 0x0F) == AP_MODE) + { + /* + AP needs to choose the STA's authType and encyType in two cases. + 1. AP is unconfigurated (authType and encyType will be updated to mixed mode by WscWriteConfToPortCfg() ) + 2. AP's authType is mixed mode, we should choose the suitable authType and encyType to STA + STA's authType and encyType depend on WscSecurityMode flag + */ + + if (((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED ) || + (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) && + (OpMode & REGISTRAR_ACTION)) + { + switch (pAd->ApCfg.MBSSID[apidx].WscSecurityMode) + { + case WPAPSKTKIP: + authType = WSC_AUTHTYPE_WPAPSK; + encyType = WSC_ENCRTYPE_TKIP; + break; + case WPAPSKAES: + authType = WSC_AUTHTYPE_WPAPSK; + encyType = WSC_ENCRTYPE_AES; + break; + case WPA2PSKTKIP: + authType = WSC_AUTHTYPE_WPA2PSK; + encyType = WSC_ENCRTYPE_TKIP; + break; + case WPA2PSKAES: + authType = WSC_AUTHTYPE_WPA2PSK; + encyType = WSC_ENCRTYPE_AES; + break; + case WPAPSKWPA2PSKTKIPAES: + default: + authType = (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK); + encyType = (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES); + break; + } + + if (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) + { + /* + Although AuthMode is mixed mode, cipher maybe not mixed mode. + We need to correct cipher here. + */ + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11TKIPEnable) + encyType = WSC_ENCRTYPE_TKIP; + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11AESEnable) + encyType = WSC_ENCRTYPE_AES; + } + } + else + { + authType = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].wdev.AuthMode); + encyType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].wdev.WepStatus); + } + WepKeyId = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId; + } +#ifdef APCLI_SUPPORT + else if ((OpMode & 0x0F) == AP_CLIENT_MODE) + { + apidx = apidx & 0x0F; + authType = WscGetAuthType(pAd->ApCfg.ApCliTab[apidx].wdev.AuthMode); + encyType = WscGetEncryType(pAd->ApCfg.ApCliTab[apidx].wdev.WepStatus); + WepKeyId = pAd->ApCfg.ApCliTab[apidx].wdev.DefaultKeyId; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + authType = WscGetAuthType(pAd->StaCfg.wdev.AuthMode); + encyType = WscGetEncryType(pAd->StaCfg.wdev.WepStatus); + WepKeyId = pAd->StaCfg.wdev.DefaultKeyId; + } +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscGetDefaultProfileForM8\n")); + + pCredential = &pWscProfile->Profile[0]; /*Only support one credential now. 20070515 */ + NdisZeroMemory(pCredential, sizeof(WSC_CREDENTIAL)); + pWscProfile->ProfileCnt = 1; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: pWscControl->WscConfStatus = %d, OpMode = %d\n", + __FUNCTION__, pWscControl->WscConfStatus, OpMode)); + + /* NewKey, NewKeyIndex for M8 */ + if ((WSC_SCSTATE_UNCONFIGURED == pWscControl->WscConfStatus) && + ((((OpMode & 0x0F) == AP_MODE) +#ifdef CONFIG_STA_SUPPORT + || (((OpMode & 0x0F) == STA_MODE) && (pAd->StaCfg.BssType == BSS_ADHOC)) +#endif /* CONFIG_STA_SUPPORT */ + ) && (OpMode & REGISTRAR_ACTION))) + { + pCredential->KeyIndex = 1; + if ((OpMode & 0x0F) == STA_MODE) + { +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.IWscInfo.IWscDefaultSecurity == 1) + { + authType = WSC_AUTHTYPE_OPEN; + encyType = WSC_ENCRTYPE_NONE; + pCredential->KeyLength = 0; + NdisZeroMemory(pCredential->Key, 64); + } + else if (pAd->StaCfg.IWscInfo.IWscDefaultSecurity == 2) + { + UCHAR idx; + CHAR tempRandomByte; + authType = WSC_AUTHTYPE_OPEN; + encyType = WSC_ENCRTYPE_WEP; + for(idx = 0; idx < 13; idx++) + { + tempRandomByte = RandomByte(pAd)%94+33; + sprintf((PSTRING) pCredential->Key+idx, "%c", tempRandomByte); + } + pCredential->KeyLength = 13; + } + else +#endif // IWSC_TEST_SUPPORT // + { + WscGenRandomKey(pAd, pWscControl, pCredential->Key, &pCredential->KeyLength); + authType = WSC_AUTHTYPE_WPA2PSK; + encyType = WSC_ENCRTYPE_AES; + } + } + else + WscGenRandomKey(pAd, pWscControl, pCredential->Key, &pCredential->KeyLength); + } + else + { + pCredential->KeyIndex = 1; + pCredential->KeyLength = 0; + NdisZeroMemory(pCredential->Key, 64); + switch (encyType) + { + case WSC_ENCRTYPE_NONE: + break; + case WSC_ENCRTYPE_WEP: + pCredential->KeyIndex = (WepKeyId + 1); + if (((OpMode & 0x0F) == AP_MODE || (OpMode & 0x0F) == STA_MODE) && pAd->SharedKey[apidx][WepKeyId].KeyLen) + { + INT i; + for (i=0; iSharedKey[apidx][WepKeyId].KeyLen; i++) + { + snprintf((PSTRING) pCredential->Key, 64, "%s%02x", pCredential->Key, pAd->SharedKey[apidx][WepKeyId].Key[i]); + } + pCredential->KeyLength = pAd->SharedKey[apidx][WepKeyId].KeyLen*2; + } +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + else if (((OpMode & 0x0F) == AP_CLIENT_MODE) && (pAd->ApCfg.ApCliTab[apidx].SharedKey[WepKeyId].KeyLen) && + (CurOpMode == AP_MODE)) + { + INT i; + for (i=0; iApCfg.ApCliTab[apidx].SharedKey[WepKeyId].KeyLen; i++) + { + snprintf((PSTRING) pCredential->Key, 64, "%s%02x", pCredential->Key, pAd->ApCfg.ApCliTab[apidx].SharedKey[WepKeyId].Key[i]); + } + pCredential->KeyLength = pAd->SharedKey[apidx][WepKeyId].KeyLen*2; + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + break; + case WSC_ENCRTYPE_TKIP: + case WSC_ENCRTYPE_AES: + case (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP): + pCredential->KeyLength = pWscControl->WpaPskLen; + memcpy(pCredential->Key, pWscControl->WpaPsk, pWscControl->WpaPskLen); + break; + } + } + + pCredential->AuthType = authType; + pCredential->EncrType = encyType; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((OpMode & 0x0F) == AP_MODE) + { + NdisMoveMemory(pCredential->MacAddr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, 6); + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) && + (pWscControl->WscDefaultSsid.SsidLength > 0) && + (pWscControl->WscDefaultSsid.SsidLength < 33)) + { + NdisMoveMemory(pCredential->SSID.Ssid, pWscControl->WscDefaultSsid.Ssid, pWscControl->WscDefaultSsid.SsidLength); + pCredential->SSID.SsidLength = pWscControl->WscDefaultSsid.SsidLength; + } + else + { + NdisMoveMemory(pCredential->SSID.Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen); + pCredential->SSID.SsidLength = pAd->ApCfg.MBSSID[apidx].SsidLen; + } + } +#ifdef APCLI_SUPPORT + else if ((OpMode & 0x0F) == AP_CLIENT_MODE) + { + NdisMoveMemory(pCredential->MacAddr, APCLI_ROOT_BSSID_GET(pAd, pAd->ApCfg.ApCliTab[apidx].MacTabWCID), 6); + NdisMoveMemory(pCredential->SSID.Ssid, pAd->ApCfg.ApCliTab[apidx].CfgSsid, pAd->ApCfg.ApCliTab[apidx].CfgSsidLen); + pCredential->SSID.SsidLength = pAd->ApCfg.ApCliTab[apidx].CfgSsidLen; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (pAd->StaCfg.BssType == BSS_INFRA) + NdisMoveMemory(pCredential->MacAddr, pAd->CommonCfg.Bssid, 6); + else + NdisMoveMemory(pCredential->MacAddr, pAd->CurrentAddress, 6); + NdisMoveMemory(pCredential->SSID.Ssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + pCredential->SSID.SsidLength = pAd->CommonCfg.SsidLen; + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2 && (OpMode & REGISTRAR_ACTION)) + NdisMoveMemory(pCredential->MacAddr, pWscControl->EntryAddr, 6); +#endif /* WSC_V2_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCreateProfileFromCfg\n")); + +} + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +void WscWriteConfToApCliCfg( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee) +{ + UCHAR CurApIdx = BSS0; + APCLI_STRUCT *pApCliTab; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToApCliCfg\n")); + + CurApIdx = (pWscControl->EntryIfIdx & 0x0F); + { + pApCliTab = &pAd->ApCfg.ApCliTab[CurApIdx]; + + NdisZeroMemory(pApCliTab->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pApCliTab->Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + pApCliTab->SsidLen = pCredential->SSID.SsidLength; + + NdisZeroMemory(pApCliTab->CfgSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pApCliTab->CfgSsid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + pApCliTab->CfgSsidLen = pCredential->SSID.SsidLength; + + DBGPRINT(RT_DEBUG_TRACE, ("SSID: %s AuthType: %d, EncrType: %d\n", pCredential->SSID.Ssid, + pCredential->AuthType, pCredential->EncrType)); + if ((pCredential->AuthType == WSC_AUTHTYPE_WPAPSK) || + (pCredential->AuthType == WSC_AUTHTYPE_WPA2PSK)) + { + if ((pCredential->EncrType != WSC_ENCRTYPE_TKIP) && (pCredential->EncrType != WSC_ENCRTYPE_AES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AuthType is WPAPSK or WPA2PAK.\n" + "Get illegal EncrType(%d) from External Registrar, set EncrType to TKIP\n", + pCredential->EncrType)); + pCredential->EncrType = WSC_ENCRTYPE_TKIP; + } + } + Set_ApCli_AuthMode_Proc(pAd, WscGetAuthTypeStr(pCredential->AuthType)); + Set_ApCli_EncrypType_Proc(pAd, WscGetEncryTypeStr(pCredential->EncrType)); + + if (pCredential->EncrType != WSC_ENCRTYPE_NONE) + { + if (pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + { + pApCliTab->wdev.DefaultKeyId = 0; + + if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64) + { + pWscControl->WpaPskLen = (INT) pCredential->KeyLength; + NdisZeroMemory(pWscControl->WpaPsk, 64); + NdisMoveMemory(pWscControl->WpaPsk, pCredential->Key, pCredential->KeyLength); + RT_CfgSetWPAPSKKey(pAd, (PSTRING) pWscControl->WpaPsk, pWscControl->WpaPskLen, + (PUCHAR)pApCliTab->Ssid, pApCliTab->SsidLen, pApCliTab->PMK); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPskLen = %d\n", pWscControl->WpaPskLen)); + } + else + { + pWscControl->WpaPskLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + } + else if (pCredential->EncrType == WSC_ENCRTYPE_WEP) + { + CHAR WepKeyId = 0; + USHORT WepKeyLen = pCredential->KeyLength; + + WepKeyId = (pCredential->KeyIndex - 1); /* KeyIndex = 1 ~ 4 */ + if ((WepKeyId >= 0) && (WepKeyId <=3)) + { + pApCliTab->wdev.DefaultKeyId = WepKeyId; + + /* 5 or 13 ASCII characters */ + /* 10 or 26 Hex characters */ + if (WepKeyLen == 5 || WepKeyLen == 13 || WepKeyLen == 10 || WepKeyLen == 26) + { + if (WepKeyLen == 5 || WepKeyLen == 13) + { + pApCliTab->SharedKey[WepKeyId].KeyLen = WepKeyLen; + memcpy(pApCliTab->SharedKey[WepKeyId].Key, pCredential->Key,WepKeyLen); + if (WepKeyLen == 5) + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP64; + else + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP128; + } + else + { + pApCliTab->SharedKey[WepKeyId].KeyLen = (UCHAR) WepKeyLen/2; + AtoH((PSTRING) pCredential->Key, pApCliTab->SharedKey[WepKeyId].Key, WepKeyLen/2); + if (WepKeyLen == 10) + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP64; + else + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP128; + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("WEP: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unsupport default key index (%d), use key Index 1.\n", WepKeyId)); + pApCliTab->wdev.DefaultKeyId = WepKeyId = 0; + } + } + } + } + + if (pWscControl->WscProfile.ProfileCnt > 1) + { + pWscControl->WscProfileRetryTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->WscProfileRetryTimer, WSC_PROFILE_RETRY_TIME_OUT); + } + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToApCliCfg\n")); +} + +VOID WscApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); + UCHAR mac_addr[MAC_ADDR_LEN]; + BOOLEAN apcliEn = pAd->ApCfg.ApCliTab[apidx].Enable; + + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, + 6); + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[apidx].Enable = FALSE; + ApCliIfDown(pAd); + } + pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn; + memcpy(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + pWscControl->bWscTrigger = TRUE; +} +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +VOID WpsSmProcess( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + int HeaderLen = LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME); + PHEADER_802_11 pHeader; + PMAC_TABLE_ENTRY pEntry = NULL; + int apidx = MAIN_MBSSID; + PWSC_CTRL pWpsCtrl = NULL; + UCHAR CurOpMode = 0xFF; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + CurOpMode = AP_MODE; + } +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + CurOpMode = STA_MODE; + } +#endif // CONFIG_STA_SUPPORT // + + if (CurOpMode == 0xFF) + { + DBGPRINT(RT_DEBUG_WARN, ("Unkown OpMode (CurOpMode=0x%02x)\n", CurOpMode)); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("CurOpMode=0x%02x\n", CurOpMode)); + + pHeader = (PHEADER_802_11)Elem->Msg; + + if (Elem->MsgType == WSC_EAPOL_PACKET_MSG) + { + if ((pEntry = MacTableLookup(pAd, pHeader->Addr2))) + apidx = pEntry->apidx; + } + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + pWpsCtrl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + else +#endif /* APCLI_SUPPORT */ + pWpsCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* CONFIG_STA_SUPPORT */ + + if((Elem->MsgType == WSC_EAPOL_UPNP_MSG) && (Elem->MsgLen > HeaderLen)) + { /*The WSC msg from UPnP daemon */ + PUCHAR pData; + UCHAR MacAddr[MAC_ADDR_LEN]= {0}; + + /* Skip the (802.11 + 802.1h + 802.1x + EAP) header */ + pData = (PUCHAR) &Elem->Msg[HeaderLen]; + Elem->MsgLen -= HeaderLen; + /* The Addr1 of UPnP-Msg used to indicate the MAC address of the AP interface. Now always be ra0. */ + NdisMoveMemory(MacAddr, pHeader->Addr1, MAC_ADDR_LEN); + NdisMoveMemory(Elem->Msg, MacAddr, MAC_ADDR_LEN); + NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen); + + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + } + else if (Elem->MsgType == WSC_EAPOL_START_MSG) + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + else if (pEntry && (Elem->MsgType == WSC_EAPOL_PACKET_MSG)) + { /* WSC_STATE_MACHINE can service only one station at one time */ + PSTRING pData; + PEAP_FRAME pEapFrame; + /* Skip the EAP LLC header */ + pData = (PSTRING) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + pEapFrame = (PEAP_FRAME)(pData + sizeof(IEEE8021X_FRAME)); + pData += sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: EAPOL Packet. Code = %d. Type = %d\n", + __FUNCTION__, pEapFrame->Code, pEapFrame->Type)); + if (pEapFrame->Code == EAP_CODE_FAIL) + { /* EAP-Fail */ + STRING fail_data[] = "EAP_FAIL"; + NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN); + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, fail_data, strlen(fail_data)); + Elem->MsgLen = strlen(fail_data); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + return; + } + else if ((pEapFrame->Code == EAP_CODE_REQ) && (pEapFrame->Type == EAP_TYPE_ID)) + { /* EAP-Req (Identity) */ + STRING id_data[] = "hello"; + + pWpsCtrl->lastId = pEapFrame->Id; + NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN); + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, id_data, strlen(id_data)); + Elem->MsgLen = strlen(id_data); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + return; + } + else if ((pEapFrame->Code == EAP_CODE_REQ) && (pEapFrame->Type == EAP_TYPE_WSC)) + { /* EAP-Req (Messages) */ + if (Elem->MsgLen <= HeaderLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("Elem->MsgLen(%ld) <= HeaderLen(%d) !!\n", Elem->MsgLen, HeaderLen)); + return; + } + + pWpsCtrl->lastId = pEapFrame->Id; + Elem->MsgLen -= (LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME)); + if (WscCheckWSCHeader((PUCHAR)pData)) + { + PWSC_FRAME pWsc = (PWSC_FRAME) pData; + + NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN); + if (pWsc->OpCode == WSC_OPCODE_FRAG_ACK) + { + /* + Send rest WSC frag data + */ + STRING wsc_frag_ack[] = "WSC_FRAG_ACK"; + + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_frag_ack, strlen(wsc_frag_ack)); + Elem->MsgLen = strlen(wsc_frag_ack); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + } + else if (pWsc->OpCode == WSC_OPCODE_START) + { + STRING wsc_start[] = "WSC_START"; + + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_start, strlen(wsc_start)); + Elem->MsgLen = strlen(wsc_start); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + } + else + { + if (pWsc->Flags & WSC_MSG_FLAG_LF) + { + pData += (sizeof(WSC_FRAME) + 2); + Elem->MsgLen -= (sizeof(WSC_FRAME) + 2); + } + else + { + pData += sizeof(WSC_FRAME); + Elem->MsgLen -= sizeof(WSC_FRAME); + } + + if ((pWpsCtrl->WscRxBufLen + Elem->MsgLen) < (MGMT_DMA_BUFFER_SIZE-6)) + { + NdisMoveMemory((pWpsCtrl->pWscRxBuf + pWpsCtrl->WscRxBufLen), pData, Elem->MsgLen); + pWpsCtrl->WscRxBufLen += Elem->MsgLen; + } +#ifdef WSC_V2_SUPPORT + if (pWsc->Flags & WSC_MSG_FLAG_MF) + WscSendEapFragAck(pAd, pWpsCtrl, pEntry); + else +#endif /* WSC_V2_SUPPORT */ + { + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, pWpsCtrl->pWscRxBuf, pWpsCtrl->WscRxBufLen); + Elem->MsgLen = pWpsCtrl->WscRxBufLen; + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + pWpsCtrl->WscRxBufLen = 0; + NdisZeroMemory(pWpsCtrl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + } + } + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ERROR: WscCheckWSCHeader() return FALSE!\n")); + return; + } + } + + if (Elem->MsgLen <= HeaderLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("Elem->MsgLen(%ld) <= HeaderLen(%d) !!\n", Elem->MsgLen, HeaderLen)); + return; + } + + Elem->MsgLen -= (LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME)); + NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN); + if (IS_ENTRY_CLIENT(pEntry) && + (pEapFrame->Code == EAP_CODE_RSP) && + (pEapFrame->Type == EAP_TYPE_ID)) + { + if (strstr(pData, "SimpleConfig")) + { + /* EAP-Rsp (Identity) */ + NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + return; + } + else + { + BOOLEAN Cancelled; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPCancelTimer EapolTimer!!\n")); + NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN); + pWpsCtrl->EapolTimerRunning = FALSE; + RTMPCancelTimer(&pWpsCtrl->EapolTimer, &Cancelled); + return; + } + } + else + { + if (WscCheckWSCHeader((PUCHAR) pData)) + { + /* EAP-Rsp (Messages) */ + PWSC_FRAME pWsc = (PWSC_FRAME) pData; + if (pWsc->OpCode == WSC_OPCODE_FRAG_ACK) + { + /* + Send rest frag data + */ + STRING wsc_frag_ack[] = "WSC_FRAG_ACK"; + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_frag_ack, strlen(wsc_frag_ack)); + Elem->MsgLen = strlen(wsc_frag_ack); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + } + else + { + if (pWsc->Flags & WSC_MSG_FLAG_LF) + { + pData += (sizeof(WSC_FRAME) + 2); + Elem->MsgLen -= (sizeof(WSC_FRAME) + 2); + } + else + { + pData += sizeof(WSC_FRAME); + Elem->MsgLen -= sizeof(WSC_FRAME); + } + + if ((pWpsCtrl->WscRxBufLen + Elem->MsgLen) < (MGMT_DMA_BUFFER_SIZE-6)) + { + NdisMoveMemory((pWpsCtrl->pWscRxBuf + pWpsCtrl->WscRxBufLen), pData, Elem->MsgLen); + pWpsCtrl->WscRxBufLen += Elem->MsgLen; + } +#ifdef WSC_V2_SUPPORT + if (pWsc->Flags & WSC_MSG_FLAG_MF) + WscSendEapFragAck(pAd, pWpsCtrl, pEntry); + else +#endif /* WSC_V2_SUPPORT */ + { + //NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen); + NdisMoveMemory(Elem->Msg+6, pWpsCtrl->pWscRxBuf, pWpsCtrl->WscRxBufLen); + Elem->MsgLen = pWpsCtrl->WscRxBufLen; + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + pWpsCtrl->WscRxBufLen = 0; + NdisZeroMemory(pWpsCtrl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + } + } + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ERROR: WscCheckWSCHeader() return FALSE!\n")); + return; + } + } + } + else + DBGPRINT(RT_DEBUG_WARN, ("Unknow Message Type (=%lu)\n", Elem->MsgType)); +} + +#ifdef CONFIG_AP_SUPPORT + +#define WSC_SINGLE_TRIGGER_APPNAME "unknown" + +#ifdef SDK_GOAHEAD_HTTPD +#undef WSC_SINGLE_TRIGGER_APPNAME +#define WSC_SINGLE_TRIGGER_APPNAME "goahead" +#endif /* SDK_GOAHEAD_HTTPD */ + +#ifdef SDK_USER_LIGHTY +#undef WSC_SINGLE_TRIGGER_APPNAME +#define WSC_SINGLE_TRIGGER_APPNAME "nvram_daemon" +#endif /* SDK_USER_LIGHTY */ + +INT WscGetConfWithoutTrigger( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromUPnP) +{ + INT WscMode; + INT IsAPConfigured; + UCHAR apIdx; + +#ifdef LINUX +#ifdef RTMP_RBUS_SUPPORT +/* +++ added by YYHuang@Ralink, 08/03/12 */ +/* + Notify user space application that WPS procedure will begin. + Signal + ra0: SIGXFSZ + rai0: SIGWINCH +*/ + { + struct task_struct *p; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SINGLE_TRIGGER_APPNAME: %s\n", + __FUNCTION__, WSC_SINGLE_TRIGGER_APPNAME)); + + rcu_read_lock(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + for_each_process(p) +#else + for_each_task(p) +#endif + { + if(!strcmp(p->comm, WSC_SINGLE_TRIGGER_APPNAME)) + { + if (pAd->dev_idx == 0) + send_sig(SIGXFSZ, p, 0); + else + send_sig(SIGWINCH, p, 0); + } + } + rcu_read_unlock(); + } +/* --- added by YYHuang@Ralink, 08/03/12 */ +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* LINUX */ + + + /* TODO: Is it possible ApCli call this fucntion?? */ + apIdx = (pWscControl->EntryIfIdx & 0x0F); + + IsAPConfigured = pWscControl->WscConfStatus; + + if (pWscControl->WscConfMode == WSC_DISABLE) + { + pWscControl->bWscTrigger = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("WscGetConfForUpnp:: WPS is disabled.\n")); + return FALSE; + } + + if (bFromUPnP) + WscStop(pAd, FALSE, pWscControl); + + if (pWscControl->WscMode == 1) + WscMode = DEV_PASS_ID_PIN; + else + WscMode = DEV_PASS_ID_PBC; + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + if(pAd->ApCfg.MBSSID[apIdx].SmartMeshCfg.bSupportHiddenWPS) + pWscControl->bRunningHiddenWPS = TRUE; +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + + WscBuildBeaconIE(pAd, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F); + + /* 2mins time-out timer */ + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + if (bFromUPnP) + WscSendUPnPConfReqMsg(pAd, apIdx, (PUCHAR)pAd->ApCfg.MBSSID[apIdx].Ssid, + pAd->ApCfg.MBSSID[apIdx].wdev.bssid, 3, 0, AP_MODE); + + pWscControl->bWscTrigger = TRUE; + pWscControl->bWscAutoTigeer = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: trigger WSC state machine\n", __FUNCTION__)); + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscSendNACK( + IN PRTMP_ADAPTER pAdapter, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + INT DataLen = 0; + PUCHAR pWscData = NULL; + BOOLEAN Cancelled; + UCHAR CurOpMode = AP_MODE; + +#ifdef CONFIG_STA_SUPPORT + if ((pAdapter->OpMode == OPMODE_STA) + && (pWscControl->EntryIfIdx == BSS0)) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + + os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN); + if (pWscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscSendNACK:: WscData Allocate failed!\n")); + return; + } + + NdisZeroMemory(pWscData, WSC_MAX_DATA_LEN); + DataLen = BuildMessageNACK(pAdapter, pWscControl, pWscData); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && + (IS_ENTRY_APCLI(pEntry) + ) + ) + WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + else + WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode & WSC_REGISTRAR)) + WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, STA_MODE, EAP_CODE_RSP); + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + pWscControl->RegData.ReComputePke = 1; + + if (pWscData) + os_free_mem(NULL, pWscData); +} + +#ifdef WSC_INCLUDED +VOID WscCheckWpsIeFromWpsAP( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT pEid, + OUT PUSHORT pDPIDFromAP) +{ + PUCHAR pData; + SHORT Len = 0; + PWSC_IE pWscIE; + USHORT DevicePasswordID; + + if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) +#ifdef IWSC_SUPPORT + || NdisEqualMemory(pEid->Octet, IWSC_OUI, 4) +#endif // IWSC_SUPPORT // + ) + { + pData = (PUCHAR) pEid->Octet + 4; + Len = (SHORT)(pEid->Len - 4); + + while (Len > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + /* Check for WSC IEs */ + pWscIE = &WscIE; + + /* Check for device password ID, PIN = 0x0000, PBC = 0x0004 */ + if (pDPIDFromAP && be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID) + { + /* Found device password ID */ + NdisMoveMemory(&DevicePasswordID, pData + 4, sizeof(DevicePasswordID)); + DevicePasswordID = be2cpu16(DevicePasswordID); + DBGPRINT(RT_DEBUG_INFO, ("WscCheckWpsIeFromWpsAP : DevicePasswordID = 0x%04x\n", DevicePasswordID)); + if (DevicePasswordID == DEV_PASS_ID_PIN) + { + /* PIN */ + *pDPIDFromAP = DEV_PASS_ID_PIN; + } + else if (DevicePasswordID == DEV_PASS_ID_PBC) + { + /* PBC */ + *pDPIDFromAP = DEV_PASS_ID_PBC; + } + } + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + /* Set the offset and look for PBC information */ + /* Since Type and Length are both short type, we need to offset 4, not 2 */ + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } + } + + return; +} +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT +VOID WscLinkDown( + IN PRTMP_ADAPTER pAd) +{ + if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + MLME_DISASSOC_REQ_STRUCT DisassocReq; + DBGPRINT(RT_DEBUG_TRACE, ("WscLinkDown(): Disassociate with current WPS AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + RTMP_MLME_HANDLER(pAd); + } + + if (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) + { +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; + + /* The protocol is connecting to a partner. */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + +#ifdef IWSC_SUPPORT + /* + We need to send EAPOL_Start again to trigger WPS process + */ + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + pAd->StaCfg.IWscInfo.bSendEapolStart = FALSE; + pAd->StaCfg.WscControl.WscState = WSC_STATE_LINK_UP; + pAd->StaCfg.WscControl.WscStatus = STATUS_WSC_LINK_UP; + WscSendEapolStart(pAd, pAd->StaCfg.WscControl.WscPeerMAC, STA_MODE); + } + else +#endif /* IWSC_SUPPORT */ + pAd->StaCfg.WscControl.WscState = WSC_STATE_START; + } + else + { + + pAd->bConfigChanged = TRUE; + pAd->StaCfg.WscControl.bWscTrigger = FALSE; + + if (pAd->StaCfg.BssType == BSS_INFRA) + { + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); + pAd->MlmeAux.SsidBssTab.BssNr = 0; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + MAC_ADDR_LEN, + pAd->MlmeAux.Bssid, 0); + + RTMP_MLME_HANDLER(pAd); + } +#ifdef IWSC_SUPPORT + else /* BSS_ADHOC */ + { + NDIS_802_11_SSID Ssid; + if (pAd->StaCfg.IWscInfo.bReStart) + { + pAd->StaCfg.bNotFirstScan = FALSE; + pAd->StaCfg.bAutoConnectByBssid = FALSE; + pAd->StaCfg.IWscInfo.bReStart = FALSE; + pAd->StaCfg.IWscInfo.bDoNotChangeBSSID = TRUE; + + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + + if (pAd->StaCfg.WscControl.WscStatus != STATUS_WSC_CONFIGURED) + { + Ssid.SsidLength = pAd->CommonCfg.SsidLen; + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(Ssid.Ssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + } + else + { + Ssid.SsidLength = pAd->MlmeAux.SsidLen; + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(Ssid.Ssid, pAd->MlmeAux.Ssid, Ssid.SsidLength); + } + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)&Ssid, 0); + RTMP_MLME_HANDLER(pAd); + } + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_MLME_STOP, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } +#endif /* IWSC_SUPPORT */ + } + pAd->StaCfg.WscControl.RegData.ReComputePke = 1; + /* YF: Reset to default after active pbc mode */ + if (!pAd->StaCfg.WscControl.Wsc2MinsTimerRunning) + pAd->StaCfg.WscControl.RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); + +} + +ULONG WscSearchWpsApBySSID( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN INT WscMode) +{ + UCHAR i; + USHORT DesiredDPID; + BSS_ENTRY *pBss; + PWSC_CTRL pWscControl = &pAd->StaCfg.WscControl; + + if (WscMode == WSC_PBC_MODE) + DesiredDPID = DEV_PASS_ID_PBC; + else + DesiredDPID = DEV_PASS_ID_PIN; + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + if (SSID_EQUAL(pSsid, SsidLen, pBss->Ssid, pBss->SsidLen) && + pBss->WpsAP && + ((pBss->WscDPIDFromWpsAP == DesiredDPID) || (DesiredDPID == DEV_PASS_ID_PIN))) + { + if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST) && + (pBss->Channel <= 14)) + continue; + else if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST) && + (pBss->Channel > 14)) + continue; + else + return (ULONG)i; + } + } + return (ULONG)BSS_NOT_FOUND; +} +#endif /* CONFIG_STA_SUPPORT */ + +VOID WscPBCSessionOverlapCheck( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + ULONG now; + PWSC_STA_PBC_PROBE_INFO pWscStaPbcProbeInfo = &pAd->CommonCfg.WscStaPbcProbeInfo; + + pAd->CommonCfg.WscPBCOverlap = FALSE; + if (pWscStaPbcProbeInfo->WscPBCStaProbeCount > 1) + { + UCHAR i; + + for (i = 0; i < MAX_PBC_STA_TABLE_SIZE; i++) + { + NdisGetSystemUpTime(&now); + if (pWscStaPbcProbeInfo->Valid[i]) + { + if( +#ifdef SMART_MESH + (pWscControl->bWscPBCAddrMode && + !MAC_ADDR_EQUAL(pWscControl->WscPBCAddr,pWscStaPbcProbeInfo->StaMacAddr[i])) || +#endif /* SMART_MESH */ + RTMP_TIME_AFTER(now, pWscStaPbcProbeInfo->ReciveTime[i] + 120*OS_HZ)) + { + NdisZeroMemory(&(pWscStaPbcProbeInfo->StaMacAddr[i][0]), MAC_ADDR_LEN); + pWscStaPbcProbeInfo->ReciveTime[i] = 0; + pWscStaPbcProbeInfo->Valid[i] = FALSE; + pWscStaPbcProbeInfo->WscPBCStaProbeCount--; + } + } + } + + if (pWscStaPbcProbeInfo->WscPBCStaProbeCount > 1) + pAd->CommonCfg.WscPBCOverlap = TRUE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WscPBCSessionOverlapCheck : WscPBCStaProbeCount = %d\n", + pWscStaPbcProbeInfo->WscPBCStaProbeCount)); + return; +} + +VOID WscPBC_DPID_FromSTA( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr) +{ + INT Index = 0; + UCHAR tab_idx; + BOOLEAN bAddEntry = FALSE; + ULONG now; + PWSC_STA_PBC_PROBE_INFO pWscStaPbcProbeInfo = &pAd->CommonCfg.WscStaPbcProbeInfo; + + NdisGetSystemUpTime(&now); + if (pWscStaPbcProbeInfo->WscPBCStaProbeCount == 0) + bAddEntry = TRUE; + else + { + for (tab_idx = 0; tab_idx < MAX_PBC_STA_TABLE_SIZE; tab_idx++) + { + if (MAC_ADDR_EQUAL(pMacAddr, pWscStaPbcProbeInfo->StaMacAddr[tab_idx])) + { + pWscStaPbcProbeInfo->ReciveTime[tab_idx] = now; + return; + } + } + + for (tab_idx = 0; tab_idx < MAX_PBC_STA_TABLE_SIZE; tab_idx++) + { + if (RTMP_TIME_AFTER(now, pWscStaPbcProbeInfo->ReciveTime[tab_idx] + 120*OS_HZ) || + MAC_ADDR_EQUAL(pWscStaPbcProbeInfo->StaMacAddr[tab_idx], &ZERO_MAC_ADDR[0])) + { + if (pWscStaPbcProbeInfo->Valid[tab_idx] == FALSE) + { + Index = tab_idx; + bAddEntry = TRUE; + break; + } + else + { + pWscStaPbcProbeInfo->ReciveTime[tab_idx] = now; + COPY_MAC_ADDR(pWscStaPbcProbeInfo->StaMacAddr[tab_idx], pMacAddr); + return; + } + } + } + } + + if (bAddEntry) + { + pWscStaPbcProbeInfo->WscPBCStaProbeCount++; + pWscStaPbcProbeInfo->ReciveTime[Index] = now; + pWscStaPbcProbeInfo->Valid[Index] = TRUE; + COPY_MAC_ADDR(pWscStaPbcProbeInfo->StaMacAddr[Index], pMacAddr); + } +} + + +VOID WscWriteConfToDatFile(RTMP_ADAPTER *pAd, UCHAR CurOpMode) +{ + char *cfgData = 0; + PSTRING fileName = NULL; + RTMP_OS_FD file_r, file_w; + RTMP_OS_FS_INFO osFSInfo; + LONG rv, fileLen = 0; + char *offset = 0; + PSTRING pTempStr = 0; +#ifdef CONFIG_AP_SUPPORT + INT index = 0; + UCHAR apidx = (pAd->WriteWscCfgToDatFile & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ + PWSC_CTRL pWscControl = NULL; + PWSC_CREDENTIAL pCredentail = NULL; + STRING WepKeyName[MAX_WEPKEYNAME_LEN] = {0}; + STRING WepKeyFormatName[MAX_WEPKEYNAME_LEN] = {0}; + INT tempStrLen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToDatFile(CurOpMode = %d)\n", CurOpMode)); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToDatFile (wrong apidx = %d)\n", apidx)); + return; + } + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + fileName = AP_PROFILE_PATH_RBUS; + else +#endif /* RTMP_RBUS_SUPPORT */ + fileName = AP_PROFILE_PATH; + + snprintf((PSTRING) WepKeyName, sizeof(WepKeyName), "Key%dStr%d=", pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1, apidx+1); + snprintf((PSTRING) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + pWscControl = &pAd->StaCfg.WscControl; +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + fileName = STA_PROFILE_PATH_RBUS; + else +#endif /* RTMP_RBUS_SUPPORT */ + fileName = STA_PROFILE_PATH; + + snprintf(WepKeyName, sizeof(WepKeyName), "Key%dStr=", pAd->StaCfg.wdev.DefaultKeyId+1); + snprintf(WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->StaCfg.wdev.DefaultKeyId+1); + } +#endif /* CONFIG_STA_SUPPORT */ + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + file_r = RtmpOSFileOpen(fileName, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(file_r)) + { + DBGPRINT(RT_DEBUG_TRACE, ("-->1) %s: Error opening file %s\n", __FUNCTION__, fileName)); + return; + } + else + { + char tempStr[64] = {0}; + while((rv = RtmpOSFileRead(file_r, tempStr, 64)) > 0) + { + fileLen += rv; + } + os_alloc_mem(NULL, (UCHAR **)&cfgData, fileLen); + if (cfgData == NULL) + { + RtmpOSFileClose(file_r); + DBGPRINT(RT_DEBUG_TRACE, ("CfgData mem alloc fail. (fileLen = %ld)\n", fileLen)); + goto out; + } + NdisZeroMemory(cfgData, fileLen); + RtmpOSFileSeek(file_r, 0); + rv = RtmpOSFileRead(file_r, (PSTRING)cfgData, fileLen); + RtmpOSFileClose(file_r); + if (rv != fileLen) + { + DBGPRINT(RT_DEBUG_TRACE, ("CfgData mem alloc fail, fileLen = %ld\n", fileLen)); + goto ReadErr; + } + } + + file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_TRUNC, 0); + if (IS_FILE_OPEN_ERR(file_w)) + { + goto WriteFileOpenErr; + } + else + { + offset = (PCHAR) rtstrstr((PSTRING) cfgData, "Default\n"); + offset += strlen("Default\n"); + RtmpOSFileWrite(file_w, (PSTRING)cfgData, (int)(offset-cfgData)); + os_alloc_mem(NULL, (UCHAR **)&pTempStr, WSC_WR_FILE_MAX_BUF); + if (!pTempStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pTempStr mem alloc fail. (512)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + + for (;;) + { + int i = 0; + PSTRING ptr; + BOOLEAN bNewFormat = TRUE; + + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + + if ((size_t)(offset - cfgData) < fileLen) + { + ptr = (PSTRING) offset; + while(*ptr && *ptr != '\n') + { + pTempStr[i++] = *ptr++; + } + pTempStr[i] = 0x00; + + offset += strlen(pTempStr) + 1; + if ((strncmp(pTempStr, "SSID=", strlen("SSID=")) == 0) || + strncmp(pTempStr, "SSID1=", strlen("SSID1=")) == 0 || + strncmp(pTempStr, "SSID2=", strlen("SSID2=")) == 0 || + strncmp(pTempStr, "SSID3=", strlen("SSID3=")) == 0 || + strncmp(pTempStr, "SSID4=", strlen("SSID4=")) == 0 + ) + { + if (rtstrstr(pTempStr, "SSID=")) + bNewFormat = FALSE; + + WscWriteSsidToDatFile(pAd, pTempStr, bNewFormat, CurOpMode); + } +#ifdef CONFIG_STA_SUPPORT + else if (strncmp(pTempStr, "NetworkType=", strlen("NetworkType=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + if (pAd->StaCfg.BssType == BSS_ADHOC) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "NetworkType=Adhoc"); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "NetworkType=Infra"); + } +#endif /* CONFIG_STA_SUPPORT */ + else if (strncmp(pTempStr, "AuthMode=", strlen("AuthMode=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "AuthMode="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (pAd->ApCfg.MBSSID[index].SsidLen) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + USHORT auth_flag = WscGetAuthType(pAd->StaCfg.wdev.AuthMode); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, WscGetAuthTypeStr(auth_flag)); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else if (strncmp(pTempStr, "EncrypType=", strlen("EncrypType=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "EncrypType="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + USHORT encrypt_flag = WscGetEncryType(pAd->StaCfg.wdev.WepStatus); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, WscGetEncryTypeStr(encrypt_flag)); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else if ((strncmp(pTempStr, "WPAPSK=", strlen("WPAPSK=")) == 0) || + (strncmp(pTempStr, "WPAPSK1=", strlen("WPAPSK1=")) == 0) || + (strncmp(pTempStr, "WPAPSK2=", strlen("WPAPSK2=")) == 0) || + (strncmp(pTempStr, "WPAPSK3=", strlen("WPAPSK3=")) == 0) || + (strncmp(pTempStr, "WPAPSK4=", strlen("WPAPSK4=")) == 0)) + { + bNewFormat = TRUE; + if (strstr(pTempStr, "WPAPSK=")) + bNewFormat = FALSE; + WscWriteWpaPskToDatFile(pAd, pTempStr, bNewFormat); + } + else if (strncmp(pTempStr, "WscConfMode=", strlen("WscConfMode=")) == 0) + { + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "WscConfMode="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfMode); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pWscControl->WscConfMode); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfMode); +#endif /* CONFIG_STA_SUPPORT */ + } + else if (strncmp(pTempStr, "WscConfStatus=", strlen("WscConfStatus=")) == 0) + { + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "WscConfStatus="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfStatus); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pWscControl->WscConfStatus); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfStatus); +#endif /* CONFIG_STA_SUPPORT */ + } + else if (strncmp(pTempStr, "DefaultKeyID=", strlen("DefaultKeyID=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "DefaultKeyID="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pAd->ApCfg.MBSSID[index].wdev.DefaultKeyId+1); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[index].wdev.DefaultKeyId+1); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pAd->StaCfg.wdev.DefaultKeyId+1); +#endif /* CONFIG_STA_SUPPORT */ + } +#ifdef CONFIG_AP_SUPPORT + else if ((strncmp(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)) == 0) && + (CurOpMode == AP_MODE)) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled) + { + UCHAR idx = 0, KeyType[4] = {0}; + PSTRING ptr2, temp_ptr; + + ptr2 = rtstrstr(pTempStr, "="); + temp_ptr = pTempStr; + pTempStr = ptr2+1; + KeyType[0] = (UCHAR)(*pTempStr - 0x30); + for (idx = 1; idx < 4; idx++) + { + ptr2 = rtstrstr(pTempStr, ";"); + if (ptr2 == NULL) + break; + pTempStr = ptr2+1; + if ((pTempStr != NULL) || + (*pTempStr == '0') || + (*pTempStr == '1')) + KeyType[idx] = (UCHAR)(*pTempStr - 0x30); + } + pTempStr = temp_ptr; + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)); + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + if (idx == apidx) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s0", pTempStr); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, KeyType[idx]); + + if (apidx < (pAd->ApCfg.BssidNum - 1)) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;", pTempStr); + } + } + } + else if ((strncmp(pTempStr, WepKeyName, strlen(WepKeyName)) == 0) && + (CurOpMode == AP_MODE)) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName)); + tempStrLen = strlen(pTempStr); + if (pCredentail->KeyLength) + { + if ((pCredentail->KeyLength == 5) || + (pCredentail->KeyLength == 13)) + { + int jjj=0; + for (jjj=0; jjjKeyLength; jjj++) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%02x", pTempStr, pCredentail->Key[jjj]); + } + else if ((pCredentail->KeyLength == 10) || + (pCredentail->KeyLength == 26)) + { + NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength); + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + else if (rtstrstr(pTempStr, (PSTRING) WepKeyFormatName) && (CurOpMode == STA_MODE)) + { + pCredentail = &pWscControl->WscProfile.Profile[pWscControl->WscProfile.ApplyProfileIdx]; + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s0", WepKeyFormatName); /* Hex */ + } + } + else if (rtstrstr(pTempStr, (PSTRING) WepKeyName) && (CurOpMode == STA_MODE)) + { + pCredentail = &pWscControl->WscProfile.Profile[pWscControl->WscProfile.ApplyProfileIdx]; + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName)); + tempStrLen = strlen(pTempStr); + if (pCredentail->KeyLength) + { + if ((pCredentail->KeyLength == 5) || + (pCredentail->KeyLength == 13)) + { + int jjj=0; + for (jjj=0; jjjKeyLength; jjj++) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%02x", pTempStr, pCredentail->Key[jjj]); + } + else if ((pCredentail->KeyLength == 10) || + (pCredentail->KeyLength == 26)) + { + NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength); + } + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + RtmpOSFileWrite(file_w, pTempStr, strlen(pTempStr)); + RtmpOSFileWrite(file_w, "\n", 1); + } + else + { + break; + } + } + RtmpOSFileClose(file_w); + } + +WriteErr: + if (pTempStr) + os_free_mem(NULL, pTempStr); +ReadErr: +WriteFileOpenErr: + if (cfgData) + os_free_mem(NULL, cfgData); +out: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToDatFile\n")); + return; +} + +#ifdef CONFIG_AP_SUPPORT +void WscWriteConfToAR9File( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode) +{ + PSTRING fileName = NULL; + RTMP_OS_FD file_w; + RTMP_OS_FS_INFO osFSInfo; + INT offset = 0; + INT datoffset = 0; + PSTRING pTempStr = 0; + PSTRING pDatStr = 0; +#ifdef CONFIG_AP_SUPPORT + INT index = 0; + UCHAR apidx = MAIN_MBSSID; +#endif /* CONFIG_AP_SUPPORT */ + PWSC_CTRL pWscControl = NULL; + PWSC_CREDENTIAL pCredentail = NULL; + STRING WepKeyName[MAX_WEPKEYNAME_LEN] = {0}; + STRING WepKeyFormatName[MAX_WEPKEYTYPE_LEN] = {0}; + INT tempStrLen = 0; + STRING item_str[10] = {0}; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToAR9File\n")); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + fileName = "/var/wps_profile.dat"; + + snprintf((PSTRING) WepKeyName, sizeof(WepKeyName), "Key%dStr1=", pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId+1); + snprintf((PSTRING) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId+1); + } +#endif /* CONFIG_AP_SUPPORT */ + + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_CREAT, 0); + if (IS_FILE_OPEN_ERR(file_w)) + { + goto WriteFileOpenErr; + } + else + { + os_alloc_mem(NULL, (UCHAR **)&pTempStr, 512); + if (!pTempStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pTempStr mem alloc fail. (512)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + os_alloc_mem(NULL, (UCHAR **)&pDatStr, 4096); + if (!pDatStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pDatStr mem alloc fail. (4096)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + + /*for (;;) */ + { + NdisZeroMemory(pTempStr, 512); + NdisZeroMemory(pDatStr, 4096); + { + { + NdisZeroMemory(item_str, 10); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(item_str, sizeof(item_str), "SSID%d", (apidx + 1)); + { + NdisMoveMemory(pTempStr, item_str, strlen(item_str)); + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, "=", 1); + offset += 1; + NdisMoveMemory(pTempStr + offset, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen); + offset += pAd->ApCfg.MBSSID[apidx].SsidLen; + NdisMoveMemory(pTempStr + offset, "\n", 1); + offset += 1; + } + NdisZeroMemory(item_str, 10); + } + } + NdisMoveMemory(pDatStr,pTempStr,offset); + datoffset += offset; + + { + offset=0; + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "AuthMode="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (pAd->ApCfg.MBSSID[index].SsidLen) + { + if (index == 0) + snprintf(pTempStr, 512, "%s%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + else + snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + } + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "EncrypType="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, 512, "%s%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + else + snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, 512); + NdisZeroMemory(item_str, 10); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(item_str, sizeof(item_str), "WPAPSK%d", (apidx + 1)); + /*if (rtstrstr(pTempStr, item_str)) */ + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + NdisMoveMemory(pTempStr, item_str, strlen(item_str)); + offset = strlen(pTempStr); + NdisMoveMemory(pTempStr + offset, "=", 1); + offset += 1; + NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen); + offset += pWscControl->WpaPskLen; + NdisMoveMemory(pTempStr + offset, "\n", 1); + offset += 1; + } + NdisZeroMemory(item_str, 10); + } + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + + { + offset=0; + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "WscConfMode="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfMode); + else + snprintf(pTempStr, 512, "%s;%d", pTempStr, pWscControl->WscConfMode); + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "WscConfStatus="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfStatus); + else + snprintf(pTempStr, 512, "%s;%d", pTempStr, pWscControl->WscConfStatus); + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "DefaultKeyID="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, 512, "%s%d", pTempStr, pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1); + else + snprintf(pTempStr, 512, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1); + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + +#endif /* CONFIG_AP_SUPPORT */ + } +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 1; index <= 4; index++) + { + snprintf(WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", index); + /*if (rtstrstr(pTempStr, WepKeyFormatName)) */ + { + NdisZeroMemory(pTempStr, 512); + offset=0; + NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.WepStatus == Ndis802_11WEPEnabled) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if ((pCredentail->KeyLength == 5) || + (pCredentail->KeyLength == 13)) + snprintf(pTempStr, 512, "%s1", pTempStr); /* ASCII */ + else + snprintf(pTempStr, 512, "%s0", pTempStr); /* Hex */ + } + if (apidx < (pAd->ApCfg.BssidNum - 1)) + snprintf(pTempStr, 512, "%s;", pTempStr); + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + + snprintf(WepKeyName, sizeof(WepKeyName), "Key%dStr=", index); + /*if (rtstrstr(pTempStr, WepKeyName)) */ + { + NdisZeroMemory(pTempStr, 512); + offset=0; + NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName)); + tempStrLen = strlen(pTempStr); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if (pCredentail->KeyLength) + { + NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength); + tempStrLen = strlen(pTempStr); + } + if (apidx < (pAd->ApCfg.BssidNum - 1)) + NdisMoveMemory(pTempStr + tempStrLen, ";", 1); + tempStrLen += 1; + } + snprintf(pTempStr, 512, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(WepKeyName, sizeof(WepKeyName), "Key%dStr%d=", index, (apidx + 1)); + if ((pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled)) + { + NdisZeroMemory(pTempStr, 512); + NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName)); + tempStrLen = strlen(pTempStr); + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength); + NdisMoveMemory(pTempStr + tempStrLen+pCredentail->KeyLength, "\n", 1); + } + offset=tempStrLen+pCredentail->KeyLength+1; + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + RtmpOSFileWrite(file_w, pDatStr, datoffset); + /*RtmpOSFileWrite(file_w, "\n", 1); */ + } + } + RtmpOSFileClose(file_w); + } + +WriteErr: + if (pTempStr) + os_free_mem(NULL, pTempStr); + if (pDatStr) + os_free_mem(NULL, pDatStr); + +WriteFileOpenErr: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToAR9File\n")); + return; +} +#endif/*CONFIG_AP_SUPPORT*/ + +static INT wsc_write_dat_file_thread ( + IN ULONG Context) +{ + RTMP_OS_TASK *pTask; + RTMP_ADAPTER *pAd; + int Status = 0; + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + if (pAd == NULL) + return 0; + + RtmpOSTaskCustomize(pTask); + + while (pTask && !RTMP_OS_TASK_IS_KILLED(pTask)) + { + RtmpusecDelay(2000); + + if (RtmpOSTaskWait(pAd, pTask, &Status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + if (Status != 0) + break; + + + if (pAd->pWscElme && (pAd->pWscElme->MsgLen != 0)) + { + MLME_QUEUE_ELEM *pElme; + os_alloc_mem(pAd, (UCHAR **)&pElme, sizeof(MLME_QUEUE_ELEM)); + if (pElme) + { + NdisZeroMemory(pElme, sizeof(MLME_QUEUE_ELEM)); + RTMP_SEM_LOCK(&pAd->WscElmeLock); + NdisMoveMemory(pElme, pAd->pWscElme, sizeof(MLME_QUEUE_ELEM)); + pAd->pWscElme->MsgLen = 0; + NdisZeroMemory(pAd->pWscElme->Msg, MGMT_DMA_BUFFER_SIZE); + RTMP_SEM_UNLOCK(&pAd->WscElmeLock); + WpsSmProcess(pAd, pElme); + os_free_mem(NULL, pElme); + } + } + + if (pAd->WriteWscCfgToDatFile != 0xFF) + { + UCHAR CurOpMode = AP_MODE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; + if (pAd->WriteWscCfgToDatFile != BSS0) + CurOpMode = AP_MODE; +#endif /* CONFIG_STA_SUPPORT */ + + WscWriteConfToDatFile(pAd, CurOpMode); + +#ifdef CONFIG_AP_SUPPORT +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT + WscWriteConfToAR9File(pAd, CurOpMode); +#endif /*AR9_MAPI_SUPPORT*/ +#endif /* INF_AR9 */ +#endif/*CONFIG_AP_SUPPORT*/ + pAd->WriteWscCfgToDatFile = 0xFF; + } + } + + if (pTask) + RtmpOSTaskNotifyToExit(pTask); + + return 0; +} + + +/* + * This kernel thread init in the probe fucntion, so we should kill it when do remove module. + */ +BOOLEAN WscThreadExit(RTMP_ADAPTER *pAd) +{ + INT ret; + + /* + This kernel thread init in the probe fucntion, so kill it when do remove module. + */ + ret = RtmpOSTaskKill(&pAd->wscTask); + if (ret == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("kill wsc task failed!\n")); + } + + if (pAd->pHmacData) + { + os_free_mem(NULL, pAd->pHmacData); + pAd->pHmacData = NULL; + } + if (pAd->pWscElme) + { + os_free_mem(NULL, pAd->pWscElme); + pAd->pWscElme = NULL; + } + NdisFreeSpinLock(&pAd->WscElmeLock); +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + INT ap_idx; + UCHAR MaxBssidNum = MAX_MBSSID_NUM(pAd); + + for (ap_idx = 0; ap_idx < MaxBssidNum; ap_idx++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[ap_idx].WscControl; + WscStop(pAd, FALSE, pWpsCtrl); + pWpsCtrl->WscRxBufLen = 0; + if (pWpsCtrl->pWscRxBuf) + { + os_free_mem(pAd, pWpsCtrl->pWscRxBuf); + pWpsCtrl->pWscRxBuf = NULL; + } + pWpsCtrl->WscTxBufLen = 0; + if (pWpsCtrl->pWscTxBuf) + { + os_free_mem(pAd, pWpsCtrl->pWscTxBuf); + pWpsCtrl->pWscTxBuf = NULL; + } +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl->WscSetupLockTimerRunning) + { + BOOLEAN Cancelled; + pWpsCtrl->WscSetupLockTimerRunning = FALSE; + RTMPCancelTimer(&pWpsCtrl->WscSetupLockTimer, &Cancelled); + } + if (pWpsCtrl->WscV2Info.ExtraTlv.pTlvData) + { + os_free_mem(NULL, pWpsCtrl->WscV2Info.ExtraTlv.pTlvData); + pWpsCtrl->WscV2Info.ExtraTlv.pTlvData = NULL; + } +#endif // WSC_V2_SUPPORT // + WscClearPeerList(&pWpsCtrl->WscPeerList); + NdisFreeSpinLock(&pWpsCtrl->WscPeerListSemLock); + } +#ifdef APCLI_SUPPORT + { + INT index; + WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[BSS0].WscControl); + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[index].WscControl; + + pWpsCtrl->WscTxBufLen = 0; + if (pWpsCtrl->pWscTxBuf) + os_free_mem(pAd, pWpsCtrl->pWscTxBuf); + pWpsCtrl->WscRxBufLen = 0; + if (pWpsCtrl->pWscRxBuf) + os_free_mem(pAd, pWpsCtrl->pWscRxBuf); + WscClearPeerList(&pWpsCtrl->WscPeerList); + NdisFreeSpinLock(&pWpsCtrl->WscPeerListSemLock); + } + } +#endif // APCLI_SUPPORT // + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif // CONFIG_AP_SUPPORT // + &pAd->StaCfg.WscControl); + pAd->StaCfg.WscControl.WscRxBufLen = 0; + if (pAd->StaCfg.WscControl.pWscRxBuf) + { + os_free_mem(pAd, pAd->StaCfg.WscControl.pWscRxBuf); + pAd->StaCfg.WscControl.pWscRxBuf = NULL; + } + pAd->StaCfg.WscControl.WscTxBufLen = 0; + if (pAd->StaCfg.WscControl.pWscTxBuf) + { + os_free_mem(pAd, pAd->StaCfg.WscControl.pWscTxBuf); + pAd->StaCfg.WscControl.pWscTxBuf = NULL; + } + WscClearPeerList(&pAd->StaCfg.WscControl.WscPeerList); + NdisFreeSpinLock(&pAd->StaCfg.WscControl.WscPeerListSemLock); + +#ifdef IWSC_SUPPORT + WscClearPeerList(&pAd->StaCfg.WscControl.WscConfiguredPeerList); + NdisFreeSpinLock(&pAd->StaCfg.WscControl.WscConfiguredPeerListSemLock); +#endif /* IWSC_SUPPORT */ + } +#endif /* CONFIG_STA_SUPPORT */ + + /* WSC hardware push button function 0811 */ + WSC_HDR_BTN_Stop(pAd); + return TRUE; +} + + +/* + * This kernel thread init in the probe function. + */ +NDIS_STATUS WscThreadInit(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS status = NDIS_STATUS_FAILURE; + RTMP_OS_TASK *pTask; + + + DBGPRINT(RT_DEBUG_TRACE, ("-->WscThreadInit()\n")); + + pTask = &pAd->wscTask; + + + RTMP_OS_TASK_INIT(pTask, "RtmpWscTask", pAd); + status = RtmpOSTaskAttach(pTask, wsc_write_dat_file_thread, (ULONG)&pAd->wscTask); + if (status == NDIS_STATUS_SUCCESS) + { + os_alloc_mem(NULL, &pAd->pHmacData, sizeof(CHAR)*(2048)); + if (pAd->pHmacData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wsc HmacData memory alloc failed!\n")); + status = FALSE; + } + NdisAllocateSpinLock(pAd, &pAd->WscElmeLock); + os_alloc_mem(NULL, (UCHAR **)&pAd->pWscElme, sizeof(MLME_QUEUE_ELEM)); + } + DBGPRINT(RT_DEBUG_TRACE, ("<--WscThreadInit(), status=%d!\n", status)); + + return status; +} + + +/* WSC hardware push button function 0811 */ +/* +======================================================================== +Routine Description: + Initialize the PUSH PUTTION Check Module. + +Arguments: + ad_p - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID WSC_HDR_BTN_Init( + IN PRTMP_ADAPTER pAd) +{ + pAd->CommonCfg.WscHdrPshBtnCheckCount = 0; +} /* End of WSC_HDR_BTN_Init */ + + +/* +======================================================================== +Routine Description: + Stop the PUSH PUTTION Check Module. + +Arguments: + ad_p - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID WSC_HDR_BTN_Stop( + IN PRTMP_ADAPTER pAd) +{ + pAd->CommonCfg.WscHdrPshBtnCheckCount = 0; +} /* End of WSC_HDR_BTN_Stop */ + + +/* +======================================================================== +Routine Description: + Start the PUSH PUTTION Check thread. + +Arguments: + *Context - WLAN control block pointer + +Return Value: + 0 - terminate the thread successfully + +Note: +======================================================================== +*/ +#ifdef CONFIG_AP_SUPPORT +extern INT Set_AP_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +extern INT Set_AP_WscGetConf_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif /* CONFIG_AP_SUPPORT */ + +/*#ifdef CONFIG_STA_SUPPORT */ + +VOID WSC_HDR_BTN_CheckHandler( + IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BOOLEAN flg_pressed; + + + WSC_HDR_BTN_MR_PRESS_FLG_GET(pAd, flg_pressed); + + if (flg_pressed) + { + /* the button is pressed */ + if (pAd->CommonCfg.WscHdrPshBtnCheckCount == WSC_HDR_BTN_CONT_TIMES) + { + /* we only handle once until the button is released */ + pAd->CommonCfg.WscHdrPshBtnCheckCount = 0; + + /* execute WSC PBC function */ + DBGPRINT(RT_DEBUG_ERROR, ("wsc> execute WSC PBC...\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pObj->ioctl_if = 0; + Set_AP_WscMode_Proc(pAd, (PUCHAR)"2"); /* 2: PBC */ + Set_AP_WscGetConf_Proc(pAd, (PUCHAR)"1"); /* 1: Trigger */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pObj->ioctl_if = 0; + Set_WscConfMode_Proc(pAd, (PUCHAR)"1"); /* 1: */ + Set_WscMode_Proc(pAd, (PUCHAR)"2"); /* 2: PBC */ + Set_WscGetConf_Proc(pAd, (PUCHAR)"1"); /* 1: Trigger */ + } +#endif /* CONFIG_STA_SUPPORT */ + return; + } + + pAd->CommonCfg.WscHdrPshBtnCheckCount ++; + } + else + { + /* the button is released */ + pAd->CommonCfg.WscHdrPshBtnCheckCount = 0; + } +} + +#ifdef WSC_LED_SUPPORT +/* */ +/* Support WPS LED mode (mode 7, mode 8 and mode 9). */ +/* Ref: User Feedback (page 80, WPS specification 1.0) */ +/* */ +BOOLEAN WscSupportWPSLEDMode( + IN PRTMP_ADAPTER pAd) +{ + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_8) || + (LED_MODE(pAd) == WPS_LED_MODE_9) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12) +#ifdef CONFIG_WIFI_LED_SUPPORT + ||(LED_MODE(pAd) == WPS_LED_MODE_SHARE) +#endif /* CONFIG_WIFI_LED_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Support WPS LED mode (The WPS LED mode = %d).\n", + __FUNCTION__, LED_MODE(pAd))); + return TRUE; /* Support WPS LED mode. */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Not support WPS LED mode (The WPS LED mode = %d).\n", + __FUNCTION__, LED_MODE(pAd))); + return FALSE; /* Not support WPS LED mode. */ + } +} + +BOOLEAN WscSupportWPSLEDMode10( + IN PRTMP_ADAPTER pAd) +{ + if ((LED_MODE(pAd) == WPS_LED_MODE_10)){ + DBGPRINT(RT_DEBUG_TRACE, ("%s: Support WPS LED mode (The WPS LED mode = %d).\n", + __FUNCTION__, LED_MODE(pAd))); + return TRUE; /*Support WPS LED mode 10. */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Not support WPS LED mode (The WPS LED mode = %d).\n", + __FUNCTION__, LED_MODE(pAd))); + return FALSE; /* Not support WPS LED mode 10. */ + } +} + +/* */ +/* Whether the WPS AP has security setting or not. */ +/* Note that this function is valid only after the WPS handshaking. */ +/* */ +BOOLEAN WscAPHasSecuritySetting( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl) +{ + BOOLEAN bAPHasSecuritySetting = FALSE; + UCHAR currentIdx = MAIN_MBSSID; + +#ifdef CONFIG_AP_SUPPORT + currentIdx = (pWscControl->EntryIfIdx & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + currentIdx = pWscControl->WscProfile.ApplyProfileIdx; +#endif /* CONFIG_STA_SUPPORT */ + + switch (pWscControl->WscProfile.Profile[currentIdx].EncrType) + { + case WSC_ENCRTYPE_NONE: + { + bAPHasSecuritySetting = FALSE; + break; + } + + case WSC_ENCRTYPE_WEP: + case WSC_ENCRTYPE_TKIP: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + case WSC_ENCRTYPE_AES: + { + bAPHasSecuritySetting = TRUE; + break; + } + + default: + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Incorrect encryption types (%d)\n", + __FUNCTION__, pWscControl->WscProfile.Profile[currentIdx].EncrType)); + ASSERT(FALSE); + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: WSC Entryption Type = %d\n", + __FUNCTION__, pWscControl->WscProfile.Profile[currentIdx].EncrType)); + + return bAPHasSecuritySetting; +} + + +/* */ +/* After the NIC connects with a WPS AP or not, */ +/* the WscLEDTimer timer controls the LED behavior according to LED mode. */ +/* */ +VOID WscLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd; + UCHAR WPSLEDStatus = 0; + + /* WPS LED mode 7, 8, 11 and 12. */ + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_8) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12)) + { + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Turn off the WPS successful LED pattern.\n", __FUNCTION__)); + } + else if ((LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */ +#ifdef CONFIG_WIFI_LED_SUPPORT + || (LED_MODE(pAd) == WPS_LED_MODE_SHARE) +#endif /* CONFIG_WIFI_LED_SUPPORT */ + ) + { + switch (pWscControl->WscLEDMode) /* Last WPS LED state. */ + { + + + /* Turn off the blue LED after 300 seconds. */ + case LED_WPS_SUCCESS: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + + /* Turn on/off the WPS success LED according to AP's encryption algorithm after one second. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_TURN_OFF_LED_TIMEOUT); + pWscControl->WscLEDTimerRunning = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SUCCESS => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + break; + + /* After turn off the blue LED for one second. */ + /* AP uses an encryption algorithm: */ + /* a) YES: Turn on the blue LED. */ + /* b) NO: Turn off the blue LED. */ + case LED_WPS_TURN_LED_OFF: + if ((pWscControl->WscState == WSC_STATE_OFF) && + (pWscControl->WscStatus == STATUS_WSC_CONFIGURED)) + { + if (WscAPHasSecuritySetting(pAd, pWscControl) == TRUE) /* The NIC connects with an AP using an encryption algorithm. */ + { + /* Turn WPS success LED. */ + WPSLEDStatus = LED_WPS_TURN_ON_BLUE_LED; + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_TURN_LED_OFF => LED_WPS_TURN_ON_BLUE_LED\n", __FUNCTION__)); + } + else /* The NIC connects with an AP using OPEN-NONE. */ + { + /* Turn off the WPS LED. */ + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_TURN_LED_OFF => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + } + } + break; + + /* Turn off the amber LED after 15 seconds. */ + case LED_WPS_ERROR: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; /* Turn off the WPS LED. */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_ERROR/LED_WPS_SESSION_OVERLAP_DETECTED => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + break; + /* Turn off the amber LED after ~3 seconds. */ + case LED_WPS_SESSION_OVERLAP_DETECTED: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; /* Turn off the WPS LED. */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SESSION_OVERLAP_DETECTED => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + break; + + default: + /* do nothing. */ + break; + } + + if (WPSLEDStatus) + RTMPSetLED(pAd, WPSLEDStatus); + } + else + { + /* do nothing. */ + } +} + + +VOID WscSkipTurnOffLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + + /* Allow the NIC to turn off the WPS LED again. */ + pWscControl->bSkipWPSTurnOffLED = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Allow the NIC to turn off the WPS LED again.\n", __FUNCTION__)); +} + +#endif /* WSC_LED_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID WscUpdatePortCfgTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = NULL; + BOOLEAN /* bRestart = TRUE,*/ bEnrollee = TRUE; + PWSC_CREDENTIAL pCredential = NULL; + PMULTISSID_STRUCT pMbss = NULL; + + if (pWscControl == NULL) + return; + + pCredential = (PWSC_CREDENTIAL) &pWscControl->WscProfile.Profile[0]; + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + + if (pAd == NULL) + return; + + pMbss = &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F]; + if (WscGetAuthMode(pCredential->AuthType) == pMbss->wdev.AuthMode && + WscGetWepStatus(pCredential->EncrType) == pMbss->wdev.WepStatus && + NdisEqualMemory(pMbss->Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength) && + NdisEqualMemory(pWscControl->WpaPsk, pCredential->Key, pCredential->KeyLength)) + { + return; + } + + if (pWscControl->WscProfile.ApplyProfileIdx & 0x8000) + bEnrollee = FALSE; + WscWriteConfToPortCfg(pAd, + pWscControl, + &pWscControl->WscProfile.Profile[0], + bEnrollee); + pWscControl->WscProfile.ApplyProfileIdx &= 0x7FFF; + { + pAd->WriteWscCfgToDatFile = (pWscControl->EntryIfIdx & 0x0F); + APStop(pAd); + APStartUp(pAd); + } + +/*#ifdef KTHREAD_SUPPORT */ +/* WAKE_UP(&(pAd->wscTask)); */ +/*#else */ +/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema)); */ +/*#endif */ + RtmpOsTaskWakeUp(&(pAd->wscTask)); + + return; +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckPeerDPID( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 Fr, + IN PUCHAR eid_data, + IN INT eid_len) +{ + WSC_IE *pWscIE; + PUCHAR pData = NULL; + INT Len = 0; + USHORT DevicePasswordID; + PWSC_CTRL pWscCtrl = NULL; + + pData = eid_data + 4; + Len = eid_len - 4; + while (Len > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + /* Check for WSC IEs*/ + pWscIE = &WscIE; + + /* Check for device password ID, PBC = 0x0004*/ + if (be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID) + { + /* Found device password ID*/ + NdisMoveMemory(&DevicePasswordID, pData + 4, sizeof(DevicePasswordID)); + DevicePasswordID = be2cpu16(DevicePasswordID); + if (DevicePasswordID == DEV_PASS_ID_PBC) /* Check for PBC value*/ + { + WscPBC_DPID_FromSTA(pAd, Fr->Hdr.Addr2); + hex_dump("PBC STA:", Fr->Hdr.Addr2, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + else if (DevicePasswordID == DEV_PASS_ID_PIN) + { +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + UCHAR ap_idx = 0; + for (ap_idx = 0; ap_idx < pAd->ApCfg.BssidNum; ap_idx++) + { + if (NdisEqualMemory(Fr->Hdr.Addr1, pAd->ApCfg.MBSSID[ap_idx].wdev.bssid, MAC_ADDR_LEN)) + break; + } + + if (ap_idx >= pAd->ApCfg.BssidNum) + { + break; + } + + pWscCtrl = &pAd->ApCfg.MBSSID[ap_idx].WscControl; + } +#endif /* CONFIG_AP_SUPPORT */ + + /* + WSC 2.0 STA will send probe request with WPS IE anyway. + Do NOT add this STA to WscPeerList after AP is triggered to do PBC. + */ + if (pWscCtrl && + (!pWscCtrl->bWscTrigger || (pWscCtrl->WscMode != WSC_PBC_MODE))) + { + RTMP_SEM_LOCK(&pWscCtrl->WscPeerListSemLock); + WscInsertPeerEntryByMAC(&pWscCtrl->WscPeerList, Fr->Hdr.Addr2); + RTMP_SEM_UNLOCK(&pWscCtrl->WscPeerListSemLock); + } + } +#ifdef IWSC_SUPPORT + else if (DevicePasswordID == DEV_PASS_ID_SMPBC) + { + IWSC_AddSmpbcEnrollee(pAd, Fr->Hdr.Addr2); + } +#endif /* IWSC_SUPPORT */ + else { + DBGPRINT(RT_DEBUG_TRACE, ("%s : DevicePasswordID = 0x%04x\n", + __FUNCTION__, DevicePasswordID)); + } + break; + } + +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + pWscCtrl = &pAd->StaCfg.WscControl; + + if ((be2cpu16(pWscIE->Type) == WSC_ID_CONFIG_METHODS) && + (pWscCtrl->WscConfMode == WSC_REGISTRAR) && + (pWscCtrl->bWscTrigger == TRUE)) + { + USHORT PeerConfigMethod = 0; + PWSC_PEER_ENTRY pWscPeerEntry = NULL; + RTMP_SEM_LOCK(&pWscCtrl->WscConfiguredPeerListSemLock); + pWscPeerEntry = WscFindPeerEntry(&pWscCtrl->WscConfiguredPeerList, Fr->Hdr.Addr2); + if (pWscPeerEntry == NULL) + { + NdisMoveMemory(&PeerConfigMethod, pData + 4, sizeof(PeerConfigMethod)); + PeerConfigMethod = be2cpu16(PeerConfigMethod); + if (pWscCtrl->WscMode == WSC_PIN_MODE) + { + NdisMoveMemory(pWscCtrl->WscPeerMAC, Fr->Hdr.Addr2, MAC_ADDR_LEN); + NdisMoveMemory(pWscCtrl->EntryAddr, Fr->Hdr.Addr2, MAC_ADDR_LEN); + } + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_PEER_PROBE_REQ, sizeof(USHORT), &PeerConfigMethod, 0); + RTMP_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Add this peer: %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(Fr->Hdr.Addr2))); + } + RTMP_SEM_UNLOCK(&pWscCtrl->WscConfiguredPeerListSemLock); + DBGPRINT(RT_DEBUG_TRACE, ("%s() : PeerConfigMethod = 0x%04x\n", + __FUNCTION__, PeerConfigMethod)); + } + } +#endif /* IWSC_SUPPORT */ + + /* Set the offset and look for PBC information*/ + /* Since Type and Length are both short type, we need to offset 4, not 2*/ + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } +} + +VOID WscClearPeerList( + IN PLIST_HEADER pWscEnList) +{ + PLIST_ENTRY pEntry = NULL; + + pEntry = pWscEnList->pHead; + + while (pEntry != NULL) + { + removeHeadList(pWscEnList); + os_free_mem(NULL, pEntry); + pEntry = pWscEnList->pHead; + } + + return; +} + +PWSC_PEER_ENTRY WscFindPeerEntry( + PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr) +{ + PWSC_PEER_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = pWscEnList->pHead; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + while (pPeerEntry != NULL) + { + if (NdisEqualMemory(pPeerEntry->mac_addr, pMacAddr, MAC_ADDR_LEN)) + return pPeerEntry; + pListEntry = pListEntry->pNext; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + } + + return NULL; +} + +VOID WscInsertPeerEntryByMAC( + PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr) +{ + PWSC_PEER_ENTRY pWscPeer = NULL; + + pWscPeer = WscFindPeerEntry(pWscEnList, pMacAddr); + if (pWscPeer) + { + NdisGetSystemUpTime(&pWscPeer->receive_time); + } + else + { + os_alloc_mem(NULL, (UCHAR **)&pWscPeer, sizeof(WSC_PEER_ENTRY)); + if (pWscPeer) + { + NdisZeroMemory(pWscPeer, sizeof(WSC_PEER_ENTRY)); + pWscPeer->pNext = NULL; + NdisMoveMemory(pWscPeer->mac_addr, pMacAddr, MAC_ADDR_LEN); + NdisGetSystemUpTime(&pWscPeer->receive_time); + insertTailList(pWscEnList, (PLIST_ENTRY)pWscPeer); + } + ASSERT(pWscPeer != NULL); + } +} + +#ifdef CONFIG_AP_SUPPORT +INT WscApShowPeerList( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ApIdx = 0; + PWSC_CTRL pWscControl = NULL; + PWSC_PEER_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + PLIST_HEADER pWscEnList = NULL; + + for (ApIdx = 0; ApIdx < pAd->ApCfg.BssidNum; ApIdx++) + { + pWscControl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; + pWscEnList = &pWscControl->WscPeerList; + + if (pWscEnList->size != 0) + { + WscMaintainPeerList(pAd, pWscControl); + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + pListEntry = pWscEnList->pHead; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + while (pPeerEntry != NULL) + { + printk("MAC:%02x:%02x:%02x:%02x:%02x:%02x\tReveive Time:%lu\n", + pPeerEntry->mac_addr[0], + pPeerEntry->mac_addr[1], + pPeerEntry->mac_addr[2], + pPeerEntry->mac_addr[3], + pPeerEntry->mac_addr[4], + pPeerEntry->mac_addr[5], + pPeerEntry->receive_time); + pListEntry = pListEntry->pNext; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + } + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + printk("\n"); + } + + return TRUE; +} + + +VOID WscSetupLockTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = NULL; + + if (pWscControl == NULL) + return; + + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + + if (pAd == NULL) + return; + + pWscControl->bSetupLock = FALSE; + pWscControl->WscSetupLockTimerRunning = FALSE; + + WscBuildBeaconIE(pAd, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + (pWscControl->EntryIfIdx & 0xF), + NULL, + 0, + AP_MODE); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_AP_WLAN_MGR, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pWscControl->EntryIfIdx, + NULL, + 0, + AP_MODE); + + APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F); + DBGPRINT(RT_DEBUG_TRACE, ("WscSetupLockTimeout!\n")); + + return; +} + + +VOID WscCheckPinAttackCount( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + BOOLEAN bCancelled; + + if ((pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI) + ) + { + /* + APCLI and P2P CLI don't need to do PIN attack checking. + */ + return; + } + + /* + If a static PIN is used, + the AP must track multiple failed attempts to authenticate an external Registrar and then enter a lock-down state + (This state is signified by setting the attribute AP Setup Locked to TRUE). + After at most 10 failed, consecutive attempts, with no time limitation, from any number of external Registrars, + the AP shall revert to a locked down state, and the AP shall remain in the locked down state indefinitely + (i.e., until the user intervenes to unlock AP's PIN for use by external Registrars) + */ + pWscControl->PinAttackCount++; + if (pWscControl->PinAttackCount >= pWscControl->MaxPinAttack) + { + pWscControl->bSetupLock = TRUE; + if (pWscControl->WscSetupLockTimerRunning) + { + RTMPCancelTimer(&pWscControl->WscSetupLockTimer, &bCancelled); + pWscControl->WscSetupLockTimerRunning = FALSE; + } + + if (pWscControl->PinAttackCount < WSC_LOCK_FOREVER_PIN_ATTACK) + { + pWscControl->WscSetupLockTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->WscSetupLockTimer, pWscControl->SetupLockTime*60*1000); + } + pWscControl->PinAttackCount = 0; + + WscBuildBeaconIE(pAd, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + (pWscControl->EntryIfIdx & 0xF), + NULL, + 0, + AP_MODE); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_AP_WLAN_MGR, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pWscControl->EntryIfIdx, + NULL, + 0, + AP_MODE); + + APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F); + } +} + +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +INT WscStaShowPeerList( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl = NULL; + PWSC_PEER_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + PLIST_HEADER pWscEnList = NULL; + + pWscControl = &pAd->StaCfg.WscControl; + pWscEnList = &pWscControl->WscPeerList; + + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + if (pWscEnList->size != 0) + { + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + WscMaintainPeerList(pAd, pWscControl); + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + pListEntry = pWscEnList->pHead; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + while (pPeerEntry != NULL) + { + printk("MAC:%02x:%02x:%02x:%02x:%02x:%02x\tReveive Time:%lu\n", + pPeerEntry->mac_addr[0], + pPeerEntry->mac_addr[1], + pPeerEntry->mac_addr[2], + pPeerEntry->mac_addr[3], + pPeerEntry->mac_addr[4], + pPeerEntry->mac_addr[5], + pPeerEntry->receive_time); + pListEntry = pListEntry->pNext; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + } + } + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + printk("\n"); + + return TRUE; +} +#endif // CONFIG_STA_SUPPORT // + +VOID WscMaintainPeerList( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWpsCtrl) +{ + PWSC_PEER_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL, pTempListEntry = NULL; + PLIST_HEADER pWscEnList = NULL; + ULONG now_time = 0; + + RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock); + pWscEnList = &pWpsCtrl->WscPeerList; + + + NdisGetSystemUpTime(&now_time); + pListEntry = pWscEnList->pHead; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + + while (pPeerEntry != NULL) + { + if (RTMP_TIME_AFTER(now_time, pPeerEntry->receive_time + (30 * OS_HZ))) + { + pTempListEntry = pListEntry->pNext; + delEntryList(pWscEnList, pListEntry); + os_free_mem(pAd, pPeerEntry); + pListEntry = pTempListEntry; + } + else + pListEntry = pListEntry->pNext; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + } + + RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock); + return; +} + +VOID WscDelListEntryByMAC( + PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr) +{ + PLIST_ENTRY pListEntry = NULL; + pListEntry = (PLIST_ENTRY)WscFindPeerEntry(pWscEnList, pMacAddr); + if (pListEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscDelListEntryByMAC : pMacAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", PRINT_MAC(pMacAddr))); + delEntryList(pWscEnList, pListEntry); + os_free_mem(NULL, pListEntry); + } +} + +VOID WscAssignEntryMAC( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWpsCtrl) +{ + PWSC_PEER_ENTRY pPeerEntry = NULL; + + WscMaintainPeerList(pAd, pWpsCtrl); + + RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock); + pPeerEntry = (PWSC_PEER_ENTRY)pWpsCtrl->WscPeerList.pHead; + + NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN); + if (pPeerEntry) + { + NdisMoveMemory(pWpsCtrl->EntryAddr, pPeerEntry->mac_addr, MAC_ADDR_LEN); + } + RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock); +} + + +/* + Get WSC IE data from WSC Peer by Tag. +*/ +BOOLEAN WscGetDataFromPeerByTag( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pIeData, + IN INT IeDataLen, + IN USHORT WscTag, + OUT PUCHAR pWscBuf, + OUT PUSHORT pWscBufLen) +{ + PUCHAR pData = pIeData; + INT Len = 0; + USHORT DataLen = 0; + PWSC_IE pWscIE; + + Len = IeDataLen; + + while (Len > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + // Check for WSC IEs + pWscIE = &WscIE; + + if (be2cpu16(pWscIE->Type) == WscTag) + { + DataLen = be2cpu16(pWscIE->Length); + if (pWscBufLen) + *pWscBufLen = DataLen; + NdisMoveMemory(pWscBuf, pData + 4, DataLen); + return TRUE; + } + + // Set the offset and look for next WSC Tag information + // Since Type and Length are both short type, we need to offset 4, not 2 + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } + + return FALSE; +} + +#endif /* WSC_INCLUDED */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_tlv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_tlv.c new file mode 100644 index 000000000..a1794d8fb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_tlv.c @@ -0,0 +1,4670 @@ +/* + *************************************************************************** + * 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.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 06-08-08 Initial + JuemingChen 06-10-30 Do modifications and Add APIs for AP +*/ + +#include "rt_config.h" + +#ifdef WSC_INCLUDED +#include "wsc_tlv.h" + +static UCHAR Wsc_Personal_String[] = "Wi-Fi Easy and Secure Key Derivation"; + +#define IV_ENCR_DATA_LEN_512 512 +#define IV_ENCR_DATA_LEN_144 144 + +#define WSC_TLV_ENT(TLV_PARA) (0x00ff & TLV_PARA) +#define WSC_TLV_BYTE1(TLV_PARA) (0x000f & TLV_PARA) +#define WSC_TLV_BYTE2(TLV_PARA) (0x000f & (TLV_PARA >> 4)) + +/* Global reusable buffer */ +static WSC_TLV_0B wsc_tlv_0b[]= +{ + {/*0,*/0}, + /*AP Channel*/ {/*0x1001,*/ 2}, /* WSC_ID_AP_CHANNEL */ + /*Association State*/ {/*0x1002,*/ 2}, /* WSC_ID_ASSOC_STATE */ + /*Authentication Type*/ {/*0x1003,*/ 2}, /* WSC_ID_AUTH_TYPE */ + /*Authentication Type Flags*/ {/*0x1004,*/ 2}, /* WSC_ID_AUTH_TYPE_FLAGS */ + /*Authenticator*/ {/*0x1005,*/ 8}, /* WSC_ID_AUTHENTICATOR */ + {/*0,*/0}, + {/*0,*/0}, + /*Config Methods*/ {/*0x1008,*/ 2}, /* WSC_ID_CONFIG_METHODS */ + /*Configuration Error*/ {/*0x1009,*/ 2}, /* WSC_ID_CONFIG_ERROR */ + /*Confirmation URL4*/ {/*0x100A,*/ 0x40}, /* <= 64B WSC_ID_CONF_URL4 */ + /*Confirmation URL6*/ {/*0x100B,*/ 0x4C}, /* <= 76B WSC_ID_CONF_URL6 */ + /*Connection Type*/ {/*0x100C,*/ 1}, /* WSC_ID_CONN_TYPE */ + /*Connection Type Flags*/ {/*0x100D,*/ 1}, /* WSC_ID_CONN_TYPE_FLAGS */ + /*Credential*/ {/*0x100E,*/ 0xff}, /* WSC_ID_CREDENTIAL */ + /*Encryption Type*/ {/*0x100F,*/ 2}, /* WSC_ID_ENCR_TYPE */ + /*Encryption Type Flags*/ {/*0x1010,*/ 2}, /* WSC_ID_ENCR_TYPE_FLAGS */ + /*Device Name*/ {/*0x1011,*/ 0x20}, /* <= 32B WSC_ID_DEVICE_NAME */ + /*Device Password ID*/ {/*0x1012,*/ 2}, /* WSC_ID_DEVICE_PWD_ID */ + {/*0,*/0}, + /*E-Hash1*/ {/*0x1014,*/ 32}, /* WSC_ID_E_HASH1 */ + /*E-Hash2*/ {/*0x1015,*/ 32}, /* WSC_ID_E_HASH2 */ + /*E-SNonce1*/ {/*0x1016,*/ 16}, /* WSC_ID_E_SNONCE1 */ + /*E-SNonce2*/ {/*0x1017,*/ 16}, /* WSC_ID_E_SNONCE2 */ + /*Encrypted Settings*/ {/*0x1018,*/ 0xff}, /* WSC_ID_ENCR_SETTINGS */ + {/*0,*/0}, + /*Enrollee Nonce*/ {/*0x101A,*/ 16}, /* WSC_ID_ENROLLEE_NONCE */ + /*Feature_ID*/ {/*0x101B,*/ 4}, /* WSC_ID_FEATURE_ID */ + /*Identity*/ {/*0x101C,*/ 0x50}, /* <= 80B WSC_ID_IDENTITY */ + {/*0,*/0}, /* WSC_ID_IDENTITY_PROOF */ + /*Key Wrap Authenticator*/ {/*0x101E,*/ 8}, /* WSC_ID_KEY_WRAP_AUTH */ + /*Key Identifier*/ {/*0x101F,*/ 16}, /* WSC_ID_KEY_IDENTIFIER */ + /*MAC Address*/ {/*0x1020,*/ 6}, /* WSC_ID_MAC_ADDR */ + /*Manufacturer*/ {/*0x1021,*/ 0x40}, /* <= 64B WSC_ID_MANUFACTURER */ + /*Message Type*/ {/*0x1022,*/ 1}, /* WSC_ID_MSG_TYPE */ + /*Model Name*/ {/*0x1023,*/ 0x20}, /* <= 32B WSC_ID_MODEL_NAME */ + /*Model Number*/ {/*0x1024,*/ 0x20}, /* <= 32B WSC_ID_MODEL_NUMBER */ + {/*0,*/0}, + /*Network Index*/ {/*0x1026,*/ 1}, /* WSC_ID_NW_INDEX */ + + /* + Windows 7 WCN test only accept Len of Network Key item in credentail is zero + when auth type of AP is OPEN/NONE + */ + /*Network Key*/ {/*0x1027,*/ 0}, /* <= 64B WSC_ID_NW_KEY */ + + /*Network Key Index*/ {/*0x1028,*/ 1}, /* WSC_ID_NW_KEY_INDEX */ + /*New Device Name*/ {/*0x1029,*/ 0x20}, /* <= 32B WSC_ID_NEW_DEVICE_NAME */ + /*New Password*/ {/*0x102A,*/ 0x40}, /* <= 64B WSC_ID_NEW_PWD */ + {/*0,*/0}, + /*OOB Device Password*/ {/*0x102C,*/ 0x3A}, /* <= 58B WSC_ID_OOB_DEV_PWD */ + /*OS Version*/ {/*0x102D,*/ 4}, /* WSC_ID_OS_VERSION */ + {/*0,*/0}, + /*Power Level*/ {/*0x102F,*/ 1}, /* WSC_ID_POWER_LEVEL */ + /*PSK Current*/ {/*0x1030,*/ 1}, /* WSC_ID_PSK_CURRENT */ + /*PSK Max*/ {/*0x1031,*/ 1}, /* WSC_ID_PSK_MAX */ + /*Public Key*/ {/*0x1032,*/ 192}, /* WSC_ID_PUBLIC_KEY */ + /*Radio Enabled*/ {/*0x1033,*/ 1}, /* WSC_ID_RADIO_ENABLED */ + /*Reboot*/ {/*0x1034,*/ 1}, /* WSC_ID_REBOOT */ + /*Registrar Current*/ {/*0x1035,*/ 1}, /* WSC_ID_REGISTRAR_CURRENT */ + /*Registrar Established*/ {/*0x1036,*/ 1}, /* WSC_ID_REGISTRAR_ESTBLSHD */ + {/*0,*/0}, /* WSC_ID_REGISTRAR_LIST */ + /*Registrar Max*/ {/*0x1038,*/ 1}, /* WSC_ID_REGISTRAR_MAX */ + /*Registrar Nonce*/ {/*0x1039,*/ 16}, /* WSC_ID_REGISTRAR_NONCE */ + /*Request Type*/ {/*0x103A,*/ 1}, /* WSC_ID_REQ_TYPE */ + /*Response Type*/ {/*0x103B,*/ 1}, /* WSC_ID_RESP_TYPE */ + /*RF Bands*/ {/*0x103C,*/ 1}, /* WSC_ID_RF_BAND */ + /*R-Hash1*/ {/*0x103D,*/ 32}, /* WSC_ID_R_HASH1 */ + /*R-Hash2*/ {/*0x103E,*/ 32}, /* WSC_ID_R_HASH2 */ + /*R-SNonce1*/ {/*0x103F,*/ 16}, /* WSC_ID_R_SNONCE1 */ + /*R-SNonce2*/ {/*0x1040,*/ 16}, /* WSC_ID_R_SNONCE2 */ + /*Selected Registrar*/ {/*0x1041,*/ 1}, /* WSC_ID_SEL_REGISTRAR */ + /*Serial Number*/ {/*0x1042,*/ 0x20}, /* <= 32B WSC_ID_SERIAL_NUM */ + {/*0,*/0}, + /*Simple Config State*/ {/*0x1044,*/ 1}, /* WSC_ID_SC_STATE */ + /*SSID*/ {/*0x1045,*/ 0x20}, /* <= 32B WSC_ID_SSID */ + /*Total Networks*/ {/*0x1046,*/ 1}, /* WSC_ID_TOT_NETWORKS */ + /*UUID-E*/ {/*0x1047,*/ 16}, /* WSC_ID_UUID_E */ + /*UUID-R*/ {/*0x1048,*/ 16}, /* WSC_ID_UUID_R */ + /*WPS Vendor Extension*/ {/*0x1049,*/ 0x400}, /* WSC_ID_VENDOR_EXT */ + /*Version*/ {/*0x104A,*/ 1}, /* WSC_ID_VERSION */ + /*X.509 Certificate Request*/ {/*0x104B,*/ 0xff}, /* WSC_ID_X509_CERT_REQ */ + /*X.509 Certificate*/ {/*0x104C,*/ 0xff}, /* WSC_ID_X509_CERT */ + /*EAP Identity*/ {/*0x104D,*/ 0x40}, /* <= 64B WSC_ID_EAP_IDENTITY */ + /*Message Counter*/ {/*0x104E,*/ 8}, /* WSC_ID_MSG_COUNTER */ + /*Public Key Hash*/ {/*0x104F,*/ 20}, /* WSC_ID_PUBKEY_HASH */ + /*Rekey Key*/ {/*0x1050,*/ 32}, /* WSC_ID_REKEY_KEY */ + /*Key Lifetime*/ {/*0x1051,*/ 4}, /* WSC_ID_KEY_LIFETIME */ + /*Permitted Config Methods*/ {/*0x1052,*/ 2}, /* WSC_ID_PERM_CFG_METHODS */ + /*Selected Registrar Config Method*/{/*0x1053,*/ 2}, /* WSC_ID_SEL_REG_CFG_METHODS */ + /*Primary Device Type*/ {/*0x1054,*/ 8}, /* WSC_ID_PRIM_DEV_TYPE */ + {/*0,*/0}, /* WSC_ID_SEC_DEV_TYPE_LIST */ + /*Portable Device*/ {/*0x1056,*/ 1}, /* WSC_ID_PORTABLE_DEVICE */ + /*AP Setup Locked*/ {/*0x1057,*/ 1}, /* WSC_ID_AP_SETUP_LOCKED */ + {/*0,*/0}, /* WSC_ID_APP_LIST */ + /*EAP Type*/ {/*0x1059,*/ 0x08}, /* <= 8B WSC_ID_EAP_TYPE */ + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + /*Initialization Vector*/ {/*0x1060,*/ 32}, /* WSC_ID_INIT_VECTOR */ + /*Key Provided Automatically*/ {/*0x1061,*/ 1}, /* WSC_ID_KEY_PROVIDED_AUTO */ + /*802.1X Enabled*/ {/*0x1062,*/ 1}, /* WSC_ID_8021X_ENABLED */ +#ifdef IWSC_SUPPORT + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, + {/*0,*/0}, //A + {/*0,*/0}, //B + {/*0,*/0}, //C + /*Entry Acceptable (only for IBSS)*/ {/*0x106D,*/ 1}, //WSC_ID_ENTRY_ACCEPTABLE + /*Registration Ready (only for IBSS)*/{/*0x106E,*/ 1}, //WSC_ID_REGISTRATON_READY + /*Registrar IPv4 Address (only for IBSS)*/{/*0x106F,*/ 4}, //WSC_ID_REGISTRAR_IPV4 + /*IPv4 Subnet Mask (only for IBSS)*/{/*0x1070,*/ 4}, //WSC_ID_IPV4_SUBMASK + /*Enrollee IPv4 Address (only for IBSS)*/{/*0x1071,*/ 4}, //WSC_ID_ENROLLEE_IPV4 + /*Available IPv4 Submask List (only for IBSS)*/{/*0x1072,*/ 0}, //WSC_ID_IPV4_SUBMASK_LIST (N*4B) + /*IP Address Configuration Methods (only for IBSS)*/{/*0x1073,*/ 2},//WSC_ID_IP_ADDR_CONF_METHOD +#endif // IWSC_SUPPORT // + /* 0x106F V 0x1FFF*/ + /* 0x000 V 0x0FFF,0x2000 V 0xFFFF*/ +}; + +extern UINT8 WPS_DH_G_VALUE[1]; +extern UINT8 WPS_DH_P_VALUE[192]; + +int AppendWSCTLV(USHORT index, OUT UCHAR * obuf, IN UCHAR * ibuf, IN USHORT varlen) +{ + USHORT len, dataLen, tag = cpu2be16(index); + + /* + The max len of WPS Vendor Extension is 1024B + */ + dataLen = ( varlen != (USHORT)0 ) ? varlen : wsc_tlv_0b[WSC_TLV_ENT(index)].len; + + NdisMoveMemory(obuf, &tag, 2); + len = cpu2be16(dataLen); + memcpy(obuf + 2, &len, 2); + if (dataLen != 0) + memcpy(obuf + 4, ibuf, dataLen); + return (dataLen + 4); +} + +/* + ======================================================================== + + Routine Description: + Process elements encryption settings + + Arguments: + pAdapter - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + 1. Recv M4 M5 M6 M7 + + ======================================================================== +*/ +static VOID WscParseEncrSettings( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPlainData, + IN INT PlainLength, + IN PWSC_CTRL pWscControl) +{ + USHORT WscType, WscLen, HmacLen; + PUCHAR pData; + UCHAR Hmac[8], Temp[32]; + UCHAR *pTmp; + USHORT Idx = 0, tmpVal = 0; + /* Point to M7 Profile */ + PWSC_PROFILE pProfile = &pWscControl->WscM7Profile; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + if(pProfile == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s: ---> pProfile is NULL\n",__FUNCTION__)); + if(pReg == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s: ---> pReg is NULL\n",__FUNCTION__)); + + HmacLen = (USHORT)(PlainLength - 12); + pData = pPlainData; + + /* Start to process WSC IEs */ + while (PlainLength > 4) + { + WSC_IE TLV_Encr; + memcpy((UINT8 *)&TLV_Encr, pData, 4); + WscType = be2cpu16(TLV_Encr.Type); + WscLen = be2cpu16(TLV_Encr.Length); + pData += 4; + PlainLength -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_E_SNONCE1: + /* for verification with our enrollee nonce */ + if(pReg) + NdisMoveMemory(pReg->Es1, pData, WscLen); + break; + + case WSC_ID_E_SNONCE2: + /* for verification with our enrollee nonce */ + if(pReg) + NdisMoveMemory(pReg->Es2, pData, WscLen); + break; + + case WSC_ID_R_SNONCE1: + /* for verification with our enrollee nonce */ + if(pReg) + NdisMoveMemory(pReg->Rs1, pData, WscLen); + break; + + case WSC_ID_R_SNONCE2: + /* for verification with our enrollee nonce */ + if(pReg) + NdisMoveMemory(pReg->Rs2, pData, WscLen); + break; + + case WSC_ID_KEY_WRAP_AUTH: + NdisMoveMemory(Hmac, pData, WscLen); + break; + + /* */ + /* Parse AP Settings in M7 if the peer is configured AP. */ + /* */ + case WSC_ID_SSID: + /* Find the exact length of SSID without null terminator */ + pTmp = pData; + for (Idx = 0; Idx < WscLen; Idx++) + { + if (*(pTmp++) == 0x0) + break; + } + if(pProfile) + { + pProfile->Profile[0].SSID.SsidLength = Idx; + RTMPMoveMemory(pProfile->Profile[0].SSID.Ssid, pData, pProfile->Profile[0].SSID.SsidLength); + /* Svae the total number, always get the first profile */ + pProfile->ProfileCnt = 1; + } + break; + + case WSC_ID_MAC_ADDR: + if (pReg && !MAC_ADDR_EQUAL(pData, pReg->SelfInfo.MacAddr)) + DBGPRINT(RT_DEBUG_TRACE, ("WscParseEncrSettings --> Enrollee macAddr not match\n")); + if(pProfile) + RTMPMoveMemory(pProfile->Profile[0].MacAddr, pData, 6); + break; + + case WSC_ID_AUTH_TYPE: + tmpVal = get_unaligned((PUSHORT) pData); + if(pProfile) + pProfile->Profile[0].AuthType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData)); */ + break; + + case WSC_ID_ENCR_TYPE: + tmpVal = get_unaligned((PUSHORT) pData); + if(pProfile) + pProfile->Profile[0].EncrType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData)); */ + break; + + case WSC_ID_NW_KEY_INDEX: + /* Netork Key Index: 1 ~ 4 */ + if(pProfile) + pProfile->Profile[0].KeyIndex = (*pData); + break; + + case WSC_ID_NW_KEY: + if (WscLen == 0) + break; + if(pProfile) + { + pProfile->Profile[0].KeyLength = WscLen; + RTMPMoveMemory(pProfile->Profile[0].Key, pData, pProfile->Profile[0].KeyLength); + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscParseEncrSettings --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + PlainLength -= WscLen; + } + /* Validate HMAC, reuse KDK buffer */ + if(pReg) + RT_HMAC_SHA256(pReg->AuthKey, 32, pPlainData, HmacLen, Temp, SHA256_DIGEST_SIZE); + + if (RTMPEqualMemory(Hmac, Temp, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("WscParseEncrSettings --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Temp[0])), (UINT)cpu2be32(*((PUINT) &Temp[4])))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + } +} + +/* + ======================================================================== + + Routine Description: + Process credentials within AP encryption settings + + Arguments: + pAdapter - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + 1. Recv M8 + + ======================================================================== +*/ +#ifdef WSC_NFC_SUPPORT +BOOLEAN WscProcessCredential( +#else +static BOOLEAN WscProcessCredential( +#endif + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPlainData, + IN INT PlainLength, + IN PWSC_CTRL pWscControl) +{ + USHORT WscType, WscLen, Cnt = 0, CurrentIdx=0, Idx, tmpVal = 0; + PUCHAR pData, pTmp; + PWSC_PROFILE pProfile; +#ifdef WSC_V2_SUPPORT + BOOLEAN bReject = FALSE; +#endif /* WSC_V2_SUPPORT */ +#ifdef IWSC_SUPPORT + UINT32 IPv4Addr = 0, IPv4SubMask = 0; + PIWSC_INFO pIWscInfo = &pAdapter->StaCfg.IWscInfo; +#endif /* IWSC_SUPPORT */ + + pData = pPlainData; + + /* Cleanup Old contents */ + NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE)); + + pProfile = (PWSC_PROFILE) &pWscControl->WscProfile; + /*CurrentIdx = pWscControl->EntryIfIdx; */ + + /* Init Profile number */ + Cnt = 0; + + hex_dump("WscProcessCredential - PlainData", pPlainData, PlainLength); + /* Start to process WSC IEs within credential */ + 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_NW_INDEX: + /* A new profile, add the cnt and save to database */ + CurrentIdx = Cnt; /* since the index start from 0, we have to minus 1 */ + Cnt++; + break; + + case WSC_ID_SSID: + /* Find the exact length of SSID without null terminator */ + pTmp = pData; + for (Idx = 0; Idx < WscLen; Idx++) + { + if (*(pTmp++) == 0x0) + break; + } + pProfile->Profile[CurrentIdx].SSID.SsidLength = Idx; + if (RTMPCheckStrPrintAble((CHAR *)pData, Idx) || (pWscControl->bCheckMultiByte == FALSE)) + NdisMoveMemory(pProfile->Profile[CurrentIdx].SSID.Ssid, pData, pProfile->Profile[CurrentIdx].SSID.SsidLength); + else + return FALSE; + break; + + case WSC_ID_AUTH_TYPE: + tmpVal = get_unaligned((PUSHORT) pData); + pProfile->Profile[CurrentIdx].AuthType = cpu2be16(tmpVal); /*cpu2be16(*((PUSHORT) pData));//(UINT8 *)&pReg->RegistrarInfo.AuthTypeFlags */ + break; + + case WSC_ID_ENCR_TYPE: + tmpVal = get_unaligned((PUSHORT) pData); + pProfile->Profile[CurrentIdx].EncrType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData));//(UINT8 *)&pReg->RegistrarInfo.EncrTypeFlags */ + break; + + case WSC_ID_NW_KEY_INDEX: + /* Netork Key Index: 1 ~ 4 */ + pProfile->Profile[CurrentIdx].KeyIndex = (*pData); + break; + + case WSC_ID_NW_KEY: + if (WscLen == 0) + break; + + if (RTMPCheckStrPrintAble((CHAR *)pData, WscLen) || (pWscControl->bCheckMultiByte == FALSE)) + { + pProfile->Profile[CurrentIdx].KeyLength = WscLen; + RTMPZeroMemory(pProfile->Profile[CurrentIdx].Key, 65); + NdisMoveMemory(pProfile->Profile[CurrentIdx].Key, pData, pProfile->Profile[CurrentIdx].KeyLength); + } + else + return FALSE; + break; + + case WSC_ID_MAC_ADDR: + /* + Some AP (ex. Buffalo WHR-G300N WPS AP) would change BSSID during WPS processing. + STA shall not change MacAddr of credential form AP. + */ + RTMPMoveMemory(pProfile->Profile[CurrentIdx].MacAddr, pData, MAC_ADDR_LEN); + break; + + case WSC_ID_KEY_WRAP_AUTH: + /* Not used here, since we already verify it at decryption */ + break; + + case WSC_ID_CREDENTIAL: + /* Credential IE, The WscLen include all length within profile, we need to modify it */ + /* to be able to parse all profile fields */ + WscLen = 0; + break; + +#ifdef IWSC_SUPPORT + case WSC_ID_IP_ADDR_CONF_METHOD: + tmpVal = get_unaligned((PUSHORT) pData); + pProfile->Profile[CurrentIdx].IpConfigMethod = be2cpu16(tmpVal); + break; + case WSC_ID_REGISTRAR_IPV4: + IPv4Addr = get_unaligned((PUINT32) pData); + pProfile->Profile[CurrentIdx].RegIpv4Addr = be2cpu32(IPv4Addr); + if (CurrentIdx == 0) + pIWscInfo->RegIpv4Addr = pProfile->Profile[CurrentIdx].RegIpv4Addr; + pIWscInfo->RegDepth = 1; + pIWscInfo->IpDevCount = 0; + break; + case WSC_ID_IPV4_SUBMASK: + IPv4SubMask = get_unaligned((PUINT32) pData); + pProfile->Profile[CurrentIdx].Ipv4SubMask = be2cpu32(IPv4SubMask); + if (pProfile->Profile[CurrentIdx].Ipv4SubMask!= IWSC_DEFAULT_IPV4_SUBMASK) + DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> different IPv4 subnet mask (=0x%08x)\n", + pProfile->Profile[CurrentIdx].Ipv4SubMask)); + break; + case WSC_ID_ENROLLEE_IPV4: + IPv4Addr = get_unaligned((PUINT32) pData); + pProfile->Profile[CurrentIdx].EnrIpv4Addr = be2cpu32(IPv4Addr); + if (CurrentIdx == 0) + pIWscInfo->SelfIpv4Addr = pProfile->Profile[CurrentIdx].EnrIpv4Addr; + break; + case WSC_ID_IPV4_SUBMASK_LIST: + NdisZeroMemory(&pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[0], sizeof(pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList)); + if ((WscLen == 0) || + (WscLen == 4) || + ((WscLen%4) != 0)) + { + pIWscInfo->AvaSubMaskListCount = 0; + pIWscInfo->bAssignWscIPv4 = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> WscLen = %d, set AvaSubMaskListCount to be 0\n", WscLen)); + } + else + { + UINT8 i = 0, AvaSubMaskListCount; + + AvaSubMaskListCount = (UINT8)((WscLen/4) - 1); + for (i = 0; i < AvaSubMaskListCount; i++) + { + pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[i] = be2cpu32(get_unaligned((PUINT32) (pData + i + 1))); + } + + pIWscInfo->bAssignWscIPv4 = TRUE; + if (CurrentIdx == 0) + { + pIWscInfo->CurrentIpRange = be2cpu32(get_unaligned((PUINT32) pData)); + pIWscInfo->AvaSubMaskListCount = (UINT8)AvaSubMaskListCount; + NdisZeroMemory(pIWscInfo->AvaSubMaskList, sizeof(pIWscInfo->AvaSubMaskList)); + NdisMoveMemory( &pIWscInfo->AvaSubMaskList[0], + &pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[0], + sizeof(pIWscInfo->AvaSubMaskList)); + } + pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[AvaSubMaskListCount] = pIWscInfo->CurrentIpRange; + } + break; +#endif /* IWSC_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + PlainLength -= WscLen; + } + + /* Svae the total number */ + pProfile->ProfileCnt = (UINT)Cnt; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* + Check all credentials + */ + for (Idx = 0; Idx < pProfile->ProfileCnt; Idx++) + { + PWSC_CREDENTIAL pCredential = &pProfile->Profile[Idx]; + /*if ((pCredential->EncrType != WSC_ENCRTYPE_WEP) && (pCredential->EncrType != WSC_ENCRTYPE_TKIP)) */ + if (pCredential->EncrType == WSC_ENCRTYPE_WEP) + { + bReject = TRUE; + /* Cleanup contents */ + NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE)); + } + } + + if (bReject) + return FALSE; + } +#endif /* WSC_V2_SUPPORT */ + + + DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> %d profile retrieved from credential\n", Cnt)); + return TRUE; +} + +/* return 0 to success ,1 to failed */ +int WscDeriveKey ( + unsigned char *kdk, unsigned int kdk_len, + unsigned char *prsnlString, unsigned int str_len, + unsigned char *key, unsigned int keyBits ) +{ + unsigned int i = 0, iterations = 0; + unsigned char input[64], output[128]; + unsigned char hmac[32]; + unsigned int temp; + + iterations = ((keyBits/8) + 32 - 1)/32; + + /*Prepare the input buffer. During the iterations, we need only replace the */ + /*value of i at the start of the buffer. */ + temp = cpu2be32(i); + memcpy(input, &temp, 4); + memcpy(input+4, prsnlString, str_len); + + temp = cpu2be32(keyBits); + memcpy(input+4+str_len, &temp, 4); + + for(i = 0; i < iterations; i++) + { + /*Set the current value of i at the start of the input buffer */ + temp = cpu2be32(i+1); /*i should start at 1 */ + memcpy(input,&temp,4); + RT_HMAC_SHA256(kdk, kdk_len, input, 4+str_len+4, hmac, SHA256_DIGEST_SIZE); + memcpy(output+i*32, hmac, 32); + } + + /*Sanity check */ + if(keyBits/8 > (32*iterations)) + { + + return 1; /*failed */ + } + + memcpy(key, output, 80); + + return 0; /*success */ + +} + +VOID WscGenPSK1( + PRTMP_ADAPTER pAd, + PWSC_CTRL pWscCtrl, + UCHAR *pPSK1) +{ + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData; + PUCHAR pTempPsk = NULL; +#ifdef WSC_NFC_SUPPORT + PUCHAR pTempPasswd = NULL; + UCHAR idx; +#endif /* WSC_NFC_SUPPORT */ + + os_alloc_mem(NULL, &pTempPsk, SHA256_DIGEST_SIZE); + if (pTempPsk == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - pTempPsk alloc failed.", __FUNCTION__)); + return; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscCtrl->bTriggerByNFC) + { + hex_dump("WscGenPSK1 1 - NfcPasswd", &pWscCtrl->NfcPasswd[0], pWscCtrl->NfcPasswdLen/2); + hex_dump("WscGenPSK1 - pReg->AuthKey", pReg->AuthKey, 32); + os_alloc_mem(NULL, &pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pTempPasswd) + { + NdisZeroMemory(pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pWscCtrl->NfcPasswdCaculate == 2) + { + for (idx = 0; idx < (pWscCtrl->NfcPasswdLen/2); idx++) + sprintf((PSTRING) pTempPasswd, "%s%02X", pTempPasswd, pWscCtrl->NfcPasswd[idx]); + RT_HMAC_SHA256(pReg->AuthKey, 32, pTempPasswd, pWscCtrl->NfcPasswdLen, pTempPsk, SHA256_DIGEST_SIZE); + } + else + { + RT_HMAC_SHA256(pReg->AuthKey, 32, pWscCtrl->NfcPasswd, pWscCtrl->NfcPasswdLen/2, pTempPsk, SHA256_DIGEST_SIZE); + } + + os_free_mem(NULL, pTempPasswd); + } + } + else +#endif /* WSC_NFC_SUPPORT */ + { + DBGPRINT(RT_DEBUG_OFF, ("sn - PinCodeLen = %d\n", pReg->PinCodeLen)); //snowpin test + hex_dump("WscGenPSK1: PIN", pReg->PIN, 8); //snowpin test + // Generate PSK1 + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[0], 2, pTempPsk, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[0], 4, pTempPsk, SHA256_DIGEST_SIZE); + } + NdisMoveMemory(pPSK1, pTempPsk, SHA256_DIGEST_SIZE); + os_free_mem(NULL, pTempPsk); +} + +VOID WscGenPSK2( + PRTMP_ADAPTER pAd, + PWSC_CTRL pWscCtrl, + UCHAR *pPSK2) +{ + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData; + PUCHAR pTempPsk = NULL; +#ifdef WSC_NFC_SUPPORT + PUCHAR pTempPasswd = NULL; + UCHAR idx; +#endif /* WSC_NFC_SUPPORT */ + + os_alloc_mem(NULL, &pTempPsk, SHA256_DIGEST_SIZE); + if (pTempPsk == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - pTempPsk alloc failed.", __FUNCTION__)); + return; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscCtrl->bTriggerByNFC) + { + hex_dump("WscGenPSK2 1 - NfcPasswd", &pWscCtrl->NfcPasswd[pWscCtrl->NfcPasswdLen/2], pWscCtrl->NfcPasswdLen/2); + hex_dump("WscGenPSK2 - pReg->AuthKey", pReg->AuthKey, 32); + os_alloc_mem(NULL, &pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pTempPasswd) + { + NdisZeroMemory(pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pWscCtrl->NfcPasswdCaculate == 2) + { + for (idx = (pWscCtrl->NfcPasswdLen/2); idx < pWscCtrl->NfcPasswdLen; idx++) + sprintf((PSTRING) pTempPasswd, "%s%02X", pTempPasswd, pWscCtrl->NfcPasswd[idx]); + RT_HMAC_SHA256(pReg->AuthKey, 32, pTempPasswd, pWscCtrl->NfcPasswdLen, pTempPsk, SHA256_DIGEST_SIZE); + } + else + { + RT_HMAC_SHA256(pReg->AuthKey, 32, &pWscCtrl->NfcPasswd[pWscCtrl->NfcPasswdLen/2], pWscCtrl->NfcPasswdLen/2, pTempPsk, SHA256_DIGEST_SIZE); + } + os_free_mem(NULL, pTempPasswd); + } + } + else +#endif /* WSC_NFC_SUPPORT */ + { + // Generate PSK2 + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, pTempPsk, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, pTempPsk, SHA256_DIGEST_SIZE); + } + NdisMoveMemory(pPSK2, pTempPsk, SHA256_DIGEST_SIZE); + os_free_mem(NULL, pTempPsk); +} + + +/* + ======================================================================== + + Routine Description: + Build WSC M1 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx EAP-Req(ID) + 1. Change the correct parameters + 2. Build M1 + + ======================================================================== +*/ +int BuildMessageM1( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[1]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + INT idx; + USHORT ConfigError = 0, ConfigMethods = 0; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + UCHAR CurOpMode = 0xFF; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + + // Enrollee 16 byte E-S1 generation + for (idx = 0; idx < 16; idx++) + { + pReg->Es1[idx] = RandomByte(pAdapter); + } + + // Enrollee 16 byte E-S2 generation + for (idx = 0; idx < 16; idx++) + { + pReg->Es2[idx] = RandomByte(pAdapter); + } + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M1 */ + TB[0] = WSC_ID_MESSAGE_M1; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. UUID_E, last 6 bytes use MAC */ + /*templen = AppendWSCTLV(WSC_ID_UUID_E, pData, pReg->EnrolleeInfo.Uuid, 0); */ + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWscControl->Wsc_Uuid_E[0], 0); + pData += templen; + Len += templen; + + /* 4. MAC address */ + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pReg->SelfInfo.MacAddr, 0); + pData += templen; + Len += templen; + + /* Enrollee Nonce, first generate and save to Wsc Control Block */ + for (idx = 0; idx < 16; idx++) + { + pReg->SelfNonce[idx] = RandomByte(pAdapter); + pReg->EnrolleeNonce[idx] = pReg->SelfNonce[idx]; + } + /* 5. Enrollee Nonce, first generate and save to Wsc Control Block */ + NdisMoveMemory(pReg->EnrolleeNonce, pReg->SelfNonce, 16); + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->SelfNonce, 0); + pData += templen; + Len += templen; + + /* 6. Public Key, 192 bytes */ + templen = AppendWSCTLV(WSC_ID_PUBLIC_KEY, pData, pReg->Pke, 0); + pData += templen; + Len += templen; + + /* 7. Authentication Type Flags */ + templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0); + pData += templen; + Len += templen; + + /* 8. Encryption Type Flags */ + templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0); + pData += templen; + Len += templen; + + /* 9. Connection Type Flag ESS */ + templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + + /*10. Config Method */ + /*pReg->SelfInfo.ConfigMethods = cpu2be16(pWscControl->WscConfigMethods);*/ + ConfigMethods = pWscControl->WscConfigMethods; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + +#ifdef IWSC_SUPPORT + if ((pWscControl->WscMode == WSC_PIN_MODE) && + (pAdapter->StaCfg.BssType == BSS_ADHOC)) + { + if (pAdapter->StaCfg.IWscInfo.bLimitedUI) + { + ConfigMethods &= (~WSC_CONFMET_KEYPAD); + } + else + { + ConfigMethods |= WSC_CONFMET_KEYPAD; + } + } +#endif /* IWSC_SUPPORT */ + } + else +#endif /* WSC_V2_SUPPORT */ + { + /* + WSC 1.0 WCN logo testing has AP PBC Enrollee testing item. + We cannot remove PBC capability here. + */ + ConfigMethods = (pWscControl->WscConfigMethods & 0x00FF); + } + + ConfigMethods = cpu2be16(ConfigMethods); + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&ConfigMethods, 0); + pData += templen; + Len += templen; + + /*11. Simple Config State (Not Configured) */ + if (CurOpMode == AP_MODE) + pReg->SelfInfo.ScState = pWscControl->WscConfStatus; + templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&pReg->SelfInfo.ScState, 0); + pData += templen; + Len += templen; + + /*12. Manufacture */ + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /*13. Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /*14. Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /*15. Serial Number */ + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber)); + pData += templen; + Len += templen; + + /*16. Primary Device Type */ + templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0); + pData += templen; + Len += templen; + + /*17. Device Name */ + templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /*18. RF Band */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /*19. Associate state (Not associated) */ + templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0); + pData += templen; + Len += templen; + + /*20. Device Password ID */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pWscControl->NfcPasswdID, 0); + } + else +#endif /* WSC_NFC_SUPPORT */ + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0); + pData += templen; + Len += templen; + + /*21. Configure Error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0); + pData += templen; + Len += templen; + + /*22. OS Version Not associated) */ + templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + + +#ifdef WSC_V2_SUPPORT + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscControl->WscV2Info.bEnableWpsV2 && pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } +#endif /* WSC_V2_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1 - bUPnPMsgTimerRunning = %d, pWscControl->WscUseUPnP = %d, pWscControl->EapMsgRunning = %d\n", + pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning, + pWscControl->WscUseUPnP, + pWscControl->EapMsgRunning)); + + /* Fixed WCN vista logo 2 registrar test item issue. */ + /* Also prevent that WCN GetDeviceInfo disturbs EAP processing. */ + if (pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning || + (pWscControl->WscUseUPnP && pWscControl->EapMsgRunning)) + ; + else + { + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + } + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1.\n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M2 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M1 + 1. Change the correct parameters + 2. Build M2 + + ======================================================================== +*/ +int BuildMessageM2( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ +#ifdef WSC_NFC_SUPPORT + UCHAR TB[256]; +#else + UCHAR TB[1]; +#endif + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg; + UCHAR DHKey[32], KDK[32], KdkInput[38], KdfKey[80]; + INT DH_Len; + INT HmacLen = 0; + INT idx; + USHORT ConfigMethods; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + // Enrollee 16 byte E-S1 generation + for (idx = 0; idx < 16; idx++) + { + pReg->Es1[idx] = RandomByte(pAdapter); + } + + // Enrollee 16 byte E-S2 generation + for (idx = 0; idx < 16; idx++) + { + pReg->Es2[idx] = RandomByte(pAdapter); + } + + DH_Len = sizeof(pReg->SecretKey); + NdisZeroMemory(pReg->SecretKey, sizeof(pReg->SecretKey)); + RT_DH_SecretKey_Generate ( + pReg->Pke, sizeof(pReg->Pke), + WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE), + pReg->EnrolleeRandom, sizeof(pReg->EnrolleeRandom), + pReg->SecretKey, (UINT *) &DH_Len); + + /* Need to prefix zero padding */ + if((DH_Len != sizeof(pReg->SecretKey)) && + (DH_Len < sizeof(pReg->SecretKey))) + { + UCHAR TempKey[192]; + INT DiffCnt; + DiffCnt = sizeof(pReg->SecretKey) - DH_Len; + + NdisFillMemory(&TempKey, DiffCnt, 0); + NdisCopyMemory(&TempKey[DiffCnt], pReg->SecretKey, DH_Len); + NdisCopyMemory(pReg->SecretKey, TempKey, sizeof(TempKey)); + DH_Len += DiffCnt; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Do zero padding!\n", __func__)); + } + + RT_SHA256(&pReg->SecretKey[0], 192, &DHKey[0]); + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M2 */ + TB[0] = WSC_ID_MESSAGE_M2; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* fixed config Windows 7 issue */ + /* Enrollee Nonce, first generate and save to Wsc Control Block */ + for (idx = 0; idx < 16; idx++) + { + pReg->SelfNonce[idx] = RandomByte(pAdapter); + pReg->RegistrarNonce[idx] = pReg->SelfNonce[idx]; + } + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + + /* UUID, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0); + pData += templen; + Len += templen; + + /* Publikc Key */ + templen = AppendWSCTLV(WSC_ID_PUBLIC_KEY, pData, pReg->Pkr, 0); + pData += templen; + Len += templen; + + /* Authentication Type Flags */ + templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0); + pData += templen; + Len += templen; + + /* Encrypt Type */ + templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0); + pData += templen; + Len += templen; + + /* Connection Type */ + templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + + /* Config Method */ + ConfigMethods = pWscControl->WscConfigMethods; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* + In WPS 2.0.0 + In Test Item 4.1.1 ,Step 13 + On the sniffer device, verify that the M2 message that the APUT sends includes + the Configuration Methods attribute. The Configuration Methods attribute in the + WSC IE must reflect the correct configuration methods that the Internal Registrar + supports. + */ +#ifdef IWSC_SUPPORT + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + { + if (pAdapter->StaCfg.IWscInfo.bLimitedUI) + { + ConfigMethods &= (~WSC_CONFMET_KEYPAD); + } + else + { + ConfigMethods |= WSC_CONFMET_KEYPAD; + } + } +#endif /* IWSC_SUPPORT */ + } + else + { + ConfigMethods = (pWscControl->WscConfigMethods & 0x00FF); + } +#endif /* WSC_V2_SUPPORT */ + ConfigMethods = cpu2be16(ConfigMethods); + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&ConfigMethods, 0); + pData += templen; + Len += templen; + + /* Manufacture Name */ + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* Serial Number */ + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber)); + pData += templen; + Len += templen; + + /* Prime Device Type */ + templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0); + pData += templen; + Len += templen; + + /* Device Name */ + templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* RF Band */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /* Assoc State */ + templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0); + pData += templen; + Len += templen; + + /* Config Error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0); + pData += templen; + Len += templen; + + /* Device Password ID */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pWscControl->PeerNfcPasswdID, 0); + } + else +#endif /* WSC_NFC_SUPPORT */ + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0); + pData += templen; + Len += templen; + + /* OS Version */ + templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0); + pData += templen; + Len += templen; + + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* Create KDK input data */ + NdisMoveMemory(&KdkInput[0], &pReg->EnrolleeNonce[0], 16); + NdisMoveMemory(&KdkInput[16], &pReg->PeerInfo.MacAddr[0], 6); + NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16); + + /* Generate the KDK */ + RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE); + + /* KDF */ + WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640); + + /* Assign Key from KDF */ + NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32); + NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16); + NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32); + +#ifdef WSC_NFC_SUPPORT +#ifdef CONFIG_AP_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + PWSC_CREDENTIAL pCredential = NULL; + INT CerLen = 0, PlainLen = 0, EncrLen; + USHORT AuthType = 0; + USHORT EncrType = 0; + UCHAR Plain[300], *IV_EncrData; + + IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG); + if(IV_EncrData) + { + WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile); + pCredential = &pAdapter->ApCfg.MBSSID[0].WscControl.WscProfile.Profile[0]; + + // 4a. Encrypted R-S1 + 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], pCredential->MacAddr, 0); + + // Prepare plain text + // Reguired attribute item in M8 if Enrollee is STA. + if (pAdapter->OpMode == OPMODE_AP) + PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen); + + // Generate HMAC + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + // 4b. Encrypted Settings + // Encrypt data + EncrLen = sizeof(IV_EncrData) - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);//IVLen + EncrLen + pData += templen; + Len += templen; + + kfree(IV_EncrData); + } + } +#endif // CONFIG_AP_SUPPORT // +#endif /* WSC_NFC_SUPPORT */ + + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + /* 22. Hmac */ + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2.\n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M2D Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M1 process Error + 1. Change the correct parameters + 2. Build M2D + + ======================================================================== +*/ +int BuildMessageM2D( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[1]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M2D */ + TB[0] = WSC_ID_MESSAGE_M2D; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->SelfNonce, 0); + /*templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); */ + pData += templen; + Len += templen; + + /* UUID, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0); + pData += templen; + Len += templen; + + + /* 7. Authentication Type Flags */ + templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0); + pData += templen; + Len += templen; + + /* Encrypt Type */ + templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0); + pData += templen; + Len += templen; + + /* Connection Type */ + templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + + /* Config Methods */ + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&pReg->SelfInfo.ConfigMethods, 0); + pData += templen; + Len += templen; + + /* Manufacturer Name */ + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* Serial Number */ + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber)); + pData += templen; + Len += templen; + + /* Prime Device Type */ + templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0); + pData += templen; + Len += templen; + + /* Device Name */ + templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* RF Band */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /* Assoc State */ + templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0); + pData += templen; + Len += templen; + + /* Config Error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0); + pData += templen; + Len += templen; + + /* OS Version */ + templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0); + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2D.\n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M3 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M2 + 1. Change the correct parameters + 2. Build M3 + + ======================================================================== +*/ +int BuildMessageM3( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[32]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg = NULL; + INT HmacLen; + UCHAR *pHash=NULL; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + +/* pHash = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pHash, 512); + if(NULL == pHash) + return Len; + pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M3 */ + TB[0] = WSC_ID_MESSAGE_M3; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + + /* 4. E-Hash1 */ + /* */ + /* Generate PSK1 */ + WscGenPSK1(pAdapter, pWscControl, &TB[0]); + + /* Copy first 16 bytes to PSK1 */ + NdisMoveMemory(pReg->Psk1, TB, 16); + + hex_dump("Es1", pReg->Es1, 16); + hex_dump("Es2", pReg->Es2, 16); + + /* Create input for E-Hash1 */ + NdisMoveMemory(pHash, pReg->Es1, 16); + NdisMoveMemory(pHash + 16, pReg->Psk1, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate E-Hash1 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash1, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_E_HASH1, pData, pReg->EHash1, 0); + pData += templen; + Len += templen; + + /* 5. E-Hash2 */ + /* */ + /* Generate PSK2 */ + WscGenPSK2(pAdapter, pWscControl, &TB[0]); + /* Copy first 16 bytes to PSK2 */ + NdisMoveMemory(pReg->Psk2, TB, 16); + + /* Create input for E-Hash2 */ + NdisMoveMemory(pHash, pReg->Es2, 16); + NdisMoveMemory(pHash + 16, pReg->Psk2, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate E-Hash2 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash2, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_E_HASH2, pData, pReg->EHash2, 0); + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* + Generate authenticator + Combine last TX & RX message contents and validate the HMAC + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + if(NULL != pHash) +/* kfree(pHash); */ + os_free_mem(NULL, pHash); + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM3 : \n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M4 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M3 + 1. Change the correct parameters + 2. Build M4 + + ======================================================================== +*/ +int BuildMessageM4( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[32]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + INT HmacLen; + UCHAR KDK[32]; + UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */ + UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */ + INT PlainLen = 0, EncrLen; + UCHAR *pHash=NULL; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + +/* pHash = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pHash, 512); + if(NULL == pHash) + return Len; + + os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144); + if (IV_EncrData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M4 */ + TB[0] = WSC_ID_MESSAGE_M4; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. R-Hash1 */ + /* */ + /* Generate PSK1 */ + WscGenPSK1(pAdapter, pWscControl, &TB[0]); + + /* Copy first 16 bytes to PSK1 */ + NdisMoveMemory(pReg->Psk1, TB, 16); + + hex_dump("Es1", pReg->Es1, 16); + hex_dump("Es2", pReg->Es2, 16); + /* Create input for R-Hash1 */ + NdisMoveMemory(pHash, pReg->Es1, 16); + NdisMoveMemory(pHash + 16, pReg->Psk1, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate R-Hash1 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash1, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_R_HASH1, pData, pReg->RHash1, 0); + pData += templen; + Len += templen; + + /* 5. R-Hash2 */ + /* */ + /* Generate PSK2 */ + WscGenPSK2(pAdapter, pWscControl, &TB[0]); + + /* Copy first 16 bytes to PSK2 */ + NdisMoveMemory(pReg->Psk2, TB, 16); + + /* Create input for R-Hash2 */ + NdisMoveMemory(pHash, pReg->Es2, 16); + NdisMoveMemory(pHash + 16, pReg->Psk2, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate R-Hash2 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash2, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_R_HASH2, pData, pReg->RHash2, 0); + pData += templen; + Len += templen; + + /* 6a. Encrypted R-S1 */ + /* Prepare plain text */ + PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE1, &Plain[0], pReg->Es1, 0); + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 6b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = IV_ENCR_DATA_LEN_144 - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */ + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* + Combine last TX & RX message contents and validate the HMAC + We have to exclude last 12 bytes from last receive since it's authenticator value + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + +LabelErr: + if(NULL != pHash) +/* kfree(pHash); */ + os_free_mem(NULL, pHash); + + pWscControl->WscRetryCount = 0; + + if (IV_EncrData != NULL) + os_free_mem(NULL, IV_EncrData); + + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM4 : \n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M5 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M4 + 1. Change the correct parameters + 2. Build M5 + + ======================================================================== +*/ +int BuildMessageM5( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[32]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + PUCHAR pAuth; + INT HmacLen; + UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */ + UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */ + INT PlainLen=0, EncrLen; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144); + if (IV_EncrData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return 0; + } + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M5 */ + TB[0] = WSC_ID_MESSAGE_M5; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + + /* 4a. Encrypted E-S1 */ + /* Prepare plain text */ + PlainLen += AppendWSCTLV(WSC_ID_E_SNONCE1, &Plain[0], pReg->Es1, 0); + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 4b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = IV_ENCR_DATA_LEN_144 - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */ + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* + Generate authenticator + Combine last TX & RX message contents and validate the HMAC + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + pWscControl->WscRetryCount = 0; + + if (IV_EncrData != NULL) + os_free_mem(NULL, IV_EncrData); + + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM5 : \n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M6 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M5 + 1. Change the correct parameters + 2. Build M6 + + ======================================================================== +*/ +int BuildMessageM6( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[32]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + INT HmacLen; + UCHAR KDK[32]; + UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */ + UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */ + INT PlainLen = 0, EncrLen; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, 144); + if (IV_EncrData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return 0; + } + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M6 */ + TB[0] = WSC_ID_MESSAGE_M6; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4a. Encrypted R-S2 */ + /* Prepare plain text */ + PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE2, &Plain[0], pReg->Es2, 0); + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 4b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = IV_ENCR_DATA_LEN_144 - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */ + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* + Combine last TX & RX message contents and validate the HMAC + We have to exclude last 12 bytes from last receive since it's authenticator value + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + pWscControl->WscRetryCount = 0; + + if (IV_EncrData != NULL) + os_free_mem(NULL, IV_EncrData); + + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM6 : \n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M7 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M6 + 1. Change the correct parameters + 2. Build M7 + + ======================================================================== +*/ +int BuildMessageM7( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[32]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + INT HmacLen; + UCHAR Plain[256], *IV_EncrData=NULL;/*IV len 16 ,EncrData len */ + INT PlainLen=0, EncrLen; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + UCHAR CurOpMode = 0xFF; + +/* IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_512); + if(NULL == IV_EncrData) + return 0; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M7 */ + TB[0] = WSC_ID_MESSAGE_M7; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + + /* 4a. Encrypted E-S2 */ + /* Prepare plain text */ + PlainLen += AppendWSCTLV(WSC_ID_E_SNONCE2, &Plain[0], pReg->Es2, 0); + + /* Marvell WPS AP doesn't accept STA includes profile in M7. 20070604 */ + if ((CurOpMode == AP_MODE) && + (pWscControl->EntryIfIdx < MIN_NET_DEVICE_FOR_APCLI)) + { + USHORT authType; + USHORT encyType; + PWSC_CREDENTIAL pCredential = &pWscControl->WscProfile.Profile[0]; + WscCreateProfileFromCfg(pAdapter, ENROLLEE_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile); + + authType = pCredential->AuthType; + encyType = pCredential->EncrType; + /* + Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType. + We need to check STA is WSC 1.0 or WSC 2.0 here. + If STA is WSC 1.0, re-assign authType and encyType. + */ + if (pWscControl->RegData.PeerInfo.Version2 == 0) + { + if (authType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK)) + authType = WSC_AUTHTYPE_WPA2PSK; + if (encyType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + encyType = WSC_ENCRTYPE_AES; + } + authType = cpu2be16(authType); + encyType = cpu2be16(encyType); + PlainLen += AppendWSCTLV(WSC_ID_SSID, &Plain[PlainLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + PlainLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &Plain[PlainLen], pCredential->MacAddr, 0); + PlainLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &Plain[PlainLen], (UINT8 *)&authType, 0); + PlainLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &Plain[PlainLen], (UINT8 *)&encyType, 0); + PlainLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &Plain[PlainLen], &pCredential->KeyIndex, 0); + PlainLen += AppendWSCTLV(WSC_ID_NW_KEY, &Plain[PlainLen], pCredential->Key, pCredential->KeyLength); + } + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 4b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = IV_ENCR_DATA_LEN_512 - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);/*IVLen + EncrLen */ + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* + Generate authenticator + Combine last TX & RX message contents and validate the HMAC + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + if(NULL != IV_EncrData) +/* kfree(IV_EncrData); */ + os_free_mem(NULL, IV_EncrData); + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM7 : \n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M8 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M7 + 1. Change the correct parameters + 2. Build M8 + + ======================================================================== +*/ +int BuildMessageM8( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromApCli, + OUT VOID *pbuf) +{ +/* UCHAR TB[256]; */ + UCHAR *TB = NULL; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + INT HmacLen; + UCHAR KDK[32]; + UCHAR /* Plain[300], */ *IV_EncrData=NULL;/*IV len 16 ,EncrData len */ + UCHAR *Plain = NULL; + INT CerLen = 0, PlainLen = 0, EncrLen; + PWSC_CREDENTIAL pCredential = NULL; + USHORT AuthType = 0; + USHORT EncrType = 0; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + UCHAR CurOpMode = 0xFF; + +/* IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_512); + if(NULL == IV_EncrData) + return 0; + + os_alloc_mem(NULL, (UCHAR **)&TB, 256); + if (TB == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&Plain, 300); + if (Plain == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M8 */ + TB[0] = WSC_ID_MESSAGE_M8; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if(!bFromApCli) + { + WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, + pWscControl, &pWscControl->WscProfile); + pCredential = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + } +#ifdef APCLI_SUPPORT + else if(bFromApCli) + { + WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_CLIENT_MODE, + pWscControl, &pWscControl->WscProfile); + pCredential = &pAdapter->ApCfg.ApCliTab[apidx].WscControl.WscProfile.Profile[0]; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (pAdapter->StaCfg.WscControl.WscProfile.ProfileCnt == 0 || + (pAdapter->StaCfg.WscControl.bConfiguredAP +#ifdef WSC_V2_SUPPORT + /* + Check AP is v2 or v1, Check WscV2 Enabled or not + */ + && !(pWscControl->WscV2Info.bForceSetAP + && pWscControl->WscV2Info.bEnableWpsV2 + && (pWscControl->RegData.PeerInfo.Version2!= 0)) +#endif /* WSC_V2_SUPPORT */ + )) + WscCreateProfileFromCfg(pAdapter, STA_MODE, pWscControl, &pWscControl->WscProfile); + + pCredential = &pAdapter->StaCfg.WscControl.WscProfile.Profile[0]; + NdisMoveMemory(pCredential->MacAddr, pAdapter->MlmeAux.Bssid, 6); + } +#endif /* CONFIG_STA_SUPPORT */ + + /* 4a. Encrypted R-S1 */ + CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0); + + if (pCredential == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__)); + goto LabelErr; + } + + AuthType = pCredential->AuthType; + EncrType = pCredential->EncrType; + /* + Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType. + We need to check STA is WSC 1.0 or WSC 2.0 here. + If STA is WSC 1.0, re-assign authType and encyType. + */ + { + if (AuthType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK)) + AuthType = WSC_AUTHTYPE_WPA2PSK; + if (EncrType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + EncrType = WSC_ENCRTYPE_AES; + } + + AuthType = cpu2be16(AuthType); + EncrType = cpu2be16(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], pCredential->MacAddr, 0); + + /* Prepare plain text */ +#ifdef CONFIG_STA_SUPPORT + if ((CurOpMode == STA_MODE) && (pAdapter->StaCfg.BssType == BSS_INFRA)) + { + /* If Enrollee is AP, CREDENTIAL isn't needed in M8. */ + PlainLen = CerLen; + NdisMoveMemory(Plain, TB, CerLen); + } + else +#endif /* CONFIG_STA_SUPPORT */ + if ((CurOpMode == AP_MODE) +#ifdef CONFIG_STA_SUPPORT + || ((CurOpMode == STA_MODE) && (pAdapter->StaCfg.BssType == BSS_ADHOC)) +#endif /* CONFIG_STA_SUPPORT */ + ) + { +#ifdef IWSC_SUPPORT + USHORT tmpVal = 0; + UINT32 tmpUint32 = 0; +#endif /* IWSC_SUPPORT */ + /* Reguired attribute item in M8 if Enrollee is STA. */ + PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen); +#ifdef IWSC_SUPPORT + // TODO: Need to check the total length, we need to alarm if total length exceeds the size of Plain. snowpin 2011/05/16 + + if (IWSC_IpContentForCredential(pAdapter)) + { + PIWSC_INFO pIWscInfo = &pAdapter->StaCfg.IWscInfo; + UINT32 *pIpv4SubMaskList = NULL; + USHORT Ipv4SubMaskListSize = 0; + + if (pIWscInfo->AvaSubMaskListCount != 0) + { + Ipv4SubMaskListSize = sizeof(UINT32)*pIWscInfo->AvaSubMaskListCount; + os_alloc_mem(NULL, (UCHAR **) &pIpv4SubMaskList, Ipv4SubMaskListSize); + if (pIWscInfo->AvaSubMaskListCount == 3) + { + *pIpv4SubMaskList = cpu2be32(pIWscInfo->AvaSubMaskList[0]); + *(pIpv4SubMaskList+1) = cpu2be32(pIWscInfo->AvaSubMaskList[1]); + *(pIpv4SubMaskList+2) = cpu2be32(pIWscInfo->AvaSubMaskList[2]); + } + else if (pIWscInfo->AvaSubMaskListCount == 2) + { + *pIpv4SubMaskList = cpu2be32(pIWscInfo->AvaSubMaskList[0]); + *(pIpv4SubMaskList+1) = cpu2be32(pIWscInfo->AvaSubMaskList[1]); + } + else if (pIWscInfo->AvaSubMaskListCount == 1) + *pIpv4SubMaskList = cpu2be32(pIWscInfo->AvaSubMaskList[0]); + pIWscInfo->AvaSubMaskListCount--; + } + + tmpVal = cpu2be16(pIWscInfo->IpMethod); + PlainLen += AppendWSCTLV(WSC_ID_IP_ADDR_CONF_METHOD, + &Plain[PlainLen], + &tmpVal, 0); + + pCredential->RegIpv4Addr = pIWscInfo->SelfIpv4Addr; + tmpUint32 = cpu2be32(pIWscInfo->SelfIpv4Addr); + PlainLen += AppendWSCTLV(WSC_ID_REGISTRAR_IPV4, + &Plain[PlainLen], + (UCHAR *)&tmpUint32, 0); + + tmpUint32 = cpu2be32(pIWscInfo->Ipv4SubMask); + PlainLen += AppendWSCTLV(WSC_ID_IPV4_SUBMASK, + &Plain[PlainLen], + (UCHAR *)&tmpUint32, 0); + + pCredential->EnrIpv4Addr = pIWscInfo->PeerIpv4Addr; + tmpUint32 = cpu2be32(pIWscInfo->PeerIpv4Addr); + PlainLen += AppendWSCTLV(WSC_ID_ENROLLEE_IPV4, + &Plain[PlainLen], + (UCHAR *)&tmpUint32, 0); + + if (pIpv4SubMaskList +#ifdef IWSC_TEST_SUPPORT + && (pIWscInfo->bEmptySubmaskList == FALSE) +#endif /* IWSC_TEST_SUPPORT */ + ) + { + PlainLen += AppendWSCTLV(WSC_ID_IPV4_SUBMASK_LIST, + &Plain[PlainLen], + (UCHAR *)pIpv4SubMaskList, Ipv4SubMaskListSize); + } + + if (pIpv4SubMaskList) + os_free_mem(NULL, pIpv4SubMaskList); + } +#endif // IWSC_SUPPORT // + } + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 4b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = IV_ENCR_DATA_LEN_512 - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);/*IVLen + EncrLen */ + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + /* + Combine last TX & RX message contents and validate the HMAC + We have to exclude last 12 bytes from last receive since it's authenticator value + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0); + pData += templen; + Len += templen; + +LabelErr: + if(NULL != IV_EncrData) +/* kfree(IV_EncrData); */ + os_free_mem(NULL, IV_EncrData); + + pWscControl->WscRetryCount = 0; + + if (TB != NULL) + os_free_mem(NULL, TB); + if (Plain != NULL) + os_free_mem(NULL, Plain); + + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM8 : \n")); + return Len; +} + +int BuildMessageDONE( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[1]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, WSC DONE */ + TB[0] = WSC_MSG_WSC_DONE; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageDONE : \n")); + return Len; +} + +int BuildMessageACK( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[1]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, WSC ACK */ + TB[0] = WSC_MSG_WSC_ACK; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageACK : \n")); + return Len; +} + +int BuildMessageNACK( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[2]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + USHORT ConfigError = htons(pReg->SelfInfo.ConfigError); +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, WSC NACK */ + TB[0] = WSC_ID_MESSAGE_NACK; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + + /* 5. Error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + 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 */ + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageNACK : \n")); + return Len; +} + + +/* + ======================================================================== + + Routine Description: + Process WSC M1 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M1 + 1. Change the correct parameters + 2. Process M1 + + ======================================================================== +*/ +int ProcessMessageM1( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR, DH_Len = 0, idx; + PUCHAR pData = NULL; + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + UCHAR CurOpMode = 0xFF; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("CurOpMode = %u\n", CurOpMode)); + + pReg->PeerInfo.Version2 = 0; +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR; + + if (pWscControl->bTriggerByNFC && pWscControl->bRegenPublicKey == 0) + ; /* Do NOT need to generate EnrolleeRandom and DH public key here. */ + else +#endif /* WSC_NFC_SUPPORT */ + { + + DH_Len = sizeof(pReg->Pkr); + NdisZeroMemory(pReg->Pkr, sizeof(pReg->Pkr)); + /* Enrollee 192 random bytes for DH key generation */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter); + + RT_DH_PublicKey_Generate ( + WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE), + WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE), + pWscControl->RegData.EnrolleeRandom, sizeof(pWscControl->RegData.EnrolleeRandom), + pReg->Pkr, (UINT *) &DH_Len); + + /* Need to prefix zero padding */ + if((DH_Len != sizeof(pReg->Pkr)) && + (DH_Len < sizeof(pReg->Pkr))) + { + UCHAR TempKey[192]; + INT DiffCnt; + DiffCnt = sizeof(pReg->Pkr) - DH_Len; + + NdisFillMemory(&TempKey, DiffCnt, 0); + NdisCopyMemory(&TempKey[DiffCnt], pReg->Pkr, DH_Len); + NdisCopyMemory(pReg->Pkr, TempKey, sizeof(TempKey)); + DH_Len += DiffCnt; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Do zero padding!\n", __func__)); + } + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + DBGPRINT(RT_DEBUG_ERROR, ("Re-generate public key for negative test!\n")); + pWscControl->bRegenPublicKey = 0; + } +#endif /* WSC_NFC_SUPPORT */ + } + + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO)); + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M1 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M1 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_UUID_E: + NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E)); + break; + + case WSC_ID_MAC_ADDR: + NdisMoveMemory(pReg->PeerInfo.MacAddr, pData, WscLen); + NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerMAC, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR)); + break; + + case WSC_ID_ENROLLEE_NONCE: + NdisMoveMemory(pReg->EnrolleeNonce, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + break; + + case WSC_ID_PUBLIC_KEY: + /* Get Enrollee Public Key */ + NdisMoveMemory(pReg->Pke, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + UCHAR HashData[SHA256_DIGEST_SIZE]; + RT_SHA256(&pWscControl->RegData.Pke[0], 192, &HashData[0]); + hex_dump("public_key RAW:", &pWscControl->RegData.Pke[0], 192); + if (NdisEqualMemory(&HashData[0], &pWscControl->PeerNfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN) == FALSE) + { + hex_dump("HashData", &HashData[0], NFC_DEV_PASSWD_HASH_LEN); + hex_dump("PeerNfcPasswdHash", &pWscControl->PeerNfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN); + DBGPRINT(RT_DEBUG_ERROR, ("Enrollee public key hash different!\n")); + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH; + } + } +#endif /* WSC_NFC_SUPPORT */ + break; + + case WSC_ID_AUTH_TYPE_FLAGS: + pReg->PeerInfo.AuthTypeFlags = *((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + break; + + case WSC_ID_ENCR_TYPE_FLAGS: + pReg->PeerInfo.EncrTypeFlags = *((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + break; + + case WSC_ID_CONN_TYPE_FLAGS: + pReg->PeerInfo.ConnTypeFlags = *pData; + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + break; + + case WSC_ID_CONFIG_METHODS: + pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + break; + + case WSC_ID_SC_STATE: + pReg->PeerInfo.ScState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + /* Don't overwrite the credential of M7 received from AP when this flag is TRUE in registrar mode! */ + pWscControl->bConfiguredAP = (pReg->PeerInfo.ScState == WSC_SCSTATE_CONFIGURED) ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Update the bConfiguredAP: %d\n", pWscControl->bConfiguredAP)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE)); + break; + + case WSC_ID_MANUFACTURER: + NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + break; + + case WSC_ID_MODEL_NAME: + NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + break; + + case WSC_ID_MODEL_NUMBER: + NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + break; + + case WSC_ID_SERIAL_NUM: + NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + break; + + case WSC_ID_PRIM_DEV_TYPE: + NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + break; + + case WSC_ID_DEVICE_NAME: + NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen); + NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + break; + + case WSC_ID_RF_BAND: + pReg->PeerInfo.RfBand = *pData; + /*if() ret = WSC_ERROR_CHAN24_NOT_SUPP; */ + /*if() ret = WSC_ERROR_CHAN50_NOT_SUPP; */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + break; + + case WSC_ID_ASSOC_STATE: + pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + break; + + case WSC_ID_CONFIG_ERROR: + pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + break; + + case WSC_ID_DEVICE_PWD_ID: + DBGPRINT(RT_DEBUG_TRACE, (" WPS Registrar DPID %04x\n",pReg->SelfInfo.DevPwdId)); + if(WSC_DEVICEPWDID_DEFAULT == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */ + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PIN\n")); + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); + } + else if(WSC_DEVICEPWDID_PUSH_BTN == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */ + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PBC\n")); + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PBC); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID unsupport\n")); + } + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + break; + + case WSC_ID_OS_VERSION: + pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData);/**((PULONG) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + break; + + case WSC_ID_VENDOR_EXT: +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + UCHAR tmp_data_len = 0; + WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Version2 = %x\n", pReg->PeerInfo.Version2)); + } +#endif // WSC_V2_SUPPORT // + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M2 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M2 + 1. Change the correct parameters + 2. Process M2 + + ======================================================================== +*/ +int ProcessMessageM2( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + IN UCHAR apidx, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32]; + UCHAR DHKey[32], KdkInput[38], KdfKey[80]; + INT DH_Len; + PUCHAR pData = NULL; + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + UCHAR CurOpMode = 0xFF; +#ifdef WSC_NFC_SUPPORT + INT EncrLen; + UCHAR *IV_DecrData=NULL;//IV len 16 ,DecrData len + BOOLEAN bWscEncrSettings=FALSE; + USHORT IV_DecrDataLen; +#endif /* WSC_NFC_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + CurOpMode = STA_MODE; +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("CurOpMode = %u\n", CurOpMode)); + + pReg->PeerInfo.Version2 = 0; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO)); + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + DBGPRINT(RT_DEBUG_ERROR, ("Allocate IV_DecrData fail @ %s\n", __FUNCTION__)); + return ret; + } + } +#endif /* WSC_NFC_SUPPORT */ + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M2 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->SelfNonce, pData, WscLen) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n")); + } + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + break; + + case WSC_ID_REGISTRAR_NONCE: + NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + break; + + case WSC_ID_UUID_R: + NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R)); + break; + + case WSC_ID_PUBLIC_KEY: + /* Get Registrar Public Key */ + NdisMoveMemory(&pReg->Pkr, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) /* So far no this test case. */ + { + DBGPRINT(RT_DEBUG_TRACE, ("NfcModel(=%d) \n", pWscControl->NfcModel)); + UCHAR HashData[SHA256_DIGEST_SIZE]; + RT_SHA256(&pWscControl->RegData.Pkr[0], 192, &HashData[0]); + if (NdisEqualMemory(&HashData[0], &pWscControl->NfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN) == FALSE) + { + hex_dump("HashData", &HashData[0], NFC_DEV_PASSWD_HASH_LEN); + hex_dump("PeerNfcPasswdHash", &pWscControl->NfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN); + DBGPRINT(RT_DEBUG_ERROR, ("Registrar public key hash different!\n")); + ret = WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH; + } + } +#endif /* WSC_NFC_SUPPORT */ + break; + + case WSC_ID_AUTH_TYPE_FLAGS: + pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + break; + + case WSC_ID_ENCR_TYPE_FLAGS: + pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + break; + + case WSC_ID_CONN_TYPE_FLAGS: + pReg->PeerInfo.ConnTypeFlags = *pData; + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + break; + + case WSC_ID_CONFIG_METHODS: + pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + break; + + case WSC_ID_MANUFACTURER: + NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + break; + + case WSC_ID_MODEL_NAME: + NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + break; + + case WSC_ID_MODEL_NUMBER: + NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + break; + + case WSC_ID_SERIAL_NUM: + NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + break; + + case WSC_ID_PRIM_DEV_TYPE: + NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + break; + + case WSC_ID_DEVICE_NAME: + NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + break; + + case WSC_ID_RF_BAND: + pReg->PeerInfo.RfBand = *pData; + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + break; + + case WSC_ID_ASSOC_STATE: + pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + break; + + case WSC_ID_CONFIG_ERROR: + pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + break; + + case WSC_ID_DEVICE_PWD_ID: + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + break; + + case WSC_ID_OS_VERSION: + pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + case WSC_ID_VENDOR_EXT: +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + UCHAR tmp_data_len = 0; + WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Version2 = %x\n", pReg->PeerInfo.Version2)); + } +#endif // WSC_V2_SUPPORT // + break; +#ifdef WSC_NFC_SUPPORT + case WSC_ID_ENCR_SETTINGS: + // There shall have smoe kind of length check + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_ENCR_SETTINGS at %s\n", __FUNCTION__)); + if (WscLen <= 16) + break; + if (WscLen > 1024) + { + // ApEncrSetting is not enough + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + hex_dump("WSC_ID_ENCR_SETTINGS-pData", pData, WscLen); + hex_dump("WSC_ID_ENCR_SETTINGS-IV_DecrData", IV_DecrData, WscLen); + IV_DecrDataLen = WscLen; + bWscEncrSettings = TRUE; + } + break; +#endif /* WSC_NFC_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerMAC, &pWscControl->RegData.PeerInfo.MacAddr, 6); + + DH_Len = sizeof(pReg->SecretKey); + NdisZeroMemory(pReg->SecretKey, sizeof(pReg->SecretKey)); + RT_DH_SecretKey_Generate ( + pReg->Pkr, sizeof(pReg->Pkr), + WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE), + pReg->EnrolleeRandom, sizeof(pReg->EnrolleeRandom), + pReg->SecretKey, (UINT *) &DH_Len); + + /* Need to prefix zero padding */ + if((DH_Len != sizeof(pReg->SecretKey)) && + (DH_Len < sizeof(pReg->SecretKey))) + { + UCHAR TempKey[192]; + INT DiffCnt; + DiffCnt = sizeof(pReg->SecretKey) - DH_Len; + + NdisFillMemory(&TempKey, DiffCnt, 0); + NdisCopyMemory(&TempKey[DiffCnt], pReg->SecretKey, DH_Len); + NdisCopyMemory(pReg->SecretKey, TempKey, sizeof(TempKey)); + DH_Len += DiffCnt; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Do zero padding!\n", __func__)); + } + + /* Compute the DHKey based on the DH secret */ + RT_SHA256(&pReg->SecretKey[0], 192, &DHKey[0]); + + /* Create KDK input data */ + NdisMoveMemory(&KdkInput[0], pReg->SelfNonce, 16); + NdisMoveMemory(&KdkInput[16], pReg->SelfInfo.MacAddr, 6); + NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16); + + /* Generate the KDK */ + RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE); + + /* KDF */ + WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640); + + /* Assign Key from KDF */ + NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32); + NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16); + NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32); + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && bWscEncrSettings && pWscControl->NfcModel == MODEL_HANDOVER) + { + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (IV_DecrDataLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M2 ApEncrSettings len = %d\n ", EncrLen)); + + // Parse encryption settings + if (WscProcessCredential(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl) == FALSE) + { + return WSC_ERROR_SETUP_LOCKED; + } + } +#endif /* WSC_NFC_SUPPORT */ + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM2 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; + +/* out : */ + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M2D Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M2D + 1. Change the correct parameters + 2. Process M2D + + ======================================================================== +*/ +int ProcessMessageM2D( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + PUCHAR pData = NULL; + USHORT WscType, WscLen; + + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M2D != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n")); + } + break; + + case WSC_ID_REGISTRAR_NONCE: + NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen); + break; + + case WSC_ID_UUID_R: + NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen); + break; + + case WSC_ID_PUBLIC_KEY: + /* There shall be no Public transmitted in M2D */ + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Receive WSC_ID_PUBLIC_KEY!! werid!\n")); + break; + + case WSC_ID_AUTH_TYPE_FLAGS: + pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_ENCR_TYPE_FLAGS: + pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_CONN_TYPE_FLAGS: + pReg->PeerInfo.ConnTypeFlags = *pData; + break; + + case WSC_ID_CONFIG_METHODS: + pReg->PeerInfo.ConfigMethods = be2cpu16(get_unaligned((PUSHORT) pData));/*be2cpu16(*((PUSHORT) pData)); */ + break; + + case WSC_ID_MANUFACTURER: + NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen); + break; + + case WSC_ID_MODEL_NAME: + NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen); + break; + + case WSC_ID_MODEL_NUMBER: + NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen); + break; + + case WSC_ID_SERIAL_NUM: + NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen); + break; + + case WSC_ID_PRIM_DEV_TYPE: + NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen); + break; + + case WSC_ID_DEVICE_NAME: + NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen); + break; + + case WSC_ID_RF_BAND: + pReg->PeerInfo.RfBand = *pData; + break; + + case WSC_ID_ASSOC_STATE: + pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_CONFIG_ERROR: + pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_DEVICE_PWD_ID: + break; + + case WSC_ID_OS_VERSION: + pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG)pData); + break; + + case WSC_ID_AUTHENTICATOR: + /* No authenticator in M2D */ + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Unknown IE 0x%04x\n", WscType)); + break; + + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M3 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M3 + 1. Change the correct parameters + 2. Process M3 + + ======================================================================== +*/ +int ProcessMessageM3( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32]; + PUCHAR pData = NULL; + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M3 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M3 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_REGISTRAR_NONCE: + /* for verification with our Registrar nonce */ + if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0) + DBGPRINT(RT_DEBUG_TRACE, ("Rx M3 Compare Registrar nonce mismatched \n")); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + break; + + case WSC_ID_E_HASH1: + NdisMoveMemory(&pReg->EHash1[0], pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1)); + break; + + case WSC_ID_E_HASH2: + NdisMoveMemory(&pReg->EHash2[0], pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM3 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M4 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M4 + 1. Change the correct parameters + 2. Process M4 + + ======================================================================== +*/ +int ProcessMessageM4( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32]; + INT EncrLen; + PUCHAR pData = NULL; + UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */ + UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */ + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + +/* IV_DecrData = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + return ret; + } + pHash = IV_DecrData; + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M4 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0) + DBGPRINT(RT_DEBUG_TRACE, ("Rx M4 Compare enrollee nonce mismatched \n")); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + break; + + case WSC_ID_R_HASH1: + NdisMoveMemory(&pReg->RHash1, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1)); + break; + + case WSC_ID_R_HASH2: + NdisMoveMemory(&pReg->RHash2, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2)); + break; + + case WSC_ID_ENCR_SETTINGS: + /* There shall have smoe kind of length check */ + if (WscLen <= 16) + break; + if (WscLen > 512) + { + /* ApEncrSetting is not enough */ + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M4 ApEncrSettings len = %d\n ", EncrLen)); + + /* Parse encryption settings */ + WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Verify R-Hash1 */ + /* Create input for R-Hash1 */ + NdisMoveMemory(pHash, pReg->Rs1, 16); + NdisMoveMemory(pHash + 16, pReg->Psk1, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate R-Hash1 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, RHash, SHA256_DIGEST_SIZE); + + if (RTMPCompareMemory(pReg->RHash1, RHash, 32) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> RHash1 not matched\n")); + ret = WSC_ERROR_DEV_PWD_AUTH_FAIL; + goto out; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM4 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; +out : + if(NULL != IV_DecrData) +/* kfree(IV_DecrData); */ + os_free_mem(NULL, IV_DecrData); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M5 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M5 + 1. Change the correct parameters + 2. Process M5 + + ======================================================================== +*/ +int ProcessMessageM5( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], EHash[32]; + INT EncrLen; + PUCHAR pData = NULL; + UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */ + UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */ + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + +/* IV_DecrData = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + return ret; + } + pHash = IV_DecrData; + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M5 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_REGISTRAR_NONCE: + /* for verification with our Registrar nonce */ + if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0) + DBGPRINT(RT_DEBUG_TRACE, ("Rx M5 Compare Registrar nonce mismatched \n")); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + break; + + case WSC_ID_ENCR_SETTINGS: + /* There shall have smoe kind of length check */ + if (WscLen <= 16) + break; + if (WscLen > 512) + { + /* ApEncrSetting is not enough */ + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M5 ApEncrSettings len = %d\n ", EncrLen)); + + /* Parse encryption settings */ + WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + } + + /* Verify E-Hash1 */ + /* Create input for E-Hash1 */ + NdisMoveMemory(pHash, pReg->Es1, 16); + NdisMoveMemory(pHash + 16, pReg->Psk1, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate E-Hash1 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, EHash, SHA256_DIGEST_SIZE); + + if (RTMPCompareMemory(pReg->EHash1, EHash, 32) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM5 --> EHash1 not matched\n")); + pReg->SelfInfo.ConfigError = WSC_ERROR_HASH_FAIL; + ret = WSC_ERROR_HASH_FAIL; + goto out; + } + + if (pAdapter->pHmacData) + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM5 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; +out : + if(NULL != IV_DecrData) +/* kfree(IV_DecrData); */ + os_free_mem(NULL, IV_DecrData); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM5 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M6 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M6 + 1. Change the correct parameters + 2. Process M6 + + ======================================================================== +*/ +int ProcessMessageM6( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32]; + INT EncrLen; + PUCHAR pData = NULL; + UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */ + UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */ + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + +/* IV_DecrData = kmalloc(512, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + return ret; + } + pHash = IV_DecrData; + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = cpu2be16(TLV_Recv.Type); + WscLen = cpu2be16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M6 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0) + DBGPRINT(RT_DEBUG_TRACE, ("Rx M6 Compare enrollee nonce mismatched \n")); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + break; + + case WSC_ID_ENCR_SETTINGS: + /* There shall have smoe kind of length check */ + if (WscLen <= 16) + break; + if (WscLen > 512) + { + /* ApEncrSetting is not enough */ + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M6 ApEncrSettings len = %d\n ", EncrLen)); + + /* Parse encryption settings */ + WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Verify R-Hash2 */ + /* Create input for R-Hash1 */ + NdisMoveMemory(pHash, pReg->Rs2, 16); + NdisMoveMemory(pHash + 16, pReg->Psk2, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate R-Hash2 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, RHash, SHA256_DIGEST_SIZE); + + if (RTMPCompareMemory(pReg->RHash2, RHash, 32) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 --> RHash2 not matched\n")); + ret = WSC_ERROR_DEV_PWD_AUTH_FAIL; + goto out; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData+ pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM6 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; +out: + if(NULL != IV_DecrData) +/* kfree(IV_DecrData); */ + os_free_mem(NULL, IV_DecrData); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M7 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M7 + 1. Change the correct parameters + 2. Process M7 + + ======================================================================== +*/ +int ProcessMessageM7( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32]; + INT EncrLen; + PUCHAR pData = NULL; + USHORT WscType, WscLen; + UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */ + + RTMPZeroMemory(KDK, 32); +/* IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 1024); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + return ret; + } + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M7 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + break; + + case WSC_ID_REGISTRAR_NONCE: + /* for verification with our Registrar nonce */ + if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx M5 Compare Registrar nonce mismatched \n")); + } + break; + + case WSC_ID_ENCR_SETTINGS: + /* There shall have smoe kind of length check */ + if (WscLen <= 16) + break; + if (WscLen > 1024) + { + /* ApEncrSetting is not enough */ + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M7 ApEncrSettings len = %d\n ", EncrLen)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + { + /* Cleanup Old M7 Profile contents */ + RTMPZeroMemory(&pAdapter->StaCfg.WscControl.WscM7Profile, sizeof(WSC_PROFILE)); + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Parse encryption settings */ + WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl); + + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM7 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM7 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if(NULL != IV_DecrData) +/* kfree(IV_DecrData); */ + os_free_mem(NULL, IV_DecrData); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM7 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M8 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M8 + 1. Change the correct parameters + 2. Process M8 + + ======================================================================== +*/ +int ProcessMessageM8( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + IN PWSC_CTRL pWscControl) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32]; + INT EncrLen; + PUCHAR pData = NULL; + USHORT WscType, WscLen; + UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */ + PWSC_REG_DATA pReg = &pWscControl->RegData; + + RTMPZeroMemory(KDK, 32); +/* IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 1024); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + return ret; + } + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M8 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M8 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx M8 Compare enrollee nonce mismatched \n")); + } + break; + + case WSC_ID_ENCR_SETTINGS: + /* There shall have smoe kind of length check */ + if (WscLen <= 16) + break; + if (WscLen > 1024) + { + /* ApEncrSetting is not enough */ + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M8 ApEncrSettings len = %d\n ", EncrLen)); + + /* Parse encryption settings */ + if (WscProcessCredential(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl) == FALSE) + { + if(NULL != IV_DecrData) + os_free_mem(NULL, IV_DecrData); + return WSC_ERROR_SETUP_LOCKED; + } + + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM8 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if(NULL != IV_DecrData) +/* kfree(IV_DecrData); */ + os_free_mem(NULL, IV_DecrData); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 : \n")); + return ret; +} + +#endif /* WSC_INCLUDED */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_ufd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_ufd.c new file mode 100644 index 000000000..6f5029059 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_ufd.c @@ -0,0 +1,598 @@ +/* + *************************************************************************** + * 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_ufd.c + + Abstract: + + Revision History: + Who When What +*/ + +#include "rt_config.h" + +#ifdef WSC_INCLUDED + +static const STRING *XML_DECLARE_START = ""; +static const STRING *XML_SSID_START = "\n" +"\n" +" \n" +" CFG_GUID" +"\n" +" CFG_AP_GUID" +"\n" +" Ralink WPS AP\n" +" \n" +" CFG_SSID" +"\n" +" ESS\n" +" 0\n" +" 0\n" +" \n" +" CFG_AUTH" +"\n" +" CFG_ENCR" +"\n" +" CFG_KEY" +"\n" +" 0\n" +" 0\n" +" \n" +"\n"; + + +static struct { + PSTRING auth_str; + USHORT auth_type; +} *PWSC_UFD_AUTH_TYPE, WSC_UFD_AUTH_TYPE[] = { + {"open", WSC_AUTHTYPE_OPEN}, + {"shared", WSC_AUTHTYPE_SHARED}, + {"WPA", WSC_AUTHTYPE_WPA}, + {"WPA2", WSC_AUTHTYPE_WPA2}, + {"WPAPSK", WSC_AUTHTYPE_WPAPSK}, + {"WPA2PSK", WSC_AUTHTYPE_WPA2PSK}, + {NULL,} +}; + + +static struct { + PSTRING encr_str; + USHORT encr_type; +} *PWSC_UFD_ENCR_TYPE, WSC_UFD_ENCR_TYPE[] = { + {"none", WSC_ENCRTYPE_NONE}, + {"WEP", WSC_ENCRTYPE_WEP}, + {"TKIP", WSC_ENCRTYPE_TKIP}, + {"AES", WSC_ENCRTYPE_AES}, + {NULL,} +}; + + +BOOLEAN WscPassXmlDeclare( + INOUT STRING **pXmlData) +{ + STRING *ptr; + + DBGPRINT(RT_DEBUG_TRACE, ("======> WscPassXmlDeclare\n")); + + ptr = rtstrstr(*pXmlData, (PSTRING)XML_DECLARE_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscPassXmlDeclare: missing XML Declare \n")); + return FALSE; + } + + (*pXmlData) = ptr + strlen(XML_DECLARE_END); + + DBGPRINT(RT_DEBUG_TRACE, ("<====== WscPassXmlDeclare\n")); + + return TRUE; +} + + +BOOLEAN WscGetXmlSSID( + IN STRING *pXmlData, + OUT NDIS_802_11_SSID *pSsid) +{ + STRING *ptr, *pBuffer = pXmlData; + + ptr = rtstrstr(pBuffer, (PSTRING)XML_SSID_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlSSID: missing "); + if (ptr) + { + pBuffer = ptr + 1; + } + + ptr = rtstrstr(pBuffer, (PSTRING)XML_SSID_END); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlSSID: missing \n")); + return FALSE; + } + + pSsid->SsidLength = (UINT)(ptr - pBuffer); + RTMPZeroMemory(pSsid->Ssid, NDIS_802_11_LENGTH_SSID); + if ((pSsid->SsidLength > 0) && (pSsid->SsidLength < 33)) + { + RTMPMoveMemory(pSsid->Ssid, pBuffer, pSsid->SsidLength); + } + else + { + pSsid->SsidLength = 0; + return FALSE; + } + + return TRUE; +} + + +BOOLEAN WscGetXmlAuth( + IN STRING *pXmlData, + OUT USHORT *pAuthType) +{ + STRING *ptr, *pBuffer = pXmlData; + STRING AuthStr[10] = {0}; + UINT AuthStrLen = 0; + + *pAuthType = 0; + ptr = rtstrstr(pBuffer, (PSTRING)XML_AUTH_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlAuth: missing %s\n", XML_AUTH_START)); + return FALSE; + } + + pBuffer = ptr + strlen(XML_AUTH_START); + + ptr = rtstrstr(pBuffer, (PSTRING)XML_AUTH_END); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlAuth: missing %s\n", XML_AUTH_END)); + return FALSE; + } + + AuthStrLen = (UINT)(ptr - pBuffer); + if ((AuthStrLen > 0) && (AuthStrLen <= 10)) + { + RTMPMoveMemory(AuthStr, pBuffer, AuthStrLen); + + for (PWSC_UFD_AUTH_TYPE = WSC_UFD_AUTH_TYPE; PWSC_UFD_AUTH_TYPE->auth_str; PWSC_UFD_AUTH_TYPE++) + { + if (strcmp(AuthStr, PWSC_UFD_AUTH_TYPE->auth_str) == 0) + { + *pAuthType = PWSC_UFD_AUTH_TYPE->auth_type; + return TRUE; + } + } + } + + return FALSE; +} + + +BOOLEAN WscGetXmlEncr( + IN STRING *pXmlData, + OUT USHORT *pEncrType) +{ + STRING *ptr, *pBuffer = pXmlData; + STRING EncrStr[10] = {0}; + UINT EncrStrLen = 0; + + *pEncrType = 0; + ptr = rtstrstr(pBuffer, (PSTRING)XML_ENCR_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlEncr: missing %s\n", XML_ENCR_START)); + return FALSE; + } + + pBuffer = ptr + strlen(XML_ENCR_START); + + ptr = rtstrstr(pBuffer, (PSTRING)XML_ENCR_END); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlEncr: missing %s\n", XML_ENCR_END)); + return FALSE; + } + + EncrStrLen = (UINT)(ptr - pBuffer); + if ((EncrStrLen > 0) && (EncrStrLen <= 10)) + { + RTMPMoveMemory(EncrStr, pBuffer, EncrStrLen); + + for (PWSC_UFD_ENCR_TYPE = WSC_UFD_ENCR_TYPE; PWSC_UFD_ENCR_TYPE->encr_str; PWSC_UFD_ENCR_TYPE++) + { + if (strcmp(EncrStr, PWSC_UFD_ENCR_TYPE->encr_str) == 0) + { + *pEncrType = PWSC_UFD_ENCR_TYPE->encr_type; + return TRUE; + } + } + } + + return FALSE; +} + + +BOOLEAN WscGetXmlKey( + IN STRING *pXmlData, + OUT UCHAR *pKey, + OUT USHORT *pKeyLen) +{ + STRING *ptr, *pBuffer = pXmlData; + UINT KeyLen = 0; + + ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKey: missing %s\n", XML_KEY_START)); + return FALSE; + } + + pBuffer = ptr + strlen(XML_KEY_START); + + ptr = rtstrstr(pBuffer, ">"); + if (ptr) + { + pBuffer = ptr + 1; + } + + ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_END); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKey: missing %s\n", XML_KEY_END)); + return FALSE; + } + + KeyLen = (UINT)(ptr - pBuffer); + if ((KeyLen >= 8) && (KeyLen <= 64)) + { + RTMPMoveMemory(pKey, pBuffer, KeyLen); + *pKeyLen = KeyLen; + } + else + { + return FALSE; + } + + return TRUE; +} + + +BOOLEAN WscGetXmlKeyIndex( + IN STRING *pXmlData, + OUT UCHAR *pKeyIndex) +{ + STRING *ptr, *pBuffer = pXmlData; + + *pKeyIndex = 1; + ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_INDEX_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKeyIndex: missing %s\n", XML_KEY_INDEX_START)); + return FALSE; + } + + pBuffer = ptr + strlen(XML_KEY_INDEX_START); + + ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_INDEX_END); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKeyIndex: missing %s\n", XML_KEY_INDEX_END)); + return FALSE; + } + + *pKeyIndex = *(--ptr) - 0x30; + + return TRUE; +} + + + +BOOLEAN WscReadProfileFromUfdFile( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN PSTRING pUfdFileName) +{ + PWSC_CREDENTIAL pCredential = &pAd->ApCfg.MBSSID[ApIdx].WscControl.WscProfile.Profile[0]; + RTMP_OS_FS_INFO osFSInfo; + RTMP_OS_FD file_r; + ssize_t rv, fileLen = 0; + PSTRING pXmlData = NULL; + BOOLEAN RV = TRUE; + + if (pUfdFileName == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s: pUfdFileName is NULL\n", __FUNCTION__)); + return FALSE; + } + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + file_r = RtmpOSFileOpen(pUfdFileName, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(file_r)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Error opening file %s\n", __FUNCTION__, pUfdFileName)); + return FALSE; + } + else + { + char tempStr[64] = {0}; + while((rv = RtmpOSFileRead(file_r, tempStr, 64)) > 0) + { + fileLen += rv; + } + os_alloc_mem(pAd, (UCHAR **)&pXmlData, fileLen+1); + if (pXmlData == NULL) + { + RtmpOSFileClose(file_r); + RtmpOSFSInfoChange(&osFSInfo, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("pXmlData kmalloc fail. (fileLen = %d)\n", fileLen)); + return FALSE; + } + RTMPZeroMemory(pXmlData, fileLen+1); + RtmpOSFileSeek(file_r, 0); + rv = RtmpOSFileRead(file_r, (PSTRING)pXmlData, fileLen); + RtmpOSFileClose(file_r); + if (rv != fileLen) + { + DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSFileRead fail, fileLen = %d\n", fileLen)); + RtmpOSFSInfoChange(&osFSInfo, FALSE); + goto ReadErr; + } + } + + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("WscReadProfileFromUfdFile\n")); + if (WscPassXmlDeclare(&pXmlData)) + { + if (WscGetXmlSSID(pXmlData, &pCredential->SSID)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SSID = %s(%d)\n", pCredential->SSID.Ssid, pCredential->SSID.SsidLength)); + } + else + { + RV = FALSE; + goto FreeXmlData; + } + + if (WscGetXmlAuth(pXmlData, &pCredential->AuthType)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Credential.AuthType = 0x%04x\n", pCredential->AuthType)); + } + else + { + RV = FALSE; + goto FreeXmlData; + } + + if (WscGetXmlEncr(pXmlData, &pCredential->EncrType)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Credential.EncrType = 0x%04x\n", pCredential->EncrType)); + } + else + { + RV = FALSE; + goto FreeXmlData; + } + + pCredential->KeyLength = 0; + RTMPZeroMemory(pCredential->Key, 64); + if (WscGetXmlKey(pXmlData, pCredential->Key, &pCredential->KeyLength)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Credential.Key = %s (%d)\n", pCredential->Key, pCredential->KeyLength)); + } + else + { + RV = FALSE; + goto FreeXmlData; + } + + /* + If we cannot find keyIndex in .wfc file, use default value 1. + */ + if (WscGetXmlKeyIndex(pXmlData, &pCredential->KeyIndex)) + { + DBGPRINT(RT_DEBUG_TRACE, ("pCredential->KeyIndex = %d\n", pCredential->KeyIndex)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("WscReadProfileFromUfdFile OK\n")); + + WscWriteConfToPortCfg(pAd, + &pAd->ApCfg.MBSSID[ApIdx].WscControl, + &pAd->ApCfg.MBSSID[ApIdx].WscControl.WscProfile.Profile[0], TRUE); + + pAd->WriteWscCfgToDatFile = ApIdx; + + RtmpOsTaskWakeUp(&(pAd->wscTask)); + +FreeXmlData: + if (pXmlData) + os_free_mem(NULL, pXmlData); + + return RV; + } + +ReadErr: + if (pXmlData) + os_free_mem(NULL, pXmlData); + return FALSE; +} + + +BOOLEAN WscWriteProfileToUfdFile( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN PSTRING pUfdFileName) +{ + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; + PWSC_CREDENTIAL pCredential = &pWscControl->WscProfile.Profile[0]; + RTMP_OS_FS_INFO osFSInfo; + RTMP_OS_FD file_w; + PSTRING offset, pXmlTemplate = (PSTRING)XML_TEMPLATE; + BOOLEAN bFound = FALSE, bRtn = TRUE; + UCHAR Guid[UUID_LEN_HEX]; + UCHAR Guid_Str[UUID_LEN_STR]; + + if (pUfdFileName == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s: pUfdFileName is NULL\n", __FUNCTION__)); + return FALSE; + } + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + file_w = RtmpOSFileOpen(pUfdFileName, O_WRONLY|O_TRUNC|O_CREAT, 0); + if (IS_FILE_OPEN_ERR(file_w)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Error opening file %s\n", __FUNCTION__, pUfdFileName)); + return FALSE; + } + else + { + WscCreateProfileFromCfg(pAd, AP_MODE, pWscControl, &pWscControl->WscProfile); + + WscGenerateUUID(pAd, &Guid[0], &Guid_Str[0], ApIdx, TRUE); + + if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_GUID_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, (PSTRING)&Guid_Str[0], (int)UUID_LEN_STR); + pXmlTemplate = offset + strlen(XML_GUID_MARK); + } + + if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_AP_GUID_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, (PSTRING)&pWscControl->Wsc_Uuid_Str[0], (int)UUID_LEN_STR); + pXmlTemplate = offset + strlen(XML_AP_GUID_MARK); + } + if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_SSID_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, (PSTRING)&pCredential->SSID.Ssid[0], (int)pCredential->SSID.SsidLength); + pXmlTemplate = offset + strlen(XML_SSID_MARK); + } + if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_AUTH_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate)); + for (PWSC_UFD_AUTH_TYPE = WSC_UFD_AUTH_TYPE; PWSC_UFD_AUTH_TYPE->auth_str; PWSC_UFD_AUTH_TYPE++) + { + if (PWSC_UFD_AUTH_TYPE->auth_type == pCredential->AuthType) + { + RtmpOSFileWrite(file_w, + (PSTRING)PWSC_UFD_AUTH_TYPE->auth_str, + (int)strlen(PWSC_UFD_AUTH_TYPE->auth_str)); + bFound = TRUE; + break; + } + } + pXmlTemplate = offset + strlen(XML_AUTH_MARK); + if (bFound == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Unknow Auth Type(=%x)\n", __FUNCTION__, pCredential->AuthType)); + bRtn = FALSE; + goto out; + } + } + if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_ENCR_MARK)) != NULL) + { + bFound = FALSE; + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate)); + for (PWSC_UFD_ENCR_TYPE = WSC_UFD_ENCR_TYPE; PWSC_UFD_ENCR_TYPE->encr_str; PWSC_UFD_ENCR_TYPE++) + { + if (PWSC_UFD_ENCR_TYPE->encr_type == pCredential->EncrType) + { + RtmpOSFileWrite(file_w, + (PSTRING)PWSC_UFD_ENCR_TYPE->encr_str, + (int)strlen(PWSC_UFD_ENCR_TYPE->encr_str)); + bFound = TRUE; + } + } + pXmlTemplate = offset + strlen(XML_ENCR_MARK); + if (bFound == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Unknow Encr Type(=%x)\n", __FUNCTION__, pCredential->EncrType)); + bRtn = FALSE; + goto out; + } + } + if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_KEY_MARK)) != NULL) + { + if (pCredential->EncrType != WSC_ENCRTYPE_NONE) + { + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, + (PSTRING)pCredential->Key, + (int)pCredential->KeyLength); + pXmlTemplate = offset + strlen(XML_KEY_MARK); + } + else + { + RtmpOSFileWrite(file_w, (PSTRING)XML_ENCR_END, (int)strlen(XML_ENCR_END)); + RtmpOSFileWrite(file_w, (PSTRING)"\n", (int)1); + pXmlTemplate = offset + strlen(XML_KEY_MARK) + strlen(XML_KEY_END) + 1; /* 1: '\n' */ + } + } + RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)strlen(pXmlTemplate)); + } + +out: + RtmpOSFileClose(file_w); + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + return bRtn; +} + + +#endif /* WSC_INCLUDED */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_v2.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_v2.c new file mode 100644 index 000000000..eb3866620 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/common/wsc_v2.c @@ -0,0 +1,300 @@ +/* + *************************************************************************** + * 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_V2_SUPPORT +#include "wsc_tlv.h" + +BOOLEAN WscAppendV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen); + +#ifdef CONFIG_AP_SUPPORT +VOID WscOnOff( + IN PRTMP_ADAPTER pAd, + IN INT ApIdx, + IN BOOLEAN bOff) +{ + PWSC_V2_INFO pWpsV2Info = &pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscV2Info; + if (bOff) + { + /* + AP must not support WEP in WPS V2 + */ + pWpsV2Info->bWpsEnable = FALSE; + pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscIEProbeResp.ValueLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - OFF.\n")); + } + else + { + pWpsV2Info->bWpsEnable = TRUE; + if (pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscConfMode != WSC_DISABLE) + { + INT IsAPConfigured; + IsAPConfigured = pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscConfStatus; + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, (ApIdx & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, ApIdx, NULL, 0, AP_MODE); + DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - ON.\n")); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - bWpsEnable = %d\n", pWpsV2Info->bWpsEnable)); +} + +VOID WscAddEntryToAclList( + IN PRTMP_ADAPTER pAd, + IN INT ApIdx, + IN PUCHAR pMacAddr) +{ + PRT_802_11_ACL pACL = NULL; + INT i; + BOOLEAN bFound = FALSE; + + pACL = &pAd->ApCfg.MBSSID[ApIdx].AccessControlList; + + if ((pACL->Policy == 0) || + (pACL->Policy == 2)) + return; + + if (pACL->Num >= (MAX_NUM_OF_ACL_LIST - 1)) + { + DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n")); + return; + } + + for (i=0; iNum; i++) + { + if (NdisEqualMemory(pACL->Entry[i].Addr, pMacAddr, MAC_ADDR_LEN)) + bFound = TRUE; + } + if (bFound == FALSE) + { + NdisMoveMemory(pACL->Entry[i].Addr, pMacAddr, MAC_ADDR_LEN); + pACL->Num++; + } +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + Vendor ID: 0x00372A + Subelements ID (one-octet) + Version2 0x00 + AuthorizedMACs 0x01 + Network Key Shareable 0x02 + Request to Enroll 0x03 + Settings Delay Time 0x04 + Reserved for future use 0x05 to 0xFF + Length (one-octet) - number of octets in the payload of this subelment + Version2 1B + AuthorizedMACs <=30B + Network Key Shareable Bool + Request to Enroll Bool + Settings Delay Time 1B +*/ +BOOLEAN WscGenV2Msg( + IN PWSC_CTRL pWpsCtrl, + IN BOOLEAN bSelRegistrar, + IN PUCHAR pAuthorizedMACs, + IN INT AuthorizedMACsLen, + OUT UCHAR **pOutBuf, + OUT INT *pOutBufLen) +{ + PUCHAR pWscV2Msg = NULL; + USHORT WscV2MsgLen = 0; + PWSC_REG_DATA pReg = &pWpsCtrl->RegData; + INT templen = 0; + + os_alloc_mem(NULL, (UCHAR **)&pWscV2Msg, 128); + if (pWscV2Msg) + { + UCHAR TmpLen = 0; + pWscV2Msg[0] = 0x00; + pWscV2Msg[1] = 0x37; + pWscV2Msg[2] = 0x2A; + + /* Version2 */ + WscAppendV2SubItem(WFA_EXT_ID_VERSION2, &pReg->SelfInfo.Version2, 1, pWscV2Msg+3, &TmpLen); + WscV2MsgLen += (3 + (USHORT)TmpLen); + + if (bSelRegistrar) + { + /* + Authorized MACs + Registrars (both internal and external) shall add the AuthorizedMACs subelement, + this applies to all Configuration Methods, including PIN, PBC and NFC. + */ + if (pAuthorizedMACs) + { + WscAppendV2SubItem( WFA_EXT_ID_AUTHORIZEDMACS, + pAuthorizedMACs, + AuthorizedMACsLen, + pWscV2Msg+WscV2MsgLen, + &TmpLen ); + WscV2MsgLen += (USHORT)TmpLen; + } + else + { + WscAppendV2SubItem( WFA_EXT_ID_AUTHORIZEDMACS, + BROADCAST_ADDR, + MAC_ADDR_LEN, + pWscV2Msg+WscV2MsgLen, + &TmpLen ); + WscV2MsgLen += (USHORT)TmpLen; + } + } + + templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, (*pOutBuf), (UINT8 *)pWscV2Msg, WscV2MsgLen); + (*pOutBuf) += templen; + (*pOutBufLen) += templen; + + os_free_mem(NULL, pWscV2Msg); + + return TRUE; + } + return FALSE; +} + +BOOLEAN WscAppendV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen) +{ + PUCHAR pBuf = NULL; + os_alloc_mem(NULL, &pBuf, DataLen + 10); + if (pBuf) + { + pBuf[0] = SubID; + pBuf[1] = DataLen; + NdisMoveMemory(pBuf+2, pData, DataLen); + *pOutBufLen = (DataLen + 2); + NdisMoveMemory(pOutBuf, pBuf, *pOutBufLen); + os_free_mem(NULL, pBuf); + return TRUE; + } + return FALSE; +} + +BOOLEAN WscParseV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN USHORT DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen) +{ + PEID_STRUCT pEid; + USHORT Length = 0; + pEid = (PEID_STRUCT) (pData + 3); + hex_dump("WscParseV2SubItem - pData", (pData+3), DataLen-3); + while ((Length + 2 + pEid->Len) <= (DataLen-3)) + { + if (pEid->Eid == SubID) + { + *pOutBufLen = pEid->Len; + NdisMoveMemory(pOutBuf, &pEid->Octet[0], pEid->Len); + return TRUE; + } + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + return FALSE; +} + +VOID WscSendEapFragAck( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry) +{ + if (pEntry == NULL) + { + ASSERT(pEntry!=NULL); + return; + } + if (IS_ENTRY_CLIENT(pEntry)) + { + pWscControl->bWscLastOne = TRUE; + if (pAdapter->OpMode == OPMODE_AP) + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ); + else + { + if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode == WSC_REGISTRAR)) + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, STA_MODE, EAP_CODE_RSP); + } + } + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); +} + +VOID WscSendEapFragData( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry) +{ + INT DataLen = 0; + PUCHAR pData = NULL; + + if (pEntry == NULL) + { + ASSERT(pEntry!=NULL); + return; + } + + pData = pWscControl->pWscCurBufIdx; + pWscControl->bWscLastOne = TRUE; + if (pWscControl->WscTxBufLen > pWscControl->WscFragSize) + { + pWscControl->bWscLastOne = FALSE; + DataLen = pWscControl->WscFragSize; + pWscControl->WscTxBufLen -= pWscControl->WscFragSize; + pWscControl->pWscCurBufIdx = (pWscControl->pWscCurBufIdx + pWscControl->WscFragSize); + } + else + { + DataLen = pWscControl->WscTxBufLen; + pWscControl->pWscCurBufIdx = NULL; + pWscControl->WscTxBufLen = 0; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + { + if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pAdapter, WSC_OPCODE_MSG, pData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + else + WscSendMessage(pAdapter, WSC_OPCODE_MSG, pData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter) + WscSendMessage(pAdapter, WSC_OPCODE_MSG, pData, DataLen, pWscControl, STA_MODE, EAP_CODE_RSP); +#endif // CONFIG_STA_SUPPORT // +} + +#endif /* WSC_V2_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860AP.dat b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860AP.dat new file mode 100644 index 000000000..adc775b58 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860AP.dat @@ -0,0 +1,144 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode=TW +BssidNum=1 +SSID1=RT2860AP1 +SSID2= +SSID3= +SSID4= +WirelessMode=9 +TxRate=0 +Channel=11 +BasicRate=15 +BeaconPeriod=100 +DtimPeriod=1 +TxPower=100 +DisableOLBC=0 +BGProtection=0 +MaxStaNum=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +TurboRate=0 +WmmCapable=0 +APSDCapable=0 +DLSCapable=0 +APAifsn=3;7;1;1 +APCwmin=4;4;3;2 +APCwmax=6;10;4;3 +APTxop=0;0;94;47 +APACM=0;0;0;0 +BSSAifsn=3;7;2;2 +BSSCwmin=4;4;3;2 +BSSCwmax=10;10;4;3 +BSSTxop=0;0;94;47 +BSSACM=0;0;0;0 +AckPolicy=0;0;0;0 +NoForwarding=0 +NoForwardingBTNBSSID=0 +HideSSID=0 +StationKeepAlive=0 +ShortSlot=1 +AutoChannelSelect=0 +IEEE8021X=0 +IEEE80211H=0 +CSPeriod=10 +WirelessEvent=0 +IdsEnable=0 +AuthFloodThreshold=32 +AssocReqFloodThreshold=32 +ReassocReqFloodThreshold=32 +ProbeReqFloodThreshold=32 +DisassocFloodThreshold=32 +DeauthFloodThreshold=32 +EapReqFooldThreshold=32 +PreAuth=0 +AuthMode=OPEN +EncrypType=NONE +RekeyInterval=0 +RekeyMethod=DISABLE +PMKCachePeriod=10 +WPAPSK1= +WPAPSK2= +WPAPSK3= +WPAPSK4= +DefaultKeyID=1 +Key1Type=0 +Key1Str1= +Key1Str2= +Key1Str3= +Key1Str4= +Key2Type=0 +Key2Str1= +Key2Str2= +Key2Str3= +Key2Str4= +Key3Type=0 +Key3Str1= +Key3Str2= +Key3Str3= +Key3Str4= +Key4Type=0 +Key4Str1= +Key4Str2= +Key4Str3= +Key4Str4= +HSCounter=0 +AccessPolicy0=0 +AccessControlList0= +AccessPolicy1=0 +AccessControlList1= +AccessPolicy2=0 +AccessControlList2= +AccessPolicy3=0 +AccessControlList3= +WdsEnable=0 +WdsEncrypType=NONE +WdsList= +WdsKey= +RADIUS_Server=192.168.2.3 +RADIUS_Port=1812 +RADIUS_Key=ralink +own_ip_addr=192.168.5.234 +EAPifname=br0 +PreAuthifname=br0 +HT_HTC=0 +HT_RDG=0 +HT_EXTCHA=0 +HT_LinkAdapt=0 +HT_OpMode=0 +HT_MpduDensity=5 +HT_BW=1 +HT_AutoBA=1 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_LDPC=1 +HT_MCS=33 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=1 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +WscManufacturer= +WscModelName= +WscDeviceName= +WscModelNumber= +WscSerialNumber= +RadioOn=1 +PMFMFPC=0 +PMFMFPR=0 +PMFSHA256=0 +LoadCodeMethod=0 diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860AP.dat_ac b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860AP.dat_ac new file mode 100644 index 000000000..122db3892 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860AP.dat_ac @@ -0,0 +1,133 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode=TW +BssidNum=1 +SSID1=RT85592AP +SSID2= +SSID3= +SSID4= +WirelessMode=14 +TxRate=0 +Channel=56 +BasicRate=15 +BeaconPeriod=100 +DtimPeriod=3 +TxPower=100 +DisableOLBC=0 +BGProtection=0 +MaxStaNum=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +TurboRate=0 +WmmCapable=0 +APSDCapable=0 +DLSCapable=0 +APAifsn=3;7;1;1 +APCwmin=4;4;3;2 +APCwmax=6;10;4;3 +APTxop=0;0;94;47 +APACM=0;0;0;0 +BSSAifsn=3;7;2;2 +BSSCwmin=4;4;3;2 +BSSCwmax=10;10;4;3 +BSSTxop=0;0;94;47 +BSSACM=0;0;0;0 +AckPolicy=0;0;0;0 +NoForwarding=0 +NoForwardingBTNBSSID=0 +HideSSID=0 +StationKeepAlive=0 +ShortSlot=1 +AutoChannelSelect=0 +IEEE8021X=0 +IEEE80211H=0 +CSPeriod=10 +WirelessEvent=0 +IdsEnable=0 +AuthFloodThreshold=32 +AssocReqFloodThreshold=32 +ReassocReqFloodThreshold=32 +ProbeReqFloodThreshold=32 +DisassocFloodThreshold=32 +DeauthFloodThreshold=32 +EapReqFooldThreshold=32 +PreAuth=0 +AuthMode=OPEN +EncrypType=NONE +RekeyInterval=0 +RekeyMethod=DISABLE +PMKCachePeriod=10 +WPAPSK1= +WPAPSK2= +WPAPSK3= +WPAPSK4= +DefaultKeyID=1 +Key1Type=0 +Key1Str1= +Key1Str2= +Key1Str3= +Key1Str4= +Key2Type=0 +Key2Str1= +Key2Str2= +Key2Str3= +Key2Str4= +Key3Type=0 +Key3Str1= +Key3Str2= +Key3Str3= +Key3Str4= +Key4Type=0 +Key4Str1= +Key4Str2= +Key4Str3= +Key4Str4= +HSCounter=0 +AccessPolicy0=0 +AccessControlList0= +AccessPolicy1=0 +AccessControlList1= +AccessPolicy2=0 +AccessControlList2= +AccessPolicy3=0 +AccessControlList3= +WdsEnable=0 +WdsEncrypType=NONE +WdsList= +WdsKey= +RADIUS_Server=192.168.2.3 +RADIUS_Port=1812 +RADIUS_Key=ralink +own_ip_addr=192.168.5.234 +EAPifname=br0 +PreAuthifname=br0 +HT_HTC=0 +HT_RDG=0 +HT_EXTCHA=0 +HT_LinkAdapt=0 +HT_OpMode=0 +HT_MpduDensity=5 +HT_BW=1 +HT_AutoBA=1 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +WscManufacturer= +WscModelName= +WscDeviceName= +WscModelNumber= +WscSerialNumber= +RadioOn=1 diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860STA.dat b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860STA.dat new file mode 100644 index 000000000..f254a2dfd --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/RT2860STA.dat @@ -0,0 +1,95 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode= +ChannelGeography=1 +SSID=Dennis2860AP +NetworkType=Infra +WirelessMode=9 +Channel=0 +BeaconPeriod=100 +TxPower=100 +BGProtection=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +WmmCapable=1 +AckPolicy=0;0;0;0 +AuthMode=OPEN +EncrypType=NONE +WPAPSK= +DefaultKeyID=1 +Key1Type=0 +Key1Str= +Key2Type=0 +Key2Str= +Key3Type=0 +Key3Str= +Key4Type=0 +Key4Str= +PSMode=CAM +AutoRoaming=0 +RoamThreshold=70 +APSDCapable=0 +APSDAC=0;0;0;0 +HT_RDG=1 +HT_EXTCHA=0 +HT_OpMode=0 +HT_MpduDensity=4 +HT_BW=1 +HT_AutoBA=1 +HT_BADecline=0 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +HT_MIMOPSMode=3 +HT_DisallowTKIP=1 +HT_LDPC=1 +HT_STBC=0 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=1 +EthConvertMode= +EthCloneMac= +IEEE80211H=0 +TGnWifiTest=0 +WirelessEvent=0 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +CarrierDetect=0 +AntDiversity=0 +BeaconLostTime=4 +FtSupport=0 +Wapiifname=ra0 +WapiPsk= +WapiPskType= +WapiUserCertPath= +WapiAsCertPath= +PSP_XLINK_MODE=0 +WscManufacturer= +WscModelName= +WscDeviceName= +WscModelNumber= +WscSerialNumber= +RadioOn=1 +WIDIEnable=1 +P2P_L2SD_SCAN_TOGGLE=3 +Wsc4digitPinCode=0 +P2P_WIDIEnable=0 +PMFMFPC=0 +PMFMFPR=0 +PMFSHA256=0 +SnifferType=0 +LoadCodeMethod=0 diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/SingleSKU.dat b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/SingleSKU.dat new file mode 100644 index 000000000..7a4b872ca --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/conf/SingleSKU.dat @@ -0,0 +1,62 @@ +# Single SKU Max Power Table +# |CCK 1~11 | | OFDM 6 ~ 54 | | HT20 MCS 0 ~ 15 | | HT40 MCS 0 ~ 15 | +ch1 16 16 16 16 14 14 14 14 14 14 14 14 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch2 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch3 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +ch4 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch5 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch6 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch7 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch8 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch9 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +ch10 18 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +ch11 16 16 16 16 14 14 14 14 14 14 14 14 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch12 +ch13 +ch14 + +# OFDM 6 ~ 54 | | HT20 MCS 0 ~ 15 | | HT40 MCS 0 ~ 15 | | VHT80 MCS 0 ~ 9 | +ch36 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch38 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch40 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch42 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch44 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch46 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch48 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch52 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 13 13 13 13 13 13 13 13 13 13 +ch54 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 13 13 13 13 13 13 13 13 13 13 +ch56 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 13 13 13 13 13 13 13 13 13 13 +ch58 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 13 13 13 13 13 13 13 13 13 13 +ch60 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch62 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch64 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch100 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch102 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch104 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +ch106 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 +ch108 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 +ch110 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 +ch112 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 +ch116 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch118 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch120 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch122 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch124 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch126 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch128 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch132 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 18 18 18 18 18 18 18 18 18 18 +ch134 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 18 18 18 18 18 18 18 18 18 18 +ch136 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 18 18 18 18 18 18 18 18 18 18 +ch140 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +ch149 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch151 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch153 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch155 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch157 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch159 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch161 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch165 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch169 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 +ch173 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 21 21 21 21 19 19 19 19 17 17 + + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/README_STA_pci b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/README_STA_pci similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/README_STA_pci rename to package/lean/mt/drivers/mt7612e/src/mt76x2/doc/README_STA_pci diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/ate_iwpriv_usage.txt b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/ate_iwpriv_usage.txt new file mode 100644 index 000000000..1de7fec1b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/ate_iwpriv_usage.txt @@ -0,0 +1,444 @@ +=================================================================================================== +ATE Test Command Format for station driver + +****** IMPORTANT ****** +If you are not familiar with hardware, it is recommanded not to modify hardware default value. +It may damage hardware. + +=================================================================================================== +Usage: + iwpriv ra0 [act] [parameters]=[val] + + +where + +[act] [parameters] [val] constraints explaination +----- ------------- ----------------- -------------------------------- + +===================================== +1. Set ATE actions. + Value: + ATESTART - Stop AP & ATE function. + ATESTOP - Start AP function. + TXCONT - Start AP continuous TX, for power mask. + TXCARR - Start AP carrier test, for frequency calibration. + TXFRAME - Transmit frame, for EVM. + RXFRAME - Continuous RX, for PER/FER. + +1.1 ATEDA + Set ATE frame header destination address. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.2 ATESA + Set ATE frame header source addr. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.3 ATEBSSID + Set ATE frame header BSSID. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.4 ATECHANNEL + Set ATE Channel, deimal. + Value: + 802.11b/g: 1 ~ 14 depends on CountryRegion setting + +1.5 ATETXPOW0 + Set ATE Tx power for Antenna 1. + Value: + 0 ~ 31 ; 2.4GHz, deimal + -7 ~15 ; 5.5GHz, deimal + +1.6 ATETXPOW1 + Set ATE Tx power for Antenna 2. + Value: + 0 ~ 31 ; 2.4GHz, decimal + -7 ~15 ; 5.5GHz, deimal + +1.7 ATETXFREQOFFSET + Set ATE RF frequency offset. + Value: + 0 ~ 63 ; unit: 2KHz, decimal + +1.8 ATETXLEN + Set ATE frame length. + Value: + 24 ~ 2312 ; decimal + +1.9 ATETXCNT + Set ATE frame Tx count. + Value: + 1 ~ ; 32-bit, decimal + +1.10 ATETXMODE (Refer to TxMode) + Set ATE Tx Mode. + Value: + 0: CCK 802.11b + 1: OFDM 802.11g + 2: HT_MIX 802.11b/g/n + 3: Green Field 802.11n + +1.11 ATETXBW (Refer to TxMode) + Set ATE Tx and Rx Bandwidth. + Value: + 0: 20MHz + 1: 40MHz + +1.12 ATETXGI (Refer to TxMode) + Set ATE Tx Guard Interval. + Value: + 0: Long + 1: Short + +1.13 ATETXMCS (Refer to TxMode) + Set ATE Tx MCS type. + Value: + 0 ~ 15 + +1.14 ATETXANT + Set ATE TX antenna. + Value: + 0: All + 1: Antenna one + 2: Antenna two + +1.15 ATERXANT + Set ATE RX antenna. + Value: + 0: All + 1: Antenna one + 2: Antenna two + 3: Antenna three + +1.16 ATERXFER + Set ATE to periodically reset and show up RxCount (per-second) and RxTotalCount. + Value: + 0: Disable counter visability + 1: Enable counter visability + +1.17 ATESHOW + Show all parameters of ATE. + Value: + 1 + +1.18 ATEHELP + List all commands of ATE. + Value: + 1 + +1.19 ResetCounter + Reset statistic counter. + Value: + 1 + +1.20 ATERRF + Read all of the RF registers. + Value: + 1 + +1.21 ATEWRF1 + Write the RF register 1. + Value: + xxxxxxxx ;32-bit, hex + +1.22 ATEWRF2 + Write the RF register 2. + Value: + xxxxxxxx ;32-bit, hex + +1.23 ATEWRF3 + Write the RF register 3. + Value: + xxxxxxxx ;32-bit, hex + +1.24 ATEWRF4 + Write the RF register 4. + Value: + xxxxxxxx ;32-bit, hex + +1.25 ATELDE2P + Overwrite all EEPROM contents from "/etc/Wireless/RT2860/(70)AP(/STA)/e2p.bin". + Value: + 1 + E.g. + iwpriv ra0 set ATELDE2P=1 +1.26 ATERE2P + Display all EEPROM content. + Value: + 1 + E.g. + iwpriv ra0 set ATERE2P=1 + +=================================================================================================== +2. Examples: +========= + +2.1 Check EVM & Power + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATEDA=00:11:22:33:44:55 + iwpriv ra0 set ATESA=00:aa:bb:cc:dd:ee + iwpriv ra0 set ATEBSSID=00:11:22:33:44:55 + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXGI=0 ; set Long GI. + iwpriv ra0 set ATETXLEN=1024 ; set packet length. + iwpriv ra0 set ATETXPOW0=18 + iwpriv ra0 set ATETXPOW1=18 + iwpriv ra0 set ATETXCNT=100000 + iwpriv ra0 set ATE=TXFRAME + K + iwpriv ra0 set ATETXPOW0=19 + K + iwpriv ra0 set ATETXPOW0=20 + K + iwpriv ra0 set ATE=ATESTART + +2.2 Check Carrier + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame(inform BBP to change, modulation mode) + iwpriv ra0 set ATE=TXCARR ; Start Tx carrier, Measure carrier with instrument + iwpriv ra0 set ATETXPOW0=05 + iwpriv ra0 set ATETXPOW1=05 + iwpriv ra0 set ATETXFREQOFFSET=19 + iwpriv ra0 set ATE=ATESTART + +2.3 Check specturm mask + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame(inform BBP to change, modulation mode) + iwpriv ra0 set ATE=TXCONT ; Start continuous TX, Measure specturm mask with instrument + iwpriv ra0 set ATETXPOW0=5 + iwpriv ra0 set ATETXPOW1=5 + iwpriv ra0 set ATE=ATESTART + +2.4 Frequency offset tuning + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATETXFREQOFFSET=0 ; Set frequency offset 0(decimal) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame + iwpriv ra0 set ATE=TXCARR ; Start Tx carrier, Measure carrier frequency with instrument + iwpriv ra0 set ATETXFREQOFFSET=10 ; Dynamic turning frequency offset, 10(decimal) + iwpriv ra0 set ATETXFREQOFFSET=20 ; Dynamic turning frequency offset, 20(decimal) + iwpriv ra0 set ATE=ATESTART ; Stop, Store the tuning result to EEPROM + +2.5 Rx + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ResetCounter=1 ; Reset statistic counter + iwpriv ra0 set ATETXFREQOFFSET=value ;To use the value(decimal) you got in tx calibration + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATE=RXFRAME ; Start Rx, + iwpriv ra0 set ATERXFER=1 ; show RxCnt and RSSI/per-antenna, Transmit test packets + iwpriv ra0 set ATE=ATESTART ; Stop + iwpriv ra0 stat ; get statistics counter + iwpriv ra0 set ATERXFER=1 + iwpriv ra0 set ATERXANT=1 + + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATERXANT=0 + iwpriv ra0 set ATE=RXFRAME + +2.6 Show all ate parameters + iwpriv ra0 set ATESHOW=1 + + Mode=4 + TxPower0=0 + TxPower1=0 + TxAntennaSel=0 + RxAntennaSel=0 + BBPCurrentBW=0 + GI=0 + MCS=7 + TxMode=1 + Addr1=00:11:22:aa:bb:cc + Addr2=00:11:22:aa:bb:cc + Addr3=00:11:22:aa:bb:cc + Channel=1 + TxLength=1024 + TxCount=40000 + TxRate=11 + RFFreqOffset=0 + +2.7 Online help + iwpriv ra0 set ATEHELP=1 + + ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME + ATEDA + ATESA + ATEBSSID + ATECHANNEL, range:0~14(unless A band !). + ATETXPOW0, set power level of antenna 1. + ATETXPOW1, set power level of antenna 2. + ATETXANT, set TX antenna. 0: all, 1: antenna one, 2: antenna two. + ATERXANT, set RX antenna.0: all, 1: antenna one, 2: antenna two, 3: antenna three. + ATETXFREQOFFSET, set frequency offset, range 0~63. + ATETXBW, set BandWidth, 0:20MHz, 1:40MHz. + ATETXLEN, set Frame length, range 24~2312. + ATETXCNT, set how many frame going to transmit. + ATETXMCS, set MCS, reference to rate table. + ATETXMODE, set Mode 0: CCK, 1: OFDM, 2: HT-Mix, 3: GreenField, reference to rate table. + ATETXGI, set GI interval, 0: Long, 1: Short. + ATERXFER, 0: disable Rx Frame error rate. 1: enable Rx Frame error rate. + ATERRF, show all RF registers. + ATEWRF1, set RF1 register. + ATEWRF2, set RF2 register. + ATEWRF3, set RF3 register. + ATEWRF4, set RF4 register. + ATELDE2P, load EEPROM from .bin file. + ATERE2P, display all EEPROM content. + ATESHOW, display all parameters of ATE. + ATEHELP, online help. + +2.8 Display Rx Packet Count and RSSI + iwpriv ra0 set ATERXANT=0 ==> Enable All Three Rx Antennas + iwpriv ra0 set ATERXFER=1 ==> Enable Rx Frame Error Rate: RxCnt/RxTotal + iwpriv ra0 set ATE=RXFRAME ==> Start Rx + MlmePeriodicExec: Rx packet cnt = 2/4 + MlmePeriodicExec: Rx AvgRssi0=-88, AvgRssi1=-80, AvgRssi2=-91 + MlmePeriodicExec: Rx packet cnt = 2/6 + MlmePeriodicExec: Rx AvgRssi0=-86, AvgRssi1=-77, AvgRssi2=-89K + K + + iwpriv ra0 set ATERXANT=1 ==> Enable Three Rx Antenna-1 + iwpriv ra0 set ATERXFER=1 ==> Enable Rx Frame Error Rate: RxCnt/RxTotal + iwpriv ra0 set ATE=RXFRAME ==> Start Rx + MlmePeriodicExec: Rx packet cnt = 0/7 + MlmePeriodicExec: Rx AvgRssi=-87 + MlmePeriodicExec: Rx packet cnt = 7/14 + MlmePeriodicExec: Rx AvgRssi=-90 + K + K + + +=================================================================================================== +3. Hardware Access +================== + +===================================== +3.1 iwpriv ra0 bbp [parameters]=[Value] + Read/Write BBP registers by ID number. + BBPID + +3.1.1 Read BBP register, BBPID only, no = symbol. + BBPID: + 0 ~ xx ; decimal, 8-bit + BBPID=Value + +3.1.2 Write BBP register. + BBPID: + 0 ~ xx ; decimal, 8-bit + Value: + 00 ~FF ; hexdecimal, 8-bit + +===================================== +3.2 iwpriv ra0 mac [parameters]=[val] + Read/Write MAC registers by offset. + MAC_OFFSET + +3.2.1 Read MAC register, MAC_OFFSET only, no = symbol. + MAC_OFFSET: + 0000 ~ FFFF ; hexdecimal, 16-bit + MAC_OFFSET=Value + +3.2.2 Write MAC register. + MAC_OFFSET: + 0000 ~ FFFF ; hexdecimal, 16-bit + Value: + 0000 ~FFFF ; hexdecimal, 32-bit + +===================================== +3.3 iwpriv ra0 e2p [parameters]=[val] + Read/Write EEPROM content by address. + EEP_ADDR + +3.3.1 Read EEPROM content, EEP_ADDR only, no = symbol. + EEP_ADDR: + 00 ~ FF ; hexdecimal, 16-bit alignment (0, 2, 4, 6, 8, A, C, K) + EEP_ADDR=Value + +3.3.2 Write EEPROM content. + EEP_ADDR: + 00 ~ FF ; hexdecimal, 16-bit alignment (0, 2, 4, 6, 8, A, C, K) + Value: + 0000 ~FFFF ; hexdecimal, 16-bit + +===================================== +3.4 Example + +3.4.1 Hardware access + iwpriv ra0 bbp 0 # read BBP register 0 + iwpriv ra0 bbp 0=12 # write BBP register 0 as 0x12 + iwpriv ra0 mac 0 # read MAC register 0 + iwpriv ra0 mac 0=1234abcd # write MAC register 0 as 0x1234abcd + iwpriv ra0 e2p 0 # read E2PROM 0 + iwpriv ra0 e2p c=12ab # write E2PROM 0xc as 0x12ab + +3.4.2 Statistic counter operation + iwpriv ra0 stat # read statistic counter + iwpriv ra0 set ResetCounter=0 # reset statistic counter + + Suggestion: + 1. To turn on ATE functionality, you have to add compile flag "RALINK_ATE" to Makefile + 2. Before doing ATE testing, please stop AP function + 3. If you want to test another ATE action, prefer to stop AP & ATE function + 4. All ATE function settings will lose efficacy after reboot. + 5. Before hardware register access, please reference hardware spec. + Note. + In ATE mode, the channel must set via "ATECHANNEL" + +=================================================================================================== +4. ated +======= +4.1 Introduction +The ated is an optional user space component for RT28xx Linux driver. +When Windows GUI starts, AP enters ATE mode (i.e.,ATESTART) immediately. +It behaves as a proxy between Windows GUI and RT28xx Linux driver when ATE process proceeds. +The ated will be killed automatically when Windows GUI is closed. +You can kill it manually, too(for example, type '$killall ated'). +RT28xx linux driver will leave ATE mode either ated is killed or Windows GUI is closed. + +4.2 Environment setup +1. Connect the platform you want to test directly with a Windows host by ether network line. +2. In the Windows host, run WinPcap_4_0.exe for the QA GUI or ./RT2880_ATE/RaUI.exe(please unrar "RT2880_ATE.rar" to get it). + +4.3 How to use ated for ATE purpose +0. First you should set both "HAS_ATE=y" and "HAS_QA_SUPPORT=y" in the file ~/Module/os/linux/config.mk and compile the driver. +1. Modify the Makefile according to our target "PLATFORM". +2. Change the path of "CROSS_COMPILE" if needed. +3. Then type 'make' command to compile the source code of the daemon. +4. After the driver interface has started up, attach both of the wireless interface and the ethernet interface to the bridge interface. +5. If you have no bridge interface, please give an IP address to the ethernet interface. + (for example : '$ated -beth0') +6. After the interfaces have entered forwarding states, manually start ated, type '$ated -bbrX -iraX'. +7. If your WLAN interface and Bridge interface is "ra0" and "br0" respectively, just type $ated. + (For further usage of options, type $ated -h) +8. In the Windows host, run RT28xxQA_ATE.exe or ./RT2880_ATE/RaUI.exe. +9. Select the wired network adapter, then press OK and wait for a moment. +10.If the Windows host cannot tolerate such a broadcast storm from ated, + please run ated with option -u.(for example : '$ated -ira1 -u') +11.If your target platform concerns its network security, please run RT28xxQA_unicast.exe instead of RT28xxQA_ATE.exe. + +Note : +a. The names of WLAN interface(default is "ra0") and Bridge interface(default is "br0") must be specified manually(for example : '$ated -bbr1 -ira2') if your WLAN interface or Bridge interface is not "ra0" or "br0" respectively ! +b. Please make sure no other RaUI is running before you excute ./RT2880_ATE/RaUI.exe. + + + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/brftph_usage.txt b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/brftph_usage.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/brftph_usage.txt rename to package/lean/mt/drivers/mt7612e/src/mt76x2/doc/brftph_usage.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/iwpriv_usage.txt b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/iwpriv_usage.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/iwpriv_usage.txt rename to package/lean/mt/drivers/mt7612e/src/mt76x2/doc/iwpriv_usage.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/mbss_phy.readme b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/mbss_phy.readme similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/mbss_phy.readme rename to package/lean/mt/drivers/mt7612e/src/mt76x2/doc/mbss_phy.readme diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/sta_ate_iwpriv_usage.txt b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/sta_ate_iwpriv_usage.txt new file mode 100644 index 000000000..2e95d7348 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/sta_ate_iwpriv_usage.txt @@ -0,0 +1,445 @@ +=================================================================================================== +ATE Test Command Format for station driver + +****** IMPORTANT ****** +If you are not familiar with hardware, it is recommanded not to modify hardware default value. +It may damage hardware. + +=================================================================================================== +Usage: + iwpriv ra0 [act] [parameters]=[val] + + +where + +[act] [parameters] [val] constraints explaination +----- ------------- ----------------- -------------------------------- + +===================================== +1. Set ATE actions. + Value: + ATESTART - Start ATE function and stop station function. + ATESTOP - Stop ATE function and start station function. + TXCONT - Start continuous TX, for power mask. + TXCARR - Start carrier test, for frequency calibration. + TXFRAME - Transmit frame, for EVM. + RXFRAME - Continuous RX, for PER/FER. + +1.1 ATEDA + Set ATE frame header destination address. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.2 ATESA + Set ATE frame header source addr. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.3 ATEBSSID + Set ATE frame header BSSID. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.4 ATECHANNEL + Set ATE Channel, deimal. + Value: + 802.11b/g: 1 ~ 14 depends on CountryRegion setting + +1.5 ATETXPOW0 + Set ATE Tx power for Antenna 1. + Value: + 0 ~ 31 ; 2.4GHz, deimal + -7 ~15 ; 5.5GHz, deimal + +1.6 ATETXPOW1 + Set ATE Tx power for Antenna 2. + Value: + 0 ~ 31 ; 2.4GHz, decimal + -7 ~15 ; 5.5GHz, deimal + +1.7 ATETXFREQOFFSET + Set ATE RF frequency offset. + Value: + 0 ~ 63 ; unit: 2KHz, decimal + +1.8 ATETXLEN + Set ATE frame length. + Value: + 24 ~ 2312 ; decimal + +1.9 ATETXCNT + Set ATE frame Tx count. + Value: + 1 ~ ; 32-bit, decimal + +1.10 ATETXMODE (Refer to TxMode) + Set ATE Tx Mode. + Value: + 0: CCK 802.11b + 1: OFDM 802.11g + 2: HT_MIX 802.11b/g/n + 3: Green Field 802.11n + +1.11 ATETXBW (Refer to TxMode) + Set ATE Tx and Rx Bandwidth. + Value: + 0: 20MHz + 1: 40MHz + +1.12 ATETXGI (Refer to TxMode) + Set ATE Tx Guard Interval. + Value: + 0: Long + 1: Short + +1.13 ATETXMCS (Refer to TxMode) + Set ATE Tx MCS type. + Value: + 0 ~ 15 + +1.14 ATETXANT + Set ATE TX antenna. + Value: + 0: All + 1: Antenna one + 2: Antenna two + +1.15 ATERXANT + Set ATE RX antenna. + Value: + 0: All + 1: Antenna one + 2: Antenna two + 3: Antenna three + +1.16 ATERXFER + Set ATE to periodically reset and show up RxCount (per-second) and RxTotalCount. + Value: + 0: Disable counter visability + 1: Enable counter visability + +1.17 ATESHOW + Show all parameters of ATE. + Value: + 1 + +1.18 ATEHELP + List all commands of ATE. + Value: + 1 + +1.19 ResetCounter + Reset statistic counter. + Value: + 1 + +1.20 ATERRF + Read all of the RF registers. + Value: + 1 + +1.21 ATEWRF1 + Write the RF register 1. + Value: + xxxxxxxx ;32-bit, hex + +1.22 ATEWRF2 + Write the RF register 2. + Value: + xxxxxxxx ;32-bit, hex + +1.23 ATEWRF3 + Write the RF register 3. + Value: + xxxxxxxx ;32-bit, hex + +1.24 ATEWRF4 + Write the RF register 4. + Value: + xxxxxxxx ;32-bit, hex + +1.25 ATELDE2P + Overwrite all EEPROM contents + Value: + 1 + E.g. + iwpriv ra0 set ATELDE2P=1 + +1.26 ATERE2P + Display all EEPROM content. + Value: + 1 + E.g. + iwpriv ra0 set ATERE2P=1 + +=================================================================================================== +2. Examples: +========= + +2.1 Check EVM & Power + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATEDA=00:11:22:33:44:55 + iwpriv ra0 set ATESA=00:aa:bb:cc:dd:ee + iwpriv ra0 set ATEBSSID=00:11:22:33:44:55 + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXGI=0 ; set Long GI. + iwpriv ra0 set ATETXLEN=1024 ; set packet length. + iwpriv ra0 set ATETXPOW0=18 + iwpriv ra0 set ATETXPOW1=18 + iwpriv ra0 set ATETXCNT=100000 + iwpriv ra0 set ATE=TXFRAME + K + iwpriv ra0 set ATETXPOW0=19 + K + iwpriv ra0 set ATETXPOW0=20 + K + iwpriv ra0 set ATE=ATESTART + +2.2 Check Carrier + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame(inform BBP to change, modulation mode) + iwpriv ra0 set ATE=TXCARR ; Start Tx carrier, Measure carrier with instrument + iwpriv ra0 set ATETXPOW0=05 + iwpriv ra0 set ATETXPOW1=05 + iwpriv ra0 set ATETXFREQOFFSET=19 + iwpriv ra0 set ATE=ATESTART + +2.3 Check specturm mask + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame(inform BBP to change, modulation mode) + iwpriv ra0 set ATE=TXCONT ; Start continuous TX, Measure specturm mask with instrument + iwpriv ra0 set ATETXPOW0=5 + iwpriv ra0 set ATETXPOW1=5 + iwpriv ra0 set ATE=ATESTART + +2.4 Frequency offset tuning + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATETXFREQOFFSET=0 ; Set frequency offset 0(decimal) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame + iwpriv ra0 set ATE=TXCARR ; Start Tx carrier, Measure carrier frequency with instrument + iwpriv ra0 set ATETXFREQOFFSET=10 ; Dynamic turning frequency offset, 10(decimal) + iwpriv ra0 set ATETXFREQOFFSET=20 ; Dynamic turning frequency offset, 20(decimal) + iwpriv ra0 set ATE=ATESTART ; Stop, Store the tuning result to EEPROM + +2.5 Rx + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ResetCounter=1 ; Reset statistic counter + iwpriv ra0 set ATETXFREQOFFSET=value ;To use the value(decimal) you got in tx calibration + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATE=RXFRAME ; Start Rx, + iwpriv ra0 set ATERXFER=1 ; show RxCnt and RSSI/per-antenna, Transmit test packets + iwpriv ra0 set ATE=ATESTART ; Stop + iwpriv ra0 stat ; get statistics counter + iwpriv ra0 set ATERXFER=1 + iwpriv ra0 set ATERXANT=1 + + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATERXANT=0 + iwpriv ra0 set ATE=RXFRAME + +2.6 Show all ate parameters + iwpriv ra0 set ATESHOW=1 + + Mode=4 + TxPower0=0 + TxPower1=0 + TxAntennaSel=0 + RxAntennaSel=0 + BBPCurrentBW=0 + GI=0 + MCS=7 + TxMode=1 + Addr1=00:11:22:aa:bb:cc + Addr2=00:11:22:aa:bb:cc + Addr3=00:11:22:aa:bb:cc + Channel=1 + TxLength=1024 + TxCount=40000 + TxRate=11 + RFFreqOffset=0 + +2.7 Online help + iwpriv ra0 set ATEHELP=1 + + ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME + ATEDA + ATESA + ATEBSSID + ATECHANNEL, range:0~14(unless A band !). + ATETXPOW0, set power level of antenna 1. + ATETXPOW1, set power level of antenna 2. + ATETXANT, set TX antenna. 0: all, 1: antenna one, 2: antenna two. + ATERXANT, set RX antenna.0: all, 1: antenna one, 2: antenna two, 3: antenna three. + ATETXFREQOFFSET, set frequency offset, range 0~63. + ATETXBW, set BandWidth, 0:20MHz, 1:40MHz. + ATETXLEN, set Frame length, range 24~2312. + ATETXCNT, set how many frame going to transmit. + ATETXMCS, set MCS, reference to rate table. + ATETXMODE, set Mode 0: CCK, 1: OFDM, 2: HT-Mix, 3: GreenField, reference to rate table. + ATETXGI, set GI interval, 0: Long, 1: Short. + ATERXFER, 0: disable Rx Frame error rate. 1: enable Rx Frame error rate. + ATERRF, show all RF registers. + ATEWRF1, set RF1 register. + ATEWRF2, set RF2 register. + ATEWRF3, set RF3 register. + ATEWRF4, set RF4 register. + ATELDE2P, load EEPROM from .bin file. + ATERE2P, display all EEPROM content. + ATESHOW, display all parameters of ATE. + ATEHELP, online help. + +2.8 Display Rx Packet Count and RSSI + iwpriv ra0 set ATERXANT=0 ==> Enable All Three Rx Antennas + iwpriv ra0 set ATERXFER=1 ==> Enable Rx Frame Error Rate: RxCnt/RxTotal + iwpriv ra0 set ATE=RXFRAME ==> Start Rx + MlmePeriodicExec: Rx packet cnt = 2/4 + MlmePeriodicExec: Rx AvgRssi0=-88, AvgRssi1=-80, AvgRssi2=-91 + MlmePeriodicExec: Rx packet cnt = 2/6 + MlmePeriodicExec: Rx AvgRssi0=-86, AvgRssi1=-77, AvgRssi2=-89K + K + + iwpriv ra0 set ATERXANT=1 ==> Enable Three Rx Antenna-1 + iwpriv ra0 set ATERXFER=1 ==> Enable Rx Frame Error Rate: RxCnt/RxTotal + iwpriv ra0 set ATE=RXFRAME ==> Start Rx + MlmePeriodicExec: Rx packet cnt = 0/7 + MlmePeriodicExec: Rx AvgRssi=-87 + MlmePeriodicExec: Rx packet cnt = 7/14 + MlmePeriodicExec: Rx AvgRssi=-90 + K + K + + +=================================================================================================== +3. Hardware Access +================== + +===================================== +3.1 iwpriv ra0 bbp [parameters]=[Value] + Read/Write BBP registers by ID number. + BBPID + +3.1.1 Read BBP register, BBPID only, no = symbol. + BBPID: + 0 ~ xx ; decimal, 8-bit + BBPID=Value + +3.1.2 Write BBP register. + BBPID: + 0 ~ xx ; decimal, 8-bit + Value: + 00 ~FF ; hexdecimal, 8-bit + +===================================== +3.2 iwpriv ra0 mac [parameters]=[val] + Read/Write MAC registers by offset. + MAC_OFFSET + +3.2.1 Read MAC register, MAC_OFFSET only, no = symbol. + MAC_OFFSET: + 0000 ~ FFFF ; hexdecimal, 16-bit + MAC_OFFSET=Value + +3.2.2 Write MAC register. + MAC_OFFSET: + 0000 ~ FFFF ; hexdecimal, 16-bit + Value: + 0000 ~FFFF ; hexdecimal, 32-bit + +===================================== +3.3 iwpriv ra0 e2p [parameters]=[val] + Read/Write EEPROM content by address. + EEP_ADDR + +3.3.1 Read EEPROM content, EEP_ADDR only, no = symbol. + EEP_ADDR: + 00 ~ FF ; hexdecimal, 16-bit alignment (0, 2, 4, 6, 8, A, C, K) + EEP_ADDR=Value + +3.3.2 Write EEPROM content. + EEP_ADDR: + 00 ~ FF ; hexdecimal, 16-bit alignment (0, 2, 4, 6, 8, A, C, K) + Value: + 0000 ~FFFF ; hexdecimal, 16-bit + +===================================== +3.4 Example + +3.4.1 Hardware access + iwpriv ra0 bbp 0 # read BBP register 0 + iwpriv ra0 bbp 0=12 # write BBP register 0 as 0x12 + iwpriv ra0 mac 0 # read MAC register 0 + iwpriv ra0 mac 0=1234abcd # write MAC register 0 as 0x1234abcd + iwpriv ra0 e2p 0 # read E2PROM 0 + iwpriv ra0 e2p c=12ab # write E2PROM 0xc as 0x12ab + +3.4.2 Statistic counter operation + iwpriv ra0 stat # read statistic counter + iwpriv ra0 set ResetCounter=0 # reset statistic counter + + Suggestion: + 1. To turn on ATE functionality, you have to add compile flag "RALINK_ATE" to Makefile + 2. Before doing ATE testing, please stop AP function + 3. If you want to test another ATE action, prefer to stop AP & ATE function + 4. All ATE function settings will lose efficacy after reboot. + 5. Before hardware register access, please reference hardware spec. + Note. + In ATE mode, the channel must set via "ATECHANNEL" + +=================================================================================================== +4. ated +======= +4.1 Introduction +The ated is an optional user space component for RT28xx Linux driver. +When Windows GUI starts, AP enters ATE mode (i.e.,ATESTART) immediately. +It behaves as a proxy between Windows GUI and RT28xx Linux driver when ATE process proceeds. +The ated will be killed automatically when Windows GUI is closed. +You can kill it manually, too(for example, type '$killall ated'). +RT28xx linux driver will leave ATE mode either ated is killed or Windows GUI is closed. + +4.2 Environment setup +1. Connect the platform you want to test directly with a Windows host by ether network line. +2. In the Windows host, run WinPcap_4_0.exe for the QA GUI or ./RT2880_ATE/RaUI.exe(please unrar "RT2880_ATE.rar" to get it). + +4.3 How to use ated for ATE purpose +0. First you should set both "HAS_ATE=y" and "HAS_QA_SUPPORT=y" in the file ~/Module/os/linux/config.mk and compile the driver. +1. Modify the Makefile according to our target "PLATFORM". +2. Change the path of "CROSS_COMPILE" if needed. +3. Then type 'make' command to compile the source code of the daemon. +4. After the driver interface has started up, attach both of the wireless interface and the ethernet interface to the bridge interface. +5. If you have no bridge interface, please give an IP address to the ethernet interface. + (for example : '$ated -beth0') +6. After the interfaces have entered forwarding states, manually start ated, type '$ated -bbrX -iraX'. +7. If your WLAN interface and Bridge interface is "ra0" and "br0" respectively, just type $ated. + (For further usage of options, type $ated -h) +8. In the Windows host, run RT28xxQA_ATE.exe or ./RT2880_ATE/RaUI.exe. +9. Select the wired network adapter, then press OK and wait for a moment. +10.If the Windows host cannot tolerate such a broadcast storm from ated, + please run ated with option -u.(for example : '$ated -ira1 -u') +11.If your target platform concerns its network security, please run RT28xxQA_unicast.exe instead of RT28xxQA_ATE.exe. + +Note : +a. The names of WLAN interface(default is "ra0") and Bridge interface(default is "br0") must be specified manually(for example : '$ated -bbr1 -ira2') if your WLAN interface or Bridge interface is not "ra0" or "br0" respectively ! +b. Please make sure no other RaUI is running before you excute ./RT2880_ATE/RaUI.exe. + + + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/wps_iwpriv_usage.txt b/package/lean/mt/drivers/mt7612e/src/mt76x2/doc/wps_iwpriv_usage.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/wps_iwpriv_usage.txt rename to package/lean/mt/drivers/mt7612e/src/mt76x2/doc/wps_iwpriv_usage.txt diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7612E3_EEPROM_layout_20131022_2G5G_iPAiLNA_wTSSI_default_slope_offset.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7612E3_EEPROM_layout_20131022_2G5G_iPAiLNA_wTSSI_default_slope_offset.bin new file mode 100644 index 000000000..216ac4928 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7612E3_EEPROM_layout_20131022_2G5G_iPAiLNA_wTSSI_default_slope_offset.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7612E_EEPROM_layout_20131121_2G5G_ePAeLNA_TXTC_off.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7612E_EEPROM_layout_20131121_2G5G_ePAeLNA_TXTC_off.bin new file mode 100644 index 000000000..5b5233872 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7612E_EEPROM_layout_20131121_2G5G_ePAeLNA_TXTC_off.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E1_EEPROM_layout_20130301.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E1_EEPROM_layout_20130301.bin new file mode 100644 index 000000000..e0b42d3b7 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E1_EEPROM_layout_20130301.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130412.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130412.bin new file mode 100644 index 000000000..2fd84a827 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130412.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130527.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130527.bin new file mode 100644 index 000000000..41d39dcaa Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130527.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130903_ePA.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130903_ePA.bin new file mode 100644 index 000000000..463674599 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/eeprom/MT7662E2_EEPROM_20130903_ePA.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/hw_ctrl/coex.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/hw_ctrl/coex.c new file mode 100644 index 000000000..efc0d1772 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/hw_ctrl/coex.c @@ -0,0 +1,26 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/hw_ctrl/greenap.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/hw_ctrl/greenap.c new file mode 100644 index 000000000..95f2e2c21 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/hw_ctrl/greenap.c @@ -0,0 +1,144 @@ +/* + *************************************************************************** + * 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: + greenap.c + + Abstract: + Ralink Wireless driver green ap related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +#ifdef GREENAP_SUPPORT +VOID EnableAPMIMOPSv2(RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower) +{ + bbp_set_mmps(pAd, ReduceCorePower); + rtmp_mac_set_mmps(pAd, ReduceCorePower); + + pAd->ApCfg.bGreenAPActive=TRUE; + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPSNew, 30xx changes the # of antenna to 1\n")); +} + + +VOID DisableAPMIMOPSv2(RTMP_ADAPTER *pAd) +{ + bbp_set_mmps(pAd, FALSE); + rtmp_mac_set_mmps(pAd, FALSE); + + pAd->ApCfg.bGreenAPActive=FALSE; + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPSNew, 30xx reserve only one antenna\n")); +} + + +VOID EnableAPMIMOPSv1( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN ReduceCorePower) +{ + ULONG TxPinCfg = 0x00050F0A;/*Gary 2007/08/09 0x050A0A*/ + UCHAR CentralChannel; + + + if(pAd->CommonCfg.Channel>14) + TxPinCfg=0x00050F05; + + TxPinCfg &= 0xFFFFFFF3; + TxPinCfg &= 0xFFFFF3FF; + pAd->ApCfg.bGreenAPActive=TRUE; + + CentralChannel = pAd->CommonCfg.CentralChannel; + DBGPRINT(RT_DEBUG_INFO, ("Run with BW_20\n")); + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + CentralChannel = pAd->CommonCfg.Channel; + + /* Set BBP registers to BW20 */ + bbp_set_bw(pAd, BW_20); + + /* RF Bandwidth related registers would be set in AsicSwitchChannel() */ + if (pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1) + { + /*Tx/Rx Stream*/ + bbp_set_txdac(pAd, 0); + bbp_set_rxpath(pAd, 1); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + } + AsicSwitchChannel(pAd, CentralChannel, FALSE); + + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPS, 305x/28xx changes the # of antenna to 1\n")); +} + + +VOID DisableAPMIMOPSv1( + IN PRTMP_ADAPTER pAd) +{ + ULONG TxPinCfg = 0x00050F0A; /* Gary 2007/08/09 0x050A0A */ + UCHAR CentralChannel; + + + if(pAd->CommonCfg.Channel>14) + TxPinCfg=0x00050F05; + /* Turn off unused PA or LNA when only 1T or 1R*/ + if (pAd->Antenna.field.TxPath == 1) + TxPinCfg &= 0xFFFFFFF3; + if (pAd->Antenna.field.RxPath == 1) + TxPinCfg &= 0xFFFFF3FF; + + pAd->ApCfg.bGreenAPActive=FALSE; + + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (pAd->CommonCfg.Channel != 14)) + { + UINT8 ext_ch = EXTCHA_NONE; + + DBGPRINT(RT_DEBUG_INFO, ("Run with BW_40\n")); + /* Set CentralChannel to work for BW40 */ + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + ext_ch = EXTCHA_ABOVE; + } + else if ((pAd->CommonCfg.Channel > 2) && (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + ext_ch = EXTCHA_BELOW; + } + CentralChannel = pAd->CommonCfg.CentralChannel; + AsicSetChannel(pAd, CentralChannel, BW_40, ext_ch, FALSE); + } + + /*Tx Stream*/ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->Antenna.field.TxPath == 2)) + bbp_set_txdac(pAd, 2); + else + bbp_set_txdac(pAd, 0); + + /*Rx Stream*/ + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPS, 305x/28xx reserve only one antenna\n")); +} +#endif /* GREENAP_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/action.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/action.h new file mode 100644 index 000000000..e02568c4e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/action.h @@ -0,0 +1,101 @@ +/* + *************************************************************************** + * 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: + aironet.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __ACTION_H__ +#define __ACTION_H__ + + +struct _RTMP_ADAPTER; + + + +VOID MlmeQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeInvalidAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerAddBAReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAddBARspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_VHT_AC +VOID PeerVHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) ; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef CONFIG_STA_SUPPORT +VOID StaPublicAction( + IN PRTMP_ADAPTER pAd, + IN BSS_2040_COEXIST_IE *pBss2040CoexIE); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* QOS_DLS_SUPPORT */ + +#endif /* __ACTION_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ags.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ags.h new file mode 100644 index 000000000..0840400be --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ags.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * 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 AGS (Adaptive Group Switching) Related Structure & Definition + +***************************************************************************/ + +#ifndef __AGS_H__ +#define __AGS_H__ + + +extern UCHAR AGS1x1HTRateTable[]; +extern UCHAR AGS2x2HTRateTable[]; +extern UCHAR AGS3x3HTRateTable[]; +#ifdef DOT11_VHT_AC +extern UCHAR Ags1x1VhtRateTable[]; +extern UCHAR Ags2x2VhtRateTable[]; +#endif /* DOT11_VHT_AC */ + +#define AGS_TX_QUALITY_WORST_BOUND 8 +#define AGS_QUICK_RA_TIME_INTERVAL 50 /* 50ms */ + +/* The size, in bytes, of an AGS entry in the rate switch table */ +#define SIZE_OF_AGS_RATE_TABLE_ENTRY 9 + +typedef struct _RTMP_RA_AGS_TB { + UCHAR ItemNo; + + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:2; + UCHAR Mode:3; + UCHAR Rsv1:1; + + UCHAR Nss:2; // NSS_XXX (VHT only) + UCHAR rsv2:6; // Reserved + + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; + UCHAR downMcs; + UCHAR upMcs3; + UCHAR upMcs2; + UCHAR upMcs1; +}RTMP_RA_AGS_TB; + + +/* AGS control */ +typedef struct _AGS_CONTROL { + UCHAR MCSGroup; /* The MCS group under testing */ + UCHAR lastRateIdx; +} AGS_CONTROL,*PAGS_CONTROL; + + +/* The statistics information for AGS */ +typedef struct _AGS_STATISTICS_INFO { + CHAR RSSI; + ULONG TxErrorRatio; + ULONG AccuTxTotalCnt; + ULONG TxTotalCnt; + ULONG TxSuccess; + ULONG TxRetransmit; + ULONG TxFailCount; +} AGS_STATISTICS_INFO, *PAGS_STATISTICS_INFO; + + +/* Support AGS (Adaptive Group Switching) */ +#define SUPPORT_AGS(__pAd) ((__pAd)->rateAlg == RATE_ALG_AGS) + +#ifdef DOT11_VHT_AC +#define AGS_IS_USING(__pAd, __pRateTable) \ + (SUPPORT_AGS(__pAd) && \ + ((__pRateTable == AGS1x1HTRateTable) ||\ + (__pRateTable == AGS2x2HTRateTable) ||\ + (__pRateTable == AGS3x3HTRateTable) ||\ + (__pRateTable == Ags1x1VhtRateTable) ||\ + (__pRateTable == Ags2x2VhtRateTable))) +#else +#define AGS_IS_USING(__pAd, __pRateTable) \ + (SUPPORT_AGS(__pAd) && \ + ((__pRateTable == AGS1x1HTRateTable) || \ + (__pRateTable == AGS2x2HTRateTable) || \ + (__pRateTable == AGS3x3HTRateTable))) +#endif /* DOT11_VHT_AC */ + +#endif /* __AGS_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap.h new file mode 100644 index 000000000..621b9d36e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap.h @@ -0,0 +1,355 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __AP_H__ +#define __AP_H__ + +#ifdef DOT11R_FT_SUPPORT +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + + + +/* ============================================================= */ +/* Common definition */ +/* ============================================================= */ +#define MBSS_VLAN_INFO_GET( \ + __pAd, __VLAN_VID, __VLAN_Priority, __FromWhichBSSID) \ +{ \ + if ((__FromWhichBSSID < __pAd->ApCfg.BssidNum) && \ + (__FromWhichBSSID < HW_BEACON_MAX_NUM) && \ + (__pAd->ApCfg.MBSSID[__FromWhichBSSID].wdev.VLAN_VID != 0)) \ + { \ + __VLAN_VID = __pAd->ApCfg.MBSSID[__FromWhichBSSID].wdev.VLAN_VID; \ + __VLAN_Priority = __pAd->ApCfg.MBSSID[__FromWhichBSSID].wdev.VLAN_Priority; \ + } \ +} + +#ifdef CUSTOMER_DCC_FEATURE +#define TIMESTAMP_GET(__pAd, __TimeStamp) \ + { \ + UINT32 __CSR=0; UINT64 __Value64; \ + RTMP_IO_READ32((__pAd), TSF_TIMER_DW0, &__CSR); \ + __TimeStamp = (UINT64)__CSR; \ + RTMP_IO_READ32((__pAd), TSF_TIMER_DW1, &__CSR); \ + __Value64 = (UINT64)__CSR; \ + __TimeStamp |= (__Value64 << 32); \ + } +#endif +/* ============================================================= */ +/* Function Prototypes */ +/* ============================================================= */ + +BOOLEAN APBridgeToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN ULONG fromwdsidx); + +INT ApAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid); + +INT APSendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket); + +NDIS_STATUS APInsertPsQueue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR QueIdx); + +#ifdef TXBF_SUPPORT +NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR QueIdx, UCHAR TxSndgTypePerEntry); +#else +NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR QueIdx); +#endif + +VOID APRxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID APHandleRxDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +VOID APRxErrorHandle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +INT APCheckRxError(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo, RX_BLK *pRxBlk); + +BOOLEAN APChkCls2Cls3Err( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN HEADER_802_11 *pHeader); + +VOID RTMPDescriptorEndianChange(UCHAR *pData, ULONG DescriptorType); + +VOID RTMPFrameEndianChange( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt); + +/* ap_assoc.c */ + +VOID APAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MbssKickOutStas(RTMP_ADAPTER *pAd, INT apidx, USHORT Reason); +VOID APMlmeKickOutSta(RTMP_ADAPTER *pAd, UCHAR *staAddr, UCHAR Wcid, USHORT Reason); + +#ifdef DOT11W_PMF_SUPPORT +VOID APMlmeKickOutAllSta(RTMP_ADAPTER *pAd, UCHAR apidx, USHORT Reason); +#endif /* DOT11W_PMF_SUPPORT */ + +VOID APCls3errAction(RTMP_ADAPTER *pAd, ULONG wcid, HEADER_802_11 *hdr); + +/* ap_auth.c */ + +void APAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APCls2errAction(RTMP_ADAPTER *pAd, ULONG wcid, HEADER_802_11 *hdr); + +/* ap_connect.c */ + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN BeaconTransmitRequired(RTMP_ADAPTER *pAd, INT apidx, MULTISSID_STRUCT *mbss); +#endif /* CONFIG_AP_SUPPORT */ + +VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx); +VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx); +VOID APMakeAllBssBeacon(RTMP_ADAPTER *pAd); +VOID APUpdateAllBeaconFrame(RTMP_ADAPTER *pAd); +void updateAllBeacon(RTMP_ADAPTER *pAd, INT apidx, ULONG FrameLen); + +/* ap_sync.c */ +VOID APSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ApSiteSurvey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_SSID pSsid, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel); + +#ifdef CUSTOMER_DCC_FEATURE +UCHAR Channel2Index( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +VOID ApSiteSurveyNew( + IN PRTMP_ADAPTER pAd, + IN UINT Channel, + IN UINT Timeout, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel); + +VOID RemoveOldBssEntry( + IN PRTMP_ADAPTER pAd); + +VOID RemoveOldStaList( + IN PRTMP_ADAPTER pAd); + +VOID ReadChannelStats( + IN UINT32 Ch_Busy_time, + IN PRTMP_ADAPTER pAd); + +VOID ClearChannelStats( + IN PRTMP_ADAPTER pAd); + +VOID ResetChannelStatus( + IN PRTMP_ADAPTER pAd); + +VOID APResetStreamingStatus( + IN PRTMP_ADAPTER pAd); +#endif +VOID SupportRate( + IN PUCHAR SupRate, + IN UCHAR SupRateLen, + IN PUCHAR ExtRate, + IN UCHAR ExtRateLen, + OUT PUCHAR *Rates, + OUT PUCHAR RatesLen, + OUT PUCHAR pMaxSupportRate); + + +BOOLEAN ApScanRunning(RTMP_ADAPTER *pAd); + +#ifdef AP_PARTIAL_SCAN_SUPPORT +UCHAR FindPartialScanChannel( + IN PRTMP_ADAPTER pAd); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +VOID APUpdateOperationMode(RTMP_ADAPTER *pAd); + +#ifdef DOT11N_DRAFT3 +VOID APOverlappingBSSScan(RTMP_ADAPTER *pAd); + +INT GetBssCoexEffectedChRange( + IN RTMP_ADAPTER *pAd, + IN BSS_COEX_CH_RANGE *pCoexChRange); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + +/* ap_mlme.c */ +VOID APMlmePeriodicExec(RTMP_ADAPTER *pAd); + +BOOLEAN APMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APAsicEvaluateRxAnt(RTMP_ADAPTER *pAd); +VOID APAsicRxAntEvalTimeout(RTMP_ADAPTER *pAd); + +/* ap.c */ +UCHAR get_apidx_by_addr(RTMP_ADAPTER *pAd, UCHAR *addr); + +NDIS_STATUS APInitialize(RTMP_ADAPTER *pAd); +VOID APShutdown(RTMP_ADAPTER *pAd); +VOID APStartUp(RTMP_ADAPTER *pAd); +VOID APStop(RTMP_ADAPTER *pAd); + +VOID APCleanupPsQueue(RTMP_ADAPTER *pAd, QUEUE_HEADER *pQueue); + + +VOID MacTableMaintenance(RTMP_ADAPTER *pAd); + +UINT32 MacTableAssocStaNumGet(RTMP_ADAPTER *pAd); + +MAC_TABLE_ENTRY *APSsPsInquiry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate); + +#ifdef SYSTEM_LOG_SUPPORT +VOID ApLogEvent( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Event); +#else +#define ApLogEvent(_pAd, _pAddr, _Event) +#endif /* SYSTEM_LOG_SUPPORT */ + +VOID APUpdateCapabilityAndErpIe(RTMP_ADAPTER *pAd); + +BOOLEAN ApCheckAccessControlList(RTMP_ADAPTER *pAd, UCHAR *addr, UCHAR apidx); +VOID ApUpdateAccessControlList(RTMP_ADAPTER *pAd, UCHAR apidx); + + +BOOLEAN PeerAssocReqCmmSanity( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isRessoc, + IN VOID *Msg, + IN INT MsgLen, + IN IE_LISTS *ie_lists); + + +BOOLEAN PeerDisassocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr1, + OUT PUCHAR pAddr2, + OUT UINT16 *SeqNum, + OUT USHORT *Reason); + +BOOLEAN PeerDeauthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT UINT16 *SeqNum, + OUT USHORT *Reason); + +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, + OUT CHAR *ChlgText +#ifdef DOT11R_FT_SUPPORT + ,OUT PFT_INFO pFtInfo +#endif /* DOT11R_FT_SUPPORT */ + ); + +#ifdef DOT1X_SUPPORT +INT Set_OwnIPAddr_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_EAPIfName_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_PreAuthIfName_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +/* Define in ap.c */ +BOOLEAN DOT1X_InternalCmdAction( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UINT8 cmd); + +BOOLEAN DOT1X_EapTriggerAction(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* DOT1X_SUPPORT */ + +#ifdef AIRPLAY_SUPPORT +#define AIRPLAY_ON(_pAd) ((_pAd)->bAirplayEnable == 1) +#endif /* AIRPLAY_SUPPORT */ + +VOID AP_E2PROM_IOCTL_PostCtrl(RTMP_IOCTL_INPUT_STRUCT *wrq, PSTRING msg); + +VOID IAPP_L2_UpdatePostCtrl(RTMP_ADAPTER *pAd, UINT8 *mac, INT bssid); + +#endif /* __AP_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_apcli.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_apcli.h new file mode 100644 index 000000000..86d774f7b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_apcli.h @@ -0,0 +1,315 @@ +/* + *************************************************************************** + * 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_apcli.h + + Abstract: + Support AP-Client function. + + Revision History: + Who When What + -------------- ---------- ---------------------------------------------- + Shiang, Fonchi 02-13-2007 created +*/ + +#ifndef _AP_APCLI_H_ +#define _AP_APCLI_H_ + +#ifdef APCLI_SUPPORT + +#include "rtmp.h" + +#define AUTH_TIMEOUT 300 /* unit: msec */ +#define ASSOC_TIMEOUT 300 /* unit: msec */ +/*#define JOIN_TIMEOUT 2000 // unit: msec // not used in Ap-client mode, remove it */ +#define PROBE_TIMEOUT 1000 /* unit: msec */ +#ifdef APCLI_CONNECTION_TRIAL +#define TRIAL_TIMEOUT 400 /* unit: msec */ +#endif /* APCLI_CONNECTION_TRIAL */ +#define OPENWEP_ERRPKT_MAX_COUNT 3 + + +#define APCLI_ROOT_BSSID_GET(pAd, wcid) ((pAd)->MacTab.Content[(wcid)].Addr) + +/* sanity check for apidx */ +#define APCLI_MR_APIDX_SANITY_CHECK(idx) \ +{ \ + if ((idx) >= MAX_APCLI_NUM) \ + { \ + (idx) = 0; \ + DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apcli-idx > MAX_APCLI_NUM!\n", __FUNCTION__)); \ + } \ +} + +typedef struct _APCLI_MLME_JOIN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; +} APCLI_MLME_JOIN_REQ_STRUCT; + +typedef struct _APCLI_CTRL_MSG_STRUCT { + USHORT Status; + UCHAR SrcAddr[MAC_ADDR_LEN]; +#ifdef MAC_REPEATER_SUPPORT + UCHAR BssIdx; + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ +} APCLI_CTRL_MSG_STRUCT, *PSTA_CTRL_MSG_STRUCT; + +BOOLEAN isValidApCliIf( + SHORT ifIndex); + +VOID ApCliCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ApCliSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ApCliAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ApCliAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid( + IN RTMP_ADAPTER *pAd, + IN UCHAR wcid, + IN UCHAR *pAddrs); + +BOOLEAN ApCliValidateRSNIE( + IN RTMP_ADAPTER *pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx); + + +VOID ApCli_Remove( + IN PRTMP_ADAPTER pAd); + +VOID RT28xx_ApCli_Close( + IN PRTMP_ADAPTER pAd); + + + +INT ApCliIfLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + + +VOID ApCliMgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid, + IN USHORT ifIndex); + +#ifdef DOT11_N_SUPPORT +BOOLEAN ApCliCheckHt( + IN PRTMP_ADAPTER pAd, + IN USHORT IfIndex, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC +BOOLEAN ApCliCheckVht( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN MAC_TABLE_ENTRY *pEntry, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op); +#endif /* DOT11_VHT_AC */ + +BOOLEAN ApCliLinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID ApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID ApCliIfUp( + IN PRTMP_ADAPTER pAd); + +VOID ApCliIfDown( + IN PRTMP_ADAPTER pAd); + +VOID ApCliIfMonitor( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ApCliMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +BOOLEAN preCheckMsgTypeSubset( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +BOOLEAN ApCliPeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *ie_list); + +VOID ApCliPeerPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApCliPeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApCliPeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +BOOLEAN ApCliCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset); + +BOOLEAN ApCliParseKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR IfIdx, + IN UCHAR bPairewise); + +BOOLEAN ApCliHandleRxBroadcastFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FromWhichBSSID); + +VOID APCliInstallPairwiseKey( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN APCliInstallSharedKey( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyLen, + IN UCHAR DefaultKeyIdx, + IN MAC_TABLE_ENTRY *pEntry); + +VOID ApCliCheckPeerExistence( + IN RTMP_ADAPTER *pAd, + IN CHAR *Ssid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +VOID ApCliUpdateMlmeRate(RTMP_ADAPTER *pAd, USHORT ifIndex); + +VOID APCli_Init( + IN RTMP_ADAPTER *pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +BOOLEAN ApCli_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +BOOLEAN ApCli_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +BOOLEAN ApCli_StatsGet(RTMP_ADAPTER *pAd, RT_CMD_STATS64 *pStats); +BOOLEAN ApCliWaitProbRsp(RTMP_ADAPTER *pAd, USHORT ifIndex); +VOID ApCliSimulateRecvBeacon(RTMP_ADAPTER *pAd); +#ifdef APCLI_AUTO_BW_SUPPORT +BOOLEAN ApCliAutoBwAction(PRTMP_ADAPTER pAd, USHORT ifIndex); +BOOLEAN ApCliSetPhyMode(PRTMP_ADAPTER pAd, USHORT ifIndex, UINT wmode); +INT Set_ApCli_Bw_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_ApCli_PhyMode_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +#endif /* APCLI_AUTO_BW_SUPPORT */ + +#ifdef APCLI_AUTO_CONNECT_SUPPORT +BOOLEAN ApCliSetIfState( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN state); + +BOOLEAN ApCliSetBssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN UCHAR *Bssid); + +BOOLEAN ApCliAutoConnectStart( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +BOOLEAN ApCliAutoConnectExec( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ApcliCompareAuthEncryp( + IN PAPCLI_STRUCT pApCliEntry, + IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, + IN NDIS_802_11_AUTHENTICATION_MODE AuthModeAux, + IN NDIS_802_11_WEP_STATUS WEPstatus, + IN CIPHER_SUITE WPA); + +VOID ApCliSwitchCandidateAP( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID RTMPApCliReconnectionCheck( + IN PRTMP_ADAPTER pAd); + +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +VOID ApCliRxOpenWEPCheck( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN BOOLEAN bSuccessPkt); + +VOID ApCliSiteSurvey( + IN RTMP_ADAPTER *pAd, + IN UCHAR ifIndex, + IN NDIS_802_11_SSID *pSsid, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel); +#endif /* APCLI_SUPPORT */ +#endif /* _AP_APCLI_H_ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_autoChSel.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_autoChSel.h new file mode 100644 index 000000000..79dbf9cf8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_autoChSel.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * 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. + **************************************************************************** + + Abstract: + + + */ + +#include "ap_autoChSel_cmm.h" + +#ifndef __AUTOCHSELECT_H__ +#define __AUTOCHSELECT_H__ + +#define AP_AUTO_CH_SEL(__P, __O) APAutoSelectChannel((__P), (__O)) + +ULONG AutoChBssSearchWithSSID( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +VOID APAutoChannelInit( + IN PRTMP_ADAPTER pAd); + +VOID UpdateChannelInfo( + IN PRTMP_ADAPTER pAd, + IN int ch, + IN ChannelSel_Alg Alg); + +#ifdef CUSTOMER_DCC_FEATURE +VOID ChannelInfoResetNew( + IN PRTMP_ADAPTER pAd); +#endif +ULONG AutoChBssInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR ChannelNo, + IN UCHAR ExtChOffset, + IN CHAR Rssi); + +VOID AutoChBssTableInit( + IN PRTMP_ADAPTER pAd); + +VOID ChannelInfoInit( + IN PRTMP_ADAPTER pAd); + +VOID AutoChBssTableDestroy( + IN PRTMP_ADAPTER pAd); + +VOID ChannelInfoDestroy( + IN PRTMP_ADAPTER pAd); + +VOID CheckPhyModeIsABand( + IN PRTMP_ADAPTER pAd); + +UCHAR SelectBestChannel( + IN PRTMP_ADAPTER pAd, + IN ChannelSel_Alg Alg); + +UCHAR APAutoSelectChannel( + IN PRTMP_ADAPTER pAd, + IN ChannelSel_Alg Alg); + +#ifdef AP_SCAN_SUPPORT +VOID AutoChannelSelCheck( + IN PRTMP_ADAPTER pAd); +#endif /* AP_SCAN_SUPPORT */ + +#endif /* __AUTOCHSELECT_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_autoChSel_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_autoChSel_cmm.h new file mode 100644 index 000000000..adeb136cd --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_autoChSel_cmm.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * 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. + **************************************************************************** + + Abstract: + + + */ + + +#ifndef __AUTOCHSELECT_CMM_H__ +#define __AUTOCHSELECT_CMM_H__ + +/* Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). */ +/* SHould not refer to this constant anymore */ +//#define RSSI_TO_DBM_OFFSET 120 /* RSSI-115 = dBm */ + + +typedef struct { + ULONG dirtyness[MAX_NUM_OF_CHANNELS+1]; + ULONG ApCnt[MAX_NUM_OF_CHANNELS+1]; + UINT32 FalseCCA[MAX_NUM_OF_CHANNELS+1]; + BOOLEAN SkipList[MAX_NUM_OF_CHANNELS+1]; +#ifdef CUSTOMER_DCC_FEATURE + UINT32 chanbusytime[MAX_NUM_OF_CHANNELS+1]; + UINT32 ChannelNo; + BOOLEAN GetChannelInfo; +#else +#ifdef AP_QLOAD_SUPPORT + UINT32 chanbusytime[MAX_NUM_OF_CHANNELS+1]; /* QLOAD ALARM */ +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CUSTOMER_DCC_FEATURE */ + BOOLEAN IsABand; +} CHANNELINFO, *PCHANNELINFO; + +typedef struct { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR Channel; + UCHAR ExtChOffset; + CHAR Rssi; +} BSSENTRY, *PBSSENTRY; + +typedef struct { + UCHAR BssNr; + BSSENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; +} BSSINFO, *PBSSINFO; + +typedef enum ChannelSelAlg +{ + ChannelAlgRandom, /*use by Dfs */ + ChannelAlgApCnt, + ChannelAlgCCA +} ChannelSel_Alg; + +#endif /* __AUTOCHSELECT_CMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_cfg.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_cfg.h new file mode 100644 index 000000000..3956fb5d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_cfg.h @@ -0,0 +1,201 @@ +#ifndef __AP_CFG_H__ +#define __AP_CFG_H__ + + +#include "rt_config.h" + +INT RTMPAPPrivIoctlSet( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +INT RTMPAPPrivIoctlShow( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +VOID RTMPAPGetAssoMacTable( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +INT RTMPAPPrivIoctlAR9Show( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +VOID RTMPAR9IoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetSTAT2( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetRadioDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ + +INT RTMPAPSetInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +INT RTMPAPQueryInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +VOID RTMPIoctlStatistics( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetMacTableStaInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + + +VOID RTMPAPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#if defined(DBG) || defined(RALINK_ATE) +VOID RTMPAPIoctlBBP( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPAPIoctlMAC( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#ifdef RTMP_RF_RW_SUPPORT +VOID RTMPAPIoctlRF( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* RTMP_RF_RW_SUPPORT */ + +#endif /* DBG */ + +VOID RtmpDrvRateGet( + IN VOID *pReserved, + IN UINT8 MODE, + IN UINT8 ShortGI, + IN UINT8 BW, + IN UINT8 MCS, + IN UINT8 Antena, + OUT UINT32 *pRate); + +#ifdef WSC_AP_SUPPORT +VOID RTMPIoctlWscProfile( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlWscProfile( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +/*add by woody */ +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +VOID RTMPAR9IoctlWscProfile( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlWscPINCode( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + + +VOID RTMPIoctlWscStatus( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetWscDynInfo( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetWscRegsDynInfo( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif/*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +VOID RTMPIoctlQueryBaTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT1X_SUPPORT +VOID RTMPIoctlStaticWepCopy( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlRadiusData( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlAddWPAKey( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlSetIdleTimeout( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlQueryStaAid( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* DOT1X_SUPPORT */ + +INT Set_AP_Daemon_Status( + IN PRTMP_ADAPTER pAd, + IN UINT8 WorkSpaceID, + IN BOOLEAN Status); + +INT Set_AP_IE( + IN PRTMP_ADAPTER pAd, + IN PSTRING IE, + IN UINT32 IELen); + +#ifdef CONFIG_HOTSPOT +INT Send_ANQP_Rsp( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING ANQPReq, + IN UINT32 ANQPReqLen); +#endif + +INT ApCfg_Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PSTRING arg); + +INT ApCfg_Set_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PSTRING arg); + +INT ApCfg_Set_IdleTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +VOID RTMPApCliAddKey( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PNDIS_APCLI_802_11_KEY pApcliKey); +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* __AP_CFG_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_diversity.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_diversity.h new file mode 100644 index 000000000..b3a9d9458 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_diversity.h @@ -0,0 +1,141 @@ +/*************************************************************************** + * 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_diversity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------- + YY Huang 06-10-2008 Init for RT3052. +*/ + +#ifndef _AP_DIVERSITY_H_ +#define _AP_DIVERSITY_H_ + +#include "rtmp.h" + +#define ADDBGPRINT(format,args...) do{if(atomic_read(&DEBUG_VERBOSE_MODE)) printk( format, ##args);}while(0) +#define PROC_DIR "AntDiv" + +/* + * For shorter udelay(). + * (ripped from rtmp.h) + */ +/* Read BBP register by register's ID. Generate PER to test BA */ +#define RTMP_BBP_IO_READ8_BY_REG_ID_SHORT_DELAY(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int i, k; \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + for (i=0; iBbpWriteLatch[_I]; \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word);\ + BbpCsr.field.Busy = 0; \ + RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word);\ + } \ + } \ +} + + +/* + * proc fs related macros. + */ +#define CREATE_PROC_ENTRY(x) \ + if ((pProc##x = create_proc_entry(#x, 0, pProcDir))){ \ + pProc##x->read_proc = (read_proc_t*)&x##Read; \ + pProc##x->write_proc = (write_proc_t*)&x##Write; \ + } \ + +#define IMPLEMENT_PROC_ENTRY(x,y,z) \ +static struct proc_dir_entry *pProc##x; \ +IMPLEMENT_PROC_ENTRY_READ(x,y,z) \ +IMPLEMENT_PROC_ENTRY_WRITE(x,y,z) + +#define IMPLEMENT_PROC_ENTRY_READ(x,y,z) \ +static INT x##Read(char *page, char **start, off_t off, \ + int count, int *eof, void *data){ \ + INT len; \ + sprintf(page, "%d\n", atomic_read(&x)); \ + len = strlen(page) + 1; \ + *eof = 1; \ + return len; \ +} +#define IMPLEMENT_PROC_ENTRY_WRITE(x,y,z) \ +static INT x##Write(struct file *file, const char *buffer, \ + unsigned long count, void *data){ \ + CHAR tmp[32];INT tmp_val; \ + if (count > 32) count = 32; \ + memset(tmp, 0, 32); \ + if (copy_from_user(tmp, buffer, count)) \ + return -EFAULT; \ + tmp_val = simple_strtol(tmp, 0, 10); \ + if(tmp_val > z || tmp_val < y) \ + return -EFAULT; \ + atomic_set(&x, (int)tmp_val); \ + return count; \ +} +#define DESTORY_PROC_ENTRY(x) if (pProc##x) remove_proc_entry(#x, pProcDir); + +/* + * function prototype + */ +VOID RT3XXX_AntDiversity_Init( + IN RTMP_ADAPTER *pAd); + +VOID RT3XXX_AntDiversity_Fini( + IN RTMP_ADAPTER *pAd); + +VOID AntDiversity_Update_Rssi_Sample( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi, + IN RXWI_STRUC *pRxWI); + + +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_ids.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_ids.h new file mode 100644 index 000000000..c71dd80d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_ids.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * 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: + IDS definition + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + */ + +VOID RTMPIdsPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN RTMPSpoofedMgmtDetection( + IN RTMP_ADAPTER *pAd, + IN HEADER_802_11 *pHeader, + IN RX_BLK *rxblk); + +VOID RTMPConflictSsidDetection( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +BOOLEAN RTMPReplayAttackDetection( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr2, + IN RX_BLK *rxblk); + +VOID RTMPUpdateStaMgmtCounter( + IN PRTMP_ADAPTER pAd, + IN USHORT type); + +VOID RTMPClearAllIdsCounter( + IN PRTMP_ADAPTER pAd); + +VOID RTMPIdsStart( + IN PRTMP_ADAPTER pAd); + +VOID RTMPIdsStop( + IN PRTMP_ADAPTER pAd); + +VOID rtmp_read_ids_from_file( + IN PRTMP_ADAPTER pAd, + char *tmpbuf, + char *buffer); + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_mbss.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_mbss.h new file mode 100644 index 000000000..7e180c866 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_mbss.h @@ -0,0 +1,81 @@ +/* + *************************************************************************** + * 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_mbss.h + + Abstract: + Support multi-BSS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sample Lin 01-02-2007 created +*/ + + +/* + For MBSS, the phy mode is different; + So MBSS_PHY_MODE_RESET() can help us to adjust the correct mode & + maximum MCS for the BSS. +*/ +#define MBSS_PHY_MODE_RESET(__BssId, __HtPhyMode) \ + { \ + UCHAR __PhyMode = pAd->ApCfg.MBSSID[__BssId].wdev.PhyMode; \ + if ((__PhyMode == WMODE_B) && \ + (__HtPhyMode.field.MODE != MODE_CCK)) \ + { \ + __HtPhyMode.field.MODE = MODE_CCK; \ + __HtPhyMode.field.MCS = 3; \ + } \ + else if ((!WMODE_CAP_N(__PhyMode)) && \ + (__PhyMode != WMODE_B) && \ + (__HtPhyMode.field.MODE != MODE_OFDM)) \ + { \ + __HtPhyMode.field.MODE = MODE_OFDM; \ + __HtPhyMode.field.MCS = 7; \ + } \ + else if ((__PhyMode != WMODE_B) && \ + (__PhyMode != WMODE_G) && \ + (__PhyMode != WMODE_A) && \ + (!WMODE_CAP_AC(__PhyMode)) && \ + (WMODE_CAP_N(__PhyMode))) \ + { \ + __HtPhyMode.field.MODE = MODE_HTMIX; \ + } \ + else if (WMODE_CAP_AC(__PhyMode)) \ + { \ + __HtPhyMode.field.MODE = MODE_VHT; \ + __HtPhyMode.field.MCS = 9; \ + } \ + } + + +/* Public function list */ +INT Show_MbssInfo_Display_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +VOID MBSS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +VOID MBSS_Remove(RTMP_ADAPTER *pAd); + +INT MBSS_Open(PNET_DEV pDev); + +INT MBSS_Close(PNET_DEV pDev); + +INT32 RT28xx_MBSS_IdxGet( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV pDev); + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_wds.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_wds.h new file mode 100644 index 000000000..952861f23 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ap_wds.h @@ -0,0 +1,183 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + Support WDS function. + + Revision History: + Who When What + ------ ---------- ---------------------------------------------- + Fonchi 02-13-2007 created +*/ + + +#ifndef _AP_WDS_H_ +#define _AP_WDS_H_ + +#define WDS_ENTRY_RETRY_INTERVAL (100 * OS_HZ / 1000) + +#ifdef WDS_VLAN_SUPPORT /* support WDS VLAN */ +#define WDS_VLAN_INFO_GET( \ + __pAd, __VLAN_VID, __VLAN_Priority, __FromWhichBSSID) \ +{ \ + if ((__FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) && \ + (__FromWhichBSSID < (MIN_NET_DEVICE_FOR_WDS+MAX_WDS_ENTRY)) && \ + (__pAd->WdsTab.WdsEntry[__FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].wdev.VLAN_VID != 0)) \ + { \ + __VLAN_VID = __pAd->WdsTab.WdsEntry[ \ + __FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].wdev.VLAN_VID; \ + __VLAN_Priority = __pAd->WdsTab.WdsEntry[ \ + __FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].wdev.VLAN_Priority;\ + } \ +} +#else +#define WDS_VLAN_INFO_GET( \ + __pAd, __VLAN_VID, __VLAN_Priority, __FromWhichBSSID) +#endif /* WDS_VLAN_SUPPORT */ + +static inline BOOLEAN WDS_IF_UP_CHECK( + IN PRTMP_ADAPTER pAd, + IN ULONG ifidx) +{ + if ((pAd->flg_wds_init != TRUE) || + (ifidx >= MAX_WDS_ENTRY)) + return FALSE; + +/* if(RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[ifidx].dev)) */ +/* Patch for wds ,when dirver call apmlmeperiod => APMlmeDynamicTxRateSwitching check if wds device ready */ +if ((pAd->WdsTab.WdsEntry[ifidx].wdev.if_dev != NULL) && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[ifidx].wdev.if_dev))) + return TRUE; + + return FALSE; +} + +LONG WdsEntryAlloc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID WdsEntryDel( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *MacTableInsertWDSEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + UINT WdsTabIdx); + +BOOLEAN MacTableDeleteWDSEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *WdsTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *WdsTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *FindWdsEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN PUCHAR pAddr, + IN UINT32 PhyMode); + +VOID WdsTableMaintenance( + IN PRTMP_ADAPTER pAd); + + +VOID WdsDown( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateWdsRxWCIDTable( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateWdsEncryption( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid); + +VOID WdsPeerBeaconProc( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR MaxSupportedRateLen, + IN BOOLEAN bWmmCapable, + IN ULONG ClientRalinkIe, +#ifdef DOT11_VHT_AC + IN UCHAR vht_cap_len, + IN VHT_CAP_IE *vht_cap, +#endif /* DOT11_VHT_AC */ + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +VOID APWdsInitialize(RTMP_ADAPTER *pAd); + +INT Show_WdsTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID rtmp_read_wds_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + +VOID WdsPrepareWepKeyFromMainBss(RTMP_ADAPTER *pAd); + +VOID RT28xx_WDS_Close(RTMP_ADAPTER *pAd); +VOID WDS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); +VOID WDS_Remove(RTMP_ADAPTER *pAd); +BOOLEAN WDS_StatsGet(RTMP_ADAPTER *pAd, RT_CMD_STATS64 *pStats); +VOID AP_WDS_KeyNameMakeUp(STRING *pKey, UINT32 KeyMaxSize, INT KeyId); + +/* + ========================================================================== + Description: + Check the WDS Entry is valid or not. + ========================================================================== + */ +static inline BOOLEAN ValidWdsEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WdsIndex) +{ + BOOLEAN result = FALSE; + PMAC_TABLE_ENTRY pMacEntry; + + if ((WdsIndex < MAX_WDS_ENTRY) && + (pAd->WdsTab.WdsEntry[WdsIndex].Valid == TRUE)) + { + if ((pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID > 0) && + (pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID < MAX_LEN_OF_MAC_TABLE)) + { + pMacEntry = &pAd->MacTab.Content[pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID]; + if (IS_ENTRY_WDS(pMacEntry)) + result = TRUE; + } + } + + return result; +} + +#endif /* _AP_WDS_H_ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/band_steering.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/band_steering.h new file mode 100644 index 000000000..a3f30261f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/band_steering.h @@ -0,0 +1,101 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + band_steering.h +*/ + +#ifndef _BAND_STEERING_H_ +#define __BAND_STEERING_H__ + +#ifdef BAND_STEERING + +/* ioctl */ +INT Show_BndStrg_List(PRTMP_ADAPTER pAd, PSTRING arg); +INT Show_BndStrg_Info(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_Enable(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_RssiDiff(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_RssiLow(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_Age(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_HoldTime(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_CheckTime5G(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_FrmChkFlag(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_BndStrg_CndChkFlag(PRTMP_ADAPTER pAd, PSTRING arg); +#ifdef BND_STRG_DBG +INT Set_BndStrg_MonitorAddr(PRTMP_ADAPTER pAd, PSTRING arg); +#endif /* BND_STRG_DBG */ + +INT BndStrg_Init(PRTMP_ADAPTER pAd); +INT BndStrg_Release(PRTMP_ADAPTER pAd); +INT BndStrg_TableInit(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table); +INT BndStrg_TableRelease(PBND_STRG_CLI_TABLE table); + +BOOLEAN BndStrg_CheckConnectionReq( + PRTMP_ADAPTER pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi); + +INT BndStrg_Enable(PBND_STRG_CLI_TABLE table, BOOLEAN enable); +INT BndStrg_SetInfFlags(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BOOLEAN bInfReady); +BOOLEAN BndStrg_IsClientStay(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY pEntry); +INT BndStrg_MsgHandle(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq); + + + + +/* Macro */ +#define IS_BND_STRG_DUAL_BAND_CLIENT(_Control_Flags) \ + ((_Control_Flags & fBND_STRG_CLIENT_SUPPORT_2G) && (_Control_Flags & fBND_STRG_CLIENT_SUPPORT_5G)) + +#define BND_STRG_CHECK_CONNECTION_REQ(_pAd, _wdev, _SrcAddr, _FrameType, _Rssi0, _Rssi1, _Rssi2, _pRet) \ +{ \ + CHAR Rssi[3] = {0}; \ + Rssi[0] = _Rssi0 ? ConvertToRssi(_pAd, (CHAR)_Rssi0, RSSI_0) : 0; \ + Rssi[1] = _Rssi1 ? ConvertToRssi(_pAd, (CHAR)_Rssi1, RSSI_1) : 0; \ + Rssi[2] = _Rssi2 ? ConvertToRssi(_pAd, (CHAR)_Rssi2, RSSI_2) : 0; \ +\ + *_pRet = BndStrg_CheckConnectionReq( _pAd, \ + _SrcAddr, \ + _FrameType, \ + Rssi); \ +} + +#ifdef BND_STRG_DBG +#define RED(_text) "\033[1;31m"_text"\033[0m" +#define GRN(_text) "\033[1;32m"_text"\033[0m" +#define YLW(_text) "\033[1;33m"_text"\033[0m" +#define BLUE(_text) "\033[1;36m"_text"\033[0m" + +#define BND_STRG_DBGPRINT(_Level, _Fmt) DBGPRINT(_Level, _Fmt) +#else /* BND_STRG_DBG */ +#define RED(_text) _text +#define GRN(_text) _text +#define YLW(_text) _text +#define BLUE(_text) _text + +#define BND_STRG_DBGPRINT(_Level, _Fmt) +#endif /* !BND_STRG_DBG */ + +#ifdef BND_STRG_QA +#define BND_STRG_PRINTQAMSG(_table, _Addr, _Fmt) \ +{ \ + if (MAC_ADDR_EQUAL(_table->MonitorAddr, _Addr)) \ + DBGPRINT(RT_DEBUG_OFF, _Fmt); \ +} +#else +#define BND_STRG_PRINTQAMSG(_Level, _Fmt) +#endif /* BND_STRG_QA */ + +#endif /* BAND_STEERING */ +#endif /* _BAND_STEERING_H_ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/band_steering_def.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/band_steering_def.h new file mode 100644 index 000000000..55fd589ca --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/band_steering_def.h @@ -0,0 +1,255 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + band_steering_def.h +*/ + +#ifndef _BAND_STEERING_DEF_H_ +#define __BAND_STEERING_DEF_H__ + +#ifdef BAND_STEERING +#ifndef DOT11_N_SUPPORT +#error: "DOT11_N_SUPPORT must be enabled when using band steering" +#endif /* DOT11_N_SUPPORT */ + +/* use daemon */ +#define BNDSTRG_DAEMON +#define BND_STRG_MAX_TABLE_SIZE 64 +#define BND_STRG_TIMER_PERIOD 1000 +#define BND_STRG_AGE_TIME 150000 +#define BND_STRG_HOLD_TIME 90000 +#define BND_STRG_CHECK_TIME_5G 30000 +#define BND_STRG_RSSI_DIFF 30 +#define BND_STRG_RSSI_LOW -70 +#define BND_STRG_AUTO_ONOFF_THRD 4000 +#define P_BND_STRG_TABLE (&pAd->ApCfg.BndStrgTable) + +#define BND_STRG_DBG +#define BND_STRG_QA + +struct _BNDSTRG_OPS; + +typedef struct _BND_STRG_ENTRY_STATISTICS{ + CHAR Rssi; + UINT8 AuthReqCount; +} BND_STRG_ENTRY_STAT, *PBND_STRG_ENTRY_STAT; + +typedef struct _BND_STRG_CLI_ENTRY{ + BOOLEAN bValid; + UINT32 Control_Flags; + ULONG jiffies; /* timestamp when insert-entry */ + UINT32 elapsed_time; /* ms */ + UCHAR Addr[MAC_ADDR_LEN]; + struct _BND_STRG_CLI_ENTRY *pNext; +} BND_STRG_CLI_ENTRY, *PBND_STRG_CLI_ENTRY; + +/* for setting different band steering algorithms */ +typedef struct _BND_STRG_ALG_CONTROL { + UINT32 FrameCheck; + UINT32 ConditionCheck; +} BND_STRG_ALG_CONTROL, *PBND_STRG_ALG_CONTROL; + +typedef struct _BND_STRG_CLI_TABLE{ + BOOLEAN bInitialized; + BOOLEAN bEnabled; + UINT32 Size; + BND_STRG_ALG_CONTROL AlgCtrl; + BND_STRG_CLI_ENTRY Entry[BND_STRG_MAX_TABLE_SIZE]; + PBND_STRG_CLI_ENTRY Hash[HASH_TABLE_SIZE]; + NDIS_SPIN_LOCK Lock; + struct _BNDSTRG_OPS *Ops; + VOID *priv; + BOOLEAN b2GInfReady; + BOOLEAN b5GInfReady; + CHAR RssiDiff; /* if Rssi2.4G > Rssi5G by RssiDiff, then allow client to connect 2.4G */ + CHAR RssiLow; /* if Rssi5G < RssiLow, then this client cannot connect to 5G */ + UINT32 AgeTime; /* Entry Age Time (ms) */ + UINT32 HoldTime; /* Time for holding 2.4G connection rsp (ms) */ + UINT32 CheckTime_5G; /* Time for deciding if a client is 2.4G only (ms) */ + RALINK_TIMER_STRUCT Timer; +#ifdef BND_STRG_DBG + UCHAR MonitorAddr[MAC_ADDR_LEN]; +#endif /* BND_STRG_DBG */ + UINT8 Band; + UINT32 AutoOnOffThrd; /* Threshold to auto turn bndstrg on/off by 2.4G false CCA */ + BOOLEAN bDaemonReady; +} BND_STRG_CLI_TABLE, *PBND_STRG_CLI_TABLE; + +enum BND_STRG_RETURN_CODE { + BND_STRG_SUCCESS = 0, + BND_STRG_INVALID_ARG, + BND_STRG_RESOURCE_ALLOC_FAIL, + BND_STRG_TABLE_FULL, + BND_STRG_TABLE_IS_NULL, + BND_STRG_NOT_INITIALIZED, + BND_STRG_2G_INF_NOT_READY, + BND_STRG_5G_INF_NOT_READY, + BND_STRG_STA_IS_CONNECTED, + BND_STRG_UNEXP, +}; + +enum BND_STRG_CONTROL_FLAGS { + fBND_STRG_CLIENT_SUPPORT_2G = (1 << 0), + fBND_STRG_CLIENT_SUPPORT_5G = (1 << 1), + fBND_STRG_CLIENT_ALLOW_TO_CONNET_2G = (1 << 2), + fBND_STRG_CLIENT_ALLOW_TO_CONNET_5G = (1 << 3), + fBND_STRG_CLIENT_NOT_SUPPORT_HT_2G = (1 << 4), + fBND_STRG_CLIENT_NOT_SUPPORT_HT_5G = (1 << 5), + fBND_STRG_CLIENT_LOW_RSSI_2G = (1 << 6), + fBND_STRG_CLIENT_LOW_RSSI_5G = (1 << 7), + fBND_STRG_CLIENT_IS_2G_ONLY = (1 << 8), + fBND_STRG_CLIENT_IS_5G_ONLY = (1 << 9), +}; + +enum BND_STRG_FRAME_CHECK_FLAGS { + fBND_STRG_FRM_CHK_PRB_REQ = (1 << 0), + fBND_STRG_FRM_CHK_ATH_REQ = (1 << 1), + fBND_STRG_FRM_CHK_ASS_REQ = (1 << 2), +}; + +enum BND_STRG_CONDITION_CHECK_FLAGS { + fBND_STRG_CND_RSSI_DIFF = (1 << 0), + fBND_STRG_CND_2G_PERSIST = (1 << 1), + fBND_STRG_CND_HT_SUPPORT = (1 << 2), + fBND_STRG_CND_5G_RSSI = (1 << 3), +}; + +#define OID_BNDSTRG_MSG 0x0950 +/* Use for I/O between driver and daemon */ +/* Must make sure the structure is the same as the one in daemon */ +typedef struct _BNDSTRG_MSG{ + UINT8 Action; + UINT8 ReturnCode; + UINT8 TalbeIndex; + BOOLEAN OnOff; + UINT8 Band; + BOOLEAN b2GInfReady; + BOOLEAN b5GInfReady; + CHAR Rssi[3]; + CHAR RssiDiff; + CHAR RssiLow; + UINT8 FrameType; + UINT32 Time; + UINT32 ConditionCheck; + UCHAR Addr[MAC_ADDR_LEN]; +} BNDSTRG_MSG, *PBNDSTRG_MSG; + +typedef struct _BNDSTRG_CLI_EVENT{ + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT8 Action; /* add or delete table entry */ +} BNDSTRG_CLI_EVENT, *PBNDSTRG_CLI_EVENT; + +typedef struct _BNDSTRG_PROBE_EVENT{ + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT8 Band; + UINT8 FrameType; + CHAR Rssi[3]; + BOOLEAN bAuthCheck; +} BNDSTRG_PROBE_EVENT, *PBNDSTRG_PROBE_EVENT; + +enum ACTION_CODE{ + CONNECTION_REQ = 1, + CLI_ADD, + CLI_DEL, + CLI_AGING_REQ, + CLI_AGING_RSP, + INF_STATUS_QUERY, + INF_STATUS_RSP_2G, + INF_STATUS_RSP_5G, + TABLE_INFO, + ENTRY_LIST, + BNDSTRG_ONOFF, + SET_RSSI_DIFF, + SET_RSSI_LOW, + SET_AGE_TIME, + SET_HOLD_TIME, + SET_CHECK_TIME, + SET_MNT_ADDR, + SET_CHEK_CONDITIONS, +}; + + + +typedef struct _BNDSTRG_OPS { + VOID (*ShowTableInfo)( + PBND_STRG_CLI_TABLE table); + + VOID (*ShowTableEntries)( + PBND_STRG_CLI_TABLE table); + + INT (*TableEntryAdd)( + BND_STRG_CLI_TABLE *table, + PUCHAR pAddr, + PBND_STRG_CLI_ENTRY *entry_out); + + INT (*TableEntryDel)( + BND_STRG_CLI_TABLE *table, + PUCHAR pAddr, + UINT32 Index); + + PBND_STRG_CLI_ENTRY (*TableLookup)( + BND_STRG_CLI_TABLE *table, + PUCHAR pAddr); + + BOOLEAN (*CheckConnectionReq)( + struct _RTMP_ADAPTER *pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi); + + INT (*SetEnable)( + PBND_STRG_CLI_TABLE table, + BOOLEAN enable); + + INT (*SetRssiDiff)( + PBND_STRG_CLI_TABLE table, + CHAR RssiDiff); + + INT (*SetRssiLow)( + PBND_STRG_CLI_TABLE table, + CHAR RssiLow); + + INT (*SetAgeTime)( + PBND_STRG_CLI_TABLE table, + UINT32 Time); + + INT (*SetHoldTime)( + PBND_STRG_CLI_TABLE table, + UINT32 Time); + + INT (*SetCheckTime)( + PBND_STRG_CLI_TABLE table, + UINT32 Time); + + INT (*SetFrmChkFlag)( + PBND_STRG_CLI_TABLE table, + UINT32 FrmChkFlag); + + INT (*SetCndChkFlag)( + PBND_STRG_CLI_TABLE table, + UINT32 CndChkFlag); + +#ifdef BND_STRG_DBG + INT (*SetMntAddr)( + PBND_STRG_CLI_TABLE table, + PUCHAR Addr); +#endif /* BND_STRG_DBG */ + + VOID (*MsgHandle)( + struct _RTMP_ADAPTER *pAd, + BNDSTRG_MSG *msg); +} BNDSTRG_OPS; + +#endif /* BAND_STEERING */ +#endif /* _BAND_STEERING_DEF_H_ */ + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/br_ftph.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/br_ftph.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/br_ftph.h rename to package/lean/mt/drivers/mt7612e/src/mt76x2/include/br_ftph.h diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211.h new file mode 100644 index 000000000..0504c6400 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * 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 MAC80211/CFG80211 Related Structure & Definition. + +***************************************************************************/ +#ifndef __CFG80211_H__ +#define __CFG80211_H__ + +#ifdef RT_CFG80211_SUPPORT + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +#define random32() prandom_u32() +#endif + +#ifdef CFG80211_BUILD_CHANNEL_LIST +#define RT_REG_RULE(regr, start, end, bw, gain, eirp, reg_flags) \ + regr.freq_range.start_freq_khz = MHZ_TO_KHZ(start); \ + regr.freq_range.end_freq_khz = MHZ_TO_KHZ(end); \ + regr.freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw); \ + regr.power_rule.max_antenna_gain = DBI_TO_MBI(gain);\ + regr.power_rule.max_eirp = DBM_TO_MBM(eirp); \ + regr.flags = reg_flags; +#endif /* CFG80211_BUILD_CHANNEL_LIST */ + +typedef enum _NDIS_HOSTAPD_STATUS { + Hostapd_Diable = 0, + Hostapd_EXT, + Hostapd_CFG +} NDIS_HOSTAPD_STATUS, *PNDIS_HOSTAPD_STATUS; + +typedef struct __CFG80211_CB { + + /* we can change channel/rate information on the fly so we backup them */ + struct ieee80211_supported_band Cfg80211_bands[IEEE80211_NUM_BANDS]; + struct ieee80211_channel *pCfg80211_Channels; + struct ieee80211_rate *pCfg80211_Rates; + + /* used in wiphy_unregister */ + struct wireless_dev *pCfg80211_Wdev; + + /* used in scan end */ + struct cfg80211_scan_request *pCfg80211_ScanReq; + + /* monitor filter */ + UINT32 MonFilterFlag; + + /* channel information */ + struct ieee80211_channel ChanInfo[MAX_NUM_OF_CHANNELS]; + + /* to protect scan status */ + spinlock_t scan_notify_lock; + +} CFG80211_CB; + + + + +/* +======================================================================== +Routine Description: + Register MAC80211 Module. + +Arguments: + pAd - WLAN control block pointer + pDev - Generic device interface + pNetDev - Network device + +Return Value: + NONE + +Note: + pDev != pNetDev + #define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev)) + + Can not use pNetDev to replace pDev; Or kernel panic. +======================================================================== +*/ +BOOLEAN CFG80211_Register( + VOID *pAd, + struct device *pDev, + struct net_device *pNetDev); + +#endif /* RT_CFG80211_SUPPORT */ + +#endif /* __CFG80211_H__ */ + +/* End of cfg80211.h */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211_cmm.h new file mode 100644 index 000000000..cd5ebd898 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211_cmm.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 Function Prototype. + +***************************************************************************/ + + +#ifndef __CFG80211CMM_H__ +#define __CFG80211CMM_H__ + +#ifdef RT_CFG80211_SUPPORT + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +#define CFG80211_GetEventDevice(__pAd) __pAd->cfg80211_ctrl.dummy_p2p_net_dev +#else +#define CFG80211_GetEventDevice(__pAd) __pAd->net_dev +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + +//yiwei debug for P2P 7.1.3 +#ifdef RT_CFG80211_P2P_SUPPORT + +//yiwei tmp hard code +#define IS_SW_NOA_TIMER(_A) (1) + + +#define P2P_OPPS_BIT 0x80 + +/* + * Macros for bit check +*/ + +#define CFG80211_P2P_TEST_BIT(_M, _F) (((_M) & (_F)) != 0) + + + +#define CFG_P2P_DISABLE 0x00000000 +#define CFG_P2P_GO_UP 0x00000001 +#define CFG_P2P_CLI_UP 0x00000002 + +#define IS_CFG80211_P2P_ABSENCE(_A) (((_A)->cfg80211_ctrl.bPreKeepSlient) || ((_A)->cfg80211_ctrl.bKeepSlient)) + +typedef struct _P2PCLIENT_NOA_SCHEDULE { + BOOLEAN bValid; + BOOLEAN bInAwake; + + + UCHAR Token; + + ULONG SwTimerTickCounter; /* this Counter os used for sw-base NoA implementation tick counter */ + + ULONG CurrentTargetTimePoint; /* For sw-base method NoA usage */ + ULONG NextTargetTimePoint; + + UCHAR Count; + ULONG Duration; + ULONG Interval; + ULONG StartTime; + ULONG OngoingAwakeTime; /* this time will keep increasing as time go by. indecate the current awake time point */ + + + ULONG LastBeaconTimeStamp; +} P2PCLIENT_NOA_SCHEDULE, *PP2PCLIENT_NOA_SCHEDULE; + + +typedef struct __CFG_P2P_ENTRY_PARM +{ + UCHAR CTWindow; /* As GO, Store client's Presence request NoA. As Client, Store GO's NoA In beacon or P2P Action frame */ + P2PCLIENT_NOA_SCHEDULE NoADesc[1]; /* As GO, Store client's Presence request NoA. As Client, Store GO's NoA In beacon or P2P Action frame */ +}CFG_P2P_ENTRY_PARM, *PCFG_P2P_ENTRY_PARM; + + +typedef struct { + UCHAR Eid; + UCHAR Len[2]; + CHAR Octet[1]; +} P2PEID_STRUCT,*PP2PEID_STRUCT; + +VOID CFG80211_P2PCTWindowTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID CFG80211_P2pSwNoATimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID CFG80211_P2pPreAbsenTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#endif /* RT_CFG80211_P2P_SUPPORT */ + + +#endif /* RT_CFG80211_SUPPORT */ + +#endif /* __CFG80211CMM_H__ */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211extr.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211extr.h new file mode 100644 index 000000000..94dd1754b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cfg80211extr.h @@ -0,0 +1,411 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 Function Prototype. + +***************************************************************************/ + +#ifndef __CFG80211EXTR_H__ +#define __CFG80211EXTR_H__ + +#ifdef RT_CFG80211_SUPPORT + +#define CFG80211CB (pAd->pCfg80211_CB) +#define RT_CFG80211_DEBUG /* debug use */ +#ifdef RT_CFG80211_DEBUG +#define CFG80211DBG(__Flg, __pMsg) DBGPRINT(__Flg, __pMsg) +#else +#define CFG80211DBG(__Flg, __pMsg) +#endif /* RT_CFG80211_DEBUG */ + +//CFG_TODO +#include "wfa_p2p.h" + +#define RT_CFG80211_REGISTER(__pDev, __pNetDev) \ + CFG80211_Register(__pDev, __pNetDev); + +#define RT_CFG80211_BEACON_CR_PARSE(__pAd, __pVIE, __LenVIE) \ + CFG80211_BeaconCountryRegionParse((VOID *)__pAd, __pVIE, __LenVIE); + +#define RT_CFG80211_BEACON_TIM_UPDATE(__pAd) \ + CFG80211_UpdateBeacon((VOID *)__pAd, NULL, 0, NULL, 0, FALSE); + +#define RT_CFG80211_CRDA_REG_HINT(__pAd, __pCountryIe, __CountryIeLen) \ + CFG80211_RegHint((VOID *)__pAd, __pCountryIe, __CountryIeLen); + +#define RT_CFG80211_CRDA_REG_HINT11D(__pAd, __pCountryIe, __CountryIeLen) \ + CFG80211_RegHint11D((VOID *)__pAd, __pCountryIe, __CountryIeLen); + +#define RT_CFG80211_CRDA_REG_RULE_APPLY(__pAd) \ + CFG80211_RegRuleApply((VOID *)__pAd, NULL, __pAd->cfg80211_ctrl.Cfg80211_Alpha2); + +#define RT_CFG80211_CONN_RESULT_INFORM(__pAd, __pBSSID, __pReqIe, \ + __ReqIeLen, __pRspIe, __RspIeLen, __FlgIsSuccess) \ + CFG80211_ConnectResultInform((VOID *)__pAd, __pBSSID, \ + __pReqIe, __ReqIeLen, __pRspIe, __RspIeLen, __FlgIsSuccess); + +#define RT_CFG80211_SCANNING_INFORM(__pAd, __BssIdx, __ChanId, __pFrame, \ + __FrameLen, __RSSI) \ + CFG80211_Scaning((VOID *)__pAd, __BssIdx, __ChanId, __pFrame, \ + __FrameLen, __RSSI); + +#define RT_CFG80211_SCAN_END(__pAd, __FlgIsAborted) \ + CFG80211_ScanEnd((VOID *)__pAd, __FlgIsAborted); +#ifdef CONFIG_STA_SUPPORT +#define RT_CFG80211_LOST_AP_INFORM(__pAd) \ + CFG80211_LostApInform((VOID *)__pAd); +#endif /*CONFIG_STA_SUPPORT*/ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +#define RT_CFG80211_LOST_GO_INFORM(__pAd) \ + CFG80211_LostP2pGoInform((VOID *)__pAd); +#endif /*RT_CFG80211_P2P_CONCURRENT_DEVICE*/ +#define RT_CFG80211_REINIT(__pAd) \ + CFG80211_SupBandReInit((VOID *)__pAd); + +#define RT_CFG80211_RFKILL_STATUS_UPDATE(_pAd, _active) \ + CFG80211_RFKillStatusUpdate(_pAd, _active); + +#define RT_CFG80211_P2P_CLI_CONN_RESULT_INFORM(__pAd, __pBSSID, __pReqIe, \ + __ReqIeLen, __pRspIe, __RspIeLen, __FlgIsSuccess) \ + CFG80211_P2pClientConnectResultInform(__pAd, __pBSSID, \ + __pReqIe, __ReqIeLen, __pRspIe, __RspIeLen, __FlgIsSuccess); + +#define RT_CFG80211_P2P_CLI_SEND_NULL_FRAME(_pAd, _PwrMgmt) \ + CFG80211_P2pClientSendNullFrame(_pAd, _PwrMgmt); + + +#ifdef SINGLE_SKU +#define CFG80211_BANDINFO_FILL(__pAd, __pBandInfo) \ +{ \ + (__pBandInfo)->RFICType = __pAd->phy_ctrl.rf_band_cap; \ + (__pBandInfo)->MpduDensity = __pAd->CommonCfg.BACapability.field.MpduDensity;\ + (__pBandInfo)->TxStream = __pAd->CommonCfg.TxStream; \ + (__pBandInfo)->RxStream = __pAd->CommonCfg.RxStream; \ + (__pBandInfo)->MaxTxPwr = __pAd->CommonCfg.DefineMaxTxPwr; \ + if (WMODE_EQUAL(__pAd->CommonCfg.PhyMode, WMODE_B)) \ + (__pBandInfo)->FlgIsBMode = TRUE; \ + else \ + (__pBandInfo)->FlgIsBMode = FALSE; \ + (__pBandInfo)->MaxBssTable = MAX_LEN_OF_BSS_TABLE; \ + (__pBandInfo)->RtsThreshold = pAd->CommonCfg.RtsThreshold; \ + (__pBandInfo)->FragmentThreshold = pAd->CommonCfg.FragmentThreshold; \ + (__pBandInfo)->RetryMaxCnt = 0; \ + RTMP_IO_READ32(__pAd, TX_RTY_CFG, &((__pBandInfo)->RetryMaxCnt)); \ +} +#else +#define CFG80211_BANDINFO_FILL(__pAd, __pBandInfo) \ +{ \ + (__pBandInfo)->RFICType = __pAd->phy_ctrl.rf_band_cap; \ + (__pBandInfo)->MpduDensity = __pAd->CommonCfg.BACapability.field.MpduDensity;\ + (__pBandInfo)->TxStream = __pAd->CommonCfg.TxStream; \ + (__pBandInfo)->RxStream = __pAd->CommonCfg.RxStream; \ + (__pBandInfo)->MaxTxPwr = 0; \ + if (WMODE_EQUAL(__pAd->CommonCfg.PhyMode, WMODE_B)) \ + (__pBandInfo)->FlgIsBMode = TRUE; \ + else \ + (__pBandInfo)->FlgIsBMode = FALSE; \ + (__pBandInfo)->MaxBssTable = MAX_LEN_OF_BSS_TABLE; \ + (__pBandInfo)->RtsThreshold = pAd->CommonCfg.RtsThreshold; \ + (__pBandInfo)->FragmentThreshold = pAd->CommonCfg.FragmentThreshold; \ + (__pBandInfo)->RetryMaxCnt = 0; \ + RTMP_IO_READ32(__pAd, TX_RTY_CFG, &((__pBandInfo)->RetryMaxCnt)); \ +} +#endif /* SINGLE_SKU */ + +/* Scan Releated */ +#ifdef CONFIG_STA_SUPPORT +BOOLEAN CFG80211DRV_OpsScanRunning(VOID *pAdOrg); +#endif /*CONFIG_STA_SUPPORT*/ +BOOLEAN CFG80211DRV_OpsScanSetSpecifyChannel( + VOID *pAdOrg, VOID *pData, UINT8 dataLen); + +BOOLEAN CFG80211DRV_OpsScanCheckStatus( + VOID *pAdOrg, UINT8 IfType); + +BOOLEAN CFG80211DRV_OpsScanExtraIesSet(VOID *pAdOrg); + +VOID CFG80211DRV_OpsScanInLinkDownAction(VOID *pAdOrg); + +INT CFG80211DRV_OpsScanGetNextChannel(VOID *pAdOrg); + +VOID CFG80211_ScanStatusLockInit(VOID *pAdCB, UINT init); + +VOID CFG80211_Scaning( + VOID *pAdCB, UINT32 BssIdx, UINT32 ChanId, UCHAR *pFrame, UINT32 FrameLen, INT32 RSSI); + +VOID CFG80211_ScanEnd(VOID *pAdCB, BOOLEAN FlgIsAborted); + +/* Connect Releated */ +BOOLEAN CFG80211DRV_OpsJoinIbss(VOID *pAdOrg, VOID *pData); +BOOLEAN CFG80211DRV_OpsLeave(VOID *pAdOrg, UINT8 IfType); +BOOLEAN CFG80211DRV_Connect(VOID *pAdOrg, VOID *pData); + +VOID CFG80211_P2pClientConnectResultInform( + IN VOID *pAdCB, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess); + +VOID CFG80211_ConnectResultInform( + VOID *pAdCB, UCHAR *pBSSID, UCHAR *pReqIe, UINT32 ReqIeLen, + UCHAR *pRspIe, UINT32 RspIeLen, UCHAR FlgIsSuccess); +VOID CFG80211DRV_PmkidConfig(VOID *pAdOrg, VOID *pData); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +VOID CFG80211_LostP2pGoInform(VOID *pAdCB); +#endif /*RT_CFG80211_P2P_CONCURRENT_DEVICE*/ +VOID CFG80211_LostApInform(VOID *pAdCB); + +INT CFG80211_StaPortSecured( + VOID *pAdCB, + UCHAR *pMac, + UINT flag); + +/* AP Related*/ +INT CFG80211_ApStaDel(VOID *pAdCB, UCHAR *pMac); + +VOID CFG80211_UpdateBeacon( + VOID *pAdOrg, + UCHAR *beacon_head_buf, + UINT32 beacon_head_len, + UCHAR *beacon_tail_buf, + UINT32 beacon_tail_len, + BOOLEAN isAllUpdate); + +INT CFG80211_ApStaDelSendEvent(PRTMP_ADAPTER pAd, const PUCHAR mac_addr); + + +/* Information Releated */ +BOOLEAN CFG80211DRV_StaGet( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211DRV_SurveyGet( + VOID *pAdOrg, + VOID *pData); + +INT CFG80211_reSetToDefault( + VOID *pAdCB); + + + +/* Key Releated */ +BOOLEAN CFG80211DRV_StaKeyAdd( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_ApKeyAdd( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_ApKeyDel( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211DRV_RtsThresholdAdd( + VOID *pAdOrg, + UINT threshold); + +VOID CFG80211DRV_FragThresholdAdd( + VOID *pAdOrg, + UINT threshold); + + +INT CFG80211_setApDefaultKey( + VOID *pAdCB, + UINT Data); + +INT CFG80211_setPowerMgmt( + VOID *pAdCB, + UINT Enable); + +#ifdef CONFIG_STA_SUPPORT +INT CFG80211_setStaDefaultKey( + VOID *pAdCB, + UINT Data); + +#ifdef DOT11W_PMF_SUPPORT +INT CFG80211_setStaMgmtDefaultKey( + VOID *pAdCB, + UINT Data); +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /*CONFIG_STA_SUPPORT*/ +/* General Releated */ +BOOLEAN CFG80211DRV_OpsSetChannel(RTMP_ADAPTER *pAd, VOID *pData); + +BOOLEAN CFG80211DRV_OpsChgVirtualInf(RTMP_ADAPTER *pAd, VOID *pData); + +VOID CFG80211DRV_OpsChangeBssParm(VOID *pAdOrg, VOID *pData); + +VOID CFG80211_UnRegister(VOID *pAdOrg, VOID *pNetDev); + +INT CFG80211DRV_IoctlHandle( + VOID *pAdSrc, + RTMP_IOCTL_INPUT_STRUCT *wrq, + INT cmd, + USHORT subcmd, + VOID *pData, + ULONG Data); + +UCHAR CFG80211_getCenCh(RTMP_ADAPTER *pAd, UCHAR prim_ch); + +/* CRDA Releatd */ +VOID CFG80211DRV_RegNotify( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211_RegHint( + VOID *pAdCB, + UCHAR *pCountryIe, + ULONG CountryIeLen); + +VOID CFG80211_RegHint11D( + VOID *pAdCB, + UCHAR *pCountryIe, + ULONG CountryIeLen); + +VOID CFG80211_RegRuleApply( + VOID *pAdCB, + VOID *pWiphy, + UCHAR *pAlpha2); + +BOOLEAN CFG80211_SupBandReInit( + VOID *pAdCB); + +#ifdef RFKILL_HW_SUPPORT +VOID CFG80211_RFKillStatusUpdate( + PVOID pAd, + BOOLEAN active); +#endif /* RFKILL_HW_SUPPORT */ + +/* P2P Related */ +VOID CFG80211DRV_SetP2pCliAssocIe( + VOID *pAdOrg, + VOID *pData, + UINT ie_len); + +VOID CFG80211DRV_P2pClientKeyAdd( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_P2pClientConnect( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211_checkScanTable( + IN VOID *pAdCB); + +VOID CFG80211_P2pClientSendNullFrame( + VOID *pAdCB, + INT PwrMgmt); + +VOID CFG80211RemainOnChannelTimeout( + PVOID SystemSpecific1, + PVOID FunctionContext, + PVOID SystemSpecific2, + PVOID SystemSpecific3); + +BOOLEAN CFG80211DRV_OpsRemainOnChannel( + VOID *pAdOrg, + VOID *pData, + UINT32 duration); + +BOOLEAN CFG80211DRV_OpsCancelRemainOnChannel( + VOID *pAdOrg, + UINT32 cookie); + + +VOID CFG80211DRV_OpsMgmtFrameProbeRegister( + VOID *pAdOrg, + VOID *pData, + BOOLEAN isReg); + +VOID CFG80211DRV_OpsMgmtFrameActionRegister( + VOID *pAdOrg, + VOID *pData, + BOOLEAN isReg); + +BOOLEAN CFG80211_CheckActionFrameType( + IN RTMP_ADAPTER *pAd, + IN PUCHAR preStr, + IN PUCHAR pData, + IN UINT32 length); + + +BOOLEAN CFG80211_SyncPacketWmmIe(RTMP_ADAPTER *pAd, VOID *pData, ULONG dataLen); +BOOLEAN CFG80211_HandleP2pMgmtFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR OpMode); +INT CFG80211_SendMgmtFrame(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data); + +#ifdef RT_CFG80211_P2P_SUPPORT +VOID CFG80211_PeerP2pBeacon( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN MLME_QUEUE_ELEM *Elem, + IN LARGE_INTEGER TimeStamp); + + +VOID CFG80211_P2pStopNoA( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacClient); + + +BOOLEAN CFG80211_P2pResetNoATimer( + IN PRTMP_ADAPTER pAd, + IN ULONG DiffTimeInus); + + +BOOLEAN CFG80211_P2pHandleNoAAttri( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacClient, + IN PUCHAR pData); + +#endif /* RT_CFG80211_P2P_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +VOID CFG80211_ParseBeaconIE(RTMP_ADAPTER *pAd, MULTISSID_STRUCT *pMbss, struct wifi_dev *wdev,UCHAR *wpa_ie,UCHAR *rsn_ie); +#endif + +//-------------------------------- +VOID CFG80211_Convert802_3Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR *pHeader802_3); +VOID CFG80211_Announce802_3Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR FromWhichBSSID); +VOID CFG80211_SendMgmtFrameDone(RTMP_ADAPTER *pAd, USHORT Sequence); + +VOID CFG80211_SwitchTxChannel(RTMP_ADAPTER *pAd, ULONG Data); + +BOOLEAN CFG80211DRV_OpsBeaconSet( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_OpsBeaconAdd( + VOID *pAdOrg, + VOID *pData); + + +VOID CFG80211DRV_DisableApInterface(PRTMP_ADAPTER pAd); + + +BOOLEAN CFG80211DRV_OpsVifAdd( + VOID *pAdOrg, + VOID *pData); + +#endif /* RT_CFG80211_SUPPORT */ + +#endif /* __CFG80211EXTR_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/chip_id.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/chip_id.h new file mode 100644 index 000000000..4d38d3f7c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/chip_id.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * 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: + chip_id.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __CHIP_ID_H__ +#define __CHIP_ID_H__ + + +#define NIC_PCI_VENDOR_ID 0x1814 +#define MTK_PCI_VENDOR_ID 0x14C3 + +#define NIC2860_PCI_DEVICE_ID 0x0601 +#define NIC2860_PCIe_DEVICE_ID 0x0681 +#define NIC2760_PCI_DEVICE_ID 0x0701 /* 1T/2R Cardbus ??? */ +#define NIC2790_PCIe_DEVICE_ID 0x0781 /* 1T/2R miniCard */ + +#define VEN_AWT_PCIe_DEVICE_ID 0x1059 +#define DLINK_PCI_VENDOR_ID 0x1186 +#define VEN_AWT_PCI_VENDOR_ID 0x1A3B + +#define EDIMAX_PCI_VENDOR_ID 0x1432 + +#define NIC3090_PCIe_DEVICE_ID 0x3090 /* 1T/1R miniCard */ +#define NIC3091_PCIe_DEVICE_ID 0x3091 /* 1T/2R miniCard */ +#define NIC3092_PCIe_DEVICE_ID 0x3092 /* 2T/2R miniCard */ +#define NIC3390_PCIe_DEVICE_ID 0x3390 /* 1T/1R miniCard */ + +#define NIC3062_PCI_DEVICE_ID 0x3062 /* 2T/2R miniCard */ +#define NIC3562_PCI_DEVICE_ID 0x3562 /* 2T/2R miniCard */ +#define NIC3060_PCI_DEVICE_ID 0x3060 /* 1T/1R miniCard */ + +#define NIC3592_PCIe_DEVICE_ID 0x3592 /* 2T/2R miniCard */ + +#define NIC3593_PCI_OR_PCIe_DEVICE_ID 0x3593 + +#define NIC5390_PCIe_DEVICE_ID 0x5390 +#define NIC539F_PCIe_DEVICE_ID 0x539F +#define NIC5392_PCIe_DEVICE_ID 0x5392 +#define NIC5360_PCI_DEVICE_ID 0x5360 +#define NIC5362_PCI_DEVICE_ID 0x5362 + +#define NIC5592_PCIe_DEVICE_ID 0x5592 + +#define NIC3290_PCIe_DEVICE_ID 0x3290 + +#define NIC6590_PCIe_DEVICE_ID 0x6590 +#define NIC7610_PCIe_DEVICE_ID 0x7610 +#define NIC7630_PCIe_DEVICE_ID 0x7630 +#define NIC7650_PCIe_DEVICE_ID 0x7650 +#define NIC7602_PCIe_DEVICE_ID 0x7602 +#define NIC7612_PCIe_DEVICE_ID 0x7612 +#define NIC7632_PCIe_DEVICE_ID 0x7632 +#define NIC7662_PCIe_DEVICE_ID 0x7662 + +#ifdef CONFIG_FPGA_MODE +#define NIC6390_PCIe_DEVICE_ID 0x6390 +#endif /* CONFIG_FPGA_MODE */ + +#define NIC7601_PCIe_DEVICE_ID 0x7601 + +#define NIC8592_PCIe_DEVICE_ID 0x8592 +#endif /* __CHIP_ID_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/mt76x2.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/mt76x2.h new file mode 100644 index 000000000..04134e62b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/mt76x2.h @@ -0,0 +1,170 @@ +#ifndef __MT76X2_H__ +#define __MT76X2_H__ + +#include "../mcu/mcu_and.h" +#include "../phy/mt_rf.h" + +struct _RTMP_ADAPTER; + +#define MAX_RF_ID 127 +#define MAC_RF_BANK 7 + +void mt76x2_init(struct _RTMP_ADAPTER *ad); +void mt76x2_adjust_per_rate_pwr_delta(struct _RTMP_ADAPTER *ad, u8 channel, char delta_pwr); +void mt76x2_get_tx_pwr_per_rate(struct _RTMP_ADAPTER *ad); +void mt76x2_antenna_sel_ctl(struct _RTMP_ADAPTER *ad); +int mt76x2_read_chl_pwr(struct _RTMP_ADAPTER *ad); +void mt76x2_pwrOn(struct _RTMP_ADAPTER *ad); +void mt76x2_calibration(struct _RTMP_ADAPTER *ad, u8 channel); +void mt76x2_external_pa_rf_dac_control(struct _RTMP_ADAPTER *ad, u8 channel); +void mt76x2_tssi_calibration(struct _RTMP_ADAPTER *ad, u8 channel); +void mt76x2_tssi_compensation(struct _RTMP_ADAPTER *ad, u8 channel); + +int mt76x2_reinit_agc_gain(struct _RTMP_ADAPTER *ad, u8 channel); +int mt76x2_reinit_hi_lna_gain(struct _RTMP_ADAPTER *ad, u8 channel); +void mt76x2_get_external_lna_gain(struct _RTMP_ADAPTER *ad); +void mt76x2_get_agc_gain(struct _RTMP_ADAPTER *ad, BOOLEAN init_phase); +int get_chl_grp(u8 channel); +VOID mt76x2_ePA_per_rate_compensate_init(struct _RTMP_ADAPTER *pAd , BOOLEAN is_ePA); + + +int get_low_mid_hi_index(u8 channel); +void mt76x2_tx_pwr_gain(struct _RTMP_ADAPTER *ad, u8 channel, u8 bw); + +void percentage_delta_pwr(struct _RTMP_ADAPTER *ad); + +void mt76x2_update_tx_power_percentage(struct _RTMP_ADAPTER *ad); + +void mt76x2_get_current_temp(struct _RTMP_ADAPTER *ad); +void mt76x2_read_temp_info_from_eeprom(struct _RTMP_ADAPTER *ad); +#ifdef RTMP_TEMPERATURE_TX_ALC +void mt76x2_read_tx_alc_info_from_eeprom(struct _RTMP_ADAPTER *ad); +void mt76x2_temp_tx_alc(struct _RTMP_ADAPTER *ad); +#endif /* RTMP_TEMPERATURE_TX_ALC */ + +#ifdef SINGLE_SKU_V2 +void mt76x2_single_sku(struct _RTMP_ADAPTER *ad, u8 channel); +void mt76x2_read_single_sku_info_from_eeprom(struct _RTMP_ADAPTER *ad); +void mt76x2_make_up_rate_pwr_table(struct _RTMP_ADAPTER *ad); +UCHAR mt76x2_get_sku_channel_base_pwr(struct _RTMP_ADAPTER *ad, u8 channel); +void mt76x2_update_per_rate_pwr(struct _RTMP_ADAPTER *ad); +UCHAR mt76x2_update_sku_pwr(struct _RTMP_ADAPTER *ad, u8 channel); +INT32 mt76x2_sku_calculate_TxPwrAdj(struct _RTMP_ADAPTER *ad,struct _TXWI_NMAC *txwi_n); + +#endif /* SINGLE_SKU_V2 */ +VOID mt76x2_ePA_per_rate_compensate_init(struct _RTMP_ADAPTER *pAd , BOOLEAN is_ePA); + +#ifdef ED_MONITOR +void mt7612_set_ed_cca(struct _RTMP_ADAPTER *ad, BOOLEAN enable); +#endif /* ED_MONITOR */ + +#ifdef RALINK_ATE +VOID mt76x2_ate_do_calibration( + struct _RTMP_ADAPTER *ad, UINT32 cal_id, UINT32 param); +VOID mt76x2_ate_SendNullFrame(struct _RTMP_ADAPTER *ad); +#endif /* RALINK_ATE */ + +struct mt76x2_frequency_item { + u8 channel; + u32 fcal_target; + u32 sdm_integer; + u32 sdm_fraction; +}; + +typedef struct _MT76x2_RATE_PWR_ITEM { + CHAR mcs_pwr; + INT32 sku_pwr; +} MT76x2_RATE_PWR_ITEM, *PMT76x2_RATE_PWR_ITEM; + +typedef struct _MT76x2_RATE_PWR_TABLE { + MT76x2_RATE_PWR_ITEM CCK[4]; + MT76x2_RATE_PWR_ITEM OFDM[8]; + MT76x2_RATE_PWR_ITEM HT[16]; + MT76x2_RATE_PWR_ITEM HT20[16]; // only for storing HT20 sku_pwr in BBPcurrentBW==80/40 case + MT76x2_RATE_PWR_ITEM HT40[16]; // only for storing HT40 sku_pwr in BBPcurrentBW==80/40 case + MT76x2_RATE_PWR_ITEM VHT1SS[10]; + MT76x2_RATE_PWR_ITEM VHT2SS[10]; + MT76x2_RATE_PWR_ITEM STBC[10]; + MT76x2_RATE_PWR_ITEM MCS32; +} MT76x2_RATE_PWR_Table, *PMT76x2_RATE_PWR_Table; + +#ifdef CONFIG_CALIBRATION_COLLECTION +#define MAX_MT76x2_CALIBRATION_ID (RXIQC_FD_CALIBRATION_7662+1) +#define MAX_RECORD_REG 50 +enum reg_rf0_addr { + RF0_214 = 0, + RF0_218 = 1, + RF0_21C = 2, + RF0_220 = 3, + RF0_224 = 4, + RF0_228 = 5, + RF0_24C = 6, + RF0_250 = 7, + RF0_264 = 8, + RF0_278 = 9, +}; +enum reg_rf1_addr { + RF1_214 = 20, + RF1_218 = 21, + RF1_21C = 22, + RF1_220 = 23, + RF1_224 = 24, + RF1_228 = 25, + RF1_24C = 26, + RF1_250 = 27, + RF1_264 = 28, + RF1_278 = 29, +}; + +enum reg_bbp_addr { + BBP_2774 = 0, + BBP_2780 = 1, + BBP_2784 = 2, + BBP_2788 = 3, + BBP_278C = 4, + BBP_2790 = 5, + BBP_2794 = 6, + BBP_2798 = 7, + BBP_279C = 8, + BBP_27A0 = 9, + BBP_27A4 = 10, + BBP_27A8 = 11, + BBP_27AC = 12, + BBP_27B0 = 13, + BBP_27B4 = 14, + BBP_27B8 = 15, + BBP_27BC = 16, + BBP_27C0 = 17, + BBP_27C4 = 18, + BBP_27C8 = 19, + BBP_27CC = 20, + BBP_208C = 21, + BBP_2720 = 22, + BBP_2C60 = 23, + BBP_2C64 = 24, + BBP_2C70 = 25, + BBP_2C74 = 26, + BBP_2818 = 27, + BBP_281C = 28, + BBP_2820 = 29, + BBP_2824 = 30, + BBP_2828 = 31, + BBP_282C = 32, +}; + +struct mt76x2_calibration_info { + UINT16 addr[MAX_RECORD_REG]; + u32 value[MAX_RECORD_REG]; +}; + +void record_calibration_info(struct _RTMP_ADAPTER *ad, u32 cal_id); +void dump_calibration_info(struct _RTMP_ADAPTER *ad, u32 cal_id); +#endif + + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT +VOID WlanResetB(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rt6352.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rt6352.h new file mode 100644 index 000000000..10df41576 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rt6352.h @@ -0,0 +1,245 @@ +/**************************************************************************** + * 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: + rt6352.h + + Abstract: + 2*2 Wireless Chip SoC + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 20120301 Initial version + */ + +#ifndef __RT6352_H__ +#define __RT6352_H__ + +#ifdef RT6352 + +#ifndef RTMP_RBUS_SUPPORT +#error "For RT3883, you should define the compile flag -DRTMP_RBUS_SUPPORT" +#endif + +#ifndef RTMP_MAC_PCI +#error "For RT3883, you should define the compile flag -DRTMP_MAC_PCI" +#endif + +struct _RTMP_ADAPTER; + +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ +#define RTMP_MAC_CSR_ADDR 0xB0180000 +#define RTMP_FLASH_BASE_ADDR 0xbc000000 + + +extern REG_PAIR RT6352_RFCentralRegTable[]; +extern UCHAR RT6352_NUM_RF_CENTRAL_REG_PARMS; +extern REG_PAIR RT6352_RFChannelRegTable[]; +extern UCHAR RT6352_NUM_RF_CHANNEL_REG_PARMS; +extern REG_PAIR RT6352_RFChannelRegE2Table[]; +extern UCHAR RT6352_NUM_RF_CHANNEL_E2_REG_PARMS; +extern REG_PAIR RT6352_RFDCCalRegTable[]; +extern UCHAR RT6352_NUM_RF_DCCAL_REG_PARMS; + +extern REG_PAIR RT6352_BBPRegTable[]; +extern UCHAR RT6352_NUM_BBP_REG_PARMS; +extern RTMP_REG_PAIR RT6352_MACRegTable[]; +extern UCHAR RT6352_NUM_MAC_REG_PARMS; + +#if defined (CONFIG_RALINK_RT6352) || defined (CONFIG_RALINK_MT7620) +#define PROCREG_DIR "rt6352" +#endif /* defined (CONFIG_RALINK_RT6352) || defined (CONFIG_RALINK_MT7620) */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +#define RT6352_EEPROM_TSSI_24G_READ(__pAd) \ +{ \ + EEPROM_TX_PWR_STRUC __Power; \ + USHORT __Value; \ + CHAR __Offset; \ + __Offset = __pAd->TemperatureRef25C; \ + __pAd->TssiCalibratedOffset = __Offset; \ + RT28xx_EEPROM_READ16(__pAd, EEPROM_G_TSSI_BOUND1, __Power.word); \ + __pAd->TssiMinusBoundaryG[7] = __Power.field.Byte0; \ + __pAd->TssiMinusBoundaryG[6] = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 2), __Power.word);\ + __pAd->TssiMinusBoundaryG[5] = __Power.field.Byte0; \ + __pAd->TssiMinusBoundaryG[4] = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 4), __Power.word);\ + __pAd->TssiMinusBoundaryG[3] = __Power.field.Byte0; \ + __pAd->TssiMinusBoundaryG[2] = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 6), __Power.word);\ + __pAd->TssiMinusBoundaryG[1] = __Power.field.Byte0; \ + __pAd->TssiRefG = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 10), __Power.word);\ + __pAd->TssiPlusBoundaryG[1] = __Power.field.Byte0; \ + __pAd->TssiPlusBoundaryG[2] = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 12), __Power.word);\ + __pAd->TssiPlusBoundaryG[3] = __Power.field.Byte0; \ + __pAd->TssiPlusBoundaryG[4] = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 14), __Power.word);\ + __pAd->TssiPlusBoundaryG[5] = __Power.field.Byte0; \ + __pAd->TssiPlusBoundaryG[6] = __Power.field.Byte1; \ + RT28xx_EEPROM_READ16(__pAd, (EEPROM_G_TSSI_BOUND1 + 16), __Value);\ + __pAd->TssiPlusBoundaryG[7] = __Power.field.Byte0; \ + __pAd->TxAgcStepG = ((__Value & 0xFF00) >> 8); \ + __pAd->TxAgcCompensateG = 0; \ + __pAd->TssiMinusBoundaryG[0] = __pAd->TssiRefG; \ + __pAd->TssiPlusBoundaryG[0] = __pAd->TssiRefG; \ + if (__pAd->TssiRefG == 0xFF) \ + __pAd->bAutoTxAgcG = FALSE; \ +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +typedef struct _RT635x_FREQUENCY_ITEM { + UCHAR Channel; + UCHAR Rdiv; + UINT16 N; + UCHAR K; + UCHAR D; + UINT32 Ksd; +} RT635x_FREQUENCY_ITEM, *PRT635x_FREQUENCY_ITEM; + +VOID RT6352_Init( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT6352_RTMPReadTxPwrPerRate( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT6352_AsicAdjustTxPower( + IN struct _RTMP_ADAPTER *pAd); + +#ifdef RTMP_TEMPERATURE_CALIBRATION +VOID RT6352_Temperature_Init( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT6352_TemperatureCalibration( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID RT6352_TssiTableAdjust( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT6352_TssiMpAdjust( + IN struct _RTMP_ADAPTER *pAd); + +BOOLEAN RT6352_TemperatureCompensation( + IN struct _RTMP_ADAPTER *pAd, + IN BOOLEAN bResetTssiInfo); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#if defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) +VOID RT6352_Init_ExtPA_ExtLNA( + IN struct _RTMP_ADAPTER *pAd, + IN BOOLEAN ReInit); + +VOID RT6352_Restore_RF_BBP( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT6352_ReCalibration( + IN struct _RTMP_ADAPTER *pAd); +#endif /* defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) */ + +#ifdef SINGLE_SKU_V2 +VOID RT6352_InitSkuRateDiffTable( + IN struct _RTMP_ADAPTER *pAd); + +UCHAR RT6352_GetSkuChannelBasePwr( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR channel); + +CHAR RT6352_AdjustChannelPwr( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR TotalDeltaPower, + OUT CHAR *PreDiff); + +VOID RT6352_AdjustPerRatePwr( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR channelpower); + +UCHAR GetSkuPerRatePwr( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR phymode, + IN UCHAR channel, + IN UCHAR bw, + IN INT32 paValue); +#endif /* SINGLE_SKU_V2 */ + +#ifdef DYNAMIC_VGA_SUPPORT +VOID rt6352_dynamic_vga_enable( + IN struct _RTMP_ADAPTER *pAd); + +VOID rt6352_dynamic_vga_disable( + IN struct _RTMP_ADAPTER *pAd); +#endif /* DYNAMIC_VGA_SUPPORT */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +#define GROUP1_2G 0 +#define GROUP2_2G 1 +#define GROUP3_2G 2 +#define GROUPS_5G 3 + +#define GET_2G_CHANNEL_GROUP(_channel) ((_channel <= 4) ? \ + (GROUP1_2G) : ((_channel <= 8) ? \ + (GROUP2_2G) : ((_channel <= 14) ? \ + (GROUP3_2G) : (GROUPS_5G)))) +#define max_ant 2 +#define DEFAULT_BO 4 +#define LIN2DB_ERROR_CODE (-10000) +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + +#ifdef RTMP_INTERNAL_TX_ALC +INT16 RT6352_lin2dBd( + IN unsigned short linearValue); + +CHAR SignedExtension6To8( + IN CHAR org_value); + +VOID RT635xGetTssiInfo( + IN struct _RTMP_ADAPTER *pAd); + +INT RT635xTssiDcCalibration( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT635xInitMcsPowerTable( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT635xInitRfPaModeTable( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT635xTssiCompensation( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR percent_delta); + +BOOLEAN RT635xTriggerTssiCompensation( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR percent_delta); + +BOOLEAN RT635xCheckTssiCompensation( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef ED_MONITOR +VOID RT6352_set_ed_cca( + IN struct _RTMP_ADAPTER *pAd, BOOLEAN enable); +#endif /* ED_MONITOR */ + +#endif /* RT6352 */ +#endif /*__RT6352_H__ */ +/* End of rt6352.h */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rt65xx.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rt65xx.h new file mode 100644 index 000000000..1f677cccc --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rt65xx.h @@ -0,0 +1,85 @@ +/* + *************************************************************************** + * MediaTek Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 1997-2012, MediaTek, Inc. + * + * All rights reserved. MediaTek 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 MediaTek. 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 MediaTek Technology, Inc. is obtained. + *************************************************************************** + +*/ + +#ifndef __MT65XX_H__ +#define __MT65XX_H__ + + +#ifdef MT76x2 +#include "mt76x2.h" +#endif /* MT76x2 */ + +struct _RTMP_ADAPTER; + +/* b'00: 2.4G+5G external PA, b'01: 5G external PA, b'10: 2.4G external PA, b'11: Internal PA */ +#define EXT_PA_2G_5G 0x0 +#define EXT_PA_5G_ONLY 0x1 +#define EXT_PA_2G_ONLY 0x2 + +#define INT_PA_2G_5G 0x3 +#define INT_PA_5G 0x2 +#define INT_PA_2G 0x1 + +#define MAX_CHECK_COUNT 200 + + +/* + EEPROM format +*/ + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG0_STRUC { + struct { +#ifdef MT76x2 + USHORT Rsv:5; + USHORT PACurrent:1; +#else + USHORT Rsv:6; +#endif + USHORT PAType:2; /* 00: 2.4G+5G external PA, 01: 5G external PA, 10: 2.4G external PA, 11: Internal PA */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + } field; + USHORT word; +} EEPROM_NIC_CONFIG0_STRUC, *PEEPROM_NIC_CONFIG0_STRUC; +#else +typedef union _EEPROM_NIC_CINFIG0_STRUC { + struct { + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT PAType:2; /* 00: 2.4G+5G external PA, 01: 5G external PA, 10: 2.4G external PA, 11: Internal PA */ +#ifdef MT76x2 + USHORT PACurrent:1; + USHORT Rsv:5; +#else + USHORT Rsv:6; +#endif + } field; + USHORT word; +} EEPROM_NIC_CONFIG0_STRUC, *PEEPROM_NIC_CONFIG0_STRUC; +#endif + +VOID RT65xxDisableTxRx(struct _RTMP_ADAPTER *pAd, UCHAR Level); +void MT76xx_PciMlmeRadioOFF(struct _RTMP_ADAPTER *pAd); +void MT76xx_PciMlmeRadioOn(struct _RTMP_ADAPTER *pAd); +VOID dump_bw_info(struct _RTMP_ADAPTER *pAd); +VOID dump_pwr_info(struct _RTMP_ADAPTER *pAd); + +#endif /* __MT65XX_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rtmp_phy.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rtmp_phy.h new file mode 100644 index 000000000..cbd122629 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chip/rtmp_phy.h @@ -0,0 +1,371 @@ +/* + *************************************************************************** + * 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_phy.h + + Abstract: + Ralink Wireless Chip PHY(BBP/RF) related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_PHY_H__ +#define __RTMP_PHY_H__ + + +#include "mac_ral/rf_ctrl.h" +#ifdef RLT_BBP +#include "phy/rlt_bbp.h" +#endif /* RLT_BBP */ + +#ifdef RTMP_BBP +#include "phy/rtmp_bbp.h" +#endif /* RTMP_BBP */ + + +/* + RF sections +*/ +#define RF_R00 0 +#define RF_R01 1 +#define RF_R02 2 +#define RF_R03 3 +#define RF_R04 4 +#define RF_R05 5 +#define RF_R06 6 +#define RF_R07 7 +#define RF_R08 8 +#define RF_R09 9 +#define RF_R10 10 +#define RF_R11 11 +#define RF_R12 12 +#define RF_R13 13 +#define RF_R14 14 +#define RF_R15 15 +#define RF_R16 16 +#define RF_R17 17 +#define RF_R18 18 +#define RF_R19 19 +#define RF_R20 20 +#define RF_R21 21 +#define RF_R22 22 +#define RF_R23 23 +#define RF_R24 24 +#define RF_R25 25 +#define RF_R26 26 +#define RF_R27 27 +#define RF_R28 28 +#define RF_R29 29 +#define RF_R30 30 +#define RF_R31 31 +#define RF_R32 32 +#define RF_R33 33 +#define RF_R34 34 +#define RF_R35 35 +#define RF_R36 36 +#define RF_R37 37 +#define RF_R38 38 +#define RF_R39 39 +#define RF_R40 40 +#define RF_R41 41 +#define RF_R42 42 +#define RF_R43 43 +#define RF_R44 44 +#define RF_R45 45 +#define RF_R46 46 +#define RF_R47 47 +#define RF_R48 48 +#define RF_R49 49 +#define RF_R50 50 +#define RF_R51 51 +#define RF_R52 52 +#define RF_R53 53 +#define RF_R54 54 +#define RF_R55 55 +#define RF_R56 56 +#define RF_R57 57 +#define RF_R58 58 +#define RF_R59 59 +#define RF_R60 60 +#define RF_R61 61 +#define RF_R62 62 +#define RF_R63 63 + +#define RF_R64 64 +#define RF_R65 65 +#define RF_R66 66 +#define RF_R67 67 +#define RF_R68 68 +#define RF_R69 69 +#define RF_R70 70 +#define RF_R71 71 +#define RF_R72 72 +#define RF_R73 73 +#define RF_R74 74 +#define RF_R75 75 +#define RF_R76 76 +#define RF_R77 77 +#define RF_R78 78 +#define RF_R79 79 +#define RF_R126 126 +#define RF_R127 127 + +/* value domain of pAd->RfIcType */ +#define RFIC_2820 1 /* 2.4G 2T3R */ +#define RFIC_2850 2 /* 2.4G/5G 2T3R */ +#define RFIC_2720 3 /* 2.4G 1T2R */ +#define RFIC_2750 4 /* 2.4G/5G 1T2R */ +#define RFIC_3020 5 /* 2.4G 1T1R */ +#define RFIC_2020 6 /* 2.4G B/G */ +#define RFIC_3021 7 /* 2.4G 1T2R */ +#define RFIC_3022 8 /* 2.4G 2T2R */ +#define RFIC_3052 9 /* 2.4G/5G 2T2R */ +#define RFIC_2853 10 /* 2.4G.5G 3T3R */ +#define RFIC_3320 11 /* 2.4G 1T1R with PA (RT3350/RT3370/RT3390) */ +#define RFIC_3322 12 /* 2.4G 2T2R with PA (RT3352/RT3371/RT3372/RT3391/RT3392) */ +#define RFIC_3053 13 /* 2.4G/5G 3T3R (RT3883/RT3563/RT3573/RT3593/RT3662) */ +#define RFIC_3853 13 /* 2.4G/5G 3T3R (RT3883/RT3563/RT3573/RT3593/RT3662) */ +#define RFIC_5592 14 /* 2.4G/5G */ +#define RFIC_6352 15 /* 2.4G 2T2R */ +#define RFIC_7650 15 /* 2.4G/5G 1x1 VHT with BT*/ +#define RFIC_7610E 16 /* 5G 1x1 VHT */ +#define RFIC_7610U 17 +#define RFIC_7630 18 /* 2.4G 1x1 HT with BT */ +#define RFIC_7662 19 /* 2.4G/5G 2T2R VHT with BT */ +#define RFIC_7612 20 /* 2.4G/5G 2T2R VHT */ +#define RFIC_7602 21 /* 2.4G 2T2R VHT */ +#define RFIC_UNKNOWN 0xff + +#define RFIC_IS_5G_BAND(__pAd) \ + ((__pAd->RfIcType == RFIC_2850) || \ + (__pAd->RfIcType == RFIC_2750) || \ + (__pAd->RfIcType == RFIC_3052) || \ + (__pAd->RfIcType == RFIC_2853) || \ + (__pAd->RfIcType == RFIC_3053) || \ + (__pAd->RfIcType == RFIC_3853) || \ + (__pAd->RfIcType == RFIC_5592) || \ + (__pAd->RfIcType == RFIC_7650) || \ + (__pAd->RfIcType == RFIC_7610E) || \ + (__pAd->RfIcType == RFIC_7610U) || \ + (__pAd->RfIcType == RFIC_7662) || \ + (__pAd->RfIcType == RFIC_7612) || \ + (__pAd->RfIcType == RFIC_UNKNOWN)) + + +#ifdef RTMP_MAC_PCI +// TODO: shiang, what's the difference of BoardType v.s. band and interface?? +#define BOARD_2G_ONLY 1 +#define BOARD_5G_ONLY 2 + +#define BOARD_IS_2G_ONLY(__pAd) \ + (__pAd->Antenna.field.BoardType == BOARD_2G_ONLY) + +#define BOARD_IS_5G_ONLY(__pAd) \ + (__pAd->Antenna.field.BoardType == BOARD_5G_ONLY) +#else +#define BOARD_IS_2G_ONLY(__pAd) 0 +#define BOARD_IS_5G_ONLY(__pAd) 0 +#endif /* !RTMP_MAC_PCI */ + +typedef enum{ + RX_CHAIN_0 = 1<<0, + RX_CHAIN_1 = 1<<1, + RX_CHAIN_2 = 1<<2, + RX_CHAIN_ALL = 0xf +}RX_CHAIN_IDX; + + +/* */ +/* BBP R49 TSSI (Transmit Signal Strength Indicator) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R49_STRUC { + struct + { + UCHAR adc5_in_sel:1; /* 0: TSSI (from the external components, old version), 1: PSI (internal components, new version - RT3390) */ + UCHAR bypassTSSIAverage:1; /* 0: the average TSSI (the average of the 16 samples), 1: the current TSSI */ + UCHAR Reserved:1; /* Reserved field */ + UCHAR TSSI:5; /* TSSI value */ + } field; + + UCHAR byte; +} BBP_R49_STRUC, *PBBP_R49_STRUC; +#else +typedef union _BBP_R49_STRUC { + struct + { + UCHAR TSSI:5; /* TSSI value */ + UCHAR Reserved:1; /* Reserved field */ + UCHAR bypassTSSIAverage:1; /* 0: the average TSSI (the average of the 16 samples), 1: the current TSSI */ + UCHAR adc5_in_sel:1; /* 0: TSSI (from the external components, old version), 1: PSI (internal components, new version - RT3390) */ + } field; + + UCHAR byte; +} BBP_R49_STRUC, *PBBP_R49_STRUC; +#endif + +#define MAX_BBP_MSG_SIZE 4096 + + +/* */ +/* BBP & RF are using indirect access. Before write any value into it. */ +/* We have to make sure there is no outstanding command pending via checking busy bit. */ +/* */ +#define MAX_BUSY_COUNT 100 /* Number of retry before failing access BBP & RF indirect register */ +#define MAX_BUSY_COUNT_US 2000 /* Number of retry before failing access BBP & RF indirect register */ + +/*#define PHY_TR_SWITCH_TIME 5 // usec */ + +#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 +#define RSSI_FOR_LOW_SENSIBILITY -58 +#define RSSI_FOR_MID_LOW_SENSIBILITY -65 /*-80*/ +#define RSSI_FOR_MID_SENSIBILITY -90 + +/***************************************************************************** + RF register Read/Write marco definition + *****************************************************************************/ +#ifdef RTMP_MAC_PCI +#define RTMP_RF_IO_WRITE32(_A, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + RF_CSR_CFG0_STRUC _value; \ + ULONG _busyCnt = 0; \ + \ + do { \ + RTMP_IO_READ32((_A), RF_CSR_CFG0, &_value.word); \ + if (_value.field.Busy == IDLE) \ + break; \ + _busyCnt++; \ + }while (_busyCnt < MAX_BUSY_COUNT); \ + if(_busyCnt < MAX_BUSY_COUNT) \ + { \ + RTMP_IO_WRITE32((_A), RF_CSR_CFG0, (_V)); \ + } \ + } \ + if ((_A)->ShowRf) \ + { \ + printk("RF:%x\n", _V); \ + } \ +} +#endif /* RTMP_MAC_PCI */ + + + +/***************************************************************************** + BBP register Read/Write marco definitions. + we read/write the bbp value by register's ID. + Generate PER to test BA + *****************************************************************************/ +#ifdef RTMP_MAC_PCI +/* + Hardware Periodic Timer interrupt setting. + Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. +*/ +#define RTMP_HW_TIMER_INT_SET(_pAd, _V) \ + { \ + UINT32 temp; \ + RTMP_IO_READ32(_pAd, INT_TIMER_CFG, &temp); \ + temp &= 0x0000ffff; \ + temp |= _V << 20; \ + RTMP_IO_WRITE32(_pAd, INT_TIMER_CFG, temp); \ + } + +/* Enable Hardware Periodic Timer interrupt */ +#define RTMP_HW_TIMER_INT_ENABLE(_pAd) \ + { \ + UINT32 temp; \ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &temp); \ + temp |=0x2; \ + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, temp); \ + } + +/* Disable Hardware Periodic Timer interrupt */ +#define RTMP_HW_TIMER_INT_DISABLE(_pAd) \ + { \ + UINT32 temp; \ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &temp); \ + temp &=~(0x2); \ + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, temp); \ + } +#endif /* RTMP_MAC_PCI */ + + +struct _RMTP_ADAPTER; + + +#define _G_BAND 0x0 +#define _A_BAND 0x1 +#define _BAND 0x3 + +#define _BW_20 (0x0 << 2) +#define _BW_40 (0x1 << 2) +#define _BW_80 (0x2 << 2) +#define _BW_160 (0x3 << 2) +#define _BW (0x3 << 2) + +#define RF_Path0 0 +#define RF_Path1 1 + +#define _1T1R (0x0 << 4) +#define _2T1R (0x1 << 4) +#define _1T2R (0x2 << 4) +#define _2T2R (0x3 << 4) +#define _TX_RX_SETTING (0x3 << 4) + +#define _LT (0x0 << 6) +#define _HT (0x1 << 6) +#define _TEM_SETTING (0x1 << 6) + +INT bbp_set_bw(struct _RTMP_ADAPTER *pAd, UINT8 bw); +INT bbp_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch); +INT bbp_set_rxpath(struct _RTMP_ADAPTER *pAd, INT rxpath); +INT bbp_get_temp(struct _RTMP_ADAPTER *pAd, CHAR *temp_val); +INT bbp_tx_comp_init(struct _RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode); +INT bbp_set_txdac(struct _RTMP_ADAPTER *pAd, INT tx_dac); +INT bbp_set_mmps(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); +INT bbp_is_ready(struct _RTMP_ADAPTER *pAd); +INT bbp_set_agc(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX idx); +INT bbp_get_agc(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX idx); +INT filter_coefficient_ctrl(struct _RTMP_ADAPTER *pAd, UCHAR Channel); +UCHAR get_random_seed_by_phy(struct _RTMP_ADAPTER *pAd); + +NDIS_STATUS NICInitBBP(struct _RTMP_ADAPTER *pAd); +VOID InitRFRegisters(struct _RTMP_ADAPTER *pAd); + +typedef struct phy_ops{ + INT (*bbp_is_ready)(struct _RTMP_ADAPTER *pAd); + UCHAR (*get_random_seed_by_phy)(struct _RTMP_ADAPTER *pAd); + INT (*filter_coefficient_ctrl)(struct _RTMP_ADAPTER *pAd, UCHAR Channel); + INT (*bbp_set_agc)(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX chain); + INT (*bbp_get_agc)(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX chain); + INT (*bbp_set_mmps)(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); + INT (*bbp_set_bw)(struct _RTMP_ADAPTER *pAd, UINT8 bw); + INT (*bbp_set_ctrlch)(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch); + INT (*bbp_set_rxpath)(struct _RTMP_ADAPTER *pAd, INT rxpath); + INT (*bbp_set_txdac)(struct _RTMP_ADAPTER *pAd, INT tx_dac); + INT (*bbp_tx_comp_init)(struct _RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode); + INT (*bbp_get_temp)(struct _RTMP_ADAPTER *pAd, CHAR *temp_val); + INT (*bbp_init)(struct _RTMP_ADAPTER *pAd); +}PHY_OPS; + + +#endif /* __RTMP_PHY_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chlist.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chlist.h new file mode 100644 index 000000000..a13e06e70 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/chlist.h @@ -0,0 +1,175 @@ +/* + *************************************************************************** + * 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: + chlist.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __CHLIST_H__ +#define __CHLIST_H__ + +#include "rtmp_type.h" +#include "rtmp_def.h" + + +typedef struct _CH_DESC { + UCHAR FirstChannel; + UCHAR NumOfCh; + UCHAR ChannelProp; +}CH_DESC, *PCH_DESC; + +typedef struct _COUNTRY_REGION_CH_DESC { + UCHAR RegionIndex; + PCH_DESC pChDesc; +}COUNTRY_REGION_CH_DESC, *PCOUNTRY_REGION_CH_DESC; + +#ifdef EXT_BUILD_CHANNEL_LIST +#define ODOR 0 +#define IDOR 1 +#define BOTH 2 + +typedef struct _CH_DESP { + UCHAR FirstChannel; + UCHAR NumOfCh; + CHAR MaxTxPwr; /* dBm */ + UCHAR Geography; /* 0:out door, 1:in door, 2:both */ + BOOLEAN DfsReq; /* Dfs require, 0: No, 1: yes. */ +} CH_DESP, *PCH_DESP; + +typedef struct _CH_REGION { + UCHAR CountReg[3]; + UCHAR DfsType; /* 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 */ + CH_DESP *pChDesp; + BOOLEAN edcca_on; +} CH_REGION, *PCH_REGION; + +extern CH_REGION ChRegion[]; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +typedef struct _COUNTRY_PROP { + UCHAR CountReg[3]; + UCHAR DfsType; /* 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 */ + BOOLEAN edcca_on; +} COUNTRY_PROP, *PCOUNTRY_PROP; + + +#ifdef SINGLE_SKU_V2 +// TODO: shiang-usw, integrate these data structures to a single one! +#define SINGLE_SKU_TABLE_LENGTH (SINGLE_SKU_TABLE_CCK_LENGTH+SINGLE_SKU_TABLE_OFDM_LENGTH+(SINGLE_SKU_TABLE_HT_LENGTH*2)) + +#define SINGLE_SKU_TABLE_CCK_LENGTH 4 +#define SINGLE_SKU_TABLE_OFDM_LENGTH 8 +#define SINGLE_SKU_TABLE_HT_LENGTH 16 +#define SINGLE_SKU_TABLE_VHT_LENGTH 10 /* VHT80 MCS 0 ~ 9 */ + +// TODO: shiang-usw, need to re-organize these for MT7610/MT7601/MT7620!! +typedef struct _CH_POWER_{ + DL_LIST List; + UCHAR StartChannel; + UCHAR num; + UCHAR *Channel; + UCHAR PwrCCK[SINGLE_SKU_TABLE_CCK_LENGTH]; + UCHAR PwrOFDM[SINGLE_SKU_TABLE_OFDM_LENGTH]; + UCHAR PwrHT20[SINGLE_SKU_TABLE_HT_LENGTH]; + UCHAR PwrHT40[SINGLE_SKU_TABLE_HT_LENGTH]; + UCHAR PwrVHT80[SINGLE_SKU_TABLE_VHT_LENGTH]; +}CH_POWER; +#endif /* SINGLE_SKU_V2 */ + +typedef struct _CH_FREQ_MAP_{ + UINT16 channel; + UINT16 freqKHz; +}CH_FREQ_MAP; + +extern CH_FREQ_MAP CH_HZ_ID_MAP[]; +extern int CH_HZ_ID_MAP_NUM; + + +#define MAP_CHANNEL_ID_TO_KHZ(_ch, _khz) \ + RTMP_MapChannelID2KHZ(_ch, (UINT32 *)&(_khz)) +#define MAP_KHZ_TO_CHANNEL_ID(_khz, _ch) \ + RTMP_MapKHZ2ChannelID(_khz, (INT *)&(_ch)) + +/* Check if it is Japan W53(ch52,56,60,64) channel. */ +#define JapanChannelCheck(_ch) ((_ch == 52) || (_ch == 56) || (_ch == 60) || (_ch == 64)) + +#ifdef ED_MONITOR +BOOLEAN GetEDCCASupport( + IN PRTMP_ADAPTER pAd); +#endif /* ED_MONITOR */ + +#ifdef EXT_BUILD_CHANNEL_LIST +VOID BuildChannelListEx( + IN PRTMP_ADAPTER pAd); + +VOID BuildBeaconChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +UCHAR GetCountryRegionFromCountryCode(PRTMP_ADAPTER pAd); + +#ifdef DOT11_N_SUPPORT +VOID N_ChannelCheck(RTMP_ADAPTER *pAd); +UCHAR N_SetCenCh(RTMP_ADAPTER *pAd, UCHAR channel); +BOOLEAN N_ChannelGroupCheck(RTMP_ADAPTER *pAd, UCHAR channel); +#ifdef SMART_MESH_MONITOR +UCHAR N_GetSecondaryChannel(RTMP_ADAPTER *pAd); +#endif /* SMART_MESH_MONITOR */ +#ifdef DOT11_VHT_AC +INT get_vht_neighbor_index(UCHAR channel); +BOOLEAN AC_ChannelGroupCheck(RTMP_ADAPTER *pAd, UCHAR channel); +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +UINT8 GetCuntryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel); + +VOID RTMP_MapChannelID2KHZ( + IN UCHAR Ch, + OUT UINT32 *pFreq); + +VOID RTMP_MapKHZ2ChannelID( + IN ULONG Freq, + OUT INT *pCh); + +UCHAR GetChannel_5GHZ( + IN PCH_DESC pChDesc, + IN UCHAR index); + +UCHAR GetChannel_2GHZ( + IN PCH_DESC pChDesc, + IN UCHAR index); + +UCHAR GetChannelFlag( + IN PCH_DESC pChDesc, + IN UCHAR index); + +UINT16 TotalChNum( + IN PCH_DESC pChDesc); + +#endif /* __CHLIST_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/client_wds.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/client_wds.h new file mode 100644 index 000000000..691583498 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/client_wds.h @@ -0,0 +1,59 @@ +/* + *************************************************************************** + * 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.h + + Abstract: +*/ + +#ifndef __CLIENT_WDS_H__ +#define __CLIENT_WDS_H__ + +#include "client_wds_cmm.h" + +VOID CliWds_ProxyTabInit( + IN PRTMP_ADAPTER pAd); + +VOID CliWds_ProxyTabDestory( + IN PRTMP_ADAPTER pAd); + +PCLIWDS_PROXY_ENTRY CliWdsEntyAlloc( + IN PRTMP_ADAPTER pAd); + + +VOID CliWdsEntyFree( + IN PRTMP_ADAPTER pAd, + IN PCLIWDS_PROXY_ENTRY pCliWdsEntry); + + +PUCHAR CliWds_ProxyLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac); + + +VOID CliWds_ProxyTabUpdate( + IN PRTMP_ADAPTER pAd, + IN SHORT Aid, + IN PUCHAR pMac); + + +VOID CliWds_ProxyTabMaintain( + IN PRTMP_ADAPTER pAd); + +#endif /* __CLIENT_WDS_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/client_wds_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/client_wds_cmm.h new file mode 100644 index 000000000..fad717167 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/client_wds_cmm.h @@ -0,0 +1,50 @@ +/* + *************************************************************************** + * 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_cmm.h + + Abstract: +*/ + +#ifndef __CLIENT_WDS_CMM_H__ +#define __CLIENT_WDS_CMM_H__ + +#include "rtmp_def.h" + +#ifdef CLIENT_WDS + +#ifdef ETH_CONVERT_SUPPORT +#error: "ETH_CONVERT function are conflict with CLIENT_WDS function.\ + And Can't support both of them at same time." +#endif /* ETH_CONVERT_SUPPORT */ + +#define CLI_WDS_ENTRY_AGEOUT 5000 /* seconds */ + +#define CLIWDS_POOL_SIZE 128 +#define CLIWDS_HASH_TAB_SIZE 64 /* the legth of hash table must be power of 2. */ +typedef struct _CLIWDS_PROXY_ENTRY { + struct _CLIWDS_PROXY_ENTRY * pNext; + ULONG LastRefTime; + SHORT Aid; + UCHAR Addr[MAC_ADDR_LEN]; +} CLIWDS_PROXY_ENTRY, *PCLIWDS_PROXY_ENTRY; + +#endif /* CLIENT_WDS */ + +#endif /* __CLIENT_WDS_CMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_aes.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_aes.h new file mode 100644 index 000000000..ab763ceb2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_aes.h @@ -0,0 +1,176 @@ +/**************************************************************************** + * 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: + AES + + Abstract: + RFC 3394: Advanced Encryption Standard (AES) Key Wrap Algorithm + RFC 3601: Counter with CBC-MAC (CCM) + RFC 4493: The AES-CMAC Algorithm + FIPS PUBS 197: ADVANCED ENCRYPTION STANDARD (AES) + NIST 800-38A: Recommendation for Block Cipher Modes of Operation + NIST 800-38C: The CCM Mode for Authentication and Confidentiality + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/05/19 Create AES-Key Wrap + Eddy 2009/04/20 Create AES-CMAC, AES-CCM + Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC +***************************************************************************/ + +#ifndef __CRYPT_AES_H__ +#define __CRYPT_AES_H__ + +#include "rt_config.h" + + +/* AES definition & structure */ +#define AES_STATE_ROWS 4 /* Block size: 4*4*8 = 128 bits */ +#define AES_STATE_COLUMNS 4 +#define AES_BLOCK_SIZES AES_STATE_ROWS*AES_STATE_COLUMNS +#define AES_KEY_ROWS 4 +#define AES_KEY_COLUMNS 8 /*Key length: 4*{4,6,8}*8 = 128, 192, 256 bits */ +#define AES_KEY128_LENGTH 16 +#define AES_KEY192_LENGTH 24 +#define AES_KEY256_LENGTH 32 +#define AES_CBC_IV_LENGTH 16 + +typedef struct { + UINT8 State[AES_STATE_ROWS][AES_STATE_COLUMNS]; + UINT8 KeyWordExpansion[AES_KEY_ROWS][AES_KEY_ROWS*((AES_KEY256_LENGTH >> 2) + 6 + 1)]; +} AES_CTX_STRUC, *PAES_CTX_STRUC; + + +/* AES operations */ +VOID RT_AES_KeyExpansion ( + IN UINT8 Key[], + IN UINT KeyLength, + INOUT AES_CTX_STRUC *paes_ctx); + +VOID RT_AES_Encrypt ( + IN UINT8 PlainBlock[], + IN UINT PlainBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherBlock[], + INOUT UINT *CipherBlockSize); + +VOID RT_AES_Decrypt ( + IN UINT8 CipherBlock[], + IN UINT CipherBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainBlock[], + INOUT UINT *PlainBlockSize); + +/* AES Counter with CBC-MAC operations */ +VOID AES_CCM_MAC ( + IN UINT8 Payload[], + IN UINT PayloadLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 MACText[]); + +INT AES_CCM_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength); + +INT AES_CCM_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength); + +/* AES-CMAC operations */ +VOID AES_CMAC_GenerateSubKey ( + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 SubKey1[], + OUT UINT8 SubKey2[]); + +VOID AES_CMAC ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 MACText[], + INOUT UINT *MACTextLength); + + + +/* AES-CBC operations */ +VOID AES_CBC_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength); + +VOID AES_CBC_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength); + +/* AES key wrap operations */ +INT AES_Key_Wrap ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherText[], + OUT UINT *CipherTextLength); + +INT AES_Key_Unwrap ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainText [], + OUT UINT *PlainTextLength); + + +#endif /* __CRYPT_AES_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_arc4.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_arc4.h new file mode 100644 index 000000000..63d87ce35 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_arc4.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * 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 +***************************************************************************/ + +#ifndef __CRYPT_ARC4_H__ +#define __CRYPT_ARC4_H__ + +#include "rt_config.h" + +/* ARC4 definition & structure */ +#define ARC4_KEY_BLOCK_SIZE 256 + +typedef struct { + UINT BlockIndex1; + UINT BlockIndex2; + UINT8 KeyBlock[256]; +} ARC4_CTX_STRUC, *PARC4_CTX_STRUC; + +/* ARC4 operations */ +VOID ARC4_INIT( + IN ARC4_CTX_STRUC * pARC4_CTX, + IN PUCHAR pKey, + IN UINT KeyLength); + +VOID ARC4_Compute( + IN ARC4_CTX_STRUC * pARC4_CTX, + IN UINT8 InputBlock[], + IN UINT InputBlockSize, + OUT UINT8 OutputBlock[]); + +VOID ARC4_Discard_KeyLength( + IN ARC4_CTX_STRUC * pARC4_CTX, + IN UINT Length); + +#endif /* __CRYPT_ARC4_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_biginteger.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_biginteger.h new file mode 100644 index 000000000..8fe20c611 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_biginteger.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * 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: + BigInteger + + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/01/12 Create +***************************************************************************/ + +#ifndef __CRYPT_BIGINTEGER_H__ +#define __CRYPT_BIGINTEGER_H__ + +#include "rt_config.h" + + +/* BigInteger definition & structure */ +#define SLIDING_WINDOW 16 +typedef struct _BIG_INTEGER_STRUC +{ + STRING Name[10]; + UINT32 *pIntegerArray; + UINT AllocSize; + UINT ArrayLength; + UINT IntegerLength; + INT Signed; +} BIG_INTEGER, *PBIG_INTEGER; + + +/* BigInteger operations */ +VOID BigInteger_Print ( + IN PBIG_INTEGER pBI); + +VOID BigInteger_Init ( + INOUT PBIG_INTEGER *pBI); + +VOID BigInteger_Free_AllocSize ( + IN PBIG_INTEGER *pBI); + +VOID BigInteger_Free ( + IN PBIG_INTEGER *pBI); + +VOID BigInteger_AllocSize ( + IN PBIG_INTEGER *pBI, + IN INT Length); + +VOID BigInteger_ClearHighBits ( + IN PBIG_INTEGER pBI); + +VOID BigInteger_BI2Bin ( + IN PBIG_INTEGER pBI, + OUT UINT8 *pValue, + OUT UINT *Length); + +VOID BigInteger_Bin2BI ( + IN UINT8 *pValue, + IN UINT Length, + OUT PBIG_INTEGER *pBI); + +VOID BigInteger_BitsOfBI ( + IN PBIG_INTEGER pBI, + OUT UINT *Bits_Of_P); + +INT BigInteger_GetBitValue ( + IN PBIG_INTEGER pBI, + IN UINT Index); + +UINT8 BigInteger_GetByteValue ( + IN PBIG_INTEGER pBI, + IN UINT Index); + +VOID BigInteger_Copy ( + IN PBIG_INTEGER pBI_Copied, + OUT PBIG_INTEGER *pBI_Result); + +INT BigInteger_UnsignedCompare ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand); + +VOID BigInteger_Add ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result); + +VOID BigInteger_Sub ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result); + +VOID BigInteger_Mul ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result); + +VOID BigInteger_Square ( + IN PBIG_INTEGER pBI, + OUT PBIG_INTEGER *pBI_Result); + +VOID BigInteger_Div ( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result, + OUT PBIG_INTEGER *pBI_Remainder); + +VOID BigInteger_Montgomery_Reduction ( + IN PBIG_INTEGER pBI_A, + IN PBIG_INTEGER pBI_P, + IN PBIG_INTEGER pBI_R, + OUT PBIG_INTEGER *pBI_Result); + +VOID BigInteger_Montgomery_ExpMod ( + IN PBIG_INTEGER pBI_G, + IN PBIG_INTEGER pBI_E, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result); + + +#endif /* __CRYPT_BIGINTEGER_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_dh.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_dh.h new file mode 100644 index 000000000..b1cdab015 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_dh.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * 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, Montgomery Algorithm +***************************************************************************/ + +#ifndef __CRYPT_DH_H__ +#define __CRYPT_DH_H__ + +#include "rt_config.h" + + +/* DH operations */ +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); + +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); + +#define RT_DH_PublicKey_Generate(GK, GKL, PV, PVL, PriK, PriKL, PubK, PubKL) \ + DH_PublicKey_Generate((GK), (GKL), (PV), (PVL), (PriK), (PriKL), (UINT8 *) (PubK), (UINT *) (PubKL)) + +#define RT_DH_SecretKey_Generate(PubK, PubKL, PV, PVL, PriK, PriKL, SecK, SecKL) \ + DH_SecretKey_Generate((PubK), (PubKL), (PV), (PVL), (PriK), (PriKL), (UINT8 *) (SecK), (UINT *) (SecKL)) + +#define RT_DH_FREE_ALL() + + +#endif /* __CRYPT_DH_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_hmac.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_hmac.h new file mode 100644 index 000000000..e6dd220f8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_hmac.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * 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 +***************************************************************************/ + +#ifndef __CRYPT_HMAC_H__ +#define __CRYPT_HMAC_H__ + +#include "rt_config.h" + + +#ifdef SHA1_SUPPORT +#define HMAC_SHA1_SUPPORT +VOID RT_HMAC_SHA1( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen); +#endif /* SHA1_SUPPORT */ + +#ifdef SHA256_SUPPORT +#define HMAC_SHA256_SUPPORT +VOID RT_HMAC_SHA256( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen); +#endif /* SHA256_SUPPORT */ + +#ifdef MD5_SUPPORT +#define HMAC_MD5_SUPPORT +VOID RT_HMAC_MD5( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen); +#endif /* MD5_SUPPORT */ + + +#endif /* __CRYPT_HMAC_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_md5.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_md5.h new file mode 100644 index 000000000..60cf5d3ba --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_md5.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * 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 +***************************************************************************/ + +#ifndef __CRYPT_MD5_H__ +#define __CRYPT_MD5_H__ + + +/* Algorithm options */ +#define MD5_SUPPORT + +#ifdef MD5_SUPPORT +#define MD5_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ +#define MD5_DIGEST_SIZE 16 /* 128 bits = 16 bytes */ +typedef struct { + UINT32 HashValue[4]; + UINT64 MessageLen; + UINT8 Block[MD5_BLOCK_SIZE]; + UINT BlockLen; +} MD5_CTX_STRUC, *PMD5_CTX_STRUC; + +VOID RT_MD5_Init( + IN MD5_CTX_STRUC * pMD5_CTX); +VOID RT_MD5_Hash( + IN MD5_CTX_STRUC * pMD5_CTX); +VOID RT_MD5_Append( + IN MD5_CTX_STRUC * pMD5_CTX, + IN const UINT8 Message[], + IN UINT MessageLen); +VOID RT_MD5_End( + IN MD5_CTX_STRUC * pMD5_CTX, + OUT UINT8 DigestMessage[]); +VOID RT_MD5( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); +#endif /* MD5_SUPPORT */ + + +#endif /* __CRYPT_MD5_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_sha2.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_sha2.h new file mode 100644 index 000000000..9d2e43e52 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/crypt_sha2.h @@ -0,0 +1,92 @@ +/**************************************************************************** + * 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 +***************************************************************************/ + +#ifndef __CRYPT_SHA2_H__ +#define __CRYPT_SHA2_H__ + + +/* Algorithm options */ +#define SHA1_SUPPORT +#define SHA256_SUPPORT + +#ifdef SHA1_SUPPORT +#define SHA1_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ +#define SHA1_DIGEST_SIZE 20 /* 160 bits = 20 bytes */ +typedef struct _SHA1_CTX_STRUC { + UINT32 HashValue[5]; /* 5 = (SHA1_DIGEST_SIZE / 32) */ + UINT64 MessageLen; /* total size */ + UINT8 Block[SHA1_BLOCK_SIZE]; + UINT BlockLen; +} SHA1_CTX_STRUC, *PSHA1_CTX_STRUC; + +VOID RT_SHA1_Init( + IN SHA1_CTX_STRUC * pSHA_CTX); +VOID RT_SHA1_Hash( + IN SHA1_CTX_STRUC * pSHA_CTX); +VOID RT_SHA1_Append( + IN SHA1_CTX_STRUC * pSHA_CTX, + IN const UINT8 Message[], + IN UINT MessageLen); +VOID RT_SHA1_End( + IN SHA1_CTX_STRUC * pSHA_CTX, + OUT UINT8 DigestMessage[]); +VOID RT_SHA1( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); +#endif /* SHA1_SUPPORT */ + +#ifdef SHA256_SUPPORT +#define SHA256_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ +#define SHA256_DIGEST_SIZE 32 /* 256 bits = 32 bytes */ +typedef struct _SHA256_CTX_STRUC { + UINT32 HashValue[8]; /* 8 = (SHA256_DIGEST_SIZE / 32) */ + UINT64 MessageLen; /* total size */ + UINT8 Block[SHA256_BLOCK_SIZE]; + UINT BlockLen; +} SHA256_CTX_STRUC, *PSHA256_CTX_STRUC; + +VOID RT_SHA256_Init( + IN SHA256_CTX_STRUC * pSHA_CTX); +VOID RT_SHA256_Hash( + IN SHA256_CTX_STRUC * pSHA_CTX); +VOID RT_SHA256_Append( + IN SHA256_CTX_STRUC * pSHA_CTX, + IN const UINT8 Message[], + IN UINT MessageLen); +VOID RT_SHA256_End( + IN SHA256_CTX_STRUC * pSHA_CTX, + OUT UINT8 DigestMessage[]); +VOID RT_SHA256( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); +#endif /* SHA256_SUPPORT */ + + +#endif /* __CRYPT_SHA2_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cs.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cs.h new file mode 100644 index 000000000..458f018b3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/cs.h @@ -0,0 +1,182 @@ +#ifndef __CS_H__ +#define __CS_H__ + +#ifdef CARRIER_DETECTION_SUPPORT +#define CARRIER_DETECT_RECHECK_TIME 3 +#define CARRIER_GONE_TRESHOLD 10 /* Radar tone count in 1 sec */ +#define CARRIER_DETECT_THRESHOLD 0x0fffffff +#define CARRIER_DETECT_STOP_RATIO 2 +#define CARRIER_DETECT_STOP_RECHECK_TIME 4 +#define CARRIER_DETECT_DEFAULT_MASK 20 +#define CARRIER_DETECT_DELTA 7 +#define CARRIER_DETECT_DIV_FLAG 0 +#define CD_INT_POLLING_CMD 0x67 +#ifdef RTMP_RBUS_SUPPORT +#define CARRIER_DETECT_CRITIRIA 280 +#else +#define CARRIER_DETECT_CRITIRIA 7000 +#endif /* RTMP_RBUS_SUPPORT */ + +typedef enum CD_STATE_n { + CD_NORMAL, + CD_SILENCE, + CD_MAX_STATE +} CD_STATE; + +typedef enum _TONE_RADAR_VERSION { + DISABLE_TONE_RADAR = 0, + TONE_RADAR_V1, + TONE_RADAR_V2, + TONE_RADAR_V3 +} TONE_RADAR_VERSION; + +typedef struct CARRIER_DETECTION_s { + BOOLEAN Enable; + BOOLEAN bCsInit; + UINT8 CDSessionTime; + UINT8 CDPeriod; + CD_STATE CD_State; + UINT8 delta; + UINT8 SymRund; + UINT8 div_flag; + UINT32 threshold; + UINT8 recheck; + UINT8 recheck1; + UINT32 TimeStamp; /*unit:16us*/ + UINT32 criteria; + ULONG idle_time; + ULONG busy_time; + ULONG Debug; + ULONG OneSecIntCount; + UINT8 CarrierGoneThreshold; + UCHAR VGA_Mask; + UCHAR Packet_End_Mask; + UCHAR Rx_PE_Mask; +} CARRIER_DETECTION_STRUCT, *PCARRIER_DETECTION_STRUCT; + +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT +/* Mcu command */ +#define CD_ONOFF_MCU_CMD 0x65 +#define CD_CHECKOUT_MCU_CMD 0x66 +/* share memory offsets */ +#define CD_CRITERIA 0x4CB2 +#define CD_CHECK_COUNT 0x4CB9 +#define RADAR_TONE_COUNT 0x4CBE +#define CD_RECHECK 0x4CBF +#undef CARRIER_DETECT_RECHECK_TIME +#undef CARRIER_GONE_TRESHOLD +#undef CARRIER_DETECT_THRESHOLD +#define CARRIER_DETECT_RECHECK_TIME 5 +#define CARRIER_GONE_TRESHOLD 35 +#define CARRIER_DETECT_THRESHOLD 0x4fffffff + +/* Parameters needed to decide the Carrier Detect State */ +typedef struct _CARRIER_DETECT_PARAM { + UINT8 RadarToneCount; /* Number of radar tones in 100 msec*/ + UINT8 ReCheck; +} CARRIER_DETECT_PARAM, *PCARRIER_DETECT_PARAM; + +/* For debug print */ +typedef struct _CARRIER_DETECT_DEBUG { + UINT8 delta_div; + UINT8 internalRadarToneCount; + UINT16 Criteria; + UINT32 Threshold; + UINT8 Count; + UINT8 CheckCount; + UINT8 Reserved; + UINT8 VGA_Mask; + UINT8 PckMask; + UINT8 RxPeMask; + UINT8 RadarToneCount; + UINT8 ReCheck; +} CARRIER_DETECT_DEBUG, *PCARRIER_DETECT_DEBUG; +#endif /*CARRIER_DETECTION_FIRMWARE_SUPPORT*/ + +INT isCarrierDetectExist( + IN PRTMP_ADAPTER pAd); + +INT CarrierDetectReset( + IN PRTMP_ADAPTER pAd); + +extern VOID RtmpOsMsDelay( + IN ULONG msec); + +INT Set_CarrierCriteria_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierReCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierGoneThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierStopCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierDelta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierDivFlag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* v2 functions */ +INT Set_CarrierSymRund_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CarrierMask_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID CSInit( + IN PRTMP_ADAPTER pAd); + +VOID CarrierDetectionStart( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleRadarInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID CarrierDetectionStop( + IN PRTMP_ADAPTER pAd); + +#ifdef RTMP_BBP +VOID ToneRadarProgram_v1( + IN PRTMP_ADAPTER pAd, + IN ULONG threshold); + +VOID ToneRadarProgram_v2( + IN PRTMP_ADAPTER pAd, + IN ULONG threshold); +#endif /* RTMP_BBP */ + +VOID ToneRadarProgram_v3( + IN PRTMP_ADAPTER pAd, + IN ULONG threshold); + +VOID CarrierDetectionPeriodicStateCtrl( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_AP_SUPPORT +INT Set_CarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /*CONFIG_AP_SUPPORT*/ +#endif /* CARRIER_DETECTION_SUPPORT */ + +#endif /*__CS_H__*/ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/default_profile.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/default_profile.h new file mode 100644 index 000000000..70e454ed0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/default_profile.h @@ -0,0 +1,137 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +PUCHAR default_profile_buffer = +"Default\n" +"CountryRegion=5\n" +"CountryRegionABand=7\n" +"CountryCode=TW\n" +"BssidNum=1\n" +"SSID=RT2860AP\n" +"WirelessMode=9\n" +"TxRate=0\n" +"Channel=11\n" +"BasicRate=15\n" +"BeaconPeriod=100\n" +"DtimPeriod=1\n" +"TxPower=100\n" +"DisableOLBC=0\n" +"BGProtection=0\n" +"TxAntenna=\n" +"RxAntenna=\n" +"TxPreamble=0\n" +"RTSThreshold=2347\n" +"FragThreshold=2346\n" +"TxBurst=1\n" +"PktAggregate=0\n" +"TurboRate=0\n" +"WmmCapable=0\n" +"APSDCapable=0\n" +"DLSCapable=0\n" +"APAifsn=3;7;1;1\n" +"APCwmin=4;4;3;2\n" +"APCwmax=6;10;4;3\n" +"APTxop=0;0;94;47\n" +"APACM=0;0;0;0\n" +"BSSAifsn=3;7;2;2\n" +"BSSCwmin=4;4;3;2\n" +"BSSCwmax=10;10;4;3\n" +"BSSTxop=0;0;94;47\n" +"BSSACM=0;0;0;0\n" +"AckPolicy=0;0;0;0\n" +"NoForwarding=0\n" +"NoForwardingBTNBSSID=0\n" +"HideSSID=0\n" +"StationKeepAlive=0\n" +"ShortSlot=1\n" +"AutoChannelSelect=0\n" +"IEEE8021X=0\n" +"IEEE80211H=0\n" +"CSPeriod=10\n" +"WirelessEvent=0\n" +"IdsEnable=0\n" +"AuthFloodThreshold=32\n" +"AssocReqFloodThreshold=32\n" +"ReassocReqFloodThreshold=32\n" +"ProbeReqFloodThreshold=32\n" +"DisassocFloodThreshold=32\n" +"DeauthFloodThreshold=32\n" +"EapReqFooldThreshold=32\n" +"PreAuth=0\n" +"AuthMode=OPEN\n" +"EncrypType=NONE\n" +"RekeyInterval=0\n" +"RekeyMethod=DISABLE\n" +"PMKCachePeriod=10\n" +"WPAPSK=\n" +"DefaultKeyID=1\n" +"Key1Type=0\n" +"Key1Str=\n" +"Key2Type=0\n" +"Key2Str=\n" +"Key3Type=0\n" +"Key3Str=\n" +"Key4Type=0\n" +"Key4Str=\n" +"HSCounter=0\n" +"AccessPolicy0=0\n" +"AccessControlList0=\n" +"AccessPolicy1=0\n" +"AccessControlList1=\n" +"AccessPolicy2=0\n" +"AccessControlList2=\n" +"AccessPolicy3=0\n" +"AccessControlList3=\n" +"WdsEnable=0\n" +"WdsEncrypType=NONE\n" +"WdsList=\n" +"WdsKey=\n" +"RADIUS_Server=192.168.2.3\n" +"RADIUS_Port=1812\n" +"RADIUS_Key=ralink\n" +"own_ip_addr=192.168.5.234\n" +"EAPifname=br0\n" +"PreAuthifname=br0\n" +"HT_HTC=0\n" +"HT_RDG=0\n" +"HT_EXTCHA=0\n" +"HT_LinkAdapt=0\n" +"HT_OpMode=0\n" +"HT_MpduDensity=5\n" +"HT_BW=1\n" +"HT_AutoBA=1\n" +"HT_AMSDU=0\n" +"HT_BAWinSize=64\n" +"HT_GI=1\n" +"HT_LDPC=1\n" +"HT_MCS=33\n" +"VHT_BW=1\n" +"VHT_SGI=1\n" +"VHT_STBC=0\n" +"VHT_BW_SIGNAL=0\n" +"VHT_DisallowNonVHT=0\n" +"VHT_LDPC=1\n" +"MeshId=MESH\n" +"MeshAutoLink=1\n" +"MeshAuthMode=OPEN\n" +"MeshEncrypType=NONE\n" +"MeshWPAKEY=\n" +"MeshDefaultkey=1\n" +"MeshWEPKEY=\n" +"WscManufacturer=\n" +"WscModelName=\n" +"WscDeviceName=\n" +"WscModelNumber=\n" +"WscSerialNumber=\n" +"RadioOn=1\n" +"PMFMFPC=0\n" +"PMFMFPR=0\n" +"PMFSHA256=0\n" +"USBAggregation=1\n" +"LoadCodeMethod=0\n" +"EDCCA_ED_TH=90\n" +"EDCCA_FALSE_CCA_TH=180\n" +"EDCCA_BLOCK_CHECK_TH=2\n" +"ED_MODE=1\n" +; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dfs.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dfs.h new file mode 100644 index 000000000..c983e2048 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dfs.h @@ -0,0 +1,519 @@ + +/* + *************************************************************************** + * 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: + dfs.h + + Abstract: + Support DFS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 03-12-2007 created +*/ +#ifndef __DFS_H__ +#define __DFS_H__ + +/************************************************************************* + * + * DFS Radar related definitions. + * + ************************************************************************/ + +#ifdef DFS_SUPPORT +#define RADAR_DEBUG_SHOW_RAW_EVENT 0x01 /* Show the 384-bytes raw data of event buffer */ +#define RADAR_DEBUG_EVENT 0x02 /* Show effective event reads out from the event buffer */ +#define RADAR_DEBUG_SILENCE 0x04 +#define RADAR_DEBUG_SW_SILENCE 0x08 +#define RADAR_DONT_SWITCH 0x10 /* Don't Switch channel when hit */ +#define RADAR_DEBUG_DONT_CHECK_BUSY 0x20 +#define RADAR_DEBUG_DONT_CHECK_RSSI 0x40 +#define RADAR_SIMULATE 0x80 /* simulate a short pulse hit this channel */ + +/* McuCmd */ +#define DFS_ONOFF_MCU_CMD 0x64 + +/*#define DFS_SW_RADAR_DECLARE_THRES 3*/ +#ifdef RLT_BBP +#define DFS_EVENT_SIZE 4 /* Number of UINT32 of each DFS event buffer data */ +#else +#define DFS_EVENT_SIZE 6 /* Number of bytes of each DFS event */ +#endif +#define DFS_EVENT_BUFFER_SIZE 384 /* Number of bytes of a DFS event buffer */ +#define DFS_SW_RADAR_CHECK_LOOP 50 +#define DFS_SW_RADAR_SHIFT 3 +#define DFS_SW_RADAR_CH0_ERR 8 +#define DFS_SW_RADAR_PERIOD_ERR 4 +#define CE_STAGGERED_RADAR_CH0_H_ERR (DFS_SW_RADAR_CH0_ERR + 16) // the step is 16 for every 0.1 us different in width +#define CE_STAGGERED_RADAR_DECLARE_THRES 2 + +#define NEW_DFS_FCC_5_ENT_NUM 5 +#define NEW_DFS_DBG_PORT_ENT_NUM_POWER 8 +#define NEW_DFS_DBG_PORT_ENT_NUM (1 << NEW_DFS_DBG_PORT_ENT_NUM_POWER) /* CE Debug Port entry number, 256 */ +#define NEW_DFS_DBG_PORT_MASK (NEW_DFS_DBG_PORT_ENT_NUM - 1) /* 0xff */ + +#define CH_BUSY_SAMPLE_POWER 3 +#define CH_BUSY_SAMPLE (1 << CH_BUSY_SAMPLE_POWER) +#define CH_BUSY_MASK (CH_BUSY_SAMPLE - 1) + +#define MAX_FDF_NUMBER 5 /* max false-detection-filter number */ + +/* Matched Period definition */ +#define NEW_DFS_MPERIOD_ENT_NUM_POWER 8 +#define NEW_DFS_MPERIOD_ENT_NUM (1 << NEW_DFS_MPERIOD_ENT_NUM_POWER) /* CE Period Table entry number, 512 */ +#define NEW_DFS_CHANNEL_0 1 +#define NEW_DFS_CHANNEL_1 2 +#define NEW_DFS_CHANNEL_2 4 +#define NEW_DFS_CHANNEL_3 8 +#define NEW_DFS_CHANNEL_4 16 +#define NEW_DFS_CHANNEL_5 32 + + +#define NEW_DFS_MAX_CHANNEL 5 +#define HW_TIMER_INTERVAL 10 +#ifdef RLT_BBP +#define DFS_RESET_INTERVAL (5000/HW_TIMER_INTERVAL) +#endif /* MT76x0 */ +#define CE_SW_CHECK 3 + +#define NEW_DFS_WATCH_DOG_TIME 1 /* note that carrier detection also need timer interrupt hook*/ + +#define NEW_DFS_FCC 0x1 /* include Japan*/ +#define NEW_DFS_EU 0x2 +#define NEW_DFS_JAP 0x4 +#define NEW_DFS_JAP_W53 0x8 +#define NEW_DFS_END 0xff +#define MAX_VALID_RADAR_W 5 +#define MAX_VALID_RADAR_T 5 + +#define DFS_SW_RADAR_CH1_SHIFT 3 +#define DFS_SW_RADAR_CH2_SHIFT 3 + +#define CE_STAGGERED_RADAR_PERIOD_MAX ((133333 + 125000 + 117647 + 1000) * 2) +#define FCC_RADAR_PERIOD_MAX (((28570 << 1) + 1000) * 2) +#define JAP_RADAR_PERIOD_MAX (((80000 << 1) + 1000) * 2) + +#define NEW_DFS_BANDWITH_MONITOR_TIME (NEW_DFS_CHECK_TIME / NEW_DFS_CHECK_TIME_TASKLET) +#define NEW_DFS_CHECK_TIME 300 +#define NEW_DFS_CHECK_TIME_TASKLET 3 + +/*#define DFS_SW_RADAR_DECLARE_THRES 3*/ + +#define DFS_SW_RADAR_SHIFT 3 + +#define DFS_SW_RADAR_CH0_ERR 8 + +#define CE_STAGGERED_RADAR_CH0_H_ERR (DFS_SW_RADAR_CH0_ERR + 16) /* the step is 16 for every 0.1 us different in width*/ + +#define CE_STAGGERED_RADAR_DECLARE_THRES 2 + + +/* DFS Macros */ +#define PERIOD_MATCH(a, b, c) ((a >= b)? ((a-b) <= c):((b-a) <= c)) +#define ENTRY_PLUS(a, b, c) (((a+b) < c)? (a+b) : (a+b-c)) +#define ENTRY_MINUS(a, b, c) ((a >= b)? (a - b) : (a+c-b)) +#define MAX_PROCESS_ENTRY 16 + +#define IS_FCC_RADAR_1(HT_BW, T) (((HT_BW)? ((T > 57120) && (T < 57160)) : (T > 28560) && (T < 28580))) +#define IS_W53_RADAR_2(HT_BW, T) (((HT_BW)? ((T > 153820) && (T < 153872)) : (T > 76910) && (T < 76936))) +#define IS_W56_RADAR_3(HT_BW, T) (((HT_BW)? ((T > 159900) && (T < 160100)) : (T > 79950) && (T < 80050))) + +#define DFS_EVENT_SANITY_CHECK(_pAd, _DfsEvent) \ + !(((_DfsEvent).EngineId >= _pAd->chipCap.DfsEngineNum) || \ + ((_DfsEvent).TimeStamp & 0xffc00000) || \ + ((_DfsEvent).Width & 0xe000)) + +#ifdef RLT_BBP +#define MT7650_DFS_EVENT_SANITY_CHECK(_pAd, _DfsEvent) \ + !(((_DfsEvent).EngineId >= _pAd->chipCap.DfsEngineNum) || \ + ((_DfsEvent).TimeStamp & 0xffc00000) || \ + ((_DfsEvent).Width & 0xF000) || \ + ((_DfsEvent).power_stable_counter >= 5)) + +#define MT7650_DFS_EVENT_BUFF_PRINT(_StarIdx, _TableIdx, _BufSize) \ +{ \ + UINT32 __k; \ + for (__k = _StarIdx; __k < _BufSize; __k++) \ + { \ + DBGPRINT(RT_DEBUG_TRACE, ("0x%08x ", _TableIdx[__k])); \ + if(__k%DFS_EVENT_SIZE == ((DFS_EVENT_SIZE-1+_StarIdx)%DFS_EVENT_SIZE)) \ + DBGPRINT(RT_DEBUG_TRACE, ("\n")); \ + } \ +} + +/* + 2a7c=0x00xx0307 + (2a7c[23:16] = (2310[21:16] + 2320[14:9] - 2320[5:3]), CR2320/2310 is from bring up result) +*/ + /* AGC Input Control */ +#define MT7650_ADJUST_DFS_AGC(_pAd) \ +{ \ + UINT32 bbp_val = 0, dfs_r31 = 0; \ + RTMP_BBP_IO_READ32(_pAd, AGC1_R4, &bbp_val); \ + dfs_r31 = (bbp_val & 0x003f0000) >> 16;\ + RTMP_BBP_IO_READ32(_pAd, AGC1_R8, &bbp_val);\ + dfs_r31 += (bbp_val & 0x00007e00) >> 9;\ + RTMP_BBP_IO_READ32(_pAd, AGC1_R8, &bbp_val);\ + dfs_r31 -= (bbp_val & 0x00000038) >> 3;\ + dfs_r31 = (dfs_r31 << 16) | 0x00000307;\ + RTMP_BBP_IO_WRITE32(_pAd, DFS_R31, dfs_r31); \ +} + +/* Normal AGC1_R4 must adjust accordingly as AGC1_R8 change */ +#define MT7650_ADJUST_AGC(_pAd) \ +{ \ + UINT32 Agc_R8 = 0, Agc_R4 = 0; \ + RTMP_BBP_IO_READ32(_pAd, AGC1_R8, &Agc_R8); \ + Agc_R8 = (((Agc_R8 & 0x00007e00) >> 9) +1) >> 1;\ + RTMP_BBP_IO_READ32(_pAd, AGC1_R4, &Agc_R4);\ + Agc_R4 = (Agc_R4 & ~0x1f000000);\ + Agc_R4 += (Agc_R8 << 24);\ + RTMP_BBP_IO_WRITE32(_pAd, AGC1_R4, Agc_R4); \ +} +#endif /* MT76x0 */ + +#define DFS_EVENT_PRINT(_DfsEvent) \ + DBGPRINT(RT_DEBUG_ERROR, ( "EngineId = %u, Timestamp = %u, Width = %u\n", \ + _DfsEvent.EngineId, _DfsEvent.TimeStamp, _DfsEvent.Width)); + + +#define DFS_EVENT_BUFF_PRINT(_StarIdx, _TableIdx, _BufSize) \ +{ \ + UINT32 k; \ + for (k = _StarIdx; k < _BufSize; k++) \ + { \ + DBGPRINT(RT_DEBUG_TRACE, ("0x%02x ", _TableIdx[k])); \ + if(k%DFS_EVENT_SIZE == ((DFS_EVENT_SIZE-1+_StarIdx)%DFS_EVENT_SIZE)) \ + DBGPRINT(RT_DEBUG_TRACE, ("\n")); \ + } \ +} + +/* check whether we can do DFS detection or not */ +#define DFS_CHECK_FLAGS(_pAd, _pRadarDetect) \ + !((_pAd->Dot11_H.RDMode == RD_SWITCHING_MODE) || \ + (_pRadarDetect->bDfsInit == FALSE) || \ + (_pRadarDetect->DFSAPRestart == 1) || \ + (ScanRunning(_pAd) == TRUE)) + + +typedef enum _DFS_VERSION { + SOFTWARE_DFS = 0, + HARDWARE_DFS_V1, + HARDWARE_DFS_V2 +} DFS_VERSION; + +typedef struct _NewDFSValidRadar +{ + USHORT type; + USHORT channel; /* bit map*/ + USHORT WLow; + USHORT WHigh; + USHORT W; /* for fixed width radar*/ + USHORT WMargin; + ULONG TLow; + ULONG THigh; + ULONG T; /* for fixed period radar */ + USHORT TMargin; +}NewDFSValidRadar, *pNewDFSValidRadar; + +typedef struct _NewDFSDebugPort { + ULONG counter; + ULONG timestamp; + USHORT width; + USHORT start_idx; /* start index to period table */ + USHORT end_idx; /* end index to period table */ +} NewDFSDebugPort, *pNewDFSDebugPort; + +/* Matched Period Table */ +typedef struct _NewDFSMPeriod { + USHORT idx; + USHORT width; + USHORT idx2; + USHORT width2; + ULONG period; +} NewDFSMPeriod, *pNewDFSMPeriod; + +typedef struct _DFS_ENGINE_LOCAL_CFG { + BOOLEAN valid; + UCHAR mode; + USHORT avgLen; + USHORT ELow; + USHORT EHigh; + USHORT WLow; + USHORT WHigh; + UCHAR EpsilonW; + ULONG TLow; + ULONG THigh; + UCHAR EpsilonT; + ULONG BLow; + ULONG BHigh; + UINT32 EventExpiration; + UINT16 PwrJump; +} DFS_ENGINE_LOCAL_CFG, *pDFS_ENGINE_LOCAL_CFG; + +typedef struct _DFS_PROGRAM_PARAM{ + DFS_ENGINE_LOCAL_CFG NewDFSTableEntry[NEW_DFS_MAX_CHANNEL*4]; + USHORT ChEnable; /* Enabled Dfs channels (bit wise)*/ + UCHAR DeltaDelay; + UCHAR Symmetric_Round; + UCHAR VGA_Mask; + UCHAR Packet_End_Mask; + UCHAR Rx_PE_Mask; + UCHAR PwrDown_Hold_Time; + UCHAR PwrGain_Offset; +}DFS_PROGRAM_PARAM, *PDFS_PROGRAM_PARAM; + +typedef struct _NewDFSTable +{ + USHORT type; + DFS_ENGINE_LOCAL_CFG entry[NEW_DFS_MAX_CHANNEL]; +}NewDFSTable, *pNewDFSTable; + +#ifdef DFS_DEBUG +typedef struct _NewDFSDebugResult +{ + char delta_delay_shift; + char EL_shift; + char EH_shift; + char WL_shift; + char WH_shift; + ULONG hit_time; + ULONG false_time; +}NewDFSDebugResult, *pNewDFSDebugResult; +#endif + +typedef struct _DFS_EVENT{ + UINT8 EngineId; + UINT32 TimeStamp; + UINT16 Width; +#ifdef RLT_BBP + UINT16 phase; + UINT8 power_stable_counter; + UINT16 current_power; +#endif /* MT76x0 */ +}DFS_EVENT, *PDFS_EVENT; + +typedef struct _DFS_SW_DETECT_PARAM{ + USHORT dfs_width_diff_ch1_Shift; + USHORT dfs_width_diff_ch2_Shift; + USHORT dfs_period_err; + ULONG dfs_max_period; /* Max possible Period */ + USHORT dfs_width_diff; + USHORT dfs_width_ch0_err_L; + USHORT dfs_width_ch0_err_H; + UCHAR dfs_check_loop; + UCHAR dfs_declare_thres; + ULONG dfs_w_counter; + DFS_EVENT PreDfsEvent; /* previous radar event */ + UINT32 EvtDropAdjTime; /* timing threshold for adjacent event */ + UINT sw_idx[NEW_DFS_MAX_CHANNEL]; + UINT hw_idx[NEW_DFS_MAX_CHANNEL]; + UINT pr_idx[NEW_DFS_MAX_CHANNEL]; + USHORT dfs_t_idx[NEW_DFS_MAX_CHANNEL]; + USHORT dfs_w_idx[NEW_DFS_MAX_CHANNEL]; + USHORT dfs_w_last_idx[NEW_DFS_MAX_CHANNEL]; + NewDFSDebugPort DFS_W[NEW_DFS_MAX_CHANNEL][NEW_DFS_DBG_PORT_ENT_NUM]; + NewDFSMPeriod DFS_T[NEW_DFS_MAX_CHANNEL][NEW_DFS_MPERIOD_ENT_NUM]; /* period table */ +}DFS_SW_DETECT_PARAM, *PDFS_SW_DETECT_PARAM; + +/*************************************************************************** + * structure for radar detection and channel switch + **************************************************************************/ +typedef struct _RADAR_DETECT_STRUCT { + UCHAR DFSAPRestart; + ULONG MCURadarRegion; + ULONG TimeStamp; /*unit: 1us*/ + UCHAR ChirpCheck; /* anounce on second detection of chirp radar */ + UCHAR bChannelSwitchInProgress; /* RDMode could cover this*/ + BOOLEAN bDfsSwDisable; /* disable sotfwre check */ + BOOLEAN bDfsInit; /* to indicate if dfs regs has been initialized */ + USHORT PollTime; + INT DfsRssiHigh; + INT DfsRssiLow; + BOOLEAN DfsRssiHighFromCfg; + BOOLEAN DfsRssiLowFromCfg; + BOOLEAN DfsRssiHighCfgValid; + BOOLEAN DfsRssiLowCfgValid; + BOOLEAN DFSParamFromConfig; + BOOLEAN use_tasklet; + UCHAR radarDeclared; + BOOLEAN SymRoundFromCfg; + BOOLEAN SymRoundCfgValid; + ULONG idle_time; + ULONG busy_time; + UCHAR ch_busy; + CHAR ch_busy_countdown; + UCHAR busy_channel; + UCHAR ch_busy_idle_ratio; + BOOLEAN BusyIdleFromCfg; + BOOLEAN BusyIdleCfgValid; + UCHAR print_ch_busy_sta; + ULONG ch_busy_sta[CH_BUSY_SAMPLE]; + ULONG ch_idle_sta[CH_BUSY_SAMPLE]; + UCHAR ch_busy_sta_index; + INT ch_busy_sum; + INT ch_idle_sum; + UCHAR McuRadarDebug; + USHORT McuRadarTick; + ULONG RadarTimeStampLow; + UCHAR EnabledChMask; /* Bit-wise mask for enabled DFS channels */ + BOOLEAN bAdjustDfsAgc; + pNewDFSTable pDFSTable; + DFS_PROGRAM_PARAM DfsProgramParam; + DFS_SW_DETECT_PARAM DfsSwParam; +#ifdef DFS_ATP_SUPPORT + BOOLEAN atp_radar_detect; + BOOLEAN atp_set_ht_bw; + BOOLEAN atp_set_vht_bw; + BOOLEAN atp_set_channel_ready; +#endif /* DFS_ATP_SUPPORT */ +} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT; + +typedef struct _NewDFSProgParam +{ + UCHAR channel; + UCHAR mode; /* reg 0x10, Detection Mode[2:0]*/ + USHORT avgLen; /* reg 0x11~0x12, M[7:0] & M[8]*/ + USHORT ELow; /* reg 0x13~0x14, Energy Low[7:0] & Energy Low[11:8]*/ + USHORT EHigh; /* reg 0x15~0x16, Energy High[7:0] & Energy High[11:8]*/ + USHORT WLow; /* reg 0x28~0x29, Width Low[7:0] & Width Low[11:8]*/ + USHORT WHigh; /* reg 0x2a~0x2b, Width High[7:0] & Width High[11:8]*/ + UCHAR EpsilonW; /* reg 0x2c, Width Delta[7:0], (Width Measurement Uncertainty) */ + ULONG TLow; /* reg 0x17~0x1a, Period Low[7:0] & Period Low[15:8] & Period Low[23:16] & Period Low[31:24]*/ + ULONG THigh; /* reg 0x1b~0x1e, Period High[7:0] & Period High[15:8] & Period High[23:16] & Period High[31:24]*/ + UCHAR EpsilonT; /* reg 0x27, Period Delt[7:0], (Period Measurement Uncertainty) */ + ULONG BLow; /* reg 0x1f~0x22, Burst Low[7:0] & Burst Low[15:8] & Burst Low[23:16] & Burst Low[31:24]*/ + ULONG BHigh; /* reg 0x23~0x26, Burst High[7:0] & Burst High[15:8] & Burst High[23:16] & Burst High[31:24] */ +}NewDFSProgParam, *pNewDFSProgParam; + +#ifdef CONFIG_AP_SUPPORT +VOID NewRadarDetectionStart( + IN PRTMP_ADAPTER pAd); + +VOID NewRadarDetectionStop( + IN PRTMP_ADAPTER pAd); + +void modify_table1( + IN PRTMP_ADAPTER pAd, + IN ULONG idx, + IN ULONG value); + +void modify_table2( + IN PRTMP_ADAPTER pAd, + IN ULONG idx, + IN ULONG value); + +void schedule_dfs_task( + IN PRTMP_ADAPTER pAd); + +int SWRadarCheck( + IN PRTMP_ADAPTER pAd, USHORT id); + +VOID NewRadarDetectionProgram( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFSTable); + +BOOLEAN DfsSwCheckOnHwDetection( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFSTable, + IN UINT8 DfsChannel, + IN ULONG RadarPeriod, + IN ULONG RadarWidth); + +INT Show_BlockCh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RadarDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ResetRadarHwDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DfsSwDisable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DfsEnvtDropAdjTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RadarStart_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RadarStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DFS_ATP_SUPPORT +INT Set_DfsAtpStart_Proc(IN PRTMP_ADAPTER , IN PSTRING ); +INT Set_DfsAtpReset_Proc(IN PRTMP_ADAPTER , IN PSTRING ); +INT Set_DfsAtpReport_Proc(IN PRTMP_ADAPTER , IN PSTRING ); +#endif + +INT Set_RadarSetTbl1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RadarSetTbl2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PollTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PrintBusyIdle_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BusyIdleRatio_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DfsRssiHigh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DfsRssiLow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +void dfs_tasklet(unsigned long data); + +VOID DFSInit( + IN PRTMP_ADAPTER pAd); + +VOID ApRadarDetectPeriodic( + IN PRTMP_ADAPTER pAd); + +#ifdef RTMP_MAC_PCI +VOID NewTimerCB_Radar( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_MAC_PCI */ + + +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#endif /*_DFS_H__*/ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11_base.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11_base.h new file mode 100644 index 000000000..2049463eb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11_base.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * 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: + dot11_base.h + + Abstract: + Defined IE/frame structures of 802.11 base line + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + + +#ifndef _DOT11_BASE_H_ +#define _DOT11_BASE_H_ + +#include "rtmp_type.h" + + +/* value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header */ +#define FC_TYPE_MGMT 0 +#define FC_TYPE_CNTL 1 +#define FC_TYPE_DATA 2 +#define FC_TYPE_RSVED 3 + +/* value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ +#define SUBTYPE_ASSOC_REQ 0 +#define SUBTYPE_ASSOC_RSP 1 +#define SUBTYPE_REASSOC_REQ 2 +#define SUBTYPE_REASSOC_RSP 3 +#define SUBTYPE_PROBE_REQ 4 +#define SUBTYPE_PROBE_RSP 5 +#define SUBTYPE_TIMING_ADV 6 +#define SUBTYPE_BEACON 8 +#define SUBTYPE_ATIM 9 +#define SUBTYPE_DISASSOC 10 +#define SUBTYPE_AUTH 11 +#define SUBTYPE_DEAUTH 12 +#define SUBTYPE_ACTION 13 +#define SUBTYPE_ACTION_NO_ACK 14 + +/* value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ +#define SUBTYPE_VHT_NDPA 5 +#define SUBTYPE_WRAPPER 7 +#define SUBTYPE_BLOCK_ACK_REQ 8 +#define SUBTYPE_BLOCK_ACK 9 +#define SUBTYPE_PS_POLL 10 +#define SUBTYPE_RTS 11 +#define SUBTYPE_CTS 12 +#define SUBTYPE_ACK 13 +#define SUBTYPE_CFEND 14 +#define SUBTYPE_CFEND_CFACK 15 + +/* value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ +#define SUBTYPE_DATA 0 +#define SUBTYPE_DATA_CFACK 1 +#define SUBTYPE_DATA_CFPOLL 2 +#define SUBTYPE_DATA_CFACK_CFPOLL 3 +#define SUBTYPE_DATA_NULL 4 +#define SUBTYPE_CFACK 5 +#define SUBTYPE_CFPOLL 6 +#define SUBTYPE_CFACK_CFPOLL 7 +#define SUBTYPE_QDATA 8 +#define SUBTYPE_QDATA_CFACK 9 +#define SUBTYPE_QDATA_CFPOLL 10 +#define SUBTYPE_QDATA_CFACK_CFPOLL 11 +#define SUBTYPE_QOS_NULL 12 +#define SUBTYPE_QOS_CFACK 13 +#define SUBTYPE_QOS_CFPOLL 14 +#define SUBTYPE_QOS_CFACK_CFPOLL 15 + +/* 2-byte Frame control field */ +typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + UINT16 Order:1; /* Strict order expected */ + UINT16 Wep:1; /* Wep data */ + UINT16 MoreData:1; /* More data bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 SubType:4; /* MSDU subtype */ + UINT16 Type:2; /* MSDU type */ + UINT16 Ver:2; /* Protocol version */ +#else + UINT16 Ver:2; /* Protocol version */ + UINT16 Type:2; /* MSDU type, refer to FC_TYPE_XX */ + UINT16 SubType:4; /* MSDU subtype, refer to SUBTYPE_XXX */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 MoreData:1; /* More data bit */ + UINT16 Wep:1; /* Wep data */ + UINT16 Order:1; /* Strict order expected */ +#endif /* !RT_BIG_ENDIAN */ +} FRAME_CONTROL, *PFRAME_CONTROL; + + +typedef struct GNU_PACKED _HEADER_802_11 { + FRAME_CONTROL FC; + UINT16 Duration; + UCHAR Addr1[6]; + UCHAR Addr2[6]; + UCHAR Addr3[6]; +#ifdef RT_BIG_ENDIAN + UINT16 Sequence:12; + UINT16 Frag:4; +#else + UINT16 Frag:4; + UINT16 Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Octet[0]; +}HEADER_802_11, *PHEADER_802_11; + +#endif /* _DOT11_BASE_H_ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11ac_vht.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11ac_vht.h new file mode 100644 index 000000000..83b03e3fd --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11ac_vht.h @@ -0,0 +1,665 @@ +/**************************************************************************** + * 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: + dot11ac_vht.h + + Abstract: + Defined IE/frame structures of 802.11ac (D1.2). + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Shiang Tu 01-11-2012 created for 11ac + */ + +#ifdef DOT11_VHT_AC + + +#ifndef __DOT11AC_VHT_H +#define __DOT11AC_VHT_H + +#include "rtmp_type.h" +#include "dot11_base.h" + +#define IE_VHT_CAP 191 +#define IE_VHT_OP 192 +#define IE_EXT_BSS_LOAD 193 +#define IE_WIDE_BW_CH_SWITCH 194 +#define IE_VHT_TXPWR_ENV 195 +#define IE_CH_SWITCH_WRAPPER 196 +#define IE_AID 197 +#define IE_QUIET_CHANNEL 198 + + +#define BW_SIGNALING_DISABLE 0 +#define BW_SIGNALING_STATIC 1 +#define BW_SIGNALING_DYNAMIC 2 + +/* + IEEE 802.11AC D3.0 sec 8.4.1.50 + Operating Mode field + + ch_width: Channel width + -> 0: 20MHz + 1: 40MHz + 2: 80MHz + 3: 160 or 80+80MHz + Reserved if Rx Nss subfield is 1 + rx_nss: Rx Nss + If the Rx Nss Type subfield is 0, indicate the max number of SS STA can rx. + If the Rx Nss Type subfield is 1, indicate the max number of SS that the STA can receive as a + beamformee in a SU PPDU using a beamforming steering matrix derived from a VHT + compressed beamforming report with Feedback Type subfield indicating MU in the VHT + Compressed Beamforming frames + -> 0: Nss=1 + 1: Nss=2 + ... + 7: Nss=8 + + rx_nss_type: + -> 0: indicate the rx_nss subfield carries the max number of SS that the STA can receive + 1: indicate the rx_nss subfield carries the max number of SS that the STA can receive + as an SU PPDU using a beamforming steering matrix derived from a VHT compressed + Beamforming frame with the Feedback Type subfield indicating MU in the VHT compressed + Beamforming frames. +*/ +typedef struct GNU_PACKED _OPERATING_MODE{ +#ifdef RT_BIG_ENDIAN + UCHAR rx_nss_type:1; + UCHAR rx_nss:3; + UCHAR rsv2:2; + UCHAR ch_width:2; +#else + UCHAR ch_width:2; + UCHAR rsv2:2; + UCHAR rx_nss:3; + UCHAR rx_nss_type:1; +#endif /* RT_BIG_ENDIAN */ +}OPERATING_MODE; + + +/* + IEEE 802.11AC D3.0 sec 8.4.2.168 + Operating Mode Notification element + + Element ID: 199 (IE_OPERATING_MODE_NOTIFY) + Length: 1 +*/ +typedef struct GNU_PACKED _OPERATING_MODE_NOTIFICATION{ + OPERATING_MODE operating_mode; +}OPERATING_MODE_NOTIFICATION; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.2 + VHT Capabilities Info field + + max_mpdu_len: MAximun MPDU Length + ->Indicate the max MPDU length. + 0: 3895 octets(Max A-MSDU length in HT Cap set to 3839) + 1: 7991 octets(Max A-MSDU length in HT Cap set to 7935) + 2: 11454 octets(Max A-MSDU length in HT Cap set to 7935) + 3: reserved + ch_width: Supported Channel Width Set + ->Indicates the channel widths supported by the STA. + 0: the STA does not support either 160 or 80+80 MHz + 1: the STA support 160 MHz + 2: the STA support 160 MHz and 80 + 80 MHz + 3: reserved + rx_ldpc: Rx LDPC + -> Indicates support of receiving LDPC coded packets + 0: not support + 1: support + sgi_80M: Short GI for 80 MHz + -> Indicates short GI support for the reception of VHT+CBW80 packet + 0: not support + 1: support + sgi_160M: Short GI for 160 and 80 + 80 MHz + ->Indicates rx short GI for VHT+(CBW160 and CBW80+80) packet + 0: not support + 1: support + tx_stbc: Tx STBC + -> Indicates support for tx of at least 2x1 STBC + 0: not support + 1: support + rx_stbc: Rx STBC + -> Indicates support for rx of PPDUs using STBC + 0: not support + 1: support 1SS + 2: support 1SS and 2SS + 3: support 1SS, 2SS and 3SS + 4: support 1SS, 2SS, 3SS and 4SS + 5,6,7: reserved + bfer_cap_su: SU Beamformer Capable + ->Indicates support for operation as a single user beamformer + 0: not support + 1: support + bfee_cap_su: SU Beamformee Capable + -> Indicates support for operation as a single user beamformee + 0: not support + 1: support + cmp_st_num_bfer: Compressed Steering Number of Beamformer Antenna Supported + -> Beamformee's capability indicateing the max number of beamformer + antennas the beamformee can support when sending compressed + beamforming feedback + If SU beamformee capable, set to the max value minus 1. + otehrwise, reserved. + num_snd_dimension: Number of Sounding Dimensions + -> Beamformer's capability indicating the number of antennas used for + beamformed transmissions. + If SU beamformer capable, set to value minus 1. + otehrwise, reserved. + bfer_cap_mu: MU Beamformer Capable + -> Indicates support for operation as an MU beamformer + 0: if not supported or if sent by a non-AP STA + 1: supported + bfee_cap_mu: MU Beamformee Capable + -> Indicates support for operation as an MU beamformer + 0: if not supported or if snet by an AP + 1: supported + vht_txop_ps: VHT TXOP PS + -> Indicates whether or not the AP supports VHT TXOP Power Save Mode or + whether or not the STA is in VHT TXOP Power Save Mode + ->When tx by a VHT AP in the VHT Capabilities element included in Beacon, + ProbeResp, AssocResp, and ReassocResp, frames: + 0: if the VHT AP does not support VHT TXOP PS in the BSS. + 1: if the VHT AP support TXOP PS in the BSS. + ->When tx by a VHT non-AP STA in the VHT Capabilities element included + in AssocReq, ReassocReq and ProbReq frames: + 0: if the VHT STA is not in TXOP Power Save Mode. + 1: if the VHT STA is in TXOP Power Save Mode. + htc_vht_cap: +HTC-VHT Capable + -> Indicates whether or not the STA supports receiving an HT Control + field in the VHT format + 0: if not support + 1: if support + max_ampdu_exp: Maximum A-MPDU Length Exponent + -> Indicates the maximum length of A-MPDU pre-EOF padding that the STA + can receive. + ->The length defined by this field is equal to 2^(13 + max_ampdu_exp) -1 + 0~7 : integer in the range of 0 to 7. + vht_link_adapt: VHT Link Adaptation Capable + -> Indicates whether or not the STA support link adaptation using VHT + variant HT Control field. + -> This field is ignored if the _HTC-VHT Capble field is set to 0. + 0: (No Feedback), if the STA does not provide VHT MFB + 2: (Unsolicited), if the STA provides only unsolicited VHT MFB + 3: (Both), if the STA can provide VHT MFB in response to VHT MRQ + and if the STA provides unsolicited VHT MFB. + 1: reserved + rx_ant_consistency: Rx Antenna Pattern Consistency + ->Indicates the possibility of Rx antenna pattern change + 0: if Rx antenna pattern might change during association + 1: if Rx antenna pattern does not change during association + tx_ant_consistency: Tx Antenna Pattern Consistency + ->Indicates the possibility of Tx antenna pattern change + 0: if Tx antenna pattern might change during association + 1: if Tx antenna pattern does not change during association +*/ +typedef struct GNU_PACKED _VHT_CAP_INFO{ +#ifdef RT_BIG_ENDIAN + UINT32 rsv:2; + UINT32 tx_ant_consistency:1; + UINT32 rx_ant_consistency:1; + UINT32 vht_link_adapt:2; + UINT32 max_ampdu_exp:3; + UINT32 htc_vht_cap:1; + UINT32 vht_txop_ps:1; + UINT32 bfee_cap_mu:1; + UINT32 bfer_cap_mu:1; + UINT32 num_snd_dimension:3; + + UINT32 cmp_st_num_bfer:3; + UINT32 bfee_cap_su:1; + UINT32 bfer_cap_su:1; + UINT32 rx_stbc:3; + + UINT32 tx_stbc:1; + UINT32 sgi_160M:1; + UINT32 sgi_80M:1; + UINT32 rx_ldpc:1; + UINT32 ch_width:2; + UINT32 max_mpdu_len:2; +#else + UINT32 max_mpdu_len:2; /* 0: 3895, 1: 7991, 2: 11454, 3: rsv */ + UINT32 ch_width:2; /* */ + UINT32 rx_ldpc:1; + UINT32 sgi_80M:1; + UINT32 sgi_160M:1; + UINT32 tx_stbc:1; + + UINT32 rx_stbc:3; + UINT32 bfer_cap_su:1; + UINT32 bfee_cap_su:1; + UINT32 cmp_st_num_bfer:3; + + UINT32 num_snd_dimension:3; + UINT32 bfer_cap_mu:1; + UINT32 bfee_cap_mu:1; + UINT32 vht_txop_ps:1; + UINT32 htc_vht_cap:1; + UINT32 max_ampdu_exp:3; + UINT32 vht_link_adapt:2; + UINT32 rx_ant_consistency:1; + UINT32 tx_ant_consistency:1; + UINT32 rsv:2; +#endif /* RT_BIG_ENDIAN */ +}VHT_CAP_INFO; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.3 + Rx MCS Map and Tx MCS map, figure 8-401bt + + mcs_ss1: Max MCS for 1SS + mcs_ss2: Max MCS for 2SS + mcs_ss3: Max MCS for 3SS + mcs_ss4: Max MCS for 4SS + mcs_ss5: Max MCS for 5SS + mcs_ss6: Max MCS for 6SS + mcs_ss7: Max MCS for 7SS + mcs_ss8: Max MCS for 8SS + + The 2-bit MAx MCS for n SS field for each number of spatial streams n = 1~8 + is encoded as following: + 0: indicates support for MCS 0~7 + 1: indicates support for MCS 0~8 + 2: indicates support for MCS 0~9 + 3: indicates that n spatial streams is not supported. + Note: some MCSs are not be valid for particular bandwidth and number of + spatial stream combinations. +*/ +#define VHT_MCS_CAP_7 0 +#define VHT_MCS_CAP_8 1 +#define VHT_MCS_CAP_9 2 +#define VHT_MCS_CAP_NA 3 + +typedef struct GNU_PACKED _VHT_MCS_MAP{ +#ifdef RT_BIG_ENDIAN + UINT16 mcs_ss8:2; + UINT16 mcs_ss7:2; + UINT16 mcs_ss6:2; + UINT16 mcs_ss5:2; + UINT16 mcs_ss4:2; + UINT16 mcs_ss3:2; + UINT16 mcs_ss2:2; + UINT16 mcs_ss1:2; +#else + UINT16 mcs_ss1:2; + UINT16 mcs_ss2:2; + UINT16 mcs_ss3:2; + UINT16 mcs_ss4:2; + UINT16 mcs_ss5:2; + UINT16 mcs_ss6:2; + UINT16 mcs_ss7:2; + UINT16 mcs_ss8:2; +#endif /* RT_BIG_ENDIAN */ +}VHT_MCS_MAP; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.3 + VHT Supported MCS Set field, figure 8-401bs + + rx_mcs_map: Rx MCS Map + -> Indicates the maximum MCS that can be received for each number of + spatial streams + See "VHT_MCS_MAP" + rx_high_rate: Rx Highest Supported Data Rate + -> Indicates the maximum data rate that the STA can receive + -> In unit of 1Mb/s where 1 represents 1Mb/s, and incrementing in steps + of 1 Mb/s. + -> If the maximum data rate expressed in Mb/s is not an integer, then + the value is rounded up to the next integer. + tx_mcs_map: Tx MCS Map + tx_high_rate: Tx Highest Supported Data Rate + -> Indicates the maximum data rate that the STA will transmit + -> In unit of 1Mb/s where 1 represents 1Mb/s, and incrementing in steps + of 1 Mb/s. + -> If the maximum data rate expressed in Mb/s is not an integer, then + the value is rounded up to the next integer. +*/ + +// TODO: shiang-6590, check the layout of this data structure!!!! +typedef struct GNU_PACKED _VHT_MCS_SET{ +#ifdef RT_BIG_ENDIAN + UINT16 rsv2:3; + UINT16 tx_high_rate:13; + struct _VHT_MCS_MAP tx_mcs_map; + UINT16 rsv:3; + UINT16 rx_high_rate:13; + struct _VHT_MCS_MAP rx_mcs_map; +#else + struct _VHT_MCS_MAP rx_mcs_map; + UINT16 rx_high_rate:13; + UINT16 rsv:3; + struct _VHT_MCS_MAP tx_mcs_map; + UINT16 tx_high_rate:13; + UINT16 rsv2:3; +#endif /* RT_BIG_ENDIAN */ +}VHT_MCS_SET; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.1 + VHT Capabilities Element structure + + eid: Element ID + 191 (IE_VHT_CAP) + len: Length + 12 + vht_cap: VHT Capabilities Info + ->contains a numner of fields that are used to advertise VHT capabilities + of a VHT STA + mcs_set: VHT supported MCS Set + ->Used to convey the combinations of MCSs and spatial streams a STA + supports for both reception and transmission. +*/ +typedef struct GNU_PACKED _VHT_CAP_IE{ + VHT_CAP_INFO vht_cap; + VHT_MCS_SET mcs_set; +}VHT_CAP_IE; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.161 + VHT Operation Information field, figure 8-401bv + + The operation of VHT STAs in the BSS is controlled by the HT Operation + element and the VHT Operation element. + + ch_width: Channel Width + -> This field, together with the HT Operation element STA Channel Width + field, defines the BSS operating channel width. + 0: for 20MHz or 40MHz operating channel width + 1: for 80MHz operating channel width + 2: for 160MHz operating channel width + 3: for 80+80MHz operating channel width + 4~255: reserved + center_freq_1: Channel Center Frequency Segment 1 + -> Defines the channel center frequency for an 80 and 160MHz VHT BSS + and the segment 1 channel center frequency for an 80+90MHz VHT BSS. + -> For 80MHZ or 160MHz operating channel width, indicates the channel + center frequency index for the 80MHz or 160MHz channel on which the + VHT BSS operates. + ->For 80+80MHz operating channel width, indicates the channel center + frequency index for the 80MHz channel of frequency segment 1 on + which the VHT BSS operates. + ->Set 0 for 20MHz or 40MHz operating channel width. + + center_freq_2: Channel Center Frequency Segment 2 + -> Defines the seg 2 channel center frequency for an 80+80MHz VHT BSS + ->For a 80+80MHz operating channel width, indicates the channel center + frequency index of the 80MHz channel of frequency segment 2 on + which the VHT BSS operates. Reserved otherwise. +*/ +typedef struct GNU_PACKED _VHT_OP_INFO{ + UINT8 ch_width; + UINT8 center_freq_1; + UINT8 center_freq_2; +}VHT_OP_INFO; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.161 + VHT Operation element, figure 8-401bu + + The operation of VHT STAs in the BSS is controlled by the HT Operation + element and the VHT Operation element. + + eid: Element ID + 192 (IE_VHT_OP) + len: Length + 5 + vht_op_info: VHT Operation Information + basic_mcs_set: VHT Basic MCS Set +*/ +typedef struct GNU_PACKED _VHT_OP_IE{ + VHT_OP_INFO vht_op_info; + VHT_MCS_MAP basic_mcs_set; +}VHT_OP_IE; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.163 + Wide Bandwidth Channel Switch element, figure 8-401bx + + included in the Channel Switch Announcement frames. + + new_ch_width: New STA Channel Width + center_freq_1: New Channel Center Frequency Segment 1 + center_freq_2: New Channel Center Frequency Segment 2 + + The definition of upper subfields is the same as "VHT_OP_INFO" +*/ +typedef struct GNU_PACKED _WIDE_BW_CH_SWITCH_ELEMENT{ + UINT8 new_ch_width; + UINT8 center_freq_1; + UINT8 center_freq_2; +}WIDE_BW_CH_SWITCH_ELEMENT; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.164 + VHT Transmit Power Envelope element +*/ +typedef struct GNU_PACKED _CH_SEG_PAIR{ + UINT8 ch_center_freq; + UINT8 seg_ch_width; +}CH_SEG_PAIR; + + +/* + max_tx_pwr_cnt: + 0: Local Maximum Transmit Power For 20 MHz. + 1: Local Maximum Transmit Power For 20, 40MHz + 2: Local Maximum Transmit Power For 20, 40, 80MHz + 3: Local Maximum Transmit Power For 20, 40, 80, 160/80+80MHz + 4~7: rsv + + max_tx_pwr_interpretation: + 0: EIRP + 1~7: rsv +*/ +#define TX_PWR_INTERPRET_EIRP 0 +typedef struct GNU_PACKED _VHT_TX_PWR_INFO_{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv6:2; + UINT8 max_tx_pwr_interpretation:3; + UINT8 max_tx_pwr_cnt: 3; +#else + UINT8 max_tx_pwr_cnt: 3; + UINT8 max_tx_pwr_interpretation:3; + UINT8 rsv6:2; +#endif +}VHT_TX_PWR_INFO; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.164 + VHT Transmit Power Envelope element + + max_txpwr: Maximum Transmit Power + -> Define the maximum transmit power limit of the tx bandwidth defined + by the VHT Transmit Power Envelop element. The Maximum Transmit + Power field is a 8 bit 2's complement signed integer in the range of + -64 dBm to 63.5 dBm with a 0.5 dB step. + + NOTE: The following two subfields may repeated as needed. + center_freq_1: Channel Center Frequency Segment + ch_seg_width: Segment Channel Width +*/ +typedef struct GNU_PACKED _VHT_TXPWR_ENV_IE{ + VHT_TX_PWR_INFO tx_pwr_info; + UINT8 tx_pwr_bw[4]; +}VHT_TXPWR_ENV_IE; + + +typedef struct GNU_PACKED _VHT_CONTROL{ +#ifdef RT_BIG_ENDIAN + UINT32 RDG:1; + UINT32 ACConstraint:1; + UINT32 unso_mfb:1; + UINT32 fb_tx_type:1; + UINT32 coding:1; + UINT32 gid_h:3; + UINT32 mfb_snr:6; + UINT32 mfb_bw:2; + UINT32 mfb_mcs:4; + UINT32 mfb_n_sts:3; + UINT32 mfsi_gidl:3; + UINT32 stbc_ind:1; + UINT32 comp_msi:2; + UINT32 mrq:1; + UINT32 rsv:1; + UINT32 vht:1; +#else + UINT32 vht:1; + UINT32 rsv:1; + UINT32 mrq:1; + UINT32 comp_msi:2; + UINT32 stbc_ind:1; + UINT32 mfsi_gidl:3; + UINT32 mfb_n_sts:3; + UINT32 mfb_mcs:4; + UINT32 mfb_bw:2; + UINT32 mfb_snr:6; + UINT32 gid_h:3; + UINT32 coding:1; + UINT32 fb_tx_type:1; + UINT32 unso_mfb:1; + UINT32 ACConstraint:1; + UINT32 RDG:1; +#endif +}VHT_CONTROL; + + +/* + 802.11 AC Draft3.1 - Section 8.3.1.19, Figure 8-29j + + token_num: Sounding Dialog Token Number + Contains a value selected by the beamformer to identify the VHT NDP + Announcment frame. +*/ +typedef struct GNU_PACKED _SNDING_DIALOG_TOKEN { +#ifdef RT_BIG_ENDIAN + UINT8 token_num:6; + UINT8 rsv:2; +#else + UINT8 rsv:2; + UINT8 token_num:6; +#endif /* RT_BIG_ENDIAN */ +}SNDING_DIALOG_TOKEN; + + +/* + 802.11 AC Draft3.1 - Section 8.3.1.19, Figure 8-29k + + aid12: AID12 + the 12 least significiant bits of the AID of a STA expected to + process the following VHT NDP and prepare the sounding + feedback. Equal to 0 if the STA is the AP, mesh STA or STA + that is a member of an IBSS + fb_type: Feedback Type + Indicates the type of feedback requested + 0: SU, 1: MU + nc_idx: Nc_Index + If the fb_type field indicates MU, then Nc Index indicates the + number of columns, Nc, in the compressed Beamforming + Feedback Matrix subfield minus one: + Set to 0 to request Nc=1, + Set to 1 to request Nc=2, + ... + Set to 7 to request Nc=8, + Reserved if the Feedback Type Field indicates SU. +*/ +typedef enum _SNDING_FB_TYPE{ + SNDING_FB_SU = 0, + SNDING_FB_MU = 1, +}SNDING_FB_TYPE; + +typedef struct GNU_PACKED _SNDING_STA_INFO { +#ifdef RT_BIG_ENDIAN + UINT16 nc_idx:3; + UINT16 fb_type:1; + UINT16 aid12:12; +#else + UINT16 aid12:12; + UINT16 fb_type:1; + UINT16 nc_idx:3; +#endif /* RT_BIG_ENDIAN */ +}SNDING_STA_INFO; + + +/* + 802.11 AC Draft3.1 - Section 8.3.1.19, Figure 8-29i + + VHT NDP Announcment frame format + + fc: Frame Control + + duration: Duration + + ra: RA + If the VHT NDPA frame contains only one STA Info field + => the RA field is set to the address of the STA + identified by the AID in the STA info field. + If the VHT NDPA frame contains more than one STA Info field, + => the RA field is set to the broadcast address. + ta: TA + The address of the STA transmitting the VHT NDPA frame. + + token: Sounding Dialog Token, refer to "SNDING_DIALOG_TOKEN" + + sta_info: STA Info 1, ..., STA Info n, refer to "SNDING_STA_INFO" + The VHT NDPA frame contains at least one STA Info field. + +*/ +typedef struct GNU_PACKED _VHT_NDPA_FRAME { + FRAME_CONTROL fc; + USHORT duration; + UCHAR ra[MAC_ADDR_LEN]; + UCHAR ta[MAC_ADDR_LEN]; + SNDING_DIALOG_TOKEN token; + SNDING_STA_INFO sta_info[1]; +} VHT_NDPA_FRAME; + +typedef struct GNU_PACKED _NDPA_PKT{ + USHORT frm_ctrl; + USHORT duration; + UINT8 ra[MAC_ADDR_LEN]; + UINT8 ta[MAC_ADDR_LEN]; + UINT8 snd_seq; +}DNPA_PKT; + +typedef struct GNU_PACKED _PLCP_SERVICE_FIELD{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv7:1; + UINT8 cbw_in_non_ht:2; + UINT8 dyn_bw:1; + UINT8 rsv03:4; +#else + UINT8 rsv03:4; + UINT8 dyn_bw:1; + UINT8 cbw_in_non_ht:2; + UINT8 rsv7:1; +#endif /* RT_BIG_ENDIAN */ +}PLCP_SERVICE_FIELD; + +#endif /* __DOT11AC_VHT_H */ + +#endif /* DOT11_VHT_AC */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11i_wpa.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11i_wpa.h new file mode 100644 index 000000000..cc9964c05 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11i_wpa.h @@ -0,0 +1,298 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36 Taiyuan St., Jhubei City, + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2008, 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: + dot11i_wpa.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __DOT11I_WPA_H__ +#define __DOT11I_WPA_H__ + +#include "rtmp_type.h" +#include "dot11_base.h" + +/* The length is the EAPoL-Key frame except key data field. + Please refer to 802.11i-2004 ,Figure 43u in p.78 */ +#define MIN_LEN_OF_EAPOL_KEY_MSG 95 + +/* The related length of the EAPOL Key frame */ +#define LEN_KEY_DESC_NONCE 32 +#define LEN_KEY_DESC_IV 16 +#define LEN_KEY_DESC_RSC 8 +#define LEN_KEY_DESC_ID 8 +#define LEN_KEY_DESC_REPLAY 8 +#define LEN_KEY_DESC_MIC 16 + +/* EAP Code Type */ +#define EAP_CODE_REQUEST 1 +#define EAP_CODE_RESPONSE 2 +#define EAP_CODE_SUCCESS 3 +#define EAP_CODE_FAILURE 4 + +/* EAPOL frame Protocol Version */ +#define EAPOL_VER 1 +#define EAPOL_VER2 2 + +/* EAPOL-KEY Descriptor Type */ +#define WPA1_KEY_DESC 0xfe +#define WPA2_KEY_DESC 0x02 +#define OSEN_KEY_DESC 0x00 + + +/* Key Descriptor Version of Key Information */ +#define KEY_DESC_OSEN 0 +#define KEY_DESC_TKIP 1 +#define KEY_DESC_AES 2 +#define KEY_DESC_EXT 3 + +#define IE_WPA 221 +#define IE_RSN 48 + +#define WPA_KDE_TYPE 0xdd + +/*EAP Packet Type */ +#define EAPPacket 0 +#define EAPOLStart 1 +#define EAPOLLogoff 2 +#define EAPOLKey 3 +#define EAPOLASFAlert 4 +#define EAPTtypeMax 5 + +#define PAIRWISEKEY 1 +#define GROUPKEY 0 + +/* RSN IE Length definition */ +#define MAX_LEN_OF_RSNIE 255 +#define MIN_LEN_OF_RSNIE 18 +#define MAX_LEN_GTK 32 +#define MIN_LEN_GTK 5 + +#define LEN_PMK 32 +#define LEN_PMKID 16 +#define LEN_PMK_NAME 16 + +#define LEN_GMK 32 + +#define LEN_PTK_KCK 16 +#define LEN_PTK_KEK 16 +#define LEN_TK 16 /* The length Temporal key. */ +#define LEN_TKIP_MIC 8 /* The length of TX/RX Mic of TKIP */ +#define LEN_TK2 (2 * LEN_TKIP_MIC) +#define LEN_PTK (LEN_PTK_KCK + LEN_PTK_KEK + LEN_TK + LEN_TK2) + +#define LEN_TKIP_PTK LEN_PTK +#define LEN_AES_PTK (LEN_PTK_KCK + LEN_PTK_KEK + LEN_TK) +#define LEN_TKIP_GTK (LEN_TK + LEN_TK2) +#define LEN_AES_GTK LEN_TK +#define LEN_TKIP_TK (LEN_TK + LEN_TK2) +#define LEN_AES_TK LEN_TK + +#define LEN_WEP64 5 +#define LEN_WEP128 13 + +#define OFFSET_OF_PTK_TK (LEN_PTK_KCK + LEN_PTK_KEK) /* The offset of the PTK Temporal key in PTK */ +#define OFFSET_OF_AP_TKIP_TX_MIC (OFFSET_OF_PTK_TK + LEN_TK) +#define OFFSET_OF_AP_TKIP_RX_MIC (OFFSET_OF_AP_TKIP_TX_MIC + LEN_TKIP_MIC) +#define OFFSET_OF_STA_TKIP_RX_MIC (OFFSET_OF_PTK_TK + LEN_TK) +#define OFFSET_OF_STA_TKIP_TX_MIC (OFFSET_OF_AP_TKIP_TX_MIC + LEN_TKIP_MIC) + +#define LEN_KDE_HDR 6 +#define LEN_NONCE 32 +#define LEN_PN 6 +#define LEN_TKIP_IV_HDR 8 +#define LEN_CCMP_HDR 8 +#define LEN_CCMP_MIC 8 +#define LEN_OUI_SUITE 4 +#define LEN_WEP_TSC 3 +#define LEN_WPA_TSC 6 +#define LEN_WEP_IV_HDR 4 +#define LEN_ICV 4 + +/* It's defined in IEEE Std 802.11-2007 Table 8-4 */ +typedef enum _WPA_KDE_ID +{ + KDE_RESV0, + KDE_GTK, + KDE_RESV2, + KDE_MAC_ADDR, + KDE_PMKID, + KDE_SMK, + KDE_NONCE, + KDE_LIFETIME, + KDE_ERROR, +#ifdef DOT11W_PMF_SUPPORT + KDE_IGTK, /* Defined in IEEE 802.11w/D10.0 */ +#endif /* DOT11W_PMF_SUPPORT */ + KDE_RESV_OTHER +} WPA_KDE_ID; + +/* EAPOL Key Information definition within Key descriptor format */ +typedef struct GNU_PACKED _KEY_INFO +{ +#ifdef RT_BIG_ENDIAN + UCHAR KeyAck:1; + UCHAR Install:1; + UCHAR KeyIndex:2; + UCHAR KeyType:1; + UCHAR KeyDescVer:3; + UCHAR Rsvd:3; + UCHAR EKD_DL:1; /* EKD for AP; DL for STA */ + UCHAR Request:1; + UCHAR Error:1; + UCHAR Secure:1; + UCHAR KeyMic:1; +#else + UCHAR KeyMic:1; + UCHAR Secure:1; + UCHAR Error:1; + UCHAR Request:1; + UCHAR EKD_DL:1; /* EKD for AP; DL for STA */ + UCHAR Rsvd:3; + UCHAR KeyDescVer:3; + UCHAR KeyType:1; + UCHAR KeyIndex:2; + UCHAR Install:1; + UCHAR KeyAck:1; +#endif +} KEY_INFO, *PKEY_INFO; + +/* EAPOL Key descriptor format */ +typedef struct GNU_PACKED _KEY_DESCRIPTER +{ + UCHAR Type; + KEY_INFO KeyInfo; + UCHAR KeyLength[2]; + UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; + UCHAR KeyNonce[LEN_KEY_DESC_NONCE]; + UCHAR KeyIv[LEN_KEY_DESC_IV]; + UCHAR KeyRsc[LEN_KEY_DESC_RSC]; + UCHAR KeyId[LEN_KEY_DESC_ID]; + UCHAR KeyMic[LEN_KEY_DESC_MIC]; + UCHAR KeyDataLen[2]; + UCHAR KeyData[0]; +} KEY_DESCRIPTER, *PKEY_DESCRIPTER; + +typedef struct GNU_PACKED _EAPOL_PACKET +{ + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + KEY_DESCRIPTER KeyDesc; +} EAPOL_PACKET, *PEAPOL_PACKET; + +typedef struct GNU_PACKED _KDE_HDR +{ + UCHAR Type; + UCHAR Len; + UCHAR OUI[3]; + UCHAR DataType; + UCHAR octet[0]; +} KDE_HDR, *PKDE_HDR; + +/*802.11i D10 page 83 */ +typedef struct GNU_PACKED _GTK_KDE +{ +#ifndef RT_BIG_ENDIAN + UCHAR Kid:2; + UCHAR tx:1; + UCHAR rsv:5; + UCHAR rsv1; +#else + UCHAR rsv:5; + UCHAR tx:1; + UCHAR Kid:2; + UCHAR rsv1; +#endif + UCHAR GTK[0]; +} GTK_KDE, *PGTK_KDE; + +/* For WPA1 */ +typedef struct GNU_PACKED _RSNIE { + UCHAR oui[4]; + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct GNU_PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE, *PRSNIE; + +/* For WPA2 */ +typedef struct GNU_PACKED _RSNIE2 { + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct GNU_PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE2, *PRSNIE2; + +/* AKM Suite */ +typedef struct GNU_PACKED _RSNIE_AUTH { + USHORT acount; + struct GNU_PACKED { + UCHAR oui[4]; + }auth[1]; +} RSNIE_AUTH,*PRSNIE_AUTH; + +/* PMKID List */ +typedef struct GNU_PACKED _RSNIE_PMKID { + USHORT pcount; + struct GNU_PACKED { + UCHAR list[16]; + }pmkid[1]; +} RSNIE_PMKID,*PRSNIE_PMKID; + +typedef union GNU_PACKED _RSN_CAPABILITIES { + struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Rsvd:8; + USHORT MFPC:1; + USHORT MFPR:1; + USHORT GTKSA_R_Counter:2; + USHORT PTKSA_R_Counter:2; + USHORT No_Pairwise:1; + USHORT PreAuth:1; +#else + USHORT PreAuth:1; + USHORT No_Pairwise:1; + USHORT PTKSA_R_Counter:2; + USHORT GTKSA_R_Counter:2; + USHORT MFPR:1; + USHORT MFPC:1; + USHORT Rsvd:8; +#endif + } field; + USHORT word; +} RSN_CAPABILITIES, *PRSN_CAPABILITIES; + +typedef struct GNU_PACKED _EAP_HDR { + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + UCHAR code; + UCHAR identifier; + UCHAR length[2]; /* including code and identifier, followed by length-2 octets of data */ +} EAP_HDR, *PEAP_HDR; + + +#endif /* __DOT11I_WPA_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11k_rrm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11k_rrm.h new file mode 100644 index 000000000..abd9723d8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11k_rrm.h @@ -0,0 +1,406 @@ +/* + *************************************************************************** + * 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: + +***************************************************************************/ + +#ifndef __DOT11K_RRM_H +#define __DOT11K_RRM_H + +#ifdef DOT11K_RRM_SUPPORT +#include "rtmp_type.h" + +#define RRM_CAP_BIT (1 << 12) /* Bit 12 in Capability information field. */ + +#define RRM_PHY_FHSS 1 +#define RRM_PHY_DSSS 2 +#define RRM_PHY_IRBASEBAND 3 +#define RRM_PHY_OFDM 4 +#define RRM_PHY_HRDSSS 5 +#define RRM_PHY_ERP 6 +#define RRM_PHY_HT 7 + +#define IE_RRM_NEIGHBOR_REP 52 +#define IE_BSS_AVAILABLE_AC 67 +#define IE_BSS_AC_DELAY 68 /* Bss Ac Access Dealy Element, Same as WAPI IE. */ +#define IE_RRM_EN_CAP 70 /* 802.11k. RRM Enable Capability element. */ + +#define RRM_MEASURE_REQ 0 +#define RRM_MEASURE_REP 1 +#define RRM_LNK_MEASURE_REQ 2 +#define RRM_LNK_MEASURE_RSP 3 +#define RRM_NEIGHTBOR_REQ 4 +#define RRM_NEIGHTBOR_RSP 5 + +#define RRM_MEASURE_SUBTYPE_BASIC 0 +#define RRM_MEASURE_SUBTYPE_CCA 1 +#define RRM_MEASURE_SUBTYPE_RPI_HISTOGRAM 2 +#define RRM_MEASURE_SUBTYPE_CH_LOAD 3 +#define RRM_MEASURE_SUBTYPE_NOISE_HISTOGRAM 4 +#define RRM_MEASURE_SUBTYPE_BEACON 5 +#define RRM_MEASURE_SUBTYPE_TX_STREAM 9 + +#define RRM_NEIGHBOR_REQ_SSID_SUB_ID 0 +#define RRM_NEIGHBOR_REQ_VENDOR_SUB_ID 221 + +#define RRM_NEIGHBOR_REP_TSF_INFO_SUB_ID 1 +#define RRM_NEIGHBOR_REP_COUNTRY_STRING_SUB_ID 2 +#define RRM_NEIGHBOR_REP_MEASURE_PILOT_TX_SUB_ID 66 +#define RRM_ENABLE_CAPABILTY_SUB_ID 70 +#define RRM_MULTIPLE_BSSID_SUB_ID 71 +#define RRM_VENDOR_SUB_ID 221 + +#define RRM_BCN_REQ_MODE_PASSIVE 0 +#define RRM_BCN_REQ_MODE_ACTIVE 1 +#define RRM_BCN_REQ_MODE_BCNTAB 2 + +#define RRM_BCN_REQ_SUBID_SSID 0 +#define RRM_BCN_REQ_SUBID_BCN_REP_INFO 1 +#define RRM_BCN_REQ_SUBID_RET_DETAIL 2 +#define RRM_BCN_REQ_SUBID_REQUEST 10 +#define RRM_BCN_REQ_SUBID_AP_CH_REP 51 +#define RRM_BCN_REQ_SUBID_VENDOR 221 + +#define RRM_BCN_REP_SUBID_REPORT_FRAME_BODY 1 +#define RRM_BCN_REP_SUBID_VENDOR 221 + +#define RRM_TX_STREAM_SUBID_TRIGGER_REPORT 1 +#define RRM_TX_STREAM_SUBID_VENDOR 221 + +#ifndef DOT11R_FT_SUPPORT +#define FT_MDID_LEN 2 +#define IE_FT_MDIE 54 + +/* +** MDIE: Mobile Domain IE. +*/ +typedef union GNU_PACKED _FT_CAP_AND_POLICY +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 :6; + UINT8 RsrReqCap:1; + UINT8 FtOverDs:1; +#else + UINT8 FtOverDs:1; + UINT8 RsrReqCap:1; + UINT8 :6; +#endif + } field; + UINT8 word; +} FT_CAP_AND_POLICY, *PFT_CAP_AND_POLICY; + +typedef struct GNU_PACKED _FT_MDIE +{ + UINT8 MdId[FT_MDID_LEN]; + FT_CAP_AND_POLICY FtCapPlc; +} FT_MDIE, *PFT_MDIE; +#endif /* !DOT11R_FT_SUPPORT */ + +typedef struct GNU_PACKED _RRM_SUBFRAME_INFO +{ + UINT8 SubId; + UINT8 Length; + UINT8 Oct[0]; +} RRM_SUBFRAME_INFO, *PRRM_SUBFRAME_INFO; + +typedef struct GNU_PACKED _RRM_BEACON_REQ_INFO +{ + UINT8 RegulatoryClass; + UINT8 ChNumber; + UINT16 RandomInterval; + UINT16 MeasureDuration; + UINT8 MeasureMode; + UINT8 Bssid[MAC_ADDR_LEN]; + UINT8 Option[0]; +} RRM_BEACON_REQ_INFO, *PRRM_BEACON_REQ_INFO; + +typedef union GNU_PACKED _RRM_BEACON_REP_INFO_FIELD +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 ReportFrameType:1; + UINT8 CondensePhyType:7; +#else + UINT8 CondensePhyType:7; + UINT8 ReportFrameType:1; +#endif + } field; + UINT8 word; +} RRM_BEACON_REP_INFO_FIELD, *PRRM_BEACON_REP_INFO_FIELD; + +typedef struct GNU_PACKED _RRM_BEACON_REP_INFO +{ + UINT8 RegulatoryClass; + UINT8 ChNumber; + UINT8 ActualMeasureStartTime[8]; + UINT16 MeasureDuration; + UINT8 RepFrameInfo; + UINT8 RCPI; + UINT8 RSNI; + UINT8 Bssid[MAC_ADDR_LEN]; + UINT8 AnntaId; + UINT32 ParentTSF; + UINT8 Option[0]; +} RRM_BEACON_REP_INFO, *PRRM_BEACON_REP_INFO; + +typedef union GNU_PACKED _RRM_BSSID_INFO +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT32 Reserved:18; + UINT32 FTM:1; + UINT32 VHT:1; + UINT32 HT:1; + UINT32 MobilityDomain:1; + UINT32 ImmediateBA:1; + UINT32 DelayBlockAck:1; + UINT32 RRM:1; + UINT32 APSD:1; + UINT32 Qos:1; + UINT32 SepctrumMng:1; + UINT32 KeyScope:1; + UINT32 Security:1; + UINT32 APReachAble:2; +#else + UINT32 APReachAble:2; + UINT32 Security:1; + UINT32 KeyScope:1; + UINT32 SepctrumMng:1; + UINT32 Qos:1; + UINT32 APSD:1; + UINT32 RRM:1; + UINT32 DelayBlockAck:1; + UINT32 ImmediateBA:1; + UINT32 MobilityDomain:1; + UINT32 HT:1; + UINT32 VHT:1; + UINT32 FTM:1; + UINT32 Reserved:18; +#endif + } field; + UINT32 word; +} RRM_BSSID_INFO, *PRRM_BSSID_INFO; + +typedef struct GNU_PACKED _RRM_NEIGHBOR_REP_INFO +{ + UINT8 Bssid[MAC_ADDR_LEN]; + UINT32 BssidInfo; + UINT8 RegulatoryClass; + UINT8 ChNum; + UINT8 PhyType; + UINT8 Oct[0]; +} RRM_NEIGHBOR_REP_INFO, *RRM_PNEIGHBOR_REP_INFO; + +typedef union GNU_PACKED __RRM_EN_CAP_IE +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT64 :30; + UINT64 AntennaInfoCap:1; + UINT64 BssAvaiableAcmCap:1; + UINT64 BssAvgAccessDelayCap:1; + UINT64 RSNIMeasureCap:1; + UINT64 RCPIMeasureCap:1; + UINT64 NeighReportTSFOffsetCap:1; + UINT64 MeasurePilotTxInfoCap:1; + UINT64 MeasurePilotCap:3; + UINT64 NotOperatingChMaxMeasureDuration:3; + /*UINT64 RRMMibCap:1; */ + UINT64 OperatingChMaxMeasureDuration:3; + UINT64 RRMMibCap:1; + UINT64 APChannelReportCap:1; + UINT64 TriggeredTransmitStreamCap:1; + UINT64 TransmitStreamCap:1; + UINT64 LCIAzimuthCap:1; + UINT64 LCIMeasureCap:1; + UINT64 StatisticMeasureCap:1; + UINT64 NoiseHistogramMeasureCap:1; + UINT64 ChannelLoadMeasureCap:1; + UINT64 FrameMeasureCap:1; + UINT64 BeaconMeasureReportCndCap:1; + UINT64 BeaconTabMeasureCap:1; + UINT64 BeaconActiveMeasureCap:1; + UINT64 BeaconPassiveMeasureCap:1; + UINT64 RepeatMeasureCap:1; + UINT64 ParallelMeasureCap:1; + UINT64 NeighborRepCap:1; + UINT64 LinkMeasureCap:1; +#else + UINT64 LinkMeasureCap:1; + UINT64 NeighborRepCap:1; + UINT64 ParallelMeasureCap:1; + UINT64 RepeatMeasureCap:1; + UINT64 BeaconPassiveMeasureCap:1; + UINT64 BeaconActiveMeasureCap:1; + UINT64 BeaconTabMeasureCap:1; + UINT64 BeaconMeasureReportCndCap:1; + UINT64 FrameMeasureCap:1; + UINT64 ChannelLoadMeasureCap:1; + UINT64 NoiseHistogramMeasureCap:1; + UINT64 StatisticMeasureCap:1; + UINT64 LCIMeasureCap:1; + UINT64 LCIAzimuthCap:1; + UINT64 TransmitStreamCap:1; + UINT64 TriggeredTransmitStreamCap:1; + UINT64 APChannelReportCap:1; + UINT64 RRMMibCap:1; + UINT64 OperatingChMaxMeasureDuration:3; + UINT64 NotOperatingChMaxMeasureDuration:3; + UINT64 MeasurePilotCap:3; + UINT64 MeasurePilotTxInfoCap:1; + UINT64 NeighReportTSFOffsetCap:1; + UINT64 RCPIMeasureCap:1; + UINT64 RSNIMeasureCap:1; + UINT64 BssAvgAccessDelayCap:1; + UINT64 BssAvaiableAcmCap:1; + UINT64 AntennaInfoCap:1; + UINT64 :30; +#endif + } field; + UINT64 word; +} RRM_EN_CAP_IE, *PRRM_EN_CAP_IE; + +typedef union GNU_PACKED _RRM_BSS_AVAILABLE_AC_BITMAP +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT16 :4; + UINT16 AC3:1; + UINT16 AC2:1; + UINT16 AC1:1; + UINT16 AC0:1; + UINT16 UP7:1; + UINT16 UP6:1; + UINT16 UP5:1; + UINT16 UP4:1; + UINT16 UP3:1; + UINT16 UP2:1; + UINT16 UP1:1; + UINT16 UP0:1; +#else + UINT16 UP0:1; + UINT16 UP1:1; + UINT16 UP2:1; + UINT16 UP3:1; + UINT16 UP4:1; + UINT16 UP5:1; + UINT16 UP6:1; + UINT16 UP7:1; + UINT16 AC0:1; + UINT16 AC1:1; + UINT16 AC2:1; + UINT16 AC3:1; + UINT16 :4; +#endif + } field; + UINT16 word; +} RRM_BSS_AVAILABLE_AC_BITMAP, *PRRM_BSS_AVAILABLE_AC_BITMAP; + +typedef struct GNU_PACKED _RRM_BSS_AVAILABLE_AC_INFO +{ + UINT16 AvailableAcBitMap; + UINT8 Oct[0]; +} RRM_BSS_AVAILABLE_AC_INFO, *PRRM_BSS_AVAILABLE_AC_INFO; + +typedef struct GNU_PACKED _RRM_BSS_AC_DELAY_INFO +{ + UINT8 BE_ACDelay; + UINT8 BK_ACDelay; + UINT8 VI_ACDelay; + UINT8 VO_ACDelay; +} RRM_BSS_AC_DELAY_INFO, *PRRM_BSS_AC_DELAY_INFO; + +typedef union GNU_PACKED _RRM_TRANSMIT_MEASURE_TRIGGER_CONDITION +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 :5; + UINT8 Delay:1; + UINT8 Consecutive:1; + UINT8 Average:1; +#else + UINT8 Average:1; + UINT8 Consecutive:1; + UINT8 Delay:1; + UINT8 :5; +#endif + } field; + UINT8 word; +} RRM_TRANSMIT_MEASURE_TRIGGER_CONDITION, *PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION; + +typedef struct GNU_PACKED _RRM_TRANSMIT_MEASURE_DELAY_THRESHOLD +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 DealyMsduCnt:6; + UINT8 DealyMsduRange:2; +#else + UINT8 DealyMsduRange:2; + UINT8 DealyMsduCnt:6; +#endif + } field; + UINT8 word; +} RRM_TRANSMIT_MEASURE_DELAY_THRESHOLD, *PRRM_TRANSMIT_MEASURE_DELAY_THRESHOLD; + +typedef struct GNU_PACKED _RRM_TRANSMIT_MEASURE_TRIGGER_REPORT +{ + UINT8 TriggerCondition; + UINT8 AvrErrorThreshold; + UINT8 ConsecutiveErrorThreshold; + UINT8 DelayThreshold; + UINT8 MeasurementCnt; + UINT8 TriggerTimeout; +} RRM_TRANSMIT_MEASURE_TRIGGER_REPORT, *PRRM_TRANSMIT_MEASURE_TRIGGER_REPORT; + +typedef struct GNU_PACKED _RRM_TID +{ + +} RRM_TID, *PRRM_TID; + +typedef struct GNU_PACKED _RRM_TRANSMIT_MEASURE_INFO +{ + UINT16 RandomInterval; + UINT16 MeasureDuration; + UINT8 PeerStaMac[MAC_ADDR_LEN]; + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 TID:4; + UINT8 Rev:4; +#else + UINT8 Rev:4; + UINT8 TID:4; +#endif + } TIDField; + UINT8 Bin0Range; + UINT8 Oct[0]; +} RRM_TRANSMIT_MEASURE_INFO, *PRRM_TRANSMIT_MEASURE_INFO; + +#endif /* DOT11K_RRM_SUPPORT */ + +#endif /* __DOT11K_RRM_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11n_ht.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11n_ht.h new file mode 100644 index 000000000..9b5534bfa --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11n_ht.h @@ -0,0 +1,353 @@ +/**************************************************************************** + * 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: + dot11n_ht.h + + Abstract: + Defined IE/frame structures of 802.11n + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifdef DOT11_N_SUPPORT + + +#ifndef _DOT11N_HT_H_ +#define _DOT11N_HT_H_ + +#include "rtmp_type.h" +#include "dot11_base.h" + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_CAP_INFO{ +#ifdef RT_BIG_ENDIAN + UINT16 LSIGTxopProSup:1; + UINT16 Forty_Mhz_Intolerant:1; + UINT16 PSMP:1; + UINT16 CCKmodein40:1; + UINT16 AMsduSize:1; + UINT16 DelayedBA:1; + UINT16 RxSTBC:2; + UINT16 TxSTBC:1; + UINT16 ShortGIfor40:1; + UINT16 ShortGIfor20:1; + UINT16 GF:1; + UINT16 MimoPs:2; + UINT16 ChannelWidth:1; + UINT16 ht_rx_ldpc:1; +#else + UINT16 ht_rx_ldpc:1; + UINT16 ChannelWidth:1; + UINT16 MimoPs:2; /* mimo power safe */ + UINT16 GF:1; /* green field */ + UINT16 ShortGIfor20:1; + UINT16 ShortGIfor40:1; /* for40MHz */ + UINT16 TxSTBC:1; /* 0:not supported, 1:if supported */ + UINT16 RxSTBC:2; + UINT16 DelayedBA:1; + UINT16 AMsduSize:1; /* only support as zero */ + UINT16 CCKmodein40:1; + UINT16 PSMP:1; + UINT16 Forty_Mhz_Intolerant:1; + UINT16 LSIGTxopProSup:1; +#endif /* RT_BIG_ENDIAN */ +} HT_CAP_INFO; + + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_CAP_PARM{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv:3;/*momi power safe */ + UINT8 MpduDensity:3; + UINT8 MaxRAmpduFactor:2; +#else + UINT8 MaxRAmpduFactor:2; + UINT8 MpduDensity:3; + UINT8 rsv:3;/*momi power safe */ +#endif /* RT_BIG_ENDIAN */ +} HT_CAP_PARM, *PHT_CAP_PARM; + + +typedef struct GNU_PACKED _HT_MCS_SET_TX_SUBFIELD{ +#ifdef RT_BIG_ENDIAN + UINT8 TxMCSSetDefined:1; + UINT8 TxRxNotEqual:1; + UINT8 TxMaxStream:2; + UINT8 TxUnqualModulation:1; + UINT8 rsv:3; +#else + UINT8 rsv:3; + UINT8 TxUnqualModulation:1; + UINT8 TxMaxStream:2; + UINT8 TxRxNotEqual:1; + UINT8 TxMCSSetDefined:1; +#endif /* RT_BIG_ENDIAN */ +}HT_MCS_SET_TX_SUBFIELD, *PHT_MCS_SET_TX_SUBFIELD; + + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_MCS_SET{ + UINT8 MCSSet[10]; + UINT8 SupRate[2]; /* unit : 1Mbps */ +#ifdef RT_BIG_ENDIAN + UINT8 rsv:3; + UINT8 MpduDensity:1; + UINT8 TxStream:2; + UINT8 TxRxNotEqual:1; + UINT8 TxMCSSetDefined:1; +#else + UINT8 TxMCSSetDefined:1; + UINT8 TxRxNotEqual:1; + UINT8 TxStream:2; + UINT8 MpduDensity:1; + UINT8 rsv:3; +#endif /* RT_BIG_ENDIAN */ + UINT8 rsv3[3]; +} HT_MCS_SET, *PHT_MCS_SET; + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _EXT_HT_CAP_INFO{ +#ifdef RT_BIG_ENDIAN + UINT16 rsv2:4; + UINT16 RDGSupport:1; /*reverse Direction Grant support */ + UINT16 PlusHTC:1; /*+HTC control field support */ + UINT16 MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + UINT16 rsv:5;/*momi power safe */ + UINT16 TranTime:2; + UINT16 Pco:1; +#else + UINT16 Pco:1; + UINT16 TranTime:2; + UINT16 rsv:5;/*momi power safe */ + UINT16 MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + UINT16 PlusHTC:1; /*+HTC control field support */ + UINT16 RDGSupport:1; /*reverse Direction Grant support */ + UINT16 rsv2:4; +#endif /* RT_BIG_ENDIAN */ +} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO; + + +/* HT Explicit Beamforming Feedback Capable */ +#define HT_ExBF_FB_CAP_NONE 0 +#define HT_ExBF_FB_CAP_DELAYED 1 +#define HT_ExBF_FB_CAP_IMMEDIATE 2 +#define HT_ExBF_FB_CAP_BOTH 3 + +/* HT Beamforming field in HT Cap IE */ +typedef struct GNU_PACKED _HT_BF_CAP{ +#ifdef RT_BIG_ENDIAN + UINT32 rsv:3; + UINT32 ChanEstimation:2; + UINT32 CSIRowBFSup:2; + UINT32 ComSteerBFAntSup:2; + UINT32 NoComSteerBFAntSup:2; + UINT32 CSIBFAntSup:2; + UINT32 MinGrouping:2; + UINT32 ExpComBF:2; + UINT32 ExpNoComBF:2; + UINT32 ExpCSIFbk:2; + UINT32 ExpComSteerCapable:1; + UINT32 ExpNoComSteerCapable:1; + UINT32 ExpCSICapable:1; + UINT32 Calibration:2; + UINT32 ImpTxBFCapable:1; + UINT32 TxNDPCapable:1; + UINT32 RxNDPCapable:1; + UINT32 TxSoundCapable:1; + UINT32 RxSoundCapable:1; + UINT32 TxBFRecCapable:1; +#else + UINT32 TxBFRecCapable:1; + UINT32 RxSoundCapable:1; + UINT32 TxSoundCapable:1; + UINT32 RxNDPCapable:1; + UINT32 TxNDPCapable:1; + UINT32 ImpTxBFCapable:1; + UINT32 Calibration:2; + UINT32 ExpCSICapable:1; + UINT32 ExpNoComSteerCapable:1; + UINT32 ExpComSteerCapable:1; + UINT32 ExpCSIFbk:2; + UINT32 ExpNoComBF:2; + UINT32 ExpComBF:2; + UINT32 MinGrouping:2; + UINT32 CSIBFAntSup:2; + UINT32 NoComSteerBFAntSup:2; + UINT32 ComSteerBFAntSup:2; + UINT32 CSIRowBFSup:2; + UINT32 ChanEstimation:2; + UINT32 rsv:3; +#endif /* RT_BIG_ENDIAN */ +} HT_BF_CAP, *PHT_BF_CAP; + +/* HT antenna selection field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_AS_CAP{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv:1; + UINT8 TxSoundPPDU:1; + UINT8 RxASel:1; + UINT8 AntIndFbk:1; + UINT8 ExpCSIFbk:1; + UINT8 AntIndFbkTxASEL:1; + UINT8 ExpCSIFbkTxASEL:1; + UINT8 AntSelect:1; +#else + UINT8 AntSelect:1; + UINT8 ExpCSIFbkTxASEL:1; + UINT8 AntIndFbkTxASEL:1; + UINT8 ExpCSIFbk:1; + UINT8 AntIndFbk:1; + UINT8 RxASel:1; + UINT8 TxSoundPPDU:1; + UINT8 rsv:1; +#endif /* RT_BIG_ENDIAN */ +} HT_AS_CAP, *PHT_AS_CAP; + + +/* Draft 1.0 set IE length 26, but is extensible.. */ +#define SIZE_HT_CAP_IE 26 +/* The structure for HT Capability IE. */ +typedef struct GNU_PACKED _HT_CAPABILITY_IE{ + HT_CAP_INFO HtCapInfo; + HT_CAP_PARM HtCapParm; +/* HT_MCS_SET HtMCSSet; */ + UCHAR MCSSet[16]; + EXT_HT_CAP_INFO ExtHtCapInfo; + HT_BF_CAP TxBFCap; /* beamforming cap. rt2860c not support beamforming. */ + HT_AS_CAP ASCap; /*antenna selection. */ +} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE; + + +/* field in Addtional HT Information IE . */ +typedef struct GNU_PACKED _ADD_HTINFO{ +#ifdef RT_BIG_ENDIAN + UCHAR SerInterGranu:3; + UCHAR S_PSMPSup:1; + UCHAR RifsMode:1; + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; +#else + UCHAR ExtChanOffset:2; + UCHAR RecomWidth:1; + UCHAR RifsMode:1; + UCHAR S_PSMPSup:1; /*Indicate support for scheduled PSMP */ + UCHAR SerInterGranu:3; /*service interval granularity */ +#endif +} ADD_HTINFO, *PADD_HTINFO; + + +typedef struct GNU_PACKED _ADD_HTINFO2{ +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif +} ADD_HTINFO2, *PADD_HTINFO2; + + +/* TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. */ +typedef struct GNU_PACKED _ADD_HTINFO3{ +#ifdef RT_BIG_ENDIAN + USHORT rsv:4; + USHORT PcoPhase:1; + USHORT PcoActive:1; + USHORT LsigTxopProt:1; + USHORT STBCBeacon:1; + USHORT DualCTSProtect:1; + USHORT DualBeacon:1; + USHORT StbcMcs:6; +#else + USHORT StbcMcs:6; + USHORT DualBeacon:1; + USHORT DualCTSProtect:1; + USHORT STBCBeacon:1; + USHORT LsigTxopProt:1; /* L-SIG TXOP protection full support */ + USHORT PcoActive:1; + USHORT PcoPhase:1; + USHORT rsv:4; +#endif /* RT_BIG_ENDIAN */ +} ADD_HTINFO3, *PADD_HTINFO3; + +#define SIZE_ADD_HT_INFO_IE 22 +typedef struct GNU_PACKED _ADD_HT_INFO_IE{ + UCHAR ControlChan; + ADD_HTINFO AddHtInfo; + ADD_HTINFO2 AddHtInfo2; + ADD_HTINFO3 AddHtInfo3; + UCHAR MCSSet[16]; /* Basic MCS set */ +} ADD_HT_INFO_IE, *PADD_HT_INFO_IE; + + +/* 802.11n draft3 related structure definitions. */ +/* 7.3.2.60 */ +#define dot11OBSSScanPassiveDwell 20 /* in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. */ +#define dot11OBSSScanActiveDwell 10 /* in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. */ +#define dot11BSSWidthTriggerScanInterval 300 /* in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. */ +#define dot11OBSSScanPassiveTotalPerChannel 200 /* in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. */ +#define dot11OBSSScanActiveTotalPerChannel 20 /*in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan */ +#define dot11BSSWidthChannelTransactionDelayFactor 5 /* min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maximum */ + /* interval between overlapping BSS scan operations. */ +#define dot11BSSScanActivityThreshold 25 /* in %%, max total time that a STA may be active on the medium during a period of */ + /* (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without */ + /* being obligated to perform OBSS Scan operations. default is 25(== 0.25%) */ + +typedef struct GNU_PACKED _OVERLAP_BSS_SCAN_IE{ + USHORT ScanPassiveDwell; + USHORT ScanActiveDwell; + USHORT TriggerScanInt; /* Trigger scan interval */ + USHORT PassiveTalPerChannel; /* passive total per channel */ + USHORT ActiveTalPerChannel; /* active total per channel */ + USHORT DelayFactor; /* BSS width channel transition delay factor */ + USHORT ScanActThre; /* Scan Activity threshold */ +}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE; + + +/* 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST */ +typedef union GNU_PACKED _BSS_2040_COEXIST_IE{ + struct GNU_PACKED { + #ifdef RT_BIG_ENDIAN + UCHAR rsv:3; + UCHAR ObssScanExempGrant:1; + UCHAR ObssScanExempReq:1; + UCHAR BSS20WidthReq:1; + UCHAR Intolerant40:1; + UCHAR InfoReq:1; + #else + UCHAR InfoReq:1; + UCHAR Intolerant40:1; /* Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. */ + UCHAR BSS20WidthReq:1; /* Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. */ + UCHAR ObssScanExempReq:1; + UCHAR ObssScanExempGrant:1; + UCHAR rsv:3; +#endif /* RT_BIG_ENDIAN */ + } field; + UCHAR word; +} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE; + + +#endif /* _DOT11N_HT_H_ */ +#endif /* DOT11_N_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11r_ft.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11r_ft.h new file mode 100644 index 000000000..9aacec3d7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11r_ft.h @@ -0,0 +1,342 @@ +/**************************************************************************** + * 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: + dot11r_ft.h + + Abstract: + Defined status code, IE and frame structures that FT (802.11rD9.0) needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 12-02-2008 created for 11r soft-AP + */ + + +#ifndef __DOT11R_FT_H +#define __DOT11R_FT_H + +#include "rtmp_type.h" + + +#ifdef DOT11R_FT_SUPPORT +/* + Fast BSS transition auth algorithm in 802.11rD9.0 specification. + All other algorithms are defined in rtmp_def.h +*/ +#define FT_MDID_LEN 2 +#define FT_ROKH_ID_LEN 48 +#define FT_R1KH_ID_LEN 6 +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +#define FT_MIC_LEN 16 +#define FT_NONCE_LEN 32 +#endif + +#ifdef DOT11R_FT_SUPPORT +#define FT_CATEGORY_BSS_TRANSITION 6 +#define FT_ACTION_BT_REQ 1 +#define FT_ACTION_BT_RSP 2 +#define FT_ACTION_BT_CONFIRM 3 +#define FT_ACTION_BT_ACK 4 + +/* Status codes defined in 802.11rD9.0 specification. */ +#define FT_STATUS_CODE_RESERVED 27 +#define FT_STATUS_CODE_R0KH_UNREACHABLE 28 +#define FT_STATUS_CODE_INVALID_FME_COUNT 52 +#define FT_STATUS_CODE_INVALID_PMKID 53 +#define FT_STATUS_CODE_INVALID_MDIE 54 +#define FT_STATUS_CODE_INVALID_FTIE 55 +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +/* Information element ID defined in 802.11rD9.0 specification. */ +#define IE_FT_MDIE 54 +#define IE_FT_FTIE 55 +#define IE_FT_TIMEOUT_INTERVAL 56 +#define IE_FT_RIC_DATA 57 +#define IE_FT_RIC_DESCRIPTOR 75 + + +/* RIC Type */ +#define FT_RIC_TYPE_BA 1 + +/* AKM SUITE */ +#define FT_AKM_SUITE_1X 3 +#define FT_AKM_SUITE_PSK 4 +#endif + +#ifdef DOT11R_FT_SUPPORT +/* +** MDIE: Mobile Domain IE. +*/ +typedef union GNU_PACKED _FT_CAP_AND_POLICY +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 :6; + UINT8 RsrReqCap:1; + UINT8 FtOverDs:1; +#else + UINT8 FtOverDs:1; + UINT8 RsrReqCap:1; + UINT8 :6; +#endif + } field; + UINT8 word; +} FT_CAP_AND_POLICY, *PFT_CAP_AND_POLICY; + +typedef struct GNU_PACKED _FT_MDIE +{ + UINT8 MdId[FT_MDID_LEN]; + FT_CAP_AND_POLICY FtCapPlc; +} FT_MDIE, *PFT_MDIE; +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +typedef union GNU_PACKED _FT_MIC_CTR_FIELD +{ + /* + IECnt: contains the number of IEs + that are included int eht MIC calculation. + */ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT16 IECnt:8; + UINT16 :8; +#else + UINT16 :8; + UINT16 IECnt:8; +#endif + } field; + UINT16 word; +} FT_MIC_CTR_FIELD, *PFT_MIC_CTR_FIELD; + +/* +** FTIE: Fast Transition IE. +*/ +typedef struct GNU_PACKED _FT_FTIE +{ + FT_MIC_CTR_FIELD MICCtr; /* 2 Octects. */ + UINT8 MIC[FT_MIC_LEN]; /* 16 Octects. */ + UINT8 ANonce[FT_NONCE_LEN]; /* 32 Octects. */ + UINT8 SNonce[FT_NONCE_LEN]; /* 32 Octects. */ + UINT8 Option[0]; /* 1:R1KHID, 2:GTK, 3:ROKHId, else:Res */ +} FT_FTIE, *PFT_FTIE; +#endif + +#ifdef DOT11R_FT_SUPPORT +/* Sub-element IDs */ +typedef enum _FT_SUB_ELEMENT_ID +{ + FT_R1KH_ID = 1, + FT_GTK, + FT_R0KH_ID, +#ifdef DOT11W_PMF_SUPPORT + FT_IGTK_ID, +#endif /* DOT11W_PMF_SUPPORT */ + FT_RESERVED_ID +} FT_SUB_ELEMENT_ID, *PFT_SUB_ELEMENT_ID; + +typedef struct GNU_PACKED _FT_OPTION_FIELD +{ + UINT8 SubElementId; + UINT8 Len; + UINT8 Oct[0]; +} FT_OPTION_FIELD, *PFT_OPTION_FIELD; + +/* Sub element frame of FTIE. */ +typedef union GNU_PACKED _FT_GTK_KEY_INFO +{ + struct GNU_PACKED{ +#ifdef RT_BIG_ENDIAN + UINT16 :14; + UINT16 KeyId:2; +#else + UINT16 KeyId:2; + UINT16 :14; +#endif + } field; + UINT16 word; +} FT_GTK_KEY_INFO, *PFT_GTK_KEY_INFO; + +typedef struct GNU_PACKED _FT_GTK_SUB_ELEMENT +{ + FT_GTK_KEY_INFO KeyInfo; /* 2 octects. */ + UINT8 KeyLen; + UINT8 RSC[8]; /* Receive seq counter. */ + UINT8 Key[0]; /* 5 to 32 octects. */ +} FT_GTK_SUB_ELEMENT, *PFT_GTK_SUB_ELEMENT; +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +/* +** Timeout Interval IE. +*/ +typedef enum _FT_TIMEOUT_INTERVAL_TYPE +{ + REASSOC_DEADLINE_INTERVAL = 1, /* TUs */ + KEY_LIFETIME_INTERVAL, /* seconds. */ +#ifdef DOT11W_PMF_SUPPORT + ASSOC_COMEBACK_TIME, /* TUs */ +#endif /* DOT11W_PMF_SUPPORT */ + RESERVED_INTERVAL +} FT_TIMEOUT_INTERVAL_TYPE, *PFT_TIMEOUT_INTERVAL_TYPE; + +typedef struct GNU_PACKED _FT_TIMEOUT_INTERVAL_IE +{ + UINT8 TimeoutIntervalType; + UINT32 TimeoutIntervalValue; +} FT_TIMEOUT_INTERVAL_IE, *PFT_TIMEOUT_INTERVAL_IE; +#endif + +#ifdef DOT11R_FT_SUPPORT +/* ----- Fast BSS Transition Action ----- */ +#define FT_OVER_DS_CATEGORY 0x06 + +typedef struct _FT_OVER_DS_ACTION_REQ_CONFIRM { + + /* must be 6 */ + UCHAR Category; + +#define FT_OVER_DS_ACTION_REQ 0x01 +#define FT_OVER_DS_ACTION_CON 0x03 + /* must be 1 or 3 */ + UCHAR Action; + + /* the STAs MAC address */ + UCHAR STA_Addr[ETH_ALEN]; + + /* the BSSID value of the target AP */ + UCHAR TargetAP_Addr[ETH_ALEN]; + + /* REQ: RSN, Mobility Domain, or Fast BSS Transition element */ + /* CONFIRM: RSN, Mobility Domain, Fast BSS Transition, or RIC element */ + UCHAR InfoElm[0];/*[1024 - 14]; */ +} GNU_PACKED FT_OVER_DS_ACTION_REQ_FONFIRM; + +typedef struct _FT_OVER_DS_ACTION_RSP_ACK { + + /* must be 6 */ + UCHAR Category; + +#define FT_OVER_DS_ACTION_RSP 0x02 +#define FT_OVER_DS_ACTION_ACK 0x04 + /* must be 2 or 4 */ + UCHAR Action; + + /* the STAs MAC address */ + UCHAR STA_Addr[ETH_ALEN]; + + /* the BSSID value of the target AP */ + UCHAR TargetAP_Addr[ETH_ALEN]; + + /* FT_STATUS_CODE_R0KH_UNREACHABLE ~ FT_STATUS_CODE_INVALID_FTIE */ + UINT16 StatusCode; + + /* RSP: RSN, Mobility Domain, or Fast BSS Transition element */ + /* ACK: RSN, Mobility Domain, Fast BSS Transition, Timeout, or RIC element */ + UCHAR InfoElm[0];/*[1024 - 16]; */ +} GNU_PACKED FT_OVER_DS_ACTION_RSP_ACK; + + +/* ----- RIC(Resource Information Container) ----- */ + +/* element ID and element length */ +#define FT_ELM_HDR_LEN 2 + +/* Resource Information Container Data information element */ +typedef struct _FT_ELM_RIC_DATA_INFO { + +#define FT_ELM_ID_RIC_DATA_INFO 57 + UCHAR ElmID; + +#define FT_ELM_LEN_RIC_DATA_INFO 4 + UCHAR ElmLen; + + /* + RDIE: RIC Data information Element + An arbitrary 8-bit value, chosen by the resource requestor to + uniquely identify the RDIE within the RIC. + */ + UCHAR RDIE_Identifier; + + /* + Resource Descriptor Count + Number of alternative Resource Descriptors that follow this RDIE. + */ + UCHAR RD_Count; + + /* the result of the request */ + /* FT_STATUS_CODE_R0KH_UNREACHABLE ~ FT_STATUS_CODE_INVALID_FTIE */ + UINT16 StatusCode; + +} GNU_PACKED FT_ELM_RIC_DATA_INFO; + +/* Resource Information Container descriptor information element */ +#define FT_ELM_RIC_DESCP_INFO_LEN (FT_ELM_HDR_LEN+7) + +typedef struct GNU_PACKED _FT_RIC_DESCP_BLOCK_ACK { + UINT16 BaParm; /* Block Ack Parameter Set */ + UINT16 TimeOutValue; /* Block Ack Timeout Value */ + UINT16 BaStartSeq; /* Block Ack Starting Sequence Control */ +} FT_RIC_DESCP_BLOCK_ACK; + +typedef struct GNU_PACKED _FT_ELM_RIC_DESCP_INFO { +#define FT_ELM_ID_RIC_DESCP_INFO 75 + UCHAR ElmID; + +#define FT_ELM_LEN_RIC_DESCP_INFO_RSC_BLOCK_ACK 7 + UCHAR ElmLen; + +#define FT_ELM_RIC_DESCP_INFO_RSC_TYPE_BLOCK_ACK 1 + UCHAR ResourceType; + + /* negotiated resources */ + /* + For FT_ELM_RIC_DESCP_INFO_RSC_TYPE_BLOCK_ACK: + Block Ack Parameter Set (2B), + Block Ack Timeout Value (2B), and + Block Ack Starting Sequence Control (2B) + */ + UCHAR Container[6]; + +} FT_ELM_RIC_DESCP_INFO; + +typedef struct GNU_PACKED __FT_ACTION +{ + UINT8 Category; + UINT8 Action; + UINT8 StaMac[MAC_ADDR_LEN]; + UINT8 TargetApAddr[MAC_ADDR_LEN]; + UINT8 Oct[0]; +} FT_ACTION, *PFT_ACTION; + +typedef struct GNU_PACKED __FT_RRB +{ + UINT8 RemoteFrTyp; + UINT8 FTPktType; + UINT16 FTActLen; + UINT8 APAdr[MAC_ADDR_LEN]; + UINT8 Oct[0]; +} FT_RRB, *PFT_RRB; +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* __DOT11R_FT_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11u_interworking.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11u_interworking.h new file mode 100644 index 000000000..0f30a1f0f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11u_interworking.h @@ -0,0 +1,113 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36 Taiyuan St., Jhubei City, + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 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: + dot11u_hotspot.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __DOT11U_HOTSPOT_H__ +#define __DOT11U_HOTSPOT_H__ + +#include "rtmp_type.h" + +/* unit ms */ +#define dot11GASResponseTimeout 5120 +#define dotGASResponseBufferingTime 5120 + + +enum GAS_ACTION_FIELD { + ACTION_GAS_INIT_REQ = 10, + ACTION_GAS_INIT_RSP = 11, + ACTION_GAS_CB_REQ = 12, + ACTION_GAS_CB_RSP = 13, +}; + +typedef struct GNU_PACKED _GAS_FRAME +{ + HEADER_802_11 Hdr; + UCHAR Category; + union { + struct { + UCHAR Action; + UCHAR DialogToken; + /* + * Following are advertisement protocol element, + * query request length, and query request + */ + UCHAR Variable[0]; + } GNU_PACKED GAS_INIT_REQ; + struct { + UCHAR Action; + UCHAR DialogToken; + UINT16 StatusCode; + UINT16 GASComebackDelay; + /* + * Following are advertisement protocol element, + * query response length, and query response(optional) + */ + UCHAR Variable[0]; + } GNU_PACKED GAS_INIT_RSP; + struct { + UCHAR Action; + UCHAR DialogToken; + } GNU_PACKED GAS_CB_REQ; + struct { + UCHAR Action; + UCHAR DialogToken; + UINT16 StatusCode; + UCHAR GASRspFragID; + UINT16 GASComebackDelay; + /* + * Following are advertisment protocol element, + * query response length, and query response(optional) + */ + UCHAR Variable[0]; + } GNU_PACKED GAS_CB_RSP; + }u; +}GAS_FRAME, *PGAS_FRAME; + + +/* Status Code */ +enum DOT11U_STATUS_CODE { + ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED = 59, + UNSPECIFIED_FAILURE = 60, + RESPONSE_NOT_RECEIVED_FROM_SERVER = 61, + TIMEOUT = 62, + QUERY_RESPONSE_TOO_LARGE = 63, + REQUEST_REFUSED_HOME_NETWORK_NOT_SUPPORT = 64, + SERVER_UNREACHABLE = 65, + REQUEST_REFUSED_PERMISSIONS_RECEIVED_FROM_SSPN = 67, + REQUEST_REFUSED_AP_NOT_SUPPORT_UNAUTH_ACCESS = 68, + TRANSMISSION_FAILURE = 79, +}; + +/* Advertismenet Protocol ID definitions */ +enum DOT11U_ADVERTISMENT_PROTOCOL_ID { + ACCESS_NETWORK_QUERY_PROTOCOL = 0, + MIH_INFORMATION_SERVICE = 1, + MIH_COMMAND_AND_EVENT_SERVICES_CAPBILITY_DISCOVERY = 2, + EMERGENCY_ALERT_SYSTEM = 3, + VENDOR_SPECIFIC = 221 +}; + + +#endif /* __DOT11U_HOTSPOT_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11v_wnm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11v_wnm.h new file mode 100644 index 000000000..03db51780 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11v_wnm.h @@ -0,0 +1,102 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36 Taiyuan St., Jhubei City, + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 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: + dot11v_wnm.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __DOT11V_WNM_H__ +#define __DOT11V_WNM_H__ + +enum WNM_ACTION_FIELD { + EVENT_REQUEST, + EVENT_REPORT, + DIAGNOSTIC_REQ, + DIAGNOSTIC_REPORT, + LOCATION_CONF_REQ, + LOCATION_CONF_RSP, + BSS_TRANSITION_QUERY, + BSS_TRANSITION_REQ, + BSS_TRANSITION_RSP, + FMS_REQ, + FMS_RSP, + COLLOCATED_INTERFERENCE_REQ, + COLLOCATED_INTERFERENCE_REPORT, + TFS_REQ, + TFS_RSP, + TFS_NOTIFY, + WNM_SLEEP_MODE_REQ, + WNM_SLEEP_MODE_RSP, + TIM_BROADCAST_REQ, + TIM_BROADCAST_RSP, + QOS_TRAFFIC_CAPABILITY_UPDATE, + CHANNEL_USAGE_REQ, + CHANNEL_USAGE_RSP, + DMS_REQ, + DMS_RSP, + TIMING_MEASUREMENT_REQ, + WNM_NOTIFICATION_REQ, + WNM_NOTIFICATION_RSP, +}; + +typedef struct GNU_PACKED _WNM_FRAME +{ + HEADER_802_11 Hdr; + UCHAR Category; + union { + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED BTM_QUERY; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED BTM_REQ; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED BTM_RSP; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Type; + UCHAR Variable[0]; + } GNU_PACKED WNM_NOTIFY_REQ; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR RespStatus; + UCHAR Variable[0]; + } GNU_PACKED WNM_NOTIFY_RSP; + }u; +} WNM_FRAME, *PWNM_FRAME; + +void PeerWNMAction(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#endif /* __DOT11V_WNM_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11w_pmf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11w_pmf.h new file mode 100644 index 000000000..e776dadc5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11w_pmf.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * 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: + dot11w_pmf.h + + Abstract: + Defined status code, IE and frame structures that PMF (802.11w) needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Albert Yang 4-02-2009 created for IEEE802.11W PMF + */ + +#ifndef __DOT11W_PMF_H +#define __DOT11W_PMF_H + +#ifdef DOT11W_PMF_SUPPORT + +#include "rtmp_type.h" + + +#define LEN_PMF_MMIE 16 +#define PMF_CIPHER_SUITE_LEN 4 +#define LEN_PMF_BIP_AAD_HDR 20 +#define LEN_PMF_BIP_MIC 8 +#define LEN_PMF_IGTK_KDE 24 + +/* PMF Action filed value */ +#define PMF_ACTION_QA_QUERY_REQ 0 +#define PMF_ACTION_QA_QUERY_RESP 1 + +/* Information element ID defined in 802.11w specification. */ +#define IE_PMF_MMIE 76 + +/* The definition in IEEE 802.11w - Table 7-32 Cipher suite selectors */ +extern UCHAR OUI_PMF_BIP_CIPHER[]; + +/* The definition in IEEE 802.11w - Table 7-34 AKM suite selectors */ +extern UCHAR OUI_PMF_8021X_AKM[]; +extern UCHAR OUI_PMF_PSK_AKM[]; + +/* The Key ID filed */ +typedef union GNU_PACKED _PMF_IGTK_KEY_ID +{ + struct GNU_PACKED{ +#ifdef RT_BIG_ENDIAN + UINT16 :4; + UINT16 KeyId:12; +#else + UINT16 KeyId:12; + UINT16 :4; +#endif + } field; + UINT16 word; +} PMF_IGTK_KEY_ID, *PPMF_IGTK_KEY_ID; + +/* The SubIE of Fast BSS transition information element */ +typedef struct GNU_PACKED _FT_IGTK_SUB_ELEMENT +{ + UINT8 KeyID[2]; /* indicates the value of the BIP key ID */ + UINT8 IPN[6]; /* indicates the receive sequence counter for the IGTK being installed */ + UINT8 KeyLen; /* the length of IGTK in octets */ + UINT8 Key[24]; /* The length of the resulting AES-Keywrapped IGTK in the Key field */ +} FT_IGTK_SUB_ELEMENT, *PFT_IGTK_SUB_ELEMENT; + +/* Management MIC information element */ +typedef struct GNU_PACKED _PMF_MMIE +{ + UINT8 KeyID[2]; /* identifies the IGTK used to compute the MIC */ + UINT8 IPN[6]; /* indicates the receive sequence counter for the IGTK being installed */ + UINT8 MIC[LEN_PMF_BIP_MIC]; /* The length of the resulting AES-Keywrapped IGTK in the Key field */ +} PMF_MMIE, *PPMF_MMIE; + +/* IGTK KDE format */ +typedef struct GNU_PACKED _PMF_IGTK_KDE +{ + UINT8 KeyID[2]; /* identifies the IGTK used to compute the MIC */ + UINT8 IPN[6]; /* indicates the receive sequence counter for the IGTK being installed */ + UINT8 IGTK[0]; /* The length of the IGTK */ +} PMF_IGTK_KDE, *PPMF_IGTK_KDE; + + +/* ===================== + * PMF SA Query Action + * ===================== */ +typedef struct GNU_PACKED _PMF_SA_QUERY_ACTION +{ + UCHAR Category; + UCHAR Action; + + /* a 16-bit non-negative counter value */ + UINT8 TransactionID[2]; +} PMF_SA_QUERY_ACTION, *PPMF_SA_QUERY_ACTION; + +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /* __DOT11W_PMF_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11z_tdls.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11z_tdls.h new file mode 100644 index 000000000..cc7150cf7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/dot11z_tdls.h @@ -0,0 +1,185 @@ +/**************************************************************************** + * 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: + dot11z_tdls.h + + Abstract: + Defined status code, IE and frame structures that TDLS (802.11zD4.0) needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT +#include "rtmp_type.h" + +#ifndef __DOT11Z_TDLS_H +#define __DOT11Z_TDLS_H + + +/* TDLS definitions in 802.11z D13.0 specification */ +#define PROTO_NAME_TDLS 2 +#define TDLS_AKM_SUITE_1X 5 // +#define TDLS_AKM_SUITE_PSK 7 + +/* TDLS Action frame definition in 802.11z D13.0 specification */ +#define TDLS_ACTION_CODE_SETUP_REQUEST 0 +#define TDLS_ACTION_CODE_SETUP_RESPONSE 1 +#define TDLS_ACTION_CODE_SETUP_CONFIRM 2 +#define TDLS_ACTION_CODE_TEARDOWN 3 +#define TDLS_ACTION_CODE_PEER_TRAFFIC_INDICATION 4 /* for TDLS UAPSD */ +#define TDLS_ACTION_CODE_CHANNEL_SWITCH_REQUEST 5 +#define TDLS_ACTION_CODE_CHANNEL_SWITCH_RESPONSE 6 +#define TDLS_ACTION_CODE_PEER_PSM_REQUEST 7 +#define TDLS_ACTION_CODE_PEER_PSM_RESPONSE 8 +#define TDLS_ACTION_CODE_PEER_TRAFFIC_RESPONSE 9 /* for TDLS UAPSD */ +#define TDLS_ACTION_CODE_DISCOVERY_REQUEST 10 + +/* Status codes defined in 802.11zD13.0 specification. */ +#define TDLS_STATUS_CODE_WAKEUP_SCHEDULE_REJECT_BUT_ALTERNATIVE_SCHEDULE_PROVIDED 2 +#define TDLS_STATUS_CODE_WAKEUP_SCHEDULE_REJECT 3 +#define TDLS_STATUS_CODE_SECURITY_DISABLED 5 +#define TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME 6 +#define TDLS_STATUS_CODE_NOT_IN_SAME_BSS 7 +#define TDLS_STATUS_CODE_INVALID_CONTENTS_OF_RSNIE 72 + +/* Reason codes defined in 802.11zD13.0 specification. */ +#define TDLS_REASON_CODE_TEARDOWN_DUE_TO_PEER_STA_UNREACHABLE 25 +#define TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON 26 + +/* Information element ID defined in 802.11z D13.0 specification. */ +#define IE_TDLS_LINK_IDENTIFIER 101 +#define IE_TDLS_WAKEUP_SCHEDULE 102 +#define IE_TDLS_CHANNEL_SWITCH_TIMING 104 +#define IE_TDLS_PTI_CONTROL 105 +#define IE_TDLS_PU_BUFFER_STATUS 106 + + +#define TDLS_ELM_LEN_LINK_IDENTIFIER 18 +#define TDLS_ELM_LEN_WAKEUP_SCHEDULE 18 +#define TDLS_ELM_LEN_CHANNEL_SWITCH_TIMING 6 +#define TDLS_ELM_LEN_PTI_CONTROL 5 +#define TDLS_ELM_LEN_BUFFER_STATUS 3 + +#define TDLS_KEY_TIMEOUT 3600 /* unit: sec */ + +#define TDLS_LEY_LIFETIME 3600 + +#ifndef DOT11R_FT_SUPPORT +#define FT_MIC_LEN 16 +#define FT_NONCE_LEN 32 + +/* Information element ID defined in 802.11rD9.0 specification. */ +#define IE_FT_MDIE 54 +#define IE_FT_FTIE 55 +#define IE_FT_TIMEOUT_INTERVAL 56 +#define IE_FT_RIC_DATA 57 +#define IE_FT_RIC_DESCRIPTOR 75 + + +/* RIC Type */ +#define FT_RIC_TYPE_BA 1 + +/* AKM SUITE */ +#define FT_AKM_SUITE_1X 3 +#define FT_AKM_SUITE_PSK 4 + +typedef union GNU_PACKED _FT_MIC_CTR_FIELD +{ + /* + IECnt: contains the number of IEs + that are included int eht MIC calculation. + */ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT16 IECnt:8; + UINT16 :8; +#else + UINT16 :8; + UINT16 IECnt:8; +#endif + } field; + UINT16 word; +} FT_MIC_CTR_FIELD, *PFT_MIC_CTR_FIELD; + +/* +** FTIE: Fast Transition IE. +*/ +typedef struct GNU_PACKED _FT_FTIE +{ + FT_MIC_CTR_FIELD MICCtr; /* 2 Octects. */ + UINT8 MIC[FT_MIC_LEN]; /* 16 Octects. */ + UINT8 ANonce[FT_NONCE_LEN]; /* 32 Octects. */ + UINT8 SNonce[FT_NONCE_LEN]; /* 32 Octects. */ + UINT8 Option[0]; /* 1:R1KHID, 2:GTK, 3:ROKHId, else:Res */ +} FT_FTIE, *PFT_FTIE; + +/* +** Timeout Interval IE. +*/ +typedef enum _FT_TIMEOUT_INTERVAL_TYPE +{ + REASSOC_DEADLINE_INTERVAL = 1, /* TUs */ + KEY_LIFETIME_INTERVAL, /* seconds. */ +#ifdef DOT11W_PMF_SUPPORT + ASSOC_COMEBACK_TIME, /* TUs */ +#endif /* DOT11W_PMF_SUPPORT */ + RESERVED_INTERVAL +} FT_TIMEOUT_INTERVAL_TYPE, *PFT_TIMEOUT_INTERVAL_TYPE; + +typedef struct GNU_PACKED _FT_TIMEOUT_INTERVAL_IE +{ + UINT8 TimeoutIntervalType; + UINT32 TimeoutIntervalValue; +} FT_TIMEOUT_INTERVAL_IE, *PFT_TIMEOUT_INTERVAL_IE; +#endif /* DOT11R_FT_SUPPORT */ + +typedef struct GNU_PACKED _TDLS_LINK_IDENT_ELEMENT{ + UCHAR BSSID[MAC_ADDR_LEN]; + UCHAR InitiatorAddr[MAC_ADDR_LEN]; + UCHAR ResponderAddr[MAC_ADDR_LEN]; +}TDLS_LINK_IDENT_ELEMENT, *PTDLS_LINK_IDENT_ELEMENT; + +typedef struct GNU_PACKED _TDLS_CH_SWITCH_TIMING_ELEMENT{ + USHORT ChSwitchTime; + USHORT ChSwitchTimeOut; +}TDLS_CH_SWITCH_TIMING_ELEMENT, *PTDLS_CH_SWITCH_TIMING_ELEMENT; + +typedef struct GNU_PACKED _TDLS_WAKEUP_SCHEDULE_IE +{ + UINT32 Interval; + UINT32 AwakeDuration; + UINT16 IdleCount; +} TDLS_WAKEUP_SCHEDULE_IE, *PTDLS_WAKEUP_SCHEDULE_IE; + +typedef struct GNU_PACKED _TDLS_AP_PHY_DATA_RATE_IE +{ + UINT32 AP_PHY_Data_Rate; +} TDLS_AP_PHY_DATA_RATE_IE, *PTDLS_AP_PHY_DATA_RATE_IE; + +typedef struct GNU_PACKED _TDLS_CHANNEL_SWITCH_TIMING_IE +{ + UINT16 SwitchTime; + UINT16 SwitchTimeout; +} TDLS_CHANNEL_SWITCH_TIMING_IE, *PTDLS_CHANNEL_SWITCH_TIMING_IE; + +#endif /* __DOT11Z_TDLS_H */ + +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/drs_extr.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/drs_extr.h new file mode 100644 index 000000000..ae630bed8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/drs_extr.h @@ -0,0 +1,422 @@ +/**************************************************************************** + * 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 Dynamic Rate Switch Related Structure & Definition + +***************************************************************************/ + +#ifndef __DRS_EXTR_H__ +#define __DRS_EXTR_H__ + +struct _RTMP_ADAPTER; +struct _MAC_TABLE_ENTRY; + + +typedef struct _RTMP_TX_RATE { + UCHAR mode; + UCHAR bw; + UCHAR mcs; + UCHAR nss; + UCHAR sgi; + UCHAR stbc; +}RTMP_TX_RATE; + + +typedef struct _RTMP_RA_LEGACY_TB +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR Mode:3; + UCHAR BW:2; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:2; + UCHAR Mode:3; + UCHAR Rsv2:1; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; +} RTMP_RA_LEGACY_TB; + +#define PTX_RA_LEGACY_ENTRY(pTable, idx) ((RTMP_RA_LEGACY_TB *)&(pTable[(idx+1)*5])) + + +#ifdef NEW_RATE_ADAPT_SUPPORT +typedef struct _RTMP_RA_GRP_TB +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR Mode:3; + UCHAR BW:2; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:2; + UCHAR Mode:3; + UCHAR Rsv2:1; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; + UCHAR downMcs; + UCHAR upMcs3; + UCHAR upMcs2; + UCHAR upMcs1; + UCHAR dataRate; +} RTMP_RA_GRP_TB; + +#define PTX_RA_GRP_ENTRY(pTable, idx) ((RTMP_RA_GRP_TB *)&(pTable[(idx+1)*10])) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#define RATE_TABLE_SIZE(pTable) ((pTable)[0]) /* Byte 0 is number of rate indices */ +#define RATE_TABLE_INIT_INDEX(pTable) ((pTable)[1]) /* Byte 1 is initial rate index */ + + +/* Values of LastSecTxRateChangeAction */ +#define RATE_NO_CHANGE 0 /* No change in rate */ +#define RATE_UP 1 /* Trying higher rate or same rate with different BF */ +#define RATE_DOWN 2 /* Trying lower rate */ + +enum RATE_ADAPT_ALG{ + RATE_ALG_LEGACY = 1, + RATE_ALG_GRP = 2, + RATE_ALG_AGS = 3, + RATE_ALG_MAX_NUM +}; + + +typedef enum { + RAL_OLD_DRS, + RAL_NEW_DRS, + RAL_QUICK_DRS +}RA_LOG_TYPE; + + +extern UCHAR RateSwitchTable11B[]; +extern UCHAR RateSwitchTable11G[]; +extern UCHAR RateSwitchTable11BG[]; + +#ifdef DOT11_N_SUPPORT +extern UCHAR RateSwitchTable11BGN1S[]; +extern UCHAR RateSwitchTable11BGN2S[]; +extern UCHAR RateSwitchTable11BGN2SForABand[]; +extern UCHAR RateSwitchTable11N1S[]; +extern UCHAR RateSwitchTable11N1SForABand[]; +extern UCHAR RateSwitchTable11N2S[]; +extern UCHAR RateSwitchTable11N2SForABand[]; +extern UCHAR RateSwitchTable11BGN3S[]; +extern UCHAR RateSwitchTable11BGN3SForABand[]; + +#ifdef NEW_RATE_ADAPT_SUPPORT +extern UCHAR RateSwitchTableAdapt11N1S[]; +extern UCHAR RateSwitchTableAdapt11N2S[]; +extern UCHAR RateSwitchTableAdapt11N3S[]; + +#define PER_THRD_ADJ 1 + +/* ADAPT_RATE_TABLE - true if pTable is one of the Adaptive Rate Switch tables */ +#ifdef DOT11_VHT_AC +extern UCHAR RateTableVht1S[]; +extern UCHAR RateTableVht1S_MCS9[]; +extern UCHAR RateTableVht2S[]; +extern UCHAR RateTableVht2S_MCS7[]; +extern UCHAR RateTableVht2S_BW20[]; +extern UCHAR RateTableVht2S_BW40[]; +extern UCHAR RateTableVht1S_2G_BW20[]; +extern UCHAR RateTableVht1S_2G_BW40[]; +extern UCHAR RateTableVht2S_2G_BW20[]; +extern UCHAR RateTableVht2S_2G_BW40[]; + +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11N1S ||\ + (pTable)==RateSwitchTableAdapt11N2S ||\ + (pTable)==RateSwitchTableAdapt11N3S ||\ + (pTable)==RateTableVht1S ||\ + (pTable)==RateTableVht1S_MCS9 ||\ + (pTable)==RateTableVht2S || \ + (pTable)==RateTableVht2S_MCS7 || \ + (pTable)==RateTableVht2S_BW20 ||\ + (pTable)==RateTableVht2S_BW40 ||\ + (pTable)==RateTableVht1S_2G_BW20 ||\ + (pTable)==RateTableVht1S_2G_BW40 ||\ + (pTable)==RateTableVht2S_2G_BW20 ||\ + (pTable)==RateTableVht2S_2G_BW40) +#else +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11N1S || \ + (pTable)==RateSwitchTableAdapt11N2S || \ + (pTable)==RateSwitchTableAdapt11N3S) +#endif /* DOT11_VHT_AC */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + +/* FUNCTION */ +VOID MlmeGetSupportedMcs( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR *pTable, + OUT CHAR mcs[]); + +UCHAR MlmeSelectTxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN CHAR mcs[], + IN CHAR Rssi, + IN CHAR RssiOffset); + +VOID MlmeClearTxQuality(struct _MAC_TABLE_ENTRY *pEntry); +VOID MlmeClearAllTxQuality(struct _MAC_TABLE_ENTRY *pEntry); +VOID MlmeDecTxQuality(struct _MAC_TABLE_ENTRY *pEntry, UCHAR rateIndex); +USHORT MlmeGetTxQuality(struct _MAC_TABLE_ENTRY *pEntry, UCHAR rateIndex); +VOID MlmeSetTxQuality( + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex, + IN USHORT txQuality); + + + +VOID MlmeOldRateAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR CurrRateIdx, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN ULONG TrainUp, + IN ULONG TrainDown, + IN ULONG TxErrorRatio); + +VOID MlmeRestoreLastRate( + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeCheckRDG( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID RTMPSetSupportMCS( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR OpMode, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, +#ifdef DOT11_VHT_AC + IN UCHAR vht_cap_len, + IN VHT_CAP_IE *vht_cap, +#endif /* DOT11_VHT_AC */ + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +#ifdef NEW_RATE_ADAPT_SUPPORT +VOID TriggerQuickInitMCSRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UINT32 CheckInterval); + +BOOLEAN QuickInitMCSRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UINT16 PacketSucc, + IN UINT16 PacketErro); + +VOID MlmeSetMcsGroup(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEnt); + +UCHAR MlmeSelectUpRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_GRP_TB *pCurrTxRate); + +UCHAR MlmeSelectDownRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR CurrRateIdx); + +VOID MlmeGetSupportedMcsAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR mcs23GI, + OUT CHAR mcs[]); + +UCHAR MlmeSelectTxRateAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN CHAR mcs[], + IN CHAR Rssi, + IN CHAR RssiOffset); + +BOOLEAN MlmeRAHybridRule( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_GRP_TB *pCurrTxRate, + IN ULONG NewTxOkCount, + IN ULONG TxErrorRatio); + +VOID MlmeNewRateAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN ULONG TrainUp, + IN ULONG TrainDown, + IN ULONG TxErrorRatio); + +#ifdef NEW_RATE_ADAPT_SUPPORT +INT Set_PerThrdAdj_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_LowTrafficThrd_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TrainUpRule_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TrainUpRuleRSSI_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TrainUpLowThrd_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TrainUpHighThrd_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_RateTable_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /*NEW_RATE_ADAPT_SUPPORT*/ + +#ifdef AGS_SUPPORT +INT Show_AGS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef CONFIG_STA_SUPPORT +VOID MlmeDynamicTxRateSwitchingAGS( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pTable, + IN UCHAR TableSize, + IN PAGS_STATISTICS_INFO pAGSStatisticsInfo, + IN UCHAR InitTxRateIdx); + +VOID StaQuickResponeForRateUpExecAGS( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pTable, + IN UCHAR TableSize, + IN PAGS_STATISTICS_INFO pAGSStatisticsInfo, + IN UCHAR InitTxRateIdx); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID ApMlmeDynamicTxRateSwitchingAGS( + IN RTMP_ADAPTER *pAd, + IN INT idx); + +VOID ApQuickResponeForRateUpExecAGS( + IN RTMP_ADAPTER *pAd, + IN INT idx); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* AGS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeDynamicTxRateSwitchingAdapt(struct _RTMP_ADAPTER *pAd, UINT idx); +VOID APQuickResponeForRateUpExecAdapt(struct _RTMP_ADAPTER *pAd, UINT idx); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +VOID StaQuickResponeForRateUpExecAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN ULONG i, + IN CHAR Rssi); + +VOID MlmeDynamicTxRateSwitchingAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN ULONG i, + IN ULONG TxSuccess, + IN ULONG TxRetransmit, + IN ULONG TxFailCount); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeDynamicTxRateSwitching( + IN struct _RTMP_ADAPTER *pAd); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APMlmeSetTxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_LEGACY_TB *pTxRate); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +VOID MlmeDynamicTxRateSwitching( + IN struct _RTMP_ADAPTER *pAd); + +VOID StaQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeSetTxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_LEGACY_TB *pTxRate); +#endif /* CONFIG_STA_SUPPORT */ + +VOID MlmeRAInit(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEntry); +VOID MlmeNewTxRate(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeRALog( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RA_LOG_TYPE raLogType, + IN ULONG TxErrorRatio, + IN ULONG TxTotalCnt); + +VOID MlmeSelectTxRateTable( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR **ppTable, + IN UCHAR *pTableSize, + IN UCHAR *pInitTxRateIdx); + +/* normal rate switch */ +#define RTMP_DRS_ALG_INIT(__pAd, __Alg) \ + (__pAd)->rateAlg = __Alg; + +#endif /* __DRS_EXTR_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom.h new file mode 100644 index 000000000..21a660c58 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom.h @@ -0,0 +1,857 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + Miniport header file for eeprom related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __EEPROM_H__ +#define __EEPROM_H__ + +/************************************************************************* + * + * EEPROM Related definitions + * + ************************************************************************/ + +#if (CONFIG_RT_FIRST_CARD == 7602 || CONFIG_RT_FIRST_CARD == 7612 || CONFIG_RT_FIRST_CARD == 7620) +#if defined (CONFIG_RT_FIRST_IF_RF_OFFSET) +#define DEFAULT_RF_OFFSET CONFIG_RT_FIRST_IF_RF_OFFSET +#else +#define DEFAULT_RF_OFFSET 0x40000 +#endif +#elif (CONFIG_RT_SECOND_CARD == 7602 || CONFIG_RT_SECOND_CARD == 7612) +#if defined (CONFIG_RT_SECOND_IF_RF_OFFSET) +#define DEFAULT_RF_OFFSET CONFIG_RT_SECOND_IF_RF_OFFSET +#else +#define DEFAULT_RF_OFFSET 0x48000 +#endif +#endif + +#if (CONFIG_RT_FIRST_CARD == 7612 || CONFIG_RT_SECOND_CARD == 7612) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/Wireless/MT7612E_EEPROM.bin" +#elif (CONFIG_RT_FIRST_CARD == 7602 || CONFIG_RT_SECOND_CARD == 7602) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/Wireless/MT7602E_EEPROM.bin" +#elif (CONFIG_RT_FIRST_CARD == 7620) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/Wireless/MT7620_AP_2T2R-4L_V15.BIN" +#endif + +/* For ioctl check usage */ +#define EEPROM_IS_PROGRAMMED 0x80 + +#define E2P_NONE 0x00 +#define E2P_EFUSE_MODE 0x01 +#define E2P_FLASH_MODE 0x02 +#define E2P_EEPROM_MODE 0x03 +#define E2P_BIN_MODE 0x04 +#define NUM_OF_E2P_MODE 0x05 + +#ifdef RTMP_MAC_PCI +#define MAX_EEPROM_BIN_FILE_SIZE 512 +#else +#define MAX_EEPROM_BIN_FILE_SIZE 1024 +#endif /* !RTMP_MAC_PCI */ + +#define EEPROM_SIZE 0x200 + +#define EEPROM_DEFULT_BIN_FILE "RT30xxEEPROM.bin" +#ifdef BB_SOC +#define BIN_FILE_PATH "/etc/RT30xxEEPROM.bin" +#else +#define BIN_FILE_PATH "/tmp/RT30xxEEPROM.bin" +#endif /* BB_SOC */ + +#define EEPROM_FILE_DIR "/etc_ro/Wireless/" +#define EEPROM_1ST_FILE_DIR "/etc_ro/Wireless/iNIC/" +#define EEPROM_2ND_FILE_DIR "/etc_ro/Wireless/iNIC/" + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_WORD_STRUC { + struct { + UCHAR Byte1; // High Byte + UCHAR Byte0; // Low Byte + } field; + USHORT word; +} EEPROM_WORD_STRUC; +#else +typedef union _EEPROM_WORD_STRUC { + struct { + UCHAR Byte0; + UCHAR Byte1; + } field; + USHORT word; +} EEPROM_WORD_STRUC; +#endif + + +/* ------------------------------------------------------------------- */ +/* E2PROM data layout */ +/* ------------------------------------------------------------------- */ + +/* Board type */ + +#define BOARD_TYPE_MINI_CARD 0 /* Mini card */ +#define BOARD_TYPE_USB_PEN 1 /* USB pen */ + +/* + EEPROM antenna select format +*/ + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT DACTestBit:1; /* control if driver should patch the DAC issue */ + USHORT CoexBit:1; + USHORT bInternalTxALC:1; /* Internal Tx ALC */ + USHORT AntOpt:1; /* Fix Antenna Option: 0:Main; 1: Aux */ + USHORT AntDiversity:1; /* Antenna diversity */ +#ifdef MT76x2 + USHORT ExternalLNA:1; +#else + USHORT Rsv1:1; /* must be 0 */ +#endif /* MT76x2 */ + USHORT BW40MAvailForA:1; /* 0:enable, 1:disable */ + USHORT BW40MAvailForG:1; /* 0:enable, 1:disable */ + USHORT EnableWPSPBC:1; /* WPS PBC Control bit */ + USHORT BW40MSidebandForA:1; + USHORT BW40MSidebandForG:1; + USHORT CardbusAcceleration:1; /* !!! NOTE: 0 - enable, 1 - disable */ + USHORT ExternalLNAForA:1; /* external LNA enable for 5G */ + USHORT ExternalLNAForG:1; /* external LNA enable for 2.4G */ + USHORT DynamicTxAgcControl:1; /* */ + USHORT HardwareRadioControl:1; /* Whether RF is controlled by driver or HW. 1:enable hw control, 0:disable */ + } field; + USHORT word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; +#else +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT HardwareRadioControl:1; /* 1:enable, 0:disable */ + USHORT DynamicTxAgcControl:1; /* */ + USHORT ExternalLNAForG:1; /* external LNA enable for 2.4G */ + USHORT ExternalLNAForA:1; /* external LNA enable for 5G */ + USHORT CardbusAcceleration:1; /* !!! NOTE: 0 - enable, 1 - disable */ + USHORT BW40MSidebandForG:1; + USHORT BW40MSidebandForA:1; + USHORT EnableWPSPBC:1; /* WPS PBC Control bit */ + USHORT BW40MAvailForG:1; /* 0:enable, 1:disable */ + USHORT BW40MAvailForA:1; /* 0:enable, 1:disable */ +#ifdef MT76x2 + USHORT ExternalLNA:1; +#else + USHORT Rsv1:1; /* must be 0 */ +#endif /* MT76x2 */ + USHORT AntDiversity:1; /* Antenna diversity */ + USHORT AntOpt:1; /* Fix Antenna Option: 0:Main; 1: Aux */ + USHORT bInternalTxALC:1; /* Internal Tx ALC */ + USHORT CoexBit:1; + USHORT DACTestBit:1; /* control if driver should patch the DAC issue */ + } field; + USHORT word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#if defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(MT76x2) + +#ifdef RTMP_PCI_SUPPORT +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG3_STRUC { + struct { +#ifdef MT76x2 + USHORT CoexMethod:3; + USHORT Rsv1:1; + USHORT TemperatureDisable:1; /* 0:enable, 1:disable */ + USHORT XtalOption:2; + USHORT HWAntDiv:1; +#else + USHORT Rsv1:4; /* must be 0 */ + USHORT rx_temp_comp:1; + USHORT CrystalShared:2; + USHORT CoexAnt:1; +#endif /* MT76x2 */ + USHORT TxStream:4; /* Number of Tx stream */ + USHORT RxStream:4; /* Number of rx stream */ + } field; + USHORT word; +} EEPROM_NIC_CONFIG3_STRUC, *PEEPROM_NIC_CONFIG3_STRUC; +#else +typedef union _EEPROM_NIC_CINFIG3_STRUC { + struct { + USHORT RxStream:4; /* Number of rx stream */ + USHORT TxStream:4; /* Number of Tx stream */ +#ifdef MT76x2 + USHORT HWAntDiv:1; + USHORT XtalOption:2; + USHORT TemperatureDisable:1; /* 0:enable, 1:disable */ + USHORT Rsv1:1; + USHORT CoexMethod:3; +#else + USHORT CoexAnt:1; + USHORT CrystalShared:2; + USHORT rx_temp_comp:1; + USHORT Rsv1:4; /* must be 0 */ +#endif /* MT76x2 */ + } field; + USHORT word; +} EEPROM_NIC_CONFIG3_STRUC, *PEEPROM_NIC_CONFIG3_STRUC; +#endif /* RT_BIG_ENDIAN */ +#endif /* RTMP_PCI_SUPPORT */ +#endif /* defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(MT76x2) */ + + + +/* + TX_PWR Value valid range 0xFA(-6) ~ 0x24(36) +*/ +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TX_PWR_STRUC { + struct { + signed char Byte1; /* High Byte */ + signed char Byte0; /* Low Byte */ + } field; + USHORT word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; +#else +typedef union _EEPROM_TX_PWR_STRUC { + struct { + signed char Byte0; /* Low Byte */ + signed char Byte1; /* High Byte */ + } field; + USHORT word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_VERSION_STRUC { + struct { + UCHAR Version; /* High Byte */ + UCHAR FaeReleaseNumber; /* Low Byte */ + } field; + USHORT word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; +#else +typedef union _EEPROM_VERSION_STRUC { + struct { + UCHAR FaeReleaseNumber; /* Low Byte */ + UCHAR Version; /* High Byte */ + } field; + USHORT word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_LED_STRUC { + struct { + USHORT Rsvd:3; /* Reserved */ + USHORT LedMode:5; /* Led mode. */ + USHORT PolarityGPIO_4:1; /* Polarity GPIO#4 setting. */ + USHORT PolarityGPIO_3:1; /* Polarity GPIO#3 setting. */ + USHORT PolarityGPIO_2:1; /* Polarity GPIO#2 setting. */ + USHORT PolarityGPIO_1:1; /* Polarity GPIO#1 setting. */ + USHORT PolarityGPIO_0:1; /* Polarity GPIO#0 setting. */ + USHORT PolarityACT:1; /* Polarity ACT setting. */ + USHORT PolarityRDY_A:1; /* Polarity RDY_A setting. */ + USHORT PolarityRDY_G:1; /* Polarity RDY_G setting. */ + } field; + USHORT word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; +#else +typedef union _EEPROM_LED_STRUC { + struct { + USHORT PolarityRDY_G:1; /* Polarity RDY_G setting. */ + USHORT PolarityRDY_A:1; /* Polarity RDY_A setting. */ + USHORT PolarityACT:1; /* Polarity ACT setting. */ + USHORT PolarityGPIO_0:1; /* Polarity GPIO#0 setting. */ + USHORT PolarityGPIO_1:1; /* Polarity GPIO#1 setting. */ + USHORT PolarityGPIO_2:1; /* Polarity GPIO#2 setting. */ + USHORT PolarityGPIO_3:1; /* Polarity GPIO#3 setting. */ + USHORT PolarityGPIO_4:1; /* Polarity GPIO#4 setting. */ + USHORT LedMode:5; /* Led mode. */ + USHORT Rsvd:3; /* Reserved */ + } field; + USHORT word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + UCHAR TxPowerEnable:1; /* Enable */ + UCHAR Type:1; /* 1: plus the delta value, 0: minus the delta value */ + UCHAR DeltaValue:6; /* Tx Power dalta value (MAX=4) */ + } field; + UCHAR value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; +#else +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + UCHAR DeltaValue:6; /* Tx Power dalta value (MAX=4) */ + UCHAR Type:1; /* 1: plus the delta value, 0: minus the delta value */ + UCHAR TxPowerEnable:1; /* Enable */ + } field; + UCHAR value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TX_PWR_OFFSET_STRUC +{ + struct + { + UCHAR Byte1; /* High Byte */ + UCHAR Byte0; /* Low Byte */ + } field; + + USHORT word; +} EEPROM_TX_PWR_OFFSET_STRUC, *PEEPROM_TX_PWR_OFFSET_STRUC; +#else +typedef union _EEPROM_TX_PWR_OFFSET_STRUC +{ + struct + { + UCHAR Byte0; /* Low Byte */ + UCHAR Byte1; /* High Byte */ + } field; + + USHORT word; +} EEPROM_TX_PWR_OFFSET_STRUC, *PEEPROM_TX_PWR_OFFSET_STRUC; +#endif /* RT_BIG_ENDIAN */ + +#define NIC_CONFIGURE_0 0x34 +#define EXTERNAL_PA_MASK (0x3 << 8) +#define GET_PA_TYPE(p) (((p) & EXTERNAL_PA_MASK) >> 8) + +#define NIC_CONFIGURE_1 0x36 +#define INTERNAL_TX_ALC_EN (1 << 13) + +#define XTAL_TRIM1 0x3A +#define XTAL_TRIM1_DIP_SELECTION (1 << 7) +#define XTAL_TRIM1_MASK (0x7F) + +#define G_BAND_20_40_BW_PWR_DELTA 0x50 +#define G_BAND_20_40_BW_PWR_DELTA_MASK (0x3f) +#define G_BAND_20_40_BW_PWR_DELTA_SIGN (1 << 6) +#define G_BAND_20_40_BW_PWR_DELTA_EN (1 << 7) +#define A_BAND_20_40_BW_PWR_DELTA_MASK (0x3f << 8) +#define A_BAND_20_40_BW_PWR_DELTA_SIGN (1 << 14) +#define A_BAND_20_40_BW_PWR_DELTA_EN (1 << 15) + +enum EEPROM_STORAGE_TYPE{ + EEPROM_PROM = 0, +#ifdef RTMP_EFUSE_SUPPORT + EEPROM_EFUSE = 1, +#endif /* RTMP_EFUSE_SUPPORT */ +#ifdef RTMP_FLASH_SUPPORT + EEPROM_FLASH = 2, +#endif /* RTMP_FLASH_SUPPORT */ +}; + +#define A_BAND_20_80_BW_PWR_DELTA 0x52 +#define A_BAND_20_80_BW_PWR_DELTA_MASK (0x3f) +#define A_BAND_20_80_BW_PWR_DELTA_SIGN (1 << 6) +#define A_BAND_20_80_BW_PWR_DELTA_EN (1 << 7) +#define G_BAND_EXT_PA_SETTING_MASK (0x7f << 8) +#define G_BAND_EXT_PA_SETTING_EN (1 << 15) + +#define A_BAND_EXT_PA_SETTING 0x54 +#define A_BAND_EXT_PA_SETTING_MASK (0x7f) +#define A_BAND_EXT_PA_SETTING_EN (1 << 7) +#define TEMP_SENSOR_CAL_MASK (0x7f << 8) +#define TEMP_SENSOR_CAL_EN (1 << 15) + +#define TX0_G_BAND_TSSI_SLOPE 0x56 +#define TX0_G_BAND_TSSI_SLOPE_MASK (0xff) +#define TX0_G_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define TX0_G_BAND_TARGET_PWR 0x58 +#define TX0_G_BAND_TARGET_PWR_MASK (0xff) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define TX0_G_BAND_CHL_PWR_DELTA_MID 0x5A +#define TX0_G_BAND_CHL_PWR_DELTA_MID_MASK (0x3f) +#define TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN (1 << 6) +#define TX0_G_BAND_CHL_PWR_DELTA_MID_EN (1 << 7) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define TX1_G_BAND_TSSI_SLOPE 0x5C +#define TX1_G_BAND_TSSI_SLOPE_MASK (0xff) +#define TX1_G_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define TX1_G_BAND_TARGET_PWR 0x5E +#define TX1_G_BAND_TARGET_PWR_MASK (0xff) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define TX1_G_BAND_CHL_PWR_DELTA_MID 0x60 +#define TX1_G_BAND_CHL_PWR_DELTA_MID_MASK (0x3f) +#define TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN (1 << 6) +#define TX1_G_BAND_CHL_PWR_DELTA_MID_EN (1 << 7) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP0_TX0_A_BAND_TSSI_SLOPE 0x62 +#define GRP0_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP0_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP0_TX0_A_BAND_TARGET_PWR 0x64 +#define GRP0_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI 0x66 +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP1_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP1_TX0_A_BAND_TSSI_OFFSET 0x68 +#define GRP1_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP1_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW 0x6A +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP2_TX0_A_BAND_TSSI_SLOPE 0x6C +#define GRP2_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP2_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP2_TX0_A_BAND_TARGET_PWR 0x6E +#define GRP2_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI 0x70 +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP3_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP3_TX0_A_BAND_TSSI_OFFSET 0x72 +#define GRP3_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP3_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW 0x74 +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP4_TX0_A_BAND_TSSI_SLOPE 0x76 +#define GRP4_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP4_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP4_TX0_A_BAND_TARGET_PWR 0x78 +#define GRP4_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI 0x7A +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP5_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP5_TX0_A_BAND_TSSI_OFFSET 0x7C +#define GRP5_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP5_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW 0X7E +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP0_TX1_A_BAND_TSSI_SLOPE 0x80 +#define GRP0_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP0_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP0_TX1_A_BAND_TARGET_PWR 0x82 +#define GRP0_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI 0x84 +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP1_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP1_TX1_A_BAND_TSSI_OFFSET 0x86 +#define GRP1_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP1_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x88 +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP2_TX1_A_BAND_TSSI_SLOPE 0x8A +#define GRP2_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP2_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP2_TX1_A_BAND_TARGET_PWR 0x8C +#define GRP2_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI 0x8E +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP3_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP3_TX1_A_BAND_TSSI_OFFSET 0x90 +#define GRP3_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP3_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x92 +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP4_TX1_A_BAND_TSSI_SLOPE 0x94 +#define GRP4_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP4_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP4_TX1_A_BAND_TARGET_PWR 0x96 +#define GRP4_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI 0x98 +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP5_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP5_TX1_A_BAND_TSSI_OFFSET 0x9A +#define GRP5_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP5_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x9C +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define G_BAND_BANDEDGE_PWR_BACK_OFF 0x9E +#define G_BAND_BANDEDGE_PWR_BACK_OFF_MASK (0x7f) +#define G_BAND_BANDEDGE_PWR_BACK_OFF_EN (1 << 7) +#define XTAL_TRIM2_MASK (0x7f << 8) +#define XTAL_TRIM2_DIP_SELECTION (1 << 15) + +#define TX_PWR_CCK_1_2M 0xA0 +#define TX_PWR_CCK_1_2M_MASK (0x3f) +#define TX_PWR_CCK_1_2M_SIGN (1 << 6) +#define TX_PWR_CCK_1_2M_EN (1 << 7) +#define TX_PWR_CCK_5_11M_MASK (0x3f << 8) +#define TX_PWR_CCK_5_11M_SIGN (1 << 14) +#define TX_PWR_CCK_5_11M_EN (1 << 15) + +#define TX_PWR_G_BAND_OFDM_6_9M 0xA2 +#define TX_PWR_G_BAND_OFDM_6_9M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_6_9M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_6_9M_EN (1 << 7) +#define TX_PWR_G_BAND_OFDM_12_18M_MASK (0x3f << 8) +#define TX_PWR_G_BAND_OFDM_12_18M_SIGN (1 << 14) +#define TX_PWR_G_BAND_OFDM_12_18M_EN (1 << 15) + +#define TX_PWR_G_BAND_OFDM_24_36M 0xA4 +#define TX_PWR_G_BAND_OFDM_24_36M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_24_36M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_24_36M_EN (1 << 7) +#define TX_PWR_G_BAND_OFDM_48_54M_MASK (0x3f << 8) +#define TX_PWR_G_BAND_OFDM_48_54M_SIGN (1 << 14) +#define TX_PWR_G_BAND_OFDM_48_54M_EN (1 << 15) + +#define TX_PWR_HT_MCS_0_1 0xA6 +#define TX_PWR_HT_MCS_0_1_MASK (0x3f) +#define TX_PWR_HT_MCS_0_1_SIGN (1 << 6) +#define TX_PWR_HT_MCS_0_1_EN (1 << 7) +#define TX_PWR_HT_MCS_2_3_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_2_3_SIGN (1 << 14) +#define TX_PWR_HT_MCS_2_3_EN (1 << 15) + +#define TX_PWR_HT_MCS_4_5 0xA8 +#define TX_PWR_HT_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_MCS_4_5_SIGN (1 << 6) +#define TX_PWR_HT_MCS_4_5_EN (1 << 7) +#define TX_PWR_HT_MCS_6_7_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_6_7_SIGN (1 << 14) +#define TX_PWR_HT_MCS_6_7_EN (1 << 15) + +#define TX_PWR_HT_MCS_8_9 0xAA +#define TX_PWR_HT_MCS_8_9_MASK (0x3f) +#define TX_PWR_HT_MCS_8_9_SIGN (1 << 6) +#define TX_PWR_HT_MCS_8_9_EN (1 << 7) +#define TX_PWR_HT_MCS_10_11_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_10_11_SIGN (1 << 14) +#define TX_PWR_HT_MCS_10_11_EN (1 << 15) + +#define TX_PWR_HT_MCS_12_13 0xAC +#define TX_PWR_HT_MCS_12_13_MASK (0x3f) +#define TX_PWR_HT_MCS_12_13_SIGN (1 << 6) +#define TX_PWR_HT_MCS_12_13_EN (1 << 7) +#define TX_PWR_HT_MCS_14_15_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_14_15_SIGN (1 << 14) +#define TX_PWR_HT_MCS_14_15_EN (1 << 15) + +#define CONFIG_G_BAND_CHL 0xB0 +#define CONFIG_G_BAND_CHL_GRP1_MASK (0xff) +#define CONFIG_G_BAND_CHL_GRP2_MASK (0xff << 8) + +#define TX_PWR_A_BAND_OFDM_6_9M 0xB2 +#define TX_PWR_A_BAND_OFDM_6_9M_MASK (0x3f) +#define TX_PWR_A_BAND_OFDM_6_9M_SIGN (1 << 6) +#define TX_PWR_A_BAND_OFDM_6_9M_EN (1 << 7) +#define TX_PWR_A_BAND_OFDM_12_18M_MASK (0x3f << 8) +#define TX_PWR_A_BAND_OFDM_12_18M_SIGN (1 << 14) +#define TX_PWR_A_BAND_OFDM_12_18M_EN (1 << 15) + +#define TX_PWR_A_BAND_OFDM_24_36M 0xB4 +#define TX_PWR_A_BAND_OFDM_24_36M_MASK (0x3f) +#define TX_PWR_A_BAND_OFDM_24_36M_SIGN (1 << 6) +#define TX_PWR_A_BAND_OFDM_24_36M_EN (1 << 7) +#define TX_PWR_A_BAND_OFDM_48_54M_MASK (0x3f << 8) +#define TX_PWR_A_BAND_OFDM_48_54M_SIGN (1 << 14) +#define TX_PWR_A_BAND_OFDM_48_54M_EN (1 << 15) + +#define CONFIG1_A_BAND_CHL 0xB6 +#define CONFIG1_A_BAND_CHL_GRP1_MASK 0xff +#define CONFIG1_A_BAND_CHL_GRP2_MASK (0xff << 8) + +#define CONFIG2_A_BAND_CHL 0xB8 +#define CONFIG2_A_BAND_CHL_GRP1_MASK (0xff) +#define CONFIG2_A_BAND_CHL_GRP2_MASK (0xff << 8) + +#define TX_PWR_VHT_MCS_0_1 0xBA +#define TX_PWR_VHT_MCS_0_1_MASK (0x3f) +#define TX_PWR_VHT_MCS_0_1_SIGN (1 << 6) +#define TX_PWR_VHT_MCS_0_1_EN (1 << 7) +#define TX_PWR_VHT_MCS_2_3_MASK (0x3f << 8) +#define TX_PWR_VHT_MCS_2_3_SIGN (1 << 14) +#define TX_PWR_VHT_MCS_2_3_EN (1 << 15) + +#define TX_PWR_VHT_MCS_4_5 0xBC +#define TX_PWR_VHT_MCS_4_5_MASK (0x3f) +#define TX_PWR_VHT_MCS_4_5_SIGN (1 << 6) +#define TX_PWR_VHT_MCS_4_5_EN (1 << 7) +#define TX_PWR_VHT_MCS_6_7_MASK (0x3f << 8) +#define TX_PWR_VHT_MCS_6_7_SIGN (1 << 14) +#define TX_PWR_VHT_MCS_6_7_EN (1 << 15) + +#define TX_PWR_5G_VHT_MCS_8_9 0xBE +#define TX_PWR_5G_VHT_MCS_8_9_MASK (0x3f) +#define TX_PWR_5G_VHT_MCS_8_9_SIGN (1 << 6) +#define TX_PWR_5G_VHT_MCS_8_9_EN (1 << 7) +#define TX_PWR_2G_VHT_MCS_8_9_MASK (0x3f << 8) +#define TX_PWR_2G_VHT_MCS_8_9_SIGN (1 << 14) +#define TX_PWR_2G_VHT_MCS_8_9_EN (1 << 15) + +#define CP_FT_VERSION 0xF6 +#define CP_FT_VERSION_MASK 0xff + +#define RF_2G_RX_HIGH_GAIN 0xF8 +#define RF0_2G_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_2G_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_2G_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_2G_RX_HIGH_GAIN_SIGN (1 << 15) + +#define RF_5G_GRP0_1_RX_HIGH_GAIN 0xFA +#define RF0_5G_GRP0_RX_HIGH_GAIN_MASK (0x07) +#define RF0_5G_GRP0_RX_HIGH_GAIN_SIGN (1 << 3) +#define RF1_5G_GRP0_RX_HIGH_GAIN_MASK (0x07 << 4) +#define RF1_5G_GRP0_RX_HIGH_GAIN_SIGN (1 << 7) +#define RF0_5G_GRP1_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_5G_GRP1_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_5G_GRP1_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_5G_GRP1_RX_HIGH_GAIN_SIGN (1 << 15) + +#define RF_5G_GRP2_3_RX_HIGH_GAIN 0xFC +#define RF0_5G_GRP2_RX_HIGH_GAIN_MASK (0x07) +#define RF0_5G_GRP2_RX_HIGH_GAIN_SIGN (1 << 3) +#define RF1_5G_GRP2_RX_HIGH_GAIN_MASK (0x07 << 4) +#define RF1_5G_GRP2_RX_HIGH_GAIN_SIGN (1 << 7) +#define RF0_5G_GRP3_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_5G_GRP3_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_5G_GRP3_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_5G_GRP3_RX_HIGH_GAIN_SIGN (1 << 15) + +#define RF_5G_GRP4_5_RX_HIGH_GAIN 0xFE +#define RF0_5G_GRP4_RX_HIGH_GAIN_MASK (0x07) +#define RF0_5G_GRP4_RX_HIGH_GAIN_SIGN (1 << 3) +#define RF1_5G_GRP4_RX_HIGH_GAIN_MASK (0x07 << 4) +#define RF1_5G_GRP4_RX_HIGH_GAIN_SIGN (1 << 7) +#define RF0_5G_GRP5_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_5G_GRP5_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_5G_GRP5_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_5G_GRP5_RX_HIGH_GAIN_SIGN (1 << 15) + +#define BT_RCAL_RESULT 0x138 +#define BT_VCDL_CALIBRATION 0x13C +#define BT_PMUCFG 0x13E + +struct _RTMP_ADAPTER; + +#ifdef RTMP_PCI_SUPPORT +/************************************************************************* + * Public function declarations for prom-based chipset + ************************************************************************/ +int rtmp_ee_prom_read16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + OUT USHORT *pValue); + +int rtmp_ee_prom_write16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT value); + +#endif /* RTMP_PCI_SUPPORT */ + + + + +#if defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) +/************************************************************************* + * Public function declarations for flash-based chipset + ************************************************************************/ +NDIS_STATUS rtmp_nv_init( + IN struct _RTMP_ADAPTER *pAd); + +int rtmp_get_flash_id_num(VOID); + +int rtmp_ee_flash_read( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + OUT USHORT *pValue); + +int rtmp_ee_flash_write( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT Data); + +VOID rtmp_ee_flash_read_all( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT *Data); + +VOID rtmp_ee_flash_write_all( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT *Data); + +INT Set_LoadEepromBufferFromFlash_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + + +#ifdef RTMP_EFUSE_SUPPORT +/************************************************************************* + * Public function declarations for efuse-based chipset + ************************************************************************/ +int rtmp_ee_efuse_read16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + OUT USHORT *pValue); + +int rtmp_ee_efuse_write16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT data); + +INT rtmp_ee_write_to_efuse( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_EFUSE_SUPPORT */ + +/************************************************************************* + * Public function declarations for using BIN buffer mode to access eeprom contents + ************************************************************************/ +INT rtmp_ee_bin_read16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + OUT USHORT *pValue); + +INT rtmp_ee_bin_write16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT data); + +INT rtmp_ee_load_from_bin( + IN struct _RTMP_ADAPTER *pAd); + +INT rtmp_ee_write_to_bin( + IN struct _RTMP_ADAPTER *pAd); + +#ifdef RT65xx +INT rtmp_ee_write_to_prom( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RT65xx */ + +INT Set_LoadEepromBufferFromBin_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_EepromBufferWriteBack_Proc( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + + +/************************************************************************* + * Public function declarations for prom operation callback functions setting + ************************************************************************/ +INT RtmpChipOpsEepromHook(struct _RTMP_ADAPTER *pAd, INT infType); + +BOOLEAN rtmp_get_default_bin_file_by_chip(struct _RTMP_ADAPTER *pAd, UINT32 ChipVersion, PSTRING *pBinFileName); +UCHAR RtmpEepromGetDefault(struct _RTMP_ADAPTER *pAd); +#endif /* __EEPROM_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom/mt7601_e2p.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom/mt7601_e2p.h new file mode 100644 index 000000000..0ebba5ff1 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom/mt7601_e2p.h @@ -0,0 +1,37 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7601_E2PImage[] = { +0x01, 0x76, 0x00, 0x0d, 0x00, 0x0c, 0x43, 0x26, 0x60, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x01, 0x02, 0x8f, 0x14, 0x01, 0x76, 0x00, 0x00, 0x4a, 0x00, 0x01, 0x00, 0x80, 0x50, 0x08, 0x00, +0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0x01, 0x40, 0x60, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x11, 0xff, 0x04, 0x28, 0xff, 0xff, 0x2c, 0x01, 0xff, 0xff, 0x99, 0x99, +0x8c, 0x88, 0xff, 0x07, 0x08, 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, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x20, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, +0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x12, 0x03, 0x4d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x61, 0x00, 0x54, 0x00, 0x65, 0x00, +0x6b, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x03, 0x38, 0x00, 0x30, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x31, 0x00, 0x20, 0x00, +0x6e, 0x00, 0x20, 0x00, 0x57, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x03, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom/mt76x2_e2p.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom/mt76x2_e2p.h new file mode 100644 index 000000000..0493aaceb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/eeprom/mt76x2_e2p.h @@ -0,0 +1,37 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT76x2_E2PImage[] = { +0x62, 0x76, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x76, 0xc3, 0x14, 0x00, 0x00, +0x00, 0x00, 0x12, 0x76, 0xc3, 0x14, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x37, 0xd8, 0x9d, 0x40, 0xff, 0x7f, 0xfd, 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x22, 0xfc, 0x0c, 0x00, 0xff, 0xff, 0xb4, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xd3, 0x8c, 0x8c, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x8c, 0xe0, 0x01, +0x00, 0x00, 0x00, 0x57, 0x47, 0xba, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, +0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, +0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, +0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, +0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0xc4, 0xc4, 0x00, 0x00, 0xc4, 0xc4, 0x82, 0x82, 0x00, 0x00, +0x00, 0x00, 0xc4, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x83, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x0f, 0x09, 0x0d, 0x10, 0x00, 0x28, 0x26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x0f, 0xca, 0x74, 0xc5, 0xe8, 0x07, 0x30, 0x3d, 0x01, 0xb0, 0x08, 0x26, 0x00, 0x0e, 0x04, 0x15, +0x00, 0x8a, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x9d, 0x08, 0x00, 0x12, 0xc0, 0x00, 0x00, +0x08, 0x20, 0x04, 0x2a, 0x90, 0x00, 0x00, 0x24, 0x01, 0x04, 0x54, 0x08, 0xd0, 0xa0, 0x28, 0x20, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xc0, 0x81, 0x82, 0xc3, 0x04, 0x45, 0x46, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/firmware.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/firmware.h new file mode 100644 index 000000000..27588bbf8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/firmware.h @@ -0,0 +1,517 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR FirmwareImage [] = { +0x02, 0x02, 0xa3, 0x02, 0x02, 0x2e, 0x22, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x2c, 0xff, 0xff, +0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0xdd, 0xc0, 0xe0, +0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03, +0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14, +0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x24, +0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14, +0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24, +0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5, +0x50, 0x85, 0x24, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55, +0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x24, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf, +0x24, 0x12, 0x02, 0x0a, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0, +0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf, +0x24, 0x12, 0x02, 0x0a, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0x90, 0x70, 0x13, 0xe4, 0xf0, +0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, +0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0xe8, 0xc0, 0xe0, 0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, +0xeb, 0xc0, 0xe0, 0xec, 0xc0, 0xe0, 0xed, 0xc0, 0xe0, 0xee, 0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, +0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x12, 0xd2, 0xaf, 0xd0, 0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, +0xe0, 0xfd, 0xd0, 0xe0, 0xfc, 0xd0, 0xe0, 0xfb, 0xd0, 0xe0, 0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, +0xf8, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, +0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, +0x0c, 0x30, 0x58, 0x0a, 0xe5, 0x54, 0x60, 0x04, 0x15, 0x54, 0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, +0x0a, 0xe5, 0x50, 0x60, 0x04, 0x15, 0x50, 0x80, 0x02, 0xc2, 0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, +0x04, 0x15, 0x46, 0xd2, 0x04, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, +0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x12, 0x02, 0x50, 0x30, 0x45, 0x03, +0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12, 0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, +0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, +0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09, 0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, +0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12, 0x02, 0x80, 0x80, 0xbf, 0xc2, 0x43, +0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5, 0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, +0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18, 0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, +0x74, 0x08, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, +0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, +0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60, 0x1f, 0xe4, 0xfe, +0x12, 0x02, 0xaf, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x02, 0xaf, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, +0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3, 0x22, 0xc0, 0xe0, +0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf, 0x30, 0x45, 0x03, +0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, +0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x01, 0xbe, 0x12, 0x02, 0x69, 0xe4, 0xf5, 0x22, 0xf5, 0x47, +0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x75, 0x89, 0x02, 0xe4, 0xf5, 0x8c, 0xf5, +0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75, 0xa8, 0x05, 0x22, +0x30, 0x45, 0x03, 0x12, 0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, +0x43, 0x87, 0x01, 0x22, 0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x02, 0xc5, 0x1e, +0x80, 0xf5, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0x7a, 0x74, +0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x02, 0xc3, 0x93, 0x90, +0x03, 0x00, 0x73, 0x0a, 0x18, 0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xc0, 0x26, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x0a, 0x22, 0xc0, 0x26, +0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x18, 0x22, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x33, 0x02, 0x14, 0xc2, 0x02, +0x14, 0xc3, 0x02, 0x15, 0x8f, 0x02, 0x15, 0x90, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x1a, 0x6f, 0x02, +0x1b, 0xec, 0x02, 0x16, 0xbc, 0x02, 0x15, 0xf7, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x1d, +0x19, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02, 0x14, 0xc1, 0x90, 0x70, 0x12, +0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x01, 0xe4, 0x10, 0xda, 0x30, 0x10, 0xb1, 0x31, +0x10, 0x93, 0x35, 0x10, 0x8a, 0x36, 0x10, 0xe7, 0x40, 0x10, 0xfe, 0x41, 0x11, 0x15, 0x50, 0x11, +0x5a, 0x51, 0x11, 0x63, 0x52, 0x11, 0x63, 0x53, 0x11, 0x63, 0x54, 0x11, 0x9f, 0x55, 0x11, 0xfc, +0x56, 0x12, 0x4f, 0x64, 0x12, 0x6a, 0x72, 0x13, 0x1e, 0x73, 0x13, 0x42, 0x74, 0x14, 0x35, 0x80, +0x14, 0xa5, 0x83, 0x14, 0x5c, 0x91, 0x00, 0x00, 0x14, 0xc1, 0x90, 0x70, 0x11, 0xe0, 0xf5, 0x3c, +0x02, 0x14, 0xbb, 0xe5, 0x55, 0xb4, 0x02, 0x0f, 0xe5, 0x58, 0x30, 0xe0, 0x06, 0x90, 0x01, 0x0d, +0x74, 0x08, 0xf0, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, +0xbb, 0x20, 0x02, 0x03, 0x30, 0x03, 0x0a, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, +0xbb, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x0c, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, +0xe0, 0x44, 0x04, 0xf0, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xb4, 0x5a, +0x03, 0xc2, 0x4f, 0x22, 0xd2, 0x4f, 0x22, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x50, 0x03, 0x02, 0x14, +0xc1, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x04, 0xf0, 0x22, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x50, 0x03, 0x02, 0x14, 0xc1, 0x90, 0x01, 0x0c, 0xe0, 0x54, 0xfd, 0xf0, 0xa3, +0xe0, 0x54, 0xfb, 0xf0, 0x22, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, +0x02, 0x14, 0xc1, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, +0xe0, 0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, +0xff, 0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, +0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x3f, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, +0x92, 0x47, 0x22, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, +0x29, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, +0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, +0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, 0xbb, 0xe5, +0x30, 0xd3, 0x94, 0x01, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x29, 0xe5, 0x47, 0x64, +0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, +0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, +0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, +0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08, 0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, +0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0xd2, 0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, +0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70, 0x11, 0xe0, 0x55, 0x3f, 0x4f, 0x90, +0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19, 0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, +0x02, 0x0a, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70, 0x18, 0xe0, 0xf5, 0x3f, 0x90, 0x02, +0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, +0x04, 0xaf, 0x3f, 0x80, 0x04, 0xe5, 0x3f, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, +0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x1a, 0x75, 0x32, 0x03, 0x75, 0x33, 0x1f, 0xe4, 0xf5, 0x31, +0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, 0xbb, 0x90, 0x10, 0x00, 0xe0, 0xf5, 0x57, +0xe4, 0xf5, 0x58, 0xf5, 0x59, 0x90, 0x10, 0x03, 0xe0, 0xb4, 0x28, 0x05, 0x75, 0x58, 0x01, 0x80, +0x3c, 0x90, 0x10, 0x03, 0xe0, 0xb4, 0x30, 0x05, 0x75, 0x58, 0x02, 0x80, 0x30, 0x90, 0x10, 0x03, +0xe0, 0xb4, 0x33, 0x05, 0x75, 0x58, 0x04, 0x80, 0x24, 0x90, 0x10, 0x03, 0xe0, 0xb4, 0x35, 0x0c, +0x90, 0x10, 0x02, 0xe0, 0xb4, 0x72, 0x05, 0x75, 0x58, 0x08, 0x80, 0x11, 0x90, 0x10, 0x03, 0xe0, +0xb4, 0x35, 0x0a, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x93, 0x03, 0x75, 0x58, 0x10, 0xe5, 0x58, 0x30, +0xe1, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, +0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, +0x75, 0x3a, 0xff, 0xf5, 0x30, 0x90, 0x05, 0xa4, 0x74, 0x11, 0xf0, 0xa3, 0x74, 0xff, 0xf0, 0xa3, +0x74, 0x03, 0xf0, 0xd2, 0x4f, 0x90, 0x01, 0x0d, 0xe0, 0x44, 0x40, 0xf0, 0x75, 0x3c, 0xff, 0xad, +0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x90, 0x70, 0x36, 0x74, 0x37, 0xf0, 0xa3, 0x74, 0x32, 0xf0, +0x90, 0x04, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x1a, 0xc2, 0x17, 0x02, 0x14, 0xbb, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x40, 0x0b, 0xe5, 0x55, 0x60, 0x07, 0x7d, 0x03, 0xaf, 0x56, 0x02, 0x02, 0x0a, +0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, +0x14, 0xbb, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x2f, 0x74, 0x40, 0xf0, +0x90, 0x70, 0x11, 0xe0, 0x54, 0x7f, 0xf5, 0x57, 0xe0, 0x54, 0x80, 0x90, 0x70, 0x32, 0xf0, 0x90, +0x70, 0x10, 0xe0, 0xff, 0xe5, 0x57, 0xd3, 0x9f, 0x40, 0x43, 0x90, 0x70, 0x33, 0xe5, 0x57, 0xf0, +0x90, 0x70, 0x10, 0xe0, 0xff, 0x90, 0x70, 0x33, 0xe0, 0xc3, 0x9f, 0xd3, 0x94, 0x04, 0x40, 0x73, +0xe0, 0x24, 0xfc, 0xf0, 0xe0, 0xff, 0x90, 0x70, 0x32, 0xe0, 0x4f, 0x90, 0x05, 0x00, 0xf0, 0xe5, +0x58, 0x54, 0x0f, 0x60, 0x04, 0x7f, 0x17, 0x80, 0x02, 0x7f, 0x11, 0x90, 0x05, 0x01, 0xef, 0xf0, +0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0xff, 0x12, 0x02, 0x94, 0x80, 0xc3, 0x90, 0x70, 0x33, +0xe5, 0x57, 0xf0, 0x90, 0x70, 0x33, 0xe0, 0xff, 0x90, 0x70, 0x10, 0xe0, 0xc3, 0x9f, 0xd3, 0x94, +0x04, 0x40, 0x30, 0x90, 0x70, 0x33, 0xe0, 0x24, 0x04, 0xf0, 0xe0, 0xff, 0x90, 0x70, 0x32, 0xe0, +0x4f, 0x90, 0x05, 0x00, 0xf0, 0xe5, 0x58, 0x54, 0x0f, 0x60, 0x04, 0x7f, 0x17, 0x80, 0x02, 0x7f, +0x11, 0x90, 0x05, 0x01, 0xef, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0xff, 0x12, 0x02, +0x94, 0x80, 0xc0, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x90, 0x70, 0x32, 0xe0, 0x4f, 0x90, 0x05, 0x00, +0xf0, 0xe5, 0x58, 0x54, 0x0f, 0x60, 0x04, 0x7f, 0x17, 0x80, 0x02, 0x7f, 0x11, 0x90, 0x05, 0x01, +0xef, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0xff, 0x12, 0x02, 0x94, 0x90, 0x10, 0x00, +0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x2f, 0x74, 0x7f, 0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, +0x02, 0x0a, 0x02, 0x14, 0xbb, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x0d, 0xe5, 0x55, 0x60, 0x09, +0x7d, 0x03, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x80, 0x72, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, +0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x80, 0x5f, 0x90, 0x70, 0x11, 0xe0, +0x24, 0xff, 0x92, 0x17, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x5d, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, +0x0a, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x30, 0x17, 0x13, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, +0x2c, 0xf0, 0x90, 0x10, 0x2f, 0xe0, 0x54, 0xf0, 0xf5, 0x57, 0x45, 0x5d, 0xf0, 0xe4, 0x90, 0x70, +0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x02, +0x2c, 0x74, 0xff, 0xf0, 0x22, 0xe4, 0xf5, 0x30, 0xd2, 0x4f, 0x90, 0x70, 0x10, 0xe0, 0xf4, 0x60, +0x03, 0xe0, 0xf5, 0x30, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x90, 0x04, 0x14, 0x74, 0x80, +0xf0, 0x22, 0x22, 0xe5, 0x33, 0x45, 0x32, 0x60, 0x0a, 0xe5, 0x33, 0x15, 0x33, 0x70, 0x0a, 0x15, +0x32, 0x80, 0x06, 0x75, 0x32, 0x03, 0x75, 0x33, 0x1f, 0xe5, 0x33, 0x45, 0x32, 0x60, 0x03, 0x02, +0x15, 0x70, 0x20, 0x1a, 0x03, 0x02, 0x15, 0x70, 0x74, 0xa0, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, +0x4c, 0xf5, 0x83, 0xe0, 0x60, 0x7a, 0x7f, 0x7e, 0x12, 0x15, 0xde, 0xef, 0x54, 0xfe, 0x44, 0x02, +0xfd, 0x7f, 0x7e, 0x12, 0x15, 0xc4, 0xe5, 0x31, 0x7f, 0x00, 0x25, 0xe0, 0xfe, 0xef, 0x24, 0x00, +0xf5, 0x82, 0x74, 0x4d, 0x3e, 0xaf, 0x82, 0x90, 0x4c, 0xa8, 0xf0, 0xa3, 0xef, 0xf0, 0xe4, 0xf5, +0x56, 0xf5, 0x57, 0x7f, 0x7f, 0x12, 0x15, 0xde, 0x90, 0x4c, 0xa8, 0xe0, 0xfa, 0xa3, 0xe0, 0x25, +0x57, 0xf5, 0x82, 0xea, 0x35, 0x56, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x57, 0xe5, 0x57, 0x70, 0x02, +0x05, 0x56, 0xc3, 0x94, 0x80, 0xe5, 0x56, 0x94, 0x01, 0x40, 0xd8, 0x7f, 0x7e, 0x12, 0x15, 0xde, +0xef, 0x44, 0x03, 0xfd, 0x7f, 0x7e, 0x12, 0x15, 0xc4, 0x74, 0xa0, 0x25, 0x31, 0xf5, 0x82, 0xe4, +0x34, 0x4c, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0xb4, 0x08, 0x03, 0xe4, 0xf5, 0x31, +0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, +0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, +0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x3f, 0xff, 0x90, 0x70, 0x18, 0xe0, 0x4f, 0xf5, +0x3f, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e, 0x90, 0x02, 0x29, +0xf0, 0x30, 0x47, 0x04, 0xaf, 0x3f, 0x80, 0x04, 0xe5, 0x3f, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, +0xf0, 0xc2, 0x14, 0x22, 0x90, 0x10, 0x1c, 0xed, 0xf0, 0xa3, 0xef, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, +0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x58, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x22, 0x90, 0x10, +0x1d, 0xef, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x58, 0x90, 0x10, 0x1e, +0xe0, 0x20, 0xe1, 0xf3, 0xaf, 0x58, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x01, 0xe4, +0x16, 0x19, 0x00, 0x16, 0xa7, 0x04, 0x16, 0xa3, 0x08, 0x16, 0x83, 0x10, 0x16, 0x2d, 0x20, 0x16, +0x4d, 0x60, 0x16, 0x5e, 0xa0, 0x00, 0x00, 0x16, 0xa9, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, +0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x16, 0xa9, 0x80, 0x1b, 0xe5, 0x48, 0xc4, +0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, +0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49, 0x43, +0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5, 0x49, +0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, +0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, +0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, +0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, +0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x27, 0xe5, 0x42, 0xc4, 0x54, +0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5, 0x47, +0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22, 0x12, +0x1a, 0x3a, 0x12, 0x16, 0xde, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, +0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, +0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, +0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x27, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, +0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x27, +0x70, 0x05, 0x75, 0x27, 0x0c, 0x80, 0x02, 0x15, 0x27, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, +0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, +0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x27, 0x70, +0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x27, 0x70, 0x05, 0x75, 0x27, 0x07, 0x80, 0x02, 0x15, +0x27, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, +0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, +0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5, 0x3a, +0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, +0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, +0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30, 0x68, +0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, 0x80, 0x02, +0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, +0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26, 0x30, +0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, +0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, +0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x26, +0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17, 0xe5, +0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03, 0x30, +0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, +0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, +0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, +0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, +0x30, 0x40, 0x19, 0xe0, 0x64, 0x32, 0x60, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, +0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x30, 0x17, 0x0d, 0x53, +0x2e, 0xf0, 0xe5, 0x2e, 0x45, 0x5d, 0x90, 0x10, 0x2f, 0xf0, 0x80, 0x06, 0x90, 0x10, 0x2f, 0xe5, +0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x47, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x03, 0xff, +0x80, 0x02, 0xf4, 0xff, 0x8f, 0x3f, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, +0x54, 0x0f, 0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0xf8, 0x80, +0x0f, 0xd2, 0xf8, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xf8, +0x30, 0x47, 0x05, 0xaf, 0x3f, 0x02, 0x1a, 0x34, 0xe5, 0x3f, 0xf4, 0xff, 0x02, 0x1a, 0x34, 0xe5, +0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, +0x03, 0x02, 0x19, 0xa2, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x03, 0xff, 0x80, 0x02, 0xf4, 0xff, +0x8f, 0x3f, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60, +0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50, +0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a, +0xd2, 0xf9, 0xc2, 0xf8, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80, +0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, +0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0xf8, 0xc2, 0xf9, 0x80, +0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xf9, 0xc2, 0xf8, 0x80, 0x04, +0xc2, 0xf8, 0xc2, 0xf9, 0x30, 0x47, 0x04, 0xaf, 0x3f, 0x80, 0x04, 0xe5, 0x3f, 0xf4, 0xff, 0x02, +0x1a, 0x34, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x0b, 0x60, 0x03, 0x02, 0x1a, +0x39, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x03, 0xff, 0x80, 0x02, 0xf4, 0xff, 0x8f, 0x3f, 0x90, +0x02, 0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, +0x2b, 0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, +0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0xf9, 0x80, 0x3a, 0xe5, +0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xf9, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, +0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, +0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0xf9, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, +0x80, 0x01, 0xc3, 0x92, 0xf9, 0x80, 0x02, 0xc2, 0xf9, 0x30, 0x47, 0x04, 0xaf, 0x3f, 0x80, 0x04, +0xe5, 0x3f, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, +0x02, 0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x3f, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x3f, 0x22, 0xe4, +0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, +0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, +0xf5, 0x25, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a, 0x14, 0x60, 0x6b, 0x24, 0x02, 0x60, 0x03, +0x02, 0x1b, 0xd0, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, +0x20, 0xe1, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, +0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x1a, 0x65, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, +0x75, 0x51, 0x01, 0x02, 0x1b, 0xd0, 0xe5, 0x50, 0x60, 0x03, 0x02, 0x1b, 0xd0, 0x75, 0x25, 0x03, +0x02, 0x1b, 0xd0, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x1a, 0x65, +0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x1b, 0xd0, 0xe5, 0x50, 0x60, +0x03, 0x02, 0x1b, 0xd0, 0x02, 0x1b, 0xcb, 0x90, 0x02, 0x08, 0xe0, 0x30, 0xe3, 0x03, 0x02, 0x1b, +0xc7, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x60, 0x03, 0x02, 0x1b, 0xc7, 0x90, 0x12, 0x04, 0x74, +0x0a, 0xf0, 0xe5, 0x58, 0x30, 0xe3, 0x1c, 0x90, 0x00, 0x02, 0xe0, 0x30, 0xe0, 0x15, 0xe4, 0x90, +0x05, 0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, +0x12, 0x02, 0x94, 0x90, 0x13, 0x28, 0xe0, 0x90, 0x70, 0x1a, 0xf0, 0x90, 0x13, 0x29, 0xe0, 0x90, +0x70, 0x1b, 0xf0, 0x90, 0x13, 0x2b, 0xe0, 0x90, 0x70, 0x22, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, +0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0x90, 0x13, 0x2b, 0xe0, 0x54, 0xcc, 0xf0, 0xe5, 0x58, +0x30, 0xe3, 0x17, 0xe5, 0x30, 0x70, 0x13, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x05, 0xe0, +0x54, 0xf3, 0x80, 0x11, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, +0x60, 0x08, 0xe0, 0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, +0x01, 0xe0, 0x44, 0x10, 0xf0, 0x75, 0x8c, 0x80, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x12, 0x04, 0xe0, +0x44, 0x04, 0xf0, 0xe5, 0x58, 0x30, 0xe0, 0x06, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x2f, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x40, 0x17, 0x20, 0x02, 0x14, 0x20, 0x03, 0x11, 0x30, 0x4f, 0x0e, 0x90, 0x01, +0x0d, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x25, 0x01, 0x75, +0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x25, 0x03, 0xf5, 0x51, +0xe5, 0x25, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x25, 0xaf, 0x40, 0x12, +0x1c, 0xe5, 0xe5, 0x25, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, +0x0e, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x1c, 0xe5, 0xe5, +0x52, 0x14, 0x60, 0x48, 0x14, 0x60, 0x25, 0x24, 0x02, 0x60, 0x03, 0x02, 0x1c, 0xe2, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x40, 0x11, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x04, +0xf0, 0x7f, 0x0a, 0x12, 0x02, 0x94, 0x75, 0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x58, 0x30, 0xe0, +0x06, 0x90, 0x01, 0x0d, 0xe5, 0x2f, 0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, +0x12, 0x1a, 0x6a, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x02, 0x1c, 0xe2, 0xe5, 0x54, 0x60, 0x03, +0x02, 0x1c, 0xe2, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0xe0, 0x54, 0xef, 0xf0, 0xe4, 0xf5, +0x8c, 0xe5, 0x58, 0x54, 0x18, 0x60, 0x1e, 0x90, 0x70, 0x1a, 0xe0, 0x90, 0x13, 0x28, 0xf0, 0x90, +0x70, 0x1b, 0xe0, 0x90, 0x13, 0x29, 0xf0, 0xa3, 0x74, 0x05, 0xf0, 0x90, 0x70, 0x22, 0xe0, 0x90, +0x13, 0x2b, 0xf0, 0x80, 0x11, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, +0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0x30, 0xe3, +0x1d, 0x90, 0x00, 0x02, 0xe0, 0x30, 0xe0, 0x16, 0x90, 0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, +0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12, 0x02, 0x94, 0x90, 0x02, +0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, +0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x1c, 0xe5, 0x30, 0x03, 0x02, +0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, +0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, +0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, +0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x43, +0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, +0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x25, +0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, +0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0xc2, +0x05, 0xd2, 0xaf, 0x22, 0x22, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x5b, 0xd2, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/fpga/fpga_ctl.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/fpga/fpga_ctl.h new file mode 100644 index 000000000..277d00c23 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/fpga/fpga_ctl.h @@ -0,0 +1,27 @@ + +#ifndef __FPGA_CTL_H__ +#define __FPGA_CTL_H__ + +struct fpga_ctrl { + int tx_kick_cnt; + int phy_rates; + int tx_data_phy; + u8 tx_data_bw; + u8 tx_data_ldpc; + u8 tx_data_mcs; + u8 tx_data_gi; + u8 tx_data_stbc; + int rx_data_phy; + u8 rx_data_bw; + u8 rx_data_ldpc; + u8 rx_data_mcs; + u8 rx_data_gi; + u8 rx_data_stbc; + u8 data_basize; + u8 fpga_on; + u8 fpga_tr_stop; + u8 vco_cal; +}; + +#endif + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/frame_hdr.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/frame_hdr.h new file mode 100644 index 000000000..9211c6146 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/frame_hdr.h @@ -0,0 +1,81 @@ +#ifndef __FRAME_HDR_H__ +#define __FRAME_HDR_H__ + +#define HDR_TRANS_LEN 50 + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _WIFI_INFO_STRUCT{ + UINT32 more_data:1; + UINT32 wep:1; + UINT32 ps:1; + UINT32 qos:1; + UINT32 eosp:1; + UINT32 tid:4; + UINT32 mode:2; + UINT32 vlan:1; + UINT32 rev:3; + UINT32 bssidx:4; + UINT32 seq_num:12; +}WIFI_INFO_STRUCT; +#else +typedef struct GNU_PACKED _WIFI_INFO_STRUCT{ + UINT32 seq_num:12; + UINT32 bssidx:4; + UINT32 rev:3; + UINT32 vlan:1; + UINT32 mode:2; + UINT32 tid:4; + UINT32 eosp:1; + UINT32 qos:1; + UINT32 rdg:1; + UINT32 ps:1; + UINT32 wep:1; + UINT32 more_data:1; +}WIFI_INFO_STRUCT; +#endif /* RT_BIG_ENDIAN */ + +WIFI_INFO_STRUCT wifi_info[] = { + /* mode 1 -> AP, mode 2 --> STA */ + /* seq_num, bssidx, rsv, vlan, mode, tid, eosp, qos, rdg, ps, wep, more_data*/ + {0xff, 5, 0, 1, 1, 3, 0, 1, 0, 0, 0, 0}, +}; + + +UINT8 Input_Frame_Hdr[][HDR_TRANS_LEN] = { +/*type, len, vlan, wcid */ +/************************************ AP LLC/SNAP *********************************/ +/************************************ WDS LLC/SNAP ******************************/ +{0, 34, 0, 1, 0x08, 0x03, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x02, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x50, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x50, 0x02, 0x00, 0xee, 0xee, 0xee, + 0xee, 0xee, 0x00, 0x00, 0x08, 0x00}, /* AP w/o LLC - Ether II*/ + +}; + +UINT8 Hdr_Bssid[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; + +UINT8 Hdr_Wcid[][6] = { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, //0 + {0x00, 0x77, 0x77, 0x77, 0x77, 0x77}, //1 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x01}, //2 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x02}, //3 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x03}, //4 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x04}, //5 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x05}, //6 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x06}, //7 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x07}, //8 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x08}, //9 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x09}, //a + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0a}, //b + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0b}, //c + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0c}, //d + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0d}, //e + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0e}, //f + }; +UINT8 MAC_WCID[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +//UINT32 RX_Black_List[] = {0x0d898e88}; /* EAPOL 888E, TDLS 890D */ +//UINT32 RX_Black_List[] = {0x888e0800}; /* EAPOL 888E, TDLS 890D */ +UINT32 RX_Black_List[] = {}; /* EAPOL 888E, TDLS 890D */ +UINT32 TCI[] = {0x10021001, 0x10041003, 0x10061005, 0x10081007}; +UINT32 RX_WCID_En[] = {0xFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/frq_cal.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/frq_cal.h new file mode 100644 index 000000000..95fb348d5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/frq_cal.h @@ -0,0 +1,91 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + Miniport header file for eeprom related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __FRQCAL_H__ +#define __FRQCAL_H__ + +/* */ +/* The frequency calibration control */ +/* */ +typedef struct _FREQUENCY_CALIBRATION_CONTROL +{ + BOOLEAN bEnableFrequencyCalibration; /* Enable the frequency calibration algorithm */ + + BOOLEAN bSkipFirstFrequencyCalibration; /* Avoid calibrating frequency at the time the STA is just link-up */ + BOOLEAN bApproachFrequency; /* Approach the frequency */ + CHAR AdaptiveFreqOffset; /* Adaptive frequency offset */ + CHAR LatestFreqOffsetOverBeacon; /* Latest frequency offset from the beacon */ + CHAR BeaconPhyMode; /* Latest frequency offset from the beacon */ + +} FREQUENCY_CALIBRATION_CONTROL, *PFREQUENCY_CALIBRATION_CONTROL; + +#define RTMP_FREQ_CAL_DISABLE(__pAd) \ + __pAd->FreqCalibrationCtrl.bEnableFrequencyCalibration = FALSE; + +/* */ +/* Invalid frequency offset */ +/* */ +#define INVALID_FREQUENCY_OFFSET -128 + +/* */ +/* The upperbound/lowerbound of the frequency offset */ +/* */ +#define UPPERBOUND_OF_FREQUENCY_OFFSET 127 +#define LOWERBOUND_OF_FREQUENCY_OFFSET -127 + + +/*#ifdef RT5390 */ +/* */ +/* The trigger point of the high/low frequency */ +/* */ +#define HIGH_FREQUENCY_TRIGGER_POINT_OFDM 20 +#define LOW_FREQUENCY_TRIGGER_POINT_OFDM -20 +#define HIGH_FREQUENCY_TRIGGER_POINT_CCK 4 +#define LOW_FREQUENCY_TRIGGER_POINT_CCK -4 + + +/* */ +/* The trigger point of decreasng/increasing the frequency offset */ +/* */ +#define DECREASE_FREQUENCY_OFFSET_OFDM 10 +#define INCREASE_FREQUENCY_OFFSET_OFDM -10 +#define DECREASE_FREQUENCY_OFFSET_CCK 2 +#define INCREASE_FREQUENCY_OFFSET_CCK -2 +/*#endif // RT5390 */ +/* */ +/* The trigger point of decreasng/increasing the frequency offset */ +/* */ +#define DECREASE_FREQUENCY_OFFSET 3 +#define INCREASE_FREQUENCY_OFFSET -3 + +/* */ +/* Frequency calibration period */ +/* */ + +#define FREQUENCY_CALIBRATION_PERIOD 100 + +#endif /* __FRQCAL_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ft.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ft.h new file mode 100644 index 000000000..ff650e293 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ft.h @@ -0,0 +1,1505 @@ +/**************************************************************************** + * 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. + **************************************************************************** + + Abstract: + + + */ + +#ifdef DOT11R_FT_SUPPORT + + +#ifndef __FT_H +#define __FT_H + +#include "link_list.h" +#include "ft_cmm.h" + +#define IN +#define OUT +#define INOUT + +/* Macro */ +#define IS_FT_STA(__A) ((__A)->MdIeInfo.Len != 0) +#define IS_FT_ACTION_FRAME(__A) ((*(__A + 13) == 0x89)&&(*(__A + 14) == 0x0d)) + +/* ASCII to Integer */ +#define FT_ARG_ATOI(__pArgv) simple_strtol((PSTRING) __pArgv, 0, 10) + +extern UINT32 FT_KDP_MemAllocNum, FT_KDP_MemFreeNum; +#define FT_MEM_ALLOC(__pAd, __pMem, __Size) \ + os_alloc_mem(__pAd, (UCHAR **)(__pMem), __Size); \ + FT_KDP_MemAllocNum++; +#define FT_MEM_FREE(__pAd, __Mem) \ + { os_free_mem(__pAd, __Mem); \ + FT_KDP_MemFreeNum++; } + +/* atoi & atoh */ +#define FT_ARG_ATOI(__pArgv) simple_strtol((PSTRING) __pArgv, 0, 10) +#define FT_ARG_ATOH(__Buf, __Hex) AtoH((PSTRING) __Buf, __Hex, 1) + +#ifdef CONFIG_AP_SUPPORT +/* linked list, please reference to link_list.h */ +#define FT_KDP_SIGNAL RT_SIGNAL_STRUC + +#define FT_KDP_IOCTL_KEY_REQ(__pAd, __pInfo, __InfoLen) \ +{ \ + UINT32 __PeerIP; \ + memcpy(&__PeerIP, __pInfo, FT_IP_ADDRESS_SIZE); \ + FT_KDP_KeyRequestToUs(__pAd, __PeerIP, \ + (__pInfo)+FT_IP_ADDRESS_SIZE, \ + (FT_KDP_EVT_KEY_ELM *) \ + ((__pInfo)+FT_IP_ADDRESS_SIZE+FT_NONCE_SIZE)); \ +} + +/* Macros relative to R1KH Table. */ +#define FT_R1NAME_HASH(_Data) (_Data[0] ^ _Data[1] ^ _Data[2] ^_Data[3] \ + ^ _Data[4] ^ _Data[5] ^_Data[6] ^ _Data[7] \ + ^ _Data[8] ^_Data[9] ^ _Data[10] ^ _Data[11] \ + ^_Data[12] ^ _Data[13] ^ _Data[14] ^_Data[15]) +#define FT_R1KH_HASH_INDEX(_Data) (FT_R1NAME_HASH(_Data) \ + % (FT_R1KH_ENTRY_HASH_TABLE_SIZE)) + +typedef struct GNU_PACKED _FT_KDP_PMK_KEY_INFO { + + UCHAR R0KHID[FT_KDP_R0KHID_MAX_SIZE]; + UCHAR R0KHIDLen; + UCHAR PMKR0Name[FT_KDP_WPA_NAME_MAX_SIZE]; /* an ID that names the PMK-R0 */ + + UCHAR R1KHID[FT_KDP_R1KHID_MAX_SIZE]; + UCHAR S1KHID[FT_KDP_S1KHID_MAX_SIZE]; + + /* reserved field */ + UCHAR RSV[4]; + +} FT_KDP_PMK_KEY_INFO; + +#ifdef IAPP_SUPPORT +typedef struct GNU_PACKED _RT_SIGNAL_STRUC { + + /* IEEE80211R_SUPPORT */ + VOID *pNext; /* point to next signal */ + + UINT16 Sequence; + UCHAR MacAddr[ETH_ALEN]; + UCHAR CurrAPAddr[ETH_ALEN]; + +#define FT_KDP_SIG_NOTHING 0x00 /* no signal */ +#define FT_KDP_SIG_IAPP_ASSOCIATION 0x01 /* a station has associated */ +#define FT_KDP_SIG_IAPP_REASSOCIATION 0x02 /* a station has re-associated */ +#define FT_KDP_SIG_TERMINATE 0x03 /* terminate the daemon */ + +#define FT_KDP_SIG_FT_ASSOCIATION 0x50 /* a FT station has associated */ +#define FT_KDP_SIG_FT_REASSOCIATION 0x51 /* a FT station has re-associated */ +#define FT_KDP_SIG_KEY_TIMEOUT 0x52 /* PMK-R1 KEY Timeout */ +#define FT_KDP_SIG_KEY_REQ 0x53 /* request PMK-R1 KEY from R0KH */ +#define FT_KDP_SIG_ACTION 0x54 /* forward FT Action frame to DS */ + +#define FT_KDP_SIG_AP_INFO_REQ 0x70 /* request neighbor AP info. */ +#define FT_KDP_SIG_AP_INFO_RSP 0x71 /* response my AP info. */ + +/* FT KDP internal use */ +#define FT_KDP_SIG_KEY_REQ_AUTO 0xA0 /* request PMK-R1 KEY from R0KH */ +#define FT_KDP_SIG_KEY_RSP_AUTO 0xA1 /* response PMK-R1 KEY to R1KH */ +#define FT_KDP_SIG_INFO_BROADCAST 0xB0 /* broadcast our AP information */ + +#define FT_KSP_SIG_DEBUG_TRACE 0xC0 /* enable debug flag to TRACE */ + UCHAR Sig; + + UCHAR MacAddrSa[ETH_ALEN]; + + /* IEEE80211R_SUPPORT */ + /* the first 6B are FT_KDP_EVT_HEADER */ + /* + For FT_KDP_SIG_NOTHING: nothing + For FT_KDP_SIG_IAPP_ASSOCIATION:nothing + For FT_KDP_SIG_REASSOCIATION: nothing + For FT_KDP_SIG_TERMINATE: nothing + For FT_KDP_SIG_FT_ASSOCIATION: nothing + FT_KDP_SIG_FT_REASSOCIATION: nothing + For FT_KDP_SIG_KEY_TIMEOUT: it is + For FT_KDP_SIG_KEY_REQ_AUTO: it is FT_KDP_EVT_KEY_REQ + For FT_KDP_SIG_KEY_RSP_AUTO: it is FT_KDP_SIG_KEY_RSP + */ + UCHAR Reserved[3]; /* let address of Content[] 4B align */ + UCHAR Content[1024]; /* signal content */ + +/* 1024 means size of Content[] */ +#define RT_SIGNAL_STRUC_HDR_SIZE (sizeof(RT_SIGNAL_STRUC)-1024) +} RT_SIGNAL_STRUC, *PRT_SIGNAL_STRUC; + +/* definition of signal */ +#define SIG_NONE 0 /* same as FT_KDP_SIG_NOTHING */ +#define SIG_ASSOCIATION 1 /* same as FT_KDP_SIG_ASSOCIATION */ +#define SIG_REASSOCIATION 2 /* same as FT_KDP_SIG_REASSOCIATION */ +#endif /* IAPP_SUPPORT */ + + +/* event */ +#define FT_KDP_EVENT_INFORM(__pAd, __ApIdx, __EventId, __pEvent, __EventLen, __CB) \ + FT_KDP_EventInform(__pAd, __ApIdx, __EventId, (VOID *)__pEvent, __EventLen, 0, __CB) + +/* ----- KDP Linked List ----- */ +#define FT_KDP_EVT_LIST_INSERT_TAIL(__pAd, __pList, __pEntry) \ + { \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + insertTailList((__pList), (LIST_ENTRY *)(__pEntry)); \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +#define FT_KDP_EVT_LIST_REMOVE_HEAD(__pAd, __pList, __pEntry) \ + { \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + __pEntry = (FT_KDP_SIGNAL *)removeHeadList((__pList)); \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +#define FT_KDP_EVT_LIST_SIZE_GET(__pAd, __pList, __Size) \ + { \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + __Size = getListSize((__pList)); \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +#define FT_KDP_EVT_LIST_EMPTY(__pAd, __pList) \ + { \ + FT_KDP_SIGNAL *__pEntry; \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + __pEntry = (FT_KDP_SIGNAL *)removeHeadList((__pList)); \ + while(__pEntry != NULL) \ + { \ + FT_MEM_FREE(__pAd, __pEntry); \ + __pEntry = (FT_KDP_SIGNAL *)removeHeadList((__pList)); \ + } \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +/* general */ +#define FT_KDP_CB ((FT_KDP_CTRL_BLOCK *)pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK) + +typedef struct GNU_PACKED _FT_KDP_EVT_HEADER +{ + UINT32 EventLen; + UINT32 PeerIpAddr; /* used in daemon, open TCP/IP socket to the IP */ +} FT_KDP_EVT_HEADER; + +typedef struct GNU_PACKED _FT_KDP_EVT_ASSOC +{ + /* same as IEEE802.11f IAPP */ + UINT16 SeqNum; + UCHAR MacAddr[ETH_ALEN]; +} FT_KDP_EVT_ASSOC; + +typedef struct GNU_PACKED _FT_KDP_EVT_REASSOC +{ + UINT16 SeqNum; + UCHAR MacAddr[ETH_ALEN]; + UCHAR OldApMacAddr[ETH_ALEN]; +} FT_KDP_EVT_REASSOC; + +typedef struct GNU_PACKED _FT_KDP_EVT_KEY_ELM +{ + /* must be 65535, Proprietary Information */ +#define FT_KDP_ELM_ID_PRI 65535 + UINT16 ElmId; + +#define FT_KDP_ELM_PRI_LEN (sizeof(FT_KDP_EVT_KEY_ELM)-4) + UINT16 ElmLen; + + /* must be 0x00 0x0E 0x2E, RALINK */ +#define FT_KDP_ELM_PRI_OUI_0 0x00 +#define FT_KDP_ELM_PRI_OUI_1 0x0E +#define FT_KDP_ELM_PRI_OUI_2 0x2E +#define FT_KDP_ELM_PRI_OUI_SIZE 3 + UCHAR OUI[3]; + + /* station MAC */ + UCHAR MacAddr[ETH_ALEN]; + UCHAR RSV[3]; + + /* used in request */ + FT_KDP_PMK_KEY_INFO KeyInfo; + + /* used in response */ + UCHAR PMKR1Name[FT_KDP_WPA_NAME_MAX_SIZE]; /* an ID that names the PMK-R1 */ + UCHAR PMKR1[FT_KDP_PMKR1_MAX_SIZE]; /* PMK R1 Key */ + UCHAR R0KH_MAC[ETH_ALEN]; /* MAC of R0KH */ + + /* + During a Fast BSS Transition a non-AP STA shall negotiate the same + pairwise cipher suite with Target APs as was negotiated in the FT + Initial Mobility Domain association. The target AP shall verify + that the same pairwise cipher suite selector is used, using the + pairwise cipher suite selector value in the PMK-R1 SA received from + the R0KH. + */ + UCHAR PairwisChipher[4]; + UCHAR AkmSuite[4]; + + UINT32 KeyLifeTime; + UINT32 ReassocDeadline; +} FT_KDP_EVT_KEY_ELM; + +typedef struct _FT_KDP_EVT_ACTION +{ + UCHAR RequestType; + UCHAR MacDa[ETH_ALEN]; + UCHAR MacSa[ETH_ALEN]; + UCHAR MacAp[ETH_ALEN]; +} FT_KDP_EVT_ACTION; + +/* global function prototype for non-11r modules */ +/* +======================================================================== +Routine Description: + Initialize FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_Init( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Release FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Get a event. + +Arguments: + pAd - WLAN control block pointer + **pFtKdp - the queued event; if NULL, no event is queued. + +Return Value: + None + +Note: + Used in IOCTL from FT KDP daemon. +======================================================================== +*/ +VOID FT_KDP_EventGet( + IN PRTMP_ADAPTER pAd, + OUT FT_KDP_SIGNAL **pFtKdp); + +/* +======================================================================== +Routine Description: + Inform us a event occurs. + +Arguments: + pAd - WLAN control block pointer + ApIdx - MBSS ID + EventId - which event, such as FT_KDP_SIG_FT_ASSOCIATION + *pEvent - event body + EventLen - event body length + PeerIP - peer IP address + pCB - for special use (such as FT_KDP_SIG_ACTION) + +Return Value: + None + +Note: + EventId *pEvent + -------------------------------------------------------------------- + FT_KDP_SIG_FT_ASSOCIATION FT_KDP_EVT_ASSOC + FT_KDP_SIG_FT_REASSOCIATION FT_KDP_EVT_REASSOC + FT_KDP_SIG_KEY_TIMEOUT yet implement + FT_KDP_SIG_KEY_REQ FT_KDP_EVT_KEY_ELM + FT_KDP_SIG_ACTION WLAN Frame Body (Start from Category field) + pCB == FT_KDP_EVT_ACTION + +======================================================================== +*/ +VOID FT_KDP_EventInform( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + IN UCHAR EventId, + IN VOID *pEvent, + IN UINT16 EventLen, + IN UINT32 PeerIP, + IN VOID *pCB); + +/* +======================================================================== +Routine Description: + Inform us a AP request the key. + +Arguments: + pAd - WLAN control block pointer + PeerIP - the IP of R0KH + *pNonce - the nonce for key request + *pEvtKeyReq - information for key request + +Return Value: + TRUE - request ok + FALSE - can not find the IP of R0KH + +Note: + If PeerIP == 0, search its IP from our information record. +======================================================================== +*/ +BOOLEAN FT_KDP_KeyRequestToUs( + IN PRTMP_ADAPTER pAd, + IN UINT32 PeerIP, + IN UCHAR *pNonce, + IN FT_KDP_EVT_KEY_ELM *pEvtKeyReq); + +/* +======================================================================== +Routine Description: + Inform us a AP response the key. + +Arguments: + pAd - WLAN control block pointer + *pInfo - key information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Nonce (8B) + FT_KDP_EVT_KEY_ELM structure +======================================================================== +*/ +VOID FT_KDP_KeyResponseToUs( + IN PRTMP_ADAPTER pAd, + IN UINT8 *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Inform us a FT station joins the BSS domain. + +Arguments: + pAd - WLAN control block pointer + *pInfo - station information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Station MAC (6B) +======================================================================== +*/ +VOID FT_KDP_StationInform( + IN PRTMP_ADAPTER pAd, + IN UINT8 *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Set the encryption/decryption key. + +Arguments: + pAd - WLAN control block pointer + *pKey - the key + KeyLen - the key length + +Return Value: + None + +Note: + Key length can be 8B ~ 64B. +======================================================================== +*/ +VOID FT_KDP_CryptKeySet( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pKey, + IN INT32 KeyLen); + +/* +======================================================================== +Routine Description: + Encrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_DataEncrypt( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pData, + IN UINT32 *pDataLen); + +/* +======================================================================== +Routine Description: + Decrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_DataDecrypt( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pData, + IN UINT32 *pDataLen); + +/* +======================================================================== +Routine Description: + Broadcast our AP information. + +Arguments: + SystemSpecific1 - no use + FunctionContext - WLAN control block pointer + SystemSpecific2 - no use + SystemSpecific3 - no use + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_KDP_InfoBroadcast( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef FT_KDP_FUNC_INFO_BROADCAST +/* +======================================================================== +Routine Description: + Receive a neighbor report from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborReportHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + +/* +======================================================================== +Routine Description: + Receive a neighbor request from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_KDP_NeighborRequestHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Receive a neighbor response from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_KDP_NeighborResponseHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Handle a RRB frame from DS. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_RRB_ActionHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +BOOLEAN FT_QueryKeyInfoForKDP( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + OUT FT_KDP_EVT_KEY_ELM *pEvtKeyReq); + +#endif /* CONFIG_AP_SUPPORT */ + +/* +======================================================================== +Routine Description: + Initialize FT RIC Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_RIC_Init( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Release FT RIC Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_RIC_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + IO control handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + None + +Note: + All test commands are listed as follows: + iwpriv ra0 set ft=[cmd id]_[arg1]_[arg2]_......_[argn] + [cmd id] = xx, such as 00, 01, 02, 03, ... +======================================================================== +*/ +INT FT_Ioctl( + IN PRTMP_ADAPTER pAd, + IN PSTRING pArgvIn); + +/* +======================================================================== +Routine Description: + FT insert MDIE to packet frame for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_InsertMdIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pMdId, + IN FT_CAP_AND_POLICY FtCapPlc); + +/* +======================================================================== +Routine Description: + FT configuration handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ + VOID FT_CfgInitial( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + FT function initialization for IEEE802.11r. + FT_Init'll allocate tables, control blocks that FT needed. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_Init( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + FT function release for IEEE802.11r. + Free all tables, control blocks which FT_Init allocated. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Req handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +USHORT FT_AuthReqHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_EnqueueAuthReply( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pRcvHdr, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT StatusCode, + IN PFT_MDIE_INFO pMdIeInfo, + IN PFT_FTIE_INFO pFtIeInfo, + IN PFT_RIC_INFO pRicInfo, + IN PUCHAR pRsnIe, + IN UCHAR RsnIeLen); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +USHORT FT_AuthConfirmHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf); + +/* +======================================================================== +Routine Description: + FT Peer Association Request handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +USHORT FT_AssocReqHandler( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN PFT_CFG pFtCfg, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pPeer_FtInfo, + OUT PFT_INFO pFtInfoBuf); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_KDP_KeyResponse( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + FT Peer Resource Request handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +UINT32 FT_RIC_ResourceRequestHandle( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pCdb, + IN UCHAR *pBufReq, + IN UINT32 ReqLen, + OUT UCHAR *pBufRsp, + OUT UINT32 *pRspLen); + + +/* +======================================================================== +Routine Description: + FT Peer Resource Request handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +UINT32 BA_ResourceAllocate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR *pBufRscReq, + OUT UCHAR *pBufRscRsp, + OUT ULONG *pBufRspLen); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +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); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +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); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_FTIE_InsertGTKSubIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pGtkSubIe, + IN UINT8 GtkSubIe_len); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_InsertTimeoutIntervalIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN FT_TIMEOUT_INTERVAL_TYPE Type, + IN UINT32 TimeOutValue); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabInit( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +INT FT_R1khEntryInsert( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPmkR0Name, + IN PUINT8 pPmkR1Name, + IN PUINT8 pPmkR1Key, + IN PUINT8 pPairwisChipher, + IN PUINT8 pAkmSuite, + IN UINT32 KeyLifeTime, + IN UINT32 RassocDeadline, + IN PUINT8 pR0khId, + IN UINT8 R0khIdLen, + IN PUINT8 pStaMac); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PFT_R1HK_ENTRY pEntry); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabDestroy( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +PFT_R1HK_ENTRY FT_R1khEntryTabLookup( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPMKR1Name); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillMdIeInfo( + PEID_STRUCT eid_ptr, + PFT_MDIE_INFO pMdIeInfo); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillFtIeInfo( + PEID_STRUCT eid_ptr, + PFT_FTIE_INFO pFtIeInfo); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FtAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_RrbHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPktSrc, + IN INT32 PktLen); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1KHInfoMaintenance( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Display all R0KH information. + +Arguments: + pAd - WLAN control block pointer + *pArgv - input parameters + +Return Value: + TRUE + +Note: +======================================================================== +*/ +INT FT_KDP_CMD_R0KH_InfoShow( + IN PRTMP_ADAPTER pAd, + IN PSTRING pArgv); + +VOID FT_MakeFtActFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ActType, + IN PUCHAR pStaMac, + IN PUCHAR pTargetApMac, + IN UINT16 StatusCode, + IN PFT_INFO pFtInfo); + +VOID FT_DerivePMKR0( + IN PUINT8 xxkey, + IN INT xxkey_len, + IN PUINT8 ssid, + IN INT ssid_len, + IN PUINT8 mdid, + IN PUINT8 r0khid, + IN INT r0khid_len, + IN PUINT8 s0khid, + OUT PUINT8 pmkr0, + OUT PUINT8 pmkr0_name); + +VOID FT_DerivePMKR1Name( + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1_name); + +VOID FT_DerivePMKR1( + IN PUINT8 pmkr0, + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1, + OUT PUINT8 pmkr1_name); + +VOID FT_DerivePTK( + IN PUINT8 pmkr1, + IN PUINT8 pmkr1_name, + IN PUINT8 a_nonce, + IN PUINT8 s_nonce, + IN PUINT8 bssid, + IN PUINT8 sta_mac, + IN UINT key_len, + OUT PUINT8 ptk, + OUT PUINT8 ptk_name); + +VOID FT_CalculateMIC( + IN PUINT8 sta_addr, + IN PUINT8 ap_addr, + IN PUINT8 kck, + IN UINT8 seq, + IN PUINT8 rsnie, + IN UINT8 rsnie_len, + IN PUINT8 mdie, + IN UINT8 mdie_len, + IN PUINT8 ftie, + IN UINT8 ftie_len, + IN PUINT8 ric, + IN UINT8 ric_len, + OUT PUINT8 mic); + +#ifdef CONFIG_STA_SUPPORT +void FT_OTA_AuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID FT_OTA_MlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTA_PeerAuthRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTA_PeerAuthAckAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTA_InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTA_AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_FT_OTA_AUTH_REQ_STRUCT *pFtOtaAuthReq, + IN PUCHAR pAddr, + IN USHORT Alg, + IN PDOT11R_CMN_STRUC pCmmDot11rCfg); + +VOID FT_FTIeParse( + IN UINT8 FtIeLen, + IN PFT_FTIE pFtIe, + OUT PUCHAR pR1KH_Id, + OUT UCHAR *GTKLen, + OUT PUCHAR pGTK, + OUT UCHAR *R0KH_IdLen, + OUT PUCHAR pR0KH_Id); + +void FT_OTD_StateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID FT_OTD_ReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTD_PeerRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTD_PeerAckAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTD_InvalidStateWhenFt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID FT_OTD_ActParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_FT_REQ_STRUCT *FtReq, + IN PUCHAR pAddr, + IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, + IN PFT_MDIE_INFO FtMdieInfo, + IN PFT_FTIE_INFO FtFtieInfo, + IN UCHAR VarIeLen, + IN PUCHAR pVarIe); + +BOOLEAN FT_CheckForRoaming( + IN PRTMP_ADAPTER pAd); + +BOOLEAN FT_GetMDIE( + IN PNDIS_802_11_VARIABLE_IEs pVIE, + IN USHORT LengthVIE, + OUT FT_MDIE_INFO *pMdIeInfo); + +BOOLEAN FT_ExtractGTKSubIe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_FTIE_INFO pFtInfo); + +VOID FT_ConstructAuthReqInRsn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +/* +======================================================================== +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 FT_RIC_ResourceRequestStart( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +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 FT_RIC_ResourceRequestEnd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pApMac); + +/* +======================================================================== +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 FT_RIC_ResourceRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pApMac, + IN UCHAR *pBufReq, + IN UINT32 ReqMaxLen); + +/* +======================================================================== +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 FT_RIC_ResourceResponseHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pApMac, + IN UCHAR *pBufRsp, + IN UINT32 RspLen, + OUT FT_RIC_STATUS *pRspStatus); +#endif /* CONFIG_STA_SUPPORT */ + +void FT_rtmp_read_parameters_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING pBuffer); + +INT Set_FT_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_FT_Mdid( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_FT_R0khid( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_FT_RIC( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_FT_OTD( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_FTConfig_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#endif /* __FT_H */ +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ft_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ft_cmm.h new file mode 100644 index 000000000..321f98a1c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ft_cmm.h @@ -0,0 +1,371 @@ +/**************************************************************************** + * 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: + + Define all structures, data types that rtmp.h needed in this file. Don't + put any sturctures and functions definition which refer to RTMP_ADAPTER + Here. + + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + + +#ifndef __FT_CMM_H__ +#define __FT_CMM_H__ + +#include "dot11r_ft.h" +#include "dot11i_wpa.h" + + +/* ========================================================================== */ +/* Definition */ +#define IS_FT_RSN_STA(_pEntry) \ + ((_pEntry) && IS_ENTRY_CLIENT(_pEntry) && (_pEntry->MdIeInfo.Len != 0) && (_pEntry->RSNIE_Len > 0)) + +#define FT_SET_MDID(__D, __S) \ + NdisMoveMemory((PUCHAR)(__D), (PUCHAR)(__S), FT_MDID_LEN) + +#define FT_MDID_EQU(__D, __S) (memcmp((__D), (__S), FT_MDID_LEN) == 0) + +#ifdef CONFIG_STA_SUPPORT +#define FT_OTD_RESPONSE 1 +#define FT_OTA_RESPONSE 2 + +/* */ +/* STA's FT OTD State machine: states, events, total function # */ +/* */ +#define FT_OTD_IDLE 0 +#define FT_OTD_WAIT_SEQ2 1 +#define FT_OTD_WAIT_SEQ4 2 +#define FT_OTD_MAX_STATE 3 + +#define FT_OTD_MACHINE_BASE 0 +#define FT_OTD_MT2_MLME_REQ 0 +#define FT_OTD_MT2_PEER_EVEN 1 +#define FT_OTD_MT2_TIMEOUT 2 +#define FT_OTD_MAX_MSG 3 + +#define FT_OTD_FUNC_SIZE (FT_OTD_MAX_STATE * FT_OTD_MAX_MSG) + +/* */ +/* STA's FT OTA AUTHENTICATION state machine: states, evvents, total function # */ +/* */ +#define FT_OTA_AUTH_REQ_IDLE 0 +#define FT_OTA_AUTH_WAIT_RESP 1 +#define FT_OTA_AUTH_WAIT_ACK 2 +#define FT_OTA_MAX_AUTH_STATE 3 + +#define FT_OTA_AUTH_MACHINE_BASE 0 +#define FT_OTA_MT2_MLME_AUTH_REQ 0 +#define FT_OTA_MT2_PEER_AUTH_EVEN 1 +#define FT_OTA_MT2_AUTH_TIMEOUT 2 +#define FT_OTA_MAX_AUTH_MSG 3 + +#define FT_OTA_AUTH_FUNC_SIZE (FT_OTA_MAX_AUTH_STATE * FT_OTA_MAX_AUTH_MSG) +#endif /* CONFIG_STA_SUPPORT */ + +/* ----- General ----- */ +#define FT_KDP_FUNC_SOCK_COMM /* used socket to communicate with driver */ +#define FT_KDP_FUNC_R0KH_IP_RECORD /* used to keep IP of any R0KH */ +/*#define FT_KDP_FUNC_INFO_BROADCAST broadcast my AP information periodically */ +#define FT_KDP_TEST + +#define FT_KDP_RALINK_PASSPHRASE "Ralink" +#define FT_KDP_KEY_DEFAULT "12345678" +#define FT_KDP_KEY_ENCRYPTION_EXTEND 8 /* 8B for AES encryption extend size */ +#define FT_DEFAULT_MDID "RT" + +#define FT_REASSOC_DEADLINE 20 + +#define FT_KDP_INFO_BC_PERIOD_TIME 1000 /* 1s */ + +#define IAPP_ETH_PRO 0xEEEE + +/* key information */ +#define FT_IP_ADDRESS_SIZE 4 +#define FT_NONCE_SIZE 8 + +#define FT_KDP_WPA_NAME_MAX_SIZE 16 +#define FT_KDP_R0KHID_MAX_SIZE 48 +#define FT_KDP_R1KHID_MAX_SIZE 6 +#define FT_KDP_S1KHID_MAX_SIZE 6 +#define FT_KDP_PMKR1_MAX_SIZE 32 /* 256-bit key */ + +#define FT_R1KH_ENTRY_TABLE_SIZE 64 +#define FT_R1KH_ENTRY_HASH_TABLE_SIZE FT_R1KH_ENTRY_TABLE_SIZE + +/* ----- FT KDP ----- */ +#define FT_KDP_EVENT_MAX 10 /* queue max 10 events */ + +/* ----- FT RIC ----- */ +#define MAX_RICIES_LEN 255 + + +/* ========================================================================== */ +/* FT user configuration. */ + +/* ethernet header */ +typedef struct _FT_DRV_ETH_HEADER { + + UCHAR DA[ETH_ALEN]; + UCHAR SA[ETH_ALEN]; + UINT16 Len; + +} GNU_PACKED FT_DRV_ETH_HEADER; + +/* R0KH information record */ +typedef struct _FT_KDP_R0KH_INFO { + + struct _FT_KDP_R0KH_INFO *pNext; + + UCHAR R0KHID[FT_KDP_R0KHID_MAX_SIZE]; + UCHAR MAC[ETH_ALEN]; + UINT32 IP; + + ULONG TimeUpdate; + +} FT_KDP_R0KH_INFO; + +/* FT KDP Control Block */ +typedef struct _FT_KDP_CTRL_BLOCK { + + /* used to record all known R0KH information in the DS */ +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +#define FT_KDP_R0KH_INFO_MAX_SIZE 256 + FT_KDP_R0KH_INFO *R0KH_InfoHead; + FT_KDP_R0KH_INFO *R0KH_InfoTail; + UINT32 R0KH_Size; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* if the signal context is got from FT KDP daemon */ + struct _LIST_HEADR EventList; +#endif /* FT_KDP_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_INFO_BROADCAST + RALINK_TIMER_STRUCT TimerReport; +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + + /* used to encrypt/decrypt the DS packet */ + UCHAR CryptKey[100]; +} FT_KDP_CTRL_BLOCK; + +/* FT RIC Control Block */ +#ifdef CONFIG_STA_SUPPORT +typedef struct _FT_RIC_STATUS { + + UCHAR AP_MAC[ETH_ALEN]; + + BOOLEAN FlgHasBaResource; /* TRUE: exist BA resource request */ + BOOLEAN FlgIsBaAccepted; /* TRUE: BLOCK ACK resource is accepted */ + + UCHAR TspecNumberOfAccepted; + UCHAR TspecNumberOfRequested; + + UINT32 TspecMediumTimeTotalCur; /* 32-us */ + UINT32 TspecMediumTimeTotalNew; /* 32-us */ + + UCHAR UnknownRDIE; /* number of RDIE with wrong Identifier or resource */ + +} FT_RIC_STATUS; + +typedef struct _FT_RIC_STATUS_TSPEC { + + BOOLEAN FlgIsValid; /* TRUE: valid */ + BOOLEAN FlgIsAccepted; /* TRUE: accepted */ + UCHAR RDIE_Identifier; + UINT16 MedimumTime; /* 32-us, maybe 0 for dnlink */ + +} FT_RIC_STATUS_TSPEC; + +typedef struct _FT_RIC_AP { + + struct _FT_RIC_AP *pNext; + + /* + 11r D9.0, 11A.11.3.2 AP procedures + + The RIC Response shall comprise one RDIE for each RDIE in the RIC + Request. The RDIEs shall be in the same order as in the request and + the RDIE Identifier in each RDIE shall be the value of the RDIE + Identifier in the corresponding RDIE in the request. + */ + + BOOLEAN FlgHasBaResource; /* TRUE: exist BA resource request */ + UCHAR RDIE_IdentifierBA; + + UCHAR AP_MAC[ETH_ALEN]; + +} FT_RIC_AP; + +typedef struct _FT_RIC_CTRL_BLOCK { + + /* resources for different APs */ + LIST_HEADER ResourceList; + + UCHAR RDIE_Identifier; + +} FT_RIC_CTRL_BLOCK; +#endif /* CONFIG_STA_SUPPORT */ + +typedef struct _FT_CAP_CFG +{ + UINT8 FtOverDs:1; /* 1: Enable FT over the DS. */ + UINT8 RsrReqCap:1; /* 1: Enable FT resource request. */ + UINT8 Dot11rFtEnable:1; /* 1: FT enable , 0: FT disable. */ + UINT8 :5; /* reserve. */ +} FT_CAP_CFG, *PFT_CAP_CFG; + +typedef struct GNU_PACKED _FT_CFG +{ + UINT8 FtMdId[FT_MDID_LEN]; /* Mobility domain ID of Fast Bss. */ + UINT32 AssocDeadLine; /* 100ms */ + UINT8 FtR0khId[FT_ROKH_ID_LEN + 1]; /* Lenght of ROKHID can be 1 to 48 chars. */ + UINT8 FtR0khIdLen; + FT_CAP_CFG FtCapFlag; /* FT capability Configuration. */ +} FT_CFG, *PFT_CFG; + +typedef struct __FT_R1KH_ENTRY +{ + struct __FT_R1KH_ENTRY *pNext; + UINT32 KeyLifeTime; + UINT32 RassocDeadline; + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + UINT8 PmkR0Name[16]; + UINT8 PmkR1Name[16]; + UINT8 PmkR1Key[32]; + UINT8 PairwisChipher[4]; + UINT8 AkmSuite[4]; + UINT8 R0khId[FT_ROKH_ID_LEN + 1]; + UINT8 R0khIdLen; + UINT8 StaMac[6]; +} FT_R1HK_ENTRY, *PFT_R1HK_ENTRY; + +typedef struct __FT_TAB +{ + /* KDP. */ + PVOID pFT_KDP_Ctrl_BK; + NDIS_SPIN_LOCK FT_KdpLock; + BOOLEAN FlgIsFtKdpInit; + + /* R1KH. */ + LIST_HEADER FT_R1khEntryTab[FT_R1KH_ENTRY_HASH_TABLE_SIZE]; + NDIS_SPIN_LOCK FT_R1khEntryTabLock; + ULONG FT_R1khEntryTabSize; + + BOOLEAN FT_R1khEntryTabReady; +} FT_TAB, *PFT_TAB; + +typedef struct __FT_MDIE_INFO +{ + INT Len; + UINT8 MdId[FT_MDID_LEN]; + FT_CAP_AND_POLICY FtCapPlc; + + PVOID pMdIe; +} FT_MDIE_INFO, *PFT_MDIE_INFO; + +typedef struct __FT_FTIE_INFO +{ + INT Len; + FT_MIC_CTR_FIELD MICCtr; + UINT8 MIC[16]; + UINT8 ANonce[32]; + UINT8 SNonce[32]; + UINT8 R0khIdLen; + UINT8 R0khId[FT_ROKH_ID_LEN + 1]; + UINT8 R1khIdLen; + UINT8 R1khId[FT_R1KH_ID_LEN + 1]; + UINT8 GtkLen; + UINT8 GtkSubIE[64]; + + PVOID pFtIe; +} FT_FTIE_INFO, *PFT_FTIE_INFO; + +typedef struct __FT_RIC_INFO +{ + INT Len; + VOID *pRicInfo; + UINT8 RicIEs[MAX_RICIES_LEN]; + UINT8 RicIEsLen; +} FT_RIC_INFO, *PFT_RIC_INFO; + +typedef struct __FT_INFO +{ + FT_MDIE_INFO MdIeInfo; + FT_FTIE_INFO FtIeInfo; + FT_RIC_INFO RicInfo; + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; +} FT_INFO, *PFT_INFO; + +typedef struct __FT_MIC_CONTENT +{ + PUINT8 rsnie_ptr; + UINT rsnie_len; + PUINT8 mdie_ptr; + UINT mdie_len; + PUINT8 ftie_ptr; + UINT ftie_len; + PUINT8 ric_ptr; + UINT ric_len; +} FT_MIC_CONTENT, *PFT_MIC_CONTENT; + + +#ifdef CONFIG_STA_SUPPORT +#define FT_ACT_TIMEOUT 2000 /* unit: msec */ + +typedef struct _MLME_FT_OTA_AUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + ULONG Timeout; + FT_MDIE MdIe; +} MLME_FT_OTA_AUTH_REQ_STRUCT, *PMLME_FT_OTA_AUTH_REQ_STRUCT; + +typedef struct _DOT11R_CMN_STRUC +{ + BOOLEAN bFtSupport; /* enable or disable Fast BSS Transition support */ + BOOLEAN bInMobilityDomain; /* Set to TRUE if is in a Mobility Domain. Decide to do Fast BSS Transition or not. */ + BOOLEAN bSupportResource; /* Set to TRUE if user wants to do resource request. */ + UINT8 FtRspSuccess; /* 0: not ft, 1: ft_action response from OTD, 2: ft_auth response from OTA */ + UINT8 PMKR0Name[LEN_PMK_NAME]; + UINT8 PMKR0[LEN_PMK]; + UINT8 R0khIdLen; + UINT8 R0khId[FT_ROKH_ID_LEN + 1]; + FT_MDIE_INFO MdIeInfo; + FT_FTIE_INFO FtIeInfo; +} DOT11R_CMN_STRUC, *PDOT11R_CMN_STRUC; + +typedef struct _MLME_FT_REQ_STRUCT { + UCHAR TargetAddr[MAC_ADDR_LEN]; + UCHAR HaveRSN; + UCHAR SNonce[32]; + UCHAR R0khIdLen; + UCHAR R0khId[FT_ROKH_ID_LEN + 1]; + FT_MDIE MdIe; + ULONG Timeout; + ULONG VIeLen; + UCHAR VIe[256]; /* Carry RSNIE */ +} MLME_FT_REQ_STRUCT, *PMLME_FT_REQ_STRUCT; +#endif /* CONFIG_STA_SUPPORT */ + +#endif /* __FT_CMM_H__ */ +#endif /* DOT11R_FT_SUPPORT */ + +/* End of ft_cmm.h */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/gas.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/gas.h new file mode 100644 index 000000000..77dc9adf1 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/gas.h @@ -0,0 +1,235 @@ +/* + *************************************************************************** + * 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: + gas.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __GAS_H__ +#define __GAS_H__ + +#include "link_list.h" + +#define GAS_MACHINE_BASE 0 + +/* gas states */ +enum GAS_STATE { + WAIT_GAS_REQ, + WAIT_GAS_RSP, + WAIT_PEER_GAS_REQ, + WAIT_PEER_GAS_RSP, + WAIT_GAS_CB_REQ, + WAIT_GAS_CB_RSP, + GAS_UNKNOWN, + MAX_GAS_STATE, +}; + +/* gas events */ +enum GAS_EVENT { + GAS_REQ, + GAS_RSP, + GAS_RSP_MORE, + PEER_GAS_REQ, + PEER_GAS_RSP, + PEER_GAS_RSP_MORE, + GAS_CB_REQ, + GAS_CB_REQ_MORE, + GAS_CB_RSP, + GAS_CB_RSP_MORE, + MAX_GAS_MSG, +}; + +#define GAS_FUNC_SIZE (MAX_GAS_STATE * MAX_GAS_MSG) + +typedef struct _GAS_QUERY_RSP_FRAGMENT +{ + DL_LIST List; + UCHAR GASRspFragID; + UINT16 FragQueryRspLen; + UCHAR *FragQueryRsp; +}GAS_QUERY_RSP_FRAGMENT, *PGAS_QUERY_RSP_FRAGMENT; + +typedef struct _GAS_PEER_ENTRY { + DL_LIST List; + enum GAS_STATE CurrentState; + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UCHAR DialogToken; + UCHAR AdvertisementProID; + void *Priv; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT PostReplyTimer; + BOOLEAN PostReplyTimerRunning; + RALINK_TIMER_STRUCT GASRspBufferingTimer; + BOOLEAN GASRspBufferingTimerRunning; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + RALINK_TIMER_STRUCT GASResponseTimer; + BOOLEAN GASResponseTimerRunning; + RALINK_TIMER_STRUCT GASCBDelayTimer; + BOOLEAN GASCBDelayTimerRunning; +#endif /* CONFIG_STA_SUPPORT */ + UCHAR GASRspFragNum; + UCHAR CurrentGASFragNum; + UINT32 AllocResource; + UINT32 FreeResource; + UCHAR QueryNum; + DL_LIST GASQueryRspFragList; +}GAS_PEER_ENTRY, *PGAS_PEER_ENTRY; + +typedef struct _GAS_CTRL { + DL_LIST GASPeerList; + NDIS_SPIN_LOCK GASPeerListLock; + UINT8 ExternalANQPServerTest; + UINT32 cb_delay; /* Come Back Delay */ +} GAS_CTRL, *PGAS_CTRL; + +/* + * gas events data + * GASComebackDelay : unit(TU) + */ +typedef struct GNU_PACKED _GAS_EVENT_DATA { + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UINT16 EventType; + union{ +#ifdef CONFIG_STA_SUPPORT + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 QueryReqLen; + UCHAR QueryReq[0]; + } GNU_PACKED GAS_REQ_DATA; + struct { + UINT16 StatusCode; + UCHAR AdvertisementProID; + UINT16 QueryRspLen; + UCHAR QueryRsp[0]; + } GNU_PACKED PEER_GAS_RSP_DATA; + struct { + UCHAR DialogToken; + } GNU_PACKED PEER_GAS_RSP_MORE_DATA; + struct { + UINT16 StatusCode; + UCHAR AdvertisementProID; + UINT16 QueryRspLen; + UCHAR QueryRsp[0]; + } GNU_PACKED GAS_CB_RSP_DATA; + struct { + UCHAR DialogToken; + } GNU_PACKED GAS_CB_RSP_MORE_DATA; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + struct { + UCHAR DialogToken; + UINT16 StatusCode; + UINT16 GASComebackDelay; + UCHAR AdvertisementProID; + UINT16 QueryRspLen; + UCHAR QueryRsp[0]; + } GNU_PACKED GAS_RSP_DATA; + struct { + UCHAR DialogToken; + UINT16 StatusCode; + UINT16 GASComebackDelay; + UCHAR AdvertisementProID; + } GNU_PACKED GAS_RSP_MORE_DATA; + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 QueryReqLen; + UCHAR QueryReq[0]; + } GNU_PACKED PEER_GAS_REQ_DATA; + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 StatusCode; + } GNU_PACKED GAS_CB_REQ_DATA; + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 StatusCode; + } GNU_PACKED GAS_CB_REQ_MORE_DATA; +#endif /* CONFIG_AP_SUPPORT */ + }u; +}GAS_EVENT_DATA, *PGAS_EVENT_DATA; + +VOID GASStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +enum GAS_STATE GASPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID GASSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem, + PGAS_EVENT_DATA Event, + IN enum GAS_STATE State); + +VOID SendGASRsp( + IN PRTMP_ADAPTER pAd, + GAS_EVENT_DATA *Event); + + +VOID GASCtrlExit(IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +VOID ReceiveGASInitRsp( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReceiveGASCBRsp( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +void SendAnqpRspEvent(void *net_dev, const char *peer_mac_addr, + u16 status, const char *anqp_rsp, u16 anqp_rsp_len); + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(PostReplyTimeout); +DECLARE_TIMER_FUNCTION(GASRspBufferingTimeout); + +void SendAnqpReqEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *anqp_req, u16 anqp_req_len); + +VOID ReceiveGASInitReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReceiveGASCBReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* CONFIG_AP_SUPPORT */ +INT Send_ANQP_Rsp( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING ANQPRsp, + IN UINT32 ANQPRspLen); + +#endif /* __GAS_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/hotspot.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/hotspot.h new file mode 100644 index 000000000..920bd712a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/hotspot.h @@ -0,0 +1,192 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __HOTSPOT_H__ +#define __HOTSPOT_H__ + +#ifndef CONFIG_DOT11V_WNM +#error "For HOTSPOT2.0 feature, you must define the compile flag -DCONFIG_DOT11V_WNM" +#endif + +#ifndef CONFIG_DOT11U_INTERWORKING +#error "For HOTSPOT2.0 feature, you must define the compile flag -DCONFIG_DOT11U_INTERWORKING" +#endif + +#include "rtmp.h" + +#define HSCTRL_MACHINE_BASE 0 + +enum HSCTRL_STATE { + WAIT_HSCTRL_OFF, + WAIT_HSCTRL_ON, + HSCTRL_IDLE, + MAX_HSCTRL_STATE, +}; + +enum HSCTRL_EVENT { + HSCTRL_OFF, + HSCTRL_ON, + MAX_HSCTRL_MSG, +}; + +typedef struct GNU_PACKED _HSCTRL_EVENT_DATA { + UCHAR ControlIndex; + UCHAR EventTrigger; + UCHAR EventType; +} HSCTRL_EVENT_DATA, *PHSCTRL_EVENT_DATA; + +typedef struct _HOTSPOT_CTRL { + UINT32 HSIndicationIELen; + UINT32 P2PIELen; + UINT32 InterWorkingIELen; + UINT32 AdvertisementProtoIELen; + UINT32 QosMapSetIELen; + UINT32 RoamingConsortiumIELen; + PUCHAR InterWorkingIE; + PUCHAR AdvertisementProtoIE; + PUCHAR QosMapSetIE; + USHORT DscpRange[8]; + USHORT DscpException[21]; + PUCHAR RoamingConsortiumIE; + PUCHAR HSIndicationIE; + PUCHAR P2PIE; + BOOLEAN HSDaemonReady; + BOOLEAN HotSpotEnable; + enum HSCTRL_STATE HSCtrlState; + BOOLEAN IsHessid; + UCHAR Hessid[MAC_ADDR_LEN]; + UINT8 AccessNetWorkType; + BOOLEAN DGAFDisable; + UINT8 L2Filter; + BOOLEAN ICMPv4Deny; + UINT32 MMPDUSize; + BOOLEAN QosMapEnable; +// BOOLEAN bNonTX; /* 0:enable TX, 1:disable TX*/ + BOOLEAN bASANEnable; /* 1:enable ASAN IE, 1:disable ASAN IE*/ + UCHAR QLoadTestEnable; /* for BSS Load IE Test */ + UCHAR QLoadCU; /* for BSS Load IE Test */ + USHORT QLoadStaCnt; /* for BSS Load IE Test */ +} HOTSPOT_CTRL, *PHOTSPOT_CTRL; + +enum { + L2FilterDisable, + L2FilterBuiltIn, + L2FilterExternal, +}; + +enum { + PARAM_DGAF_DISABLED, + PARAM_PROXY_ARP, + PARAM_L2_FILTER, + PARAM_ICMPV4_DENY, + PARAM_MMPDU_SIZE, + PARAM_EXTERNAL_ANQP_SERVER_TEST, + PARAM_GAS_COME_BACK_DELAY, + PARAM_WNM_NOTIFICATION, + PARAM_QOSMAP, +}; + +BOOLEAN L2FilterInspection( + IN PRTMP_ADAPTER pAd, + IN PHOTSPOT_CTRL pHSCtrl, + IN PUCHAR pData); + +VOID HSCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +INT Set_STAHotSpot_OnOff( + IN PRTMP_ADAPTER pAd, + IN UINT8 OnOff); + +enum HSCTRL_STATE HSCtrlCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +BOOLEAN HotSpotEnable( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN INT Type); + +VOID HSCtrlExit( + IN PRTMP_ADAPTER pAd); + +VOID HSCtrlHalt( + IN PRTMP_ADAPTER pAd); + +INT Set_HotSpot_OnOff( + IN PRTMP_ADAPTER pAd, + IN UINT8 OnOff, + IN UINT8 EventTrigger, + IN UINT8 EventType); + +struct _PEER_PROBE_REQ_PARAM; + +BOOLEAN ProbeReqforHSAP( + IN PRTMP_ADAPTER pAd, + IN UCHAR APIndex, + IN struct _PEER_PROBE_REQ_PARAM *ProbeReqParam); + +VOID Clear_Hotspot_All_IE(IN PRTMP_ADAPTER PAd); + +#define isBcastEtherAddr(addr) ((addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5])== 0xff) + +#define GAS_STATE_MESSAGES 0 +#define ACTION_STATE_MESSAGES 1 + +void HotspotOnOffEvent(PNET_DEV net_dev, int onoff); +void HotspotAPReload(PNET_DEV net_dev); + +INT Set_HotSpot_Param( + IN PRTMP_ADAPTER pAd, + UINT32 Param, + UINT32 Value); + +enum { + HS_ON_OFF_BASE, + HS_AP_RELOAD, +}; + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN HSIPv4Check( + IN PRTMP_ADAPTER pAd, + PUSHORT pWcid, + PNDIS_PACKET pPacket, + PUCHAR pSrcBUf, + UINT16 srcPort, + UINT16 dscPort); +#endif +#ifdef CONFIG_HOTSPOT_R2 +struct _sta_hs_info { + //UCHAR addr[6]; + UCHAR version; + UCHAR ppsmo_exist; + USHORT ppsmo_id; +}; +#endif + +#endif /* __HOTSPOT_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/iface_util.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/iface_util.h new file mode 100644 index 000000000..3c191d495 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/iface_util.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * 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: + rtmp_util.h + + Abstract: + Common for PCI/USB/RBUS. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_UTIL_H__ +#define __RTMP_UTIL_H__ + +#define LEN_CCMP_HDR 8 +#define LEN_CCMP_MIC 8 +/* maximum of PCI, USB, or RBUS, int PCI, it is 0 but in USB, it is 11 */ +#define RTMP_PKT_TAIL_PADDING 11 /* 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding) */ + +#ifdef PCI_MSI_SUPPORT +#define RTMP_MSI_ENABLE(_pAd) \ + { POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + (_pAd)->HaveMsi = pci_enable_msi(_pObj->pci_dev) == 0 ? TRUE : FALSE; \ + } + +#define RTMP_MSI_DISABLE(_pci_dev, _pHaveMsi) \ + { \ + if (*(_pHaveMsi) == TRUE) \ + pci_disable_msi(_pci_dev); \ + *(_pHaveMsi) = FALSE; \ + } + +#else +#define RTMP_MSI_ENABLE(_pAd) do{}while(0) +#define RTMP_MSI_DISABLE(_pci_dev, _pHaveMsi) do{}while(0) +#endif /* PCI_MSI_SUPPORT */ + +#define RTMP_PCI_DMA_TODEVICE 0xFF00 +#define RTMP_PCI_DMA_FROMDEVICE 0xFF01 + + + + +#define UNLINK_TIMEOUT_MS 3 + +#define USBD_TRANSFER_DIRECTION_OUT 0 +#define USBD_TRANSFER_DIRECTION_IN 0 +#define USBD_SHORT_TRANSFER_OK 0 +#define PURB purbb_t + +#define OS_RTMP_MlmeUp RtmpOsMlmeUp + +#endif /* __RTMP_UTIL_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_pci.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_pci.h new file mode 100644 index 000000000..87b0d20cc --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_pci.h @@ -0,0 +1,91 @@ +/**************************************************************************** + * 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: + rtmp_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_PCI_H__ +#define __RTMP_PCI_H__ + +/* + Device ID & Vendor ID related definitions, + NOTE: you should not add the new VendorID/DeviceID here unless you + not sure it belongs to what chip. +*/ + +#define PCIBUS_INTEL_VENDOR 0x8086 + +#if !defined(PCI_CAP_ID_EXP) +#define PCI_CAP_ID_EXP 0x10 +#endif +#if !defined(PCI_EXP_LNKCTL) +#define PCI_EXP_LNKCTL 0x10 +#endif +#if !defined(PCI_CLASS_BRIDGE_PCI) +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#endif + + +#define SYSCFG0 0x10 + +/* + PCI registers - base address 0x0000 +*/ +#define PCI_CFG 0x0000 +#define PCI_EECTRL 0x0004 +#define PCI_MCUCTRL 0x0008 +#define AUX_CTRL 0x10c + +#define OPT_14 0x114 + + +#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ + ((POS_COOKIE)handle)->pci_dev = dev_p; + + +#ifdef LINUX +/* set driver data */ +#define RT28XX_DRVDATA_SET(_a) pci_set_drvdata(_a, net_dev); + +#define RT28XX_PUT_DEVICE(dev_p) + + +#define RTMP_PCI_DEV_UNMAP() \ +{ if (net_dev->base_addr) { \ + iounmap((void *)(net_dev->base_addr)); \ + release_mem_region(pci_resource_start(dev_p, 0), \ + pci_resource_len(dev_p, 0)); } \ + if (net_dev->irq) pci_release_regions(dev_p); } + + +#define PCI_REG_READ_WORD(pci_dev, offset, Configuration) \ + if (pci_read_config_word(pci_dev, offset, ®16) == 0) \ + Configuration = le2cpu16(reg16); \ + else \ + Configuration = 0; + +#define PCI_REG_WIRTE_WORD(pci_dev, offset, Configuration) \ + reg16 = cpu2le16(Configuration); \ + pci_write_config_word(pci_dev, offset, reg16); +#endif /* LINUX */ + +#endif /* __RTMP_PCI_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_rbs.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_rbs.h new file mode 100644 index 000000000..4117e6f5a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_rbs.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * 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: + rtmp_rbs.h + + Abstract: + Ralink SoC Internal Bus related definitions and data dtructures + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RTMP_RBUS_H__ +#define __RTMP_RBUS_H__ + +/************************************************************************* + * + * Device hardware/ Interface related definitions. + * + ************************************************************************/ + +#define RTMP_MAC_IRQ_NUM SURFBOARDINT_WLAN + +//#define DEFAULT_RF_OFFSET 0x40000 + +#ifdef LINUX +/************************************************************************* + * + * Device Tx/Rx related definitions. + * + ************************************************************************/ +#ifdef DFS_SUPPORT +/* TODO: Check these functions. */ +#ifdef RTMP_RBUS_SUPPORT +extern void unregister_tmr_service(void); +extern void request_tmr_service(int, void *, void *); +#endif /* RTMP_RBUS_SUPPORT */ + +#endif /* DFS_SUPPORT */ + +#endif /* LINUX */ + +#endif /* __RTMP_RBUS_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_reg_pcirbs.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_reg_pcirbs.h new file mode 100644 index 000000000..08581a695 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/iface/rtmp_reg_pcirbs.h @@ -0,0 +1,389 @@ +/**************************************************************************** + * 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: + rtmp_reg_pcirbus.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_REG_PCIRBUS_H__ +#define __RTMP_REG_PCIRBUS_H__ + + +// TODO: shiang, for RT3290, make sure following definition is correct to put as here + +#ifdef RT_BIG_ENDIAN +typedef union _CMB_CTRL_STRUC{ + struct{ + UINT32 LDO0_EN:1; + UINT32 LDO3_EN:1; + UINT32 LDO_BGSEL:2; + UINT32 LDO_CORE_LEVEL:4; + UINT32 PLL_LD:1; + UINT32 XTAL_RDY:1; +#ifdef RT65xx + UINT32 Rsv:3; + UINT32 GPIOModeLed2:1; + UINT32 GPIOModeLed1:1; + UINT32 CsrUartMode:1; +#else + UINT32 Rsv:2; + UINT32 LDO25_FRC_ON:1;//4 + UINT32 LDO25_LARGEA:1; + UINT32 LDO25_LEVEL:2; +#endif + UINT32 AUX_OPT_Bit15_Two_AntennaMode:1; + UINT32 AUX_OPT_Bit14_TRSW1_as_GPIO:1; + UINT32 AUX_OPT_Bit13_GPIO7_as_GPIO:1; + UINT32 AUX_OPT_Bit12_TRSW0_as_WLAN_ANT_SEL:1; + UINT32 AUX_OPT_Bit11_Rsv:1; + UINT32 AUX_OPT_Bit10_NotSwap_WL_LED_ACT_RDY:1; + UINT32 AUX_OPT_Bit9_GPIO3_as_GPIO:1; + UINT32 AUX_OPT_Bit8_AuxPower_Exists:1; + UINT32 AUX_OPT_Bit7_KeepInterfaceClk:1; + UINT32 AUX_OPT_Bit6_KeepXtal_On:1; + UINT32 AUX_OPT_Bit5_RemovePCIePhyClk_BTOff:1; + UINT32 AUX_OPT_Bit4_RemovePCIePhyClk_WLANOff:1; + UINT32 AUX_OPT_Bit3_PLLOn_L1:1; + UINT32 AUX_OPT_Bit2_PCIeCoreClkOn_L1:1; + UINT32 AUX_OPT_Bit1_PCIePhyClkOn_L1:1; + UINT32 AUX_OPT_Bit0_InterfaceClk_40Mhz:1; + }field; + UINT32 word; +}CMB_CTRL_STRUC, *PCMB_CTRL_STRUC; +#else +typedef union _CMB_CTRL_STRUC{ + struct{ + UINT32 AUX_OPT_Bit0_InterfaceClk_40Mhz:1; + UINT32 AUX_OPT_Bit1_PCIePhyClkOn_L1:1; + UINT32 AUX_OPT_Bit2_PCIeCoreClkOn_L1:1; + UINT32 AUX_OPT_Bit3_PLLOn_L1:1; + UINT32 AUX_OPT_Bit4_RemovePCIePhyClk_WLANOff:1; + UINT32 AUX_OPT_Bit5_RemovePCIePhyClk_BTOff:1; + UINT32 AUX_OPT_Bit6_KeepXtal_On:1; + UINT32 AUX_OPT_Bit7_KeepInterfaceClk:1; + UINT32 AUX_OPT_Bit8_AuxPower_Exists:1; + UINT32 AUX_OPT_Bit9_GPIO3_as_GPIO:1; + UINT32 AUX_OPT_Bit10_NotSwap_WL_LED_ACT_RDY:1; + UINT32 AUX_OPT_Bit11_Rsv:1; + UINT32 AUX_OPT_Bit12_TRSW0_as_WLAN_ANT_SEL:1; + UINT32 AUX_OPT_Bit13_GPIO7_as_GPIO:1; + UINT32 AUX_OPT_Bit14_TRSW1_as_GPIO:1; + UINT32 AUX_OPT_Bit15_Two_AntennaMode:1; +#ifdef RT65xx + UINT32 CsrUartMode:1; + UINT32 GPIOModeLed1:1; + UINT32 GPIOModeLed2:1; + UINT32 Rsv:3; +#else + UINT32 LDO25_LEVEL:2; + UINT32 LDO25_LARGEA:1; + UINT32 LDO25_FRC_ON:1;//4 + UINT32 Rsv:2; +#endif /* RT65xx */ + UINT32 XTAL_RDY:1; + UINT32 PLL_LD:1; + UINT32 LDO_CORE_LEVEL:4; + UINT32 LDO_BGSEL:2; + UINT32 LDO3_EN:1; + UINT32 LDO0_EN:1; + }field; + UINT32 word; +}CMB_CTRL_STRUC, *PCMB_CTRL_STRUC; +#endif + + +#define OSCCTL 0x38 +#ifdef RT_BIG_ENDIAN +typedef union _OSCCTL_STRUC{ + struct{ + UINT32 ROSC_EN:1; + UINT32 CAL_REQ:1; + UINT32 CLK_32K_VLD:1; + UINT32 CAL_ACK:1; + UINT32 CAL_CNT:12; + UINT32 Rsv:3; + UINT32 REF_CYCLE:13; + }field; + UINT32 word; +}OSCCTL_STRUC, *POSCCTL_STRUC; +#else +typedef union _OSCCTL_STRUC{ + struct{ + UINT32 REF_CYCLE:13; + UINT32 Rsv:3; + UINT32 CAL_CNT:12; + UINT32 CAL_ACK:1; + UINT32 CLK_32K_VLD:1; + UINT32 CAL_REQ:1; + UINT32 ROSC_EN:1; + }field; + UINT32 word; +}OSCCTL_STRUC, *POSCCTL_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _COEXCFG0_STRUC{ + struct{ + UINT32 COEX_CFG1:8; + UINT32 COEX_CFG0:8; + UINT32 FIX_WL_RF_LNA:2; + UINT32 FIX_BT_H_PA:3; + UINT32 FIX_BT_L_PA:3; + UINT32 FIX_WL_TX_PWR:2; + UINT32 Rsv:3; + UINT32 FIX_WL_ANT_EN:1; + UINT32 FIX_WL_DI_ANT:1; + UINT32 COEX_ENT:1; + }field; + UINT32 word; +}COEXCFG0_STRUC, *PCOEXCFG0_STRUC; +#else +typedef union _COEXCFG0_STRUC{ + struct{ + UINT32 COEX_ENT:1; + UINT32 FIX_WL_DI_ANT:1; + UINT32 FIX_WL_ANT_EN:1; + UINT32 Rsv:3; + UINT32 FIX_WL_TX_PWR:2; + UINT32 FIX_BT_L_PA:3; + UINT32 FIX_BT_H_PA:3; + UINT32 FIX_WL_RF_LNA:2; + + UINT32 COEX_CFG0:8; + UINT32 COEX_CFG1:8; + }field; + UINT32 word; +}COEXCFG0_STRUC, *PCOEXCFG0_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _COEXCFG1_STRUC{ + struct{ + UINT32 Rsv:8; + UINT32 DIS_WL_RF_DELY:8; + UINT32 DIS_WL_PA_DELY:8; + UINT32 DIS_WL_TR_DELY:8; + }field; + UINT32 word; +}COEXCFG1_STRUC, *PCOEXCFG1_STRUC; +#else +typedef union _COEXCFG1_STRUC{ + struct{ + UINT32 DIS_WL_TR_DELY:8; + UINT32 DIS_WL_PA_DELY:8; + UINT32 DIS_WL_RF_DELY:8; + UINT32 Rsv:8; + }field; + UINT32 word; +}COEXCFG1_STRUC, *PCOEXCFG1_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _COEXCFG2_STRUC{ + struct{ + UINT32 BT_COEX_CFG1_Bit31_Rsv:1; + UINT32 BT_COEX_CFG1_Bit30_Rsv:1; + UINT32 BT_COEX_CFG1_Bit29_HaltHighPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG1_Bit28_HaltHighPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG1_Bit27_HaltHighPriorityTx_wl_busy:1; + UINT32 BT_COEX_CFG1_Bit26_HaltLowPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG1_Bit25_HaltLowPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG1_Bit24_HaltLowPriorityTx_wl_busy:1; + + UINT32 BT_COEX_CFG0_Bit23_Rsv:1; + UINT32 BT_COEX_CFG0_Bit22_Rsv:1; + UINT32 BT_COEX_CFG0_Bit21_HaltHighPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG0_Bit20_HaltHighPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG0_Bit19_HaltHighPriorityTx_wl_busy:1; + UINT32 BT_COEX_CFG0_Bit18_HaltLowPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG0_Bit17_HaltLowPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG0_Bit16_HaltLowPriorityTx_wl_busy:1; + + UINT32 WL_COEX_CFG1_Bit15_LowerTxPwr_bt_high_priority:1; + UINT32 WL_COEX_CFG1_Bit14_Enable_Tx_free_timer:1; + UINT32 WL_COEX_CFG1_Bit13_Disable_TxAgg_bi_high_priority:1; + UINT32 WL_COEX_CFG1_Bit12_Disable_bt_rx_req_h:1; + UINT32 WL_COEX_CFG1_Bit11_HaltTx_bt_tx_req_l:1; + UINT32 WL_COEX_CFG1_Bit10_HaltTx_bt_tx_req_h:1; + UINT32 WL_COEX_CFG1_Bit9_HaltTx_bt_rx_req_h:1; + UINT32 WL_COEX_CFG1_Bit8_HaltTx_bt_rx_busy:1; + + UINT32 WL_COEX_CFG0_Bit7_LowerTxPwr_bt_high_priority:1; + UINT32 WL_COEX_CFG0_Bit6_Enable_Tx_free_timer:1; + UINT32 WL_COEX_CFG0_Bit5_Disable_TxAgg_bi_high_priority:1; + UINT32 WL_COEX_CFG0_Bit4_Disable_bt_rx_req_h:1; + UINT32 WL_COEX_CFG0_Bit3_HaltTx_bt_tx_req_l:1; + UINT32 WL_COEX_CFG0_Bit2_HaltTx_bt_tx_req_h:1; + UINT32 WL_COEX_CFG0_Bit1_HaltTx_bt_rx_req_h:1; + UINT32 WL_COEX_CFG0_Bit0_HaltTx_bt_rx_busy:1; + }field; + UINT32 word; +}COEXCFG2_STRUC, *PCOEXCFG2_STRUC; +#else +typedef union _COEXCFG2_STRUC{ + struct{ + UINT32 WL_COEX_CFG0_Bit0_HaltTx_bt_rx_busy:1; + UINT32 WL_COEX_CFG0_Bit1_HaltTx_bt_rx_req_h:1; + UINT32 WL_COEX_CFG0_Bit2_HaltTx_bt_tx_req_h:1; + UINT32 WL_COEX_CFG0_Bit3_HaltTx_bt_tx_req_l:1; + UINT32 WL_COEX_CFG0_Bit4_Disable_bt_rx_req_h:1; + UINT32 WL_COEX_CFG0_Bit5_Disable_TxAgg_bi_high_priority:1; + UINT32 WL_COEX_CFG0_Bit6_Enable_Tx_free_timer:1; + UINT32 WL_COEX_CFG0_Bit7_LowerTxPwr_bt_high_priority:1; + + UINT32 WL_COEX_CFG1_Bit8_HaltTx_bt_rx_busy:1; + UINT32 WL_COEX_CFG1_Bit9_HaltTx_bt_rx_req_h:1; + UINT32 WL_COEX_CFG1_Bit10_HaltTx_bt_tx_req_h:1; + UINT32 WL_COEX_CFG1_Bit11_HaltTx_bt_tx_req_l:1; + UINT32 WL_COEX_CFG1_Bit12_Disable_bt_rx_req_h:1; + UINT32 WL_COEX_CFG1_Bit13_Disable_TxAgg_bi_high_priority:1; + UINT32 WL_COEX_CFG1_Bit14_Enable_Tx_free_timer:1; + UINT32 WL_COEX_CFG1_Bit15_LowerTxPwr_bt_high_priority:1; + + UINT32 BT_COEX_CFG0_Bit16_HaltLowPriorityTx_wl_busy:1; + UINT32 BT_COEX_CFG0_Bit17_HaltLowPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG0_Bit18_HaltLowPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG0_Bit19_HaltHighPriorityTx_wl_busy:1; + UINT32 BT_COEX_CFG0_Bit20_HaltHighPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG0_Bit21_HaltHighPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG0_Bit22_Rsv:1; + UINT32 BT_COEX_CFG0_Bit23_Rsv:1; + + UINT32 BT_COEX_CFG1_Bit24_HaltLowPriorityTx_wl_busy:1; + UINT32 BT_COEX_CFG1_Bit25_HaltLowPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG1_Bit26_HaltLowPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG1_Bit27_HaltHighPriorityTx_wl_busy:1; + UINT32 BT_COEX_CFG1_Bit28_HaltHighPriorityTx_wl_rx_busy:1; + UINT32 BT_COEX_CFG1_Bit29_HaltHighPriorityTx_wl_bcn_busy:1; + UINT32 BT_COEX_CFG1_Bit30_Rsv:1; + UINT32 BT_COEX_CFG1_Bit31_Rsv:1; + }field; + UINT32 word; +}COEXCFG2_STRUC, *PCOEXCFG2_STRUC; +#endif + + +#define PLL_CTRL 0x50 +#ifdef RT_BIG_ENDIAN +typedef union _PLL_CTRL_STRUC { + struct { + ULONG VBGBK_EN:1; + ULONG LOCK_DETECT_WINDOW_CTRL:3; + ULONG PFD_DELAY_CTRL:2; + ULONG CP_CURRENT_CTRL:2; + ULONG LPF_C2_CTRL:2; + ULONG LPF_C1_CTRL:2; + ULONG LPF_R1:1; + ULONG VCO_FIXED_CURRENT_CONTROL:3; + ULONG RESERVED_INPUT2:8; + ULONG RESERVED_INPUT1:8; + } field; + ULONG word; +} PLL_CTRL_STRUC, *PPLL_CTRL_STRUC; +#else +typedef union _PLL_CTRL_STRUC { + struct { + ULONG RESERVED_INPUT1:8; + ULONG RESERVED_INPUT2:8; + ULONG VCO_FIXED_CURRENT_CONTROL:3; + ULONG LPF_R1:1; + ULONG LPF_C1_CTRL:2; + ULONG LPF_C2_CTRL:2; + ULONG CP_CURRENT_CTRL:2; + ULONG PFD_DELAY_CTRL:2; + ULONG LOCK_DETECT_WINDOW_CTRL:3; + ULONG VBGBK_EN:1; + } field; + ULONG word; +} PLL_CTRL_STRUC, *PPLL_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#define WPDMA_RST_IDX 0x20c +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 :14; + UINT32 RST_DRX_IDX1:1; + UINT32 RST_DRX_IDX0:1; + UINT32 rsv:6; + UINT32 RST_DTX_IDX9:1; + UINT32 RST_DTX_IDX8:1; + UINT32 RST_DTX_IDX7:1; + UINT32 RST_DTX_IDX6:1; + UINT32 RST_DTX_IDX5:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX0:1; + } field; + UINT32 word; +}WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#else +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 RST_DTX_IDX0:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX5:1; + UINT32 RST_DTX_IDX6:1; + UINT32 RST_DTX_IDX7:1; + UINT32 RST_DTX_IDX8:1; + UINT32 RST_DTX_IDX9:1; + UINT32 rsv:6; + UINT32 RST_DRX_IDX0:1; + UINT32 RST_DRX_IDX1:1; + UINT32 :14; + } field; + UINT32 word; +} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#endif +#define DELAY_INT_CFG 0x0210 +#ifdef RT_BIG_ENDIAN +typedef union _DELAY_INT_CFG_STRUC { + struct { + UINT32 TXDLY_INT_EN:1; + UINT32 TXMAX_PINT:7; + UINT32 TXMAX_PTIME:8; + UINT32 RXDLY_INT_EN:1; + UINT32 RXMAX_PINT:7; + UINT32 RXMAX_PTIME:8; + } field; + UINT32 word; +}DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#else +typedef union _DELAY_INT_CFG_STRUC { + struct { + UINT32 RXMAX_PTIME:8; + UINT32 RXMAX_PINT:7; + UINT32 RXDLY_INT_EN:1; + UINT32 TXMAX_PTIME:8; + UINT32 TXMAX_PINT:7; + UINT32 TXDLY_INT_EN:1; + } field; + UINT32 word; +} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#endif + +#endif /* __RTMP_REG_PCIRBUS_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/igmp_snoop.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/igmp_snoop.h new file mode 100644 index 000000000..d8c18cd36 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/igmp_snoop.h @@ -0,0 +1,144 @@ +/**************************************************************************** + * 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: + igmp_snoop.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + + +#ifndef __RTMP_IGMP_SNOOP_H__ +#define __RTMP_IGMP_SNOOP_H__ + +#include "link_list.h" + +#define IGMP_PROTOCOL_DESCRIPTOR 0x02 +#define IGMP_V1_MEMBERSHIP_REPORT 0x12 +#define IGMP_V2_MEMBERSHIP_REPORT 0x16 +#define IGMP_LEAVE_GROUP 0x17 +#define IGMP_V3_MEMBERSHIP_REPORT 0x22 + +#define MLD_QUERY 130 +#define MLD_V1_LISTENER_REPORT 131 +#define MLD_V1_LISTENER_DONE 132 +#define MLD_V2_LISTERNER_REPORT 143 + +#define IGMPMAC_TB_ENTRY_AGEOUT_TIME (135 * OS_HZ) + +#define MULTICAST_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) & (MAX_LEN_OF_MULTICAST_FILTER_HASH_TABLE - 1)) + +#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) +#define IS_IPV6_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) == 0x33)) +#define IS_BROADCAST_MAC_ADDR(Addr) ((((Addr[0]) & 0xff) == 0xff)) + +#define IGMP_NONE 0 +#define IGMP_PKT 1 +#define IGMP_IN_GROUP 2 + + +VOID MulticastFilterTableInit( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable); + +VOID MultiCastFilterTableReset( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable); + +BOOLEAN MulticastFilterTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pGrpId, + IN PUCHAR pMemberAddr, + IN PNET_DEV dev, + IN MulticastFilterEntryType type); + +BOOLEAN MulticastFilterTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pGrpId, + IN PUCHAR pMemberAddr, + IN PNET_DEV dev, + IN MulticastFilterEntryType type); + +PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup( + IN PRTMP_ADAPTER pAd, + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PUCHAR pAddr, + IN PNET_DEV dev); + +VOID IGMPSnooping( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDstMacAddr, + IN PUCHAR pSrcMacAddr, + IN PUCHAR pIpHeader, + IN PNET_DEV pDev); + +VOID MLDSnooping( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDstMacAddr, + IN PUCHAR pSrcMacAddr, + IN PUCHAR pIpHeader, + IN PNET_DEV pDev); + +UCHAR IgmpMemberCnt( + IN PLIST_HEADER pList); + +VOID IgmpGroupDelMembers( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMemberAddr, + IN PNET_DEV pDev); + +INT Set_IgmpSn_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IgmpSn_AddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IgmpSn_DelEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IgmpSn_TabDisplay_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +void rtmp_read_igmp_snoop_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + +NDIS_STATUS IgmpPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN struct wifi_dev *wdev, + OUT INT *pInIgmpGroup, + OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry); + +NDIS_STATUS IgmpPktClone( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN INT IgmpPktInGroup, + IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry, + IN UCHAR QueIdx, + IN UINT8 UserPriority); + +#endif /* __RTMP_IGMP_SNOOP_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ipv6.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ipv6.h new file mode 100644 index 000000000..16c9b8ea9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/ipv6.h @@ -0,0 +1,205 @@ +/**************************************************************************** + * 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: + ipv6.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __IPV6_HDR_H_ +#define __IPV6_HDR_H_ + +#define IPV6_ADDR_LEN 16 +#define IPV6_HDR_LEN 40 + +/* IPv6 address definition */ +#define IPV6_LINK_LOCAL_ADDR_PREFIX 0xFE8 +#define IPV6_SITE_LOCAL_ADDR_PREFIX 0xFEC +#define IPV6_LOCAL_ADDR_PREFIX 0xFE8 +#define IPV6_MULTICAST_ADDR_PREFIX 0xFF +#define IPV6_LOOPBACK_ADDR 0x1 +#define IPV6_UNSPECIFIED_ADDR 0x0 + +/* defined as sequence in IPv6 header */ +#define IPV6_NEXT_HEADER_HOP_BY_HOP 0x00 /* 0 */ +#define IPV6_NEXT_HEADER_DESTINATION 0x3c /* 60 */ +#define IPV6_NEXT_HEADER_ROUTING 0x2b /* 43 */ +#define IPV6_NEXT_HEADER_FRAGMENT 0x2c /* 44 */ +#define IPV6_NEXT_HEADER_AUTHENTICATION 0x33 /* 51 */ +#define IPV6_NEXT_HEADER_ENCAPSULATION 0x32 /* 50, RFC-2406 */ +#define IPV6_NEXT_HEADER_NONE 0x3b /* 59 */ + +#define IPV6_NEXT_HEADER_TCP 0x06 +#define IPV6_NEXT_HEADER_UDP 0x11 +#define IPV6_NEXT_HEADER_ICMPV6 0x3a +#define IPV6_NEXT_HEADER_PIM 0x67 + +/* ICMPv6 msg type definition */ +#define ICMPV6_MSG_TYPE_ROUTER_SOLICITATION 0x85 /* 133 */ +#define ROUTER_SOLICITATION_FIXED_LEN 8 + +#define ICMPV6_MSG_TYPE_ROUTER_ADVERTISEMENT 0x86 /* 134 */ +#define ROUTER_ADVERTISEMENT_FIXED_LEN 16 + +#define ICMPV6_MSG_TYPE_NEIGHBOR_SOLICITATION 0x87 /* 135 */ +#define NEIGHBOR_SOLICITATION_FIXED_LEN 24 + +#define ICMPV6_MSG_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 /* 136 */ +#define NEIGHBOR_ADVERTISEMENT_FIXED_LEN 24 + +#define ICMPV6_MSG_TYPE_REDIRECT 0x89 /* 137 */ +#define REDIRECT_FIXED_LEN 40 + +/* IPv6 Address related structures */ +typedef struct rt_ipv6_addr_ +{ + union + { + UCHAR ipv6Addr8[16]; + USHORT ipv6Addr16[8]; + UINT32 ipv6Addr32[4]; + }addr; +#define ipv6_addr addr.ipv6Addr8 +#define ipv6_addr16 addr.ipv6Addr16 +#define ipv6_addr32 addr.ipv6Addr32 +}RT_IPV6_ADDR, *PRT_IPV6_ADDR; + + +#define PRINT_IPV6_ADDR(ipv6Addr) \ + OS_NTOHS((ipv6Addr).ipv6_addr16[0]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[1]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[2]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[3]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[4]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[5]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[6]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[7]) + + +/*IPv6 Header related structures */ +typedef struct GNU_PACKED _rt_ipv6_hdr_ +{ + UINT32 ver:4, + trafficClass:8, + flowLabel:20; + USHORT payload_len; + UCHAR nextHdr; + UCHAR hopLimit; + RT_IPV6_ADDR srcAddr; + RT_IPV6_ADDR dstAddr; +}RT_IPV6_HDR, *PRT_IPV6_HDR; + + +typedef struct GNU_PACKED _rt_ipv6_ext_hdr_ +{ + UCHAR nextProto; /* Indicate the protocol type of next extension header. */ + UCHAR extHdrLen; /* optional field for msg length of this extension header which didn't include the first "nextProto" field. */ + UCHAR octets[1]; /* hook to extend header message body. */ +}RT_IPV6_EXT_HDR, *PRT_IPV6_EXT_HDR; + + +/* ICMPv6 related structures */ +typedef struct GNU_PACKED _rt_ipv6_icmpv6_hdr_ +{ + UCHAR type; + UCHAR code; + USHORT chksum; + UCHAR octets[1]; /*hook to extend header message body. */ +}RT_ICMPV6_HDR, *PRT_ICMPV6_HDR; + + +typedef struct GNU_PACKED _rt_icmp6_option_hdr_ +{ + UCHAR type; + UCHAR len; + UCHAR octet[1]; +}RT_ICMPV6_OPTION_HDR, *PRT_ICMPV6_OPTION_HDR; + +typedef enum{ +/* Defined ICMPv6 Option Types. */ + TYPE_SRC_LL_ADDR = 1, + TYPE_TGT_LL_ADDR = 2, + TYPE_PREFIX_INFO = 3, + TYPE_REDIRECTED_HDR = 4, + TYPE_MTU = 5, +}ICMPV6_OPTIONS_TYPE_DEF; + + +static inline BOOLEAN IPv6ExtHdrHandle( + RT_IPV6_EXT_HDR *pExtHdr, + UCHAR *pProto, + UINT32 *pOffset) +{ + UCHAR nextProto = 0xff; + UINT32 extLen = 0; + BOOLEAN status = TRUE; + + /*printk("%s(): parsing the Extension Header with Protocol(0x%x):\n", __FUNCTION__, *pProto); */ + switch (*pProto) + { + case IPV6_NEXT_HEADER_HOP_BY_HOP: + /* IPv6ExtHopByHopHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = (pExtHdr->extHdrLen + 1) * 8; + break; + + case IPV6_NEXT_HEADER_DESTINATION: + /* IPv6ExtDestHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = (pExtHdr->extHdrLen + 1) * 8; + break; + + case IPV6_NEXT_HEADER_ROUTING: + /* IPv6ExtRoutingHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = (pExtHdr->extHdrLen + 1) * 8; + break; + + case IPV6_NEXT_HEADER_FRAGMENT: + /* IPv6ExtFragmentHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = 8; /* The Fragment header length is fixed to 8 bytes. */ + break; + + case IPV6_NEXT_HEADER_AUTHENTICATION: + /* IPV6_NEXT_HEADER_ENCAPSULATION: */ + /* + TODO: Not support. For encryption issue. + */ + nextProto = 0xFF; + status = FALSE; + break; + + default: + nextProto = 0xFF; + status = FALSE; + break; + } + + *pProto = nextProto; + *pOffset += extLen; + /*printk("%s(): nextProto = 0x%x!, offset=0x%x!\n", __FUNCTION__, nextProto, offset); */ + + return status; + +} + +#endif /* __IPV6_HDR_H_ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/link_list.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/link_list.h new file mode 100644 index 000000000..5f14e9e55 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/link_list.h @@ -0,0 +1,181 @@ + +#ifndef __LINK_LIST_H__ +#define __LINK_LIST_H__ + +typedef struct _LIST_ENTRY +{ + struct _LIST_ENTRY *pNext; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _LIST_HEADR +{ + PLIST_ENTRY pHead; + PLIST_ENTRY pTail; + UCHAR size; +} LIST_HEADER, *PLIST_HEADER; + +static inline VOID initList( + IN PLIST_HEADER pList) +{ + pList->pHead = pList->pTail = NULL; + pList->size = 0; + return; +} + +static inline VOID insertTailList( + IN PLIST_HEADER pList, + IN PLIST_ENTRY pEntry) +{ + pEntry->pNext = NULL; + if (pList->pTail) + pList->pTail->pNext = pEntry; + else + pList->pHead = pEntry; + pList->pTail = pEntry; + pList->size++; + + return; +} + +static inline PLIST_ENTRY removeHeadList( + IN PLIST_HEADER pList) +{ + PLIST_ENTRY pNext; + PLIST_ENTRY pEntry; + + pEntry = pList->pHead; + if (pList->pHead != NULL) + { + pNext = pList->pHead->pNext; + pList->pHead = pNext; + if (pNext == NULL) + pList->pTail = NULL; + pList->size--; + } + return pEntry; +} + +static inline int getListSize( + IN PLIST_HEADER pList) +{ + return pList->size; +} + +static inline PLIST_ENTRY delEntryList( + IN PLIST_HEADER pList, + IN PLIST_ENTRY pEntry) +{ + PLIST_ENTRY pCurEntry; + PLIST_ENTRY pPrvEntry; + + if(pList->pHead == NULL) + return NULL; + + if(pEntry == pList->pHead) + { + pCurEntry = pList->pHead; + pList->pHead = pCurEntry->pNext; + + if(pList->pHead == NULL) + pList->pTail = NULL; + + pList->size--; + return pCurEntry; + } + + pPrvEntry = pList->pHead; + pCurEntry = pPrvEntry->pNext; + while(pCurEntry != NULL) + { + if (pEntry == pCurEntry) + { + pPrvEntry->pNext = pCurEntry->pNext; + + if(pEntry == pList->pTail) + pList->pTail = pPrvEntry; + + pList->size--; + break; + } + pPrvEntry = pCurEntry; + pCurEntry = pPrvEntry->pNext; + } + + return pCurEntry; +} + + +typedef struct _DL_LIST +{ + struct _DL_LIST *Next; + struct _DL_LIST *Prev; +}DL_LIST, *PDL_LIST; + +static inline void DlListInit(struct _DL_LIST *List) +{ + List->Next = List; + List->Prev = List; +} + +static inline void DlListAdd(struct _DL_LIST *List, struct _DL_LIST *Item) +{ + Item->Next = List->Next; + Item->Prev = List; + List->Next->Prev = Item; + List->Next = Item; +} + +static inline void DlListAddTail(struct _DL_LIST *List, struct _DL_LIST *Item) +{ + DlListAdd(List->Prev, Item); +} + +static inline void DlListDel(struct _DL_LIST *Item) +{ + Item->Next->Prev = Item->Prev; + Item->Prev->Next = Item->Next; + Item->Next = NULL; + Item->Prev = NULL; +} + +static inline int DlListEmpty(struct _DL_LIST *List) +{ + return List->Next == List; +} + +static inline unsigned int DlListLen(struct _DL_LIST *List) +{ + struct _DL_LIST *Item; + unsigned int Count = 0; + + for (Item = List->Next; Item != List; Item = Item->Next) + Count++; + + return Count; +} + + +#ifndef offsetof +#define offsetof(type, member) ((long) &((type *) 0)->member) +#endif + +#define DlListEntry(item, type, member) \ + ((type *) ((char *) item - offsetof(type, member))) + +#define DlListFirst(list, type, member) \ + (DlListEmpty((list)) ? NULL : \ + DlListEntry((list)->Next, type, member)) + +#define DlListForEach(item, list, type, member) \ + for (item = DlListEntry((list)->Next, type, member); \ + &item->member != (list); \ + item = DlListEntry(item->member.Next, type, member)) + +#define DlListForEachSafe(item, n, list, type, member) \ + for (item = DlListEntry((list)->Next, type, member), \ + n = DlListEntry(item->member.Next, type, member); \ + &item->member != (list); \ + item = n, n = DlListEntry(n->member.Next, type, member)) + +#endif /* ___LINK_LIST_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/fce.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/fce.h new file mode 100644 index 000000000..7997c9ba4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/fce.h @@ -0,0 +1,94 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __FCE_H__ +#define __FCE_H__ + +#include "rt_config.h" + +#define FCE_PSE_CTRL 0x0800 +#define FCE_PARAMETERS 0x0804 +#define FCE_CSO 0x0808 +#define FCE_L2_STUFF 0x080c +#define TX_CPU_PORT_FROM_FCE_BASE_PTR 0x09A0 +#define TX_CPU_PORT_FROM_FCE_MAX_COUNT 0x09A4 +#define FCE_PDMA_GLOBAL_CONF 0x09C4 +#define TX_CPU_PORT_FROM_FCE_CPU_DESC_INDEX 0x09A8 +#define FCE_SKIP_FS 0x0A6C +#define PER_PORT_PAUSE_ENABLE_CONTROL1 0x0A38 + +#ifdef RT_BIG_ENDIAN +typedef union _L2_STUFFING_STRUC +{ + struct { + UINT32 RSV:6; + UINT32 OTHER_PORT:2; + UINT32 TS_LENGTH_EN:8; + UINT32 TS_CMD_QSEL_EN:8; + UINT32 RSV2:2; + UINT32 MVINF_BYTE_SWP:1; + UINT32 FS_WR_MPDU_LEN_EN:1; + UINT32 TX_L2_DE_STUFFING_EN:1; + UINT32 RX_L2_STUFFING_EN:1; + UINT32 QoS_L2_EN:1; + UINT32 HT_L2_EN:1; + } field; + + UINT32 word; +} L2_STUFFING_STRUC, *PL2_STUFFING_STRUC; +#else +typedef union _L2_STUFFING_STRUC +{ + struct { + UINT32 HT_L2_EN:1; + UINT32 QoS_L2_EN:1; + UINT32 RX_L2_STUFFING_EN:1; + UINT32 TX_L2_DE_STUFFING_EN:1; + UINT32 FS_WR_MPDU_LEN_EN:1; + UINT32 MVINF_BYTE_SWP:1; + UINT32 RSV2:2; + UINT32 TS_CMD_QSEL_EN:8; + UINT32 TS_LENGTH_EN:8; + UINT32 OTHER_PORT:2; + UINT32 RSV:6; + } field; + + UINT32 word; +} L2_STUFFING_STRUC, *PL2_STUFFING_STRUC; +#endif + +#define NORMAL_PKT 0x0 +#define CMD_PKT 0x1 + +#define FCE_WLAN_PORT 0x0 +#define FCE_CPU_RX_PORT 0x1 +#define FCE_CPU_TX_PORT 0x2 +#define FCE_HOST_PORT 0x3 +#define FCE_VIRTUAL_CPU_RX_PORT 0x4 +#define FCE_VIRTUAL_CPU_TX_PORT 0x5 +#define FCE_DISCARD 0x6 +#endif /*__FCE_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/mac_pci.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/mac_pci.h new file mode 100644 index 000000000..87be0556d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/mac_pci.h @@ -0,0 +1,453 @@ +/**************************************************************************** + * 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: + mac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MAC_PCI_H__ +#define __MAC_PCI_H__ + +#include "rtmp_type.h" + +#ifdef RLT_MAC +#include "mac_ral/nmac/ral_nmac_pci.h" +#endif /* RLT_MAC */ +#ifdef RTMP_MAC +#include "mac_ral/omac/ral_omac_pci.h" +#endif /* RTMP_MAC */ + +#include "mac_ral/rtmp_mac.h" +#include "chip/rtmp_phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.h" + + + +#define fRTMP_ADAPTER_NEED_STOP_TX 0 + + +/* ================================================================================= + PCI/RBUS TX / RX Frame Descriptors format + + Memory Layout + + 1. Tx Descriptor + TxD (12 bytes) + TXINFO (4 bytes) + 2. Packet Buffer + TXWI + 802.11 + 31 0 + +--------------------------------------------------------------------------+ + | SDP0[31:0] | + +-+--+---------------------+-+--+-----------------------------------------+ + |D |L0| SDL0[13:0] |B|L1| SDL1[13:0] | + +-+--+---------------------+-+--+-----------------------------------------+ + | SDP1[31:0] | + +--------------------------------------------------------------------------+ + | TXINFO | + +--------------------------------------------------------------------------+ +================================================================================= */ +/* + TX descriptor format for Tx Data/Mgmt Rings +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXD_STRUC { + /* Word 0 */ + UINT32 SDPtr0; + /* Word 1 */ + UINT32 DMADONE:1; + UINT32 LastSec0:1; + UINT32 SDLen0:14; + UINT32 Burst:1; + UINT32 LastSec1:1; + UINT32 SDLen1:14; + /* Word 2 */ + UINT32 SDPtr1; +} TXD_STRUC, *PTXD_STRUC; +#else +typedef struct GNU_PACKED _TXD_STRUC { + /* Word 0 */ + UINT32 SDPtr0; + /* Word 1 */ + UINT32 SDLen1:14; + UINT32 LastSec1:1; + UINT32 Burst:1; + UINT32 SDLen0:14; + UINT32 LastSec0:1; + UINT32 DMADONE:1; + /*Word2 */ + UINT32 SDPtr1; +} TXD_STRUC, *PTXD_STRUC; +#endif + + +/* + Rx descriptor format, Rx Ring +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 DDONE:1; + UINT32 LS0:1; + UINT32 SDL0:14; + UINT32 BURST:1; + UINT32 LS1:1; + UINT32 SDL1:14; + /* Word 2 */ + UINT32 SDP1; +}RXD_STRUC, *PRXD_STRUC; +#else +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 SDL1:14; + UINT32 LS1:1; + UINT32 BURST:1; + UINT32 SDL0:14; + UINT32 LS0:1; + UINT32 DDONE:1; + /* Word 2 */ + UINT32 SDP1; +}RXD_STRUC, *PRXD_STRUC; +#endif + +/* INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit */ +#define INT_SOURCE_CSR 0x200 + + +/* ----------------- EEPROM Related MACRO ----------------- */ + +/* 8051 firmware image for RT2860 - base address = 0x4000 */ +#define FIRMWARE_IMAGE_BASE 0x2000 +#define MAX_FIRMWARE_IMAGE_SIZE 0x2000 /* 8kbyte */ + + +/* ----------------- Frimware Related MACRO ----------------- */ +#define RTMP_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ + do{ \ + ULONG _i, _firm; \ + /* protect 8051 we will do firmware upload */ \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x10000); \ + \ + for(_i=0; _i<_FwLen; _i+=4) \ + { \ + _firm = _pFwImage[_i] + \ + (_pFwImage[_i+3] << 24) + \ + (_pFwImage[_i+2] << 16) + \ + (_pFwImage[_i+1] << 8); \ + RTMP_IO_WRITE32(_pAd, FIRMWARE_IMAGE_BASE + _i, _firm); \ + } \ + /* do 8051 firmware reset */ \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00000); \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00001); \ + \ + /* initialize BBP R/W access agent */ \ + RTMP_IO_WRITE32(_pAd, H2M_BBP_AGENT, 0); \ + RTMP_IO_WRITE32(_pAd, H2M_MAILBOX_CSR, 0); \ + }while(0) + + +/* ----------------- TX Related MACRO ----------------- */ +#define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) +#define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) + + +#define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + ((freeNum) >= (ULONG)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */ +#define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#ifdef WFA_VHT_PF +#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ + ((((pAd->force_amsdu && (_TxFrameType == TX_AMSDU_FRAME)) || (freeNum != (TX_RING_SIZE-1))) && (pAd->TxSwQueue[QueIdx].Number == 0)) || \ + (freeNum<3)\ + ) +#else +#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ + (((freeNum != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (freeNum<3)) + /*(((freeNum) != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 1)) */ +#endif /* WFA_VHT_PF */ + +#define HAL_KickOutMgmtTx(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) \ + RtmpPCIMgmtKickOut(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)*/ + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpPCI_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpPCI_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpPCI_WriteMultiTxResource(pAd, pTxBlk, frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) \ + RtmpPCI_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) + +#define HAL_LastTxIdx(_pAd, _QueIdx,_LastTxIdx) \ + if (_LastTxIdx) {}; \ + /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/ + +#define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \ + RTMP_IO_WRITE32((_pAd), (_pAd)->TxRing[(_QueIdx)].hw_cidx_addr, (_pAd)->TxRing[(_QueIdx)].TxCpuIdx) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + MiniportMMRequest(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx > _pAd->TxRing[_QueIdx].TxCpuIdx) ? \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx - _pAd->TxRing[_QueIdx].TxCpuIdx - 1) \ + : \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx + TX_RING_SIZE - _pAd->TxRing[_QueIdx].TxCpuIdx - 1); + + +#define GET_MGMTRING_FREENO(_pAd) \ + (_pAd->MgmtRing.TxSwFreeIdx > _pAd->MgmtRing.TxCpuIdx) ? \ + (_pAd->MgmtRing.TxSwFreeIdx - _pAd->MgmtRing.TxCpuIdx - 1) \ + : \ + (_pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->MgmtRing.TxCpuIdx - 1); + +#ifdef CONFIG_ANDES_SUPPORT +#define GET_CTRLRING_FREENO(_pAd) \ + (_pAd->CtrlRing.TxSwFreeIdx > _pAd->CtrlRing.TxCpuIdx) ? \ + (_pAd->CtrlRing.TxSwFreeIdx - _pAd->CtrlRing.TxCpuIdx - 1) \ + : \ + (_pAd->CtrlRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->CtrlRing.TxCpuIdx - 1); +#endif /* CONFIG_ANDES_SUPPORT */ + +/* ----------------- RX Related MACRO ----------------- */ + + +/* ----------------- ASIC Related MACRO ----------------- */ +/* reset MAC of a station entry to 0x000000000000 */ +#define RTMP_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + AsicDelWcidTab(pAd, Wcid); + +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ + AsicUpdateRxWCIDTable(pAd, pEntry->wcid, pEntry->Addr); + +#define RTMP_UPDATE_PROTECT(_pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist) \ + AsicUpdateProtect(pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist); + +#ifdef CONFIG_AP_SUPPORT +#define RTMP_AP_UPDATE_CAPABILITY_AND_ERPIE(pAd) \ + APUpdateCapabilityAndErpIe(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +/* Insert the BA bitmap to ASIC for the Wcid entry */ +#define RTMP_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ + do{ \ + UINT32 _Value = 0, _Offset; \ + _Offset = MAC_WCID_BASE + (_Aid) * HW_WCID_ENTRY_SIZE + 4; \ + RTMP_IO_READ32((_pAd), _Offset, &_Value);\ + _Value |= (0x10000<<(_TID)); \ + RTMP_IO_WRITE32((_pAd), _Offset, _Value);\ + }while(0) + + +/* Remove the BA bitmap from ASIC for the Wcid entry */ +/* bitmap field starts at 0x10000 in ASIC WCID table */ +#define RTMP_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ + do{ \ + UINT32 _Value = 0, _Offset; \ + _Offset = MAC_WCID_BASE + (_Wcid) * HW_WCID_ENTRY_SIZE + 4; \ + RTMP_IO_READ32((_pAd), _Offset, &_Value); \ + _Value &= (~(0x10000 << (_TID))); \ + RTMP_IO_WRITE32((_pAd), _Offset, _Value); \ + }while(0) + + +/* ----------------- Interface Related MACRO ----------------- */ + +typedef enum _RTMP_TX_DONE_MASK{ + TX_AC0_DONE = 0x1, + TX_AC1_DONE = 0x2, + TX_AC2_DONE = 0x4, + TX_AC3_DONE = 0x8, + TX_HCCA_DONE = 0x10, + TX_MGMT_DONE = 0x20, +}RTMP_TX_DONE_MASK; + + +/* + Enable & Disable NIC interrupt via writing interrupt mask register + Since it use ADAPTER structure, it have to be put after structure definition. +*/ +#define RTMP_ASIC_INTERRUPT_DISABLE(_pAd) \ + do{ \ + RTMP_IO_WRITE32((_pAd), INT_MASK_CSR, 0x0); /* 0: disable */ \ + RTMP_CLEAR_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ + }while(0) + +#define RTMP_ASIC_INTERRUPT_ENABLE(_pAd)\ + do{ \ + RTMP_IO_WRITE32((_pAd), INT_MASK_CSR, (_pAd)->int_enable_reg); /* 1:enable */ \ + RTMP_SET_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ + }while(0) + +#define RTMP_IRQ_ENABLE(pAd) \ + do{ \ + unsigned long _irqFlags;\ + RTMP_INT_LOCK(&pAd->irq_lock, _irqFlags);\ + /* clear garbage ints */\ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); \ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); \ + RTMP_INT_UNLOCK(&pAd->irq_lock, _irqFlags);\ + } while(0) + + +/* Disable MAC RX */ +#define RTMP_MAC_RX_DISABLE(pAd) \ + do{ \ + UINT32 value; \ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &value); \ + value &= ~(1<<3); \ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, value); \ + } while(0) + + +/* Enable MAC RX */ +#define RTMP_MAC_RX_ENABLE(pAd) \ + do{ \ + UINT32 value; \ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &value); \ + value |= (1<<3); \ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, value); \ + } while(0) + + +/* ----------------- MLME Related MACRO ----------------- */ +// TODO: shiang-usw, need to verify this to make sure that's solid enough! +//#define RTMP_MLME_HANDLER(pAd) MlmeHandler(pAd) +#define RTMP_MLME_HANDLER(pAd) RtmpMLMEUp(&((pAd)->mlmeTask)) + +#define RTMP_MLME_PRE_SANITY_CHECK(pAd) + +#define RTMP_MLME_RESET_STATE_MACHINE(pAd) \ + MlmeRestartStateMachine(pAd) + +#define RTMP_HANDLE_COUNTER_MEASURE(_pAd, _pEntry)\ + HandleCounterMeasure(_pAd, _pEntry) + +/* ----------------- Power Save Related MACRO ----------------- */ +#define RTMP_PS_POLL_ENQUEUE(pAd) EnqueuePsPoll(pAd) + + +/* For RTMPPCIePowerLinkCtrlRestore () function */ +#define RESTORE_HALT 1 +#define RESTORE_WAKEUP 2 +#define RESTORE_CLOSE 3 + +#define PowerSafeCID 1 +#define PowerRadioOffCID 2 +#define PowerWakeCID 3 +#define CID0MASK 0x000000ff +#define CID1MASK 0x0000ff00 +#define CID2MASK 0x00ff0000 +#define CID3MASK 0xff000000 + + +#ifdef CONFIG_STA_SUPPORT +#define RTMP_STA_FORCE_WAKEUP(pAd, bFromTx) \ + RT28xxPciStaAsicForceWakeup(pAd, bFromTx); + +#define RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ + RT28xxPciStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + +#define RTMP_SET_PSM_BIT(_pAd, _val) \ + MlmeSetPsmBit(_pAd, _val); +#endif /* CONFIG_STA_SUPPORT */ + +#define RTMP_MLME_RADIO_ON(pAd) \ + RT28xxPciMlmeRadioOn(pAd); + +#define RTMP_MLME_RADIO_OFF(pAd) \ + RT28xxPciMlmeRadioOFF(pAd); + +/* ----------------- Security Related MACRO ----------------- */ + +/* Set Asic WCID Attribute table */ +#define RTMP_SET_WCID_SEC_INFO(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) \ + RTMPSetWcidSecurityInfo(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) + +/* Set Asic WCID IV/EIV table */ +#define RTMP_ASIC_WCID_IVEIV_TABLE(_pAd, _Wcid, _uIV, _uEIV) \ + AsicUpdateWCIDIVEIV(_pAd, _Wcid, _uIV, _uEIV) + +/* Set Asic WCID Attribute table (offset:0x6800) */ +#define RTMP_ASIC_WCID_ATTR_TABLE(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag)\ + AsicUpdateWcidAttributeEntry(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) + +/* Set Asic Pairwise key table */ +#define RTMP_ASIC_PAIRWISE_KEY_TABLE(_pAd, _WCID, _pCipherKey) \ + AsicAddPairwiseKeyEntry(_pAd, _WCID, _pCipherKey) + +/* Set Asic Shared key table */ +#define RTMP_ASIC_SHARED_KEY_TABLE(_pAd, _BssIndex, _KeyIdx, _pCipherKey) \ + AsicAddSharedKeyEntry(_pAd, _BssIndex, _KeyIdx, _pCipherKey) + +#ifdef CONFIG_STA_SUPPORT +/* Set Port Secured */ +#define RTMP_SET_PORT_SECURED(_pAd) \ + STA_PORT_SECURED(_pAd); +#endif /* CONFIG_STA_SUPPORT */ + +/* Remove Pairwise Key table */ +#define RTMP_REMOVE_PAIRWISE_KEY_ENTRY(_pAd, _Wcid)\ + AsicRemovePairwiseKeyEntry(_pAd, _Wcid) + +#ifdef PCI_MSI_SUPPORT +#define RTMP_OS_IRQ_RELEASE(_pAd, _NetDev) \ +{ \ + POS_COOKIE pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + RtmpOSIRQRelease(_NetDev, pAd->infType, pObj->pci_dev, &_pAd->HaveMsi); \ +} +#else +#define RTMP_OS_IRQ_RELEASE(_pAd, _NetDev) \ +{ \ + POS_COOKIE pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + RtmpOSIRQRelease(_NetDev, pAd->infType, pObj->pci_dev, NULL); \ +} +#endif /* PCI_MSI_SUPPORT */ + + +struct _RTMP_ADAPTER; +enum _RTMP_TX_DONE_MASK; + +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct _RTMP_ADAPTER *pAd, enum _RTMP_TX_DONE_MASK tx_mask); +VOID RTMPHandleMgmtRingDmaDoneInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandleTBTTInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandlePreTBTTInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandleRxCoherentInterrupt(struct _RTMP_ADAPTER *pAd); + +VOID RTMPHandleMcuInterrupt(struct _RTMP_ADAPTER *pAd); +void RTMPHandleTwakeupInterrupt(struct _RTMP_ADAPTER *pAd); + +VOID AsicInitTxRxRing(struct _RTMP_ADAPTER *pAd); + +#endif /*__MAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac.h new file mode 100644 index 000000000..1aa587459 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac.h @@ -0,0 +1,1124 @@ +/* + *************************************************************************** + * 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: + ral_nmac.h + + Abstract: + Ralink Wireless Chip RAL MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_NMAC_H__ +#define __RAL_NMAC_H__ + +enum INFO_TYPE { + NORMAL_PACKET, + CMD_PACKET, +}; + +enum D_PORT { + WLAN_PORT, + CPU_RX_PORT, + CPU_TX_PORT, + HOST_PORT, + VIRTUAL_CPU_RX_PORT, + VIRTUAL_CPU_TX_PORT, + DISCARD, +}; + +#include "rtmp_type.h" + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXINFO_NMAC_PKT{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 QSEL:2; + UINT32 wiv:1; + UINT32 rsv1:2; + UINT32 cso:1; + UINT32 tso:1; + UINT32 pkt_80211:1; + UINT32 rsv0:1; + UINT32 tx_burst:1; + UINT32 next_vld:1; + UINT32 pkt_len:16; +}TXINFO_NMAC_PKT; +#else +typedef struct GNU_PACKED _TXINFO_NMAC_PKT { + UINT32 pkt_len:16; + UINT32 next_vld:1; + UINT32 tx_burst:1; + UINT32 rsv0:1; + UINT32 pkt_80211:1; + UINT32 tso:1; + UINT32 cso:1; + UINT32 rsv1:2; + UINT32 wiv:1; + UINT32 QSEL:2; + UINT32 d_port:3; + UINT32 info_type:2; +}TXINFO_NMAC_PKT; +#endif /* RT_BIG_ENDIAN */ + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXINFO_NMAC_CMD{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 cmd_type:7; + UINT32 cmd_seq:4; + UINT32 pkt_len:16; +}TXINFO_NMAC_CMD; +#else +typedef struct GNU_PACKED _TXINFO_NMAC_CMD{ + UINT32 pkt_len:16; + UINT32 cmd_seq:4; + UINT32 cmd_type:7; + UINT32 d_port:3; + UINT32 info_type:2; +}TXINFO_NMAC_CMD; +#endif /* RT_BIG_ENDIAN */ + + +typedef union GNU_PACKED _TXINFO_NMAC{ + struct _TXINFO_NMAC_PKT txinfo_pkt; + struct _TXINFO_NMAC_CMD txinfo_cmd; +}TXINFO_NMAC; + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _LED_NMAC_CMD{ + UINT32 rsv:8; + UINT32 CmdID:8; + UINT32 Arg0:8; + UINT32 Arg1:8; +}LED_NMAC_CMD; +#else +typedef struct GNU_PACKED _LED_NMAC_CMD{ + UINT32 Arg1:8; + UINT32 Arg0:8; + UINT32 CmdID:8; + UINT32 rsv:8; +}LED_NMAC_CMD; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_NMAC { + /* Word 0 */ + UINT32 PHYMODE:3; + UINT32 iTxBF:1; + UINT32 eTxBF:1; + UINT32 STBC:1; + UINT32 ShortGI:1; + UINT32 BW:2; /* channel bandwidth 20/40/80 MHz */ + UINT32 LDPC:1; + UINT32 MCS:6; + + UINT32 lut_en:1; + UINT32 Sounding:1; + UINT32 NDPSndBW:2; /* NDP sounding BW */ + UINT32 RTSBWSIG:1; + UINT32 NDPSndRate:1; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 txop:2; + + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + + /* Word 1 */ + UINT32 TIM:1; + UINT32 TXBF_PT_SCA:1; + UINT32 MPDUtotalByteCnt:14; + UINT32 wcid:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + + /* Word 2 */ + UINT32 IV; + /* Word 3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 TxPktId:8; + UINT32 GroupID:1; + UINT32 Rsv4:3; + //UINT32 Rsv4:4; + UINT32 TxPwrAdj:4; + UINT32 TxStreamMode:8; + UINT32 TxEAPId:8; +} TXWI_NMAC; +#else +typedef struct GNU_PACKED _TXWI_NMAC { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 CFACK:1; + UINT32 TS:1; + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + + UINT32 txop:2; + UINT32 NDPSndRate:1; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 RTSBWSIG:1; + UINT32 NDPSndBW:2; /* NDP sounding BW */ + UINT32 Sounding:1; + UINT32 lut_en:1; + + UINT32 MCS:6; + UINT32 LDPC:1; + UINT32 BW:2; /*channel bandwidth 20/40/80 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:1; + UINT32 eTxBF:1; + UINT32 iTxBF:1; + UINT32 PHYMODE:3; + + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCnt = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 wcid:8; + UINT32 MPDUtotalByteCnt:14; + UINT32 TXBF_PT_SCA:1; + UINT32 TIM:1; + + /*Word2 */ + UINT32 IV; + + /*Word3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 TxEAPId:8; + UINT32 TxStreamMode:8; + UINT32 TxPwrAdj:4; + //UINT32 Rsv4:4; + UINT32 Rsv4:3; + UINT32 GroupID:1; + UINT32 TxPktId:8; +} TXWI_NMAC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_XMAC { + /* Word 0 */ + UINT32 PHYMODE:2; + UINT32 rsv0_27:3; + UINT32 STBC:2; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 MCS:7; + + UINT32 TXLUT:1; + UINT32 TXRPT:1; + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 txop:2; + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + + /* Word 1 */ + UINT32 PacketId:4; + UINT32 MPDUtotalByteCnt:12; + UINT32 wcid:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + + /* Word 2 */ + UINT32 IV; + + /* Word 3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 rsv4_23:9; + UINT32 PIFSREV:1; + UINT32 rsv4_21:1; + UINT32 CCP:1; + UINT32 TxPwrAdj:4; + UINT32 TxStreamMode:8; + UINT32 EncodedAntID:8; +} TXWI_XMAC; +#else +typedef struct GNU_PACKED _TXWI_XMAC { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 CFACK:1; + UINT32 TS:1; + + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + UINT32 txop:2; /*FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 TXRPT:1; + UINT32 TXLUT:1; + + UINT32 MCS:7; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:2; /* 1: STBC support MCS =0-7, 2,3 : RESERVE */ + UINT32 rsv0_27:3; + UINT32 PHYMODE:2; + + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCnt = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 wcid:8; + UINT32 MPDUtotalByteCnt:12; + UINT32 PacketId:4; + + /*Word2 */ + UINT32 IV; + + /*Word3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 EncodedAntID:8; + UINT32 TxStreamMode:8; + UINT32 TxPwrAdj:4; + UINT32 rsv4_21:1; + UINT32 CCP:1; + UINT32 PIFSREV:1; + UINT32 rsv4_23:9; +} TXWI_XMAC; +#endif + + + +#ifdef HDR_TRANS_SUPPORT +#define TX_WIFI_INFO_SIZE 4 +#define RX_WIFI_INFO_SIZE 36 +#define RX_WIFI_INFO_PAD 2 +#else +#define TX_WIFI_INFO_SIZE 0 +#define RX_WIFI_INFO_SIZE 0 +#define RX_WIFI_INFO_PAD 0 +#endif +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_WIFI_INFO { + struct { + UINT32 More_Data:1; + UINT32 WEP:1; + UINT32 PS:1; + UINT32 RDG:1; + UINT32 QoS:1; + UINT32 EOSP:1; + UINT32 TID:4; + UINT32 Mode:2; + UINT32 VLAN:1; + UINT32 Rsv:3; + UINT32 BssIdx:4; + UINT32 Seq_Num:12; + } field; + UINT32 word; +} TX_WIFI_INFO; +#else +typedef union GNU_PACKED _TX_WIFI_INFO { + struct { + UINT32 Seq_Num:12; + UINT32 BssIdx:4; + UINT32 Rsv:3; + UINT32 VLAN:1; + UINT32 Mode:2; + UINT32 TID:4; + UINT32 EOSP:1; + UINT32 QoS:1; + UINT32 RDG:1; + UINT32 PS:1; + UINT32 WEP:1; + UINT32 More_Data:1; + } field; + UINT32 word; +} TX_WIFI_INFO; +#endif /* RT_BIG_ENDIAN */ + + +typedef struct GNU_PACKED _RX_WIFI_INFO{ + UINT8 wifi_hdr[36]; +}RX_WIFI_INFO; + + + + +/* + Rx Memory layout: + + 1. Rx Descriptor + Rx Descriptor(12 Bytes) + RX_FCE_Info(4 Bytes) + 2. Rx Buffer + RxInfo(4 Bytes) + RXWI() + 802.11 packet +*/ + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXFCE_INFO{ + UINT32 info_type:2; + UINT32 s_port:3; + UINT32 qsel:2; + UINT32 pcie_intr:1; + + UINT32 mac_len:3; + UINT32 l3l4_done:1; + UINT32 pkt_80211:1; + UINT32 ip_err:1; + UINT32 tcp_err:1; + UINT32 udp_err:1; + + UINT32 rsv:2; + UINT32 pkt_len:14; +}RXFCE_INFO; +#else +typedef struct GNU_PACKED _RXFCE_INFO{ + UINT32 pkt_len:14; + UINT32 rsv:2; + + UINT32 udp_err:1; + UINT32 tcp_err:1; + UINT32 ip_err:1; + UINT32 pkt_80211:1; + UINT32 l3l4_done:1; + UINT32 mac_len:3; + + UINT32 pcie_intr:1; + UINT32 qsel:2; + UINT32 s_port:3; + UINT32 info_type:2; +}RXFCE_INFO; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXFCE_INFO_CMD{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 qsel:2; + UINT32 pcie_intr:1; + UINT32 evt_type:4; + UINT32 cmd_seq:4; + UINT32 self_gen:1; + UINT32 rsv:1; + UINT32 pkt_len:14; +}RXFCE_INFO_CMD; +#else +typedef struct GNU_PACKED _RXFCE_INFO_CMD{ + UINT32 pkt_len:14; + UINT32 rsv:1; + UINT32 self_gen:1; + UINT32 cmd_seq:4; + UINT32 evt_type:4; + UINT32 pcie_intr:1; + UINT32 qsel:2; + UINT32 d_port:3; + UINT32 info_type:2; +}RXFCE_INFO_CMD; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXINFO_NMAC{ + UINT32 hdr_trans:1; + UINT32 vlan_tag:1; + UINT32 rsv:1; + UINT32 action_wanted:1; + UINT32 deauth:1; + UINT32 disasso:1; + UINT32 beacon:1; + UINT32 probe_rsp:1; + UINT32 sw_fc_type1:1; + UINT32 sw_fc_type0:1; + UINT32 pn_len:3; + UINT32 wapi_kid:1; + UINT32 bssid_idx3:1; + UINT32 dec:1; + UINT32 ampdu:1; + UINT32 l2pad:1; + UINT32 rssi:1; + UINT32 htc:1; + UINT32 amsdu:1; + UINT32 mic_err:1; + UINT32 icv_err:1; + UINT32 crc_err:1; + UINT32 mybss:1; + UINT32 bc:1; + UINT32 mc:1; + UINT32 u2me:1; + UINT32 frag:1; + UINT32 null:1; + UINT32 data:1; + UINT32 ba:1; +}RXINFO_NMAC; +#else +typedef struct GNU_PACKED _RXINFO_NMAC{ + UINT32 ba:1; + UINT32 data:1; + UINT32 null:1; + UINT32 frag:1; + UINT32 u2me:1; + UINT32 mcast:1; + UINT32 bcast:1; + UINT32 mybss:1; + UINT32 crc_err:1; + UINT32 icv_err:1; + UINT32 mic_err:1; + UINT32 amsdu:1; + UINT32 htc:1; + UINT32 rssi:1; + UINT32 l2pad:1; + UINT32 ampdu:1; + UINT32 dec:1; + UINT32 bssid_idx3:1; + UINT32 wapi_kid:1; + UINT32 pn_len:3; + UINT32 sw_fc_type0:1; + UINT32 sw_fc_type1:1; + UINT32 probe_rsp:1; + UINT32 beacon:1; + UINT32 disasso:1; + UINT32 deauth:1; + UINT32 action_wanted:1; + UINT32 rsv:1; + UINT32 vlan_tag:1; + UINT32 hdr_trans:1; +}RXINFO_NMAC; +#endif /* RT_BIG_ENDIAN */ + + +/* + RXWI wireless information format. +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXWI_NMAC{ + /* Word 0 */ + UINT32 eof:1; + UINT32 rsv:1; + UINT32 MPDUtotalByteCnt:14; /* = rxfceinfo_len - rxwi_len- rxinfo_len - l2pad */ + UINT32 udf:3; + UINT32 bss_idx:3; + UINT32 key_idx:2; + UINT32 wcid:8; + + /* Word 1 */ + UINT32 phy_mode:3; + UINT32 rsv_1:1; + UINT32 ldpc_ex_sym:1; + UINT32 stbc:1; + UINT32 sgi:1; + UINT32 bw:2; + UINT32 ldpc:1; + UINT32 mcs:6; + UINT32 sn:12; + UINT32 tid:4; + + /* Word 2 */ + UINT8 rssi[4]; + + /* Word 3~6 */ + UINT8 bbp_rxinfo[16]; +} RXWI_NMAC; +#else +typedef struct GNU_PACKED _RXWI_NMAC { + /* Word 0 */ + UINT32 wcid:8; + UINT32 key_idx:2; + UINT32 bss_idx:3; + UINT32 udf:3; + UINT32 MPDUtotalByteCnt:14; + UINT32 rsv:1; + UINT32 eof:1; + + /* Word 1 */ + UINT32 tid:4; + UINT32 sn:12; + UINT32 mcs:6; + UINT32 ldpc:1; + UINT32 bw:2; + UINT32 sgi:1; + UINT32 stbc:1; + UINT32 ldpc_ex_sym:1; + UINT32 rsv_1:1; + UINT32 phy_mode:3; + + /* Word 2 */ + UINT8 rssi[4]; + + /* Word 3~6 */ + UINT8 bbp_rxinfo[16]; +} RXWI_NMAC; +#endif /* RT_BIG_ENDIAN */ + +typedef struct GNU_PACKED _NMAC_HW_RATE_CTRL_STRUCT{ +#ifdef RT_BIG_ENDIAN + UINT16 PHYMODE:3; + UINT16 iTxBF:1; + UINT16 eTxBF:1; + UINT16 STBC:1; + UINT16 ShortGI:1; + UINT16 BW:2; /* channel bandwidth 20/40/80 MHz */ + UINT16 ldpc:1; + UINT16 MCS:6; +#else + UINT16 MCS:6; + UINT16 ldpc:1; + UINT16 BW:2; + UINT16 ShortGI:1; + UINT16 STBC:1; + UINT16 eTxBF:1; + UINT16 iTxBF:1; + UINT16 PHYMODE:3; +#endif /* RT_BIG_ENDIAN */ +}NMAC_HW_RATE_CTRL_STRUCT; + + + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ +#define CMB_CTRL 0x0020 +#define CMB_CTRL_AUX_OPT_MASK (0xffff) +#define CMB_CTRL_AUX_OPT_ANTSEL (1 << 12) +#define CMB_CTRL_AUX_OPT_GPIO_SETTING (1 << 14) +#define CMB_CTRL_CSR_UART_MODE (1 << 16) +#define CMB_CTRL_GPIO_MODE_LED1 (1 << 17) +#define CMB_CTRL_GPIO_MODE_LED2 (1 << 18) +#define CMB_CTRL_FOR_CLK_XTAL (1 << 19) +#define CMB_CTRL_CSR_UART_NFC (1 << 20) +#define CMB_CTRL_XTAL_RDY (1 << 22) +#define CMB_CTRL_PLL_LD (1 << 23) + +#define COEXCFG0 0x0040 +#define COEXCFG0_COEX_EN (1 << 0) +#define COEXCFG0_FIX_WL_DI_ANT (1 << 1) +#define COEXCFG0_FIX_WL_ANT_EN (1 << 2) +#define COEXCFG0_FIX_WL_TX_PWR_MASK (0x3 << 6) +#define COEXCFG0_FIX_WL_GCRF_EN (1 << 8) +#define COEXCFG0_FIX_WL_RF_LNA0_MASK (0x3 << 12) +#define COEXCFG0_FIX_WL_RF_LNA1_MASK (0x3 << 14) +#define COEXCFG0_COEX_CFG0_MASK (0xff << 16) +#define COEXCFG0_COEX_CFG1_MASK (0xff << 24) + +#define COEXCFG1 0x0044 +#define COEXCFG1_DIS_WL_TR_DELAY_MASK (0xff << 0) +#define COEXCFG1_DIS_WL_PA_DELAY_MASK (0xff << 8) +#define COEXCFG1_DIS_WL_RF_DELAY_MASK (0xff << 16) +#define COEXCFG1_FIX_WL_TX_GCRF0_MASK (0xf << 24) +#define COEXCFG1_FIX_WL_TX_GCRF1_MASK (0xf << 28) + +#define COEXCFG2 0x0048 +#define COEXCFG2_WL_COEX_CFG0_MASK (0xff << 0) +#define COEXCFG2_WL_COEX_CFG1_MASK (0xff << 8) +#define COEXCFG2_BT_COEX_CFG0_MASK (0xff << 16) +#define COEXCFG2_BT_COEX_CFG1_MASK (0xff << 24) + +#define COEXCFG3 0x004c +#define COEXCFG3_COEX_VER (1 << 0) +#define COEXCFG3_TDM_EN (1 << 1) +#define COEXCFG3_IO_TR_SW0_MODE (1 << 2) +#define COEXCFG3_CSR_FRC_TR_SW0 (1 << 3) +#define COEXCFG3_FIX_IO_ANT_SEL_EN (1 << 4) +#define COEXCFG3_REG_IO_ANT_SEL_EN (1 << 5) +#define COEXCFG3_PTA_CNT_CLEAR (1 << 6) +#define COEXCFG3_PTA_CNT_EN (1 << 7) +#define COEXCFG3_BT_TX_STATUS (1 << 16) + +#define MISC_CTRL 0x64 + +#define WLAN_FUN_CTRL 0x80 +#define WLAN_FUN_CTRL_WLAN_EN (1 << 0) +#define WLAN_FUN_CTRL_WLAN_CLK_EN (1 << 1) +#define WLAN_FUN_CTRL_WLAN_RESET_RF (1 << 2) + +/* MT76x0 definition */ +#define WLAN_FUN_CTRL_WLAN_RESET (1 << 3) + +/* MT76x2 definition */ +#define WLAN_FUN_CTRL_CSR_F20M_CKEN (1 << 3) + +#define WLAN_FUN_CTRL_PCIE_APP0_CLK_REQ (1 << 4) +#define WLAN_FUN_CTRL_FRC_WL_ANT_SEL (1 << 5) +#define WLAN_FUN_CTRL_INV_ANT_SEL (1 << 6) +#define WLAN_FUN_CTRL_WAKE_HOST_F0 (1 << 7) + +/* MT76x0 definition */ +#define WLAN_FUN_CTRL_GPIO0_IN_MASK (0xff << 8) +#define WLAN_FUN_CTRL_GPIO0_OUT_MASK (0xff << 16) +#define WLAN_FUN_CTRL_GPIO0_OUT_OE_N_MASK (0xff << 24) + +/* MT76x2 definition */ +#define WLAN_FUN_CTRL_THERM_RST (1 << 8) +#define WLAN_FUN_CTRL_THERM_CKEN (1 << 9) + +#ifdef RT_BIG_ENDIAN +typedef union _WLAN_FUN_CTRL_STRUC{ + struct{ + UINT32 GPIO0_OUT_OE_N:8; + UINT32 GPIO0_OUT:8; + UINT32 GPIO0_IN:8; + UINT32 WLAN_ACC_BT:1; + UINT32 INV_TR_SW0:1; + UINT32 FRC_WL_ANT_SET:1; + UINT32 PCIE_APP0_CLK_REQ:1; + UINT32 WLAN_RESET:1; + UINT32 WLAN_RESET_RF:1; + UINT32 WLAN_CLK_EN:1; + UINT32 WLAN_EN:1; + }field; + UINT32 word; +}WLAN_FUN_CTRL_STRUC, *PWLAN_FUN_CTRL_STRUC; +#else +typedef union _WLAN_FUN_CTRL_STRUC{ + struct{ + UINT32 WLAN_EN:1; + UINT32 WLAN_CLK_EN:1; + UINT32 WLAN_RESET_RF:1; + UINT32 WLAN_RESET:1; + UINT32 PCIE_APP0_CLK_REQ:1; + UINT32 FRC_WL_ANT_SET:1; + UINT32 INV_TR_SW0:1; + UINT32 WLAN_ACC_BT:1; + UINT32 GPIO0_IN:8; + UINT32 GPIO0_OUT:8; + UINT32 GPIO0_OUT_OE_N:8; + }field; + UINT32 word; +}WLAN_FUN_CTRL_STRUC, *PWLAN_FUN_CTRL_STRUC; +#endif + + +#define WLAN_FUN_INFO 0x84 +#ifdef RT_BIG_ENDIAN +typedef union _WLAN_FUN_INFO_STRUC{ + struct{ + UINT32 BT_EEP_BUSY:1; /* Read-only for WLAN Driver */ + UINT32 Rsv1:26; + UINT32 COEX_MODE:5; /* WLAN function enable */ + }field; + UINT32 word; +}WLAN_FUN_INFO_STRUC, *PWLAN_FUN_INFO_STRUC; +#else +typedef union _WLAN_FUN_INFO_STRUC{ + struct{ + UINT32 COEX_MODE:5; /* WLAN function enable */ + UINT32 Rsv1:26; + UINT32 BT_EEP_BUSY:1; /* Read-only for WLAN Driver */ + }field; + UINT32 word; +}WLAN_FUN_INFO_STRUC, *PWLAN_FUN_INFO_STRUC; +#endif + + +#define BT_FUN_CTRL 0xC0 +#ifdef RT_BIG_ENDIAN +typedef union _BT_FUN_CTRL_STRUC{ + struct{ + UINT32 GPIO1_OUT_OE_N:8; + UINT32 GPIO1_OUT:8; + UINT32 GPIO1_IN:8; + UINT32 BT_ACC_WLAN:1; + UINT32 INV_TR_SW1:1; + UINT32 URXD_GPIO_MODE:1; + UINT32 PCIE_APP1_CLK_REQ:1; + UINT32 BT_RESET:1; + UINT32 BT_RF_EN:1; + UINT32 BT_CLK_EN:1; + UINT32 BT_EN:1; + }field; + UINT32 word; +}BT_FUN_CTRL_STRUC, *PBT_FUN_CTRL_STRUC; +#else +typedef union _BT_FUN_CTRL_STRUC { + struct{ + UINT32 BT_EN:1; + UINT32 BT_CLK_EN:1; + UINT32 BT_RF_EN:1; + UINT32 BT_RESET:1; + UINT32 PCIE_APP1_CLK_REQ:1; + UINT32 URXD_GPIO_MODE:1; + UINT32 INV_TR_SW1:1; + UINT32 BT_ACC_WLAN:1; + UINT32 GPIO1_IN:8; + UINT32 GPIO1_OUT:8; + UINT32 GPIO1_OUT_OE_N:8; + }field; + UINT32 word; +}BT_FUN_CTRL_STRUC, *PBT_FUN_CTRL_STRUC; +#endif + + +#define BT_FUN_INFO 0xC4 +#ifdef RT_BIG_ENDIAN +typedef union _BT_FUN_INFO_STRUC{ + struct{ + UINT32 WLAN_EEP_BUSY:1; + UINT32 BTPower1:7; /* Peer */ + UINT32 BTPower0:8; /* Self */ + UINT32 AFH_END_CH:8; + UINT32 AFH_START_CH:8; + }field; + UINT32 word; +} BT_FUN_INFO_STRUC, *PBT_FUN_INFO_STRUC; +#else +typedef union _BT_FUN_INFO_STRUC { + struct{ + UINT32 AFH_START_CH:8; + UINT32 AFH_END_CH:8; + UINT32 BTPower0:8; /* Self */ + UINT32 BTPower1:7; /* Peer */ + UINT32 WLAN_EEP_BUSY:1; + }field; + UINT32 word; +}BT_FUN_INFO_STRUC, *PBT_FUN_INFO_STRUC; +#endif + +// TODO: shiang, this data structure is not defined for register. may can move to other place +typedef struct _WLAN_BT_COEX_SETTING +{ + BOOLEAN ampduOff; + BOOLEAN coexSettingRunning; + BOOLEAN RateSelectionForceToUseRSSI; + UCHAR TxQualityFlag; + ULONG alc; + ULONG slna; +}WLAN_BT_COEX_SETTING, *PWLAN_BT_COEX_SETTING; + +#define XO_CTRL0 0x0100 +#define XO_CTRL1 0x0104 +#define XO_CTRL2 0x0108 +#define XO_CTRL3 0x010C +#define XO_CTRL4 0x0110 +#define XO_CTRL5 0x0114 +#define XO_CTRL6 0x0118 + +#define CLK_ENABLE 0x014C + +#define MCU_CMD_CFG 0x0234 + + +#define TSO_CTRL 0x0250 +#ifdef RT_BIG_ENDIAN +typedef union _TSO_CTRL_STRUC { + struct { + UINT32 rsv:13; + UINT32 TSO_WR_LEN_EN:1; + UINT32 TSO_SEG_EN:1; + UINT32 TSO_EN:1; + UINT32 RXWI_LEN:4; + UINT32 RX_L2_FIX_LEN:4; + UINT32 TXWI_LEN:4; + UINT32 TX_L2_FIX_LEN:4; + } field; + UINT32 word; +} TSO_CTRL_STRUC; +#else +typedef union _TSO_CTRL_STRUC { + struct { + UINT32 TX_L2_FIX_LEN:4; + UINT32 TXWI_LEN:4; + UINT32 RX_L2_FIX_LEN:4; + UINT32 RXWI_LEN:4; + UINT32 TSO_EN:1; + UINT32 TSO_SEG_EN:1; + UINT32 TSO_WR_LEN_EN:1; + UINT32 rsv:13; + } field; + UINT32 word; +} TSO_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#define TX_PROT_CFG6 0x13E0 // VHT 20 Protection +#define TX_PROT_CFG7 0x13E4 // VHT 40 Protection +#define TX_PROT_CFG8 0x13E8 // VHT 80 Protection +#define PIFS_TX_CFG 0x13EC // PIFS setting + +//---------------------------------------------------------------- +// Header Translation +//---------------------------------------------------------------- + +/* + header translation control register + bit0 --> TX translation enable + bit1 --> RX translation enable +*/ +#define HEADER_TRANS_CTRL_REG 0x0260 +#define HT_TX_ENABLE 0x1 +#define HT_RX_ENABLE 0x2 + +#define HT_MAC_ADDR_DW0 0x02A4 +#define HT_MAC_ADDR_DW1 0x02A8 +#define HT_MAC_BSSID_DW0 0x02AC +#define HT_MAC_BSSID_DW1 0x02B0 + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HDR_TRANS_CTRL_STRUC { + struct { + UINT32 Rsv:30; + UINT32 Rx_En:1; + UINT32 Tx_En:1; + } field; + UINT32 word; +} HDR_TRANS_CTRL_STRUC, *PHDR_TRANS_CTRL_STRUC; +#else +typedef union GNU_PACKED _HDR_TRANS_CTRL_STRUC { + struct { + UINT32 Tx_En:1; + UINT32 Rx_En:1; + UINT32 Rsv:30; + } field; + UINT32 word; +} HDR_TRANS_CTRL_STRUC, *PHDR_TRANS_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* RX header translation enable by WCID */ +#define HT_RX_WCID_EN_BASE 0x0264 +#define HT_RX_WCID_OFFSET 32 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HT_RX_WCID_EN_STRUC { + struct { + UINT32 RX_WCID31_TRAN_EN:1; + UINT32 RX_WCID30_TRAN_EN:1; + UINT32 RX_WCID29_TRAN_EN:1; + UINT32 RX_WCID28_TRAN_EN:1; + UINT32 RX_WCID27_TRAN_EN:1; + UINT32 RX_WCID26_TRAN_EN:1; + UINT32 RX_WCID25_TRAN_EN:1; + UINT32 RX_WCID24_TRAN_EN:1; + UINT32 RX_WCID23_TRAN_EN:1; + UINT32 RX_WCID22_TRAN_EN:1; + UINT32 RX_WCID21_TRAN_EN:1; + UINT32 RX_WCID20_TRAN_EN:1; + UINT32 RX_WCID19_TRAN_EN:1; + UINT32 RX_WCID18_TRAN_EN:1; + UINT32 RX_WCID17_TRAN_EN:1; + UINT32 RX_WCID16_TRAN_EN:1; + UINT32 RX_WCID15_TRAN_EN:1; + UINT32 RX_WCID14_TRAN_EN:1; + UINT32 RX_WCID13_TRAN_EN:1; + UINT32 RX_WCID12_TRAN_EN:1; + UINT32 RX_WCID11_TRAN_EN:1; + UINT32 RX_WCID10_TRAN_EN:1; + UINT32 RX_WCID9_TRAN_EN:1; + UINT32 RX_WCID8_TRAN_EN:1; + UINT32 RX_WCID7_TRAN_EN:1; + UINT32 RX_WCID6_TRAN_EN:1; + UINT32 RX_WCID5_TRAN_EN:1; + UINT32 RX_WCID4_TRAN_EN:1; + UINT32 RX_WCID3_TRAN_EN:1; + UINT32 RX_WCID2_TRAN_EN:1; + UINT32 RX_WCID1_TRAN_EN:1; + UINT32 RX_WCID0_TRAN_EN:1; + } field; + UINT32 word; +} HT_RX_WCID_EN_STRUC, *PHT_RX_WCID_EN_STRUC; +#else +typedef union GNU_PACKED _HT_RX_WCID_EN_STRUC { + struct { + UINT32 RX_WCID0_TRAN_EN:1; + UINT32 RX_WCID1_TRAN_EN:1; + UINT32 RX_WCID2_TRAN_EN:1; + UINT32 RX_WCID3_TRAN_EN:1; + UINT32 RX_WCID4_TRAN_EN:1; + UINT32 RX_WCID5_TRAN_EN:1; + UINT32 RX_WCID6_TRAN_EN:1; + UINT32 RX_WCID7_TRAN_EN:1; + UINT32 RX_WCID8_TRAN_EN:1; + UINT32 RX_WCID9_TRAN_EN:1; + UINT32 RX_WCID10_TRAN_EN:1; + UINT32 RX_WCID11_TRAN_EN:1; + UINT32 RX_WCID12_TRAN_EN:1; + UINT32 RX_WCID13_TRAN_EN:1; + UINT32 RX_WCID14_TRAN_EN:1; + UINT32 RX_WCID15_TRAN_EN:1; + UINT32 RX_WCID16_TRAN_EN:1; + UINT32 RX_WCID17_TRAN_EN:1; + UINT32 RX_WCID18_TRAN_EN:1; + UINT32 RX_WCID19_TRAN_EN:1; + UINT32 RX_WCID20_TRAN_EN:1; + UINT32 RX_WCID21_TRAN_EN:1; + UINT32 RX_WCID22_TRAN_EN:1; + UINT32 RX_WCID23_TRAN_EN:1; + UINT32 RX_WCID24_TRAN_EN:1; + UINT32 RX_WCID25_TRAN_EN:1; + UINT32 RX_WCID26_TRAN_EN:1; + UINT32 RX_WCID27_TRAN_EN:1; + UINT32 RX_WCID28_TRAN_EN:1; + UINT32 RX_WCID29_TRAN_EN:1; + UINT32 RX_WCID30_TRAN_EN:1; + UINT32 RX_WCID31_TRAN_EN:1; + } field; + UINT32 word; +} HT_RX_WCID_EN_STRUC, *PHT_RX_WCID_EN_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* RX header translation - black list */ +#define HT_RX_BL_BASE 0x0284 +#define HT_RX_BL_OFFSET 2 +#define HT_RX_BL_SIZE 8 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HT_RX_BLACK_LIST_STRUC { + struct { + UINT32 BLACK_ETHER_TYPE1:16; + UINT32 BLACK_ETHER_TYPE0:16; + } field; + UINT32 word; +} HT_RX_BLACK_LIST_STRUC, *PHT_RX_BLACK_LIST_STRUC; +#else +typedef union GNU_PACKED _HT_RX_BLACK_LIST_STRUC { + struct { + UINT32 BLACK_ETHER_TYPE0:16; + UINT32 BLACK_ETHER_TYPE1:16; + } field; + UINT32 word; +} HT_RX_BLACK_LIST_STRUC, *PHT_RX_BLACK_LIST_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* RX VLAN Mapping (TCI) */ +#define HT_BSS_VLAN_BASE 0x0294 +#define HT_BSS_VLAN_OFFSET 2 +#define HT_BSS_VLAN_SIZE 8 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HT_BSS_VLAN_STRUC { + struct { + UINT32 TCI1_VID:12; + UINT32 TCI1_CFI:1; + UINT32 TCI1_PCP:3; + UINT32 TCI0_VID:12; + UINT32 TCI0_CFI:1; + UINT32 TCI0_PCP:3; + } field; + UINT32 word; +} HT_BSS_VLAN_STRUC, *PHT_BSS_VLAN_STRUC; +#else +typedef union GNU_PACKED _HT_BSS_VLAN_STRUC { + struct { + UINT32 TCI0_PCP:3; + UINT32 TCI0_CFI:1; + UINT32 TCI0_VID:12; + UINT32 TCI1_PCP:3; + UINT32 TCI1_CFI:1; + UINT32 TCI1_VID:12; + } field; + UINT32 word; +} HT_BSS_VLAN_STRUC, *PHT_BSS_VLAN_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +// TODO: shiang-6590, following definitions are dummy and not used for RT6590, shall remove/correct these! +#define GPIO_CTRL_CFG 0x0228 +#define RLT_PBF_MAX_PCNT 0x0408 //TX_MAX_PCNT +// TODO:shiang-6590 -------------------------- + + +#define RF_MISC 0x0518 +#ifdef RT_BIG_ENDIAN +typedef union _RF_MISC_STRUC{ + struct{ + UINT32 Rsv1:29; + UINT32 EXT_PA_EN:1; + UINT32 ADDAC_LDO_ADC9_EN:1; + UINT32 ADDAC_LDO_ADC6_EN:1; + }field; + UINT32 word; +}RF_MISC_STRUC, *PRF_MISC_STRUC; +#else +typedef union _RF_MISC_STRUC{ + struct{ + UINT32 ADDAC_LDO_ADC6_EN:1; + UINT32 ADDAC_LDO_ADC9_EN:1; + UINT32 EXT_PA_EN:1; + UINT32 Rsv1:29; + }field; + UINT32 word; +}RF_MISC_STRUC, *PRF_MISC_STRUC; +#endif + +#define RF_BSI_CKDIV 0x520 + +#define PAMODE_PWR_ADJ0 0x1228 +#define PAMODE_PWR_ADJ1 0x122c +#define DACCLK_EN_DLY_CFG 0x1264 + +#define RLT_PAIRWISE_KEY_TABLE_BASE 0x8000 /* 32-byte * 256-entry = -byte */ +#define RLT_HW_KEY_ENTRY_SIZE 0x20 + +#define RLT_PAIRWISE_IVEIV_TABLE_BASE 0xa000 /* 8-byte * 256-entry = -byte */ +#define RLT_MAC_IVEIV_TABLE_BASE 0xa000 /* 8-byte * 256-entry = -byte */ +#define RLT_HW_IVEIV_ENTRY_SIZE 8 + +#define RLT_MAC_WCID_ATTRIBUTE_BASE 0xa800 /* 4-byte * 256-entry = -byte */ +#define RLT_HW_WCID_ATTRI_SIZE 4 + +#define RLT_SHARED_KEY_TABLE_BASE 0xac00 /* 32-byte * 16-entry = 512-byte */ +#define RLT_SHARED_KEY_MODE_BASE 0xb000 /* 32-byte * 16-entry = 512-byte */ + +#define RLT_HW_SHARED_KEY_MODE_SIZE 4 + +#define RLT_SHARED_KEY_TABLE_BASE_EXT 0xb400 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ +#define RLT_SHARED_KEY_MODE_BASE_EXT 0xb3f0 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ + +/* This resgiser is ONLY be supported for RT3883 or later. + It conflicted with BCN#0 offset of previous chipset. */ +#define RLT_WAPI_PN_TABLE_BASE 0xb800 +#define RLT_WAPI_PN_ENTRY_SIZE 8 + +struct _RTMP_ADAPTER; +struct _RXINFO_STRUC; +union _TXINFO_STRUC; +union _TXWI_STRUC; +union _RXWI_STRUC; + +#ifdef DBG +VOID dump_rlt_rxinfo(struct _RTMP_ADAPTER *pAd, struct _RXINFO_STRUC *pRxInfo); +VOID dump_rlt_txinfo(struct _RTMP_ADAPTER *pAd, union _TXINFO_STRUC *pTxInfo); +VOID dump_rlt_txwi(struct _RTMP_ADAPTER *pAd, union _TXWI_STRUC *pTxWI); +VOID dump_rlt_rxwi(struct _RTMP_ADAPTER *pAd, union _RXWI_STRUC *pRxWI); +VOID dumpRxFCEInfo(struct _RTMP_ADAPTER *pAd, RXFCE_INFO *pRxFceInfo); +#endif + +INT rlt_get_rxwi_phymode(union _RXWI_STRUC *rxwi); +INT rlt_get_rxwi_rssi(union _RXWI_STRUC *rxwi, INT size, CHAR *rssi); +INT rlt_get_rxwi_snr(struct _RTMP_ADAPTER *pAd, union _RXWI_STRUC *rxwi, INT size, UCHAR *snr); +VOID rlt_asic_init_txrx_ring(struct _RTMP_ADAPTER *pAd); + +INT rlt_wlan_chip_onoff(struct _RTMP_ADAPTER *pAd, BOOLEAN bOn, BOOLEAN bResetWLAN); + + +#endif /* __RAL_NMAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_pbf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_pbf.h new file mode 100644 index 000000000..29f929715 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_pbf.h @@ -0,0 +1,99 @@ +/* + *************************************************************************** + * 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: + ral_nmac_pbf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_NMAC_PBF_H__ +#define __RAL_NMAC_PBF_H__ + + + +/* ================================================================================= */ +/* Register format for PBF */ +/* ================================================================================= */ + + +/* Most are for debug. Driver doesn't touch PBF register. */ +#ifdef RT_BIG_ENDIAN +typedef union _RLT_PBF_SYS_CTRL_STRUC { + struct { + UINT32 rsv5:7; /* Reserved */ + UINT32 CSR_TEST_EN:1; + UINT32 MAC_CLKSEL:2; /* MAC clock selection */ + UINT32 PWRSV_EN:2; + UINT32 SHRM_SEL:1; /* Shared memory access selection */ + UINT32 PBF_MSEL:2; /* Packet buffer memory access selection */ + UINT32 rsv4:5; + UINT32 PBF_CLK_EN:1; /* PBF clock enable */ + UINT32 MAC_CLK_EN:1; /* MAC clock enable */ + UINT32 rsv3:6; + UINT32 PBF_RESET:1; /* PBF hardware reset */ + UINT32 MAC_RESET:1; /* MAC hardware reset */ + UINT32 rsv:2; + } field; + UINT32 word; +} RLT_PBF_SYS_CTRL_STRUC; +#else +typedef union _RLT_PBF_SYS_CTRL_STRUC{ + struct { + UINT32 rsv5:7; /* Reserved */ + UINT32 CSR_TEST_EN:1; + UINT32 MAC_CLKSEL:2; /* MAC clock selection */ + UINT32 PWRSV_EN:2; + UINT32 SHRM_SEL:1; /* Shared memory access selection */ + UINT32 PBF_MSEL:2; /* Packet buffer memory access selection */ + UINT32 rsv4:5; + UINT32 PBF_CLK_EN:1; /* PBF clock enable */ + UINT32 MAC_CLK_EN:1; /* MAC clock enable */ + UINT32 rsv3:6; + UINT32 PBF_RESET:1; /* PBF hardware reset */ + UINT32 MAC_RESET:1; /* MAC hardware reset */ + UINT32 rsv:2; + }field; + UINT32 word; +} RLT_PBF_SYS_CTRL_STRUC; +#endif + + +#define RLT_PBF_CFG 0x0404 +#define RX_DROP_MODE (1 << 8) +#define TX_MAX_PCNT 0x0408 +#define RX_MAX_PCNT 0x040c +#define RXQ_STA 0x0430 +#define TXQ_STA 0x0434 + +#define RLT_BCN_OFFSET0 0x041c +#define RLT_BCN_OFFSET1 0x0420 +#define RLT_BCN_OFFSET2 0x0424 +#define RLT_BCN_OFFSET3 0x0428 + + +#define FCE_CTRL 0x0800 +#define FCE_PARAM 0x0804 +#define CHECKSUM_OFFLOAD 0x0808 + +#endif /* __RAL_NMAC_PBF_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_pci.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_pci.h new file mode 100644 index 000000000..5e248cbf4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_pci.h @@ -0,0 +1,335 @@ +/**************************************************************************** + * 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: + ral_nmac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_NMAC_PCI_H__ +#define __RAL_NMAC_PCI_H__ + + +#define INT_R0_DONE (1<<0) +#define INT_R1_DONE (1<<1) +#define INT_T0_DONE (1<<4) +#define INT_T1_DONE (1<<5) +#define INT_T2_DONE (1<<6) +#define INT_T3_DONE (1<<7) +#define INT_T4_DONE (1<<8) +#define INT_T5_DONE (1<<9) +#define INT_T6_DONE (1<<10) +#define INT_T7_DONE (1<<11) +#define INT_T8_DONE (1<<12) +#define INT_T9_DONE (1<<13) +#define INT_RESVD ((1<<14) | (1<<15)) +#define INT_RX_COHE (1<<16) +#define INT_TX_COHE (1<<17) +#define INT_ANY_COH (1<<18) +#define INT_MCU_CMD (1<<19) +#define INT_TBTT_ISR (1<<20) +#define INT_PRE_TBTT (1<<21) +#define INT_TX_STAT (1<<22) +#define INT_AUTO_WAKE (1<<23) +#define INT_GP_TIMER (1<<24) +#define INT_RESVD_2 (1<<25) +#define INT_RX_DLY (1<<26) +#define INT_TX_DLY (1<<27) + +// TODO: shiang-6590, for 6590, what's the interrupt bit for TONE_RADAR?? now just give a reseved bit +#define RLT_INT_TONE_RADAR (1<<29) + + +//#define RLT_RxINT (INT_R0_DONE | INT_R1_DONE /* | INT_RX_DLY */) /* Delayed Rx or indivi rx */ +#define RLT_RxINT (INT_R1_DONE | INT_RX_DLY ) /* Delayed Rx or indivi rx */ +#define RLT_TxDataInt (INT_T0_DONE | \ + INT_T1_DONE | \ + INT_T2_DONE | \ + INT_T3_DONE /*| INT_TX_DLY*/) /* Delayed Tx or indivi tx */ + +#define RLT_76x2TxDataInt (INT_T1_DONE | \ + INT_T2_DONE | \ + INT_T3_DONE | \ + INT_TX_DLY) + +#ifdef RT8592 +#define RLT_TxMgmtInt (INT_T5_DONE /*| INT_TX_DLY*/) +#else +#define RLT_TxMgmtInt (INT_T9_DONE /*| INT_TX_DLY*/) +#endif /* RT8592 */ + +#define RLT_TxCoherent INT_TX_COHE +#define RLT_RxCoherent INT_RX_COHE +#define RLT_TxRxCoherent INT_ANY_COH +#define RLT_McuCommand INT_MCU_CMD /* mcu */ +#define RLT_PreTBTTInt INT_PRE_TBTT +#define RLT_TBTTInt INT_TBTT_ISR +#define RLT_GPTimeOutInt INT_GP_TIMER /* GPtimeout interrupt */ +#define RLT_AutoWakeupInt INT_AUTO_WAKE /* AutoWakeupInt interrupt */ +#define RLT_FifoStaFullInt INT_TX_STAT /* fifo statistics full interrupt */ +#define RLT_RadarInt (RLT_INT_TONE_RADAR) + +#define RLT_INT_RX (INT_R0_DONE | INT_R1_DONE) +#define RLT_INT_RX_DATA (INT_R0_DONE) +#define RLT_INT_RX_CMD (INT_R1_DONE) +#define RLT_INT_AC0_DLY (INT_T0_DONE) +#define RLT_INT_AC1_DLY (INT_T1_DONE) +#define RLT_INT_AC2_DLY (INT_T2_DONE) +#define RLT_INT_AC3_DLY (INT_T3_DONE) +#ifdef RT8592 +#define RLT_INT_HCCA_DLY (INT_T4_DONE) +#define RLT_INT_MGMT_DLY (INT_T5_DONE) +#else +#define RLT_INT_HCCA_DLY (INT_T8_DONE) +#define RLT_INT_MGMT_DLY (INT_T9_DONE) +#endif /* RT8592 */ + +#ifdef CARRIER_DETECTION_SUPPORT +#define RLT_DELAYINTMASK (0x0DFF3FF3 | (RLT_RadarInt)) +#define RLT_INTMASK (0x0DFF3FF3 | (RLT_RadarInt)) +#else +#define RLT_DELAYINTMASK 0x0DFF3FF3 +#define RLT_INTMASK 0x0DFF3FF3 +#endif /* CARRIER_DETECTION_SUPPORT */ + + +#ifdef RT_BIG_ENDIAN +typedef union _RLT_INT_SOURCE_CSR_STRUC { + struct { + UINT32 rsv1:4; + UINT32 TxDelayINT:1; + UINT32 RxDelayINT:1; + UINT32 rsv2:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1; + UINT32 TXFifoStatusInt:1; + UINT32 PreTBTT:1; + UINT32 tbttInt:1; + UINT32 MCUCommandINT:1; + UINT32 trCoherent:1; + UINT32 txCoherent:1; + UINT32 rxCoherent:1; + UINT32 rsv3:2; + UINT32 TxDone9:1; + UINT32 TxDone8:1; + UINT32 TxDone7:1; + UINT32 TxDone6:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 rsv4:2; + UINT32 RxDone1:1; + UINT32 RxDone:1; + }field; + UINT32 word; +}RLT_INT_SOURCE_CSR_STRUC; +#else +typedef union _RLT_INT_SOURCE_CSR_STRUC { + struct { + UINT32 RxDone:1; + UINT32 RxDone1:1; + UINT32 rsv4:2; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 TxDone6:1; + UINT32 TxDone7:1; + UINT32 TxDone8:1; + UINT32 TxDone9:1; + UINT32 rsv3:2; + UINT32 rxCoherent:1; + UINT32 txCoherent:1; + UINT32 trCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 tbttInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1; + UINT32 AutoWakeup:1; + UINT32 GPTimer:1; + UINT32 rsv2:1; + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 rsv1:4; + }field; + UINT32 word; +}RLT_INT_SOURCE_CSR_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +/* INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF */ +#define INT_MASK_CSR 0x204 +#ifdef RT_BIG_ENDIAN +typedef union _PDMA_INT_MASK{ + struct { + UINT32 rsv1:4; + UINT32 TxDelayINT:1; + UINT32 RxDelayINT:1; + UINT32 rsv2:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1; + UINT32 TXFifoStatusInt:1; + UINT32 PreTBTT:1; + UINT32 tbttInt:1; + UINT32 MCUCommandINT:1; + UINT32 trCoherent:1; + UINT32 txCoherent:1; + UINT32 rxCoherent:1; + UINT32 rsv3:2; + UINT32 TxDone9:1; + UINT32 TxDone8:1; + UINT32 TxDone7:1; + UINT32 TxDone6:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 rsv4:2; + UINT32 RxDone1:1; + UINT32 RxDone:1; + }field; + UINT32 word; +}PMDA_INT_MASK; +#else +typedef union _PDMA_INT_MASK{ + struct { + UINT32 RxDone:1; + UINT32 RxDone1:1; + UINT32 rsv4:2; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 TxDone6:1; + UINT32 TxDone7:1; + UINT32 TxDone8:1; + UINT32 TxDone9:1; + UINT32 rsv3:2; + UINT32 rxCoherent:1; + UINT32 txCoherent:1; + UINT32 trCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 tbttInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1; + UINT32 AutoWakeup:1; + UINT32 GPTimer:1; + UINT32 rsv2:1; + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 rsv1:4; + }field; + UINT32 word; +}PMDA_INT_MASK; +#endif /* RT_BIG_ENDIAN */ + + +/*@!Release + Tx Ring Layout and assignments + + Totally we have 10 Tx Rings and assigned as following usage: + 1. RT85592 + TxRing 0~3: for TxQ Channel 1 with AC_BK/BE/VI/VO + TxRing 4 : for TxQ CTRL + TxRing 5 : for TxQ MGMT + TxRing 6~9: for TxQ Channel 2 with AC_BK/BE/VI/VO + + 2. MT7650 + TxRing 0~3: for TxQ Channel 1 with AC_BK/BE/VI/VO + TxRing 4~7: for TxQ Channel 2 with AC_BK/BE/VI/VO + TxRing 8 : for TxQ CTRL + TxRing 9 : for TxQ MGMT + + For each TxRing, we have four register to control it + TX_RINGn_CTRL0 (0x0): base address of this ring(4-DWORD aligned address) + TX_RINGn_CTRL1 (0x4): maximum number of TxD count in this ring + TX_RINGn_CTRL2 (0x8): Point to the next TxD CPU wants to use + TX_RINGn_CTRL3 (0xc): Point to the next TxD DMA wants to use +*/ +#define RLT_RINGREG_DIFF 0x10 +#define TX_RING_BASE 0x0300 +#define TX_RING_NUM 10 +#define TX_RING_PTR 0x0300 +#define TX_RING_CNT 0x0304 +#define TX_RING_CIDX 0x0308 +#define TX_RING_DIDX 0x030c + +#define TX_CHAN_BASE_1 (TX_RING_BASE + RLT_RINGREG_DIFF * 0) +#define TX_CHAN_BASE_2 (TX_RING_BASE + RLT_RINGREG_DIFF * 6) + +/* following address is base on TX_CHAN_BASE_X */ +#define TX_RING_BK_BASE 0x0 +#define TX_RING_BK_CNT (TX_RING_BK_BASE + 0x04) +#define TX_RING_BK_CIDX (TX_RING_BK_BASE + 0x08) +#define TX_RING_BK_DIDX (TX_RING_BK_BASE + 0x0c) + +#define TX_RING_BE_BASE (TX_RING_BK_BASE + RLT_RINGREG_DIFF) +#define TX_RING_BE_CNT (TX_RING_BE_BASE + 0x04) +#define TX_RING_BE_CIDX (TX_RING_BE_BASE + 0x08) +#define TX_RING_BE_DIDX (TX_RING_BE_BASE + 0x0c) + +#define TX_RING_VI_BASE (TX_RING_BE_BASE + RLT_RINGREG_DIFF) +#define TX_RING_VI_CNT (TX_RING_VI_BASE + 0x04) +#define TX_RING_VI_CIDX (TX_RING_VI_BASE + 0x08) +#define TX_RING_VI_DIDX (TX_RING_VI_BASE + 0x0c) + +#define TX_RING_VO_BASE (TX_RING_VI_BASE + RLT_RINGREG_DIFF) +#define TX_RING_VO_CNT (TX_RING_VO_BASE + 0x04) +#define TX_RING_VO_CIDX (TX_RING_VO_BASE + 0x08) +#define TX_RING_VO_DIDX (TX_RING_VO_BASE + 0x0c) + + +/* + Rx Ring Layput and assignments + + Totally we have 2 Rx Rings and assigned as following usage: + RxRing 0: for all received data packets + RxRing 1: for internal ctrl/info packets generated by on-chip CPU. + + For each TxRing, we have four register to control it + RX_RING_CTRL0 (0x0): base address of this ring(4-DWORD aligned address) + RX_RING_CTRL1 (0x4): maximum number of RxD count in this ring + RX_RING_CTRL2 (0x8): Point to the next RxD CPU wants to use + RX_RING_CTRL3 (0xc): Point to the next RxD DMA wants to use +*/ +#define RX_RING_BASE 0x03c0 +#define RX_RING1_BASE 0x03d0 +#define RX_RING_NUM 2 +#define RX_RING_PTR RX_RING_BASE +#define RX_RING_CNT (RX_RING_BASE + 0x04) +#define RX_RING_CIDX (RX_RING_BASE + 0x08) +#define RX_RING_DIDX (RX_RING_BASE + 0x0c) + +#define RX_RING1_PTR (RX_RING_BASE + RLT_RINGREG_DIFF * 1) +#define RX_RING1_CNT (RX_RING_BASE + RLT_RINGREG_DIFF * 1 + 0x04) +#define RX_RING1_CIDX (RX_RING_BASE + RLT_RINGREG_DIFF * 1 + 0x08) +#define RX_RING1_DIDX (RX_RING_BASE + RLT_RINGREG_DIFF * 1 + 0x0c) + +#endif /*__RAL_NMAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_rf_ctrl.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_rf_ctrl.h new file mode 100644 index 000000000..b69a614db --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_rf_ctrl.h @@ -0,0 +1,43 @@ +/* + *************************************************************************** + * 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: + ral_nmac_rf_ctrl.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_NMAC_RF_CTRL_H__ +#define __RAL_NMAC_RF_CTRL_H__ + + + +/* ================================================================================= */ +/* Register format for RFCTRL */ +/* ================================================================================= */ + +#define RLT_RF_BYPASS_0 0x0504 +#define RLT_RF_SETTING_0 0x050C + + +#endif /* __RAL_OMAC_RF_CTRL_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_usb.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_usb.h new file mode 100644 index 000000000..93047800c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/nmac/ral_nmac_usb.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * 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: + ral_nmac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_NMAC_USB_H__ +#define __RAL_NMAC_USB_H__ + +#define RLT_USB_DMA_CFG 0x0238 +#define U3DMA_WLCFG 0x9018 + +#endif /*__RAL_NMAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac.h new file mode 100644 index 000000000..11a5b412e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac.h @@ -0,0 +1,390 @@ +/* + *************************************************************************** + * 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: + ral_omac.h + + Abstract: + Ralink Wireless Chip RAL MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_OMAC_H__ +#define __RAL_OMAC_H__ + + + +/* + TXINFO +*/ + +/* + TXINFO fields defintion: + + USBDMATxPktLen[b0~b14]: + Total bytes of all sub-frame. ONLY for USB bulk Aggregation + IPOffset[b15~b18]: + Start byte of IP packet. The base address is from TXINFO. + 0: header will be parsed by hardware. + This field is like backdoor. + For AMSDU, this field is useless + + TCPOffset[b19~b23]: + Start byte of TCP packet from IP packet The base address is IP header. + 0: header will be parsed by hardware. + This field is like backdoor. + For AMSDU, this field is useless + + WIV[b24]: + Wireless Info Valid. + 1: if Driver already fill WI + 0: if DMA needs to copy WI to correctposition + + QSEL[b25~b26]: + Select on-chip FIFO ID for 2nd-stage output scheduler. + 0:MGMT, 1:HCCA 2:EDCA + + SwUseLastRound[b27]: + Software used for USB-based chipset, reserved for other interfaces. + + uso[b28]: + UDP checksum enable. + 1: indicate this packet needs to do UDP checksum + + cso[b29]: + Checksum offload. + 1: indicate this packet needs to do checksum + + USBDMANextVLD[b30]: + Used for USB-based chipset, reserved for other interfaces. + Used ONLY in USB bulk Aggregation, host driver info DMA current + frame is not he last frame in current Tx queue + + USBDMATxburst[b31]: + force DMA transmit frame from current selected endpoint +*/ +#ifdef RT_BIG_ENDIAN +typedef struct _TXINFO_OMAC { + UINT32 USBDMATxburst:1; + UINT32 USBDMANextVLD:1; + UINT32 cso:1; + UINT32 uso:1; +#ifdef USB_BULK_BUF_ALIGMENT + UINT32 bFragLasAlignmentsectiontRound:1; +#else + UINT32 SwUseLastRound:1; +#endif /* USB_BULK_BUF_ALIGMENT */ + UINT32 QSEL:2; + UINT32 WIV:1; + UINT32 TCPOffset:5; + UINT32 IPOffset:4; + UINT32 USBDMATxPktLen:15; +}TXINFO_OMAC; +#else +typedef struct _TXINFO_OMAC { + UINT32 USBDMATxPktLen:15; + UINT32 IPOffset:4; + UINT32 TCPOffset:5; + UINT32 WIV:1; + UINT32 QSEL:2; +#ifdef USB_BULK_BUF_ALIGMENT + UINT32 bFragLasAlignmentsectiontRound:1; +#else + UINT32 SwUseLastRound:1; +#endif /* USB_BULK_BUF_ALIGMENT */ + UINT32 uso:1; + UINT32 cso:1; + UINT32 USBDMANextVLD:1; + UINT32 USBDMATxburst:1; +}TXINFO_OMAC; +#endif /* RT_BIG_ENDIAN */ + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_OMAC { + /* Word 0 */ + UINT32 PHYMODE:2; + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 STBC:2; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 MCS:7; + + UINT32 TXLUT:1; + UINT32 TXRPT:1; + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 txop:2; + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + /* Word 1 */ + UINT32 PacketId:4; + UINT32 MPDUtotalByteCnt:12; + UINT32 wcid:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + /* Word 2 */ + UINT32 IV; + /* Word 3 */ + UINT32 EIV; + +#if defined(RT5592) || defined(RT6352) + /* Word 4 */ + /* For Expert Antenna */ + UINT32 Reserved:11; + UINT32 CCP:1; + UINT32 TxPwrAdj:4; + UINT32 TxStreamMode:8; + UINT32 EncodedAntID:8; +#endif /* defined(RT5592) || defined(RT6352) */ +} TXWI_OMAC; +#else +typedef struct GNU_PACKED _TXWI_OMAC { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 CFACK:1; + UINT32 TS:1; + + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + UINT32 txop:2; /*FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 TXRPT:1; + UINT32 TXLUT:1; + + UINT32 MCS:7; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:2; /* 1: STBC support MCS =0-7, 2,3 : RESERVE */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 PHYMODE:2; + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCnt = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 wcid:8; + UINT32 MPDUtotalByteCnt:12; + UINT32 PacketId:4; + /*Word2 */ + UINT32 IV; + /*Word3 */ + UINT32 EIV; + +#if defined(RT5592) || defined(RT6352) + /* Word 4 */ + /* For Expert Antenna */ + UINT32 EncodedAntID:8; + UINT32 TxStreamMode:8; + UINT32 TxPwrAdj:4; + UINT32 CCP:1; + UINT32 Reserved:11; +#endif /* defined(RT5592) || defined(RT6352) */ +} TXWI_OMAC; +#endif + + +#ifdef RTMP_RBUS_SUPPORT +#endif /* RTMP_RBUS_SUPPORT */ + +/* + RXWI wireless information format, in PBF. invisible in driver. +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXWI_OMAC{ + /* Word 0 */ + UINT32 tid:4; + UINT32 MPDUtotalByteCnt:12; + UINT32 UDF:3; + UINT32 bss_idx:3; + UINT32 key_idx:2; + UINT32 wcid:8; + + /* Word 1 */ + UINT32 phy_mode:2; /* 1: this RX frame is unicast to me */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 stbc:2; + UINT32 sgi:1; + UINT32 bw:1; + UINT32 mcs:7; + UINT32 SEQUENCE:12; + UINT32 FRAG:4; + + /* Word 2 */ + UINT32 rsv1:8; + UINT32 RSSI2:8; + UINT32 RSSI1:8; + UINT32 RSSI0:8; + + /* Word 3 */ + UINT32 FOFFSET:8; + UINT32 SNR2:8; + UINT32 SNR1:8; + UINT32 SNR0:8; + +#if defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT5592) || defined(RT6352) + UINT32 rsv3; +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT5592) || defined(RT6352) */ + +#if defined(RT5592) || defined(RT6352) + /* Word 5 */ + /* For Exper Antenna */ + UINT32 rsv4:24; + UINT32 EANT_ID:8; +#endif /* defined(RT5592) || defined(RT6352) */ +} RXWI_OMAC; +#else +typedef struct GNU_PACKED _RXWI_OMAC{ + /* Word 0 */ + UINT32 wcid:8; + UINT32 key_idx:2; + UINT32 bss_idx:3; + UINT32 UDF:3; + UINT32 MPDUtotalByteCnt:12; + UINT32 tid:4; + + /* Word 1 */ + UINT32 FRAG:4; + UINT32 SEQUENCE:12; + UINT32 mcs:7; + UINT32 bw:1; + UINT32 sgi:1; + UINT32 stbc:2; + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 phy_mode:2; /* 1: this RX frame is unicast to me */ + + /*Word2 */ + UINT32 RSSI0:8; + UINT32 RSSI1:8; + UINT32 RSSI2:8; + UINT32 rsv1:8; + + /*Word3 */ + UINT32 SNR0:8; + UINT32 SNR1:8; + UINT32 SNR2:8; + UINT32 FOFFSET:8; + +#if defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT5592) || defined(RT6352) + UINT32 rsv3; +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT5592) || defined(RT6352) */ + +#if defined(RT5592) || defined(RT6352) + /* Word 5 */ + /* For Exper Antenna */ + UINT32 EANT_ID:8; + UINT32 rsv4:24; +#endif /* defined(RT5592) || defined(RT6352) */ +} RXWI_OMAC; +#endif + + +typedef struct GNU_PACKED _OMAC_HW_RATE_CTRL_STRUCT{ +#ifdef RT_BIG_ENDIAN + UINT16 PHYMODE:2; + UINT16 iTxBF:1; + UINT16 Sounding:1; /* Sounding enable */ + UINT16 eTxBF:1; + UINT16 STBC:2; + UINT16 ShortGI:1; + UINT16 BW:1; /* channel bandwidth 20/40 */ + UINT16 MCS:7; +#else + UINT16 MCS:7; + UINT16 BW:1; + UINT16 ShortGI:1; + UINT16 STBC:2; + UINT16 eTxBF:1; + UINT16 Sounding:1; + UINT16 iTxBF:1; + UINT16 PHYMODE:2; +#endif /* RT_BIG_ENDIAN */ +}OMAC_HW_RATE_CTRL_STRUCT; + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ + +#define GPIO_CTRL_CFG 0x0228 +#define RLT_MCU_CMD_CFG 0x022c + + +#define PAIRWISE_KEY_TABLE_BASE 0x4000 /* 32-byte * 256-entry = -byte */ +#define HW_KEY_ENTRY_SIZE 0x20 + +#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 /* 8-byte * 256-entry = -byte */ +#define MAC_IVEIV_TABLE_BASE 0x6000 /* 8-byte * 256-entry = -byte */ +#define HW_IVEIV_ENTRY_SIZE 8 + +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 /* 4-byte * 256-entry = -byte */ +#define HW_WCID_ATTRI_SIZE 4 + +#define SHARED_KEY_TABLE_BASE 0x6c00 /* 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE 0x7000 /* 32-byte * 16-entry = 512-byte */ + +#define HW_SHARED_KEY_MODE_SIZE 4 + +#define SHARED_KEY_TABLE_BASE_EXT 0x7400 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE_EXT 0x73F0 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ + +/* This resgiser is ONLY be supported for RT3883 or later. + It conflicted with BCN#0 offset of previous chipset. */ +#define WAPI_PN_TABLE_BASE 0x7800 +#define WAPI_PN_ENTRY_SIZE 8 + + +struct _RTMP_ADAPTER; +struct _RXINFO_STRUC; +union _RXWI_STRUC; +union _TXWI_STRUC; + +#ifdef DBG +VOID dump_rtmp_rxwi(struct _RTMP_ADAPTER *pAd, union _RXWI_STRUC *pRxWI); +VOID dump_rtmp_txwi(struct _RTMP_ADAPTER *pAd, union _TXWI_STRUC *pTxWI); +VOID dump_rtmp_rxinfo(struct _RTMP_ADAPTER *pAd, struct _RXINFO_STRUC *pRxInfo); +#endif + +INT rtmp_get_rxwi_phymode(union _RXWI_STRUC *rxwi); +INT rtmp_get_rxwi_rssi(union _RXWI_STRUC *rxwi, INT size, CHAR *rssi); +INT rtmp_get_rxwi_snr(union _RXWI_STRUC *rxwi, INT size, UCHAR *snr); +VOID rtmp_asic_init_txrx_ring(struct _RTMP_ADAPTER *pAd); + +#endif /* __RAL_OMAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_pbf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_pbf.h new file mode 100644 index 000000000..c727a7070 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_pbf.h @@ -0,0 +1,106 @@ +/* + *************************************************************************** + * 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: + ral_omac_pbf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_OMAC_PBF_H__ +#define __RAL_OMAC_PBF_H__ + + +#include "rtmp_type.h" + +/* ================================================================================= */ +/* Register format for PBF */ +/* ================================================================================= */ + + +#ifdef RT_BIG_ENDIAN +typedef union _RTMP_PBF_SYS_CTRL_STRUC { + struct { + UINT32 Reserved5:12; /* Reserved */ + UINT32 SHR_MSEL:1; /* Shared memory access selection */ + UINT32 PBF_MSEL:2; /* Packet buffer memory access selection */ + UINT32 HST_PM_SEL:1; /* The write selection of the host program RAM */ + UINT32 Reserved4:1; /* Reserved */ + UINT32 CAP_MODE:1; /* Packet buffer capture mode */ + UINT32 Reserved3:1; /* Reserved */ + UINT32 CLK_SEL:1; /* MAC/PBF clock source selection */ + UINT32 PBF_CLK_EN:1; /* PBF clock enable */ + UINT32 MAC_CLK_EN:1; /* MAC clock enable */ + UINT32 DMA_CLK_EN:1; /* DMA clock enable */ + UINT32 Reserved2:1; /* Reserved */ + UINT32 MCU_READY:1; /* MCU ready */ + UINT32 Reserved1:2; /* Reserved */ + UINT32 ASY_RESET:1; /* ASYNC interface reset */ + UINT32 PBF_RESET:1; /* PBF hardware reset */ + UINT32 MAC_RESET:1; /* MAC hardware reset */ + UINT32 DMA_RESET:1; /* DMA hardware reset */ + UINT32 MCU_RESET:1; /* MCU hardware reset */ + } field; + UINT32 word; +} RTMP_PBF_SYS_CTRL_STRUC; +#else +typedef union _RTMP_PBF_SYS_CTRL_STRUC { + struct { + UINT32 MCU_RESET:1; + UINT32 DMA_RESET:1; + UINT32 MAC_RESET:1; + UINT32 PBF_RESET:1; + UINT32 ASY_RESET:1; + UINT32 Reserved1:2; + UINT32 MCU_READY:1; + UINT32 Reserved2:1; + UINT32 DMA_CLK_EN:1; + UINT32 MAC_CLK_EN:1; + UINT32 PBF_CLK_EN:1; + UINT32 CLK_SEL:1; + UINT32 Reserved3:1; + UINT32 CAP_MODE:1; + UINT32 Reserved4:1; + UINT32 HST_PM_SEL:1; + UINT32 PBF_MSEL:2; + UINT32 SHR_MSEL:1; + UINT32 Reserved5:12; + }field; + UINT32 word; +} RTMP_PBF_SYS_CTRL_STRUC; +#endif + + +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040C +#define PBF_CAP_CTRL 0x0440 + +#define BCN_OFFSET0 0x042C +#define BCN_OFFSET1 0x0430 +#define TXRXQ_STA 0x0434 +#ifdef SPECIFIC_BCN_BUF_SUPPORT +#define BCN_OFFSET2 0x0444 +#define BCN_OFFSET3 0x0448 +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + +#endif /* __RAL_OMAC_PBF_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_pci.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_pci.h new file mode 100644 index 000000000..a7ebc382d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_pci.h @@ -0,0 +1,255 @@ +/**************************************************************************** + * 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: + ral_omac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_OMAC_PCI_H__ +#define __RAL_OMAC_PCI_H__ + + +#define RTMP_INT_RX_DLY (1<<0) /* bit 0 */ +#define RTMP_INT_TX_DLY (1<<1) /* bit 1 */ +#define RTMP_INT_RX_DONE (1<<2) /* bit 2 */ +#define RTMP_INT_AC0_DMA_DONE (1<<3) /* bit 3 */ +#define RTMP_INT_AC1_DMA_DONE (1<<4) /* bit 4 */ +#define RTMP_INT_AC2_DMA_DONE (1<<5) /* bit 5 */ +#define RTMP_INT_AC3_DMA_DONE (1<<6) /* bit 6 */ +#define RTMP_INT_HCCA_DMA_DONE (1<<7) /* bit 7 */ +#define RTMP_INT_MGMT_DONE (1<<8) /* bit 8 */ +#define RTMP_INT_MCU_CMD (1<<9) +#define RTMP_INT_ANY_COHERENT (1<<10) +#define RTMP_INT_TBTT (1<<11) +#define RTMP_INT_PRE_TBTT (1<<12) +#define RTMP_INT_FIFO_STAT (1<<13) +#define RTMP_INT_AUTO_WAKEUP (1<<14) +#define RTMP_INT_GPIO_TIMER (1<<15) +#define RTMP_INT_RX_COHERENT (1<<16) +#define RTMP_INT_TX_COHERENT (1<<17) +#define RTMP_INT_TONE_RADAR (1<<20) /* bit 20 */ + +#define RTMP_RxINT (RTMP_INT_RX_DLY | RTMP_INT_RX_DONE) /* 0x00000005 */ /* Delayed Rx or indivi rx */ +#define RTMP_TxDataInt (RTMP_INT_TX_DLY |\ + RTMP_INT_AC0_DMA_DONE | \ + RTMP_INT_AC1_DMA_DONE | \ + RTMP_INT_AC2_DMA_DONE | \ + RTMP_INT_AC3_DMA_DONE | \ + RTMP_INT_HCCA_DMA_DONE) /* 0x000000fa */ /* Delayed Tx or indivi tx */ +#define RTMP_TxMgmtInt (RTMP_INT_TX_DLY | RTMP_INT_MGMT_DONE) /* 0x00000102 */ /* Delayed Tx or indivi tx */ +#define RTMP_TxCoherent (RTMP_INT_TX_COHERENT) /* 0x00020000 */ /* tx coherent */ +#define RTMP_RxCoherent (RTMP_INT_RX_COHERENT) /* 0x00010000 */ /* rx coherent */ +#define RTMP_TxRxCoherent (RTMP_INT_ANY_COHERENT) /* 0x00000400 */ /* tx rx coherent */ +#define RTMP_McuCommand (RTMP_INT_MCU_CMD) /* 0x00000200 */ /* mcu */ +#define RTMP_PreTBTTInt (RTMP_INT_PRE_TBTT) /* 0x00001000 */ /* Pre-TBTT interrupt */ +#define RTMP_TBTTInt (RTMP_INT_TBTT) /* 0x00000800 */ /* TBTT interrupt */ +#define RTMP_GPTimeOutInt (RTMP_INT_GPIO_TIMER) /* 0x00008000 */ /* GPtimeout interrupt */ +#define RTMP_AutoWakeupInt (RTMP_INT_AUTO_WAKEUP) /* 0x00004000 */ /* AutoWakeupInt interrupt */ +#define RTMP_FifoStaFullInt (RTMP_INT_FIFO_STAT) /* 0x00002000 */ /* fifo statistics full interrupt */ +#define RTMP_RadarInt (RTMP_INT_TONE_RADAR) /* 0x00100000 */ + +#define RTMP_INT_RX RTMP_INT_RX_DONE + +#define RTMP_INT_AC0_DLY (RTMP_INT_AC0_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_AC1_DLY (RTMP_INT_AC1_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_AC2_DLY (RTMP_INT_AC2_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_AC3_DLY (RTMP_INT_AC3_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_HCCA_DLY (RTMP_INT_HCCA_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_MGMT_DLY (RTMP_INT_MGMT_DONE) + + +#ifdef CARRIER_DETECTION_SUPPORT +#define RTMP_DELAYINTMASK (0x0003FFFB | (RTMP_RadarInt)) +#define RTMP_INTMASK (0x0003FFFB | (RTMP_RadarInt)) +#else +#define RTMP_DELAYINTMASK 0x0003FFFB +#define RTMP_INTMASK 0x0003FFFB +#endif /* CARRIER_DETECTION_SUPPORT */ + + +#ifdef RT_BIG_ENDIAN +typedef union _RTMP_INT_SOURCE_CSR_STRUC { + struct { + UINT32 rsv21:11; + UINT32 RadarINT:1; + UINT32 rsv18:2; + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1;/*bit14 */ + UINT32 TXFifoStatusInt:1;/*FIFO Statistics is full, sw should read 0x171c */ + UINT32 PreTBTT:1; + UINT32 TBTTInt:1; + UINT32 RxTxCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelayINT:1; /*delayed interrupt, not interrupt until several int or time limit hit */ + UINT32 RxDelayINT:1; /*dealyed interrupt */ + } field; + UINT32 word; +} RTMP_INT_SOURCE_CSR_STRUC; +#else +typedef union _RTMP_INT_SOURCE_CSR_STRUC { + struct { + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1;/*4 */ + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; /* bit7 */ + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1;/*bit 9 */ + UINT32 RxTxCoherent:1; + UINT32 TBTTInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1;/*FIFO Statistics is full, sw should read 0x171c */ + UINT32 AutoWakeup:1;/*bit14 */ + UINT32 GPTimer:1; + UINT32 RxCoherent:1;/*bit16 */ + UINT32 TxCoherent:1; + UINT32 rsv18:2; + UINT32 RadarINT:1; + UINT32 rsv21:11; + } field; + UINT32 word; +} RTMP_INT_SOURCE_CSR_STRUC; +#endif + + +/* INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF */ +#define INT_MASK_CSR 0x204 +#ifdef RT_BIG_ENDIAN +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 :9; + UINT32 RadarINT:1; + UINT32 rsv:10; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelay:1; + UINT32 RXDelay_INT_MSK:1; + } field; + UINT32 word; +}INT_MASK_CSR_STRUC; +#else +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 RXDelay_INT_MSK:1; + UINT32 TxDelay:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1; + UINT32 rsv:10; + UINT32 RadarINT:1; + UINT32 :9; + UINT32 RxCoherent:1; + UINT32 TxCoherent:1; + } field; + UINT32 word; +} INT_MASK_CSR_STRUC; +#endif + + +#define RINGREG_DIFF 0x10 +#define TX_BASE_PTR0 0x0230 /*AC_BK base address */ +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c +#define TX_BASE_PTR1 0x0240 /*AC_BE base address */ +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c +#define TX_BASE_PTR2 0x0250 /*AC_VI base address */ +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c +#define TX_BASE_PTR3 0x0260 /*AC_VO base address */ +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c +#define TX_BASE_PTR4 0x0270 /*HCCA base address */ +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c +#define TX_BASE_PTR5 0x0280 /*MGMT base address */ +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c +#define TX_MGMTMAX_CNT TX_MAX_CNT5 +#define TX_MGMTCTX_IDX TX_CTX_IDX5 +#define TX_MGMTDTX_IDX TX_DTX_IDX5 +#define RX_BASE_PTR 0x0290 /*RX base address */ +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + + +#define US_CYC_CNT 0x02a4 +#ifdef RT_BIG_ENDIAN +typedef union _US_CYC_CNT_STRUC { + struct { + UINT32 rsv2:7; + UINT32 TestEn:1; + UINT32 TestSel:8; + UINT32 rsv1:7; + UINT32 MiscModeEn:1; + UINT32 UsCycCnt:8; + } field; + UINT32 word; +} US_CYC_CNT_STRUC; +#else +typedef union _US_CYC_CNT_STRUC { + struct { + UINT32 UsCycCnt:8; + UINT32 MiscModeEn:1; + UINT32 rsv1:7; + UINT32 TestSel:8; + UINT32 TestEn:1; + UINT32 rsv2:7; + } field; + UINT32 word; +} US_CYC_CNT_STRUC; +#endif + + +#endif /*__RAL_OMAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_rf_ctrl.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_rf_ctrl.h new file mode 100644 index 000000000..6d609db1f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_rf_ctrl.h @@ -0,0 +1,103 @@ +/* + *************************************************************************** + * 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: + ral_omac_rf_ctrl.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_OMAC_RF_CTRL_H__ +#define __RAL_OMAC_RF_CTRL_H__ + + + +/* ================================================================================= */ +/* Register format for RFCTRL */ +/* ================================================================================= */ + +#define OSC_CTRL 0x5a4 +#define PCIE_PHY_TX_ATTENUATION_CTRL 0x05C8 +#define INTERNAL_1 0x05C8 + +#ifdef RT_BIG_ENDIAN +typedef union _INTERNAL_1_STRUCT +{ + struct + { + UINT32 Reserve1:10; + UINT32 CSO_RX_IPV6_CHKSUM_EN:1; + UINT32 CSO_TX_IPV6_CHKSUM_EN:1; + UINT32 CSO_HW_PARSE_TCP:1; + UINT32 CSO_HW_PARSE_IP:1; + UINT32 CSO_RX_CHKSUM_EN:1; + UINT32 CSO_TX_CHKSUM_EN:1; + UINT32 CSO_TIMEOUT_VALUE:4; + UINT32 PCIE_PHY_TX_ATTEN_EN:1; + UINT32 PCIE_PHY_TX_ATTEN_VALUE:3; + UINT32 Reserve2:7; + UINT32 RF_ISOLATION_ENABLE:1; + } field; + + UINT32 word; +} INTERNAL_1_STRUCT; +#else +typedef union _INTERNAL_1_STRUCT { + struct + { + UINT32 RF_ISOLATION_ENABLE:1; + UINT32 Reserve2:7; + UINT32 PCIE_PHY_TX_ATTEN_VALUE:3; + UINT32 PCIE_PHY_TX_ATTEN_EN:1; + UINT32 CSO_TIMEOUT_VALUE:4; + UINT32 CSO_TX_CHKSUM_EN:1; + UINT32 CSO_RX_CHKSUM_EN:1; + UINT32 CSO_HW_PARSE_IP:1; + UINT32 CSO_HW_PARSE_TCP:1; + UINT32 CSO_TX_IPV6_CHKSUM_EN:1; + UINT32 CSO_RX_IPV6_CHKSUM_EN:1; + UINT32 Reserve1:10; + } field; + + UINT32 word; +} INTERNAL_1_STRUCT; +#endif + +#define RF_DBG1 0x050C +#define RF_CONTROL0 0x0518 +#define RTMP_RF_BYPASS0 0x051C +#define RF_CONTROL1 0x0520 +#define RF_BYPASS1 0x0524 +#define RF_CONTROL2 0x0528 +#define RF_BYPASS2 0x052C +#define RF_CONTROL3 0x0530 +#define RF_BYPASS3 0x0534 + +#define LDO_CFG0 0x05d4 +#define GPIO_SWITCH 0x05dc + +#define DEBUG_INDEX 0x05e8 + + + +#endif /* __RAL_OMAC_RF_CTRL_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_usb.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_usb.h new file mode 100644 index 000000000..bc664a84f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/omac/ral_omac_usb.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * 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: + ral_omac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_OMAC_USB_H__ +#define __RAL_OMAC_USB_H__ + +#endif /*__RAL_OMAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/pbf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/pbf.h new file mode 100644 index 000000000..bd0f8e52b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/pbf.h @@ -0,0 +1,105 @@ +/* + *************************************************************************** + * 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: + pbf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __PBF_H__ +#define __PBF_H__ + + +#ifdef RLT_MAC +#include "mac_ral/nmac/ral_nmac_pbf.h" +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC +#include "mac_ral/omac/ral_omac_pbf.h" +#endif /* RTMP_MAC */ + + +/* ================================================================================= */ +/* Register format for PBF */ +/* ================================================================================= */ + + +#define WPDMA_GLO_CFG 0x208 +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 rx_2b_offset:1; + UINT32 clk_gate_dis:1; + UINT32 rsv:14; +#ifdef DESC_32B_SUPPORT + UINT32 RXHdrScater:7; + UINT32 Desc32BEn:1; +#else + UINT32 HDR_SEG_LEN:8; +#endif /* DESC_32B_SUPPORT */ + UINT32 BigEndian:1; + UINT32 EnTXWriteBackDDONE:1; + UINT32 WPDMABurstSIZE:2; + UINT32 RxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableTxDMA:1; + } field; + UINT32 word; +}WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#else +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 EnableTxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 RxDMABusy:1; + UINT32 WPDMABurstSIZE:2; + UINT32 EnTXWriteBackDDONE:1; + UINT32 BigEndian:1; +#ifdef DESC_32B_SUPPORT + UINT32 Desc32BEn:1; + UINT32 RXHdrScater:7; +#else + UINT32 HDR_SEG_LEN:8; +#endif /* DESC_32B_SUPPORT */ + UINT32 rsv:14; + UINT32 clk_gate_dis:1; + UINT32 rx_2b_offset:1; + } field; + UINT32 word; +} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#endif + +#define PBF_SYS_CTRL 0x0400 +//#define PBF_CFG 0x0404 + +#define PBF_CTRL 0x0410 +#define MCU_INT_STA 0x0414 +#define MCU_INT_ENA 0x0418 +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c + + +#endif /* __PBF_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/rf_ctrl.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/rf_ctrl.h new file mode 100644 index 000000000..8ce6821a3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/rf_ctrl.h @@ -0,0 +1,225 @@ +/* + *************************************************************************** + * 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: + rf_ctrl.h + + Abstract: + Ralink wireless chip RF related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RF_CTRL_H__ +#define __RF_CTRL_H__ + +#ifdef RTMP_MAC +#include "mac_ral/omac/ral_omac_rf_ctrl.h" +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC +#include "mac_ral/nmac/ral_nmac_rf_ctrl.h" +#endif /* RLT_MAC */ + + +/* ================================================================================= */ +/* Register format for RFCTRL */ +/* ================================================================================= */ + +#define RF_CSR_CFG 0x500 + +#ifdef RLT_RF + +#define RF_BANK0 0 +#define RF_BANK1 1 +#define RF_BANK2 2 +#define RF_BANK3 3 +#define RF_BANK4 4 +#define RF_BANK5 5 +#define RF_BANK6 6 +#define RF_BANK7 7 +#define RF_BANK8 8 +#define RF_BANK9 9 +#define RF_BANK10 10 +#define RF_BANK11 11 +#define RF_BANK12 12 +#define RF_BANK13 13 +#define RF_BANK14 14 +#define RF_BANK15 15 + +#define MAX_RF_ID 127 +#define MAC_RF_BANK 7 + + +/* @!Release + RF_CSR_KICK:1 + Write - kick RF register read/write + 0: do nothing + 1: kick read/write process + Read - Polling RF register read/write + 0: idle + 1: busy + RF_CSR_RW:1 + 0: read 1: write + rsv:12 + RF_CSR_REG_ID:10 + RF register ID, 0 for R0, 1 for R1 and so on + Bits [17:15] 3 bits, indicates the bank number + Bits [14:08] 7 bits, indicates the register number + + RF_CSR_DATA:8 + DATA written to/read from RF +*/ +#endif /* RLT_RF */ + + +typedef union _RF_CSR_CFG_STRUC { +#ifdef RT_BIG_ENDIAN + struct { + UINT32 Rsvd18:14; /* Reserved */ + UINT32 RF_CSR_KICK:1; /* kick RF register read/write */ + UINT32 RF_CSR_WR:1; /* 0: read 1: write */ + UINT32 TESTCSR_RFACC_REGNUM:8; /* RF register ID */ + UINT32 RF_CSR_DATA:8; /* DATA */ + } non_bank; +#ifdef RLT_RF +#ifdef RT6352 + struct { + UINT32 Rsvd26:6; + UINT32 TESTCSR_RFACC_REGNUM:10; /* RF register ID */ + UINT32 RF_CSR_DATA:8; /* DATA */ + UINT32 Rsvd5:3; /* Reserved */ + UINT32 RF_CSR_WR:1; /* 0: read 1: write */ + UINT32 Rsvd1:3; /* Reserved */ + UINT32 RF_CSR_KICK:1; /* kick RF register read/write */ + } bank_6352; +#endif /* RT6352 */ +#ifdef RT65xx + struct { + UINT32 RF_CSR_KICK:1; + UINT32 RF_CSR_WR:1; + UINT32 rsv18:12; + UINT32 RF_CSR_REG_BANK:3; + UINT32 RF_CSR_REG_ID:7; + UINT32 RF_CSR_DATA:8; + } bank_65xx; +#endif /* RT65xx */ +#endif /* RLT_RF */ +#else + struct { + UINT32 RF_CSR_DATA:8; + UINT32 TESTCSR_RFACC_REGNUM:8; + UINT32 RF_CSR_WR:1; + UINT32 RF_CSR_KICK:1; + UINT32 Rsvd18:14; + } non_bank; +#ifdef RLT_RF +#ifdef RT6352 + struct { + UINT32 RF_CSR_KICK:1; + UINT32 Rsvd1:3; + UINT32 RF_CSR_WR:1; + UINT32 Rsvd5:3; + UINT32 RF_CSR_DATA:8; + UINT32 TESTCSR_RFACC_REGNUM:10; + UINT32 Rsvd26:6; + } bank_6352; +#endif /* RT6352 */ +#ifdef RT65xx + struct { + UINT32 RF_CSR_DATA:8; + UINT32 RF_CSR_REG_ID:7; + UINT32 RF_CSR_REG_BANK:3; + UINT32 rsv18:12; + UINT32 RF_CSR_WR:1; + UINT32 RF_CSR_KICK:1; + } bank_65xx; +#endif /* RT65xx */ +#endif /* RLT_RF */ +#endif /* RT_BIG_ENDIAN */ + UINT32 word; +}RF_CSR_CFG_STRUC; + + +#define RF_PA_MODE_CCK_1M (pAd->chipCap.PAModeCCK[0]) +#define RF_PA_MODE_CCK_2M (pAd->chipCap.PAModeCCK[1]) +#define RF_PA_MODE_CCK_5M (pAd->chipCap.PAModeCCK[2]) +#define RF_PA_MODE_CCK_11M (pAd->chipCap.PAModeCCK[3]) + +#define RF_PA_MODE_OFDM_6M (pAd->chipCap.PAModeOFDM[0]) +#define RF_PA_MODE_OFDM_9M (pAd->chipCap.PAModeOFDM[1]) +#define RF_PA_MODE_OFDM_12M (pAd->chipCap.PAModeOFDM[2]) +#define RF_PA_MODE_OFDM_18M (pAd->chipCap.PAModeOFDM[3]) +#define RF_PA_MODE_OFDM_24M (pAd->chipCap.PAModeOFDM[4]) +#define RF_PA_MODE_OFDM_36M (pAd->chipCap.PAModeOFDM[5]) +#define RF_PA_MODE_OFDM_48M (pAd->chipCap.PAModeOFDM[6]) +#define RF_PA_MODE_OFDM_54M (pAd->chipCap.PAModeOFDM[7]) + +#define RF_PA_MODE_HT_MCS0 (pAd->chipCap.PAModeHT[0]) +#define RF_PA_MODE_HT_MCS1 (pAd->chipCap.PAModeHT[1]) +#define RF_PA_MODE_HT_MCS2 (pAd->chipCap.PAModeHT[2]) +#define RF_PA_MODE_HT_MCS3 (pAd->chipCap.PAModeHT[3]) +#define RF_PA_MODE_HT_MCS4 (pAd->chipCap.PAModeHT[4]) +#define RF_PA_MODE_HT_MCS5 (pAd->chipCap.PAModeHT[5]) +#define RF_PA_MODE_HT_MCS6 (pAd->chipCap.PAModeHT[6]) +#define RF_PA_MODE_HT_MCS7 (pAd->chipCap.PAModeHT[7]) +#define RF_PA_MODE_HT_MCS8 (pAd->chipCap.PAModeHT[8]) +#define RF_PA_MODE_HT_MCS9 (pAd->chipCap.PAModeHT[9]) +#define RF_PA_MODE_HT_MCS10 (pAd->chipCap.PAModeHT[10]) +#define RF_PA_MODE_HT_MCS11 (pAd->chipCap.PAModeHT[11]) +#define RF_PA_MODE_HT_MCS12 (pAd->chipCap.PAModeHT[12]) +#define RF_PA_MODE_HT_MCS13 (pAd->chipCap.PAModeHT[13]) +#define RF_PA_MODE_HT_MCS14 (pAd->chipCap.PAModeHT[14]) +#define RF_PA_MODE_HT_MCS15 (pAd->chipCap.PAModeHT[15]) + +#ifdef MT_RF +#define W_RFDATA 0x0524 +#define R_RFDATA 0x052C +#define RF_CTRL 0x0528 +#define RF_ADDR_MASK 0xfff +#define RF_ADDR(p) ((p) & 0xfff) +#define RF_R_W_CTRL (1 << 12) +#define RF_READY_MASK (1<< 13) +#define RF_READY(p) (((p) & RF_READY_MASK) == (0x0 << 13)) +#define RF_IDX_MASK (1 << 16) +#define RF_IDX(p) (((p) & 0x1) << 16) +#endif /* MT_RF */ + + +typedef struct _BANK_RF_REG_PAIR { + UCHAR Bank; + UCHAR Register; + UCHAR Value; +} BANK_RF_REG_PAIR, *PBANK_RF_REG_PAIR; + +typedef struct _R_M_W_REG{ + UINT32 Register; + UINT32 ClearBitMask; + UINT32 Value; +} R_M_W_REG, *PR_M_W_REG; + +typedef struct _RF_R_M_W_REG{ + UCHAR Bank; + UCHAR Register; + UCHAR ClearBitMask; + UCHAR Value; +} RF_R_M_W_REG, *PRF_R_M_W_REG; + +#endif /* __RF_CTRL_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/rtmp_mac.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/rtmp_mac.h new file mode 100644 index 000000000..82ea476ba --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mac_ral/rtmp_mac.h @@ -0,0 +1,2695 @@ +/* + *************************************************************************** + * 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_mac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_MAC_H__ +#define __RTMP_MAC_H__ + + +#ifdef RLT_MAC +#include "mac_ral/nmac/ral_nmac.h" +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC +#include "mac_ral/omac/ral_omac.h" +#endif /* RTMP_MAC */ + + +/* + TX / RX ring descriptor format + + TX: + PCI/RBUS_Descriptor + TXINFO + TXWI + 802.11 + + Rx: + PCI/RBUS/USB_Descripotr + (PCI/RBUS RXFCE_INFO) + (PCI/RBUS RXINFO) + RXWI + 802.11 + (USB RXINFO) + +*/ + +/* the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. */ +/* MAC block use this TXINFO to control the transmission behavior of this frame. */ +#define FIFO_MGMT 0 +#define FIFO_HCCA 1 +#define FIFO_EDCA 2 + +typedef union GNU_PACKED _TXWI_STRUC { +#ifdef RLT_MAC + struct _TXWI_NMAC TXWI_N; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + struct _TXWI_OMAC TXWI_O; +#endif /* RTMP_MAC */ + UINT32 word; +}TXWI_STRUC; + + +#define TXINFO_SIZE 4 +typedef union GNU_PACKED _TXINFO_STRUC{ +#ifdef RTMP_MAC + struct _TXINFO_OMAC txinfo_omac; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + struct _TXINFO_NMAC_PKT txinfo_nmac_pkt; + struct _TXINFO_NMAC_CMD txinfo_nmac_cmd; +#endif /* RLT_MAC */ + UINT32 word; +}TXINFO_STRUC; + + +/* + RXWI wireless information format, in PBF. invisible in driver. +*/ +typedef union GNU_PACKED _RXWI_STRUC { +#ifdef RLT_MAC + struct _RXWI_NMAC RXWI_N; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + struct _RXWI_OMAC RXWI_O; +#endif /* RTMP_MAC */ +}RXWI_STRUC; + + +typedef union GNU_PACKED _HW_RATE_CTRL_STRUCT_ { +#ifdef RLT_MAC + struct _NMAC_HW_RATE_CTRL_STRUCT RATE_CTRL_N; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + struct _OMAC_HW_RATE_CTRL_STRUCT RATE_CTRL_O; +#endif /* RTMP_MAC */ + UINT16 word; +}HW_RATE_CTRL_STRUCT; + + +/* + bit31 =>802.3 if set 1, implay you hav did header translation + bit30 => put VLAN field + +*/ +#define RXINFO_SIZE 4 +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXINFO_STRUC { + UINT32 hdr_trans_ip_sum_err:1; /* IP checksum error */ + UINT32 vlan_taged_tcp_sum_err:1; /* TCP checksum error */ + UINT32 rsv:1; + UINT32 action_wanted:1; + UINT32 deauth:1; + UINT32 disasso:1; + UINT32 beacon:1; + UINT32 probe_rsp:1; + UINT32 sw_fc_type1:1; + UINT32 sw_fc_type0:1; + UINT32 pn_len:3; + UINT32 wapi_kidx:1; + UINT32 BssIdx3:1; + UINT32 Decrypted:1; + UINT32 AMPDU:1; + UINT32 L2PAD:1; + UINT32 RSSI:1; + UINT32 HTC:1; + UINT32 AMSDU:1; /* rx with 802.3 header, not 802.11 header. obsolete. */ + UINT32 CipherErr:2; /* 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid */ + UINT32 Crc:1; /* 1: CRC error */ + UINT32 MyBss:1; /* 1: this frame belongs to the same BSSID */ + UINT32 Bcast:1; /* 1: this is a broadcast frame */ + UINT32 Mcast:1; /* 1: this is a multicast frame */ + UINT32 U2M:1; /* 1: this RX frame is unicast to me */ + UINT32 FRAG:1; + UINT32 NULLDATA:1; + UINT32 DATA:1; + UINT32 BA:1; +} RXINFO_STRUC, *PRXINFO_STRUC; +#else +typedef struct GNU_PACKED _RXINFO_STRUC { + UINT32 BA:1; + UINT32 DATA:1; + UINT32 NULLDATA:1; + UINT32 FRAG:1; + UINT32 U2M:1; + UINT32 Mcast:1; + UINT32 Bcast:1; + UINT32 MyBss:1; + UINT32 Crc:1; + UINT32 CipherErr:2; + UINT32 AMSDU:1; + UINT32 HTC:1; + UINT32 RSSI:1; + UINT32 L2PAD:1; + UINT32 AMPDU:1; + UINT32 Decrypted:1; + UINT32 BssIdx3:1; + UINT32 wapi_kidx:1; + UINT32 pn_len:3; + UINT32 sw_fc_type0:1; + UINT32 sw_fc_type1:1; + UINT32 probe_rsp:1; + UINT32 beacon:1; + UINT32 disasso:1; + UINT32 deauth:1; + UINT32 action_wanted:1; + UINT32 rsv:1; + UINT32 vlan_taged_tcp_sum_err:1; + UINT32 hdr_trans_ip_sum_err:1; +}RXINFO_STRUC, *PRXINFO_STRUC; +#endif + + +#define TSO_SIZE 0 + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ + +#define ASIC_VERSION 0x0000 + + +/* + SCH/DMA registers - base address 0x0200 +*/ +#define WMM_AIFSN_CFG 0x0214 +#ifdef RT_BIG_ENDIAN +typedef union _AIFSN_CSR_STRUC{ + struct { + UINT32 Aifsn7:4; /* for AC_VO */ + UINT32 Aifsn6:4; /* for AC_VI */ + UINT32 Aifsn5:4; /* for AC_BK */ + UINT32 Aifsn4:4; /* for AC_BE */ + UINT32 Aifsn3:4; /* for AC_VO */ + UINT32 Aifsn2:4; /* for AC_VI */ + UINT32 Aifsn1:4; /* for AC_BK */ + UINT32 Aifsn0:4; /* for AC_BE */ + }field; + UINT32 word; +} AIFSN_CSR_STRUC; +#else +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Aifsn0:4; + UINT32 Aifsn1:4; + UINT32 Aifsn2:4; + UINT32 Aifsn3:4; + UINT32 Aifsn4:4; + UINT32 Aifsn5:4; + UINT32 Aifsn6:4; + UINT32 Aifsn7:4; + } field; + UINT32 word; +} AIFSN_CSR_STRUC; +#endif + +/* CWMIN_CSR: CWmin for each EDCA AC */ +#define WMM_CWMIN_CFG 0x0218 +#ifdef RT_BIG_ENDIAN +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin7:4; /* for AC_VO */ + UINT32 Cwmin6:4; /* for AC_VI */ + UINT32 Cwmin5:4; /* for AC_BK */ + UINT32 Cwmin4:4; /* for AC_BE */ + UINT32 Cwmin3:4; /* for AC_VO */ + UINT32 Cwmin2:4; /* for AC_VI */ + UINT32 Cwmin1:4; /* for AC_BK */ + UINT32 Cwmin0:4; /* for AC_BE */ + } field; + UINT32 word; +} CWMIN_CSR_STRUC; +#else +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin0:4; + UINT32 Cwmin1:4; + UINT32 Cwmin2:4; + UINT32 Cwmin3:4; + UINT32 Cwmin4:4; + UINT32 Cwmin5:4; + UINT32 Cwmin6:4; + UINT32 Cwmin7:4; + } field; + UINT32 word; +} CWMIN_CSR_STRUC; +#endif + + +/* CWMAX_CSR: CWmin for each EDCA AC */ +#define WMM_CWMAX_CFG 0x021c +#ifdef RT_BIG_ENDIAN +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax7:4; /* for AC_VO */ + UINT32 Cwmax6:4; /* for AC_VI */ + UINT32 Cwmax5:4; /* for AC_BK */ + UINT32 Cwmax4:4; /* for AC_BE */ + UINT32 Cwmax3:4; /* for AC_VO */ + UINT32 Cwmax2:4; /* for AC_VI */ + UINT32 Cwmax1:4; /* for AC_BK */ + UINT32 Cwmax0:4; /* for AC_BE */ + } field; + UINT32 word; +} CWMAX_CSR_STRUC; +#else +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax0:4; + UINT32 Cwmax1:4; + UINT32 Cwmax2:4; + UINT32 Cwmax3:4; + UINT32 Cwmax4:4; + UINT32 Cwmax5:4; + UINT32 Cwmax6:4; + UINT32 Cwmax7:4; + } field; + UINT32 word; +} CWMAX_CSR_STRUC; +#endif + + +/* AC_TXOP_CSR0: AC_BK/AC_BE TXOP register */ +#define WMM_TXOP0_CFG 0x0220 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR0_STRUC { + struct { + UINT16 Ac1Txop; /* for AC_BE, in unit of 32us */ + UINT16 Ac0Txop; /* for AC_BK, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC; +#else +typedef union _AC_TXOP_CSR0_STRUC { + struct { + UINT16 Ac0Txop; + UINT16 Ac1Txop; + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC; +#endif + + +/* AC_TXOP_CSR1: AC_VO/AC_VI TXOP register */ +#define WMM_TXOP1_CFG 0x0224 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR1_STRUC { + struct { + UINT16 Ac3Txop; /* for AC_VO, in unit of 32us */ + UINT16 Ac2Txop; /* for AC_VI, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC; +#else +typedef union _AC_TXOP_CSR1_STRUC { + struct { + UINT16 Ac2Txop; + UINT16 Ac3Txop; + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC; +#endif + + +#define WMM_TXOP2_CFG 0x0228 +#define WMM_TXOP3_CFG 0x022c + +#define WMM_CTRL 0x0230 + + +/*================================================================================= */ +/* MAC registers */ +/*================================================================================= */ +/* 4.1 MAC SYSTEM configuration registers (offset:0x1000) */ +#define MAC_CSR0 0x1000 +#ifdef RT_BIG_ENDIAN +typedef union _ASIC_VER_ID_STRUC { + struct { + UINT16 ASICVer; /* version */ + UINT16 ASICRev; /* reversion */ + } field; + UINT32 word; +} ASIC_VER_ID_STRUC; +#else +typedef union _ASIC_VER_ID_STRUC { + struct { + UINT16 ASICRev; + UINT16 ASICVer; + } field; + UINT32 word; +} ASIC_VER_ID_STRUC; +#endif + +#define MAC_SYS_CTRL 0x1004 +#define PBF_LOOP_EN (1 << 5) +#define MAC_ADDR_DW0 0x1008 +#define MAC_ADDR_DW1 0x100c + +/* MAC_CSR2: STA MAC register 0 */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW0_STRUC { + struct { + UINT8 Byte3; /* MAC address byte 3 */ + UINT8 Byte2; /* MAC address byte 2 */ + UINT8 Byte1; /* MAC address byte 1 */ + UINT8 Byte0; /* MAC address byte 0 */ + } field; + UINT32 word; +} MAC_DW0_STRUC; +#else +typedef union _MAC_DW0_STRUC { + struct { + UINT8 Byte0; + UINT8 Byte1; + UINT8 Byte2; + UINT8 Byte3; + } field; + UINT32 word; +} MAC_DW0_STRUC; +#endif + + +/* MAC_CSR3: STA MAC register 1 */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW1_STRUC { + struct { + UINT8 Rsvd1; + UINT8 U2MeMask; + UINT8 Byte5; /* MAC address byte 5 */ + UINT8 Byte4; /* MAC address byte 4 */ + } field; + UINT32 word; +} MAC_DW1_STRUC; +#else +typedef union _MAC_DW1_STRUC { + struct { + UINT8 Byte4; + UINT8 Byte5; + UINT8 U2MeMask; + UINT8 Rsvd1; + } field; + UINT32 word; +} MAC_DW1_STRUC; +#endif + +#define MAC_BSSID_DW0 0x1010 +#define MAC_BSSID_DW1 0x1014 +/* MAC_CSR5: BSSID register 1 */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_BSSID_DW1_STRUC { + struct { + UINT32 NMBssMode3:1; + UINT32 NMBssMode2:1; + UINT32 NMBssMode:1; + UINT32 MBssBcnNum:3; + UINT32 MBssMode:2; /* 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID */ + UINT32 Byte5:8; /* BSSID byte 5 */ + UINT32 Byte4:8; /* BSSID byte 4 */ + } field; + UINT32 word; +} MAC_BSSID_DW1_STRUC; +#else +typedef union _MAC_BSSID_DW1_STRUC { + struct { + UINT32 Byte4:8; + UINT32 Byte5:8; + UINT32 MBssMode:2; + UINT32 MBssBcnNum:3; + UINT32 NMBssMode:1; + UINT32 NMBssMode2:1; + UINT32 NMBssMode3:1; + } field; + UINT32 word; +} MAC_BSSID_DW1_STRUC; +#endif + +/* rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 */ +#define MAX_LEN_CFG 0x1018 + + +/* BBP_CSR_CFG: BBP serial control register */ +#define BBP_CSR_CFG 0x101c +#ifdef RT_BIG_ENDIAN +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 :12; + UINT32 BBP_RW_MODE:1; /* 0: use serial mode 1:parallel */ + UINT32 BBP_PAR_DUR:1; /* 0: 4 MAC clock cycles 1: 8 MAC clock cycles */ + UINT32 Busy:1; /* 1: ASIC is busy execute BBP programming. */ + UINT32 fRead:1; /* 0: Write BBP, 1: Read BBP */ + UINT32 RegNum:8; /* Selected BBP register */ + UINT32 Value:8; /* Register value to program into BBP */ + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC; +#else +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 Value:8; + UINT32 RegNum:8; + UINT32 fRead:1; + UINT32 Busy:1; + UINT32 BBP_PAR_DUR:1; + UINT32 BBP_RW_MODE:1; + UINT32 :12; + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC; +#endif + + +/* RF_CSR_CFG: RF control register */ +#define RF_CSR_CFG0 0x1020 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 Busy:1; /* 0: idle 1: 8busy */ + UINT32 Sel:1; /* 0:RF_LE0 activate 1:RF_LE1 activate */ + UINT32 StandbyMode:1; /* 0: high when stand by 1: low when standby */ + UINT32 bitwidth:5; /* Selected BBP register */ + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC; +#else +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 RegIdAndContent:24; + UINT32 bitwidth:5; + UINT32 StandbyMode:1; + UINT32 Sel:1; + UINT32 Busy:1; + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC; +#endif + + +#define RF_CSR_CFG1 0x1024 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 rsv:7; /* 0: idle 1: 8busy */ + UINT32 RFGap:5; /* Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) */ + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC; +#else +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 RegIdAndContent:24; + UINT32 RFGap:5; + UINT32 rsv:7; + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC; +#endif + + +#define RF_CSR_CFG2 0x1028 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 rsv:8; /* 0: idle 1: 8busy */ + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC; +#else +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 RegIdAndContent:24; + UINT32 rsv:8; + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC; +#endif + + +#define LED_CFG 0x102c +#ifdef RT_BIG_ENDIAN +typedef union _LED_CFG_STRUC { + struct { + UINT32 :1; + UINT32 LedPolar:1; /* Led Polarity. 0: active low1: active high */ + UINT32 YLedMode:2; /* yellow Led Mode */ + UINT32 GLedMode:2; /* green Led Mode */ + UINT32 RLedMode:2; /* red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on */ + UINT32 rsv:2; + UINT32 SlowBlinkPeriod:6; /* slow blinking period. unit:1ms */ + UINT32 OffPeriod:8; /* blinking off period unit 1ms */ + UINT32 OnPeriod:8; /* blinking on period unit 1ms */ + } field; + UINT32 word; +} LED_CFG_STRUC; +#else +typedef union _LED_CFG_STRUC { + struct { + UINT32 OnPeriod:8; + UINT32 OffPeriod:8; + UINT32 SlowBlinkPeriod:6; + UINT32 rsv:2; + UINT32 RLedMode:2; + UINT32 GLedMode:2; + UINT32 YLedMode:2; + UINT32 LedPolar:1; + UINT32 :1; + } field; + UINT32 word; +} LED_CFG_STRUC; +#endif + + +#define AMPDU_MAX_LEN_20M1S 0x1030 +#define AMPDU_MAX_LEN_20M2S 0x1034 +#define AMPDU_MAX_LEN_20M1S_MCS0_7 0x1030 +#define AMPDU_MAX_LEN_20M1S_MCS8_9 0x1034 +#define AMPDU_MAX_LEN_40M1S 0x1038 +#define AMPDU_MAX_LEN_40M2S 0x103c +#define AMPDU_MAX_LEN 0x1040 + + +/* The number of the Tx chains */ +#define NUM_OF_TX_CHAIN 4 + +#define TX_CHAIN_ADDR0_L 0x1044 /* Stream mode MAC address registers */ +#define TX_CHAIN_ADDR0_H 0x1048 +#define TX_CHAIN_ADDR1_L 0x104C +#define TX_CHAIN_ADDR1_H 0x1050 +#define TX_CHAIN_ADDR2_L 0x1054 +#define TX_CHAIN_ADDR2_H 0x1058 +#define TX_CHAIN_ADDR3_L 0x105C +#define TX_CHAIN_ADDR3_H 0x1060 + +#define TX_WCID_DROP_MASK0 0x106C + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR0_L_STRUC { + struct { + UINT8 TxChainAddr0L_Byte3; /* Destination MAC address of Tx chain0 (byte 3) */ + UINT8 TxChainAddr0L_Byte2; /* Destination MAC address of Tx chain0 (byte 2) */ + UINT8 TxChainAddr0L_Byte1; /* Destination MAC address of Tx chain0 (byte 1) */ + UINT8 TxChainAddr0L_Byte0; /* Destination MAC address of Tx chain0 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR0_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR0_L_STRUC { + struct { + UINT8 TxChainAddr0L_Byte0; + UINT8 TxChainAddr0L_Byte1; + UINT8 TxChainAddr0L_Byte2; + UINT8 TxChainAddr0L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR0_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR0_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr0H_Byte5; /* Destination MAC address of Tx chain0 (byte 5) */ + UINT8 TxChainAddr0H_Byte4; /* Destination MAC address of Tx chain0 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR0_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR0_H_STRUC { + struct { + UINT8 TxChainAddr0H_Byte4; /* Destination MAC address of Tx chain0 (byte 4) */ + UINT8 TxChainAddr0H_Byte5; /* Destination MAC address of Tx chain0 (byte 5) */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT16 Reserved:12; /* Reserved */ + } field; + UINT32 word; +} TX_CHAIN_ADDR0_H_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR1_L_STRUC { + struct { + UINT8 TxChainAddr1L_Byte3; /* Destination MAC address of Tx chain1 (byte 3) */ + UINT8 TxChainAddr1L_Byte2; /* Destination MAC address of Tx chain1 (byte 2) */ + UINT8 TxChainAddr1L_Byte1; /* Destination MAC address of Tx chain1 (byte 1) */ + UINT8 TxChainAddr1L_Byte0; /* Destination MAC address of Tx chain1 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR1_L_STRUC, *PTX_CHAIN_ADDR1_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR1_L_STRUC { + struct { + UINT8 TxChainAddr1L_Byte0; + UINT8 TxChainAddr1L_Byte1; + UINT8 TxChainAddr1L_Byte2; + UINT8 TxChainAddr1L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR1_L_STRUC, *PTX_CHAIN_ADDR1_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR1_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr1H_Byte5; /* Destination MAC address of Tx chain1 (byte 5) */ + UINT8 TxChainAddr1H_Byte4; /* Destination MAC address of Tx chain1 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR1_H_STRUC ; +#else +typedef union _TX_CHAIN_ADDR1_H_STRUC { + struct { + UINT8 TxChainAddr1H_Byte4; + UINT8 TxChainAddr1H_Byte5; + UINT16 TxChainSel0:4; + UINT16 Reserved:12; + } field; + UINT32 word; +} TX_CHAIN_ADDR1_H_STRUC ; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR2_L_STRUC { + struct { + UINT8 TxChainAddr2L_Byte3; /* Destination MAC address of Tx chain2 (byte 3) */ + UINT8 TxChainAddr2L_Byte2; /* Destination MAC address of Tx chain2 (byte 2) */ + UINT8 TxChainAddr2L_Byte1; /* Destination MAC address of Tx chain2 (byte 1) */ + UINT8 TxChainAddr2L_Byte0; /* Destination MAC address of Tx chain2 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR2_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR2_L_STRUC { + struct { + UINT8 TxChainAddr2L_Byte0; + UINT8 TxChainAddr2L_Byte1; + UINT8 TxChainAddr2L_Byte2; + UINT8 TxChainAddr2L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR2_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR2_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr2H_Byte5; /* Destination MAC address of Tx chain2 (byte 5) */ + UINT8 TxChainAddr2H_Byte4; /* Destination MAC address of Tx chain2 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR2_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR2_H_STRUC { + struct { + UINT8 TxChainAddr2H_Byte4; + UINT8 TxChainAddr2H_Byte5; + UINT16 TxChainSel0:4; + UINT16 Reserved:12; + } field; + UINT32 word; +} TX_CHAIN_ADDR2_H_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR3_L_STRUC { + struct { + UINT8 TxChainAddr3L_Byte3; /* Destination MAC address of Tx chain3 (byte 3) */ + UINT8 TxChainAddr3L_Byte2; /* Destination MAC address of Tx chain3 (byte 2) */ + UINT8 TxChainAddr3L_Byte1; /* Destination MAC address of Tx chain3 (byte 1) */ + UINT8 TxChainAddr3L_Byte0; /* Destination MAC address of Tx chain3 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR3_L_STRUC, *PTX_CHAIN_ADDR3_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR3_L_STRUC { + struct { + UINT8 TxChainAddr3L_Byte0; + UINT8 TxChainAddr3L_Byte1; + UINT8 TxChainAddr3L_Byte2; + UINT8 TxChainAddr3L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR3_L_STRUC, *PTX_CHAIN_ADDR3_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR3_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr3H_Byte5; /* Destination MAC address of Tx chain3 (byte 5) */ + UINT8 TxChainAddr3H_Byte4; /* Destination MAC address of Tx chain3 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR3_H_STRUC, *PTX_CHAIN_ADDR3_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR3_H_STRUC { + struct { + UINT8 TxChainAddr3H_Byte4; + UINT8 TxChainAddr3H_Byte5; + UINT16 TxChainSel0:4; + UINT16 Reserved:12; + } field; + UINT32 word; +} TX_CHAIN_ADDR3_H_STRUC; +#endif + +#define TX_BCN_BYPASS_MASK 0x108C +typedef union _BCN_BYPASS_MASK_STRUC { + struct { + UINT32 BeaconDropMask:16; + } field; + UINT32 word; +} BCN_BYPASS_MASK_STRUC; + +/* 4.2 MAC TIMING configuration registers (offset:0x1100) */ +#define XIFS_TIME_CFG 0x1100 +#define XIFS_TIME_OFDM_SIFS_MASK (0xff << 8) +#define XIFS_TIME_OFDM_SIFS(p) (((p) & 0xff) << 8) +#ifdef RT_BIG_ENDIAN +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 rsv:2; + UINT32 BBRxendEnable:1; /* reference RXEND signal to begin XIFS defer */ + UINT32 EIFS:9; /* unit 1us */ + UINT32 OfdmXifsTime:4; /*OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND */ + UINT32 OfdmSifsTime:8; /* unit 1us. Applied after OFDM RX/TX */ + UINT32 CckmSifsTime:8; /* unit 1us. Applied after CCK RX/TX */ + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC; +#else +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 CckmSifsTime:8; + UINT32 OfdmSifsTime:8; + UINT32 OfdmXifsTime:4; + UINT32 EIFS:9; + UINT32 BBRxendEnable:1; + UINT32 rsv:2; + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC; +#endif + +#define BKOFF_SLOT_CFG 0x1104 +#define BKOFF_SLOT_CFG_CC_DELAY_TIME_MASK (0x0f << 8) +#define BKOFF_SLOT_CFG_CC_DELAY_TIME(p) (((p) & 0x0f) << 8) + +#define NAV_TIME_CFG 0x1108 +#define CH_TIME_CFG 0x110C +#define PBF_LIFE_TIMER 0x1110 /*TX/RX MPDU timestamp timer (free run)Unit: 1us */ + + +/* BCN_TIME_CFG : Synchronization control register */ +#define BCN_TIME_CFG 0x1114 +#ifdef RT_BIG_ENDIAN +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 TxTimestampCompensate:8; + UINT32 :3; + UINT32 bBeaconGen:1; /* Enable beacon generator */ + UINT32 bTBTTEnable:1; + UINT32 TsfSyncMode:2; /* Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode */ + UINT32 bTsfTicking:1; /* Enable TSF auto counting */ + UINT32 BeaconInterval:16; /* in unit of 1/16 TU */ + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC; +#else +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 BeaconInterval:16; + UINT32 bTsfTicking:1; + UINT32 TsfSyncMode:2; + UINT32 bTBTTEnable:1; + UINT32 bBeaconGen:1; + UINT32 :3; + UINT32 TxTimestampCompensate:8; + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC; +#endif + + +#define TBTT_SYNC_CFG 0x1118 +#define TSF_TIMER_DW0 0x111c /* Local TSF timer lsb 32 bits. Read-only */ +#define TSF_TIMER_DW1 0x1120 /* msb 32 bits. Read-only. */ +#define TBTT_TIMER 0x1124 /* TImer remains till next TBTT. Read-only */ +#define INT_TIMER_CFG 0x1128 +#define INT_TIMER_EN 0x112c /* GP-timer and pre-tbtt Int enable */ +#define INT_TIMER_EN_PRE_TBTT 0x1 +#define INT_TIMER_EN_GP_TIMER 0x2 + +#define CH_IDLE_STA 0x1130 /* channel idle time */ +#define CH_BUSY_STA 0x1134 /* channle busy time */ +#define CH_BUSY_STA_SEC 0x1138 /* channel busy time for secondary channel */ +#ifdef CUSTOMER_DCC_FEATURE +#define CCA_BUSY_TIME 0x1140 +#endif + +/* 4.2 MAC POWER configuration registers (offset:0x1200) */ +#define MAC_STATUS_CFG 0x1200 +#define PWR_PIN_CFG 0x1204 + + +/* AUTO_WAKEUP_CFG: Manual power control / status register */ +#define AUTO_WAKEUP_CFG 0x1208 +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 :16; + UINT32 EnableAutoWakeup:1; /* 0:sleep, 1:awake */ + UINT32 NumofSleepingTbtt:7; /* ForceWake has high privilege than PutToSleep when both set */ + UINT32 AutoLeadTime:8; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC; +#else +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 AutoLeadTime:8; + UINT32 NumofSleepingTbtt:7; + UINT32 EnableAutoWakeup:1; + UINT32 :16; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC; +#endif + +#define AUX_CLK_CFG 0x120C +#define MIMO_PS_CFG 0x1210 + +#if defined(RT6352) || defined(MT76x0) || defined(MT76x2) || defined (MT7601) +#define BB_PA_MODE_CFG0 0x1214 +#define BB_PA_MODE_CFG1 0x1218 +#define RF_PA_MODE_CFG0 0x121C +#define RF_PA_MODE_CFG1 0x1220 + +#define DACCLK_EN_DLY_CFG 0x1264 + +#define TX_ALC_CFG_0 0x13B0 +#define TX_ALC_CFG_0_CH_INT_0_MASK (0x3f) +#define TX_ALC_CFG_0_CH_INT_0(p) ((p) & 0x3f) +#define TX_ALC_CFG_0_CH_INT_1_MASK ((0x3f) << 8) +#define TX_ALC_CFG_0_CH_INT_1(p) (((p) & 0x3f) << 8) + +#define TX_ALC_CFG_1 0x13B4 +#define TX_ALC_CFG_1_TX0_TEMP_COMP_MASK (0x3f) +#define TX_ALC_CFG_1_TX0_TEMP_COMP(p) ((p) & 0x3f) +#define TX_ALC_CFG_2 0x13A8 +#define TX_ALC_CFG_2_TX1_TEMP_COMP_MASK (0x3f) +#define TX_ALC_CFG_2_TX1_TEMP_COMP(p) ((p) & 0x3f) +#define TX_ALC_CFG_3 0x13AC +#define TX_ALC_CFG_4 0x13C0 + +#define TX0_RF_GAIN_CORR 0x13A0 +#define TX0_RF_GAIN_ATTEN 0x13A8 +#define TX0_BB_GAIN_ATTEN 0x13C0 +#define WL_LOWGAIN_CH_EN (1 << 31) + +#define TX_ALC_VGA3 0x13C8 + +#define TX1_RF_GAIN_CORR 0x13A4 +#define TX1_RF_GAIN_ATTEN 0x13AC +#define WL_LOWGAIN_CH_EN (1 << 31) +#endif /* defined(RT6352) || defined(MT76x0) || defined(MT76x2) || defined (MT7601) */ + + +/* 4.3 MAC TX configuration registers (offset:0x1300) */ +#define EDCA_AC0_CFG 0x1300 +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC3_CFG 0x130c +#ifdef RT_BIG_ENDIAN +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 :12; + UINT32 Cwmax:4; /* unit power of 2 */ + UINT32 Cwmin:4; + UINT32 Aifsn:4; /* # of slot time */ + UINT32 AcTxop:8; /* in unit of 32us */ + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC; +#else +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 AcTxop:8; + UINT32 Aifsn:4; + UINT32 Cwmin:4; + UINT32 Cwmax:4; + UINT32 :12; + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC; +#endif /* RT_BIG_ENDIAN */ + +#define EDCA_TID_AC_MAP 0x1310 + + +/* Default Tx power */ +#define DEFAULT_TX_POWER 0x6 + +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CCK_1_2_MASK (0x3f) +#define TX_PWR_CCK_1_2(p) (((p) & 0x3f)) +#define TX_PWR_CCK_5_11_MASK (0x3f << 8) +#define TX_PWR_CCK_5_11(p) (((p) & 0x3f) << 8) +#define TX_PWR_OFDM_6_9_MASK (0x3f << 16) +#define TX_PWR_OFDM_6_9(p) (((p) & 0x3f) << 16) +#define TX_PWR_OFDM_12_18_MASK (0x3f << 24) +#define TX_PWR_OFDM_12_18(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_0_EXT 0x1390 + +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_OFDM_24_36_MASK (0x3f) +#define TX_PWR_OFDM_24_36(p) (((p) & 0x3f)) +#define TX_PWR_OFDM_48_MASK (0x3f << 8) +#define TX_PWR_OFDM_48(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_VHT_1SS_MCS_0_1_MASK (0x3f << 16) +#define TX_PWR_HT_VHT_1SS_MCS_0_1(p) (((p) & 0x3f) << 16) +#define TX_PWR_HT_VHT_1SS_MCS_2_3_MASK (0x3f << 24) +#define TX_PWR_HT_VHT_1SS_MCS_2_3(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_1_EXT 0x1394 + +#define TX_PWR_CFG_2 0x131C +#define TX_PWR_HT_VHT_1SS_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_VHT_1SS_MCS_4_5(p) (((p) & 0x3f)) +#define TX_PWR_HT_VHT_1SS_MCS_6_MASK (0x3f << 8) +#define TX_PWR_HT_VHT_1SS_MCS_6(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_MCS_8_9_VHT_2SS_0_1_MASK (0x3f << 16) +#define TX_PWR_HT_MCS_8_9_VHT_2SS_0_1(p) (((p) & 0x3f) << 16) +#define TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3_MASK (0x3f << 24) +#define TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_2_EXT 0x1398 + +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_HT_MCS_12_13_VHT_2SS_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_MCS_12_13_VHT_2SS_MCS_4_5(p) (((p) & 0x3f)) +#define TX_PWR_HT_MCS_14_VHT_2SS_MCS_6_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_14_VHT_2SS_MCS_6(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_VHT_STBC_MCS_0_1_MASK (0x3f << 16) +#define TX_PWR_HT_VHT_STBC_MCS_0_1(p) (((p) & 0x3f) << 16) +#define TX_PWR_HT_VHT_STBC_MCS_2_3_MASK (0x3f << 24) +#define TX_PWR_HT_VHT_STBC_MCS_2_3(p) (((p) & 0x3f) << 24) + +#define GF20_PORT_CFG 0x1374 +#define TX_PWR_CFG_3_EXT 0x139C + +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_HT_VHT_STBC_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_VHT_STBC_MCS_4_5(p) (((p) & 0x3f)) +#define TX_PWR_HT_VHT_STBC_MCS_6_MASK (0x3f << 8) +#define TX_PWR_HT_VHT_STBC_MCS_6(p) (((p) & 0x3f) << 8) + +#define TX_PWR_CFG_0_EXT 0x1390 +#define TX_PWR_CFG_1_EXT 0x1394 +#define TX_PWR_CFG_2_EXT 0x1398 +#define TX_PWR_CFG_3_EXT 0x139C +#define TX_PWR_CFG_4_EXT 0x13A0 + +#define TX_PWR_CFG_5 0x1384 +#define TX_PWR_CFG_6 0x1388 + +#define TX_PWR_CFG_7 0x13D4 +#define TX_PWR_OFDM_54_MASK (0x3f) +#define TX_PWR_OFDM_54(p) (((p) & 0x3f)) +#define TX_PWR_VHT_2SS_MCS_8_MASK (0x3f << 8) +#define TX_PWR_VHT_2SS_MCS_8(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_MCS_7_VHT_1SS_MCS_7_MASK (0x3f << 16) +#define TX_PWR_HT_MCS_7_VHT_1SS_MCS_7(p) (((p) & 0x3f) << 16) +#define TX_PWR_VHT_2SS_MCS_9_MASK (0X3f << 24) +#define TX_PWR_VHT_2SS_MCS_9(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_8 0x13D8 +#define TX_PWR_HT_MCS_15_VHT_2SS_MCS7_MASK (0x3f) +#define TX_PWR_HT_MCS_15_VHT_2SS_MCS7(p) (((p) & 0x3f)) +#define TX_PWR_VHT_1SS_MCS_8_MASK (0x3f << 16) +#define TX_PWR_VHT_1SS_MCS_8(p) (((p) & 0x3f) << 16) +#define TX_PWR_VHT_1SS_MCS_9_MASK (0X3f << 24) +#define TX_PWR_VHT_1SS_MCS_9(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_9 0x13DC +#define TX_PWR_HT_VHT_STBC_MCS_7_MASK (0x3f) +#define TX_PWR_HT_VHT_STBC_MCS_7(p) (((p) & 0x3f)) +#define TX_PWR_VHT_STBC_MCS_8_MASK (0x3f << 16) +#define TX_PWR_VHT_STBC_MCS_8(p) (((p) & 0x3f) << 16) +#define TX_PWR_VHT_STBC_MCS_9_MASK (0x3f << 24) +#define TX_PWR_VHT_STBC_MCS_9(p) (((p) & 0x3f) << 24) + +#ifdef RT_BIG_ENDIAN +typedef union _TX_PWR_CFG_STRUC { + struct { + UINT32 Byte3:8; + UINT32 Byte2:8; + UINT32 Byte1:8; + UINT32 Byte0:8; + } field; + UINT32 word; +} TX_PWR_CFG_STRUC; +#else +typedef union _TX_PWR_CFG_STRUC { + struct { + UINT32 Byte0:8; + UINT32 Byte1:8; + UINT32 Byte2:8; + UINT32 Byte3:8; + } field; + UINT32 word; +} TX_PWR_CFG_STRUC; +#endif + + +#define TX_PIN_CFG 0x1328 +#define TX_BAND_CFG 0x132c /* 0x1 use upper 20MHz. 0 juse lower 20MHz */ +#define TX_SW_CFG0 0x1330 +#define TX_SW_CFG1 0x1334 +#define TX_SW_CFG2 0x1338 + + +#define TXOP_THRES_CFG 0x133c +#ifdef RT_BIG_ENDIAN +typedef union _TXOP_THRESHOLD_CFG_STRUC { + struct { + UINT32 TXOP_REM_THRES:8; /* Remaining TXOP threshold (unit: 32us) */ + UINT32 CF_END_THRES:8; /* CF-END threshold (unit: 32us) */ + UINT32 RDG_IN_THRES:8; /* Rx RDG threshold (unit: 32us) */ + UINT32 RDG_OUT_THRES:8; /* Tx RDG threshold (unit: 32us) */ + } field; + UINT32 word; +} TXOP_THRESHOLD_CFG_STRUC; +#else +typedef union _TXOP_THRESHOLD_CFG_STRUC { + struct { + UINT32 RDG_OUT_THRES:8; + UINT32 RDG_IN_THRES:8; + UINT32 CF_END_THRES:8; + UINT32 TXOP_REM_THRES:8; + } field; + UINT32 word; +} TXOP_THRESHOLD_CFG_STRUC; +#endif + +#define TXOP_CTRL_CFG 0x1340 + + +#define TX_RTS_CFG 0x1344 +#ifdef RT_BIG_ENDIAN +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 rsv:7; + UINT32 RtsFbkEn:1; /* enable rts rate fallback */ + UINT32 RtsThres:16; /* unit:byte */ + UINT32 AutoRtsRetryLimit:8; + } field; + UINT32 word; +} TX_RTS_CFG_STRUC; +#else +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 AutoRtsRetryLimit:8; + UINT32 RtsThres:16; + UINT32 RtsFbkEn:1; + UINT32 rsv:7; + } field; + UINT32 word; +} TX_RTS_CFG_STRUC; +#endif + + +#ifdef RT6352 +#define TX0_RF_GAIN_CORRECT 0x13A0 +#define TX1_RF_GAIN_CORRECT 0x13A4 + +#define TX0_RF_GAIN_ATTEN 0x13A8 +#define TX1_RF_GAIN_ATTEN 0x13AC + +#define TX_ALG_CFG_0 0x13B0 +#define TX_ALG_CFG_1 0x13B4 +#define TX0_BB_GAIN_ATTEN 0x13C0 +#define TX1_BB_GAIN_ATTEN 0x13C4 +#endif /* RT6352 */ + +#ifndef MT76x2 +#define TX_TXBF_CFG_0 0x138c +#define TX_TXBF_CFG_1 0x13A4 +#define TX_TXBF_CFG_2 0x13A8 +#define TX_TXBF_CFG_3 0x13AC +#else +#define TX_TXBF_CFG_0 0x1624 +#define TX_TXBF_CFG_1 0x1628 +#define TX_TXBF_CFG_2 0x162C +#define TX_TXBF_CFG_3 0x1630 +#endif +typedef union _TX_TXBF_CFG_0_STRUC { + struct { +#ifdef RT_BIG_ENDIAN + UINT32 EtxbfFbkRate:16; + UINT32 EtxbfFbkEn:1; + UINT32 EtxbfFbkSeqEn:1; + UINT32 EtxbfFbkCoef:2; + UINT32 EtxbfFbkCode:2; + UINT32 EtxbfFbkNg:2; + UINT32 CsdBypass:1; + UINT32 EtxbfForce:1; + UINT32 EtxbfEnable:1; + UINT32 AutoTxbfEn:3; + UINT32 ItxbfForce:1; + UINT32 ItxbfEn:1; +#else + UINT32 ItxbfEn:1; + UINT32 ItxbfForce:1; + UINT32 AutoTxbfEn:3; + UINT32 EtxbfEnable:1; + UINT32 EtxbfForce:1; + UINT32 CsdBypass:1; + UINT32 EtxbfFbkNg:2; + UINT32 EtxbfFbkCode:2; + UINT32 EtxbfFbkCoef:2; + UINT32 EtxbfFbkSeqEn:1; + UINT32 EtxbfFbkEn:1; + UINT32 EtxbfFbkRate:16; +#endif + } field; + UINT32 word; +} TX_TXBF_CFG_0_STRUC; + + +#define TX_TIMEOUT_CFG 0x1348 +#ifdef RT_BIG_ENDIAN +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv2:8; + UINT32 TxopTimeout:8; /*TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) */ + UINT32 RxAckTimeout:8; /* unit:slot. Used for TX precedure */ + UINT32 MpduLifeTime:4; /* expiration time = 2^(9+MPDU LIFE TIME) us */ + UINT32 rsv:4; + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC; +#else +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv:4; + UINT32 MpduLifeTime:4; + UINT32 RxAckTimeout:8; + UINT32 TxopTimeout:8; + UINT32 rsv2:8; + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#define TX_RTY_CFG 0x134c +#define TX_RTY_CFG_RTY_LIMIT_SHORT 0x1 +#define TX_RTY_CFG_RTY_LIMIT_LONG 0x2 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_RTY_CFG_STRUC { + struct { + UINT32 rsv:1; + UINT32 TxautoFBEnable:1; /* Tx retry PHY rate auto fallback enable */ + UINT32 AggRtyMode:1; /* Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + UINT32 NonAggRtyMode:1; /* Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + UINT32 LongRtyThre:12; /* Long retry threshoold */ + UINT32 LongRtyLimit:8; /*long retry limit */ + UINT32 ShortRtyLimit:8; /* short retry limit */ + } field; + UINT32 word; +} TX_RTY_CFG_STRUC; +#else +typedef union _TX_RTY_CFG_STRUC { + struct { + UINT32 ShortRtyLimit:8; + UINT32 LongRtyLimit:8; + UINT32 LongRtyThre:12; + UINT32 NonAggRtyMode:1; + UINT32 AggRtyMode:1; + UINT32 TxautoFBEnable:1; + UINT32 rsv:1; + } field; + UINT32 word; +} TX_RTY_CFG_STRUC; +#endif + + +#define TX_LINK_CFG 0x1350 +#ifdef RT_BIG_ENDIAN +typedef union _TX_LINK_CFG_STRUC { + struct { + UINT32 RemotMFS:8; /*remote MCS feedback sequence number */ + UINT32 RemotMFB:8; /* remote MCS feedback */ + UINT32 rsv:3; /* */ + UINT32 TxCFAckEn:1; /* Piggyback CF-ACK enable */ + UINT32 TxRDGEn:1; /* RDG TX enable */ + UINT32 TxMRQEn:1; /* MCS request TX enable */ + UINT32 RemoteUMFSEnable:1; /* remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) */ + UINT32 MFBEnable:1; /* TX apply remote MFB 1:enable */ + UINT32 RemoteMFBLifeTime:8; /*remote MFB life time. unit : 32us */ + } field; + UINT32 word; +} TX_LINK_CFG_STRUC; +#else +typedef union _TX_LINK_CFG_STRUC { + struct { + UINT32 RemoteMFBLifeTime:8; + UINT32 MFBEnable:1; + UINT32 RemoteUMFSEnable:1; + UINT32 TxMRQEn:1; + UINT32 TxRDGEn:1; + UINT32 TxCFAckEn:1; + UINT32 rsv:3; + UINT32 RemotMFB:8; + UINT32 RemotMFS:8; + } field; + UINT32 word; +} TX_LINK_CFG_STRUC; +#endif + + +#define HT_FBK_CFG0 0x1354 +#ifdef RT_BIG_ENDIAN +typedef union _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS7FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS0FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC; +#else +typedef union _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS0FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS7FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC; +#endif + + +#define HT_FBK_CFG1 0x1358 +#ifdef RT_BIG_ENDIAN +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS15FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS8FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC; +#else +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS8FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS15FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC; +#endif + + +#define LG_FBK_CFG0 0x135c +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS7FBK:4; + UINT32 OFDMMCS6FBK:4; + UINT32 OFDMMCS5FBK:4; + UINT32 OFDMMCS4FBK:4; + UINT32 OFDMMCS3FBK:4; + UINT32 OFDMMCS2FBK:4; + UINT32 OFDMMCS1FBK:4; + UINT32 OFDMMCS0FBK:4; + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC; +#else +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS0FBK:4; + UINT32 OFDMMCS1FBK:4; + UINT32 OFDMMCS2FBK:4; + UINT32 OFDMMCS3FBK:4; + UINT32 OFDMMCS4FBK:4; + UINT32 OFDMMCS5FBK:4; + UINT32 OFDMMCS6FBK:4; + UINT32 OFDMMCS7FBK:4; + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC; +#endif + + +#define LG_FBK_CFG1 0x1360 +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 rsv:16; + UINT32 CCKMCS3FBK:4; + UINT32 CCKMCS2FBK:4; + UINT32 CCKMCS1FBK:4; + UINT32 CCKMCS0FBK:4; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC; +#else +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 CCKMCS0FBK:4; + UINT32 CCKMCS1FBK:4; + UINT32 CCKMCS2FBK:4; + UINT32 CCKMCS3FBK:4; + UINT32 rsv:16; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC; +#endif + + +/*======================================================= */ +/* Protection Paramater */ +/*======================================================= */ +#define ASIC_SHORTNAV 1 +#define ASIC_LONGNAV 2 +#define ASIC_RTS 1 +#define ASIC_CTS 2 + +#define CCK_PROT_CFG 0x1364 /* CCK Protection */ +#define OFDM_PROT_CFG 0x1368 /* OFDM Protection */ +#define MM20_PROT_CFG 0x136C /* MM20 Protection */ +#define MM40_PROT_CFG 0x1370 /* MM40 Protection */ +#define GF20_PROT_CFG 0x1374 /* GF20 Protection */ +#define GF40_PROT_CFG 0x1378 /* GR40 Protection */ +#ifdef RT_BIG_ENDIAN +typedef union _PROT_CFG_STRUC { + struct { +#ifdef DOT11_VHT_AC + UINT32 ProtectTxop:3; /* TXOP allowance */ + UINT32 DynCbw:1; /* RTS use dynamic channel bandwidth when TX signaling mode is turned on */ + UINT32 RtsTaSignal:1; /* RTS TA signaling mode */ +#else + UINT32 rsv:5; +#endif + UINT32 RTSThEn:1; /*RTS threshold enable on CCK TX */ + UINT32 TxopAllowGF40:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowGF20:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowMM40:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowMM20:1; /*CCK TXOP allowance. 0:disallow. */ + UINT32 TxopAllowOfdm:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowCck:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 ProtectNav:2; /*TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv */ + UINT32 ProtectCtrl:2; /*Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv */ + UINT32 ProtectRate:16; /*Protection control frame rate for CCK TX(RTS/CTS/CFEnd). */ + } field; + UINT32 word; +} PROT_CFG_STRUC; +#else +typedef union _PROT_CFG_STRUC { + struct { + UINT32 ProtectRate:16; + UINT32 ProtectCtrl:2; + UINT32 ProtectNav:2; + UINT32 TxopAllowCck:1; + UINT32 TxopAllowOfdm:1; + UINT32 TxopAllowMM20:1; + UINT32 TxopAllowMM40:1; + UINT32 TxopAllowGF20:1; + UINT32 TxopAllowGF40:1; + UINT32 RTSThEn:1; +#ifdef DOT11_VHT_AC + UINT32 RtsTaSignal:1; /* RTS TA signaling mode */ + UINT32 DynCbw:1; /* RTS use dynamic channel bandwidth when TX signaling mode is turned on */ + UINT32 ProtectTxop:3; /* TXOP allowance */ +#else + UINT32 rsv:5; +#endif /* !DOT11_VHT_AC */ + } field; + UINT32 word; +} PROT_CFG_STRUC; +#endif + +#define EXP_CTS_TIME 0x137C +#define EXP_ACK_TIME 0x1380 + + +#define HT_FBK_TO_LEGACY 0x1384 + +#define TX_FBK_LIMIT 0x1398 + +#ifdef DOT11N_SS3_SUPPORT +#define TX_FBK_CFG_3S_0 0x13c4 +#ifdef RT_BIG_ENDIAN +typedef union _TX_FBK_CFG_3S_0_STRUC { + struct { + UINT32 rsv0:3; + UINT32 HTMCS19FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS18FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS17FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS16FBK:5; + } field; + UINT32 word; +} TX_FBK_CFG_3S_0_STRUC; +#else +typedef union _TX_FBK_CFG_3S_0_STRUC { + struct { + UINT32 HTMCS16FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS17FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS18FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS19FBK:5; + UINT32 rsv0:4; + } field; + UINT32 word; +} TX_FBK_CFG_3S_0_STRUC; +#endif + +#define TX_FBK_CFG_3S_1 0x13c8 +#ifdef RT_BIG_ENDIAN +typedef union _TX_FBK_CFG_3S_1_STRUC { + struct { + UINT32 rsv0:3; + UINT32 HTMCS23FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS22FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS21FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS20FBK:5; + } field; + UINT32 word; +} TX_FBK_CFG_3S_1_STRUC; +#else +typedef union _TX_FBK_CFG_3S_1_STRUC { + struct { + UINT32 HTMCS20FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS21FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS22FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS23FBK:5; + UINT32 rsv0:3; + } field; + UINT32 word; +} TX_FBK_CFG_3S_1_STRUC; +#endif +#endif /* DOT11N_SS3_SUPPORT */ + +#define TX_AC_RTY_LIMIT 0x13cc +#define TX_AC_FBK_SPEED 0x13d0 + + + +/* 4.4 MAC RX configuration registers (offset:0x1400) */ + +/* RX_FILTR_CFG: /RX configuration register */ +#define RX_FILTR_CFG 0x1400 +#ifdef RT_BIG_ENDIAN +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 rsv:15; + UINT32 DropRsvCntlType:1; + UINT32 DropBAR:1; + UINT32 DropBA:1; + UINT32 DropPsPoll:1; /* Drop Ps-Poll */ + UINT32 DropRts:1; /* Drop Ps-Poll */ + UINT32 DropCts:1; /* Drop Ps-Poll */ + UINT32 DropAck:1; /* Drop Ps-Poll */ + UINT32 DropCFEnd:1; /* Drop Ps-Poll */ + UINT32 DropCFEndAck:1; /* Drop Ps-Poll */ + UINT32 DropDuplicate:1; /* Drop duplicate frame */ + UINT32 DropBcast:1; /* Drop broadcast frames */ + UINT32 DropMcast:1; /* Drop multicast frames */ + UINT32 DropVerErr:1; /* Drop version error frame */ + UINT32 DropNotMyBSSID:1; /* Drop fram ToDs bit is true */ + UINT32 DropNotToMe:1; /* Drop not to me unicast frame */ + UINT32 DropPhyErr:1; /* Drop physical error */ + UINT32 DropCRCErr:1; /* Drop CRC error */ + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC; +#else +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 DropCRCErr:1; + UINT32 DropPhyErr:1; + UINT32 DropNotToMe:1; + UINT32 DropNotMyBSSID:1; + UINT32 DropVerErr:1; + UINT32 DropMcast:1; + UINT32 DropBcast:1; + UINT32 DropDuplicate:1; + UINT32 DropCFEndAck:1; + UINT32 DropCFEnd:1; + UINT32 DropAck:1; + UINT32 DropCts:1; + UINT32 DropRts:1; + UINT32 DropPsPoll:1; + UINT32 DropBA:1; + UINT32 DropBAR:1; + UINT32 DropRsvCntlType:1; + UINT32 rsv:15; + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC; +#endif + + +/* AUTO_RSP_CFG: Auto-Responder */ +#define AUTO_RSP_CFG 0x1404 +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 :24; + UINT32 AckCtsPsmBit:1; /* Power bit value in conrtrol frame */ + UINT32 DualCTSEn:1; /* Power bit value in conrtrol frame */ + UINT32 rsv:1; /* Power bit value in conrtrol frame */ + UINT32 AutoResponderPreamble:1; /* 0:long, 1:short preamble */ + UINT32 CTS40MRef:1; /* Response CTS 40MHz duplicate mode */ + UINT32 CTS40MMode:1; /* Response CTS 40MHz duplicate mode */ + UINT32 BACAckPolicyEnable:1; /* 0:long, 1:short preamble */ + UINT32 AutoResponderEnable:1; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC; +#else +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 AutoResponderEnable:1; + UINT32 BACAckPolicyEnable:1; + UINT32 CTS40MMode:1; + UINT32 CTS40MRef:1; + UINT32 AutoResponderPreamble:1; + UINT32 rsv:1; + UINT32 DualCTSEn:1; + UINT32 AckCtsPsmBit:1; + UINT32 :24; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC; +#endif + + +#define LEGACY_BASIC_RATE 0x1408 +#define HT_BASIC_RATE 0x140c +#define HT_CTRL_CFG 0x1410 +#define SIFS_COST_CFG 0x1414 +#define RX_PARSER_CFG 0x1418 /*Set NAV for all received frames */ + +#define EXT_CCA_CFG 0x141c + +#ifdef MAC_APCLI_SUPPORT +#define APCLI_BSSID_IDX 8 +#define MAC_APCLI_BSSID_DW0 0x1090 +#define MAC_APCLI_BSSID_DW1 0x1094 +#endif /* MAC_APCLI_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +#define MAC_ADDR_EXT_EN 0x147C +#define MAC_ADDR_EXT0_31_0 0x1480 +#define MAC_ADDR_EXT0_47_32 0x1484 +#define MAX_EXT_MAC_ADDR_SIZE 16 + +#define UNKOWN_APCLI_IDX 0xFF +#define CLIENT_APCLI 0x00 +#define CLIENT_STA 0x01 +#define CLIENT_ETH 0x02 +#define EXTERNDER_CLI 0x08 +#endif /* MAC_REPEATER_SUPPORT */ + + +/* 4.5 MAC Security configuration (offset:0x1500) */ +#define TX_SEC_CNT0 0x1500 +#define RX_SEC_CNT0 0x1504 +#define CCMP_FC_MUTE 0x1508 +#define PN_PAD_MODE 0x150C +#define PN_PAD_MODE_OFFSET 0x1 + +/* 4.6 HCCA/PSMP (offset:0x1600) */ +#define TXOP_HLDR_ADDR0 0x1600 +#define TXOP_HLDR_ADDR1 0x1604 +#define TXOP_HLDR_ET 0x1608 +#define QOS_CFPOLL_RA_DW0 0x160c +#define QOS_CFPOLL_A1_DW1 0x1610 +#define QOS_CFPOLL_QC 0x1614 + + +/* 4.7 MAC Statistis registers (offset:0x1700) */ +/* RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count */ +#define RX_STA_CNT0 0x1700 +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT0_STRUC { + struct { + UINT16 PhyErr; + UINT16 CrcErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC; +#else +typedef union _RX_STA_CNT0_STRUC { + struct { + UINT16 CrcErr; + UINT16 PhyErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC; +#endif + + +/* RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count */ +#define RX_STA_CNT1 0x1704 +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT1_STRUC { + struct { + UINT16 PlcpErr; + UINT16 FalseCca; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC; +#else +typedef union _RX_STA_CNT1_STRUC { + struct { + UINT16 FalseCca; + UINT16 PlcpErr; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC; +#endif + + +/* RX_STA_CNT2_STRUC: */ +#define RX_STA_CNT2 0x1708 +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT2_STRUC { + struct { + UINT16 RxFifoOverflowCount; + UINT16 RxDupliCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC; +#else +typedef union _RX_STA_CNT2_STRUC { + struct { + UINT16 RxDupliCount; + UINT16 RxFifoOverflowCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC; +#endif + + +/* STA_CSR3: TX Beacon count */ +#define TX_STA_CNT0 0x170C +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT0_STRUC { + struct { + UINT16 TxBeaconCount; + UINT16 TxFailCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC; +#else +typedef union _TX_STA_CNT0_STRUC { + struct { + UINT16 TxFailCount; + UINT16 TxBeaconCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC; +#endif + + + +/* TX_STA_CNT1: TX tx count */ +#define TX_STA_CNT1 0x1710 +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT1_STRUC { + struct { + UINT16 TxRetransmit; + UINT16 TxSuccess; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC; +#else +typedef union _TX_STA_CNT1_STRUC { + struct { + UINT16 TxSuccess; + UINT16 TxRetransmit; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC; +#endif + + +/* TX_STA_CNT2: TX tx count */ +#define TX_STA_CNT2 0x1714 +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT2_STRUC { + struct { + UINT16 TxUnderFlowCount; + UINT16 TxZeroLenCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC; +#else +typedef union _TX_STA_CNT2_STRUC { + struct { + UINT16 TxZeroLenCount; + UINT16 TxUnderFlowCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC; +#endif + + +/* TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register */ +#define TX_STA_FIFO 0x1718 + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_FIFO_STRUC { + struct { + UINT32 PhyMode:3; + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 SuccessRate:11; /*include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. */ + UINT32 wcid:8; /*wireless client index */ + UINT32 TxAckRequired:1; /* ack required */ + UINT32 TxAggre:1; /* Tx is aggregated */ + UINT32 TxSuccess:1; /* Tx success. whether success or not */ + UINT32 PidType:4; + UINT32 bValid:1; /* 1:This register contains a valid TX result */ + } field; + UINT32 word; +} TX_STA_FIFO_STRUC; +#else +typedef union _TX_STA_FIFO_STRUC { + struct { + UINT32 bValid:1; + UINT32 PidType:4; + UINT32 TxSuccess:1; + UINT32 TxAggre:1; + UINT32 TxAckRequired:1; + UINT32 wcid:8; + UINT32 SuccessRate:11; + UINT32 eTxBF:1; + UINT32 iTxBF:1; + UINT32 PhyMode:3; + } field; + UINT32 word; +} TX_STA_FIFO_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +/* + Debug counters +*/ +#define TX_AGG_CNT 0x171c +#ifdef RT_BIG_ENDIAN +typedef union _TX_NAG_AGG_CNT_STRUC { + struct { + UINT16 AggTxCount; + UINT16 NonAggTxCount; + } field; + UINT32 word; +} TX_NAG_AGG_CNT_STRUC; +#else +typedef union _TX_NAG_AGG_CNT_STRUC { + struct { + UINT16 NonAggTxCount; + UINT16 AggTxCount; + } field; + UINT32 word; +} TX_NAG_AGG_CNT_STRUC; +#endif + + +#define TX_AGG_CNT0 0x1720 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT0_STRUC { + struct { + UINT16 AggSize2Count; + UINT16 AggSize1Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC; +#else +typedef union _TX_AGG_CNT0_STRUC { + struct { + UINT16 AggSize1Count; + UINT16 AggSize2Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC; +#endif + + +#define TX_AGG_CNT1 0x1724 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT1_STRUC { + struct { + UINT16 AggSize4Count; + UINT16 AggSize3Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC; +#else +typedef union _TX_AGG_CNT1_STRUC { + struct { + UINT16 AggSize3Count; + UINT16 AggSize4Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC; +#endif + + +#define TX_AGG_CNT2 0x1728 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT2_STRUC { + struct { + UINT16 AggSize6Count; + UINT16 AggSize5Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC; +#else +typedef union _TX_AGG_CNT2_STRUC { + struct { + UINT16 AggSize5Count; + UINT16 AggSize6Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC; +#endif + + +#define TX_AGG_CNT3 0x172c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT3_STRUC { + struct { + UINT16 AggSize8Count; + UINT16 AggSize7Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC; +#else +typedef union _TX_AGG_CNT3_STRUC { + struct { + UINT16 AggSize7Count; + UINT16 AggSize8Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC; +#endif + + +#define TX_AGG_CNT4 0x1730 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT4_STRUC { + struct { + UINT16 AggSize10Count; + UINT16 AggSize9Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC; +#else +typedef union _TX_AGG_CNT4_STRUC { + struct { + UINT16 AggSize9Count; + UINT16 AggSize10Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC; +#endif + + +#define TX_AGG_CNT5 0x1734 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT5_STRUC { + struct { + UINT16 AggSize12Count; + UINT16 AggSize11Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC; +#else +typedef union _TX_AGG_CNT5_STRUC { + struct { + UINT16 AggSize11Count; + UINT16 AggSize12Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC; +#endif + + +#define TX_AGG_CNT6 0x1738 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT6_STRUC { + struct { + UINT16 AggSize14Count; + UINT16 AggSize13Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC; +#else +typedef union _TX_AGG_CNT6_STRUC { + struct { + UINT16 AggSize13Count; + UINT16 AggSize14Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC; +#endif + + +#define TX_AGG_CNT7 0x173c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT7_STRUC { + struct { + UINT16 AggSize16Count; + UINT16 AggSize15Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC; +#else +typedef union _TX_AGG_CNT7_STRUC { + struct { + UINT16 AggSize15Count; + UINT16 AggSize16Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC; +#endif + + +#define TX_AGG_CNT8 0x174c /* AGG_SIZE = 17,18 */ +#define TX_AGG_CNT9 0x1750 /* AGG_SIZE = 19,20 */ +#define TX_AGG_CNT10 0x1754 /* AGG_SIZE = 21,22 */ +#define TX_AGG_CNT11 0x1758 /* AGG_SIZE = 23,24 */ +#define TX_AGG_CNT12 0x175c /* AGG_SIZE = 25,26 */ +#define TX_AGG_CNT13 0x1760 /* AGG_SIZE = 27,28 */ +#define TX_AGG_CNT14 0x1764 /* AGG_SIZE = 29,30 */ +#define TX_AGG_CNT15 0x1768 /* AGG_SIZE = 31,32 */ +#define TX_AGG_CNT16 0x179C /* AGG_SIZE = 33, 34 */ +#define TX_AGG_CNT17 0x17a0 /* AGG_SIZE = 35, 36 */ +#define TX_AGG_CNT18 0x17a4 /* AGG_SIZE = 37, 38 */ +#define TX_AGG_CNT19 0x17a8 /* AGG_SIZE = 39, 40 */ +#define TX_AGG_CNT20 0x17ac /* AGG_SIZE = 41, 42 */ +#define TX_AGG_CNT21 0x17b0 /* AGG_SIZE = 43, 44 */ +#define TX_AGG_CNT22 0x17b4 /* AGG_SIZE = 45, 46 */ +#define TX_AGG_CNT23 0x17b8 /* AGG_SIZE = 47, 48 */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT_STRUC { + struct { + UINT16 AggCnt_y; /* the count of aggregation size = x + 1 */ + UINT16 AggCnt_x; /* the count of aggregation size = x */ + } field; + UINT32 word; +} TX_AGG_CNT_STRUC; +#else +typedef union _TX_AGG_CNT_STRUC { + struct { + UINT16 AggCnt_x; + UINT16 AggCnt_y; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC; +#endif + +typedef union _TX_AGG_CNTN_STRUC { + struct { +#ifdef RT_BIG_ENDIAN + UINT16 AggSizeHighCount; + UINT16 AggSizeLowCount; +#else + UINT16 AggSizeLowCount; + UINT16 AggSizeHighCount; +#endif + } field; + UINT32 word; +} TX_AGG_CNTN_STRUC; + + +#define MPDU_DENSITY_CNT 0x1740 +#ifdef RT_BIG_ENDIAN +typedef union _MPDU_DEN_CNT_STRUC { + struct { + UINT16 RXZeroDelCount; /*RX zero length delimiter count */ + UINT16 TXZeroDelCount; /*TX zero length delimiter count */ + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC; +#else +typedef union _MPDU_DEN_CNT_STRUC { + struct { + UINT16 TXZeroDelCount; + UINT16 RXZeroDelCount; + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC; +#endif + +#define RTS_TX_CNT 0x1744 +#ifdef RT_BIG_ENDIAN +typedef union _RTS_TX_CNT_STRUC { + struct { + UINT16 RtsTxFailCount; /* RTS TX fail count */ + UINT16 RtsTxOkCount; /* RTS TX OK count */ + } field; + UINT32 word; +} RTS_TX_CNT_STRUC; +#else +typedef union _RTS_TX_CNT_STRUC { + struct { + UINT16 RtsTxOkCount; + UINT16 RtsTxFailCount; + } field; + UINT32 word; +} RTS_TX_CNT_STRUC; +#endif + + +#ifdef FIFO_EXT_SUPPORT +/* TX_STA_FIFO_EXT_STRUC: TX retry cnt for specific frame */ +#define TX_STA_FIFO_EXT 0x1798 /* Only work after RT53xx */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_FIFO_EXT_STRUC { + struct { + UINT32 Reserve:16; + UINT32 PidType:8; + UINT32 txRtyCnt:8; /* frame Tx retry cnt */ + } field; + UINT32 word; +} TX_STA_FIFO_EXT_STRUC; +#else +typedef union _TX_STA_FIFO_EXT_STRUC { + struct { + UINT32 txRtyCnt:8; + UINT32 PidType:8; + UINT32 Reserve:16; + } field; + UINT32 word; +} TX_STA_FIFO_EXT_STRUC; +#endif + + + +#define WCID_TX_CNT_0 0x176c +#define WCID_TX_CNT_1 0x1770 +#define WCID_TX_CNT_2 0x1774 +#define WCID_TX_CNT_3 0x1778 +#define WCID_TX_CNT_4 0x177c +#define WCID_TX_CNT_5 0x1780 +#define WCID_TX_CNT_6 0x1784 +#define WCID_TX_CNT_7 0x1788 +#ifdef RT_BIG_ENDIAN +typedef union _WCID_TX_CNT_STRUC { + struct { + UINT32 reTryCnt:16; + UINT32 succCnt:16; + } field; + UINT32 word; +} WCID_TX_CNT_STRUC; +#else +typedef union _WCID_TX_CNT_STRUC { + struct { + UINT32 succCnt:16; + UINT32 reTryCnt:16; + } field; + UINT32 word; +} WCID_TX_CNT_STRUC; +#endif + + +#define WCID_MAPPING_0 0x178c +#define WCID_MAPPING_1 0x1790 +#ifdef RT_BIG_ENDIAN +typedef union _WCID_MAPPING_STRUC { + struct { + UINT32 wcid3:8; + UINT32 wcid2:8; + UINT32 wcid1:8; + UINT32 wcid0:8; + } field; + UINT32 word; +} WCID_MAPPING_STRUC; +#else +typedef union _WCID_MAPPING_STRUC { + struct { + UINT32 wcid0:8; + UINT32 wcid1:8; + UINT32 wcid2:8; + UINT32 wcid3:8; + } field; + UINT32 word; +} WCID_MAPPINGT_STRUC; +#endif +#endif /* FIFO_EXT_SUPPORT */ + +#define TX_REPORT_CNT 0x1794 + + +/* Security key table memory, base address = 0x1000 */ +#define MAC_WCID_BASE 0x1800 /*8-bytes(use only 6-bytes) * 256 entry = */ +#define HW_WCID_ENTRY_SIZE 8 + +#ifdef MCS_LUT_SUPPORT +#define MAC_MCS_LUT_BASE 0x1c00 +#endif /* MCS_LUT_SUPPORT */ + +#ifdef RT_BIG_ENDIAN +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 Bss1Key3CipherAlg:4; + UINT32 Bss1Key2CipherAlg:4; + UINT32 Bss1Key1CipherAlg:4; + UINT32 Bss1Key0CipherAlg:4; + UINT32 Bss0Key3CipherAlg:4; + UINT32 Bss0Key2CipherAlg:4; + UINT32 Bss0Key1CipherAlg:4; + UINT32 Bss0Key0CipherAlg:4; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC; +#else +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 Bss0Key0CipherAlg:4; + UINT32 Bss0Key1CipherAlg:4; + UINT32 Bss0Key2CipherAlg:4; + UINT32 Bss0Key3CipherAlg:4; + UINT32 Bss1Key0CipherAlg:4; + UINT32 Bss1Key1CipherAlg:4; + UINT32 Bss1Key2CipherAlg:4; + UINT32 Bss1Key3CipherAlg:4; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC; +#endif + + +/* 64-entry for pairwise key table, 8-byte per entry */ +typedef struct _HW_WCID_ENTRY { + UINT8 Address[6]; + UINT8 Rsv[2]; +} HW_WCID_ENTRY; + + +/* ================================================================================= */ +/* WCID format */ +/* ================================================================================= */ +/*7.1 WCID ENTRY format : 8bytes */ +typedef struct _WCID_ENTRY_STRUC { + UINT8 RXBABitmap7; /* bit0 for TID8, bit7 for TID 15 */ + UINT8 RXBABitmap0; /* bit0 for TID0, bit7 for TID 7 */ + UINT8 MAC[6]; /* 0 for shared key table. 1 for pairwise key table */ +} WCID_ENTRY_STRUC; + + +/*8.1.1 SECURITY KEY format : 8DW */ +/* 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table */ +typedef struct _HW_KEY_ENTRY { + UINT8 Key[16]; + UINT8 TxMic[8]; + UINT8 RxMic[8]; +} HW_KEY_ENTRY; + + +/*8.1.2 IV/EIV format : 2DW */ + +/* RX attribute entry format : 1DW */ +#ifdef RT_BIG_ENDIAN +typedef union _WCID_ATTRIBUTE_STRUC { + struct { + UINT32 WAPIKeyIdx:8; + UINT32 WAPI_rsv:8; + UINT32 WAPI_MCBC:1; + UINT32 rsv:3; + UINT32 BSSIdxExt:1; + UINT32 PairKeyModeExt:1; + UINT32 RXWIUDF:3; + UINT32 BSSIdx:3; /*multipleBSS index for the WCID */ + UINT32 PairKeyMode:3; + UINT32 KeyTab:1; /* 0 for shared key table. 1 for pairwise key table */ + } field; + UINT32 word; +} WCID_ATTRIBUTE_STRUC; +#else +typedef union _WCID_ATTRIBUTE_STRUC { + struct { + UINT32 KeyTab:1; /* 0 for shared key table. 1 for pairwise key table */ + UINT32 PairKeyMode:3; + UINT32 BSSIdx:3; /*multipleBSS index for the WCID */ + UINT32 RXWIUDF:3; + UINT32 PairKeyModeExt:1; + UINT32 BSSIdxExt:1; + UINT32 rsv:3; + UINT32 WAPI_MCBC:1; + UINT32 WAPI_rsv:8; + UINT32 WAPIKeyIdx:8; + } field; + UINT32 word; +} WCID_ATTRIBUTE_STRUC; +#endif + + +/* ================================================================================= */ +/* HOST-MCU communication data structure */ +/* ================================================================================= */ + +/* H2M_MAILBOX_CSR: Host-to-MCU Mailbox */ +#ifdef RT_BIG_ENDIAN +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 Owner:8; + UINT32 CmdToken:8; /* 0xff tells MCU not to report CmdDoneInt after excuting the command */ + UINT32 HighByte:8; + UINT32 LowByte:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC; +#else +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 LowByte:8; + UINT32 HighByte:8; + UINT32 CmdToken:8; + UINT32 Owner:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC; +#endif + + +/* M2H_CMD_DONE_CSR: MCU-to-Host command complete indication */ +#ifdef RT_BIG_ENDIAN +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken3; + UINT32 CmdToken2; + UINT32 CmdToken1; + UINT32 CmdToken0; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC; +#else +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken0; + UINT32 CmdToken1; + UINT32 CmdToken2; + UINT32 CmdToken3; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC; +#endif + + +/* HOST_CMD_CSR: For HOST to interrupt embedded processor */ +#ifdef RT_BIG_ENDIAN +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 Rsv:24; + UINT32 HostCommand:8; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC; +#else +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 HostCommand:8; + UINT32 Rsv:24; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC; +#endif + + +// TODO: shiang-6590, Need to check following definitions are useful or not!!! +/* AIFSN_CSR: AIFSN for each EDCA AC */ + + +/* E2PROM_CSR: EEPROM control register */ +#ifdef RT_BIG_ENDIAN +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Rsvd:25; + UINT32 LoadStatus:1; /* 1:loading, 0:done */ + UINT32 Type:1; /* 1: 93C46, 0:93C66 */ + UINT32 EepromDO:1; + UINT32 EepromDI:1; + UINT32 EepromCS:1; + UINT32 EepromSK:1; + UINT32 Reload:1; /* Reload EEPROM content, write one to reload, self-cleared. */ + } field; + UINT32 word; +} E2PROM_CSR_STRUC; +#else +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Reload:1; + UINT32 EepromSK:1; + UINT32 EepromCS:1; + UINT32 EepromDI:1; + UINT32 EepromDO:1; + UINT32 Type:1; + UINT32 LoadStatus:1; + UINT32 Rsvd:25; + } field; + UINT32 word; +} E2PROM_CSR_STRUC; +#endif + + +/* QOS_CSR0: TXOP holder address0 register */ +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR0_STRUC { + struct { + UINT8 Byte3; /* MAC address byte 3 */ + UINT8 Byte2; /* MAC address byte 2 */ + UINT8 Byte1; /* MAC address byte 1 */ + UINT8 Byte0; /* MAC address byte 0 */ + } field; + UINT32 word; +} QOS_CSR0_STRUC; +#else +typedef union _QOS_CSR0_STRUC { + struct { + UINT8 Byte0; + UINT8 Byte1; + UINT8 Byte2; + UINT8 Byte3; + } field; + UINT32 word; +} QOS_CSR0_STRUC; +#endif + + +/* QOS_CSR1: TXOP holder address1 register */ +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR1_STRUC { + struct { + UINT8 Rsvd1; + UINT8 Rsvd0; + UINT8 Byte5; /* MAC address byte 5 */ + UINT8 Byte4; /* MAC address byte 4 */ + } field; + UINT32 word; +} QOS_CSR1_STRUC; +#else +typedef union _QOS_CSR1_STRUC { + struct { + UINT8 Byte4; /* MAC address byte 4 */ + UINT8 Byte5; /* MAC address byte 5 */ + UINT8 Rsvd0; + UINT8 Rsvd1; + } field; + UINT32 word; +} QOS_CSR1_STRUC; +#endif + +// TODO: shiang-6590, check upper definitions are useful or not! + + + +/* Other on-chip shared memory space, base = 0x2000 */ + +/* CIS space - base address = 0x2000 */ +#define HW_CIS_BASE 0x2000 + +/* Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. */ +#define HW_CS_CTS_BASE 0x7700 +/* DFS CTS frame base address. It's where mac stores CTS frame for DFS. */ +#define HW_DFS_CTS_BASE 0x7780 +#define HW_CTS_FRAME_SIZE 0x80 + +/* 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes */ +/* to save debugging settings */ +#define HW_DEBUG_SETTING_BASE 0x77f0 /* 0x77f0~0x77ff total 16 bytes */ +#define HW_DEBUG_SETTING_BASE2 0x7770 /* 0x77f0~0x77ff total 16 bytes */ + + +/* + On-chip BEACON frame space - + 1. HW_BEACON_OFFSET/64B must be 0; + 2. BCN_OFFSETx(0~) must also be changed in MACRegTable(common/rtmp_init.c) + */ +#define HW_BEACON_OFFSET 0x0200 + +/* NullFrame buffer */ +#define HW_NULL_BASE 0x7700 +#define HW_NULL2_BASE 0x7780 + + + +/* In order to support maximum 8 MBSS and its maximum length is 512 for each beacon + Three section discontinue memory segments will be used. + 1. The original region for BCN 0~3 + 2. Extract memory from FCE table for BCN 4~5 + 3. Extract memory from Pair-wise key table for BCN 6~7 + It occupied those memory of wcid 238~253 for BCN 6 + and wcid 222~237 for BCN 7 */ +/*#define HW_BEACON_MAX_COUNT 8 */ +#define HW_BEACON_MAX_SIZE(__pAd) ((__pAd)->chipCap.BcnMaxHwSize) +#define HW_BEACON_BASE0(__pAd) ((__pAd)->chipCap.BcnBase[0]) +/*#define HW_BEACON_BASE1 0x7A00 */ +/*#define HW_BEACON_BASE2 0x7C00 */ +/*#define HW_BEACON_BASE3 0x7E00 */ +/*#define HW_BEACON_BASE4 0x7200 */ +/*#define HW_BEACON_BASE5 0x7400 */ +/*#define HW_BEACON_BASE6 0x5DC0 */ +/*#define HW_BEACON_BASE7 0x5BC0 */ + + +/* Higher 8KB shared memory */ +#define HW_BEACON_BASE0_REDIRECTION 0x4000 +#define HW_BEACON_BASE1_REDIRECTION 0x4200 +#define HW_BEACON_BASE2_REDIRECTION 0x4400 +#define HW_BEACON_BASE3_REDIRECTION 0x4600 +#define HW_BEACON_BASE4_REDIRECTION 0x4800 +#define HW_BEACON_BASE5_REDIRECTION 0x4A00 +#define HW_BEACON_BASE6_REDIRECTION 0x4C00 +#define HW_BEACON_BASE7_REDIRECTION 0x4E00 + + +/* HOST-MCU shared memory - base address = 0x2100 */ +#define HOST_CMD_CSR 0x404 +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_STATUS 0x701c +#define H2M_INT_SRC 0x7024 +#define H2M_BBP_AGENT 0x7028 +#define M2H_CMD_DONE_CSR 0x000c +#define MCU_TXOP_ARRAY_BASE 0x000c /* TODO: to be provided by Albert */ +#define MCU_TXOP_ENTRY_SIZE 32 /* TODO: to be provided by Albert */ +#define MAX_NUM_OF_TXOP_ENTRY 16 /* TODO: must be same with 8051 firmware */ +#define MCU_MBOX_VERSION 0x01 /* TODO: to be confirmed by Albert */ +#define MCU_MBOX_VERSION_OFFSET 5 /* TODO: to be provided by Albert */ + + +/* Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, */ +/* DMA RING DESCRIPTOR */ +#define E2PROM_CSR 0x0004 +#define IO_CNTL_CSR 0x77d0 + + + +/* ================================================================ */ +/* Tx / Rx / Mgmt ring descriptor definition */ +/* ================================================================ */ + +/* the following PID values are used to mark outgoing frame type in TXD->PID so that */ +/* proper TX statistics can be collected based on these categories */ +/* b3-2 of PID field - */ +#define PID_MGMT 0x05 +#define PID_BEACON 0x0c +#define PID_DATA_NORMALUCAST 0x02 +#define PID_DATA_AMPDU 0x04 +#define PID_DATA_NO_ACK 0x08 +#define PID_DATA_NOT_NORM_ACK 0x03 +/* value domain of pTxD->HostQId (4-bit: 0~15) */ +#define QID_AC_BK 1 /* meet ACI definition in 802.11e */ +#define QID_AC_BE 0 /* meet ACI definition in 802.11e */ +#define QID_AC_VI 2 +#define QID_AC_VO 3 +#define QID_HCCA 4 +#define NUM_OF_TX_RING 5 + +#define NUM_OF_RX_RING 1 +#ifdef CONFIG_ANDES_SUPPORT +#undef NUM_OF_RX_RING +#define NUM_OF_RX_RING 2 +#endif /* CONFIG_ANDES_SUPPORT */ + +#define QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 +#ifdef CONFIG_ANDES_SUPPORT +#define QID_CTRL 16 +#endif /* CONFIG_ANDES_SUPPORT */ + + + +#ifdef SPECIFIC_BCN_BUF_SUPPORT +#define LOWER_SHRMEM 0 +#define HIGHER_SHRMEM 1 + +/* + Shared memory access selection. + 0: address 0x4000 ~ 0x7FFF mapping to lower 16kB of shared memory + 1: address 0x4000 ~ 0x5FFF mapping to higher 8kB of shared memory + + When you swtich shr_mem to high, you can not access MCU, just like + H2M_MAILBOX_CSR 0x7010 + H2M_MAILBOX_CID 0x7014 + H2M_MAILBOX_STATUS 0x701c + H2M_INT_SRC 0x7024 + H2M_BBP_AGENT 0x7028 +*/ + +#ifdef RTMP_MAC_PCI +#define RTMP_MAC_SHR_MSEL_PROTECT_LOCK(__pAd, __IrqFlags) \ + if (__pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + RTMP_INT_LOCK(&__pAd->ShrMemLock, __IrqFlags); + +#define RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(__pAd, __IrqFlags) \ + if (__pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + RTMP_INT_UNLOCK(&__pAd->ShrMemLock, __IrqFlags); + +/* + Disable irq to make sure the shared memory status(Mac Reg : 0x0400, bit-19) + doesn't been changed. + Becasue the PRE-TBTT interrupt would change this status. */ +#define RTMP_MAC_SHR_MSEL_LOCK(_pAd, _shr_msel, _irqFlag) \ + do{ \ + if (_pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + {\ + UINT32 _val, _bit = (1 << 19); \ + \ + RTMP_INT_LOCK(&_pAd->ShrMemLock, _irqFlag); \ + _pAd->ShrMSel = _shr_msel; \ + RTMP_IO_READ32(_pAd, PBF_SYS_CTRL, &_val);\ + _val = (_shr_msel == HIGHER_SHRMEM) ? (_val | _bit) : (_val & (~_bit));\ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, _val);\ + }\ + } while(0) + + +#define RTMP_MAC_SHR_MSEL_UNLOCK(_pAd, _shr_msel, _irqFlag) \ + do{ \ + if (_pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + {\ + UINT32 _val, _bit = (1 << 19); \ + \ + _pAd->ShrMSel = _shr_msel; \ + RTMP_IO_READ32(_pAd, PBF_SYS_CTRL, &_val);\ + _val = (_shr_msel == HIGHER_SHRMEM) ? (_val | _bit) : (_val & (~_bit));\ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, _val); \ + RTMP_INT_UNLOCK(&_pAd->ShrMemLock, _irqFlag); \ + }\ + } while(0) +#endif /* RTMP_MAC_PCI */ + + +#else + +#define RTMP_MAC_SHR_MSEL_PROTECT_LOCK(__pAd, __IrqFlags) __IrqFlags = __IrqFlags; +#define RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(__pAd, __IrqFlags) __IrqFlags = __IrqFlags; + +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + + + + +struct _RTMP_ADAPTER; + +INT get_pkt_phymode_by_rxwi(struct _RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi); +INT get_pkt_rssi_by_rxwi(struct _RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi, INT size, CHAR *rssi); +INT get_pkt_snr_by_rxwi(struct _RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi, INT size, UCHAR *snr); + +INT rtmp_mac_set_band(struct _RTMP_ADAPTER *pAd, int band); +INT rtmp_mac_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 extch); +INT rtmp_mac_set_mmps(struct _RTMP_ADAPTER *pAd, INT ReduceCorePower); + +VOID rtmp_mac_bcn_buf_init(struct _RTMP_ADAPTER *pAd); + +INT rtmp_mac_init(struct _RTMP_ADAPTER *pAd); + +#ifdef MCS_LUT_SUPPORT +INT set_lut_phy_rate( + struct _RTMP_ADAPTER *pAd, UINT8 wcid, + UINT8 mcs, UINT8 bw, UINT8 gi, + UINT8 stbc, UINT8 mode); +#endif /* MCS_LUT_SUPPORT */ + +#endif /* __RTMP_MAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mat.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mat.h new file mode 100644 index 000000000..c86510edf --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mat.h @@ -0,0 +1,211 @@ +/* + *************************************************************************** + * 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: + mat.h + + Abstract: + Support AP-Client function. + + Revision History: + Who When What + -------------- ---------- ---------------------------------------------- + Shiang 02-26-2007 created +*/ + +#ifndef _MAT_H_ +#define _MAT_H_ + + + + +/*#if defined(LINUX) || defined (VXWORKS) */ + +/*#else */ +/*Currently support upper layer protocols */ +#ifndef ETH_P_IP +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#endif +#ifndef ETH_P_ARP +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#endif +#ifndef ETH_P_PPP_DISC +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#endif +#ifndef ETH_P_PPP_SES +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +#endif + +/* ARP protocol HARDWARE identifiers. */ +#ifndef ARPHRD_ETHER +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#endif + +/* ARP protocol opcodes. */ +#ifndef ARPOP_REQUEST +#define ARPOP_REQUEST 1 /* ARP request */ +#endif +#ifndef ARPOP_REPLY +#define ARPOP_REPLY 2 /* ARP reply */ +#endif + +typedef struct _NET_PRO_ARP_HDR{ + unsigned short ar_hrd; /* format of hardware address */ + unsigned short ar_pro; /* format of protocol address */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + unsigned short ar_op; /* ARP opcode (command) */ +} NET_PRO_ARP_HDR; + +typedef struct _NET_PRO_IP_HDR{ +#ifndef RT_BIG_ENDIAN + UCHAR ihl:4, + version:4; +#else + UCHAR version:4, + ihl:4; +#endif + UCHAR tos; + UINT16 tot_len; + UINT16 id; + UINT16 frag_off; + UCHAR ttl; + UCHAR protocol; + UINT16 check; + UINT16 saddr; + UINT32 daddr; +} NET_PRO_IP_HDR; +/*#endif //endif of __LINUX__ */ + +#ifndef MAT_SUPPORT +//#error "You should define MAT_SUPPORT if you want to compile MAT related functions!" +#endif + + +/* MAT relate definition */ +#define MAT_MAX_HASH_ENTRY_SUPPORT 64 +#define MAT_TB_ENTRY_AGEOUT_TIME (5 * 60 * OS_HZ) /* 30000, 5min. MAT convert table entry age-out time interval. now set it as 5min. */ + + +/* 802.3 Ethernet related definition */ +#define MAT_ETHER_HDR_LEN 14 /* dstMac(6) + srcMac(6) + protoType(2) */ +#define MAT_VLAN_ETH_HDR_LEN (MAT_ETHER_HDR_LEN + 4) /* 4 for h_vlan_TCI and h_vlan_encapsulated_proto */ + +#define MAT_MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define MAT_MAC_ADDR_HASH_INDEX(Addr) (MAT_MAC_ADDR_HASH(Addr) % MAT_MAX_HASH_ENTRY_SUPPORT) + +#define isMcastEtherAddr(addr) (addr[0] & 0x1) +#define isBcastEtherAddr(addr) ((addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5])== 0xff) +#define isZeroEtherAddr(addr) (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) + +#define IS_GROUP_MAC(Addr) ((Addr[0]) & 0x01) +#define IS_UCAST_MAC(addr) (!(isMcastEtherAddr(addr) || isZeroEtherAddr(addr))) /* isUcastMac = !(00:00:00:00:00:00 || mcastMac); */ +#define IS_EQUAL_MAC(a, b) (((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5])) == 0) + +#define IS_VLAN_PACKET(pkt) ((((pkt)[12] << 8) | (pkt)[13]) == 0x8100) + +/* IPv4 related definition */ +#define IPMAC_TB_HASH_ENTRY_NUM (MAT_MAX_HASH_ENTRY_SUPPORT+1) /* One entry for broadcast address */ +#define IPMAC_TB_HASH_INDEX_OF_BCAST MAT_MAX_HASH_ENTRY_SUPPORT /* cause hash index start from 0. */ + +#define MAT_IP_ADDR_HASH(Addr) (((Addr>>24)&0xff)^((Addr>>16) & 0xff) ^((Addr>>8) & 0xff) ^ (Addr & 0xff)) +#define MAT_IP_ADDR_HASH_INDEX(Addr) (MAT_IP_ADDR_HASH(Addr) % MAT_MAX_HASH_ENTRY_SUPPORT) + +#define IS_GOOD_IP(IP) (IP!= 0) +#define IS_MULTICAST_IP(IP) (((UINT32)(IP) & 0xf0000000) == 0xe0000000) + +/* IPv6 related definition */ +#define IPV6MAC_TB_HASH_ENTRY_NUM (MAT_MAX_HASH_ENTRY_SUPPORT+1) /* One entry for broadcast address */ +#define IPV6MAC_TB_HASH_INDEX_OF_BCAST MAT_MAX_HASH_ENTRY_SUPPORT /* cause hash index start from 0. */ + +/*We just use byte 10,13,14,15 to calculate the IPv6 hash, because the byte 11,12 usually are 0xff, 0xfe for link-local address. */ +#define MAT_IPV6_ADDR_HASH(Addr) ((Addr[10]&0xff) ^ (Addr[13] & 0xff) ^(Addr[14] & 0xff) ^ (Addr[15] & 0xff)) +#define MAT_IPV6_ADDR_HASH_INDEX(Addr) (MAT_IPV6_ADDR_HASH(Addr) % MAT_MAX_HASH_ENTRY_SUPPORT) + +#define IS_UNSPECIFIED_IPV6_ADDR(_addr) \ + (!((_addr).ipv6_addr32[0] | (_addr).ipv6_addr32[1] | (_addr).ipv6_addr32[2] | (_addr).ipv6_addr32[3])) + +#define IS_LOOPBACK_IPV6_ADDR(_addr) \ + (NdisEqualMemory((UCHAR *)(&((_addr).ipv6_addr[0])), &IPV6_LOOPBACKADDR[0], IPV6_ADDR_LEN)) +#define IS_MULTICAST_IPV6_ADDR(_addr) \ + (((_addr).ipv6_addr[0] & 0xff) == 0xff) + +/* The MAT_TABLE used for MacAddress <-> UpperLayer Address Translation. */ +typedef struct _MAT_TABLE_ +{ + VOID *IPMacTable; /* IPv4 Address, Used for IP, ARP protocol */ + VOID *IPv6MacTable; /* IPv6 Address, Used for IPv6 related protocols */ + VOID *SesMacTable; /* PPPoE Session */ + VOID *UidMacTable; /* PPPoE Discovery */ +}MAT_TABLE, *PMAT_TABLE; + + +typedef enum _MAT_ENGINE_STATUS_ +{ + MAT_ENGINE_STAT_UNKNOWN = 0, + MAT_ENGINE_STAT_INITED = 1, + MAT_ENGINE_STAT_EXITED = 2, +}MAT_ENGINE_STATUS; + + +typedef struct _MAT_STRUCT_ +{ + MAT_ENGINE_STATUS status; + NDIS_SPIN_LOCK MATDBLock; + MAT_TABLE MatTableSet; +#ifdef KMALLOC_BATCH + UCHAR *pMATNodeEntryPoll; +#endif +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bMACRepeaterEn; +#endif /* MAC_REPEATER_SUPPORT */ + UINT32 nodeCount; /* the number of nodes which connect to Internet via us. */ + VOID *pPriv; +}MAT_STRUCT; + + +typedef struct _MATProtoOps +{ + NDIS_STATUS (*init)(MAT_STRUCT *pMatCfg); + PUCHAR (*tx)(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr); + PUCHAR (*rx)(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr); + NDIS_STATUS (*exit)(MAT_STRUCT *pMatCfg); +}MATProtoOps, *PMATProtoOps; + + +typedef struct _MATProtoTable +{ + USHORT protocol; + MATProtoOps *pHandle; +}MATProtoTable, *PMATProtoTable; + + +VOID dumpPkt(PUCHAR pHeader, int len); + +/*#define KMALLOC_BATCH */ + +PUCHAR MATDBEntryAlloc( + IN MAT_STRUCT *pMatStruct, + IN UINT32 size); + +NDIS_STATUS MATDBEntryFree( + IN MAT_STRUCT *pMatStruct, + IN PUCHAR NodeEntry); + + +#endif /* _MAT_H_ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/btcoex.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/btcoex.h new file mode 100644 index 000000000..11feb5680 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/btcoex.h @@ -0,0 +1,344 @@ +/* + *************************************************************************** + * 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: + mcu.h + + Abstract: + MCU related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __BTCOEX_H__ +#define __BTCOEX_H__ + +struct _RTMP_ADAPTER; +struct _MAC_TABLE_ENTRY; + +/* Woody add for BT COEX*/ +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) +#define BIT8 (1 << 8) +#define BIT9 (1 << 9) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT15 (1 << 15) +#define BIT16 (1 << 16) +#define BIT17 (1 << 17) +#define BIT18 (1 << 18) +#define BIT19 (1 << 19) +#define BIT20 (1 << 20) +#define BIT21 (1 << 21) +#define BIT22 (1 << 22) +#define BIT23 (1 << 23) +#define BIT24 (1 << 24) +#define BIT25 (1 << 25) +#define BIT26 (1 << 26) +#define BIT27 (1 << 27) +#define BIT28 (1 << 28) +#define BIT29 (1 << 29) +#define BIT30 (1 << 30) +#define BIT31 (1 << 31) + +#define IS_MT76XXBTCOMBO(_pAd) (IS_MT7650(_pAd) || IS_MT7630(_pAd) || IS_MT7662(_pAd)) +// +// Antenna mode (ANT_MODE_XXX) +// +#define ANT_MODE_DUAL (0x01) // Chip is in dual antenna mode +#define ANT_MODE_SINGLE (0x02) // Chip is in single antenna mode + +#define TypeTFSwitch 0x1 +#define TypeProtectionFrame 0x2 +#define TypeAFH 0x3 +#define TypeWiFiStatus 0x4 +#define TypeHostLoopBackTFSwitch 0xFFF1 +#define TypeCoexCCUForceMode 0xFFF2 + +#define COEX_MODE_RESET 0 +#define COEX_MODE_TDD 1 +#define COEX_MODE_HYBRID 2 +#define COEX_MODE_FDD 3 + +#define COEX_OPMODE_STA 1 +#define COEX_OPMODE_AP 2 +#define COEX_OPMODE_GC 3 +#define COEX_OPMODE_GO 4 +#define COEX_OPMODE_BT 5 +#define COEX_OPMODE_AD_HOC 6 + + +#define COEX_BARXSIZE_A2DP 8 +#define COEX_BARXSIZE_SCO_ESCO 2 +#define COEX_BARXSIZE_OPP 32 + + + +#define WLAN_NO_BSSID 0x0 +#define WLAN_Device_OFF 0x1 +#define WLAN_Device_ON 0x2 +#define WLAN_SCANREQEST 0x3 +#define WLAN_SCANDONE 0x4 +#define WLAN_SCANCANCEL 0x5 +#define WLAN_SCAN2GREQUET 0x6 +#define WLAN_SCAN5GREQUET 0x7 +#define WLAN_CONNECTION_START 0x14 +#define WLAN_CONNECTION_COMPLETION 0x15 +#define WLAN_CONNECTION_CANCEL_IND 0x16 +#define WLAN_CONNECTION_JOIN_FAIL 0x17 +#define WLAN_CONNECTION_AUTH_FAIL 0x18 +#define WLAN_CONNECTION_ASSOC_FAIL 0x19 +#define WLAN_DISCONNECT 0x1A +#define WLAN_ROAMING_START 0x1B +#define WLAN_ROAMING_COMPLETE 0x1C +#define WLAN_DeAuthConfirm 0x8 +#define WLAN_AssocRequest 0x9 +#define WLAN_AssocConfirm 0xA +#define WLAN_ReAssocRequest 0xB +#define WLAN_ReAssocConfirm 0xC +#define WLAN_DisAssocRequest 0xD +#define WLAN_INVINCIBLE_REQ 0xF1 +#define WLAN_INVINCIBLE_ABORT 0xF2 +#define WLAN_BEACON_SERVICE_REQ 0xF3 +#define WLAN_BEACON_SERVICE_CONF 0xF4 + +#define fBTSTATUS_BT_DISABLE 0x00000001 +#define fBTSTATUS_BT_INACTIVE 0x00000002 +#define fBTSTATUS_BT_SCANONLY 0x00000004 +#define fBTSTATUS_BT_HOLD 0x00000008 +#define fBTSTATUS_BT_ACTIVE 0x00000010 + +#define BT_STATUS_SET_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags |= (_F)) +#define BT_STATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags &= ~(_F)) +#define BT_STATUS_TEST_FLAG(_pAd, _F) (((_pAd)->BTStatusFlags & (_F)) != 0) + +#define NULLFRAMESPACE 10 +#define COEXNOZEROSHIFT 1 +#define CTSTOSELF 1 +#define CFEND 2 +#define POWERSAVE0 3 +#define POWERSAVE1 4 +#define PROTECTIONFRAMEREADY 1 +#define PROTECTIONFRAMECANCEL 2 + +#define COEX_WIFI_LINK_UP 1 +#define COEX_WIFI_LINK_DOWN 2 + +typedef struct PROTECTION_FRAME_STRUCT { + BOOLEAN Occupied; + ULONG Triggernumber; + ULONG Valid; + ULONG NodeType; + ULONG BssHashID; + ULONG FrameType; +} PROTECTION_FRAME_STRUCT, *PPROTECTION_FRAME_STRUCT; + +typedef struct _COEX_RX_MANUAL_AGC_GAIN { + BOOLEAN bEnable; + BOOLEAN bStopAGC; + CHAR LMthreshold; + CHAR MHthreshold; +} COEX_RX_MANUAL_AGC_GAIN, *PCOEX_RX_MANUAL_AGC_GAIN; + +typedef struct _COEX_MODE_STRUCTURE { + BOOLEAN bForce; + BOOLEAN FDDRequest; + BOOLEAN TDDRequest; + ULONG TDD_Power; + ULONG FDD_Power; + ULONG DefaultMode; + ULONG CurrentMode; + ULONG UpdateMode; + CHAR CoexTDDRSSITreshold; + CHAR CoexFDDRSSITreshold; + UCHAR RxBAWinLimit; /* 0 = not set, use original value */ + UCHAR TxBAWinLimit; /* 0 = not set, use origianl value */ +} COEX_MODE_STRUCTURE, *PCOEX_MODE_STRUCTURE; + + +typedef struct _COEX_PROTECTION_FRAME_INFO +{ + ULONG CoexOperation; + ULONG Triggernumber; + ULONG Valid; + ULONG NodeType; + ULONG BssHashID; + ULONG FrameType; +} COEX_PROTECTION_FRAME_INFO, *PCOEX_PROTECTION_FRAME_INFO; + +typedef struct _COEX_AFH +{ + ULONG CoexOperation; + ULONG LinkStatus; + ULONG BW; + ULONG Channel; + ULONG BssHashID; + } COEX_AFH, *PCOEX_AFH; + +typedef struct _COEX_TF_SWITCH +{ + ULONG CoexOperation; + ULONG CoexMode; + + } COEX_TF_SWITCH, *PCOEX_TF_SWITCH; + + +typedef struct _COEX_WLAN_STATUS +{ + ULONG CoexOperation; + ULONG WLANStatus; + ULONG PrivilegeTime; + ULONG BssHashID; + + } COEX_WLAN_STATUS, *PCOEX_WLAN_STATUS; + +#define PKT_CMD_TYPE_COEX_OP (17) + +#define BTCOEX_BB_BITWISE_WRITE(_BbReg, _BitLocation, _BitValue) \ + (_BbReg = (((_BbReg) & ~(_BitLocation)) | (_BitValue))) + +#define BTCOEX_BB_BITMASK_READ(_BbReg, _BitLocation) \ + ((_BbReg) & (_BitLocation)) + +#define MAC_BITWISE_WRITE(_MacReg, _BitLocation, _BitValue) \ + (_MacReg = (((_MacReg) & ~(_BitLocation)) | (_BitValue))) + +#define MAC_BITMASK_READ(_MacReg, _BitLocation) \ + ((_MacReg) & (_BitLocation)) + +#define BT_STATUS_SET_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags |= (_F)) +#define BT_STATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags &= ~(_F)) +#define BT_STATUS_TEST_FLAG(_pAd, _F) (((_pAd)->BTStatusFlags & (_F)) != 0) + +typedef union _BT_STATUS_REPORT_STRUC { + struct { + ULONG BT_DISABLE:1; + ULONG BT_INACTIVE:1; + ULONG BT_SCANONLY:1; + ULONG BT_HOLD:1; + ULONG BT_ACTIVE:1; + ULONG RESERVE1:3; + ULONG BT_TRANSPORT:5; + ULONG RESERVE2:3; + ULONG BT_LINK_CNT:3; + ULONG BLE_LINK_CNT:2; + ULONG RESERVE3:3; + ULONG BT_SLAVE_IND:7; + ULONG RESERVE4:1; + } field; + ULONG word; +} BT_STATUS_REPORT_STRUC, *PBT_STATUS_REPORT_STRUC; + +VOID BtAFHCtl( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BBPCurrentBW, + IN UCHAR Channel, + IN UCHAR CentralChannel, + IN BOOLEAN Disable); + +VOID TDDFDDExclusiveRequest(IN struct _RTMP_ADAPTER *pAd, UCHAR CoexMode); + +VOID EstablishFrameBundle( + IN struct _RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN ULONG OPMode, + IN struct _MAC_TABLE_ENTRY *pEntry +); + +VOID UpdateAndesNullFrameSpace( + IN struct _RTMP_ADAPTER *pAd); + +VOID InvalidProtectionFrameSpace( + IN struct _RTMP_ADAPTER *pAd, + IN PUCHAR pAddr +); + +VOID RemoveProtectionFrameSpace( + IN struct _RTMP_ADAPTER *pAd, + IN PUCHAR pAddr +); + +VOID TDDFDDCoexBACapability( + IN struct _RTMP_ADAPTER *pAd, + UCHAR CoexMode ); + +VOID SendAndesTFSWITCH( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR CoexMode + ); + +VOID CoexFDDRXAGCGain( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR rssi); + +VOID CoexTDDRXAGCGain(IN struct _RTMP_ADAPTER *pAd); + +VOID SendAndesWLANStatus( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR WlanStatus, + IN ULONG PrivilegeTime, + IN ULONG BssHashID + ); + +VOID InitBTCoexistence( + IN struct _RTMP_ADAPTER *pAd); + +VOID SendAndesAFH( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BBPCurrentBW, + IN UCHAR Channel, + IN UCHAR CentralChannel, + IN BOOLEAN Disable, + IN ULONG BssHashID); + + +VOID MLMEHook( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR WlanStatus, + IN ULONG BssHashID + ); + +VOID CoexistencePeriodicRoutine( + IN struct _RTMP_ADAPTER *pAd + ); + +VOID COEXLinkDown( + IN struct _RTMP_ADAPTER *pAd, + PUCHAR pAddr +); + +ULONG QueryHashID( + IN struct _RTMP_ADAPTER *pAd, + PUCHAR pAddr, + BOOLEAN RemoveBSS); + +VOID CoexParseBTStatus( + IN PRTMP_ADAPTER pAd + ) ; + +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mcu.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mcu.h new file mode 100644 index 000000000..1f17dffd2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mcu.h @@ -0,0 +1,66 @@ +/* + *************************************************************************** + * 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: + mcu.h + + Abstract: + MCU related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __MCU_H__ +#define __MCU_H__ + +enum MCU_TYPE { + SWMCU, + M8051, + ANDES, +}; + +/* + * Power opration + */ +enum PWR_OP { + RADIO_OFF = 0x30, + RADIO_ON, + RADIO_OFF_AUTO_PWR_SAVING, + RADIO_ON_AUTO_PWR_SAVING, + RADIO_OFF_ADVANCE_PWR_SAVING, + RADIO_ON_ADVANCE_PWR_SAVING, +}; + +/* + * Load code method + */ +enum LOAD_CODE_METHOD { + HEADER_METHOD, + BIN_FILE_METHOD, +}; + +struct _RTMP_ADAPTER; + +VOID ChipOpsMCUHook(struct _RTMP_ADAPTER *pAd, enum MCU_TYPE MCUType); +VOID MCUCtrlInit(struct _RTMP_ADAPTER *pAd); +VOID MCUCtrlExit(struct _RTMP_ADAPTER *pAd); + +INT mcu_sys_init(struct _RTMP_ADAPTER *pAd); + +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mcu_and.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mcu_and.h new file mode 100644 index 000000000..b34b96248 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mcu_and.h @@ -0,0 +1,464 @@ +/* + *************************************************************************** + * 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: + mcu_and.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __MCU_AND_H__ +#define __MCU_AND_H__ + +#include "mcu.h" + +#ifndef WORKQUEUE_BH +#include +#endif + +struct _RTMP_ADAPTER; +struct _BANK_RF_REG_PAIR; +struct _R_M_W_REG; +struct _RF_R_M_W_REG; + +#define CPU_CTL 0x0704 +#define CLOCK_CTL 0x0708 +#define RESET_CTL 0x070C +#define INT_LEVEL 0x0718 +#define COM_REG0 0x0730 +#define COM_REG1 0x0734 +#define COM_REG2 0x0738 +#define COM_REG3 0x073C +#define PCIE_REMAP_BASE1 0x0740 +#define PCIE_REMAP_BASE2 0x0744 +#define PCIE_REMAP_BASE3 0x0748 +#define PCIE_REMAP_BASE4 0x074C +#define LED_CTRL 0x0770 +#define LED_TX_BLINK_0 0x0774 +#define LED_TX_BLINK_1 0x0778 +#define LED0_S0 0x077C +#define LED0_S1 0x0780 +#define SEMAPHORE_00 0x07B0 +#define SEMAPHORE_01 0x07B4 +#define SEMAPHORE_02 0x07B8 +#define SEMAPHORE_03 0x07BC + +#define MCU_WAIT_ACK_CMD_THRESHOLD 0x0f +#define MCU_RX_CMD_THRESHOLD 0x0f + + + +#ifdef RTMP_MAC_PCI +#define ANDES_FIRMWARE_IMAGE_BASE 0x80000 +#endif /* RTMP_MAC_PCI */ + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXINFO_NMAC_CMD_PKT{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 cmd_type:7; + UINT32 cmd_seq:4; + UINT32 pkt_len:16; +}TXINFO_NMAC_CMD_PKT; +#else +typedef struct GNU_PACKED _TXINFO_NMAC_CMD_PKT { + UINT32 pkt_len:16; + UINT32 cmd_seq:4; + UINT32 cmd_type:7; + UINT32 d_port:3; + UINT32 info_type:2; +}TXINFO_NMAC_CMD_PKT; +#endif /* RT_BIG_ENDIAN */ + +enum cmd_msg_state { + illegal, + tx_start, + tx_kickout_fail, + tx_timeout_fail, + tx_retransmit, + tx_done, + wait_cmd_out, + wait_cmd_out_and_ack, + wait_ack, + rx_start, + rx_receive_fail, + rx_done, +}; + +enum { + MCU_INIT, + MCU_TX_HALT, + MCU_RX_HALT, +}; + +enum { + CMD_ACK, +}; + +enum cmd_msg_error_type { + error_tx_kickout_fail, + error_tx_timeout_fail, + error_rx_receive_fail, +}; + +struct MCU_CTRL { + u8 cmd_seq; + unsigned long flags; +#ifndef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT cmd_msg_task; +#else + struct tasklet_struct cmd_msg_task; +#endif + NDIS_SPIN_LOCK txq_lock; + DL_LIST txq; + NDIS_SPIN_LOCK rxq_lock; + DL_LIST rxq; + NDIS_SPIN_LOCK ackq_lock; + DL_LIST ackq; + NDIS_SPIN_LOCK kickq_lock; + DL_LIST kickq; + NDIS_SPIN_LOCK tx_doneq_lock; + DL_LIST tx_doneq; + NDIS_SPIN_LOCK rx_doneq_lock; + DL_LIST rx_doneq; + unsigned long tx_kickout_fail_count; + unsigned long tx_timeout_fail_count; + unsigned long rx_receive_fail_count; + unsigned long alloc_cmd_msg; + unsigned long free_cmd_msg; + BOOLEAN power_on; + BOOLEAN dpd_on; + struct _RTMP_ADAPTER *ad; +}; + + +struct cmd_msg; +typedef void (*MSG_RSP_HANDLER)(struct cmd_msg *msg, char *payload, u16 payload_len); +typedef void (*MSG_EVENT_HANDLER)(struct _RTMP_ADAPTER *ad, char *payload, u16 payload_len); + +struct cmd_msg_cb { + struct cmd_msg *msg; +}; + +#define USB_END_PADDING 4 +#define UPLOAD_PATCH_UNIT 2048 +#define PATCH_INFO_SIZE 30 +#define FW_INFO_SIZE 32 +#define IV_SIZE 0x40 +#define GET_SEMAPHORE_RETRY_MAX 600 +#define UPLOAD_FW_UNIT 14592 +#define UPLOAD_FW_TIMEOUT 1000 +#define CMD_MSG_CB(pkt) ((struct cmd_msg_cb *)(GET_OS_PKT_CB(pkt))) +#define CMD_MSG_RETRANSMIT_TIMES 3 +#define CMD_MSG_TIMEOUT 500 + +struct cmd_msg { + DL_LIST list; + u8 type; + u8 seq; + u16 timeout; + u16 rsp_payload_len; + BOOLEAN need_wait; + BOOLEAN need_rsp; + BOOLEAN need_retransmit; +#ifdef RTMP_PCI_SUPPORT + BOOLEAN ack_done; +#endif + + char *rsp_payload; + MSG_RSP_HANDLER rsp_handler; + enum cmd_msg_state state; + void *priv; + PNDIS_PACKET net_pkt; + int retransmit_times; +}; + +/* + * Calibration ID + */ +enum CALIBRATION_ID { + R_CALIBRATION = 1, + RXDCOC_CALIBRATION = 2, + LC_CALIBRATION = 3, + LOFT_CALIBRATION = 4, + TXIQ_CALIBRATION = 5, + BW_CALIBRATION = 6, + DPD_CALIBRATION = 7, + RXIQ_CALIBRATION = 8, + TXDCOC_CALIBRATION = 9, + RX_GROUP_DELAY_CALIBRATION = 10, + TX_GROUP_DELAY_CALIBRATION = 11, + VCO_CALIBRATION = 12, + NON_SIGNAL_CALIBRATION = 0xFE, + FULL_CALIBRATION_ID = 0xFF, +}; + +enum CALIBRATION_ID_7662 { + R_CALIBRATION_7662 = 1, + TEMP_SENSOR_CALIBRATION_7662, + RXDCOC_CALIBRATION_7662, + RC_CALIBRATION_7662, + SX_LOGEN_CALIBRATION_7662, + LC_CALIBRATION_7662, + TX_LOFT_CALIBRATION_7662, + TXIQ_CALIBRATION_7662, + TSSI_CALIBRATION_7662, + TSSI_COMPENSATION_7662, + DPD_CALIBRATION_7662, + RXIQC_FI_CALIBRATION_7662, + RXIQC_FD_CALIBRATION_7662, + PWR_ON_CALIBRATION_7662, + TX_SHAPING_CALIBRATION_7662, +}; + +enum CALIBRATION_TYPE { + FULL_CALIBRATION, + PARTIAL_CALIBRATION, +}; + +enum SWITCH_CHANNEL_STAGE { + NORMAL_OPERATING = 0x01, + SCANNING = 0x02, + TEMPERATURE_CHANGE = 0x04, +}; + +/* + * Function set ID + */ +enum FUN_ID { + Q_SELECT = 1, + BW_SETTING = 2, + USB2_SW_DISCONNECT = 2, + USB3_SW_DISCONNECT = 3, + LOG_FW_DEBUG_MSG = 4, + GET_FW_VERSION = 5, +}; + +/* + * Command response RX Ring selection + */ +enum RX_RING_ID { + RX_RING0, + RX_RING1, +}; + +enum BW_SETTING { + BW20 = 1, + BW40 = 2, + BW10 = 4, + BW80 = 8, +}; + +/* + * FW debug message parameters + */ +enum FW_DEBUG_SETTING { + DISABLE_DEBUG_MSG = 0, + DEBUG_MSG_TO_UART, + DEBUG_MSG_TO_HOST, +}; + +enum CR_TYPE { + RF_CR, + BBP_CR, + RF_BBP_CR, + HL_TEMP_CR_UPDATE, +}; + +enum TEMPERATURE_LEVEL_7662 { + NORMAL_TEMP_7662, /* 0~60 */ + LOW_TEMP_7662, /* < 0 */ + HIGH_TEMP_7662, /* > 60 */ +}; + +#define LOAD_CR_MODE_MASK (0xff) +#define LOAD_CR_MODE(p) (((p) & 0xff)) +#define LOAD_CR_TEMP_LEVEL_MASK (0xff << 8) +#define LOAD_CR_TEMP_LEVEL(p) (((p) & 0xff) << 8) +#define LOAD_CR_CHL_MASK (0xff << 16) +#define LOAD_CR_CHL(p) (((p) & 0xff) << 16) + +#define SC_PARAM1_CHL_MASK (0xff) +#define SC_PARAM1_CHL(p) (((p) & 0xff)) +#define SC_PARAM1_SCAN_MASK (0xff << 8) +#define SC_PARAM1_SCAN(p) (((p) & 0xff) << 8) +#define SC_PARAM1_BW_MASK (0xff << 16) +#define SC_PARAM1_BW(p) (((p) & 0xff) << 16) + +#define SC_PARAM2_TR_SETTING_MASK (0xffff) +#define SC_PARAM2_TR_SETTING(p) (((p) & 0xffff)) +#define SC_PARAM2_EXTENSION_CHL_MASK (0xff << 16) +#define SC_PARAM2_EXTENSION_CHL(p) (((p) & 0xff) << 16) + +#define TSSI_PARAM2_SLOPE0_MASK (0xff) +#define TSSI_PARAM2_SLOPE0(p) (((p) & 0xff)) +#define TSSI_PARAM2_SLOPE1_MASK (0xff << 8) +#define TSSI_PARAM2_SLOPE1(p) (((p) & 0xff) << 8) +#define TSSI_PARAM2_OFFSET0_MASK (0xff << 16) +#define TSSI_PARAM2_OFFSET0(p) (((p) & 0xff) << 16) +#define TSSI_PARAM2_OFFSET1_MASK (0xff << 24) +#define TSSI_PARAM2_OFFSET1(p) (((p) & 0xff) << 24) + +/* + * Command type table + */ +enum CMD_TYPE { + CMD_FUN_SET_OP = 1, + CMD_LOAD_CR, + CMD_INIT_GAIN_OP = 3, + CMD_DYNC_VGA_OP = 6, + CMD_TDLS_CH_SW = 7, + CMD_BURST_WRITE = 8, + CMD_READ_MODIFY_WRITE, + CMD_RANDOM_READ, + CMD_BURST_READ, + CMD_RANDOM_WRITE = 12, + CMD_LED_MODE_OP = 16, + CMD_POWER_SAVING_OP = 20, + CMD_WOW_CONFIG, + CMD_WOW_QUERY, + CMD_WOW_FEATURE = 24, + CMD_CARRIER_DETECT_OP = 28, + CMD_RADOR_DETECT_OP, + CMD_SWITCH_CHANNEL_OP, + CMD_CALIBRATION_OP, + CMD_BEACON_OP, + CMD_ANTENNA_OP +}; + +/* + * Event type table + */ +enum EVENT_TYPE { + CMD_DONE, + CMD_ERROR, + CMD_RETRY, + EVENT_PWR_RSP, + EVENT_WOW_RSP, + EVENT_CARRIER_DETECT_RSP, + EVENT_DFS_DETECT_RSP, +}; + +enum mcu_skb_state { + ILLEAGAL = 0, + MCU_CMD_START, + MCU_CMD_DONE, + MCU_RSP_START, + MCU_RSP_DONE, + MCU_RSP_CLEANUP, + UNLINK_START, +}; + +struct mcu_skb_data { + enum mcu_skb_state state; +}; + +typedef union _ANDES_CALIBRATION_PARAM { + UINT32 generic; +#ifdef MT76x2 + struct { + UINT32 pa_mode; + UINT32 tssi_slope_offset; + } mt76x2_tssi_comp_param; +#endif +} ANDES_CALIBRATION_PARAM; + +enum CALIBRATION_TEST_TYPE { + CAL_ROBUST_TEST=0, + +}; + +#ifdef RTMP_PCI_SUPPORT +int andes_pci_load_rom_patch(struct _RTMP_ADAPTER *ad); +int andes_pci_erase_rom_patch(struct _RTMP_ADAPTER *ad); +int andes_pci_loadfw(struct _RTMP_ADAPTER *ad); +int andes_pci_erasefw(struct _RTMP_ADAPTER *ad); +void pci_rx_cmd_msg_complete(struct _RTMP_ADAPTER *ad, RXFCE_INFO *fce_info, PUCHAR payload); +void andes_pci_fw_init(struct _RTMP_ADAPTER *ad); +#endif /* RTMP_PCI_SUPPORT */ +void andes_ctrl_init(struct _RTMP_ADAPTER *ad); +void andes_ctrl_enable(struct _RTMP_ADAPTER *ad); +void andes_ctrl_disable(struct _RTMP_ADAPTER *ad); +void andes_ctrl_exit(struct _RTMP_ADAPTER *ad); +int andes_send_cmd_msg(struct _RTMP_ADAPTER *ad, struct cmd_msg *msg); +int andes_burst_write(struct _RTMP_ADAPTER *ad, u32 offset, u32 *data, u32 cnt); +int andes_burst_read(struct _RTMP_ADAPTER *ad, u32 offset, u32 cnt, u32 *data); +int andes_random_read(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, u32 num); +int andes_rf_random_read(struct _RTMP_ADAPTER *ad, struct _BANK_RF_REG_PAIR *reg_pair, u32 num); +int andes_read_modify_write(struct _RTMP_ADAPTER *ad, struct _R_M_W_REG *reg_pair, u32 num); +int andes_rf_read_modify_write(struct _RTMP_ADAPTER *ad, struct _RF_R_M_W_REG *reg_pair, u32 num); +int andes_random_write(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, u32 num); +int andes_rf_random_write(struct _RTMP_ADAPTER *ad, struct _BANK_RF_REG_PAIR *reg_pair, u32 num); +int andes_sc_random_write(struct _RTMP_ADAPTER *ad, CR_REG *table, u32 nums, u32 flags); +int andes_sc_rf_random_write(struct _RTMP_ADAPTER *ad, BANK_RF_CR_REG *table, u32 nums, u32 flags); +int andes_fun_set(struct _RTMP_ADAPTER *ad, u32 fun_id, u32 param); +int andes_pwr_saving(struct _RTMP_ADAPTER *ad, u32 op, u32 level, + u32 listen_interval, u32 pre_tbtt_lead_time, + u8 tim_byte_offset, u8 tim_byte_pattern); +int andes_calibration(struct _RTMP_ADAPTER *ad, u32 cal_id, ANDES_CALIBRATION_PARAM *param); +BOOLEAN is_inband_cmd_processing(struct _RTMP_ADAPTER *ad); +void andes_cmd_msg_bh(unsigned long param); +int usb_rx_cmd_msg_submit(struct _RTMP_ADAPTER *ad); +int usb_rx_cmd_msgs_receive(struct _RTMP_ADAPTER *ad); +void andes_bh_schedule(struct _RTMP_ADAPTER *ad); +void pci_kick_out_cmd_msg_complete(PNDIS_PACKET net_pkt); +int andes_load_cr(struct _RTMP_ADAPTER *ad, u32 cr_type, UINT8 temp_level, UINT8 channel); +int andes_switch_channel(struct _RTMP_ADAPTER *ad, u8 channel, BOOLEAN scan, unsigned int bw, unsigned int tx_rx_setting, u8 bbp_ch_idx); +int andes_init_gain(struct _RTMP_ADAPTER *ad, UINT8 channel, BOOLEAN force_mode, unsigned int gain_from_e2p); +int andes_dynamic_vga(struct _RTMP_ADAPTER *ad, UINT8 channel, BOOLEAN mode, BOOLEAN ext, int rssi, unsigned int false_cca); +int andes_led_op(struct _RTMP_ADAPTER *ad, u32 led_idx, u32 link_status); +struct cmd_msg *andes_alloc_cmd_msg(struct _RTMP_ADAPTER *ad, unsigned int length); +void andes_init_cmd_msg(struct cmd_msg *msg, u8 type, BOOLEAN need_wait, u16 timeout, + BOOLEAN need_retransmit, BOOLEAN need_rsp, u16 rsp_payload_len, + char *rsp_payload, MSG_RSP_HANDLER rsp_handler); +void andes_append_cmd_msg(struct cmd_msg *msg, char *data, unsigned int len); + +#define MAX_CALIBRATION_WAIT_TIME 100 +#ifdef RTMP_PCI_SUPPORT +#define ANDES_CALIBRATION_START(_pAd) \ +{ \ + UINT32 _value; \ + RTMP_IO_READ32(_pAd, COM_REG0, &_value); \ + _value &= 0x7FFFFFFF; \ + _RTMP_IO_WRITE32(_pAd, COM_REG0, _value); \ +} + + +#define ANDES_WAIT_CALIBRATION_DONE(_pAd) \ +{ \ + UINT32 _value; \ + INT32 _i; \ + RtmpOsMsDelay(1); \ + for ( _i = 0 ; _i < MAX_CALIBRATION_WAIT_TIME; _i ++ ) { \ + RTMP_IO_READ32(_pAd, COM_REG0, &_value); \ + if ( _value & 0x80000000 ) \ + break; \ + RtmpOsMsDelay(5); \ + } \ + if ( _i == MAX_CALIBRATION_WAIT_TIME ) \ + DBGPRINT(RT_DEBUG_ERROR,("ANDES_WAIT_CALIBRATION_DONE timeout!\n")); \ + else \ + DBGPRINT(RT_DEBUG_INFO,("ANDES_WAIT_CALIBRATION_DONE %d\n", _i)); \ +} +#endif /* RTMP_PCI_SUPPORT */ + +#endif /* __MCU_AND_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7601_firmware.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7601_firmware.h new file mode 100644 index 000000000..31feb7d78 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7601_firmware.h @@ -0,0 +1,2924 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7601_FirmwareImage[] = { +0x44, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x76, 0x00, 0x01, 0x41, 0x76, 0x07, 0x02, +0x32, 0x30, 0x31, 0x33, 0x30, 0x34, 0x32, 0x33, 0x31, 0x35, 0x35, 0x37, 0x5f, 0x5f, 0x5f, 0x5f, +0x48, 0x00, 0x00, 0x52, 0x48, 0x00, 0x00, 0x1e, 0x48, 0x00, 0x00, 0x1c, 0x48, 0x00, 0x00, 0x1a, +0x48, 0x00, 0x00, 0x18, 0x48, 0x00, 0x00, 0x16, 0x48, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x12, +0x48, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x0e, 0x48, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x0a, +0x48, 0x00, 0x00, 0x08, 0x48, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x02, +0x92, 0x00, 0x48, 0x00, 0x00, 0x00, 0x92, 0x00, 0x3a, 0x0f, 0xab, 0xbc, 0x3a, 0xff, 0xbc, 0x3c, +0x64, 0x62, 0x04, 0x02, 0x64, 0x72, 0xa4, 0x02, 0x64, 0x82, 0x00, 0x02, 0x3a, 0x6f, 0xa0, 0x3c, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0x58, 0xb4, 0x00, 0x15, 0xf0, 0x00, 0x00, 0x46, 0x10, +0x00, 0x05, 0x58, 0x10, 0x8c, 0xe4, 0xdd, 0x21, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0x58, +0xb4, 0x00, 0x05, 0xf0, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x04, 0x64, 0x62, 0x04, 0x03, 0x64, 0x72, +0xa4, 0x03, 0x64, 0x82, 0x00, 0x03, 0x3a, 0xff, 0xbc, 0x04, 0x3a, 0x0f, 0xab, 0x84, 0x64, 0x00, +0x00, 0x04, 0x92, 0x00, 0x84, 0x0a, 0x64, 0x02, 0x00, 0x03, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x02, 0x00, 0x44, 0x10, 0x04, 0x01, 0xa8, 0x41, 0x84, 0x00, 0x64, 0x02, 0x24, 0x03, 0x46, 0x0c, +0x00, 0x00, 0x58, 0x00, 0x00, 0x02, 0x64, 0x03, 0x00, 0x03, 0x47, 0xf0, 0x00, 0x0f, 0x59, 0xff, +0x8f, 0x00, 0x46, 0x00, 0x00, 0x0a, 0x58, 0x00, 0x0b, 0xe0, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, +0x83, 0xe0, 0x84, 0x40, 0xd5, 0x02, 0xaa, 0x81, 0x4c, 0x10, 0x7f, 0xff, 0x46, 0x00, 0x00, 0x0b, +0x58, 0x00, 0x06, 0x50, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0xbc, 0x84, 0x40, 0xd5, 0x02, +0xaa, 0x81, 0x4c, 0x10, 0x7f, 0xff, 0x48, 0x00, 0x2d, 0x69, 0x92, 0x00, 0x84, 0x80, 0xa8, 0xc5, +0xa9, 0x01, 0xa8, 0x46, 0xa8, 0x84, 0xb6, 0x80, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0xb4, 0x20, 0xc1, 0x17, 0xa1, 0x41, 0x84, 0x80, 0xa9, 0x49, 0xb6, 0x25, 0xb6, 0x80, +0xa9, 0x01, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x40, 0xa0, 0xc2, 0xb4, 0x20, 0x9e, 0x99, +0xa8, 0x82, 0x4c, 0x10, 0x40, 0x08, 0xa0, 0x0b, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x7c, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x80, 0xd3, 0x80, 0xe0, 0xc2, 0x11, 0x80, 0x02, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x7c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xd3, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x83, 0x04, 0xdd, 0x2f, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x82, 0x1c, 0xdd, 0x2f, 0x46, 0x17, 0xff, 0xff, 0x58, 0x10, 0x8f, 0xff, +0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x03, 0x40, 0x81, 0x00, 0x40, 0xa0, 0x04, 0x00, 0x44, 0x00, +0xea, 0x60, 0x14, 0xa1, 0x00, 0x04, 0x80, 0xe2, 0xb4, 0xc2, 0x41, 0xc4, 0x00, 0x00, 0xd5, 0x2e, +0xa0, 0x32, 0x40, 0x34, 0x00, 0x01, 0x4e, 0x35, 0x00, 0x21, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0xa4, 0x36, 0xc0, 0x10, 0x9e, 0x01, 0xac, 0x36, 0x15, 0xc3, +0x00, 0x02, 0x05, 0xe3, 0x80, 0x01, 0xa9, 0xb9, 0xb6, 0xe6, 0x15, 0xe3, 0x00, 0x01, 0xb6, 0xde, +0xa1, 0x7a, 0x9d, 0x29, 0xa9, 0x3a, 0xd5, 0x06, 0xa0, 0xb6, 0xc2, 0x04, 0xa0, 0x75, 0xa0, 0x34, +0xdd, 0x22, 0x14, 0xa3, 0x80, 0x04, 0xd5, 0x09, 0xa0, 0xbc, 0x40, 0x90, 0x08, 0x01, 0x4e, 0x95, +0x00, 0x03, 0xd5, 0x02, 0xa8, 0x3c, 0x81, 0x26, 0xb4, 0xc9, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, +0x83, 0x40, 0x4c, 0x64, 0xff, 0xcf, 0xb4, 0xa6, 0xd6, 0x09, 0xa0, 0xf4, 0x40, 0x01, 0xa0, 0x01, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x5c, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xe1, 0x44, 0x10, 0xea, 0x60, +0x80, 0xc0, 0xe2, 0x27, 0xe8, 0x0e, 0x40, 0x03, 0x84, 0x57, 0x44, 0x2f, 0x15, 0xa0, 0x96, 0x01, +0x42, 0x70, 0x08, 0x73, 0xac, 0x36, 0xcf, 0x07, 0x9e, 0xc1, 0xac, 0xf6, 0x80, 0xe1, 0xd5, 0x03, +0x84, 0x20, 0xac, 0x46, 0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, 0x03, 0x40, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x82, 0x1c, 0xdd, 0x2f, 0xb4, 0x88, 0x40, 0x90, 0x1c, 0x00, 0x4c, 0x44, 0x00, 0x08, +0x05, 0xe4, 0x00, 0x04, 0x40, 0x54, 0xf8, 0x01, 0x4e, 0x54, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0x0e, +0x14, 0x97, 0x80, 0xd4, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x5c, 0xdd, 0x2f, +0xb4, 0x06, 0x14, 0x93, 0x00, 0x02, 0xc8, 0x0f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x47, 0x80, 0xd1, +0x14, 0x64, 0x00, 0x01, 0xb7, 0x06, 0xa9, 0x31, 0xb6, 0xc4, 0x04, 0x14, 0x00, 0x02, 0x9c, 0xc9, +0x14, 0x34, 0x00, 0x02, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x40, 0xa0, 0x33, 0x84, 0x20, 0xa8, 0x72, 0xb6, 0xc6, +0xa9, 0xb1, 0xc8, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x0c, 0xdd, 0x2f, 0xa8, 0x33, +0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x7c, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, 0xa0, 0x32, 0xc8, 0x02, 0xd5, 0x09, +0x9e, 0x01, 0xa8, 0x32, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xec, 0xdd, 0x2f, +0x80, 0xc0, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0x80, 0x06, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xc0, +0x50, 0x0f, 0x80, 0x04, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, +0xa0, 0xb2, 0x80, 0x06, 0x9c, 0x51, 0xa8, 0x72, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8e, 0xe0, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, +0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x03, 0x54, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xd8, 0xdd, 0x2f, 0x46, 0x70, +0x00, 0x0b, 0x58, 0x73, 0x86, 0x70, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x00, 0xa0, 0x46, 0x80, +0x00, 0x00, 0x58, 0x84, 0x03, 0x68, 0xa9, 0xf2, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x03, 0x54, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x73, 0x86, 0x40, 0x46, 0x50, 0x00, 0x0d, 0x58, 0x52, +0x8b, 0xf0, 0x8c, 0xd8, 0xdf, 0xf1, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8e, 0xd8, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0x0d, 0x58, 0x73, 0x8b, 0xf0, +0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x01, 0x30, 0x46, 0x80, 0x00, 0x00, 0x58, 0x84, 0x03, 0x68, +0xa9, 0xf2, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0x4b, 0xe0, 0x20, 0x01, +0x50, 0x73, 0x80, 0xc8, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x80, 0xa0, 0x8c, 0xd8, 0xdf, 0xf1, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x30, 0x04, 0x00, +0xb4, 0x43, 0x44, 0x50, 0x76, 0x10, 0x40, 0x01, 0x40, 0x09, 0xd8, 0x07, 0x83, 0xc3, 0x04, 0x5f, +0x00, 0x41, 0x42, 0x42, 0xd0, 0x0b, 0xc4, 0x0f, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x82, 0x88, +0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x07, 0x86, 0x64, 0x46, 0xf0, 0x00, 0x0b, +0x10, 0x07, 0x86, 0x63, 0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x04, 0xe4, 0x44, 0x00, 0x00, 0x10, +0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x87, 0x24, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x11, 0x46, 0x10, +0x00, 0x03, 0x58, 0x10, 0x87, 0x34, 0xdd, 0x26, 0x84, 0x00, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, +0x87, 0x44, 0xdd, 0x26, 0x84, 0x01, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x87, 0x54, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x19, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x87, 0x64, 0xdd, 0x26, 0x46, 0x10, +0x00, 0x03, 0x58, 0x10, 0x88, 0x60, 0x44, 0x00, 0x00, 0x18, 0xdd, 0x26, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x83, 0xa8, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x46, 0xf0, +0x00, 0x03, 0x58, 0xf7, 0x86, 0x30, 0xdd, 0x2f, 0x84, 0xc0, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8f, 0x34, 0xdd, 0x2f, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x83, 0x74, 0x84, 0x80, 0x10, 0x41, +0x82, 0xac, 0x14, 0x61, 0x80, 0x2d, 0x50, 0x01, 0x82, 0xae, 0x80, 0x26, 0x84, 0x48, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x10, 0x58, 0x31, 0x88, 0x00, +0xa9, 0x9c, 0x46, 0x00, 0x30, 0x00, 0xa1, 0x5b, 0x40, 0x42, 0x80, 0x04, 0xa9, 0x1b, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0x3c, 0x96, 0x00, 0x96, 0x48, 0x95, 0x82, 0x99, 0x71, +0x44, 0x32, 0x0d, 0x60, 0x99, 0x2b, 0x00, 0x31, 0x00, 0x40, 0x95, 0x25, 0x84, 0xa0, 0x38, 0x71, +0x14, 0x00, 0x99, 0xac, 0xaf, 0xf0, 0x9d, 0x69, 0x44, 0x70, 0x00, 0x10, 0xdf, 0xf9, 0x9b, 0x94, +0x50, 0x52, 0x00, 0x18, 0x50, 0x22, 0x00, 0x10, 0x38, 0x73, 0x08, 0x00, 0x18, 0x71, 0x00, 0x01, +0xda, 0xfc, 0x50, 0x42, 0x00, 0x20, 0x38, 0x23, 0x14, 0x00, 0x18, 0x22, 0x80, 0x01, 0xdc, 0xfc, +0x46, 0x40, 0x01, 0x06, 0x40, 0x20, 0x04, 0x09, 0x58, 0x42, 0x0c, 0x00, 0x99, 0x54, 0x94, 0xaa, +0x97, 0x04, 0xb4, 0x02, 0xcc, 0x1d, 0xc9, 0x05, 0x54, 0x31, 0x80, 0x0f, 0x84, 0xd0, 0xd5, 0x39, +0x84, 0xa1, 0xd9, 0x07, 0x54, 0x11, 0x80, 0x0f, 0x94, 0xcc, 0x44, 0x6f, 0xff, 0x0f, 0xd5, 0x31, +0x84, 0x82, 0x54, 0x31, 0x80, 0x0f, 0x4c, 0x12, 0x40, 0x07, 0x40, 0x31, 0xa0, 0x08, 0x44, 0x6f, +0xf0, 0xff, 0xd5, 0x27, 0x40, 0x31, 0xb0, 0x08, 0x44, 0x1f, 0x0f, 0xff, 0xd5, 0x2b, 0xc9, 0x0c, +0x46, 0x5f, 0xff, 0x0f, 0x54, 0x31, 0x80, 0x0f, 0x58, 0x52, 0x8f, 0xff, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x00, 0x14, 0x02, 0xd5, 0x21, 0x84, 0xa1, 0xd9, 0x0a, 0x54, 0x11, 0x80, 0x0f, 0x40, 0x30, +0xd0, 0x08, 0x46, 0x1f, 0xf0, 0xff, 0x58, 0x10, 0x8f, 0xff, 0xd5, 0x14, 0x84, 0xa2, 0xd9, 0x0c, +0x54, 0x61, 0x80, 0x0f, 0x40, 0x33, 0x60, 0x08, 0x46, 0x6f, 0x0f, 0xff, 0x58, 0x63, 0x0f, 0xff, +0x40, 0x00, 0x18, 0x02, 0xd5, 0x09, 0x46, 0x10, 0xff, 0xff, 0x40, 0x31, 0xf0, 0x08, 0x58, 0x10, +0x8f, 0xff, 0x40, 0x00, 0x04, 0x02, 0x40, 0x00, 0x0c, 0x04, 0xb6, 0x02, 0x3a, 0x6f, 0x9c, 0x04, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x02, 0x10, 0x00, 0x0a, 0xa1, 0x84, +0x5c, 0xf0, 0x80, 0x66, 0xe9, 0x2a, 0x51, 0xc0, 0xff, 0x9a, 0x84, 0xe0, 0x46, 0xa0, 0x01, 0x02, +0x58, 0xa5, 0x06, 0xd4, 0x80, 0x06, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x85, 0x14, 0x84, 0x46, +0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x15, 0x81, 0x20, 0x50, 0x83, 0x00, 0x06, 0x80, 0x08, 0x46, 0x10, +0x00, 0x0e, 0x58, 0x10, 0x86, 0x2c, 0x84, 0x46, 0x8d, 0x21, 0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x09, +0x44, 0x50, 0x00, 0x10, 0x8d, 0x06, 0x4c, 0x92, 0xff, 0xf3, 0x84, 0x01, 0xd5, 0x07, 0x9d, 0xb1, +0x9d, 0xf9, 0x40, 0xfe, 0x1c, 0x06, 0xe8, 0xdf, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x44, 0x30, 0x01, 0x0c, 0x54, 0xa0, +0x80, 0xff, 0x42, 0x65, 0x0c, 0x24, 0x54, 0x91, 0x00, 0xff, 0x44, 0x20, 0x00, 0x43, 0x42, 0x64, +0x88, 0x73, 0x97, 0xc0, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xa4, 0x99, 0xb0, 0x84, 0x20, +0x97, 0x20, 0x80, 0x06, 0x81, 0x05, 0xf4, 0x81, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, +0xdd, 0x2f, 0x84, 0x24, 0x4c, 0x70, 0xc0, 0x04, 0x84, 0x03, 0xd5, 0x09, 0x84, 0x46, 0x4c, 0x71, +0x40, 0x04, 0x84, 0x04, 0xd5, 0x04, 0x84, 0xab, 0xdf, 0x04, 0x84, 0x02, 0x10, 0x03, 0x00, 0x40, +0x41, 0xe0, 0x88, 0x08, 0x11, 0xe3, 0x00, 0x41, 0x80, 0x28, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, +0x86, 0xa4, 0x80, 0x06, 0x80, 0x5e, 0xdd, 0x27, 0x01, 0xc3, 0x00, 0x40, 0x84, 0x23, 0x4d, 0xc0, +0xc0, 0x1b, 0xf4, 0x01, 0x50, 0x54, 0x00, 0x18, 0x50, 0x33, 0x00, 0x10, 0x8d, 0x10, 0x51, 0xc3, +0x00, 0x18, 0xc4, 0x09, 0xb6, 0xbf, 0x80, 0x03, 0x80, 0x28, 0x84, 0x48, 0xdd, 0x27, 0xb4, 0x3f, +0x80, 0x1c, 0xd5, 0x07, 0x80, 0x25, 0x80, 0x03, 0x84, 0x48, 0xdd, 0x27, 0x80, 0x1c, 0x80, 0x28, +0x84, 0x48, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x29, 0x80, 0x46, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x85, 0x44, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x30, 0x01, 0x0c, 0x97, 0x00, 0x42, 0x62, 0x0c, 0x24, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, +0x04, 0xa4, 0x99, 0xb2, 0x81, 0x01, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x43, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x85, 0xb1, +0x84, 0xa4, 0xd8, 0x03, 0x84, 0x03, 0xd5, 0x04, 0x84, 0xa6, 0xd8, 0x24, 0x84, 0x04, 0x45, 0xe0, +0x00, 0x10, 0x10, 0x03, 0x00, 0x40, 0x11, 0xe3, 0x00, 0x41, 0x50, 0x14, 0x00, 0x20, 0x46, 0x70, +0x01, 0x02, 0x58, 0x73, 0x86, 0xa4, 0x80, 0x06, 0x80, 0x5e, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x03, +0x00, 0x40, 0x84, 0xa3, 0xd8, 0x0f, 0x50, 0x14, 0x00, 0x38, 0x84, 0x48, 0x50, 0x03, 0x00, 0x10, +0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x03, 0x00, 0x18, 0x50, 0x14, 0x00, 0x30, 0x84, 0x48, 0x4b, 0xe0, +0x1c, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x97, 0x20, +0x55, 0xc0, 0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0x96, 0xd8, 0xc4, 0x44, 0x84, 0x23, 0x4c, 0x30, +0x80, 0x05, 0x84, 0x45, 0x4c, 0x31, 0x40, 0x70, 0x85, 0x40, 0x80, 0xe0, 0x81, 0x2a, 0x81, 0x0a, +0x80, 0xdf, 0xd5, 0x30, 0xa6, 0x38, 0x44, 0x30, 0x00, 0xdd, 0x4c, 0x01, 0xc0, 0x26, 0x9c, 0x3a, +0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x84, 0xf0, 0x84, 0x43, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x86, 0xd4, 0xdd, 0x2f, 0xc8, 0x19, 0xa7, 0x7d, 0x87, 0xc1, 0x4c, 0x5f, 0x40, 0x16, 0xa7, 0x39, +0x00, 0x93, 0x80, 0x06, 0x50, 0x82, 0x7f, 0xfa, 0x54, 0x84, 0x00, 0xff, 0x50, 0x13, 0x80, 0x08, +0x80, 0x1f, 0x80, 0x48, 0x54, 0x94, 0x80, 0x03, 0xe7, 0x10, 0xe9, 0x40, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xa6, 0xb9, 0x9c, 0x52, 0x89, 0x41, 0x99, 0xf9, 0x54, 0xa5, +0x00, 0xff, 0xa7, 0x79, 0x9c, 0xea, 0x40, 0x01, 0xa8, 0x00, 0x40, 0xfe, 0x00, 0x07, 0xe8, 0xcb, +0xd5, 0x0f, 0x84, 0xc5, 0x4c, 0x33, 0x40, 0x30, 0x80, 0x20, 0x80, 0x5c, 0x80, 0x1f, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xe7, 0x24, 0xe8, 0x20, 0x81, 0x1c, 0x46, 0x60, +0x00, 0x0e, 0x58, 0x63, 0x03, 0x74, 0x80, 0x48, 0x80, 0x3f, 0x50, 0x03, 0x01, 0x10, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x84, 0x20, 0x00, 0x03, 0x02, 0x3e, 0x10, 0x93, +0x02, 0x3c, 0x80, 0x49, 0x50, 0x53, 0x01, 0x10, 0x80, 0x61, 0x80, 0x81, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x85, 0x20, 0x81, 0x09, 0xd5, 0xdb, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x94, 0x85, 0x40, 0x80, 0xc2, 0x55, 0xc0, 0x00, 0xff, 0x44, 0x00, 0x02, 0x00, 0x81, 0x21, +0x14, 0xaf, 0x80, 0x19, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0x08, 0xdd, 0x2f, 0xa7, 0x32, +0xa6, 0x73, 0x40, 0x32, 0x20, 0x08, 0x40, 0x21, 0x84, 0x04, 0x9c, 0x94, 0x50, 0x1f, 0x80, 0x64, +0x80, 0x66, 0x84, 0x9f, 0x50, 0x8f, 0x80, 0x54, 0x80, 0xe0, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8d, 0x54, 0xdd, 0x2f, 0x80, 0x2a, 0x80, 0x08, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x84, 0x02, 0x4d, 0xc0, 0x40, 0x1a, 0x50, 0xaf, 0x80, 0x04, +0xf3, 0x19, 0x80, 0x09, 0x80, 0x47, 0x80, 0x8a, 0x44, 0x50, 0x00, 0x14, 0x9e, 0x6c, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x82, 0x80, 0xdd, 0x2f, 0x80, 0x08, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xd5, 0x0d, 0x44, 0x10, 0x00, 0x10, +0xf3, 0x19, 0x80, 0x09, 0x80, 0x88, 0x80, 0x47, 0x80, 0xa1, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x81, 0x3c, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x54, 0x44, 0x20, 0x00, 0x10, 0x50, 0x03, 0x00, 0x51, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x87, 0x85, 0xb3, 0xf6, 0x0c, +0x84, 0xe3, 0x85, 0x21, 0x84, 0xa0, 0x44, 0x00, 0x00, 0x5f, 0xaf, 0xf1, 0x10, 0x93, 0x00, 0x00, +0xaf, 0x72, 0xae, 0x33, 0x83, 0x83, 0xf4, 0x81, 0x97, 0xc8, 0x96, 0x90, 0x4e, 0x82, 0x00, 0x04, +0x84, 0x02, 0xd5, 0x02, 0x84, 0x1e, 0xae, 0x34, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x85, 0xb4, +0xc1, 0x03, 0x85, 0x23, 0xd5, 0x0d, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, 0x85, 0xb1, 0x84, 0x81, +0x56, 0x3f, 0x00, 0x06, 0x85, 0x42, 0x40, 0x95, 0x0c, 0x1a, 0x40, 0x92, 0x0c, 0x1b, 0xa7, 0x76, +0x40, 0x02, 0x8c, 0x09, 0x94, 0x03, 0x40, 0x00, 0x24, 0x04, 0xae, 0x36, 0xe6, 0xe5, 0xe9, 0x04, +0x42, 0x00, 0x0c, 0x09, 0xd5, 0x03, 0x58, 0x00, 0x00, 0x08, 0xae, 0x36, 0x4e, 0x83, 0x00, 0x14, +0xe6, 0xe5, 0xe9, 0x11, 0xa7, 0x76, 0x54, 0x11, 0x00, 0x03, 0x44, 0x3f, 0xff, 0xcf, 0x94, 0x0c, +0x41, 0xe2, 0x8c, 0x02, 0x40, 0xaf, 0x00, 0x04, 0x84, 0x43, 0x10, 0xa3, 0x00, 0x06, 0x4c, 0x71, +0x40, 0x0f, 0xd5, 0x0f, 0x84, 0x83, 0x4c, 0x72, 0x40, 0x08, 0x00, 0xa3, 0x00, 0x06, 0x58, 0x25, +0x00, 0x40, 0xae, 0xb6, 0xd5, 0x06, 0x87, 0xc1, 0x4c, 0x7f, 0x00, 0x04, 0x84, 0xa5, 0xdf, 0x09, +0xa7, 0x36, 0x44, 0x1f, 0xff, 0x80, 0x40, 0x32, 0x04, 0x04, 0x84, 0xa1, 0xae, 0xf6, 0xd7, 0x06, +0x00, 0xa3, 0x00, 0x05, 0x58, 0x25, 0x00, 0x01, 0xae, 0xb5, 0x4e, 0x82, 0x00, 0x05, 0xe6, 0xe3, +0xe8, 0x04, 0xd5, 0x0c, 0xe6, 0xe5, 0xe9, 0x17, 0xa6, 0x35, 0x59, 0xe0, 0x00, 0x02, 0x11, 0xe3, +0x00, 0x05, 0x4e, 0x82, 0x00, 0x11, 0x84, 0xa3, 0xd7, 0x03, 0x84, 0xa5, 0xdf, 0x05, 0xa6, 0x75, +0x58, 0x40, 0x80, 0x10, 0xaf, 0x35, 0x4e, 0x82, 0x00, 0x07, 0x84, 0x41, 0x4c, 0x71, 0x00, 0x04, +0x84, 0xa3, 0xdf, 0x10, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x47, 0x85, 0xb1, 0x44, 0x00, 0x00, 0x10, +0x56, 0x32, 0x00, 0x04, 0x95, 0x41, 0x41, 0xe2, 0x8c, 0x1a, 0x41, 0xe0, 0x0c, 0x1b, 0x11, 0xe3, +0x00, 0x08, 0x50, 0x03, 0x00, 0x09, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0x3c, 0x84, 0x48, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xe6, 0xe4, 0xe9, 0x05, 0x4e, 0x83, +0x00, 0x26, 0x84, 0xa5, 0xdf, 0x23, 0x46, 0xa0, 0x01, 0x02, 0x58, 0xa5, 0x06, 0xa4, 0x50, 0x03, +0x00, 0x11, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x20, 0x4b, 0xe0, 0x28, 0x01, 0x4e, 0x83, 0x00, 0x12, +0x84, 0xa5, 0xdf, 0x0f, 0x50, 0x1e, 0x00, 0x10, 0x50, 0x03, 0x00, 0x31, 0x44, 0x20, 0x00, 0x10, +0x4b, 0xe0, 0x28, 0x01, 0x00, 0x53, 0x00, 0x40, 0x9c, 0x2a, 0x10, 0x03, 0x00, 0x40, 0xd5, 0x08, +0x84, 0xa3, 0xdf, 0x04, 0x4e, 0x83, 0x00, 0x05, 0xd5, 0x0c, 0x84, 0xa5, 0xdf, 0x0a, 0xf1, 0x01, +0x50, 0x03, 0x00, 0x41, 0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, +0x84, 0x20, 0x50, 0x03, 0x00, 0x51, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x87, 0x08, 0xdd, 0x2f, 0x84, 0xa1, 0xd7, 0x0c, 0x80, 0x09, 0x80, 0x46, 0x46, 0x10, 0x00, 0x0e, +0x58, 0x10, 0x84, 0x44, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x89, 0x0c, 0xdd, 0x2f, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0x84, 0x46, 0x80, +0x01, 0x02, 0x58, 0x84, 0x07, 0x08, 0x50, 0x60, 0x00, 0x5b, 0x84, 0x20, 0x97, 0xd0, 0x50, 0x0f, +0x81, 0x60, 0x44, 0x20, 0x00, 0x10, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x20, 0x00, 0x50, 0x50, 0x0f, +0x81, 0x00, 0xdd, 0x28, 0x50, 0x9f, 0x81, 0x74, 0x84, 0x20, 0x44, 0x20, 0x00, 0xff, 0x80, 0x1f, +0xdd, 0x28, 0x84, 0x20, 0x84, 0x42, 0x80, 0x09, 0xdd, 0x28, 0x50, 0x13, 0x7f, 0xaa, 0x80, 0x09, +0x84, 0x42, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x84, 0x01, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x87, 0x85, 0xb3, 0x4c, 0x70, 0x00, 0x08, 0x84, 0x43, 0x4c, 0x71, 0x00, 0x05, +0x84, 0x65, 0x4c, 0x71, 0xc0, 0x26, 0x51, 0xcf, 0x81, 0x50, 0x84, 0x20, 0x84, 0x48, 0x80, 0x1c, +0x50, 0xa3, 0x7f, 0xae, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x46, 0x90, +0x00, 0x02, 0x58, 0x94, 0x89, 0xb8, 0x80, 0x0a, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0x3c, +0x84, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x81, 0x4c, 0x02, 0x00, 0x09, 0x80, 0x0a, 0x80, 0x3c, +0x84, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x4e, 0x03, 0x00, 0xcc, 0x84, 0xa1, 0xd7, 0x6a, 0x00, 0xa3, +0x7f, 0xa7, 0x00, 0x93, 0x7f, 0xa8, 0x41, 0xe5, 0x20, 0x08, 0x50, 0xa3, 0x7f, 0xf6, 0x41, 0xcf, +0x24, 0x04, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x46, 0x90, 0x01, 0x02, 0x58, 0x94, 0x86, 0xa4, +0x50, 0x0f, 0x81, 0x50, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x20, 0x80, 0x0a, 0x44, 0x20, 0x00, 0x10, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x00, 0x0f, 0x81, 0x75, 0x84, 0x21, +0x54, 0x00, 0x00, 0x07, 0x51, 0xce, 0x00, 0x04, 0x4c, 0x00, 0xc0, 0x18, 0x46, 0x90, 0x00, 0x0e, +0x58, 0x94, 0x83, 0x74, 0x85, 0x44, 0x8c, 0x2f, 0x10, 0xa4, 0x82, 0x3d, 0x50, 0x04, 0x80, 0xd0, +0x80, 0x7c, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x60, 0x80, 0xa1, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0xd5, 0x21, 0x84, 0x42, 0x4c, 0x01, 0x40, 0x1f, 0x46, 0xa0, +0x00, 0x0e, 0x58, 0xa5, 0x03, 0x74, 0x80, 0x7c, 0x87, 0x86, 0x11, 0xc5, 0x02, 0x3d, 0x50, 0x05, +0x00, 0xd0, 0x8c, 0x2f, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x00, 0x9d, 0x4c, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x82, 0x80, 0xdd, 0x2f, 0x50, 0x1f, 0x81, 0x00, 0x50, 0x0f, 0x81, 0x60, +0x44, 0x20, 0x00, 0x10, 0x4b, 0xe0, 0x24, 0x01, 0x50, 0x0f, 0x81, 0x50, 0x50, 0x1f, 0x81, 0x60, +0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, 0xdd, 0x2f, 0xc8, 0x60, +0xa7, 0x76, 0xa7, 0x37, 0x40, 0x32, 0xa0, 0x08, 0x40, 0x31, 0x90, 0x04, 0x4e, 0x36, 0x00, 0x04, +0x84, 0x01, 0xd5, 0x57, 0x84, 0x23, 0x4c, 0x70, 0xc0, 0x05, 0x4e, 0x83, 0x00, 0x06, 0xd5, 0x42, +0x84, 0x05, 0x4c, 0x70, 0x40, 0x40, 0x00, 0x5f, 0x81, 0x75, 0x84, 0x42, 0x55, 0xe2, 0x80, 0x07, +0x80, 0x9f, 0x50, 0x03, 0x00, 0x08, 0x4d, 0xe1, 0x40, 0x1e, 0xa6, 0x76, 0x01, 0xe3, 0x00, 0x07, +0x40, 0x90, 0xa0, 0x08, 0x40, 0x14, 0xf8, 0x04, 0x94, 0xd3, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, +0x04, 0x54, 0x50, 0x5f, 0x81, 0x70, 0x85, 0x20, 0x14, 0x9f, 0x80, 0x5c, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x8f, 0xc4, 0xdd, 0x2f, 0xf3, 0x5c, 0x00, 0x4f, 0x81, 0x71, 0xae, 0xf7, 0xaf, 0x36, +0xd5, 0x0d, 0x80, 0x40, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0x54, 0x50, 0x13, 0x7f, 0xd6, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, 0x4e, 0x83, 0x00, 0x0c, 0x84, 0x05, +0x4c, 0x70, 0x40, 0x09, 0x00, 0x5f, 0x81, 0x75, 0x40, 0x22, 0x90, 0x09, 0x54, 0x21, 0x00, 0x03, +0xd5, 0x02, 0x84, 0x40, 0xa6, 0x77, 0x80, 0x67, 0x80, 0x88, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x88, 0x08, 0xdd, 0x2f, 0x84, 0x60, 0x40, 0x01, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, +0xed, 0x7c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x46, 0x90, +0x00, 0x0e, 0x58, 0x94, 0x83, 0x74, 0x00, 0x34, 0x82, 0x3d, 0x80, 0xc1, 0x80, 0xe0, 0x80, 0x22, +0x80, 0x06, 0x84, 0x45, 0xf3, 0x85, 0x01, 0xc4, 0x82, 0x3c, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x8b, 0xc8, 0xdd, 0x2f, 0x80, 0x60, 0xc8, 0x0b, 0x46, 0x02, 0x00, 0x00, 0x80, 0x23, 0x80, 0x47, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xd5, 0x69, 0x50, 0x13, 0x00, 0x09, +0x84, 0x48, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, 0x06, 0xa4, 0x50, 0x04, 0x80, 0xc8, 0xdd, 0x28, +0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x89, 0x70, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x03, 0x54, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x81, 0x40, 0xc0, 0x4f, +0xa1, 0xc2, 0xc7, 0x4d, 0x84, 0xc0, 0x80, 0x26, 0x44, 0x20, 0x04, 0x00, 0x80, 0x07, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xf0, 0x05, 0x80, 0x66, 0x80, 0x86, 0x80, 0xa6, +0x80, 0x5c, 0x84, 0x26, 0x51, 0xc3, 0x80, 0x0e, 0xb6, 0xdf, 0xf6, 0x81, 0x15, 0xcf, 0x80, 0x02, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x89, 0xe0, 0xdd, 0x2f, 0x50, 0x14, 0x82, 0x41, 0x84, 0x46, +0x50, 0x0f, 0x80, 0x18, 0xdd, 0x28, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0x2c, 0x84, 0x46, +0x50, 0x0f, 0x80, 0x1e, 0xdd, 0x28, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x85, 0x08, 0x84, 0x42, +0x50, 0x0f, 0x80, 0x24, 0xdd, 0x28, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x03, 0x40, 0x81, +0x20, 0x08, 0x40, 0x84, 0x00, 0x04, 0x50, 0x1f, 0x80, 0x18, 0x84, 0x4e, 0x80, 0x07, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, 0x50, 0x14, 0x00, 0x12, 0x80, 0x0a, 0x96, 0x49, +0x80, 0x46, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x85, 0x28, 0xdd, 0x2f, 0xec, 0x2c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x50, 0x6f, 0x80, 0x04, 0x80, 0xe1, +0x81, 0x00, 0x84, 0x20, 0x81, 0x22, 0x80, 0x06, 0x84, 0x42, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x87, 0x08, 0xdd, 0x2f, 0x80, 0x06, 0x9c, 0x7d, 0x84, 0x42, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x86, 0xa4, 0xdd, 0x2f, 0xa6, 0xf1, 0x54, 0x01, 0x80, 0x80, 0xc0, 0x29, 0xa7, 0x30, 0x54, 0x12, +0x00, 0x0e, 0xc9, 0x16, 0x54, 0x21, 0x80, 0x08, 0xc2, 0x13, 0x96, 0x64, 0xc9, 0x20, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x47, 0x81, 0x74, 0x54, 0x32, 0x02, 0x00, 0xc3, 0x19, 0x46, 0x04, 0x00, 0x00, +0x80, 0x48, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xd5, 0x10, 0x54, 0x02, +0x00, 0x0f, 0x84, 0xa3, 0xd8, 0x0c, 0x54, 0x11, 0x80, 0x08, 0xc9, 0x09, 0x80, 0x08, 0x80, 0x27, +0x80, 0x49, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8e, 0x18, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x9c, 0x80, 0xc0, 0x44, 0x00, 0x00, 0x10, +0xf3, 0x83, 0xf2, 0x88, 0xf4, 0x89, 0xf5, 0x8a, 0x4c, 0x30, 0x00, 0x0d, 0x44, 0x20, 0x00, 0x18, +0x4c, 0x31, 0x00, 0x09, 0x41, 0xe0, 0x04, 0x08, 0x4c, 0x3f, 0x00, 0x05, 0x84, 0x1f, 0x48, 0x00, +0x00, 0xa2, 0x8e, 0x28, 0x80, 0x01, 0x84, 0xe0, 0xf1, 0x81, 0xf7, 0x97, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8f, 0x08, 0xdd, 0x2f, 0xf0, 0x82, 0xc8, 0x04, 0x84, 0x1e, 0x48, 0x00, 0x00, 0x93, +0x50, 0x0f, 0x80, 0x54, 0x46, 0xa0, 0x01, 0x02, 0x58, 0xa5, 0x06, 0xa4, 0x80, 0x26, 0x84, 0x48, +0x4b, 0xe0, 0x28, 0x01, 0xf2, 0x01, 0xf0, 0x02, 0x40, 0x91, 0x0c, 0x09, 0x50, 0x13, 0x00, 0x08, +0x4b, 0xe0, 0x28, 0x01, 0x84, 0xe5, 0x54, 0x04, 0x80, 0xff, 0x80, 0x89, 0x42, 0x40, 0x1c, 0x73, +0x40, 0x24, 0x8c, 0x08, 0x05, 0xef, 0x80, 0x02, 0x50, 0x31, 0x7f, 0xf8, 0x52, 0x50, 0x00, 0x00, +0x54, 0x82, 0x80, 0xff, 0x55, 0xc2, 0x00, 0xff, 0x40, 0xaf, 0x0c, 0x00, 0x50, 0x64, 0xff, 0xff, +0x14, 0x8f, 0x80, 0x07, 0x15, 0xcf, 0x80, 0x04, 0xf7, 0x85, 0x14, 0xaf, 0x80, 0x0b, 0xf6, 0x86, +0xf6, 0x06, 0x04, 0xaf, 0x80, 0x0b, 0x05, 0xcf, 0x80, 0x04, 0x46, 0x90, 0x01, 0x02, 0x58, 0x94, +0x86, 0xa4, 0x50, 0x8f, 0x80, 0x5c, 0x50, 0x7f, 0x80, 0x4c, 0xd5, 0x2f, 0xa7, 0x0f, 0x9f, 0xb1, +0x40, 0x3e, 0x10, 0x03, 0xae, 0xcf, 0xdd, 0x29, 0x80, 0x2a, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x3c, +0xdd, 0x29, 0xf3, 0x03, 0x46, 0xf0, 0x00, 0x0b, 0x04, 0x17, 0x80, 0xf8, 0xf2, 0x08, 0x45, 0xe0, +0x00, 0x10, 0x50, 0x4f, 0x80, 0x44, 0x80, 0xa8, 0x50, 0x0f, 0x80, 0x34, 0x15, 0xef, 0x80, 0x17, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x88, 0xac, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x44, 0x84, 0x48, +0x50, 0x0f, 0x80, 0x54, 0xdd, 0x29, 0x80, 0x0a, 0x80, 0x27, 0x84, 0x48, 0xdd, 0x29, 0x50, 0x1e, +0x7f, 0xff, 0x55, 0xc0, 0x80, 0xff, 0x8f, 0x48, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x34, 0x50, 0x1f, +0x80, 0x54, 0x4e, 0x64, 0xff, 0xcd, 0x05, 0xef, 0x80, 0x04, 0xf4, 0x07, 0xf1, 0x05, 0x40, 0x3f, +0x10, 0x00, 0x9e, 0x89, 0x96, 0x18, 0x84, 0xbf, 0xf2, 0x85, 0xf0, 0x84, 0xda, 0xb2, 0xf2, 0x01, +0xf5, 0x0a, 0xb6, 0x45, 0xf2, 0x01, 0xf1, 0x02, 0xf0, 0x09, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x86, 0xa4, 0xdd, 0x2f, 0xf0, 0x02, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x64, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xee, 0xe4, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x87, 0x08, +0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x68, 0x81, 0x44, 0x81, 0x25, +0x50, 0x8f, 0x80, 0xc8, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x50, 0x0f, +0x80, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x4b, 0xe0, +0x1c, 0x01, 0x5c, 0xf3, 0x00, 0x41, 0xe8, 0x0f, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x46, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x50, 0x6f, 0x80, 0xc8, 0x51, 0xcf, 0x81, 0x08, +0x80, 0xe6, 0xd5, 0x0a, 0x80, 0x1c, 0x80, 0x26, 0x80, 0x48, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, +0x8e, 0x98, 0xdd, 0x2f, 0xd5, 0xf2, 0xa6, 0x78, 0x56, 0x00, 0x80, 0x36, 0x18, 0x03, 0x80, 0x01, +0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x68, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, +0x8e, 0x54, 0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x0d, 0xc0, 0x80, 0x07, 0x50, 0x1f, +0x80, 0xc8, 0x44, 0x20, 0x00, 0x40, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0x3f, 0xf2, 0x01, 0x80, 0x07, +0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x08, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, +0x8d, 0x48, 0xdd, 0x2f, 0xa6, 0xf0, 0x56, 0x21, 0x80, 0x6a, 0x18, 0x23, 0x00, 0x01, 0x4c, 0x6e, +0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x08, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8e, 0x54, +0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x0d, 0xc0, 0x80, 0x07, 0x50, 0x1f, 0x80, 0xc8, +0x44, 0x20, 0x00, 0x40, 0x50, 0x6f, 0x81, 0x08, 0x4b, 0xe0, 0x20, 0x01, 0x44, 0x20, 0x00, 0x10, +0x80, 0x07, 0x80, 0x26, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x80, 0x26, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x8d, 0x48, 0xdd, 0x2f, 0x46, 0x30, 0x01, 0x02, 0x58, 0x31, 0x86, 0xa4, 0xe7, 0x31, +0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0xd5, 0x04, 0x80, 0x0a, 0x80, 0x26, +0x80, 0x49, 0x4b, 0xe0, 0x0c, 0x01, 0xed, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xcc, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, 0x46, 0x70, 0x01, 0x02, +0x58, 0x73, 0x87, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x68, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x70, +0x81, 0x44, 0x81, 0x25, 0x50, 0x8f, 0x80, 0xdc, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0x44, 0x20, +0x00, 0x68, 0x50, 0x0f, 0x80, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, +0x00, 0x40, 0x4b, 0xe0, 0x1c, 0x01, 0x5c, 0xf3, 0x00, 0x41, 0xe8, 0x0f, 0x80, 0x08, 0x80, 0x3c, +0x80, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x50, 0x6f, 0x80, 0xdc, +0x51, 0xcf, 0x81, 0x1c, 0x80, 0xe6, 0xd5, 0x0a, 0x80, 0x1c, 0x80, 0x26, 0x80, 0x48, 0x46, 0xf0, +0x01, 0x03, 0x58, 0xf7, 0x81, 0xbc, 0xdd, 0x2f, 0xd5, 0xf2, 0xa6, 0x78, 0x56, 0x00, 0x80, 0x36, +0x18, 0x03, 0x80, 0x01, 0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x70, 0x80, 0x07, 0x46, 0xf0, +0x01, 0x03, 0x58, 0xf7, 0x81, 0x78, 0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0xe4, +0x80, 0x07, 0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0x3f, +0xf2, 0x01, 0x80, 0x07, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x1c, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x8f, 0xd8, 0xdd, 0x2f, 0xa6, 0xf0, 0x56, 0x21, 0x80, 0x6a, 0x18, 0x23, +0x00, 0x01, 0x4c, 0x6e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x08, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x81, 0x78, 0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0xe4, 0x80, 0x07, +0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x50, 0x6f, 0x81, 0x1c, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x20, 0x00, 0x14, 0x80, 0x07, 0x80, 0x26, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x80, 0x26, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x8f, 0xd8, 0xdd, 0x2f, 0x46, 0x30, 0x01, 0x02, 0x58, 0x31, +0x86, 0xa4, 0xe7, 0x35, 0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x14, 0xd5, 0x04, +0x80, 0x0a, 0x80, 0x26, 0x80, 0x49, 0x4b, 0xe0, 0x0c, 0x01, 0xed, 0x34, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x20, 0x00, 0x80, 0x58, 0x21, 0x00, 0x50, 0x46, 0x50, 0x04, 0x00, +0x98, 0xc2, 0x58, 0x52, 0x82, 0x7c, 0x94, 0x03, 0x84, 0x40, 0x99, 0x05, 0x94, 0xdb, 0xb6, 0x44, +0xb6, 0x43, 0x50, 0x22, 0xff, 0xf4, 0x44, 0x30, 0x00, 0xff, 0x40, 0x51, 0x80, 0x0c, 0xb4, 0x82, +0x40, 0x32, 0x94, 0x05, 0x40, 0x51, 0x90, 0x02, 0x96, 0x48, 0x84, 0x61, 0xb6, 0xa2, 0x4c, 0x11, +0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xdf, 0x40, 0x41, +0x80, 0x0c, 0x40, 0x02, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x50, 0x00, 0x80, +0x58, 0x52, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, 0x98, 0x85, 0x58, 0x42, 0x02, 0x7c, 0x94, 0x03, +0x99, 0x44, 0x94, 0x93, 0x44, 0x31, 0x00, 0x00, 0x84, 0x80, 0xb6, 0x65, 0xb6, 0x82, 0x46, 0x20, +0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x44, 0x30, 0x00, 0xff, 0x40, 0x51, 0x80, 0x0c, 0xb4, 0x82, +0x40, 0x32, 0x94, 0x05, 0x40, 0x51, 0x90, 0x02, 0x96, 0x48, 0x84, 0x61, 0xb6, 0xa2, 0x4c, 0x11, +0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xdf, 0x40, 0x41, +0x80, 0x0c, 0x40, 0x02, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x40, 0x04, 0x00, +0x46, 0x20, 0x30, 0x70, 0x80, 0xa4, 0x58, 0x21, 0x03, 0x07, 0x14, 0x22, 0x00, 0x9d, 0x14, 0x22, +0x80, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x44, 0x30, 0x00, 0xff, 0x94, 0x03, +0x40, 0x51, 0x80, 0x0c, 0xb4, 0x82, 0x40, 0x32, 0x94, 0x05, 0x40, 0x51, 0x90, 0x02, 0x96, 0x48, +0x84, 0x61, 0xb6, 0xa2, 0x4c, 0x11, 0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x86, 0xd5, 0x04, +0xb4, 0x22, 0x44, 0x30, 0x00, 0x84, 0x40, 0x51, 0x80, 0x0c, 0x40, 0x02, 0x84, 0x04, 0xb6, 0x02, +0xdd, 0x9e, 0x92, 0x00, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x41, 0x90, 0x04, 0x40, 0x21, 0x40, 0x08, +0x46, 0x50, 0x00, 0x80, 0x40, 0x22, 0x08, 0x04, 0x58, 0x52, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, +0x98, 0xc5, 0x58, 0x42, 0x02, 0x7c, 0x94, 0x03, 0x99, 0x44, 0xb6, 0x45, 0x94, 0xdb, 0x84, 0x40, +0xb6, 0x43, 0x50, 0x22, 0x7f, 0xf4, 0x44, 0x50, 0x00, 0xff, 0x40, 0x32, 0x80, 0x0c, 0xb4, 0x82, +0x40, 0x51, 0x8c, 0x05, 0x40, 0x32, 0x90, 0x02, 0x96, 0x48, 0x84, 0xa1, 0xb6, 0x62, 0xd9, 0x05, +0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xef, 0x40, 0x41, 0x80, 0x0c, +0x40, 0x02, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, +0x00, 0x19, 0x96, 0x48, 0x80, 0x62, 0x84, 0x81, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x84, 0xd4, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x32, 0x96, 0x48, 0x84, 0x6a, 0x84, 0x81, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x84, 0xd4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x00, 0x80, 0x20, 0x54, 0x00, +0x01, 0x00, 0xc0, 0x09, 0x84, 0x00, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x84, 0x1c, +0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x83, 0xc4, 0xdd, 0x2f, +0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x00, 0x20, 0xb4, 0x22, 0x59, 0xe0, 0x88, 0x00, 0x15, 0xe1, +0x00, 0x00, 0x84, 0x01, 0xb4, 0xa2, 0x80, 0x20, 0x42, 0x32, 0xc4, 0x09, 0xb6, 0x62, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x83, 0xc4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x40, 0x04, 0x84, 0x81, +0xd5, 0x07, 0x95, 0x51, 0xd1, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xc4, 0x84, 0x82, 0x46, 0xa0, +0x10, 0x00, 0x58, 0xa5, 0x00, 0x01, 0x85, 0x20, 0x47, 0xc1, 0x11, 0x10, 0x46, 0x70, 0x04, 0x00, +0xb6, 0x9f, 0x14, 0xaf, 0x80, 0x01, 0x59, 0xce, 0x01, 0x90, 0x81, 0x49, 0x58, 0x73, 0x82, 0x70, +0x46, 0x80, 0x00, 0x01, 0x58, 0x84, 0x04, 0x1c, 0x81, 0x20, 0x80, 0x29, 0xa3, 0x89, 0xb4, 0x21, +0xe6, 0xc4, 0x4e, 0xf2, 0x00, 0xa0, 0x84, 0xa4, 0xd1, 0x34, 0xe6, 0x25, 0xe8, 0x0a, 0x84, 0xa1, +0xd1, 0x1d, 0xc1, 0x17, 0x84, 0xa2, 0xd1, 0x21, 0x84, 0xa3, 0x4c, 0x12, 0xc0, 0x94, 0xd5, 0x25, +0x8c, 0xac, 0xd1, 0x42, 0xe6, 0x31, 0xe8, 0x07, 0x84, 0xa5, 0xd1, 0x2a, 0x84, 0xa6, 0x4c, 0x12, +0xc0, 0x8a, 0xd5, 0x32, 0x9d, 0x69, 0xd1, 0x59, 0x9d, 0x69, 0x4c, 0x12, 0xc0, 0x84, 0xd5, 0x64, +0x80, 0x06, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0xd5, 0x7d, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x83, 0xc4, 0xdd, 0x2f, 0xd5, 0x76, 0x80, 0x06, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x84, 0x7c, 0xdd, 0x2f, 0xd5, 0x6e, 0x84, 0x21, 0x44, 0x20, 0x00, 0x32, 0xd5, 0x0b, +0x80, 0x06, 0x84, 0x21, 0x46, 0x20, 0x00, 0x01, 0x58, 0x21, 0x05, 0x38, 0xd5, 0x62, 0x84, 0x21, +0x44, 0x20, 0x00, 0x11, 0x80, 0x06, 0x80, 0x62, 0x80, 0x81, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x84, 0xd4, 0xdd, 0x2f, 0xd5, 0x57, 0x80, 0x06, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x85, 0x5c, 0xdd, 0x2f, 0xd5, 0x4f, 0x46, 0x50, 0x00, 0x80, 0x58, 0x52, 0x80, 0x50, 0x46, 0x20, +0x04, 0x00, 0x98, 0xf5, 0x58, 0x21, 0x02, 0x7c, 0x95, 0x73, 0x98, 0x6a, 0x15, 0xc0, 0x80, 0x00, +0x41, 0xe1, 0x8c, 0x08, 0xf4, 0x01, 0xb6, 0x9e, 0x44, 0x00, 0x00, 0x82, 0xb4, 0x47, 0x40, 0x60, +0x14, 0x0c, 0x41, 0xe1, 0x20, 0x09, 0x41, 0xef, 0x20, 0x08, 0x15, 0xe3, 0x80, 0x00, 0xb4, 0x27, +0x40, 0x63, 0x04, 0x04, 0xb6, 0xc7, 0xd5, 0x2e, 0x80, 0x06, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, +0x80, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x01, 0xc0, 0x46, 0x10, 0x00, 0x01, 0x58, 0x10, +0x87, 0x88, 0x84, 0x61, 0xd5, 0x0f, 0x80, 0x06, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x46, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x01, 0xc0, 0x46, 0x10, 0x00, 0x01, 0x58, 0x10, 0x87, 0x88, +0x84, 0x63, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x0c, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x01, 0xc0, 0x44, 0x10, 0x13, 0x88, 0x46, 0x20, 0x00, 0x00, 0x58, 0x21, 0x02, 0x54, +0xdd, 0x22, 0xb4, 0x1f, 0x8d, 0x41, 0x8d, 0x28, 0xe3, 0x40, 0x4e, 0xf3, 0xff, 0x58, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0xa2, 0x80, 0xc0, +0xd1, 0x25, 0x84, 0xa3, 0xd1, 0x2a, 0x84, 0xa1, 0xd9, 0x2e, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x83, 0xc4, 0xdd, 0x2f, 0x80, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x01, 0xc0, 0x46, 0x10, +0x00, 0x01, 0x58, 0x10, 0x87, 0x88, 0x84, 0x62, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x0c, +0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x01, 0xc0, 0x44, 0x10, 0x0b, 0xb8, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, 0xd5, 0x0e, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x84, 0x7c, 0xdd, 0x2f, 0xd5, 0x07, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x83, 0xc4, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x46, 0x10, 0x04, 0x00, 0x04, 0x60, 0x80, 0x97, 0x96, 0x34, 0xc0, 0x15, 0x80, 0x61, +0x04, 0x21, 0x80, 0x20, 0x54, 0x01, 0x01, 0x00, 0xc0, 0x09, 0x84, 0x00, 0x80, 0x20, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x84, 0x1c, 0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x83, 0xc4, 0xdd, 0x2f, 0x40, 0x43, 0x40, 0x08, 0x92, 0x9f, 0xc4, 0x06, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x80, 0x0c, 0xdd, 0x2f, 0x55, 0xe3, 0x10, 0x00, 0x4f, 0xe2, 0x00, 0x07, +0x84, 0x21, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x17, 0x83, 0x38, 0x54, 0x23, 0x20, 0x00, 0xc2, 0x11, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x86, 0x8c, 0x84, 0xa1, 0xd9, 0x0b, 0x46, 0xf0, 0x00, 0x0e, +0x00, 0x07, 0x86, 0x91, 0x4c, 0x00, 0xc0, 0x06, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x07, 0x86, 0x6b, +0x47, 0xe0, 0x04, 0x00, 0x14, 0x6f, 0x00, 0x97, 0x04, 0x5f, 0x00, 0x97, 0xf5, 0x81, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x49, 0x54, 0x20, 0x80, 0x03, 0x40, 0x30, +0x88, 0x09, 0xca, 0x10, 0x5c, 0xf0, 0x80, 0xc8, 0xe8, 0x0d, 0x80, 0x20, 0xb4, 0x40, 0x84, 0x01, +0xd5, 0x04, 0xb4, 0x81, 0x9c, 0x01, 0xab, 0x11, 0x9c, 0x4c, 0xe2, 0x03, 0xe9, 0xfb, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0xa4, 0x88, 0x5c, 0xf1, +0x00, 0xc8, 0xe8, 0x16, 0x80, 0x60, 0xa2, 0x99, 0xb4, 0xa3, 0x5c, 0xf2, 0x80, 0x40, 0xe8, 0x10, +0x84, 0x60, 0xd5, 0x04, 0xa3, 0x91, 0x80, 0x64, 0xb6, 0xc0, 0x40, 0x21, 0x20, 0x08, 0x92, 0x48, +0x9c, 0x04, 0x9d, 0x19, 0xdb, 0xf8, 0x94, 0x22, 0xac, 0x08, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x49, 0xe6, 0x28, 0xe8, 0x03, 0x84, 0x01, +0xd5, 0x29, 0x80, 0x40, 0xa2, 0xd1, 0x8c, 0x08, 0xb4, 0x22, 0xb4, 0x40, 0xc3, 0x02, 0xd5, 0x21, +0x46, 0x44, 0x00, 0x04, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x80, 0xdc, 0x40, 0x51, 0x10, 0x04, +0xb6, 0xa1, 0x80, 0x03, 0xd5, 0x09, 0x92, 0x00, 0x84, 0x67, 0x9c, 0x49, 0x4c, 0x11, 0xff, 0xfd, +0x9c, 0x01, 0x84, 0xaa, 0xd0, 0x03, 0x84, 0x20, 0xd5, 0xf7, 0x46, 0x1b, 0xff, 0xfb, 0x46, 0x00, +0x04, 0x00, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x21, 0x04, 0x02, 0x58, 0x00, 0x00, 0xdc, 0xb6, 0x40, +0x84, 0x00, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe4, 0x81, 0x42, 0x81, 0x03, +0x81, 0x25, 0x55, 0xc0, 0x00, 0xff, 0x97, 0x08, 0x5c, 0xf3, 0x80, 0xc1, 0xe8, 0x4e, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0xf4, 0x81, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, +0xdd, 0x2f, 0x80, 0xc0, 0xf4, 0x01, 0xc0, 0x41, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x81, 0xdc, +0x54, 0x22, 0x00, 0x0f, 0x54, 0x5e, 0x00, 0x0f, 0x41, 0xe1, 0x40, 0x08, 0x40, 0x02, 0xd0, 0x08, +0x46, 0x25, 0x80, 0x00, 0xa1, 0x72, 0x40, 0x4f, 0x00, 0x04, 0x54, 0x11, 0x80, 0x03, 0x41, 0xe2, +0x08, 0x04, 0x14, 0x82, 0x80, 0x01, 0x40, 0x00, 0xe4, 0x08, 0xb7, 0x45, 0x50, 0x83, 0x80, 0x08, +0x40, 0x3f, 0x00, 0x04, 0x80, 0x47, 0x54, 0x84, 0x3f, 0xff, 0x80, 0x29, 0x50, 0x02, 0x80, 0x08, +0x40, 0x71, 0xa0, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, 0x84, 0x21, +0x84, 0x00, 0x10, 0x13, 0x00, 0x0f, 0x10, 0x03, 0x00, 0x14, 0x12, 0x83, 0x00, 0x06, 0xa9, 0xf4, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8a, 0x8c, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x96, 0x89, 0x97, 0xd8, 0xe6, 0x44, +0xe8, 0x03, 0x84, 0x01, 0xd5, 0x22, 0xb4, 0x00, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x03, 0xd5, 0x1c, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x81, 0x87, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, 0x81, 0x86, +0xf5, 0x81, 0xb6, 0x7f, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x89, 0x18, 0xdd, 0x2f, 0x84, 0x40, +0x80, 0x27, 0x80, 0xbf, 0x84, 0x05, 0x80, 0x62, 0x84, 0x88, 0x80, 0xdf, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x84, 0x05, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x97, 0x82, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, +0x97, 0xc8, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0xc8, 0x03, 0x84, 0x01, +0xd5, 0x2b, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, 0x81, 0xdc, 0x54, 0x53, 0x80, 0x0f, 0x54, 0x4f, +0x00, 0x03, 0x40, 0x32, 0xc0, 0x08, 0x40, 0x12, 0x64, 0x08, 0x46, 0x25, 0x88, 0x08, 0x41, 0xe1, +0x84, 0x04, 0xa1, 0x42, 0x58, 0x21, 0x00, 0x08, 0x40, 0x1f, 0x08, 0x04, 0x84, 0x88, 0x84, 0x61, +0x84, 0x40, 0xb6, 0xc5, 0xa8, 0x44, 0xad, 0x06, 0x10, 0x30, 0x00, 0x0f, 0x10, 0x20, 0x00, 0x14, +0x80, 0x20, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8a, 0x8c, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x00, 0x0e, 0x20, 0x27, 0x81, 0xde, 0x84, 0xa1, 0xda, 0x58, +0x46, 0x60, 0x04, 0x10, 0x04, 0x53, 0x01, 0x0e, 0x40, 0x82, 0xc0, 0x09, 0x46, 0xf0, 0x00, 0x0b, +0x00, 0x37, 0x85, 0x1d, 0x54, 0x84, 0x00, 0xff, 0xe3, 0x03, 0xe9, 0x22, 0x46, 0x70, 0x00, 0x0e, +0x20, 0x63, 0x81, 0xe1, 0xce, 0x1d, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x67, 0x81, 0xe0, 0x10, 0x23, +0x81, 0xe1, 0x80, 0x02, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8a, 0x80, 0xdd, 0x2f, +0xc0, 0x03, 0x10, 0x63, 0x81, 0xe1, 0x84, 0x01, 0x80, 0x20, 0x46, 0x60, 0x00, 0x01, 0x58, 0x63, +0x0a, 0x80, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x01, 0x84, 0x22, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x27, 0x81, 0xdf, 0xe2, 0x48, 0xe9, 0x23, 0x46, 0x70, 0x00, 0x0e, 0x20, 0x63, +0x81, 0xe0, 0xce, 0x1e, 0x84, 0x61, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x67, 0x81, 0xe1, 0x10, 0x33, +0x81, 0xe0, 0x80, 0x06, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8a, 0x80, 0xdd, 0x2f, +0xc0, 0x03, 0x10, 0x63, 0x81, 0xe0, 0x84, 0x21, 0x46, 0x60, 0x00, 0x01, 0x58, 0x63, 0x0a, 0x80, +0x84, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x00, 0x84, 0x22, 0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0xa2, 0x41, 0x84, 0x41, 0xb4, 0x00, +0x4c, 0x11, 0x40, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x85, 0xc8, 0xd5, 0x61, 0x84, 0xa3, +0xd9, 0x49, 0x97, 0xc0, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x74, 0x10, 0x73, 0x02, 0xac, +0x46, 0x10, 0x04, 0x10, 0x04, 0x00, 0x82, 0x03, 0x42, 0x00, 0x60, 0x09, 0x42, 0x00, 0x64, 0x09, +0xcf, 0x1a, 0x46, 0x20, 0x30, 0x00, 0x41, 0xe0, 0x08, 0x04, 0x15, 0xe0, 0x82, 0x03, 0x50, 0x03, +0x02, 0x68, 0x46, 0x60, 0x00, 0x00, 0x58, 0x63, 0x01, 0x1c, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x06, 0xa0, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x77, +0x86, 0x6b, 0xd5, 0x36, 0x42, 0x30, 0x60, 0x08, 0x14, 0x30, 0x82, 0x03, 0x84, 0x20, 0x10, 0x13, +0x02, 0x64, 0x14, 0x13, 0x00, 0xa9, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xb8, 0xdd, 0x2f, +0x84, 0x01, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0x38, 0xdd, 0x2f, 0x50, 0x03, +0x02, 0x68, 0x44, 0x10, 0x27, 0x10, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, +0xd5, 0x17, 0x84, 0xa4, 0xd9, 0x0b, 0x5c, 0x50, 0x00, 0x03, 0x84, 0x80, 0x40, 0x02, 0x14, 0x1a, +0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x85, 0xd9, 0xd5, 0x0b, 0x84, 0xa5, 0xd9, 0x09, 0x56, 0x10, +0x00, 0x01, 0x5c, 0x00, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x86, 0x9d, 0x84, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x94, 0x80, 0xc0, +0xb4, 0x00, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x24, 0x9c, 0xb4, 0xb4, 0x22, 0x50, 0x33, 0x00, 0x0c, +0x97, 0x0c, 0x8c, 0xc8, 0xb4, 0x46, 0xb4, 0x63, 0xc4, 0x05, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, +0x85, 0xc9, 0x54, 0x00, 0x80, 0x02, 0xc0, 0x0a, 0x85, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x87, +0x85, 0xcb, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x87, 0x85, 0xca, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x37, +0x81, 0x75, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x27, 0x81, 0x74, 0xd5, 0x4e, 0x84, 0xa2, 0xd8, 0x4e, +0x01, 0xe3, 0x00, 0x50, 0x00, 0x43, 0x00, 0x51, 0x00, 0x33, 0x00, 0x53, 0x51, 0xc3, 0x00, 0x04, +0xb5, 0x3c, 0x01, 0xc3, 0x00, 0x52, 0x15, 0xef, 0x80, 0x01, 0xf3, 0x83, 0xf4, 0x82, 0x46, 0x80, +0x01, 0x02, 0x58, 0x84, 0x06, 0xf0, 0x50, 0x13, 0x00, 0x08, 0x94, 0xad, 0x50, 0xaf, 0x80, 0x50, +0x50, 0x0f, 0x80, 0x10, 0x46, 0x70, 0x00, 0x0e, 0x58, 0x73, 0x83, 0x74, 0xdd, 0x28, 0x50, 0x13, +0x00, 0x48, 0x84, 0x48, 0x42, 0x64, 0x84, 0x0b, 0x80, 0x0a, 0x54, 0x94, 0x80, 0x01, 0xdd, 0x28, +0x10, 0x93, 0x82, 0x3f, 0x10, 0x63, 0x82, 0x40, 0x50, 0x1f, 0x80, 0x10, 0xf5, 0x01, 0x44, 0x20, +0x00, 0x40, 0x10, 0x53, 0x82, 0x3c, 0x50, 0x03, 0x80, 0xd0, 0xf3, 0x02, 0x10, 0x33, 0x82, 0x3d, +0xf4, 0x03, 0x13, 0xc3, 0x81, 0x26, 0x10, 0x43, 0x82, 0x3e, 0xdd, 0x28, 0x80, 0x2a, 0x84, 0x48, +0x50, 0x03, 0x80, 0xc8, 0xdd, 0x28, 0x50, 0x13, 0x80, 0xd0, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x87, 0x7c, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x2a, 0x84, 0xa3, 0xd0, 0x02, 0xd5, 0x26, +0x50, 0x9f, 0x80, 0x60, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xf0, 0x9c, 0x74, 0x84, 0x46, +0x50, 0x8f, 0x80, 0x58, 0x80, 0x09, 0xdd, 0x27, 0x50, 0x13, 0x00, 0x0a, 0x84, 0x46, 0x80, 0x08, +0xdd, 0x27, 0x80, 0x29, 0x84, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0x2c, 0xdd, 0x27, +0x8c, 0xd0, 0x84, 0x46, 0x80, 0x28, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x05, 0xb5, 0xdd, 0x27, +0xb4, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x07, 0x81, 0x85, 0x84, 0x01, 0xec, 0x6c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x96, 0x49, 0x54, 0x70, 0x80, 0x07, 0x40, 0xa0, +0x88, 0x09, 0xcf, 0x2e, 0x9d, 0x84, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x81, 0xec, 0x46, 0x80, +0x00, 0x06, 0x58, 0x84, 0x00, 0xac, 0xd5, 0x1f, 0xb4, 0x20, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, +0x40, 0x20, 0xf8, 0x09, 0x4e, 0x14, 0x00, 0x0a, 0x40, 0x00, 0xc0, 0x09, 0x84, 0x40, 0x96, 0x48, +0x96, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0xd5, 0x0a, 0x84, 0xa1, 0xda, 0x09, 0x40, 0x40, 0xc0, 0x09, +0x96, 0x20, 0x96, 0x48, 0x84, 0x40, 0x4b, 0xe0, 0x24, 0x01, 0xc8, 0x0a, 0xb4, 0xa0, 0x9d, 0xfa, +0xb6, 0xa6, 0x8c, 0xc8, 0x9e, 0x34, 0xe2, 0xea, 0xe9, 0xe0, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x96, 0x49, +0x54, 0x70, 0x80, 0x07, 0x41, 0xc0, 0x88, 0x09, 0xcf, 0x35, 0x9d, 0x84, 0x46, 0xa0, 0x00, 0x06, +0x58, 0xa5, 0x02, 0x60, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x81, 0x64, 0xd5, 0x26, 0xb4, 0x20, +0x9d, 0xfa, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, 0x40, 0x80, 0xf8, 0x09, 0x4e, 0x14, 0x00, 0x0c, +0x40, 0x00, 0xc0, 0x09, 0xb4, 0x46, 0x96, 0x00, 0x96, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0xa1, +0xd0, 0x13, 0xd5, 0x18, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0c, 0x40, 0x50, 0xc0, 0x09, 0xb4, 0x46, +0x96, 0x28, 0x96, 0x48, 0x4b, 0xe0, 0x28, 0x01, 0x4c, 0x04, 0x00, 0x07, 0xd5, 0x0b, 0x05, 0xe3, +0x00, 0x00, 0x15, 0xe0, 0x00, 0x00, 0x8c, 0xc8, 0x9e, 0x34, 0xe2, 0xfc, 0xe9, 0xd9, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x85, 0x0c, 0x96, 0xc9, 0x40, 0x21, 0xa1, 0x17, 0x40, 0x11, 0x88, 0x09, 0xf1, 0x81, +0x4e, 0x83, 0x00, 0x6a, 0x50, 0x70, 0x00, 0x08, 0x9d, 0x84, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, +0x01, 0x64, 0xd5, 0x5a, 0xb4, 0x20, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, 0x8d, 0x03, 0x40, 0x20, +0xf8, 0x09, 0x4e, 0x14, 0x00, 0x20, 0x40, 0x90, 0xc0, 0x09, 0x54, 0x94, 0x80, 0xff, 0x54, 0xa0, +0x80, 0xff, 0x80, 0x2a, 0x84, 0x40, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, +0xdd, 0x2f, 0x80, 0x40, 0x80, 0x2a, 0x80, 0x09, 0xca, 0x46, 0xb4, 0x66, 0xb4, 0x82, 0x05, 0xe3, +0x80, 0x00, 0x40, 0x21, 0x8c, 0x05, 0x40, 0x51, 0x10, 0x02, 0x40, 0x22, 0xf8, 0x04, 0xdd, 0x3c, +0xd5, 0x23, 0x84, 0xa1, 0xda, 0x24, 0x40, 0x00, 0xc0, 0x09, 0x54, 0x90, 0x00, 0xff, 0x54, 0xa0, +0x80, 0xff, 0x80, 0x2a, 0x84, 0x40, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0x80, 0x40, 0x80, 0x2a, 0x80, 0x09, 0xca, 0x26, 0xb4, 0xa6, 0xb4, 0x82, 0xb4, 0x67, +0x40, 0x22, 0x94, 0x05, 0x41, 0xe1, 0x10, 0x02, 0x40, 0x2f, 0x0c, 0x04, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0x60, 0xdd, 0x2f, 0x84, 0xa1, 0xd0, 0x0d, 0xd5, 0x15, 0xb4, 0x60, 0xb4, 0x26, +0xb4, 0x47, 0x40, 0x50, 0x84, 0x05, 0x40, 0x41, 0x94, 0x02, 0x41, 0xe2, 0x08, 0x04, 0x15, 0xe0, +0x00, 0x00, 0x8c, 0xcc, 0x8c, 0xec, 0x05, 0xef, 0x80, 0x01, 0x9e, 0x34, 0xe3, 0x1e, 0xe9, 0xa3, +0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0xe6, 0x24, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x5b, +0xb4, 0x20, 0x84, 0xa4, 0xd1, 0x2a, 0xe6, 0x25, 0xe8, 0x06, 0x84, 0xa1, 0xd1, 0x09, 0x84, 0xa3, +0xd9, 0x51, 0xd5, 0x12, 0x84, 0xa5, 0xd1, 0x31, 0x84, 0xa6, 0xd9, 0x4c, 0xd5, 0x38, 0x9c, 0x04, +0xb4, 0x40, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x01, 0xdc, 0x96, 0x50, 0xae, 0x40, 0xe6, 0x22, +0xe9, 0x41, 0x84, 0x20, 0xd5, 0x20, 0x9d, 0x04, 0xb4, 0x64, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, +0x85, 0x1c, 0x54, 0x01, 0x80, 0x0f, 0xae, 0x08, 0xe6, 0x04, 0xe9, 0x03, 0x84, 0x05, 0xd5, 0x31, +0xc8, 0x31, 0x84, 0xa1, 0xaf, 0x48, 0xd5, 0x2f, 0x9c, 0x84, 0xb4, 0x22, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x01, 0xdd, 0x55, 0xe0, 0x80, 0x0f, 0x11, 0xe0, 0x00, 0x00, 0x5c, 0xff, 0x00, 0x04, +0xe9, 0x21, 0x84, 0x23, 0xae, 0x40, 0xd5, 0x1e, 0x9c, 0xc4, 0xb4, 0x03, 0x54, 0x00, 0x00, 0x0f, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x8b, 0x58, 0xdd, 0x2f, 0xd5, 0x14, 0x9c, 0x84, 0xb4, 0x02, +0x40, 0x50, 0x40, 0x09, 0x40, 0x10, 0x7c, 0x09, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x57, 0x85, 0x1d, +0x46, 0xf0, 0x00, 0x0e, 0x10, 0x17, 0x81, 0xde, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x81, 0xdf, +0xae, 0x08, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xf4, 0x04, 0x80, 0x80, 0x04, 0x80, 0xc1, 0x40, 0x14, 0x50, 0x09, 0x81, 0x20, 0x54, 0x10, +0x80, 0x7f, 0x44, 0x00, 0x00, 0x10, 0x84, 0xe4, 0x4c, 0x10, 0x00, 0x60, 0xe4, 0x31, 0xe8, 0x18, +0x84, 0xa9, 0xd1, 0x35, 0xe4, 0x2a, 0xe8, 0x0b, 0x84, 0xa2, 0x4c, 0x12, 0x80, 0x9d, 0x84, 0xa8, +0xd1, 0x26, 0x84, 0xa1, 0x4c, 0x12, 0xc0, 0xf4, 0x48, 0x00, 0x00, 0x8e, 0x84, 0x0b, 0x4c, 0x10, +0x00, 0x41, 0xe0, 0x20, 0xe9, 0x2c, 0x84, 0xac, 0x4c, 0x12, 0xc0, 0xea, 0xd5, 0x32, 0x44, 0x50, +0x00, 0x18, 0xd1, 0x5b, 0xe4, 0x39, 0xe8, 0x09, 0x9d, 0x45, 0xd1, 0x4f, 0x9d, 0x46, 0xd1, 0x0d, +0x9d, 0x44, 0x4c, 0x12, 0xc0, 0xdd, 0xd5, 0x41, 0x9d, 0x6e, 0xd1, 0x65, 0x9d, 0x69, 0xd1, 0x6b, +0x9f, 0x6e, 0x4c, 0x12, 0xc0, 0xd5, 0xd5, 0x51, 0x84, 0x01, 0xd5, 0x7c, 0xa0, 0x32, 0xa4, 0x76, +0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0x98, 0xdd, 0x2f, 0xd5, 0x74, 0xa0, 0x32, 0xa4, 0x76, +0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8e, 0xec, 0xdd, 0x2f, 0xd5, 0x6c, 0xa0, 0x32, 0xa4, 0x76, +0x54, 0x74, 0x3f, 0xff, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8d, 0xf4, 0xdd, 0x2f, 0xd5, 0x62, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8e, 0x68, 0xdd, 0x2f, 0xd5, 0x5a, +0xa0, 0x32, 0x50, 0x13, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0xc8, 0xdd, 0x2f, +0xa5, 0xf6, 0x54, 0x73, 0xbf, 0xff, 0xd5, 0x4e, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x85, 0xe0, 0xdd, 0x2f, 0xd5, 0x46, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x0a, +0x58, 0xf7, 0x87, 0x7c, 0xdd, 0x2f, 0xd5, 0x3e, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x8c, 0xa8, 0xdd, 0x2f, 0xd5, 0x36, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x8b, 0xc4, 0xdd, 0x2f, 0xd5, 0x2e, 0x40, 0x24, 0x40, 0x09, 0xa4, 0x76, 0xa0, 0x32, +0x54, 0x31, 0x00, 0x0f, 0x50, 0x2f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8a, 0x24, +0xdd, 0x2f, 0xd5, 0x75, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x85, 0x14, +0xdd, 0x2f, 0xd5, 0x18, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x09, 0x58, 0xf7, 0x8e, 0xfc, +0xdd, 0x2f, 0xd5, 0x10, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8f, 0xe0, +0xdd, 0x2f, 0xd5, 0x08, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x89, 0x08, +0xdd, 0x2f, 0x93, 0x10, 0x54, 0x84, 0x00, 0x0f, 0x4e, 0x82, 0x00, 0x52, 0x46, 0x3f, 0xff, 0x0f, +0x58, 0x31, 0x8f, 0xff, 0x40, 0x73, 0x8c, 0x02, 0x40, 0x84, 0x40, 0x08, 0x41, 0xe3, 0xa0, 0x04, +0x42, 0x5f, 0x78, 0x09, 0x42, 0x52, 0xfc, 0x09, 0x46, 0x4f, 0xf0, 0xff, 0x42, 0x32, 0xf8, 0x08, +0x54, 0x10, 0x00, 0x0f, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x71, 0x90, 0x02, 0x40, 0x00, 0xd0, 0x08, +0x47, 0xec, 0x6f, 0xff, 0x40, 0x53, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x81, 0xdc, +0x59, 0xef, 0x0f, 0xff, 0x46, 0x11, 0x80, 0x00, 0x40, 0x42, 0xf8, 0x02, 0x40, 0x72, 0x04, 0x04, +0x54, 0x01, 0x80, 0x03, 0x42, 0x53, 0xe4, 0x09, 0x42, 0x52, 0xe8, 0x09, 0x41, 0xe0, 0x64, 0x08, +0x40, 0x32, 0xf8, 0x04, 0x42, 0x71, 0xbc, 0x09, 0x54, 0x13, 0xbf, 0xff, 0xe4, 0x28, 0xe8, 0x07, +0x40, 0x03, 0xb8, 0x09, 0x40, 0x00, 0x38, 0x08, 0x58, 0x70, 0x00, 0x08, 0x54, 0x53, 0xbf, 0xff, +0x84, 0x21, 0x10, 0x13, 0x00, 0x0f, 0xad, 0x76, 0xa9, 0xf4, 0x80, 0x09, 0x80, 0x26, 0x46, 0xf0, +0x00, 0x03, 0x58, 0xf7, 0x8a, 0x8c, 0xdd, 0x2f, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x0c, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x44, 0x20, +0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, +0xdd, 0x2f, 0xa6, 0x70, 0xa6, 0xb4, 0xa6, 0x31, 0x84, 0x7e, 0x40, 0x40, 0x8c, 0x02, 0x92, 0x02, +0x94, 0x02, 0x40, 0x51, 0x0c, 0x02, 0xaf, 0x30, 0xaf, 0x74, 0xae, 0x31, 0xa7, 0x37, 0x00, 0x33, +0x80, 0x9d, 0x54, 0x21, 0x00, 0x02, 0xae, 0xf5, 0xa6, 0xf3, 0xa1, 0x7b, 0x00, 0x03, 0x80, 0x9e, +0x54, 0x31, 0x80, 0x38, 0x98, 0x28, 0x96, 0x01, 0x40, 0x70, 0x20, 0x09, 0x54, 0x53, 0x80, 0x0f, +0x92, 0x84, 0x95, 0x24, 0x40, 0x42, 0x14, 0x04, 0x58, 0x21, 0x00, 0x1c, 0x54, 0x50, 0x80, 0x08, +0x58, 0x31, 0x80, 0x40, 0x84, 0x20, 0xaf, 0x70, 0xaf, 0x37, 0xae, 0xb4, 0xae, 0x72, 0xae, 0xf3, +0xae, 0x36, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xa6, 0x70, 0xa6, 0xb4, 0xa6, 0x31, 0x84, 0x7e, 0x40, 0x40, +0x8c, 0x02, 0x92, 0x02, 0x94, 0x02, 0x40, 0x51, 0x0c, 0x02, 0xaf, 0x30, 0xaf, 0x74, 0xae, 0x31, +0xa7, 0x37, 0x00, 0x33, 0x80, 0x9d, 0x54, 0x21, 0x00, 0x02, 0xae, 0xf5, 0xa6, 0xf3, 0xa1, 0x7b, +0x00, 0x03, 0x80, 0x9e, 0x58, 0x21, 0x00, 0x1c, 0x98, 0x28, 0x96, 0x01, 0x40, 0x70, 0x20, 0x09, +0x54, 0x53, 0x80, 0x0f, 0x92, 0x84, 0x95, 0x24, 0x40, 0x42, 0x14, 0x04, 0x54, 0x31, 0x80, 0x38, +0x54, 0x50, 0x80, 0x08, 0x84, 0x20, 0xaf, 0x70, 0xaf, 0x37, 0xae, 0xb4, 0xae, 0x72, 0xae, 0xf3, +0xae, 0x36, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x60, 0x00, 0x18, 0x10, 0x60, 0x00, 0x9e, 0x50, 0x60, 0x00, 0x24, 0x80, 0xe0, 0x84, 0x20, +0x44, 0x20, 0x00, 0x18, 0x80, 0x06, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, +0xa6, 0xf0, 0x00, 0x83, 0x00, 0x01, 0x44, 0x0f, 0xff, 0xd8, 0x40, 0x44, 0x00, 0x02, 0x54, 0x51, +0x80, 0x03, 0x58, 0x22, 0x80, 0x08, 0x58, 0x12, 0x00, 0x01, 0x84, 0x60, 0x10, 0x33, 0x00, 0x16, +0x10, 0x33, 0x00, 0x17, 0xae, 0xb0, 0xae, 0x71, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, 0x06, 0xf0, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x85, 0xb5, 0x84, 0x46, 0x50, 0x03, 0x80, 0x28, 0x4b, 0xe0, +0x20, 0x01, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0x2c, 0x84, 0x46, 0x50, 0x03, 0x80, 0x2e, +0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x79, 0x50, 0x03, 0x80, 0x34, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, +0x00, 0x03, 0x80, 0x94, 0xc0, 0x06, 0xa6, 0x71, 0x59, 0xe0, 0x80, 0x40, 0x11, 0xe3, 0x00, 0x01, +0xa7, 0x31, 0x42, 0x22, 0x10, 0x09, 0xae, 0xb1, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x80, 0x20, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x89, 0x68, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0x81, 0x01, 0x80, 0xe2, 0x50, 0x9f, +0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x81, 0x43, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x84, 0x80, 0x80, 0x28, 0x80, 0x47, 0x84, 0x7f, 0x80, 0x09, +0xf4, 0x83, 0x10, 0x3f, 0x80, 0x9d, 0xf4, 0x82, 0xb7, 0x5f, 0x14, 0x8f, 0x80, 0x01, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, 0x96, 0xb8, 0x40, 0x04, 0x88, 0x00, 0x9d, 0x43, +0x40, 0x42, 0x88, 0x09, 0x95, 0x22, 0x9a, 0xe0, 0x80, 0x3f, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, +0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x83, 0x5c, 0xdd, 0x2f, +0x80, 0x1f, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, 0x80, 0xdf, 0x84, 0x01, +0xec, 0xa0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x5c, 0x81, 0x00, +0x97, 0x90, 0x40, 0x90, 0x80, 0x13, 0x80, 0x1f, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x04, 0x74, +0x00, 0x02, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xce, 0x13, 0x46, 0x30, +0x00, 0x0e, 0x58, 0x31, 0x83, 0x74, 0x00, 0x41, 0x81, 0x70, 0xcc, 0x05, 0x80, 0x64, 0x44, 0x20, +0x00, 0xff, 0xd5, 0x0c, 0x00, 0x01, 0x81, 0x71, 0xc0, 0x05, 0x50, 0x31, 0x81, 0x30, 0x80, 0x46, +0xd5, 0x05, 0x84, 0x60, 0x44, 0x20, 0x00, 0xff, 0x80, 0x83, 0x87, 0xc1, 0x50, 0x53, 0x80, 0x0e, +0x50, 0x14, 0xff, 0xf2, 0x80, 0x1f, 0x11, 0xef, 0x80, 0x9d, 0xf3, 0xa6, 0xb7, 0x1f, 0xf5, 0x82, +0xf1, 0x83, 0x10, 0x4f, 0x80, 0x94, 0x10, 0x2f, 0x80, 0x9c, 0xf7, 0x81, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x83, 0xdc, 0xdd, 0x2f, 0x00, 0x0f, 0x80, 0x9e, 0x50, 0x2f, 0x80, 0x24, 0x99, 0x50, +0x9d, 0xeb, 0x92, 0xe2, 0x95, 0xfa, 0x9b, 0x3d, 0x10, 0x4f, 0x80, 0x9f, 0x46, 0x80, 0x01, 0x02, +0x58, 0x84, 0x06, 0xf0, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x84, 0xf4, 0x84, 0x46, 0x80, 0x07, +0x4b, 0xe0, 0x20, 0x01, 0xf1, 0x01, 0x9c, 0x3e, 0x8c, 0x2c, 0x84, 0x42, 0x4b, 0xe0, 0x20, 0x01, +0x00, 0x3f, 0x80, 0x9e, 0x80, 0x3f, 0x50, 0x21, 0x80, 0x08, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x2f, +0x80, 0x9e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x82, 0xd8, 0xdd, 0x2f, 0x80, 0x1f, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, 0x80, 0xdf, 0x84, 0x00, 0xec, 0xa4, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xec, 0xa0, 0x42, 0x80, 0xc0, 0xa6, 0xc8, +0x44, 0x20, 0x00, 0x80, 0x54, 0x01, 0x80, 0xf0, 0x4c, 0x01, 0x40, 0x9d, 0x8c, 0x2a, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x05, 0xb5, 0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, +0xdd, 0x2f, 0x4e, 0x03, 0x00, 0x90, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x9a, 0x46, 0x70, +0x00, 0x0e, 0x58, 0x73, 0x83, 0x74, 0x14, 0x13, 0x80, 0x92, 0x80, 0x5f, 0x02, 0x13, 0x00, 0x0a, +0xa0, 0x34, 0x50, 0x3f, 0x80, 0x08, 0x50, 0x4f, 0x80, 0x0e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8a, 0x64, 0xdd, 0x2f, 0x4e, 0x02, 0x00, 0xa5, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x57, 0x86, 0x8c, +0x84, 0x41, 0xda, 0x26, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x86, 0x91, 0xc8, 0x21, 0x03, 0xe3, +0x81, 0x28, 0x4f, 0xe2, 0x00, 0x0d, 0x00, 0x53, 0x82, 0xac, 0xda, 0x09, 0x00, 0x23, 0x82, 0x51, +0xc2, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0x5c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, +0x00, 0x57, 0x85, 0xc4, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x85, 0xc5, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x06, 0x8c, 0x87, 0xc0, 0x11, 0xe0, 0x00, 0x03, 0xaf, 0x41, 0xae, 0x42, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x06, 0x8c, 0xb4, 0x20, 0x40, 0x30, 0xa0, 0x08, 0x92, 0x68, 0x84, 0xa1, +0xdb, 0x6f, 0xa6, 0x85, 0xca, 0x6d, 0xa6, 0x44, 0x84, 0x01, 0x4c, 0x10, 0x00, 0x68, 0x84, 0xa2, +0xd9, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x10, 0x84, 0xa3, 0xd1, 0x0c, 0x84, 0xa4, 0xd1, 0x0a, +0x56, 0x40, 0x80, 0x05, 0x44, 0x50, 0x15, 0x7c, 0x40, 0x01, 0x10, 0x1b, 0x40, 0x02, 0x90, 0x1a, +0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x85, 0xc2, 0xcb, 0x05, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x85, 0xc3, 0x46, 0x20, 0x04, 0x11, 0x05, 0xe1, 0x00, 0x49, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x81, 0xa6, 0x40, 0x2f, 0x18, 0x08, 0x44, 0x40, 0x03, 0xe8, +0x43, 0xe2, 0x90, 0x24, 0x50, 0x21, 0x51, 0x20, 0x9a, 0x90, 0x9e, 0x19, 0x42, 0x2f, 0x00, 0x73, +0x4e, 0x27, 0x00, 0x37, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x85, 0xf0, 0xdd, 0x2f, +0xd5, 0x2f, 0xa0, 0x32, 0x44, 0x50, 0x00, 0xd0, 0xa6, 0xc0, 0x54, 0x71, 0x80, 0xf0, 0xdf, 0x28, +0xa1, 0x74, 0x00, 0x12, 0x80, 0x18, 0x00, 0x02, 0x80, 0x19, 0xc9, 0x13, 0x87, 0xc4, 0x4c, 0x0f, +0x40, 0x20, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xc8, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x05, 0xdc, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0xd5, 0x10, +0x84, 0x83, 0x4c, 0x12, 0x40, 0x0e, 0xc8, 0x0c, 0x80, 0x06, 0x44, 0x10, 0x00, 0x25, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8c, 0x28, 0xdd, 0x2f, 0xd5, 0x03, 0x84, 0x02, 0xd5, 0xad, 0xec, 0x14, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x17, 0x85, 0xc8, 0x80, 0xc0, 0xc1, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x82, 0x34, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x85, 0xd8, 0x84, 0xa1, 0x4c, 0x02, +0x80, 0x8d, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0x8c, 0xa7, 0x48, 0x4e, 0x52, 0x00, 0x86, +0xa7, 0xcd, 0x84, 0xa1, 0x4c, 0x72, 0x80, 0x82, 0xb4, 0x06, 0xa6, 0x00, 0x54, 0x20, 0x00, 0x60, +0xca, 0x0b, 0x54, 0x30, 0x00, 0x10, 0xc3, 0x08, 0xa1, 0x72, 0xa7, 0x29, 0x54, 0x62, 0x00, 0x20, +0x96, 0x30, 0xc8, 0x02, 0xae, 0x0a, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x85, 0xc5, 0xc1, 0x0d, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0x8c, 0x01, 0xe0, 0x00, 0x02, 0x4f, 0xe2, 0x00, 0x06, +0xa6, 0x81, 0xc2, 0x03, 0x84, 0x20, 0xd5, 0x06, 0x84, 0x21, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x06, 0x8c, 0xae, 0x43, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x06, 0x8c, 0xb4, 0x86, 0x46, 0x5f, +0xf0, 0x00, 0x58, 0x52, 0x80, 0xff, 0x46, 0x30, 0x10, 0x00, 0x40, 0x02, 0x14, 0x02, 0x58, 0x31, +0x80, 0x01, 0x4c, 0x01, 0xc0, 0x4b, 0xa7, 0xf5, 0xcf, 0x48, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x80, 0x5c, 0xdd, 0x2f, 0xa6, 0x74, 0x84, 0xa1, 0xd1, 0x3d, 0x84, 0xa2, 0xd9, 0x04, +0x44, 0x00, 0x00, 0xc8, 0xd5, 0x11, 0x84, 0x03, 0x4c, 0x10, 0x00, 0x0d, 0x84, 0xa4, 0xd1, 0x0a, +0x56, 0x50, 0x80, 0x05, 0x44, 0x40, 0x15, 0x7c, 0x40, 0x03, 0x94, 0x1b, 0x40, 0x02, 0x14, 0x1a, +0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x85, 0xc2, 0xcb, 0x05, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x85, 0xc3, 0x46, 0x40, 0x04, 0x11, 0x04, 0x22, 0x00, 0x49, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x81, 0xa6, 0x44, 0x40, 0x03, 0xe8, 0x41, 0xe1, 0x18, 0x08, +0x50, 0x2f, 0x51, 0x20, 0x42, 0x42, 0x90, 0x24, 0x9a, 0x90, 0x51, 0xe1, 0xff, 0xff, 0x42, 0x22, +0x78, 0x73, 0x4e, 0x27, 0x00, 0x0b, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x85, 0xf0, +0xdd, 0x2f, 0xd5, 0x03, 0x84, 0x02, 0xd5, 0xd8, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xe0, 0x80, 0x60, 0xa4, 0x06, 0x5c, 0xf0, 0x00, 0x35, 0xe9, 0x2e, +0xa0, 0x5a, 0x9c, 0x8c, 0xa7, 0x97, 0x40, 0x43, 0x18, 0x09, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x47, +0x86, 0x21, 0xc1, 0x24, 0xa7, 0x89, 0x55, 0xe3, 0x00, 0x01, 0x4f, 0xe3, 0x00, 0x20, 0x54, 0x63, +0x00, 0x06, 0xce, 0x1c, 0xd5, 0x20, 0x12, 0x20, 0x00, 0x0a, 0x12, 0x60, 0x00, 0x0b, 0xa6, 0xa0, +0x40, 0x11, 0x08, 0x09, 0x54, 0x10, 0x80, 0x03, 0xc1, 0x0b, 0x84, 0xa2, 0xd1, 0x02, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x87, 0xc8, 0xdd, 0x2f, 0x84, 0x01, 0xd5, 0x08, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x86, 0x14, 0xdd, 0x2f, 0xd5, 0xf9, 0x84, 0x00, 0xec, 0x20, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x50, 0x0f, 0x80, 0x04, 0x50, 0x40, 0x80, 0x1c, 0xb6, 0x20, 0xa8, 0x81, +0xa8, 0xc3, 0xa9, 0x02, 0xa9, 0x04, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, 0x85, 0xd8, 0xa7, 0x53, +0xa6, 0xd2, 0x54, 0x22, 0x80, 0x0f, 0x40, 0x11, 0x20, 0x08, 0x84, 0xa1, 0x40, 0x20, 0x8c, 0x04, +0x4d, 0xe2, 0xff, 0xcb, 0xd5, 0xe3, 0x92, 0x00, 0x84, 0x60, 0xd5, 0x0e, 0x38, 0x50, 0x0c, 0x00, +0x38, 0x40, 0x8c, 0x00, 0x9c, 0xd9, 0xe2, 0x85, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x08, 0xe2, 0xa4, +0xe8, 0x03, 0x84, 0x02, 0xd5, 0x04, 0xe2, 0x62, 0xe9, 0xf2, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0x3c, 0x9c, 0x01, 0x08, 0x60, 0x00, 0x01, 0x96, 0x49, 0xaf, 0x90, 0x08, 0x60, +0x00, 0x01, 0xaf, 0xa0, 0x08, 0x60, 0x00, 0x01, 0xaf, 0xa8, 0xa7, 0xa0, 0xa7, 0x40, 0xf4, 0x01, +0xce, 0x05, 0x97, 0xac, 0xc6, 0x03, 0x84, 0xc1, 0xd5, 0x02, 0x84, 0xc0, 0xaf, 0x98, 0x54, 0x32, +0x80, 0xfe, 0x95, 0x5b, 0xa6, 0x90, 0xe0, 0x25, 0xe9, 0x08, 0x9e, 0x94, 0x99, 0x5a, 0x96, 0xa8, +0x9d, 0x51, 0x94, 0xab, 0xe0, 0x22, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x16, 0x40, 0x50, 0x8c, 0x09, +0x9a, 0xeb, 0x96, 0x98, 0x98, 0x02, 0x96, 0xd4, 0x84, 0xa8, 0x40, 0x21, 0x8c, 0x1a, 0x40, 0x22, +0x8c, 0x1b, 0x20, 0x00, 0x00, 0x01, 0x54, 0x50, 0x80, 0x0f, 0x9a, 0xea, 0x40, 0x10, 0x0c, 0x0e, +0x96, 0x4c, 0xc1, 0x04, 0x84, 0x01, 0xae, 0x20, 0xd5, 0x02, 0xae, 0x60, 0x84, 0x01, 0x3a, 0x6f, +0x98, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x85, 0x20, 0xf4, 0x83, 0x12, 0x92, +0x00, 0x00, 0x80, 0xa0, 0x08, 0x82, 0x80, 0x0a, 0xf3, 0x82, 0x93, 0x04, 0xf1, 0x85, 0x14, 0x8f, +0x80, 0x04, 0x80, 0xc0, 0x80, 0x25, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xf0, 0x80, 0x02, +0x84, 0x46, 0x4b, 0xe0, 0x1c, 0x01, 0xf0, 0x02, 0x50, 0x13, 0x00, 0x10, 0x84, 0x46, 0x47, 0xc0, +0x00, 0x0e, 0x59, 0xce, 0x03, 0x74, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x63, 0x00, 0x24, 0x44, 0xa0, +0x00, 0x24, 0x50, 0x7f, 0x80, 0x1f, 0x50, 0x9e, 0x02, 0x51, 0xd5, 0x59, 0xf0, 0x03, 0xa4, 0xc0, +0x98, 0x5a, 0x5e, 0xf0, 0x81, 0x7e, 0xe8, 0x5a, 0xa6, 0x70, 0x84, 0x85, 0x4c, 0x12, 0x00, 0x1e, +0x45, 0xe0, 0x00, 0x25, 0x4c, 0x1f, 0x40, 0x46, 0x85, 0x03, 0x4c, 0x24, 0x40, 0x43, 0xa7, 0xb3, +0x46, 0xf0, 0x00, 0x0e, 0x10, 0x67, 0x86, 0x9c, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xc8, +0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x05, 0xdc, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x81, 0x1c, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x3b, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x57, 0x86, 0x8c, +0x84, 0x21, 0xd9, 0x27, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x86, 0x91, 0xcb, 0x22, 0xf0, 0x04, +0x85, 0x08, 0x4c, 0x04, 0x40, 0x1f, 0xf0, 0x02, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x85, 0xb5, +0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, 0xdd, 0x2f, 0xc8, 0x12, 0x02, 0x1e, +0x01, 0x26, 0xb7, 0x3f, 0x80, 0x06, 0x80, 0x47, 0x50, 0x34, 0xff, 0xff, 0x50, 0x44, 0xff, 0xfd, +0x50, 0x54, 0xff, 0xfe, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x09, 0xe0, 0x4b, 0xe0, 0x20, 0x01, +0x01, 0xe3, 0x00, 0x01, 0x50, 0x4f, 0x00, 0x02, 0x99, 0xb4, 0x89, 0x44, 0xa6, 0xb1, 0xf5, 0x05, +0x9c, 0xd2, 0x40, 0x11, 0xa8, 0x00, 0xe2, 0xa1, 0xe8, 0xa2, 0x84, 0x01, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x80, 0xe1, 0x81, 0x22, +0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x81, 0x03, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, +0xdd, 0x2f, 0xa7, 0x30, 0x44, 0x2f, 0xff, 0xd0, 0x54, 0x32, 0x00, 0x03, 0x40, 0x11, 0x88, 0x04, +0x80, 0x06, 0x18, 0x10, 0x00, 0x04, 0x84, 0x46, 0x80, 0x27, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, +0x86, 0xf0, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x29, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x4b, 0xe0, +0x1c, 0x01, 0x80, 0x28, 0x84, 0x46, 0x50, 0x03, 0x00, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x00, 0x10, 0x02, 0x66, 0x00, 0x43, 0x00, 0x16, 0x54, 0x50, +0x80, 0x0f, 0x94, 0xec, 0x54, 0x22, 0x00, 0x0f, 0x40, 0x41, 0x0c, 0x04, 0x40, 0x50, 0x90, 0x09, +0x10, 0x53, 0x00, 0x17, 0x10, 0x43, 0x00, 0x16, 0x44, 0x20, 0x00, 0xff, 0x00, 0x10, 0x02, 0x66, +0x9c, 0xc9, 0x10, 0x30, 0x02, 0x66, 0x4c, 0x11, 0x40, 0x05, 0x87, 0xc0, 0x11, 0xe0, 0x02, 0x66, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, +0x40, 0x80, 0x80, 0x13, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x89, 0x70, 0xdd, 0x2f, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x03, 0x54, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, +0x80, 0xe0, 0xc0, 0x41, 0xa1, 0x82, 0x8c, 0xd8, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x85, 0xb5, +0x80, 0x61, 0x50, 0x03, 0x7f, 0xe8, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x06, 0x2c, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8b, 0x84, 0xdd, 0x2f, 0x84, 0x63, 0x84, 0x21, 0x04, 0x04, 0x80, 0x04, +0xa6, 0xb5, 0xae, 0xf0, 0xae, 0x71, 0x58, 0x21, 0x00, 0x02, 0x00, 0x40, 0x00, 0x1a, 0x42, 0x31, +0x00, 0x09, 0x40, 0x14, 0x20, 0x09, 0xae, 0xf5, 0xaf, 0x32, 0xae, 0x74, 0x10, 0x83, 0x00, 0x03, +0x54, 0x31, 0x00, 0x02, 0x00, 0x50, 0x00, 0x1b, 0x44, 0x10, 0x00, 0x10, 0x54, 0x42, 0x80, 0x3c, +0x40, 0x21, 0x90, 0x04, 0x84, 0x00, 0xae, 0xb5, 0xae, 0x76, 0xae, 0x37, 0x10, 0x03, 0x00, 0x08, +0x50, 0x13, 0x7f, 0xe8, 0x80, 0x67, 0x44, 0x20, 0x00, 0x21, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x84, 0xa4, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0x80, 0xc0, 0x54, 0xa0, 0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0x84, 0x20, 0x44, 0x20, 0x00, 0x18, +0x80, 0xe3, 0x81, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xa7, 0x30, +0xa6, 0x31, 0x54, 0x32, 0x00, 0x03, 0x40, 0x55, 0x10, 0x08, 0x42, 0x40, 0x00, 0x09, 0x54, 0x24, +0x80, 0x01, 0x40, 0x02, 0x08, 0x04, 0x40, 0x11, 0x94, 0x04, 0xae, 0x70, 0xae, 0x31, 0x80, 0x27, +0x84, 0x46, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xf0, 0x9c, 0x34, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0x2c, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x4b, 0xe0, +0x1c, 0x01, 0x50, 0x03, 0x00, 0x10, 0x80, 0x28, 0x84, 0x46, 0x4b, 0xe0, 0x1c, 0x01, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x2f, 0x94, 0x3c, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x81, 0x20, +0x50, 0x0f, 0x80, 0x20, 0xf0, 0x81, 0x80, 0xe1, 0x84, 0xc0, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, +0x06, 0xa4, 0xf2, 0x01, 0x84, 0xbf, 0x9d, 0x14, 0xf4, 0x81, 0x40, 0x04, 0x98, 0x00, 0xb4, 0x62, +0x9c, 0x64, 0x80, 0x43, 0xd3, 0x07, 0xf1, 0x81, 0x99, 0xb3, 0xb4, 0x24, 0x4b, 0xe0, 0x20, 0x01, +0xd5, 0xf1, 0x80, 0x06, 0xb6, 0xc7, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xec, 0x10, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x60, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x81, 0x58, 0x11, +0x00, 0x0c, 0xa8, 0x41, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, 0x46, 0x40, 0x04, 0x10, +0x46, 0x30, 0x04, 0x10, 0x46, 0x20, 0x04, 0x10, 0x58, 0x42, 0x04, 0x38, 0x58, 0x31, 0x8a, 0x30, +0x58, 0x21, 0x0a, 0x34, 0x84, 0x20, 0xb4, 0xc4, 0xb4, 0xa3, 0x5c, 0x63, 0x00, 0x01, 0x96, 0x28, +0xc0, 0x02, 0x84, 0xc0, 0xb4, 0xa2, 0x46, 0x7f, 0xf0, 0x0f, 0x58, 0x73, 0x8f, 0x00, 0x40, 0x02, +0x9c, 0x02, 0x9c, 0x49, 0xc8, 0x02, 0xce, 0x08, 0x84, 0x1f, 0x4c, 0x50, 0x00, 0x92, 0x44, 0x50, +0x07, 0xd0, 0xd9, 0xea, 0xd5, 0x6b, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x00, 0xb4, 0x81, +0x96, 0xa4, 0xc2, 0x17, 0x84, 0x40, 0xd5, 0x0b, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0xd9, 0x4c, 0x33, +0x7f, 0xfd, 0x9c, 0x91, 0x44, 0x70, 0x00, 0x32, 0x4c, 0x23, 0x80, 0x04, 0x84, 0x60, 0xd5, 0xf5, +0x84, 0x7f, 0x4c, 0x41, 0x80, 0x76, 0x9c, 0x01, 0x44, 0x40, 0x07, 0xd0, 0x4c, 0x02, 0x7f, 0xe9, +0x46, 0x60, 0x04, 0x11, 0x58, 0x63, 0x00, 0x04, 0xb4, 0x06, 0x84, 0xb7, 0x40, 0x10, 0x14, 0x02, +0x46, 0x40, 0x04, 0x10, 0x46, 0x30, 0x04, 0x10, 0x46, 0x20, 0x04, 0x10, 0xb6, 0x26, 0x58, 0x42, +0x04, 0x38, 0x58, 0x31, 0x8a, 0x30, 0x58, 0x21, 0x0a, 0x34, 0x84, 0x20, 0xb4, 0xa4, 0x46, 0x60, +0x0f, 0xf0, 0xb4, 0x03, 0x40, 0x52, 0x98, 0x02, 0xc0, 0x03, 0x84, 0xa0, 0xd5, 0x03, 0x5c, 0x52, +0x80, 0x01, 0xb4, 0x02, 0x9c, 0x49, 0xc8, 0x03, 0xc5, 0x05, 0xd5, 0x09, 0x84, 0xff, 0x4c, 0x03, +0x80, 0x48, 0x44, 0x00, 0x07, 0xd0, 0x4c, 0x10, 0x7f, 0xeb, 0xd5, 0x31, 0x46, 0x10, 0x04, 0x11, +0x58, 0x10, 0x82, 0x00, 0xb4, 0x81, 0x54, 0x22, 0x00, 0x02, 0xc2, 0x3a, 0x84, 0x40, 0xd5, 0x0b, +0x92, 0x00, 0x84, 0xe7, 0x9c, 0xd9, 0x4c, 0x33, 0xff, 0xfd, 0x9c, 0x91, 0x44, 0x60, 0x00, 0x32, +0x4c, 0x23, 0x00, 0x04, 0x84, 0x60, 0xd5, 0xf5, 0x84, 0xff, 0x4c, 0x43, 0x80, 0x2a, 0x9c, 0x01, +0x44, 0x30, 0x07, 0xd0, 0x4c, 0x01, 0xff, 0xe8, 0xd5, 0x23, 0x46, 0x10, 0x04, 0x10, 0x46, 0x60, +0x04, 0x10, 0x46, 0x40, 0x04, 0x10, 0x58, 0x10, 0x8a, 0x30, 0x58, 0x63, 0x0a, 0x34, 0x58, 0x42, +0x04, 0x38, 0xb4, 0x41, 0xb4, 0x26, 0xb4, 0x04, 0x84, 0x00, 0xd5, 0x86, 0x46, 0x20, 0x04, 0x10, +0x46, 0x00, 0x04, 0x10, 0x46, 0x50, 0x04, 0x10, 0x58, 0x00, 0x0a, 0x34, 0x58, 0x21, 0x0a, 0x30, +0x58, 0x52, 0x84, 0x38, 0xb4, 0x42, 0xb4, 0x20, 0xb4, 0x05, 0x84, 0x00, 0xd5, 0xc0, 0x3a, 0x6f, +0x9c, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x05, 0xc8, +0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x87, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x80, 0x06, +0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0x44, 0x20, 0x01, 0x8c, 0x50, 0x03, 0x7e, 0x74, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x20, 0x84, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0x2c, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x40, 0x46, 0x70, 0x00, 0x00, 0x58, 0x73, 0x81, 0x0c, 0x80, 0x62, 0x50, 0x03, +0x00, 0x14, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x81, 0x20, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x40, +0x50, 0x03, 0x00, 0x30, 0x80, 0x62, 0x46, 0x10, 0x00, 0x02, 0x58, 0x10, 0x8f, 0xf0, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x74, 0x84, 0x80, 0x46, 0x50, 0x00, 0x0e, +0x58, 0x52, 0x86, 0x8c, 0x44, 0x80, 0x00, 0x1e, 0x84, 0x40, 0x10, 0x42, 0x80, 0x11, 0x10, 0x43, +0x02, 0x65, 0x14, 0x82, 0x80, 0x02, 0x10, 0x43, 0x02, 0x66, 0x10, 0x43, 0x02, 0x64, 0xaf, 0x28, +0xaf, 0x2d, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0xa0, 0x46, 0x10, 0x00, 0x0a, 0x58, 0x10, +0x86, 0x98, 0x80, 0x62, 0x4b, 0xe0, 0x1c, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x04, 0x20, +0x00, 0xa8, 0x96, 0x54, 0xc1, 0x1c, 0x04, 0x50, 0x00, 0x92, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x47, +0x80, 0x9a, 0x50, 0x32, 0x83, 0xe8, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x81, 0xe4, 0xe2, 0x64, +0xe8, 0x0c, 0xb4, 0x81, 0x9c, 0xa1, 0xb6, 0x41, 0xe4, 0x4a, 0xe9, 0x09, 0x04, 0x50, 0x00, 0xa9, +0x42, 0x32, 0xf0, 0x08, 0x14, 0x30, 0x00, 0xa9, 0x84, 0x00, 0xb6, 0x01, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x05, 0xf8, 0x44, 0x10, 0x03, 0xe8, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0x81, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x89, 0x70, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x03, 0x54, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x80, 0xe0, +0xc0, 0x4c, 0xa1, 0x82, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x85, 0xb5, 0x80, 0x83, 0x80, 0x06, +0x84, 0x24, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8c, 0xdc, 0xdd, 0x2f, 0x84, 0x40, +0xae, 0xb2, 0xae, 0xb3, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0x74, 0x00, 0x30, 0x82, 0x66, +0xa7, 0x30, 0x00, 0x53, 0x00, 0x16, 0xa6, 0x31, 0x85, 0x53, 0x54, 0x91, 0x80, 0x0f, 0x40, 0x42, +0x28, 0x02, 0x54, 0x84, 0x00, 0x01, 0x40, 0x94, 0x90, 0x08, 0x54, 0x52, 0x80, 0x0f, 0x40, 0x84, +0x10, 0x08, 0x42, 0x00, 0x10, 0x09, 0x40, 0x00, 0x20, 0x04, 0x92, 0x64, 0x58, 0x42, 0x00, 0x08, +0x40, 0x52, 0xa4, 0x04, 0x10, 0x33, 0x00, 0x17, 0xaf, 0x30, 0x10, 0x53, 0x00, 0x16, 0xae, 0x31, +0x44, 0x30, 0x00, 0xff, 0x00, 0x00, 0x82, 0x66, 0x9d, 0x01, 0x10, 0x40, 0x82, 0x66, 0x4c, 0x01, +0xc0, 0x04, 0x10, 0x20, 0x82, 0x66, 0x80, 0x26, 0x80, 0x67, 0x84, 0x00, 0x8c, 0x58, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x84, 0xa4, 0xdd, 0x2f, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x86, 0x8c, 0x84, 0xa1, +0xd8, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x86, 0x91, 0xc9, 0x13, 0xd5, 0x02, 0xc8, 0x11, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0x5c, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x05, 0xdc, 0x44, 0x10, 0x27, 0x10, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xe0, +0x80, 0xc1, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x84, 0x7c, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xc8, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x05, 0xdc, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0x0e, +0x58, 0x21, 0x03, 0x74, 0x00, 0x31, 0x02, 0x65, 0x84, 0x01, 0x14, 0x71, 0x00, 0xa9, 0x14, 0x61, +0x00, 0xaa, 0x10, 0x01, 0x02, 0x64, 0xcb, 0x14, 0x46, 0x40, 0x04, 0x00, 0x05, 0xe2, 0x00, 0x19, +0x42, 0x5f, 0x00, 0x09, 0x14, 0x52, 0x00, 0x19, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x34, +0xb4, 0x60, 0x96, 0x59, 0xb6, 0x20, 0x46, 0x31, 0x23, 0x40, 0xb4, 0x20, 0xd5, 0x1d, 0x84, 0xa1, +0xdb, 0x1e, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x00, 0x8e, 0x46, 0x40, 0x04, 0x00, 0x42, 0x20, +0xc4, 0x08, 0x14, 0x20, 0x00, 0x8e, 0x05, 0xe2, 0x00, 0x20, 0x46, 0x00, 0x04, 0x00, 0x58, 0x5f, +0x00, 0x80, 0x14, 0x52, 0x00, 0x20, 0x58, 0x00, 0x02, 0x34, 0xb4, 0x60, 0x96, 0x59, 0xb6, 0x20, +0x46, 0x35, 0x67, 0x80, 0xb4, 0x20, 0x40, 0x10, 0x8c, 0x04, 0xd5, 0x08, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x80, 0xb4, 0x60, 0x42, 0x11, 0xc0, 0x08, 0xb6, 0x20, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0xa0, 0x42, 0x50, 0x60, 0x00, 0x08, +0xa6, 0xc8, 0x40, 0x21, 0x90, 0x09, 0x54, 0x01, 0x00, 0x04, 0x4e, 0x03, 0x01, 0x0f, 0x04, 0x73, +0x7f, 0xfe, 0xa7, 0x78, 0x54, 0x42, 0x80, 0x60, 0xc4, 0x0e, 0x8c, 0x2a, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x05, 0xb5, 0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, 0xdd, 0x2f, +0x4e, 0x03, 0x00, 0xfc, 0xb5, 0x26, 0x00, 0x84, 0x80, 0x01, 0x54, 0x14, 0x00, 0x40, 0xc1, 0x08, +0x04, 0x23, 0x7f, 0xfe, 0xa6, 0x12, 0x55, 0xe0, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0xef, 0x04, 0x43, +0x7f, 0xfe, 0xa6, 0x20, 0x54, 0x30, 0x00, 0x40, 0xc3, 0x03, 0x84, 0xe3, 0xd5, 0x0f, 0x54, 0x50, +0x00, 0x10, 0xc5, 0x03, 0x84, 0xe1, 0xd5, 0x0a, 0x54, 0x70, 0x00, 0x20, 0x54, 0x83, 0x80, 0xff, +0x84, 0x22, 0x40, 0x74, 0x20, 0x1a, 0x40, 0x70, 0xa0, 0x1b, 0xa0, 0xb2, 0xa5, 0x36, 0x8c, 0x58, +0x50, 0x32, 0x7f, 0xe8, 0xb4, 0x06, 0xac, 0xf6, 0xa8, 0xb2, 0x01, 0xe0, 0x00, 0x00, 0x40, 0x9f, +0x10, 0x09, 0x54, 0x04, 0x80, 0x08, 0xc0, 0x19, 0xa4, 0x77, 0x58, 0x80, 0x80, 0x40, 0x40, 0x14, +0x00, 0x13, 0xac, 0x77, 0xa6, 0x10, 0x97, 0x42, 0x4e, 0x54, 0x00, 0x06, 0x58, 0x90, 0x80, 0x02, +0x12, 0x93, 0x00, 0x07, 0xa0, 0xb2, 0xa5, 0x36, 0x9c, 0xd2, 0x51, 0xe2, 0x7f, 0xfe, 0xa8, 0xf2, +0x13, 0xe3, 0x00, 0x06, 0x54, 0x00, 0x00, 0x0f, 0x10, 0x03, 0x00, 0x10, 0x04, 0x83, 0x7f, 0xfe, +0x00, 0x54, 0x00, 0x01, 0x54, 0x02, 0x80, 0x10, 0xc0, 0x0e, 0xa4, 0xb7, 0xa1, 0x32, 0xa4, 0xf6, +0x59, 0xe1, 0x00, 0x08, 0x9c, 0x64, 0x50, 0x91, 0xff, 0xfc, 0x13, 0xe3, 0x00, 0x07, 0xa8, 0x72, +0x12, 0x93, 0x00, 0x06, 0x04, 0x83, 0x7f, 0xfe, 0x00, 0x54, 0x00, 0x01, 0x54, 0x02, 0x80, 0x40, +0xc0, 0x0b, 0xa4, 0xf7, 0x05, 0xe3, 0x00, 0x02, 0x58, 0x11, 0x80, 0x10, 0x50, 0x9f, 0x00, 0x02, +0xac, 0x77, 0x14, 0x93, 0x00, 0x02, 0xa0, 0x32, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, 0x06, 0xd4, +0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x84, 0xf4, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, 0xc0, 0x0a, +0xa0, 0x32, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x84, 0xfc, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, +0xc8, 0x74, 0xa0, 0x72, 0xa4, 0xf6, 0x9c, 0x4e, 0x51, 0xe1, 0xff, 0xfa, 0x13, 0xe3, 0x00, 0x06, +0xa8, 0x72, 0x84, 0x42, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, +0xdd, 0x2f, 0x04, 0x93, 0x00, 0x02, 0xa4, 0x36, 0x50, 0x54, 0x80, 0x02, 0x9e, 0x82, 0x84, 0x82, +0xa9, 0x72, 0xac, 0xb6, 0x4c, 0x72, 0x00, 0x1a, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x81, 0x74, +0x97, 0x14, 0xc4, 0x13, 0x50, 0x03, 0x7f, 0xf8, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x86, 0x44, +0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x0a, 0x50, 0x23, 0x7f, 0xf8, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xd5, 0x41, 0x50, 0x9f, 0x80, 0x04, 0x46, 0x80, 0x01, 0x02, +0x58, 0x84, 0x06, 0xd4, 0x80, 0x09, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x85, 0x04, 0x84, 0x42, +0x4b, 0xe0, 0x20, 0x01, 0xc0, 0x32, 0x80, 0x09, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x85, 0x0c, +0x84, 0x42, 0x4b, 0xe0, 0x20, 0x01, 0xc8, 0x03, 0x84, 0xa2, 0xdf, 0x27, 0x50, 0x8f, 0x80, 0x04, +0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xd4, 0x80, 0x08, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, +0x85, 0x10, 0x84, 0x42, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x18, 0x80, 0x08, 0x46, 0x10, 0x00, 0x0b, +0x58, 0x10, 0x85, 0x08, 0x84, 0x42, 0x4b, 0xe0, 0x1c, 0x01, 0xc8, 0x0f, 0xa0, 0x72, 0x84, 0xa3, +0x01, 0xe0, 0x80, 0x01, 0x4d, 0xe2, 0xc0, 0x0a, 0xa4, 0xb6, 0x50, 0x03, 0x7f, 0xf8, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x8f, 0x34, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0xbc, 0x46, 0xf0, +0x00, 0x0b, 0x14, 0x17, 0x81, 0x94, 0x46, 0x40, 0x04, 0x00, 0x05, 0xe2, 0x00, 0x08, 0x42, 0x5f, +0x40, 0x09, 0x14, 0x52, 0x00, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x81, 0xb8, 0xdd, 0x2f, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x38, 0xb4, 0x60, 0xb6, 0x60, 0xa0, 0x81, 0xa8, 0x81, +0xa0, 0x42, 0xa8, 0x42, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x04, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x82, 0x28, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0xec, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0x80, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x01, 0xe8, 0x38, 0x12, 0x02, 0x0a, +0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x04, 0x50, 0x80, 0x78, 0x84, 0x41, 0x40, 0x41, +0x00, 0x0c, 0x40, 0x32, 0x14, 0x04, 0x14, 0x30, 0x80, 0x78, 0x04, 0x20, 0x80, 0x7a, 0x40, 0x02, +0x08, 0x04, 0x14, 0x00, 0x80, 0x7a, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x78, 0x96, 0x40, 0x96, 0x8c, 0xc2, 0x07, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x7a, 0x84, 0x01, 0xd5, 0x68, 0x54, 0x10, 0x80, 0x02, +0xc1, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x7b, 0x84, 0x02, 0xd5, 0x5f, 0x41, 0xe0, +0x40, 0x09, 0x54, 0x1f, 0x00, 0xff, 0x54, 0x50, 0x80, 0x02, 0xc5, 0x08, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x80, 0x8b, 0x44, 0x02, 0x00, 0x00, 0xd5, 0x51, 0x96, 0xcc, 0xc3, 0x08, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x17, 0x80, 0x8a, 0x44, 0x01, 0x00, 0x00, 0xd5, 0x48, 0x40, 0x10, 0x60, 0x09, +0x97, 0x0c, 0xc4, 0x08, 0x46, 0x00, 0x10, 0x00, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x92, +0xd5, 0x3d, 0x54, 0x50, 0x80, 0x02, 0xc5, 0x08, 0x46, 0x00, 0x20, 0x00, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x80, 0x93, 0xd5, 0x33, 0x54, 0x20, 0x80, 0x04, 0xc2, 0x08, 0x46, 0x00, 0x40, 0x00, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x94, 0xd5, 0x29, 0x54, 0x40, 0x80, 0x10, 0xc4, 0x08, +0x46, 0x01, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x96, 0xd5, 0x1f, 0x54, 0x50, +0x80, 0x20, 0xc5, 0x08, 0x46, 0x02, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x97, +0xd5, 0x15, 0x54, 0x20, 0x80, 0x40, 0xc2, 0x08, 0x46, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x80, 0x98, 0xd5, 0x0b, 0x54, 0x40, 0x80, 0x80, 0x96, 0x60, 0xc1, 0x07, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x17, 0x80, 0x99, 0x46, 0x08, 0x00, 0x00, 0x47, 0xe0, 0x04, 0x10, 0x59, 0xef, +0x08, 0x00, 0x14, 0x0f, 0x00, 0x78, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x04, 0x5f, +0x00, 0x78, 0xf5, 0x81, 0xdd, 0x21, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x44, 0x40, 0x00, 0x40, 0x84, 0xa0, 0xf5, 0x81, 0x46, 0x10, +0x04, 0x10, 0x10, 0x4f, 0x80, 0x04, 0x10, 0x4f, 0x80, 0x07, 0x58, 0x10, 0x88, 0x00, 0xb4, 0x61, +0x50, 0x60, 0x00, 0x9c, 0x58, 0x01, 0x80, 0x02, 0xb6, 0x01, 0x80, 0x01, 0xf2, 0x01, 0x14, 0x20, +0x80, 0x71, 0x04, 0x70, 0x00, 0x71, 0x42, 0x93, 0x8c, 0x0b, 0xf7, 0x81, 0x81, 0x01, 0x4e, 0x93, +0xff, 0xfa, 0x42, 0x73, 0x84, 0x0b, 0xcf, 0xf6, 0x46, 0x90, 0x00, 0x03, 0x58, 0x94, 0x8e, 0x20, +0x50, 0x13, 0x7f, 0x64, 0x50, 0x23, 0x7f, 0xe4, 0x50, 0x04, 0x01, 0xa0, 0x84, 0x62, 0x4b, 0xe0, +0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0x84, 0x50, 0x23, 0x7f, 0xec, 0x58, 0x00, +0x09, 0xb0, 0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x46, 0x90, 0x00, 0x03, +0x58, 0x94, 0x8d, 0xd4, 0x50, 0x13, 0x7f, 0xa4, 0x50, 0x23, 0x7f, 0xf4, 0x58, 0x00, 0x09, 0x80, +0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0xc4, 0x9e, 0xb4, +0x58, 0x00, 0x09, 0x90, 0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x61, 0xaf, 0xf5, 0xaf, 0xf4, +0x10, 0x34, 0x01, 0xa8, 0x10, 0x34, 0x01, 0xb8, 0x14, 0x73, 0x00, 0x09, 0xaf, 0xf7, 0xaf, 0xf6, +0xa9, 0xf4, 0xa9, 0xf5, 0xa9, 0xf2, 0xa9, 0xf3, 0x50, 0x03, 0x00, 0x1c, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8e, 0xd8, 0xdd, 0x2f, 0x04, 0x04, 0x00, 0x71, 0x58, 0x20, 0x00, 0x05, 0xf0, 0x81, +0x10, 0x2f, 0x80, 0x04, 0xf1, 0x01, 0x14, 0x14, 0x00, 0x71, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x42, 0x11, 0x40, 0x08, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x42, 0x11, 0x44, 0x08, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x58, 0x11, 0x00, 0x01, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x58, 0x11, 0x00, 0x02, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0x3c, 0xef, 0xf4, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, +0x08, 0x00, 0x50, 0x10, 0x00, 0x80, 0x85, 0x20, 0x04, 0x40, 0x00, 0x43, 0x40, 0x32, 0x40, 0x09, +0x54, 0x31, 0x80, 0x0f, 0x80, 0x40, 0xc3, 0x64, 0x84, 0x40, 0x97, 0x5c, 0xc5, 0x5c, 0x54, 0x61, +0x00, 0x03, 0x14, 0x60, 0x00, 0x43, 0x84, 0xc0, 0x04, 0x80, 0x00, 0x43, 0x40, 0x44, 0x20, 0x09, +0x54, 0x42, 0x00, 0x7f, 0x40, 0x72, 0x20, 0x08, 0x40, 0x53, 0x90, 0x04, 0x14, 0x50, 0x00, 0x1d, +0x44, 0x7f, 0xff, 0xc7, 0x04, 0xa0, 0x80, 0x02, 0xb5, 0x01, 0x14, 0xaf, 0x80, 0x01, 0x8d, 0x04, +0x00, 0xaf, 0x80, 0x07, 0x80, 0xa4, 0x40, 0xa5, 0x1c, 0x02, 0x58, 0xa5, 0x00, 0x20, 0x10, 0xaf, +0x80, 0x07, 0x54, 0x74, 0x00, 0x7f, 0x40, 0xa4, 0x1c, 0x09, 0x40, 0x74, 0x9c, 0x06, 0x04, 0x8f, +0x80, 0x01, 0x88, 0xea, 0x14, 0x80, 0x80, 0x02, 0x50, 0x83, 0xff, 0xff, 0xd5, 0x08, 0x14, 0xa0, +0x00, 0x1b, 0x9d, 0xb1, 0x04, 0xa0, 0x00, 0x1b, 0x54, 0x55, 0x00, 0x7f, 0x40, 0xa2, 0xa0, 0x08, +0xe2, 0xc8, 0xe9, 0xf6, 0x54, 0x63, 0x80, 0x7f, 0x40, 0x63, 0x20, 0x08, 0x40, 0x52, 0xc0, 0x08, +0x58, 0x73, 0x00, 0x02, 0x58, 0x63, 0x00, 0x18, 0x40, 0x73, 0x94, 0x04, 0x40, 0x53, 0x14, 0x04, +0x46, 0x68, 0x0f, 0xff, 0x58, 0x63, 0x0f, 0xff, 0x40, 0x42, 0x60, 0x08, 0x40, 0x52, 0x98, 0x02, +0x40, 0x73, 0x98, 0x02, 0x40, 0x73, 0x90, 0x04, 0x40, 0x42, 0x90, 0x04, 0x14, 0x40, 0x00, 0x44, +0x14, 0x70, 0x00, 0x45, 0x9c, 0x91, 0x84, 0xa4, 0xd2, 0x98, 0x92, 0x61, 0xd5, 0x9f, 0x46, 0x00, +0x20, 0x00, 0x14, 0x01, 0x00, 0x78, 0xec, 0x0c, 0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0x3c, 0xef, 0xf4, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x50, 0x10, +0x00, 0x80, 0x85, 0x20, 0x04, 0x40, 0x00, 0x40, 0x40, 0x32, 0x40, 0x09, 0x54, 0x31, 0x80, 0x0f, +0x80, 0x40, 0xc3, 0x6a, 0x84, 0x40, 0x97, 0x5c, 0xc5, 0x62, 0x54, 0x61, 0x00, 0x03, 0x14, 0x60, +0x00, 0x40, 0x84, 0xc0, 0x04, 0x80, 0x00, 0x40, 0x40, 0x44, 0x20, 0x09, 0x54, 0x42, 0x00, 0x7f, +0x40, 0x72, 0x20, 0x08, 0x40, 0x53, 0x90, 0x04, 0x14, 0x50, 0x00, 0x1d, 0x44, 0x7f, 0xff, 0xc7, +0x04, 0xa0, 0x80, 0x02, 0xb5, 0x01, 0x14, 0xaf, 0x80, 0x01, 0x8d, 0x04, 0x00, 0xaf, 0x80, 0x07, +0x80, 0xa4, 0x40, 0xa5, 0x1c, 0x02, 0x58, 0xa5, 0x00, 0x28, 0x10, 0xaf, 0x80, 0x07, 0x54, 0x74, +0x00, 0x7f, 0x40, 0xa4, 0x1c, 0x09, 0x40, 0x74, 0x9c, 0x06, 0x04, 0x8f, 0x80, 0x01, 0x88, 0xea, +0x14, 0x80, 0x80, 0x02, 0x50, 0x83, 0xff, 0xff, 0xd5, 0x08, 0x14, 0xa0, 0x00, 0x1b, 0x9d, 0xb1, +0x04, 0xa0, 0x00, 0x1b, 0x54, 0x55, 0x00, 0x7f, 0x40, 0xa2, 0xa0, 0x08, 0xe2, 0xc8, 0xe9, 0xf6, +0x00, 0x8f, 0x80, 0x07, 0x54, 0x63, 0x80, 0x7f, 0x40, 0x74, 0x04, 0x09, 0x40, 0x63, 0x20, 0x08, +0x54, 0x73, 0x80, 0x03, 0x40, 0x82, 0xc0, 0x08, 0x40, 0x73, 0x98, 0x04, 0x40, 0x53, 0xa0, 0x04, +0x58, 0x63, 0x00, 0x02, 0x46, 0x78, 0x0f, 0xff, 0x40, 0x63, 0x20, 0x04, 0x58, 0x73, 0x8f, 0xff, +0x40, 0x82, 0x60, 0x08, 0x40, 0x52, 0x9c, 0x02, 0x40, 0x63, 0x1c, 0x02, 0x40, 0x63, 0x20, 0x04, +0x40, 0x42, 0xa0, 0x04, 0x14, 0x40, 0x00, 0x41, 0x14, 0x60, 0x00, 0x42, 0x9c, 0x91, 0x84, 0xa4, +0xd2, 0x92, 0x92, 0x61, 0xd5, 0x99, 0x46, 0x00, 0x10, 0x00, 0x14, 0x01, 0x00, 0x78, 0xec, 0x0c, +0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0x3c, 0x04, 0x50, 0x00, 0x29, +0x04, 0x30, 0x00, 0x2a, 0x9d, 0x2a, 0x9a, 0xa3, 0xe4, 0x42, 0x4e, 0xf3, 0x00, 0x85, 0x00, 0x30, +0x00, 0xa2, 0x9c, 0x9c, 0x40, 0x81, 0x10, 0x08, 0x40, 0x20, 0x20, 0x00, 0xa7, 0xd7, 0x54, 0x63, +0x80, 0x80, 0xc6, 0x79, 0xb5, 0x01, 0x50, 0x41, 0x80, 0x24, 0x38, 0x80, 0x12, 0x0a, 0x00, 0x70, +0x80, 0x9f, 0x00, 0x50, 0x80, 0x9e, 0xa1, 0x0b, 0x99, 0xbd, 0x50, 0x73, 0x00, 0x14, 0x50, 0x50, +0x80, 0x10, 0x02, 0x81, 0x00, 0x03, 0x95, 0x9c, 0xc4, 0x22, 0x93, 0x0e, 0x40, 0x84, 0x38, 0x08, +0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0xb6, 0xa2, 0xa7, 0x17, 0x42, 0x42, 0x18, 0x09, 0xaf, 0x17, +0x99, 0x86, 0xa1, 0x4a, 0x14, 0x53, 0x00, 0x12, 0xa1, 0x0b, 0xa4, 0x52, 0x54, 0x42, 0x3f, 0xff, +0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x50, 0x90, 0x04, 0xad, 0x52, 0xa7, 0x17, 0xa6, 0x55, +0x54, 0x52, 0x00, 0x7f, 0x58, 0x10, 0x80, 0x40, 0xaf, 0x57, 0xd5, 0x1b, 0x93, 0x0e, 0x40, 0x84, +0x38, 0x08, 0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0x99, 0x86, 0xa6, 0x57, 0xb6, 0xa2, 0x58, 0x10, +0x80, 0x40, 0xae, 0x57, 0x14, 0x43, 0x00, 0x12, 0xa4, 0x52, 0xa7, 0x17, 0x92, 0x2e, 0x40, 0x10, +0xb8, 0x08, 0xac, 0x52, 0x54, 0x42, 0x00, 0x7f, 0xa6, 0x55, 0xaf, 0x17, 0x42, 0x10, 0x98, 0x09, +0x95, 0x1c, 0xae, 0x55, 0x98, 0x44, 0x50, 0x10, 0x80, 0x48, 0xa6, 0x8e, 0x44, 0x5f, 0xff, 0xcf, +0x40, 0x41, 0x14, 0x02, 0x58, 0x22, 0x00, 0x08, 0x9c, 0xdc, 0x84, 0x84, 0xaf, 0x0f, 0xae, 0x8e, +0x40, 0x51, 0x90, 0x0c, 0x99, 0x05, 0xa4, 0xa3, 0xb4, 0x61, 0x54, 0x51, 0x3f, 0xff, 0x99, 0x1d, +0xad, 0x0a, 0x46, 0x40, 0x04, 0x10, 0x00, 0x20, 0x00, 0xa2, 0x04, 0x50, 0x00, 0x2a, 0x9c, 0x51, +0x96, 0x8c, 0x9c, 0xe9, 0x58, 0x42, 0x08, 0x00, 0x14, 0x30, 0x00, 0x2a, 0x10, 0x20, 0x00, 0xa2, +0x10, 0x22, 0x01, 0x88, 0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x04, 0x50, 0x00, 0x2b, +0x04, 0x30, 0x00, 0x2c, 0x9d, 0x2a, 0x9a, 0xa3, 0xe4, 0x42, 0xe9, 0x3e, 0x00, 0x30, 0x00, 0xa3, +0x9d, 0x1e, 0x94, 0xa4, 0x98, 0x82, 0xa7, 0x57, 0x54, 0x42, 0x80, 0x80, 0xc4, 0x35, 0x50, 0x51, +0x80, 0x26, 0x38, 0x10, 0x16, 0x0a, 0x94, 0xdc, 0xa1, 0x0a, 0x98, 0xc3, 0xb6, 0x82, 0xa1, 0x4c, +0x14, 0x51, 0x80, 0x1b, 0xa5, 0x0e, 0xa4, 0xd3, 0x54, 0x42, 0x3f, 0xff, 0x92, 0x6e, 0x40, 0x31, +0xb8, 0x08, 0x40, 0x51, 0x90, 0x04, 0xad, 0x53, 0xa7, 0x55, 0x00, 0x40, 0x80, 0x0f, 0xa6, 0xd7, +0x96, 0x64, 0x95, 0x0e, 0x54, 0x11, 0x80, 0x3f, 0x40, 0x30, 0x90, 0x04, 0x54, 0x12, 0x80, 0x7f, +0xae, 0xd7, 0xae, 0x55, 0x46, 0x10, 0x04, 0x10, 0x00, 0x50, 0x00, 0xa3, 0x04, 0x40, 0x00, 0x2c, +0x9c, 0xa9, 0x97, 0x54, 0x9c, 0xe1, 0x58, 0x10, 0x88, 0x00, 0x14, 0x30, 0x00, 0x2c, 0x10, 0x50, +0x00, 0xa3, 0x10, 0x50, 0x81, 0x98, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, +0x80, 0xc0, 0x46, 0x80, 0x00, 0x00, 0x58, 0x84, 0x03, 0x68, 0xd5, 0x22, 0xa7, 0x1f, 0x54, 0x22, +0x00, 0x80, 0xc2, 0x30, 0x38, 0x23, 0x06, 0x02, 0x38, 0x93, 0x06, 0x0a, 0x80, 0x22, 0x00, 0x31, +0x00, 0x14, 0xcb, 0x02, 0xd5, 0x05, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x54, 0x4b, 0xe0, +0x20, 0x01, 0x9c, 0x3e, 0x94, 0xc4, 0x99, 0xf3, 0xa6, 0xbf, 0x44, 0x4f, 0xff, 0xc0, 0x40, 0x51, +0x10, 0x04, 0xaf, 0x7f, 0x04, 0x13, 0x00, 0x2b, 0x9c, 0x09, 0x14, 0x03, 0x00, 0x2b, 0x04, 0x23, +0x00, 0x2b, 0x04, 0x53, 0x00, 0x2c, 0x97, 0xd4, 0x9c, 0x7e, 0x95, 0x0c, 0x41, 0xe2, 0x88, 0x01, +0x50, 0x13, 0x80, 0x26, 0x98, 0xf4, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0x4f, 0xe6, +0xff, 0xcf, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0x46, 0x80, 0x00, 0x00, 0x58, 0x84, 0x03, 0x68, 0xd5, 0x1a, +0xa6, 0xff, 0x54, 0x11, 0x80, 0x80, 0xc1, 0x28, 0x38, 0x13, 0x0a, 0x02, 0x38, 0x93, 0x0a, 0x0a, +0x4b, 0xe0, 0x20, 0x01, 0xa6, 0x7f, 0xa6, 0xfd, 0x44, 0x0f, 0xff, 0xc0, 0x40, 0x50, 0x80, 0x04, +0x58, 0x41, 0x80, 0x40, 0xaf, 0x7f, 0xaf, 0x3d, 0x04, 0x23, 0x00, 0x29, 0x9c, 0x11, 0x14, 0x03, +0x00, 0x29, 0x04, 0x43, 0x00, 0x29, 0x04, 0x53, 0x00, 0x2a, 0x96, 0x64, 0x9c, 0xcc, 0x95, 0xdc, +0x41, 0xe2, 0x90, 0x01, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x54, 0x50, 0x20, 0x80, 0x24, +0x99, 0xf7, 0x4f, 0xe6, 0xff, 0xd7, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, 0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, +0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, 0x00, 0xa1, 0x00, 0x12, 0x01, 0xbc, 0x9d, 0x7a, +0x94, 0xac, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x54, 0x50, 0xa3, 0x80, 0x22, 0x40, 0x6e, +0x08, 0x00, 0x4c, 0x70, 0x80, 0x55, 0xa6, 0x77, 0x55, 0xe0, 0x80, 0x80, 0x4f, 0xe2, 0x00, 0x50, +0x02, 0x83, 0x00, 0x03, 0xb6, 0x9f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, +0x54, 0x94, 0x3f, 0xff, 0x95, 0x3c, 0x81, 0x00, 0x40, 0x3e, 0x10, 0x00, 0xf0, 0x01, 0xb4, 0x9f, +0x4e, 0x83, 0x00, 0x07, 0xbb, 0x2d, 0x42, 0x01, 0xc4, 0x08, 0xb8, 0xad, 0xd5, 0x38, 0x39, 0xee, +0x2a, 0x02, 0x84, 0x41, 0x12, 0x9f, 0x00, 0x06, 0x80, 0x3e, 0x04, 0x51, 0x80, 0x0b, 0x10, 0x2f, +0x00, 0x14, 0x14, 0x5f, 0x00, 0x04, 0xb6, 0x9f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x68, +0xdd, 0x2f, 0x38, 0x8e, 0x2a, 0x0a, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xa6, 0xf7, 0x04, 0x84, 0x00, 0x02, 0x58, 0x01, +0x80, 0x40, 0xae, 0x37, 0xa4, 0x73, 0xb7, 0x06, 0x40, 0x50, 0xb8, 0x09, 0x40, 0x52, 0xb8, 0x08, +0x58, 0x22, 0x86, 0x40, 0xac, 0xb3, 0xb4, 0x9f, 0x10, 0x72, 0x01, 0xb8, 0x00, 0xae, 0x00, 0xa1, +0x50, 0x75, 0x00, 0x01, 0x97, 0xbc, 0x10, 0x6e, 0x00, 0xa1, 0xd5, 0x9e, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, 0x50, 0x00, 0x00, 0xb8, +0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, 0x00, 0xa0, 0x00, 0x52, +0x01, 0xac, 0x94, 0xbc, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0x50, 0xa3, 0x80, 0x20, +0x40, 0x6e, 0x08, 0x00, 0xd7, 0x54, 0x01, 0xe3, 0x00, 0x07, 0x54, 0x5f, 0x00, 0x80, 0xc5, 0x4f, +0x02, 0x83, 0x00, 0x03, 0xb6, 0x9f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, +0x98, 0x7f, 0x54, 0x94, 0x3f, 0xff, 0x81, 0x00, 0x9c, 0x09, 0x95, 0x03, 0x40, 0x3e, 0x10, 0x00, +0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x06, 0x44, 0x31, 0x00, 0x00, 0xbb, 0xad, 0xd5, 0x37, +0x39, 0xee, 0x2a, 0x02, 0x84, 0x40, 0x12, 0x9f, 0x00, 0x06, 0x80, 0x3e, 0xa1, 0x59, 0x10, 0x2f, +0x00, 0x14, 0x14, 0x5f, 0x00, 0x04, 0xb6, 0x9f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x68, +0xdd, 0x2f, 0x38, 0x8e, 0x2a, 0x0a, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xa6, 0xf7, 0x04, 0x84, 0x00, 0x02, 0x58, 0x11, +0x80, 0x40, 0xae, 0x77, 0xa5, 0x33, 0xb7, 0x06, 0x40, 0x52, 0x38, 0x09, 0x40, 0x52, 0xb8, 0x08, +0x58, 0x22, 0x80, 0xc8, 0xac, 0xb3, 0xb4, 0x9f, 0x10, 0x72, 0x01, 0xa8, 0x00, 0xae, 0x00, 0xa0, +0x50, 0x75, 0x00, 0x01, 0x97, 0xbc, 0x10, 0x6e, 0x00, 0xa0, 0xd5, 0xa0, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xb6, 0x20, 0xa8, 0xc1, 0x80, 0xc1, +0xa0, 0x43, 0x84, 0xe0, 0x81, 0x23, 0x81, 0x02, 0xa8, 0x42, 0x47, 0xc0, 0x01, 0x02, 0x59, 0xce, +0x07, 0x08, 0x81, 0x47, 0xd5, 0x0c, 0xdd, 0x3c, 0xa6, 0xb7, 0x44, 0x3f, 0xff, 0xc0, 0x40, 0x01, +0x0c, 0x04, 0xae, 0x37, 0x1c, 0xa4, 0x00, 0x01, 0x9d, 0xf9, 0x8c, 0xd0, 0x80, 0x06, 0x84, 0x20, +0x44, 0x20, 0x00, 0x10, 0xe2, 0xe9, 0xe9, 0xf0, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0xb6, 0x20, 0xa8, 0xc1, 0x46, 0x80, 0x04, 0x10, 0x04, 0x90, +0x00, 0x03, 0x58, 0x84, 0x09, 0xb0, 0x14, 0x90, 0x00, 0x02, 0x44, 0x70, 0x06, 0x40, 0x83, 0x83, +0x80, 0xc1, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x83, 0x54, 0x40, 0x10, 0x20, 0x03, 0x44, 0x50, +0x00, 0xc8, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0x40, 0x41, 0x84, 0x1a, 0x40, 0x40, +0x04, 0x1b, 0x40, 0x82, 0x84, 0x1b, 0x40, 0x83, 0x84, 0x1a, 0x84, 0xe0, 0xf4, 0x83, 0x81, 0x42, +0x46, 0x40, 0x01, 0x02, 0x58, 0x42, 0x07, 0x08, 0x81, 0x27, 0x54, 0x34, 0x3f, 0xff, 0xd5, 0x26, +0xf3, 0x81, 0xf4, 0x82, 0xdd, 0x24, 0xf0, 0x03, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, +0xdd, 0x2f, 0xf3, 0x01, 0xf4, 0x02, 0xc0, 0x20, 0x12, 0x80, 0x00, 0x06, 0x10, 0x90, 0x00, 0x0e, +0x10, 0x90, 0x00, 0x0f, 0xa6, 0x77, 0x9d, 0xf9, 0x55, 0xe0, 0x80, 0x3f, 0x11, 0xe3, 0x00, 0x07, +0xa5, 0x73, 0x40, 0x12, 0xb8, 0x09, 0x40, 0x10, 0xb8, 0x08, 0x41, 0xe0, 0x8c, 0x04, 0x13, 0xe3, +0x00, 0x03, 0xa0, 0x82, 0xaa, 0xb4, 0x1c, 0x05, 0x00, 0x01, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, +0x00, 0x10, 0xe2, 0xfc, 0xe9, 0xd6, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x08, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x69, 0x84, 0xa1, 0xd8, 0x0b, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x00, 0x04, 0xb4, 0x80, 0x54, 0x32, 0x01, 0xfd, 0x58, 0x11, 0x80, 0x02, +0xd5, 0x08, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x04, 0xb4, 0xa0, 0x54, 0x12, 0x81, 0xfd, +0xb6, 0x20, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x08, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, +0x04, 0x00, 0x58, 0x63, 0x00, 0x04, 0x84, 0xe0, 0x85, 0x08, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, +0x86, 0x08, 0x84, 0x01, 0x4b, 0xe0, 0x24, 0x01, 0xb4, 0x46, 0x99, 0xff, 0x54, 0x11, 0x00, 0x08, +0x84, 0x01, 0x97, 0xf8, 0xc1, 0x03, 0x40, 0x73, 0x80, 0x04, 0x05, 0xe3, 0x00, 0x00, 0x8f, 0x01, +0x54, 0x5f, 0x01, 0xfe, 0x58, 0x42, 0x80, 0x01, 0xb6, 0x86, 0x54, 0x84, 0x00, 0xff, 0x4b, 0xe0, +0x24, 0x01, 0xb4, 0x66, 0x54, 0x01, 0x81, 0xfe, 0xb6, 0x06, 0x4e, 0x83, 0xff, 0xe4, 0x84, 0x08, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x08, 0xdd, 0x2f, 0x80, 0x07, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x04, 0x00, 0x97, 0xc0, +0x58, 0x63, 0x00, 0x04, 0x85, 0x28, 0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x06, 0x08, 0xb4, 0x46, +0x40, 0x33, 0x9c, 0x09, 0x94, 0x5a, 0x55, 0xe1, 0x01, 0xfb, 0x40, 0x00, 0xf8, 0x04, 0xb6, 0x06, +0x84, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0xa6, 0x84, 0x01, 0x54, 0x42, 0x81, 0xfe, 0x40, 0x32, +0x00, 0x04, 0xb6, 0x66, 0x8f, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0x46, 0x84, 0x01, 0x54, 0x11, +0x01, 0xfe, 0xb6, 0x26, 0x99, 0xff, 0x54, 0x94, 0x80, 0xff, 0x4b, 0xe0, 0x20, 0x01, 0x97, 0xf8, +0x4e, 0x93, 0xff, 0xdf, 0x84, 0x0a, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x08, 0xdd, 0x2f, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x00, 0x0b, +0x00, 0x07, 0x86, 0x69, 0x84, 0xa1, 0xd8, 0x16, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x00, 0x04, +0x05, 0xe3, 0x00, 0x00, 0x54, 0x5f, 0x01, 0xfd, 0x58, 0x42, 0x80, 0x02, 0xb6, 0x86, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0x08, 0xdd, 0x2f, 0xb4, 0x66, 0x54, 0x21, 0x81, 0xfd, 0xb6, 0x46, +0xd5, 0x09, 0x46, 0x60, 0x04, 0x00, 0xa0, 0xb1, 0x54, 0x01, 0x01, 0xfd, 0x58, 0x10, 0x00, 0x02, +0xa8, 0x71, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x08, 0xdd, 0x2f, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0x18, +0xdd, 0x2f, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0xa4, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x03, 0x58, 0xf7, 0x8f, 0x38, 0xdd, 0x2f, 0x80, 0xc0, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8e, 0xe0, 0xdd, 0x2f, 0x96, 0x34, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x97, 0x81, 0x97, 0xca, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0x18, 0xdd, 0x2f, +0x84, 0x03, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0xa4, 0xdd, 0x2f, 0xcf, 0x05, 0x44, 0x00, +0xfc, 0x00, 0x40, 0x63, 0x00, 0x04, 0x46, 0x70, 0x00, 0x03, 0x58, 0x73, 0x8f, 0xa4, 0x40, 0x03, +0x20, 0x09, 0x4b, 0xe0, 0x1c, 0x01, 0x96, 0x30, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8f, 0x38, 0xdd, 0x2f, 0x80, 0xc0, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8e, 0xe0, +0xdd, 0x2f, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x0f, 0xa4, 0x54, 0x80, 0x80, 0xff, 0x97, 0xc1, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x80, 0x18, 0xdd, 0x2f, 0x84, 0x02, 0xdd, 0x26, 0x40, 0x03, 0xa0, 0x09, +0xdd, 0x26, 0x96, 0x38, 0xdd, 0x26, 0x80, 0x08, 0xdd, 0x26, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, +0x00, 0x74, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0x4b, 0xe0, 0x18, 0x01, +0xc8, 0xfe, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x80, 0x18, 0xdd, 0x2f, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8f, 0xa4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x80, 0x18, 0xdd, 0x2f, 0x84, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8f, 0xa4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x00, 0x80, 0x01, 0x84, 0x48, +0x14, 0x20, 0x81, 0x06, 0x14, 0x20, 0x01, 0x0a, 0xdd, 0x9e, 0x92, 0x00, 0xef, 0xf8, 0x46, 0x10, +0x00, 0x0e, 0x04, 0x40, 0x80, 0x9a, 0x46, 0x30, 0x04, 0x00, 0x9c, 0xa1, 0x14, 0x20, 0x80, 0x9a, +0x58, 0x31, 0x84, 0x00, 0xb4, 0x03, 0x46, 0x10, 0x04, 0x00, 0x58, 0x50, 0x00, 0x11, 0xb6, 0xa3, +0x04, 0x40, 0x81, 0x06, 0x58, 0x22, 0x00, 0x80, 0x14, 0x20, 0x81, 0x06, 0xb4, 0x03, 0xf0, 0x81, +0xec, 0x08, 0xdd, 0x9e, 0x46, 0x30, 0x04, 0x00, 0x80, 0x03, 0x44, 0x20, 0x00, 0x4e, 0x44, 0x10, +0x00, 0xa8, 0x14, 0x21, 0x81, 0x04, 0x14, 0x10, 0x01, 0x06, 0xdd, 0x9e, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x07, 0x80, 0x9a, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0x48, +0x84, 0x80, 0xb6, 0x80, 0x84, 0x21, 0xb4, 0x60, 0xa8, 0xc1, 0xa8, 0x42, 0xb4, 0x40, 0xa1, 0x42, +0x9f, 0x29, 0x40, 0x32, 0x08, 0x02, 0x9c, 0x5a, 0x95, 0x4a, 0x98, 0xc5, 0x46, 0x40, 0x00, 0x0e, +0x58, 0x42, 0x06, 0x34, 0xa9, 0x19, 0xb4, 0x40, 0x9c, 0x51, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x82, 0x68, 0xb4, 0x41, 0x98, 0x02, 0xd5, 0x03, 0x64, 0x00, +0x00, 0x00, 0xb4, 0x81, 0x9a, 0xe0, 0x4e, 0x35, 0xff, 0xfc, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, +0xdd, 0x2f, 0xa0, 0x32, 0xc0, 0x2d, 0x84, 0xa2, 0xd0, 0x2b, 0x84, 0xa3, 0xd8, 0x02, 0xd5, 0x28, +0xa0, 0x33, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x80, 0x9b, 0xd0, 0x07, 0xa0, 0x41, 0x05, 0xe3, +0x00, 0x01, 0x40, 0x50, 0xf8, 0x00, 0xa9, 0x41, 0xa0, 0x73, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x02, 0x6c, 0x4c, 0x13, 0x40, 0x05, 0x84, 0x40, 0xb6, 0x40, 0xd5, 0x0d, 0x05, 0xe3, 0x00, 0x04, +0x14, 0x1f, 0x00, 0x03, 0xa1, 0x33, 0xa1, 0x74, 0xa9, 0x64, 0xb4, 0x60, 0x4c, 0x33, 0x40, 0x04, +0xa0, 0x73, 0xb6, 0x20, 0x84, 0x00, 0x84, 0x43, 0xa8, 0x34, 0xa8, 0xb2, 0xa8, 0x33, 0xf0, 0x01, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xe1, 0x80, 0xc0, 0xc1, 0x7a, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, 0x84, 0x01, +0xa8, 0x32, 0x46, 0x30, 0x00, 0x0e, 0x04, 0x21, 0x80, 0x9b, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x02, 0x74, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x82, 0x68, 0xca, 0x0b, 0xa9, 0xb3, 0xa9, 0xb4, +0x14, 0x61, 0x80, 0x9b, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x77, 0x80, 0x9c, 0xa9, 0xf1, 0xd5, 0x39, +0xb4, 0x21, 0xb4, 0x00, 0xe2, 0x20, 0xe8, 0x03, 0x9a, 0x01, 0xd5, 0x02, 0x9a, 0x08, 0x44, 0x10, +0x00, 0x21, 0x40, 0x00, 0x04, 0x37, 0xa0, 0x51, 0xe2, 0x01, 0xe8, 0x03, 0x9a, 0x08, 0xd5, 0x02, +0x84, 0x00, 0xa8, 0x11, 0xa0, 0xd1, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0x9b, 0x46, 0xf0, +0x00, 0x0e, 0x14, 0x37, 0x80, 0x9c, 0xa0, 0x11, 0xe2, 0xe0, 0xe8, 0x0b, 0x9a, 0x07, 0xa8, 0x11, +0x46, 0x00, 0x00, 0x0e, 0x04, 0x50, 0x00, 0x9b, 0xda, 0x20, 0x14, 0x60, 0x00, 0x9b, 0xd5, 0x1d, +0xa0, 0x93, 0x9b, 0xf8, 0x4c, 0x20, 0xff, 0xf1, 0xd5, 0x18, 0x14, 0x00, 0x80, 0x9c, 0xc0, 0x0c, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x82, 0x68, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x02, 0x74, +0xb4, 0x41, 0xb6, 0x40, 0xd5, 0x03, 0x84, 0x22, 0xa8, 0x72, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xd5, 0x16, 0xa8, 0xb3, 0xa0, 0x14, 0x46, 0x10, 0x00, 0x0e, +0xa8, 0x34, 0x05, 0xe1, 0x00, 0x04, 0x14, 0x6f, 0x00, 0x03, 0xa9, 0x94, 0xa9, 0xf1, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x37, 0x80, 0x9b, 0x04, 0x40, 0x80, 0x9c, 0xa0, 0x19, 0xe2, 0x80, 0xe8, 0xd6, +0xd5, 0xe5, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0x48, 0xa0, 0xc9, 0xa1, 0x4a, 0xf0, 0x01, 0x9f, 0x29, +0x40, 0x22, 0x0c, 0x02, 0x9d, 0x92, 0x95, 0x72, 0x99, 0x0d, 0xa1, 0xa1, 0xa0, 0xc9, 0x9c, 0x99, +0xa8, 0x89, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0x84, 0x00, 0xa8, 0x34, +0xb6, 0x06, 0xa8, 0x31, 0xa8, 0x32, 0xa8, 0x33, 0x80, 0x06, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, +0x80, 0x9a, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x80, 0xd4, 0x9a, 0x0a, 0x4e, 0x05, 0x00, 0x07, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x98, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x01, 0x84, 0x21, 0xa8, 0x42, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x00, 0x04, 0x01, 0x84, 0x20, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x01, +0x96, 0x00, 0xa8, 0x09, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x01, 0x84, 0x22, 0xa8, 0x42, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x01, 0x04, 0x00, 0x81, 0x8a, 0x96, 0x04, 0xc0, 0x04, +0x84, 0x41, 0x14, 0x20, 0x81, 0x8a, 0xdd, 0x9e, 0x46, 0x20, 0x04, 0x01, 0xa0, 0x52, 0x56, 0x00, +0x80, 0x04, 0x42, 0x00, 0x08, 0x0b, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x50, 0x04, 0x00, +0x46, 0x60, 0x04, 0x01, 0x58, 0x63, 0x06, 0x8c, 0x04, 0x82, 0x80, 0x80, 0xb4, 0x86, 0x46, 0x70, +0x00, 0x04, 0x58, 0x73, 0x86, 0x14, 0x58, 0x02, 0x00, 0x40, 0xb6, 0x06, 0x44, 0x00, 0x00, 0xff, +0xdd, 0x27, 0x44, 0x00, 0x00, 0xff, 0xdd, 0x27, 0x44, 0x00, 0x00, 0xff, 0xdd, 0x27, 0x44, 0x00, +0x00, 0xff, 0xdd, 0x27, 0xb4, 0x66, 0x42, 0x11, 0x98, 0x09, 0x54, 0x04, 0x00, 0x03, 0xb6, 0x26, +0xc8, 0x14, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x04, 0xb4, 0x80, 0x46, 0x3f, 0xf0, 0xff, +0x58, 0x22, 0x00, 0x01, 0xb6, 0x40, 0x05, 0xe0, 0x00, 0x00, 0x58, 0x31, 0x8f, 0xff, 0x50, 0x10, +0x00, 0x08, 0x40, 0x2f, 0x0c, 0x02, 0xd5, 0x19, 0x84, 0xa1, 0xd8, 0x1c, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x02, 0x04, 0xb4, 0xa0, 0x42, 0x42, 0x80, 0x09, 0xb6, 0x80, 0x46, 0x3f, 0xf0, 0xff, +0xb4, 0x40, 0x58, 0x31, 0x8f, 0xff, 0x41, 0xe1, 0x0c, 0x02, 0x15, 0xe0, 0x00, 0x00, 0xb4, 0xa0, +0x50, 0x10, 0x00, 0x08, 0x42, 0x22, 0xd0, 0x08, 0xb6, 0x40, 0xb4, 0x41, 0x58, 0x01, 0x03, 0x00, +0xb6, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0x3c, 0x96, 0xd8, 0x96, 0x90, +0xcb, 0x15, 0x54, 0x21, 0x00, 0xfc, 0xd5, 0x0f, 0x38, 0x41, 0x84, 0x02, 0x9c, 0xdc, 0x40, 0x52, +0x60, 0x09, 0x40, 0x72, 0x20, 0x09, 0x40, 0x62, 0x40, 0x09, 0xa9, 0xc1, 0xa9, 0x82, 0xa9, 0x43, +0xb6, 0x80, 0x8c, 0x10, 0x4c, 0x31, 0x7f, 0xf2, 0xd5, 0x0c, 0x84, 0xa1, 0xdb, 0x0a, 0x84, 0x60, +0xd5, 0x05, 0xa3, 0xc9, 0x38, 0x71, 0x80, 0x08, 0x9c, 0xd9, 0x97, 0x18, 0xe2, 0x82, 0xe9, 0xfa, +0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x01, 0x96, 0x89, 0xe2, 0x02, 0xe8, 0x02, +0x80, 0x20, 0x96, 0x09, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x00, 0x96, 0x88, 0xe2, 0x02, 0xe8, 0x02, +0x80, 0x20, 0x96, 0x08, 0xdd, 0x9e, 0x92, 0x00, 0xd5, 0x03, 0x92, 0x00, 0x9e, 0x01, 0x96, 0x00, +0xc8, 0xfd, 0xdd, 0x9e, 0xd5, 0x08, 0x44, 0x10, 0x00, 0xff, 0x92, 0x00, 0x9e, 0x49, 0x96, 0x48, +0xc9, 0xfd, 0x9e, 0x01, 0x96, 0x00, 0xc8, 0xf8, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x20, 0x00, 0x0e, +0x58, 0x21, 0x02, 0x78, 0xb4, 0x22, 0xc1, 0x08, 0xd5, 0x09, 0x84, 0x2a, 0x92, 0x00, 0x9e, 0xc9, +0x96, 0x58, 0xc9, 0xfd, 0x9e, 0x01, 0xc8, 0xfa, 0xd5, 0x0b, 0x8c, 0x1f, 0x92, 0x05, 0xd5, 0x07, +0x84, 0x28, 0x92, 0x00, 0x9f, 0x09, 0x96, 0x60, 0xc9, 0xfd, 0x9e, 0x01, 0xc8, 0xfa, 0xdd, 0x9e, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x96, 0x00, 0x54, 0xa0, 0x80, 0xff, 0x46, 0x10, +0x00, 0x0b, 0x58, 0x10, 0x85, 0x20, 0x97, 0xd1, 0x40, 0x80, 0x04, 0x00, 0x84, 0xc0, 0x46, 0x90, +0x00, 0x04, 0x58, 0x94, 0x80, 0xac, 0xd5, 0x09, 0x4b, 0xe0, 0x24, 0x01, 0x9d, 0xb1, 0x9d, 0xf9, +0x18, 0x04, 0x00, 0x01, 0x97, 0xb0, 0x97, 0xf9, 0x80, 0x07, 0x84, 0x20, 0xe2, 0xca, 0xe9, 0xf5, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x04, 0x00, +0x04, 0x10, 0x00, 0x09, 0x4e, 0x14, 0x00, 0x04, 0x84, 0x21, 0xd5, 0x02, 0x84, 0x20, 0x46, 0xf0, +0x00, 0x0b, 0x10, 0x17, 0x86, 0x69, 0x44, 0x00, 0x00, 0x11, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0x54, 0x30, 0x00, 0x0f, 0x84, 0xa2, 0xdb, 0x0e, 0x54, 0x40, +0x00, 0x10, 0xc4, 0x09, 0x46, 0x50, 0x04, 0x00, 0x05, 0xe2, 0x80, 0x08, 0x42, 0x6f, 0x2c, 0x09, +0x14, 0x62, 0x80, 0x08, 0x84, 0x20, 0xd5, 0x02, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, +0x86, 0x68, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x68, 0xc8, 0x47, 0x46, 0x60, 0x00, 0x04, +0x58, 0x63, 0x06, 0x64, 0x84, 0x02, 0x84, 0x21, 0x94, 0x83, 0xdd, 0x26, 0x84, 0x08, 0x84, 0x26, +0x44, 0x20, 0x00, 0x12, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x24, 0x84, 0x22, 0x9e, 0x82, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x2a, 0x84, 0x23, 0x94, 0x8b, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x2e, 0x84, 0x23, +0x44, 0x20, 0x00, 0x1b, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x35, 0x84, 0x21, 0x44, 0x20, 0x00, 0x1e, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x39, 0x84, 0x21, 0x44, 0x20, 0x00, 0x1f, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x76, 0x84, 0x21, 0x94, 0x8d, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x7a, 0x84, 0x21, 0x44, 0x20, +0x00, 0x21, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x78, 0x84, 0x21, 0x44, 0x20, 0x00, 0x26, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x96, 0x84, 0x21, 0x44, 0x20, 0x00, 0x24, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x9d, +0x84, 0x21, 0x44, 0x20, 0x00, 0x25, 0xdd, 0x26, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0x80, 0x04, 0x01, 0x97, 0x81, 0x46, 0x00, 0x00, 0x0b, +0x58, 0x00, 0x05, 0x20, 0x97, 0x08, 0x96, 0x92, 0x96, 0xda, 0x58, 0x84, 0x04, 0x00, 0x40, 0x93, +0x00, 0x00, 0x84, 0xe0, 0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, 0x00, 0xac, 0x85, 0x47, 0xd5, 0x1a, +0xc3, 0x0b, 0xf2, 0x82, 0xf3, 0x81, 0xf4, 0x83, 0x80, 0x06, 0x84, 0x20, 0xdd, 0x3c, 0xf2, 0x02, +0xf3, 0x01, 0xf4, 0x03, 0xd5, 0x03, 0x00, 0x04, 0x80, 0x00, 0x9c, 0x79, 0x9d, 0xb1, 0x56, 0x73, +0x80, 0x01, 0xc2, 0x03, 0x40, 0x05, 0x1c, 0x1a, 0x1c, 0x04, 0x00, 0x01, 0x97, 0xc8, 0x97, 0xb1, +0x8d, 0x21, 0xe2, 0xe4, 0xe9, 0xe6, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x0b, 0x02, 0x07, 0x83, 0x2e, 0xc8, 0x02, 0xd5, 0x03, 0x84, 0xa1, 0xd8, 0x0b, 0x46, 0xf0, +0x00, 0x0b, 0x10, 0x07, 0x86, 0x62, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, +0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, +0x86, 0x65, 0xc8, 0x1c, 0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, 0x83, 0x2e, 0x84, 0xa1, 0xd8, 0x13, +0x46, 0x40, 0x04, 0x01, 0x04, 0x12, 0x01, 0xa3, 0x46, 0x00, 0x04, 0x10, 0x59, 0xe0, 0x80, 0x08, +0x54, 0x5f, 0x00, 0xff, 0x14, 0x52, 0x01, 0xa3, 0x58, 0x00, 0x02, 0x38, 0xb4, 0x60, 0x42, 0x11, +0xc4, 0x08, 0xd5, 0x36, 0x84, 0xa2, 0xd8, 0x50, 0xd5, 0x49, 0x84, 0xa2, 0xd8, 0x4d, 0x46, 0xf0, +0x00, 0x0b, 0x02, 0x07, 0x83, 0x2e, 0xc8, 0x48, 0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, 0x83, 0x2f, +0x44, 0x50, 0x00, 0x81, 0xd0, 0x1d, 0x5c, 0xf0, 0x00, 0x82, 0xe8, 0x08, 0xe6, 0x0a, 0xe8, 0x03, +0xc8, 0x0f, 0xd5, 0x34, 0x9f, 0x69, 0xd8, 0x38, 0xd5, 0x31, 0x9c, 0x6a, 0x4c, 0x00, 0x80, 0x20, +0xe2, 0x01, 0xe9, 0x18, 0x9d, 0x49, 0xd0, 0x20, 0x9d, 0x4a, 0xd8, 0x2e, 0xd5, 0x22, 0x97, 0x40, +0x46, 0x40, 0x04, 0x01, 0x94, 0x2d, 0x58, 0x42, 0x00, 0x08, 0x98, 0x04, 0xd5, 0x05, 0x46, 0x00, +0x04, 0x01, 0x58, 0x00, 0x00, 0x38, 0x05, 0xe0, 0x00, 0x00, 0x58, 0x1f, 0x00, 0x40, 0xb6, 0x20, +0xd5, 0x15, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x58, 0xd5, 0xf6, 0x46, 0x00, 0x04, 0x01, +0x58, 0x00, 0x00, 0x78, 0xd5, 0xf1, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x98, 0xd5, 0xec, +0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0xb8, 0xd5, 0xe7, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x84, 0xb8, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x0b, 0x00, 0x07, 0x86, 0x65, 0xc0, 0x05, 0x84, 0xa2, 0x4c, 0x02, 0xc0, 0xa3, 0xd5, 0x1a, +0x46, 0xf0, 0x00, 0x0b, 0x02, 0x37, 0x83, 0x2e, 0x84, 0xa1, 0x4c, 0x32, 0xc0, 0x9b, 0x46, 0x30, +0x04, 0x01, 0x04, 0x41, 0x81, 0xa3, 0x46, 0x50, 0x04, 0x10, 0x54, 0x22, 0x00, 0xf7, 0x14, 0x21, +0x81, 0xa3, 0x04, 0x02, 0x80, 0x8e, 0x43, 0xe0, 0x44, 0x09, 0x15, 0xe2, 0x80, 0x8e, 0x48, 0x00, +0x00, 0x83, 0x46, 0xf0, 0x00, 0x0b, 0x02, 0x57, 0x83, 0x2e, 0x4e, 0x53, 0x00, 0x83, 0x46, 0x20, +0x00, 0x0b, 0x02, 0x01, 0x03, 0x2f, 0x44, 0x50, 0x00, 0x82, 0xd0, 0x3b, 0x5c, 0xf0, 0x00, 0x83, +0xe8, 0x07, 0xc0, 0x71, 0xe6, 0x0a, 0xe9, 0x0c, 0x9f, 0x69, 0xd8, 0x6d, 0xd5, 0x25, 0x9c, 0x6a, +0x4c, 0x00, 0x80, 0x4a, 0xe2, 0x01, 0xe9, 0x3a, 0x9d, 0x49, 0xd8, 0x65, 0xd5, 0x51, 0x55, 0xe0, +0x00, 0xff, 0x46, 0x50, 0x04, 0x01, 0x58, 0x52, 0x86, 0x88, 0x58, 0x3f, 0x00, 0x60, 0x15, 0xe2, +0x80, 0x00, 0x40, 0x0f, 0x14, 0x08, 0xb6, 0x65, 0x50, 0x12, 0xf9, 0x80, 0x41, 0xe0, 0x04, 0x00, +0xb4, 0x7e, 0x42, 0x11, 0x98, 0x09, 0xb6, 0x3e, 0x00, 0x01, 0x06, 0x5e, 0x58, 0x40, 0x00, 0x60, +0xb6, 0x05, 0xb6, 0x85, 0xd5, 0x48, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, +0x00, 0x11, 0x44, 0x20, 0x00, 0x71, 0xb6, 0x60, 0x50, 0x10, 0x79, 0xb0, 0xb6, 0x40, 0xd5, 0x34, +0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, 0x00, 0x12, 0x44, 0x20, 0x00, 0x72, +0xb6, 0x60, 0x50, 0x10, 0x79, 0xd0, 0xb6, 0x40, 0xd5, 0x27, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, +0x06, 0x88, 0x44, 0x30, 0x00, 0x13, 0x44, 0x20, 0x00, 0x73, 0xb6, 0x60, 0x50, 0x10, 0x79, 0xf0, +0xb6, 0x40, 0xd5, 0x1a, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, 0x00, 0x14, +0x44, 0x20, 0x00, 0x74, 0xb6, 0x60, 0x50, 0x10, 0x7a, 0x10, 0xb6, 0x40, 0xd5, 0x0d, 0x46, 0x00, +0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, 0x00, 0x15, 0x44, 0x20, 0x00, 0x75, 0xb6, 0x60, +0xb6, 0x40, 0x50, 0x10, 0x7a, 0x30, 0x05, 0xe0, 0x80, 0x00, 0x42, 0x4f, 0x18, 0x09, 0xb6, 0x81, +0xb6, 0x60, 0xb6, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x92, 0x97, 0xc1, 0x97, 0x8b, +0xf2, 0x81, 0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, 0x07, 0xa0, 0x46, 0xa0, 0x00, 0x04, 0x58, 0xa5, +0x04, 0xac, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, 0x84, 0xb8, 0xd5, 0x20, 0x96, 0x30, 0x44, 0x10, +0x00, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, 0x81, 0x00, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0xd8, 0xdd, 0x2f, 0xc0, 0xfb, 0xf3, 0x01, 0x80, 0x28, 0x84, 0x40, +0x80, 0x07, 0xdd, 0x3c, 0x50, 0x63, 0x7f, 0xc0, 0x80, 0x08, 0x50, 0x73, 0x80, 0x40, 0x4b, 0xe0, +0x28, 0x01, 0x97, 0xb3, 0x4b, 0xe0, 0x24, 0x01, 0x97, 0xf9, 0x4e, 0x64, 0xff, 0xe1, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x00, 0x0b, +0x00, 0x57, 0x86, 0x64, 0x40, 0x80, 0x00, 0x10, 0x4c, 0x54, 0x40, 0x31, 0x46, 0x00, 0x00, 0x0b, +0x58, 0x00, 0x05, 0x20, 0x44, 0x40, 0x00, 0x40, 0x84, 0x60, 0x10, 0x30, 0x00, 0x8e, 0x10, 0x40, +0x00, 0x8d, 0x10, 0x40, 0x00, 0x3e, 0x10, 0x30, 0x00, 0x3f, 0x10, 0x40, 0x00, 0x45, 0x10, 0x30, +0x00, 0x46, 0x10, 0x40, 0x00, 0x4c, 0x10, 0x30, 0x00, 0x4d, 0x10, 0x40, 0x00, 0x53, 0x10, 0x30, +0x00, 0x54, 0x10, 0x40, 0x00, 0x5a, 0x10, 0x30, 0x00, 0x5b, 0x10, 0x40, 0x00, 0x61, 0x10, 0x30, +0x00, 0x62, 0x10, 0x40, 0x00, 0x68, 0x10, 0x30, 0x00, 0x69, 0x10, 0x40, 0x00, 0x6f, 0x10, 0x30, +0x00, 0x70, 0x10, 0x40, 0x00, 0x86, 0x10, 0x30, 0x00, 0x87, 0x46, 0x60, 0x00, 0x0b, 0x00, 0x03, +0x06, 0x60, 0x44, 0x10, 0x00, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, +0x80, 0x20, 0x80, 0x48, 0x84, 0x60, 0x80, 0xe0, 0x44, 0x00, 0x00, 0x28, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x87, 0xa0, 0xdd, 0x2f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xac, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0x00, 0x53, 0x06, 0x60, +0x5c, 0xf2, 0x80, 0x41, 0xe9, 0x37, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x04, 0xd8, 0x4b, 0xe0, +0x18, 0x01, 0xc0, 0xfe, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x67, 0x85, 0x4c, 0x84, 0xa1, 0x46, 0x00, +0x00, 0x0b, 0x46, 0x20, 0x00, 0x04, 0x58, 0x21, 0x05, 0xf8, 0xde, 0x05, 0x00, 0x00, 0x06, 0x60, +0x84, 0x2a, 0xd5, 0x05, 0x00, 0x00, 0x06, 0x60, 0x44, 0x10, 0x00, 0x36, 0x50, 0x00, 0x7f, 0xc0, +0x96, 0x00, 0x4b, 0xe0, 0x08, 0x01, 0x84, 0x40, 0x80, 0x20, 0x80, 0xc0, 0x80, 0x62, 0x44, 0x00, +0x00, 0x68, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x87, 0xa0, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0xac, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, +0xdd, 0x2f, 0x46, 0x30, 0x00, 0x0b, 0x58, 0x31, 0x85, 0x20, 0x84, 0x40, 0x84, 0x82, 0x10, 0x41, +0x80, 0x8e, 0x10, 0x21, 0x80, 0x8d, 0x10, 0x21, 0x80, 0x3e, 0x10, 0x41, 0x80, 0x3f, 0x10, 0x21, +0x80, 0x45, 0x10, 0x41, 0x80, 0x46, 0x10, 0x21, 0x80, 0x4c, 0x10, 0x41, 0x80, 0x4d, 0x10, 0x21, +0x80, 0x53, 0x10, 0x41, 0x80, 0x54, 0x10, 0x21, 0x80, 0x5a, 0x10, 0x41, 0x80, 0x5b, 0x10, 0x21, +0x80, 0x61, 0x10, 0x41, 0x80, 0x62, 0x10, 0x21, 0x80, 0x68, 0x10, 0x41, 0x80, 0x69, 0x10, 0x21, +0x80, 0x6f, 0x10, 0x41, 0x80, 0x70, 0x10, 0x21, 0x80, 0x86, 0x10, 0x41, 0x80, 0x87, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x80, 0x00, 0x0b, 0x02, 0x04, +0x03, 0x2e, 0x84, 0xa3, 0x40, 0x10, 0x20, 0x09, 0xd1, 0x45, 0xe6, 0x24, 0xe8, 0x07, 0x84, 0xa1, +0xd1, 0x0d, 0x84, 0xa2, 0x4c, 0x12, 0xc0, 0x98, 0xd5, 0x34, 0x84, 0xa7, 0xd1, 0x34, 0x84, 0xaf, +0xd1, 0x14, 0x84, 0xa6, 0x4c, 0x12, 0xc0, 0x90, 0xd5, 0x1e, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, +0x86, 0x60, 0x44, 0x10, 0x00, 0x12, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, +0x80, 0x20, 0x84, 0x00, 0x80, 0x40, 0xd5, 0x79, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x60, +0x84, 0x2c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, 0x80, 0x20, 0x44, 0x00, +0x00, 0x1c, 0xd5, 0x51, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x60, 0x84, 0x2a, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, 0x80, 0x20, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x43, +0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8b, 0x38, 0xdd, 0x2f, +0xd5, 0x5f, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x67, 0x86, 0x68, 0xce, 0x03, 0x96, 0x00, 0xc8, 0x05, +0x44, 0x00, 0x00, 0x9e, 0x84, 0x24, 0xd5, 0x2f, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x80, 0xac, +0x80, 0x26, 0x50, 0x00, 0x00, 0x27, 0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x20, 0x80, 0x26, 0x44, 0x00, +0x00, 0x27, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x50, 0x00, 0xff, 0x80, 0x20, 0xd0, 0x05, 0x00, 0x04, +0x06, 0x5c, 0xe6, 0x0d, 0xe9, 0x1a, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x5c, 0x84, 0xa1, +0xd8, 0x06, 0x44, 0x00, 0x00, 0xa2, 0x44, 0x10, 0x00, 0x12, 0xd5, 0x0d, 0x84, 0xa2, 0xd8, 0x06, +0x44, 0x00, 0x00, 0xb4, 0x44, 0x10, 0x00, 0x1c, 0xd5, 0x06, 0x84, 0xa3, 0xd8, 0x24, 0x44, 0x00, +0x00, 0xd0, 0x84, 0x28, 0x84, 0x40, 0xd5, 0x19, 0x40, 0x00, 0xa0, 0x08, 0x55, 0xe4, 0x80, 0xff, +0x40, 0x8f, 0x00, 0x04, 0x40, 0x84, 0x00, 0x13, 0x80, 0x26, 0x80, 0x08, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x86, 0x60, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, +0xdd, 0x2f, 0x80, 0x20, 0x84, 0x41, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8a, 0xc4, +0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x40, +0x04, 0x01, 0x80, 0x64, 0x96, 0x48, 0x96, 0x00, 0x14, 0x02, 0x01, 0x00, 0x14, 0x11, 0x81, 0x01, +0x96, 0x10, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xac, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x00, 0x80, 0x20, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x8e, 0x28, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x62, 0x84, 0x20, +0x84, 0x41, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8e, 0x28, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, +0x86, 0x65, 0x44, 0x50, 0x00, 0x81, 0xd0, 0x50, 0x9d, 0x69, 0xd0, 0x0b, 0x9f, 0x6a, 0xd8, 0x44, +0x47, 0xe0, 0x04, 0x01, 0x04, 0x5f, 0x01, 0xa3, 0x54, 0x42, 0x80, 0x08, 0xcc, 0x43, 0xd5, 0x44, +0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x5e, 0x9f, 0x69, 0xd0, 0x12, 0x5c, 0xf0, 0x00, 0x82, +0xe8, 0x05, 0xc0, 0x3a, 0xe6, 0x0a, 0xe8, 0x30, 0xd5, 0x24, 0x9c, 0x6a, 0x4c, 0x00, 0x80, 0x13, +0xe2, 0x01, 0xe9, 0x0b, 0x9d, 0x49, 0xd0, 0x13, 0x9d, 0x4a, 0xd8, 0x26, 0xd5, 0x15, 0x46, 0x00, +0x04, 0x01, 0x58, 0x00, 0x00, 0x38, 0xd5, 0x1b, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x58, +0xd5, 0x16, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x78, 0xd5, 0x11, 0x46, 0x00, 0x04, 0x01, +0x58, 0x00, 0x00, 0x98, 0xd5, 0x0c, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0xb8, 0xd5, 0x07, +0x46, 0x50, 0x04, 0x01, 0x95, 0x05, 0x58, 0x52, 0x80, 0x08, 0x98, 0x25, 0x05, 0xe0, 0x00, 0x00, +0x42, 0x0f, 0x18, 0x0b, 0xd5, 0x0a, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, +0xd5, 0x0b, 0x84, 0x02, 0xd5, 0x02, 0x84, 0x00, 0x84, 0x20, 0x84, 0x42, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x8e, 0x28, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x30, 0x04, 0x01, 0x04, 0x51, 0x81, 0x80, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x57, 0x86, 0x65, +0x80, 0x83, 0x04, 0x12, 0x01, 0x81, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x86, 0x66, 0x80, 0xa3, +0x04, 0x21, 0x81, 0x82, 0x04, 0x42, 0x81, 0x83, 0x96, 0x10, 0x96, 0x60, 0x40, 0x30, 0xa0, 0x08, +0x40, 0x51, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x0b, 0x12, 0x57, 0x83, 0x2e, 0x46, 0x20, 0x04, 0x01, +0x80, 0x02, 0x04, 0x11, 0x01, 0x84, 0x04, 0x30, 0x01, 0x85, 0x97, 0x08, 0x97, 0x58, 0x40, 0x22, +0xa0, 0x08, 0x40, 0x51, 0x10, 0x04, 0x46, 0xf0, 0x00, 0x0b, 0x12, 0x57, 0x83, 0x2f, 0x80, 0x20, +0x04, 0x40, 0x81, 0x86, 0x04, 0x30, 0x01, 0x87, 0x96, 0x60, 0x96, 0x18, 0x40, 0x40, 0x20, 0x08, +0x40, 0x32, 0x04, 0x04, 0x46, 0x00, 0x04, 0x01, 0x46, 0xf0, 0x00, 0x0b, 0x12, 0x37, 0x83, 0x30, +0x84, 0x41, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x0b, 0x14, 0x57, 0x81, 0x95, 0x46, 0xf0, 0x00, 0x0b, +0x10, 0x27, 0x86, 0x63, 0x14, 0x10, 0x01, 0x8c, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x20, 0x46, 0xf0, +0x00, 0x0e, 0x10, 0x17, 0x82, 0x7c, 0xdd, 0x9e, 0x46, 0x30, 0x04, 0x01, 0x44, 0x50, 0x00, 0xff, +0x80, 0x43, 0x14, 0x51, 0x81, 0x8a, 0x44, 0x30, 0x00, 0x39, 0x46, 0x10, 0x04, 0x01, 0x14, 0x31, +0x01, 0x98, 0x58, 0x10, 0x86, 0x88, 0x84, 0x80, 0x44, 0x50, 0x00, 0x10, 0x44, 0x30, 0x00, 0x70, +0x44, 0x20, 0x00, 0x60, 0xb6, 0xa1, 0x50, 0x00, 0x80, 0x18, 0xb6, 0x61, 0xb6, 0x81, 0xb6, 0x41, +0x44, 0x10, 0x00, 0x31, 0xb6, 0x20, 0x9d, 0x49, 0x9c, 0x4c, 0x9e, 0xca, 0x9e, 0x89, 0xb6, 0xa0, +0xb6, 0x60, 0xb6, 0x40, 0xb6, 0x20, 0x80, 0x24, 0x50, 0x20, 0x80, 0x21, 0x84, 0xa9, 0x9c, 0x49, +0xb6, 0x40, 0xd9, 0xfb, 0x46, 0x00, 0x04, 0x01, 0x44, 0x10, 0x00, 0x3f, 0x14, 0x10, 0x01, 0x8c, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x0b, +0x10, 0x27, 0x86, 0x64, 0x47, 0xe0, 0x04, 0x01, 0x04, 0x1f, 0x01, 0xa3, 0x46, 0x40, 0x04, 0x00, +0x58, 0x50, 0x80, 0x01, 0x14, 0x5f, 0x01, 0xa3, 0x83, 0x9e, 0x81, 0x5c, 0x81, 0x2a, 0x04, 0x02, +0x00, 0x8f, 0x15, 0xcf, 0x80, 0x00, 0x14, 0xaf, 0x80, 0x01, 0x14, 0x9f, 0x80, 0x02, 0xb4, 0x7f, +0xf2, 0x01, 0xf1, 0x02, 0x81, 0x09, 0x80, 0xe8, 0x80, 0xc7, 0x14, 0x8f, 0x80, 0x03, 0xf7, 0x84, +0xf6, 0x85, 0x58, 0x31, 0x80, 0x38, 0x58, 0x21, 0x00, 0x58, 0x58, 0x10, 0x80, 0x78, 0xb6, 0x7f, +0xf2, 0x81, 0xf1, 0x82, 0xf3, 0x03, 0xf2, 0x04, 0xf1, 0x05, 0x58, 0x00, 0x02, 0x00, 0x58, 0x31, +0x80, 0x98, 0x58, 0x21, 0x00, 0xb8, 0x58, 0x10, 0x80, 0x48, 0xf3, 0x83, 0xf2, 0x84, 0xf1, 0x85, +0x14, 0x02, 0x00, 0x8f, 0x44, 0x00, 0x00, 0x8c, 0xb4, 0x9f, 0x9e, 0x84, 0xb6, 0x04, 0x9e, 0xd4, +0xf4, 0x01, 0x9e, 0x43, 0xb6, 0x44, 0x83, 0xc6, 0xf0, 0x02, 0x83, 0x86, 0xb6, 0x60, 0x81, 0x46, +0xf4, 0x03, 0x81, 0x26, 0xb6, 0x24, 0x81, 0x06, 0xf0, 0x04, 0x80, 0xe6, 0xb6, 0x40, 0xf4, 0x05, +0x80, 0xa6, 0x44, 0x00, 0x00, 0x20, 0xb6, 0x44, 0x14, 0x3f, 0x00, 0x1a, 0xb9, 0xa2, 0x14, 0x15, +0x00, 0x2a, 0x14, 0x14, 0x80, 0x32, 0x14, 0x14, 0x00, 0x3a, 0x14, 0x23, 0x80, 0x42, 0x14, 0x13, +0x00, 0x4a, 0x14, 0x02, 0x81, 0x8c, 0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x10, 0x04, 0x01, 0x04, 0x60, 0x81, 0x8c, 0x96, 0x34, +0xc0, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8f, 0x70, 0xdd, 0x2f, 0x54, 0x23, 0x00, 0x08, +0xc2, 0x17, 0x46, 0x40, 0x04, 0x01, 0x80, 0x64, 0x84, 0x48, 0x84, 0x20, 0x84, 0x01, 0x14, 0x22, +0x01, 0x8c, 0x14, 0x11, 0x81, 0xa7, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x82, 0x7c, 0x46, 0x30, +0x04, 0x00, 0x04, 0x51, 0x80, 0x96, 0x42, 0x42, 0xfc, 0x08, 0x14, 0x41, 0x80, 0x96, 0x54, 0x53, +0x00, 0x10, 0xc5, 0x06, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x80, 0x18, 0xdd, 0x2f, 0x54, 0x63, +0x00, 0x20, 0xc6, 0x06, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x80, 0x84, 0xdd, 0x2f, 0x46, 0x00, +0x04, 0x01, 0x05, 0xe0, 0x01, 0x8c, 0x15, 0xef, 0x80, 0x01, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x01, 0x44, 0x50, 0x00, 0x80, +0x14, 0x52, 0x01, 0xa8, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x65, 0x46, 0x60, 0x00, 0x0b, +0x84, 0x40, 0x54, 0x00, 0x00, 0x60, 0x44, 0x10, 0x00, 0x20, 0x10, 0x23, 0x06, 0x63, 0x4c, 0x00, +0x80, 0x20, 0x95, 0x49, 0xd0, 0x14, 0xc8, 0x1c, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x86, 0x66, +0x84, 0x2c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, +0x58, 0x10, 0x83, 0xe8, 0x38, 0x20, 0x82, 0x02, 0xdd, 0x22, 0xd5, 0x0f, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x86, 0xb0, 0xdd, 0x2f, 0x96, 0xc0, 0x10, 0x33, 0x06, 0x63, 0xd5, 0x06, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x01, 0x84, 0xa0, 0x14, 0x52, +0x01, 0xa8, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0xa8, 0xdd, 0x2f, 0x46, 0x50, 0x04, 0x01, 0x04, 0x02, 0x81, 0xa3, +0x54, 0x00, 0x00, 0x02, 0xc8, 0x66, 0x80, 0xe5, 0xb6, 0xff, 0x80, 0xc5, 0xb4, 0x3f, 0xf6, 0x81, +0x58, 0x10, 0x80, 0xb8, 0xb6, 0x3f, 0xf1, 0x01, 0x80, 0x45, 0x58, 0x10, 0x80, 0x88, 0xf1, 0x81, +0x44, 0x10, 0x00, 0x8b, 0x14, 0x11, 0x00, 0x26, 0x83, 0xc2, 0xb4, 0x5f, 0x83, 0x85, 0xb6, 0x22, +0x81, 0x45, 0xf2, 0x01, 0x81, 0x25, 0x81, 0x05, 0x80, 0xe5, 0xb6, 0x22, 0x80, 0xc5, 0x44, 0x20, +0x00, 0xff, 0x46, 0x40, 0x04, 0x01, 0x14, 0x1f, 0x00, 0x2a, 0x58, 0x42, 0x06, 0x88, 0xb9, 0xb2, +0x14, 0x15, 0x00, 0x3a, 0x14, 0x14, 0x80, 0x42, 0x14, 0x14, 0x00, 0x4a, 0x14, 0x23, 0x81, 0x8a, +0x44, 0x10, 0x00, 0x39, 0x44, 0x20, 0x00, 0x10, 0x14, 0x13, 0x01, 0x98, 0xb6, 0x44, 0x44, 0x10, +0x00, 0x70, 0x44, 0x20, 0x00, 0x60, 0xb6, 0x24, 0x50, 0x32, 0x00, 0x18, 0xb6, 0x04, 0x84, 0x22, +0xb6, 0x44, 0x44, 0x20, 0x00, 0x31, 0x14, 0x12, 0x81, 0xa3, 0x9d, 0x12, 0xb6, 0x43, 0x9c, 0x53, +0x9f, 0x4a, 0x9c, 0x89, 0xb6, 0xa3, 0xb6, 0x83, 0xb6, 0x23, 0xb6, 0x43, 0x80, 0x23, 0x50, 0x50, +0x00, 0x21, 0x84, 0x69, 0x9c, 0x01, 0xb6, 0xa1, 0x4c, 0x01, 0xff, 0xfb, 0x80, 0xa6, 0x44, 0x00, +0x00, 0x3f, 0x84, 0x20, 0x14, 0x02, 0x81, 0x8c, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x86, 0x64, +0x80, 0x05, 0x04, 0x20, 0x01, 0xa3, 0x54, 0x41, 0x00, 0xfe, 0x14, 0x40, 0x01, 0xa3, 0xd5, 0x38, +0x46, 0x40, 0x04, 0x00, 0x04, 0x32, 0x00, 0x85, 0x80, 0xe5, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, +0x06, 0xa0, 0x58, 0x21, 0x80, 0x04, 0x44, 0x60, 0x00, 0x39, 0x45, 0xe0, 0x00, 0x31, 0x45, 0xc0, +0x00, 0x32, 0x44, 0xa0, 0x00, 0x33, 0x44, 0x90, 0x00, 0x34, 0x44, 0x80, 0x00, 0x35, 0x14, 0x22, +0x00, 0x85, 0x14, 0x63, 0x81, 0x98, 0x15, 0xe0, 0x00, 0x00, 0x15, 0xc0, 0x00, 0x00, 0xb7, 0x40, +0xb7, 0x20, 0xb7, 0x00, 0x84, 0x20, 0x50, 0x80, 0x80, 0x21, 0x84, 0xa9, 0x9c, 0x49, 0xb7, 0x00, +0xd9, 0xfb, 0x81, 0x27, 0x8d, 0x4c, 0x14, 0xa4, 0x81, 0x8c, 0x80, 0x07, 0x04, 0x10, 0x01, 0xa3, +0x96, 0x4c, 0xc1, 0x02, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x86, 0x64, 0x46, 0x00, +0x04, 0x01, 0x84, 0xa0, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x27, 0x86, 0x6a, 0x46, 0xf0, +0x00, 0x0b, 0x10, 0x27, 0x86, 0x63, 0x46, 0xf0, 0x00, 0x0b, 0x14, 0x57, 0x81, 0x96, 0x14, 0x50, +0x01, 0xa8, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x37, 0x86, 0x64, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, +0x86, 0x68, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x47, 0x86, 0x69, 0x40, 0x11, 0xa4, 0x08, 0x40, 0x00, +0x28, 0x08, 0x40, 0x30, 0x80, 0x04, 0x58, 0x01, 0x80, 0x02, 0x40, 0x12, 0x2c, 0x08, 0x46, 0x40, +0x04, 0x00, 0x40, 0x20, 0x04, 0x04, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x57, 0x86, 0x67, 0x14, 0x22, +0x00, 0x8f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x04, 0xc4, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xa0, +0xdd, 0x2f, 0x4b, 0xe0, 0x18, 0x01, 0xc0, 0xfe, 0x46, 0x00, 0x04, 0x01, 0xb4, 0x40, 0x46, 0x00, +0x04, 0x01, 0x96, 0x90, 0x58, 0x00, 0x05, 0x00, 0x84, 0x20, 0xd5, 0x05, 0xa3, 0x01, 0x96, 0xe0, +0x18, 0x30, 0x80, 0x01, 0xe0, 0x22, 0xe9, 0xfb, 0x47, 0xe0, 0x00, 0x0b, 0x02, 0x3f, 0x03, 0x30, +0x84, 0x20, 0x9a, 0x1a, 0x97, 0x41, 0x40, 0x00, 0x94, 0x06, 0x12, 0x5f, 0x03, 0x30, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x04, 0xc4, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xa0, 0xdd, 0x2f, 0x4b, 0xe0, 0x18, 0x01, 0xc0, 0xfe, +0x47, 0xe0, 0x04, 0x01, 0xb4, 0xde, 0x97, 0xb0, 0x46, 0xf0, 0x00, 0x0b, 0x04, 0x07, 0x81, 0x95, +0x46, 0x10, 0x04, 0x01, 0x80, 0x46, 0x58, 0x10, 0x85, 0x00, 0x84, 0x61, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x85, 0x98, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, 0x02, 0x40, 0x83, 0x30, 0x84, 0x00, +0x9a, 0xe6, 0x96, 0x99, 0x40, 0x00, 0x08, 0x06, 0x12, 0x20, 0x83, 0x30, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x60, +0xa4, 0x30, 0x44, 0x10, 0x00, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xe8, 0xdd, 0x2f, +0x46, 0x80, 0x00, 0x0b, 0x58, 0x84, 0x06, 0x54, 0x97, 0xc0, 0xb4, 0x28, 0x46, 0x00, 0x04, 0x01, +0x80, 0x47, 0x58, 0x00, 0x04, 0x00, 0x84, 0x60, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x98, +0xdd, 0x2f, 0xb4, 0x68, 0x80, 0x07, 0x98, 0xbb, 0xb6, 0x48, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x84, 0xac, 0xdd, 0x2f, 0xa4, 0x70, 0x84, 0x00, 0x9b, 0xcf, 0x97, 0xf9, 0x40, 0x00, 0x1c, 0x06, +0xad, 0xf0, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x02, +0xf0, 0x81, 0x84, 0xc0, 0x46, 0xa0, 0x00, 0x04, 0x58, 0xa5, 0x05, 0xe8, 0x46, 0x70, 0x00, 0x0b, +0x58, 0x73, 0x86, 0x54, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, 0x80, 0xac, 0xd5, 0x12, 0x00, 0x83, +0x80, 0x01, 0xa7, 0x78, 0x40, 0x44, 0x20, 0x08, 0x40, 0x02, 0x14, 0x04, 0xb6, 0x7f, 0x4b, 0xe0, +0x24, 0x01, 0xb4, 0x7f, 0x9d, 0xb1, 0xb6, 0x03, 0x97, 0xb0, 0xb4, 0x47, 0x9c, 0x51, 0xb6, 0x27, +0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, 0x83, 0x30, 0x44, 0x10, 0x00, 0x40, 0x4b, 0xe0, 0x28, 0x01, +0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x85, 0x00, 0x98, 0xb1, 0x46, 0x80, 0x00, 0x0b, 0xf1, 0x01, +0x94, 0xd2, 0xe2, 0xc0, 0xe9, 0xdd, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xac, +0xdd, 0x2f, 0x02, 0x34, 0x03, 0x30, 0x84, 0x00, 0x9b, 0x9e, 0x97, 0xb1, 0x40, 0x00, 0x18, 0x06, +0x12, 0x64, 0x03, 0x30, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x84, 0xc4, 0x97, 0x82, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x84, 0xa0, 0xdd, 0x2f, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0xfe, 0x46, 0x20, 0x04, 0x01, +0xb5, 0x22, 0x85, 0x00, 0x44, 0x10, 0x00, 0xfc, 0x40, 0x04, 0x18, 0x1b, 0x40, 0x00, 0x98, 0x1a, +0x46, 0x70, 0x04, 0x01, 0xf0, 0x81, 0x54, 0x94, 0x80, 0xff, 0x58, 0x73, 0x85, 0x00, 0x47, 0xc0, +0x00, 0x04, 0x59, 0xce, 0x01, 0x88, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x54, 0x46, 0xa0, +0x00, 0x04, 0x58, 0xa5, 0x01, 0x0c, 0xd5, 0x15, 0xdd, 0x3c, 0xa7, 0x31, 0xf2, 0x01, 0xa6, 0x70, +0x40, 0x31, 0x10, 0x04, 0xa3, 0x79, 0x40, 0x01, 0xa0, 0x08, 0x40, 0x00, 0x04, 0x04, 0x96, 0x68, +0x4b, 0xe0, 0x28, 0x01, 0xb4, 0x86, 0x8d, 0x01, 0x9c, 0xe1, 0xb6, 0x66, 0x54, 0x84, 0x00, 0xff, +0xe3, 0x09, 0xe9, 0xeb, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x81, 0x58, 0xdd, 0x2f, 0x46, 0x30, +0x00, 0x0b, 0x02, 0x41, 0x83, 0x30, 0x84, 0x20, 0x40, 0x02, 0x24, 0x01, 0x97, 0x41, 0x40, 0x00, +0x94, 0x06, 0x12, 0x51, 0x83, 0x30, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x66, 0xa6, 0x00, 0x46, 0x60, +0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, 0x84, 0x40, 0x44, 0x10, 0x00, 0x26, 0xae, 0xb0, 0x4c, 0x00, +0x81, 0xde, 0x5c, 0xf0, 0x00, 0x27, 0xe8, 0x35, 0x84, 0x68, 0x4c, 0x01, 0x82, 0x45, 0xe6, 0x09, +0xe8, 0x15, 0x84, 0x83, 0x4c, 0x02, 0x01, 0x7b, 0xe6, 0x04, 0xe8, 0x08, 0x84, 0xa1, 0xd0, 0x6e, +0x87, 0xc2, 0x4c, 0x0f, 0x42, 0x5f, 0x48, 0x00, 0x01, 0x5c, 0x84, 0x26, 0x4c, 0x00, 0x81, 0x67, +0x84, 0x47, 0x4c, 0x01, 0x42, 0x57, 0x48, 0x00, 0x01, 0x6a, 0x84, 0x6b, 0x4c, 0x01, 0x82, 0x35, +0xe6, 0x0c, 0xe8, 0x09, 0x84, 0x89, 0x4c, 0x02, 0x02, 0x30, 0x84, 0xaa, 0x4c, 0x02, 0xc2, 0x4a, +0x48, 0x00, 0x02, 0x24, 0x45, 0xe0, 0x00, 0x22, 0x4c, 0x0f, 0x01, 0xa1, 0x44, 0x10, 0x00, 0x23, +0x4c, 0x00, 0x81, 0xb8, 0x44, 0x20, 0x00, 0x20, 0x4c, 0x01, 0x42, 0x3c, 0x48, 0x00, 0x01, 0x89, +0x44, 0x30, 0x00, 0x43, 0x4c, 0x01, 0x81, 0x79, 0x5c, 0xf0, 0x00, 0x44, 0xe8, 0x20, 0x44, 0x40, +0x00, 0x33, 0x4c, 0x02, 0x01, 0xcc, 0x5c, 0xf0, 0x00, 0x34, 0xe8, 0x0b, 0x44, 0x50, 0x00, 0x27, +0x4c, 0x02, 0x81, 0xa0, 0x45, 0xe0, 0x00, 0x32, 0x4c, 0x0f, 0x42, 0x24, 0x48, 0x00, 0x01, 0xaa, +0x44, 0x10, 0x00, 0x37, 0x4c, 0x00, 0x81, 0xbb, 0x44, 0x20, 0x00, 0x42, 0x4c, 0x01, 0x01, 0x3c, +0x44, 0x30, 0x00, 0x36, 0x4c, 0x01, 0xc2, 0x16, 0x48, 0x00, 0x01, 0xa9, 0x44, 0x40, 0x00, 0x52, +0x4c, 0x02, 0x01, 0xb9, 0x5c, 0xf0, 0x00, 0x53, 0xe8, 0x0b, 0x44, 0x50, 0x00, 0x46, 0x4c, 0x02, +0x81, 0x3c, 0x45, 0xe0, 0x00, 0x47, 0x4c, 0x0f, 0x42, 0x05, 0x48, 0x00, 0x01, 0x46, 0x44, 0x10, +0x00, 0x56, 0x4c, 0x00, 0x81, 0xb6, 0x44, 0x20, 0x00, 0x57, 0x4c, 0x01, 0x01, 0xbb, 0x44, 0x30, +0x00, 0x53, 0x4c, 0x01, 0xc1, 0xf7, 0x48, 0x00, 0x01, 0xb5, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x06, 0x5c, 0xa6, 0x00, 0x84, 0x88, 0x4c, 0x02, 0x00, 0x8b, 0xe6, 0x09, 0xe8, 0x07, 0x84, 0xa1, +0xd0, 0x0f, 0x87, 0xc2, 0x4c, 0x0f, 0x41, 0xec, 0xd5, 0x76, 0x44, 0x10, 0x00, 0x10, 0x4c, 0x00, +0x80, 0x89, 0x44, 0x20, 0x00, 0x12, 0x4c, 0x01, 0x41, 0xe3, 0x48, 0x00, 0x00, 0xa3, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x00, 0x58, 0x42, 0x02, 0x0c, +0xb4, 0x44, 0x84, 0x20, 0x58, 0x31, 0x00, 0x10, 0xb6, 0x64, 0x92, 0x00, 0x84, 0x07, 0x9c, 0x49, +0x4c, 0x10, 0x7f, 0xfd, 0x44, 0x1f, 0xff, 0xef, 0x46, 0x00, 0x04, 0x00, 0x40, 0x21, 0x04, 0x02, +0x58, 0x00, 0x02, 0x0c, 0xb6, 0x40, 0x47, 0xe0, 0x04, 0x00, 0x59, 0xef, 0x02, 0x00, 0xb4, 0xbe, +0x54, 0x12, 0x80, 0x03, 0xc9, 0x12, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x04, 0x05, 0xe0, +0x80, 0x00, 0x46, 0x3f, 0xf0, 0xff, 0x58, 0x5f, 0x00, 0x01, 0xb6, 0xa1, 0x58, 0x31, 0x8f, 0xff, +0xb4, 0x81, 0x40, 0x22, 0x0c, 0x02, 0xd5, 0x31, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x18, 0x46, 0x10, +0x04, 0x00, 0x58, 0x10, 0x82, 0x04, 0xb4, 0x41, 0x84, 0x9e, 0x41, 0xe1, 0x10, 0x02, 0x15, 0xe0, +0x80, 0x00, 0x46, 0x3f, 0xf0, 0xff, 0xb4, 0xa1, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x42, 0x8c, 0x02, +0xb6, 0x81, 0x46, 0x30, 0x01, 0x00, 0xb4, 0x41, 0xd5, 0x16, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, +0x82, 0x04, 0xb4, 0x81, 0x84, 0xbe, 0x40, 0x22, 0x14, 0x02, 0xb6, 0x41, 0x46, 0x3f, 0xf0, 0xff, +0x05, 0xe0, 0x80, 0x00, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x5f, 0x0c, 0x02, 0xb6, 0xa1, 0x46, 0x30, +0x05, 0x00, 0xb4, 0x41, 0x40, 0x21, 0x0c, 0x04, 0xb6, 0x41, 0xb4, 0x20, 0x58, 0x10, 0x83, 0x00, +0x48, 0x00, 0x00, 0xca, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0xe8, 0xdd, 0x2f, 0x48, 0x00, 0x01, 0x6a, 0x46, 0x00, 0x04, 0x10, +0x58, 0x00, 0x04, 0x00, 0x05, 0xe0, 0x00, 0x00, 0x58, 0x1f, 0x0c, 0x00, 0x48, 0x00, 0x00, 0xb4, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xd8, 0xdd, 0x2f, 0xc8, 0x09, 0x84, 0x61, 0x46, 0x00, +0x00, 0x0b, 0x58, 0x00, 0x06, 0x6a, 0xae, 0xc0, 0x48, 0x00, 0x01, 0x52, 0x46, 0x50, 0x00, 0x0b, +0x58, 0x52, 0x83, 0xe4, 0xa7, 0x28, 0x46, 0x20, 0x04, 0x01, 0x58, 0x21, 0x04, 0x00, 0xb6, 0x82, +0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xac, 0xdd, 0x2f, 0x48, 0x00, 0x01, 0x40, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x01, 0x58, 0x42, +0x06, 0x60, 0x84, 0xa0, 0xb6, 0xa4, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x84, 0x4c, 0xdd, 0x2f, +0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x6a, 0xae, 0x08, 0x46, 0x40, 0x04, 0x00, 0x58, 0x42, +0x02, 0x04, 0xb4, 0x44, 0x44, 0x3f, 0x00, 0xff, 0x40, 0x01, 0x0c, 0x02, 0x58, 0x50, 0x44, 0x00, +0xb6, 0xa4, 0x46, 0x0f, 0xf0, 0xff, 0xb4, 0x44, 0x58, 0x00, 0x0f, 0xff, 0x58, 0x31, 0x00, 0x01, +0xb6, 0x64, 0x46, 0x10, 0x04, 0x00, 0xb4, 0xa4, 0x58, 0x10, 0x82, 0x0c, 0x40, 0x22, 0x80, 0x02, +0xb6, 0x44, 0xb4, 0x61, 0x58, 0x01, 0x83, 0x00, 0xb6, 0x01, 0x48, 0x00, 0x01, 0x09, 0x46, 0x00, +0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x47, 0xe0, 0x00, 0x0b, 0x59, 0xef, 0x06, 0x5c, 0x46, 0x30, +0x04, 0x10, 0xb4, 0x20, 0x02, 0x2f, 0x00, 0x00, 0xd5, 0x22, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x06, 0x54, 0x46, 0x20, 0x04, 0x10, 0xb4, 0x20, 0xd5, 0x26, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x06, 0x54, 0x46, 0x30, 0x04, 0x10, 0xb4, 0x20, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, +0x48, 0x00, 0x00, 0xab, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x20, 0x00, 0x0b, +0x58, 0x21, 0x06, 0x5c, 0x46, 0x30, 0x04, 0x00, 0xb4, 0x20, 0xa4, 0x90, 0x98, 0x4b, 0xb6, 0x20, +0xac, 0x88, 0x48, 0x00, 0x00, 0xd5, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x20, +0x04, 0x00, 0xb4, 0x20, 0x98, 0xca, 0xb6, 0x60, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x84, 0xa4, +0xdd, 0x2f, 0x48, 0x00, 0x00, 0xbd, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x30, +0x04, 0x00, 0xb4, 0x20, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, 0xd5, 0x7d, 0x46, 0x00, +0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0xb4, 0x80, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x58, +0x40, 0x12, 0x40, 0x08, 0xb6, 0x20, 0x48, 0x00, 0x00, 0xab, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x06, 0x54, 0x47, 0xe0, 0x00, 0x0b, 0x59, 0xef, 0x06, 0x58, 0x46, 0x50, 0x00, 0x0b, 0x58, 0x52, +0x86, 0x5c, 0xb4, 0x3e, 0xb4, 0x60, 0xa4, 0xa8, 0xd5, 0xc2, 0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, +0x06, 0x58, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0xb4, 0x22, 0xb4, 0x40, 0xd5, 0xc3, +0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x58, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, +0xb4, 0x26, 0xb4, 0x60, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, 0x98, 0x4b, 0xd5, 0x45, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x40, 0x00, 0x0b, 0x58, 0x42, 0x06, 0x5c, +0x46, 0x30, 0x04, 0x20, 0xb4, 0x20, 0xa4, 0xa0, 0xd5, 0x9a, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x06, 0x54, 0x46, 0x20, 0x04, 0x20, 0xb4, 0x20, 0xd5, 0x9e, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x06, 0x54, 0x46, 0x30, 0x04, 0x20, 0xb4, 0x20, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, +0xd5, 0x23, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x50, 0x00, 0x0b, 0x58, 0x52, +0x86, 0x5c, 0x46, 0x30, 0x05, 0x00, 0xb4, 0x20, 0xa4, 0xa8, 0x48, 0xff, 0xff, 0x79, 0x46, 0x00, +0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x20, 0x05, 0x00, 0xb4, 0x20, 0x48, 0xff, 0xff, 0x7c, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x54, 0x46, 0x30, 0x05, 0x00, 0xb4, 0x20, 0x46, 0x60, +0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, 0x98, 0x4b, 0xb6, 0x20, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x84, 0xd8, 0xdd, 0x2f, 0xc8, 0x02, 0xd5, 0x1a, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x85, 0x04, +0xdd, 0x2f, 0xd5, 0x25, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x85, 0xfc, 0xdd, 0x2f, 0xd5, 0x1c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xd8, 0xdd, 0x2f, +0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x06, 0x6a, 0xc8, 0x03, 0x84, 0x01, 0xd5, 0x10, 0x46, 0x20, +0x00, 0x0b, 0x58, 0x21, 0x06, 0x66, 0x01, 0xe1, 0x00, 0x00, 0x56, 0x0f, 0x00, 0x0b, 0x5c, 0x00, +0x00, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x85, 0x68, 0xdd, 0x2f, 0xae, 0x30, 0xd5, 0x07, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x94, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x6a, 0x20, 0x00, +0x80, 0x00, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x84, 0x70, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x84, 0x48, 0xdd, 0x2f, +0x46, 0x40, 0x04, 0x10, 0x04, 0x62, 0x02, 0x01, 0x40, 0x53, 0x20, 0x08, 0x92, 0xa8, 0x14, 0x52, +0x02, 0x01, 0x84, 0x0a, 0x46, 0x10, 0x00, 0x05, 0x58, 0x10, 0x8f, 0x54, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8c, 0xfc, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x00, 0xb4, 0x43, 0x44, 0x50, 0x76, 0x10, +0x40, 0x01, 0x40, 0x09, 0xd8, 0x07, 0x04, 0x01, 0x80, 0x41, 0x43, 0xe0, 0x50, 0x0b, 0x4f, 0xe2, +0x00, 0x0c, 0x84, 0x02, 0x46, 0x10, 0x00, 0x05, 0x58, 0x10, 0x81, 0x60, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8f, 0x30, 0xdd, 0x2f, 0x46, 0x60, 0x00, 0x05, 0x58, 0x63, 0x0f, 0x30, 0x84, 0x01, +0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x85, 0x18, 0xdd, 0x26, 0x84, 0x0c, 0x46, 0x10, 0x00, 0x04, +0x58, 0x10, 0x81, 0xcc, 0xdd, 0x26, 0x84, 0x0f, 0x46, 0x10, 0x00, 0x01, 0x58, 0x10, 0x87, 0xfc, +0xdd, 0x26, 0x46, 0x10, 0x00, 0x09, 0x58, 0x10, 0x8f, 0xd4, 0x84, 0x00, 0xdd, 0x26, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x06, 0x7c, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xd8, 0xdd, 0x2f, +0x84, 0x20, 0x80, 0x81, 0x46, 0x20, 0x00, 0x0a, 0x58, 0x21, 0x0b, 0xe0, 0x44, 0x30, 0x08, 0x00, +0x46, 0x00, 0x00, 0x05, 0x58, 0x00, 0x0d, 0x90, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x8c, +0xdd, 0x2f, 0x84, 0x00, 0x46, 0x10, 0x00, 0x0a, 0x58, 0x10, 0x8a, 0x58, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x00, 0x84, 0xa1, 0x14, 0x52, 0x00, 0x8c, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x4c, 0xdd, 0x2f, 0x84, 0x00, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x04, 0x07, +0x81, 0x88, 0xdd, 0x20, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x00, 0x0b, +0x58, 0x21, 0x05, 0xf8, 0x94, 0xc2, 0x98, 0x1a, 0xb6, 0x20, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x06, 0x58, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x86, 0x60, 0xb6, 0x20, 0x48, 0xff, +0xd1, 0x8d, 0xdd, 0x9e, 0x64, 0x12, 0x00, 0x02, 0x96, 0x4c, 0x64, 0x02, 0x00, 0x43, 0x64, 0x00, +0x00, 0x08, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x64, 0x12, 0x00, 0x02, 0x42, 0x10, 0x80, 0x09, +0x40, 0x10, 0x80, 0x04, 0x64, 0x12, 0x00, 0x03, 0x64, 0x00, 0x00, 0x08, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x64, 0x12, 0x00, 0x43, 0x64, 0x00, 0x00, 0x08, 0x46, 0x60, 0x00, 0x0e, +0x58, 0x63, 0x06, 0x58, 0x04, 0x03, 0x00, 0x0b, 0xc0, 0x02, 0xdd, 0x20, 0x04, 0x03, 0x00, 0x0c, +0xc0, 0x02, 0xdd, 0x20, 0x04, 0x23, 0x00, 0x08, 0x44, 0x10, 0x03, 0x00, 0x54, 0x01, 0x03, 0x00, +0x4c, 0x00, 0xff, 0xf2, 0x64, 0x00, 0x00, 0x00, 0xd5, 0xee, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, 0x81, 0x9e, 0x40, 0x43, 0x18, 0x05, 0x40, 0x22, +0x0c, 0x02, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x27, 0x81, 0x9e, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, 0x81, 0x9e, 0xf0, 0x01, +0x40, 0x23, 0x0c, 0x04, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x27, 0x81, 0x9e, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc1, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x07, 0x81, 0xa1, 0x46, 0xf0, +0x00, 0x0e, 0x14, 0x67, 0x81, 0xa2, 0xc8, 0x08, 0x44, 0x00, 0x01, 0x00, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0xce, 0x08, 0x44, 0x00, 0x02, 0x00, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0x44, 0x50, 0x00, 0x14, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x06, 0x60, 0x42, 0x60, 0x94, 0x73, +0x80, 0xe0, 0x81, 0x43, 0x50, 0x03, 0x00, 0x0c, 0xa8, 0x71, 0x84, 0x20, 0x81, 0x22, 0x81, 0x04, +0xa8, 0x72, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xd8, 0xdd, 0x2f, 0x50, 0x35, 0x7f, 0xb8, +0x40, 0x24, 0x8c, 0x00, 0x58, 0x44, 0x00, 0x08, 0x84, 0x0a, 0xb6, 0x46, 0xa9, 0xd1, 0xb6, 0x82, +0xa8, 0x12, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0xa8, 0x01, 0xb6, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xa0, 0x81, 0xb6, 0x01, 0xa8, 0x89, 0xb6, 0x22, 0xa8, 0x41, 0xdd, 0x9e, 0xb4, 0x20, 0x4c, 0x10, +0x40, 0x04, 0x84, 0x20, 0xd5, 0x07, 0xa0, 0xc9, 0xb4, 0x81, 0xb6, 0x83, 0xb4, 0x01, 0xa0, 0x89, +0xa8, 0x81, 0x80, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x20, 0x00, 0x0b, 0x04, 0x11, 0x01, 0x94, +0x98, 0x01, 0x14, 0x01, 0x01, 0x94, 0x80, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x00, 0x0e, +0x58, 0x10, 0x86, 0xbc, 0x46, 0xf0, 0x00, 0x0b, 0x14, 0x17, 0x81, 0x94, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x82, 0x80, 0x38, 0x12, 0x82, 0x0a, 0x46, 0x10, 0x04, 0x00, +0x58, 0x10, 0x82, 0x00, 0xa0, 0x8d, 0x84, 0x61, 0x40, 0x41, 0x80, 0x0c, 0x40, 0x02, 0x08, 0x04, +0xa8, 0x0d, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, +0x82, 0x00, 0xa0, 0x5c, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x83, 0x3a, 0xc0, 0x0e, 0x47, 0xe0, +0x04, 0x00, 0x46, 0x08, 0x00, 0x00, 0x58, 0x00, 0x03, 0xe8, 0x84, 0xa1, 0x14, 0x0f, 0x00, 0x22, +0x46, 0xf0, 0x00, 0x0e, 0x10, 0x57, 0x83, 0x3b, 0x96, 0x08, 0x54, 0x20, 0x00, 0x08, 0xc2, 0x07, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa3, 0x48, 0x00, 0x00, 0x84, 0x54, 0x30, 0x00, 0x10, +0xc3, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa4, 0xd5, 0x7b, 0x54, 0x50, 0x00, 0x20, +0xc5, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa5, 0xd5, 0x73, 0x54, 0x20, 0x00, 0x02, +0xc2, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa1, 0xd5, 0x6b, 0x96, 0xc4, 0xc3, 0x06, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa0, 0xd5, 0x64, 0x54, 0x40, 0x00, 0x04, 0xc4, 0x06, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa2, 0xd5, 0x5c, 0x40, 0x20, 0xa0, 0x09, 0x96, 0x10, +0x55, 0xe0, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa8, +0xd5, 0x50, 0x54, 0x30, 0x00, 0x02, 0xc3, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xa9, +0xd5, 0x48, 0x54, 0x40, 0x00, 0x04, 0xc4, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xaa, +0xd5, 0x40, 0x55, 0xe0, 0x00, 0x08, 0x4f, 0xe2, 0x00, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xab, 0xd5, 0x37, 0x54, 0x30, 0x00, 0x10, 0xc3, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xac, 0xd5, 0x2f, 0x54, 0x40, 0x00, 0x20, 0xc4, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xad, 0xd5, 0x27, 0x54, 0x50, 0x00, 0x40, 0xc5, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xae, 0xd5, 0x1f, 0x54, 0x20, 0x00, 0x80, 0xc2, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xaf, 0xd5, 0x17, 0x40, 0x40, 0xc0, 0x09, 0x96, 0x60, 0x96, 0x0c, 0xc0, 0x02, 0xd5, 0x04, +0x54, 0x10, 0x80, 0x02, 0xc1, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xb0, 0xd5, 0x09, +0x47, 0xe0, 0x04, 0x00, 0x04, 0x3f, 0x00, 0x8d, 0x9c, 0x99, 0x14, 0x2f, 0x00, 0x8d, 0xd5, 0x02, +0xdd, 0x20, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0x3c, +0xef, 0xf4, 0x46, 0x30, 0x04, 0x10, 0x54, 0x80, 0x00, 0x0f, 0x58, 0x31, 0x85, 0x00, 0x40, 0x84, +0x38, 0x08, 0x84, 0x80, 0x54, 0x70, 0x80, 0x3f, 0xb4, 0xa3, 0xf5, 0x81, 0x00, 0x5f, 0x80, 0x07, +0x54, 0x52, 0x80, 0x80, 0x97, 0x68, 0xcd, 0x3c, 0xf5, 0x81, 0x00, 0x9f, 0x80, 0x07, 0x42, 0x94, +0x98, 0x09, 0x00, 0x6f, 0x80, 0x05, 0x92, 0xc6, 0x95, 0xb6, 0x44, 0xaf, 0xff, 0x80, 0x40, 0x94, +0xa8, 0x04, 0x40, 0x63, 0x1c, 0x04, 0x10, 0x9f, 0x80, 0x07, 0x10, 0x6f, 0x80, 0x05, 0x44, 0x9c, +0x3f, 0xff, 0xf6, 0x01, 0x40, 0x63, 0x24, 0x02, 0x40, 0x63, 0x20, 0x04, 0xf6, 0x81, 0xb6, 0xc3, +0xb4, 0xc3, 0x9d, 0x69, 0xf6, 0x81, 0x00, 0x6f, 0x80, 0x07, 0x54, 0x63, 0x00, 0x80, 0xc6, 0x05, +0x44, 0xa0, 0x00, 0x64, 0x4c, 0x55, 0x7f, 0xf6, 0x00, 0x5f, 0x80, 0x07, 0x54, 0x52, 0x80, 0x80, +0xcd, 0x0f, 0x00, 0x5f, 0x80, 0x05, 0x54, 0x52, 0x80, 0x3f, 0xd9, 0x0a, 0xf5, 0x01, 0x92, 0xae, +0x54, 0x52, 0x80, 0x0f, 0xd8, 0x05, 0x00, 0x0f, 0x80, 0x04, 0xb6, 0x02, 0xd5, 0x05, 0x9d, 0x21, +0x44, 0x50, 0x00, 0x64, 0xdc, 0xba, 0xf1, 0x01, 0x40, 0x00, 0xfc, 0x09, 0xec, 0x0c, 0x3a, 0x6f, +0xa8, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x30, 0x04, 0x10, 0x84, 0x80, +0x05, 0xe1, 0x81, 0x40, 0x9d, 0x21, 0x15, 0xef, 0x80, 0x01, 0x00, 0x6f, 0x80, 0x07, 0x54, 0x53, +0x00, 0x80, 0xc5, 0x04, 0x44, 0x50, 0x00, 0x64, 0xdc, 0xf4, 0x00, 0x5f, 0x80, 0x07, 0x44, 0x3f, +0xff, 0xc0, 0x41, 0xe2, 0x8c, 0x04, 0x11, 0xef, 0x80, 0x07, 0x54, 0x40, 0x00, 0x0f, 0xf3, 0x01, +0x44, 0x6c, 0x3f, 0xff, 0x40, 0x52, 0x38, 0x08, 0x41, 0xe1, 0x98, 0x02, 0x40, 0x3f, 0x14, 0x04, +0xf3, 0x81, 0x01, 0xef, 0x80, 0x05, 0x54, 0x40, 0x80, 0x3f, 0x40, 0x6f, 0x18, 0x09, 0x95, 0xb6, +0x40, 0x33, 0x10, 0x04, 0x10, 0x2f, 0x80, 0x04, 0x10, 0x3f, 0x80, 0x05, 0x46, 0x20, 0x04, 0x10, +0xf6, 0x01, 0x14, 0x61, 0x01, 0x40, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, +0xdd, 0x2f, 0x84, 0x01, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0xef, 0xf8, 0x46, 0x00, +0x04, 0x11, 0x58, 0x00, 0x00, 0x1c, 0x84, 0x60, 0xb4, 0x80, 0xf4, 0x81, 0x00, 0x5f, 0x80, 0x06, +0x54, 0x42, 0x80, 0x02, 0x97, 0x20, 0xcc, 0x23, 0xf4, 0x81, 0x10, 0x1f, 0x80, 0x05, 0x00, 0x5f, +0x80, 0x06, 0x58, 0x52, 0x80, 0x03, 0x10, 0x5f, 0x80, 0x06, 0xf5, 0x01, 0xb6, 0xa0, 0xb4, 0xa0, +0x9d, 0x21, 0xf5, 0x81, 0x00, 0x5f, 0x80, 0x06, 0x54, 0x52, 0x80, 0x02, 0xc5, 0x04, 0x44, 0x50, +0x00, 0x64, 0xdc, 0xf6, 0x00, 0x5f, 0x80, 0x06, 0x54, 0x42, 0x80, 0x02, 0xcc, 0x08, 0x00, 0x5f, +0x80, 0x05, 0xd9, 0x05, 0x00, 0x0f, 0x80, 0x04, 0xb6, 0x02, 0xd5, 0x05, 0x9c, 0xd9, 0x44, 0x50, +0x00, 0x64, 0xdb, 0xd3, 0xf1, 0x01, 0x42, 0x00, 0xc4, 0x0b, 0xec, 0x08, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x46, 0x30, 0x04, 0x11, 0x84, 0x80, 0xa1, 0x5f, 0x9d, 0x21, +0xf5, 0x81, 0x01, 0xef, 0x80, 0x06, 0x54, 0x5f, 0x00, 0x02, 0xc5, 0x04, 0x44, 0x50, 0x00, 0x64, +0xdc, 0xf6, 0x84, 0xa0, 0x84, 0x82, 0xf5, 0x81, 0x10, 0x2f, 0x80, 0x04, 0x10, 0x4f, 0x80, 0x06, +0x10, 0x1f, 0x80, 0x05, 0x80, 0x43, 0xf3, 0x01, 0xa8, 0xd7, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x84, 0x01, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x46, 0x10, 0x04, 0x10, 0x46, 0x00, 0x04, 0x10, 0x46, 0x20, +0x00, 0xff, 0x58, 0x10, 0x85, 0x0c, 0x58, 0x00, 0x05, 0x04, 0x44, 0x40, 0xe0, 0x10, 0x58, 0x21, +0x0f, 0xf8, 0xb5, 0x21, 0xb5, 0x00, 0xb6, 0x81, 0xb6, 0x40, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x00, 0xac, 0x84, 0x21, 0x50, 0x2f, 0x80, 0x04, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x64, 0x80, 0x43, +0x84, 0x05, 0x84, 0x21, 0xb6, 0x7f, 0x81, 0x46, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, +0xdd, 0x2f, 0x80, 0xdf, 0xd5, 0x0a, 0x84, 0x00, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0x01, 0xd8, 0xfd, +0x84, 0x05, 0x84, 0x21, 0x80, 0x5f, 0xdd, 0x2a, 0xb4, 0xff, 0x54, 0x73, 0x80, 0x04, 0xcf, 0xf4, +0xf2, 0x01, 0x84, 0x21, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, +0x46, 0x30, 0x04, 0x10, 0x46, 0x00, 0x04, 0x10, 0x58, 0x31, 0x85, 0x04, 0x58, 0x00, 0x05, 0x0c, +0xb6, 0xe3, 0xb7, 0x20, 0xb7, 0x03, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x84, 0x21, 0x80, 0x40, 0x44, 0x00, 0x02, 0x58, 0x40, 0x51, 0x00, 0x97, 0x9c, 0x49, 0x96, 0x48, +0x84, 0x6b, 0x98, 0x28, 0x92, 0x01, 0x4c, 0x11, 0xff, 0xf9, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xf4, 0x46, 0x20, 0x04, 0x11, 0x80, 0x80, 0x84, 0x60, 0x05, 0xe1, 0x00, 0x07, 0x9c, 0xd9, +0x15, 0xef, 0x80, 0x01, 0x00, 0x5f, 0x80, 0x06, 0x54, 0x02, 0x80, 0x02, 0xc0, 0x04, 0x44, 0x50, +0x00, 0x64, 0xdb, 0xf4, 0x84, 0x62, 0x84, 0x00, 0xf0, 0x81, 0x10, 0x3f, 0x80, 0x06, 0x10, 0x1f, +0x80, 0x04, 0x10, 0x4f, 0x80, 0x05, 0xf1, 0x01, 0xa8, 0x57, 0x80, 0x24, 0x80, 0x5f, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x84, 0x01, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xa4, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x80, 0xac, 0x84, 0x22, 0x50, 0x2f, 0x80, 0x50, 0x84, 0x04, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x1c, +0x50, 0x2f, 0x80, 0x4c, 0x84, 0x04, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x1d, 0x50, 0x2f, 0x80, 0x48, +0x84, 0x04, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x44, 0x84, 0x04, 0xdd, 0x27, +0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x40, 0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x12, +0x50, 0x2f, 0x80, 0x3c, 0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x38, +0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x34, 0x84, 0x05, 0xdd, 0x27, +0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x00, 0x80, 0xb4, 0x80, 0x46, 0x10, 0x04, 0x10, 0xf4, 0x87, +0x58, 0x10, 0x84, 0x00, 0xb4, 0x41, 0x46, 0xa0, 0x04, 0x11, 0xf2, 0x86, 0x58, 0xa5, 0x02, 0x04, +0xb4, 0x6a, 0x46, 0x90, 0x04, 0x10, 0xf3, 0x85, 0x58, 0x94, 0x85, 0x0c, 0xb4, 0xa9, 0x46, 0x60, +0x04, 0x10, 0xf5, 0x84, 0x58, 0x63, 0x05, 0x04, 0xb4, 0x86, 0x47, 0xcf, 0xf0, 0x00, 0x46, 0x80, +0x00, 0x80, 0x84, 0x43, 0x59, 0xce, 0x00, 0x03, 0x58, 0x84, 0x0c, 0x00, 0xf4, 0x83, 0x15, 0xc0, +0x00, 0x00, 0xb7, 0x01, 0xb6, 0x4a, 0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, 0x02, 0x60, 0x84, 0x01, +0xdd, 0x3c, 0x46, 0x50, 0x18, 0xca, 0x44, 0x30, 0x00, 0x1f, 0x58, 0x52, 0x80, 0x0f, 0x84, 0x9f, +0x44, 0xa0, 0x00, 0x17, 0xb7, 0x49, 0xb6, 0x66, 0xb6, 0xa9, 0xb6, 0x86, 0x44, 0x10, 0x00, 0x11, +0x50, 0x2f, 0x80, 0x30, 0x84, 0x00, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x2c, +0x84, 0x00, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x28, 0x84, 0x00, 0xdd, 0x27, +0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x24, 0x84, 0x00, 0xdd, 0x27, 0x84, 0x24, 0x50, 0x2f, +0x80, 0x20, 0x84, 0x00, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x01, 0x64, 0xdd, 0x27, 0x44, 0x10, +0x00, 0x11, 0x44, 0x20, 0x00, 0x99, 0x84, 0x00, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, +0x00, 0x99, 0x84, 0x00, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x13, 0x84, 0x49, 0x84, 0x00, 0xdd, 0x28, +0x44, 0x10, 0x00, 0x14, 0x44, 0x20, 0x00, 0x51, 0x84, 0x00, 0xdd, 0x28, 0x84, 0x24, 0x44, 0x20, +0x00, 0x8e, 0x84, 0x00, 0xdd, 0x28, 0x84, 0x21, 0x80, 0x41, 0x84, 0x05, 0xdd, 0x28, 0x84, 0x01, +0xdd, 0x3c, 0x46, 0x06, 0x00, 0x42, 0x58, 0x00, 0x00, 0x3f, 0xb6, 0x09, 0x44, 0x10, 0x00, 0x13, +0x44, 0x20, 0x00, 0x27, 0x84, 0x04, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, +0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xf1, 0x84, 0x05, 0xdd, 0x28, +0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0xa1, 0x84, 0x05, 0xdd, 0x28, 0x84, 0x41, 0x44, 0x10, +0x00, 0x14, 0x84, 0x05, 0xdd, 0x28, 0x46, 0x10, 0x00, 0x82, 0x58, 0x10, 0x80, 0x3f, 0xb6, 0x29, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x80, 0x0a, 0x84, 0x24, 0xdd, 0x26, 0x84, 0x2a, +0x44, 0x00, 0x00, 0xf1, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf2, 0xdd, 0x26, 0x84, 0x20, +0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x31, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x26, 0x46, 0x20, +0x04, 0x10, 0xf2, 0x82, 0x84, 0x01, 0x84, 0x24, 0xdd, 0x26, 0xf3, 0x02, 0x85, 0x40, 0x58, 0x31, +0x80, 0x7c, 0xf3, 0x82, 0x14, 0xaf, 0x80, 0x01, 0x83, 0x8a, 0x50, 0x9f, 0x80, 0x54, 0x05, 0xef, +0x80, 0x01, 0x54, 0x75, 0x00, 0x07, 0x41, 0xe3, 0x9c, 0x1a, 0x54, 0x85, 0x00, 0xff, 0x15, 0xef, +0x80, 0x01, 0x41, 0xc3, 0x9c, 0x1a, 0xe7, 0x08, 0xe8, 0x19, 0x80, 0x49, 0x44, 0x10, 0x00, 0x2b, +0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf0, 0x15, 0x44, 0x10, +0x00, 0x2b, 0x54, 0x50, 0x00, 0xf8, 0x40, 0x25, 0x14, 0x04, 0x84, 0x04, 0xf5, 0x95, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0xd5, 0x19, 0x44, 0x10, 0x00, 0x11, 0x80, 0x49, +0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf2, 0x15, 0x94, 0x7b, +0x54, 0x31, 0x00, 0xc7, 0x40, 0x20, 0x8c, 0x04, 0x84, 0x04, 0x44, 0x10, 0x00, 0x11, 0xf3, 0x95, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x84, 0x21, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x9b, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x84, 0x20, 0xd5, 0x0b, +0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, 0x7f, 0xfd, 0x9c, 0x49, 0x45, 0xe0, 0x01, 0x2c, +0x4c, 0x1f, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf5, 0x84, 0x21, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x26, +0x84, 0x20, 0xd5, 0x09, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0x01, 0xd8, 0xfd, 0x9c, 0x49, 0x84, 0x0a, +0x4c, 0x10, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf7, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x26, +0x44, 0x10, 0x00, 0xba, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x10, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x26, 0xf3, 0x02, 0xb4, 0x23, 0x40, 0x00, 0xc0, 0x09, 0x4e, 0x14, 0x00, 0x05, +0x44, 0x2f, 0x00, 0x00, 0x98, 0x02, 0x45, 0xe0, 0x80, 0x00, 0x40, 0x40, 0xf8, 0x02, 0x96, 0x49, +0xc4, 0x04, 0x44, 0x5f, 0x00, 0x00, 0x98, 0x4d, 0x42, 0x00, 0x00, 0x24, 0x42, 0x00, 0x84, 0x73, +0xf1, 0x01, 0xe2, 0x20, 0xe8, 0x04, 0xf0, 0x81, 0x55, 0xc4, 0x00, 0x07, 0x84, 0x07, 0x4c, 0x70, +0x40, 0x6a, 0x4c, 0x83, 0xc0, 0x4b, 0x80, 0x49, 0x44, 0x10, 0x00, 0x2b, 0x84, 0x04, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf5, 0x15, 0x44, 0x10, 0x00, 0x2b, 0x54, 0x22, +0x80, 0xf8, 0x40, 0x4e, 0x08, 0x04, 0x80, 0x44, 0x84, 0x04, 0xf4, 0x95, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x80, 0x49, 0x44, 0x10, 0x00, 0x2c, 0x84, 0x04, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf3, 0x15, 0x44, 0x10, 0x00, 0x2c, 0x54, 0x01, +0x80, 0xf8, 0x40, 0x5e, 0x00, 0x04, 0x80, 0x45, 0x84, 0x04, 0xf5, 0x95, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x80, 0x49, 0x44, 0x10, 0x00, 0x2d, 0x84, 0x04, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf4, 0x15, 0x44, 0x10, 0x00, 0x2d, 0x54, 0x22, +0x00, 0xf8, 0x40, 0x3e, 0x08, 0x04, 0x80, 0x43, 0x84, 0x04, 0xf3, 0x95, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0xd5, 0x1e, 0x87, 0xcf, 0x4c, 0x8f, 0x40, 0x1c, 0x44, 0x10, +0x00, 0x11, 0x80, 0x49, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, +0xf4, 0x15, 0x40, 0x1e, 0x0c, 0x08, 0x54, 0x02, 0x00, 0xc7, 0x40, 0x30, 0x80, 0x04, 0x80, 0x43, +0x84, 0x04, 0x44, 0x10, 0x00, 0x11, 0xf3, 0x95, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, +0xdd, 0x2f, 0x8d, 0x41, 0x44, 0x20, 0x00, 0x10, 0x4c, 0xa1, 0x7e, 0xfb, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x03, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x15, +0x84, 0x21, 0xdd, 0x26, 0x84, 0x00, 0xd5, 0x09, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0x49, 0xd9, 0xfd, +0x9c, 0x01, 0x87, 0xca, 0x4c, 0x0f, 0x00, 0x04, 0x84, 0x20, 0xd5, 0xf7, 0x84, 0x20, 0x44, 0x00, +0x00, 0x15, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xf2, 0x0c, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x44, 0x10, 0x00, 0x11, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x0b, +0x44, 0x10, 0x00, 0x12, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x0a, 0x44, 0x10, 0x00, 0x13, 0x84, 0x00, +0xdd, 0x26, 0xf2, 0x09, 0x44, 0x10, 0x00, 0x14, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x08, 0x84, 0x24, +0x84, 0x00, 0xdd, 0x26, 0xf2, 0x11, 0x44, 0x10, 0x00, 0x13, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x10, +0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0f, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, +0xdd, 0x26, 0xf2, 0x0e, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0d, 0x44, 0x10, +0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf5, 0x07, 0x46, 0x40, 0x04, 0x10, 0x58, 0x42, 0x00, 0x80, +0xb6, 0xa4, 0x46, 0x30, 0x04, 0x10, 0xf4, 0x06, 0x58, 0x31, 0x84, 0x00, 0xb6, 0x83, 0x46, 0x20, +0x04, 0x11, 0xf5, 0x05, 0x58, 0x21, 0x02, 0x04, 0xb6, 0xa2, 0x46, 0x10, 0x04, 0x10, 0xf4, 0x03, +0x58, 0x10, 0x85, 0x04, 0xb6, 0x81, 0x46, 0x00, 0x04, 0x10, 0xf3, 0x04, 0x58, 0x00, 0x05, 0x0c, +0xb6, 0x60, 0xec, 0x5c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xc4, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0xb4, 0xa4, 0x84, 0xc0, 0xf5, 0x81, +0x46, 0x20, 0x04, 0x10, 0xb6, 0xc4, 0x44, 0x30, 0x18, 0x30, 0x58, 0x21, 0x05, 0x04, 0x05, 0xc1, +0x00, 0x00, 0x46, 0x00, 0x04, 0x10, 0xb6, 0x62, 0x58, 0x00, 0x05, 0x0c, 0x44, 0x10, 0x20, 0x00, +0xb5, 0x40, 0xb6, 0x20, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x00, 0xac, 0x50, 0x2f, 0x80, 0x34, +0x84, 0x24, 0x84, 0x05, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0x64, 0xdd, 0x28, 0x84, 0x24, +0x44, 0x20, 0x00, 0x27, 0x84, 0x05, 0xdd, 0x27, 0x50, 0x2f, 0x80, 0x30, 0x44, 0x10, 0x00, 0x11, +0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x27, +0x50, 0x2f, 0x80, 0x2c, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x12, +0x44, 0x20, 0x00, 0x83, 0x84, 0x05, 0xdd, 0x27, 0x50, 0x2f, 0x80, 0x28, 0x44, 0x10, 0x00, 0x13, +0x84, 0x05, 0xdd, 0x28, 0x50, 0x2f, 0x80, 0x24, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x28, +0x80, 0x46, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x14, 0x44, 0x20, +0x00, 0x20, 0x84, 0x05, 0xdd, 0x27, 0x50, 0x2f, 0x80, 0x20, 0x80, 0x06, 0x84, 0x21, 0xdd, 0x28, +0x80, 0x46, 0x80, 0x06, 0x84, 0x21, 0xdd, 0x27, 0x50, 0x2f, 0x80, 0x1c, 0x80, 0x06, 0x44, 0x10, +0x00, 0x22, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x00, 0x22, 0x44, 0x20, 0x00, 0x13, 0xdd, 0x27, +0x50, 0x2f, 0x80, 0x18, 0x80, 0x06, 0x44, 0x10, 0x00, 0x23, 0xdd, 0x28, 0x80, 0x46, 0x80, 0x06, +0x44, 0x10, 0x00, 0x23, 0xdd, 0x27, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x81, 0xec, 0x50, 0x2f, +0x80, 0x14, 0x44, 0x10, 0x00, 0x2f, 0x80, 0x06, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x80, 0x00, 0x06, +0x58, 0x84, 0x03, 0x6c, 0x84, 0x24, 0x44, 0x00, 0x00, 0x2f, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x80, +0x44, 0x00, 0x00, 0x16, 0xdd, 0x28, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x60, +0xdd, 0x2f, 0x50, 0x2f, 0x80, 0x10, 0x80, 0x06, 0x44, 0x10, 0x00, 0x31, 0x4b, 0xe0, 0x24, 0x01, +0x80, 0x26, 0x44, 0x00, 0x00, 0x16, 0x04, 0x9f, 0x80, 0x04, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, +0x00, 0x23, 0x84, 0x41, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x16, 0xdd, 0x28, +0xd5, 0x0b, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x49, 0x4c, 0x1f, 0x7f, 0xfd, 0x9d, 0xb1, 0x44, 0x70, +0x00, 0x3c, 0x4c, 0x63, 0x80, 0x04, 0x84, 0x20, 0xd5, 0xf5, 0x44, 0x10, 0x00, 0x31, 0x50, 0x2f, +0x80, 0x10, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x20, 0x7f, +0x80, 0x10, 0x40, 0x54, 0x80, 0x10, 0x9a, 0xfd, 0x44, 0x40, 0x03, 0xe8, 0x42, 0x01, 0x90, 0x24, +0x44, 0x20, 0x00, 0x2b, 0x40, 0x00, 0x08, 0x36, 0x84, 0x2a, 0x40, 0x20, 0x04, 0xd6, 0xe4, 0xc5, +0xe9, 0x02, 0x8c, 0x0a, 0x87, 0xca, 0x40, 0x20, 0x78, 0x16, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x01, 0x64, 0x84, 0x27, 0x84, 0x00, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, 0xdd, 0x26, +0x84, 0x20, 0x44, 0x00, 0x00, 0x16, 0xdd, 0x27, 0x84, 0x21, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x27, +0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x27, 0xf2, 0x0d, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x0c, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0b, 0x44, 0x10, 0x00, 0x12, +0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0a, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x09, +0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x08, 0x84, 0x21, 0x84, 0x00, 0xdd, 0x26, +0xf2, 0x07, 0x44, 0x10, 0x00, 0x22, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x06, 0x44, 0x10, 0x00, 0x23, +0x84, 0x00, 0xdd, 0x26, 0xf1, 0x05, 0x44, 0x00, 0x00, 0x2f, 0xdd, 0x27, 0xf3, 0x01, 0x46, 0x20, +0x04, 0x11, 0x46, 0x10, 0x04, 0x10, 0x46, 0x00, 0x04, 0x10, 0x58, 0x21, 0x00, 0x04, 0x58, 0x10, +0x85, 0x04, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0x62, 0x15, 0xc0, 0x80, 0x00, 0xb7, 0x40, 0x84, 0x27, +0x50, 0x2f, 0x80, 0x0c, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, +0xec, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x84, 0x21, +0x96, 0x00, 0x50, 0x2f, 0x80, 0x04, 0x46, 0x30, 0x00, 0x06, 0x58, 0x31, 0x80, 0xac, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x4c, 0x00, 0xc0, 0x10, 0x84, 0x23, 0x84, 0x05, 0x4b, 0xe0, +0x0c, 0x01, 0xf2, 0x01, 0x40, 0x31, 0x14, 0x09, 0x94, 0xdd, 0x58, 0x31, 0x80, 0x11, 0x84, 0x23, +0x80, 0x43, 0x84, 0x05, 0xd5, 0x0e, 0x84, 0x23, 0x84, 0x05, 0x4b, 0xe0, 0x0c, 0x01, 0xf7, 0x01, +0x40, 0x53, 0x94, 0x09, 0x95, 0x6d, 0x58, 0x32, 0x80, 0x08, 0x84, 0x05, 0x80, 0x43, 0x84, 0x23, +0xf3, 0x81, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0xec, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x5f, +0x44, 0x10, 0x00, 0x2f, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xb4, 0x5f, 0x44, 0x0f, 0xff, 0x9f, +0x40, 0x31, 0x00, 0x02, 0x58, 0x51, 0x80, 0x40, 0xb6, 0xbf, 0x80, 0x25, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x03, 0x6c, 0x44, 0x00, 0x00, 0x2f, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0x44, 0x00, +0x00, 0x3a, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x5f, 0x44, 0x10, 0x00, 0x2f, 0x84, 0x00, 0x4b, 0xe0, +0x1c, 0x01, 0xb4, 0x9f, 0x40, 0x22, 0x1c, 0x09, 0x94, 0x97, 0x58, 0x31, 0x00, 0x50, 0xb6, 0x7f, +0x80, 0x23, 0x44, 0x00, 0x00, 0x2f, 0x81, 0x1f, 0x4b, 0xe0, 0x18, 0x01, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x84, 0x80, 0x84, 0x24, 0x40, 0x2f, +0x84, 0x00, 0x97, 0x80, 0x80, 0x04, 0xf4, 0x81, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0xf0, 0x01, 0x44, 0x3f, 0xff, 0xe7, 0x84, 0x41, 0x40, 0x10, 0x0c, 0x02, 0x4c, 0x61, +0x00, 0x06, 0xc6, 0x09, 0x84, 0xa3, 0xde, 0x07, 0xd5, 0x04, 0x58, 0x10, 0x80, 0x10, 0xd5, 0x03, +0x58, 0x10, 0x80, 0x08, 0x4c, 0x10, 0x00, 0x08, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x01, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x44, 0x10, +0x00, 0x10, 0x81, 0x20, 0x84, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xba, 0x84, 0x21, 0xdd, 0x26, +0x84, 0xe0, 0x80, 0x66, 0x50, 0xaf, 0x80, 0x0c, 0x84, 0xc3, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, +0x01, 0xec, 0xf3, 0x81, 0x80, 0x26, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x23, 0x44, 0x10, 0x00, 0xbc, +0x84, 0x00, 0x80, 0x4a, 0xdd, 0x3c, 0xf1, 0x03, 0x9d, 0xb4, 0x44, 0x50, 0x00, 0x2f, 0x99, 0xf9, +0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x03, 0x6c, 0xf3, 0x01, 0xde, 0xec, 0x9e, 0x6c, 0x44, 0x00, +0x00, 0xbb, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x4a, 0x44, 0x10, 0x00, 0xbc, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf6, 0x03, 0x84, 0x20, 0x84, 0x04, 0x4b, 0xe0, +0x20, 0x01, 0x44, 0x50, 0x00, 0x37, 0x42, 0x33, 0x14, 0x24, 0x84, 0x96, 0x40, 0x21, 0x90, 0x36, +0x99, 0xfa, 0xe1, 0x27, 0xe8, 0x03, 0x84, 0x00, 0xd5, 0x05, 0x5e, 0x73, 0xff, 0xf6, 0x56, 0x03, +0x80, 0x01, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x2c, 0x46, 0x40, 0x00, 0x0b, 0x58, 0x42, 0x04, 0xa8, 0xf0, 0x81, 0x3a, 0x02, 0x0c, 0x04, +0x50, 0x8f, 0x80, 0x80, 0x84, 0xc0, 0x47, 0xc0, 0x04, 0x11, 0x3a, 0x04, 0x0c, 0x24, 0x46, 0x70, +0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, 0x80, 0x26, 0x44, 0x00, 0x00, 0xba, 0xb4, 0x64, 0x40, 0x91, +0xc0, 0x09, 0x12, 0x34, 0x00, 0x00, 0x10, 0x9f, 0x80, 0x92, 0xf6, 0xb2, 0x81, 0x5c, 0x05, 0xee, +0x00, 0x01, 0x15, 0xef, 0x80, 0x0f, 0x50, 0x8f, 0x80, 0xcc, 0xdd, 0x27, 0x80, 0x26, 0x44, 0x00, +0x00, 0xbb, 0xdd, 0x27, 0x80, 0x26, 0x44, 0x00, 0x00, 0xbc, 0xdd, 0x27, 0x04, 0x55, 0x00, 0xca, +0x80, 0x26, 0xf5, 0x8e, 0x44, 0x00, 0x00, 0x1b, 0xdd, 0x27, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, +0x81, 0xec, 0x80, 0x48, 0x44, 0x10, 0x00, 0x41, 0x80, 0x06, 0xdd, 0x29, 0xf4, 0x33, 0x80, 0x48, +0xf4, 0x8d, 0x44, 0x10, 0x00, 0x42, 0x80, 0x06, 0xdd, 0x29, 0xf3, 0x33, 0x44, 0x10, 0x00, 0x8c, +0xf3, 0x8c, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0x80, 0x48, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x06, +0xdd, 0x29, 0xf2, 0x33, 0x84, 0x23, 0xf2, 0x8b, 0x44, 0x00, 0x00, 0x9e, 0x47, 0xc0, 0x04, 0x10, +0xdd, 0x27, 0x80, 0x48, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x06, 0xdd, 0x29, 0x04, 0xae, 0x01, 0x41, +0x46, 0x90, 0x04, 0x10, 0x14, 0xaf, 0x80, 0x0a, 0x04, 0x84, 0x81, 0x43, 0x46, 0x58, 0x1f, 0xff, +0x58, 0x52, 0x8e, 0x7f, 0x46, 0x30, 0xa0, 0x00, 0x46, 0x00, 0x80, 0x00, 0x40, 0x74, 0x14, 0x02, +0xf4, 0x33, 0x40, 0x13, 0x8c, 0x04, 0x40, 0x23, 0x80, 0x04, 0x14, 0x8f, 0x80, 0x06, 0xf6, 0x83, +0xf7, 0x84, 0xf4, 0x89, 0xf6, 0x85, 0xf6, 0x82, 0xf1, 0x87, 0xf2, 0x88, 0x44, 0x00, 0x00, 0x9f, +0x44, 0x10, 0x00, 0x60, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x46, 0x50, +0x04, 0x10, 0x04, 0xa2, 0x81, 0x41, 0x47, 0xc0, 0x00, 0xc0, 0x59, 0xce, 0x00, 0x80, 0x40, 0x65, +0x70, 0x04, 0x14, 0x62, 0x81, 0x41, 0xf0, 0x02, 0xc8, 0x13, 0x05, 0xef, 0x80, 0x01, 0x5e, 0xff, +0x01, 0x5f, 0xe9, 0x03, 0xf3, 0x07, 0xd5, 0x1d, 0x04, 0x9f, 0x80, 0x01, 0x5e, 0xf4, 0xff, 0x06, +0xe8, 0x05, 0xf2, 0x04, 0x42, 0x31, 0x68, 0x08, 0xd5, 0x14, 0xf3, 0x08, 0xd5, 0x12, 0xf3, 0x01, +0x5e, 0xf1, 0x81, 0x5f, 0xe9, 0x07, 0xf4, 0x04, 0x46, 0x80, 0xc0, 0x00, 0x40, 0x32, 0x20, 0x04, +0xd5, 0x08, 0xf0, 0x01, 0xf3, 0x08, 0xf7, 0x07, 0x5e, 0x10, 0x7f, 0x06, 0x40, 0x33, 0x84, 0x1a, +0x80, 0x85, 0x46, 0x20, 0x04, 0x11, 0x51, 0xee, 0x7f, 0xa0, 0x14, 0x32, 0x01, 0x43, 0x15, 0xe1, +0x00, 0xca, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x80, 0xac, 0x84, 0x21, 0x50, 0x2f, 0x80, 0xc4, +0x84, 0x05, 0xdd, 0x29, 0x84, 0x21, 0x50, 0x2f, 0x80, 0xc0, 0x84, 0x00, 0xdd, 0x29, 0x84, 0x20, +0x50, 0x2f, 0x80, 0xbc, 0x84, 0x04, 0xdd, 0x29, 0x84, 0x2b, 0x50, 0x2f, 0x80, 0xb8, 0x84, 0x04, +0xdd, 0x29, 0x84, 0x2d, 0x50, 0x2f, 0x80, 0xb4, 0x84, 0x04, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x13, +0x50, 0x2f, 0x80, 0xb0, 0x84, 0x04, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0xac, +0x84, 0x04, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x16, 0x50, 0x2f, 0x80, 0xa8, 0x84, 0x04, 0xdd, 0x29, +0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0xa4, 0x84, 0x05, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x12, +0x50, 0x2f, 0x80, 0xa0, 0x84, 0x05, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x9c, +0x84, 0x05, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x98, 0x84, 0x05, 0xdd, 0x29, +0x84, 0x21, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, 0x01, 0x64, 0x80, 0x41, 0x84, 0x05, 0xdd, 0x3c, +0x84, 0x21, 0x44, 0x20, 0x00, 0xe1, 0x84, 0x00, 0xdd, 0x3c, 0x84, 0x20, 0x44, 0x20, 0x00, 0x83, +0x84, 0x04, 0xdd, 0x3c, 0x84, 0x2b, 0x44, 0x20, 0x00, 0x51, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x2d, +0x44, 0x20, 0x00, 0x3c, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0x24, +0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x15, 0x9e, 0x8b, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, +0x00, 0x16, 0x44, 0x20, 0x00, 0xa1, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, +0x00, 0x80, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xf1, 0x84, 0x05, +0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0xa1, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x41, +0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x3c, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, +0x44, 0x10, 0x00, 0x10, 0x9c, 0x0f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x6d, 0xdd, 0x26, +0x46, 0xa0, 0x04, 0x11, 0x84, 0x20, 0x44, 0x00, 0x00, 0x6e, 0xdd, 0x26, 0x84, 0xa8, 0x14, 0x55, +0x00, 0x01, 0x44, 0x10, 0x00, 0x8c, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x40, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x1b, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x39, 0x44, 0x00, 0x00, 0x41, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0x8c, +0xdd, 0x26, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0xec, 0x84, 0xc0, 0x84, 0x00, 0x44, 0x10, +0x00, 0x8c, 0x50, 0x2f, 0x80, 0xcc, 0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x33, 0x9d, 0xb1, 0xc3, 0x05, +0x44, 0x80, 0x00, 0x64, 0x4c, 0x64, 0x7f, 0xf4, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, +0x84, 0x20, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x22, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x26, +0x84, 0x2a, 0x44, 0x00, 0x00, 0xbc, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x41, 0x44, 0x00, 0x00, 0xbc, 0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, 0x00, 0xf1, +0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf2, 0xdd, 0x26, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x81, 0xec, 0x84, 0x00, 0x84, 0x24, 0x50, 0x2f, 0x80, 0xc8, 0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x06, +0x85, 0x25, 0x87, 0x88, 0x85, 0x40, 0x50, 0x7f, 0x80, 0x94, 0x84, 0x20, 0x44, 0x00, 0x00, 0x1b, +0xdd, 0x28, 0x50, 0x5f, 0x80, 0x80, 0x38, 0x12, 0xa4, 0x00, 0x44, 0x00, 0x00, 0x42, 0xdd, 0x28, +0xf1, 0x32, 0x54, 0x00, 0x80, 0x10, 0xc8, 0x05, 0x58, 0x10, 0x80, 0x10, 0x84, 0x04, 0xdd, 0x28, +0x44, 0x10, 0x00, 0x11, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0x15, +0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0xba, +0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x28, 0xf1, 0x02, 0xc9, 0x06, 0x44, 0x10, +0x00, 0x80, 0x44, 0x00, 0x00, 0xbc, 0xd5, 0x05, 0x44, 0x00, 0x00, 0xbc, 0x44, 0x10, 0x00, 0x81, +0xdd, 0x28, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x60, 0xdd, 0x2f, 0x84, 0xc0, +0x50, 0x2f, 0x80, 0xcc, 0x84, 0x00, 0x44, 0x10, 0x00, 0xbc, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x81, 0xec, 0xdd, 0x2f, 0xf4, 0x33, 0x9d, 0xb1, 0x54, 0x22, 0x00, 0x80, 0xc2, 0x04, 0x44, 0x50, +0x00, 0x64, 0xde, 0xef, 0xf1, 0x32, 0x84, 0x04, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf4, +0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, +0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x28, 0x44, 0x10, 0x00, 0xff, 0x44, 0x00, +0x00, 0xbb, 0xdd, 0x28, 0x44, 0x10, 0x00, 0xbc, 0x84, 0x00, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf1, 0x25, 0x5c, 0xf0, 0x80, 0xb4, 0xe8, 0x05, 0x8d, 0x21, +0xe5, 0x33, 0xe9, 0x8c, 0xd5, 0x1f, 0x5c, 0xf0, 0x80, 0xf6, 0xe9, 0x05, 0x8f, 0x21, 0x4e, 0x94, +0xff, 0x86, 0xd5, 0x18, 0x84, 0x05, 0x40, 0x25, 0x00, 0xd6, 0x84, 0xa4, 0xde, 0x03, 0x51, 0xce, +0x00, 0x0a, 0x84, 0xa5, 0x4c, 0xa2, 0x80, 0x0f, 0x80, 0x1c, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x8c, 0x80, 0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x03, 0x85, 0x00, 0xd5, 0x05, 0x8d, 0x41, 0x48, 0xff, +0xff, 0x6e, 0x85, 0x01, 0xf3, 0x32, 0x54, 0x71, 0x80, 0x10, 0xcf, 0x09, 0x58, 0x11, 0x80, 0x10, +0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x03, 0x6c, 0x84, 0x24, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x2f, 0x44, 0x00, 0x00, 0xbd, 0xdd, 0x26, 0x84, 0x25, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x25, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x2f, 0x44, 0x00, +0x00, 0xbd, 0xdd, 0x26, 0x84, 0x26, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x26, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x2f, 0x44, 0x00, 0x00, 0xbd, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xbd, +0x84, 0x2f, 0xdd, 0x26, 0xf2, 0x02, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0xec, 0xca, 0x30, +0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0xf0, 0x02, 0x50, 0x2f, 0x80, 0xcc, 0x44, 0x10, 0x00, 0xbd, 0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x33, +0xf4, 0x01, 0x40, 0x21, 0x98, 0x09, 0x94, 0x96, 0x5e, 0xf2, 0x01, 0x5f, 0xe9, 0x04, 0x58, 0x21, +0x00, 0x14, 0xd5, 0x0b, 0x05, 0xef, 0x80, 0x01, 0x5e, 0xff, 0x7f, 0x06, 0xe8, 0x04, 0x58, 0x21, +0x00, 0x08, 0xd5, 0x03, 0x58, 0x21, 0x00, 0x10, 0xf2, 0xb3, 0x84, 0x22, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x03, 0x6c, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x22, 0xd5, 0x2e, 0x84, 0x23, +0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x44, 0x10, +0x00, 0xbd, 0x50, 0x2f, 0x80, 0xcc, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xf5, 0x33, 0xf0, 0x01, +0x40, 0x22, 0x98, 0x09, 0x94, 0x96, 0x5e, 0xf0, 0x01, 0x5f, 0xe9, 0x04, 0x58, 0x21, 0x00, 0x18, +0xd5, 0x0a, 0xf7, 0x01, 0x5e, 0xf3, 0xff, 0x06, 0xe8, 0x04, 0x58, 0x21, 0x00, 0x10, 0xd5, 0x03, +0x58, 0x21, 0x00, 0x14, 0xf2, 0xb3, 0x84, 0x23, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, +0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0xf1, 0x33, +0x44, 0x00, 0x00, 0xbd, 0xdd, 0x26, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x27, 0xf4, 0x02, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0xcc, 0x11, 0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xbd, 0x84, 0x2f, 0xdd, 0x26, +0x14, 0x8f, 0x80, 0x05, 0x48, 0x00, 0x00, 0x90, 0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xbd, 0x84, 0x2f, 0xdd, 0x26, +0x14, 0x8f, 0x80, 0x03, 0xd5, 0x03, 0xf3, 0x02, 0xc3, 0x7e, 0xf7, 0x05, 0x84, 0xa1, 0xdf, 0x03, +0xf5, 0x03, 0xd7, 0x79, 0x46, 0xa0, 0x00, 0x0b, 0x58, 0xa5, 0x04, 0x68, 0x81, 0x0a, 0x3a, 0x04, +0x0c, 0x04, 0x50, 0x9f, 0x80, 0x40, 0x85, 0x40, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, 0x03, 0x6c, +0x3a, 0x04, 0x8c, 0x24, 0x3a, 0x04, 0x0c, 0x04, 0x3a, 0x04, 0x8c, 0x24, 0x3a, 0x04, 0x0c, 0x04, +0x3a, 0x04, 0x8c, 0x24, 0x3a, 0x04, 0x0c, 0x00, 0x3a, 0x04, 0x8c, 0x20, 0x44, 0x00, 0x00, 0xba, +0x50, 0x15, 0x00, 0x02, 0xdd, 0x3c, 0x50, 0x7f, 0x80, 0x40, 0x84, 0xc3, 0x85, 0x0a, 0x80, 0x26, +0x44, 0x00, 0x00, 0xbb, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0xbc, 0x50, 0x2f, 0x80, 0xcc, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf0, 0x33, 0x50, 0x00, 0x7f, 0x80, +0x4e, 0x06, 0x00, 0x05, 0x44, 0x10, 0x00, 0x80, 0xd5, 0x08, 0xa6, 0xb8, 0x42, 0x10, 0x08, 0x24, +0x40, 0x40, 0xa0, 0x56, 0x50, 0x12, 0x00, 0x80, 0x44, 0x00, 0x00, 0xbc, 0xdd, 0x3c, 0x9d, 0xb4, +0x44, 0x50, 0x01, 0x03, 0x9d, 0xf9, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x83, 0x6c, 0xde, 0xd8, +0x8d, 0x41, 0x84, 0xa2, 0x4c, 0xa2, 0xff, 0xcc, 0x84, 0x20, 0x44, 0x00, 0x00, 0xba, 0x4b, 0xe0, +0x24, 0x01, 0x44, 0x00, 0x00, 0xbb, 0x84, 0x24, 0x4b, 0xe0, 0x24, 0x01, 0xf6, 0x01, 0x5e, 0xf3, +0x7f, 0x06, 0xe8, 0x05, 0x84, 0x2e, 0x44, 0x00, 0x00, 0xbc, 0xd5, 0x05, 0x44, 0x00, 0x00, 0xbc, +0x44, 0x10, 0x00, 0x1c, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, +0x84, 0x20, 0x44, 0x00, 0x00, 0xbb, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0xbc, 0x9c, 0x44, +0x4b, 0xe0, 0x1c, 0x01, 0xf6, 0x0e, 0x47, 0xe0, 0x04, 0x11, 0x14, 0x6f, 0x00, 0xca, 0x46, 0x70, +0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, 0xf1, 0x32, 0x84, 0x04, 0xdd, 0x27, 0x84, 0x20, 0x44, 0x00, +0x00, 0x1b, 0xdd, 0x27, 0xf1, 0x0d, 0x44, 0x00, 0x00, 0x41, 0xdd, 0x27, 0xf1, 0x0c, 0x44, 0x00, +0x00, 0x42, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x8c, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x0b, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0xf2, 0x31, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, +0x84, 0x21, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x30, 0x84, 0x21, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x2f, +0x84, 0x20, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2e, 0x84, 0x2b, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2d, +0x84, 0x2d, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2c, 0x44, 0x10, 0x00, 0x13, 0x84, 0x04, 0xdd, 0x26, +0xf2, 0x2b, 0x44, 0x10, 0x00, 0x15, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2a, 0x44, 0x10, 0x00, 0x16, +0x84, 0x04, 0xdd, 0x26, 0xf2, 0x29, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x28, +0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x27, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, +0xdd, 0x26, 0xf2, 0x26, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf3, 0x0f, 0x46, 0x20, +0x04, 0x11, 0xa8, 0xd1, 0x84, 0x23, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x09, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x27, 0xf4, 0x0a, 0x46, 0x10, 0x04, 0x10, 0x14, 0x40, 0x81, 0x41, 0x80, 0xa1, +0xf0, 0x06, 0x14, 0x02, 0x81, 0x43, 0xf7, 0x02, 0xcf, 0x06, 0x87, 0x81, 0x15, 0xcf, 0x80, 0x02, +0x48, 0xff, 0xfc, 0x66, 0xec, 0xd4, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x8c, 0x96, 0x48, 0x97, 0xd0, 0x54, 0xa0, 0x00, 0xff, 0xf1, 0x83, 0x4e, 0x73, 0x05, 0x5a, +0x84, 0x24, 0x50, 0x2f, 0x80, 0x40, 0x80, 0x07, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x00, 0xac, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x64, +0x84, 0x05, 0xdd, 0x26, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x60, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, +0x80, 0x20, 0x50, 0x2f, 0x80, 0x5c, 0xdd, 0x26, 0x80, 0x27, 0x50, 0x2f, 0x80, 0x58, 0x84, 0x05, +0xdd, 0x26, 0x84, 0x26, 0x50, 0x2f, 0x80, 0x54, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0x84, 0x27, +0x50, 0x2f, 0x80, 0x50, 0xdd, 0x26, 0x81, 0x26, 0x44, 0x80, 0x00, 0x25, 0x50, 0x6f, 0x80, 0x18, +0x80, 0x28, 0x80, 0x46, 0x84, 0x05, 0xdd, 0x29, 0x8d, 0x01, 0x44, 0x00, 0x00, 0x2f, 0x9d, 0xb4, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x80, 0xac, 0x4c, 0x80, 0x7f, 0xf4, 0x44, 0x10, 0x00, 0x3a, +0x50, 0x2f, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x3b, 0x50, 0x2f, 0x80, 0x44, +0x84, 0x05, 0xdd, 0x27, 0x50, 0x9f, 0x80, 0x6c, 0x44, 0x10, 0x00, 0x17, 0x50, 0x2f, 0x80, 0x4c, +0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x49, +0x84, 0x05, 0xdd, 0x27, 0xf4, 0x1b, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x01, 0x64, 0x58, 0x22, +0x00, 0x03, 0x84, 0x20, 0x84, 0x05, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0x21, 0x80, 0x49, 0x84, 0x05, +0xdd, 0x27, 0xf3, 0x1b, 0x84, 0x05, 0x58, 0x21, 0x80, 0x01, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, +0x84, 0xc0, 0x81, 0x09, 0x84, 0x00, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x47, 0x9c, 0x49, 0x4c, 0x11, +0x7f, 0xfd, 0x9c, 0x01, 0x44, 0x50, 0x00, 0x64, 0xd0, 0x03, 0x84, 0x20, 0xd5, 0xf6, 0x84, 0x21, +0x84, 0x05, 0x80, 0x48, 0xdd, 0x27, 0xf1, 0x1b, 0x9d, 0xb1, 0x96, 0x0c, 0x45, 0xc0, 0x00, 0x28, +0xf0, 0x9b, 0x4c, 0x6e, 0x00, 0x03, 0xc8, 0xe7, 0x51, 0xef, 0x80, 0x6c, 0x80, 0x5e, 0x84, 0x20, +0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf0, 0x1b, 0x85, 0x1c, +0x40, 0x60, 0x20, 0x02, 0x58, 0x23, 0x00, 0x01, 0x84, 0x20, 0x50, 0x7f, 0x80, 0x68, 0x84, 0x05, +0xf6, 0x9b, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x80, 0x47, 0x44, 0x10, +0x00, 0x17, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf5, 0x1a, +0x45, 0xcf, 0xff, 0xe0, 0x40, 0x92, 0xf0, 0x02, 0x58, 0x14, 0x80, 0x10, 0x44, 0x00, 0x00, 0x17, +0x14, 0x9f, 0x80, 0x1a, 0x85, 0x09, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, +0x44, 0x30, 0x00, 0x31, 0x84, 0x82, 0x44, 0x00, 0x00, 0x27, 0x40, 0x64, 0x28, 0x1b, 0x40, 0x60, +0x28, 0x1a, 0x40, 0x22, 0x28, 0x1b, 0x40, 0x21, 0xa8, 0x1a, 0x85, 0x20, 0xf2, 0x84, 0xf6, 0x85, +0x81, 0x09, 0x83, 0x89, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x80, 0xac, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x01, 0x64, 0x4e, 0x93, 0x00, 0x56, 0x84, 0x28, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, +0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x1b, 0x84, 0x28, 0x54, 0x21, 0x80, 0xfb, 0x84, 0x05, 0x4b, 0xe0, +0x18, 0x01, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf2, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x58, 0x11, 0x00, 0x01, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xf1, 0x05, 0xf1, 0x82, 0x80, 0x29, +0xd5, 0x09, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0xaa, +0xd1, 0x03, 0x84, 0x00, 0xd5, 0xf7, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf7, 0x1a, 0x84, 0x04, 0x54, 0x13, 0x80, 0xe7, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, +0x84, 0xc7, 0x9c, 0x01, 0x4c, 0x03, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, +0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0xd5, 0x58, +0x84, 0x28, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x1b, 0x84, 0x28, +0x58, 0x21, 0x80, 0x04, 0x84, 0x05, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, +0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf2, 0x1a, +0x44, 0x00, 0x00, 0x15, 0x58, 0x11, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, +0xdd, 0x2f, 0xf1, 0x04, 0xf1, 0x82, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, +0x4c, 0x0f, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x8a, 0x4c, 0x12, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, +0x84, 0x24, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0xf7, 0x1a, 0x84, 0x04, 0x54, 0x53, 0x80, 0xe7, 0x58, 0x12, 0x80, 0x10, 0xf5, 0x9a, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, +0x84, 0xc7, 0x9c, 0x01, 0x4c, 0x03, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, +0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, 0x84, 0x00, 0x50, 0x2f, 0x80, 0x68, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf1, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x54, 0x10, +0x80, 0xfe, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x80, 0xac, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x4e, 0xa2, 0x00, 0x7a, +0x46, 0x20, 0x04, 0x10, 0x47, 0xe0, 0x04, 0x10, 0x59, 0xef, 0x05, 0x04, 0x44, 0x30, 0x00, 0x10, +0x58, 0x21, 0x05, 0x0c, 0x44, 0x10, 0x00, 0x18, 0xb6, 0x62, 0xb6, 0x3e, 0x50, 0x2f, 0x80, 0x6c, +0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x1b, 0x44, 0x10, 0x00, 0x11, +0x58, 0x2e, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xc1, +0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0x20, 0x84, 0x05, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x14, 0x84, 0x42, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x6c, +0x84, 0x05, 0xdd, 0x27, 0xf0, 0x1b, 0x44, 0x5f, 0xff, 0xc0, 0x40, 0x40, 0x14, 0x02, 0xf4, 0x9b, +0x58, 0x22, 0x00, 0x3f, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x6c, +0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x44, 0x3f, 0xff, 0xc0, 0x41, 0xc1, 0x0c, 0x02, 0x15, 0xcf, +0x80, 0x1b, 0x58, 0x2e, 0x00, 0x3f, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0x80, 0x20, +0x44, 0x20, 0x00, 0x31, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x3a, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, +0xdd, 0x27, 0xf0, 0x1b, 0x44, 0x5f, 0xff, 0x80, 0x40, 0x40, 0x14, 0x02, 0xf4, 0x9b, 0x80, 0x44, +0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x3b, 0x50, 0x2f, 0x80, 0x6c, +0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x44, 0x3f, 0xff, 0x80, 0x41, 0xc1, 0x0c, 0x02, 0x15, 0xcf, +0x80, 0x1b, 0x80, 0x5c, 0x84, 0x05, 0x44, 0x10, 0x00, 0x3b, 0xdd, 0x26, 0x87, 0x80, 0xd5, 0x6c, +0x46, 0x10, 0x04, 0x10, 0x47, 0xe0, 0x04, 0x10, 0x59, 0xef, 0x05, 0x04, 0x84, 0x88, 0x44, 0x80, +0x00, 0x18, 0x58, 0x10, 0x85, 0x0c, 0xb6, 0x81, 0xb7, 0x1e, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, +0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, 0x44, 0x10, 0x00, 0x11, 0x58, 0x21, 0x80, 0x80, +0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xf1, 0x84, 0x05, 0xdd, 0x26, +0x80, 0x48, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x14, 0x44, 0x20, +0x00, 0xc2, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, +0xf2, 0x1b, 0x44, 0x0f, 0xff, 0xc0, 0x40, 0x51, 0x00, 0x02, 0xf5, 0x9b, 0x58, 0x22, 0x80, 0x34, +0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, +0xf4, 0x1b, 0x44, 0x8f, 0xff, 0xc0, 0x40, 0x32, 0x20, 0x02, 0xf3, 0x9b, 0x58, 0x21, 0x80, 0x34, +0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x26, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, +0xf2, 0x1b, 0x44, 0x0f, 0xff, 0x80, 0x40, 0x51, 0x00, 0x02, 0xf5, 0x9b, 0x80, 0x45, 0x84, 0x26, +0x84, 0x05, 0xdd, 0x26, 0x84, 0x27, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf7, 0x1b, +0x44, 0x4f, 0xff, 0x80, 0x40, 0x83, 0x90, 0x02, 0x14, 0x8f, 0x80, 0x1b, 0x80, 0x48, 0x84, 0x05, +0x84, 0x27, 0xdd, 0x26, 0x81, 0x0a, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, +0x4c, 0x03, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0xea, 0x4c, 0x13, 0x80, 0x04, 0x84, 0x00, 0xd5, 0xf6, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x84, 0x22, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, +0x18, 0x01, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0xec, 0x50, 0x2f, 0x80, 0x68, 0x44, 0x10, +0x00, 0x9f, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x1a, 0x84, 0x59, 0x40, 0x11, 0x88, 0x02, +0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, +0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xf5, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x58, 0x12, 0x80, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, 0x4c, 0x0f, +0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, +0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0xf1, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x54, 0x10, 0x80, 0xfe, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, +0x4c, 0x02, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0xca, 0x4c, 0x13, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, +0x1c, 0x01, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x82, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0xc0, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0xec, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0xa7, +0x9c, 0x01, 0xd8, 0xfd, 0x9c, 0x49, 0x44, 0x30, 0x00, 0x64, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x00, +0xd5, 0xf6, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x4b, 0xe0, 0x1c, 0x01, +0xf2, 0x1a, 0x84, 0x02, 0x4c, 0x20, 0x00, 0x08, 0x45, 0xe0, 0x00, 0x14, 0x4c, 0x6f, 0x00, 0x04, +0x9d, 0xb1, 0xd5, 0xe3, 0x44, 0x10, 0x00, 0x39, 0x44, 0x00, 0x00, 0x9e, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x50, 0x2f, 0x80, 0x68, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x00, 0x1f, 0x80, 0x68, 0x54, 0x10, +0x80, 0x7f, 0xf1, 0x81, 0x5e, 0xf0, 0x80, 0x40, 0xe9, 0x06, 0x44, 0x6f, 0xff, 0x80, 0x40, 0x40, +0x98, 0x04, 0xf4, 0x81, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, 0x84, 0x22, 0x44, 0x00, +0x00, 0x9e, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x30, 0x00, 0x06, 0x58, 0x31, 0x81, 0xec, 0x44, 0x10, +0x00, 0x9f, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x4b, 0xe0, 0x0c, 0x01, 0xf5, 0x1a, 0x44, 0x00, +0x00, 0x9f, 0x58, 0x12, 0x80, 0x06, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x81, 0x64, 0x4e, 0xa2, 0x00, 0x2a, 0x50, 0x2f, 0x80, 0x6c, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf0, 0x1b, 0x44, 0x10, 0x00, 0x3a, +0x54, 0x40, 0x00, 0x80, 0xf4, 0x9b, 0x40, 0x2e, 0x10, 0x00, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, +0x50, 0x2f, 0x80, 0x6c, 0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x80, 0xac, 0xdd, 0x2f, 0xf2, 0x1b, 0x44, 0x10, 0x00, 0x3b, 0x54, 0x31, 0x00, 0x80, 0x40, 0x2e, +0x0c, 0x00, 0x84, 0x00, 0xd5, 0x24, 0x84, 0x26, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf5, 0x1b, 0x84, 0x26, 0x54, 0x62, 0x80, 0x80, +0xf6, 0x9b, 0x40, 0x24, 0x18, 0x00, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x27, 0x50, 0x2f, +0x80, 0x6c, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf1, 0x1b, +0x84, 0x05, 0x54, 0x30, 0x80, 0x80, 0x40, 0x24, 0x0c, 0x00, 0x84, 0x27, 0xf3, 0x9b, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, 0x4c, 0x0f, 0x7f, 0xfd, +0x9c, 0x49, 0x84, 0x6a, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, +0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, +0xf2, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x58, 0x11, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, +0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, +0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0xf1, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x54, 0x10, 0x80, 0xfe, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x09, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, +0x4c, 0x03, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0xaa, 0xd1, 0x03, 0x84, 0x00, 0xd5, 0xf7, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, +0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x82, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0xc0, 0x84, 0x20, +0xd5, 0x0b, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, 0x4c, 0x0f, 0x7f, 0xfd, 0x9c, 0x49, 0x44, 0x30, +0x00, 0x64, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x00, 0xd5, 0xf5, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, +0x44, 0x10, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf2, 0x1a, +0x84, 0x82, 0x4c, 0x22, 0x00, 0x08, 0x44, 0x00, 0x00, 0x14, 0x4c, 0x60, 0x00, 0x04, 0x9d, 0xb1, +0xd5, 0xdf, 0x44, 0x10, 0x00, 0x39, 0x44, 0x00, 0x00, 0x9e, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x50, 0x2f, 0x80, 0x68, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x00, 0x1f, 0x80, 0x68, 0x54, 0x10, 0x80, 0x7f, +0x5e, 0xf0, 0x80, 0x40, 0xe9, 0x05, 0x44, 0x5f, 0xff, 0x80, 0x40, 0x10, 0x94, 0x04, 0x05, 0xef, +0x80, 0x01, 0xf6, 0x02, 0x40, 0x1f, 0x04, 0x01, 0x40, 0x2e, 0x28, 0x1b, 0x40, 0x24, 0x28, 0x1a, +0xe0, 0xc1, 0xe8, 0x22, 0xca, 0x2d, 0x4e, 0x93, 0x00, 0x12, 0x4e, 0xa2, 0x00, 0x09, 0x46, 0x70, +0x00, 0x0e, 0x58, 0x73, 0x83, 0x1d, 0x10, 0x93, 0x80, 0x00, 0xd5, 0x4e, 0x46, 0x90, 0x00, 0x0e, +0x58, 0x94, 0x83, 0x1c, 0x10, 0xa4, 0x80, 0x00, 0xd5, 0x47, 0x4e, 0xa2, 0x00, 0x07, 0x46, 0x10, +0x00, 0x0e, 0x58, 0x10, 0x83, 0x1f, 0xd5, 0x4a, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x83, 0x1e, +0x10, 0xa1, 0x80, 0x00, 0xd5, 0x4b, 0x5e, 0xf1, 0x00, 0x3f, 0xe8, 0x0a, 0x4e, 0xa2, 0x00, 0x06, +0x51, 0xce, 0x00, 0x01, 0x48, 0xff, 0xfe, 0xdf, 0x8d, 0x01, 0x48, 0xff, 0xfe, 0xdc, 0xf4, 0x02, +0xe0, 0x24, 0xe8, 0x19, 0x44, 0x00, 0x00, 0x3f, 0x4c, 0x20, 0x40, 0x16, 0x4e, 0x93, 0x00, 0x0b, +0x4e, 0xa2, 0x00, 0x1d, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0x1d, 0x11, 0xc0, 0x80, 0x00, +0xd5, 0x1b, 0x4e, 0xa2, 0x00, 0x26, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x83, 0x1f, 0x11, 0xc2, +0x80, 0x00, 0xd5, 0x24, 0x4e, 0x93, 0x00, 0x14, 0x4e, 0xa2, 0x00, 0x09, 0x47, 0xe0, 0x00, 0x0e, +0x59, 0xef, 0x03, 0x1d, 0x11, 0xcf, 0x00, 0x00, 0xd5, 0x07, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, +0x83, 0x1c, 0x10, 0x84, 0x80, 0x00, 0x85, 0x21, 0x48, 0xff, 0xfc, 0x26, 0x4e, 0xa2, 0x00, 0x09, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0x1f, 0x80, 0x5c, 0xae, 0x88, 0xd5, 0x07, 0x46, 0x30, +0x00, 0x0e, 0x58, 0x31, 0x83, 0x1e, 0x10, 0x81, 0x80, 0x00, 0x8d, 0x21, 0x84, 0x82, 0x4c, 0x92, +0x7c, 0x13, 0x46, 0x20, 0x04, 0x10, 0x46, 0x10, 0x04, 0x10, 0x85, 0x00, 0x58, 0x21, 0x05, 0x0c, +0x58, 0x10, 0x85, 0x04, 0xb7, 0x02, 0xb7, 0x01, 0x50, 0x2f, 0x80, 0x6c, 0x44, 0x10, 0x00, 0x11, +0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, 0xf0, 0x1b, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x54, 0x20, 0x00, 0x7f, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, +0x80, 0x48, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x14, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x19, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x18, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, +0x84, 0x05, 0xf2, 0x17, 0x80, 0x20, 0xdd, 0x26, 0xf2, 0x16, 0x80, 0x28, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x15, 0x84, 0x26, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, 0x84, 0x05, 0x84, 0x27, 0xdd, 0x26, +0x50, 0x9f, 0x80, 0x18, 0x44, 0x70, 0x00, 0x25, 0x0c, 0x24, 0x80, 0x01, 0x80, 0x27, 0x84, 0x05, +0xdd, 0x26, 0x9d, 0xf9, 0x44, 0x50, 0x00, 0x2f, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x01, 0x64, +0xdf, 0xf4, 0xf2, 0x12, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0x4b, 0xe0, 0x20, 0x01, 0xf2, 0x11, +0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x26, 0x50, 0x8f, 0x80, 0x68, 0x84, 0x22, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x90, +0x00, 0x06, 0x58, 0x94, 0x81, 0xec, 0x80, 0x48, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x4b, 0xe0, +0x24, 0x01, 0xf3, 0x1a, 0x44, 0x00, 0x00, 0x9f, 0x54, 0x11, 0x80, 0xf9, 0xdd, 0x26, 0x80, 0x48, +0x84, 0x24, 0x84, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0xf7, 0x1a, 0x84, 0x04, 0x54, 0x13, 0x80, 0xf3, +0xdd, 0x26, 0xf1, 0x13, 0x44, 0x00, 0x00, 0x17, 0xdd, 0x26, 0xf1, 0x10, 0x84, 0x04, 0xdd, 0x26, +0x05, 0xef, 0x80, 0x03, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x80, 0xac, 0x50, 0x8f, 0x80, 0x6c, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x4f, 0xe3, 0x00, 0x4c, 0x80, 0x48, 0x84, 0x26, +0x84, 0x05, 0xdd, 0x27, 0xf4, 0x1b, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, 0x83, 0x1c, 0x54, 0x52, +0x00, 0xc0, 0x00, 0x14, 0x80, 0x00, 0xf5, 0x9b, 0x98, 0x8d, 0x84, 0x05, 0x84, 0x26, 0xdd, 0x26, +0x80, 0x48, 0x84, 0x27, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, 0x00, 0x04, 0x80, 0x00, 0x54, 0x91, +0x80, 0xc0, 0x14, 0x9f, 0x80, 0x1b, 0x40, 0x20, 0x24, 0x00, 0x84, 0x27, 0x84, 0x05, 0xdd, 0x26, +0x80, 0x48, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x46, 0x90, 0x00, 0x0e, +0x58, 0x94, 0x83, 0x1d, 0x54, 0x51, 0x00, 0xc0, 0x00, 0x44, 0x80, 0x00, 0xf5, 0x9b, 0x98, 0xa5, +0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0xdd, 0x26, 0x80, 0x48, 0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, +0xdd, 0x27, 0xf1, 0x1b, 0x00, 0x04, 0x80, 0x00, 0x54, 0x40, 0x80, 0xc0, 0xf4, 0x9b, 0x98, 0x84, +0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x03, 0x84, 0x28, 0x84, 0x05, 0xd5, 0x49, +0x84, 0x26, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, 0xf1, 0x1b, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, +0x83, 0x1e, 0x54, 0x50, 0x80, 0xc0, 0x00, 0x04, 0x80, 0x00, 0xf5, 0x9b, 0x98, 0x85, 0x84, 0x26, +0x84, 0x05, 0xdd, 0x26, 0x84, 0x27, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, 0x00, 0x24, +0x80, 0x00, 0x54, 0x91, 0x80, 0xc0, 0x14, 0x9f, 0x80, 0x1b, 0x88, 0x49, 0x84, 0x27, 0x84, 0x05, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x3a, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, 0xf4, 0x1b, 0x46, 0x90, +0x00, 0x0e, 0x58, 0x94, 0x83, 0x1f, 0x54, 0x52, 0x00, 0xc0, 0x00, 0x14, 0x80, 0x00, 0xf5, 0x9b, +0x98, 0x8d, 0x84, 0x05, 0x44, 0x10, 0x00, 0x3a, 0xdd, 0x26, 0x80, 0x48, 0x44, 0x10, 0x00, 0x3b, +0x84, 0x05, 0xdd, 0x27, 0xf0, 0x1b, 0x00, 0x24, 0x80, 0x00, 0x54, 0x30, 0x00, 0xc0, 0xf3, 0x9b, +0x98, 0x93, 0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0x84, 0x28, 0x84, 0x44, +0xdd, 0x26, 0xec, 0x74, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xf4, 0x84, 0x40, 0xf2, 0x81, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x97, 0x83, 0x28, 0x54, 0x80, +0x00, 0xff, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x04, 0x20, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x81, 0x64, 0xa7, 0x70, 0x4c, 0x54, 0x40, 0x16, 0xa6, 0xb1, 0x44, 0x10, 0x00, 0x11, 0x84, 0x00, +0xdd, 0x27, 0xa6, 0xb2, 0x44, 0x10, 0x00, 0x12, 0x84, 0x00, 0xdd, 0x27, 0xa6, 0xb3, 0x44, 0x10, +0x00, 0x13, 0x84, 0x00, 0xdd, 0x27, 0xa6, 0xb4, 0x84, 0x00, 0x44, 0x10, 0x00, 0x14, 0xdd, 0x27, +0x9d, 0xb5, 0x46, 0x50, 0x00, 0x0b, 0x58, 0x52, 0x84, 0x66, 0xde, 0xe4, 0x46, 0x50, 0x04, 0x11, +0x05, 0xe2, 0x80, 0xec, 0x44, 0x1f, 0xc0, 0xc0, 0x54, 0x74, 0x80, 0x3f, 0x40, 0x6f, 0x04, 0x02, +0x40, 0x43, 0x98, 0x04, 0x14, 0x42, 0x80, 0xec, 0xe7, 0x0f, 0xe8, 0x1a, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x27, 0x80, 0xcb, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x52, 0x71, 0x00, 0x37, +0x80, 0x27, 0x44, 0x00, 0x00, 0x3e, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x27, 0x44, 0x00, 0x00, 0x3f, +0x4b, 0xe0, 0x18, 0x01, 0x80, 0x27, 0x44, 0x00, 0x00, 0x40, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x24, +0x40, 0x2f, 0x84, 0x00, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, +0xf1, 0x01, 0x84, 0x00, 0x58, 0x50, 0x80, 0x80, 0x80, 0x45, 0x84, 0x24, 0x46, 0x60, 0x00, 0x0e, +0x58, 0x63, 0x03, 0x20, 0xf5, 0x81, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, +0xa7, 0x32, 0x40, 0x32, 0x04, 0x09, 0x54, 0x71, 0x80, 0x07, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x8c, 0x24, 0xdd, 0x2f, 0xc7, 0x06, 0x84, 0xa1, 0x4c, 0x72, 0xc1, 0x3a, 0x48, 0x00, +0x00, 0x86, 0x00, 0x83, 0x00, 0x01, 0x84, 0xa4, 0x54, 0x84, 0x00, 0x0e, 0x4c, 0x82, 0xc0, 0x07, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0xd5, 0x4a, 0x84, 0xa2, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x03, 0x6c, 0x4c, 0x82, 0xc0, 0x44, 0x44, 0x10, 0x00, 0x12, 0x44, 0x00, 0x00, 0x45, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x5e, 0x44, 0x00, 0x00, 0x4b, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, +0x00, 0x5b, 0xdd, 0x26, 0x80, 0x28, 0x44, 0x00, 0x00, 0x5c, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x23, +0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x26, 0x44, 0x00, 0x00, 0xc4, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x17, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x88, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x5e, 0x48, 0x00, 0x00, 0xb0, 0x44, 0x10, 0x00, 0x12, +0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, 0x00, 0x5b, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, 0x44, 0x00, 0x00, 0xc4, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x26, 0x44, 0x00, +0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x12, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, 0x00, 0xc3, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, 0x48, 0x00, 0x00, 0x81, 0xa6, 0xf1, 0x84, 0x04, 0x54, 0x81, +0x80, 0x0e, 0x4c, 0x80, 0x40, 0x34, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x44, 0x10, +0x00, 0x15, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x80, 0x28, 0x44, 0x00, 0x00, 0x5b, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x00, +0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x28, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x16, 0xd5, 0x48, 0x84, 0xa2, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x03, 0x6c, 0x4c, 0x82, 0xc0, 0x45, 0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0x45, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x5c, 0x44, 0x00, 0x00, 0x4b, 0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, +0x00, 0x5b, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x00, 0x00, 0x5c, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x23, +0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x10, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x28, 0x44, 0x00, 0x00, 0xc4, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x15, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x16, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x88, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x5b, 0x44, 0x00, 0x00, 0xc4, 0xd5, 0x30, 0x44, 0x10, +0x00, 0x15, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, 0x00, 0x5b, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x00, +0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x28, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xc4, 0x44, 0x10, 0x00, 0x16, 0xdd, 0x26, 0x84, 0x01, +0x80, 0x40, 0x80, 0x27, 0x46, 0x60, 0x00, 0x07, 0x58, 0x63, 0x05, 0x6c, 0x4b, 0xe0, 0x18, 0x01, +0x80, 0x27, 0x84, 0x00, 0x84, 0x41, 0x4b, 0xe0, 0x18, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0xe6, 0x38, 0xe9, 0x36, +0x80, 0x60, 0xa2, 0x59, 0x47, 0xe0, 0x00, 0x0e, 0x14, 0x1f, 0x00, 0xc8, 0xb4, 0xa3, 0x50, 0x20, +0x00, 0x08, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x57, 0x80, 0xc9, 0xb4, 0x62, 0x50, 0x20, 0x00, 0x0c, +0x46, 0xf0, 0x00, 0x0e, 0x14, 0x37, 0x80, 0xca, 0xb4, 0xa2, 0x50, 0x20, 0x00, 0x10, 0x46, 0xf0, +0x00, 0x0e, 0x14, 0x57, 0x80, 0xcb, 0x50, 0x50, 0x00, 0x14, 0xb4, 0x82, 0x46, 0xf0, 0x00, 0x0e, +0x14, 0x47, 0x80, 0xcc, 0x00, 0x0f, 0x03, 0x20, 0xb4, 0x65, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x37, +0x80, 0xcd, 0x5c, 0xf0, 0x00, 0x37, 0xe8, 0x0a, 0x42, 0x10, 0xa0, 0x0b, 0x46, 0xf0, 0x00, 0x08, +0x58, 0xf7, 0x81, 0x7c, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x54, 0x90, 0x00, 0xff, 0x54, 0x80, 0x80, 0xff, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, +0x00, 0xb0, 0x97, 0xd0, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x29, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, +0x18, 0x01, 0x4e, 0x83, 0x00, 0x07, 0x44, 0x10, 0x00, 0xb1, 0x44, 0x00, 0x00, 0x9e, 0xd5, 0x05, +0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0xb2, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x27, 0x44, 0x00, +0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x54, 0x90, 0x00, 0xff, 0x97, 0xc8, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0xb0, +0x81, 0x02, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x44, 0x30, +0x00, 0xb2, 0x44, 0x40, 0x00, 0xb1, 0x40, 0x12, 0x24, 0x1a, 0x40, 0x11, 0xa4, 0x1b, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x26, 0x80, 0x27, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x15, +0x84, 0x21, 0xdd, 0x26, 0x84, 0x00, 0x92, 0x00, 0x84, 0x27, 0x9c, 0x01, 0x4c, 0x00, 0xff, 0xfd, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0x4b, 0xe0, +0x18, 0x01, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x9f, +0x44, 0x10, 0x00, 0x9b, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x9b, 0xf0, 0x81, 0x84, 0xe0, +0x50, 0x6f, 0x80, 0x04, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x81, 0xec, 0xd5, 0x27, 0x44, 0x20, +0x00, 0x65, 0x4c, 0x71, 0x00, 0x04, 0x84, 0x00, 0xd5, 0x18, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0x44, 0x00, +0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0xd5, 0x17, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0x49, 0xd9, 0xfd, +0x9c, 0x01, 0x87, 0xca, 0x4c, 0x0f, 0x00, 0x04, 0x84, 0x20, 0xd5, 0xf7, 0x84, 0x00, 0x44, 0x10, +0x00, 0x9f, 0x80, 0x46, 0x9d, 0xf9, 0x4b, 0xe0, 0x24, 0x01, 0xf4, 0x01, 0x44, 0x30, 0x00, 0x9b, +0x4c, 0x41, 0xbf, 0xd7, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x44, 0x10, 0x00, 0xba, +0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x2a, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, +0x18, 0x01, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x80, 0x7c, 0xb4, 0x01, 0x40, 0x10, 0x40, 0x09, +0x4e, 0x04, 0x00, 0x05, 0x44, 0x2f, 0x00, 0x00, 0x98, 0x4a, 0x45, 0xe0, 0x80, 0x00, 0x40, 0x50, +0x78, 0x02, 0x96, 0x01, 0xc5, 0x04, 0x44, 0x4f, 0x00, 0x00, 0x98, 0x04, 0x42, 0x30, 0x84, 0x24, +0x42, 0x30, 0x00, 0x73, 0xb6, 0x68, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x6c, 0x96, 0x00, 0xf0, 0x82, 0xc0, 0x08, 0x84, 0x20, 0xf1, 0x84, +0xf1, 0x89, 0xf1, 0x8a, 0xf1, 0x8b, 0x48, 0x00, 0x02, 0x7f, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, +0x80, 0x04, 0xb5, 0x23, 0x47, 0xe0, 0x04, 0x11, 0x14, 0x9f, 0x80, 0x0b, 0x59, 0xef, 0x03, 0xb8, +0xb4, 0x5e, 0x46, 0x70, 0x04, 0x10, 0xf2, 0x8a, 0x58, 0x73, 0x85, 0x04, 0xb4, 0x87, 0x46, 0x80, +0x04, 0x10, 0xf4, 0x89, 0x58, 0x84, 0x05, 0x0c, 0xb4, 0x28, 0xf0, 0x02, 0x44, 0xa0, 0x00, 0x10, +0xf1, 0x84, 0xb6, 0x03, 0xb7, 0x5e, 0x50, 0x2f, 0x80, 0x48, 0xf0, 0x02, 0x84, 0x24, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf5, 0x12, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, +0x83, 0x6c, 0x54, 0x12, 0x80, 0xe7, 0x84, 0x04, 0x4b, 0xe0, 0x24, 0x01, 0xf0, 0x02, 0x47, 0xc0, +0x00, 0x06, 0x59, 0xce, 0x00, 0xac, 0x84, 0x21, 0x50, 0x2f, 0x80, 0x7c, 0xdd, 0x3c, 0xf0, 0x02, +0x84, 0x22, 0x50, 0x2f, 0x80, 0x78, 0xdd, 0x3c, 0xf0, 0x02, 0x44, 0x10, 0x00, 0x23, 0x50, 0x2f, +0x80, 0x74, 0xdd, 0x3c, 0xf0, 0x02, 0x44, 0x10, 0x00, 0x2a, 0x50, 0x2f, 0x80, 0x70, 0xdd, 0x3c, +0xf1, 0x02, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x22, 0x50, 0x2f, 0x80, 0x68, +0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x22, 0x50, 0x2f, 0x80, 0x64, 0x84, 0x04, 0xdd, 0x3c, +0x84, 0x23, 0x50, 0x2f, 0x80, 0x60, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x5c, +0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x58, 0x84, 0x05, 0xdd, 0x3c, +0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x54, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, +0x50, 0x2f, 0x80, 0x50, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x4c, +0x84, 0x05, 0xdd, 0x3c, 0xf0, 0x02, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x84, 0x21, +0x44, 0x20, 0x00, 0x21, 0xdd, 0x26, 0xf0, 0x02, 0x80, 0x4a, 0x84, 0x22, 0xdd, 0x26, 0xf0, 0x02, +0x44, 0x10, 0x00, 0x23, 0x80, 0x40, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x00, 0x2a, 0x44, 0x20, +0x00, 0x1b, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x20, 0x00, 0x81, 0x84, 0x04, 0xdd, 0x26, 0x84, 0x22, +0x44, 0x20, 0x00, 0x81, 0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x22, 0x44, 0x20, 0x00, 0xee, +0x84, 0x04, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x20, 0x00, 0x30, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x24, +0x44, 0x20, 0x00, 0x30, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, +0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xd7, 0x84, 0x05, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0xa2, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x20, 0x00, 0x20, +0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x00, 0x00, 0x17, 0x4b, 0xe0, +0x24, 0x01, 0xf2, 0x02, 0x46, 0x30, 0x00, 0xcf, 0x58, 0x31, 0x88, 0xb0, 0x44, 0x45, 0x20, 0x00, +0xb6, 0x47, 0xb6, 0x88, 0xb6, 0x67, 0xf3, 0x02, 0x92, 0x00, 0x84, 0xe7, 0x9c, 0xd9, 0x4c, 0x33, +0xff, 0xfd, 0x46, 0x80, 0x04, 0x10, 0x58, 0x84, 0x05, 0x0c, 0x44, 0x65, 0x20, 0x1e, 0xb6, 0xc8, +0x84, 0x60, 0x92, 0x00, 0x85, 0x47, 0x9c, 0xd9, 0x4c, 0x35, 0x7f, 0xfd, 0x47, 0xc0, 0x04, 0x10, +0x59, 0xce, 0x05, 0x0c, 0x44, 0x55, 0x20, 0x3e, 0xb6, 0xbc, 0x84, 0x60, 0x92, 0x00, 0x87, 0xc7, +0x9c, 0xd9, 0x4c, 0x3f, 0x7f, 0xfd, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x83, 0x6c, 0x84, 0x20, +0x44, 0x00, 0x00, 0x17, 0xdd, 0x29, 0x44, 0x10, 0x00, 0xaa, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, +0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x44, 0x10, 0x00, 0xab, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x29, 0x84, 0x2a, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x44, 0x10, 0x00, 0xac, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x3f, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x44, 0x10, +0x00, 0xad, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x3f, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x29, 0x44, 0x10, 0x00, 0x40, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x29, 0x50, 0x2f, 0x80, 0x88, +0x44, 0x10, 0x00, 0x1f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, +0xf7, 0x22, 0x44, 0x00, 0x00, 0x1f, 0x58, 0x23, 0x80, 0x60, 0xf2, 0xa2, 0x80, 0x22, 0xdd, 0x29, +0x84, 0x25, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, +0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x03, 0x00, 0x22, 0x12, 0x00, 0x00, 0x46, 0x30, 0x00, 0x0e, +0x58, 0x31, 0x83, 0x10, 0x84, 0x00, 0xf1, 0x88, 0xf3, 0x86, 0xf0, 0x83, 0x46, 0x80, 0x00, 0x0b, +0x58, 0x84, 0x04, 0xd8, 0x3a, 0x04, 0x04, 0x00, 0x46, 0x70, 0x00, 0x0b, 0x58, 0x73, 0x84, 0xd0, +0xf0, 0x90, 0x12, 0x1f, 0x80, 0x22, 0xf1, 0x03, 0x50, 0x0f, 0x80, 0x40, 0x38, 0x20, 0x04, 0x00, +0x44, 0x31, 0x20, 0x3e, 0x40, 0x91, 0x64, 0x08, 0x3a, 0x03, 0x84, 0x00, 0x46, 0x40, 0x04, 0x10, +0x41, 0xe4, 0x8c, 0x04, 0x58, 0x42, 0x05, 0x0c, 0x51, 0xcf, 0x80, 0x38, 0xb6, 0x1c, 0x12, 0x1f, +0x80, 0x1e, 0x15, 0xe2, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x06, 0x58, 0xa5, 0x03, 0x6c, 0xf5, 0x03, +0x44, 0x00, 0x00, 0x17, 0x38, 0x1e, 0x14, 0x00, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0xb0, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x2a, 0x44, 0x10, +0x00, 0xb2, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x2a, 0x44, 0x00, 0x00, 0x9f, 0x84, 0x20, 0xdd, 0x2a, +0xf6, 0x03, 0x54, 0x83, 0x00, 0xff, 0x4e, 0x83, 0x00, 0x3b, 0x46, 0x80, 0x2e, 0xba, 0x58, 0x84, +0x0e, 0x3f, 0x44, 0x70, 0x00, 0x12, 0x47, 0xc0, 0x00, 0x0b, 0x59, 0xce, 0x04, 0xbc, 0x46, 0xa0, +0x00, 0x06, 0x58, 0xa5, 0x01, 0x64, 0x46, 0x90, 0x00, 0x08, 0x58, 0x94, 0x85, 0xf4, 0xd5, 0x22, +0xf5, 0x08, 0x9f, 0xfa, 0x38, 0x6e, 0x14, 0x00, 0x80, 0x46, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x46, +0x84, 0x24, 0x84, 0x05, 0x4b, 0xe0, 0x28, 0x01, 0x84, 0x00, 0x80, 0x20, 0x50, 0x2f, 0x80, 0x84, +0x4b, 0xe0, 0x24, 0x01, 0x84, 0x00, 0x44, 0x10, 0x00, 0x21, 0x50, 0x2f, 0x80, 0x80, 0x4b, 0xe0, +0x24, 0x01, 0xf6, 0x21, 0xe3, 0x06, 0xe9, 0x05, 0x05, 0xef, 0x80, 0x20, 0xe3, 0x1e, 0xe8, 0x07, +0x97, 0xf9, 0x97, 0x3b, 0x84, 0x23, 0x84, 0x05, 0xf4, 0x88, 0xcf, 0xdb, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x83, 0x6c, 0x44, 0x10, 0x00, 0xb1, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x00, 0x00, 0x9f, 0x84, 0x20, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x90, 0x00, 0x20, 0x84, 0x60, +0x85, 0x40, 0x87, 0x85, 0x14, 0x9f, 0x80, 0x05, 0x10, 0x3f, 0x80, 0x8d, 0x10, 0x3f, 0x80, 0x8c, +0x15, 0xcf, 0x80, 0x07, 0x81, 0x2a, 0xd5, 0x63, 0x81, 0x49, 0xf1, 0x05, 0xa7, 0x98, 0x44, 0x80, +0x00, 0x20, 0x9a, 0xb1, 0x54, 0x71, 0x00, 0x3f, 0x80, 0x1c, 0x80, 0x27, 0x50, 0x2f, 0x80, 0x84, +0x4c, 0x64, 0x40, 0x06, 0x14, 0x9f, 0x80, 0x21, 0x80, 0xe6, 0xd5, 0x08, 0xf3, 0x81, 0x46, 0xf0, +0x00, 0x08, 0x58, 0xf7, 0x85, 0xf4, 0xdd, 0x2f, 0xf3, 0x01, 0x05, 0xef, 0x80, 0x0c, 0x80, 0x1c, +0x40, 0x5f, 0x18, 0x00, 0x54, 0x82, 0x80, 0x3f, 0x80, 0x28, 0x50, 0x2f, 0x80, 0x80, 0xf3, 0x81, +0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x85, 0xf4, 0xdd, 0x2f, 0x04, 0x9f, 0x80, 0x21, 0xf5, 0x20, +0x40, 0x04, 0xa8, 0x06, 0xf1, 0x0d, 0x56, 0x20, 0x00, 0x01, 0x40, 0x31, 0x04, 0x02, 0x40, 0x45, +0x14, 0x06, 0x40, 0x01, 0x90, 0x02, 0xf3, 0x01, 0xc0, 0x04, 0xaf, 0x98, 0x81, 0x2a, 0xd5, 0x08, +0xe3, 0x25, 0xe8, 0x03, 0xaf, 0xd8, 0xd5, 0x04, 0x10, 0x81, 0x80, 0x00, 0x81, 0x25, 0x08, 0x21, +0x80, 0x01, 0x80, 0x3c, 0x84, 0x00, 0x51, 0xce, 0x00, 0x01, 0x84, 0xc2, 0xf3, 0x81, 0x46, 0xf0, +0x00, 0x08, 0x58, 0xf7, 0x85, 0x94, 0xdd, 0x2f, 0xf3, 0x01, 0x4d, 0xc3, 0x7f, 0xaf, 0xf3, 0x07, +0x84, 0xff, 0x50, 0x81, 0xff, 0xff, 0x40, 0xa4, 0x00, 0x10, 0x14, 0xaf, 0x80, 0x07, 0x4c, 0xa3, +0x80, 0x18, 0xf4, 0x05, 0x41, 0xc2, 0x04, 0x09, 0x15, 0xcf, 0x80, 0x05, 0xf6, 0x07, 0x87, 0x80, +0xf0, 0x05, 0x56, 0x23, 0x00, 0x05, 0x87, 0xc0, 0x80, 0x3c, 0x40, 0x5f, 0x08, 0x06, 0x40, 0x10, +0x08, 0x1b, 0xf5, 0x8d, 0x50, 0x3f, 0x80, 0x8c, 0x81, 0x49, 0xf1, 0x8c, 0xd5, 0x8f, 0x04, 0x8f, +0x80, 0x06, 0xf1, 0x03, 0x00, 0x4f, 0x80, 0x8c, 0x00, 0x3f, 0x80, 0x8d, 0x50, 0x90, 0x80, 0x01, +0x50, 0x74, 0x00, 0x02, 0x85, 0x43, 0x14, 0x9f, 0x80, 0x03, 0x10, 0x44, 0x00, 0x00, 0x10, 0x34, +0x00, 0x01, 0xf7, 0x86, 0x4c, 0x95, 0x7e, 0xdc, 0xf2, 0x08, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x03, 0x00, 0xac, 0x80, 0x85, 0x20, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, 0xd5, 0x37, +0x44, 0x10, 0x00, 0xb0, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0x80, 0x2a, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x27, 0x00, 0x24, 0x00, 0x00, 0x44, 0x10, 0x00, 0xb1, 0x54, 0x41, 0x00, 0x3f, 0xf4, 0xa2, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x22, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0x00, 0x34, +0x00, 0x01, 0x44, 0x10, 0x00, 0xb2, 0x54, 0x61, 0x80, 0x3f, 0xf6, 0xa2, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x27, 0xf1, 0x22, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0x8d, 0x02, 0x46, 0x50, 0x00, 0x0e, +0x58, 0x52, 0x83, 0x16, 0x8d, 0x41, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x4c, 0x82, +0xff, 0xd1, 0x8d, 0x24, 0x45, 0xe0, 0x00, 0x10, 0x4c, 0x9f, 0x00, 0x08, 0x46, 0x80, 0x00, 0x0e, +0x58, 0x84, 0x03, 0x10, 0x81, 0x49, 0xd5, 0xc5, 0xf1, 0x02, 0x4e, 0x13, 0x00, 0x95, 0xf3, 0x0b, +0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0xb6, 0x64, 0x46, 0x50, 0x04, 0x11, 0xf0, 0x0a, +0x58, 0x52, 0x83, 0xb8, 0xb6, 0x05, 0x44, 0x00, 0x00, 0xf4, 0xf1, 0x02, 0xdd, 0x26, 0xf0, 0x02, +0x50, 0x2f, 0x80, 0x88, 0x44, 0x10, 0x00, 0x1f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0x04, 0x8f, 0x80, 0x22, 0x44, 0x00, 0x00, 0x1f, 0x54, 0x74, 0x00, 0x9f, 0xf7, 0xa2, +0x80, 0x27, 0xdd, 0x26, 0x84, 0x28, 0x44, 0x00, 0x00, 0x1f, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x15, +0x84, 0x21, 0xdd, 0x26, 0xf0, 0x02, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, 0x4c, 0x03, 0x7f, 0xfd, +0x84, 0x20, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x03, 0x6c, 0x44, 0x00, 0x00, 0x15, 0x4b, 0xe0, +0x20, 0x01, 0x46, 0x20, 0x04, 0x10, 0x84, 0xe0, 0x58, 0x21, 0x05, 0x04, 0xb6, 0xe2, 0x46, 0x00, +0x04, 0x10, 0xf5, 0x04, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0xa0, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x01, 0x64, 0xf1, 0x09, 0x80, 0x07, 0xb6, 0x22, 0x84, 0x21, 0xf2, 0x1f, 0xdd, 0x26, 0xf2, 0x1e, +0x84, 0x22, 0x80, 0x07, 0xdd, 0x26, 0xf2, 0x1d, 0x44, 0x10, 0x00, 0x23, 0x80, 0x07, 0xdd, 0x26, +0xf2, 0x1c, 0x44, 0x10, 0x00, 0x2a, 0x80, 0x07, 0xdd, 0x26, 0xf2, 0x1b, 0x80, 0x27, 0x84, 0x04, +0xdd, 0x26, 0xf2, 0x1a, 0x84, 0x22, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x19, 0x44, 0x10, 0x00, 0x22, +0x84, 0x04, 0xdd, 0x26, 0xf2, 0x18, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x17, 0x84, 0x24, +0x84, 0x05, 0xdd, 0x26, 0xf2, 0x16, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x15, +0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, +0xdd, 0x26, 0xf2, 0x13, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf1, 0x12, 0x84, 0x04, +0x4b, 0xe0, 0x20, 0x01, 0xec, 0x94, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0xef, 0xf8, 0x84, 0x21, 0x80, 0xe0, 0x44, 0x00, 0x00, 0x15, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x07, 0x9c, 0x91, 0x4c, 0x20, +0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x6a, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x40, 0xd5, 0xf6, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0x4b, 0xe0, 0x18, 0x01, +0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x9b, 0x44, 0x00, +0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x9b, 0xf1, 0x81, 0x50, 0x6f, 0x80, 0x04, +0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x01, 0xec, 0xd5, 0x12, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x91, +0x4c, 0x22, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x4a, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x40, 0xd5, 0xf6, +0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x46, 0x4b, 0xe0, 0x20, 0x01, 0xf5, 0x01, 0x45, 0xe0, +0x00, 0x9b, 0x4c, 0x5f, 0x40, 0x04, 0x84, 0x20, 0xd5, 0xf2, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x44, 0x10, 0x00, 0xba, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, +0x00, 0x14, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, +0x00, 0x7c, 0xb4, 0x20, 0x40, 0x20, 0xc0, 0x09, 0x4e, 0x14, 0x00, 0x05, 0x44, 0x3f, 0x00, 0x00, +0x98, 0x93, 0x44, 0x50, 0x80, 0x00, 0x40, 0x40, 0x94, 0x02, 0x96, 0x49, 0xc4, 0x04, 0x45, 0xef, +0x00, 0x00, 0x88, 0x3e, 0x42, 0x21, 0x08, 0x24, 0x42, 0x20, 0x84, 0x73, 0xb6, 0x47, 0xec, 0x08, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x7c, 0x96, 0x00, +0xf0, 0x83, 0xc0, 0x08, 0x84, 0x20, 0xf1, 0x87, 0xf1, 0x8a, 0xf1, 0x8b, 0xf1, 0x8c, 0x48, 0x00, +0x03, 0x9d, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0xb5, 0x24, 0x46, 0x30, 0x04, 0x11, +0x14, 0x9f, 0x80, 0x0a, 0x58, 0x31, 0x83, 0xb8, 0xb4, 0x43, 0x46, 0x70, 0x04, 0x10, 0xf2, 0x87, +0x58, 0x73, 0x85, 0x04, 0xb4, 0x27, 0x46, 0x80, 0x04, 0x10, 0xf1, 0x8c, 0x58, 0x84, 0x05, 0x0c, +0x05, 0xef, 0x80, 0x03, 0xb4, 0x08, 0x44, 0xa0, 0x00, 0x10, 0xf0, 0x8b, 0x15, 0xe2, 0x00, 0x00, +0xb7, 0x43, 0x50, 0x2f, 0x80, 0x44, 0xf0, 0x03, 0x84, 0x24, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x81, 0xec, 0xdd, 0x2f, 0xf5, 0x11, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x83, 0x6c, 0x54, 0x12, +0x80, 0xe7, 0x84, 0x04, 0x4b, 0xe0, 0x24, 0x01, 0xf0, 0x03, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, +0x00, 0xac, 0x84, 0x21, 0x50, 0x2f, 0x80, 0x78, 0xdd, 0x3c, 0xf0, 0x03, 0x84, 0x22, 0x50, 0x2f, +0x80, 0x74, 0xdd, 0x3c, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x23, 0x50, 0x2f, 0x80, 0x70, 0xdd, 0x3c, +0xf0, 0x03, 0x44, 0x10, 0x00, 0x2a, 0x50, 0x2f, 0x80, 0x6c, 0xdd, 0x3c, 0xf1, 0x03, 0x50, 0x2f, +0x80, 0x68, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x22, 0x50, 0x2f, 0x80, 0x64, 0x84, 0x04, 0xdd, 0x3c, +0x44, 0x10, 0x00, 0x22, 0x50, 0x2f, 0x80, 0x60, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x23, 0x50, 0x2f, +0x80, 0x5c, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x58, 0x84, 0x05, 0xdd, 0x3c, +0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x54, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x12, +0x50, 0x2f, 0x80, 0x50, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x4c, +0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x3c, +0xf0, 0x03, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0x84, 0x21, 0x44, 0x20, 0x00, 0x21, +0xdd, 0x26, 0xf0, 0x03, 0x80, 0x4a, 0x84, 0x22, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x23, +0x80, 0x40, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x2a, 0x44, 0x20, 0x00, 0x1b, 0xdd, 0x26, +0xf1, 0x03, 0x44, 0x20, 0x00, 0x81, 0x84, 0x04, 0xdd, 0x26, 0x84, 0x22, 0x44, 0x20, 0x00, 0x81, +0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x22, 0x44, 0x20, 0x00, 0xee, 0x84, 0x04, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, +0x44, 0x20, 0x00, 0xd7, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0xa2, +0x84, 0x05, 0xdd, 0x26, 0x44, 0x20, 0x00, 0x20, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, +0xf1, 0x03, 0x44, 0x00, 0x00, 0x17, 0x4b, 0xe0, 0x24, 0x01, 0xf2, 0x03, 0x46, 0x30, 0x00, 0xcf, +0x58, 0x31, 0x88, 0xb0, 0x44, 0x45, 0x20, 0x00, 0xb6, 0x47, 0xb6, 0x88, 0xb6, 0x67, 0xf3, 0x03, +0x92, 0x00, 0x84, 0xe7, 0x9c, 0xd9, 0x4c, 0x33, 0xff, 0xfd, 0x46, 0x80, 0x04, 0x10, 0x58, 0x84, +0x05, 0x0c, 0x44, 0x65, 0x20, 0x1e, 0xb6, 0xc8, 0x84, 0x60, 0x92, 0x00, 0x85, 0x47, 0x9c, 0xd9, +0x4c, 0x35, 0x7f, 0xfd, 0x47, 0xc0, 0x04, 0x10, 0x59, 0xce, 0x05, 0x0c, 0x44, 0x55, 0x20, 0x3e, +0xb6, 0xbc, 0x84, 0x60, 0x92, 0x00, 0x84, 0x87, 0x9c, 0xd9, 0x4c, 0x32, 0x7f, 0xfd, 0x46, 0x90, +0x00, 0x06, 0x58, 0x94, 0x83, 0x6c, 0x84, 0x24, 0x44, 0x00, 0x00, 0x17, 0xdd, 0x29, 0x44, 0x10, +0x00, 0x14, 0x44, 0x00, 0x00, 0xf1, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0xf2, +0xdd, 0x29, 0x44, 0x10, 0x00, 0x31, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x29, 0x44, 0x10, 0x00, 0xb0, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, +0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x01, 0xec, 0x50, 0x2f, 0x80, 0x40, 0x44, 0x10, 0x00, 0x1f, +0x84, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0xf1, 0x10, 0x44, 0x00, 0x00, 0x1f, 0x58, 0x20, 0x80, 0x60, +0xf2, 0x9f, 0x80, 0x22, 0xdd, 0x29, 0x84, 0x25, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x84, 0x24, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x84, 0x23, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x50, 0x2f, +0x80, 0x7c, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0xf3, 0x1f, 0x44, 0x00, +0x00, 0x9f, 0x58, 0x11, 0x80, 0x60, 0xdd, 0x29, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0x64, +0x84, 0x23, 0x44, 0x20, 0x00, 0x3c, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x20, 0x00, 0x3c, +0x84, 0x24, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x29, 0x44, 0x00, 0x00, 0x9f, 0x84, 0x20, 0xdd, 0x29, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, +0x83, 0x00, 0x22, 0x41, 0x80, 0x00, 0x4e, 0x44, 0x00, 0x04, 0x84, 0x80, 0xd5, 0x05, 0xe4, 0x93, +0xe9, 0x42, 0x44, 0x40, 0x00, 0x12, 0xad, 0x18, 0xd5, 0x3e, 0x46, 0x40, 0x00, 0x0b, 0x58, 0x42, +0x04, 0xbc, 0x38, 0x22, 0x08, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, +0x22, 0x54, 0x00, 0x00, 0x47, 0xe0, 0x00, 0x0b, 0x59, 0xef, 0x04, 0xbc, 0x38, 0x2f, 0x14, 0x00, +0x84, 0x24, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x44, 0x10, +0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x21, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x29, 0x80, 0x07, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, +0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x80, 0x06, 0xdd, 0x3c, 0xf0, 0x0f, 0xe3, 0x40, +0xe9, 0x24, 0xf3, 0x0e, 0xe3, 0x43, 0xe9, 0x21, 0x02, 0x14, 0x00, 0x00, 0x9c, 0x8a, 0x12, 0x24, +0x00, 0x00, 0xd5, 0x15, 0x46, 0xa0, 0x05, 0xf5, 0x58, 0xa5, 0x0e, 0x10, 0x46, 0x80, 0x00, 0x0e, +0x58, 0x84, 0x03, 0x00, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x83, 0x6c, 0x50, 0x7f, 0x80, 0x3c, +0x47, 0xc0, 0x00, 0x08, 0x59, 0xce, 0x0e, 0x0c, 0x50, 0x6f, 0x80, 0x38, 0x22, 0x24, 0x00, 0x00, +0x84, 0x23, 0x84, 0x05, 0xe4, 0x53, 0xe9, 0xaa, 0x85, 0x40, 0x85, 0x25, 0x45, 0xc0, 0x00, 0x20, +0x84, 0x00, 0x46, 0x70, 0x00, 0x0e, 0x58, 0x73, 0x83, 0x0c, 0x14, 0x9f, 0x80, 0x05, 0x15, 0xcf, +0x80, 0x06, 0x14, 0xaf, 0x80, 0x04, 0xae, 0x38, 0x50, 0x2f, 0x80, 0x38, 0x50, 0x5f, 0x80, 0x3c, +0x81, 0x2a, 0x83, 0x8a, 0x48, 0x00, 0x00, 0xf4, 0x14, 0x9f, 0x80, 0x04, 0x84, 0x61, 0x4c, 0xa1, +0x80, 0x17, 0x05, 0xef, 0x80, 0x05, 0x5e, 0xff, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0xd7, 0x46, 0x80, +0x00, 0x0e, 0x58, 0x84, 0x03, 0x0c, 0x00, 0x94, 0x00, 0x00, 0x04, 0x8f, 0x80, 0x09, 0x54, 0x14, +0x80, 0x0f, 0x56, 0x40, 0x80, 0x08, 0x40, 0x02, 0x0c, 0x06, 0xd5, 0x09, 0x54, 0x64, 0x80, 0x3f, +0x56, 0x33, 0x00, 0x20, 0x04, 0x8f, 0x80, 0x08, 0x5c, 0x01, 0x80, 0x01, 0xc0, 0x05, 0x15, 0xcf, +0x80, 0x0f, 0x80, 0xe9, 0xd5, 0x39, 0xf0, 0x06, 0x40, 0x74, 0x80, 0x01, 0x96, 0xf8, 0x4e, 0xa3, +0x00, 0x12, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0xf2, 0x81, 0xb6, 0xbf, 0x54, 0x71, +0x80, 0x0f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xf2, 0x01, 0xb4, 0xbf, +0xd5, 0x10, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0x29, 0xf2, 0x81, 0xb6, 0xbf, 0x54, 0x71, +0x80, 0x3f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, +0x80, 0x27, 0x44, 0x00, 0x00, 0x9f, 0xf2, 0x81, 0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0xb4, 0xbf, 0x80, 0x05, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x8e, 0x0c, +0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, 0xf1, 0x06, 0x84, 0x80, 0x40, 0x40, 0xa0, 0x1a, 0x41, 0xe2, +0x24, 0x00, 0x54, 0x3f, 0x00, 0xff, 0x4e, 0xa3, 0x00, 0x12, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, +0x00, 0x9e, 0xf2, 0x81, 0xb6, 0xbf, 0x54, 0x61, 0x80, 0x0f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0xf2, 0x01, 0xb4, 0xbf, 0xd5, 0x10, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, +0x00, 0x29, 0xf2, 0x81, 0xb6, 0xbf, 0x54, 0x61, 0x80, 0x3f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, 0x80, 0x26, 0x44, 0x00, 0x00, 0x9f, 0xb6, 0xbf, +0xf2, 0x81, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xf2, 0x01, 0x80, 0x02, +0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x8e, 0x0c, 0xdd, 0x2f, 0xf2, 0x01, 0xb4, 0xbf, 0x4e, 0x83, +0x00, 0x09, 0xf3, 0x0f, 0xe2, 0x7c, 0xe9, 0x05, 0xf0, 0x0e, 0x40, 0xfe, 0x00, 0x06, 0xe9, 0x0a, +0xf3, 0x0f, 0x05, 0xcf, 0x80, 0x0e, 0xe2, 0x7c, 0xe8, 0x04, 0x83, 0x83, 0x81, 0x27, 0xd5, 0x02, +0x81, 0x26, 0x4e, 0xa3, 0x00, 0x10, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0xf2, 0x81, +0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xf2, 0x01, 0xb4, 0xbf, +0xd5, 0x0e, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0x29, 0xf2, 0x81, 0xb6, 0xbf, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, 0x44, 0x00, 0x00, 0x9f, +0x80, 0x29, 0xf2, 0x81, 0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, +0xf2, 0x01, 0xb4, 0xbf, 0x4e, 0xa3, 0x00, 0x0a, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x0c, +0x10, 0x93, 0x00, 0x00, 0x04, 0x9f, 0x80, 0x04, 0x8d, 0x41, 0x54, 0xa5, 0x00, 0xff, 0x84, 0xe2, +0x4c, 0xa3, 0xff, 0x1c, 0xf1, 0x05, 0x9f, 0x09, 0x41, 0xe2, 0x00, 0x10, 0x15, 0xef, 0x80, 0x05, +0x4f, 0xe2, 0x00, 0x18, 0xf0, 0x06, 0x40, 0x30, 0x04, 0x09, 0xf3, 0x86, 0x05, 0xef, 0x80, 0x05, +0x14, 0x9f, 0x80, 0x04, 0x56, 0x4f, 0x00, 0x05, 0x56, 0x7f, 0x00, 0x03, 0x5c, 0xa2, 0x00, 0x01, +0x5c, 0x63, 0x80, 0x01, 0x14, 0xaf, 0x80, 0x08, 0xf6, 0x89, 0x85, 0x40, 0x48, 0xff, 0xff, 0x00, +0x44, 0x00, 0x00, 0x17, 0x84, 0x27, 0x14, 0x9f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x03, 0x0c, 0xa7, 0x50, 0x80, 0xdc, +0x55, 0xc2, 0x80, 0x08, 0x54, 0x32, 0x80, 0x0f, 0x4f, 0xc2, 0x00, 0x05, 0x50, 0x11, 0xff, 0xf0, +0x96, 0xca, 0x84, 0x04, 0x42, 0x31, 0x80, 0x01, 0x5e, 0xf1, 0xff, 0xf9, 0xe8, 0x04, 0x84, 0x78, +0xf3, 0x86, 0xd5, 0x04, 0x9f, 0x19, 0x97, 0xe2, 0xf7, 0x86, 0x05, 0xcf, 0x80, 0x04, 0x55, 0xee, +0x00, 0x20, 0x54, 0x3e, 0x00, 0x3f, 0x4f, 0xe2, 0x00, 0x05, 0x50, 0x51, 0xff, 0xc0, 0x96, 0xea, +0x44, 0x20, 0x00, 0x1c, 0x42, 0x31, 0x88, 0x01, 0x5e, 0xf1, 0xff, 0xe1, 0xe8, 0x04, 0x44, 0x3f, +0xff, 0xe0, 0xd5, 0x03, 0x9e, 0x59, 0x96, 0xca, 0xf3, 0x85, 0xf3, 0x06, 0xf7, 0x05, 0x87, 0xc0, +0x9d, 0x1b, 0x9c, 0x3b, 0x15, 0xef, 0x80, 0x08, 0xf4, 0x89, 0xf0, 0x8d, 0x50, 0x2f, 0x80, 0x3c, +0x83, 0x83, 0xd5, 0x5f, 0xf2, 0x81, 0xf4, 0x82, 0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x80, 0x2a, 0x44, 0x00, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x83, 0x6c, 0xdd, 0x2f, 0x44, 0x10, 0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x80, 0x26, 0x44, 0x00, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xf5, 0x01, 0x80, 0x05, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, +0x8e, 0x0c, 0xdd, 0x2f, 0xb4, 0xbf, 0xf1, 0x06, 0xf2, 0x01, 0xf4, 0x02, 0xd9, 0x09, 0xf3, 0x05, +0x4c, 0x81, 0xc0, 0x07, 0x10, 0xa2, 0x00, 0x00, 0xf6, 0x84, 0xf0, 0x0f, 0xd5, 0x0c, 0xf0, 0x0f, +0xe2, 0x09, 0xe9, 0x03, 0x80, 0x09, 0xd5, 0x07, 0x54, 0x93, 0x80, 0x3f, 0x10, 0xa2, 0x00, 0x00, +0x14, 0x9f, 0x80, 0x04, 0x8d, 0x01, 0x40, 0x84, 0x00, 0x10, 0x51, 0xce, 0x00, 0x01, 0x81, 0x20, +0x05, 0xef, 0x80, 0x05, 0x54, 0x74, 0x00, 0xff, 0x40, 0x3e, 0x78, 0x00, 0x05, 0xef, 0x80, 0x0d, +0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0x54, 0x63, 0x80, 0x3f, 0x40, 0xff, 0x0c, 0x07, +0xe8, 0xaa, 0xf7, 0x08, 0x9d, 0x29, 0x9c, 0x39, 0xf0, 0x88, 0x80, 0xc9, 0x41, 0xc2, 0x00, 0x10, +0x05, 0xef, 0x80, 0x08, 0xf3, 0x06, 0xf1, 0x09, 0x40, 0x5f, 0x0c, 0x00, 0xe0, 0x25, 0xe9, 0x0f, +0x54, 0x9e, 0x00, 0x0f, 0x85, 0x40, 0x80, 0xbc, 0x04, 0x8f, 0x80, 0x05, 0x83, 0x8a, 0x46, 0x40, +0x00, 0x0e, 0x58, 0x42, 0x03, 0x0c, 0x81, 0x49, 0x81, 0x26, 0xd5, 0xd3, 0xf6, 0x04, 0x46, 0x20, +0x00, 0x0e, 0x58, 0x21, 0x03, 0x0d, 0xaf, 0x90, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, +0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, +0x83, 0x0c, 0xa7, 0x28, 0x44, 0x00, 0x00, 0x9f, 0x54, 0x12, 0x00, 0x0f, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x0d, +0xa7, 0xc0, 0x44, 0x00, 0x00, 0x9f, 0x54, 0x13, 0x80, 0x3f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, +0x00, 0xf4, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x15, 0x84, 0x21, 0xdd, 0x26, 0x84, 0x60, 0x92, 0x00, +0x84, 0x27, 0x9c, 0xd9, 0x4c, 0x30, 0xff, 0xfd, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, +0x44, 0x00, 0x00, 0x15, 0x84, 0x20, 0xdd, 0x27, 0xf3, 0x03, 0xcb, 0x6e, 0x05, 0xef, 0x80, 0x0a, +0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x80, 0x04, 0x15, 0xe1, 0x80, 0x00, 0x46, 0x50, 0x04, 0x11, +0xf1, 0x07, 0x58, 0x52, 0x83, 0xb8, 0xb6, 0x25, 0x46, 0x20, 0x04, 0x10, 0xf0, 0x03, 0x58, 0x21, +0x05, 0x04, 0xb6, 0x02, 0x46, 0x40, 0x04, 0x10, 0xf6, 0x0b, 0x58, 0x42, 0x05, 0x0c, 0xb6, 0xc4, +0x44, 0x10, 0x00, 0xb0, 0x05, 0xef, 0x80, 0x0c, 0x44, 0x00, 0x00, 0x9e, 0x15, 0xe1, 0x00, 0x00, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0xdd, 0x27, 0xf1, 0x03, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x27, 0xf1, 0x10, 0x44, 0x00, 0x00, 0x1f, 0xdd, 0x27, 0xf2, 0x1e, 0xf0, 0x03, 0x84, 0x21, +0xdd, 0x26, 0xf2, 0x1d, 0xf0, 0x03, 0x84, 0x22, 0xdd, 0x26, 0xf2, 0x1c, 0xf0, 0x03, 0x44, 0x10, +0x00, 0x23, 0xdd, 0x26, 0xf2, 0x1b, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x2a, 0xdd, 0x26, 0xf2, 0x1a, +0xf1, 0x03, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x19, 0x84, 0x22, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x18, +0x44, 0x10, 0x00, 0x22, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x17, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x16, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x15, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, +0xdd, 0x26, 0xf2, 0x14, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x13, 0x44, 0x10, +0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x12, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, +0xf1, 0x11, 0x84, 0x04, 0xdd, 0x27, 0xec, 0x84, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x94, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x04, 0xe0, 0x96, 0x40, +0xf1, 0x82, 0x3a, 0x03, 0x08, 0x00, 0x50, 0x5f, 0x80, 0x2c, 0x80, 0x65, 0x3a, 0x01, 0x84, 0x24, +0x40, 0x41, 0x40, 0x09, 0xf0, 0x02, 0xac, 0x98, 0x10, 0x4f, 0x80, 0x36, 0xc0, 0x06, 0x84, 0x40, +0xf2, 0x87, 0xf2, 0x89, 0x48, 0x00, 0x02, 0xa3, 0x46, 0x70, 0x04, 0x10, 0x58, 0x73, 0x85, 0x0c, +0xb4, 0x87, 0x46, 0x80, 0x04, 0x10, 0xf4, 0x89, 0x58, 0x84, 0x05, 0x04, 0x05, 0xe4, 0x00, 0x00, +0xf1, 0x02, 0x15, 0xef, 0x80, 0x07, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, 0x00, 0xac, 0x50, 0x2f, +0x80, 0x64, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x60, 0x84, 0x04, +0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x5c, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, +0x00, 0x12, 0x50, 0x2f, 0x80, 0x58, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, +0x80, 0x54, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x50, 0x84, 0x05, +0xdd, 0x3c, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x4c, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x24, 0x50, 0x2f, +0x80, 0x48, 0x84, 0x05, 0xdd, 0x3c, 0xf1, 0x02, 0x46, 0xa0, 0x00, 0x06, 0x58, 0xa5, 0x01, 0x64, +0x44, 0x20, 0x00, 0x87, 0x84, 0x04, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0x24, +0x84, 0x04, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x2a, +0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xc1, 0x84, 0x05, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x13, +0x44, 0x20, 0x00, 0x60, 0x84, 0x05, 0xdd, 0x2a, 0xf2, 0x02, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, +0xdd, 0x2a, 0x84, 0x23, 0x44, 0x20, 0x00, 0x3c, 0x84, 0x05, 0xdd, 0x2a, 0x84, 0x24, 0x44, 0x20, +0x00, 0x3c, 0x84, 0x05, 0xdd, 0x2a, 0xf0, 0x02, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x81, 0xec, +0x44, 0x10, 0x00, 0x17, 0x50, 0x2f, 0x80, 0x40, 0x4b, 0xe0, 0x24, 0x01, 0xf0, 0x02, 0x50, 0x2f, +0x80, 0x44, 0x84, 0x24, 0x4b, 0xe0, 0x24, 0x01, 0xf1, 0x02, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x84, 0x04, 0x4b, 0xe0, 0x18, 0x01, 0xf1, 0x02, 0x44, 0x00, 0x00, 0x17, 0x4b, 0xe0, +0x18, 0x01, 0x47, 0xc0, 0x00, 0x92, 0xf0, 0x02, 0x46, 0xa0, 0x00, 0xdf, 0x46, 0x90, 0x00, 0x92, +0x58, 0xa5, 0x08, 0x38, 0x58, 0x94, 0x80, 0x10, 0xb6, 0x08, 0x15, 0xc3, 0x80, 0x00, 0xb7, 0x48, +0xb7, 0x27, 0xf3, 0x02, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0xd9, 0xdb, 0xfd, 0x46, 0x30, 0x04, 0x10, +0x46, 0x10, 0x00, 0x92, 0x58, 0x31, 0x85, 0x0c, 0x58, 0x10, 0x80, 0x30, 0xb6, 0x23, 0x84, 0x60, +0x92, 0x00, 0x84, 0x47, 0x9c, 0xd9, 0x4c, 0x31, 0x7f, 0xfd, 0x46, 0x70, 0x04, 0x10, 0x46, 0x80, +0x00, 0x92, 0x58, 0x73, 0x85, 0x0c, 0x58, 0x84, 0x00, 0x38, 0xb7, 0x07, 0x84, 0x60, 0x92, 0x00, +0x84, 0x07, 0x9c, 0xd9, 0x4c, 0x30, 0x7f, 0xfd, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x83, 0x6c, +0x84, 0x22, 0x44, 0x00, 0x00, 0x17, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x14, 0x44, 0x00, 0x00, 0xf1, +0xdd, 0x29, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0xf2, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x31, +0x44, 0x00, 0x00, 0xf4, 0xdd, 0x29, 0x84, 0x25, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x84, 0x20, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x85, 0x40, 0x84, 0x23, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, +0x14, 0xaf, 0x80, 0x03, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x60, 0xdd, 0x29, 0xf6, 0x03, +0x50, 0x5f, 0x80, 0x38, 0xf6, 0x88, 0xf6, 0x86, 0xf6, 0x85, 0xf6, 0x84, 0x81, 0x26, 0x51, 0xef, +0x80, 0x2c, 0x38, 0x8f, 0x24, 0x00, 0x84, 0x23, 0x80, 0x48, 0x84, 0x05, 0xb6, 0xbf, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x80, 0x48, 0x84, 0x24, 0x84, 0x05, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x6c, +0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x1c, 0x01, 0x45, 0xc0, 0x00, 0x93, 0x44, 0x00, +0x00, 0x9f, 0x44, 0x10, 0x00, 0x93, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0xc0, 0x15, 0xcf, 0x80, 0x0f, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0xec, 0xd5, 0x1b, 0x9d, 0xb1, 0x44, 0x40, 0x03, 0xe9, +0x4c, 0x62, 0x00, 0x1d, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x67, 0x9c, 0x01, 0x4c, 0x01, +0xff, 0xfd, 0x9c, 0x49, 0x84, 0x4a, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0xb6, 0xbf, +0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x50, 0x2f, 0x80, 0x3c, 0x4b, 0xe0, 0x1c, 0x01, 0xf0, 0x0f, +0x44, 0x10, 0x00, 0x93, 0xb4, 0xbf, 0x4c, 0x00, 0xbf, 0xe2, 0x87, 0x80, 0x46, 0xa0, 0x00, 0x06, +0x58, 0xa5, 0x03, 0x6c, 0x44, 0x40, 0x10, 0x00, 0x87, 0xc0, 0x15, 0xef, 0x80, 0x0e, 0xf4, 0x81, +0xb6, 0xbf, 0x44, 0x10, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x2a, 0x80, 0x3c, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x22, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x2a, 0x46, 0x50, +0x00, 0x0b, 0x58, 0x52, 0x84, 0x1c, 0xb5, 0x1f, 0xb4, 0x05, 0x80, 0x48, 0x44, 0x10, 0x00, 0x9f, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf2, 0x0e, 0x44, 0x10, 0x00, 0x21, +0x44, 0x00, 0x00, 0x9e, 0x40, 0x81, 0x60, 0x08, 0xdd, 0x2a, 0x46, 0x30, 0x00, 0x0b, 0x58, 0x31, +0x84, 0x1c, 0xb4, 0xff, 0xb4, 0x03, 0x80, 0x47, 0x44, 0x10, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf4, 0x0e, 0x44, 0x10, 0x00, 0x20, 0x44, 0x00, 0x00, 0x9e, +0x40, 0x72, 0x40, 0x08, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x04, 0x1c, 0xdd, 0x2a, 0xb4, 0x3f, +0xb4, 0x06, 0x80, 0x41, 0x44, 0x10, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, +0xdd, 0x2f, 0xf5, 0x0e, 0x44, 0x10, 0x00, 0x1f, 0x44, 0x00, 0x00, 0x9e, 0x40, 0x62, 0xa0, 0x08, +0xdd, 0x2a, 0xb4, 0x7f, 0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, 0x04, 0x1c, 0xb4, 0x02, 0x44, 0x10, +0x00, 0x9f, 0x80, 0x43, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0x40, 0x44, +0x1c, 0x00, 0x04, 0x8f, 0x80, 0x0e, 0x54, 0x3e, 0x00, 0xff, 0x40, 0x52, 0x20, 0x00, 0x98, 0xae, +0xf4, 0x01, 0xb4, 0xbf, 0xe6, 0x62, 0xe8, 0x10, 0x46, 0x10, 0x08, 0x00, 0x40, 0x01, 0x04, 0x02, +0xc0, 0x10, 0x46, 0x80, 0x0f, 0xff, 0x58, 0x84, 0x0f, 0xff, 0x46, 0x7f, 0xf0, 0x00, 0x40, 0x61, +0x20, 0x02, 0x98, 0x37, 0xd5, 0x07, 0x87, 0xc4, 0x4c, 0x3f, 0x40, 0x04, 0x80, 0x02, 0xd5, 0x1d, +0x80, 0x02, 0xcb, 0x05, 0x40, 0x30, 0x10, 0x16, 0xf3, 0x84, 0xd5, 0x1b, 0x84, 0x21, 0x4c, 0x30, +0xc0, 0x06, 0x40, 0x20, 0x10, 0x16, 0xf2, 0x85, 0xd5, 0x14, 0x84, 0xc2, 0x4c, 0x33, 0x40, 0x06, +0x40, 0x01, 0x30, 0x09, 0xf0, 0x86, 0xd5, 0x0d, 0x84, 0xe3, 0x4c, 0x33, 0xc0, 0x07, 0x40, 0x81, +0x30, 0x09, 0x14, 0x8f, 0x80, 0x08, 0xd5, 0x05, 0x41, 0xe0, 0x10, 0x16, 0x15, 0xef, 0x80, 0x03, +0x51, 0xce, 0x00, 0x01, 0x84, 0x65, 0x4d, 0xc1, 0xff, 0x59, 0xf1, 0x06, 0xf4, 0x04, 0x42, 0x12, +0x10, 0x75, 0xf1, 0x8f, 0x5c, 0xf0, 0xa7, 0x10, 0xe8, 0x38, 0x5c, 0xf0, 0x80, 0x65, 0xe8, 0x04, +0x50, 0x04, 0x80, 0x09, 0xd5, 0x2d, 0x5c, 0xf0, 0x80, 0x9f, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x08, +0xd5, 0x27, 0x5c, 0xf0, 0x80, 0xfc, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x07, 0xd5, 0x21, 0x5c, 0xf0, +0x81, 0x8f, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x06, 0xd5, 0x1b, 0x5c, 0xf0, 0x82, 0x77, 0xe8, 0x04, +0x50, 0x04, 0x80, 0x05, 0xd5, 0x15, 0x5c, 0xf0, 0x83, 0xe9, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x04, +0xd5, 0x0f, 0x5c, 0xf0, 0x86, 0x31, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x03, 0xd5, 0x09, 0x5c, 0xf0, +0x89, 0xd0, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x02, 0xd5, 0x03, 0x50, 0x04, 0x80, 0x01, 0x54, 0x90, +0x00, 0xff, 0xe7, 0x2b, 0x4e, 0xf3, 0xfe, 0xc5, 0xf0, 0x04, 0xf6, 0x06, 0x44, 0x80, 0x00, 0x64, +0x42, 0x60, 0x00, 0x75, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x83, 0x50, 0x42, 0x03, 0x20, 0x24, +0x4b, 0xe0, 0x1c, 0x01, 0xf1, 0x08, 0xf2, 0x05, 0x80, 0xc0, 0x42, 0x11, 0x08, 0x75, 0x42, 0x00, +0xa0, 0x24, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x53, 0x7c, 0x18, 0x80, 0x60, 0x5c, 0xf2, 0x81, 0x91, +0xe8, 0x48, 0x9b, 0x30, 0x5e, 0xf2, 0x00, 0x71, 0xe8, 0x44, 0x5e, 0xf2, 0x7f, 0x90, 0xe9, 0x41, +0xf0, 0x04, 0x51, 0xe0, 0x00, 0x20, 0x5c, 0xff, 0x00, 0x41, 0xe8, 0x3b, 0xf1, 0x05, 0x50, 0x40, +0x80, 0x20, 0x5c, 0xf2, 0x00, 0x41, 0xe8, 0x35, 0x44, 0x70, 0x03, 0xe8, 0x42, 0x21, 0x9c, 0x24, +0x04, 0x8f, 0x80, 0x03, 0x44, 0x50, 0x59, 0x88, 0x42, 0x80, 0x80, 0x75, 0x40, 0x01, 0x18, 0x96, +0x42, 0x84, 0x14, 0x24, 0x42, 0x41, 0x98, 0x24, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x83, 0x08, +0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x83, 0x04, 0x51, 0xe0, 0x7c, 0x18, 0x40, 0x24, 0x10, 0xd6, +0x50, 0x70, 0x03, 0xe8, 0x40, 0x6f, 0x20, 0x08, 0x40, 0x43, 0x1c, 0xf6, 0x50, 0x11, 0x00, 0x0c, +0xb6, 0x45, 0xb6, 0x83, 0xe6, 0x39, 0xe9, 0x03, 0x84, 0x20, 0xb6, 0x25, 0x9c, 0xe7, 0xe6, 0x6f, +0xe9, 0x15, 0x84, 0x00, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x04, 0xb6, 0x06, 0xd5, 0x0e, +0x87, 0xc0, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x83, 0x08, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, +0x03, 0x04, 0x15, 0xe2, 0x80, 0x00, 0x15, 0xe2, 0x00, 0x00, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x03, 0x6c, 0x84, 0x23, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x50, 0x2f, 0x80, 0x3c, 0x44, 0x10, +0x00, 0x9f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf5, 0x0f, +0x44, 0x00, 0x00, 0x9f, 0x58, 0x12, 0x80, 0x07, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x37, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x04, 0xb4, 0x80, 0x44, 0x00, +0x00, 0x9f, 0x54, 0x12, 0x00, 0x3f, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x35, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x26, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0x08, 0xb4, 0x61, 0x44, 0x00, 0x00, 0x9f, +0x54, 0x11, 0x80, 0x3f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x9f, 0x84, 0x20, 0xdd, 0x26, 0xf2, 0x02, 0x4e, 0x23, 0x00, 0x9e, 0x46, 0x60, 0x04, 0x10, +0x47, 0xe0, 0x00, 0x92, 0x58, 0x63, 0x05, 0x0c, 0x59, 0xef, 0x00, 0x18, 0x15, 0xe3, 0x00, 0x00, +0xf1, 0x02, 0x92, 0x00, 0x84, 0x47, 0x9c, 0x49, 0x4c, 0x11, 0x7f, 0xfd, 0x46, 0x30, 0x04, 0x10, +0x46, 0x10, 0x00, 0x92, 0x58, 0x31, 0x85, 0x0c, 0x58, 0x10, 0x80, 0x08, 0xb6, 0x23, 0x84, 0x00, +0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, 0x7f, 0xfd, 0x46, 0x00, 0x04, 0x10, 0x46, 0x50, +0x00, 0x92, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0xa0, 0x84, 0x00, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, +0x4c, 0x03, 0x7f, 0xfd, 0xf1, 0x10, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x03, 0x6c, 0x44, 0x00, +0x00, 0x17, 0xdd, 0x26, 0xf1, 0x11, 0x84, 0x04, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf4, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x3c, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0xec, 0xdd, 0x2f, 0xf3, 0x0f, 0x44, 0x00, 0x00, 0x15, 0x58, 0x21, 0x80, 0x01, +0xf2, 0x8f, 0x80, 0x22, 0xdd, 0x26, 0x84, 0x00, 0xd5, 0x0a, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x49, +0x4c, 0x1f, 0x7f, 0xfd, 0x9c, 0x01, 0x84, 0x2a, 0x4c, 0x00, 0x80, 0x04, 0x84, 0x20, 0xd5, 0xf6, +0xf3, 0x0f, 0x44, 0x00, 0x00, 0x15, 0x54, 0x21, 0x80, 0xfe, 0x80, 0x22, 0xf2, 0x8f, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x10, 0x58, 0x42, 0x05, 0x04, +0x84, 0x20, 0xb6, 0x24, 0x46, 0x50, 0x04, 0x10, 0xf6, 0x09, 0x58, 0x52, 0x85, 0x0c, 0xb6, 0xc5, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x64, 0xf0, 0x07, 0xb6, 0x04, 0x84, 0x04, 0xf2, 0x19, +0xdd, 0x26, 0xf2, 0x18, 0x44, 0x10, 0x00, 0x13, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x17, 0x44, 0x10, +0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x16, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x15, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, 0x44, 0x10, 0x00, 0x14, +0x84, 0x05, 0xdd, 0x26, 0xf2, 0x13, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x12, 0x84, 0x05, +0x84, 0x24, 0xdd, 0x26, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x96, 0x49, 0xe6, 0x24, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x61, 0xb4, 0x20, 0x84, 0xa5, +0xd1, 0x2c, 0xe4, 0x26, 0xe8, 0x09, 0x84, 0xa3, 0xd1, 0x17, 0xe4, 0x24, 0xe8, 0x1b, 0x84, 0x01, +0x4c, 0x10, 0x40, 0x55, 0xd5, 0x0b, 0x84, 0x47, 0x4c, 0x11, 0x00, 0x3b, 0xe0, 0x22, 0xe9, 0x26, +0x84, 0xa8, 0xd1, 0x3e, 0x84, 0xa9, 0xd1, 0x45, 0xd5, 0x49, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x88, 0xdc, 0xdd, 0x2f, 0xd5, 0x43, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0xc4, 0xdd, 0x2f, +0xd5, 0x3d, 0x9c, 0x44, 0x05, 0xe0, 0x80, 0x00, 0x54, 0x0f, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x08, +0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0xd5, 0x32, 0x9c, 0xc4, 0xb4, 0x43, 0x96, 0x14, 0x46, 0xf0, +0x00, 0x08, 0x58, 0xf7, 0x8f, 0x08, 0xdd, 0x2f, 0xd5, 0x29, 0x9c, 0x04, 0x05, 0xe0, 0x00, 0x00, +0xb4, 0x20, 0xb4, 0x80, 0x40, 0x50, 0xa0, 0x09, 0x54, 0x0f, 0x00, 0xff, 0x96, 0x68, 0x42, 0x22, +0x40, 0x0b, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, 0xd5, 0x17, 0x9c, 0x84, +0xb4, 0x02, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x8d, 0x2c, 0xdd, 0x2f, 0xd5, 0x0f, 0x9d, 0x04, +0xb4, 0x64, 0x96, 0x1c, 0x46, 0xf0, 0x00, 0x09, 0x58, 0xf7, 0x87, 0xc0, 0xdd, 0x2f, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xb0, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x20, 0x04, 0x10, 0x04, 0x61, +0x01, 0x05, 0x40, 0x03, 0x38, 0x08, 0x92, 0x1f, 0xc0, 0x14, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, +0x86, 0x91, 0x84, 0xa1, 0xdb, 0x0e, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x81, 0xa5, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x06, 0xa0, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, +0x47, 0xe0, 0x04, 0x10, 0x14, 0x6f, 0x01, 0x05, 0x04, 0x5f, 0x01, 0x05, 0xf5, 0x81, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xc4, 0x84, 0xa1, +0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x03, 0x3a, 0x84, 0x60, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x03, 0x3b, 0xaf, 0x60, 0x46, 0x60, 0x04, 0x00, 0xae, 0xc0, 0x58, 0x63, 0x02, 0x14, 0x05, 0xc3, +0x00, 0x00, 0x45, 0xef, 0xef, 0xff, 0x40, 0xae, 0x78, 0x02, 0xb7, 0x46, 0x46, 0x70, 0x04, 0x00, +0x58, 0x73, 0x84, 0x18, 0xb5, 0x27, 0x44, 0x6f, 0xff, 0x7f, 0x40, 0x84, 0x98, 0x02, 0xb7, 0x07, +0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x82, 0x58, 0xb4, 0xa3, 0x46, 0x7f, 0x0f, 0xff, 0x58, 0x73, +0x8f, 0xff, 0x47, 0xe0, 0xa0, 0x00, 0x54, 0xa0, 0x80, 0xff, 0x40, 0x12, 0x9c, 0x02, 0x40, 0x40, +0xf8, 0x04, 0x84, 0x05, 0xb6, 0x83, 0x4c, 0xa0, 0x41, 0x64, 0x47, 0xc0, 0x04, 0x10, 0x15, 0xcf, +0x80, 0x04, 0x47, 0xe0, 0x0c, 0x2d, 0x15, 0xef, 0x80, 0x01, 0x05, 0xef, 0x80, 0x04, 0x46, 0x00, +0x04, 0x10, 0x59, 0xef, 0x07, 0x20, 0x15, 0xef, 0x80, 0x04, 0x05, 0xef, 0x80, 0x01, 0x58, 0x00, +0x00, 0x80, 0x59, 0xef, 0x0f, 0xc0, 0x15, 0xef, 0x80, 0x01, 0x46, 0x10, 0x04, 0x10, 0x05, 0xe0, +0x00, 0x00, 0x58, 0x10, 0x80, 0xc0, 0x15, 0xef, 0x80, 0x0b, 0x46, 0x50, 0x04, 0x10, 0x05, 0xe0, +0x80, 0x00, 0x58, 0x52, 0x80, 0x04, 0x15, 0xef, 0x80, 0x0a, 0x46, 0x60, 0x04, 0x10, 0x05, 0xe2, +0x80, 0x00, 0x58, 0x63, 0x07, 0x08, 0x15, 0xef, 0x80, 0x09, 0x46, 0x90, 0x04, 0x10, 0x05, 0xe3, +0x00, 0x00, 0x58, 0x94, 0x80, 0x20, 0x15, 0xef, 0x80, 0x08, 0x46, 0x30, 0x04, 0x10, 0x05, 0xe4, +0x80, 0x00, 0x58, 0x31, 0x80, 0x78, 0x15, 0xef, 0x80, 0x07, 0x46, 0x4f, 0x02, 0x10, 0x05, 0xe1, +0x80, 0x00, 0x15, 0xef, 0x80, 0x06, 0x05, 0xef, 0x80, 0x04, 0x46, 0x7f, 0xf0, 0x00, 0x05, 0xef, +0x00, 0x00, 0x46, 0x80, 0x04, 0x10, 0x47, 0xc0, 0x18, 0x00, 0x15, 0xef, 0x80, 0x05, 0x58, 0x84, +0x00, 0x3c, 0xb6, 0x80, 0x44, 0x40, 0x00, 0x10, 0x44, 0x00, 0x00, 0xc8, 0x59, 0xce, 0x00, 0x80, +0xb6, 0xe1, 0xb6, 0x85, 0xb6, 0x06, 0x15, 0xc4, 0x00, 0x00, 0x47, 0xe0, 0x00, 0x0e, 0x59, 0xef, +0x02, 0x78, 0xf7, 0x01, 0x84, 0xc1, 0xb6, 0xe9, 0xb6, 0xde, 0xf2, 0x82, 0xf3, 0x83, 0x46, 0x70, +0x00, 0x04, 0x58, 0x73, 0x86, 0x2c, 0x80, 0x0a, 0xdd, 0x27, 0x46, 0x10, 0x0c, 0x2d, 0x58, 0x10, +0x8f, 0x80, 0xb6, 0x29, 0x46, 0x28, 0x00, 0x00, 0xf5, 0x03, 0xb6, 0x45, 0x46, 0x00, 0x19, 0xc0, +0xf3, 0x04, 0x84, 0x84, 0x58, 0x00, 0x00, 0x80, 0xb6, 0x83, 0x46, 0x60, 0x19, 0xc0, 0xb6, 0x08, +0x58, 0x63, 0x00, 0x90, 0x80, 0x0a, 0xdd, 0x27, 0xb6, 0xc8, 0x84, 0x0a, 0xdd, 0x27, 0x46, 0x10, +0x19, 0x40, 0x58, 0x10, 0x80, 0x90, 0xb6, 0x28, 0x84, 0x0a, 0xdd, 0x27, 0x46, 0x20, 0x18, 0x40, +0x58, 0x21, 0x00, 0x90, 0xb6, 0x48, 0x84, 0x0a, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x00, 0xf2, 0x02, +0x58, 0x00, 0x00, 0x88, 0xb4, 0x20, 0xc2, 0x09, 0x46, 0x3f, 0xf0, 0x00, 0x40, 0x60, 0x8c, 0x02, +0x98, 0x96, 0x42, 0x81, 0x7c, 0x08, 0xb7, 0x00, 0x64, 0x00, 0x00, 0x00, 0x84, 0x00, 0x46, 0x40, +0x00, 0x0e, 0x58, 0x42, 0x03, 0x3a, 0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, 0x03, 0x3b, 0xae, 0x20, +0x46, 0x30, 0x04, 0x00, 0x10, 0x04, 0x00, 0x00, 0x58, 0x31, 0x82, 0x14, 0xb4, 0x23, 0x47, 0xe0, +0x04, 0x00, 0x58, 0x50, 0x90, 0x00, 0xb6, 0xa3, 0x59, 0xef, 0x04, 0x18, 0xb4, 0xde, 0x46, 0x80, +0x04, 0x10, 0x46, 0x70, 0x19, 0x40, 0x58, 0x84, 0x00, 0x3c, 0x58, 0x23, 0x00, 0x80, 0x58, 0x73, +0x80, 0x90, 0xb6, 0x5e, 0xb6, 0xe8, 0x44, 0x00, 0x08, 0x98, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, +0x86, 0x2c, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x40, 0x19, 0xc0, 0x58, 0x42, 0x00, 0x90, 0xb6, 0x88, +0x84, 0x0a, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x00, 0x19, 0x80, 0x46, 0x50, 0x04, 0x10, 0x46, 0x10, +0x0c, 0x0d, 0x58, 0x00, 0x00, 0x90, 0x58, 0x52, 0x80, 0x20, 0x58, 0x10, 0x8f, 0xc0, 0xb6, 0x08, +0x46, 0x80, 0x04, 0x00, 0xb6, 0x25, 0x58, 0x84, 0x00, 0x20, 0x84, 0xc0, 0xb4, 0xa8, 0x46, 0x30, +0x04, 0x00, 0xf5, 0x8d, 0xf2, 0x0d, 0x84, 0x04, 0x41, 0xe1, 0x0c, 0x02, 0x4f, 0xe3, 0x00, 0x0a, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x07, 0xd1, 0x4c, 0x60, 0x80, 0x04, 0x9d, 0xb1, 0xd5, 0xef, +0x46, 0x70, 0x04, 0x10, 0x46, 0x60, 0x0c, 0x0d, 0x58, 0x73, 0x80, 0x20, 0x58, 0x63, 0x0f, 0xc8, +0xb6, 0xc7, 0x46, 0x70, 0x04, 0x00, 0x58, 0x73, 0x80, 0x20, 0x84, 0xc0, 0x46, 0x80, 0x00, 0x04, +0x58, 0x84, 0x06, 0x2c, 0xb4, 0x67, 0x46, 0x20, 0x08, 0x00, 0xf3, 0x8d, 0x05, 0xef, 0x80, 0x0d, +0x84, 0x04, 0x40, 0x4f, 0x08, 0x02, 0xcc, 0x09, 0x4b, 0xe0, 0x20, 0x01, 0x44, 0x00, 0x0b, 0xb9, +0x4c, 0x60, 0x00, 0x04, 0x9d, 0xb1, 0xd5, 0xef, 0x46, 0x70, 0x04, 0x10, 0x58, 0x73, 0x80, 0x3c, +0x84, 0x20, 0xb6, 0x27, 0x46, 0x80, 0x04, 0x10, 0x05, 0xef, 0x80, 0x0b, 0x58, 0x84, 0x00, 0x80, +0x15, 0xe4, 0x00, 0x00, 0x46, 0x60, 0x04, 0x10, 0xf7, 0x0a, 0x58, 0x63, 0x00, 0xc0, 0xb6, 0xe6, +0x46, 0x50, 0x04, 0x10, 0xf6, 0x09, 0x58, 0x52, 0x80, 0x04, 0xb6, 0xc5, 0x46, 0x40, 0x04, 0x10, +0xf7, 0x08, 0x58, 0x42, 0x07, 0x08, 0xb6, 0xe4, 0x46, 0x30, 0x04, 0x10, 0x05, 0xef, 0x80, 0x07, +0x58, 0x31, 0x80, 0x20, 0x15, 0xe1, 0x80, 0x00, 0x46, 0x20, 0x04, 0x10, 0xf3, 0x06, 0x58, 0x21, +0x00, 0x78, 0xb6, 0x62, 0x46, 0x00, 0x04, 0x10, 0xf4, 0x05, 0x58, 0x00, 0x07, 0x20, 0x46, 0x50, +0x00, 0x0e, 0x58, 0x52, 0x82, 0x78, 0xb6, 0x80, 0xb6, 0x25, 0x48, 0x00, 0x01, 0x34, 0x51, 0xc5, +0x7f, 0xff, 0x54, 0x9e, 0x00, 0xff, 0xe7, 0x24, 0x4e, 0xf2, 0x01, 0x2d, 0x46, 0x40, 0x04, 0x00, +0x58, 0x42, 0x00, 0x64, 0x46, 0x60, 0x04, 0x00, 0xb4, 0xa4, 0x58, 0x63, 0x00, 0x38, 0x46, 0x31, +0x00, 0x00, 0xb4, 0x26, 0x44, 0x0f, 0xe0, 0x00, 0x40, 0x82, 0x8c, 0x02, 0x40, 0x40, 0x80, 0x02, +0x4e, 0x82, 0x00, 0x05, 0x58, 0x42, 0x00, 0x13, 0xd5, 0x03, 0x58, 0x42, 0x00, 0x27, 0x46, 0x80, +0x04, 0x00, 0x58, 0x84, 0x00, 0x38, 0xb6, 0x88, 0x46, 0x70, 0x04, 0x00, 0x58, 0x73, 0x82, 0x08, +0xb5, 0x07, 0x05, 0xc3, 0x80, 0x00, 0x45, 0xef, 0xef, 0x37, 0x40, 0x9e, 0x78, 0x02, 0xb7, 0x27, +0xe7, 0x43, 0xe9, 0x13, 0x46, 0x50, 0x04, 0x00, 0x58, 0x52, 0x80, 0x80, 0xb4, 0xc5, 0x44, 0x1f, +0xff, 0xef, 0x40, 0x33, 0x04, 0x02, 0xb6, 0x65, 0x84, 0x05, 0xf2, 0x82, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x2c, 0xdd, 0x2f, 0xf2, 0x02, 0x47, 0xc0, 0x04, 0x00, 0x46, 0x60, 0x04, 0x00, +0x59, 0xce, 0x00, 0xc0, 0x58, 0x63, 0x00, 0x80, 0xb5, 0x3c, 0xb4, 0xe6, 0x84, 0x3d, 0x40, 0x43, +0x84, 0x02, 0xb6, 0x86, 0x84, 0x05, 0xb4, 0xbc, 0x41, 0xe2, 0x84, 0x02, 0x15, 0xee, 0x00, 0x00, +0xf2, 0x82, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x2c, 0xdd, 0x2f, 0xb4, 0x46, 0x87, 0xde, +0x40, 0x31, 0x78, 0x02, 0xb6, 0x66, 0x46, 0x10, 0x04, 0x00, 0xb4, 0xfc, 0x58, 0x10, 0x82, 0x14, +0x40, 0x73, 0xf8, 0x02, 0xb6, 0xfc, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x81, 0x58, 0x21, 0x02, 0x58, +0x42, 0x02, 0x3c, 0x08, 0xb6, 0x01, 0x46, 0x6f, 0x0f, 0xff, 0xb4, 0xa2, 0x58, 0x63, 0x0f, 0xff, +0x47, 0xc0, 0xa0, 0x00, 0x40, 0x42, 0x98, 0x02, 0x40, 0x02, 0x70, 0x04, 0xb6, 0x02, 0x46, 0x30, +0x04, 0x00, 0xf2, 0x02, 0x58, 0x31, 0x80, 0x88, 0xb4, 0x83, 0xc2, 0x0c, 0x46, 0x7f, 0xf0, 0x00, +0x40, 0x62, 0x1c, 0x02, 0x47, 0xe8, 0x00, 0x00, 0x41, 0xc1, 0x18, 0x00, 0x40, 0x0e, 0x78, 0x04, +0xb6, 0x03, 0x47, 0xc0, 0x04, 0x00, 0x59, 0xce, 0x00, 0x80, 0xb4, 0x3c, 0x46, 0x50, 0x04, 0x00, +0x58, 0x30, 0x80, 0x40, 0xb6, 0x7c, 0x58, 0x52, 0x80, 0x04, 0xb4, 0xc5, 0x84, 0x1b, 0x40, 0x43, +0x00, 0x02, 0xb6, 0x85, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x80, 0x20, 0xb4, 0x23, 0x46, 0x00, +0x04, 0x00, 0x58, 0x50, 0x90, 0x00, 0xb6, 0xa3, 0x58, 0x00, 0x00, 0x3c, 0xb4, 0xdc, 0x46, 0x1f, +0x00, 0x00, 0x58, 0x43, 0x00, 0x20, 0xb6, 0x9c, 0xb4, 0x60, 0x84, 0xa3, 0x40, 0x31, 0x84, 0x02, +0x4c, 0xa2, 0x80, 0x0d, 0x87, 0x84, 0x4c, 0xae, 0x00, 0x06, 0x84, 0xa2, 0x4c, 0xa2, 0xc0, 0x0f, +0xd5, 0x09, 0x44, 0x70, 0xef, 0x01, 0x98, 0xdf, 0xd5, 0x0c, 0x45, 0xe0, 0xe3, 0x01, 0x88, 0x7e, +0xd5, 0x08, 0x44, 0x40, 0xc0, 0x01, 0x98, 0xdc, 0xd5, 0x04, 0x44, 0x60, 0x80, 0x01, 0x98, 0xde, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x80, 0x3c, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x83, 0x38, +0x84, 0x00, 0xb6, 0x61, 0xae, 0x28, 0xa6, 0xe8, 0xcb, 0x04, 0x64, 0x00, 0x00, 0x20, 0xd5, 0xfc, +0x44, 0x60, 0x03, 0xe8, 0x40, 0x21, 0x18, 0x77, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x82, 0x68, +0xb4, 0xc5, 0x46, 0x40, 0x04, 0x00, 0x58, 0x42, 0x02, 0x14, 0x47, 0xc0, 0x04, 0x00, 0x59, 0xce, +0x04, 0x18, 0x98, 0xd6, 0xb6, 0x65, 0xb4, 0x24, 0x58, 0x00, 0x90, 0x00, 0xb6, 0x04, 0xb4, 0xbc, +0x58, 0x22, 0x80, 0x80, 0xb6, 0x5c, 0xe7, 0x43, 0xe9, 0x09, 0x47, 0xc0, 0x04, 0x00, 0x59, 0xce, +0x00, 0x80, 0xb4, 0x9c, 0x58, 0x02, 0x00, 0x10, 0xb6, 0x1c, 0x47, 0xc0, 0x04, 0x00, 0x59, 0xce, +0x00, 0x80, 0xb4, 0x1c, 0x46, 0x20, 0x04, 0x00, 0x58, 0x10, 0x00, 0x02, 0xb6, 0x3c, 0x58, 0x21, +0x00, 0xc0, 0xb4, 0x7c, 0x46, 0x10, 0x04, 0x00, 0x58, 0x51, 0x80, 0x01, 0xb6, 0xbc, 0xb7, 0x22, +0x58, 0x10, 0x80, 0x20, 0xb4, 0x01, 0x44, 0x4f, 0xef, 0xff, 0x40, 0x30, 0x10, 0x02, 0xb6, 0x61, +0x46, 0x20, 0x04, 0x00, 0xb4, 0x9c, 0x46, 0x10, 0x04, 0x00, 0x44, 0x5f, 0xff, 0xdf, 0x58, 0x21, +0x00, 0x3c, 0x40, 0x02, 0x14, 0x02, 0x58, 0x10, 0x82, 0x08, 0x84, 0x60, 0xb6, 0x1c, 0xb6, 0x62, +0xb7, 0x01, 0x84, 0x60, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x3a, 0x46, 0x10, 0x00, 0x0e, +0x58, 0x10, 0x83, 0x3b, 0xae, 0xc0, 0x46, 0x40, 0x04, 0x00, 0xae, 0xc8, 0x58, 0x42, 0x00, 0x20, +0xb4, 0xa4, 0x58, 0x22, 0x80, 0x40, 0xb6, 0x44, 0xec, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x14, 0x84, 0xa0, +0xb4, 0xc0, 0xb6, 0xa0, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x86, 0x9d, 0x96, 0x48, 0xc3, 0x04, +0x44, 0x30, 0x80, 0x02, 0xd5, 0x03, 0x44, 0x30, 0x80, 0x06, 0xb6, 0x60, 0x46, 0x70, 0x04, 0x00, +0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x80, 0x28, 0xdd, 0x2f, 0x14, 0x63, 0x80, 0x85, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x86, 0x8c, 0x84, 0xa1, 0xd8, 0x2a, 0x84, 0xc0, 0xf6, 0x81, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0x64, 0x84, 0x24, 0x84, 0x4a, 0x80, 0x06, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x25, 0x44, 0x20, 0x00, 0x20, 0x80, 0x06, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x24, +0x40, 0x2f, 0x84, 0x00, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0xac, 0xdd, 0x2f, +0xf4, 0x01, 0x80, 0x06, 0x58, 0x32, 0x00, 0x80, 0xf3, 0x81, 0x80, 0x43, 0x84, 0x24, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xa0, 0xdd, 0x2f, 0xec, 0x0c, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x17, 0x86, 0x8c, 0xc1, 0x1a, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x85, 0xd8, +0x84, 0xa1, 0xd3, 0x14, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x81, 0xa5, 0x44, 0x00, 0x03, 0xe8, +0x42, 0x50, 0x80, 0x24, 0x45, 0xe1, 0x73, 0x16, 0x84, 0x00, 0x40, 0x2f, 0x14, 0x01, 0x84, 0x21, +0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x85, 0xf0, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x34, 0x96, 0x00, +0x96, 0x48, 0x4c, 0x01, 0x40, 0x41, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x86, 0x91, 0xc8, 0x06, +0x46, 0x10, 0x04, 0x11, 0x04, 0x00, 0x80, 0x49, 0xd5, 0x36, 0x84, 0x81, 0x4c, 0x02, 0x40, 0x34, +0x4c, 0x10, 0x00, 0x30, 0x84, 0xa2, 0xd9, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x12, 0x84, 0xa3, +0xd1, 0x0e, 0x84, 0x04, 0x4c, 0x10, 0x00, 0x0c, 0x56, 0x10, 0x80, 0x05, 0x44, 0x20, 0x15, 0x7c, +0x84, 0x60, 0x40, 0x01, 0x84, 0x1b, 0x40, 0x01, 0x04, 0x1a, 0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, 0x81, 0xa5, 0x44, 0x20, 0x03, 0xe8, 0x42, 0x51, 0x88, 0x24, +0x45, 0xe1, 0x73, 0x18, 0x40, 0x4f, 0x14, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x86, 0x90, +0x9a, 0xa0, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x85, 0xf0, 0xdd, 0x2f, 0xd5, 0x03, +0x84, 0x02, 0xd5, 0xe7, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x96, 0x49, 0xe6, 0x28, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xc0, 0x80, 0x60, +0xa2, 0x99, 0x44, 0x40, 0x00, 0x30, 0xb4, 0x23, 0x4c, 0x22, 0x40, 0x06, 0x80, 0x02, 0x96, 0x48, +0x84, 0x40, 0xd5, 0x4b, 0x44, 0x50, 0x00, 0x31, 0xda, 0x0b, 0x46, 0x00, 0x04, 0x00, 0x04, 0x30, +0x00, 0x20, 0x58, 0x21, 0x80, 0x13, 0x14, 0x20, 0x00, 0x20, 0x48, 0x00, 0x00, 0xa7, 0x9d, 0x62, +0xda, 0x42, 0x84, 0x81, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x47, 0x83, 0x39, 0x50, 0x80, 0x00, 0x0c, +0x50, 0x90, 0x00, 0x08, 0x84, 0xe1, 0xb4, 0x89, 0xb4, 0x68, 0x4c, 0x13, 0x80, 0x9c, 0x84, 0xa2, +0xd9, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x13, 0x84, 0x03, 0x4c, 0x10, 0x00, 0x0f, 0x84, 0x44, +0x4c, 0x11, 0x00, 0x0c, 0x56, 0x60, 0x80, 0x05, 0x44, 0x70, 0x15, 0x7c, 0x85, 0x00, 0x40, 0x04, +0x18, 0x1b, 0x40, 0x03, 0x98, 0x1a, 0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x46, 0x80, 0x04, 0x11, +0x04, 0x24, 0x00, 0x49, 0x44, 0x70, 0x03, 0xe8, 0x43, 0xe1, 0x9c, 0x24, 0x95, 0x56, 0x50, 0x92, +0xd1, 0x20, 0x50, 0x3f, 0x7c, 0x18, 0x42, 0x91, 0x90, 0x73, 0x40, 0x24, 0x80, 0x01, 0x4e, 0x27, +0x00, 0x6d, 0x96, 0x48, 0x44, 0x00, 0x00, 0x32, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x85, 0xf0, +0xdd, 0x2f, 0xd5, 0x63, 0x44, 0x10, 0x00, 0x33, 0x4c, 0x20, 0xc0, 0x08, 0x84, 0x80, 0x46, 0xf0, +0x00, 0x0e, 0x10, 0x47, 0x83, 0x39, 0xd5, 0x59, 0x9d, 0x49, 0xda, 0x3d, 0x50, 0x70, 0x00, 0x0c, +0x50, 0x50, 0x00, 0x08, 0x50, 0x20, 0x00, 0x10, 0x51, 0xe0, 0x00, 0x14, 0xb5, 0x23, 0xb5, 0x05, +0xb4, 0x67, 0xb4, 0x82, 0xb4, 0xfe, 0xe6, 0xe2, 0xe9, 0x02, 0xd5, 0x04, 0x84, 0x21, 0x4c, 0x70, +0x80, 0x05, 0x84, 0xa0, 0x80, 0xe5, 0xd5, 0x0f, 0x8c, 0x18, 0xb4, 0xa0, 0x5c, 0xf2, 0x80, 0x3d, +0xe9, 0x04, 0x44, 0x50, 0x00, 0x3c, 0xd5, 0x07, 0x5d, 0xe2, 0x80, 0x14, 0x44, 0x60, 0x00, 0x14, +0x40, 0x53, 0x78, 0x1b, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x06, 0x8c, 0x54, 0x94, 0x80, 0xff, +0xa9, 0x72, 0x84, 0xa1, 0xaf, 0x70, 0xaf, 0xf5, 0x10, 0x93, 0x00, 0x04, 0x14, 0x83, 0x00, 0x03, +0x80, 0x29, 0x80, 0x48, 0x44, 0x00, 0x00, 0x34, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x86, 0xe4, +0xdd, 0x2f, 0xd5, 0x1b, 0x44, 0x50, 0x00, 0x35, 0xd2, 0x02, 0xd5, 0x17, 0x85, 0x00, 0x46, 0xf0, +0x00, 0x0b, 0x10, 0x87, 0x86, 0x6b, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x87, 0x86, 0x90, 0x46, 0xf0, +0x00, 0x0e, 0x10, 0x87, 0x86, 0x8c, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0xa0, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x84, 0x02, 0x48, 0xff, 0xff, 0x7c, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x81, 0x0a, 0x54, 0x70, 0x80, 0x02, 0xc7, 0x04, 0x42, 0x10, 0x80, 0x09, 0x84, 0xe1, +0xf0, 0x01, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x74, 0x14, 0x13, 0x00, 0x2d, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xc7, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8b, 0x18, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x03, 0x74, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, 0x04, 0x73, 0x00, 0x2d, +0xf0, 0x01, 0x97, 0xfc, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xc7, 0x07, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8b, 0x9c, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, +0x03, 0x74, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, +0x04, 0x33, 0x00, 0x2d, 0xf0, 0x01, 0x84, 0x40, 0xb6, 0x7f, 0x14, 0x23, 0x00, 0x2d, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xb4, 0x3f, 0x96, 0x0c, 0xc0, 0x07, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8b, 0x9c, 0xdd, 0x2f, 0xb4, 0xbf, 0x54, 0x42, 0x80, 0x02, +0xc4, 0x0a, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8b, 0x18, 0xdd, 0x2f, 0xb4, 0x1f, 0x41, 0xe0, 0x3c, 0x08, 0x41, 0xef, 0x7c, 0x09, 0x4f, 0xe2, +0x00, 0x0b, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8c, 0xf4, 0xdd, 0x2f, 0xb4, 0x7f, 0x40, 0x21, 0xb8, 0x08, 0x92, 0x5f, 0xc2, 0x0a, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8c, 0x10, 0xdd, 0x2f, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x44, 0x00, +0x02, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0xcc, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x00, +0xb4, 0x43, 0x44, 0x50, 0x76, 0x10, 0x40, 0x01, 0x40, 0x09, 0xd8, 0x07, 0x80, 0xe3, 0x04, 0x53, +0x80, 0x41, 0x42, 0x42, 0xd0, 0x0b, 0xc4, 0x23, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x87, 0x86, 0x63, +0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x07, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x81, 0xe4, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x85, 0xc8, 0xc8, 0x12, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, +0x82, 0x7c, 0x84, 0xa1, 0x4d, 0xe2, 0xc0, 0x0c, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x85, 0x1c, +0x80, 0x40, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x85, 0xf0, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0x0b, +0x00, 0x01, 0x06, 0x6b, 0x84, 0xa1, 0xd8, 0x11, 0x84, 0xa0, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, +0x81, 0xa5, 0x10, 0x51, 0x06, 0x6b, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x06, 0xa0, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x64, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x89, 0xb4, 0xdd, 0x2f, 0x46, 0xa0, 0x00, 0x00, +0x58, 0xa5, 0x03, 0x24, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8b, 0x00, 0xdd, 0x2f, 0x46, 0x90, +0x00, 0x02, 0x58, 0x94, 0x89, 0x10, 0x46, 0x70, 0x00, 0x00, 0x58, 0x73, 0x83, 0x68, 0x46, 0x80, +0x00, 0x02, 0x58, 0x84, 0x00, 0xac, 0xd5, 0x20, 0x4b, 0xe0, 0x28, 0x01, 0x00, 0x10, 0x00, 0x14, +0x80, 0xc0, 0xc9, 0x0f, 0x80, 0x20, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x74, 0x4b, 0xe0, +0x20, 0x01, 0xc8, 0x12, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x64, 0xd5, 0x0a, +0x84, 0xa1, 0xd9, 0x0a, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x03, 0x54, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x81, 0x0d, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0x2c, 0xca, 0xd9, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xcf, +0x44, 0x30, 0x03, 0xe8, 0x40, 0x20, 0x0c, 0x36, 0xc9, 0x06, 0x46, 0x40, 0x04, 0x00, 0x9d, 0x51, +0x14, 0x52, 0x00, 0x8e, 0x46, 0x10, 0x00, 0x0e, 0x51, 0xe0, 0x00, 0x01, 0x15, 0xe0, 0x80, 0xcf, +0x5e, 0xf0, 0x13, 0x89, 0xe9, 0x04, 0x84, 0x40, 0x14, 0x20, 0x80, 0xcf, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x81, 0x0a, 0xc9, 0x08, 0x44, 0x00, 0x02, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8e, 0x10, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x4e, 0x00, 0x00, 0x58, 0x49, 0x00, 0x00, +0x94, 0x44, 0x00, 0x00, 0x64, 0x48, 0x00, 0x00, 0x94, 0x44, 0x00, 0x00, 0x60, 0x46, 0x00, 0x00, +0xc4, 0x4c, 0x00, 0x00, 0x94, 0x44, 0x00, 0x00, 0x80, 0x4e, 0x00, 0x00, 0x28, 0x48, 0x00, 0x00, +0x60, 0x4e, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x94, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x99, 0x99, 0x09, 0x50, 0x02, 0x46, 0x44, 0x0a, 0x50, 0x03, 0xec, 0xee, 0x0a, 0x50, 0x04, +0x99, 0x99, 0x0b, 0x50, 0x05, 0x46, 0x44, 0x08, 0x51, 0x06, 0xec, 0xee, 0x08, 0x51, 0x07, 0x99, +0x99, 0x09, 0x51, 0x08, 0x46, 0x44, 0x0a, 0x51, 0x09, 0xec, 0xee, 0x0a, 0x51, 0x0a, 0x99, 0x99, +0x0b, 0x51, 0x0b, 0x46, 0x44, 0x08, 0x52, 0x0c, 0xec, 0xee, 0x08, 0x52, 0x0d, 0x99, 0x99, 0x09, +0x52, 0x0e, 0x33, 0x33, 0x0b, 0x52, 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, +0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x30, 0x34, 0x38, +0x3c, 0x40, 0x44, 0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, 0x00, 0x24, 0x25, 0x26, 0x27, +0x28, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, +0x16, 0x14, 0x12, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x14, 0x18, 0x1c, 0x00, 0x00, +0x20, 0x21, 0x22, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0f, 0xac, 0x00, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x03, 0x00, +0x00, 0xf8, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x88, 0x8e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, +0x86, 0xdd, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, +0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x14, 0x01, 0x76, 0x01, 0x00, 0x01, 0x02, +0x03, 0x01, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x05, 0x0f, 0x0c, 0x00, +0x01, 0x07, 0x10, 0x02, 0x02, 0x00, 0x00, 0x00, 0x09, 0x02, 0x4a, 0x00, 0x01, 0x01, 0x00, 0xa0, +0x50, 0x09, 0x04, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x84, 0x02, 0x00, 0x02, +0x00, 0x07, 0x05, 0x85, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x08, 0x02, 0x00, 0x02, 0x00, 0x07, +0x05, 0x04, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x05, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x06, +0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x07, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x09, 0x02, 0x00, +0x02, 0x00, 0x09, 0x04, 0x01, 0x00, 0x05, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x81, 0x03, 0x40, +0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x02, 0x02, 0x00, 0x02, 0x00, +0x07, 0x05, 0x83, 0x01, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x01, 0x40, 0x00, 0x00, 0x04, 0x03, +0x09, 0x04, 0x12, 0x03, 0x4d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x61, 0x00, 0x54, 0x00, +0x65, 0x00, 0x6b, 0x00, 0x1c, 0x03, 0x38, 0x00, 0x30, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, +0x31, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x57, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x4e, 0x00, +0x08, 0x03, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x0c, 0x5d, 0x00, 0x00, 0x10, 0x5d, 0x00, 0x00, +0x14, 0x5d, 0x00, 0x00, 0x18, 0x5d, 0x00, 0x00, 0x1c, 0x5d, 0x00, 0x00, 0x20, 0x5d, 0x00, 0x00, +0x24, 0x5d, 0x00, 0x00, 0x28, 0x5d, 0x00, 0x00, 0x2c, 0x5d, 0x00, 0x00, 0x30, 0x5d, 0x00, 0x00, +0x34, 0x5d, 0x00, 0x00, 0x38, 0x5d, 0x00, 0x00, 0x3c, 0x5d, 0x00, 0x00, 0x40, 0x5d, 0x00, 0x00, +0x44, 0x5d, 0x00, 0x00, 0x48, 0x5d, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0xb1, 0x00, 0x00, 0x00, +0x40, 0x76, 0x00, 0x01, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7612_firmware.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7612_firmware.h new file mode 100644 index 000000000..17d698aa1 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7612_firmware.h @@ -0,0 +1,455 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7612_FirmwareImage[] = { +0x58, 0x19, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x32, 0x30, 0x31, 0x32, 0x31, 0x31, 0x31, 0x39, 0x32, 0x30, 0x35, 0x30, 0x5f, 0x5f, 0x5f, 0x5f, +0x46, 0x00, 0x00, 0x81, 0x58, 0x00, 0x07, 0x34, 0x4a, 0x00, 0x00, 0x00, 0x80, 0x9e, 0x46, 0x00, +0x01, 0x10, 0x58, 0x00, 0x00, 0x00, 0x46, 0x10, 0x01, 0x10, 0x58, 0x10, 0x80, 0x00, 0x46, 0x20, +0x01, 0x10, 0x58, 0x21, 0x02, 0xa8, 0x40, 0x31, 0x04, 0x01, 0x40, 0x00, 0x0c, 0x00, 0x3a, 0x10, +0x04, 0x1c, 0x3a, 0x11, 0x04, 0x3c, 0x50, 0x31, 0xff, 0xfc, 0x4e, 0x36, 0xff, 0xfa, 0x64, 0x00, +0x00, 0x09, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x00, 0x00, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, +0x00, 0x00, 0x4c, 0x01, 0x00, 0x08, 0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x01, 0x4c, 0x01, +0x7f, 0xfe, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0xa8, 0x46, 0x20, 0x01, 0x13, 0x58, 0x21, +0x0d, 0x44, 0x4c, 0x01, 0x00, 0x08, 0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x01, 0x4c, 0x01, +0x7f, 0xfe, 0x83, 0xc4, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x87, 0x80, +0xf3, 0x85, 0xf0, 0x83, 0xf2, 0x84, 0x15, 0xcf, 0x80, 0x02, 0x81, 0x3c, 0x80, 0xdc, 0x50, 0x8f, +0x80, 0x14, 0x81, 0x41, 0x48, 0x00, 0x01, 0x5c, 0x84, 0x22, 0x4c, 0x60, 0x80, 0x44, 0xe6, 0xc3, +0xe8, 0x06, 0xc6, 0x0c, 0x84, 0x41, 0x4c, 0x61, 0x41, 0x4d, 0xd5, 0x17, 0x84, 0x63, 0x4c, 0x61, +0x80, 0x4c, 0x84, 0x04, 0x4c, 0x60, 0x41, 0x46, 0xd5, 0x65, 0x44, 0x10, 0x00, 0x25, 0x4c, 0x00, +0x80, 0x0a, 0xf2, 0x04, 0x80, 0x28, 0xdd, 0x22, 0xf3, 0x02, 0x9c, 0xd9, 0xf3, 0x82, 0x48, 0x00, +0x01, 0x3c, 0xf0, 0x03, 0x9c, 0x01, 0xf0, 0x83, 0xf1, 0x03, 0x44, 0x20, 0x00, 0x25, 0x20, 0x00, +0x80, 0x00, 0x4c, 0x01, 0x40, 0x0b, 0xf3, 0x04, 0x80, 0x28, 0xdd, 0x23, 0xf0, 0x02, 0x87, 0x80, +0x9c, 0x01, 0xf0, 0x82, 0x48, 0x00, 0x01, 0x27, 0x44, 0x10, 0x00, 0x2d, 0x4c, 0x00, 0xc0, 0x0b, +0x54, 0x04, 0x80, 0x01, 0x4e, 0x03, 0x01, 0x1e, 0x58, 0x94, 0x80, 0x01, 0x84, 0xc1, 0x48, 0x00, +0x01, 0x1c, 0x9c, 0x8b, 0x4c, 0x01, 0x40, 0x07, 0xf3, 0x03, 0x58, 0x94, 0x80, 0x40, 0x9c, 0xd9, +0xf3, 0x83, 0xf1, 0x03, 0x20, 0x00, 0x80, 0x00, 0x50, 0x10, 0x7f, 0xd0, 0x96, 0x48, 0xe6, 0x2a, +0xe8, 0x0b, 0x84, 0x2a, 0x43, 0xce, 0x04, 0x24, 0x84, 0xc2, 0x51, 0xce, 0x7f, 0xd0, 0x41, 0xce, +0x00, 0x00, 0x48, 0x00, 0x01, 0x02, 0xf2, 0x03, 0x44, 0x30, 0x00, 0x46, 0x20, 0x01, 0x00, 0x00, +0x4c, 0x01, 0xc0, 0x05, 0x58, 0x94, 0x80, 0x80, 0xd5, 0x12, 0x44, 0x10, 0x00, 0x4e, 0x4c, 0x00, +0xc0, 0x03, 0xd5, 0x0d, 0x44, 0x20, 0x00, 0x6c, 0x4c, 0x01, 0x40, 0x05, 0x58, 0x94, 0x80, 0x08, +0xd5, 0x06, 0x9e, 0xd4, 0x4c, 0x01, 0xc0, 0x07, 0x58, 0x94, 0x80, 0x10, 0x84, 0xc3, 0x48, 0x00, +0x00, 0xe4, 0xf1, 0x03, 0x44, 0x20, 0x00, 0x6e, 0x20, 0x00, 0x80, 0x00, 0x84, 0x20, 0x10, 0x1f, +0x80, 0x27, 0x4c, 0x01, 0x00, 0x30, 0x5e, 0xf0, 0x00, 0x6f, 0xe8, 0x14, 0x44, 0x30, 0x00, 0x63, +0x4c, 0x01, 0x80, 0x52, 0x5e, 0xf0, 0x00, 0x64, 0xe8, 0x06, 0x44, 0x10, 0x00, 0x58, 0x4c, 0x00, +0xc0, 0xc9, 0xd5, 0x1e, 0x8e, 0x4a, 0x4c, 0x01, 0x00, 0x21, 0x9c, 0xd5, 0x4c, 0x01, 0xc0, 0xc2, +0xd5, 0x1c, 0x9c, 0x55, 0x4c, 0x00, 0x80, 0x4b, 0x5e, 0xf0, 0x00, 0x74, 0xe8, 0x08, 0x9e, 0x8c, +0x4c, 0x01, 0x00, 0x0d, 0x9e, 0xcb, 0x4c, 0x01, 0xc0, 0xb5, 0xd5, 0x0c, 0x9c, 0x4a, 0x4c, 0x00, +0x80, 0x0f, 0x9c, 0x8b, 0x4c, 0x01, 0x40, 0xae, 0xd5, 0x05, 0x84, 0x88, 0xd5, 0x09, 0x58, 0x94, +0x80, 0x02, 0x44, 0x40, 0x00, 0x10, 0xd5, 0x04, 0x58, 0x94, 0x80, 0x04, 0x84, 0x8a, 0x54, 0x04, +0x80, 0x04, 0xb4, 0x6a, 0x8d, 0x44, 0xc0, 0x07, 0x4e, 0x34, 0x00, 0x06, 0x58, 0x94, 0x80, 0x20, +0x52, 0x31, 0x80, 0x00, 0x50, 0x5f, 0x80, 0x27, 0x54, 0x04, 0x80, 0x02, 0x40, 0x21, 0x90, 0x37, +0x9f, 0x69, 0x50, 0x20, 0x80, 0x30, 0xe6, 0x2a, 0xe8, 0x02, 0xd5, 0x08, 0x50, 0x20, 0x80, 0x57, +0x50, 0x10, 0x80, 0x37, 0xc0, 0x03, 0xae, 0x68, 0xd5, 0x02, 0xae, 0xa8, 0x40, 0x31, 0x90, 0x37, +0xcb, 0xee, 0xd5, 0x10, 0x00, 0x35, 0x00, 0x00, 0x10, 0x3f, 0x80, 0x26, 0x42, 0x94, 0x98, 0x09, +0x8d, 0x44, 0x50, 0x5f, 0x80, 0x26, 0x84, 0xe1, 0xd5, 0x22, 0xb4, 0xaa, 0x42, 0x94, 0x98, 0x09, +0x8d, 0x44, 0x80, 0x05, 0xf5, 0x81, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x86, 0x28, 0xdd, 0x2f, +0x54, 0x14, 0x80, 0x20, 0x80, 0xe0, 0xf5, 0x01, 0xc1, 0x02, 0x9d, 0xc1, 0x54, 0x14, 0x80, 0x60, +0x44, 0x20, 0x00, 0x60, 0x4c, 0x11, 0x40, 0x0c, 0xf5, 0x81, 0xf3, 0x04, 0x44, 0x00, 0x00, 0x2d, +0x80, 0x28, 0xdd, 0x23, 0xf0, 0x02, 0xf5, 0x01, 0x9c, 0x01, 0xf0, 0x82, 0x54, 0x14, 0x80, 0x01, +0xc1, 0x0c, 0xd5, 0x1d, 0xf2, 0x81, 0xf3, 0x04, 0x51, 0xce, 0x7f, 0xff, 0xdd, 0x23, 0xf0, 0x02, +0xf2, 0x01, 0x9c, 0x01, 0xf0, 0x82, 0xd5, 0x0c, 0x54, 0x24, 0x80, 0x40, 0x44, 0x10, 0x00, 0x20, +0x44, 0x60, 0x00, 0x30, 0x40, 0x60, 0x88, 0x1a, 0x80, 0x4a, 0x81, 0x49, 0x81, 0x25, 0x80, 0x06, +0x80, 0x28, 0xe2, 0xfc, 0xe9, 0xe8, 0x80, 0xa9, 0x81, 0x2a, 0x81, 0x42, 0x54, 0x94, 0x80, 0x60, +0x44, 0x10, 0x00, 0x20, 0x4c, 0x90, 0xc0, 0x14, 0xf5, 0x81, 0xf2, 0x04, 0x44, 0x00, 0x00, 0x2d, +0x80, 0x28, 0xdd, 0x22, 0xf3, 0x02, 0xf5, 0x01, 0x9c, 0xd9, 0xf3, 0x82, 0xd5, 0x08, 0xf2, 0x04, +0x8d, 0x21, 0xdd, 0x22, 0xf3, 0x02, 0x9c, 0xd9, 0xf3, 0x82, 0xd5, 0x02, 0x81, 0x25, 0x00, 0x64, +0x80, 0x00, 0x80, 0x28, 0x80, 0x06, 0xce, 0xf4, 0x40, 0xfe, 0x1c, 0x06, 0xe9, 0x03, 0x40, 0x6e, +0x1c, 0x01, 0x83, 0x86, 0xd5, 0x05, 0xf2, 0x04, 0x51, 0xce, 0x7f, 0xff, 0xdd, 0x22, 0x44, 0x00, +0x00, 0x20, 0x80, 0x28, 0x4f, 0xc3, 0xff, 0xf9, 0xf3, 0x02, 0x98, 0xde, 0xf3, 0x82, 0xd5, 0x02, +0x87, 0x80, 0x81, 0x3c, 0x80, 0xdc, 0xf0, 0x03, 0x9c, 0x01, 0xf0, 0x83, 0xf1, 0x03, 0x20, 0x00, +0x80, 0x00, 0x4e, 0x03, 0xfe, 0xa3, 0xf0, 0x02, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x20, 0x00, 0x80, 0x58, 0x21, 0x03, 0xb8, 0x84, 0x60, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8b, 0x14, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x1f, 0x94, 0x3c, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf8, 0x50, 0x1f, +0x80, 0x0c, 0xf1, 0x81, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xf8, 0xdd, 0x2f, 0xec, 0x08, +0x3b, 0xff, 0xfc, 0x84, 0xec, 0x14, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8e, 0x78, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x81, 0x47, 0x54, 0x21, 0x00, 0x20, +0xc2, 0xfc, 0x14, 0x00, 0x81, 0x41, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x84, 0x0a, +0x4c, 0x60, 0x40, 0x08, 0x84, 0x0d, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x44, 0xdd, 0x2f, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x44, 0xdd, 0x2f, 0x80, 0x06, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x10, 0x00, 0x10, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8e, 0x58, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0x3c, 0x46, 0x10, 0x01, 0xc2, 0x40, 0x00, 0x04, 0x37, 0x46, 0x10, 0x04, 0x00, +0x04, 0x90, 0x80, 0x88, 0x81, 0x01, 0x80, 0xe1, 0x80, 0xa1, 0x80, 0x81, 0x84, 0xc0, 0x58, 0x94, +0x80, 0x10, 0x80, 0x61, 0x14, 0x90, 0x80, 0x88, 0x14, 0x64, 0x01, 0x42, 0x80, 0x41, 0x14, 0x63, +0x81, 0x43, 0x14, 0x62, 0x81, 0x4d, 0x14, 0x02, 0x01, 0x4a, 0x84, 0x03, 0x14, 0x01, 0x81, 0x45, +0x44, 0x00, 0x00, 0xf7, 0x14, 0x01, 0x01, 0x44, 0x04, 0x00, 0x80, 0x08, 0x42, 0x00, 0x40, 0x08, +0x14, 0x00, 0x80, 0x08, 0x3a, 0x6f, 0xa4, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x81, 0x00, 0x80, 0x01, 0x58, 0x21, 0x00, 0x11, 0x14, 0x20, +0x81, 0x00, 0x04, 0x10, 0x01, 0x06, 0x46, 0x60, 0x01, 0x10, 0x58, 0x63, 0x02, 0xa8, 0x58, 0x10, +0x80, 0x80, 0x14, 0x10, 0x01, 0x06, 0x44, 0x50, 0x03, 0xe8, 0xb4, 0x06, 0x9c, 0x01, 0xb6, 0x06, +0xd8, 0x0c, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6d, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x81, 0xe4, 0xdd, 0x2f, 0x84, 0x00, 0xb6, 0x06, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x00, 0x00, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0x46, 0x10, 0x04, 0x00, 0x44, 0x20, 0x00, 0x4e, +0x80, 0x01, 0x14, 0x20, 0x81, 0x04, 0x44, 0x10, 0x00, 0x98, 0x14, 0x10, 0x01, 0x06, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x04, 0x60, 0x00, 0x78, 0x96, 0xb0, 0x96, 0x14, 0xc0, 0x07, +0x46, 0xf0, 0x01, 0x10, 0x04, 0x77, 0x80, 0xab, 0x84, 0xc1, 0xd5, 0x44, 0x54, 0x21, 0x00, 0x02, +0x96, 0x90, 0xc2, 0x07, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x77, 0x80, 0xac, 0x84, 0xc2, 0xd5, 0x3a, +0x40, 0x73, 0x40, 0x09, 0x97, 0xf8, 0x54, 0x03, 0x80, 0x02, 0x96, 0x00, 0xc0, 0x0b, 0x44, 0x10, +0x00, 0x6f, 0x84, 0x02, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x77, 0x80, 0xbc, 0x44, 0x62, 0x00, 0x00, +0xd5, 0x0d, 0x97, 0xfc, 0xc7, 0x11, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x77, 0x80, 0xbb, 0x80, 0x40, +0x44, 0x10, 0x00, 0x6f, 0x84, 0x02, 0x44, 0x61, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x81, 0xe4, 0xdd, 0x2f, 0xd5, 0x17, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x00, 0x0c, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0x80, 0x07, 0x80, 0x27, 0x46, 0x20, 0x01, 0x10, +0x58, 0x21, 0x00, 0x2c, 0x44, 0x30, 0x00, 0xd0, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, +0xdd, 0x2f, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x84, 0x20, 0x14, 0x60, 0x00, 0x78, +0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0x2c, 0x40, 0x00, 0x9c, 0x06, 0x44, 0x30, 0x00, 0xdb, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, +0x0a, 0xd4, 0xdd, 0x27, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0x2c, 0x80, 0xc0, 0x80, 0xe1, 0x5c, 0x00, +0x00, 0x20, 0x84, 0x20, 0x44, 0x30, 0x00, 0x9a, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, +0xdd, 0x2f, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0xac, 0x38, 0x70, 0x1a, 0x0a, 0x46, 0x10, +0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x04, 0x00, 0x80, 0x78, 0x84, 0x41, 0x40, 0x61, 0x18, 0x0c, +0x40, 0x03, 0x00, 0x04, 0x14, 0x00, 0x80, 0x78, 0x04, 0x00, 0x80, 0x7a, 0x40, 0x63, 0x00, 0x04, +0x14, 0x60, 0x80, 0x7a, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xf4, 0x84, 0x20, 0xf1, 0x81, 0x44, 0x10, 0x00, 0x40, 0x10, 0x1f, 0x80, 0x04, 0x10, 0x1f, +0x80, 0x07, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0xb4, 0x41, 0x50, 0x60, 0x00, 0x9c, +0x58, 0x01, 0x00, 0x02, 0xb6, 0x01, 0x80, 0x01, 0xf2, 0x01, 0x14, 0x20, 0x80, 0x71, 0x04, 0x70, +0x00, 0x71, 0x46, 0x80, 0x04, 0x10, 0x42, 0x13, 0x8c, 0x0b, 0xf7, 0x81, 0x58, 0x84, 0x08, 0x00, +0xc9, 0xf7, 0x42, 0x73, 0x84, 0x0b, 0xcf, 0xf4, 0x46, 0x90, 0x00, 0x80, 0x58, 0x94, 0x8b, 0x30, +0x50, 0x13, 0x7f, 0x64, 0x50, 0x23, 0x7f, 0xe4, 0x50, 0x04, 0x01, 0xa0, 0x84, 0x62, 0x4b, 0xe0, +0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0x84, 0x50, 0x23, 0x7f, 0xec, 0x58, 0x00, +0x09, 0xb0, 0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x46, 0x90, 0x00, 0x80, +0x58, 0x94, 0x8a, 0xe4, 0x50, 0x13, 0x7f, 0xa4, 0x50, 0x23, 0x7f, 0xf4, 0x58, 0x00, 0x09, 0x80, +0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0xc4, 0x9e, 0xb4, +0x84, 0x62, 0x58, 0x00, 0x09, 0x90, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x01, 0xaf, 0xf5, 0xaf, 0xf4, +0x10, 0x04, 0x01, 0xa8, 0x10, 0x04, 0x01, 0xb8, 0x14, 0x73, 0x00, 0x09, 0xaf, 0xf7, 0xaf, 0xf6, +0xa9, 0xf4, 0xa9, 0xf5, 0xa9, 0xf2, 0xa9, 0xf3, 0x50, 0x03, 0x00, 0x1c, 0x46, 0xf0, 0x00, 0x80, +0x58, 0xf7, 0x8f, 0x90, 0xdd, 0x2f, 0x04, 0x14, 0x00, 0x71, 0x58, 0x00, 0x80, 0x05, 0xf1, 0x81, +0x10, 0x0f, 0x80, 0x04, 0xf0, 0x01, 0x14, 0x04, 0x00, 0x71, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x10, 0x00, 0x2d, 0x42, 0x10, 0xc0, 0x08, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x10, 0x00, 0x2d, 0x42, 0x10, 0xc4, 0x08, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x10, 0x00, 0x2d, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x10, 0x00, 0x2d, 0x58, 0x10, 0x80, 0x02, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2b, 0x04, 0x30, 0x00, 0x2c, 0x9c, 0x92, 0x9a, 0x93, +0xe4, 0x42, 0xe9, 0x3e, 0x00, 0x30, 0x00, 0xa3, 0x9c, 0x9e, 0x94, 0x94, 0x98, 0x82, 0xa7, 0x17, +0x54, 0x42, 0x00, 0x80, 0xc4, 0x35, 0x50, 0x41, 0x80, 0x26, 0x38, 0x10, 0x12, 0x0a, 0x94, 0xdc, +0xa1, 0x0a, 0x98, 0xc3, 0xb6, 0x82, 0xa1, 0x4c, 0x14, 0x51, 0x80, 0x1b, 0xa5, 0x0e, 0xa4, 0xd3, +0x54, 0x42, 0x3f, 0xff, 0x92, 0x6e, 0x40, 0x31, 0xb8, 0x08, 0x40, 0x31, 0x90, 0x04, 0xac, 0xd3, +0xa7, 0x55, 0x00, 0x40, 0x80, 0x0f, 0xa6, 0xd7, 0x97, 0x24, 0x95, 0x26, 0x54, 0x31, 0x80, 0x3f, +0x40, 0x31, 0x90, 0x04, 0x54, 0x12, 0x80, 0x7f, 0xae, 0x55, 0xae, 0xd7, 0x46, 0x10, 0x04, 0x10, +0x00, 0x20, 0x00, 0xa3, 0x04, 0x30, 0x00, 0x2c, 0x9c, 0x91, 0x96, 0x94, 0x9c, 0xd9, 0x58, 0x10, +0x88, 0x00, 0x14, 0x30, 0x00, 0x2c, 0x10, 0x20, 0x00, 0xa3, 0x10, 0x20, 0x81, 0x98, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0x46, 0x80, 0x00, 0x80, 0x58, 0x84, +0x0d, 0x58, 0xd5, 0x22, 0xa6, 0x9f, 0x54, 0x21, 0x00, 0x80, 0xc2, 0x2f, 0x38, 0x23, 0x06, 0x02, +0x38, 0x93, 0x06, 0x0a, 0x80, 0x22, 0x00, 0x31, 0x00, 0x14, 0xcb, 0x02, 0xd5, 0x05, 0x46, 0x00, +0x01, 0x13, 0x58, 0x00, 0x0a, 0xb4, 0x9d, 0xfe, 0x95, 0xfc, 0x99, 0xf7, 0x4b, 0xe0, 0x20, 0x01, +0xa6, 0x3f, 0x44, 0x1f, 0xff, 0xc0, 0x40, 0x00, 0x04, 0x04, 0xae, 0x3f, 0x04, 0x03, 0x00, 0x2b, +0x9c, 0x01, 0x14, 0x03, 0x00, 0x2b, 0x04, 0x03, 0x00, 0x2b, 0x04, 0x23, 0x00, 0x2c, 0x97, 0xc4, +0x9c, 0xfe, 0x94, 0xdc, 0x9a, 0x90, 0x50, 0x13, 0x80, 0x26, 0x98, 0xf3, 0x46, 0x00, 0x01, 0x13, +0x58, 0x00, 0x0a, 0xc4, 0x4e, 0x26, 0xff, 0xd0, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0x46, 0x80, 0x00, 0x80, 0x58, 0x84, +0x0d, 0x58, 0xd5, 0x1a, 0xa6, 0x7f, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x27, 0x38, 0x13, 0x0a, 0x02, +0x38, 0x93, 0x0a, 0x0a, 0x4b, 0xe0, 0x20, 0x01, 0xa6, 0x7f, 0xa6, 0x3d, 0x44, 0x2f, 0xff, 0xc0, +0x58, 0x00, 0x00, 0x40, 0x40, 0x10, 0x88, 0x04, 0xae, 0x7f, 0xae, 0x3d, 0x04, 0x03, 0x00, 0x29, +0x9c, 0x01, 0x14, 0x03, 0x00, 0x29, 0x04, 0x13, 0x00, 0x29, 0x04, 0x33, 0x00, 0x2a, 0x97, 0xcc, +0x50, 0x23, 0x80, 0x24, 0x9d, 0xfc, 0x95, 0xfc, 0x9a, 0x59, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, +0x0a, 0xb4, 0x99, 0xf7, 0x4e, 0x16, 0xff, 0xd8, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, 0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, +0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, 0x00, 0xa1, 0x00, 0x52, 0x01, 0xbc, 0x9c, 0xba, +0x94, 0x94, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xb4, 0x50, 0xa3, 0x80, 0x22, 0x40, 0x6e, +0x08, 0x00, 0xd7, 0x58, 0xa6, 0x77, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x54, 0xa4, 0x73, 0xb6, 0x9f, +0x54, 0x90, 0xbf, 0xff, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8c, 0xf8, 0xdd, 0x2f, 0x81, 0x00, +0x94, 0x7c, 0x40, 0x3e, 0x04, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x10, 0x46, 0x00, +0x01, 0x10, 0x58, 0x00, 0x00, 0x4c, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, +0xb9, 0x2d, 0x42, 0x10, 0xc4, 0x08, 0xb9, 0xad, 0xd5, 0x35, 0x38, 0x2e, 0x2a, 0x02, 0x12, 0x91, +0x00, 0x06, 0x80, 0x22, 0x04, 0x31, 0x80, 0x0b, 0xa8, 0xd4, 0x84, 0x61, 0x10, 0x31, 0x00, 0x14, +0xb6, 0x9f, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8d, 0x58, 0xdd, 0x2f, 0x38, 0x8e, 0x2a, 0x0a, +0x84, 0x20, 0x80, 0x06, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x86, 0x18, +0xdd, 0x2f, 0xa6, 0x77, 0x04, 0x84, 0x00, 0x02, 0x58, 0x10, 0x80, 0x40, 0xae, 0x77, 0xa4, 0x73, +0xb7, 0x06, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x58, 0x10, 0x80, 0x64, 0xac, 0x73, 0xb4, 0x9f, +0x10, 0x72, 0x01, 0xb8, 0x00, 0x1e, 0x00, 0xa1, 0x9c, 0x49, 0x96, 0x4c, 0x10, 0x1e, 0x00, 0xa1, +0xd5, 0x9b, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x83, 0x80, 0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, +0x08, 0x00, 0x00, 0x7e, 0x00, 0xa0, 0x00, 0x52, 0x01, 0xac, 0x94, 0xbc, 0x46, 0x00, 0x01, 0x13, +0x58, 0x00, 0x0a, 0xc4, 0x50, 0xa3, 0x80, 0x20, 0x40, 0x6e, 0x08, 0x00, 0xd7, 0x58, 0xa6, 0x77, +0x54, 0x10, 0x80, 0x80, 0xc1, 0x54, 0xa4, 0x73, 0xb6, 0x9f, 0x54, 0x90, 0xbf, 0xff, 0x46, 0xf0, +0x00, 0x80, 0x58, 0xf7, 0x8c, 0xf8, 0xdd, 0x2f, 0x98, 0x7f, 0x9c, 0x49, 0x81, 0x00, 0x94, 0x4b, +0x40, 0x3e, 0x04, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x0f, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x00, 0x78, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0x44, 0x11, +0x00, 0x00, 0xb9, 0xad, 0xd5, 0x34, 0x38, 0x2e, 0x2a, 0x02, 0x12, 0x91, 0x00, 0x06, 0x80, 0x22, +0xa0, 0xd9, 0xa8, 0xd4, 0x84, 0x60, 0x10, 0x31, 0x00, 0x14, 0xb6, 0x9f, 0x46, 0xf0, 0x00, 0x80, +0x58, 0xf7, 0x8d, 0x58, 0xdd, 0x2f, 0x38, 0x8e, 0x2a, 0x0a, 0x84, 0x20, 0x80, 0x06, 0x44, 0x20, +0x00, 0x10, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x86, 0x18, 0xdd, 0x2f, 0xa6, 0x77, 0x04, 0x84, +0x00, 0x02, 0x58, 0x10, 0x80, 0x40, 0xae, 0x77, 0xa4, 0x73, 0xb7, 0x06, 0x92, 0x2e, 0x40, 0x10, +0xb8, 0x08, 0x58, 0x10, 0x88, 0x98, 0xac, 0x73, 0xb4, 0x9f, 0x10, 0x72, 0x01, 0xa8, 0x00, 0x1e, +0x00, 0xa0, 0x9c, 0x49, 0x96, 0x4c, 0x10, 0x1e, 0x00, 0xa0, 0xd5, 0x9c, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xb6, 0x20, 0xa8, 0xc1, 0x80, 0xc1, +0xa0, 0x43, 0x84, 0xe0, 0x81, 0x23, 0x81, 0x02, 0xa8, 0x42, 0x47, 0xc0, 0x00, 0x50, 0x59, 0xce, +0x06, 0x18, 0x81, 0x47, 0xd5, 0x0c, 0xdd, 0x3c, 0xa6, 0x37, 0x44, 0x1f, 0xff, 0xc0, 0x40, 0x00, +0x04, 0x04, 0xae, 0x37, 0x1c, 0xa4, 0x00, 0x01, 0x9d, 0xf9, 0x8c, 0xd0, 0x80, 0x06, 0x84, 0x20, +0x44, 0x20, 0x00, 0x10, 0xe2, 0xe9, 0xe9, 0xf0, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0xb6, 0x20, 0x83, 0x83, 0xa8, 0xc1, 0x46, 0x30, 0x04, 0x10, +0x58, 0x31, 0x89, 0xb0, 0x80, 0xc1, 0x40, 0x10, 0x0c, 0x03, 0xa0, 0xc3, 0x44, 0x40, 0x00, 0x64, +0xa8, 0xc2, 0x44, 0x50, 0x08, 0x98, 0x46, 0x30, 0x01, 0x13, 0x58, 0x31, 0x8a, 0xb4, 0x46, 0x00, +0x01, 0x13, 0x58, 0x00, 0x0a, 0xc4, 0x40, 0x82, 0x84, 0x1b, 0x40, 0x82, 0x04, 0x1a, 0x84, 0xe0, +0x40, 0x41, 0x84, 0x1a, 0x40, 0x40, 0x04, 0x1b, 0xf4, 0x83, 0x81, 0x42, 0x46, 0x40, 0x00, 0x50, +0x58, 0x42, 0x06, 0x18, 0x81, 0x27, 0x54, 0x34, 0x3f, 0xff, 0xd5, 0x23, 0xf3, 0x81, 0xf4, 0x82, +0xdd, 0x24, 0xf0, 0x03, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8c, 0xf8, 0xdd, 0x2f, 0xf3, 0x01, +0xf4, 0x02, 0xc0, 0x1d, 0x12, 0x80, 0x00, 0x06, 0x10, 0x90, 0x00, 0x0e, 0x10, 0x90, 0x00, 0x0f, +0xa6, 0x77, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x3f, 0xae, 0x77, 0xa4, 0x73, 0x92, 0x2e, 0x40, 0x10, +0xb8, 0x08, 0x40, 0x10, 0x8c, 0x04, 0xac, 0x73, 0xa0, 0x42, 0xaa, 0x74, 0x1c, 0x05, 0x00, 0x01, +0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0xe2, 0xfc, 0xe9, 0xd9, 0xec, 0x14, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x00, +0xa0, 0x44, 0x40, 0x00, 0xa0, 0x09, 0x96, 0x00, 0x54, 0x20, 0x00, 0x10, 0xc2, 0x06, 0x46, 0xf0, +0x01, 0x10, 0x04, 0x67, 0x80, 0xd7, 0xd5, 0x35, 0x54, 0x20, 0x00, 0x20, 0xc2, 0x06, 0x46, 0xf0, +0x01, 0x10, 0x04, 0x67, 0x80, 0xd8, 0xd5, 0x2d, 0x54, 0x20, 0x00, 0x40, 0xc2, 0x06, 0x46, 0xf0, +0x01, 0x10, 0x04, 0x67, 0x80, 0xd9, 0xd5, 0x25, 0x54, 0x00, 0x00, 0x80, 0xc0, 0x06, 0x46, 0xf0, +0x01, 0x10, 0x04, 0x67, 0x80, 0xda, 0xd5, 0x1d, 0x40, 0x60, 0xc0, 0x09, 0x97, 0xb0, 0x96, 0x34, +0xc0, 0x06, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x67, 0x80, 0xdb, 0xd5, 0x13, 0x54, 0x63, 0x00, 0x02, +0x97, 0xb0, 0xc6, 0x06, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x67, 0x80, 0xdc, 0xd5, 0x0a, 0x46, 0x00, +0x01, 0x10, 0x58, 0x00, 0x00, 0xa0, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, +0x84, 0x20, 0x40, 0x00, 0x98, 0x06, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xb8, 0x44, 0x30, +0x00, 0x71, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, 0xdd, 0x26, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x0a, 0xc8, +0x80, 0xe1, 0x80, 0xc0, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x20, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, +0x00, 0xb8, 0x44, 0x30, 0x00, 0x35, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0x20, 0x40, 0x00, 0x9c, 0x06, +0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xb8, 0x44, 0x30, 0x00, 0x36, 0x4b, 0xe0, 0x20, 0x01, +0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x03, 0x2c, 0x38, 0x70, 0x1a, 0x0a, 0x46, 0x10, 0x04, 0x00, +0x58, 0x10, 0x82, 0x00, 0xa0, 0x0d, 0x84, 0x41, 0x40, 0x61, 0x18, 0x0c, 0x40, 0x63, 0x00, 0x04, +0xa9, 0x8d, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x84, 0x20, +0x80, 0xc0, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xdc, 0x40, 0x00, 0x80, 0x06, 0x44, 0x30, +0x00, 0x8a, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8c, 0x00, 0xdd, 0x2f, 0xa0, 0x32, 0xc8, 0x02, 0xd5, 0x09, +0x9e, 0x01, 0xa8, 0x32, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8e, 0x8c, 0xdd, 0x2f, +0x80, 0xc0, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8c, 0x2c, 0xdd, 0x2f, 0x80, 0x06, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x84, 0x40, +0x80, 0xc0, 0x44, 0x30, 0x00, 0x6d, 0x40, 0x01, 0x00, 0x06, 0x80, 0xe1, 0x80, 0x22, 0x46, 0x20, +0x01, 0x10, 0x58, 0x21, 0x00, 0xdc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8c, 0x00, 0xdd, 0x2f, 0xa0, 0x72, +0x80, 0x06, 0x9c, 0x49, 0xa8, 0x72, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8f, 0x38, +0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8c, 0x2c, 0xdd, 0x2f, 0xec, 0x0c, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x01, 0x13, +0x58, 0x00, 0x0a, 0xb4, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8f, 0x90, 0xdd, 0x2f, 0x46, 0x70, +0x01, 0x10, 0x58, 0x73, 0x83, 0xac, 0x46, 0x60, 0x01, 0x13, 0x58, 0x63, 0x09, 0x94, 0x46, 0x80, +0x00, 0x80, 0x58, 0x84, 0x0d, 0x58, 0xa9, 0xf2, 0x80, 0x26, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, +0x0a, 0xb4, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x73, 0x80, 0x64, 0x46, 0x50, 0x01, 0x10, 0x58, 0x52, +0x86, 0x04, 0x8c, 0xd8, 0xdf, 0xf1, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xc4, 0x46, 0xf0, +0x00, 0x80, 0x58, 0xf7, 0x8f, 0x90, 0xdd, 0x2f, 0x46, 0x70, 0x01, 0x10, 0x58, 0x73, 0x86, 0x04, +0x46, 0x60, 0x01, 0x13, 0x58, 0x63, 0x0a, 0x24, 0x46, 0x80, 0x00, 0x80, 0x58, 0x84, 0x0d, 0x58, +0xa9, 0xf2, 0x80, 0x26, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xc4, 0x4b, 0xe0, 0x20, 0x01, +0x50, 0x73, 0x88, 0x98, 0x46, 0x50, 0x01, 0x13, 0x58, 0x52, 0x89, 0x94, 0x8c, 0xd8, 0xdf, 0xf1, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x20, 0x80, 0xc0, +0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xf8, 0x40, 0x00, 0x80, 0x06, 0x44, 0x30, 0x00, 0x7f, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, 0xa0, 0x31, 0xb4, 0x26, 0xb6, 0x20, +0xb4, 0x06, 0xa1, 0xb1, 0xa9, 0x81, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x84, 0xe0, 0x81, 0x00, 0x80, 0x27, 0x40, 0x03, 0x80, 0x06, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, +0x00, 0xf8, 0x44, 0x30, 0x00, 0x91, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, +0xb4, 0xc8, 0x4c, 0x64, 0x40, 0x04, 0x80, 0xc7, 0xd5, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x80, +0x58, 0xf7, 0x8e, 0x58, 0xdd, 0x2f, 0x80, 0x06, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0xbc, 0x84, 0xc0, 0x80, 0xe0, 0x81, 0x21, 0x81, 0x02, 0x46, 0xa0, 0x00, 0x02, +0x58, 0xa5, 0x0a, 0xc8, 0x40, 0x03, 0x00, 0x06, 0x80, 0x26, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, +0x00, 0xf8, 0x44, 0x30, 0x00, 0x49, 0x4b, 0xe0, 0x28, 0x01, 0x40, 0x03, 0x24, 0x06, 0x80, 0x26, +0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xf8, 0x44, 0x30, 0x00, 0x4a, 0x4b, 0xe0, 0x28, 0x01, +0x40, 0x03, 0x20, 0x06, 0x80, 0x26, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xf8, 0x44, 0x30, +0x00, 0x4b, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x93, 0x80, 0x01, 0xb7, 0x07, 0xb6, 0xe9, 0x14, 0x74, +0x00, 0x01, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x84, 0xc0, +0x80, 0xe0, 0x81, 0x01, 0x40, 0x03, 0x00, 0x06, 0x46, 0x90, 0x00, 0x02, 0x58, 0x94, 0x8a, 0xc8, +0x80, 0x26, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xf8, 0x44, 0x30, 0x00, 0x6f, 0x4b, 0xe0, +0x24, 0x01, 0x40, 0x03, 0x20, 0x06, 0x80, 0x26, 0x44, 0x30, 0x00, 0x70, 0x46, 0x20, 0x01, 0x10, +0x58, 0x21, 0x00, 0xf8, 0x4b, 0xe0, 0x24, 0x01, 0xa0, 0x79, 0x80, 0x08, 0x80, 0x47, 0x46, 0xf0, +0x00, 0x80, 0x58, 0xf7, 0x8e, 0xd0, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x20, 0x80, 0xc0, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x00, 0xf8, +0x40, 0x00, 0x80, 0x06, 0x44, 0x30, 0x00, 0x29, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, +0xdd, 0x2f, 0xa9, 0xb1, 0xb6, 0xc6, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x84, 0x20, 0x44, 0x20, 0x00, 0x14, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0d, 0x20, +0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x86, 0x18, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x96, 0x49, 0xe6, 0x24, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x11, 0xb4, 0x20, +0x84, 0xa1, 0xd9, 0x0d, 0x9c, 0x04, 0xb4, 0x20, 0x46, 0x00, 0x01, 0x10, 0x96, 0x48, 0x10, 0x10, +0x02, 0xa4, 0xe6, 0x22, 0xe9, 0x04, 0x84, 0x20, 0x10, 0x10, 0x02, 0xa4, 0x84, 0x00, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0x54, 0x20, 0x80, 0x03, 0x41, 0xc0, 0x88, 0x09, +0xc2, 0x03, 0x84, 0x01, 0xd5, 0x1f, 0x81, 0x00, 0xb4, 0xe0, 0x84, 0xc1, 0x46, 0x90, 0x00, 0x02, +0x58, 0x94, 0x8e, 0x10, 0xd5, 0x0e, 0xb5, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x01, 0x1c, 0x80, 0x2a, 0x4b, 0xe0, 0x24, 0x01, 0x1c, 0xa3, 0x80, 0x01, 0x9d, 0xb1, +0x80, 0x27, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0x10, 0x8d, 0x04, 0xe2, 0xdc, 0xe9, 0xec, +0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0xef, 0xf8, 0x46, 0x30, 0x04, 0x10, 0x54, 0x80, 0x00, 0x07, 0x58, 0x31, 0x85, 0x00, 0x40, 0x84, +0x3c, 0x08, 0x84, 0x80, 0x54, 0x70, 0x80, 0x7f, 0xb4, 0xa3, 0xf5, 0x81, 0x00, 0x5f, 0x80, 0x07, +0x54, 0x52, 0x80, 0x80, 0x97, 0x68, 0xcd, 0x3c, 0xf5, 0x81, 0x00, 0x9f, 0x80, 0x07, 0x44, 0xaf, +0xff, 0x80, 0x42, 0x94, 0x98, 0x09, 0x00, 0x6f, 0x80, 0x05, 0x40, 0x94, 0xa8, 0x04, 0x40, 0x63, +0x28, 0x02, 0x40, 0x63, 0x1c, 0x04, 0x10, 0x9f, 0x80, 0x07, 0x10, 0x6f, 0x80, 0x05, 0x44, 0x9c, +0x7f, 0xff, 0xf6, 0x01, 0x40, 0x63, 0x24, 0x02, 0x40, 0x63, 0x20, 0x04, 0xf6, 0x81, 0xb6, 0xc3, +0xb4, 0xc3, 0x9d, 0x69, 0xf6, 0x81, 0x00, 0x6f, 0x80, 0x07, 0x54, 0x63, 0x00, 0x80, 0xc6, 0x05, +0x44, 0xa0, 0x00, 0x64, 0x4c, 0x55, 0x7f, 0xf6, 0x00, 0x5f, 0x80, 0x07, 0x54, 0x52, 0x80, 0x80, +0xcd, 0x0f, 0x00, 0x5f, 0x80, 0x05, 0x54, 0x52, 0x80, 0x7f, 0xd9, 0x0a, 0xf5, 0x01, 0x92, 0xaf, +0x54, 0x52, 0x80, 0x07, 0xd8, 0x05, 0x00, 0x0f, 0x80, 0x04, 0xb6, 0x02, 0xd5, 0x05, 0x9d, 0x21, +0x44, 0x50, 0x00, 0x64, 0xdc, 0xba, 0x00, 0x0f, 0x80, 0x07, 0x54, 0x00, 0x00, 0x80, 0xc0, 0x0a, +0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0x28, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, +0xdd, 0x2f, 0xf0, 0x01, 0x92, 0x1f, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0x54, 0x70, 0x80, 0x07, 0x40, 0x90, 0x88, 0x09, +0xcf, 0x1e, 0x9d, 0x84, 0x46, 0x80, 0x00, 0x81, 0x58, 0x84, 0x00, 0x6c, 0xd5, 0x13, 0xb4, 0x20, +0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, 0x4e, 0x14, 0x00, 0x0a, 0x40, 0x00, 0xc0, 0x09, 0x96, 0x00, +0x96, 0x48, 0x84, 0x40, 0x4b, 0xe0, 0x20, 0x01, 0xc8, 0x0a, 0xb4, 0x00, 0x9d, 0xfa, 0xb6, 0x06, +0x8c, 0xc8, 0x9e, 0x34, 0xe2, 0xe9, 0xe9, 0xec, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x81, 0x41, +0xa4, 0x48, 0x84, 0xa8, 0xd9, 0x24, 0x80, 0x40, 0xa3, 0xd1, 0xb5, 0x02, 0x5c, 0xf4, 0x00, 0x40, +0xe8, 0x1e, 0x81, 0x20, 0x84, 0xc0, 0x47, 0xc0, 0x00, 0x02, 0x59, 0xce, 0x0e, 0x10, 0xd5, 0x06, +0xa2, 0xb9, 0x9d, 0xb1, 0xb6, 0x49, 0x80, 0x26, 0xdd, 0x3c, 0x40, 0x73, 0xa0, 0x08, 0x92, 0xe8, +0x8d, 0x24, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0x3c, 0xe2, 0xc8, 0xe9, 0xf2, 0x8d, 0x01, +0x40, 0x84, 0x08, 0x08, 0x12, 0x85, 0x00, 0x00, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x46, 0x60, +0x04, 0x10, 0x58, 0x63, 0x05, 0x00, 0xb4, 0x86, 0x81, 0x00, 0x80, 0xe1, 0x81, 0x22, 0x40, 0x02, +0x7c, 0x09, 0x84, 0x20, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x01, 0x4c, 0x44, 0x30, 0x00, 0x76, +0xf4, 0x81, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, 0x10, 0x9f, 0x80, 0x04, +0x44, 0x2c, 0x7f, 0xff, 0xf0, 0x01, 0x54, 0x14, 0x00, 0x07, 0x40, 0x10, 0xbc, 0x08, 0x40, 0x00, +0x08, 0x02, 0x40, 0x00, 0x04, 0x04, 0xf0, 0x81, 0x44, 0x3f, 0xff, 0x80, 0x00, 0x0f, 0x80, 0x07, +0x00, 0x1f, 0x80, 0x05, 0x54, 0x23, 0x80, 0x7f, 0x40, 0x10, 0x8c, 0x02, 0x58, 0x00, 0x00, 0x40, +0x40, 0x10, 0x88, 0x04, 0x54, 0x00, 0x00, 0x7f, 0x10, 0x0f, 0x80, 0x07, 0x10, 0x1f, 0x80, 0x05, +0x84, 0x00, 0xf2, 0x01, 0x80, 0x26, 0xb6, 0x46, 0x00, 0x2f, 0x80, 0x07, 0x40, 0x21, 0x0c, 0x04, +0x10, 0x2f, 0x80, 0x07, 0xf3, 0x01, 0xb6, 0x66, 0xb4, 0x41, 0x9c, 0x01, 0xf2, 0x81, 0x00, 0x2f, +0x80, 0x07, 0x54, 0x21, 0x00, 0x80, 0xc2, 0x04, 0x44, 0x50, 0x00, 0x64, 0xd8, 0xf6, 0xf6, 0x01, +0x84, 0x20, 0x92, 0xdf, 0x80, 0x06, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x01, 0x4c, 0x44, 0x30, +0x00, 0x85, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0xc8, 0xdd, 0x2f, 0x80, 0x06, 0xec, 0x0c, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x96, 0x49, +0x54, 0x70, 0x80, 0x07, 0x40, 0x90, 0x88, 0x09, 0xcf, 0x20, 0x9d, 0x84, 0x46, 0x80, 0x00, 0x81, +0x58, 0x84, 0x01, 0xf8, 0xd5, 0x15, 0xb4, 0x20, 0x9d, 0xfa, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, +0x4e, 0x14, 0x00, 0x0c, 0x40, 0x00, 0xc0, 0x09, 0xb4, 0x46, 0x96, 0x48, 0x96, 0x00, 0x4b, 0xe0, +0x20, 0x01, 0x84, 0xa1, 0xd0, 0x04, 0xd5, 0x09, 0xb4, 0x26, 0xb6, 0x20, 0x8c, 0xc8, 0x9e, 0x34, +0xe2, 0xe9, 0xe9, 0xea, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x85, 0x0c, 0x96, 0x49, 0x40, 0x20, +0xa1, 0x17, 0x92, 0x22, 0xf1, 0x81, 0x4e, 0x83, 0x00, 0x41, 0x50, 0x70, 0x00, 0x08, 0x9d, 0x84, +0x47, 0xc0, 0x00, 0x81, 0x59, 0xce, 0x01, 0xf8, 0xd5, 0x32, 0xb4, 0x20, 0x8d, 0x03, 0x40, 0x00, +0xa0, 0x08, 0x92, 0x08, 0x4e, 0x14, 0x00, 0x20, 0x40, 0x90, 0xc0, 0x09, 0x54, 0x94, 0x80, 0xff, +0x54, 0xa0, 0x80, 0xff, 0x80, 0x2a, 0x84, 0x40, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, +0x80, 0x6c, 0xdd, 0x2f, 0x80, 0x40, 0x80, 0x2a, 0x80, 0x09, 0xca, 0x1f, 0xb4, 0x66, 0xb4, 0x82, +0x40, 0x21, 0x8c, 0x05, 0xb4, 0x67, 0x40, 0x21, 0x10, 0x02, 0x40, 0x21, 0x0c, 0x04, 0xdd, 0x3c, +0xc0, 0x0c, 0xd5, 0x13, 0xb4, 0x60, 0xb4, 0x26, 0xb4, 0x47, 0x40, 0x10, 0x84, 0x05, 0x40, 0x11, +0x84, 0x02, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, 0x8c, 0xcc, 0x8c, 0xec, 0xf1, 0x01, 0x9e, 0x34, +0xe3, 0x01, 0xe9, 0xcc, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0x20, 0x01, 0x10, 0x04, 0x31, +0x00, 0xa8, 0x80, 0xc1, 0x9c, 0x59, 0x14, 0x11, 0x00, 0xa8, 0xf0, 0x81, 0x46, 0xa0, 0x00, 0x02, +0x58, 0xa5, 0x0e, 0x10, 0x04, 0x93, 0x00, 0x04, 0xa4, 0xb6, 0x40, 0x84, 0xd0, 0x09, 0x80, 0x29, +0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0x68, 0x54, 0x84, 0x00, 0x7f, 0x41, 0xc4, 0xc0, 0x09, +0x4b, 0xe0, 0x28, 0x01, 0x55, 0xce, 0x00, 0x0f, 0x80, 0x28, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, +0x01, 0x88, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0xa8, 0x80, 0x3c, +0x4b, 0xe0, 0x28, 0x01, 0x84, 0x09, 0x84, 0xe4, 0x4c, 0x80, 0x00, 0x1c, 0xe5, 0x0a, 0xe8, 0x08, +0x84, 0xa1, 0x4c, 0x82, 0x80, 0x3f, 0x84, 0xa8, 0x4c, 0x82, 0xc0, 0x44, 0xd5, 0x0a, 0x84, 0x2b, +0x4c, 0x80, 0x80, 0x23, 0xe1, 0x01, 0xe9, 0x16, 0x84, 0xac, 0x4c, 0x82, 0xc0, 0x3b, 0xd5, 0x29, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, 0x80, 0x10, 0xdd, 0x2f, 0xd5, 0x08, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x81, 0x00, +0xd5, 0x33, 0xa0, 0x32, 0xa4, 0x76, 0x54, 0x74, 0xbf, 0xff, 0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, +0x81, 0x40, 0xdd, 0x2f, 0xd5, 0xf5, 0xa0, 0x32, 0x50, 0x13, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0x81, +0x58, 0xf7, 0x81, 0x98, 0xdd, 0x2f, 0xa5, 0xf6, 0x81, 0x00, 0x54, 0x73, 0xbf, 0xff, 0xd5, 0x1c, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, 0x82, 0xc8, 0xdd, 0x2f, 0xd5, 0xe0, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8f, 0xe4, 0xdd, 0x2f, 0xd5, 0xd8, +0x80, 0x28, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0xc4, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8e, 0x10, 0xdd, 0x2f, 0x85, 0x00, 0x93, 0x30, 0x54, 0x94, 0x80, 0x0f, 0x4e, 0x93, 0x00, 0x04, +0x80, 0x09, 0xd5, 0x5a, 0x46, 0x90, 0x01, 0x10, 0x00, 0x14, 0x82, 0xa4, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x01, 0xdc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0x46, 0x1f, +0xff, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x73, 0x84, 0x02, 0x41, 0xce, 0x40, 0x08, 0x40, 0x73, +0xf0, 0x04, 0x42, 0x73, 0xf8, 0x09, 0x42, 0x73, 0xfc, 0x09, 0x46, 0x0f, 0xf0, 0xff, 0x58, 0x00, +0x0f, 0xff, 0x42, 0x73, 0xf8, 0x08, 0x54, 0x84, 0x00, 0x0f, 0x40, 0x73, 0x80, 0x02, 0x40, 0x84, +0x50, 0x08, 0x46, 0x1c, 0x6f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x73, 0xa0, 0x04, 0x40, 0x73, +0x84, 0x02, 0x46, 0x11, 0x80, 0x00, 0x00, 0x04, 0x82, 0xa4, 0x40, 0x73, 0x84, 0x04, 0x54, 0x00, +0x00, 0x03, 0x40, 0x00, 0x64, 0x08, 0x42, 0x73, 0xe4, 0x09, 0x42, 0x73, 0xe8, 0x09, 0x40, 0x73, +0x80, 0x04, 0x42, 0x73, 0xbc, 0x09, 0x54, 0x03, 0xbf, 0xff, 0xe4, 0x08, 0xe8, 0x06, 0x92, 0xee, +0x40, 0x73, 0xb8, 0x08, 0x58, 0x73, 0x80, 0x08, 0x54, 0x03, 0xbf, 0xff, 0xac, 0x36, 0x84, 0x01, +0x10, 0x03, 0x00, 0x0f, 0xa9, 0xf4, 0x80, 0x26, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, +0x87, 0x94, 0xdd, 0x2f, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x05, 0xfc, 0x44, 0x00, 0x00, 0x10, +0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x87, 0x54, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x11, 0x46, 0x10, +0x00, 0x80, 0x58, 0x10, 0x87, 0x64, 0xdd, 0x26, 0x84, 0x00, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, +0x87, 0x74, 0xdd, 0x26, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x87, 0x84, 0x84, 0x01, 0xdd, 0x26, +0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8d, 0xb8, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, +0x0a, 0xd4, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x86, 0x5c, 0xdd, 0x2f, 0x84, 0xc0, 0x46, 0xf0, +0x00, 0x80, 0x58, 0xf7, 0x8f, 0xbc, 0xdd, 0x2f, 0x46, 0x30, 0x01, 0x13, 0x58, 0x31, 0x8a, 0xd4, +0x84, 0x80, 0x10, 0x41, 0x82, 0x64, 0x14, 0x61, 0x80, 0x2d, 0x80, 0x26, 0x50, 0x01, 0x82, 0x66, +0x84, 0x48, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x86, 0x18, 0xdd, 0x2f, 0x46, 0x20, 0x04, 0x10, +0x58, 0x21, 0x08, 0x00, 0xa9, 0x94, 0x46, 0x30, 0x30, 0x00, 0xa0, 0x53, 0x40, 0x10, 0x8c, 0x04, +0xa8, 0x53, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x01, 0xfc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8e, 0x10, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x80, 0x20, 0xd5, 0x02, +0x9c, 0x49, 0x20, 0x20, 0x80, 0x00, 0xca, 0xfd, 0x9a, 0x08, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x46, 0x60, 0x01, 0x13, 0x58, 0x63, 0x0a, 0xd4, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x8c, 0x00, 0xdd, 0x2f, 0x04, 0x03, 0x00, 0x2d, 0xb6, 0x1f, 0x84, 0x00, +0x14, 0x03, 0x00, 0x2d, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8c, 0x2c, 0xdd, 0x2f, +0xb4, 0x1f, 0x96, 0x04, 0xc0, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x88, 0xa0, +0xdd, 0x2f, 0xb4, 0x1f, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x0a, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, +0x0a, 0xd4, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x88, 0x20, 0xdd, 0x2f, 0xb4, 0x1f, 0x40, 0x00, +0x3c, 0x08, 0x92, 0x1f, 0xc0, 0x0a, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xd4, 0x46, 0xf0, +0x00, 0x80, 0x58, 0xf7, 0x89, 0xfc, 0xdd, 0x2f, 0xb4, 0x1f, 0x40, 0x00, 0x38, 0x08, 0x92, 0x1f, +0xc0, 0x0a, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xd4, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, +0x89, 0x10, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x80, 0x60, 0x99, 0x5a, +0xd3, 0x04, 0x18, 0x11, 0x80, 0x01, 0xd5, 0xfd, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x84, 0x00, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x0e, 0x42, 0x00, 0x4c, 0x0b, 0x46, 0x10, 0x00, 0x4d, 0x58, 0x10, 0x8e, 0x24, 0xc0, 0x06, +0x46, 0x00, 0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x26, 0x25, 0x58, 0x00, +0x0a, 0x00, 0x4b, 0xe0, 0x04, 0x01, 0x46, 0x60, 0x00, 0x02, 0x58, 0x63, 0x0e, 0x10, 0x46, 0x00, +0x01, 0x10, 0x58, 0x00, 0x02, 0x04, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, +0x80, 0x0c, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, 0x85, 0xa0, 0xdd, 0x2f, 0x46, 0x10, 0x04, 0x10, 0x04, 0x20, +0x82, 0x01, 0x40, 0x21, 0x20, 0x08, 0x92, 0x48, 0x14, 0x20, 0x82, 0x01, 0x84, 0x0a, 0x84, 0x20, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x86, 0x38, 0xdd, 0x2f, 0x84, 0x0c, 0x46, 0x10, 0x00, 0x80, +0x58, 0x10, 0x84, 0x8c, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x8c, 0x94, 0xdd, 0x2f, 0x46, 0x70, +0x00, 0x00, 0x58, 0x73, 0x87, 0x98, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x85, 0x18, 0x46, 0x20, +0x01, 0x10, 0x58, 0x21, 0x02, 0x3c, 0x84, 0x07, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x60, 0x00, 0x00, +0x58, 0x63, 0x06, 0x80, 0x84, 0x07, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, +0x8b, 0xe4, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x02, 0x3c, 0x84, 0x0a, 0x4b, 0xe0, 0x1c, 0x01, +0x84, 0x0a, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, 0x84, 0xe0, 0xdd, 0x2f, +0x46, 0x00, 0x04, 0x00, 0x84, 0x21, 0x14, 0x10, 0x00, 0x8c, 0x47, 0xc0, 0x00, 0x01, 0x59, 0xce, +0x08, 0xec, 0x46, 0x90, 0x00, 0x80, 0x58, 0x94, 0x8c, 0xf8, 0x46, 0x80, 0x00, 0x81, 0x58, 0x84, +0x03, 0xc4, 0x84, 0x02, 0xdd, 0x3c, 0x80, 0xc0, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0x1c, +0xdd, 0x2f, 0x80, 0xe0, 0xa0, 0x32, 0x44, 0x50, 0x00, 0x6d, 0xd8, 0x12, 0x44, 0x10, 0x9c, 0x40, +0x40, 0x13, 0x84, 0x17, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x27, 0x80, 0xa8, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x02, 0x44, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0xdd, 0x2f, 0xa0, 0xb2, +0x44, 0x50, 0x00, 0x71, 0xda, 0x3a, 0x46, 0x80, 0x00, 0x00, 0x58, 0x84, 0x06, 0xbc, 0x84, 0x0a, +0x46, 0x60, 0x04, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x63, 0x02, 0x0c, 0x84, 0x07, 0x4b, 0xe0, +0x20, 0x01, 0xb5, 0x26, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x0e, 0x10, 0x58, 0x04, 0x80, 0x10, +0xb6, 0x06, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x70, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0x0a, +0x46, 0xf0, 0x00, 0x4e, 0x58, 0xf7, 0x8f, 0xbc, 0xdd, 0x2f, 0x44, 0x10, 0x9c, 0x40, 0x40, 0x13, +0x84, 0xf7, 0x42, 0x94, 0x90, 0x09, 0x84, 0x60, 0xb7, 0x26, 0x46, 0xf0, 0x01, 0x00, 0x10, 0x37, +0x82, 0xb7, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x7c, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x46, 0xf0, 0x00, 0x81, 0x58, 0xf7, 0x86, 0x6c, +0xdd, 0x2f, 0xd5, 0x19, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0xe0, 0x00, 0x00, 0x00, 0x14, 0xc8, 0x13, +0x80, 0x27, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xd4, 0x4b, 0xe0, 0x20, 0x01, 0xc8, 0x0b, +0x80, 0x27, 0x46, 0x00, 0x01, 0x13, 0x58, 0x00, 0x0a, 0xc4, 0x46, 0xf0, 0x00, 0x80, 0x58, 0xf7, +0x8d, 0x58, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x37, 0x82, 0xe5, 0x46, 0x00, 0x01, 0x13, +0x58, 0x00, 0x0b, 0x8c, 0xcb, 0xe0, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0xcc, +0xdd, 0x2f, 0x48, 0xff, 0xff, 0x78, 0x92, 0x00, 0x49, 0x4e, 0x49, 0x54, 0x20, 0x54, 0x49, 0x4d, +0x45, 0x52, 0x0a, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x46, 0x43, 0x45, 0x20, +0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, +0x0a, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x57, 0x48, 0x4e, +0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2f, 0x66, 0x63, 0x65, 0x2f, 0x66, 0x63, 0x65, 0x2e, +0x63, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x21, 0x20, 0x52, 0x78, 0x46, 0x53, +0x20, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, +0x20, 0x42, 0x75, 0x66, 0x20, 0x44, 0x65, 0x73, 0x63, 0x20, 0x21, 0x21, 0x0a, 0x00, 0x00, 0x00, +0x45, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x21, 0x20, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x61, +0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x42, 0x75, 0x66, 0x20, 0x44, 0x65, 0x73, 0x63, +0x20, 0x21, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, +0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x20, 0x28, 0x25, 0x78, 0x29, 0x0a, 0x00, +0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x57, 0x48, 0x4e, 0x2f, 0x70, 0x65, 0x72, +0x69, 0x2f, 0x6d, 0x63, 0x75, 0x63, 0x74, 0x6c, 0x2f, 0x6d, 0x63, 0x75, 0x63, 0x74, 0x6c, 0x2e, +0x63, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x57, 0x48, 0x4e, +0x2f, 0x61, 0x70, 0x69, 0x2f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, +0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x57, 0x48, 0x4e, 0x2f, 0x61, 0x70, 0x69, +0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x63, 0x00, 0x41, 0x64, 0x64, 0x72, 0x20, 0x3d, 0x20, 0x25, +0x78, 0x0a, 0x00, 0x00, 0x44, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, +0x52, 0x46, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x52, 0x25, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6c, +0x2c, 0x20, 0x0a, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x25, 0x64, 0x20, 0x3d, 0x20, +0x25, 0x78, 0x0a, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x57, 0x48, 0x4e, +0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6b, 0x74, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x63, 0x00, 0x00, +0x43, 0x6d, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x20, 0x3d, 0x20, 0x25, 0x78, +0x2c, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, +0x43, 0x6d, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x43, 0x6d, +0x64, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x6d, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x43, 0x6d, +0x64, 0x5f, 0x53, 0x65, 0x71, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x55, 0x6e, 0x6b, 0x6e, +0x6f, 0x77, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x25, 0x64, 0x29, +0x0a, 0x0a, 0x00, 0x00, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, +0x6f, 0x6e, 0x73, 0x65, 0x20, 0x49, 0x6e, 0x42, 0x61, 0x6e, 0x64, 0x51, 0x3d, 0x25, 0x64, 0x0a, +0x0a, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x20, 0x0a, 0x0a, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, +0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2d, 0x2d, 0x20, +0x57, 0x69, 0x46, 0x69, 0x5f, 0x54, 0x61, 0x73, 0x6b, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x20, 0x2d, +0x2d, 0x0a, 0x00, 0x00, 0x4e, 0x55, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x57, 0x49, 0x46, 0x49, +0x20, 0x52, 0x41, 0x4d, 0x20, 0x43, 0x4f, 0x44, 0x45, 0x3a, 0x20, 0x54, 0x61, 0x73, 0x6b, 0x20, +0x6a, 0x69, 0x66, 0x66, 0x69, 0x65, 0x73, 0x28, 0x25, 0x64, 0x29, 0x20, 0x50, 0x4b, 0x54, 0x43, +0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x46, 0x43, +0x45, 0x0a, 0x00, 0x00, 0x20, 0x21, 0x21, 0x2d, 0x2d, 0x3e, 0x20, 0x54, 0x61, 0x73, 0x6b, 0x20, +0x6a, 0x69, 0x66, 0x66, 0x69, 0x65, 0x73, 0x28, 0x25, 0x64, 0x29, 0x20, 0x52, 0x45, 0x53, 0x45, +0x54, 0x20, 0x52, 0x41, 0x4d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662_firmware.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662_firmware.h new file mode 100644 index 000000000..362bfd2f0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662_firmware.h @@ -0,0 +1,5129 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7662_FirmwareImage[] = { +0x0c, 0xfb, 0x00, 0x00, 0x14, 0x45, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xe3, 0x02, 0x03, +0x32, 0x30, 0x31, 0x36, 0x30, 0x37, 0x31, 0x31, 0x31, 0x34, 0x34, 0x33, 0x5f, 0x5f, 0x5f, 0x5f, +0x46, 0x00, 0x00, 0x8f, 0x58, 0x00, 0x06, 0x44, 0x4a, 0x00, 0x00, 0x00, 0x80, 0x9e, 0x3e, 0x08, +0xf5, 0x58, 0x3e, 0x18, 0xf5, 0x58, 0x3e, 0x29, 0x3a, 0x6c, 0x40, 0x31, 0x04, 0x01, 0x40, 0x00, +0x0c, 0x00, 0x3a, 0x10, 0x04, 0x1c, 0x3a, 0x11, 0x04, 0x3c, 0x50, 0x31, 0xff, 0xfc, 0x4e, 0x36, +0xff, 0xfa, 0x64, 0x00, 0x00, 0x09, 0x3e, 0x08, 0xf5, 0x58, 0x3e, 0x28, 0xf5, 0x58, 0x4c, 0x01, +0x00, 0x08, 0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfe, 0x3e, 0x09, +0x3a, 0x6c, 0x3e, 0x29, 0x97, 0x18, 0x4c, 0x01, 0x00, 0x08, 0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, +0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfe, 0x83, 0xc4, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x10, 0x04, 0x00, +0x44, 0x20, 0x00, 0xea, 0x80, 0x01, 0x14, 0x20, 0x81, 0x04, 0x44, 0x10, 0x00, 0x98, 0x14, 0x10, +0x01, 0x06, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x81, 0x00, +0x80, 0x01, 0x58, 0x21, 0x00, 0x11, 0x14, 0x20, 0x81, 0x00, 0x04, 0x10, 0x01, 0x06, 0x3e, 0x69, +0x3a, 0x8c, 0x58, 0x10, 0x80, 0x80, 0x14, 0x10, 0x01, 0x06, 0x44, 0x50, 0x03, 0xe8, 0xb4, 0x06, +0x9c, 0x01, 0xb6, 0x06, 0xd8, 0x09, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6d, 0x84, 0x40, 0x49, 0xfc, +0x35, 0xa3, 0x84, 0x00, 0xb6, 0x06, 0x2e, 0x01, 0x3a, 0x5c, 0x84, 0xa1, 0xd8, 0x09, 0x3c, 0x1c, +0x4e, 0xa3, 0x84, 0x05, 0x40, 0x10, 0x80, 0x16, 0xc8, 0x03, 0x49, 0x00, 0x14, 0x53, 0x49, 0x00, +0x16, 0x3d, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x04, 0x60, 0x00, 0x78, 0x96, 0x30, 0x96, 0x44, 0xc1, 0x05, +0x3c, 0x7c, 0x4e, 0xba, 0x84, 0xc1, 0xd5, 0x26, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x05, 0x3c, 0x7c, +0x4e, 0xbb, 0x84, 0xc2, 0xd5, 0x1f, 0x40, 0x73, 0x40, 0x09, 0x97, 0xf8, 0x54, 0x03, 0x80, 0x02, +0xc0, 0x06, 0x3c, 0x7c, 0x4e, 0xcb, 0x44, 0x62, 0x00, 0x00, 0xd5, 0x14, 0x97, 0xfc, 0xc7, 0x06, +0x3c, 0x7c, 0x4e, 0xca, 0x44, 0x61, 0x00, 0x00, 0xd5, 0x0d, 0x3e, 0x08, 0xf5, 0x58, 0x49, 0x00, +0x05, 0x59, 0x80, 0x07, 0x80, 0x27, 0x3e, 0x28, 0xf5, 0x78, 0x44, 0x30, 0x01, 0x00, 0x49, 0xfc, +0x1f, 0xf7, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x84, 0x20, 0x14, 0x60, 0x00, 0x78, +0x3e, 0x28, 0xf5, 0x78, 0x40, 0x00, 0x9c, 0x06, 0x44, 0x30, 0x01, 0x0b, 0x49, 0xfc, 0x1f, 0xe8, +0x92, 0x00, 0x3e, 0x09, 0x8a, 0x58, 0xdd, 0x27, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3e, 0x28, 0xf5, 0x78, 0x80, 0xc0, 0x80, 0xe1, 0x5c, 0x00, +0x00, 0x20, 0x84, 0x20, 0x44, 0x30, 0x00, 0xb5, 0x49, 0xfc, 0x1f, 0xd2, 0x92, 0x00, 0x3e, 0x09, +0x3a, 0xe8, 0x38, 0x70, 0x1a, 0x0a, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x04, 0x00, +0x80, 0x78, 0x84, 0x41, 0x40, 0x61, 0x18, 0x0c, 0x40, 0x03, 0x00, 0x04, 0x14, 0x00, 0x80, 0x78, +0x04, 0x00, 0x80, 0x7a, 0x40, 0x63, 0x00, 0x04, 0x14, 0x60, 0x80, 0x7a, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x84, 0x20, 0xf1, 0x81, 0x44, 0x10, +0x00, 0x40, 0x10, 0x1f, 0x80, 0x04, 0x10, 0x1f, 0x80, 0x07, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, +0x88, 0x00, 0xb4, 0x41, 0x50, 0x60, 0x00, 0x9c, 0x58, 0x01, 0x00, 0x02, 0xb6, 0x01, 0x80, 0x01, +0xf2, 0x01, 0x14, 0x20, 0x80, 0x71, 0x04, 0x70, 0x00, 0x71, 0x46, 0x80, 0x04, 0x10, 0x42, 0x13, +0x8c, 0x0b, 0xf7, 0x81, 0x58, 0x84, 0x08, 0x00, 0xc9, 0xf7, 0x42, 0x73, 0x84, 0x0b, 0xcf, 0xf4, +0x50, 0x13, 0x7f, 0x64, 0x50, 0x23, 0x7f, 0xe4, 0x50, 0x04, 0x01, 0xa0, 0x84, 0x62, 0x49, 0x00, +0x03, 0xdf, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0x84, 0x50, 0x23, 0x7f, 0xec, 0x58, 0x00, +0x09, 0xb0, 0x84, 0x62, 0x49, 0x00, 0x03, 0xd4, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0xa4, +0x50, 0x23, 0x7f, 0xf4, 0x58, 0x00, 0x09, 0x80, 0x84, 0x62, 0x49, 0x00, 0x03, 0xa5, 0x46, 0x00, +0x04, 0x10, 0x50, 0x13, 0x7f, 0xc4, 0x9e, 0xb4, 0x84, 0x62, 0x58, 0x00, 0x09, 0x90, 0x49, 0x00, +0x03, 0x9b, 0x84, 0x01, 0xaf, 0xf5, 0xaf, 0xf4, 0x10, 0x04, 0x01, 0xa8, 0x10, 0x04, 0x01, 0xb8, +0x14, 0x73, 0x00, 0x09, 0xaf, 0xf7, 0xaf, 0xf6, 0xa9, 0xf4, 0xa9, 0xf5, 0xa9, 0xf2, 0xa9, 0xf3, +0x50, 0x03, 0x00, 0x1c, 0x49, 0x00, 0x07, 0x52, 0x04, 0x14, 0x00, 0x71, 0x58, 0x00, 0x80, 0x05, +0xf1, 0x81, 0x10, 0x0f, 0x80, 0x04, 0xf0, 0x01, 0x14, 0x04, 0x00, 0x71, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x04, 0x20, 0x00, 0x29, 0x04, 0x30, 0x00, 0x2a, +0x9c, 0x92, 0x9a, 0x93, 0xe4, 0x42, 0x4e, 0xf3, 0x00, 0x84, 0x00, 0x30, 0x00, 0xa2, 0x9c, 0x9c, +0x94, 0x94, 0x98, 0x82, 0xa7, 0x17, 0x54, 0x42, 0x00, 0x80, 0xc4, 0x7a, 0xb4, 0xa1, 0x50, 0x41, +0x80, 0x24, 0x38, 0x50, 0x12, 0x0a, 0x95, 0x9c, 0x00, 0x50, 0x80, 0x9e, 0x00, 0x70, 0x80, 0x9f, +0xa1, 0x0b, 0x99, 0xfd, 0x8c, 0xf4, 0x50, 0x50, 0x80, 0x10, 0x02, 0x81, 0x00, 0x03, 0xc4, 0x22, +0x93, 0x0e, 0x40, 0x84, 0x38, 0x08, 0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0xb6, 0xa2, 0xa7, 0x17, +0x42, 0x42, 0x18, 0x09, 0xaf, 0x17, 0x99, 0x86, 0xa1, 0x0a, 0x14, 0x43, 0x00, 0x12, 0xa1, 0x0b, +0xa4, 0x52, 0x54, 0x42, 0x3f, 0xff, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x10, 0x90, 0x04, +0xac, 0x52, 0xa7, 0x17, 0xa6, 0x55, 0x54, 0x42, 0x00, 0x7f, 0x58, 0x10, 0x80, 0x40, 0xaf, 0x17, +0xd5, 0x1b, 0x93, 0x0e, 0x40, 0x84, 0x38, 0x08, 0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0x99, 0x86, +0xa6, 0x57, 0xb6, 0xa2, 0x58, 0x10, 0x80, 0x40, 0xae, 0x57, 0x14, 0x43, 0x00, 0x12, 0xa4, 0x52, +0xa7, 0x17, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0xac, 0x52, 0x54, 0x42, 0x00, 0x7f, 0xa6, 0x55, +0xaf, 0x17, 0x42, 0x10, 0x98, 0x09, 0xae, 0x55, 0x94, 0x5c, 0x98, 0x41, 0x50, 0x10, 0x80, 0x48, +0xa6, 0x8e, 0x44, 0x5f, 0xff, 0xcf, 0x40, 0x21, 0x14, 0x02, 0x58, 0x21, 0x00, 0x08, 0x84, 0x84, +0x9c, 0xdc, 0xaf, 0x0f, 0xae, 0x8e, 0x40, 0x31, 0x90, 0x0c, 0x98, 0xc3, 0xa4, 0x9b, 0xb4, 0x61, +0x54, 0x21, 0x3f, 0xff, 0x98, 0x9a, 0xac, 0x8a, 0x46, 0x10, 0x04, 0x10, 0x00, 0x20, 0x00, 0xa2, +0x04, 0x30, 0x00, 0x2a, 0x9c, 0x91, 0x96, 0x94, 0x9c, 0xd9, 0x58, 0x10, 0x88, 0x00, 0x14, 0x30, +0x00, 0x2a, 0x10, 0x20, 0x00, 0xa2, 0x10, 0x20, 0x81, 0x88, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, +0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2b, 0x04, 0x30, 0x00, 0x2c, +0x9c, 0x92, 0x9a, 0x93, 0xe4, 0x42, 0xe9, 0x40, 0x00, 0x30, 0x00, 0xa3, 0x9c, 0x9e, 0x94, 0x94, +0x98, 0x82, 0xa7, 0x17, 0x54, 0x42, 0x00, 0x80, 0xc4, 0x37, 0x50, 0x41, 0x80, 0x26, 0x38, 0x10, +0x12, 0x0a, 0x94, 0xdc, 0xa1, 0x0a, 0x98, 0xc3, 0xb6, 0x82, 0xa1, 0x4c, 0x14, 0x51, 0x80, 0x1b, +0xa5, 0x0e, 0xa4, 0xd3, 0x54, 0x42, 0x3f, 0xff, 0x92, 0x6e, 0x40, 0x31, 0xb8, 0x08, 0x40, 0x31, +0x90, 0x04, 0xac, 0xd3, 0xa7, 0x55, 0x00, 0x40, 0x80, 0x0f, 0xa6, 0xd7, 0x97, 0x24, 0x95, 0x26, +0x54, 0x31, 0x80, 0x3f, 0x40, 0x31, 0x90, 0x04, 0x54, 0x12, 0x80, 0x7f, 0xae, 0x55, 0xae, 0xd7, +0x46, 0x10, 0x04, 0x10, 0x00, 0x20, 0x00, 0xa3, 0x04, 0x30, 0x00, 0x2c, 0x9c, 0x91, 0x96, 0x94, +0x9c, 0xd9, 0x58, 0x10, 0x88, 0x00, 0x14, 0x30, 0x00, 0x2c, 0x10, 0x20, 0x00, 0xa3, 0x10, 0x20, +0x81, 0x98, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0xd5, 0x20, 0xa6, 0x9f, 0x54, 0x21, 0x00, 0x80, 0xc2, 0x2b, +0x38, 0x23, 0x06, 0x02, 0x38, 0x93, 0x06, 0x0a, 0x80, 0x22, 0x00, 0x31, 0x00, 0x14, 0xcb, 0x02, +0xd5, 0x03, 0x3e, 0x09, 0x83, 0x70, 0x9d, 0xfe, 0x95, 0xfc, 0x99, 0xf7, 0x49, 0x00, 0x05, 0x82, +0xa6, 0x3f, 0x44, 0x1f, 0xff, 0xc0, 0x40, 0x00, 0x04, 0x04, 0xae, 0x3f, 0x04, 0x03, 0x00, 0x2b, +0x9c, 0x01, 0x14, 0x03, 0x00, 0x2b, 0x04, 0x03, 0x00, 0x2b, 0x04, 0x23, 0x00, 0x2c, 0x97, 0xc4, +0x9c, 0xfe, 0x94, 0xdc, 0x9a, 0x90, 0x50, 0x13, 0x80, 0x26, 0x98, 0xf3, 0x3e, 0x09, 0x83, 0x80, +0x4e, 0x26, 0xff, 0xd4, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xff, 0xff, 0xc5, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0xd5, 0x1a, 0xa6, 0x7f, 0x54, 0x10, +0x80, 0x80, 0xc1, 0x25, 0x38, 0x13, 0x0a, 0x02, 0x38, 0x93, 0x0a, 0x0a, 0x49, 0x00, 0x05, 0x4a, +0xa6, 0x7f, 0xa6, 0x3d, 0x44, 0x2f, 0xff, 0xc0, 0x58, 0x00, 0x00, 0x40, 0x40, 0x10, 0x88, 0x04, +0xae, 0x7f, 0xae, 0x3d, 0x04, 0x03, 0x00, 0x29, 0x9c, 0x01, 0x14, 0x03, 0x00, 0x29, 0x04, 0x13, +0x00, 0x29, 0x04, 0x33, 0x00, 0x2a, 0x97, 0xcc, 0x50, 0x23, 0x80, 0x24, 0x9d, 0xfc, 0x95, 0xfc, +0x9a, 0x59, 0x3e, 0x09, 0x83, 0x70, 0x99, 0xf7, 0x4e, 0x16, 0xff, 0xda, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xff, 0xcb, 0x92, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0xa0, +0x04, 0x10, 0x58, 0x35, 0x08, 0x00, 0x81, 0x00, 0x00, 0x51, 0x81, 0xbc, 0x00, 0x74, 0x00, 0xa1, +0xdf, 0x13, 0x9c, 0x79, 0x96, 0x4c, 0x96, 0x08, 0x9c, 0x82, 0x94, 0x94, 0x88, 0x48, 0xa6, 0x97, +0x54, 0x21, 0x00, 0x80, 0xca, 0x06, 0x56, 0x00, 0x00, 0x01, 0x4c, 0x00, 0xff, 0xf7, 0xd5, 0x74, +0x4c, 0x70, 0x00, 0x03, 0xd5, 0x6d, 0x9d, 0xba, 0x95, 0xb4, 0x88, 0xc8, 0xa6, 0x37, 0x54, 0x00, +0x00, 0x80, 0xc8, 0x23, 0x9c, 0x79, 0x96, 0x4c, 0x96, 0x08, 0x9c, 0x82, 0x94, 0x94, 0x88, 0x48, +0xa6, 0x97, 0x54, 0x21, 0x00, 0x80, 0xca, 0x07, 0x56, 0x00, 0x00, 0x01, 0x4c, 0x00, 0xff, 0xf7, +0x48, 0x00, 0x00, 0x76, 0x4c, 0x70, 0x40, 0x55, 0xd5, 0x57, 0x46, 0x10, 0x04, 0x10, 0x04, 0x10, +0x82, 0x8d, 0x40, 0x10, 0xa0, 0x08, 0x92, 0x38, 0xc1, 0x4f, 0x00, 0x10, 0x01, 0xb8, 0x9c, 0x49, +0x96, 0x4c, 0x10, 0x10, 0x01, 0xb8, 0xd5, 0x48, 0x03, 0xc3, 0x00, 0x03, 0x3e, 0x09, 0x83, 0x70, +0xb6, 0x7f, 0x49, 0x00, 0x04, 0xad, 0x55, 0xce, 0x3f, 0xff, 0x81, 0x20, 0xb4, 0x7f, 0xc0, 0x3c, +0x50, 0x23, 0x80, 0x22, 0x38, 0x14, 0x0a, 0x02, 0x94, 0x3c, 0x13, 0xc0, 0x80, 0x06, 0x40, 0xa4, +0x00, 0x00, 0x51, 0xc5, 0x00, 0x2c, 0xb4, 0x9c, 0x84, 0x01, 0xa9, 0x0c, 0x10, 0x00, 0x80, 0x14, +0x3e, 0x09, 0x83, 0x70, 0xf2, 0x81, 0xb6, 0x7f, 0x49, 0x00, 0x04, 0xb4, 0xf2, 0x01, 0x50, 0x05, +0x00, 0x28, 0x38, 0x94, 0x0a, 0x0a, 0xa4, 0x73, 0x84, 0x80, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, +0x58, 0x10, 0x86, 0x40, 0xac, 0x73, 0xa6, 0x77, 0x58, 0x10, 0x80, 0x40, 0xae, 0x77, 0x04, 0x94, +0x80, 0x02, 0xb7, 0x26, 0xb6, 0x80, 0xb6, 0x9c, 0xa6, 0x37, 0x54, 0x00, 0x00, 0x7f, 0xae, 0x37, +0xb4, 0x7f, 0x10, 0x71, 0x81, 0xb8, 0x00, 0x04, 0x00, 0xa1, 0x9c, 0x01, 0x96, 0x04, 0x10, 0x04, +0x00, 0xa1, 0x48, 0xff, 0xff, 0x7b, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x00, 0x00, +0x81, 0xbc, 0x00, 0x50, 0x81, 0xb8, 0xd8, 0x1d, 0x04, 0x00, 0x80, 0x71, 0x54, 0x00, 0x00, 0x08, +0xc0, 0x18, 0x00, 0x00, 0x81, 0xb8, 0x9c, 0x01, 0x96, 0x04, 0x10, 0x00, 0x81, 0xb8, 0x00, 0x04, +0x00, 0xa1, 0x9c, 0x01, 0x96, 0x04, 0x10, 0x04, 0x00, 0xa1, 0xd5, 0x0b, 0x46, 0x00, 0x04, 0x10, +0x58, 0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x71, 0x54, 0x10, 0x80, 0x08, 0xc1, 0x87, 0xd5, 0xdc, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x80, 0x60, +0x50, 0x00, 0x00, 0xb8, 0x46, 0x50, 0x04, 0x10, 0xf0, 0x85, 0x58, 0x52, 0x88, 0x00, 0x84, 0x80, +0x80, 0xe3, 0x00, 0x83, 0x80, 0xa1, 0x00, 0x12, 0x81, 0xbc, 0x50, 0x24, 0x00, 0x22, 0xf2, 0x84, +0x50, 0x24, 0x00, 0x02, 0x94, 0x94, 0x3e, 0x09, 0x83, 0x70, 0x99, 0xba, 0x4c, 0x80, 0x80, 0x5c, +0xa6, 0x77, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x57, 0xa4, 0x73, 0xf4, 0x83, 0x54, 0xa0, 0xbf, 0xff, +0xf5, 0x82, 0x49, 0x00, 0x04, 0x1d, 0x40, 0x14, 0x10, 0x08, 0x81, 0x20, 0x98, 0xf9, 0x51, 0xc1, +0x80, 0x2c, 0xf0, 0x05, 0xf4, 0x03, 0xf5, 0x02, 0x4e, 0x93, 0x00, 0x0f, 0x3e, 0x08, 0xf5, 0x94, +0xf7, 0x81, 0x49, 0x00, 0x02, 0x57, 0xf3, 0x01, 0x04, 0x11, 0x80, 0x2d, 0x42, 0x10, 0xc4, 0x08, +0x14, 0x11, 0x80, 0x2d, 0xd5, 0x38, 0xf1, 0x04, 0x38, 0x23, 0x86, 0x02, 0x12, 0xa1, 0x00, 0x06, +0x80, 0x22, 0xb5, 0x5c, 0x14, 0xa1, 0x00, 0x04, 0x85, 0x41, 0x10, 0xa1, 0x00, 0x14, 0xf3, 0x81, +0xf4, 0x83, 0xf5, 0x82, 0x49, 0x00, 0x04, 0x16, 0x92, 0x00, 0x04, 0xaf, 0x80, 0x04, 0x9c, 0xb4, +0x38, 0x93, 0xaa, 0x0a, 0xf4, 0x03, 0xb6, 0x82, 0x44, 0x20, 0x06, 0x40, 0xac, 0xb3, 0xb6, 0x86, +0xa6, 0xb7, 0xf3, 0x01, 0x58, 0x21, 0x00, 0x40, 0xae, 0xb7, 0x50, 0x11, 0x80, 0x28, 0x04, 0x94, +0x80, 0x02, 0xb7, 0x26, 0xb6, 0x81, 0xb6, 0x9c, 0xa6, 0x77, 0x54, 0x10, 0x80, 0x7f, 0xae, 0x77, +0xf5, 0x02, 0x10, 0x82, 0x81, 0xb8, 0x00, 0x13, 0x80, 0xa1, 0x9c, 0x49, 0x96, 0x4c, 0x10, 0x13, +0x80, 0xa1, 0xd5, 0x98, 0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x46, 0x10, 0x04, 0x10, 0x04, 0x20, 0x81, 0x00, 0x46, 0x60, 0x04, 0x00, 0x58, 0x21, 0x00, 0x0c, +0x14, 0x20, 0x81, 0x00, 0x58, 0x63, 0x00, 0x64, 0xb4, 0x26, 0x81, 0x00, 0x42, 0x00, 0xd4, 0x08, +0xb6, 0x06, 0x44, 0x00, 0x00, 0x28, 0x49, 0xfc, 0x0f, 0xad, 0xb4, 0x06, 0x42, 0x00, 0x54, 0x09, +0xb6, 0x06, 0x46, 0x10, 0x04, 0x10, 0x04, 0x00, 0x82, 0x00, 0x58, 0x00, 0x00, 0x01, 0x14, 0x00, +0x82, 0x00, 0x3e, 0x09, 0x83, 0x70, 0x49, 0x00, 0x03, 0xa3, 0xc8, 0xfc, 0x3e, 0x09, 0x83, 0x80, +0x49, 0x00, 0x03, 0x9e, 0x80, 0xe0, 0xc8, 0xfb, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x01, 0x80, +0x44, 0x00, 0x00, 0x10, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x8a, 0xc4, 0xdd, 0x26, 0x46, 0x10, +0x00, 0x80, 0x58, 0x10, 0x8a, 0x90, 0x44, 0x00, 0x00, 0x11, 0xdd, 0x26, 0x80, 0x07, 0x46, 0x10, +0x00, 0x80, 0x58, 0x10, 0x85, 0x54, 0xdd, 0x26, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x84, 0xdc, +0x84, 0x01, 0xdd, 0x26, 0x49, 0x00, 0x03, 0xc0, 0x80, 0x08, 0x49, 0xff, 0xfc, 0xb5, 0x46, 0x10, +0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0xa9, 0xcc, 0xa0, 0x8b, 0x42, 0x21, 0x60, 0x09, 0x42, 0x21, +0x64, 0x09, 0x42, 0x21, 0x60, 0x08, 0xa8, 0x8b, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x00, +0x84, 0x53, 0x40, 0x10, 0x88, 0x02, 0x14, 0x10, 0x01, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x04, 0x20, +0x80, 0x71, 0x54, 0x21, 0x00, 0x08, 0xc2, 0x0b, 0x00, 0x20, 0x81, 0xb8, 0x00, 0x50, 0x81, 0xbc, +0xda, 0x06, 0x3e, 0x08, 0xf5, 0xb0, 0x49, 0x00, 0x01, 0x95, 0xd5, 0x03, 0x49, 0xff, 0xff, 0x80, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, +0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, +0x00, 0xa0, 0x00, 0x52, 0x01, 0xac, 0x94, 0xbc, 0x3e, 0x09, 0x83, 0x80, 0x50, 0xa3, 0x80, 0x20, +0x40, 0x6e, 0x08, 0x00, 0xd7, 0x4b, 0xa6, 0x77, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x47, 0xa4, 0x73, +0xb6, 0x9f, 0x54, 0x90, 0xbf, 0xff, 0x49, 0x00, 0x03, 0x23, 0x98, 0x7f, 0x9c, 0x49, 0x81, 0x00, +0x94, 0x4b, 0x40, 0x3e, 0x04, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x0b, 0x3e, 0x08, +0xf5, 0xd0, 0x49, 0x00, 0x01, 0x5f, 0xb9, 0x2d, 0x42, 0x10, 0xc0, 0x08, 0xb9, 0xad, 0xd5, 0x2e, +0x38, 0x2e, 0x2a, 0x02, 0x12, 0x91, 0x00, 0x06, 0x80, 0x22, 0xa0, 0xd9, 0xa8, 0xd4, 0x84, 0x60, +0x10, 0x31, 0x00, 0x14, 0xb6, 0x9f, 0x49, 0x00, 0x03, 0x25, 0x38, 0x8e, 0x2a, 0x0a, 0x84, 0x20, +0x80, 0x06, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xcd, 0x2f, 0xa6, 0x77, 0x04, 0x84, 0x00, 0x02, +0x58, 0x10, 0x80, 0x40, 0xae, 0x77, 0xa4, 0x73, 0xb7, 0x06, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, +0x58, 0x10, 0x80, 0xc8, 0xac, 0x73, 0xb4, 0x9f, 0x10, 0x72, 0x01, 0xa8, 0x00, 0x1e, 0x00, 0xa0, +0x9c, 0x49, 0x96, 0x4c, 0x10, 0x1e, 0x00, 0xa0, 0xd5, 0xab, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xb6, 0x20, 0xa8, 0xc1, 0x80, 0xc1, +0xa0, 0x43, 0x84, 0xe0, 0x81, 0x23, 0x81, 0x02, 0xa8, 0x42, 0x45, 0xc5, 0xa3, 0xc4, 0x81, 0x47, +0xd5, 0x0c, 0xdd, 0x3c, 0xa6, 0x37, 0x44, 0x1f, 0xff, 0xc0, 0x40, 0x00, 0x04, 0x04, 0xae, 0x37, +0x1c, 0xa4, 0x00, 0x01, 0x9d, 0xf9, 0x8c, 0xd0, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, +0xe2, 0xe9, 0xe9, 0xf0, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xec, 0xb6, 0x20, 0x83, 0x83, 0xa8, 0xc1, 0x46, 0x30, 0x04, 0x10, 0x58, 0x31, 0x89, 0xb0, +0x80, 0xc1, 0x40, 0x10, 0x0c, 0x03, 0xa0, 0xc3, 0x44, 0x40, 0x06, 0x40, 0xa8, 0xc2, 0x44, 0x50, +0x00, 0xc8, 0x3e, 0x39, 0x83, 0x70, 0x3e, 0x09, 0x83, 0x80, 0x40, 0x82, 0x84, 0x1b, 0x40, 0x82, +0x04, 0x1a, 0x84, 0xe0, 0x40, 0x41, 0x84, 0x1a, 0x40, 0x40, 0x04, 0x1b, 0xf4, 0x83, 0x81, 0x42, +0x44, 0x45, 0xa3, 0xc4, 0x81, 0x27, 0x54, 0x34, 0x3f, 0xff, 0xd5, 0x21, 0xf3, 0x81, 0xf4, 0x82, +0xdd, 0x24, 0xf0, 0x03, 0x49, 0x00, 0x02, 0x8c, 0x92, 0x00, 0xf3, 0x01, 0xf4, 0x02, 0xc0, 0x1d, +0x12, 0x80, 0x00, 0x06, 0x10, 0x90, 0x00, 0x0e, 0x10, 0x90, 0x00, 0x0f, 0xa6, 0x77, 0x9d, 0xf9, +0x54, 0x10, 0x80, 0x3f, 0xae, 0x77, 0xa4, 0x73, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x10, +0x8c, 0x04, 0xac, 0x73, 0xa0, 0x42, 0xaa, 0x74, 0x1c, 0x05, 0x00, 0x01, 0x80, 0x06, 0x84, 0x20, +0x44, 0x20, 0x00, 0x10, 0xe2, 0xfc, 0xe9, 0xdb, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x04, 0x10, 0x00, 0x2d, 0x42, 0x10, 0xc4, 0x08, 0x14, 0x10, +0x00, 0x2d, 0x2e, 0x21, 0x3a, 0x58, 0x84, 0xa1, 0xda, 0x07, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6f, +0x49, 0xfc, 0x30, 0xaa, 0x92, 0x00, 0x84, 0x20, 0x3e, 0x11, 0x3a, 0x58, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x04, 0x20, 0x00, 0x2d, 0x80, 0x20, +0x42, 0x21, 0x40, 0x08, 0x14, 0x20, 0x80, 0x2d, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6f, 0x84, 0x40, +0x49, 0xfc, 0x30, 0x92, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x00, 0xa0, 0x44, 0x40, 0x00, 0xa0, 0x09, 0x96, 0x00, +0x54, 0x20, 0x00, 0x10, 0xc2, 0x04, 0x3c, 0x6c, 0x4e, 0xe6, 0xd5, 0x26, 0x54, 0x20, 0x00, 0x20, +0xc2, 0x04, 0x3c, 0x6c, 0x4e, 0xe7, 0xd5, 0x20, 0x54, 0x20, 0x00, 0x40, 0xc2, 0x04, 0x3c, 0x6c, +0x4e, 0xe8, 0xd5, 0x1a, 0x54, 0x00, 0x00, 0x80, 0xc0, 0x04, 0x3c, 0x6c, 0x4e, 0xe9, 0xd5, 0x14, +0x40, 0x60, 0xc0, 0x09, 0x97, 0xb0, 0x96, 0x34, 0xc0, 0x04, 0x3c, 0x6c, 0x4e, 0xea, 0xd5, 0x0c, +0x54, 0x63, 0x00, 0x02, 0x97, 0xb0, 0xc6, 0x04, 0x3c, 0x6c, 0x4e, 0xeb, 0xd5, 0x05, 0x3e, 0x08, +0xf5, 0xec, 0x49, 0x00, 0x00, 0x4f, 0x84, 0x20, 0x40, 0x00, 0x98, 0x06, 0x3e, 0x28, 0xf6, 0x04, +0x44, 0x30, 0x00, 0x6e, 0x49, 0xfc, 0x1a, 0xec, 0xdd, 0x26, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xe1, 0x80, 0xc0, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x20, 0x3e, 0x28, +0xf6, 0x04, 0x44, 0x30, 0x00, 0x36, 0x49, 0xfc, 0x1a, 0xdb, 0x84, 0x20, 0x40, 0x00, 0x9c, 0x06, +0x3e, 0x28, 0xf6, 0x04, 0x44, 0x30, 0x00, 0x37, 0x49, 0xfc, 0x1a, 0xd2, 0x3e, 0x09, 0x3b, 0x68, +0x38, 0x70, 0x1a, 0x0a, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x00, 0xa0, 0x0d, 0x84, 0x41, +0x40, 0x61, 0x18, 0x0c, 0x40, 0x63, 0x00, 0x04, 0xa9, 0x8d, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0xb4, 0x41, 0x18, 0x01, 0x00, 0x01, 0x84, 0x00, 0xb6, 0x41, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x80, 0xc0, 0x80, 0x66, 0x80, 0x01, 0x80, 0x22, 0x46, 0x20, 0x00, 0x80, 0x58, 0x21, 0x0b, 0xc0, +0x49, 0xfc, 0x1a, 0xd4, 0x84, 0x40, 0x38, 0x23, 0x00, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x1f, 0x94, 0x3c, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf4, 0x2e, 0x21, 0x3a, 0x5a, 0x84, 0x21, +0x80, 0xc0, 0x4c, 0x20, 0xc0, 0x08, 0x50, 0x1f, 0x80, 0x14, 0xf1, 0x81, 0x49, 0xfc, 0x1c, 0x30, +0xd5, 0x1f, 0x84, 0x62, 0x4c, 0x21, 0xc0, 0x1d, 0x50, 0x3f, 0x80, 0x14, 0x84, 0x20, 0x44, 0x20, +0x02, 0x00, 0x3e, 0x09, 0x3b, 0xe8, 0xf3, 0x81, 0x49, 0xfe, 0xcb, 0xce, 0xf2, 0x01, 0x80, 0x26, +0x3e, 0x09, 0x3b, 0xe8, 0x49, 0xff, 0xff, 0xcc, 0x3e, 0x09, 0x3b, 0xe8, 0x49, 0xfe, 0xcb, 0xcc, +0x9c, 0xc1, 0x84, 0x20, 0x84, 0x03, 0x3e, 0x29, 0x3b, 0xe8, 0x49, 0x00, 0x10, 0x25, 0xec, 0x0c, +0x3a, 0x6f, 0x98, 0x84, 0xec, 0x14, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x01, +0x80, 0xe2, 0x81, 0x23, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x00, 0xa0, 0x80, 0xc0, +0x49, 0xfc, 0x1a, 0x66, 0x84, 0x00, 0x14, 0x93, 0x00, 0x05, 0xa8, 0x31, 0x14, 0x83, 0x00, 0x06, +0xa9, 0xf4, 0xb6, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x84, 0x20, 0x80, 0xc0, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x00, 0xd1, 0x44, 0x70, +0x41, 0x3c, 0xdd, 0x27, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x40, 0x44, 0x30, 0x00, 0xd7, +0xdd, 0x27, 0xb4, 0x06, 0xc0, 0x22, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x00, 0xd4, +0x3e, 0x09, 0x83, 0x5c, 0xdd, 0x27, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, +0x00, 0xd4, 0xdd, 0x27, 0xa0, 0x71, 0xb4, 0x46, 0x84, 0x00, 0xa8, 0x51, 0xb6, 0x41, 0xa8, 0x31, +0xb6, 0x06, 0x3e, 0x59, 0x83, 0x5c, 0xa0, 0xaa, 0xb4, 0x25, 0x9e, 0x91, 0xa8, 0xaa, 0xd9, 0x05, +0xa0, 0x0b, 0x49, 0xfc, 0x0f, 0x63, 0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x60, 0xda, 0x80, 0xe0, 0xc1, 0x10, 0x80, 0x01, +0x49, 0xfc, 0x0f, 0x54, 0x44, 0x10, 0x03, 0xe8, 0x42, 0x13, 0x84, 0x24, 0x44, 0x20, 0x7f, 0xff, +0x98, 0x4a, 0x3c, 0x0c, 0x60, 0xda, 0x92, 0x2f, 0x49, 0xfc, 0x11, 0x64, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x49, 0xfc, 0x0d, 0x01, 0x81, 0x20, +0x46, 0x07, 0xff, 0xff, 0x58, 0x00, 0x0f, 0xff, 0x3e, 0x19, 0x83, 0x5c, 0x41, 0xc4, 0x80, 0x00, +0x15, 0xc0, 0x80, 0x04, 0x80, 0xe1, 0xb4, 0xc1, 0x46, 0x10, 0x01, 0xe0, 0x88, 0x29, 0xf1, 0x81, +0xd5, 0x42, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x01, 0x3c, 0x49, 0xfc, +0x19, 0xe7, 0xa0, 0x32, 0x40, 0x14, 0x80, 0x01, 0x4e, 0x15, 0x00, 0x2e, 0x80, 0x06, 0x84, 0x20, +0x3e, 0x28, 0xf6, 0x40, 0x44, 0x30, 0x00, 0xd7, 0x49, 0xfc, 0x19, 0xda, 0xb4, 0x06, 0x84, 0x20, +0x40, 0x00, 0x80, 0x06, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x01, 0x40, 0x49, 0xfc, 0x19, 0xd0, +0x80, 0x06, 0x49, 0xff, 0xff, 0x75, 0xa4, 0x36, 0xc0, 0x0e, 0x9e, 0x01, 0xac, 0x36, 0xf0, 0x01, +0xa8, 0x32, 0xa0, 0x39, 0xa9, 0xb9, 0xb6, 0xe6, 0xa8, 0x31, 0xb6, 0xc0, 0xa0, 0x3a, 0x9c, 0x01, +0xa8, 0x3a, 0xd5, 0x06, 0xa0, 0xb6, 0xc2, 0x04, 0xa0, 0x75, 0xa0, 0x34, 0xdd, 0x22, 0x15, 0xc3, +0x80, 0x04, 0xd5, 0x08, 0xa0, 0x7c, 0x9a, 0x41, 0x4e, 0x15, 0x00, 0x03, 0xd5, 0x02, 0xa8, 0x3c, +0x81, 0x06, 0xb4, 0xc8, 0x3e, 0x89, 0x83, 0x5c, 0x4c, 0x64, 0x7f, 0xbd, 0xb4, 0xa6, 0xd6, 0x10, +0xa0, 0x34, 0x84, 0x20, 0x40, 0x04, 0x80, 0x01, 0x92, 0x1f, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, +0x01, 0x60, 0x49, 0xfc, 0x19, 0x9d, 0xa0, 0x34, 0x8a, 0x09, 0x49, 0xff, 0xff, 0x7b, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x44, 0x80, +0xea, 0x60, 0x80, 0xe1, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x00, 0xf4, 0x80, 0xc0, +0x49, 0xfc, 0x19, 0x86, 0xe3, 0x07, 0xe8, 0x1b, 0x46, 0x0e, 0xa5, 0xf1, 0x58, 0x00, 0x05, 0xa1, +0x40, 0x03, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, 0x00, 0xfc, 0x49, 0xfc, +0x19, 0x77, 0x40, 0x03, 0xa0, 0x37, 0x44, 0x1f, 0x15, 0xa0, 0x96, 0x01, 0x42, 0x70, 0x04, 0x73, +0xac, 0x36, 0xcf, 0x07, 0x9e, 0x01, 0xac, 0x36, 0x80, 0xe8, 0xd5, 0x03, 0x84, 0x00, 0xac, 0x36, +0x44, 0x00, 0xff, 0xff, 0x40, 0x03, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x28, 0xf6, 0x24, 0x44, 0x30, +0x01, 0x0a, 0x40, 0x93, 0xbc, 0x08, 0x49, 0xfc, 0x19, 0x5b, 0x50, 0x94, 0x83, 0xe7, 0x44, 0x00, +0x03, 0xe8, 0x40, 0x94, 0x80, 0x17, 0x3e, 0x79, 0x83, 0x5c, 0x49, 0xfc, 0x0c, 0x51, 0x40, 0x84, +0x80, 0x00, 0xb4, 0xa7, 0xd7, 0x06, 0xa0, 0x3c, 0x40, 0x04, 0x00, 0x01, 0x4e, 0x04, 0x00, 0x07, +0x3c, 0x8e, 0x60, 0xdb, 0x80, 0x09, 0x49, 0xff, 0xff, 0x25, 0x14, 0x83, 0x00, 0x02, 0x84, 0x20, +0x80, 0x06, 0x3e, 0x28, 0xf6, 0x40, 0x44, 0x30, 0x00, 0xd7, 0x49, 0xfc, 0x19, 0x39, 0xb4, 0x26, +0xc9, 0x0a, 0x3c, 0x0c, 0x60, 0xd8, 0xa9, 0xb9, 0xb6, 0xe6, 0xa8, 0x31, 0xb6, 0xc0, 0xa0, 0x3a, +0x9c, 0x01, 0xa8, 0x3a, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x3e, 0x69, 0x83, 0x5c, 0x84, 0xe0, 0xa0, 0x33, 0x80, 0x27, 0x3e, 0x28, 0xf6, 0x24, +0x44, 0x30, 0x00, 0x88, 0xb6, 0xc6, 0xa9, 0xb1, 0xa9, 0xf2, 0x49, 0xfc, 0x19, 0x19, 0xa0, 0x33, +0x49, 0x00, 0x35, 0x3c, 0xa9, 0xf3, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3e, 0x69, 0x83, 0x5c, 0xa1, 0xf3, 0x84, 0x20, 0xa8, 0x72, +0xb6, 0xc6, 0xa9, 0xb1, 0xcf, 0x0c, 0x49, 0xfc, 0x0d, 0x41, 0x80, 0x27, 0x3e, 0x28, 0xf6, 0x24, +0x44, 0x30, 0x00, 0x59, 0xa8, 0x33, 0x49, 0xfc, 0x18, 0xfb, 0xd5, 0x05, 0x80, 0x07, 0x49, 0xfc, +0x0e, 0x35, 0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x84, 0x20, 0x80, 0xc0, 0x3e, 0x28, 0xf6, 0x5c, 0x40, 0x00, 0x80, 0x06, 0x44, 0x30, +0x00, 0x8b, 0x49, 0xfc, 0x18, 0xe5, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfc, 0x06, 0x59, 0xa0, 0x32, +0xc8, 0x02, 0xd5, 0x06, 0x9e, 0x01, 0xa8, 0x32, 0x80, 0x06, 0x49, 0x00, 0x00, 0x71, 0x80, 0xc0, +0xf0, 0x01, 0x49, 0xfc, 0x06, 0x63, 0x80, 0x06, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x84, 0x40, 0x80, 0xc0, 0x44, 0x30, 0x00, 0x6e, 0x40, 0x01, +0x00, 0x06, 0x80, 0xe1, 0x80, 0x22, 0x3e, 0x28, 0xf6, 0x5c, 0x49, 0xfc, 0x18, 0xc1, 0x50, 0x0f, +0x80, 0x04, 0x49, 0xfc, 0x06, 0x35, 0xa0, 0x72, 0x80, 0x06, 0x9c, 0x49, 0xa8, 0x72, 0x80, 0x27, +0x49, 0x00, 0x00, 0x92, 0xf0, 0x01, 0x49, 0xfc, 0x06, 0x41, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x09, 0x83, 0x70, 0x49, 0x00, 0x00, 0xa6, +0x3e, 0x79, 0x3d, 0xe8, 0x3e, 0x69, 0x7a, 0xd8, 0xa9, 0xf2, 0x80, 0x26, 0x3e, 0x09, 0x83, 0x70, +0x49, 0xff, 0xff, 0xd0, 0x50, 0x73, 0x86, 0x40, 0x3e, 0x59, 0x63, 0x68, 0x8c, 0xd8, 0xdf, 0xf5, +0x3e, 0x09, 0x83, 0x80, 0x49, 0x00, 0x00, 0x92, 0x3e, 0x79, 0x63, 0x68, 0x3e, 0x69, 0x7b, 0x68, +0xa9, 0xf2, 0x80, 0x26, 0x3e, 0x09, 0x83, 0x80, 0x49, 0xff, 0xff, 0xbc, 0x50, 0x73, 0x80, 0xc8, +0x3e, 0x59, 0x7a, 0xd8, 0x8c, 0xd8, 0xdf, 0xf5, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x20, 0x80, 0xc0, 0x3e, 0x28, 0xf6, 0x74, 0x40, 0x00, 0x80, 0x06, +0x44, 0x30, 0x00, 0x7f, 0x49, 0xfc, 0x18, 0x74, 0x92, 0x00, 0xa0, 0x31, 0xb4, 0x26, 0xb6, 0x20, +0xb4, 0x06, 0xa1, 0xb1, 0xa9, 0x81, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x84, 0xe0, 0x81, 0x00, 0x80, 0x27, 0x40, 0x03, 0x80, 0x06, 0x3e, 0x28, 0xf6, 0x74, 0x44, 0x30, +0x00, 0x91, 0x49, 0xfc, 0x18, 0x5d, 0xb4, 0xc8, 0x4c, 0x64, 0x40, 0x04, 0x80, 0xc7, 0xd5, 0x04, +0x80, 0x06, 0x49, 0xff, 0xff, 0xd7, 0x80, 0x06, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0xbc, 0x84, 0xc0, 0x80, 0xe0, 0x81, 0x21, 0x81, 0x02, 0x40, 0x03, 0x00, 0x06, +0x80, 0x26, 0x3e, 0x28, 0xf6, 0x74, 0x44, 0x30, 0x00, 0x49, 0x49, 0xfc, 0x18, 0x41, 0x40, 0x03, +0x24, 0x06, 0x80, 0x26, 0x3e, 0x28, 0xf6, 0x74, 0x44, 0x30, 0x00, 0x4a, 0x49, 0xfc, 0x18, 0x38, +0x40, 0x03, 0x20, 0x06, 0x80, 0x26, 0x3e, 0x28, 0xf6, 0x74, 0x44, 0x30, 0x00, 0x4b, 0x49, 0xfc, +0x18, 0x2f, 0x14, 0x93, 0x80, 0x01, 0xb7, 0x07, 0xb6, 0xe9, 0x14, 0x74, 0x00, 0x01, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x84, 0xc0, 0x80, 0xe0, 0x81, 0x01, +0x40, 0x03, 0x00, 0x06, 0x80, 0x26, 0x3e, 0x28, 0xf6, 0x74, 0x44, 0x30, 0x00, 0x6f, 0x49, 0xfc, +0x18, 0x17, 0x40, 0x03, 0x20, 0x06, 0x80, 0x26, 0x44, 0x30, 0x00, 0x70, 0x3e, 0x28, 0xf6, 0x74, +0x49, 0xfc, 0x18, 0x0e, 0xa0, 0x79, 0x80, 0x08, 0x80, 0x47, 0x49, 0xff, 0xff, 0xbb, 0x92, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x20, 0x80, 0xc0, +0x3e, 0x28, 0xf6, 0x74, 0x40, 0x00, 0x80, 0x06, 0x44, 0x30, 0x00, 0x29, 0x49, 0xfc, 0x17, 0xf8, +0x92, 0x00, 0xa9, 0xb1, 0xb6, 0xc6, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x00, 0x80, +0x58, 0x21, 0x00, 0x50, 0x46, 0x50, 0x04, 0x00, 0x98, 0xc2, 0x58, 0x52, 0x82, 0x7c, 0x94, 0x03, +0x84, 0x40, 0x94, 0xdb, 0x99, 0x05, 0xb6, 0x44, 0xb6, 0x43, 0x50, 0x22, 0xff, 0xf4, 0x44, 0x30, +0x00, 0xff, 0xb4, 0x82, 0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, +0xb6, 0x62, 0x96, 0x48, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, +0xd5, 0x03, 0xb4, 0x22, 0x94, 0xdf, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x02, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x30, 0x00, 0x80, 0x58, 0x31, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, +0x98, 0x83, 0x58, 0x42, 0x02, 0x7c, 0x94, 0x03, 0x98, 0xc4, 0x44, 0x41, 0x00, 0x00, 0xb6, 0x83, +0x94, 0x93, 0x84, 0x60, 0xb6, 0x62, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x44, 0x30, +0x00, 0xff, 0xb4, 0x82, 0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, +0xb6, 0x62, 0x96, 0x48, 0x84, 0xa1, 0xd9, 0x05, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, +0xb4, 0x22, 0x94, 0xef, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, +0x46, 0x40, 0x04, 0x00, 0x46, 0x20, 0x30, 0x70, 0x80, 0x64, 0x58, 0x21, 0x03, 0x07, 0x14, 0x22, +0x00, 0x9d, 0x14, 0x21, 0x80, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x94, 0x03, +0x44, 0x30, 0x00, 0xff, 0xb4, 0x82, 0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, +0x90, 0x02, 0xb6, 0x62, 0x96, 0x48, 0x84, 0xa1, 0xd9, 0x05, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x86, +0xd5, 0x04, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x84, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, +0xb6, 0x02, 0xdd, 0x9e, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x41, 0x90, 0x04, 0x40, 0x21, 0x40, 0x08, +0x46, 0x50, 0x00, 0x80, 0x40, 0x22, 0x08, 0x04, 0x58, 0x52, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, +0x98, 0xc5, 0x58, 0x42, 0x02, 0x7c, 0x94, 0x03, 0x99, 0x44, 0xb6, 0x45, 0x94, 0xdb, 0x84, 0x40, +0xb6, 0x43, 0x50, 0x22, 0x7f, 0xf4, 0x44, 0x30, 0x00, 0xff, 0xb4, 0x82, 0x40, 0x31, 0x80, 0x0c, +0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, 0x96, 0x48, 0x84, 0xa1, 0xb6, 0x62, 0xd9, 0x05, +0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xef, 0x40, 0x01, 0x80, 0x0c, +0x40, 0x00, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, +0x00, 0x19, 0x96, 0x48, 0x80, 0x62, 0x84, 0x81, 0x49, 0xff, 0xff, 0xc6, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x32, 0x96, 0x48, +0x44, 0x30, 0x00, 0x46, 0x84, 0x81, 0x49, 0xff, 0xff, 0xb7, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x32, 0x96, 0x48, +0x84, 0x6a, 0x84, 0x81, 0x49, 0xff, 0xff, 0xa8, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x84, 0xa2, 0x80, 0xc0, 0xd1, 0x18, 0x84, 0xa3, 0xd1, 0x1a, 0x84, 0xa1, +0xd9, 0x1b, 0x49, 0xff, 0xff, 0x15, 0x80, 0x46, 0x3e, 0x09, 0x7e, 0x38, 0x46, 0x10, 0x00, 0x81, +0x58, 0x10, 0x83, 0x20, 0x84, 0x62, 0x49, 0xff, 0xfc, 0x89, 0x3e, 0x09, 0x7e, 0x38, 0x44, 0x10, +0x0b, 0xb8, 0x49, 0xff, 0xfd, 0x63, 0xd5, 0x08, 0x84, 0x20, 0x49, 0xff, 0xff, 0x5b, 0xd5, 0x04, +0x84, 0x21, 0x49, 0xff, 0xfe, 0xfd, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xec, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x40, 0x05, 0x84, 0x61, 0xf3, 0x82, 0xd5, 0x08, +0x95, 0x51, 0xd1, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xba, 0x84, 0xa2, 0xf5, 0x82, 0x46, 0x11, +0x11, 0x10, 0x47, 0xc0, 0x10, 0x00, 0x58, 0x10, 0x81, 0x90, 0x59, 0xce, 0x00, 0x01, 0x85, 0x40, +0x46, 0x80, 0x04, 0x00, 0xf1, 0x81, 0x15, 0xcf, 0x80, 0x03, 0x58, 0x84, 0x02, 0x70, 0x83, 0x8a, +0x81, 0x40, 0x80, 0x6a, 0xa3, 0x99, 0x3e, 0x08, 0xf6, 0x88, 0xb4, 0xe3, 0x80, 0x26, 0x80, 0x47, +0x49, 0xfc, 0x18, 0x62, 0xe6, 0xc4, 0x4e, 0xf2, 0x00, 0x91, 0x96, 0x79, 0x84, 0xa5, 0xd1, 0x39, +0xe6, 0x26, 0xe8, 0x10, 0x84, 0xa2, 0xd1, 0x27, 0xe6, 0x23, 0xe8, 0x06, 0xc1, 0x19, 0x84, 0xa1, +0x4c, 0x12, 0xc0, 0x84, 0xd5, 0x1b, 0x84, 0xa3, 0xd1, 0x23, 0x84, 0xa4, 0x4c, 0x12, 0xc0, 0x7e, +0xd5, 0x23, 0x8c, 0xab, 0xd1, 0x39, 0xe6, 0x31, 0xe8, 0x06, 0x84, 0xa6, 0xd1, 0x2b, 0x84, 0xa7, +0xd9, 0x74, 0xd5, 0x2d, 0x9d, 0x69, 0xd1, 0x4e, 0x9d, 0x69, 0xd9, 0x6f, 0xd5, 0x5a, 0x80, 0x06, +0x84, 0x21, 0x49, 0xff, 0xfe, 0xd1, 0x48, 0x00, 0x00, 0x69, 0x80, 0x06, 0x49, 0xff, 0xfe, 0xa0, +0x48, 0x00, 0x00, 0x64, 0x80, 0x06, 0x84, 0x20, 0x49, 0xff, 0xfe, 0xf4, 0xd5, 0x5e, 0x84, 0x21, +0x44, 0x20, 0x00, 0x32, 0xd5, 0x09, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xff, 0x47, 0xd5, 0x55, +0x84, 0x21, 0x44, 0x20, 0x00, 0x11, 0x80, 0x06, 0x80, 0x62, 0x80, 0x81, 0x49, 0xff, 0xff, 0x0c, +0xd5, 0x4c, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xff, 0x57, 0xd5, 0x47, 0x80, 0x06, 0x84, 0x21, +0x49, 0xff, 0xff, 0x42, 0xd5, 0x42, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x80, 0x50, 0x46, 0x20, +0x04, 0x00, 0xf3, 0x01, 0x98, 0x31, 0x58, 0x21, 0x02, 0x7c, 0x95, 0xb3, 0x98, 0x72, 0xb6, 0x61, +0x94, 0x03, 0xf4, 0x03, 0xb6, 0x80, 0x44, 0x50, 0x00, 0x82, 0xb4, 0x08, 0x40, 0x62, 0x98, 0x0c, +0x92, 0x08, 0x40, 0x00, 0x20, 0x08, 0xb6, 0x08, 0xb4, 0x08, 0x40, 0x63, 0x00, 0x04, 0xb6, 0xc8, +0xd5, 0x24, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xfe, 0x87, 0x80, 0x46, 0x3e, 0x09, 0x7e, 0x38, +0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x83, 0x20, 0x84, 0x61, 0x49, 0xff, 0xfb, 0xcf, 0xd5, 0x0f, +0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xfe, 0x78, 0x80, 0x46, 0x3e, 0x09, 0x7e, 0x38, 0x46, 0x10, +0x00, 0x81, 0x58, 0x10, 0x83, 0x20, 0x84, 0x63, 0x49, 0xff, 0xfb, 0xc0, 0x3e, 0x09, 0x7e, 0x38, +0x44, 0x10, 0x13, 0x88, 0x49, 0xff, 0xfc, 0x9a, 0xf0, 0x02, 0x51, 0xce, 0x00, 0x01, 0x8d, 0x48, +0x40, 0xfe, 0x00, 0x06, 0x4e, 0xf3, 0xff, 0x5f, 0x84, 0x00, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3c, 0x1c, 0x33, 0xef, 0x2e, 0x00, 0xda, 0x10, 0x40, 0x00, 0x80, 0x04, +0x96, 0x00, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x3e, 0x89, +0x8c, 0xb8, 0x44, 0x75, 0xa3, 0xc4, 0x84, 0x20, 0x44, 0x20, 0x01, 0x44, 0x80, 0x08, 0xdd, 0x27, +0x84, 0x20, 0x44, 0x20, 0x01, 0x94, 0x50, 0x04, 0x7e, 0x6c, 0xdd, 0x27, 0x84, 0x20, 0x84, 0x46, +0x3e, 0x09, 0x8e, 0x64, 0xdd, 0x27, 0x84, 0x40, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x0c, 0x58, +0x80, 0x62, 0x50, 0x04, 0x01, 0x58, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x88, 0xec, 0xdd, 0x26, +0x84, 0x40, 0x50, 0x04, 0x01, 0x74, 0x80, 0x62, 0x46, 0x10, 0x00, 0x82, 0x58, 0x10, 0x88, 0x60, +0xdd, 0x26, 0x84, 0x40, 0x80, 0x62, 0x3e, 0x09, 0x89, 0xd0, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, +0x85, 0x14, 0xdd, 0x26, 0x84, 0x40, 0x80, 0x62, 0x3e, 0x09, 0x89, 0xec, 0x46, 0x10, 0x00, 0x81, +0x58, 0x10, 0x87, 0x64, 0xdd, 0x26, 0x85, 0x25, 0x3e, 0x59, 0x8e, 0x6c, 0x84, 0x20, 0x3e, 0x49, +0x8a, 0x58, 0x85, 0x01, 0x10, 0x92, 0x80, 0x04, 0x44, 0x90, 0x00, 0x64, 0x10, 0x82, 0x02, 0x66, +0x14, 0x92, 0x80, 0x02, 0x10, 0x12, 0x80, 0x0d, 0x14, 0x12, 0x00, 0xfe, 0x12, 0x12, 0x01, 0xda, +0x12, 0x12, 0x01, 0xdb, 0x10, 0x12, 0x03, 0xa4, 0x10, 0x12, 0x03, 0xf0, 0x10, 0x82, 0x03, 0xf1, +0x10, 0x12, 0x03, 0xf2, 0x10, 0x12, 0x03, 0xa5, 0xae, 0x68, 0x10, 0x12, 0x80, 0x0e, 0x10, 0x12, +0x80, 0x0f, 0xae, 0x6d, 0x40, 0x24, 0x90, 0x08, 0x3e, 0x09, 0x83, 0x90, 0xdd, 0x27, 0x46, 0x00, +0x04, 0x00, 0x46, 0x11, 0x23, 0x40, 0x58, 0x10, 0x87, 0x25, 0x14, 0x10, 0x00, 0xa1, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3e, 0x08, +0xf6, 0xa4, 0x3e, 0x18, 0xfa, 0xf8, 0x49, 0xff, 0xfa, 0xed, 0x92, 0x00, 0x46, 0x00, 0x04, 0x11, +0xa0, 0x41, 0x58, 0x10, 0x80, 0x0c, 0xa8, 0x41, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0xa0, 0xc4, 0x84, 0xa0, 0xa7, 0xdc, 0xa6, 0x1d, 0x40, 0x73, 0xa0, 0x08, +0xa6, 0x9e, 0x40, 0x73, 0x80, 0x04, 0x44, 0x00, 0x00, 0x28, 0xc2, 0x13, 0x44, 0x40, 0x00, 0x2b, +0x4c, 0x22, 0x00, 0x10, 0x44, 0x80, 0x00, 0x2c, 0x4c, 0x24, 0x00, 0x0c, 0x8c, 0x88, 0x4c, 0x22, +0x00, 0x09, 0x8d, 0x0f, 0x4c, 0x24, 0x40, 0x03, 0xd5, 0x22, 0x8c, 0x89, 0x4c, 0x22, 0x40, 0x22, +0xe2, 0xa7, 0xe8, 0x18, 0x44, 0x80, 0x00, 0x2c, 0x99, 0x98, 0x4c, 0x24, 0x40, 0x07, 0xa5, 0x31, +0x92, 0x83, 0xcc, 0x17, 0x84, 0x88, 0xd5, 0x0a, 0x8d, 0x07, 0xa7, 0x31, 0x4c, 0x24, 0x40, 0x05, +0x9d, 0x22, 0x95, 0x22, 0xd5, 0x03, 0x9d, 0x21, 0x95, 0x23, 0x99, 0x6c, 0xa6, 0xb0, 0x98, 0x04, +0xd5, 0xd5, 0x3e, 0x08, 0xf6, 0xb0, 0x49, 0xff, 0xfa, 0xa5, 0x92, 0x00, 0x84, 0x1f, 0xd5, 0x02, +0xae, 0x88, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xc0, 0x81, 0x00, +0x81, 0x41, 0x81, 0x22, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x80, 0x1f, 0x49, 0xfe, 0xc6, 0x7c, +0x50, 0x14, 0x00, 0x08, 0x44, 0x20, 0x00, 0x10, 0x80, 0x1f, 0x49, 0xfe, 0xc6, 0x55, 0x44, 0x20, +0x00, 0x10, 0x50, 0x14, 0x00, 0x18, 0x40, 0x0f, 0x88, 0x00, 0x49, 0xfe, 0xc6, 0x4d, 0x02, 0x34, +0x00, 0x02, 0x80, 0x2a, 0x40, 0x21, 0xa0, 0x09, 0x40, 0x01, 0xa0, 0x08, 0x40, 0x00, 0x08, 0x04, +0x96, 0x01, 0x44, 0x20, 0xff, 0x00, 0x40, 0x30, 0x08, 0x02, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x00, +0x60, 0x08, 0x40, 0x31, 0x80, 0x04, 0xf3, 0x88, 0x80, 0x49, 0x44, 0x30, 0x00, 0x3a, 0x50, 0x0f, +0x80, 0x28, 0x10, 0x3f, 0x80, 0x27, 0x80, 0xdf, 0x49, 0xfe, 0xc6, 0x2e, 0x50, 0x3f, 0x80, 0x40, +0x84, 0x20, 0x0a, 0x03, 0x00, 0x01, 0x40, 0x20, 0x20, 0x09, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, +0x08, 0x04, 0x96, 0x01, 0x98, 0x48, 0x4c, 0x61, 0xff, 0xf6, 0xd5, 0x02, 0x98, 0x50, 0x40, 0x00, +0xc0, 0x09, 0x96, 0x89, 0xc8, 0xfc, 0x40, 0x00, 0x84, 0x05, 0x96, 0x01, 0xec, 0x40, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xfb, 0xf4, 0x6d, 0x84, 0x00, +0x49, 0x00, 0x2f, 0xec, 0x49, 0xfb, 0xf4, 0x70, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, 0x49, 0x00, 0x31, 0xde, 0x3e, 0x09, 0x83, 0x70, +0x49, 0xff, 0xfb, 0xe6, 0x81, 0x00, 0xc8, 0x08, 0x3e, 0x08, 0xf6, 0xd0, 0x3e, 0x18, 0xfb, 0x08, +0x49, 0xff, 0xfa, 0x28, 0xd5, 0x50, 0x3e, 0x79, 0x8a, 0x58, 0x02, 0x53, 0x81, 0xdb, 0xa1, 0x82, +0x50, 0x33, 0x82, 0x45, 0x9d, 0x69, 0x54, 0x52, 0x8f, 0xff, 0x80, 0x83, 0x80, 0x06, 0x84, 0x24, +0x84, 0x41, 0x12, 0x53, 0x81, 0xdb, 0x49, 0x00, 0x14, 0xe1, 0x84, 0x80, 0xaf, 0x32, 0xaf, 0x33, +0x00, 0x13, 0x00, 0x16, 0x00, 0x03, 0x83, 0xb6, 0x54, 0x10, 0x80, 0x0f, 0x54, 0x00, 0x00, 0x0f, +0x94, 0x04, 0x40, 0x00, 0x80, 0x04, 0x10, 0x03, 0x00, 0x16, 0xa6, 0x70, 0xa6, 0x31, 0x84, 0xb3, +0x02, 0x23, 0x81, 0xdb, 0x40, 0x10, 0x94, 0x02, 0x54, 0x34, 0x80, 0x01, 0x94, 0xdc, 0x42, 0x00, +0x10, 0x09, 0x40, 0x00, 0x0c, 0x04, 0x92, 0x44, 0x58, 0x10, 0x80, 0x08, 0x10, 0x23, 0x00, 0x17, +0xae, 0x31, 0xae, 0x70, 0x00, 0x03, 0x83, 0xf1, 0xc8, 0x04, 0x44, 0x20, 0x00, 0x18, 0xd5, 0x0e, +0x54, 0x10, 0x80, 0x0f, 0x44, 0x2f, 0xff, 0xc0, 0x40, 0x00, 0x88, 0x04, 0x80, 0x26, 0x18, 0x00, +0x80, 0x18, 0x44, 0x20, 0x00, 0x1a, 0xaf, 0x09, 0xaf, 0x08, 0x80, 0x26, 0x80, 0x68, 0x84, 0x00, +0x49, 0x00, 0x17, 0x84, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x2e, 0x11, 0x8e, 0x58, 0xc1, 0x47, 0x2e, 0x01, 0x8c, 0xb8, 0xc0, 0x44, 0x49, 0x00, +0x14, 0x5d, 0x80, 0xc0, 0x3c, 0x0c, 0x4e, 0xa5, 0xe2, 0xc0, 0xe8, 0x0a, 0x3c, 0x1c, 0x4e, 0xa6, +0x3e, 0x08, 0xf6, 0xec, 0x80, 0x46, 0x49, 0xff, 0xf9, 0xbd, 0x3c, 0x6e, 0x4e, 0xa6, 0x2e, 0x01, +0x3a, 0x60, 0x3c, 0x6e, 0x4e, 0xa5, 0x84, 0xa1, 0xd0, 0x2e, 0x3e, 0x09, 0x8e, 0x6c, 0xa6, 0x40, +0x84, 0xa1, 0xd9, 0x11, 0xa6, 0x45, 0xc9, 0x27, 0x3c, 0x1c, 0x4e, 0xa6, 0x50, 0x23, 0x00, 0xc8, +0xe2, 0x41, 0xe9, 0x21, 0x3c, 0x1c, 0x63, 0x94, 0x42, 0x10, 0xf0, 0x0b, 0xc9, 0x18, 0x00, 0x00, +0x00, 0x0e, 0xd5, 0x13, 0xc9, 0x18, 0x3c, 0x0c, 0x4e, 0xa6, 0x50, 0x13, 0x00, 0xc8, 0xe2, 0x20, +0xe9, 0x12, 0x3e, 0x08, 0xf7, 0x18, 0x49, 0xff, 0xf9, 0x95, 0x3c, 0x0c, 0x63, 0x94, 0x46, 0x11, +0x00, 0x00, 0x40, 0x00, 0x04, 0x02, 0xc8, 0x03, 0x49, 0xff, 0xff, 0x54, 0x50, 0x63, 0x27, 0x10, +0x3c, 0x6e, 0x4e, 0xa6, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xff, 0xff, 0xad, 0x3e, 0x09, 0x8e, 0x10, 0x44, 0x10, 0x01, 0x5e, 0x49, 0xff, +0xfa, 0x8d, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0x3e, 0x08, 0xf7, 0x30, 0x49, 0xff, 0xf9, 0x6e, 0x49, 0x00, 0x31, 0x16, 0x3e, 0x09, 0x83, 0x70, +0x49, 0xff, 0xfb, 0x1e, 0x80, 0xe0, 0xc8, 0x08, 0x3e, 0x08, 0xf6, 0xd0, 0x3e, 0x18, 0xfb, 0x18, +0x49, 0xff, 0xf9, 0x60, 0xd5, 0x35, 0xa1, 0x82, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x80, 0x06, +0x49, 0xfe, 0xc5, 0x42, 0xa6, 0x70, 0xa6, 0x31, 0x44, 0x2f, 0xff, 0xa4, 0x54, 0x10, 0x80, 0x03, +0x40, 0x10, 0x88, 0x04, 0x58, 0x00, 0x00, 0x10, 0xae, 0x70, 0xae, 0x31, 0x3e, 0x19, 0x8a, 0x58, +0x02, 0x00, 0x81, 0x29, 0x44, 0x2f, 0xc0, 0x00, 0x40, 0x00, 0x08, 0x04, 0x96, 0x01, 0x40, 0x20, +0x20, 0x09, 0xae, 0xb3, 0xae, 0x32, 0x50, 0x10, 0x82, 0x45, 0x84, 0x46, 0x9c, 0x34, 0x49, 0xfe, +0xc5, 0x03, 0x3e, 0x19, 0x8e, 0x64, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x49, 0xfe, 0xc4, 0xfc, +0x80, 0x26, 0x80, 0x67, 0x84, 0x00, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x16, 0xa1, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xfd, 0xad, 0xc0, 0x0a, +0x84, 0x01, 0x84, 0x20, 0x49, 0xfe, 0xab, 0xbc, 0x3c, 0x2d, 0xfc, 0x0e, 0x84, 0x22, 0x84, 0x01, +0xdd, 0x22, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xbc, 0xb6, 0x1f, 0x83, 0x81, 0x81, 0x02, 0xf3, 0x81, 0x49, 0x00, 0x30, 0xb5, 0x3e, 0x09, +0x83, 0x70, 0x49, 0xff, 0xfa, 0xbd, 0x81, 0x40, 0xc8, 0x07, 0x3e, 0x08, 0xf7, 0x44, 0x49, 0xff, +0xf9, 0x01, 0x48, 0x00, 0x00, 0x89, 0x04, 0x90, 0x00, 0x02, 0x50, 0x6f, 0x80, 0x08, 0x84, 0x20, +0x44, 0x20, 0x05, 0xdc, 0x80, 0x09, 0x49, 0xfe, 0xc4, 0xdf, 0x84, 0x20, 0x44, 0x20, 0x00, 0x28, +0x80, 0x06, 0x49, 0xfe, 0xc4, 0xd9, 0xa6, 0x33, 0x44, 0x3f, 0xf0, 0x0f, 0x54, 0x00, 0x00, 0x0f, +0x58, 0x00, 0x00, 0x60, 0xae, 0x33, 0x46, 0x40, 0x0f, 0x00, 0xa4, 0x31, 0x40, 0x00, 0x0c, 0x02, +0xac, 0x31, 0x44, 0x20, 0x00, 0x10, 0xb4, 0x66, 0x80, 0x28, 0x40, 0x01, 0x90, 0x02, 0x92, 0x08, +0x92, 0x78, 0x40, 0x31, 0x80, 0x04, 0xb6, 0x66, 0x44, 0x30, 0x18, 0x00, 0xac, 0xf2, 0x44, 0x30, +0x00, 0x3a, 0xae, 0xf6, 0x84, 0x7f, 0xae, 0xf7, 0x44, 0x85, 0xa3, 0x84, 0x40, 0x0f, 0x88, 0x00, +0xdd, 0x28, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x10, 0x51, 0xc4, 0x80, 0x0e, 0x50, 0x0f, 0x80, 0x20, +0xdd, 0x28, 0x80, 0x26, 0x80, 0x1c, 0x44, 0x20, 0x00, 0x28, 0xdd, 0x28, 0x50, 0x64, 0x80, 0x36, +0x44, 0x0f, 0xff, 0x88, 0x84, 0xe0, 0xae, 0x30, 0x44, 0x00, 0x00, 0x40, 0xae, 0x34, 0xaf, 0xf1, +0xad, 0xf1, 0xaf, 0xf5, 0xaf, 0xf6, 0xaf, 0xf7, 0x44, 0x20, 0x00, 0x10, 0xf1, 0x01, 0x50, 0x04, +0x80, 0x3e, 0xdd, 0x28, 0x80, 0x26, 0x80, 0x1c, 0x44, 0x20, 0x00, 0x18, 0x49, 0xff, 0xfe, 0x06, +0x40, 0x10, 0x20, 0x09, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x04, 0x04, 0xac, 0x31, 0x51, 0xcf, +0x80, 0x30, 0xb4, 0x1f, 0xa0, 0x82, 0x80, 0x1c, 0x50, 0x11, 0x00, 0x10, 0x84, 0x46, 0x49, 0xfe, +0xc4, 0x65, 0x3e, 0x19, 0x8e, 0x64, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x36, 0x49, 0xfe, 0xc4, 0x5e, +0x84, 0x42, 0x3e, 0x19, 0x37, 0xa4, 0x50, 0x0f, 0x80, 0x3c, 0x49, 0xfe, 0xc4, 0x57, 0x80, 0x3c, +0x84, 0x4e, 0x80, 0x09, 0xdd, 0x28, 0x80, 0x0a, 0x80, 0x47, 0x44, 0x10, 0x00, 0x4e, 0x49, 0x00, +0x16, 0x93, 0x92, 0x00, 0xec, 0x44, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xe4, 0x81, 0x00, 0x49, 0x00, 0x30, 0x18, 0x3e, 0x09, 0x83, 0x70, 0x49, 0xff, 0xfa, 0x20, +0x81, 0x40, 0xc8, 0x06, 0x3e, 0x08, 0xf7, 0x44, 0x49, 0xff, 0xf8, 0x64, 0xd5, 0x5c, 0xa1, 0x82, +0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x80, 0x06, 0x49, 0xfe, 0xc4, 0x46, 0x50, 0x13, 0x00, 0x0e, +0x84, 0x01, 0xae, 0x09, 0x84, 0x08, 0xae, 0x0a, 0x84, 0x06, 0x85, 0x20, 0xae, 0x0c, 0x87, 0x82, +0x84, 0x04, 0xae, 0x0d, 0x11, 0xc0, 0x80, 0x07, 0x10, 0x90, 0x80, 0x00, 0x10, 0x90, 0x80, 0x03, +0x10, 0x90, 0x80, 0x06, 0x44, 0x75, 0xa3, 0x84, 0x3e, 0x19, 0x8e, 0x64, 0x84, 0x46, 0x50, 0x03, +0x00, 0x16, 0xdd, 0x27, 0x04, 0x14, 0x00, 0x04, 0x84, 0x44, 0x8c, 0x38, 0x50, 0x03, 0x00, 0x1c, +0xdd, 0x27, 0x04, 0x14, 0x00, 0x04, 0x50, 0x33, 0x00, 0x20, 0x80, 0x03, 0x8c, 0x28, 0x84, 0x46, +0xf3, 0x81, 0xdd, 0x27, 0x04, 0x14, 0x00, 0x04, 0x84, 0x44, 0x8c, 0x2e, 0x50, 0x03, 0x00, 0x26, +0xdd, 0x27, 0xf3, 0x01, 0x80, 0x23, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x08, 0x49, 0xfe, 0xc3, 0xf6, +0x3e, 0x19, 0x8e, 0x64, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x0e, 0x49, 0xfe, 0xc3, 0xef, 0x80, 0x5c, +0x3e, 0x19, 0x37, 0x98, 0x50, 0x0f, 0x80, 0x14, 0x49, 0xfe, 0xc3, 0xe8, 0x50, 0x1f, 0x80, 0x08, +0x84, 0x4e, 0x80, 0x06, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x49, 0x44, 0x10, 0x00, 0x2a, 0x49, 0x00, +0x16, 0x23, 0x92, 0x00, 0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0xa0, 0xc4, 0x81, 0x00, 0x96, 0x08, 0x84, 0x21, 0x8c, 0x78, 0x4c, 0x00, 0x80, 0x04, +0x80, 0x01, 0xd5, 0x27, 0x3e, 0x79, 0x8d, 0xc4, 0x84, 0xc0, 0x45, 0xc0, 0x00, 0x12, 0xa6, 0x38, +0xc8, 0x1b, 0x00, 0x93, 0x80, 0x01, 0x84, 0xa1, 0x4c, 0x92, 0xc0, 0x17, 0x42, 0x03, 0x70, 0x24, +0x3e, 0x29, 0x8d, 0xc6, 0x80, 0x23, 0x98, 0x02, 0x84, 0x44, 0xf3, 0x81, 0x49, 0x00, 0x12, 0x5a, +0xf3, 0x01, 0xc8, 0x0a, 0x3e, 0x08, 0xf7, 0x60, 0x49, 0xff, 0xf7, 0xdc, 0x80, 0x08, 0x49, 0xff, +0xff, 0x67, 0x80, 0x09, 0xd5, 0x06, 0x9d, 0xb1, 0x84, 0xa3, 0x8c, 0xf2, 0xde, 0xe1, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x84, 0x00, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x47, +0x9c, 0x49, 0x4c, 0x11, 0x7f, 0xfd, 0x9c, 0x01, 0x84, 0x23, 0x4c, 0x00, 0x80, 0x04, 0x84, 0x20, +0xd5, 0xf6, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x3e, 0x08, 0xf6, 0xa4, 0x3e, 0x18, 0xfa, 0xe4, +0x49, 0xff, 0xf7, 0xb8, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x41, 0x42, 0x10, 0x8c, 0x09, 0xa8, 0x41, +0x46, 0x20, 0x04, 0x10, 0x80, 0x22, 0x84, 0x00, 0x04, 0x31, 0x01, 0x0e, 0x04, 0x40, 0x82, 0x8c, +0x9c, 0x01, 0x97, 0x20, 0xcc, 0x02, 0xc3, 0x07, 0x44, 0x30, 0x01, 0x06, 0x4c, 0x01, 0xff, 0xf6, +0x48, 0x00, 0x00, 0x6d, 0x46, 0x70, 0x04, 0x11, 0x84, 0xc0, 0x04, 0x83, 0x80, 0x80, 0x54, 0x04, +0x00, 0x01, 0xc0, 0x0a, 0x49, 0xff, 0xff, 0xca, 0x84, 0xbf, 0x9d, 0xb1, 0x4c, 0x82, 0x80, 0x99, +0x44, 0x50, 0x01, 0x06, 0xde, 0xf3, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x41, 0x42, 0x10, 0x88, 0x09, +0xa8, 0x41, 0x5c, 0xf3, 0x01, 0x06, 0xe9, 0x05, 0x3e, 0x08, 0xf7, 0x88, 0x49, 0xff, 0xf7, 0x82, +0x46, 0x70, 0x04, 0x10, 0x84, 0xc0, 0x46, 0x00, 0x04, 0x10, 0x04, 0x13, 0x81, 0x0c, 0x04, 0x00, +0x01, 0x0e, 0x40, 0x00, 0x20, 0x08, 0x92, 0x18, 0xc0, 0x03, 0x84, 0x20, 0xd5, 0x04, 0x92, 0x30, +0x5c, 0x10, 0x80, 0x01, 0x46, 0x00, 0x04, 0x10, 0x04, 0x00, 0x02, 0x8d, 0x40, 0x00, 0x20, 0x08, +0x92, 0x18, 0xc8, 0x02, 0xc9, 0x1d, 0x49, 0x00, 0x2f, 0x2d, 0xd5, 0x10, 0x49, 0xff, 0xf9, 0x18, +0x00, 0x30, 0x00, 0x14, 0x80, 0x40, 0x80, 0x20, 0x3e, 0x09, 0x83, 0x70, 0xc3, 0x02, 0xd5, 0x04, +0x80, 0x22, 0x3e, 0x09, 0x83, 0x80, 0x49, 0xff, 0xf9, 0x2d, 0x3c, 0x3c, 0x62, 0xc6, 0x3e, 0x09, +0x8b, 0x10, 0xcb, 0xed, 0x9d, 0xb1, 0x44, 0x50, 0x01, 0x06, 0xde, 0xce, 0xd5, 0x31, 0x46, 0x70, +0x04, 0x11, 0x84, 0xc0, 0x04, 0x83, 0x80, 0x80, 0x9d, 0xb1, 0x54, 0x04, 0x00, 0x02, 0xc0, 0x07, +0x49, 0xff, 0xff, 0x74, 0x44, 0x50, 0x01, 0x06, 0xde, 0xf6, 0xd5, 0x3b, 0x3e, 0x08, 0xf7, 0xa8, +0x3e, 0x18, 0xfa, 0xe4, 0x49, 0xff, 0xf7, 0x36, 0xd5, 0x3b, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x02, 0x8c, 0x3e, 0x08, 0xf7, 0xb4, 0x49, 0xff, 0xf7, 0x2d, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x02, 0x8d, 0x3e, 0x08, 0xf7, 0xc8, 0x49, 0xff, 0xf7, 0x25, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x01, 0x0e, 0x3e, 0x08, 0xf7, 0xdc, 0x49, 0xff, 0xf7, 0x1d, 0x48, 0xff, 0xff, 0x7d, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x8c, 0x3e, 0x08, 0xf7, 0xb4, 0x49, 0xff, 0xf7, 0x13, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x8d, 0x3e, 0x08, 0xf7, 0xc8, 0x49, 0xff, 0xf7, 0x0b, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x01, 0x0e, 0x3e, 0x08, 0xf7, 0xec, 0x49, 0xff, 0xf7, 0x03, 0xd5, 0xb8, +0x80, 0x28, 0x3e, 0x08, 0xf8, 0x00, 0x49, 0xff, 0xf6, 0xfd, 0x92, 0x00, 0xd5, 0xc0, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x85, 0x41, 0x80, 0xe0, 0x3e, 0xa1, +0x3a, 0x61, 0x3e, 0x08, 0xf8, 0x20, 0x84, 0x60, 0x83, 0x81, 0x80, 0x27, 0x10, 0x3f, 0x80, 0x17, +0x80, 0xc2, 0x49, 0xff, 0xf6, 0xe7, 0x46, 0x00, 0x04, 0x00, 0x14, 0x70, 0x00, 0xa2, 0x3e, 0x89, +0x8a, 0x58, 0x00, 0x04, 0x03, 0xa4, 0x84, 0x21, 0x4c, 0x00, 0x81, 0xec, 0x00, 0x04, 0x03, 0xf0, +0xc8, 0x11, 0x49, 0xff, 0xff, 0x19, 0x50, 0x04, 0x03, 0xd4, 0x49, 0xff, 0xf7, 0x21, 0x50, 0x04, +0x03, 0xb8, 0x49, 0xff, 0xf7, 0x1d, 0x3e, 0x09, 0x89, 0xec, 0x49, 0xff, 0xf7, 0x19, 0x10, 0xa4, +0x03, 0xa4, 0x3d, 0xce, 0x63, 0x95, 0x3c, 0x7e, 0x63, 0x94, 0x3e, 0x09, 0x83, 0x90, 0x84, 0x20, +0x44, 0x20, 0x06, 0x40, 0x49, 0xfe, 0xc2, 0xa8, 0xc6, 0x3a, 0xa0, 0x71, 0xa6, 0x8b, 0xa6, 0x4a, +0x54, 0x21, 0x00, 0x3f, 0x40, 0x21, 0x20, 0x08, 0x40, 0x21, 0x04, 0x04, 0x3c, 0x2e, 0x4e, 0x85, +0xb4, 0x06, 0xa6, 0x01, 0x54, 0x10, 0x00, 0x40, 0xc1, 0x24, 0xa0, 0x72, 0x44, 0x20, 0x00, 0x1a, +0xa7, 0x08, 0x9e, 0xd2, 0x92, 0x84, 0x54, 0x42, 0x00, 0x08, 0x54, 0x00, 0x00, 0x10, 0x40, 0x81, +0x90, 0x1a, 0x40, 0x81, 0x10, 0x1b, 0xc0, 0x02, 0x8d, 0x04, 0x80, 0x48, 0x3e, 0x09, 0x83, 0x90, +0x49, 0xfe, 0xc2, 0x62, 0xa0, 0x72, 0x3c, 0x2c, 0x4e, 0x85, 0x3e, 0x39, 0x83, 0x90, 0x50, 0x04, +0x00, 0x02, 0x98, 0x48, 0x8a, 0x48, 0x40, 0x04, 0x0c, 0x00, 0x49, 0xfe, 0xc2, 0x55, 0xd5, 0x09, +0xa0, 0x72, 0x3e, 0x09, 0x83, 0x90, 0x49, 0xfe, 0xc2, 0x4f, 0xd5, 0x03, 0x3c, 0x6e, 0x4e, 0x85, +0x3c, 0x3d, 0xfb, 0xe5, 0x44, 0x00, 0x00, 0x19, 0x84, 0x20, 0x50, 0x2f, 0x80, 0x17, 0xdd, 0x23, +0x00, 0x1f, 0x80, 0x17, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x0b, 0xf0, 0x3e, 0x08, 0xf8, 0x30, +0xdd, 0x26, 0x00, 0xaf, 0x80, 0x17, 0x4e, 0xa3, 0x01, 0x76, 0x2e, 0x01, 0x8d, 0xfd, 0xc8, 0x15, +0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x19, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x80, 0x19, +0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x34, 0xb4, 0x20, 0x46, 0x31, 0x23, 0x40, 0x96, 0x49, +0xb6, 0x20, 0xb4, 0x20, 0x48, 0x00, 0x01, 0x3d, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x26, 0x3e, 0x08, +0xf8, 0x4c, 0xdd, 0x26, 0x3c, 0x2c, 0x4e, 0x89, 0x80, 0x27, 0xa6, 0xd0, 0x3e, 0x08, 0xf8, 0x68, +0xdd, 0x26, 0x46, 0x21, 0x00, 0x00, 0x4c, 0x71, 0x00, 0x09, 0x44, 0x30, 0x01, 0x00, 0x4c, 0x71, +0x80, 0x05, 0x94, 0x19, 0x4c, 0x70, 0x40, 0x0d, 0x3c, 0x0c, 0x4e, 0x89, 0xc0, 0x09, 0xa6, 0x00, +0x84, 0x22, 0x4c, 0x00, 0xc0, 0x06, 0x49, 0x00, 0x2c, 0x7f, 0x48, 0x00, 0x01, 0x43, 0x49, 0xff, +0xfd, 0x0b, 0x48, 0x00, 0x01, 0x3f, 0x84, 0x42, 0x4c, 0x01, 0x41, 0x05, 0x3c, 0x0c, 0x4e, 0x89, +0xc0, 0x4a, 0xa6, 0x40, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x47, 0x00, 0xa0, 0x00, 0x02, 0x4e, 0xa2, +0x00, 0x43, 0xa6, 0x03, 0x84, 0x25, 0x4c, 0x00, 0xc0, 0x3f, 0x46, 0x70, 0x04, 0x00, 0x58, 0x73, +0x82, 0x58, 0x3e, 0x08, 0xf8, 0xa8, 0xdd, 0x26, 0xb4, 0x07, 0x44, 0x2f, 0xf3, 0xff, 0x40, 0x00, +0x08, 0x02, 0xb6, 0x07, 0x46, 0x80, 0x04, 0x00, 0x58, 0x84, 0x01, 0xbc, 0xb4, 0x08, 0x44, 0x3f, +0xff, 0xdf, 0x40, 0x00, 0x0c, 0x02, 0xb6, 0x08, 0x50, 0x64, 0x7f, 0xfc, 0xb4, 0x06, 0x44, 0x10, +0x00, 0x1e, 0x40, 0x00, 0x0c, 0x02, 0xb6, 0x06, 0x44, 0x00, 0x03, 0xe8, 0x3c, 0x20, 0xc7, 0x02, +0x42, 0x01, 0x00, 0x24, 0x40, 0xa5, 0x28, 0x08, 0x40, 0x00, 0x04, 0x37, 0x49, 0xfc, 0x03, 0xa2, +0xb4, 0x28, 0x44, 0x00, 0x0c, 0x80, 0x58, 0x10, 0x80, 0x20, 0xb6, 0x28, 0xb4, 0x26, 0x58, 0x10, +0x80, 0x20, 0xb6, 0x26, 0x49, 0xfc, 0x03, 0x96, 0xb4, 0x07, 0x40, 0xa5, 0x00, 0x04, 0xb7, 0x47, +0x48, 0x00, 0x00, 0xf0, 0x3e, 0x08, 0xf8, 0xbc, 0x49, 0xff, 0xf5, 0xdc, 0x2e, 0x11, 0x8e, 0x02, +0x3c, 0x2c, 0x63, 0x80, 0x84, 0x05, 0x4c, 0x10, 0x00, 0x59, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x01, 0x20, 0x94, 0xca, 0x84, 0x8f, 0x40, 0x32, 0x0c, 0x0c, 0xb4, 0x80, 0x40, 0x31, 0x8c, 0x05, +0x40, 0x31, 0x90, 0x02, 0xb6, 0x60, 0x84, 0xe1, 0xb4, 0x60, 0x40, 0x73, 0x84, 0x0c, 0x40, 0x13, +0x8c, 0x04, 0xb6, 0x20, 0x4e, 0x24, 0x00, 0x0a, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, +0xb4, 0x20, 0x40, 0x13, 0x84, 0x04, 0xd5, 0x0a, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, +0xb4, 0x20, 0x40, 0x23, 0x9c, 0x05, 0x40, 0x11, 0x04, 0x02, 0xb6, 0x20, 0x46, 0x00, 0x04, 0x00, +0x04, 0x10, 0x00, 0x6e, 0x40, 0x93, 0x9c, 0x05, 0x40, 0x14, 0x84, 0x02, 0x46, 0x60, 0x04, 0x00, +0x14, 0x10, 0x00, 0x6e, 0x58, 0x63, 0x01, 0xbc, 0x3e, 0x89, 0x8e, 0x00, 0x44, 0x10, 0x03, 0xe8, +0x45, 0xc0, 0x00, 0x1e, 0xb4, 0x08, 0x4e, 0x04, 0x00, 0x06, 0xb4, 0x46, 0x40, 0x23, 0x88, 0x04, +0xd5, 0x04, 0xb4, 0x46, 0x40, 0x24, 0x88, 0x02, 0x96, 0x01, 0x42, 0x00, 0x04, 0x24, 0xb6, 0x46, +0x40, 0x00, 0x70, 0x57, 0xf1, 0x81, 0x8d, 0x04, 0x49, 0xfc, 0x03, 0x34, 0x3e, 0x39, 0x8e, 0x0c, +0xf1, 0x01, 0x4c, 0x81, 0xff, 0xe9, 0xd5, 0x41, 0x4e, 0x24, 0x00, 0x0a, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x64, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xd5, 0x08, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x64, 0xb4, 0x20, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x64, 0xb4, 0x20, 0x80, 0xe0, 0x58, 0x10, 0x80, 0x06, 0xb6, 0x20, 0x3e, 0x69, +0x8e, 0x00, 0x44, 0xa0, 0x03, 0xe8, 0x44, 0x90, 0x00, 0x1e, 0xb4, 0x06, 0x4e, 0x04, 0x00, 0x06, +0xb4, 0x27, 0x58, 0x10, 0x80, 0x01, 0xd5, 0x04, 0xb4, 0x27, 0x42, 0x10, 0x80, 0x09, 0x96, 0x01, +0x42, 0x00, 0x28, 0x24, 0xb6, 0x27, 0x40, 0x00, 0x24, 0x37, 0x9d, 0xb4, 0x49, 0xfc, 0x02, 0xfa, +0x3e, 0x29, 0x8e, 0x0c, 0x4c, 0x61, 0x7f, 0xeb, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x19, +0x92, 0x23, 0x94, 0x4b, 0x14, 0x10, 0x00, 0x19, 0x84, 0x02, 0x84, 0x21, 0x49, 0xff, 0xf8, 0x1c, +0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0xa3, 0x3e, 0x08, 0xf8, 0xcc, 0x49, 0xff, 0xf5, 0x32, +0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0xa4, 0x3e, 0x08, 0xf8, 0xe0, 0x49, 0xff, 0xf5, 0x2a, +0xd5, 0x38, 0x84, 0x23, 0x4c, 0x00, 0xc0, 0x11, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0xb0, +0xb4, 0x20, 0x46, 0x30, 0x02, 0x00, 0x42, 0x10, 0xf4, 0x09, 0x58, 0x31, 0x80, 0x20, 0x40, 0x10, +0x8c, 0x04, 0xb6, 0x20, 0xd5, 0x26, 0x84, 0x24, 0x4c, 0x00, 0xc0, 0x24, 0x3c, 0x2c, 0x63, 0x95, +0x3c, 0x9c, 0x63, 0x94, 0x50, 0x7f, 0x80, 0x0c, 0xa8, 0xb9, 0xb7, 0x27, 0x49, 0x00, 0x2c, 0x96, +0x80, 0xa7, 0x80, 0x2a, 0x84, 0x05, 0x80, 0x4a, 0x80, 0x6a, 0x84, 0x88, 0x49, 0x00, 0x05, 0x04, +0x80, 0xe0, 0x3e, 0x08, 0xf8, 0xf4, 0xdd, 0x26, 0xc7, 0x0c, 0x3e, 0x08, 0xf9, 0x18, 0xdd, 0x26, +0xd5, 0x08, 0x84, 0x20, 0x3c, 0x3d, 0xfb, 0xe5, 0x44, 0x00, 0x00, 0x1a, 0x80, 0x41, 0xdd, 0x23, +0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x3e, 0x48, +0xfa, 0xcc, 0x80, 0xc0, 0x3a, 0x02, 0x0c, 0x04, 0x50, 0x5f, 0x80, 0x04, 0x3a, 0x02, 0x8c, 0x24, +0x3a, 0x02, 0x04, 0x00, 0x3a, 0x02, 0x84, 0x20, 0xa0, 0x72, 0xa6, 0x08, 0x92, 0x04, 0x54, 0x00, +0x00, 0x04, 0xc0, 0x05, 0x3e, 0x08, 0xf9, 0x30, 0x48, 0x00, 0x00, 0xc8, 0xb4, 0x06, 0xa6, 0x00, +0x54, 0x00, 0x00, 0x60, 0xc0, 0x09, 0x8c, 0x2a, 0x3e, 0x09, 0x8c, 0x9d, 0x84, 0x46, 0x49, 0x00, +0x0f, 0x41, 0xc0, 0x02, 0xd5, 0x13, 0xa0, 0x32, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x40, 0xc0, 0x11, +0xb4, 0x06, 0xa6, 0x02, 0x96, 0x04, 0xc8, 0x0d, 0xa0, 0x71, 0x3e, 0x08, 0xf9, 0x40, 0xa6, 0x49, +0x92, 0x22, 0x54, 0x10, 0x80, 0x07, 0x49, 0xff, 0xf4, 0xb5, 0x84, 0x1f, 0x48, 0x00, 0x02, 0xe6, +0xb4, 0x06, 0xa6, 0x00, 0x54, 0x10, 0x00, 0x40, 0xc1, 0x03, 0x85, 0x03, 0xd5, 0x0e, 0x54, 0x10, +0x00, 0x10, 0xc1, 0x03, 0x85, 0x01, 0xd5, 0x09, 0x54, 0x00, 0x00, 0x20, 0x96, 0x00, 0x84, 0x22, +0x40, 0x80, 0x00, 0x1a, 0x40, 0x80, 0x80, 0x1b, 0x02, 0x13, 0x00, 0x0a, 0x3e, 0x08, 0xf9, 0x64, +0x49, 0xff, 0xf4, 0x98, 0xa0, 0xb4, 0x02, 0x03, 0x00, 0x0a, 0x8c, 0x58, 0x8e, 0x18, 0x12, 0x03, +0x00, 0x0a, 0xa8, 0xb4, 0xa0, 0x32, 0xa6, 0x00, 0x92, 0x04, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x1a, +0x02, 0x13, 0x00, 0x0b, 0x58, 0x10, 0x80, 0x40, 0x96, 0x49, 0x12, 0x13, 0x00, 0x0b, 0xa6, 0x10, +0x96, 0x82, 0x4e, 0x24, 0x00, 0x06, 0x58, 0x10, 0x80, 0x02, 0x12, 0x13, 0x00, 0x0b, 0xa0, 0xb4, +0x02, 0x13, 0x00, 0x0a, 0x9c, 0x92, 0x9e, 0x4a, 0xa8, 0xb4, 0x12, 0x13, 0x00, 0x0a, 0x54, 0x00, +0x00, 0x0f, 0x10, 0x03, 0x00, 0x18, 0xa0, 0x32, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x80, 0xc0, 0x16, +0x02, 0x23, 0x00, 0x0b, 0xa0, 0x74, 0x02, 0x03, 0x00, 0x0a, 0x9c, 0x4c, 0x9e, 0x04, 0x58, 0x21, +0x00, 0x08, 0xa8, 0x74, 0x12, 0x03, 0x00, 0x0a, 0x12, 0x23, 0x00, 0x0b, 0xa0, 0x71, 0x3e, 0x08, +0xf9, 0x71, 0xa6, 0x4f, 0x92, 0x25, 0x49, 0xff, 0xf4, 0x55, 0xb4, 0x06, 0xa6, 0x01, 0x54, 0x00, +0x00, 0x40, 0xc0, 0x0a, 0x02, 0x13, 0x00, 0x0b, 0xa0, 0x34, 0x58, 0x10, 0x80, 0x10, 0x9c, 0x02, +0x12, 0x13, 0x00, 0x0b, 0xa8, 0x34, 0xa0, 0x34, 0x3e, 0x19, 0x37, 0x88, 0x84, 0x46, 0x49, 0x00, +0x0e, 0xb9, 0xc0, 0x08, 0xa0, 0x34, 0x3e, 0x19, 0x37, 0x90, 0x84, 0x46, 0x49, 0x00, 0x0e, 0xb2, +0xc8, 0x2a, 0xa0, 0x74, 0x02, 0x03, 0x00, 0x0a, 0x9c, 0x4e, 0x9e, 0x06, 0xa8, 0x74, 0x12, 0x03, +0x00, 0x0a, 0x46, 0x20, 0x04, 0x00, 0x04, 0x01, 0x00, 0xa4, 0x50, 0x7f, 0x80, 0x1c, 0x9c, 0x01, +0x14, 0x01, 0x00, 0xa4, 0x84, 0x42, 0x80, 0x07, 0x49, 0xfe, 0xbf, 0xee, 0xa0, 0x74, 0x02, 0x03, +0x00, 0x0a, 0x9c, 0x4a, 0x9e, 0x02, 0x12, 0x03, 0x00, 0x0a, 0xa8, 0x74, 0x3e, 0x08, 0xf9, 0x88, +0xa6, 0xb9, 0xa6, 0x78, 0x80, 0x68, 0x49, 0xff, 0xf4, 0x15, 0x3c, 0x0c, 0x63, 0x30, 0x96, 0x04, +0xc8, 0x08, 0xd5, 0x15, 0x3e, 0x08, 0xf9, 0xac, 0x49, 0xff, 0xf4, 0x0c, 0x48, 0xff, 0xff, 0x57, +0x80, 0x06, 0x49, 0x00, 0x15, 0x11, 0x80, 0xe0, 0x84, 0xa1, 0xdf, 0x09, 0x3e, 0x08, 0xf9, 0xbc, +0x49, 0xff, 0xf4, 0x00, 0x80, 0x07, 0x80, 0x46, 0x48, 0x00, 0x01, 0x2c, 0x50, 0xaf, 0x80, 0x1c, +0x46, 0x70, 0x00, 0x84, 0x58, 0x73, 0x80, 0xe0, 0x80, 0x0a, 0x3e, 0x19, 0x37, 0x98, 0x84, 0x42, +0xdd, 0x27, 0xc8, 0x0b, 0x2e, 0x01, 0x8c, 0xba, 0x4e, 0x02, 0x02, 0x1f, 0x80, 0x06, 0x84, 0x21, +0x49, 0xff, 0xfb, 0xe6, 0x48, 0x00, 0x02, 0x19, 0x3e, 0x19, 0x37, 0xa0, 0x80, 0x0a, 0x84, 0x42, +0xdd, 0x27, 0x80, 0x20, 0x4e, 0x03, 0x01, 0x19, 0xa0, 0xf4, 0xa7, 0xd8, 0x54, 0x73, 0x80, 0x0f, +0x95, 0xfa, 0xe6, 0xf9, 0x4e, 0xf2, 0x02, 0x09, 0x00, 0x41, 0x80, 0x09, 0x44, 0x00, 0x00, 0x11, +0x98, 0x9f, 0x4c, 0x40, 0x40, 0x0c, 0xa6, 0x12, 0xa6, 0x93, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, +0x08, 0x04, 0x81, 0x21, 0x80, 0x41, 0x80, 0xa1, 0xd5, 0x16, 0x84, 0xa6, 0x4c, 0x42, 0xc1, 0xf5, +0x01, 0xc1, 0x00, 0x00, 0x00, 0x91, 0x00, 0x02, 0xa6, 0x13, 0x00, 0xa1, 0x00, 0x01, 0x41, 0xce, +0x20, 0x08, 0x40, 0x94, 0xa0, 0x08, 0x00, 0x51, 0x00, 0x0d, 0x40, 0x94, 0x80, 0x04, 0x40, 0x2e, +0x28, 0x04, 0x80, 0x01, 0x84, 0x21, 0x4c, 0x80, 0xc0, 0x6f, 0x84, 0x06, 0x4c, 0x40, 0x41, 0xdd, +0x3c, 0x1c, 0x63, 0x30, 0x54, 0x10, 0x80, 0x04, 0xc1, 0x33, 0x54, 0x52, 0x80, 0x02, 0xc5, 0x30, +0x3c, 0x00, 0xc6, 0x66, 0x4c, 0x20, 0x00, 0x03, 0xc8, 0x2b, 0x3c, 0x00, 0xc6, 0x67, 0x4c, 0x90, +0x00, 0x03, 0xc8, 0x26, 0x50, 0x11, 0x80, 0x0c, 0x3e, 0x09, 0x8c, 0xd0, 0x84, 0x44, 0x49, 0x00, +0x0e, 0x09, 0xc0, 0x09, 0x3e, 0x09, 0x8c, 0xd0, 0x3e, 0x19, 0x7e, 0x54, 0x84, 0x44, 0x49, 0x00, +0x0e, 0x01, 0xc8, 0x16, 0xa0, 0x74, 0x8c, 0x30, 0x3e, 0x09, 0x8c, 0xe0, 0x84, 0x44, 0x49, 0x00, +0x0d, 0xf9, 0xc0, 0x09, 0x3e, 0x09, 0x8c, 0xe0, 0x3e, 0x19, 0x7e, 0x54, 0x84, 0x44, 0x49, 0x00, +0x0d, 0xf1, 0xc8, 0x06, 0x80, 0x46, 0x44, 0x00, 0x10, 0x00, 0x48, 0x00, 0x00, 0xa3, 0x3e, 0x79, +0x8a, 0x58, 0x04, 0x03, 0x80, 0x9a, 0x54, 0x00, 0x40, 0x00, 0x4e, 0x02, 0x01, 0x9e, 0x02, 0x03, +0x81, 0x4c, 0xc8, 0x09, 0xa0, 0x74, 0x8c, 0x30, 0x50, 0x03, 0x82, 0x88, 0x84, 0x44, 0x49, 0x00, +0x0d, 0xd9, 0xc8, 0x09, 0x3e, 0x09, 0x8a, 0x58, 0x50, 0x10, 0x02, 0x9c, 0x02, 0x20, 0x01, 0x4d, +0x84, 0x00, 0xd5, 0x14, 0x50, 0x03, 0x82, 0x88, 0x3e, 0x19, 0x7e, 0x54, 0x84, 0x44, 0x49, 0x00, +0x0d, 0xc9, 0xc0, 0xf1, 0x48, 0x00, 0x01, 0x81, 0x0a, 0x40, 0x80, 0x01, 0x96, 0x19, 0x4c, 0x92, +0x40, 0x06, 0x80, 0x46, 0x84, 0x04, 0x48, 0x00, 0x00, 0x75, 0x9c, 0xc1, 0xe2, 0x02, 0xe9, 0xf5, +0x48, 0x00, 0x01, 0x73, 0x84, 0x22, 0x4c, 0x80, 0xc1, 0x70, 0x3e, 0x19, 0x8a, 0x58, 0x04, 0x20, +0x80, 0x9a, 0x40, 0x21, 0x40, 0x08, 0x92, 0x5f, 0x4e, 0x22, 0x01, 0x67, 0x50, 0x20, 0x82, 0xc6, +0x02, 0x40, 0x81, 0x62, 0x84, 0x20, 0xd5, 0x63, 0x0a, 0x81, 0x00, 0x01, 0x96, 0x69, 0x4c, 0x04, +0x40, 0x5f, 0x44, 0x10, 0x14, 0xe9, 0x4c, 0x00, 0xc0, 0x52, 0x2e, 0x01, 0x8c, 0xbd, 0xc0, 0x4e, +0xa0, 0x71, 0xa6, 0x0b, 0xa6, 0x4a, 0x54, 0x00, 0x00, 0x3f, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, +0x04, 0x04, 0x9a, 0x07, 0x5c, 0xf0, 0x00, 0x2d, 0xe9, 0x3c, 0x50, 0x03, 0x80, 0x14, 0x50, 0xaf, +0x80, 0x04, 0x98, 0x18, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x18, 0x49, 0x00, 0x0d, 0x83, 0x81, 0x00, +0xc8, 0x0b, 0x3e, 0x08, 0xf9, 0xd4, 0x49, 0xff, 0xf3, 0x05, 0x80, 0x46, 0x44, 0x00, 0x04, 0x00, +0x80, 0x28, 0x48, 0x00, 0x01, 0x2e, 0xa0, 0x71, 0xa6, 0x0b, 0xa6, 0x4a, 0x54, 0x00, 0x00, 0x3f, +0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x04, 0x04, 0x9a, 0x07, 0x5c, 0xf0, 0x00, 0x3c, 0xe9, 0x19, +0xa0, 0x34, 0x50, 0x73, 0x80, 0x23, 0x98, 0x07, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x18, 0x49, 0x00, +0x0d, 0x61, 0x80, 0xe0, 0xc8, 0x0e, 0x3e, 0x08, 0xf9, 0xfc, 0x49, 0xff, 0xf2, 0xe3, 0x44, 0x00, +0x04, 0x00, 0x80, 0x46, 0x80, 0x27, 0x49, 0xff, 0xfb, 0xe7, 0x80, 0x07, 0x48, 0x00, 0x01, 0x0e, +0x3e, 0x08, 0xfa, 0x24, 0x49, 0xff, 0xf2, 0xd6, 0xd5, 0x07, 0x80, 0x46, 0x44, 0x00, 0x04, 0x00, +0x84, 0x20, 0x49, 0xff, 0xfb, 0xd9, 0x84, 0x00, 0x48, 0x00, 0x01, 0x00, 0x9d, 0x49, 0xe2, 0x24, +0xe9, 0x9c, 0x48, 0x00, 0x00, 0xfa, 0x80, 0x0a, 0x3e, 0x19, 0x37, 0xa4, 0x84, 0x42, 0xdd, 0x27, +0x81, 0x20, 0x4e, 0x03, 0x00, 0xc1, 0x10, 0x9f, 0x80, 0x1f, 0x80, 0x06, 0x50, 0x1f, 0x80, 0x1f, +0x05, 0xc3, 0x00, 0x04, 0x49, 0xff, 0xf7, 0xd6, 0x4e, 0x05, 0x00, 0xe7, 0xa1, 0xf4, 0x84, 0x41, +0x50, 0xae, 0x00, 0x18, 0x99, 0xf8, 0x51, 0xce, 0x00, 0x08, 0x4c, 0x81, 0x40, 0x72, 0x00, 0x0f, +0x80, 0x1f, 0x84, 0xa6, 0x4c, 0x02, 0xc0, 0x8d, 0x3e, 0x39, 0x8a, 0x58, 0x04, 0x01, 0x80, 0x9a, +0x54, 0x00, 0x40, 0x00, 0xc0, 0x1f, 0xa6, 0xba, 0xa6, 0x7b, 0x02, 0x01, 0x81, 0x8b, 0x40, 0x21, +0x20, 0x08, 0x40, 0x21, 0x04, 0x04, 0xc0, 0x16, 0x50, 0x01, 0x83, 0x1a, 0x02, 0x11, 0x81, 0x8c, +0xd5, 0x0d, 0x0a, 0x40, 0x00, 0x01, 0x40, 0x91, 0x80, 0x13, 0x4c, 0x22, 0x40, 0x08, 0x84, 0x08, +0x84, 0x20, 0x80, 0x46, 0x49, 0xff, 0xfb, 0x90, 0xd5, 0x05, 0x50, 0x34, 0x80, 0x01, 0xe3, 0x21, +0xe9, 0xf1, 0x3c, 0x1c, 0x63, 0x30, 0x54, 0x10, 0x80, 0x08, 0xc1, 0x62, 0x00, 0x53, 0x80, 0x0d, +0xa6, 0xf8, 0x54, 0x52, 0x80, 0x02, 0xa7, 0x39, 0xa6, 0x7a, 0xa6, 0xbb, 0xc5, 0x59, 0x40, 0x31, +0xa0, 0x08, 0x3c, 0x00, 0xc6, 0xa5, 0x40, 0x31, 0x90, 0x04, 0x4c, 0x30, 0x00, 0x03, 0xc8, 0x50, +0x40, 0x10, 0xa0, 0x08, 0x3c, 0x00, 0xc6, 0xa6, 0x40, 0x10, 0x88, 0x04, 0x4c, 0x10, 0x00, 0x03, +0xc8, 0x47, 0x3e, 0x09, 0x8d, 0x4e, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x0c, 0xd2, +0xc0, 0x0a, 0x3e, 0x09, 0x8d, 0x4e, 0x3e, 0x19, 0x7e, 0x54, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, +0x0c, 0xc9, 0xc8, 0x36, 0x3e, 0x09, 0x8d, 0x5e, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, +0x0c, 0xc1, 0xc0, 0x0a, 0x3e, 0x09, 0x8d, 0x5e, 0x3e, 0x19, 0x7e, 0x54, 0x44, 0x20, 0x00, 0x10, +0x49, 0x00, 0x0c, 0xb8, 0xc8, 0x25, 0x44, 0x00, 0x20, 0x00, 0x84, 0x20, 0xd5, 0x19, 0x84, 0x02, +0x4c, 0x80, 0x40, 0x1f, 0x3e, 0x39, 0x8a, 0x58, 0x04, 0x01, 0x80, 0x9a, 0x40, 0x00, 0x40, 0x08, +0x92, 0x1f, 0xc0, 0x16, 0x50, 0x11, 0x83, 0x44, 0x02, 0x21, 0x81, 0xa1, 0xd5, 0x0d, 0x0a, 0x00, +0x80, 0x01, 0x40, 0x91, 0x80, 0x13, 0xc8, 0x08, 0x80, 0x20, 0x44, 0x00, 0x08, 0x00, 0x80, 0x46, +0x49, 0xff, 0xfb, 0x2a, 0xd5, 0x05, 0x50, 0x34, 0x80, 0x01, 0xe3, 0x22, 0xe9, 0xf1, 0x8f, 0x01, +0x54, 0x84, 0x00, 0xff, 0xe7, 0x02, 0xe8, 0x48, 0x00, 0x0f, 0x80, 0x1f, 0x44, 0x20, 0x00, 0x3a, +0x4c, 0x01, 0x40, 0x43, 0x2e, 0x01, 0x8c, 0xbb, 0xc0, 0x3f, 0xa6, 0x38, 0x44, 0x40, 0x00, 0x87, +0x4c, 0x02, 0x40, 0x3b, 0x80, 0x06, 0x80, 0x3c, 0x80, 0x4a, 0x50, 0x33, 0x80, 0x08, 0x49, 0xff, +0xf8, 0xef, 0xd5, 0x32, 0x80, 0x0a, 0x3e, 0x19, 0x37, 0x9c, 0x84, 0x42, 0xdd, 0x27, 0xc8, 0x2c, +0xa0, 0x34, 0xa7, 0xc1, 0x84, 0xa3, 0xdf, 0x0c, 0x3e, 0x08, 0xfa, 0x44, 0x49, 0xff, 0xf1, 0xf2, +0xa0, 0x74, 0x02, 0x23, 0x00, 0x0a, 0x80, 0x06, 0x49, 0x00, 0x16, 0xfe, 0xd5, 0x1d, 0xcf, 0x1c, +0x3c, 0x0c, 0x63, 0x30, 0x54, 0x00, 0x00, 0x10, 0xc0, 0x17, 0x3e, 0x08, 0xfa, 0x54, 0x49, 0xff, +0xf1, 0xe1, 0xa0, 0x74, 0x84, 0x41, 0x9c, 0x4c, 0xa6, 0x08, 0x4c, 0x01, 0x40, 0x0e, 0x00, 0x80, +0x80, 0x04, 0x4c, 0x80, 0x40, 0x0a, 0x80, 0x27, 0x80, 0x46, 0x44, 0x00, 0x00, 0x10, 0x49, 0xff, +0xfa, 0xdb, 0x80, 0x08, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x24, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x69, 0x8a, 0x58, 0x04, 0x03, 0x00, 0xfd, 0x96, 0x04, 0x4e, 0x02, +0x00, 0x7f, 0x49, 0x00, 0x0c, 0x53, 0x04, 0x13, 0x00, 0x93, 0x50, 0x10, 0x83, 0xe8, 0xe2, 0x20, +0xe8, 0x6d, 0x04, 0x03, 0x00, 0xfe, 0x42, 0x00, 0x70, 0x0b, 0xc8, 0x48, 0x49, 0x00, 0x0c, 0x46, +0x3c, 0x2c, 0x4e, 0xa4, 0x02, 0x33, 0x01, 0x28, 0x04, 0x43, 0x00, 0x93, 0x80, 0x20, 0x3e, 0x08, +0xfa, 0x68, 0x49, 0xff, 0xf1, 0xa7, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x02, 0x03, 0x42, 0x10, +0xe0, 0x09, 0x42, 0x10, 0xe4, 0x09, 0x14, 0x10, 0x02, 0x03, 0x80, 0xe0, 0x44, 0x00, 0x00, 0x28, +0x49, 0xfb, 0xff, 0x48, 0x49, 0xff, 0xf9, 0xd8, 0x04, 0x03, 0x82, 0x83, 0xc8, 0x13, 0x46, 0x00, +0x04, 0x10, 0x04, 0x00, 0x02, 0x8d, 0x40, 0x00, 0x20, 0x08, 0x92, 0x18, 0xc8, 0x0b, 0x80, 0x06, +0x49, 0xff, 0xef, 0x76, 0x04, 0x13, 0x82, 0x83, 0x3e, 0x08, 0xfa, 0x98, 0x49, 0xff, 0xf1, 0x82, +0xd5, 0x07, 0x49, 0x00, 0x2d, 0xb5, 0x2e, 0x01, 0x8c, 0xb0, 0x49, 0x00, 0x2a, 0xaf, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x03, 0x42, 0x10, 0xe0, 0x09, 0x42, 0x10, 0xe4, 0x09, 0x42, 0x10, +0xe0, 0x08, 0x14, 0x10, 0x02, 0x03, 0x49, 0xff, 0xf6, 0x79, 0x3e, 0x69, 0x3a, 0x90, 0xb4, 0x06, +0x9c, 0x01, 0xb6, 0x06, 0xe4, 0x0a, 0xe9, 0x23, 0x3e, 0x08, 0xfa, 0xbc, 0x49, 0xff, 0xf1, 0x62, +0x3e, 0x09, 0x8a, 0x58, 0x04, 0x30, 0x00, 0xfe, 0x04, 0x20, 0x00, 0x9a, 0x42, 0x31, 0xf0, 0x08, +0x84, 0x20, 0x54, 0x21, 0x00, 0x80, 0xb6, 0x26, 0x14, 0x30, 0x00, 0xfe, 0xc2, 0x10, 0x46, 0x01, +0x00, 0x00, 0x80, 0x41, 0x49, 0xff, 0xfa, 0x58, 0xd5, 0x10, 0x04, 0x03, 0x00, 0xfe, 0x42, 0x00, +0x70, 0x09, 0x14, 0x03, 0x00, 0xfe, 0x84, 0x20, 0x3c, 0x1e, 0x4e, 0xa4, 0x3e, 0x09, 0x8e, 0x2c, +0x44, 0x10, 0x03, 0xe8, 0x49, 0xff, 0xf2, 0x52, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0x3c, 0x46, 0x60, 0x04, 0x11, 0x80, 0xa6, 0x84, 0x81, 0x84, 0x20, 0x84, 0x0a, +0x04, 0x73, 0x01, 0xe6, 0x04, 0x22, 0x81, 0xc6, 0x96, 0xfc, 0xc3, 0x55, 0x54, 0x31, 0x00, 0x80, +0xc3, 0x4c, 0x40, 0x31, 0x20, 0x09, 0x96, 0xd8, 0xe6, 0x68, 0xe8, 0x47, 0x40, 0x81, 0x74, 0x09, +0x50, 0x94, 0x7f, 0xfe, 0x54, 0x94, 0x80, 0xff, 0xe7, 0x22, 0xe8, 0x0a, 0x40, 0x13, 0xa0, 0x09, +0x92, 0x50, 0x54, 0x10, 0x80, 0x0f, 0x54, 0x21, 0x00, 0x0f, 0x9a, 0x4a, 0xd5, 0x1b, 0x85, 0x24, +0x4c, 0x84, 0xc0, 0x1a, 0x92, 0xe8, 0x92, 0x50, 0x54, 0x83, 0x80, 0x0f, 0x54, 0x11, 0x00, 0x0f, +0x40, 0x14, 0x04, 0x01, 0x54, 0x73, 0x80, 0x10, 0x40, 0x83, 0x9c, 0x1a, 0x40, 0x80, 0x1c, 0x1b, +0x96, 0x48, 0x54, 0x21, 0x00, 0x10, 0x88, 0x28, 0x40, 0x71, 0x08, 0x1a, 0x40, 0x70, 0x08, 0x1b, +0x9a, 0x4f, 0x96, 0x48, 0xc9, 0x07, 0x42, 0x31, 0x80, 0x24, 0x3e, 0x29, 0x8a, 0x08, 0x98, 0xda, +0xd5, 0x11, 0xe6, 0x2a, 0xe9, 0x08, 0x42, 0x31, 0x80, 0x24, 0x3e, 0x99, 0x8a, 0x08, 0x88, 0x69, +0x8c, 0x69, 0xd5, 0x08, 0x80, 0x41, 0x42, 0x21, 0x80, 0x73, 0x3e, 0x99, 0x8a, 0x08, 0x40, 0x31, +0x24, 0x00, 0xa6, 0x98, 0x9c, 0x91, 0xae, 0x98, 0x9d, 0x21, 0x97, 0x20, 0x44, 0x20, 0x00, 0x21, +0x4c, 0x41, 0x7f, 0xa8, 0x3a, 0x6f, 0xa4, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0xb4, 0x20, 0x92, 0x38, +0x54, 0x10, 0x80, 0x07, 0x3e, 0x11, 0x3a, 0x6c, 0xb4, 0x60, 0x92, 0x70, 0x96, 0xd8, 0x3e, 0x31, +0x3a, 0x6d, 0xb4, 0x80, 0x92, 0x88, 0x3e, 0x41, 0x3a, 0x6e, 0x84, 0x80, 0x3c, 0x48, 0x9d, 0x44, +0x46, 0x40, 0x01, 0x04, 0x58, 0x42, 0x05, 0xdb, 0x98, 0x8c, 0x94, 0x92, 0xb4, 0x42, 0xe6, 0x24, +0xe8, 0x09, 0x94, 0x4b, 0x46, 0x20, 0x04, 0x11, 0x40, 0x31, 0x84, 0x0c, 0x58, 0x21, 0x07, 0x8c, +0xd5, 0x08, 0x94, 0x4b, 0x46, 0x20, 0x04, 0x11, 0x40, 0x31, 0x84, 0x0c, 0x58, 0x21, 0x07, 0x90, +0xb6, 0x62, 0xa2, 0x81, 0x3e, 0x21, 0x3a, 0x6f, 0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xd3, +0xb4, 0x60, 0x40, 0x20, 0xc0, 0x09, 0x54, 0x21, 0x0f, 0xff, 0xe2, 0x62, 0xe9, 0x02, 0x92, 0x28, +0x3e, 0x11, 0x3a, 0x70, 0x84, 0x00, 0xdd, 0x9e, 0x96, 0x49, 0x54, 0x20, 0x80, 0x03, 0x92, 0x22, +0xca, 0x0f, 0xb4, 0x60, 0x54, 0x21, 0x80, 0x03, 0xca, 0x0b, 0x84, 0x41, 0xd5, 0x04, 0xb4, 0x80, +0x9c, 0x91, 0xab, 0x19, 0x9c, 0x04, 0xe2, 0x41, 0xe9, 0xfb, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, 0x96, 0x89, 0x84, 0x2c, 0x40, 0x31, 0x04, 0x37, +0x92, 0x42, 0xc9, 0x1b, 0xd5, 0x16, 0xa2, 0xc3, 0x54, 0x61, 0x80, 0x03, 0x9c, 0x4b, 0x50, 0x40, +0x7f, 0xf8, 0x9f, 0x44, 0x40, 0x31, 0xa0, 0x08, 0x92, 0x68, 0xce, 0x0f, 0xb4, 0xc3, 0xb4, 0x84, +0xb4, 0xa5, 0x40, 0x42, 0x10, 0x05, 0x40, 0x42, 0x18, 0x02, 0x40, 0x42, 0x14, 0x04, 0xb6, 0x83, +0xe2, 0x22, 0xe9, 0xea, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0x3c, 0x96, 0x49, 0x54, 0x20, 0x80, 0x07, 0x92, 0x22, 0xca, 0x11, 0xd5, 0x0c, +0xa2, 0xc2, 0x54, 0x51, 0x80, 0x03, 0x9c, 0x92, 0x9f, 0x04, 0x40, 0x31, 0xa0, 0x08, 0x92, 0x68, +0xcd, 0x07, 0xb4, 0x84, 0xb6, 0x83, 0xe2, 0x41, 0xe9, 0xf4, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0x96, 0x49, 0x54, 0x20, +0x80, 0x07, 0x92, 0x22, 0xca, 0x11, 0xd5, 0x0c, 0xa2, 0xc2, 0x54, 0x51, 0x80, 0x03, 0x9c, 0x92, +0x9f, 0x04, 0x40, 0x31, 0xa0, 0x08, 0x92, 0x68, 0xcd, 0x07, 0xb4, 0x63, 0xb6, 0x64, 0xe2, 0x41, +0xe9, 0xf4, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0x3c, 0xa4, 0x88, 0x5c, 0xf1, 0x00, 0xc8, 0xe8, 0x18, 0x80, 0x80, 0xa2, 0xa1, +0x54, 0x31, 0x00, 0x03, 0xb4, 0xa4, 0xcb, 0x12, 0x5c, 0xf2, 0x80, 0x40, 0xe8, 0x0f, 0xd5, 0x04, +0xa3, 0x91, 0x80, 0x64, 0xb6, 0xc0, 0x40, 0x21, 0x20, 0x08, 0x92, 0x48, 0x9c, 0x04, 0x9d, 0x19, +0xdb, 0xf8, 0x95, 0x22, 0xad, 0x08, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x3a, 0x6f, 0x98, 0x04, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe4, 0x81, 0x42, 0x81, 0x03, +0x81, 0x25, 0x55, 0xc0, 0x00, 0xff, 0x97, 0x08, 0x5c, 0xf3, 0x80, 0xc1, 0xe8, 0x3f, 0x3e, 0x09, +0x83, 0x80, 0xf4, 0x81, 0x49, 0xff, 0xf1, 0xa4, 0x80, 0xc0, 0xf4, 0x01, 0xc0, 0x37, 0x54, 0x42, +0x00, 0x0f, 0x54, 0x2e, 0x00, 0x0f, 0x2e, 0x11, 0x3a, 0x59, 0x40, 0x21, 0x50, 0x08, 0x40, 0x42, +0x40, 0x08, 0xa0, 0x32, 0x40, 0x42, 0x08, 0x04, 0x46, 0x25, 0x80, 0x00, 0x54, 0x10, 0x80, 0x03, +0x40, 0x32, 0x08, 0x04, 0x14, 0x80, 0x00, 0x01, 0xb7, 0x40, 0x40, 0x10, 0xe4, 0x08, 0x50, 0x83, +0x80, 0x08, 0x40, 0x31, 0x84, 0x04, 0x80, 0x47, 0x54, 0x84, 0x3f, 0xff, 0x80, 0x29, 0x8c, 0x08, +0x40, 0x71, 0xa0, 0x04, 0x49, 0xfe, 0xbb, 0x90, 0x84, 0x01, 0x10, 0x03, 0x00, 0x0f, 0x84, 0x00, +0x10, 0x03, 0x00, 0x14, 0x12, 0x83, 0x00, 0x06, 0xa9, 0xf4, 0x80, 0x26, 0x3e, 0x09, 0x8a, 0x58, +0x49, 0xff, 0xeb, 0xac, 0x92, 0x00, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x81, 0x40, 0x3e, 0x09, 0x83, 0x80, 0x81, 0x22, +0x80, 0xe3, 0x54, 0x80, 0x80, 0xff, 0x49, 0xff, 0xf1, 0x5b, 0x80, 0xc0, 0xc8, 0x03, 0x84, 0x01, +0xd5, 0x43, 0x5c, 0xf3, 0x80, 0xc9, 0xe9, 0x09, 0x3e, 0x08, 0xfb, 0x28, 0x44, 0x10, 0x00, 0xc8, +0x49, 0xff, 0xef, 0x98, 0x44, 0x70, 0x00, 0xc8, 0x2e, 0x11, 0x3a, 0x59, 0x54, 0x84, 0x00, 0x0f, +0x54, 0x05, 0x00, 0x0f, 0x40, 0x00, 0x50, 0x08, 0x40, 0x84, 0x40, 0x08, 0x40, 0x84, 0x00, 0x04, +0x46, 0x05, 0x80, 0x00, 0x54, 0x10, 0x80, 0x03, 0x40, 0x10, 0xe4, 0x08, 0x40, 0x84, 0x00, 0x04, +0xa0, 0x32, 0x80, 0x47, 0x40, 0x84, 0x04, 0x04, 0x80, 0x29, 0x49, 0xfe, 0xbb, 0x45, 0x54, 0x73, +0xbf, 0xff, 0x84, 0x01, 0x40, 0x84, 0x1c, 0x04, 0x10, 0x03, 0x00, 0x0f, 0x84, 0x00, 0xad, 0xf6, +0x10, 0x03, 0x00, 0x14, 0x14, 0x83, 0x00, 0x04, 0x3e, 0x09, 0x8a, 0x58, 0x80, 0x26, 0x49, 0xff, +0xeb, 0x5d, 0x80, 0xe0, 0xc0, 0x03, 0x84, 0x00, 0xd5, 0x07, 0x3e, 0x09, 0x83, 0x80, 0x80, 0x26, +0x49, 0xff, 0xf1, 0x38, 0x80, 0x07, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x3e, 0x28, 0x1e, 0x84, 0x80, 0x61, 0x84, 0x02, 0x84, 0x20, 0x49, 0xff, 0xff, 0xa4, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x2e, 0x51, +0x3a, 0x6d, 0xc5, 0x4d, 0x46, 0x00, 0x01, 0x14, 0x2e, 0x11, 0x3a, 0x6f, 0xc1, 0x48, 0x2e, 0x41, +0x3a, 0x6c, 0x9e, 0x49, 0x46, 0x20, 0x01, 0x04, 0x58, 0x21, 0x05, 0xdb, 0x96, 0x48, 0x3e, 0x11, +0x3a, 0x6f, 0x98, 0x22, 0x94, 0x02, 0xb4, 0x60, 0x3c, 0x60, 0x9d, 0x44, 0x40, 0x01, 0xc0, 0x09, +0x98, 0x06, 0x96, 0x01, 0x96, 0xd9, 0x3c, 0x08, 0x9d, 0x44, 0xcb, 0x06, 0xc1, 0x05, 0x2e, 0x21, +0x3a, 0x70, 0xe2, 0x02, 0xe9, 0x2c, 0x2e, 0x21, 0x3a, 0x6e, 0x40, 0x42, 0x60, 0x08, 0x40, 0x62, +0xc0, 0x08, 0x40, 0x63, 0x10, 0x04, 0x40, 0x21, 0x20, 0x08, 0x40, 0x63, 0x08, 0x04, 0x40, 0x50, +0x40, 0x08, 0x84, 0x08, 0x40, 0x52, 0x8c, 0x04, 0x40, 0x63, 0x04, 0x04, 0x80, 0x5f, 0x84, 0x20, +0x80, 0x60, 0xf5, 0x81, 0xb6, 0xdf, 0x49, 0xff, 0xff, 0x5f, 0x92, 0x00, 0x84, 0x60, 0x3e, 0x31, +0x3a, 0x6d, 0x46, 0x10, 0x04, 0x11, 0x80, 0x01, 0x84, 0xa0, 0x3c, 0x58, 0x9d, 0x44, 0x84, 0x40, +0x3e, 0x31, 0x3a, 0x6f, 0x14, 0x20, 0x81, 0xe3, 0x14, 0x20, 0x01, 0xe4, 0xec, 0x08, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x54, 0x80, 0x00, 0xff, 0x3e, 0x09, 0x83, 0x80, +0x80, 0xe1, 0x49, 0xff, 0xf0, 0xa5, 0x80, 0xc0, 0xc8, 0x03, 0x84, 0x01, 0xd5, 0x2d, 0x2e, 0x01, +0x3a, 0x59, 0x54, 0x14, 0x00, 0x0f, 0x54, 0x00, 0x00, 0x03, 0x40, 0x10, 0xd0, 0x08, 0x40, 0x00, +0x64, 0x08, 0x40, 0x00, 0x80, 0x04, 0xa0, 0x72, 0x46, 0x25, 0x80, 0x00, 0xb6, 0xe1, 0x84, 0x28, +0x58, 0x21, 0x00, 0x08, 0xac, 0x76, 0x84, 0x21, 0x40, 0x00, 0x08, 0x04, 0x10, 0x13, 0x00, 0x0f, +0x84, 0x20, 0x10, 0x13, 0x00, 0x14, 0xa8, 0x34, 0x80, 0x26, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, +0xea, 0xbd, 0x80, 0xe0, 0xc0, 0x03, 0x84, 0x00, 0xd5, 0x07, 0x3e, 0x09, 0x83, 0x80, 0x80, 0x26, +0x49, 0xff, 0xf0, 0x98, 0x80, 0x07, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x00, 0x05, 0x84, 0x01, 0x48, 0x00, 0x00, 0xda, 0x9c, 0x04, +0xb4, 0xc0, 0x3e, 0x08, 0xfb, 0x48, 0x80, 0x26, 0x49, 0xff, 0xee, 0xac, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x92, 0x23, 0x94, 0x4b, 0x84, 0x81, 0xb6, 0x20, 0x4c, 0x62, +0x40, 0x16, 0xb4, 0x40, 0x46, 0x10, 0x04, 0x00, 0x40, 0x21, 0x10, 0x04, 0xb6, 0x40, 0x04, 0x00, +0x80, 0x0e, 0x44, 0x2f, 0x1f, 0xff, 0x40, 0x00, 0x08, 0x02, 0x14, 0x00, 0x80, 0x0e, 0x3c, 0x1d, +0xfb, 0xfe, 0x84, 0x00, 0xdd, 0x21, 0x48, 0x00, 0x00, 0xab, 0x84, 0xa3, 0xde, 0x4d, 0xb4, 0x40, +0x46, 0x10, 0x04, 0x10, 0x58, 0x21, 0x00, 0x02, 0xb6, 0x40, 0x04, 0x20, 0x81, 0x01, 0x46, 0x00, +0x04, 0x11, 0x92, 0x44, 0x94, 0x94, 0x14, 0x20, 0x81, 0x01, 0x84, 0x20, 0x04, 0x20, 0x00, 0x80, +0x9c, 0x49, 0x96, 0x94, 0xc2, 0x04, 0x44, 0x50, 0x01, 0x2c, 0xd9, 0xf9, 0x3e, 0x08, 0xfb, 0x64, +0x49, 0xff, 0xee, 0x70, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x3c, 0xb4, 0x41, 0x42, 0x21, +0x04, 0x09, 0xb6, 0x41, 0xb4, 0x41, 0x42, 0x21, 0x08, 0x09, 0xb6, 0x41, 0x46, 0x00, 0x04, 0x00, +0xb4, 0x41, 0x58, 0x00, 0x00, 0x38, 0x42, 0x21, 0x00, 0x09, 0xb6, 0x41, 0x44, 0x4f, 0x1f, 0xff, +0xb4, 0x20, 0x44, 0x50, 0x00, 0xc0, 0x40, 0x10, 0x90, 0x02, 0xb6, 0x20, 0x3c, 0x1c, 0x4e, 0x86, +0xd9, 0x07, 0xb4, 0x20, 0x44, 0x30, 0xc0, 0x00, 0x40, 0x10, 0x8c, 0x04, 0xd5, 0x06, 0xb4, 0x20, +0x44, 0x40, 0xa0, 0x00, 0x40, 0x10, 0x90, 0x04, 0xb6, 0x20, 0x3c, 0x1d, 0xfb, 0xfe, 0x84, 0x00, +0xdd, 0x21, 0x84, 0xc2, 0xd5, 0x5c, 0x84, 0xa2, 0xd6, 0x03, 0x84, 0xc0, 0xd5, 0x58, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x00, 0x38, 0xb4, 0x20, 0x44, 0x20, 0xe0, 0x00, 0x40, 0x10, 0x88, 0x02, +0x44, 0x50, 0xc0, 0x00, 0xd1, 0x3b, 0xb4, 0x20, 0x44, 0x50, 0xa0, 0x00, 0x40, 0x10, 0x88, 0x02, +0xd1, 0x35, 0x46, 0x20, 0x04, 0x10, 0x04, 0x31, 0x01, 0x01, 0x92, 0x64, 0x94, 0xdc, 0x14, 0x31, +0x01, 0x01, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x3c, 0xb4, 0x41, 0x42, 0x21, 0x04, 0x09, +0xb6, 0x41, 0xb4, 0x41, 0x42, 0x21, 0x08, 0x09, 0xb6, 0x41, 0x44, 0x4f, 0x1f, 0xff, 0xb4, 0x41, +0x42, 0x21, 0x00, 0x09, 0xb6, 0x41, 0x44, 0x50, 0x00, 0xc0, 0xb4, 0x20, 0x40, 0x10, 0x90, 0x02, +0xb6, 0x20, 0x3c, 0x1c, 0x4e, 0x86, 0xd9, 0x07, 0xb4, 0x20, 0x44, 0x30, 0xc0, 0x00, 0x40, 0x10, +0x8c, 0x04, 0xd5, 0x06, 0xb4, 0x20, 0x44, 0x40, 0xa0, 0x00, 0x40, 0x10, 0x90, 0x04, 0xb6, 0x20, +0x3c, 0x1d, 0xfb, 0xfe, 0x84, 0x00, 0xdd, 0x21, 0xd5, 0x09, 0x46, 0x00, 0x04, 0x11, 0x04, 0x10, +0x00, 0x8f, 0x42, 0x10, 0x84, 0x09, 0x14, 0x10, 0x00, 0x8f, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, +0x00, 0x8f, 0x84, 0xc1, 0x58, 0x10, 0x80, 0x04, 0x14, 0x10, 0x00, 0x8f, 0x42, 0x23, 0x70, 0x08, +0x84, 0x00, 0x44, 0x10, 0x00, 0x73, 0x49, 0xfc, 0x1d, 0xe7, 0x92, 0x00, 0x84, 0x00, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, +0x00, 0x04, 0x84, 0x01, 0xd5, 0x16, 0x9c, 0x04, 0xb4, 0x40, 0x84, 0xa1, 0xd2, 0x09, 0x56, 0x31, +0x00, 0x03, 0x84, 0x02, 0x84, 0x20, 0x40, 0x20, 0x8c, 0x1b, 0x40, 0x20, 0x0c, 0x1a, 0x42, 0x21, +0x70, 0x08, 0x84, 0x00, 0x44, 0x10, 0x00, 0x73, 0x49, 0xfc, 0x1d, 0xc6, 0x92, 0x00, 0x84, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x48, +0x96, 0x49, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x06, 0x9c, 0x04, 0xb4, 0x00, 0x49, 0x00, +0x61, 0x4b, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x97, 0xc9, 0x80, 0xc0, 0x3e, 0x08, 0xfb, 0x78, 0x80, 0x27, 0x49, 0xff, 0xed, 0x9a, +0x44, 0x50, 0x00, 0x10, 0xd7, 0x03, 0x84, 0x01, 0xd5, 0x16, 0x50, 0x03, 0x00, 0x0c, 0x9c, 0x74, +0x8c, 0xc8, 0xb4, 0xe1, 0xb4, 0xc6, 0xb5, 0x00, 0x80, 0x27, 0x3e, 0x08, 0xfb, 0x9e, 0x80, 0x68, +0x80, 0x46, 0x49, 0xff, 0xed, 0x87, 0x80, 0x08, 0x80, 0x27, 0x80, 0x46, 0x49, 0x00, 0x5f, 0x40, +0x92, 0x00, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x80, 0xc0, 0x96, 0x49, 0x44, 0x00, 0x00, 0x14, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x13, +0x3e, 0x08, 0xfb, 0xc4, 0x49, 0xff, 0xed, 0x6e, 0x50, 0x13, 0x00, 0x10, 0x50, 0x03, 0x00, 0x08, +0x9c, 0xb4, 0x8c, 0xcc, 0xb4, 0x61, 0xb4, 0x20, 0xb4, 0x06, 0xb4, 0x42, 0x49, 0x00, 0x5a, 0xfa, +0x5c, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x18, 0x96, 0x49, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x13, +0x50, 0x40, 0x00, 0x14, 0x9d, 0x44, 0x50, 0x10, 0x00, 0x08, 0x50, 0x20, 0x00, 0x0c, 0x50, 0x30, +0x00, 0x10, 0xb4, 0x05, 0xb4, 0x21, 0xb4, 0x42, 0xb4, 0x63, 0xb4, 0x84, 0x49, 0x00, 0x5c, 0x7a, +0x5c, 0x00, 0x00, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0xb4, 0x40, 0x84, 0x63, 0x96, 0x49, 0x4c, 0x21, 0x80, 0x18, 0xe6, 0x44, 0xe8, 0x06, +0x84, 0xa1, 0xd2, 0x0d, 0x84, 0xa2, 0xda, 0x09, 0xd5, 0x0d, 0x44, 0x50, 0xff, 0xf1, 0xd2, 0x13, +0x9d, 0x69, 0xd2, 0x14, 0x84, 0xa4, 0xd2, 0x0c, 0x84, 0x00, 0xd5, 0x12, 0x49, 0xff, 0xff, 0x4c, +0xd5, 0x0f, 0x49, 0xff, 0xff, 0xc5, 0xd5, 0x0c, 0x49, 0xff, 0xff, 0xa2, 0xd5, 0x09, 0x49, 0xff, +0xff, 0x77, 0xd5, 0x06, 0x49, 0xff, 0xff, 0x62, 0xd5, 0x03, 0x49, 0xff, 0xfe, 0x59, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x96, 0x49, +0x97, 0xd0, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0x66, 0xb4, 0x00, 0x84, 0x21, +0x4c, 0x00, 0xc0, 0x12, 0x3c, 0x2c, 0x63, 0x95, 0x3c, 0x0c, 0x63, 0x94, 0xf2, 0x81, 0xb6, 0x1f, +0x49, 0x00, 0x24, 0x84, 0x84, 0x40, 0x80, 0xdf, 0x80, 0x27, 0x80, 0xbf, 0x84, 0x05, 0x80, 0x62, +0x84, 0x88, 0xd5, 0x4d, 0x84, 0x22, 0x4c, 0x00, 0xc0, 0x3f, 0x3e, 0x79, 0x3a, 0x14, 0xb4, 0x47, +0xc2, 0x49, 0x3e, 0x09, 0x83, 0x70, 0x49, 0xff, 0xee, 0x9b, 0x80, 0xc0, 0xc8, 0x08, 0x3e, 0x08, +0xf6, 0xd0, 0x3e, 0x18, 0xff, 0xd4, 0x49, 0xff, 0xec, 0xdd, 0xd5, 0x3c, 0xb4, 0x07, 0x54, 0x10, +0x00, 0x03, 0xc1, 0x05, 0x92, 0x02, 0x94, 0x02, 0x9c, 0x04, 0xb6, 0x07, 0x2e, 0x81, 0x3a, 0x59, +0x3c, 0x1c, 0x4e, 0x85, 0x54, 0x84, 0x00, 0x03, 0x46, 0x25, 0x8b, 0x00, 0xa0, 0x32, 0x40, 0x84, +0x64, 0x08, 0x54, 0x70, 0xbf, 0xff, 0x40, 0x84, 0x08, 0x04, 0x80, 0x41, 0x3e, 0x19, 0x83, 0x90, +0x49, 0xfe, 0xb8, 0x8a, 0x40, 0x84, 0x1c, 0x04, 0x84, 0x01, 0x10, 0x03, 0x00, 0x14, 0x10, 0x03, +0x00, 0x0f, 0xad, 0xf6, 0x14, 0x83, 0x00, 0x04, 0x80, 0x26, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, +0xe8, 0xa5, 0xd5, 0x10, 0x84, 0x24, 0x4c, 0x00, 0xc0, 0x0e, 0x49, 0x00, 0x24, 0x37, 0x80, 0x27, +0x84, 0x05, 0x84, 0x41, 0x84, 0x60, 0x84, 0x82, 0x3e, 0x59, 0x8e, 0x0c, 0x49, 0xff, 0xfc, 0xa4, +0x92, 0x00, 0x84, 0x05, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x3e, 0x69, 0x8a, 0x08, 0x81, 0x00, 0x84, 0xe0, 0xa6, 0x71, 0xa6, 0x30, 0x40, 0x10, +0xa0, 0x08, 0x40, 0x10, 0x80, 0x04, 0x40, 0x03, 0xc0, 0x08, 0x40, 0x10, 0x80, 0x04, 0x80, 0x08, +0xaa, 0x41, 0x50, 0x14, 0x00, 0x08, 0xa7, 0x75, 0xa6, 0xb4, 0xa7, 0x32, 0xa6, 0xf3, 0x40, 0x52, +0xe0, 0x08, 0x40, 0x21, 0x40, 0x08, 0x40, 0x22, 0x88, 0x04, 0x40, 0x21, 0x10, 0x04, 0x40, 0x31, +0xa0, 0x08, 0x40, 0x21, 0x0c, 0x04, 0xb6, 0x40, 0x9d, 0xf9, 0x00, 0x43, 0x00, 0x09, 0x00, 0x03, +0x00, 0x08, 0xa6, 0xf6, 0xa6, 0xb7, 0x40, 0x42, 0x60, 0x08, 0x40, 0x00, 0x40, 0x08, 0x40, 0x02, +0x00, 0x04, 0x40, 0x00, 0x0c, 0x04, 0x40, 0x21, 0x20, 0x08, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x01, +0x84, 0x4a, 0x80, 0x06, 0x84, 0x20, 0x49, 0xfe, 0xb8, 0x47, 0x84, 0xa8, 0x8c, 0xca, 0x8d, 0x0c, +0xdf, 0xc5, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x81, 0x20, 0x0c, 0x80, 0x00, 0x01, 0x46, 0x70, 0x00, 0x80, 0x58, 0x73, 0x8b, 0xf0, +0xb4, 0xc0, 0x80, 0x28, 0x3e, 0x08, 0xfb, 0xe4, 0x80, 0x46, 0xdd, 0x27, 0x84, 0xa1, 0x4c, 0x82, +0xc0, 0x0c, 0x3e, 0x61, 0x8c, 0xb8, 0x4e, 0x63, 0x01, 0x37, 0x3e, 0x81, 0x3a, 0x61, 0x3e, 0x61, +0x8e, 0x6c, 0x48, 0x00, 0x01, 0x31, 0x84, 0xa3, 0x4c, 0x82, 0xc0, 0xc9, 0x97, 0xb0, 0x3e, 0x89, +0x8a, 0x58, 0x10, 0x64, 0x04, 0x00, 0x46, 0x90, 0x04, 0x10, 0x58, 0x94, 0x88, 0x0c, 0xb5, 0x49, +0x42, 0xa5, 0x60, 0x09, 0x42, 0xa5, 0x64, 0x09, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x8c, 0x74, +0xce, 0x47, 0x3e, 0x08, 0xfc, 0x0c, 0xf1, 0x81, 0x47, 0xc0, 0x00, 0x80, 0x59, 0xce, 0x0c, 0x8c, +0xdd, 0x27, 0x50, 0x04, 0x03, 0xb8, 0xdd, 0x3c, 0x50, 0x04, 0x03, 0xd4, 0xdd, 0x3c, 0x3e, 0x09, +0x89, 0xec, 0xdd, 0x3c, 0xb7, 0x49, 0x44, 0x00, 0x00, 0x28, 0x49, 0xfb, 0xf9, 0xbb, 0x84, 0x41, +0x3e, 0x61, 0x8e, 0x6c, 0x3e, 0x21, 0x3a, 0x61, 0x80, 0x06, 0x49, 0x00, 0x21, 0xaf, 0x3e, 0x08, +0xfc, 0x28, 0xdd, 0x27, 0xf1, 0x01, 0xdd, 0x21, 0x46, 0x30, 0x30, 0x00, 0x40, 0xa5, 0x0c, 0x04, +0xb7, 0x49, 0x3e, 0x08, 0xfc, 0x3c, 0xb4, 0x29, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, +0x00, 0x18, 0xb4, 0x40, 0x92, 0x4c, 0x40, 0x21, 0x30, 0x08, 0xb6, 0x40, 0x3c, 0x2c, 0x4e, 0xa9, +0xb4, 0x60, 0x40, 0x21, 0x88, 0x04, 0xb6, 0x40, 0x46, 0x10, 0x04, 0x10, 0x3c, 0x0c, 0x4e, 0xa8, +0x14, 0x00, 0x81, 0x03, 0x84, 0x01, 0x3e, 0x01, 0x3a, 0x61, 0x48, 0x00, 0x00, 0xd5, 0xdd, 0x21, +0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x00, 0x18, 0xb4, 0x02, 0x54, 0x00, 0x0f, 0xff, 0x3c, 0x0e, +0x4e, 0xa9, 0xb4, 0x62, 0x92, 0x6c, 0x40, 0x31, 0xb0, 0x08, 0xb6, 0x62, 0x50, 0x11, 0x73, 0xf4, +0xb4, 0x62, 0x58, 0x31, 0x85, 0x78, 0xb6, 0x62, 0xb4, 0x41, 0x44, 0x00, 0x00, 0x28, 0x3c, 0x2e, +0x4e, 0xa8, 0xb4, 0x41, 0x92, 0x48, 0x40, 0x21, 0x20, 0x08, 0xb6, 0x41, 0xb4, 0x41, 0x58, 0x21, +0x00, 0x04, 0xb6, 0x41, 0xb7, 0x49, 0x42, 0xa5, 0x60, 0x08, 0x49, 0xfb, 0xf9, 0x63, 0x3e, 0x08, +0xfc, 0x5c, 0xdd, 0x27, 0x46, 0x20, 0x04, 0x00, 0x80, 0x22, 0x80, 0x01, 0x84, 0x60, 0xb7, 0x49, +0x14, 0x34, 0x00, 0xfe, 0x14, 0x31, 0x00, 0xa3, 0x14, 0x30, 0x80, 0xa4, 0x14, 0x30, 0x00, 0xa2, +0x3c, 0x3e, 0x4e, 0x85, 0x10, 0x34, 0x03, 0xa4, 0x80, 0x23, 0x44, 0x20, 0x06, 0x40, 0x3e, 0x09, +0x83, 0x90, 0x49, 0xfe, 0xb7, 0x81, 0x49, 0xff, 0xf0, 0xa1, 0x2e, 0x01, 0x8e, 0x7a, 0x49, 0xff, +0xf1, 0x59, 0x49, 0x00, 0x06, 0x23, 0x50, 0x20, 0x27, 0x10, 0x3c, 0x2e, 0x4e, 0xa6, 0x44, 0x10, +0x01, 0x5e, 0x50, 0x04, 0x03, 0xb8, 0x49, 0xff, 0xec, 0x99, 0x50, 0x04, 0x03, 0xd4, 0x44, 0x10, +0x03, 0xe8, 0x49, 0xff, 0xec, 0x93, 0x00, 0x04, 0x03, 0xa5, 0x84, 0xa3, 0xd8, 0x74, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0x2c, 0x42, 0x10, 0xd4, 0x09, 0x42, 0x10, 0xf4, 0x09, 0x58, 0x10, +0x80, 0x20, 0x14, 0x10, 0x00, 0x2c, 0x48, 0x00, 0x00, 0x67, 0x84, 0xa4, 0x4c, 0x82, 0xc0, 0x26, +0x84, 0xa1, 0x3e, 0x61, 0x8d, 0xfd, 0xde, 0x04, 0x3c, 0x6e, 0x33, 0xe9, 0xd5, 0x5c, 0x84, 0xa2, +0xde, 0x16, 0x3e, 0x08, 0xfc, 0x88, 0xdd, 0x27, 0x50, 0x04, 0x80, 0x08, 0xb4, 0x20, 0x50, 0x04, +0x80, 0x0c, 0x3c, 0x1e, 0x63, 0x80, 0x8d, 0x30, 0xb4, 0x40, 0x3e, 0x08, 0xfc, 0xa0, 0x3c, 0x2e, +0x63, 0x81, 0xb4, 0x69, 0x3c, 0x3e, 0x63, 0x82, 0xdd, 0x27, 0xd5, 0x45, 0x84, 0xa4, 0xde, 0x43, +0x3e, 0x08, 0xfc, 0xd0, 0xdd, 0x27, 0xd5, 0x3f, 0x84, 0xa5, 0x4c, 0x82, 0xc0, 0x09, 0x56, 0x63, +0x00, 0x01, 0x5c, 0x63, 0x00, 0x01, 0x3e, 0x61, 0x8e, 0x79, 0xd5, 0x35, 0x84, 0xa6, 0x4c, 0x82, +0xc0, 0x14, 0x3e, 0x39, 0x8a, 0x58, 0x12, 0x61, 0x81, 0x29, 0x50, 0x04, 0x80, 0x08, 0xb4, 0x20, +0x8d, 0x2c, 0x14, 0x11, 0x80, 0x96, 0x3e, 0x08, 0xfc, 0xec, 0xb4, 0x89, 0x96, 0xa0, 0x10, 0x21, +0x82, 0x5c, 0xdd, 0x27, 0xd5, 0x20, 0x84, 0xa7, 0x4c, 0x82, 0xc0, 0x0a, 0x97, 0xb0, 0x3e, 0x61, +0x8e, 0x48, 0x80, 0x26, 0x3e, 0x08, 0xfd, 0x00, 0xdd, 0x27, 0xd5, 0x15, 0x84, 0xa8, 0x4c, 0x82, +0xc0, 0x13, 0x3e, 0x09, 0x8a, 0x58, 0x10, 0x60, 0x03, 0xf1, 0x50, 0x14, 0x80, 0x08, 0xb4, 0x21, +0x8d, 0x2c, 0x54, 0x10, 0x80, 0x0f, 0x10, 0x10, 0x03, 0xf2, 0xb4, 0x29, 0x54, 0x10, 0x8f, 0xff, +0x12, 0x10, 0x01, 0xda, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x8c, 0xb4, 0x40, 0x85, 0x21, 0x80, 0xc0, 0x40, 0x80, 0x80, 0x13, +0x4c, 0x24, 0xc0, 0x26, 0x9c, 0x04, 0xb4, 0x00, 0x50, 0x33, 0x00, 0x0c, 0x40, 0x10, 0x24, 0x02, +0x8c, 0xc8, 0xb4, 0xe6, 0xb4, 0x63, 0xc1, 0x03, 0x3e, 0x21, 0x8c, 0xb9, 0x54, 0x00, 0x00, 0x02, +0xc0, 0x06, 0x84, 0x21, 0x3e, 0x11, 0x8c, 0xbb, 0x3e, 0x11, 0x8c, 0xba, 0x3c, 0x3e, 0x63, 0x31, +0x3c, 0x7e, 0x63, 0x30, 0x3e, 0x08, 0xfd, 0x1c, 0x84, 0x21, 0x49, 0xff, 0xea, 0xdb, 0x80, 0x27, +0x3e, 0x08, 0xfd, 0x34, 0x49, 0xff, 0xea, 0xd6, 0x48, 0x00, 0x01, 0x8c, 0x84, 0x02, 0x4c, 0x20, +0x40, 0x47, 0x00, 0x53, 0x00, 0x50, 0x00, 0x43, 0x00, 0x51, 0x00, 0x33, 0x00, 0x53, 0x9c, 0x34, +0xb5, 0x20, 0x01, 0xc3, 0x00, 0x52, 0xf3, 0x83, 0xf4, 0x82, 0xf5, 0x84, 0x44, 0x85, 0xa3, 0x84, +0x50, 0x13, 0x00, 0x08, 0x50, 0xaf, 0x80, 0x58, 0x44, 0x20, 0x00, 0x40, 0x50, 0x0f, 0x80, 0x18, +0x3e, 0x79, 0x8a, 0x58, 0xdd, 0x28, 0x50, 0x13, 0x00, 0x48, 0x84, 0x48, 0x42, 0x64, 0x84, 0x0b, +0x80, 0x0a, 0x54, 0x94, 0x80, 0x01, 0xdd, 0x28, 0x10, 0x93, 0x82, 0x43, 0x10, 0x63, 0x82, 0x44, +0x50, 0x1f, 0x80, 0x18, 0xf5, 0x04, 0x44, 0x20, 0x00, 0x40, 0x10, 0x53, 0x82, 0x40, 0x50, 0x03, +0x80, 0xd4, 0xf4, 0x02, 0x10, 0x43, 0x82, 0x41, 0xf3, 0x03, 0x13, 0xc3, 0x81, 0x29, 0x10, 0x33, +0x82, 0x42, 0xdd, 0x28, 0x80, 0x2a, 0x84, 0x48, 0x50, 0x03, 0x80, 0xcc, 0xdd, 0x28, 0x50, 0x13, +0x80, 0xd4, 0x84, 0x00, 0x49, 0x00, 0x0c, 0x30, 0x48, 0x00, 0x01, 0x44, 0x84, 0x23, 0x4c, 0x20, +0xc0, 0x49, 0x50, 0xaf, 0x80, 0x68, 0x44, 0x75, 0xa3, 0x84, 0x9c, 0x74, 0x50, 0x8f, 0x80, 0x60, +0x84, 0x46, 0x80, 0x0a, 0xdd, 0x27, 0x50, 0x13, 0x00, 0x0a, 0x84, 0x46, 0x80, 0x08, 0xdd, 0x27, +0x80, 0x2a, 0x84, 0x46, 0x3e, 0x09, 0x8e, 0x64, 0xdd, 0x27, 0x80, 0x28, 0x84, 0x46, 0x3e, 0x09, +0x8c, 0x9d, 0xdd, 0x27, 0x8c, 0xd0, 0x3e, 0x79, 0x8e, 0x64, 0xb5, 0x46, 0x00, 0x83, 0x80, 0x05, +0x3e, 0x69, 0x8a, 0x58, 0xa6, 0x78, 0xa6, 0xb9, 0xa6, 0xfa, 0xa7, 0x3b, 0xa7, 0x7c, 0x14, 0xa3, +0x00, 0xfd, 0xb7, 0x1f, 0x3e, 0x08, 0xfd, 0x50, 0x49, 0xff, 0xea, 0x5c, 0x00, 0x83, 0x02, 0x4a, +0x00, 0x13, 0x02, 0x45, 0x00, 0x23, 0x02, 0x46, 0x00, 0x33, 0x02, 0x47, 0x00, 0x43, 0x02, 0x48, +0x00, 0x53, 0x02, 0x49, 0xb7, 0x1f, 0x3e, 0x08, 0xfd, 0x80, 0x49, 0xff, 0xea, 0x4b, 0x04, 0x13, +0x00, 0xfd, 0x3e, 0x08, 0xfd, 0xb0, 0x49, 0xff, 0xea, 0x45, 0x80, 0x09, 0x48, 0x00, 0x01, 0xf2, +0x84, 0x84, 0x4c, 0x22, 0x01, 0xee, 0x84, 0xa6, 0xda, 0x60, 0x3e, 0x08, 0xfd, 0xc4, 0x80, 0x28, +0x49, 0xff, 0xea, 0x38, 0x84, 0xe0, 0xd5, 0x0d, 0xc8, 0x05, 0x3e, 0x08, 0xfd, 0xd4, 0x49, 0xff, +0xea, 0x31, 0x38, 0x13, 0x1c, 0x00, 0x3e, 0x08, 0xfd, 0xd8, 0x49, 0xff, 0xea, 0x2b, 0x9d, 0xf9, +0x54, 0x03, 0x80, 0x0f, 0xe2, 0xe8, 0xe9, 0xf1, 0x3e, 0x08, 0xfd, 0xd4, 0x49, 0xff, 0xea, 0x22, +0x9c, 0x34, 0xb5, 0x20, 0x50, 0x13, 0x00, 0x08, 0x50, 0x03, 0x00, 0x0c, 0x05, 0xc0, 0x80, 0x00, +0xb4, 0xe0, 0xe7, 0x23, 0x4e, 0xf2, 0x01, 0xc5, 0xe6, 0xe2, 0x4e, 0xf2, 0x01, 0xc2, 0x44, 0x30, +0x00, 0x12, 0x42, 0x34, 0x8c, 0x24, 0x3e, 0x49, 0x8d, 0xc6, 0x50, 0x52, 0x7c, 0x92, 0x40, 0xa1, +0x90, 0x00, 0x44, 0x00, 0x00, 0x10, 0x98, 0xdd, 0x84, 0x24, 0x40, 0x20, 0x9c, 0x1a, 0x40, 0x20, +0x1c, 0x1b, 0x50, 0x31, 0x83, 0x68, 0xf2, 0x85, 0xaf, 0xdc, 0x11, 0xc1, 0x80, 0x05, 0x98, 0x70, +0x80, 0x0a, 0x49, 0xfe, 0xb5, 0xc1, 0x80, 0x27, 0x80, 0x49, 0x80, 0x7c, 0x3e, 0x08, 0xfd, 0xe0, +0x49, 0xff, 0xe9, 0xf0, 0x80, 0xea, 0x84, 0xc0, 0x08, 0x13, 0x80, 0x01, 0x3e, 0x08, 0xfe, 0x0c, +0x49, 0xff, 0xe9, 0xe8, 0xf5, 0x05, 0x9d, 0xb1, 0xe2, 0xc5, 0xe9, 0xf7, 0x3e, 0x08, 0xfd, 0xd4, +0x49, 0xff, 0xe9, 0xe0, 0x48, 0x00, 0x00, 0x96, 0x84, 0x07, 0x4c, 0x20, 0x40, 0x7b, 0x9c, 0x34, +0xb4, 0xe0, 0x50, 0x13, 0x00, 0x08, 0x50, 0x03, 0x00, 0x0c, 0xb5, 0x21, 0xb4, 0x60, 0xb4, 0x80, +0xe6, 0xe2, 0x4e, 0xf2, 0x01, 0x7e, 0xe7, 0x22, 0x4e, 0xf2, 0x01, 0x7b, 0x44, 0xa0, 0x00, 0x7e, +0x42, 0xa3, 0xa8, 0x24, 0x44, 0x00, 0x00, 0x10, 0x84, 0x24, 0x40, 0x80, 0x9c, 0x1a, 0x40, 0x80, +0x1c, 0x1b, 0x3e, 0x19, 0x8a, 0x58, 0x40, 0x55, 0x04, 0x00, 0x50, 0x52, 0x82, 0x70, 0x40, 0x42, +0x00, 0x0d, 0x96, 0xd9, 0x51, 0xc5, 0x02, 0x78, 0xad, 0x2b, 0x10, 0x92, 0x80, 0x01, 0xac, 0xea, +0xaf, 0xe8, 0x41, 0xce, 0x04, 0x00, 0x80, 0x48, 0x98, 0x70, 0x80, 0x1c, 0xf3, 0x83, 0xf4, 0x82, +0x49, 0xfe, 0xb5, 0x72, 0x50, 0x05, 0x02, 0x88, 0x3e, 0x29, 0x8a, 0x58, 0x50, 0x13, 0x00, 0x20, +0x98, 0x02, 0x80, 0x48, 0x49, 0xfe, 0xb5, 0x68, 0xf3, 0x03, 0xf4, 0x02, 0x80, 0x49, 0x46, 0x60, +0x00, 0x80, 0x58, 0x63, 0x0b, 0xf0, 0x3e, 0x08, 0xfe, 0x14, 0x80, 0x27, 0xdd, 0x26, 0x3e, 0x08, +0xfe, 0x4c, 0x81, 0x5c, 0xdd, 0x26, 0x83, 0x86, 0x85, 0x20, 0x08, 0x15, 0x00, 0x01, 0x3e, 0x08, +0xfe, 0x5c, 0x8d, 0x21, 0xdd, 0x3c, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x0b, 0xf0, 0xe3, 0x28, +0xe9, 0xf5, 0x3e, 0x08, 0xfd, 0xd4, 0xdd, 0x26, 0x3e, 0x08, 0xfe, 0x64, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x7e, 0x42, 0x73, 0x80, 0x24, 0x3e, 0x09, 0x8a, 0x58, 0x50, 0x73, 0x82, 0x88, 0x81, 0x26, +0x99, 0xf8, 0x84, 0xc0, 0x08, 0x13, 0x80, 0x01, 0x9d, 0xb1, 0x3e, 0x08, 0xfe, 0x5c, 0xdd, 0x29, +0xe2, 0xc8, 0xe9, 0xf9, 0x3e, 0x08, 0xfd, 0xd4, 0x49, 0xff, 0xe9, 0x64, 0x48, 0x00, 0x01, 0x11, +0x84, 0x28, 0x4c, 0x20, 0xc0, 0x1a, 0x9c, 0x34, 0xb4, 0x20, 0x3e, 0x49, 0x8a, 0x58, 0x96, 0x49, +0x12, 0x12, 0x01, 0x29, 0x50, 0x03, 0x00, 0x08, 0xb4, 0x40, 0x8c, 0xcc, 0x14, 0x22, 0x00, 0x96, +0x3e, 0x08, 0xfe, 0x74, 0xb4, 0xa6, 0x96, 0xe8, 0x10, 0x32, 0x02, 0x5c, 0x49, 0xff, 0xe9, 0x4a, +0x84, 0x00, 0x48, 0x00, 0x00, 0xf7, 0x84, 0x89, 0x4c, 0x22, 0x40, 0x67, 0x9c, 0x74, 0xb4, 0x01, +0xc8, 0x06, 0x3c, 0x98, 0xc6, 0xb7, 0x3c, 0x98, 0xc6, 0x78, 0xd5, 0x06, 0x3e, 0x09, 0x8c, 0xe0, +0x84, 0x44, 0x49, 0xfe, 0xb5, 0x01, 0x50, 0x03, 0x00, 0x08, 0xb4, 0xe0, 0x96, 0x39, 0xe6, 0x15, +0xe9, 0x03, 0x44, 0x70, 0x00, 0x14, 0x97, 0xf9, 0x3c, 0x78, 0xc6, 0x79, 0x46, 0x80, 0x00, 0x80, +0x58, 0x84, 0x0b, 0xf0, 0x3e, 0x08, 0xfe, 0x8c, 0x80, 0x27, 0xdd, 0x28, 0x81, 0x28, 0x85, 0x00, +0xd5, 0x08, 0xb4, 0x41, 0x8d, 0x01, 0x96, 0x51, 0xac, 0x5a, 0xdd, 0x29, 0x54, 0x84, 0x00, 0xff, +0x50, 0x14, 0x00, 0x03, 0x50, 0x04, 0x01, 0x4c, 0x98, 0x00, 0x94, 0x4a, 0x3e, 0x59, 0x8a, 0x58, +0x98, 0xc5, 0x98, 0x71, 0x3e, 0x08, 0xfe, 0xa4, 0xe3, 0x07, 0xe9, 0xec, 0x9c, 0x3b, 0x94, 0x02, +0x98, 0x30, 0xb5, 0x00, 0x9d, 0xfc, 0x40, 0x04, 0x00, 0x13, 0x97, 0xf9, 0xe6, 0x15, 0xe9, 0x03, +0x44, 0x80, 0x00, 0x14, 0x40, 0x84, 0x00, 0x13, 0x3c, 0x88, 0xc6, 0xb8, 0x3e, 0x08, 0xfe, 0xb8, +0x80, 0x28, 0x49, 0xff, 0xe8, 0xf7, 0x84, 0x00, 0xd5, 0x04, 0xb4, 0x44, 0x96, 0x18, 0xac, 0x8a, +0x99, 0x07, 0x50, 0x10, 0x01, 0x8b, 0x95, 0x22, 0x98, 0x49, 0x3e, 0x29, 0x8a, 0x58, 0x99, 0x34, +0x98, 0x4a, 0x9c, 0xc1, 0xe2, 0x08, 0xe9, 0xf2, 0x04, 0x31, 0x00, 0x9a, 0x3e, 0x08, 0xfe, 0xd0, +0x58, 0x31, 0xc0, 0x00, 0xd5, 0x59, 0x84, 0x8a, 0x4c, 0x22, 0x40, 0x5b, 0x9c, 0x34, 0xb4, 0xe0, +0x96, 0x39, 0xe6, 0x15, 0xe9, 0x02, 0x95, 0xe1, 0x97, 0xf9, 0x3c, 0x78, 0xc6, 0x8e, 0x46, 0x80, +0x00, 0x80, 0x58, 0x84, 0x0b, 0xf0, 0x3e, 0x08, 0xfe, 0xe4, 0x80, 0x27, 0xdd, 0x28, 0x81, 0x28, +0x85, 0x00, 0xd5, 0x08, 0xb4, 0x41, 0x8d, 0x01, 0x96, 0x51, 0xac, 0x5b, 0xdd, 0x29, 0x54, 0x84, +0x00, 0xff, 0x50, 0x14, 0x00, 0x02, 0x50, 0x04, 0x01, 0x60, 0x98, 0x00, 0x94, 0x4a, 0x3e, 0x59, +0x8a, 0x58, 0x98, 0xc5, 0x98, 0x71, 0x3e, 0x08, 0xfe, 0xfc, 0xe3, 0x07, 0xe9, 0xec, 0x9c, 0x3a, +0x94, 0x02, 0x98, 0x30, 0xb5, 0x00, 0x40, 0x04, 0x00, 0x13, 0xe6, 0x15, 0xe9, 0x03, 0x44, 0x80, +0x00, 0x14, 0x40, 0x84, 0x00, 0x13, 0x3c, 0x88, 0xc6, 0xcd, 0x3e, 0x08, 0xff, 0x10, 0x9d, 0xfb, +0x80, 0x28, 0x49, 0xff, 0xe8, 0x9f, 0x97, 0xf9, 0x84, 0x00, 0xd5, 0x04, 0xb4, 0x44, 0x96, 0x18, +0xac, 0x8b, 0x99, 0x07, 0x50, 0x10, 0x01, 0x9f, 0x95, 0x22, 0x98, 0x49, 0x3e, 0x29, 0x8a, 0x58, +0x99, 0x34, 0x98, 0x4a, 0x9c, 0xc1, 0xe2, 0x08, 0xe9, 0xf2, 0x04, 0x31, 0x00, 0x9a, 0x3e, 0x08, +0xff, 0x28, 0x42, 0x31, 0xbc, 0x08, 0x80, 0x23, 0x14, 0x31, 0x00, 0x9a, 0xd5, 0x0b, 0x84, 0xab, +0xda, 0x0c, 0x9d, 0xb4, 0xb4, 0x46, 0x96, 0x90, 0x3e, 0x21, 0x8c, 0xbd, 0x80, 0x22, 0x3e, 0x08, +0xff, 0x3c, 0x49, 0xff, 0xe8, 0x77, 0xd5, 0x24, 0x84, 0x0c, 0x4c, 0x20, 0x40, 0x22, 0x9c, 0x34, +0x05, 0xc0, 0x00, 0x00, 0xe7, 0x0d, 0xe8, 0x1c, 0x84, 0xe0, 0x8c, 0xc8, 0x81, 0x07, 0xd5, 0x15, +0xa6, 0x30, 0x84, 0x21, 0x54, 0x00, 0x00, 0x0f, 0x4c, 0x00, 0xc0, 0x0e, 0xa6, 0xb2, 0x00, 0x83, +0x00, 0x01, 0x40, 0x21, 0x04, 0x02, 0x3e, 0x21, 0x8c, 0xbe, 0x3e, 0x08, 0xff, 0x64, 0x80, 0x22, +0x49, 0xff, 0xe8, 0x58, 0x9d, 0xf9, 0x97, 0xf8, 0x88, 0xc8, 0xe2, 0xfc, 0xe9, 0xea, 0x84, 0x01, +0xec, 0x74, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x96, 0x49, 0x80, 0xc0, +0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xe2, 0xb4, 0x20, 0x84, 0xa6, 0xd1, 0x4f, +0xe6, 0x27, 0xe8, 0x11, 0x84, 0xa3, 0xd1, 0x2c, 0xe6, 0x24, 0xe8, 0x07, 0x84, 0xa1, 0xd1, 0x1b, +0x84, 0xa2, 0x4c, 0x12, 0xc0, 0xd3, 0xd5, 0x22, 0x84, 0xa4, 0xd1, 0x29, 0x84, 0xa5, 0x4c, 0x12, +0xc0, 0xcd, 0xd5, 0x38, 0x84, 0xa9, 0xd1, 0x4b, 0xe6, 0x2a, 0xe8, 0x07, 0x84, 0xa7, 0xd1, 0x3d, +0x84, 0xa8, 0x4c, 0x12, 0xc0, 0xc3, 0xd5, 0x3f, 0x84, 0xaa, 0xd1, 0x53, 0x84, 0xab, 0x4c, 0x12, +0xc0, 0xbd, 0xd5, 0x5d, 0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x3a, 0x59, 0x96, 0x48, 0xae, 0x40, +0xe6, 0x22, 0x4e, 0xf3, 0x00, 0xb3, 0x84, 0x20, 0xd5, 0x42, 0x84, 0x03, 0xd5, 0x02, 0x84, 0x04, +0x84, 0x20, 0x84, 0x41, 0x49, 0xfe, 0xa7, 0xdc, 0x48, 0x00, 0x00, 0xa8, 0x9d, 0xb4, 0xb4, 0x06, +0x96, 0x00, 0x84, 0xa1, 0x3e, 0x01, 0x3a, 0x5a, 0x4c, 0x02, 0xc0, 0xa0, 0x46, 0x10, 0x04, 0x00, +0x58, 0x10, 0x81, 0x28, 0xb4, 0x41, 0x46, 0x30, 0x00, 0xff, 0x84, 0x00, 0x40, 0x21, 0x0c, 0x04, +0xd5, 0x34, 0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x3a, 0x64, 0xd5, 0x21, 0x9d, 0xb4, 0xb4, 0x26, +0x3e, 0x09, 0x3a, 0x63, 0x96, 0x4c, 0xd5, 0x1b, 0x3c, 0x1c, 0x4e, 0x88, 0x84, 0x00, 0xb6, 0x26, +0x48, 0x00, 0x00, 0x85, 0x49, 0x00, 0x1e, 0x46, 0x48, 0x00, 0x00, 0x80, 0x3e, 0x79, 0x8a, 0x08, +0x80, 0x07, 0x84, 0x20, 0x84, 0x4a, 0x49, 0xfe, 0xb3, 0xc7, 0x8c, 0xea, 0x3e, 0x59, 0x8a, 0x58, +0xdf, 0xf8, 0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x3a, 0x5c, 0x96, 0x4c, 0xae, 0x40, 0xd5, 0x6d, +0x9d, 0xb4, 0xb4, 0x06, 0x84, 0xa1, 0xd8, 0x69, 0x3e, 0x1f, 0xee, 0xc4, 0xb4, 0x01, 0xc8, 0x65, +0x46, 0x20, 0x00, 0x82, 0x58, 0x21, 0x0d, 0x3c, 0xb6, 0x41, 0xd5, 0x60, 0x9d, 0xb4, 0xb4, 0x06, +0xb4, 0x86, 0xb4, 0x46, 0x40, 0x21, 0x20, 0x08, 0x42, 0x00, 0x0c, 0x0b, 0x92, 0x58, 0xc8, 0x12, +0x46, 0x10, 0x04, 0x00, 0x04, 0x30, 0x80, 0x49, 0x44, 0x5f, 0xf0, 0x00, 0x40, 0x31, 0x94, 0x04, +0x14, 0x30, 0x80, 0x49, 0x80, 0x01, 0x04, 0x10, 0x00, 0x4a, 0x58, 0x10, 0x8f, 0xff, 0x14, 0x10, +0x00, 0x4a, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x38, 0xb4, 0x60, 0x40, 0x12, 0x40, 0x08, +0x92, 0x68, 0x40, 0x31, 0xa0, 0x08, 0xb6, 0x60, 0x92, 0x38, 0xb4, 0x60, 0x44, 0x5f, 0x00, 0xff, +0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, 0x40, 0x41, 0x20, 0x08, 0xb4, 0x60, 0x40, 0x31, 0x94, 0x02, +0xb6, 0x60, 0x50, 0x10, 0x02, 0x04, 0xb4, 0x60, 0x40, 0x32, 0x0c, 0x04, 0xb6, 0x60, 0xb4, 0x01, +0x44, 0x40, 0x00, 0xc0, 0x92, 0x03, 0x94, 0x03, 0xb6, 0x01, 0x4c, 0x22, 0x40, 0x06, 0xb4, 0x01, +0x58, 0x00, 0x00, 0x02, 0xd5, 0x04, 0xb4, 0x01, 0x58, 0x00, 0x00, 0x01, 0xb6, 0x01, 0x3c, 0x2e, +0x4e, 0x86, 0x3c, 0x1d, 0xfb, 0xfe, 0x84, 0x00, 0xdd, 0x21, 0x46, 0x10, 0x04, 0x00, 0x80, 0x41, +0x80, 0x01, 0x04, 0x10, 0x80, 0x0e, 0x04, 0x21, 0x00, 0x49, 0x04, 0x30, 0x00, 0x4a, 0x3e, 0x08, +0xff, 0x80, 0x49, 0xff, 0xe7, 0x67, 0x92, 0x00, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x3c, 0x3c, 0x4e, 0x87, 0x80, 0xc1, 0x9c, 0x59, 0x3c, 0x1e, +0x4e, 0x87, 0x81, 0x20, 0x04, 0x83, 0x00, 0x04, 0x84, 0x0e, 0x40, 0x14, 0x50, 0x09, 0x54, 0x10, +0x80, 0x7f, 0x84, 0xe4, 0x4c, 0x10, 0x00, 0xb0, 0xe4, 0x2f, 0xe8, 0x22, 0x84, 0xa8, 0xd1, 0x3e, +0xe4, 0x29, 0xe8, 0x13, 0x84, 0xa2, 0x4c, 0x12, 0x80, 0x93, 0xe4, 0x23, 0xe8, 0x06, 0x84, 0xa1, +0x4c, 0x12, 0xc0, 0xa7, 0x48, 0x00, 0x00, 0x7d, 0x84, 0xa3, 0x4c, 0x12, 0x80, 0x8e, 0x84, 0xa6, +0x4c, 0x12, 0xc0, 0x9f, 0x48, 0x00, 0x00, 0x8e, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x34, 0xe0, 0x20, +0xe9, 0x2b, 0x84, 0xab, 0xd1, 0x37, 0x84, 0xac, 0x4c, 0x12, 0xc0, 0x93, 0xd5, 0x3d, 0x9d, 0x47, +0xd1, 0x52, 0xe4, 0x36, 0xe8, 0x0d, 0x9c, 0x02, 0x4c, 0x10, 0x00, 0x44, 0xe0, 0x20, 0xe9, 0x3a, +0x9d, 0x41, 0x4c, 0x12, 0x80, 0x7c, 0x9d, 0x44, 0x4c, 0x12, 0xc0, 0x83, 0xd5, 0x3f, 0x9d, 0x6c, +0xd1, 0x4c, 0xe4, 0x3a, 0xe8, 0x05, 0x9f, 0x69, 0x4c, 0x12, 0xc0, 0x7b, 0xd5, 0x41, 0x9d, 0x6d, +0xd1, 0x59, 0x9d, 0x69, 0x4c, 0x12, 0xc0, 0x75, 0xd5, 0x50, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, +0xf6, 0x75, 0x48, 0x00, 0x00, 0x73, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf6, 0x85, 0x48, 0x00, +0x00, 0x6d, 0xa0, 0x32, 0xa4, 0x76, 0x54, 0x74, 0x3f, 0xff, 0x49, 0xff, 0xf6, 0xbf, 0x48, 0x00, +0x00, 0x65, 0xa0, 0x32, 0x50, 0x13, 0x00, 0x0c, 0x49, 0xff, 0xf6, 0xd4, 0xa5, 0xf6, 0x54, 0x73, +0xbf, 0xff, 0x48, 0x00, 0x00, 0x5b, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf6, 0x93, 0x48, 0x00, +0x00, 0x55, 0xa0, 0x32, 0xa4, 0x76, 0x44, 0x70, 0x01, 0x40, 0x49, 0xff, 0xfa, 0x49, 0xd5, 0x4d, +0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xea, 0x9c, 0xd5, 0x48, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, +0x1a, 0xa7, 0xd5, 0x43, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xfb, 0xd4, 0xd5, 0x3e, 0xa0, 0x32, +0xa4, 0x76, 0x49, 0xff, 0xfa, 0x7d, 0xd5, 0x39, 0x40, 0x24, 0x40, 0x09, 0xa4, 0x76, 0xa0, 0x32, +0x54, 0x21, 0x00, 0x0f, 0x49, 0xff, 0xf9, 0xba, 0x84, 0x00, 0x48, 0x00, 0x00, 0x89, 0xa0, 0x32, +0xa4, 0x76, 0x49, 0xff, 0xfe, 0x73, 0xd5, 0x29, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x51, 0xa8, +0xd5, 0x24, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x3e, 0x4f, 0xd5, 0x1f, 0xa0, 0x32, 0xa4, 0x76, +0x49, 0x00, 0x3e, 0x8a, 0xd5, 0x1a, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x38, 0xcd, 0xd5, 0x15, +0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x23, 0xe4, 0xd5, 0x10, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, +0xf9, 0x67, 0xd5, 0x0b, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf5, 0xca, 0xd5, 0x06, 0x3e, 0x08, +0xff, 0xbc, 0x49, 0xff, 0xe6, 0x97, 0x84, 0x00, 0x46, 0x10, 0x04, 0x00, 0x04, 0x30, 0x80, 0x8c, +0x93, 0x10, 0x42, 0x31, 0xfc, 0x08, 0x54, 0x84, 0x00, 0x0f, 0x14, 0x30, 0x80, 0x8c, 0x4e, 0x83, +0x00, 0x04, 0x80, 0x08, 0xd5, 0x4c, 0x46, 0x1f, 0xff, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x73, +0x84, 0x02, 0x40, 0x84, 0x40, 0x08, 0x40, 0x73, 0xa0, 0x04, 0x42, 0x73, 0xf8, 0x09, 0x42, 0x73, +0xfc, 0x09, 0x46, 0x2f, 0xf0, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x42, 0x73, 0xf8, 0x08, 0x54, 0x00, +0x00, 0x0f, 0x40, 0x00, 0x50, 0x08, 0x40, 0x73, 0x88, 0x02, 0x40, 0x73, 0x80, 0x04, 0x46, 0x1c, +0x6f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x2e, 0x01, 0x3a, 0x59, 0x46, 0x21, 0x80, 0x00, 0x40, 0x73, +0x84, 0x02, 0x40, 0x73, 0x88, 0x04, 0x54, 0x00, 0x00, 0x03, 0x40, 0x00, 0x64, 0x08, 0x42, 0x73, +0xe4, 0x09, 0x42, 0x73, 0xe8, 0x09, 0x40, 0x73, 0x80, 0x04, 0x42, 0x73, 0xbc, 0x09, 0x54, 0x03, +0xbf, 0xff, 0xe4, 0x08, 0xe8, 0x06, 0x92, 0xee, 0x40, 0x73, 0xb8, 0x08, 0x58, 0x73, 0x80, 0x08, +0x54, 0x03, 0xbf, 0xff, 0xac, 0x36, 0x84, 0x01, 0x10, 0x03, 0x00, 0x0f, 0xa9, 0xf4, 0x80, 0x26, +0x80, 0x09, 0x49, 0xff, 0xe2, 0x33, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x01, 0x80, +0x44, 0x00, 0x00, 0x10, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x8a, 0xc4, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x11, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x8a, 0x90, 0xdd, 0x26, 0x84, 0x00, 0x46, 0x10, +0x00, 0x80, 0x58, 0x10, 0x85, 0x54, 0xdd, 0x26, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x84, 0xdc, +0x84, 0x01, 0xdd, 0x26, 0x49, 0xff, 0xe8, 0x10, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, 0xe1, 0x04, +0x3e, 0x19, 0x97, 0x18, 0x3c, 0x1e, 0x4e, 0xab, 0x84, 0xc0, 0x49, 0xff, 0xea, 0x9f, 0x3e, 0x39, +0x8a, 0x58, 0x84, 0x80, 0x10, 0x41, 0x84, 0x00, 0x14, 0x61, 0x80, 0x2d, 0x80, 0x26, 0x50, 0x01, +0x84, 0x02, 0x84, 0x48, 0x49, 0xfe, 0xb1, 0xe8, 0x46, 0x20, 0x04, 0x10, 0x58, 0x21, 0x08, 0x00, +0xa9, 0x94, 0x46, 0x30, 0x30, 0x00, 0xa0, 0x53, 0x40, 0x10, 0x8c, 0x04, 0xa8, 0x53, 0x3e, 0x08, +0xff, 0xec, 0x49, 0xff, 0xe5, 0xef, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x84, 0x60, 0xd5, 0x0e, +0x38, 0x50, 0x0c, 0x00, 0x38, 0x40, 0x8c, 0x00, 0x9c, 0xd9, 0xe2, 0x85, 0xe8, 0x03, 0x84, 0x01, +0xd5, 0x08, 0xe2, 0xa4, 0xe8, 0x03, 0x84, 0x02, 0xd5, 0x04, 0xe2, 0x62, 0xe9, 0xf2, 0x84, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0x9c, 0x01, 0x08, 0x60, 0x00, 0x01, 0x96, 0x49, +0xaf, 0x90, 0x08, 0x60, 0x00, 0x01, 0xaf, 0xa0, 0x08, 0x60, 0x00, 0x01, 0xaf, 0xa8, 0xa7, 0xa0, +0xa7, 0x40, 0xf4, 0x01, 0xce, 0x05, 0x97, 0xac, 0xc6, 0x03, 0x84, 0xc1, 0xd5, 0x02, 0x84, 0xc0, +0xaf, 0x98, 0x54, 0x32, 0x80, 0xfe, 0x95, 0x5b, 0xa6, 0x90, 0xe0, 0x25, 0xe9, 0x08, 0x9e, 0x94, +0x98, 0x9a, 0x96, 0x90, 0x9c, 0x91, 0x94, 0x93, 0xe0, 0x22, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x16, +0x40, 0x20, 0x8c, 0x09, 0x9a, 0xd3, 0x96, 0xd8, 0x98, 0x03, 0x84, 0xa8, 0x96, 0xdc, 0x40, 0x21, +0x8c, 0x1a, 0x40, 0x22, 0x8c, 0x1b, 0x20, 0x00, 0x00, 0x01, 0x54, 0x10, 0x80, 0x0f, 0x9a, 0x4a, +0x40, 0x10, 0x04, 0x0e, 0x96, 0x4c, 0xc1, 0x04, 0x84, 0x01, 0xae, 0x20, 0xd5, 0x02, 0xae, 0x60, +0x84, 0x01, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x84, 0x60, 0x80, 0x82, 0xd5, 0x07, 0x38, 0x50, +0x8c, 0x00, 0x9f, 0x21, 0x38, 0x50, 0x0c, 0x08, 0x9c, 0xd9, 0xcc, 0xfa, 0x98, 0x02, 0xdd, 0x9e, +0x84, 0x60, 0x80, 0x80, 0xd5, 0x09, 0x38, 0x52, 0x0c, 0x00, 0x38, 0x00, 0x8c, 0x00, 0x9c, 0xd9, +0x9a, 0x28, 0xc8, 0x04, 0x9e, 0x91, 0xca, 0xf8, 0x80, 0x02, 0xdd, 0x9e, 0x3e, 0x19, 0x97, 0x18, +0xb4, 0x41, 0x98, 0x02, 0xb6, 0x01, 0x80, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3e, 0x18, 0xf5, 0x58, +0x3c, 0x1e, 0x65, 0xc6, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xfb, +0xf3, 0x0f, 0x92, 0x05, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x2f, 0x94, 0x3c, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x81, 0x20, 0x50, 0x0f, 0x80, 0x20, 0xf0, 0x81, 0x80, 0xe1, +0x84, 0xc0, 0xf2, 0x01, 0x84, 0xbf, 0x9d, 0x14, 0xf4, 0x81, 0x40, 0x04, 0x98, 0x00, 0xb4, 0x62, +0x9c, 0x64, 0x80, 0x43, 0xd3, 0x07, 0xf1, 0x81, 0x99, 0xb3, 0xb4, 0x24, 0x49, 0xfe, 0xb1, 0x1e, +0xd5, 0xf1, 0x80, 0x06, 0xb6, 0xc7, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xec, 0x10, 0xdd, 0x9e, +0x84, 0x40, 0x80, 0x60, 0x38, 0x40, 0x88, 0x00, 0x9c, 0x91, 0x18, 0x41, 0x80, 0x01, 0x84, 0x86, +0x4c, 0x22, 0x7f, 0xfa, 0x98, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xc0, 0x54, 0xa0, +0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x81, 0x04, 0x80, 0xe3, +0x49, 0xfe, 0xb1, 0x12, 0xa6, 0xf0, 0xa6, 0x31, 0x54, 0x31, 0x80, 0x03, 0x54, 0x24, 0x80, 0x01, +0x42, 0x00, 0x00, 0x09, 0x40, 0x15, 0x10, 0x08, 0x40, 0x11, 0x84, 0x04, 0x40, 0x00, 0x08, 0x04, +0xae, 0x70, 0xae, 0x31, 0x80, 0x27, 0x9c, 0x34, 0x49, 0xff, 0xff, 0xd4, 0x3e, 0x19, 0x8e, 0x64, +0x50, 0x03, 0x00, 0x0a, 0x49, 0xff, 0xff, 0xce, 0x50, 0x03, 0x00, 0x10, 0x80, 0x28, 0x49, 0xff, +0xff, 0xc9, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xc0, +0x80, 0xe1, 0x81, 0x22, 0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x81, 0x03, 0x49, 0xfe, 0xb0, 0xe4, +0x92, 0x00, 0xa6, 0x70, 0x44, 0x2f, 0xff, 0xd0, 0x54, 0x10, 0x80, 0x03, 0x40, 0x10, 0x88, 0x04, +0x80, 0x06, 0x18, 0x10, 0x00, 0x04, 0x80, 0x27, 0x49, 0xff, 0xff, 0xac, 0x80, 0x29, 0x50, 0x03, +0x00, 0x0a, 0x49, 0xff, 0xff, 0xa7, 0x80, 0x28, 0x50, 0x03, 0x00, 0x10, 0x49, 0xff, 0xff, 0xa2, +0x3c, 0x20, 0xc7, 0x06, 0x9c, 0x91, 0x96, 0x91, 0x54, 0x11, 0x0f, 0xff, 0x3c, 0x18, 0xc7, 0x06, +0x54, 0x01, 0x00, 0x0f, 0x00, 0x23, 0x00, 0x16, 0x94, 0x04, 0x54, 0x21, 0x00, 0x0f, 0x40, 0x21, +0x00, 0x04, 0x92, 0x24, 0x10, 0x13, 0x00, 0x17, 0x10, 0x23, 0x00, 0x16, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, 0x40, 0x80, 0x80, 0x13, +0x49, 0x00, 0x1c, 0x6a, 0x3e, 0x09, 0x83, 0x70, 0x49, 0xff, 0xe6, 0x72, 0x80, 0xe0, 0xc8, 0x08, +0x3e, 0x08, 0xf6, 0xd0, 0x3e, 0x19, 0x00, 0x40, 0x49, 0xff, 0xe4, 0xb4, 0xd5, 0x44, 0xa1, 0x82, +0x8c, 0xd8, 0x3e, 0x19, 0x8c, 0x9d, 0x80, 0x61, 0x50, 0x03, 0x7f, 0xe8, 0x3e, 0x29, 0x8e, 0x64, +0x49, 0xff, 0xff, 0xa4, 0x2e, 0x01, 0x8e, 0x7a, 0x00, 0x13, 0x7f, 0xe9, 0x96, 0x04, 0x94, 0x04, +0x42, 0x10, 0x90, 0x09, 0x40, 0x10, 0x80, 0x04, 0x04, 0x04, 0x80, 0x04, 0x10, 0x13, 0x7f, 0xe9, +0x84, 0x23, 0xa6, 0xb5, 0xae, 0x70, 0x84, 0x21, 0xae, 0x71, 0x58, 0x21, 0x00, 0x02, 0x42, 0x31, +0x00, 0x09, 0x00, 0x40, 0x00, 0x1a, 0x40, 0x14, 0x20, 0x09, 0xae, 0xf5, 0xaf, 0x32, 0xae, 0x74, +0x10, 0x83, 0x00, 0x03, 0x54, 0x21, 0x00, 0x02, 0x00, 0x10, 0x00, 0x1b, 0x84, 0x00, 0x54, 0x10, +0x80, 0x3c, 0x40, 0x21, 0x04, 0x04, 0x44, 0x10, 0x00, 0x10, 0xae, 0xb5, 0xae, 0x76, 0xae, 0x37, +0x10, 0x03, 0x00, 0x08, 0x50, 0x13, 0x7f, 0xe8, 0x80, 0x67, 0x44, 0x20, 0x00, 0x21, 0x49, 0x00, +0x02, 0x55, 0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xdc, 0x84, 0xa0, 0xf4, 0x83, 0xad, 0x60, 0x80, 0xa0, 0x08, 0x82, 0x80, 0x0a, 0xf3, 0x82, +0x93, 0x04, 0xf1, 0x85, 0x14, 0x8f, 0x80, 0x04, 0x80, 0xc0, 0x80, 0x25, 0x80, 0x02, 0x49, 0xff, +0xff, 0x19, 0xf0, 0x02, 0x50, 0x13, 0x00, 0x10, 0x3f, 0xc9, 0x8a, 0x58, 0x49, 0xff, 0xff, 0x12, +0x44, 0xa0, 0x00, 0x24, 0x50, 0x73, 0x00, 0x24, 0x50, 0x9e, 0x02, 0x57, 0x50, 0x6f, 0x80, 0x1f, +0xd5, 0x3d, 0xf0, 0x03, 0xa4, 0x80, 0x98, 0x91, 0x5e, 0xf1, 0x01, 0x7e, 0xe8, 0x3d, 0xa6, 0xb8, +0x84, 0x65, 0x4c, 0x21, 0x80, 0x18, 0x44, 0x40, 0x00, 0x25, 0x4c, 0x22, 0x40, 0x2c, 0x84, 0x03, +0x4c, 0x10, 0x40, 0x29, 0x3e, 0x09, 0x00, 0x18, 0x49, 0xff, 0xe4, 0x34, 0xa7, 0xfb, 0x3e, 0x71, +0x8e, 0x78, 0x49, 0xff, 0xec, 0x71, 0x3e, 0x09, 0x8e, 0x10, 0x49, 0xff, 0xe4, 0x79, 0x84, 0x00, +0xd5, 0x24, 0xf1, 0x04, 0x84, 0x68, 0x4c, 0x11, 0xc0, 0x16, 0xf0, 0x02, 0x3e, 0x19, 0x8c, 0x9d, +0x84, 0x46, 0x49, 0xff, 0xfe, 0x97, 0xc8, 0x0e, 0x02, 0x1e, 0x01, 0x29, 0xb7, 0x3f, 0x80, 0x07, +0x80, 0x46, 0x50, 0x34, 0xff, 0xff, 0x50, 0x44, 0xff, 0xfd, 0x50, 0x54, 0xff, 0xfe, 0x49, 0xff, +0xfe, 0x3b, 0xa6, 0x79, 0x9c, 0x4a, 0x99, 0xf9, 0x89, 0x41, 0xa6, 0x79, 0xf0, 0x05, 0x9c, 0x8a, +0x88, 0x4a, 0xe2, 0x02, 0xe8, 0xbf, 0x84, 0x01, 0xec, 0x24, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, +0x49, 0xfe, 0xaf, 0xe2, 0x92, 0x00, 0xa6, 0xb0, 0xa6, 0xf4, 0xa6, 0x31, 0x84, 0x3e, 0x40, 0x41, +0x04, 0x02, 0x92, 0x02, 0x94, 0x02, 0x40, 0x11, 0x84, 0x02, 0xaf, 0x30, 0xae, 0x74, 0xae, 0x31, +0x00, 0x83, 0x00, 0x07, 0x00, 0x93, 0x80, 0x9d, 0xa6, 0x33, 0x10, 0x93, 0x00, 0x05, 0xa1, 0x3b, +0x00, 0x13, 0x80, 0x9e, 0xa7, 0x72, 0x98, 0x61, 0x96, 0x49, 0x40, 0x40, 0xa0, 0x09, 0x54, 0x42, +0x00, 0x3f, 0x40, 0x74, 0x18, 0x09, 0x95, 0xfe, 0x40, 0x73, 0x90, 0x04, 0x54, 0x31, 0x80, 0x02, +0x44, 0x4f, 0xff, 0xea, 0x40, 0x21, 0x10, 0x02, 0x54, 0x52, 0x80, 0x7f, 0x40, 0x40, 0x0c, 0x09, +0x95, 0x23, 0x58, 0x31, 0x80, 0x1c, 0xae, 0x76, 0xaf, 0xf7, 0xaf, 0x72, 0xae, 0xb0, 0xae, 0xf4, +0xaf, 0x33, 0x3c, 0x2c, 0x63, 0x2c, 0x54, 0x00, 0x00, 0x18, 0x84, 0x20, 0xe6, 0x4f, 0xe9, 0x03, +0x58, 0x00, 0x00, 0x20, 0xae, 0x33, 0xa6, 0x30, 0xae, 0x72, 0x54, 0x00, 0x00, 0x1d, 0xae, 0x30, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xe0, 0x44, 0x00, +0x00, 0x18, 0x50, 0x63, 0x80, 0x24, 0x10, 0x03, 0x80, 0x9e, 0x84, 0x20, 0x80, 0x06, 0x44, 0x20, +0x00, 0x18, 0x49, 0xfe, 0xaf, 0x89, 0x92, 0x00, 0xa6, 0x30, 0x84, 0x33, 0x40, 0x00, 0x04, 0x02, +0x58, 0x00, 0x00, 0x08, 0xae, 0x30, 0x2e, 0x11, 0x8e, 0x49, 0x54, 0x00, 0x00, 0x0f, 0xc1, 0x05, +0x44, 0x2f, 0xff, 0x80, 0x40, 0x00, 0x08, 0x04, 0xa6, 0x71, 0x42, 0x10, 0x84, 0x09, 0x58, 0x10, +0x80, 0x01, 0xae, 0x71, 0xae, 0x30, 0x3e, 0x09, 0x8a, 0x58, 0x02, 0x20, 0x01, 0xda, 0x50, 0x10, +0x02, 0x45, 0x9c, 0x91, 0x96, 0x91, 0x54, 0x31, 0x0f, 0xff, 0x12, 0x30, 0x01, 0xda, 0x44, 0x4f, +0xff, 0xdb, 0xa6, 0x31, 0x92, 0x64, 0x40, 0x00, 0x10, 0x02, 0x94, 0x94, 0x10, 0x33, 0x00, 0x17, +0x10, 0x23, 0x00, 0x16, 0xae, 0x31, 0x84, 0x46, 0x9c, 0x34, 0x49, 0xfe, 0xaf, 0x35, 0x3e, 0x19, +0x8e, 0x64, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x49, 0xfe, 0xaf, 0x2e, 0xa0, 0x79, 0x50, 0x03, +0x00, 0x10, 0x84, 0x46, 0x49, 0xfe, 0xaf, 0x28, 0x00, 0x03, 0x80, 0x94, 0xc0, 0x05, 0xa6, 0x31, +0x58, 0x00, 0x00, 0x40, 0xae, 0x31, 0x2e, 0x11, 0x8e, 0x7a, 0xa6, 0x31, 0xc1, 0x04, 0x58, 0x00, +0x00, 0x10, 0xd5, 0x03, 0x42, 0x00, 0x10, 0x09, 0xae, 0x31, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0xc8, 0xcb, 0x10, 0x3e, 0x49, 0x8a, 0x58, 0x00, 0x22, +0x01, 0x74, 0xca, 0x05, 0x80, 0x82, 0x44, 0x30, 0x00, 0xff, 0xd5, 0x0b, 0x00, 0x12, 0x01, 0x75, +0xc1, 0x04, 0x50, 0x42, 0x01, 0x34, 0xd5, 0x05, 0x84, 0x80, 0x44, 0x30, 0x00, 0xff, 0x80, 0x44, +0x14, 0x40, 0x00, 0x26, 0x10, 0x30, 0x00, 0x9c, 0x10, 0x20, 0x00, 0x94, 0x3e, 0x19, 0x02, 0x48, +0x3e, 0x09, 0x00, 0x54, 0x49, 0xff, 0xe3, 0x26, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, +0x49, 0xfe, 0xaf, 0x02, 0xa6, 0xf0, 0xa6, 0xb4, 0xa6, 0x31, 0x92, 0x02, 0x94, 0x02, 0x58, 0x21, +0x00, 0x01, 0x42, 0x11, 0x80, 0x09, 0xae, 0xb4, 0xae, 0x70, 0xae, 0x31, 0x00, 0x83, 0x00, 0x07, +0x00, 0x93, 0x80, 0x9d, 0xa7, 0x72, 0x10, 0x93, 0x00, 0x05, 0x00, 0x03, 0x80, 0x9e, 0xa0, 0x7b, +0x40, 0x74, 0x18, 0x09, 0x95, 0xfe, 0x98, 0x48, 0x96, 0x49, 0x40, 0x40, 0xa0, 0x09, 0xa6, 0x33, +0x54, 0x42, 0x00, 0x3f, 0x40, 0x73, 0x90, 0x04, 0x44, 0x4f, 0xff, 0xea, 0x40, 0x31, 0x90, 0x02, +0x54, 0x52, 0x80, 0x7f, 0x54, 0x21, 0x00, 0x03, 0x40, 0x40, 0x0c, 0x09, 0x95, 0x23, 0xae, 0x76, +0xaf, 0xf7, 0xaf, 0x72, 0xae, 0xf0, 0xae, 0xb4, 0xaf, 0x33, 0x3c, 0x1c, 0x63, 0x2c, 0xe6, 0x2f, +0xe9, 0x12, 0x3e, 0x09, 0x00, 0x70, 0x3e, 0x19, 0x02, 0x60, 0x49, 0xff, 0xe2, 0xdb, 0xa6, 0x72, +0xa6, 0x33, 0x92, 0x27, 0x94, 0x4f, 0x54, 0x00, 0x00, 0x1f, 0x58, 0x10, 0x80, 0x03, 0x58, 0x00, +0x00, 0x20, 0xd5, 0x04, 0x54, 0x00, 0x00, 0x18, 0x84, 0x23, 0xae, 0x33, 0xa6, 0x30, 0xae, 0x72, +0x54, 0x00, 0x00, 0x1d, 0xae, 0x30, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xc2, 0x12, 0xa6, 0x11, 0x96, 0x44, 0xc9, 0x0f, 0x54, 0x10, +0x00, 0x02, 0xc1, 0x04, 0x3e, 0x09, 0x00, 0x80, 0xd5, 0x07, 0x54, 0x00, 0x00, 0x04, 0x96, 0x00, +0xc0, 0x06, 0x3e, 0x09, 0x00, 0x8c, 0x49, 0xff, 0xe2, 0xad, 0x84, 0x01, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x84, 0x61, 0x80, 0xe0, 0x3e, 0x31, +0x3a, 0x5d, 0x3e, 0x09, 0x8a, 0x58, 0x80, 0x27, 0x49, 0xff, 0xdd, 0xfe, 0x80, 0xc0, 0xc8, 0x0a, +0xb4, 0x27, 0x3e, 0x09, 0x83, 0x70, 0x49, 0xff, 0xe4, 0x6d, 0x3e, 0x09, 0x00, 0x98, 0x49, 0xff, +0xe2, 0x91, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0xef, 0x60, 0x81, 0x01, 0x80, 0xe2, 0x50, 0x9f, 0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, +0x80, 0x1f, 0x81, 0x43, 0x49, 0xfe, 0xae, 0x68, 0x84, 0x80, 0x80, 0x28, 0x80, 0x47, 0x84, 0x61, +0x80, 0x09, 0xf4, 0x83, 0xf4, 0x82, 0x10, 0x3f, 0x80, 0x9d, 0xb7, 0x5f, 0x14, 0x8f, 0x80, 0x01, +0x49, 0xfe, 0xae, 0x3a, 0x96, 0xb8, 0x40, 0x04, 0x88, 0x00, 0x9c, 0xc3, 0x92, 0x62, 0x94, 0xda, +0x9a, 0xd8, 0x80, 0x3f, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, 0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, +0x49, 0xff, 0xff, 0x40, 0x80, 0x1f, 0x49, 0xff, 0xff, 0xb7, 0x80, 0xdf, 0x84, 0x01, 0xec, 0xa0, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x5c, 0x81, 0x21, +0x81, 0x02, 0x50, 0xaf, 0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x83, 0x83, +0x84, 0xe0, 0x49, 0xfe, 0xae, 0x31, 0x80, 0x29, 0x80, 0x48, 0x84, 0x7f, 0x80, 0x0a, 0x10, 0x3f, +0x80, 0x9d, 0x15, 0xcf, 0x80, 0x00, 0xf7, 0x82, 0xf7, 0x83, 0x14, 0x9f, 0x80, 0x01, 0x49, 0xfe, +0xae, 0x03, 0x54, 0x24, 0x00, 0xff, 0x40, 0x05, 0x08, 0x00, 0x9c, 0xc3, 0x92, 0x62, 0x94, 0xda, +0x9a, 0xd8, 0x80, 0x3f, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, 0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, +0x49, 0xff, 0xff, 0x08, 0x80, 0x1f, 0x49, 0xff, 0xff, 0x7f, 0x40, 0x03, 0x80, 0x06, 0x80, 0xdf, +0xec, 0xa4, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0x81, 0x01, +0x80, 0xe2, 0x50, 0x9f, 0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x81, 0x43, +0x49, 0xfe, 0xad, 0xfa, 0x84, 0x80, 0x80, 0x28, 0x80, 0x47, 0x84, 0x7f, 0x80, 0x09, 0xf4, 0x83, +0xf4, 0x82, 0x10, 0x3f, 0x80, 0x9d, 0xb7, 0x5f, 0x14, 0x8f, 0x80, 0x01, 0x49, 0xfe, 0xad, 0xcc, +0x96, 0xb8, 0x40, 0x04, 0x88, 0x00, 0x9c, 0xc3, 0x92, 0x62, 0x94, 0xda, 0x9a, 0xd8, 0x80, 0x3f, +0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, 0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, 0x49, 0xff, 0xfd, 0xf2, +0x80, 0x1f, 0x49, 0xff, 0xff, 0x49, 0x80, 0xdf, 0x84, 0x01, 0xec, 0xa0, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0xa1, 0xc2, 0x81, 0x00, 0x40, 0x90, +0x80, 0x13, 0x54, 0xa1, 0x00, 0xff, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x49, 0xfe, +0xad, 0xc3, 0x50, 0x24, 0xff, 0xf2, 0x80, 0x2a, 0x50, 0x33, 0x80, 0x0e, 0x80, 0x1f, 0xf2, 0x83, +0x84, 0x41, 0x10, 0x2f, 0x80, 0x9d, 0xf3, 0x82, 0xb7, 0x1f, 0xf7, 0x81, 0x49, 0xff, 0xfe, 0x82, +0x80, 0x1f, 0x49, 0xff, 0xfe, 0x1b, 0x00, 0x1f, 0x80, 0x9e, 0x2e, 0x01, 0x8e, 0x49, 0x50, 0x2f, +0x80, 0x24, 0x98, 0x51, 0xc0, 0x0a, 0x84, 0x00, 0xae, 0x09, 0xae, 0x08, 0x9c, 0x4a, 0x00, 0x0f, +0x80, 0x9e, 0x9c, 0x02, 0x10, 0x0f, 0x80, 0x9e, 0x9d, 0xcb, 0x92, 0xe2, 0x95, 0xfa, 0x9a, 0xf9, +0x10, 0x3f, 0x80, 0x9f, 0x3e, 0x19, 0x37, 0x88, 0x84, 0x46, 0x80, 0x07, 0x49, 0xfe, 0xad, 0x74, +0xf1, 0x01, 0x9c, 0x3e, 0x8c, 0x2c, 0x84, 0x42, 0x49, 0xfe, 0xad, 0x6e, 0x00, 0x2f, 0x80, 0x9e, +0x80, 0x3f, 0x8c, 0x48, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x2f, 0x80, 0x9e, 0x49, 0xff, 0xfe, 0x7a, +0x80, 0x1f, 0x49, 0xff, 0xfe, 0xf1, 0x92, 0x00, 0x80, 0xdf, 0x84, 0x00, 0xec, 0xa0, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xec, 0x3e, 0x79, 0x8a, 0x58, 0x00, 0x13, +0x82, 0x60, 0x80, 0xc0, 0xc1, 0x36, 0xa0, 0x42, 0x84, 0x46, 0x50, 0x03, 0x82, 0x45, 0x8c, 0x2a, +0x49, 0xff, 0xfb, 0xf8, 0x81, 0x00, 0xc8, 0x2d, 0xa0, 0x32, 0x44, 0x50, 0x00, 0xa0, 0xa6, 0x00, +0x54, 0x00, 0x00, 0xf0, 0xd8, 0x10, 0x04, 0x03, 0x80, 0x9a, 0x54, 0x00, 0x08, 0x00, 0xc0, 0x0b, +0x3e, 0x09, 0x00, 0xb8, 0x49, 0xff, 0xe1, 0x6e, 0x80, 0x28, 0x44, 0x00, 0x01, 0x00, 0x80, 0x46, +0x49, 0xff, 0xea, 0x72, 0xa0, 0x32, 0x44, 0x50, 0x00, 0xc0, 0xa6, 0x00, 0x54, 0x00, 0x00, 0xf0, +0xd8, 0x10, 0x3c, 0x0c, 0x63, 0x30, 0x54, 0x00, 0x08, 0x00, 0xc0, 0x0b, 0x3e, 0x09, 0x00, 0xe8, +0x49, 0xff, 0xe1, 0x58, 0x44, 0x00, 0x02, 0x00, 0x84, 0x20, 0x80, 0x46, 0x49, 0xff, 0xea, 0x5c, +0xa0, 0x72, 0x44, 0x50, 0x00, 0x80, 0xa6, 0x08, 0x54, 0x00, 0x00, 0xf0, 0x4c, 0x02, 0xc0, 0xa9, +0x8c, 0x2a, 0x3e, 0x09, 0x8c, 0x9d, 0x84, 0x46, 0x49, 0xff, 0xfb, 0xbc, 0x4e, 0x03, 0x00, 0xa1, +0x49, 0xff, 0xfb, 0xd4, 0x3e, 0x79, 0x8a, 0x58, 0x14, 0x03, 0x80, 0x93, 0x80, 0x5f, 0xa0, 0x32, +0x50, 0x3f, 0x80, 0x08, 0x00, 0x10, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x94, 0x4c, 0x92, 0x04, +0x40, 0x00, 0x80, 0x04, 0x12, 0x03, 0x81, 0x28, 0x50, 0x4f, 0x80, 0x0e, 0xa0, 0x34, 0x02, 0x13, +0x00, 0x0a, 0x49, 0xff, 0xfc, 0xbd, 0xc8, 0x07, 0x3e, 0x09, 0x01, 0x14, 0x49, 0xff, 0xe1, 0x22, +0x48, 0x00, 0x00, 0xa9, 0x2e, 0x51, 0x8e, 0x6c, 0x84, 0x21, 0xd9, 0x2d, 0x2e, 0x91, 0x8e, 0x71, +0x4e, 0x93, 0x00, 0x2a, 0x02, 0x03, 0x81, 0x2b, 0xc0, 0x19, 0x00, 0x53, 0x84, 0x00, 0xd9, 0x16, +0x00, 0x03, 0x82, 0x57, 0xc0, 0x13, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x25, 0x3e, 0x09, +0x01, 0x5c, 0x49, 0xff, 0xe1, 0x07, 0x2e, 0x01, 0x8e, 0x7b, 0x84, 0xa1, 0xd8, 0x05, 0x49, 0x00, +0x15, 0x9b, 0x3e, 0x91, 0x8e, 0x7b, 0x49, 0xff, 0xe7, 0x8b, 0x3e, 0x09, 0x8e, 0x6c, 0x84, 0x20, +0x84, 0x41, 0xae, 0x43, 0x3e, 0x21, 0x3a, 0x61, 0x2e, 0x21, 0x8c, 0xae, 0x2e, 0x11, 0x8c, 0xaf, +0xae, 0x81, 0xae, 0x42, 0x3e, 0x09, 0x8e, 0x6c, 0xb4, 0x20, 0x40, 0x10, 0xa0, 0x08, 0x92, 0x28, +0x84, 0xa1, 0xd9, 0x46, 0xa6, 0x85, 0xca, 0x44, 0xa6, 0x04, 0x84, 0xa1, 0xd8, 0x03, 0x84, 0x22, +0xd5, 0x16, 0x84, 0xa2, 0xd8, 0x04, 0x44, 0x10, 0x00, 0xc8, 0xd5, 0x11, 0x84, 0xa3, 0xd0, 0x0d, +0x84, 0x24, 0x4c, 0x00, 0x80, 0x0b, 0x56, 0x00, 0x00, 0x05, 0x44, 0x30, 0x13, 0x88, 0x40, 0x11, +0x00, 0x1b, 0x40, 0x11, 0x80, 0x1a, 0xd5, 0x03, 0x44, 0x10, 0x07, 0xd0, 0x2e, 0x31, 0x8c, 0xac, +0xcb, 0x03, 0x2e, 0x31, 0x8c, 0xad, 0x46, 0x00, 0x04, 0x11, 0x04, 0x70, 0x00, 0x49, 0x3c, 0x4c, +0x63, 0x9d, 0x44, 0x20, 0x03, 0xe8, 0x95, 0xfe, 0x42, 0x42, 0x08, 0x24, 0x50, 0x73, 0xec, 0x78, +0x9b, 0xf9, 0x9e, 0xd9, 0x46, 0x20, 0x04, 0x00, 0x42, 0x72, 0x0c, 0x73, 0x04, 0x11, 0x00, 0x25, +0x04, 0x30, 0x00, 0x49, 0x80, 0x47, 0x3e, 0x09, 0x01, 0x7c, 0x49, 0xff, 0xe0, 0xab, 0x5e, 0xf3, +0xae, 0xe1, 0xe9, 0x06, 0x2e, 0x01, 0x8e, 0x70, 0x80, 0x27, 0x49, 0x00, 0x16, 0xc3, 0x3e, 0x79, +0x8a, 0x58, 0x04, 0x03, 0x80, 0x9a, 0x40, 0x00, 0x3c, 0x08, 0x92, 0x1f, 0xc0, 0x23, 0xa0, 0x32, +0x44, 0x50, 0x00, 0xd0, 0xa6, 0x00, 0x54, 0x00, 0x00, 0xf0, 0xd8, 0x1c, 0xa0, 0x34, 0x00, 0x10, +0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0xc9, 0x0e, 0x84, 0xa4, 0xd8, 0x14, 0x3e, 0x09, 0x01, 0xa8, +0x49, 0xff, 0xe0, 0x88, 0x49, 0xff, 0xe8, 0xc8, 0x50, 0x03, 0x83, 0xb8, 0x49, 0xff, 0xe0, 0xd0, +0xd5, 0x09, 0x84, 0xa3, 0xd9, 0x07, 0xc8, 0x06, 0x80, 0x06, 0x44, 0x10, 0x00, 0x25, 0x49, 0xff, +0xfb, 0xb3, 0xec, 0x14, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0x2e, 0x11, 0x8c, 0xb8, 0x80, 0xe0, 0xc1, 0x03, 0x49, 0xff, 0xeb, 0x80, 0x2e, 0x51, 0x8d, 0xfc, +0x84, 0x21, 0x4c, 0x50, 0x80, 0x91, 0x3e, 0x69, 0x8e, 0x6c, 0xa6, 0x30, 0x4e, 0x02, 0x00, 0x8c, +0xa7, 0x75, 0x4c, 0x50, 0x80, 0x89, 0xb4, 0x07, 0xa6, 0x00, 0x54, 0x80, 0x00, 0x60, 0x4e, 0x83, +0x00, 0x16, 0x54, 0x00, 0x00, 0x10, 0xc0, 0x12, 0xa0, 0x3a, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x20, +0x96, 0x00, 0xc0, 0x0b, 0x00, 0x53, 0x00, 0x0f, 0xd9, 0x05, 0x49, 0x00, 0x14, 0xe5, 0x10, 0x83, +0x00, 0x0f, 0x49, 0xff, 0xe6, 0xd5, 0xd5, 0x02, 0xae, 0x32, 0x2e, 0x01, 0x8c, 0xaf, 0xc0, 0x04, +0x2e, 0x01, 0x8e, 0x6e, 0xc8, 0x04, 0x2e, 0x01, 0x8e, 0x6d, 0xc0, 0x0a, 0x84, 0x40, 0x3e, 0x21, +0x8e, 0x6f, 0x84, 0x41, 0x3e, 0x09, 0x01, 0xd0, 0x3e, 0x21, 0x3a, 0x61, 0xd5, 0x06, 0x84, 0x41, +0x3e, 0x21, 0x8e, 0x6f, 0x3e, 0x09, 0x01, 0xec, 0x49, 0xff, 0xe0, 0x2c, 0x3e, 0x09, 0x8e, 0x6c, +0xb4, 0x20, 0x46, 0x2f, 0xf0, 0x00, 0x58, 0x21, 0x00, 0xff, 0x40, 0x50, 0x88, 0x02, 0x46, 0x20, +0x10, 0x00, 0x58, 0x21, 0x00, 0x01, 0xda, 0x47, 0xa6, 0x85, 0xca, 0x45, 0xa6, 0x04, 0x84, 0xa1, +0xd8, 0x03, 0x84, 0x22, 0xd5, 0x16, 0x84, 0xa2, 0xd8, 0x04, 0x44, 0x10, 0x00, 0xc8, 0xd5, 0x11, +0x84, 0xa3, 0xd0, 0x0d, 0x84, 0x24, 0x4c, 0x00, 0x80, 0x0b, 0x56, 0x00, 0x00, 0x05, 0x44, 0x30, +0x13, 0x88, 0x40, 0x11, 0x00, 0x1b, 0x40, 0x11, 0x80, 0x1a, 0xd5, 0x03, 0x44, 0x10, 0x07, 0xd0, +0x2e, 0x21, 0x8c, 0xac, 0xca, 0x03, 0x2e, 0x21, 0x8c, 0xad, 0x46, 0x00, 0x04, 0x11, 0x04, 0x60, +0x00, 0x49, 0x3e, 0x79, 0x8e, 0x6c, 0xa0, 0xfa, 0x44, 0x00, 0x03, 0xe8, 0x95, 0xb6, 0x42, 0x31, +0x80, 0x24, 0x50, 0x63, 0x6c, 0x78, 0x9b, 0xb1, 0x9e, 0x91, 0x46, 0x00, 0x04, 0x00, 0x42, 0x61, +0x88, 0x73, 0x04, 0x10, 0x00, 0x25, 0x80, 0x46, 0x3e, 0x09, 0x02, 0x08, 0x49, 0xff, 0xdf, 0xe2, +0x5e, 0xf3, 0x2e, 0xe1, 0xe9, 0x08, 0x84, 0x41, 0xa6, 0x3c, 0x10, 0x23, 0x80, 0x0e, 0x80, 0x26, +0x49, 0x00, 0x15, 0xf8, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0xef, 0xe0, 0xa4, 0x46, 0x81, 0x20, 0x5c, 0xf0, 0x80, 0x38, 0xe8, 0x06, 0x3e, 0x09, 0x02, 0x28, +0x49, 0xff, 0xdf, 0xc8, 0xd5, 0x16, 0x04, 0x80, 0x00, 0x02, 0x50, 0x64, 0x00, 0x04, 0xa6, 0xf7, +0x50, 0x74, 0x00, 0x20, 0x92, 0x65, 0x80, 0x26, 0x80, 0x07, 0x80, 0x48, 0x3e, 0x31, 0x8e, 0x59, +0x49, 0xff, 0xfc, 0xf8, 0x84, 0xa1, 0xd8, 0x07, 0x3e, 0x09, 0x02, 0x30, 0x49, 0xff, 0xdf, 0xb2, +0x84, 0x00, 0xd5, 0x2d, 0x50, 0x0f, 0x80, 0x04, 0xb7, 0x00, 0x14, 0x90, 0x00, 0x03, 0xa9, 0x81, +0xa9, 0xc2, 0xa9, 0xc4, 0x2e, 0x21, 0x8d, 0xfc, 0xa6, 0x73, 0xa6, 0xf2, 0x54, 0x10, 0x80, 0x3f, +0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x8c, 0x04, 0x84, 0xa1, 0xda, 0x02, 0xd5, 0xea, 0x12, 0x10, +0x00, 0x0a, 0x84, 0x20, 0x12, 0x10, 0x00, 0x0b, 0xa6, 0x78, 0x92, 0x22, 0x54, 0x10, 0x80, 0x03, +0xc1, 0x06, 0x84, 0xa2, 0xd9, 0x07, 0x49, 0xff, 0xff, 0x1b, 0xd5, 0x08, 0x49, 0xff, 0xfd, 0xfc, +0xd5, 0x05, 0x3e, 0x09, 0x02, 0x44, 0x49, 0xff, 0xdf, 0x85, 0x84, 0x01, 0xec, 0x20, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x96, 0x00, 0x96, 0x48, 0x95, 0x02, 0x44, 0x32, +0x0d, 0x60, 0x99, 0x21, 0x99, 0x23, 0x00, 0x31, 0x00, 0x40, 0x95, 0x25, 0x84, 0xa0, 0x38, 0x71, +0x14, 0x00, 0x99, 0xac, 0xaf, 0xf0, 0x9d, 0x69, 0x44, 0x60, 0x00, 0x10, 0xde, 0xf9, 0x99, 0x66, +0x84, 0xd0, 0x4c, 0x23, 0x00, 0x0a, 0x50, 0x72, 0x00, 0x18, 0x9b, 0x94, 0x38, 0x83, 0x14, 0x00, +0x18, 0x82, 0x80, 0x01, 0xdf, 0xfc, 0x44, 0x5f, 0xff, 0xe8, 0xd2, 0x0b, 0x9a, 0x94, 0x50, 0x52, +0x00, 0x18, 0x50, 0x42, 0x00, 0x20, 0x38, 0x61, 0x14, 0x00, 0x18, 0x62, 0x80, 0x01, 0xdc, 0xfc, +0x46, 0x60, 0x01, 0x06, 0x40, 0x20, 0x04, 0x09, 0x58, 0x63, 0x0c, 0x00, 0x98, 0x96, 0x94, 0x92, +0x97, 0x04, 0xb4, 0x02, 0xcc, 0x22, 0xc9, 0x05, 0x54, 0x31, 0x80, 0x0f, 0x84, 0x30, 0xd5, 0x13, +0x84, 0x81, 0x4c, 0x12, 0x40, 0x08, 0x54, 0x31, 0x80, 0x0f, 0x94, 0xdc, 0x44, 0x5f, 0xff, 0x0f, +0xd5, 0x35, 0x84, 0xc2, 0x54, 0x31, 0x80, 0x0f, 0x4c, 0x13, 0x40, 0x09, 0x40, 0x31, 0xa0, 0x08, +0x44, 0x1f, 0xf0, 0xff, 0x40, 0x00, 0x04, 0x02, 0xd5, 0x30, 0x44, 0x4f, 0x0f, 0xff, 0x40, 0x31, +0xb0, 0x08, 0x40, 0x00, 0x10, 0x02, 0xd5, 0x29, 0xc9, 0x0a, 0x54, 0x31, 0x80, 0x0f, 0x46, 0x5f, +0xff, 0x0f, 0x40, 0x31, 0xc0, 0x08, 0x58, 0x52, 0x8f, 0xff, 0xd5, 0x18, 0x84, 0xc1, 0x4c, 0x13, +0x40, 0x0b, 0x54, 0x31, 0x80, 0x0f, 0x46, 0x1f, 0xf0, 0xff, 0x40, 0x31, 0xd0, 0x08, 0x58, 0x10, +0x8f, 0xff, 0xd5, 0xe1, 0x84, 0x82, 0x4c, 0x12, 0x40, 0x0d, 0x54, 0x31, 0x80, 0x0f, 0x46, 0x5f, +0x0f, 0xff, 0x40, 0x31, 0xe0, 0x08, 0x58, 0x52, 0x8f, 0xff, 0x40, 0x00, 0x14, 0x02, 0xd5, 0x05, +0x40, 0x31, 0xf0, 0x08, 0x94, 0x04, 0x92, 0x04, 0x40, 0x00, 0x0c, 0x04, 0xb6, 0x02, 0x3a, 0x6f, +0xa0, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x02, 0x10, 0x00, 0x0a, 0xa1, 0xc4, +0x5c, 0xf0, 0x80, 0x66, 0xe9, 0x2b, 0x50, 0x10, 0xff, 0x9a, 0xf1, 0x81, 0x84, 0xc0, 0x47, 0xc0, +0x00, 0x80, 0x59, 0xce, 0x0b, 0xf0, 0x80, 0x07, 0x3e, 0x19, 0x37, 0xa8, 0x84, 0x46, 0x49, 0xff, +0xf9, 0x59, 0x81, 0x20, 0xc8, 0x16, 0x3e, 0x09, 0x02, 0x88, 0x80, 0x26, 0xdd, 0x3c, 0x50, 0x83, +0x80, 0x06, 0x80, 0x08, 0x3e, 0x19, 0x8e, 0x64, 0x84, 0x46, 0x8d, 0x21, 0x49, 0xff, 0xf9, 0x4a, +0xc8, 0x09, 0x44, 0x50, 0x00, 0x10, 0x8d, 0x06, 0x4c, 0x92, 0xff, 0xf5, 0x84, 0x01, 0xd5, 0x07, +0x9d, 0xf9, 0xf0, 0x01, 0x9d, 0xb1, 0xe2, 0x06, 0xe8, 0xdf, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x97, 0x20, 0x96, 0x48, 0x81, 0x25, +0x97, 0xc0, 0x54, 0x81, 0x00, 0xff, 0xf4, 0x81, 0xc9, 0x52, 0xe7, 0x04, 0xe8, 0x50, 0x44, 0x20, +0x00, 0x43, 0x42, 0x64, 0x08, 0x24, 0x3e, 0x09, 0x8b, 0x8c, 0x99, 0xb0, 0x80, 0x06, 0x49, 0xfe, +0xaa, 0x93, 0x84, 0x24, 0x4c, 0x70, 0xc0, 0x04, 0x84, 0x03, 0xd5, 0x0a, 0x84, 0x06, 0x4c, 0x70, +0x40, 0x04, 0x84, 0x04, 0xd5, 0x05, 0x84, 0x2b, 0x4c, 0x70, 0xc0, 0x05, 0x84, 0x02, 0x10, 0x03, +0x00, 0x40, 0x00, 0x23, 0x00, 0x40, 0x3e, 0x09, 0x02, 0xac, 0x3e, 0x19, 0x03, 0xa8, 0x84, 0x60, +0x80, 0x88, 0x49, 0xff, 0xde, 0x8f, 0x44, 0x30, 0x00, 0x10, 0x10, 0x33, 0x00, 0x41, 0x80, 0x29, +0x44, 0x75, 0xa3, 0x98, 0x80, 0x06, 0x80, 0x43, 0xdd, 0x27, 0x00, 0x03, 0x00, 0x40, 0x84, 0x23, +0x4c, 0x00, 0xc0, 0x18, 0xf1, 0x01, 0x51, 0xc4, 0x80, 0x18, 0x50, 0x03, 0x00, 0x10, 0x8d, 0x30, +0x50, 0xa3, 0x00, 0x18, 0xc1, 0x07, 0x80, 0x29, 0x84, 0x48, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x3c, +0xd5, 0x06, 0x80, 0x3c, 0x84, 0x48, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x29, 0x84, 0x48, 0xdd, 0x27, +0x80, 0x28, 0x80, 0x46, 0x84, 0x00, 0x49, 0xff, 0xfe, 0xe7, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x44, 0x60, 0x01, 0x0c, 0x96, 0x00, 0x42, 0x60, +0x18, 0x24, 0x3e, 0x09, 0x8b, 0x8c, 0x99, 0xb0, 0x44, 0x20, 0x00, 0x43, 0x81, 0x01, 0x80, 0x06, +0x84, 0x20, 0x49, 0xfe, 0xaa, 0x39, 0x2e, 0x21, 0x8c, 0x99, 0x84, 0xa4, 0xda, 0x03, 0x84, 0x03, +0xd5, 0x04, 0x84, 0xa6, 0xda, 0x05, 0x84, 0x04, 0x10, 0x03, 0x00, 0x40, 0xd5, 0x08, 0x3e, 0x09, +0x02, 0xd8, 0x3e, 0x19, 0x03, 0xbc, 0x49, 0xff, 0xde, 0x3d, 0xd5, 0x1d, 0x44, 0x30, 0x00, 0x10, +0x10, 0x33, 0x00, 0x41, 0x50, 0x14, 0x00, 0x20, 0x80, 0x06, 0x80, 0x43, 0x49, 0xfe, 0xaa, 0x06, +0x00, 0x03, 0x00, 0x40, 0x84, 0xa3, 0xd8, 0x0f, 0x50, 0x14, 0x00, 0x38, 0x84, 0x48, 0x50, 0x03, +0x00, 0x10, 0x49, 0xfe, 0xa9, 0xfb, 0x50, 0x03, 0x00, 0x18, 0x50, 0x14, 0x00, 0x30, 0x84, 0x48, +0x49, 0xfe, 0xa9, 0xf4, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xd4, 0x50, 0x9f, 0x80, 0x08, 0x80, 0xe0, 0x55, 0xc0, 0x80, 0xff, 0x54, 0x81, 0x00, 0xff, +0x54, 0xa2, 0x00, 0xff, 0x80, 0x09, 0x84, 0x20, 0x44, 0x20, 0x00, 0x20, 0x97, 0x98, 0x49, 0xfe, +0xa9, 0xf3, 0x4e, 0xa2, 0x00, 0x45, 0x84, 0x03, 0x4c, 0x60, 0x00, 0x05, 0x84, 0x25, 0x4c, 0x60, +0xc0, 0x4c, 0x85, 0x40, 0x81, 0x0a, 0x81, 0x2a, 0x50, 0x6f, 0x80, 0x08, 0xd5, 0x31, 0xa6, 0x38, +0x44, 0x30, 0x00, 0xdd, 0x4c, 0x01, 0xc0, 0x27, 0x9c, 0x3a, 0x3e, 0x19, 0x37, 0x84, 0x84, 0x43, +0x49, 0xff, 0xf8, 0x68, 0x80, 0x60, 0xc8, 0x1e, 0xa6, 0x3d, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x1b, +0x00, 0x93, 0x80, 0x01, 0x00, 0x83, 0x80, 0x06, 0x8f, 0x26, 0x54, 0x94, 0x80, 0xff, 0x50, 0x13, +0x80, 0x08, 0x80, 0x06, 0x80, 0x49, 0x54, 0x84, 0x00, 0x03, 0xe7, 0x30, 0xe8, 0x09, 0x3e, 0x09, +0x02, 0xfc, 0x80, 0x29, 0xf3, 0x81, 0x49, 0xff, 0xdd, 0xd5, 0xf0, 0x01, 0xd5, 0x36, 0x49, 0xfe, +0xa9, 0xa5, 0xa6, 0x39, 0x9c, 0x02, 0x89, 0x40, 0x99, 0xf8, 0x54, 0xa5, 0x00, 0xff, 0xa6, 0x39, +0x9c, 0x02, 0x88, 0x0a, 0x40, 0xfe, 0x00, 0x07, 0xe8, 0xcb, 0xd5, 0x0a, 0x84, 0x05, 0x4c, 0x60, +0x40, 0x0c, 0x80, 0x09, 0x80, 0x27, 0x80, 0x5c, 0x49, 0xfe, 0xa9, 0x90, 0x81, 0x3c, 0xe7, 0x04, +0xe9, 0x05, 0x84, 0x00, 0xd5, 0x1a, 0x85, 0x00, 0x81, 0x28, 0x3e, 0x69, 0x8a, 0x58, 0x80, 0x49, +0x50, 0x1f, 0x80, 0x08, 0x50, 0x03, 0x01, 0x14, 0x49, 0xfe, 0xa9, 0x80, 0x84, 0x20, 0x00, 0x03, +0x02, 0x42, 0x10, 0x83, 0x02, 0x40, 0x80, 0x48, 0x50, 0x53, 0x01, 0x14, 0x80, 0x61, 0x80, 0x81, +0x49, 0xff, 0xfe, 0xe2, 0x92, 0x00, 0x84, 0x01, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x94, 0x85, 0x40, 0x80, 0xc2, 0x55, 0xc0, 0x00, 0xff, 0x44, 0x00, +0x02, 0x00, 0x81, 0x21, 0x14, 0xaf, 0x80, 0x19, 0x49, 0xff, 0xf8, 0x12, 0xa6, 0xb2, 0xa6, 0x73, +0x40, 0x21, 0x20, 0x08, 0x40, 0x21, 0x04, 0x04, 0x9c, 0x94, 0x50, 0x1f, 0x80, 0x64, 0x80, 0x66, +0x84, 0x9f, 0x50, 0x8f, 0x80, 0x54, 0x80, 0xe0, 0x49, 0xff, 0xf8, 0x1a, 0x80, 0x2a, 0x80, 0x08, +0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xa9, 0x60, 0x84, 0x02, 0x4d, 0xc0, 0x40, 0x14, 0x50, 0xaf, +0x80, 0x04, 0xf3, 0x19, 0x80, 0x09, 0x80, 0x47, 0x80, 0x8a, 0x44, 0x50, 0x00, 0x14, 0x9e, 0x6c, +0x49, 0x00, 0x06, 0xd0, 0x80, 0x08, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xa9, 0x36, +0xd5, 0x0a, 0x44, 0x10, 0x00, 0x10, 0xf3, 0x19, 0x80, 0x09, 0x80, 0x88, 0x80, 0x47, 0x80, 0xa1, +0x49, 0x00, 0x06, 0x40, 0x50, 0x1f, 0x80, 0x54, 0x44, 0x20, 0x00, 0x10, 0x50, 0x03, 0x00, 0x51, +0x49, 0xfe, 0xa9, 0x24, 0x80, 0x07, 0x49, 0xff, 0xf7, 0xdb, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0xf6, 0x0c, 0x2e, 0x81, 0x8c, 0x9b, +0x84, 0x01, 0xae, 0x30, 0x84, 0x03, 0xae, 0x31, 0x84, 0x00, 0xae, 0x32, 0x44, 0x00, 0x00, 0x5f, +0xae, 0x33, 0x83, 0x83, 0xf4, 0x81, 0x97, 0xc8, 0x96, 0x90, 0x4e, 0x82, 0x00, 0x04, 0x84, 0x02, +0xd5, 0x02, 0x84, 0x1e, 0xae, 0x34, 0x2e, 0x11, 0x8c, 0x9c, 0xc1, 0x03, 0x85, 0x23, 0xd5, 0x0b, +0x2e, 0x31, 0x8c, 0x99, 0x84, 0x22, 0x56, 0x31, 0x80, 0x06, 0x84, 0x01, 0x40, 0x90, 0x8c, 0x1a, +0x40, 0x90, 0x0c, 0x1b, 0xa6, 0x36, 0x92, 0x03, 0x94, 0x03, 0x40, 0x00, 0x24, 0x04, 0xae, 0x36, +0xe6, 0xe5, 0xe9, 0x04, 0x42, 0x00, 0x0c, 0x09, 0xd5, 0x03, 0x58, 0x00, 0x00, 0x08, 0xae, 0x36, +0x4e, 0x83, 0x00, 0x12, 0xe6, 0xe5, 0xe9, 0x0f, 0xa6, 0x76, 0x54, 0x01, 0x00, 0x03, 0x44, 0x3f, +0xff, 0xcf, 0x94, 0x04, 0x40, 0x20, 0x8c, 0x02, 0x40, 0x21, 0x00, 0x04, 0x84, 0xa3, 0xae, 0xb6, +0xdf, 0x0b, 0xd5, 0x0c, 0x84, 0xa3, 0xdf, 0x06, 0xa6, 0x36, 0x58, 0x00, 0x00, 0x40, 0xae, 0x36, +0xd5, 0x05, 0x84, 0xa1, 0xd7, 0x03, 0x84, 0xa5, 0xdf, 0x09, 0xa6, 0x36, 0x44, 0x1f, 0xff, 0x80, +0x40, 0x00, 0x04, 0x04, 0x84, 0xa1, 0xae, 0x36, 0xd7, 0x05, 0xa6, 0x35, 0x58, 0x00, 0x00, 0x01, +0xae, 0x35, 0x4e, 0x82, 0x00, 0x05, 0xe6, 0xe3, 0xe8, 0x04, 0xd5, 0x0b, 0xe6, 0xe5, 0xe9, 0x18, +0xa6, 0x35, 0x58, 0x00, 0x00, 0x02, 0xae, 0x35, 0x4e, 0x82, 0x00, 0x13, 0x84, 0xa3, 0xd7, 0x03, +0x84, 0xa5, 0xdf, 0x05, 0xa6, 0x35, 0x58, 0x00, 0x00, 0x10, 0xae, 0x35, 0x4e, 0x82, 0x00, 0x09, +0x84, 0xa1, 0xd7, 0x03, 0x84, 0xa3, 0xdf, 0x18, 0x3e, 0x09, 0x8a, 0x58, 0xd5, 0x08, 0x3e, 0x09, +0x8a, 0x58, 0xe6, 0xe5, 0xe9, 0x04, 0x00, 0x30, 0x02, 0x42, 0xd5, 0x03, 0x00, 0x30, 0x02, 0x41, +0x56, 0x31, 0x80, 0x04, 0x44, 0x10, 0x00, 0x10, 0x94, 0x89, 0x40, 0x01, 0x0c, 0x1a, 0x40, 0x00, +0x8c, 0x1b, 0x10, 0x03, 0x00, 0x08, 0x50, 0x03, 0x00, 0x09, 0x3e, 0x19, 0x8b, 0x24, 0x84, 0x48, +0x49, 0xfe, 0xa8, 0x84, 0xe6, 0xe4, 0xe9, 0x05, 0x4e, 0x83, 0x00, 0x22, 0x84, 0xa5, 0xdf, 0x1f, +0x50, 0x03, 0x00, 0x11, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x20, 0x49, 0xfe, 0xa8, 0x77, 0x4e, 0x83, +0x00, 0x12, 0x84, 0xa5, 0xdf, 0x0f, 0x50, 0x1e, 0x00, 0x10, 0x50, 0x03, 0x00, 0x31, 0x44, 0x20, +0x00, 0x10, 0x49, 0xfe, 0xa8, 0x6b, 0x00, 0x03, 0x00, 0x40, 0x9c, 0x02, 0x10, 0x03, 0x00, 0x40, +0xd5, 0x08, 0x84, 0xa3, 0xdf, 0x04, 0x4e, 0x83, 0x00, 0x05, 0xd5, 0x09, 0x84, 0xa5, 0xdf, 0x07, +0xf1, 0x01, 0x50, 0x03, 0x00, 0x41, 0x84, 0x46, 0x49, 0xfe, 0xa8, 0x58, 0x50, 0x03, 0x00, 0x51, +0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xa8, 0x67, 0x84, 0xa1, 0xd7, 0x07, 0x80, 0x09, +0x80, 0x46, 0x3e, 0x19, 0x8b, 0x2c, 0x49, 0xff, 0xfe, 0xdd, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0x84, 0x44, 0x85, 0xa3, 0xc4, 0x50, 0x60, +0x00, 0x5b, 0x84, 0x20, 0x97, 0xd0, 0x50, 0x0f, 0x81, 0x60, 0x44, 0x20, 0x00, 0x10, 0xdd, 0x28, +0x84, 0x20, 0x44, 0x20, 0x00, 0x50, 0x50, 0x0f, 0x81, 0x00, 0xdd, 0x28, 0x50, 0x9f, 0x81, 0x74, +0x84, 0x20, 0x44, 0x20, 0x00, 0xff, 0x80, 0x1f, 0xdd, 0x28, 0x84, 0x20, 0x84, 0x42, 0x80, 0x09, +0xdd, 0x28, 0x80, 0x09, 0x50, 0x13, 0x7f, 0xaa, 0x84, 0x42, 0x49, 0xfe, 0xa8, 0x1f, 0x2e, 0x81, +0x8c, 0x9b, 0x84, 0x01, 0x4c, 0x70, 0x00, 0x08, 0x84, 0x23, 0x4c, 0x70, 0x80, 0x05, 0x84, 0x45, +0x4c, 0x71, 0x40, 0x1e, 0x51, 0xcf, 0x81, 0x50, 0x84, 0x20, 0x84, 0x48, 0x80, 0x1c, 0x50, 0xa3, +0x7f, 0xae, 0x49, 0xfe, 0xa8, 0x21, 0x3e, 0x19, 0x8b, 0x24, 0x80, 0x0a, 0x84, 0x48, 0x49, 0xff, +0xf6, 0x47, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x09, 0x80, 0x0a, 0x80, 0x3c, 0x84, 0x48, 0x49, 0xff, +0xf6, 0x3f, 0x4e, 0x03, 0x00, 0xac, 0x84, 0x41, 0x4c, 0x71, 0x00, 0x57, 0x01, 0xc3, 0x7f, 0xa7, +0x00, 0x03, 0x7f, 0xa8, 0x50, 0xa3, 0x7f, 0xf6, 0x41, 0xce, 0x20, 0x08, 0x41, 0xce, 0x00, 0x04, +0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x50, 0x0f, 0x81, 0x50, 0x49, 0xfe, 0xa7, 0xe7, 0x84, 0x20, +0x80, 0x0a, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xa7, 0xf7, 0x00, 0x0f, 0x81, 0x75, 0x84, 0x21, +0x54, 0x00, 0x00, 0x07, 0x51, 0xce, 0x00, 0x04, 0x4c, 0x00, 0xc0, 0x13, 0x3e, 0x99, 0x8a, 0x58, +0x85, 0x44, 0x8c, 0x2f, 0x10, 0xa4, 0x82, 0x41, 0x50, 0x04, 0x80, 0xd4, 0x80, 0x7c, 0x50, 0x23, +0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x60, 0x80, 0xa1, 0x49, 0x00, 0x04, 0xdc, 0xd5, 0x1c, 0x84, 0x42, +0x4c, 0x01, 0x40, 0x1a, 0x3e, 0xa9, 0x8a, 0x58, 0x80, 0x7c, 0x87, 0x86, 0x11, 0xc5, 0x02, 0x41, +0x50, 0x05, 0x00, 0xd4, 0x8c, 0x2f, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x00, 0x9d, 0x4c, +0x49, 0x00, 0x05, 0x48, 0x50, 0x1f, 0x81, 0x00, 0x50, 0x0f, 0x81, 0x60, 0x44, 0x20, 0x00, 0x10, +0x49, 0xfe, 0xa7, 0xac, 0x50, 0x0f, 0x81, 0x50, 0x50, 0x1f, 0x81, 0x60, 0x44, 0x20, 0x00, 0x10, +0x49, 0xff, 0xf6, 0x48, 0xc8, 0x53, 0xa6, 0xf6, 0xa6, 0x37, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x31, +0x80, 0x04, 0x4e, 0x36, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x4a, 0x84, 0x03, 0x4c, 0x70, 0x40, 0x05, +0x4e, 0x83, 0x00, 0x06, 0xd5, 0x37, 0x84, 0x25, 0x4c, 0x70, 0xc0, 0x35, 0x00, 0x1f, 0x81, 0x75, +0x84, 0x42, 0x54, 0x10, 0x80, 0x07, 0x80, 0x9f, 0x50, 0x03, 0x00, 0x08, 0x4c, 0x11, 0x40, 0x19, +0xa6, 0x76, 0xa6, 0xb7, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x88, 0x04, 0x44, 0x30, 0x00, 0x10, +0x3e, 0x29, 0x8b, 0x3c, 0x50, 0x5f, 0x81, 0x70, 0x85, 0x20, 0x14, 0x9f, 0x80, 0x5c, 0x49, 0x00, +0x03, 0x75, 0xf0, 0x5c, 0x00, 0x1f, 0x81, 0x71, 0xae, 0x37, 0xae, 0x76, 0xd5, 0x08, 0x80, 0x40, +0x3e, 0x09, 0x8b, 0x3c, 0x50, 0x13, 0x7f, 0xd6, 0x49, 0x00, 0x0b, 0x7e, 0x4e, 0x83, 0x00, 0x0b, +0x84, 0x45, 0x4c, 0x71, 0x40, 0x08, 0x00, 0x2f, 0x81, 0x75, 0x92, 0x44, 0x54, 0x21, 0x00, 0x03, +0xd5, 0x02, 0x84, 0x40, 0xa6, 0x77, 0x80, 0x67, 0x80, 0x88, 0x80, 0x1f, 0x49, 0xff, 0xfd, 0x68, +0x92, 0x00, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, 0xed, 0x7c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x3e, 0x79, 0x8a, 0x58, 0x80, 0xc1, +0x00, 0x33, 0x82, 0x41, 0x80, 0x22, 0x81, 0x20, 0x84, 0x45, 0x80, 0x06, 0xf3, 0x85, 0x49, 0xff, +0xfe, 0xfb, 0x81, 0x00, 0xc8, 0x12, 0x04, 0x03, 0x80, 0x9a, 0x54, 0x00, 0x04, 0x00, 0xc0, 0x6e, +0x3e, 0x09, 0x03, 0x24, 0x49, 0xff, 0xdb, 0x5e, 0x46, 0x02, 0x00, 0x00, 0x80, 0x28, 0x80, 0x49, +0x49, 0xff, 0xe4, 0x62, 0x48, 0x00, 0x00, 0x63, 0x00, 0x13, 0x00, 0x0f, 0x00, 0x23, 0x00, 0x10, +0x3e, 0x09, 0x03, 0x4c, 0x01, 0xc3, 0x82, 0x40, 0x44, 0x95, 0xa3, 0x98, 0x49, 0xff, 0xdb, 0x4a, +0x50, 0x13, 0x00, 0x09, 0x84, 0x48, 0x50, 0x03, 0x80, 0xcc, 0xdd, 0x29, 0x49, 0x00, 0x12, 0xec, +0x3e, 0x09, 0x83, 0x70, 0x49, 0xff, 0xdc, 0xf4, 0x81, 0x40, 0xc8, 0x08, 0x3e, 0x08, 0xf7, 0x44, +0x3e, 0x19, 0x03, 0xd4, 0x49, 0xff, 0xdb, 0x36, 0xd5, 0x41, 0x04, 0x80, 0x00, 0x02, 0x4e, 0x82, +0x00, 0x3e, 0x84, 0xc0, 0x80, 0x26, 0x44, 0x20, 0x04, 0x00, 0x80, 0x08, 0x49, 0xfe, 0xa7, 0x14, +0xf0, 0x05, 0x80, 0x66, 0x80, 0x86, 0x80, 0xa6, 0x80, 0x5c, 0x84, 0x26, 0x51, 0xc4, 0x00, 0x0e, +0xb6, 0xdf, 0xf6, 0x81, 0x15, 0xcf, 0x80, 0x02, 0x49, 0xff, 0xfd, 0xd6, 0x50, 0x13, 0x82, 0x45, +0x84, 0x46, 0x50, 0x0f, 0x80, 0x18, 0xdd, 0x29, 0x3e, 0x19, 0x8e, 0x64, 0x84, 0x46, 0x50, 0x0f, +0x80, 0x1e, 0xdd, 0x29, 0x3e, 0x19, 0x37, 0x9c, 0x84, 0x42, 0x50, 0x0f, 0x80, 0x24, 0xdd, 0x29, +0x00, 0x7e, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x03, 0x40, 0x73, 0xa0, 0x08, 0x40, 0x73, 0x80, 0x04, +0x50, 0x1f, 0x80, 0x18, 0x84, 0x4e, 0x80, 0x08, 0x49, 0xfe, 0xa6, 0xc6, 0x50, 0x13, 0x80, 0x12, +0x80, 0x0a, 0x96, 0x49, 0x80, 0x46, 0x49, 0xff, 0xf9, 0x0f, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x50, 0x6f, 0x80, 0x04, 0x80, 0xe1, +0x81, 0x00, 0x84, 0x20, 0x81, 0x22, 0x80, 0x06, 0x84, 0x42, 0x49, 0xfe, 0xa6, 0xcd, 0x80, 0x06, +0x9c, 0x7d, 0x84, 0x42, 0x49, 0xfe, 0xa6, 0xb2, 0xa6, 0xf1, 0x54, 0x01, 0x80, 0x80, 0xc0, 0x34, +0xa7, 0x30, 0x54, 0x02, 0x00, 0x0e, 0xc8, 0x19, 0x54, 0x01, 0x80, 0x08, 0xc0, 0x16, 0x97, 0xa4, +0x46, 0x30, 0x00, 0x80, 0x58, 0x31, 0x8b, 0xf0, 0xce, 0x1b, 0x3e, 0x09, 0x03, 0x60, 0xdd, 0x23, +0x3c, 0x0c, 0x63, 0x30, 0x54, 0x00, 0x02, 0x00, 0xc0, 0x1f, 0x46, 0x04, 0x00, 0x00, 0x80, 0x26, +0x80, 0x48, 0x49, 0xff, 0xe3, 0xc9, 0xd5, 0x18, 0x54, 0x42, 0x00, 0x0f, 0x84, 0xa3, 0xdc, 0x14, +0x54, 0x01, 0x80, 0x08, 0x46, 0x30, 0x00, 0x80, 0x58, 0x31, 0x8b, 0xf0, 0xc0, 0x05, 0x3e, 0x09, +0x03, 0x78, 0xdd, 0x23, 0xd5, 0x09, 0x3e, 0x09, 0x03, 0x90, 0xdd, 0x23, 0x80, 0x08, 0x80, 0x27, +0x80, 0x49, 0x49, 0xff, 0xff, 0x31, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x50, 0x31, 0x00, 0x10, 0x92, 0x22, 0x80, 0x83, 0x84, 0xa0, +0xd5, 0x11, 0xa7, 0x80, 0x9d, 0x69, 0xaf, 0xa0, 0x00, 0xa0, 0x00, 0x01, 0x10, 0xa2, 0x00, 0x3c, +0x01, 0xc0, 0x00, 0x02, 0x11, 0xc2, 0x00, 0x78, 0xa7, 0x83, 0x9c, 0x04, 0x10, 0x62, 0x00, 0xb4, +0x9d, 0x21, 0xe2, 0xa1, 0xe9, 0xef, 0x9c, 0x0f, 0x94, 0x02, 0x50, 0x40, 0x80, 0x10, 0xf0, 0x83, +0x98, 0x94, 0x81, 0x21, 0x3e, 0x09, 0x04, 0x18, 0x3f, 0xe9, 0x03, 0xec, 0xd5, 0x53, 0x40, 0xa4, +0x85, 0x17, 0x00, 0x71, 0x7f, 0xff, 0x00, 0x61, 0x00, 0x3b, 0x00, 0x51, 0x00, 0x77, 0x00, 0x41, +0x00, 0xb3, 0x4e, 0x83, 0x00, 0x21, 0x38, 0x50, 0x14, 0x00, 0x38, 0x8f, 0x2a, 0x02, 0x10, 0x5f, +0x80, 0x00, 0x38, 0x50, 0x10, 0x00, 0x01, 0xcf, 0x80, 0x00, 0x38, 0x40, 0x1c, 0x00, 0x40, 0xa4, +0x20, 0x09, 0x38, 0x70, 0x18, 0x00, 0x40, 0x64, 0x40, 0x09, 0x40, 0x44, 0x10, 0x03, 0x40, 0x63, +0x70, 0x03, 0x40, 0x55, 0x14, 0x03, 0x93, 0x18, 0x40, 0x74, 0x1c, 0x03, 0x97, 0xb0, 0x97, 0x68, +0x97, 0x20, 0xd5, 0x0e, 0xe6, 0x27, 0xe9, 0x0c, 0x85, 0x44, 0x4c, 0x85, 0x40, 0x0a, 0x38, 0x60, +0x18, 0x00, 0x38, 0x50, 0x14, 0x00, 0x38, 0x40, 0x10, 0x00, 0x38, 0x70, 0x1c, 0x00, 0x00, 0x81, +0x80, 0x00, 0x8d, 0x21, 0x40, 0x73, 0xa0, 0x03, 0xaf, 0xd0, 0x00, 0x71, 0x80, 0x3c, 0x40, 0x63, +0x1c, 0x03, 0x10, 0x61, 0x00, 0x3c, 0x00, 0x61, 0x80, 0x78, 0x40, 0x52, 0x98, 0x03, 0x10, 0x51, +0x00, 0x78, 0x00, 0x51, 0x80, 0xb4, 0x9c, 0xd9, 0x40, 0x42, 0x14, 0x03, 0x10, 0x41, 0x00, 0xb4, +0x9c, 0x91, 0x05, 0xcf, 0x80, 0x03, 0xe3, 0x3c, 0xe9, 0xab, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xbc, 0xf5, 0x8c, 0x80, 0xc3, 0xb4, 0xe5, +0xf4, 0x8e, 0xe6, 0xf0, 0x4e, 0xf3, 0x01, 0xe6, 0x44, 0x30, 0x00, 0x10, 0x4c, 0x61, 0x80, 0x09, +0x44, 0x40, 0x00, 0x18, 0x4c, 0x62, 0x00, 0x05, 0x95, 0x59, 0x4c, 0x62, 0xc1, 0xdb, 0x80, 0xe3, +0x4c, 0x13, 0xc1, 0xd8, 0x84, 0x20, 0x50, 0x9f, 0x80, 0x40, 0xd5, 0x0c, 0x08, 0x72, 0x00, 0x04, +0x9c, 0xd9, 0x18, 0x72, 0x80, 0x01, 0x84, 0xe4, 0x4c, 0x33, 0xff, 0xfa, 0x9c, 0x49, 0x4c, 0x11, +0x80, 0x07, 0x95, 0x4a, 0x88, 0xa9, 0x99, 0x01, 0x84, 0x60, 0xd5, 0xf1, 0x80, 0x02, 0x80, 0x26, +0x50, 0x2f, 0x80, 0x40, 0x50, 0x9f, 0x80, 0x41, 0x49, 0xff, 0xff, 0x4c, 0x92, 0xc2, 0x14, 0x9f, +0x80, 0x04, 0x50, 0x7f, 0x80, 0x40, 0x50, 0x9f, 0x80, 0x42, 0x50, 0xaf, 0x80, 0x43, 0x50, 0x03, +0x00, 0x0a, 0x50, 0x5f, 0x80, 0x50, 0x94, 0x02, 0x14, 0x9f, 0x80, 0x06, 0x14, 0xaf, 0x80, 0x05, +0xf7, 0x8d, 0xf5, 0x81, 0x04, 0x8f, 0x80, 0x04, 0x98, 0x38, 0xa6, 0x80, 0xa6, 0x78, 0x40, 0x11, +0x04, 0x03, 0x18, 0x13, 0x80, 0x04, 0xa6, 0x81, 0x00, 0x14, 0x00, 0x00, 0x40, 0x11, 0x04, 0x03, +0x18, 0x14, 0x00, 0x04, 0xa6, 0x82, 0x00, 0x14, 0x80, 0x00, 0x40, 0x10, 0x88, 0x03, 0x18, 0x14, +0x80, 0x04, 0xa6, 0x43, 0x00, 0x25, 0x00, 0x00, 0x50, 0x00, 0x00, 0x3c, 0x40, 0x10, 0x88, 0x03, +0x18, 0x15, 0x00, 0x04, 0xf1, 0x01, 0x4c, 0x70, 0xff, 0xe2, 0x9d, 0xb5, 0x50, 0x2f, 0x80, 0x40, +0x95, 0xb2, 0x9c, 0x94, 0xf6, 0x88, 0xf2, 0x8f, 0x48, 0x00, 0x00, 0xf9, 0x00, 0x2f, 0x80, 0x47, +0x00, 0x0f, 0x80, 0x48, 0x00, 0x1f, 0x80, 0x49, 0x00, 0x3f, 0x80, 0x4c, 0x00, 0x4f, 0x80, 0x46, +0x00, 0x5f, 0x80, 0x4a, 0x00, 0x6f, 0x80, 0x45, 0x00, 0x7f, 0x80, 0x4b, 0x00, 0x9f, 0x80, 0x44, +0x10, 0x0f, 0x80, 0x4a, 0x10, 0x2f, 0x80, 0x44, 0x00, 0x0f, 0x80, 0x4d, 0x00, 0x2f, 0x80, 0x4f, +0x10, 0x1f, 0x80, 0x4b, 0x00, 0x1f, 0x80, 0x4e, 0x10, 0x4f, 0x80, 0x47, 0x10, 0x2f, 0x80, 0x4e, +0x10, 0x3f, 0x80, 0x4f, 0x10, 0x5f, 0x80, 0x48, 0x10, 0x6f, 0x80, 0x46, 0x10, 0x7f, 0x80, 0x49, +0x10, 0x9f, 0x80, 0x45, 0x10, 0x0f, 0x80, 0x4c, 0xf2, 0x05, 0xf3, 0x06, 0xf4, 0x04, 0x10, 0x1f, +0x80, 0x4d, 0x50, 0x1f, 0x80, 0x40, 0xa6, 0x08, 0x3e, 0x59, 0x05, 0x18, 0x38, 0x02, 0x80, 0x00, +0xf6, 0x01, 0x18, 0x00, 0x80, 0x04, 0xa6, 0x20, 0x38, 0x02, 0x80, 0x00, 0x18, 0x02, 0x00, 0x04, +0xa6, 0x18, 0x38, 0x02, 0x80, 0x00, 0x18, 0x01, 0x80, 0x04, 0xa6, 0x10, 0x38, 0x02, 0x80, 0x00, +0x18, 0x01, 0x00, 0x04, 0x4c, 0x13, 0x7f, 0xe9, 0xf7, 0x08, 0x50, 0x5f, 0x80, 0x40, 0x50, 0x03, +0x80, 0x10, 0xf3, 0x05, 0xf4, 0x06, 0xf6, 0x04, 0x98, 0xa8, 0xa6, 0x50, 0xa6, 0x28, 0x40, 0x00, +0x80, 0x03, 0x18, 0x02, 0x80, 0x04, 0xa6, 0x51, 0xa6, 0x30, 0x40, 0x00, 0x80, 0x03, 0x18, 0x03, +0x00, 0x04, 0xa6, 0x52, 0xa6, 0x20, 0x40, 0x00, 0x80, 0x03, 0x18, 0x02, 0x00, 0x04, 0xa6, 0x13, +0xa6, 0x58, 0x50, 0x21, 0x00, 0x3c, 0x40, 0x00, 0x04, 0x03, 0x18, 0x01, 0x80, 0x04, 0xf0, 0x01, +0xd8, 0xe5, 0x50, 0x1f, 0x80, 0x44, 0x50, 0x2f, 0x80, 0x48, 0x50, 0x3f, 0x80, 0x4c, 0x50, 0x4f, +0x80, 0x40, 0xf1, 0x8b, 0xf2, 0x8a, 0xf3, 0x89, 0xf4, 0x87, 0xf5, 0x07, 0xf6, 0x0b, 0xa6, 0xe8, +0xa6, 0x30, 0x04, 0x9f, 0x80, 0x09, 0x3e, 0x69, 0x09, 0x18, 0x3e, 0x19, 0x07, 0x18, 0x38, 0x20, +0x80, 0x00, 0x38, 0x13, 0x0c, 0x00, 0x00, 0x54, 0x80, 0x00, 0xf7, 0x0a, 0x40, 0x11, 0x04, 0x03, +0x3e, 0x29, 0x06, 0x18, 0xa7, 0x38, 0x38, 0x21, 0x14, 0x00, 0x3e, 0x79, 0x08, 0x18, 0x38, 0xa3, +0x90, 0x00, 0x10, 0x2f, 0x80, 0x08, 0x38, 0x23, 0x00, 0x00, 0x3e, 0x69, 0x06, 0x18, 0x38, 0x83, +0x00, 0x00, 0x39, 0xe3, 0x80, 0x00, 0x3e, 0x99, 0x07, 0x18, 0x80, 0x07, 0x38, 0x74, 0x8c, 0x00, +0x38, 0x93, 0x0c, 0x00, 0x38, 0x60, 0x0c, 0x00, 0x40, 0x30, 0xa8, 0x03, 0x3e, 0x19, 0x06, 0x18, +0x38, 0x00, 0x90, 0x00, 0x3e, 0x19, 0x07, 0x18, 0x39, 0xc0, 0x90, 0x00, 0x3e, 0x19, 0x09, 0x18, +0x38, 0xa0, 0x90, 0x00, 0x40, 0x21, 0x24, 0x03, 0x00, 0x4f, 0x80, 0x08, 0x40, 0x14, 0x18, 0x03, +0x3e, 0x99, 0x08, 0x18, 0x3e, 0x69, 0x09, 0x18, 0x38, 0x83, 0x14, 0x00, 0x38, 0x64, 0x94, 0x00, +0x3e, 0x99, 0x07, 0x18, 0x40, 0x31, 0x90, 0x03, 0x38, 0x44, 0x94, 0x00, 0xf5, 0x07, 0x40, 0x21, +0x70, 0x03, 0x18, 0x32, 0x80, 0x01, 0xf3, 0x0b, 0x40, 0x21, 0x18, 0x03, 0x40, 0x10, 0xa8, 0x03, +0x40, 0x10, 0x90, 0x03, 0x18, 0x21, 0x80, 0x01, 0xf4, 0x0a, 0x40, 0x7f, 0x1c, 0x03, 0xf5, 0x87, +0x40, 0x03, 0x80, 0x03, 0xf3, 0x8b, 0x18, 0x12, 0x00, 0x01, 0xf5, 0x09, 0x40, 0x00, 0x20, 0x03, +0x18, 0x02, 0x80, 0x01, 0xf6, 0x07, 0xf7, 0x0f, 0xf4, 0x8a, 0xf5, 0x89, 0x4c, 0x63, 0xff, 0x8f, +0x04, 0x9f, 0x80, 0x08, 0x8f, 0x24, 0x14, 0x9f, 0x80, 0x08, 0xf0, 0x08, 0x4e, 0x03, 0xff, 0x08, +0x00, 0x1f, 0x80, 0x47, 0x00, 0x3f, 0x80, 0x48, 0x00, 0x2f, 0x80, 0x49, 0x00, 0x4f, 0x80, 0x46, +0x00, 0x5f, 0x80, 0x4a, 0x00, 0x6f, 0x80, 0x45, 0x00, 0x7f, 0x80, 0x4b, 0x00, 0x9f, 0x80, 0x44, +0x10, 0x3f, 0x80, 0x4a, 0x10, 0x2f, 0x80, 0x4b, 0x00, 0x3f, 0x80, 0x4f, 0x00, 0x2f, 0x80, 0x4e, +0x10, 0x1f, 0x80, 0x44, 0x00, 0x1f, 0x80, 0x4d, 0x00, 0x0f, 0x80, 0x4c, 0x10, 0x4f, 0x80, 0x47, +0x10, 0x1f, 0x80, 0x4c, 0x10, 0x2f, 0x80, 0x4d, 0x10, 0x3f, 0x80, 0x4e, 0x10, 0x5f, 0x80, 0x48, +0x10, 0x6f, 0x80, 0x46, 0x10, 0x7f, 0x80, 0x49, 0x10, 0x9f, 0x80, 0x45, 0xf1, 0x0d, 0xf2, 0x04, +0xf3, 0x05, 0xf4, 0x06, 0x10, 0x0f, 0x80, 0x4f, 0x3e, 0x09, 0x05, 0x18, 0xa7, 0x48, 0x38, 0x50, +0x14, 0x00, 0x18, 0x50, 0x80, 0x04, 0xa7, 0x50, 0x38, 0x50, 0x14, 0x00, 0x18, 0x51, 0x00, 0x04, +0xa7, 0x60, 0x38, 0x50, 0x14, 0x00, 0x18, 0x52, 0x00, 0x04, 0xa7, 0x58, 0x38, 0x50, 0x14, 0x00, +0x18, 0x51, 0x80, 0x04, 0xf5, 0x01, 0xd9, 0xeb, 0x84, 0x00, 0x50, 0x7f, 0x80, 0x40, 0x44, 0x60, +0x00, 0x3c, 0xd5, 0x13, 0x08, 0x41, 0x80, 0x01, 0xa7, 0x50, 0x9c, 0x49, 0x40, 0x42, 0x14, 0x03, +0x85, 0x24, 0x18, 0x41, 0x00, 0x01, 0x4c, 0x14, 0xff, 0xf7, 0x9c, 0x01, 0x4c, 0x00, 0xc0, 0x06, +0x84, 0x00, 0x50, 0x6f, 0x80, 0x40, 0xd5, 0x13, 0x42, 0x30, 0x18, 0x24, 0x94, 0x82, 0x8c, 0x70, +0x98, 0xba, 0x98, 0xfb, 0x84, 0x20, 0xd5, 0xe7, 0x08, 0x41, 0x80, 0x01, 0x9c, 0x49, 0x84, 0xa4, +0x18, 0x41, 0x00, 0x04, 0xd9, 0xfa, 0x9c, 0x01, 0x4c, 0x00, 0x80, 0x08, 0xf7, 0x0e, 0x94, 0xc2, +0x98, 0xf3, 0x98, 0xb8, 0x84, 0x20, 0xd5, 0xf1, 0x04, 0x9f, 0x80, 0x0c, 0x94, 0x2a, 0xb6, 0x09, +0xed, 0x44, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x9c, 0x80, 0xc0, +0x44, 0x00, 0x00, 0x10, 0xf3, 0x83, 0xf2, 0x88, 0xf4, 0x89, 0xf5, 0x8a, 0x4c, 0x30, 0x00, 0x0d, +0x44, 0x20, 0x00, 0x18, 0x4c, 0x31, 0x00, 0x09, 0x41, 0xe0, 0x04, 0x08, 0x4c, 0x3f, 0x00, 0x05, +0x84, 0x1f, 0x48, 0x00, 0x00, 0x8d, 0x8e, 0x28, 0x80, 0x01, 0x84, 0xe0, 0xf1, 0x81, 0xf7, 0x97, +0x49, 0xff, 0xf2, 0x96, 0xf0, 0x82, 0xc8, 0x04, 0x84, 0x1e, 0x48, 0x00, 0x00, 0x81, 0x50, 0x0f, +0x80, 0x54, 0x80, 0x26, 0x84, 0x48, 0x49, 0xfe, 0xa3, 0xd9, 0xf2, 0x01, 0xf0, 0x02, 0x50, 0x13, +0x00, 0x08, 0x40, 0x61, 0x0c, 0x09, 0x54, 0x83, 0x00, 0xff, 0x49, 0xfe, 0xa3, 0xcf, 0x83, 0x86, +0x84, 0xe5, 0x43, 0xc4, 0x1c, 0x73, 0x40, 0xa3, 0x0c, 0x08, 0x05, 0xef, 0x80, 0x02, 0x8f, 0x48, +0x52, 0x84, 0x00, 0x00, 0x54, 0x84, 0x00, 0xff, 0x55, 0xce, 0x00, 0xff, 0x89, 0x5e, 0x9f, 0xb1, +0x14, 0x8f, 0x80, 0x07, 0x15, 0xcf, 0x80, 0x04, 0xf7, 0x85, 0x14, 0xaf, 0x80, 0x0b, 0xf6, 0x86, +0xf6, 0x06, 0x04, 0xaf, 0x80, 0x0b, 0x05, 0xcf, 0x80, 0x04, 0x44, 0x95, 0xa3, 0x98, 0x50, 0x8f, +0x80, 0x5c, 0x50, 0x7f, 0x80, 0x4c, 0xd5, 0x2a, 0xa7, 0x0f, 0x9f, 0xb1, 0x40, 0x4e, 0x10, 0x03, +0xaf, 0x0f, 0x51, 0xce, 0x7f, 0xff, 0xdd, 0x29, 0x80, 0x2a, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x3c, +0xdd, 0x29, 0xf3, 0x03, 0x3c, 0x1c, 0x40, 0xfa, 0xf2, 0x08, 0x45, 0xe0, 0x00, 0x10, 0x50, 0x4f, +0x80, 0x44, 0x80, 0xa8, 0x50, 0x0f, 0x80, 0x34, 0x15, 0xef, 0x80, 0x17, 0x49, 0xff, 0xfd, 0x9c, +0x50, 0x1f, 0x80, 0x44, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x54, 0xdd, 0x29, 0x80, 0x0a, 0x80, 0x27, +0x84, 0x48, 0xdd, 0x29, 0x55, 0xce, 0x00, 0xff, 0x8f, 0x48, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x34, +0x50, 0x1f, 0x80, 0x54, 0x4e, 0x64, 0xff, 0xd2, 0xf1, 0x04, 0xf2, 0x07, 0x05, 0xef, 0x80, 0x05, +0x98, 0x0a, 0x96, 0x00, 0x51, 0xef, 0x7f, 0xff, 0xf0, 0x84, 0x84, 0x1f, 0x15, 0xef, 0x80, 0x05, +0x4d, 0xe0, 0x7f, 0xb8, 0xf2, 0x01, 0xf1, 0x0a, 0xb6, 0x41, 0xf2, 0x01, 0xf1, 0x02, 0xf0, 0x09, +0x49, 0xfe, 0xa3, 0x64, 0xf0, 0x02, 0x49, 0xff, 0xf2, 0x1b, 0x84, 0x00, 0xec, 0x64, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x84, 0x60, 0x50, 0x50, 0x00, 0x08, 0xb6, 0x60, +0xa8, 0xc1, 0x80, 0x85, 0x18, 0x32, 0x00, 0x01, 0x44, 0x60, 0x01, 0x00, 0x9c, 0xd9, 0x4c, 0x33, +0x7f, 0xfb, 0x84, 0x80, 0x80, 0x64, 0x40, 0x71, 0x88, 0xd7, 0xa7, 0xe8, 0x9c, 0xd9, 0x99, 0x27, +0x38, 0x60, 0x98, 0x00, 0x99, 0x26, 0x97, 0x20, 0x99, 0x84, 0x8c, 0xc8, 0x00, 0x83, 0x00, 0x00, +0x18, 0x82, 0x80, 0x01, 0xaf, 0xf0, 0x44, 0x60, 0x01, 0x00, 0x4c, 0x33, 0x7f, 0xee, 0x3a, 0x6f, +0xa0, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x84, 0x80, 0xd5, 0x20, 0xb4, 0xc0, 0x9d, 0xb1, +0x97, 0xb0, 0x38, 0x62, 0x98, 0x0e, 0x8c, 0xa8, 0xa7, 0xa8, 0xa1, 0xc1, 0x99, 0xf7, 0x97, 0xf8, +0xa9, 0xc1, 0x99, 0xc7, 0x8c, 0xe8, 0x00, 0x83, 0x80, 0x00, 0x10, 0x82, 0x80, 0x00, 0xaf, 0xb8, +0xa7, 0xe8, 0x38, 0x80, 0x90, 0x00, 0x99, 0xb7, 0x97, 0xb0, 0x99, 0x86, 0x00, 0x53, 0x00, 0x08, +0x40, 0x52, 0xa0, 0x03, 0x38, 0x51, 0x90, 0x08, 0x9d, 0x21, 0x80, 0xa0, 0xe2, 0x82, 0xe9, 0xdf, +0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0x84, 0x40, 0xd5, 0x12, +0xb4, 0x80, 0x9c, 0x91, 0x9d, 0x21, 0x97, 0x20, 0x38, 0x41, 0x90, 0x0e, 0x8c, 0x68, 0xa7, 0x58, +0xa1, 0x01, 0x99, 0x2c, 0x97, 0x20, 0xa9, 0x01, 0x99, 0x04, 0x8c, 0x88, 0xa7, 0xa0, 0xaf, 0x98, +0xaf, 0x60, 0x80, 0x60, 0xe2, 0x41, 0xe9, 0xed, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xe4, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, 0x84, 0x20, 0x44, 0x20, +0x00, 0x60, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x68, 0x81, 0x44, 0x81, 0x25, 0x50, 0x8f, 0x80, 0xc8, +0x49, 0xfe, 0xa2, 0xf2, 0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x50, 0x0f, 0x80, 0x08, 0x49, 0xfe, +0xa2, 0xeb, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0xa2, 0xe5, 0x5c, 0xf3, +0x00, 0x41, 0xe8, 0x0c, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x46, 0x49, 0xfe, 0xa2, 0xc7, 0x50, 0x6f, +0x80, 0xc8, 0x51, 0xcf, 0x81, 0x08, 0x80, 0xe6, 0xd5, 0x07, 0x80, 0x1c, 0x80, 0x26, 0x80, 0x48, +0x49, 0x00, 0x06, 0x88, 0xd5, 0xf5, 0xa6, 0x38, 0x56, 0x00, 0x00, 0x36, 0x18, 0x03, 0x80, 0x01, +0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x68, 0x80, 0x07, 0x49, 0x00, 0x06, 0x61, 0x80, 0x07, +0x50, 0x1f, 0x80, 0xc8, 0x44, 0x20, 0x00, 0x40, 0x49, 0x00, 0x06, 0x16, 0xb4, 0x3f, 0xf2, 0x01, +0x80, 0x07, 0x49, 0x00, 0x06, 0x11, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x08, 0x49, 0x00, 0x05, 0xd8, +0xa6, 0x30, 0x56, 0x00, 0x00, 0x6a, 0x18, 0x03, 0x00, 0x01, 0x4c, 0x6e, 0x7f, 0xfb, 0x50, 0x7f, +0x80, 0x08, 0x80, 0x07, 0x49, 0x00, 0x06, 0x44, 0x80, 0x07, 0x50, 0x1f, 0x80, 0xc8, 0x44, 0x20, +0x00, 0x40, 0x50, 0x6f, 0x81, 0x08, 0x49, 0x00, 0x05, 0xf7, 0x44, 0x20, 0x00, 0x10, 0x80, 0x07, +0x80, 0x26, 0x49, 0x00, 0x05, 0xf1, 0x80, 0x07, 0x80, 0x26, 0x49, 0x00, 0x05, 0xb9, 0xe7, 0x31, +0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0xd5, 0x04, 0x80, 0x0a, 0x80, 0x26, +0x80, 0x49, 0x49, 0xfe, 0xa2, 0x73, 0xed, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xcc, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, 0x84, 0x20, 0x44, 0x20, +0x00, 0x68, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x70, 0x81, 0x44, 0x81, 0x25, 0x50, 0x8f, 0x80, 0xdc, +0x49, 0xfe, 0xa2, 0x72, 0x84, 0x20, 0x44, 0x20, 0x00, 0x68, 0x50, 0x0f, 0x80, 0x08, 0x49, 0xfe, +0xa2, 0x6b, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0xa2, 0x65, 0x5c, 0xf3, +0x00, 0x41, 0xe8, 0x0c, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x46, 0x49, 0xfe, 0xa2, 0x47, 0x50, 0x6f, +0x80, 0xdc, 0x51, 0xcf, 0x81, 0x1c, 0x80, 0xe6, 0xd5, 0x07, 0x80, 0x1c, 0x80, 0x26, 0x80, 0x48, +0x49, 0x00, 0x08, 0x20, 0xd5, 0xf5, 0xa6, 0x38, 0x56, 0x00, 0x00, 0x36, 0x18, 0x03, 0x80, 0x01, +0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x70, 0x80, 0x07, 0x49, 0x00, 0x07, 0xf9, 0x80, 0x07, +0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x49, 0x00, 0x07, 0xae, 0xb4, 0x3f, 0xf2, 0x01, +0x80, 0x07, 0x49, 0x00, 0x07, 0xa9, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x1c, 0x49, 0x00, 0x07, 0x2e, +0xa6, 0x30, 0x56, 0x00, 0x00, 0x6a, 0x18, 0x03, 0x00, 0x01, 0x4c, 0x6e, 0x7f, 0xfb, 0x50, 0x7f, +0x80, 0x08, 0x80, 0x07, 0x49, 0x00, 0x07, 0xdc, 0x80, 0x07, 0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, +0x00, 0x40, 0x50, 0x6f, 0x81, 0x1c, 0x49, 0x00, 0x07, 0x8f, 0x44, 0x20, 0x00, 0x14, 0x80, 0x07, +0x80, 0x26, 0x49, 0x00, 0x07, 0x89, 0x80, 0x07, 0x80, 0x26, 0x49, 0x00, 0x07, 0x0f, 0xe7, 0x35, +0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x14, 0xd5, 0x04, 0x80, 0x0a, 0x80, 0x26, +0x80, 0x49, 0x49, 0xfe, 0xa1, 0xf3, 0xed, 0x34, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x5c, 0xf0, 0x85, 0x8c, 0x18, 0xf0, 0x97, 0x50, 0x6f, 0x80, 0x60, +0xf1, 0x17, 0x44, 0x20, 0x00, 0x40, 0x80, 0x06, 0x49, 0xfe, 0xa1, 0xe0, 0x80, 0x46, 0x50, 0x3f, +0x80, 0xa0, 0x9c, 0x94, 0x4c, 0x21, 0xff, 0xff, 0xf1, 0x05, 0xf2, 0x05, 0xa0, 0x49, 0xf5, 0x05, +0xf1, 0x82, 0x50, 0x3f, 0x80, 0x60, 0xa0, 0x92, 0xb4, 0x03, 0xf2, 0x83, 0xf1, 0x05, 0xa1, 0x6b, +0xf2, 0x02, 0xf5, 0x84, 0xf0, 0x96, 0x40, 0x81, 0x08, 0x05, 0xb4, 0x21, 0x40, 0x84, 0x14, 0x02, +0xf5, 0x03, 0x99, 0xc8, 0x46, 0x0d, 0x76, 0xaa, 0x40, 0x92, 0x88, 0x02, 0x58, 0x00, 0x04, 0x78, +0x40, 0x84, 0x24, 0x04, 0x99, 0xf8, 0x88, 0xe8, 0x40, 0x73, 0xe4, 0x0b, 0x98, 0xba, 0x40, 0x81, +0x08, 0x05, 0xf1, 0x81, 0x40, 0x84, 0x14, 0x02, 0xa0, 0x59, 0xf5, 0x04, 0xf0, 0x02, 0xf1, 0x95, +0x99, 0xe9, 0x46, 0x1e, 0x8c, 0x7b, 0x40, 0x91, 0x00, 0x02, 0x58, 0x10, 0x87, 0x56, 0x40, 0x84, +0x24, 0x04, 0x99, 0xf9, 0x88, 0xe8, 0x40, 0x73, 0xd0, 0x0b, 0x99, 0xfa, 0x40, 0x83, 0x9c, 0x05, +0xa1, 0x5a, 0x40, 0x84, 0x00, 0x02, 0xf0, 0x03, 0x46, 0x12, 0x42, 0x07, 0x40, 0x43, 0x88, 0x02, +0x41, 0xc0, 0x14, 0x00, 0x58, 0x10, 0x80, 0xdb, 0x41, 0xce, 0x04, 0x00, 0x40, 0x84, 0x10, 0x04, +0x89, 0x1c, 0x40, 0x84, 0x3c, 0x0b, 0x89, 0x07, 0xf0, 0x02, 0xf5, 0x94, 0xa1, 0x5b, 0x41, 0xc4, +0x20, 0x05, 0x46, 0x1c, 0x1b, 0xdc, 0x40, 0xae, 0x08, 0x02, 0x40, 0x44, 0x1c, 0x02, 0x41, 0xc0, +0x14, 0x00, 0x58, 0x10, 0x8e, 0xee, 0x40, 0x45, 0x10, 0x04, 0x41, 0xce, 0x04, 0x00, 0x41, 0xce, +0x10, 0x00, 0x41, 0xce, 0x28, 0x0b, 0x40, 0x9e, 0x20, 0x00, 0xf5, 0x93, 0x46, 0x0f, 0x57, 0xc0, +0xa1, 0x5c, 0x41, 0xe4, 0xa4, 0x05, 0x58, 0x00, 0x0f, 0xaf, 0x40, 0xa4, 0xa0, 0x02, 0x99, 0x28, +0x41, 0xef, 0x1c, 0x02, 0x99, 0x22, 0x41, 0xef, 0x28, 0x04, 0x41, 0xe2, 0x78, 0x00, 0x41, 0xef, +0x64, 0x0b, 0xa0, 0x5d, 0xf5, 0x92, 0x46, 0x24, 0x78, 0x7c, 0x40, 0x5f, 0x24, 0x00, 0x40, 0xa2, +0x94, 0x05, 0x58, 0x21, 0x06, 0x2a, 0x99, 0x0a, 0x40, 0xa5, 0x20, 0x02, 0x40, 0x22, 0xa4, 0x02, +0x99, 0xe7, 0x40, 0xa5, 0x08, 0x04, 0x89, 0x47, 0x40, 0xa5, 0x50, 0x0b, 0x41, 0xe5, 0x14, 0x00, +0xa0, 0x1e, 0xf1, 0x91, 0x46, 0x1a, 0x83, 0x04, 0x40, 0x7f, 0x78, 0x05, 0x58, 0x10, 0x86, 0x13, +0x99, 0x01, 0x40, 0x2f, 0x14, 0x02, 0x40, 0x73, 0xa4, 0x02, 0x89, 0x04, 0x40, 0x73, 0x88, 0x04, +0x88, 0xe8, 0x40, 0x73, 0xbc, 0x0b, 0x40, 0x63, 0xf8, 0x00, 0xa0, 0x9f, 0xf0, 0x90, 0x46, 0x0f, +0xd4, 0x69, 0x41, 0xc3, 0x18, 0x05, 0x58, 0x00, 0x05, 0x01, 0xf2, 0x8f, 0x40, 0x81, 0x00, 0x00, +0x41, 0xce, 0x14, 0x02, 0x40, 0x23, 0x78, 0x02, 0x89, 0x09, 0x41, 0xce, 0x08, 0x04, 0x41, 0xc4, +0x70, 0x00, 0x41, 0xce, 0x28, 0x0b, 0x40, 0x2e, 0x18, 0x00, 0x04, 0x11, 0x80, 0x08, 0x46, 0x06, +0x98, 0x09, 0x40, 0x81, 0x08, 0x05, 0x58, 0x00, 0x08, 0xd8, 0x40, 0x94, 0x78, 0x02, 0x99, 0x08, +0x40, 0x81, 0x18, 0x02, 0x99, 0x25, 0x40, 0x84, 0xa0, 0x04, 0x89, 0x04, 0x40, 0x84, 0x64, 0x0b, +0x40, 0x54, 0x08, 0x00, 0xf1, 0x8e, 0x46, 0x08, 0xb4, 0x4f, 0x04, 0x11, 0x80, 0x09, 0x40, 0xa2, +0x94, 0x05, 0x58, 0x00, 0x07, 0xaf, 0x40, 0x42, 0x88, 0x02, 0x40, 0x90, 0x80, 0x00, 0x40, 0xa5, +0x18, 0x02, 0x89, 0x3e, 0x40, 0xa5, 0x10, 0x04, 0x89, 0x49, 0x40, 0xa5, 0x50, 0x0b, 0x40, 0x85, +0x14, 0x00, 0xf1, 0x8d, 0x04, 0x11, 0x80, 0x0a, 0x40, 0x74, 0x20, 0x05, 0x44, 0x0f, 0x5b, 0xb1, +0x41, 0xe4, 0x14, 0x02, 0x41, 0xc0, 0x80, 0x00, 0x40, 0x73, 0x88, 0x02, 0x41, 0xce, 0x18, 0x00, +0x40, 0x73, 0xf8, 0x04, 0x88, 0xfc, 0x40, 0x73, 0xbc, 0x0b, 0x40, 0x63, 0xa0, 0x00, 0xf1, 0x8c, +0x46, 0x08, 0x95, 0xcd, 0x04, 0x11, 0x80, 0x0b, 0x41, 0xc3, 0x18, 0x05, 0x58, 0x00, 0x07, 0xbe, +0x41, 0xe3, 0x20, 0x02, 0x99, 0xc8, 0x41, 0xce, 0x14, 0x02, 0x99, 0xfa, 0x41, 0xce, 0x78, 0x04, +0x41, 0xc3, 0xf0, 0x00, 0x41, 0xce, 0x28, 0x0b, 0x40, 0x9e, 0x18, 0x00, 0xf1, 0x8b, 0x46, 0x26, +0xb9, 0x01, 0x04, 0x11, 0x80, 0x0c, 0x41, 0xe4, 0xa4, 0x05, 0x58, 0x21, 0x01, 0x22, 0x99, 0x0a, +0x41, 0xef, 0x20, 0x02, 0x40, 0x24, 0x98, 0x02, 0x99, 0x25, 0x41, 0xef, 0x08, 0x04, 0x41, 0xe2, +0x78, 0x00, 0x41, 0xef, 0x64, 0x0b, 0x40, 0x5f, 0x24, 0x00, 0xf1, 0x8a, 0x04, 0x01, 0x80, 0x0d, +0x46, 0x1f, 0xd9, 0x87, 0x40, 0xa2, 0x94, 0x05, 0x58, 0x10, 0x81, 0x93, 0x40, 0x22, 0xa4, 0x02, +0x99, 0x01, 0x40, 0xa5, 0x18, 0x02, 0x88, 0x88, 0x40, 0xa5, 0x08, 0x04, 0x89, 0x44, 0x40, 0xa5, +0x50, 0x0b, 0x40, 0x15, 0x14, 0x00, 0xf0, 0x89, 0x04, 0x21, 0x80, 0x0e, 0x46, 0x0a, 0x67, 0x94, +0x41, 0xe0, 0x84, 0x05, 0x58, 0x00, 0x03, 0x8e, 0xf2, 0x88, 0x40, 0x81, 0x00, 0x00, 0x40, 0x7f, +0x24, 0x02, 0x40, 0x20, 0x94, 0x02, 0x89, 0x06, 0x40, 0x73, 0x88, 0x04, 0x88, 0xe8, 0x40, 0x73, +0xbc, 0x0b, 0x99, 0xb9, 0x04, 0x31, 0x80, 0x0f, 0x46, 0x24, 0x9b, 0x40, 0x40, 0xa3, 0x18, 0x05, +0x58, 0x21, 0x08, 0x21, 0x40, 0x73, 0x04, 0x02, 0x40, 0x81, 0x88, 0x00, 0x41, 0xc5, 0x14, 0x02, +0x89, 0x09, 0x41, 0xce, 0x1c, 0x04, 0x41, 0xc4, 0x70, 0x00, 0xf3, 0x87, 0x41, 0xce, 0x28, 0x0b, +0xf3, 0x15, 0x46, 0x0f, 0x61, 0xe2, 0x40, 0x4e, 0x18, 0x00, 0x58, 0x00, 0x05, 0x62, 0x41, 0xc2, +0x04, 0x02, 0x40, 0x91, 0x80, 0x00, 0x41, 0xe3, 0x78, 0x02, 0x89, 0x25, 0x41, 0xee, 0x78, 0x04, +0x41, 0xe4, 0xf8, 0x00, 0xf2, 0x10, 0x41, 0xef, 0x6c, 0x0b, 0x46, 0x0c, 0x04, 0x0b, 0x40, 0x5f, +0x10, 0x00, 0x58, 0x00, 0x03, 0x40, 0x41, 0xc2, 0x98, 0x02, 0x98, 0xd0, 0x40, 0xa2, 0x28, 0x02, +0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, 0x5c, 0x0b, 0xf3, 0x0b, 0x46, 0x02, +0x65, 0xe5, 0x40, 0x15, 0x14, 0x00, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x0a, 0x51, 0x41, 0xc0, +0x90, 0x02, 0x98, 0x98, 0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, 0x1c, 0x04, 0x99, 0xd7, +0x40, 0x73, 0xc8, 0x0b, 0xf2, 0x16, 0x46, 0x3e, 0x9b, 0x6c, 0x99, 0xb9, 0x41, 0xc2, 0x94, 0x05, +0x58, 0x31, 0x87, 0xaa, 0x40, 0x73, 0x14, 0x02, 0x40, 0x81, 0x0c, 0x00, 0x41, 0xc0, 0xf0, 0x02, +0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, 0x41, 0xc4, 0x70, 0x00, 0xf0, 0x11, 0x41, 0xce, 0x30, 0x0b, +0x46, 0x2d, 0x62, 0xf1, 0x40, 0x4e, 0x18, 0x00, 0x41, 0xe0, 0x84, 0x05, 0x58, 0x21, 0x00, 0x5d, +0x41, 0xc2, 0x04, 0x02, 0x40, 0x90, 0x08, 0x00, 0x41, 0xe3, 0x78, 0x02, 0x89, 0x25, 0x41, 0xee, +0x78, 0x04, 0x41, 0xe4, 0xf8, 0x00, 0xf0, 0x0c, 0x41, 0xef, 0x6c, 0x0b, 0x46, 0x20, 0x24, 0x41, +0x40, 0x5f, 0x10, 0x00, 0x40, 0xa3, 0x18, 0x05, 0x58, 0x21, 0x04, 0x53, 0x41, 0xc2, 0x98, 0x02, +0x98, 0xc2, 0x40, 0xa2, 0x28, 0x02, 0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, +0x5c, 0x0b, 0xf3, 0x07, 0x46, 0x0d, 0x8a, 0x1e, 0x40, 0x15, 0x14, 0x00, 0x40, 0x72, 0x10, 0x05, +0x58, 0x00, 0x06, 0x81, 0x41, 0xc0, 0x90, 0x02, 0x98, 0x98, 0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, +0x40, 0x7e, 0x1c, 0x04, 0x99, 0xd7, 0x40, 0x73, 0xc8, 0x0b, 0xf2, 0x12, 0x46, 0x3e, 0x7d, 0x3f, +0x99, 0xb9, 0x41, 0xc2, 0x94, 0x05, 0x58, 0x31, 0x8b, 0xc8, 0x40, 0x73, 0x14, 0x02, 0x40, 0x81, +0x0c, 0x00, 0x41, 0xc0, 0xf0, 0x02, 0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, 0x41, 0xc4, 0x70, 0x00, +0xf0, 0x0d, 0x41, 0xce, 0x30, 0x0b, 0x46, 0x22, 0x1e, 0x1c, 0x40, 0x4e, 0x18, 0x00, 0x41, 0xe0, +0x84, 0x05, 0x58, 0x21, 0x0d, 0xe6, 0x41, 0xc2, 0x04, 0x02, 0x40, 0x90, 0x08, 0x00, 0x41, 0xe3, +0x78, 0x02, 0x89, 0x25, 0x41, 0xee, 0x78, 0x04, 0x41, 0xe4, 0xf8, 0x00, 0xf0, 0x08, 0x41, 0xef, +0x6c, 0x0b, 0x46, 0x2c, 0x33, 0x70, 0x40, 0x5f, 0x10, 0x00, 0x40, 0xa3, 0x18, 0x05, 0x58, 0x21, +0x07, 0xd6, 0x41, 0xc2, 0x98, 0x02, 0x98, 0xc2, 0x40, 0xa2, 0x28, 0x02, 0x98, 0xd9, 0x40, 0xae, +0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, 0x5c, 0x0b, 0xf3, 0x13, 0x46, 0x0f, 0x4d, 0x50, 0x40, 0x15, +0x14, 0x00, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x0d, 0x87, 0x41, 0xc0, 0x90, 0x02, 0x98, 0x98, +0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, 0x1c, 0x04, 0x99, 0xd7, 0x40, 0x73, 0xc8, 0x0b, +0xf2, 0x0e, 0x46, 0x34, 0x55, 0xa1, 0x99, 0xb9, 0x41, 0xc2, 0x94, 0x05, 0x58, 0x31, 0x84, 0xed, +0x40, 0x73, 0x14, 0x02, 0x40, 0x81, 0x0c, 0x00, 0x41, 0xc0, 0xf0, 0x02, 0x89, 0x04, 0x41, 0xc3, +0xf0, 0x04, 0x41, 0xc4, 0x70, 0x00, 0xf0, 0x09, 0x41, 0xce, 0x30, 0x0b, 0x46, 0x2a, 0x9e, 0x3e, +0x40, 0x4e, 0x18, 0x00, 0x41, 0xe0, 0x84, 0x05, 0x58, 0x21, 0x09, 0x05, 0x41, 0xc2, 0x04, 0x02, +0x40, 0x90, 0x08, 0x00, 0x41, 0xe3, 0x78, 0x02, 0x89, 0x25, 0x41, 0xee, 0x78, 0x04, 0x41, 0xe4, +0xf8, 0x00, 0xf0, 0x14, 0x41, 0xef, 0x6c, 0x0b, 0x46, 0x2f, 0xce, 0xfa, 0x40, 0x5f, 0x10, 0x00, +0x40, 0xa3, 0x18, 0x05, 0x58, 0x21, 0x03, 0xf8, 0x41, 0xc2, 0x98, 0x02, 0x98, 0xc2, 0x40, 0xa2, +0x28, 0x02, 0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, 0x5c, 0x0b, 0xf3, 0x0f, +0x46, 0x06, 0x76, 0xf0, 0x89, 0x45, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x02, 0xd9, 0x41, 0xc5, +0x10, 0x02, 0x98, 0x98, 0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, 0x1c, 0x04, 0x99, 0xd7, +0xf1, 0x0a, 0x40, 0x73, 0xc8, 0x0b, 0x46, 0x28, 0xd2, 0xa4, 0x40, 0x03, 0xa8, 0x00, 0x41, 0xc2, +0x94, 0x05, 0x58, 0x21, 0x0c, 0x8a, 0x40, 0x70, 0x14, 0x02, 0x40, 0x80, 0x88, 0x00, 0x41, 0xc5, +0x70, 0x02, 0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, 0xf3, 0x11, 0x41, 0xc4, 0x70, 0x00, 0x41, 0xce, +0x30, 0x0b, 0x44, 0x1a, 0x39, 0x42, 0x40, 0x4e, 0x00, 0x00, 0x40, 0x91, 0x84, 0x00, 0x41, 0xe0, +0x28, 0x03, 0x14, 0xaf, 0x80, 0x06, 0xf2, 0x0e, 0x89, 0x25, 0x41, 0xef, 0x10, 0x03, 0x46, 0x58, +0x77, 0x1f, 0x41, 0xe4, 0xf8, 0x00, 0x58, 0x52, 0x86, 0x81, 0x98, 0xd5, 0x41, 0xef, 0x70, 0x0b, +0xf2, 0x06, 0x40, 0x1f, 0x10, 0x00, 0x40, 0xa2, 0x00, 0x03, 0x98, 0xda, 0x40, 0xa5, 0x04, 0x03, +0x89, 0x43, 0x46, 0x56, 0xd9, 0xd6, 0xf3, 0x0b, 0x40, 0xa5, 0x54, 0x0b, 0x58, 0x52, 0x81, 0x22, +0x40, 0x65, 0x04, 0x00, 0x98, 0x9d, 0x40, 0x70, 0x90, 0x03, 0x98, 0x90, 0x40, 0x73, 0x98, 0x03, +0xf0, 0x08, 0x99, 0xd7, 0x46, 0x2f, 0xde, 0x53, 0x40, 0x73, 0xc0, 0x0b, 0x58, 0x21, 0x08, 0x0c, +0x99, 0x7e, 0x40, 0x80, 0x08, 0x00, 0x41, 0xc3, 0x04, 0x03, 0x89, 0x04, 0x41, 0xce, 0x14, 0x03, +0xf3, 0x15, 0x41, 0xc4, 0x70, 0x00, 0x46, 0x0a, 0x4b, 0xee, 0x41, 0xce, 0x24, 0x0b, 0x58, 0x00, +0x0a, 0x44, 0x40, 0x4e, 0x14, 0x00, 0x40, 0x91, 0x80, 0x00, 0x41, 0xe2, 0x98, 0x03, 0x89, 0x21, +0x41, 0xef, 0x10, 0x03, 0xf2, 0x12, 0x41, 0xe4, 0xf8, 0x00, 0x46, 0x04, 0xbd, 0xec, 0x41, 0xef, +0x70, 0x0b, 0x58, 0x00, 0x0f, 0xa9, 0x40, 0x1f, 0x10, 0x00, 0x98, 0xd0, 0x40, 0xa2, 0x14, 0x03, +0x98, 0xde, 0x40, 0xa5, 0x04, 0x03, 0x89, 0x43, 0x46, 0x0f, 0x6b, 0xb4, 0xf3, 0x0f, 0x40, 0xa5, +0x54, 0x0b, 0x58, 0x00, 0x0b, 0x60, 0x40, 0x65, 0x04, 0x00, 0x98, 0x98, 0x40, 0x70, 0x90, 0x03, +0x98, 0x95, 0x40, 0x73, 0x98, 0x03, 0x99, 0xd7, 0x46, 0x3b, 0xeb, 0xfb, 0xf2, 0x0c, 0x40, 0x73, +0xc0, 0x0b, 0x58, 0x31, 0x8c, 0x70, 0x99, 0x7e, 0x40, 0x81, 0x0c, 0x00, 0x41, 0xc3, 0x04, 0x03, +0x89, 0x04, 0x41, 0xce, 0x14, 0x03, 0xf0, 0x09, 0x41, 0xc4, 0x70, 0x00, 0x46, 0x22, 0x89, 0xb7, +0x41, 0xce, 0x24, 0x0b, 0x58, 0x21, 0x0e, 0xc6, 0x40, 0x4e, 0x14, 0x00, 0x40, 0x90, 0x08, 0x00, +0x41, 0xe2, 0x98, 0x03, 0x89, 0x21, 0x41, 0xef, 0x10, 0x03, 0xf0, 0x16, 0x41, 0xe4, 0xf8, 0x00, +0x46, 0x2e, 0xaa, 0x12, 0x41, 0xef, 0x70, 0x0b, 0x58, 0x21, 0x07, 0xfa, 0x40, 0x1f, 0x10, 0x00, +0x98, 0xc2, 0x40, 0xa2, 0x14, 0x03, 0x98, 0xde, 0x40, 0xa5, 0x04, 0x03, 0x89, 0x43, 0x46, 0x0d, +0x4e, 0xf3, 0xf3, 0x13, 0x40, 0xa5, 0x54, 0x0b, 0x58, 0x00, 0x00, 0x85, 0x40, 0x65, 0x04, 0x00, +0x98, 0x98, 0x40, 0x70, 0x90, 0x03, 0x98, 0x95, 0x40, 0x73, 0x98, 0x03, 0x99, 0xd7, 0x46, 0x30, +0x48, 0x81, 0xf2, 0x10, 0x40, 0x73, 0xc0, 0x0b, 0x58, 0x31, 0x8d, 0x05, 0x99, 0x7e, 0x40, 0x81, +0x0c, 0x00, 0x41, 0xc3, 0x04, 0x03, 0x89, 0x04, 0x41, 0xce, 0x14, 0x03, 0xf0, 0x0d, 0x41, 0xc4, +0x70, 0x00, 0x46, 0x2d, 0x9d, 0x4d, 0x41, 0xce, 0x24, 0x0b, 0x58, 0x21, 0x00, 0x39, 0x40, 0x4e, +0x14, 0x00, 0x40, 0x90, 0x08, 0x00, 0x41, 0xe2, 0x98, 0x03, 0x89, 0x21, 0x41, 0xef, 0x10, 0x03, +0xf0, 0x0a, 0x41, 0xe4, 0xf8, 0x00, 0x46, 0x1e, 0x6d, 0xb9, 0x41, 0xef, 0x70, 0x0b, 0x58, 0x10, +0x89, 0xe5, 0x40, 0x9f, 0x10, 0x00, 0x98, 0xc1, 0x40, 0xa2, 0x14, 0x03, 0x98, 0xde, 0x40, 0xa5, +0x24, 0x03, 0x89, 0x43, 0x46, 0x01, 0xfa, 0x27, 0xf3, 0x07, 0x58, 0x00, 0x0c, 0xf8, 0x40, 0xa5, +0x54, 0x0b, 0x89, 0x49, 0x98, 0x98, 0x40, 0x74, 0x90, 0x03, 0x98, 0x95, 0x40, 0x73, 0xa8, 0x03, +0xf1, 0x14, 0x99, 0xd7, 0x46, 0x2c, 0x4a, 0xc5, 0x58, 0x21, 0x06, 0x65, 0x40, 0x73, 0xc0, 0x0b, +0x88, 0xea, 0x40, 0x80, 0x88, 0x00, 0x41, 0xc5, 0x24, 0x03, 0x89, 0x04, 0x41, 0xce, 0x1c, 0x03, +0x41, 0xc4, 0x70, 0x00, 0xf3, 0x16, 0x41, 0xce, 0x24, 0x0b, 0x46, 0x5f, 0x42, 0x92, 0x40, 0x2e, +0x1c, 0x00, 0x41, 0xe5, 0x28, 0x05, 0x58, 0x52, 0x82, 0x44, 0x99, 0x9d, 0x41, 0xe1, 0x78, 0x04, +0x88, 0xc9, 0x41, 0xef, 0x1c, 0x03, 0x41, 0xe3, 0x78, 0x00, 0xf0, 0x0f, 0x41, 0xef, 0x68, 0x0b, +0x46, 0x14, 0x32, 0xaf, 0x41, 0xef, 0x08, 0x00, 0x40, 0x63, 0x9c, 0x05, 0x58, 0x10, 0x8f, 0x97, +0x99, 0x41, 0x40, 0x6f, 0x18, 0x04, 0x88, 0xaa, 0x40, 0xa3, 0x08, 0x03, 0x89, 0x45, 0xf3, 0x08, +0x40, 0xa5, 0x58, 0x0b, 0x46, 0x0a, 0xb9, 0x42, 0x40, 0x85, 0x78, 0x00, 0x40, 0x51, 0x08, 0x05, +0x58, 0x00, 0x03, 0xa7, 0x99, 0x18, 0x40, 0x54, 0x14, 0x04, 0x99, 0x27, 0x40, 0x72, 0xf8, 0x03, +0x99, 0xe7, 0xf1, 0x11, 0x40, 0x73, 0xc4, 0x0b, 0x46, 0x3f, 0xc9, 0x3a, 0x40, 0x43, 0xa0, 0x00, +0x41, 0xcf, 0x78, 0x05, 0x58, 0x31, 0x80, 0x39, 0x40, 0xa0, 0x8c, 0x00, 0x41, 0xc2, 0x70, 0x04, +0x89, 0x42, 0x41, 0xce, 0x20, 0x03, 0x41, 0xc5, 0x70, 0x00, 0xf5, 0x0a, 0x41, 0xce, 0x2c, 0x0b, +0x46, 0x06, 0x55, 0xb5, 0x41, 0xce, 0x10, 0x00, 0x40, 0xa4, 0x20, 0x05, 0x58, 0x00, 0x09, 0xc3, +0x99, 0xe8, 0x40, 0xae, 0x28, 0x04, 0x88, 0xfe, 0x41, 0xe5, 0x10, 0x03, 0x41, 0xe3, 0xf8, 0x00, +0xf1, 0x13, 0x41, 0xef, 0x68, 0x0b, 0x46, 0x28, 0xf0, 0xcc, 0x40, 0x6f, 0x70, 0x00, 0x40, 0xa2, +0x10, 0x05, 0x58, 0x21, 0x0c, 0x92, 0x41, 0xe0, 0x88, 0x00, 0x40, 0xa3, 0x28, 0x04, 0x41, 0xef, +0x20, 0x00, 0x40, 0xa5, 0x70, 0x03, 0x89, 0x5e, 0xf3, 0x0c, 0x40, 0xa5, 0x58, 0x0b, 0x46, 0x0f, +0xfe, 0xff, 0x40, 0x55, 0x18, 0x00, 0x40, 0x7e, 0x70, 0x05, 0x58, 0x00, 0x04, 0x7d, 0x40, 0x91, +0x80, 0x00, 0x40, 0x72, 0x9c, 0x04, 0x89, 0x24, 0x40, 0x73, 0x98, 0x03, 0x88, 0xe9, 0xf1, 0x15, +0x40, 0x73, 0xc4, 0x0b, 0x46, 0x28, 0x58, 0x45, 0x99, 0x3d, 0x40, 0x93, 0x18, 0x05, 0x58, 0x21, +0x0d, 0xd1, 0x98, 0xca, 0x40, 0x92, 0x24, 0x04, 0x88, 0x7c, 0x41, 0xc4, 0x94, 0x03, 0x41, 0xc1, +0xf0, 0x00, 0x41, 0xce, 0x2c, 0x0b, 0xf3, 0x0e, 0x46, 0x06, 0xfa, 0x87, 0x41, 0xce, 0x10, 0x00, +0x41, 0xe2, 0x94, 0x05, 0x58, 0x00, 0x0e, 0x4f, 0x98, 0x98, 0x41, 0xee, 0x78, 0x04, 0x98, 0x96, +0x41, 0xef, 0x10, 0x03, 0x41, 0xe1, 0x78, 0x00, 0xf1, 0x07, 0x41, 0xef, 0x68, 0x0b, 0x46, 0x3f, +0xe2, 0xce, 0x40, 0x2f, 0x70, 0x00, 0x40, 0xa2, 0x10, 0x05, 0x58, 0x31, 0x86, 0xe0, 0x40, 0x80, +0x8c, 0x00, 0x40, 0xa1, 0x28, 0x04, 0x89, 0x05, 0x40, 0xa5, 0x70, 0x03, 0x89, 0x48, 0xf5, 0x10, +0x40, 0xa5, 0x58, 0x0b, 0x46, 0x0a, 0x30, 0x14, 0x40, 0x85, 0x08, 0x00, 0x40, 0x7e, 0x70, 0x05, +0x58, 0x00, 0x03, 0x14, 0x99, 0xa8, 0x40, 0x74, 0x1c, 0x04, 0x99, 0xb4, 0x40, 0x73, 0x88, 0x03, +0x99, 0xf7, 0xf1, 0x09, 0x40, 0x73, 0xc4, 0x0b, 0x46, 0x34, 0xe0, 0x81, 0x40, 0x63, 0xa0, 0x00, +0x58, 0x31, 0x81, 0xa1, 0x40, 0x71, 0x08, 0x05, 0x99, 0x0b, 0x40, 0x73, 0x1c, 0x04, 0x40, 0x73, +0xa0, 0x03, 0x88, 0x9c, 0x99, 0x27, 0xf0, 0x12, 0x40, 0x42, 0x2c, 0x0b, 0x46, 0x1f, 0x75, 0x37, +0x99, 0x26, 0x41, 0xe4, 0x20, 0x05, 0x58, 0x10, 0x8e, 0x82, 0x99, 0x41, 0x41, 0xe2, 0x78, 0x04, +0x99, 0x6a, 0x41, 0xef, 0x18, 0x03, 0x41, 0xe2, 0xf8, 0x00, 0xf2, 0x0b, 0x41, 0xef, 0x68, 0x0b, +0x46, 0x3b, 0xd3, 0xaf, 0x41, 0xef, 0x10, 0x00, 0x40, 0xa3, 0x18, 0x05, 0x58, 0x31, 0x82, 0x35, +0x41, 0xc1, 0x0c, 0x00, 0x40, 0xaf, 0x28, 0x04, 0x41, 0xce, 0x20, 0x00, 0x40, 0xa5, 0x10, 0x03, +0x89, 0x5c, 0xf5, 0x14, 0x40, 0xa5, 0x58, 0x0b, 0x46, 0x02, 0xad, 0x7d, 0x40, 0x25, 0x78, 0x00, +0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x02, 0xbb, 0x40, 0x92, 0x80, 0x00, 0x40, 0x71, 0x1c, 0x04, +0x89, 0x26, 0x40, 0x73, 0xf8, 0x03, 0x88, 0xe9, 0xf1, 0x0d, 0x40, 0x73, 0xc4, 0x0b, 0x46, 0x5e, +0xb8, 0x6d, 0x98, 0xfa, 0xf0, 0x02, 0x40, 0x7f, 0x78, 0x05, 0x58, 0x52, 0x83, 0x91, 0x40, 0x80, +0x94, 0x00, 0x40, 0x71, 0x9c, 0x04, 0xf1, 0x01, 0x99, 0x98, 0x40, 0x73, 0x88, 0x03, 0xf0, 0x03, +0x88, 0x88, 0x40, 0x5f, 0x04, 0x00, 0x99, 0x27, 0xf1, 0x04, 0x98, 0xc3, 0x40, 0x42, 0x2c, 0x0b, +0xf0, 0x05, 0x99, 0x34, 0x98, 0x8a, 0xb6, 0xa0, 0xa9, 0x01, 0xa8, 0xc2, 0xa8, 0x83, 0x84, 0x20, +0xf0, 0x17, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0x9c, 0xe7, 0xf2, 0x05, 0x84, 0x20, 0x14, 0x11, +0x00, 0x16, 0xec, 0xa4, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0xef, 0xf8, 0x80, 0xc0, 0x04, 0x00, 0x00, 0x16, 0x50, 0x73, 0x00, 0x18, 0x81, 0x01, 0x98, 0x38, +0x44, 0x10, 0x00, 0x80, 0x84, 0x41, 0x49, 0xfe, 0x9c, 0xcf, 0x04, 0x03, 0x00, 0x16, 0x5c, 0xf0, +0x00, 0x38, 0xe9, 0x04, 0x80, 0x06, 0x49, 0xff, 0xfa, 0xc5, 0xa0, 0xf4, 0xa1, 0x35, 0x40, 0x01, +0xf4, 0x09, 0x95, 0x23, 0x40, 0x42, 0x00, 0x04, 0x94, 0xdb, 0xf4, 0x81, 0xb6, 0x7f, 0x80, 0x3f, +0x84, 0x48, 0x50, 0x03, 0x80, 0x38, 0x49, 0xfe, 0x9c, 0xa1, 0x80, 0x06, 0x49, 0xff, 0xfa, 0xb2, +0x80, 0x08, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0x9c, 0x98, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe0, 0x8c, 0x18, 0xf1, 0x81, +0x83, 0x82, 0xb6, 0x1f, 0x85, 0x00, 0xd5, 0x28, 0x04, 0x33, 0x80, 0x16, 0xf1, 0x01, 0xb4, 0x1f, +0x40, 0x50, 0xa0, 0x00, 0x99, 0x03, 0x40, 0x93, 0x0c, 0x00, 0x80, 0x25, 0x80, 0x04, 0x5c, 0xf4, +0x80, 0x40, 0xe8, 0x0a, 0x49, 0xfe, 0x9c, 0x7a, 0x04, 0x23, 0x80, 0x16, 0x89, 0x06, 0x98, 0x96, +0x14, 0x23, 0x80, 0x16, 0xd5, 0x11, 0x52, 0x21, 0x80, 0x40, 0x49, 0xfe, 0x9c, 0x6f, 0x44, 0x00, +0x00, 0x40, 0x04, 0x13, 0x80, 0x16, 0x14, 0x03, 0x80, 0x16, 0x9a, 0x41, 0x80, 0x07, 0x89, 0x01, +0x49, 0xff, 0xfa, 0x78, 0x92, 0x00, 0x40, 0x6e, 0x20, 0x01, 0x80, 0x46, 0x4c, 0x8e, 0x7f, 0xd6, +0xa0, 0x3c, 0xa0, 0x7d, 0x80, 0x48, 0x84, 0x60, 0x99, 0x02, 0xe2, 0x82, 0x99, 0x4b, 0x88, 0xaf, +0xa9, 0x3c, 0xa9, 0x7d, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x3e, 0x19, 0x0a, 0x18, 0x80, 0xc0, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0x9c, 0x47, 0x50, 0x03, +0x00, 0x18, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0x9c, 0x56, 0x84, 0x00, 0x14, 0x03, +0x00, 0x16, 0x84, 0x20, 0x84, 0x00, 0xa8, 0x34, 0xa8, 0x75, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x9c, 0x81, 0x20, 0x81, 0x01, 0x80, 0xe2, 0x84, 0x20, 0x44, 0x20, +0x00, 0x60, 0x80, 0x1f, 0x49, 0xfe, 0x9c, 0x40, 0x80, 0x1f, 0x49, 0xff, 0xff, 0xd9, 0x80, 0x1f, +0x80, 0x29, 0x80, 0x48, 0x49, 0xff, 0xff, 0x90, 0x80, 0x1f, 0x80, 0x27, 0x80, 0xdf, 0x49, 0xff, +0xff, 0x57, 0xec, 0x64, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xee, 0xd4, 0x51, 0xcf, 0x81, 0x08, 0x80, 0xc0, 0x81, 0x42, 0x44, 0x20, 0x00, 0x10, 0x80, 0x1c, +0x81, 0x23, 0x81, 0x04, 0x49, 0xfe, 0x9c, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0x50, 0x0f, +0x81, 0x18, 0x49, 0xfe, 0x9c, 0x03, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x20, 0x80, 0x1f, 0x49, 0xff, +0xf8, 0xa3, 0x80, 0x1f, 0x44, 0x10, 0x01, 0x00, 0x49, 0xff, 0xf8, 0xf0, 0x80, 0x1f, 0x80, 0x2a, +0x80, 0x49, 0x80, 0x68, 0x80, 0xdf, 0x49, 0xff, 0xf8, 0xbf, 0x92, 0x00, 0xed, 0x2c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xff, 0xd1, 0x92, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xb4, 0x80, 0xc0, +0x50, 0x00, 0x00, 0x20, 0xf0, 0x81, 0x50, 0x9f, 0x80, 0x08, 0xf1, 0x01, 0x44, 0x20, 0x00, 0x40, +0x80, 0x09, 0x49, 0xfe, 0x9b, 0xd3, 0x50, 0x8f, 0x80, 0x48, 0x83, 0xc9, 0x80, 0x49, 0xb4, 0x02, +0x44, 0x50, 0xff, 0x00, 0x46, 0xa0, 0x0f, 0xf0, 0x40, 0x40, 0x60, 0x09, 0x40, 0x10, 0x60, 0x08, +0x40, 0x30, 0x14, 0x02, 0x40, 0x12, 0x04, 0x04, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x00, 0x28, 0x02, +0x40, 0x10, 0x8c, 0x04, 0x92, 0x08, 0x40, 0x00, 0x80, 0x04, 0xaa, 0x11, 0x4c, 0x24, 0x7f, 0xe9, +0x50, 0x2f, 0x80, 0x3c, 0x50, 0x34, 0x81, 0x34, 0x04, 0x41, 0x7f, 0xfb, 0xb4, 0x22, 0x04, 0x01, +0x7f, 0xf5, 0x40, 0x12, 0x04, 0x03, 0x04, 0x41, 0x7f, 0xf3, 0x40, 0x00, 0x80, 0x03, 0x40, 0x00, +0x10, 0x03, 0x40, 0x00, 0x7c, 0x0b, 0xa8, 0x13, 0x9c, 0x94, 0x4c, 0x21, 0xff, 0xef, 0xb4, 0x06, +0x04, 0x83, 0x00, 0x01, 0xa1, 0x32, 0xa0, 0xf3, 0x05, 0xc3, 0x00, 0x04, 0x50, 0x14, 0x80, 0x50, +0x80, 0xe0, 0x0c, 0x5f, 0x00, 0x01, 0x46, 0xa5, 0xa8, 0x27, 0x58, 0xa5, 0x09, 0x99, 0x40, 0x24, +0x20, 0x05, 0x88, 0xaa, 0x88, 0xbc, 0x40, 0xa2, 0x20, 0x02, 0x41, 0xc3, 0xec, 0x0b, 0x40, 0x21, +0x0c, 0x02, 0x88, 0xbc, 0x40, 0x21, 0x28, 0x03, 0x99, 0x6a, 0x83, 0x83, 0x40, 0x24, 0x08, 0x0b, +0x81, 0x07, 0x4d, 0xe0, 0x80, 0x06, 0x80, 0x64, 0x80, 0xe5, 0x80, 0x82, 0xd5, 0xe3, 0x83, 0xc3, +0x50, 0x8f, 0x80, 0x58, 0x50, 0xa4, 0x80, 0xa0, 0x0d, 0xc4, 0x00, 0x01, 0x46, 0x36, 0xed, 0x9e, +0x58, 0x31, 0x8b, 0xa1, 0x41, 0xce, 0x0c, 0x00, 0x40, 0x11, 0x1c, 0x03, 0x41, 0xce, 0x78, 0x00, +0x40, 0x32, 0xec, 0x0b, 0x41, 0xce, 0x0c, 0x00, 0x40, 0x10, 0x90, 0x03, 0x40, 0x33, 0x88, 0x0b, +0x41, 0xce, 0x04, 0x00, 0x83, 0xc4, 0x80, 0xe5, 0x4c, 0x85, 0x00, 0x06, 0x80, 0x82, 0x80, 0xbc, +0x80, 0x43, 0xd5, 0xe3, 0x81, 0x05, 0x80, 0xbc, 0x80, 0xe2, 0x51, 0xcf, 0x80, 0xa8, 0x50, 0x14, +0x80, 0xf0, 0x0c, 0x4e, 0x00, 0x01, 0x46, 0xa8, 0xf1, 0xbb, 0x58, 0xa5, 0x0c, 0xdc, 0x88, 0x8a, +0x40, 0x21, 0x9c, 0x03, 0x88, 0x9e, 0x40, 0x21, 0x20, 0x02, 0x41, 0xe2, 0xec, 0x0b, 0x40, 0xa3, +0x8c, 0x02, 0x88, 0x9e, 0x40, 0x21, 0x28, 0x03, 0x99, 0x22, 0x83, 0xc7, 0x40, 0x24, 0x08, 0x0b, +0x81, 0x05, 0x4d, 0xc0, 0x80, 0x06, 0x80, 0xe3, 0x80, 0xa4, 0x80, 0x62, 0xd5, 0xe3, 0x83, 0x87, +0x50, 0x94, 0x81, 0x40, 0x50, 0x7f, 0x80, 0xf8, 0x0c, 0xa3, 0x80, 0x01, 0x46, 0x8c, 0xa6, 0x2c, +0x58, 0x84, 0x01, 0xd6, 0x89, 0x48, 0x40, 0x11, 0x14, 0x03, 0x89, 0x5c, 0x40, 0x82, 0x6c, 0x0b, +0x89, 0x48, 0x40, 0x10, 0x8c, 0x03, 0x40, 0x82, 0x88, 0x0b, 0x89, 0x41, 0x83, 0x83, 0x80, 0xa4, +0x4c, 0x74, 0x80, 0x06, 0x80, 0x62, 0x80, 0x8a, 0x80, 0x48, 0xd5, 0xe7, 0x05, 0xc3, 0x00, 0x01, +0x04, 0x93, 0x00, 0x02, 0xa1, 0xf3, 0xa1, 0x74, 0x89, 0x40, 0x88, 0x9c, 0x98, 0xba, 0x98, 0xeb, +0x89, 0x09, 0xa8, 0xb3, 0xb7, 0x46, 0xa9, 0x31, 0x14, 0x83, 0x00, 0x02, 0xa8, 0xf4, 0x84, 0x20, +0xf0, 0x01, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0x9b, 0x0f, 0x84, 0x00, 0x14, 0x03, 0x00, 0x18, +0xed, 0x4c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xc0, +0x04, 0x00, 0x00, 0x18, 0x50, 0x73, 0x00, 0x20, 0x81, 0x01, 0x98, 0x38, 0x44, 0x10, 0x00, 0x80, +0x84, 0x41, 0x49, 0xfe, 0x9a, 0xf9, 0x04, 0x03, 0x00, 0x18, 0x5c, 0xf0, 0x00, 0x38, 0xe9, 0x04, +0x80, 0x06, 0x49, 0xff, 0xfe, 0xfb, 0xa0, 0xf6, 0xa0, 0xb7, 0x40, 0x01, 0xf4, 0x09, 0x94, 0x93, +0x40, 0x20, 0x08, 0x04, 0x94, 0xdb, 0x44, 0x00, 0xff, 0x00, 0x46, 0x10, 0x0f, 0xf0, 0x40, 0xa1, +0x80, 0x02, 0x40, 0x41, 0x00, 0x02, 0x40, 0x51, 0x84, 0x02, 0x40, 0x01, 0xe0, 0x08, 0x40, 0x91, +0x60, 0x08, 0x40, 0x11, 0x04, 0x02, 0x40, 0xa5, 0x20, 0x08, 0x40, 0x42, 0x20, 0x08, 0x92, 0xa8, +0x92, 0x28, 0x40, 0x05, 0x00, 0x04, 0x40, 0x44, 0x90, 0x04, 0x40, 0x00, 0x14, 0x04, 0x40, 0x42, +0x04, 0x04, 0x92, 0x58, 0x92, 0x78, 0x40, 0x31, 0x80, 0x04, 0x40, 0x42, 0x08, 0x04, 0x80, 0x3f, +0x84, 0x48, 0x50, 0x03, 0x80, 0x38, 0xb6, 0x9f, 0xf3, 0x81, 0x49, 0xfe, 0x9a, 0xa7, 0x80, 0x06, +0x49, 0xff, 0xfe, 0xc4, 0x84, 0x40, 0x38, 0x33, 0x08, 0x02, 0x44, 0x50, 0xff, 0x00, 0x47, 0xc0, +0x0f, 0xf0, 0x40, 0x41, 0xe0, 0x09, 0x40, 0x01, 0xe0, 0x08, 0x40, 0x11, 0x94, 0x02, 0x40, 0x02, +0x00, 0x04, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x31, 0xf0, 0x02, 0x40, 0x00, 0x04, 0x04, 0x92, 0x68, +0x40, 0x30, 0x0c, 0x04, 0x38, 0x33, 0x08, 0x0a, 0x44, 0x00, 0x00, 0x14, 0x9c, 0x94, 0x4c, 0x20, +0x7f, 0xe4, 0x80, 0x08, 0x80, 0x26, 0x49, 0xfe, 0x9a, 0x81, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe0, 0x50, 0x00, 0x00, 0x20, +0xf1, 0x81, 0x83, 0x82, 0xb6, 0x1f, 0x85, 0x00, 0xd5, 0x27, 0x04, 0x33, 0x80, 0x18, 0xf1, 0x01, +0xb4, 0x1f, 0x40, 0x50, 0xa0, 0x00, 0x99, 0x03, 0x40, 0x93, 0x0c, 0x00, 0x80, 0x25, 0x80, 0x04, +0x5c, 0xf4, 0x80, 0x40, 0xe8, 0x0a, 0x49, 0xfe, 0x9a, 0x61, 0x04, 0x23, 0x80, 0x18, 0x89, 0x06, +0x98, 0x96, 0x14, 0x23, 0x80, 0x18, 0xd5, 0x10, 0x52, 0x21, 0x80, 0x40, 0x49, 0xfe, 0x9a, 0x56, +0x44, 0x00, 0x00, 0x40, 0x04, 0x13, 0x80, 0x18, 0x14, 0x03, 0x80, 0x18, 0x9a, 0x41, 0x80, 0x07, +0x89, 0x01, 0x49, 0xff, 0xfe, 0x6b, 0x40, 0x6e, 0x20, 0x01, 0x80, 0x46, 0x4c, 0x8e, 0x7f, 0xd7, +0xa0, 0x3e, 0xa0, 0x7f, 0x80, 0x48, 0x84, 0x60, 0x99, 0x02, 0xe2, 0x82, 0x99, 0x4b, 0x88, 0xaf, +0xa9, 0x3e, 0xa9, 0x7f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x3e, 0x19, 0x0a, 0x38, 0x80, 0xc0, 0x44, 0x20, 0x00, 0x14, 0x49, 0xfe, 0x9a, 0x2f, 0x50, 0x03, +0x00, 0x20, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0x9a, 0x3e, 0x84, 0x00, 0x14, 0x03, +0x00, 0x18, 0x84, 0x20, 0x84, 0x00, 0xa8, 0x36, 0xa8, 0x77, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x94, 0x81, 0x20, 0x81, 0x01, 0x80, 0xe2, 0x84, 0x20, 0x44, 0x20, +0x00, 0x68, 0x80, 0x1f, 0x49, 0xfe, 0x9a, 0x28, 0x80, 0x1f, 0x49, 0xff, 0xff, 0xd9, 0x80, 0x1f, +0x80, 0x29, 0x80, 0x48, 0x49, 0xff, 0xff, 0x90, 0x80, 0x1f, 0x80, 0x27, 0x80, 0xdf, 0x49, 0xff, +0xff, 0x15, 0xec, 0x6c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x23, 0x42, 0x00, +0x04, 0x24, 0x84, 0x20, 0xd5, 0x08, 0x84, 0x40, 0x92, 0x00, 0x84, 0x67, 0x9c, 0x91, 0x4c, 0x21, +0xff, 0xfd, 0x9c, 0x49, 0xe2, 0x20, 0xe9, 0xf8, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x00, +0x04, 0x00, 0x00, 0x0e, 0x84, 0xa2, 0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd8, 0x05, 0x2e, 0x00, +0x2a, 0x99, 0x84, 0xa1, 0xd8, 0x19, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x53, 0x42, 0x21, +0x4c, 0x09, 0x42, 0x21, 0x50, 0x09, 0x14, 0x20, 0x80, 0x53, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x01, 0x30, 0xb4, 0x20, 0x44, 0x2c, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0xb4, 0x20, +0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x01, 0x48, 0xb4, 0x20, 0x81, 0x00, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0x84, 0xc0, +0xb4, 0x08, 0x40, 0x10, 0x30, 0x09, 0x42, 0x20, 0x70, 0x0b, 0x9d, 0xb1, 0x54, 0x10, 0x80, 0x03, +0x84, 0x0a, 0xc2, 0x03, 0x84, 0xa3, 0xd1, 0x06, 0x49, 0xff, 0xff, 0xb2, 0x44, 0x50, 0x00, 0x64, +0xde, 0xf0, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x48, 0xb4, 0x06, 0x46, 0x1f, 0xf8, 0x0f, +0x58, 0x10, 0x8f, 0xff, 0x40, 0x00, 0x04, 0x02, 0xb6, 0x06, 0x84, 0x01, 0x49, 0xff, 0xff, 0xa0, +0xb4, 0x26, 0x46, 0x2f, 0x0f, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x26, +0x84, 0x01, 0x49, 0xff, 0xff, 0x95, 0xb4, 0x06, 0x46, 0x30, 0xf0, 0x00, 0x40, 0x00, 0x0c, 0x04, +0xb6, 0x06, 0xb4, 0x06, 0x46, 0x20, 0x04, 0x01, 0x92, 0x0c, 0x40, 0x00, 0x30, 0x08, 0xb6, 0x06, +0x04, 0x31, 0x00, 0x81, 0x42, 0x31, 0x8c, 0x09, 0x14, 0x31, 0x00, 0x81, 0x46, 0x10, 0x04, 0x00, +0x04, 0x20, 0x80, 0x20, 0x80, 0x01, 0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x80, 0x20, 0x04, 0x10, +0x00, 0x19, 0x42, 0x10, 0xc8, 0x09, 0x14, 0x10, 0x00, 0x19, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x48, 0xb4, 0x20, 0x46, 0x2f, +0xf8, 0x0f, 0x46, 0x30, 0x05, 0xf0, 0x40, 0x10, 0x88, 0x02, 0x58, 0x31, 0x80, 0x02, 0x40, 0x10, +0x8c, 0x04, 0xb6, 0x20, 0x81, 0x00, 0x84, 0xc0, 0xb4, 0x08, 0x9d, 0xb1, 0x40, 0x10, 0x30, 0x09, +0x40, 0x20, 0x70, 0x09, 0x54, 0x10, 0x80, 0x03, 0x84, 0x0a, 0xca, 0x02, 0xc1, 0x06, 0x49, 0xff, +0xff, 0x4f, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf1, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x52, +0x92, 0x4c, 0x40, 0x21, 0x30, 0x08, 0x14, 0x20, 0x00, 0x52, 0x80, 0x20, 0x04, 0x20, 0x80, 0x20, +0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x80, 0x20, 0x04, 0x10, 0x00, 0x19, 0x42, 0x10, 0xc8, 0x08, +0x14, 0x10, 0x00, 0x19, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0x46, 0x70, 0x04, 0x10, 0x84, 0x21, 0x84, 0xc0, 0x04, 0x93, 0x82, 0x8c, 0x9d, 0xb1, 0x54, 0x84, +0x80, 0xff, 0x84, 0x01, 0x4e, 0x82, 0x00, 0x0a, 0x49, 0xff, 0xff, 0x22, 0x44, 0x00, 0x07, 0xd0, +0x84, 0x20, 0x4c, 0x60, 0x7f, 0xf3, 0xd5, 0x02, 0xc9, 0x05, 0x80, 0x29, 0x3e, 0x09, 0x0b, 0xc0, +0xd5, 0x15, 0x46, 0x60, 0x04, 0x10, 0x84, 0x21, 0x04, 0x73, 0x01, 0x0e, 0x8d, 0x01, 0x84, 0x01, +0xc7, 0x09, 0x49, 0xff, 0xff, 0x0d, 0x44, 0x00, 0x61, 0xa8, 0x84, 0x20, 0x4c, 0x80, 0x7f, 0xf6, +0xd5, 0x02, 0xc9, 0x07, 0x80, 0x27, 0x3e, 0x09, 0x0b, 0x9c, 0x49, 0xff, 0xcd, 0x2b, 0xd5, 0x19, +0x46, 0x60, 0x04, 0x11, 0x84, 0x21, 0x04, 0x23, 0x00, 0x80, 0x9d, 0xf9, 0x96, 0x94, 0x84, 0x01, +0xc2, 0x09, 0x49, 0xff, 0xfe, 0xf5, 0x44, 0x00, 0x13, 0x88, 0x84, 0x20, 0x4c, 0x70, 0x7f, 0xf5, +0xd5, 0x04, 0xc1, 0x03, 0x84, 0x01, 0xd5, 0x06, 0x3e, 0x09, 0x0b, 0xb0, 0x49, 0xff, 0xcd, 0x12, +0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, +0x04, 0x00, 0x58, 0x63, 0x00, 0x1c, 0xb4, 0x06, 0x42, 0x00, 0x60, 0x0b, 0xc8, 0x47, 0x50, 0x73, +0x01, 0x14, 0xb4, 0x07, 0x44, 0x21, 0x00, 0x01, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x07, 0x84, 0x01, +0x49, 0xfb, 0xda, 0xa8, 0xb4, 0x06, 0x92, 0x08, 0x40, 0x00, 0x20, 0x08, 0xb6, 0x06, 0x46, 0x80, +0x04, 0x00, 0xb4, 0x26, 0x58, 0x84, 0x01, 0x4c, 0x58, 0x10, 0x80, 0x30, 0xb6, 0x26, 0x84, 0x01, +0x49, 0xff, 0xfe, 0xbe, 0xb4, 0x28, 0x42, 0x10, 0xcc, 0x09, 0x42, 0x10, 0xd0, 0x09, 0xb6, 0x28, +0x84, 0x05, 0xb4, 0x27, 0x42, 0x10, 0xc4, 0x08, 0xb6, 0x27, 0x49, 0xfb, 0xda, 0x8b, 0xb4, 0x27, +0x42, 0x10, 0xc0, 0x09, 0xb6, 0x27, 0x84, 0x04, 0x49, 0xfb, 0xda, 0x84, 0xb4, 0x06, 0x42, 0x00, +0x60, 0x0b, 0xc0, 0x05, 0xb4, 0x06, 0x42, 0x00, 0x64, 0x0b, 0xc0, 0x0a, 0x3e, 0x09, 0x0b, 0xd8, +0x3e, 0x19, 0x0b, 0xe8, 0x44, 0x20, 0x02, 0x5c, 0x49, 0xff, 0xcc, 0xc4, 0xd5, 0x00, 0xb4, 0x08, +0x46, 0x10, 0x01, 0x80, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x08, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0x96, 0x48, 0xc8, 0x36, +0x84, 0x01, 0x4c, 0x10, 0x40, 0x17, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x26, +0x84, 0x0a, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x26, 0x49, 0xff, 0xfe, 0x7a, 0xb4, 0x26, 0x84, 0x0a, +0x58, 0x10, 0x80, 0x3a, 0xb6, 0x26, 0x49, 0xff, 0xfe, 0x73, 0xb4, 0x06, 0x84, 0x3b, 0xd5, 0x35, +0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x26, 0x84, 0x05, 0x58, 0x10, 0x80, 0x04, +0xb6, 0x26, 0x49, 0xff, 0xfe, 0x65, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x4c, 0x92, 0x24, +0x94, 0x4c, 0x14, 0x10, 0x01, 0x4c, 0x49, 0xff, 0xfe, 0x6b, 0xb4, 0x06, 0x44, 0x1f, 0xff, 0xc5, +0x58, 0x00, 0x00, 0x01, 0xb6, 0x06, 0xb4, 0x06, 0xd5, 0x43, 0x84, 0xa1, 0xd9, 0x24, 0x46, 0x60, +0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x26, 0x84, 0x0a, 0x58, 0x10, 0x81, 0x00, 0xb6, 0x26, +0x49, 0xff, 0xfe, 0x46, 0xb4, 0x26, 0x84, 0x0a, 0x58, 0x10, 0xba, 0x00, 0xb6, 0x26, 0x49, 0xff, +0xfe, 0x3f, 0xb4, 0x06, 0x44, 0x1f, 0xfb, 0xff, 0x40, 0x00, 0x04, 0x02, 0xb6, 0x06, 0x49, 0xff, +0xff, 0x55, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x4c, 0x58, 0x10, 0x80, 0x0f, 0x14, 0x10, +0x01, 0x4c, 0xd5, 0x21, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x26, 0x84, 0x05, +0x58, 0x10, 0x84, 0x00, 0xb6, 0x26, 0x49, 0xff, 0xfe, 0x23, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x01, 0x4c, 0x92, 0x24, 0x94, 0x4c, 0x14, 0x10, 0x01, 0x4c, 0x49, 0xff, 0xfe, 0x29, 0x92, 0x00, +0xb4, 0x06, 0x44, 0x1f, 0xc5, 0xff, 0x58, 0x00, 0x01, 0x00, 0xb6, 0x06, 0xb4, 0x06, 0x40, 0x00, +0x04, 0x02, 0xb6, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x96, 0x49, 0x81, 0x00, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xc2, 0xb4, 0xc0, +0x46, 0x70, 0x00, 0x80, 0x58, 0x73, 0x8b, 0xf0, 0x3e, 0x09, 0x0c, 0x00, 0x80, 0x26, 0xdd, 0x27, +0x44, 0x50, 0x00, 0x30, 0xde, 0x48, 0x84, 0x02, 0x84, 0x20, 0x84, 0x41, 0x49, 0x00, 0x12, 0x86, +0x3c, 0x2d, 0xfb, 0xa7, 0x84, 0x20, 0x84, 0x03, 0xdd, 0x22, 0x2e, 0x07, 0xf0, 0x4d, 0x84, 0xc1, +0x4c, 0x03, 0x00, 0xa6, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x40, 0x44, 0x00, 0x00, 0x1b, 0x80, 0x26, +0xdd, 0x23, 0x84, 0x00, 0x80, 0x20, 0x49, 0xff, 0xff, 0x4f, 0x80, 0x06, 0x84, 0x20, 0x49, 0xff, +0xff, 0x4b, 0x49, 0xff, 0xfe, 0x67, 0x84, 0x20, 0x3e, 0x61, 0x3a, 0x5e, 0x3c, 0x3d, 0xfb, 0xe5, +0x80, 0x41, 0x44, 0x00, 0x00, 0x1b, 0xdd, 0x23, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x40, 0x50, +0xc0, 0x09, 0x40, 0x52, 0xc0, 0x08, 0x46, 0x27, 0x66, 0x20, 0xd2, 0x09, 0xb4, 0x00, 0x46, 0x27, +0x63, 0x20, 0x40, 0x50, 0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, 0xda, 0x06, 0x84, 0x00, 0x84, 0x21, +0x80, 0x40, 0x49, 0x00, 0x3d, 0x9d, 0x2e, 0x11, 0x3a, 0x73, 0x84, 0x00, 0x49, 0xfb, 0xde, 0xa4, +0x48, 0x00, 0x00, 0x6e, 0x44, 0x50, 0x00, 0x31, 0xde, 0x44, 0x2e, 0x11, 0x3a, 0x73, 0x84, 0x00, +0x49, 0xfb, 0xde, 0x68, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x40, 0x44, 0x00, 0x00, 0x1b, 0x84, 0x21, +0xdd, 0x23, 0x49, 0xff, 0xfd, 0xd3, 0x84, 0x00, 0x84, 0x21, 0x49, 0xff, 0xff, 0x0d, 0x84, 0x01, +0x80, 0x20, 0x49, 0xff, 0xff, 0x09, 0x3c, 0x2d, 0xfb, 0xa7, 0x84, 0x21, 0x84, 0x03, 0xdd, 0x22, +0x84, 0x20, 0x3e, 0x11, 0x3a, 0x5e, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x20, 0x80, 0x41, 0x44, 0x00, +0x00, 0x1b, 0xdd, 0x23, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x40, 0x50, 0xc0, 0x09, 0x40, 0x52, +0xc0, 0x08, 0x46, 0x27, 0x66, 0x20, 0xd2, 0x09, 0xb4, 0x00, 0x46, 0x27, 0x63, 0x20, 0x40, 0x50, +0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, 0xda, 0x08, 0x49, 0x00, 0x3a, 0x58, 0x84, 0x00, 0x84, 0x22, +0x80, 0x40, 0x49, 0x00, 0x3d, 0x55, 0x84, 0x00, 0x49, 0x00, 0x07, 0xea, 0x92, 0x00, 0xd5, 0x27, +0x44, 0x50, 0x00, 0x34, 0xde, 0x15, 0x8d, 0x08, 0xb4, 0xc8, 0x3e, 0x29, 0x8e, 0x6c, 0x84, 0x61, +0x84, 0x85, 0x10, 0x31, 0x00, 0x0e, 0xaf, 0x14, 0xae, 0xd0, 0xa9, 0x92, 0x3e, 0x09, 0x0c, 0x18, +0x84, 0x25, 0xdd, 0x27, 0x80, 0x26, 0x3e, 0x09, 0x0c, 0x30, 0xdd, 0x27, 0xd5, 0x10, 0x44, 0x50, +0x00, 0x35, 0xde, 0x0d, 0x84, 0x20, 0x3e, 0x29, 0x8e, 0x6c, 0x10, 0x11, 0x00, 0x0e, 0x3e, 0x11, +0x3a, 0x60, 0xae, 0x50, 0xae, 0x54, 0x3e, 0x09, 0x0c, 0x40, 0xdd, 0x27, 0x84, 0x00, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x40, 0x44, 0x00, +0x00, 0x1b, 0x84, 0x21, 0xdd, 0x23, 0x84, 0x01, 0x80, 0x20, 0x49, 0xff, 0xfe, 0xa5, 0x92, 0x00, +0x84, 0x20, 0x3c, 0x3d, 0xfb, 0xe5, 0x44, 0x00, 0x00, 0x1b, 0x80, 0x41, 0xdd, 0x23, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x2e, 0x11, 0x3a, 0x73, 0x84, 0x00, +0x49, 0xfb, 0xdd, 0xe0, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x21, 0x44, 0x00, 0x00, 0x1b, 0x84, 0x40, +0xdd, 0x23, 0x49, 0xff, 0xfd, 0x4b, 0x84, 0x00, 0x84, 0x21, 0x49, 0xff, 0xfe, 0x85, 0x2e, 0x01, +0x8c, 0xbe, 0xc0, 0x04, 0x2e, 0x01, 0x8e, 0x6c, 0xc8, 0x08, 0x84, 0x01, 0x80, 0x20, 0x49, 0xff, +0xfe, 0x7b, 0x84, 0x20, 0x3e, 0x11, 0x8e, 0x7b, 0x3c, 0x2d, 0xfb, 0xa7, 0x84, 0x21, 0x84, 0x03, +0xdd, 0x22, 0x84, 0x20, 0x3e, 0x11, 0x3a, 0x5e, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x20, 0x44, 0x00, +0x00, 0x1b, 0x80, 0x41, 0xdd, 0x23, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3c, 0x3d, 0xfb, 0xe5, 0x84, 0x40, 0x44, 0x00, 0x00, 0x1b, +0x84, 0x21, 0xdd, 0x23, 0x3c, 0x2d, 0xfb, 0xa7, 0x84, 0x20, 0x84, 0x03, 0xdd, 0x22, 0x84, 0x00, +0x80, 0x20, 0x49, 0xff, 0xfe, 0x51, 0x84, 0x20, 0x84, 0x01, 0x49, 0xff, 0xfe, 0x4d, 0x84, 0xe1, +0x3e, 0x71, 0x8e, 0x7b, 0x49, 0xff, 0xfd, 0x66, 0x3e, 0x71, 0x3a, 0x5e, 0x3c, 0x3d, 0xfb, 0xe5, +0x84, 0x20, 0x80, 0x41, 0x44, 0x00, 0x00, 0x1b, 0xdd, 0x23, 0x2e, 0x11, 0x3a, 0x73, 0x84, 0x00, +0x49, 0xfb, 0xdd, 0xba, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xfc, 0x46, 0x60, 0x04, 0x11, 0x58, 0x63, 0x00, 0x04, 0xb4, 0x06, 0x42, 0x00, 0x0c, 0x09, +0xb6, 0x06, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0xd0, 0x42, 0x21, 0x50, 0x09, 0x14, 0x20, +0x80, 0xd0, 0x80, 0x01, 0x04, 0x10, 0x01, 0x82, 0x42, 0x10, 0x84, 0x09, 0x14, 0x10, 0x01, 0x82, +0x49, 0xff, 0xfd, 0x76, 0x84, 0xa1, 0xd8, 0x05, 0xb4, 0x06, 0x42, 0x00, 0x08, 0x09, 0xb6, 0x06, +0x46, 0x10, 0x04, 0x11, 0xa0, 0x89, 0x42, 0x21, 0x0c, 0x09, 0xa8, 0x89, 0x80, 0x01, 0x04, 0x30, +0x00, 0xd1, 0x46, 0x10, 0x00, 0x92, 0x58, 0x10, 0x8b, 0x00, 0x3c, 0x3e, 0x4e, 0xac, 0x46, 0x70, +0x04, 0x10, 0x14, 0x10, 0x00, 0xd1, 0x84, 0xc0, 0x46, 0x10, 0x04, 0x10, 0x04, 0x03, 0x81, 0x0c, +0x04, 0x10, 0x81, 0x0e, 0x40, 0x10, 0xa0, 0x08, 0x92, 0x38, 0xc1, 0x03, 0x84, 0x00, 0xd5, 0x04, +0x92, 0x10, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, 0x04, 0x10, 0x80, 0x22, 0x04, 0x31, 0x02, 0x8c, +0x04, 0x10, 0x82, 0x8d, 0x84, 0x40, 0x40, 0x01, 0x0c, 0x1b, 0xc9, 0x02, 0xc8, 0x1c, 0x49, 0x00, +0x02, 0x61, 0xd5, 0x10, 0x49, 0xff, 0xcc, 0x4c, 0x00, 0x30, 0x00, 0x14, 0x80, 0x40, 0x80, 0x20, +0x3e, 0x09, 0x83, 0x70, 0xc3, 0x02, 0xd5, 0x04, 0x80, 0x22, 0x3e, 0x09, 0x83, 0x80, 0x49, 0xff, +0xcc, 0x61, 0x3c, 0x3c, 0x62, 0xc6, 0x3e, 0x09, 0x8b, 0x10, 0xcb, 0xed, 0x9d, 0xb1, 0x44, 0x50, +0x07, 0xd0, 0xde, 0xcb, 0x46, 0x80, 0x04, 0x11, 0x46, 0x70, 0x04, 0x12, 0x84, 0xc0, 0x45, 0xc0, +0x27, 0x50, 0x04, 0xa4, 0x00, 0x80, 0x04, 0x93, 0x80, 0x4c, 0x54, 0xa5, 0x00, 0x03, 0x4e, 0xa3, +0x00, 0x04, 0x4e, 0x92, 0x00, 0x15, 0x5c, 0xf3, 0x01, 0x2c, 0xe9, 0x07, 0x3e, 0x09, 0x0c, 0x5c, +0x80, 0x2a, 0x80, 0x49, 0x49, 0xff, 0xca, 0x66, 0x84, 0x01, 0x9d, 0xb1, 0xdd, 0x3c, 0x4e, 0xa3, +0x00, 0x04, 0x4e, 0x92, 0x00, 0x05, 0x44, 0x50, 0x01, 0x2c, 0xde, 0xe4, 0x49, 0xff, 0xff, 0x42, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x49, 0xff, 0xff, 0x04, +0x49, 0x00, 0x1f, 0x76, 0x84, 0x02, 0x49, 0xfb, 0xd7, 0xfd, 0x84, 0x20, 0x2e, 0x01, 0x8c, 0xb0, +0x80, 0x41, 0x49, 0x00, 0x1f, 0x7f, 0x2e, 0x01, 0x8c, 0xb4, 0x46, 0x70, 0x04, 0x10, 0x54, 0x00, +0x00, 0x0f, 0x49, 0x00, 0x08, 0xdb, 0x46, 0x10, 0x04, 0x10, 0x46, 0x00, 0x60, 0x00, 0x84, 0xc0, +0x14, 0x60, 0x81, 0x43, 0x14, 0x03, 0x81, 0x41, 0x44, 0x00, 0x00, 0x10, 0x49, 0xfb, 0xd7, 0xe2, +0x46, 0x00, 0x04, 0x11, 0x84, 0x2c, 0x14, 0x63, 0x81, 0x41, 0xa8, 0x41, 0x3c, 0x1c, 0x4e, 0xac, +0x14, 0x10, 0x00, 0xd1, 0x3e, 0x61, 0x3a, 0x71, 0x3e, 0x61, 0x3a, 0x61, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x2e, 0x31, 0x8e, 0x6c, 0x84, 0xa1, +0xdb, 0x0a, 0x3e, 0x31, 0x3a, 0x60, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6d, 0x84, 0x40, 0x49, 0xfb, +0xfa, 0x1b, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x84, 0x61, 0x96, 0x48, 0x3e, 0x31, 0x3a, 0x61, 0x3e, 0x29, 0x3a, 0x72, 0xc9, 0x06, 0xae, 0x50, +0x84, 0x45, 0x3e, 0x21, 0x3a, 0x62, 0xd5, 0x0a, 0xa6, 0xd0, 0xe6, 0x7f, 0xe8, 0x17, 0x9c, 0xd9, +0x96, 0xd8, 0x9d, 0x1d, 0x3e, 0x41, 0x3a, 0x62, 0xae, 0xd0, 0x2e, 0x61, 0x3a, 0x71, 0xce, 0x0e, +0x2e, 0x11, 0x3a, 0x72, 0x84, 0x61, 0x3e, 0x31, 0x3a, 0x71, 0x9a, 0x41, 0x3e, 0x09, 0x89, 0xec, +0x49, 0xff, 0xca, 0xfc, 0x80, 0x06, 0x49, 0xff, 0xfe, 0xfb, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x2e, 0x01, 0x3a, 0x5d, 0x84, 0xa1, 0xd8, 0x09, 0x3e, 0x09, 0x0c, 0x90, +0x49, 0xff, 0xc9, 0xd8, 0x84, 0x00, 0x3e, 0x01, 0x3a, 0x5d, 0xd5, 0x11, 0x4e, 0x15, 0x00, 0x10, +0x5e, 0xf0, 0xae, 0xe0, 0xe9, 0x0c, 0x44, 0x01, 0x73, 0x18, 0x42, 0x10, 0x80, 0x01, 0x44, 0x00, +0x03, 0xe8, 0x40, 0x00, 0x80, 0x36, 0x84, 0x20, 0x49, 0xff, 0xff, 0xba, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x80, 0x20, 0xd5, 0x02, 0x9c, 0x49, 0x20, 0x20, 0x80, 0x00, 0xca, 0xfd, +0x9a, 0x08, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x01, 0xd4, 0x58, 0x10, 0x80, 0x01, +0x14, 0x10, 0x01, 0xd4, 0x3c, 0x0c, 0x4e, 0x89, 0x84, 0x21, 0xae, 0x41, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x10, 0x04, 0x50, 0xa0, 0x8d, 0x54, 0x21, 0x00, 0x20, 0xc2, 0xfd, 0xb6, 0x01, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x30, 0xb6, 0x1f, 0x84, 0x00, 0x10, 0x0f, +0x80, 0x04, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x44, 0x2f, 0x00, 0x00, 0x46, 0x37, 0x66, 0x20, +0x40, 0x50, 0x88, 0x02, 0xd3, 0x07, 0xb4, 0x00, 0x46, 0x17, 0x63, 0x20, 0x40, 0x50, 0x08, 0x02, +0xd9, 0x09, 0x84, 0x00, 0x50, 0x1f, 0x80, 0x04, 0x49, 0xfb, 0xe7, 0x0a, 0x84, 0x20, 0x3e, 0x10, +0x05, 0x0c, 0x84, 0x24, 0x80, 0x1f, 0x49, 0xff, 0xfd, 0x4b, 0x84, 0x0a, 0x49, 0xfb, 0xc6, 0xe2, +0x84, 0x07, 0x49, 0xfb, 0xc6, 0xdf, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x81, 0x06, 0x42, 0x21, +0x1c, 0x09, 0x14, 0x20, 0x81, 0x06, 0x80, 0x01, 0x04, 0x10, 0x00, 0x85, 0x42, 0x10, 0xb0, 0x09, +0x14, 0x10, 0x00, 0x85, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x02, 0x0c, 0xb4, 0xe6, 0x84, 0x0a, +0x58, 0x13, 0x80, 0x10, 0xb6, 0x26, 0x49, 0xfb, 0xd7, 0x0d, 0x42, 0x73, 0x90, 0x09, 0x84, 0x20, +0xb6, 0xe6, 0x3e, 0x17, 0xf0, 0x5a, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x8c, 0x84, 0x7e, +0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x00, 0x8c, 0x46, 0x10, 0x04, 0x05, 0x58, 0x10, 0x87, 0x00, +0xb4, 0x41, 0x44, 0x00, 0x13, 0x88, 0x58, 0x21, 0x00, 0x01, 0xb6, 0x41, 0xb4, 0x41, 0x40, 0x21, +0x0c, 0x02, 0xb6, 0x41, 0x49, 0xfe, 0x83, 0xea, 0xb4, 0x06, 0x58, 0x00, 0x02, 0x00, 0xb6, 0x06, +0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x3e, 0x68, +0x08, 0x28, 0x80, 0xe0, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, 0xd1, 0x4a, 0xb4, 0x46, 0xa0, 0x31, +0xa0, 0x72, 0x9a, 0x90, 0x40, 0x01, 0x04, 0x06, 0x44, 0x30, 0x04, 0x94, 0x84, 0x20, 0x3e, 0x29, +0x0c, 0xb0, 0x49, 0xfb, 0xe3, 0xc5, 0xb4, 0x46, 0xa0, 0x72, 0xf0, 0x01, 0x9e, 0x49, 0x40, 0x10, +0x88, 0x02, 0x9c, 0x4a, 0x94, 0x4a, 0x98, 0x71, 0xa9, 0xc9, 0xb4, 0x26, 0x9c, 0x49, 0xb6, 0x26, +0x49, 0xfb, 0xd1, 0x44, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x86, 0x84, 0xa1, 0x96, 0x00, 0xd8, 0x30, +0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x34, 0xb4, 0x20, 0x84, 0xa3, 0x54, 0x10, 0x80, 0x03, +0xd9, 0x20, 0xb4, 0x40, 0x92, 0x42, 0x94, 0x92, 0xb6, 0x40, 0x50, 0x10, 0x7e, 0x30, 0xb4, 0x41, +0x46, 0x30, 0x06, 0x00, 0x40, 0x21, 0x0c, 0x04, 0xb6, 0x41, 0xb4, 0x41, 0x42, 0x21, 0x54, 0x09, +0x42, 0x21, 0x58, 0x09, 0xb6, 0x41, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x04, 0x00, 0xb4, 0x20, +0x84, 0x53, 0x58, 0x10, 0x80, 0x0c, 0xb6, 0x20, 0xb4, 0x20, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, +0x84, 0x02, 0x44, 0x10, 0x00, 0x71, 0x84, 0x40, 0x49, 0xfb, 0xf8, 0xde, 0x92, 0x00, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0x86, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, 0x14, 0x10, 0x00, 0x86, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x2c, +0x4e, 0x89, 0x84, 0x20, 0xae, 0x51, 0x84, 0x21, 0x3c, 0x0c, 0x4e, 0x89, 0xae, 0x44, 0x2e, 0x10, +0xd0, 0x21, 0x84, 0x00, 0x49, 0xfb, 0xdb, 0x4e, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xd4, +0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x81, 0xd4, 0x84, 0x03, 0x84, 0x20, 0x84, 0x41, 0x49, 0xfe, +0x88, 0x77, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x00, 0x04, 0x00, 0x04, 0x60, 0x00, 0x97, 0x84, 0xa1, 0xde, 0x09, 0x3c, 0x1d, 0xfb, 0x99, +0xc1, 0x0c, 0x04, 0x00, 0x00, 0x97, 0x96, 0x04, 0xdd, 0x21, 0xd5, 0x07, 0x54, 0x03, 0x20, 0x00, +0xc0, 0x04, 0x84, 0x00, 0x49, 0xff, 0xfe, 0x70, 0x3c, 0x0c, 0x4e, 0x89, 0xc0, 0x0e, 0xa6, 0x40, +0xc1, 0x0c, 0xa6, 0x42, 0xc1, 0x0a, 0xa6, 0x43, 0x40, 0x13, 0x04, 0x0d, 0x96, 0x4c, 0xc1, 0x05, +0xa6, 0x01, 0xc0, 0x03, 0x49, 0xff, 0xff, 0xba, 0x46, 0x00, 0x04, 0x00, 0x14, 0x60, 0x00, 0x97, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x50, 0x0f, +0x80, 0x04, 0x49, 0xfb, 0xd0, 0x8d, 0x3c, 0x1c, 0x62, 0xc3, 0x54, 0x70, 0x80, 0x02, 0xc7, 0x04, +0x42, 0x10, 0x84, 0x09, 0x84, 0xe1, 0xf0, 0x01, 0x3e, 0x69, 0x8a, 0x58, 0x14, 0x13, 0x00, 0x2d, +0x49, 0xfb, 0xd0, 0x94, 0xc7, 0x04, 0x80, 0x06, 0x49, 0xff, 0xc4, 0x9a, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, +0xd0, 0x6f, 0x3c, 0x1c, 0x62, 0xc3, 0x97, 0xcc, 0xc7, 0x04, 0x42, 0x10, 0x80, 0x09, 0x84, 0xe1, +0xf0, 0x01, 0x3e, 0x69, 0x8a, 0x58, 0x14, 0x13, 0x00, 0x2d, 0x49, 0xfb, 0xd0, 0x77, 0xc7, 0x05, +0x80, 0x06, 0x49, 0xff, 0xc4, 0xbf, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x3e, 0x69, 0x8a, 0x58, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, +0xd0, 0x4f, 0x04, 0x13, 0x00, 0x2d, 0xf0, 0x01, 0xb6, 0x3f, 0x84, 0x20, 0x14, 0x13, 0x00, 0x2d, +0x49, 0xfb, 0xd0, 0x5c, 0xb4, 0x1f, 0x96, 0x04, 0xc0, 0x04, 0x80, 0x06, 0x49, 0xff, 0xc4, 0xa2, +0xb4, 0x1f, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x05, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, 0xc4, 0x58, +0xb4, 0x1f, 0x40, 0x00, 0x3c, 0x08, 0x92, 0x1f, 0xc0, 0x05, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, +0xc6, 0x85, 0xb4, 0x1f, 0x40, 0x00, 0x38, 0x08, 0x92, 0x1f, 0xc0, 0x05, 0x3e, 0x09, 0x8a, 0x58, +0x49, 0xff, 0xc5, 0x7c, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x84, 0x00, 0xd5, 0x0a, +0x92, 0x00, 0x84, 0x47, 0x9c, 0x49, 0x4c, 0x11, 0x7f, 0xfd, 0x9c, 0x01, 0x84, 0x23, 0x4c, 0x00, +0x80, 0x04, 0x84, 0x20, 0xd5, 0xf6, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x54, 0xa0, 0x00, 0xff, +0x3e, 0x09, 0x8e, 0x10, 0x49, 0xff, 0xc8, 0x3c, 0x46, 0x70, 0x04, 0x11, 0x3e, 0x09, 0x8e, 0x2c, +0x49, 0xff, 0xc8, 0x36, 0x84, 0xc0, 0x04, 0x03, 0x80, 0x80, 0x9d, 0xb1, 0x96, 0x04, 0xc0, 0x06, +0x49, 0xff, 0xff, 0xde, 0x44, 0x50, 0x01, 0x06, 0xde, 0xf7, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, +0x80, 0x04, 0xb4, 0x41, 0x42, 0x21, 0x08, 0x09, 0xb6, 0x41, 0xb4, 0x41, 0x46, 0x80, 0x04, 0x10, +0x42, 0x21, 0x0c, 0x09, 0x80, 0xc8, 0xb6, 0x41, 0x84, 0xe0, 0x84, 0x01, 0x04, 0x24, 0x01, 0x0c, +0x4c, 0xa0, 0x40, 0x07, 0x46, 0x0f, 0xf0, 0x00, 0x04, 0x13, 0x02, 0x8d, 0xd5, 0x05, 0x46, 0x00, +0x0f, 0xf0, 0x04, 0x13, 0x02, 0x8d, 0x40, 0x10, 0x80, 0x02, 0x9d, 0xf9, 0x92, 0x50, 0x3e, 0x09, +0x8a, 0x58, 0xc9, 0x02, 0xc2, 0x07, 0x49, 0xff, 0xc4, 0x71, 0x44, 0x50, 0x01, 0x06, 0xdf, 0xe6, +0xd5, 0x27, 0x85, 0x21, 0x46, 0x70, 0x04, 0x11, 0x84, 0xc0, 0x04, 0x83, 0x80, 0x80, 0x9d, 0xb1, +0x54, 0x04, 0x00, 0x02, 0xc0, 0x07, 0x49, 0xff, 0xff, 0xa3, 0x44, 0x50, 0x01, 0x06, 0xde, 0xf6, +0xd5, 0x31, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, 0xc5, 0xf5, 0x49, 0xff, 0xcc, 0xa7, 0x3e, 0x09, +0x8e, 0x2c, 0x44, 0x10, 0x03, 0xe8, 0x49, 0xff, 0xc8, 0xa9, 0x3e, 0x09, 0x8e, 0x10, 0x44, 0x10, +0x01, 0x5e, 0x49, 0xff, 0xc8, 0xa3, 0x80, 0x09, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x8c, 0x3e, 0x08, 0xf7, 0xb4, 0x49, 0xff, 0xc7, 0x83, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x8d, 0x3e, 0x08, 0xf7, 0xc8, 0x49, 0xff, 0xc7, 0x7b, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x01, 0x0e, 0x3e, 0x08, 0xf7, 0xec, 0x49, 0xff, 0xc7, 0x73, 0x85, 0x20, +0xd5, 0xc2, 0x80, 0x28, 0x3e, 0x08, 0xf8, 0x00, 0x49, 0xff, 0xc7, 0x6c, 0x92, 0x00, 0xd5, 0xca, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x3e, 0x69, 0x8a, 0x58, 0x04, 0x73, 0x00, 0x2d, 0x44, 0x02, +0x00, 0x00, 0x46, 0x50, 0x04, 0x10, 0x80, 0x85, 0x80, 0x64, 0x80, 0x43, 0x80, 0x22, 0x40, 0x73, +0x80, 0x02, 0x04, 0x52, 0x82, 0x6f, 0x04, 0x42, 0x02, 0x6e, 0x04, 0x01, 0x82, 0x6b, 0x04, 0x01, +0x02, 0x6a, 0x04, 0x00, 0x82, 0x71, 0xcf, 0x1f, 0xdc, 0x1e, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x0e, +0x3e, 0x09, 0x0c, 0xcc, 0x49, 0xff, 0xc7, 0x46, 0x80, 0x07, 0x49, 0xff, 0xff, 0x4f, 0xc8, 0x13, +0x3e, 0x09, 0x0c, 0xf0, 0x49, 0xff, 0xc7, 0x3e, 0xd5, 0x0e, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, +0xcf, 0x57, 0x04, 0x13, 0x00, 0x2d, 0xf0, 0x01, 0x42, 0x10, 0xc4, 0x08, 0x14, 0x13, 0x00, 0x2d, +0x49, 0xfb, 0xcf, 0x64, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x84, 0x23, 0x42, 0x00, +0x04, 0x24, 0x84, 0x20, 0xd5, 0x08, 0x84, 0x40, 0x92, 0x00, 0x84, 0x67, 0x9c, 0x91, 0x4c, 0x21, +0xff, 0xfd, 0x9c, 0x49, 0xe2, 0x20, 0xe9, 0xf8, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x04, 0x54, 0x10, +0x8f, 0xff, 0x58, 0x10, 0x90, 0x00, 0x40, 0x00, 0x40, 0x08, 0x46, 0x40, 0x04, 0x10, 0x80, 0x64, +0x40, 0x00, 0x80, 0x04, 0x14, 0x22, 0x01, 0x49, 0x14, 0x01, 0x81, 0x4a, 0x84, 0x20, 0x04, 0x01, +0x81, 0x4a, 0x9c, 0x49, 0x42, 0x00, 0x34, 0x0b, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x64, 0x4c, 0x10, +0x7f, 0xf8, 0x84, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x3c, 0x6c, 0x4e, 0xb4, +0x3e, 0x09, 0x7f, 0xd0, 0x50, 0x83, 0x7f, 0xff, 0x40, 0x74, 0x08, 0x08, 0x40, 0x93, 0x80, 0x00, +0x3e, 0x09, 0x7f, 0x30, 0x89, 0x00, 0x3e, 0x09, 0x7f, 0x50, 0x99, 0xf8, 0x08, 0x04, 0x7f, 0xff, +0x0c, 0x13, 0xff, 0xff, 0x0c, 0x24, 0xff, 0xff, 0x9f, 0xb1, 0x49, 0xff, 0xff, 0xc9, 0x4e, 0x66, +0xff, 0xf7, 0x3c, 0x6e, 0x4e, 0xb4, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x84, 0x21, 0x80, 0x40, +0x44, 0x00, 0x02, 0x58, 0x40, 0x31, 0x00, 0x97, 0x9c, 0x49, 0x96, 0x48, 0x98, 0x18, 0x84, 0x6b, +0x92, 0x01, 0x4c, 0x11, 0xff, 0xf9, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x10, +0x04, 0x11, 0x84, 0x48, 0x96, 0x00, 0x04, 0x80, 0x80, 0x01, 0xa8, 0x89, 0xe6, 0x0f, 0xe8, 0x0a, +0x46, 0x00, 0x04, 0x12, 0x46, 0x12, 0x02, 0x02, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x80, 0x20, +0xd5, 0x71, 0x2e, 0x11, 0x3a, 0x75, 0xc9, 0x2a, 0x5c, 0xf0, 0x00, 0x34, 0xe8, 0x0a, 0x46, 0x00, +0x04, 0x12, 0x46, 0x16, 0x45, 0x03, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, 0xd5, 0x62, +0x5c, 0xf0, 0x00, 0x45, 0xe8, 0x02, 0xd5, 0x4d, 0x5c, 0xf0, 0x00, 0x75, 0xe8, 0x02, 0xd5, 0x49, +0x5c, 0xf0, 0x00, 0xae, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0xf3, 0xf3, 0x58, 0x00, +0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, 0xd5, 0x4e, 0x46, 0x00, 0x04, 0x12, 0x46, 0x16, 0x46, 0x43, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, 0xd5, 0x45, 0x5c, 0xf0, 0x00, 0x34, 0xe8, 0x0a, +0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0xf3, 0xf3, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x83, 0x33, +0xd5, 0x39, 0x5c, 0xf0, 0x00, 0x45, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0xf3, 0xf2, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x88, 0x33, 0xd5, 0x2d, 0x5c, 0xf0, 0x00, 0x75, 0xe8, 0x0a, +0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0x33, 0x32, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x88, 0x33, +0xd5, 0x21, 0x5c, 0xf0, 0x00, 0xae, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0x33, 0x32, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x80, 0x28, 0xd5, 0x15, 0x5c, 0xf0, 0x00, 0xc5, 0xe8, 0x0a, +0x46, 0x00, 0x04, 0x12, 0x46, 0x15, 0x05, 0x03, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, +0xd5, 0x09, 0x46, 0x00, 0x04, 0x12, 0x46, 0x15, 0x05, 0x03, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, +0x83, 0x33, 0xb6, 0x20, 0x46, 0x60, 0x04, 0x12, 0x80, 0x26, 0x84, 0x01, 0x44, 0x20, 0xff, 0xff, +0x04, 0x90, 0x80, 0xc2, 0x14, 0x20, 0x80, 0xc2, 0xa8, 0x34, 0x49, 0xff, 0xff, 0x11, 0x84, 0x40, +0x46, 0x10, 0x04, 0x12, 0xa8, 0xb4, 0x80, 0x01, 0x44, 0x20, 0x33, 0xf0, 0x14, 0x20, 0x83, 0x2f, +0x44, 0x10, 0x00, 0x4c, 0x14, 0x10, 0x03, 0x2e, 0x3c, 0x0c, 0x4e, 0x8a, 0xc8, 0x04, 0x44, 0x00, +0x07, 0xd0, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x14, 0x49, 0xff, 0xfe, 0xfa, 0x46, 0x00, 0x04, 0x12, +0x44, 0x10, 0x33, 0xe0, 0x14, 0x10, 0x03, 0x2f, 0x3c, 0x0c, 0x4e, 0x8a, 0xc8, 0x04, 0x44, 0x00, +0x07, 0xd0, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x14, 0x49, 0xff, 0xfe, 0xea, 0x46, 0x10, 0x04, 0x12, +0x46, 0x00, 0x04, 0x11, 0x14, 0x90, 0x80, 0xc2, 0x14, 0x80, 0x00, 0x01, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x96, 0x01, 0x94, 0x04, 0x44, 0x10, 0x7f, 0xff, 0xe2, 0x20, 0xe8, 0x05, +0x84, 0x3c, 0x44, 0x20, 0xff, 0xff, 0xd5, 0x11, 0x80, 0x41, 0x84, 0x3c, 0x9e, 0x49, 0x96, 0x4b, +0x44, 0x5f, 0xff, 0xeb, 0x98, 0x00, 0xd1, 0x30, 0xe2, 0x40, 0xe8, 0xf9, 0xd5, 0x09, 0x96, 0x5b, +0x44, 0x50, 0x00, 0x15, 0xd1, 0x29, 0x92, 0x01, 0x9c, 0xc9, 0xe2, 0x40, 0xe9, 0xf9, 0x44, 0x30, +0xb8, 0x00, 0x40, 0x20, 0x0c, 0x09, 0xe2, 0x60, 0xe9, 0x07, 0x44, 0x4f, 0x6a, 0x00, 0x98, 0xc4, +0x98, 0x9a, 0x92, 0x04, 0xd5, 0x06, 0x9a, 0x82, 0x92, 0x06, 0x9a, 0x10, 0x44, 0x2f, 0xa6, 0x00, +0x98, 0x02, 0x84, 0x60, 0x8c, 0x2f, 0x42, 0x00, 0x0c, 0x00, 0x40, 0x10, 0xbc, 0x08, 0x98, 0x41, +0x98, 0x89, 0x94, 0x0a, 0x98, 0x10, 0x40, 0x20, 0x98, 0x0a, 0x98, 0x02, 0x90, 0x27, 0x98, 0x01, +0x90, 0x0a, 0x96, 0x03, 0xd5, 0x03, 0x44, 0x0f, 0xd8, 0xf0, 0xdd, 0x9e, 0x3e, 0x09, 0x30, 0x1c, +0xb4, 0x20, 0xa0, 0x81, 0x8c, 0x08, 0xb6, 0x41, 0x3e, 0x59, 0x30, 0xdc, 0xd8, 0xfa, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0x3c, 0x3e, 0x09, 0x2d, 0xcc, 0xa0, 0x47, 0xb4, 0xc0, 0xa1, 0xc1, 0xa1, 0x02, +0xa1, 0x43, 0xa0, 0x84, 0xa0, 0xc5, 0xa0, 0x06, 0xb6, 0xe6, 0xb6, 0xa4, 0xb6, 0x62, 0xb6, 0x20, +0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x00, 0x96, 0x48, 0x96, 0x90, 0xe6, 0x0f, +0xe8, 0x1c, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x0e, 0x40, 0x21, 0x04, 0x03, 0x3e, 0x39, 0x37, 0xf8, +0x3e, 0x49, 0x37, 0xb0, 0x40, 0x02, 0x08, 0x1a, 0x40, 0x01, 0x88, 0x1b, 0x84, 0x29, 0xd5, 0x39, +0x3e, 0x19, 0x38, 0x78, 0x56, 0x21, 0x00, 0x01, 0x3e, 0x39, 0x38, 0x40, 0x40, 0x01, 0x88, 0x1a, +0x40, 0x00, 0x88, 0x1b, 0x84, 0x27, 0xd5, 0x2d, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x15, 0x84, 0xa2, +0xda, 0x05, 0x3e, 0x09, 0x38, 0xb0, 0x84, 0x23, 0xd5, 0x24, 0x84, 0x66, 0x56, 0x21, 0x00, 0x01, +0x84, 0x07, 0x40, 0x11, 0x88, 0x1a, 0x40, 0x10, 0x08, 0x1b, 0x3e, 0x49, 0x38, 0xc8, 0x3e, 0x39, +0x38, 0xf8, 0xd5, 0x13, 0x84, 0xa2, 0xda, 0x05, 0x3e, 0x09, 0x39, 0x30, 0x84, 0x21, 0xd5, 0x11, +0x84, 0x64, 0x56, 0x21, 0x00, 0x01, 0x84, 0x05, 0x40, 0x11, 0x88, 0x1a, 0x40, 0x10, 0x08, 0x1b, +0x3e, 0x49, 0x39, 0x38, 0x3e, 0x39, 0x39, 0x58, 0x40, 0x02, 0x08, 0x1a, 0x40, 0x01, 0x88, 0x1b, +0x84, 0x40, 0xb4, 0x60, 0xa1, 0x01, 0x9c, 0x91, 0xb6, 0x83, 0x8c, 0x08, 0xe0, 0x41, 0xe9, 0xfa, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, 0x46, 0x00, 0x04, 0x11, 0x46, 0x18, 0x02, 0x50, +0x46, 0x60, 0x04, 0x12, 0x46, 0x50, 0x07, 0x77, 0x80, 0x86, 0x84, 0x48, 0xa1, 0xc1, 0xa8, 0x81, +0x58, 0x52, 0x87, 0x77, 0x84, 0x00, 0x48, 0x00, 0x00, 0xaf, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x92, +0xe6, 0x06, 0x4e, 0xf3, 0x00, 0x92, 0xe6, 0x0b, 0x4e, 0xf3, 0x00, 0x92, 0xe6, 0x11, 0x4e, 0xf3, +0x00, 0x92, 0xe6, 0x17, 0x4e, 0xf3, 0x00, 0x92, 0xe6, 0x1e, 0x4e, 0xf3, 0x00, 0x92, 0x5c, 0xf0, +0x00, 0x28, 0x4e, 0xf3, 0x00, 0x91, 0x5c, 0xf0, 0x00, 0x3a, 0x4e, 0xf3, 0x00, 0x90, 0x5c, 0xf0, +0x00, 0x46, 0x4e, 0xf3, 0x00, 0x8f, 0x5c, 0xf0, 0x00, 0x58, 0x4e, 0xf3, 0x00, 0x88, 0x5c, 0xf0, +0x00, 0x62, 0x4e, 0xf3, 0x00, 0x81, 0x5c, 0xf0, 0x00, 0x69, 0xe9, 0x7a, 0x5c, 0xf0, 0x00, 0x6f, +0xe9, 0x74, 0x5c, 0xf0, 0x00, 0x75, 0xe9, 0x6e, 0x5c, 0xf0, 0x00, 0x7a, 0xe9, 0x68, 0x5c, 0xf0, +0x00, 0x7e, 0xe9, 0x62, 0x5c, 0xf0, 0x00, 0x81, 0xe9, 0x5c, 0x5c, 0xf0, 0x00, 0x83, 0xe9, 0x5c, +0x5c, 0xf0, 0x00, 0x88, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0x8a, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0x8e, +0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0x92, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0x9a, 0xe9, 0x5f, 0x5c, 0xf0, +0x00, 0xa0, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0xa8, 0xe9, 0x59, 0x5c, 0xf0, 0x00, 0xac, 0xe9, 0x53, +0x5c, 0xf0, 0x00, 0xb0, 0xe9, 0x4d, 0x5c, 0xf0, 0x00, 0xb2, 0xe9, 0x47, 0x5c, 0xf0, 0x00, 0xb5, +0xe9, 0x41, 0x5c, 0xf0, 0x00, 0xb7, 0xe9, 0x3b, 0x5c, 0xf0, 0x00, 0xb9, 0xe9, 0x35, 0x5c, 0xf0, +0x00, 0xbb, 0xe9, 0x2f, 0x44, 0x10, 0x00, 0xbb, 0x4c, 0x00, 0x80, 0x2f, 0x9c, 0x49, 0x4c, 0x00, +0x80, 0x2f, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x2f, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x2f, 0x9c, 0x49, +0x4c, 0x00, 0x80, 0x2f, 0x5c, 0xf0, 0x00, 0xc2, 0xe9, 0x2e, 0x5c, 0xf0, 0x00, 0xc6, 0xe9, 0x2e, +0x5c, 0xf0, 0x00, 0xca, 0xe9, 0x2e, 0x5c, 0xf0, 0x00, 0xce, 0xe9, 0x28, 0x5c, 0xf0, 0x00, 0xd0, +0xe9, 0x22, 0x8c, 0x31, 0x4c, 0x00, 0x80, 0x1d, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x17, 0x9c, 0x49, +0x4c, 0x00, 0x80, 0x11, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x0b, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x05, +0x46, 0x18, 0x02, 0x50, 0xd5, 0x18, 0x46, 0x18, 0x02, 0x40, 0xd5, 0x15, 0x46, 0x18, 0x02, 0x30, +0xd5, 0x12, 0x46, 0x18, 0x02, 0x20, 0xd5, 0x0f, 0x46, 0x18, 0x02, 0x10, 0xd5, 0x0c, 0x46, 0x18, +0x02, 0x00, 0xd5, 0x09, 0x46, 0x18, 0x01, 0xf0, 0xd5, 0x06, 0x46, 0x18, 0x01, 0xe0, 0xd5, 0x03, +0x46, 0x18, 0x01, 0xd0, 0x40, 0x10, 0x04, 0x04, 0x80, 0x44, 0x14, 0x53, 0x01, 0x8c, 0x9c, 0x01, +0x14, 0x12, 0x01, 0x8d, 0x44, 0x10, 0x00, 0xd6, 0x80, 0x65, 0x4c, 0x00, 0xff, 0x48, 0x46, 0x00, +0x04, 0x11, 0x9e, 0x5c, 0x14, 0x31, 0x01, 0x8c, 0x14, 0x11, 0x01, 0x8c, 0xa9, 0xc1, 0x3a, 0x6f, +0x9c, 0x04, 0xdd, 0x9e, 0x96, 0x00, 0xe6, 0x0f, 0xe8, 0x30, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x01, 0xbc, 0xb4, 0x40, 0x46, 0x10, 0x04, 0x00, 0x58, 0x21, 0x00, 0x10, 0xb6, 0x40, 0x04, 0x30, +0x80, 0x49, 0x94, 0xdc, 0x92, 0x64, 0x42, 0x31, 0xf0, 0x08, 0x14, 0x30, 0x80, 0x49, 0x80, 0x41, +0x04, 0x31, 0x00, 0x4a, 0x46, 0x4f, 0xff, 0x00, 0x58, 0x42, 0x0f, 0xf0, 0x40, 0x31, 0x90, 0x02, +0x44, 0x41, 0x10, 0x01, 0x40, 0x31, 0x90, 0x04, 0x14, 0x31, 0x00, 0x4a, 0x04, 0x20, 0x80, 0x6e, +0x46, 0x3f, 0xfe, 0x67, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x80, 0x6e, +0xb4, 0x20, 0x40, 0x10, 0x8c, 0x02, 0xd5, 0x23, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x6f, +0x42, 0x21, 0x10, 0x09, 0x14, 0x20, 0x00, 0x6f, 0x80, 0x20, 0x04, 0x20, 0x80, 0x49, 0x46, 0x47, +0x00, 0x00, 0x94, 0x94, 0x92, 0x44, 0x40, 0x21, 0x10, 0x04, 0x14, 0x20, 0x80, 0x49, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x01, 0x28, 0xb4, 0x20, 0x46, 0x2f, 0xff, 0x00, 0x58, 0x21, 0x0f, 0xf0, +0x40, 0x10, 0x88, 0x02, 0x44, 0x37, 0x70, 0x07, 0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, 0xdd, 0x9e, +0x46, 0x00, 0x04, 0x12, 0x04, 0x00, 0x00, 0xc8, 0x84, 0x22, 0x92, 0x06, 0x54, 0x00, 0x00, 0x03, +0x4c, 0x00, 0x80, 0x11, 0x84, 0xa3, 0xd0, 0x14, 0x84, 0xa1, 0xd0, 0x06, 0x46, 0x00, 0x04, 0x12, +0x58, 0x00, 0x03, 0x18, 0xd5, 0x05, 0x46, 0x00, 0x04, 0x12, 0x58, 0x00, 0x03, 0x10, 0xb4, 0x00, +0xd5, 0x0c, 0x46, 0x00, 0x04, 0x12, 0x04, 0x00, 0x00, 0xc4, 0x92, 0x08, 0xd5, 0x06, 0x46, 0x00, +0x04, 0x12, 0x04, 0x00, 0x00, 0xc4, 0x92, 0x10, 0x46, 0x10, 0x04, 0x12, 0x04, 0x10, 0x80, 0xc8, +0x54, 0x00, 0x00, 0x3f, 0x92, 0x29, 0x54, 0x10, 0x80, 0x3f, 0x98, 0x01, 0x5c, 0xf0, 0x00, 0x41, +0xe9, 0x14, 0x50, 0x00, 0x7f, 0xc0, 0x84, 0x23, 0x40, 0x00, 0x04, 0x37, 0xe6, 0x02, 0xe9, 0x0d, +0x84, 0x21, 0x9e, 0x02, 0x40, 0x00, 0x80, 0x0c, 0x5c, 0x30, 0x00, 0x0f, 0x84, 0x4e, 0x40, 0x10, +0x0c, 0x1b, 0x40, 0x11, 0x0c, 0x1a, 0xd5, 0x02, 0x84, 0x21, 0x46, 0x00, 0x04, 0x12, 0x04, 0x30, +0x00, 0xc2, 0x92, 0x70, 0x40, 0x31, 0xc0, 0x08, 0x40, 0x20, 0xa0, 0x08, 0x40, 0x10, 0x8c, 0x04, +0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0xc2, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0x46, 0x70, 0x04, 0x11, 0x84, 0xc0, 0x04, 0x13, 0x80, 0x80, 0x9d, 0xb1, 0x96, 0x4c, 0x84, 0x01, +0xc1, 0x06, 0x49, 0xff, 0xfc, 0x95, 0x44, 0x50, 0x75, 0x30, 0xde, 0xf6, 0x46, 0x70, 0x04, 0x12, +0x84, 0xc0, 0x04, 0x13, 0x80, 0x4c, 0x9d, 0xb1, 0x84, 0x01, 0xc1, 0x06, 0x49, 0xff, 0xfc, 0x88, +0x44, 0x50, 0x75, 0x30, 0xde, 0xf7, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xfc, 0x2e, 0x21, 0x8e, 0x7c, 0x84, 0x61, 0x96, 0x00, 0x4c, 0x21, 0xc0, 0x07, 0x2e, 0x51, +0x8e, 0x7d, 0xd8, 0x03, 0x85, 0x00, 0xd5, 0x13, 0x2e, 0x81, 0x8f, 0x5c, 0x84, 0xa1, 0x4c, 0x82, +0xc0, 0x05, 0x2e, 0x51, 0x8f, 0x5d, 0xd0, 0x0b, 0x2e, 0x21, 0x90, 0x3c, 0x84, 0xa1, 0x4c, 0x22, +0xc0, 0xca, 0x4e, 0x03, 0x00, 0xc8, 0x3e, 0x01, 0x90, 0x3c, 0x85, 0x02, 0x46, 0x00, 0x04, 0x12, +0x44, 0x90, 0x00, 0xe0, 0x42, 0x94, 0x24, 0x24, 0x44, 0x11, 0x00, 0x00, 0x04, 0xa0, 0x01, 0xc0, +0x14, 0x10, 0x01, 0xc0, 0x3e, 0x09, 0x8e, 0x7c, 0x40, 0x64, 0x80, 0x00, 0x50, 0x63, 0x00, 0x34, +0xb4, 0x46, 0x46, 0x70, 0x00, 0x87, 0x58, 0x73, 0x8d, 0xbc, 0x44, 0x10, 0x02, 0x4c, 0x84, 0x00, +0xdd, 0x27, 0xa0, 0xb1, 0x44, 0x10, 0x02, 0x50, 0x84, 0x00, 0xdd, 0x27, 0xa0, 0xb2, 0x44, 0x10, +0x02, 0x64, 0x84, 0x00, 0xdd, 0x27, 0xa0, 0xb3, 0x44, 0x10, 0x02, 0x78, 0x84, 0x00, 0xdd, 0x27, +0xa0, 0xb4, 0x44, 0x10, 0x02, 0x4c, 0x84, 0x01, 0xdd, 0x27, 0xa0, 0xb5, 0x44, 0x10, 0x02, 0x50, +0x84, 0x01, 0xdd, 0x27, 0xa0, 0xb6, 0x44, 0x10, 0x02, 0x64, 0x84, 0x01, 0xdd, 0x27, 0xa0, 0xb7, +0x44, 0x10, 0x02, 0x78, 0x84, 0x01, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x01, 0xdd, +0x46, 0x3f, 0xf0, 0x0f, 0x04, 0x23, 0x00, 0x08, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0x8c, 0x02, +0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x01, 0xdd, 0x04, 0x13, 0x00, 0x15, 0x14, 0x10, 0x01, 0xe6, +0x04, 0x13, 0x00, 0x16, 0x14, 0x10, 0x01, 0xe7, 0x04, 0x13, 0x00, 0x17, 0x14, 0x10, 0x01, 0xe8, +0x04, 0x13, 0x00, 0x18, 0x14, 0x10, 0x01, 0xe9, 0x04, 0x13, 0x00, 0x19, 0x14, 0x10, 0x01, 0xf0, +0x04, 0x13, 0x00, 0x1a, 0x14, 0x10, 0x01, 0xf1, 0x04, 0x13, 0x00, 0x1b, 0x14, 0x10, 0x01, 0xf2, +0x04, 0x13, 0x00, 0x1c, 0x14, 0x10, 0x01, 0xf3, 0x50, 0x74, 0x80, 0xa8, 0x3e, 0x09, 0x8e, 0x7c, +0x46, 0x60, 0x04, 0x12, 0x80, 0xa6, 0x80, 0x85, 0x80, 0x64, 0x80, 0x43, 0x99, 0xf8, 0x84, 0x00, +0x14, 0x03, 0x03, 0x14, 0x9c, 0x01, 0xa2, 0x79, 0x41, 0xc0, 0xa0, 0x09, 0x41, 0xe0, 0xc0, 0x09, +0x81, 0x3c, 0x54, 0x10, 0x80, 0x7f, 0x55, 0xef, 0x7f, 0x00, 0x55, 0xce, 0x00, 0x7f, 0x54, 0x94, +0xff, 0x00, 0x15, 0xe2, 0x83, 0x18, 0x15, 0xc2, 0x03, 0x1c, 0x14, 0x91, 0x83, 0x19, 0x14, 0x11, +0x03, 0x1d, 0x84, 0x24, 0x4c, 0x00, 0xff, 0xe6, 0x44, 0x00, 0x00, 0xe0, 0x42, 0x04, 0x00, 0x24, +0x3e, 0x29, 0x8e, 0x7c, 0x98, 0x02, 0x50, 0x00, 0x00, 0xb8, 0xb4, 0x40, 0x80, 0x23, 0x14, 0x20, +0x82, 0x06, 0xa0, 0x81, 0x14, 0x20, 0x82, 0x07, 0xa0, 0x82, 0x14, 0x20, 0x82, 0x08, 0xa0, 0x83, +0x14, 0x20, 0x82, 0x09, 0xa0, 0x84, 0x14, 0x20, 0x82, 0x0a, 0xa0, 0x85, 0x14, 0x20, 0x82, 0x0b, +0xa0, 0x86, 0x14, 0x20, 0x81, 0xcf, 0xa0, 0x87, 0x14, 0x20, 0x83, 0x04, 0x04, 0x20, 0x00, 0x08, +0x14, 0x20, 0x83, 0x05, 0x04, 0x20, 0x00, 0x09, 0x80, 0x01, 0x14, 0x20, 0x82, 0x05, 0x14, 0xa0, +0x01, 0xc0, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0xb4, 0x80, 0xb5, 0x40, 0xb4, 0x40, 0x80, 0x20, 0xf2, 0x81, 0x8c, 0x08, 0xa2, 0xc9, +0x42, 0xa5, 0x78, 0x0b, 0xb6, 0x7f, 0xb4, 0xc1, 0xb5, 0x20, 0x3c, 0x0c, 0x4e, 0x8b, 0x3c, 0x6e, +0x4e, 0x8b, 0x84, 0xa1, 0x4c, 0xa2, 0x80, 0x09, 0x44, 0x1f, 0xff, 0xb5, 0x44, 0x2f, 0xff, 0xc4, +0x44, 0x3f, 0xff, 0xd3, 0xd5, 0x18, 0x40, 0x00, 0x18, 0x07, 0x44, 0x1f, 0xff, 0xd5, 0x9e, 0x8c, +0x40, 0x31, 0x00, 0x1a, 0x40, 0x30, 0x80, 0x1b, 0x44, 0x5f, 0xff, 0xb3, 0x8e, 0x5a, 0x40, 0x12, +0x80, 0x1a, 0x40, 0x11, 0x00, 0x1b, 0x44, 0x7f, 0xff, 0xc2, 0x8c, 0xb3, 0x40, 0x23, 0x80, 0x1a, +0x40, 0x22, 0x80, 0x1b, 0x96, 0x20, 0xe6, 0x0f, 0xe8, 0x19, 0x2e, 0x01, 0x3a, 0x74, 0x84, 0xa1, +0xd8, 0x10, 0xe0, 0x66, 0xe8, 0x04, 0x46, 0x01, 0xa0, 0xe0, 0xd5, 0x3b, 0xe0, 0x46, 0xe8, 0x04, +0x46, 0x01, 0x61, 0xc0, 0xd5, 0x36, 0xe0, 0x26, 0xe8, 0x2c, 0x46, 0x01, 0x82, 0x20, 0xd5, 0x31, +0xe0, 0x66, 0xe8, 0x22, 0x46, 0x01, 0x81, 0xe0, 0xd5, 0x2c, 0x2e, 0x01, 0x3a, 0x75, 0x84, 0xa1, +0xd8, 0x16, 0xe0, 0x66, 0xe8, 0x04, 0x46, 0x01, 0xe2, 0x00, 0xd5, 0x23, 0xe0, 0x46, 0xe8, 0x04, +0x46, 0x02, 0x02, 0xa0, 0xd5, 0x1e, 0x46, 0x51, 0x42, 0x40, 0x46, 0x42, 0x23, 0x20, 0x40, 0x70, +0x98, 0x07, 0x40, 0x02, 0x9c, 0x1b, 0x40, 0x02, 0x1c, 0x1a, 0xd5, 0x13, 0xe0, 0x66, 0xe8, 0x04, +0x46, 0x01, 0x82, 0x00, 0xd5, 0x0e, 0xe0, 0x46, 0xe9, 0x04, 0xe0, 0x26, 0xe9, 0x05, 0xd5, 0x07, +0x46, 0x01, 0x83, 0x00, 0xd5, 0x06, 0x46, 0x01, 0x83, 0x60, 0xd5, 0x03, 0x46, 0x01, 0xe4, 0x20, +0x3c, 0x50, 0x9d, 0x6a, 0x92, 0x10, 0x40, 0x00, 0x40, 0x08, 0x46, 0x40, 0x04, 0x12, 0x40, 0x50, +0x14, 0x04, 0x14, 0x52, 0x00, 0xc8, 0x3c, 0x70, 0x9d, 0x6c, 0x80, 0xa4, 0x40, 0x00, 0x1c, 0x04, +0x14, 0x02, 0x80, 0xc9, 0x04, 0x72, 0x00, 0xc8, 0x92, 0xe8, 0x54, 0x73, 0x80, 0x7f, 0xe0, 0x66, +0xe8, 0x08, 0x50, 0x73, 0xff, 0xd0, 0x97, 0xf8, 0x44, 0x8f, 0xff, 0xd3, 0x84, 0x00, 0xd5, 0x15, +0xe0, 0x46, 0xe8, 0x08, 0x50, 0x73, 0xff, 0xe0, 0x97, 0xf8, 0x44, 0x8f, 0xff, 0xc4, 0x84, 0x01, +0xd5, 0x0c, 0xe0, 0x26, 0xe9, 0x05, 0x44, 0x8f, 0xff, 0x9c, 0x84, 0x03, 0xd5, 0x06, 0x8e, 0xf0, +0x97, 0xf8, 0x44, 0x8f, 0xff, 0xb5, 0x84, 0x02, 0x4e, 0xa3, 0x00, 0x35, 0x47, 0xc0, 0x01, 0x14, +0x3c, 0x0c, 0x4e, 0xad, 0x4c, 0x80, 0x00, 0x0d, 0x3e, 0x09, 0x0e, 0x28, 0x80, 0x27, 0x49, 0xff, +0xc2, 0x09, 0x3c, 0x0c, 0x4e, 0xad, 0xe0, 0x08, 0xe8, 0x03, 0x3e, 0xa1, 0x3a, 0x76, 0x3c, 0x8e, +0x4e, 0xad, 0x5c, 0xf4, 0x83, 0xe9, 0xe9, 0x0a, 0x3e, 0x09, 0x3a, 0x76, 0x20, 0x10, 0x00, 0x00, +0x5e, 0xf0, 0xff, 0xf5, 0xe9, 0x0e, 0x9e, 0x4a, 0xd5, 0x0b, 0x5c, 0xf4, 0x80, 0x64, 0xe8, 0x09, +0x3e, 0x09, 0x3a, 0x76, 0x20, 0x10, 0x00, 0x00, 0x4e, 0x14, 0x00, 0x04, 0x9c, 0x4a, 0xae, 0x40, +0x2e, 0x19, 0x3a, 0x76, 0x3e, 0x09, 0x0e, 0x4c, 0x49, 0xff, 0xc1, 0xe4, 0x2e, 0x11, 0x3a, 0x76, +0xd5, 0x1d, 0x5c, 0xf4, 0x83, 0xe9, 0xe9, 0x0a, 0x3e, 0x19, 0x7e, 0x64, 0x38, 0x20, 0x82, 0x02, +0x5e, 0xf1, 0x7f, 0xf5, 0xe9, 0x0f, 0x9e, 0x92, 0xd5, 0x0b, 0x5c, 0xf4, 0x80, 0x64, 0xe8, 0x0a, +0x3e, 0x19, 0x7e, 0x64, 0x38, 0x20, 0x82, 0x02, 0x4e, 0x24, 0x00, 0x05, 0x9c, 0x92, 0x38, 0x20, +0x82, 0x0a, 0x3e, 0x19, 0x7e, 0x64, 0x38, 0x10, 0x82, 0x02, 0x46, 0x00, 0x04, 0x12, 0x04, 0x30, +0x00, 0xc8, 0x99, 0xf9, 0x96, 0x78, 0x44, 0x4f, 0x80, 0xff, 0x40, 0x20, 0xa0, 0x08, 0x40, 0x31, +0x90, 0x02, 0x40, 0x31, 0x0c, 0x04, 0x14, 0x30, 0x00, 0xc8, 0x04, 0x30, 0x00, 0xc9, 0x40, 0x31, +0x90, 0x02, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x00, 0xc9, 0x3e, 0x09, 0x0e, 0x6c, 0x49, 0xff, +0xc1, 0xa9, 0xf1, 0x01, 0x84, 0xa1, 0x42, 0x00, 0xf4, 0x0b, 0xd8, 0x03, 0x49, 0xff, 0xfd, 0x82, +0xb4, 0x7f, 0x84, 0xa1, 0x42, 0x01, 0xf0, 0x0b, 0xd8, 0x33, 0x5e, 0xf3, 0x7f, 0xc0, 0xe9, 0x18, +0x46, 0x00, 0x04, 0x12, 0x04, 0x20, 0x02, 0x54, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x02, 0x54, +0x80, 0x20, 0x04, 0x20, 0x80, 0xc8, 0x46, 0x00, 0x04, 0x12, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, +0x80, 0xc8, 0x58, 0x00, 0x03, 0x24, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x02, 0xd5, 0x18, 0x46, 0x00, +0x04, 0x12, 0x04, 0x20, 0x02, 0x54, 0x80, 0x20, 0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x02, 0x54, +0x04, 0x20, 0x80, 0xc8, 0x84, 0x9d, 0x40, 0x21, 0x10, 0x02, 0x46, 0x00, 0x04, 0x12, 0x14, 0x20, +0x80, 0xc8, 0x58, 0x00, 0x03, 0x24, 0xb4, 0x20, 0x40, 0x10, 0x90, 0x02, 0xb6, 0x20, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x2e, 0x31, +0x3a, 0x84, 0x46, 0x20, 0x04, 0x12, 0x96, 0x40, 0x04, 0x21, 0x00, 0xc0, 0xcb, 0x02, 0xd5, 0x0c, +0x84, 0xa1, 0xdb, 0x07, 0x4c, 0x11, 0xc0, 0x03, 0xd5, 0x07, 0x84, 0xa3, 0xd9, 0x20, 0xd5, 0x0b, +0x84, 0xa2, 0xdb, 0x1d, 0xc9, 0x06, 0x44, 0x0f, 0xfc, 0xff, 0x40, 0x21, 0x00, 0x02, 0xd5, 0x17, +0x84, 0xa1, 0xd9, 0x08, 0x44, 0x0f, 0xfc, 0xff, 0x40, 0x21, 0x00, 0x02, 0x58, 0x21, 0x01, 0x00, +0xd5, 0x0e, 0x84, 0xa2, 0xd9, 0x08, 0x44, 0x0f, 0xfc, 0xff, 0x40, 0x21, 0x00, 0x02, 0x58, 0x21, +0x02, 0x00, 0xd5, 0x05, 0x84, 0xa3, 0xd9, 0x2d, 0x58, 0x21, 0x03, 0x00, 0x46, 0x00, 0x04, 0x12, +0x14, 0x20, 0x00, 0xc0, 0x04, 0x20, 0x01, 0xc0, 0xcb, 0x02, 0xd5, 0x0c, 0x84, 0xa1, 0xdb, 0x07, +0x4c, 0x11, 0xc0, 0x03, 0xd5, 0x07, 0x84, 0xa3, 0xd9, 0x22, 0xd5, 0x09, 0x84, 0xa2, 0xdb, 0x1f, +0xc9, 0x04, 0x92, 0x42, 0x94, 0x92, 0xd5, 0x1b, 0x84, 0xa1, 0xd9, 0x06, 0x92, 0x42, 0x94, 0x92, +0x58, 0x21, 0x00, 0x01, 0xd5, 0x14, 0x84, 0xa2, 0xd9, 0x06, 0x92, 0x42, 0x94, 0x92, 0x58, 0x21, +0x00, 0x02, 0xd5, 0x0d, 0x84, 0x03, 0x4c, 0x10, 0x40, 0x05, 0x40, 0x21, 0x00, 0x04, 0xd5, 0x07, +0x3e, 0x09, 0x0e, 0x88, 0x49, 0xff, 0xc1, 0x06, 0x92, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x04, 0x12, +0x14, 0x20, 0x01, 0xc0, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xfc, 0x55, 0xc0, 0x00, 0xff, 0x4f, 0xc2, 0x00, 0x0a, 0x2e, 0x01, 0x3a, 0x7a, 0x84, 0xa1, +0xd8, 0x0d, 0x3e, 0x69, 0x39, 0x80, 0x85, 0x4b, 0xd5, 0x0b, 0x2e, 0x01, 0x3a, 0x7b, 0x84, 0xa1, +0xd8, 0x05, 0x3e, 0x69, 0x39, 0xd8, 0x85, 0x45, 0xd5, 0x03, 0x84, 0xc0, 0x81, 0x46, 0x80, 0xe6, +0x85, 0x20, 0xd5, 0x1b, 0xa6, 0xf8, 0x84, 0xa9, 0x80, 0x23, 0xdb, 0x0a, 0xa4, 0x79, 0xa0, 0xb9, +0x84, 0x00, 0x49, 0xff, 0xf9, 0xbd, 0xa4, 0x79, 0xa0, 0xb9, 0x84, 0x01, 0xd5, 0x06, 0xe6, 0x62, +0xe8, 0x07, 0xa4, 0x79, 0xa0, 0xb9, 0x80, 0x03, 0x49, 0xff, 0xf9, 0xb2, 0xd5, 0x04, 0x49, 0xff, +0xc0, 0xc9, 0x92, 0x00, 0x8d, 0x21, 0x8c, 0xe8, 0x3e, 0x09, 0x0e, 0xb0, 0xe1, 0x2a, 0xe9, 0xe3, +0x4f, 0xc2, 0x00, 0x0a, 0x2e, 0x81, 0x3a, 0x75, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0d, 0x3e, 0x69, +0x3a, 0x00, 0xd5, 0x0a, 0x2e, 0x81, 0x3a, 0x74, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x05, 0x3e, 0x69, +0x3a, 0x08, 0xd5, 0x02, 0x85, 0x00, 0x84, 0x20, 0xd5, 0x1a, 0xa6, 0xf0, 0x84, 0x49, 0x80, 0x23, +0x4c, 0x31, 0x40, 0x0b, 0xa4, 0x71, 0xa0, 0xb1, 0x84, 0x00, 0x49, 0xff, 0xf9, 0x89, 0xa4, 0x71, +0xa0, 0xb1, 0x84, 0x01, 0xd5, 0x06, 0xe6, 0x62, 0xe8, 0x07, 0xa4, 0x71, 0xa0, 0xb1, 0x80, 0x03, +0x49, 0xff, 0xf9, 0x7e, 0xd5, 0x03, 0x49, 0xff, 0xc0, 0x95, 0x84, 0x21, 0x3e, 0x09, 0x0e, 0xcc, +0xe0, 0x28, 0xe9, 0xe4, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0x3e, 0x69, 0x2d, 0x74, 0xa6, 0xf0, 0x84, 0xa9, 0x3e, 0x09, 0x0e, 0xe8, 0x80, 0x23, 0xdb, 0x0e, +0x02, 0x83, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x01, 0x80, 0x28, 0x80, 0x4a, 0x84, 0x00, 0x49, 0xff, +0xf9, 0x5f, 0x80, 0x28, 0x80, 0x4a, 0x84, 0x01, 0xd5, 0x06, 0xe6, 0x62, 0xe8, 0x07, 0xa4, 0x71, +0xa0, 0xb1, 0x80, 0x03, 0x49, 0xff, 0xf9, 0x54, 0xd5, 0x03, 0x49, 0xff, 0xc0, 0x6b, 0x8c, 0xc8, +0x3e, 0x59, 0x2d, 0xcc, 0xde, 0xe0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x2e, 0x21, 0x3a, 0x64, 0x97, 0xc0, 0x44, 0x50, 0x00, 0xff, 0x80, 0xc1, 0xd2, 0x3f, +0x2e, 0x01, 0x3a, 0x80, 0xe2, 0x02, 0xe9, 0x3b, 0xcf, 0x1c, 0x3e, 0x09, 0x3a, 0x81, 0xa6, 0x80, +0x3e, 0x89, 0x7e, 0x80, 0x9c, 0x51, 0x96, 0x48, 0x38, 0x64, 0x0a, 0x0a, 0x84, 0xa8, 0xae, 0x40, +0xd9, 0x48, 0xaf, 0xc0, 0x80, 0xc7, 0xb4, 0x28, 0x3e, 0x09, 0x0f, 0x00, 0x49, 0xff, 0xc0, 0x42, +0x0c, 0x04, 0x00, 0x01, 0x99, 0xb0, 0x3e, 0x59, 0x7e, 0xa0, 0x4c, 0x82, 0xff, 0xf6, 0xd5, 0x1c, +0x3e, 0x09, 0x3a, 0x82, 0xa6, 0x80, 0x3e, 0x89, 0x7e, 0xa0, 0x9c, 0x51, 0x96, 0x48, 0x38, 0x64, +0x0a, 0x0a, 0x84, 0xa8, 0xae, 0x40, 0xd9, 0x2d, 0x84, 0x20, 0xae, 0x40, 0x84, 0xc0, 0xb4, 0x28, +0x3e, 0x09, 0x0f, 0x00, 0x49, 0xff, 0xc0, 0x26, 0x0c, 0x04, 0x00, 0x01, 0x99, 0xb0, 0x3e, 0x59, +0x7e, 0xc0, 0x4c, 0x82, 0xff, 0xf6, 0x84, 0x08, 0x40, 0x63, 0x00, 0x16, 0x80, 0x46, 0x3e, 0x09, +0x0f, 0x04, 0x80, 0x27, 0x49, 0xff, 0xc0, 0x16, 0x54, 0x63, 0x00, 0x3f, 0xcf, 0x06, 0x46, 0x00, +0x04, 0x11, 0x58, 0x00, 0x03, 0xb4, 0xd5, 0x05, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x03, 0xa8, +0xb4, 0x20, 0x92, 0x26, 0x94, 0x4e, 0xb6, 0x20, 0xb4, 0x20, 0x40, 0x63, 0x04, 0x04, 0xb6, 0xc0, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x2e, 0x71, +0x3a, 0x7f, 0x54, 0x90, 0x00, 0xff, 0x84, 0x01, 0x96, 0x48, 0x96, 0x90, 0x96, 0xd8, 0x97, 0x20, +0x97, 0xa8, 0x4c, 0x70, 0x02, 0x21, 0x50, 0x5f, 0x80, 0x10, 0x96, 0x1a, 0xa8, 0xa9, 0xb6, 0x25, +0x50, 0x5f, 0x80, 0x08, 0x4e, 0x04, 0x00, 0x04, 0x50, 0x31, 0xff, 0x00, 0x96, 0x22, 0xb6, 0x65, +0x50, 0x5f, 0x80, 0x08, 0x4e, 0x04, 0x00, 0x04, 0x50, 0x42, 0x7f, 0x00, 0xa9, 0x29, 0x50, 0x0f, +0x80, 0x08, 0xa1, 0x01, 0xb4, 0x60, 0x3e, 0x09, 0x0f, 0x24, 0x49, 0xff, 0xbf, 0xd3, 0xe6, 0xc2, +0xe8, 0x13, 0x46, 0x10, 0x04, 0x12, 0x46, 0x20, 0x00, 0x8a, 0x58, 0x21, 0x0c, 0x50, 0x14, 0x20, +0x80, 0x22, 0x84, 0x21, 0x4c, 0x60, 0xc0, 0x09, 0x3e, 0x09, 0x0f, 0x5c, 0x49, 0xff, 0xbf, 0xc2, +0x80, 0x06, 0x48, 0x00, 0x01, 0xf3, 0x46, 0x70, 0x04, 0x12, 0x84, 0xc0, 0x47, 0xc0, 0x00, 0x80, +0x59, 0xce, 0x0b, 0xf0, 0x04, 0x83, 0x80, 0x22, 0x3e, 0x09, 0x0f, 0x6c, 0x80, 0x28, 0x54, 0x84, +0x00, 0x10, 0xdd, 0x3c, 0x44, 0x00, 0x00, 0x64, 0x4e, 0x82, 0x00, 0x08, 0x49, 0xff, 0xf8, 0x80, +0x9d, 0xb1, 0x84, 0x45, 0x4c, 0x61, 0x7f, 0xf0, 0x3e, 0x09, 0x0f, 0x78, 0x80, 0x26, 0x49, 0xff, +0xbf, 0xa1, 0x84, 0x65, 0x4c, 0x61, 0x81, 0xd0, 0x2e, 0x01, 0x3a, 0x64, 0x2e, 0x21, 0x3a, 0x80, +0xe2, 0x40, 0xe8, 0x04, 0x9c, 0x91, 0x3e, 0x21, 0x3a, 0x80, 0x46, 0x10, 0x04, 0x12, 0x04, 0x10, +0x80, 0x23, 0x50, 0x2f, 0x80, 0x18, 0x4e, 0x93, 0x00, 0x09, 0x40, 0x00, 0xc0, 0x09, 0x96, 0x00, +0x96, 0x48, 0xa8, 0x11, 0xb6, 0x22, 0xd5, 0x07, 0x40, 0x00, 0xa0, 0x09, 0x96, 0x00, 0x92, 0x38, +0xa8, 0x51, 0xb6, 0x02, 0x50, 0x1f, 0x80, 0x18, 0xb4, 0x01, 0x5e, 0xf0, 0x00, 0x80, 0xe9, 0x04, +0x50, 0x00, 0x7f, 0x00, 0xb6, 0x01, 0x50, 0x1f, 0x80, 0x18, 0xa0, 0x09, 0x5e, 0xf0, 0x00, 0x80, +0xe9, 0x04, 0x50, 0x00, 0x7f, 0x00, 0xa8, 0x09, 0x3c, 0x24, 0xbf, 0x3f, 0x3c, 0x14, 0xbf, 0x3e, +0x46, 0x70, 0x00, 0x80, 0x58, 0x73, 0x8b, 0xf0, 0x3e, 0x09, 0x0f, 0x80, 0xdd, 0x27, 0x50, 0x0f, +0x80, 0x18, 0xa0, 0x81, 0xb4, 0x20, 0x3e, 0x09, 0x0f, 0x9c, 0xdd, 0x27, 0x46, 0x20, 0x04, 0x12, +0x46, 0x00, 0x00, 0x8a, 0x58, 0x21, 0x00, 0x88, 0x58, 0x00, 0x0c, 0x41, 0xb6, 0x02, 0x46, 0x30, +0x00, 0x8a, 0x9c, 0x14, 0x58, 0x31, 0x8c, 0x42, 0xb4, 0x20, 0xb6, 0x62, 0x46, 0x30, 0x00, 0x8a, +0xb4, 0x80, 0x58, 0x31, 0x8c, 0x44, 0xb6, 0x62, 0x40, 0x22, 0x40, 0x08, 0x92, 0x5e, 0xb5, 0x00, +0xc2, 0x06, 0x3e, 0x09, 0x0f, 0xb4, 0xdd, 0x27, 0x48, 0x00, 0x01, 0x6e, 0x54, 0x00, 0x80, 0x07, +0x96, 0x49, 0xe6, 0x04, 0xe8, 0x04, 0xe6, 0x02, 0xe8, 0x06, 0xd5, 0x22, 0x84, 0x64, 0x4c, 0x01, +0xc0, 0x1d, 0xd5, 0x15, 0x40, 0x00, 0xa0, 0x09, 0x54, 0x00, 0x00, 0x7f, 0xe6, 0x08, 0xe9, 0x07, +0x44, 0x20, 0x00, 0x20, 0x4c, 0x01, 0x00, 0x04, 0x84, 0xc2, 0xd5, 0x02, 0x84, 0xc1, 0x92, 0x26, +0x54, 0x10, 0x80, 0x03, 0x84, 0x02, 0x40, 0x60, 0x04, 0x1b, 0xd5, 0x0b, 0x40, 0x60, 0x94, 0x09, +0x54, 0x63, 0x00, 0x07, 0x9d, 0xb1, 0xd5, 0x05, 0x3e, 0x09, 0x0f, 0xd4, 0xdd, 0x27, 0x84, 0xc1, +0x3e, 0x09, 0x0f, 0xe8, 0x80, 0x26, 0x40, 0x94, 0x00, 0x13, 0x49, 0xff, 0xbf, 0x0b, 0x50, 0x0f, +0x80, 0x20, 0x54, 0x14, 0x00, 0xff, 0x40, 0x24, 0xa0, 0x09, 0xa8, 0x81, 0xb6, 0x20, 0x5e, 0xf0, +0x80, 0x80, 0x4e, 0xf2, 0x01, 0x31, 0x5e, 0xf1, 0x00, 0x80, 0x4e, 0xf2, 0x01, 0x2d, 0x3e, 0x09, +0x0f, 0xf4, 0x49, 0xff, 0xbe, 0xf7, 0x46, 0x00, 0x04, 0x12, 0x84, 0x21, 0x04, 0x00, 0x01, 0xc5, +0x4c, 0x60, 0xc0, 0x0d, 0x54, 0x00, 0x00, 0x03, 0xc8, 0x03, 0xb6, 0x1f, 0xd5, 0x0a, 0x84, 0x41, +0x4c, 0x01, 0x40, 0x05, 0xb6, 0xdf, 0xf6, 0x81, 0xd5, 0x05, 0x84, 0x61, 0xb6, 0x7f, 0x84, 0x00, +0xf0, 0x81, 0x05, 0xcf, 0x80, 0x01, 0x85, 0x40, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x0b, 0xf0, +0x48, 0x00, 0x00, 0xaf, 0x3e, 0x39, 0x7e, 0x7c, 0x50, 0x1f, 0x80, 0x18, 0x38, 0x21, 0xf1, 0x01, +0x38, 0x90, 0xf2, 0x02, 0x50, 0x0f, 0x80, 0x20, 0x40, 0x24, 0x88, 0x01, 0x38, 0x70, 0x72, 0x02, +0x96, 0x11, 0x49, 0xff, 0xf8, 0xc1, 0x80, 0x20, 0x81, 0x00, 0x3e, 0x09, 0x10, 0x10, 0xdd, 0x26, +0x50, 0x3f, 0x80, 0x10, 0x38, 0x21, 0xf2, 0x02, 0x3e, 0x09, 0x10, 0x20, 0x42, 0x84, 0x08, 0x24, +0x40, 0x73, 0xb0, 0x08, 0x80, 0x28, 0xdd, 0x26, 0x50, 0x0f, 0x80, 0x08, 0x38, 0x20, 0x72, 0x02, +0x3e, 0x09, 0x10, 0x30, 0x40, 0x21, 0x24, 0x08, 0x89, 0x02, 0x80, 0x28, 0xdd, 0x26, 0x8a, 0xe8, +0x3e, 0x09, 0x10, 0x40, 0x80, 0x3c, 0x40, 0x24, 0x30, 0x09, 0xdd, 0x26, 0x3e, 0x09, 0x10, 0x60, +0x80, 0x27, 0xdd, 0x26, 0x4e, 0x75, 0x00, 0x04, 0x84, 0x80, 0xd5, 0x04, 0x52, 0x73, 0x80, 0x00, +0x84, 0x81, 0x54, 0x23, 0x8f, 0xff, 0x40, 0x13, 0xb0, 0x0a, 0x5e, 0xf1, 0x08, 0x01, 0xe9, 0x02, +0x9c, 0x49, 0x56, 0x42, 0x00, 0x01, 0x52, 0x20, 0x80, 0x00, 0x40, 0x11, 0x10, 0x1a, 0x40, 0xa0, +0x80, 0x11, 0x3e, 0x09, 0x10, 0x78, 0xdd, 0x26, 0x3e, 0x09, 0x10, 0x90, 0x80, 0x2a, 0xdd, 0x26, +0x4f, 0xc3, 0x00, 0x07, 0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x03, 0xb4, 0xd5, 0x05, 0x46, 0x20, +0x04, 0x11, 0x58, 0x21, 0x03, 0xa8, 0xb4, 0x42, 0x54, 0x21, 0x00, 0x3f, 0x54, 0x41, 0x00, 0x20, +0xc4, 0x04, 0x50, 0x71, 0x7f, 0xc0, 0xd5, 0x02, 0x80, 0xe2, 0x80, 0x27, 0x3e, 0x09, 0x10, 0xa0, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x7f, 0x4c, 0x90, 0xc0, 0x07, 0x5e, 0x05, 0x00, 0x01, 0x84, 0x9f, +0x40, 0xa2, 0x00, 0x1a, 0x3e, 0x29, 0x7e, 0x7c, 0x38, 0x31, 0x71, 0x11, 0x40, 0x34, 0x8c, 0x01, +0xe4, 0x65, 0xe8, 0x03, 0x85, 0x40, 0xd5, 0x08, 0xe5, 0x45, 0xe9, 0x03, 0x85, 0x44, 0xd5, 0x04, +0x84, 0x7c, 0x42, 0xa5, 0x0c, 0x00, 0x88, 0xea, 0x5e, 0xf3, 0x80, 0x20, 0xe9, 0x04, 0x44, 0x70, +0x00, 0x1f, 0xd5, 0x05, 0x44, 0x3f, 0xff, 0xe0, 0x42, 0x73, 0x8c, 0x00, 0x46, 0x90, 0x04, 0x11, +0x81, 0x09, 0x04, 0x14, 0x80, 0xed, 0x04, 0x24, 0x00, 0xea, 0x3e, 0x09, 0x10, 0xb0, 0xdd, 0x26, +0x80, 0x1c, 0x80, 0x27, 0x49, 0xff, 0xfd, 0xd4, 0x04, 0x14, 0x80, 0xed, 0x04, 0x24, 0x00, 0xea, +0x3e, 0x09, 0x10, 0xd4, 0x51, 0xce, 0x00, 0x01, 0xdd, 0x26, 0x55, 0xce, 0x00, 0xff, 0xb4, 0x7f, +0xe2, 0x7c, 0x4e, 0xf2, 0xff, 0x51, 0xf0, 0x01, 0x4c, 0x01, 0x80, 0x03, 0xd5, 0x52, 0x46, 0x70, +0x04, 0x11, 0x80, 0xc7, 0x04, 0x13, 0x80, 0xed, 0x04, 0x23, 0x00, 0xea, 0x3e, 0x09, 0x10, 0xf8, +0x49, 0xff, 0xbe, 0x18, 0xf1, 0x01, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x1d, 0x3e, 0x09, 0x11, 0x28, +0x49, 0xff, 0xbe, 0x10, 0x04, 0x03, 0x80, 0xed, 0x54, 0x20, 0x00, 0x20, 0x54, 0x00, 0x00, 0x3f, +0xc2, 0x03, 0x50, 0x00, 0x7f, 0xc0, 0x40, 0x10, 0x28, 0x00, 0x5e, 0xf0, 0x80, 0x20, 0xe9, 0x04, +0x44, 0x10, 0x00, 0x1f, 0xd5, 0x05, 0x44, 0x0f, 0xff, 0xe0, 0x42, 0x10, 0x80, 0x00, 0x84, 0x00, +0xd5, 0x1b, 0x3e, 0x09, 0x11, 0x58, 0x49, 0xff, 0xbd, 0xf5, 0x04, 0x03, 0x00, 0xea, 0x54, 0x20, +0x00, 0x20, 0x54, 0x00, 0x00, 0x3f, 0xc2, 0x03, 0x50, 0x00, 0x7f, 0xc0, 0x40, 0x10, 0x28, 0x00, +0x5e, 0xf0, 0x80, 0x20, 0xe9, 0x04, 0x44, 0x10, 0x00, 0x1f, 0xd5, 0x05, 0x44, 0x0f, 0xff, 0xe0, +0x42, 0x10, 0x80, 0x00, 0x84, 0x01, 0x49, 0xff, 0xfd, 0x7b, 0x46, 0x10, 0x04, 0x11, 0x80, 0x01, +0x04, 0x10, 0x80, 0xed, 0x04, 0x20, 0x00, 0xea, 0x3e, 0x09, 0x11, 0x88, 0x49, 0xff, 0xbd, 0xd2, +0x84, 0x01, 0xd5, 0x03, 0x44, 0x00, 0x00, 0xff, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x10, 0x04, 0x12, 0x04, 0x20, 0x81, 0xca, 0x80, 0xe1, 0x46, 0x20, +0x10, 0x00, 0x81, 0x00, 0x84, 0x60, 0x14, 0x23, 0x81, 0xc9, 0x44, 0x04, 0x00, 0x00, 0x98, 0x90, +0x04, 0x00, 0x81, 0xca, 0x80, 0xc1, 0x96, 0x00, 0x98, 0xd8, 0x46, 0x00, 0x12, 0xc0, 0x80, 0xa1, +0x4c, 0x20, 0x7f, 0xf3, 0x46, 0x10, 0x12, 0x80, 0x14, 0x13, 0x01, 0xc9, 0x44, 0x60, 0x00, 0x37, +0x04, 0x22, 0x81, 0xca, 0x84, 0x0a, 0x96, 0x90, 0x42, 0x61, 0x18, 0x24, 0x80, 0x23, 0x40, 0x63, +0x00, 0x17, 0x80, 0x88, 0x3e, 0x09, 0x11, 0xb8, 0x9b, 0x9e, 0x80, 0x66, 0x49, 0xff, 0xbd, 0x9a, +0x92, 0x00, 0xe0, 0xc8, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x05, 0x5e, 0x63, 0x7f, 0xf2, 0x56, 0x03, +0x00, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x0c, +0x4e, 0xb2, 0x4e, 0x06, 0x00, 0x08, 0x3e, 0x09, 0x11, 0xe4, 0x49, 0xff, 0xbd, 0x83, 0x92, 0x00, +0xd5, 0x16, 0x9e, 0x41, 0x94, 0x4a, 0x3e, 0x39, 0x81, 0xd0, 0x3e, 0x59, 0x81, 0x50, 0x98, 0x8b, +0x98, 0x4d, 0x0c, 0x30, 0xff, 0xff, 0x46, 0x50, 0x04, 0x10, 0x0c, 0x41, 0x7f, 0xff, 0x98, 0xdd, +0x9e, 0x01, 0xb6, 0x83, 0x4e, 0x06, 0xff, 0xf7, 0x3c, 0x0e, 0x4e, 0xb2, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x4e, 0xb2, 0x3e, 0x39, +0x81, 0x50, 0x38, 0x01, 0x86, 0x0a, 0x46, 0x30, 0x04, 0x10, 0x98, 0x03, 0xb4, 0x80, 0x3e, 0x39, +0x81, 0xd0, 0x9c, 0x09, 0x38, 0x41, 0x86, 0x0a, 0x3c, 0x0e, 0x4e, 0xb2, 0x5e, 0xf0, 0x00, 0x21, +0xe9, 0x06, 0x3e, 0x09, 0x11, 0xfc, 0x49, 0xff, 0xbd, 0x4d, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xbc, 0x3c, 0x2c, 0x4c, 0xa0, 0x96, 0x00, +0x96, 0x48, 0x40, 0x31, 0x40, 0x09, 0xf0, 0x86, 0x84, 0xa1, 0xf1, 0x8b, 0x10, 0x3f, 0x80, 0x3e, +0x12, 0x2f, 0x80, 0x1e, 0xd9, 0x06, 0x84, 0x28, 0xf1, 0x8a, 0x44, 0x90, 0x00, 0xb8, 0xd5, 0x0d, +0x2e, 0x41, 0x3a, 0x7b, 0x44, 0x30, 0x00, 0xa4, 0x44, 0x20, 0x00, 0xb8, 0x40, 0x91, 0x90, 0x1a, +0x40, 0x91, 0x10, 0x1b, 0x84, 0x44, 0xf2, 0x8a, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x01, 0x24, +0x44, 0x00, 0x27, 0x14, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x6c, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x70, +0xdd, 0x26, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x26, 0x44, 0x00, +0x29, 0x80, 0xdd, 0x26, 0xf3, 0x06, 0x46, 0x20, 0x04, 0x12, 0x46, 0x18, 0x00, 0x00, 0x58, 0x41, +0x80, 0x80, 0x46, 0x0c, 0x00, 0x02, 0x40, 0x31, 0xf8, 0x08, 0x58, 0x10, 0x80, 0x12, 0x14, 0x41, +0x01, 0xc5, 0x84, 0xa0, 0x46, 0x60, 0x0f, 0xff, 0x40, 0x11, 0x84, 0x04, 0x58, 0x00, 0x01, 0x01, +0x50, 0x2f, 0x80, 0x3f, 0xf1, 0x8c, 0x58, 0x63, 0x0f, 0xff, 0xf0, 0x89, 0xf5, 0x85, 0xf2, 0x81, +0x48, 0x00, 0x00, 0xb6, 0x46, 0x30, 0x04, 0x12, 0x40, 0x24, 0xa0, 0x08, 0xf3, 0x87, 0xf0, 0x06, +0x40, 0x21, 0x24, 0x04, 0x44, 0x10, 0x02, 0x10, 0xf3, 0x88, 0xf3, 0x84, 0xf5, 0x82, 0x49, 0xff, +0xf5, 0xc7, 0xf0, 0x07, 0xf1, 0x08, 0xf2, 0x04, 0x47, 0xc0, 0x04, 0x12, 0x58, 0x00, 0x07, 0x18, +0x58, 0x10, 0x87, 0x6c, 0x58, 0x21, 0x07, 0x70, 0x59, 0xce, 0x00, 0x10, 0x14, 0x9f, 0x80, 0x0d, +0xf0, 0x87, 0xf1, 0x88, 0xf2, 0x84, 0x04, 0x9f, 0x80, 0x0b, 0xf5, 0x02, 0x80, 0x7c, 0x50, 0xaf, +0x80, 0x3c, 0x83, 0x86, 0xf1, 0x09, 0xf0, 0x07, 0xb6, 0x20, 0x44, 0x00, 0x00, 0x3f, 0xf2, 0x08, +0x84, 0x21, 0xb6, 0x02, 0x00, 0x05, 0x00, 0x00, 0x4c, 0x90, 0xc0, 0x09, 0x40, 0x10, 0x20, 0x08, +0xf2, 0x04, 0x40, 0x00, 0x80, 0x04, 0xb6, 0x02, 0xd5, 0x0b, 0xf2, 0x04, 0x40, 0x00, 0x40, 0x08, +0x46, 0x10, 0x04, 0x12, 0xb6, 0x02, 0x44, 0x00, 0x00, 0x60, 0x14, 0x00, 0x83, 0x04, 0x84, 0x01, +0xb6, 0x03, 0xf3, 0x83, 0xf5, 0x82, 0x49, 0xff, 0xf5, 0x7b, 0xf3, 0x03, 0x46, 0x00, 0x04, 0x12, +0x84, 0x20, 0xb6, 0x23, 0x14, 0x10, 0x02, 0x4d, 0x80, 0x40, 0xf1, 0x0c, 0x14, 0x10, 0x02, 0x4d, +0x84, 0x00, 0x14, 0x01, 0x02, 0x60, 0x84, 0x21, 0xf5, 0x02, 0x4c, 0x90, 0xc0, 0x07, 0x46, 0x0c, +0x00, 0x10, 0x58, 0x00, 0x00, 0x06, 0xd5, 0x05, 0x46, 0x0c, 0x00, 0x20, 0x58, 0x00, 0x00, 0x0c, +0x84, 0x20, 0x14, 0x01, 0x02, 0x60, 0x80, 0xc1, 0xd5, 0x0f, 0x44, 0x10, 0x00, 0x65, 0x4c, 0x60, +0x80, 0x11, 0xf3, 0x83, 0xf5, 0x82, 0x97, 0x91, 0x49, 0xff, 0xf5, 0x52, 0x04, 0x13, 0x82, 0x7f, +0xf3, 0x03, 0xf5, 0x02, 0xd5, 0x02, 0x80, 0xe2, 0x96, 0x4c, 0x9c, 0xb1, 0x84, 0x0a, 0xc1, 0xee, +0x84, 0x41, 0x4c, 0x91, 0x40, 0x0b, 0x46, 0x10, 0x04, 0x12, 0x46, 0x0c, 0x00, 0x10, 0x58, 0x10, +0x89, 0x80, 0x58, 0x00, 0x00, 0x06, 0xd5, 0x09, 0x46, 0x10, 0x04, 0x12, 0x46, 0x0c, 0x00, 0x20, +0x58, 0x10, 0x89, 0x80, 0x58, 0x00, 0x00, 0x0c, 0xb6, 0x01, 0x46, 0x00, 0x04, 0x12, 0x04, 0x00, +0x02, 0x61, 0x8d, 0x41, 0x40, 0x20, 0x70, 0x06, 0x40, 0x12, 0x80, 0x06, 0x40, 0x50, 0x04, 0x1b, +0x41, 0xc0, 0x08, 0x1b, 0xf0, 0x01, 0x4c, 0xa0, 0x7f, 0x87, 0x44, 0x20, 0xff, 0xfd, 0x04, 0x9f, +0x80, 0x0d, 0x80, 0xdc, 0xe2, 0x5c, 0xe9, 0x06, 0x5c, 0xf2, 0xb0, 0x00, 0xe8, 0x0d, 0x8d, 0x21, +0xd5, 0x02, 0x8f, 0x21, 0xf2, 0x05, 0x9c, 0x51, 0x96, 0x49, 0xf1, 0x85, 0xf3, 0x05, 0xf0, 0x0a, +0xe2, 0x60, 0x4e, 0xf3, 0xff, 0x49, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xfe, 0xa7, 0x84, 0x01, +0xa8, 0x34, 0x49, 0xff, 0xf5, 0x05, 0x84, 0x00, 0xa8, 0x34, 0xec, 0x44, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, +0x80, 0x20, 0x83, 0x80, 0x3e, 0x09, 0x12, 0x1c, 0x49, 0xff, 0xbc, 0x1c, 0x46, 0x10, 0x04, 0x10, +0x04, 0x00, 0x80, 0x20, 0x58, 0x00, 0x02, 0x00, 0x14, 0x00, 0x80, 0x20, 0x2e, 0x61, 0x3a, 0x83, +0xce, 0x40, 0x46, 0x20, 0x04, 0xf0, 0x04, 0x01, 0x00, 0x0c, 0x46, 0x10, 0x04, 0x0d, 0x58, 0x00, +0x00, 0x01, 0x14, 0x01, 0x00, 0x0c, 0xb4, 0x01, 0x81, 0x21, 0x46, 0xa2, 0x01, 0xe8, 0x80, 0x41, +0x46, 0x87, 0x00, 0x04, 0x80, 0xa1, 0x46, 0x77, 0xf0, 0x30, 0x46, 0x47, 0x11, 0x14, 0x80, 0x61, +0x42, 0x00, 0x70, 0x08, 0x58, 0x84, 0x00, 0x01, 0x58, 0x73, 0x80, 0x7f, 0x58, 0xa5, 0x08, 0x5d, +0x58, 0x42, 0x00, 0x01, 0xb6, 0x01, 0x14, 0xa4, 0x80, 0x02, 0x14, 0x81, 0x00, 0x06, 0xa9, 0xe9, +0xa9, 0x16, 0xa9, 0x9b, 0x81, 0x01, 0xb4, 0x01, 0x42, 0x00, 0x4c, 0x08, 0xb6, 0x01, 0xb4, 0x21, +0xd5, 0x08, 0x44, 0x50, 0x00, 0x65, 0xd6, 0x0a, 0x97, 0x91, 0x49, 0xff, 0xf4, 0xb1, 0xb4, 0x28, +0x92, 0x30, 0x96, 0x4c, 0x9c, 0xb1, 0x84, 0x0a, 0xc9, 0xf5, 0x84, 0x21, 0x3e, 0x11, 0x3a, 0x83, +0x46, 0x10, 0x04, 0x0d, 0xb4, 0x21, 0x3e, 0x09, 0x12, 0x28, 0x54, 0x10, 0x80, 0x7f, 0xb6, 0x3c, +0x49, 0xff, 0xbb, 0xc8, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x3c, 0x0c, 0x4e, 0xb3, 0x4e, 0x06, 0x00, 0x08, 0x3e, 0x09, 0x12, 0x40, 0x49, 0xff, +0xbb, 0xb9, 0x92, 0x00, 0xd5, 0x16, 0x9e, 0x41, 0x94, 0x4a, 0x3e, 0x39, 0x80, 0xd0, 0x3e, 0x59, +0x80, 0x50, 0x98, 0x8b, 0x98, 0x4d, 0x0c, 0x30, 0xff, 0xff, 0x46, 0x50, 0x04, 0x10, 0x0c, 0x41, +0x7f, 0xff, 0x98, 0xdd, 0x9e, 0x01, 0xb6, 0x83, 0x4e, 0x06, 0xff, 0xf7, 0x3c, 0x0e, 0x4e, 0xb3, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, +0x4e, 0xb3, 0x3e, 0x39, 0x80, 0x50, 0x38, 0x01, 0x86, 0x0a, 0x46, 0x30, 0x04, 0x10, 0x98, 0x03, +0xb4, 0x80, 0x3e, 0x39, 0x80, 0xd0, 0x9c, 0x09, 0x38, 0x41, 0x86, 0x0a, 0x3c, 0x0e, 0x4e, 0xb3, +0x5e, 0xf0, 0x00, 0x21, 0xe9, 0x06, 0x3e, 0x09, 0x12, 0x58, 0x49, 0xff, 0xbb, 0x83, 0x92, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x96, 0x04, +0x40, 0x00, 0x40, 0x08, 0x54, 0x40, 0x8f, 0xff, 0x46, 0x30, 0x04, 0x10, 0x40, 0x70, 0x10, 0x04, +0x58, 0x31, 0x85, 0x28, 0x84, 0x00, 0xb4, 0xc3, 0x84, 0x81, 0x42, 0x63, 0x34, 0x0b, 0x4c, 0x62, +0x00, 0x18, 0xb6, 0xe3, 0x84, 0x80, 0xb4, 0xa3, 0x9d, 0x21, 0x42, 0x62, 0xb4, 0x0b, 0xce, 0x05, +0x54, 0x52, 0x8f, 0xff, 0xd1, 0x06, 0xd5, 0x0c, 0x44, 0x50, 0x00, 0x64, 0xdc, 0xf5, 0xd5, 0x07, +0x46, 0x00, 0x04, 0x10, 0x04, 0x00, 0x01, 0x4b, 0xb6, 0x02, 0xd5, 0x0e, 0x84, 0xc1, 0x9c, 0x01, +0x44, 0x40, 0x00, 0x64, 0x4c, 0x02, 0x7f, 0xe1, 0x84, 0xa1, 0xde, 0x06, 0x3e, 0x09, 0x12, 0x74, +0x49, 0xff, 0xbb, 0x48, 0x92, 0x00, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x84, 0xe0, 0x54, 0xa0, 0x00, 0xff, 0x55, 0xc0, 0x80, 0xff, +0x50, 0x6f, 0x80, 0x04, 0x44, 0x10, 0x01, 0x30, 0x80, 0x07, 0x80, 0x46, 0x49, 0xff, 0xff, 0xb6, +0xf0, 0x01, 0x84, 0x61, 0x42, 0x00, 0x48, 0x09, 0x42, 0x00, 0x4c, 0x09, 0x4d, 0xc1, 0xc0, 0x05, +0x42, 0x00, 0x48, 0x08, 0xd5, 0x03, 0x42, 0x00, 0x4c, 0x08, 0xf0, 0x81, 0x44, 0x10, 0x01, 0x30, +0xf2, 0x01, 0x80, 0x07, 0x3e, 0x99, 0x2b, 0xf2, 0x49, 0xff, 0xf4, 0x02, 0x50, 0x84, 0x80, 0x22, +0x02, 0x04, 0x80, 0x00, 0xe3, 0x40, 0xe9, 0x2a, 0x02, 0x04, 0x80, 0x01, 0xe2, 0x0a, 0xe9, 0x26, +0x44, 0x10, 0x00, 0x58, 0x80, 0x46, 0x80, 0x07, 0x49, 0xff, 0xff, 0x90, 0xf0, 0x01, 0x46, 0x1f, +0x8f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x84, 0x61, 0x40, 0x00, 0x04, 0x02, 0x4d, 0xc1, 0xc0, 0x05, +0x00, 0x14, 0x00, 0x00, 0xd5, 0x08, 0x4f, 0xc3, 0x00, 0x05, 0x04, 0x14, 0x7f, 0xff, 0xd5, 0x03, +0x00, 0x14, 0x00, 0x01, 0x40, 0x10, 0xe0, 0x08, 0x40, 0x00, 0x80, 0x04, 0xf0, 0x81, 0x44, 0x10, +0x00, 0x58, 0xf2, 0x01, 0x80, 0x07, 0x49, 0xff, 0xf3, 0xd3, 0x50, 0x84, 0x00, 0x34, 0x3e, 0x59, +0x2d, 0x80, 0x50, 0x94, 0x80, 0x34, 0x4c, 0x82, 0xff, 0xcd, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xab, +0xe7, 0x4f, 0xe8, 0x0a, 0x2e, 0x51, 0x3a, 0x7b, 0x84, 0x61, 0xd3, 0x04, 0x2e, 0x51, 0x3a, 0x74, +0xdb, 0x0e, 0x84, 0x00, 0xd5, 0x09, 0x2e, 0x51, 0x3a, 0x7a, 0x84, 0x21, 0xd1, 0x04, 0x2e, 0x51, +0x3a, 0x75, 0xd9, 0x05, 0x84, 0x01, 0x49, 0xff, 0xf9, 0xd3, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x84, 0xc0, 0x97, 0xc0, 0x80, 0x26, +0x50, 0x2f, 0x80, 0x04, 0x80, 0x06, 0xf6, 0x81, 0x49, 0xff, 0xff, 0x40, 0xf3, 0x01, 0x44, 0x09, +0xff, 0xff, 0x40, 0x31, 0x80, 0x02, 0x42, 0x31, 0xc8, 0x08, 0xf3, 0x81, 0x46, 0x80, 0x00, 0x87, +0x58, 0x84, 0x0d, 0xbc, 0x80, 0x43, 0x80, 0x06, 0x80, 0x26, 0xdd, 0x28, 0xc7, 0x0f, 0x46, 0x2a, +0x00, 0x56, 0x58, 0x21, 0x04, 0x06, 0x80, 0x26, 0x80, 0x06, 0xdd, 0x28, 0x46, 0x2a, 0x00, 0x56, +0x80, 0x26, 0x58, 0x21, 0x04, 0x06, 0x84, 0x01, 0xd5, 0x0e, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, +0x04, 0x02, 0x80, 0x27, 0x80, 0x07, 0xdd, 0x28, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x04, 0x02, +0x84, 0x01, 0x80, 0x27, 0xdd, 0x28, 0x84, 0x00, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x0d, 0xbc, +0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, 0x44, 0x20, 0x08, 0x00, +0x84, 0x00, 0xdd, 0x26, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x0d, 0x9c, 0x44, 0x00, 0x00, 0x23, +0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, +0x44, 0x20, 0x40, 0x00, 0x84, 0x00, 0xdd, 0x26, 0x84, 0x0a, 0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, +0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, 0x44, 0x20, 0x08, 0x00, 0x84, 0x00, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x23, 0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, +0xdd, 0x26, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x44, 0x20, 0x10, 0x00, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x50, 0xdd, 0x28, 0xc7, 0x62, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, +0x44, 0x10, 0x03, 0x08, 0x44, 0x21, 0x00, 0x00, 0x84, 0x00, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x28, +0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, +0x44, 0x22, 0x00, 0x00, 0x84, 0x00, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x14, 0xdd, 0x28, 0x84, 0x00, +0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, 0x44, 0x24, 0x00, 0x00, +0x84, 0x00, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x28, 0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, +0x80, 0x40, 0xdd, 0x26, 0x46, 0x20, 0x00, 0x80, 0x44, 0x10, 0x03, 0x08, 0x84, 0x00, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x14, 0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, 0x84, 0x40, 0x84, 0x01, 0xdd, 0x26, +0x44, 0x10, 0x03, 0x08, 0x44, 0x24, 0x00, 0x00, 0x84, 0x01, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x28, +0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, 0x84, 0x40, 0x84, 0x01, 0xdd, 0x26, 0x46, 0x20, 0x00, 0x80, +0x44, 0x10, 0x03, 0x08, 0x84, 0x01, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x14, 0xdd, 0x28, 0x84, 0x00, +0x46, 0x28, 0x00, 0x56, 0x58, 0x21, 0x00, 0x04, 0x80, 0x20, 0xdd, 0x26, 0x46, 0x28, 0x00, 0x56, +0x58, 0x21, 0x00, 0x04, 0x84, 0x20, 0xd5, 0x41, 0x44, 0x10, 0x03, 0x08, 0x80, 0x47, 0x80, 0x07, +0xdd, 0x26, 0x46, 0x20, 0x01, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x07, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x32, 0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, 0x80, 0x47, 0x84, 0x01, 0xdd, 0x26, 0x46, 0x20, +0x01, 0x00, 0x44, 0x10, 0x03, 0x08, 0x84, 0x01, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x32, 0xdd, 0x28, +0x44, 0x10, 0x03, 0x08, 0x80, 0x47, 0x80, 0x07, 0xdd, 0x26, 0x46, 0x20, 0x02, 0x00, 0x44, 0x10, +0x03, 0x08, 0x80, 0x07, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x32, 0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, +0x80, 0x47, 0x84, 0x01, 0xdd, 0x26, 0x46, 0x20, 0x02, 0x00, 0x44, 0x10, 0x03, 0x08, 0x84, 0x01, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x32, 0xdd, 0x28, 0x46, 0x28, 0x00, 0x56, 0x80, 0x27, 0x80, 0x07, +0xdd, 0x26, 0x46, 0x28, 0x00, 0x56, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x26, 0x84, 0x00, 0x50, 0x2f, +0x80, 0x04, 0x80, 0x20, 0x49, 0xff, 0xfe, 0x2a, 0xf3, 0x01, 0x44, 0x16, 0x00, 0x00, 0x40, 0x31, +0x84, 0x04, 0x84, 0x00, 0x80, 0x43, 0x80, 0x20, 0xf3, 0x81, 0x49, 0xff, 0xf2, 0x81, 0x92, 0x00, +0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x54, 0x90, +0x00, 0xff, 0x96, 0xc8, 0x96, 0x90, 0xe7, 0x23, 0xe9, 0x08, 0x80, 0x29, 0x3e, 0x09, 0x12, 0x88, +0x49, 0xff, 0xb9, 0x88, 0x48, 0x00, 0x00, 0xf0, 0x84, 0xa2, 0x4c, 0x92, 0xc0, 0x07, 0x2e, 0x01, +0x90, 0x3c, 0x84, 0xa1, 0x4c, 0x02, 0x80, 0xe8, 0xca, 0x0c, 0x44, 0x10, 0x00, 0xe0, 0x42, 0x94, +0x84, 0x24, 0x3e, 0x39, 0x8e, 0x7c, 0x89, 0x23, 0x10, 0x24, 0x80, 0x00, 0x48, 0x00, 0x00, 0xdc, +0x44, 0xa0, 0x00, 0xe0, 0x42, 0xa4, 0xa8, 0x24, 0x3e, 0x79, 0x8e, 0x7c, 0x40, 0x65, 0x1c, 0x00, +0x50, 0x63, 0x00, 0x88, 0x84, 0x81, 0x10, 0x43, 0x7f, 0x78, 0x50, 0x8f, 0x80, 0x04, 0x10, 0x33, +0x7f, 0x79, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x84, 0xf8, 0x44, 0x10, 0x02, 0x4c, 0x80, 0x48, +0x84, 0x00, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x44, 0x10, 0x02, 0x50, 0x15, 0xc3, 0x7f, 0xeb, +0x80, 0x48, 0x84, 0x00, 0xdd, 0x27, 0xf3, 0x01, 0x44, 0x10, 0x02, 0x64, 0x14, 0x33, 0x7f, 0xec, +0x80, 0x48, 0x84, 0x00, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x44, 0x10, 0x02, 0x78, 0x15, 0xc3, +0x7f, 0xed, 0x80, 0x48, 0x84, 0x00, 0xdd, 0x27, 0xf3, 0x01, 0x44, 0x10, 0x02, 0x4c, 0x14, 0x33, +0x7f, 0xee, 0x80, 0x48, 0x84, 0x01, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x44, 0x10, 0x02, 0x50, +0x15, 0xc3, 0x7f, 0xef, 0x80, 0x48, 0x84, 0x01, 0xdd, 0x27, 0xf3, 0x01, 0x44, 0x10, 0x02, 0x64, +0x14, 0x33, 0x7f, 0xf0, 0x80, 0x48, 0x84, 0x01, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x80, 0x48, +0x15, 0xc3, 0x7f, 0xf1, 0x44, 0x10, 0x02, 0x78, 0x84, 0x01, 0xdd, 0x27, 0xf1, 0x01, 0x46, 0x00, +0x04, 0x12, 0x14, 0x13, 0x7f, 0xf2, 0x04, 0x10, 0x01, 0xdd, 0x46, 0x20, 0x0f, 0xf0, 0x40, 0x10, +0x88, 0x02, 0x14, 0x13, 0x7f, 0xf3, 0x04, 0x10, 0x01, 0xe6, 0xb6, 0x26, 0x04, 0x10, 0x01, 0xe7, +0xa8, 0x71, 0x04, 0x10, 0x01, 0xe8, 0xa8, 0x72, 0x04, 0x10, 0x01, 0xe9, 0xa8, 0x73, 0x04, 0x10, +0x01, 0xf0, 0xa8, 0x74, 0x04, 0x10, 0x01, 0xf1, 0xa8, 0x75, 0x04, 0x10, 0x01, 0xf2, 0xa8, 0x76, +0x04, 0x00, 0x01, 0xf3, 0x50, 0xa5, 0x00, 0xa8, 0x46, 0x50, 0x04, 0x12, 0x80, 0x85, 0x80, 0x64, +0x80, 0x43, 0x80, 0x22, 0x3e, 0x79, 0x8e, 0x7c, 0xa8, 0x37, 0x40, 0x65, 0x1c, 0x00, 0x84, 0x00, +0x14, 0x02, 0x83, 0x14, 0x9c, 0x01, 0x04, 0xa2, 0x03, 0x18, 0x04, 0x81, 0x83, 0x19, 0x05, 0xc1, +0x03, 0x1c, 0x04, 0x70, 0x83, 0x1d, 0x55, 0xce, 0x00, 0x7f, 0x41, 0xce, 0x20, 0x08, 0x54, 0x73, +0x80, 0x7f, 0x40, 0x7e, 0x1c, 0x04, 0x47, 0xc7, 0xf0, 0x00, 0x40, 0xa5, 0x40, 0x08, 0x40, 0xa5, +0x70, 0x02, 0x40, 0x73, 0xa8, 0x04, 0x46, 0xa0, 0x07, 0xf0, 0x40, 0x84, 0x20, 0x08, 0x40, 0x84, +0x28, 0x02, 0x40, 0x73, 0xa0, 0x04, 0x87, 0x84, 0xab, 0xf1, 0x4c, 0x0e, 0x7f, 0xdb, 0x80, 0x01, +0x44, 0x10, 0x00, 0xe0, 0x42, 0x14, 0x84, 0x24, 0x04, 0x00, 0x02, 0x06, 0x3e, 0x29, 0x8e, 0x7c, +0x98, 0x4a, 0x50, 0x10, 0x80, 0xb8, 0xb6, 0x01, 0x80, 0x03, 0x04, 0x20, 0x02, 0x07, 0xa8, 0x89, +0x04, 0x20, 0x02, 0x08, 0xa8, 0x8a, 0x04, 0x20, 0x02, 0x09, 0xa8, 0x8b, 0x04, 0x20, 0x02, 0x0a, +0xa8, 0x8c, 0x04, 0x20, 0x02, 0x0b, 0xa8, 0x8d, 0x04, 0x20, 0x01, 0xcf, 0xa8, 0x8e, 0x04, 0x20, +0x03, 0x04, 0xa8, 0x8f, 0x04, 0x20, 0x03, 0x05, 0x14, 0x20, 0x80, 0x08, 0x04, 0x00, 0x02, 0x05, +0x14, 0x00, 0x80, 0x09, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0xef, 0xf8, 0x84, 0x00, 0xf0, 0x81, 0x3e, 0x69, 0x2d, 0x5c, 0xa6, 0xf0, 0x84, 0xa9, 0x3e, 0x09, +0x12, 0x9c, 0x80, 0x23, 0xdb, 0x0e, 0x02, 0x83, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x01, 0x80, 0x28, +0x80, 0x4a, 0x84, 0x00, 0x49, 0xff, 0xf1, 0x64, 0x80, 0x28, 0x80, 0x4a, 0x84, 0x01, 0xd5, 0x06, +0xe6, 0x62, 0xe8, 0x07, 0xa4, 0x71, 0xa0, 0xb1, 0x80, 0x03, 0x49, 0xff, 0xf1, 0x59, 0xd5, 0x03, +0x49, 0xff, 0xb8, 0x70, 0x8c, 0xc8, 0x3e, 0x59, 0x2d, 0x74, 0xde, 0xe0, 0x50, 0x8f, 0x80, 0x04, +0x80, 0x48, 0x44, 0x10, 0x00, 0x34, 0x84, 0x00, 0x49, 0xff, 0xfc, 0xe8, 0xf2, 0x01, 0x44, 0x10, +0x00, 0x34, 0x58, 0x21, 0x00, 0x01, 0x84, 0x00, 0x49, 0xff, 0xf1, 0x42, 0x80, 0x48, 0x44, 0x10, +0x00, 0x34, 0x84, 0x01, 0x49, 0xff, 0xfc, 0xda, 0xf2, 0x01, 0x84, 0x01, 0x40, 0x21, 0x00, 0x04, +0x44, 0x10, 0x00, 0x34, 0x49, 0xff, 0xf1, 0x34, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x97, 0x80, 0x84, 0x60, 0x50, 0x2f, 0x80, 0x04, 0x80, 0x06, +0x80, 0xe1, 0xf3, 0x81, 0x49, 0xff, 0xfc, 0xc2, 0x3c, 0x2c, 0x4e, 0xb4, 0x3e, 0x09, 0x7f, 0x30, +0x38, 0x60, 0x08, 0x08, 0xf1, 0x01, 0x3e, 0x09, 0x7f, 0x50, 0x9d, 0x11, 0x38, 0x70, 0x0a, 0x0a, +0x3e, 0x09, 0x7f, 0xd0, 0x38, 0x10, 0x0a, 0x0a, 0x3c, 0x4e, 0x4e, 0xb4, 0x5e, 0xf2, 0x00, 0x21, +0xe9, 0x05, 0x3e, 0x09, 0x12, 0xb8, 0x49, 0xff, 0xb8, 0x25, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x97, 0xc0, 0x84, 0x00, 0x3e, 0x01, +0x3a, 0x82, 0x3e, 0x01, 0x3a, 0x80, 0x3e, 0x01, 0x3a, 0x81, 0x84, 0x01, 0x54, 0xa0, 0x80, 0xff, +0x4c, 0x70, 0x40, 0x09, 0x2e, 0x61, 0x3a, 0x7a, 0x4c, 0x63, 0xc0, 0x12, 0x3e, 0x09, 0x12, 0xd4, +0xd5, 0x08, 0xcf, 0x0d, 0x2e, 0x61, 0x3a, 0x7b, 0x84, 0xa1, 0xde, 0x09, 0x3e, 0x09, 0x12, 0xf8, +0x49, 0xff, 0xb8, 0x00, 0x3e, 0x61, 0x3a, 0x7f, 0x48, 0x00, 0x01, 0x45, 0x84, 0x20, 0x3e, 0x11, +0x3a, 0x7f, 0xcf, 0x67, 0x46, 0x90, 0x00, 0x89, 0x58, 0x94, 0x8b, 0x60, 0x46, 0x80, 0x00, 0x87, +0x58, 0x84, 0x0d, 0xbc, 0x50, 0x6f, 0x80, 0x04, 0x47, 0xc0, 0x00, 0x89, 0x59, 0xce, 0x04, 0xf8, +0x80, 0x07, 0x84, 0x20, 0xdd, 0x29, 0x46, 0x28, 0x00, 0x56, 0x58, 0x21, 0x0e, 0x53, 0x80, 0x07, +0x84, 0x20, 0xdd, 0x28, 0x80, 0x07, 0x84, 0x24, 0xdd, 0x29, 0x44, 0x24, 0x01, 0x2c, 0x80, 0x07, +0x84, 0x24, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0x46, 0x23, 0x00, 0x70, +0x58, 0x21, 0x00, 0x06, 0x80, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, +0x02, 0x44, 0xdd, 0x29, 0x44, 0x21, 0x01, 0x03, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x28, +0x80, 0x07, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x29, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, +0x80, 0x07, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x29, +0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, +0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x29, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x80, 0x46, +0xdd, 0x3c, 0xf3, 0x01, 0x44, 0x10, 0x80, 0x80, 0x40, 0x31, 0x84, 0x04, 0xf3, 0x81, 0x80, 0x07, +0x80, 0x43, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x28, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xaa, 0xd5, 0x67, +0x84, 0xe0, 0x46, 0x90, 0x00, 0x89, 0x58, 0x94, 0x8b, 0x60, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, +0x0d, 0xbc, 0x50, 0x6f, 0x80, 0x04, 0x47, 0xc0, 0x00, 0x89, 0x59, 0xce, 0x04, 0xf8, 0x80, 0x07, +0x84, 0x20, 0xdd, 0x29, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0e, 0x57, 0x80, 0x07, 0x84, 0x20, +0xdd, 0x28, 0x80, 0x07, 0x84, 0x24, 0xdd, 0x29, 0x44, 0x24, 0x01, 0x23, 0x80, 0x07, 0x84, 0x24, +0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0x46, 0x23, 0x00, 0x70, 0x58, 0x21, +0x00, 0x06, 0x80, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, +0xdd, 0x29, 0x44, 0x21, 0x01, 0x03, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x28, 0x80, 0x07, +0x44, 0x10, 0x01, 0x14, 0xdd, 0x29, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x80, 0x07, +0x44, 0x10, 0x01, 0x14, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x29, 0x46, 0x20, +0xa8, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, 0x80, 0x07, +0x44, 0x10, 0x02, 0x10, 0xdd, 0x29, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x80, 0x46, 0xdd, 0x3c, +0xf3, 0x01, 0x44, 0x10, 0x80, 0x80, 0x40, 0x31, 0x84, 0x04, 0xf3, 0x81, 0x80, 0x07, 0x80, 0x43, +0x44, 0x10, 0x02, 0x10, 0xdd, 0x28, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xaa, 0x44, 0x00, 0x27, 0x14, +0x49, 0xff, 0xfb, 0x8c, 0x46, 0x70, 0x04, 0x12, 0x46, 0x00, 0x04, 0x12, 0x46, 0x50, 0x00, 0x8a, +0x80, 0x87, 0x80, 0x44, 0x46, 0x38, 0x00, 0x00, 0x58, 0x00, 0x00, 0x88, 0x58, 0x52, 0x8c, 0x50, +0x84, 0xc0, 0x44, 0x10, 0x00, 0x83, 0xa9, 0xbc, 0xb6, 0xa0, 0x14, 0x12, 0x01, 0xc5, 0x14, 0x31, +0x01, 0xc6, 0x80, 0xe0, 0xb4, 0x47, 0x84, 0x0a, 0x54, 0x11, 0x00, 0x10, 0xf2, 0x81, 0xc1, 0x08, +0x49, 0xff, 0xef, 0xde, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf5, 0xd5, 0x04, 0x5c, 0xf3, +0x00, 0x64, 0xe9, 0x0c, 0x80, 0x26, 0x3e, 0x09, 0x0f, 0x78, 0x49, 0xff, 0xb6, 0xfb, 0x84, 0x20, +0x3c, 0x18, 0xbf, 0x3f, 0x3c, 0x18, 0xbf, 0x3e, 0xd5, 0x39, 0x46, 0x00, 0x04, 0x12, 0x04, 0x30, +0x00, 0x23, 0x4e, 0xa3, 0x00, 0x07, 0x40, 0x21, 0xc0, 0x09, 0x96, 0x90, 0x96, 0x58, 0xd5, 0x06, +0x40, 0x11, 0xa0, 0x09, 0x96, 0x48, 0x40, 0x21, 0xe0, 0x09, 0x3c, 0x18, 0xbf, 0x3e, 0x3c, 0x28, +0xbf, 0x3f, 0x3c, 0x14, 0xbf, 0x3e, 0x5e, 0xf0, 0x80, 0x80, 0xe9, 0x05, 0x50, 0x10, 0xff, 0x00, +0x3c, 0x18, 0xbf, 0x3e, 0x3c, 0x14, 0xbf, 0x3f, 0x5e, 0xf0, 0x80, 0x80, 0xe9, 0x05, 0x50, 0x10, +0xff, 0x00, 0x3c, 0x18, 0xbf, 0x3f, 0x46, 0x10, 0x04, 0x12, 0x84, 0x40, 0x80, 0x01, 0x14, 0x20, +0x81, 0xc6, 0x84, 0x21, 0xa8, 0x44, 0xa8, 0x84, 0x3c, 0x24, 0xbf, 0x3f, 0x3c, 0x14, 0xbf, 0x3e, +0x3e, 0x09, 0x0f, 0x80, 0xf3, 0x81, 0x49, 0xff, 0xb6, 0xbd, 0x49, 0xff, 0xef, 0xbf, 0x49, 0xff, +0xfa, 0xf7, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xa4, 0x96, 0x00, 0xf0, 0x85, 0x46, 0x20, 0x04, 0x12, 0xf4, 0x05, 0x84, 0x00, 0x96, 0x48, +0x58, 0x21, 0x0c, 0x04, 0x84, 0x64, 0x58, 0x42, 0x00, 0x80, 0xf0, 0x8a, 0xf1, 0x8b, 0xf2, 0x90, +0xf3, 0x89, 0xf0, 0x8d, 0xf0, 0x8e, 0xf0, 0x8f, 0xf0, 0x88, 0xf0, 0x86, 0xf4, 0x93, 0xf0, 0x0b, +0x46, 0x90, 0x00, 0x87, 0x58, 0x94, 0x8d, 0xbc, 0x4e, 0x02, 0x00, 0x87, 0xf0, 0x05, 0x84, 0x20, +0x49, 0xff, 0xfe, 0x48, 0xf0, 0x05, 0x46, 0x28, 0x00, 0x56, 0x58, 0x21, 0x07, 0x57, 0x84, 0x20, +0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x00, 0x10, 0x49, 0xff, 0xfe, 0x3c, 0xf0, 0x05, 0x46, 0x23, +0x0d, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, +0x02, 0x44, 0x49, 0xff, 0xfe, 0x2f, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x80, +0xdd, 0x29, 0xf0, 0x05, 0x44, 0x21, 0x01, 0x40, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x29, 0xf0, 0x05, +0x44, 0x10, 0x00, 0x58, 0x49, 0xff, 0xfe, 0x1e, 0xf0, 0x05, 0x44, 0x10, 0x00, 0x54, 0x49, 0xff, +0xfe, 0x19, 0xf0, 0x05, 0x46, 0x26, 0x57, 0xc0, 0x44, 0x10, 0x00, 0x58, 0xdd, 0x29, 0xf0, 0x05, +0x46, 0x20, 0x15, 0xac, 0x58, 0x21, 0x0a, 0x00, 0x44, 0x10, 0x00, 0x54, 0xdd, 0x29, 0xf0, 0x05, +0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xfe, 0x06, 0x2e, 0x61, 0x3a, 0x7a, 0xf0, 0x05, 0x56, 0x63, +0x00, 0x01, 0x85, 0x06, 0x84, 0xec, 0x40, 0x23, 0x98, 0x1a, 0x40, 0x24, 0x18, 0x1b, 0x44, 0x10, +0x01, 0x14, 0xf2, 0x8c, 0x46, 0x70, 0x04, 0x10, 0x49, 0xff, 0xfd, 0xf4, 0xf0, 0x05, 0x46, 0x20, +0x0c, 0x21, 0x58, 0x21, 0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x84, 0xc8, 0xdd, 0x29, 0x14, 0x63, +0x81, 0x48, 0x94, 0x76, 0xf0, 0x05, 0x84, 0xe0, 0x49, 0xff, 0xfd, 0xe4, 0xf0, 0x05, 0x46, 0x20, +0x50, 0x00, 0x58, 0x21, 0x01, 0x0f, 0x94, 0x76, 0xdd, 0x29, 0xf0, 0x05, 0x94, 0x76, 0x50, 0x2f, +0x80, 0x50, 0x49, 0xff, 0xfa, 0xa3, 0xf1, 0x14, 0x9d, 0xf9, 0x54, 0x10, 0x81, 0x00, 0x97, 0xf9, +0x84, 0x05, 0x4e, 0x12, 0x00, 0x8c, 0x49, 0xff, 0xee, 0xeb, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x70, +0x7f, 0xee, 0x48, 0x00, 0x00, 0x84, 0xf0, 0x05, 0xf1, 0x0b, 0x49, 0xff, 0xfd, 0xc3, 0xf1, 0x0b, +0xf0, 0x05, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0f, 0x53, 0xdd, 0x29, 0xf0, 0x05, 0x84, 0x24, +0x49, 0xff, 0xfd, 0xb8, 0xf0, 0x05, 0x44, 0x24, 0x01, 0x2c, 0x84, 0x24, 0xdd, 0x29, 0xf0, 0x05, +0x44, 0x10, 0x00, 0x10, 0x49, 0xff, 0xfd, 0xae, 0xf0, 0x05, 0x46, 0x23, 0x0d, 0x70, 0x58, 0x21, +0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, +0xfd, 0xa1, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xfd, 0x9c, 0x2e, 0x61, 0x3a, 0x7b, +0x84, 0x81, 0x4c, 0x62, 0x40, 0x0b, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x30, +0xdd, 0x29, 0x84, 0x0d, 0xf0, 0x8c, 0xd5, 0x09, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, +0x01, 0x70, 0xdd, 0x29, 0x84, 0x26, 0xf1, 0x8c, 0xf0, 0x05, 0x44, 0x10, 0x01, 0x14, 0x49, 0xff, +0xfd, 0x81, 0x46, 0x20, 0x0c, 0x21, 0xf0, 0x05, 0x58, 0x21, 0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, +0x49, 0xff, 0xee, 0xa6, 0xf0, 0x05, 0x44, 0x10, 0x00, 0x44, 0x49, 0xff, 0xfd, 0x73, 0x46, 0x70, +0x04, 0x10, 0xf0, 0x05, 0x46, 0x20, 0x04, 0x92, 0x58, 0x21, 0x00, 0x16, 0x44, 0x10, 0x00, 0x44, +0x84, 0xc8, 0x49, 0xff, 0xee, 0x95, 0x14, 0x63, 0x81, 0x48, 0x94, 0x76, 0xf0, 0x05, 0x84, 0xe0, +0x49, 0xff, 0xfd, 0x60, 0xf0, 0x05, 0x46, 0x20, 0x50, 0x00, 0x58, 0x21, 0x01, 0x0f, 0x94, 0x76, +0x49, 0xff, 0xee, 0x86, 0xf0, 0x05, 0x94, 0x76, 0x50, 0x2f, 0x80, 0x50, 0x49, 0xff, 0xfa, 0x1e, +0xf1, 0x14, 0x9d, 0xf9, 0x54, 0x10, 0x81, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, +0xee, 0x67, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x70, 0x7f, 0xef, 0x46, 0x70, 0x04, 0x10, 0x84, 0xc2, +0x14, 0x63, 0x81, 0x48, 0x46, 0x80, 0x00, 0x89, 0x58, 0x84, 0x04, 0xb8, 0x44, 0x00, 0x20, 0x04, +0xdd, 0x28, 0x44, 0x00, 0x27, 0x04, 0xdd, 0x28, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x28, 0x44, 0x00, +0x27, 0x14, 0xdd, 0x28, 0x46, 0x70, 0x04, 0x12, 0x44, 0x00, 0x20, 0x88, 0xdd, 0x28, 0x44, 0x00, +0x23, 0x00, 0x44, 0x60, 0x74, 0x08, 0xdd, 0x28, 0x14, 0x63, 0x80, 0xc0, 0x44, 0x00, 0x10, 0x04, +0xdd, 0x28, 0xf1, 0x09, 0x46, 0x70, 0x04, 0x11, 0x84, 0x40, 0x9e, 0x49, 0x58, 0x73, 0x80, 0x04, +0x84, 0xc8, 0x46, 0x90, 0x04, 0x12, 0x80, 0x09, 0x81, 0x40, 0xf1, 0x91, 0x50, 0x33, 0x90, 0x0c, +0xb6, 0x47, 0x84, 0x81, 0xb6, 0xc7, 0x84, 0xc2, 0xb6, 0x47, 0x14, 0x24, 0x80, 0x01, 0x80, 0xe0, +0xb6, 0x83, 0xb6, 0x43, 0x14, 0x10, 0x03, 0x14, 0x14, 0x65, 0x00, 0x22, 0xf3, 0x84, 0xf4, 0x83, +0xf2, 0x82, 0x44, 0x00, 0x20, 0x80, 0x44, 0x63, 0x00, 0x01, 0xdd, 0x28, 0x14, 0x63, 0x80, 0x20, +0x46, 0x70, 0x04, 0x12, 0x44, 0x00, 0x20, 0x84, 0x44, 0x62, 0x00, 0x00, 0xdd, 0x28, 0x14, 0x63, +0x80, 0x21, 0x44, 0x00, 0x2c, 0xb8, 0xdd, 0x28, 0x46, 0x60, 0x04, 0x12, 0xf2, 0x02, 0x14, 0x23, +0x03, 0x2e, 0x83, 0x86, 0x84, 0x05, 0xf2, 0x82, 0x49, 0xff, 0xee, 0x02, 0x04, 0x6e, 0x03, 0x04, +0x92, 0xc3, 0x95, 0xb3, 0x46, 0xa0, 0x04, 0x12, 0x14, 0x6e, 0x03, 0x04, 0x44, 0x60, 0x0b, 0x0b, +0x14, 0x65, 0x01, 0xc1, 0x81, 0x2a, 0xf1, 0x13, 0x81, 0x09, 0x46, 0x7c, 0x00, 0x02, 0x58, 0x73, +0x81, 0x01, 0x14, 0x14, 0x81, 0xc5, 0x14, 0x74, 0x01, 0xc6, 0x44, 0x00, 0x00, 0x32, 0x49, 0xff, +0xed, 0xe7, 0xf2, 0x02, 0x46, 0x00, 0x00, 0x88, 0xf2, 0x87, 0xf2, 0x11, 0x58, 0x00, 0x00, 0x80, +0x40, 0x61, 0x40, 0x08, 0x40, 0x03, 0x00, 0x04, 0xf0, 0x92, 0x04, 0x9f, 0x80, 0x0c, 0x46, 0x30, +0x04, 0x12, 0xf1, 0x12, 0x84, 0x81, 0xf0, 0x05, 0xa9, 0x1c, 0x84, 0x80, 0xa9, 0x1c, 0x40, 0x74, +0x84, 0x04, 0x40, 0x64, 0xa0, 0x08, 0x40, 0x23, 0x98, 0x04, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, +0xed, 0xd7, 0xf0, 0x05, 0x50, 0x2f, 0x80, 0x54, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xf9, 0x6e, +0x44, 0x00, 0x2c, 0x08, 0x49, 0xff, 0xf9, 0x4a, 0x46, 0x60, 0x04, 0x12, 0xf0, 0x05, 0x14, 0x03, +0x03, 0x02, 0x80, 0xe6, 0x84, 0x03, 0x49, 0xff, 0xed, 0xb3, 0x44, 0x60, 0x04, 0x0c, 0x44, 0x00, +0x2c, 0x14, 0x49, 0xff, 0xf9, 0x3b, 0x14, 0x63, 0x83, 0x05, 0x44, 0x00, 0x2c, 0x04, 0x49, 0xff, +0xf9, 0x35, 0xf2, 0x10, 0x44, 0x60, 0x00, 0x93, 0xb6, 0xc2, 0xf6, 0x0a, 0xd5, 0x07, 0x9d, 0xb1, +0x49, 0xff, 0xed, 0x9e, 0x5c, 0xf3, 0x00, 0xc8, 0xe8, 0x07, 0xf4, 0x10, 0x84, 0x0a, 0xb4, 0x24, +0x54, 0x10, 0x80, 0x80, 0xc9, 0xf5, 0x46, 0xa0, 0x07, 0xff, 0x58, 0xa5, 0x0f, 0xff, 0x46, 0x10, +0x04, 0x12, 0x58, 0x10, 0x8c, 0x28, 0x80, 0xaa, 0xf6, 0x8a, 0x47, 0xc3, 0xff, 0xff, 0x9e, 0x8c, +0xf7, 0x0d, 0xf6, 0x0e, 0x14, 0x9f, 0x80, 0x0c, 0x81, 0x41, 0x59, 0xce, 0x0f, 0xff, 0x85, 0x00, +0x81, 0x22, 0x80, 0x25, 0xb7, 0x09, 0xb4, 0x0a, 0xe7, 0x02, 0xe8, 0x0a, 0xe2, 0x20, 0xe8, 0x14, +0x46, 0x3f, 0xf0, 0x00, 0x40, 0x00, 0x20, 0x08, 0x92, 0x08, 0x98, 0x03, 0xd5, 0x0d, 0x84, 0x84, +0x4c, 0x82, 0x40, 0x0b, 0x40, 0xfe, 0x00, 0x06, 0xe8, 0x07, 0x46, 0x38, 0x00, 0x00, 0x42, 0x00, +0x7c, 0x09, 0x98, 0x03, 0xd5, 0x12, 0x4e, 0x83, 0x00, 0x05, 0x90, 0x0c, 0xf0, 0x86, 0xd5, 0x14, +0x84, 0x81, 0x4c, 0x82, 0x40, 0x05, 0x90, 0x0c, 0xf0, 0x88, 0xd5, 0x0e, 0x84, 0x42, 0x4c, 0x81, +0x40, 0x05, 0x90, 0x0c, 0xf0, 0x8f, 0xd5, 0x08, 0x90, 0x0c, 0x56, 0x34, 0x00, 0x03, 0x40, 0x70, +0x0c, 0x1b, 0x40, 0x60, 0x0c, 0x1a, 0x84, 0x0a, 0xf1, 0x84, 0x8d, 0x01, 0x49, 0xff, 0xed, 0x48, +0x84, 0x85, 0xf1, 0x04, 0x4c, 0x82, 0x7f, 0xc8, 0xf6, 0x8e, 0xf0, 0x06, 0xf6, 0x0f, 0xf1, 0x06, +0x42, 0x60, 0x00, 0x75, 0xf2, 0x08, 0xf3, 0x0f, 0xf4, 0x0e, 0x3e, 0x09, 0x13, 0x1c, 0x80, 0xa7, +0x04, 0x9f, 0x80, 0x0c, 0xf7, 0x8d, 0xb6, 0xdf, 0x49, 0xff, 0xb4, 0x5c, 0xf1, 0x0b, 0x84, 0x41, +0x4c, 0x11, 0x00, 0x29, 0xf3, 0x09, 0x84, 0x84, 0x4c, 0x32, 0x40, 0x25, 0x5c, 0xf3, 0x2b, 0xf2, +0xe9, 0x03, 0x8f, 0x21, 0xd5, 0x0e, 0x5c, 0xf3, 0x07, 0x08, 0xe8, 0x1c, 0x5c, 0xf3, 0x01, 0xc3, +0xe8, 0x03, 0x8d, 0x25, 0xd5, 0x11, 0x5c, 0xf3, 0x02, 0xae, 0xe8, 0x03, 0x8d, 0x24, 0xd5, 0x0c, +0x5c, 0xf3, 0x04, 0x23, 0xe8, 0x03, 0x8d, 0x23, 0xd5, 0x07, 0x5c, 0xf3, 0x05, 0x49, 0xe8, 0x03, +0x8d, 0x22, 0xd5, 0x02, 0x8d, 0x21, 0xf0, 0x07, 0x84, 0x26, 0x9c, 0x01, 0xf0, 0x87, 0x4c, 0x00, +0xff, 0x30, 0xf2, 0x06, 0xf6, 0x0f, 0x45, 0xc0, 0x00, 0x64, 0x42, 0x61, 0x08, 0x75, 0x42, 0x03, +0x70, 0x24, 0x49, 0xff, 0xed, 0x4d, 0xf6, 0x0e, 0xf3, 0x08, 0x80, 0x40, 0x42, 0x61, 0x8c, 0x75, +0xf2, 0x82, 0x42, 0x03, 0x70, 0x24, 0x49, 0xff, 0xed, 0x43, 0x81, 0x40, 0xf2, 0x02, 0xc0, 0x2a, +0xc2, 0x29, 0x44, 0x60, 0x03, 0xe8, 0x42, 0x60, 0x18, 0x24, 0xf4, 0x08, 0x40, 0x63, 0x09, 0x36, +0xf0, 0x06, 0xf7, 0x0d, 0x85, 0x0a, 0x42, 0x72, 0x00, 0x75, 0x43, 0xc5, 0x08, 0x24, 0x42, 0x83, +0xa0, 0x24, 0x44, 0x70, 0x11, 0xe8, 0x42, 0x84, 0x1c, 0x24, 0xf1, 0x11, 0x3e, 0x09, 0x13, 0x5c, +0x50, 0x73, 0x7c, 0x18, 0x40, 0x93, 0xa4, 0x08, 0x50, 0x63, 0x03, 0xe8, 0x40, 0x24, 0x99, 0x56, +0x40, 0x74, 0x71, 0x16, 0x80, 0x62, 0xf2, 0x87, 0x80, 0x87, 0x80, 0xa7, 0x49, 0xff, 0xb3, 0xf2, +0xd5, 0x03, 0x84, 0xe0, 0xf7, 0x87, 0xf3, 0x07, 0xf4, 0x05, 0x55, 0xe3, 0x80, 0x7f, 0x54, 0x01, +0x80, 0x7f, 0xcc, 0x0a, 0x47, 0xc0, 0x04, 0x12, 0x41, 0xef, 0x20, 0x08, 0x59, 0xce, 0x0c, 0x60, +0x50, 0xae, 0x00, 0x10, 0xd5, 0x09, 0x47, 0xc0, 0x04, 0x12, 0x41, 0xef, 0x20, 0x08, 0x59, 0xce, +0x0c, 0x64, 0x50, 0xae, 0x00, 0x10, 0x15, 0xee, 0x00, 0x00, 0x46, 0x90, 0x04, 0x12, 0xb6, 0x0a, +0x04, 0x64, 0x83, 0x04, 0x58, 0x63, 0x00, 0x07, 0x14, 0x64, 0x83, 0x04, 0xf0, 0x0b, 0xc8, 0x20, +0xf1, 0x07, 0x84, 0x44, 0x54, 0x83, 0x80, 0x7f, 0x80, 0x09, 0x80, 0xe0, 0x81, 0x40, 0x83, 0xc0, +0x83, 0x80, 0xf2, 0x89, 0x54, 0x60, 0x80, 0x7f, 0x40, 0x84, 0x20, 0x08, 0x80, 0x22, 0x9e, 0x49, +0x14, 0x10, 0x03, 0x14, 0xf3, 0x05, 0xcb, 0x06, 0x14, 0x8f, 0x03, 0x18, 0x14, 0x6e, 0x03, 0x1c, +0xd5, 0x05, 0x14, 0x83, 0x83, 0x19, 0x14, 0x65, 0x03, 0x1d, 0xc9, 0xf2, 0xf1, 0x89, 0x80, 0xc9, +0x85, 0x20, 0x14, 0x93, 0x01, 0xc6, 0x46, 0x70, 0x04, 0x11, 0x58, 0x73, 0x80, 0x04, 0x49, 0xff, +0xec, 0xa5, 0x84, 0xc8, 0x49, 0xff, 0xf7, 0xdc, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, 0xf7, 0xfe, +0x92, 0x00, 0xb7, 0x27, 0xb6, 0xc7, 0xb7, 0x27, 0x46, 0xa0, 0x04, 0x12, 0x49, 0xff, 0xf7, 0xd0, +0x46, 0x70, 0x04, 0x12, 0x81, 0x07, 0x84, 0x01, 0x14, 0x94, 0x03, 0x24, 0x14, 0x93, 0x83, 0x25, +0x14, 0x05, 0x00, 0x04, 0x49, 0xff, 0xec, 0x5c, 0x14, 0x95, 0x00, 0x04, 0x84, 0x02, 0x49, 0xff, +0xec, 0x57, 0xf4, 0x0b, 0xc4, 0x06, 0xf0, 0x09, 0x9e, 0x01, 0xf0, 0x89, 0x4e, 0x03, 0xfc, 0xe1, +0xec, 0x5c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x97, 0x80, +0x3e, 0x09, 0x13, 0x88, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x84, 0xb8, 0x49, 0xff, 0xb3, 0x6a, +0x44, 0x00, 0x20, 0x04, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x44, 0x10, 0x00, 0x42, 0xa8, 0x41, +0x46, 0x90, 0x00, 0x89, 0x58, 0x94, 0x8b, 0x60, 0x80, 0x06, 0x84, 0x20, 0xdd, 0x29, 0x46, 0x28, +0x00, 0x56, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x0d, 0xbc, 0x58, 0x21, 0x0f, 0x57, 0x84, 0x20, +0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0x46, 0x23, 0x04, 0xf0, +0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, +0x02, 0x44, 0xdd, 0x29, 0x44, 0x21, 0x01, 0x00, 0x44, 0x10, 0x02, 0x44, 0x80, 0x06, 0xdd, 0x28, +0x80, 0x06, 0x44, 0x10, 0x02, 0x98, 0xdd, 0x29, 0x46, 0x20, 0x30, 0x30, 0x58, 0x21, 0x03, 0x04, +0x44, 0x10, 0x02, 0x98, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x02, 0xa8, 0xdd, 0x29, +0x44, 0x10, 0x02, 0xa8, 0x50, 0x2f, 0x80, 0x04, 0x80, 0x06, 0x49, 0xff, 0xf7, 0xa7, 0xf2, 0x01, +0x42, 0x21, 0x60, 0x09, 0x44, 0x10, 0x02, 0xa8, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, +0x01, 0x14, 0xdd, 0x29, 0x46, 0x20, 0x0c, 0x21, 0x58, 0x21, 0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, +0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x29, 0x46, 0x20, 0xab, 0x92, +0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x29, 0x44, 0x20, 0x95, 0x95, 0x44, 0x10, 0x02, 0x10, 0x80, 0x06, 0xdd, 0x28, +0x46, 0x00, 0x04, 0x12, 0x85, 0x00, 0x84, 0x21, 0xa8, 0x44, 0x14, 0x80, 0x00, 0x04, 0x44, 0x00, +0x20, 0x88, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x84, 0x22, 0x14, 0x10, 0x00, 0x22, 0x44, 0x00, +0x23, 0x00, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x44, 0x10, 0x74, 0x08, 0x14, 0x10, 0x00, 0xc0, +0x44, 0x00, 0x10, 0x04, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x00, 0x04, 0x84, 0x28, +0xb7, 0x00, 0xb6, 0x20, 0xb7, 0x00, 0x44, 0x00, 0x20, 0x80, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, +0x44, 0x13, 0x00, 0x01, 0x14, 0x10, 0x00, 0x20, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x27, 0x46, 0x00, +0x04, 0x12, 0x46, 0x1c, 0x00, 0x02, 0x58, 0x10, 0x81, 0x01, 0x14, 0x10, 0x01, 0xc6, 0x44, 0x00, +0x27, 0x3c, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x46, 0x18, 0x00, 0x00, 0x14, 0x10, 0x01, 0xcf, +0x44, 0x00, 0x27, 0x04, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x14, 0x80, 0x01, 0xc1, 0x44, 0x00, +0x27, 0x14, 0xdd, 0x27, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x27, 0x46, 0x38, 0x00, 0x00, 0x58, 0x31, +0x80, 0x12, 0x46, 0x10, 0x04, 0x12, 0x40, 0x23, 0x78, 0x08, 0x80, 0x01, 0x40, 0x21, 0x0c, 0x04, +0x58, 0x33, 0x00, 0x80, 0x14, 0x30, 0x81, 0xc5, 0x14, 0x20, 0x02, 0x4d, 0x44, 0x00, 0x29, 0x80, +0xdd, 0x27, 0x44, 0x00, 0x27, 0x00, 0xdd, 0x27, 0x46, 0x30, 0x04, 0x12, 0x46, 0x47, 0x0f, 0x20, +0x58, 0x42, 0x00, 0x06, 0x80, 0x43, 0x80, 0x02, 0x46, 0x10, 0x92, 0xf5, 0x14, 0x41, 0x82, 0x60, +0x58, 0x10, 0x89, 0x08, 0x44, 0x31, 0x00, 0x00, 0x14, 0x31, 0x01, 0xc0, 0x80, 0xe0, 0x14, 0x10, +0x01, 0xda, 0x04, 0x13, 0x81, 0xdd, 0x46, 0x20, 0x07, 0x70, 0x3e, 0x09, 0x13, 0x9c, 0x40, 0x10, +0x88, 0x02, 0x49, 0xff, 0xb2, 0x77, 0x44, 0x00, 0x03, 0xe8, 0x49, 0xff, 0xeb, 0x49, 0x04, 0x03, +0x81, 0xdd, 0x8d, 0x01, 0x54, 0x00, 0x00, 0x80, 0xc0, 0x05, 0x44, 0x50, 0x00, 0x64, 0x4c, 0x82, +0xff, 0xf4, 0x46, 0x00, 0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x14, 0x10, +0x01, 0xda, 0x04, 0x00, 0x01, 0xf4, 0xce, 0x04, 0x54, 0x10, 0x00, 0x07, 0xd5, 0x05, 0x40, 0x10, +0x10, 0x09, 0x54, 0x10, 0x80, 0x07, 0x84, 0xa7, 0xd1, 0x17, 0x9c, 0x89, 0xce, 0x0a, 0x92, 0x03, +0x94, 0x03, 0x46, 0x10, 0x04, 0x12, 0x40, 0x21, 0x00, 0x04, 0x14, 0x20, 0x81, 0xf4, 0xd5, 0x0c, +0x44, 0x1f, 0xff, 0x8f, 0x40, 0x00, 0x04, 0x02, 0x94, 0x94, 0x46, 0x10, 0x04, 0x12, 0x40, 0x01, +0x00, 0x04, 0x14, 0x00, 0x81, 0xf4, 0x49, 0xff, 0xeb, 0x41, 0x49, 0xff, 0xf6, 0x79, 0x44, 0x00, +0x10, 0x04, 0x49, 0xff, 0xf6, 0x9b, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x00, 0x04, 0x85, 0x00, +0x84, 0x28, 0xb7, 0x00, 0xb6, 0x20, 0xb7, 0x00, 0x46, 0x70, 0x04, 0x12, 0x49, 0xff, 0xf6, 0x68, +0x84, 0x01, 0xa8, 0x3c, 0x49, 0xff, 0xea, 0xfc, 0x14, 0x83, 0x80, 0x04, 0x46, 0x00, 0x04, 0x12, +0x04, 0x20, 0x01, 0xdd, 0x46, 0x30, 0x07, 0x70, 0x80, 0x26, 0x40, 0x21, 0x0c, 0x02, 0x3e, 0x09, +0x13, 0xb8, 0x49, 0xff, 0xb2, 0x17, 0x92, 0x00, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xc4, 0x96, 0x00, 0x84, 0x40, 0xb6, 0x1f, 0x96, 0x48, 0x3e, 0x09, +0x13, 0xe0, 0xf1, 0x84, 0xf2, 0x8b, 0xf2, 0x8d, 0xf2, 0x8c, 0x49, 0xff, 0xb2, 0x03, 0xf0, 0x04, +0x4e, 0x03, 0x03, 0x44, 0x80, 0x20, 0xb4, 0x1f, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x0b, 0x60, +0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x01, 0x14, +0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x01, 0x38, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x01, 0x2c, +0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x02, 0x10, +0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x26, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, +0x04, 0xb8, 0x44, 0x00, 0x27, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x26, 0x44, 0x00, +0x29, 0x34, 0xdd, 0x26, 0x44, 0x00, 0x20, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x26, +0x44, 0x00, 0x29, 0x80, 0xdd, 0x26, 0xf1, 0x04, 0xf1, 0x81, 0xf2, 0x01, 0xca, 0x2f, 0xf1, 0x01, +0x46, 0x28, 0x00, 0x56, 0xb4, 0x1f, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x0d, 0xbc, 0x58, 0x21, +0x0e, 0x53, 0xdd, 0x26, 0xb4, 0x1f, 0x46, 0x25, 0x40, 0x37, 0x44, 0x10, 0x01, 0x38, 0xdd, 0x26, +0xb4, 0x1f, 0x46, 0x20, 0x81, 0x00, 0x58, 0x21, 0x00, 0x1b, 0x44, 0x10, 0x01, 0x2c, 0xdd, 0x26, +0xb4, 0x1f, 0x44, 0x10, 0x02, 0x44, 0x44, 0x20, 0x01, 0xc0, 0xdd, 0x26, 0xf3, 0x01, 0x84, 0x44, +0x56, 0x41, 0x80, 0x01, 0x84, 0x65, 0x40, 0x01, 0x90, 0x1a, 0x40, 0x01, 0x10, 0x1b, 0x84, 0x20, +0xf0, 0x89, 0xf1, 0x82, 0x05, 0xcf, 0x80, 0x00, 0xd5, 0x1c, 0xf2, 0x01, 0x84, 0x61, 0x46, 0x60, +0x00, 0x87, 0x58, 0x63, 0x0d, 0xbc, 0x4c, 0x21, 0xc0, 0x08, 0x46, 0x28, 0x20, 0x56, 0x58, 0x21, +0x0e, 0x53, 0xb4, 0x1f, 0xd5, 0x0c, 0xb4, 0x1f, 0x44, 0x20, 0x01, 0x00, 0x44, 0x10, 0x02, 0x44, +0xdd, 0x26, 0x46, 0x28, 0x30, 0x56, 0xb4, 0x1f, 0x58, 0x21, 0x0e, 0x53, 0x84, 0x20, 0xd5, 0xd6, +0xf7, 0x09, 0xf0, 0x01, 0xf1, 0x02, 0x84, 0x46, 0x40, 0x71, 0x00, 0x1a, 0x46, 0x60, 0x00, 0x87, +0x58, 0x63, 0x0d, 0xbc, 0xc9, 0x1f, 0x44, 0x10, 0x00, 0x10, 0x80, 0x1c, 0xdd, 0x26, 0x46, 0x20, +0x04, 0x00, 0x58, 0x21, 0x08, 0xb1, 0x80, 0x1c, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf2, 0x01, +0xca, 0x07, 0x80, 0x1c, 0x44, 0x10, 0x02, 0x10, 0x44, 0x20, 0x88, 0x88, 0xdd, 0x26, 0x46, 0x20, +0xa8, 0x98, 0x58, 0x21, 0x03, 0xbc, 0x80, 0x1c, 0x44, 0x10, 0x01, 0x30, 0x49, 0xff, 0xea, 0x38, +0xd5, 0x11, 0x46, 0x20, 0x04, 0x21, 0x58, 0x21, 0x08, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x80, 0x1c, +0xdd, 0x26, 0x46, 0x20, 0xa8, 0x90, 0x80, 0x1c, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, +0xdd, 0x26, 0x84, 0x61, 0x44, 0x10, 0x02, 0x4c, 0x50, 0x2f, 0x80, 0x30, 0x80, 0x1c, 0x40, 0x91, +0x9c, 0x0c, 0x49, 0xff, 0xf5, 0xbb, 0x46, 0x30, 0x04, 0x12, 0xf3, 0x87, 0xf3, 0x85, 0x44, 0x10, +0x02, 0x50, 0x80, 0x1c, 0x50, 0x2f, 0x80, 0x2c, 0x49, 0xff, 0xf5, 0xb0, 0xf0, 0x07, 0xf1, 0x05, +0x9f, 0xf9, 0x58, 0x00, 0x07, 0x04, 0x58, 0x10, 0x89, 0xfc, 0xf7, 0x83, 0xf0, 0x87, 0xf1, 0x85, +0x04, 0xaf, 0x80, 0x02, 0xd5, 0x04, 0xf2, 0x03, 0x9e, 0x91, 0xf2, 0x83, 0xf3, 0x03, 0xf0, 0x01, +0x9c, 0xd9, 0xf3, 0x88, 0xc8, 0x1c, 0x4e, 0xa3, 0x00, 0x09, 0xf2, 0x0c, 0x92, 0x47, 0x94, 0x97, +0x80, 0x1c, 0x40, 0x24, 0x88, 0x04, 0xd5, 0x0e, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0x53, 0xf2, 0x0c, +0x44, 0x0f, 0x80, 0xff, 0x40, 0x21, 0x00, 0x02, 0x40, 0x34, 0xa0, 0x08, 0x40, 0x21, 0x88, 0x04, +0x80, 0x1c, 0x44, 0x10, 0x02, 0x4c, 0x49, 0xff, 0xe9, 0xe3, 0xd5, 0x43, 0xf1, 0x01, 0x84, 0xa1, +0xd9, 0x20, 0x4e, 0xa3, 0x00, 0x0a, 0x46, 0x0f, 0xf8, 0x0f, 0x40, 0x34, 0xc0, 0x08, 0xf2, 0x0c, +0x58, 0x00, 0x0f, 0xff, 0xd5, 0x0b, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0xa1, 0x46, 0x08, 0x0f, 0xff, +0xf2, 0x0c, 0x40, 0x34, 0xe0, 0x08, 0x58, 0x00, 0x0f, 0xff, 0x40, 0x21, 0x00, 0x02, 0x40, 0x21, +0x88, 0x04, 0x80, 0x1c, 0x44, 0x10, 0x02, 0x4c, 0x49, 0xff, 0xe9, 0xc2, 0x48, 0x00, 0x00, 0x8f, +0xf1, 0x01, 0x84, 0xa2, 0x4c, 0x12, 0xc0, 0x88, 0x4e, 0xa3, 0x00, 0x09, 0xf2, 0x0b, 0x92, 0x47, +0x94, 0x97, 0x80, 0x1c, 0x40, 0x24, 0x88, 0x04, 0xd5, 0x0e, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0xf2, +0xf2, 0x0b, 0x44, 0x1f, 0x80, 0xff, 0x40, 0x34, 0xa0, 0x08, 0x40, 0x21, 0x04, 0x02, 0x40, 0x21, +0x88, 0x04, 0x80, 0x1c, 0x44, 0x10, 0x02, 0x50, 0x49, 0xff, 0xe9, 0xa2, 0x48, 0x00, 0x00, 0xe2, +0x46, 0x20, 0x04, 0x12, 0x80, 0x62, 0x84, 0x00, 0xa8, 0x11, 0x44, 0x23, 0x7f, 0x7f, 0x14, 0x21, +0x83, 0x3b, 0x4e, 0xa3, 0x00, 0x07, 0x46, 0x20, 0x12, 0x07, 0x58, 0x21, 0x0f, 0x7f, 0xd5, 0x05, +0x46, 0x20, 0x12, 0xa7, 0x58, 0x21, 0x0f, 0x7f, 0x14, 0x21, 0x83, 0x3b, 0x80, 0x43, 0x46, 0x38, +0x00, 0x00, 0x14, 0x31, 0x03, 0x3a, 0x4f, 0xc3, 0x00, 0x0c, 0x80, 0x82, 0x46, 0x38, 0x00, 0x00, +0x58, 0x31, 0x80, 0x12, 0x14, 0x32, 0x02, 0x4d, 0x15, 0xc1, 0x01, 0xc5, 0xd5, 0x0d, 0x80, 0x82, +0x46, 0x2c, 0x00, 0x00, 0x58, 0x21, 0x00, 0x12, 0x80, 0x64, 0x14, 0x22, 0x02, 0x4d, 0x44, 0x20, +0x00, 0x81, 0x14, 0x21, 0x81, 0xc5, 0x46, 0x60, 0x04, 0x12, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, +0xe9, 0x57, 0x46, 0x20, 0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xe0, 0xa9, 0xf4, 0x14, 0x71, +0x02, 0x60, 0x14, 0x31, 0x02, 0x60, 0x80, 0x47, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd7, 0x09, +0x49, 0xff, 0xe9, 0x46, 0xf0, 0x05, 0x9d, 0xf9, 0xb4, 0x40, 0x96, 0x94, 0x84, 0x0a, 0xc2, 0xf6, +0x46, 0x40, 0x04, 0x12, 0x46, 0x2f, 0x0f, 0x30, 0x58, 0x21, 0x00, 0x03, 0x58, 0x42, 0x09, 0x80, +0xb6, 0x44, 0x46, 0x20, 0x04, 0x12, 0x04, 0x21, 0x02, 0x61, 0xf2, 0x86, 0x4e, 0xa3, 0x00, 0x07, +0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x20, 0xd5, 0x73, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, +0x80, 0x2a, 0xd5, 0x6e, 0xf2, 0x01, 0x84, 0xa1, 0xda, 0x74, 0x46, 0x30, 0x04, 0x12, 0x44, 0x20, +0x00, 0x12, 0x80, 0x83, 0xa8, 0x99, 0x44, 0x23, 0x7f, 0x7f, 0x14, 0x22, 0x03, 0x3b, 0x4e, 0xa3, +0x00, 0x07, 0x46, 0x20, 0x14, 0x07, 0x58, 0x21, 0x0f, 0x7f, 0xd5, 0x05, 0x46, 0x20, 0x15, 0x47, +0x58, 0x21, 0x0f, 0x7f, 0x14, 0x22, 0x03, 0x3b, 0x46, 0x38, 0x00, 0x00, 0x80, 0x44, 0x14, 0x31, +0x03, 0x3a, 0x4f, 0xc3, 0x00, 0x0c, 0x80, 0x82, 0x46, 0x38, 0x00, 0x00, 0x58, 0x31, 0x80, 0x12, +0x14, 0x32, 0x02, 0x4d, 0x15, 0xc1, 0x01, 0xc5, 0xd5, 0x0d, 0x80, 0x82, 0x46, 0x2c, 0x00, 0x00, +0x58, 0x21, 0x00, 0x12, 0x80, 0x64, 0x14, 0x22, 0x02, 0x4d, 0x44, 0x20, 0x00, 0x81, 0x14, 0x21, +0x81, 0xc5, 0x46, 0x60, 0x04, 0x12, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xe8, 0xe9, 0x46, 0x20, +0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xe0, 0xa9, 0xf4, 0x14, 0x71, 0x02, 0x60, 0x14, 0x31, +0x02, 0x60, 0x80, 0x47, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd7, 0x09, 0x49, 0xff, 0xe8, 0xd8, +0xf0, 0x05, 0x9d, 0xf9, 0xb4, 0x40, 0x96, 0x94, 0x84, 0x0a, 0xc2, 0xf6, 0x46, 0x40, 0x04, 0x12, +0x46, 0x2f, 0x0f, 0x30, 0x58, 0x21, 0x00, 0x03, 0x58, 0x42, 0x09, 0x80, 0xb6, 0x44, 0x46, 0x20, +0x04, 0x12, 0x04, 0x21, 0x02, 0x61, 0xf2, 0x86, 0x4e, 0xa3, 0x00, 0x07, 0x46, 0x3f, 0x0f, 0x30, +0x58, 0x31, 0x80, 0x40, 0xd5, 0x05, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x54, 0xb6, 0x64, +0x46, 0x30, 0x04, 0x12, 0x58, 0x31, 0x89, 0x84, 0x50, 0x41, 0x83, 0x64, 0x48, 0x00, 0x00, 0xbb, +0xf2, 0x07, 0x46, 0x40, 0x04, 0x12, 0x80, 0xa4, 0x46, 0x3c, 0x00, 0x02, 0x84, 0x00, 0xb6, 0x02, +0x58, 0x31, 0x81, 0x01, 0x44, 0x20, 0x00, 0x5a, 0xa8, 0xa1, 0x14, 0x32, 0x81, 0xc6, 0x4f, 0xc3, +0x00, 0x0c, 0x46, 0x38, 0x00, 0x00, 0x80, 0x44, 0x58, 0x31, 0x80, 0x12, 0x14, 0x32, 0x02, 0x4d, +0x15, 0xc1, 0x01, 0xc5, 0xd5, 0x0a, 0x50, 0x21, 0xdf, 0x11, 0x80, 0x64, 0x14, 0x22, 0x02, 0x4d, +0x44, 0x20, 0x00, 0x81, 0x14, 0x21, 0x81, 0xc5, 0x80, 0xc5, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, +0xe8, 0x87, 0x46, 0x20, 0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xe0, 0xa9, 0xf4, 0x14, 0x71, +0x02, 0x60, 0x14, 0x31, 0x02, 0x60, 0x80, 0x47, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd7, 0x09, +0x49, 0xff, 0xe8, 0x76, 0xf0, 0x05, 0x9d, 0xf9, 0xb4, 0x40, 0x96, 0x94, 0x84, 0x0a, 0xc2, 0xf6, +0x46, 0x20, 0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x06, 0x14, 0x31, 0x02, 0x60, +0x04, 0x21, 0x02, 0x61, 0x46, 0x70, 0x04, 0x12, 0x80, 0xc7, 0x84, 0x01, 0x84, 0x20, 0xf2, 0x86, +0x14, 0x13, 0x81, 0xc6, 0xa8, 0x34, 0x49, 0xff, 0xe8, 0x5b, 0x84, 0x60, 0xa8, 0xf4, 0x4e, 0xa3, +0x00, 0x07, 0x46, 0x38, 0x00, 0x02, 0x58, 0x31, 0x81, 0x28, 0xd5, 0x05, 0x46, 0x3c, 0x00, 0x02, +0x58, 0x31, 0x81, 0x1c, 0x14, 0x33, 0x81, 0xc6, 0x4f, 0xc3, 0x00, 0x0e, 0x46, 0x50, 0x04, 0x12, +0x46, 0x48, 0x00, 0x00, 0x80, 0x65, 0x58, 0x42, 0x00, 0x12, 0x14, 0x42, 0x82, 0x4d, 0x15, 0xc1, +0x81, 0xc5, 0xd5, 0x0e, 0x46, 0x50, 0x04, 0x12, 0x46, 0x3c, 0x00, 0x00, 0x58, 0x31, 0x80, 0x12, +0x80, 0x85, 0x14, 0x32, 0x82, 0x4d, 0x44, 0x30, 0x00, 0x81, 0x14, 0x32, 0x01, 0xc5, 0x46, 0x80, +0x04, 0x12, 0x46, 0x70, 0x04, 0x12, 0x84, 0x61, 0x58, 0x84, 0x09, 0x80, 0x84, 0x00, 0xb6, 0x08, +0xa8, 0xfc, 0x80, 0x03, 0x49, 0xff, 0xe8, 0x24, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xc0, 0xa9, 0xbc, +0xb6, 0xc8, 0xb6, 0x68, 0x80, 0x66, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd6, 0x09, 0x49, 0xff, +0xe8, 0x17, 0xf0, 0x05, 0x9d, 0xb1, 0xb4, 0x60, 0x96, 0xdc, 0x84, 0x0a, 0xc3, 0xf6, 0x4e, 0xa3, +0x00, 0x0b, 0x46, 0x40, 0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x42, 0x09, 0x80, 0x58, 0x31, +0x80, 0x80, 0xd5, 0x09, 0x46, 0x40, 0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x42, 0x09, 0x80, +0x58, 0x31, 0x80, 0xa8, 0xb6, 0x64, 0x46, 0x30, 0x04, 0x12, 0x58, 0x31, 0x89, 0x84, 0x50, 0x41, +0xfd, 0x94, 0x84, 0x20, 0xb4, 0x63, 0xb6, 0x24, 0x84, 0x21, 0xf0, 0x06, 0x40, 0x30, 0x8c, 0x1a, +0x94, 0x87, 0x4e, 0xa3, 0x00, 0x15, 0x40, 0x21, 0x0c, 0x77, 0x5c, 0xf1, 0x01, 0x79, 0xe9, 0x08, +0xf2, 0x08, 0x40, 0x10, 0x88, 0x0c, 0x40, 0x10, 0x84, 0x05, 0x40, 0x94, 0x84, 0x02, 0xf3, 0x03, +0x4e, 0x35, 0x00, 0x1d, 0x84, 0x21, 0x40, 0x10, 0x8c, 0x0c, 0xd5, 0x14, 0x40, 0x21, 0x0c, 0x77, +0x5c, 0xf1, 0x01, 0xcb, 0xe9, 0x08, 0xf0, 0x08, 0x40, 0x10, 0x80, 0x0c, 0x40, 0x10, 0x84, 0x05, +0x40, 0x94, 0x84, 0x02, 0xf1, 0x03, 0x4e, 0x15, 0x00, 0x0a, 0xf2, 0x03, 0x84, 0x21, 0x40, 0x10, +0x88, 0x0c, 0x40, 0x94, 0x84, 0x04, 0x48, 0xff, 0xfd, 0xd0, 0xf3, 0x01, 0xcb, 0x09, 0xf0, 0x02, +0xc8, 0x04, 0x3e, 0x29, 0x7f, 0x18, 0xd5, 0x19, 0x3e, 0x29, 0x7f, 0x1c, 0xd5, 0x16, 0xf1, 0x01, +0x84, 0xa1, 0xd9, 0x09, 0xf3, 0x02, 0xcb, 0x04, 0x3e, 0x29, 0x7f, 0x20, 0xd5, 0x0e, 0x3e, 0x29, +0x7f, 0x24, 0xd5, 0x0b, 0xf0, 0x01, 0x84, 0xa2, 0xd8, 0x0a, 0xf2, 0x02, 0xca, 0x04, 0x3e, 0x29, +0x7f, 0x28, 0xd5, 0x03, 0x3e, 0x29, 0x7f, 0x2c, 0x38, 0x91, 0x70, 0x08, 0xf3, 0x02, 0x84, 0xa2, +0x9c, 0x59, 0x96, 0x48, 0xf1, 0x82, 0x4c, 0x12, 0xfd, 0x4d, 0xf2, 0x01, 0x84, 0xa3, 0x9c, 0x51, +0x96, 0x48, 0xf1, 0x81, 0x4c, 0x12, 0xfc, 0xfb, 0xb4, 0x3f, 0x46, 0x70, 0x00, 0x80, 0x58, 0x73, +0x8b, 0xf0, 0x3e, 0x09, 0x13, 0xf0, 0xdd, 0x27, 0xb4, 0x1f, 0x3f, 0xc9, 0x7f, 0x18, 0x38, 0x1e, +0x00, 0x00, 0x3e, 0x09, 0x14, 0x00, 0xdd, 0x27, 0xb4, 0x5f, 0x3e, 0xa9, 0x7f, 0x1c, 0x38, 0x15, +0x08, 0x00, 0x3e, 0x09, 0x14, 0x14, 0xdd, 0x27, 0xb4, 0x7f, 0x3e, 0x69, 0x7f, 0x20, 0x38, 0x13, +0x0c, 0x00, 0x3e, 0x09, 0x14, 0x28, 0xdd, 0x27, 0xb4, 0x5f, 0x3e, 0x09, 0x7f, 0x24, 0x38, 0x10, +0x08, 0x00, 0x3e, 0x09, 0x14, 0x3c, 0xdd, 0x27, 0xb4, 0x1f, 0x3e, 0x39, 0x7f, 0x28, 0x38, 0x11, +0x80, 0x00, 0x3e, 0x09, 0x14, 0x50, 0xdd, 0x27, 0xb4, 0x7f, 0x3e, 0x29, 0x7f, 0x2c, 0x38, 0x11, +0x0c, 0x00, 0x3e, 0x09, 0x14, 0x64, 0xdd, 0x27, 0x50, 0x9f, 0x80, 0x34, 0xb4, 0x1f, 0x46, 0x80, +0x00, 0x89, 0x58, 0x84, 0x04, 0xf8, 0x44, 0x10, 0x02, 0x4c, 0x80, 0x49, 0xdd, 0x28, 0xb4, 0x1f, +0xf2, 0x0d, 0x38, 0x4e, 0x00, 0x00, 0xb4, 0x7f, 0x38, 0x05, 0x00, 0x00, 0x46, 0x18, 0x08, 0x08, +0x58, 0x10, 0x80, 0x80, 0x38, 0x53, 0x0c, 0x00, 0x40, 0x21, 0x04, 0x02, 0x40, 0x60, 0x20, 0x08, +0x3e, 0x09, 0x7f, 0x24, 0x38, 0x30, 0x0c, 0x00, 0x40, 0x42, 0x08, 0x04, 0x40, 0x52, 0xc0, 0x08, +0x40, 0x42, 0x18, 0x04, 0x40, 0x42, 0x14, 0x04, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x32, 0x0c, 0x04, +0xf3, 0x8d, 0xb4, 0x1f, 0x80, 0x43, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x0d, 0xbc, 0x44, 0x10, +0x02, 0x4c, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x02, 0x50, 0x80, 0x49, 0xdd, 0x28, 0xb4, 0x5f, +0x3e, 0x39, 0x7f, 0x2c, 0x38, 0x41, 0x88, 0x00, 0x3e, 0x19, 0x7f, 0x28, 0xf3, 0x0d, 0x38, 0x50, +0x88, 0x00, 0x44, 0x0f, 0x80, 0x80, 0x40, 0x31, 0x80, 0x02, 0x40, 0x32, 0x8c, 0x04, 0x40, 0x42, +0x20, 0x08, 0x40, 0x31, 0x90, 0x04, 0xf3, 0x8d, 0xb4, 0x1f, 0x80, 0x43, 0x44, 0x10, 0x02, 0x50, +0xdd, 0x26, 0xb4, 0x1f, 0x80, 0x49, 0x44, 0x10, 0x02, 0x4c, 0xdd, 0x28, 0xf1, 0x0d, 0x3e, 0x09, +0x14, 0x78, 0xdd, 0x27, 0xb4, 0x1f, 0x80, 0x49, 0x44, 0x10, 0x02, 0x50, 0xdd, 0x28, 0xf1, 0x0d, +0x3e, 0x09, 0x14, 0x84, 0xdd, 0x27, 0xb4, 0x1f, 0x44, 0x10, 0x02, 0x64, 0x80, 0x49, 0xdd, 0x28, +0xb4, 0x3f, 0xf3, 0x0d, 0x38, 0x4e, 0x04, 0x00, 0x46, 0x28, 0x0f, 0xff, 0x58, 0x21, 0x0f, 0xff, +0x40, 0x42, 0x60, 0x08, 0x40, 0x31, 0x88, 0x02, 0xb4, 0x1f, 0x40, 0x22, 0x0c, 0x04, 0x44, 0x10, +0x02, 0x64, 0xdd, 0x26, 0xb4, 0x1f, 0x80, 0x49, 0x44, 0x10, 0x02, 0x78, 0xdd, 0x28, 0xb4, 0x1f, +0xf2, 0x0d, 0x38, 0x35, 0x00, 0x00, 0x46, 0x18, 0x0f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x31, +0xe0, 0x08, 0x40, 0x21, 0x04, 0x02, 0x40, 0x21, 0x88, 0x04, 0x44, 0x10, 0x02, 0x78, 0xdd, 0x26, +0xf2, 0x04, 0xca, 0x0d, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xe6, 0xf0, 0x49, 0xff, 0xf2, 0x28, +0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xe6, 0xbc, 0xf3, 0x04, 0xa8, 0xf4, 0xec, 0x3c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0xb5, 0x00, 0xb4, 0xe0, 0x80, 0xc0, +0x3e, 0x09, 0x14, 0x90, 0x49, 0xff, 0xad, 0xd6, 0x92, 0xff, 0x84, 0x01, 0x4c, 0x70, 0x40, 0x13, +0x9c, 0x34, 0xb4, 0x60, 0xb4, 0x40, 0xb4, 0x20, 0xb4, 0x00, 0x92, 0x48, 0x92, 0x30, 0x92, 0x18, +0x10, 0x3f, 0x80, 0x0f, 0x10, 0x2f, 0x80, 0x0e, 0x10, 0x1f, 0x80, 0x0d, 0x10, 0x0f, 0x80, 0x0c, +0xd5, 0x1b, 0x44, 0x65, 0x10, 0xf0, 0x50, 0x1f, 0x80, 0x0f, 0x84, 0x41, 0x44, 0x00, 0x00, 0x44, +0xdd, 0x26, 0x50, 0x1f, 0x80, 0x0e, 0x84, 0x41, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x50, 0x1f, +0x80, 0x0d, 0x84, 0x41, 0x44, 0x00, 0x00, 0x49, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x4d, 0x50, 0x1f, +0x80, 0x0c, 0x84, 0x41, 0xdd, 0x26, 0x00, 0x4f, 0x80, 0x0d, 0x00, 0x2f, 0x80, 0x0f, 0x00, 0x3f, +0x80, 0x0e, 0x00, 0x5f, 0x80, 0x0c, 0x80, 0x27, 0x3e, 0x09, 0x14, 0xac, 0x49, 0xff, 0xad, 0x9a, +0x00, 0x4f, 0x80, 0x0f, 0x44, 0x10, 0x00, 0xff, 0x4c, 0x40, 0x80, 0x0e, 0x00, 0x3f, 0x80, 0x0e, +0x4c, 0x30, 0x80, 0x0a, 0x00, 0x2f, 0x80, 0x0d, 0x4c, 0x20, 0x80, 0x06, 0x00, 0x0f, 0x80, 0x0c, +0x4c, 0x00, 0xc0, 0x06, 0x49, 0xff, 0xe9, 0x66, 0x48, 0x00, 0x01, 0x17, 0x54, 0x14, 0x00, 0xff, +0xe6, 0x2f, 0xe9, 0x0f, 0x2e, 0x81, 0x3a, 0x75, 0x84, 0xac, 0x56, 0x84, 0x00, 0x01, 0x84, 0x80, +0x40, 0x62, 0xa0, 0x1a, 0x40, 0x62, 0x20, 0x1b, 0x5c, 0xf0, 0x80, 0x41, 0xe8, 0x10, 0xd5, 0x0d, +0x2e, 0x31, 0x3a, 0x74, 0x84, 0x40, 0x84, 0x0c, 0x56, 0x31, 0x80, 0x01, 0x40, 0x61, 0x0c, 0x1b, +0x40, 0x60, 0x0c, 0x1a, 0x80, 0x04, 0xd5, 0x07, 0x80, 0x03, 0xd5, 0x05, 0x5c, 0x30, 0x80, 0x81, +0x40, 0x01, 0x0c, 0x1b, 0x96, 0x02, 0x4e, 0x05, 0x00, 0x09, 0x54, 0x90, 0x00, 0x7f, 0x52, 0x94, +0x80, 0x00, 0x40, 0x94, 0x80, 0x10, 0xd5, 0x03, 0x54, 0x90, 0x00, 0x7f, 0x80, 0x47, 0x80, 0x69, +0x3e, 0x09, 0x14, 0xdc, 0x40, 0x93, 0x24, 0x01, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xad, 0x4a, +0xf6, 0x81, 0x54, 0x94, 0x80, 0xff, 0x04, 0xaf, 0x80, 0x01, 0x46, 0x60, 0x04, 0x12, 0x58, 0x63, +0x03, 0x14, 0x9f, 0xf4, 0x50, 0x83, 0x00, 0x04, 0x51, 0xc4, 0x00, 0x08, 0x58, 0xa5, 0x03, 0x24, +0x40, 0x14, 0x80, 0x10, 0x3e, 0x09, 0x14, 0xfc, 0x14, 0xaf, 0x80, 0x01, 0x49, 0xff, 0xad, 0x32, +0xb4, 0x3c, 0xb4, 0x4a, 0xb4, 0x67, 0xb4, 0x86, 0xb4, 0xa8, 0x3e, 0x09, 0x15, 0x10, 0x49, 0xff, +0xad, 0x29, 0xb4, 0x1c, 0xb4, 0x5c, 0x44, 0x3f, 0x80, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x14, +0xa4, 0x00, 0xb6, 0x5c, 0x96, 0x48, 0x92, 0x08, 0x98, 0x01, 0xb4, 0x5c, 0x54, 0x00, 0x00, 0x7f, +0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x1c, 0x81, 0x43, 0xf4, 0x01, 0x3e, 0x09, +0x15, 0x50, 0xb4, 0x44, 0xb4, 0x64, 0x92, 0x48, 0x40, 0x31, 0xa8, 0x02, 0xb6, 0x64, 0x98, 0x51, +0x54, 0x10, 0x80, 0x7f, 0xb4, 0x44, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x24, +0x46, 0x3f, 0xfc, 0x0f, 0xb4, 0x27, 0xb4, 0x47, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, +0xb6, 0x47, 0x92, 0x30, 0x8a, 0x29, 0xb4, 0x47, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0xc0, 0x08, +0x40, 0x10, 0x88, 0x04, 0xb6, 0x27, 0x44, 0x4f, 0xc0, 0xff, 0xb4, 0x26, 0xb4, 0x46, 0x92, 0x30, +0x40, 0x21, 0x0c, 0x02, 0xb6, 0x46, 0x8a, 0x29, 0xb4, 0x46, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, +0xc0, 0x08, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x26, 0x44, 0xaf, 0xff, 0xc0, 0xb4, 0x27, 0xb4, 0x47, +0x92, 0x28, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x47, 0x8a, 0x29, 0xb4, 0x47, 0x54, 0x10, 0x80, 0x3f, +0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x27, 0xb4, 0x26, 0xb4, 0x46, 0x92, 0x28, +0x40, 0x21, 0x10, 0x02, 0xb6, 0x46, 0x8a, 0x29, 0xb4, 0x46, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, +0xa0, 0x08, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x26, 0xb4, 0x27, 0xb4, 0x47, 0x8a, 0x29, 0x40, 0x21, +0x28, 0x02, 0xb6, 0x47, 0xb4, 0x47, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x27, +0xb4, 0x26, 0xb4, 0x46, 0x8a, 0x29, 0x40, 0x21, 0x28, 0x02, 0xb6, 0x46, 0x54, 0x10, 0x80, 0x3f, +0xb4, 0x46, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x26, 0xb4, 0x28, 0xb4, 0x48, 0x8a, 0x29, 0x40, 0x21, +0x28, 0x02, 0xb6, 0x48, 0x54, 0x10, 0x80, 0x3f, 0xb4, 0x48, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x28, +0xb4, 0x28, 0xb4, 0x48, 0x92, 0x28, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x48, 0x40, 0x90, 0xa4, 0x01, +0x54, 0x94, 0x80, 0x3f, 0xb4, 0x28, 0x40, 0x94, 0xa0, 0x08, 0x40, 0x94, 0x84, 0x04, 0xb7, 0x28, +0xf3, 0x01, 0xb4, 0x3c, 0xb4, 0x43, 0xb4, 0x67, 0xb4, 0x86, 0xb4, 0xa8, 0x49, 0xff, 0xac, 0x82, +0x49, 0xff, 0xe8, 0x60, 0xb4, 0x3c, 0x3c, 0x1e, 0x4e, 0xb5, 0x04, 0xaf, 0x80, 0x01, 0xb4, 0x6a, +0x84, 0x00, 0x3e, 0x19, 0x7e, 0x64, 0x3c, 0x3e, 0x4e, 0xb6, 0xa8, 0x0b, 0x3c, 0x0e, 0x4e, 0x8b, +0xb6, 0x01, 0xa8, 0x09, 0xa8, 0x0a, 0x84, 0x00, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0x30, 0x04, 0x00, 0x04, 0x31, 0x80, 0x0e, 0x97, 0x80, +0x40, 0x01, 0xb4, 0x09, 0x97, 0xd0, 0x54, 0x00, 0x00, 0x07, 0x84, 0x42, 0x96, 0x48, 0x4c, 0x01, +0x00, 0x05, 0x84, 0xa1, 0xde, 0x35, 0xd5, 0x03, 0x84, 0xa1, 0xde, 0x04, 0x10, 0x1f, 0x80, 0x07, +0xd5, 0x08, 0x44, 0x00, 0x00, 0x35, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x2e, 0xca, +0x00, 0x0f, 0x80, 0x07, 0x42, 0x10, 0x04, 0x0b, 0xc9, 0x04, 0x84, 0x41, 0x3e, 0x21, 0x3a, 0x7a, +0x96, 0x04, 0xc8, 0x04, 0x84, 0x21, 0x3e, 0x11, 0x3a, 0x7b, 0x84, 0xa1, 0xde, 0x04, 0x10, 0x7f, +0x80, 0x07, 0xd5, 0x08, 0x44, 0x00, 0x00, 0x36, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, +0x2e, 0xb1, 0x00, 0x0f, 0x80, 0x07, 0x42, 0x10, 0x0c, 0x0b, 0xc1, 0x04, 0x84, 0x41, 0x3e, 0x21, +0x3a, 0x75, 0x42, 0x00, 0x08, 0x0b, 0xc0, 0x04, 0x84, 0x21, 0x3e, 0x11, 0x3a, 0x74, 0x3e, 0x09, +0x15, 0x90, 0x80, 0x26, 0x49, 0xff, 0xac, 0x1e, 0x2e, 0x11, 0x3a, 0x7a, 0x2e, 0x21, 0x3a, 0x75, +0x3e, 0x09, 0x15, 0xa4, 0x49, 0xff, 0xac, 0x16, 0x2e, 0x11, 0x3a, 0x7b, 0x2e, 0x21, 0x3a, 0x74, +0x3e, 0x09, 0x15, 0xbc, 0x49, 0xff, 0xac, 0x0e, 0x84, 0xa1, 0xde, 0x67, 0x46, 0x00, 0x04, 0x00, +0x84, 0x60, 0x14, 0x30, 0x00, 0x48, 0x80, 0x20, 0x04, 0x20, 0x80, 0x10, 0x96, 0x91, 0x14, 0x20, +0x80, 0x10, 0x04, 0x10, 0x00, 0x49, 0x46, 0x20, 0x04, 0x00, 0x14, 0x30, 0x00, 0x49, 0x58, 0x21, +0x01, 0x28, 0xb4, 0x02, 0xb6, 0x62, 0x2e, 0x57, 0xf0, 0x4d, 0xde, 0x05, 0xb4, 0x02, 0x42, 0x00, +0x7c, 0x08, 0xb6, 0x02, 0x2e, 0x01, 0x3a, 0x7a, 0x84, 0xc1, 0x4c, 0x03, 0x00, 0x0b, 0x2e, 0x51, +0x3a, 0x7b, 0xd6, 0x07, 0x2e, 0x51, 0x3a, 0x75, 0xd6, 0x04, 0x2e, 0x51, 0x3a, 0x74, 0xde, 0x32, +0x46, 0x00, 0x04, 0x00, 0x84, 0x80, 0x14, 0x40, 0x00, 0x48, 0x50, 0x01, 0x7f, 0x24, 0xb4, 0x20, +0x44, 0x2f, 0xff, 0xc5, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0x46, 0x30, 0x04, 0x00, 0xb4, 0x20, +0x58, 0x10, 0x80, 0x10, 0xb6, 0x20, 0x04, 0x01, 0x80, 0x08, 0x80, 0x43, 0x42, 0x00, 0x30, 0x09, +0x14, 0x01, 0x80, 0x08, 0x04, 0x31, 0x00, 0x20, 0x42, 0x31, 0x98, 0x09, 0x14, 0x31, 0x00, 0x20, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x24, 0xb4, 0x41, 0xb6, 0x81, 0x9c, 0x0c, 0xb4, 0x40, +0xb6, 0x80, 0xb4, 0x41, 0xb6, 0x41, 0x44, 0x27, 0x70, 0x00, 0xb4, 0x20, 0x40, 0x10, 0x88, 0x04, +0xb6, 0x20, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x24, 0x9c, 0xcc, 0xb4, 0x41, 0xb4, 0x83, +0x3e, 0x09, 0x15, 0xd4, 0x49, 0xff, 0xab, 0xa6, 0x2e, 0x21, 0x3a, 0x7b, 0xc2, 0x19, 0x46, 0x10, +0x04, 0x00, 0x04, 0x30, 0x80, 0x49, 0x46, 0x4f, 0xff, 0x00, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x31, +0x90, 0x02, 0x44, 0x57, 0x70, 0x00, 0x40, 0x31, 0x94, 0x04, 0x14, 0x30, 0x80, 0x49, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x01, 0x46, 0x58, 0x10, 0x80, 0x14, 0x14, 0x10, 0x01, 0x46, 0x2e, 0x31, +0x3a, 0x7a, 0xc3, 0x19, 0x46, 0x10, 0x04, 0x00, 0x04, 0x40, 0x80, 0x49, 0x46, 0x6f, 0x00, 0xff, +0x58, 0x63, 0x0f, 0xff, 0x46, 0x50, 0x77, 0x00, 0x40, 0x42, 0x18, 0x02, 0x40, 0x42, 0x14, 0x04, +0x14, 0x40, 0x80, 0x49, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x46, 0x58, 0x10, 0x80, 0x0a, +0x14, 0x10, 0x01, 0x46, 0x2e, 0x41, 0x3a, 0x75, 0xcc, 0x04, 0x2e, 0x01, 0x3a, 0x74, 0xc0, 0x47, +0x46, 0x10, 0x04, 0x00, 0x04, 0x50, 0x80, 0x49, 0x95, 0x6c, 0x92, 0xa4, 0x46, 0x67, 0x00, 0x00, +0x40, 0x52, 0x98, 0x04, 0x14, 0x50, 0x80, 0x49, 0x80, 0x01, 0x04, 0x10, 0x00, 0x4a, 0x92, 0x24, +0x94, 0x4c, 0x58, 0x10, 0x80, 0x07, 0x14, 0x10, 0x00, 0x4a, 0xc4, 0x31, 0x2e, 0x01, 0x3a, 0x74, +0xc8, 0x2e, 0xcb, 0x2d, 0xca, 0x2c, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x00, 0x46, 0x17, 0x61, 0x20, +0x40, 0x50, 0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, 0xd9, 0x22, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x0e, 0x84, 0xa3, 0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd8, 0x19, 0x46, 0x10, 0x04, 0x00, +0x04, 0x20, 0x80, 0x48, 0x46, 0x3f, 0xff, 0x0f, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, +0x42, 0x21, 0x40, 0x08, 0x14, 0x20, 0x80, 0x48, 0x80, 0x01, 0x04, 0x10, 0x00, 0x6e, 0x42, 0x10, +0x90, 0x09, 0x14, 0x10, 0x00, 0x6e, 0x84, 0x21, 0x3e, 0x11, 0x3a, 0x7c, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x3e, 0x09, 0x2d, 0xec, 0xb4, 0x20, +0xa0, 0x81, 0x8c, 0x08, 0xb6, 0x41, 0x3e, 0x59, 0x30, 0x1c, 0xd8, 0xfa, 0x46, 0x00, 0x04, 0x00, +0xb4, 0x00, 0x92, 0x04, 0x54, 0x00, 0x00, 0x0f, 0xe6, 0x03, 0xe9, 0x08, 0x46, 0x00, 0x04, 0x12, +0x46, 0x18, 0x70, 0x00, 0x58, 0x10, 0x83, 0x0a, 0xa8, 0x43, 0x2e, 0x01, 0x3a, 0x77, 0x84, 0xa1, +0xd8, 0x06, 0x2e, 0x01, 0x3a, 0x78, 0x10, 0x0f, 0x80, 0x07, 0xd5, 0x08, 0x44, 0x00, 0x00, 0x35, +0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x2d, 0x75, 0x00, 0x1f, 0x80, 0x07, 0x42, 0x10, +0x98, 0x0b, 0xc9, 0x05, 0x46, 0x00, 0x04, 0x12, 0x14, 0x10, 0x01, 0x02, 0x2e, 0x01, 0x3a, 0x63, +0x84, 0xa1, 0xd8, 0x09, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x02, 0x54, 0x42, 0x10, 0x80, 0x09, +0x14, 0x10, 0x02, 0x54, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xff, 0xea, 0x4d, 0x49, 0xff, 0xf2, 0x43, 0x49, 0xff, 0xff, 0xb5, 0x49, 0xff, +0xe5, 0x19, 0x49, 0xff, 0xe5, 0x81, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x96, 0x00, 0x84, 0xee, 0x2e, 0x11, 0x3a, 0x84, 0x40, 0x73, +0x80, 0x06, 0xf0, 0x82, 0x84, 0x02, 0x54, 0x91, 0x00, 0xff, 0xf7, 0x81, 0x4c, 0x10, 0x40, 0x04, +0x85, 0x08, 0xd5, 0x09, 0x56, 0x10, 0x80, 0x01, 0x84, 0x40, 0x84, 0x64, 0x40, 0x81, 0x84, 0x1a, +0x40, 0x81, 0x04, 0x1b, 0x2e, 0x11, 0x3a, 0x85, 0x84, 0xa1, 0xd9, 0x06, 0x2e, 0x31, 0x3a, 0x86, +0x4c, 0x30, 0xc0, 0x0b, 0xd5, 0x16, 0x84, 0xa2, 0xd9, 0x10, 0x2e, 0x11, 0x3a, 0x86, 0x84, 0xa1, +0xd9, 0x07, 0x95, 0x83, 0xd5, 0x0f, 0x84, 0xa2, 0xdb, 0x08, 0x95, 0x84, 0xd5, 0x0b, 0x84, 0xa2, +0xd9, 0x04, 0x44, 0x60, 0x00, 0x30, 0xd5, 0x06, 0x3e, 0x09, 0x15, 0xe8, 0x49, 0xff, 0xaa, 0x92, +0x84, 0xc0, 0x49, 0xff, 0xff, 0x71, 0xf3, 0x02, 0x50, 0x11, 0xff, 0xf4, 0x96, 0x48, 0xe6, 0x38, +0xe9, 0x05, 0x49, 0xff, 0xf1, 0xf5, 0x49, 0xff, 0xe4, 0xcd, 0xf0, 0x01, 0xc0, 0x03, 0x49, 0xff, +0xe4, 0xbf, 0xf2, 0x01, 0x40, 0x14, 0x08, 0x04, 0x40, 0x60, 0x98, 0x04, 0x3e, 0x19, 0x19, 0xf0, +0xb4, 0x01, 0x54, 0x50, 0x00, 0x3f, 0xde, 0x04, 0xa0, 0x09, 0xa0, 0x8a, 0xb6, 0x40, 0x8c, 0x2c, +0x3e, 0x59, 0x1e, 0xe8, 0xd9, 0xf6, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x0e, 0x84, 0xa1, +0x92, 0x54, 0x54, 0x21, 0x00, 0x03, 0xd2, 0x08, 0x04, 0x10, 0x80, 0x0e, 0x84, 0xa2, 0x92, 0x34, +0x54, 0x10, 0x80, 0x03, 0xd9, 0x15, 0xf3, 0x01, 0xc3, 0x1c, 0x84, 0xa4, 0x4c, 0x82, 0x80, 0x05, +0x84, 0xa8, 0x4c, 0x82, 0xc0, 0x10, 0x46, 0x40, 0x04, 0x12, 0x46, 0x11, 0xe4, 0x25, 0x80, 0x64, +0x58, 0x10, 0x8c, 0xf8, 0x14, 0x12, 0x00, 0xc8, 0x14, 0x11, 0x80, 0xc9, 0xd5, 0x03, 0xf2, 0x01, +0xc2, 0x08, 0x2e, 0x11, 0x3a, 0x75, 0x84, 0xa1, 0xd9, 0x37, 0x3e, 0x19, 0x1e, 0xe8, 0xd5, 0x06, +0x2e, 0x11, 0x3a, 0x74, 0x84, 0xa1, 0xd9, 0x30, 0xd5, 0xf9, 0xb4, 0x01, 0x54, 0x50, 0x00, 0x3f, +0xde, 0x04, 0xa0, 0x09, 0xa0, 0x8a, 0xb6, 0x40, 0x8c, 0x2c, 0x3e, 0x59, 0x21, 0xd0, 0xd9, 0xf6, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x30, 0xb4, 0x41, 0x44, 0x3f, 0xbf, 0xbf, 0x40, 0x21, +0x0c, 0x02, 0xb6, 0x41, 0xf0, 0x01, 0xc0, 0x05, 0x2e, 0x31, 0x3a, 0x7a, 0xcb, 0x09, 0xd5, 0x04, +0x2e, 0x31, 0x3a, 0x7b, 0xcb, 0x08, 0xb4, 0x41, 0x58, 0x21, 0x40, 0x40, 0xd5, 0x0c, 0x84, 0xa1, +0xdb, 0x0b, 0xd5, 0x03, 0x84, 0xa1, 0xdb, 0x08, 0x46, 0x10, 0x04, 0x12, 0x58, 0x10, 0x80, 0x88, +0x44, 0x20, 0x00, 0x40, 0xb6, 0x41, 0x2e, 0x11, 0x3a, 0x7c, 0x84, 0xa1, 0xd9, 0x04, 0xf0, 0x02, +0x49, 0xff, 0xe5, 0x92, 0x4e, 0x93, 0x01, 0x9c, 0x3e, 0x89, 0x21, 0xd0, 0x50, 0x94, 0x00, 0x08, +0x50, 0x6f, 0x80, 0x1c, 0x47, 0xc0, 0x00, 0x89, 0x59, 0xce, 0x04, 0xf8, 0x46, 0xa0, 0x00, 0x87, +0x58, 0xa5, 0x0d, 0xbc, 0xd5, 0x62, 0x00, 0x54, 0x00, 0x00, 0xf1, 0x02, 0xd9, 0x5c, 0x44, 0x10, +0x01, 0x44, 0x80, 0x46, 0x84, 0x00, 0xdd, 0x3c, 0x04, 0x74, 0x00, 0x01, 0xf4, 0x07, 0x46, 0x2f, +0xe0, 0x00, 0x58, 0x21, 0x07, 0xff, 0x54, 0x73, 0xbf, 0xff, 0x40, 0x73, 0xac, 0x08, 0x40, 0x42, +0x08, 0x02, 0x40, 0x43, 0x90, 0x04, 0x80, 0x44, 0x44, 0x10, 0x01, 0x44, 0x84, 0x00, 0xf4, 0x87, +0xdd, 0x2a, 0x44, 0x10, 0x01, 0x44, 0x80, 0x46, 0x84, 0x01, 0xdd, 0x3c, 0xf3, 0x07, 0x46, 0x0f, +0xe0, 0x00, 0x58, 0x00, 0x07, 0xff, 0x40, 0x31, 0x80, 0x02, 0x40, 0x33, 0x8c, 0x04, 0x80, 0x43, +0x44, 0x10, 0x01, 0x44, 0x84, 0x01, 0xf3, 0x87, 0xdd, 0x2a, 0x44, 0x10, 0x01, 0x58, 0x80, 0x46, +0x84, 0x00, 0xdd, 0x3c, 0xf4, 0x07, 0xb4, 0xa9, 0x04, 0x74, 0x80, 0x01, 0x54, 0x52, 0x83, 0xff, +0x54, 0x42, 0x0c, 0x00, 0x40, 0x42, 0x14, 0x04, 0x40, 0x73, 0xb0, 0x08, 0x40, 0x42, 0x1c, 0x04, +0x80, 0x44, 0x44, 0x10, 0x01, 0x58, 0x84, 0x00, 0xb6, 0xbf, 0xf4, 0x87, 0xdd, 0x2a, 0x44, 0x10, +0x01, 0x58, 0x80, 0x46, 0x84, 0x01, 0xdd, 0x3c, 0xf3, 0x07, 0xb4, 0xbf, 0x54, 0x31, 0x8c, 0x00, +0x40, 0x31, 0x94, 0x04, 0x40, 0x31, 0x9c, 0x04, 0x84, 0x01, 0x80, 0x43, 0x44, 0x10, 0x01, 0x58, +0xf3, 0x87, 0xdd, 0x2a, 0x8d, 0x10, 0x8d, 0x30, 0x3e, 0x59, 0x2b, 0xf0, 0x4c, 0x82, 0xff, 0x9d, +0x3e, 0x79, 0x2b, 0xf2, 0x50, 0x23, 0x80, 0x26, 0x84, 0x61, 0x9c, 0x7e, 0xf2, 0x83, 0xf3, 0x84, +0x51, 0xc3, 0x80, 0x1a, 0x50, 0x83, 0x80, 0x0e, 0xf7, 0x85, 0x46, 0xa0, 0x00, 0x87, 0x58, 0xa5, +0x0d, 0xbc, 0x50, 0x9f, 0x80, 0x1c, 0x80, 0xe1, 0xf1, 0x05, 0xf2, 0x02, 0xa4, 0x08, 0xe2, 0x40, +0x4e, 0xf3, 0x00, 0x80, 0xa4, 0x09, 0xe2, 0x02, 0x4e, 0xf3, 0x00, 0x7c, 0x84, 0xc0, 0x2e, 0x21, +0x3a, 0x75, 0x84, 0xa1, 0x80, 0x06, 0x44, 0x10, 0x02, 0x54, 0xda, 0x09, 0xf0, 0x03, 0xb4, 0x40, +0x80, 0x06, 0xdd, 0x2a, 0xf1, 0x03, 0x80, 0x06, 0xa0, 0x89, 0xd5, 0x05, 0xb4, 0x47, 0xdd, 0x2a, +0xa0, 0xb9, 0x80, 0x06, 0x44, 0x10, 0x02, 0x60, 0xdd, 0x2a, 0xb4, 0x48, 0x44, 0x10, 0x02, 0x9c, +0x80, 0x06, 0xdd, 0x2a, 0x2e, 0x11, 0x3a, 0x7a, 0x84, 0xa1, 0xd9, 0x20, 0xf0, 0x01, 0xc0, 0x1e, +0x44, 0x10, 0x02, 0xa8, 0x80, 0x06, 0x80, 0x49, 0x49, 0xff, 0xed, 0xd0, 0xf1, 0x07, 0x46, 0x0f, +0xe0, 0xff, 0x58, 0x00, 0x0f, 0xff, 0x40, 0x10, 0x80, 0x02, 0xce, 0x04, 0x04, 0x24, 0x00, 0x01, +0xd5, 0x03, 0x04, 0x2e, 0x7f, 0xff, 0x40, 0x21, 0x50, 0x08, 0x40, 0x11, 0x04, 0x04, 0xf1, 0x87, +0x80, 0x06, 0xf2, 0x07, 0x44, 0x10, 0x02, 0xa8, 0xdd, 0x2a, 0x80, 0x06, 0x44, 0x10, 0x02, 0x10, +0x80, 0x49, 0x49, 0xff, 0xed, 0xb3, 0xf1, 0x07, 0x02, 0x3e, 0x00, 0x00, 0x92, 0x30, 0x40, 0x10, +0xc0, 0x08, 0x40, 0x31, 0x84, 0x04, 0x80, 0x43, 0x80, 0x06, 0x44, 0x10, 0x02, 0x10, 0xf3, 0x87, +0xdd, 0x2a, 0x80, 0x06, 0x44, 0x10, 0x01, 0x48, 0x80, 0x49, 0x49, 0xff, 0xed, 0x9f, 0xf2, 0x07, +0x00, 0x1e, 0x00, 0x02, 0x44, 0x0f, 0x87, 0xff, 0x40, 0x21, 0x00, 0x02, 0x40, 0x10, 0xac, 0x08, +0x40, 0x30, 0x88, 0x04, 0x80, 0x43, 0x80, 0x06, 0x44, 0x10, 0x01, 0x48, 0xf3, 0x87, 0xdd, 0x2a, +0xba, 0x01, 0x80, 0x06, 0x44, 0x10, 0x00, 0x58, 0xdd, 0x2a, 0xba, 0x05, 0x80, 0x06, 0x44, 0x10, +0x02, 0x98, 0xdd, 0x2a, 0x9d, 0xb1, 0x84, 0xa2, 0xde, 0x8b, 0xf2, 0x04, 0x3e, 0x21, 0x3a, 0x7e, +0xf3, 0x04, 0xf0, 0x05, 0xf1, 0x03, 0x9c, 0xd9, 0x50, 0x00, 0x00, 0x34, 0x50, 0x10, 0x80, 0x34, +0x84, 0xa8, 0xf3, 0x84, 0xf0, 0x85, 0x51, 0xce, 0x00, 0x34, 0x50, 0x84, 0x00, 0x34, 0xf1, 0x83, +0x50, 0x73, 0x80, 0x34, 0x4c, 0x32, 0xff, 0x6a, 0xf3, 0x01, 0xc3, 0x09, 0x84, 0x01, 0x49, 0xff, +0xee, 0x1b, 0x2e, 0x11, 0x3a, 0x7a, 0x84, 0xa1, 0xd9, 0x56, 0xd5, 0x59, 0xf2, 0x01, 0x3e, 0x21, +0x3a, 0x7e, 0x80, 0xe2, 0x50, 0x6f, 0x80, 0x1c, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x80, 0x46, +0x49, 0xff, 0xed, 0x54, 0xf3, 0x07, 0x92, 0x70, 0x40, 0x31, 0xc0, 0x08, 0x58, 0x31, 0x8c, 0x0c, +0xf3, 0x87, 0x80, 0x43, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xe1, 0xa9, 0x80, 0x07, +0x44, 0x10, 0x01, 0x48, 0x80, 0x46, 0x49, 0xff, 0xed, 0x41, 0xf3, 0x07, 0x44, 0x2f, 0x87, 0xff, +0x40, 0x31, 0x88, 0x02, 0x58, 0x31, 0xb0, 0x00, 0xf3, 0x87, 0x80, 0x43, 0x80, 0x07, 0x44, 0x10, +0x01, 0x48, 0x49, 0xff, 0xe1, 0x95, 0x80, 0x07, 0x44, 0x10, 0x00, 0x58, 0x80, 0x46, 0x49, 0xff, +0xed, 0x2d, 0xf3, 0x07, 0x46, 0x1f, 0x8f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x46, 0x20, 0x60, 0x00, +0x40, 0x31, 0x84, 0x02, 0x40, 0x31, 0x88, 0x04, 0xf3, 0x87, 0x80, 0x07, 0x80, 0x43, 0x44, 0x10, +0x00, 0x58, 0x49, 0xff, 0xe1, 0x7d, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xbf, 0x84, 0x00, 0x49, 0xff, +0xed, 0xcb, 0x2e, 0x51, 0x3a, 0x7b, 0x84, 0x01, 0xd0, 0x04, 0x2e, 0x51, 0x3a, 0x74, 0xd8, 0x0a, +0x84, 0x00, 0xd5, 0x06, 0x2e, 0x11, 0x3a, 0x75, 0x84, 0xa1, 0xd9, 0x04, 0x84, 0x01, 0x49, 0xff, +0xe7, 0x87, 0xf0, 0x02, 0x3c, 0x0e, 0x07, 0x43, 0x49, 0xff, 0xe4, 0xd2, 0x46, 0x10, 0x04, 0x12, +0x46, 0x20, 0x07, 0x77, 0x58, 0x21, 0x07, 0x73, 0x14, 0x20, 0x81, 0x8c, 0x84, 0xae, 0xf3, 0x02, +0xdb, 0x06, 0x80, 0x01, 0xa0, 0x41, 0x58, 0x10, 0x80, 0x20, 0xa8, 0x41, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0x40, 0xb5, 0x00, 0xb4, 0xe0, 0xa2, 0xd1, +0x92, 0x70, 0x96, 0xd8, 0x3e, 0x31, 0x3a, 0x84, 0xb4, 0x82, 0x97, 0x20, 0x3e, 0x41, 0x3a, 0x86, +0xb4, 0xa2, 0x92, 0xa8, 0x97, 0x68, 0x3e, 0x51, 0x3a, 0x85, 0xb4, 0x02, 0x92, 0x10, 0x96, 0x00, +0x50, 0x10, 0x00, 0x20, 0x96, 0x48, 0xe6, 0x24, 0xe8, 0x06, 0x54, 0x00, 0x00, 0x0f, 0x49, 0xff, +0xe6, 0xe5, 0xd5, 0x1d, 0x92, 0xe8, 0x54, 0x84, 0x00, 0xff, 0x97, 0xf8, 0x80, 0x47, 0x3e, 0x09, +0x16, 0x0c, 0x80, 0x28, 0x85, 0x40, 0x3e, 0xa1, 0x3a, 0x7d, 0x49, 0xff, 0xa8, 0x3b, 0x80, 0x08, +0x80, 0x27, 0x84, 0x40, 0x49, 0xff, 0xfd, 0x6e, 0x2e, 0x01, 0x3a, 0x85, 0x84, 0x22, 0x4c, 0x00, +0xc0, 0x07, 0x46, 0x00, 0x04, 0x12, 0x8c, 0x31, 0x14, 0x10, 0x01, 0xc5, 0x84, 0x00, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xb4, 0xc0, 0xb4, 0xe0, 0x96, 0x49, 0x92, 0xe8, +0x97, 0xb0, 0x97, 0xf8, 0xb5, 0x00, 0xe6, 0x25, 0xe9, 0x0d, 0x9c, 0x04, 0xb4, 0x40, 0x92, 0x5f, +0x3e, 0x21, 0x3a, 0x77, 0xb4, 0x40, 0x3e, 0x21, 0x3a, 0x78, 0xb4, 0x20, 0x92, 0x28, 0x3e, 0x11, +0x3a, 0x79, 0x93, 0x10, 0x54, 0x84, 0x00, 0xff, 0x3e, 0x09, 0x16, 0x5c, 0x80, 0x26, 0x80, 0x47, +0x80, 0x68, 0x49, 0xff, 0xa8, 0x07, 0x84, 0xa2, 0xd6, 0x22, 0xe6, 0xc3, 0xe8, 0x05, 0xc6, 0x09, +0x84, 0xa1, 0xde, 0x44, 0xd5, 0x11, 0x84, 0xa3, 0xd6, 0x2d, 0x84, 0xa4, 0xde, 0x3f, 0xd5, 0x3c, +0x2e, 0x01, 0x3a, 0x77, 0x2e, 0x11, 0x3a, 0x78, 0x2e, 0x21, 0x3a, 0x79, 0x49, 0xff, 0xfb, 0x8a, +0x49, 0xff, 0xe7, 0x66, 0xd5, 0x33, 0x2e, 0x01, 0x3a, 0x77, 0x2e, 0x11, 0x3a, 0x78, 0x2e, 0x21, +0x3a, 0x79, 0x49, 0xff, 0xfb, 0x7f, 0x49, 0xff, 0xfc, 0xc7, 0xd5, 0x28, 0x2e, 0x01, 0x3a, 0x77, +0x2e, 0x11, 0x3a, 0x78, 0x2e, 0x21, 0x3a, 0x79, 0x49, 0xff, 0xfb, 0x74, 0x49, 0xff, 0xe7, 0x50, +0x49, 0xff, 0xef, 0x46, 0x49, 0xff, 0xfc, 0xb8, 0x49, 0xff, 0xe2, 0x1c, 0x49, 0xff, 0xe2, 0x84, +0xd5, 0x15, 0x80, 0x08, 0x80, 0x27, 0x49, 0xff, 0xec, 0x8d, 0xcf, 0x07, 0x80, 0x08, 0x80, 0x27, +0x84, 0x41, 0x49, 0xff, 0xfc, 0xff, 0xd5, 0x0a, 0x2e, 0x21, 0x3a, 0x84, 0x80, 0x27, 0x80, 0x08, +0x49, 0xff, 0xe2, 0x1c, 0xd5, 0x03, 0x49, 0xff, 0xef, 0x2b, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x84, 0x60, 0x50, 0x1f, 0x80, 0x07, +0x84, 0xc0, 0x44, 0x00, 0x01, 0x38, 0x84, 0x41, 0xae, 0xc8, 0xb6, 0xdf, 0x49, 0xfe, 0x2a, 0x2a, +0x00, 0x0f, 0x80, 0x07, 0x44, 0x50, 0x00, 0xff, 0xd0, 0x3a, 0x44, 0x10, 0x00, 0x38, 0x80, 0x5f, +0x80, 0x06, 0x49, 0xff, 0xec, 0x23, 0x00, 0x3f, 0x80, 0x07, 0xb4, 0x1f, 0x46, 0x1f, 0xff, 0x0f, +0x58, 0x10, 0x8f, 0xff, 0x54, 0x31, 0x80, 0x0f, 0x40, 0x00, 0x04, 0x02, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x31, 0x80, 0x04, 0xb6, 0x7f, 0x80, 0x43, 0x80, 0x06, 0x44, 0x10, 0x00, 0x38, 0x49, 0xff, +0xe0, 0x6f, 0x80, 0x5f, 0x44, 0x10, 0x00, 0x38, 0x84, 0x01, 0x49, 0xff, 0xec, 0x07, 0x00, 0x3f, +0x80, 0x07, 0xb4, 0x1f, 0x46, 0x1f, 0xff, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x54, 0x31, 0x80, 0x0f, +0x40, 0x00, 0x04, 0x02, 0x40, 0x31, 0xc0, 0x08, 0x40, 0x31, 0x80, 0x04, 0xb6, 0x7f, 0x80, 0x43, +0x84, 0x01, 0x44, 0x10, 0x00, 0x38, 0x81, 0x1f, 0x49, 0xff, 0xe0, 0x52, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xb4, 0x3e, 0x19, 0x31, 0x38, 0x54, 0x80, +0x00, 0xff, 0x3a, 0x00, 0x84, 0x00, 0x3e, 0x29, 0x31, 0x30, 0xf0, 0x90, 0x12, 0x1f, 0x80, 0x22, +0x3a, 0x01, 0x04, 0x00, 0x3e, 0x29, 0x31, 0x28, 0xf0, 0x8e, 0x12, 0x1f, 0x80, 0x1e, 0x3a, 0x01, +0x04, 0x00, 0x51, 0xcf, 0x80, 0x30, 0xb6, 0x1c, 0x12, 0x1e, 0x00, 0x02, 0x46, 0x20, 0x04, 0x10, +0x46, 0x35, 0x85, 0x04, 0x58, 0x31, 0x88, 0x40, 0x50, 0x7f, 0x80, 0x1c, 0x04, 0xa1, 0x01, 0x09, +0x14, 0x31, 0x01, 0x09, 0x84, 0x20, 0x44, 0x20, 0x00, 0x14, 0x80, 0x07, 0x49, 0xfe, 0x73, 0x24, +0xa7, 0xba, 0xa7, 0x3b, 0xa4, 0xfb, 0xa6, 0xbc, 0x00, 0x03, 0x80, 0x12, 0x92, 0xc7, 0x95, 0xb7, +0x54, 0x42, 0x00, 0x1f, 0x92, 0x6e, 0x40, 0x31, 0xb8, 0x08, 0x54, 0x21, 0x00, 0x03, 0x54, 0x54, +0x00, 0x7f, 0x58, 0x42, 0x00, 0x40, 0x40, 0x53, 0x14, 0x04, 0x59, 0xe1, 0x00, 0x1c, 0x40, 0x60, +0x10, 0x09, 0x95, 0xb4, 0x58, 0x31, 0x80, 0x18, 0xaf, 0x3b, 0x84, 0x81, 0x50, 0x8f, 0x80, 0x04, +0xaf, 0x7a, 0x11, 0xe3, 0x80, 0x04, 0xaf, 0x3d, 0xac, 0xfb, 0x10, 0x63, 0x80, 0x12, 0x84, 0x20, +0x44, 0x20, 0x00, 0x18, 0x80, 0x08, 0x49, 0xfe, 0x72, 0xf7, 0x00, 0x44, 0x00, 0x00, 0x00, 0x34, +0x00, 0x01, 0x54, 0x42, 0x00, 0x03, 0x58, 0x42, 0x00, 0x08, 0x58, 0x31, 0x80, 0x01, 0x10, 0x44, +0x00, 0x00, 0x10, 0x34, 0x00, 0x01, 0x44, 0x65, 0xa3, 0x84, 0x50, 0x1f, 0x80, 0x40, 0x84, 0x46, +0x50, 0x0f, 0x80, 0x08, 0xdd, 0x26, 0x50, 0x1f, 0x80, 0x38, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x0e, +0xdd, 0x26, 0x80, 0x3c, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x14, 0xdd, 0x26, 0x46, 0x20, 0x04, 0x10, +0x04, 0x31, 0x01, 0x01, 0x44, 0x1f, 0xff, 0x1f, 0x40, 0x31, 0x84, 0x02, 0x14, 0x31, 0x01, 0x01, +0x46, 0x00, 0x04, 0x1d, 0x80, 0x27, 0x44, 0x20, 0x00, 0x14, 0xdd, 0x26, 0x46, 0x00, 0x04, 0x1d, +0x80, 0x28, 0x58, 0x00, 0x00, 0x14, 0x44, 0x20, 0x00, 0x18, 0xdd, 0x26, 0x46, 0x00, 0x04, 0x11, +0x84, 0x24, 0xa8, 0x41, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x04, 0x10, 0xb4, 0x20, 0x81, 0x00, +0x58, 0x10, 0x80, 0x04, 0xb6, 0x20, 0x84, 0xc0, 0xb4, 0x28, 0x84, 0x0a, 0x54, 0x10, 0x80, 0x40, +0xc1, 0x08, 0x9d, 0xb1, 0x49, 0xff, 0xdf, 0x94, 0x97, 0xb1, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf5, +0x46, 0x10, 0x04, 0x11, 0x46, 0x00, 0x04, 0x10, 0x84, 0x40, 0xa8, 0x89, 0x14, 0xa0, 0x01, 0x09, +0xec, 0x4c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x54, 0x3e, 0x29, +0x31, 0x1c, 0x96, 0x00, 0x96, 0x48, 0xf0, 0x85, 0xf1, 0x93, 0x3a, 0x01, 0x08, 0x00, 0x50, 0x3f, +0x80, 0x90, 0x3a, 0x01, 0x84, 0x24, 0xf0, 0x05, 0xac, 0x98, 0xe6, 0x0f, 0xe8, 0x09, 0x2e, 0x21, +0x3a, 0x7b, 0x84, 0x21, 0x4c, 0x20, 0xc0, 0x10, 0x3e, 0x09, 0x16, 0x88, 0xd5, 0x08, 0x2e, 0x21, +0x3a, 0x7a, 0x84, 0x61, 0x4c, 0x21, 0xc0, 0x08, 0x3e, 0x09, 0x16, 0xa8, 0x49, 0xff, 0xa6, 0x8a, +0x48, 0x00, 0x06, 0xa2, 0x3e, 0x09, 0x16, 0xc8, 0x49, 0xff, 0xa6, 0x84, 0x2e, 0x21, 0x3a, 0x7d, +0xf0, 0x05, 0x4c, 0x20, 0x00, 0x0d, 0x84, 0x40, 0x3c, 0x2e, 0x4e, 0xb1, 0x3c, 0x2e, 0x4e, 0xae, +0x3c, 0x2e, 0x4e, 0xaf, 0x3c, 0x2e, 0x4e, 0xb0, 0x3e, 0x01, 0x3a, 0x7d, 0x46, 0x10, 0x04, 0x12, +0x84, 0x40, 0x50, 0x3f, 0x80, 0x9c, 0x58, 0x10, 0x87, 0x20, 0xf2, 0x87, 0xac, 0x9a, 0xb6, 0x43, +0xf1, 0x84, 0xf2, 0x8a, 0xf2, 0x83, 0xf2, 0x8e, 0xf2, 0x86, 0xd5, 0x03, 0x84, 0x61, 0xf3, 0x83, +0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xec, 0xf0, 0x03, 0xf1, 0x89, 0x4e, 0x03, 0x00, 0xa3, +0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xed, 0x54, 0x20, 0x80, 0x20, 0x54, 0x10, 0x80, 0x3f, +0xc2, 0x03, 0x50, 0x10, 0xff, 0xc0, 0x46, 0x20, 0x04, 0x11, 0x04, 0x21, 0x00, 0xec, 0x54, 0x21, +0x00, 0x3f, 0x98, 0x4a, 0x4e, 0x14, 0x00, 0x04, 0x84, 0x20, 0xd5, 0x02, 0x96, 0x48, 0x3c, 0x2c, +0x4e, 0xae, 0xca, 0x04, 0x3c, 0x3c, 0x4e, 0xaf, 0xc3, 0x0c, 0xe2, 0x41, 0xe9, 0x0a, 0x3c, 0x3c, +0x4e, 0xaf, 0xe2, 0x23, 0xe9, 0x06, 0x3e, 0x09, 0x16, 0xd4, 0x49, 0xff, 0xa6, 0x33, 0xd5, 0xcf, +0x54, 0x20, 0x80, 0x03, 0xe4, 0x42, 0xe9, 0x38, 0x5e, 0xf0, 0x80, 0x78, 0xe9, 0x06, 0x44, 0x40, +0x00, 0x7f, 0x3c, 0x4e, 0x4e, 0xae, 0xd5, 0x0b, 0x50, 0x40, 0x80, 0x08, 0x3c, 0x4e, 0x4e, 0xae, +0xe4, 0x24, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, 0x4e, 0xaf, 0xd5, 0x04, 0x9e, 0x4c, 0x3c, 0x1e, +0x4e, 0xaf, 0xf2, 0x09, 0x44, 0x40, 0x00, 0x3f, 0x54, 0x11, 0x00, 0x3f, 0x9d, 0x8c, 0x50, 0x70, +0x80, 0x08, 0x5c, 0x53, 0x00, 0x40, 0x5c, 0x33, 0x80, 0x40, 0x40, 0x72, 0x0c, 0x1a, 0x40, 0x62, +0x14, 0x1a, 0xe6, 0x24, 0xe8, 0x09, 0x84, 0x21, 0x84, 0x7f, 0x84, 0x02, 0xf1, 0x8d, 0xf3, 0x8b, +0xf0, 0x8c, 0x84, 0x20, 0xd5, 0x39, 0x84, 0x5f, 0x84, 0x62, 0x84, 0x01, 0x9e, 0x4c, 0xf2, 0x8b, +0xf3, 0x8c, 0xf0, 0x8d, 0xd5, 0x31, 0x5e, 0xf0, 0x80, 0x7c, 0xe9, 0x06, 0x44, 0x40, 0x00, 0x7f, +0x3c, 0x4e, 0x4e, 0xae, 0xd5, 0x0a, 0x9d, 0x0c, 0x3c, 0x4e, 0x4e, 0xae, 0xe4, 0x28, 0xe8, 0x05, +0x84, 0x40, 0x3c, 0x2e, 0x4e, 0xaf, 0xd5, 0x04, 0x8e, 0x28, 0x3c, 0x1e, 0x4e, 0xaf, 0xf2, 0x09, +0x54, 0x11, 0x00, 0x3f, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0xc0, 0x80, 0xe6, 0xd5, 0x08, 0x9f, 0x8c, +0xe6, 0x28, 0xe8, 0x03, 0x84, 0xe0, 0xd5, 0x03, 0x50, 0x70, 0xff, 0xf8, 0x9c, 0x4c, 0x84, 0x61, +0x84, 0x1e, 0x84, 0x5f, 0x5c, 0x50, 0x80, 0x40, 0x44, 0x40, 0x00, 0x3f, 0xf3, 0x8b, 0xf0, 0x8c, +0xf2, 0x8d, 0x40, 0x12, 0x14, 0x1a, 0xf0, 0x09, 0x40, 0x30, 0x18, 0x09, 0x94, 0xde, 0x40, 0x10, +0x8c, 0x04, 0x40, 0x63, 0x0c, 0x04, 0xf1, 0x90, 0xf6, 0x92, 0x40, 0x33, 0x8c, 0x04, 0x48, 0x00, +0x00, 0xad, 0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xea, 0x54, 0x20, 0x80, 0x20, 0x54, 0x10, +0x80, 0x3f, 0xc2, 0x03, 0x50, 0x10, 0xff, 0xc0, 0x46, 0x20, 0x04, 0x11, 0x04, 0x21, 0x00, 0xec, +0x92, 0x48, 0x54, 0x21, 0x00, 0x3f, 0x98, 0x4a, 0x4e, 0x14, 0x00, 0x04, 0x84, 0x20, 0xd5, 0x02, +0x96, 0x48, 0x3c, 0x2c, 0x4e, 0xb0, 0xca, 0x04, 0x3c, 0x3c, 0x4e, 0xb1, 0xc3, 0x0d, 0xe2, 0x41, +0xe9, 0x0b, 0x3c, 0x3c, 0x4e, 0xb1, 0xe2, 0x23, 0xe9, 0x07, 0x3e, 0x09, 0x17, 0x28, 0x49, 0xff, +0xa5, 0x91, 0x48, 0x00, 0x05, 0xa9, 0x54, 0x20, 0x80, 0x03, 0xe4, 0x42, 0xe9, 0x39, 0x5e, 0xf0, +0x80, 0x78, 0xe9, 0x06, 0x44, 0x40, 0x00, 0x7f, 0x3c, 0x4e, 0x4e, 0xb0, 0xd5, 0x0b, 0x50, 0x40, +0x80, 0x08, 0x3c, 0x4e, 0x4e, 0xb0, 0xe4, 0x24, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, 0x4e, 0xb1, +0xd5, 0x04, 0x9e, 0x4c, 0x3c, 0x1e, 0x4e, 0xb1, 0xf3, 0x09, 0x44, 0x40, 0x00, 0x3f, 0x40, 0x11, +0xa0, 0x09, 0x54, 0x10, 0x80, 0x3f, 0x9d, 0x8c, 0x50, 0x30, 0x80, 0x08, 0x5c, 0x53, 0x00, 0x40, +0x5c, 0x71, 0x80, 0x40, 0x40, 0x32, 0x1c, 0x1a, 0x40, 0x62, 0x14, 0x1a, 0xe6, 0x24, 0xe8, 0x09, +0x84, 0x22, 0x84, 0x1f, 0x84, 0x41, 0xf1, 0x8c, 0xf0, 0x8b, 0xf2, 0x8d, 0x84, 0x20, 0xd5, 0x3a, +0x84, 0x1f, 0x84, 0x42, 0xf0, 0x8b, 0x9e, 0x4c, 0xf2, 0x8c, 0x84, 0x01, 0xd5, 0x32, 0x5e, 0xf0, +0x80, 0x7c, 0xe9, 0x06, 0x44, 0x40, 0x00, 0x7f, 0x3c, 0x4e, 0x4e, 0xb0, 0xd5, 0x0a, 0x9d, 0x0c, +0x3c, 0x4e, 0x4e, 0xb0, 0xe4, 0x28, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, 0x4e, 0xb1, 0xd5, 0x04, +0x8e, 0x28, 0x3c, 0x1e, 0x4e, 0xb1, 0xf2, 0x09, 0x40, 0x11, 0x20, 0x09, 0x54, 0x10, 0x80, 0x3f, +0xe6, 0x24, 0xe8, 0x04, 0x84, 0xc0, 0x80, 0x66, 0xd5, 0x08, 0x9f, 0x8c, 0xe6, 0x28, 0xe8, 0x03, +0x84, 0x60, 0xd5, 0x03, 0x50, 0x30, 0xff, 0xf8, 0x9c, 0x4c, 0x84, 0x5e, 0x84, 0x01, 0x5c, 0x50, +0x80, 0x40, 0x44, 0x40, 0x00, 0x3f, 0xf2, 0x8c, 0xf0, 0x8b, 0x40, 0x12, 0x14, 0x1a, 0x84, 0x1f, +0xf0, 0x8d, 0xf2, 0x09, 0x44, 0x0f, 0xc0, 0xff, 0x40, 0x41, 0xa0, 0x08, 0x40, 0x63, 0x20, 0x08, +0x40, 0x31, 0x00, 0x02, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x8c, 0x04, 0x40, 0x63, 0x0c, 0x04, +0xf1, 0x90, 0xf6, 0x92, 0x40, 0x32, 0x0c, 0x04, 0xf3, 0x91, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, +0xe9, 0x6d, 0x44, 0x00, 0x13, 0x44, 0x49, 0xff, 0xe9, 0x69, 0x46, 0x50, 0x04, 0x11, 0xa1, 0x29, +0x84, 0x33, 0x40, 0x32, 0x04, 0x02, 0xa8, 0xe9, 0x80, 0xc5, 0x04, 0x43, 0x00, 0xd1, 0x80, 0xe5, +0x40, 0x32, 0x20, 0x09, 0x40, 0x31, 0xa0, 0x08, 0x14, 0x33, 0x00, 0xd1, 0x84, 0xc0, 0x04, 0x43, +0x80, 0x80, 0x9d, 0xb1, 0x97, 0x24, 0x84, 0x0a, 0xc4, 0x21, 0x49, 0xff, 0xdd, 0xc1, 0x44, 0x30, +0x0b, 0xb8, 0x4c, 0x61, 0xff, 0xf6, 0x46, 0x10, 0x04, 0x11, 0x80, 0x41, 0x80, 0x61, 0x80, 0x81, +0x80, 0xa1, 0x80, 0x01, 0x04, 0x10, 0x80, 0x38, 0x04, 0x21, 0x00, 0x39, 0x04, 0x31, 0x80, 0x3c, +0x04, 0x42, 0x00, 0x3d, 0x04, 0x52, 0x80, 0x3e, 0x04, 0x60, 0x00, 0x3f, 0x3e, 0x09, 0x17, 0x7c, +0xb6, 0xdf, 0x49, 0xff, 0xa4, 0xcf, 0x48, 0x00, 0x02, 0x0e, 0x46, 0x60, 0x04, 0x12, 0x80, 0xe4, +0x04, 0x13, 0x00, 0x4c, 0x9d, 0xf9, 0x84, 0x0a, 0xc1, 0x0d, 0x49, 0xff, 0xdd, 0x99, 0x44, 0x00, +0x0b, 0xb8, 0x4c, 0x70, 0x7f, 0xf7, 0x3e, 0x09, 0x17, 0xc4, 0x49, 0xff, 0xa4, 0xbb, 0x48, 0x00, +0x01, 0xfa, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x04, 0xb8, 0x44, 0x00, 0x13, 0xb0, 0xdd, 0x26, +0xf1, 0x04, 0x44, 0x2f, 0x1f, 0xff, 0xb4, 0x81, 0x44, 0x00, 0x23, 0x20, 0x40, 0x32, 0x08, 0x02, +0xb6, 0x61, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x44, 0x00, 0x27, 0x04, 0x04, 0x42, 0x00, 0xc8, +0xdd, 0x26, 0x44, 0x00, 0x27, 0x08, 0xdd, 0x26, 0x44, 0x00, 0x13, 0x28, 0xdd, 0x26, 0xf3, 0x05, +0xe6, 0x6f, 0xe8, 0x15, 0xf0, 0x03, 0xc8, 0x0a, 0x46, 0x50, 0x04, 0x11, 0x46, 0x40, 0x01, 0xc0, +0x58, 0x52, 0x83, 0x28, 0x58, 0x42, 0x00, 0x20, 0xd5, 0x1d, 0x46, 0x50, 0x04, 0x11, 0x46, 0x40, +0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, 0x58, 0x42, 0x00, 0x80, 0xd5, 0x14, 0xf1, 0x03, 0xc9, 0x0a, +0x46, 0x50, 0x04, 0x11, 0x46, 0x40, 0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, 0x58, 0x42, 0x00, 0x10, +0xd5, 0x09, 0x46, 0x50, 0x04, 0x11, 0x46, 0x40, 0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, 0x58, 0x42, +0x00, 0x40, 0xb6, 0x85, 0x46, 0x60, 0x04, 0x12, 0x44, 0x00, 0x20, 0x04, 0x49, 0xff, 0xe8, 0xce, +0xa1, 0x71, 0x54, 0x42, 0x80, 0x10, 0xcc, 0x04, 0x58, 0x32, 0x80, 0x10, 0xa8, 0xf1, 0x44, 0x00, +0x21, 0x24, 0x49, 0xff, 0xe8, 0xc3, 0x46, 0x40, 0x04, 0x12, 0x44, 0x3f, 0xf5, 0x7c, 0x14, 0x32, +0x00, 0x49, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x0b, 0x60, 0xf2, 0x05, 0x46, 0x70, 0x00, 0x87, +0x58, 0x73, 0x8d, 0xbc, 0xe6, 0x4f, 0xe8, 0x45, 0xf0, 0x03, 0x84, 0x20, 0xdd, 0x26, 0xf0, 0x03, +0x84, 0x24, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, +0x00, 0x44, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, +0x02, 0x64, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x03, 0x46, 0x2a, +0x00, 0x56, 0x58, 0x21, 0x0f, 0x53, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x03, 0x84, 0x24, 0x44, 0x24, +0x01, 0x2c, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x23, 0x0c, 0xf0, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, +0x00, 0x10, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x20, 0x25, 0x12, 0x58, 0x21, 0x00, 0x16, 0x44, 0x10, +0x00, 0x44, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x20, 0x00, 0xb9, 0x58, 0x21, 0x0e, 0x9e, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x27, 0x46, 0x20, 0x08, 0x88, 0xf0, 0x03, 0x44, 0x10, 0x02, 0x64, 0xd5, 0x52, +0xf0, 0x03, 0x84, 0x20, 0xdd, 0x26, 0xf0, 0x03, 0x84, 0x24, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, +0x00, 0x10, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x02, 0xa8, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x02, 0x54, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, +0x02, 0x60, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x03, 0x46, 0x2a, +0x00, 0x56, 0x58, 0x21, 0x0f, 0x57, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x03, 0x84, 0x24, 0x44, 0x24, +0x01, 0x23, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x23, 0x04, 0xf0, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, +0x00, 0x10, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x20, 0x14, 0xec, 0x58, 0x21, 0x0d, 0x28, 0x44, 0x10, +0x02, 0xa8, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x20, 0x00, 0xb9, 0x58, 0x21, 0x0e, 0x9e, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x23, 0x64, 0x55, 0x58, 0x21, 0x07, 0x77, 0x44, 0x10, +0x02, 0x54, 0xdd, 0x27, 0x46, 0x26, 0x63, 0xca, 0xf0, 0x03, 0x58, 0x21, 0x05, 0x8f, 0x44, 0x10, +0x02, 0x60, 0xdd, 0x27, 0xf0, 0x03, 0x46, 0x20, 0x08, 0x04, 0x44, 0x10, 0x01, 0x14, 0x58, 0x21, +0x00, 0x81, 0xdd, 0x27, 0x44, 0x00, 0x13, 0xb8, 0x49, 0xff, 0xe8, 0x10, 0x44, 0x00, 0x13, 0xbc, +0x49, 0xff, 0xe8, 0x0c, 0x46, 0x50, 0x04, 0x11, 0xf0, 0x03, 0x04, 0x42, 0x80, 0xef, 0x40, 0x30, +0x7c, 0x08, 0x40, 0x31, 0x90, 0x04, 0x84, 0x25, 0x14, 0x32, 0x80, 0xef, 0xf1, 0x8f, 0x85, 0x42, +0x84, 0x42, 0x4c, 0xa1, 0x40, 0x08, 0x46, 0x20, 0x04, 0x11, 0xf3, 0x09, 0x14, 0x31, 0x00, 0xec, +0xd5, 0x40, 0x84, 0x03, 0x4c, 0xa0, 0x40, 0x0c, 0xf1, 0x0e, 0xf3, 0x0d, 0x46, 0x20, 0x04, 0x11, +0x98, 0x4b, 0x58, 0x21, 0x03, 0xb0, 0xf1, 0x86, 0xf0, 0x12, 0xd5, 0x21, 0x84, 0x44, 0x4c, 0xa1, +0x40, 0x16, 0xf3, 0x0e, 0xf0, 0x0c, 0x46, 0x20, 0x04, 0x11, 0xf1, 0x11, 0x98, 0xd8, 0xf3, 0x86, +0x14, 0x11, 0x00, 0xec, 0x4e, 0x34, 0x00, 0x03, 0xd5, 0x15, 0xf0, 0x06, 0x46, 0x30, 0x04, 0x11, +0x58, 0x31, 0x83, 0xb8, 0x58, 0x20, 0x00, 0x10, 0xd5, 0x1b, 0xf1, 0x0e, 0xf3, 0x0b, 0x46, 0x20, +0x04, 0x11, 0x98, 0x4b, 0xf1, 0x86, 0xf0, 0x10, 0x58, 0x21, 0x03, 0xb0, 0xb6, 0x02, 0x4e, 0x14, +0x00, 0x09, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x83, 0xb8, 0x44, 0x20, 0x00, 0x10, 0xd5, 0x08, +0xf1, 0x06, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x83, 0xb8, 0x58, 0x20, 0x80, 0x10, 0xb6, 0x43, +0xf2, 0x05, 0xe6, 0x4f, 0xe8, 0x0d, 0x46, 0x30, 0x04, 0x12, 0x44, 0x20, 0x11, 0x10, 0x46, 0x40, +0x04, 0x12, 0x14, 0x21, 0x81, 0xc1, 0x58, 0x42, 0x07, 0x08, 0x84, 0x40, 0xd5, 0x0d, 0x46, 0x30, +0x04, 0x12, 0x44, 0x20, 0x0d, 0x0d, 0x46, 0x40, 0x04, 0x12, 0x14, 0x21, 0x81, 0xc1, 0x58, 0x42, +0x07, 0x08, 0x44, 0x20, 0x08, 0x08, 0xb6, 0x44, 0x44, 0x00, 0x27, 0x14, 0x49, 0xff, 0xe7, 0x96, +0xf3, 0x03, 0xcb, 0x06, 0x46, 0x20, 0x04, 0x12, 0x14, 0x31, 0x01, 0xc5, 0xd5, 0x07, 0x46, 0x30, +0x04, 0x12, 0x44, 0x20, 0x00, 0x81, 0x14, 0x21, 0x81, 0xc5, 0xf0, 0x03, 0x44, 0x10, 0x02, 0x98, +0x49, 0xff, 0xea, 0xd8, 0x44, 0x00, 0x12, 0x80, 0x49, 0xff, 0xe7, 0x80, 0xf0, 0x03, 0x84, 0x60, +0x44, 0x10, 0x02, 0x98, 0x50, 0x2f, 0x80, 0xa4, 0xf3, 0xa9, 0x49, 0xff, 0xe7, 0x97, 0xf3, 0x29, +0x92, 0x62, 0x94, 0xda, 0xf0, 0x03, 0x80, 0x43, 0x44, 0x10, 0x02, 0x98, 0xf3, 0xa9, 0x49, 0xff, +0xdb, 0xef, 0x46, 0x30, 0x04, 0x11, 0x44, 0x20, 0x00, 0x30, 0x14, 0x21, 0x80, 0xa0, 0x84, 0x42, +0x4c, 0xa1, 0x40, 0x05, 0x84, 0x07, 0x49, 0xff, 0xfb, 0x97, 0x46, 0x70, 0x04, 0x11, 0x84, 0xc0, +0x04, 0x13, 0x80, 0x80, 0x9d, 0xb1, 0x96, 0x4c, 0x84, 0x0a, 0xc1, 0x20, 0x49, 0xff, 0xdb, 0xc8, +0x44, 0x00, 0x03, 0xe8, 0x4c, 0x60, 0x7f, 0xf6, 0x46, 0x10, 0x04, 0x11, 0x80, 0x41, 0x80, 0x61, +0x80, 0x81, 0x80, 0xa1, 0x80, 0x01, 0x04, 0x10, 0x80, 0x38, 0x04, 0x21, 0x00, 0x39, 0x04, 0x31, +0x80, 0x3c, 0x04, 0x42, 0x00, 0x3d, 0x04, 0x52, 0x80, 0x3e, 0x04, 0x60, 0x00, 0x3f, 0x3e, 0x09, +0x17, 0xd0, 0xb6, 0xdf, 0x49, 0xff, 0xa2, 0xd6, 0xd5, 0x13, 0x46, 0x60, 0x04, 0x12, 0x80, 0xe1, +0x04, 0x13, 0x00, 0x4c, 0x9d, 0xf9, 0x84, 0x0a, 0xc1, 0x11, 0x49, 0xff, 0xdb, 0xa1, 0x44, 0x20, +0x03, 0xe8, 0x4c, 0x71, 0x7f, 0xf7, 0x3e, 0x09, 0x18, 0x18, 0x49, 0xff, 0xa2, 0xc3, 0x49, 0xff, +0xdb, 0xc5, 0x49, 0xff, 0xe6, 0xfd, 0x48, 0x00, 0x02, 0xd7, 0x84, 0x62, 0x4c, 0xa1, 0xc0, 0x0a, +0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xef, 0x54, 0x10, 0x80, 0x0f, 0xf1, 0x8e, 0xf1, 0x86, +0x87, 0x80, 0x15, 0xcf, 0x80, 0x08, 0x85, 0x25, 0x50, 0x0f, 0x80, 0x90, 0x39, 0xc0, 0x24, 0x00, +0x46, 0x10, 0x00, 0xb0, 0x40, 0x4e, 0x04, 0x04, 0x40, 0x3e, 0x20, 0x08, 0xf0, 0x03, 0x40, 0x22, +0x0c, 0x04, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xdb, 0x83, 0x46, 0x40, 0x04, 0x11, 0x84, 0x68, +0x80, 0xe4, 0x46, 0x58, 0x00, 0x08, 0x80, 0xc4, 0x46, 0x80, 0x04, 0x12, 0xa8, 0xe1, 0x44, 0x30, +0x21, 0x05, 0x84, 0x00, 0xa8, 0x21, 0x14, 0x53, 0x80, 0x99, 0x46, 0x40, 0x04, 0x12, 0x14, 0x53, +0x00, 0x9a, 0x14, 0x34, 0x01, 0xc6, 0x58, 0x42, 0x07, 0x24, 0xb4, 0x64, 0x46, 0x13, 0x80, 0x0f, +0x58, 0x10, 0x8f, 0xff, 0x40, 0x31, 0x84, 0x02, 0xb6, 0x64, 0xf2, 0x03, 0xca, 0x1a, 0x84, 0x64, +0x4c, 0xa1, 0x80, 0x10, 0x84, 0x05, 0x4c, 0xa0, 0x00, 0x11, 0x84, 0x23, 0x4c, 0xa0, 0x80, 0x06, +0x46, 0x20, 0x20, 0x00, 0xb4, 0x64, 0xd5, 0x29, 0x46, 0x04, 0x20, 0x00, 0xb4, 0x64, 0xd5, 0x19, +0x46, 0x10, 0x60, 0x00, 0xb4, 0x64, 0xd5, 0x1b, 0x46, 0x24, 0x60, 0x00, 0xb4, 0x64, 0xd5, 0x1d, +0x84, 0x64, 0x4c, 0xa1, 0x80, 0x12, 0x84, 0x05, 0x4c, 0xa0, 0x00, 0x15, 0x84, 0x23, 0x4c, 0xa0, +0x80, 0x06, 0x46, 0x28, 0x20, 0x00, 0xb4, 0x64, 0xd5, 0x10, 0x46, 0x0c, 0x20, 0x00, 0xb4, 0x64, +0x40, 0x31, 0x80, 0x04, 0xd5, 0x0c, 0x46, 0x18, 0x60, 0x00, 0xb4, 0x64, 0x40, 0x31, 0x84, 0x04, +0xd5, 0x06, 0x46, 0x2c, 0x60, 0x00, 0xb4, 0x64, 0x40, 0x31, 0x88, 0x04, 0xb6, 0x64, 0x80, 0x88, +0x84, 0x61, 0xa8, 0xe4, 0x84, 0x60, 0xa8, 0xe4, 0x46, 0x54, 0x10, 0x06, 0xf0, 0x04, 0x58, 0x52, +0x80, 0x0a, 0xb6, 0xa0, 0x80, 0xc3, 0xf2, 0x04, 0x9d, 0xb1, 0xb4, 0x22, 0x84, 0x0a, 0x54, 0x10, +0xa0, 0x00, 0xc1, 0x07, 0x49, 0xff, 0xdb, 0x04, 0x44, 0x00, 0x00, 0x64, 0x4c, 0x60, 0x7f, 0xf5, +0x46, 0x50, 0x04, 0x12, 0x80, 0x85, 0x46, 0x30, 0x1f, 0xc0, 0x84, 0x20, 0x14, 0x12, 0x81, 0xc6, +0x14, 0x32, 0x01, 0xc9, 0x80, 0x64, 0x04, 0x31, 0x81, 0xca, 0x3e, 0x09, 0x18, 0x24, 0x97, 0x98, +0x80, 0x29, 0x80, 0x5c, 0x80, 0x66, 0x49, 0xff, 0xa2, 0x15, 0x5e, 0xf3, 0x00, 0x50, 0xe8, 0x06, +0x8d, 0x21, 0xe5, 0x2a, 0x4e, 0xf3, 0xff, 0x62, 0xd5, 0x3b, 0x5e, 0xf3, 0x00, 0xa1, 0xe9, 0x05, +0x8f, 0x21, 0x4e, 0x94, 0xff, 0x5b, 0xd5, 0x34, 0xf2, 0x08, 0x84, 0x65, 0x40, 0x41, 0x0c, 0x76, +0x84, 0x04, 0x4c, 0x30, 0x40, 0x05, 0xf1, 0x0f, 0x9c, 0x4e, 0xf1, 0x8f, 0xf2, 0x08, 0x84, 0x65, +0x4c, 0x21, 0x80, 0x27, 0xf0, 0x0f, 0x49, 0xff, 0xe4, 0x2d, 0x80, 0xc0, 0x84, 0x01, 0x4c, 0x60, +0x40, 0x1b, 0x80, 0x5c, 0x80, 0x29, 0x3e, 0x09, 0x18, 0x3c, 0x49, 0xff, 0xa1, 0xeb, 0x2e, 0x31, +0x3a, 0x63, 0xf1, 0x06, 0x50, 0x4f, 0x80, 0x9c, 0x38, 0x62, 0x28, 0x08, 0x96, 0x88, 0x4c, 0x33, +0x40, 0x05, 0xe6, 0x4a, 0xe9, 0x22, 0xd5, 0x03, 0xe6, 0x49, 0xe9, 0x1f, 0x84, 0x20, 0x38, 0x12, +0x28, 0x08, 0xd5, 0x1b, 0xf2, 0x08, 0x9c, 0x91, 0xf2, 0x88, 0x48, 0xff, 0xff, 0x27, 0x84, 0x60, +0x50, 0x2f, 0x80, 0x9c, 0x05, 0xcf, 0x80, 0x08, 0x38, 0x31, 0x28, 0x08, 0xe7, 0x2a, 0xe9, 0x06, +0x80, 0x29, 0x3e, 0x09, 0x18, 0x50, 0x49, 0xff, 0xa1, 0xc5, 0x84, 0x65, 0x4d, 0xc1, 0xc0, 0x06, +0x3e, 0x09, 0x18, 0x74, 0x49, 0xff, 0xa1, 0xbe, 0x8d, 0x41, 0x84, 0x06, 0x4c, 0xa0, 0x7e, 0x22, +0xf2, 0x03, 0x50, 0x1f, 0x80, 0x9c, 0xca, 0x51, 0xa6, 0x48, 0xc9, 0x0b, 0xf3, 0x03, 0x46, 0x20, +0x04, 0x12, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, +0x00, 0x1f, 0x80, 0x9d, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x80, 0x22, 0x44, 0x31, 0x00, 0x00, +0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x9e, +0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x00, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, +0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x9f, 0xc9, 0x0c, 0x46, 0x20, +0x04, 0x12, 0x46, 0x30, 0x20, 0x10, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, +0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0xa0, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, +0x60, 0x00, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, +0x00, 0x1f, 0x80, 0xa1, 0xc9, 0x5f, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x60, 0x10, 0x46, 0x10, +0x04, 0x12, 0x58, 0x21, 0x07, 0x24, 0xd5, 0x51, 0xa6, 0x48, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, +0x80, 0x22, 0x44, 0x32, 0x00, 0x00, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, +0x81, 0xcb, 0x00, 0x1f, 0x80, 0x9d, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x80, 0x22, 0x44, 0x33, +0x00, 0x00, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, +0x80, 0x9e, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x20, 0x80, 0x22, 0x14, 0x31, +0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x9f, 0xc9, 0x0c, +0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x30, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, +0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0xa0, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, +0x46, 0x30, 0x60, 0x20, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, +0x81, 0xcb, 0x00, 0x1f, 0x80, 0xa1, 0xc9, 0x0e, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x60, 0x30, +0x46, 0x10, 0x04, 0x12, 0x58, 0x21, 0x07, 0x24, 0xb6, 0x62, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, +0x81, 0xcb, 0x3e, 0x59, 0x30, 0xdc, 0x3a, 0x02, 0x8c, 0x04, 0x50, 0x6f, 0x80, 0x50, 0x80, 0x86, +0x46, 0x70, 0x04, 0x12, 0x46, 0x90, 0x04, 0x12, 0x3a, 0x02, 0x0c, 0x24, 0x83, 0x86, 0x58, 0x73, +0x87, 0x24, 0x85, 0x02, 0x3a, 0x02, 0x8c, 0x04, 0x85, 0x4a, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, +0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x00, 0x3a, 0x02, 0x0c, 0x20, 0xf6, 0x03, +0xb4, 0x07, 0x46, 0x1f, 0x80, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x00, 0x04, 0x02, 0x84, 0x44, +0xb6, 0x07, 0x4c, 0x81, 0x00, 0x1a, 0x84, 0x65, 0x4c, 0x81, 0x80, 0x22, 0x84, 0x03, 0x4c, 0x80, +0x00, 0x0b, 0xce, 0x05, 0x46, 0x10, 0x20, 0x00, 0xb4, 0x07, 0xd5, 0x1d, 0x46, 0x20, 0x20, 0x20, +0xb4, 0x07, 0xd5, 0x1f, 0xce, 0x05, 0x46, 0x30, 0x20, 0x10, 0xb4, 0x07, 0xd5, 0x0d, 0x46, 0x10, +0x20, 0x30, 0xb4, 0x07, 0xd5, 0x10, 0xce, 0x05, 0x46, 0x20, 0x60, 0x00, 0xb4, 0x07, 0xd5, 0x11, +0x46, 0x30, 0x60, 0x20, 0xb4, 0x07, 0x40, 0x00, 0x0c, 0x04, 0xd5, 0x0d, 0xce, 0x07, 0x46, 0x10, +0x60, 0x10, 0xb4, 0x07, 0x40, 0x00, 0x04, 0x04, 0xd5, 0x06, 0x46, 0x20, 0x60, 0x30, 0xb4, 0x07, +0x40, 0x00, 0x08, 0x04, 0xb6, 0x07, 0x80, 0x9c, 0xb4, 0xa7, 0x84, 0x60, 0x40, 0x01, 0x94, 0x04, +0xb6, 0x07, 0x04, 0x04, 0x81, 0xca, 0xa6, 0x60, 0x96, 0x80, 0x50, 0x21, 0x7f, 0x80, 0x42, 0x11, +0x04, 0x24, 0x4e, 0x26, 0x00, 0x05, 0x44, 0x10, 0x00, 0x80, 0xd5, 0x05, 0x40, 0x10, 0xa8, 0x56, +0x50, 0x10, 0x80, 0x80, 0x92, 0x08, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x80, 0x04, 0x46, 0x20, +0x10, 0x00, 0x44, 0x14, 0x00, 0x00, 0x98, 0xd9, 0x14, 0x04, 0x81, 0xca, 0x9d, 0x21, 0x4c, 0x31, +0x7f, 0xdf, 0x8d, 0x01, 0x84, 0x66, 0x4c, 0x81, 0xff, 0x9d, 0xf0, 0x05, 0xe6, 0x0f, 0xe8, 0x05, +0x80, 0x27, 0x44, 0x20, 0x0c, 0x0c, 0xd5, 0x2a, 0xf2, 0x05, 0x50, 0x11, 0x7f, 0xdc, 0x96, 0x48, +0xe6, 0x2d, 0xe8, 0x07, 0x2e, 0x11, 0x3a, 0x63, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x12, 0xd5, 0x0c, +0xf0, 0x05, 0x50, 0x10, 0x7f, 0xcc, 0x96, 0x48, 0xe6, 0x2d, 0xe8, 0x0e, 0x2e, 0x11, 0x3a, 0x63, +0x84, 0x41, 0x4c, 0x11, 0x40, 0x06, 0x80, 0x27, 0x44, 0x20, 0x19, 0x19, 0xd5, 0x0f, 0x80, 0x27, +0x44, 0x20, 0x22, 0x22, 0xd5, 0x0b, 0xf3, 0x05, 0x50, 0x11, 0xff, 0x9e, 0x96, 0x48, 0xe6, 0x31, +0xe8, 0x02, 0xd5, 0x01, 0x80, 0x27, 0x44, 0x20, 0x18, 0x18, 0xb6, 0x41, 0x50, 0x1f, 0x80, 0x9c, +0xf3, 0x03, 0xcb, 0x12, 0xa6, 0x88, 0xca, 0x20, 0xa6, 0x89, 0xca, 0x1e, 0xa6, 0x8a, 0xca, 0x1c, +0xa6, 0x8b, 0xca, 0x1a, 0xa6, 0x8c, 0xca, 0x18, 0xa6, 0x8d, 0xf0, 0x0a, 0x84, 0x21, 0x40, 0x00, +0x88, 0x1a, 0xf0, 0x8a, 0xd5, 0x11, 0xa6, 0x88, 0xca, 0x0f, 0xa6, 0x89, 0xca, 0x0d, 0xa6, 0x8a, +0xca, 0x0b, 0xa6, 0x8b, 0xca, 0x09, 0xa6, 0x8c, 0xca, 0x07, 0xa6, 0x8d, 0xf3, 0x07, 0x84, 0x21, +0x40, 0x30, 0x88, 0x1a, 0xf3, 0x87, 0xf0, 0x0a, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x0d, 0xf2, 0x07, +0x4c, 0x20, 0x40, 0x0a, 0xf3, 0x04, 0x44, 0x0f, 0x9f, 0xff, 0xb4, 0x23, 0x40, 0x10, 0x80, 0x02, +0xb6, 0x23, 0xd5, 0x0c, 0xf2, 0x04, 0x44, 0x3f, 0x9f, 0xff, 0xb4, 0x22, 0x40, 0x10, 0x8c, 0x02, +0xb6, 0x22, 0xb4, 0x22, 0x42, 0x10, 0xbc, 0x08, 0xb6, 0x22, 0xf1, 0x13, 0x84, 0x41, 0x4c, 0x11, +0x40, 0x27, 0xf3, 0x03, 0x50, 0x1f, 0x80, 0x9c, 0xcb, 0x0a, 0xa6, 0x8a, 0xc2, 0x29, 0xa6, 0x8b, +0xc2, 0x27, 0xa6, 0x8c, 0xc2, 0x25, 0xa6, 0x4d, 0xc1, 0x23, 0xd5, 0x0b, 0xa6, 0x8a, 0xc2, 0x07, +0xa6, 0x8b, 0xc2, 0x05, 0xa6, 0x8c, 0xc2, 0x03, 0xa6, 0x4d, 0xc9, 0x03, 0x84, 0x01, 0xf0, 0x87, +0xf1, 0x0a, 0x84, 0x41, 0x4c, 0x11, 0x00, 0x05, 0xf3, 0x07, 0x4c, 0x31, 0x40, 0x09, 0xf0, 0x04, +0x44, 0x2f, 0x9f, 0xff, 0xb4, 0x20, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0x49, 0xff, 0xd8, 0xf6, +0x49, 0xff, 0xe4, 0x2e, 0x92, 0x00, 0xf3, 0x03, 0x4e, 0x32, 0xf9, 0x8a, 0xd5, 0x04, 0x84, 0x01, +0xf0, 0x8a, 0xd5, 0xee, 0xec, 0xac, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x2c, 0x3e, 0x49, 0x31, 0xf0, 0x96, 0x00, 0x96, 0x48, 0xf0, 0x87, 0xf1, 0x89, 0x3a, 0x02, +0x04, 0x00, 0x96, 0x90, 0x96, 0xd8, 0x3e, 0x49, 0x31, 0xd8, 0xf0, 0xb0, 0x12, 0x1f, 0x80, 0x62, +0xf2, 0x8b, 0xf3, 0x88, 0x3a, 0x02, 0x0c, 0x04, 0x50, 0x5f, 0x80, 0x84, 0x3e, 0x69, 0x31, 0xd0, +0x3e, 0x89, 0x31, 0xb8, 0x51, 0xef, 0x80, 0x6c, 0x3a, 0x02, 0x8c, 0x24, 0x50, 0x0f, 0x80, 0x54, +0x3f, 0xc9, 0x31, 0xb0, 0x3e, 0xa9, 0x31, 0x88, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x8b, 0x60, +0xf0, 0x85, 0x3a, 0x02, 0x04, 0x00, 0x80, 0x45, 0x3a, 0x01, 0x04, 0x20, 0x50, 0x1f, 0x80, 0x9c, +0xf1, 0x84, 0x3a, 0x03, 0x04, 0x00, 0x3e, 0x49, 0x31, 0x98, 0xf0, 0xae, 0x12, 0x1f, 0x80, 0x5e, +0x3a, 0x04, 0x0c, 0x04, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x0d, 0xbc, 0x3a, 0x0f, 0x0c, 0x24, +0x3a, 0x04, 0x04, 0x00, 0x3a, 0x0f, 0x04, 0x20, 0x3a, 0x0e, 0x04, 0x00, 0xf0, 0xac, 0x12, 0x1f, +0x80, 0x5a, 0x3a, 0x02, 0x0c, 0x04, 0xf5, 0x05, 0x3a, 0x02, 0x8c, 0x24, 0x3a, 0x02, 0x04, 0x00, +0x3a, 0x02, 0x84, 0x20, 0x3a, 0x05, 0x08, 0x00, 0x3c, 0x4c, 0x4c, 0x65, 0xf3, 0x04, 0x40, 0x52, +0x40, 0x09, 0x3a, 0x01, 0x88, 0x20, 0x44, 0x10, 0x02, 0x44, 0x10, 0x5f, 0x80, 0xce, 0x12, 0x4f, +0x80, 0x66, 0xf0, 0x07, 0xdd, 0x27, 0x44, 0x00, 0x27, 0x00, 0x49, 0xff, 0xe3, 0xdf, 0x44, 0x00, +0x20, 0x04, 0x49, 0xff, 0xe3, 0xdb, 0x46, 0x40, 0x04, 0x12, 0x44, 0x50, 0x00, 0x42, 0xa9, 0x61, +0xf5, 0x09, 0xc5, 0x70, 0xf0, 0x07, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x2a, 0x00, 0x56, +0x58, 0x21, 0x06, 0x57, 0x84, 0x20, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, +0xf0, 0x07, 0x46, 0x23, 0x80, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, +0xf0, 0x07, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, +0x02, 0x95, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, +0xf0, 0x07, 0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, +0xf0, 0x07, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0xf0, 0x07, 0x44, 0x20, 0xb8, 0xb8, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x10, 0x84, 0xa8, 0x14, 0x52, 0x01, 0x48, 0x44, 0x10, +0x02, 0x0c, 0xf0, 0x07, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, +0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x50, 0x80, +0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x26, 0x84, 0xe0, 0x50, 0x6f, 0x80, 0xc8, +0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, 0x80, 0x46, 0x49, 0xff, 0xe3, 0x98, 0xf1, 0x32, 0x9d, 0xf9, +0x54, 0x10, 0x84, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd7, 0xe1, 0x44, 0x00, +0x03, 0xe8, 0x4c, 0x70, 0x7f, 0xef, 0x46, 0x40, 0x04, 0x10, 0x84, 0xa2, 0x14, 0x52, 0x01, 0x48, +0xd5, 0x73, 0xf0, 0x07, 0xf1, 0x09, 0xdd, 0x27, 0xf1, 0x09, 0xf0, 0x07, 0x46, 0x2a, 0x00, 0x56, +0x58, 0x21, 0x0e, 0x53, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x07, +0x46, 0x23, 0x80, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xf0, 0x07, +0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, +0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, 0xf0, 0x07, +0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, 0xf0, 0x07, +0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0xf0, 0x07, 0x44, 0x20, 0xa4, 0xa4, 0x44, 0x10, 0x02, 0x10, +0xdd, 0x26, 0x46, 0x40, 0x04, 0x10, 0x84, 0xa8, 0x14, 0x52, 0x01, 0x48, 0x44, 0x10, 0x02, 0x0c, +0xf0, 0x07, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, 0xdd, 0x26, +0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x50, 0x80, 0x58, 0x21, +0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x26, 0xf7, 0x09, 0x50, 0x6f, 0x80, 0xc8, 0xf0, 0x07, +0x44, 0x10, 0x02, 0x00, 0x80, 0x46, 0x49, 0xff, 0xe3, 0x29, 0xf1, 0x32, 0x9d, 0xf9, 0x54, 0x10, +0x84, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd7, 0x72, 0x44, 0x10, 0x03, 0xe8, +0x4c, 0x70, 0xff, 0xef, 0x46, 0x40, 0x04, 0x10, 0x84, 0xa2, 0x14, 0x52, 0x01, 0x48, 0x84, 0x20, +0xf0, 0x07, 0x49, 0xff, 0xe1, 0x49, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x04, 0xb8, 0x44, 0x00, +0x20, 0x88, 0xdd, 0x26, 0x44, 0x00, 0x23, 0x00, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x84, 0xe0, +0x85, 0x21, 0x81, 0x04, 0x14, 0x92, 0x00, 0x04, 0xa9, 0xe4, 0x80, 0xa4, 0x84, 0x82, 0x14, 0x44, +0x00, 0x22, 0x44, 0x40, 0x74, 0x08, 0x14, 0x42, 0x80, 0xc0, 0x44, 0x00, 0x10, 0x04, 0xdd, 0x26, +0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0x84, 0xa8, 0xb6, 0xe4, 0xb6, 0xa4, 0xb6, 0xe4, +0x44, 0x00, 0x20, 0x80, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x44, 0x53, 0x00, 0x01, 0x14, 0x52, +0x00, 0x20, 0x44, 0x00, 0x20, 0x84, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x44, 0x52, 0x00, 0x00, +0x14, 0x52, 0x00, 0x21, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x46, 0x54, +0x00, 0x02, 0x58, 0x52, 0x81, 0x01, 0x14, 0x52, 0x01, 0xc6, 0x44, 0x00, 0x27, 0x3c, 0xdd, 0x26, +0x46, 0x40, 0x04, 0x12, 0x46, 0x58, 0x00, 0x00, 0x14, 0x52, 0x01, 0xcf, 0x44, 0x00, 0x27, 0x14, +0xdd, 0x26, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x04, 0xdd, 0x26, 0x44, 0x00, +0x29, 0x80, 0xdd, 0x26, 0xf3, 0x07, 0x46, 0x08, 0x00, 0x00, 0x40, 0xa1, 0xf8, 0x08, 0x58, 0x00, +0x00, 0x12, 0x46, 0x90, 0x04, 0x12, 0x81, 0x09, 0x80, 0xa8, 0x46, 0x64, 0x80, 0x20, 0x59, 0xc1, +0x80, 0x80, 0x40, 0xa5, 0x00, 0x04, 0x58, 0x63, 0x00, 0x0c, 0x80, 0x85, 0x15, 0xc4, 0x81, 0xc5, +0x14, 0xa4, 0x02, 0x4d, 0x14, 0x62, 0x82, 0x60, 0x44, 0x50, 0x00, 0x60, 0x14, 0x52, 0x03, 0x04, +0x04, 0x62, 0x03, 0x05, 0x80, 0xa4, 0x58, 0x63, 0x00, 0x0c, 0x14, 0x62, 0x03, 0x05, 0x44, 0x41, +0x00, 0x00, 0x14, 0x42, 0x81, 0xc0, 0x84, 0x05, 0x49, 0xff, 0xd6, 0xe2, 0xf1, 0x08, 0x46, 0x00, +0x92, 0xf5, 0x40, 0x30, 0xf0, 0x08, 0x46, 0x50, 0x04, 0x12, 0x58, 0x00, 0x09, 0x04, 0x9e, 0x42, +0x40, 0x01, 0x80, 0x04, 0x58, 0x52, 0x87, 0x74, 0x40, 0x11, 0x84, 0x04, 0xf0, 0x8c, 0xf7, 0x8a, +0xf5, 0x88, 0xf1, 0x8d, 0xf3, 0x09, 0x4e, 0x32, 0x01, 0x41, 0x2e, 0x71, 0x3a, 0x7a, 0x44, 0x65, +0xa3, 0x84, 0x4e, 0x73, 0x00, 0x9e, 0x50, 0x1f, 0x80, 0xc0, 0x84, 0x46, 0x50, 0x0f, 0x80, 0xa8, +0xdd, 0x26, 0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, 0x80, 0x84, 0x44, 0x20, 0x00, 0x18, 0xdd, 0x26, +0x46, 0x80, 0x04, 0x12, 0x04, 0xaf, 0x80, 0x07, 0x05, 0xcf, 0x80, 0x0b, 0x4f, 0xc3, 0x00, 0x23, +0x50, 0x5f, 0x80, 0xa8, 0x38, 0x22, 0x9c, 0x00, 0x44, 0x11, 0x01, 0x00, 0x94, 0x94, 0x40, 0x21, +0x04, 0x04, 0x80, 0x0a, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd6, 0xb2, 0x50, 0x5f, 0x80, 0x3c, +0x46, 0x00, 0x92, 0xf5, 0x38, 0x32, 0x9e, 0x02, 0x40, 0x23, 0xf0, 0x08, 0x46, 0x10, 0x04, 0x12, +0x58, 0x00, 0x09, 0x02, 0x40, 0x21, 0x00, 0x04, 0x14, 0x34, 0x01, 0xc1, 0x14, 0x20, 0x81, 0xda, +0xd5, 0x11, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x80, 0x80, 0x0a, 0x49, 0xff, 0xd6, 0x98, +0x44, 0x10, 0x0a, 0x0a, 0x14, 0x14, 0x01, 0xc1, 0x46, 0x20, 0x04, 0x12, 0xf1, 0x0d, 0x14, 0x11, +0x01, 0xda, 0x84, 0xc0, 0x44, 0x00, 0x01, 0xf4, 0x49, 0xff, 0xd6, 0x7a, 0xf5, 0x08, 0x9d, 0xb1, +0xb4, 0x05, 0x97, 0xb1, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x05, 0x44, 0x00, 0x27, 0x10, 0x4c, 0x60, +0x7f, 0xf3, 0x84, 0x05, 0x49, 0xff, 0xd6, 0x6c, 0x46, 0x60, 0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, +0x58, 0x63, 0x07, 0x68, 0x58, 0x10, 0x89, 0x00, 0xb6, 0x26, 0x84, 0x05, 0x49, 0xff, 0xd6, 0x60, +0x4f, 0xc3, 0x00, 0x0c, 0x46, 0x50, 0x92, 0xf5, 0x40, 0x13, 0xf0, 0x08, 0x58, 0x52, 0x89, 0x04, +0x40, 0x10, 0x94, 0x04, 0xb6, 0x26, 0xd5, 0x04, 0xf0, 0x0c, 0x84, 0xea, 0xb6, 0x06, 0x84, 0xc0, +0x44, 0x00, 0x01, 0xf4, 0x49, 0xff, 0xd6, 0x4c, 0xf3, 0x08, 0x9d, 0xb1, 0xb4, 0x03, 0x97, 0xb1, +0x54, 0x00, 0x00, 0x08, 0xc0, 0x04, 0x44, 0x50, 0x27, 0x10, 0xde, 0xf3, 0x84, 0x05, 0x49, 0xff, +0xd6, 0x3f, 0x46, 0x20, 0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x80, 0x62, +0x14, 0x11, 0x01, 0xda, 0x84, 0x21, 0xa8, 0x5c, 0x84, 0x20, 0xa8, 0x5c, 0x9d, 0xf9, 0x84, 0x05, +0x49, 0xff, 0xd6, 0x2e, 0xe6, 0xe6, 0x4e, 0xf3, 0xff, 0x7b, 0x48, 0x00, 0x01, 0x66, 0x50, 0x1f, +0x80, 0xb8, 0x84, 0x46, 0x50, 0x0f, 0x80, 0xa8, 0xdd, 0x26, 0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, +0x80, 0x6c, 0x44, 0x20, 0x00, 0x18, 0xdd, 0x26, 0x46, 0x80, 0x04, 0x12, 0x04, 0xaf, 0x80, 0x07, +0x05, 0xcf, 0x80, 0x0b, 0x84, 0xe0, 0x4f, 0xc3, 0x00, 0x23, 0x50, 0x5f, 0x80, 0xa8, 0x38, 0x22, +0x9c, 0x00, 0x44, 0x11, 0x01, 0x00, 0x94, 0x94, 0x40, 0x21, 0x04, 0x04, 0x80, 0x0a, 0x44, 0x10, +0x02, 0x44, 0x49, 0xff, 0xd6, 0x15, 0x50, 0x5f, 0x80, 0x3c, 0x46, 0x00, 0x92, 0xf5, 0x38, 0x32, +0x9e, 0x02, 0x40, 0x23, 0xf0, 0x08, 0x46, 0x10, 0x04, 0x12, 0x58, 0x00, 0x09, 0x02, 0x40, 0x21, +0x00, 0x04, 0x14, 0x34, 0x01, 0xc1, 0x14, 0x20, 0x81, 0xda, 0xd5, 0x11, 0x44, 0x10, 0x02, 0x44, +0x44, 0x21, 0x01, 0x80, 0x80, 0x0a, 0x49, 0xff, 0xd5, 0xfb, 0x44, 0x10, 0x0a, 0x0a, 0x14, 0x14, +0x01, 0xc1, 0x46, 0x20, 0x04, 0x12, 0xf1, 0x0d, 0x14, 0x11, 0x01, 0xda, 0x84, 0xc0, 0x44, 0x00, +0x01, 0xf4, 0x49, 0xff, 0xd5, 0xdd, 0xf5, 0x08, 0x9d, 0xb1, 0xb4, 0x05, 0x97, 0xb1, 0x54, 0x00, +0x00, 0x08, 0xc0, 0x05, 0x44, 0x00, 0x27, 0x10, 0x4c, 0x60, 0x7f, 0xf3, 0x84, 0x05, 0x49, 0xff, +0xd5, 0xcf, 0x46, 0x60, 0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x63, 0x07, 0x68, 0x58, 0x10, +0x89, 0x00, 0xb6, 0x26, 0x84, 0x05, 0x49, 0xff, 0xd5, 0xc3, 0x4f, 0xc3, 0x00, 0x0c, 0x46, 0x50, +0x92, 0xf5, 0x40, 0x13, 0xf0, 0x08, 0x58, 0x52, 0x89, 0x04, 0x40, 0x10, 0x94, 0x04, 0xb6, 0x26, +0xd5, 0x04, 0xf0, 0x0c, 0x84, 0xea, 0xb6, 0x06, 0x84, 0xc0, 0x44, 0x00, 0x01, 0xf4, 0x49, 0xff, +0xd5, 0xaf, 0xf3, 0x08, 0x9d, 0xb1, 0xb4, 0x03, 0x97, 0xb1, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x04, +0x44, 0x50, 0x27, 0x10, 0xde, 0xf3, 0x84, 0x05, 0x49, 0xff, 0xd5, 0xa2, 0x46, 0x20, 0x04, 0x12, +0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x80, 0x62, 0x14, 0x11, 0x01, 0xda, 0x84, 0x21, +0xa8, 0x5c, 0x84, 0x20, 0xa8, 0x5c, 0x9d, 0xf9, 0x84, 0x05, 0x49, 0xff, 0xd5, 0x91, 0xe6, 0xe6, +0x4e, 0xf3, 0xff, 0x7b, 0x48, 0x00, 0x00, 0xc9, 0x2e, 0x11, 0x3a, 0x7b, 0x44, 0x65, 0xa3, 0x84, +0xc9, 0x62, 0x50, 0x1f, 0x80, 0xb0, 0x84, 0x46, 0x50, 0x0f, 0x80, 0xa8, 0xdd, 0x26, 0x50, 0x0f, +0x80, 0x3c, 0x50, 0x1f, 0x80, 0x54, 0x44, 0x20, 0x00, 0x18, 0x47, 0xc0, 0x04, 0x12, 0x46, 0x80, +0x04, 0x12, 0xdd, 0x26, 0x04, 0x9f, 0x80, 0x09, 0x58, 0x84, 0x07, 0x68, 0x50, 0xaf, 0x80, 0x3c, +0x50, 0x5f, 0x80, 0xa8, 0x38, 0x22, 0xa4, 0x00, 0x44, 0x11, 0x01, 0x00, 0xf0, 0x07, 0x94, 0x94, +0x40, 0x21, 0x04, 0x04, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd5, 0x72, 0x46, 0x50, 0x92, 0xf5, +0xb4, 0x6a, 0x40, 0x74, 0xf0, 0x08, 0x58, 0x52, 0x89, 0x02, 0x40, 0x13, 0x94, 0x04, 0x14, 0x3e, +0x01, 0xc1, 0xb6, 0x28, 0x84, 0xc0, 0xf1, 0x08, 0x9d, 0xb1, 0xb4, 0x01, 0x97, 0xb1, 0x54, 0x10, +0x00, 0x08, 0x84, 0x05, 0xc1, 0x06, 0x49, 0xff, 0xd5, 0x4b, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf4, +0x46, 0x00, 0x92, 0xf5, 0x58, 0x00, 0x09, 0x04, 0x9e, 0x44, 0x40, 0x23, 0x80, 0x04, 0xb6, 0x28, +0xb6, 0x48, 0x84, 0xc0, 0xf1, 0x08, 0x9d, 0xb1, 0xb4, 0x01, 0x97, 0xb1, 0x54, 0x10, 0x00, 0x08, +0x84, 0x05, 0xc1, 0x06, 0x49, 0xff, 0xd5, 0x34, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf4, 0x46, 0x10, +0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x8d, 0x21, 0x84, 0x06, 0xb6, 0x28, 0x8d, 0x44, 0x4c, 0x90, +0x7f, 0xb9, 0xd5, 0x62, 0x50, 0x1f, 0x80, 0xcc, 0x84, 0x43, 0x50, 0x0f, 0x80, 0xa8, 0xdd, 0x26, +0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, 0x80, 0x9c, 0x84, 0x4c, 0x47, 0xc0, 0x04, 0x12, 0x46, 0x80, +0x04, 0x12, 0xdd, 0x26, 0x04, 0x9f, 0x80, 0x09, 0x58, 0x84, 0x07, 0x68, 0x50, 0xaf, 0x80, 0x3c, +0x50, 0x1f, 0x80, 0xa8, 0x38, 0x20, 0xa4, 0x00, 0x44, 0x31, 0x01, 0x00, 0xf0, 0x07, 0x94, 0x94, +0x40, 0x21, 0x0c, 0x04, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd5, 0x12, 0x50, 0x14, 0x80, 0x03, +0x46, 0x00, 0x92, 0xf5, 0xb4, 0x6a, 0x40, 0x70, 0xf0, 0x08, 0x58, 0x00, 0x09, 0x02, 0x40, 0x23, +0x80, 0x04, 0x14, 0x3e, 0x01, 0xc1, 0xb6, 0x48, 0x84, 0xc0, 0xf1, 0x08, 0x9d, 0xb1, 0xb4, 0x01, +0x97, 0xb1, 0x54, 0x10, 0x00, 0x08, 0x84, 0x05, 0xc1, 0x06, 0x49, 0xff, 0xd4, 0xe9, 0x44, 0x50, +0x03, 0xe8, 0xde, 0xf4, 0x46, 0x00, 0x92, 0xf5, 0x58, 0x00, 0x09, 0x04, 0x9e, 0x84, 0x40, 0x13, +0x80, 0x04, 0xb6, 0x48, 0xb6, 0x28, 0x84, 0xc0, 0xf1, 0x08, 0x9d, 0xb1, 0xb4, 0x01, 0x97, 0xb1, +0x54, 0x10, 0x00, 0x08, 0x84, 0x05, 0xc1, 0x06, 0x49, 0xff, 0xd4, 0xd2, 0x44, 0x50, 0x03, 0xe8, +0xde, 0xf4, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x8d, 0x21, 0x84, 0x03, 0xb6, 0x28, +0x8d, 0x44, 0x4c, 0x90, 0x7f, 0xb7, 0xf1, 0x07, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x22, 0x46, 0x10, +0x04, 0x12, 0x80, 0x41, 0x80, 0x61, 0x80, 0x81, 0x80, 0xa1, 0x81, 0x01, 0x80, 0xe1, 0x80, 0xc1, +0x04, 0x10, 0x81, 0xe6, 0x04, 0x21, 0x01, 0xe7, 0x04, 0x31, 0x81, 0xe8, 0x04, 0x42, 0x01, 0xe9, +0x04, 0x52, 0x81, 0xf0, 0x04, 0x84, 0x01, 0xf1, 0x04, 0x73, 0x81, 0xf2, 0x04, 0x63, 0x01, 0xf3, +0x3e, 0x09, 0x18, 0x9c, 0xb7, 0x1f, 0xf7, 0x81, 0xf6, 0x82, 0x49, 0xff, 0x9b, 0xcb, 0xf5, 0x0a, +0x84, 0x02, 0x9d, 0x69, 0xf5, 0x8a, 0x4c, 0x50, 0x7d, 0xcf, 0x49, 0xff, 0xd4, 0xc7, 0x49, 0xff, +0xdf, 0xff, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, 0xe0, 0x21, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, +0x80, 0x04, 0x84, 0xe0, 0x84, 0x68, 0xb6, 0xe1, 0xb6, 0x61, 0xb6, 0xe1, 0x46, 0x60, 0x04, 0x12, +0x49, 0xff, 0xdf, 0xee, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xd4, 0x82, 0xa9, 0xf4, 0xf1, 0x0b, +0xc9, 0x1f, 0xf3, 0x07, 0x84, 0xa1, 0xdb, 0x1c, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x01, 0xda, +0x3c, 0x1e, 0x5f, 0xb0, 0x46, 0x00, 0x04, 0x12, 0x58, 0x00, 0x07, 0x80, 0x3e, 0x39, 0x7e, 0xc0, +0x46, 0x5f, 0xfb, 0xed, 0xb4, 0x40, 0x98, 0x43, 0x58, 0x52, 0x88, 0x84, 0x98, 0x4d, 0xb6, 0x41, +0x46, 0x10, 0x04, 0x12, 0x9c, 0x04, 0x58, 0x10, 0x87, 0xd4, 0x4c, 0x00, 0xff, 0xf1, 0x3e, 0x09, +0x18, 0xfc, 0x49, 0xff, 0x9b, 0x87, 0xec, 0xd4, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xf4, 0x3e, 0x49, 0x32, 0x74, 0x96, 0x00, 0x96, 0x48, 0x96, 0x90, +0xf0, 0x8d, 0xf1, 0x8e, 0xf2, 0x90, 0x3a, 0x02, 0x08, 0x00, 0x50, 0x5f, 0x80, 0xe4, 0x3e, 0x49, +0x32, 0x6c, 0x3a, 0x02, 0x84, 0x24, 0x50, 0x8f, 0x80, 0xf0, 0x3e, 0x79, 0x32, 0x64, 0x3a, 0x02, +0x04, 0x00, 0x96, 0xd8, 0x3a, 0x04, 0x04, 0x20, 0x3e, 0x49, 0x32, 0x3c, 0x3a, 0x03, 0x84, 0x00, +0x50, 0x7f, 0x80, 0x70, 0xae, 0xa8, 0xf3, 0x91, 0xf0, 0xbe, 0x12, 0x14, 0x00, 0x06, 0x3a, 0x02, +0x0c, 0x04, 0x83, 0x87, 0x50, 0x5f, 0x80, 0x94, 0x50, 0x6f, 0x80, 0xb4, 0x3f, 0xe9, 0x32, 0x1c, +0x3a, 0x0e, 0x0c, 0x24, 0x50, 0x0f, 0x80, 0xcc, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x8b, 0x60, +0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x0d, 0xbc, 0xf0, 0x89, 0x3a, 0x02, 0x0c, 0x04, 0xf5, 0x8b, +0xf6, 0x8a, 0x3a, 0x0e, 0x0c, 0x24, 0x3c, 0xac, 0x4c, 0x98, 0x80, 0xbe, 0x3a, 0x02, 0x8c, 0x04, +0x40, 0x95, 0x40, 0x09, 0xb4, 0x84, 0x10, 0x9f, 0x81, 0x06, 0xb6, 0x9c, 0xf4, 0x0b, 0x12, 0xaf, +0x80, 0x82, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x00, 0x3a, 0x02, 0x0c, 0x20, 0x3e, 0x49, +0x32, 0x04, 0x3a, 0x02, 0x0c, 0x04, 0xf5, 0x0a, 0x3a, 0x02, 0x8c, 0x24, 0x3e, 0x39, 0x31, 0xf8, +0x3a, 0x02, 0x04, 0x00, 0x3a, 0x02, 0x84, 0x20, 0x3a, 0x01, 0x88, 0x00, 0xf5, 0x09, 0x3a, 0x02, +0x88, 0x20, 0x44, 0x10, 0x02, 0x44, 0xf0, 0x0d, 0xdd, 0x27, 0x44, 0x00, 0x27, 0x00, 0x49, 0xff, +0xdf, 0x75, 0x44, 0x00, 0x20, 0x04, 0x49, 0xff, 0xdf, 0x71, 0x46, 0x40, 0x04, 0x12, 0x44, 0x00, +0x00, 0x42, 0xa8, 0x21, 0xf6, 0x0e, 0xc6, 0x75, 0xf0, 0x0d, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x0d, +0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x06, 0x57, 0x84, 0x20, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, +0x00, 0x10, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x23, 0x80, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, +0x00, 0x10, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, +0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, +0x01, 0x30, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0xab, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, +0x01, 0x30, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0xf0, 0x0d, 0x44, 0x20, +0xa8, 0xa8, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x28, 0x46, 0x40, 0x04, 0x10, 0x84, 0x08, 0x14, 0x02, +0x01, 0x48, 0x44, 0x10, 0x02, 0x0c, 0xf0, 0x0d, 0x50, 0x6f, 0x81, 0x00, 0xdd, 0x27, 0xf0, 0x0d, +0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x50, 0x80, 0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x28, 0x84, 0xe0, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x00, 0x80, 0x46, 0x49, 0xff, 0xdf, 0x2e, +0xf1, 0x40, 0x9d, 0xf9, 0x54, 0x10, 0x84, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, +0xd3, 0x77, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x70, 0x7f, 0xef, 0x46, 0x40, 0x04, 0x10, 0x84, 0x02, +0x14, 0x02, 0x01, 0x48, 0x3e, 0x09, 0x19, 0x10, 0x49, 0xff, 0x9a, 0x94, 0x48, 0x00, 0x00, 0x78, +0xf0, 0x0d, 0xf1, 0x0e, 0x50, 0x6f, 0x81, 0x00, 0xdd, 0x27, 0xf1, 0x0e, 0xf0, 0x0d, 0x46, 0x2a, +0x00, 0x56, 0x58, 0x21, 0x0e, 0x53, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, +0xf0, 0x0d, 0x46, 0x23, 0x80, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, +0xf0, 0x0d, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, +0x02, 0x95, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, +0xf0, 0x0d, 0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, +0xf0, 0x0d, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0xf0, 0x0d, 0x44, 0x20, 0xb8, 0xb8, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x28, 0x3e, 0x09, 0x19, 0x1c, 0x49, 0xff, 0x9a, 0x54, 0x46, 0x40, 0x04, 0x10, +0x84, 0x08, 0x14, 0x02, 0x01, 0x48, 0x44, 0x10, 0x02, 0x0c, 0xf0, 0x0d, 0xdd, 0x27, 0xf0, 0x0d, +0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x50, 0x80, 0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x28, 0xf7, 0x0e, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x00, 0x80, 0x46, 0x49, 0xff, 0xde, 0xb6, +0xf1, 0x40, 0x9d, 0xf9, 0x54, 0x10, 0x84, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, +0xd2, 0xff, 0x44, 0x10, 0x03, 0xe8, 0x4c, 0x70, 0xff, 0xef, 0x46, 0x40, 0x04, 0x10, 0x84, 0x02, +0x14, 0x02, 0x01, 0x48, 0x84, 0x21, 0xf0, 0x0d, 0x49, 0xff, 0xdc, 0xd6, 0x46, 0x40, 0x04, 0x12, +0x84, 0x60, 0x84, 0x01, 0xa8, 0x24, 0xa8, 0xe4, 0xf3, 0x8c, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, +0x84, 0xb8, 0x44, 0x00, 0x20, 0x88, 0xdd, 0x27, 0x46, 0x80, 0x04, 0x12, 0x44, 0x00, 0x23, 0x00, +0x81, 0x28, 0xdd, 0x27, 0x44, 0x20, 0x74, 0x08, 0x84, 0xc2, 0x14, 0x64, 0x00, 0x22, 0x14, 0x24, +0x80, 0xc0, 0x44, 0x00, 0x10, 0x04, 0xdd, 0x27, 0x44, 0x00, 0x27, 0x04, 0xdd, 0x27, 0x44, 0x00, +0x20, 0x80, 0xdd, 0x27, 0x44, 0x00, 0x20, 0x84, 0xdd, 0x27, 0x46, 0x50, 0x04, 0x12, 0xf5, 0x8f, +0xf3, 0x0c, 0xf0, 0x0f, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0x58, 0x00, 0x00, 0x80, +0x87, 0x88, 0xf0, 0x8f, 0xb6, 0x64, 0x15, 0xc2, 0x00, 0x00, 0xb6, 0x64, 0x14, 0x64, 0x00, 0x22, +0x44, 0x60, 0x74, 0x08, 0x14, 0x64, 0x80, 0xc0, 0x44, 0x03, 0x00, 0x01, 0xf6, 0x0f, 0x80, 0x45, +0x83, 0xc2, 0x46, 0xa4, 0x00, 0x02, 0x80, 0xa2, 0x46, 0x18, 0x00, 0x00, 0xb6, 0x06, 0x58, 0xa5, +0x01, 0x01, 0x44, 0x02, 0x00, 0x00, 0xb6, 0x64, 0x15, 0xc2, 0x00, 0x00, 0xb6, 0x64, 0x14, 0x01, +0x00, 0x21, 0x14, 0xaf, 0x01, 0xc6, 0x14, 0x12, 0x81, 0xcf, 0xf3, 0x8c, 0x44, 0x00, 0x27, 0x14, +0xdd, 0x27, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x27, 0xf1, 0x0d, 0x46, 0x28, 0x00, 0x00, 0x46, 0x90, +0x04, 0x12, 0x40, 0x00, 0xf8, 0x08, 0x81, 0x09, 0x58, 0x21, 0x00, 0x12, 0x40, 0x00, 0x08, 0x04, +0x80, 0xa8, 0x46, 0x74, 0x80, 0x10, 0x80, 0x85, 0x58, 0xa0, 0x80, 0x80, 0x14, 0xa4, 0x81, 0xc5, +0x14, 0x04, 0x02, 0x4d, 0x58, 0x73, 0x80, 0x06, 0x44, 0x01, 0x00, 0x00, 0x14, 0x72, 0x82, 0x60, +0x14, 0x02, 0x01, 0xc0, 0xf5, 0x0e, 0xf3, 0x0c, 0x4e, 0x52, 0x00, 0xfb, 0x2e, 0x41, 0x3a, 0x7a, +0xf0, 0x11, 0x50, 0x8f, 0x80, 0xd8, 0x40, 0x60, 0x70, 0x08, 0x44, 0x75, 0xa3, 0x84, 0x50, 0x9f, +0x80, 0x4c, 0xcc, 0x77, 0xf4, 0x8c, 0x50, 0x1f, 0x80, 0xe4, 0x84, 0x49, 0x80, 0x08, 0xdd, 0x27, +0x50, 0x1f, 0x80, 0x70, 0x80, 0x09, 0x44, 0x20, 0x00, 0x24, 0xdd, 0x27, 0x46, 0x10, 0x92, 0xf5, +0x58, 0x10, 0x89, 0x01, 0x40, 0x13, 0x04, 0x04, 0xf4, 0x0c, 0x46, 0xa0, 0x04, 0x12, 0x83, 0x8a, +0xf1, 0x8e, 0x80, 0xc4, 0xf2, 0x10, 0xca, 0x2e, 0x50, 0x3f, 0x80, 0xd8, 0x38, 0x21, 0x98, 0x00, +0x44, 0x51, 0x01, 0x00, 0xf0, 0x0d, 0x94, 0x94, 0x40, 0x21, 0x14, 0x04, 0x44, 0x10, 0x02, 0x44, +0x49, 0xff, 0xd2, 0x4e, 0x38, 0x04, 0x9a, 0x02, 0x14, 0x05, 0x01, 0xc1, 0xe6, 0xc6, 0xe8, 0x0c, +0x46, 0x20, 0x92, 0xf5, 0x40, 0x03, 0x70, 0x08, 0x58, 0x21, 0x09, 0x01, 0x46, 0x10, 0x04, 0x12, +0x40, 0x00, 0x08, 0x04, 0xd5, 0x0c, 0x9c, 0x33, 0x46, 0x30, 0x92, 0xf5, 0x40, 0x00, 0x70, 0x08, +0x58, 0x31, 0x89, 0x01, 0x46, 0x10, 0x04, 0x12, 0x40, 0x00, 0x0c, 0x04, 0x14, 0x00, 0x81, 0xda, +0xd5, 0x13, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x80, 0x49, 0xff, 0xd2, 0x28, +0x44, 0x00, 0x04, 0x04, 0x14, 0x05, 0x01, 0xc1, 0x46, 0x10, 0x04, 0x12, 0xf5, 0x0e, 0x14, 0x50, +0x81, 0xda, 0x44, 0x60, 0x00, 0x64, 0x84, 0xe0, 0x04, 0x1e, 0x01, 0xdd, 0x9d, 0xf9, 0x54, 0x10, +0x80, 0x08, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd2, 0x02, 0x44, 0x20, 0x27, 0x10, +0x4c, 0x71, 0x7f, 0xf4, 0x9d, 0xb1, 0x46, 0x10, 0x04, 0x12, 0x46, 0x20, 0x92, 0xf5, 0x58, 0x21, +0x09, 0x00, 0x97, 0xb1, 0x14, 0x20, 0x81, 0xda, 0xe6, 0xc9, 0xe9, 0xa5, 0x48, 0x00, 0x01, 0x19, +0xf3, 0x8c, 0x80, 0x5c, 0x50, 0x1f, 0x80, 0xf0, 0x80, 0x08, 0xdd, 0x27, 0x80, 0x09, 0x50, 0x1f, +0x80, 0x94, 0x44, 0x20, 0x00, 0x20, 0xdd, 0x27, 0x46, 0x50, 0x92, 0xf5, 0x58, 0x52, 0x89, 0x01, +0x40, 0x53, 0x14, 0x04, 0xf3, 0x0c, 0x46, 0xa0, 0x04, 0x12, 0x83, 0x8a, 0xf5, 0x8e, 0x80, 0xc3, +0xf0, 0x10, 0xc8, 0x2f, 0x50, 0x1f, 0x80, 0xd8, 0x38, 0x20, 0x98, 0x00, 0x44, 0x31, 0x01, 0x00, +0xf0, 0x0d, 0x94, 0x94, 0x40, 0x21, 0x0c, 0x04, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd1, 0xd8, +0x38, 0x04, 0x9a, 0x02, 0x14, 0x05, 0x01, 0xc1, 0xe6, 0xc5, 0xe8, 0x0d, 0x9c, 0x31, 0x46, 0x50, +0x92, 0xf5, 0x40, 0x00, 0x70, 0x08, 0x58, 0x52, 0x89, 0x01, 0x46, 0x10, 0x04, 0x12, 0x40, 0x00, +0x14, 0x04, 0xd5, 0x0c, 0x9c, 0x34, 0x46, 0x20, 0x92, 0xf5, 0x40, 0x00, 0x70, 0x08, 0x58, 0x21, +0x09, 0x01, 0x46, 0x10, 0x04, 0x12, 0x40, 0x00, 0x08, 0x04, 0x14, 0x00, 0x81, 0xda, 0xd5, 0x13, +0xf0, 0x0d, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x80, 0x49, 0xff, 0xd1, 0xb1, 0x44, 0x00, +0x04, 0x04, 0x14, 0x05, 0x01, 0xc1, 0x46, 0x10, 0x04, 0x12, 0xf3, 0x0e, 0x14, 0x30, 0x81, 0xda, +0x44, 0x60, 0x00, 0x64, 0x84, 0xe0, 0x04, 0x1e, 0x01, 0xdd, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, +0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd1, 0x8b, 0x44, 0x00, 0x27, 0x10, 0x4c, 0x70, +0x7f, 0xf4, 0x9d, 0xb1, 0x46, 0x10, 0x04, 0x12, 0x46, 0x20, 0x92, 0xf5, 0x58, 0x21, 0x09, 0x00, +0x97, 0xb1, 0x14, 0x20, 0x81, 0xda, 0xe6, 0xc8, 0xe9, 0xa4, 0x48, 0x00, 0x00, 0xa2, 0x2e, 0x01, +0x3a, 0x7b, 0x50, 0x8f, 0x80, 0xd8, 0x44, 0x75, 0xa3, 0x84, 0x50, 0x9f, 0x80, 0x4c, 0xc8, 0x4d, +0x50, 0x1f, 0x80, 0xf8, 0x84, 0x46, 0x80, 0x08, 0xdd, 0x27, 0x46, 0x30, 0x04, 0x12, 0xf3, 0x8f, +0x80, 0x09, 0x50, 0x1f, 0x80, 0xb4, 0x44, 0x20, 0x00, 0x18, 0xdd, 0x27, 0xf5, 0x0f, 0x46, 0xa0, +0x04, 0x12, 0x58, 0x52, 0x87, 0x04, 0x83, 0x8a, 0xf6, 0x0e, 0xf5, 0x8f, 0x50, 0x0f, 0x80, 0xd8, +0x38, 0x20, 0x18, 0x00, 0x44, 0x11, 0x01, 0x00, 0xf0, 0x0d, 0x94, 0x94, 0x40, 0x21, 0x04, 0x04, +0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd1, 0x5c, 0x46, 0x50, 0x92, 0xf5, 0xb4, 0x49, 0xf0, 0x0f, +0x40, 0x13, 0x70, 0x08, 0x58, 0x52, 0x89, 0x01, 0x40, 0x10, 0x94, 0x04, 0xb6, 0x40, 0x14, 0x15, +0x01, 0xda, 0x84, 0xe0, 0x04, 0x1e, 0x01, 0xdd, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, 0x97, 0xf9, +0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd1, 0x34, 0x44, 0x10, 0x27, 0x10, 0x4c, 0x70, 0xff, 0xf4, +0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x9d, 0xb1, 0x84, 0x46, 0x14, 0x15, 0x01, 0xda, +0x8d, 0x24, 0x4c, 0x61, 0x7f, 0xcd, 0xd5, 0x4c, 0x50, 0x1f, 0x81, 0x04, 0x84, 0x43, 0x80, 0x08, +0xdd, 0x27, 0x46, 0x30, 0x04, 0x12, 0xf3, 0x8f, 0x80, 0x09, 0x50, 0x1f, 0x80, 0xcc, 0x84, 0x4c, +0xdd, 0x27, 0xf5, 0x0f, 0x46, 0xa0, 0x04, 0x12, 0x58, 0x52, 0x87, 0x04, 0x83, 0x8a, 0xf6, 0x0e, +0xf5, 0x8f, 0x50, 0x0f, 0x80, 0xd8, 0x38, 0x20, 0x18, 0x00, 0x44, 0x11, 0x01, 0x00, 0xf0, 0x0d, +0x94, 0x94, 0x40, 0x21, 0x04, 0x04, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd1, 0x11, 0x9c, 0x73, +0x46, 0x50, 0x92, 0xf5, 0xb4, 0x49, 0xf0, 0x0f, 0x40, 0x10, 0xf0, 0x08, 0x58, 0x52, 0x89, 0x01, +0x40, 0x10, 0x94, 0x04, 0xb6, 0x40, 0x14, 0x15, 0x01, 0xda, 0x84, 0xe0, 0x04, 0x1e, 0x01, 0xdd, +0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd0, 0xe8, +0x44, 0x10, 0x27, 0x10, 0x4c, 0x70, 0xff, 0xf4, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, +0x9d, 0xb1, 0x84, 0x43, 0x14, 0x15, 0x01, 0xda, 0x8d, 0x24, 0x4c, 0x61, 0x7f, 0xcc, 0x46, 0x10, +0x04, 0x12, 0x84, 0x01, 0xa8, 0x0c, 0x84, 0x00, 0xa8, 0x0c, 0x84, 0x05, 0x49, 0xff, 0xd0, 0xd0, +0x46, 0x10, 0x04, 0x12, 0x84, 0xe0, 0x14, 0x70, 0x82, 0x60, 0x49, 0xff, 0xd0, 0xf7, 0x49, 0xff, +0xdc, 0x2f, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, 0xdc, 0x51, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, +0x80, 0x04, 0x84, 0x08, 0xb6, 0xe1, 0xb6, 0x01, 0xb6, 0xe1, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, +0xdc, 0x1f, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xd0, 0xb3, 0xa9, 0xf4, 0x84, 0xa1, 0xf3, 0x0d, +0xdb, 0x36, 0x46, 0x10, 0x04, 0x12, 0x80, 0x41, 0x80, 0x61, 0x80, 0x81, 0x80, 0xa1, 0x83, 0x81, +0x81, 0x41, 0x81, 0x21, 0x81, 0x01, 0x80, 0xe1, 0x80, 0xc1, 0x80, 0x01, 0x04, 0x10, 0x81, 0xe0, +0x04, 0x21, 0x01, 0xe1, 0x04, 0x31, 0x81, 0xe2, 0x04, 0x42, 0x01, 0xe3, 0x04, 0x52, 0x81, 0xe4, +0x05, 0xce, 0x01, 0xe5, 0x04, 0xa5, 0x01, 0xea, 0x04, 0x94, 0x81, 0xeb, 0x04, 0x84, 0x01, 0xec, +0x04, 0x73, 0x81, 0xed, 0x04, 0x63, 0x01, 0xee, 0x05, 0xe0, 0x01, 0xef, 0x3e, 0x09, 0x19, 0x28, +0x15, 0xcf, 0x80, 0x00, 0x14, 0xaf, 0x80, 0x01, 0x14, 0x9f, 0x80, 0x02, 0x14, 0x8f, 0x80, 0x03, +0xf7, 0x84, 0xf6, 0x85, 0x15, 0xef, 0x80, 0x06, 0x49, 0xff, 0x97, 0xa4, 0x3e, 0x09, 0x19, 0x90, +0x49, 0xff, 0x97, 0xa0, 0xed, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x6c, 0x3e, 0x49, 0x31, 0x7c, 0x96, 0x00, 0x96, 0x48, 0xf0, 0x86, 0xf1, 0x87, 0x97, 0x90, +0x3a, 0x02, 0x08, 0x00, 0x50, 0x5f, 0x80, 0x7c, 0x3e, 0x49, 0x31, 0x70, 0x3a, 0x02, 0x88, 0x20, +0x50, 0x7f, 0x80, 0x70, 0x3e, 0x59, 0x31, 0x58, 0x3a, 0x02, 0x08, 0x00, 0x50, 0x8f, 0x80, 0x58, +0x3e, 0x49, 0x31, 0x40, 0x3a, 0x03, 0x88, 0x20, 0x50, 0x7f, 0x80, 0x40, 0x3a, 0x02, 0x8c, 0x04, +0x3a, 0x04, 0x0c, 0x24, 0x3a, 0x02, 0x84, 0x00, 0x3a, 0x04, 0x04, 0x20, 0x3a, 0x02, 0x0c, 0x04, +0x3a, 0x03, 0x8c, 0x24, 0x3a, 0x02, 0x04, 0x00, 0x3a, 0x03, 0x84, 0x20, 0x84, 0x01, 0x4c, 0x60, +0x40, 0x31, 0xf1, 0x07, 0xe6, 0x23, 0x4e, 0xf2, 0x02, 0x4f, 0x8c, 0x17, 0x42, 0x00, 0x80, 0x24, +0x3e, 0x39, 0x82, 0x50, 0x98, 0x03, 0x80, 0x60, 0xa3, 0x19, 0x46, 0x20, 0x04, 0x12, 0x14, 0x41, +0x02, 0x06, 0x84, 0xa3, 0xb4, 0x83, 0x42, 0x30, 0x94, 0x24, 0x14, 0x41, 0x02, 0x07, 0x9c, 0xd9, +0x3e, 0x19, 0x82, 0x50, 0x38, 0x20, 0x8f, 0x02, 0x46, 0x10, 0x04, 0x12, 0x14, 0x20, 0x82, 0x08, +0x40, 0x31, 0x94, 0x0c, 0x3e, 0x59, 0x82, 0x50, 0x98, 0xdd, 0xa0, 0x99, 0x14, 0x20, 0x82, 0x09, +0xa0, 0x84, 0x14, 0x20, 0x82, 0x0a, 0xa0, 0x05, 0x14, 0x00, 0x82, 0x0b, 0x48, 0x00, 0x02, 0x24, +0x84, 0x20, 0x44, 0x20, 0x00, 0x48, 0x3e, 0x09, 0x82, 0x50, 0x49, 0xfe, 0x63, 0x1d, 0xf0, 0x06, +0x44, 0x10, 0x02, 0x8c, 0x50, 0x2f, 0x80, 0x88, 0x49, 0xff, 0xdb, 0xb0, 0xf0, 0x06, 0x46, 0x38, +0x30, 0xf0, 0x96, 0x84, 0x46, 0x50, 0x30, 0xf0, 0x40, 0x21, 0x6c, 0x08, 0x84, 0x20, 0x40, 0x31, +0x0c, 0x04, 0x40, 0x51, 0x14, 0x04, 0x58, 0x00, 0x00, 0x80, 0xf1, 0x84, 0xf3, 0x8c, 0xf5, 0x8b, +0xf1, 0x88, 0xf1, 0x83, 0xf0, 0x8f, 0x04, 0xaf, 0x80, 0x06, 0x48, 0x00, 0x01, 0x8c, 0xf1, 0x02, +0x84, 0xa2, 0x56, 0x60, 0x80, 0x01, 0x84, 0x83, 0xf2, 0x05, 0xf3, 0x0a, 0x40, 0x82, 0x18, 0x1b, +0x40, 0x82, 0x98, 0x1a, 0xf5, 0x09, 0x8c, 0x58, 0x8c, 0x78, 0x8c, 0xb8, 0xf2, 0x85, 0xf3, 0x8a, +0xf5, 0x89, 0xf2, 0x0e, 0x80, 0x0a, 0x44, 0x10, 0x02, 0x8c, 0x49, 0xff, 0xcf, 0xe1, 0xf0, 0x02, +0xc8, 0x08, 0x46, 0x50, 0x04, 0x12, 0x58, 0x52, 0x80, 0x04, 0x44, 0x40, 0x00, 0x42, 0xd5, 0x11, +0xf1, 0x02, 0x84, 0xa1, 0xd9, 0x08, 0x46, 0x50, 0x04, 0x12, 0x58, 0x52, 0x80, 0x04, 0x44, 0x40, +0x00, 0x52, 0xd5, 0x07, 0x46, 0x50, 0x04, 0x12, 0x58, 0x52, 0x80, 0x04, 0x44, 0x40, 0x00, 0x5a, +0xb6, 0x85, 0xf3, 0x03, 0x97, 0x19, 0xe6, 0x84, 0xe8, 0x14, 0xf5, 0x02, 0xcd, 0x12, 0xf1, 0x08, +0x50, 0x0f, 0x80, 0x7c, 0x38, 0x60, 0x04, 0x00, 0x84, 0x21, 0x80, 0x41, 0x80, 0x66, 0x80, 0x0a, +0x49, 0xff, 0xfb, 0x50, 0x84, 0x21, 0x80, 0x0a, 0x80, 0x66, 0x80, 0x41, 0x49, 0xff, 0xf6, 0xe8, +0x46, 0x50, 0x04, 0x12, 0x04, 0x42, 0x82, 0x60, 0x42, 0x42, 0x78, 0x09, 0x14, 0x42, 0x82, 0x60, +0x80, 0xc5, 0x04, 0x43, 0x03, 0x04, 0x58, 0x42, 0x00, 0x67, 0x14, 0x43, 0x03, 0x04, 0x04, 0x42, +0x83, 0x05, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x8b, 0x60, 0x58, 0x42, 0x00, 0x0c, 0x14, 0x42, +0x83, 0x05, 0x80, 0x0a, 0x84, 0x20, 0xdd, 0x27, 0x46, 0x38, 0x00, 0x56, 0x58, 0x31, 0x87, 0x57, +0x40, 0x84, 0x60, 0x08, 0x40, 0x24, 0x0c, 0x04, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x0d, 0xbc, +0x84, 0x20, 0x80, 0x0a, 0xdd, 0x26, 0x80, 0x0a, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0x46, 0x23, +0x0d, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0x80, 0x0a, 0xdd, 0x26, 0x80, 0x0a, +0x44, 0x10, 0x02, 0x44, 0xdd, 0x27, 0x44, 0x21, 0x01, 0x80, 0x44, 0x10, 0x02, 0x44, 0x80, 0x0a, +0xdd, 0x26, 0x80, 0x0a, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, 0x46, 0x20, 0x0c, 0x21, 0x58, 0x21, +0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x80, 0x0a, 0xdd, 0x26, 0x46, 0x50, 0x04, 0x10, 0x84, 0x88, +0x14, 0x42, 0x81, 0x48, 0x94, 0x66, 0x80, 0x0a, 0xdd, 0x27, 0x46, 0x20, 0x50, 0x00, 0x80, 0x0a, +0x58, 0x21, 0x01, 0x0f, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x26, 0x84, 0xc0, 0x44, 0x10, 0x02, 0x00, +0x50, 0x2f, 0x80, 0x8c, 0x80, 0x0a, 0x49, 0xff, 0xda, 0xe9, 0xf1, 0x23, 0x9d, 0xb1, 0x54, 0x10, +0x81, 0x00, 0x97, 0xb1, 0x84, 0x05, 0xc1, 0x05, 0xdd, 0x3c, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xef, +0x46, 0x50, 0x04, 0x10, 0x84, 0x82, 0x14, 0x42, 0x81, 0x48, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, +0x04, 0xb8, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x26, 0x44, 0x00, 0x20, 0x04, 0xdd, 0x26, 0x44, 0x00, +0x2c, 0xf8, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x28, 0x14, 0xdd, 0x26, +0x44, 0x00, 0x29, 0xf0, 0xdd, 0x26, 0x44, 0x00, 0x23, 0x00, 0xdd, 0x26, 0x46, 0x70, 0x04, 0x12, +0x44, 0x00, 0x10, 0x04, 0xdd, 0x26, 0x44, 0x50, 0x74, 0x08, 0x46, 0x80, 0x04, 0x11, 0x14, 0x53, +0x80, 0xc0, 0x84, 0x81, 0x58, 0x84, 0x00, 0x04, 0x50, 0x94, 0x10, 0x0c, 0x84, 0xc0, 0x84, 0xa8, +0xb6, 0xc8, 0xb6, 0xa8, 0xb6, 0xc8, 0xb6, 0x89, 0xf4, 0x81, 0x84, 0x05, 0xdd, 0x3c, 0xb6, 0xc9, +0x46, 0x50, 0x04, 0x12, 0xf1, 0x0f, 0x14, 0x12, 0x81, 0xc5, 0x50, 0x5f, 0x80, 0x40, 0xf2, 0x04, +0x84, 0x0a, 0x38, 0x72, 0x88, 0x02, 0x46, 0x50, 0x04, 0x12, 0x14, 0x72, 0x83, 0x3e, 0x50, 0x5f, +0x80, 0x58, 0x38, 0x82, 0x88, 0x02, 0x46, 0x50, 0x04, 0x12, 0x80, 0xe5, 0x14, 0x82, 0x81, 0xc1, +0x44, 0x53, 0x00, 0x21, 0x14, 0x53, 0x80, 0x20, 0x46, 0x70, 0x04, 0x12, 0xdd, 0x3c, 0xf3, 0x0d, +0x46, 0x50, 0x04, 0x12, 0x14, 0x32, 0x82, 0x05, 0x58, 0x73, 0x89, 0xf0, 0xf5, 0x0b, 0x84, 0x05, +0xb6, 0xa7, 0xf4, 0x01, 0xb6, 0x89, 0xdd, 0x3c, 0xb6, 0xc9, 0xf0, 0x0c, 0xb6, 0x07, 0xb4, 0x27, +0x9d, 0xb1, 0x97, 0xb1, 0x84, 0x0a, 0x4e, 0x14, 0x00, 0x06, 0xdd, 0x3c, 0x44, 0x50, 0x03, 0xe8, +0xde, 0xf7, 0x84, 0x0a, 0xdd, 0x3c, 0x4e, 0xa3, 0x00, 0x1e, 0x46, 0x60, 0x04, 0x12, 0x80, 0xe6, +0x46, 0x80, 0x04, 0x12, 0x58, 0x84, 0x08, 0x20, 0x04, 0x23, 0x02, 0x06, 0xf1, 0x03, 0x04, 0x33, +0x82, 0x07, 0xb4, 0x88, 0x3e, 0x09, 0x19, 0xa4, 0x49, 0xff, 0x95, 0xd4, 0x04, 0x43, 0x02, 0x06, +0xf2, 0x05, 0xb6, 0x82, 0x04, 0x43, 0x82, 0x07, 0xa9, 0x11, 0xb4, 0x88, 0xf3, 0x0a, 0xb6, 0x83, +0xd5, 0x1c, 0x46, 0x60, 0x04, 0x12, 0x80, 0xe6, 0x46, 0x80, 0x04, 0x12, 0x58, 0x84, 0x08, 0x2c, +0x04, 0x23, 0x02, 0x09, 0xf1, 0x03, 0x04, 0x33, 0x82, 0x0a, 0xb4, 0x88, 0x3e, 0x09, 0x19, 0xa4, +0x49, 0xff, 0x95, 0xb8, 0x04, 0x43, 0x02, 0x09, 0xf5, 0x0a, 0xa9, 0x29, 0x04, 0x43, 0x82, 0x0a, +0xf0, 0x09, 0xb6, 0x80, 0xb4, 0x88, 0xa9, 0x01, 0x46, 0x70, 0x04, 0x12, 0x58, 0x73, 0x80, 0x10, +0x49, 0xff, 0xce, 0xac, 0x49, 0xff, 0xd9, 0xe4, 0xb4, 0xc7, 0x84, 0x01, 0x40, 0x63, 0x00, 0x04, +0xb6, 0xc7, 0xdd, 0x3c, 0x42, 0x43, 0x00, 0x09, 0xb6, 0x87, 0x84, 0x02, 0xdd, 0x3c, 0xf2, 0x02, +0x84, 0xa3, 0x9c, 0xd1, 0x96, 0xd9, 0xf3, 0x82, 0x4c, 0x32, 0xfe, 0x83, 0xf0, 0x03, 0xf1, 0x08, +0xf2, 0x04, 0x9c, 0x01, 0x9c, 0x4a, 0x9c, 0x94, 0x84, 0xa6, 0xf0, 0x83, 0xf1, 0x88, 0xf2, 0x84, +0xd0, 0x1f, 0xf5, 0x08, 0x50, 0x2f, 0x80, 0x70, 0x38, 0x21, 0x14, 0x01, 0x84, 0x20, 0x46, 0x30, +0x3e, 0x40, 0xf5, 0x03, 0x3e, 0x09, 0x82, 0x50, 0xf1, 0x82, 0x80, 0x20, 0xf0, 0x85, 0x40, 0x31, +0x0c, 0x04, 0x99, 0x6d, 0x8c, 0x08, 0x8c, 0x30, 0xf3, 0x8e, 0xf5, 0x8d, 0xf0, 0x8a, 0xf1, 0x89, +0x85, 0x00, 0x47, 0xc0, 0x00, 0x87, 0x59, 0xce, 0x0d, 0x9c, 0x48, 0xff, 0xfe, 0x6c, 0xf3, 0x07, +0x44, 0x20, 0x00, 0x18, 0x42, 0x21, 0x88, 0x24, 0x3e, 0x59, 0x82, 0x50, 0x98, 0x95, 0x80, 0x82, +0xa3, 0x61, 0x46, 0x30, 0x04, 0x12, 0x14, 0x51, 0x82, 0x06, 0xf0, 0x07, 0xf5, 0x02, 0xb4, 0x84, +0x42, 0x10, 0x14, 0x24, 0x14, 0x41, 0x82, 0x07, 0x9c, 0xc9, 0x3e, 0x19, 0x82, 0x50, 0x38, 0x40, +0x8f, 0x02, 0x46, 0x10, 0x04, 0x12, 0x14, 0x40, 0x82, 0x08, 0x3e, 0x09, 0x82, 0x50, 0x94, 0xdb, +0x98, 0xd8, 0xa0, 0xd9, 0x14, 0x30, 0x82, 0x09, 0xa0, 0xd4, 0x14, 0x30, 0x82, 0x0a, 0x80, 0x61, +0xa0, 0x95, 0x14, 0x21, 0x82, 0x0b, 0x84, 0x41, 0x14, 0x20, 0x82, 0x05, 0x44, 0x10, 0x02, 0x8c, +0xf2, 0x22, 0xf0, 0x06, 0x49, 0xff, 0xce, 0x1c, 0x92, 0x00, 0xf1, 0x06, 0x84, 0xa1, 0xd9, 0x1b, +0x3c, 0x1c, 0x5f, 0xb0, 0x46, 0x00, 0x04, 0x12, 0x14, 0x10, 0x01, 0xda, 0x46, 0x00, 0x04, 0x12, +0x58, 0x00, 0x07, 0x80, 0x3e, 0x39, 0x7e, 0xc0, 0x46, 0x5f, 0xfb, 0xed, 0x98, 0x43, 0x58, 0x52, +0x88, 0x84, 0x98, 0x4d, 0xb4, 0x21, 0xaa, 0x41, 0x46, 0x10, 0x04, 0x12, 0x58, 0x10, 0x87, 0xd4, +0x4c, 0x00, 0xff, 0xf2, 0xec, 0x94, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0x96, 0x49, 0x80, 0xe0, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x01, 0x9c, 0xb4, 0xc0, +0x3e, 0x09, 0x19, 0xc8, 0x80, 0x26, 0x49, 0xff, 0x95, 0x05, 0x46, 0x10, 0x04, 0x12, 0x46, 0x30, +0x04, 0x11, 0x46, 0x08, 0x00, 0x08, 0x80, 0x43, 0x44, 0x4f, 0xf5, 0x7c, 0x04, 0xa0, 0x80, 0x49, +0x14, 0x40, 0x80, 0x49, 0x14, 0x01, 0x80, 0x99, 0x14, 0x01, 0x00, 0x9a, 0x84, 0x08, 0x4c, 0x60, +0x00, 0x93, 0xe6, 0xc9, 0xe8, 0x16, 0x84, 0x24, 0x4c, 0x60, 0x80, 0x43, 0xe6, 0xc5, 0xe8, 0x0a, +0x84, 0x42, 0x4c, 0x61, 0x00, 0x30, 0xe6, 0xc3, 0xe8, 0x32, 0x84, 0x61, 0x4c, 0x61, 0xc1, 0x60, +0xd5, 0x25, 0x84, 0x06, 0x4c, 0x60, 0x00, 0x43, 0x9d, 0xfc, 0xe6, 0xc7, 0xe8, 0x6f, 0xd5, 0x38, +0x84, 0x2c, 0x4c, 0x60, 0x80, 0xc7, 0xe6, 0xcd, 0xe8, 0x0a, 0x84, 0x4a, 0x4c, 0x61, 0x00, 0x92, +0x9d, 0xfc, 0xe6, 0xcb, 0x4e, 0xf2, 0x00, 0xa9, 0x48, 0x00, 0x00, 0x83, 0x84, 0x6e, 0x4c, 0x61, +0x80, 0xdf, 0xe2, 0xc3, 0x4e, 0xf3, 0x00, 0xc7, 0x84, 0x0f, 0x4c, 0x60, 0x01, 0x33, 0x44, 0x10, +0x00, 0xff, 0x4c, 0x60, 0xc1, 0x3d, 0x48, 0x00, 0x01, 0x30, 0x49, 0xff, 0xed, 0x05, 0x48, 0x00, +0x01, 0x37, 0x80, 0x07, 0x49, 0xff, 0xd8, 0x90, 0x48, 0x00, 0x01, 0x32, 0x9d, 0xfc, 0xb4, 0xc7, +0x49, 0xff, 0xd0, 0xe6, 0x96, 0x30, 0x49, 0xff, 0xcd, 0xe1, 0x48, 0x00, 0x01, 0x29, 0x9d, 0xfc, +0xb4, 0xe7, 0x46, 0x60, 0x00, 0x8a, 0x58, 0x63, 0x07, 0xd0, 0x48, 0x00, 0x00, 0x99, 0xb4, 0x07, +0x96, 0x00, 0x49, 0xff, 0xd9, 0xd9, 0x48, 0x00, 0x01, 0x1b, 0x9d, 0xfc, 0xb5, 0x07, 0x3e, 0x69, +0x7e, 0x74, 0x54, 0x84, 0x00, 0x01, 0x4e, 0x82, 0x00, 0x16, 0x46, 0x00, 0x04, 0x12, 0x58, 0x00, +0x07, 0xd0, 0xb4, 0x20, 0x44, 0x2f, 0xff, 0x88, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0x2e, 0x21, +0x3a, 0x7e, 0xb4, 0x20, 0x38, 0x23, 0x08, 0x00, 0x40, 0x11, 0x04, 0x04, 0xb6, 0x20, 0x48, 0x00, +0x00, 0xff, 0x49, 0xff, 0xd0, 0xb5, 0x80, 0x08, 0x49, 0xff, 0xe1, 0x08, 0x84, 0x01, 0x49, 0xff, +0xe1, 0x05, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x01, 0xf4, 0x2e, 0x01, 0x3a, 0x7e, 0x54, 0x10, +0x80, 0x77, 0x38, 0x13, 0x00, 0x08, 0x48, 0x00, 0x00, 0xeb, 0xb4, 0xe7, 0x49, 0xff, 0xd0, 0xa0, +0x97, 0xf8, 0x84, 0x00, 0x80, 0x27, 0x80, 0x40, 0x80, 0x60, 0x46, 0x60, 0x00, 0x8d, 0x58, 0x63, +0x04, 0xf0, 0xd5, 0x0e, 0x9d, 0xfc, 0xb4, 0xe7, 0x49, 0xff, 0xd0, 0x92, 0x97, 0xf8, 0x84, 0x00, +0x80, 0x27, 0x80, 0x40, 0x80, 0x60, 0x46, 0x60, 0x00, 0x8c, 0x58, 0x63, 0x0c, 0x2c, 0xdd, 0x26, +0x84, 0x40, 0x80, 0x27, 0x84, 0x01, 0x80, 0x62, 0xdd, 0x26, 0x48, 0x00, 0x00, 0xc9, 0xb4, 0x07, +0xb4, 0x27, 0x96, 0x00, 0x92, 0x28, 0x96, 0x48, 0x49, 0xff, 0xdc, 0x26, 0x48, 0x00, 0x00, 0xc0, +0x50, 0x43, 0x80, 0x08, 0x9c, 0x7c, 0xb4, 0x01, 0xb4, 0xa1, 0xb4, 0x24, 0xb4, 0x44, 0xb4, 0x64, +0xb4, 0x84, 0x92, 0x48, 0x92, 0x70, 0x92, 0xa8, 0x96, 0xd8, 0x96, 0x00, 0x96, 0x48, 0x96, 0x90, +0x92, 0x98, 0x97, 0x68, 0x49, 0xff, 0xd4, 0x32, 0x44, 0x30, 0x00, 0xff, 0x4c, 0x01, 0xc0, 0xa8, +0xb6, 0x07, 0x48, 0x00, 0x00, 0xa5, 0x46, 0x60, 0x04, 0x10, 0x58, 0x63, 0x00, 0x40, 0xb4, 0x07, +0xb4, 0x27, 0xb4, 0xe6, 0xb4, 0x46, 0x44, 0x3f, 0xff, 0x3f, 0x40, 0x21, 0x0c, 0x02, 0x92, 0x28, +0xb6, 0x46, 0x96, 0x00, 0x96, 0x48, 0x49, 0xff, 0xed, 0x69, 0xb6, 0xe6, 0x48, 0x00, 0x00, 0x90, +0x9d, 0xfc, 0xb4, 0xe7, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x0e, 0x8c, 0x97, 0xf8, 0x49, 0xff, +0xd0, 0x3f, 0x80, 0x27, 0x84, 0x00, 0xdd, 0x26, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x26, 0x48, 0x00, +0x00, 0x7f, 0x9d, 0xfc, 0xb4, 0xc7, 0xb5, 0x07, 0x97, 0xb0, 0xe6, 0xc3, 0xe8, 0x78, 0x42, 0x84, +0x20, 0x0b, 0x49, 0xff, 0xd0, 0x2d, 0x80, 0x26, 0x80, 0x48, 0x84, 0x00, 0x49, 0xff, 0xfc, 0x58, +0x80, 0x26, 0x80, 0x48, 0x84, 0x01, 0x49, 0xff, 0xfc, 0x53, 0xd5, 0x69, 0x9d, 0xfc, 0x49, 0xff, +0xec, 0x33, 0xb5, 0x27, 0x54, 0x94, 0x80, 0xff, 0x80, 0x09, 0x49, 0xff, 0xcd, 0x17, 0x84, 0x00, +0x80, 0x20, 0x49, 0xff, 0xe1, 0xcf, 0x84, 0x01, 0x84, 0x20, 0x49, 0xff, 0xe1, 0xcb, 0x46, 0x80, +0x00, 0x8d, 0x58, 0x84, 0x04, 0xf0, 0x46, 0x70, 0x00, 0x8c, 0x58, 0x73, 0x8c, 0x2c, 0x46, 0x60, +0x00, 0x89, 0x58, 0x63, 0x0e, 0x8c, 0xe7, 0x2f, 0xe9, 0x21, 0x84, 0x00, 0x49, 0xff, 0xe0, 0x56, +0x84, 0x01, 0x49, 0xff, 0xe0, 0x53, 0x84, 0x00, 0x80, 0x40, 0x80, 0x60, 0x84, 0x21, 0xdd, 0x28, +0x84, 0x01, 0x84, 0x40, 0x80, 0x20, 0x80, 0x62, 0xdd, 0x28, 0x84, 0x00, 0x80, 0x40, 0x80, 0x60, +0x84, 0x21, 0xdd, 0x27, 0x84, 0x40, 0x84, 0x01, 0x80, 0x20, 0x80, 0x62, 0xdd, 0x27, 0x84, 0x00, +0x84, 0x21, 0xdd, 0x26, 0x84, 0x01, 0x80, 0x20, 0xd5, 0xaa, 0x84, 0x00, 0x80, 0x20, 0x80, 0x40, +0x80, 0x60, 0xdd, 0x28, 0x84, 0x20, 0x80, 0x41, 0x80, 0x61, 0x84, 0x01, 0xdd, 0x28, 0x84, 0x00, +0x80, 0x20, 0x80, 0x40, 0x80, 0x60, 0xdd, 0x27, 0x84, 0x20, 0x80, 0x41, 0x80, 0x61, 0x84, 0x01, +0xdd, 0x27, 0x84, 0x00, 0x80, 0x20, 0xdd, 0x26, 0x84, 0x01, 0x84, 0x20, 0x48, 0xff, 0xff, 0x90, +0x49, 0xff, 0xce, 0x42, 0xd5, 0x0c, 0x9d, 0xfc, 0xb4, 0x07, 0xb4, 0x27, 0xb4, 0x47, 0x92, 0x28, +0x42, 0x00, 0x40, 0x0b, 0x96, 0x48, 0x96, 0x94, 0x49, 0xff, 0xd9, 0xf0, 0x46, 0x40, 0x04, 0x11, +0x80, 0x44, 0x46, 0x38, 0x00, 0x08, 0x46, 0x10, 0x04, 0x12, 0x84, 0xc0, 0x14, 0x62, 0x00, 0x99, +0x14, 0x31, 0x00, 0x9a, 0x14, 0xa0, 0x80, 0x49, 0x3e, 0x09, 0x19, 0xdc, 0x49, 0xff, 0x93, 0x72, +0x80, 0x06, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x04, 0x21, 0x00, 0x20, +0x84, 0xa3, 0x54, 0x21, 0x00, 0x03, 0xd2, 0x09, 0xc8, 0x04, 0x3e, 0x09, 0x3a, 0x65, 0xd5, 0x03, +0x3e, 0x09, 0x3a, 0x66, 0xae, 0x40, 0xd5, 0x1b, 0xc8, 0x0a, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, +0x02, 0x3c, 0xb4, 0x40, 0x94, 0x4c, 0x44, 0x3f, 0xff, 0x0f, 0xd5, 0x0c, 0x46, 0x00, 0x04, 0x10, +0x58, 0x00, 0x04, 0x10, 0x46, 0x3f, 0xff, 0x0f, 0xb4, 0x40, 0x40, 0x10, 0xc0, 0x08, 0x58, 0x31, +0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, +0x2e, 0x01, 0x3a, 0x6a, 0xc0, 0x04, 0x3e, 0x09, 0x3a, 0x38, 0xd5, 0x03, 0x3e, 0x09, 0x3a, 0x30, +0xb4, 0x00, 0xdd, 0x9e, 0x2e, 0x01, 0x3a, 0x6a, 0xc0, 0x04, 0x3e, 0x09, 0x3a, 0x3c, 0xd5, 0x03, +0x3e, 0x09, 0x3a, 0x34, 0xb4, 0x00, 0xdd, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x04, 0x21, 0x00, 0x20, +0x84, 0xa3, 0x54, 0x21, 0x00, 0x03, 0xda, 0x25, 0xe6, 0x0a, 0xe8, 0x23, 0x3e, 0x29, 0x82, 0x98, +0x38, 0x11, 0x02, 0x0a, 0x3c, 0x0e, 0x4e, 0x94, 0xe6, 0x04, 0xe8, 0x0e, 0x46, 0x10, 0x04, 0x10, +0x04, 0x30, 0x81, 0x04, 0x84, 0x41, 0x40, 0x01, 0x00, 0x0c, 0x40, 0x00, 0x0c, 0x04, 0x14, 0x00, +0x81, 0x04, 0x80, 0x02, 0xd5, 0x0f, 0x46, 0x10, 0x04, 0x10, 0x9c, 0x84, 0x04, 0x30, 0x81, 0x04, +0x84, 0x01, 0x40, 0x20, 0x08, 0x0c, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x81, 0x04, 0xd5, 0x02, +0x84, 0x00, 0xdd, 0x9e, 0x46, 0x40, 0x04, 0x11, 0x46, 0x5e, 0xee, 0xee, 0x58, 0x52, 0x8e, 0xaa, +0x80, 0x64, 0x80, 0x23, 0x14, 0x52, 0x00, 0x92, 0x50, 0x22, 0x80, 0x44, 0x44, 0x40, 0x0e, 0xee, +0x80, 0x01, 0x14, 0x41, 0x80, 0x93, 0x14, 0x20, 0x80, 0x94, 0x44, 0x10, 0x06, 0xae, 0x14, 0x10, +0x00, 0x95, 0xdd, 0x9e, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, +0x80, 0x03, 0xd1, 0x04, 0x3e, 0x01, 0x3a, 0x67, 0xd5, 0x2a, 0xc0, 0x15, 0x46, 0x00, 0x04, 0x11, +0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, +0x80, 0x04, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x02, 0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, +0xc0, 0x08, 0xd5, 0x14, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x42, 0x10, +0x84, 0x09, 0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, 0x88, 0x09, 0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, +0x80, 0x09, 0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, 0xc0, 0x09, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x04, +0x3e, 0x19, 0x3a, 0x4c, 0xd5, 0x0e, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x40, 0xb4, 0x41, +0x92, 0x50, 0x40, 0x21, 0x40, 0x08, 0xb6, 0x41, 0x96, 0x01, 0xb4, 0x41, 0x40, 0x00, 0x08, 0x04, +0xb6, 0x01, 0xdd, 0x9e, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, +0x80, 0x03, 0xd1, 0x04, 0x3e, 0x01, 0x3a, 0x68, 0xd5, 0x22, 0xc0, 0x11, 0x46, 0x10, 0x04, 0x11, +0x04, 0x20, 0x80, 0x8f, 0x46, 0x00, 0x04, 0x11, 0x42, 0x21, 0x60, 0x08, 0x14, 0x20, 0x80, 0x8f, +0x58, 0x00, 0x02, 0x44, 0xb4, 0x20, 0x42, 0x10, 0xfc, 0x08, 0xd5, 0x10, 0x46, 0x10, 0x04, 0x11, +0x04, 0x20, 0x80, 0x8f, 0x42, 0x21, 0x60, 0x09, 0x14, 0x20, 0x80, 0x8f, 0x46, 0x00, 0x04, 0x11, +0x58, 0x00, 0x02, 0x44, 0xb4, 0x20, 0x42, 0x10, 0xfc, 0x09, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x9f, 0x09, 0xe6, 0x83, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x57, 0x84, 0xa1, +0xda, 0x0d, 0x84, 0x86, 0x42, 0x41, 0x90, 0x24, 0x3e, 0x69, 0x94, 0x7c, 0x9d, 0x21, 0x95, 0x63, +0x99, 0x6e, 0xa8, 0x29, 0x38, 0x13, 0x13, 0x0a, 0xd5, 0x1d, 0x84, 0xa2, 0xda, 0x1b, 0x84, 0xa6, +0x42, 0x51, 0x94, 0x24, 0x44, 0x60, 0x00, 0x30, 0x9d, 0x69, 0x42, 0x61, 0x98, 0x24, 0x3e, 0x49, +0x94, 0x7c, 0x40, 0x82, 0x8c, 0x08, 0x99, 0xb4, 0x89, 0x04, 0x84, 0x80, 0x14, 0x44, 0x00, 0x01, +0x9d, 0xf4, 0x3e, 0x89, 0x94, 0x7c, 0x50, 0x63, 0x00, 0x28, 0x38, 0x44, 0x17, 0x0a, 0xaf, 0x34, +0xb6, 0x87, 0x84, 0x83, 0x42, 0x41, 0x90, 0x24, 0x3e, 0x59, 0x94, 0x7c, 0x9d, 0x21, 0x95, 0x24, +0x99, 0x25, 0xb6, 0x44, 0xe6, 0x0f, 0xe9, 0x06, 0x46, 0x20, 0x40, 0x00, 0x58, 0x21, 0x00, 0x20, +0xd5, 0x13, 0xc8, 0x04, 0x46, 0x20, 0x40, 0x00, 0xd5, 0x0f, 0x84, 0x06, 0x42, 0x31, 0x80, 0x24, +0x80, 0xc5, 0x9c, 0xd9, 0x94, 0xdb, 0x98, 0xde, 0xa0, 0x99, 0x46, 0x00, 0x40, 0x00, 0x58, 0x00, +0x00, 0x10, 0x40, 0x21, 0x00, 0x04, 0x84, 0xa2, 0xd9, 0x03, 0x58, 0x21, 0x00, 0x80, 0x84, 0x00, +0x44, 0x10, 0x00, 0x73, 0x49, 0xfb, 0xc2, 0x18, 0x84, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x00, 0x8e, 0x58, 0x10, 0x86, 0x24, 0xc0, 0x06, 0x84, 0x01, +0xdd, 0x21, 0x3e, 0x09, 0x32, 0x84, 0xd5, 0x04, 0xdd, 0x21, 0x3e, 0x09, 0x32, 0x94, 0x49, 0xff, +0x91, 0xf9, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0x30, 0x04, 0x00, +0x04, 0x31, 0x80, 0x20, 0x81, 0x20, 0x80, 0xc1, 0x54, 0x01, 0x80, 0x03, 0x84, 0x23, 0x81, 0x42, +0x4c, 0x00, 0x80, 0x03, 0xd5, 0x16, 0x49, 0xff, 0xfe, 0xa5, 0x81, 0x00, 0x84, 0xaa, 0x4c, 0x82, +0x80, 0x0a, 0x3e, 0x19, 0x96, 0x5c, 0x40, 0x04, 0x10, 0x08, 0x98, 0x01, 0xb4, 0x00, 0x84, 0xa1, +0xd0, 0x0b, 0x84, 0xa1, 0xde, 0x08, 0x80, 0x28, 0x3e, 0x09, 0x32, 0xa8, 0x49, 0xff, 0x91, 0xd2, +0x84, 0x00, 0xd5, 0x53, 0x85, 0x01, 0x49, 0xff, 0xfe, 0x97, 0x84, 0x2a, 0x80, 0xe0, 0x4c, 0x00, +0x80, 0x09, 0x3e, 0x19, 0x96, 0x5c, 0x94, 0x04, 0x98, 0x01, 0xb4, 0x00, 0x84, 0xa1, 0xd0, 0x08, +0x84, 0xa1, 0xde, 0x05, 0x80, 0x27, 0x3e, 0x09, 0x32, 0xdc, 0xd5, 0xe9, 0x84, 0xe4, 0x4e, 0x93, +0x00, 0x1b, 0x84, 0xa1, 0xde, 0x16, 0x80, 0x28, 0x89, 0x08, 0x80, 0x09, 0x8d, 0x01, 0x49, 0xff, +0xfe, 0x45, 0x40, 0x84, 0x0c, 0x08, 0x3e, 0x09, 0x96, 0x5c, 0x89, 0x00, 0x04, 0x54, 0x00, 0x01, +0x46, 0x10, 0x00, 0x8e, 0x58, 0x10, 0x86, 0xc4, 0xde, 0x02, 0xd5, 0x1d, 0x80, 0x09, 0xd5, 0x1e, +0x80, 0x08, 0xd5, 0x20, 0x3c, 0x5c, 0x4e, 0xb8, 0xd7, 0x03, 0x3c, 0x7e, 0x4e, 0xb8, 0x84, 0xa1, +0xde, 0x18, 0x80, 0x27, 0x99, 0xff, 0x80, 0x06, 0x9d, 0xf9, 0x49, 0xff, 0xfe, 0x27, 0x95, 0xfb, +0x3e, 0x19, 0x96, 0x5c, 0x99, 0xf9, 0xa1, 0xf9, 0x84, 0xa2, 0x46, 0x10, 0x00, 0x8e, 0x58, 0x10, +0x86, 0xc4, 0xdf, 0x03, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x21, 0x80, 0x06, 0xd5, 0x05, +0x80, 0x07, 0x80, 0x2a, 0x49, 0xff, 0xfe, 0x52, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x20, 0x84, 0xa3, +0x54, 0x00, 0x00, 0x03, 0xd8, 0x26, 0x84, 0x00, 0x84, 0x21, 0x80, 0x40, 0x49, 0xff, 0xff, 0x76, +0xc8, 0x05, 0x3e, 0x09, 0x33, 0x0c, 0x49, 0xff, 0x91, 0x65, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, +0x80, 0x8f, 0x84, 0x01, 0x58, 0x21, 0x00, 0x08, 0x14, 0x20, 0x80, 0x8f, 0x80, 0x20, 0x84, 0x40, +0x49, 0xff, 0xff, 0x64, 0xc8, 0x05, 0x3e, 0x09, 0x33, 0x48, 0x49, 0xff, 0x91, 0x53, 0x46, 0x00, +0x04, 0x11, 0x44, 0x10, 0x07, 0x01, 0x14, 0x10, 0x00, 0xfc, 0x49, 0xff, 0xfe, 0x4d, 0x92, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x49, 0xff, 0xff, 0xca, +0x2e, 0x11, 0x3a, 0x65, 0x44, 0x50, 0x00, 0xff, 0xd1, 0x09, 0x84, 0x00, 0x49, 0xff, 0xfd, 0xce, +0x2e, 0x11, 0x3a, 0x66, 0x84, 0x01, 0x49, 0xff, 0xfd, 0xc9, 0x2e, 0x01, 0x3a, 0x67, 0x44, 0x50, +0x00, 0xff, 0xd0, 0x03, 0x49, 0xff, 0xfe, 0x48, 0x2e, 0x01, 0x3a, 0x68, 0x44, 0x50, 0x00, 0xff, +0xd0, 0x03, 0x49, 0xff, 0xfe, 0x91, 0x3c, 0x0c, 0x4e, 0x93, 0x84, 0xbf, 0xd0, 0x03, 0x49, 0xff, +0xfe, 0x71, 0x84, 0x1f, 0x3e, 0x01, 0x3a, 0x68, 0x84, 0x5f, 0x3c, 0x2e, 0x4e, 0x93, 0x3e, 0x01, +0x3a, 0x65, 0x3e, 0x01, 0x3a, 0x66, 0x3e, 0x01, 0x3a, 0x67, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xc0, 0x02, 0x84, 0x01, 0x3e, 0x01, 0x3a, 0x6a, 0x84, 0x00, +0x84, 0x21, 0x80, 0x40, 0x49, 0xff, 0xff, 0x12, 0xc8, 0x05, 0x3e, 0x09, 0x33, 0x0c, 0x49, 0xff, +0x91, 0x01, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0x8f, 0x84, 0x01, 0x58, 0x21, 0x00, 0x08, +0x14, 0x20, 0x80, 0x8f, 0x80, 0x20, 0x84, 0x40, 0x49, 0xff, 0xff, 0x00, 0xc8, 0x05, 0x3e, 0x09, +0x33, 0x48, 0x49, 0xff, 0x90, 0xef, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, +0x54, 0x10, 0x80, 0x03, 0xd1, 0x03, 0x84, 0x00, 0xd5, 0x10, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x0d, +0xc8, 0x03, 0x80, 0x01, 0xd5, 0x07, 0x84, 0xa2, 0xd8, 0x02, 0xd5, 0x03, 0x84, 0xa3, 0xd8, 0x04, +0x84, 0x00, 0x49, 0xff, 0xff, 0xbf, 0x84, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x80, 0xc0, 0x81, 0x41, 0x80, 0xe2, 0x81, 0x23, 0x81, 0x04, +0xe6, 0x0a, 0x4e, 0xf2, 0x01, 0xb4, 0xe6, 0x6a, 0x4e, 0xf2, 0x01, 0xb1, 0xe6, 0x22, 0x4e, 0xf2, +0x01, 0xae, 0x9e, 0x11, 0xe6, 0x06, 0x4e, 0xf2, 0x01, 0xaa, 0x9e, 0x21, 0xe6, 0x04, 0x4e, 0xf2, +0x01, 0xa6, 0xc9, 0x15, 0x80, 0x23, 0x3e, 0x09, 0x33, 0x84, 0x80, 0x46, 0x49, 0xff, 0x90, 0xaa, +0x44, 0x00, 0x00, 0x30, 0x42, 0x04, 0x80, 0x24, 0x94, 0x74, 0x3e, 0x29, 0x96, 0x5c, 0x3e, 0x39, +0x94, 0x7c, 0x98, 0x4a, 0x98, 0x03, 0xb7, 0x41, 0x14, 0xa0, 0x00, 0x01, 0x84, 0x00, 0x3f, 0xc9, +0x94, 0x80, 0xf0, 0x84, 0x14, 0x8f, 0x80, 0x05, 0x80, 0x3c, 0x81, 0x06, 0x80, 0x60, 0x87, 0xc1, +0x80, 0x80, 0x80, 0xc0, 0xb4, 0x41, 0x84, 0xa4, 0xda, 0x04, 0x4c, 0x71, 0x41, 0x85, 0xd5, 0x10, +0x84, 0xa1, 0xda, 0x06, 0x40, 0x23, 0x88, 0x03, 0x40, 0x3f, 0x08, 0x1b, 0xd5, 0x09, 0x40, 0x53, +0x88, 0x03, 0xf5, 0x84, 0x84, 0xa3, 0xda, 0x04, 0xf2, 0x04, 0x40, 0x0f, 0x08, 0x1b, 0x50, 0x10, +0x80, 0x30, 0x50, 0x5e, 0x01, 0xe0, 0xd9, 0xe7, 0x80, 0xa6, 0xf4, 0x84, 0x80, 0xc8, 0x04, 0x8f, +0x80, 0x05, 0xcc, 0x1a, 0xc8, 0x19, 0xcb, 0x18, 0x4e, 0xa3, 0x00, 0x17, 0x3e, 0xa1, 0x3a, 0x69, +0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x02, 0x3c, 0xb4, 0x22, 0x42, 0x10, 0x88, 0x09, 0xb6, 0x22, +0xb4, 0x22, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x22, 0x80, 0x0a, 0xb4, 0x22, 0x42, 0x10, 0x84, 0x09, +0xb6, 0x22, 0x48, 0x00, 0x01, 0x4d, 0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x02, 0x3c, 0xb4, 0x02, +0x96, 0x04, 0xc8, 0x0d, 0xb4, 0x02, 0x58, 0x00, 0x00, 0x01, 0xb6, 0x02, 0xb4, 0x02, 0x58, 0x00, +0x00, 0x04, 0xb6, 0x02, 0xb4, 0x02, 0x58, 0x00, 0x00, 0x02, 0xb6, 0x02, 0x44, 0x00, 0x00, 0x30, +0x42, 0x04, 0x80, 0x24, 0x50, 0x1e, 0x7f, 0xfc, 0x98, 0x01, 0x84, 0x41, 0xa9, 0xc1, 0x4c, 0x81, +0x40, 0x04, 0xa9, 0x87, 0xd5, 0x0f, 0x84, 0x64, 0x4c, 0x81, 0xc0, 0x05, 0x14, 0x60, 0x00, 0x08, +0xd5, 0x09, 0x84, 0x82, 0x4c, 0x82, 0x40, 0x05, 0x14, 0x60, 0x00, 0x09, 0xd5, 0x03, 0x14, 0x60, +0x00, 0x0a, 0xcd, 0x49, 0x84, 0xa3, 0x4c, 0x82, 0x80, 0x2a, 0x84, 0x04, 0x4c, 0x80, 0x00, 0x19, +0x84, 0x22, 0x4c, 0x80, 0x80, 0x0d, 0x3c, 0x6e, 0x4e, 0x8e, 0x4c, 0x70, 0x80, 0x1d, 0x84, 0x44, +0x4c, 0x71, 0x00, 0x1a, 0x84, 0x65, 0x4c, 0x71, 0xc0, 0x27, 0xd5, 0x15, 0x3c, 0x6e, 0x4e, 0x8f, +0x4c, 0x74, 0x00, 0x1f, 0x84, 0x84, 0x4c, 0x72, 0x00, 0x1c, 0x84, 0xa5, 0xd5, 0x18, 0x3c, 0x6e, +0x4e, 0x90, 0x84, 0x01, 0x4c, 0x70, 0x00, 0x08, 0x84, 0x23, 0x4c, 0x70, 0x80, 0x05, 0x84, 0x46, +0x4c, 0x71, 0x40, 0x12, 0x3e, 0x09, 0x3a, 0x30, 0xd5, 0x0d, 0x84, 0x61, 0x3c, 0x6e, 0x4e, 0x91, +0x4c, 0x71, 0x80, 0x07, 0x84, 0x83, 0x4c, 0x72, 0x00, 0x04, 0x84, 0xa6, 0xdf, 0x04, 0x3e, 0x09, +0x3a, 0x34, 0xb6, 0xc0, 0x3e, 0x29, 0x96, 0x5c, 0x94, 0x34, 0x98, 0x76, 0x98, 0x02, 0x9c, 0x49, +0x1c, 0xa0, 0x00, 0x01, 0x80, 0x62, 0x94, 0x8b, 0x98, 0x93, 0xb6, 0xe0, 0x38, 0x91, 0x87, 0x0a, +0x14, 0x81, 0x00, 0x01, 0x84, 0x81, 0x4c, 0x82, 0x40, 0x05, 0x3e, 0x49, 0x33, 0xac, 0xd5, 0x11, +0x84, 0xa2, 0x4c, 0x82, 0xc0, 0x05, 0x3e, 0x49, 0x33, 0xb0, 0xd5, 0x0b, 0x56, 0x84, 0x00, 0x04, +0x3e, 0x09, 0x33, 0xb8, 0x3e, 0x19, 0x33, 0xbc, 0x40, 0x40, 0xa0, 0x1a, 0x40, 0x40, 0x20, 0x1b, +0x3c, 0x8c, 0x4e, 0x8d, 0x3c, 0x5c, 0x4e, 0x8c, 0xb7, 0x1f, 0x3c, 0x8c, 0x4e, 0x8e, 0x3e, 0x09, +0x33, 0xc0, 0x14, 0x8f, 0x80, 0x01, 0x3c, 0x8c, 0x4e, 0x8f, 0x80, 0x29, 0x80, 0x46, 0x80, 0x67, +0x14, 0x8f, 0x80, 0x02, 0x49, 0xff, 0x8f, 0xb6, 0x84, 0x00, 0xb4, 0x3c, 0x51, 0xce, 0x00, 0x30, +0x9e, 0x8b, 0xe6, 0x42, 0xe9, 0x04, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x03, 0x9c, 0x01, 0x3e, 0x39, +0x96, 0x60, 0x4d, 0xc1, 0xff, 0xf4, 0xe6, 0x02, 0xe8, 0x09, 0x84, 0x81, 0x4c, 0x02, 0x40, 0x04, +0xf5, 0x04, 0xd0, 0x04, 0x84, 0x04, 0x4c, 0x70, 0x40, 0x0d, 0x84, 0x41, 0x3e, 0x21, 0x3a, 0x69, +0x84, 0x01, 0x49, 0xff, 0xfd, 0x01, 0x44, 0x00, 0x02, 0x71, 0x49, 0xff, 0xfc, 0xe3, 0xd5, 0x4a, +0x3c, 0x00, 0x9d, 0x2b, 0x54, 0x10, 0x00, 0x41, 0xc9, 0x04, 0x54, 0x70, 0x00, 0x08, 0xc7, 0x22, +0x84, 0x01, 0x49, 0xff, 0xfc, 0xf1, 0x44, 0x00, 0x02, 0x71, 0x49, 0xff, 0xfc, 0xd3, 0x84, 0x01, +0x49, 0xff, 0xfe, 0x70, 0x3c, 0x1c, 0x4e, 0x8e, 0x3c, 0x0c, 0x4e, 0x8f, 0x98, 0xc9, 0x98, 0x80, +0x9c, 0xd9, 0x9c, 0x91, 0x3e, 0x49, 0x96, 0x5c, 0x94, 0xdb, 0x94, 0x93, 0x98, 0xdc, 0x98, 0x94, +0x84, 0x81, 0xa9, 0x19, 0x84, 0x62, 0xa8, 0xd1, 0x3c, 0x1e, 0x4e, 0x8c, 0x3c, 0x0e, 0x4e, 0x8d, +0xd5, 0x1e, 0xc0, 0x1d, 0x80, 0x07, 0x49, 0xff, 0xfc, 0xcf, 0x44, 0x00, 0x13, 0x88, 0x49, 0xff, +0xfc, 0xb1, 0x80, 0x07, 0x49, 0xff, 0xfe, 0x4e, 0x3c, 0x1c, 0x4e, 0x8c, 0x3c, 0x0c, 0x4e, 0x8d, +0x98, 0x49, 0x98, 0x00, 0x9c, 0x49, 0x3e, 0x59, 0x96, 0x5c, 0x9c, 0x01, 0x94, 0x4b, 0x98, 0x4d, +0x94, 0x03, 0x84, 0x44, 0xa8, 0x89, 0x98, 0x05, 0x84, 0x23, 0xa8, 0x41, 0x84, 0x20, 0x3e, 0x11, +0x3a, 0x69, 0x99, 0xb6, 0x44, 0x00, 0x00, 0x30, 0x42, 0x04, 0x80, 0x24, 0x9d, 0xb1, 0x3e, 0x19, +0x94, 0x7c, 0x3e, 0x29, 0x96, 0x5c, 0x95, 0xb3, 0x98, 0x01, 0x99, 0xb2, 0xa0, 0x81, 0xa0, 0x31, +0x44, 0x40, 0xff, 0x00, 0x54, 0x21, 0x00, 0x0f, 0x54, 0x00, 0x00, 0xf0, 0x94, 0x04, 0x40, 0x94, +0x90, 0x02, 0x42, 0x21, 0x4c, 0x08, 0x40, 0x21, 0x00, 0x04, 0x40, 0x94, 0xa0, 0x08, 0x40, 0x21, +0x24, 0x04, 0x44, 0x10, 0x00, 0x73, 0x84, 0x00, 0x49, 0xfb, 0xbf, 0x2e, 0x84, 0x00, 0x84, 0x21, +0x80, 0x40, 0x49, 0xff, 0xfd, 0x2b, 0xc8, 0x05, 0x3e, 0x09, 0x34, 0x1c, 0x49, 0xff, 0x8f, 0x1a, +0x84, 0x01, 0x80, 0x20, 0x84, 0x40, 0x49, 0xff, 0xfd, 0x21, 0xc0, 0x02, 0xd5, 0x05, 0x3e, 0x09, +0x34, 0x44, 0x49, 0xff, 0x8f, 0x0f, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x1c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x84, 0x81, 0x80, 0xc4, 0x48, 0xff, 0xfe, 0x8b, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x84, 0x40, 0x3c, 0x2e, 0x4e, 0xb7, 0x3e, 0x09, 0x96, 0xfc, 0x49, 0xff, 0x8f, 0x48, +0x84, 0x01, 0x49, 0xff, 0xfc, 0x11, 0x49, 0xff, 0xfb, 0xf7, 0x3e, 0x09, 0x34, 0x88, 0x49, 0xff, +0x8e, 0xf1, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x3e, 0x09, 0x34, 0xa8, 0x49, 0xff, 0x8e, 0xe5, 0x49, 0xff, 0xff, 0xe1, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x84, 0xa2, +0xf0, 0x81, 0x80, 0x5f, 0x84, 0x20, 0x84, 0x68, 0x84, 0x09, 0xb6, 0xbf, 0x49, 0xff, 0x9f, 0x24, +0x92, 0x00, 0x84, 0x01, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x80, 0xc0, 0x3c, 0x00, 0x9d, 0x2a, 0x49, 0xff, 0xff, 0xe9, 0x54, 0x03, 0x00, 0x04, 0xc0, 0x04, +0x44, 0x74, 0x00, 0x04, 0xd5, 0x3b, 0x54, 0x03, 0x00, 0x08, 0xc0, 0x04, 0x44, 0x74, 0x00, 0x06, +0xd5, 0x35, 0x54, 0x03, 0x00, 0x20, 0xc8, 0x30, 0x54, 0x03, 0x00, 0x10, 0xc0, 0x04, 0x44, 0x74, +0x00, 0x05, 0xd5, 0x2c, 0x54, 0x03, 0x00, 0x40, 0xc0, 0x04, 0x44, 0x74, 0x00, 0x07, 0xd5, 0x26, +0x54, 0x13, 0x00, 0x02, 0xc9, 0x21, 0x96, 0x34, 0xc0, 0x0b, 0x46, 0x24, 0x00, 0x00, 0x80, 0x01, +0x44, 0x10, 0x00, 0x73, 0x49, 0xfb, 0xbe, 0xa8, 0x44, 0x74, 0x00, 0x01, 0xd5, 0x17, 0x54, 0x13, +0x00, 0x80, 0xc1, 0x0a, 0x46, 0x28, 0x00, 0x00, 0x44, 0x10, 0x00, 0x73, 0x49, 0xfb, 0xbe, 0x9c, +0x44, 0x74, 0x00, 0x02, 0xd5, 0x0b, 0x3e, 0x09, 0x34, 0xcc, 0x80, 0x26, 0x49, 0xff, 0x8e, 0x8a, +0x44, 0x74, 0x00, 0x00, 0xd5, 0x03, 0x44, 0x74, 0x00, 0x03, 0x80, 0x27, 0x3e, 0x09, 0x34, 0xf0, +0x49, 0xff, 0x8e, 0x80, 0x80, 0x47, 0x84, 0x00, 0x44, 0x10, 0x00, 0x73, 0x49, 0xfb, 0xbe, 0x84, +0x3c, 0x73, 0xf8, 0x25, 0x84, 0xa1, 0xdf, 0x2f, 0x54, 0x03, 0x00, 0x08, 0xc0, 0x24, 0x3e, 0x09, +0x35, 0x00, 0x49, 0xff, 0x8e, 0x6f, 0x3c, 0x7e, 0x4e, 0xb7, 0x3e, 0x09, 0x96, 0xfc, 0x44, 0x10, +0x07, 0xd0, 0x49, 0xff, 0x8f, 0x7b, 0x46, 0x40, 0x04, 0x11, 0x46, 0x04, 0x44, 0x44, 0x80, 0x64, +0x80, 0x43, 0x80, 0x22, 0x58, 0x00, 0x04, 0x44, 0x44, 0x50, 0x04, 0x44, 0x14, 0x02, 0x00, 0x92, +0x14, 0x51, 0x80, 0x93, 0x14, 0x01, 0x00, 0x94, 0x14, 0x50, 0x80, 0x95, 0x84, 0x00, 0x49, 0xff, +0xfb, 0x6b, 0xd5, 0x09, 0x54, 0x63, 0x00, 0x10, 0xc6, 0x06, 0x3c, 0x0c, 0x4e, 0xb7, 0xc0, 0x03, +0x49, 0xff, 0xff, 0x46, 0x84, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x80, 0xe1, 0x80, 0xc0, 0xf2, 0x81, 0xc9, 0x08, 0x3e, 0x09, 0x35, 0x20, 0x49, 0xff, +0x8e, 0x39, 0x80, 0xc7, 0x48, 0x00, 0x01, 0xd3, 0x44, 0x90, 0x00, 0x30, 0x3e, 0x09, 0x35, 0x38, +0x80, 0x26, 0x80, 0x47, 0x42, 0x93, 0x24, 0x24, 0x49, 0xff, 0x8e, 0x2c, 0x3e, 0x09, 0x94, 0x7c, +0x89, 0x20, 0x44, 0x50, 0x00, 0x1a, 0xb6, 0xe9, 0x4c, 0x72, 0x80, 0xaa, 0xe6, 0xfb, 0xe8, 0x1c, +0xe6, 0xe8, 0xe8, 0x0f, 0xe6, 0xe6, 0x4e, 0xf2, 0x00, 0xc7, 0x84, 0xa3, 0x4c, 0x72, 0x80, 0xc4, +0xe6, 0xe4, 0x4e, 0xf2, 0x00, 0xd2, 0x84, 0xa1, 0xd7, 0x3b, 0x84, 0xa2, 0xdf, 0x36, 0xd5, 0x48, +0x9f, 0x6c, 0xd7, 0x73, 0xe6, 0xf7, 0x4e, 0xf2, 0x00, 0xd4, 0x9f, 0x6a, 0x4c, 0x72, 0x80, 0xd1, +0x9d, 0x69, 0xdf, 0x2b, 0xd5, 0x30, 0x44, 0x50, 0x00, 0xb4, 0x4c, 0x72, 0x80, 0xca, 0x5c, 0xf3, +0x80, 0xb5, 0xe8, 0x12, 0x9f, 0x6c, 0x4c, 0x72, 0x80, 0xb6, 0x5c, 0xf3, 0x80, 0xb1, 0xe8, 0x07, +0x44, 0x50, 0x00, 0x1b, 0x4c, 0x72, 0x80, 0xbd, 0x9c, 0xe9, 0xd5, 0x15, 0x5c, 0xf3, 0x80, 0xb2, +0xe9, 0x14, 0x48, 0x00, 0x00, 0x75, 0x5c, 0xf3, 0x80, 0xb9, 0xe8, 0x07, 0x5c, 0xf3, 0x80, 0xb7, +0xe8, 0x6e, 0x9d, 0x69, 0xdf, 0x0a, 0xd5, 0x6b, 0x9c, 0x6e, 0x4c, 0x70, 0x80, 0x69, 0xe2, 0xe1, +0xe9, 0x44, 0x9c, 0xc9, 0x4c, 0x71, 0x80, 0x08, 0x84, 0xc0, 0x48, 0x00, 0x01, 0x78, 0x80, 0xc7, +0x48, 0x00, 0x00, 0xa0, 0x44, 0x00, 0x00, 0x30, 0x42, 0x63, 0x00, 0x24, 0x3e, 0x09, 0x94, 0x7c, +0x99, 0xb0, 0x84, 0x01, 0x10, 0x03, 0x00, 0x2c, 0x95, 0x84, 0x48, 0x00, 0x00, 0x93, 0x3c, 0x03, +0xf8, 0x25, 0x84, 0xa1, 0xd8, 0x06, 0x49, 0xff, 0xfc, 0x4d, 0x84, 0x01, 0x49, 0xff, 0xfb, 0xba, +0x84, 0x43, 0x84, 0x86, 0x42, 0x23, 0x08, 0x24, 0x42, 0x43, 0x10, 0x24, 0x44, 0x00, 0x00, 0x30, +0x42, 0x63, 0x00, 0x24, 0x9d, 0x21, 0x3e, 0x39, 0x94, 0x7c, 0x9c, 0x91, 0x80, 0x03, 0x99, 0xb3, +0x94, 0x94, 0x94, 0x63, 0x50, 0x33, 0x00, 0x28, 0x98, 0x90, 0x98, 0x48, 0x9d, 0xb4, 0x84, 0x00, +0x3e, 0x59, 0x94, 0x7c, 0xb6, 0x06, 0x38, 0x02, 0x93, 0x0a, 0x44, 0x60, 0x00, 0x80, 0xb6, 0x02, +0xa8, 0x09, 0xae, 0x1c, 0xae, 0x1d, 0xd5, 0x65, 0x84, 0x43, 0x84, 0x86, 0x42, 0x23, 0x08, 0x24, +0x42, 0x43, 0x10, 0x24, 0x44, 0x00, 0x00, 0x30, 0x42, 0x63, 0x00, 0x24, 0x9d, 0x21, 0x3e, 0x19, +0x94, 0x7c, 0x9c, 0x91, 0x99, 0xb1, 0x80, 0x01, 0x94, 0x94, 0x94, 0x63, 0x50, 0x33, 0x00, 0x28, +0x98, 0x90, 0x98, 0x48, 0x9d, 0xb4, 0x84, 0x00, 0x3e, 0x59, 0x94, 0x7c, 0xb6, 0x06, 0x38, 0x02, +0x93, 0x0a, 0xb6, 0x02, 0xa8, 0x09, 0xae, 0x1c, 0xae, 0x1d, 0xd5, 0x40, 0x84, 0x43, 0x84, 0x86, +0x42, 0x23, 0x08, 0x24, 0x42, 0x43, 0x10, 0x24, 0x44, 0x00, 0x00, 0x30, 0x42, 0x63, 0x00, 0x24, +0x9d, 0x21, 0x3e, 0x19, 0x94, 0x7c, 0x9c, 0x91, 0x99, 0xb1, 0x80, 0x01, 0x94, 0x94, 0x94, 0x63, +0x50, 0x33, 0x00, 0x28, 0x98, 0x90, 0x98, 0x48, 0x9d, 0xb4, 0x84, 0x00, 0x3e, 0x59, 0x94, 0x7c, +0xb6, 0x06, 0x38, 0x02, 0x93, 0x0a, 0x44, 0x60, 0x00, 0x20, 0xb6, 0x02, 0xa8, 0x09, 0xae, 0x1c, +0xae, 0x1d, 0xd5, 0x1f, 0x80, 0x26, 0x3e, 0x09, 0x35, 0x60, 0x49, 0xff, 0x8d, 0x53, 0x44, 0x00, +0x00, 0x30, 0x42, 0x63, 0x00, 0x24, 0x3e, 0x19, 0x94, 0x7c, 0x99, 0xb1, 0x84, 0x01, 0x10, 0x03, +0x00, 0x2d, 0x84, 0xc0, 0xd5, 0x0e, 0x3e, 0x09, 0x35, 0x74, 0x84, 0x20, 0x49, 0xff, 0x8d, 0x42, +0x50, 0x94, 0x80, 0x28, 0x84, 0x00, 0x10, 0x04, 0x80, 0x05, 0x84, 0xc2, 0xd5, 0x02, 0x84, 0xc8, +0x2e, 0x01, 0x3a, 0x5e, 0xc0, 0x03, 0x58, 0x63, 0x00, 0x40, 0x3f, 0xc9, 0x94, 0x84, 0x85, 0x00, +0xb5, 0x3c, 0x84, 0xa2, 0x4c, 0x92, 0x80, 0x13, 0x84, 0x03, 0x4c, 0x90, 0x00, 0x18, 0x84, 0xa1, +0x4c, 0x92, 0x80, 0x04, 0x84, 0x00, 0xd5, 0x1a, 0x3e, 0x09, 0x35, 0x88, 0x80, 0x28, 0x49, 0xff, +0x8d, 0x21, 0x42, 0x63, 0x40, 0x08, 0x80, 0x09, 0xd5, 0x11, 0x3e, 0x09, 0x35, 0x94, 0x80, 0x28, +0x49, 0xff, 0x8d, 0x18, 0x42, 0x63, 0x44, 0x08, 0xd5, 0x08, 0x80, 0x28, 0x3e, 0x09, 0x35, 0xa0, +0x49, 0xff, 0x8d, 0x10, 0x42, 0x63, 0x48, 0x08, 0x84, 0x01, 0x8d, 0x01, 0x84, 0xaa, 0x4c, 0x82, +0xc0, 0x06, 0x3e, 0x39, 0x94, 0xa9, 0x84, 0x00, 0xd5, 0x05, 0x51, 0xce, 0x00, 0x30, 0xc0, 0xd1, +0xd5, 0xf9, 0xa6, 0x98, 0x50, 0x31, 0x80, 0x30, 0xc2, 0x09, 0x80, 0x20, 0x3e, 0x09, 0x35, 0xac, +0x58, 0x63, 0x00, 0x04, 0x49, 0xff, 0x8c, 0xf6, 0xd5, 0x04, 0x9c, 0x01, 0x84, 0xaa, 0xd8, 0xf2, +0x3e, 0x39, 0x94, 0xa8, 0x84, 0x00, 0xa6, 0x98, 0x50, 0x31, 0x80, 0x30, 0xc2, 0x0b, 0x80, 0x20, +0x58, 0x63, 0x00, 0x10, 0x3e, 0x09, 0x35, 0xbc, 0x42, 0x63, 0x04, 0x09, 0x49, 0xff, 0x8c, 0xe2, +0xd5, 0x04, 0x9c, 0x01, 0x84, 0xaa, 0xd8, 0xf0, 0x3e, 0x39, 0x94, 0x88, 0x84, 0x00, 0xb4, 0x43, +0x50, 0x31, 0x80, 0x30, 0xc2, 0x10, 0x54, 0x31, 0x00, 0x0f, 0x40, 0x31, 0xcc, 0x08, 0x80, 0x20, +0x3e, 0x09, 0x35, 0xcc, 0x40, 0x63, 0x0c, 0x04, 0x49, 0xff, 0x8c, 0xcc, 0x3e, 0xa9, 0x94, 0x80, +0x85, 0x00, 0xd5, 0x05, 0x9c, 0x01, 0x84, 0xaa, 0xd8, 0xeb, 0xd5, 0xf9, 0xb4, 0x0a, 0x84, 0xa3, +0xd0, 0x1c, 0xe6, 0x04, 0xe8, 0x06, 0x84, 0xa1, 0xd0, 0x0c, 0x84, 0xa2, 0xd8, 0x2f, 0xd5, 0x0f, +0x84, 0x25, 0x4c, 0x00, 0x80, 0x1f, 0xe2, 0x01, 0xe9, 0x16, 0x84, 0xa6, 0xd8, 0x27, 0xd5, 0x1f, +0x3e, 0x09, 0x35, 0xdc, 0x80, 0x28, 0x58, 0x63, 0x01, 0x00, 0xd5, 0x1e, 0x3e, 0x09, 0x35, 0xf0, +0x80, 0x28, 0x58, 0x63, 0x02, 0x00, 0xd5, 0x18, 0x3e, 0x09, 0x36, 0x04, 0x80, 0x28, 0x58, 0x63, +0x04, 0x00, 0xd5, 0x12, 0x3e, 0x09, 0x36, 0x18, 0x80, 0x28, 0x58, 0x63, 0x08, 0x00, 0xd5, 0x0c, +0x3e, 0x09, 0x36, 0x2c, 0x80, 0x28, 0x58, 0x63, 0x20, 0x00, 0xd5, 0x06, 0x3e, 0x09, 0x36, 0x40, +0x80, 0x28, 0x58, 0x63, 0x10, 0x00, 0x49, 0xff, 0x8c, 0x8d, 0x8d, 0x01, 0x84, 0xaa, 0x50, 0xa5, +0x00, 0x30, 0x4c, 0x82, 0xff, 0xc5, 0x80, 0x26, 0x3e, 0x09, 0x36, 0x54, 0x49, 0xff, 0x8c, 0x82, +0x80, 0x06, 0x49, 0xff, 0xfd, 0xb5, 0x44, 0x10, 0x00, 0xb0, 0x80, 0xc0, 0x4c, 0x70, 0x80, 0x04, +0x9d, 0x4c, 0xdf, 0x04, 0xf1, 0x01, 0x84, 0x01, 0xd5, 0x0f, 0x9d, 0x6f, 0xdf, 0x04, 0x84, 0x00, +0x80, 0x20, 0xd5, 0x0a, 0x9f, 0x6a, 0xdf, 0x04, 0x84, 0x20, 0x84, 0x03, 0xd5, 0x05, 0x9d, 0x4a, +0xdf, 0x05, 0x84, 0x02, 0x84, 0x20, 0x49, 0xff, 0xfb, 0x7d, 0x80, 0x06, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x84, 0xc1, 0xf0, 0x81, 0x80, 0x5f, +0x84, 0x20, 0x84, 0x68, 0x84, 0x09, 0xb6, 0xdf, 0x49, 0xff, 0x9c, 0xa6, 0x92, 0x00, 0x80, 0x06, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x40, 0x10, +0x40, 0x09, 0x40, 0x10, 0xc0, 0x08, 0x44, 0x51, 0x00, 0x00, 0x4c, 0x12, 0x80, 0x7f, 0x46, 0x51, +0x00, 0x00, 0x4c, 0x12, 0xc0, 0xbb, 0x54, 0x80, 0x00, 0x41, 0x97, 0xc0, 0x4e, 0x83, 0x00, 0x04, +0x80, 0xc8, 0xd5, 0x04, 0x85, 0x01, 0x44, 0x60, 0x04, 0x00, 0x54, 0x03, 0x80, 0x02, 0xf0, 0x81, +0xc0, 0x03, 0x58, 0x63, 0x01, 0x00, 0x54, 0x13, 0x80, 0x04, 0xb6, 0x3f, 0xc1, 0x03, 0x58, 0x63, +0x00, 0x10, 0x55, 0xc3, 0x80, 0x08, 0x4f, 0xc2, 0x00, 0x05, 0x58, 0x63, 0x04, 0x00, 0x85, 0x01, +0x54, 0xa3, 0x80, 0x10, 0x4e, 0xa2, 0x00, 0x04, 0x58, 0x63, 0x10, 0x00, 0x54, 0x93, 0x80, 0x20, +0x4e, 0x92, 0x00, 0x04, 0x58, 0x63, 0x10, 0x00, 0x3c, 0x53, 0xf8, 0x25, 0x84, 0x41, 0xda, 0x45, +0x4e, 0x83, 0x00, 0x05, 0x2e, 0x51, 0x3a, 0x69, 0xda, 0x0a, 0x84, 0x01, 0x49, 0xff, 0xf9, 0x74, +0x44, 0x00, 0x02, 0x71, 0x49, 0xff, 0xf9, 0x56, 0x84, 0x01, 0xd5, 0x09, 0x80, 0x08, 0x49, 0xff, +0xf9, 0x6b, 0x44, 0x00, 0x13, 0x88, 0x49, 0xff, 0xf9, 0x4d, 0x80, 0x08, 0x49, 0xff, 0xfa, 0xea, +0x96, 0x3c, 0xc0, 0x04, 0x3e, 0x19, 0x36, 0x70, 0xd5, 0x1d, 0xf0, 0x01, 0xc0, 0x04, 0x3e, 0x19, +0x36, 0x74, 0xd5, 0x18, 0xb4, 0x3f, 0xc1, 0x04, 0x3e, 0x19, 0x36, 0x7c, 0xd5, 0x13, 0x4f, 0xc2, +0x00, 0x05, 0x3e, 0x19, 0x36, 0x84, 0xd5, 0x0e, 0x4e, 0xa2, 0x00, 0x05, 0x3e, 0x19, 0x36, 0x88, +0xd5, 0x09, 0x3e, 0x09, 0x36, 0x90, 0x3e, 0x29, 0x36, 0x98, 0x40, 0x11, 0x24, 0x1b, 0x40, 0x10, +0x24, 0x1a, 0x46, 0x00, 0x04, 0x11, 0x04, 0x30, 0x00, 0x8f, 0x80, 0x48, 0x42, 0x31, 0xe0, 0x0b, +0x3e, 0x09, 0x36, 0xa0, 0x49, 0xff, 0x8b, 0xce, 0x3c, 0x78, 0x9d, 0x2b, 0x3c, 0x68, 0x9d, 0x2a, +0x80, 0x06, 0x49, 0xff, 0xfc, 0xeb, 0xd5, 0x41, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x8f, +0x54, 0x10, 0x80, 0x04, 0xc1, 0x18, 0x3e, 0x09, 0x36, 0xd4, 0x49, 0xff, 0x8b, 0xbb, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x04, 0x04, 0xb4, 0x20, 0x54, 0x10, 0x80, 0x0f, 0xc9, 0x05, 0xb4, 0x20, +0x58, 0x10, 0x80, 0x0f, 0xb6, 0x20, 0x50, 0x10, 0x0e, 0x38, 0xb4, 0x41, 0x84, 0x02, 0x40, 0x21, +0x00, 0x04, 0xd5, 0x10, 0x54, 0x10, 0x00, 0x06, 0xc1, 0x0f, 0x3e, 0x09, 0x36, 0xec, 0x49, 0xff, +0x8b, 0xa1, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x3c, 0xb4, 0x41, 0x84, 0x01, 0x58, 0x21, +0x00, 0x02, 0xb6, 0x41, 0xd5, 0x10, 0x96, 0x04, 0xc0, 0x10, 0x46, 0x10, 0x04, 0x10, 0x04, 0x20, +0x81, 0x01, 0x3e, 0x09, 0x37, 0x04, 0x58, 0x21, 0x00, 0x0f, 0x14, 0x20, 0x81, 0x01, 0x49, 0xff, +0x8b, 0x89, 0x84, 0x03, 0x49, 0xff, 0xff, 0x28, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x40, 0x3e, 0x09, 0x96, 0xfc, 0x46, 0x10, 0x00, 0x8e, +0x58, 0x10, 0x8e, 0x1c, 0x80, 0x62, 0x49, 0xff, 0x8b, 0xa9, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, +0x04, 0x00, 0x04, 0x80, 0x00, 0x05, 0x04, 0x90, 0x00, 0x14, 0x42, 0x64, 0x40, 0x0b, 0xce, 0x03, +0x80, 0xe6, 0xd5, 0x08, 0x3c, 0x7c, 0x60, 0xc0, 0xcf, 0x02, 0xd5, 0x02, 0xdd, 0x27, 0x44, 0x61, +0x00, 0x00, 0x40, 0x04, 0x1c, 0x09, 0x94, 0x07, 0x96, 0x00, 0xc0, 0x0c, 0x3e, 0x09, 0x37, 0x1c, +0x49, 0xff, 0x8b, 0x50, 0x3c, 0x0c, 0x60, 0xb7, 0xc0, 0x06, 0x58, 0x63, 0x00, 0x80, 0xdd, 0x20, +0xd5, 0x09, 0xcf, 0x08, 0x80, 0x28, 0x80, 0x49, 0x3e, 0x09, 0x37, 0x30, 0x49, 0xff, 0x8b, 0x42, +0xd5, 0x09, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x04, 0x00, 0x84, 0x20, 0xa9, 0x85, 0x14, 0x10, +0x00, 0x14, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x3e, 0x29, 0x37, 0x68, 0x80, 0xc0, 0x80, 0xe1, 0x5c, 0x00, 0x00, 0x20, 0x84, 0x20, +0x44, 0x30, 0x00, 0xf4, 0x49, 0xfb, 0xa5, 0xcc, 0x92, 0x00, 0x3e, 0x09, 0x82, 0xc0, 0x38, 0x70, +0x1a, 0x0a, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x84, 0x00, 0xa0, 0x0d, 0x84, 0x41, 0x40, 0x61, +0x18, 0x0c, 0x40, 0x03, 0x00, 0x04, 0xa8, 0x0d, 0xa0, 0x0e, 0x40, 0x63, 0x00, 0x04, 0xa9, 0x8e, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3e, 0x09, +0x83, 0x40, 0x84, 0x20, 0x49, 0xff, 0x8c, 0x1a, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x40, 0x3e, 0x09, 0x83, 0x40, 0x46, 0x10, 0x00, 0x8f, +0x58, 0x10, 0x86, 0x14, 0x80, 0x62, 0x49, 0xff, 0x8b, 0x29, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x20, 0x84, 0x0f, 0x49, 0xff, +0x9b, 0xf3, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x84, 0x00, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x43, 0x50, 0x1f, +0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x0d, 0x4e, 0x00, 0x0f, 0x80, 0x07, 0x84, 0x21, 0x92, 0x01, +0x54, 0x50, 0x00, 0x03, 0xd1, 0x10, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x8c, 0x42, 0x00, +0x78, 0x0b, 0xc8, 0x09, 0x46, 0x00, 0x04, 0x00, 0x46, 0x15, 0xc1, 0xfe, 0x58, 0x10, 0x8e, 0x80, +0x14, 0x10, 0x00, 0x47, 0x2e, 0x07, 0xf0, 0x4d, 0x84, 0xa1, 0xd8, 0x05, 0x49, 0xfb, 0x93, 0x82, +0x49, 0xfb, 0xa8, 0xc8, 0x2e, 0x07, 0xf0, 0x4d, 0xc8, 0x36, 0x2e, 0x01, 0x3a, 0x5a, 0x84, 0xa1, +0xd8, 0x0b, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x4a, 0x46, 0x20, 0x00, 0xff, 0x40, 0x10, +0x88, 0x04, 0x14, 0x10, 0x00, 0x4a, 0x46, 0x10, 0x04, 0x00, 0x04, 0x50, 0x80, 0x82, 0x46, 0x6f, +0xff, 0x0f, 0x58, 0x63, 0x0f, 0xff, 0x46, 0x00, 0x04, 0x50, 0x40, 0x52, 0x98, 0x02, 0x14, 0x50, +0x80, 0x82, 0x44, 0x10, 0x00, 0x83, 0x80, 0x80, 0xa8, 0x43, 0x44, 0x10, 0x00, 0x41, 0xb6, 0x24, +0x80, 0x60, 0x84, 0x23, 0xa8, 0x43, 0x80, 0x40, 0x44, 0x00, 0x00, 0xcf, 0x14, 0x01, 0x80, 0x0a, +0x44, 0x00, 0x00, 0x67, 0x14, 0x01, 0x00, 0x0b, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, 0x88, 0xa0, +0x3c, 0x1f, 0xfb, 0xb3, 0x49, 0xfb, 0x8e, 0x8c, 0x3c, 0x2d, 0xfb, 0xa7, 0x84, 0x21, 0x84, 0x03, +0xdd, 0x22, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x0e, 0x42, 0x00, 0x4c, 0x0b, 0xc0, 0x06, +0x46, 0x00, 0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x26, 0x25, 0x58, 0x00, +0x0a, 0x00, 0x49, 0xfe, 0x44, 0x87, 0x84, 0x20, 0x44, 0x20, 0x00, 0xe0, 0x3e, 0x09, 0x8e, 0x7c, +0x49, 0xfe, 0x56, 0x42, 0x84, 0x20, 0x44, 0x20, 0x00, 0xe0, 0x3e, 0x09, 0x8f, 0x5c, 0x49, 0xfe, +0x56, 0x3b, 0x44, 0x20, 0x00, 0xe0, 0x84, 0x20, 0x3e, 0x09, 0x90, 0x3c, 0x49, 0xfe, 0x56, 0x34, +0x3c, 0x1c, 0x4e, 0x88, 0x3e, 0x09, 0x0d, 0x0c, 0x49, 0xff, 0x8a, 0x44, 0x3e, 0x09, 0x0d, 0x1c, +0x49, 0xff, 0x8a, 0x40, 0x49, 0xff, 0x84, 0x4c, 0x3e, 0x09, 0x0d, 0x3c, 0x49, 0xff, 0x8a, 0x3a, +0x49, 0xff, 0xa4, 0x02, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x44, 0x3f, 0x00, 0x00, 0x46, 0x67, +0x66, 0x20, 0x40, 0x50, 0x8c, 0x02, 0xd6, 0x07, 0xb4, 0x00, 0x46, 0x17, 0x63, 0x20, 0x40, 0x50, +0x0c, 0x02, 0xd9, 0x03, 0x49, 0xff, 0xfe, 0xa6, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x02, 0x01, +0x40, 0x10, 0xa0, 0x08, 0x92, 0x28, 0x14, 0x10, 0x02, 0x01, 0x84, 0x0a, 0x84, 0x20, 0x49, 0xfb, +0x87, 0x3f, 0x84, 0x0c, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x80, 0x84, 0x49, 0xff, 0x89, 0xd2, +0x84, 0x0f, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, 0x8a, 0xac, 0x49, 0xff, 0x89, 0xcb, 0x44, 0x00, +0x00, 0x10, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, 0x89, 0xdc, 0x49, 0xff, 0x89, 0xc3, 0x84, 0x07, +0x84, 0x20, 0x49, 0xfb, 0x87, 0x25, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x80, 0xe8, 0x3e, 0x29, +0x0d, 0x54, 0x84, 0x07, 0x49, 0xfb, 0x87, 0xd4, 0x84, 0x07, 0x49, 0xfb, 0x87, 0x3d, 0x46, 0x10, +0x00, 0x80, 0x58, 0x10, 0x8a, 0xec, 0x3e, 0x29, 0x0d, 0x54, 0x84, 0x0a, 0x49, 0xfb, 0x87, 0xc8, +0x84, 0x0a, 0x49, 0xfb, 0x87, 0x31, 0x84, 0x02, 0x49, 0xff, 0x8b, 0x7c, 0x49, 0xff, 0x84, 0x20, +0x84, 0x00, 0x49, 0xfb, 0x97, 0x51, 0x80, 0x40, 0x3e, 0x21, 0x3a, 0x73, 0x80, 0x20, 0x84, 0x00, +0x49, 0xfb, 0x9c, 0x70, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x8c, 0x46, 0x00, 0x04, 0x00, +0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x80, 0x8c, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x40, 0x92, 0x43, +0x94, 0x93, 0xb6, 0x40, 0x04, 0x20, 0x80, 0x0e, 0x44, 0x60, 0xe0, 0x00, 0x40, 0x21, 0x18, 0x02, +0x44, 0x50, 0xc0, 0x00, 0xd2, 0x08, 0x04, 0x10, 0x80, 0x0e, 0x40, 0x10, 0x98, 0x02, 0x44, 0x50, +0xa0, 0x00, 0xd9, 0x09, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x58, 0x10, +0x80, 0x02, 0xd5, 0x04, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0x46, 0x10, 0x04, 0x0e, +0x44, 0x20, 0x38, 0xbc, 0x80, 0x01, 0x14, 0x20, 0x80, 0x7e, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, +0x88, 0xb0, 0x14, 0x10, 0x00, 0x7f, 0x04, 0x10, 0x00, 0x81, 0x42, 0x10, 0xfc, 0x08, 0x14, 0x10, +0x00, 0x81, 0x3e, 0x09, 0x0d, 0x5c, 0x49, 0xff, 0x89, 0x95, 0x84, 0x07, 0x46, 0x10, 0x00, 0x8f, +0x58, 0x10, 0x85, 0xd8, 0x49, 0xff, 0xfe, 0x5c, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x06, +0x42, 0x10, 0x9c, 0x09, 0x14, 0x10, 0x01, 0x06, 0x47, 0xc0, 0x00, 0x80, 0x59, 0xce, 0x0f, 0x5c, +0x49, 0xff, 0xfe, 0x80, 0x46, 0x10, 0x00, 0x8f, 0x58, 0x10, 0x85, 0x14, 0x3e, 0x29, 0x0d, 0x54, +0x84, 0x06, 0x49, 0xfb, 0x87, 0x55, 0x84, 0x06, 0x49, 0xfb, 0x86, 0xbe, 0x3e, 0x09, 0x0d, 0x7c, +0x49, 0xff, 0x89, 0x70, 0x84, 0x02, 0x49, 0xfb, 0x99, 0xef, 0x80, 0xe0, 0x49, 0xfb, 0x97, 0x10, +0x81, 0x20, 0xa0, 0x3a, 0x44, 0x50, 0x00, 0x67, 0xd8, 0x05, 0xa0, 0x3b, 0x84, 0x21, 0x49, 0xff, +0xbf, 0x57, 0xa0, 0xba, 0x44, 0x50, 0x00, 0x6d, 0xda, 0x32, 0x44, 0x80, 0x9c, 0x40, 0x40, 0x84, +0xa0, 0x17, 0x84, 0x05, 0x40, 0x14, 0x00, 0x17, 0xc8, 0x08, 0x3c, 0x2c, 0x4e, 0x87, 0x80, 0x28, +0x3e, 0x09, 0x0d, 0x8c, 0x49, 0xff, 0x89, 0x4e, 0x46, 0x20, 0x04, 0x00, 0x14, 0x81, 0x00, 0x8e, +0x04, 0x01, 0x00, 0x8c, 0x54, 0x00, 0x00, 0x10, 0xc0, 0x0c, 0x84, 0x21, 0x3e, 0x11, 0x3a, 0x5a, +0x04, 0x01, 0x00, 0x4a, 0x46, 0x10, 0x00, 0xf0, 0x40, 0x00, 0x04, 0x04, 0x14, 0x01, 0x00, 0x4a, +0x2e, 0x01, 0x3a, 0x60, 0x84, 0xa1, 0xd8, 0x0b, 0x84, 0x00, 0x49, 0xff, 0xbe, 0xdf, 0x3e, 0x09, +0x0d, 0xb8, 0x49, 0xff, 0x89, 0x2f, 0x84, 0x00, 0x3e, 0x01, 0x3a, 0x60, 0xa0, 0xfa, 0x44, 0x50, +0x00, 0x2e, 0xdb, 0x14, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x02, 0x44, 0x1f, 0x00, 0x00, 0x46, 0x37, +0x66, 0x20, 0x40, 0x50, 0x04, 0x02, 0xd3, 0x07, 0xb4, 0x02, 0x40, 0x50, 0x04, 0x02, 0x46, 0x17, +0x63, 0x20, 0xd9, 0x04, 0xa0, 0x3b, 0x49, 0xff, 0xfc, 0xc9, 0xa0, 0xba, 0x44, 0x50, 0x00, 0x7c, +0xda, 0x08, 0xa0, 0xbb, 0x3c, 0x2e, 0x4e, 0x89, 0x3e, 0x09, 0x0d, 0xc0, 0x49, 0xff, 0x89, 0x0a, +0xa0, 0x3a, 0x44, 0x50, 0x00, 0x71, 0xd8, 0x59, 0x84, 0x0a, 0x49, 0xfb, 0x86, 0x6b, 0x84, 0x07, +0x49, 0xfb, 0x86, 0x68, 0x46, 0x30, 0x04, 0x00, 0x04, 0x01, 0x81, 0x06, 0x42, 0x00, 0x1c, 0x09, +0x14, 0x01, 0x81, 0x06, 0x80, 0x43, 0x04, 0x01, 0x00, 0x85, 0x42, 0x00, 0x30, 0x09, 0x14, 0x01, +0x00, 0x85, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x02, 0x0c, 0xb5, 0x46, 0x58, 0x05, 0x00, 0x10, +0xb6, 0x06, 0x3e, 0x09, 0x0d, 0xf8, 0x49, 0xff, 0x88, 0xe5, 0x84, 0x0a, 0x49, 0xfb, 0x96, 0x92, +0x42, 0xa5, 0x10, 0x09, 0xb7, 0x46, 0x2e, 0x30, 0x07, 0x60, 0x9e, 0xd9, 0x2e, 0x11, 0x3a, 0x73, +0x3e, 0x30, 0x07, 0x60, 0x84, 0x00, 0x49, 0xfb, 0x9b, 0x9f, 0x44, 0x10, 0x9c, 0x40, 0x40, 0x14, +0x85, 0x37, 0x84, 0x60, 0x3e, 0x37, 0xf0, 0x5a, 0x3e, 0x09, 0x0e, 0x04, 0x49, 0xff, 0x88, 0xca, +0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x8c, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x00, 0x8c, +0x44, 0x10, 0x0a, 0x2c, 0x3e, 0x29, 0x0d, 0x54, 0x84, 0x0a, 0x49, 0xfb, 0x86, 0x99, 0x84, 0x0a, +0x49, 0xfb, 0x86, 0x02, 0x49, 0xff, 0x8a, 0x34, 0x80, 0x07, 0x49, 0xfb, 0x97, 0xd3, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x84, 0xa1, 0xd8, 0x03, 0x49, 0xff, 0x89, 0x4c, +0xa0, 0xba, 0x44, 0x50, 0x00, 0x6f, 0xda, 0x0e, 0x04, 0x83, 0x80, 0x03, 0x84, 0xa1, 0x4c, 0x82, +0xc0, 0x0a, 0x80, 0x1f, 0x49, 0xfb, 0x90, 0xbc, 0xb4, 0x1f, 0x3e, 0x81, 0x3a, 0x58, 0x49, 0xfb, +0x90, 0xcd, 0x49, 0xff, 0xc0, 0x5f, 0xd5, 0x17, 0xdd, 0x3c, 0x00, 0x20, 0x00, 0x14, 0x81, 0x00, +0x80, 0x20, 0xca, 0x0a, 0x3e, 0x09, 0x8a, 0x58, 0x49, 0xff, 0xa1, 0x2c, 0xc8, 0x0c, 0x80, 0x28, +0x3e, 0x09, 0x83, 0x80, 0xd5, 0x06, 0x49, 0xff, 0xa8, 0xb3, 0x80, 0x28, 0x3e, 0x09, 0x83, 0x70, +0x49, 0xff, 0x8a, 0x58, 0x3c, 0x3c, 0x62, 0xc6, 0x3e, 0x09, 0x8b, 0x10, 0xcb, 0xe6, 0x49, 0xff, +0xc1, 0x11, 0x80, 0x07, 0x49, 0xfb, 0x97, 0x96, 0x48, 0xff, 0xff, 0x06, 0x49, 0x6e, 0x76, 0x61, +0x6c, 0x69, 0x64, 0x20, 0x46, 0x43, 0x45, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, +0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, +0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2f, 0x66, 0x63, 0x65, 0x2f, +0x66, 0x63, 0x65, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x21, 0x20, +0x52, 0x78, 0x46, 0x53, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x66, 0x61, +0x69, 0x6c, 0x0a, 0x00, 0x53, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x62, 0x6e, +0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, +0x6e, 0x0a, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x21, 0x20, 0x54, 0x78, 0x46, 0x73, +0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x0a, 0x00, +0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, +0x74, 0x20, 0x28, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x70, 0x65, 0x72, 0x69, 0x2f, 0x6d, 0x63, 0x75, 0x63, 0x74, 0x6c, 0x2f, 0x6d, 0x63, 0x75, +0x63, 0x74, 0x6c, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x63, +0x00, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x61, 0x70, 0x69, +0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x68, 0x00, 0x00, 0x00, 0x00, +0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x71, 0x75, 0x65, +0x75, 0x65, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x63, 0x00, 0x4c, 0x65, 0x64, 0x4e, +0x6f, 0x3a, 0x25, 0x6c, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x64, 0x43, 0x74, 0x72, 0x6c, 0x3a, 0x25, +0x6c, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x3e, 0x20, 0x25, 0x73, +0x0a, 0x00, 0x00, 0x00, 0x49, 0x50, 0x76, 0x36, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x20, +0x4e, 0x6f, 0x20, 0x75, 0x70, 0x70, 0x65, 0x72, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, +0x6c, 0x0a, 0x00, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x61, 0x70, 0x69, 0x51, 0x55, 0x5f, 0x44, 0x65, +0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x2b, 0x2b, 0x2b, 0x20, 0x77, 0x72, 0x61, 0x70, 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, +0x4e, 0x75, 0x6c, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +0x3a, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x75, 0x6c, 0x6c, +0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x21, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x50, 0x73, 0x50, 0x6f, 0x6c, +0x6c, 0x20, 0x3e, 0x3e, 0x20, 0x0a, 0x00, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x61, 0x70, 0x69, 0x51, +0x55, 0x5f, 0x44, 0x65, 0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x41, 0x72, 0x70, 0x20, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x20, +0x6d, 0x61, 0x74, 0x63, 0x68, 0x2c, 0x20, 0x52, 0x54, 0x4d, 0x50, 0x42, 0x75, 0x69, 0x6c, 0x64, +0x41, 0x72, 0x70, 0x4d, 0x73, 0x67, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x43, 0x68, 0x65, 0x63, +0x6b, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x54, 0x78, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, +0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x2d, 0x2d, 0x2d, +0x2d, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x61, 0x33, 0x30, 0x20, 0x3d, +0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x61, +0x33, 0x34, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x30, 0x78, 0x34, 0x33, 0x38, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, +0x30, 0x78, 0x30, 0x34, 0x33, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x52, 0x78, +0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x29, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x57, 0x61, 0x6b, 0x65, 0x20, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x3a, +0x25, 0x64, 0x0a, 0x00, 0x75, 0x63, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x62, 0x6c, 0x65, 0x57, 0x6f, +0x77, 0x53, 0x68, 0x61, 0x72, 0x65, 0x50, 0x69, 0x6e, 0x45, 0x6e, 0x3d, 0x25, 0x64, 0x0a, 0x00, +0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x55, 0x53, 0x42, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, +0x65, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x0a, 0x00, 0x00, 0x78, 0x3d, 0x30, 0x78, +0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x67, 0x50, 0x72, 0x55, 0x73, 0x62, 0x44, 0x70, 0x50, 0x75, +0x6c, 0x6c, 0x44, 0x6f, 0x77, 0x6e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3d, 0x30, 0x78, +0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x75, 0x63, 0x55, 0x73, 0x62, 0x44, 0x70, 0x50, 0x64, 0x6e, +0x4d, 0x6f, 0x64, 0x65, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x57, 0x6f, 0x57, 0x20, +0x77, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20, 0x70, 0x69, 0x6e, 0x0a, 0x00, +0x47, 0x50, 0x49, 0x4f, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x0a, 0x00, 0x00, 0x00, +0x52, 0x45, 0x47, 0x5f, 0x4c, 0x45, 0x44, 0x32, 0x5f, 0x53, 0x30, 0x3a, 0x25, 0x78, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x47, 0x5f, 0x4c, 0x45, 0x44, 0x32, 0x5f, 0x53, 0x31, 0x3a, +0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x68, 0x6f, +0x73, 0x74, 0x20, 0x61, 0x70, 0x70, 0x50, 0x6b, 0x74, 0x43, 0x6d, 0x64, 0x5f, 0x53, 0x65, 0x6e, +0x64, 0x57, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x0a, 0x00, 0x53, 0x65, 0x6e, 0x64, +0x57, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x21, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x2b, 0x2b, 0x2b, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x79, 0x70, 0x74, +0x65, 0x64, 0x2c, 0x20, 0x52, 0x78, 0x57, 0x49, 0x5f, 0x62, 0x73, 0x73, 0x69, 0x64, 0x3a, 0x25, +0x64, 0x20, 0x2b, 0x2b, 0x2b, 0x0a, 0x00, 0x00, 0x44, 0x33, 0x20, 0x6c, 0x65, 0x6e, 0x3a, 0x20, +0x25, 0x64, 0x2c, 0x20, 0x00, 0x2b, 0x2b, 0x2b, 0x48, 0x54, 0x43, 0x2c, 0x20, 0x50, 0x48, 0x59, +0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x45, 0x74, 0x68, 0x54, +0x79, 0x70, 0x65, 0x3a, 0x20, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x20, +0x50, 0x6b, 0x74, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x4c, 0x4c, 0x43, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, +0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x6d, 0x61, +0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x62, +0x79, 0x20, 0x55, 0x44, 0x50, 0x20, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x73, 0x20, 0x6e, +0x61, 0x6d, 0x65, 0x31, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, +0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x62, 0x79, 0x20, 0x55, 0x44, 0x50, 0x20, 0x51, 0x75, +0x65, 0x72, 0x69, 0x65, 0x72, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x20, 0x69, 0x73, 0x20, +0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x55, 0x44, 0x50, 0x20, 0x51, 0x75, 0x65, 0x72, +0x69, 0x65, 0x72, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x6e, 0x27, 0x74, 0x20, +0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x45, 0x41, 0x50, 0x4f, 0x4c, 0x20, 0x4b, 0x45, +0x59, 0x20, 0x2b, 0x2b, 0x2b, 0x0a, 0x00, 0x00, 0x45, 0x41, 0x50, 0x4f, 0x4c, 0x20, 0x74, 0x79, +0x70, 0x65, 0x20, 0x30, 0x20, 0x2b, 0x2b, 0x2b, 0x20, 0x0a, 0x00, 0x00, 0x5b, 0x25, 0x75, 0x5d, +0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x73, 0x74, 0x20, 0x31, 0x20, 0x73, 0x65, +0x63, 0x20, 0x23, 0x25, 0x64, 0x20, 0x21, 0x4c, 0x61, 0x73, 0x74, 0x42, 0x43, 0x4e, 0x20, 0x53, +0x45, 0x51, 0x28, 0x25, 0x75, 0x29, 0x40, 0x25, 0x75, 0x20, 0x0a, 0x00, 0x61, 0x62, 0x6e, 0x6f, +0x72, 0x6d, 0x61, 0x6c, 0x20, 0x52, 0x45, 0x53, 0x45, 0x54, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x50, +0x42, 0x46, 0x2c, 0x20, 0x30, 0x78, 0x61, 0x30, 0x63, 0x3a, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x73, 0x74, 0x20, 0x21, 0x0a, 0x00, 0x00, +0x0b, 0x5f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, 0x04, 0x5f, 0x74, 0x63, +0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x5f, 0x44, 0x69, 0x73, +0x61, 0x62, 0x6c, 0x65, 0x54, 0x78, 0x52, 0x78, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, +0x5f, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x78, 0x52, 0x78, 0x00, 0x53, 0x65, 0x6e, 0x64, +0x4e, 0x75, 0x6c, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x71, 0x75, +0x65, 0x75, 0x65, 0x50, 0x73, 0x50, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x45, 0x76, 0x65, 0x6e, +0x74, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3e, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x74, +0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x00, 0x00, 0x3d, 0x3d, 0x3d, 0x3e, +0x20, 0x54, 0x46, 0x20, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x2c, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3d, +0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, +0x6d, 0x61, 0x63, 0x20, 0x62, 0x75, 0x73, 0x79, 0x20, 0x25, 0x64, 0x00, 0x50, 0x6b, 0x74, 0x43, +0x6d, 0x64, 0x3a, 0x20, 0x43, 0x6f, 0x65, 0x78, 0x20, 0x57, 0x69, 0x66, 0x69, 0x20, 0x73, 0x74, +0x61, 0x74, 0x75, 0x73, 0x2c, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x25, 0x64, 0x29, +0x0a, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x74, 0x69, 0x6d, +0x65, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, +0x69, 0x64, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x50, 0x6b, 0x74, 0x43, 0x6d, 0x64, 0x3a, 0x20, +0x43, 0x6f, 0x65, 0x78, 0x20, 0x41, 0x46, 0x48, 0x2c, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, +0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, +0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x74, 0x65, 0x72, 0x3a, +0x25, 0x64, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, +0x5b, 0x46, 0x57, 0x2d, 0x3e, 0x48, 0x4f, 0x53, 0x54, 0x5d, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, +0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x30, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x46, 0x57, 0x2d, +0x3e, 0x48, 0x4f, 0x53, 0x54, 0x5d, 0x20, 0x73, 0x74, 0x65, 0x70, 0x32, 0x0a, 0x00, 0x00, 0x00, +0x5b, 0x46, 0x57, 0x2d, 0x3e, 0x48, 0x4f, 0x53, 0x54, 0x5d, 0x20, 0x73, 0x74, 0x65, 0x70, 0x33, +0x2c, 0x20, 0x30, 0x78, 0x38, 0x30, 0x43, 0x3d, 0x25, 0x30, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, +0x5b, 0x48, 0x4f, 0x53, 0x54, 0x20, 0x2d, 0x3e, 0x20, 0x46, 0x57, 0x5d, 0x20, 0x68, 0x6f, 0x73, +0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x31, 0x20, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, +0x63, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x0a, 0x00, 0x00, 0x57, 0x4f, 0x57, 0x5f, +0x57, 0x41, 0x4b, 0x45, 0x55, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x5f, 0x47, 0x50, 0x49, 0x4f, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4f, 0x3a, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, +0x30, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x31, 0x20, 0x30, +0x78, 0x25, 0x78, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x32, 0x20, 0x30, 0x78, 0x25, 0x78, +0x20, 0x0a, 0x00, 0x00, 0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x6f, 0x70, 0x74, 0x20, 0x46, +0x41, 0x4b, 0x45, 0x53, 0x54, 0x41, 0x4e, 0x44, 0x42, 0x59, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3a, 0x25, 0x64, 0x20, 0x65, 0x78, 0x74, 0x3a, 0x25, +0x64, 0x0a, 0x0a, 0x00, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67, +0x65, 0x72, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x77, 0x6f, 0x77, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, +0x20, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x77, 0x6f, 0x77, 0x20, 0x70, 0x6b, 0x74, 0x44, +0x65, 0x74, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x73, 0x6b, 0x3a, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x53, 0x74, 0x61, 0x4d, 0x61, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, +0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x41, 0x70, 0x4d, 0x61, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, +0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x46, 0x6c, 0x61, 0x67, 0x3a, 0x30, +0x78, 0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x52, 0x50, 0x4e, 0x53, 0x2c, 0x20, 0x6c, +0x65, 0x6e, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x25, 0x30, 0x32, 0x78, +0x20, 0x00, 0x00, 0x00, 0x49, 0x50, 0x61, 0x64, 0x64, 0x72, 0x28, 0x74, 0x79, 0x70, 0x65, 0x3d, +0x25, 0x64, 0x29, 0x20, 0x69, 0x64, 0x78, 0x5b, 0x25, 0x64, 0x5d, 0x20, 0x65, 0x6e, 0x61, 0x62, +0x6c, 0x65, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x41, 0x64, 0x64, 0x72, 0x3a, 0x30, 0x78, 0x00, 0x00, +0x25, 0x30, 0x32, 0x78, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, 0x53, 0x59, 0x4e, 0x20, +0x74, 0x79, 0x70, 0x65, 0x5b, 0x25, 0x64, 0x5d, 0x20, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x3a, +0x25, 0x64, 0x2c, 0x20, 0x53, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x3a, 0x25, 0x64, 0x2c, 0x20, +0x44, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x54, 0x43, 0x50, 0x20, 0x53, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x20, 0x3a, 0x30, 0x78, 0x00, +0x25, 0x30, 0x32, 0x78, 0x00, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, 0x44, 0x73, 0x74, 0x41, +0x64, 0x64, 0x72, 0x20, 0x3a, 0x30, 0x78, 0x00, 0x41, 0x69, 0x64, 0x3a, 0x25, 0x64, 0x2c, 0x20, +0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x0a, 0x00, 0x00, 0x00, +0x49, 0x50, 0x76, 0x34, 0x2f, 0x54, 0x43, 0x50, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6e, +0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x50, 0x76, 0x34, 0x2f, 0x54, 0x43, 0x50, +0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x49, 0x50, 0x76, 0x36, +0x2f, 0x54, 0x43, 0x50, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x4d, +0x61, 0x73, 0x6b, 0x3a, 0x25, 0x58, 0x0a, 0x00, 0x49, 0x50, 0x76, 0x34, 0x2f, 0x55, 0x44, 0x50, +0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x49, 0x50, 0x76, 0x34, 0x2f, 0x55, 0x44, 0x50, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x3a, 0x25, +0x64, 0x0a, 0x00, 0x00, 0x49, 0x50, 0x76, 0x36, 0x2f, 0x55, 0x44, 0x50, 0x20, 0x70, 0x6f, 0x72, +0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x55, 0x44, 0x50, 0x20, +0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x4d, 0x61, 0x73, 0x6b, 0x3a, 0x25, 0x58, 0x0a, 0x00, +0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x6e, +0x61, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, +0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x57, 0x4f, 0x57, 0x20, 0x61, 0x6e, 0x74, 0x65, +0x6e, 0x6e, 0x61, 0x20, 0x31, 0x78, 0x31, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x25, +0x64, 0x0a, 0x00, 0x00, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x4d, 0x43, 0x55, 0x20, 0x43, +0x52, 0x28, 0x30, 0x78, 0x33, 0x38, 0x29, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x43, 0x52, +0x28, 0x30, 0x78, 0x31, 0x32, 0x34, 0x29, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x43, 0x52, +0x28, 0x30, 0x78, 0x31, 0x32, 0x38, 0x29, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, +0x28, 0x25, 0x64, 0x29, 0x0a, 0x0a, 0x00, 0x00, 0x61, 0x70, 0x70, 0x50, 0x6b, 0x74, 0x43, 0x6d, +0x64, 0x5f, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, +0x2d, 0x2d, 0x2d, 0x20, 0x0a, 0x0a, 0x00, 0x00, 0x4d, 0x41, 0x43, 0x20, 0x54, 0x78, 0x2f, 0x52, +0x78, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2e, 0x20, 0x42, 0x75, 0x73, +0x79, 0x20, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x0a, 0x00, 0x62, 0x65, 0x61, 0x63, +0x6f, 0x6e, 0x20, 0x49, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x57, +0x49, 0x54, 0x43, 0x48, 0x5f, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x4d, 0x45, 0x4e, +0x54, 0x20, 0x0a, 0x00, 0x50, 0x65, 0x65, 0x72, 0x41, 0x64, 0x64, 0x42, 0x41, 0x52, 0x65, 0x71, +0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x25, 0x73, 0x20, 0x63, 0x69, 0x70, 0x68, 0x65, +0x72, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x78, 0x3a, 0x25, 0x64, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x35, 0x47, 0x20, 0x63, 0x68, 0x20, 0x64, 0x61, +0x74, 0x61, 0x0a, 0x00, 0x49, 0x63, 0x76, 0x45, 0x72, 0x72, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x4d, 0x69, 0x63, 0x45, 0x72, 0x72, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x57, 0x72, 0x69, 0x74, +0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, +0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x48, +0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x78, 0x4d, 0x67, 0x6d, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, +0x3a, 0x20, 0x44, 0x49, 0x53, 0x41, 0x53, 0x53, 0x4f, 0x43, 0x21, 0x20, 0x57, 0x41, 0x4b, 0x45, +0x55, 0x50, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x48, +0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x78, 0x4d, 0x67, 0x6d, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, +0x3a, 0x20, 0x44, 0x45, 0x41, 0x55, 0x54, 0x48, 0x21, 0x20, 0x57, 0x41, 0x4b, 0x45, 0x55, 0x50, +0x5f, 0x48, 0x4f, 0x53, 0x54, 0x21, 0x0a, 0x00, 0x53, 0x54, 0x41, 0x48, 0x61, 0x6e, 0x64, 0x6c, +0x65, 0x52, 0x78, 0x4d, 0x67, 0x6d, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x50, 0x65, +0x65, 0x72, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x41, 0x64, 0x76, 0x50, 0x77, 0x72, 0x53, 0x61, +0x76, 0x69, 0x6e, 0x67, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x79, 0x28, 0x29, 0x3d, 0x46, 0x41, 0x4c, +0x53, 0x45, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x1b, 0x5b, 0x33, 0x31, 0x6d, 0x5b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x55, 0x32, 0x4d, +0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x5d, 0x20, 0x25, 0x64, 0x1b, 0x5b, 0x6d, 0x0a, 0x00, +0x5b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5d, 0x20, 0x25, +0x64, 0x2c, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x25, 0x64, 0x2c, +0x20, 0x74, 0x62, 0x74, 0x74, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x61, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x49, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x57, +0x49, 0x54, 0x43, 0x48, 0x5f, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x4d, 0x45, 0x4e, +0x54, 0x20, 0x0a, 0x00, 0x52, 0x78, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x20, +0x6b, 0x65, 0x65, 0x70, 0x20, 0x61, 0x77, 0x61, 0x6b, 0x65, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x52, 0x78, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x62, 0x6c, 0x65, +0x20, 0x74, 0x6f, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x0a, 0x00, 0x5b, 0x44, 0x61, 0x74, +0x61, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5d, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x73, 0x6c, 0x65, +0x65, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x6c, 0x65, 0x6e, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x78, 0x45, +0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x46, 0x20, 0x00, 0x53, 0x54, 0x41, 0x46, +0x69, 0x6e, 0x64, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, +0x68, 0x6d, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x57, 0x72, 0x69, 0x74, 0x65, 0x54, 0x78, 0x57, +0x49, 0x5f, 0x44, 0x61, 0x74, 0x61, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x52, 0x65, 0x70, 0x6f, +0x72, 0x74, 0x4d, 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x67, 0x65, 0x6e, 0x65, +0x72, 0x69, 0x63, 0x20, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x30, 0x78, 0x66, 0x66, 0x20, 0x2a, +0x36, 0x20, 0x61, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x25, 0x73, 0x2c, 0x20, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x41, 0x6c, 0x67, 0x3a, 0x25, 0x64, +0x2c, 0x20, 0x42, 0x73, 0x73, 0x49, 0x64, 0x78, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x4b, 0x65, 0x79, +0x49, 0x64, 0x78, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x20, 0x3a, +0x20, 0x28, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x54, 0x79, 0x70, 0x65, 0x2d, 0x25, 0x64, 0x29, +0x20, 0x4e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x0a, 0x00, 0x00, +0x45, 0x52, 0x52, 0x4f, 0x52, 0x3a, 0x20, 0x47, 0x54, 0x4b, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x6c, +0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, +0x28, 0x25, 0x64, 0x29, 0x20, 0x0a, 0x00, 0x00, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, +0x70, 0x4d, 0x73, 0x67, 0x31, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x45, 0x56, 0x45, +0x4e, 0x54, 0x5f, 0x47, 0x54, 0x4b, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x21, 0x0a, 0x00, 0x00, +0x3d, 0x3e, 0x47, 0x31, 0x2c, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x2d, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x50, 0x65, 0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x4d, 0x73, 0x67, 0x31, +0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x50, 0x65, 0x65, 0x72, +0x50, 0x61, 0x69, 0x72, 0x4d, 0x73, 0x67, 0x33, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x73, 0x67, +0x31, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x50, 0x41, 0x49, +0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x00, +0x57, 0x50, 0x41, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x77, 0x69, +0x73, 0x65, 0x4b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, +0x70, 0x4d, 0x73, 0x67, 0x31, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x10, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, +0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, +0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x36, 0x63, 0x7c, 0x77, 0x7b, +0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, +0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, +0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, +0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, +0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, +0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, +0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, +0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, +0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, +0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, +0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, +0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, +0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, +0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, +0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, +0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x52, 0x09, 0x6a, 0xd5, +0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, +0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, +0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, +0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, +0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, +0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, +0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, +0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, +0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, +0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, +0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, +0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, +0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, +0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, +0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, +0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, 0x00, 0x09, 0x12, 0x1b, +0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, +0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20, +0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0xab, 0xa2, 0xb9, 0xb0, +0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, +0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd, +0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 0x4d, 0x44, 0x5f, 0x56, +0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, +0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7, +0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 0x7c, 0x75, 0x6e, 0x67, +0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, +0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c, +0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0x9a, 0x93, 0x88, 0x81, +0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, +0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba, +0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 0x31, 0x38, 0x23, 0x2a, +0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, 0x00, 0x0b, 0x16, 0x1d, +0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, +0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66, +0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 0xcb, 0xc0, 0xdd, 0xd6, +0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, +0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b, +0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 0x8d, 0x86, 0x9b, 0x90, +0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, +0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea, +0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 0x47, 0x4c, 0x51, 0x5a, +0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, +0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21, +0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 0x01, 0x0a, 0x17, 0x1c, +0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, +0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67, +0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 0xca, 0xc1, 0xdc, 0xd7, +0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, 0x00, 0x0d, 0x1a, 0x17, +0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, +0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac, +0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 0x6b, 0x66, 0x71, 0x7c, +0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, +0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa, +0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0xd6, 0xdb, 0xcc, 0xc1, +0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, +0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd, +0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 0x0a, 0x07, 0x10, 0x1d, +0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, +0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6, +0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 0xb7, 0xba, 0xad, 0xa0, +0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, +0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b, +0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 0xdc, 0xd1, 0xc6, 0xcb, +0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, 0x00, 0x0e, 0x1c, 0x12, +0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, +0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9, +0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 0x3b, 0x35, 0x27, 0x29, +0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, +0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f, +0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 0x76, 0x78, 0x6a, 0x64, +0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, +0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53, +0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 0xa1, 0xaf, 0xbd, 0xb3, +0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, +0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68, +0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0xec, 0xe2, 0xf0, 0xfe, +0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, +0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25, +0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 0xd7, 0xd9, 0xcb, 0xc5, +0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, 0x01, 0x23, 0x45, 0x67, +0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x99, 0x79, 0x82, 0x5a, +0xa1, 0xeb, 0xd9, 0x6e, 0xdc, 0xbc, 0x1b, 0x8f, 0xd6, 0xc1, 0x62, 0xca, 0x01, 0x23, 0x45, 0x67, +0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf0, 0xe1, 0xd2, 0xc3, +0x98, 0x2f, 0x8a, 0x42, 0x91, 0x44, 0x37, 0x71, 0xcf, 0xfb, 0xc0, 0xb5, 0xa5, 0xdb, 0xb5, 0xe9, +0x5b, 0xc2, 0x56, 0x39, 0xf1, 0x11, 0xf1, 0x59, 0xa4, 0x82, 0x3f, 0x92, 0xd5, 0x5e, 0x1c, 0xab, +0x98, 0xaa, 0x07, 0xd8, 0x01, 0x5b, 0x83, 0x12, 0xbe, 0x85, 0x31, 0x24, 0xc3, 0x7d, 0x0c, 0x55, +0x74, 0x5d, 0xbe, 0x72, 0xfe, 0xb1, 0xde, 0x80, 0xa7, 0x06, 0xdc, 0x9b, 0x74, 0xf1, 0x9b, 0xc1, +0xc1, 0x69, 0x9b, 0xe4, 0x86, 0x47, 0xbe, 0xef, 0xc6, 0x9d, 0xc1, 0x0f, 0xcc, 0xa1, 0x0c, 0x24, +0x6f, 0x2c, 0xe9, 0x2d, 0xaa, 0x84, 0x74, 0x4a, 0xdc, 0xa9, 0xb0, 0x5c, 0xda, 0x88, 0xf9, 0x76, +0x52, 0x51, 0x3e, 0x98, 0x6d, 0xc6, 0x31, 0xa8, 0xc8, 0x27, 0x03, 0xb0, 0xc7, 0x7f, 0x59, 0xbf, +0xf3, 0x0b, 0xe0, 0xc6, 0x47, 0x91, 0xa7, 0xd5, 0x51, 0x63, 0xca, 0x06, 0x67, 0x29, 0x29, 0x14, +0x85, 0x0a, 0xb7, 0x27, 0x38, 0x21, 0x1b, 0x2e, 0xfc, 0x6d, 0x2c, 0x4d, 0x13, 0x0d, 0x38, 0x53, +0x54, 0x73, 0x0a, 0x65, 0xbb, 0x0a, 0x6a, 0x76, 0x2e, 0xc9, 0xc2, 0x81, 0x85, 0x2c, 0x72, 0x92, +0xa1, 0xe8, 0xbf, 0xa2, 0x4b, 0x66, 0x1a, 0xa8, 0x70, 0x8b, 0x4b, 0xc2, 0xa3, 0x51, 0x6c, 0xc7, +0x19, 0xe8, 0x92, 0xd1, 0x24, 0x06, 0x99, 0xd6, 0x85, 0x35, 0x0e, 0xf4, 0x70, 0xa0, 0x6a, 0x10, +0x16, 0xc1, 0xa4, 0x19, 0x08, 0x6c, 0x37, 0x1e, 0x4c, 0x77, 0x48, 0x27, 0xb5, 0xbc, 0xb0, 0x34, +0xb3, 0x0c, 0x1c, 0x39, 0x4a, 0xaa, 0xd8, 0x4e, 0x4f, 0xca, 0x9c, 0x5b, 0xf3, 0x6f, 0x2e, 0x68, +0xee, 0x82, 0x8f, 0x74, 0x6f, 0x63, 0xa5, 0x78, 0x14, 0x78, 0xc8, 0x84, 0x08, 0x02, 0xc7, 0x8c, +0xfa, 0xff, 0xbe, 0x90, 0xeb, 0x6c, 0x50, 0xa4, 0xf7, 0xa3, 0xf9, 0xbe, 0xf2, 0x78, 0x71, 0xc6, +0x67, 0xe6, 0x09, 0x6a, 0x85, 0xae, 0x67, 0xbb, 0x72, 0xf3, 0x6e, 0x3c, 0x3a, 0xf5, 0x4f, 0xa5, +0x7f, 0x52, 0x0e, 0x51, 0x8c, 0x68, 0x05, 0x9b, 0xab, 0xd9, 0x83, 0x1f, 0x19, 0xcd, 0xe0, 0x5b, +0x50, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x43, +0x4e, 0x54, 0x31, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x50, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x52, 0x54, +0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x43, 0x4e, 0x54, 0x32, 0x3a, 0x25, 0x64, 0x0a, 0x00, +0x54, 0x58, 0x52, 0x58, 0x51, 0x5f, 0x50, 0x43, 0x4e, 0x54, 0x20, 0x62, 0x75, 0x73, 0x79, 0x3a, +0x25, 0x78, 0x0a, 0x00, 0x54, 0x58, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x62, 0x75, 0x73, 0x79, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x4f, 0x54, +0x41, 0x4c, 0x5f, 0x43, 0x4e, 0x54, 0x31, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x41, 0x53, 0x53, 0x45, +0x52, 0x54, 0x20, 0x25, 0x73, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, +0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x63, 0x68, 0x69, 0x70, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x70, +0x73, 0x2e, 0x63, 0x00, 0x57, 0x49, 0x46, 0x49, 0x20, 0x50, 0x53, 0x20, 0x4f, 0x70, 0x65, 0x72, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x41, 0x64, 0x76, 0x50, +0x53, 0x4d, 0x6f, 0x64, 0x65, 0x2e, 0x50, 0x77, 0x72, 0x4c, 0x76, 0x6c, 0x3a, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x32, 0x5d, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, +0x64, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x2d, 0x73, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x0a, 0x00, +0x25, 0x73, 0x3a, 0x3a, 0x20, 0x57, 0x61, 0x69, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, +0x4d, 0x41, 0x43, 0x20, 0x30, 0x78, 0x31, 0x32, 0x30, 0x30, 0x28, 0x25, 0x78, 0x29, 0x20, 0x61, +0x6e, 0x64, 0x20, 0x42, 0x42, 0x50, 0x20, 0x30, 0x78, 0x32, 0x31, 0x33, 0x30, 0x20, 0x28, 0x25, +0x78, 0x29, 0x0a, 0x00, 0x57, 0x6f, 0x77, 0x4c, 0x6f, 0x77, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53, +0x6c, 0x65, 0x65, 0x70, 0x3a, 0x20, 0x67, 0x66, 0x67, 0x54, 0x78, 0x53, 0x65, 0x6e, 0x74, 0x21, +0x20, 0x0a, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x63, 0x68, 0x69, +0x70, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x63, 0x00, 0x00, 0x00, +0x63, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x73, 0x77, 0x69, +0x74, 0x63, 0x68, 0x20, 0x62, 0x75, 0x73, 0x79, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, +0x0a, 0x00, 0x00, 0x00, 0x63, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x75, 0x73, 0x79, +0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, +0x46, 0x57, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x25, 0x78, 0x0a, 0x00, +0x77, 0x69, 0x66, 0x69, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x6f, 0x70, 0x65, 0x72, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x20, 0x2d, 0x2d, 0x20, 0x57, 0x69, 0x46, 0x69, 0x5f, 0x54, 0x61, 0x73, 0x6b, 0x5f, 0x49, 0x4e, +0x49, 0x54, 0x20, 0x2d, 0x2d, 0x0a, 0x00, 0x00, 0x4e, 0x55, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, +0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x62, 0x63, 0x6e, 0x20, 0x74, 0x78, 0x20, +0x64, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x2e, 0x2e, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x57, 0x69, 0x46, 0x69, 0x5f, 0x54, 0x61, 0x73, 0x6b, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x0a, 0x00, +0x57, 0x49, 0x46, 0x49, 0x20, 0x52, 0x41, 0x4d, 0x20, 0x43, 0x4f, 0x44, 0x45, 0x3a, 0x20, 0x54, +0x61, 0x73, 0x6b, 0x20, 0x6a, 0x69, 0x66, 0x66, 0x69, 0x65, 0x73, 0x28, 0x25, 0x64, 0x29, 0x20, +0x50, 0x4b, 0x54, 0x43, 0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x77, 0x61, 0x6b, 0x65, +0x75, 0x70, 0x0a, 0x00, 0x57, 0x49, 0x46, 0x49, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, +0x20, 0x4d, 0x53, 0x47, 0x5f, 0x49, 0x44, 0x5f, 0x57, 0x4d, 0x54, 0x5f, 0x57, 0x49, 0x46, 0x49, +0x5f, 0x55, 0x53, 0x42, 0x5f, 0x44, 0x50, 0x5f, 0x50, 0x55, 0x4c, 0x4c, 0x5f, 0x44, 0x4f, 0x57, +0x4e, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x0a, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, +0x74, 0x20, 0x46, 0x43, 0x45, 0x0a, 0x00, 0x00, 0x20, 0x21, 0x21, 0x2d, 0x2d, 0x3e, 0x20, 0x54, +0x61, 0x73, 0x6b, 0x20, 0x6a, 0x69, 0x66, 0x66, 0x69, 0x65, 0x73, 0x28, 0x25, 0x64, 0x29, 0x20, +0x52, 0x45, 0x53, 0x45, 0x54, 0x20, 0x52, 0x41, 0x4d, 0x0a, 0x00, 0x00, 0x5b, 0x44, 0x79, 0x56, +0x47, 0x41, 0x5d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, 0x30, 0x5b, +0x31, 0x35, 0x3a, 0x38, 0x5d, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x5b, 0x44, 0x79, 0x56, 0x47, 0x41, 0x5d, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x56, 0x47, 0x41, +0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x5b, 0x44, 0x79, 0x56, 0x47, 0x41, 0x5d, 0x53, 0x65, 0x74, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, +0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x76, 0x61, +0x6c, 0x69, 0x64, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, +0x6e, 0x6e, 0x65, 0x6c, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x78, 0x50, 0x41, 0x20, +0x72, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, +0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x78, 0x4c, 0x4e, 0x41, 0x20, 0x72, 0x66, 0x20, +0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x69, 0x6c, 0x6c, 0x65, +0x67, 0x61, 0x6c, 0x20, 0x72, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, +0x0a, 0x00, 0x00, 0x00, 0x25, 0x64, 0x20, 0x00, 0x0a, 0x57, 0x46, 0x49, 0x44, 0x3d, 0x25, 0x64, +0x20, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x54, 0x53, 0x53, 0x49, 0x20, 0x57, 0x52, 0x49, 0x54, +0x45, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x6c, 0x6f, 0x70, 0x65, 0x5b, 0x30, 0x5d, +0x3d, 0x25, 0x64, 0x2c, 0x20, 0x73, 0x6c, 0x6f, 0x70, 0x65, 0x5b, 0x31, 0x5d, 0x3d, 0x25, 0x64, +0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x30, 0x5d, 0x3d, 0x25, 0x64, 0x2c, 0x20, +0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x31, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x20, 0x54, 0x53, 0x53, 0x49, 0x21, 0x21, 0x0a, 0x00, +0x74, 0x6d, 0x70, 0x76, 0x61, 0x6c, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x63, 0x6e, 0x74, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x54, 0x53, 0x53, 0x49, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x25, 0x78, +0x2c, 0x20, 0x54, 0x53, 0x53, 0x49, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, +0x4c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x5b, 0x30, 0x5d, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x5b, 0x31, +0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x20, 0x64, 0x75, +0x65, 0x20, 0x74, 0x6f, 0x20, 0x54, 0x58, 0x42, 0x46, 0x20, 0x6f, 0x72, 0x20, 0x42, 0x54, 0x2d, +0x43, 0x6f, 0x65, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x49, 0x4e, +0x46, 0x4f, 0x5f, 0x31, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x53, 0x54, 0x53, +0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5b, 0x30, +0x5d, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5b, 0x31, 0x5d, 0x3d, +0x25, 0x78, 0x0a, 0x00, 0x31, 0x2e, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x32, 0x2e, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x33, 0x2e, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x69, 0x64, 0x78, 0x3d, 0x25, 0x64, 0x20, 0x6d, 0x65, 0x61, 0x73, 0x75, +0x72, 0x65, 0x64, 0x5f, 0x64, 0x62, 0x3d, 0x25, 0x64, 0x20, 0x2a, 0x20, 0x28, 0x30, 0x2e, 0x35, +0x29, 0x0a, 0x00, 0x00, 0x31, 0x2e, 0x20, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x64, 0x65, 0x6c, 0x74, +0x61, 0x5f, 0x74, 0x6d, 0x70, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x20, 0x74, +0x73, 0x73, 0x69, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x74, 0x6d, 0x70, 0x3d, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x3d, 0x25, +0x64, 0x0a, 0x00, 0x00, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x3d, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x5b, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5d, 0x20, 0x30, 0x78, 0x31, +0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x33, 0x41, 0x38, +0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x5b, 0x41, 0x66, 0x74, 0x65, 0x72, 0x5d, 0x20, +0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, +0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x5b, 0x42, 0x65, 0x66, +0x6f, 0x72, 0x65, 0x20, 0x31, 0x53, 0x53, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5d, +0x20, 0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, +0x31, 0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x5b, 0x31, 0x53, 0x53, +0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5d, 0x20, 0x55, 0x73, 0x65, 0x20, 0x57, 0x46, +0x31, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, +0x65, 0x6e, 0x73, 0x61, 0x74, 0x65, 0x20, 0x57, 0x46, 0x30, 0x0a, 0x00, 0x5b, 0x31, 0x53, 0x53, +0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5d, 0x20, 0x55, 0x73, 0x65, 0x20, 0x57, 0x46, +0x30, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, +0x65, 0x6e, 0x73, 0x61, 0x74, 0x65, 0x20, 0x57, 0x46, 0x31, 0x0a, 0x00, 0x5b, 0x41, 0x66, 0x74, +0x65, 0x72, 0x20, 0x31, 0x53, 0x53, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5d, 0x20, +0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, +0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x53, 0x55, +0x4d, 0x3d, 0x25, 0x64, 0x20, 0x41, 0x4d, 0x31, 0x30, 0x3d, 0x25, 0x64, 0x20, 0x41, 0x4d, 0x5f, +0x44, 0x49, 0x46, 0x46, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x50, 0x41, 0x53, 0x53, 0x54, 0x68, 0x72, +0x65, 0x73, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x53, 0x4f, 0x46, 0x54, 0x41, 0x47, 0x43, 0x20, +0x52, 0x45, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00, 0x00, +0x45, 0x52, 0x52, 0x4f, 0x52, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x41, 0x47, +0x43, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x0a, 0x00, 0x00, +0x54, 0x48, 0x45, 0x52, 0x4d, 0x41, 0x4c, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x54, 0x68, 0x65, 0x72, +0x6d, 0x61, 0x6c, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x30, 0x78, 0x25, +0x78, 0x0a, 0x00, 0x00, 0x4d, 0x41, 0x43, 0x2d, 0x43, 0x52, 0x20, 0x52, 0x45, 0x53, 0x54, 0x4f, +0x52, 0x45, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x45, 0x52, 0x52, 0x4f, +0x52, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, +0x73, 0x70, 0x61, 0x63, 0x65, 0x0a, 0x00, 0x00, 0x52, 0x46, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, +0x52, 0x25, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x2c, 0x20, 0x0a, 0x00, 0x49, 0x6e, 0x76, 0x61, +0x6c, 0x69, 0x64, 0x20, 0x4d, 0x43, 0x43, 0x49, 0x44, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x54, 0x58, 0x42, 0x46, 0x20, 0x72, 0x66, 0x20, +0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x45, 0x52, 0x52, 0x4f, +0x52, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x52, 0x46, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x73, +0x70, 0x61, 0x63, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x35, 0x47, 0x20, 0x65, 0x50, 0x41, 0x20, 0x6f, +0x6e, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, +0x61, 0x74, 0x65, 0x20, 0x54, 0x53, 0x53, 0x49, 0x0a, 0x00, 0x00, 0x00, 0x32, 0x47, 0x20, 0x65, +0x50, 0x41, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, +0x6c, 0x69, 0x62, 0x72, 0x61, 0x74, 0x65, 0x20, 0x54, 0x53, 0x53, 0x49, 0x0a, 0x00, 0x00, 0x00, +0x52, 0x58, 0x49, 0x51, 0x20, 0x6d, 0x69, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x6d, 0x71, +0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x73, 0x69, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, +0x73, 0x71, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x72, 0x69, 0x71, 0x3d, 0x30, 0x78, 0x25, +0x78, 0x2c, 0x20, 0x62, 0x62, 0x70, 0x76, 0x61, 0x6c, 0x3d, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, +0x4c, 0x4e, 0x41, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x5b, 0x47, 0x5f, 0x69, 0x6d, 0x62, 0x3d, 0x30, +0x78, 0x25, 0x32, 0x78, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x50, 0x68, 0x5f, 0x72, 0x78, 0x3d, +0x30, 0x78, 0x25, 0x32, 0x78, 0x28, 0x25, 0x64, 0x29, 0x5d, 0x0a, 0x00, 0x20, 0x4c, 0x43, 0x2d, +0x54, 0x61, 0x6e, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x42, 0x42, 0x50, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, +0x37, 0x34, 0x5d, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x28, 0x57, 0x46, 0x25, +0x64, 0x29, 0x2d, 0x43, 0x61, 0x6c, 0x20, 0x44, 0x6f, 0x6e, 0x65, 0x21, 0x21, 0x20, 0x42, 0x42, +0x50, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x37, 0x34, 0x5d, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x42, 0x57, 0x43, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x20, 0x57, 0x46, 0x20, 0x25, 0x64, 0x20, 0x2d, 0x2d, +0x2d, 0x0a, 0x00, 0x00, 0x52, 0x58, 0x31, 0x5f, 0x42, 0x57, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x30, +0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x32, 0x5f, 0x42, 0x57, 0x32, 0x30, +0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x31, 0x5f, +0x42, 0x57, 0x34, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x52, 0x58, 0x32, 0x5f, 0x42, 0x57, 0x34, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x31, 0x5f, 0x42, 0x57, 0x38, 0x30, 0x20, 0x3d, 0x20, 0x30, +0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x32, 0x5f, 0x42, 0x57, 0x38, 0x30, +0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x32, 0x34, +0x43, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x30, 0x78, 0x32, 0x35, 0x30, 0x20, 0x3d, 0x20, +0x25, 0x78, 0x0a, 0x00, 0x61, 0x70, 0x70, 0x50, 0x6b, 0x74, 0x43, 0x6d, 0x64, 0x5f, 0x49, 0x6e, +0x69, 0x74, 0x47, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x21, 0x0a, 0x00, 0x00, +0x66, 0x6f, 0x72, 0x63, 0x65, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x34, 0x34, 0x3d, 0x25, +0x78, 0x2c, 0x20, 0x30, 0x78, 0x34, 0x35, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x34, 0x39, +0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x34, 0x44, 0x3d, 0x25, 0x78, 0x21, 0x0a, 0x00, 0x00, +0x63, 0x68, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x3d, 0x25, 0x64, 0x2c, +0x20, 0x65, 0x66, 0x75, 0x73, 0x65, 0x47, 0x61, 0x69, 0x6e, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, +0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x3e, 0x20, 0x30, 0x78, 0x32, 0x33, +0x32, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, 0x34, 0x3d, 0x25, 0x78, +0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, +0x33, 0x31, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x38, 0x3d, 0x25, +0x78, 0x0a, 0x00, 0x00, 0x41, 0x66, 0x74, 0x65, 0x72, 0x3e, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, +0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, 0x34, 0x3d, 0x25, 0x78, 0x2c, +0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, +0x31, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x38, 0x3d, 0x25, 0x78, +0x0a, 0x00, 0x00, 0x00, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x3d, +0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2d, 0x42, 0x61, 0x6e, 0x64, 0x20, 0x65, +0x50, 0x41, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x65, 0x4c, 0x4e, 0x41, 0x3d, 0x25, 0x64, 0x0a, 0x00, +0x47, 0x2d, 0x42, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x65, +0x4c, 0x4e, 0x41, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x43, 0x52, 0x5b, 0x25, 0x78, 0x5d, 0x3d, 0x25, +0x78, 0x2c, 0x20, 0x5b, 0x25, 0x78, 0x5d, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x49, 0x6e, 0x76, 0x61, +0x6c, 0x69, 0x64, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, +0x54, 0x58, 0x2f, 0x52, 0x58, 0x20, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x0a, 0x00, 0x00, 0x00, +0x6d, 0x74, 0x37, 0x36, 0x36, 0x32, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5f, 0x63, 0x68, +0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3d, 0x20, 0x25, +0x64, 0x2c, 0x20, 0x73, 0x63, 0x61, 0x6e, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x42, 0x57, 0x3d, 0x25, +0x64, 0x2c, 0x20, 0x52, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3d, 0x25, 0x64, 0x2c, 0x20, +0x54, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x52, 0x20, 0x4c, 0x6f, 0x61, 0x64, 0x20, 0x28, 0x6d, 0x6f, 0x64, 0x65, 0x3d, 0x25, 0x64, +0x29, 0x20, 0x28, 0x74, 0x65, 0x6d, 0x70, 0x3d, 0x25, 0x64, 0x29, 0x20, 0x28, 0x63, 0x68, 0x61, +0x6e, 0x6e, 0x65, 0x6c, 0x3d, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x47, 0x20, 0x62, 0x61, +0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x49, 0x67, 0x6e, +0x6f, 0x72, 0x65, 0x20, 0x44, 0x50, 0x44, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x41, 0x20, 0x62, 0x61, +0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x49, 0x67, 0x6e, +0x6f, 0x72, 0x65, 0x20, 0x44, 0x50, 0x44, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x44, 0x50, 0x44, 0x20, +0x53, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x00, 0x00, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x20, 0x57, +0x46, 0x30, 0x20, 0x44, 0x50, 0x44, 0x3a, 0x74, 0x78, 0x41, 0x4c, 0x43, 0x5f, 0x72, 0x65, 0x71, +0x5f, 0x73, 0x61, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x54, 0x78, 0x30, 0x5f, 0x44, 0x50, 0x44, 0x5f, +0x41, 0x4c, 0x43, 0x5f, 0x55, 0x70, 0x5f, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x3d, 0x25, 0x64, 0x2c, +0x54, 0x78, 0x30, 0x5f, 0x44, 0x50, 0x44, 0x5f, 0x41, 0x4c, 0x43, 0x5f, 0x4c, 0x72, 0x5f, 0x4c, +0x69, 0x6d, 0x69, 0x74, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x59, 0x50, 0x41, +0x53, 0x53, 0x20, 0x57, 0x46, 0x31, 0x20, 0x44, 0x50, 0x44, 0x3a, 0x74, 0x78, 0x41, 0x4c, 0x43, +0x5f, 0x72, 0x65, 0x71, 0x5f, 0x73, 0x61, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x54, 0x78, 0x31, 0x5f, +0x44, 0x50, 0x44, 0x5f, 0x41, 0x4c, 0x43, 0x5f, 0x55, 0x70, 0x5f, 0x4c, 0x69, 0x6d, 0x69, 0x74, +0x3d, 0x25, 0x64, 0x2c, 0x54, 0x78, 0x31, 0x5f, 0x44, 0x50, 0x44, 0x5f, 0x41, 0x4c, 0x43, 0x5f, +0x4c, 0x72, 0x5f, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x28, 0x31, 0x29, 0x20, 0x30, 0x78, 0x31, 0x30, 0x45, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, +0x78, 0x31, 0x30, 0x45, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x30, +0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, +0x30, 0x78, 0x31, 0x30, 0x46, 0x38, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, +0x43, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x28, 0x32, 0x29, 0x20, 0x52, 0x65, 0x74, 0x75, +0x72, 0x6e, 0x0a, 0x00, 0x28, 0x33, 0x29, 0x20, 0x30, 0x78, 0x31, 0x30, 0x45, 0x30, 0x3d, 0x25, +0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x45, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, +0x31, 0x30, 0x46, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x34, 0x3d, +0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x38, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, +0x78, 0x31, 0x30, 0x46, 0x43, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x28, 0x34, 0x29, 0x20, +0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x00, 0x69, 0x64, 0x78, 0x3d, 0x25, 0x64, 0x2c, 0x20, +0x58, 0x59, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x41, 0x4d, 0x36, 0x33, 0x3d, 0x25, 0x64, 0x0a, 0x00, +0x69, 0x64, 0x78, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x58, 0x59, 0x5b, 0x5d, 0x3d, 0x25, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x44, 0x50, 0x44, 0x20, 0x43, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x21, 0x20, 0x28, 0x69, 0x64, 0x78, +0x3d, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x50, 0x44, 0x20, 0x43, 0x61, 0x6c, 0x69, +0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x21, 0x20, +0x28, 0x52, 0x65, 0x74, 0x72, 0x79, 0x20, 0x43, 0x6e, 0x74, 0x3d, 0x35, 0x29, 0x0a, 0x00, 0x00, +0x57, 0x46, 0x30, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x39, 0x38, 0x7e, 0x30, 0x78, 0x32, 0x37, +0x41, 0x34, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, +0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x20, 0x20, 0x20, 0x20, +0x57, 0x46, 0x31, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x43, 0x30, 0x7e, 0x30, 0x78, 0x32, 0x37, +0x43, 0x43, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, +0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x54, 0x58, 0x20, 0x49, 0x51, 0x43, 0x20, 0x43, 0x41, 0x4c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x35, 0x47, 0x20, 0x54, 0x58, 0x20, 0x4c, 0x4f, 0x46, 0x54, 0x0a, 0x00, +0x32, 0x47, 0x20, 0x54, 0x58, 0x20, 0x4c, 0x4f, 0x46, 0x54, 0x0a, 0x00, 0x57, 0x46, 0x30, 0x20, +0x5b, 0x30, 0x78, 0x32, 0x37, 0x38, 0x30, 0x7e, 0x30, 0x78, 0x32, 0x37, 0x39, 0x34, 0x5d, 0x0a, +0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, +0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x57, 0x46, +0x31, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x41, 0x38, 0x7e, 0x30, 0x78, 0x32, 0x37, 0x42, 0x43, +0x5d, 0x0a, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, +0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x54, 0x58, 0x20, 0x4c, 0x4f, 0x46, 0x54, 0x20, 0x43, 0x41, 0x4c, 0x20, +0x64, 0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x69, 0x3d, 0x25, 0x64, 0x20, 0x46, 0x44, 0x49, +0x51, 0x20, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, +0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x3e, 0x20, +0x4b, 0x20, 0x49, 0x44, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x20, 0x3c, 0x2d, 0x2d, 0x0a, 0x00, 0x00, +0x3d, 0x3d, 0x3d, 0x20, 0x45, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4b, 0x20, 0x3d, 0x3d, 0x3d, +0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0x52, 0x00, 0x00, 0x00, +0x34, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0x52, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, +0x04, 0x20, 0x41, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, +0xd2, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0xda, 0x00, 0x00, 0x00, +0x39, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0xda, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, +0x00, 0x23, 0x41, 0x00, 0x08, 0x14, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, +0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x08, 0x34, 0x00, 0x00, +0x31, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x08, 0x14, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, +0x00, 0x23, 0x41, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, +0x08, 0x34, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x00, 0x74, 0x00, 0x00, +0x39, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x08, 0x74, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +0x04, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, +0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, +0x35, 0x00, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, +0x08, 0x23, 0x41, 0x00, 0x70, 0x70, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x08, 0x23, 0x41, 0x00, +0x70, 0x70, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x50, 0x9d, 0xe8, 0x15, +0x35, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x50, 0x9d, 0xe8, 0x15, 0x09, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x4e, 0x9b, 0xe7, 0x15, 0x39, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x4e, 0x9b, 0xe7, 0x15, 0x05, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x50, 0x9d, 0xe8, 0x15, +0x35, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x50, 0x9d, 0xe8, 0x15, 0x09, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x4e, 0x9b, 0xe7, 0x15, 0x39, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, +0x4e, 0x9b, 0xe7, 0x15, 0x09, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x02, 0x02, 0x00, 0x00, +0x39, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x42, 0x1e, 0x34, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5c, 0x42, 0x1e, 0x05, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, +0x35, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x09, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x58, 0x42, 0x1e, 0x39, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x58, 0x42, 0x1e, 0x04, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x42, 0x1e, +0x34, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x42, 0x1e, 0x05, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x35, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x42, 0x1e, 0x09, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x58, 0x42, 0x1e, +0x39, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x58, 0x42, 0x1e, 0x00, 0x00, 0x00, 0x00, +0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x08, 0x30, 0x00, 0x00, 0x00, 0x30, 0x23, 0x41, 0x00, +0xf3, 0x00, 0x05, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x07, +0x31, 0x00, 0x00, 0x00, 0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x07, 0x04, 0x00, 0x00, 0x00, +0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, 0x34, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, +0x08, 0x04, 0x0a, 0x04, 0x01, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x0b, 0x08, 0x0a, 0x04, +0x31, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x0b, 0x08, 0x0a, 0x04, 0x05, 0x00, 0x00, 0x00, +0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, 0x35, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, +0x08, 0x04, 0x0a, 0x04, 0x09, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x05, 0x03, 0x0a, 0x04, +0x39, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x05, 0x03, 0x0a, 0x04, 0x09, 0x00, 0x00, 0x00, +0x8c, 0x23, 0x41, 0x00, 0x14, 0x10, 0x10, 0x10, 0x39, 0x00, 0x00, 0x00, 0x8c, 0x23, 0x41, 0x00, +0x14, 0x10, 0x10, 0x10, 0x04, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x32, 0x23, 0x2e, 0x2e, +0x34, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x32, 0x23, 0x2e, 0x2e, 0x05, 0x00, 0x00, 0x00, +0xa4, 0x23, 0x41, 0x00, 0x32, 0x23, 0x2e, 0x2e, 0x35, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x32, 0x23, 0x2e, 0x2e, 0x09, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x26, 0x22, 0x1c, 0x1c, +0x39, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x26, 0x22, 0x1c, 0x1c, 0x09, 0x00, 0x00, 0x00, +0xac, 0x23, 0x41, 0x00, 0x17, 0x17, 0x16, 0x16, 0x39, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, +0x17, 0x17, 0x16, 0x16, 0x04, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, +0x34, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x00, 0x26, 0x41, 0x00, 0x80, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, +0x80, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x81, 0x00, 0x00, 0x00, +0x35, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x81, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, +0x00, 0x26, 0x41, 0x00, 0x82, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, +0x82, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x00, 0x03, 0x00, +0x34, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, +0x04, 0x26, 0x41, 0x00, 0x0b, 0x0f, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, +0x0b, 0x0f, 0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x2c, 0x01, 0x00, +0x35, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x2c, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, +0x04, 0x26, 0x41, 0x00, 0x0b, 0x3c, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, +0x0b, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x26, 0x41, 0x00, 0x87, 0x00, 0x10, 0x00, +0x34, 0x00, 0x00, 0x00, 0x0c, 0x26, 0x41, 0x00, 0x87, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, +0x14, 0x26, 0x41, 0x00, 0xf4, 0xa7, 0xab, 0x00, 0x31, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, +0xf4, 0xa7, 0xab, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, 0xf5, 0xa7, 0xab, 0x00, +0x35, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, 0xf5, 0xa7, 0xab, 0x00, 0x09, 0x00, 0x00, 0x00, +0x14, 0x26, 0x41, 0x00, 0xf6, 0xa7, 0xab, 0x00, 0x39, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, +0xf6, 0xa7, 0xab, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x0e, 0x00, +0x31, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x0e, 0x00, 0x05, 0x00, 0x00, 0x00, +0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x18, 0x00, 0x35, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, +0x00, 0x04, 0x18, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x20, 0x00, +0x39, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, +0x40, 0x29, 0x41, 0x00, 0x1e, 0x38, 0x00, 0x01, 0x31, 0x00, 0x00, 0x00, 0x40, 0x29, 0x41, 0x00, +0x1e, 0x38, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x40, 0x29, 0x41, 0x00, 0x1e, 0x38, 0x00, 0x01, +0x35, 0x00, 0x00, 0x00, 0x40, 0x29, 0x41, 0x00, 0x1e, 0x38, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, +0x48, 0x29, 0x41, 0x00, 0x91, 0xa9, 0x00, 0xf0, 0x39, 0x00, 0x00, 0x00, 0x48, 0x29, 0x41, 0x00, +0x91, 0xa9, 0x00, 0xf0, 0x09, 0x00, 0x00, 0x00, 0x4c, 0x29, 0x41, 0x00, 0xf9, 0x9f, 0xff, 0xf9, +0x39, 0x00, 0x00, 0x00, 0x4c, 0x29, 0x41, 0x00, 0xf9, 0x9f, 0xff, 0xf9, 0x04, 0x00, 0x00, 0x00, +0xac, 0x29, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xac, 0x29, 0x41, 0x00, +0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xac, 0x29, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, +0x35, 0x00, 0x00, 0x00, 0xac, 0x29, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x4e, 0xa5, 0xf3, 0x15, 0x30, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x4e, 0xa5, 0xf3, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x4e, 0xa4, 0xf3, 0x15, +0x34, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x4e, 0xa4, 0xf3, 0x15, 0x01, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x5b, 0xa6, 0xf3, 0x15, 0x31, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x5b, 0xa6, 0xf3, 0x15, 0x05, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, +0x35, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x09, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x39, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x5b, 0xa8, 0xf3, 0x15, 0x00, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x4e, 0xa5, 0xf3, 0x15, +0x30, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x4e, 0xa5, 0xf3, 0x15, 0x04, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x4e, 0xa4, 0xf3, 0x15, 0x34, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, +0x4e, 0xa4, 0xf3, 0x15, 0x01, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa6, 0xf3, 0x15, +0x31, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa6, 0xf3, 0x15, 0x05, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x35, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, +0x5b, 0xa8, 0xf3, 0x15, 0x09, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, +0x39, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x00, 0x00, 0x00, 0x00, +0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x10, 0x10, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, +0x34, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, +0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x31, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x10, 0x10, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, +0x35, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x09, 0x00, 0x00, 0x00, +0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x39, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x10, 0x10, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x0f, +0x30, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x0f, 0x04, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x34, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x48, 0x36, 0x18, 0x01, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x18, +0x31, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x18, 0x05, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x35, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x48, 0x36, 0x18, 0x09, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, +0x39, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x00, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x0f, 0x30, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x4a, 0x36, 0x0f, 0x04, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, +0x34, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x01, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x18, 0x31, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x4a, 0x36, 0x18, 0x05, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, +0x35, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x09, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x39, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x48, 0x36, 0x18, 0x01, 0x00, 0x00, 0x00, 0x68, 0x23, 0x41, 0x00, 0x04, 0x20, 0x7c, 0x00, +0x31, 0x00, 0x00, 0x00, 0x68, 0x23, 0x41, 0x00, 0x04, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x30, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, +0x96, 0x0e, 0x9e, 0xba, 0x04, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, +0x34, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x01, 0x00, 0x00, 0x00, +0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x31, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, +0x96, 0x0e, 0x9e, 0xba, 0x05, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, +0x35, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x09, 0x00, 0x00, 0x00, +0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x39, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, +0x96, 0x0e, 0x9e, 0xba, 0x01, 0x00, 0x00, 0x00, 0x45, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, +0x66, 0x66, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, +0x11, 0x11, 0x09, 0x00, 0x03, 0x00, 0x00, 0x00, 0x63, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, +0xbb, 0xbb, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 0x72, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, +0x66, 0x66, 0x0e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x81, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0x11, 0x11, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0xbb, 0xbb, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9f, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0x66, 0x66, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0xae, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0x11, 0x11, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0xbd, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0xbb, 0xbb, 0x0b, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xcc, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0x66, 0x66, 0x0e, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xdb, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0x11, 0x11, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xea, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0xbb, 0xbb, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf9, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0x66, 0x66, 0x06, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1d, 0x1d, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0xcc, 0xcc, 0x0c, 0x00, 0x22, 0x00, 0x00, 0x00, 0x4c, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x5b, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x63, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x6a, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x27, 0x00, 0x00, 0x00, 0x72, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x28, 0x00, 0x00, 0x00, 0x79, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x29, 0x00, 0x00, 0x00, 0x81, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x88, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x97, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x9f, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xa6, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x2f, 0x00, 0x00, 0x00, 0xae, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0xb5, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00, 0xbd, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xc4, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x33, 0x00, 0x00, 0x00, 0xcc, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x34, 0x00, 0x00, 0x00, 0xd3, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x35, 0x00, 0x00, 0x00, 0xdb, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x36, 0x00, 0x00, 0x00, 0xe2, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x37, 0x00, 0x00, 0x00, 0xea, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x38, 0x00, 0x00, 0x00, 0xf1, 0x1e, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0xf9, 0x1e, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x08, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x17, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x26, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2d, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x41, 0x00, 0x00, 0x00, 0x35, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x43, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4b, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x53, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x5a, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00, 0x62, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x48, 0x00, 0x00, 0x00, 0x69, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x49, 0x00, 0x00, 0x00, 0x71, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x78, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x87, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x8f, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x96, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x9e, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x50, 0x00, 0x00, 0x00, 0xa5, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0xad, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x52, 0x00, 0x00, 0x00, 0xb4, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x53, 0x00, 0x00, 0x00, 0xbc, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x54, 0x00, 0x00, 0x00, 0xc3, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x55, 0x00, 0x00, 0x00, 0xcb, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x56, 0x00, 0x00, 0x00, 0xd2, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x57, 0x00, 0x00, 0x00, 0xda, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x58, 0x00, 0x00, 0x00, 0xe1, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x59, 0x00, 0x00, 0x00, 0xe9, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x0e, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x16, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x1d, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, 0x25, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x61, 0x00, 0x00, 0x00, 0x2c, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x62, 0x00, 0x00, 0x00, 0x34, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x63, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3b, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x66, 0x00, 0x00, 0x00, 0x4a, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x67, 0x00, 0x00, 0x00, 0x52, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x68, 0x00, 0x00, 0x00, 0x59, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x68, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x70, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x77, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x7f, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x86, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x8e, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x70, 0x00, 0x00, 0x00, 0x95, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x71, 0x00, 0x00, 0x00, 0x9d, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x72, 0x00, 0x00, 0x00, 0xa4, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x73, 0x00, 0x00, 0x00, 0xac, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x74, 0x00, 0x00, 0x00, 0xb3, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0xbb, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x76, 0x00, 0x00, 0x00, 0xc2, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x77, 0x00, 0x00, 0x00, 0xca, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x78, 0x00, 0x00, 0x00, 0xd1, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x79, 0x00, 0x00, 0x00, 0xd9, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x7a, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x7b, 0x00, 0x00, 0x00, 0xe8, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xef, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xf7, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0d, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x15, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x82, 0x00, 0x00, 0x00, 0x1c, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x83, 0x00, 0x00, 0x00, 0x24, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x84, 0x00, 0x00, 0x00, 0x2b, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x85, 0x00, 0x00, 0x00, 0x33, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x86, 0x00, 0x00, 0x00, 0x3a, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x87, 0x00, 0x00, 0x00, 0x42, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x88, 0x00, 0x00, 0x00, 0x49, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x89, 0x00, 0x00, 0x00, 0x51, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x58, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x60, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x67, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x6f, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x76, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x7e, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x90, 0x00, 0x00, 0x00, 0x85, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x91, 0x00, 0x00, 0x00, 0x8d, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x92, 0x00, 0x00, 0x00, 0x94, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x93, 0x00, 0x00, 0x00, 0x9c, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0x94, 0x00, 0x00, 0x00, 0xa3, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x95, 0x00, 0x00, 0x00, 0xab, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x96, 0x00, 0x00, 0x00, 0xb2, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0x97, 0x00, 0x00, 0x00, 0xba, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0x98, 0x00, 0x00, 0x00, 0xc1, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0xc9, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0x9a, 0x00, 0x00, 0x00, 0xd0, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xd8, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0x9c, 0x00, 0x00, 0x00, 0xdf, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xe7, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xee, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xf6, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xfd, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x05, 0x22, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x0c, 0x22, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x55, 0x55, 0x0d, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x14, 0x22, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x1b, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x23, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x32, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x41, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0xab, 0x00, 0x00, 0x00, 0x50, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, +0x55, 0x55, 0x09, 0x00, 0xad, 0x00, 0x00, 0x00, 0x5f, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xce, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0e, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xd5, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xdd, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0x55, 0x55, 0x01, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xec, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xf3, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xfb, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x06, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x11, 0x1d, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x2f, 0x1d, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x4d, 0x1d, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x6b, 0x1d, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x89, 0x1d, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xa7, 0x1d, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, +0x55, 0x55, 0x05, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xc5, 0x1d, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, +0xaa, 0xaa, 0x0a, 0x00, 0x01, 0x00, 0xb7, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x77, 0x77, 0x55, 0x33, +0x8f, 0xaa, 0x11, 0x66, 0x10, 0x1f, 0x1f, 0x3f, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, +0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x9c, 0x0f, 0x05, 0x07, 0x00, 0x00, 0x77, 0x77, 0x44, 0x33, +0x8f, 0xaa, 0x33, 0x66, 0x00, 0xf3, 0x33, 0x03, 0x02, 0x00, 0xc8, 0x00, 0xd8, 0x00, 0x00, 0x00, +0x77, 0x77, 0x55, 0x33, 0x8f, 0xaa, 0x11, 0x66, 0x10, 0x1f, 0x1f, 0x3f, 0x17, 0x00, 0x00, 0x00, +0x17, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x9c, 0x0f, 0x05, 0x07, 0x00, 0x00, +0x77, 0x77, 0x44, 0x22, 0x8f, 0xaa, 0x33, 0xaa, 0x00, 0xf3, 0x33, 0x03, 0x03, 0x00, 0x20, 0x00, +0x32, 0x00, 0x00, 0x00, 0x77, 0x77, 0x45, 0x33, 0x8f, 0xaa, 0x11, 0x66, 0x10, 0x1f, 0x1f, 0x3f, +0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x9c, 0x0f, +0x05, 0x07, 0x00, 0x00, 0x77, 0x77, 0x33, 0x22, 0x8f, 0xaa, 0x66, 0xaa, 0x00, 0xf3, 0x33, 0x03, +0x04, 0x00, 0x34, 0x00, 0x44, 0x00, 0x00, 0x00, 0x77, 0x77, 0x44, 0x33, 0x8f, 0xaa, 0x33, 0x66, +0x10, 0x1f, 0x1f, 0x3f, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, +0x00, 0x60, 0x9c, 0x0f, 0x05, 0x07, 0x00, 0x00, 0x77, 0x77, 0x33, 0x21, 0x8f, 0xaa, 0x66, 0xaf, +0x00, 0xf3, 0x33, 0x03, 0x05, 0x00, 0x64, 0x00, 0x74, 0x00, 0x00, 0x00, 0x77, 0x57, 0x44, 0x33, +0x8f, 0xaa, 0x33, 0x66, 0x10, 0x10, 0x10, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, +0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x7c, 0x2f, 0x05, 0x07, 0x00, 0x00, 0x65, 0x46, 0x22, 0x21, +0x8f, 0xaa, 0xaa, 0xaf, 0x00, 0xf3, 0x03, 0x03, 0x06, 0x00, 0x78, 0x00, 0x90, 0x00, 0x00, 0x00, +0x77, 0x46, 0x33, 0x33, 0x8f, 0xaa, 0x66, 0x66, 0x10, 0x0f, 0x0f, 0x3f, 0x13, 0x00, 0x00, 0x00, +0x13, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x7c, 0x2b, 0x05, 0x07, 0x00, 0x00, +0x64, 0x35, 0x22, 0x10, 0x8f, 0xaa, 0xaa, 0xff, 0x00, 0x83, 0xf3, 0x02, 0x07, 0x00, 0x95, 0x00, +0xa5, 0x00, 0x00, 0x00, 0x65, 0x34, 0x33, 0x33, 0x8f, 0xaa, 0x66, 0x66, 0x10, 0x0f, 0x0f, 0x3f, +0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x7c, 0x2b, +0x05, 0x07, 0x00, 0x00, 0x32, 0x03, 0x22, 0x10, 0x8f, 0xaa, 0xaa, 0xff, 0x00, 0x83, 0xf3, 0x02, +0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x47, 0x10, 0x09, 0x00, 0x0c, 0x00, 0x47, 0x30, 0xc7, 0x11, +0x09, 0x00, 0x10, 0x00, 0x47, 0x10, 0x00, 0x00, 0x09, 0x00, 0x9c, 0x02, 0x10, 0x10, 0x10, 0x3f, +0x09, 0x00, 0x6c, 0x02, 0x57, 0x77, 0x50, 0x00, 0x00, 0x00, 0xa4, 0x02, 0x5f, 0x77, 0x2a, 0x25, +0x00, 0x00, 0x54, 0x01, 0xa1, 0x1e, 0xf6, 0xac, 0x00, 0x00, 0x48, 0x01, 0x00, 0x7c, 0x72, 0xa9, +0x00, 0x00, 0x08, 0x03, 0x00, 0x7c, 0x72, 0xa9, 0x00, 0x00, 0x58, 0x00, 0x00, 0x60, 0x7c, 0x2f, +0x01, 0x00, 0xa4, 0x02, 0x7e, 0x77, 0x2a, 0x26, 0x09, 0x00, 0x34, 0x01, 0x80, 0x38, 0x04, 0x20, +0x01, 0x00, 0x20, 0x03, 0x83, 0x68, 0x88, 0x04, 0x09, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, +0x04, 0x2f, 0x41, 0x00, 0x01, 0x22, 0x00, 0x80, 0x0c, 0x2f, 0x41, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, +0x10, 0x2f, 0x41, 0x00, 0xee, 0xff, 0x00, 0x00, 0xd8, 0x2f, 0x41, 0x00, 0x00, 0x01, 0x00, 0x00, +0x04, 0x20, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x20, 0x41, 0x00, 0x00, 0x00, 0x03, 0x00, +0x0c, 0x20, 0x41, 0x00, 0x0a, 0x03, 0x00, 0x03, 0x2c, 0x21, 0x41, 0x00, 0x01, 0x80, 0xde, 0x0f, +0x00, 0x23, 0x41, 0x00, 0x00, 0x14, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, 0x01, 0x00, 0x00, 0x00, +0x08, 0x23, 0x41, 0x00, 0x14, 0x14, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x44, 0x95, 0xe7, 0x15, +0x14, 0x23, 0x41, 0x00, 0x44, 0x95, 0xe7, 0x15, 0x18, 0x23, 0x41, 0x00, 0x40, 0x40, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x5e, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5e, 0x36, 0x18, +0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x05, 0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, +0x38, 0x23, 0x41, 0x00, 0x38, 0x20, 0x0f, 0x11, 0x5c, 0x23, 0x41, 0x00, 0x2c, 0x27, 0x00, 0x00, +0x64, 0x23, 0x41, 0x00, 0x00, 0x00, 0x00, 0x80, 0x68, 0x23, 0x41, 0x00, 0x05, 0x20, 0x7c, 0x00, +0x6c, 0x23, 0x41, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, 0x23, 0x41, 0x00, 0x00, 0x08, 0x00, 0x00, +0x78, 0x23, 0x41, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, 0xe3, 0x0f, 0x00, 0x00, +0x84, 0x23, 0x41, 0x00, 0x70, 0x70, 0x00, 0x00, 0x8c, 0x23, 0x41, 0x00, 0x16, 0x15, 0x11, 0x11, +0x9c, 0x23, 0x41, 0x00, 0x45, 0x3e, 0x38, 0x38, 0xa4, 0x23, 0x41, 0x00, 0x2e, 0x2a, 0x2a, 0x2a, +0xac, 0x23, 0x41, 0x00, 0x30, 0x2b, 0x26, 0x26, 0xcc, 0x23, 0x41, 0x00, 0x1c, 0x1c, 0x16, 0x16, +0xd4, 0x23, 0x41, 0x00, 0x2f, 0x2a, 0x26, 0x26, 0xdc, 0x23, 0x41, 0x00, 0x66, 0x54, 0x40, 0x40, +0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0xa2, 0xba, 0x00, 0x24, 0x41, 0x00, 0x03, 0x04, 0xe9, 0x02, +0x08, 0x24, 0x41, 0x00, 0xaa, 0x55, 0x00, 0x00, 0x04, 0x25, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x00, +0x14, 0x25, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x25, 0x41, 0x00, 0x80, 0x00, 0x00, 0x00, +0x00, 0x26, 0x41, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x06, 0x06, 0x00, +0x0c, 0x26, 0x41, 0x00, 0x07, 0x00, 0x10, 0x00, 0x10, 0x26, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, +0x14, 0x26, 0x41, 0x00, 0xf4, 0x03, 0xc0, 0x00, 0x18, 0x26, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x26, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x26, 0x41, 0x00, 0x73, 0x77, 0x77, 0x00, +0x00, 0x27, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x27, 0x41, 0x00, 0x00, 0x00, 0x04, 0x01, +0x10, 0x27, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x27, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, +0x20, 0x27, 0x41, 0x00, 0x14, 0x00, 0x00, 0x80, 0x40, 0x27, 0x41, 0x00, 0x04, 0x00, 0x00, 0x00, +0x04, 0x25, 0x41, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x25, 0x41, 0x00, 0xec, 0xc4, 0x77, 0xf9, +0x00, 0x28, 0x41, 0x00, 0xe0, 0x00, 0x50, 0x3d, 0x34, 0x29, 0x41, 0x00, 0x92, 0x04, 0x00, 0x00, +0x38, 0x29, 0x41, 0x00, 0x11, 0x04, 0x56, 0x00, 0x3c, 0x29, 0x41, 0x00, 0x1c, 0x1b, 0xf2, 0xc8, +0x40, 0x29, 0x41, 0x00, 0x1e, 0x58, 0x00, 0x00, 0x44, 0x29, 0x41, 0x00, 0x20, 0x40, 0x07, 0x00, +0x48, 0x29, 0x41, 0x00, 0x91, 0xa9, 0x00, 0xc0, 0x4c, 0x29, 0x41, 0x00, 0xf9, 0x9f, 0xff, 0xb9, +0x50, 0x29, 0x41, 0x00, 0x6f, 0x00, 0x40, 0x26, 0x60, 0x29, 0x41, 0x00, 0x16, 0x00, 0x00, 0x00, +0x64, 0x29, 0x41, 0x00, 0x30, 0xf0, 0x8f, 0x89, 0x88, 0x29, 0x41, 0x00, 0x44, 0x44, 0x01, 0x00, +0x94, 0x29, 0x41, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xac, 0x29, 0x41, 0x00, 0x28, 0x00, 0x00, 0x00, +0xd4, 0x29, 0x41, 0x00, 0x00, 0x8a, 0x00, 0x00, 0xf0, 0x29, 0x41, 0x00, 0x00, 0x00, 0x02, 0x00, +0x50, 0x2c, 0x41, 0x00, 0x03, 0x00, 0x00, 0x00, 0xc4, 0x2c, 0x41, 0x00, 0x07, 0x4f, 0x03, 0x00, +0x08, 0x23, 0x41, 0x00, 0x18, 0x18, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x4f, 0x9d, 0xe8, 0x15, +0x14, 0x23, 0x41, 0x00, 0x4f, 0x9d, 0xe8, 0x15, 0x18, 0x23, 0x41, 0x00, 0x04, 0x04, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x36, 0x18, +0x38, 0x23, 0x41, 0x00, 0x38, 0x02, 0x0f, 0x11, 0x78, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, +0x7c, 0x23, 0x41, 0x00, 0xf3, 0x0f, 0x00, 0x00, 0x84, 0x23, 0x41, 0x00, 0x78, 0x78, 0x00, 0x00, +0x8c, 0x23, 0x41, 0x00, 0x16, 0x11, 0x11, 0x11, 0xcc, 0x23, 0x41, 0x00, 0xff, 0xff, 0xff, 0xff, +0xd4, 0x23, 0x41, 0x00, 0xff, 0xff, 0xff, 0xff, 0xdc, 0x23, 0x41, 0x00, 0xff, 0xff, 0xff, 0xff, +0x08, 0x24, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x00, +0x14, 0x25, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x26, 0x41, 0x00, 0x08, 0x00, 0x04, 0x00, +0x10, 0x26, 0x41, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x26, 0x41, 0x00, 0x70, 0x00, 0x00, 0x00, +0x44, 0x29, 0x41, 0x00, 0x21, 0x40, 0x07, 0x00, 0xd4, 0x29, 0x41, 0x00, 0x00, 0x0a, 0x00, 0x00, +0x10, 0x27, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x28, 0x41, 0x00, 0xe0, 0x00, 0x50, 0x89, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x88, 0x90, 0x98, 0x9a, 0x9c, 0x9e, 0xb8, 0xba, 0xbc, 0xbe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, +0x44, 0x55, 0x00, 0x00, 0xa8, 0xa8, 0x88, 0x00, 0xa0, 0xa0, 0x99, 0x00, 0x98, 0x98, 0xaa, 0x00, +0x90, 0x90, 0xbb, 0x00, 0x8b, 0x8b, 0xbb, 0x00, 0x87, 0x87, 0xbb, 0x00, 0x06, 0x06, 0x00, 0x00, +0x09, 0x09, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0c, 0x0c, 0x00, 0x00, 0x27, 0x00, 0x25, 0x00, 0x65, 0x00, 0xe5, 0x00, 0xe5, 0x00, 0xe5, 0x00, +0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x06, 0x00, 0x00, +0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x05, 0x07, 0x06, 0x00, 0x07, 0x07, 0x00, 0x00, +0x07, 0x07, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, +0x08, 0x08, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x06, 0x0d, 0x0c, 0x08, 0x07, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, +0x08, 0x08, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x06, 0x08, 0x07, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, +0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, +0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0c, 0x0c, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, +0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x08, 0x07, 0x06, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, 0x00, +0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, +0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x20, 0x00, 0x54, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x6e, 0x20, +0x54, 0x44, 0x44, 0x2e, 0x2e, 0x2e, 0x0a, 0x00, 0x54, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x66, 0x66, +0x20, 0x54, 0x44, 0x44, 0x2e, 0x2e, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x48, 0x57, 0x20, 0x41, +0x55, 0x54, 0x4f, 0x20, 0x4d, 0x4f, 0x44, 0x45, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x2c, 0x20, 0x63, +0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x28, 0x25, 0x64, 0x29, +0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x48, 0x57, 0x20, 0x41, 0x55, 0x54, 0x4f, 0x20, 0x4d, 0x4f, 0x44, 0x45, 0x20, 0x66, 0x61, 0x69, +0x6c, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x72, 0x65, 0x61, 0x72, 0x28, +0x25, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x21, 0x0a, 0x00, +0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x48, 0x57, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, +0x6b, 0x69, 0x63, 0x6b, 0x20, 0x5b, 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5d, 0x20, 0x50, 0x46, 0x20, +0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, +0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x29, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x53, 0x65, 0x74, 0x74, +0x69, 0x6e, 0x67, 0x20, 0x48, 0x57, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6b, 0x69, 0x63, 0x6b, +0x20, 0x5b, 0x52, 0x45, 0x41, 0x52, 0x5d, 0x20, 0x50, 0x46, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, +0x64, 0x20, 0x28, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, +0x79, 0x29, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5b, 0x25, +0x64, 0x5d, 0x3a, 0x20, 0x20, 0x50, 0x46, 0x28, 0x25, 0x64, 0x29, 0x20, 0x2c, 0x20, 0x61, 0x6e, +0x64, 0x20, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x2e, 0x2e, 0x0a, 0x00, 0x00, 0x00, +0x43, 0x54, 0x53, 0x00, 0x43, 0x46, 0x2d, 0x45, 0x6e, 0x64, 0x00, 0x00, 0x50, 0x53, 0x30, 0x00, +0x50, 0x53, 0x31, 0x00, 0x20, 0x49, 0x4e, 0x46, 0x5b, 0x25, 0x64, 0x5d, 0x3a, 0x20, 0x54, 0x72, +0x69, 0x67, 0x67, 0x65, 0x72, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x28, +0x25, 0x64, 0x29, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3a, +0x20, 0x25, 0x73, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x66, 0x20, +0x28, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, +0x74, 0x5f, 0x63, 0x74, 0x73, 0x20, 0x28, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x29, 0x0a, 0x00, +0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x48, 0x57, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6b, +0x69, 0x63, 0x6b, 0x20, 0x5b, 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5d, 0x20, 0x50, 0x46, 0x20, 0x66, +0x61, 0x69, 0x6c, 0x65, 0x64, 0x2e, 0x0a, 0x00, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x48, +0x57, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, 0x5b, 0x52, 0x45, 0x41, +0x52, 0x5d, 0x20, 0x50, 0x46, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2e, 0x0a, 0x00, 0x00, +0x25, 0x73, 0x3a, 0x20, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72, 0x69, 0x67, +0x67, 0x65, 0x72, 0x20, 0x6e, 0x75, 0x6d, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, +0x20, 0x57, 0x46, 0x20, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x20, 0x73, 0x74, +0x6f, 0x70, 0x65, 0x64, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00, 0x00, 0x57, 0x69, 0x46, 0x69, +0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x20, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, +0x67, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x21, 0x0a, 0x00, 0x00, 0x00, +0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x57, 0x49, 0x46, 0x49, 0x20, 0x73, 0x74, 0x61, +0x74, 0x75, 0x73, 0x3a, 0x20, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x28, 0x30, 0x78, 0x25, 0x78, +0x29, 0x0a, 0x00, 0x00, 0x57, 0x4c, 0x3d, 0x3e, 0x57, 0x4d, 0x54, 0x3a, 0x20, 0x30, 0x78, 0x25, +0x78, 0x0a, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x57, +0x46, 0x20, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, +0x0a, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x77, 0x69, 0x66, 0x69, +0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x29, 0x0a, 0x00, 0x3e, 0x3e, 0x3e, 0x20, +0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x57, 0x69, 0x66, 0x69, 0x20, 0x42, 0x53, 0x53, 0x5b, +0x25, 0x64, 0x5d, 0x3a, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5b, 0x30, 0x78, 0x25, 0x78, +0x5d, 0x0a, 0x00, 0x00, 0x53, 0x65, 0x74, 0x20, 0x69, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x5b, +0x25, 0x64, 0x5d, 0x3d, 0x31, 0x0a, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x20, 0x53, +0x63, 0x61, 0x6e, 0x5b, 0x25, 0x64, 0x5d, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x42, 0x57, 0x32, 0x30, +0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x42, 0x57, 0x34, 0x30, 0x5b, 0x25, 0x64, 0x5d, +0x0a, 0x00, 0x00, 0x00, 0x42, 0x57, 0x38, 0x30, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, +0x53, 0x43, 0x41, 0x4e, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x4f, 0x4e, 0x4e, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, +0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x53, 0x54, 0x41, 0x5b, 0x25, 0x64, 0x5d, +0x0a, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x41, 0x50, 0x5b, +0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, +0x20, 0x47, 0x43, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, +0x6f, 0x64, 0x65, 0x3a, 0x20, 0x47, 0x4f, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x42, 0x54, 0x33, 0x5b, 0x25, 0x64, 0x5d, +0x0a, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x41, 0x44, 0x48, +0x4f, 0x43, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x3d, 0x3d, 0x3d, 0x3e, 0x20, 0x66, 0x69, 0x6e, +0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x53, 0x43, 0x4f, 0x00, 0x41, 0x32, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, +0x43, 0x6f, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x48, 0x49, 0x44, 0x00, 0x50, 0x41, 0x47, 0x65, +0x00, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x49, 0x4e, 0x51, 0x52, +0x59, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x5b, 0x42, 0x54, 0x20, 0x25, 0x73, 0x5d, +0x3a, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x77, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, +0x43, 0x54, 0x53, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x25, 0x64, 0x29, 0x20, 0x3c, +0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x6e, 0x6f, 0x74, +0x69, 0x66, 0x79, 0x20, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x20, 0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, +0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x20, 0x54, 0x44, 0x44, 0x20, +0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x6e, 0x6f, 0x74, +0x69, 0x66, 0x79, 0x20, 0x46, 0x44, 0x44, 0x20, 0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x62, 0x63, 0x6e, 0x20, 0x74, 0x78, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x2e, +0x2e, 0x0a, 0x00, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x42, 0x46, 0x20, +0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, +0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x30, +0x78, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, +0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x66, 0x2f, +0x70, 0x62, 0x66, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xac, 0x00, 0xaa, 0xaa, 0x03, 0x00, +0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, +0x88, 0x8e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x43, 0x94, 0xe5, 0x15, 0x14, 0x23, 0x41, 0x00, +0x43, 0x94, 0xe5, 0x15, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5e, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5e, 0x42, 0x1e, 0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0d, 0x04, 0x38, 0x23, 0x41, 0x00, +0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, +0x30, 0x2b, 0x26, 0x26, 0xcc, 0x23, 0x41, 0x00, 0x1c, 0x1c, 0x15, 0x15, 0x10, 0x23, 0x41, 0x00, +0x43, 0x94, 0xe5, 0x15, 0x14, 0x23, 0x41, 0x00, 0x43, 0x94, 0xe5, 0x15, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x60, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x60, 0x42, 0x1e, 0x34, 0x23, 0x41, 0x00, +0x0f, 0x04, 0x0d, 0x04, 0x38, 0x23, 0x41, 0x00, 0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, +0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, 0x30, 0x2b, 0x26, 0x26, 0xcc, 0x23, 0x41, 0x00, +0x1c, 0x1c, 0x15, 0x15, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x36, 0x18, 0x34, 0x23, 0x41, 0x00, 0x0a, 0x04, 0x0a, 0x04, 0x38, 0x23, 0x41, 0x00, +0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, +0x28, 0x23, 0x1e, 0x1e, 0xcc, 0x23, 0x41, 0x00, 0x1c, 0x1c, 0x15, 0x15, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5c, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x36, 0x18, 0x34, 0x23, 0x41, 0x00, +0x0d, 0x08, 0x0a, 0x04, 0x38, 0x23, 0x41, 0x00, 0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, +0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, 0x28, 0x23, 0x1e, 0x1e, 0xcc, 0x23, 0x41, 0x00, +0x1c, 0x1c, 0x15, 0x15, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x42, 0x1e, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x68, 0x23, 0x41, 0x00, +0x05, 0x20, 0x7c, 0x00, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x28, 0x24, 0x24, 0x24, 0xac, 0x23, 0x41, 0x00, 0x30, 0x2b, 0x26, 0x26, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x36, 0x18, 0x34, 0x23, 0x41, 0x00, +0x0a, 0x08, 0x0a, 0x04, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, +0xf3, 0x0f, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x21, 0x1d, 0x1d, 0x1d, 0xac, 0x23, 0x41, 0x00, +0x28, 0x23, 0x1e, 0x1e, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x68, 0x23, 0x41, 0x00, +0x06, 0x20, 0x7c, 0x00, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x32, 0x2e, 0x2e, 0x2e, 0xac, 0x23, 0x41, 0x00, 0x2a, 0x1c, 0x20, 0x20, 0x34, 0x23, 0x41, 0x00, +0x0b, 0x08, 0x0a, 0x04, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, +0xd3, 0x0f, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x21, 0x1d, 0x1d, 0x1d, 0xac, 0x23, 0x41, 0x00, +0x30, 0x2b, 0x26, 0x26, 0x09, 0x00, 0x54, 0x00, 0x00, 0x3a, 0x7a, 0x29, 0x09, 0x00, 0x58, 0x00, +0x00, 0x60, 0x6c, 0x22, 0x09, 0x00, 0x94, 0x02, 0xe3, 0x03, 0xe1, 0x03, 0x09, 0x00, 0x98, 0x02, +0x00, 0x03, 0x03, 0x03, 0x09, 0x00, 0x9c, 0x02, 0x10, 0x1f, 0x1f, 0x2e, 0x09, 0x00, 0x7c, 0x02, +0x27, 0x00, 0x25, 0x00, 0x09, 0x00, 0x80, 0x02, 0x24, 0x00, 0x67, 0x00, 0x09, 0x00, 0x84, 0x02, +0x65, 0x00, 0x64, 0x00, 0x09, 0x00, 0x88, 0x02, 0xe7, 0x00, 0xe5, 0x00, 0x09, 0x00, 0x8c, 0x02, +0xe4, 0x00, 0xe7, 0x03, 0x09, 0x00, 0x90, 0x02, 0xe5, 0x03, 0xe4, 0x03, 0x09, 0x00, 0x3c, 0x00, +0xc5, 0x59, 0xb5, 0x05, 0x09, 0x00, 0xa0, 0x02, 0x14, 0x14, 0x1a, 0xdc, 0x00, 0x00, 0xa4, 0x02, +0x7f, 0x47, 0x20, 0x20, 0x01, 0x00, 0xa4, 0x02, 0x7f, 0x47, 0x20, 0x20, 0x09, 0x00, 0xa8, 0x02, +0x28, 0xee, 0x0e, 0x00, 0x09, 0x00, 0x5c, 0x00, 0xa1, 0x0a, 0xb4, 0x14, 0x09, 0x00, 0x44, 0x00, +0x16, 0x20, 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662_rom_patch.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662_rom_patch.h new file mode 100644 index 000000000..cb1c0fdf2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662_rom_patch.h @@ -0,0 +1,1652 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR mt7662_rom_patch[] = { +0x32, 0x30, 0x31, 0x34, 0x31, 0x31, 0x31, 0x35, 0x30, 0x36, 0x30, 0x36, 0x30, 0x36, 0x61, 0x0a, +0x41, 0x4c, 0x50, 0x53, 0x8a, 0x10, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x10, 0xd8, 0x48, 0xff, 0xff, +0xff, 0xff, 0x3f, 0x1f, 0x00, 0x00, 0x20, 0x48, 0x00, 0x00, 0x58, 0x1d, 0x00, 0x00, 0x0c, 0x83, +0x05, 0x00, 0xc0, 0xee, 0x03, 0x00, 0xd8, 0x78, 0x02, 0x00, 0x58, 0xf9, 0x04, 0x00, 0x9c, 0xda, +0x02, 0x00, 0x70, 0xfe, 0x04, 0x00, 0xf4, 0x64, 0x02, 0x00, 0xb8, 0xe6, 0x03, 0x00, 0x48, 0xf9, +0x00, 0x00, 0xf0, 0x82, 0x05, 0x00, 0x88, 0xce, 0x03, 0x00, 0x50, 0x20, 0x01, 0x00, 0xcc, 0x95, +0x04, 0x00, 0xec, 0x9e, 0x04, 0x00, 0xa8, 0x65, 0x05, 0x00, 0x48, 0xbe, 0x03, 0x00, 0x8c, 0x8b, +0x05, 0x00, 0x4c, 0x87, 0x05, 0x00, 0x9c, 0x1e, 0x04, 0x00, 0x48, 0x83, 0x05, 0x00, 0x68, 0xcd, +0x00, 0x00, 0x7c, 0x8b, 0x03, 0x00, 0x78, 0x8c, 0x03, 0x00, 0xc8, 0x93, 0x03, 0x00, 0xa8, 0x4a, +0x02, 0x00, 0xac, 0x34, 0x05, 0x00, 0xe0, 0x74, 0x00, 0x00, 0xc0, 0x72, 0x00, 0x00, 0x14, 0x40, +0x02, 0x00, 0xf4, 0x38, 0x00, 0x00, 0xd8, 0x31, 0x05, 0x00, 0x18, 0x50, 0x05, 0x00, 0x3c, 0xf8, +0x00, 0x00, 0x78, 0xc5, 0x01, 0x00, 0xcc, 0xf1, 0x00, 0x00, 0xfc, 0x81, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcc, 0x03, 0x00, 0x90, 0xc5, 0x03, 0x00, 0x48, 0xba, +0x03, 0x00, 0xfc, 0xa1, 0x03, 0x00, 0x68, 0xdb, 0x03, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2e, 0x09, 0x00, 0x0c, 0x05, 0x09, 0x00, 0xcc, 0x07, +0x09, 0x00, 0x2c, 0x08, 0x09, 0x00, 0xf8, 0x43, 0x09, 0x00, 0x78, 0x5f, 0x09, 0x00, 0x54, 0x42, +0x09, 0x00, 0xc8, 0x40, 0x09, 0x00, 0x24, 0x40, 0x09, 0x00, 0xf4, 0x3b, 0x09, 0x00, 0x1c, 0x4d, +0x09, 0x00, 0x20, 0x09, 0x09, 0x00, 0x3c, 0x5c, 0x09, 0x00, 0x58, 0x39, 0x09, 0x00, 0x14, 0x39, +0x09, 0x00, 0x98, 0x15, 0x09, 0x00, 0xa4, 0x34, 0x09, 0x00, 0x0c, 0x33, 0x09, 0x00, 0x30, 0x32, +0x09, 0x00, 0x14, 0x29, 0x09, 0x00, 0x68, 0x0a, 0x09, 0x00, 0x80, 0x0b, 0x09, 0x00, 0xc0, 0x53, +0x09, 0x00, 0xcc, 0x61, 0x09, 0x00, 0x28, 0x62, 0x09, 0x00, 0x3c, 0x55, 0x09, 0x00, 0xec, 0x1f, +0x09, 0x00, 0x90, 0x1e, 0x09, 0x00, 0x44, 0x1e, 0x09, 0x00, 0x0c, 0x1e, 0x09, 0x00, 0x64, 0x0e, +0x09, 0x00, 0xa8, 0x1c, 0x09, 0x00, 0x30, 0x1b, 0x09, 0x00, 0x2c, 0x0f, 0x09, 0x00, 0xc8, 0x1a, +0x09, 0x00, 0xfc, 0x18, 0x09, 0x00, 0x38, 0x15, 0x09, 0x00, 0x34, 0x14, 0x09, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x09, 0x00, 0x8c, 0x18, 0x09, 0x00, 0xc0, 0x16, +0x09, 0x00, 0x5c, 0x11, 0x09, 0x00, 0xc8, 0x0f, 0x09, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x01, 0x18, 0x20, 0x80, 0x01, 0x08, 0x20, +0x00, 0x01, 0x18, 0x20, 0x80, 0x01, 0x08, 0x20, 0x00, 0x01, 0x18, 0x20, 0x80, 0x01, 0x08, 0x20, +0x00, 0x01, 0x18, 0x20, 0x80, 0x01, 0xa6, 0x80, 0xae, 0x88, 0xa6, 0x01, 0xae, 0x09, 0xdd, 0x9e, +0x92, 0x00, 0x3e, 0x09, 0xf5, 0x58, 0x46, 0x10, 0x00, 0x96, 0x58, 0x10, 0x86, 0x0c, 0x3e, 0x29, +0xf6, 0x1c, 0xd5, 0x03, 0xa2, 0xc9, 0xaa, 0xc1, 0xe2, 0x02, 0xe9, 0xfd, 0xdd, 0x9e, 0x3e, 0x09, +0xf6, 0x1c, 0x3e, 0x29, 0xf8, 0x30, 0x84, 0x20, 0xd5, 0x02, 0xaa, 0x41, 0xe2, 0x02, 0xe9, 0xfe, +0xdd, 0x9e, 0x84, 0x23, 0x42, 0x00, 0x04, 0x24, 0x84, 0x20, 0xd5, 0x08, 0x84, 0x40, 0x92, 0x00, +0x84, 0x67, 0x9c, 0x91, 0x4c, 0x21, 0xff, 0xfd, 0x9c, 0x49, 0xe2, 0x20, 0xe9, 0xf8, 0xdd, 0x9e, +0x92, 0x00, 0x96, 0x00, 0xc0, 0x0d, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x20, +0x58, 0x10, 0x80, 0x30, 0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, 0x84, 0x09, 0xd5, 0x0e, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x20, 0x44, 0x2f, 0xff, 0xcf, 0x40, 0x10, 0x88, 0x02, +0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x02, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x2e, 0x07, 0xf0, 0x58, 0x84, 0xa4, 0xd0, 0x08, 0x84, 0xa6, 0xd0, 0x06, +0x84, 0xa7, 0xd0, 0x04, 0x84, 0xa8, 0x4c, 0x02, 0xc1, 0x08, 0x3c, 0x13, 0xf8, 0x24, 0x84, 0xa1, +0xd9, 0x03, 0x84, 0xc0, 0xd5, 0x08, 0x3c, 0x63, 0xf8, 0x25, 0x84, 0x00, 0x56, 0x63, 0x00, 0x01, +0x40, 0x60, 0x18, 0x06, 0x3c, 0x0c, 0x07, 0x32, 0x44, 0x50, 0x00, 0xc0, 0x54, 0x20, 0x00, 0xc0, +0xda, 0x54, 0x2e, 0x30, 0x1c, 0xdd, 0x54, 0x31, 0x80, 0x10, 0xc3, 0x4f, 0xce, 0x2a, 0x84, 0x41, +0x4c, 0x11, 0x00, 0x05, 0x3c, 0x53, 0xf8, 0x25, 0xda, 0x24, 0x46, 0x10, 0x04, 0x00, 0x04, 0x30, +0x80, 0x10, 0x96, 0xd9, 0x14, 0x30, 0x80, 0x10, 0x44, 0x1f, 0xc8, 0x30, 0x3c, 0x6c, 0x07, 0x30, +0x40, 0x00, 0x04, 0x02, 0x54, 0x63, 0x06, 0xc6, 0x40, 0x03, 0x00, 0x04, 0x3c, 0x0e, 0x07, 0x32, +0x42, 0x63, 0x40, 0x08, 0x3c, 0x2d, 0xfb, 0xf2, 0x80, 0x26, 0x44, 0x00, 0x00, 0x2e, 0xdd, 0x22, +0x3c, 0x2d, 0xfb, 0xf3, 0x80, 0x26, 0x44, 0x00, 0x00, 0x2d, 0xdd, 0x22, 0x48, 0x00, 0x00, 0x6b, +0x46, 0x10, 0x04, 0x00, 0x04, 0x30, 0x80, 0x10, 0x46, 0x46, 0xf0, 0x00, 0x40, 0x31, 0x90, 0x04, +0x14, 0x30, 0x80, 0x10, 0x3c, 0x7c, 0x07, 0x30, 0x44, 0x1f, 0xc8, 0x30, 0x40, 0x00, 0x04, 0x02, +0x54, 0x73, 0x91, 0xc9, 0x40, 0x03, 0x80, 0x04, 0x3c, 0x0e, 0x07, 0x32, 0x3c, 0x2d, 0xfb, 0xf2, +0x42, 0x73, 0xc0, 0x08, 0x80, 0x27, 0x44, 0x00, 0x00, 0x2e, 0xdd, 0x22, 0x3c, 0x2d, 0xfb, 0xf3, +0x80, 0x27, 0x44, 0x00, 0x00, 0x2d, 0xd5, 0x44, 0x46, 0x10, 0x04, 0x00, 0x04, 0x30, 0x80, 0x10, +0x96, 0xd9, 0x14, 0x30, 0x80, 0x10, 0x44, 0x50, 0x00, 0xc0, 0xda, 0x17, 0x44, 0x2f, 0xc8, 0x30, +0x40, 0x00, 0x08, 0x02, 0x58, 0x00, 0x00, 0xc1, 0x3c, 0x0e, 0x07, 0x32, 0x3c, 0x2d, 0xfb, 0xf2, +0x44, 0x11, 0x00, 0xc1, 0x44, 0x00, 0x00, 0x2e, 0xdd, 0x22, 0x3c, 0x2d, 0xfb, 0xf3, 0x44, 0x11, +0x00, 0xc1, 0x44, 0x00, 0x00, 0x2d, 0xd5, 0x24, 0x54, 0x10, 0x00, 0x80, 0xc1, 0x10, 0x44, 0x4f, +0xc8, 0x30, 0x40, 0x00, 0x10, 0x02, 0x58, 0x00, 0x04, 0x81, 0x3c, 0x0e, 0x07, 0x32, 0x3c, 0x2d, +0xfb, 0xf2, 0x44, 0x11, 0x04, 0x81, 0x44, 0x00, 0x00, 0x2e, 0xd5, 0x12, 0x54, 0x10, 0x00, 0x40, +0xc1, 0x10, 0x44, 0x1f, 0xc8, 0x30, 0x40, 0x00, 0x04, 0x02, 0x58, 0x00, 0x00, 0x41, 0x3c, 0x0e, +0x07, 0x32, 0x3c, 0x2d, 0xfb, 0xf3, 0x44, 0x11, 0x00, 0x41, 0x44, 0x00, 0x00, 0x2d, 0xdd, 0x22, +0xce, 0x0c, 0x3c, 0x1c, 0x07, 0x32, 0x96, 0x0c, 0xc0, 0x05, 0x54, 0x10, 0x80, 0x40, 0xc1, 0x05, +0x84, 0x01, 0x49, 0xff, 0xff, 0x20, 0x92, 0x00, 0x3e, 0x08, 0x1c, 0xc0, 0xa0, 0x42, 0x54, 0x10, +0x81, 0x00, 0xc1, 0x12, 0x20, 0x10, 0x00, 0x19, 0x84, 0xbf, 0xd9, 0x05, 0x00, 0x40, 0x00, 0x3b, +0x10, 0x40, 0x00, 0x19, 0x2e, 0x10, 0x1c, 0xd9, 0x3c, 0x2d, 0xfb, 0xf3, 0x42, 0x10, 0xc4, 0x08, +0x44, 0x00, 0x00, 0x2d, 0xdd, 0x22, 0x3e, 0x08, 0x1c, 0xc0, 0xa0, 0x42, 0x54, 0x10, 0x90, 0x00, +0xc1, 0x12, 0x20, 0x10, 0x00, 0x1b, 0x84, 0xbf, 0xd9, 0x05, 0x00, 0x40, 0x00, 0x41, 0x10, 0x40, +0x00, 0x1b, 0x2e, 0x10, 0x1c, 0xdb, 0x3c, 0x2d, 0xfb, 0xf2, 0x42, 0x10, 0xe0, 0x08, 0x44, 0x00, +0x00, 0x2e, 0xdd, 0x22, 0x3c, 0x0c, 0x07, 0x32, 0x54, 0x10, 0x00, 0x04, 0x54, 0x00, 0x00, 0x80, +0xc1, 0x0e, 0xc0, 0x1a, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x58, 0x10, +0x80, 0x01, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x04, 0xd5, 0x0d, 0xc0, 0x0d, 0x46, 0x00, +0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x42, 0x10, 0x88, 0x09, 0xb6, 0x20, 0xb4, 0x20, +0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x84, 0x00, +0x3e, 0x19, 0xf6, 0x30, 0x10, 0x00, 0x80, 0x66, 0x3e, 0x01, 0xf6, 0x1c, 0xae, 0x08, 0x10, 0x00, +0x80, 0x22, 0x10, 0x00, 0x80, 0x44, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x00, 0x90, 0x3c, 0x0f, +0xfb, 0xa0, 0x46, 0x30, 0x00, 0x95, 0x58, 0x31, 0x8c, 0xc4, 0x3c, 0x3f, 0xfb, 0x9b, 0x46, 0x30, +0x00, 0x95, 0x58, 0x31, 0x81, 0x18, 0x3c, 0x3f, 0xfb, 0x9c, 0x46, 0x30, 0x00, 0x92, 0x58, 0x31, +0x8b, 0x64, 0x3c, 0x3f, 0xfb, 0x9d, 0x2e, 0x11, 0xf6, 0x0f, 0x84, 0x63, 0x3e, 0x30, 0x04, 0xfa, +0x84, 0xa1, 0xd9, 0x06, 0x84, 0x00, 0x3e, 0x01, 0xf6, 0x0f, 0x3c, 0x1e, 0x16, 0xdb, 0x84, 0x40, +0x2e, 0x01, 0xf6, 0x0e, 0x3e, 0x21, 0xf6, 0x10, 0x84, 0xa1, 0xd8, 0x05, 0x3e, 0x21, 0xf6, 0x0e, +0x3c, 0x0e, 0x16, 0xdb, 0x46, 0x10, 0x00, 0x94, 0x58, 0x10, 0x89, 0xe0, 0x3c, 0x1f, 0xfd, 0x35, +0xdd, 0x9e, 0x96, 0x40, 0xe6, 0x2b, 0xe9, 0x02, 0x84, 0x0a, 0x96, 0x00, 0x8c, 0x15, 0x92, 0x02, +0x3e, 0x01, 0xf5, 0xfa, 0xdd, 0x9e, 0x96, 0x40, 0xe6, 0x28, 0xe9, 0x02, 0x84, 0x07, 0x96, 0x00, +0x8c, 0x18, 0x92, 0x02, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x50, 0x3f, 0x80, 0x0c, +0x3a, 0x01, 0x88, 0x20, 0x84, 0xc0, 0x46, 0x20, 0x00, 0x90, 0x58, 0x21, 0x05, 0x74, 0x00, 0xa1, +0x80, 0x01, 0xa7, 0xda, 0x3e, 0x19, 0xf5, 0xe4, 0xf1, 0x81, 0xf2, 0x82, 0x80, 0x07, 0xdd, 0x22, +0x50, 0x83, 0x00, 0x01, 0x3e, 0x39, 0xf5, 0xdc, 0x38, 0x41, 0x80, 0x00, 0x40, 0x94, 0x08, 0x08, +0x3e, 0x0f, 0xf6, 0x50, 0x98, 0xf0, 0x8f, 0x21, 0x3e, 0x09, 0xf5, 0xbc, 0x9b, 0x3c, 0x40, 0x54, +0x80, 0x00, 0x38, 0x52, 0x90, 0x00, 0x80, 0x0a, 0xaf, 0x58, 0x49, 0xff, 0xff, 0xce, 0xf1, 0x01, +0x3e, 0x4f, 0xf6, 0x60, 0x38, 0x30, 0x80, 0x00, 0x83, 0x80, 0x98, 0x34, 0x3e, 0x49, 0xf5, 0x9c, +0x40, 0x35, 0x0c, 0x01, 0x89, 0x24, 0x38, 0x94, 0x8c, 0x00, 0x80, 0xc8, 0x10, 0x90, 0x00, 0x00, +0x84, 0xa8, 0xf2, 0x02, 0x4c, 0x82, 0xff, 0xd2, 0x3e, 0x6f, 0xf6, 0x61, 0x3e, 0x99, 0xf5, 0xed, +0x3e, 0x8f, 0xf6, 0x68, 0x46, 0x10, 0x00, 0x90, 0x58, 0x10, 0x85, 0x74, 0xf1, 0x81, 0x80, 0x07, +0xdd, 0x21, 0xf1, 0x01, 0x4c, 0x0e, 0x00, 0x0a, 0xa6, 0xf0, 0x00, 0x44, 0x80, 0x00, 0x10, 0x33, +0x7f, 0xff, 0x10, 0x44, 0x00, 0x00, 0xd5, 0x05, 0x00, 0x04, 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, +0x9d, 0xb1, 0x3e, 0x5f, 0xf6, 0x68, 0x8d, 0x21, 0x8d, 0x01, 0xde, 0xe9, 0x80, 0x07, 0x49, 0xff, +0xff, 0x8a, 0x80, 0xc0, 0x80, 0x0a, 0x49, 0xff, 0xff, 0x90, 0x4c, 0x60, 0x00, 0x06, 0x2e, 0x11, +0xf5, 0xbb, 0x3e, 0x17, 0xf6, 0x67, 0x2e, 0x11, 0xf5, 0xf3, 0x3e, 0x17, 0xf6, 0x6f, 0xec, 0x1c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x19, 0xf5, 0xf4, 0xa6, 0x88, +0x96, 0x00, 0x4c, 0x20, 0x00, 0x51, 0x44, 0x50, 0x00, 0xff, 0xae, 0x08, 0xd0, 0x1e, 0x54, 0x20, +0x00, 0x0c, 0x40, 0x40, 0x10, 0x09, 0x92, 0x42, 0xa6, 0xcd, 0x54, 0x00, 0x00, 0x03, 0x99, 0x54, +0x10, 0x00, 0x80, 0x08, 0xaf, 0x0a, 0xae, 0x8b, 0xe0, 0x65, 0xe8, 0x03, 0x9a, 0x9a, 0xae, 0x8a, +0x80, 0x01, 0xa6, 0x44, 0xa6, 0xc3, 0xa6, 0x82, 0x9b, 0x0b, 0xe0, 0x44, 0xe8, 0x03, 0x84, 0x20, +0xd5, 0x03, 0x98, 0x9a, 0x9a, 0x51, 0xae, 0x41, 0x3e, 0x69, 0xf5, 0xf4, 0xa6, 0x32, 0x49, 0xff, +0xff, 0x4a, 0x00, 0x13, 0x00, 0x08, 0xae, 0x36, 0x9a, 0x01, 0xae, 0x37, 0x3a, 0x03, 0x08, 0x00, +0x49, 0xff, 0xff, 0x53, 0x92, 0x00, 0xa7, 0xf2, 0x3e, 0x70, 0x02, 0x7b, 0x80, 0x07, 0x49, 0xff, +0xff, 0x3a, 0x2e, 0x40, 0xda, 0xd2, 0x44, 0x10, 0x00, 0x30, 0x42, 0x42, 0x04, 0x24, 0x94, 0x02, +0xa6, 0xf6, 0xa6, 0xb7, 0x9b, 0xf8, 0x3e, 0x08, 0x79, 0xd8, 0x3e, 0x18, 0x03, 0xb0, 0x99, 0x20, +0x3e, 0x70, 0x02, 0x7c, 0x10, 0x22, 0x00, 0x25, 0x10, 0x30, 0x80, 0xcd, 0x10, 0x30, 0x80, 0xc9, +0x10, 0x20, 0x81, 0x51, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x97, 0x81, +0x3c, 0x2d, 0xfb, 0xfc, 0x96, 0x49, 0x80, 0x06, 0xdd, 0x22, 0x2e, 0x00, 0xac, 0x94, 0xc0, 0x29, +0x44, 0x50, 0x00, 0x20, 0xde, 0x03, 0x84, 0x0f, 0xd5, 0x02, 0x96, 0x30, 0x3e, 0x18, 0xab, 0xdc, +0x10, 0x00, 0x80, 0x1b, 0x10, 0x00, 0x80, 0x0c, 0x10, 0x00, 0x80, 0x0d, 0x10, 0x00, 0x80, 0x0e, +0x10, 0x00, 0x80, 0x0f, 0x10, 0x00, 0x80, 0x10, 0x10, 0x00, 0x80, 0x11, 0x10, 0x00, 0x80, 0x12, +0x10, 0x00, 0x80, 0x13, 0x10, 0x00, 0x80, 0x14, 0x10, 0x00, 0x80, 0x15, 0x10, 0x00, 0x80, 0x16, +0x10, 0x00, 0x80, 0x17, 0x10, 0x00, 0x80, 0x18, 0x10, 0x00, 0x80, 0x19, 0x10, 0x00, 0x80, 0x1a, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x42, 0x00, 0x00, 0x09, 0x9c, 0x02, 0xdd, 0x9e, 0x96, 0x00, +0x54, 0x10, 0x00, 0x08, 0x3c, 0x0e, 0x2b, 0x1b, 0xc9, 0x02, 0xc8, 0x06, 0x46, 0x00, 0x04, 0xa0, +0x84, 0x20, 0x14, 0x10, 0x00, 0x92, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x02, 0x04, 0x00, +0x02, 0x00, 0x84, 0xa3, 0x54, 0x00, 0x00, 0x07, 0xd0, 0x16, 0x84, 0xa4, 0xd0, 0x04, 0x84, 0xa1, +0xd8, 0x24, 0xd5, 0x11, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xd4, 0x46, 0x00, 0x04, 0x05, +0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x81, 0xd4, 0x58, 0x00, 0x08, 0x18, 0xb4, 0x20, 0x42, 0x10, +0xec, 0x09, 0xd5, 0x12, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xcc, 0x46, 0x00, 0x04, 0x05, +0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x81, 0xcc, 0x58, 0x00, 0x09, 0x08, 0xb4, 0x20, 0x46, 0x26, +0x00, 0x00, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, 0xdd, 0x9e, 0x00, 0x10, 0x00, 0x20, 0x9e, 0x8e, +0x96, 0x90, 0x3c, 0x0c, 0x21, 0x30, 0xe6, 0x44, 0xe9, 0x09, 0x2e, 0x50, 0xda, 0xd2, 0xd9, 0x10, +0x84, 0xa1, 0xd0, 0x0e, 0x54, 0x00, 0x00, 0x02, 0xc8, 0x0b, 0x3c, 0x0c, 0x21, 0x38, 0x46, 0x10, +0x00, 0xff, 0x40, 0x00, 0x04, 0x02, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, +0xdd, 0x9e, 0xa6, 0x40, 0x44, 0x50, 0x00, 0xff, 0xd1, 0x03, 0x3e, 0x10, 0xf0, 0x38, 0xa6, 0x41, +0xd1, 0x03, 0x3e, 0x10, 0xf0, 0x39, 0xa6, 0x02, 0xd0, 0x03, 0x3e, 0x00, 0xf0, 0x3a, 0xdd, 0x9e, +0x92, 0x00, 0xa6, 0x40, 0x84, 0xa2, 0xd1, 0x0a, 0x84, 0xa3, 0xd1, 0x0a, 0x84, 0x01, 0x4c, 0x10, +0x40, 0x13, 0x84, 0x20, 0x3e, 0x10, 0x02, 0x5f, 0xd5, 0x0e, 0x84, 0x20, 0xd5, 0x0a, 0xa6, 0x81, +0x3e, 0x20, 0x02, 0x5f, 0xa6, 0x43, 0xa6, 0x02, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x80, 0x04, +0x3c, 0x18, 0x36, 0x4f, 0xdd, 0x9e, 0x3c, 0x1c, 0x2a, 0xf7, 0x96, 0x8c, 0xca, 0x05, 0x2e, 0x20, +0x02, 0xda, 0x84, 0xa1, 0xda, 0x23, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x20, 0xc0, 0x1f, 0xa6, 0x80, +0x96, 0x94, 0xca, 0x04, 0x44, 0x20, 0x00, 0x4e, 0xd5, 0x02, 0x84, 0x40, 0x3e, 0x20, 0x7d, 0xb0, +0xa6, 0x83, 0x96, 0x94, 0xca, 0x04, 0x44, 0x20, 0x00, 0x4e, 0xd5, 0x03, 0x44, 0x20, 0x00, 0x18, +0x3e, 0x20, 0x7d, 0xb1, 0x00, 0x00, 0x00, 0x09, 0x54, 0x00, 0x00, 0x40, 0xc8, 0x02, 0xd5, 0x03, +0x44, 0x00, 0x00, 0x4e, 0x3e, 0x00, 0x7d, 0xb2, 0xd5, 0x0a, 0x3e, 0x08, 0x7d, 0xb0, 0x44, 0x10, +0x00, 0x4e, 0xae, 0x42, 0x84, 0x20, 0xae, 0x40, 0x8c, 0x38, 0xae, 0x41, 0xdd, 0x9e, 0x46, 0x10, +0x04, 0x05, 0x04, 0x20, 0x82, 0x42, 0x42, 0x21, 0x74, 0x09, 0x42, 0x21, 0x78, 0x09, 0x14, 0x20, +0x82, 0x42, 0x46, 0x00, 0x04, 0x04, 0x58, 0x00, 0x04, 0x04, 0xb4, 0x20, 0x42, 0x10, 0x98, 0x09, +0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xac, 0x44, 0x25, 0xd4, 0xac, 0x38, 0x41, 0x02, 0x02, 0x2e, 0x20, 0x04, 0x54, +0x50, 0x32, 0x00, 0x54, 0x46, 0x00, 0x3d, 0x09, 0xf3, 0x84, 0x40, 0x00, 0x08, 0x0e, 0x3c, 0x0e, +0x00, 0x6b, 0xf0, 0x04, 0x50, 0x52, 0x00, 0x58, 0x84, 0x60, 0xf5, 0x83, 0xac, 0xc0, 0xac, 0xe8, +0x81, 0x41, 0x3c, 0x2c, 0x00, 0x6b, 0x84, 0x2a, 0xf2, 0x82, 0x42, 0x61, 0x04, 0x24, 0x40, 0x21, +0x28, 0xf7, 0x50, 0x5f, 0x80, 0x38, 0xf5, 0x81, 0x46, 0x70, 0x00, 0x96, 0x58, 0x73, 0x85, 0x7c, +0x04, 0x8f, 0x80, 0x01, 0x50, 0x5f, 0x80, 0x20, 0xb6, 0xbf, 0x50, 0x52, 0x00, 0x24, 0xf5, 0x86, +0xb4, 0xbf, 0x51, 0xc2, 0x00, 0x0c, 0x81, 0x24, 0xf2, 0x87, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, +0x05, 0x94, 0x83, 0xc2, 0x3a, 0x0f, 0x0c, 0x04, 0x3a, 0x04, 0x0c, 0x24, 0x50, 0x02, 0x00, 0x2c, +0x50, 0x42, 0x00, 0x28, 0xf0, 0x85, 0x3a, 0x0f, 0x04, 0x00, 0xb6, 0x08, 0x12, 0x1f, 0x80, 0x26, +0x3a, 0x03, 0x8c, 0x04, 0x3a, 0x02, 0x8c, 0x24, 0x40, 0x23, 0x28, 0xd7, 0x3a, 0x03, 0x84, 0x00, +0xb6, 0x05, 0x84, 0x0a, 0x12, 0x1f, 0x80, 0x1a, 0xf1, 0x07, 0x96, 0xc9, 0x92, 0x68, 0x9c, 0xd9, +0x42, 0x11, 0xa8, 0x24, 0x97, 0xd8, 0x92, 0x68, 0x40, 0x51, 0x00, 0x57, 0xf5, 0x02, 0x40, 0x02, +0x84, 0x37, 0x50, 0x5f, 0x80, 0x38, 0x38, 0x12, 0x89, 0x01, 0xf5, 0x04, 0xac, 0x68, 0x50, 0x5f, +0x80, 0x20, 0x38, 0x12, 0x89, 0x01, 0xf2, 0x03, 0xac, 0x50, 0x84, 0x23, 0xf5, 0x06, 0xac, 0x68, +0x02, 0x1e, 0x00, 0x00, 0x58, 0x20, 0x80, 0x80, 0x12, 0x2e, 0x00, 0x00, 0x1a, 0x74, 0x80, 0x02, +0x12, 0x34, 0x80, 0x00, 0x9e, 0x01, 0x96, 0x01, 0xac, 0x20, 0x40, 0x30, 0x04, 0x09, 0x96, 0x84, +0x9a, 0x9a, 0xf0, 0x05, 0x96, 0x91, 0xac, 0x80, 0x12, 0x1e, 0x00, 0x00, 0xec, 0x54, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x80, 0xc1, 0x44, 0x10, +0x00, 0x41, 0xa6, 0x00, 0xae, 0x70, 0x9c, 0x49, 0xae, 0x72, 0x2e, 0x10, 0x02, 0xa3, 0x54, 0x81, +0x00, 0xff, 0x84, 0xa1, 0xd9, 0x08, 0x3e, 0x1f, 0xf6, 0x60, 0x38, 0x70, 0x80, 0x00, 0x3e, 0x1f, +0xf6, 0x68, 0xd5, 0x07, 0x3e, 0x1f, 0xf6, 0x50, 0x38, 0x70, 0x80, 0x00, 0x3e, 0x1f, 0xf6, 0x58, +0x38, 0x10, 0x80, 0x00, 0xae, 0x73, 0x3c, 0x1d, 0xfb, 0xa9, 0x50, 0x0f, 0x80, 0x04, 0xdd, 0x21, +0xc8, 0x04, 0x44, 0x00, 0x00, 0x19, 0xf0, 0x81, 0xf1, 0x01, 0x2e, 0x08, 0x02, 0xaf, 0x3e, 0x2f, +0xf6, 0x70, 0x38, 0x21, 0x1c, 0x00, 0x98, 0x01, 0x3e, 0x20, 0x02, 0xb0, 0xf0, 0x81, 0x5e, 0xf0, +0x7f, 0xd8, 0xe8, 0x04, 0x44, 0x0f, 0xff, 0xd8, 0xd5, 0x06, 0x5e, 0xf0, 0x00, 0x52, 0xe9, 0x04, +0x44, 0x00, 0x00, 0x51, 0xf0, 0x81, 0xf0, 0x01, 0x50, 0x00, 0x00, 0x2f, 0x90, 0x03, 0x96, 0x00, +0x3e, 0x4f, 0xf6, 0xac, 0x3e, 0x3f, 0xf6, 0xc0, 0x2e, 0x20, 0xa4, 0xdd, 0x38, 0x31, 0x80, 0x10, +0x38, 0x02, 0x00, 0x10, 0x2e, 0x40, 0x02, 0xb2, 0xe2, 0x48, 0xe8, 0x03, 0x84, 0x42, 0xd5, 0x05, +0x2e, 0x20, 0xa4, 0xdc, 0x40, 0x21, 0x20, 0x06, 0x3e, 0x18, 0xf0, 0x38, 0x38, 0x20, 0x88, 0x00, +0x98, 0x63, 0x98, 0x4a, 0x96, 0x4a, 0x44, 0x20, 0x00, 0x18, 0x42, 0x10, 0x88, 0x01, 0x99, 0xf8, +0x9c, 0x94, 0x84, 0x00, 0x42, 0x73, 0x88, 0x01, 0x42, 0x10, 0x80, 0x00, 0x3e, 0x2f, 0xf6, 0x90, +0x38, 0x11, 0x04, 0x00, 0x42, 0x03, 0x80, 0x00, 0xae, 0x71, 0x3e, 0x1f, 0xf6, 0x70, 0x38, 0x00, +0x80, 0x00, 0x40, 0x10, 0x20, 0x08, 0x40, 0x10, 0x80, 0x04, 0x3e, 0x00, 0x02, 0xb1, 0xac, 0x72, +0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0xa6, 0x80, 0x3e, 0x18, 0xf0, 0x38, +0xae, 0x88, 0xa6, 0x81, 0xae, 0x89, 0xa6, 0x02, 0xae, 0x0a, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0x3c, 0x96, 0x00, 0x97, 0x22, 0x97, 0x6a, 0x20, 0x8f, 0x80, 0x18, 0x20, 0x7f, 0x80, 0x1c, +0xca, 0x11, 0x46, 0x00, 0x04, 0x02, 0x04, 0x10, 0x00, 0x40, 0x46, 0x2f, 0xfb, 0xcf, 0x58, 0x21, +0x0f, 0xff, 0x40, 0x10, 0x88, 0x02, 0x40, 0x31, 0x84, 0x04, 0x14, 0x30, 0x00, 0x40, 0x48, 0x00, +0x01, 0x39, 0x97, 0xa0, 0x5e, 0xf1, 0x84, 0x01, 0xe8, 0x23, 0x5e, 0xf1, 0x83, 0xff, 0xe8, 0x48, +0x44, 0x40, 0x00, 0x40, 0x4c, 0x32, 0x00, 0x3d, 0x5e, 0xf1, 0x80, 0x41, 0xe8, 0x0d, 0x44, 0x90, +0x00, 0x10, 0x4c, 0x34, 0x80, 0x32, 0x40, 0xa4, 0x84, 0x08, 0x4c, 0x35, 0x00, 0x30, 0x84, 0x88, +0x4c, 0x32, 0x40, 0x29, 0xd5, 0x29, 0x40, 0x92, 0x08, 0x08, 0x4c, 0x34, 0x80, 0x2e, 0x40, 0xa2, +0x0c, 0x08, 0x4c, 0x35, 0x00, 0x2c, 0x95, 0x21, 0x4c, 0x32, 0x40, 0x1d, 0xd5, 0x23, 0x44, 0x90, +0x10, 0x00, 0x4c, 0x34, 0x80, 0x26, 0x5e, 0xf1, 0x90, 0x01, 0xe8, 0x08, 0x44, 0xa0, 0x08, 0x00, +0x4c, 0x35, 0x00, 0x1f, 0x44, 0x40, 0x0c, 0x00, 0xd5, 0x0b, 0x44, 0x90, 0x40, 0x00, 0x4c, 0x34, +0x80, 0x18, 0x40, 0xa4, 0x84, 0x08, 0x4c, 0x35, 0x00, 0x14, 0x44, 0x40, 0x20, 0x00, 0x4c, 0x32, +0x00, 0x10, 0x84, 0x80, 0xd5, 0x0e, 0x84, 0x84, 0xd5, 0x0c, 0x84, 0x85, 0xd5, 0x0a, 0x84, 0x86, +0xd5, 0x08, 0x84, 0x87, 0xd5, 0x06, 0x84, 0x88, 0xd5, 0x04, 0x84, 0x89, 0xd5, 0x02, 0x84, 0x8a, +0xc9, 0x70, 0x44, 0xa4, 0x02, 0x10, 0x40, 0x90, 0x28, 0x00, 0x40, 0x94, 0x90, 0x08, 0x85, 0x41, +0x05, 0xc4, 0x80, 0x00, 0x4c, 0x25, 0x40, 0x09, 0x89, 0x47, 0x50, 0x14, 0x00, 0x01, 0x42, 0x15, +0x04, 0x24, 0x9e, 0x49, 0x96, 0x48, 0x40, 0x52, 0xa0, 0x08, 0x54, 0x52, 0xbf, 0x00, 0x54, 0x84, +0x00, 0x0f, 0x40, 0x84, 0x14, 0x04, 0x46, 0x50, 0x0c, 0x00, 0x40, 0x73, 0xd8, 0x08, 0x40, 0x73, +0x94, 0x02, 0x40, 0x74, 0x1c, 0x04, 0x46, 0x80, 0x03, 0xf0, 0x40, 0x10, 0xc0, 0x08, 0x50, 0xa0, +0x7f, 0xfc, 0x40, 0x10, 0xa0, 0x02, 0x54, 0xa5, 0x00, 0xff, 0x40, 0x13, 0x84, 0x04, 0xe7, 0x42, +0xe9, 0x03, 0x84, 0xa0, 0xd5, 0x07, 0x46, 0x50, 0x00, 0x96, 0x58, 0x52, 0x85, 0xec, 0x38, 0x52, +0xaa, 0x02, 0x54, 0x52, 0x9f, 0xff, 0x40, 0x42, 0x40, 0x08, 0x85, 0x42, 0x40, 0x42, 0x90, 0x04, +0x4c, 0x25, 0x00, 0x14, 0x84, 0xa3, 0xda, 0x08, 0x40, 0x63, 0x60, 0x08, 0x40, 0x42, 0x18, 0x04, +0x58, 0x10, 0x80, 0x10, 0xd5, 0x0a, 0x84, 0xe1, 0x4c, 0x23, 0xc0, 0x08, 0x40, 0x63, 0x60, 0x08, +0x40, 0x42, 0x18, 0x04, 0x58, 0x10, 0x80, 0x20, 0x46, 0x20, 0x04, 0x02, 0x58, 0x21, 0x00, 0x8c, +0xb4, 0xe2, 0x84, 0xc1, 0x9f, 0x41, 0x40, 0x03, 0x00, 0x0c, 0x96, 0xdd, 0x40, 0x00, 0x1c, 0x04, +0x95, 0x6c, 0x40, 0x6e, 0x2c, 0x09, 0x40, 0x63, 0x2c, 0x08, 0x42, 0x31, 0xf4, 0x08, 0x50, 0x71, +0x00, 0x8c, 0x50, 0x83, 0xff, 0xfc, 0x40, 0x31, 0x98, 0x04, 0x99, 0xaf, 0x88, 0xa8, 0xd5, 0x75, +0x85, 0x21, 0x4c, 0x14, 0xc0, 0x77, 0x44, 0xa4, 0x02, 0x20, 0x40, 0x90, 0x28, 0x00, 0x40, 0x94, +0x90, 0x08, 0x05, 0xc4, 0x80, 0x00, 0x4c, 0x20, 0x80, 0x04, 0x85, 0x40, 0xd5, 0x0a, 0x50, 0xa3, +0x80, 0x01, 0x50, 0x14, 0x00, 0x01, 0x42, 0xa5, 0x04, 0x24, 0x8f, 0x41, 0x54, 0xa5, 0x00, 0xff, +0x40, 0x52, 0xa0, 0x08, 0x54, 0x52, 0xbf, 0x00, 0x54, 0x84, 0x00, 0x0f, 0x40, 0x14, 0x14, 0x04, +0x46, 0x50, 0x0c, 0x00, 0x40, 0x73, 0xd8, 0x08, 0x40, 0x73, 0x94, 0x02, 0x40, 0x10, 0x9c, 0x04, +0x46, 0x70, 0x03, 0xf0, 0x40, 0xa5, 0x40, 0x08, 0x9f, 0x44, 0x40, 0xa5, 0x1c, 0x02, 0x97, 0x68, +0x40, 0x10, 0xa8, 0x04, 0xe6, 0xa6, 0xe9, 0x03, 0x84, 0xa0, 0xd5, 0x07, 0x46, 0x70, 0x00, 0x96, +0x58, 0x73, 0x85, 0xf4, 0x38, 0x53, 0x96, 0x02, 0x54, 0x52, 0x9f, 0xff, 0x40, 0x42, 0x40, 0x08, +0x85, 0x02, 0x40, 0x42, 0x90, 0x04, 0x4c, 0x24, 0x00, 0x14, 0x85, 0x43, 0x4c, 0x25, 0x40, 0x09, +0x40, 0x63, 0x60, 0x08, 0x40, 0x42, 0x18, 0x04, 0x58, 0x10, 0x80, 0x10, 0xd5, 0x09, 0x84, 0xa1, +0xda, 0x07, 0x40, 0x63, 0x60, 0x08, 0x40, 0x42, 0x18, 0x04, 0x58, 0x10, 0x80, 0x20, 0x46, 0x20, +0x04, 0x02, 0x58, 0x21, 0x00, 0x8c, 0xb4, 0xe2, 0x44, 0x61, 0x00, 0x00, 0x9f, 0x41, 0x40, 0x03, +0x00, 0x0c, 0x96, 0xdd, 0x40, 0x00, 0x1c, 0x04, 0x95, 0x6c, 0x40, 0x6e, 0x2c, 0x09, 0x40, 0x63, +0x2c, 0x08, 0x42, 0x31, 0xf4, 0x08, 0x50, 0xa1, 0x01, 0x8c, 0x50, 0x75, 0x7f, 0xfc, 0x40, 0x31, +0x98, 0x04, 0x40, 0x62, 0xa8, 0x00, 0x99, 0x6f, 0xb6, 0x02, 0xb6, 0x69, 0xb6, 0x25, 0xb6, 0x86, +0x3a, 0x6f, 0xaa, 0x04, 0xdd, 0x9e, 0x02, 0x00, 0x00, 0x5d, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x00, +0x3e, 0x19, 0xf7, 0xa4, 0x10, 0x00, 0x80, 0x45, 0x3e, 0x01, 0xf6, 0x1d, 0xae, 0x08, 0x10, 0x00, +0x80, 0x17, 0x10, 0x00, 0x80, 0x2e, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x3c, 0x1d, 0xff, 0xd2, 0x3c, 0x0c, 0x7d, 0x82, 0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3e, 0x18, 0x72, 0x78, 0x00, 0x20, 0x80, 0xb5, +0x9c, 0x91, 0x10, 0x20, 0x80, 0xb5, 0xc8, 0x07, 0x00, 0x00, 0x80, 0xb7, 0x9c, 0x01, 0x10, 0x00, +0x80, 0xb7, 0xd5, 0x06, 0x00, 0x00, 0x80, 0xb6, 0x9c, 0x01, 0x10, 0x00, 0x80, 0xb6, 0x80, 0x01, +0x00, 0x20, 0x00, 0xb7, 0x00, 0x40, 0x00, 0xba, 0x00, 0x50, 0x00, 0xb9, 0x00, 0x30, 0x00, 0xb6, +0x40, 0x42, 0x08, 0x06, 0x9b, 0x25, 0x99, 0x23, 0x10, 0x40, 0x00, 0xbb, 0x3e, 0x30, 0xa8, 0xb5, +0x3e, 0x20, 0xa8, 0xb4, 0x3c, 0x1d, 0xff, 0xd2, 0x84, 0x04, 0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x2e, 0x00, 0x2b, 0x08, 0x56, 0x00, 0x00, 0x08, 0x5c, 0x00, +0x00, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0xa2, 0xd8, 0x08, +0x2e, 0x01, 0xf6, 0x17, 0x56, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x01, 0xd5, 0x0b, 0x84, 0xa3, +0xd0, 0x03, 0x84, 0x00, 0xd5, 0x07, 0x49, 0xff, 0xff, 0xe8, 0x92, 0x00, 0x84, 0x20, 0x40, 0x00, +0x80, 0x06, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x02, 0x58, 0x00, +0x01, 0x00, 0xb4, 0x20, 0xb4, 0x40, 0x42, 0x21, 0x7c, 0x08, 0xb6, 0x40, 0xb4, 0x40, 0x42, 0x21, +0x7c, 0x09, 0xb6, 0x40, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x20, 0x04, 0x02, 0x04, 0x21, +0x00, 0x40, 0x46, 0x30, 0x04, 0x00, 0x40, 0x21, 0x0c, 0x02, 0xc2, 0x02, 0x84, 0x41, 0xb6, 0x41, +0x2e, 0x10, 0xda, 0xe9, 0xc1, 0x06, 0x84, 0x21, 0xb6, 0x20, 0x3e, 0x11, 0xf6, 0x0d, 0xd5, 0x02, +0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0xb4, 0x20, 0x84, 0xbf, 0xd9, 0x04, 0x84, 0x20, 0xaa, 0x41, +0xb4, 0x20, 0x9c, 0x49, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x44, 0x20, 0xff, 0xfd, 0x96, 0x49, +0x4c, 0x11, 0x40, 0x0e, 0xa6, 0x00, 0x44, 0x10, 0x00, 0xff, 0x4c, 0x00, 0x80, 0x1b, 0x44, 0x50, +0x00, 0x13, 0xd0, 0x17, 0x5c, 0xf0, 0x00, 0x3f, 0xe8, 0x14, 0xd5, 0x0d, 0x44, 0x50, 0xff, 0xfc, +0xd1, 0x0e, 0x9d, 0x51, 0xd9, 0x0e, 0xa6, 0x40, 0x44, 0x50, 0x00, 0x35, 0xd9, 0x08, 0xa6, 0x01, +0x56, 0x00, 0x00, 0x0c, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xd5, 0x04, 0x84, 0x01, 0xd5, 0x02, +0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xa4, 0x40, 0x5c, 0xf0, 0x80, 0x29, 0xe9, 0x04, 0x44, 0x10, +0x00, 0x28, 0xac, 0x40, 0xdd, 0x9e, 0x3c, 0x0c, 0x21, 0x34, 0x44, 0x10, 0x00, 0x80, 0x4c, 0x00, +0x80, 0x08, 0xe2, 0x01, 0xe9, 0x17, 0x5c, 0xf0, 0x00, 0x83, 0xe8, 0x14, 0xd5, 0x0c, 0x3c, 0x0c, +0x21, 0x37, 0x40, 0x10, 0x30, 0x08, 0x92, 0x3c, 0xc9, 0x0f, 0x40, 0x00, 0x40, 0x08, 0x92, 0x1c, +0xc8, 0x0b, 0xd5, 0x08, 0x3c, 0x0c, 0x21, 0x37, 0x44, 0x55, 0x00, 0x00, 0xd8, 0x03, 0x84, 0x02, +0xd5, 0x04, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x06, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x96, 0x48, +0x9e, 0x89, 0x96, 0xd0, 0xe6, 0x6e, 0xe9, 0x05, 0x44, 0x65, 0xb1, 0x48, 0x84, 0x20, 0xd5, 0x09, +0x84, 0xca, 0x42, 0x61, 0x18, 0x24, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0xbc, 0x99, 0xb2, +0x54, 0x20, 0x00, 0x80, 0xc2, 0x13, 0x96, 0x04, 0xc8, 0x04, 0x2e, 0x00, 0x02, 0xda, 0xc0, 0x0e, +0xc1, 0x0d, 0x2e, 0x00, 0x02, 0xd9, 0xc0, 0x04, 0x3c, 0x5c, 0x00, 0x0b, 0xd6, 0x1e, 0x84, 0x21, +0x80, 0x06, 0x84, 0x61, 0x3e, 0x28, 0x02, 0xd9, 0xd5, 0x09, 0x3e, 0x28, 0x02, 0xd9, 0xa6, 0x50, +0x84, 0x01, 0x4c, 0x10, 0x40, 0x13, 0x80, 0x06, 0x84, 0x60, 0xae, 0xd0, 0x3c, 0x6e, 0x00, 0x0b, +0x49, 0xfc, 0xaa, 0x41, 0x80, 0x06, 0x49, 0xff, 0xfc, 0x20, 0x3c, 0x3d, 0xfc, 0x06, 0x80, 0x46, +0x44, 0x00, 0x00, 0x46, 0x84, 0x20, 0xdd, 0x23, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x44, 0x00, 0x00, 0x7e, 0x4c, 0x60, 0x00, 0x06, 0x44, 0x00, +0x00, 0xcc, 0x4c, 0x60, 0x40, 0x0b, 0x3c, 0x4d, 0xff, 0x14, 0x80, 0x66, 0x84, 0x04, 0x84, 0x21, +0x44, 0x20, 0x30, 0x01, 0xdd, 0x24, 0xd5, 0x1c, 0x3c, 0x4d, 0xff, 0x14, 0x80, 0x66, 0x84, 0x04, +0x84, 0x21, 0x44, 0x20, 0x30, 0x01, 0xdd, 0x24, 0x80, 0x86, 0x3c, 0x5c, 0x36, 0xe6, 0x3c, 0x6c, +0x21, 0x34, 0x84, 0x00, 0x46, 0x10, 0x00, 0x96, 0x58, 0x10, 0x84, 0x6c, 0x46, 0x20, 0x00, 0x96, +0x58, 0x21, 0x04, 0x70, 0x44, 0x30, 0x2d, 0x63, 0xb6, 0xdf, 0x49, 0xfb, 0x98, 0x00, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x21, 0x37, +0x44, 0x20, 0x40, 0x00, 0x3c, 0x0c, 0x21, 0x34, 0x4c, 0x11, 0x00, 0x07, 0x44, 0x55, 0x00, 0x00, +0xd1, 0x07, 0xc1, 0x18, 0xd5, 0x1e, 0x44, 0x50, 0x00, 0x80, 0xd8, 0x1b, 0xd5, 0x10, 0x44, 0x50, +0x00, 0x81, 0xd8, 0x04, 0x49, 0xfd, 0x6a, 0xc1, 0xd5, 0x15, 0x44, 0x50, 0x00, 0x82, 0xd8, 0x04, +0x49, 0xfd, 0x67, 0xa9, 0xd5, 0x0f, 0x44, 0x50, 0x00, 0x80, 0xd8, 0x0b, 0x49, 0xfd, 0x60, 0xc7, +0xd5, 0x09, 0x49, 0xfd, 0x5a, 0x1c, 0x56, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x01, 0xd5, 0x02, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x54, 0x80, +0x00, 0xff, 0x3c, 0x10, 0x50, 0x40, 0x4e, 0x82, 0x00, 0x47, 0x54, 0x10, 0x80, 0x0f, 0xc1, 0x04, +0x84, 0xcc, 0x48, 0x00, 0x00, 0x64, 0x3e, 0x68, 0xa1, 0x8c, 0xb4, 0x06, 0xc8, 0x0d, 0xa6, 0x36, +0xe6, 0x02, 0xe8, 0x0a, 0x49, 0xfd, 0x30, 0x81, 0xb6, 0x06, 0xc8, 0x03, 0x84, 0xc7, 0xd5, 0x56, +0x84, 0x21, 0x10, 0x10, 0x00, 0xb5, 0x3e, 0x78, 0xa1, 0x8c, 0x00, 0x83, 0x80, 0x06, 0x3c, 0x20, +0x50, 0x40, 0x84, 0x21, 0x40, 0x10, 0xa0, 0x0c, 0x40, 0x10, 0x88, 0x04, 0x3c, 0x18, 0x50, 0x40, +0x84, 0x00, 0xae, 0x3c, 0x84, 0x01, 0x4c, 0x80, 0x40, 0x0d, 0x3c, 0x2d, 0xfc, 0x55, 0x44, 0x10, +0x10, 0x00, 0x84, 0x06, 0xdd, 0x22, 0xc8, 0x05, 0x10, 0x83, 0x80, 0x13, 0x80, 0xc0, 0xd5, 0x36, +0x3e, 0x68, 0xa1, 0x8c, 0x84, 0xe0, 0x84, 0x20, 0xb4, 0x66, 0x10, 0x73, 0x00, 0x13, 0x84, 0x02, +0x44, 0x23, 0xa1, 0x70, 0x84, 0x81, 0x80, 0xa1, 0x49, 0xfc, 0xa4, 0x7f, 0x10, 0x03, 0x00, 0x10, +0x84, 0xc0, 0xd5, 0x24, 0x3e, 0x78, 0xa1, 0x8c, 0xa6, 0xbe, 0x84, 0x61, 0x40, 0x21, 0x88, 0x0c, +0x40, 0x21, 0x08, 0x05, 0x40, 0x11, 0x04, 0x02, 0x3c, 0x18, 0x50, 0x40, 0x84, 0x02, 0xae, 0x3c, +0x3c, 0x0d, 0xff, 0x2b, 0xdd, 0x20, 0x80, 0xc0, 0xc0, 0x06, 0x10, 0x83, 0x80, 0x04, 0x80, 0x07, +0x49, 0xfd, 0x46, 0xcb, 0x2e, 0x10, 0xa1, 0x9f, 0xc1, 0x09, 0x84, 0x20, 0x3e, 0x10, 0xa1, 0x9f, +0x3c, 0x2d, 0xfc, 0x56, 0x84, 0x20, 0x84, 0x06, 0xdd, 0x22, 0x80, 0x06, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xc4, 0x44, 0x20, 0x20, 0x0d, 0x96, 0x49, 0x80, 0xa0, +0x4c, 0x11, 0x40, 0x83, 0x3e, 0x18, 0xa0, 0x78, 0x00, 0x30, 0x80, 0x10, 0x00, 0x20, 0x80, 0x0f, +0x87, 0x84, 0x98, 0x9a, 0x4c, 0x2e, 0x40, 0x04, 0x84, 0x09, 0xd5, 0x70, 0xa4, 0x4c, 0x54, 0x10, +0x80, 0x40, 0xc1, 0x03, 0x84, 0x0c, 0xd5, 0x6a, 0x9d, 0x83, 0x00, 0x03, 0x00, 0x17, 0xa6, 0x71, +0x01, 0xe3, 0x00, 0x03, 0x00, 0x93, 0x00, 0x0e, 0x00, 0x83, 0x00, 0x10, 0x00, 0x73, 0x00, 0x12, +0x00, 0x43, 0x00, 0x14, 0x00, 0x33, 0x00, 0x16, 0x00, 0x23, 0x00, 0x18, 0xf0, 0x85, 0x40, 0x94, +0xa0, 0x08, 0x01, 0xc3, 0x00, 0x0d, 0xa6, 0x30, 0x00, 0xa3, 0x00, 0x02, 0x15, 0xcf, 0x80, 0x00, +0x40, 0x84, 0x20, 0x08, 0x01, 0xc3, 0x00, 0x0f, 0x40, 0x73, 0xa0, 0x08, 0x15, 0xcf, 0x80, 0x01, +0x40, 0x42, 0x20, 0x08, 0x01, 0xc3, 0x00, 0x11, 0x40, 0x31, 0xa0, 0x08, 0x15, 0xcf, 0x80, 0x02, +0x41, 0xef, 0x20, 0x08, 0x01, 0xc3, 0x00, 0x13, 0x40, 0x21, 0x20, 0x08, 0x15, 0xcf, 0x80, 0x03, +0x89, 0x5e, 0x01, 0xc3, 0x00, 0x15, 0x8c, 0xa9, 0x15, 0xcf, 0x80, 0x04, 0x41, 0xc0, 0xa0, 0x08, +0x41, 0xce, 0x00, 0x00, 0xb4, 0x1f, 0x50, 0x1f, 0x80, 0x18, 0x89, 0x20, 0xf0, 0x01, 0x13, 0xc0, +0x80, 0x02, 0x89, 0x00, 0xf0, 0x02, 0x12, 0xa0, 0x80, 0x05, 0x99, 0xf8, 0xf0, 0x03, 0xb6, 0xa1, +0x99, 0x20, 0xf0, 0x04, 0x12, 0x90, 0x80, 0x04, 0x98, 0xd8, 0xf0, 0x05, 0x12, 0x80, 0x80, 0x03, +0x98, 0x90, 0xad, 0xce, 0xad, 0x0f, 0x12, 0x30, 0x80, 0x09, 0x12, 0x20, 0x80, 0x08, 0x80, 0x01, +0xa6, 0xb4, 0x10, 0x20, 0x80, 0x18, 0x01, 0xc3, 0x00, 0x05, 0x11, 0xc0, 0x80, 0x16, 0x00, 0x63, +0x00, 0x0c, 0x10, 0x60, 0x80, 0x15, 0x49, 0xfd, 0x34, 0xb4, 0x44, 0x10, 0x20, 0x0d, 0x49, 0xfb, +0xdb, 0x44, 0x84, 0x00, 0xd5, 0x03, 0x49, 0xfb, 0xd1, 0x9e, 0xec, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x2e, 0x40, 0x04, 0xd4, 0x81, 0x00, 0x3c, 0xad, +0xfd, 0x05, 0x54, 0x42, 0x00, 0x03, 0x84, 0x01, 0x12, 0x1f, 0x80, 0x02, 0x97, 0x91, 0x54, 0x91, +0x80, 0xff, 0x4c, 0x40, 0x40, 0x40, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xff, 0xfe, 0x16, 0x02, 0x7f, +0x80, 0x02, 0x44, 0x10, 0xff, 0xfc, 0x9d, 0xfb, 0x97, 0xf9, 0x4c, 0x60, 0xc0, 0x04, 0x9d, 0xfd, +0x97, 0xf9, 0x80, 0x26, 0x80, 0x08, 0x49, 0xff, 0xfd, 0xe2, 0x84, 0xa1, 0xd8, 0x2b, 0x54, 0x45, +0x01, 0xff, 0x3e, 0x08, 0xe0, 0x38, 0x95, 0x23, 0x99, 0x20, 0x54, 0x03, 0x80, 0x07, 0x84, 0x20, +0x40, 0x10, 0x80, 0x06, 0x80, 0x44, 0x3c, 0x0d, 0xfd, 0x05, 0x92, 0xe3, 0x99, 0xf9, 0x1a, 0x61, +0x00, 0x01, 0x98, 0x38, 0x44, 0x10, 0xff, 0xfc, 0x3c, 0x0f, 0xfd, 0x05, 0xaf, 0xd0, 0x9d, 0x63, +0x4c, 0x60, 0xc0, 0x0b, 0x10, 0x92, 0x80, 0x00, 0x46, 0x20, 0x04, 0x90, 0x04, 0x01, 0x00, 0x0e, +0x50, 0x52, 0x00, 0x08, 0xa8, 0x21, 0x02, 0x2f, 0x80, 0x02, 0x80, 0x05, 0x80, 0x28, 0x49, 0xfd, +0x77, 0xfa, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0xa6, 0x82, 0x80, 0xc0, 0x97, 0xc9, 0x84, 0x60, 0x9c, 0x53, 0x44, 0x20, 0xff, 0xfe, 0x49, 0xff, +0xff, 0xa2, 0x80, 0x06, 0x80, 0x27, 0x49, 0xfb, 0xc5, 0x6a, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x87, 0x81, 0x97, 0xe0, 0x80, 0xc1, 0x81, 0x22, +0x54, 0xa1, 0x80, 0xff, 0x97, 0x68, 0x81, 0x00, 0x4c, 0x7e, 0x40, 0x09, 0x96, 0x49, 0x44, 0x20, +0xff, 0xfd, 0x84, 0x60, 0x49, 0xff, 0xff, 0x87, 0xd5, 0x0b, 0x84, 0x0d, 0x4c, 0x70, 0x00, 0x2a, +0x44, 0x10, 0x00, 0x22, 0x4c, 0x70, 0x80, 0x4e, 0x84, 0x01, 0x4c, 0x70, 0x40, 0x62, 0x2e, 0x07, +0xf0, 0x61, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x70, +0x44, 0x30, 0x2b, 0xe8, 0x49, 0xfb, 0x96, 0x5b, 0x3c, 0xae, 0x0b, 0x0c, 0x3c, 0x9e, 0x0b, 0x09, +0x3c, 0x8e, 0x0b, 0x0f, 0x84, 0x01, 0x3c, 0x6e, 0x0b, 0x15, 0x3e, 0x07, 0xf0, 0x61, 0x3e, 0x00, +0x2a, 0xdd, 0x3c, 0x6e, 0x0b, 0x10, 0x3e, 0x00, 0x2a, 0xd9, 0x49, 0xfb, 0xb6, 0x10, 0xd5, 0x40, +0x3e, 0x4f, 0xf0, 0x62, 0xa6, 0x20, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, 0x00, 0x96, +0x58, 0x21, 0x04, 0x70, 0x44, 0x30, 0x2b, 0xfb, 0xb6, 0x9f, 0xf5, 0x81, 0x49, 0xfb, 0x96, 0x37, +0x3c, 0xae, 0x0b, 0x0d, 0xf5, 0x01, 0x3c, 0x9e, 0x0b, 0x0a, 0x3e, 0x08, 0x2a, 0xd4, 0x3c, 0x8e, +0x0b, 0x11, 0x10, 0x50, 0x00, 0x0a, 0x3c, 0x6e, 0x0b, 0x16, 0x84, 0x20, 0xb4, 0x9f, 0x11, 0xc0, +0x00, 0x03, 0xaf, 0xc7, 0xae, 0x60, 0x3c, 0x6e, 0x0b, 0x12, 0x49, 0xfb, 0xb5, 0x6a, 0xd5, 0x18, +0x3c, 0xae, 0x0b, 0x0e, 0x3c, 0x2e, 0x0b, 0x0b, 0x3c, 0x8e, 0x0b, 0x13, 0x3c, 0x6e, 0x0b, 0x17, +0x84, 0x40, 0x3e, 0x18, 0x2a, 0xd4, 0x3e, 0x27, 0xf0, 0x63, 0x10, 0x50, 0x80, 0x0c, 0x11, 0xc0, +0x80, 0x04, 0x10, 0x70, 0x80, 0x08, 0x3c, 0x6e, 0x0b, 0x14, 0x49, 0xfb, 0xb3, 0xc4, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0xd0, 0x96, 0x48, +0x44, 0x20, 0xff, 0xfc, 0x49, 0xff, 0xff, 0x0f, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x2e, 0x21, 0xf6, 0x11, 0x80, 0xc0, 0x84, 0x01, 0x80, 0xe1, +0x4c, 0x20, 0x40, 0x18, 0x84, 0x48, 0x9c, 0x37, 0x49, 0xfd, 0x77, 0x45, 0x50, 0x13, 0x80, 0x0a, +0x50, 0x03, 0x00, 0x12, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfd, 0x77, 0x3d, 0x00, 0x03, 0x80, 0x09, +0x00, 0x13, 0x80, 0x08, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x04, 0x04, 0x12, 0x03, 0x00, 0x08, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3e, 0x68, 0xad, 0x94, +0x02, 0x40, 0x00, 0x17, 0x02, 0x33, 0x00, 0x0c, 0x80, 0xe0, 0x84, 0x21, 0x84, 0x08, 0x44, 0x20, +0xb0, 0x02, 0x49, 0xfd, 0x18, 0xa4, 0x92, 0x00, 0x02, 0x03, 0x80, 0x17, 0x54, 0x00, 0x00, 0x03, +0xc8, 0x03, 0x84, 0x02, 0xd5, 0x08, 0x84, 0xa3, 0xd8, 0x05, 0xa0, 0xb6, 0x84, 0xa5, 0xd2, 0x04, +0xd5, 0x02, 0x84, 0x03, 0xa8, 0x36, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x37, 0x0c, 0x96, 0x4c, 0xc1, 0x58, 0x3c, 0x2c, 0x2a, 0xf7, +0x54, 0x21, 0x00, 0x80, 0xc2, 0x53, 0x2e, 0x10, 0xac, 0x7c, 0xc1, 0x50, 0xe6, 0x1a, 0xe8, 0x4e, +0x84, 0x21, 0x46, 0x30, 0x24, 0x80, 0x40, 0x10, 0x80, 0x0c, 0x40, 0x20, 0x8c, 0x02, 0xca, 0x05, +0x54, 0x10, 0x80, 0x82, 0xc9, 0x1f, 0xd5, 0x42, 0x46, 0x10, 0x04, 0xa0, 0x04, 0x20, 0x80, 0x92, +0x54, 0x31, 0x02, 0x00, 0xc3, 0x3b, 0x3c, 0x4c, 0x00, 0x06, 0x46, 0x30, 0x0c, 0x00, 0x58, 0x31, +0x88, 0x00, 0x96, 0x90, 0x50, 0x21, 0x01, 0x00, 0x40, 0x42, 0x0c, 0x04, 0x40, 0x42, 0x08, 0x04, +0x14, 0x40, 0x80, 0x92, 0x96, 0xc1, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x72, +0xd5, 0x22, 0x46, 0x10, 0x04, 0xa0, 0x04, 0x10, 0x80, 0x92, 0x54, 0x20, 0x82, 0x00, 0xc2, 0x1e, +0x96, 0x48, 0xc1, 0x03, 0x9e, 0x49, 0x96, 0x48, 0x3c, 0x4c, 0x00, 0x06, 0x46, 0x20, 0x0c, 0x00, +0x58, 0x21, 0x08, 0x00, 0x50, 0x10, 0x81, 0x00, 0x40, 0x42, 0x08, 0x04, 0x46, 0x20, 0x04, 0xa0, +0x40, 0x42, 0x04, 0x04, 0x14, 0x41, 0x00, 0x92, 0x96, 0xc1, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, +0x44, 0x20, 0x90, 0x73, 0x49, 0xfd, 0x18, 0x33, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x30, 0x80, 0x20, 0x3e, 0x09, +0xf8, 0x00, 0x49, 0xfd, 0x76, 0x94, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0x50, 0x60, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x2d, 0x4e, 0x72, +0x00, 0x8b, 0x00, 0x00, 0x00, 0x2c, 0x84, 0xad, 0xd8, 0x08, 0x3c, 0x1c, 0x28, 0x7c, 0xa6, 0x34, +0xdd, 0x21, 0x84, 0xa1, 0x4c, 0x02, 0x80, 0x80, 0x2e, 0x91, 0xf6, 0x18, 0xa0, 0x34, 0x00, 0xa3, +0x00, 0x06, 0x04, 0x00, 0x00, 0x0d, 0x4e, 0x92, 0x00, 0x0a, 0x2e, 0x91, 0xf6, 0x19, 0xa6, 0x74, +0x40, 0x94, 0x84, 0x03, 0x84, 0x20, 0x40, 0x90, 0xa4, 0x06, 0x84, 0xa1, 0xd0, 0x03, 0x84, 0xa3, +0xd8, 0x16, 0x4e, 0x93, 0x00, 0x65, 0x4e, 0xa3, 0x00, 0x0a, 0x46, 0x00, 0x04, 0x80, 0x58, 0x00, +0x0f, 0x80, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xd5, 0x08, 0x46, 0x00, 0x04, 0x80, 0x58, 0x00, +0x0f, 0x80, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x02, 0xb6, 0x20, 0xd5, 0x51, 0x85, 0x00, 0x84, 0x04, +0x80, 0x20, 0x44, 0x20, 0x30, 0x13, 0x80, 0x67, 0x80, 0x88, 0x49, 0xfd, 0x17, 0xd8, 0xa0, 0x34, +0xa6, 0x74, 0x00, 0x00, 0x00, 0x2c, 0x80, 0x47, 0x49, 0xfd, 0x24, 0x69, 0xc0, 0x15, 0xa0, 0xb4, +0x46, 0x10, 0x04, 0x80, 0x00, 0x21, 0x00, 0x2b, 0x10, 0x20, 0x00, 0x09, 0xb4, 0x00, 0x04, 0x10, +0x83, 0xe5, 0x80, 0x47, 0x49, 0xfd, 0x76, 0x33, 0xa0, 0x34, 0xa6, 0x74, 0x00, 0x00, 0x00, 0x2c, +0x49, 0xfd, 0x27, 0xf3, 0xd5, 0x06, 0x3c, 0x1d, 0xff, 0x31, 0x44, 0x00, 0x00, 0x99, 0xdd, 0x21, +0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x29, 0x4e, 0x92, 0x00, 0x0e, 0xa0, 0x34, 0x46, 0x10, 0x00, 0x90, +0x58, 0x10, 0x8f, 0x58, 0x4e, 0xa3, 0x00, 0x04, 0x8c, 0x10, 0xd5, 0x02, 0x8c, 0x18, 0xdd, 0x21, +0xd5, 0x1a, 0xa0, 0x34, 0x4e, 0xa3, 0x00, 0x0b, 0x46, 0x10, 0x04, 0x80, 0x04, 0x20, 0x83, 0xd2, +0xa8, 0x84, 0x04, 0x10, 0x83, 0xd3, 0xa8, 0x45, 0xd5, 0x0e, 0x46, 0x10, 0x04, 0x80, 0x04, 0x20, +0x83, 0xd4, 0xa8, 0x86, 0x04, 0x10, 0x83, 0xd5, 0xa8, 0x47, 0xd5, 0x05, 0x9f, 0xfc, 0x97, 0xf9, +0x85, 0x01, 0xd5, 0xae, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x97, 0x80, 0x80, 0xe1, 0x84, 0x01, 0x84, 0x20, 0x9c, 0xb5, 0x49, 0xfd, 0x24, 0x18, 0xc0, 0x1a, +0xb4, 0x40, 0x9c, 0x33, 0xae, 0x11, 0x84, 0x01, 0xae, 0x12, 0x44, 0x0f, 0xff, 0x9e, 0xae, 0x13, +0x84, 0x1c, 0x84, 0x6e, 0xae, 0x14, 0xae, 0xd0, 0x84, 0x60, 0x9c, 0x19, 0x98, 0x53, 0x38, 0x33, +0x8c, 0x00, 0xae, 0xcd, 0x96, 0xc0, 0xe2, 0xc3, 0xe8, 0xf9, 0x84, 0x01, 0x84, 0x20, 0x49, 0xfd, +0x27, 0x9c, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x97, 0x88, 0x81, 0x00, 0x81, 0x22, 0x84, 0x01, 0x84, 0x20, 0x9c, 0xb6, 0x97, 0xd9, 0x49, 0xfd, +0x23, 0xee, 0xc0, 0x18, 0xb4, 0x80, 0x9c, 0x74, 0x40, 0x03, 0xa0, 0x09, 0x84, 0x4e, 0xae, 0x61, +0x84, 0x21, 0xae, 0xa0, 0xae, 0x62, 0xae, 0x24, 0x10, 0x92, 0x00, 0x05, 0xaf, 0xe3, 0x80, 0x28, +0x9c, 0x26, 0x80, 0x46, 0x49, 0xfd, 0x75, 0xbf, 0x84, 0x01, 0x84, 0x20, 0x49, 0xfd, 0x27, 0x75, +0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x04, 0x10, +0x00, 0x0b, 0x80, 0xc0, 0x04, 0x00, 0x80, 0x0d, 0xc0, 0x16, 0xa0, 0x8c, 0x46, 0x00, 0x04, 0x80, +0x14, 0x20, 0x03, 0xd2, 0xa0, 0x8d, 0x14, 0x20, 0x03, 0xd3, 0xa0, 0x8e, 0x14, 0x20, 0x03, 0xd4, +0xa0, 0x4f, 0x14, 0x10, 0x03, 0xd5, 0x84, 0x21, 0x3e, 0x11, 0xf6, 0x18, 0x00, 0x13, 0x00, 0x20, +0x3e, 0x11, 0xf6, 0x19, 0x46, 0x00, 0x04, 0x80, 0x46, 0x10, 0x04, 0x25, 0x58, 0x10, 0x8e, 0x4c, +0x14, 0x10, 0x03, 0xe4, 0x3c, 0x0d, 0xff, 0xb7, 0xdd, 0x20, 0x49, 0xfd, 0x4c, 0x04, 0x92, 0x00, +0x3c, 0x4d, 0xff, 0x14, 0x00, 0x33, 0x00, 0x20, 0x84, 0x04, 0x44, 0x12, 0x00, 0x00, 0x44, 0x20, +0x30, 0x59, 0xdd, 0x24, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x97, 0xc0, 0x80, 0x07, 0x49, 0xfc, 0x50, 0x3f, 0x50, 0x60, 0x01, 0xe3, 0xc0, 0x37, 0x00, 0x00, +0x01, 0xea, 0x3e, 0x28, 0xda, 0x8c, 0xc8, 0x1b, 0x3c, 0x1c, 0x01, 0x04, 0x44, 0x00, 0x00, 0x30, +0x42, 0x13, 0x80, 0x73, 0x84, 0x02, 0xae, 0x10, 0x84, 0xa2, 0xa0, 0x09, 0xd8, 0x16, 0x04, 0x00, +0x80, 0x0a, 0x84, 0x25, 0x00, 0x30, 0x00, 0x31, 0x42, 0x01, 0x84, 0x73, 0x00, 0x00, 0x00, 0x35, +0xc0, 0x0c, 0x94, 0x0b, 0xae, 0x10, 0x2e, 0x00, 0x02, 0x5c, 0xd5, 0x06, 0x44, 0x00, 0x00, 0x28, +0xae, 0x10, 0xa6, 0x37, 0x9e, 0x01, 0xae, 0x37, 0x2e, 0x00, 0x04, 0xd2, 0xc0, 0x09, 0x49, 0xfc, +0x84, 0xa0, 0x84, 0xa2, 0xd8, 0x05, 0x44, 0x10, 0x00, 0x28, 0x3e, 0x10, 0xda, 0x8c, 0x3c, 0x0d, +0xff, 0xed, 0xdd, 0x20, 0xc0, 0x03, 0x84, 0x00, 0xae, 0x37, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xc4, 0x96, 0x49, 0x54, 0x20, 0x83, 0xff, 0xe6, 0x4e, +0xe9, 0x03, 0x84, 0x01, 0xd5, 0x2a, 0x50, 0x2f, 0x80, 0x04, 0x84, 0x80, 0x44, 0x50, 0x10, 0x04, +0xac, 0x50, 0xa9, 0x14, 0xd9, 0x20, 0x9c, 0xc3, 0xa6, 0x58, 0xc9, 0x05, 0x3e, 0x08, 0x03, 0xd4, +0xa8, 0x13, 0xd5, 0x0d, 0xe6, 0x23, 0xe8, 0x07, 0x94, 0x4b, 0x3e, 0x08, 0x03, 0xd4, 0x98, 0x48, +0xa8, 0x53, 0xd5, 0x05, 0x44, 0x00, 0x00, 0x30, 0xa9, 0x13, 0xa8, 0x14, 0xa6, 0xd8, 0x50, 0x0f, +0x80, 0x04, 0x84, 0x42, 0x10, 0x30, 0x00, 0x2c, 0x10, 0x20, 0x00, 0x2d, 0x49, 0xfb, 0xde, 0xef, +0x84, 0x00, 0xd5, 0x03, 0x49, 0xfb, 0xc2, 0x6d, 0xec, 0x3c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x00, 0x20, 0x01, 0xc7, 0x80, 0xc0, 0x9e, 0x92, 0x96, 0x08, +0x3e, 0x18, 0x5b, 0x84, 0xae, 0x88, 0x84, 0x44, 0xae, 0x89, 0x84, 0x42, 0xae, 0x8b, 0xae, 0x0a, +0xc8, 0x06, 0x9c, 0x4c, 0x84, 0x08, 0x3e, 0x28, 0x03, 0xd4, 0xd5, 0x07, 0xe6, 0x02, 0xe8, 0x08, +0x9c, 0x4c, 0x84, 0x08, 0x3e, 0x28, 0x03, 0xdc, 0x49, 0xfc, 0xa1, 0x53, 0xd5, 0x06, 0x9c, 0x0c, +0x84, 0x48, 0x84, 0x20, 0x49, 0xfd, 0x74, 0xf1, 0x00, 0x13, 0x01, 0xf8, 0x00, 0x03, 0x01, 0xae, +0x58, 0x10, 0x80, 0x02, 0x10, 0x13, 0x01, 0xf8, 0x3e, 0x28, 0x5b, 0x84, 0x44, 0x10, 0x7f, 0x04, +0x49, 0xfc, 0x1f, 0x87, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x04, 0x20, 0x00, 0x6c, 0x80, 0xe1, 0x56, 0x11, 0x00, 0x01, 0x00, 0x93, 0x80, 0x00, 0x00, 0x83, +0x80, 0x01, 0x10, 0x10, 0x01, 0xc7, 0x80, 0xc0, 0xa6, 0x78, 0x49, 0xff, 0xff, 0xbc, 0x84, 0xa1, +0x4c, 0x92, 0xc0, 0x08, 0x9c, 0xba, 0x84, 0x08, 0x50, 0x13, 0x01, 0x14, 0x49, 0xfc, 0xa1, 0x21, +0x02, 0x03, 0x00, 0xd1, 0x44, 0x50, 0x00, 0x8f, 0xd0, 0x04, 0x44, 0x50, 0x00, 0x39, 0xd8, 0x09, +0x4e, 0x83, 0x00, 0x08, 0x00, 0x03, 0x01, 0x14, 0x58, 0x00, 0x00, 0x01, 0x10, 0x03, 0x01, 0x14, +0x00, 0x13, 0x01, 0xf8, 0x84, 0x00, 0x58, 0x10, 0x80, 0x01, 0x10, 0x13, 0x01, 0xf8, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x00, 0x20, 0x01, 0xc7, 0x80, 0xc0, +0x9e, 0x92, 0x96, 0x08, 0x3e, 0x18, 0x5b, 0x78, 0xae, 0x88, 0x84, 0x43, 0xae, 0x89, 0x84, 0x42, +0xae, 0x8b, 0xae, 0x0a, 0xc8, 0x06, 0x9c, 0x4c, 0x84, 0x08, 0x3e, 0x28, 0x03, 0xd4, 0xd5, 0x07, +0xe6, 0x02, 0xe8, 0x08, 0x9c, 0x4c, 0x84, 0x08, 0x3e, 0x28, 0x03, 0xdc, 0x49, 0xfc, 0xa0, 0xe9, +0xd5, 0x06, 0x9c, 0x0c, 0x84, 0x48, 0x84, 0x20, 0x49, 0xfd, 0x74, 0x87, 0x00, 0x13, 0x01, 0xf8, +0x00, 0x03, 0x01, 0xae, 0x58, 0x10, 0x80, 0x02, 0x10, 0x13, 0x01, 0xf8, 0x3e, 0x28, 0x5b, 0x78, +0x44, 0x10, 0x7f, 0x03, 0x49, 0xfc, 0x1f, 0x1d, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x84, 0x00, 0x84, 0x28, 0x3e, 0x28, 0xcf, 0x94, 0x49, 0xfe, 0x19, 0x87, +0x2e, 0x01, 0xf6, 0x0d, 0x84, 0xa1, 0xd8, 0x06, 0x49, 0xff, 0xf9, 0xe1, 0x84, 0x00, 0x3e, 0x01, +0xf6, 0x0d, 0x84, 0x00, 0x3e, 0x68, 0xc3, 0x68, 0x49, 0xfe, 0x03, 0x43, 0x00, 0x13, 0x0c, 0x2c, +0x44, 0x50, 0x00, 0x20, 0x54, 0x00, 0x80, 0x60, 0xd0, 0x0b, 0x95, 0x69, 0xd0, 0x33, 0xc8, 0x39, +0x50, 0x13, 0x0c, 0x2c, 0x50, 0x03, 0x0c, 0x60, 0x49, 0xfe, 0x0a, 0x99, 0xd5, 0x37, 0x44, 0x00, +0x00, 0x2d, 0x49, 0xfe, 0x18, 0xa0, 0x00, 0x03, 0x0c, 0x2c, 0x50, 0x00, 0x7f, 0xe0, 0x96, 0x00, +0xe6, 0x02, 0xe8, 0x27, 0x00, 0x13, 0x0c, 0x30, 0x44, 0x00, 0x01, 0x5c, 0x42, 0x00, 0x80, 0x24, +0x3e, 0x28, 0xc3, 0x68, 0x98, 0x02, 0x04, 0x20, 0x00, 0x10, 0xc2, 0x11, 0x50, 0x03, 0x0c, 0x2c, +0xdd, 0x22, 0x00, 0x13, 0x0c, 0x30, 0x44, 0x00, 0x00, 0x14, 0x42, 0x00, 0x80, 0x24, 0x3e, 0x18, +0xda, 0x38, 0x98, 0x01, 0xa0, 0x04, 0x49, 0xfe, 0x03, 0x0c, 0xd5, 0x10, 0x84, 0x03, 0x84, 0x21, +0xd5, 0x0b, 0x50, 0x13, 0x0c, 0x2c, 0x50, 0x03, 0x0c, 0x60, 0x49, 0xfe, 0x06, 0x32, 0xd5, 0x06, +0x84, 0x03, 0x84, 0x21, 0x84, 0x40, 0x49, 0xfe, 0x29, 0x9e, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xc0, 0x40, 0x90, 0x80, 0x13, 0xc8, 0x02, +0xd5, 0x4e, 0x84, 0x02, 0x84, 0x20, 0x47, 0xc0, 0x01, 0x0e, 0x49, 0xfe, 0x1c, 0xd2, 0x3c, 0x00, +0x6d, 0x8f, 0x40, 0x24, 0x81, 0x37, 0x96, 0x91, 0x40, 0x94, 0x80, 0x13, 0xc2, 0x25, 0x46, 0x70, +0x04, 0x09, 0x58, 0x73, 0x80, 0x24, 0x85, 0x00, 0x44, 0x35, 0x64, 0x10, 0x81, 0x47, 0x3c, 0x00, +0x6d, 0x8f, 0xf2, 0x81, 0xb6, 0x7f, 0x80, 0x26, 0xdd, 0x23, 0x3c, 0x10, 0x6d, 0x8f, 0x84, 0x02, +0x42, 0x64, 0x04, 0x73, 0x49, 0xfe, 0x19, 0xd3, 0xb4, 0x7f, 0xf2, 0x01, 0xb4, 0x07, 0x42, 0x00, +0x04, 0x0b, 0xc0, 0xfd, 0xb4, 0x2a, 0x8d, 0x01, 0x58, 0x10, 0x80, 0x02, 0x40, 0x04, 0x00, 0x13, +0xb6, 0x2a, 0xe2, 0x02, 0xe9, 0xe5, 0x4e, 0x93, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x18, 0x80, 0x09, +0x80, 0x26, 0x49, 0xfe, 0x23, 0xce, 0x84, 0x02, 0x84, 0x20, 0x49, 0xfe, 0x19, 0x9c, 0x46, 0x00, +0x04, 0x09, 0x04, 0x20, 0x00, 0x09, 0x80, 0x20, 0x42, 0x21, 0x04, 0x0b, 0xc2, 0xfb, 0x04, 0x20, +0x80, 0x09, 0x84, 0x01, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x80, 0x09, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x81, 0x00, 0x84, 0x02, 0x80, 0xc1, +0x49, 0xff, 0xf9, 0x13, 0x84, 0xa1, 0xd8, 0x1f, 0x2e, 0x00, 0x05, 0x0f, 0x84, 0xa2, 0xd8, 0x3b, +0x3e, 0x08, 0x1e, 0x84, 0x84, 0x20, 0x44, 0x20, 0x00, 0x84, 0x49, 0xfd, 0x73, 0xa6, 0x3e, 0x78, +0x1e, 0x84, 0x40, 0x13, 0x40, 0x08, 0x44, 0x00, 0xfc, 0x6f, 0x98, 0x48, 0x80, 0x07, 0xaa, 0x41, +0x80, 0x46, 0x80, 0x28, 0x49, 0xfd, 0x73, 0x87, 0x9c, 0x74, 0x80, 0x07, 0x96, 0x49, 0x49, 0xff, +0xff, 0x82, 0xd5, 0x21, 0x84, 0x03, 0x49, 0xff, 0xf8, 0xf0, 0x84, 0xa1, 0xd8, 0x1c, 0x3c, 0x0d, +0xfb, 0xb1, 0xc0, 0x19, 0x3e, 0x08, 0x1e, 0x84, 0x84, 0x20, 0x44, 0x20, 0x00, 0x84, 0x49, 0xfd, +0x73, 0x84, 0x44, 0x00, 0xfc, 0x6f, 0x40, 0x13, 0x40, 0x08, 0x98, 0x48, 0x3e, 0x08, 0x1e, 0x84, +0xaa, 0x41, 0x80, 0x46, 0x80, 0x28, 0x49, 0xfd, 0x73, 0x66, 0x3c, 0x2d, 0xfb, 0xb1, 0x9c, 0x74, +0x84, 0x04, 0xdd, 0x22, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x2e, 0x20, +0xa0, 0x88, 0x2e, 0x10, 0xa0, 0x87, 0x98, 0x4a, 0x96, 0x48, 0x3c, 0x08, 0x6d, 0x89, 0xc9, 0x09, +0x2e, 0x10, 0x73, 0x2d, 0xc9, 0x06, 0x44, 0x10, 0xff, 0xfb, 0x40, 0x50, 0x04, 0x02, 0xd5, 0x03, +0x58, 0x50, 0x00, 0x04, 0x42, 0x62, 0xc4, 0x08, 0x44, 0x10, 0x20, 0x00, 0x84, 0x07, 0x44, 0x20, +0x90, 0x8c, 0x84, 0x60, 0x80, 0x86, 0x3c, 0x5e, 0x2a, 0x21, 0x49, 0xfd, 0x16, 0x94, 0x3c, 0x1c, +0x7d, 0x82, 0x4c, 0x13, 0x00, 0x0a, 0x3c, 0x2d, 0xfc, 0x07, 0x80, 0x26, 0x44, 0x00, 0x00, 0x4a, +0xdd, 0x22, 0x3c, 0x6e, 0x7d, 0x82, 0x3e, 0x69, 0xf6, 0x16, 0xa6, 0xb0, 0xc2, 0x07, 0x80, 0x06, +0x44, 0x10, 0x00, 0x64, 0x49, 0xfc, 0x9e, 0x69, 0xd5, 0x0e, 0x44, 0x00, 0x00, 0x64, 0x46, 0x10, +0x00, 0x90, 0x58, 0x10, 0x8e, 0x4c, 0x80, 0x62, 0x80, 0x82, 0x80, 0xa2, 0x49, 0xfc, 0x9e, 0x95, +0x92, 0x00, 0xae, 0x30, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x3e, 0x38, 0x72, 0x78, 0x96, 0x81, 0x3c, 0x28, 0x02, 0x3b, 0x12, 0x21, 0x80, 0x54, 0x50, 0x01, +0x80, 0xc4, 0x80, 0x22, 0x49, 0xfc, 0x9e, 0x49, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xfd, 0xa8, 0xcd, 0x84, 0x20, 0x3e, 0x10, +0xab, 0xfc, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, +0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, 0x7f, 0x0b, 0x3e, 0x28, 0x2a, 0x98, 0xa6, 0x11, 0x84, 0xa1, +0xd8, 0x07, 0x84, 0x60, 0xa6, 0x50, 0xae, 0xd1, 0x84, 0x00, 0x49, 0xfb, 0x89, 0x7a, 0x84, 0x03, +0x49, 0xfb, 0x72, 0xf7, 0xf0, 0x01, 0x49, 0xfb, 0x7f, 0x10, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, 0x7e, 0xef, +0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x51, 0x42, 0x10, 0xc4, 0x09, 0x14, 0x10, 0x00, 0x51, +0x3c, 0x2d, 0xfb, 0xa7, 0x84, 0x02, 0x84, 0x21, 0xdd, 0x22, 0x84, 0x60, 0x2e, 0x10, 0x2a, 0x98, +0x3e, 0x30, 0x2a, 0x99, 0x84, 0x00, 0x49, 0xfb, 0x89, 0x54, 0xf0, 0x01, 0x49, 0xfb, 0x7e, 0xed, +0x84, 0x01, 0x49, 0xfb, 0x83, 0xf6, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa0, 0xbc, 0x3c, 0x1c, 0x33, 0xee, 0x84, 0xa1, 0xd9, 0x05, 0x3c, 0x0c, 0x34, 0x06, 0xc0, 0x02, +0xdd, 0x20, 0x3e, 0x88, 0xc3, 0x68, 0x84, 0xc0, 0x14, 0x64, 0x03, 0x14, 0x14, 0x64, 0x03, 0x15, +0x44, 0x70, 0x00, 0x2c, 0x49, 0xfe, 0x27, 0x5d, 0x49, 0xfe, 0x17, 0xbb, 0x49, 0xfe, 0x0a, 0x2f, +0xd5, 0x07, 0x04, 0x10, 0x81, 0x1e, 0xc1, 0x02, 0xdd, 0x21, 0x9d, 0xb1, 0x97, 0xb0, 0x42, 0x13, +0x1c, 0x24, 0x00, 0x04, 0x0c, 0x84, 0x3e, 0x28, 0xc3, 0x68, 0x98, 0x4a, 0xe2, 0xc0, 0xe9, 0xf2, +0x84, 0xc0, 0x81, 0x02, 0x44, 0x70, 0x00, 0x2c, 0xd5, 0x07, 0x04, 0x00, 0x81, 0x3f, 0xc0, 0x02, +0xdd, 0x20, 0x9d, 0xb1, 0x97, 0xb0, 0x42, 0x13, 0x1c, 0x24, 0x00, 0x04, 0x0c, 0x85, 0x3e, 0x28, +0xc3, 0x68, 0x98, 0x4a, 0xe2, 0xc0, 0xe9, 0xf2, 0x84, 0xc0, 0x81, 0x02, 0x44, 0x70, 0x00, 0x2c, +0xd5, 0x07, 0x04, 0x00, 0x81, 0x8c, 0xc0, 0x02, 0xdd, 0x20, 0x9d, 0xb1, 0x97, 0xb0, 0x42, 0x13, +0x1c, 0x24, 0x00, 0x04, 0x0c, 0x86, 0x3e, 0x28, 0xc3, 0x68, 0x98, 0x4a, 0xe2, 0xc0, 0xe9, 0xf2, +0x84, 0xc0, 0x81, 0x02, 0x44, 0x70, 0x00, 0x2c, 0xd5, 0x07, 0x04, 0x00, 0x81, 0x97, 0xc0, 0x02, +0xdd, 0x20, 0x9d, 0xb1, 0x97, 0xb0, 0x42, 0x13, 0x1c, 0x24, 0x00, 0x04, 0x0c, 0x87, 0x3e, 0x28, +0xc3, 0x68, 0x98, 0x4a, 0xe2, 0xc0, 0xe9, 0xf2, 0x84, 0xc0, 0x81, 0x02, 0x44, 0x70, 0x00, 0x2c, +0xd5, 0x07, 0x04, 0x00, 0x81, 0xe4, 0xc0, 0x02, 0xdd, 0x20, 0x9d, 0xb1, 0x97, 0xb0, 0x42, 0x13, +0x1c, 0x24, 0x00, 0x04, 0x0c, 0x88, 0x3e, 0x28, 0xc3, 0x68, 0x98, 0x4a, 0xe2, 0xc0, 0xe9, 0xf2, +0x2e, 0x10, 0xd0, 0x21, 0x84, 0x00, 0x49, 0xfb, 0x88, 0xcc, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x97, 0xc9, 0x9c, 0x03, 0x80, 0x3f, +0x49, 0xff, 0xf1, 0x33, 0xa6, 0xb2, 0x80, 0x06, 0x9c, 0x53, 0x84, 0x60, 0x44, 0x20, 0xff, 0xfe, +0x49, 0xff, 0xf9, 0xd9, 0x44, 0x50, 0x08, 0x0b, 0x81, 0x1f, 0xdf, 0x10, 0x80, 0x1f, 0x49, 0xfc, +0x4d, 0x3c, 0x02, 0x10, 0x00, 0xd1, 0x44, 0x50, 0x00, 0x39, 0xd9, 0x08, 0x02, 0x00, 0x00, 0xd2, +0x44, 0x50, 0x05, 0x28, 0xd8, 0x03, 0x84, 0x0c, 0xd5, 0x05, 0x80, 0x06, 0x80, 0x27, 0x49, 0xfb, +0xc1, 0x48, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0xa0, 0x82, 0x80, 0xc0, 0x9c, 0x54, 0xa7, 0x49, 0xa6, 0xca, 0xa7, 0x14, 0x40, 0x52, 0xa0, 0x08, +0xa6, 0x4b, 0x40, 0x31, 0xc0, 0x08, 0x98, 0xeb, 0x98, 0xdc, 0x40, 0x10, 0xe0, 0x08, 0x98, 0xd9, +0x94, 0xde, 0x92, 0x68, 0x94, 0xda, 0x3c, 0x1c, 0x1c, 0xd8, 0x40, 0x41, 0xc8, 0x09, 0x40, 0x51, +0x88, 0x09, 0x92, 0x6a, 0x10, 0x50, 0x81, 0xa8, 0x10, 0x30, 0x81, 0xa9, 0x10, 0x40, 0x81, 0xaa, +0x00, 0x31, 0x00, 0x08, 0x10, 0x30, 0x81, 0xab, 0x00, 0x41, 0x00, 0x0a, 0x00, 0x31, 0x00, 0x09, +0x40, 0x22, 0x20, 0x08, 0x98, 0x93, 0x96, 0x91, 0x40, 0x31, 0x20, 0x09, 0x10, 0x30, 0x81, 0xad, +0x10, 0x20, 0x81, 0xac, 0x2e, 0x71, 0xf6, 0x0e, 0x84, 0x21, 0x4c, 0x70, 0xc0, 0x16, 0x3c, 0x1c, +0x1c, 0xd8, 0x84, 0x46, 0x50, 0x10, 0x81, 0xa8, 0x3e, 0x09, 0xf6, 0xb8, 0x49, 0xfd, 0x71, 0xc3, +0x84, 0x40, 0x80, 0x07, 0x46, 0x10, 0x00, 0x92, 0x58, 0x10, 0x81, 0x34, 0x80, 0x62, 0x80, 0x82, +0x80, 0xa7, 0x49, 0xfc, 0x9d, 0x32, 0xa0, 0x32, 0x9c, 0x06, 0x3e, 0x68, 0x73, 0x40, 0xa7, 0x07, +0xa6, 0xc5, 0xa6, 0x86, 0x84, 0x00, 0xae, 0x30, 0x04, 0x13, 0x00, 0x08, 0x40, 0x02, 0x40, 0x08, +0x40, 0x21, 0x20, 0x08, 0x98, 0x90, 0x00, 0x00, 0x81, 0xae, 0x98, 0x93, 0x50, 0x10, 0x81, 0xa8, +0x49, 0xfb, 0xfe, 0x1d, 0x84, 0x00, 0x14, 0x03, 0x00, 0x08, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, +0xb4, 0x20, 0x42, 0x10, 0xcc, 0x0b, 0xc1, 0x05, 0xb4, 0x20, 0x42, 0x10, 0xcc, 0x09, 0xd5, 0x04, +0xb4, 0x20, 0x42, 0x10, 0xcc, 0x08, 0xb6, 0x20, 0x84, 0x00, 0x49, 0xfc, 0x95, 0xe2, 0x92, 0x00, +0x84, 0x20, 0x3e, 0x11, 0xf6, 0x0e, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x3e, 0x79, 0xf7, 0xa4, 0x81, 0x20, 0x84, 0xc0, 0xa6, 0x38, 0xc0, 0x07, +0x50, 0x03, 0x80, 0x11, 0x80, 0x29, 0x49, 0xfc, 0x9d, 0xae, 0xc8, 0x06, 0x9d, 0xb1, 0x97, 0xb0, +0x84, 0xa4, 0x8c, 0xf7, 0xde, 0xf4, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3e, 0x09, 0xf6, 0xb8, 0x49, 0xff, 0xff, 0xe1, +0xe6, 0x04, 0xe8, 0x03, 0x49, 0xff, 0xff, 0xbf, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x69, 0xf7, 0xa4, 0x81, 0x00, 0xa6, 0x30, 0xc0, 0x10, +0x50, 0x03, 0x00, 0x11, 0x80, 0x28, 0x49, 0xfc, 0x9d, 0x86, 0xc0, 0x0a, 0x2e, 0x11, 0xf6, 0x1d, +0x84, 0x40, 0x9e, 0x49, 0xae, 0xb0, 0x3e, 0x11, 0xf6, 0x1d, 0x84, 0x00, 0xd5, 0x07, 0x8c, 0xd7, +0x3e, 0x59, 0xf8, 0x00, 0xde, 0xec, 0x44, 0x00, 0x00, 0x12, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xc1, 0xa6, 0x49, 0x80, 0xe0, 0x44, 0x00, +0x00, 0xff, 0x4c, 0x10, 0x40, 0x31, 0x2e, 0x21, 0xf6, 0x11, 0x84, 0xa1, 0xda, 0x1a, 0xa6, 0x30, +0x8c, 0xb6, 0xd8, 0x29, 0x3e, 0x19, 0xf5, 0x6c, 0x00, 0x53, 0x00, 0x09, 0xa6, 0x08, 0xd8, 0x23, +0x00, 0x53, 0x00, 0x0a, 0xa6, 0x09, 0xd8, 0x1f, 0x00, 0x53, 0x00, 0x0b, 0xa6, 0x0a, 0xd8, 0x1b, +0xa6, 0x0b, 0x00, 0x53, 0x00, 0x0c, 0xd8, 0x17, 0xa7, 0xb4, 0x80, 0x02, 0xaf, 0xb8, 0xd5, 0x14, +0x84, 0xa2, 0xda, 0x11, 0xa6, 0x30, 0x8c, 0xb1, 0xd8, 0x0e, 0x50, 0x03, 0x00, 0x08, 0x3e, 0x18, +0x03, 0xb0, 0x49, 0xfc, 0x9d, 0x40, 0x92, 0x00, 0xc0, 0x06, 0x00, 0x63, 0x00, 0x0e, 0x84, 0x01, +0xaf, 0xb8, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x3e, 0x79, 0xf6, 0x30, 0x81, 0x20, 0x84, 0xc0, 0xa6, 0x38, 0xc0, 0x06, +0x9c, 0x39, 0x80, 0x29, 0x49, 0xfc, 0x9d, 0x27, 0xc8, 0x07, 0x9d, 0xb1, 0x97, 0xb0, 0x84, 0xa4, +0x50, 0x73, 0x80, 0x22, 0xde, 0xf4, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x69, 0xf6, 0x30, 0x81, 0x00, 0xa6, 0x30, 0xc0, 0x0f, +0x9c, 0x31, 0x80, 0x28, 0x49, 0xfc, 0x9d, 0x0f, 0xc0, 0x0a, 0x2e, 0x11, 0xf6, 0x1c, 0x84, 0x40, +0x9e, 0x49, 0xae, 0xb0, 0x3e, 0x11, 0xf6, 0x1c, 0x84, 0x00, 0xd5, 0x08, 0x50, 0x63, 0x00, 0x22, +0x3e, 0x59, 0xf6, 0xb8, 0xde, 0xec, 0x44, 0x00, 0x00, 0x12, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x49, 0xff, 0xff, 0xdd, 0xc0, 0x04, 0x80, 0x06, +0x49, 0xff, 0xff, 0x61, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x3e, 0x79, 0xf7, 0xa4, 0x81, 0x20, 0x81, 0x41, 0x81, 0x02, 0x80, 0xc7, 0x45, 0xc2, 0x5c, 0x74, +0xa6, 0x38, 0xc0, 0x0e, 0x50, 0x03, 0x80, 0x11, 0x80, 0x29, 0xdd, 0x3c, 0xc0, 0x09, 0x9c, 0x39, +0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfd, 0x70, 0x96, 0x84, 0x00, 0xd5, 0x23, 0x8c, 0xf7, +0x3e, 0x59, 0xf8, 0x00, 0xdf, 0xee, 0xa7, 0xf0, 0xcf, 0x18, 0x44, 0x20, 0x00, 0x10, 0x80, 0x2a, +0x9c, 0x31, 0x49, 0xfd, 0x70, 0x88, 0x80, 0x29, 0x50, 0x03, 0x00, 0x11, 0x49, 0xfc, 0x9c, 0xb9, +0x46, 0x00, 0x01, 0x20, 0x2e, 0x11, 0xf6, 0x1d, 0x84, 0x41, 0x9c, 0x49, 0xae, 0xb0, 0x3e, 0x11, +0xf6, 0x1d, 0x14, 0x74, 0x00, 0x04, 0xd5, 0x08, 0x8c, 0xd7, 0x3e, 0x59, 0xf8, 0x00, 0xde, 0xe4, +0x84, 0x07, 0x14, 0x04, 0x00, 0x04, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0x3e, 0x79, 0xf6, 0x30, 0x81, 0x00, 0x81, 0x21, 0x80, 0xc7, 0xa6, 0x38, 0xc0, 0x0c, +0x9c, 0x39, 0x80, 0x28, 0x49, 0xfc, 0x9c, 0x9f, 0xc0, 0x07, 0x80, 0x07, 0x80, 0x29, 0x49, 0xff, +0xf9, 0x0a, 0x84, 0x00, 0xd5, 0x22, 0x50, 0x73, 0x80, 0x22, 0x3e, 0x59, 0xf6, 0xb8, 0xdf, 0xef, +0xa7, 0xf0, 0xcf, 0x15, 0x80, 0x29, 0x80, 0x06, 0x49, 0xff, 0xf8, 0xfd, 0x80, 0x28, 0x9c, 0x31, +0x49, 0xfc, 0x9c, 0x7f, 0x92, 0x00, 0x46, 0x10, 0x01, 0x20, 0x2e, 0x01, 0xf6, 0x1c, 0x84, 0x41, +0x9c, 0x01, 0xae, 0xb0, 0x3e, 0x01, 0xf6, 0x1c, 0x80, 0x07, 0xd5, 0x07, 0x50, 0x63, 0x00, 0x22, +0x3e, 0x59, 0xf6, 0xb8, 0xde, 0xe6, 0x84, 0x07, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x80, 0xc2, 0x49, 0xff, 0xff, 0xc5, 0x92, 0x00, 0xa8, 0x34, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xa7, 0x40, 0x84, 0x41, 0xda, 0x04, 0x98, 0x02, +0x49, 0xff, 0xf3, 0xdd, 0x44, 0x00, 0xfc, 0xc5, 0x84, 0x20, 0x49, 0xfb, 0xe7, 0x40, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x50, 0x80, 0x00, 0x05, 0x80, 0xc0, +0x00, 0x04, 0x00, 0x00, 0x8e, 0x10, 0x96, 0x00, 0x5c, 0xf0, 0x00, 0xef, 0xe8, 0x10, 0x49, 0xff, +0xf1, 0x54, 0x92, 0x00, 0xa6, 0x32, 0xa6, 0x71, 0x40, 0x00, 0x20, 0x08, 0x98, 0x01, 0x96, 0x01, +0x49, 0xff, 0xfc, 0xed, 0x44, 0x00, 0xfc, 0x79, 0x84, 0x20, 0xd5, 0x2b, 0xa6, 0x30, 0x3e, 0x78, +0x03, 0xb0, 0x10, 0x03, 0x80, 0xc9, 0xa6, 0x32, 0xa6, 0x71, 0x40, 0x00, 0x20, 0x08, 0x98, 0x01, +0x96, 0x01, 0x49, 0xff, 0xfc, 0xdc, 0x2e, 0x10, 0xda, 0xd2, 0x9d, 0xb4, 0x44, 0x00, 0x00, 0x30, +0x42, 0x00, 0x80, 0x24, 0xa6, 0x70, 0x10, 0x13, 0x81, 0x51, 0x3e, 0x18, 0x79, 0xd8, 0xa7, 0xb0, +0x98, 0x01, 0x10, 0x60, 0x00, 0x25, 0x00, 0x24, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x7c, 0x95, 0x12, +0x99, 0x20, 0x3e, 0x40, 0x02, 0x7b, 0x10, 0x23, 0x80, 0xcd, 0x44, 0x00, 0xfc, 0x79, 0x84, 0x20, +0x49, 0xfb, 0xe6, 0xf5, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0xa6, 0x01, 0x84, 0xa4, 0xd0, 0x39, 0xe6, 0x05, 0xe8, 0x08, 0x84, 0xa2, 0xd0, 0x1d, 0xe6, 0x03, +0xe8, 0x27, 0x84, 0xa1, 0xd8, 0x62, 0xd5, 0x0c, 0x84, 0x26, 0x4c, 0x00, 0x80, 0x45, 0xe2, 0x01, +0xe9, 0x37, 0x84, 0xa8, 0xd0, 0x4f, 0x44, 0x50, 0x00, 0xff, 0xd8, 0x57, 0xd5, 0x47, 0x3e, 0x08, +0xab, 0xdc, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, +0x44, 0x10, 0x01, 0xb0, 0xd5, 0x55, 0x3e, 0x08, 0xab, 0xdc, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, +0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x01, 0x20, 0xd5, 0x49, 0x3e, 0x08, +0xab, 0xdc, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, +0x44, 0x10, 0x00, 0xd8, 0xd5, 0x3d, 0x3e, 0x08, 0xab, 0xdc, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, +0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0xb4, 0xd5, 0x31, 0x3e, 0x08, +0xab, 0xdc, 0x8c, 0x32, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, +0x00, 0x90, 0xd5, 0x26, 0x3e, 0x08, 0xab, 0xdc, 0x8c, 0x32, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, +0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0x6c, 0xd5, 0x1b, 0x84, 0x24, 0x3c, 0x1e, 0x2b, 0x24, +0xd5, 0x19, 0x3e, 0x08, 0xab, 0xdc, 0x8c, 0x3e, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, +0x00, 0x2d, 0x44, 0x10, 0x00, 0x48, 0xd5, 0x0c, 0x3e, 0x08, 0xab, 0xdc, 0x44, 0x10, 0x00, 0x24, +0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0x60, 0x12, 0x10, +0x00, 0x56, 0x44, 0x00, 0xfc, 0x22, 0x84, 0x20, 0x49, 0xfb, 0xe6, 0x71, 0x92, 0x00, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xc0, 0x80, 0xc0, 0xa6, 0x00, +0x84, 0xa1, 0xd0, 0x16, 0xc0, 0x08, 0x84, 0xa2, 0xd0, 0x1e, 0x84, 0xa3, 0x50, 0x7f, 0x80, 0x04, +0xd8, 0x2d, 0xd5, 0x20, 0x50, 0x7f, 0x80, 0x38, 0x80, 0x27, 0x9c, 0x31, 0x49, 0xff, 0xee, 0x3d, +0x80, 0x07, 0x9c, 0x77, 0x50, 0x2f, 0x80, 0x04, 0x49, 0xff, 0xfe, 0xfb, 0xd5, 0x21, 0x50, 0x7f, +0x80, 0x38, 0x9c, 0x31, 0x80, 0x27, 0x49, 0xff, 0xee, 0x30, 0x80, 0x07, 0x49, 0xff, 0xfe, 0x6b, +0xf0, 0x85, 0xd5, 0x16, 0x49, 0xff, 0xef, 0x9d, 0x84, 0x00, 0x50, 0x1f, 0x80, 0x04, 0xa8, 0x0c, +0xd5, 0x0f, 0x50, 0x8f, 0x80, 0x38, 0x80, 0x28, 0x9c, 0x31, 0x49, 0xff, 0xee, 0x1e, 0x80, 0x08, +0x9c, 0x77, 0x80, 0x47, 0x49, 0xff, 0xfe, 0x63, 0xd5, 0x03, 0x84, 0x01, 0xa8, 0x3c, 0xf1, 0x05, +0x44, 0x00, 0xfc, 0xf3, 0x49, 0xfb, 0xe6, 0x2b, 0xec, 0x40, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xdc, 0x46, 0x50, 0x00, 0x96, 0x58, 0x52, 0x85, 0x60, +0x80, 0xc0, 0x3a, 0x02, 0x8c, 0x04, 0x50, 0x4f, 0x80, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x80, 0x64, +0x2e, 0x40, 0x05, 0x24, 0x3a, 0x02, 0x88, 0x00, 0x54, 0x72, 0x00, 0x03, 0x40, 0x92, 0x10, 0x09, +0x3a, 0x01, 0x88, 0x20, 0x84, 0x20, 0x3e, 0x10, 0x2b, 0x19, 0x84, 0x21, 0x3e, 0x10, 0x2b, 0x1a, +0x46, 0x00, 0x00, 0x96, 0x58, 0x00, 0x05, 0xac, 0x38, 0x80, 0x1e, 0x02, 0x40, 0x52, 0x18, 0x09, +0x46, 0x00, 0x00, 0x96, 0x58, 0x00, 0x05, 0xbc, 0x54, 0x42, 0x00, 0x0c, 0x38, 0x72, 0x00, 0x02, +0x54, 0x94, 0x80, 0x03, 0x46, 0x00, 0x00, 0x96, 0x58, 0x00, 0x05, 0xcc, 0x38, 0x40, 0x26, 0x02, +0xe6, 0xa4, 0xe9, 0x03, 0x84, 0x62, 0xd5, 0x07, 0x46, 0x00, 0x00, 0x96, 0x58, 0x00, 0x05, 0xdc, +0x38, 0x30, 0x16, 0x02, 0x50, 0x1f, 0x80, 0x04, 0xb6, 0xc1, 0x14, 0x80, 0x80, 0x01, 0xa9, 0xca, +0xa9, 0x0b, 0xa8, 0xcc, 0x84, 0x00, 0x49, 0xfd, 0xfb, 0xe4, 0x2e, 0x00, 0x2b, 0x19, 0x44, 0x11, +0xc2, 0x00, 0x49, 0xff, 0xf1, 0x5e, 0x84, 0x00, 0x80, 0x20, 0x80, 0x40, 0x80, 0x80, 0x46, 0x30, +0x00, 0x92, 0x58, 0x31, 0x87, 0x34, 0x49, 0xfb, 0x6f, 0x32, 0x84, 0x00, 0x49, 0xfb, 0x6e, 0xb9, +0xec, 0x24, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x06, 0x44, 0x11, 0x00, 0x01, 0x40, 0x00, +0x04, 0x04, 0xb6, 0x06, 0x84, 0x01, 0x49, 0xfb, 0x80, 0x3c, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, +0x80, 0x1c, 0xb4, 0x41, 0x92, 0x48, 0x40, 0x21, 0x20, 0x08, 0xb6, 0x41, 0x84, 0x01, 0xb4, 0x41, +0x58, 0x21, 0x00, 0x30, 0xb6, 0x41, 0x49, 0xff, 0xed, 0xb6, 0xb4, 0x26, 0x84, 0x05, 0x42, 0x10, +0xc4, 0x08, 0xb6, 0x26, 0x49, 0xfb, 0x80, 0x25, 0xb4, 0x26, 0x42, 0x10, 0xc0, 0x09, 0xb6, 0x26, +0x84, 0x02, 0x49, 0xfb, 0x80, 0x1e, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x53, 0x46, 0x20, +0x01, 0x80, 0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0x53, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x2e, 0x67, 0xf0, 0x6a, 0xc6, 0x0b, 0x84, 0xa2, +0x84, 0x00, 0x3e, 0x57, 0xf0, 0x6a, 0x80, 0x20, 0x94, 0xac, 0x80, 0x60, 0x49, 0xfb, 0x84, 0xd3, +0xd5, 0x0e, 0x84, 0x03, 0x49, 0xfb, 0x7f, 0xfd, 0x80, 0x06, 0x80, 0x26, 0x44, 0x20, 0x00, 0x1e, +0x80, 0x66, 0x49, 0xfb, 0x84, 0xc8, 0x80, 0x06, 0x49, 0xfb, 0x6f, 0x8d, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x44, 0x05, +0xd4, 0xac, 0x38, 0x80, 0x1a, 0x02, 0x44, 0x50, 0x00, 0x63, 0x81, 0x21, 0xde, 0x03, 0x84, 0x00, +0xd5, 0x49, 0x9c, 0x29, 0x49, 0xfb, 0x7f, 0xdd, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x08, +0x84, 0x22, 0x84, 0x48, 0x49, 0xfe, 0x32, 0x47, 0x44, 0x20, 0x00, 0x88, 0x44, 0x40, 0x00, 0x11, +0x42, 0x23, 0x08, 0x24, 0x42, 0x43, 0x10, 0x24, 0x3c, 0x3c, 0x37, 0x16, 0x3e, 0x58, 0xc2, 0xd4, +0x98, 0x95, 0x9d, 0x21, 0x84, 0xe1, 0x84, 0x0c, 0xa9, 0xd1, 0x42, 0x33, 0x00, 0x73, 0x38, 0x92, +0x93, 0x0a, 0x50, 0x11, 0x00, 0x48, 0xb4, 0xa3, 0x50, 0x01, 0x00, 0x34, 0x84, 0x80, 0xb6, 0xa0, +0xad, 0x0b, 0xad, 0x0a, 0x50, 0x44, 0x00, 0x04, 0xa4, 0xda, 0x8d, 0x08, 0xac, 0xcc, 0x44, 0x15, +0x1c, 0x70, 0xb4, 0x00, 0x14, 0x01, 0x00, 0x15, 0x84, 0x07, 0x12, 0x04, 0x00, 0x00, 0x84, 0x0d, +0xac, 0x20, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x88, 0x84, 0x00, 0x49, 0xfb, 0x6f, 0xcf, +0x84, 0x00, 0x80, 0x20, 0x49, 0xfb, 0x6f, 0x13, 0x84, 0x00, 0x49, 0xfb, 0x6f, 0x34, 0x92, 0x00, +0x80, 0x07, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x2e, 0x61, 0xf6, 0x15, 0xce, 0x3a, 0x3c, 0x6f, 0xfe, 0x15, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, +0x80, 0x48, 0x44, 0x30, 0xf0, 0xf0, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x80, 0x48, 0x80, 0x01, +0x04, 0x10, 0x00, 0x4a, 0x3e, 0x78, 0x05, 0x08, 0x42, 0x10, 0xfc, 0x08, 0x14, 0x10, 0x00, 0x4a, +0x44, 0x01, 0xc2, 0x00, 0x14, 0x03, 0x80, 0x08, 0x10, 0x63, 0x80, 0x1c, 0x49, 0xfd, 0xfa, 0x95, +0x80, 0x06, 0x49, 0xfd, 0xf8, 0xec, 0x46, 0x90, 0x00, 0x92, 0x58, 0x94, 0x87, 0x78, 0x3e, 0x2f, +0xf8, 0x58, 0xb7, 0x22, 0x80, 0x26, 0x80, 0x06, 0x49, 0xfd, 0xfb, 0x9b, 0x84, 0x21, 0x80, 0x06, +0xdd, 0x29, 0x49, 0xfd, 0xf5, 0xc2, 0x49, 0xfd, 0xf5, 0xa8, 0x04, 0x03, 0x80, 0x08, 0x49, 0xff, +0xfe, 0xaa, 0x84, 0x01, 0x3e, 0x01, 0xf6, 0x15, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xe4, 0x49, 0xff, 0xff, 0xb9, 0x92, 0x00, 0x2e, 0x01, +0xf6, 0x15, 0x84, 0xa1, 0xd8, 0x23, 0x46, 0x00, 0x00, 0x96, 0x58, 0x00, 0x05, 0x54, 0x3a, 0x00, +0x08, 0x00, 0x50, 0x3f, 0x80, 0x0c, 0x80, 0x83, 0x3a, 0x02, 0x04, 0x24, 0x80, 0x23, 0xac, 0xa0, +0x2e, 0x00, 0x2b, 0x19, 0x84, 0x4a, 0x49, 0xfd, 0xf4, 0x80, 0x46, 0x00, 0x00, 0x96, 0x58, 0x00, +0x05, 0x48, 0x3a, 0x00, 0x08, 0x00, 0x80, 0x9f, 0x3a, 0x02, 0x04, 0x24, 0x80, 0x3f, 0xac, 0xa0, +0x2e, 0x00, 0x2b, 0x19, 0x84, 0x4a, 0x49, 0xfd, 0xf4, 0x70, 0xec, 0x1c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x00, 0x04, 0x05, 0x44, 0x10, 0xff, 0xff, +0x14, 0x10, 0x01, 0xec, 0x49, 0xfe, 0x14, 0x09, 0x84, 0xa2, 0xd0, 0x1b, 0x49, 0xfe, 0x14, 0x05, +0x84, 0xa3, 0xd8, 0x0c, 0x46, 0x00, 0x04, 0x03, 0x04, 0x10, 0x01, 0xad, 0x92, 0x28, 0x40, 0x10, +0xa0, 0x08, 0x58, 0x10, 0x80, 0x3f, 0x14, 0x10, 0x01, 0xad, 0x46, 0x00, 0x04, 0x04, 0x58, 0x00, +0x04, 0x40, 0xb4, 0x20, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, 0x58, 0x10, 0x80, 0x3f, 0xd5, 0x0b, +0x46, 0x00, 0x04, 0x04, 0x58, 0x00, 0x04, 0x40, 0xb4, 0x20, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, +0x58, 0x10, 0x80, 0x50, 0xb6, 0x20, 0x49, 0xfe, 0x13, 0xe0, 0x84, 0xa3, 0xd8, 0x17, 0x46, 0x10, +0x04, 0x03, 0x04, 0x20, 0x81, 0x2c, 0x92, 0x48, 0x40, 0x21, 0x20, 0x08, 0x58, 0x21, 0x00, 0x14, +0x14, 0x20, 0x81, 0x2c, 0x80, 0x01, 0x04, 0x10, 0x01, 0x28, 0x44, 0x4f, 0x00, 0xff, 0x40, 0x10, +0x90, 0x02, 0x58, 0x10, 0x86, 0x00, 0x14, 0x10, 0x01, 0x28, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, +0x81, 0xdf, 0x92, 0x48, 0x40, 0x21, 0x20, 0x08, 0x58, 0x21, 0x00, 0x14, 0x14, 0x20, 0x81, 0xdf, +0x80, 0x01, 0x04, 0x10, 0x01, 0xc0, 0x44, 0x2f, 0x00, 0xff, 0x40, 0x10, 0x88, 0x02, 0x58, 0x10, +0x8d, 0x00, 0x14, 0x10, 0x01, 0xc0, 0x49, 0xfe, 0x13, 0xb0, 0x84, 0xa3, 0xd8, 0x09, 0x46, 0x00, +0x04, 0x03, 0x04, 0x10, 0x01, 0x04, 0x42, 0x10, 0x88, 0x09, 0x14, 0x10, 0x01, 0x04, 0x46, 0x00, +0x04, 0x04, 0x04, 0x10, 0x01, 0x01, 0x58, 0x10, 0xe0, 0x00, 0x14, 0x10, 0x01, 0x01, 0x49, 0xfe, +0x13, 0x9c, 0x84, 0xa3, 0xd8, 0x2f, 0x46, 0x20, 0x04, 0x03, 0x58, 0x21, 0x06, 0x10, 0xb4, 0x02, +0x92, 0x02, 0x94, 0x02, 0xb6, 0x02, 0x50, 0x6f, 0x80, 0x04, 0xb4, 0x62, 0x80, 0x26, 0x58, 0x31, +0x83, 0x00, 0xb6, 0x62, 0x44, 0x00, 0x01, 0x37, 0x84, 0x41, 0x49, 0xfd, 0xf3, 0x62, 0xa6, 0x70, +0x9e, 0x09, 0x96, 0x00, 0xe6, 0x1f, 0xe8, 0x11, 0x46, 0x00, 0x04, 0x03, 0x04, 0x20, 0x01, 0x03, +0x46, 0x3f, 0xfe, 0x0f, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0xc0, 0x08, 0x40, 0x21, 0x0c, 0x02, +0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x01, 0x03, 0x46, 0x00, 0x04, 0x03, 0x84, 0x21, 0x14, 0x10, +0x01, 0x8a, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, 0x0b, 0x14, 0xb4, 0x20, 0x44, 0x4f, 0xff, 0x9f, +0x58, 0x10, 0x80, 0x18, 0xb6, 0x20, 0xb4, 0x20, 0x46, 0x30, 0x04, 0x05, 0x40, 0x10, 0x90, 0x02, +0x58, 0x10, 0x80, 0x20, 0xb6, 0x20, 0xb4, 0x80, 0x80, 0x43, 0x42, 0x42, 0x1c, 0x09, 0xb6, 0x80, +0xb4, 0x80, 0x95, 0x25, 0x92, 0x85, 0x42, 0x42, 0x78, 0x08, 0xb6, 0x80, 0x04, 0x01, 0x82, 0x8c, +0x42, 0x00, 0x50, 0x09, 0x14, 0x01, 0x82, 0x8c, 0x04, 0x01, 0x02, 0x90, 0x42, 0x00, 0x04, 0x09, +0x14, 0x01, 0x02, 0x90, 0x80, 0x22, 0x04, 0x00, 0x82, 0x91, 0x58, 0x00, 0x00, 0x01, 0x14, 0x00, +0x82, 0x91, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, +0x84, 0x7f, 0x44, 0x00, 0x01, 0x33, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0xae, 0xc8, 0x49, 0xfd, +0xf3, 0x08, 0xc0, 0x04, 0x44, 0x00, 0x00, 0xff, 0xd5, 0x03, 0x00, 0x0f, 0x80, 0x07, 0xec, 0x0c, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x49, 0xff, 0xff, 0xe7, +0x80, 0x20, 0x44, 0x50, 0x00, 0xff, 0xd1, 0x0b, 0xa6, 0x35, 0x8e, 0x10, 0x96, 0x00, 0x5c, 0x20, +0x00, 0xef, 0x40, 0x00, 0x88, 0x1a, 0x49, 0xff, 0xed, 0xb8, 0xd5, 0x20, 0x2e, 0x10, 0xda, 0xd2, +0x44, 0x00, 0x00, 0x30, 0x42, 0x00, 0x80, 0x24, 0x80, 0x26, 0x08, 0x30, 0x80, 0x04, 0x3e, 0x28, +0x03, 0xb0, 0x10, 0x31, 0x00, 0xc9, 0xa6, 0xc8, 0x10, 0x31, 0x01, 0x51, 0x3e, 0x38, 0x79, 0xd8, +0xa6, 0x48, 0x98, 0x03, 0x10, 0x10, 0x00, 0x25, 0xa6, 0x35, 0x2e, 0x10, 0x02, 0x7c, 0x94, 0xc2, +0x98, 0xd9, 0x3e, 0x30, 0x02, 0x7b, 0x10, 0x01, 0x00, 0xcd, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xff, 0xb1, 0x49, 0xff, 0xed, 0x8d, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, +0x46, 0x10, 0x04, 0x00, 0x80, 0x01, 0x04, 0x60, 0x80, 0x0e, 0x04, 0x00, 0x00, 0x08, 0x84, 0x1f, +0x10, 0x0f, 0x80, 0x07, 0x80, 0x41, 0x04, 0x41, 0x00, 0x13, 0x46, 0x10, 0x04, 0x00, 0x46, 0x38, +0x08, 0x00, 0x58, 0x10, 0x80, 0xf4, 0x84, 0x03, 0x58, 0x42, 0x00, 0x01, 0x58, 0x31, 0x80, 0x03, +0x84, 0xe0, 0x14, 0x41, 0x00, 0x13, 0xb6, 0x01, 0xb6, 0x61, 0xb6, 0x01, 0xb6, 0xe1, 0x40, 0x63, +0x40, 0x08, 0x50, 0x1f, 0x80, 0x07, 0x44, 0x00, 0x00, 0x23, 0x84, 0x41, 0x49, 0xfd, 0xf2, 0x91, +0x00, 0x0f, 0x80, 0x07, 0x92, 0xdd, 0x54, 0x00, 0x00, 0x08, 0xc8, 0x06, 0x46, 0x2f, 0x0f, 0xff, +0x44, 0x00, 0x0f, 0xff, 0xd5, 0x03, 0x80, 0x07, 0x80, 0x47, 0x2e, 0x17, 0xf0, 0x4d, 0xc1, 0x03, +0x42, 0x00, 0x7c, 0x08, 0x84, 0xa2, 0xd6, 0x3f, 0xe4, 0xc3, 0xe8, 0x05, 0x84, 0xa1, 0x4c, 0x62, +0xc0, 0xbd, 0xd5, 0x06, 0x9e, 0x75, 0xe6, 0x22, 0x4e, 0xf2, 0x00, 0xb8, 0xd5, 0x70, 0x46, 0x10, +0x04, 0x00, 0x84, 0x60, 0x14, 0x30, 0x80, 0x48, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x80, 0x4c, +0xb4, 0x61, 0x44, 0x6f, 0xff, 0xc5, 0x40, 0x31, 0x98, 0x02, 0xb6, 0x61, 0x46, 0x50, 0x04, 0x00, +0xb4, 0x61, 0x58, 0x31, 0x80, 0x10, 0xb6, 0x61, 0x04, 0x12, 0x80, 0x08, 0x80, 0x85, 0x42, 0x10, +0xb0, 0x09, 0x14, 0x12, 0x80, 0x08, 0x04, 0x52, 0x00, 0x20, 0x42, 0x52, 0x98, 0x09, 0x14, 0x52, +0x00, 0x20, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x81, 0x24, 0xb4, 0x83, 0x40, 0x21, 0x10, 0x02, +0xb6, 0x43, 0x9c, 0x5c, 0xb4, 0x41, 0x40, 0x00, 0x08, 0x02, 0xb6, 0x01, 0xb4, 0x03, 0xb6, 0x03, +0xb4, 0x01, 0xd5, 0x37, 0x46, 0x10, 0x04, 0x00, 0x84, 0x60, 0x14, 0x30, 0x80, 0x48, 0x46, 0x10, +0x04, 0x00, 0x58, 0x10, 0x80, 0x4c, 0xb4, 0x61, 0x44, 0x4f, 0xff, 0xc5, 0x40, 0x31, 0x90, 0x02, +0xb6, 0x61, 0x46, 0x50, 0x04, 0x00, 0xb4, 0x61, 0x58, 0x31, 0x80, 0x10, 0xb6, 0x61, 0x04, 0x12, +0x80, 0x08, 0x80, 0x85, 0x42, 0x10, 0xb0, 0x09, 0x14, 0x12, 0x80, 0x08, 0x04, 0x52, 0x00, 0x20, +0x42, 0x52, 0x98, 0x09, 0x14, 0x52, 0x00, 0x20, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x81, 0x24, +0xb4, 0x83, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x43, 0x9c, 0x5c, 0xb4, 0x41, 0x40, 0x00, 0x08, 0x02, +0xb6, 0x01, 0x44, 0x27, 0x70, 0x00, 0xb4, 0x03, 0xb6, 0x03, 0xb4, 0x01, 0x40, 0x00, 0x08, 0x04, +0xb6, 0x01, 0x84, 0x25, 0x3e, 0x17, 0xf0, 0x58, 0x48, 0x00, 0x00, 0x89, 0x46, 0x10, 0x04, 0x00, +0x84, 0x60, 0x14, 0x30, 0x80, 0x48, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x80, 0x4c, 0xb4, 0x61, +0x44, 0x4f, 0xff, 0xc5, 0x40, 0x31, 0x90, 0x02, 0x84, 0xa5, 0xb6, 0x61, 0xde, 0x05, 0xb4, 0x61, +0x58, 0x31, 0x80, 0x30, 0xd5, 0x04, 0xb4, 0x61, 0x58, 0x31, 0x80, 0x10, 0xb6, 0x61, 0x46, 0x30, +0x04, 0x00, 0x04, 0x41, 0x80, 0x08, 0x42, 0x42, 0x30, 0x09, 0x14, 0x41, 0x80, 0x08, 0x80, 0x23, +0x04, 0x40, 0x80, 0x20, 0x42, 0x42, 0x18, 0x09, 0x14, 0x40, 0x80, 0x20, 0x46, 0x30, 0x04, 0x00, +0x58, 0x31, 0x81, 0x24, 0xb4, 0x83, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x43, 0x9c, 0x5c, 0xb4, 0x81, +0x40, 0x00, 0x10, 0x02, 0xb6, 0x01, 0xb4, 0x03, 0xb6, 0x03, 0xb4, 0x01, 0xb6, 0x01, 0x84, 0xa5, +0xde, 0x03, 0x84, 0x04, 0xd5, 0x02, 0x84, 0x08, 0x3e, 0x07, 0xf0, 0x58, 0x84, 0x02, 0x3c, 0x0b, +0xf8, 0x25, 0x3c, 0x0b, 0xf8, 0x24, 0xd5, 0x42, 0x46, 0x10, 0x04, 0x00, 0x84, 0x60, 0x14, 0x30, +0x80, 0x48, 0x80, 0x61, 0x04, 0x41, 0x80, 0x10, 0x46, 0x10, 0x04, 0x00, 0x97, 0x21, 0x14, 0x41, +0x80, 0x10, 0x58, 0x10, 0x80, 0x4c, 0xb4, 0x61, 0x44, 0x6f, 0xff, 0xc5, 0x40, 0x31, 0x98, 0x02, +0xb6, 0x61, 0x46, 0x50, 0x04, 0x00, 0xb4, 0x61, 0x58, 0x31, 0x80, 0x02, 0xb6, 0x61, 0x04, 0x12, +0x80, 0x08, 0x80, 0x85, 0x42, 0x10, 0xb0, 0x09, 0x14, 0x12, 0x80, 0x08, 0x04, 0x52, 0x00, 0x20, +0x42, 0x52, 0x98, 0x09, 0x14, 0x52, 0x00, 0x20, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x81, 0x24, +0xb4, 0xa3, 0x40, 0x21, 0x14, 0x02, 0xb6, 0x43, 0x9c, 0x5c, 0xb4, 0x41, 0x84, 0x81, 0x40, 0x00, +0x08, 0x02, 0xb6, 0x01, 0xb4, 0x03, 0xb6, 0x03, 0xb4, 0x01, 0xb6, 0x01, 0x84, 0x26, 0x3e, 0x17, +0xf0, 0x58, 0x3c, 0x4b, 0xf8, 0x25, 0x3c, 0x4b, 0xf8, 0x24, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x49, 0xff, 0xea, 0x15, 0x49, 0xff, 0xea, 0x21, +0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x82, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x00, 0x82, +0x84, 0xa1, 0x2e, 0x27, 0xf0, 0x4d, 0xda, 0x17, 0x50, 0x1f, 0x80, 0x07, 0x44, 0x00, 0x00, 0x25, +0x49, 0xfd, 0xf1, 0x5f, 0x00, 0x0f, 0x80, 0x07, 0x44, 0x50, 0x00, 0xff, 0xd8, 0x0c, 0x84, 0x00, +0x3e, 0x07, 0xf0, 0x4d, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x4a, 0x42, 0x10, 0xfc, 0x09, +0x14, 0x10, 0x00, 0x4a, 0x46, 0x30, 0x00, 0x90, 0x58, 0x31, 0x82, 0xc0, 0x46, 0x10, 0x00, 0x92, +0x58, 0x10, 0x8b, 0x7c, 0x3c, 0x3f, 0xfb, 0xef, 0x3c, 0x1f, 0xfb, 0xfe, 0x2e, 0x07, 0xf0, 0x58, +0xdd, 0x21, 0x49, 0xff, 0xec, 0xac, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, 0x0b, 0x14, 0xb4, 0x20, +0x44, 0x3f, 0xff, 0x9f, 0x58, 0x10, 0x80, 0x18, 0xb6, 0x20, 0xb4, 0x20, 0x46, 0x20, 0x04, 0x02, +0x40, 0x10, 0x8c, 0x02, 0x58, 0x10, 0x80, 0x20, 0xb6, 0x20, 0xb4, 0x60, 0x46, 0x10, 0x04, 0x00, +0x42, 0x31, 0x9c, 0x09, 0xb6, 0x60, 0xb4, 0x60, 0x94, 0xdd, 0x92, 0x65, 0x42, 0x31, 0xf8, 0x08, +0xb6, 0x60, 0x44, 0x00, 0xff, 0xff, 0x14, 0x01, 0x02, 0x08, 0x04, 0x00, 0x80, 0x0e, 0x84, 0xa1, +0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd0, 0x08, 0x04, 0x00, 0x80, 0x0e, 0x84, 0xa2, 0x92, 0x14, +0x54, 0x00, 0x00, 0x03, 0xd8, 0x09, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x02, 0x42, 0x42, 0x10, +0xb4, 0x09, 0x14, 0x10, 0x02, 0x42, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x44, 0x2f, 0x00, 0x00, +0x46, 0x37, 0x66, 0x20, 0x40, 0x50, 0x88, 0x02, 0xd3, 0x07, 0xb4, 0x00, 0x46, 0x47, 0x63, 0x20, +0x40, 0x50, 0x08, 0x02, 0xdc, 0x45, 0x46, 0x10, 0x00, 0x95, 0x58, 0x10, 0x89, 0xc4, 0x3c, 0x1f, +0xfb, 0xaa, 0x46, 0x10, 0x00, 0x95, 0x58, 0x10, 0x88, 0xc8, 0x3c, 0x1f, 0xfb, 0x98, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x01, 0x48, 0xb4, 0x20, 0x46, 0x2f, 0xf8, 0x0f, 0x46, 0x30, 0x05, 0xf0, +0x40, 0x10, 0x88, 0x02, 0x58, 0x31, 0x80, 0x02, 0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, 0x81, 0x00, +0x84, 0xc0, 0xb4, 0x08, 0x9d, 0xb1, 0x40, 0x10, 0x30, 0x09, 0x40, 0x20, 0x70, 0x09, 0x54, 0x10, +0x80, 0x03, 0x84, 0x0a, 0xca, 0x02, 0xc1, 0x06, 0x49, 0xff, 0xe9, 0x85, 0x44, 0x50, 0x00, 0x64, +0xde, 0xf1, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x52, 0x92, 0x4c, 0x40, 0x21, 0x30, 0x08, +0x14, 0x20, 0x00, 0x52, 0x80, 0x20, 0x04, 0x20, 0x80, 0x20, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, +0x80, 0x20, 0x04, 0x10, 0x00, 0x19, 0x42, 0x10, 0xc8, 0x08, 0x14, 0x10, 0x00, 0x19, 0x46, 0x70, +0x00, 0x95, 0x58, 0x73, 0x86, 0x84, 0x3c, 0x7f, 0xfb, 0xa8, 0x46, 0x70, 0x00, 0x95, 0x58, 0x73, +0x82, 0x1c, 0x3c, 0x7e, 0x0a, 0xf6, 0x84, 0xe0, 0x3e, 0x71, 0xf6, 0x0d, 0x3e, 0x0f, 0xee, 0x1c, +0x44, 0x60, 0x78, 0x00, 0x46, 0x40, 0x01, 0x00, 0xa9, 0x87, 0x84, 0xe4, 0x46, 0x30, 0x01, 0x10, +0x46, 0x20, 0x01, 0x21, 0x46, 0x10, 0x04, 0x20, 0x3c, 0x7e, 0x0a, 0xe1, 0x84, 0xa0, 0x58, 0x31, +0x88, 0x00, 0xb6, 0x80, 0x44, 0x41, 0x08, 0x00, 0xa9, 0x01, 0xa8, 0xc2, 0xa8, 0x84, 0xa9, 0x45, +0xa8, 0x46, 0xa9, 0x43, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x3a, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfd, +0xf0, 0x78, 0x00, 0x0f, 0x80, 0x07, 0x96, 0x42, 0x4e, 0x15, 0x00, 0x16, 0x46, 0x40, 0x04, 0x00, +0x46, 0x10, 0x00, 0xa0, 0x80, 0x64, 0x80, 0x43, 0x9f, 0x41, 0x58, 0x10, 0x8a, 0x3f, 0x97, 0x68, +0x14, 0x12, 0x00, 0x41, 0x14, 0x11, 0x80, 0x42, 0x14, 0x11, 0x00, 0x43, 0x5c, 0xf2, 0x80, 0xfe, +0xe8, 0x53, 0xd5, 0x23, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x19, 0x42, 0x10, 0xf4, 0x0b, +0x9f, 0xc1, 0xc1, 0x26, 0x46, 0x50, 0x04, 0x00, 0x46, 0x60, 0x00, 0x80, 0x80, 0x65, 0x46, 0x40, +0x00, 0x90, 0x80, 0x43, 0x46, 0x10, 0x00, 0xa1, 0x58, 0x63, 0x00, 0x0f, 0x58, 0x42, 0x0a, 0x1e, +0x58, 0x10, 0x8e, 0x7f, 0x97, 0xf8, 0x14, 0x62, 0x80, 0x41, 0x14, 0x41, 0x80, 0x42, 0x14, 0x11, +0x00, 0x43, 0x5c, 0xf3, 0x80, 0xfe, 0xe8, 0x30, 0x54, 0x10, 0x00, 0x7f, 0x46, 0x00, 0x00, 0xb8, +0x40, 0x10, 0xa0, 0x08, 0x58, 0x00, 0x00, 0x7f, 0x40, 0x10, 0x80, 0x04, 0xd5, 0x25, 0x46, 0x50, +0x04, 0x00, 0x46, 0x60, 0x00, 0x80, 0x80, 0x65, 0x46, 0x40, 0x00, 0x90, 0x80, 0x43, 0x46, 0x10, +0x00, 0xa1, 0x58, 0x63, 0x00, 0x1e, 0x58, 0x42, 0x0a, 0x3c, 0x58, 0x10, 0x8e, 0x7f, 0x97, 0xf8, +0x14, 0x62, 0x80, 0x41, 0x14, 0x41, 0x80, 0x42, 0x14, 0x11, 0x00, 0x43, 0x5c, 0xf3, 0x80, 0xfe, +0xe8, 0x0b, 0x54, 0x10, 0x00, 0x7f, 0x46, 0x20, 0x00, 0xb8, 0x40, 0x10, 0xa0, 0x08, 0x58, 0x21, +0x00, 0xe0, 0x40, 0x10, 0x88, 0x04, 0x46, 0x20, 0x04, 0x00, 0x14, 0x11, 0x00, 0x44, 0xec, 0x0c, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x3a, +0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfd, 0xef, 0xfc, 0x92, 0x00, 0x20, 0x0f, 0x80, 0x07, +0x4e, 0x05, 0x00, 0x12, 0x46, 0x40, 0x04, 0x00, 0x80, 0x64, 0x80, 0x43, 0x80, 0x22, 0x44, 0x06, +0x0a, 0x3f, 0x14, 0x02, 0x00, 0x41, 0x14, 0x01, 0x80, 0x42, 0x14, 0x01, 0x00, 0x43, 0x14, 0x00, +0x80, 0x44, 0xd5, 0x36, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x19, 0x42, 0x00, 0x74, 0x0b, +0xc0, 0x18, 0x46, 0x30, 0x04, 0x00, 0x80, 0x43, 0x44, 0x46, 0x9e, 0x3f, 0x14, 0x41, 0x80, 0x41, +0x80, 0x22, 0x44, 0x35, 0x94, 0x2f, 0x14, 0x31, 0x00, 0x42, 0x46, 0x00, 0x04, 0x00, 0x44, 0x24, +0x8a, 0x0f, 0x14, 0x20, 0x80, 0x43, 0x58, 0x00, 0x01, 0x10, 0x44, 0x14, 0x00, 0x07, 0xd5, 0x17, +0x46, 0x30, 0x04, 0x00, 0x80, 0x43, 0x44, 0x46, 0x9e, 0xe0, 0x14, 0x41, 0x80, 0x41, 0x80, 0x22, +0x44, 0x35, 0x94, 0x7f, 0x14, 0x31, 0x00, 0x42, 0x46, 0x00, 0x04, 0x00, 0x44, 0x24, 0x8a, 0x3f, +0x14, 0x20, 0x80, 0x43, 0x58, 0x00, 0x01, 0x10, 0x44, 0x14, 0x00, 0x0f, 0xb6, 0x20, 0xec, 0x0c, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x04, 0x05, 0x84, 0x41, +0x14, 0x20, 0x81, 0xe6, 0x84, 0xa4, 0xd8, 0x0a, 0x80, 0x01, 0x04, 0x10, 0x02, 0x42, 0x42, 0x10, +0xf4, 0x09, 0x42, 0x10, 0xf8, 0x09, 0x14, 0x10, 0x02, 0x42, 0x46, 0x00, 0x04, 0x05, 0x84, 0x20, +0x14, 0x10, 0x01, 0xe6, 0x04, 0x00, 0x01, 0xd4, 0x96, 0x04, 0xc8, 0x0d, 0x84, 0x21, 0x46, 0x00, +0x04, 0x05, 0x58, 0x00, 0x07, 0x14, 0x80, 0x41, 0x80, 0x61, 0x44, 0x40, 0x01, 0x40, 0x49, 0xfe, +0x27, 0x5e, 0x92, 0x00, 0x44, 0x11, 0x00, 0x00, 0x46, 0x00, 0x04, 0x05, 0x80, 0x41, 0x84, 0x61, +0x44, 0x40, 0x01, 0x40, 0x58, 0x00, 0x07, 0x10, 0x49, 0xfe, 0x27, 0x51, 0x84, 0x24, 0x46, 0x00, +0x04, 0x05, 0x80, 0x41, 0x84, 0x61, 0x44, 0x40, 0x01, 0x40, 0x58, 0x00, 0x07, 0x10, 0x49, 0xfe, +0x27, 0x46, 0x84, 0x28, 0x46, 0x00, 0x04, 0x05, 0x80, 0x41, 0x84, 0x61, 0x44, 0x40, 0x01, 0x40, +0x58, 0x00, 0x07, 0x10, 0x49, 0xfe, 0x27, 0x3b, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x2e, 0x10, 0x2b, 0x0f, 0x80, 0xc0, 0x97, 0xd0, 0xc1, 0x63, 0x46, 0x00, +0x04, 0x02, 0x04, 0x00, 0x02, 0x00, 0x54, 0x50, 0x00, 0x07, 0xd6, 0x5c, 0x49, 0xfe, 0x00, 0x67, +0x49, 0xfe, 0x28, 0x23, 0xc7, 0x05, 0x80, 0x06, 0x49, 0xff, 0xff, 0x9f, 0xd5, 0x19, 0x49, 0xfe, +0x2b, 0xc0, 0x49, 0xfe, 0x0f, 0x6a, 0x84, 0xa3, 0xd8, 0x05, 0x46, 0x00, 0x04, 0x03, 0x14, 0x70, +0x01, 0x07, 0x49, 0xfe, 0x28, 0x3e, 0x84, 0x0a, 0x49, 0xfe, 0x27, 0x67, 0x46, 0x10, 0x04, 0x02, +0x80, 0x01, 0x84, 0x40, 0x14, 0x20, 0x82, 0x14, 0x84, 0x21, 0x14, 0x10, 0x02, 0x15, 0x44, 0x00, +0x00, 0x32, 0x49, 0xfe, 0x27, 0x5a, 0x49, 0xfe, 0x2b, 0xa4, 0x84, 0xa3, 0xde, 0x09, 0x46, 0x00, +0x04, 0x05, 0x58, 0x00, 0x07, 0x30, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x20, 0xd5, 0x0a, 0x84, 0xa4, +0xde, 0x09, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, 0x07, 0x30, 0xb4, 0x20, 0x42, 0x10, 0x94, 0x09, +0xb6, 0x20, 0x80, 0x06, 0x3e, 0x68, 0xc3, 0x68, 0x49, 0xfe, 0x29, 0xa7, 0x49, 0xfe, 0x2b, 0xfb, +0x49, 0xfe, 0x2c, 0x47, 0x50, 0x03, 0x00, 0x2e, 0x3a, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x02, +0xc0, 0x0e, 0x49, 0xfe, 0x0f, 0x68, 0x04, 0x03, 0x03, 0x2d, 0x02, 0x10, 0x00, 0x0b, 0x40, 0x00, +0xa0, 0x09, 0x54, 0x00, 0x00, 0x0f, 0x92, 0x2c, 0x49, 0xfe, 0x10, 0x51, 0x49, 0xfe, 0x28, 0x07, +0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x04, 0x10, 0x00, 0x0b, 0x84, 0x4a, 0x04, 0x70, 0x80, 0x0c, 0x50, 0x60, 0x00, 0x1c, 0x4c, 0x71, +0x40, 0x23, 0x00, 0x80, 0x80, 0x40, 0x84, 0x22, 0x8d, 0x01, 0x54, 0x84, 0x00, 0xff, 0x4c, 0x80, +0xc0, 0x12, 0x8c, 0x37, 0x49, 0xfd, 0x5e, 0x3d, 0x3c, 0x3c, 0x28, 0x89, 0x84, 0x21, 0x9c, 0xd9, +0x3c, 0x3e, 0x28, 0x89, 0x3c, 0x4d, 0xff, 0x14, 0x44, 0x20, 0x30, 0x0d, 0x84, 0x04, 0xdd, 0x24, +0x84, 0xeb, 0xa0, 0x74, 0x10, 0x80, 0x80, 0x40, 0x3c, 0x1c, 0x28, 0x88, 0x9c, 0x49, 0x3c, 0x1e, +0x28, 0x88, 0xd5, 0x2e, 0x84, 0x40, 0x10, 0x20, 0x80, 0x40, 0x46, 0x80, 0x04, 0x80, 0x49, 0xfd, +0x43, 0xe8, 0x80, 0xe0, 0xd5, 0x05, 0x3c, 0x4d, 0xff, 0x14, 0xa6, 0xf4, 0xdd, 0x24, 0x04, 0x44, +0x03, 0xc9, 0x46, 0x30, 0x04, 0x80, 0x97, 0x24, 0x84, 0x04, 0x84, 0x21, 0x44, 0x20, 0x30, 0x0e, +0xcc, 0xf3, 0x84, 0x44, 0x04, 0x01, 0x83, 0xc9, 0x4c, 0x71, 0x40, 0x13, 0x42, 0x00, 0x08, 0x0b, +0xc0, 0x0f, 0x50, 0x03, 0x7f, 0xe4, 0x8c, 0x39, 0x49, 0xfd, 0x5e, 0x03, 0x3c, 0x4d, 0xff, 0x14, +0xa6, 0xf4, 0x80, 0x07, 0x84, 0x21, 0x44, 0x20, 0x30, 0x0f, 0xdd, 0x24, 0x84, 0xec, 0xa0, 0x74, +0x50, 0x03, 0xff, 0xf5, 0x14, 0x70, 0x80, 0x0c, 0xe6, 0x02, 0xe9, 0x51, 0xa6, 0x36, 0x84, 0xa1, +0xd8, 0x1d, 0x84, 0xa4, 0xd7, 0x03, 0x84, 0xa6, 0xdf, 0x19, 0x2e, 0x00, 0x02, 0x9d, 0xc0, 0x08, +0xa0, 0x34, 0x00, 0x10, 0x00, 0x27, 0xc9, 0x12, 0x00, 0x00, 0x00, 0x28, 0xc8, 0x0f, 0x50, 0x03, +0x7f, 0xe4, 0x44, 0x10, 0x00, 0x1b, 0x49, 0xfd, 0x5d, 0xdc, 0x3c, 0x4d, 0xff, 0x14, 0x80, 0x67, +0x84, 0x04, 0x84, 0x21, 0x44, 0x20, 0x30, 0x14, 0xd5, 0x27, 0x46, 0x00, 0x04, 0x90, 0x04, 0x70, +0x00, 0x4f, 0x95, 0xff, 0x92, 0xf7, 0x3c, 0x4d, 0xff, 0x14, 0x44, 0x11, 0x00, 0x00, 0x84, 0x04, +0x44, 0x20, 0x30, 0x16, 0x80, 0x67, 0xdd, 0x24, 0x49, 0xfd, 0x87, 0x4b, 0xe2, 0x07, 0xe9, 0x02, +0xcf, 0x15, 0x50, 0x03, 0x7f, 0xe4, 0x44, 0x10, 0x00, 0x1b, 0x49, 0xfd, 0x5d, 0xba, 0x3c, 0x1c, +0x28, 0x9f, 0x80, 0x67, 0x9c, 0x49, 0x3c, 0x1e, 0x28, 0x9f, 0x3c, 0x4d, 0xff, 0x14, 0x84, 0x21, +0x84, 0x04, 0x44, 0x20, 0x30, 0x15, 0xdd, 0x24, 0xd5, 0x0a, 0x2e, 0x00, 0x84, 0xf5, 0xc8, 0x07, +0x44, 0x00, 0x00, 0x15, 0x49, 0xfd, 0x60, 0x3b, 0x49, 0xfd, 0x44, 0xad, 0xa6, 0x36, 0x84, 0x41, +0x3e, 0x78, 0xa2, 0x20, 0x4c, 0x01, 0x40, 0x09, 0xa0, 0x3b, 0xa0, 0x7c, 0x98, 0x02, 0x98, 0x4a, +0xa8, 0x7c, 0xa8, 0x3b, 0xd5, 0x0b, 0x50, 0x03, 0x7f, 0xe4, 0x49, 0xfd, 0x65, 0x18, 0x92, 0x00, +0x04, 0x03, 0x80, 0x08, 0x9c, 0x01, 0x14, 0x03, 0x80, 0x08, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x84, 0x08, 0x49, 0xfb, 0x69, 0x0a, 0x84, 0x21, +0x3c, 0x1e, 0x36, 0x40, 0x46, 0x00, 0x04, 0x02, 0xb4, 0xe0, 0x54, 0x73, 0x80, 0x10, 0xc7, 0x0a, +0x46, 0x10, 0x04, 0x04, 0x80, 0x01, 0x04, 0x10, 0x81, 0x07, 0x04, 0x70, 0x01, 0x06, 0x40, 0x73, +0x84, 0x02, 0x46, 0x00, 0x04, 0x02, 0xb4, 0xc0, 0x54, 0x63, 0x00, 0x04, 0xc6, 0x0a, 0x46, 0x10, +0x04, 0x03, 0x80, 0x01, 0x04, 0x10, 0x81, 0x50, 0x04, 0x60, 0x01, 0x4f, 0x40, 0x63, 0x04, 0x02, +0x46, 0x10, 0x04, 0x02, 0x80, 0x01, 0x04, 0x10, 0x80, 0x20, 0x04, 0x20, 0x00, 0x21, 0x40, 0x21, +0x04, 0x02, 0x40, 0x11, 0x40, 0x09, 0x3c, 0x1e, 0x37, 0x21, 0x80, 0x60, 0x80, 0x20, 0x04, 0x31, +0x82, 0x15, 0x04, 0xa0, 0x82, 0x14, 0xb4, 0x00, 0x40, 0xa5, 0x0c, 0x02, 0x54, 0x00, 0x00, 0x10, +0x54, 0x91, 0x00, 0xff, 0xc0, 0x05, 0x46, 0x00, 0x04, 0x04, 0x14, 0x70, 0x01, 0x07, 0x80, 0x01, +0xb4, 0x00, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x05, 0x46, 0x00, 0x04, 0x03, 0x14, 0x60, 0x01, 0x50, +0x80, 0x01, 0x54, 0x33, 0x20, 0x00, 0x14, 0x20, 0x80, 0x20, 0x14, 0xa0, 0x02, 0x15, 0xc3, 0x22, +0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xcc, 0x42, 0x21, 0x04, 0x09, 0x14, 0x20, 0x81, 0xcc, +0x80, 0x01, 0x04, 0x10, 0x01, 0xc2, 0x42, 0x10, 0x80, 0x09, 0x14, 0x10, 0x01, 0xc2, 0x3c, 0x0c, +0x36, 0x43, 0xc8, 0x0a, 0x80, 0x20, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x70, 0x44, 0x30, +0x1d, 0x7f, 0x49, 0xfb, 0x85, 0xdc, 0x3c, 0x0c, 0x36, 0x43, 0xdd, 0x20, 0x84, 0x00, 0x3c, 0x0e, +0x36, 0x3e, 0x54, 0x03, 0x82, 0x00, 0xc0, 0x1f, 0x46, 0x00, 0x04, 0x04, 0x04, 0x00, 0x01, 0x01, +0x54, 0x00, 0x04, 0x00, 0xc8, 0x18, 0x46, 0x00, 0x04, 0x05, 0x04, 0x20, 0x01, 0xc2, 0x42, 0x21, +0x00, 0x09, 0x14, 0x20, 0x01, 0xc2, 0x80, 0x20, 0x04, 0x20, 0x81, 0xd4, 0x42, 0x21, 0x04, 0x09, +0x14, 0x20, 0x81, 0xd4, 0x46, 0x00, 0x04, 0x04, 0x04, 0x10, 0x01, 0x13, 0x58, 0x10, 0x80, 0x01, +0x14, 0x10, 0x01, 0x13, 0x54, 0x03, 0x80, 0x02, 0xc0, 0x22, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, +0x81, 0xc2, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x81, 0xc2, 0x80, 0x01, 0x04, 0x10, 0x01, 0xd4, +0x42, 0x10, 0x84, 0x09, 0x14, 0x10, 0x01, 0xd4, 0x3c, 0x0c, 0x36, 0x43, 0xc8, 0x0a, 0x80, 0x20, +0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x70, 0x44, 0x30, 0x1d, 0xa9, 0x49, 0xfb, 0x85, 0x97, +0x3c, 0x0c, 0x36, 0x43, 0xdd, 0x20, 0x84, 0x00, 0x3c, 0x0e, 0x36, 0x3e, 0x54, 0x03, 0x80, 0x04, +0xc0, 0x29, 0x46, 0x00, 0x04, 0x05, 0x04, 0x20, 0x01, 0xcc, 0x84, 0x7d, 0x40, 0x21, 0x0c, 0x02, +0x14, 0x20, 0x01, 0xcc, 0x80, 0x20, 0x04, 0x20, 0x81, 0xd4, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, +0x81, 0xd4, 0x04, 0x10, 0x01, 0xc2, 0x42, 0x10, 0x80, 0x09, 0x14, 0x10, 0x01, 0xc2, 0x3c, 0x0c, +0x36, 0x41, 0xc8, 0x0a, 0x80, 0x20, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x70, 0x44, 0x30, +0x1d, 0xbd, 0x49, 0xfb, 0x85, 0x6c, 0x3c, 0x0c, 0x36, 0x41, 0xdd, 0x20, 0x84, 0x00, 0x49, 0xfe, +0x2a, 0x58, 0x54, 0xa5, 0x00, 0x01, 0x4e, 0xa2, 0x00, 0x0a, 0x46, 0x00, 0x04, 0x02, 0x04, 0x00, +0x02, 0x00, 0x54, 0x00, 0x00, 0x07, 0x49, 0xfe, 0x12, 0xc8, 0x54, 0x03, 0x00, 0x02, 0xc0, 0x0f, +0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x01, 0xd4, 0x42, 0x10, 0x80, 0x09, 0x14, 0x10, 0x01, 0xd4, +0x84, 0xc0, 0x49, 0xfe, 0x26, 0x0c, 0x49, 0xfe, 0x2a, 0x14, 0xd5, 0x18, 0x54, 0x03, 0x40, 0x00, +0xc0, 0x0b, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x02, 0x42, 0x42, 0x10, 0xf4, 0x09, 0x42, 0x10, +0xf8, 0x09, 0x14, 0x10, 0x02, 0x42, 0x54, 0x03, 0x00, 0x10, 0xc0, 0x03, 0x49, 0xfd, 0xfe, 0xef, +0x54, 0x03, 0x00, 0x20, 0xc0, 0x03, 0x49, 0xfd, 0xfe, 0xea, 0x54, 0x03, 0x80, 0x20, 0xc0, 0x20, +0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x82, 0x42, 0x42, 0x21, 0x74, 0x09, 0x42, 0x21, 0x78, 0x09, +0x14, 0x20, 0x82, 0x42, 0x80, 0x01, 0x04, 0x20, 0x01, 0xc2, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, +0x01, 0xc2, 0x80, 0x20, 0x04, 0x20, 0x81, 0xcc, 0x84, 0x7d, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, +0x81, 0xcc, 0x04, 0x10, 0x01, 0xd4, 0x40, 0x10, 0x8c, 0x02, 0x14, 0x10, 0x01, 0xd4, 0x3c, 0x0c, +0x37, 0x21, 0x40, 0x14, 0x80, 0x04, 0x96, 0x4c, 0xc1, 0x1c, 0x3c, 0x8c, 0x36, 0x44, 0x4e, 0x83, +0x00, 0x13, 0x80, 0x08, 0x46, 0x10, 0x00, 0x96, 0x58, 0x10, 0x84, 0x6c, 0x46, 0x20, 0x00, 0x96, +0x58, 0x21, 0x04, 0x70, 0x44, 0x30, 0x1e, 0x3f, 0x80, 0x88, 0x80, 0xa8, 0xb7, 0x1f, 0x49, 0xfb, +0x84, 0xce, 0xd5, 0x07, 0x96, 0x04, 0xc0, 0x04, 0x84, 0x21, 0x3e, 0x10, 0xda, 0xe9, 0xdd, 0x28, +0x46, 0x00, 0x04, 0x02, 0x04, 0x00, 0x00, 0x21, 0x40, 0x90, 0x24, 0x02, 0x93, 0x21, 0x4e, 0x92, +0x00, 0x1a, 0x85, 0x01, 0x45, 0xc5, 0x56, 0xc8, 0x50, 0x04, 0x7f, 0xff, 0x84, 0x21, 0x40, 0x00, +0x80, 0x0c, 0x40, 0x00, 0x24, 0x02, 0xc0, 0x0a, 0x80, 0x08, 0xdd, 0x3c, 0xc0, 0x07, 0x84, 0x20, +0x80, 0x08, 0x80, 0x41, 0x84, 0x61, 0x49, 0xfe, 0x15, 0x44, 0x8d, 0x01, 0x84, 0x4a, 0x4c, 0x81, +0x7f, 0xed, 0x46, 0x00, 0x04, 0x02, 0x04, 0x90, 0x00, 0x21, 0x3c, 0x0c, 0x37, 0x21, 0x93, 0x31, +0x92, 0x01, 0x40, 0x94, 0x80, 0x02, 0x4e, 0x92, 0x00, 0x1a, 0x85, 0x01, 0x45, 0xc5, 0x56, 0x9c, +0x50, 0x04, 0x7f, 0xff, 0x84, 0x61, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x24, 0x02, 0xc0, 0x0a, +0x80, 0x08, 0xdd, 0x3c, 0xc0, 0x07, 0x80, 0x08, 0x84, 0x21, 0x84, 0x40, 0x84, 0x62, 0x49, 0xfe, +0x15, 0x20, 0x8d, 0x01, 0x84, 0x0a, 0x4c, 0x80, 0x7f, 0xed, 0x96, 0x3c, 0xc0, 0x34, 0x3c, 0x0c, +0x36, 0x42, 0xc8, 0x0a, 0x80, 0x20, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x70, 0x44, 0x30, +0x1e, 0xcd, 0x49, 0xfb, 0x84, 0x9c, 0x3c, 0x0c, 0x36, 0x42, 0xdd, 0x20, 0x2e, 0x00, 0x02, 0xfc, +0x84, 0x21, 0x3c, 0x1e, 0x36, 0x3e, 0xc0, 0x11, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xd4, +0x80, 0x01, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x81, 0xd4, 0x04, 0x10, 0x01, 0xc2, 0x58, 0x10, +0x80, 0x01, 0x14, 0x10, 0x01, 0xc2, 0xd5, 0x0f, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x96, +0x42, 0x21, 0x78, 0x09, 0x42, 0x21, 0x7c, 0x09, 0x14, 0x20, 0x80, 0x96, 0x2e, 0x10, 0xd0, 0x21, +0x49, 0xfb, 0x7c, 0x67, 0x54, 0x73, 0x81, 0x00, 0xc7, 0x1c, 0x46, 0x10, 0x04, 0x04, 0x80, 0x01, +0x04, 0x10, 0x81, 0x11, 0x04, 0x10, 0x01, 0x01, 0x04, 0x00, 0x01, 0x01, 0x54, 0x00, 0x04, 0x00, +0xc8, 0x10, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xd4, 0x80, 0x01, 0x58, 0x21, 0x00, 0x02, +0x14, 0x20, 0x81, 0xd4, 0x04, 0x10, 0x01, 0xc2, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x01, 0xc2, +0x54, 0x63, 0x04, 0x00, 0xc6, 0x34, 0x3c, 0x0c, 0x36, 0x42, 0xc8, 0x0a, 0x80, 0x20, 0x46, 0x20, +0x00, 0x96, 0x58, 0x21, 0x04, 0x70, 0x44, 0x30, 0x1e, 0xfb, 0x49, 0xfb, 0x84, 0x48, 0x3c, 0x0c, +0x36, 0x42, 0xdd, 0x20, 0x2e, 0x00, 0x02, 0xfc, 0x84, 0x21, 0x3c, 0x1e, 0x36, 0x3e, 0xc0, 0x11, +0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xcc, 0x80, 0x01, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, +0x81, 0xcc, 0x04, 0x10, 0x01, 0xc2, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x01, 0xc2, 0xd5, 0x0f, +0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x96, 0x42, 0x21, 0x78, 0x09, 0x42, 0x21, 0x7c, 0x09, +0x14, 0x20, 0x80, 0x96, 0x2e, 0x10, 0xd0, 0x21, 0x49, 0xfb, 0x7c, 0x13, 0x84, 0x40, 0x3c, 0x2e, +0x36, 0x40, 0x84, 0x08, 0x49, 0xfb, 0x66, 0xbf, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x2e, 0x00, 0xb6, 0x98, 0x84, 0xa1, 0xd8, 0x07, +0x3c, 0x2c, 0x00, 0x62, 0x84, 0x20, 0x44, 0x00, 0x00, 0x29, 0xdd, 0x22, 0x3c, 0x2d, 0xfe, 0x0a, +0x84, 0x20, 0x84, 0x04, 0xdd, 0x22, 0x49, 0xfd, 0xb2, 0xfc, 0x2e, 0x00, 0x04, 0xd3, 0x84, 0xa1, +0xd8, 0x07, 0x3c, 0x2c, 0x00, 0x78, 0x84, 0x20, 0x3e, 0x08, 0x6d, 0xfc, 0xdd, 0x22, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x40, 0x91, 0x00, 0x13, 0x80, 0xe0, +0x80, 0x09, 0x80, 0xc1, 0x49, 0xfc, 0x79, 0x69, 0x54, 0x80, 0x00, 0xff, 0x80, 0x09, 0x49, 0xfc, +0x79, 0x20, 0x81, 0x40, 0x2e, 0x00, 0x73, 0x2d, 0xe6, 0x02, 0xe9, 0x03, 0x42, 0x63, 0x14, 0x09, +0x80, 0x08, 0x49, 0xfc, 0x75, 0x0a, 0x80, 0x40, 0x80, 0x26, 0x80, 0x07, 0x49, 0xfb, 0xf2, 0x05, +0x80, 0x60, 0x44, 0x50, 0x00, 0x1d, 0xdb, 0x04, 0x4c, 0x85, 0x40, 0x67, 0xd5, 0x08, 0xc3, 0x07, +0x56, 0x11, 0x80, 0x23, 0x84, 0x0c, 0x40, 0x30, 0x04, 0x1a, 0xd5, 0x5e, 0x00, 0x33, 0x81, 0x1d, +0x54, 0x01, 0x80, 0x08, 0xc0, 0x57, 0x54, 0x03, 0x00, 0x20, 0xc8, 0x0d, 0x54, 0x03, 0x00, 0x40, +0xc0, 0x04, 0x54, 0x01, 0x80, 0x10, 0xc8, 0x07, 0x54, 0x03, 0x00, 0x80, 0xc0, 0x4b, 0x54, 0x01, +0x80, 0x20, 0xc0, 0x48, 0x54, 0x01, 0x80, 0x10, 0xc8, 0x03, 0x42, 0x63, 0x18, 0x09, 0x54, 0x01, +0x80, 0x20, 0xc8, 0x03, 0x42, 0x63, 0x1c, 0x09, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x06, 0x54, 0x31, +0x80, 0x40, 0xcb, 0x0f, 0xd5, 0x37, 0x84, 0xa2, 0x4c, 0x82, 0xc0, 0x06, 0x96, 0xda, 0x4e, 0x34, +0x00, 0x32, 0xd5, 0x07, 0x4e, 0x83, 0x00, 0x06, 0x00, 0x03, 0x81, 0x1e, 0x96, 0x04, 0xc0, 0x2a, +0x00, 0x03, 0x81, 0xae, 0x80, 0x29, 0x84, 0x40, 0x49, 0xfc, 0x81, 0x0b, 0x81, 0x00, 0xc8, 0x03, +0x84, 0x69, 0xd5, 0x22, 0x04, 0x23, 0x80, 0x6c, 0x80, 0x26, 0x10, 0x23, 0x81, 0xc7, 0x84, 0x60, +0x49, 0xfc, 0x7f, 0xbd, 0x80, 0x07, 0x80, 0x28, 0x49, 0xfb, 0xe6, 0x9d, 0x04, 0x63, 0x80, 0x6c, +0xce, 0x08, 0x00, 0x14, 0x00, 0x40, 0x80, 0x07, 0x49, 0xfc, 0x59, 0xa7, 0x80, 0x66, 0xd5, 0x0c, +0x02, 0x04, 0x00, 0x17, 0x49, 0xfc, 0x78, 0xf5, 0x80, 0x08, 0x49, 0xfc, 0x80, 0x6a, 0x84, 0x60, +0xd5, 0x03, 0x44, 0x30, 0x00, 0x1a, 0x80, 0x03, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa0, 0xbc, 0x80, 0xc0, 0xc0, 0x0f, 0x00, 0x10, 0x00, 0x20, 0x9e, 0x4e, 0x96, 0x48, 0xe6, 0x24, +0xe8, 0x09, 0x84, 0x41, 0x3e, 0x20, 0x84, 0xfa, 0x49, 0xfd, 0x59, 0x69, 0x80, 0xe0, 0x48, 0x00, +0x00, 0xa1, 0x49, 0xfc, 0xf8, 0xbc, 0x84, 0xa1, 0x80, 0xe0, 0xd8, 0x47, 0x3c, 0x1d, 0xff, 0x0f, +0xdd, 0x21, 0x49, 0xfc, 0xf8, 0xb4, 0x4c, 0x03, 0xc0, 0x10, 0xc6, 0x0a, 0x49, 0xfc, 0xf8, 0xb3, +0x4c, 0x03, 0x40, 0x41, 0x3c, 0x6e, 0x21, 0x36, 0x44, 0x70, 0x00, 0x60, 0xd5, 0x38, 0x49, 0xfc, +0xf8, 0xae, 0x48, 0x00, 0x00, 0x95, 0x3c, 0x1c, 0x1f, 0x07, 0x80, 0x07, 0xdd, 0x21, 0x80, 0xc0, +0xc0, 0x1e, 0x00, 0x30, 0x00, 0x20, 0x9e, 0x5e, 0x96, 0x48, 0xe6, 0x24, 0xe8, 0x10, 0x3e, 0x70, +0x84, 0xfa, 0x49, 0xfd, 0x59, 0x3c, 0x80, 0xe0, 0x84, 0x22, 0x84, 0x03, 0x44, 0x20, 0x10, 0x50, +0x44, 0x30, 0xff, 0xff, 0x80, 0x87, 0x49, 0xfd, 0x06, 0x02, 0xd5, 0x1b, 0x80, 0x87, 0x84, 0x03, +0x84, 0x22, 0x44, 0x20, 0x10, 0x50, 0x49, 0xfd, 0x05, 0xfa, 0xd5, 0x14, 0x3e, 0x70, 0x84, 0xf5, +0x3e, 0x60, 0x84, 0xf6, 0x3c, 0x4d, 0xff, 0x14, 0x80, 0x66, 0x84, 0x03, 0x84, 0x22, 0x44, 0x20, +0x10, 0x50, 0xdd, 0x24, 0x48, 0x00, 0x00, 0x64, 0x80, 0x06, 0x84, 0xe0, 0xc0, 0x4e, 0x80, 0xc0, +0xcf, 0x4b, 0x00, 0x13, 0x00, 0x22, 0x00, 0x03, 0x00, 0x20, 0xc9, 0x2b, 0x3e, 0x78, 0x84, 0xd4, +0x00, 0x13, 0x80, 0x22, 0x4c, 0x10, 0x40, 0x03, 0xd5, 0x21, 0x04, 0x23, 0x00, 0x0a, 0xa0, 0x53, +0xc1, 0x1a, 0x02, 0x21, 0x00, 0x11, 0xa0, 0xf3, 0x49, 0xfc, 0xfa, 0x8f, 0x3c, 0x1d, 0xff, 0x0f, +0x84, 0x01, 0xdd, 0x21, 0x84, 0x01, 0x10, 0x03, 0x80, 0x26, 0x44, 0x20, 0x10, 0x4f, 0x04, 0x13, +0x00, 0x0a, 0xa1, 0x33, 0xa4, 0xce, 0x84, 0x03, 0x84, 0x22, 0x49, 0xfd, 0x05, 0xc0, 0x44, 0x70, +0x00, 0x60, 0xd5, 0x1b, 0x84, 0x01, 0x10, 0x03, 0x80, 0x26, 0x44, 0x70, 0x00, 0x50, 0xd5, 0x15, +0x3c, 0x1c, 0x36, 0xe2, 0xc1, 0x0a, 0x00, 0x10, 0x81, 0xae, 0x4c, 0x10, 0x40, 0x07, 0x84, 0x21, +0x3e, 0x10, 0x84, 0xfa, 0x84, 0xe7, 0xd5, 0x09, 0x2e, 0x50, 0x84, 0xf6, 0xd8, 0x02, 0xd5, 0x04, +0x84, 0x01, 0x3e, 0x00, 0x84, 0xfa, 0x84, 0xe5, 0x3c, 0x6e, 0x21, 0x36, 0x00, 0x13, 0x00, 0x20, +0x3e, 0x10, 0x84, 0xf6, 0xd5, 0x06, 0x80, 0x06, 0x84, 0x40, 0x3e, 0x20, 0x84, 0xf6, 0x80, 0xc0, +0x3c, 0x0c, 0x21, 0x37, 0x84, 0xa2, 0xd8, 0x07, 0xc7, 0x06, 0x3c, 0x2d, 0xff, 0x08, 0x80, 0x27, +0x80, 0x06, 0xdd, 0x22, 0x80, 0x07, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x84, 0x00, 0x80, 0xe0, +0xd5, 0xec, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xc4, 0x50, 0x6f, 0x80, 0x30, 0x3c, 0x0c, 0x28, 0xb7, +0x80, 0x26, 0x49, 0xfd, 0x3e, 0x72, 0x3c, 0x4d, 0xff, 0x14, 0xa6, 0xf0, 0x84, 0x04, 0x94, 0x47, +0x44, 0x20, 0x30, 0x74, 0xdd, 0x24, 0xa6, 0x30, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x0b, 0xc0, 0x0e, +0x84, 0x62, 0x4c, 0x01, 0x80, 0x06, 0x84, 0x26, 0x4c, 0x00, 0xc0, 0xf7, 0xd5, 0x06, 0x84, 0x03, +0x10, 0x0f, 0x80, 0x04, 0x84, 0xc0, 0xd5, 0x05, 0x84, 0x02, 0x10, 0x0f, 0x80, 0x04, 0x84, 0xc1, +0x50, 0x7f, 0x80, 0x30, 0xa6, 0x7b, 0x50, 0x8f, 0x80, 0x08, 0x80, 0x08, 0x49, 0xfd, 0x3e, 0x87, +0xa6, 0xfb, 0xa6, 0x79, 0x9e, 0xde, 0xa6, 0x38, 0x10, 0x3f, 0x80, 0x06, 0x84, 0x61, 0x10, 0x1f, +0x80, 0x05, 0x4c, 0x01, 0xc0, 0x09, 0x3c, 0x5c, 0x28, 0x70, 0xa6, 0xfa, 0x80, 0x48, 0x50, 0x4f, +0x80, 0x0e, 0xd5, 0x06, 0x84, 0x60, 0x3c, 0x5c, 0x28, 0x70, 0x80, 0x83, 0x80, 0x48, 0xdd, 0x25, +0x80, 0xe0, 0x2e, 0x01, 0xf6, 0x10, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x42, 0x4c, 0x70, 0xc0, 0x40, +0x00, 0x0f, 0x80, 0x30, 0xc0, 0x04, 0x84, 0x62, 0x4c, 0x01, 0xc0, 0x2c, 0x50, 0x0f, 0x80, 0x37, +0x50, 0x1f, 0x80, 0x0e, 0x49, 0xff, 0xf2, 0x77, 0xc0, 0x24, 0x00, 0x2f, 0x80, 0x37, 0x2e, 0x01, +0xf6, 0x14, 0x4c, 0x01, 0x00, 0x15, 0x84, 0x81, 0x3e, 0x41, 0xf6, 0x10, 0x3e, 0x21, 0xf6, 0x14, +0x80, 0x1f, 0x49, 0xff, 0xec, 0xf0, 0x84, 0x40, 0x84, 0x01, 0x46, 0x10, 0x00, 0x95, 0x58, 0x10, +0x86, 0x20, 0x80, 0x62, 0x80, 0x82, 0x80, 0xa0, 0x49, 0xfc, 0x8f, 0x07, 0x3c, 0x4d, 0xff, 0x14, +0x00, 0x3f, 0x80, 0x37, 0x84, 0x04, 0x84, 0x21, 0x44, 0x20, 0x30, 0xab, 0x48, 0x00, 0x00, 0x94, +0x2e, 0x11, 0xf6, 0x0f, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x0b, 0x3c, 0x4d, 0xff, 0x14, 0x00, 0x3f, +0x80, 0x30, 0x84, 0x04, 0x44, 0x20, 0x30, 0xac, 0x48, 0x00, 0x00, 0x86, 0x84, 0x21, 0x4c, 0x60, +0xc0, 0x4f, 0x4c, 0x73, 0x40, 0x4d, 0x3e, 0x68, 0xa2, 0xc8, 0xa6, 0x30, 0x4c, 0x03, 0xc0, 0x48, +0x02, 0x93, 0x00, 0x04, 0x8f, 0x21, 0x40, 0x94, 0x80, 0x13, 0x12, 0x93, 0x00, 0x04, 0x4e, 0x93, +0x00, 0x3f, 0x46, 0x00, 0x04, 0x90, 0x04, 0x80, 0x00, 0x4f, 0x40, 0x84, 0x1c, 0x08, 0x93, 0x17, +0x49, 0xfd, 0x82, 0xbf, 0xe2, 0x08, 0xe9, 0x03, 0x4e, 0x83, 0x00, 0x09, 0x3c, 0x2c, 0x28, 0x9c, +0x84, 0x00, 0x9c, 0x91, 0x3c, 0x2e, 0x28, 0x9c, 0xd5, 0x26, 0x2e, 0x00, 0x84, 0xf5, 0xc0, 0x03, +0x80, 0x09, 0xd5, 0x21, 0x00, 0x3f, 0x80, 0x31, 0xa0, 0x36, 0x84, 0x46, 0xae, 0xf2, 0x98, 0x02, +0x50, 0x1f, 0x80, 0x08, 0x49, 0xfe, 0x33, 0x07, 0xa0, 0x35, 0x44, 0x10, 0x20, 0x00, 0x49, 0xfd, +0x42, 0x5e, 0x84, 0x03, 0x44, 0x10, 0x20, 0x00, 0xa8, 0x37, 0x3c, 0x1e, 0x21, 0x30, 0x49, 0xfd, +0x40, 0x1a, 0x3c, 0x4d, 0xff, 0x14, 0x80, 0x68, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x72, +0xdd, 0x24, 0x80, 0x07, 0x84, 0x41, 0x3c, 0x28, 0x51, 0x68, 0xc8, 0x13, 0x49, 0xfd, 0x3b, 0xdb, +0x3c, 0x1d, 0xff, 0xaa, 0x84, 0x00, 0xdd, 0x21, 0x84, 0x22, 0x3c, 0x1e, 0x28, 0xb9, 0x3c, 0x4d, +0xff, 0x14, 0x44, 0x10, 0x02, 0x00, 0x84, 0x04, 0x44, 0x20, 0x30, 0x73, 0x80, 0x67, 0xdd, 0x24, +0x2e, 0x01, 0xf6, 0x0f, 0xc8, 0x13, 0x84, 0x01, 0x4c, 0x70, 0x40, 0x11, 0x3c, 0x0c, 0x28, 0xb7, +0x49, 0xfd, 0x3f, 0x81, 0x92, 0x00, 0x3c, 0x1c, 0x28, 0xb7, 0x80, 0x1f, 0x00, 0x10, 0x80, 0x24, +0x10, 0x1f, 0x80, 0x07, 0x3c, 0x1c, 0x28, 0x6c, 0xdd, 0x21, 0x3c, 0x1c, 0x28, 0x97, 0x44, 0x20, +0x30, 0x75, 0x9c, 0x49, 0x3c, 0x1e, 0x28, 0x97, 0x3c, 0x4d, 0xff, 0x14, 0x3c, 0x3c, 0x28, 0xb9, +0x84, 0x22, 0x84, 0x04, 0xdd, 0x24, 0xec, 0x3c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xec, 0x3c, 0x9c, 0x1b, 0x23, 0x84, 0x20, 0x10, 0x1f, 0x80, 0x0f, 0x83, 0x80, +0x2e, 0x80, 0x6c, 0x99, 0x4e, 0x92, 0x00, 0x89, 0x3c, 0x2c, 0x36, 0xe2, 0xca, 0x04, 0x44, 0x20, +0x00, 0xff, 0xd5, 0x03, 0x00, 0x21, 0x01, 0xae, 0x4c, 0x81, 0x40, 0x14, 0x3c, 0x6c, 0x01, 0x04, +0x44, 0x20, 0x00, 0x30, 0x42, 0x64, 0x08, 0x73, 0x3c, 0x70, 0x3c, 0xda, 0x84, 0x00, 0x49, 0xfd, +0x0d, 0x12, 0x80, 0x40, 0x80, 0x27, 0x80, 0x06, 0x49, 0xfc, 0x3f, 0xbd, 0x48, 0x00, 0x00, 0x6c, +0x3c, 0x7c, 0x36, 0xd8, 0xc7, 0x53, 0x50, 0x24, 0x7f, 0xfa, 0x96, 0x90, 0x84, 0x01, 0xf2, 0x81, +0xb6, 0x1f, 0x50, 0x6f, 0x80, 0x0f, 0xb4, 0x67, 0x3c, 0x5c, 0x1b, 0x23, 0xdb, 0x05, 0x84, 0x60, +0xa0, 0x7c, 0xb6, 0x7f, 0xd5, 0x3c, 0xa6, 0x7e, 0xe6, 0x23, 0xe8, 0x38, 0x84, 0x02, 0x00, 0x91, +0x80, 0x20, 0x4c, 0x10, 0x00, 0x0d, 0xb4, 0x3f, 0xc9, 0x0a, 0x80, 0x09, 0x49, 0xfd, 0x0f, 0x79, +0x81, 0x40, 0x80, 0x08, 0x49, 0xfd, 0x0f, 0x75, 0xe3, 0x40, 0xe9, 0x28, 0xf3, 0x01, 0xe6, 0x64, +0xe8, 0x04, 0x2e, 0x10, 0x84, 0xfd, 0xc9, 0x22, 0x80, 0x09, 0x80, 0x26, 0x80, 0x48, 0x49, 0xfc, +0x44, 0xa6, 0xc0, 0x1c, 0x3c, 0x1c, 0x36, 0xe2, 0xc1, 0x0a, 0x00, 0x50, 0x81, 0xae, 0x4c, 0x54, +0xc0, 0x07, 0x3e, 0x08, 0x6c, 0x88, 0x80, 0x28, 0x49, 0xfc, 0x49, 0x31, 0x80, 0x68, 0x84, 0x06, +0x84, 0x21, 0x44, 0x20, 0x70, 0x7c, 0x80, 0x89, 0x49, 0xfd, 0x04, 0x01, 0x3c, 0x0c, 0x1c, 0x91, +0x81, 0x09, 0x9c, 0x01, 0x3c, 0x0e, 0x1c, 0x91, 0xd5, 0x41, 0xa0, 0x7c, 0x4c, 0x13, 0x80, 0x07, +0xc1, 0x05, 0xb4, 0x01, 0xc0, 0x03, 0x80, 0xe1, 0xd5, 0xb7, 0x50, 0x24, 0x7f, 0xfa, 0x96, 0x90, +0xe6, 0x44, 0xe9, 0x34, 0x3c, 0x2c, 0x1b, 0x23, 0x00, 0x21, 0x00, 0x22, 0xc2, 0x06, 0x3c, 0x2d, +0xfe, 0xd8, 0x80, 0x08, 0xdd, 0x22, 0xd5, 0x06, 0x3c, 0x2d, 0xfe, 0xd9, 0x80, 0x08, 0x80, 0x3c, +0xdd, 0x22, 0xc8, 0x24, 0x85, 0x21, 0x4f, 0xc3, 0x00, 0x65, 0x3c, 0x7c, 0x36, 0xd8, 0xc7, 0x61, +0x50, 0x6f, 0x80, 0x0f, 0x45, 0xc1, 0xc8, 0x1c, 0xa6, 0x3e, 0x80, 0x26, 0x84, 0x40, 0xe6, 0x03, +0xe8, 0x0d, 0x4e, 0x92, 0x00, 0x06, 0xb4, 0xa7, 0x3c, 0x0c, 0x1b, 0x23, 0xd0, 0x07, 0xb4, 0x07, +0x00, 0x80, 0x00, 0x20, 0x80, 0x08, 0xdd, 0x3c, 0xc8, 0x09, 0xa0, 0x3c, 0x4c, 0x03, 0x80, 0x4a, +0xc0, 0x48, 0xb4, 0x20, 0xc1, 0x46, 0x80, 0xe0, 0xd5, 0xe8, 0x3c, 0x0c, 0x01, 0x04, 0x44, 0x10, +0x00, 0x30, 0x42, 0x04, 0x04, 0x73, 0x3e, 0x68, 0x6c, 0x88, 0xa8, 0x31, 0x3c, 0x1d, 0xfe, 0xce, +0x10, 0x83, 0x00, 0x11, 0x80, 0x08, 0xdd, 0x21, 0x84, 0x00, 0x84, 0x3f, 0x49, 0xfc, 0x9d, 0x0b, +0xa0, 0x72, 0x80, 0x08, 0x5c, 0x10, 0x80, 0x01, 0x49, 0xfc, 0x9c, 0x67, 0x84, 0x02, 0xa8, 0x32, +0xa0, 0x31, 0x00, 0x33, 0x00, 0x11, 0xa1, 0x03, 0x84, 0x21, 0x84, 0x06, 0x44, 0x20, 0x70, 0x76, +0xd5, 0x18, 0x49, 0xfc, 0x3e, 0x74, 0xc0, 0x0a, 0x00, 0x03, 0x00, 0x14, 0xc8, 0x07, 0x84, 0x21, +0x10, 0x13, 0x00, 0x14, 0x3c, 0x1d, 0xfe, 0xdd, 0xdd, 0x21, 0x84, 0x00, 0x84, 0x3f, 0x49, 0xfc, +0x9c, 0xea, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, 0x70, 0x77, 0x84, 0x60, 0x44, 0x40, 0x00, 0xff, +0x49, 0xfd, 0x03, 0x7d, 0x3c, 0x0c, 0x1b, 0x23, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x00, 0x1f, 0x80, 0x0f, 0x3e, 0x68, 0x6c, 0x88, 0x84, 0x00, 0xa8, 0x32, 0xa8, 0x31, 0xc9, 0xe6, +0xd5, 0xd9, 0x3a, 0x6f, 0xa8, 0xbc, 0x2e, 0x20, 0x02, 0xd9, 0x80, 0xc0, 0x96, 0x08, 0xc2, 0x02, +0xc0, 0x48, 0x44, 0x12, 0xd8, 0x30, 0xce, 0x04, 0x3e, 0x08, 0x79, 0x60, 0xd5, 0x02, 0x80, 0x06, +0xdd, 0x21, 0x81, 0x00, 0xe6, 0x14, 0xe8, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x3a, 0xce, 0x05, +0x84, 0xe1, 0x81, 0x27, 0x81, 0x47, 0xd5, 0x19, 0x80, 0x26, 0x3e, 0x08, 0x79, 0x60, 0x84, 0x4a, +0x00, 0xa3, 0x00, 0x00, 0x00, 0x93, 0x00, 0x03, 0x00, 0x73, 0x00, 0x09, 0x49, 0xfd, 0x61, 0xc3, +0x2e, 0x10, 0x79, 0x69, 0x54, 0xa5, 0x00, 0x01, 0x54, 0x10, 0x80, 0x7f, 0x3e, 0x10, 0x79, 0x69, +0x54, 0x94, 0x80, 0x01, 0x42, 0x73, 0x98, 0x0b, 0x8b, 0x0a, 0x40, 0x94, 0x24, 0x01, 0x40, 0x74, +0x9c, 0x01, 0xe6, 0xf4, 0xe8, 0x02, 0xce, 0x05, 0x3e, 0x08, 0x79, 0x60, 0x49, 0xfc, 0x95, 0xc1, +0x3c, 0x0c, 0x36, 0xe2, 0x3e, 0x18, 0x79, 0x60, 0x49, 0xfc, 0x91, 0x79, 0x2e, 0x10, 0xda, 0xa1, +0x58, 0x10, 0x80, 0x01, 0x3e, 0x10, 0xda, 0xa1, 0x84, 0x3f, 0x3e, 0x10, 0xda, 0x9e, 0x84, 0x00, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x84, 0xe0, 0x80, 0xc0, 0x80, 0x27, +0x40, 0x03, 0x80, 0x06, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x90, 0x44, 0x30, 0x02, 0x4c, +0x49, 0xfb, 0x80, 0x2d, 0xa0, 0x36, 0x80, 0x27, 0x40, 0x03, 0x80, 0x06, 0x46, 0x20, 0x00, 0x96, +0x58, 0x21, 0x04, 0x90, 0x44, 0x30, 0x02, 0x4d, 0x49, 0xfb, 0x80, 0x21, 0xa0, 0x36, 0x00, 0x70, +0x00, 0x08, 0x3c, 0x1d, 0xff, 0x54, 0x84, 0x03, 0xdd, 0x21, 0xc7, 0x2d, 0x84, 0xa1, 0xdf, 0x02, +0xd5, 0x26, 0x04, 0x03, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x53, 0xc9, 0x1d, 0x84, 0x41, 0x10, 0x20, +0x00, 0x37, 0x84, 0x42, 0x80, 0x06, 0x49, 0xfd, 0xdd, 0xf0, 0x80, 0x27, 0x80, 0x06, 0x49, 0xfc, +0xb7, 0x56, 0x80, 0x06, 0x49, 0xfc, 0xb6, 0xa3, 0x2e, 0x10, 0xac, 0x15, 0xc1, 0x18, 0x3c, 0x5c, +0x2b, 0x07, 0xde, 0x15, 0x46, 0x00, 0x01, 0x20, 0x3c, 0x1c, 0x7d, 0x80, 0x9c, 0x49, 0x3c, 0x1e, +0x7d, 0x80, 0xd5, 0x0d, 0x00, 0x03, 0x00, 0x22, 0x84, 0xa1, 0xd8, 0x05, 0x80, 0x06, 0x49, 0xfd, +0xde, 0x5c, 0xd5, 0x05, 0x80, 0x06, 0x49, 0xfd, 0xde, 0x6e, 0x92, 0x00, 0x3c, 0x6e, 0x1f, 0xa4, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x2e, 0x20, 0xac, 0x15, +0x96, 0x00, 0xc2, 0x0d, 0x3c, 0x1c, 0x2b, 0x07, 0x00, 0x50, 0x80, 0x20, 0xd8, 0x08, 0x46, 0x10, +0x01, 0x20, 0x3c, 0x2c, 0x7d, 0x81, 0x9c, 0x91, 0x3c, 0x2e, 0x7d, 0x81, 0x49, 0xfc, 0x53, 0xe9, +0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe8, +0x81, 0x20, 0xa6, 0x00, 0x84, 0xa1, 0xd8, 0x43, 0x2e, 0x70, 0xac, 0x15, 0xcf, 0x04, 0x80, 0x27, +0x80, 0xc7, 0xd5, 0x1d, 0x3c, 0x0c, 0x2b, 0x07, 0x00, 0x00, 0x00, 0x20, 0x49, 0xfc, 0x3b, 0xdb, +0x04, 0x60, 0x00, 0x6d, 0x3c, 0x1c, 0x7d, 0x80, 0x3c, 0x7c, 0x7d, 0x81, 0xe6, 0xc3, 0xe9, 0x06, +0x9f, 0xb2, 0x97, 0xb0, 0x84, 0xa3, 0xd6, 0x04, 0xd5, 0x0a, 0x97, 0xb0, 0xd5, 0x08, 0x00, 0x20, +0x01, 0x1f, 0x84, 0x02, 0x54, 0x21, 0x00, 0x04, 0x40, 0x60, 0x08, 0x1a, 0x50, 0x8f, 0x80, 0x04, +0x80, 0x08, 0x49, 0xfb, 0xc3, 0x80, 0x80, 0x27, 0x50, 0x0f, 0x80, 0x08, 0x49, 0xfb, 0xc3, 0x7b, +0x80, 0x08, 0x84, 0x29, 0x84, 0x40, 0x44, 0x30, 0xfc, 0x4d, 0x10, 0x64, 0x00, 0x08, 0x49, 0xff, +0xeb, 0x0e, 0x00, 0x04, 0x80, 0x01, 0x84, 0xa1, 0xd0, 0x04, 0x2e, 0x00, 0xac, 0x15, 0xc8, 0x0e, +0x84, 0x00, 0x3c, 0x0e, 0x7d, 0x81, 0x3c, 0x0e, 0x7d, 0x80, 0xd5, 0x08, 0x84, 0x00, 0x80, 0x20, +0x84, 0x41, 0x44, 0x30, 0xfc, 0x4d, 0x49, 0xff, 0xea, 0xfa, 0xec, 0x18, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x96, 0xc8, 0x3c, 0x4c, 0x36, 0xe2, 0x95, 0x9b, +0x3e, 0x18, 0x7f, 0xf0, 0x99, 0xb1, 0x84, 0x20, 0xae, 0x74, 0x84, 0x28, 0xae, 0x75, 0x80, 0xe2, +0x96, 0x00, 0xc4, 0x07, 0x00, 0x52, 0x01, 0xae, 0xdb, 0x04, 0x3e, 0x09, 0xf6, 0xc0, 0xd5, 0x0e, +0xe6, 0x05, 0xe9, 0x05, 0x84, 0x09, 0x49, 0xfb, 0xca, 0x0c, 0x84, 0x00, 0x44, 0x10, 0x00, 0xe4, +0x42, 0x00, 0x04, 0x24, 0x3e, 0x18, 0x80, 0x28, 0x98, 0x01, 0xb6, 0x06, 0x80, 0x27, 0xb4, 0x06, +0x49, 0xfc, 0xa8, 0x85, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0xbc, 0xef, 0xf0, 0x97, 0x20, 0x54, 0x62, 0x00, 0x0f, 0x52, 0x23, 0x00, 0x10, 0x97, 0xd8, +0x96, 0x90, 0x81, 0x41, 0x81, 0x00, 0xe2, 0x47, 0xe9, 0x1c, 0xe6, 0x8f, 0xe8, 0x1a, 0x80, 0x3f, +0x84, 0x41, 0x49, 0xfd, 0xe5, 0xc2, 0x44, 0x50, 0x00, 0xff, 0x81, 0x3f, 0xd0, 0x12, 0x80, 0x8a, +0x80, 0x3f, 0x84, 0x40, 0xd5, 0x06, 0x08, 0x02, 0x00, 0x01, 0x9c, 0x91, 0x38, 0x01, 0x98, 0x08, +0x96, 0x10, 0x98, 0xca, 0xe2, 0x07, 0xe9, 0xf8, 0x80, 0x08, 0x49, 0xfd, 0xe6, 0x52, 0xc0, 0x02, +0x84, 0x0c, 0xec, 0x10, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0xa7, 0xc0, 0x00, 0x80, 0x00, 0x01, 0xe6, 0xf1, 0xe9, 0x03, 0x84, 0x8c, 0xd5, 0x24, 0x54, 0x44, +0x00, 0x0f, 0x52, 0x62, 0x00, 0x10, 0x50, 0xa0, 0x00, 0x03, 0x44, 0x00, 0xff, 0xf0, 0x97, 0xb0, +0x41, 0xc4, 0x00, 0x02, 0x80, 0x1c, 0x80, 0x2a, 0x84, 0x41, 0x80, 0x66, 0x49, 0xff, 0xff, 0xb9, +0x80, 0x80, 0xc8, 0x11, 0x9e, 0x39, 0x89, 0x00, 0x44, 0x10, 0xff, 0xf0, 0x40, 0x04, 0x04, 0x02, +0x4d, 0xc0, 0x00, 0x0a, 0x9a, 0xfe, 0x40, 0x15, 0x18, 0x00, 0x96, 0xd8, 0x84, 0x41, 0x49, 0xff, +0xff, 0xa8, 0x80, 0x80, 0x80, 0x24, 0x44, 0x00, 0xfc, 0x6b, 0x49, 0xfb, 0xd7, 0x68, 0xec, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x84, 0x40, 0x38, 0x10, +0x08, 0x00, 0x9c, 0x91, 0xc9, 0x04, 0x84, 0xa6, 0xda, 0xfb, 0xd5, 0x32, 0x80, 0x20, 0x08, 0x70, +0x80, 0x01, 0x3e, 0x38, 0x03, 0xb0, 0x08, 0x60, 0x80, 0x01, 0x50, 0x21, 0x80, 0x08, 0x08, 0x50, +0x80, 0x01, 0x40, 0x03, 0x20, 0x08, 0x08, 0x80, 0x80, 0x01, 0x40, 0x42, 0xc0, 0x08, 0x00, 0xa0, +0x80, 0x01, 0x00, 0x90, 0x80, 0x00, 0x98, 0x20, 0x10, 0x81, 0x80, 0x03, 0x10, 0x91, 0x80, 0x04, +0x10, 0xa1, 0x80, 0x05, 0xaf, 0xd8, 0xaf, 0x99, 0xaf, 0x5a, 0x98, 0x07, 0x50, 0x11, 0x80, 0x0c, +0x10, 0x7f, 0x80, 0x00, 0x10, 0xaf, 0x80, 0x05, 0x10, 0x9f, 0x80, 0x04, 0x10, 0x8f, 0x80, 0x03, +0x10, 0x5f, 0x80, 0x02, 0x10, 0x6f, 0x80, 0x01, 0x49, 0xfb, 0x70, 0x59, 0x92, 0x00, 0xec, 0x08, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3e, 0x78, 0x03, 0xb0, +0x04, 0x63, 0x80, 0x18, 0x96, 0x00, 0x44, 0x20, 0x00, 0x30, 0x42, 0x60, 0x08, 0x73, 0x96, 0x08, +0xce, 0x03, 0x84, 0x02, 0xd5, 0x27, 0xc8, 0x03, 0xa8, 0x31, 0xd5, 0x24, 0x84, 0x01, 0x10, 0x03, +0x00, 0x22, 0x80, 0x06, 0x49, 0xfc, 0xf8, 0xe7, 0x84, 0x02, 0xa8, 0x31, 0x04, 0x43, 0x00, 0x0a, +0xa6, 0xfa, 0xa6, 0x39, 0xa6, 0xb8, 0xa6, 0x7b, 0x40, 0x31, 0xc0, 0x08, 0x40, 0x00, 0x20, 0x08, +0x98, 0x18, 0x98, 0x02, 0x40, 0x10, 0xe0, 0x08, 0x40, 0x00, 0x04, 0x04, 0xa8, 0x22, 0x80, 0x06, +0xa0, 0xba, 0x04, 0x13, 0x00, 0x0a, 0xa1, 0xfb, 0xb6, 0x41, 0xa9, 0xc9, 0x49, 0xfc, 0xa5, 0x4d, +0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x20, 0x3e, 0x10, 0x04, 0x98, 0x3e, 0x10, 0x02, 0x74, 0x96, 0x00, 0x49, 0xfd, 0xcd, 0xb7, +0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x84, 0xa6, 0x80, 0xc0, 0xd8, 0x15, 0x46, 0x00, 0x04, 0x80, 0x04, 0x30, 0x00, 0x0a, 0x3c, 0x4c, +0x36, 0xe6, 0x54, 0x31, 0x80, 0x03, 0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x0d, 0x49, 0xfd, +0x01, 0x26, 0x84, 0x02, 0x3c, 0x0e, 0x36, 0xe6, 0x49, 0xfc, 0xc4, 0x23, 0xd5, 0x12, 0xc8, 0x0f, +0x3c, 0x4d, 0xff, 0x14, 0x3c, 0x3c, 0x36, 0xe6, 0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x0b, +0xdd, 0x24, 0x3c, 0x6e, 0x36, 0xe6, 0x49, 0xfc, 0xc2, 0x00, 0xd5, 0x03, 0x49, 0xfc, 0xc5, 0xab, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, +0xa6, 0x00, 0x3c, 0x0e, 0x01, 0x20, 0xc8, 0x02, 0xd5, 0x02, 0x84, 0x01, 0x49, 0xfd, 0x05, 0x3f, +0xa6, 0x72, 0xa6, 0x31, 0x40, 0x10, 0xa0, 0x08, 0x98, 0x48, 0x3e, 0x08, 0x03, 0xb0, 0x12, 0x10, +0x00, 0x6a, 0xa6, 0x74, 0xa6, 0xb3, 0x40, 0x10, 0xa0, 0x08, 0x98, 0x4a, 0x12, 0x10, 0x00, 0x6b, +0xa6, 0x75, 0x10, 0x10, 0x00, 0xd8, 0xa7, 0xb6, 0x10, 0x60, 0x00, 0xd9, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x96, 0x00, 0x80, 0xc1, 0x98, 0x48, 0x00, 0x50, 0xff, 0xff, +0xd0, 0x03, 0x84, 0x01, 0xd5, 0x16, 0x9c, 0x32, 0x49, 0xff, 0xff, 0x17, 0x50, 0x03, 0x00, 0x08, +0x49, 0xff, 0xf2, 0xd3, 0x50, 0x03, 0x00, 0x0e, 0x49, 0xff, 0xe1, 0x85, 0x50, 0x03, 0x00, 0x11, +0x49, 0xff, 0xff, 0xc5, 0x50, 0x03, 0x00, 0x27, 0x49, 0xff, 0xe1, 0x8d, 0x92, 0x00, 0x84, 0x00, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xc0, 0xa7, 0x88, 0x80, 0xe0, +0x84, 0x01, 0x4c, 0x60, 0x00, 0x09, 0x84, 0x23, 0x4c, 0x60, 0x80, 0x06, 0x84, 0xa5, 0xd6, 0x03, +0x8c, 0x1d, 0xd5, 0x39, 0x49, 0xfc, 0x6e, 0x85, 0x81, 0x00, 0xc0, 0x09, 0xe6, 0xc2, 0xe9, 0x07, +0x2e, 0x00, 0x05, 0x05, 0x96, 0x04, 0xc0, 0x05, 0xe7, 0x02, 0xe8, 0x03, 0x80, 0x26, 0xd5, 0x02, +0x84, 0x21, 0x04, 0x23, 0x80, 0x6d, 0x80, 0x07, 0x49, 0xfc, 0x62, 0x2d, 0x00, 0x33, 0x81, 0xec, +0x80, 0x03, 0x4c, 0x03, 0x40, 0x03, 0xd5, 0x1e, 0x4e, 0x83, 0x00, 0x17, 0x84, 0xa1, 0xde, 0x14, +0x00, 0x43, 0x81, 0xb0, 0x10, 0x03, 0x81, 0xed, 0x10, 0x43, 0x81, 0xc7, 0x00, 0x03, 0x81, 0xae, +0x80, 0x3f, 0x10, 0x3f, 0x80, 0x0f, 0x44, 0x30, 0x00, 0x2e, 0x10, 0x4f, 0x80, 0x08, 0x12, 0x3f, +0x80, 0x0e, 0x49, 0xfc, 0x08, 0x9a, 0x10, 0x63, 0x81, 0xec, 0x80, 0x07, 0x80, 0x26, 0x49, 0xfc, +0x61, 0x5e, 0x84, 0x00, 0xec, 0x40, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x14, 0x0d, 0x96, 0x49, 0x80, 0xe0, 0x4c, 0x11, 0x40, 0x1d, +0x84, 0x01, 0x84, 0x20, 0x84, 0x46, 0x49, 0xfd, 0x0d, 0x02, 0xc0, 0x18, 0xb4, 0xc0, 0x84, 0x0e, +0xae, 0x30, 0x84, 0x04, 0xae, 0x31, 0x84, 0x01, 0xae, 0x32, 0x84, 0x0d, 0xae, 0x33, 0x9c, 0x07, +0xae, 0x34, 0x9c, 0x3b, 0x49, 0xfc, 0x97, 0x57, 0xae, 0x35, 0x84, 0x20, 0x84, 0x01, 0x49, 0xfd, +0x10, 0x8c, 0x84, 0x00, 0xd5, 0x03, 0x49, 0xfb, 0xad, 0x56, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0x96, 0x90, 0x4c, 0x01, 0x00, 0x04, +0x84, 0x00, 0xd5, 0x08, 0x80, 0x01, 0x84, 0x46, 0x80, 0x23, 0x49, 0xfd, 0x5e, 0xd6, 0x5c, 0x00, +0x00, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x3c, 0x6c, 0x28, 0x55, 0x54, 0x80, 0x00, 0xff, 0x81, 0x22, 0x97, 0xc8, 0x96, 0x18, 0xc6, 0x49, +0x3e, 0x58, 0x03, 0xb0, 0x00, 0x23, 0x00, 0xbe, 0x50, 0x12, 0x81, 0x34, 0x40, 0x32, 0x88, 0x1a, +0x40, 0x30, 0x88, 0x1b, 0x84, 0x21, 0x4c, 0x80, 0xc0, 0x0e, 0x80, 0x24, 0x49, 0xff, 0xff, 0xd3, +0x80, 0xc0, 0xc8, 0x08, 0x80, 0x67, 0x80, 0x88, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, 0x70, 0x2f, +0xd5, 0x2e, 0x2e, 0x00, 0x9c, 0x26, 0x54, 0x10, 0x00, 0x40, 0xc1, 0x0c, 0x3e, 0x38, 0xa1, 0x54, +0x00, 0x21, 0x80, 0x17, 0x80, 0x07, 0x80, 0x29, 0x8c, 0x70, 0x49, 0xff, 0xff, 0xbc, 0x80, 0xc0, +0xd5, 0x18, 0x96, 0x02, 0x4e, 0x04, 0x00, 0x15, 0x80, 0x29, 0x80, 0x07, 0x49, 0xfd, 0x11, 0x71, +0x2e, 0x50, 0x02, 0x92, 0xd0, 0x0d, 0x3e, 0x38, 0xa1, 0x54, 0x10, 0x71, 0x80, 0x17, 0x50, 0x01, +0x80, 0x10, 0x80, 0x29, 0x84, 0x46, 0x49, 0xfd, 0x5e, 0x6e, 0x84, 0xc1, 0xd5, 0x02, 0x84, 0xc0, +0x80, 0x88, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, 0x70, 0x2e, 0x80, 0x66, 0x49, 0xfc, 0xff, 0xe7, +0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x3e, 0x18, 0x5c, 0x90, 0x00, 0x20, 0x80, 0x2c, 0xca, 0x0c, 0xa0, 0x8b, 0x4c, 0x20, 0x00, 0x0a, +0xc8, 0x08, 0x84, 0xa1, 0xd2, 0x06, 0x00, 0x20, 0x80, 0x36, 0xc2, 0x03, 0x10, 0x00, 0x80, 0x36, +0x49, 0xfb, 0xfb, 0xad, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x3e, 0x68, 0x5c, 0x90, 0x00, 0x13, 0x00, 0x30, 0x96, 0x00, 0xc1, 0x6f, +0x50, 0x10, 0x7f, 0xf1, 0x84, 0x42, 0xe2, 0x41, 0xe9, 0x68, 0x2e, 0x00, 0x73, 0x33, 0xc8, 0x3f, +0x00, 0x13, 0x00, 0x33, 0xc1, 0x3c, 0x00, 0x53, 0x00, 0x34, 0xd9, 0x39, 0x49, 0xfd, 0x08, 0x73, +0x3c, 0x1d, 0xfc, 0x60, 0x80, 0xe0, 0xdd, 0x21, 0x81, 0x20, 0xc8, 0x12, 0x00, 0x03, 0x00, 0x2e, +0x49, 0xfc, 0x88, 0x8b, 0x80, 0xe0, 0x84, 0xbf, 0xdf, 0x2f, 0x3c, 0x4d, 0xff, 0x16, 0x00, 0x33, +0x00, 0x2e, 0xa0, 0xb3, 0x80, 0x29, 0x44, 0x00, 0x70, 0x1b, 0xdd, 0x24, 0xd5, 0x25, 0x00, 0x03, +0x00, 0x2e, 0x49, 0xfc, 0x88, 0x7a, 0x84, 0x3f, 0x81, 0x00, 0x4c, 0x00, 0xc0, 0x0b, 0x3c, 0x4d, +0xff, 0x16, 0x00, 0x33, 0x00, 0x2e, 0xa0, 0xb3, 0x44, 0x00, 0x70, 0x1b, 0x84, 0x21, 0xdd, 0x24, +0x80, 0x07, 0x80, 0x29, 0x49, 0xfc, 0xf8, 0x69, 0x84, 0x3f, 0x80, 0xe0, 0x4c, 0x80, 0x80, 0x0d, +0x80, 0x28, 0x49, 0xfc, 0xf8, 0xc4, 0x40, 0x74, 0x00, 0x1b, 0xd5, 0x06, 0x2e, 0x00, 0x5c, 0xbe, +0x49, 0xfc, 0x88, 0x5b, 0x80, 0xe0, 0x3c, 0x0c, 0x17, 0x27, 0x8e, 0x0f, 0xe6, 0x03, 0xe8, 0x08, +0x84, 0x01, 0x49, 0xfc, 0x98, 0x34, 0x84, 0x3f, 0x3c, 0x1e, 0x1b, 0x25, 0xd5, 0x04, 0x84, 0x00, +0x49, 0xfc, 0x98, 0x2d, 0x3c, 0x30, 0x2e, 0x4e, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, +0x70, 0x95, 0x80, 0x87, 0x49, 0xfd, 0x01, 0x2f, 0x3c, 0x3c, 0x00, 0x10, 0x3c, 0x0c, 0x17, 0x27, +0x80, 0x47, 0x84, 0x20, 0xdd, 0x23, 0xd5, 0x03, 0x49, 0xfb, 0xff, 0xf1, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x48, 0xe6, 0x02, +0xe8, 0x07, 0x2e, 0x30, 0x5c, 0xc6, 0xc3, 0x04, 0x84, 0x60, 0x3e, 0x30, 0x5c, 0xc6, 0x49, 0xfb, +0xfb, 0xf4, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x50, 0x60, 0x00, 0x98, 0x00, 0x00, 0x01, 0xae, 0x54, 0xa1, 0x00, 0xff, 0xf1, 0x81, 0x49, 0xfc, +0x98, 0xf2, 0x81, 0x00, 0x00, 0x03, 0x01, 0x16, 0x80, 0x28, 0x49, 0xfc, 0x3d, 0x26, 0x80, 0x40, +0x04, 0x03, 0x00, 0x46, 0xc0, 0x04, 0x04, 0x93, 0x00, 0x07, 0xd5, 0x03, 0x04, 0x93, 0x00, 0x06, +0xb6, 0x5f, 0x80, 0x09, 0x80, 0x28, 0x49, 0xfc, 0xf8, 0x62, 0x83, 0x80, 0xb4, 0x5f, 0xc0, 0x0b, +0x04, 0x23, 0x00, 0x46, 0x84, 0x03, 0x84, 0x21, 0x40, 0x90, 0x88, 0x1a, 0x40, 0x90, 0x08, 0x1b, +0x84, 0xe0, 0xd5, 0x4e, 0x80, 0x02, 0x80, 0x29, 0x49, 0xfc, 0xf8, 0x51, 0x80, 0xe0, 0x04, 0x23, +0x00, 0x0c, 0xc8, 0x67, 0xc2, 0x69, 0x84, 0xa2, 0xd2, 0x67, 0x3c, 0x4d, 0xff, 0x16, 0x00, 0x13, +0x01, 0x16, 0x44, 0x00, 0x70, 0x14, 0x80, 0x67, 0xdd, 0x24, 0xd5, 0x56, 0x2e, 0x00, 0xda, 0x8c, +0x02, 0x13, 0x00, 0x7f, 0x80, 0xe2, 0x9a, 0x08, 0x12, 0x03, 0x00, 0x7f, 0x84, 0x01, 0xf3, 0x01, +0xae, 0x18, 0xd5, 0x4a, 0x80, 0x2a, 0x3e, 0x08, 0x6c, 0x88, 0x49, 0xfc, 0x44, 0x10, 0x44, 0x10, +0x00, 0x30, 0x80, 0x1c, 0x42, 0x04, 0x84, 0x73, 0x40, 0x23, 0xa0, 0x01, 0x94, 0x94, 0x92, 0x44, +0x80, 0x27, 0x49, 0xfc, 0x97, 0x9e, 0x2e, 0x10, 0x6c, 0x9d, 0x92, 0x22, 0x94, 0x4a, 0x3e, 0x10, +0x6c, 0x9d, 0x84, 0xe1, 0x84, 0x21, 0x3e, 0x10, 0xda, 0x8a, 0x14, 0x73, 0x00, 0x0c, 0x44, 0x04, +0x00, 0x00, 0x49, 0xfc, 0x7e, 0x26, 0x02, 0x33, 0x00, 0x14, 0xa9, 0xf2, 0x12, 0x33, 0x00, 0x15, +0x3c, 0x2c, 0x00, 0x05, 0x50, 0x13, 0x7f, 0x68, 0x84, 0x02, 0xdd, 0x22, 0x81, 0x27, 0x02, 0x13, +0x00, 0x14, 0xa0, 0x36, 0x98, 0x49, 0x49, 0xfc, 0xf7, 0xa0, 0xa8, 0x35, 0x02, 0x23, 0x00, 0x11, +0xa0, 0x36, 0x80, 0x28, 0x49, 0xfc, 0xf7, 0xc9, 0x93, 0x21, 0xa8, 0x36, 0x4e, 0x92, 0x00, 0x07, +0x80, 0x28, 0x50, 0x03, 0x7f, 0x68, 0x49, 0xfc, 0x43, 0x26, 0xa8, 0x37, 0x3c, 0x1d, 0xfe, 0xdf, +0x00, 0x03, 0x01, 0x16, 0xdd, 0x21, 0x80, 0x07, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0xc2, 0xa6, 0x80, 0xfc, 0xd5, 0xf9, 0xa0, 0x36, 0x84, 0x21, 0x49, 0xfc, 0xf7, 0x84, 0x80, 0xe0, +0x3d, 0xcc, 0x01, 0x04, 0x00, 0x93, 0x01, 0x16, 0x4e, 0xa2, 0xff, 0xab, 0xd5, 0xa4, 0x3a, 0x6f, +0xa8, 0xbc, 0x97, 0xc0, 0x44, 0x50, 0x00, 0xfe, 0x4c, 0x72, 0x80, 0xb8, 0x3c, 0x6c, 0x36, 0xf5, +0x85, 0x00, 0x84, 0x1f, 0xa8, 0x33, 0x00, 0xa3, 0x00, 0xb6, 0x3c, 0x8e, 0x36, 0xf5, 0x14, 0x83, +0x00, 0x05, 0x00, 0x03, 0x00, 0xb6, 0x80, 0x28, 0x49, 0xfc, 0x3b, 0xf7, 0x00, 0x33, 0x00, 0xb6, +0x84, 0x06, 0x84, 0x21, 0x44, 0x20, 0x70, 0x66, 0x80, 0x87, 0x49, 0xfc, 0xfe, 0x70, 0x2e, 0x90, +0xda, 0xd1, 0x84, 0xa1, 0x4c, 0x92, 0xc0, 0x10, 0x49, 0xfb, 0x93, 0xcb, 0x4c, 0x04, 0xc0, 0x09, +0x3c, 0x3d, 0xfc, 0x06, 0x80, 0x28, 0x44, 0x00, 0x00, 0x3d, 0x80, 0x48, 0xdd, 0x23, 0x84, 0x20, +0x3e, 0x10, 0xda, 0xd1, 0x2e, 0x00, 0xda, 0xcc, 0x54, 0x00, 0x00, 0x03, 0xc0, 0x08, 0x3c, 0x3d, +0xfc, 0x06, 0x84, 0x20, 0x44, 0x00, 0x00, 0x49, 0x80, 0x41, 0xdd, 0x23, 0x44, 0x50, 0x00, 0x1a, +0xdf, 0x0a, 0x02, 0x03, 0x00, 0x51, 0x58, 0x00, 0x01, 0x00, 0x12, 0x03, 0x00, 0x51, 0x44, 0x00, +0x00, 0x3d, 0xd5, 0x1f, 0x9f, 0x6a, 0xdf, 0x1f, 0x00, 0x03, 0x00, 0xb4, 0x84, 0xac, 0xd8, 0x07, +0x02, 0x03, 0x00, 0x51, 0x58, 0x00, 0x01, 0x00, 0x12, 0x03, 0x00, 0x51, 0x02, 0x13, 0x00, 0x51, +0x54, 0x00, 0x80, 0x04, 0xc8, 0x10, 0x02, 0x23, 0x00, 0x52, 0x2e, 0x00, 0x04, 0xe3, 0x9c, 0x91, +0xe0, 0x40, 0xe9, 0x09, 0x58, 0x10, 0x81, 0x00, 0x12, 0x13, 0x00, 0x51, 0x44, 0x00, 0x00, 0x3e, +0x10, 0x03, 0x00, 0xbc, 0x02, 0x13, 0x00, 0x51, 0x54, 0x00, 0x81, 0x00, 0xc0, 0x18, 0x3c, 0x2d, +0xfd, 0x15, 0x00, 0x13, 0x00, 0xbc, 0x80, 0x06, 0xdd, 0x22, 0x3c, 0x0c, 0x16, 0xdb, 0x84, 0xa3, +0xd8, 0x35, 0x2e, 0x00, 0x73, 0x2d, 0xc8, 0x32, 0x2e, 0x00, 0xa0, 0x88, 0x2e, 0x10, 0xa0, 0x87, +0x98, 0x08, 0x96, 0x00, 0xc8, 0x2b, 0x49, 0xfb, 0xd7, 0x42, 0xd5, 0x28, 0x44, 0x50, 0x00, 0x1c, +0xdf, 0x04, 0x54, 0x10, 0x90, 0x00, 0xc9, 0x0d, 0x80, 0x06, 0x80, 0x27, 0x49, 0xfd, 0x2c, 0xd7, +0x3c, 0x1d, 0xfd, 0x36, 0x80, 0x06, 0xdd, 0x21, 0x80, 0x06, 0x49, 0xfd, 0x2c, 0x92, 0x80, 0xc0, +0xc6, 0x15, 0x3c, 0x7c, 0x01, 0x04, 0x00, 0x13, 0x00, 0xb6, 0x02, 0x83, 0x00, 0x19, 0x44, 0x00, +0x00, 0x30, 0x42, 0x70, 0x80, 0x73, 0x89, 0x08, 0x84, 0x00, 0x49, 0xfd, 0x06, 0xac, 0x40, 0x14, +0x00, 0x13, 0x80, 0x40, 0x80, 0x07, 0x49, 0xfc, 0x39, 0x56, 0x3c, 0x2d, 0xfd, 0x13, 0x80, 0x26, +0x84, 0x04, 0xdd, 0x22, 0x84, 0x00, 0x84, 0x3f, 0x49, 0xfc, 0x97, 0x3d, 0x3c, 0x2d, 0xff, 0xe8, +0x44, 0x10, 0x00, 0x20, 0x80, 0x0a, 0xdd, 0x22, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0xa6, 0x82, 0x80, 0xc0, 0x97, 0xc9, 0x84, 0x60, 0x9c, 0x53, 0x44, 0x20, +0xff, 0xfe, 0x49, 0xff, 0xe3, 0xf8, 0x80, 0x06, 0x80, 0x27, 0x49, 0xfb, 0xb9, 0x22, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x37, 0x0c, +0x80, 0xc0, 0x96, 0x0c, 0x4e, 0x02, 0x00, 0xbf, 0x3c, 0x0c, 0x2a, 0xf7, 0x54, 0x00, 0x00, 0x80, +0x4e, 0x02, 0x00, 0xb9, 0x49, 0xfc, 0x95, 0x2b, 0x81, 0x00, 0x3c, 0x9c, 0x01, 0x04, 0x49, 0xfc, +0x95, 0x26, 0x49, 0xfc, 0x6c, 0x5c, 0x92, 0x00, 0xc0, 0x25, 0xb4, 0x20, 0xe6, 0x26, 0xe8, 0x05, +0x84, 0x21, 0x3e, 0x10, 0x02, 0xc9, 0xd5, 0x20, 0x80, 0x49, 0x44, 0x30, 0x00, 0x30, 0x42, 0x24, +0x0c, 0x73, 0x00, 0x01, 0x00, 0x22, 0x84, 0x41, 0x4c, 0x01, 0x40, 0x0b, 0x4c, 0x60, 0x40, 0x15, +0x56, 0x10, 0x80, 0x09, 0x40, 0x10, 0x88, 0x06, 0x3e, 0x10, 0x02, 0xc9, 0xd5, 0x10, 0x84, 0xa7, +0xde, 0x0b, 0x56, 0x00, 0x80, 0x0f, 0x5c, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x02, 0xc9, 0x48, 0x00, +0x00, 0x8a, 0x3e, 0x00, 0x02, 0xc9, 0x44, 0x50, 0x00, 0x13, 0xd6, 0x05, 0x44, 0x00, 0x00, 0x16, +0x4c, 0x60, 0x40, 0x45, 0x3c, 0x0c, 0x21, 0x37, 0x54, 0x00, 0x00, 0x11, 0xc0, 0x2e, 0x2e, 0x00, +0x02, 0xc9, 0xc0, 0x16, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x3e, 0x08, 0xa8, 0x40, +0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x07, 0x04, 0x10, 0x00, 0x08, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x08, +0xd5, 0x69, 0x04, 0x10, 0x00, 0x09, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x09, 0xd5, 0x63, 0x46, 0x00, +0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x3e, 0x08, 0xa8, 0x40, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x07, +0x04, 0x10, 0x00, 0x0a, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x0a, 0xd5, 0x54, 0x04, 0x10, 0x00, 0x0b, +0x9c, 0x49, 0x14, 0x10, 0x00, 0x0b, 0xd5, 0x4e, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, +0x3e, 0x08, 0xa8, 0x40, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x05, 0xa0, 0x42, 0x9c, 0x49, 0xa8, 0x42, +0xd5, 0x41, 0xa0, 0x43, 0x9c, 0x49, 0xa8, 0x43, 0xd5, 0x3d, 0x9d, 0x43, 0xde, 0x3b, 0x3c, 0x0c, +0x21, 0x37, 0x54, 0x00, 0x00, 0x11, 0xc0, 0x26, 0x2e, 0x00, 0x02, 0xc9, 0xc0, 0x12, 0x46, 0x00, +0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x3e, 0x08, 0xa8, 0x40, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x05, +0xa0, 0x44, 0x9c, 0x49, 0xa8, 0x44, 0xd5, 0x26, 0xa0, 0x45, 0x9c, 0x49, 0xa8, 0x45, 0xd5, 0x22, +0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x3e, 0x08, 0xa8, 0x40, 0x42, 0x10, 0xc0, 0x0b, +0xc9, 0x05, 0xa0, 0x46, 0x9c, 0x49, 0xa8, 0x46, 0xd5, 0x15, 0xa0, 0x47, 0x9c, 0x49, 0xa8, 0x47, +0xd5, 0x11, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x3e, 0x08, 0xa8, 0x40, 0x42, 0x10, +0xc0, 0x0b, 0xc9, 0x05, 0xb4, 0x20, 0x9c, 0x49, 0xb6, 0x20, 0xd5, 0x04, 0xa0, 0x41, 0x9c, 0x49, +0xa8, 0x41, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x3c, 0x0c, +0x16, 0xdb, 0x84, 0xa3, 0xd8, 0x14, 0x2e, 0x01, 0xf6, 0x0f, 0xc0, 0x04, 0x2e, 0x01, 0xf6, 0x0e, +0xc0, 0x09, 0x84, 0x08, 0x84, 0x20, 0x49, 0xfb, 0xd2, 0xa2, 0x84, 0x20, 0x3c, 0x1e, 0x16, 0xdb, +0xd5, 0x06, 0x49, 0xfd, 0x08, 0x74, 0x84, 0x0a, 0x3c, 0x0e, 0x16, 0xdb, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x3e, 0x08, 0x5b, 0x60, 0x84, 0x20, 0xae, 0x40, +0xa0, 0x43, 0x84, 0xa3, 0xd9, 0x63, 0x2e, 0x11, 0xf6, 0x0f, 0xc1, 0x04, 0x2e, 0x11, 0xf6, 0x0e, +0xc9, 0x03, 0x84, 0x20, 0xd5, 0x02, 0x84, 0x2a, 0xa8, 0x43, 0x84, 0xc0, 0x44, 0x80, 0x00, 0x13, +0x9d, 0xb1, 0x80, 0x06, 0x49, 0xfc, 0x35, 0xff, 0xc0, 0x0d, 0xb4, 0x60, 0x40, 0x21, 0xbc, 0x08, +0x92, 0x5e, 0x44, 0x50, 0x00, 0x10, 0xd3, 0x06, 0xca, 0x05, 0x14, 0x80, 0x00, 0x29, 0x49, 0xfb, +0xee, 0x22, 0x84, 0x05, 0x4c, 0x60, 0x7f, 0xee, 0x85, 0x00, 0x50, 0x6f, 0x80, 0x04, 0x45, 0xc2, +0x59, 0x9c, 0x50, 0x04, 0x00, 0x06, 0x49, 0xfd, 0x11, 0xd2, 0x80, 0xe0, 0xc0, 0x26, 0x02, 0x00, +0x00, 0x51, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x21, 0x80, 0x06, 0x49, 0xfb, 0x67, 0x30, 0x3c, 0x5c, +0x36, 0xf5, 0xdf, 0x12, 0x02, 0x03, 0x80, 0x51, 0x44, 0x10, 0x00, 0x13, 0x58, 0x00, 0x01, 0x00, +0x10, 0x13, 0x80, 0xbc, 0x12, 0x03, 0x80, 0x51, 0xf0, 0x01, 0x49, 0xfb, 0x67, 0x36, 0x50, 0x03, +0x80, 0xb7, 0xdd, 0x3c, 0xd5, 0x0a, 0xf0, 0x01, 0x49, 0xfb, 0x67, 0x2f, 0x3c, 0x2d, 0xfd, 0x15, +0x80, 0x07, 0x44, 0x10, 0x00, 0x13, 0xdd, 0x22, 0x8d, 0x01, 0x84, 0xa4, 0x4c, 0x82, 0xff, 0xd3, +0x2e, 0x01, 0xf6, 0x0f, 0xc0, 0x04, 0x2e, 0x01, 0xf6, 0x0e, 0xc8, 0x06, 0x84, 0x08, 0x84, 0x20, +0x49, 0xfb, 0xd2, 0x2d, 0xd5, 0x03, 0x49, 0xfd, 0x08, 0x02, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe8, 0x84, 0x21, 0x4c, 0x00, 0x81, 0x03, 0xc0, 0x08, +0x84, 0x4a, 0x4c, 0x01, 0x41, 0x13, 0x3e, 0x11, 0xf6, 0x0e, 0x3e, 0x11, 0xf6, 0x0f, 0x3c, 0x0c, +0x16, 0xdb, 0x84, 0x61, 0x4c, 0x01, 0x80, 0x0a, 0x2e, 0x01, 0xf6, 0x0f, 0x4c, 0x01, 0x80, 0x06, +0x2e, 0x01, 0xf6, 0x0e, 0x4c, 0x01, 0xc1, 0x02, 0x84, 0x63, 0x3c, 0x3e, 0x16, 0xdb, 0x84, 0x20, +0x84, 0x40, 0x50, 0x0f, 0x80, 0x17, 0x10, 0x1f, 0x80, 0x02, 0x12, 0x1f, 0x80, 0x00, 0xae, 0x80, +0x49, 0xfc, 0x90, 0x5f, 0x80, 0x1f, 0x49, 0xfc, 0x93, 0x36, 0x3c, 0x0d, 0xfe, 0xe4, 0x42, 0x00, +0x68, 0x0b, 0xc0, 0x05, 0x46, 0x00, 0x40, 0x00, 0x49, 0xfc, 0x7b, 0xb7, 0x84, 0xc0, 0x80, 0xe6, +0x9d, 0xb1, 0x80, 0x06, 0x49, 0xfc, 0x35, 0x6f, 0xc0, 0x14, 0xb4, 0x20, 0x40, 0x20, 0xbc, 0x08, +0x92, 0x5e, 0x44, 0x30, 0x00, 0x10, 0x4c, 0x11, 0x80, 0x0d, 0x8c, 0x70, 0x4c, 0x11, 0x80, 0x0a, +0xca, 0x08, 0x02, 0x00, 0x00, 0xc4, 0x44, 0x10, 0x00, 0x13, 0x49, 0xfb, 0xed, 0x04, 0x84, 0xe1, +0x84, 0x05, 0x4c, 0x60, 0x7f, 0xe7, 0x3c, 0x6d, 0xfe, 0xe4, 0x46, 0x10, 0x05, 0x00, 0x40, 0x63, +0x04, 0x02, 0xc6, 0x11, 0x84, 0x04, 0xb6, 0x1f, 0x49, 0xfc, 0x97, 0x39, 0x3c, 0x1c, 0x1e, 0xf0, +0xc1, 0x03, 0x80, 0x1f, 0xdd, 0x21, 0x2e, 0x00, 0x5b, 0x48, 0xc8, 0x02, 0xd5, 0x03, 0x49, 0xfb, +0xf0, 0xdc, 0x84, 0xc1, 0x3c, 0x2c, 0x1c, 0xde, 0x84, 0x63, 0x4c, 0x21, 0xc0, 0x0b, 0x49, 0xfc, +0x96, 0xf4, 0x2e, 0x00, 0x73, 0x94, 0xc8, 0x02, 0xd5, 0x03, 0x49, 0xfc, 0x82, 0x5e, 0x84, 0xc1, +0x2e, 0x01, 0xf6, 0x0f, 0xc0, 0x04, 0x2e, 0x01, 0xf6, 0x0e, 0xc8, 0x05, 0x49, 0xfc, 0x7c, 0xbf, +0x3c, 0x0e, 0x16, 0xdc, 0x49, 0xfc, 0x7c, 0xbb, 0xc0, 0x04, 0x84, 0x00, 0x49, 0xfc, 0x7e, 0xb9, +0x2e, 0x01, 0xf6, 0x0e, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x05, 0x84, 0x02, 0x49, 0xfc, 0x7e, 0xb1, +0x3c, 0x00, 0x50, 0x40, 0x54, 0x00, 0x00, 0x40, 0xc0, 0x04, 0x49, 0xfd, 0x15, 0xf2, 0x84, 0xc1, +0x2e, 0x01, 0xf6, 0x0f, 0xc8, 0x09, 0x80, 0x20, 0x49, 0xfd, 0x14, 0x3b, 0x56, 0x00, 0x00, 0x0c, +0x84, 0x21, 0x40, 0x60, 0x80, 0x1b, 0x3c, 0x00, 0x50, 0x40, 0x54, 0x00, 0x00, 0x0f, 0xc0, 0x0d, +0x2e, 0x00, 0xa1, 0x92, 0x84, 0x41, 0x4c, 0x01, 0x00, 0x09, 0x2e, 0x01, 0xf6, 0x0f, 0xc8, 0x0a, +0x3e, 0x08, 0x5b, 0x60, 0x80, 0x22, 0xd5, 0x04, 0x84, 0x20, 0x3e, 0x08, 0x5b, 0x60, 0x10, 0x10, +0x00, 0x15, 0x84, 0x00, 0x49, 0xfd, 0x29, 0x2b, 0x56, 0x00, 0x00, 0x0c, 0x84, 0x21, 0x40, 0x60, +0x80, 0x1b, 0x85, 0x00, 0x50, 0x04, 0x00, 0x06, 0x8d, 0x01, 0x49, 0xfd, 0x10, 0xd0, 0xc0, 0x0c, +0x02, 0x10, 0x00, 0x51, 0x54, 0x10, 0x80, 0x02, 0xc1, 0x07, 0x3c, 0x2d, 0xfd, 0x1e, 0x44, 0x10, +0x00, 0x13, 0xdd, 0x22, 0x84, 0xe1, 0x84, 0x64, 0x4c, 0x81, 0xff, 0xee, 0x84, 0x01, 0x4c, 0x70, +0x40, 0x11, 0x84, 0x40, 0x3c, 0x0c, 0x16, 0xd9, 0x80, 0xa7, 0x46, 0x10, 0x00, 0x94, 0x58, 0x10, +0x8d, 0x54, 0x80, 0x62, 0x80, 0x82, 0x49, 0xfc, 0x85, 0x78, 0x3e, 0x00, 0x5b, 0x60, 0xd5, 0x0e, +0x84, 0x21, 0x4c, 0x60, 0xc0, 0x0f, 0x84, 0x40, 0x3c, 0x0c, 0x16, 0xda, 0x80, 0xa6, 0x44, 0x10, +0xf9, 0x48, 0x80, 0x62, 0x80, 0x82, 0x49, 0xfc, 0x85, 0x68, 0x44, 0x00, 0x00, 0x1f, 0xd5, 0x26, +0x2e, 0x01, 0xf6, 0x0f, 0xc0, 0x04, 0x2e, 0x01, 0xf6, 0x0e, 0xc8, 0x05, 0x84, 0x00, 0x3c, 0x0e, +0x16, 0xdb, 0xd5, 0x1c, 0x49, 0xfd, 0x06, 0xfb, 0x84, 0x2a, 0x3c, 0x1e, 0x16, 0xdb, 0xd5, 0x15, +0x3e, 0x68, 0x5b, 0x60, 0xa1, 0xf3, 0xcf, 0x11, 0xa0, 0x74, 0xa8, 0x33, 0xc1, 0x05, 0x80, 0x01, +0x49, 0xfc, 0x7e, 0x2f, 0xa9, 0xf4, 0x2e, 0x00, 0x5b, 0x75, 0xc0, 0x07, 0x84, 0x01, 0x49, 0xfd, +0x28, 0xce, 0x84, 0x00, 0x3e, 0x00, 0x5b, 0x75, 0x84, 0x00, 0xec, 0x18, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xa6, 0x40, 0xc9, 0x05, 0x2e, 0x10, 0x5b, 0x6c, +0x84, 0x07, 0xd5, 0x14, 0x84, 0xa1, 0xd9, 0x0f, 0xa6, 0x01, 0x49, 0xff, 0xfe, 0xd4, 0xc8, 0x10, +0x2e, 0x01, 0xf6, 0x0f, 0xc8, 0x0d, 0x2e, 0x01, 0xf6, 0x0e, 0xc8, 0x0a, 0x2e, 0x10, 0x5b, 0x6c, +0x84, 0x08, 0xd5, 0x04, 0x84, 0x08, 0x44, 0x10, 0x00, 0xff, 0x49, 0xfb, 0xd0, 0xe8, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xc0, 0x07, 0x49, 0xfd, +0x06, 0xb6, 0x84, 0x01, 0x80, 0x20, 0x49, 0xfd, 0x13, 0x8c, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x49, 0xfd, 0x79, 0xca, 0x80, 0xc0, 0xc8, 0x04, 0x84, 0x01, +0x49, 0xfd, 0x04, 0x15, 0x80, 0x06, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x84, 0xa4, 0x96, 0x00, 0xd9, 0x09, 0x46, 0x50, 0x04, 0xb0, 0x04, 0x62, +0x80, 0x20, 0x42, 0x63, 0x1c, 0x09, 0x14, 0x62, 0x80, 0x20, 0x49, 0xfd, 0x6d, 0xda, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x50, 0x80, 0x00, 0x02, 0x00, 0x24, +0x00, 0x00, 0x97, 0xc9, 0x84, 0x60, 0x9c, 0x53, 0x44, 0x20, 0xff, 0xfe, 0x80, 0xc0, 0x49, 0xff, +0xe1, 0x1a, 0x44, 0x00, 0xfc, 0xbc, 0x4c, 0x70, 0x00, 0x33, 0xe2, 0x07, 0xe9, 0x0a, 0x44, 0x50, +0xfc, 0x6b, 0xd7, 0x31, 0x8c, 0xae, 0xd7, 0x41, 0x44, 0x50, 0xfc, 0x4d, 0xdf, 0x4a, 0xd5, 0x22, +0x44, 0x10, 0xfc, 0xc5, 0x4c, 0x70, 0x80, 0x3e, 0xe2, 0x27, 0xe9, 0x04, 0x9d, 0x47, 0xdf, 0x41, +0xd5, 0x07, 0x9d, 0x4c, 0xd7, 0x24, 0x44, 0x50, 0xfc, 0xf3, 0xdf, 0x3b, 0xd5, 0x36, 0xa7, 0x73, +0x84, 0x41, 0xd2, 0x03, 0x80, 0x02, 0xd5, 0x08, 0x00, 0x04, 0x00, 0x00, 0x9c, 0x74, 0x9e, 0x01, +0x96, 0x00, 0x49, 0xff, 0xf9, 0xd8, 0x80, 0x20, 0x44, 0x00, 0xfc, 0xc3, 0x49, 0xfb, 0xd0, 0x57, +0xd5, 0x04, 0x9c, 0x33, 0x49, 0xff, 0xf8, 0x0b, 0x84, 0x00, 0xd5, 0x27, 0xa6, 0x33, 0x49, 0xff, +0xf9, 0x66, 0xd5, 0xfb, 0x9c, 0x33, 0x49, 0xff, 0xf8, 0xb2, 0xd5, 0xf7, 0x9c, 0x33, 0xa6, 0x40, +0x84, 0xa1, 0xd9, 0x08, 0xa6, 0x74, 0xc9, 0x02, 0xd5, 0x03, 0x84, 0xa1, 0xd9, 0x03, 0x3e, 0x11, +0xf6, 0x17, 0x49, 0xff, 0xff, 0x58, 0xd5, 0xe9, 0x9c, 0x33, 0x49, 0xff, 0xe8, 0xfe, 0xd5, 0xe5, +0x9c, 0x33, 0x49, 0xff, 0xe8, 0xe8, 0xd5, 0xe1, 0x9c, 0x33, 0x49, 0xff, 0xe9, 0xc6, 0xd5, 0xdd, +0x80, 0x06, 0x80, 0x27, 0x49, 0xfb, 0xc9, 0x91, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x44, 0x60, 0x70, 0x20, 0x96, 0x01, 0x80, 0x82, 0x4c, 0x03, 0x40, 0x0b, 0x96, 0xc9, +0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0xa4, 0x49, 0xfc, 0xfc, 0x4c, 0xd5, 0x03, +0x49, 0xfc, 0xfe, 0x43, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x2e, 0x51, 0xf6, 0x0f, 0x84, 0x41, 0xd2, 0x06, 0x2e, 0x51, 0xf6, 0x0e, 0xd2, 0x03, 0x49, 0xfb, +0x8f, 0xf2, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x2e, 0x01, 0xf6, 0x11, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x03, 0xd5, 0x04, 0x84, 0x22, 0x4c, 0x00, +0xc0, 0x13, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, 0xb4, 0x20, 0x42, 0x10, 0xcc, 0x0b, +0xc1, 0x05, 0xb4, 0x20, 0x42, 0x10, 0xcc, 0x09, 0xd5, 0x04, 0xb4, 0x20, 0x42, 0x10, 0xcc, 0x08, +0xb6, 0x20, 0xd5, 0x10, 0x84, 0x40, 0x84, 0x05, 0x46, 0x10, 0x00, 0x92, 0x58, 0x10, 0x88, 0xb4, +0x80, 0x62, 0x80, 0x82, 0x84, 0xa1, 0x49, 0xfc, 0x84, 0x30, 0x3e, 0x09, 0xf8, 0x00, 0x49, 0xfd, +0x11, 0xfa, 0x84, 0x20, 0x3e, 0x11, 0xf6, 0x10, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xc0, 0x50, 0x7f, 0x80, 0x24, 0x54, 0x90, 0x80, 0xff, +0x80, 0xc0, 0x81, 0x02, 0x80, 0x07, 0x84, 0x20, 0x44, 0x20, 0x00, 0x1a, 0x49, 0xfe, 0x28, 0x83, +0x84, 0x01, 0x4c, 0x90, 0x00, 0x3e, 0x4e, 0x92, 0x00, 0x06, 0x84, 0x42, 0x4c, 0x91, 0x40, 0x72, +0xd5, 0x59, 0x3e, 0x08, 0xa0, 0x78, 0x00, 0x10, 0x00, 0x0f, 0x84, 0x44, 0x4c, 0x11, 0x00, 0x6c, +0x00, 0x10, 0x00, 0x10, 0x84, 0x41, 0x4c, 0x11, 0x00, 0x67, 0xa4, 0x04, 0x54, 0x00, 0x00, 0x0f, +0xc0, 0x07, 0x2e, 0x00, 0xa1, 0x92, 0xe6, 0x02, 0xe8, 0x03, 0x84, 0x0c, 0xd5, 0x5d, 0x50, 0x0f, +0x80, 0x04, 0x44, 0x50, 0x00, 0x24, 0xad, 0x42, 0x8e, 0xb2, 0xad, 0x45, 0x3e, 0x59, 0xf8, 0x08, +0x84, 0x60, 0x84, 0x46, 0x84, 0x80, 0xb6, 0xa0, 0x44, 0x50, 0x00, 0x64, 0x10, 0x30, 0x00, 0x15, +0xad, 0x47, 0x12, 0x40, 0x00, 0x09, 0x12, 0x20, 0x00, 0x08, 0x10, 0x30, 0x00, 0x18, 0x10, 0x30, +0x00, 0x16, 0xac, 0x84, 0xac, 0x83, 0xad, 0x06, 0x49, 0xfd, 0x14, 0xbb, 0xd5, 0x3d, 0xc6, 0x39, +0x02, 0x44, 0x00, 0x08, 0x50, 0xaf, 0x80, 0x2e, 0x40, 0x32, 0x20, 0x09, 0x10, 0x33, 0x80, 0x09, +0x10, 0x43, 0x80, 0x08, 0x50, 0x14, 0x00, 0x12, 0x94, 0x84, 0x80, 0x0a, 0x49, 0xfd, 0x58, 0x4b, +0x50, 0x14, 0x00, 0x07, 0x80, 0x07, 0x84, 0x48, 0x49, 0xfd, 0x58, 0x45, 0x80, 0x06, 0x80, 0x27, +0x80, 0x6a, 0x50, 0x2f, 0x80, 0x2c, 0x49, 0xfd, 0x16, 0x92, 0x80, 0x06, 0x49, 0xfd, 0x15, 0x75, +0xd5, 0x1b, 0x3c, 0x2d, 0xfd, 0x1e, 0x44, 0x10, 0x00, 0x13, 0x80, 0x06, 0xdd, 0x22, 0x84, 0x40, +0x3c, 0x0c, 0x16, 0xd9, 0x44, 0x11, 0x2b, 0xb8, 0x80, 0x62, 0x80, 0x82, 0x84, 0xa1, 0x49, 0xfc, +0x83, 0xa4, 0x3e, 0x00, 0x5b, 0x60, 0x49, 0xff, 0xff, 0x4a, 0x84, 0x20, 0x3e, 0x11, 0xf6, 0x12, +0x84, 0x00, 0xd5, 0x02, 0x84, 0x09, 0xec, 0x40, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xcc, 0x2e, 0x91, 0xf6, 0x12, 0x80, 0xe0, 0x84, 0x01, 0x81, 0x01, 0x4c, 0x90, +0x40, 0x27, 0xc9, 0x1c, 0x3e, 0x09, 0xf8, 0x08, 0x49, 0xff, 0xe7, 0x1b, 0xe6, 0x04, 0xe8, 0x0d, +0x44, 0x20, 0x00, 0x22, 0x42, 0x20, 0x08, 0x24, 0x3e, 0x39, 0xf6, 0x30, 0x80, 0x07, 0x80, 0x29, +0x98, 0x93, 0x49, 0xff, 0xff, 0x58, 0xd5, 0x07, 0x3e, 0x81, 0xf6, 0x12, 0x44, 0x00, 0x00, 0x1f, +0x49, 0xff, 0xfe, 0x5b, 0x80, 0x08, 0x48, 0x00, 0x00, 0x81, 0x84, 0x20, 0x3e, 0x11, 0xf6, 0x12, +0x8c, 0x1e, 0x49, 0xff, 0xfe, 0x52, 0x84, 0x00, 0x48, 0x00, 0x00, 0x78, 0x50, 0x6f, 0x80, 0x20, +0xc9, 0x23, 0x50, 0x23, 0x80, 0xc9, 0x00, 0x13, 0x80, 0xb5, 0x14, 0x83, 0x7f, 0xfe, 0x14, 0x23, +0x7f, 0xf9, 0x80, 0x01, 0x02, 0x23, 0x80, 0x53, 0xae, 0x75, 0xac, 0xb1, 0x00, 0x33, 0x80, 0xbf, +0xae, 0xf6, 0x02, 0x13, 0x80, 0x19, 0x12, 0x13, 0x7f, 0xfe, 0x02, 0x23, 0x80, 0x1a, 0x12, 0x23, +0x7f, 0xff, 0x02, 0x33, 0x80, 0x1b, 0xac, 0xf0, 0xc8, 0x02, 0xd5, 0x04, 0x00, 0x03, 0x80, 0x3d, +0x92, 0x05, 0xae, 0x34, 0xd5, 0x4d, 0x50, 0x03, 0x7f, 0xe4, 0x84, 0x20, 0x44, 0x20, 0x00, 0x24, +0x49, 0xfd, 0x57, 0xd3, 0x44, 0x50, 0x00, 0x3c, 0x14, 0x83, 0x7f, 0xfe, 0x4c, 0x82, 0xc0, 0x23, +0x50, 0x1f, 0x80, 0x28, 0x14, 0x13, 0x7f, 0xf9, 0x3e, 0x08, 0xa1, 0x8c, 0x00, 0x23, 0x80, 0xb5, +0x00, 0x30, 0x00, 0x0f, 0xae, 0xb5, 0xae, 0xcd, 0x00, 0x20, 0x00, 0x12, 0x02, 0x73, 0x80, 0x53, +0x00, 0x30, 0x00, 0x0a, 0xae, 0xb6, 0x00, 0x20, 0x00, 0x0b, 0xae, 0xc8, 0xae, 0x89, 0x00, 0x30, +0x00, 0x0c, 0x00, 0x20, 0x00, 0x0d, 0xad, 0xf1, 0xae, 0xca, 0xae, 0x8b, 0x00, 0x00, 0x00, 0x0e, +0xd5, 0x1e, 0x84, 0xa2, 0x4c, 0x82, 0xc0, 0x1d, 0x3e, 0x08, 0xa1, 0x54, 0x00, 0x20, 0x00, 0x15, +0x00, 0x30, 0x00, 0x17, 0x50, 0x1f, 0x80, 0x28, 0xae, 0x8d, 0xae, 0xf6, 0x00, 0x20, 0x00, 0x10, +0x00, 0x30, 0x00, 0x11, 0xae, 0x88, 0xae, 0xc9, 0x00, 0x20, 0x00, 0x12, 0x00, 0x30, 0x00, 0x13, +0x14, 0x13, 0x7f, 0xf9, 0xae, 0x8a, 0xae, 0xcb, 0x00, 0x00, 0x00, 0x14, 0xae, 0x0c, 0x84, 0x01, +0x50, 0x1f, 0x80, 0x04, 0x49, 0xfb, 0xba, 0xe7, 0xec, 0x34, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xb4, 0x41, 0xca, 0x05, 0x84, 0x22, 0x49, 0xff, +0xfe, 0xc2, 0xd5, 0x08, 0x84, 0x40, 0x3e, 0x21, 0xf6, 0x12, 0x44, 0x00, 0x00, 0x1f, 0x49, 0xff, +0xfd, 0xc4, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x8c, +0x00, 0x30, 0x00, 0xb6, 0x00, 0x40, 0x00, 0xb3, 0x50, 0x60, 0x00, 0xb2, 0x84, 0x21, 0x84, 0x06, +0x44, 0x20, 0x70, 0x45, 0x49, 0xfc, 0xfa, 0xa7, 0x02, 0x03, 0x7f, 0xf8, 0x84, 0x20, 0xae, 0x76, +0xc0, 0x5b, 0x44, 0x00, 0x00, 0x22, 0x44, 0x20, 0x00, 0x4c, 0x10, 0x03, 0x00, 0x0a, 0x40, 0x8f, +0x88, 0x00, 0x80, 0x1f, 0x84, 0x20, 0x49, 0xfd, 0x57, 0x50, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, +0x00, 0x24, 0x49, 0xfd, 0x57, 0x4a, 0xa6, 0x71, 0x84, 0xaa, 0x80, 0xff, 0xd9, 0x13, 0xa6, 0x34, +0x44, 0x10, 0x00, 0x22, 0x14, 0x14, 0x00, 0x05, 0x49, 0xfd, 0x0e, 0x07, 0x12, 0x04, 0x00, 0x0f, +0x50, 0x23, 0x00, 0x0f, 0x80, 0x28, 0x84, 0x04, 0x14, 0x24, 0x00, 0x02, 0x49, 0xfb, 0xba, 0x93, +0xd5, 0x2d, 0x84, 0xab, 0xa6, 0x34, 0xd9, 0x0d, 0x44, 0x10, 0x00, 0x22, 0xb6, 0x3f, 0x49, 0xfd, +0x0d, 0xf4, 0x12, 0x0f, 0x80, 0x06, 0x3c, 0x2d, 0xfe, 0xb9, 0x80, 0x3f, 0x84, 0x0c, 0xd5, 0x1d, +0x49, 0xfd, 0x1e, 0xbd, 0x84, 0xa1, 0xd8, 0x1a, 0xa6, 0x33, 0xc8, 0x18, 0xa6, 0x34, 0x44, 0x10, +0x00, 0x22, 0xb6, 0x3f, 0x49, 0xfd, 0x0d, 0xe1, 0x2e, 0x11, 0xf6, 0x12, 0x84, 0xa1, 0x12, 0x0f, +0x80, 0x06, 0xd9, 0x07, 0x80, 0x3f, 0x50, 0x03, 0x7f, 0x4e, 0x49, 0xff, 0xff, 0x8c, 0xd5, 0x06, +0x3c, 0x2d, 0xfe, 0xb9, 0x80, 0x3f, 0x84, 0x08, 0xdd, 0x22, 0x02, 0x03, 0x7f, 0xf8, 0x58, 0x00, +0x01, 0x00, 0x12, 0x03, 0x7f, 0xf8, 0xec, 0x74, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0xef, 0xe0, 0x2e, 0x61, 0xf6, 0x11, 0xce, 0x04, 0x49, 0xff, 0xfe, 0x08, 0xd5, 0x26, +0x84, 0xa1, 0xde, 0x0f, 0x3e, 0x09, 0xf8, 0x08, 0x49, 0xff, 0xe5, 0xeb, 0xe6, 0x04, 0xe8, 0x1e, +0x84, 0x00, 0x3e, 0x61, 0xf6, 0x12, 0x80, 0x20, 0x80, 0x5f, 0x49, 0xff, 0xfe, 0x2c, 0xd5, 0x16, +0x84, 0xa2, 0xde, 0x14, 0x3e, 0x19, 0xf8, 0x00, 0x3e, 0x09, 0xf5, 0x58, 0x00, 0x50, 0x80, 0x0e, +0xa6, 0x80, 0xda, 0x09, 0x9c, 0x04, 0x8c, 0x32, 0x84, 0x44, 0x49, 0xfd, 0x56, 0xde, 0xc8, 0x03, +0x49, 0xff, 0xfd, 0xe5, 0x84, 0x20, 0x3e, 0x11, 0xf6, 0x10, 0xec, 0x20, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0x80, 0xe1, +0x49, 0xfb, 0x62, 0xcd, 0x84, 0xa1, 0x3e, 0x28, 0x2b, 0x08, 0xdf, 0x07, 0xa6, 0x10, 0x40, 0x63, +0x98, 0x0c, 0x40, 0x63, 0x00, 0x04, 0xd5, 0x0b, 0xa6, 0x10, 0x84, 0x21, 0x40, 0x60, 0x98, 0x0c, +0x54, 0x00, 0x00, 0x0f, 0x40, 0x63, 0x18, 0x05, 0x40, 0x60, 0x18, 0x02, 0x2e, 0x07, 0xf0, 0x4d, +0x84, 0xa1, 0xaf, 0x90, 0xd8, 0x03, 0x48, 0x00, 0x00, 0xf8, 0x2e, 0x00, 0x2b, 0x08, 0x84, 0xa4, +0xd8, 0x7c, 0x49, 0xff, 0xe7, 0xf4, 0x3c, 0x0c, 0x0a, 0xdc, 0xc8, 0x1b, 0x46, 0x00, 0x04, 0x00, +0x04, 0x20, 0x00, 0x53, 0x46, 0x10, 0x04, 0x00, 0x42, 0x21, 0x60, 0x08, 0x14, 0x20, 0x00, 0x53, +0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, 0xf8, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, +0x46, 0x00, 0x1e, 0x84, 0xb4, 0x41, 0x58, 0x00, 0x08, 0x00, 0x58, 0x21, 0x14, 0x00, 0xd5, 0x1a, +0x84, 0xa1, 0xd8, 0x1c, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x53, 0x46, 0x10, 0x04, 0x00, +0x42, 0x21, 0x60, 0x08, 0x14, 0x20, 0x00, 0x53, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, +0xf8, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x46, 0x00, 0x3d, 0x09, 0xb4, 0x41, 0x58, 0x21, +0x10, 0x00, 0xb6, 0x41, 0x49, 0xfb, 0x8e, 0xc3, 0xd5, 0x1a, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, +0x00, 0x82, 0x42, 0x21, 0x30, 0x09, 0x14, 0x20, 0x00, 0x82, 0x80, 0x20, 0x04, 0x00, 0x80, 0x19, +0x42, 0x00, 0x74, 0x0b, 0xc0, 0x06, 0x46, 0x00, 0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, +0x46, 0x00, 0x26, 0x25, 0x58, 0x00, 0x0a, 0x00, 0x49, 0xfb, 0x8e, 0xa9, 0x46, 0x00, 0x04, 0x00, +0x04, 0x00, 0x00, 0x0e, 0x46, 0x30, 0x03, 0x00, 0x46, 0x10, 0x02, 0x00, 0x40, 0x50, 0x0c, 0x02, +0x4c, 0x50, 0x80, 0x93, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x53, 0x42, 0x21, 0x4c, 0x09, +0x42, 0x21, 0x50, 0x09, 0x14, 0x20, 0x80, 0x53, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x30, +0xb4, 0x20, 0x44, 0x2c, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, +0x80, 0x01, 0xb6, 0x20, 0x48, 0x00, 0x00, 0x79, 0x84, 0xa8, 0xd0, 0x03, 0x84, 0xac, 0xd8, 0x20, +0x49, 0xff, 0xe7, 0x75, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x53, 0x42, 0x21, 0x60, 0x09, +0x14, 0x20, 0x00, 0x53, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, +0xf8, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x46, 0x00, 0x72, 0x70, 0xb4, 0x41, 0x58, 0x00, +0x0e, 0x00, 0x58, 0x21, 0x10, 0x00, 0xb6, 0x41, 0x49, 0xfb, 0x8e, 0x61, 0xd5, 0x55, 0x46, 0x60, +0x04, 0x00, 0x58, 0x63, 0x02, 0x08, 0xb4, 0x06, 0x42, 0x00, 0x30, 0x09, 0xb6, 0x06, 0x49, 0xff, +0xe7, 0x4e, 0x46, 0x00, 0x04, 0x00, 0xa0, 0x07, 0x42, 0x00, 0x60, 0x0b, 0xc0, 0x0f, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0x53, 0x42, 0x10, 0xe0, 0x09, 0x14, 0x10, 0x00, 0x53, 0x44, 0x1f, +0xf8, 0xff, 0xb4, 0x06, 0x40, 0x00, 0x04, 0x02, 0xb6, 0x06, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x0e, 0x46, 0x20, 0x03, 0x00, 0x46, 0x30, 0x02, 0x00, 0x40, 0x50, 0x08, 0x02, 0xd3, 0x19, +0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x53, 0x42, 0x21, 0x4c, 0x09, 0x42, 0x21, 0x50, 0x09, +0x14, 0x20, 0x80, 0x53, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x30, 0xb4, 0x20, 0x44, 0x2c, +0xff, 0xff, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, +0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x19, 0x42, 0x00, 0x74, 0x0b, 0x44, 0x10, 0x74, 0xcc, +0xc0, 0x06, 0x46, 0x00, 0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x26, 0x25, +0x58, 0x00, 0x0a, 0x00, 0xdd, 0x21, 0xf0, 0x01, 0x49, 0xfb, 0x61, 0xcf, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, +0x04, 0x00, 0x00, 0x83, 0x96, 0x04, 0xc0, 0x11, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x38, +0xb4, 0x20, 0x84, 0xa1, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x07, 0xb4, 0x20, 0x84, 0xa2, +0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0xd9, 0x04, 0x49, 0xfb, 0x57, 0x2b, 0xd5, 0x5f, 0x46, 0x10, +0x04, 0x10, 0x04, 0x40, 0x80, 0x53, 0x80, 0x41, 0x46, 0x30, 0x08, 0x5f, 0x42, 0x42, 0x68, 0x09, +0x58, 0x31, 0x89, 0x10, 0x14, 0x40, 0x80, 0x53, 0x14, 0x31, 0x00, 0x19, 0x84, 0x23, 0xb4, 0x00, +0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0x4c, 0x00, 0xc0, 0x09, 0x80, 0x02, 0x46, 0x10, 0x20, 0x40, +0x58, 0x10, 0x84, 0x05, 0x14, 0x10, 0x00, 0x4c, 0x49, 0xff, 0xeb, 0x5b, 0x46, 0x00, 0x04, 0x10, +0x84, 0x25, 0x14, 0x10, 0x00, 0x40, 0x04, 0x10, 0x00, 0x40, 0x40, 0x10, 0xbc, 0x08, 0x92, 0x3f, +0xc1, 0xfb, 0x04, 0x10, 0x00, 0x40, 0x44, 0x51, 0x00, 0x00, 0x40, 0x10, 0x94, 0x02, 0xc9, 0xfa, +0x2e, 0x01, 0xf6, 0x0c, 0x3e, 0x17, 0xf0, 0x4c, 0x84, 0xa1, 0xd8, 0x10, 0x46, 0x10, 0x04, 0x00, +0x04, 0x20, 0x81, 0x00, 0x80, 0x01, 0x58, 0x21, 0x00, 0x11, 0x14, 0x20, 0x81, 0x00, 0x04, 0x10, +0x01, 0x06, 0x58, 0x10, 0x80, 0x80, 0x14, 0x10, 0x01, 0x06, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x97, 0x40, 0x00, 0x40, 0x08, 0x92, 0x1f, 0xc0, 0x07, 0x2e, 0x10, 0xd0, 0x21, 0x84, 0x00, +0x49, 0xfb, 0x6b, 0xbf, 0x92, 0x00, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x96, 0x42, 0x10, +0xf8, 0x09, 0x42, 0x10, 0xfc, 0x09, 0x14, 0x10, 0x00, 0x96, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x0c, 0xb4, 0x00, +0x96, 0x04, 0xc0, 0x13, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x38, 0xb4, 0x20, 0x84, 0x41, +0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0x4c, 0x11, 0x00, 0x09, 0xb4, 0x00, 0x84, 0x62, 0x92, 0x14, +0x54, 0x00, 0x00, 0x03, 0x4c, 0x01, 0xc0, 0x06, 0x49, 0xfb, 0x65, 0xb7, 0x48, 0x00, 0x01, 0x1c, +0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x04, 0x18, 0xb4, 0x20, 0x3e, 0x29, 0xf6, 0x0c, 0x54, 0x10, +0x80, 0x80, 0xc1, 0x12, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x84, 0x00, 0xb4, 0x61, 0x58, 0x31, +0x80, 0x11, 0xb6, 0x61, 0x44, 0x3f, 0xff, 0x7f, 0xb4, 0x20, 0x40, 0x10, 0x8c, 0x02, 0xb6, 0x20, +0x84, 0x01, 0xae, 0x10, 0xd5, 0x02, 0xae, 0x50, 0x49, 0xfb, 0x53, 0x05, 0x84, 0x21, 0x3e, 0x0f, +0xf0, 0x4c, 0xae, 0x40, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, +0xef, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x38, +0xb4, 0x20, 0x84, 0x43, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0x4c, 0x11, 0x00, 0x08, 0xb4, 0x00, +0x92, 0x14, 0x40, 0x00, 0x08, 0x02, 0x4e, 0x03, 0x00, 0x81, 0x46, 0x50, 0x04, 0x05, 0x46, 0x30, +0x04, 0x05, 0x46, 0x40, 0x01, 0x20, 0x46, 0x10, 0x04, 0x05, 0x46, 0x20, 0x20, 0x20, 0x58, 0x10, +0x87, 0xbc, 0x84, 0xcf, 0x46, 0x00, 0x04, 0x05, 0x58, 0x52, 0x87, 0xb0, 0x58, 0x31, 0x87, 0xb4, +0x58, 0x42, 0x00, 0x12, 0x58, 0x21, 0x02, 0x02, 0xb6, 0xc5, 0x58, 0x00, 0x07, 0xc0, 0xb6, 0x83, +0x46, 0x70, 0x04, 0x05, 0xb6, 0x41, 0x84, 0x25, 0xb6, 0x20, 0x58, 0x73, 0x87, 0xc4, 0x84, 0xc0, +0xd5, 0x1e, 0x84, 0x65, 0x4c, 0x61, 0xc0, 0x1a, 0x3e, 0x19, 0xf6, 0x0c, 0xa6, 0x08, 0x84, 0x41, +0x4c, 0x01, 0x40, 0x0c, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x04, 0x18, 0xb4, 0x40, 0x58, 0x21, +0x00, 0x80, 0xb6, 0x40, 0x84, 0x00, 0xae, 0x08, 0x84, 0x20, 0x3e, 0x0f, 0xf0, 0x4c, 0xae, 0x40, +0x49, 0xfb, 0x52, 0xb1, 0x48, 0x00, 0x00, 0xa0, 0x49, 0xfb, 0x66, 0x2b, 0xb4, 0x27, 0x9d, 0xb1, +0x54, 0x10, 0x80, 0x90, 0x44, 0x30, 0x00, 0x90, 0x97, 0xb0, 0x84, 0x01, 0x4c, 0x11, 0xff, 0xdb, +0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x00, 0x80, 0x84, 0x2e, 0xb6, 0x20, 0x49, 0xff, 0xea, 0xe5, +0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x01, 0x00, 0x84, 0x25, 0xb6, 0x20, 0x84, 0x27, 0xb6, 0x20, +0xb4, 0x20, 0x44, 0x25, 0x00, 0x00, 0x40, 0x10, 0x88, 0x02, 0x4c, 0x11, 0x7f, 0xfb, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x01, 0x00, 0xb4, 0x20, 0x44, 0x34, 0x00, 0x00, 0x40, 0x10, 0x8c, 0x02, +0xc1, 0xfb, 0x46, 0x20, 0x04, 0x10, 0x46, 0x30, 0x20, 0x40, 0x46, 0x00, 0x04, 0x10, 0x46, 0x10, +0x08, 0x40, 0x58, 0x21, 0x01, 0x30, 0x58, 0x31, 0x84, 0x04, 0x58, 0x00, 0x00, 0x64, 0x58, 0x10, +0x81, 0x30, 0xb6, 0x62, 0xb6, 0x20, 0xd5, 0x3e, 0x46, 0x70, 0x04, 0x10, 0x46, 0x80, 0x00, 0xe9, +0x46, 0x50, 0x04, 0x10, 0x46, 0x60, 0x00, 0xd8, 0x46, 0x30, 0x04, 0x10, 0x46, 0x40, 0x00, 0xc8, +0x46, 0x10, 0x04, 0x10, 0x46, 0x20, 0x00, 0xc0, 0x58, 0x10, 0x81, 0x10, 0x46, 0x00, 0x04, 0x10, +0x58, 0x73, 0x81, 0x04, 0x58, 0x84, 0x0f, 0xe0, 0x58, 0x52, 0x81, 0x08, 0x58, 0x63, 0x0f, 0x7f, +0x58, 0x31, 0x81, 0x0c, 0x58, 0x42, 0x07, 0x3f, 0x58, 0x21, 0x03, 0x1f, 0xb7, 0x07, 0x58, 0x00, +0x01, 0x00, 0xb6, 0xc5, 0xb6, 0x83, 0xb6, 0x41, 0x84, 0x25, 0xb6, 0x20, 0x84, 0x27, 0xb6, 0x20, +0xb4, 0x20, 0x44, 0x25, 0x00, 0x00, 0x40, 0x10, 0x88, 0x02, 0x4c, 0x11, 0x7f, 0xfb, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x01, 0x00, 0xb4, 0x20, 0x44, 0x34, 0x00, 0x00, 0x40, 0x10, 0x8c, 0x02, +0xc1, 0xfb, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x01, 0x40, 0xb4, 0x40, 0x44, 0x3f, 0xf0, 0x00, +0x40, 0x21, 0x0c, 0x02, 0x58, 0x21, 0x01, 0x31, 0xb6, 0x40, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, +0x81, 0x4c, 0xb4, 0x41, 0x46, 0x00, 0x04, 0x00, 0x42, 0x21, 0x68, 0x08, 0xb6, 0x41, 0x58, 0x00, +0x02, 0x58, 0xb4, 0x20, 0x42, 0x10, 0xf8, 0x08, 0xb6, 0x20, 0x49, 0xfb, 0x52, 0x14, 0x92, 0x00, +0x64, 0x00, 0x00, 0x20, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x3c, 0x6c, +0x21, 0x30, 0x44, 0x10, 0x10, 0x00, 0x96, 0x00, 0x4c, 0x60, 0x80, 0x04, 0x95, 0x4b, 0xde, 0x37, +0x2e, 0x10, 0x84, 0xf5, 0xc9, 0x17, 0x49, 0xfd, 0x4a, 0x10, 0xc0, 0x14, 0x3c, 0x0c, 0x36, 0xe6, +0x44, 0x50, 0x00, 0xca, 0xd8, 0x09, 0x44, 0x50, 0x10, 0x00, 0xde, 0x0c, 0x49, 0xfd, 0x2c, 0x7b, +0x49, 0xfd, 0x71, 0x57, 0xd5, 0x07, 0x9d, 0x6a, 0xd8, 0x05, 0x49, 0xfd, 0x2c, 0x80, 0x49, 0xfd, +0x71, 0xc6, 0x3c, 0x0c, 0x36, 0xe6, 0x44, 0x50, 0x00, 0xcc, 0xd8, 0x19, 0x46, 0x00, 0x04, 0x90, +0x04, 0x00, 0x00, 0x46, 0x96, 0x04, 0xc0, 0x13, 0x3c, 0x4d, 0xff, 0x14, 0x84, 0x21, 0x84, 0x04, +0x80, 0x66, 0x44, 0x20, 0x30, 0x58, 0xdd, 0x24, 0x46, 0x00, 0x04, 0x90, 0x04, 0x10, 0x00, 0x47, +0x42, 0x10, 0xc0, 0x08, 0x14, 0x10, 0x00, 0x47, 0x49, 0xfd, 0x38, 0x59, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x40, 0x00, 0x90, 0x3c, 0x4f, 0xfb, 0xa0, +0x46, 0x50, 0x00, 0x95, 0x58, 0x52, 0x80, 0xf0, 0x3c, 0x5f, 0xff, 0x6a, 0x46, 0x50, 0x00, 0x95, +0x58, 0x52, 0x80, 0xd4, 0x3c, 0x5f, 0xff, 0xb1, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x87, 0x3c, +0x3c, 0x5f, 0xff, 0xd3, 0x46, 0x50, 0x00, 0x91, 0x58, 0x52, 0x85, 0xe0, 0x3c, 0x5f, 0xff, 0xea, +0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x87, 0xa8, 0x3c, 0x5f, 0xff, 0xf6, 0x46, 0x50, 0x00, 0x94, +0x58, 0x52, 0x8b, 0x88, 0x3c, 0x5f, 0xff, 0xbf, 0x46, 0x50, 0x00, 0x92, 0x58, 0x52, 0x84, 0x5c, +0x3c, 0x5f, 0xff, 0xcb, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x87, 0xb0, 0x3e, 0x3f, 0xf0, 0x6c, +0x3c, 0x5f, 0xff, 0xf1, 0x46, 0x40, 0x00, 0x91, 0x58, 0x42, 0x09, 0x84, 0xa9, 0x1c, 0x46, 0x50, +0x00, 0x94, 0x58, 0x52, 0x85, 0x78, 0x3c, 0x5f, 0xfc, 0x8e, 0x46, 0x50, 0x00, 0x94, 0x58, 0x52, +0x88, 0x8c, 0x3e, 0x2f, 0xf1, 0x50, 0x3c, 0x5f, 0xfe, 0xda, 0x46, 0x40, 0x00, 0x94, 0x58, 0x42, +0x07, 0x3c, 0x46, 0x50, 0x00, 0x91, 0x58, 0x52, 0x80, 0x0c, 0x14, 0x41, 0x00, 0x0b, 0x3c, 0x5e, +0x00, 0x09, 0x46, 0x40, 0x00, 0x94, 0x58, 0x42, 0x0b, 0x60, 0xa9, 0x1b, 0x46, 0x40, 0x00, 0x94, +0x58, 0x42, 0x06, 0x10, 0xa9, 0x1d, 0x46, 0x30, 0x00, 0x94, 0x58, 0x31, 0x88, 0x68, 0xa8, 0xd2, +0x46, 0x30, 0x00, 0x94, 0x58, 0x31, 0x87, 0x70, 0xa8, 0xd5, 0x84, 0x09, 0x46, 0x10, 0x00, 0x94, +0x58, 0x10, 0x86, 0x8c, 0x49, 0xfd, 0x27, 0xff, 0x46, 0x40, 0x00, 0x94, 0x58, 0x42, 0x04, 0x8c, +0x46, 0x20, 0x30, 0x61, 0x3c, 0x4f, 0xfe, 0xf0, 0x58, 0x21, 0x01, 0xdf, 0x3c, 0x2f, 0xfe, 0xfc, +0x3c, 0x2f, 0xfe, 0xfb, 0x84, 0xc0, 0x3c, 0x6e, 0x7d, 0x80, 0x3c, 0x6e, 0x7d, 0x81, 0x44, 0x00, +0x00, 0x1d, 0x46, 0x10, 0x00, 0x94, 0x58, 0x10, 0x81, 0x78, 0x49, 0xfc, 0x8c, 0x90, 0x3e, 0x09, +0xf6, 0xc0, 0x80, 0x26, 0x44, 0x20, 0x00, 0xe4, 0x49, 0xfd, 0x53, 0x17, 0x44, 0x15, 0xae, 0xe5, +0x84, 0x4a, 0x3e, 0x09, 0xf6, 0xd0, 0x49, 0xfd, 0x52, 0xfe, 0x3e, 0x29, 0xf6, 0xc0, 0x50, 0x31, +0x00, 0x3b, 0x50, 0x41, 0x00, 0x8a, 0x14, 0x41, 0x00, 0x38, 0x14, 0x31, 0x00, 0x37, 0x44, 0x00, +0x00, 0x19, 0x46, 0x10, 0x00, 0x93, 0x58, 0x10, 0x8e, 0x20, 0x49, 0xfc, 0x8c, 0x70, 0x2e, 0x11, +0xf6, 0x13, 0x44, 0x50, 0x00, 0xff, 0xd9, 0x24, 0x3e, 0x61, 0xf6, 0x13, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x01, 0x28, 0xb4, 0x20, 0x44, 0x3f, 0x0f, 0xff, 0x40, 0x10, 0x8c, 0x02, 0xb6, 0x20, +0x46, 0x20, 0x04, 0x00, 0xb4, 0x60, 0x58, 0x31, 0x90, 0x00, 0xb6, 0x60, 0x46, 0x3f, 0xff, 0x7f, +0x04, 0x01, 0x00, 0x6e, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x00, 0x0c, 0x02, 0x14, 0x01, 0x00, 0x6e, +0x80, 0x22, 0x04, 0x00, 0x80, 0x6f, 0x40, 0x00, 0x0c, 0x02, 0x14, 0x00, 0x80, 0x6f, 0x49, 0xff, +0xd3, 0x40, 0x2e, 0x47, 0xf0, 0xad, 0x3e, 0x0f, 0xf0, 0xd0, 0x44, 0x20, 0x00, 0x78, 0x58, 0x42, +0x00, 0x38, 0x46, 0x70, 0x00, 0x93, 0x58, 0x73, 0x8a, 0x70, 0x3c, 0x7f, 0xff, 0x06, 0x12, 0x20, +0x00, 0x13, 0x3e, 0x47, 0xf0, 0xad, 0x46, 0x40, 0x00, 0x95, 0x58, 0x42, 0x01, 0xf0, 0x3c, 0x4f, +0xff, 0x16, 0x46, 0x40, 0x00, 0x90, 0x58, 0x42, 0x0e, 0x28, 0x3c, 0x4f, 0xfe, 0xe2, 0x46, 0x40, +0x00, 0x91, 0x58, 0x42, 0x0d, 0x3c, 0x3c, 0x4f, 0xff, 0xd2, 0x46, 0x40, 0x00, 0x91, 0x58, 0x42, +0x0d, 0xf4, 0x3c, 0x4f, 0xff, 0xcf, 0x46, 0x40, 0x00, 0x91, 0x58, 0x42, 0x0a, 0x5c, 0x3c, 0x4f, +0xfc, 0xa6, 0x3e, 0x6f, 0xf0, 0x6c, 0x84, 0x6c, 0x46, 0x10, 0x00, 0x91, 0x58, 0x10, 0x8f, 0x94, +0x10, 0x30, 0x00, 0x24, 0xa8, 0x72, 0x10, 0x30, 0x00, 0x14, 0x12, 0x20, 0x00, 0x0b, 0x46, 0x00, +0x04, 0x90, 0x04, 0x20, 0x00, 0x20, 0x46, 0x3e, 0x0f, 0xff, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, +0x0c, 0x02, 0x46, 0x30, 0x70, 0x00, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x00, 0x20, 0x80, 0x20, +0x04, 0x20, 0x80, 0x1d, 0x44, 0x3f, 0xf0, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x58, 0x21, 0x08, 0x00, +0x14, 0x20, 0x80, 0x1d, 0x04, 0x10, 0x00, 0x22, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, 0x58, 0x10, +0x80, 0x09, 0x14, 0x10, 0x00, 0x22, 0x46, 0x10, 0x00, 0x91, 0x58, 0x10, 0x84, 0x0c, 0xa8, 0x71, +0x3e, 0x09, 0xf5, 0x70, 0x49, 0xfc, 0xf4, 0xb3, 0x92, 0x00, 0x46, 0x00, 0x00, 0x91, 0x58, 0x00, +0x02, 0x44, 0x14, 0x03, 0x00, 0x08, 0x46, 0x10, 0x00, 0x91, 0x58, 0x10, 0x80, 0xf8, 0x3c, 0x1f, +0xff, 0x36, 0x46, 0x10, 0x00, 0x91, 0x58, 0x10, 0x80, 0x90, 0x3c, 0x1f, 0xff, 0x31, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x94, 0x51, 0xc0, 0x00, 0x02, +0x81, 0x00, 0x84, 0x42, 0x80, 0x1c, 0xa6, 0x40, 0x9c, 0x91, 0x56, 0x10, 0x80, 0x55, 0x18, 0x10, +0x00, 0x01, 0x96, 0x90, 0x84, 0xab, 0xda, 0xf8, 0x3e, 0x08, 0x03, 0xb0, 0x49, 0xfc, 0x2d, 0x2d, +0x80, 0xe0, 0x4e, 0x03, 0x00, 0x8b, 0x49, 0xfc, 0x2d, 0xb2, 0x80, 0xe0, 0x50, 0x0f, 0x80, 0x14, +0x4e, 0x72, 0x00, 0xf4, 0x84, 0x20, 0x10, 0x10, 0x00, 0x0a, 0x84, 0x20, 0xb6, 0x20, 0x3e, 0x28, +0x03, 0xb0, 0x44, 0x10, 0x02, 0x55, 0xa8, 0x41, 0xa8, 0x84, 0x84, 0x21, 0x02, 0x33, 0x80, 0xc4, +0xac, 0xc6, 0x14, 0x13, 0x80, 0x6c, 0xb6, 0x27, 0x00, 0x03, 0x81, 0xae, 0xf0, 0x83, 0x3a, 0x01, +0x04, 0x00, 0x12, 0x13, 0x80, 0xd6, 0x14, 0x03, 0x80, 0x6a, 0x49, 0xfc, 0xc0, 0x04, 0x84, 0xaa, +0xd8, 0x04, 0x84, 0x02, 0x49, 0xfc, 0xbe, 0x9f, 0x3e, 0x08, 0x03, 0xb0, 0x02, 0x30, 0x00, 0x34, +0x04, 0x20, 0x00, 0x18, 0x44, 0x10, 0x00, 0x30, 0x42, 0x21, 0x84, 0x73, 0x85, 0x21, 0x84, 0x82, +0x3c, 0x4e, 0x21, 0x32, 0x14, 0x91, 0x00, 0x01, 0x50, 0xaf, 0x80, 0x60, 0x04, 0x60, 0x00, 0x18, +0xf2, 0x03, 0x46, 0x00, 0x0a, 0x5f, 0x42, 0x61, 0x04, 0x73, 0x58, 0x00, 0x00, 0xc3, 0x04, 0x13, +0x00, 0x0a, 0x14, 0x93, 0x00, 0x01, 0x10, 0x90, 0x80, 0x33, 0x80, 0x4a, 0x50, 0x1f, 0x80, 0x64, +0x49, 0xfb, 0x62, 0x2d, 0xb4, 0x4a, 0x04, 0x13, 0x00, 0x0a, 0x04, 0xa5, 0x00, 0x01, 0xb6, 0x41, +0x14, 0xa0, 0x80, 0x01, 0x46, 0x00, 0x0a, 0x5f, 0x04, 0x13, 0x00, 0x0a, 0x85, 0x40, 0x40, 0x55, +0x18, 0x06, 0x44, 0x40, 0x41, 0x3c, 0x58, 0x00, 0x00, 0xc3, 0xa8, 0x0a, 0xf4, 0x81, 0xf5, 0x82, +0x80, 0x05, 0x80, 0x2a, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x90, 0x44, 0x30, 0x02, 0x9c, +0xdd, 0x24, 0x04, 0x03, 0x00, 0x0a, 0x46, 0x20, 0x00, 0x96, 0x58, 0x21, 0x04, 0x90, 0x10, 0x90, +0x00, 0x2e, 0x80, 0x2a, 0xf0, 0x02, 0xf4, 0x01, 0x44, 0x30, 0x02, 0x89, 0xdd, 0x24, 0x04, 0x13, +0x00, 0x0a, 0x80, 0x06, 0x10, 0x90, 0x80, 0x2d, 0x49, 0xfc, 0x97, 0x27, 0x3c, 0x2d, 0xfe, 0xb9, +0x50, 0x1f, 0x80, 0x14, 0x84, 0x03, 0xdd, 0x22, 0x00, 0x63, 0x81, 0xae, 0x80, 0x3c, 0x80, 0x06, +0x49, 0xfc, 0xd2, 0x7b, 0xf0, 0x85, 0xc0, 0x04, 0x44, 0x50, 0x00, 0x1f, 0xd8, 0x5d, 0x80, 0x06, +0x49, 0xfc, 0xd1, 0xb5, 0x3c, 0x0c, 0x36, 0xec, 0x84, 0xa4, 0xd8, 0x03, 0x84, 0x05, 0xd5, 0x17, +0x84, 0xa3, 0xd8, 0x18, 0x46, 0x00, 0x04, 0x90, 0x04, 0x20, 0x00, 0x0d, 0x3c, 0x0c, 0x01, 0x04, +0x94, 0x6c, 0x44, 0x3b, 0x1e, 0x00, 0x42, 0x03, 0x04, 0x73, 0x98, 0x53, 0x94, 0x4c, 0x92, 0x24, +0xb6, 0x20, 0x80, 0x06, 0x84, 0x20, 0x49, 0xfc, 0x8e, 0x98, 0x84, 0x06, 0x3c, 0x0e, 0x36, 0xec, +0xd5, 0x37, 0x84, 0xa8, 0xd8, 0x35, 0x00, 0x74, 0x00, 0x12, 0x00, 0x14, 0x00, 0x13, 0x40, 0x73, +0xc0, 0x08, 0x40, 0x10, 0xa0, 0x08, 0x00, 0x04, 0x00, 0x14, 0x00, 0xa4, 0x00, 0x11, 0x40, 0x73, +0x84, 0x04, 0x40, 0x73, 0x80, 0x04, 0x4e, 0xa3, 0x00, 0x03, 0xc7, 0x1e, 0x50, 0x9f, 0x80, 0x60, +0x80, 0x07, 0x80, 0x49, 0x50, 0x1f, 0x80, 0x64, 0x49, 0xfb, 0x61, 0xa9, 0x3c, 0x1c, 0x01, 0x04, +0x44, 0x00, 0x00, 0x30, 0x42, 0x13, 0x00, 0x73, 0xb4, 0x49, 0x04, 0x00, 0x80, 0x0a, 0x04, 0x94, +0x80, 0x01, 0xb6, 0x40, 0x14, 0x90, 0x00, 0x01, 0x40, 0xa5, 0x60, 0x08, 0x04, 0x00, 0x80, 0x0a, +0x40, 0x73, 0xa8, 0x04, 0xa9, 0xc2, 0x80, 0x08, 0x49, 0xfc, 0xd0, 0x1d, 0xf0, 0x85, 0x80, 0x06, +0x84, 0x20, 0x49, 0xfc, 0x8a, 0x24, 0xf1, 0x05, 0x44, 0x50, 0x00, 0x1f, 0xd1, 0x09, 0x44, 0x00, +0xfc, 0x0d, 0x49, 0xfb, 0xc8, 0x54, 0xd5, 0x04, 0x84, 0x22, 0xb6, 0x20, 0xd5, 0xf5, 0xec, 0x6c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, +0x80, 0x04, 0x49, 0xfb, 0x5d, 0x3c, 0x84, 0x00, 0x10, 0x03, 0x00, 0xc0, 0xf0, 0x01, 0x49, 0xfb, +0x5d, 0x4c, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xac, +0x80, 0xc0, 0x00, 0x00, 0x00, 0xb3, 0x80, 0xe1, 0x84, 0x27, 0x4c, 0x00, 0x80, 0x03, 0xd5, 0x1a, +0x84, 0x01, 0x10, 0x03, 0x00, 0xb3, 0x50, 0x03, 0x00, 0xb8, 0x49, 0xfc, 0x7b, 0xd8, 0x80, 0x06, +0x49, 0xff, 0xff, 0xdb, 0xa6, 0xb8, 0x50, 0x1f, 0x80, 0x04, 0xb6, 0x41, 0x02, 0x23, 0x00, 0x53, +0x2e, 0x01, 0xf6, 0x12, 0xac, 0x8e, 0x84, 0xa1, 0xd8, 0x07, 0x80, 0x06, 0x49, 0xff, 0xf9, 0x83, +0x92, 0x00, 0x84, 0x00, 0xd5, 0x05, 0x3c, 0x2d, 0xfe, 0xb9, 0x84, 0x08, 0xdd, 0x22, 0xec, 0x54, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xac, 0x00, 0x70, 0x00, 0xb6, +0x00, 0x40, 0x00, 0xb3, 0x50, 0x60, 0x00, 0xae, 0x84, 0x28, 0x84, 0x06, 0x44, 0x20, 0x70, 0x54, +0x80, 0x67, 0x49, 0xfc, 0xf4, 0x30, 0xa7, 0x75, 0x84, 0x28, 0xd1, 0x05, 0xa7, 0x76, 0xd1, 0x03, +0x84, 0x0c, 0xd5, 0x4e, 0xa6, 0x77, 0x84, 0xa1, 0xd9, 0x12, 0x44, 0x00, 0x00, 0x30, 0x42, 0x73, +0x80, 0x24, 0x3e, 0x08, 0x79, 0xd8, 0x99, 0xf8, 0x04, 0x23, 0x80, 0x0b, 0x50, 0x03, 0x7f, 0x52, +0x14, 0x11, 0x00, 0x0d, 0x3c, 0x1d, 0xfd, 0x22, 0xdd, 0x21, 0xc8, 0x3a, 0xa6, 0x37, 0x84, 0xa1, +0xd8, 0x03, 0xae, 0x36, 0xd5, 0x07, 0x84, 0x01, 0xae, 0x35, 0x50, 0x03, 0x7f, 0x52, 0x49, 0xff, +0xff, 0x8c, 0x02, 0x13, 0x7f, 0xfa, 0x50, 0x03, 0x00, 0x0a, 0x58, 0x10, 0x80, 0x80, 0x12, 0x13, +0x7f, 0xfa, 0x84, 0xe0, 0x49, 0xfc, 0x7b, 0x7b, 0x50, 0x1f, 0x80, 0x04, 0x84, 0x41, 0x00, 0x03, +0x00, 0x0d, 0x10, 0x20, 0x80, 0x0a, 0x02, 0x23, 0x7f, 0xfc, 0xb6, 0xe1, 0xac, 0x8e, 0x84, 0xa1, +0xd8, 0x06, 0x3c, 0x2d, 0xfe, 0xb9, 0x44, 0x00, 0x00, 0x30, 0xd5, 0x0e, 0x2e, 0x01, 0xf6, 0x12, +0x84, 0xa1, 0xd8, 0x07, 0x50, 0x03, 0x7f, 0x52, 0x49, 0xff, 0xf9, 0x1d, 0x80, 0x07, 0xd5, 0x05, +0x3c, 0x2d, 0xfe, 0xb9, 0x84, 0x08, 0xdd, 0x22, 0x84, 0x20, 0x10, 0x13, 0x00, 0x0d, 0xec, 0x54, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x3c, 0x1d, 0xff, 0x34, 0x84, 0x04, +0xdd, 0x21, 0x3c, 0x0d, 0xff, 0xb0, 0xdd, 0x20, 0x3c, 0x7c, 0x21, 0x30, 0x49, 0xfd, 0x2f, 0x13, +0x80, 0xc0, 0x3c, 0x1c, 0x36, 0xe6, 0x50, 0x10, 0xff, 0x37, 0xe6, 0x2b, 0x4e, 0xf2, 0x00, 0x97, +0x84, 0x01, 0x40, 0x10, 0x04, 0x0c, 0x54, 0x00, 0x81, 0xf9, 0x4e, 0x03, 0x00, 0x76, 0x54, 0x00, +0x86, 0x00, 0xc8, 0x70, 0x54, 0x10, 0x80, 0x02, 0x4e, 0x12, 0x00, 0x89, 0x3e, 0x01, 0xf6, 0x18, +0x84, 0x3f, 0x3e, 0x11, 0xf6, 0x19, 0x49, 0xfd, 0x30, 0x98, 0x49, 0xfd, 0x48, 0x3a, 0x04, 0x13, +0x00, 0x0b, 0x2e, 0x00, 0x84, 0xf5, 0x04, 0x80, 0x80, 0x0c, 0x84, 0xa1, 0xd8, 0x02, 0xd5, 0x46, +0x50, 0x04, 0x7f, 0xf5, 0xe6, 0x02, 0xe9, 0x2b, 0x3c, 0xac, 0x21, 0x30, 0x8c, 0xaf, 0x4c, 0xa2, +0xc0, 0x0b, 0x9c, 0x2d, 0x49, 0xfd, 0x48, 0xb3, 0x2e, 0x00, 0x84, 0xf5, 0x84, 0xa1, 0xd8, 0x03, +0x48, 0x00, 0x00, 0x6c, 0x49, 0xfd, 0x2d, 0x1f, 0x46, 0x10, 0x04, 0x80, 0x04, 0x90, 0x83, 0xc4, +0x44, 0x10, 0x01, 0x00, 0x54, 0x94, 0x80, 0x07, 0x3c, 0x0c, 0x21, 0x30, 0x4c, 0x70, 0xc0, 0x08, +0x84, 0xa2, 0xd8, 0x05, 0x84, 0x20, 0x3c, 0x1e, 0x21, 0x38, 0xd5, 0x0e, 0x44, 0x50, 0x01, 0x00, +0xd0, 0x0b, 0x44, 0x00, 0x00, 0x15, 0x49, 0xfd, 0x49, 0x76, 0xd5, 0x06, 0x44, 0x00, 0x00, 0x15, +0x49, 0xfd, 0x49, 0x71, 0xd5, 0x03, 0x4e, 0x93, 0x00, 0x1a, 0x2e, 0x00, 0x84, 0xf5, 0x84, 0xa1, +0xd8, 0x02, 0xd5, 0x0c, 0x49, 0xfd, 0x2c, 0xc7, 0x46, 0x10, 0x04, 0x80, 0x04, 0x00, 0x83, 0xc6, +0x54, 0x00, 0x00, 0x03, 0xc8, 0x06, 0x49, 0xfd, 0x45, 0x08, 0x49, 0xfd, 0x31, 0x0e, 0xd5, 0x09, +0x44, 0x10, 0x00, 0xd2, 0x3c, 0x1e, 0x36, 0xe6, 0xd5, 0x04, 0x80, 0x09, 0x49, 0xfd, 0x31, 0x49, +0x84, 0xa4, 0x4c, 0x82, 0xc0, 0x2d, 0x84, 0xa2, 0xdf, 0x2a, 0x80, 0x06, 0x49, 0xfd, 0x2b, 0x1d, +0xd5, 0x26, 0x49, 0xfd, 0x28, 0xa8, 0x3c, 0x1c, 0x28, 0x95, 0x9c, 0x49, 0x3c, 0x3c, 0x36, 0xe6, +0x3c, 0x1e, 0x28, 0x95, 0x44, 0x50, 0x00, 0xcc, 0xdb, 0x09, 0x46, 0x00, 0x04, 0x80, 0x04, 0x10, +0x03, 0xc6, 0x58, 0x10, 0x80, 0x03, 0x14, 0x10, 0x03, 0xc6, 0x3c, 0x4d, 0xff, 0x14, 0x84, 0x21, +0x84, 0x04, 0x44, 0x20, 0x30, 0x5b, 0xdd, 0x24, 0xd5, 0x0a, 0x3c, 0x1d, 0xff, 0x31, 0x44, 0x00, +0x00, 0xc9, 0xdd, 0x21, 0x49, 0xfd, 0x44, 0xd1, 0x49, 0xfd, 0x30, 0xd7, 0x3c, 0x1d, 0xff, 0x34, +0x84, 0x05, 0xdd, 0x21, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x30, 0x00, 0x00, 0x00, 0x70, 0x61, +0x74, 0x63, 0x68, 0x2f, 0x73, 0x79, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x62, 0x69, +0x6e, 0x5f, 0x74, 0x2e, 0x63, 0x00, 0x55, 0x41, 0x52, 0x54, 0x31, 0x00, 0x00, 0x00, 0x62, 0x6c, +0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6c, 0x63, 0x2f, +0x64, 0x6c, 0x2f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x2f, 0x64, 0x6c, 0x5f, 0x64, 0x65, +0x76, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf7, +0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xde, 0xff, 0xff, 0x7f, 0x00, 0x00, +0x00, 0x00, 0x00, 0xc0, 0xdf, 0xfb, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7b, +0xff, 0x7f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xef, 0x7f, 0xff, 0x03, 0x00, 0x00, +0x00, 0x00, 0x00, 0xe0, 0xef, 0x7d, 0xf7, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3d, +0xff, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xff, 0xdf, 0xff, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0x70, 0xff, 0xff, 0xfb, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x7f, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xef, 0xff, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xbf, 0xff, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x55, 0x0f, 0xaa, 0x0f, 0x55, 0x0f, 0xaa, 0x0f, 0xf8, +0x00, 0x00, 0x0f, 0x55, 0x0f, 0xaa, 0x0f, 0x55, 0x0f, 0xaa, 0x0f, 0xf2, 0x00, 0x00, 0x00, 0xc2, +0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x11, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x15, 0x00, 0x55, 0x00, 0x57, 0x00, 0x57, 0x00, +0x77, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, +0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, +0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, +0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xc8, 0x00, +0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0xc4, 0x01, +0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x13, 0xff, 0x0d, 0x00, 0x01, 0x00, +0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x53, 0x4f, +0x4e, 0x59, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x11, +0x09, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x07, 0x27, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, +0x00, 0x03, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0d, +0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x0f, 0x11, 0x13, 0x15, 0x15, 0x17, 0x19, 0x1b, 0x13, 0x15, +0x17, 0x19, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, 0x19, 0x1b, 0x0b, 0x0d, +0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x0f, 0x11, 0x13, 0x15, 0x15, 0x17, 0x19, 0x1b, 0x13, 0x15, +0x17, 0x19, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, 0x19, 0x1b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x06, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x01, 0x01, +0x03, 0x24, 0x07, 0x0b, 0x31, 0x3f, 0xff, 0x0a, 0x07, 0x00, 0x03, 0x0a, 0x07, 0x05, 0x02, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662t_firmware.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662t_firmware.h new file mode 100644 index 000000000..48e5a2026 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662t_firmware.h @@ -0,0 +1,5158 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7662T_FirmwareImage[] = { +0x5c, 0xfc, 0x00, 0x00, 0x8c, 0x45, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0xe3, 0x01, 0x08, +0x32, 0x30, 0x31, 0x36, 0x30, 0x31, 0x31, 0x35, 0x31, 0x35, 0x35, 0x37, 0x5f, 0x5f, 0x5f, 0x5f, +0x46, 0x00, 0x00, 0x8f, 0x58, 0x00, 0x08, 0x24, 0x4a, 0x00, 0x00, 0x00, 0x80, 0x9e, 0x3e, 0x09, +0x44, 0xd8, 0x3e, 0x19, 0x44, 0xd8, 0x3e, 0x29, 0x8a, 0x64, 0x40, 0x31, 0x04, 0x01, 0x40, 0x00, +0x0c, 0x00, 0x3a, 0x10, 0x04, 0x1c, 0x3a, 0x11, 0x04, 0x3c, 0x50, 0x31, 0xff, 0xfc, 0x4e, 0x36, +0xff, 0xfa, 0x64, 0x00, 0x00, 0x09, 0x3e, 0x09, 0x44, 0xd8, 0x3e, 0x29, 0x44, 0xd8, 0x4c, 0x01, +0x00, 0x08, 0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfe, 0x3e, 0x09, +0x8a, 0x64, 0x3e, 0x29, 0xed, 0x54, 0x4c, 0x01, 0x00, 0x08, 0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, +0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfe, 0x83, 0xc4, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x10, 0x04, 0x00, +0x44, 0x20, 0x00, 0xea, 0x80, 0x01, 0x14, 0x20, 0x81, 0x04, 0x44, 0x10, 0x00, 0x98, 0x14, 0x10, +0x01, 0x06, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x81, 0x00, +0x80, 0x01, 0x58, 0x21, 0x00, 0x11, 0x14, 0x20, 0x81, 0x00, 0x04, 0x10, 0x01, 0x06, 0x3e, 0x69, +0x8a, 0x84, 0x58, 0x10, 0x80, 0x80, 0x14, 0x10, 0x01, 0x06, 0x44, 0x50, 0x03, 0xe8, 0xb4, 0x06, +0x9c, 0x01, 0xb6, 0x06, 0xd8, 0x09, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6d, 0x84, 0x40, 0x49, 0xfc, +0x38, 0x4b, 0x84, 0x00, 0xb6, 0x06, 0x2e, 0x01, 0x8a, 0x52, 0x84, 0xa1, 0xd8, 0x09, 0x3c, 0x1c, +0x62, 0xa1, 0x84, 0x05, 0x40, 0x10, 0x80, 0x16, 0xc8, 0x03, 0x49, 0x00, 0x12, 0x6d, 0x49, 0x00, +0x14, 0x59, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x04, 0x60, 0x00, 0x78, 0x96, 0x30, 0x96, 0x44, 0xc1, 0x05, +0x3c, 0x7c, 0x62, 0xc5, 0x84, 0xc1, 0xd5, 0x26, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x05, 0x3c, 0x7c, +0x62, 0xc6, 0x84, 0xc2, 0xd5, 0x1f, 0x40, 0x73, 0x40, 0x09, 0x97, 0xf8, 0x54, 0x03, 0x80, 0x02, +0xc0, 0x06, 0x3c, 0x7c, 0x62, 0xd6, 0x44, 0x62, 0x00, 0x00, 0xd5, 0x14, 0x97, 0xfc, 0xc7, 0x06, +0x3c, 0x7c, 0x62, 0xd5, 0x44, 0x61, 0x00, 0x00, 0xd5, 0x0d, 0x3e, 0x09, 0x44, 0xd8, 0x49, 0x00, +0x04, 0x07, 0x80, 0x07, 0x80, 0x27, 0x3e, 0x29, 0x44, 0xf8, 0x44, 0x30, 0x01, 0x00, 0x49, 0xfc, +0x22, 0x9d, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x84, 0x20, 0x14, 0x60, 0x00, 0x78, +0x3e, 0x29, 0x44, 0xf8, 0x40, 0x00, 0x9c, 0x06, 0x44, 0x30, 0x01, 0x0b, 0x49, 0xfc, 0x22, 0x8e, +0x92, 0x00, 0x3e, 0x09, 0xd9, 0xe8, 0xdd, 0x27, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3e, 0x29, 0x44, 0xf8, 0x80, 0xc0, 0x80, 0xe1, 0x5c, 0x00, +0x00, 0x20, 0x84, 0x20, 0x44, 0x30, 0x00, 0xb5, 0x49, 0xfc, 0x22, 0x78, 0x92, 0x00, 0x3e, 0x09, +0x8b, 0x14, 0x38, 0x70, 0x1a, 0x0a, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x04, 0x00, +0x80, 0x78, 0x84, 0x41, 0x40, 0x61, 0x18, 0x0c, 0x40, 0x03, 0x00, 0x04, 0x14, 0x00, 0x80, 0x78, +0x04, 0x00, 0x80, 0x7a, 0x40, 0x63, 0x00, 0x04, 0x14, 0x60, 0x80, 0x7a, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x84, 0x20, 0xf1, 0x81, 0x44, 0x10, +0x00, 0x40, 0x10, 0x1f, 0x80, 0x04, 0x10, 0x1f, 0x80, 0x07, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, +0x88, 0x00, 0xb4, 0x41, 0x50, 0x60, 0x00, 0x9c, 0x58, 0x01, 0x00, 0x02, 0xb6, 0x01, 0x80, 0x01, +0xf2, 0x01, 0x14, 0x20, 0x80, 0x71, 0x04, 0x70, 0x00, 0x71, 0x46, 0x80, 0x04, 0x10, 0x42, 0x13, +0x8c, 0x0b, 0xf7, 0x81, 0x58, 0x84, 0x08, 0x00, 0xc9, 0xf7, 0x42, 0x73, 0x84, 0x0b, 0xcf, 0xf4, +0x50, 0x13, 0x7f, 0x64, 0x50, 0x23, 0x7f, 0xe4, 0x50, 0x04, 0x01, 0xa0, 0x84, 0x62, 0x49, 0x00, +0x02, 0x8d, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0x84, 0x50, 0x23, 0x7f, 0xec, 0x58, 0x00, +0x09, 0xb0, 0x84, 0x62, 0x49, 0x00, 0x02, 0x82, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0xa4, +0x50, 0x23, 0x7f, 0xf4, 0x58, 0x00, 0x09, 0x80, 0x84, 0x62, 0x49, 0x00, 0x02, 0x53, 0x46, 0x00, +0x04, 0x10, 0x50, 0x13, 0x7f, 0xc4, 0x9e, 0xb4, 0x84, 0x62, 0x58, 0x00, 0x09, 0x90, 0x49, 0x00, +0x02, 0x49, 0x84, 0x01, 0xaf, 0xf5, 0xaf, 0xf4, 0x10, 0x04, 0x01, 0xa8, 0x10, 0x04, 0x01, 0xb8, +0x14, 0x73, 0x00, 0x09, 0xaf, 0xf7, 0xaf, 0xf6, 0xa9, 0xf4, 0xa9, 0xf5, 0xa9, 0xf2, 0xa9, 0xf3, +0x50, 0x03, 0x00, 0x1c, 0x49, 0x00, 0x06, 0x00, 0x04, 0x14, 0x00, 0x71, 0x58, 0x00, 0x80, 0x05, +0xf1, 0x81, 0x10, 0x0f, 0x80, 0x04, 0xf0, 0x01, 0x14, 0x04, 0x00, 0x71, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x04, 0x20, 0x00, 0x29, 0x04, 0x30, 0x00, 0x2a, +0x9c, 0x92, 0x9a, 0x93, 0xe4, 0x42, 0x4e, 0xf3, 0x00, 0x84, 0x00, 0x30, 0x00, 0xa2, 0x9c, 0x9c, +0x94, 0x94, 0x98, 0x82, 0xa7, 0x17, 0x54, 0x42, 0x00, 0x80, 0xc4, 0x7a, 0xb4, 0xa1, 0x50, 0x41, +0x80, 0x24, 0x38, 0x50, 0x12, 0x0a, 0x95, 0x9c, 0x00, 0x50, 0x80, 0x9e, 0x00, 0x70, 0x80, 0x9f, +0xa1, 0x0b, 0x99, 0xfd, 0x8c, 0xf4, 0x50, 0x50, 0x80, 0x10, 0x02, 0x81, 0x00, 0x03, 0xc4, 0x22, +0x93, 0x0e, 0x40, 0x84, 0x38, 0x08, 0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0xb6, 0xa2, 0xa7, 0x17, +0x42, 0x42, 0x18, 0x09, 0xaf, 0x17, 0x99, 0x86, 0xa1, 0x0a, 0x14, 0x43, 0x00, 0x12, 0xa1, 0x0b, +0xa4, 0x52, 0x54, 0x42, 0x3f, 0xff, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x10, 0x90, 0x04, +0xac, 0x52, 0xa7, 0x17, 0xa6, 0x55, 0x54, 0x42, 0x00, 0x7f, 0x58, 0x10, 0x80, 0x40, 0xaf, 0x17, +0xd5, 0x1b, 0x93, 0x0e, 0x40, 0x84, 0x38, 0x08, 0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0x99, 0x86, +0xa6, 0x57, 0xb6, 0xa2, 0x58, 0x10, 0x80, 0x40, 0xae, 0x57, 0x14, 0x43, 0x00, 0x12, 0xa4, 0x52, +0xa7, 0x17, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0xac, 0x52, 0x54, 0x42, 0x00, 0x7f, 0xa6, 0x55, +0xaf, 0x17, 0x42, 0x10, 0x98, 0x09, 0xae, 0x55, 0x94, 0x5c, 0x98, 0x41, 0x50, 0x10, 0x80, 0x48, +0xa6, 0x8e, 0x44, 0x5f, 0xff, 0xcf, 0x40, 0x21, 0x14, 0x02, 0x58, 0x21, 0x00, 0x08, 0x84, 0x84, +0x9c, 0xdc, 0xaf, 0x0f, 0xae, 0x8e, 0x40, 0x31, 0x90, 0x0c, 0x98, 0xc3, 0xa4, 0x9b, 0xb4, 0x61, +0x54, 0x21, 0x3f, 0xff, 0x98, 0x9a, 0xac, 0x8a, 0x46, 0x10, 0x04, 0x10, 0x00, 0x20, 0x00, 0xa2, +0x04, 0x30, 0x00, 0x2a, 0x9c, 0x91, 0x96, 0x94, 0x9c, 0xd9, 0x58, 0x10, 0x88, 0x00, 0x14, 0x30, +0x00, 0x2a, 0x10, 0x20, 0x00, 0xa2, 0x10, 0x20, 0x81, 0x88, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, +0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2b, 0x04, 0x30, 0x00, 0x2c, +0x9c, 0x92, 0x9a, 0x93, 0xe4, 0x42, 0xe9, 0x40, 0x00, 0x30, 0x00, 0xa3, 0x9c, 0x9e, 0x94, 0x94, +0x98, 0x82, 0xa7, 0x17, 0x54, 0x42, 0x00, 0x80, 0xc4, 0x37, 0x50, 0x41, 0x80, 0x26, 0x38, 0x10, +0x12, 0x0a, 0x94, 0xdc, 0xa1, 0x0a, 0x98, 0xc3, 0xb6, 0x82, 0xa1, 0x4c, 0x14, 0x51, 0x80, 0x1b, +0xa5, 0x0e, 0xa4, 0xd3, 0x54, 0x42, 0x3f, 0xff, 0x92, 0x6e, 0x40, 0x31, 0xb8, 0x08, 0x40, 0x31, +0x90, 0x04, 0xac, 0xd3, 0xa7, 0x55, 0x00, 0x40, 0x80, 0x0f, 0xa6, 0xd7, 0x97, 0x24, 0x95, 0x26, +0x54, 0x31, 0x80, 0x3f, 0x40, 0x31, 0x90, 0x04, 0x54, 0x12, 0x80, 0x7f, 0xae, 0x55, 0xae, 0xd7, +0x46, 0x10, 0x04, 0x10, 0x00, 0x20, 0x00, 0xa3, 0x04, 0x30, 0x00, 0x2c, 0x9c, 0x91, 0x96, 0x94, +0x9c, 0xd9, 0x58, 0x10, 0x88, 0x00, 0x14, 0x30, 0x00, 0x2c, 0x10, 0x20, 0x00, 0xa3, 0x10, 0x20, +0x81, 0x98, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0xd5, 0x20, 0xa6, 0x9f, 0x54, 0x21, 0x00, 0x80, 0xc2, 0x2b, +0x38, 0x23, 0x06, 0x02, 0x38, 0x93, 0x06, 0x0a, 0x80, 0x22, 0x00, 0x31, 0x00, 0x14, 0xcb, 0x02, +0xd5, 0x03, 0x3e, 0x09, 0xd3, 0x00, 0x9d, 0xfe, 0x95, 0xfc, 0x99, 0xf7, 0x49, 0x00, 0x04, 0x30, +0xa6, 0x3f, 0x44, 0x1f, 0xff, 0xc0, 0x40, 0x00, 0x04, 0x04, 0xae, 0x3f, 0x04, 0x03, 0x00, 0x2b, +0x9c, 0x01, 0x14, 0x03, 0x00, 0x2b, 0x04, 0x03, 0x00, 0x2b, 0x04, 0x23, 0x00, 0x2c, 0x97, 0xc4, +0x9c, 0xfe, 0x94, 0xdc, 0x9a, 0x90, 0x50, 0x13, 0x80, 0x26, 0x98, 0xf3, 0x3e, 0x09, 0xd3, 0x10, +0x4e, 0x26, 0xff, 0xd4, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xff, 0xff, 0xc5, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0xd5, 0x1a, 0xa6, 0x7f, 0x54, 0x10, +0x80, 0x80, 0xc1, 0x25, 0x38, 0x13, 0x0a, 0x02, 0x38, 0x93, 0x0a, 0x0a, 0x49, 0x00, 0x03, 0xf8, +0xa6, 0x7f, 0xa6, 0x3d, 0x44, 0x2f, 0xff, 0xc0, 0x58, 0x00, 0x00, 0x40, 0x40, 0x10, 0x88, 0x04, +0xae, 0x7f, 0xae, 0x3d, 0x04, 0x03, 0x00, 0x29, 0x9c, 0x01, 0x14, 0x03, 0x00, 0x29, 0x04, 0x13, +0x00, 0x29, 0x04, 0x33, 0x00, 0x2a, 0x97, 0xcc, 0x50, 0x23, 0x80, 0x24, 0x9d, 0xfc, 0x95, 0xfc, +0x9a, 0x59, 0x3e, 0x09, 0xd3, 0x00, 0x99, 0xf7, 0x4e, 0x16, 0xff, 0xda, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xff, 0xcb, 0x92, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, +0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, +0x00, 0xa1, 0x00, 0x52, 0x01, 0xbc, 0x9c, 0xba, 0x94, 0x94, 0x3e, 0x09, 0xd3, 0x00, 0x50, 0xa3, +0x80, 0x22, 0x40, 0x6e, 0x08, 0x00, 0xd7, 0x4a, 0xa6, 0x77, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x46, +0xa4, 0x73, 0xb6, 0x9f, 0x54, 0x90, 0xbf, 0xff, 0x49, 0x00, 0x03, 0x88, 0x81, 0x00, 0x94, 0x7c, +0x40, 0x3e, 0x04, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x0b, 0x3e, 0x09, 0x45, 0x14, +0x49, 0x00, 0x01, 0xc6, 0xb9, 0x2d, 0x42, 0x10, 0xc4, 0x08, 0xb9, 0xad, 0xd5, 0x2f, 0x38, 0x2e, +0x2a, 0x02, 0x12, 0x91, 0x00, 0x06, 0x80, 0x22, 0x04, 0x31, 0x80, 0x0b, 0xa8, 0xd4, 0x84, 0x61, +0x10, 0x31, 0x00, 0x14, 0xb6, 0x9f, 0x49, 0x00, 0x03, 0x8b, 0x38, 0x8e, 0x2a, 0x0a, 0x84, 0x20, +0x80, 0x06, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xd8, 0x51, 0xa6, 0x77, 0x04, 0x84, 0x00, 0x02, +0x58, 0x10, 0x80, 0x40, 0xae, 0x77, 0xa4, 0x73, 0xb7, 0x06, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, +0x58, 0x10, 0x86, 0x40, 0xac, 0x73, 0xb4, 0x9f, 0x10, 0x72, 0x01, 0xb8, 0x00, 0x1e, 0x00, 0xa1, +0x9c, 0x49, 0x96, 0x4c, 0x10, 0x1e, 0x00, 0xa1, 0xd5, 0xab, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, 0x50, 0x00, 0x00, 0xb8, +0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, 0x00, 0xa0, 0x00, 0x52, +0x01, 0xac, 0x94, 0xbc, 0x3e, 0x09, 0xd3, 0x10, 0x50, 0xa3, 0x80, 0x20, 0x40, 0x6e, 0x08, 0x00, +0xd7, 0x4b, 0xa6, 0x77, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x47, 0xa4, 0x73, 0xb6, 0x9f, 0x54, 0x90, +0xbf, 0xff, 0x49, 0x00, 0x03, 0x23, 0x98, 0x7f, 0x9c, 0x49, 0x81, 0x00, 0x94, 0x4b, 0x40, 0x3e, +0x04, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x0b, 0x3e, 0x09, 0x45, 0x30, 0x49, 0x00, +0x01, 0x5f, 0xb9, 0x2d, 0x42, 0x10, 0xc0, 0x08, 0xb9, 0xad, 0xd5, 0x2e, 0x38, 0x2e, 0x2a, 0x02, +0x12, 0x91, 0x00, 0x06, 0x80, 0x22, 0xa0, 0xd9, 0xa8, 0xd4, 0x84, 0x60, 0x10, 0x31, 0x00, 0x14, +0xb6, 0x9f, 0x49, 0x00, 0x03, 0x25, 0x38, 0x8e, 0x2a, 0x0a, 0x84, 0x20, 0x80, 0x06, 0x44, 0x20, +0x00, 0x10, 0x49, 0xfe, 0xd7, 0xeb, 0xa6, 0x77, 0x04, 0x84, 0x00, 0x02, 0x58, 0x10, 0x80, 0x40, +0xae, 0x77, 0xa4, 0x73, 0xb7, 0x06, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x58, 0x10, 0x80, 0xc8, +0xac, 0x73, 0xb4, 0x9f, 0x10, 0x72, 0x01, 0xa8, 0x00, 0x1e, 0x00, 0xa0, 0x9c, 0x49, 0x96, 0x4c, +0x10, 0x1e, 0x00, 0xa0, 0xd5, 0xab, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xb6, 0x20, 0xa8, 0xc1, 0x80, 0xc1, 0xa0, 0x43, 0x84, 0xe0, +0x81, 0x23, 0x81, 0x02, 0xa8, 0x42, 0x45, 0xc5, 0xb6, 0x98, 0x81, 0x47, 0xd5, 0x0c, 0xdd, 0x3c, +0xa6, 0x37, 0x44, 0x1f, 0xff, 0xc0, 0x40, 0x00, 0x04, 0x04, 0xae, 0x37, 0x1c, 0xa4, 0x00, 0x01, +0x9d, 0xf9, 0x8c, 0xd0, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0xe2, 0xe9, 0xe9, 0xf0, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0xb6, 0x20, +0x83, 0x83, 0xa8, 0xc1, 0x46, 0x30, 0x04, 0x10, 0x58, 0x31, 0x89, 0xb0, 0x80, 0xc1, 0x40, 0x10, +0x0c, 0x03, 0xa0, 0xc3, 0x44, 0x40, 0x06, 0x40, 0xa8, 0xc2, 0x44, 0x50, 0x00, 0xc8, 0x3e, 0x39, +0xd3, 0x00, 0x3e, 0x09, 0xd3, 0x10, 0x40, 0x82, 0x84, 0x1b, 0x40, 0x82, 0x04, 0x1a, 0x84, 0xe0, +0x40, 0x41, 0x84, 0x1a, 0x40, 0x40, 0x04, 0x1b, 0xf4, 0x83, 0x81, 0x42, 0x44, 0x45, 0xb6, 0x98, +0x81, 0x27, 0x54, 0x34, 0x3f, 0xff, 0xd5, 0x21, 0xf3, 0x81, 0xf4, 0x82, 0xdd, 0x24, 0xf0, 0x03, +0x49, 0x00, 0x02, 0x8c, 0x92, 0x00, 0xf3, 0x01, 0xf4, 0x02, 0xc0, 0x1d, 0x12, 0x80, 0x00, 0x06, +0x10, 0x90, 0x00, 0x0e, 0x10, 0x90, 0x00, 0x0f, 0xa6, 0x77, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x3f, +0xae, 0x77, 0xa4, 0x73, 0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x10, 0x8c, 0x04, 0xac, 0x73, +0xa0, 0x42, 0xaa, 0x74, 0x1c, 0x05, 0x00, 0x01, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, +0xe2, 0xfc, 0xe9, 0xdb, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x04, 0x10, 0x00, 0x2d, 0x42, 0x10, 0xc4, 0x08, 0x14, 0x10, 0x00, 0x2d, 0x2e, 0x21, +0x8a, 0x4e, 0x84, 0xa1, 0xda, 0x07, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6f, 0x49, 0xfc, 0x34, 0xa4, +0x92, 0x00, 0x84, 0x20, 0x3e, 0x11, 0x8a, 0x4e, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x04, 0x20, 0x00, 0x2d, 0x80, 0x20, 0x42, 0x21, 0x40, 0x08, +0x14, 0x20, 0x80, 0x2d, 0x84, 0x02, 0x44, 0x10, 0x00, 0x6f, 0x84, 0x40, 0x49, 0xfc, 0x34, 0x8c, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x02, 0x00, 0xa0, 0x44, 0x40, 0x00, 0xa0, 0x09, 0x96, 0x00, 0x54, 0x20, 0x00, 0x10, +0xc2, 0x04, 0x3c, 0x6c, 0x62, 0xf1, 0xd5, 0x26, 0x54, 0x20, 0x00, 0x20, 0xc2, 0x04, 0x3c, 0x6c, +0x62, 0xf2, 0xd5, 0x20, 0x54, 0x20, 0x00, 0x40, 0xc2, 0x04, 0x3c, 0x6c, 0x62, 0xf3, 0xd5, 0x1a, +0x54, 0x00, 0x00, 0x80, 0xc0, 0x04, 0x3c, 0x6c, 0x62, 0xf4, 0xd5, 0x14, 0x40, 0x60, 0xc0, 0x09, +0x97, 0xb0, 0x96, 0x34, 0xc0, 0x04, 0x3c, 0x6c, 0x62, 0xf5, 0xd5, 0x0c, 0x54, 0x63, 0x00, 0x02, +0x97, 0xb0, 0xc6, 0x04, 0x3c, 0x6c, 0x62, 0xf6, 0xd5, 0x05, 0x3e, 0x09, 0x45, 0x4c, 0x49, 0x00, +0x00, 0x4f, 0x84, 0x20, 0x40, 0x00, 0x98, 0x06, 0x3e, 0x29, 0x45, 0x64, 0x44, 0x30, 0x00, 0x6e, +0x49, 0xfc, 0x1e, 0xe4, 0xdd, 0x26, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x80, 0xe1, 0x80, 0xc0, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x20, 0x3e, 0x29, 0x45, 0x64, 0x44, 0x30, +0x00, 0x36, 0x49, 0xfc, 0x1e, 0xd3, 0x84, 0x20, 0x40, 0x00, 0x9c, 0x06, 0x3e, 0x29, 0x45, 0x64, +0x44, 0x30, 0x00, 0x37, 0x49, 0xfc, 0x1e, 0xca, 0x3e, 0x09, 0x8b, 0x94, 0x38, 0x70, 0x1a, 0x0a, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x00, 0xa0, 0x0d, 0x84, 0x41, 0x40, 0x61, 0x18, 0x0c, +0x40, 0x63, 0x00, 0x04, 0xa9, 0x8d, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0xb4, 0x41, 0x18, 0x01, +0x00, 0x01, 0x84, 0x00, 0xb6, 0x41, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x80, 0x66, +0x80, 0x01, 0x80, 0x22, 0x46, 0x20, 0x00, 0x80, 0x58, 0x21, 0x09, 0x1c, 0x49, 0xfc, 0x1e, 0xcc, +0x84, 0x40, 0x38, 0x23, 0x00, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x1f, 0x94, 0x3c, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf4, 0x2e, 0x21, 0x8a, 0x50, 0x84, 0x21, 0x80, 0xc0, 0x4c, 0x20, +0xc0, 0x08, 0x50, 0x1f, 0x80, 0x14, 0xf1, 0x81, 0x49, 0xfc, 0x20, 0x28, 0xd5, 0x1f, 0x84, 0x62, +0x4c, 0x21, 0xc0, 0x1d, 0x50, 0x3f, 0x80, 0x14, 0x84, 0x20, 0x44, 0x20, 0x02, 0x00, 0x3e, 0x09, +0x8c, 0x14, 0xf3, 0x81, 0x49, 0xfe, 0xd6, 0x8a, 0xf2, 0x01, 0x80, 0x26, 0x3e, 0x09, 0x8c, 0x14, +0x49, 0xff, 0xff, 0xcc, 0x3e, 0x09, 0x8c, 0x14, 0x49, 0xfe, 0xd6, 0x88, 0x9c, 0xc1, 0x84, 0x20, +0x84, 0x03, 0x3e, 0x29, 0x8c, 0x14, 0x49, 0x00, 0x0f, 0x93, 0xec, 0x0c, 0x3a, 0x6f, 0x98, 0x84, +0xec, 0x14, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x01, 0x80, 0xe2, 0x81, 0x23, +0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0xa0, 0x80, 0xc0, 0x49, 0xfc, 0x1e, 0x5e, +0x84, 0x00, 0x14, 0x93, 0x00, 0x05, 0xa8, 0x31, 0x14, 0x83, 0x00, 0x06, 0xa9, 0xf4, 0xb6, 0x06, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x84, 0x20, +0x80, 0xc0, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0xd1, 0x44, 0x70, 0x46, 0x88, 0xdd, 0x27, +0x80, 0x06, 0x84, 0x20, 0x3e, 0x29, 0x45, 0xa0, 0x44, 0x30, 0x00, 0xd7, 0xdd, 0x27, 0xb4, 0x06, +0xc0, 0x22, 0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0xd4, 0x3e, 0x09, 0xd2, 0xec, +0xdd, 0x27, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0xd4, 0xdd, 0x27, +0xa0, 0x71, 0xb4, 0x46, 0x84, 0x00, 0xa8, 0x51, 0xb6, 0x41, 0xa8, 0x31, 0xb6, 0x06, 0x3e, 0x59, +0xd2, 0xec, 0xa0, 0xaa, 0xb4, 0x25, 0x9e, 0x91, 0xa8, 0xaa, 0xd9, 0x05, 0xa0, 0x0b, 0x49, 0xfc, +0x13, 0x67, 0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x3c, 0x1c, 0x74, 0xbe, 0x80, 0xe0, 0xc1, 0x10, 0x80, 0x01, 0x49, 0xfc, 0x13, 0x58, +0x44, 0x10, 0x03, 0xe8, 0x42, 0x13, 0x84, 0x24, 0x44, 0x20, 0x7f, 0xff, 0x98, 0x4a, 0x3c, 0x0c, +0x74, 0xbe, 0x92, 0x2f, 0x49, 0xfc, 0x15, 0x68, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x49, 0xfc, 0x12, 0x07, 0x81, 0x20, 0x46, 0x07, 0xff, 0xff, +0x58, 0x00, 0x0f, 0xff, 0x3e, 0x19, 0xd2, 0xec, 0x41, 0xc4, 0x80, 0x00, 0x15, 0xc0, 0x80, 0x04, +0x80, 0xe1, 0xb4, 0xc1, 0x46, 0x10, 0x01, 0xe0, 0x88, 0x29, 0xf1, 0x81, 0xd5, 0x42, 0x80, 0x06, +0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x01, 0x3c, 0x49, 0xfc, 0x1d, 0xdf, 0xa0, 0x32, +0x40, 0x14, 0x80, 0x01, 0x4e, 0x15, 0x00, 0x2e, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x29, 0x45, 0xa0, +0x44, 0x30, 0x00, 0xd7, 0x49, 0xfc, 0x1d, 0xd2, 0xb4, 0x06, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, +0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x01, 0x40, 0x49, 0xfc, 0x1d, 0xc8, 0x80, 0x06, 0x49, 0xff, +0xff, 0x75, 0xa4, 0x36, 0xc0, 0x0e, 0x9e, 0x01, 0xac, 0x36, 0xf0, 0x01, 0xa8, 0x32, 0xa0, 0x39, +0xa9, 0xb9, 0xb6, 0xe6, 0xa8, 0x31, 0xb6, 0xc0, 0xa0, 0x3a, 0x9c, 0x01, 0xa8, 0x3a, 0xd5, 0x06, +0xa0, 0xb6, 0xc2, 0x04, 0xa0, 0x75, 0xa0, 0x34, 0xdd, 0x22, 0x15, 0xc3, 0x80, 0x04, 0xd5, 0x08, +0xa0, 0x7c, 0x9a, 0x41, 0x4e, 0x15, 0x00, 0x03, 0xd5, 0x02, 0xa8, 0x3c, 0x81, 0x06, 0xb4, 0xc8, +0x3e, 0x89, 0xd2, 0xec, 0x4c, 0x64, 0x7f, 0xbd, 0xb4, 0xa6, 0xd6, 0x10, 0xa0, 0x34, 0x84, 0x20, +0x40, 0x04, 0x80, 0x01, 0x92, 0x1f, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x01, 0x60, 0x49, 0xfc, +0x1d, 0x95, 0xa0, 0x34, 0x8a, 0x09, 0x49, 0xff, 0xff, 0x7b, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x44, 0x80, 0xea, 0x60, 0x80, 0xe1, +0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0xf4, 0x80, 0xc0, 0x49, 0xfc, 0x1d, 0x7e, +0xe3, 0x07, 0xe8, 0x1b, 0x46, 0x0e, 0xa5, 0xf1, 0x58, 0x00, 0x05, 0xa1, 0x40, 0x03, 0x80, 0x06, +0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0xfc, 0x49, 0xfc, 0x1d, 0x6f, 0x40, 0x03, +0xa0, 0x37, 0x44, 0x1f, 0x15, 0xa0, 0x96, 0x01, 0x42, 0x70, 0x04, 0x73, 0xac, 0x36, 0xcf, 0x07, +0x9e, 0x01, 0xac, 0x36, 0x80, 0xe8, 0xd5, 0x03, 0x84, 0x00, 0xac, 0x36, 0x44, 0x00, 0xff, 0xff, +0x40, 0x03, 0x80, 0x06, 0x84, 0x20, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x01, 0x0a, 0x40, 0x93, +0xbc, 0x08, 0x49, 0xfc, 0x1d, 0x53, 0x50, 0x94, 0x83, 0xe7, 0x44, 0x00, 0x03, 0xe8, 0x40, 0x94, +0x80, 0x17, 0x3e, 0x79, 0xd2, 0xec, 0x49, 0xfc, 0x11, 0x57, 0x40, 0x84, 0x80, 0x00, 0xb4, 0xa7, +0xd7, 0x06, 0xa0, 0x3c, 0x40, 0x04, 0x00, 0x01, 0x4e, 0x04, 0x00, 0x07, 0x3c, 0x8e, 0x74, 0xbf, +0x80, 0x09, 0x49, 0xff, 0xff, 0x25, 0x14, 0x83, 0x00, 0x02, 0x84, 0x20, 0x80, 0x06, 0x3e, 0x29, +0x45, 0xa0, 0x44, 0x30, 0x00, 0xd7, 0x49, 0xfc, 0x1d, 0x31, 0xb4, 0x26, 0xc9, 0x0a, 0x3c, 0x0c, +0x74, 0xbc, 0xa9, 0xb9, 0xb6, 0xe6, 0xa8, 0x31, 0xb6, 0xc0, 0xa0, 0x3a, 0x9c, 0x01, 0xa8, 0x3a, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x3e, 0x69, +0xd2, 0xec, 0x84, 0xe0, 0xa0, 0x33, 0x80, 0x27, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0x88, +0xb6, 0xc6, 0xa9, 0xb1, 0xa9, 0xf2, 0x49, 0xfc, 0x1d, 0x11, 0xa0, 0x33, 0x49, 0x00, 0x33, 0xd8, +0xa9, 0xf3, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x3e, 0x69, 0xd2, 0xec, 0xa1, 0xf3, 0x84, 0x20, 0xa8, 0x72, 0xb6, 0xc6, 0xa9, 0xb1, +0xcf, 0x0c, 0x49, 0xfc, 0x11, 0x45, 0x80, 0x27, 0x3e, 0x29, 0x45, 0x84, 0x44, 0x30, 0x00, 0x59, +0xa8, 0x33, 0x49, 0xfc, 0x1c, 0xf3, 0xd5, 0x05, 0x80, 0x07, 0x49, 0xfc, 0x12, 0x39, 0x92, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x84, 0x20, +0x80, 0xc0, 0x3e, 0x29, 0x45, 0xbc, 0x40, 0x00, 0x80, 0x06, 0x44, 0x30, 0x00, 0x8b, 0x49, 0xfc, +0x1c, 0xdd, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfc, 0x0a, 0x33, 0xa0, 0x32, 0xc8, 0x02, 0xd5, 0x06, +0x9e, 0x01, 0xa8, 0x32, 0x80, 0x06, 0x49, 0x00, 0x00, 0x71, 0x80, 0xc0, 0xf0, 0x01, 0x49, 0xfc, +0x0a, 0x3d, 0x80, 0x06, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xf4, 0x84, 0x40, 0x80, 0xc0, 0x44, 0x30, 0x00, 0x6e, 0x40, 0x01, 0x00, 0x06, 0x80, 0xe1, +0x80, 0x22, 0x3e, 0x29, 0x45, 0xbc, 0x49, 0xfc, 0x1c, 0xb9, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfc, +0x0a, 0x0f, 0xa0, 0x72, 0x80, 0x06, 0x9c, 0x49, 0xa8, 0x72, 0x80, 0x27, 0x49, 0x00, 0x00, 0x92, +0xf0, 0x01, 0x49, 0xfc, 0x0a, 0x1b, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x09, 0xd3, 0x00, 0x49, 0x00, 0x00, 0xa6, 0x3e, 0x79, 0x8e, 0x14, +0x3e, 0x69, 0xcb, 0x04, 0xa9, 0xf2, 0x80, 0x26, 0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, 0xff, 0xd0, +0x50, 0x73, 0x86, 0x40, 0x3e, 0x59, 0xb3, 0x94, 0x8c, 0xd8, 0xdf, 0xf5, 0x3e, 0x09, 0xd3, 0x10, +0x49, 0x00, 0x00, 0x92, 0x3e, 0x79, 0xb3, 0x94, 0x3e, 0x69, 0xcb, 0x94, 0xa9, 0xf2, 0x80, 0x26, +0x3e, 0x09, 0xd3, 0x10, 0x49, 0xff, 0xff, 0xbc, 0x50, 0x73, 0x80, 0xc8, 0x3e, 0x59, 0xcb, 0x04, +0x8c, 0xd8, 0xdf, 0xf5, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x84, 0x20, 0x80, 0xc0, 0x3e, 0x29, 0x45, 0xd4, 0x40, 0x00, 0x80, 0x06, 0x44, 0x30, 0x00, 0x7f, +0x49, 0xfc, 0x1c, 0x6c, 0x92, 0x00, 0xa0, 0x31, 0xb4, 0x26, 0xb6, 0x20, 0xb4, 0x06, 0xa1, 0xb1, +0xa9, 0x81, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x84, 0xe0, 0x81, 0x00, +0x80, 0x27, 0x40, 0x03, 0x80, 0x06, 0x3e, 0x29, 0x45, 0xd4, 0x44, 0x30, 0x00, 0x91, 0x49, 0xfc, +0x1c, 0x55, 0xb4, 0xc8, 0x4c, 0x64, 0x40, 0x04, 0x80, 0xc7, 0xd5, 0x04, 0x80, 0x06, 0x49, 0xff, +0xff, 0xd7, 0x80, 0x06, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0x84, 0xc0, 0x80, 0xe0, 0x81, 0x21, 0x81, 0x02, 0x40, 0x03, 0x00, 0x06, 0x80, 0x26, 0x3e, 0x29, +0x45, 0xd4, 0x44, 0x30, 0x00, 0x49, 0x49, 0xfc, 0x1c, 0x39, 0x40, 0x03, 0x24, 0x06, 0x80, 0x26, +0x3e, 0x29, 0x45, 0xd4, 0x44, 0x30, 0x00, 0x4a, 0x49, 0xfc, 0x1c, 0x30, 0x40, 0x03, 0x20, 0x06, +0x80, 0x26, 0x3e, 0x29, 0x45, 0xd4, 0x44, 0x30, 0x00, 0x4b, 0x49, 0xfc, 0x1c, 0x27, 0x14, 0x93, +0x80, 0x01, 0xb7, 0x07, 0xb6, 0xe9, 0x14, 0x74, 0x00, 0x01, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x84, 0xc0, 0x80, 0xe0, 0x81, 0x01, 0x40, 0x03, 0x00, 0x06, +0x80, 0x26, 0x3e, 0x29, 0x45, 0xd4, 0x44, 0x30, 0x00, 0x6f, 0x49, 0xfc, 0x1c, 0x0f, 0x40, 0x03, +0x20, 0x06, 0x80, 0x26, 0x44, 0x30, 0x00, 0x70, 0x3e, 0x29, 0x45, 0xd4, 0x49, 0xfc, 0x1c, 0x06, +0xa0, 0x79, 0x80, 0x08, 0x80, 0x47, 0x49, 0xff, 0xff, 0xbb, 0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x20, 0x80, 0xc0, 0x3e, 0x29, 0x45, 0xd4, +0x40, 0x00, 0x80, 0x06, 0x44, 0x30, 0x00, 0x29, 0x49, 0xfc, 0x1b, 0xf0, 0x92, 0x00, 0xa9, 0xb1, +0xb6, 0xc6, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x00, 0x80, 0x58, 0x21, 0x00, 0x50, +0x46, 0x50, 0x04, 0x00, 0x98, 0xc2, 0x58, 0x52, 0x82, 0x7c, 0x94, 0x03, 0x84, 0x40, 0x94, 0xdb, +0x99, 0x05, 0xb6, 0x44, 0xb6, 0x43, 0x50, 0x22, 0xff, 0xf4, 0x44, 0x30, 0x00, 0xff, 0xb4, 0x82, +0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, 0xb6, 0x62, 0x96, 0x48, +0x84, 0x61, 0x4c, 0x11, 0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, +0x94, 0xdf, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x30, 0x00, 0x80, 0x58, 0x31, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, 0x98, 0x83, 0x58, 0x42, +0x02, 0x7c, 0x94, 0x03, 0x98, 0xc4, 0x44, 0x41, 0x00, 0x00, 0xb6, 0x83, 0x94, 0x93, 0x84, 0x60, +0xb6, 0x62, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x44, 0x30, 0x00, 0xff, 0xb4, 0x82, +0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, 0xb6, 0x62, 0x96, 0x48, +0x84, 0xa1, 0xd9, 0x05, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xef, +0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x46, 0x40, 0x04, 0x00, +0x46, 0x20, 0x30, 0x70, 0x80, 0x64, 0x58, 0x21, 0x03, 0x07, 0x14, 0x22, 0x00, 0x9d, 0x14, 0x21, +0x80, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x94, 0x03, 0x44, 0x30, 0x00, 0xff, +0xb4, 0x82, 0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, 0xb6, 0x62, +0x96, 0x48, 0x84, 0xa1, 0xd9, 0x05, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x86, 0xd5, 0x04, 0xb4, 0x22, +0x44, 0x30, 0x00, 0x84, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, +0x40, 0x31, 0xe0, 0x08, 0x40, 0x41, 0x90, 0x04, 0x40, 0x21, 0x40, 0x08, 0x46, 0x50, 0x00, 0x80, +0x40, 0x22, 0x08, 0x04, 0x58, 0x52, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, 0x98, 0xc5, 0x58, 0x42, +0x02, 0x7c, 0x94, 0x03, 0x99, 0x44, 0xb6, 0x45, 0x94, 0xdb, 0x84, 0x40, 0xb6, 0x43, 0x50, 0x22, +0x7f, 0xf4, 0x44, 0x30, 0x00, 0xff, 0xb4, 0x82, 0x40, 0x31, 0x80, 0x0c, 0x40, 0x31, 0x8c, 0x05, +0x40, 0x31, 0x90, 0x02, 0x96, 0x48, 0x84, 0xa1, 0xb6, 0x62, 0xd9, 0x05, 0xb4, 0x22, 0x44, 0x30, +0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xef, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x04, 0x04, +0xb6, 0x02, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x19, 0x96, 0x48, +0x80, 0x62, 0x84, 0x81, 0x49, 0xff, 0xff, 0xc6, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x32, 0x96, 0x48, 0x44, 0x30, 0x00, 0x46, +0x84, 0x81, 0x49, 0xff, 0xff, 0xb7, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x32, 0x96, 0x48, 0x84, 0x6a, 0x84, 0x81, +0x49, 0xff, 0xff, 0xa8, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x84, 0xa2, 0x80, 0xc0, 0xd1, 0x18, 0x84, 0xa3, 0xd1, 0x1a, 0x84, 0xa1, 0xd9, 0x1b, 0x49, 0xff, +0xff, 0x15, 0x80, 0x46, 0x3e, 0x09, 0xce, 0x64, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x80, 0x7c, +0x84, 0x62, 0x49, 0xff, 0xfc, 0x89, 0x3e, 0x09, 0xce, 0x64, 0x44, 0x10, 0x0b, 0xb8, 0x49, 0xff, +0xfd, 0x63, 0xd5, 0x08, 0x84, 0x20, 0x49, 0xff, 0xff, 0x5b, 0xd5, 0x04, 0x84, 0x21, 0x49, 0xff, +0xfe, 0xfd, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x84, 0x48, +0x96, 0x49, 0x4c, 0x11, 0x40, 0x05, 0x84, 0x61, 0xf3, 0x82, 0xd5, 0x08, 0x95, 0x51, 0xd1, 0x04, +0x84, 0x01, 0x48, 0x00, 0x00, 0xba, 0x84, 0xa2, 0xf5, 0x82, 0x46, 0x11, 0x11, 0x10, 0x47, 0xc0, +0x10, 0x00, 0x58, 0x10, 0x81, 0x90, 0x59, 0xce, 0x00, 0x01, 0x85, 0x40, 0x46, 0x80, 0x04, 0x00, +0xf1, 0x81, 0x15, 0xcf, 0x80, 0x03, 0x58, 0x84, 0x02, 0x70, 0x83, 0x8a, 0x81, 0x40, 0x80, 0x6a, +0xa3, 0x99, 0x3e, 0x09, 0x45, 0xe8, 0xb4, 0xe3, 0x80, 0x26, 0x80, 0x47, 0x49, 0xfc, 0x1c, 0x5a, +0xe6, 0xc4, 0x4e, 0xf2, 0x00, 0x91, 0x96, 0x79, 0x84, 0xa5, 0xd1, 0x39, 0xe6, 0x26, 0xe8, 0x10, +0x84, 0xa2, 0xd1, 0x27, 0xe6, 0x23, 0xe8, 0x06, 0xc1, 0x19, 0x84, 0xa1, 0x4c, 0x12, 0xc0, 0x84, +0xd5, 0x1b, 0x84, 0xa3, 0xd1, 0x23, 0x84, 0xa4, 0x4c, 0x12, 0xc0, 0x7e, 0xd5, 0x23, 0x8c, 0xab, +0xd1, 0x39, 0xe6, 0x31, 0xe8, 0x06, 0x84, 0xa6, 0xd1, 0x2b, 0x84, 0xa7, 0xd9, 0x74, 0xd5, 0x2d, +0x9d, 0x69, 0xd1, 0x4e, 0x9d, 0x69, 0xd9, 0x6f, 0xd5, 0x5a, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, +0xfe, 0xd1, 0x48, 0x00, 0x00, 0x69, 0x80, 0x06, 0x49, 0xff, 0xfe, 0xa0, 0x48, 0x00, 0x00, 0x64, +0x80, 0x06, 0x84, 0x20, 0x49, 0xff, 0xfe, 0xf4, 0xd5, 0x5e, 0x84, 0x21, 0x44, 0x20, 0x00, 0x32, +0xd5, 0x09, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xff, 0x47, 0xd5, 0x55, 0x84, 0x21, 0x44, 0x20, +0x00, 0x11, 0x80, 0x06, 0x80, 0x62, 0x80, 0x81, 0x49, 0xff, 0xff, 0x0c, 0xd5, 0x4c, 0x80, 0x06, +0x84, 0x21, 0x49, 0xff, 0xff, 0x57, 0xd5, 0x47, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xff, 0x42, +0xd5, 0x42, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x80, 0x50, 0x46, 0x20, 0x04, 0x00, 0xf3, 0x01, +0x98, 0x31, 0x58, 0x21, 0x02, 0x7c, 0x95, 0xb3, 0x98, 0x72, 0xb6, 0x61, 0x94, 0x03, 0xf4, 0x03, +0xb6, 0x80, 0x44, 0x50, 0x00, 0x82, 0xb4, 0x08, 0x40, 0x62, 0x98, 0x0c, 0x92, 0x08, 0x40, 0x00, +0x20, 0x08, 0xb6, 0x08, 0xb4, 0x08, 0x40, 0x63, 0x00, 0x04, 0xb6, 0xc8, 0xd5, 0x24, 0x80, 0x06, +0x84, 0x21, 0x49, 0xff, 0xfe, 0x87, 0x80, 0x46, 0x3e, 0x09, 0xce, 0x64, 0x46, 0x10, 0x00, 0x81, +0x58, 0x10, 0x80, 0x7c, 0x84, 0x61, 0x49, 0xff, 0xfb, 0xcf, 0xd5, 0x0f, 0x80, 0x06, 0x84, 0x21, +0x49, 0xff, 0xfe, 0x78, 0x80, 0x46, 0x3e, 0x09, 0xce, 0x64, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, +0x80, 0x7c, 0x84, 0x63, 0x49, 0xff, 0xfb, 0xc0, 0x3e, 0x09, 0xce, 0x64, 0x44, 0x10, 0x13, 0x88, +0x49, 0xff, 0xfc, 0x9a, 0xf0, 0x02, 0x51, 0xce, 0x00, 0x01, 0x8d, 0x48, 0x40, 0xfe, 0x00, 0x06, +0x4e, 0xf3, 0xff, 0x5f, 0x84, 0x00, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3c, 0x1c, 0x45, 0x9e, 0x2e, 0x01, 0x20, 0xcc, 0x40, 0x00, 0x80, 0x04, 0x96, 0x00, 0xdd, 0x9e, +0x3c, 0x10, 0xee, 0xcc, 0x9c, 0x49, 0x54, 0x10, 0x8f, 0xff, 0x3c, 0x18, 0xee, 0xcc, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x3e, 0x89, 0xdc, 0x44, 0x44, 0x75, 0xb6, 0x98, 0x84, 0x20, +0x44, 0x20, 0x01, 0x44, 0x80, 0x08, 0xdd, 0x27, 0x84, 0x20, 0x44, 0x20, 0x01, 0x94, 0x50, 0x04, +0x7e, 0x6c, 0xdd, 0x27, 0x84, 0x20, 0x84, 0x46, 0x3e, 0x09, 0xde, 0x10, 0xdd, 0x27, 0x84, 0x40, +0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x09, 0xb4, 0x80, 0x62, 0x50, 0x04, 0x01, 0x58, 0x46, 0x10, +0x00, 0x81, 0x58, 0x10, 0x87, 0x0c, 0xdd, 0x26, 0x84, 0x40, 0x50, 0x04, 0x01, 0x74, 0x80, 0x62, +0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x8e, 0xf8, 0xdd, 0x26, 0x84, 0x40, 0x80, 0x62, 0x3e, 0x09, +0xd9, 0x60, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x85, 0x10, 0xdd, 0x26, 0x84, 0x40, 0x80, 0x62, +0x3e, 0x09, 0xd9, 0x7c, 0x46, 0x10, 0x00, 0x81, 0x58, 0x10, 0x84, 0xdc, 0xdd, 0x26, 0x44, 0x90, +0x00, 0x64, 0x3e, 0x39, 0xde, 0x18, 0x14, 0x91, 0x80, 0x03, 0x44, 0x90, 0x00, 0x1e, 0x84, 0x20, +0x3e, 0x59, 0xd9, 0xe8, 0x85, 0x01, 0x14, 0x91, 0x80, 0x02, 0x85, 0x25, 0x10, 0x81, 0x80, 0x14, +0x10, 0x12, 0x83, 0xa1, 0x10, 0x91, 0x80, 0x04, 0x10, 0x11, 0x80, 0x13, 0x14, 0x12, 0x81, 0x05, +0x12, 0x12, 0x81, 0xd8, 0x10, 0x12, 0x83, 0xa0, 0x10, 0x12, 0x83, 0xec, 0x10, 0x82, 0x83, 0xed, +0x10, 0x12, 0x83, 0xee, 0xae, 0x58, 0x10, 0x11, 0x80, 0x12, 0xae, 0x5d, 0x10, 0x11, 0x80, 0x11, +0x44, 0x20, 0x06, 0x40, 0x3e, 0x09, 0xd3, 0x20, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x00, 0x46, 0x11, +0x23, 0x40, 0x58, 0x10, 0x87, 0x25, 0x14, 0x10, 0x00, 0xa1, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x3e, 0x09, 0x46, 0x04, 0x3e, 0x19, 0x4a, 0x04, +0x49, 0xff, 0xfa, 0xe6, 0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x00, 0x04, 0xb4, 0x22, 0x3e, 0x09, +0x46, 0x10, 0x58, 0x10, 0x80, 0x0c, 0xb6, 0x22, 0x3e, 0x19, 0x4a, 0x04, 0xb4, 0x42, 0x49, 0xff, +0xfa, 0xd7, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xa0, 0xc4, 0x84, 0xa0, +0xa7, 0xdc, 0xa6, 0x1d, 0x40, 0x73, 0xa0, 0x08, 0xa6, 0x9e, 0x40, 0x73, 0x80, 0x04, 0x44, 0x00, +0x00, 0x28, 0xc2, 0x13, 0x44, 0x40, 0x00, 0x2b, 0x4c, 0x22, 0x00, 0x10, 0x44, 0x80, 0x00, 0x2c, +0x4c, 0x24, 0x00, 0x0c, 0x8c, 0x88, 0x4c, 0x22, 0x00, 0x09, 0x8d, 0x0f, 0x4c, 0x24, 0x40, 0x03, +0xd5, 0x22, 0x8c, 0x89, 0x4c, 0x22, 0x40, 0x22, 0xe2, 0xa7, 0xe8, 0x18, 0x44, 0x80, 0x00, 0x2c, +0x99, 0x98, 0x4c, 0x24, 0x40, 0x07, 0xa5, 0x31, 0x92, 0x83, 0xcc, 0x17, 0x84, 0x88, 0xd5, 0x0a, +0x8d, 0x07, 0xa7, 0x31, 0x4c, 0x24, 0x40, 0x05, 0x9d, 0x22, 0x95, 0x22, 0xd5, 0x03, 0x9d, 0x21, +0x95, 0x23, 0x99, 0x6c, 0xa6, 0xb0, 0x98, 0x04, 0xd5, 0xd5, 0x3e, 0x09, 0x46, 0x30, 0x49, 0xff, +0xfa, 0x97, 0x92, 0x00, 0x84, 0x1f, 0xd5, 0x02, 0xae, 0x88, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xc0, 0x81, 0x00, 0x81, 0x41, 0x81, 0x22, 0x84, 0x20, 0x44, 0x20, +0x00, 0x40, 0x80, 0x1f, 0x49, 0xfe, 0xd1, 0x2a, 0x50, 0x14, 0x00, 0x08, 0x44, 0x20, 0x00, 0x10, +0x80, 0x1f, 0x49, 0xfe, 0xd1, 0x03, 0x44, 0x20, 0x00, 0x10, 0x50, 0x14, 0x00, 0x18, 0x40, 0x0f, +0x88, 0x00, 0x49, 0xfe, 0xd0, 0xfb, 0x02, 0x34, 0x00, 0x02, 0x80, 0x2a, 0x40, 0x21, 0xa0, 0x09, +0x40, 0x01, 0xa0, 0x08, 0x40, 0x00, 0x08, 0x04, 0x96, 0x01, 0x44, 0x20, 0xff, 0x00, 0x40, 0x30, +0x08, 0x02, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x00, 0x60, 0x08, 0x40, 0x31, 0x80, 0x04, 0xf3, 0x88, +0x80, 0x49, 0x44, 0x30, 0x00, 0x3a, 0x50, 0x0f, 0x80, 0x28, 0x10, 0x3f, 0x80, 0x27, 0x80, 0xdf, +0x49, 0xfe, 0xd0, 0xdc, 0x50, 0x3f, 0x80, 0x40, 0x84, 0x20, 0x0a, 0x03, 0x00, 0x01, 0x40, 0x20, +0x20, 0x09, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, 0x04, 0x96, 0x01, 0x98, 0x48, 0x4c, 0x61, +0xff, 0xf6, 0xd5, 0x02, 0x98, 0x50, 0x40, 0x00, 0xc0, 0x09, 0x96, 0x89, 0xc8, 0xfc, 0x40, 0x00, +0x84, 0x05, 0x96, 0x01, 0xec, 0x40, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xfb, 0xf5, 0xb1, 0x84, 0x00, 0x49, 0x00, 0x2e, 0x6c, 0x49, 0xfb, 0xf5, 0xb4, +0x46, 0x10, 0x04, 0x00, 0x46, 0x00, 0x04, 0x11, 0x04, 0x10, 0x80, 0x25, 0x04, 0x20, 0x00, 0x49, +0x3e, 0x09, 0x46, 0x50, 0x49, 0xff, 0xfa, 0x24, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x3c, 0x0c, 0x62, 0x78, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x29, 0x49, 0xfc, +0x0c, 0xc3, 0x3c, 0x0e, 0x62, 0xa5, 0x84, 0x00, 0x49, 0x00, 0x2e, 0x4c, 0x49, 0xfc, 0x0c, 0xbc, +0x3c, 0x0e, 0x62, 0xa4, 0x3e, 0x09, 0x46, 0x74, 0x49, 0xff, 0xfa, 0x0a, 0x3e, 0x09, 0x8a, 0x98, +0xb4, 0x20, 0x9c, 0x49, 0xb6, 0x20, 0x5e, 0xf0, 0x80, 0x33, 0xe9, 0x03, 0x84, 0x20, 0xb6, 0x20, +0x3c, 0x3c, 0x62, 0xa5, 0x3c, 0x3e, 0x62, 0xa3, 0x84, 0x60, 0x3c, 0x3e, 0x62, 0x78, 0x3e, 0x09, +0xd9, 0x60, 0x44, 0x10, 0x00, 0x14, 0x49, 0xff, 0xfb, 0x07, 0xd5, 0x14, 0x46, 0x00, 0x04, 0x11, +0x04, 0x10, 0x00, 0x49, 0x44, 0x00, 0x03, 0xe8, 0x94, 0x4e, 0x40, 0x10, 0x80, 0x17, 0x3e, 0x09, +0xd9, 0x60, 0x49, 0xff, 0xfa, 0xf9, 0x84, 0x00, 0x49, 0x00, 0x2d, 0x86, 0x84, 0x01, 0x3c, 0x0e, +0x62, 0x78, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x81, 0x00, 0x49, 0x00, +0x30, 0x1d, 0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, 0xfb, 0x89, 0x80, 0xe0, 0xc8, 0x08, 0x3e, 0x09, +0x46, 0x84, 0x3e, 0x19, 0x4a, 0x14, 0x49, 0xff, 0xf9, 0xcb, 0xd5, 0x54, 0xa1, 0x82, 0x49, 0xff, +0xfe, 0x59, 0x3e, 0x39, 0xdc, 0x29, 0x80, 0x83, 0x80, 0x06, 0x84, 0x24, 0x84, 0x41, 0x49, 0x00, +0x13, 0xd1, 0x84, 0x80, 0xaf, 0x32, 0xaf, 0x33, 0x3e, 0x19, 0xd9, 0xe8, 0x00, 0x20, 0x83, 0xb0, +0x00, 0x03, 0x00, 0x16, 0x54, 0x21, 0x00, 0x0f, 0x94, 0x94, 0x54, 0x00, 0x00, 0x0f, 0x40, 0x00, +0x08, 0x04, 0x10, 0x03, 0x00, 0x16, 0xa6, 0xb0, 0xa6, 0x31, 0x54, 0x54, 0x00, 0x01, 0x85, 0x13, +0x02, 0x30, 0x81, 0xd8, 0x40, 0x21, 0x20, 0x02, 0x95, 0x6c, 0x42, 0x00, 0x10, 0x09, 0x40, 0x00, +0x14, 0x04, 0x92, 0x64, 0x58, 0x21, 0x00, 0x08, 0x10, 0x33, 0x00, 0x17, 0xae, 0x31, 0xae, 0xb0, +0x00, 0x00, 0x83, 0xed, 0xc8, 0x04, 0x44, 0x20, 0x00, 0x18, 0xd5, 0x0e, 0x54, 0x21, 0x00, 0x0f, +0x44, 0x0f, 0xff, 0xc0, 0x80, 0x26, 0x40, 0x21, 0x00, 0x04, 0x18, 0x20, 0x80, 0x18, 0x44, 0x20, +0x00, 0x1a, 0xaf, 0x09, 0xaf, 0x08, 0x80, 0x26, 0x80, 0x67, 0x84, 0x00, 0x49, 0x00, 0x15, 0xec, +0x3c, 0x20, 0xee, 0xcc, 0x3e, 0x19, 0x4a, 0x14, 0x3e, 0x09, 0x46, 0xa0, 0x49, 0xff, 0xf9, 0x78, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x2e, 0x11, +0xde, 0x04, 0xc1, 0x49, 0x2e, 0x01, 0xdc, 0x44, 0xc0, 0x46, 0x49, 0x00, 0x12, 0xb7, 0x80, 0xc0, +0x3c, 0x0c, 0x62, 0xa7, 0xe2, 0xc0, 0xe8, 0x07, 0x3c, 0x1c, 0x62, 0xa8, 0x3e, 0x09, 0x46, 0xbc, +0x49, 0xff, 0xf9, 0x5e, 0x2e, 0x51, 0x8a, 0x56, 0x3c, 0x6e, 0x62, 0xa7, 0x84, 0x21, 0xd1, 0x33, +0x3e, 0x79, 0xde, 0x18, 0xa6, 0x38, 0x4c, 0x00, 0xc0, 0x16, 0xa6, 0x3d, 0xc8, 0x2c, 0x3c, 0x1c, +0x62, 0xa8, 0x50, 0x03, 0x00, 0xc8, 0xe2, 0x01, 0xe9, 0x26, 0x3e, 0x09, 0x46, 0xe4, 0x49, 0xff, +0xf9, 0x47, 0x3c, 0x0c, 0x77, 0x7f, 0x42, 0x00, 0x70, 0x0b, 0xc8, 0x19, 0x00, 0x03, 0x80, 0x12, +0xd5, 0x13, 0xc8, 0x19, 0x3c, 0x0c, 0x62, 0xa8, 0x50, 0x13, 0x00, 0xc8, 0xe2, 0x20, 0xe9, 0x13, +0x3e, 0x09, 0x47, 0x10, 0x49, 0xff, 0xf9, 0x34, 0x3c, 0x0c, 0x77, 0x7f, 0x46, 0x11, 0x00, 0x00, +0x40, 0x00, 0x04, 0x02, 0xc8, 0x04, 0x49, 0xff, 0xff, 0x51, 0x92, 0x00, 0x50, 0x63, 0x27, 0x10, +0x3c, 0x6e, 0x62, 0xa8, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xff, 0xff, 0xab, 0x3e, 0x09, 0xdd, 0x9c, 0x44, 0x10, 0x01, 0xf4, 0x49, 0xff, +0xfa, 0x2b, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0x3e, 0x09, 0x47, 0x28, 0x49, 0xff, 0xf9, 0x0c, 0x49, 0x00, 0x2f, 0x50, 0x3e, 0x09, 0xd3, 0x00, +0x49, 0xff, 0xfa, 0xbc, 0x80, 0xe0, 0xc8, 0x08, 0x3e, 0x09, 0x46, 0x84, 0x3e, 0x19, 0x4a, 0x24, +0x49, 0xff, 0xf8, 0xfe, 0xd5, 0x35, 0xa1, 0x82, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x80, 0x06, +0x49, 0xfe, 0xcf, 0x9c, 0xa6, 0x70, 0xa6, 0x31, 0x44, 0x2f, 0xff, 0xa4, 0x54, 0x10, 0x80, 0x03, +0x40, 0x10, 0x88, 0x04, 0x58, 0x00, 0x00, 0x10, 0xae, 0x70, 0xae, 0x31, 0x3e, 0x19, 0xd9, 0xe8, +0x02, 0x00, 0x81, 0x26, 0x44, 0x2f, 0xc0, 0x00, 0x40, 0x00, 0x08, 0x04, 0x96, 0x01, 0x40, 0x20, +0x20, 0x09, 0xae, 0xb3, 0xae, 0x32, 0x50, 0x10, 0x82, 0x41, 0x84, 0x46, 0x9c, 0x34, 0x49, 0xfe, +0xcf, 0x5d, 0x3e, 0x19, 0xde, 0x10, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x49, 0xfe, 0xcf, 0x56, +0x80, 0x26, 0x80, 0x67, 0x84, 0x00, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x14, 0xff, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xfd, 0x4b, 0xc0, 0x0a, +0x84, 0x01, 0x84, 0x20, 0x49, 0xfe, 0xb6, 0x14, 0x3c, 0x2d, 0xfb, 0xef, 0x84, 0x22, 0x84, 0x01, +0xdd, 0x22, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xbc, 0x83, 0x80, 0x81, 0x41, 0xb6, 0x5f, 0xf3, 0x81, 0x49, 0x00, 0x2e, 0xef, 0x3e, 0x09, +0xd3, 0x00, 0x49, 0xff, 0xfa, 0x5b, 0x81, 0x20, 0xc8, 0x07, 0x3e, 0x09, 0x47, 0x3c, 0x49, 0xff, +0xf8, 0x9f, 0x48, 0x00, 0x00, 0x87, 0x04, 0x80, 0x00, 0x02, 0x50, 0x6f, 0x80, 0x08, 0x84, 0x20, +0x44, 0x20, 0x05, 0xdc, 0x80, 0x08, 0x49, 0xfe, 0xcf, 0x39, 0x84, 0x20, 0x44, 0x20, 0x00, 0x28, +0x80, 0x06, 0x49, 0xfe, 0xcf, 0x33, 0xa6, 0x33, 0xb4, 0x3f, 0x54, 0x00, 0x00, 0x0f, 0x58, 0x00, +0x00, 0x60, 0xae, 0x33, 0x44, 0x3f, 0xf0, 0x0f, 0xa4, 0x31, 0x46, 0x40, 0x0f, 0x00, 0x40, 0x00, +0x0c, 0x02, 0xac, 0x31, 0xb4, 0x66, 0x44, 0x20, 0x00, 0x10, 0x40, 0x01, 0x90, 0x02, 0x92, 0x08, +0x92, 0x78, 0x40, 0x31, 0x80, 0x04, 0xb6, 0x66, 0x44, 0x30, 0x18, 0x00, 0xac, 0xf2, 0x44, 0x30, +0x00, 0x3a, 0xae, 0xf6, 0x84, 0x7f, 0xae, 0xf7, 0x44, 0x75, 0xb6, 0x58, 0x40, 0x0f, 0x88, 0x00, +0xdd, 0x27, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x50, 0xa4, 0x00, 0x0e, 0x50, 0x0f, 0x80, 0x20, +0xdd, 0x27, 0x80, 0x26, 0x80, 0x0a, 0x44, 0x20, 0x00, 0x28, 0xdd, 0x27, 0x50, 0x64, 0x00, 0x36, +0x44, 0x0f, 0xff, 0x88, 0x84, 0x40, 0xae, 0x30, 0x44, 0x00, 0x00, 0x40, 0xae, 0x34, 0xae, 0xb7, +0xae, 0xb1, 0xac, 0xb1, 0xae, 0xb5, 0xae, 0xb6, 0x50, 0x04, 0x00, 0x3e, 0xf1, 0x01, 0x8c, 0x50, +0xdd, 0x27, 0x80, 0x26, 0x80, 0x0a, 0x44, 0x20, 0x00, 0x18, 0x49, 0xff, 0xfd, 0xb3, 0x40, 0x10, +0x20, 0x09, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x04, 0x04, 0xac, 0x31, 0x50, 0xaf, 0x80, 0x30, +0xba, 0x02, 0x50, 0x11, 0x00, 0x10, 0x80, 0x0a, 0x84, 0x46, 0x49, 0xfe, 0xce, 0xc1, 0x3e, 0x19, +0xde, 0x10, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x36, 0x49, 0xfe, 0xce, 0xba, 0x84, 0x42, 0x3e, 0x19, +0x87, 0x74, 0x50, 0x0f, 0x80, 0x3c, 0x49, 0xfe, 0xce, 0xb3, 0x80, 0x2a, 0x84, 0x4e, 0x80, 0x08, +0xdd, 0x27, 0x80, 0x09, 0x44, 0x10, 0x00, 0x4e, 0x84, 0x41, 0x49, 0x00, 0x14, 0xf3, 0x92, 0x00, +0xec, 0x44, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x81, 0x00, +0x49, 0x00, 0x2e, 0x54, 0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, 0xf9, 0xc0, 0x81, 0x20, 0xc8, 0x06, +0x3e, 0x09, 0x47, 0x3c, 0x49, 0xff, 0xf8, 0x04, 0xd5, 0x5a, 0xa1, 0x82, 0x84, 0x20, 0x44, 0x20, +0x00, 0x40, 0x80, 0x06, 0x49, 0xfe, 0xce, 0xa2, 0x50, 0x13, 0x00, 0x0e, 0x84, 0x48, 0xae, 0x8a, +0x84, 0x46, 0x84, 0x00, 0xae, 0x8c, 0x85, 0x41, 0x87, 0x82, 0x84, 0x44, 0xae, 0x8d, 0xae, 0x0e, +0xae, 0x08, 0xae, 0x0b, 0x11, 0xc0, 0x80, 0x07, 0x10, 0xa0, 0x80, 0x01, 0x44, 0x75, 0xb6, 0x58, +0x3e, 0x19, 0xde, 0x10, 0x84, 0x46, 0x50, 0x03, 0x00, 0x16, 0xdd, 0x27, 0x04, 0x14, 0x00, 0x04, +0x84, 0x44, 0x8c, 0x38, 0x50, 0x03, 0x00, 0x1c, 0xdd, 0x27, 0x04, 0x14, 0x00, 0x04, 0x50, 0x33, +0x00, 0x20, 0x80, 0x03, 0x8c, 0x28, 0x84, 0x46, 0xf3, 0x81, 0xdd, 0x27, 0x04, 0x14, 0x00, 0x04, +0x84, 0x44, 0x8c, 0x2e, 0x50, 0x03, 0x00, 0x26, 0xdd, 0x27, 0xf3, 0x01, 0x80, 0x23, 0x84, 0x46, +0x50, 0x0f, 0x80, 0x08, 0x49, 0xfe, 0xce, 0x54, 0x3e, 0x19, 0xde, 0x10, 0x84, 0x46, 0x50, 0x0f, +0x80, 0x0e, 0x49, 0xfe, 0xce, 0x4d, 0x80, 0x5c, 0x3e, 0x19, 0x87, 0x68, 0x50, 0x0f, 0x80, 0x14, +0x49, 0xfe, 0xce, 0x46, 0x50, 0x1f, 0x80, 0x08, 0x84, 0x4e, 0x80, 0x06, 0xdd, 0x27, 0x80, 0x09, +0x80, 0x4a, 0x44, 0x10, 0x00, 0x2a, 0x49, 0x00, 0x14, 0x85, 0x92, 0x00, 0xec, 0x1c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0xa0, 0xc4, 0x81, 0x00, 0x96, 0x08, +0x84, 0x21, 0x8c, 0x78, 0x4c, 0x00, 0x80, 0x04, 0x80, 0x01, 0xd5, 0x23, 0x3e, 0x79, 0xdd, 0x50, +0x84, 0xc0, 0x45, 0xc0, 0x00, 0x12, 0xa6, 0x38, 0xc8, 0x17, 0x00, 0x93, 0x80, 0x01, 0x84, 0xa1, +0x4c, 0x92, 0xc0, 0x13, 0x42, 0x03, 0x70, 0x24, 0x3e, 0x29, 0xdd, 0x52, 0x80, 0x23, 0x98, 0x02, +0x84, 0x44, 0xf3, 0x81, 0x49, 0x00, 0x10, 0xb6, 0xf3, 0x01, 0xc8, 0x06, 0x80, 0x08, 0x49, 0xff, +0xff, 0x6d, 0x80, 0x09, 0xd5, 0x06, 0x9d, 0xb1, 0x84, 0xa3, 0x8c, 0xf2, 0xde, 0xe5, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x84, 0x00, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x47, +0x9c, 0x49, 0x4c, 0x11, 0x7f, 0xfd, 0x9c, 0x01, 0x84, 0x23, 0x4c, 0x00, 0x80, 0x04, 0x84, 0x20, +0xd5, 0xf6, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x3e, 0x09, 0x46, 0x04, 0x3e, 0x19, 0x49, 0xf0, +0x49, 0xff, 0xf7, 0x5e, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x41, 0x42, 0x10, 0x8c, 0x09, 0xa8, 0x41, +0x46, 0x20, 0x04, 0x10, 0x80, 0x22, 0x84, 0x00, 0x04, 0x31, 0x01, 0x0e, 0x04, 0x40, 0x82, 0x8c, +0x9c, 0x01, 0x97, 0x20, 0xcc, 0x02, 0xc3, 0x07, 0x44, 0x30, 0x01, 0x06, 0x4c, 0x01, 0xff, 0xf6, +0x48, 0x00, 0x00, 0x6d, 0x46, 0x70, 0x04, 0x11, 0x84, 0xc0, 0x04, 0x83, 0x80, 0x80, 0x54, 0x04, +0x00, 0x01, 0xc0, 0x0a, 0x49, 0xff, 0xff, 0xca, 0x84, 0xbf, 0x9d, 0xb1, 0x4c, 0x82, 0x80, 0x99, +0x44, 0x50, 0x01, 0x06, 0xde, 0xf3, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x41, 0x42, 0x10, 0x88, 0x09, +0xa8, 0x41, 0x5c, 0xf3, 0x01, 0x06, 0xe9, 0x05, 0x3e, 0x09, 0x47, 0x58, 0x49, 0xff, 0xf7, 0x28, +0x46, 0x70, 0x04, 0x10, 0x84, 0xc0, 0x46, 0x00, 0x04, 0x10, 0x04, 0x13, 0x81, 0x0c, 0x04, 0x00, +0x01, 0x0e, 0x40, 0x00, 0x20, 0x08, 0x92, 0x18, 0xc0, 0x03, 0x84, 0x20, 0xd5, 0x04, 0x92, 0x30, +0x5c, 0x10, 0x80, 0x01, 0x46, 0x00, 0x04, 0x10, 0x04, 0x00, 0x02, 0x8d, 0x40, 0x00, 0x20, 0x08, +0x92, 0x18, 0xc8, 0x02, 0xc9, 0x1d, 0x49, 0x00, 0x2d, 0x6f, 0xd5, 0x10, 0x49, 0xff, 0xf8, 0xbe, +0x00, 0x30, 0x00, 0x14, 0x80, 0x40, 0x80, 0x20, 0x3e, 0x09, 0xd3, 0x00, 0xc3, 0x02, 0xd5, 0x04, +0x80, 0x22, 0x3e, 0x09, 0xd3, 0x10, 0x49, 0xff, 0xf8, 0xd3, 0x3c, 0x3c, 0x76, 0xaa, 0x3e, 0x09, +0xda, 0xa0, 0xcb, 0xed, 0x9d, 0xb1, 0x44, 0x50, 0x01, 0x06, 0xde, 0xce, 0xd5, 0x31, 0x46, 0x70, +0x04, 0x11, 0x84, 0xc0, 0x04, 0x83, 0x80, 0x80, 0x9d, 0xb1, 0x54, 0x04, 0x00, 0x02, 0xc0, 0x07, +0x49, 0xff, 0xff, 0x74, 0x44, 0x50, 0x01, 0x06, 0xde, 0xf6, 0xd5, 0x3b, 0x3e, 0x09, 0x47, 0x78, +0x3e, 0x19, 0x49, 0xf0, 0x49, 0xff, 0xf6, 0xdc, 0xd5, 0x3b, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x02, 0x8c, 0x3e, 0x09, 0x47, 0x84, 0x49, 0xff, 0xf6, 0xd3, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x02, 0x8d, 0x3e, 0x09, 0x47, 0x98, 0x49, 0xff, 0xf6, 0xcb, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, +0x01, 0x0e, 0x3e, 0x09, 0x47, 0xac, 0x49, 0xff, 0xf6, 0xc3, 0x48, 0xff, 0xff, 0x7d, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x8c, 0x3e, 0x09, 0x47, 0x84, 0x49, 0xff, 0xf6, 0xb9, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x02, 0x8d, 0x3e, 0x09, 0x47, 0x98, 0x49, 0xff, 0xf6, 0xb1, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x01, 0x0e, 0x3e, 0x09, 0x47, 0xbc, 0x49, 0xff, 0xf6, 0xa9, 0xd5, 0xb8, +0x80, 0x28, 0x3e, 0x09, 0x47, 0xd0, 0x49, 0xff, 0xf6, 0xa3, 0x92, 0x00, 0xd5, 0xc0, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x85, 0x21, 0x2e, 0x31, 0xde, 0x2b, +0x3e, 0x91, 0x8a, 0x57, 0x84, 0x80, 0x10, 0x4f, 0x80, 0x07, 0x81, 0x00, 0x81, 0x41, 0x80, 0xc2, +0xc3, 0x07, 0x3e, 0x09, 0x47, 0xf0, 0x49, 0xff, 0xf6, 0x8b, 0x48, 0x00, 0x01, 0x5b, 0x3e, 0x79, +0xd9, 0xe8, 0x00, 0x03, 0x83, 0xec, 0xc8, 0x09, 0x49, 0xff, 0xff, 0x1e, 0x50, 0x03, 0x83, 0xb4, +0x49, 0xff, 0xf6, 0xcc, 0x10, 0x93, 0x83, 0xa0, 0x3c, 0xae, 0x77, 0x80, 0x3c, 0x8e, 0x77, 0x7f, +0x3e, 0x09, 0xd3, 0x20, 0x84, 0x20, 0x44, 0x20, 0x06, 0x40, 0x49, 0xfe, 0xcd, 0x17, 0xc6, 0x38, +0xa0, 0x71, 0xa6, 0x8b, 0xa6, 0x4a, 0x54, 0x21, 0x00, 0x3f, 0x40, 0x21, 0x20, 0x08, 0x40, 0x21, +0x04, 0x04, 0x3c, 0x2e, 0x62, 0x79, 0xb4, 0x06, 0xa6, 0x01, 0x54, 0x10, 0x00, 0x40, 0xc1, 0x22, +0xa0, 0x72, 0x44, 0x20, 0x00, 0x1a, 0xa7, 0x08, 0x9e, 0xd2, 0x92, 0x84, 0x54, 0x42, 0x00, 0x08, +0x54, 0x00, 0x00, 0x10, 0x40, 0x71, 0x90, 0x1a, 0x40, 0x71, 0x10, 0x1b, 0xc0, 0x02, 0x9d, 0xfc, +0x80, 0x47, 0x3e, 0x09, 0xd3, 0x20, 0x49, 0xfe, 0xcc, 0xd1, 0xa0, 0x72, 0x3c, 0x2c, 0x62, 0x79, +0x3e, 0x39, 0xd3, 0x20, 0x9c, 0x3a, 0x98, 0x48, 0x9a, 0x97, 0x98, 0x3b, 0x49, 0xfe, 0xcc, 0xc6, +0xd5, 0x09, 0xa0, 0x72, 0x3e, 0x09, 0xd3, 0x20, 0x49, 0xfe, 0xcc, 0xc0, 0xd5, 0x03, 0x3c, 0x6e, +0x62, 0x79, 0x3c, 0x3d, 0xfb, 0xc6, 0x44, 0x00, 0x00, 0x19, 0x84, 0x20, 0x50, 0x2f, 0x80, 0x07, +0xdd, 0x23, 0x00, 0x1f, 0x80, 0x07, 0x3e, 0x09, 0x48, 0x14, 0x46, 0x70, 0x00, 0x80, 0x58, 0x73, +0x89, 0x4c, 0xdd, 0x27, 0x00, 0x0f, 0x80, 0x07, 0x4e, 0x03, 0x00, 0xed, 0x2e, 0x01, 0xdd, 0x89, +0xc8, 0x15, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x19, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, +0x80, 0x19, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x34, 0xb4, 0x20, 0x46, 0x31, 0x23, 0x40, +0x96, 0x49, 0xb6, 0x20, 0xb4, 0x20, 0x48, 0x00, 0x00, 0xd2, 0x84, 0xa1, 0xd8, 0x24, 0x3e, 0x09, +0x48, 0x30, 0xdd, 0x27, 0x3c, 0x2c, 0x62, 0x7d, 0x80, 0x28, 0xa6, 0xd0, 0x3e, 0x09, 0x48, 0x4c, +0xdd, 0x27, 0x46, 0x51, 0x00, 0x00, 0x4c, 0x82, 0x80, 0x09, 0x44, 0x50, 0x01, 0x00, 0x4c, 0x82, +0x80, 0x05, 0x95, 0x69, 0x4c, 0x82, 0xc0, 0x0c, 0x3c, 0x0c, 0x62, 0x7d, 0xc0, 0x08, 0xa6, 0x00, +0x84, 0xa2, 0xd8, 0x05, 0x49, 0x00, 0x2a, 0xd2, 0x48, 0x00, 0x00, 0xbc, 0x49, 0xff, 0xfd, 0x24, +0x48, 0x00, 0x00, 0xb8, 0x84, 0xa2, 0x4c, 0x02, 0xc0, 0x9d, 0x3c, 0x0c, 0x62, 0x7d, 0xc0, 0x48, +0xa6, 0x40, 0x84, 0xa1, 0xd9, 0x45, 0x00, 0x90, 0x00, 0x02, 0x4e, 0x92, 0x00, 0x42, 0xa6, 0x03, +0x84, 0xa5, 0xd8, 0x3e, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x02, 0x58, 0x3e, 0x09, 0x48, 0x8c, +0xdd, 0x27, 0xb4, 0x06, 0x44, 0x2f, 0xf3, 0xff, 0x40, 0x00, 0x08, 0x02, 0xb6, 0x06, 0x46, 0x80, +0x04, 0x00, 0x58, 0x84, 0x01, 0xbc, 0xb4, 0x08, 0x44, 0x3f, 0xff, 0xdf, 0x40, 0x00, 0x0c, 0x02, +0xb6, 0x08, 0x50, 0x74, 0x7f, 0xfc, 0xb4, 0x07, 0x44, 0x10, 0x00, 0x1e, 0x40, 0x00, 0x0c, 0x02, +0xb6, 0x07, 0x44, 0x00, 0x03, 0xe8, 0x3c, 0x20, 0xee, 0xc8, 0x42, 0x01, 0x00, 0x24, 0x40, 0x94, +0xa8, 0x08, 0x40, 0x00, 0x04, 0x37, 0x49, 0xfc, 0x08, 0x61, 0xb4, 0x28, 0x44, 0x00, 0x0c, 0x80, +0x58, 0x10, 0x80, 0x20, 0xb6, 0x28, 0xb4, 0x27, 0x58, 0x10, 0x80, 0x20, 0xb6, 0x27, 0x49, 0xfc, +0x08, 0x55, 0xb4, 0x06, 0x40, 0x94, 0x80, 0x04, 0xb7, 0x26, 0x48, 0x00, 0x00, 0x6b, 0x3e, 0x09, +0x48, 0xa0, 0x49, 0xff, 0xf5, 0x95, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x20, 0xb4, 0x40, +0x46, 0x3f, 0xf0, 0xff, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x40, 0x46, 0x10, +0x04, 0x00, 0xb4, 0x40, 0x42, 0x21, 0x50, 0x08, 0xb6, 0x40, 0x04, 0x00, 0x80, 0x6e, 0x46, 0x60, +0x04, 0x00, 0x42, 0x00, 0x14, 0x09, 0x14, 0x00, 0x80, 0x6e, 0x58, 0x63, 0x01, 0xbc, 0x3e, 0x79, +0xdd, 0x8c, 0x44, 0xa0, 0x03, 0xe8, 0x44, 0x90, 0x00, 0x1e, 0xb4, 0x07, 0x4e, 0x04, 0x00, 0x06, +0xb4, 0x26, 0x58, 0x10, 0x80, 0x20, 0xd5, 0x04, 0xb4, 0x26, 0x42, 0x10, 0x94, 0x09, 0x96, 0x01, +0x42, 0x00, 0x28, 0x24, 0xb6, 0x26, 0x40, 0x00, 0x24, 0x37, 0x9d, 0xfc, 0x49, 0xfc, 0x08, 0x16, +0x3e, 0x59, 0xdd, 0x98, 0xdf, 0xeb, 0x84, 0x02, 0x84, 0x21, 0x49, 0xff, 0xf8, 0x3b, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0xa3, 0x3e, 0x09, 0x48, 0xb0, 0x49, 0xff, 0xf5, 0x51, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0xa4, 0x3e, 0x09, 0x48, 0xc4, 0x49, 0xff, 0xf5, 0x49, 0xd5, 0x19, +0x84, 0xa3, 0xd8, 0x17, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0xb0, 0xb4, 0x20, 0x46, 0x30, +0x02, 0x00, 0x42, 0x10, 0xf4, 0x09, 0x58, 0x31, 0x80, 0x20, 0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, +0xd5, 0x08, 0x84, 0x20, 0x3c, 0x3d, 0xfb, 0xc6, 0x44, 0x00, 0x00, 0x1a, 0x80, 0x41, 0xdd, 0x23, +0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x2e, 0x11, 0xde, 0x2b, +0xc1, 0x0b, 0x2e, 0x01, 0xde, 0x2c, 0x5c, 0xf0, 0x00, 0x33, 0xe9, 0x06, 0x85, 0x0a, 0x40, 0x80, +0x20, 0x17, 0x89, 0x08, 0xd5, 0x02, 0x85, 0x0a, 0x3e, 0x69, 0xd9, 0xe8, 0x04, 0x03, 0x01, 0x04, +0x96, 0x04, 0xc0, 0x2f, 0x49, 0x00, 0x0e, 0x62, 0x04, 0x13, 0x00, 0x92, 0x3e, 0x79, 0x8a, 0x88, +0x50, 0x10, 0x83, 0xe8, 0xe2, 0x20, 0xe8, 0x1d, 0xb4, 0x07, 0x9c, 0x01, 0xb6, 0x07, 0xe0, 0x08, +0xe9, 0x20, 0x3e, 0x09, 0x48, 0xd8, 0x49, 0xff, 0xf5, 0x03, 0x04, 0x23, 0x01, 0x05, 0x04, 0x03, +0x00, 0x99, 0x42, 0x21, 0x70, 0x08, 0x84, 0x20, 0x54, 0x00, 0x00, 0x80, 0xb6, 0x27, 0x14, 0x23, +0x01, 0x05, 0xc0, 0x0f, 0x46, 0x01, 0x00, 0x00, 0x80, 0x41, 0x49, 0xff, 0xfe, 0x55, 0xd5, 0x09, +0x04, 0x03, 0x01, 0x05, 0x42, 0x00, 0x70, 0x09, 0x14, 0x03, 0x01, 0x05, 0x84, 0x00, 0xb6, 0x07, +0x3e, 0x09, 0xdd, 0xb8, 0x44, 0x10, 0x03, 0xe8, 0x49, 0xff, 0xf5, 0xf6, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x3e, 0x49, 0x49, 0xd8, 0x80, 0xc0, +0x3a, 0x02, 0x0c, 0x04, 0x50, 0x5f, 0x80, 0x04, 0x3a, 0x02, 0x8c, 0x24, 0x3a, 0x02, 0x04, 0x00, +0x3a, 0x02, 0x84, 0x20, 0xa0, 0x72, 0xa6, 0x08, 0x92, 0x04, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x05, +0x3e, 0x09, 0x48, 0xe8, 0x48, 0x00, 0x00, 0xc0, 0xb4, 0x06, 0xa6, 0x00, 0x54, 0x00, 0x00, 0x60, +0xc0, 0x09, 0x8c, 0x2a, 0x3e, 0x09, 0xdc, 0x29, 0x84, 0x46, 0x49, 0x00, 0x0d, 0xeb, 0xc0, 0x02, +0xd5, 0x13, 0xa0, 0x32, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x40, 0xc0, 0x11, 0xb4, 0x06, 0xa6, 0x02, +0x96, 0x04, 0xc8, 0x0d, 0xa0, 0x71, 0x3e, 0x09, 0x48, 0xf8, 0xa6, 0x49, 0x92, 0x22, 0x54, 0x10, +0x80, 0x07, 0x49, 0xff, 0xf4, 0xa5, 0x84, 0x1f, 0x48, 0x00, 0x02, 0xd2, 0xb4, 0x06, 0xa6, 0x00, +0x54, 0x10, 0x00, 0x40, 0xc1, 0x03, 0x85, 0x03, 0xd5, 0x0e, 0x54, 0x10, 0x00, 0x10, 0xc1, 0x03, +0x85, 0x01, 0xd5, 0x09, 0x54, 0x00, 0x00, 0x20, 0x96, 0x00, 0x84, 0x22, 0x40, 0x80, 0x00, 0x1a, +0x40, 0x80, 0x80, 0x1b, 0x02, 0x13, 0x00, 0x0a, 0x3e, 0x09, 0x49, 0x1c, 0x49, 0xff, 0xf4, 0x88, +0xa0, 0xb4, 0x02, 0x03, 0x00, 0x0a, 0x8c, 0x58, 0x8e, 0x18, 0x12, 0x03, 0x00, 0x0a, 0xa8, 0xb4, +0xa0, 0x32, 0xa6, 0x00, 0x92, 0x04, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x1a, 0x02, 0x13, 0x00, 0x0b, +0x58, 0x10, 0x80, 0x40, 0x96, 0x49, 0x12, 0x13, 0x00, 0x0b, 0xa6, 0x10, 0x96, 0x82, 0x4e, 0x24, +0x00, 0x06, 0x58, 0x10, 0x80, 0x02, 0x12, 0x13, 0x00, 0x0b, 0xa0, 0xb4, 0x02, 0x13, 0x00, 0x0a, +0x9c, 0x92, 0x9e, 0x4a, 0xa8, 0xb4, 0x12, 0x13, 0x00, 0x0a, 0x54, 0x00, 0x00, 0x0f, 0x10, 0x03, +0x00, 0x18, 0xa0, 0x32, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x80, 0xc0, 0x16, 0x02, 0x23, 0x00, 0x0b, +0xa0, 0x74, 0x02, 0x03, 0x00, 0x0a, 0x9c, 0x4c, 0x9e, 0x04, 0x58, 0x21, 0x00, 0x08, 0xa8, 0x74, +0x12, 0x03, 0x00, 0x0a, 0x12, 0x23, 0x00, 0x0b, 0xa0, 0x71, 0x3e, 0x09, 0x49, 0x29, 0xa6, 0x4f, +0x92, 0x25, 0x49, 0xff, 0xf4, 0x45, 0xb4, 0x06, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x40, 0xc0, 0x0a, +0x02, 0x13, 0x00, 0x0b, 0xa0, 0x34, 0x58, 0x10, 0x80, 0x10, 0x9c, 0x02, 0x12, 0x13, 0x00, 0x0b, +0xa8, 0x34, 0xa0, 0x34, 0x3e, 0x19, 0x87, 0x58, 0x84, 0x46, 0x49, 0x00, 0x0d, 0x63, 0xc0, 0x08, +0xa0, 0x34, 0x3e, 0x19, 0x87, 0x60, 0x84, 0x46, 0x49, 0x00, 0x0d, 0x5c, 0xc8, 0x22, 0xa0, 0x74, +0x02, 0x03, 0x00, 0x0a, 0x9c, 0x4e, 0x9e, 0x06, 0x12, 0x03, 0x00, 0x0a, 0xa8, 0x74, 0x46, 0x00, +0x04, 0x00, 0x04, 0x20, 0x00, 0xa4, 0x9c, 0x91, 0x14, 0x20, 0x00, 0xa4, 0x50, 0x0f, 0x80, 0x1c, +0x84, 0x42, 0x49, 0xfe, 0xca, 0x9b, 0xa0, 0x74, 0x02, 0x03, 0x00, 0x0a, 0x9c, 0x4a, 0x9e, 0x02, +0x12, 0x03, 0x00, 0x0a, 0xa8, 0x74, 0x3c, 0x0c, 0x77, 0x13, 0x96, 0x04, 0xc8, 0x08, 0xd5, 0x15, +0x3e, 0x09, 0x49, 0x40, 0x49, 0xff, 0xf4, 0x04, 0x48, 0xff, 0xff, 0x5f, 0x80, 0x06, 0x49, 0x00, +0x13, 0xf1, 0x80, 0xe0, 0x84, 0xa1, 0xdf, 0x09, 0x3e, 0x09, 0x49, 0x50, 0x49, 0xff, 0xf3, 0xf8, +0x80, 0x07, 0x80, 0x46, 0x48, 0x00, 0x01, 0x2c, 0x50, 0xaf, 0x80, 0x1c, 0x46, 0x70, 0x00, 0x83, +0x58, 0x73, 0x8b, 0xb0, 0x80, 0x0a, 0x3e, 0x19, 0x87, 0x68, 0x84, 0x42, 0xdd, 0x27, 0xc8, 0x0b, +0x2e, 0x01, 0xdc, 0x46, 0x4e, 0x02, 0x02, 0x13, 0x80, 0x06, 0x84, 0x21, 0x49, 0xff, 0xfc, 0x3c, +0x48, 0x00, 0x02, 0x0d, 0x3e, 0x19, 0x87, 0x70, 0x80, 0x0a, 0x84, 0x42, 0xdd, 0x27, 0x80, 0x20, +0x4e, 0x03, 0x01, 0x19, 0xa0, 0xf4, 0xa7, 0xd8, 0x54, 0x73, 0x80, 0x0f, 0x95, 0xfa, 0xe6, 0xf9, +0x4e, 0xf2, 0x01, 0xfd, 0x00, 0x41, 0x80, 0x09, 0x44, 0x00, 0x00, 0x11, 0x98, 0x9f, 0x4c, 0x40, +0x40, 0x0c, 0xa6, 0x12, 0xa6, 0x93, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, 0x04, 0x81, 0x21, +0x80, 0x41, 0x80, 0xa1, 0xd5, 0x16, 0x84, 0xa6, 0x4c, 0x42, 0xc1, 0xe9, 0x01, 0xc1, 0x00, 0x00, +0x00, 0x91, 0x00, 0x02, 0xa6, 0x13, 0x00, 0xa1, 0x00, 0x01, 0x41, 0xce, 0x20, 0x08, 0x40, 0x94, +0xa0, 0x08, 0x00, 0x51, 0x00, 0x0d, 0x40, 0x94, 0x80, 0x04, 0x40, 0x2e, 0x28, 0x04, 0x80, 0x01, +0x84, 0x21, 0x4c, 0x80, 0xc0, 0x6f, 0x84, 0x06, 0x4c, 0x40, 0x41, 0xd1, 0x3c, 0x1c, 0x77, 0x13, +0x54, 0x10, 0x80, 0x04, 0xc1, 0x33, 0x54, 0x52, 0x80, 0x02, 0xc5, 0x30, 0x3c, 0x00, 0xee, 0x2c, +0x4c, 0x20, 0x00, 0x03, 0xc8, 0x2b, 0x3c, 0x00, 0xee, 0x2d, 0x4c, 0x90, 0x00, 0x03, 0xc8, 0x26, +0x50, 0x11, 0x80, 0x0c, 0x3e, 0x09, 0xdc, 0x5c, 0x84, 0x44, 0x49, 0x00, 0x0c, 0xbb, 0xc0, 0x09, +0x3e, 0x09, 0xdc, 0x5c, 0x3e, 0x19, 0xce, 0x80, 0x84, 0x44, 0x49, 0x00, 0x0c, 0xb3, 0xc8, 0x16, +0xa0, 0x74, 0x8c, 0x30, 0x3e, 0x09, 0xdc, 0x6c, 0x84, 0x44, 0x49, 0x00, 0x0c, 0xab, 0xc0, 0x09, +0x3e, 0x09, 0xdc, 0x6c, 0x3e, 0x19, 0xce, 0x80, 0x84, 0x44, 0x49, 0x00, 0x0c, 0xa3, 0xc8, 0x06, +0x80, 0x46, 0x44, 0x00, 0x10, 0x00, 0x48, 0x00, 0x00, 0xa3, 0x3e, 0x79, 0xd9, 0xe8, 0x04, 0x03, +0x80, 0x99, 0x54, 0x00, 0x40, 0x00, 0x4e, 0x02, 0x01, 0x92, 0x02, 0x03, 0x81, 0x4a, 0xc8, 0x09, +0xa0, 0x74, 0x8c, 0x30, 0x50, 0x03, 0x82, 0x84, 0x84, 0x44, 0x49, 0x00, 0x0c, 0x8b, 0xc8, 0x09, +0x3e, 0x09, 0xd9, 0xe8, 0x50, 0x10, 0x02, 0x98, 0x02, 0x20, 0x01, 0x4b, 0x84, 0x00, 0xd5, 0x14, +0x50, 0x03, 0x82, 0x84, 0x3e, 0x19, 0xce, 0x80, 0x84, 0x44, 0x49, 0x00, 0x0c, 0x7b, 0xc0, 0xf1, +0x48, 0x00, 0x01, 0x75, 0x0a, 0x40, 0x80, 0x01, 0x96, 0x19, 0x4c, 0x92, 0x40, 0x06, 0x80, 0x46, +0x84, 0x04, 0x48, 0x00, 0x00, 0x75, 0x9c, 0xc1, 0xe2, 0x02, 0xe9, 0xf5, 0x48, 0x00, 0x01, 0x67, +0x84, 0x22, 0x4c, 0x80, 0xc1, 0x64, 0x3e, 0x19, 0xd9, 0xe8, 0x04, 0x20, 0x80, 0x99, 0x40, 0x21, +0x40, 0x08, 0x92, 0x5f, 0x4e, 0x22, 0x01, 0x5b, 0x50, 0x20, 0x82, 0xc2, 0x02, 0x40, 0x81, 0x60, +0x84, 0x20, 0xd5, 0x63, 0x0a, 0x81, 0x00, 0x01, 0x96, 0x69, 0x4c, 0x04, 0x40, 0x5f, 0x44, 0x10, +0x14, 0xe9, 0x4c, 0x00, 0xc0, 0x52, 0x2e, 0x01, 0xdc, 0x49, 0xc0, 0x4e, 0xa0, 0x71, 0xa6, 0x0b, +0xa6, 0x4a, 0x54, 0x00, 0x00, 0x3f, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x04, 0x04, 0x9a, 0x07, +0x5c, 0xf0, 0x00, 0x2d, 0xe9, 0x3c, 0x50, 0x03, 0x80, 0x14, 0x50, 0xaf, 0x80, 0x04, 0x98, 0x18, +0x80, 0x2a, 0x44, 0x20, 0x00, 0x18, 0x49, 0x00, 0x0c, 0x35, 0x81, 0x00, 0xc8, 0x0e, 0x3e, 0x09, +0x49, 0x68, 0x49, 0xff, 0xf2, 0xfd, 0x44, 0x00, 0x04, 0x00, 0x80, 0x46, 0x80, 0x28, 0x49, 0xff, +0xfc, 0x5b, 0x80, 0x08, 0x48, 0x00, 0x01, 0x24, 0xa0, 0x71, 0xa6, 0x0b, 0xa6, 0x4a, 0x54, 0x00, +0x00, 0x3f, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x04, 0x04, 0x9a, 0x07, 0x5c, 0xf0, 0x00, 0x3c, +0xe9, 0x16, 0xa0, 0x34, 0x50, 0x73, 0x80, 0x23, 0x98, 0x07, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x18, +0x49, 0x00, 0x0c, 0x10, 0x80, 0xe0, 0xc8, 0x0b, 0x3e, 0x09, 0x49, 0x90, 0x49, 0xff, 0xf2, 0xd8, +0x80, 0x46, 0x44, 0x00, 0x04, 0x00, 0x80, 0x27, 0x48, 0x00, 0x00, 0xfc, 0x3e, 0x09, 0x49, 0xb8, +0x49, 0xff, 0xf2, 0xce, 0xd5, 0x07, 0x80, 0x46, 0x44, 0x00, 0x04, 0x00, 0x84, 0x20, 0x49, 0xff, +0xfc, 0x2b, 0x84, 0x00, 0x48, 0x00, 0x00, 0xf4, 0x9d, 0x49, 0xe2, 0x24, 0xe9, 0x9c, 0x48, 0x00, +0x00, 0xee, 0x80, 0x0a, 0x3e, 0x19, 0x87, 0x74, 0x84, 0x42, 0xdd, 0x27, 0x81, 0x20, 0x4e, 0x03, +0x00, 0xc1, 0x10, 0x9f, 0x80, 0x1f, 0x80, 0x06, 0x50, 0x1f, 0x80, 0x1f, 0x05, 0xc3, 0x00, 0x04, +0x49, 0xff, 0xf7, 0xdc, 0x4e, 0x05, 0x00, 0xdb, 0xa1, 0xf4, 0x84, 0x61, 0x50, 0xae, 0x00, 0x18, +0x99, 0xf8, 0x51, 0xce, 0x00, 0x08, 0x4c, 0x81, 0xc0, 0x72, 0x00, 0x0f, 0x80, 0x1f, 0x84, 0xa6, +0x4c, 0x02, 0xc0, 0x8d, 0x3e, 0x39, 0xd9, 0xe8, 0x04, 0x01, 0x80, 0x99, 0x54, 0x00, 0x40, 0x00, +0xc0, 0x1f, 0xa6, 0xba, 0xa6, 0x7b, 0x02, 0x01, 0x81, 0x89, 0x40, 0x21, 0x20, 0x08, 0x40, 0x21, +0x04, 0x04, 0xc0, 0x16, 0x50, 0x01, 0x83, 0x16, 0x02, 0x11, 0x81, 0x8a, 0xd5, 0x0d, 0x0a, 0x40, +0x00, 0x01, 0x40, 0x91, 0x80, 0x13, 0x4c, 0x22, 0x40, 0x08, 0x84, 0x08, 0x84, 0x20, 0x80, 0x46, +0x49, 0xff, 0xfb, 0xe2, 0xd5, 0x05, 0x50, 0x34, 0x80, 0x01, 0xe3, 0x21, 0xe9, 0xf1, 0x3c, 0x1c, +0x77, 0x13, 0x54, 0x10, 0x80, 0x08, 0xc1, 0x62, 0x00, 0x53, 0x80, 0x0d, 0xa6, 0xf8, 0x54, 0x52, +0x80, 0x02, 0xa7, 0x39, 0xa6, 0x7a, 0xa6, 0xbb, 0xc5, 0x59, 0x40, 0x31, 0xa0, 0x08, 0x3c, 0x00, +0xee, 0x6b, 0x40, 0x31, 0x90, 0x04, 0x4c, 0x30, 0x00, 0x03, 0xc8, 0x50, 0x40, 0x10, 0xa0, 0x08, +0x3c, 0x00, 0xee, 0x6c, 0x40, 0x10, 0x88, 0x04, 0x4c, 0x10, 0x00, 0x03, 0xc8, 0x47, 0x3e, 0x09, +0xdc, 0xda, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x0b, 0x84, 0xc0, 0x0a, 0x3e, 0x09, +0xdc, 0xda, 0x3e, 0x19, 0xce, 0x80, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x0b, 0x7b, 0xc8, 0x36, +0x3e, 0x09, 0xdc, 0xea, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x0b, 0x73, 0xc0, 0x0a, +0x3e, 0x09, 0xdc, 0xea, 0x3e, 0x19, 0xce, 0x80, 0x44, 0x20, 0x00, 0x10, 0x49, 0x00, 0x0b, 0x6a, +0xc8, 0x25, 0x44, 0x00, 0x20, 0x00, 0x84, 0x20, 0xd5, 0x19, 0x84, 0x02, 0x4c, 0x80, 0x40, 0x1f, +0x3e, 0x39, 0xd9, 0xe8, 0x04, 0x01, 0x80, 0x99, 0x40, 0x00, 0x40, 0x08, 0x92, 0x1f, 0xc0, 0x16, +0x50, 0x11, 0x83, 0x40, 0x02, 0x21, 0x81, 0x9f, 0xd5, 0x0d, 0x0a, 0x00, 0x80, 0x01, 0x40, 0x91, +0x80, 0x13, 0xc8, 0x08, 0x80, 0x20, 0x44, 0x00, 0x08, 0x00, 0x80, 0x46, 0x49, 0xff, 0xfb, 0x7c, +0xd5, 0x05, 0x50, 0x34, 0x80, 0x01, 0xe3, 0x22, 0xe9, 0xf1, 0x8f, 0x01, 0x54, 0x84, 0x00, 0xff, +0xe7, 0x02, 0xe8, 0x3c, 0x00, 0x0f, 0x80, 0x1f, 0x44, 0x30, 0x00, 0x3a, 0x4c, 0x01, 0xc0, 0x37, +0x2e, 0x01, 0xdc, 0x47, 0xc0, 0x33, 0xa6, 0x38, 0x44, 0x40, 0x00, 0x87, 0x4c, 0x02, 0x40, 0x2f, +0x80, 0x06, 0x80, 0x3c, 0x80, 0x4a, 0x50, 0x33, 0x80, 0x08, 0x49, 0xff, 0xf9, 0x49, 0xd5, 0x26, +0x80, 0x0a, 0x3e, 0x19, 0x87, 0x6c, 0x84, 0x42, 0xdd, 0x27, 0xc8, 0x20, 0xa0, 0x74, 0x84, 0xa3, +0xa6, 0x89, 0xda, 0x07, 0x02, 0x23, 0x00, 0x0a, 0x80, 0x06, 0x49, 0x00, 0x15, 0xdd, 0xd5, 0x16, +0xca, 0x15, 0x3c, 0x0c, 0x77, 0x13, 0x54, 0x00, 0x00, 0x10, 0xc0, 0x10, 0x9c, 0x4c, 0xa6, 0x08, +0x84, 0xa1, 0xd8, 0x0c, 0xa7, 0xcc, 0x4c, 0x70, 0x40, 0x0a, 0x80, 0x22, 0x94, 0x2c, 0x80, 0x46, +0x49, 0xff, 0xfb, 0x3a, 0x92, 0x00, 0x80, 0x07, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0x3c, 0x46, 0x60, 0x04, 0x11, 0x80, 0xa6, 0x84, 0x81, +0x84, 0x20, 0x84, 0x0a, 0x04, 0x73, 0x01, 0xe6, 0x04, 0x22, 0x81, 0xc6, 0x96, 0xfc, 0xc3, 0x55, +0x54, 0x31, 0x00, 0x80, 0xc3, 0x4c, 0x40, 0x31, 0x20, 0x09, 0x96, 0xd8, 0xe6, 0x68, 0xe8, 0x47, +0x40, 0x81, 0x74, 0x09, 0x50, 0x94, 0x7f, 0xfe, 0x54, 0x94, 0x80, 0xff, 0xe7, 0x22, 0xe8, 0x0a, +0x40, 0x13, 0xa0, 0x09, 0x92, 0x50, 0x54, 0x10, 0x80, 0x0f, 0x54, 0x21, 0x00, 0x0f, 0x9a, 0x4a, +0xd5, 0x1b, 0x85, 0x24, 0x4c, 0x84, 0xc0, 0x1a, 0x92, 0xe8, 0x92, 0x50, 0x54, 0x83, 0x80, 0x0f, +0x54, 0x11, 0x00, 0x0f, 0x40, 0x14, 0x04, 0x01, 0x54, 0x73, 0x80, 0x10, 0x40, 0x83, 0x9c, 0x1a, +0x40, 0x80, 0x1c, 0x1b, 0x96, 0x48, 0x54, 0x21, 0x00, 0x10, 0x88, 0x28, 0x40, 0x71, 0x08, 0x1a, +0x40, 0x70, 0x08, 0x1b, 0x9a, 0x4f, 0x96, 0x48, 0xc9, 0x07, 0x42, 0x31, 0x80, 0x24, 0x3e, 0x29, +0xd9, 0x98, 0x98, 0xda, 0xd5, 0x11, 0xe6, 0x2a, 0xe9, 0x08, 0x42, 0x31, 0x80, 0x24, 0x3e, 0x99, +0xd9, 0x98, 0x88, 0x69, 0x8c, 0x69, 0xd5, 0x08, 0x80, 0x41, 0x42, 0x21, 0x80, 0x73, 0x3e, 0x99, +0xd9, 0x98, 0x40, 0x31, 0x24, 0x00, 0xa6, 0x98, 0x9c, 0x91, 0xae, 0x98, 0x9d, 0x21, 0x97, 0x20, +0x44, 0x20, 0x00, 0x21, 0x4c, 0x41, 0x7f, 0xa8, 0x3a, 0x6f, 0xa4, 0x04, 0xdd, 0x9e, 0x92, 0x00, +0xb4, 0x20, 0x92, 0x38, 0x54, 0x10, 0x80, 0x07, 0x3e, 0x11, 0x8a, 0x64, 0xb4, 0x60, 0x92, 0x70, +0x96, 0xd8, 0x3e, 0x31, 0x8a, 0x65, 0xb4, 0x80, 0x92, 0x88, 0x3e, 0x41, 0x8a, 0x66, 0x84, 0x80, +0x3c, 0x48, 0xc5, 0x40, 0x46, 0x40, 0x01, 0x04, 0x58, 0x42, 0x05, 0xdb, 0x98, 0x8c, 0x94, 0x92, +0xb4, 0x42, 0xe6, 0x24, 0xe8, 0x09, 0x94, 0x4b, 0x46, 0x20, 0x04, 0x11, 0x40, 0x31, 0x84, 0x0c, +0x58, 0x21, 0x07, 0x8c, 0xd5, 0x08, 0x94, 0x4b, 0x46, 0x20, 0x04, 0x11, 0x40, 0x31, 0x84, 0x0c, +0x58, 0x21, 0x07, 0x90, 0xb6, 0x62, 0xa2, 0x81, 0x3e, 0x21, 0x8a, 0x67, 0x46, 0x10, 0x04, 0x11, +0x04, 0x10, 0x80, 0xd3, 0xb4, 0x60, 0x40, 0x20, 0xc0, 0x09, 0x54, 0x21, 0x0f, 0xff, 0xe2, 0x62, +0xe9, 0x02, 0x92, 0x28, 0x3e, 0x11, 0x8a, 0x68, 0x84, 0x00, 0xdd, 0x9e, 0x96, 0x49, 0x54, 0x20, +0x80, 0x03, 0x92, 0x22, 0xca, 0x0f, 0xb4, 0x60, 0x54, 0x21, 0x80, 0x03, 0xca, 0x0b, 0x84, 0x41, +0xd5, 0x04, 0xb4, 0x80, 0x9c, 0x91, 0xab, 0x19, 0x9c, 0x04, 0xe2, 0x41, 0xe9, 0xfb, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, 0x96, 0x89, 0x84, 0x2c, +0x40, 0x31, 0x04, 0x37, 0x92, 0x42, 0xc9, 0x1b, 0xd5, 0x16, 0xa2, 0xc3, 0x54, 0x61, 0x80, 0x03, +0x9c, 0x4b, 0x50, 0x40, 0x7f, 0xf8, 0x9f, 0x44, 0x40, 0x31, 0xa0, 0x08, 0x92, 0x68, 0xce, 0x0f, +0xb4, 0xc3, 0xb4, 0x84, 0xb4, 0xa5, 0x40, 0x42, 0x10, 0x05, 0x40, 0x42, 0x18, 0x02, 0x40, 0x42, +0x14, 0x04, 0xb6, 0x83, 0xe2, 0x22, 0xe9, 0xea, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x3a, 0x6f, +0x9c, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0x3c, 0x96, 0x49, 0x54, 0x20, 0x80, 0x07, 0x92, 0x22, +0xca, 0x11, 0xd5, 0x0c, 0xa2, 0xc2, 0x54, 0x51, 0x80, 0x03, 0x9c, 0x92, 0x9f, 0x04, 0x40, 0x31, +0xa0, 0x08, 0x92, 0x68, 0xcd, 0x07, 0xb4, 0x84, 0xb6, 0x83, 0xe2, 0x41, 0xe9, 0xf4, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, +0x96, 0x49, 0x54, 0x20, 0x80, 0x07, 0x92, 0x22, 0xca, 0x11, 0xd5, 0x0c, 0xa2, 0xc2, 0x54, 0x51, +0x80, 0x03, 0x9c, 0x92, 0x9f, 0x04, 0x40, 0x31, 0xa0, 0x08, 0x92, 0x68, 0xcd, 0x07, 0xb4, 0x63, +0xb6, 0x64, 0xe2, 0x41, 0xe9, 0xf4, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0x3a, 0x6f, 0x98, 0x04, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0xa4, 0x88, 0x5c, 0xf1, 0x00, 0xc8, 0xe8, 0x18, +0x80, 0x80, 0xa2, 0xa1, 0x54, 0x31, 0x00, 0x03, 0xb4, 0xa4, 0xcb, 0x12, 0x5c, 0xf2, 0x80, 0x40, +0xe8, 0x0f, 0xd5, 0x04, 0xa3, 0x91, 0x80, 0x64, 0xb6, 0xc0, 0x40, 0x21, 0x20, 0x08, 0x92, 0x48, +0x9c, 0x04, 0x9d, 0x19, 0xdb, 0xf8, 0x95, 0x22, 0xad, 0x08, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x01, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x80, 0xe4, 0x81, 0x42, 0x81, 0x03, 0x81, 0x25, 0x55, 0xc0, 0x00, 0xff, 0x97, 0x08, +0x5c, 0xf3, 0x80, 0xc1, 0xe8, 0x3f, 0x3e, 0x09, 0xd3, 0x10, 0xf4, 0x81, 0x49, 0xff, 0xf2, 0x36, +0x80, 0xc0, 0xf4, 0x01, 0xc0, 0x37, 0x54, 0x42, 0x00, 0x0f, 0x54, 0x2e, 0x00, 0x0f, 0x2e, 0x11, +0x8a, 0x4f, 0x40, 0x21, 0x50, 0x08, 0x40, 0x42, 0x40, 0x08, 0xa0, 0x32, 0x40, 0x42, 0x08, 0x04, +0x46, 0x25, 0x80, 0x00, 0x54, 0x10, 0x80, 0x03, 0x40, 0x32, 0x08, 0x04, 0x14, 0x80, 0x00, 0x01, +0xb7, 0x40, 0x40, 0x10, 0xe4, 0x08, 0x50, 0x83, 0x80, 0x08, 0x40, 0x31, 0x84, 0x04, 0x80, 0x47, +0x54, 0x84, 0x3f, 0xff, 0x80, 0x29, 0x8c, 0x08, 0x40, 0x71, 0xa0, 0x04, 0x49, 0xfe, 0xc6, 0xde, +0x84, 0x01, 0x10, 0x03, 0x00, 0x0f, 0x84, 0x00, 0x10, 0x03, 0x00, 0x14, 0x12, 0x83, 0x00, 0x06, +0xa9, 0xf4, 0x80, 0x26, 0x3e, 0x09, 0xd9, 0xe8, 0x49, 0xff, 0xed, 0x90, 0x92, 0x00, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0x81, 0x40, 0x3e, 0x09, 0xd3, 0x10, 0x81, 0x22, 0x80, 0xe3, 0x54, 0x80, 0x80, 0xff, 0x49, 0xff, +0xf1, 0xed, 0x80, 0xc0, 0xc8, 0x03, 0x84, 0x01, 0xd5, 0x43, 0x5c, 0xf3, 0x80, 0xc9, 0xe9, 0x09, +0x3e, 0x09, 0x4a, 0x34, 0x44, 0x10, 0x00, 0xc8, 0x49, 0xff, 0xf0, 0x2a, 0x44, 0x70, 0x00, 0xc8, +0x2e, 0x11, 0x8a, 0x4f, 0x54, 0x84, 0x00, 0x0f, 0x54, 0x05, 0x00, 0x0f, 0x40, 0x00, 0x50, 0x08, +0x40, 0x84, 0x40, 0x08, 0x40, 0x84, 0x00, 0x04, 0x46, 0x05, 0x80, 0x00, 0x54, 0x10, 0x80, 0x03, +0x40, 0x10, 0xe4, 0x08, 0x40, 0x84, 0x00, 0x04, 0xa0, 0x32, 0x80, 0x47, 0x40, 0x84, 0x04, 0x04, +0x80, 0x29, 0x49, 0xfe, 0xc6, 0x93, 0x54, 0x73, 0xbf, 0xff, 0x84, 0x01, 0x40, 0x84, 0x1c, 0x04, +0x10, 0x03, 0x00, 0x0f, 0x84, 0x00, 0xad, 0xf6, 0x10, 0x03, 0x00, 0x14, 0x14, 0x83, 0x00, 0x04, +0x3e, 0x09, 0xd9, 0xe8, 0x80, 0x26, 0x49, 0xff, 0xed, 0x41, 0x80, 0xe0, 0xc0, 0x03, 0x84, 0x00, +0xd5, 0x07, 0x3e, 0x09, 0xd3, 0x10, 0x80, 0x26, 0x49, 0xff, 0xf1, 0xca, 0x80, 0x07, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3e, 0x28, 0x1e, 0xc0, 0x80, 0x61, +0x84, 0x02, 0x84, 0x20, 0x49, 0xff, 0xff, 0xa4, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x2e, 0x51, 0x8a, 0x65, 0xc5, 0x4d, 0x46, 0x00, 0x01, 0x19, +0x2e, 0x11, 0x8a, 0x67, 0xc1, 0x48, 0x2e, 0x41, 0x8a, 0x64, 0x9e, 0x49, 0x46, 0x20, 0x01, 0x04, +0x58, 0x21, 0x05, 0xdb, 0x96, 0x48, 0x3e, 0x11, 0x8a, 0x67, 0x98, 0x22, 0x94, 0x02, 0xb4, 0x60, +0x3c, 0x60, 0xc5, 0x40, 0x40, 0x01, 0xc0, 0x09, 0x98, 0x06, 0x96, 0x01, 0x96, 0xd9, 0x3c, 0x08, +0xc5, 0x40, 0xcb, 0x06, 0xc1, 0x05, 0x2e, 0x21, 0x8a, 0x68, 0xe2, 0x02, 0xe9, 0x2c, 0x2e, 0x21, +0x8a, 0x66, 0x40, 0x42, 0x60, 0x08, 0x40, 0x62, 0xc0, 0x08, 0x40, 0x63, 0x10, 0x04, 0x40, 0x21, +0x20, 0x08, 0x40, 0x63, 0x08, 0x04, 0x40, 0x50, 0x40, 0x08, 0x84, 0x08, 0x40, 0x52, 0x8c, 0x04, +0x40, 0x63, 0x04, 0x04, 0x80, 0x5f, 0x84, 0x20, 0x80, 0x60, 0xf5, 0x81, 0xb6, 0xdf, 0x49, 0xff, +0xff, 0x5f, 0x92, 0x00, 0x84, 0x60, 0x3e, 0x31, 0x8a, 0x65, 0x46, 0x10, 0x04, 0x11, 0x80, 0x01, +0x84, 0xa0, 0x3c, 0x58, 0xc5, 0x40, 0x84, 0x40, 0x3e, 0x31, 0x8a, 0x67, 0x14, 0x20, 0x81, 0xe3, +0x14, 0x20, 0x01, 0xe4, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x54, 0x80, 0x00, 0xff, 0x3e, 0x09, 0xd3, 0x10, 0x80, 0xe1, 0x49, 0xff, 0xf1, 0x37, 0x80, 0xc0, +0xc8, 0x03, 0x84, 0x01, 0xd5, 0x2d, 0x2e, 0x01, 0x8a, 0x4f, 0x54, 0x14, 0x00, 0x0f, 0x54, 0x00, +0x00, 0x03, 0x40, 0x10, 0xd0, 0x08, 0x40, 0x00, 0x64, 0x08, 0x40, 0x00, 0x80, 0x04, 0xa0, 0x72, +0x46, 0x25, 0x80, 0x00, 0xb6, 0xe1, 0x84, 0x28, 0x58, 0x21, 0x00, 0x08, 0xac, 0x76, 0x84, 0x21, +0x40, 0x00, 0x08, 0x04, 0x10, 0x13, 0x00, 0x0f, 0x84, 0x20, 0x10, 0x13, 0x00, 0x14, 0xa8, 0x34, +0x80, 0x26, 0x3e, 0x09, 0xd9, 0xe8, 0x49, 0xff, 0xec, 0xa1, 0x80, 0xe0, 0xc0, 0x03, 0x84, 0x00, +0xd5, 0x07, 0x3e, 0x09, 0xd3, 0x10, 0x80, 0x26, 0x49, 0xff, 0xf1, 0x2a, 0x80, 0x07, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x00, 0x04, +0x84, 0x01, 0xd5, 0x3a, 0x9c, 0x04, 0xb4, 0xc0, 0x3e, 0x09, 0x4a, 0x54, 0x80, 0x26, 0x49, 0xff, +0xef, 0x3f, 0x84, 0xa1, 0xde, 0x10, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x0e, 0x44, 0x2f, +0x1f, 0xff, 0x40, 0x10, 0x88, 0x02, 0x14, 0x10, 0x00, 0x0e, 0x3c, 0x1d, 0xfb, 0xdf, 0x84, 0x00, +0xdd, 0x21, 0xd5, 0x1a, 0x84, 0xa3, 0xd6, 0x03, 0x84, 0xc0, 0xd5, 0x16, 0x46, 0x10, 0x04, 0x00, +0x58, 0x10, 0x80, 0x38, 0xb4, 0x01, 0x44, 0x2f, 0x1f, 0xff, 0x40, 0x00, 0x08, 0x02, 0xb6, 0x01, +0x44, 0x30, 0xa0, 0x00, 0xb4, 0x41, 0x84, 0x00, 0x40, 0x21, 0x0c, 0x04, 0xb6, 0x41, 0x3c, 0x1d, +0xfb, 0xdf, 0x84, 0xc2, 0xdd, 0x21, 0x42, 0x23, 0x70, 0x08, 0x84, 0x00, 0x44, 0x10, 0x00, 0x73, +0x49, 0xfc, 0x23, 0x12, 0x84, 0x00, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x16, 0x9c, 0x04, +0xb4, 0x40, 0x84, 0xa1, 0xd2, 0x09, 0x56, 0x31, 0x00, 0x03, 0x84, 0x02, 0x84, 0x20, 0x40, 0x20, +0x8c, 0x1b, 0x40, 0x20, 0x0c, 0x1a, 0x42, 0x21, 0x70, 0x08, 0x84, 0x00, 0x44, 0x10, 0x00, 0x73, +0x49, 0xfc, 0x22, 0xf2, 0x92, 0x00, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x01, +0xd5, 0x06, 0x9c, 0x04, 0xb4, 0x00, 0x49, 0x00, 0x61, 0x1f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x97, 0xc9, 0x80, 0xc0, 0x3e, 0x09, +0x4a, 0x70, 0x80, 0x27, 0x49, 0xff, 0xee, 0xcc, 0x44, 0x50, 0x00, 0x10, 0xd7, 0x03, 0x84, 0x01, +0xd5, 0x16, 0x50, 0x03, 0x00, 0x0c, 0x9c, 0x74, 0x8c, 0xc8, 0xb4, 0xe1, 0xb4, 0xc6, 0xb5, 0x00, +0x80, 0x27, 0x3e, 0x09, 0x4a, 0x96, 0x80, 0x68, 0x80, 0x46, 0x49, 0xff, 0xee, 0xb9, 0x80, 0x08, +0x80, 0x27, 0x80, 0x46, 0x49, 0x00, 0x5f, 0x08, 0x92, 0x00, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x96, 0x49, 0x44, 0x00, 0x00, 0x14, +0x4c, 0x10, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x13, 0x3e, 0x09, 0x4a, 0xbc, 0x49, 0xff, 0xee, 0xa0, +0x50, 0x13, 0x00, 0x10, 0x50, 0x03, 0x00, 0x08, 0x9c, 0xb4, 0x8c, 0xcc, 0xb4, 0x61, 0xb4, 0x20, +0xb4, 0x06, 0xb4, 0x42, 0x49, 0x00, 0x5d, 0xb8, 0x5c, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x18, 0x96, 0x49, +0x4c, 0x11, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x13, 0x50, 0x40, 0x00, 0x14, 0x9d, 0x44, 0x50, 0x10, +0x00, 0x08, 0x50, 0x20, 0x00, 0x0c, 0x50, 0x30, 0x00, 0x10, 0xb4, 0x05, 0xb4, 0x21, 0xb4, 0x42, +0xb4, 0x63, 0xb4, 0x84, 0x49, 0x00, 0x5c, 0x84, 0x5c, 0x00, 0x00, 0x01, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xb4, 0x40, 0x84, 0x63, 0x96, 0x49, +0x4c, 0x21, 0x80, 0x18, 0xe6, 0x44, 0xe8, 0x06, 0x84, 0xa1, 0xd2, 0x0d, 0x84, 0xa2, 0xda, 0x09, +0xd5, 0x0d, 0x44, 0x50, 0xff, 0xf1, 0xd2, 0x13, 0x9d, 0x69, 0xd2, 0x14, 0x84, 0xa4, 0xd2, 0x0c, +0x84, 0x00, 0xd5, 0x12, 0x49, 0xff, 0xff, 0x4c, 0xd5, 0x0f, 0x49, 0xff, 0xff, 0xc5, 0xd5, 0x0c, +0x49, 0xff, 0xff, 0xa2, 0xd5, 0x09, 0x49, 0xff, 0xff, 0x77, 0xd5, 0x06, 0x49, 0xff, 0xff, 0x62, +0xd5, 0x03, 0x49, 0xff, 0xfe, 0xf9, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x96, 0x49, 0x97, 0xd8, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, +0x48, 0x00, 0x00, 0x66, 0xb4, 0x00, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x12, 0x3c, 0x2c, 0x77, 0x80, +0x3c, 0x0c, 0x77, 0x7f, 0xf2, 0x81, 0xb6, 0x1f, 0x49, 0x00, 0x24, 0x52, 0x84, 0x40, 0x80, 0xdf, +0x80, 0x27, 0x80, 0xbf, 0x84, 0x05, 0x80, 0x62, 0x84, 0x88, 0xd5, 0x4d, 0x84, 0x22, 0x4c, 0x00, +0xc0, 0x3f, 0x3e, 0x79, 0x89, 0xe4, 0xb4, 0x47, 0xc2, 0x49, 0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, +0xef, 0xcd, 0x80, 0xc0, 0xc8, 0x08, 0x3e, 0x09, 0x46, 0x84, 0x3e, 0x19, 0x4e, 0x38, 0x49, 0xff, +0xee, 0x0f, 0xd5, 0x3c, 0xb4, 0x07, 0x54, 0x10, 0x00, 0x03, 0xc1, 0x05, 0x92, 0x02, 0x94, 0x02, +0x9c, 0x04, 0xb6, 0x07, 0x2e, 0x81, 0x8a, 0x4f, 0x3c, 0x1c, 0x62, 0x79, 0x54, 0x84, 0x00, 0x03, +0x46, 0x25, 0x8b, 0x00, 0xa0, 0x32, 0x40, 0x84, 0x64, 0x08, 0x54, 0x70, 0xbf, 0xff, 0x40, 0x84, +0x08, 0x04, 0x80, 0x41, 0x3e, 0x19, 0xd3, 0x20, 0x49, 0xfe, 0xc4, 0x78, 0x40, 0x84, 0x1c, 0x04, +0x84, 0x01, 0x10, 0x03, 0x00, 0x14, 0x10, 0x03, 0x00, 0x0f, 0xad, 0xf6, 0x14, 0x83, 0x00, 0x04, +0x80, 0x26, 0x3e, 0x09, 0xd9, 0xe8, 0x49, 0xff, 0xeb, 0x29, 0xd5, 0x10, 0x84, 0x24, 0x4c, 0x00, +0xc0, 0x0e, 0x49, 0x00, 0x24, 0x05, 0x80, 0x27, 0x84, 0x05, 0x84, 0x41, 0x84, 0x60, 0x84, 0x82, +0x3e, 0x59, 0xdd, 0x98, 0x49, 0xff, 0xfd, 0x44, 0x92, 0x00, 0x84, 0x05, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x3e, 0x69, 0xd9, 0x98, 0x81, 0x00, +0x84, 0xe0, 0xa6, 0x71, 0xa6, 0x30, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x80, 0x04, 0x40, 0x03, +0xc0, 0x08, 0x40, 0x10, 0x80, 0x04, 0x80, 0x08, 0xaa, 0x41, 0x50, 0x14, 0x00, 0x08, 0xa7, 0x75, +0xa6, 0xb4, 0xa7, 0x32, 0xa6, 0xf3, 0x40, 0x52, 0xe0, 0x08, 0x40, 0x21, 0x40, 0x08, 0x40, 0x22, +0x88, 0x04, 0x40, 0x21, 0x10, 0x04, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x21, 0x0c, 0x04, 0xb6, 0x40, +0x9d, 0xf9, 0x00, 0x43, 0x00, 0x09, 0x00, 0x03, 0x00, 0x08, 0xa6, 0xf6, 0xa6, 0xb7, 0x40, 0x42, +0x60, 0x08, 0x40, 0x00, 0x40, 0x08, 0x40, 0x02, 0x00, 0x04, 0x40, 0x00, 0x0c, 0x04, 0x40, 0x21, +0x20, 0x08, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x01, 0x84, 0x4a, 0x80, 0x06, 0x84, 0x20, 0x49, 0xfe, +0xc4, 0x35, 0x84, 0xa8, 0x8c, 0xca, 0x8d, 0x0c, 0xdf, 0xc5, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x81, 0x00, 0xa3, 0xc1, 0x46, 0x90, +0x00, 0x80, 0x58, 0x94, 0x89, 0x4c, 0xb4, 0xc0, 0x80, 0x27, 0x3e, 0x09, 0x4a, 0xdc, 0x80, 0x46, +0xdd, 0x29, 0x84, 0xa1, 0xdf, 0x0b, 0x3e, 0x61, 0xdc, 0x44, 0x4e, 0x63, 0x01, 0x2f, 0x3e, 0x71, +0x8a, 0x57, 0x3e, 0x61, 0xde, 0x18, 0x48, 0x00, 0x01, 0x29, 0x84, 0xa3, 0x4c, 0x72, 0xc0, 0xca, +0x97, 0xb0, 0x3e, 0x79, 0xd9, 0xe8, 0x10, 0x63, 0x84, 0x1c, 0x46, 0x80, 0x04, 0x10, 0x58, 0x84, +0x08, 0x0c, 0xb5, 0x48, 0x42, 0xa5, 0x60, 0x09, 0x42, 0xa5, 0x64, 0x09, 0x46, 0x10, 0x00, 0x81, +0x58, 0x10, 0x8a, 0x84, 0xce, 0x47, 0x3e, 0x09, 0x4b, 0x04, 0xf1, 0x81, 0x47, 0xc0, 0x00, 0x80, +0x59, 0xce, 0x09, 0xe8, 0xdd, 0x29, 0x50, 0x03, 0x83, 0xb4, 0xdd, 0x3c, 0x50, 0x03, 0x83, 0xd0, +0xdd, 0x3c, 0x3e, 0x09, 0xd9, 0x7c, 0xdd, 0x3c, 0xb7, 0x48, 0x44, 0x00, 0x00, 0x28, 0x49, 0xfb, +0xff, 0xf5, 0x84, 0x41, 0x3e, 0x61, 0xde, 0x18, 0x3e, 0x21, 0x8a, 0x57, 0x80, 0x06, 0x49, 0x00, +0x21, 0x71, 0x3e, 0x09, 0x4b, 0x20, 0xdd, 0x29, 0xf1, 0x01, 0xdd, 0x21, 0x46, 0x30, 0x30, 0x00, +0x40, 0xa5, 0x0c, 0x04, 0xb7, 0x48, 0x3e, 0x09, 0x4b, 0x34, 0xb4, 0x28, 0xdd, 0x29, 0x46, 0x00, +0x04, 0x11, 0x58, 0x00, 0x00, 0x18, 0xb4, 0x40, 0x92, 0x4c, 0x40, 0x21, 0x30, 0x08, 0xb6, 0x40, +0x3c, 0x2c, 0x62, 0xab, 0xb4, 0x60, 0x40, 0x21, 0x88, 0x04, 0xb6, 0x40, 0x46, 0x10, 0x04, 0x10, +0x3c, 0x0c, 0x62, 0xaa, 0x14, 0x00, 0x81, 0x03, 0x84, 0x01, 0x3e, 0x01, 0x8a, 0x57, 0x48, 0x00, +0x00, 0xcd, 0xdd, 0x21, 0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x00, 0x18, 0xb4, 0x02, 0x54, 0x00, +0x0f, 0xff, 0x3c, 0x0e, 0x62, 0xab, 0xb4, 0x62, 0x92, 0x6c, 0x40, 0x31, 0xb0, 0x08, 0xb6, 0x62, +0x50, 0x11, 0x73, 0xf4, 0xb4, 0x62, 0x58, 0x31, 0x85, 0x78, 0xb6, 0x62, 0xb4, 0x41, 0x44, 0x00, +0x00, 0x28, 0x3c, 0x2e, 0x62, 0xaa, 0xb4, 0x41, 0x92, 0x48, 0x40, 0x21, 0x20, 0x08, 0xb6, 0x41, +0xb4, 0x41, 0x58, 0x21, 0x00, 0x04, 0xb6, 0x41, 0xb7, 0x48, 0x42, 0xa5, 0x60, 0x08, 0x49, 0xfb, +0xff, 0x9d, 0x3e, 0x09, 0x4b, 0x54, 0xdd, 0x29, 0x46, 0x20, 0x04, 0x00, 0x80, 0x22, 0x80, 0x01, +0x84, 0x60, 0xb7, 0x48, 0x14, 0x33, 0x81, 0x05, 0x14, 0x31, 0x00, 0xa3, 0x14, 0x30, 0x80, 0xa4, +0x14, 0x30, 0x00, 0xa2, 0x3c, 0x3e, 0x62, 0x79, 0x10, 0x33, 0x83, 0xa0, 0x80, 0x23, 0x44, 0x20, +0x06, 0x40, 0x3e, 0x09, 0xd3, 0x20, 0x49, 0xfe, 0xc3, 0x71, 0x49, 0xff, 0xf1, 0xdd, 0x2e, 0x01, +0xde, 0x2a, 0x49, 0xff, 0xf2, 0xeb, 0x50, 0x03, 0x83, 0xb4, 0x44, 0x10, 0x01, 0xf4, 0x49, 0xff, +0xed, 0xd3, 0x46, 0x00, 0x04, 0x00, 0x04, 0x30, 0x00, 0x25, 0x50, 0x31, 0xa7, 0x10, 0x3c, 0x3e, +0x62, 0xa8, 0x50, 0x03, 0x83, 0xd0, 0x44, 0x10, 0x03, 0xe8, 0x49, 0xff, 0xed, 0xc5, 0x00, 0x03, +0x83, 0xa1, 0x84, 0xa3, 0xd8, 0x6a, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x2c, 0x42, 0x10, +0xd4, 0x09, 0x42, 0x10, 0xf4, 0x09, 0x58, 0x10, 0x80, 0x20, 0x14, 0x10, 0x00, 0x2c, 0xd5, 0x5d, +0x84, 0x64, 0x4c, 0x71, 0xc0, 0x21, 0x84, 0x00, 0x40, 0x13, 0x0c, 0x06, 0x40, 0x60, 0x04, 0x1a, +0x84, 0xa1, 0x3e, 0x09, 0xd9, 0xe8, 0x10, 0x60, 0x03, 0xa1, 0xde, 0x04, 0x3c, 0x6e, 0x45, 0x98, +0xd5, 0x4c, 0x84, 0xa2, 0xde, 0x4a, 0x50, 0x14, 0x00, 0x08, 0xb4, 0x41, 0x50, 0x14, 0x00, 0x0c, +0x14, 0x20, 0x00, 0xe9, 0x8d, 0x10, 0xb4, 0x21, 0x14, 0x10, 0x00, 0xea, 0xb4, 0x28, 0x14, 0x10, +0x00, 0xeb, 0xd5, 0x3b, 0x84, 0xa5, 0xdf, 0x08, 0x56, 0x63, 0x00, 0x01, 0x5c, 0x63, 0x00, 0x01, +0x3e, 0x61, 0xde, 0x29, 0xd5, 0x32, 0x84, 0xa6, 0xdf, 0x13, 0x3e, 0x39, 0xd9, 0xe8, 0x12, 0x61, +0x81, 0x26, 0x50, 0x04, 0x00, 0x08, 0xb4, 0x20, 0x8d, 0x0c, 0x14, 0x11, 0x80, 0x95, 0x3e, 0x09, +0x4b, 0x80, 0xb4, 0x88, 0x96, 0xa0, 0x10, 0x21, 0x82, 0x58, 0xdd, 0x29, 0xd5, 0x1e, 0x84, 0xa7, +0xdf, 0x09, 0x97, 0xb0, 0x3e, 0x61, 0xdd, 0xd4, 0x80, 0x26, 0x3e, 0x09, 0x4b, 0x94, 0xdd, 0x29, +0xd5, 0x14, 0x84, 0xa8, 0xdf, 0x12, 0x3e, 0x09, 0xd9, 0xe8, 0x10, 0x60, 0x03, 0xed, 0x50, 0x14, +0x00, 0x08, 0xb4, 0x21, 0x8d, 0x0c, 0x54, 0x10, 0x80, 0x0f, 0x10, 0x10, 0x03, 0xee, 0xb4, 0x28, +0x54, 0x10, 0x8f, 0xff, 0x12, 0x10, 0x01, 0xd8, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x8c, 0xb4, 0x40, 0x85, 0x01, 0x80, 0xc0, +0x40, 0x90, 0x80, 0x13, 0x4c, 0x24, 0x40, 0x26, 0x9c, 0x04, 0xb4, 0x00, 0x50, 0x33, 0x00, 0x0c, +0x40, 0x10, 0x20, 0x02, 0x8c, 0xc8, 0xb4, 0xe6, 0xb4, 0x63, 0xc1, 0x03, 0x3e, 0x21, 0xdc, 0x45, +0x54, 0x00, 0x00, 0x02, 0xc0, 0x06, 0x84, 0x21, 0x3e, 0x11, 0xdc, 0x47, 0x3e, 0x11, 0xdc, 0x46, +0x3c, 0x3e, 0x77, 0x14, 0x3c, 0x7e, 0x77, 0x13, 0x3e, 0x09, 0x4b, 0xb0, 0x84, 0x21, 0x49, 0xff, +0xec, 0x17, 0x80, 0x27, 0x3e, 0x09, 0x4b, 0xc8, 0x49, 0xff, 0xec, 0x12, 0x48, 0x00, 0x01, 0x8a, +0x84, 0x02, 0x4c, 0x20, 0x40, 0x47, 0x00, 0x53, 0x00, 0x50, 0x00, 0x43, 0x00, 0x51, 0x00, 0x33, +0x00, 0x53, 0x9c, 0x34, 0xb5, 0x20, 0x01, 0xc3, 0x00, 0x52, 0xf3, 0x83, 0xf4, 0x82, 0xf5, 0x84, +0x44, 0x85, 0xb6, 0x58, 0x50, 0x13, 0x00, 0x08, 0x50, 0xaf, 0x80, 0x58, 0x44, 0x20, 0x00, 0x40, +0x50, 0x0f, 0x80, 0x18, 0x3e, 0x79, 0xd9, 0xe8, 0xdd, 0x28, 0x50, 0x13, 0x00, 0x48, 0x84, 0x48, +0x42, 0x64, 0x84, 0x0b, 0x80, 0x0a, 0x54, 0x94, 0x80, 0x01, 0xdd, 0x28, 0x10, 0x93, 0x82, 0x3f, +0x10, 0x63, 0x82, 0x40, 0x50, 0x1f, 0x80, 0x18, 0xf5, 0x04, 0x44, 0x20, 0x00, 0x40, 0x10, 0x53, +0x82, 0x3c, 0x50, 0x03, 0x80, 0xd0, 0xf4, 0x02, 0x10, 0x43, 0x82, 0x3d, 0xf3, 0x03, 0x13, 0xc3, +0x81, 0x26, 0x10, 0x33, 0x82, 0x3e, 0xdd, 0x28, 0x80, 0x2a, 0x84, 0x48, 0x50, 0x03, 0x80, 0xc8, +0xdd, 0x28, 0x50, 0x13, 0x80, 0xd0, 0x84, 0x00, 0x49, 0x00, 0x0c, 0x54, 0x48, 0x00, 0x01, 0x42, +0x84, 0x23, 0x4c, 0x20, 0xc0, 0x49, 0x50, 0xaf, 0x80, 0x68, 0x44, 0x75, 0xb6, 0x58, 0x9c, 0x74, +0x50, 0x9f, 0x80, 0x60, 0x84, 0x46, 0x80, 0x0a, 0xdd, 0x27, 0x50, 0x13, 0x00, 0x0a, 0x84, 0x46, +0x80, 0x09, 0xdd, 0x27, 0x80, 0x2a, 0x84, 0x46, 0x3e, 0x09, 0xde, 0x10, 0xdd, 0x27, 0x80, 0x29, +0x84, 0x46, 0x3e, 0x09, 0xdc, 0x29, 0xdd, 0x27, 0x8c, 0xd0, 0x3e, 0x79, 0xde, 0x10, 0xb5, 0x46, +0x00, 0x93, 0x80, 0x05, 0x3e, 0x69, 0xd9, 0xe8, 0xa6, 0x78, 0xa6, 0xb9, 0xa6, 0xfa, 0xa7, 0x3b, +0xa7, 0x7c, 0x14, 0xa3, 0x01, 0x04, 0xb7, 0x3f, 0x3e, 0x09, 0x4b, 0xe4, 0x49, 0xff, 0xeb, 0x98, +0x00, 0x93, 0x02, 0x46, 0x00, 0x13, 0x02, 0x41, 0x00, 0x23, 0x02, 0x42, 0x00, 0x33, 0x02, 0x43, +0x00, 0x43, 0x02, 0x44, 0x00, 0x53, 0x02, 0x45, 0xb7, 0x3f, 0x3e, 0x09, 0x4c, 0x14, 0x49, 0xff, +0xeb, 0x87, 0x04, 0x13, 0x01, 0x04, 0x3e, 0x09, 0x4c, 0x44, 0x49, 0xff, 0xeb, 0x81, 0x80, 0x08, +0x48, 0x00, 0x01, 0xc2, 0x84, 0x84, 0x4c, 0x22, 0x01, 0xbe, 0x84, 0xa6, 0xda, 0x61, 0x3e, 0x09, +0x4c, 0x58, 0x80, 0x29, 0x49, 0xff, 0xeb, 0x74, 0x84, 0xe0, 0xd5, 0x0d, 0xc8, 0x05, 0x3e, 0x09, +0x4c, 0x68, 0x49, 0xff, 0xeb, 0x6d, 0x38, 0x13, 0x1c, 0x00, 0x3e, 0x09, 0x4c, 0x6c, 0x49, 0xff, +0xeb, 0x67, 0x9d, 0xf9, 0x54, 0x03, 0x80, 0x0f, 0xe2, 0xe9, 0xe9, 0xf1, 0x3e, 0x09, 0x4c, 0x68, +0x49, 0xff, 0xeb, 0x5e, 0x9c, 0x34, 0xb5, 0x20, 0x50, 0x13, 0x00, 0x08, 0x50, 0x03, 0x00, 0x0c, +0x05, 0xc0, 0x80, 0x00, 0xb4, 0xe0, 0xe7, 0x23, 0x4e, 0xf2, 0x01, 0x95, 0xe6, 0xe2, 0x4e, 0xf2, +0x01, 0x92, 0x44, 0x30, 0x00, 0x12, 0x42, 0x34, 0x8c, 0x24, 0x3e, 0x49, 0xdd, 0x52, 0x50, 0x52, +0x7c, 0x96, 0x40, 0xa1, 0x90, 0x00, 0x44, 0x00, 0x00, 0x10, 0x98, 0xdd, 0x84, 0x24, 0x40, 0x20, +0x9c, 0x1a, 0x40, 0x20, 0x1c, 0x1b, 0x50, 0x31, 0x83, 0x60, 0xf2, 0x85, 0x10, 0x71, 0x80, 0x08, +0x11, 0xc1, 0x80, 0x09, 0x98, 0x70, 0x80, 0x0a, 0x49, 0xfe, 0xc1, 0xb8, 0x80, 0x27, 0x80, 0x49, +0x80, 0x7c, 0x3e, 0x09, 0x4c, 0x74, 0x49, 0xff, 0xeb, 0x2b, 0x80, 0xea, 0x84, 0xc0, 0x08, 0x13, +0x80, 0x01, 0x3e, 0x09, 0x4c, 0xa0, 0x49, 0xff, 0xeb, 0x23, 0xf5, 0x05, 0x9d, 0xb1, 0xe2, 0xc5, +0xe9, 0xf7, 0x3e, 0x09, 0x4c, 0x68, 0x49, 0xff, 0xeb, 0x1b, 0x48, 0x00, 0x00, 0x93, 0x84, 0x07, +0x4c, 0x20, 0x40, 0x78, 0x9c, 0x34, 0xb4, 0xe0, 0x50, 0x13, 0x00, 0x08, 0x50, 0x03, 0x00, 0x0c, +0xb5, 0x21, 0xb4, 0x60, 0xb4, 0x80, 0xe6, 0xe2, 0x4e, 0xf2, 0x01, 0x4d, 0xe7, 0x22, 0x4e, 0xf2, +0x01, 0x4a, 0x44, 0xa0, 0x00, 0x7e, 0x42, 0xa3, 0xa8, 0x24, 0x3e, 0x29, 0xd9, 0xe8, 0x40, 0x04, +0x10, 0x08, 0x40, 0x55, 0x08, 0x00, 0x84, 0x24, 0x50, 0x52, 0x82, 0x68, 0x40, 0x42, 0x00, 0x0d, +0x96, 0xd9, 0x40, 0x80, 0x9c, 0x1a, 0x40, 0x80, 0x1c, 0x1b, 0x50, 0x11, 0x02, 0x74, 0xad, 0x2d, +0x10, 0x92, 0x80, 0x05, 0xac, 0xec, 0xaf, 0xec, 0x41, 0xc5, 0x04, 0x00, 0x80, 0x48, 0x98, 0x70, +0x80, 0x1c, 0xf3, 0x83, 0xf4, 0x82, 0x49, 0xfe, 0xc1, 0x69, 0x3e, 0x29, 0xdc, 0x6c, 0x50, 0x13, +0x00, 0x20, 0x40, 0x05, 0x08, 0x00, 0x80, 0x48, 0x49, 0xfe, 0xc1, 0x60, 0xf3, 0x03, 0xf4, 0x02, +0x80, 0x49, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x09, 0x4c, 0x3e, 0x09, 0x4c, 0xa8, 0x80, 0x27, +0xdd, 0x26, 0x3e, 0x09, 0x4c, 0xe0, 0x81, 0x5c, 0xdd, 0x26, 0x83, 0x86, 0x85, 0x20, 0x08, 0x15, +0x00, 0x01, 0x3e, 0x09, 0x4c, 0xf0, 0x8d, 0x21, 0xdd, 0x3c, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, +0x09, 0x4c, 0xe3, 0x28, 0xe9, 0xf5, 0x3e, 0x09, 0x4c, 0x68, 0xdd, 0x26, 0x3e, 0x09, 0x4c, 0xf8, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x7e, 0x42, 0x73, 0x80, 0x24, 0x3e, 0x09, 0xdc, 0x6c, 0x81, 0x26, +0x99, 0xf8, 0x84, 0xc0, 0x08, 0x13, 0x80, 0x01, 0x9d, 0xb1, 0x3e, 0x09, 0x4c, 0xf0, 0xdd, 0x29, +0xe2, 0xc8, 0xe9, 0xf9, 0x3e, 0x09, 0x4c, 0x68, 0x49, 0xff, 0xea, 0xa2, 0x48, 0x00, 0x00, 0xe3, +0x84, 0x28, 0x4c, 0x20, 0xc0, 0x1a, 0x9c, 0x34, 0xb4, 0x20, 0x3e, 0x49, 0xd9, 0xe8, 0x96, 0x49, +0x12, 0x12, 0x01, 0x26, 0x50, 0x03, 0x00, 0x08, 0xb4, 0x40, 0x8c, 0xcc, 0x14, 0x22, 0x00, 0x95, +0x3e, 0x09, 0x4d, 0x08, 0xb4, 0xa6, 0x96, 0xe8, 0x10, 0x32, 0x02, 0x58, 0x49, 0xff, 0xea, 0x88, +0x84, 0x00, 0x48, 0x00, 0x00, 0xc9, 0x84, 0x89, 0x4c, 0x22, 0x40, 0x5d, 0x9c, 0x74, 0xb4, 0x01, +0xc8, 0x06, 0x3c, 0x88, 0xee, 0x7d, 0x3c, 0x88, 0xee, 0x3e, 0xd5, 0x06, 0x3e, 0x09, 0xdc, 0x6c, +0x84, 0x44, 0x49, 0xfe, 0xc0, 0xfb, 0x50, 0x03, 0x00, 0x08, 0xb4, 0xe0, 0x96, 0x39, 0xe6, 0x15, +0xe9, 0x03, 0x44, 0x70, 0x00, 0x14, 0x97, 0xf9, 0x3e, 0x89, 0xd9, 0xe8, 0x12, 0x74, 0x01, 0x4b, +0x3e, 0x09, 0x4d, 0x20, 0x80, 0x27, 0x49, 0xff, 0xea, 0x63, 0x98, 0xbf, 0x3e, 0x59, 0xdc, 0x80, +0x50, 0x04, 0x02, 0x98, 0x98, 0x95, 0x50, 0x13, 0x00, 0x0c, 0xd5, 0x04, 0xa2, 0xc9, 0x1a, 0x30, +0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfd, 0x9c, 0x3b, 0x94, 0x02, 0x98, 0x30, 0xb5, 0x00, 0x40, 0x04, +0x00, 0x13, 0xe6, 0x15, 0xe9, 0x03, 0x44, 0x80, 0x00, 0x14, 0x40, 0x84, 0x00, 0x13, 0x50, 0x92, +0xfd, 0x68, 0x12, 0x84, 0x81, 0x8a, 0x9d, 0xfc, 0x80, 0x28, 0x3e, 0x09, 0x4d, 0x38, 0x97, 0xf9, +0x49, 0xff, 0xea, 0x3e, 0x95, 0xfa, 0x89, 0x08, 0x3e, 0x19, 0xdc, 0xfe, 0x99, 0xb7, 0x50, 0x04, +0x83, 0x16, 0x89, 0x01, 0xd5, 0x04, 0xa2, 0x71, 0x1a, 0x10, 0x00, 0x01, 0x4c, 0x04, 0x7f, 0xfd, +0x3e, 0x29, 0xd9, 0xe8, 0x04, 0x31, 0x00, 0x99, 0x3e, 0x09, 0x4d, 0x50, 0x58, 0x31, 0xc0, 0x00, +0xd5, 0x58, 0x84, 0x8a, 0x4c, 0x22, 0x40, 0x5a, 0x9c, 0x34, 0xb4, 0xe0, 0x96, 0x39, 0xe6, 0x15, +0xe9, 0x02, 0x95, 0xe1, 0x97, 0xf9, 0x3e, 0xa9, 0xd9, 0xe8, 0x12, 0x75, 0x01, 0x60, 0x46, 0x80, +0x00, 0x80, 0x58, 0x84, 0x09, 0x4c, 0x3e, 0x09, 0x4d, 0x64, 0x80, 0x27, 0xdd, 0x28, 0x83, 0x88, +0x50, 0xa5, 0x02, 0xc2, 0x50, 0x93, 0x00, 0x08, 0x85, 0x00, 0xd5, 0x0a, 0x0c, 0x24, 0x80, 0x01, +0x8d, 0x01, 0x96, 0x51, 0x1a, 0x15, 0x00, 0x01, 0xdd, 0x3c, 0x40, 0x84, 0x00, 0x13, 0x3e, 0x09, +0x4d, 0x7c, 0xe3, 0x07, 0xe9, 0xf4, 0x9c, 0x3a, 0x94, 0x02, 0x98, 0x30, 0xb5, 0x00, 0x40, 0x04, +0x00, 0x13, 0xe6, 0x15, 0xe9, 0x03, 0x44, 0x80, 0x00, 0x14, 0x40, 0x84, 0x00, 0x13, 0x3e, 0x99, +0xd9, 0xe8, 0x12, 0x84, 0x81, 0x9f, 0x9d, 0xfb, 0x3e, 0x09, 0x4d, 0x90, 0x80, 0x28, 0x97, 0xf9, +0x49, 0xff, 0xe9, 0xe6, 0x95, 0xfa, 0x89, 0x08, 0x3e, 0x59, 0xdd, 0x28, 0x99, 0xb7, 0x50, 0x04, +0x83, 0x40, 0x89, 0x05, 0xd5, 0x04, 0xa2, 0x71, 0x1a, 0x10, 0x00, 0x01, 0x4c, 0x04, 0x7f, 0xfd, +0x50, 0x22, 0xfc, 0xc0, 0x04, 0x31, 0x00, 0x99, 0x3e, 0x09, 0x4d, 0xa8, 0x42, 0x31, 0xbc, 0x08, +0x80, 0x23, 0x14, 0x31, 0x00, 0x99, 0xd5, 0x0c, 0x84, 0x8b, 0x4c, 0x22, 0x40, 0x0c, 0x9d, 0xb4, +0xb4, 0x46, 0x96, 0x90, 0x3e, 0x21, 0xdc, 0x49, 0x80, 0x22, 0x3e, 0x09, 0x4d, 0xbc, 0x49, 0xff, +0xe9, 0xbf, 0x84, 0x01, 0xec, 0x74, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x96, 0x49, 0x80, 0xc0, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xca, 0xb4, 0x20, +0x84, 0xa6, 0xd1, 0x4f, 0xe6, 0x27, 0xe8, 0x11, 0x84, 0xa3, 0xd1, 0x2c, 0xe6, 0x24, 0xe8, 0x07, +0x84, 0xa1, 0xd1, 0x1b, 0x84, 0xa2, 0x4c, 0x12, 0xc0, 0xbb, 0xd5, 0x22, 0x84, 0xa4, 0xd1, 0x29, +0x84, 0xa5, 0x4c, 0x12, 0xc0, 0xb5, 0xd5, 0x38, 0x84, 0xa9, 0xd1, 0x4a, 0xe6, 0x2a, 0xe8, 0x07, +0x84, 0xa7, 0xd1, 0x3d, 0x84, 0xa8, 0x4c, 0x12, 0xc0, 0xab, 0xd5, 0x3f, 0x84, 0xaa, 0xd1, 0x52, +0x84, 0xab, 0x4c, 0x12, 0xc0, 0xa5, 0xd5, 0x5c, 0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x8a, 0x4f, +0x96, 0x48, 0xae, 0x40, 0xe6, 0x22, 0x4e, 0xf3, 0x00, 0x9b, 0x84, 0x20, 0xd5, 0x41, 0x84, 0x03, +0xd5, 0x02, 0x84, 0x04, 0x84, 0x20, 0x84, 0x41, 0x49, 0x03, 0xef, 0x86, 0x48, 0x00, 0x00, 0x90, +0x9d, 0xb4, 0xb4, 0x06, 0x96, 0x00, 0x3e, 0x01, 0x8a, 0x50, 0x84, 0xa1, 0x4c, 0x02, 0xc0, 0x88, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x28, 0xb4, 0x41, 0x46, 0x30, 0x00, 0xff, 0x84, 0x00, +0x40, 0x21, 0x0c, 0x04, 0xd5, 0x33, 0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x8a, 0x5a, 0xd5, 0x20, +0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x8a, 0x59, 0x96, 0x4c, 0xd5, 0x1a, 0x3c, 0x1c, 0x62, 0x7c, +0x84, 0x00, 0xb6, 0x26, 0x48, 0x00, 0x00, 0x6d, 0x49, 0x00, 0x1e, 0x4e, 0xd5, 0x68, 0x3e, 0x79, +0xd9, 0x98, 0x80, 0x07, 0x84, 0x20, 0x84, 0x4a, 0x49, 0xfe, 0xbf, 0xf0, 0x8c, 0xea, 0x3e, 0x59, +0xd9, 0xe8, 0xdf, 0xf8, 0x9d, 0xb4, 0xb4, 0x26, 0x3e, 0x09, 0x8a, 0x52, 0x96, 0x4c, 0xae, 0x40, +0xd5, 0x56, 0x9d, 0xb4, 0xb4, 0x06, 0x84, 0xa1, 0xd8, 0x52, 0x3e, 0x1f, 0xee, 0x48, 0xb4, 0x01, +0xc8, 0x4e, 0x46, 0x20, 0x00, 0x82, 0x58, 0x21, 0x09, 0x74, 0xb6, 0x41, 0xd5, 0x49, 0x9d, 0xb4, +0xb4, 0x06, 0xb4, 0x46, 0x42, 0x00, 0x0c, 0x0b, 0xb4, 0x66, 0xc8, 0x12, 0x46, 0x10, 0x04, 0x00, +0x04, 0x40, 0x80, 0x49, 0x44, 0x5f, 0xf0, 0x00, 0x40, 0x42, 0x14, 0x04, 0x14, 0x40, 0x80, 0x49, +0x80, 0x01, 0x04, 0x10, 0x00, 0x4a, 0x58, 0x10, 0x8f, 0xff, 0x14, 0x10, 0x00, 0x4a, 0x46, 0x60, +0x04, 0x00, 0x58, 0x63, 0x00, 0x38, 0xb4, 0x26, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, 0xb6, 0x26, +0x40, 0x01, 0x40, 0x08, 0xb4, 0x46, 0x92, 0x18, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x06, 0x44, 0x5f, +0x00, 0xff, 0xb4, 0x06, 0x46, 0x40, 0x0f, 0xf0, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x06, 0xb4, 0x46, +0x40, 0x11, 0x90, 0x02, 0x92, 0x28, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x26, 0x3c, 0x1d, 0xfb, 0xdf, +0x84, 0x00, 0xdd, 0x21, 0x46, 0x20, 0x04, 0x00, 0x80, 0x02, 0xb4, 0x26, 0x04, 0x21, 0x00, 0x49, +0x04, 0x30, 0x00, 0x4a, 0x3e, 0x09, 0x4d, 0xe4, 0x49, 0xff, 0xe8, 0xea, 0x84, 0x00, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x3c, 0x3c, 0x62, 0x7a, 0x80, 0xc1, +0x9c, 0x59, 0x3c, 0x1e, 0x62, 0x7a, 0x81, 0x20, 0x04, 0x83, 0x00, 0x04, 0x84, 0x0e, 0x40, 0x14, +0x50, 0x09, 0x54, 0x10, 0x80, 0x7f, 0x84, 0xe4, 0x4c, 0x10, 0x00, 0xd9, 0xe4, 0x2f, 0xe8, 0x28, +0x84, 0xa7, 0x4c, 0x12, 0x80, 0xc5, 0xe4, 0x28, 0xe8, 0x13, 0x84, 0xa2, 0x4c, 0x12, 0x80, 0xac, +0xe4, 0x23, 0xe8, 0x06, 0x84, 0xa1, 0x4c, 0x12, 0xc0, 0xd4, 0x48, 0x00, 0x00, 0x96, 0x84, 0xa3, +0x4c, 0x12, 0x80, 0xa7, 0x84, 0xa6, 0x4c, 0x12, 0xc0, 0xcc, 0x48, 0x00, 0x00, 0xa7, 0x84, 0xaa, +0xd1, 0x42, 0xe4, 0x2b, 0xe8, 0x07, 0x84, 0xa8, 0xd1, 0x32, 0x84, 0xa9, 0x4c, 0x12, 0xc0, 0xc1, +0xd5, 0x34, 0x84, 0xab, 0xd1, 0x40, 0x84, 0xac, 0x4c, 0x12, 0xc0, 0xbb, 0xd5, 0x46, 0x9d, 0x47, +0xd1, 0x5e, 0xe4, 0x36, 0xe8, 0x13, 0x9d, 0x43, 0x4c, 0x12, 0x80, 0x95, 0xe4, 0x32, 0xe8, 0x07, +0x84, 0xaf, 0xd1, 0x41, 0x9d, 0x42, 0x4c, 0x12, 0xc0, 0xac, 0xd5, 0x45, 0x9d, 0x45, 0x4c, 0x12, +0x80, 0xa3, 0x9d, 0x46, 0x4c, 0x12, 0xc0, 0xa5, 0xd5, 0x44, 0x9d, 0x6c, 0xd1, 0x58, 0xe4, 0x3a, +0xe8, 0x07, 0x9f, 0x6b, 0xd1, 0x4f, 0x9d, 0x6a, 0x4c, 0x12, 0xc0, 0x9b, 0xd5, 0x46, 0x9d, 0x6d, +0xd1, 0x65, 0x9d, 0x69, 0x4c, 0x12, 0xc0, 0x95, 0x48, 0x00, 0x00, 0x5c, 0xa0, 0x32, 0xa4, 0x76, +0x49, 0xff, 0xf7, 0x56, 0x48, 0x00, 0x00, 0x92, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf7, 0x66, +0x48, 0x00, 0x00, 0x8c, 0xa0, 0x32, 0xa4, 0x76, 0x54, 0x74, 0x3f, 0xff, 0x49, 0xff, 0xf7, 0xa0, +0x48, 0x00, 0x00, 0x84, 0xa0, 0x32, 0x50, 0x13, 0x00, 0x0c, 0x49, 0xff, 0xf7, 0xb5, 0xa5, 0xf6, +0x54, 0x73, 0xbf, 0xff, 0x48, 0x00, 0x00, 0x7a, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf7, 0x74, +0x48, 0x00, 0x00, 0x74, 0xa0, 0x32, 0xa4, 0x76, 0x44, 0x70, 0x01, 0x40, 0x49, 0xff, 0xfa, 0x8c, +0x48, 0x00, 0x00, 0x6c, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xec, 0x10, 0x48, 0x00, 0x00, 0x66, +0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x1a, 0xc4, 0x48, 0x00, 0x00, 0x60, 0xa0, 0x32, 0xa4, 0x76, +0x49, 0xff, 0xfc, 0x0a, 0x48, 0x00, 0x00, 0x5a, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xfa, 0xbc, +0xd5, 0x54, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf7, 0xa9, 0xd5, 0x4f, 0x40, 0x34, 0x40, 0x09, +0xa4, 0x76, 0xa0, 0x32, 0x54, 0x31, 0x80, 0x0f, 0x50, 0x2f, 0x80, 0x04, 0x49, 0xff, 0xf9, 0xf2, +0x84, 0x00, 0x48, 0x00, 0x00, 0x9d, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xfe, 0x71, 0xd5, 0x3d, +0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x52, 0x50, 0xd5, 0x38, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, +0x3d, 0x65, 0xd5, 0x33, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x3e, 0xee, 0xd5, 0x2e, 0xa0, 0x32, +0xa4, 0x76, 0x49, 0x00, 0x38, 0x0f, 0xd5, 0x29, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x24, 0x56, +0xd5, 0x24, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, 0xf9, 0x9f, 0xd5, 0x1f, 0x40, 0x24, 0x40, 0x09, +0xa4, 0x76, 0xa0, 0x32, 0x54, 0x21, 0x00, 0x0f, 0x49, 0x00, 0x5f, 0x40, 0x46, 0x1f, 0xff, 0x0f, +0x58, 0x10, 0x8f, 0xff, 0x40, 0x84, 0x04, 0x02, 0xd5, 0x10, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0xff, +0xf6, 0x91, 0xd5, 0x0b, 0xa0, 0x32, 0xa4, 0x76, 0x49, 0x00, 0x3f, 0xa2, 0xd5, 0x06, 0x3e, 0x09, +0x4e, 0x20, 0x49, 0xff, 0xe7, 0xed, 0x84, 0x00, 0x46, 0x10, 0x04, 0x00, 0x04, 0x30, 0x80, 0x8c, +0x93, 0x10, 0x42, 0x31, 0xfc, 0x08, 0x54, 0x84, 0x00, 0x0f, 0x14, 0x30, 0x80, 0x8c, 0x4e, 0x83, +0x00, 0x04, 0x80, 0x08, 0xd5, 0x4c, 0x46, 0x1f, 0xff, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x73, +0x84, 0x02, 0x40, 0x84, 0x40, 0x08, 0x40, 0x73, 0xa0, 0x04, 0x42, 0x73, 0xf8, 0x09, 0x42, 0x73, +0xfc, 0x09, 0x46, 0x2f, 0xf0, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x42, 0x73, 0xf8, 0x08, 0x54, 0x00, +0x00, 0x0f, 0x40, 0x00, 0x50, 0x08, 0x40, 0x73, 0x88, 0x02, 0x40, 0x73, 0x80, 0x04, 0x46, 0x1c, +0x6f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x2e, 0x01, 0x8a, 0x4f, 0x46, 0x21, 0x80, 0x00, 0x40, 0x73, +0x84, 0x02, 0x40, 0x73, 0x88, 0x04, 0x54, 0x00, 0x00, 0x03, 0x40, 0x00, 0x64, 0x08, 0x42, 0x73, +0xe4, 0x09, 0x42, 0x73, 0xe8, 0x09, 0x40, 0x73, 0x80, 0x04, 0x42, 0x73, 0xbc, 0x09, 0x54, 0x03, +0xbf, 0xff, 0xe4, 0x08, 0xe8, 0x06, 0x92, 0xee, 0x40, 0x73, 0xb8, 0x08, 0x58, 0x73, 0x80, 0x08, +0x54, 0x03, 0xbf, 0xff, 0xac, 0x36, 0x84, 0x01, 0x10, 0x03, 0x00, 0x0f, 0xa9, 0xf4, 0x80, 0x26, +0x80, 0x09, 0x49, 0xff, 0xe4, 0xdb, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x01, 0x80, +0x44, 0x00, 0x00, 0x10, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x88, 0x20, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x11, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x87, 0xec, 0xdd, 0x26, 0x84, 0x00, 0x46, 0x10, +0x00, 0x80, 0x58, 0x10, 0x85, 0x54, 0xdd, 0x26, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x84, 0xdc, +0x84, 0x01, 0xdd, 0x26, 0x49, 0xff, 0xe9, 0x66, 0x3e, 0x09, 0xd9, 0xe8, 0x49, 0xff, 0xe3, 0xac, +0x3e, 0x19, 0xed, 0x54, 0x3c, 0x1e, 0x62, 0xad, 0x84, 0xc0, 0x3e, 0x79, 0xd9, 0xe8, 0x49, 0xff, +0xeb, 0xf9, 0x80, 0x26, 0x84, 0x60, 0x84, 0x48, 0x50, 0x03, 0x84, 0x1e, 0x10, 0x33, 0x84, 0x1c, +0x14, 0x63, 0x80, 0x2d, 0x49, 0xfe, 0xbd, 0xfa, 0x80, 0x66, 0x50, 0x03, 0x83, 0xf0, 0x80, 0x46, +0x46, 0x10, 0x00, 0x8b, 0x58, 0x10, 0x88, 0x74, 0x49, 0xff, 0xe7, 0x7e, 0x80, 0x26, 0x50, 0x03, +0x84, 0x0c, 0x84, 0x43, 0x49, 0xfe, 0xbd, 0xea, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, +0xa9, 0x8c, 0x46, 0x30, 0x30, 0x00, 0xa0, 0x8b, 0x40, 0x21, 0x0c, 0x04, 0xa8, 0x8b, 0x3e, 0x09, +0x4e, 0x50, 0x49, 0xff, 0xe7, 0x35, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x84, 0x60, 0xd5, 0x0e, +0x38, 0x50, 0x0c, 0x00, 0x38, 0x40, 0x8c, 0x00, 0x9c, 0xd9, 0xe2, 0x85, 0xe8, 0x03, 0x84, 0x01, +0xd5, 0x08, 0xe2, 0xa4, 0xe8, 0x03, 0x84, 0x02, 0xd5, 0x04, 0xe2, 0x62, 0xe9, 0xf2, 0x84, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0x9c, 0x01, 0x08, 0x60, 0x00, 0x01, 0x96, 0x49, +0xaf, 0x90, 0x08, 0x60, 0x00, 0x01, 0xaf, 0xa0, 0x08, 0x60, 0x00, 0x01, 0xaf, 0xa8, 0xa7, 0xa0, +0xa7, 0x40, 0xf4, 0x01, 0xce, 0x05, 0x97, 0xac, 0xc6, 0x03, 0x84, 0xc1, 0xd5, 0x02, 0x84, 0xc0, +0xaf, 0x98, 0x54, 0x32, 0x80, 0xfe, 0x95, 0x5b, 0xa6, 0x90, 0xe0, 0x25, 0xe9, 0x08, 0x9e, 0x94, +0x98, 0x9a, 0x96, 0x90, 0x9c, 0x91, 0x94, 0x93, 0xe0, 0x22, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x16, +0x40, 0x20, 0x8c, 0x09, 0x9a, 0xd3, 0x96, 0xd8, 0x98, 0x03, 0x84, 0xa8, 0x96, 0xdc, 0x40, 0x21, +0x8c, 0x1a, 0x40, 0x22, 0x8c, 0x1b, 0x20, 0x00, 0x00, 0x01, 0x54, 0x10, 0x80, 0x0f, 0x9a, 0x4a, +0x40, 0x10, 0x04, 0x0e, 0x96, 0x4c, 0xc1, 0x04, 0x84, 0x01, 0xae, 0x20, 0xd5, 0x02, 0xae, 0x60, +0x84, 0x01, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x84, 0x60, 0x80, 0x82, 0xd5, 0x07, 0x38, 0x50, +0x8c, 0x00, 0x9f, 0x21, 0x38, 0x50, 0x0c, 0x08, 0x9c, 0xd9, 0xcc, 0xfa, 0x98, 0x02, 0xdd, 0x9e, +0x84, 0x60, 0x80, 0x80, 0xd5, 0x09, 0x38, 0x52, 0x0c, 0x00, 0x38, 0x00, 0x8c, 0x00, 0x9c, 0xd9, +0x9a, 0x28, 0xc8, 0x04, 0x9e, 0x91, 0xca, 0xf8, 0x80, 0x02, 0xdd, 0x9e, 0x3e, 0x19, 0xed, 0x54, +0xb4, 0x41, 0x98, 0x02, 0xb6, 0x01, 0x80, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3e, 0x19, 0x44, 0xd8, +0x3c, 0x1e, 0x7b, 0x55, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xfb, +0xf9, 0x5b, 0x92, 0x05, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x2f, 0x94, 0x3c, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x81, 0x20, 0x50, 0x0f, 0x80, 0x20, 0xf0, 0x81, 0x80, 0xe1, +0x84, 0xc0, 0xf2, 0x01, 0x84, 0xbf, 0x9d, 0x14, 0xf4, 0x81, 0x40, 0x04, 0x98, 0x00, 0xb4, 0x62, +0x9c, 0x64, 0x80, 0x43, 0xd3, 0x07, 0xf1, 0x81, 0x99, 0xb3, 0xb4, 0x24, 0x49, 0xfe, 0xbd, 0x20, +0xd5, 0xf1, 0x80, 0x06, 0xb6, 0xc7, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xec, 0x10, 0xdd, 0x9e, +0x84, 0x40, 0x80, 0x60, 0x38, 0x40, 0x88, 0x00, 0x9c, 0x91, 0x18, 0x41, 0x80, 0x01, 0x84, 0x86, +0x4c, 0x22, 0x7f, 0xfa, 0x98, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xc0, +0x80, 0xe1, 0x81, 0x22, 0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x81, 0x03, 0x49, 0xfe, 0xbd, 0x16, +0xa6, 0x70, 0x44, 0x2f, 0xff, 0xd0, 0x54, 0x10, 0x80, 0x03, 0x40, 0x10, 0x88, 0x04, 0x80, 0x06, +0x18, 0x10, 0x00, 0x04, 0x80, 0x27, 0x49, 0xff, 0xff, 0xdd, 0x80, 0x29, 0x50, 0x03, 0x00, 0x0a, +0x49, 0xff, 0xff, 0xd8, 0x80, 0x28, 0x50, 0x03, 0x00, 0x10, 0x49, 0xff, 0xff, 0xd3, 0x49, 0xff, +0xea, 0xe9, 0x2e, 0x21, 0xdd, 0x98, 0x00, 0x13, 0x00, 0x16, 0x54, 0x21, 0x00, 0x0f, 0x94, 0x94, +0x54, 0x10, 0x80, 0x0f, 0x40, 0x10, 0x88, 0x04, 0x10, 0x13, 0x00, 0x16, 0x3c, 0x00, 0xee, 0xcc, +0x92, 0x04, 0x10, 0x03, 0x00, 0x17, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, 0x40, 0x80, 0x80, 0x13, 0x49, 0x00, 0x1c, 0x7e, +0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, 0xe7, 0xea, 0x80, 0xe0, 0xc8, 0x08, 0x3e, 0x09, 0x46, 0x84, +0x3e, 0x19, 0x4e, 0xa4, 0x49, 0xff, 0xe6, 0x2c, 0xd5, 0x38, 0xa1, 0x82, 0x8c, 0xd8, 0x3e, 0x19, +0xdc, 0x29, 0x80, 0x61, 0x50, 0x03, 0x7f, 0xe8, 0x3e, 0x29, 0xde, 0x10, 0x49, 0xff, 0xff, 0xa6, +0x84, 0x23, 0x04, 0x04, 0x80, 0x04, 0xa6, 0xb5, 0xae, 0x70, 0x84, 0x21, 0xae, 0x71, 0x58, 0x21, +0x00, 0x02, 0x42, 0x31, 0x00, 0x09, 0x00, 0x40, 0x00, 0x1a, 0x40, 0x14, 0x20, 0x09, 0xae, 0xf5, +0xaf, 0x32, 0xae, 0x74, 0x10, 0x83, 0x00, 0x03, 0x54, 0x21, 0x00, 0x02, 0x00, 0x10, 0x00, 0x1b, +0x84, 0x00, 0x54, 0x10, 0x80, 0x3c, 0x40, 0x21, 0x04, 0x04, 0x44, 0x10, 0x00, 0x10, 0xae, 0xb5, +0xae, 0x76, 0xae, 0x37, 0x10, 0x03, 0x00, 0x08, 0x50, 0x13, 0x7f, 0xe8, 0x80, 0x67, 0x44, 0x20, +0x00, 0x21, 0x49, 0x00, 0x02, 0x99, 0x92, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xc0, 0x54, 0xa0, 0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0x84, 0x20, +0x44, 0x20, 0x00, 0x18, 0x81, 0x04, 0x80, 0xe3, 0x49, 0xfe, 0xbc, 0x88, 0xa6, 0xf0, 0xa6, 0x31, +0x54, 0x31, 0x80, 0x03, 0x54, 0x24, 0x80, 0x01, 0x42, 0x00, 0x00, 0x09, 0x40, 0x15, 0x10, 0x08, +0x40, 0x11, 0x84, 0x04, 0x40, 0x00, 0x08, 0x04, 0xae, 0x70, 0xae, 0x31, 0x80, 0x27, 0x9c, 0x34, +0x49, 0xff, 0xff, 0x48, 0x3e, 0x19, 0xde, 0x10, 0x50, 0x03, 0x00, 0x0a, 0x49, 0xff, 0xff, 0x42, +0x50, 0x03, 0x00, 0x10, 0x80, 0x28, 0x49, 0xff, 0xff, 0x3d, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x84, 0xa0, 0xf4, 0x83, 0xad, 0x60, 0x80, 0xa0, 0x08, 0x82, +0x80, 0x0a, 0xf3, 0x82, 0x93, 0x04, 0xf1, 0x85, 0x14, 0x8f, 0x80, 0x04, 0x80, 0xc0, 0x80, 0x25, +0x80, 0x02, 0x49, 0xff, 0xff, 0x27, 0xf0, 0x02, 0x50, 0x13, 0x00, 0x10, 0x3f, 0xc9, 0xd9, 0xe8, +0x49, 0xff, 0xff, 0x20, 0x44, 0xa0, 0x00, 0x24, 0x50, 0x73, 0x00, 0x24, 0x50, 0x9e, 0x02, 0x51, +0x50, 0x6f, 0x80, 0x1f, 0xd5, 0x3d, 0xf0, 0x03, 0xa4, 0x80, 0x98, 0x91, 0x5e, 0xf1, 0x01, 0x7e, +0xe8, 0x3d, 0xa6, 0xb8, 0x84, 0x65, 0x4c, 0x21, 0x80, 0x18, 0x44, 0x40, 0x00, 0x25, 0x4c, 0x22, +0x40, 0x2c, 0x84, 0x03, 0x4c, 0x10, 0x40, 0x29, 0x3e, 0x09, 0x4e, 0x7c, 0x49, 0xff, 0xe5, 0x88, +0xa7, 0xfb, 0x3e, 0x71, 0xde, 0x28, 0x49, 0xff, 0xee, 0x1f, 0x3e, 0x09, 0xdd, 0x9c, 0x49, 0xff, +0xe5, 0xcd, 0x84, 0x00, 0xd5, 0x24, 0xf1, 0x04, 0x84, 0x68, 0x4c, 0x11, 0xc0, 0x16, 0xf0, 0x02, +0x3e, 0x19, 0xdc, 0x29, 0x84, 0x46, 0x49, 0xff, 0xfe, 0xa5, 0xc8, 0x0e, 0x02, 0x1e, 0x01, 0x26, +0xb7, 0x3f, 0x80, 0x07, 0x80, 0x46, 0x50, 0x34, 0xff, 0xff, 0x50, 0x44, 0xff, 0xfd, 0x50, 0x54, +0xff, 0xfe, 0x49, 0xff, 0xfe, 0x49, 0xa6, 0x79, 0x9c, 0x4a, 0x99, 0xf9, 0x89, 0x41, 0xa6, 0x79, +0xf0, 0x05, 0x9c, 0x8a, 0x88, 0x4a, 0xe2, 0x02, 0xe8, 0xbf, 0x84, 0x01, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xe0, 0x44, 0x00, 0x00, 0x18, 0x50, 0x63, +0x80, 0x24, 0x10, 0x03, 0x80, 0x9e, 0x84, 0x20, 0x80, 0x06, 0x44, 0x20, 0x00, 0x18, 0x49, 0xfe, +0xbb, 0xed, 0xa6, 0x30, 0x84, 0x33, 0x40, 0x00, 0x04, 0x02, 0x58, 0x00, 0x00, 0x08, 0xae, 0x30, +0x2e, 0x11, 0xdd, 0xd5, 0x54, 0x00, 0x00, 0x0f, 0xc1, 0x05, 0x44, 0x4f, 0xff, 0x80, 0x40, 0x00, +0x10, 0x04, 0xae, 0x30, 0xa6, 0x31, 0x42, 0x00, 0x04, 0x09, 0x58, 0x00, 0x00, 0x01, 0xae, 0x31, +0x49, 0xff, 0xe9, 0xc0, 0x3e, 0x19, 0xd9, 0xe8, 0x00, 0x20, 0x83, 0xb0, 0x00, 0x03, 0x00, 0x16, +0x54, 0x21, 0x00, 0x0f, 0x94, 0x94, 0x54, 0x00, 0x00, 0x0f, 0x40, 0x00, 0x08, 0x04, 0x10, 0x03, +0x00, 0x16, 0xa6, 0xb1, 0x02, 0x30, 0x81, 0xd8, 0x92, 0x04, 0x94, 0x04, 0x44, 0x4f, 0xff, 0xdb, +0x40, 0x21, 0x10, 0x02, 0x92, 0x64, 0x10, 0x33, 0x00, 0x17, 0x10, 0x03, 0x00, 0x16, 0xae, 0xb1, +0x50, 0x10, 0x82, 0x41, 0x84, 0x46, 0x9c, 0x34, 0x49, 0xfe, 0xbb, 0x90, 0x3e, 0x19, 0xde, 0x10, +0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x49, 0xfe, 0xbb, 0x89, 0xa0, 0x79, 0x50, 0x03, 0x00, 0x10, +0x84, 0x46, 0x49, 0xfe, 0xbb, 0x83, 0x00, 0x03, 0x80, 0x94, 0xc0, 0x05, 0xa6, 0x31, 0x58, 0x00, +0x00, 0x40, 0xae, 0x31, 0x2e, 0x11, 0xde, 0x2a, 0xa6, 0x31, 0xc1, 0x04, 0x58, 0x00, 0x00, 0x10, +0xd5, 0x03, 0x42, 0x00, 0x10, 0x09, 0xae, 0x31, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0xc8, 0xcb, 0x0d, 0x3e, 0x49, 0xd9, 0xe8, 0x00, 0x22, +0x01, 0x70, 0xca, 0x02, 0xd5, 0x08, 0x00, 0x12, 0x01, 0x71, 0xc1, 0x04, 0x50, 0x42, 0x01, 0x30, +0xd5, 0x05, 0x84, 0x40, 0x80, 0x82, 0x44, 0x30, 0x00, 0xff, 0x14, 0x40, 0x00, 0x26, 0x10, 0x30, +0x00, 0x9c, 0x10, 0x20, 0x00, 0x94, 0x3e, 0x19, 0x50, 0x18, 0x3e, 0x09, 0x4e, 0xb8, 0x49, 0xff, +0xe4, 0xc7, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, 0x49, 0xfe, 0xbb, 0x5e, +0xa6, 0xf0, 0xa6, 0xb4, 0xa6, 0x31, 0x92, 0x02, 0x94, 0x02, 0x58, 0x21, 0x00, 0x01, 0x42, 0x11, +0x80, 0x09, 0xae, 0xb4, 0xae, 0x70, 0xae, 0x31, 0x00, 0x83, 0x00, 0x07, 0x00, 0x93, 0x80, 0x9d, +0xa7, 0x72, 0x10, 0x93, 0x00, 0x05, 0x00, 0x03, 0x80, 0x9e, 0xa0, 0x7b, 0x40, 0x74, 0x18, 0x09, +0x95, 0xfe, 0x98, 0x48, 0x96, 0x49, 0x40, 0x40, 0xa0, 0x09, 0xa6, 0x33, 0x54, 0x42, 0x00, 0x3f, +0x40, 0x73, 0x90, 0x04, 0x44, 0x4f, 0xff, 0xea, 0x40, 0x31, 0x90, 0x02, 0x54, 0x52, 0x80, 0x7f, +0x54, 0x21, 0x00, 0x03, 0x40, 0x40, 0x0c, 0x09, 0x95, 0x23, 0xae, 0x76, 0xaf, 0xf7, 0xaf, 0x72, +0xae, 0xf0, 0xae, 0xb4, 0xaf, 0x33, 0x3c, 0x1c, 0x77, 0x0f, 0xe6, 0x2f, 0xe9, 0x12, 0x3e, 0x09, +0x4e, 0xd4, 0x3e, 0x19, 0x50, 0x30, 0x49, 0xff, 0xe4, 0x7b, 0xa6, 0x72, 0xa6, 0x33, 0x92, 0x27, +0x94, 0x4f, 0x54, 0x00, 0x00, 0x1f, 0x58, 0x10, 0x80, 0x03, 0x58, 0x00, 0x00, 0x20, 0xd5, 0x04, +0x54, 0x00, 0x00, 0x18, 0x84, 0x23, 0xae, 0x33, 0xa6, 0x30, 0xae, 0x72, 0x54, 0x00, 0x00, 0x1d, +0xae, 0x30, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, 0x49, 0xfe, 0xba, 0xfe, +0xa6, 0xb0, 0xa6, 0xf4, 0xa6, 0x31, 0x84, 0x3e, 0x40, 0x41, 0x04, 0x02, 0x92, 0x02, 0x94, 0x02, +0x40, 0x11, 0x84, 0x02, 0xaf, 0x30, 0xae, 0x74, 0xae, 0x31, 0x00, 0x83, 0x00, 0x07, 0x00, 0x93, +0x80, 0x9d, 0xa7, 0x72, 0x10, 0x93, 0x00, 0x05, 0x00, 0x03, 0x80, 0x9e, 0xa0, 0x7b, 0x40, 0x74, +0x18, 0x09, 0x95, 0xfe, 0x98, 0x48, 0x96, 0x49, 0x40, 0x40, 0xa0, 0x09, 0xa6, 0x33, 0x54, 0x42, +0x00, 0x3f, 0x40, 0x73, 0x90, 0x04, 0x54, 0x31, 0x80, 0x02, 0x44, 0x4f, 0xff, 0xea, 0x40, 0x21, +0x10, 0x02, 0x54, 0x52, 0x80, 0x7f, 0x58, 0x31, 0x80, 0x1c, 0x40, 0x40, 0x0c, 0x09, 0x95, 0x23, +0xae, 0x76, 0xaf, 0xf7, 0xaf, 0x72, 0xae, 0xb0, 0xae, 0xf4, 0xaf, 0x33, 0x3c, 0x1c, 0x77, 0x0f, +0xe6, 0x2f, 0xe9, 0x10, 0x3e, 0x09, 0x4e, 0xe4, 0x3e, 0x19, 0x50, 0x44, 0x49, 0xff, 0xe4, 0x18, +0xa6, 0x33, 0xa6, 0x72, 0x54, 0x00, 0x00, 0x1f, 0x92, 0x27, 0x94, 0x4f, 0x58, 0x00, 0x00, 0x20, +0xd5, 0x04, 0x54, 0x00, 0x00, 0x18, 0x84, 0x20, 0xae, 0x33, 0xa6, 0x30, 0xae, 0x72, 0x54, 0x00, +0x00, 0x1d, 0xae, 0x30, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0xc2, 0x12, 0xa6, 0x11, 0x96, 0x44, 0xc9, 0x0f, 0x54, 0x10, 0x00, 0x02, 0xc1, 0x04, +0x3e, 0x09, 0x4e, 0xf4, 0xd5, 0x07, 0x54, 0x00, 0x00, 0x04, 0x96, 0x00, 0xc0, 0x06, 0x3e, 0x09, +0x4f, 0x00, 0x49, 0xff, 0xe3, 0xed, 0x84, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x84, 0x61, 0x80, 0xe0, 0x3e, 0x31, 0x8a, 0x53, 0x3e, 0x09, +0xd9, 0xe8, 0x80, 0x27, 0x49, 0xff, 0xe0, 0x90, 0x80, 0xc0, 0xc8, 0x0a, 0xb4, 0x27, 0x3e, 0x09, +0xd3, 0x00, 0x49, 0xff, 0xe5, 0xad, 0x3e, 0x09, 0x4f, 0x0c, 0x49, 0xff, 0xe3, 0xd1, 0x80, 0x06, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0x81, 0x01, +0x80, 0xe2, 0x50, 0x9f, 0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x81, 0x43, +0x49, 0xfe, 0xba, 0x64, 0x84, 0x80, 0x80, 0x28, 0x80, 0x47, 0x84, 0x61, 0x80, 0x09, 0xf4, 0x83, +0xf4, 0x82, 0x10, 0x3f, 0x80, 0x9d, 0xb7, 0x5f, 0x14, 0x8f, 0x80, 0x01, 0x49, 0xfe, 0xba, 0x36, +0x96, 0xb8, 0x40, 0x04, 0x88, 0x00, 0x9c, 0xc3, 0x92, 0x62, 0x94, 0xda, 0x9a, 0xd8, 0x80, 0x3f, +0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, 0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, 0x49, 0xff, 0xfe, 0xe0, +0x80, 0x1f, 0x49, 0xff, 0xff, 0xb7, 0x80, 0xdf, 0x84, 0x01, 0xec, 0xa0, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x5c, 0x81, 0x21, 0x81, 0x02, 0x50, 0xaf, +0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x83, 0x83, 0x84, 0xe0, 0x49, 0xfe, +0xba, 0x2d, 0x80, 0x29, 0x80, 0x48, 0x84, 0x7f, 0x80, 0x0a, 0x10, 0x3f, 0x80, 0x9d, 0x15, 0xcf, +0x80, 0x00, 0xf7, 0x82, 0xf7, 0x83, 0x14, 0x9f, 0x80, 0x01, 0x49, 0xfe, 0xb9, 0xff, 0x54, 0x24, +0x00, 0xff, 0x40, 0x05, 0x08, 0x00, 0x9c, 0xc3, 0x92, 0x62, 0x94, 0xda, 0x9a, 0xd8, 0x80, 0x3f, +0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, 0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, 0x49, 0xff, 0xfe, 0xa8, +0x80, 0x1f, 0x49, 0xff, 0xff, 0x7f, 0x40, 0x03, 0x80, 0x06, 0x80, 0xdf, 0xec, 0xa4, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0x81, 0x01, 0x80, 0xe2, 0x50, 0x9f, +0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x81, 0x43, 0x49, 0xfe, 0xb9, 0xf6, +0x84, 0x80, 0x80, 0x28, 0x80, 0x47, 0x84, 0x7f, 0x80, 0x09, 0xf4, 0x83, 0xf4, 0x82, 0x10, 0x3f, +0x80, 0x9d, 0xb7, 0x5f, 0x14, 0x8f, 0x80, 0x01, 0x49, 0xfe, 0xb9, 0xc8, 0x96, 0xb8, 0x40, 0x04, +0x88, 0x00, 0x9c, 0xc3, 0x92, 0x62, 0x94, 0xda, 0x9a, 0xd8, 0x80, 0x3f, 0x50, 0x0f, 0x80, 0x10, +0x10, 0x3f, 0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, 0x49, 0xff, 0xfe, 0xd2, 0x80, 0x1f, 0x49, 0xff, +0xff, 0x49, 0x80, 0xdf, 0x84, 0x01, 0xec, 0xa0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0xa1, 0xc2, 0x81, 0x00, 0x40, 0x90, 0x80, 0x13, 0x54, 0xa1, +0x00, 0xff, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x49, 0xfe, 0xb9, 0xbf, 0x50, 0x24, +0xff, 0xf2, 0x80, 0x2a, 0x50, 0x33, 0x80, 0x0e, 0x80, 0x1f, 0xf2, 0x83, 0x84, 0x41, 0x10, 0x2f, +0x80, 0x9d, 0xf3, 0x82, 0xb7, 0x1f, 0xf7, 0x81, 0x49, 0xff, 0xfe, 0x24, 0x80, 0x1f, 0x49, 0xff, +0xfd, 0xb3, 0x00, 0x1f, 0x80, 0x9e, 0x2e, 0x01, 0xdd, 0xd5, 0x50, 0x2f, 0x80, 0x24, 0x98, 0x51, +0xc0, 0x0a, 0x84, 0x00, 0xae, 0x09, 0xae, 0x08, 0x9c, 0x4a, 0x00, 0x0f, 0x80, 0x9e, 0x9c, 0x02, +0x10, 0x0f, 0x80, 0x9e, 0x9d, 0xcb, 0x92, 0xe2, 0x95, 0xfa, 0x9a, 0xf9, 0x10, 0x3f, 0x80, 0x9f, +0x3e, 0x19, 0x87, 0x58, 0x84, 0x46, 0x80, 0x07, 0x49, 0xfe, 0xb9, 0x70, 0xf1, 0x01, 0x9c, 0x3e, +0x8c, 0x2c, 0x84, 0x42, 0x49, 0xfe, 0xb9, 0x6a, 0x00, 0x2f, 0x80, 0x9e, 0x80, 0x3f, 0x8c, 0x48, +0x50, 0x0f, 0x80, 0x10, 0x10, 0x2f, 0x80, 0x9e, 0x49, 0xff, 0xfe, 0x1a, 0x80, 0x1f, 0x49, 0xff, +0xfe, 0xf1, 0x92, 0x00, 0x80, 0xdf, 0x84, 0x00, 0xec, 0xa0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xec, 0x3e, 0x79, 0xd9, 0xe8, 0x00, 0x13, 0x82, 0x5c, 0x80, 0xc0, +0xc1, 0x2d, 0xa0, 0x42, 0x84, 0x46, 0x50, 0x03, 0x82, 0x41, 0x8c, 0x2a, 0x49, 0xff, 0xfb, 0xf2, +0xc8, 0x25, 0xa0, 0x72, 0x44, 0x50, 0x00, 0xa0, 0xa6, 0x48, 0x54, 0x10, 0x80, 0xf0, 0xd9, 0x0c, +0x04, 0x13, 0x80, 0x99, 0x54, 0x10, 0x88, 0x00, 0xc1, 0x07, 0x80, 0x20, 0x80, 0x46, 0x44, 0x00, +0x01, 0x00, 0x49, 0xff, 0xec, 0x11, 0xa0, 0x32, 0x44, 0x50, 0x00, 0xc0, 0xa6, 0x00, 0x54, 0x00, +0x00, 0xf0, 0xd8, 0x0c, 0x3c, 0x0c, 0x77, 0x13, 0x54, 0x00, 0x08, 0x00, 0xc0, 0x07, 0x44, 0x00, +0x02, 0x00, 0x84, 0x20, 0x80, 0x46, 0x49, 0xff, 0xeb, 0xff, 0xa0, 0x72, 0x44, 0x50, 0x00, 0x80, +0xa6, 0x08, 0x54, 0x00, 0x00, 0xf0, 0x4c, 0x02, 0xc0, 0xa2, 0x8c, 0x2a, 0x3e, 0x09, 0xdc, 0x29, +0x84, 0x46, 0x49, 0xff, 0xfb, 0xbf, 0x4e, 0x03, 0x00, 0x9a, 0x49, 0xff, 0xfb, 0xd7, 0x3e, 0x79, +0xd9, 0xe8, 0x14, 0x03, 0x80, 0x92, 0x80, 0x5f, 0xa0, 0x34, 0x02, 0x13, 0x00, 0x0a, 0x50, 0x3f, +0x80, 0x08, 0x50, 0x4f, 0x80, 0x0e, 0x49, 0xff, 0xfc, 0xbd, 0x4e, 0x02, 0x00, 0xcb, 0x2e, 0x51, +0xde, 0x18, 0x84, 0x41, 0xda, 0x24, 0x2e, 0x01, 0xde, 0x1d, 0xc8, 0x21, 0x02, 0x03, 0x81, 0x28, +0xc0, 0x11, 0x00, 0x53, 0x84, 0x1c, 0xda, 0x0e, 0x00, 0x03, 0x82, 0x51, 0xc0, 0x0b, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0x25, 0x3e, 0x09, 0x4f, 0x2c, 0x49, 0xff, 0xe2, 0x61, 0x49, 0xff, +0xe9, 0x4f, 0x3e, 0x09, 0xde, 0x18, 0x84, 0x20, 0x84, 0x41, 0xae, 0x43, 0x3e, 0x21, 0x8a, 0x57, +0x2e, 0x21, 0xdc, 0x38, 0x2e, 0x11, 0xdc, 0x39, 0xae, 0x81, 0xae, 0x42, 0x3e, 0x09, 0xde, 0x18, +0xb4, 0x20, 0x40, 0x50, 0xa0, 0x08, 0x92, 0xa8, 0x84, 0x41, 0xda, 0x58, 0xa6, 0x45, 0xc9, 0x56, +0xa6, 0x04, 0x4c, 0x01, 0x00, 0x94, 0x84, 0xa2, 0xd8, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x10, +0x84, 0xa3, 0xd0, 0x0c, 0x84, 0xa4, 0xd0, 0x0a, 0x56, 0x30, 0x00, 0x05, 0x44, 0x20, 0x13, 0x88, +0x40, 0x00, 0x8c, 0x1b, 0x40, 0x01, 0x0c, 0x1a, 0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x2e, 0x21, +0xde, 0x2b, 0xca, 0x07, 0x2e, 0x21, 0xdc, 0x36, 0xca, 0x13, 0x2e, 0x21, 0xdc, 0x37, 0xd5, 0x10, +0x2e, 0x11, 0xde, 0x2c, 0xe6, 0x25, 0xe9, 0x03, 0x84, 0x63, 0xd5, 0x5c, 0x5c, 0x50, 0x80, 0x03, +0x84, 0x41, 0x84, 0x82, 0x40, 0x32, 0x14, 0x1a, 0x40, 0x31, 0x14, 0x1b, 0xd5, 0x53, 0x46, 0x10, +0x04, 0x11, 0x04, 0x70, 0x80, 0x49, 0x3c, 0x3c, 0x77, 0x89, 0x95, 0xfe, 0x44, 0x10, 0x03, 0xe8, +0x42, 0x11, 0x84, 0x24, 0x50, 0x73, 0xec, 0x78, 0x9b, 0xf8, 0x9e, 0x91, 0x42, 0x70, 0x88, 0x73, +0x46, 0x10, 0x04, 0x00, 0x46, 0x00, 0x04, 0x11, 0x04, 0x10, 0x80, 0x25, 0x04, 0x30, 0x00, 0x49, +0x80, 0x47, 0x3e, 0x09, 0x4f, 0x4c, 0x49, 0xff, 0xe1, 0xfb, 0x5e, 0xf3, 0xae, 0xe1, 0xe9, 0x06, +0x2e, 0x01, 0xde, 0x1c, 0x80, 0x27, 0x49, 0x00, 0x16, 0xa1, 0x3e, 0x79, 0xd9, 0xe8, 0x04, 0x03, +0x80, 0x99, 0x40, 0x00, 0x3c, 0x08, 0x92, 0x1f, 0xc0, 0x3c, 0xa0, 0x32, 0x44, 0x50, 0x00, 0xd0, +0xa6, 0x00, 0x54, 0x00, 0x00, 0xf0, 0xd8, 0x35, 0xa0, 0x34, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, +0x00, 0x19, 0xc9, 0x0f, 0x84, 0x24, 0x4c, 0x00, 0xc0, 0x2d, 0x3e, 0x09, 0x4f, 0x78, 0x49, 0xff, +0xe1, 0xd7, 0x49, 0xff, 0xea, 0x71, 0x50, 0x03, 0x83, 0xb4, 0x49, 0xff, 0xe2, 0x1f, 0xd5, 0x21, +0x84, 0xa3, 0xd9, 0x1f, 0xc8, 0x1e, 0x80, 0x06, 0x44, 0x10, 0x00, 0x25, 0x49, 0xff, 0xfb, 0x8a, +0xd5, 0x18, 0x46, 0x20, 0x04, 0x11, 0x3c, 0x4c, 0x77, 0x89, 0x04, 0x71, 0x00, 0x49, 0x44, 0x20, +0x03, 0xe8, 0x42, 0x22, 0x08, 0x24, 0x9e, 0x49, 0x95, 0xfe, 0x42, 0x71, 0x04, 0x73, 0x9b, 0xf8, +0x44, 0x0f, 0xec, 0x78, 0x42, 0x71, 0x80, 0x73, 0xd5, 0xac, 0x84, 0x02, 0x48, 0xff, 0xff, 0x81, +0xec, 0x14, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x2e, 0x11, 0xdc, 0x44, +0x80, 0xc0, 0xc1, 0x03, 0x49, 0xff, 0xec, 0xc8, 0x2e, 0x01, 0xdd, 0x88, 0x84, 0xa1, 0x4c, 0x02, +0x80, 0xb1, 0x3e, 0x19, 0xde, 0x18, 0xa6, 0x08, 0x4e, 0x02, 0x00, 0xac, 0xa6, 0x0d, 0x84, 0xa1, +0x4c, 0x02, 0x80, 0xa8, 0xb4, 0x06, 0xa6, 0x00, 0x54, 0x20, 0x00, 0x60, 0xca, 0x0e, 0x54, 0x00, +0x00, 0x10, 0xc0, 0x0b, 0xa0, 0x32, 0xa6, 0x01, 0x54, 0x00, 0x00, 0x20, 0x96, 0x00, 0xc0, 0x04, +0x49, 0xff, 0xe8, 0x76, 0xd5, 0x02, 0xae, 0x0a, 0x2e, 0x01, 0xdc, 0x39, 0xc0, 0x04, 0x2e, 0x01, +0xde, 0x1a, 0xc8, 0x04, 0x2e, 0x01, 0xde, 0x19, 0xc0, 0x0a, 0x84, 0x40, 0x3e, 0x21, 0xde, 0x1b, +0x84, 0x41, 0x3e, 0x09, 0x4f, 0xa0, 0x3e, 0x21, 0x8a, 0x57, 0xd5, 0x06, 0x84, 0x41, 0x3e, 0x21, +0xde, 0x1b, 0x3e, 0x09, 0x4f, 0xbc, 0x49, 0xff, 0xe1, 0x6b, 0x3e, 0x09, 0xde, 0x18, 0xb4, 0x20, +0x46, 0x2f, 0xf0, 0x00, 0x58, 0x21, 0x00, 0xff, 0x40, 0x50, 0x88, 0x02, 0x46, 0x20, 0x10, 0x00, +0x58, 0x21, 0x00, 0x01, 0xda, 0x6e, 0xa6, 0x45, 0xc9, 0x6c, 0xa6, 0x04, 0x84, 0xa1, 0xd0, 0x67, +0x84, 0xa2, 0xd8, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x10, 0x84, 0xa3, 0xd0, 0x0c, 0x84, 0xa4, +0xd0, 0x0a, 0x56, 0x30, 0x00, 0x05, 0x44, 0x20, 0x13, 0x88, 0x40, 0x00, 0x8c, 0x1b, 0x40, 0x01, +0x0c, 0x1a, 0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x2e, 0x21, 0xde, 0x2b, 0xca, 0x07, 0x2e, 0x21, +0xdc, 0x36, 0xca, 0x13, 0x2e, 0x21, 0xdc, 0x37, 0xd5, 0x10, 0x2e, 0x11, 0xde, 0x2c, 0xe6, 0x25, +0xe9, 0x03, 0x84, 0x63, 0xd5, 0x30, 0x5c, 0x50, 0x80, 0x03, 0x84, 0x41, 0x84, 0x82, 0x40, 0x32, +0x14, 0x1a, 0x40, 0x31, 0x14, 0x1b, 0xd5, 0x27, 0x46, 0x10, 0x04, 0x11, 0x04, 0x60, 0x80, 0x49, +0x3c, 0x3c, 0x77, 0x89, 0x95, 0xb6, 0x44, 0x10, 0x03, 0xe8, 0x42, 0x11, 0x84, 0x24, 0x50, 0x63, +0x6c, 0x78, 0x9b, 0xb0, 0x9e, 0x91, 0x42, 0x60, 0x88, 0x73, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, +0x00, 0x25, 0x80, 0x46, 0x3e, 0x09, 0x4f, 0xd8, 0x49, 0xff, 0xe1, 0x12, 0x5e, 0xf3, 0x2e, 0xe1, +0xe9, 0x20, 0x84, 0x61, 0x2e, 0x01, 0xde, 0x1c, 0x3e, 0x31, 0xde, 0x2a, 0x80, 0x26, 0x49, 0x00, +0x15, 0xb5, 0xd5, 0x17, 0x46, 0x20, 0x04, 0x11, 0x3c, 0x4c, 0x77, 0x89, 0x04, 0x61, 0x00, 0x49, +0x44, 0x20, 0x03, 0xe8, 0x42, 0x22, 0x08, 0x24, 0x9e, 0x49, 0x95, 0xb6, 0x42, 0x61, 0x04, 0x73, +0x9b, 0xb0, 0x44, 0x0f, 0xec, 0x78, 0x42, 0x61, 0x80, 0x73, 0xd5, 0xd8, 0x84, 0x02, 0xd5, 0xad, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe0, 0xa4, 0x46, +0x81, 0x20, 0x5c, 0xf0, 0x80, 0x38, 0xe8, 0x06, 0x3e, 0x09, 0x4f, 0xf8, 0x49, 0xff, 0xe0, 0xe0, +0xd5, 0x16, 0x04, 0x80, 0x00, 0x02, 0x50, 0x64, 0x00, 0x04, 0xa6, 0xf7, 0x50, 0x74, 0x00, 0x20, +0x92, 0x65, 0x80, 0x26, 0x80, 0x07, 0x80, 0x48, 0x3e, 0x31, 0xde, 0x05, 0x49, 0xff, 0xfc, 0xd0, +0x84, 0xa1, 0xd8, 0x07, 0x3e, 0x09, 0x50, 0x00, 0x49, 0xff, 0xe0, 0xca, 0x84, 0x00, 0xd5, 0x2d, +0x50, 0x0f, 0x80, 0x04, 0xb7, 0x00, 0x14, 0x90, 0x00, 0x03, 0xa9, 0x81, 0xa9, 0xc2, 0xa9, 0xc4, +0x2e, 0x21, 0xdd, 0x88, 0xa6, 0x73, 0xa6, 0xf2, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0xa0, 0x08, +0x40, 0x10, 0x8c, 0x04, 0x84, 0xa1, 0xda, 0x02, 0xd5, 0xea, 0x12, 0x10, 0x00, 0x0a, 0x84, 0x20, +0x12, 0x10, 0x00, 0x0b, 0xa6, 0x78, 0x92, 0x22, 0x54, 0x10, 0x80, 0x03, 0xc1, 0x06, 0x84, 0xa2, +0xd9, 0x07, 0x49, 0xff, 0xfe, 0xfb, 0xd5, 0x08, 0x49, 0xff, 0xfd, 0xd4, 0xd5, 0x05, 0x3e, 0x09, +0x50, 0x14, 0x49, 0xff, 0xe0, 0x9d, 0x84, 0x01, 0xec, 0x20, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0x3c, 0x96, 0x00, 0x96, 0x48, 0x95, 0x02, 0x44, 0x32, 0x0d, 0x60, 0x99, 0x21, +0x99, 0x23, 0x00, 0x31, 0x00, 0x40, 0x95, 0x25, 0x84, 0xa0, 0x38, 0x71, 0x14, 0x00, 0x99, 0xac, +0xaf, 0xf0, 0x9d, 0x69, 0x44, 0x60, 0x00, 0x10, 0xde, 0xf9, 0x99, 0x66, 0x84, 0xd0, 0x4c, 0x23, +0x00, 0x0a, 0x50, 0x72, 0x00, 0x18, 0x9b, 0x94, 0x38, 0x83, 0x14, 0x00, 0x18, 0x82, 0x80, 0x01, +0xdf, 0xfc, 0x44, 0x5f, 0xff, 0xe8, 0xd2, 0x0b, 0x9a, 0x94, 0x50, 0x52, 0x00, 0x18, 0x50, 0x42, +0x00, 0x20, 0x38, 0x61, 0x14, 0x00, 0x18, 0x62, 0x80, 0x01, 0xdc, 0xfc, 0x46, 0x60, 0x01, 0x06, +0x40, 0x20, 0x04, 0x09, 0x58, 0x63, 0x0c, 0x00, 0x98, 0x96, 0x94, 0x92, 0x97, 0x04, 0xb4, 0x02, +0xcc, 0x22, 0xc9, 0x05, 0x54, 0x31, 0x80, 0x0f, 0x84, 0x30, 0xd5, 0x13, 0x84, 0x81, 0x4c, 0x12, +0x40, 0x08, 0x54, 0x31, 0x80, 0x0f, 0x94, 0xdc, 0x44, 0x5f, 0xff, 0x0f, 0xd5, 0x35, 0x84, 0xc2, +0x54, 0x31, 0x80, 0x0f, 0x4c, 0x13, 0x40, 0x09, 0x40, 0x31, 0xa0, 0x08, 0x44, 0x1f, 0xf0, 0xff, +0x40, 0x00, 0x04, 0x02, 0xd5, 0x30, 0x44, 0x4f, 0x0f, 0xff, 0x40, 0x31, 0xb0, 0x08, 0x40, 0x00, +0x10, 0x02, 0xd5, 0x29, 0xc9, 0x0a, 0x54, 0x31, 0x80, 0x0f, 0x46, 0x5f, 0xff, 0x0f, 0x40, 0x31, +0xc0, 0x08, 0x58, 0x52, 0x8f, 0xff, 0xd5, 0x18, 0x84, 0xc1, 0x4c, 0x13, 0x40, 0x0b, 0x54, 0x31, +0x80, 0x0f, 0x46, 0x1f, 0xf0, 0xff, 0x40, 0x31, 0xd0, 0x08, 0x58, 0x10, 0x8f, 0xff, 0xd5, 0xe1, +0x84, 0x82, 0x4c, 0x12, 0x40, 0x0d, 0x54, 0x31, 0x80, 0x0f, 0x46, 0x5f, 0x0f, 0xff, 0x40, 0x31, +0xe0, 0x08, 0x58, 0x52, 0x8f, 0xff, 0x40, 0x00, 0x14, 0x02, 0xd5, 0x05, 0x40, 0x31, 0xf0, 0x08, +0x94, 0x04, 0x92, 0x04, 0x40, 0x00, 0x0c, 0x04, 0xb6, 0x02, 0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x02, 0x10, 0x00, 0x0a, 0xa1, 0xc4, 0x5c, 0xf0, 0x80, 0x66, +0xe9, 0x2b, 0x50, 0x10, 0xff, 0x9a, 0xf1, 0x81, 0x84, 0xc0, 0x47, 0xc0, 0x00, 0x80, 0x59, 0xce, +0x09, 0x4c, 0x80, 0x07, 0x3e, 0x19, 0x87, 0x78, 0x84, 0x46, 0x49, 0xff, 0xf9, 0x2b, 0x81, 0x20, +0xc8, 0x16, 0x3e, 0x09, 0x50, 0x6c, 0x80, 0x26, 0xdd, 0x3c, 0x50, 0x83, 0x80, 0x06, 0x80, 0x08, +0x3e, 0x19, 0xde, 0x10, 0x84, 0x46, 0x8d, 0x21, 0x49, 0xff, 0xf9, 0x1c, 0xc8, 0x09, 0x44, 0x50, +0x00, 0x10, 0x8d, 0x06, 0x4c, 0x92, 0xff, 0xf5, 0x84, 0x01, 0xd5, 0x07, 0x9d, 0xf9, 0xf0, 0x01, +0x9d, 0xb1, 0xe2, 0x06, 0xe8, 0xdf, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x97, 0x20, 0x96, 0x48, 0x81, 0x25, 0x97, 0xc0, 0x54, 0x81, +0x00, 0xff, 0xf4, 0x81, 0xc9, 0x52, 0xe7, 0x04, 0xe8, 0x50, 0x44, 0x20, 0x00, 0x43, 0x42, 0x64, +0x08, 0x24, 0x3e, 0x09, 0xdb, 0x18, 0x99, 0xb0, 0x80, 0x06, 0x49, 0xfe, 0xb6, 0x67, 0x84, 0x24, +0x4c, 0x70, 0xc0, 0x04, 0x84, 0x03, 0xd5, 0x0a, 0x84, 0x06, 0x4c, 0x70, 0x40, 0x04, 0x84, 0x04, +0xd5, 0x05, 0x84, 0x2b, 0x4c, 0x70, 0xc0, 0x05, 0x84, 0x02, 0x10, 0x03, 0x00, 0x40, 0x00, 0x23, +0x00, 0x40, 0x3e, 0x09, 0x50, 0x90, 0x3e, 0x19, 0x51, 0x34, 0x84, 0x60, 0x80, 0x88, 0x49, 0xff, +0xdf, 0xa7, 0x44, 0x30, 0x00, 0x10, 0x10, 0x33, 0x00, 0x41, 0x80, 0x29, 0x44, 0x75, 0xb6, 0x6c, +0x80, 0x06, 0x80, 0x43, 0xdd, 0x27, 0x00, 0x03, 0x00, 0x40, 0x84, 0x23, 0x4c, 0x00, 0xc0, 0x18, +0xf1, 0x01, 0x51, 0xc4, 0x80, 0x18, 0x50, 0x03, 0x00, 0x10, 0x8d, 0x30, 0x50, 0xa3, 0x00, 0x18, +0xc1, 0x07, 0x80, 0x29, 0x84, 0x48, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x3c, 0xd5, 0x06, 0x80, 0x3c, +0x84, 0x48, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x29, 0x84, 0x48, 0xdd, 0x27, 0x80, 0x28, 0x80, 0x46, +0x84, 0x00, 0x49, 0xff, 0xfe, 0xe7, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x44, 0x60, 0x01, 0x0c, 0x96, 0x00, 0x42, 0x60, 0x18, 0x24, 0x3e, 0x09, +0xdb, 0x18, 0x99, 0xb0, 0x44, 0x20, 0x00, 0x43, 0x81, 0x01, 0x80, 0x06, 0x84, 0x20, 0x49, 0xfe, +0xb6, 0x0d, 0x2e, 0x21, 0xdc, 0x25, 0x84, 0xa4, 0xda, 0x03, 0x84, 0x03, 0xd5, 0x04, 0x84, 0xa6, +0xda, 0x05, 0x84, 0x04, 0x10, 0x03, 0x00, 0x40, 0xd5, 0x08, 0x3e, 0x09, 0x50, 0xbc, 0x3e, 0x19, +0x51, 0x48, 0x49, 0xff, 0xdf, 0x55, 0xd5, 0x1d, 0x44, 0x30, 0x00, 0x10, 0x10, 0x33, 0x00, 0x41, +0x50, 0x14, 0x00, 0x20, 0x80, 0x06, 0x80, 0x43, 0x49, 0xfe, 0xb5, 0xda, 0x00, 0x03, 0x00, 0x40, +0x84, 0xa3, 0xd8, 0x0f, 0x50, 0x14, 0x00, 0x38, 0x84, 0x48, 0x50, 0x03, 0x00, 0x10, 0x49, 0xfe, +0xb5, 0xcf, 0x50, 0x03, 0x00, 0x18, 0x50, 0x14, 0x00, 0x30, 0x84, 0x48, 0x49, 0xfe, 0xb5, 0xc8, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x50, 0x9f, +0x80, 0x08, 0x80, 0xe0, 0x55, 0xc0, 0x80, 0xff, 0x54, 0x81, 0x00, 0xff, 0x54, 0xa2, 0x00, 0xff, +0x80, 0x09, 0x84, 0x20, 0x44, 0x20, 0x00, 0x20, 0x97, 0x98, 0x49, 0xfe, 0xb5, 0xc7, 0x4e, 0xa2, +0x00, 0x45, 0x84, 0x03, 0x4c, 0x60, 0x00, 0x05, 0x84, 0x25, 0x4c, 0x60, 0xc0, 0x4c, 0x85, 0x40, +0x81, 0x0a, 0x81, 0x2a, 0x50, 0x6f, 0x80, 0x08, 0xd5, 0x31, 0xa6, 0x38, 0x44, 0x30, 0x00, 0xdd, +0x4c, 0x01, 0xc0, 0x27, 0x9c, 0x3a, 0x3e, 0x19, 0x87, 0x54, 0x84, 0x43, 0x49, 0xff, 0xf8, 0x3a, +0x80, 0x60, 0xc8, 0x1e, 0xa6, 0x3d, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x1b, 0x00, 0x93, 0x80, 0x01, +0x00, 0x83, 0x80, 0x06, 0x8f, 0x26, 0x54, 0x94, 0x80, 0xff, 0x50, 0x13, 0x80, 0x08, 0x80, 0x06, +0x80, 0x49, 0x54, 0x84, 0x00, 0x03, 0xe7, 0x30, 0xe8, 0x09, 0x3e, 0x09, 0x50, 0xe0, 0x80, 0x29, +0xf3, 0x81, 0x49, 0xff, 0xde, 0xed, 0xf0, 0x01, 0xd5, 0x36, 0x49, 0xfe, 0xb5, 0x79, 0xa6, 0x39, +0x9c, 0x02, 0x89, 0x40, 0x99, 0xf8, 0x54, 0xa5, 0x00, 0xff, 0xa6, 0x39, 0x9c, 0x02, 0x88, 0x0a, +0x40, 0xfe, 0x00, 0x07, 0xe8, 0xcb, 0xd5, 0x0a, 0x84, 0x05, 0x4c, 0x60, 0x40, 0x0c, 0x80, 0x09, +0x80, 0x27, 0x80, 0x5c, 0x49, 0xfe, 0xb5, 0x64, 0x81, 0x3c, 0xe7, 0x04, 0xe9, 0x05, 0x84, 0x00, +0xd5, 0x1a, 0x85, 0x00, 0x81, 0x28, 0x3e, 0x69, 0xd9, 0xe8, 0x80, 0x49, 0x50, 0x1f, 0x80, 0x08, +0x50, 0x03, 0x01, 0x10, 0x49, 0xfe, 0xb5, 0x54, 0x84, 0x20, 0x00, 0x03, 0x02, 0x3e, 0x10, 0x83, +0x02, 0x3c, 0x80, 0x48, 0x50, 0x53, 0x01, 0x10, 0x80, 0x61, 0x80, 0x81, 0x49, 0xff, 0xfe, 0xe2, +0x92, 0x00, 0x84, 0x01, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x94, 0x85, 0x40, 0x80, 0xc2, 0x55, 0xc0, 0x00, 0xff, 0x44, 0x00, 0x02, 0x00, 0x81, 0x21, +0x14, 0xaf, 0x80, 0x19, 0x49, 0xff, 0xf7, 0xe4, 0xa6, 0xb2, 0xa6, 0x73, 0x40, 0x21, 0x20, 0x08, +0x40, 0x21, 0x04, 0x04, 0x9c, 0x94, 0x50, 0x1f, 0x80, 0x64, 0x80, 0x66, 0x84, 0x9f, 0x50, 0x8f, +0x80, 0x54, 0x80, 0xe0, 0x49, 0xff, 0xf7, 0xec, 0x80, 0x2a, 0x80, 0x08, 0x44, 0x20, 0x00, 0x10, +0x49, 0xfe, 0xb5, 0x34, 0x84, 0x02, 0x4d, 0xc0, 0x40, 0x14, 0x50, 0xaf, 0x80, 0x04, 0xf3, 0x19, +0x80, 0x09, 0x80, 0x47, 0x80, 0x8a, 0x44, 0x50, 0x00, 0x14, 0x9e, 0x6c, 0x49, 0x00, 0x06, 0xbc, +0x80, 0x08, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xb5, 0x0a, 0xd5, 0x0a, 0x44, 0x10, +0x00, 0x10, 0xf3, 0x19, 0x80, 0x09, 0x80, 0x88, 0x80, 0x47, 0x80, 0xa1, 0x49, 0x00, 0x06, 0x2c, +0x50, 0x1f, 0x80, 0x54, 0x44, 0x20, 0x00, 0x10, 0x50, 0x03, 0x00, 0x51, 0x49, 0xfe, 0xb4, 0xf8, +0x80, 0x07, 0x49, 0xff, 0xf7, 0xad, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0xf6, 0x0c, 0x2e, 0x81, 0xdc, 0x27, 0x84, 0x01, 0xae, 0x30, +0x84, 0x03, 0xae, 0x31, 0x84, 0x00, 0xae, 0x32, 0x44, 0x00, 0x00, 0x5f, 0xae, 0x33, 0x83, 0x83, +0xf4, 0x81, 0x97, 0xc8, 0x96, 0x90, 0x4e, 0x82, 0x00, 0x04, 0x84, 0x02, 0xd5, 0x02, 0x84, 0x1e, +0xae, 0x34, 0x2e, 0x11, 0xdc, 0x28, 0xc1, 0x03, 0x85, 0x23, 0xd5, 0x0b, 0x2e, 0x31, 0xdc, 0x25, +0x84, 0x22, 0x56, 0x31, 0x80, 0x06, 0x84, 0x01, 0x40, 0x90, 0x8c, 0x1a, 0x40, 0x90, 0x0c, 0x1b, +0xa6, 0x36, 0x92, 0x03, 0x94, 0x03, 0x40, 0x00, 0x24, 0x04, 0xae, 0x36, 0xe6, 0xe5, 0xe9, 0x04, +0x42, 0x00, 0x0c, 0x09, 0xd5, 0x03, 0x58, 0x00, 0x00, 0x08, 0xae, 0x36, 0x4e, 0x83, 0x00, 0x12, +0xe6, 0xe5, 0xe9, 0x0f, 0xa6, 0x76, 0x54, 0x01, 0x00, 0x03, 0x44, 0x3f, 0xff, 0xcf, 0x94, 0x04, +0x40, 0x20, 0x8c, 0x02, 0x40, 0x21, 0x00, 0x04, 0x84, 0xa3, 0xae, 0xb6, 0xdf, 0x0b, 0xd5, 0x0c, +0x84, 0xa3, 0xdf, 0x06, 0xa6, 0x36, 0x58, 0x00, 0x00, 0x40, 0xae, 0x36, 0xd5, 0x05, 0x84, 0xa1, +0xd7, 0x03, 0x84, 0xa5, 0xdf, 0x09, 0xa6, 0x36, 0x44, 0x1f, 0xff, 0x80, 0x40, 0x00, 0x04, 0x04, +0x84, 0xa1, 0xae, 0x36, 0xd7, 0x05, 0xa6, 0x35, 0x58, 0x00, 0x00, 0x01, 0xae, 0x35, 0x4e, 0x82, +0x00, 0x05, 0xe6, 0xe3, 0xe8, 0x04, 0xd5, 0x0b, 0xe6, 0xe5, 0xe9, 0x18, 0xa6, 0x35, 0x58, 0x00, +0x00, 0x02, 0xae, 0x35, 0x4e, 0x82, 0x00, 0x13, 0x84, 0xa3, 0xd7, 0x03, 0x84, 0xa5, 0xdf, 0x05, +0xa6, 0x35, 0x58, 0x00, 0x00, 0x10, 0xae, 0x35, 0x4e, 0x82, 0x00, 0x09, 0x84, 0xa1, 0xd7, 0x03, +0x84, 0xa3, 0xdf, 0x18, 0x3e, 0x09, 0xd9, 0xe8, 0xd5, 0x08, 0x3e, 0x09, 0xd9, 0xe8, 0xe6, 0xe5, +0xe9, 0x04, 0x00, 0x30, 0x02, 0x3e, 0xd5, 0x03, 0x00, 0x30, 0x02, 0x3d, 0x56, 0x31, 0x80, 0x04, +0x44, 0x10, 0x00, 0x10, 0x94, 0x89, 0x40, 0x01, 0x0c, 0x1a, 0x40, 0x00, 0x8c, 0x1b, 0x10, 0x03, +0x00, 0x08, 0x50, 0x03, 0x00, 0x09, 0x3e, 0x19, 0xda, 0xb0, 0x84, 0x48, 0x49, 0xfe, 0xb4, 0x58, +0xe6, 0xe4, 0xe9, 0x05, 0x4e, 0x83, 0x00, 0x22, 0x84, 0xa5, 0xdf, 0x1f, 0x50, 0x03, 0x00, 0x11, +0x80, 0x3c, 0x44, 0x20, 0x00, 0x20, 0x49, 0xfe, 0xb4, 0x4b, 0x4e, 0x83, 0x00, 0x12, 0x84, 0xa5, +0xdf, 0x0f, 0x50, 0x1e, 0x00, 0x10, 0x50, 0x03, 0x00, 0x31, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, +0xb4, 0x3f, 0x00, 0x03, 0x00, 0x40, 0x9c, 0x02, 0x10, 0x03, 0x00, 0x40, 0xd5, 0x08, 0x84, 0xa3, +0xdf, 0x04, 0x4e, 0x83, 0x00, 0x05, 0xd5, 0x09, 0x84, 0xa5, 0xdf, 0x07, 0xf1, 0x01, 0x50, 0x03, +0x00, 0x41, 0x84, 0x46, 0x49, 0xfe, 0xb4, 0x2c, 0x50, 0x03, 0x00, 0x51, 0x84, 0x20, 0x44, 0x20, +0x00, 0x10, 0x49, 0xfe, 0xb4, 0x3b, 0x84, 0xa1, 0xd7, 0x07, 0x80, 0x09, 0x80, 0x46, 0x3e, 0x19, +0xda, 0xb8, 0x49, 0xff, 0xfe, 0xdd, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0x84, 0x44, 0x85, 0xb6, 0x98, 0x50, 0x60, 0x00, 0x5b, 0x84, 0x20, +0x97, 0xd0, 0x50, 0x0f, 0x81, 0x60, 0x44, 0x20, 0x00, 0x10, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x20, +0x00, 0x50, 0x50, 0x0f, 0x81, 0x00, 0xdd, 0x28, 0x50, 0x9f, 0x81, 0x74, 0x84, 0x20, 0x44, 0x20, +0x00, 0xff, 0x80, 0x1f, 0xdd, 0x28, 0x84, 0x20, 0x84, 0x42, 0x80, 0x09, 0xdd, 0x28, 0x80, 0x09, +0x50, 0x13, 0x7f, 0xaa, 0x84, 0x42, 0x49, 0xfe, 0xb3, 0xf3, 0x2e, 0x81, 0xdc, 0x27, 0x84, 0x01, +0x4c, 0x70, 0x00, 0x08, 0x84, 0x23, 0x4c, 0x70, 0x80, 0x05, 0x84, 0x45, 0x4c, 0x71, 0x40, 0x1e, +0x51, 0xcf, 0x81, 0x50, 0x84, 0x20, 0x84, 0x48, 0x80, 0x1c, 0x50, 0xa3, 0x7f, 0xae, 0x49, 0xfe, +0xb3, 0xf5, 0x3e, 0x19, 0xda, 0xb0, 0x80, 0x0a, 0x84, 0x48, 0x49, 0xff, 0xf6, 0x19, 0x84, 0x21, +0x4c, 0x00, 0x80, 0x09, 0x80, 0x0a, 0x80, 0x3c, 0x84, 0x48, 0x49, 0xff, 0xf6, 0x11, 0x4e, 0x03, +0x00, 0xac, 0x84, 0x41, 0x4c, 0x71, 0x00, 0x57, 0x01, 0xc3, 0x7f, 0xa7, 0x00, 0x03, 0x7f, 0xa8, +0x50, 0xa3, 0x7f, 0xf6, 0x41, 0xce, 0x20, 0x08, 0x41, 0xce, 0x00, 0x04, 0x80, 0x2a, 0x44, 0x20, +0x00, 0x10, 0x50, 0x0f, 0x81, 0x50, 0x49, 0xfe, 0xb3, 0xbb, 0x84, 0x20, 0x80, 0x0a, 0x44, 0x20, +0x00, 0x10, 0x49, 0xfe, 0xb3, 0xcb, 0x00, 0x0f, 0x81, 0x75, 0x84, 0x21, 0x54, 0x00, 0x00, 0x07, +0x51, 0xce, 0x00, 0x04, 0x4c, 0x00, 0xc0, 0x13, 0x3e, 0x99, 0xd9, 0xe8, 0x85, 0x44, 0x8c, 0x2f, +0x10, 0xa4, 0x82, 0x3d, 0x50, 0x04, 0x80, 0xd0, 0x80, 0x7c, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, +0x81, 0x60, 0x80, 0xa1, 0x49, 0x00, 0x04, 0xc8, 0xd5, 0x1c, 0x84, 0x42, 0x4c, 0x01, 0x40, 0x1a, +0x3e, 0xa9, 0xd9, 0xe8, 0x80, 0x7c, 0x87, 0x86, 0x11, 0xc5, 0x02, 0x3d, 0x50, 0x05, 0x00, 0xd0, +0x8c, 0x2f, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x00, 0x9d, 0x4c, 0x49, 0x00, 0x05, 0x34, +0x50, 0x1f, 0x81, 0x00, 0x50, 0x0f, 0x81, 0x60, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xb3, 0x80, +0x50, 0x0f, 0x81, 0x50, 0x50, 0x1f, 0x81, 0x60, 0x44, 0x20, 0x00, 0x10, 0x49, 0xff, 0xf6, 0x1a, +0xc8, 0x53, 0xa6, 0xf6, 0xa6, 0x37, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x31, 0x80, 0x04, 0x4e, 0x36, +0x00, 0x04, 0x84, 0x01, 0xd5, 0x4a, 0x84, 0x03, 0x4c, 0x70, 0x40, 0x05, 0x4e, 0x83, 0x00, 0x06, +0xd5, 0x37, 0x84, 0x25, 0x4c, 0x70, 0xc0, 0x35, 0x00, 0x1f, 0x81, 0x75, 0x84, 0x42, 0x54, 0x10, +0x80, 0x07, 0x80, 0x9f, 0x50, 0x03, 0x00, 0x08, 0x4c, 0x11, 0x40, 0x19, 0xa6, 0x76, 0xa6, 0xb7, +0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x88, 0x04, 0x44, 0x30, 0x00, 0x10, 0x3e, 0x29, 0xda, 0xc8, +0x50, 0x5f, 0x81, 0x70, 0x85, 0x20, 0x14, 0x9f, 0x80, 0x5c, 0x49, 0x00, 0x03, 0x61, 0xf0, 0x5c, +0x00, 0x1f, 0x81, 0x71, 0xae, 0x37, 0xae, 0x76, 0xd5, 0x08, 0x80, 0x40, 0x3e, 0x09, 0xda, 0xc8, +0x50, 0x13, 0x7f, 0xd6, 0x49, 0x00, 0x0b, 0x6a, 0x4e, 0x83, 0x00, 0x0b, 0x84, 0x45, 0x4c, 0x71, +0x40, 0x08, 0x00, 0x2f, 0x81, 0x75, 0x92, 0x44, 0x54, 0x21, 0x00, 0x03, 0xd5, 0x02, 0x84, 0x40, +0xa6, 0x77, 0x80, 0x67, 0x80, 0x88, 0x80, 0x1f, 0x49, 0xff, 0xfd, 0x68, 0x92, 0x00, 0x84, 0x20, +0x40, 0x00, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, 0xed, 0x7c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x3e, 0x79, 0xd9, 0xe8, 0x80, 0xc1, 0x00, 0x33, 0x82, 0x3d, +0x80, 0x22, 0x81, 0x00, 0x84, 0x45, 0x80, 0x06, 0xf3, 0x85, 0x49, 0xff, 0xfe, 0xfb, 0x80, 0x20, +0xc8, 0x0d, 0x04, 0x03, 0x80, 0x99, 0x54, 0x00, 0x04, 0x00, 0xc0, 0x69, 0x46, 0x02, 0x00, 0x00, +0x80, 0x48, 0x49, 0xff, 0xe5, 0xd9, 0x48, 0x00, 0x00, 0x63, 0x00, 0x13, 0x00, 0x0f, 0x00, 0x23, +0x00, 0x10, 0x3e, 0x09, 0x51, 0x08, 0x01, 0xc3, 0x82, 0x3c, 0x44, 0x95, 0xb6, 0x6c, 0x49, 0xff, +0xdc, 0x67, 0x50, 0x13, 0x00, 0x09, 0x84, 0x48, 0x50, 0x03, 0x80, 0xc8, 0xdd, 0x29, 0x49, 0x00, +0x12, 0xa5, 0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, 0xde, 0x11, 0x81, 0x40, 0xc8, 0x08, 0x3e, 0x09, +0x47, 0x3c, 0x3e, 0x19, 0x51, 0x60, 0x49, 0xff, 0xdc, 0x53, 0xd5, 0x41, 0x04, 0x80, 0x00, 0x02, +0x4e, 0x82, 0x00, 0x3e, 0x84, 0xc0, 0x80, 0x26, 0x44, 0x20, 0x04, 0x00, 0x80, 0x08, 0x49, 0xfe, +0xb2, 0xed, 0xf0, 0x05, 0x80, 0x66, 0x80, 0x86, 0x80, 0xa6, 0x80, 0x5c, 0x84, 0x26, 0x51, 0xc4, +0x00, 0x0e, 0xb6, 0xdf, 0xf6, 0x81, 0x15, 0xcf, 0x80, 0x02, 0x49, 0xff, 0xfd, 0xdb, 0x50, 0x13, +0x82, 0x41, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x18, 0xdd, 0x29, 0x3e, 0x19, 0xde, 0x10, 0x84, 0x46, +0x50, 0x0f, 0x80, 0x1e, 0xdd, 0x29, 0x3e, 0x19, 0x87, 0x6c, 0x84, 0x42, 0x50, 0x0f, 0x80, 0x24, +0xdd, 0x29, 0x00, 0x7e, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x03, 0x40, 0x73, 0xa0, 0x08, 0x40, 0x73, +0x80, 0x04, 0x50, 0x1f, 0x80, 0x18, 0x84, 0x4e, 0x80, 0x08, 0x49, 0xfe, 0xb2, 0x9f, 0x50, 0x13, +0x80, 0x12, 0x80, 0x0a, 0x96, 0x49, 0x80, 0x46, 0x49, 0xff, 0xf8, 0xec, 0xec, 0x2c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x50, 0x6f, 0x80, 0x04, 0x80, 0xe1, +0x81, 0x00, 0x84, 0x20, 0x81, 0x22, 0x80, 0x06, 0x84, 0x42, 0x49, 0xfe, 0xb2, 0xa7, 0x80, 0x06, +0x9c, 0x7d, 0x84, 0x42, 0x49, 0xfe, 0xb2, 0x8c, 0xa6, 0xf1, 0x54, 0x01, 0x80, 0x80, 0xc0, 0x27, +0xa7, 0x30, 0x54, 0x02, 0x00, 0x0e, 0xc8, 0x16, 0x54, 0x01, 0x80, 0x08, 0xc0, 0x13, 0x97, 0xa4, +0xce, 0x1e, 0x3e, 0x09, 0x51, 0x1c, 0x49, 0xff, 0xdb, 0xeb, 0x3c, 0x0c, 0x77, 0x13, 0x54, 0x00, +0x02, 0x00, 0xc0, 0x15, 0x46, 0x04, 0x00, 0x00, 0x80, 0x26, 0x80, 0x48, 0x49, 0xff, 0xe5, 0x44, +0xd5, 0x0e, 0x54, 0x42, 0x00, 0x0f, 0x84, 0xa3, 0xdc, 0x0a, 0x54, 0x31, 0x80, 0x08, 0xcb, 0x07, +0x80, 0x08, 0x80, 0x27, 0x80, 0x49, 0x49, 0xff, 0xff, 0x45, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x50, 0x31, 0x00, 0x10, 0x92, 0x22, +0x80, 0x83, 0x84, 0xa0, 0xd5, 0x11, 0xa7, 0x80, 0x9d, 0x69, 0xaf, 0xa0, 0x00, 0xa0, 0x00, 0x01, +0x10, 0xa2, 0x00, 0x3c, 0x01, 0xc0, 0x00, 0x02, 0x11, 0xc2, 0x00, 0x78, 0xa7, 0x83, 0x9c, 0x04, +0x10, 0x62, 0x00, 0xb4, 0x9d, 0x21, 0xe2, 0xa1, 0xe9, 0xef, 0x9c, 0x0f, 0x94, 0x02, 0x50, 0x40, +0x80, 0x10, 0xf0, 0x83, 0x98, 0x94, 0x81, 0x21, 0x3e, 0x09, 0x51, 0xa4, 0x3f, 0xe9, 0x51, 0x78, +0xd5, 0x53, 0x40, 0xa4, 0x85, 0x17, 0x00, 0x71, 0x7f, 0xff, 0x00, 0x61, 0x00, 0x3b, 0x00, 0x51, +0x00, 0x77, 0x00, 0x41, 0x00, 0xb3, 0x4e, 0x83, 0x00, 0x21, 0x38, 0x50, 0x14, 0x00, 0x38, 0x8f, +0x2a, 0x02, 0x10, 0x5f, 0x80, 0x00, 0x38, 0x50, 0x10, 0x00, 0x01, 0xcf, 0x80, 0x00, 0x38, 0x40, +0x1c, 0x00, 0x40, 0xa4, 0x20, 0x09, 0x38, 0x70, 0x18, 0x00, 0x40, 0x64, 0x40, 0x09, 0x40, 0x44, +0x10, 0x03, 0x40, 0x63, 0x70, 0x03, 0x40, 0x55, 0x14, 0x03, 0x93, 0x18, 0x40, 0x74, 0x1c, 0x03, +0x97, 0xb0, 0x97, 0x68, 0x97, 0x20, 0xd5, 0x0e, 0xe6, 0x27, 0xe9, 0x0c, 0x85, 0x44, 0x4c, 0x85, +0x40, 0x0a, 0x38, 0x60, 0x18, 0x00, 0x38, 0x50, 0x14, 0x00, 0x38, 0x40, 0x10, 0x00, 0x38, 0x70, +0x1c, 0x00, 0x00, 0x81, 0x80, 0x00, 0x8d, 0x21, 0x40, 0x73, 0xa0, 0x03, 0xaf, 0xd0, 0x00, 0x71, +0x80, 0x3c, 0x40, 0x63, 0x1c, 0x03, 0x10, 0x61, 0x00, 0x3c, 0x00, 0x61, 0x80, 0x78, 0x40, 0x52, +0x98, 0x03, 0x10, 0x51, 0x00, 0x78, 0x00, 0x51, 0x80, 0xb4, 0x9c, 0xd9, 0x40, 0x42, 0x14, 0x03, +0x10, 0x41, 0x00, 0xb4, 0x9c, 0x91, 0x05, 0xcf, 0x80, 0x03, 0xe3, 0x3c, 0xe9, 0xab, 0xec, 0x14, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xbc, 0xf5, 0x8c, +0x80, 0xc3, 0xb4, 0xe5, 0xf4, 0x8e, 0xe6, 0xf0, 0x4e, 0xf3, 0x01, 0xe6, 0x44, 0x30, 0x00, 0x10, +0x4c, 0x61, 0x80, 0x09, 0x44, 0x40, 0x00, 0x18, 0x4c, 0x62, 0x00, 0x05, 0x95, 0x59, 0x4c, 0x62, +0xc1, 0xdb, 0x80, 0xe3, 0x4c, 0x13, 0xc1, 0xd8, 0x84, 0x20, 0x50, 0x9f, 0x80, 0x40, 0xd5, 0x0c, +0x08, 0x72, 0x00, 0x04, 0x9c, 0xd9, 0x18, 0x72, 0x80, 0x01, 0x84, 0xe4, 0x4c, 0x33, 0xff, 0xfa, +0x9c, 0x49, 0x4c, 0x11, 0x80, 0x07, 0x95, 0x4a, 0x88, 0xa9, 0x99, 0x01, 0x84, 0x60, 0xd5, 0xf1, +0x80, 0x02, 0x80, 0x26, 0x50, 0x2f, 0x80, 0x40, 0x50, 0x9f, 0x80, 0x41, 0x49, 0xff, 0xff, 0x4c, +0x92, 0xc2, 0x14, 0x9f, 0x80, 0x04, 0x50, 0x7f, 0x80, 0x40, 0x50, 0x9f, 0x80, 0x42, 0x50, 0xaf, +0x80, 0x43, 0x50, 0x03, 0x00, 0x0a, 0x50, 0x5f, 0x80, 0x50, 0x94, 0x02, 0x14, 0x9f, 0x80, 0x06, +0x14, 0xaf, 0x80, 0x05, 0xf7, 0x8d, 0xf5, 0x81, 0x04, 0x8f, 0x80, 0x04, 0x98, 0x38, 0xa6, 0x80, +0xa6, 0x78, 0x40, 0x11, 0x04, 0x03, 0x18, 0x13, 0x80, 0x04, 0xa6, 0x81, 0x00, 0x14, 0x00, 0x00, +0x40, 0x11, 0x04, 0x03, 0x18, 0x14, 0x00, 0x04, 0xa6, 0x82, 0x00, 0x14, 0x80, 0x00, 0x40, 0x10, +0x88, 0x03, 0x18, 0x14, 0x80, 0x04, 0xa6, 0x43, 0x00, 0x25, 0x00, 0x00, 0x50, 0x00, 0x00, 0x3c, +0x40, 0x10, 0x88, 0x03, 0x18, 0x15, 0x00, 0x04, 0xf1, 0x01, 0x4c, 0x70, 0xff, 0xe2, 0x9d, 0xb5, +0x50, 0x2f, 0x80, 0x40, 0x95, 0xb2, 0x9c, 0x94, 0xf6, 0x88, 0xf2, 0x8f, 0x48, 0x00, 0x00, 0xf9, +0x00, 0x2f, 0x80, 0x47, 0x00, 0x0f, 0x80, 0x48, 0x00, 0x1f, 0x80, 0x49, 0x00, 0x3f, 0x80, 0x4c, +0x00, 0x4f, 0x80, 0x46, 0x00, 0x5f, 0x80, 0x4a, 0x00, 0x6f, 0x80, 0x45, 0x00, 0x7f, 0x80, 0x4b, +0x00, 0x9f, 0x80, 0x44, 0x10, 0x0f, 0x80, 0x4a, 0x10, 0x2f, 0x80, 0x44, 0x00, 0x0f, 0x80, 0x4d, +0x00, 0x2f, 0x80, 0x4f, 0x10, 0x1f, 0x80, 0x4b, 0x00, 0x1f, 0x80, 0x4e, 0x10, 0x4f, 0x80, 0x47, +0x10, 0x2f, 0x80, 0x4e, 0x10, 0x3f, 0x80, 0x4f, 0x10, 0x5f, 0x80, 0x48, 0x10, 0x6f, 0x80, 0x46, +0x10, 0x7f, 0x80, 0x49, 0x10, 0x9f, 0x80, 0x45, 0x10, 0x0f, 0x80, 0x4c, 0xf2, 0x05, 0xf3, 0x06, +0xf4, 0x04, 0x10, 0x1f, 0x80, 0x4d, 0x50, 0x1f, 0x80, 0x40, 0xa6, 0x08, 0x3e, 0x59, 0x52, 0xa4, +0x38, 0x02, 0x80, 0x00, 0xf6, 0x01, 0x18, 0x00, 0x80, 0x04, 0xa6, 0x20, 0x38, 0x02, 0x80, 0x00, +0x18, 0x02, 0x00, 0x04, 0xa6, 0x18, 0x38, 0x02, 0x80, 0x00, 0x18, 0x01, 0x80, 0x04, 0xa6, 0x10, +0x38, 0x02, 0x80, 0x00, 0x18, 0x01, 0x00, 0x04, 0x4c, 0x13, 0x7f, 0xe9, 0xf7, 0x08, 0x50, 0x5f, +0x80, 0x40, 0x50, 0x03, 0x80, 0x10, 0xf3, 0x05, 0xf4, 0x06, 0xf6, 0x04, 0x98, 0xa8, 0xa6, 0x50, +0xa6, 0x28, 0x40, 0x00, 0x80, 0x03, 0x18, 0x02, 0x80, 0x04, 0xa6, 0x51, 0xa6, 0x30, 0x40, 0x00, +0x80, 0x03, 0x18, 0x03, 0x00, 0x04, 0xa6, 0x52, 0xa6, 0x20, 0x40, 0x00, 0x80, 0x03, 0x18, 0x02, +0x00, 0x04, 0xa6, 0x13, 0xa6, 0x58, 0x50, 0x21, 0x00, 0x3c, 0x40, 0x00, 0x04, 0x03, 0x18, 0x01, +0x80, 0x04, 0xf0, 0x01, 0xd8, 0xe5, 0x50, 0x1f, 0x80, 0x44, 0x50, 0x2f, 0x80, 0x48, 0x50, 0x3f, +0x80, 0x4c, 0x50, 0x4f, 0x80, 0x40, 0xf1, 0x8b, 0xf2, 0x8a, 0xf3, 0x89, 0xf4, 0x87, 0xf5, 0x07, +0xf6, 0x0b, 0xa6, 0xe8, 0xa6, 0x30, 0x04, 0x9f, 0x80, 0x09, 0x3e, 0x69, 0x56, 0xa4, 0x3e, 0x19, +0x54, 0xa4, 0x38, 0x20, 0x80, 0x00, 0x38, 0x13, 0x0c, 0x00, 0x00, 0x54, 0x80, 0x00, 0xf7, 0x0a, +0x40, 0x11, 0x04, 0x03, 0x3e, 0x29, 0x53, 0xa4, 0xa7, 0x38, 0x38, 0x21, 0x14, 0x00, 0x3e, 0x79, +0x55, 0xa4, 0x38, 0xa3, 0x90, 0x00, 0x10, 0x2f, 0x80, 0x08, 0x38, 0x23, 0x00, 0x00, 0x3e, 0x69, +0x53, 0xa4, 0x38, 0x83, 0x00, 0x00, 0x39, 0xe3, 0x80, 0x00, 0x3e, 0x99, 0x54, 0xa4, 0x80, 0x07, +0x38, 0x74, 0x8c, 0x00, 0x38, 0x93, 0x0c, 0x00, 0x38, 0x60, 0x0c, 0x00, 0x40, 0x30, 0xa8, 0x03, +0x3e, 0x19, 0x53, 0xa4, 0x38, 0x00, 0x90, 0x00, 0x3e, 0x19, 0x54, 0xa4, 0x39, 0xc0, 0x90, 0x00, +0x3e, 0x19, 0x56, 0xa4, 0x38, 0xa0, 0x90, 0x00, 0x40, 0x21, 0x24, 0x03, 0x00, 0x4f, 0x80, 0x08, +0x40, 0x14, 0x18, 0x03, 0x3e, 0x99, 0x55, 0xa4, 0x3e, 0x69, 0x56, 0xa4, 0x38, 0x83, 0x14, 0x00, +0x38, 0x64, 0x94, 0x00, 0x3e, 0x99, 0x54, 0xa4, 0x40, 0x31, 0x90, 0x03, 0x38, 0x44, 0x94, 0x00, +0xf5, 0x07, 0x40, 0x21, 0x70, 0x03, 0x18, 0x32, 0x80, 0x01, 0xf3, 0x0b, 0x40, 0x21, 0x18, 0x03, +0x40, 0x10, 0xa8, 0x03, 0x40, 0x10, 0x90, 0x03, 0x18, 0x21, 0x80, 0x01, 0xf4, 0x0a, 0x40, 0x7f, +0x1c, 0x03, 0xf5, 0x87, 0x40, 0x03, 0x80, 0x03, 0xf3, 0x8b, 0x18, 0x12, 0x00, 0x01, 0xf5, 0x09, +0x40, 0x00, 0x20, 0x03, 0x18, 0x02, 0x80, 0x01, 0xf6, 0x07, 0xf7, 0x0f, 0xf4, 0x8a, 0xf5, 0x89, +0x4c, 0x63, 0xff, 0x8f, 0x04, 0x9f, 0x80, 0x08, 0x8f, 0x24, 0x14, 0x9f, 0x80, 0x08, 0xf0, 0x08, +0x4e, 0x03, 0xff, 0x08, 0x00, 0x1f, 0x80, 0x47, 0x00, 0x3f, 0x80, 0x48, 0x00, 0x2f, 0x80, 0x49, +0x00, 0x4f, 0x80, 0x46, 0x00, 0x5f, 0x80, 0x4a, 0x00, 0x6f, 0x80, 0x45, 0x00, 0x7f, 0x80, 0x4b, +0x00, 0x9f, 0x80, 0x44, 0x10, 0x3f, 0x80, 0x4a, 0x10, 0x2f, 0x80, 0x4b, 0x00, 0x3f, 0x80, 0x4f, +0x00, 0x2f, 0x80, 0x4e, 0x10, 0x1f, 0x80, 0x44, 0x00, 0x1f, 0x80, 0x4d, 0x00, 0x0f, 0x80, 0x4c, +0x10, 0x4f, 0x80, 0x47, 0x10, 0x1f, 0x80, 0x4c, 0x10, 0x2f, 0x80, 0x4d, 0x10, 0x3f, 0x80, 0x4e, +0x10, 0x5f, 0x80, 0x48, 0x10, 0x6f, 0x80, 0x46, 0x10, 0x7f, 0x80, 0x49, 0x10, 0x9f, 0x80, 0x45, +0xf1, 0x0d, 0xf2, 0x04, 0xf3, 0x05, 0xf4, 0x06, 0x10, 0x0f, 0x80, 0x4f, 0x3e, 0x09, 0x52, 0xa4, +0xa7, 0x48, 0x38, 0x50, 0x14, 0x00, 0x18, 0x50, 0x80, 0x04, 0xa7, 0x50, 0x38, 0x50, 0x14, 0x00, +0x18, 0x51, 0x00, 0x04, 0xa7, 0x60, 0x38, 0x50, 0x14, 0x00, 0x18, 0x52, 0x00, 0x04, 0xa7, 0x58, +0x38, 0x50, 0x14, 0x00, 0x18, 0x51, 0x80, 0x04, 0xf5, 0x01, 0xd9, 0xeb, 0x84, 0x00, 0x50, 0x7f, +0x80, 0x40, 0x44, 0x60, 0x00, 0x3c, 0xd5, 0x13, 0x08, 0x41, 0x80, 0x01, 0xa7, 0x50, 0x9c, 0x49, +0x40, 0x42, 0x14, 0x03, 0x85, 0x24, 0x18, 0x41, 0x00, 0x01, 0x4c, 0x14, 0xff, 0xf7, 0x9c, 0x01, +0x4c, 0x00, 0xc0, 0x06, 0x84, 0x00, 0x50, 0x6f, 0x80, 0x40, 0xd5, 0x13, 0x42, 0x30, 0x18, 0x24, +0x94, 0x82, 0x8c, 0x70, 0x98, 0xba, 0x98, 0xfb, 0x84, 0x20, 0xd5, 0xe7, 0x08, 0x41, 0x80, 0x01, +0x9c, 0x49, 0x84, 0xa4, 0x18, 0x41, 0x00, 0x04, 0xd9, 0xfa, 0x9c, 0x01, 0x4c, 0x00, 0x80, 0x08, +0xf7, 0x0e, 0x94, 0xc2, 0x98, 0xf3, 0x98, 0xb8, 0x84, 0x20, 0xd5, 0xf1, 0x04, 0x9f, 0x80, 0x0c, +0x94, 0x2a, 0xb6, 0x09, 0xed, 0x44, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x9c, 0x80, 0xc0, 0x44, 0x00, 0x00, 0x10, 0xf3, 0x83, 0xf2, 0x88, 0xf4, 0x89, 0xf5, 0x8a, +0x4c, 0x30, 0x00, 0x0d, 0x44, 0x20, 0x00, 0x18, 0x4c, 0x31, 0x00, 0x09, 0x41, 0xe0, 0x04, 0x08, +0x4c, 0x3f, 0x00, 0x05, 0x84, 0x1f, 0x48, 0x00, 0x00, 0x8d, 0x8e, 0x28, 0x80, 0x01, 0x84, 0xe0, +0xf1, 0x81, 0xf7, 0x97, 0x49, 0xff, 0xf2, 0x7c, 0xf0, 0x82, 0xc8, 0x04, 0x84, 0x1e, 0x48, 0x00, +0x00, 0x81, 0x50, 0x0f, 0x80, 0x54, 0x80, 0x26, 0x84, 0x48, 0x49, 0xfe, 0xaf, 0xc1, 0xf2, 0x01, +0xf0, 0x02, 0x50, 0x13, 0x00, 0x08, 0x40, 0x61, 0x0c, 0x09, 0x54, 0x83, 0x00, 0xff, 0x49, 0xfe, +0xaf, 0xb7, 0x83, 0x86, 0x84, 0xe5, 0x43, 0xc4, 0x1c, 0x73, 0x40, 0xa3, 0x0c, 0x08, 0x05, 0xef, +0x80, 0x02, 0x8f, 0x48, 0x52, 0x84, 0x00, 0x00, 0x54, 0x84, 0x00, 0xff, 0x55, 0xce, 0x00, 0xff, +0x89, 0x5e, 0x9f, 0xb1, 0x14, 0x8f, 0x80, 0x07, 0x15, 0xcf, 0x80, 0x04, 0xf7, 0x85, 0x14, 0xaf, +0x80, 0x0b, 0xf6, 0x86, 0xf6, 0x06, 0x04, 0xaf, 0x80, 0x0b, 0x05, 0xcf, 0x80, 0x04, 0x44, 0x95, +0xb6, 0x6c, 0x50, 0x8f, 0x80, 0x5c, 0x50, 0x7f, 0x80, 0x4c, 0xd5, 0x2a, 0xa7, 0x0f, 0x9f, 0xb1, +0x40, 0x4e, 0x10, 0x03, 0xaf, 0x0f, 0x51, 0xce, 0x7f, 0xff, 0xdd, 0x29, 0x80, 0x2a, 0x84, 0x48, +0x50, 0x0f, 0x80, 0x3c, 0xdd, 0x29, 0xf3, 0x03, 0x3c, 0x1c, 0x54, 0x5d, 0xf2, 0x08, 0x45, 0xe0, +0x00, 0x10, 0x50, 0x4f, 0x80, 0x44, 0x80, 0xa8, 0x50, 0x0f, 0x80, 0x34, 0x15, 0xef, 0x80, 0x17, +0x49, 0xff, 0xfd, 0x9c, 0x50, 0x1f, 0x80, 0x44, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x54, 0xdd, 0x29, +0x80, 0x0a, 0x80, 0x27, 0x84, 0x48, 0xdd, 0x29, 0x55, 0xce, 0x00, 0xff, 0x8f, 0x48, 0x84, 0x48, +0x50, 0x0f, 0x80, 0x34, 0x50, 0x1f, 0x80, 0x54, 0x4e, 0x64, 0xff, 0xd2, 0xf1, 0x04, 0xf2, 0x07, +0x05, 0xef, 0x80, 0x05, 0x98, 0x0a, 0x96, 0x00, 0x51, 0xef, 0x7f, 0xff, 0xf0, 0x84, 0x84, 0x1f, +0x15, 0xef, 0x80, 0x05, 0x4d, 0xe0, 0x7f, 0xb8, 0xf2, 0x01, 0xf1, 0x0a, 0xb6, 0x41, 0xf2, 0x01, +0xf1, 0x02, 0xf0, 0x09, 0x49, 0xfe, 0xaf, 0x4c, 0xf0, 0x02, 0x49, 0xff, 0xf2, 0x01, 0x84, 0x00, +0xec, 0x64, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x84, 0x60, 0x50, 0x50, +0x00, 0x08, 0xb6, 0x60, 0xa8, 0xc1, 0x80, 0x85, 0x18, 0x32, 0x00, 0x01, 0x44, 0x60, 0x01, 0x00, +0x9c, 0xd9, 0x4c, 0x33, 0x7f, 0xfb, 0x84, 0x80, 0x80, 0x64, 0x40, 0x71, 0x88, 0xd7, 0xa7, 0xe8, +0x9c, 0xd9, 0x99, 0x27, 0x38, 0x60, 0x98, 0x00, 0x99, 0x26, 0x97, 0x20, 0x99, 0x84, 0x8c, 0xc8, +0x00, 0x83, 0x00, 0x00, 0x18, 0x82, 0x80, 0x01, 0xaf, 0xf0, 0x44, 0x60, 0x01, 0x00, 0x4c, 0x33, +0x7f, 0xee, 0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0x3c, 0x84, 0x80, 0xd5, 0x20, +0xb4, 0xc0, 0x9d, 0xb1, 0x97, 0xb0, 0x38, 0x62, 0x98, 0x0e, 0x8c, 0xa8, 0xa7, 0xa8, 0xa1, 0xc1, +0x99, 0xf7, 0x97, 0xf8, 0xa9, 0xc1, 0x99, 0xc7, 0x8c, 0xe8, 0x00, 0x83, 0x80, 0x00, 0x10, 0x82, +0x80, 0x00, 0xaf, 0xb8, 0xa7, 0xe8, 0x38, 0x80, 0x90, 0x00, 0x99, 0xb7, 0x97, 0xb0, 0x99, 0x86, +0x00, 0x53, 0x00, 0x08, 0x40, 0x52, 0xa0, 0x03, 0x38, 0x51, 0x90, 0x08, 0x9d, 0x21, 0x80, 0xa0, +0xe2, 0x82, 0xe9, 0xdf, 0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, +0x84, 0x40, 0xd5, 0x12, 0xb4, 0x80, 0x9c, 0x91, 0x9d, 0x21, 0x97, 0x20, 0x38, 0x41, 0x90, 0x0e, +0x8c, 0x68, 0xa7, 0x58, 0xa1, 0x01, 0x99, 0x2c, 0x97, 0x20, 0xa9, 0x01, 0x99, 0x04, 0x8c, 0x88, +0xa7, 0xa0, 0xaf, 0x98, 0xaf, 0x60, 0x80, 0x60, 0xe2, 0x41, 0xe9, 0xed, 0x3a, 0x6f, 0x98, 0x04, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xe4, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, +0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x68, 0x81, 0x44, 0x81, 0x25, +0x50, 0x8f, 0x80, 0xc8, 0x49, 0xfe, 0xae, 0xda, 0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x50, 0x0f, +0x80, 0x08, 0x49, 0xfe, 0xae, 0xd3, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, +0xae, 0xcd, 0x5c, 0xf3, 0x00, 0x41, 0xe8, 0x0c, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x46, 0x49, 0xfe, +0xae, 0xaf, 0x50, 0x6f, 0x80, 0xc8, 0x51, 0xcf, 0x81, 0x08, 0x80, 0xe6, 0xd5, 0x07, 0x80, 0x1c, +0x80, 0x26, 0x80, 0x48, 0x49, 0x00, 0x06, 0x88, 0xd5, 0xf5, 0xa6, 0x38, 0x56, 0x00, 0x00, 0x36, +0x18, 0x03, 0x80, 0x01, 0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x68, 0x80, 0x07, 0x49, 0x00, +0x06, 0x61, 0x80, 0x07, 0x50, 0x1f, 0x80, 0xc8, 0x44, 0x20, 0x00, 0x40, 0x49, 0x00, 0x06, 0x16, +0xb4, 0x3f, 0xf2, 0x01, 0x80, 0x07, 0x49, 0x00, 0x06, 0x11, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x08, +0x49, 0x00, 0x05, 0xd8, 0xa6, 0x30, 0x56, 0x00, 0x00, 0x6a, 0x18, 0x03, 0x00, 0x01, 0x4c, 0x6e, +0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x08, 0x80, 0x07, 0x49, 0x00, 0x06, 0x44, 0x80, 0x07, 0x50, 0x1f, +0x80, 0xc8, 0x44, 0x20, 0x00, 0x40, 0x50, 0x6f, 0x81, 0x08, 0x49, 0x00, 0x05, 0xf7, 0x44, 0x20, +0x00, 0x10, 0x80, 0x07, 0x80, 0x26, 0x49, 0x00, 0x05, 0xf1, 0x80, 0x07, 0x80, 0x26, 0x49, 0x00, +0x05, 0xb9, 0xe7, 0x31, 0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0xd5, 0x04, +0x80, 0x0a, 0x80, 0x26, 0x80, 0x49, 0x49, 0xfe, 0xae, 0x5b, 0xed, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xcc, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, +0x84, 0x20, 0x44, 0x20, 0x00, 0x68, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x70, 0x81, 0x44, 0x81, 0x25, +0x50, 0x8f, 0x80, 0xdc, 0x49, 0xfe, 0xae, 0x5a, 0x84, 0x20, 0x44, 0x20, 0x00, 0x68, 0x50, 0x0f, +0x80, 0x08, 0x49, 0xfe, 0xae, 0x53, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, +0xae, 0x4d, 0x5c, 0xf3, 0x00, 0x41, 0xe8, 0x0c, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x46, 0x49, 0xfe, +0xae, 0x2f, 0x50, 0x6f, 0x80, 0xdc, 0x51, 0xcf, 0x81, 0x1c, 0x80, 0xe6, 0xd5, 0x07, 0x80, 0x1c, +0x80, 0x26, 0x80, 0x48, 0x49, 0x00, 0x08, 0x20, 0xd5, 0xf5, 0xa6, 0x38, 0x56, 0x00, 0x00, 0x36, +0x18, 0x03, 0x80, 0x01, 0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x70, 0x80, 0x07, 0x49, 0x00, +0x07, 0xf9, 0x80, 0x07, 0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x49, 0x00, 0x07, 0xae, +0xb4, 0x3f, 0xf2, 0x01, 0x80, 0x07, 0x49, 0x00, 0x07, 0xa9, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x1c, +0x49, 0x00, 0x07, 0x2e, 0xa6, 0x30, 0x56, 0x00, 0x00, 0x6a, 0x18, 0x03, 0x00, 0x01, 0x4c, 0x6e, +0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x08, 0x80, 0x07, 0x49, 0x00, 0x07, 0xdc, 0x80, 0x07, 0x50, 0x1f, +0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x50, 0x6f, 0x81, 0x1c, 0x49, 0x00, 0x07, 0x8f, 0x44, 0x20, +0x00, 0x14, 0x80, 0x07, 0x80, 0x26, 0x49, 0x00, 0x07, 0x89, 0x80, 0x07, 0x80, 0x26, 0x49, 0x00, +0x07, 0x0f, 0xe7, 0x35, 0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x14, 0xd5, 0x04, +0x80, 0x0a, 0x80, 0x26, 0x80, 0x49, 0x49, 0xfe, 0xad, 0xdb, 0xed, 0x34, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x5c, 0xf0, 0x85, 0x8c, 0x18, 0xf0, 0x97, +0x50, 0x6f, 0x80, 0x60, 0xf1, 0x17, 0x44, 0x20, 0x00, 0x40, 0x80, 0x06, 0x49, 0xfe, 0xad, 0xc8, +0x80, 0x46, 0x50, 0x3f, 0x80, 0xa0, 0x9c, 0x94, 0x4c, 0x21, 0xff, 0xff, 0xf1, 0x05, 0xf2, 0x05, +0xa0, 0x49, 0xf5, 0x05, 0xf1, 0x82, 0x50, 0x3f, 0x80, 0x60, 0xa0, 0x92, 0xb4, 0x03, 0xf2, 0x83, +0xf1, 0x05, 0xa1, 0x6b, 0xf2, 0x02, 0xf5, 0x84, 0xf0, 0x96, 0x40, 0x81, 0x08, 0x05, 0xb4, 0x21, +0x40, 0x84, 0x14, 0x02, 0xf5, 0x03, 0x99, 0xc8, 0x46, 0x0d, 0x76, 0xaa, 0x40, 0x92, 0x88, 0x02, +0x58, 0x00, 0x04, 0x78, 0x40, 0x84, 0x24, 0x04, 0x99, 0xf8, 0x88, 0xe8, 0x40, 0x73, 0xe4, 0x0b, +0x98, 0xba, 0x40, 0x81, 0x08, 0x05, 0xf1, 0x81, 0x40, 0x84, 0x14, 0x02, 0xa0, 0x59, 0xf5, 0x04, +0xf0, 0x02, 0xf1, 0x95, 0x99, 0xe9, 0x46, 0x1e, 0x8c, 0x7b, 0x40, 0x91, 0x00, 0x02, 0x58, 0x10, +0x87, 0x56, 0x40, 0x84, 0x24, 0x04, 0x99, 0xf9, 0x88, 0xe8, 0x40, 0x73, 0xd0, 0x0b, 0x99, 0xfa, +0x40, 0x83, 0x9c, 0x05, 0xa1, 0x5a, 0x40, 0x84, 0x00, 0x02, 0xf0, 0x03, 0x46, 0x12, 0x42, 0x07, +0x40, 0x43, 0x88, 0x02, 0x41, 0xc0, 0x14, 0x00, 0x58, 0x10, 0x80, 0xdb, 0x41, 0xce, 0x04, 0x00, +0x40, 0x84, 0x10, 0x04, 0x89, 0x1c, 0x40, 0x84, 0x3c, 0x0b, 0x89, 0x07, 0xf0, 0x02, 0xf5, 0x94, +0xa1, 0x5b, 0x41, 0xc4, 0x20, 0x05, 0x46, 0x1c, 0x1b, 0xdc, 0x40, 0xae, 0x08, 0x02, 0x40, 0x44, +0x1c, 0x02, 0x41, 0xc0, 0x14, 0x00, 0x58, 0x10, 0x8e, 0xee, 0x40, 0x45, 0x10, 0x04, 0x41, 0xce, +0x04, 0x00, 0x41, 0xce, 0x10, 0x00, 0x41, 0xce, 0x28, 0x0b, 0x40, 0x9e, 0x20, 0x00, 0xf5, 0x93, +0x46, 0x0f, 0x57, 0xc0, 0xa1, 0x5c, 0x41, 0xe4, 0xa4, 0x05, 0x58, 0x00, 0x0f, 0xaf, 0x40, 0xa4, +0xa0, 0x02, 0x99, 0x28, 0x41, 0xef, 0x1c, 0x02, 0x99, 0x22, 0x41, 0xef, 0x28, 0x04, 0x41, 0xe2, +0x78, 0x00, 0x41, 0xef, 0x64, 0x0b, 0xa0, 0x5d, 0xf5, 0x92, 0x46, 0x24, 0x78, 0x7c, 0x40, 0x5f, +0x24, 0x00, 0x40, 0xa2, 0x94, 0x05, 0x58, 0x21, 0x06, 0x2a, 0x99, 0x0a, 0x40, 0xa5, 0x20, 0x02, +0x40, 0x22, 0xa4, 0x02, 0x99, 0xe7, 0x40, 0xa5, 0x08, 0x04, 0x89, 0x47, 0x40, 0xa5, 0x50, 0x0b, +0x41, 0xe5, 0x14, 0x00, 0xa0, 0x1e, 0xf1, 0x91, 0x46, 0x1a, 0x83, 0x04, 0x40, 0x7f, 0x78, 0x05, +0x58, 0x10, 0x86, 0x13, 0x99, 0x01, 0x40, 0x2f, 0x14, 0x02, 0x40, 0x73, 0xa4, 0x02, 0x89, 0x04, +0x40, 0x73, 0x88, 0x04, 0x88, 0xe8, 0x40, 0x73, 0xbc, 0x0b, 0x40, 0x63, 0xf8, 0x00, 0xa0, 0x9f, +0xf0, 0x90, 0x46, 0x0f, 0xd4, 0x69, 0x41, 0xc3, 0x18, 0x05, 0x58, 0x00, 0x05, 0x01, 0xf2, 0x8f, +0x40, 0x81, 0x00, 0x00, 0x41, 0xce, 0x14, 0x02, 0x40, 0x23, 0x78, 0x02, 0x89, 0x09, 0x41, 0xce, +0x08, 0x04, 0x41, 0xc4, 0x70, 0x00, 0x41, 0xce, 0x28, 0x0b, 0x40, 0x2e, 0x18, 0x00, 0x04, 0x11, +0x80, 0x08, 0x46, 0x06, 0x98, 0x09, 0x40, 0x81, 0x08, 0x05, 0x58, 0x00, 0x08, 0xd8, 0x40, 0x94, +0x78, 0x02, 0x99, 0x08, 0x40, 0x81, 0x18, 0x02, 0x99, 0x25, 0x40, 0x84, 0xa0, 0x04, 0x89, 0x04, +0x40, 0x84, 0x64, 0x0b, 0x40, 0x54, 0x08, 0x00, 0xf1, 0x8e, 0x46, 0x08, 0xb4, 0x4f, 0x04, 0x11, +0x80, 0x09, 0x40, 0xa2, 0x94, 0x05, 0x58, 0x00, 0x07, 0xaf, 0x40, 0x42, 0x88, 0x02, 0x40, 0x90, +0x80, 0x00, 0x40, 0xa5, 0x18, 0x02, 0x89, 0x3e, 0x40, 0xa5, 0x10, 0x04, 0x89, 0x49, 0x40, 0xa5, +0x50, 0x0b, 0x40, 0x85, 0x14, 0x00, 0xf1, 0x8d, 0x04, 0x11, 0x80, 0x0a, 0x40, 0x74, 0x20, 0x05, +0x44, 0x0f, 0x5b, 0xb1, 0x41, 0xe4, 0x14, 0x02, 0x41, 0xc0, 0x80, 0x00, 0x40, 0x73, 0x88, 0x02, +0x41, 0xce, 0x18, 0x00, 0x40, 0x73, 0xf8, 0x04, 0x88, 0xfc, 0x40, 0x73, 0xbc, 0x0b, 0x40, 0x63, +0xa0, 0x00, 0xf1, 0x8c, 0x46, 0x08, 0x95, 0xcd, 0x04, 0x11, 0x80, 0x0b, 0x41, 0xc3, 0x18, 0x05, +0x58, 0x00, 0x07, 0xbe, 0x41, 0xe3, 0x20, 0x02, 0x99, 0xc8, 0x41, 0xce, 0x14, 0x02, 0x99, 0xfa, +0x41, 0xce, 0x78, 0x04, 0x41, 0xc3, 0xf0, 0x00, 0x41, 0xce, 0x28, 0x0b, 0x40, 0x9e, 0x18, 0x00, +0xf1, 0x8b, 0x46, 0x26, 0xb9, 0x01, 0x04, 0x11, 0x80, 0x0c, 0x41, 0xe4, 0xa4, 0x05, 0x58, 0x21, +0x01, 0x22, 0x99, 0x0a, 0x41, 0xef, 0x20, 0x02, 0x40, 0x24, 0x98, 0x02, 0x99, 0x25, 0x41, 0xef, +0x08, 0x04, 0x41, 0xe2, 0x78, 0x00, 0x41, 0xef, 0x64, 0x0b, 0x40, 0x5f, 0x24, 0x00, 0xf1, 0x8a, +0x04, 0x01, 0x80, 0x0d, 0x46, 0x1f, 0xd9, 0x87, 0x40, 0xa2, 0x94, 0x05, 0x58, 0x10, 0x81, 0x93, +0x40, 0x22, 0xa4, 0x02, 0x99, 0x01, 0x40, 0xa5, 0x18, 0x02, 0x88, 0x88, 0x40, 0xa5, 0x08, 0x04, +0x89, 0x44, 0x40, 0xa5, 0x50, 0x0b, 0x40, 0x15, 0x14, 0x00, 0xf0, 0x89, 0x04, 0x21, 0x80, 0x0e, +0x46, 0x0a, 0x67, 0x94, 0x41, 0xe0, 0x84, 0x05, 0x58, 0x00, 0x03, 0x8e, 0xf2, 0x88, 0x40, 0x81, +0x00, 0x00, 0x40, 0x7f, 0x24, 0x02, 0x40, 0x20, 0x94, 0x02, 0x89, 0x06, 0x40, 0x73, 0x88, 0x04, +0x88, 0xe8, 0x40, 0x73, 0xbc, 0x0b, 0x99, 0xb9, 0x04, 0x31, 0x80, 0x0f, 0x46, 0x24, 0x9b, 0x40, +0x40, 0xa3, 0x18, 0x05, 0x58, 0x21, 0x08, 0x21, 0x40, 0x73, 0x04, 0x02, 0x40, 0x81, 0x88, 0x00, +0x41, 0xc5, 0x14, 0x02, 0x89, 0x09, 0x41, 0xce, 0x1c, 0x04, 0x41, 0xc4, 0x70, 0x00, 0xf3, 0x87, +0x41, 0xce, 0x28, 0x0b, 0xf3, 0x15, 0x46, 0x0f, 0x61, 0xe2, 0x40, 0x4e, 0x18, 0x00, 0x58, 0x00, +0x05, 0x62, 0x41, 0xc2, 0x04, 0x02, 0x40, 0x91, 0x80, 0x00, 0x41, 0xe3, 0x78, 0x02, 0x89, 0x25, +0x41, 0xee, 0x78, 0x04, 0x41, 0xe4, 0xf8, 0x00, 0xf2, 0x10, 0x41, 0xef, 0x6c, 0x0b, 0x46, 0x0c, +0x04, 0x0b, 0x40, 0x5f, 0x10, 0x00, 0x58, 0x00, 0x03, 0x40, 0x41, 0xc2, 0x98, 0x02, 0x98, 0xd0, +0x40, 0xa2, 0x28, 0x02, 0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, 0x5c, 0x0b, +0xf3, 0x0b, 0x46, 0x02, 0x65, 0xe5, 0x40, 0x15, 0x14, 0x00, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, +0x0a, 0x51, 0x41, 0xc0, 0x90, 0x02, 0x98, 0x98, 0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, +0x1c, 0x04, 0x99, 0xd7, 0x40, 0x73, 0xc8, 0x0b, 0xf2, 0x16, 0x46, 0x3e, 0x9b, 0x6c, 0x99, 0xb9, +0x41, 0xc2, 0x94, 0x05, 0x58, 0x31, 0x87, 0xaa, 0x40, 0x73, 0x14, 0x02, 0x40, 0x81, 0x0c, 0x00, +0x41, 0xc0, 0xf0, 0x02, 0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, 0x41, 0xc4, 0x70, 0x00, 0xf0, 0x11, +0x41, 0xce, 0x30, 0x0b, 0x46, 0x2d, 0x62, 0xf1, 0x40, 0x4e, 0x18, 0x00, 0x41, 0xe0, 0x84, 0x05, +0x58, 0x21, 0x00, 0x5d, 0x41, 0xc2, 0x04, 0x02, 0x40, 0x90, 0x08, 0x00, 0x41, 0xe3, 0x78, 0x02, +0x89, 0x25, 0x41, 0xee, 0x78, 0x04, 0x41, 0xe4, 0xf8, 0x00, 0xf0, 0x0c, 0x41, 0xef, 0x6c, 0x0b, +0x46, 0x20, 0x24, 0x41, 0x40, 0x5f, 0x10, 0x00, 0x40, 0xa3, 0x18, 0x05, 0x58, 0x21, 0x04, 0x53, +0x41, 0xc2, 0x98, 0x02, 0x98, 0xc2, 0x40, 0xa2, 0x28, 0x02, 0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, +0x89, 0x43, 0x40, 0xa5, 0x5c, 0x0b, 0xf3, 0x07, 0x46, 0x0d, 0x8a, 0x1e, 0x40, 0x15, 0x14, 0x00, +0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x06, 0x81, 0x41, 0xc0, 0x90, 0x02, 0x98, 0x98, 0x40, 0x72, +0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, 0x1c, 0x04, 0x99, 0xd7, 0x40, 0x73, 0xc8, 0x0b, 0xf2, 0x12, +0x46, 0x3e, 0x7d, 0x3f, 0x99, 0xb9, 0x41, 0xc2, 0x94, 0x05, 0x58, 0x31, 0x8b, 0xc8, 0x40, 0x73, +0x14, 0x02, 0x40, 0x81, 0x0c, 0x00, 0x41, 0xc0, 0xf0, 0x02, 0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, +0x41, 0xc4, 0x70, 0x00, 0xf0, 0x0d, 0x41, 0xce, 0x30, 0x0b, 0x46, 0x22, 0x1e, 0x1c, 0x40, 0x4e, +0x18, 0x00, 0x41, 0xe0, 0x84, 0x05, 0x58, 0x21, 0x0d, 0xe6, 0x41, 0xc2, 0x04, 0x02, 0x40, 0x90, +0x08, 0x00, 0x41, 0xe3, 0x78, 0x02, 0x89, 0x25, 0x41, 0xee, 0x78, 0x04, 0x41, 0xe4, 0xf8, 0x00, +0xf0, 0x08, 0x41, 0xef, 0x6c, 0x0b, 0x46, 0x2c, 0x33, 0x70, 0x40, 0x5f, 0x10, 0x00, 0x40, 0xa3, +0x18, 0x05, 0x58, 0x21, 0x07, 0xd6, 0x41, 0xc2, 0x98, 0x02, 0x98, 0xc2, 0x40, 0xa2, 0x28, 0x02, +0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, 0x5c, 0x0b, 0xf3, 0x13, 0x46, 0x0f, +0x4d, 0x50, 0x40, 0x15, 0x14, 0x00, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x0d, 0x87, 0x41, 0xc0, +0x90, 0x02, 0x98, 0x98, 0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, 0x1c, 0x04, 0x99, 0xd7, +0x40, 0x73, 0xc8, 0x0b, 0xf2, 0x0e, 0x46, 0x34, 0x55, 0xa1, 0x99, 0xb9, 0x41, 0xc2, 0x94, 0x05, +0x58, 0x31, 0x84, 0xed, 0x40, 0x73, 0x14, 0x02, 0x40, 0x81, 0x0c, 0x00, 0x41, 0xc0, 0xf0, 0x02, +0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, 0x41, 0xc4, 0x70, 0x00, 0xf0, 0x09, 0x41, 0xce, 0x30, 0x0b, +0x46, 0x2a, 0x9e, 0x3e, 0x40, 0x4e, 0x18, 0x00, 0x41, 0xe0, 0x84, 0x05, 0x58, 0x21, 0x09, 0x05, +0x41, 0xc2, 0x04, 0x02, 0x40, 0x90, 0x08, 0x00, 0x41, 0xe3, 0x78, 0x02, 0x89, 0x25, 0x41, 0xee, +0x78, 0x04, 0x41, 0xe4, 0xf8, 0x00, 0xf0, 0x14, 0x41, 0xef, 0x6c, 0x0b, 0x46, 0x2f, 0xce, 0xfa, +0x40, 0x5f, 0x10, 0x00, 0x40, 0xa3, 0x18, 0x05, 0x58, 0x21, 0x03, 0xf8, 0x41, 0xc2, 0x98, 0x02, +0x98, 0xc2, 0x40, 0xa2, 0x28, 0x02, 0x98, 0xd9, 0x40, 0xae, 0x28, 0x04, 0x89, 0x43, 0x40, 0xa5, +0x5c, 0x0b, 0xf3, 0x0f, 0x46, 0x06, 0x76, 0xf0, 0x89, 0x45, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, +0x02, 0xd9, 0x41, 0xc5, 0x10, 0x02, 0x98, 0x98, 0x40, 0x72, 0x9c, 0x02, 0x98, 0x96, 0x40, 0x7e, +0x1c, 0x04, 0x99, 0xd7, 0xf1, 0x0a, 0x40, 0x73, 0xc8, 0x0b, 0x46, 0x28, 0xd2, 0xa4, 0x40, 0x03, +0xa8, 0x00, 0x41, 0xc2, 0x94, 0x05, 0x58, 0x21, 0x0c, 0x8a, 0x40, 0x70, 0x14, 0x02, 0x40, 0x80, +0x88, 0x00, 0x41, 0xc5, 0x70, 0x02, 0x89, 0x04, 0x41, 0xc3, 0xf0, 0x04, 0xf3, 0x11, 0x41, 0xc4, +0x70, 0x00, 0x41, 0xce, 0x30, 0x0b, 0x44, 0x1a, 0x39, 0x42, 0x40, 0x4e, 0x00, 0x00, 0x40, 0x91, +0x84, 0x00, 0x41, 0xe0, 0x28, 0x03, 0x14, 0xaf, 0x80, 0x06, 0xf2, 0x0e, 0x89, 0x25, 0x41, 0xef, +0x10, 0x03, 0x46, 0x58, 0x77, 0x1f, 0x41, 0xe4, 0xf8, 0x00, 0x58, 0x52, 0x86, 0x81, 0x98, 0xd5, +0x41, 0xef, 0x70, 0x0b, 0xf2, 0x06, 0x40, 0x1f, 0x10, 0x00, 0x40, 0xa2, 0x00, 0x03, 0x98, 0xda, +0x40, 0xa5, 0x04, 0x03, 0x89, 0x43, 0x46, 0x56, 0xd9, 0xd6, 0xf3, 0x0b, 0x40, 0xa5, 0x54, 0x0b, +0x58, 0x52, 0x81, 0x22, 0x40, 0x65, 0x04, 0x00, 0x98, 0x9d, 0x40, 0x70, 0x90, 0x03, 0x98, 0x90, +0x40, 0x73, 0x98, 0x03, 0xf0, 0x08, 0x99, 0xd7, 0x46, 0x2f, 0xde, 0x53, 0x40, 0x73, 0xc0, 0x0b, +0x58, 0x21, 0x08, 0x0c, 0x99, 0x7e, 0x40, 0x80, 0x08, 0x00, 0x41, 0xc3, 0x04, 0x03, 0x89, 0x04, +0x41, 0xce, 0x14, 0x03, 0xf3, 0x15, 0x41, 0xc4, 0x70, 0x00, 0x46, 0x0a, 0x4b, 0xee, 0x41, 0xce, +0x24, 0x0b, 0x58, 0x00, 0x0a, 0x44, 0x40, 0x4e, 0x14, 0x00, 0x40, 0x91, 0x80, 0x00, 0x41, 0xe2, +0x98, 0x03, 0x89, 0x21, 0x41, 0xef, 0x10, 0x03, 0xf2, 0x12, 0x41, 0xe4, 0xf8, 0x00, 0x46, 0x04, +0xbd, 0xec, 0x41, 0xef, 0x70, 0x0b, 0x58, 0x00, 0x0f, 0xa9, 0x40, 0x1f, 0x10, 0x00, 0x98, 0xd0, +0x40, 0xa2, 0x14, 0x03, 0x98, 0xde, 0x40, 0xa5, 0x04, 0x03, 0x89, 0x43, 0x46, 0x0f, 0x6b, 0xb4, +0xf3, 0x0f, 0x40, 0xa5, 0x54, 0x0b, 0x58, 0x00, 0x0b, 0x60, 0x40, 0x65, 0x04, 0x00, 0x98, 0x98, +0x40, 0x70, 0x90, 0x03, 0x98, 0x95, 0x40, 0x73, 0x98, 0x03, 0x99, 0xd7, 0x46, 0x3b, 0xeb, 0xfb, +0xf2, 0x0c, 0x40, 0x73, 0xc0, 0x0b, 0x58, 0x31, 0x8c, 0x70, 0x99, 0x7e, 0x40, 0x81, 0x0c, 0x00, +0x41, 0xc3, 0x04, 0x03, 0x89, 0x04, 0x41, 0xce, 0x14, 0x03, 0xf0, 0x09, 0x41, 0xc4, 0x70, 0x00, +0x46, 0x22, 0x89, 0xb7, 0x41, 0xce, 0x24, 0x0b, 0x58, 0x21, 0x0e, 0xc6, 0x40, 0x4e, 0x14, 0x00, +0x40, 0x90, 0x08, 0x00, 0x41, 0xe2, 0x98, 0x03, 0x89, 0x21, 0x41, 0xef, 0x10, 0x03, 0xf0, 0x16, +0x41, 0xe4, 0xf8, 0x00, 0x46, 0x2e, 0xaa, 0x12, 0x41, 0xef, 0x70, 0x0b, 0x58, 0x21, 0x07, 0xfa, +0x40, 0x1f, 0x10, 0x00, 0x98, 0xc2, 0x40, 0xa2, 0x14, 0x03, 0x98, 0xde, 0x40, 0xa5, 0x04, 0x03, +0x89, 0x43, 0x46, 0x0d, 0x4e, 0xf3, 0xf3, 0x13, 0x40, 0xa5, 0x54, 0x0b, 0x58, 0x00, 0x00, 0x85, +0x40, 0x65, 0x04, 0x00, 0x98, 0x98, 0x40, 0x70, 0x90, 0x03, 0x98, 0x95, 0x40, 0x73, 0x98, 0x03, +0x99, 0xd7, 0x46, 0x30, 0x48, 0x81, 0xf2, 0x10, 0x40, 0x73, 0xc0, 0x0b, 0x58, 0x31, 0x8d, 0x05, +0x99, 0x7e, 0x40, 0x81, 0x0c, 0x00, 0x41, 0xc3, 0x04, 0x03, 0x89, 0x04, 0x41, 0xce, 0x14, 0x03, +0xf0, 0x0d, 0x41, 0xc4, 0x70, 0x00, 0x46, 0x2d, 0x9d, 0x4d, 0x41, 0xce, 0x24, 0x0b, 0x58, 0x21, +0x00, 0x39, 0x40, 0x4e, 0x14, 0x00, 0x40, 0x90, 0x08, 0x00, 0x41, 0xe2, 0x98, 0x03, 0x89, 0x21, +0x41, 0xef, 0x10, 0x03, 0xf0, 0x0a, 0x41, 0xe4, 0xf8, 0x00, 0x46, 0x1e, 0x6d, 0xb9, 0x41, 0xef, +0x70, 0x0b, 0x58, 0x10, 0x89, 0xe5, 0x40, 0x9f, 0x10, 0x00, 0x98, 0xc1, 0x40, 0xa2, 0x14, 0x03, +0x98, 0xde, 0x40, 0xa5, 0x24, 0x03, 0x89, 0x43, 0x46, 0x01, 0xfa, 0x27, 0xf3, 0x07, 0x58, 0x00, +0x0c, 0xf8, 0x40, 0xa5, 0x54, 0x0b, 0x89, 0x49, 0x98, 0x98, 0x40, 0x74, 0x90, 0x03, 0x98, 0x95, +0x40, 0x73, 0xa8, 0x03, 0xf1, 0x14, 0x99, 0xd7, 0x46, 0x2c, 0x4a, 0xc5, 0x58, 0x21, 0x06, 0x65, +0x40, 0x73, 0xc0, 0x0b, 0x88, 0xea, 0x40, 0x80, 0x88, 0x00, 0x41, 0xc5, 0x24, 0x03, 0x89, 0x04, +0x41, 0xce, 0x1c, 0x03, 0x41, 0xc4, 0x70, 0x00, 0xf3, 0x16, 0x41, 0xce, 0x24, 0x0b, 0x46, 0x5f, +0x42, 0x92, 0x40, 0x2e, 0x1c, 0x00, 0x41, 0xe5, 0x28, 0x05, 0x58, 0x52, 0x82, 0x44, 0x99, 0x9d, +0x41, 0xe1, 0x78, 0x04, 0x88, 0xc9, 0x41, 0xef, 0x1c, 0x03, 0x41, 0xe3, 0x78, 0x00, 0xf0, 0x0f, +0x41, 0xef, 0x68, 0x0b, 0x46, 0x14, 0x32, 0xaf, 0x41, 0xef, 0x08, 0x00, 0x40, 0x63, 0x9c, 0x05, +0x58, 0x10, 0x8f, 0x97, 0x99, 0x41, 0x40, 0x6f, 0x18, 0x04, 0x88, 0xaa, 0x40, 0xa3, 0x08, 0x03, +0x89, 0x45, 0xf3, 0x08, 0x40, 0xa5, 0x58, 0x0b, 0x46, 0x0a, 0xb9, 0x42, 0x40, 0x85, 0x78, 0x00, +0x40, 0x51, 0x08, 0x05, 0x58, 0x00, 0x03, 0xa7, 0x99, 0x18, 0x40, 0x54, 0x14, 0x04, 0x99, 0x27, +0x40, 0x72, 0xf8, 0x03, 0x99, 0xe7, 0xf1, 0x11, 0x40, 0x73, 0xc4, 0x0b, 0x46, 0x3f, 0xc9, 0x3a, +0x40, 0x43, 0xa0, 0x00, 0x41, 0xcf, 0x78, 0x05, 0x58, 0x31, 0x80, 0x39, 0x40, 0xa0, 0x8c, 0x00, +0x41, 0xc2, 0x70, 0x04, 0x89, 0x42, 0x41, 0xce, 0x20, 0x03, 0x41, 0xc5, 0x70, 0x00, 0xf5, 0x0a, +0x41, 0xce, 0x2c, 0x0b, 0x46, 0x06, 0x55, 0xb5, 0x41, 0xce, 0x10, 0x00, 0x40, 0xa4, 0x20, 0x05, +0x58, 0x00, 0x09, 0xc3, 0x99, 0xe8, 0x40, 0xae, 0x28, 0x04, 0x88, 0xfe, 0x41, 0xe5, 0x10, 0x03, +0x41, 0xe3, 0xf8, 0x00, 0xf1, 0x13, 0x41, 0xef, 0x68, 0x0b, 0x46, 0x28, 0xf0, 0xcc, 0x40, 0x6f, +0x70, 0x00, 0x40, 0xa2, 0x10, 0x05, 0x58, 0x21, 0x0c, 0x92, 0x41, 0xe0, 0x88, 0x00, 0x40, 0xa3, +0x28, 0x04, 0x41, 0xef, 0x20, 0x00, 0x40, 0xa5, 0x70, 0x03, 0x89, 0x5e, 0xf3, 0x0c, 0x40, 0xa5, +0x58, 0x0b, 0x46, 0x0f, 0xfe, 0xff, 0x40, 0x55, 0x18, 0x00, 0x40, 0x7e, 0x70, 0x05, 0x58, 0x00, +0x04, 0x7d, 0x40, 0x91, 0x80, 0x00, 0x40, 0x72, 0x9c, 0x04, 0x89, 0x24, 0x40, 0x73, 0x98, 0x03, +0x88, 0xe9, 0xf1, 0x15, 0x40, 0x73, 0xc4, 0x0b, 0x46, 0x28, 0x58, 0x45, 0x99, 0x3d, 0x40, 0x93, +0x18, 0x05, 0x58, 0x21, 0x0d, 0xd1, 0x98, 0xca, 0x40, 0x92, 0x24, 0x04, 0x88, 0x7c, 0x41, 0xc4, +0x94, 0x03, 0x41, 0xc1, 0xf0, 0x00, 0x41, 0xce, 0x2c, 0x0b, 0xf3, 0x0e, 0x46, 0x06, 0xfa, 0x87, +0x41, 0xce, 0x10, 0x00, 0x41, 0xe2, 0x94, 0x05, 0x58, 0x00, 0x0e, 0x4f, 0x98, 0x98, 0x41, 0xee, +0x78, 0x04, 0x98, 0x96, 0x41, 0xef, 0x10, 0x03, 0x41, 0xe1, 0x78, 0x00, 0xf1, 0x07, 0x41, 0xef, +0x68, 0x0b, 0x46, 0x3f, 0xe2, 0xce, 0x40, 0x2f, 0x70, 0x00, 0x40, 0xa2, 0x10, 0x05, 0x58, 0x31, +0x86, 0xe0, 0x40, 0x80, 0x8c, 0x00, 0x40, 0xa1, 0x28, 0x04, 0x89, 0x05, 0x40, 0xa5, 0x70, 0x03, +0x89, 0x48, 0xf5, 0x10, 0x40, 0xa5, 0x58, 0x0b, 0x46, 0x0a, 0x30, 0x14, 0x40, 0x85, 0x08, 0x00, +0x40, 0x7e, 0x70, 0x05, 0x58, 0x00, 0x03, 0x14, 0x99, 0xa8, 0x40, 0x74, 0x1c, 0x04, 0x99, 0xb4, +0x40, 0x73, 0x88, 0x03, 0x99, 0xf7, 0xf1, 0x09, 0x40, 0x73, 0xc4, 0x0b, 0x46, 0x34, 0xe0, 0x81, +0x40, 0x63, 0xa0, 0x00, 0x58, 0x31, 0x81, 0xa1, 0x40, 0x71, 0x08, 0x05, 0x99, 0x0b, 0x40, 0x73, +0x1c, 0x04, 0x40, 0x73, 0xa0, 0x03, 0x88, 0x9c, 0x99, 0x27, 0xf0, 0x12, 0x40, 0x42, 0x2c, 0x0b, +0x46, 0x1f, 0x75, 0x37, 0x99, 0x26, 0x41, 0xe4, 0x20, 0x05, 0x58, 0x10, 0x8e, 0x82, 0x99, 0x41, +0x41, 0xe2, 0x78, 0x04, 0x99, 0x6a, 0x41, 0xef, 0x18, 0x03, 0x41, 0xe2, 0xf8, 0x00, 0xf2, 0x0b, +0x41, 0xef, 0x68, 0x0b, 0x46, 0x3b, 0xd3, 0xaf, 0x41, 0xef, 0x10, 0x00, 0x40, 0xa3, 0x18, 0x05, +0x58, 0x31, 0x82, 0x35, 0x41, 0xc1, 0x0c, 0x00, 0x40, 0xaf, 0x28, 0x04, 0x41, 0xce, 0x20, 0x00, +0x40, 0xa5, 0x10, 0x03, 0x89, 0x5c, 0xf5, 0x14, 0x40, 0xa5, 0x58, 0x0b, 0x46, 0x02, 0xad, 0x7d, +0x40, 0x25, 0x78, 0x00, 0x40, 0x72, 0x10, 0x05, 0x58, 0x00, 0x02, 0xbb, 0x40, 0x92, 0x80, 0x00, +0x40, 0x71, 0x1c, 0x04, 0x89, 0x26, 0x40, 0x73, 0xf8, 0x03, 0x88, 0xe9, 0xf1, 0x0d, 0x40, 0x73, +0xc4, 0x0b, 0x46, 0x5e, 0xb8, 0x6d, 0x98, 0xfa, 0xf0, 0x02, 0x40, 0x7f, 0x78, 0x05, 0x58, 0x52, +0x83, 0x91, 0x40, 0x80, 0x94, 0x00, 0x40, 0x71, 0x9c, 0x04, 0xf1, 0x01, 0x99, 0x98, 0x40, 0x73, +0x88, 0x03, 0xf0, 0x03, 0x88, 0x88, 0x40, 0x5f, 0x04, 0x00, 0x99, 0x27, 0xf1, 0x04, 0x98, 0xc3, +0x40, 0x42, 0x2c, 0x0b, 0xf0, 0x05, 0x99, 0x34, 0x98, 0x8a, 0xb6, 0xa0, 0xa9, 0x01, 0xa8, 0xc2, +0xa8, 0x83, 0x84, 0x20, 0xf0, 0x17, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0xa8, 0xcf, 0xf2, 0x05, +0x84, 0x20, 0x14, 0x11, 0x00, 0x16, 0xec, 0xa4, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x04, 0x00, 0x00, 0x16, 0x50, 0x73, 0x00, 0x18, +0x81, 0x01, 0x98, 0x38, 0x44, 0x10, 0x00, 0x80, 0x84, 0x41, 0x49, 0xfe, 0xa8, 0xb7, 0x04, 0x03, +0x00, 0x16, 0x5c, 0xf0, 0x00, 0x38, 0xe9, 0x04, 0x80, 0x06, 0x49, 0xff, 0xfa, 0xc5, 0xa0, 0xf4, +0xa1, 0x35, 0x40, 0x01, 0xf4, 0x09, 0x95, 0x23, 0x40, 0x42, 0x00, 0x04, 0x94, 0xdb, 0xf4, 0x81, +0xb6, 0x7f, 0x80, 0x3f, 0x84, 0x48, 0x50, 0x03, 0x80, 0x38, 0x49, 0xfe, 0xa8, 0x89, 0x80, 0x06, +0x49, 0xff, 0xfa, 0xb2, 0x80, 0x08, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, 0xa8, 0x80, +0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe0, +0x8c, 0x18, 0xf1, 0x81, 0x83, 0x82, 0xb6, 0x1f, 0x85, 0x00, 0xd5, 0x28, 0x04, 0x33, 0x80, 0x16, +0xf1, 0x01, 0xb4, 0x1f, 0x40, 0x50, 0xa0, 0x00, 0x99, 0x03, 0x40, 0x93, 0x0c, 0x00, 0x80, 0x25, +0x80, 0x04, 0x5c, 0xf4, 0x80, 0x40, 0xe8, 0x0a, 0x49, 0xfe, 0xa8, 0x62, 0x04, 0x23, 0x80, 0x16, +0x89, 0x06, 0x98, 0x96, 0x14, 0x23, 0x80, 0x16, 0xd5, 0x11, 0x52, 0x21, 0x80, 0x40, 0x49, 0xfe, +0xa8, 0x57, 0x44, 0x00, 0x00, 0x40, 0x04, 0x13, 0x80, 0x16, 0x14, 0x03, 0x80, 0x16, 0x9a, 0x41, +0x80, 0x07, 0x89, 0x01, 0x49, 0xff, 0xfa, 0x78, 0x92, 0x00, 0x40, 0x6e, 0x20, 0x01, 0x80, 0x46, +0x4c, 0x8e, 0x7f, 0xd6, 0xa0, 0x3c, 0xa0, 0x7d, 0x80, 0x48, 0x84, 0x60, 0x99, 0x02, 0xe2, 0x82, +0x99, 0x4b, 0x88, 0xaf, 0xa9, 0x3c, 0xa9, 0x7d, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x3e, 0x19, 0x57, 0xa4, 0x80, 0xc0, 0x44, 0x20, 0x00, 0x10, 0x49, 0xfe, +0xa8, 0x2f, 0x50, 0x03, 0x00, 0x18, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0xa8, 0x3e, +0x84, 0x00, 0x14, 0x03, 0x00, 0x16, 0x84, 0x20, 0x84, 0x00, 0xa8, 0x34, 0xa8, 0x75, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x9c, 0x81, 0x20, 0x81, 0x01, 0x80, 0xe2, +0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x80, 0x1f, 0x49, 0xfe, 0xa8, 0x28, 0x80, 0x1f, 0x49, 0xff, +0xff, 0xd9, 0x80, 0x1f, 0x80, 0x29, 0x80, 0x48, 0x49, 0xff, 0xff, 0x90, 0x80, 0x1f, 0x80, 0x27, +0x80, 0xdf, 0x49, 0xff, 0xff, 0x57, 0xec, 0x64, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xd4, 0x51, 0xcf, 0x81, 0x08, 0x80, 0xc0, 0x81, 0x42, 0x44, 0x20, +0x00, 0x10, 0x80, 0x1c, 0x81, 0x23, 0x81, 0x04, 0x49, 0xfe, 0xa7, 0xf2, 0x80, 0x26, 0x44, 0x20, +0x00, 0x10, 0x50, 0x0f, 0x81, 0x18, 0x49, 0xfe, 0xa7, 0xeb, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x20, +0x80, 0x1f, 0x49, 0xff, 0xf8, 0xa3, 0x80, 0x1f, 0x44, 0x10, 0x01, 0x00, 0x49, 0xff, 0xf8, 0xf0, +0x80, 0x1f, 0x80, 0x2a, 0x80, 0x49, 0x80, 0x68, 0x80, 0xdf, 0x49, 0xff, 0xf8, 0xbf, 0x92, 0x00, +0xed, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, +0xff, 0xd1, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xee, 0xb4, 0x80, 0xc0, 0x50, 0x00, 0x00, 0x20, 0xf0, 0x81, 0x50, 0x9f, 0x80, 0x08, 0xf1, 0x01, +0x44, 0x20, 0x00, 0x40, 0x80, 0x09, 0x49, 0xfe, 0xa7, 0xbb, 0x50, 0x8f, 0x80, 0x48, 0x83, 0xc9, +0x80, 0x49, 0xb4, 0x02, 0x44, 0x50, 0xff, 0x00, 0x46, 0xa0, 0x0f, 0xf0, 0x40, 0x40, 0x60, 0x09, +0x40, 0x10, 0x60, 0x08, 0x40, 0x30, 0x14, 0x02, 0x40, 0x12, 0x04, 0x04, 0x40, 0x31, 0xa0, 0x08, +0x40, 0x00, 0x28, 0x02, 0x40, 0x10, 0x8c, 0x04, 0x92, 0x08, 0x40, 0x00, 0x80, 0x04, 0xaa, 0x11, +0x4c, 0x24, 0x7f, 0xe9, 0x50, 0x2f, 0x80, 0x3c, 0x50, 0x34, 0x81, 0x34, 0x04, 0x41, 0x7f, 0xfb, +0xb4, 0x22, 0x04, 0x01, 0x7f, 0xf5, 0x40, 0x12, 0x04, 0x03, 0x04, 0x41, 0x7f, 0xf3, 0x40, 0x00, +0x80, 0x03, 0x40, 0x00, 0x10, 0x03, 0x40, 0x00, 0x7c, 0x0b, 0xa8, 0x13, 0x9c, 0x94, 0x4c, 0x21, +0xff, 0xef, 0xb4, 0x06, 0x04, 0x83, 0x00, 0x01, 0xa1, 0x32, 0xa0, 0xf3, 0x05, 0xc3, 0x00, 0x04, +0x50, 0x14, 0x80, 0x50, 0x80, 0xe0, 0x0c, 0x5f, 0x00, 0x01, 0x46, 0xa5, 0xa8, 0x27, 0x58, 0xa5, +0x09, 0x99, 0x40, 0x24, 0x20, 0x05, 0x88, 0xaa, 0x88, 0xbc, 0x40, 0xa2, 0x20, 0x02, 0x41, 0xc3, +0xec, 0x0b, 0x40, 0x21, 0x0c, 0x02, 0x88, 0xbc, 0x40, 0x21, 0x28, 0x03, 0x99, 0x6a, 0x83, 0x83, +0x40, 0x24, 0x08, 0x0b, 0x81, 0x07, 0x4d, 0xe0, 0x80, 0x06, 0x80, 0x64, 0x80, 0xe5, 0x80, 0x82, +0xd5, 0xe3, 0x83, 0xc3, 0x50, 0x8f, 0x80, 0x58, 0x50, 0xa4, 0x80, 0xa0, 0x0d, 0xc4, 0x00, 0x01, +0x46, 0x36, 0xed, 0x9e, 0x58, 0x31, 0x8b, 0xa1, 0x41, 0xce, 0x0c, 0x00, 0x40, 0x11, 0x1c, 0x03, +0x41, 0xce, 0x78, 0x00, 0x40, 0x32, 0xec, 0x0b, 0x41, 0xce, 0x0c, 0x00, 0x40, 0x10, 0x90, 0x03, +0x40, 0x33, 0x88, 0x0b, 0x41, 0xce, 0x04, 0x00, 0x83, 0xc4, 0x80, 0xe5, 0x4c, 0x85, 0x00, 0x06, +0x80, 0x82, 0x80, 0xbc, 0x80, 0x43, 0xd5, 0xe3, 0x81, 0x05, 0x80, 0xbc, 0x80, 0xe2, 0x51, 0xcf, +0x80, 0xa8, 0x50, 0x14, 0x80, 0xf0, 0x0c, 0x4e, 0x00, 0x01, 0x46, 0xa8, 0xf1, 0xbb, 0x58, 0xa5, +0x0c, 0xdc, 0x88, 0x8a, 0x40, 0x21, 0x9c, 0x03, 0x88, 0x9e, 0x40, 0x21, 0x20, 0x02, 0x41, 0xe2, +0xec, 0x0b, 0x40, 0xa3, 0x8c, 0x02, 0x88, 0x9e, 0x40, 0x21, 0x28, 0x03, 0x99, 0x22, 0x83, 0xc7, +0x40, 0x24, 0x08, 0x0b, 0x81, 0x05, 0x4d, 0xc0, 0x80, 0x06, 0x80, 0xe3, 0x80, 0xa4, 0x80, 0x62, +0xd5, 0xe3, 0x83, 0x87, 0x50, 0x94, 0x81, 0x40, 0x50, 0x7f, 0x80, 0xf8, 0x0c, 0xa3, 0x80, 0x01, +0x46, 0x8c, 0xa6, 0x2c, 0x58, 0x84, 0x01, 0xd6, 0x89, 0x48, 0x40, 0x11, 0x14, 0x03, 0x89, 0x5c, +0x40, 0x82, 0x6c, 0x0b, 0x89, 0x48, 0x40, 0x10, 0x8c, 0x03, 0x40, 0x82, 0x88, 0x0b, 0x89, 0x41, +0x83, 0x83, 0x80, 0xa4, 0x4c, 0x74, 0x80, 0x06, 0x80, 0x62, 0x80, 0x8a, 0x80, 0x48, 0xd5, 0xe7, +0x05, 0xc3, 0x00, 0x01, 0x04, 0x93, 0x00, 0x02, 0xa1, 0xf3, 0xa1, 0x74, 0x89, 0x40, 0x88, 0x9c, +0x98, 0xba, 0x98, 0xeb, 0x89, 0x09, 0xa8, 0xb3, 0xb7, 0x46, 0xa9, 0x31, 0x14, 0x83, 0x00, 0x02, +0xa8, 0xf4, 0x84, 0x20, 0xf0, 0x01, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0xa6, 0xf7, 0x84, 0x00, +0x14, 0x03, 0x00, 0x18, 0xed, 0x4c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x80, 0xc0, 0x04, 0x00, 0x00, 0x18, 0x50, 0x73, 0x00, 0x20, 0x81, 0x01, 0x98, 0x38, +0x44, 0x10, 0x00, 0x80, 0x84, 0x41, 0x49, 0xfe, 0xa6, 0xe1, 0x04, 0x03, 0x00, 0x18, 0x5c, 0xf0, +0x00, 0x38, 0xe9, 0x04, 0x80, 0x06, 0x49, 0xff, 0xfe, 0xfb, 0xa0, 0xf6, 0xa0, 0xb7, 0x40, 0x01, +0xf4, 0x09, 0x94, 0x93, 0x40, 0x20, 0x08, 0x04, 0x94, 0xdb, 0x44, 0x00, 0xff, 0x00, 0x46, 0x10, +0x0f, 0xf0, 0x40, 0xa1, 0x80, 0x02, 0x40, 0x41, 0x00, 0x02, 0x40, 0x51, 0x84, 0x02, 0x40, 0x01, +0xe0, 0x08, 0x40, 0x91, 0x60, 0x08, 0x40, 0x11, 0x04, 0x02, 0x40, 0xa5, 0x20, 0x08, 0x40, 0x42, +0x20, 0x08, 0x92, 0xa8, 0x92, 0x28, 0x40, 0x05, 0x00, 0x04, 0x40, 0x44, 0x90, 0x04, 0x40, 0x00, +0x14, 0x04, 0x40, 0x42, 0x04, 0x04, 0x92, 0x58, 0x92, 0x78, 0x40, 0x31, 0x80, 0x04, 0x40, 0x42, +0x08, 0x04, 0x80, 0x3f, 0x84, 0x48, 0x50, 0x03, 0x80, 0x38, 0xb6, 0x9f, 0xf3, 0x81, 0x49, 0xfe, +0xa6, 0x8f, 0x80, 0x06, 0x49, 0xff, 0xfe, 0xc4, 0x84, 0x40, 0x38, 0x33, 0x08, 0x02, 0x44, 0x50, +0xff, 0x00, 0x47, 0xc0, 0x0f, 0xf0, 0x40, 0x41, 0xe0, 0x09, 0x40, 0x01, 0xe0, 0x08, 0x40, 0x11, +0x94, 0x02, 0x40, 0x02, 0x00, 0x04, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x31, 0xf0, 0x02, 0x40, 0x00, +0x04, 0x04, 0x92, 0x68, 0x40, 0x30, 0x0c, 0x04, 0x38, 0x33, 0x08, 0x0a, 0x44, 0x00, 0x00, 0x14, +0x9c, 0x94, 0x4c, 0x20, 0x7f, 0xe4, 0x80, 0x08, 0x80, 0x26, 0x49, 0xfe, 0xa6, 0x69, 0x92, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe0, +0x50, 0x00, 0x00, 0x20, 0xf1, 0x81, 0x83, 0x82, 0xb6, 0x1f, 0x85, 0x00, 0xd5, 0x27, 0x04, 0x33, +0x80, 0x18, 0xf1, 0x01, 0xb4, 0x1f, 0x40, 0x50, 0xa0, 0x00, 0x99, 0x03, 0x40, 0x93, 0x0c, 0x00, +0x80, 0x25, 0x80, 0x04, 0x5c, 0xf4, 0x80, 0x40, 0xe8, 0x0a, 0x49, 0xfe, 0xa6, 0x49, 0x04, 0x23, +0x80, 0x18, 0x89, 0x06, 0x98, 0x96, 0x14, 0x23, 0x80, 0x18, 0xd5, 0x10, 0x52, 0x21, 0x80, 0x40, +0x49, 0xfe, 0xa6, 0x3e, 0x44, 0x00, 0x00, 0x40, 0x04, 0x13, 0x80, 0x18, 0x14, 0x03, 0x80, 0x18, +0x9a, 0x41, 0x80, 0x07, 0x89, 0x01, 0x49, 0xff, 0xfe, 0x6b, 0x40, 0x6e, 0x20, 0x01, 0x80, 0x46, +0x4c, 0x8e, 0x7f, 0xd7, 0xa0, 0x3e, 0xa0, 0x7f, 0x80, 0x48, 0x84, 0x60, 0x99, 0x02, 0xe2, 0x82, +0x99, 0x4b, 0x88, 0xaf, 0xa9, 0x3e, 0xa9, 0x7f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x3e, 0x19, 0x57, 0xc4, 0x80, 0xc0, 0x44, 0x20, 0x00, 0x14, 0x49, 0xfe, +0xa6, 0x17, 0x50, 0x03, 0x00, 0x20, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x49, 0xfe, 0xa6, 0x26, +0x84, 0x00, 0x14, 0x03, 0x00, 0x18, 0x84, 0x20, 0x84, 0x00, 0xa8, 0x36, 0xa8, 0x77, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x94, 0x81, 0x20, 0x81, 0x01, 0x80, 0xe2, +0x84, 0x20, 0x44, 0x20, 0x00, 0x68, 0x80, 0x1f, 0x49, 0xfe, 0xa6, 0x10, 0x80, 0x1f, 0x49, 0xff, +0xff, 0xd9, 0x80, 0x1f, 0x80, 0x29, 0x80, 0x48, 0x49, 0xff, 0xff, 0x90, 0x80, 0x1f, 0x80, 0x27, +0x80, 0xdf, 0x49, 0xff, 0xff, 0x15, 0xec, 0x6c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x84, 0x23, 0x42, 0x00, 0x04, 0x24, 0x84, 0x20, 0xd5, 0x08, 0x84, 0x40, 0x92, 0x00, 0x84, 0x67, +0x9c, 0x91, 0x4c, 0x21, 0xff, 0xfd, 0x9c, 0x49, 0xe2, 0x20, 0xe9, 0xf8, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x48, 0xb4, 0x20, 0x81, 0x00, +0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0x84, 0xc0, 0xb4, 0x08, 0x40, 0x10, 0x30, 0x09, 0x42, 0x20, +0x70, 0x0b, 0x9d, 0xb1, 0x54, 0x10, 0x80, 0x03, 0x84, 0x0a, 0xc2, 0x03, 0x84, 0xa3, 0xd1, 0x06, +0x49, 0xff, 0xff, 0xd8, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, +0x01, 0x48, 0xb4, 0x06, 0x46, 0x1f, 0xf8, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x00, 0x04, 0x02, +0xb6, 0x06, 0x84, 0x01, 0x49, 0xff, 0xff, 0xc6, 0xb4, 0x26, 0x46, 0x2f, 0x0f, 0xff, 0x58, 0x21, +0x0f, 0xff, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x26, 0x84, 0x01, 0x49, 0xff, 0xff, 0xbb, 0xb4, 0x06, +0x46, 0x30, 0xf0, 0x00, 0x40, 0x00, 0x0c, 0x04, 0xb6, 0x06, 0xb4, 0x06, 0x46, 0x20, 0x04, 0x01, +0x92, 0x0c, 0x40, 0x00, 0x30, 0x08, 0xb6, 0x06, 0x04, 0x31, 0x00, 0x81, 0x42, 0x31, 0x8c, 0x09, +0x14, 0x31, 0x00, 0x81, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x20, 0x80, 0x01, 0x58, 0x21, +0x00, 0x01, 0x14, 0x20, 0x80, 0x20, 0x04, 0x10, 0x00, 0x19, 0x42, 0x10, 0xc8, 0x09, 0x14, 0x10, +0x00, 0x19, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x01, 0x48, 0xb4, 0x20, 0x46, 0x2f, 0xf8, 0x0f, 0x46, 0x30, 0x05, 0xf0, 0x40, 0x10, +0x88, 0x02, 0x58, 0x31, 0x80, 0x02, 0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, 0x81, 0x00, 0x84, 0xc0, +0xb4, 0x08, 0x9d, 0xb1, 0x40, 0x10, 0x30, 0x09, 0x40, 0x20, 0x70, 0x09, 0x54, 0x10, 0x80, 0x03, +0x84, 0x0a, 0xca, 0x02, 0xc1, 0x06, 0x49, 0xff, 0xff, 0x75, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf1, +0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x52, 0x92, 0x4c, 0x40, 0x21, 0x30, 0x08, 0x14, 0x20, +0x00, 0x52, 0x80, 0x20, 0x04, 0x20, 0x80, 0x20, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x80, 0x20, +0x04, 0x10, 0x00, 0x19, 0x42, 0x10, 0xc8, 0x08, 0x14, 0x10, 0x00, 0x19, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0x70, 0x04, 0x10, 0x84, 0x21, 0x84, 0xc0, +0x04, 0x93, 0x82, 0x8c, 0x9d, 0xb1, 0x54, 0x84, 0x80, 0xff, 0x84, 0x01, 0x4e, 0x82, 0x00, 0x0a, +0x49, 0xff, 0xff, 0x48, 0x44, 0x00, 0x07, 0xd0, 0x84, 0x20, 0x4c, 0x60, 0x7f, 0xf3, 0xd5, 0x02, +0xc9, 0x05, 0x80, 0x29, 0x3e, 0x09, 0x59, 0x4c, 0xd5, 0x15, 0x46, 0x60, 0x04, 0x10, 0x84, 0x21, +0x04, 0x73, 0x01, 0x0e, 0x8d, 0x01, 0x84, 0x01, 0xc7, 0x09, 0x49, 0xff, 0xff, 0x33, 0x44, 0x00, +0x61, 0xa8, 0x84, 0x20, 0x4c, 0x80, 0x7f, 0xf6, 0xd5, 0x02, 0xc9, 0x07, 0x80, 0x27, 0x3e, 0x09, +0x59, 0x28, 0x49, 0xff, 0xce, 0x7d, 0xd5, 0x19, 0x46, 0x60, 0x04, 0x11, 0x84, 0x21, 0x04, 0x23, +0x00, 0x80, 0x9d, 0xf9, 0x96, 0x94, 0x84, 0x01, 0xc2, 0x09, 0x49, 0xff, 0xff, 0x1b, 0x44, 0x00, +0x13, 0x88, 0x84, 0x20, 0x4c, 0x70, 0x7f, 0xf5, 0xd5, 0x04, 0xc1, 0x03, 0x84, 0x01, 0xd5, 0x06, +0x3e, 0x09, 0x59, 0x3c, 0x49, 0xff, 0xce, 0x64, 0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x00, 0x1c, 0xb4, 0x06, +0x42, 0x00, 0x60, 0x0b, 0xc8, 0x47, 0x50, 0x73, 0x01, 0x14, 0xb4, 0x07, 0x44, 0x21, 0x00, 0x01, +0x40, 0x00, 0x08, 0x04, 0xb6, 0x07, 0x84, 0x01, 0x49, 0xfb, 0xe1, 0x00, 0xb4, 0x06, 0x92, 0x08, +0x40, 0x00, 0x20, 0x08, 0xb6, 0x06, 0x46, 0x80, 0x04, 0x00, 0xb4, 0x26, 0x58, 0x84, 0x01, 0x4c, +0x58, 0x10, 0x80, 0x30, 0xb6, 0x26, 0x84, 0x01, 0x49, 0xff, 0xfe, 0xe4, 0xb4, 0x28, 0x42, 0x10, +0xcc, 0x09, 0x42, 0x10, 0xd0, 0x09, 0xb6, 0x28, 0x84, 0x05, 0xb4, 0x27, 0x42, 0x10, 0xc4, 0x08, +0xb6, 0x27, 0x49, 0xfb, 0xe0, 0xe3, 0xb4, 0x27, 0x42, 0x10, 0xc0, 0x09, 0xb6, 0x27, 0x84, 0x04, +0x49, 0xfb, 0xe0, 0xdc, 0xb4, 0x06, 0x42, 0x00, 0x60, 0x0b, 0xc0, 0x05, 0xb4, 0x06, 0x42, 0x00, +0x64, 0x0b, 0xc0, 0x0a, 0x3e, 0x09, 0x59, 0x64, 0x3e, 0x19, 0x59, 0x74, 0x44, 0x20, 0x02, 0x52, +0x49, 0xff, 0xce, 0x16, 0xd5, 0x00, 0xb4, 0x08, 0x46, 0x10, 0x01, 0x80, 0x40, 0x00, 0x04, 0x04, +0xb6, 0x08, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x96, 0x00, 0x96, 0x48, 0xc8, 0x34, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x17, 0x46, 0x60, +0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x26, 0x84, 0x0a, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x26, +0x49, 0xff, 0xfe, 0xa0, 0xb4, 0x26, 0x84, 0x0a, 0x58, 0x10, 0x80, 0x3a, 0xb6, 0x26, 0x49, 0xff, +0xfe, 0x99, 0xb4, 0x06, 0x84, 0x3b, 0xd5, 0x33, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x30, +0xb4, 0x26, 0x84, 0x05, 0x58, 0x10, 0x80, 0x04, 0xb6, 0x26, 0x49, 0xff, 0xfe, 0x8b, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x01, 0x4c, 0x92, 0x24, 0x94, 0x4c, 0x14, 0x10, 0x01, 0x4c, 0x44, 0x1f, +0xff, 0xc5, 0xb4, 0x06, 0x58, 0x00, 0x00, 0x01, 0xb6, 0x06, 0xb4, 0x06, 0xd5, 0x41, 0x84, 0xa1, +0xd9, 0x25, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x01, 0x30, 0xb4, 0x26, 0x84, 0x0a, 0x58, 0x10, +0x81, 0x00, 0xb6, 0x26, 0x49, 0xff, 0xfe, 0x6e, 0xb4, 0x26, 0x84, 0x0a, 0x58, 0x10, 0xba, 0x00, +0xb6, 0x26, 0x49, 0xff, 0xfe, 0x67, 0xb4, 0x06, 0x44, 0x1f, 0xfb, 0xff, 0x40, 0x00, 0x04, 0x02, +0xb6, 0x06, 0x49, 0xff, 0xff, 0x57, 0x92, 0x00, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x4c, +0x58, 0x10, 0x80, 0x0f, 0x14, 0x10, 0x01, 0x4c, 0xd5, 0x1e, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, +0x01, 0x30, 0xb4, 0x26, 0x84, 0x05, 0x58, 0x10, 0x84, 0x00, 0xb6, 0x26, 0x49, 0xff, 0xfe, 0x4a, +0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x4c, 0x92, 0x24, 0x94, 0x4c, 0x14, 0x10, 0x01, 0x4c, +0x44, 0x1f, 0xc5, 0xff, 0xb4, 0x06, 0x58, 0x00, 0x01, 0x00, 0xb6, 0x06, 0xb4, 0x06, 0x40, 0x00, +0x04, 0x02, 0xb6, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x96, 0x49, 0x80, 0xc0, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xf6, +0xb4, 0xe0, 0x3e, 0x09, 0x59, 0x8c, 0x80, 0x27, 0x49, 0xff, 0xcd, 0x7a, 0x44, 0x50, 0x00, 0x30, +0xdf, 0x47, 0x84, 0x02, 0x84, 0x20, 0x84, 0x41, 0x3e, 0x69, 0xd9, 0xe8, 0x49, 0x00, 0x11, 0xb2, +0x00, 0x03, 0x04, 0x0c, 0x84, 0xa1, 0xd8, 0x08, 0x50, 0x03, 0x03, 0xf0, 0x49, 0xff, 0xcd, 0xb6, +0x84, 0x00, 0x10, 0x03, 0x04, 0x0c, 0x3c, 0x2d, 0xfb, 0x87, 0x84, 0x20, 0x84, 0x03, 0xdd, 0x22, +0x2e, 0x57, 0xef, 0xd1, 0x84, 0xc1, 0x4c, 0x53, 0x00, 0xd0, 0x84, 0x00, 0x80, 0x20, 0x49, 0xff, +0xff, 0x4f, 0x80, 0x06, 0x84, 0x20, 0x49, 0xff, 0xff, 0x4b, 0x49, 0xff, 0xfe, 0x67, 0x3e, 0x61, +0x8a, 0x54, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x40, 0x50, 0xc0, 0x09, 0x40, 0x52, 0xc0, 0x08, +0x46, 0x27, 0x66, 0x20, 0xd2, 0x09, 0xb4, 0x00, 0x46, 0x27, 0x63, 0x20, 0x40, 0x50, 0x40, 0x09, +0x40, 0x52, 0xc0, 0x08, 0xda, 0x06, 0x84, 0x00, 0x84, 0x21, 0x80, 0x40, 0x49, 0x00, 0x3d, 0x8c, +0x2e, 0x11, 0x8a, 0x6b, 0x84, 0x00, 0x49, 0xfb, 0xe4, 0x01, 0x48, 0x00, 0x00, 0xa6, 0x44, 0x50, +0x00, 0x31, 0xdf, 0x38, 0x2e, 0x11, 0x8a, 0x6b, 0x84, 0x00, 0x49, 0xfb, 0xe3, 0xc5, 0x49, 0xff, +0xfd, 0xe1, 0x84, 0x00, 0x84, 0x21, 0x49, 0xff, 0xff, 0x1b, 0x84, 0x01, 0x80, 0x20, 0x49, 0xff, +0xff, 0x17, 0x3c, 0x2d, 0xfb, 0x87, 0x84, 0x21, 0x84, 0x03, 0xdd, 0x22, 0x84, 0x20, 0x3e, 0x11, +0x8a, 0x54, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x40, 0x50, 0xc0, 0x09, 0x40, 0x52, 0xc0, 0x08, +0x46, 0x27, 0x66, 0x20, 0xd2, 0x09, 0xb4, 0x00, 0x46, 0x27, 0x63, 0x20, 0x40, 0x50, 0x40, 0x09, +0x40, 0x52, 0xc0, 0x08, 0xda, 0x08, 0x49, 0x00, 0x3a, 0x97, 0x84, 0x00, 0x84, 0x22, 0x80, 0x40, +0x49, 0x00, 0x3d, 0x52, 0x84, 0x00, 0x80, 0x20, 0x80, 0x40, 0x49, 0x00, 0x08, 0x1d, 0x48, 0x00, +0x00, 0x6c, 0x44, 0x50, 0x00, 0x34, 0xdf, 0x58, 0x50, 0x03, 0x00, 0x18, 0x50, 0x23, 0x00, 0x08, +0x9c, 0xf4, 0x50, 0x13, 0x00, 0x10, 0x8c, 0xd4, 0xb4, 0x63, 0xb5, 0x22, 0x84, 0x65, 0xb4, 0x21, +0xb4, 0x26, 0xb4, 0x40, 0x3e, 0x09, 0xde, 0x18, 0x84, 0x21, 0x84, 0xc0, 0xae, 0xc4, 0x84, 0x60, +0x10, 0x10, 0x00, 0x12, 0xae, 0xc5, 0xae, 0x40, 0x14, 0x90, 0x00, 0x03, 0xa9, 0x82, 0x5c, 0xf1, +0x01, 0x92, 0xe9, 0x07, 0x80, 0x22, 0x3e, 0x09, 0x59, 0xa4, 0x49, 0xff, 0xcc, 0xd1, 0x80, 0x46, +0x40, 0x31, 0x04, 0x09, 0x3e, 0x79, 0xde, 0x18, 0x96, 0x94, 0x10, 0x23, 0x80, 0x13, 0x10, 0x33, +0x80, 0x14, 0xa6, 0x7c, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x09, 0x4c, 0x3e, 0x09, 0x59, 0xd8, +0xdd, 0x26, 0x80, 0x29, 0x3e, 0x09, 0x59, 0xf0, 0xdd, 0x26, 0x3c, 0x1c, 0x62, 0x7b, 0x3e, 0x09, +0x5a, 0x00, 0xdd, 0x26, 0x3e, 0x09, 0x5a, 0x10, 0x84, 0x20, 0xdd, 0x26, 0x00, 0x23, 0x80, 0x14, +0x00, 0x13, 0x80, 0x13, 0x3e, 0x09, 0x5a, 0x20, 0x3e, 0x79, 0xd9, 0xe8, 0xdd, 0x26, 0x00, 0x03, +0x84, 0x0c, 0xc0, 0x1a, 0x50, 0x03, 0x83, 0xf0, 0x49, 0xff, 0xcc, 0xf0, 0x92, 0x00, 0x84, 0x00, +0x10, 0x03, 0x84, 0x0c, 0xd5, 0x11, 0x44, 0x50, 0x00, 0x35, 0xdf, 0x0e, 0x84, 0x20, 0x3e, 0x29, +0xde, 0x18, 0x10, 0x11, 0x00, 0x12, 0x3e, 0x11, 0x8a, 0x56, 0xae, 0x50, 0xae, 0x54, 0x3e, 0x09, +0x5a, 0x44, 0x49, 0xff, 0xcc, 0x8d, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x2e, 0x11, 0x8a, 0x6b, 0x84, 0x00, 0x49, 0xfb, 0xe3, 0x1d, 0x49, 0xff, +0xfd, 0x39, 0x84, 0x00, 0x84, 0x21, 0x49, 0xff, 0xfe, 0x73, 0x84, 0x01, 0x80, 0x20, 0x49, 0xff, +0xfe, 0x6f, 0x3c, 0x2d, 0xfb, 0x87, 0x84, 0x21, 0x84, 0x03, 0xdd, 0x22, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x00, 0x80, 0x20, 0x49, 0xff, 0xfe, 0x60, +0x84, 0x01, 0x84, 0x20, 0x49, 0xff, 0xfe, 0x5c, 0x49, 0xff, 0xfd, 0x78, 0x92, 0x00, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x04, 0x11, 0x58, 0x63, +0x00, 0x04, 0xb4, 0x06, 0x42, 0x00, 0x0c, 0x09, 0xb6, 0x06, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, +0x80, 0xd0, 0x42, 0x21, 0x50, 0x09, 0x14, 0x20, 0x80, 0xd0, 0x80, 0x01, 0x04, 0x10, 0x01, 0x82, +0x42, 0x10, 0x84, 0x09, 0x14, 0x10, 0x01, 0x82, 0x49, 0xff, 0xfd, 0x96, 0x84, 0xa1, 0xd8, 0x05, +0xb4, 0x06, 0x42, 0x00, 0x08, 0x09, 0xb6, 0x06, 0x46, 0x10, 0x04, 0x11, 0xa0, 0x89, 0x42, 0x21, +0x0c, 0x09, 0xa8, 0x89, 0x80, 0x01, 0x04, 0x30, 0x00, 0xd1, 0x46, 0x10, 0x00, 0x92, 0x58, 0x10, +0x8b, 0x00, 0x3c, 0x3e, 0x62, 0xae, 0x46, 0x70, 0x04, 0x10, 0x14, 0x10, 0x00, 0xd1, 0x84, 0xc0, +0x46, 0x10, 0x04, 0x10, 0x04, 0x03, 0x81, 0x0c, 0x04, 0x10, 0x81, 0x0e, 0x40, 0x10, 0xa0, 0x08, +0x92, 0x38, 0xc1, 0x03, 0x84, 0x00, 0xd5, 0x04, 0x92, 0x10, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, +0x04, 0x10, 0x80, 0x22, 0x04, 0x31, 0x02, 0x8c, 0x04, 0x10, 0x82, 0x8d, 0x84, 0x40, 0x40, 0x01, +0x0c, 0x1b, 0xc9, 0x02, 0xc8, 0x1c, 0x49, 0x00, 0x02, 0x6f, 0xd5, 0x10, 0x49, 0xff, 0xcd, 0xbe, +0x00, 0x30, 0x00, 0x14, 0x80, 0x40, 0x80, 0x20, 0x3e, 0x09, 0xd3, 0x00, 0xc3, 0x02, 0xd5, 0x04, +0x80, 0x22, 0x3e, 0x09, 0xd3, 0x10, 0x49, 0xff, 0xcd, 0xd3, 0x3c, 0x3c, 0x76, 0xaa, 0x3e, 0x09, +0xda, 0xa0, 0xcb, 0xed, 0x9d, 0xb1, 0x44, 0x50, 0x07, 0xd0, 0xde, 0xcb, 0x46, 0x80, 0x04, 0x11, +0x46, 0x70, 0x04, 0x12, 0x84, 0xc0, 0x45, 0xc0, 0x2e, 0xb8, 0x04, 0xa4, 0x00, 0x80, 0x04, 0x93, +0x80, 0x4c, 0x54, 0xa5, 0x00, 0x03, 0x4e, 0xa3, 0x00, 0x04, 0x4e, 0x92, 0x00, 0x15, 0x5c, 0xf3, +0x01, 0x2c, 0xe9, 0x07, 0x3e, 0x09, 0x5a, 0x60, 0x80, 0x2a, 0x80, 0x49, 0x49, 0xff, 0xcb, 0xd8, +0x84, 0x01, 0x9d, 0xb1, 0xdd, 0x3c, 0x4e, 0xa3, 0x00, 0x04, 0x4e, 0x92, 0x00, 0x05, 0x44, 0x50, +0x01, 0x2c, 0xde, 0xe4, 0x49, 0xff, 0xff, 0x60, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x49, 0xff, 0xff, 0x3e, 0x49, 0x00, 0x1e, 0xba, 0x84, 0x02, 0x49, 0xfb, +0xde, 0x75, 0x84, 0x20, 0x2e, 0x01, 0xdc, 0x3c, 0x80, 0x41, 0x49, 0x00, 0x1e, 0xc3, 0x2e, 0x01, +0xdc, 0x40, 0x46, 0x70, 0x04, 0x10, 0x54, 0x00, 0x00, 0x0f, 0x49, 0x00, 0x09, 0x55, 0x46, 0x10, +0x04, 0x10, 0x46, 0x00, 0x60, 0x00, 0x84, 0xc0, 0x14, 0x60, 0x81, 0x43, 0x14, 0x03, 0x81, 0x41, +0x44, 0x00, 0x00, 0x10, 0x49, 0xfb, 0xde, 0x5a, 0x46, 0x00, 0x04, 0x11, 0x84, 0x2c, 0x14, 0x63, +0x81, 0x41, 0xa8, 0x41, 0x3c, 0x1c, 0x62, 0xae, 0x14, 0x10, 0x00, 0xd1, 0x3e, 0x61, 0x8a, 0x69, +0x3e, 0x61, 0x8a, 0x57, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x2e, 0x31, 0xde, 0x18, 0x84, 0xa1, 0xdb, 0x0a, 0x3e, 0x31, 0x8a, 0x56, 0x84, 0x02, +0x44, 0x10, 0x00, 0x6d, 0x84, 0x40, 0x49, 0xfb, 0xff, 0x87, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x61, 0x96, 0x48, 0x3e, 0x31, 0x8a, 0x57, +0x3e, 0x29, 0x8a, 0x6a, 0xc9, 0x06, 0xae, 0x50, 0x84, 0x45, 0x3e, 0x21, 0x8a, 0x58, 0xd5, 0x0a, +0xa6, 0xd0, 0xe6, 0x7f, 0xe8, 0x17, 0x9c, 0xd9, 0x96, 0xd8, 0x9d, 0x1d, 0x3e, 0x41, 0x8a, 0x58, +0xae, 0xd0, 0x2e, 0x61, 0x8a, 0x69, 0xce, 0x0e, 0x2e, 0x11, 0x8a, 0x6a, 0x84, 0x61, 0x3e, 0x31, +0x8a, 0x69, 0x9a, 0x41, 0x3e, 0x09, 0xd9, 0x7c, 0x49, 0xff, 0xcc, 0x6e, 0x80, 0x06, 0x49, 0xff, +0xfe, 0xfb, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, +0x01, 0x19, 0x2e, 0x21, 0x8a, 0x53, 0x84, 0xa1, 0xda, 0x05, 0x84, 0x20, 0x3e, 0x11, 0x8a, 0x53, +0xd5, 0x20, 0x4e, 0x15, 0x00, 0x1f, 0x5e, 0xf0, 0xae, 0xe0, 0xe9, 0x1b, 0x2e, 0x01, 0xde, 0x2b, +0xc8, 0x11, 0x3c, 0x3c, 0x62, 0x7b, 0x44, 0x20, 0x03, 0xe8, 0x46, 0x00, 0x00, 0xf4, 0x42, 0x21, +0x88, 0x24, 0x58, 0x00, 0x02, 0x40, 0x42, 0x10, 0x80, 0x01, 0x40, 0x00, 0x88, 0x06, 0x40, 0x11, +0x00, 0x1a, 0x44, 0x00, 0x03, 0xe8, 0x40, 0x00, 0x80, 0x36, 0x84, 0x20, 0x49, 0xff, 0xff, 0xac, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x80, 0x20, 0xd5, 0x02, 0x9c, 0x49, 0x20, 0x20, +0x80, 0x00, 0xca, 0xfd, 0x9a, 0x08, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x01, 0xd4, +0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x01, 0xd4, 0x3c, 0x0c, 0x62, 0x7d, 0x84, 0x21, 0xae, 0x41, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x50, 0xa0, 0x8d, 0x54, 0x21, 0x00, 0x20, 0xc2, 0xfd, +0xb6, 0x01, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x30, 0xb6, 0x1f, +0x84, 0x00, 0x10, 0x0f, 0x80, 0x04, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x44, 0x2f, 0x00, 0x00, +0x46, 0x37, 0x66, 0x20, 0x40, 0x50, 0x88, 0x02, 0xd3, 0x07, 0xb4, 0x00, 0x46, 0x17, 0x63, 0x20, +0x40, 0x50, 0x08, 0x02, 0xd9, 0x09, 0x84, 0x00, 0x50, 0x1f, 0x80, 0x04, 0x49, 0xfb, 0xec, 0x66, +0x84, 0x20, 0x3e, 0x10, 0x05, 0x48, 0x84, 0x24, 0x80, 0x1f, 0x49, 0xff, 0xfd, 0x59, 0x84, 0x0a, +0x49, 0xfb, 0xc9, 0x98, 0x84, 0x07, 0x49, 0xfb, 0xc9, 0x95, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, +0x81, 0x06, 0x42, 0x21, 0x1c, 0x09, 0x14, 0x20, 0x81, 0x06, 0x80, 0x01, 0x04, 0x10, 0x00, 0x85, +0x42, 0x10, 0xb0, 0x09, 0x14, 0x10, 0x00, 0x85, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x02, 0x0c, +0xb4, 0xe6, 0x84, 0x0a, 0x58, 0x13, 0x80, 0x10, 0xb6, 0x26, 0x49, 0xfb, 0xdd, 0x77, 0x42, 0x73, +0x90, 0x09, 0x84, 0x20, 0xb6, 0xe6, 0x3e, 0x17, 0xef, 0xde, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, +0x00, 0x8c, 0x84, 0x7e, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x00, 0x8c, 0x46, 0x10, 0x04, 0x05, +0x58, 0x10, 0x87, 0x00, 0xb4, 0x41, 0x44, 0x00, 0x13, 0x88, 0x58, 0x21, 0x00, 0x01, 0xb6, 0x41, +0xb4, 0x41, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x49, 0xfe, 0x90, 0x0a, 0xb4, 0x06, 0x58, 0x00, +0x02, 0x00, 0xb6, 0x06, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xf4, 0x3e, 0x68, 0x08, 0x64, 0x80, 0xe0, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, 0xd6, 0x88, +0xb4, 0x46, 0xa0, 0x31, 0xa0, 0x72, 0x9a, 0x90, 0x40, 0x01, 0x04, 0x06, 0x44, 0x30, 0x03, 0x75, +0x84, 0x20, 0x3e, 0x29, 0x5a, 0x94, 0x49, 0xfb, 0xe9, 0x21, 0xb4, 0x46, 0xa0, 0x72, 0xf0, 0x01, +0x9e, 0x49, 0x40, 0x10, 0x88, 0x02, 0x9c, 0x4a, 0x94, 0x4a, 0x98, 0x71, 0xa9, 0xc9, 0xb4, 0x26, +0x9c, 0x49, 0xb6, 0x26, 0x49, 0xfb, 0xd6, 0x82, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x86, 0x84, 0xa1, +0x96, 0x00, 0xd8, 0x30, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x34, 0xb4, 0x20, 0x84, 0xa3, +0x54, 0x10, 0x80, 0x03, 0xd9, 0x20, 0xb4, 0x40, 0x92, 0x42, 0x94, 0x92, 0xb6, 0x40, 0x50, 0x10, +0x7e, 0x30, 0xb4, 0x41, 0x46, 0x30, 0x06, 0x00, 0x40, 0x21, 0x0c, 0x04, 0xb6, 0x41, 0xb4, 0x41, +0x42, 0x21, 0x54, 0x09, 0x42, 0x21, 0x58, 0x09, 0xb6, 0x41, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, +0x04, 0x00, 0xb4, 0x20, 0x84, 0x53, 0x58, 0x10, 0x80, 0x0c, 0xb6, 0x20, 0xb4, 0x20, 0x40, 0x10, +0x88, 0x02, 0xb6, 0x20, 0x84, 0x02, 0x44, 0x10, 0x00, 0x71, 0x84, 0x40, 0x49, 0xfb, 0xfe, 0x3c, +0x92, 0x00, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x86, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, +0x14, 0x10, 0x00, 0x86, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x3c, 0x2c, 0x62, 0x7d, 0x84, 0x20, 0xae, 0x51, 0x84, 0x21, 0x3c, 0x0c, 0x62, 0x7d, +0xae, 0x44, 0x2e, 0x11, 0x16, 0xdd, 0x84, 0x00, 0x49, 0xfb, 0xe0, 0xb6, 0x46, 0x10, 0x04, 0x05, +0x04, 0x20, 0x81, 0xd4, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x81, 0xd4, 0x84, 0x03, 0x84, 0x20, +0x84, 0x41, 0x49, 0x03, 0xd0, 0x19, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x60, 0x00, 0x97, 0x84, 0xa1, 0xde, 0x09, +0x3c, 0x1d, 0xfb, 0x79, 0xc1, 0x0c, 0x04, 0x00, 0x00, 0x97, 0x96, 0x04, 0xdd, 0x21, 0xd5, 0x07, +0x54, 0x03, 0x20, 0x00, 0xc0, 0x04, 0x84, 0x00, 0x49, 0xff, 0xfe, 0x62, 0x3c, 0x0c, 0x62, 0x7d, +0xc0, 0x0e, 0xa6, 0x40, 0xc1, 0x0c, 0xa6, 0x42, 0xc1, 0x0a, 0xa6, 0x43, 0x40, 0x13, 0x04, 0x0d, +0x96, 0x4c, 0xc1, 0x05, 0xa6, 0x01, 0xc0, 0x03, 0x49, 0xff, 0xff, 0xba, 0x46, 0x00, 0x04, 0x00, +0x14, 0x60, 0x00, 0x97, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xf4, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xfb, 0xd5, 0xcb, 0x3c, 0x1c, 0x76, 0xa7, 0x54, 0x70, +0x80, 0x02, 0xc7, 0x04, 0x42, 0x10, 0x84, 0x09, 0x84, 0xe1, 0xf0, 0x01, 0x3e, 0x69, 0xd9, 0xe8, +0x14, 0x13, 0x00, 0x2d, 0x49, 0xfb, 0xd5, 0xd2, 0xc7, 0x04, 0x80, 0x06, 0x49, 0xff, 0xc7, 0x50, +0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x50, 0x0f, +0x80, 0x04, 0x49, 0xfb, 0xd5, 0xad, 0x3c, 0x1c, 0x76, 0xa7, 0x97, 0xcc, 0xc7, 0x04, 0x42, 0x10, +0x80, 0x09, 0x84, 0xe1, 0xf0, 0x01, 0x3e, 0x69, 0xd9, 0xe8, 0x14, 0x13, 0x00, 0x2d, 0x49, 0xfb, +0xd5, 0xb5, 0xc7, 0x05, 0x80, 0x06, 0x49, 0xff, 0xc7, 0x75, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x3e, 0x69, 0xd9, 0xe8, 0x50, 0x0f, +0x80, 0x04, 0x49, 0xfb, 0xd5, 0x8d, 0x04, 0x13, 0x00, 0x2d, 0xf0, 0x01, 0xb6, 0x3f, 0x84, 0x20, +0x14, 0x13, 0x00, 0x2d, 0x49, 0xfb, 0xd5, 0x9a, 0xb4, 0x1f, 0x96, 0x04, 0xc0, 0x04, 0x80, 0x06, +0x49, 0xff, 0xc7, 0x58, 0xb4, 0x1f, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x05, 0x3e, 0x09, 0xd9, 0xe8, +0x49, 0xff, 0xc7, 0x0e, 0xb4, 0x1f, 0x40, 0x00, 0x3c, 0x08, 0x92, 0x1f, 0xc0, 0x05, 0x3e, 0x09, +0xd9, 0xe8, 0x49, 0xff, 0xc7, 0xe9, 0xb4, 0x1f, 0x40, 0x00, 0x38, 0x08, 0x92, 0x1f, 0xc0, 0x05, +0x3e, 0x09, 0xd9, 0xe8, 0x49, 0xff, 0xc7, 0x7a, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x84, 0x23, 0x42, 0x00, 0x04, 0x24, 0x84, 0x20, 0xd5, 0x08, 0x84, 0x40, 0x92, 0x00, 0x84, 0x67, +0x9c, 0x91, 0x4c, 0x21, 0xff, 0xfd, 0x9c, 0x49, 0xe2, 0x20, 0xe9, 0xf8, 0xdd, 0x9e, 0x92, 0x00, +0x96, 0x04, 0x54, 0x10, 0x8f, 0xff, 0x58, 0x10, 0x90, 0x00, 0x40, 0x00, 0x40, 0x08, 0x46, 0x40, +0x04, 0x10, 0x80, 0x64, 0x40, 0x00, 0x80, 0x04, 0x14, 0x22, 0x01, 0x49, 0x14, 0x01, 0x81, 0x4a, +0x84, 0x20, 0x04, 0x01, 0x81, 0x4a, 0x9c, 0x49, 0x42, 0x00, 0x34, 0x0b, 0xc0, 0x06, 0x44, 0x00, +0x00, 0x64, 0x4c, 0x10, 0x7f, 0xf8, 0x84, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0x3c, 0x6c, 0x62, 0xb6, 0x3e, 0x09, 0xcf, 0xfc, 0x50, 0x83, 0x7f, 0xff, 0x40, 0x74, 0x08, 0x08, +0x40, 0x93, 0x80, 0x00, 0x3e, 0x09, 0xcf, 0x5c, 0x89, 0x00, 0x3e, 0x09, 0xcf, 0x7c, 0x99, 0xf8, +0x08, 0x04, 0x7f, 0xff, 0x0c, 0x13, 0xff, 0xff, 0x0c, 0x24, 0xff, 0xff, 0x9f, 0xb1, 0x49, 0xff, +0xff, 0xc9, 0x4e, 0x66, 0xff, 0xf7, 0x3c, 0x6e, 0x62, 0xb6, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x97, 0xc0, 0xc7, 0x10, 0x84, 0x00, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, +0x04, 0x06, 0x80, 0x20, 0x49, 0xff, 0xff, 0xb6, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x04, 0x06, +0x84, 0x20, 0x84, 0x01, 0xd5, 0x0f, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x04, 0x02, 0x80, 0x27, +0x80, 0x07, 0x49, 0xff, 0xff, 0xa7, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x04, 0x02, 0x84, 0x01, +0x80, 0x27, 0x49, 0xff, 0xff, 0x9f, 0x84, 0x00, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x06, 0xa0, +0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, 0x44, 0x20, 0x08, 0x00, +0x84, 0x00, 0xdd, 0x26, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x06, 0x80, 0x44, 0x00, 0x00, 0x23, +0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, +0x44, 0x20, 0x40, 0x00, 0x84, 0x00, 0xdd, 0x26, 0x84, 0x0a, 0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, +0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, 0x44, 0x20, 0x08, 0x00, 0x84, 0x00, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x23, 0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, +0xdd, 0x26, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x44, 0x20, 0x10, 0x00, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x50, 0xdd, 0x28, 0xc7, 0x62, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, +0x44, 0x10, 0x03, 0x08, 0x44, 0x21, 0x00, 0x00, 0x84, 0x00, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x28, +0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, +0x44, 0x22, 0x00, 0x00, 0x84, 0x00, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x14, 0xdd, 0x28, 0x84, 0x00, +0x44, 0x10, 0x03, 0x08, 0x80, 0x40, 0xdd, 0x26, 0x44, 0x10, 0x03, 0x08, 0x44, 0x24, 0x00, 0x00, +0x84, 0x00, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x28, 0xdd, 0x28, 0x84, 0x00, 0x44, 0x10, 0x03, 0x08, +0x80, 0x40, 0xdd, 0x26, 0x46, 0x20, 0x00, 0x80, 0x44, 0x10, 0x03, 0x08, 0x84, 0x00, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x14, 0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, 0x84, 0x40, 0x84, 0x01, 0xdd, 0x26, +0x44, 0x10, 0x03, 0x08, 0x44, 0x24, 0x00, 0x00, 0x84, 0x01, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x28, +0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, 0x84, 0x40, 0x84, 0x01, 0xdd, 0x26, 0x46, 0x20, 0x00, 0x80, +0x44, 0x10, 0x03, 0x08, 0x84, 0x01, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x14, 0xdd, 0x28, 0x84, 0x00, +0x46, 0x28, 0x00, 0x56, 0x58, 0x21, 0x00, 0x04, 0x80, 0x20, 0xdd, 0x26, 0x46, 0x28, 0x00, 0x56, +0x58, 0x21, 0x00, 0x04, 0x84, 0x20, 0xd5, 0x41, 0x44, 0x10, 0x03, 0x08, 0x80, 0x47, 0x80, 0x07, +0xdd, 0x26, 0x46, 0x20, 0x01, 0x00, 0x44, 0x10, 0x03, 0x08, 0x80, 0x07, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x32, 0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, 0x80, 0x47, 0x84, 0x01, 0xdd, 0x26, 0x46, 0x20, +0x01, 0x00, 0x44, 0x10, 0x03, 0x08, 0x84, 0x01, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x32, 0xdd, 0x28, +0x44, 0x10, 0x03, 0x08, 0x80, 0x47, 0x80, 0x07, 0xdd, 0x26, 0x46, 0x20, 0x02, 0x00, 0x44, 0x10, +0x03, 0x08, 0x80, 0x07, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x32, 0xdd, 0x28, 0x44, 0x10, 0x03, 0x08, +0x80, 0x47, 0x84, 0x01, 0xdd, 0x26, 0x46, 0x20, 0x02, 0x00, 0x44, 0x10, 0x03, 0x08, 0x84, 0x01, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x32, 0xdd, 0x28, 0x46, 0x28, 0x00, 0x56, 0x80, 0x27, 0x80, 0x07, +0xdd, 0x26, 0x46, 0x28, 0x00, 0x56, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x26, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x84, 0x21, 0x80, 0x40, 0x44, 0x00, 0x02, 0x58, 0x40, 0x31, 0x00, 0x97, +0x9c, 0x49, 0x96, 0x48, 0x98, 0x18, 0x84, 0x6b, 0x92, 0x01, 0x4c, 0x11, 0xff, 0xf9, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x11, 0x84, 0x48, 0x96, 0x00, 0x04, 0x80, +0x80, 0x01, 0xa8, 0x89, 0xe6, 0x0f, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x12, 0x02, 0x02, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x80, 0x20, 0xd5, 0x71, 0x2e, 0x11, 0x8a, 0x6d, 0xc9, 0x2a, +0x5c, 0xf0, 0x00, 0x34, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x16, 0x45, 0x03, 0x58, 0x00, +0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, 0xd5, 0x62, 0x5c, 0xf0, 0x00, 0x45, 0xe8, 0x02, 0xd5, 0x4d, +0x5c, 0xf0, 0x00, 0x75, 0xe8, 0x02, 0xd5, 0x49, 0x5c, 0xf0, 0x00, 0xae, 0xe8, 0x0a, 0x46, 0x00, +0x04, 0x12, 0x46, 0x13, 0xf3, 0xf3, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, 0xd5, 0x4e, +0x46, 0x00, 0x04, 0x12, 0x46, 0x16, 0x46, 0x43, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, +0xd5, 0x45, 0x5c, 0xf0, 0x00, 0x34, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0xf3, 0xf3, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x83, 0x33, 0xd5, 0x39, 0x5c, 0xf0, 0x00, 0x45, 0xe8, 0x0a, +0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0xf3, 0xf2, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x88, 0x33, +0xd5, 0x2d, 0x5c, 0xf0, 0x00, 0x75, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0x33, 0x32, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x88, 0x33, 0xd5, 0x21, 0x5c, 0xf0, 0x00, 0xae, 0xe8, 0x0a, +0x46, 0x00, 0x04, 0x12, 0x46, 0x13, 0x33, 0x32, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x80, 0x28, +0xd5, 0x15, 0x5c, 0xf0, 0x00, 0xc5, 0xe8, 0x0a, 0x46, 0x00, 0x04, 0x12, 0x46, 0x15, 0x05, 0x03, +0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x8f, 0x3f, 0xd5, 0x09, 0x46, 0x00, 0x04, 0x12, 0x46, 0x15, +0x05, 0x03, 0x58, 0x00, 0x0c, 0xe0, 0x58, 0x10, 0x83, 0x33, 0xb6, 0x20, 0x46, 0x60, 0x04, 0x12, +0x80, 0x26, 0x84, 0x01, 0x44, 0x20, 0xff, 0xff, 0x04, 0x90, 0x80, 0xc2, 0x14, 0x20, 0x80, 0xc2, +0xa8, 0x34, 0x49, 0xff, 0xfe, 0x07, 0x84, 0x40, 0x46, 0x10, 0x04, 0x12, 0xa8, 0xb4, 0x80, 0x01, +0x44, 0x20, 0x33, 0xf0, 0x14, 0x20, 0x83, 0x2f, 0x44, 0x10, 0x00, 0x4c, 0x14, 0x10, 0x03, 0x2e, +0x3c, 0x0c, 0x62, 0x7e, 0xc8, 0x04, 0x44, 0x00, 0x07, 0xd0, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x14, +0x49, 0xff, 0xfd, 0xf0, 0x46, 0x00, 0x04, 0x12, 0x44, 0x10, 0x33, 0xe0, 0x14, 0x10, 0x03, 0x2f, +0x3c, 0x0c, 0x62, 0x7e, 0xc8, 0x04, 0x44, 0x00, 0x07, 0xd0, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x14, +0x49, 0xff, 0xfd, 0xe0, 0x46, 0x10, 0x04, 0x12, 0x46, 0x00, 0x04, 0x11, 0x14, 0x90, 0x80, 0xc2, +0x14, 0x80, 0x00, 0x01, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x96, 0x01, 0x94, 0x04, +0x44, 0x10, 0x7f, 0xff, 0xe2, 0x20, 0xe8, 0x05, 0x84, 0x3c, 0x44, 0x20, 0xff, 0xff, 0xd5, 0x11, +0x80, 0x41, 0x84, 0x3c, 0x9e, 0x49, 0x96, 0x4b, 0x44, 0x5f, 0xff, 0xeb, 0x98, 0x00, 0xd1, 0x30, +0xe2, 0x40, 0xe8, 0xf9, 0xd5, 0x09, 0x96, 0x5b, 0x44, 0x50, 0x00, 0x15, 0xd1, 0x29, 0x92, 0x01, +0x9c, 0xc9, 0xe2, 0x40, 0xe9, 0xf9, 0x44, 0x30, 0xb8, 0x00, 0x40, 0x20, 0x0c, 0x09, 0xe2, 0x60, +0xe9, 0x07, 0x44, 0x4f, 0x6a, 0x00, 0x98, 0xc4, 0x98, 0x9a, 0x92, 0x04, 0xd5, 0x06, 0x9a, 0x82, +0x92, 0x06, 0x9a, 0x10, 0x44, 0x2f, 0xa6, 0x00, 0x98, 0x02, 0x84, 0x60, 0x8c, 0x2f, 0x42, 0x00, +0x0c, 0x00, 0x40, 0x10, 0xbc, 0x08, 0x98, 0x41, 0x98, 0x89, 0x94, 0x0a, 0x98, 0x10, 0x40, 0x20, +0x98, 0x0a, 0x98, 0x02, 0x90, 0x27, 0x98, 0x01, 0x90, 0x0a, 0x96, 0x03, 0xd5, 0x03, 0x44, 0x0f, +0xd8, 0xf0, 0xdd, 0x9e, 0x3e, 0x09, 0x7d, 0xd0, 0xb4, 0x20, 0xa0, 0x81, 0x8c, 0x08, 0xb6, 0x41, +0x3e, 0x59, 0x7e, 0x90, 0xd8, 0xfa, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0x3c, 0x3e, 0x09, 0x7b, 0x80, +0xa0, 0x47, 0xb4, 0xc0, 0xa1, 0xc1, 0xa1, 0x02, 0xa1, 0x43, 0xa0, 0x84, 0xa0, 0xc5, 0xa0, 0x06, +0xb6, 0xe6, 0xb6, 0xa4, 0xb6, 0x62, 0xb6, 0x20, 0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, 0x92, 0x00, +0x96, 0x00, 0x96, 0x48, 0x96, 0x90, 0xe6, 0x0f, 0xe8, 0x1c, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x0e, +0x40, 0x21, 0x04, 0x03, 0x3e, 0x39, 0x87, 0xc8, 0x3e, 0x49, 0x87, 0x80, 0x40, 0x02, 0x08, 0x1a, +0x40, 0x01, 0x88, 0x1b, 0x84, 0x29, 0xd5, 0x39, 0x3e, 0x19, 0x88, 0x48, 0x56, 0x21, 0x00, 0x01, +0x3e, 0x39, 0x88, 0x10, 0x40, 0x01, 0x88, 0x1a, 0x40, 0x00, 0x88, 0x1b, 0x84, 0x27, 0xd5, 0x2d, +0x84, 0x01, 0x4c, 0x10, 0x40, 0x15, 0x84, 0xa2, 0xda, 0x05, 0x3e, 0x09, 0x88, 0x80, 0x84, 0x23, +0xd5, 0x24, 0x84, 0x66, 0x56, 0x21, 0x00, 0x01, 0x84, 0x07, 0x40, 0x11, 0x88, 0x1a, 0x40, 0x10, +0x08, 0x1b, 0x3e, 0x49, 0x88, 0x98, 0x3e, 0x39, 0x88, 0xc8, 0xd5, 0x13, 0x84, 0xa2, 0xda, 0x05, +0x3e, 0x09, 0x89, 0x00, 0x84, 0x21, 0xd5, 0x11, 0x84, 0x64, 0x56, 0x21, 0x00, 0x01, 0x84, 0x05, +0x40, 0x11, 0x88, 0x1a, 0x40, 0x10, 0x08, 0x1b, 0x3e, 0x49, 0x89, 0x08, 0x3e, 0x39, 0x89, 0x28, +0x40, 0x02, 0x08, 0x1a, 0x40, 0x01, 0x88, 0x1b, 0x84, 0x40, 0xb4, 0x60, 0xa1, 0x01, 0x9c, 0x91, +0xb6, 0x83, 0x8c, 0x08, 0xe0, 0x41, 0xe9, 0xfa, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, +0x46, 0x00, 0x04, 0x11, 0x46, 0x18, 0x02, 0x50, 0x46, 0x60, 0x04, 0x12, 0x46, 0x50, 0x07, 0x77, +0x80, 0x86, 0x84, 0x48, 0xa1, 0xc1, 0xa8, 0x81, 0x58, 0x52, 0x87, 0x77, 0x84, 0x00, 0x48, 0x00, +0x00, 0xaf, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x92, 0xe6, 0x06, 0x4e, 0xf3, 0x00, 0x92, 0xe6, 0x0b, +0x4e, 0xf3, 0x00, 0x92, 0xe6, 0x11, 0x4e, 0xf3, 0x00, 0x92, 0xe6, 0x17, 0x4e, 0xf3, 0x00, 0x92, +0xe6, 0x1e, 0x4e, 0xf3, 0x00, 0x92, 0x5c, 0xf0, 0x00, 0x28, 0x4e, 0xf3, 0x00, 0x91, 0x5c, 0xf0, +0x00, 0x3a, 0x4e, 0xf3, 0x00, 0x90, 0x5c, 0xf0, 0x00, 0x46, 0x4e, 0xf3, 0x00, 0x8f, 0x5c, 0xf0, +0x00, 0x58, 0x4e, 0xf3, 0x00, 0x88, 0x5c, 0xf0, 0x00, 0x62, 0x4e, 0xf3, 0x00, 0x81, 0x5c, 0xf0, +0x00, 0x69, 0xe9, 0x7a, 0x5c, 0xf0, 0x00, 0x6f, 0xe9, 0x74, 0x5c, 0xf0, 0x00, 0x75, 0xe9, 0x6e, +0x5c, 0xf0, 0x00, 0x7a, 0xe9, 0x68, 0x5c, 0xf0, 0x00, 0x7e, 0xe9, 0x62, 0x5c, 0xf0, 0x00, 0x81, +0xe9, 0x5c, 0x5c, 0xf0, 0x00, 0x83, 0xe9, 0x5c, 0x5c, 0xf0, 0x00, 0x88, 0xe9, 0x5f, 0x5c, 0xf0, +0x00, 0x8a, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0x8e, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0x92, 0xe9, 0x5f, +0x5c, 0xf0, 0x00, 0x9a, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0xa0, 0xe9, 0x5f, 0x5c, 0xf0, 0x00, 0xa8, +0xe9, 0x59, 0x5c, 0xf0, 0x00, 0xac, 0xe9, 0x53, 0x5c, 0xf0, 0x00, 0xb0, 0xe9, 0x4d, 0x5c, 0xf0, +0x00, 0xb2, 0xe9, 0x47, 0x5c, 0xf0, 0x00, 0xb5, 0xe9, 0x41, 0x5c, 0xf0, 0x00, 0xb7, 0xe9, 0x3b, +0x5c, 0xf0, 0x00, 0xb9, 0xe9, 0x35, 0x5c, 0xf0, 0x00, 0xbb, 0xe9, 0x2f, 0x44, 0x10, 0x00, 0xbb, +0x4c, 0x00, 0x80, 0x2f, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x2f, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x2f, +0x9c, 0x49, 0x4c, 0x00, 0x80, 0x2f, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x2f, 0x5c, 0xf0, 0x00, 0xc2, +0xe9, 0x2e, 0x5c, 0xf0, 0x00, 0xc6, 0xe9, 0x2e, 0x5c, 0xf0, 0x00, 0xca, 0xe9, 0x2e, 0x5c, 0xf0, +0x00, 0xce, 0xe9, 0x28, 0x5c, 0xf0, 0x00, 0xd0, 0xe9, 0x22, 0x8c, 0x31, 0x4c, 0x00, 0x80, 0x1d, +0x9c, 0x49, 0x4c, 0x00, 0x80, 0x17, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x11, 0x9c, 0x49, 0x4c, 0x00, +0x80, 0x0b, 0x9c, 0x49, 0x4c, 0x00, 0x80, 0x05, 0x46, 0x18, 0x02, 0x50, 0xd5, 0x18, 0x46, 0x18, +0x02, 0x40, 0xd5, 0x15, 0x46, 0x18, 0x02, 0x30, 0xd5, 0x12, 0x46, 0x18, 0x02, 0x20, 0xd5, 0x0f, +0x46, 0x18, 0x02, 0x10, 0xd5, 0x0c, 0x46, 0x18, 0x02, 0x00, 0xd5, 0x09, 0x46, 0x18, 0x01, 0xf0, +0xd5, 0x06, 0x46, 0x18, 0x01, 0xe0, 0xd5, 0x03, 0x46, 0x18, 0x01, 0xd0, 0x40, 0x10, 0x04, 0x04, +0x80, 0x44, 0x14, 0x53, 0x01, 0x8c, 0x9c, 0x01, 0x14, 0x12, 0x01, 0x8d, 0x44, 0x10, 0x00, 0xd6, +0x80, 0x65, 0x4c, 0x00, 0xff, 0x48, 0x46, 0x00, 0x04, 0x11, 0x9e, 0x5c, 0x14, 0x31, 0x01, 0x8c, +0x14, 0x11, 0x01, 0x8c, 0xa9, 0xc1, 0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, 0x96, 0x00, 0xe6, 0x0f, +0xe8, 0x30, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, 0xb4, 0x40, 0x46, 0x10, 0x04, 0x00, +0x58, 0x21, 0x00, 0x10, 0xb6, 0x40, 0x04, 0x30, 0x80, 0x49, 0x94, 0xdc, 0x92, 0x64, 0x42, 0x31, +0xf0, 0x08, 0x14, 0x30, 0x80, 0x49, 0x80, 0x41, 0x04, 0x31, 0x00, 0x4a, 0x46, 0x4f, 0xff, 0x00, +0x58, 0x42, 0x0f, 0xf0, 0x40, 0x31, 0x90, 0x02, 0x44, 0x41, 0x10, 0x01, 0x40, 0x31, 0x90, 0x04, +0x14, 0x31, 0x00, 0x4a, 0x04, 0x20, 0x80, 0x6e, 0x46, 0x3f, 0xfe, 0x67, 0x58, 0x31, 0x8f, 0xff, +0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x80, 0x6e, 0xb4, 0x20, 0x40, 0x10, 0x8c, 0x02, 0xd5, 0x23, +0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x6f, 0x42, 0x21, 0x10, 0x09, 0x14, 0x20, 0x00, 0x6f, +0x80, 0x20, 0x04, 0x20, 0x80, 0x49, 0x46, 0x47, 0x00, 0x00, 0x94, 0x94, 0x92, 0x44, 0x40, 0x21, +0x10, 0x04, 0x14, 0x20, 0x80, 0x49, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x28, 0xb4, 0x20, +0x46, 0x2f, 0xff, 0x00, 0x58, 0x21, 0x0f, 0xf0, 0x40, 0x10, 0x88, 0x02, 0x44, 0x37, 0x70, 0x07, +0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x12, 0x04, 0x00, 0x00, 0xc8, +0x84, 0x22, 0x92, 0x06, 0x54, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x80, 0x11, 0x84, 0xa3, 0xd0, 0x14, +0x84, 0xa1, 0xd0, 0x06, 0x46, 0x00, 0x04, 0x12, 0x58, 0x00, 0x03, 0x18, 0xd5, 0x05, 0x46, 0x00, +0x04, 0x12, 0x58, 0x00, 0x03, 0x10, 0xb4, 0x00, 0xd5, 0x0c, 0x46, 0x00, 0x04, 0x12, 0x04, 0x00, +0x00, 0xc4, 0x92, 0x08, 0xd5, 0x06, 0x46, 0x00, 0x04, 0x12, 0x04, 0x00, 0x00, 0xc4, 0x92, 0x10, +0x46, 0x10, 0x04, 0x12, 0x04, 0x10, 0x80, 0xc8, 0x54, 0x00, 0x00, 0x3f, 0x92, 0x29, 0x54, 0x10, +0x80, 0x3f, 0x98, 0x01, 0x5c, 0xf0, 0x00, 0x41, 0xe9, 0x14, 0x50, 0x00, 0x7f, 0xc0, 0x84, 0x23, +0x40, 0x00, 0x04, 0x37, 0xe6, 0x02, 0xe9, 0x0d, 0x84, 0x21, 0x9e, 0x02, 0x40, 0x00, 0x80, 0x0c, +0x5c, 0x30, 0x00, 0x0f, 0x84, 0x4e, 0x40, 0x10, 0x0c, 0x1b, 0x40, 0x11, 0x0c, 0x1a, 0xd5, 0x02, +0x84, 0x21, 0x46, 0x00, 0x04, 0x12, 0x04, 0x30, 0x00, 0xc2, 0x92, 0x70, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x20, 0xa0, 0x08, 0x40, 0x10, 0x8c, 0x04, 0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0xc2, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x70, 0x04, 0x11, 0x84, 0xc0, 0x04, 0x13, +0x80, 0x80, 0x9d, 0xb1, 0x96, 0x4c, 0x84, 0x01, 0xc1, 0x06, 0x49, 0xff, 0xfb, 0x8b, 0x44, 0x50, +0x75, 0x30, 0xde, 0xf6, 0x46, 0x70, 0x04, 0x12, 0x84, 0xc0, 0x04, 0x13, 0x80, 0x4c, 0x9d, 0xb1, +0x84, 0x01, 0xc1, 0x06, 0x49, 0xff, 0xfb, 0x7e, 0x44, 0x50, 0x75, 0x30, 0xde, 0xf7, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0x54, 0x80, 0x80, 0xff, +0x96, 0x90, 0xc8, 0x1c, 0x2e, 0x31, 0xde, 0x30, 0x84, 0xa1, 0xdb, 0x06, 0x2e, 0x51, 0xde, 0x31, +0xda, 0x03, 0x81, 0x00, 0xd5, 0x13, 0x2e, 0x81, 0xdf, 0x10, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x05, +0x2e, 0x51, 0xdf, 0x11, 0xd2, 0x0b, 0x2e, 0x11, 0xdf, 0xf0, 0x84, 0xa1, 0x4c, 0x12, 0xc0, 0xca, +0x4e, 0x23, 0x00, 0xc8, 0x3e, 0x21, 0xdf, 0xf0, 0x85, 0x02, 0x46, 0x00, 0x04, 0x12, 0x44, 0x90, +0x00, 0xe0, 0x42, 0x94, 0x24, 0x24, 0x44, 0x11, 0x00, 0x00, 0x3e, 0x49, 0xde, 0x30, 0x04, 0xa0, +0x01, 0xc0, 0x14, 0x10, 0x01, 0xc0, 0x40, 0x64, 0x90, 0x00, 0x50, 0x63, 0x00, 0x34, 0xb4, 0x46, +0x46, 0x70, 0x00, 0x87, 0x58, 0x73, 0x86, 0xa0, 0x44, 0x10, 0x02, 0x4c, 0x84, 0x00, 0xdd, 0x27, +0xa0, 0xb1, 0x44, 0x10, 0x02, 0x50, 0x84, 0x00, 0xdd, 0x27, 0xa0, 0xb2, 0x44, 0x10, 0x02, 0x64, +0x84, 0x00, 0xdd, 0x27, 0xa0, 0xb3, 0x44, 0x10, 0x02, 0x78, 0x84, 0x00, 0xdd, 0x27, 0xa0, 0xb4, +0x44, 0x10, 0x02, 0x4c, 0x84, 0x01, 0xdd, 0x27, 0xa0, 0xb5, 0x44, 0x10, 0x02, 0x50, 0x84, 0x01, +0xdd, 0x27, 0xa0, 0xb6, 0x44, 0x10, 0x02, 0x64, 0x84, 0x01, 0xdd, 0x27, 0xa0, 0xb7, 0x44, 0x10, +0x02, 0x78, 0x84, 0x01, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x01, 0xdd, 0x46, 0x3f, +0xf0, 0x0f, 0x04, 0x23, 0x00, 0x08, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0x8c, 0x02, 0x40, 0x10, +0x88, 0x04, 0x14, 0x10, 0x01, 0xdd, 0x04, 0x13, 0x00, 0x15, 0x14, 0x10, 0x01, 0xe6, 0x04, 0x13, +0x00, 0x16, 0x14, 0x10, 0x01, 0xe7, 0x04, 0x13, 0x00, 0x17, 0x14, 0x10, 0x01, 0xe8, 0x04, 0x13, +0x00, 0x18, 0x14, 0x10, 0x01, 0xe9, 0x04, 0x13, 0x00, 0x19, 0x14, 0x10, 0x01, 0xf0, 0x04, 0x13, +0x00, 0x1a, 0x14, 0x10, 0x01, 0xf1, 0x04, 0x13, 0x00, 0x1b, 0x14, 0x10, 0x01, 0xf2, 0x04, 0x13, +0x00, 0x1c, 0x14, 0x10, 0x01, 0xf3, 0x50, 0x74, 0x80, 0xa8, 0x3e, 0x09, 0xde, 0x30, 0x46, 0x60, +0x04, 0x12, 0x80, 0xa6, 0x80, 0x85, 0x80, 0x64, 0x80, 0x43, 0x99, 0xf8, 0x84, 0x00, 0x14, 0x03, +0x03, 0x14, 0x9c, 0x01, 0xa2, 0x79, 0x41, 0xc0, 0xa0, 0x09, 0x41, 0xe0, 0xc0, 0x09, 0x81, 0x3c, +0x54, 0x10, 0x80, 0x7f, 0x55, 0xef, 0x7f, 0x00, 0x55, 0xce, 0x00, 0x7f, 0x54, 0x94, 0xff, 0x00, +0x15, 0xe2, 0x83, 0x18, 0x15, 0xc2, 0x03, 0x1c, 0x14, 0x91, 0x83, 0x19, 0x14, 0x11, 0x03, 0x1d, +0x84, 0x24, 0x4c, 0x00, 0xff, 0xe6, 0x44, 0x00, 0x00, 0xe0, 0x42, 0x04, 0x00, 0x24, 0x3e, 0x29, +0xde, 0x30, 0x98, 0x02, 0x50, 0x00, 0x00, 0xb8, 0xb4, 0x40, 0x80, 0x23, 0x14, 0x20, 0x82, 0x06, +0xa0, 0x81, 0x14, 0x20, 0x82, 0x07, 0xa0, 0x82, 0x14, 0x20, 0x82, 0x08, 0xa0, 0x83, 0x14, 0x20, +0x82, 0x09, 0xa0, 0x84, 0x14, 0x20, 0x82, 0x0a, 0xa0, 0x85, 0x14, 0x20, 0x82, 0x0b, 0xa0, 0x86, +0x14, 0x20, 0x81, 0xcf, 0xa0, 0x87, 0x14, 0x20, 0x83, 0x04, 0x04, 0x20, 0x00, 0x08, 0x14, 0x20, +0x83, 0x05, 0x04, 0x20, 0x00, 0x09, 0x80, 0x01, 0x14, 0x20, 0x82, 0x05, 0x14, 0xa0, 0x01, 0xc0, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x96, 0x00, 0x9e, 0x41, 0x96, 0x48, 0xe6, 0x2e, +0xe9, 0x32, 0x50, 0x10, 0x00, 0x49, 0x96, 0x48, 0xe6, 0x2e, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x2c, +0x50, 0x10, 0x00, 0x38, 0x96, 0x48, 0xe6, 0x31, 0xe8, 0x03, 0x84, 0x02, 0xd5, 0x25, 0x50, 0x10, +0x7f, 0xe0, 0x96, 0x48, 0xe6, 0x33, 0xe8, 0x03, 0x84, 0x03, 0xd5, 0x1e, 0x50, 0x10, 0x7f, 0xcc, +0x96, 0x48, 0xe6, 0x31, 0xe8, 0x03, 0x84, 0x04, 0xd5, 0x17, 0x50, 0x10, 0x7f, 0x9c, 0x96, 0x48, +0xe6, 0x31, 0xe8, 0x03, 0x84, 0x05, 0xd5, 0x10, 0x50, 0x10, 0x7f, 0x88, 0x96, 0x48, 0xe6, 0x35, +0xe8, 0x03, 0x84, 0x06, 0xd5, 0x09, 0x50, 0x00, 0x00, 0x6b, 0x96, 0x00, 0xe6, 0x11, 0xe8, 0x03, +0x84, 0x07, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0xb4, 0x80, +0xb5, 0x40, 0xb4, 0x40, 0x80, 0x20, 0xf2, 0x81, 0x8c, 0x08, 0xa2, 0xc9, 0x42, 0xa5, 0x78, 0x0b, +0xb6, 0x7f, 0xb4, 0xc1, 0xb5, 0x20, 0x3c, 0x0c, 0x62, 0x82, 0x3c, 0x6e, 0x62, 0x82, 0x84, 0xa1, +0x4c, 0xa2, 0x80, 0x09, 0x44, 0x1f, 0xff, 0xb5, 0x44, 0x2f, 0xff, 0xc4, 0x44, 0x3f, 0xff, 0xd3, +0xd5, 0x18, 0x40, 0x00, 0x18, 0x07, 0x44, 0x1f, 0xff, 0xd5, 0x9e, 0x8c, 0x40, 0x31, 0x00, 0x1a, +0x40, 0x30, 0x80, 0x1b, 0x44, 0x5f, 0xff, 0xb3, 0x8e, 0x5a, 0x40, 0x12, 0x80, 0x1a, 0x40, 0x11, +0x00, 0x1b, 0x44, 0x7f, 0xff, 0xc2, 0x8c, 0xb3, 0x40, 0x23, 0x80, 0x1a, 0x40, 0x22, 0x80, 0x1b, +0x96, 0x20, 0xe6, 0x0f, 0xe8, 0x19, 0x2e, 0x01, 0x8a, 0x6c, 0x84, 0xa1, 0xd8, 0x10, 0xe0, 0x66, +0xe8, 0x04, 0x46, 0x01, 0xa0, 0xe0, 0xd5, 0x3b, 0xe0, 0x46, 0xe8, 0x04, 0x46, 0x01, 0x61, 0xc0, +0xd5, 0x36, 0xe0, 0x26, 0xe8, 0x2c, 0x46, 0x01, 0x82, 0x20, 0xd5, 0x31, 0xe0, 0x66, 0xe8, 0x22, +0x46, 0x01, 0x81, 0xe0, 0xd5, 0x2c, 0x2e, 0x01, 0x8a, 0x6d, 0x84, 0xa1, 0xd8, 0x16, 0xe0, 0x66, +0xe8, 0x04, 0x46, 0x01, 0xe2, 0x00, 0xd5, 0x23, 0xe0, 0x46, 0xe8, 0x04, 0x46, 0x02, 0x02, 0xa0, +0xd5, 0x1e, 0x46, 0x51, 0x42, 0x40, 0x46, 0x42, 0x23, 0x20, 0x40, 0x70, 0x98, 0x07, 0x40, 0x02, +0x9c, 0x1b, 0x40, 0x02, 0x1c, 0x1a, 0xd5, 0x13, 0xe0, 0x66, 0xe8, 0x04, 0x46, 0x01, 0x82, 0x00, +0xd5, 0x0e, 0xe0, 0x46, 0xe9, 0x04, 0xe0, 0x26, 0xe9, 0x05, 0xd5, 0x07, 0x46, 0x01, 0x83, 0x00, +0xd5, 0x06, 0x46, 0x01, 0x83, 0x60, 0xd5, 0x03, 0x46, 0x01, 0xe4, 0x20, 0x3c, 0x50, 0xc5, 0x6e, +0x92, 0x10, 0x40, 0x00, 0x40, 0x08, 0x46, 0x40, 0x04, 0x12, 0x40, 0x50, 0x14, 0x04, 0x14, 0x52, +0x00, 0xc8, 0x3c, 0x70, 0xc5, 0x70, 0x80, 0xa4, 0x40, 0x00, 0x1c, 0x04, 0x14, 0x02, 0x80, 0xc9, +0x04, 0x72, 0x00, 0xc8, 0x92, 0xe8, 0x54, 0x73, 0x80, 0x7f, 0xe0, 0x66, 0xe8, 0x08, 0x50, 0x73, +0xff, 0xd0, 0x97, 0xf8, 0x44, 0x8f, 0xff, 0xd3, 0x84, 0x00, 0xd5, 0x15, 0xe0, 0x46, 0xe8, 0x08, +0x50, 0x73, 0xff, 0xe0, 0x97, 0xf8, 0x44, 0x8f, 0xff, 0xc4, 0x84, 0x01, 0xd5, 0x0c, 0xe0, 0x26, +0xe9, 0x05, 0x44, 0x8f, 0xff, 0x9c, 0x84, 0x03, 0xd5, 0x06, 0x8e, 0xf0, 0x97, 0xf8, 0x44, 0x8f, +0xff, 0xb5, 0x84, 0x02, 0x4e, 0xa3, 0x00, 0x35, 0x47, 0xc0, 0x01, 0x19, 0x3c, 0x0c, 0x62, 0xaf, +0x4c, 0x80, 0x00, 0x0d, 0x3e, 0x09, 0x5b, 0x9c, 0x80, 0x27, 0x49, 0xff, 0xc3, 0x01, 0x3c, 0x0c, +0x62, 0xaf, 0xe0, 0x08, 0xe8, 0x03, 0x3e, 0xa1, 0x8a, 0x6e, 0x3c, 0x8e, 0x62, 0xaf, 0x5c, 0xf4, +0x83, 0xe9, 0xe9, 0x0a, 0x3e, 0x09, 0x8a, 0x6e, 0x20, 0x10, 0x00, 0x00, 0x5e, 0xf0, 0xff, 0xf5, +0xe9, 0x0e, 0x9e, 0x4a, 0xd5, 0x0b, 0x5c, 0xf4, 0x80, 0x64, 0xe8, 0x09, 0x3e, 0x09, 0x8a, 0x6e, +0x20, 0x10, 0x00, 0x00, 0x4e, 0x14, 0x00, 0x04, 0x9c, 0x4a, 0xae, 0x40, 0x2e, 0x19, 0x8a, 0x6e, +0x3e, 0x09, 0x5b, 0xc0, 0x49, 0xff, 0xc2, 0xdc, 0x2e, 0x11, 0x8a, 0x6e, 0xd5, 0x1d, 0x5c, 0xf4, +0x83, 0xe9, 0xe9, 0x0a, 0x3e, 0x19, 0xce, 0x90, 0x38, 0x20, 0x82, 0x02, 0x5e, 0xf1, 0x7f, 0xf5, +0xe9, 0x0f, 0x9e, 0x92, 0xd5, 0x0b, 0x5c, 0xf4, 0x80, 0x64, 0xe8, 0x0a, 0x3e, 0x19, 0xce, 0x90, +0x38, 0x20, 0x82, 0x02, 0x4e, 0x24, 0x00, 0x05, 0x9c, 0x92, 0x38, 0x20, 0x82, 0x0a, 0x3e, 0x19, +0xce, 0x90, 0x38, 0x10, 0x82, 0x02, 0x46, 0x00, 0x04, 0x12, 0x04, 0x30, 0x00, 0xc8, 0x99, 0xf9, +0x96, 0x78, 0x44, 0x4f, 0x80, 0xff, 0x40, 0x20, 0xa0, 0x08, 0x40, 0x31, 0x90, 0x02, 0x40, 0x31, +0x0c, 0x04, 0x14, 0x30, 0x00, 0xc8, 0x04, 0x30, 0x00, 0xc9, 0x40, 0x31, 0x90, 0x02, 0x40, 0x21, +0x0c, 0x04, 0x14, 0x20, 0x00, 0xc9, 0x3e, 0x09, 0x5b, 0xe0, 0x49, 0xff, 0xc2, 0xa1, 0xf1, 0x01, +0x84, 0xa1, 0x42, 0x00, 0xf4, 0x0b, 0xd8, 0x03, 0x49, 0xff, 0xfd, 0x48, 0xb4, 0x7f, 0x84, 0xa1, +0x42, 0x01, 0xf0, 0x0b, 0xd8, 0x33, 0x5e, 0xf3, 0x7f, 0xc0, 0xe9, 0x18, 0x46, 0x00, 0x04, 0x12, +0x04, 0x20, 0x02, 0x54, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x02, 0x54, 0x80, 0x20, 0x04, 0x20, +0x80, 0xc8, 0x46, 0x00, 0x04, 0x12, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x80, 0xc8, 0x58, 0x00, +0x03, 0x24, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x02, 0xd5, 0x18, 0x46, 0x00, 0x04, 0x12, 0x04, 0x20, +0x02, 0x54, 0x80, 0x20, 0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x02, 0x54, 0x04, 0x20, 0x80, 0xc8, +0x84, 0x9d, 0x40, 0x21, 0x10, 0x02, 0x46, 0x00, 0x04, 0x12, 0x14, 0x20, 0x80, 0xc8, 0x58, 0x00, +0x03, 0x24, 0xb4, 0x20, 0x40, 0x10, 0x90, 0x02, 0xb6, 0x20, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x2e, 0x31, 0x8a, 0x7c, 0x46, 0x20, +0x04, 0x12, 0x96, 0x40, 0x04, 0x21, 0x00, 0xc0, 0xcb, 0x02, 0xd5, 0x0c, 0x84, 0xa1, 0xdb, 0x07, +0x4c, 0x11, 0xc0, 0x03, 0xd5, 0x07, 0x84, 0xa3, 0xd9, 0x20, 0xd5, 0x0b, 0x84, 0xa2, 0xdb, 0x1d, +0xc9, 0x06, 0x44, 0x0f, 0xfc, 0xff, 0x40, 0x21, 0x00, 0x02, 0xd5, 0x17, 0x84, 0xa1, 0xd9, 0x08, +0x44, 0x0f, 0xfc, 0xff, 0x40, 0x21, 0x00, 0x02, 0x58, 0x21, 0x01, 0x00, 0xd5, 0x0e, 0x84, 0xa2, +0xd9, 0x08, 0x44, 0x0f, 0xfc, 0xff, 0x40, 0x21, 0x00, 0x02, 0x58, 0x21, 0x02, 0x00, 0xd5, 0x05, +0x84, 0xa3, 0xd9, 0x2d, 0x58, 0x21, 0x03, 0x00, 0x46, 0x00, 0x04, 0x12, 0x14, 0x20, 0x00, 0xc0, +0x04, 0x20, 0x01, 0xc0, 0xcb, 0x02, 0xd5, 0x0c, 0x84, 0xa1, 0xdb, 0x07, 0x4c, 0x11, 0xc0, 0x03, +0xd5, 0x07, 0x84, 0xa3, 0xd9, 0x22, 0xd5, 0x09, 0x84, 0xa2, 0xdb, 0x1f, 0xc9, 0x04, 0x92, 0x42, +0x94, 0x92, 0xd5, 0x1b, 0x84, 0xa1, 0xd9, 0x06, 0x92, 0x42, 0x94, 0x92, 0x58, 0x21, 0x00, 0x01, +0xd5, 0x14, 0x84, 0xa2, 0xd9, 0x06, 0x92, 0x42, 0x94, 0x92, 0x58, 0x21, 0x00, 0x02, 0xd5, 0x0d, +0x84, 0x03, 0x4c, 0x10, 0x40, 0x05, 0x40, 0x21, 0x00, 0x04, 0xd5, 0x07, 0x3e, 0x09, 0x5b, 0xfc, +0x49, 0xff, 0xc1, 0xfe, 0x92, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x04, 0x12, 0x14, 0x20, 0x01, 0xc0, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x55, 0xc0, +0x00, 0xff, 0x4f, 0xc2, 0x00, 0x0a, 0x2e, 0x01, 0x8a, 0x72, 0x84, 0xa1, 0xd8, 0x0d, 0x3e, 0x69, +0x89, 0x50, 0x85, 0x4b, 0xd5, 0x0b, 0x2e, 0x01, 0x8a, 0x73, 0x84, 0xa1, 0xd8, 0x05, 0x3e, 0x69, +0x89, 0xa8, 0x85, 0x45, 0xd5, 0x03, 0x84, 0xc0, 0x81, 0x46, 0x80, 0xe6, 0x85, 0x20, 0xd5, 0x1b, +0xa6, 0xf8, 0x84, 0xa9, 0x80, 0x23, 0xdb, 0x0a, 0xa4, 0x79, 0xa0, 0xb9, 0x84, 0x00, 0x49, 0xff, +0xf8, 0x79, 0xa4, 0x79, 0xa0, 0xb9, 0x84, 0x01, 0xd5, 0x06, 0xe6, 0x62, 0xe8, 0x07, 0xa4, 0x79, +0xa0, 0xb9, 0x80, 0x03, 0x49, 0xff, 0xf8, 0x6e, 0xd5, 0x04, 0x49, 0xff, 0xc1, 0xc1, 0x92, 0x00, +0x8d, 0x21, 0x8c, 0xe8, 0x3e, 0x09, 0x5c, 0x24, 0xe1, 0x2a, 0xe9, 0xe3, 0x4f, 0xc2, 0x00, 0x0a, +0x2e, 0x81, 0x8a, 0x6d, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0d, 0x3e, 0x69, 0x89, 0xd0, 0xd5, 0x0a, +0x2e, 0x81, 0x8a, 0x6c, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x05, 0x3e, 0x69, 0x89, 0xd8, 0xd5, 0x02, +0x85, 0x00, 0x84, 0x20, 0xd5, 0x1a, 0xa6, 0xf0, 0x84, 0x49, 0x80, 0x23, 0x4c, 0x31, 0x40, 0x0b, +0xa4, 0x71, 0xa0, 0xb1, 0x84, 0x00, 0x49, 0xff, 0xf8, 0x45, 0xa4, 0x71, 0xa0, 0xb1, 0x84, 0x01, +0xd5, 0x06, 0xe6, 0x62, 0xe8, 0x07, 0xa4, 0x71, 0xa0, 0xb1, 0x80, 0x03, 0x49, 0xff, 0xf8, 0x3a, +0xd5, 0x03, 0x49, 0xff, 0xc1, 0x8d, 0x84, 0x21, 0x3e, 0x09, 0x5c, 0x40, 0xe0, 0x28, 0xe9, 0xe4, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x3e, 0x69, 0x7b, 0x30, +0xa6, 0xf0, 0x84, 0xa9, 0x3e, 0x09, 0x5c, 0x5c, 0x80, 0x23, 0xdb, 0x0e, 0x02, 0x83, 0x00, 0x01, +0x04, 0xa3, 0x00, 0x01, 0x80, 0x28, 0x80, 0x4a, 0x84, 0x00, 0x49, 0xff, 0xf8, 0x1b, 0x80, 0x28, +0x80, 0x4a, 0x84, 0x01, 0xd5, 0x06, 0xe6, 0x62, 0xe8, 0x07, 0xa4, 0x71, 0xa0, 0xb1, 0x80, 0x03, +0x49, 0xff, 0xf8, 0x10, 0xd5, 0x03, 0x49, 0xff, 0xc1, 0x63, 0x8c, 0xc8, 0x3e, 0x59, 0x7b, 0x80, +0xde, 0xe0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x2e, 0x21, +0x8a, 0x5a, 0x97, 0xc0, 0x44, 0x50, 0x00, 0xff, 0x80, 0xc1, 0xd2, 0x3f, 0x2e, 0x01, 0x8a, 0x78, +0xe2, 0x02, 0xe9, 0x3b, 0xcf, 0x1c, 0x3e, 0x09, 0x8a, 0x79, 0xa6, 0x80, 0x3e, 0x89, 0xce, 0xac, +0x9c, 0x51, 0x96, 0x48, 0x38, 0x64, 0x0a, 0x0a, 0x84, 0xa8, 0xae, 0x40, 0xd9, 0x48, 0xaf, 0xc0, +0x80, 0xc7, 0xb4, 0x28, 0x3e, 0x09, 0x5c, 0x74, 0x49, 0xff, 0xc1, 0x3a, 0x0c, 0x04, 0x00, 0x01, +0x99, 0xb0, 0x3e, 0x59, 0xce, 0xcc, 0x4c, 0x82, 0xff, 0xf6, 0xd5, 0x1c, 0x3e, 0x09, 0x8a, 0x7a, +0xa6, 0x80, 0x3e, 0x89, 0xce, 0xcc, 0x9c, 0x51, 0x96, 0x48, 0x38, 0x64, 0x0a, 0x0a, 0x84, 0xa8, +0xae, 0x40, 0xd9, 0x2d, 0x84, 0x20, 0xae, 0x40, 0x84, 0xc0, 0xb4, 0x28, 0x3e, 0x09, 0x5c, 0x74, +0x49, 0xff, 0xc1, 0x1e, 0x0c, 0x04, 0x00, 0x01, 0x99, 0xb0, 0x3e, 0x59, 0xce, 0xec, 0x4c, 0x82, +0xff, 0xf6, 0x84, 0x08, 0x40, 0x63, 0x00, 0x16, 0x80, 0x46, 0x3e, 0x09, 0x5c, 0x78, 0x80, 0x27, +0x49, 0xff, 0xc1, 0x0e, 0x54, 0x63, 0x00, 0x3f, 0xcf, 0x06, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, +0x03, 0xb4, 0xd5, 0x05, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x03, 0xa8, 0xb4, 0x20, 0x92, 0x26, +0x94, 0x4e, 0xb6, 0x20, 0xb4, 0x20, 0x40, 0x63, 0x04, 0x04, 0xb6, 0xc0, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x2e, 0x71, 0x8a, 0x77, 0x54, 0x90, +0x00, 0xff, 0x84, 0x01, 0x96, 0x48, 0x96, 0x90, 0x96, 0xd8, 0x97, 0x20, 0x97, 0xa8, 0x4c, 0x70, +0x02, 0x21, 0x50, 0x5f, 0x80, 0x10, 0x96, 0x1a, 0xa8, 0xa9, 0xb6, 0x25, 0x50, 0x5f, 0x80, 0x08, +0x4e, 0x04, 0x00, 0x04, 0x50, 0x31, 0xff, 0x00, 0x96, 0x22, 0xb6, 0x65, 0x50, 0x5f, 0x80, 0x08, +0x4e, 0x04, 0x00, 0x04, 0x50, 0x42, 0x7f, 0x00, 0xa9, 0x29, 0x50, 0x0f, 0x80, 0x08, 0xa1, 0x01, +0xb4, 0x60, 0x3e, 0x09, 0x5c, 0x98, 0x49, 0xff, 0xc0, 0xcb, 0xe6, 0xc2, 0xe8, 0x13, 0x46, 0x10, +0x04, 0x12, 0x46, 0x20, 0x00, 0x8a, 0x58, 0x21, 0x0c, 0x50, 0x14, 0x20, 0x80, 0x22, 0x84, 0x21, +0x4c, 0x60, 0xc0, 0x09, 0x3e, 0x09, 0x5c, 0xd0, 0x49, 0xff, 0xc0, 0xba, 0x80, 0x06, 0x48, 0x00, +0x01, 0xf3, 0x46, 0x70, 0x04, 0x12, 0x84, 0xc0, 0x47, 0xc0, 0x00, 0x80, 0x59, 0xce, 0x09, 0x4c, +0x04, 0x83, 0x80, 0x22, 0x3e, 0x09, 0x5c, 0xe0, 0x80, 0x28, 0x54, 0x84, 0x00, 0x10, 0xdd, 0x3c, +0x44, 0x00, 0x00, 0x64, 0x4e, 0x82, 0x00, 0x08, 0x49, 0xff, 0xf7, 0x3c, 0x9d, 0xb1, 0x84, 0x45, +0x4c, 0x61, 0x7f, 0xf0, 0x3e, 0x09, 0x5c, 0xec, 0x80, 0x26, 0x49, 0xff, 0xc0, 0x99, 0x84, 0x65, +0x4c, 0x61, 0x81, 0xd0, 0x2e, 0x01, 0x8a, 0x5a, 0x2e, 0x21, 0x8a, 0x78, 0xe2, 0x40, 0xe8, 0x04, +0x9c, 0x91, 0x3e, 0x21, 0x8a, 0x78, 0x46, 0x10, 0x04, 0x12, 0x04, 0x10, 0x80, 0x23, 0x50, 0x2f, +0x80, 0x18, 0x4e, 0x93, 0x00, 0x09, 0x40, 0x00, 0xc0, 0x09, 0x96, 0x00, 0x96, 0x48, 0xa8, 0x11, +0xb6, 0x22, 0xd5, 0x07, 0x40, 0x00, 0xa0, 0x09, 0x96, 0x00, 0x92, 0x38, 0xa8, 0x51, 0xb6, 0x02, +0x50, 0x1f, 0x80, 0x18, 0xb4, 0x01, 0x5e, 0xf0, 0x00, 0x80, 0xe9, 0x04, 0x50, 0x00, 0x7f, 0x00, +0xb6, 0x01, 0x50, 0x1f, 0x80, 0x18, 0xa0, 0x09, 0x5e, 0xf0, 0x00, 0x80, 0xe9, 0x04, 0x50, 0x00, +0x7f, 0x00, 0xa8, 0x09, 0x3c, 0x24, 0xe7, 0x55, 0x3c, 0x14, 0xe7, 0x54, 0x46, 0x70, 0x00, 0x80, +0x58, 0x73, 0x89, 0x4c, 0x3e, 0x09, 0x5c, 0xf4, 0xdd, 0x27, 0x50, 0x0f, 0x80, 0x18, 0xa0, 0x81, +0xb4, 0x20, 0x3e, 0x09, 0x5d, 0x10, 0xdd, 0x27, 0x46, 0x20, 0x04, 0x12, 0x46, 0x00, 0x00, 0x8a, +0x58, 0x21, 0x00, 0x88, 0x58, 0x00, 0x0c, 0x41, 0xb6, 0x02, 0x46, 0x30, 0x00, 0x8a, 0x9c, 0x14, +0x58, 0x31, 0x8c, 0x42, 0xb4, 0x20, 0xb6, 0x62, 0x46, 0x30, 0x00, 0x8a, 0xb4, 0x80, 0x58, 0x31, +0x8c, 0x44, 0xb6, 0x62, 0x40, 0x22, 0x40, 0x08, 0x92, 0x5e, 0xb5, 0x00, 0xc2, 0x06, 0x3e, 0x09, +0x5d, 0x28, 0xdd, 0x27, 0x48, 0x00, 0x01, 0x6e, 0x54, 0x00, 0x80, 0x07, 0x96, 0x49, 0xe6, 0x04, +0xe8, 0x04, 0xe6, 0x02, 0xe8, 0x06, 0xd5, 0x22, 0x84, 0x64, 0x4c, 0x01, 0xc0, 0x1d, 0xd5, 0x15, +0x40, 0x00, 0xa0, 0x09, 0x54, 0x00, 0x00, 0x7f, 0xe6, 0x08, 0xe9, 0x07, 0x44, 0x20, 0x00, 0x20, +0x4c, 0x01, 0x00, 0x04, 0x84, 0xc2, 0xd5, 0x02, 0x84, 0xc1, 0x92, 0x26, 0x54, 0x10, 0x80, 0x03, +0x84, 0x02, 0x40, 0x60, 0x04, 0x1b, 0xd5, 0x0b, 0x40, 0x60, 0x94, 0x09, 0x54, 0x63, 0x00, 0x07, +0x9d, 0xb1, 0xd5, 0x05, 0x3e, 0x09, 0x5d, 0x48, 0xdd, 0x27, 0x84, 0xc1, 0x3e, 0x09, 0x5d, 0x5c, +0x80, 0x26, 0x40, 0x94, 0x00, 0x13, 0x49, 0xff, 0xc0, 0x03, 0x50, 0x0f, 0x80, 0x20, 0x54, 0x14, +0x00, 0xff, 0x40, 0x24, 0xa0, 0x09, 0xa8, 0x81, 0xb6, 0x20, 0x5e, 0xf0, 0x80, 0x80, 0x4e, 0xf2, +0x01, 0x31, 0x5e, 0xf1, 0x00, 0x80, 0x4e, 0xf2, 0x01, 0x2d, 0x3e, 0x09, 0x5d, 0x68, 0x49, 0xff, +0xbf, 0xef, 0x46, 0x00, 0x04, 0x12, 0x84, 0x21, 0x04, 0x00, 0x01, 0xc5, 0x4c, 0x60, 0xc0, 0x0d, +0x54, 0x00, 0x00, 0x03, 0xc8, 0x03, 0xb6, 0x1f, 0xd5, 0x0a, 0x84, 0x41, 0x4c, 0x01, 0x40, 0x05, +0xb6, 0xdf, 0xf6, 0x81, 0xd5, 0x05, 0x84, 0x61, 0xb6, 0x7f, 0x84, 0x00, 0xf0, 0x81, 0x05, 0xcf, +0x80, 0x01, 0x85, 0x40, 0x46, 0x60, 0x00, 0x80, 0x58, 0x63, 0x09, 0x4c, 0x48, 0x00, 0x00, 0xaf, +0x3e, 0x39, 0xce, 0xa8, 0x50, 0x1f, 0x80, 0x18, 0x38, 0x21, 0xf1, 0x01, 0x38, 0x90, 0xf2, 0x02, +0x50, 0x0f, 0x80, 0x20, 0x40, 0x24, 0x88, 0x01, 0x38, 0x70, 0x72, 0x02, 0x96, 0x11, 0x49, 0xff, +0xf8, 0x87, 0x80, 0x20, 0x81, 0x00, 0x3e, 0x09, 0x5d, 0x84, 0xdd, 0x26, 0x50, 0x3f, 0x80, 0x10, +0x38, 0x21, 0xf2, 0x02, 0x3e, 0x09, 0x5d, 0x94, 0x42, 0x84, 0x08, 0x24, 0x40, 0x73, 0xb0, 0x08, +0x80, 0x28, 0xdd, 0x26, 0x50, 0x0f, 0x80, 0x08, 0x38, 0x20, 0x72, 0x02, 0x3e, 0x09, 0x5d, 0xa4, +0x40, 0x21, 0x24, 0x08, 0x89, 0x02, 0x80, 0x28, 0xdd, 0x26, 0x8a, 0xe8, 0x3e, 0x09, 0x5d, 0xb4, +0x80, 0x3c, 0x40, 0x24, 0x30, 0x09, 0xdd, 0x26, 0x3e, 0x09, 0x5d, 0xd4, 0x80, 0x27, 0xdd, 0x26, +0x4e, 0x75, 0x00, 0x04, 0x84, 0x80, 0xd5, 0x04, 0x52, 0x73, 0x80, 0x00, 0x84, 0x81, 0x54, 0x23, +0x8f, 0xff, 0x40, 0x13, 0xb0, 0x0a, 0x5e, 0xf1, 0x08, 0x01, 0xe9, 0x02, 0x9c, 0x49, 0x56, 0x42, +0x00, 0x01, 0x52, 0x20, 0x80, 0x00, 0x40, 0x11, 0x10, 0x1a, 0x40, 0xa0, 0x80, 0x11, 0x3e, 0x09, +0x5d, 0xec, 0xdd, 0x26, 0x3e, 0x09, 0x5e, 0x04, 0x80, 0x2a, 0xdd, 0x26, 0x4f, 0xc3, 0x00, 0x07, +0x46, 0x20, 0x04, 0x11, 0x58, 0x21, 0x03, 0xb4, 0xd5, 0x05, 0x46, 0x20, 0x04, 0x11, 0x58, 0x21, +0x03, 0xa8, 0xb4, 0x42, 0x54, 0x21, 0x00, 0x3f, 0x54, 0x41, 0x00, 0x20, 0xc4, 0x04, 0x50, 0x71, +0x7f, 0xc0, 0xd5, 0x02, 0x80, 0xe2, 0x80, 0x27, 0x3e, 0x09, 0x5e, 0x14, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x7f, 0x4c, 0x90, 0xc0, 0x07, 0x5e, 0x05, 0x00, 0x01, 0x84, 0x9f, 0x40, 0xa2, 0x00, 0x1a, +0x3e, 0x29, 0xce, 0xa8, 0x38, 0x31, 0x71, 0x11, 0x40, 0x34, 0x8c, 0x01, 0xe4, 0x65, 0xe8, 0x03, +0x85, 0x40, 0xd5, 0x08, 0xe5, 0x45, 0xe9, 0x03, 0x85, 0x44, 0xd5, 0x04, 0x84, 0x7c, 0x42, 0xa5, +0x0c, 0x00, 0x88, 0xea, 0x5e, 0xf3, 0x80, 0x20, 0xe9, 0x04, 0x44, 0x70, 0x00, 0x1f, 0xd5, 0x05, +0x44, 0x3f, 0xff, 0xe0, 0x42, 0x73, 0x8c, 0x00, 0x46, 0x90, 0x04, 0x11, 0x81, 0x09, 0x04, 0x14, +0x80, 0xed, 0x04, 0x24, 0x00, 0xea, 0x3e, 0x09, 0x5e, 0x24, 0xdd, 0x26, 0x80, 0x1c, 0x80, 0x27, +0x49, 0xff, 0xfd, 0xd4, 0x04, 0x14, 0x80, 0xed, 0x04, 0x24, 0x00, 0xea, 0x3e, 0x09, 0x5e, 0x48, +0x51, 0xce, 0x00, 0x01, 0xdd, 0x26, 0x55, 0xce, 0x00, 0xff, 0xb4, 0x7f, 0xe2, 0x7c, 0x4e, 0xf2, +0xff, 0x51, 0xf0, 0x01, 0x4c, 0x01, 0x80, 0x03, 0xd5, 0x52, 0x46, 0x70, 0x04, 0x11, 0x80, 0xc7, +0x04, 0x13, 0x80, 0xed, 0x04, 0x23, 0x00, 0xea, 0x3e, 0x09, 0x5e, 0x6c, 0x49, 0xff, 0xbf, 0x10, +0xf1, 0x01, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x1d, 0x3e, 0x09, 0x5e, 0x9c, 0x49, 0xff, 0xbf, 0x08, +0x04, 0x03, 0x80, 0xed, 0x54, 0x20, 0x00, 0x20, 0x54, 0x00, 0x00, 0x3f, 0xc2, 0x03, 0x50, 0x00, +0x7f, 0xc0, 0x40, 0x10, 0x28, 0x00, 0x5e, 0xf0, 0x80, 0x20, 0xe9, 0x04, 0x44, 0x10, 0x00, 0x1f, +0xd5, 0x05, 0x44, 0x0f, 0xff, 0xe0, 0x42, 0x10, 0x80, 0x00, 0x84, 0x00, 0xd5, 0x1b, 0x3e, 0x09, +0x5e, 0xcc, 0x49, 0xff, 0xbe, 0xed, 0x04, 0x03, 0x00, 0xea, 0x54, 0x20, 0x00, 0x20, 0x54, 0x00, +0x00, 0x3f, 0xc2, 0x03, 0x50, 0x00, 0x7f, 0xc0, 0x40, 0x10, 0x28, 0x00, 0x5e, 0xf0, 0x80, 0x20, +0xe9, 0x04, 0x44, 0x10, 0x00, 0x1f, 0xd5, 0x05, 0x44, 0x0f, 0xff, 0xe0, 0x42, 0x10, 0x80, 0x00, +0x84, 0x01, 0x49, 0xff, 0xfd, 0x7b, 0x46, 0x10, 0x04, 0x11, 0x80, 0x01, 0x04, 0x10, 0x80, 0xed, +0x04, 0x20, 0x00, 0xea, 0x3e, 0x09, 0x5e, 0xfc, 0x49, 0xff, 0xbe, 0xca, 0x84, 0x01, 0xd5, 0x03, +0x44, 0x00, 0x00, 0xff, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x46, 0x10, 0x04, 0x12, 0x04, 0x20, 0x81, 0xca, 0x80, 0xe1, 0x46, 0x20, 0x10, 0x00, 0x81, 0x00, +0x84, 0x60, 0x14, 0x23, 0x81, 0xc9, 0x44, 0x04, 0x00, 0x00, 0x98, 0x90, 0x04, 0x00, 0x81, 0xca, +0x80, 0xc1, 0x96, 0x00, 0x98, 0xd8, 0x46, 0x00, 0x12, 0xc0, 0x80, 0xa1, 0x4c, 0x20, 0x7f, 0xf3, +0x46, 0x10, 0x12, 0x80, 0x14, 0x13, 0x01, 0xc9, 0x44, 0x60, 0x00, 0x37, 0x04, 0x22, 0x81, 0xca, +0x84, 0x0a, 0x96, 0x90, 0x42, 0x61, 0x18, 0x24, 0x80, 0x23, 0x40, 0x63, 0x00, 0x17, 0x80, 0x88, +0x3e, 0x09, 0x5f, 0x2c, 0x9b, 0x9e, 0x80, 0x66, 0x49, 0xff, 0xbe, 0x92, 0x92, 0x00, 0xe0, 0xc8, +0xe9, 0x03, 0x84, 0x00, 0xd5, 0x05, 0x5e, 0x63, 0x7f, 0xf2, 0x56, 0x03, 0x00, 0x01, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x0c, 0x62, 0xb4, 0x4e, 0x06, +0x00, 0x08, 0x3e, 0x09, 0x5f, 0x58, 0x49, 0xff, 0xbe, 0x7b, 0x92, 0x00, 0xd5, 0x16, 0x9e, 0x41, +0x94, 0x4a, 0x3e, 0x39, 0xd1, 0xfc, 0x3e, 0x59, 0xd1, 0x7c, 0x98, 0x8b, 0x98, 0x4d, 0x0c, 0x30, +0xff, 0xff, 0x46, 0x50, 0x04, 0x10, 0x0c, 0x41, 0x7f, 0xff, 0x98, 0xdd, 0x9e, 0x01, 0xb6, 0x83, +0x4e, 0x06, 0xff, 0xf7, 0x3c, 0x0e, 0x62, 0xb4, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x62, 0xb4, 0x3e, 0x39, 0xd1, 0x7c, 0x38, 0x01, +0x86, 0x0a, 0x46, 0x30, 0x04, 0x10, 0x98, 0x03, 0xb4, 0x80, 0x3e, 0x39, 0xd1, 0xfc, 0x9c, 0x09, +0x38, 0x41, 0x86, 0x0a, 0x3c, 0x0e, 0x62, 0xb4, 0x5e, 0xf0, 0x00, 0x21, 0xe9, 0x06, 0x3e, 0x09, +0x5f, 0x70, 0x49, 0xff, 0xbe, 0x45, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xbc, 0x3c, 0x2c, 0x60, 0x0d, 0x96, 0x00, 0x96, 0x48, 0x40, 0x31, +0x40, 0x09, 0xf0, 0x86, 0x84, 0xa1, 0xf1, 0x8b, 0x10, 0x3f, 0x80, 0x3e, 0x12, 0x2f, 0x80, 0x1e, +0xd9, 0x06, 0x84, 0x28, 0xf1, 0x8a, 0x44, 0x90, 0x00, 0xb8, 0xd5, 0x0d, 0x2e, 0x41, 0x8a, 0x73, +0x44, 0x30, 0x00, 0xa4, 0x44, 0x20, 0x00, 0xb8, 0x40, 0x91, 0x90, 0x1a, 0x40, 0x91, 0x10, 0x1b, +0x84, 0x44, 0xf2, 0x8a, 0x46, 0x60, 0x00, 0x88, 0x58, 0x63, 0x0c, 0x90, 0x44, 0x00, 0x27, 0x14, +0xdd, 0x26, 0x44, 0x00, 0x27, 0x6c, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x70, 0xdd, 0x26, 0x44, 0x00, +0x27, 0x18, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x80, 0xdd, 0x26, +0xf3, 0x06, 0x46, 0x20, 0x04, 0x12, 0x46, 0x18, 0x00, 0x00, 0x58, 0x41, 0x80, 0x80, 0x46, 0x0c, +0x00, 0x02, 0x40, 0x31, 0xf8, 0x08, 0x58, 0x10, 0x80, 0x12, 0x14, 0x41, 0x01, 0xc5, 0x84, 0xa0, +0x46, 0x60, 0x0f, 0xff, 0x40, 0x11, 0x84, 0x04, 0x58, 0x00, 0x01, 0x01, 0x50, 0x2f, 0x80, 0x3f, +0xf1, 0x8c, 0x58, 0x63, 0x0f, 0xff, 0xf0, 0x89, 0xf5, 0x85, 0xf2, 0x81, 0x48, 0x00, 0x00, 0xb6, +0x46, 0x30, 0x04, 0x12, 0x40, 0x24, 0xa0, 0x08, 0xf3, 0x87, 0xf0, 0x06, 0x40, 0x21, 0x24, 0x04, +0x44, 0x10, 0x02, 0x10, 0xf3, 0x88, 0xf3, 0x84, 0xf5, 0x82, 0x49, 0xff, 0xf4, 0x83, 0xf0, 0x07, +0xf1, 0x08, 0xf2, 0x04, 0x47, 0xc0, 0x04, 0x12, 0x58, 0x00, 0x07, 0x18, 0x58, 0x10, 0x87, 0x6c, +0x58, 0x21, 0x07, 0x70, 0x59, 0xce, 0x00, 0x10, 0x14, 0x9f, 0x80, 0x0d, 0xf0, 0x87, 0xf1, 0x88, +0xf2, 0x84, 0x04, 0x9f, 0x80, 0x0b, 0xf5, 0x02, 0x80, 0x7c, 0x50, 0xaf, 0x80, 0x3c, 0x83, 0x86, +0xf1, 0x09, 0xf0, 0x07, 0xb6, 0x20, 0x44, 0x00, 0x00, 0x3f, 0xf2, 0x08, 0x84, 0x21, 0xb6, 0x02, +0x00, 0x05, 0x00, 0x00, 0x4c, 0x90, 0xc0, 0x09, 0x40, 0x10, 0x20, 0x08, 0xf2, 0x04, 0x40, 0x00, +0x80, 0x04, 0xb6, 0x02, 0xd5, 0x0b, 0xf2, 0x04, 0x40, 0x00, 0x40, 0x08, 0x46, 0x10, 0x04, 0x12, +0xb6, 0x02, 0x44, 0x00, 0x00, 0x60, 0x14, 0x00, 0x83, 0x04, 0x84, 0x01, 0xb6, 0x03, 0xf3, 0x83, +0xf5, 0x82, 0x49, 0xff, 0xf4, 0x37, 0xf3, 0x03, 0x46, 0x00, 0x04, 0x12, 0x84, 0x20, 0xb6, 0x23, +0x14, 0x10, 0x02, 0x4d, 0x80, 0x40, 0xf1, 0x0c, 0x14, 0x10, 0x02, 0x4d, 0x84, 0x00, 0x14, 0x01, +0x02, 0x60, 0x84, 0x21, 0xf5, 0x02, 0x4c, 0x90, 0xc0, 0x07, 0x46, 0x0c, 0x00, 0x10, 0x58, 0x00, +0x00, 0x06, 0xd5, 0x05, 0x46, 0x0c, 0x00, 0x20, 0x58, 0x00, 0x00, 0x0c, 0x84, 0x20, 0x14, 0x01, +0x02, 0x60, 0x80, 0xc1, 0xd5, 0x0f, 0x44, 0x10, 0x00, 0x65, 0x4c, 0x60, 0x80, 0x11, 0xf3, 0x83, +0xf5, 0x82, 0x97, 0x91, 0x49, 0xff, 0xf4, 0x0e, 0x04, 0x13, 0x82, 0x7f, 0xf3, 0x03, 0xf5, 0x02, +0xd5, 0x02, 0x80, 0xe2, 0x96, 0x4c, 0x9c, 0xb1, 0x84, 0x0a, 0xc1, 0xee, 0x84, 0x41, 0x4c, 0x91, +0x40, 0x0b, 0x46, 0x10, 0x04, 0x12, 0x46, 0x0c, 0x00, 0x10, 0x58, 0x10, 0x89, 0x80, 0x58, 0x00, +0x00, 0x06, 0xd5, 0x09, 0x46, 0x10, 0x04, 0x12, 0x46, 0x0c, 0x00, 0x20, 0x58, 0x10, 0x89, 0x80, +0x58, 0x00, 0x00, 0x0c, 0xb6, 0x01, 0x46, 0x00, 0x04, 0x12, 0x04, 0x00, 0x02, 0x61, 0x8d, 0x41, +0x40, 0x20, 0x70, 0x06, 0x40, 0x12, 0x80, 0x06, 0x40, 0x50, 0x04, 0x1b, 0x41, 0xc0, 0x08, 0x1b, +0xf0, 0x01, 0x4c, 0xa0, 0x7f, 0x87, 0x44, 0x20, 0xff, 0xfd, 0x04, 0x9f, 0x80, 0x0d, 0x80, 0xdc, +0xe2, 0x5c, 0xe9, 0x06, 0x5c, 0xf2, 0xb0, 0x00, 0xe8, 0x0d, 0x8d, 0x21, 0xd5, 0x02, 0x8f, 0x21, +0xf2, 0x05, 0x9c, 0x51, 0x96, 0x49, 0xf1, 0x85, 0xf3, 0x05, 0xf0, 0x0a, 0xe2, 0x60, 0x4e, 0xf3, +0xff, 0x49, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xfe, 0xa7, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, +0xf3, 0xc1, 0x84, 0x00, 0xa8, 0x34, 0xec, 0x44, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x83, 0x80, +0x3e, 0x09, 0x5f, 0x90, 0x49, 0xff, 0xbd, 0x14, 0x46, 0x10, 0x04, 0x10, 0x04, 0x00, 0x80, 0x20, +0x58, 0x00, 0x02, 0x00, 0x14, 0x00, 0x80, 0x20, 0x2e, 0x61, 0x8a, 0x7b, 0xce, 0x40, 0x46, 0x20, +0x04, 0xf0, 0x04, 0x01, 0x00, 0x0c, 0x46, 0x10, 0x04, 0x0d, 0x58, 0x00, 0x00, 0x01, 0x14, 0x01, +0x00, 0x0c, 0xb4, 0x01, 0x81, 0x21, 0x46, 0xa2, 0x01, 0xe8, 0x80, 0x41, 0x46, 0x87, 0x00, 0x04, +0x80, 0xa1, 0x46, 0x77, 0xf0, 0x30, 0x46, 0x47, 0x11, 0x14, 0x80, 0x61, 0x42, 0x00, 0x70, 0x08, +0x58, 0x84, 0x00, 0x01, 0x58, 0x73, 0x80, 0x7f, 0x58, 0xa5, 0x08, 0x5d, 0x58, 0x42, 0x00, 0x01, +0xb6, 0x01, 0x14, 0xa4, 0x80, 0x02, 0x14, 0x81, 0x00, 0x06, 0xa9, 0xe9, 0xa9, 0x16, 0xa9, 0x9b, +0x81, 0x01, 0xb4, 0x01, 0x42, 0x00, 0x4c, 0x08, 0xb6, 0x01, 0xb4, 0x21, 0xd5, 0x08, 0x44, 0x50, +0x00, 0x65, 0xd6, 0x0a, 0x97, 0x91, 0x49, 0xff, 0xf3, 0x6d, 0xb4, 0x28, 0x92, 0x30, 0x96, 0x4c, +0x9c, 0xb1, 0x84, 0x0a, 0xc9, 0xf5, 0x84, 0x21, 0x3e, 0x11, 0x8a, 0x7b, 0x46, 0x10, 0x04, 0x0d, +0xb4, 0x21, 0x3e, 0x09, 0x5f, 0x9c, 0x54, 0x10, 0x80, 0x7f, 0xb6, 0x3c, 0x49, 0xff, 0xbc, 0xc0, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x0c, +0x62, 0xb5, 0x4e, 0x06, 0x00, 0x08, 0x3e, 0x09, 0x5f, 0xb4, 0x49, 0xff, 0xbc, 0xb1, 0x92, 0x00, +0xd5, 0x16, 0x9e, 0x41, 0x94, 0x4a, 0x3e, 0x39, 0xd0, 0xfc, 0x3e, 0x59, 0xd0, 0x7c, 0x98, 0x8b, +0x98, 0x4d, 0x0c, 0x30, 0xff, 0xff, 0x46, 0x50, 0x04, 0x10, 0x0c, 0x41, 0x7f, 0xff, 0x98, 0xdd, +0x9e, 0x01, 0xb6, 0x83, 0x4e, 0x06, 0xff, 0xf7, 0x3c, 0x0e, 0x62, 0xb5, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3c, 0x1c, 0x62, 0xb5, 0x3e, 0x39, +0xd0, 0x7c, 0x38, 0x01, 0x86, 0x0a, 0x46, 0x30, 0x04, 0x10, 0x98, 0x03, 0xb4, 0x80, 0x3e, 0x39, +0xd0, 0xfc, 0x9c, 0x09, 0x38, 0x41, 0x86, 0x0a, 0x3c, 0x0e, 0x62, 0xb5, 0x5e, 0xf0, 0x00, 0x21, +0xe9, 0x06, 0x3e, 0x09, 0x5f, 0xcc, 0x49, 0xff, 0xbc, 0x7b, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x96, 0x04, 0x40, 0x00, 0x40, 0x08, +0x54, 0x40, 0x8f, 0xff, 0x46, 0x30, 0x04, 0x10, 0x40, 0x70, 0x10, 0x04, 0x58, 0x31, 0x85, 0x28, +0x84, 0x00, 0xb4, 0xc3, 0x84, 0x81, 0x42, 0x63, 0x34, 0x0b, 0x4c, 0x62, 0x00, 0x18, 0xb6, 0xe3, +0x84, 0x80, 0xb4, 0xa3, 0x9d, 0x21, 0x42, 0x62, 0xb4, 0x0b, 0xce, 0x05, 0x54, 0x52, 0x8f, 0xff, +0xd1, 0x06, 0xd5, 0x0c, 0x44, 0x50, 0x00, 0x64, 0xdc, 0xf5, 0xd5, 0x07, 0x46, 0x00, 0x04, 0x10, +0x04, 0x00, 0x01, 0x4b, 0xb6, 0x02, 0xd5, 0x0e, 0x84, 0xc1, 0x9c, 0x01, 0x44, 0x40, 0x00, 0x64, +0x4c, 0x02, 0x7f, 0xe1, 0x84, 0xa1, 0xde, 0x06, 0x3e, 0x09, 0x5f, 0xe8, 0x49, 0xff, 0xbc, 0x40, +0x92, 0x00, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x84, 0xe0, 0x54, 0xa0, 0x00, 0xff, 0x55, 0xc0, 0x80, 0xff, 0x50, 0x6f, 0x80, 0x04, +0x44, 0x10, 0x01, 0x30, 0x80, 0x07, 0x80, 0x46, 0x49, 0xff, 0xff, 0xb6, 0xf0, 0x01, 0x84, 0x61, +0x42, 0x00, 0x48, 0x09, 0x42, 0x00, 0x4c, 0x09, 0x4d, 0xc1, 0xc0, 0x05, 0x42, 0x00, 0x48, 0x08, +0xd5, 0x03, 0x42, 0x00, 0x4c, 0x08, 0xf0, 0x81, 0x44, 0x10, 0x01, 0x30, 0xf2, 0x01, 0x80, 0x07, +0x3e, 0x99, 0x79, 0xae, 0x49, 0xff, 0xf2, 0xbe, 0x50, 0x84, 0x80, 0x22, 0x02, 0x04, 0x80, 0x00, +0xe3, 0x40, 0xe9, 0x2a, 0x02, 0x04, 0x80, 0x01, 0xe2, 0x0a, 0xe9, 0x26, 0x44, 0x10, 0x00, 0x58, +0x80, 0x46, 0x80, 0x07, 0x49, 0xff, 0xff, 0x90, 0xf0, 0x01, 0x46, 0x1f, 0x8f, 0xff, 0x58, 0x10, +0x8f, 0xff, 0x84, 0x61, 0x40, 0x00, 0x04, 0x02, 0x4d, 0xc1, 0xc0, 0x05, 0x00, 0x14, 0x00, 0x00, +0xd5, 0x08, 0x4f, 0xc3, 0x00, 0x05, 0x04, 0x14, 0x7f, 0xff, 0xd5, 0x03, 0x00, 0x14, 0x00, 0x01, +0x40, 0x10, 0xe0, 0x08, 0x40, 0x00, 0x80, 0x04, 0xf0, 0x81, 0x44, 0x10, 0x00, 0x58, 0xf2, 0x01, +0x80, 0x07, 0x49, 0xff, 0xf2, 0x8f, 0x50, 0x84, 0x00, 0x34, 0x3e, 0x59, 0x7b, 0x3c, 0x50, 0x94, +0x80, 0x34, 0x4c, 0x82, 0xff, 0xcd, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xab, 0xe7, 0x4f, 0xe8, 0x0a, +0x2e, 0x51, 0x8a, 0x73, 0x84, 0x61, 0xd3, 0x04, 0x2e, 0x51, 0x8a, 0x6c, 0xdb, 0x0e, 0x84, 0x00, +0xd5, 0x09, 0x2e, 0x51, 0x8a, 0x72, 0x84, 0x21, 0xd1, 0x04, 0x2e, 0x51, 0x8a, 0x6d, 0xd9, 0x05, +0x84, 0x01, 0x49, 0xff, 0xf9, 0xd3, 0x92, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x54, 0x80, 0x00, 0xff, 0x96, 0xc8, 0x96, 0x90, 0xe7, 0x0b, +0xe9, 0x08, 0x80, 0x28, 0x3e, 0x09, 0x5f, 0xfc, 0x49, 0xff, 0xbb, 0xb2, 0x48, 0x00, 0x00, 0xf2, +0xe7, 0x03, 0xe8, 0x15, 0x84, 0xa2, 0x4c, 0x82, 0xc0, 0x07, 0x2e, 0x01, 0xdf, 0xf0, 0x84, 0xa1, +0x4c, 0x02, 0x80, 0xe8, 0xca, 0x0c, 0x44, 0x10, 0x00, 0xe0, 0x42, 0x84, 0x04, 0x24, 0x3e, 0x39, +0xde, 0x30, 0x89, 0x03, 0x10, 0x24, 0x00, 0x00, 0x48, 0x00, 0x00, 0xdc, 0x44, 0xa0, 0x00, 0xe0, +0x42, 0xa4, 0x28, 0x24, 0x3e, 0x79, 0xde, 0x30, 0x40, 0x65, 0x1c, 0x00, 0x50, 0x63, 0x00, 0x88, +0x84, 0x81, 0x10, 0x43, 0x7f, 0x78, 0x50, 0x9f, 0x80, 0x04, 0x10, 0x33, 0x7f, 0x79, 0x46, 0x70, +0x00, 0x89, 0x58, 0x73, 0x80, 0x64, 0x44, 0x10, 0x02, 0x4c, 0x80, 0x49, 0x84, 0x00, 0xdd, 0x27, +0x05, 0xcf, 0x80, 0x01, 0x44, 0x10, 0x02, 0x50, 0x15, 0xc3, 0x7f, 0xeb, 0x80, 0x49, 0x84, 0x00, +0xdd, 0x27, 0xf3, 0x01, 0x44, 0x10, 0x02, 0x64, 0x14, 0x33, 0x7f, 0xec, 0x80, 0x49, 0x84, 0x00, +0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x44, 0x10, 0x02, 0x78, 0x15, 0xc3, 0x7f, 0xed, 0x80, 0x49, +0x84, 0x00, 0xdd, 0x27, 0xf3, 0x01, 0x44, 0x10, 0x02, 0x4c, 0x14, 0x33, 0x7f, 0xee, 0x80, 0x49, +0x84, 0x01, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x44, 0x10, 0x02, 0x50, 0x15, 0xc3, 0x7f, 0xef, +0x80, 0x49, 0x84, 0x01, 0xdd, 0x27, 0xf3, 0x01, 0x44, 0x10, 0x02, 0x64, 0x14, 0x33, 0x7f, 0xf0, +0x80, 0x49, 0x84, 0x01, 0xdd, 0x27, 0x05, 0xcf, 0x80, 0x01, 0x80, 0x49, 0x15, 0xc3, 0x7f, 0xf1, +0x44, 0x10, 0x02, 0x78, 0x84, 0x01, 0xdd, 0x27, 0xf1, 0x01, 0x46, 0x00, 0x04, 0x12, 0x14, 0x13, +0x7f, 0xf2, 0x04, 0x10, 0x01, 0xdd, 0x46, 0x20, 0x0f, 0xf0, 0x40, 0x10, 0x88, 0x02, 0x14, 0x13, +0x7f, 0xf3, 0x04, 0x10, 0x01, 0xe6, 0xb6, 0x26, 0x04, 0x10, 0x01, 0xe7, 0xa8, 0x71, 0x04, 0x10, +0x01, 0xe8, 0xa8, 0x72, 0x04, 0x10, 0x01, 0xe9, 0xa8, 0x73, 0x04, 0x10, 0x01, 0xf0, 0xa8, 0x74, +0x04, 0x10, 0x01, 0xf1, 0xa8, 0x75, 0x04, 0x10, 0x01, 0xf2, 0xa8, 0x76, 0x04, 0x00, 0x01, 0xf3, +0x50, 0xa5, 0x00, 0xa8, 0x46, 0x50, 0x04, 0x12, 0x80, 0x85, 0x80, 0x64, 0x80, 0x43, 0x80, 0x22, +0x3e, 0x79, 0xde, 0x30, 0xa8, 0x37, 0x40, 0x65, 0x1c, 0x00, 0x84, 0x00, 0x14, 0x02, 0x83, 0x14, +0x9c, 0x01, 0x04, 0xa2, 0x03, 0x18, 0x04, 0x91, 0x83, 0x19, 0x05, 0xc1, 0x03, 0x1c, 0x04, 0x70, +0x83, 0x1d, 0x55, 0xce, 0x00, 0x7f, 0x41, 0xce, 0x20, 0x08, 0x54, 0x73, 0x80, 0x7f, 0x40, 0x7e, +0x1c, 0x04, 0x47, 0xc7, 0xf0, 0x00, 0x40, 0xa5, 0x40, 0x08, 0x40, 0xa5, 0x70, 0x02, 0x40, 0x73, +0xa8, 0x04, 0x46, 0xa0, 0x07, 0xf0, 0x40, 0x94, 0xa0, 0x08, 0x40, 0x94, 0xa8, 0x02, 0x40, 0x73, +0xa4, 0x04, 0x87, 0x84, 0xab, 0xf1, 0x4c, 0x0e, 0x7f, 0xdb, 0x80, 0x01, 0x44, 0x10, 0x00, 0xe0, +0x42, 0x14, 0x04, 0x24, 0x04, 0x00, 0x02, 0x06, 0x3e, 0x29, 0xde, 0x30, 0x98, 0x4a, 0x50, 0x10, +0x80, 0xb8, 0xb6, 0x01, 0x80, 0x03, 0x04, 0x20, 0x02, 0x07, 0xa8, 0x89, 0x04, 0x20, 0x02, 0x08, +0xa8, 0x8a, 0x04, 0x20, 0x02, 0x09, 0xa8, 0x8b, 0x04, 0x20, 0x02, 0x0a, 0xa8, 0x8c, 0x04, 0x20, +0x02, 0x0b, 0xa8, 0x8d, 0x04, 0x20, 0x01, 0xcf, 0xa8, 0x8e, 0x04, 0x20, 0x03, 0x04, 0xa8, 0x8f, +0x04, 0x20, 0x03, 0x05, 0x14, 0x20, 0x80, 0x08, 0x04, 0x00, 0x02, 0x05, 0x14, 0x00, 0x80, 0x09, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x84, 0x00, +0xf0, 0x81, 0x3e, 0x69, 0x7b, 0x18, 0xa6, 0xf0, 0x84, 0xa9, 0x3e, 0x09, 0x60, 0x10, 0x80, 0x23, +0xdb, 0x0e, 0x02, 0x83, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x01, 0x80, 0x28, 0x80, 0x4a, 0x84, 0x00, +0x49, 0xff, 0xf1, 0x50, 0x80, 0x28, 0x80, 0x4a, 0x84, 0x01, 0xd5, 0x06, 0xe6, 0x62, 0xe8, 0x07, +0xa4, 0x71, 0xa0, 0xb1, 0x80, 0x03, 0x49, 0xff, 0xf1, 0x45, 0xd5, 0x03, 0x49, 0xff, 0xba, 0x98, +0x8c, 0xc8, 0x3e, 0x59, 0x7b, 0x30, 0xde, 0xe0, 0x50, 0x8f, 0x80, 0x04, 0x80, 0x48, 0x44, 0x10, +0x00, 0x34, 0x84, 0x00, 0x49, 0xff, 0xfe, 0x18, 0xf2, 0x01, 0x44, 0x10, 0x00, 0x34, 0x58, 0x21, +0x00, 0x01, 0x84, 0x00, 0x49, 0xff, 0xf1, 0x2e, 0x80, 0x48, 0x44, 0x10, 0x00, 0x34, 0x84, 0x01, +0x49, 0xff, 0xfe, 0x0a, 0xf2, 0x01, 0x84, 0x01, 0x40, 0x21, 0x00, 0x04, 0x44, 0x10, 0x00, 0x34, +0x49, 0xff, 0xf1, 0x20, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xf4, 0x97, 0x80, 0x84, 0x60, 0x50, 0x2f, 0x80, 0x04, 0x80, 0x06, 0x80, 0xe1, 0xf3, 0x81, +0x49, 0xff, 0xfd, 0xf2, 0x3c, 0x2c, 0x62, 0xb6, 0x3e, 0x09, 0xcf, 0x5c, 0x38, 0x60, 0x08, 0x08, +0xf1, 0x01, 0x3e, 0x09, 0xcf, 0x7c, 0x9d, 0x11, 0x38, 0x70, 0x0a, 0x0a, 0x3e, 0x09, 0xcf, 0xfc, +0x38, 0x10, 0x0a, 0x0a, 0x3c, 0x4e, 0x62, 0xb6, 0x5e, 0xf2, 0x00, 0x21, 0xe9, 0x05, 0x3e, 0x09, +0x60, 0x2c, 0x49, 0xff, 0xba, 0x4d, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x97, 0xc0, 0x84, 0x00, 0x3e, 0x01, 0x8a, 0x7a, 0x3e, 0x01, +0x8a, 0x78, 0x3e, 0x01, 0x8a, 0x79, 0x84, 0x01, 0x54, 0xa0, 0x80, 0xff, 0x4c, 0x70, 0x40, 0x09, +0x2e, 0x61, 0x8a, 0x72, 0x4c, 0x63, 0xc0, 0x12, 0x3e, 0x09, 0x60, 0x48, 0xd5, 0x08, 0xcf, 0x0d, +0x2e, 0x61, 0x8a, 0x73, 0x84, 0xa1, 0xde, 0x09, 0x3e, 0x09, 0x60, 0x6c, 0x49, 0xff, 0xba, 0x28, +0x3e, 0x61, 0x8a, 0x77, 0x48, 0x00, 0x01, 0x45, 0x84, 0x20, 0x3e, 0x11, 0x8a, 0x77, 0xcf, 0x67, +0x46, 0x90, 0x00, 0x89, 0x58, 0x94, 0x84, 0x6c, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x06, 0xa0, +0x50, 0x6f, 0x80, 0x04, 0x47, 0xc0, 0x00, 0x89, 0x59, 0xce, 0x00, 0x64, 0x80, 0x07, 0x84, 0x20, +0xdd, 0x29, 0x46, 0x28, 0x00, 0x56, 0x58, 0x21, 0x0e, 0x53, 0x80, 0x07, 0x84, 0x20, 0xdd, 0x28, +0x80, 0x07, 0x84, 0x24, 0xdd, 0x29, 0x44, 0x24, 0x01, 0x2c, 0x80, 0x07, 0x84, 0x24, 0xdd, 0x28, +0x80, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0x46, 0x23, 0x00, 0x70, 0x58, 0x21, 0x00, 0x06, +0x80, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x29, +0x44, 0x21, 0x01, 0x03, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, +0x01, 0x14, 0xdd, 0x29, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x80, 0x07, 0x44, 0x10, +0x01, 0x14, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x29, 0x46, 0x20, 0xa8, 0x90, +0x58, 0x21, 0x03, 0xbc, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x29, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x80, 0x46, 0xdd, 0x3c, 0xf3, 0x01, +0x44, 0x10, 0x80, 0x80, 0x40, 0x31, 0x84, 0x04, 0xf3, 0x81, 0x80, 0x07, 0x80, 0x43, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x28, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xaa, 0xd5, 0x67, 0x84, 0xe0, 0x46, 0x90, +0x00, 0x89, 0x58, 0x94, 0x84, 0x6c, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x06, 0xa0, 0x50, 0x6f, +0x80, 0x04, 0x47, 0xc0, 0x00, 0x89, 0x59, 0xce, 0x00, 0x64, 0x80, 0x07, 0x84, 0x20, 0xdd, 0x29, +0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0e, 0x57, 0x80, 0x07, 0x84, 0x20, 0xdd, 0x28, 0x80, 0x07, +0x84, 0x24, 0xdd, 0x29, 0x44, 0x24, 0x01, 0x23, 0x80, 0x07, 0x84, 0x24, 0xdd, 0x28, 0x80, 0x07, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0x46, 0x23, 0x00, 0x70, 0x58, 0x21, 0x00, 0x06, 0x80, 0x07, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x29, 0x44, 0x21, +0x01, 0x03, 0x80, 0x07, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x01, 0x14, +0xdd, 0x29, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x80, 0x07, 0x44, 0x10, 0x01, 0x14, +0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x29, 0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, +0x03, 0xbc, 0x80, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, +0xdd, 0x29, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x80, 0x46, 0xdd, 0x3c, 0xf3, 0x01, 0x44, 0x10, +0x80, 0x80, 0x40, 0x31, 0x84, 0x04, 0xf3, 0x81, 0x80, 0x07, 0x80, 0x43, 0x44, 0x10, 0x02, 0x10, +0xdd, 0x28, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xaa, 0x44, 0x00, 0x27, 0x14, 0x49, 0xff, 0xfc, 0xbc, +0x46, 0x70, 0x04, 0x12, 0x46, 0x00, 0x04, 0x12, 0x46, 0x50, 0x00, 0x8a, 0x80, 0x87, 0x80, 0x44, +0x46, 0x38, 0x00, 0x00, 0x58, 0x00, 0x00, 0x88, 0x58, 0x52, 0x8c, 0x50, 0x84, 0xc0, 0x44, 0x10, +0x00, 0x83, 0xa9, 0xbc, 0xb6, 0xa0, 0x14, 0x12, 0x01, 0xc5, 0x14, 0x31, 0x01, 0xc6, 0x80, 0xe0, +0xb4, 0x47, 0x84, 0x0a, 0x54, 0x11, 0x00, 0x10, 0xf2, 0x81, 0xc1, 0x08, 0x49, 0xff, 0xef, 0xca, +0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf5, 0xd5, 0x04, 0x5c, 0xf3, 0x00, 0x64, 0xe9, 0x0c, +0x80, 0x26, 0x3e, 0x09, 0x5c, 0xec, 0x49, 0xff, 0xb9, 0x23, 0x84, 0x20, 0x3c, 0x18, 0xe7, 0x55, +0x3c, 0x18, 0xe7, 0x54, 0xd5, 0x39, 0x46, 0x00, 0x04, 0x12, 0x04, 0x30, 0x00, 0x23, 0x4e, 0xa3, +0x00, 0x07, 0x40, 0x21, 0xc0, 0x09, 0x96, 0x90, 0x96, 0x58, 0xd5, 0x06, 0x40, 0x11, 0xa0, 0x09, +0x96, 0x48, 0x40, 0x21, 0xe0, 0x09, 0x3c, 0x18, 0xe7, 0x54, 0x3c, 0x28, 0xe7, 0x55, 0x3c, 0x14, +0xe7, 0x54, 0x5e, 0xf0, 0x80, 0x80, 0xe9, 0x05, 0x50, 0x10, 0xff, 0x00, 0x3c, 0x18, 0xe7, 0x54, +0x3c, 0x14, 0xe7, 0x55, 0x5e, 0xf0, 0x80, 0x80, 0xe9, 0x05, 0x50, 0x10, 0xff, 0x00, 0x3c, 0x18, +0xe7, 0x55, 0x46, 0x10, 0x04, 0x12, 0x84, 0x40, 0x80, 0x01, 0x14, 0x20, 0x81, 0xc6, 0x84, 0x21, +0xa8, 0x44, 0xa8, 0x84, 0x3c, 0x24, 0xe7, 0x55, 0x3c, 0x14, 0xe7, 0x54, 0x3e, 0x09, 0x5c, 0xf4, +0xf3, 0x81, 0x49, 0xff, 0xb8, 0xe5, 0x49, 0xff, 0xef, 0xab, 0x49, 0xff, 0xfc, 0x27, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xa4, 0x96, 0x00, +0xf0, 0x85, 0x46, 0x20, 0x04, 0x12, 0xf4, 0x05, 0x84, 0x00, 0x96, 0x48, 0x58, 0x21, 0x0c, 0x04, +0x84, 0x64, 0x58, 0x42, 0x00, 0x80, 0xf0, 0x8a, 0xf1, 0x8b, 0xf2, 0x90, 0xf3, 0x89, 0xf0, 0x8d, +0xf0, 0x8e, 0xf0, 0x8f, 0xf0, 0x88, 0xf0, 0x86, 0xf4, 0x93, 0xf0, 0x0b, 0x46, 0x90, 0x00, 0x87, +0x58, 0x94, 0x86, 0xa0, 0x4e, 0x02, 0x00, 0x87, 0xf0, 0x05, 0x84, 0x20, 0x49, 0xff, 0xfe, 0x48, +0xf0, 0x05, 0x46, 0x28, 0x00, 0x56, 0x58, 0x21, 0x07, 0x57, 0x84, 0x20, 0xdd, 0x29, 0xf0, 0x05, +0x44, 0x10, 0x00, 0x10, 0x49, 0xff, 0xfe, 0x3c, 0xf0, 0x05, 0x46, 0x23, 0x0d, 0x70, 0x58, 0x21, +0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, +0xfe, 0x2f, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x80, 0xdd, 0x29, 0xf0, 0x05, +0x44, 0x21, 0x01, 0x40, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x00, 0x58, +0x49, 0xff, 0xfe, 0x1e, 0xf0, 0x05, 0x44, 0x10, 0x00, 0x54, 0x49, 0xff, 0xfe, 0x19, 0xf0, 0x05, +0x46, 0x26, 0x57, 0xc0, 0x44, 0x10, 0x00, 0x58, 0xdd, 0x29, 0xf0, 0x05, 0x46, 0x20, 0x15, 0xac, +0x58, 0x21, 0x0a, 0x00, 0x44, 0x10, 0x00, 0x54, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x10, +0x49, 0xff, 0xfe, 0x06, 0x2e, 0x61, 0x8a, 0x72, 0xf0, 0x05, 0x56, 0x63, 0x00, 0x01, 0x85, 0x06, +0x84, 0xec, 0x40, 0x23, 0x98, 0x1a, 0x40, 0x24, 0x18, 0x1b, 0x44, 0x10, 0x01, 0x14, 0xf2, 0x8c, +0x46, 0x70, 0x04, 0x10, 0x49, 0xff, 0xfd, 0xf4, 0xf0, 0x05, 0x46, 0x20, 0x0c, 0x21, 0x58, 0x21, +0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x84, 0xc8, 0xdd, 0x29, 0x14, 0x63, 0x81, 0x48, 0x94, 0x76, +0xf0, 0x05, 0x84, 0xe0, 0x49, 0xff, 0xfd, 0xe4, 0xf0, 0x05, 0x46, 0x20, 0x50, 0x00, 0x58, 0x21, +0x01, 0x0f, 0x94, 0x76, 0xdd, 0x29, 0xf0, 0x05, 0x94, 0x76, 0x50, 0x2f, 0x80, 0x50, 0x49, 0xff, +0xfb, 0xd3, 0xf1, 0x14, 0x9d, 0xf9, 0x54, 0x10, 0x81, 0x00, 0x97, 0xf9, 0x84, 0x05, 0x4e, 0x12, +0x00, 0x8c, 0x49, 0xff, 0xee, 0xd7, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x70, 0x7f, 0xee, 0x48, 0x00, +0x00, 0x84, 0xf0, 0x05, 0xf1, 0x0b, 0x49, 0xff, 0xfd, 0xc3, 0xf1, 0x0b, 0xf0, 0x05, 0x46, 0x2a, +0x00, 0x56, 0x58, 0x21, 0x0f, 0x53, 0xdd, 0x29, 0xf0, 0x05, 0x84, 0x24, 0x49, 0xff, 0xfd, 0xb8, +0xf0, 0x05, 0x44, 0x24, 0x01, 0x2c, 0x84, 0x24, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x00, 0x10, +0x49, 0xff, 0xfd, 0xae, 0xf0, 0x05, 0x46, 0x23, 0x0d, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, +0x00, 0x10, 0xdd, 0x29, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xfd, 0xa1, 0xf0, 0x05, +0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xfd, 0x9c, 0x2e, 0x61, 0x8a, 0x73, 0x84, 0x81, 0x4c, 0x62, +0x40, 0x0b, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x30, 0xdd, 0x29, 0x84, 0x0d, +0xf0, 0x8c, 0xd5, 0x09, 0xf0, 0x05, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x70, 0xdd, 0x29, +0x84, 0x26, 0xf1, 0x8c, 0xf0, 0x05, 0x44, 0x10, 0x01, 0x14, 0x49, 0xff, 0xfd, 0x81, 0x46, 0x20, +0x0c, 0x21, 0xf0, 0x05, 0x58, 0x21, 0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x49, 0xff, 0xee, 0x92, +0xf0, 0x05, 0x44, 0x10, 0x00, 0x44, 0x49, 0xff, 0xfd, 0x73, 0x46, 0x70, 0x04, 0x10, 0xf0, 0x05, +0x46, 0x20, 0x04, 0x92, 0x58, 0x21, 0x00, 0x16, 0x44, 0x10, 0x00, 0x44, 0x84, 0xc8, 0x49, 0xff, +0xee, 0x81, 0x14, 0x63, 0x81, 0x48, 0x94, 0x76, 0xf0, 0x05, 0x84, 0xe0, 0x49, 0xff, 0xfd, 0x60, +0xf0, 0x05, 0x46, 0x20, 0x50, 0x00, 0x58, 0x21, 0x01, 0x0f, 0x94, 0x76, 0x49, 0xff, 0xee, 0x72, +0xf0, 0x05, 0x94, 0x76, 0x50, 0x2f, 0x80, 0x50, 0x49, 0xff, 0xfb, 0x4e, 0xf1, 0x14, 0x9d, 0xf9, +0x54, 0x10, 0x81, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xee, 0x53, 0x44, 0x00, +0x03, 0xe8, 0x4c, 0x70, 0x7f, 0xef, 0x46, 0x70, 0x04, 0x10, 0x84, 0xc2, 0x14, 0x63, 0x81, 0x48, +0x46, 0x80, 0x00, 0x89, 0x58, 0x84, 0x00, 0x24, 0x44, 0x00, 0x20, 0x04, 0xdd, 0x28, 0x44, 0x00, +0x27, 0x04, 0xdd, 0x28, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x28, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x28, +0x46, 0x70, 0x04, 0x12, 0x44, 0x00, 0x20, 0x88, 0xdd, 0x28, 0x44, 0x00, 0x23, 0x00, 0x44, 0x60, +0x74, 0x08, 0xdd, 0x28, 0x14, 0x63, 0x80, 0xc0, 0x44, 0x00, 0x10, 0x04, 0xdd, 0x28, 0xf1, 0x09, +0x46, 0x70, 0x04, 0x11, 0x84, 0x40, 0x9e, 0x49, 0x58, 0x73, 0x80, 0x04, 0x84, 0xc8, 0x46, 0x90, +0x04, 0x12, 0x80, 0x09, 0x81, 0x40, 0xf1, 0x91, 0x50, 0x33, 0x90, 0x0c, 0xb6, 0x47, 0x84, 0x81, +0xb6, 0xc7, 0x84, 0xc2, 0xb6, 0x47, 0x14, 0x24, 0x80, 0x01, 0x80, 0xe0, 0xb6, 0x83, 0xb6, 0x43, +0x14, 0x10, 0x03, 0x14, 0x14, 0x65, 0x00, 0x22, 0xf3, 0x84, 0xf4, 0x83, 0xf2, 0x82, 0x44, 0x00, +0x20, 0x80, 0x44, 0x63, 0x00, 0x01, 0xdd, 0x28, 0x14, 0x63, 0x80, 0x20, 0x46, 0x70, 0x04, 0x12, +0x44, 0x00, 0x20, 0x84, 0x44, 0x62, 0x00, 0x00, 0xdd, 0x28, 0x14, 0x63, 0x80, 0x21, 0x44, 0x00, +0x2c, 0xb8, 0xdd, 0x28, 0x46, 0x60, 0x04, 0x12, 0xf2, 0x02, 0x14, 0x23, 0x03, 0x2e, 0x83, 0x86, +0x84, 0x05, 0xf2, 0x82, 0x49, 0xff, 0xed, 0xee, 0x04, 0x6e, 0x03, 0x04, 0x92, 0xc3, 0x95, 0xb3, +0x46, 0xa0, 0x04, 0x12, 0x14, 0x6e, 0x03, 0x04, 0x44, 0x60, 0x0b, 0x0b, 0x14, 0x65, 0x01, 0xc1, +0x81, 0x2a, 0xf1, 0x13, 0x81, 0x09, 0x46, 0x7c, 0x00, 0x02, 0x58, 0x73, 0x81, 0x01, 0x14, 0x14, +0x81, 0xc5, 0x14, 0x74, 0x01, 0xc6, 0x44, 0x00, 0x00, 0x32, 0x49, 0xff, 0xed, 0xd3, 0xf2, 0x02, +0x46, 0x00, 0x00, 0x88, 0xf2, 0x87, 0xf2, 0x11, 0x58, 0x00, 0x00, 0x80, 0x40, 0x61, 0x40, 0x08, +0x40, 0x03, 0x00, 0x04, 0xf0, 0x92, 0x04, 0x9f, 0x80, 0x0c, 0x46, 0x30, 0x04, 0x12, 0xf1, 0x12, +0x84, 0x81, 0xf0, 0x05, 0xa9, 0x1c, 0x84, 0x80, 0xa9, 0x1c, 0x40, 0x74, 0x84, 0x04, 0x40, 0x64, +0xa0, 0x08, 0x40, 0x23, 0x98, 0x04, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xed, 0xc3, 0xf0, 0x05, +0x50, 0x2f, 0x80, 0x54, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xfa, 0x9e, 0x44, 0x00, 0x2c, 0x08, +0x49, 0xff, 0xfa, 0x7a, 0x46, 0x60, 0x04, 0x12, 0xf0, 0x05, 0x14, 0x03, 0x03, 0x02, 0x80, 0xe6, +0x84, 0x03, 0x49, 0xff, 0xed, 0x9f, 0x44, 0x60, 0x04, 0x0c, 0x44, 0x00, 0x2c, 0x14, 0x49, 0xff, +0xfa, 0x6b, 0x14, 0x63, 0x83, 0x05, 0x44, 0x00, 0x2c, 0x04, 0x49, 0xff, 0xfa, 0x65, 0xf2, 0x10, +0x44, 0x60, 0x00, 0x93, 0xb6, 0xc2, 0xf6, 0x0a, 0xd5, 0x07, 0x9d, 0xb1, 0x49, 0xff, 0xed, 0x8a, +0x5c, 0xf3, 0x00, 0xc8, 0xe8, 0x07, 0xf4, 0x10, 0x84, 0x0a, 0xb4, 0x24, 0x54, 0x10, 0x80, 0x80, +0xc9, 0xf5, 0x46, 0xa0, 0x07, 0xff, 0x58, 0xa5, 0x0f, 0xff, 0x46, 0x10, 0x04, 0x12, 0x58, 0x10, +0x8c, 0x28, 0x80, 0xaa, 0xf6, 0x8a, 0x47, 0xc3, 0xff, 0xff, 0x9e, 0x8c, 0xf7, 0x0d, 0xf6, 0x0e, +0x14, 0x9f, 0x80, 0x0c, 0x81, 0x41, 0x59, 0xce, 0x0f, 0xff, 0x85, 0x00, 0x81, 0x22, 0x80, 0x25, +0xb7, 0x09, 0xb4, 0x0a, 0xe7, 0x02, 0xe8, 0x0a, 0xe2, 0x20, 0xe8, 0x14, 0x46, 0x3f, 0xf0, 0x00, +0x40, 0x00, 0x20, 0x08, 0x92, 0x08, 0x98, 0x03, 0xd5, 0x0d, 0x84, 0x84, 0x4c, 0x82, 0x40, 0x0b, +0x40, 0xfe, 0x00, 0x06, 0xe8, 0x07, 0x46, 0x38, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x09, 0x98, 0x03, +0xd5, 0x12, 0x4e, 0x83, 0x00, 0x05, 0x90, 0x0c, 0xf0, 0x86, 0xd5, 0x14, 0x84, 0x81, 0x4c, 0x82, +0x40, 0x05, 0x90, 0x0c, 0xf0, 0x88, 0xd5, 0x0e, 0x84, 0x42, 0x4c, 0x81, 0x40, 0x05, 0x90, 0x0c, +0xf0, 0x8f, 0xd5, 0x08, 0x90, 0x0c, 0x56, 0x34, 0x00, 0x03, 0x40, 0x70, 0x0c, 0x1b, 0x40, 0x60, +0x0c, 0x1a, 0x84, 0x0a, 0xf1, 0x84, 0x8d, 0x01, 0x49, 0xff, 0xed, 0x34, 0x84, 0x85, 0xf1, 0x04, +0x4c, 0x82, 0x7f, 0xc8, 0xf6, 0x8e, 0xf0, 0x06, 0xf6, 0x0f, 0xf1, 0x06, 0x42, 0x60, 0x00, 0x75, +0xf2, 0x08, 0xf3, 0x0f, 0xf4, 0x0e, 0x3e, 0x09, 0x60, 0x90, 0x80, 0xa7, 0x04, 0x9f, 0x80, 0x0c, +0xf7, 0x8d, 0xb6, 0xdf, 0x49, 0xff, 0xb6, 0x84, 0xf1, 0x0b, 0x84, 0x41, 0x4c, 0x11, 0x00, 0x29, +0xf3, 0x09, 0x84, 0x84, 0x4c, 0x32, 0x40, 0x25, 0x5c, 0xf3, 0x2b, 0xf2, 0xe9, 0x03, 0x8f, 0x21, +0xd5, 0x0e, 0x5c, 0xf3, 0x07, 0x08, 0xe8, 0x1c, 0x5c, 0xf3, 0x01, 0xc3, 0xe8, 0x03, 0x8d, 0x25, +0xd5, 0x11, 0x5c, 0xf3, 0x02, 0xae, 0xe8, 0x03, 0x8d, 0x24, 0xd5, 0x0c, 0x5c, 0xf3, 0x04, 0x23, +0xe8, 0x03, 0x8d, 0x23, 0xd5, 0x07, 0x5c, 0xf3, 0x05, 0x49, 0xe8, 0x03, 0x8d, 0x22, 0xd5, 0x02, +0x8d, 0x21, 0xf0, 0x07, 0x84, 0x26, 0x9c, 0x01, 0xf0, 0x87, 0x4c, 0x00, 0xff, 0x30, 0xf2, 0x06, +0xf6, 0x0f, 0x45, 0xc0, 0x00, 0x64, 0x42, 0x61, 0x08, 0x75, 0x42, 0x03, 0x70, 0x24, 0x49, 0xff, +0xee, 0x43, 0xf6, 0x0e, 0xf3, 0x08, 0x80, 0x40, 0x42, 0x61, 0x8c, 0x75, 0xf2, 0x82, 0x42, 0x03, +0x70, 0x24, 0x49, 0xff, 0xee, 0x39, 0x81, 0x40, 0xf2, 0x02, 0xc0, 0x2a, 0xc2, 0x29, 0x44, 0x60, +0x03, 0xe8, 0x42, 0x60, 0x18, 0x24, 0xf4, 0x08, 0x40, 0x63, 0x09, 0x36, 0xf0, 0x06, 0xf7, 0x0d, +0x85, 0x0a, 0x42, 0x72, 0x00, 0x75, 0x43, 0xc5, 0x08, 0x24, 0x42, 0x83, 0xa0, 0x24, 0x44, 0x70, +0x11, 0xe8, 0x42, 0x84, 0x1c, 0x24, 0xf1, 0x11, 0x3e, 0x09, 0x60, 0xd0, 0x50, 0x73, 0x7c, 0x18, +0x40, 0x93, 0xa4, 0x08, 0x50, 0x63, 0x03, 0xe8, 0x40, 0x24, 0x99, 0x56, 0x40, 0x74, 0x71, 0x16, +0x80, 0x62, 0xf2, 0x87, 0x80, 0x87, 0x80, 0xa7, 0x49, 0xff, 0xb6, 0x1a, 0xd5, 0x03, 0x84, 0xe0, +0xf7, 0x87, 0xf3, 0x07, 0xf4, 0x05, 0x55, 0xe3, 0x80, 0x7f, 0x54, 0x01, 0x80, 0x7f, 0xcc, 0x0a, +0x47, 0xc0, 0x04, 0x12, 0x41, 0xef, 0x20, 0x08, 0x59, 0xce, 0x0c, 0x60, 0x50, 0xae, 0x00, 0x10, +0xd5, 0x09, 0x47, 0xc0, 0x04, 0x12, 0x41, 0xef, 0x20, 0x08, 0x59, 0xce, 0x0c, 0x64, 0x50, 0xae, +0x00, 0x10, 0x15, 0xee, 0x00, 0x00, 0x46, 0x90, 0x04, 0x12, 0xb6, 0x0a, 0x04, 0x64, 0x83, 0x04, +0x58, 0x63, 0x00, 0x07, 0x14, 0x64, 0x83, 0x04, 0xf0, 0x0b, 0xc8, 0x20, 0xf1, 0x07, 0x84, 0x44, +0x54, 0x83, 0x80, 0x7f, 0x80, 0x09, 0x80, 0xe0, 0x81, 0x40, 0x83, 0xc0, 0x83, 0x80, 0xf2, 0x89, +0x54, 0x60, 0x80, 0x7f, 0x40, 0x84, 0x20, 0x08, 0x80, 0x22, 0x9e, 0x49, 0x14, 0x10, 0x03, 0x14, +0xf3, 0x05, 0xcb, 0x06, 0x14, 0x8f, 0x03, 0x18, 0x14, 0x6e, 0x03, 0x1c, 0xd5, 0x05, 0x14, 0x83, +0x83, 0x19, 0x14, 0x65, 0x03, 0x1d, 0xc9, 0xf2, 0xf1, 0x89, 0x80, 0xc9, 0x85, 0x20, 0x14, 0x93, +0x01, 0xc6, 0x46, 0x70, 0x04, 0x11, 0x58, 0x73, 0x80, 0x04, 0x49, 0xff, 0xec, 0x91, 0x84, 0xc8, +0x49, 0xff, 0xf9, 0x0c, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, 0xf9, 0x2e, 0x92, 0x00, 0xb7, 0x27, +0xb6, 0xc7, 0xb7, 0x27, 0x46, 0xa0, 0x04, 0x12, 0x49, 0xff, 0xf9, 0x00, 0x46, 0x70, 0x04, 0x12, +0x81, 0x07, 0x84, 0x01, 0x14, 0x94, 0x03, 0x24, 0x14, 0x93, 0x83, 0x25, 0x14, 0x05, 0x00, 0x04, +0x49, 0xff, 0xec, 0x48, 0x14, 0x95, 0x00, 0x04, 0x84, 0x02, 0x49, 0xff, 0xec, 0x43, 0xf4, 0x0b, +0xc4, 0x06, 0xf0, 0x09, 0x9e, 0x01, 0xf0, 0x89, 0x4e, 0x03, 0xfc, 0xe1, 0xec, 0x5c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x97, 0x80, 0x3e, 0x09, 0x60, 0xfc, +0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x80, 0x24, 0x49, 0xff, 0xb5, 0x92, 0x44, 0x00, 0x20, 0x04, +0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x44, 0x10, 0x00, 0x42, 0xa8, 0x41, 0x46, 0x90, 0x00, 0x89, +0x58, 0x94, 0x84, 0x6c, 0x80, 0x06, 0x84, 0x20, 0xdd, 0x29, 0x46, 0x28, 0x00, 0x56, 0x46, 0x80, +0x00, 0x87, 0x58, 0x84, 0x06, 0xa0, 0x58, 0x21, 0x0f, 0x57, 0x84, 0x20, 0x80, 0x06, 0xdd, 0x28, +0x80, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x29, 0x46, 0x23, 0x04, 0xf0, 0x58, 0x21, 0x00, 0x06, +0x44, 0x10, 0x00, 0x10, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x29, +0x44, 0x21, 0x01, 0x00, 0x44, 0x10, 0x02, 0x44, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, +0x02, 0x98, 0xdd, 0x29, 0x46, 0x20, 0x30, 0x30, 0x58, 0x21, 0x03, 0x04, 0x44, 0x10, 0x02, 0x98, +0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x02, 0xa8, 0xdd, 0x29, 0x44, 0x10, 0x02, 0xa8, +0x50, 0x2f, 0x80, 0x04, 0x80, 0x06, 0x49, 0xff, 0xf8, 0xd7, 0xf2, 0x01, 0x42, 0x21, 0x60, 0x09, +0x44, 0x10, 0x02, 0xa8, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x29, +0x46, 0x20, 0x0c, 0x21, 0x58, 0x21, 0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x80, 0x06, 0xdd, 0x28, +0x80, 0x06, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x29, 0x46, 0x20, 0xab, 0x92, 0x58, 0x21, 0x03, 0xbc, +0x44, 0x10, 0x01, 0x30, 0x80, 0x06, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x29, +0x44, 0x20, 0x95, 0x95, 0x44, 0x10, 0x02, 0x10, 0x80, 0x06, 0xdd, 0x28, 0x46, 0x00, 0x04, 0x12, +0x85, 0x00, 0x84, 0x21, 0xa8, 0x44, 0x14, 0x80, 0x00, 0x04, 0x44, 0x00, 0x20, 0x88, 0xdd, 0x27, +0x46, 0x00, 0x04, 0x12, 0x84, 0x22, 0x14, 0x10, 0x00, 0x22, 0x44, 0x00, 0x23, 0x00, 0xdd, 0x27, +0x46, 0x00, 0x04, 0x12, 0x44, 0x10, 0x74, 0x08, 0x14, 0x10, 0x00, 0xc0, 0x44, 0x00, 0x10, 0x04, +0xdd, 0x27, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x00, 0x04, 0x84, 0x28, 0xb7, 0x00, 0xb6, 0x20, +0xb7, 0x00, 0x44, 0x00, 0x20, 0x80, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x44, 0x13, 0x00, 0x01, +0x14, 0x10, 0x00, 0x20, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x46, 0x1c, +0x00, 0x02, 0x58, 0x10, 0x81, 0x01, 0x14, 0x10, 0x01, 0xc6, 0x44, 0x00, 0x27, 0x3c, 0xdd, 0x27, +0x46, 0x00, 0x04, 0x12, 0x46, 0x18, 0x00, 0x00, 0x14, 0x10, 0x01, 0xcf, 0x44, 0x00, 0x27, 0x04, +0xdd, 0x27, 0x46, 0x00, 0x04, 0x12, 0x14, 0x80, 0x01, 0xc1, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x27, +0x44, 0x00, 0x29, 0x34, 0xdd, 0x27, 0x46, 0x38, 0x00, 0x00, 0x58, 0x31, 0x80, 0x12, 0x46, 0x10, +0x04, 0x12, 0x40, 0x23, 0x78, 0x08, 0x80, 0x01, 0x40, 0x21, 0x0c, 0x04, 0x58, 0x33, 0x00, 0x80, +0x14, 0x30, 0x81, 0xc5, 0x14, 0x20, 0x02, 0x4d, 0x44, 0x00, 0x29, 0x80, 0xdd, 0x27, 0x44, 0x00, +0x27, 0x00, 0xdd, 0x27, 0x46, 0x30, 0x04, 0x12, 0x46, 0x47, 0x0f, 0x20, 0x58, 0x42, 0x00, 0x06, +0x80, 0x43, 0x80, 0x02, 0x46, 0x10, 0x92, 0xf5, 0x14, 0x41, 0x82, 0x60, 0x58, 0x10, 0x89, 0x08, +0x44, 0x31, 0x00, 0x00, 0x14, 0x31, 0x01, 0xc0, 0x80, 0xe0, 0x14, 0x10, 0x01, 0xda, 0x04, 0x13, +0x81, 0xdd, 0x46, 0x20, 0x07, 0x70, 0x3e, 0x09, 0x61, 0x10, 0x40, 0x10, 0x88, 0x02, 0x49, 0xff, +0xb4, 0x9f, 0x44, 0x00, 0x03, 0xe8, 0x49, 0xff, 0xeb, 0x35, 0x04, 0x03, 0x81, 0xdd, 0x8d, 0x01, +0x54, 0x00, 0x00, 0x80, 0xc0, 0x05, 0x44, 0x50, 0x00, 0x64, 0x4c, 0x82, 0xff, 0xf4, 0x46, 0x00, +0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x14, 0x10, 0x01, 0xda, 0x04, 0x00, +0x01, 0xf4, 0xce, 0x04, 0x54, 0x10, 0x00, 0x07, 0xd5, 0x05, 0x40, 0x10, 0x10, 0x09, 0x54, 0x10, +0x80, 0x07, 0x84, 0xa7, 0xd1, 0x17, 0x9c, 0x89, 0xce, 0x0a, 0x92, 0x03, 0x94, 0x03, 0x46, 0x10, +0x04, 0x12, 0x40, 0x21, 0x00, 0x04, 0x14, 0x20, 0x81, 0xf4, 0xd5, 0x0c, 0x44, 0x1f, 0xff, 0x8f, +0x40, 0x00, 0x04, 0x02, 0x94, 0x94, 0x46, 0x10, 0x04, 0x12, 0x40, 0x01, 0x00, 0x04, 0x14, 0x00, +0x81, 0xf4, 0x49, 0xff, 0xeb, 0x2d, 0x49, 0xff, 0xf7, 0xa9, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, +0xf7, 0xcb, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x00, 0x04, 0x85, 0x00, 0x84, 0x28, 0xb7, 0x00, +0xb6, 0x20, 0xb7, 0x00, 0x46, 0x70, 0x04, 0x12, 0x49, 0xff, 0xf7, 0x98, 0x84, 0x01, 0xa8, 0x3c, +0x49, 0xff, 0xea, 0xe8, 0x14, 0x83, 0x80, 0x04, 0x46, 0x00, 0x04, 0x12, 0x04, 0x20, 0x01, 0xdd, +0x46, 0x30, 0x07, 0x70, 0x80, 0x26, 0x40, 0x21, 0x0c, 0x02, 0x3e, 0x09, 0x61, 0x2c, 0x49, 0xff, +0xb4, 0x3f, 0x92, 0x00, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xc4, 0x96, 0x00, 0x84, 0x40, 0xb6, 0x1f, 0x96, 0x48, 0x3e, 0x09, 0x61, 0x54, 0xf1, 0x84, +0xf2, 0x8b, 0xf2, 0x8d, 0xf2, 0x8c, 0x49, 0xff, 0xb4, 0x2b, 0xf0, 0x04, 0x4e, 0x03, 0x03, 0x44, +0x80, 0x20, 0xb4, 0x1f, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x04, 0x6c, 0xdd, 0x26, 0xb4, 0x1f, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xb4, 0x1f, +0x44, 0x10, 0x01, 0x38, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x01, 0x2c, 0xdd, 0x26, 0xb4, 0x1f, +0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x26, 0xb4, 0x1f, +0x44, 0x10, 0x02, 0x44, 0xdd, 0x26, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x00, 0x24, 0x44, 0x00, +0x27, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x26, +0x44, 0x00, 0x20, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x18, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x80, +0xdd, 0x26, 0xf1, 0x04, 0xf1, 0x81, 0xf2, 0x01, 0xca, 0x2f, 0xf1, 0x01, 0x46, 0x28, 0x00, 0x56, +0xb4, 0x1f, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x06, 0xa0, 0x58, 0x21, 0x0e, 0x53, 0xdd, 0x26, +0xb4, 0x1f, 0x46, 0x25, 0x40, 0x37, 0x44, 0x10, 0x01, 0x38, 0xdd, 0x26, 0xb4, 0x1f, 0x46, 0x20, +0x81, 0x00, 0x58, 0x21, 0x00, 0x1b, 0x44, 0x10, 0x01, 0x2c, 0xdd, 0x26, 0xb4, 0x1f, 0x44, 0x10, +0x02, 0x44, 0x44, 0x20, 0x01, 0xc0, 0xdd, 0x26, 0xf3, 0x01, 0x84, 0x44, 0x56, 0x41, 0x80, 0x01, +0x84, 0x65, 0x40, 0x01, 0x90, 0x1a, 0x40, 0x01, 0x10, 0x1b, 0x84, 0x20, 0xf0, 0x89, 0xf1, 0x82, +0x05, 0xcf, 0x80, 0x00, 0xd5, 0x1c, 0xf2, 0x01, 0x84, 0x61, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, +0x06, 0xa0, 0x4c, 0x21, 0xc0, 0x08, 0x46, 0x28, 0x20, 0x56, 0x58, 0x21, 0x0e, 0x53, 0xb4, 0x1f, +0xd5, 0x0c, 0xb4, 0x1f, 0x44, 0x20, 0x01, 0x00, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x26, 0x46, 0x28, +0x30, 0x56, 0xb4, 0x1f, 0x58, 0x21, 0x0e, 0x53, 0x84, 0x20, 0xd5, 0xd6, 0xf7, 0x09, 0xf0, 0x01, +0xf1, 0x02, 0x84, 0x46, 0x40, 0x71, 0x00, 0x1a, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x06, 0xa0, +0xc9, 0x1f, 0x44, 0x10, 0x00, 0x10, 0x80, 0x1c, 0xdd, 0x26, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, +0x08, 0xb1, 0x80, 0x1c, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf2, 0x01, 0xca, 0x07, 0x80, 0x1c, +0x44, 0x10, 0x02, 0x10, 0x44, 0x20, 0x88, 0x88, 0xdd, 0x26, 0x46, 0x20, 0xa8, 0x98, 0x58, 0x21, +0x03, 0xbc, 0x80, 0x1c, 0x44, 0x10, 0x01, 0x30, 0x49, 0xff, 0xea, 0x24, 0xd5, 0x11, 0x46, 0x20, +0x04, 0x21, 0x58, 0x21, 0x08, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x80, 0x1c, 0xdd, 0x26, 0x46, 0x20, +0xa8, 0x90, 0x80, 0x1c, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, 0x84, 0x61, +0x44, 0x10, 0x02, 0x4c, 0x50, 0x2f, 0x80, 0x30, 0x80, 0x1c, 0x40, 0x91, 0x9c, 0x0c, 0x49, 0xff, +0xf6, 0xeb, 0x46, 0x30, 0x04, 0x12, 0xf3, 0x87, 0xf3, 0x85, 0x44, 0x10, 0x02, 0x50, 0x80, 0x1c, +0x50, 0x2f, 0x80, 0x2c, 0x49, 0xff, 0xf6, 0xe0, 0xf0, 0x07, 0xf1, 0x05, 0x9f, 0xf9, 0x58, 0x00, +0x07, 0x04, 0x58, 0x10, 0x89, 0xfc, 0xf7, 0x83, 0xf0, 0x87, 0xf1, 0x85, 0x04, 0xaf, 0x80, 0x02, +0xd5, 0x04, 0xf2, 0x03, 0x9e, 0x91, 0xf2, 0x83, 0xf3, 0x03, 0xf0, 0x01, 0x9c, 0xd9, 0xf3, 0x88, +0xc8, 0x1c, 0x4e, 0xa3, 0x00, 0x09, 0xf2, 0x0c, 0x92, 0x47, 0x94, 0x97, 0x80, 0x1c, 0x40, 0x24, +0x88, 0x04, 0xd5, 0x0e, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0x53, 0xf2, 0x0c, 0x44, 0x0f, 0x80, 0xff, +0x40, 0x21, 0x00, 0x02, 0x40, 0x34, 0xa0, 0x08, 0x40, 0x21, 0x88, 0x04, 0x80, 0x1c, 0x44, 0x10, +0x02, 0x4c, 0x49, 0xff, 0xe9, 0xcf, 0xd5, 0x43, 0xf1, 0x01, 0x84, 0xa1, 0xd9, 0x20, 0x4e, 0xa3, +0x00, 0x0a, 0x46, 0x0f, 0xf8, 0x0f, 0x40, 0x34, 0xc0, 0x08, 0xf2, 0x0c, 0x58, 0x00, 0x0f, 0xff, +0xd5, 0x0b, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0xa1, 0x46, 0x08, 0x0f, 0xff, 0xf2, 0x0c, 0x40, 0x34, +0xe0, 0x08, 0x58, 0x00, 0x0f, 0xff, 0x40, 0x21, 0x00, 0x02, 0x40, 0x21, 0x88, 0x04, 0x80, 0x1c, +0x44, 0x10, 0x02, 0x4c, 0x49, 0xff, 0xe9, 0xae, 0x48, 0x00, 0x00, 0x8f, 0xf1, 0x01, 0x84, 0xa2, +0x4c, 0x12, 0xc0, 0x88, 0x4e, 0xa3, 0x00, 0x09, 0xf2, 0x0b, 0x92, 0x47, 0x94, 0x97, 0x80, 0x1c, +0x40, 0x24, 0x88, 0x04, 0xd5, 0x0e, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0xf2, 0xf2, 0x0b, 0x44, 0x1f, +0x80, 0xff, 0x40, 0x34, 0xa0, 0x08, 0x40, 0x21, 0x04, 0x02, 0x40, 0x21, 0x88, 0x04, 0x80, 0x1c, +0x44, 0x10, 0x02, 0x50, 0x49, 0xff, 0xe9, 0x8e, 0x48, 0x00, 0x00, 0xe2, 0x46, 0x20, 0x04, 0x12, +0x80, 0x62, 0x84, 0x00, 0xa8, 0x11, 0x44, 0x23, 0x7f, 0x7f, 0x14, 0x21, 0x83, 0x3b, 0x4e, 0xa3, +0x00, 0x07, 0x46, 0x20, 0x12, 0x07, 0x58, 0x21, 0x0f, 0x7f, 0xd5, 0x05, 0x46, 0x20, 0x12, 0xa7, +0x58, 0x21, 0x0f, 0x7f, 0x14, 0x21, 0x83, 0x3b, 0x80, 0x43, 0x46, 0x38, 0x00, 0x00, 0x14, 0x31, +0x03, 0x3a, 0x4f, 0xc3, 0x00, 0x0c, 0x80, 0x82, 0x46, 0x38, 0x00, 0x00, 0x58, 0x31, 0x80, 0x12, +0x14, 0x32, 0x02, 0x4d, 0x15, 0xc1, 0x01, 0xc5, 0xd5, 0x0d, 0x80, 0x82, 0x46, 0x2c, 0x00, 0x00, +0x58, 0x21, 0x00, 0x12, 0x80, 0x64, 0x14, 0x22, 0x02, 0x4d, 0x44, 0x20, 0x00, 0x81, 0x14, 0x21, +0x81, 0xc5, 0x46, 0x60, 0x04, 0x12, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xe9, 0x43, 0x46, 0x20, +0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xe0, 0xa9, 0xf4, 0x14, 0x71, 0x02, 0x60, 0x14, 0x31, +0x02, 0x60, 0x80, 0x47, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd7, 0x09, 0x49, 0xff, 0xe9, 0x32, +0xf0, 0x05, 0x9d, 0xf9, 0xb4, 0x40, 0x96, 0x94, 0x84, 0x0a, 0xc2, 0xf6, 0x46, 0x40, 0x04, 0x12, +0x46, 0x2f, 0x0f, 0x30, 0x58, 0x21, 0x00, 0x03, 0x58, 0x42, 0x09, 0x80, 0xb6, 0x44, 0x46, 0x20, +0x04, 0x12, 0x04, 0x21, 0x02, 0x61, 0xf2, 0x86, 0x4e, 0xa3, 0x00, 0x07, 0x46, 0x3f, 0x0f, 0x30, +0x58, 0x31, 0x80, 0x20, 0xd5, 0x73, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x2a, 0xd5, 0x6e, +0xf2, 0x01, 0x84, 0xa1, 0xda, 0x74, 0x46, 0x30, 0x04, 0x12, 0x44, 0x20, 0x00, 0x12, 0x80, 0x83, +0xa8, 0x99, 0x44, 0x23, 0x7f, 0x7f, 0x14, 0x22, 0x03, 0x3b, 0x4e, 0xa3, 0x00, 0x07, 0x46, 0x20, +0x14, 0x07, 0x58, 0x21, 0x0f, 0x7f, 0xd5, 0x05, 0x46, 0x20, 0x15, 0x47, 0x58, 0x21, 0x0f, 0x7f, +0x14, 0x22, 0x03, 0x3b, 0x46, 0x38, 0x00, 0x00, 0x80, 0x44, 0x14, 0x31, 0x03, 0x3a, 0x4f, 0xc3, +0x00, 0x0c, 0x80, 0x82, 0x46, 0x38, 0x00, 0x00, 0x58, 0x31, 0x80, 0x12, 0x14, 0x32, 0x02, 0x4d, +0x15, 0xc1, 0x01, 0xc5, 0xd5, 0x0d, 0x80, 0x82, 0x46, 0x2c, 0x00, 0x00, 0x58, 0x21, 0x00, 0x12, +0x80, 0x64, 0x14, 0x22, 0x02, 0x4d, 0x44, 0x20, 0x00, 0x81, 0x14, 0x21, 0x81, 0xc5, 0x46, 0x60, +0x04, 0x12, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xe8, 0xd5, 0x46, 0x20, 0x04, 0x12, 0x46, 0x3f, +0x0f, 0x30, 0x84, 0xe0, 0xa9, 0xf4, 0x14, 0x71, 0x02, 0x60, 0x14, 0x31, 0x02, 0x60, 0x80, 0x47, +0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd7, 0x09, 0x49, 0xff, 0xe8, 0xc4, 0xf0, 0x05, 0x9d, 0xf9, +0xb4, 0x40, 0x96, 0x94, 0x84, 0x0a, 0xc2, 0xf6, 0x46, 0x40, 0x04, 0x12, 0x46, 0x2f, 0x0f, 0x30, +0x58, 0x21, 0x00, 0x03, 0x58, 0x42, 0x09, 0x80, 0xb6, 0x44, 0x46, 0x20, 0x04, 0x12, 0x04, 0x21, +0x02, 0x61, 0xf2, 0x86, 0x4e, 0xa3, 0x00, 0x07, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x40, +0xd5, 0x05, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x54, 0xb6, 0x64, 0x46, 0x30, 0x04, 0x12, +0x58, 0x31, 0x89, 0x84, 0x50, 0x41, 0x83, 0x64, 0x48, 0x00, 0x00, 0xbb, 0xf2, 0x07, 0x46, 0x40, +0x04, 0x12, 0x80, 0xa4, 0x46, 0x3c, 0x00, 0x02, 0x84, 0x00, 0xb6, 0x02, 0x58, 0x31, 0x81, 0x01, +0x44, 0x20, 0x00, 0x5a, 0xa8, 0xa1, 0x14, 0x32, 0x81, 0xc6, 0x4f, 0xc3, 0x00, 0x0c, 0x46, 0x38, +0x00, 0x00, 0x80, 0x44, 0x58, 0x31, 0x80, 0x12, 0x14, 0x32, 0x02, 0x4d, 0x15, 0xc1, 0x01, 0xc5, +0xd5, 0x0a, 0x50, 0x21, 0xdf, 0x11, 0x80, 0x64, 0x14, 0x22, 0x02, 0x4d, 0x44, 0x20, 0x00, 0x81, +0x14, 0x21, 0x81, 0xc5, 0x80, 0xc5, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, 0xe8, 0x73, 0x46, 0x20, +0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xe0, 0xa9, 0xf4, 0x14, 0x71, 0x02, 0x60, 0x14, 0x31, +0x02, 0x60, 0x80, 0x47, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd7, 0x09, 0x49, 0xff, 0xe8, 0x62, +0xf0, 0x05, 0x9d, 0xf9, 0xb4, 0x40, 0x96, 0x94, 0x84, 0x0a, 0xc2, 0xf6, 0x46, 0x20, 0x04, 0x12, +0x46, 0x3f, 0x0f, 0x30, 0x58, 0x31, 0x80, 0x06, 0x14, 0x31, 0x02, 0x60, 0x04, 0x21, 0x02, 0x61, +0x46, 0x70, 0x04, 0x12, 0x80, 0xc7, 0x84, 0x01, 0x84, 0x20, 0xf2, 0x86, 0x14, 0x13, 0x81, 0xc6, +0xa8, 0x34, 0x49, 0xff, 0xe8, 0x47, 0x84, 0x60, 0xa8, 0xf4, 0x4e, 0xa3, 0x00, 0x07, 0x46, 0x38, +0x00, 0x02, 0x58, 0x31, 0x81, 0x28, 0xd5, 0x05, 0x46, 0x3c, 0x00, 0x02, 0x58, 0x31, 0x81, 0x1c, +0x14, 0x33, 0x81, 0xc6, 0x4f, 0xc3, 0x00, 0x0e, 0x46, 0x50, 0x04, 0x12, 0x46, 0x48, 0x00, 0x00, +0x80, 0x65, 0x58, 0x42, 0x00, 0x12, 0x14, 0x42, 0x82, 0x4d, 0x15, 0xc1, 0x81, 0xc5, 0xd5, 0x0e, +0x46, 0x50, 0x04, 0x12, 0x46, 0x3c, 0x00, 0x00, 0x58, 0x31, 0x80, 0x12, 0x80, 0x85, 0x14, 0x32, +0x82, 0x4d, 0x44, 0x30, 0x00, 0x81, 0x14, 0x32, 0x01, 0xc5, 0x46, 0x80, 0x04, 0x12, 0x46, 0x70, +0x04, 0x12, 0x84, 0x61, 0x58, 0x84, 0x09, 0x80, 0x84, 0x00, 0xb6, 0x08, 0xa8, 0xfc, 0x80, 0x03, +0x49, 0xff, 0xe8, 0x10, 0x46, 0x3f, 0x0f, 0x30, 0x84, 0xc0, 0xa9, 0xbc, 0xb6, 0xc8, 0xb6, 0x68, +0x80, 0x66, 0xd5, 0x09, 0x44, 0x50, 0x00, 0x65, 0xd6, 0x09, 0x49, 0xff, 0xe8, 0x03, 0xf0, 0x05, +0x9d, 0xb1, 0xb4, 0x60, 0x96, 0xdc, 0x84, 0x0a, 0xc3, 0xf6, 0x4e, 0xa3, 0x00, 0x0b, 0x46, 0x40, +0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x42, 0x09, 0x80, 0x58, 0x31, 0x80, 0x80, 0xd5, 0x09, +0x46, 0x40, 0x04, 0x12, 0x46, 0x3f, 0x0f, 0x30, 0x58, 0x42, 0x09, 0x80, 0x58, 0x31, 0x80, 0xa8, +0xb6, 0x64, 0x46, 0x30, 0x04, 0x12, 0x58, 0x31, 0x89, 0x84, 0x50, 0x41, 0xfd, 0x94, 0x84, 0x20, +0xb4, 0x63, 0xb6, 0x24, 0x84, 0x21, 0xf0, 0x06, 0x40, 0x30, 0x8c, 0x1a, 0x94, 0x87, 0x4e, 0xa3, +0x00, 0x15, 0x40, 0x21, 0x0c, 0x77, 0x5c, 0xf1, 0x01, 0x79, 0xe9, 0x08, 0xf2, 0x08, 0x40, 0x10, +0x88, 0x0c, 0x40, 0x10, 0x84, 0x05, 0x40, 0x94, 0x84, 0x02, 0xf3, 0x03, 0x4e, 0x35, 0x00, 0x1d, +0x84, 0x21, 0x40, 0x10, 0x8c, 0x0c, 0xd5, 0x14, 0x40, 0x21, 0x0c, 0x77, 0x5c, 0xf1, 0x01, 0xcb, +0xe9, 0x08, 0xf0, 0x08, 0x40, 0x10, 0x80, 0x0c, 0x40, 0x10, 0x84, 0x05, 0x40, 0x94, 0x84, 0x02, +0xf1, 0x03, 0x4e, 0x15, 0x00, 0x0a, 0xf2, 0x03, 0x84, 0x21, 0x40, 0x10, 0x88, 0x0c, 0x40, 0x94, +0x84, 0x04, 0x48, 0xff, 0xfd, 0xd0, 0xf3, 0x01, 0xcb, 0x09, 0xf0, 0x02, 0xc8, 0x04, 0x3e, 0x29, +0xcf, 0x44, 0xd5, 0x19, 0x3e, 0x29, 0xcf, 0x48, 0xd5, 0x16, 0xf1, 0x01, 0x84, 0xa1, 0xd9, 0x09, +0xf3, 0x02, 0xcb, 0x04, 0x3e, 0x29, 0xcf, 0x4c, 0xd5, 0x0e, 0x3e, 0x29, 0xcf, 0x50, 0xd5, 0x0b, +0xf0, 0x01, 0x84, 0xa2, 0xd8, 0x0a, 0xf2, 0x02, 0xca, 0x04, 0x3e, 0x29, 0xcf, 0x54, 0xd5, 0x03, +0x3e, 0x29, 0xcf, 0x58, 0x38, 0x91, 0x70, 0x08, 0xf3, 0x02, 0x84, 0xa2, 0x9c, 0x59, 0x96, 0x48, +0xf1, 0x82, 0x4c, 0x12, 0xfd, 0x4d, 0xf2, 0x01, 0x84, 0xa3, 0x9c, 0x51, 0x96, 0x48, 0xf1, 0x81, +0x4c, 0x12, 0xfc, 0xfb, 0xb4, 0x3f, 0x46, 0x70, 0x00, 0x80, 0x58, 0x73, 0x89, 0x4c, 0x3e, 0x09, +0x61, 0x64, 0xdd, 0x27, 0xb4, 0x1f, 0x3f, 0xc9, 0xcf, 0x44, 0x38, 0x1e, 0x00, 0x00, 0x3e, 0x09, +0x61, 0x74, 0xdd, 0x27, 0xb4, 0x5f, 0x3e, 0xa9, 0xcf, 0x48, 0x38, 0x15, 0x08, 0x00, 0x3e, 0x09, +0x61, 0x88, 0xdd, 0x27, 0xb4, 0x7f, 0x3e, 0x69, 0xcf, 0x4c, 0x38, 0x13, 0x0c, 0x00, 0x3e, 0x09, +0x61, 0x9c, 0xdd, 0x27, 0xb4, 0x5f, 0x3e, 0x09, 0xcf, 0x50, 0x38, 0x10, 0x08, 0x00, 0x3e, 0x09, +0x61, 0xb0, 0xdd, 0x27, 0xb4, 0x1f, 0x3e, 0x39, 0xcf, 0x54, 0x38, 0x11, 0x80, 0x00, 0x3e, 0x09, +0x61, 0xc4, 0xdd, 0x27, 0xb4, 0x7f, 0x3e, 0x29, 0xcf, 0x58, 0x38, 0x11, 0x0c, 0x00, 0x3e, 0x09, +0x61, 0xd8, 0xdd, 0x27, 0x50, 0x9f, 0x80, 0x34, 0xb4, 0x1f, 0x46, 0x80, 0x00, 0x89, 0x58, 0x84, +0x00, 0x64, 0x44, 0x10, 0x02, 0x4c, 0x80, 0x49, 0xdd, 0x28, 0xb4, 0x1f, 0xf2, 0x0d, 0x38, 0x4e, +0x00, 0x00, 0xb4, 0x7f, 0x38, 0x05, 0x00, 0x00, 0x46, 0x18, 0x08, 0x08, 0x58, 0x10, 0x80, 0x80, +0x38, 0x53, 0x0c, 0x00, 0x40, 0x21, 0x04, 0x02, 0x40, 0x60, 0x20, 0x08, 0x3e, 0x09, 0xcf, 0x50, +0x38, 0x30, 0x0c, 0x00, 0x40, 0x42, 0x08, 0x04, 0x40, 0x52, 0xc0, 0x08, 0x40, 0x42, 0x18, 0x04, +0x40, 0x42, 0x14, 0x04, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x32, 0x0c, 0x04, 0xf3, 0x8d, 0xb4, 0x1f, +0x80, 0x43, 0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x06, 0xa0, 0x44, 0x10, 0x02, 0x4c, 0xdd, 0x26, +0xb4, 0x1f, 0x44, 0x10, 0x02, 0x50, 0x80, 0x49, 0xdd, 0x28, 0xb4, 0x5f, 0x3e, 0x39, 0xcf, 0x58, +0x38, 0x41, 0x88, 0x00, 0x3e, 0x19, 0xcf, 0x54, 0xf3, 0x0d, 0x38, 0x50, 0x88, 0x00, 0x44, 0x0f, +0x80, 0x80, 0x40, 0x31, 0x80, 0x02, 0x40, 0x32, 0x8c, 0x04, 0x40, 0x42, 0x20, 0x08, 0x40, 0x31, +0x90, 0x04, 0xf3, 0x8d, 0xb4, 0x1f, 0x80, 0x43, 0x44, 0x10, 0x02, 0x50, 0xdd, 0x26, 0xb4, 0x1f, +0x80, 0x49, 0x44, 0x10, 0x02, 0x4c, 0xdd, 0x28, 0xf1, 0x0d, 0x3e, 0x09, 0x61, 0xec, 0xdd, 0x27, +0xb4, 0x1f, 0x80, 0x49, 0x44, 0x10, 0x02, 0x50, 0xdd, 0x28, 0xf1, 0x0d, 0x3e, 0x09, 0x61, 0xf8, +0xdd, 0x27, 0xb4, 0x1f, 0x44, 0x10, 0x02, 0x64, 0x80, 0x49, 0xdd, 0x28, 0xb4, 0x3f, 0xf3, 0x0d, +0x38, 0x4e, 0x04, 0x00, 0x46, 0x28, 0x0f, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x42, 0x60, 0x08, +0x40, 0x31, 0x88, 0x02, 0xb4, 0x1f, 0x40, 0x22, 0x0c, 0x04, 0x44, 0x10, 0x02, 0x64, 0xdd, 0x26, +0xb4, 0x1f, 0x80, 0x49, 0x44, 0x10, 0x02, 0x78, 0xdd, 0x28, 0xb4, 0x1f, 0xf2, 0x0d, 0x38, 0x35, +0x00, 0x00, 0x46, 0x18, 0x0f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x21, +0x04, 0x02, 0x40, 0x21, 0x88, 0x04, 0x44, 0x10, 0x02, 0x78, 0xdd, 0x26, 0xf2, 0x04, 0xca, 0x0d, +0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xe6, 0xdc, 0x49, 0xff, 0xf3, 0x58, 0x84, 0x01, 0xa8, 0x34, +0x49, 0xff, 0xe6, 0xa8, 0xf3, 0x04, 0xa8, 0xf4, 0xec, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0xb5, 0x00, 0xb4, 0xe0, 0x80, 0xc0, 0x3e, 0x09, 0x62, 0x04, +0x49, 0xff, 0xaf, 0xfe, 0x92, 0xff, 0x84, 0x01, 0x4c, 0x70, 0x40, 0x13, 0x9c, 0x34, 0xb4, 0x60, +0xb4, 0x40, 0xb4, 0x20, 0xb4, 0x00, 0x92, 0x48, 0x92, 0x30, 0x92, 0x18, 0x10, 0x3f, 0x80, 0x0f, +0x10, 0x2f, 0x80, 0x0e, 0x10, 0x1f, 0x80, 0x0d, 0x10, 0x0f, 0x80, 0x0c, 0xd5, 0x1b, 0x44, 0x65, +0x22, 0x9c, 0x50, 0x1f, 0x80, 0x0f, 0x84, 0x41, 0x44, 0x00, 0x00, 0x44, 0xdd, 0x26, 0x50, 0x1f, +0x80, 0x0e, 0x84, 0x41, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x50, 0x1f, 0x80, 0x0d, 0x84, 0x41, +0x44, 0x00, 0x00, 0x49, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x4d, 0x50, 0x1f, 0x80, 0x0c, 0x84, 0x41, +0xdd, 0x26, 0x00, 0x4f, 0x80, 0x0d, 0x00, 0x2f, 0x80, 0x0f, 0x00, 0x3f, 0x80, 0x0e, 0x00, 0x5f, +0x80, 0x0c, 0x80, 0x27, 0x3e, 0x09, 0x62, 0x20, 0x49, 0xff, 0xaf, 0xc2, 0x00, 0x4f, 0x80, 0x0f, +0x44, 0x10, 0x00, 0xff, 0x4c, 0x40, 0x80, 0x0e, 0x00, 0x3f, 0x80, 0x0e, 0x4c, 0x30, 0x80, 0x0a, +0x00, 0x2f, 0x80, 0x0d, 0x4c, 0x20, 0x80, 0x06, 0x00, 0x0f, 0x80, 0x0c, 0x4c, 0x00, 0xc0, 0x06, +0x49, 0xff, 0xea, 0x5c, 0x48, 0x00, 0x01, 0x17, 0x54, 0x14, 0x00, 0xff, 0xe6, 0x2f, 0xe9, 0x0f, +0x2e, 0x81, 0x8a, 0x6d, 0x84, 0xac, 0x56, 0x84, 0x00, 0x01, 0x84, 0x80, 0x40, 0x62, 0xa0, 0x1a, +0x40, 0x62, 0x20, 0x1b, 0x5c, 0xf0, 0x80, 0x41, 0xe8, 0x10, 0xd5, 0x0d, 0x2e, 0x31, 0x8a, 0x6c, +0x84, 0x40, 0x84, 0x0c, 0x56, 0x31, 0x80, 0x01, 0x40, 0x61, 0x0c, 0x1b, 0x40, 0x60, 0x0c, 0x1a, +0x80, 0x04, 0xd5, 0x07, 0x80, 0x03, 0xd5, 0x05, 0x5c, 0x30, 0x80, 0x81, 0x40, 0x01, 0x0c, 0x1b, +0x96, 0x02, 0x4e, 0x05, 0x00, 0x09, 0x54, 0x90, 0x00, 0x7f, 0x52, 0x94, 0x80, 0x00, 0x40, 0x94, +0x80, 0x10, 0xd5, 0x03, 0x54, 0x90, 0x00, 0x7f, 0x80, 0x47, 0x80, 0x69, 0x3e, 0x09, 0x62, 0x50, +0x40, 0x93, 0x24, 0x01, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xaf, 0x72, 0xf6, 0x81, 0x54, 0x94, +0x80, 0xff, 0x04, 0xaf, 0x80, 0x01, 0x46, 0x60, 0x04, 0x12, 0x58, 0x63, 0x03, 0x14, 0x9f, 0xf4, +0x50, 0x83, 0x00, 0x04, 0x51, 0xc4, 0x00, 0x08, 0x58, 0xa5, 0x03, 0x24, 0x40, 0x14, 0x80, 0x10, +0x3e, 0x09, 0x62, 0x70, 0x14, 0xaf, 0x80, 0x01, 0x49, 0xff, 0xaf, 0x5a, 0xb4, 0x3c, 0xb4, 0x4a, +0xb4, 0x67, 0xb4, 0x86, 0xb4, 0xa8, 0x3e, 0x09, 0x62, 0x84, 0x49, 0xff, 0xaf, 0x51, 0xb4, 0x1c, +0xb4, 0x5c, 0x44, 0x3f, 0x80, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x14, 0xa4, 0x00, 0xb6, 0x5c, +0x96, 0x48, 0x92, 0x08, 0x98, 0x01, 0xb4, 0x5c, 0x54, 0x00, 0x00, 0x7f, 0x40, 0x00, 0x20, 0x08, +0x40, 0x00, 0x08, 0x04, 0xb6, 0x1c, 0x81, 0x43, 0xf4, 0x01, 0x3e, 0x09, 0x62, 0xc4, 0xb4, 0x44, +0xb4, 0x64, 0x92, 0x48, 0x40, 0x31, 0xa8, 0x02, 0xb6, 0x64, 0x98, 0x51, 0x54, 0x10, 0x80, 0x7f, +0xb4, 0x44, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x24, 0x46, 0x3f, 0xfc, 0x0f, +0xb4, 0x27, 0xb4, 0x47, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x47, 0x92, 0x30, +0x8a, 0x29, 0xb4, 0x47, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0xc0, 0x08, 0x40, 0x10, 0x88, 0x04, +0xb6, 0x27, 0x44, 0x4f, 0xc0, 0xff, 0xb4, 0x26, 0xb4, 0x46, 0x92, 0x30, 0x40, 0x21, 0x0c, 0x02, +0xb6, 0x46, 0x8a, 0x29, 0xb4, 0x46, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0xc0, 0x08, 0x40, 0x10, +0x88, 0x04, 0xb6, 0x26, 0x44, 0xaf, 0xff, 0xc0, 0xb4, 0x27, 0xb4, 0x47, 0x92, 0x28, 0x40, 0x21, +0x10, 0x02, 0xb6, 0x47, 0x8a, 0x29, 0xb4, 0x47, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0xa0, 0x08, +0x40, 0x10, 0x88, 0x04, 0xb6, 0x27, 0xb4, 0x26, 0xb4, 0x46, 0x92, 0x28, 0x40, 0x21, 0x10, 0x02, +0xb6, 0x46, 0x8a, 0x29, 0xb4, 0x46, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, +0x88, 0x04, 0xb6, 0x26, 0xb4, 0x27, 0xb4, 0x47, 0x8a, 0x29, 0x40, 0x21, 0x28, 0x02, 0xb6, 0x47, +0xb4, 0x47, 0x54, 0x10, 0x80, 0x3f, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x27, 0xb4, 0x26, 0xb4, 0x46, +0x8a, 0x29, 0x40, 0x21, 0x28, 0x02, 0xb6, 0x46, 0x54, 0x10, 0x80, 0x3f, 0xb4, 0x46, 0x40, 0x10, +0x88, 0x04, 0xb6, 0x26, 0xb4, 0x28, 0xb4, 0x48, 0x8a, 0x29, 0x40, 0x21, 0x28, 0x02, 0xb6, 0x48, +0x54, 0x10, 0x80, 0x3f, 0xb4, 0x48, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x28, 0xb4, 0x28, 0xb4, 0x48, +0x92, 0x28, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x48, 0x40, 0x90, 0xa4, 0x01, 0x54, 0x94, 0x80, 0x3f, +0xb4, 0x28, 0x40, 0x94, 0xa0, 0x08, 0x40, 0x94, 0x84, 0x04, 0xb7, 0x28, 0xf3, 0x01, 0xb4, 0x3c, +0xb4, 0x43, 0xb4, 0x67, 0xb4, 0x86, 0xb4, 0xa8, 0x49, 0xff, 0xae, 0xaa, 0x49, 0xff, 0xe9, 0x56, +0xb4, 0x3c, 0x3c, 0x1e, 0x62, 0xb7, 0x04, 0xaf, 0x80, 0x01, 0xb4, 0x6a, 0x84, 0x00, 0x3e, 0x19, +0xce, 0x90, 0x3c, 0x3e, 0x62, 0xb8, 0xa8, 0x0b, 0x3c, 0x0e, 0x62, 0x82, 0xb6, 0x01, 0xa8, 0x09, +0xa8, 0x0a, 0x84, 0x00, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x46, 0x30, 0x04, 0x00, 0x04, 0x31, 0x80, 0x0e, 0x97, 0x80, 0x40, 0x01, 0xb4, 0x09, +0x97, 0xd0, 0x54, 0x00, 0x00, 0x07, 0x84, 0x42, 0x96, 0x48, 0x4c, 0x01, 0x00, 0x05, 0x84, 0xa1, +0xde, 0x35, 0xd5, 0x03, 0x84, 0xa1, 0xde, 0x04, 0x10, 0x1f, 0x80, 0x07, 0xd5, 0x08, 0x44, 0x00, +0x00, 0x35, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x3b, 0x1a, 0x00, 0x0f, 0x80, 0x07, +0x42, 0x10, 0x04, 0x0b, 0xc9, 0x04, 0x84, 0x41, 0x3e, 0x21, 0x8a, 0x72, 0x96, 0x04, 0xc8, 0x04, +0x84, 0x21, 0x3e, 0x11, 0x8a, 0x73, 0x84, 0xa1, 0xde, 0x04, 0x10, 0x7f, 0x80, 0x07, 0xd5, 0x08, +0x44, 0x00, 0x00, 0x36, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x3b, 0x01, 0x00, 0x0f, +0x80, 0x07, 0x42, 0x10, 0x0c, 0x0b, 0xc1, 0x04, 0x84, 0x41, 0x3e, 0x21, 0x8a, 0x6d, 0x42, 0x00, +0x08, 0x0b, 0xc0, 0x04, 0x84, 0x21, 0x3e, 0x11, 0x8a, 0x6c, 0x3e, 0x09, 0x63, 0x04, 0x80, 0x26, +0x47, 0xc0, 0x01, 0x19, 0x49, 0xff, 0xae, 0x44, 0x2e, 0x11, 0x8a, 0x72, 0x2e, 0x21, 0x8a, 0x6d, +0x3e, 0x09, 0x63, 0x18, 0x49, 0xff, 0xae, 0x3c, 0x2e, 0x11, 0x8a, 0x73, 0x2e, 0x21, 0x8a, 0x6c, +0x3e, 0x09, 0x63, 0x30, 0x49, 0xff, 0xae, 0x34, 0x84, 0xa1, 0xde, 0x5f, 0x46, 0x00, 0x04, 0x00, +0x84, 0x40, 0x14, 0x20, 0x00, 0x48, 0x80, 0x20, 0x04, 0x30, 0x80, 0x10, 0x96, 0xd9, 0x14, 0x30, +0x80, 0x10, 0x04, 0x10, 0x00, 0x49, 0x14, 0x20, 0x00, 0x49, 0x04, 0x10, 0x00, 0x4a, 0x14, 0x20, +0x00, 0x4a, 0x2e, 0x51, 0x8a, 0x72, 0xd6, 0x0b, 0x2e, 0x01, 0x8a, 0x73, 0x84, 0xa1, 0xd0, 0x07, +0x2e, 0x01, 0x8a, 0x6d, 0xd0, 0x04, 0x2e, 0x01, 0x8a, 0x6c, 0xd8, 0x34, 0x46, 0x00, 0x04, 0x00, +0x84, 0x80, 0x14, 0x40, 0x00, 0x48, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x20, +0x44, 0x6f, 0xff, 0xc5, 0x40, 0x10, 0x98, 0x02, 0xb6, 0x20, 0x46, 0x30, 0x04, 0x00, 0xb4, 0x20, +0x58, 0x10, 0x80, 0x10, 0xb6, 0x20, 0x04, 0x01, 0x80, 0x08, 0x80, 0x43, 0x42, 0x00, 0x30, 0x09, +0x14, 0x01, 0x80, 0x08, 0x04, 0x31, 0x00, 0x20, 0x42, 0x31, 0x98, 0x09, 0x14, 0x31, 0x00, 0x20, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x24, 0xb4, 0x41, 0xb6, 0x81, 0x9c, 0x0c, 0xb4, 0x40, +0xb6, 0x80, 0xb4, 0x41, 0xb6, 0x41, 0x44, 0x27, 0x70, 0x00, 0xb4, 0x20, 0x40, 0x10, 0x88, 0x04, +0xb6, 0x20, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x24, 0x9c, 0xcc, 0xb4, 0x41, 0xb4, 0x83, +0x3e, 0x09, 0x63, 0x48, 0x49, 0xff, 0xad, 0xd4, 0x2e, 0x21, 0x8a, 0x73, 0xc2, 0x19, 0x46, 0x10, +0x04, 0x00, 0x04, 0x30, 0x80, 0x49, 0x46, 0x4f, 0xff, 0x00, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x31, +0x90, 0x02, 0x44, 0x57, 0x70, 0x00, 0x40, 0x31, 0x94, 0x04, 0x14, 0x30, 0x80, 0x49, 0x46, 0x00, +0x04, 0x10, 0x04, 0x10, 0x01, 0x46, 0x58, 0x10, 0x80, 0x14, 0x14, 0x10, 0x01, 0x46, 0x2e, 0x31, +0x8a, 0x72, 0xc3, 0x19, 0x46, 0x10, 0x04, 0x00, 0x04, 0x40, 0x80, 0x49, 0x46, 0x6f, 0x00, 0xff, +0x58, 0x63, 0x0f, 0xff, 0x46, 0x50, 0x77, 0x00, 0x40, 0x42, 0x18, 0x02, 0x40, 0x42, 0x14, 0x04, +0x14, 0x40, 0x80, 0x49, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x46, 0x58, 0x10, 0x80, 0x0a, +0x14, 0x10, 0x01, 0x46, 0x2e, 0x41, 0x8a, 0x6d, 0xcc, 0x04, 0x2e, 0x01, 0x8a, 0x6c, 0xc0, 0x47, +0x46, 0x10, 0x04, 0x00, 0x04, 0x50, 0x80, 0x49, 0x95, 0x6c, 0x92, 0xa4, 0x46, 0x67, 0x00, 0x00, +0x40, 0x52, 0x98, 0x04, 0x14, 0x50, 0x80, 0x49, 0x80, 0x01, 0x04, 0x10, 0x00, 0x4a, 0x92, 0x24, +0x94, 0x4c, 0x58, 0x10, 0x80, 0x07, 0x14, 0x10, 0x00, 0x4a, 0xc4, 0x31, 0x2e, 0x01, 0x8a, 0x6c, +0xc8, 0x2e, 0xcb, 0x2d, 0xca, 0x2c, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x00, 0x46, 0x17, 0x61, 0x20, +0x40, 0x50, 0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, 0xd9, 0x22, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x0e, 0x84, 0xa3, 0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd8, 0x19, 0x46, 0x10, 0x04, 0x00, +0x04, 0x20, 0x80, 0x48, 0x46, 0x3f, 0xff, 0x0f, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, +0x42, 0x21, 0x40, 0x08, 0x14, 0x20, 0x80, 0x48, 0x80, 0x01, 0x04, 0x10, 0x00, 0x6e, 0x42, 0x10, +0x90, 0x09, 0x14, 0x10, 0x00, 0x6e, 0x84, 0x21, 0x3e, 0x11, 0x8a, 0x74, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x3e, 0x09, 0x7b, 0xa0, 0xb4, 0x20, +0xa0, 0x81, 0x8c, 0x08, 0xb6, 0x41, 0x3e, 0x59, 0x7d, 0xd0, 0xd8, 0xfa, 0x46, 0x00, 0x04, 0x00, +0xb4, 0x00, 0x92, 0x04, 0x54, 0x00, 0x00, 0x0f, 0xe6, 0x03, 0xe9, 0x08, 0x46, 0x00, 0x04, 0x12, +0x46, 0x18, 0x70, 0x00, 0x58, 0x10, 0x83, 0x0a, 0xa8, 0x43, 0x2e, 0x01, 0x8a, 0x6f, 0x84, 0xa1, +0xd8, 0x06, 0x2e, 0x01, 0x8a, 0x70, 0x10, 0x0f, 0x80, 0x07, 0xd5, 0x08, 0x44, 0x00, 0x00, 0x35, +0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x39, 0xcb, 0x00, 0x1f, 0x80, 0x07, 0x42, 0x10, +0x98, 0x0b, 0xc9, 0x05, 0x46, 0x00, 0x04, 0x12, 0x14, 0x10, 0x01, 0x02, 0x2e, 0x01, 0x8a, 0x59, +0x84, 0xa1, 0xd8, 0x09, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x02, 0x54, 0x42, 0x10, 0x80, 0x09, +0x14, 0x10, 0x02, 0x54, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x49, 0xff, 0xeb, 0x83, 0x49, 0xff, 0xf2, 0x49, 0x49, 0xff, 0xff, 0xb5, 0x49, 0xff, +0xe6, 0x15, 0x49, 0xff, 0xe6, 0x7d, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x96, 0x00, 0x84, 0xee, 0x2e, 0x11, 0x8a, 0x7c, 0x40, 0x73, +0x80, 0x06, 0xf0, 0x83, 0x84, 0x02, 0x54, 0x91, 0x00, 0xff, 0xf7, 0x82, 0x4c, 0x10, 0x40, 0x04, +0x85, 0x08, 0xd5, 0x09, 0x56, 0x10, 0x80, 0x01, 0x84, 0x60, 0x84, 0x84, 0x40, 0x82, 0x04, 0x1a, +0x40, 0x81, 0x84, 0x1b, 0x2e, 0x11, 0x8a, 0x7d, 0x84, 0xa1, 0xd9, 0x06, 0x2e, 0x31, 0x8a, 0x7e, +0x4c, 0x30, 0xc0, 0x0b, 0xd5, 0x16, 0x84, 0xa2, 0xd9, 0x10, 0x2e, 0x11, 0x8a, 0x7e, 0x84, 0xa1, +0xd9, 0x07, 0x95, 0x83, 0xd5, 0x0f, 0x84, 0xa2, 0xdb, 0x08, 0x95, 0x84, 0xd5, 0x0b, 0x84, 0xa2, +0xd9, 0x04, 0x44, 0x60, 0x00, 0x30, 0xd5, 0x06, 0x3e, 0x09, 0x63, 0x5c, 0x49, 0xff, 0xac, 0xc0, +0x84, 0xc0, 0x49, 0xff, 0xff, 0x71, 0x49, 0xff, 0xf2, 0x01, 0x49, 0xff, 0xe5, 0xcf, 0xf0, 0x02, +0xc0, 0x03, 0x49, 0xff, 0xe5, 0xc1, 0xf3, 0x02, 0x40, 0x14, 0x0c, 0x04, 0x40, 0x60, 0x98, 0x04, +0x3e, 0x19, 0x67, 0x94, 0xb4, 0x01, 0x54, 0x50, 0x00, 0x3f, 0xde, 0x04, 0xa0, 0x09, 0xa0, 0x8a, +0xb6, 0x40, 0x8c, 0x2c, 0x3e, 0x59, 0x6c, 0xa4, 0xd9, 0xf6, 0x46, 0x10, 0x04, 0x00, 0x04, 0x30, +0x80, 0x0e, 0x84, 0xa1, 0x92, 0x74, 0x54, 0x31, 0x80, 0x03, 0xd3, 0x08, 0x04, 0x10, 0x80, 0x0e, +0x84, 0xa2, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0xd9, 0x15, 0xf0, 0x02, 0xc0, 0x1c, 0x84, 0xa4, +0x4c, 0x82, 0x80, 0x05, 0x84, 0xa8, 0x4c, 0x82, 0xc0, 0x10, 0x46, 0x40, 0x04, 0x12, 0x46, 0x11, +0xe4, 0x25, 0x80, 0x64, 0x58, 0x10, 0x8c, 0xf8, 0x14, 0x12, 0x00, 0xc8, 0x14, 0x11, 0x80, 0xc9, +0xd5, 0x03, 0xf0, 0x02, 0xc0, 0x08, 0x2e, 0x11, 0x8a, 0x6d, 0x84, 0xa1, 0xd9, 0x37, 0x3e, 0x19, +0x6c, 0xa4, 0xd5, 0x06, 0x2e, 0x11, 0x8a, 0x6c, 0x84, 0xa1, 0xd9, 0x30, 0xd5, 0xf9, 0xb4, 0x01, +0x54, 0x50, 0x00, 0x3f, 0xde, 0x04, 0xa0, 0x09, 0xa0, 0x8a, 0xb6, 0x40, 0x8c, 0x2c, 0x3e, 0x59, +0x6f, 0x8c, 0xd9, 0xf6, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0x30, 0xb4, 0x61, 0x44, 0x0f, +0xbf, 0xbf, 0x40, 0x31, 0x80, 0x02, 0xb6, 0x61, 0xf3, 0x02, 0xc3, 0x05, 0x2e, 0x31, 0x8a, 0x72, +0xcb, 0x09, 0xd5, 0x04, 0x2e, 0x31, 0x8a, 0x73, 0xcb, 0x08, 0xb4, 0x61, 0x58, 0x31, 0xc0, 0x40, +0xd5, 0x0c, 0x84, 0xa1, 0xdb, 0x0b, 0xd5, 0x03, 0x84, 0xa1, 0xdb, 0x08, 0x46, 0x10, 0x04, 0x12, +0x58, 0x10, 0x80, 0x88, 0x44, 0x30, 0x00, 0x40, 0xb6, 0x61, 0x2e, 0x11, 0x8a, 0x74, 0x84, 0xa1, +0xd9, 0x04, 0xf0, 0x03, 0x49, 0xff, 0xe6, 0x94, 0x4e, 0x93, 0x01, 0x7b, 0x3e, 0x89, 0x6f, 0x8c, +0x50, 0x94, 0x00, 0x08, 0x50, 0x6f, 0x80, 0x24, 0x47, 0xc0, 0x00, 0x89, 0x59, 0xce, 0x00, 0x64, +0x46, 0xa0, 0x00, 0x87, 0x58, 0xa5, 0x06, 0xa0, 0xd5, 0x62, 0x00, 0x54, 0x00, 0x00, 0xf1, 0x03, +0xd9, 0x5c, 0x44, 0x10, 0x01, 0x44, 0x80, 0x46, 0x84, 0x00, 0xdd, 0x3c, 0x04, 0x74, 0x00, 0x01, +0xf4, 0x09, 0x46, 0x3f, 0xe0, 0x00, 0x58, 0x31, 0x87, 0xff, 0x54, 0x73, 0xbf, 0xff, 0x40, 0x42, +0x0c, 0x02, 0x40, 0x73, 0xac, 0x08, 0x40, 0x43, 0x90, 0x04, 0xf4, 0x89, 0x80, 0x44, 0x44, 0x10, +0x01, 0x44, 0x84, 0x00, 0xdd, 0x2a, 0x44, 0x10, 0x01, 0x44, 0x80, 0x46, 0x84, 0x01, 0xdd, 0x3c, +0xf3, 0x09, 0x46, 0x0f, 0xe0, 0x00, 0x58, 0x00, 0x07, 0xff, 0x40, 0x31, 0x80, 0x02, 0x40, 0x33, +0x8c, 0x04, 0xf3, 0x89, 0x80, 0x43, 0x44, 0x10, 0x01, 0x44, 0x84, 0x01, 0xdd, 0x2a, 0x44, 0x10, +0x01, 0x58, 0x80, 0x46, 0x84, 0x00, 0xdd, 0x3c, 0xf4, 0x09, 0xb4, 0xa9, 0x04, 0x74, 0x80, 0x01, +0x54, 0x52, 0x83, 0xff, 0x54, 0x42, 0x0c, 0x00, 0x40, 0x42, 0x14, 0x04, 0x40, 0x73, 0xb0, 0x08, +0x40, 0x42, 0x1c, 0x04, 0xf5, 0x81, 0xf4, 0x89, 0x80, 0x44, 0x44, 0x10, 0x01, 0x58, 0x84, 0x00, +0xdd, 0x2a, 0x44, 0x10, 0x01, 0x58, 0x80, 0x46, 0x84, 0x01, 0xdd, 0x3c, 0xf3, 0x09, 0xf5, 0x01, +0x54, 0x31, 0x8c, 0x00, 0x40, 0x31, 0x94, 0x04, 0x40, 0x31, 0x9c, 0x04, 0xf3, 0x89, 0x84, 0x01, +0x80, 0x43, 0x44, 0x10, 0x01, 0x58, 0xdd, 0x2a, 0x8d, 0x10, 0x8d, 0x30, 0x3e, 0x59, 0x79, 0xac, +0x4c, 0x82, 0xff, 0x9d, 0x84, 0x61, 0x3e, 0x79, 0x79, 0xae, 0xf3, 0x84, 0x50, 0xa3, 0x80, 0x1a, +0x50, 0x93, 0x80, 0x26, 0x50, 0x83, 0x80, 0x06, 0x51, 0xcf, 0x80, 0x24, 0xa4, 0x38, 0xf1, 0x03, +0xe2, 0x20, 0xe9, 0x6e, 0xa4, 0x39, 0xe2, 0x01, 0xe9, 0x6b, 0x50, 0x33, 0x80, 0x0e, 0x50, 0x03, +0x80, 0x1e, 0x50, 0x13, 0x80, 0x2e, 0xf3, 0x85, 0xf0, 0x86, 0xf1, 0x87, 0x84, 0xc0, 0x2e, 0x21, +0x8a, 0x6d, 0x84, 0xa1, 0x80, 0x06, 0x44, 0x10, 0x02, 0x54, 0xda, 0x08, 0xb4, 0x49, 0x49, 0xff, +0xe2, 0x49, 0x80, 0x06, 0x04, 0x24, 0x80, 0x01, 0xd5, 0x07, 0xb4, 0x48, 0x49, 0xff, 0xe2, 0x42, +0x04, 0x24, 0x00, 0x01, 0x80, 0x06, 0x44, 0x10, 0x02, 0x60, 0x49, 0xff, 0xe2, 0x3b, 0xf0, 0x05, +0x44, 0x10, 0x02, 0x9c, 0xb4, 0x40, 0x80, 0x06, 0x49, 0xff, 0xe2, 0x34, 0x80, 0x06, 0x44, 0x10, +0x02, 0x10, 0x80, 0x5c, 0x49, 0xff, 0xef, 0x10, 0xf1, 0x09, 0x02, 0x35, 0x00, 0x00, 0x92, 0x30, +0x40, 0x10, 0xc0, 0x08, 0x40, 0x31, 0x84, 0x04, 0x80, 0x43, 0x80, 0x06, 0x44, 0x10, 0x02, 0x10, +0xf3, 0x89, 0x49, 0xff, 0xe2, 0x1f, 0x80, 0x06, 0x44, 0x10, 0x01, 0x48, 0x80, 0x5c, 0x49, 0xff, +0xee, 0xfb, 0xf2, 0x09, 0x00, 0x15, 0x00, 0x02, 0x44, 0x0f, 0x87, 0xff, 0x40, 0x21, 0x00, 0x02, +0x40, 0x10, 0xac, 0x08, 0x40, 0x30, 0x88, 0x04, 0x80, 0x43, 0x80, 0x06, 0x44, 0x10, 0x01, 0x48, +0xf3, 0x89, 0x49, 0xff, 0xe2, 0x07, 0xf1, 0x06, 0x80, 0x06, 0xb4, 0x41, 0x44, 0x10, 0x00, 0x58, +0x49, 0xff, 0xe2, 0x00, 0xf1, 0x07, 0x80, 0x06, 0xb4, 0x41, 0x44, 0x10, 0x02, 0x98, 0x49, 0xff, +0xe1, 0xf9, 0x9d, 0xb1, 0x84, 0xa2, 0xde, 0xa4, 0xf1, 0x04, 0x3e, 0x11, 0x8a, 0x76, 0xf3, 0x04, +0x84, 0xa8, 0x9c, 0xd9, 0xf3, 0x84, 0x50, 0x73, 0x80, 0x34, 0x50, 0xa5, 0x00, 0x34, 0x50, 0x94, +0x80, 0x34, 0x50, 0x84, 0x00, 0x34, 0x4c, 0x32, 0xff, 0x83, 0xf1, 0x02, 0xc1, 0x09, 0x84, 0x01, +0x49, 0xff, 0xe2, 0x20, 0x2e, 0x11, 0x8a, 0x72, 0x84, 0xa1, 0xd9, 0x56, 0xd5, 0x59, 0xf0, 0x02, +0x3e, 0x01, 0x8a, 0x76, 0x80, 0xe0, 0x50, 0x6f, 0x80, 0x24, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, +0x80, 0x46, 0x49, 0xff, 0xee, 0xb1, 0xf3, 0x09, 0x92, 0x70, 0x40, 0x31, 0xc0, 0x08, 0x58, 0x31, +0x8c, 0x0c, 0xf3, 0x89, 0x80, 0x43, 0x80, 0x07, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xe1, 0xc2, +0x80, 0x07, 0x44, 0x10, 0x01, 0x48, 0x80, 0x46, 0x49, 0xff, 0xee, 0x9e, 0xf3, 0x09, 0x44, 0x1f, +0x87, 0xff, 0x40, 0x31, 0x84, 0x02, 0x58, 0x31, 0xb0, 0x00, 0xf3, 0x89, 0x80, 0x43, 0x80, 0x07, +0x44, 0x10, 0x01, 0x48, 0x49, 0xff, 0xe1, 0xae, 0x80, 0x07, 0x44, 0x10, 0x00, 0x58, 0x80, 0x46, +0x49, 0xff, 0xee, 0x8a, 0xf3, 0x09, 0x46, 0x1f, 0x8f, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x31, +0x84, 0x02, 0x46, 0x10, 0x60, 0x00, 0x40, 0x31, 0x84, 0x04, 0xf3, 0x89, 0x80, 0x07, 0x80, 0x43, +0x44, 0x10, 0x00, 0x58, 0x49, 0xff, 0xe1, 0x96, 0x9d, 0xf9, 0x84, 0xa2, 0xdf, 0xbf, 0x84, 0x00, +0x49, 0xff, 0xe1, 0xd0, 0x2e, 0x51, 0x8a, 0x73, 0x84, 0x01, 0xd0, 0x04, 0x2e, 0x51, 0x8a, 0x6c, +0xd8, 0x0a, 0x84, 0x00, 0xd5, 0x06, 0x2e, 0x11, 0x8a, 0x6d, 0x84, 0xa1, 0xd9, 0x04, 0x84, 0x01, +0x49, 0xff, 0xe8, 0xe4, 0x84, 0x00, 0xf2, 0x03, 0x80, 0x20, 0x49, 0xff, 0xe5, 0xf5, 0x46, 0x10, +0x04, 0x12, 0x46, 0x30, 0x07, 0x77, 0x58, 0x31, 0x87, 0x73, 0x14, 0x30, 0x81, 0x8c, 0x84, 0xae, +0xf0, 0x03, 0xd8, 0x06, 0x80, 0x01, 0xa0, 0x41, 0x58, 0x10, 0x80, 0x20, 0xa8, 0x41, 0xec, 0x2c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0x40, +0xb4, 0xe0, 0xb4, 0xc0, 0xa2, 0xd1, 0x92, 0x70, 0x96, 0xd8, 0x3e, 0x31, 0x8a, 0x7c, 0xb4, 0x82, +0x97, 0x20, 0x3e, 0x41, 0x8a, 0x7e, 0xb4, 0xa2, 0x92, 0xa8, 0x97, 0x68, 0x3e, 0x51, 0x8a, 0x7d, +0xb4, 0x02, 0x92, 0x10, 0x96, 0x00, 0x50, 0x10, 0x00, 0x20, 0x96, 0x48, 0xe6, 0x24, 0xe8, 0x06, +0x54, 0x00, 0x00, 0x0f, 0x49, 0xff, 0xe8, 0x40, 0xd5, 0x13, 0x92, 0xc8, 0x97, 0xf8, 0x97, 0xb0, +0x80, 0x46, 0x3e, 0x09, 0x63, 0x80, 0x80, 0x27, 0x85, 0x20, 0x3e, 0x91, 0x8a, 0x75, 0x49, 0xff, +0xaa, 0x8f, 0x80, 0x07, 0x80, 0x26, 0x84, 0x40, 0x49, 0xff, 0xfd, 0x94, 0x92, 0x00, 0x84, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x00, +0x04, 0x11, 0x58, 0x00, 0x03, 0x40, 0xb5, 0x00, 0xb4, 0x40, 0x42, 0x21, 0x50, 0x09, 0xb6, 0x40, +0x46, 0x10, 0x04, 0x11, 0xa1, 0xc9, 0x84, 0x93, 0x80, 0x01, 0x46, 0x20, 0x00, 0x92, 0x40, 0x33, +0x90, 0x02, 0x58, 0x21, 0x0b, 0x00, 0x04, 0x90, 0x00, 0xd1, 0xa8, 0xc9, 0x14, 0x20, 0x00, 0xd1, +0x46, 0x10, 0x04, 0x12, 0x80, 0x60, 0x46, 0x08, 0x00, 0x08, 0x80, 0x43, 0x44, 0x4f, 0xf5, 0x7c, +0x04, 0xa0, 0x80, 0x49, 0x14, 0x40, 0x80, 0x49, 0x14, 0x01, 0x80, 0x99, 0x14, 0x01, 0x00, 0x9a, +0x3e, 0x69, 0xd9, 0xe8, 0x49, 0xff, 0xe5, 0x58, 0x00, 0x03, 0x04, 0x0d, 0x49, 0xff, 0xe2, 0x52, +0x84, 0x80, 0x84, 0x20, 0x00, 0x03, 0x04, 0x0d, 0x3e, 0x41, 0x8a, 0x75, 0x80, 0x41, 0x49, 0xff, +0xfd, 0x51, 0x00, 0x03, 0x04, 0x0e, 0x50, 0x10, 0x00, 0x20, 0x96, 0x48, 0xe6, 0x24, 0xe8, 0x05, +0x54, 0x00, 0x00, 0x0f, 0x49, 0xff, 0xe7, 0xe0, 0x2e, 0x61, 0xdd, 0xf5, 0x87, 0x80, 0x80, 0x06, +0x49, 0xff, 0xe6, 0x44, 0x9c, 0x03, 0x96, 0x40, 0x80, 0x46, 0x84, 0x01, 0x49, 0xff, 0xe5, 0x54, +0x46, 0x60, 0x04, 0x11, 0x80, 0x86, 0x46, 0x58, 0x00, 0x08, 0x46, 0x30, 0x04, 0x12, 0x80, 0x44, +0x80, 0x22, 0x80, 0x01, 0x15, 0xc3, 0x00, 0x99, 0x14, 0x52, 0x00, 0x9a, 0x14, 0xa1, 0x80, 0x49, +0xa9, 0xd1, 0x14, 0x90, 0x80, 0xd1, 0x14, 0x80, 0x00, 0xd0, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x3e, 0x51, 0x8a, 0x7e, 0x3e, 0x41, 0x8a, 0x7d, +0x96, 0x90, 0x3e, 0x21, 0x8a, 0x7c, 0x46, 0x50, 0x04, 0x12, 0x80, 0x85, 0x04, 0x92, 0x80, 0x01, +0x54, 0x80, 0x00, 0xff, 0x04, 0x72, 0x00, 0xc0, 0x44, 0x0f, 0xff, 0xe7, 0x40, 0x54, 0x80, 0x02, +0x44, 0x0f, 0x8f, 0xff, 0x40, 0x43, 0x80, 0x02, 0x84, 0x01, 0x96, 0x48, 0x97, 0x98, 0x04, 0xaf, +0x80, 0x07, 0x4c, 0x20, 0x00, 0x0f, 0xc2, 0x14, 0x84, 0x02, 0x4c, 0x20, 0x00, 0x06, 0x84, 0x04, +0x4c, 0x20, 0x40, 0x11, 0xd5, 0x0b, 0x58, 0x52, 0x80, 0x18, 0x58, 0x42, 0x70, 0x00, 0xd5, 0x0a, +0x58, 0x52, 0x80, 0x10, 0x58, 0x42, 0x30, 0x00, 0xd5, 0x05, 0x58, 0x52, 0x80, 0x08, 0x58, 0x42, +0x10, 0x00, 0x4c, 0x54, 0x80, 0x05, 0x46, 0x30, 0x04, 0x12, 0xa9, 0x59, 0x4c, 0x43, 0x80, 0x06, +0x46, 0x30, 0x04, 0x12, 0x14, 0x41, 0x80, 0xc0, 0x46, 0x30, 0x04, 0x11, 0x04, 0x41, 0x80, 0xcb, +0x42, 0x32, 0x00, 0x09, 0x84, 0x01, 0x4c, 0x60, 0x00, 0x08, 0xc6, 0x06, 0x84, 0x03, 0x4c, 0x60, +0x40, 0x04, 0x58, 0x31, 0x80, 0x01, 0x4c, 0x32, 0x00, 0x06, 0x46, 0x40, 0x04, 0x11, 0x14, 0x32, +0x00, 0xcb, 0x46, 0x40, 0x04, 0x12, 0x80, 0x64, 0x04, 0x52, 0x00, 0xc0, 0x44, 0x0f, 0xfc, 0xff, +0x04, 0x71, 0x81, 0xc0, 0x40, 0x42, 0x80, 0x02, 0x40, 0x33, 0x88, 0x09, 0x94, 0xda, 0x84, 0x01, +0x4c, 0x60, 0x00, 0x09, 0x84, 0x03, 0x4c, 0x60, 0x40, 0x06, 0x58, 0x42, 0x01, 0x00, 0x58, 0x31, +0x80, 0x01, 0xd4, 0x05, 0x46, 0x50, 0x04, 0x12, 0x14, 0x42, 0x80, 0xc0, 0x4c, 0x33, 0x80, 0x06, +0x46, 0x40, 0x04, 0x12, 0x14, 0x32, 0x01, 0xc0, 0x46, 0x30, 0x04, 0x11, 0x04, 0x41, 0x81, 0x07, +0x92, 0x8c, 0x40, 0x42, 0x30, 0x08, 0x84, 0x01, 0x4c, 0x20, 0x40, 0x08, 0x4c, 0x61, 0x40, 0x03, +0xd5, 0x04, 0x58, 0x42, 0x02, 0xe1, 0xd5, 0x03, 0x58, 0x42, 0x01, 0xe4, 0x14, 0x41, 0x81, 0x07, +0xca, 0x0a, 0x46, 0x20, 0x04, 0x11, 0x46, 0x30, 0x01, 0x01, 0x58, 0x21, 0x03, 0x30, 0x58, 0x31, +0x80, 0x01, 0xd5, 0x09, 0x46, 0x20, 0x04, 0x11, 0x46, 0x30, 0x00, 0xb0, 0x58, 0x21, 0x03, 0x30, +0x58, 0x31, 0x8b, 0x01, 0xb6, 0x62, 0x46, 0x20, 0x04, 0x11, 0x44, 0x02, 0x00, 0x00, 0x14, 0x01, +0x00, 0xcd, 0x80, 0xe2, 0x04, 0x43, 0x80, 0x47, 0x3c, 0x4e, 0x62, 0x7f, 0x84, 0x40, 0x80, 0x08, +0x49, 0xff, 0xfc, 0x70, 0x80, 0x06, 0x49, 0xff, 0xe7, 0x07, 0x04, 0x13, 0x80, 0x47, 0x3c, 0x1e, +0x62, 0x80, 0x84, 0x01, 0x4c, 0xa0, 0x40, 0x2d, 0x46, 0x10, 0x04, 0x12, 0x04, 0x00, 0x82, 0x4d, +0x80, 0x41, 0x46, 0x31, 0x01, 0x01, 0x58, 0x00, 0x04, 0x00, 0x58, 0x31, 0x86, 0x1c, 0x14, 0x00, +0x82, 0x4d, 0x14, 0x31, 0x00, 0xe5, 0x04, 0x00, 0x82, 0x52, 0x80, 0x41, 0x46, 0x3b, 0x9c, 0xb9, +0x58, 0x00, 0x00, 0x01, 0x58, 0x31, 0x8f, 0xf9, 0x14, 0x00, 0x82, 0x52, 0x14, 0x31, 0x02, 0x53, +0x80, 0x08, 0x49, 0xff, 0xe1, 0x3f, 0x92, 0x00, 0xe7, 0x0f, 0xe9, 0x05, 0x2e, 0x11, 0x8a, 0x72, +0x80, 0x0a, 0xd5, 0x04, 0x2e, 0x11, 0x8a, 0x73, 0x84, 0x00, 0x49, 0xff, 0xee, 0xeb, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xb4, 0xc0, 0xb4, 0xe0, 0x96, 0x49, 0x92, 0xe8, +0x97, 0xb0, 0x97, 0xf8, 0xb5, 0x00, 0xe6, 0x25, 0xe9, 0x0d, 0x9c, 0x04, 0xb4, 0x40, 0x92, 0x5f, +0x3e, 0x21, 0x8a, 0x6f, 0xb4, 0x40, 0x3e, 0x21, 0x8a, 0x70, 0xb4, 0x20, 0x92, 0x28, 0x3e, 0x11, +0x8a, 0x71, 0x93, 0x10, 0x54, 0x84, 0x00, 0xff, 0x3e, 0x09, 0x63, 0xd0, 0x80, 0x26, 0x80, 0x47, +0x80, 0x68, 0x49, 0xff, 0xa9, 0x0d, 0x84, 0xa2, 0xd6, 0x22, 0xe6, 0xc3, 0xe8, 0x05, 0xc6, 0x09, +0x84, 0xa1, 0xde, 0x44, 0xd5, 0x11, 0x84, 0xa3, 0xd6, 0x2d, 0x84, 0xa4, 0xde, 0x3f, 0xd5, 0x3c, +0x2e, 0x01, 0x8a, 0x6f, 0x2e, 0x11, 0x8a, 0x70, 0x2e, 0x21, 0x8a, 0x71, 0x49, 0xff, 0xfa, 0x68, +0x49, 0xff, 0xe7, 0x74, 0xd5, 0x33, 0x2e, 0x01, 0x8a, 0x6f, 0x2e, 0x11, 0x8a, 0x70, 0x2e, 0x21, +0x8a, 0x71, 0x49, 0xff, 0xfa, 0x5d, 0x49, 0xff, 0xfb, 0x9f, 0xd5, 0x28, 0x2e, 0x01, 0x8a, 0x6f, +0x2e, 0x11, 0x8a, 0x70, 0x2e, 0x21, 0x8a, 0x71, 0x49, 0xff, 0xfa, 0x52, 0x49, 0xff, 0xe7, 0x5e, +0x49, 0xff, 0xee, 0x24, 0x49, 0xff, 0xfb, 0x90, 0x49, 0xff, 0xe1, 0xf0, 0x49, 0xff, 0xe2, 0x58, +0xd5, 0x15, 0x80, 0x08, 0x80, 0x27, 0x49, 0xff, 0xec, 0x9b, 0xcf, 0x07, 0x80, 0x08, 0x80, 0x27, +0x84, 0x41, 0x49, 0xff, 0xfb, 0xd7, 0xd5, 0x0a, 0x2e, 0x21, 0x8a, 0x7c, 0x80, 0x27, 0x80, 0x08, +0x49, 0xff, 0xe1, 0xf0, 0xd5, 0x03, 0x49, 0xff, 0xee, 0x09, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x84, 0x60, 0x50, 0x1f, 0x80, 0x07, +0x84, 0xc0, 0x44, 0x00, 0x01, 0x38, 0x84, 0x41, 0xae, 0xc8, 0xb6, 0xdf, 0x49, 0xfe, 0x35, 0x58, +0x00, 0x0f, 0x80, 0x07, 0x44, 0x50, 0x00, 0xff, 0xd0, 0x3a, 0x44, 0x10, 0x00, 0x38, 0x80, 0x5f, +0x80, 0x06, 0x49, 0xff, 0xec, 0x31, 0x00, 0x3f, 0x80, 0x07, 0xb4, 0x1f, 0x46, 0x1f, 0xff, 0x0f, +0x58, 0x10, 0x8f, 0xff, 0x54, 0x31, 0x80, 0x0f, 0x40, 0x00, 0x04, 0x02, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x31, 0x80, 0x04, 0xb6, 0x7f, 0x80, 0x43, 0x80, 0x06, 0x44, 0x10, 0x00, 0x38, 0x49, 0xff, +0xdf, 0x39, 0x80, 0x5f, 0x44, 0x10, 0x00, 0x38, 0x84, 0x01, 0x49, 0xff, 0xec, 0x15, 0x00, 0x3f, +0x80, 0x07, 0xb4, 0x1f, 0x46, 0x1f, 0xff, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x54, 0x31, 0x80, 0x0f, +0x40, 0x00, 0x04, 0x02, 0x40, 0x31, 0xc0, 0x08, 0x40, 0x31, 0x80, 0x04, 0xb6, 0x7f, 0x80, 0x43, +0x84, 0x01, 0x44, 0x10, 0x00, 0x38, 0x81, 0x1f, 0x49, 0xff, 0xdf, 0x1c, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x49, 0xff, 0xfd, 0xe7, 0x3e, 0x19, +0xd9, 0xe8, 0x84, 0x40, 0x10, 0x20, 0x84, 0x0c, 0x50, 0x00, 0x83, 0xf0, 0x49, 0xff, 0xa8, 0xae, +0x49, 0xff, 0xde, 0x86, 0x84, 0x20, 0x84, 0x43, 0x80, 0x61, 0x80, 0x81, 0x80, 0xa1, 0x84, 0x07, +0x49, 0xff, 0xb7, 0xc6, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0xb4, 0x20, 0x3e, 0x69, 0xd9, 0xe8, 0x10, 0x13, 0x04, 0x0d, 0x80, 0x20, 0xa2, 0xc9, 0x92, 0x70, +0x3e, 0x31, 0x8a, 0x7c, 0xb4, 0x61, 0x8c, 0x08, 0x3e, 0x31, 0x8a, 0x7e, 0xb4, 0x61, 0x92, 0x68, +0x3e, 0x31, 0x8a, 0x7d, 0xb4, 0x21, 0x92, 0x30, 0x10, 0x13, 0x04, 0x0e, 0xb4, 0xe0, 0xb5, 0x00, +0x97, 0xf8, 0x93, 0x10, 0xcf, 0x2e, 0x04, 0xa3, 0x00, 0xfe, 0x44, 0x90, 0x03, 0xe8, 0x42, 0xa5, +0x24, 0x24, 0x44, 0x00, 0x7f, 0xff, 0x89, 0x40, 0x49, 0xfb, 0xba, 0xd6, 0x42, 0x90, 0x24, 0x24, +0x44, 0x10, 0x7f, 0xff, 0x89, 0x21, 0x93, 0x2f, 0x93, 0x4f, 0x8d, 0x25, 0xe3, 0x2a, 0xe8, 0x25, +0x00, 0x03, 0x04, 0x0c, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x21, 0x50, 0x03, 0x03, 0xf0, 0x49, 0xff, +0xa8, 0x65, 0x10, 0x73, 0x04, 0x0c, 0x49, 0xff, 0xfd, 0x91, 0x49, 0xff, 0xde, 0x39, 0x80, 0x27, +0x84, 0x43, 0x80, 0x67, 0x80, 0x87, 0x80, 0xa7, 0x84, 0x05, 0x49, 0xff, 0xb7, 0x79, 0xd5, 0x0d, +0x50, 0x03, 0x03, 0xf0, 0x49, 0xff, 0xa8, 0x52, 0x50, 0x03, 0x03, 0xf0, 0x80, 0x28, 0x49, 0xff, +0xa9, 0x13, 0x84, 0x01, 0x10, 0x03, 0x04, 0x0c, 0x80, 0x28, 0x80, 0x47, 0x3e, 0x09, 0x63, 0xfc, +0x49, 0xff, 0xa7, 0xf6, 0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xb4, 0x3e, 0x19, 0x7e, 0xec, 0x54, 0x80, 0x00, 0xff, 0x3a, 0x00, 0x84, 0x00, 0x3e, 0x29, +0x7e, 0xe4, 0xf0, 0x90, 0x12, 0x1f, 0x80, 0x22, 0x3a, 0x01, 0x04, 0x00, 0x3e, 0x29, 0x7e, 0xdc, +0xf0, 0x8e, 0x12, 0x1f, 0x80, 0x1e, 0x3a, 0x01, 0x04, 0x00, 0x51, 0xcf, 0x80, 0x30, 0xb6, 0x1c, +0x12, 0x1e, 0x00, 0x02, 0x46, 0x20, 0x04, 0x10, 0x46, 0x35, 0x85, 0x04, 0x58, 0x31, 0x88, 0x40, +0x50, 0x7f, 0x80, 0x1c, 0x04, 0xa1, 0x01, 0x09, 0x14, 0x31, 0x01, 0x09, 0x84, 0x20, 0x44, 0x20, +0x00, 0x14, 0x80, 0x07, 0x49, 0xfe, 0x7e, 0x6a, 0xa7, 0xba, 0xa7, 0x3b, 0xa4, 0xfb, 0xa6, 0xbc, +0x00, 0x03, 0x80, 0x12, 0x92, 0xc7, 0x95, 0xb7, 0x54, 0x42, 0x00, 0x1f, 0x92, 0x6e, 0x40, 0x31, +0xb8, 0x08, 0x54, 0x21, 0x00, 0x03, 0x54, 0x54, 0x00, 0x7f, 0x58, 0x42, 0x00, 0x40, 0x40, 0x53, +0x14, 0x04, 0x59, 0xe1, 0x00, 0x1c, 0x40, 0x60, 0x10, 0x09, 0x95, 0xb4, 0x58, 0x31, 0x80, 0x18, +0xaf, 0x3b, 0x84, 0x81, 0x50, 0x8f, 0x80, 0x04, 0xaf, 0x7a, 0x11, 0xe3, 0x80, 0x04, 0xaf, 0x3d, +0xac, 0xfb, 0x10, 0x63, 0x80, 0x12, 0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x80, 0x08, 0x49, 0xfe, +0x7e, 0x3d, 0x00, 0x44, 0x00, 0x00, 0x00, 0x34, 0x00, 0x01, 0x54, 0x42, 0x00, 0x03, 0x58, 0x42, +0x00, 0x08, 0x58, 0x31, 0x80, 0x01, 0x10, 0x44, 0x00, 0x00, 0x10, 0x34, 0x00, 0x01, 0x44, 0x65, +0xb6, 0x58, 0x50, 0x1f, 0x80, 0x40, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x08, 0xdd, 0x26, 0x50, 0x1f, +0x80, 0x38, 0x84, 0x46, 0x50, 0x0f, 0x80, 0x0e, 0xdd, 0x26, 0x80, 0x3c, 0x84, 0x46, 0x50, 0x0f, +0x80, 0x14, 0xdd, 0x26, 0x46, 0x20, 0x04, 0x10, 0x04, 0x31, 0x01, 0x01, 0x44, 0x1f, 0xff, 0x1f, +0x40, 0x31, 0x84, 0x02, 0x14, 0x31, 0x01, 0x01, 0x46, 0x00, 0x04, 0x1d, 0x80, 0x27, 0x44, 0x20, +0x00, 0x14, 0xdd, 0x26, 0x46, 0x00, 0x04, 0x1d, 0x80, 0x28, 0x58, 0x00, 0x00, 0x14, 0x44, 0x20, +0x00, 0x18, 0xdd, 0x26, 0x46, 0x00, 0x04, 0x11, 0x84, 0x24, 0xa8, 0x41, 0x46, 0x00, 0x04, 0x10, +0x58, 0x00, 0x04, 0x10, 0xb4, 0x20, 0x81, 0x00, 0x58, 0x10, 0x80, 0x04, 0xb6, 0x20, 0x84, 0xc0, +0xb4, 0x28, 0x84, 0x0a, 0x54, 0x10, 0x80, 0x40, 0xc1, 0x08, 0x9d, 0xb1, 0x49, 0xff, 0xdd, 0xe2, +0x97, 0xb1, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf5, 0x46, 0x10, 0x04, 0x11, 0x46, 0x00, 0x04, 0x10, +0x84, 0x40, 0xa8, 0x89, 0x14, 0xa0, 0x01, 0x09, 0xec, 0x4c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x5c, 0x3e, 0x19, 0x7e, 0xd0, 0x96, 0x00, 0xf0, 0x83, 0x3a, 0x00, +0x88, 0x00, 0x50, 0x3f, 0x80, 0x88, 0x3a, 0x01, 0x84, 0x24, 0xf0, 0x03, 0xac, 0x98, 0xe6, 0x0f, +0xe8, 0x09, 0x2e, 0x11, 0x8a, 0x73, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x10, 0x3e, 0x09, 0x64, 0x2c, +0xd5, 0x08, 0x2e, 0x11, 0x8a, 0x72, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x08, 0x3e, 0x09, 0x64, 0x4c, +0x49, 0xff, 0xa7, 0x16, 0x48, 0x00, 0x06, 0x6c, 0x3e, 0x09, 0x64, 0x6c, 0x49, 0xff, 0xa7, 0x10, +0x2e, 0x11, 0x8a, 0x75, 0xf0, 0x03, 0x4c, 0x10, 0x00, 0x0d, 0x84, 0x20, 0x3c, 0x1e, 0x62, 0xb3, +0x3c, 0x1e, 0x62, 0xb0, 0x3c, 0x1e, 0x62, 0xb1, 0x3c, 0x1e, 0x62, 0xb2, 0x3e, 0x01, 0x8a, 0x75, +0x46, 0x30, 0x04, 0x12, 0x84, 0x20, 0x50, 0x2f, 0x80, 0x94, 0x58, 0x31, 0x87, 0x20, 0xf1, 0x87, +0xac, 0x52, 0xb6, 0x22, 0xf3, 0x84, 0xf1, 0x8d, 0xf1, 0x82, 0xf1, 0x8c, 0xf1, 0x85, 0xd5, 0x03, +0x84, 0x21, 0xf1, 0x82, 0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xec, 0xf2, 0x02, 0xf1, 0x88, +0x4e, 0x23, 0x00, 0x9a, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0xed, 0x54, 0x11, 0x00, 0x20, +0x54, 0x21, 0x00, 0x3f, 0xc1, 0x03, 0x50, 0x21, 0x7f, 0xc0, 0x46, 0x10, 0x04, 0x11, 0x04, 0x10, +0x80, 0xec, 0x54, 0x10, 0x80, 0x3f, 0x98, 0x51, 0x4e, 0x14, 0x00, 0x04, 0x84, 0x20, 0xd5, 0x02, +0x96, 0x48, 0x3c, 0x2c, 0x62, 0xb0, 0xca, 0x04, 0x3c, 0x3c, 0x62, 0xb1, 0xc3, 0x0c, 0xe2, 0x41, +0xe9, 0x0a, 0x3c, 0x3c, 0x62, 0xb1, 0xe2, 0x23, 0xe9, 0x06, 0x3e, 0x09, 0x64, 0x78, 0x49, 0xff, +0xa6, 0xbf, 0xd5, 0xcf, 0x54, 0x20, 0x80, 0x03, 0xe4, 0x42, 0xe9, 0x38, 0x5e, 0xf0, 0x80, 0x78, +0xe9, 0x06, 0x44, 0x30, 0x00, 0x7f, 0x3c, 0x3e, 0x62, 0xb0, 0xd5, 0x0b, 0x50, 0x30, 0x80, 0x08, +0x3c, 0x3e, 0x62, 0xb0, 0xe4, 0x24, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, 0x62, 0xb1, 0xd5, 0x04, +0x9e, 0x4c, 0x3c, 0x1e, 0x62, 0xb1, 0xf3, 0x08, 0x54, 0x11, 0x80, 0x3f, 0x9d, 0x4c, 0x50, 0x60, +0x80, 0x08, 0x44, 0x30, 0x00, 0x3f, 0x5c, 0x72, 0x80, 0x40, 0x5c, 0x43, 0x00, 0x40, 0x40, 0x61, +0x90, 0x1a, 0x40, 0x51, 0x9c, 0x1a, 0xe6, 0x24, 0xe8, 0x09, 0x84, 0x22, 0x84, 0x1f, 0x84, 0x41, +0xf1, 0x8a, 0xf0, 0x89, 0xf2, 0x8b, 0x84, 0x20, 0xd5, 0x39, 0x84, 0x7f, 0x84, 0x02, 0x84, 0x41, +0x9e, 0x4c, 0xf3, 0x89, 0xf0, 0x8a, 0xf2, 0x8b, 0xd5, 0x31, 0x5e, 0xf0, 0x80, 0x7c, 0xe9, 0x06, +0x44, 0x30, 0x00, 0x7f, 0x3c, 0x3e, 0x62, 0xb0, 0xd5, 0x0a, 0x9c, 0xcc, 0x3c, 0x3e, 0x62, 0xb0, +0xe4, 0x28, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, 0x62, 0xb1, 0xd5, 0x04, 0x8e, 0x28, 0x3c, 0x1e, +0x62, 0xb1, 0xf3, 0x08, 0x54, 0x11, 0x80, 0x3f, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0xa0, 0x80, 0xc5, +0xd5, 0x08, 0x9f, 0x4c, 0xe6, 0x28, 0xe8, 0x03, 0x84, 0xc0, 0xd5, 0x03, 0x50, 0x60, 0xff, 0xf8, +0x9c, 0x4c, 0x5c, 0x30, 0x80, 0x40, 0x44, 0x40, 0x00, 0x3f, 0x40, 0x12, 0x0c, 0x1a, 0x84, 0x01, +0x84, 0x5e, 0x84, 0x7f, 0xf0, 0x89, 0xf2, 0x8a, 0xf3, 0x8b, 0xf0, 0x08, 0x44, 0x2f, 0xff, 0xc0, +0x48, 0x00, 0x00, 0xa3, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0xea, 0x54, 0x11, 0x00, 0x20, +0x54, 0x21, 0x00, 0x3f, 0xc1, 0x03, 0x50, 0x21, 0x7f, 0xc0, 0x46, 0x10, 0x04, 0x11, 0x04, 0x10, +0x80, 0xec, 0x92, 0x28, 0x54, 0x10, 0x80, 0x3f, 0x98, 0x51, 0x4e, 0x14, 0x00, 0x04, 0x84, 0x20, +0xd5, 0x02, 0x96, 0x48, 0x3c, 0x2c, 0x62, 0xb2, 0xca, 0x04, 0x3c, 0x3c, 0x62, 0xb3, 0xc3, 0x0d, +0xe2, 0x41, 0xe9, 0x0b, 0x3c, 0x3c, 0x62, 0xb3, 0xe2, 0x23, 0xe9, 0x07, 0x3e, 0x09, 0x64, 0xcc, +0x49, 0xff, 0xa6, 0x26, 0x48, 0x00, 0x05, 0x7c, 0x54, 0x20, 0x80, 0x03, 0xe4, 0x42, 0xe9, 0x39, +0x5e, 0xf0, 0x80, 0x78, 0xe9, 0x06, 0x44, 0x30, 0x00, 0x7f, 0x3c, 0x3e, 0x62, 0xb2, 0xd5, 0x0b, +0x50, 0x30, 0x80, 0x08, 0x3c, 0x3e, 0x62, 0xb2, 0xe4, 0x24, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, +0x62, 0xb3, 0xd5, 0x04, 0x9e, 0x4c, 0x3c, 0x1e, 0x62, 0xb3, 0xf3, 0x08, 0x44, 0x60, 0x00, 0x3f, +0x40, 0x11, 0xa0, 0x09, 0x54, 0x10, 0x80, 0x3f, 0x9d, 0x4c, 0x50, 0x30, 0x80, 0x08, 0x5c, 0x72, +0x80, 0x40, 0x5c, 0x41, 0x80, 0x40, 0x40, 0x33, 0x10, 0x1a, 0x40, 0x53, 0x1c, 0x1a, 0xe6, 0x24, +0xe8, 0x09, 0x84, 0x22, 0x84, 0x1f, 0x84, 0x41, 0xf1, 0x8a, 0xf0, 0x89, 0xf2, 0x8b, 0x84, 0x20, +0xd5, 0x3a, 0x84, 0x1f, 0x84, 0x42, 0xf0, 0x89, 0x9e, 0x4c, 0xf2, 0x8a, 0x84, 0x01, 0xd5, 0x32, +0x5e, 0xf0, 0x80, 0x7c, 0xe9, 0x06, 0x44, 0x30, 0x00, 0x7f, 0x3c, 0x3e, 0x62, 0xb2, 0xd5, 0x0a, +0x9c, 0xcc, 0x3c, 0x3e, 0x62, 0xb2, 0xe4, 0x28, 0xe8, 0x05, 0x84, 0x40, 0x3c, 0x2e, 0x62, 0xb3, +0xd5, 0x04, 0x8e, 0x28, 0x3c, 0x1e, 0x62, 0xb3, 0xf2, 0x08, 0x40, 0x11, 0x20, 0x09, 0x54, 0x10, +0x80, 0x3f, 0xe6, 0x24, 0xe8, 0x04, 0x84, 0xa0, 0x80, 0x65, 0xd5, 0x08, 0x9f, 0x4c, 0xe6, 0x28, +0xe8, 0x03, 0x84, 0x60, 0xd5, 0x03, 0x50, 0x30, 0xff, 0xf8, 0x9c, 0x4c, 0x84, 0x5e, 0x84, 0x01, +0x5c, 0x60, 0x80, 0x40, 0x44, 0x40, 0x00, 0x3f, 0xf2, 0x8a, 0xf0, 0x89, 0x40, 0x12, 0x18, 0x1a, +0x84, 0x1f, 0xf0, 0x8b, 0xf2, 0x08, 0x40, 0x52, 0xa0, 0x08, 0x40, 0x61, 0xa0, 0x08, 0x40, 0x10, +0xa0, 0x08, 0x44, 0x0f, 0xc0, 0xff, 0x40, 0x31, 0x00, 0x02, 0x40, 0x10, 0x8c, 0x04, 0x40, 0x52, +0x8c, 0x04, 0x40, 0x33, 0x0c, 0x04, 0xf1, 0x8f, 0xf5, 0x91, 0xf3, 0x90, 0x44, 0x00, 0x10, 0x04, +0x49, 0xff, 0xe9, 0x0a, 0x44, 0x00, 0x13, 0x44, 0x49, 0xff, 0xe9, 0x06, 0x46, 0x50, 0x04, 0x11, +0xa1, 0x29, 0x84, 0x33, 0x40, 0x32, 0x04, 0x02, 0xa8, 0xe9, 0x80, 0xc5, 0x04, 0x43, 0x00, 0xd1, +0x40, 0x32, 0x20, 0x09, 0x40, 0x31, 0xa0, 0x08, 0x81, 0x05, 0x14, 0x33, 0x00, 0xd1, 0x84, 0xe0, +0x04, 0x44, 0x00, 0x80, 0x9d, 0xf9, 0x97, 0x24, 0x84, 0x0a, 0xc4, 0x21, 0x49, 0xff, 0xdc, 0x1a, +0x44, 0x30, 0x0b, 0xb8, 0x4c, 0x71, 0xff, 0xf6, 0x46, 0x10, 0x04, 0x11, 0x80, 0x41, 0x80, 0x61, +0x80, 0x81, 0x80, 0xa1, 0x80, 0x01, 0x04, 0x10, 0x80, 0x38, 0x04, 0x21, 0x00, 0x39, 0x04, 0x31, +0x80, 0x3c, 0x04, 0x42, 0x00, 0x3d, 0x04, 0x52, 0x80, 0x3e, 0x04, 0x60, 0x00, 0x3f, 0x3e, 0x09, +0x65, 0x20, 0xb6, 0xdf, 0x49, 0xff, 0xa5, 0x64, 0x48, 0x00, 0x02, 0x0e, 0x46, 0x70, 0x04, 0x12, +0x81, 0x04, 0x04, 0x13, 0x80, 0x4c, 0x8d, 0x01, 0x84, 0x0a, 0xc1, 0x0d, 0x49, 0xff, 0xdb, 0xf2, +0x44, 0x00, 0x0b, 0xb8, 0x4c, 0x80, 0x7f, 0xf7, 0x3e, 0x09, 0x65, 0x68, 0x49, 0xff, 0xa5, 0x50, +0x48, 0x00, 0x01, 0xfa, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x00, 0x24, 0x44, 0x00, 0x13, 0xb0, +0xdd, 0x26, 0xf1, 0x04, 0x44, 0x2f, 0x1f, 0xff, 0xb4, 0x81, 0x44, 0x00, 0x23, 0x20, 0x40, 0x32, +0x08, 0x02, 0xb6, 0x61, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x44, 0x00, 0x27, 0x04, 0x04, 0x42, +0x00, 0xc8, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x08, 0xdd, 0x26, 0x44, 0x00, 0x13, 0x28, 0xdd, 0x26, +0xf3, 0x03, 0xe6, 0x6f, 0xe8, 0x15, 0xf0, 0x02, 0xc8, 0x0a, 0x46, 0x50, 0x04, 0x11, 0x46, 0x40, +0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, 0x58, 0x42, 0x00, 0x20, 0xd5, 0x1d, 0x46, 0x50, 0x04, 0x11, +0x46, 0x40, 0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, 0x58, 0x42, 0x00, 0x80, 0xd5, 0x14, 0xf1, 0x02, +0xc9, 0x0a, 0x46, 0x50, 0x04, 0x11, 0x46, 0x40, 0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, 0x58, 0x42, +0x00, 0x10, 0xd5, 0x09, 0x46, 0x50, 0x04, 0x11, 0x46, 0x40, 0x01, 0xc0, 0x58, 0x52, 0x83, 0x28, +0x58, 0x42, 0x00, 0x40, 0xb6, 0x85, 0x46, 0x60, 0x04, 0x12, 0x44, 0x00, 0x20, 0x04, 0x49, 0xff, +0xe8, 0x6b, 0xa1, 0x71, 0x54, 0x42, 0x80, 0x10, 0xcc, 0x04, 0x58, 0x32, 0x80, 0x10, 0xa8, 0xf1, +0x44, 0x00, 0x21, 0x24, 0x49, 0xff, 0xe8, 0x60, 0x46, 0x40, 0x04, 0x12, 0x44, 0x3f, 0xf5, 0x7c, +0x14, 0x32, 0x00, 0x49, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x04, 0x6c, 0xf2, 0x03, 0x46, 0x70, +0x00, 0x87, 0x58, 0x73, 0x86, 0xa0, 0xe6, 0x4f, 0xe8, 0x45, 0xf0, 0x02, 0x84, 0x20, 0xdd, 0x26, +0xf0, 0x02, 0x84, 0x24, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xf0, 0x02, +0x44, 0x10, 0x00, 0x44, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x26, 0xf0, 0x02, +0x44, 0x10, 0x02, 0x64, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x02, +0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0f, 0x53, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x02, 0x84, 0x24, +0x44, 0x24, 0x01, 0x2c, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x23, 0x0c, 0xf0, 0x58, 0x21, 0x00, 0x06, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x20, 0x25, 0x12, 0x58, 0x21, 0x00, 0x16, +0x44, 0x10, 0x00, 0x44, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x20, 0x00, 0xb9, 0x58, 0x21, 0x0e, 0x9e, +0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0x46, 0x20, 0x08, 0x88, 0xf0, 0x02, 0x44, 0x10, 0x02, 0x64, +0xd5, 0x52, 0xf0, 0x02, 0x84, 0x20, 0xdd, 0x26, 0xf0, 0x02, 0x84, 0x24, 0xdd, 0x26, 0xf0, 0x02, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x02, 0xa8, 0xdd, 0x26, 0xf0, 0x02, +0x44, 0x10, 0x02, 0x10, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x02, 0x54, 0xdd, 0x26, 0xf0, 0x02, +0x44, 0x10, 0x02, 0x60, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x02, +0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0f, 0x57, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x02, 0x84, 0x24, +0x44, 0x24, 0x01, 0x23, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x23, 0x04, 0xf0, 0x58, 0x21, 0x00, 0x06, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x20, 0x14, 0xec, 0x58, 0x21, 0x0d, 0x28, +0x44, 0x10, 0x02, 0xa8, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x20, 0x00, 0xb9, 0x58, 0x21, 0x0e, 0x9e, +0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x23, 0x64, 0x55, 0x58, 0x21, 0x07, 0x77, +0x44, 0x10, 0x02, 0x54, 0xdd, 0x27, 0x46, 0x26, 0x63, 0xca, 0xf0, 0x02, 0x58, 0x21, 0x05, 0x8f, +0x44, 0x10, 0x02, 0x60, 0xdd, 0x27, 0xf0, 0x02, 0x46, 0x20, 0x08, 0x04, 0x44, 0x10, 0x01, 0x14, +0x58, 0x21, 0x00, 0x81, 0xdd, 0x27, 0x44, 0x00, 0x13, 0xb8, 0x49, 0xff, 0xe7, 0xad, 0x44, 0x00, +0x13, 0xbc, 0x49, 0xff, 0xe7, 0xa9, 0x46, 0x50, 0x04, 0x11, 0xf0, 0x02, 0x04, 0x42, 0x80, 0xef, +0x40, 0x30, 0x7c, 0x08, 0x40, 0x31, 0x90, 0x04, 0x84, 0x25, 0x14, 0x32, 0x80, 0xef, 0xf1, 0x8e, +0x85, 0x42, 0x84, 0x42, 0x4c, 0xa1, 0x40, 0x08, 0x46, 0x20, 0x04, 0x11, 0xf3, 0x08, 0x14, 0x31, +0x00, 0xec, 0xd5, 0x40, 0x84, 0x03, 0x4c, 0xa0, 0x40, 0x0c, 0xf1, 0x0c, 0xf3, 0x0b, 0x46, 0x20, +0x04, 0x11, 0x98, 0x4b, 0x58, 0x21, 0x03, 0xb0, 0xf1, 0x85, 0xf0, 0x11, 0xd5, 0x21, 0x84, 0x44, +0x4c, 0xa1, 0x40, 0x16, 0xf3, 0x0c, 0xf0, 0x0a, 0x46, 0x20, 0x04, 0x11, 0xf1, 0x10, 0x98, 0xd8, +0xf3, 0x85, 0x14, 0x11, 0x00, 0xec, 0x4e, 0x34, 0x00, 0x03, 0xd5, 0x15, 0xf0, 0x05, 0x46, 0x30, +0x04, 0x11, 0x58, 0x31, 0x83, 0xb8, 0x58, 0x20, 0x00, 0x10, 0xd5, 0x1b, 0xf1, 0x0c, 0xf3, 0x09, +0x46, 0x20, 0x04, 0x11, 0x98, 0x4b, 0xf1, 0x85, 0xf0, 0x0f, 0x58, 0x21, 0x03, 0xb0, 0xb6, 0x02, +0x4e, 0x14, 0x00, 0x09, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x83, 0xb8, 0x44, 0x20, 0x00, 0x10, +0xd5, 0x08, 0xf1, 0x05, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x83, 0xb8, 0x58, 0x20, 0x80, 0x10, +0xb6, 0x43, 0xf2, 0x03, 0xe6, 0x4f, 0xe8, 0x0d, 0x46, 0x30, 0x04, 0x12, 0x44, 0x20, 0x11, 0x10, +0x46, 0x40, 0x04, 0x12, 0x14, 0x21, 0x81, 0xc1, 0x58, 0x42, 0x07, 0x08, 0x84, 0x40, 0xd5, 0x0d, +0x46, 0x30, 0x04, 0x12, 0x44, 0x20, 0x0d, 0x0d, 0x46, 0x40, 0x04, 0x12, 0x14, 0x21, 0x81, 0xc1, +0x58, 0x42, 0x07, 0x08, 0x44, 0x20, 0x08, 0x08, 0xb6, 0x44, 0x44, 0x00, 0x27, 0x14, 0x49, 0xff, +0xe7, 0x33, 0xf3, 0x02, 0xcb, 0x06, 0x46, 0x20, 0x04, 0x12, 0x14, 0x31, 0x01, 0xc5, 0xd5, 0x07, +0x46, 0x30, 0x04, 0x12, 0x44, 0x20, 0x00, 0x81, 0x14, 0x21, 0x81, 0xc5, 0xf0, 0x02, 0x44, 0x10, +0x02, 0x98, 0x49, 0xff, 0xe9, 0x45, 0x44, 0x00, 0x12, 0x80, 0x49, 0xff, 0xe7, 0x1d, 0xf0, 0x02, +0x84, 0x60, 0x44, 0x10, 0x02, 0x98, 0x50, 0x2f, 0x80, 0x9c, 0xf3, 0xa7, 0x49, 0xff, 0xe7, 0x34, +0xf3, 0x27, 0x92, 0x62, 0x94, 0xda, 0xf0, 0x02, 0x80, 0x43, 0x44, 0x10, 0x02, 0x98, 0xf3, 0xa7, +0x49, 0xff, 0xda, 0x48, 0x46, 0x30, 0x04, 0x11, 0x44, 0x20, 0x00, 0x30, 0x14, 0x21, 0x80, 0xa0, +0x84, 0x42, 0x4c, 0xa1, 0x40, 0x05, 0x84, 0x07, 0x49, 0xff, 0xfb, 0xa2, 0x46, 0x70, 0x04, 0x11, +0x84, 0xc0, 0x04, 0x13, 0x80, 0x80, 0x9d, 0xb1, 0x96, 0x4c, 0x84, 0x0a, 0xc1, 0x20, 0x49, 0xff, +0xda, 0x21, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x60, 0x7f, 0xf6, 0x46, 0x10, 0x04, 0x11, 0x80, 0x41, +0x80, 0x61, 0x80, 0x81, 0x80, 0xa1, 0x80, 0x01, 0x04, 0x10, 0x80, 0x38, 0x04, 0x21, 0x00, 0x39, +0x04, 0x31, 0x80, 0x3c, 0x04, 0x42, 0x00, 0x3d, 0x04, 0x52, 0x80, 0x3e, 0x04, 0x60, 0x00, 0x3f, +0x3e, 0x09, 0x65, 0x74, 0xb6, 0xdf, 0x49, 0xff, 0xa3, 0x6b, 0xd5, 0x13, 0x46, 0x60, 0x04, 0x12, +0x80, 0xe1, 0x04, 0x13, 0x00, 0x4c, 0x9d, 0xf9, 0x84, 0x0a, 0xc1, 0x11, 0x49, 0xff, 0xd9, 0xfa, +0x44, 0x20, 0x03, 0xe8, 0x4c, 0x71, 0x7f, 0xf7, 0x3e, 0x09, 0x65, 0xbc, 0x49, 0xff, 0xa3, 0x58, +0x49, 0xff, 0xda, 0x1e, 0x49, 0xff, 0xe6, 0x9a, 0x48, 0x00, 0x02, 0xaa, 0x84, 0x62, 0x4c, 0xa1, +0xc0, 0x0a, 0x46, 0x10, 0x04, 0x11, 0x04, 0x10, 0x80, 0xef, 0x54, 0x10, 0x80, 0x0f, 0xf1, 0x8c, +0xf1, 0x85, 0x87, 0x80, 0x15, 0xcf, 0x80, 0x06, 0x85, 0x25, 0x50, 0x0f, 0x80, 0x88, 0x39, 0xc0, +0x24, 0x00, 0x46, 0x10, 0x00, 0xb0, 0x40, 0x4e, 0x04, 0x04, 0x40, 0x3e, 0x20, 0x08, 0xf0, 0x02, +0x40, 0x22, 0x0c, 0x04, 0x44, 0x10, 0x02, 0x10, 0x49, 0xff, 0xd9, 0xdc, 0x46, 0x40, 0x04, 0x11, +0x84, 0x68, 0x80, 0xe4, 0x46, 0x58, 0x00, 0x08, 0x80, 0xc4, 0x46, 0x80, 0x04, 0x12, 0xa8, 0xe1, +0x44, 0x30, 0x21, 0x05, 0x84, 0x00, 0xa8, 0x21, 0x14, 0x53, 0x80, 0x99, 0x46, 0x40, 0x04, 0x12, +0x14, 0x53, 0x00, 0x9a, 0x14, 0x34, 0x01, 0xc6, 0x58, 0x42, 0x07, 0x24, 0xb4, 0x64, 0x46, 0x13, +0x80, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x31, 0x84, 0x02, 0xb6, 0x64, 0xf2, 0x02, 0xca, 0x1a, +0x84, 0x64, 0x4c, 0xa1, 0x80, 0x10, 0x84, 0x05, 0x4c, 0xa0, 0x00, 0x11, 0x84, 0x23, 0x4c, 0xa0, +0x80, 0x06, 0x46, 0x20, 0x20, 0x00, 0xb4, 0x64, 0xd5, 0x29, 0x46, 0x04, 0x20, 0x00, 0xb4, 0x64, +0xd5, 0x19, 0x46, 0x10, 0x60, 0x00, 0xb4, 0x64, 0xd5, 0x1b, 0x46, 0x24, 0x60, 0x00, 0xb4, 0x64, +0xd5, 0x1d, 0x84, 0x64, 0x4c, 0xa1, 0x80, 0x12, 0x84, 0x05, 0x4c, 0xa0, 0x00, 0x15, 0x84, 0x23, +0x4c, 0xa0, 0x80, 0x06, 0x46, 0x28, 0x20, 0x00, 0xb4, 0x64, 0xd5, 0x10, 0x46, 0x0c, 0x20, 0x00, +0xb4, 0x64, 0x40, 0x31, 0x80, 0x04, 0xd5, 0x0c, 0x46, 0x18, 0x60, 0x00, 0xb4, 0x64, 0x40, 0x31, +0x84, 0x04, 0xd5, 0x06, 0x46, 0x2c, 0x60, 0x00, 0xb4, 0x64, 0x40, 0x31, 0x88, 0x04, 0xb6, 0x64, +0x80, 0x88, 0x84, 0x61, 0xa8, 0xe4, 0x84, 0x60, 0xa8, 0xe4, 0x46, 0x54, 0x10, 0x06, 0xf0, 0x04, +0x58, 0x52, 0x80, 0x0a, 0xb6, 0xa0, 0x80, 0xc3, 0xf2, 0x04, 0x9d, 0xb1, 0xb4, 0x22, 0x84, 0x0a, +0x54, 0x10, 0xa0, 0x00, 0xc1, 0x07, 0x49, 0xff, 0xd9, 0x5d, 0x44, 0x00, 0x00, 0x64, 0x4c, 0x60, +0x7f, 0xf5, 0x46, 0x50, 0x04, 0x12, 0x80, 0x85, 0x46, 0x30, 0x1f, 0xc0, 0x84, 0x20, 0x14, 0x12, +0x81, 0xc6, 0x14, 0x32, 0x01, 0xc9, 0x80, 0x64, 0x04, 0x31, 0x81, 0xca, 0x3e, 0x09, 0x65, 0xc8, +0x97, 0x98, 0x80, 0x29, 0x80, 0x5c, 0x80, 0x66, 0x49, 0xff, 0xa2, 0xaa, 0x5e, 0xf3, 0x00, 0x50, +0xe8, 0x06, 0x8d, 0x21, 0xe5, 0x2a, 0x4e, 0xf3, 0xff, 0x62, 0xd5, 0x3b, 0x5e, 0xf3, 0x00, 0xa1, +0xe9, 0x05, 0x8f, 0x21, 0x4e, 0x94, 0xff, 0x5b, 0xd5, 0x34, 0xf2, 0x06, 0x84, 0x65, 0x40, 0x41, +0x0c, 0x76, 0x84, 0x04, 0x4c, 0x30, 0x40, 0x05, 0xf1, 0x0e, 0x9c, 0x4e, 0xf1, 0x8e, 0xf2, 0x06, +0x84, 0x65, 0x4c, 0x21, 0x80, 0x27, 0xf0, 0x0e, 0x49, 0xff, 0xe3, 0xca, 0x80, 0xc0, 0x84, 0x01, +0x4c, 0x60, 0x40, 0x1b, 0x80, 0x5c, 0x80, 0x29, 0x3e, 0x09, 0x65, 0xe0, 0x49, 0xff, 0xa2, 0x80, +0x2e, 0x31, 0x8a, 0x59, 0xf1, 0x05, 0x50, 0x4f, 0x80, 0x94, 0x38, 0x62, 0x28, 0x08, 0x96, 0x88, +0x4c, 0x33, 0x40, 0x05, 0xe6, 0x4a, 0xe9, 0x22, 0xd5, 0x03, 0xe6, 0x49, 0xe9, 0x1f, 0x84, 0x20, +0x38, 0x12, 0x28, 0x08, 0xd5, 0x1b, 0xf2, 0x06, 0x9c, 0x91, 0xf2, 0x86, 0x48, 0xff, 0xff, 0x27, +0x84, 0x60, 0x50, 0x2f, 0x80, 0x94, 0x05, 0xcf, 0x80, 0x06, 0x38, 0x31, 0x28, 0x08, 0xe7, 0x2a, +0xe9, 0x06, 0x80, 0x29, 0x3e, 0x09, 0x65, 0xf4, 0x49, 0xff, 0xa2, 0x5a, 0x84, 0x65, 0x4d, 0xc1, +0xc0, 0x06, 0x3e, 0x09, 0x66, 0x18, 0x49, 0xff, 0xa2, 0x53, 0x8d, 0x41, 0x84, 0x06, 0x4c, 0xa0, +0x7e, 0x22, 0xf2, 0x02, 0x50, 0x1f, 0x80, 0x94, 0xca, 0x51, 0xa6, 0x48, 0xc9, 0x0b, 0xf3, 0x02, +0x46, 0x20, 0x04, 0x12, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, +0x81, 0xcb, 0x00, 0x1f, 0x80, 0x95, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x80, 0x22, 0x44, 0x31, +0x00, 0x00, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, +0x80, 0x96, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x00, 0x80, 0x22, 0x14, 0x31, +0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x97, 0xc9, 0x0c, +0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x10, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, +0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x98, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, +0x46, 0x30, 0x60, 0x00, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, +0x81, 0xcb, 0x00, 0x1f, 0x80, 0x99, 0xc9, 0x5f, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x60, 0x10, +0x46, 0x10, 0x04, 0x12, 0x58, 0x21, 0x07, 0x24, 0xd5, 0x51, 0xa6, 0x48, 0xc9, 0x0c, 0x46, 0x20, +0x04, 0x12, 0x80, 0x22, 0x44, 0x32, 0x00, 0x00, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, +0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x95, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x80, 0x22, +0x44, 0x31, 0x00, 0x00, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x23, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, +0x00, 0x1f, 0x80, 0x96, 0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x20, 0x80, 0x22, +0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x97, +0xc9, 0x0c, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, 0x20, 0x30, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, +0x44, 0x20, 0x0f, 0xff, 0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x98, 0xc9, 0x0c, 0x46, 0x20, +0x04, 0x12, 0x46, 0x30, 0x60, 0x20, 0x80, 0x22, 0x14, 0x31, 0x01, 0xc9, 0x44, 0x20, 0x0f, 0xff, +0x14, 0x20, 0x81, 0xcb, 0x00, 0x1f, 0x80, 0x99, 0xc9, 0x0e, 0x46, 0x20, 0x04, 0x12, 0x46, 0x30, +0x60, 0x30, 0x46, 0x10, 0x04, 0x12, 0x58, 0x21, 0x07, 0x24, 0xb6, 0x62, 0x44, 0x20, 0x0f, 0xff, +0x14, 0x20, 0x81, 0xcb, 0x3e, 0x59, 0x7e, 0x90, 0x3a, 0x02, 0x8c, 0x04, 0x50, 0x6f, 0x80, 0x48, +0x80, 0x86, 0x46, 0x70, 0x04, 0x12, 0x46, 0x90, 0x04, 0x12, 0x3a, 0x02, 0x0c, 0x24, 0x83, 0x86, +0x58, 0x73, 0x87, 0x24, 0x85, 0x02, 0x3a, 0x02, 0x8c, 0x04, 0x85, 0x4a, 0x3a, 0x02, 0x0c, 0x24, +0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x00, 0x3a, 0x02, 0x0c, 0x20, +0xf6, 0x02, 0xb4, 0x07, 0x46, 0x1f, 0x80, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x00, 0x04, 0x02, +0x84, 0x44, 0xb6, 0x07, 0x4c, 0x81, 0x00, 0x1a, 0x84, 0x65, 0x4c, 0x81, 0x80, 0x22, 0x84, 0x03, +0x4c, 0x80, 0x00, 0x0b, 0xce, 0x05, 0x46, 0x10, 0x20, 0x00, 0xb4, 0x07, 0xd5, 0x1d, 0x46, 0x20, +0x20, 0x20, 0xb4, 0x07, 0xd5, 0x1f, 0xce, 0x05, 0x46, 0x30, 0x20, 0x10, 0xb4, 0x07, 0xd5, 0x0d, +0x46, 0x10, 0x20, 0x30, 0xb4, 0x07, 0xd5, 0x10, 0xce, 0x05, 0x46, 0x20, 0x60, 0x00, 0xb4, 0x07, +0xd5, 0x11, 0x46, 0x30, 0x60, 0x20, 0xb4, 0x07, 0x40, 0x00, 0x0c, 0x04, 0xd5, 0x0d, 0xce, 0x07, +0x46, 0x10, 0x60, 0x10, 0xb4, 0x07, 0x40, 0x00, 0x04, 0x04, 0xd5, 0x06, 0x46, 0x20, 0x60, 0x30, +0xb4, 0x07, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x07, 0x80, 0x9c, 0xb4, 0xa7, 0x84, 0x60, 0x40, 0x01, +0x94, 0x04, 0xb6, 0x07, 0x04, 0x04, 0x81, 0xca, 0xa6, 0x60, 0x96, 0x80, 0x50, 0x21, 0x7f, 0x80, +0x42, 0x11, 0x04, 0x24, 0x4e, 0x26, 0x00, 0x05, 0x44, 0x10, 0x00, 0x80, 0xd5, 0x05, 0x40, 0x10, +0xa8, 0x56, 0x50, 0x10, 0x80, 0x80, 0x92, 0x08, 0x40, 0x00, 0x20, 0x08, 0x40, 0x00, 0x80, 0x04, +0x46, 0x20, 0x10, 0x00, 0x44, 0x14, 0x00, 0x00, 0x98, 0xd9, 0x14, 0x04, 0x81, 0xca, 0x9d, 0x21, +0x4c, 0x31, 0x7f, 0xdf, 0x8d, 0x01, 0x84, 0x66, 0x4c, 0x81, 0xff, 0x9d, 0xf0, 0x03, 0xe6, 0x0f, +0xe8, 0x05, 0x80, 0x27, 0x44, 0x20, 0x0c, 0x0c, 0xd5, 0x2a, 0xf2, 0x03, 0x50, 0x11, 0x7f, 0xdc, +0x96, 0x48, 0xe6, 0x2d, 0xe8, 0x07, 0x2e, 0x11, 0x8a, 0x59, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x12, +0xd5, 0x0c, 0xf0, 0x03, 0x50, 0x10, 0x7f, 0xcc, 0x96, 0x48, 0xe6, 0x2d, 0xe8, 0x0e, 0x2e, 0x11, +0x8a, 0x59, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x06, 0x80, 0x27, 0x44, 0x20, 0x19, 0x19, 0xd5, 0x0f, +0x80, 0x27, 0x44, 0x20, 0x22, 0x22, 0xd5, 0x0b, 0xf3, 0x03, 0x50, 0x11, 0xff, 0x9e, 0x96, 0x48, +0xe6, 0x31, 0xe8, 0x02, 0xd5, 0x01, 0x80, 0x27, 0x44, 0x20, 0x18, 0x18, 0xb6, 0x41, 0x50, 0x1f, +0x80, 0x94, 0xf3, 0x02, 0xcb, 0x12, 0xa6, 0x88, 0xca, 0x20, 0xa6, 0x89, 0xca, 0x1e, 0xa6, 0x8a, +0xca, 0x1c, 0xa6, 0x8b, 0xca, 0x1a, 0xa6, 0x8c, 0xca, 0x18, 0xa6, 0x8d, 0xf0, 0x0d, 0x84, 0x21, +0x40, 0x00, 0x88, 0x1a, 0xf0, 0x8d, 0xd5, 0x11, 0xa6, 0x88, 0xca, 0x0f, 0xa6, 0x89, 0xca, 0x0d, +0xa6, 0x8a, 0xca, 0x0b, 0xa6, 0x8b, 0xca, 0x09, 0xa6, 0x8c, 0xca, 0x07, 0xa6, 0x8d, 0xf3, 0x07, +0x84, 0x21, 0x40, 0x30, 0x88, 0x1a, 0xf3, 0x87, 0xf0, 0x0d, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x0d, +0xf2, 0x07, 0x4c, 0x20, 0x40, 0x0a, 0xf3, 0x04, 0x44, 0x0f, 0x9f, 0xff, 0xb4, 0x23, 0x40, 0x10, +0x80, 0x02, 0xb6, 0x23, 0xd5, 0x0c, 0xf2, 0x04, 0x44, 0x3f, 0x9f, 0xff, 0xb4, 0x22, 0x40, 0x10, +0x8c, 0x02, 0xb6, 0x22, 0xb4, 0x22, 0x42, 0x10, 0xbc, 0x08, 0xb6, 0x22, 0x49, 0xff, 0xd7, 0x78, +0x49, 0xff, 0xe3, 0xf4, 0x92, 0x00, 0xf1, 0x02, 0x4e, 0x12, 0xf9, 0xbc, 0xec, 0xa4, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x2c, 0x3e, 0x49, 0x7f, 0xa4, 0x96, 0x00, +0x96, 0x48, 0xf0, 0x87, 0xf1, 0x89, 0x3a, 0x02, 0x04, 0x00, 0x96, 0x90, 0x96, 0xd8, 0x3e, 0x49, +0x7f, 0x8c, 0xf0, 0xb0, 0x12, 0x1f, 0x80, 0x62, 0xf2, 0x8b, 0xf3, 0x88, 0x3a, 0x02, 0x0c, 0x04, +0x50, 0x5f, 0x80, 0x84, 0x3e, 0x69, 0x7f, 0x84, 0x3e, 0x89, 0x7f, 0x6c, 0x51, 0xef, 0x80, 0x6c, +0x3a, 0x02, 0x8c, 0x24, 0x50, 0x0f, 0x80, 0x54, 0x3f, 0xc9, 0x7f, 0x64, 0x3e, 0xa9, 0x7f, 0x3c, +0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x84, 0x6c, 0xf0, 0x85, 0x3a, 0x02, 0x04, 0x00, 0x80, 0x45, +0x3a, 0x01, 0x04, 0x20, 0x50, 0x1f, 0x80, 0x9c, 0xf1, 0x84, 0x3a, 0x03, 0x04, 0x00, 0x3e, 0x49, +0x7f, 0x4c, 0xf0, 0xae, 0x12, 0x1f, 0x80, 0x5e, 0x3a, 0x04, 0x0c, 0x04, 0x46, 0x60, 0x00, 0x87, +0x58, 0x63, 0x06, 0xa0, 0x3a, 0x0f, 0x0c, 0x24, 0x3a, 0x04, 0x04, 0x00, 0x3a, 0x0f, 0x04, 0x20, +0x3a, 0x0e, 0x04, 0x00, 0xf0, 0xac, 0x12, 0x1f, 0x80, 0x5a, 0x3a, 0x02, 0x0c, 0x04, 0xf5, 0x05, +0x3a, 0x02, 0x8c, 0x24, 0x3a, 0x02, 0x04, 0x00, 0x3a, 0x02, 0x84, 0x20, 0x3a, 0x05, 0x08, 0x00, +0x3c, 0x4c, 0x5f, 0xd2, 0xf3, 0x04, 0x40, 0x52, 0x40, 0x09, 0x3a, 0x01, 0x88, 0x20, 0x44, 0x10, +0x02, 0x44, 0x10, 0x5f, 0x80, 0xce, 0x12, 0x4f, 0x80, 0x66, 0xf0, 0x07, 0xdd, 0x27, 0x44, 0x00, +0x27, 0x00, 0x49, 0xff, 0xe3, 0xa9, 0x44, 0x00, 0x20, 0x04, 0x49, 0xff, 0xe3, 0xa5, 0x46, 0x40, +0x04, 0x12, 0x44, 0x50, 0x00, 0x42, 0xa9, 0x61, 0xf5, 0x09, 0xc5, 0x70, 0xf0, 0x07, 0x84, 0x20, +0xdd, 0x27, 0xf0, 0x07, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x06, 0x57, 0x84, 0x20, 0xdd, 0x26, +0xf0, 0x07, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x23, 0x80, 0x70, 0x58, 0x21, +0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, +0xf0, 0x07, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, +0xf0, 0x07, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, +0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, +0xf0, 0x07, 0x44, 0x20, 0xb8, 0xb8, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x10, +0x84, 0xa8, 0x14, 0x52, 0x01, 0x48, 0x44, 0x10, 0x02, 0x0c, 0xf0, 0x07, 0xdd, 0x27, 0xf0, 0x07, +0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0x50, 0x80, 0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x26, 0x84, 0xe0, 0x50, 0x6f, 0x80, 0xc8, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, 0x80, 0x46, +0x49, 0xff, 0xe3, 0x62, 0xf1, 0x32, 0x9d, 0xf9, 0x54, 0x10, 0x84, 0x00, 0x97, 0xf9, 0x84, 0x05, +0xc1, 0x07, 0x49, 0xff, 0xd6, 0x67, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x70, 0x7f, 0xef, 0x46, 0x40, +0x04, 0x10, 0x84, 0xa2, 0x14, 0x52, 0x01, 0x48, 0xd5, 0x73, 0xf0, 0x07, 0xf1, 0x09, 0xdd, 0x27, +0xf1, 0x09, 0xf0, 0x07, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0e, 0x53, 0xdd, 0x26, 0xf0, 0x07, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x23, 0x80, 0x70, 0x58, 0x21, 0x00, 0x06, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, 0xf0, 0x07, +0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x26, 0xf0, 0x07, +0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, 0x03, 0xbc, +0x44, 0x10, 0x01, 0x30, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, 0xf0, 0x07, +0x44, 0x20, 0xa4, 0xa4, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x10, 0x84, 0xa8, +0x14, 0x52, 0x01, 0x48, 0x44, 0x10, 0x02, 0x0c, 0xf0, 0x07, 0xdd, 0x27, 0xf0, 0x07, 0x46, 0x20, +0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, 0xdd, 0x26, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x27, +0xf0, 0x07, 0x46, 0x20, 0x50, 0x80, 0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x26, +0xf7, 0x09, 0x50, 0x6f, 0x80, 0xc8, 0xf0, 0x07, 0x44, 0x10, 0x02, 0x00, 0x80, 0x46, 0x49, 0xff, +0xe2, 0xf3, 0xf1, 0x32, 0x9d, 0xf9, 0x54, 0x10, 0x84, 0x00, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, +0x49, 0xff, 0xd5, 0xf8, 0x44, 0x10, 0x03, 0xe8, 0x4c, 0x70, 0xff, 0xef, 0x46, 0x40, 0x04, 0x10, +0x84, 0xa2, 0x14, 0x52, 0x01, 0x48, 0x84, 0x20, 0xf0, 0x07, 0x49, 0xff, 0xe1, 0x13, 0x46, 0x60, +0x00, 0x89, 0x58, 0x63, 0x00, 0x24, 0x44, 0x00, 0x20, 0x88, 0xdd, 0x26, 0x44, 0x00, 0x23, 0x00, +0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x84, 0xe0, 0x85, 0x21, 0x81, 0x04, 0x14, 0x92, 0x00, 0x04, +0xa9, 0xe4, 0x80, 0xa4, 0x84, 0x82, 0x14, 0x44, 0x00, 0x22, 0x44, 0x40, 0x74, 0x08, 0x14, 0x42, +0x80, 0xc0, 0x44, 0x00, 0x10, 0x04, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, +0x84, 0xa8, 0xb6, 0xe4, 0xb6, 0xa4, 0xb6, 0xe4, 0x44, 0x00, 0x20, 0x80, 0xdd, 0x26, 0x46, 0x40, +0x04, 0x12, 0x44, 0x53, 0x00, 0x01, 0x14, 0x52, 0x00, 0x20, 0x44, 0x00, 0x20, 0x84, 0xdd, 0x26, +0x46, 0x40, 0x04, 0x12, 0x44, 0x52, 0x00, 0x00, 0x14, 0x52, 0x00, 0x21, 0x44, 0x00, 0x27, 0x18, +0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x46, 0x54, 0x00, 0x02, 0x58, 0x52, 0x81, 0x01, 0x14, 0x52, +0x01, 0xc6, 0x44, 0x00, 0x27, 0x3c, 0xdd, 0x26, 0x46, 0x40, 0x04, 0x12, 0x46, 0x58, 0x00, 0x00, +0x14, 0x52, 0x01, 0xcf, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x26, +0x44, 0x00, 0x27, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x29, 0x80, 0xdd, 0x26, 0xf3, 0x07, 0x46, 0x08, +0x00, 0x00, 0x40, 0xa1, 0xf8, 0x08, 0x58, 0x00, 0x00, 0x12, 0x46, 0x90, 0x04, 0x12, 0x81, 0x09, +0x80, 0xa8, 0x46, 0x64, 0x80, 0x20, 0x59, 0xc1, 0x80, 0x80, 0x40, 0xa5, 0x00, 0x04, 0x58, 0x63, +0x00, 0x0c, 0x80, 0x85, 0x15, 0xc4, 0x81, 0xc5, 0x14, 0xa4, 0x02, 0x4d, 0x14, 0x62, 0x82, 0x60, +0x44, 0x50, 0x00, 0x60, 0x14, 0x52, 0x03, 0x04, 0x04, 0x62, 0x03, 0x05, 0x80, 0xa4, 0x58, 0x63, +0x00, 0x0c, 0x14, 0x62, 0x03, 0x05, 0x44, 0x41, 0x00, 0x00, 0x14, 0x42, 0x81, 0xc0, 0x84, 0x05, +0x49, 0xff, 0xd5, 0x68, 0xf1, 0x08, 0x46, 0x00, 0x92, 0xf5, 0x40, 0x30, 0xf0, 0x08, 0x46, 0x50, +0x04, 0x12, 0x58, 0x00, 0x09, 0x04, 0x9e, 0x42, 0x40, 0x01, 0x80, 0x04, 0x58, 0x52, 0x87, 0x74, +0x40, 0x11, 0x84, 0x04, 0xf0, 0x8c, 0xf7, 0x8a, 0xf5, 0x88, 0xf1, 0x8d, 0xf3, 0x09, 0x4e, 0x32, +0x01, 0x41, 0x2e, 0x71, 0x8a, 0x72, 0x44, 0x65, 0xb6, 0x58, 0x4e, 0x73, 0x00, 0x9e, 0x50, 0x1f, +0x80, 0xc0, 0x84, 0x46, 0x50, 0x0f, 0x80, 0xa8, 0xdd, 0x26, 0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, +0x80, 0x84, 0x44, 0x20, 0x00, 0x18, 0xdd, 0x26, 0x46, 0x80, 0x04, 0x12, 0x04, 0xaf, 0x80, 0x07, +0x05, 0xcf, 0x80, 0x0b, 0x4f, 0xc3, 0x00, 0x23, 0x50, 0x5f, 0x80, 0xa8, 0x38, 0x22, 0x9c, 0x00, +0x44, 0x11, 0x01, 0x00, 0x94, 0x94, 0x40, 0x21, 0x04, 0x04, 0x80, 0x0a, 0x44, 0x10, 0x02, 0x44, +0x49, 0xff, 0xd5, 0x38, 0x50, 0x5f, 0x80, 0x3c, 0x46, 0x00, 0x92, 0xf5, 0x38, 0x32, 0x9e, 0x02, +0x40, 0x23, 0xf0, 0x08, 0x46, 0x10, 0x04, 0x12, 0x58, 0x00, 0x09, 0x02, 0x40, 0x21, 0x00, 0x04, +0x14, 0x34, 0x01, 0xc1, 0x14, 0x20, 0x81, 0xda, 0xd5, 0x11, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, +0x01, 0x80, 0x80, 0x0a, 0x49, 0xff, 0xd5, 0x1e, 0x44, 0x10, 0x0a, 0x0a, 0x14, 0x14, 0x01, 0xc1, +0x46, 0x20, 0x04, 0x12, 0xf1, 0x0d, 0x14, 0x11, 0x01, 0xda, 0x84, 0xc0, 0x44, 0x00, 0x01, 0xf4, +0x49, 0xff, 0xd5, 0x00, 0xf5, 0x08, 0x9d, 0xb1, 0xb4, 0x05, 0x97, 0xb1, 0x54, 0x00, 0x00, 0x08, +0xc0, 0x05, 0x44, 0x00, 0x27, 0x10, 0x4c, 0x60, 0x7f, 0xf3, 0x84, 0x05, 0x49, 0xff, 0xd4, 0xf2, +0x46, 0x60, 0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x63, 0x07, 0x68, 0x58, 0x10, 0x89, 0x00, +0xb6, 0x26, 0x84, 0x05, 0x49, 0xff, 0xd4, 0xe6, 0x4f, 0xc3, 0x00, 0x0c, 0x46, 0x50, 0x92, 0xf5, +0x40, 0x13, 0xf0, 0x08, 0x58, 0x52, 0x89, 0x04, 0x40, 0x10, 0x94, 0x04, 0xb6, 0x26, 0xd5, 0x04, +0xf0, 0x0c, 0x84, 0xea, 0xb6, 0x06, 0x84, 0xc0, 0x44, 0x00, 0x01, 0xf4, 0x49, 0xff, 0xd4, 0xd2, +0xf3, 0x08, 0x9d, 0xb1, 0xb4, 0x03, 0x97, 0xb1, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x04, 0x44, 0x50, +0x27, 0x10, 0xde, 0xf3, 0x84, 0x05, 0x49, 0xff, 0xd4, 0xc5, 0x46, 0x20, 0x04, 0x12, 0x46, 0x10, +0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x80, 0x62, 0x14, 0x11, 0x01, 0xda, 0x84, 0x21, 0xa8, 0x5c, +0x84, 0x20, 0xa8, 0x5c, 0x9d, 0xf9, 0x84, 0x05, 0x49, 0xff, 0xd4, 0xb4, 0xe6, 0xe6, 0x4e, 0xf3, +0xff, 0x7b, 0x48, 0x00, 0x01, 0x66, 0x50, 0x1f, 0x80, 0xb8, 0x84, 0x46, 0x50, 0x0f, 0x80, 0xa8, +0xdd, 0x26, 0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, 0x80, 0x6c, 0x44, 0x20, 0x00, 0x18, 0xdd, 0x26, +0x46, 0x80, 0x04, 0x12, 0x04, 0xaf, 0x80, 0x07, 0x05, 0xcf, 0x80, 0x0b, 0x84, 0xe0, 0x4f, 0xc3, +0x00, 0x23, 0x50, 0x5f, 0x80, 0xa8, 0x38, 0x22, 0x9c, 0x00, 0x44, 0x11, 0x01, 0x00, 0x94, 0x94, +0x40, 0x21, 0x04, 0x04, 0x80, 0x0a, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd4, 0x9b, 0x50, 0x5f, +0x80, 0x3c, 0x46, 0x00, 0x92, 0xf5, 0x38, 0x32, 0x9e, 0x02, 0x40, 0x23, 0xf0, 0x08, 0x46, 0x10, +0x04, 0x12, 0x58, 0x00, 0x09, 0x02, 0x40, 0x21, 0x00, 0x04, 0x14, 0x34, 0x01, 0xc1, 0x14, 0x20, +0x81, 0xda, 0xd5, 0x11, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, 0x01, 0x80, 0x80, 0x0a, 0x49, 0xff, +0xd4, 0x81, 0x44, 0x10, 0x0a, 0x0a, 0x14, 0x14, 0x01, 0xc1, 0x46, 0x20, 0x04, 0x12, 0xf1, 0x0d, +0x14, 0x11, 0x01, 0xda, 0x84, 0xc0, 0x44, 0x00, 0x01, 0xf4, 0x49, 0xff, 0xd4, 0x63, 0xf5, 0x08, +0x9d, 0xb1, 0xb4, 0x05, 0x97, 0xb1, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x05, 0x44, 0x00, 0x27, 0x10, +0x4c, 0x60, 0x7f, 0xf3, 0x84, 0x05, 0x49, 0xff, 0xd4, 0x55, 0x46, 0x60, 0x04, 0x12, 0x46, 0x10, +0x92, 0xf5, 0x58, 0x63, 0x07, 0x68, 0x58, 0x10, 0x89, 0x00, 0xb6, 0x26, 0x84, 0x05, 0x49, 0xff, +0xd4, 0x49, 0x4f, 0xc3, 0x00, 0x0c, 0x46, 0x50, 0x92, 0xf5, 0x40, 0x13, 0xf0, 0x08, 0x58, 0x52, +0x89, 0x04, 0x40, 0x10, 0x94, 0x04, 0xb6, 0x26, 0xd5, 0x04, 0xf0, 0x0c, 0x84, 0xea, 0xb6, 0x06, +0x84, 0xc0, 0x44, 0x00, 0x01, 0xf4, 0x49, 0xff, 0xd4, 0x35, 0xf3, 0x08, 0x9d, 0xb1, 0xb4, 0x03, +0x97, 0xb1, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x04, 0x44, 0x50, 0x27, 0x10, 0xde, 0xf3, 0x84, 0x05, +0x49, 0xff, 0xd4, 0x28, 0x46, 0x20, 0x04, 0x12, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, +0x80, 0x62, 0x14, 0x11, 0x01, 0xda, 0x84, 0x21, 0xa8, 0x5c, 0x84, 0x20, 0xa8, 0x5c, 0x9d, 0xf9, +0x84, 0x05, 0x49, 0xff, 0xd4, 0x17, 0xe6, 0xe6, 0x4e, 0xf3, 0xff, 0x7b, 0x48, 0x00, 0x00, 0xc9, +0x2e, 0x11, 0x8a, 0x73, 0x44, 0x65, 0xb6, 0x58, 0xc9, 0x62, 0x50, 0x1f, 0x80, 0xb0, 0x84, 0x46, +0x50, 0x0f, 0x80, 0xa8, 0xdd, 0x26, 0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, 0x80, 0x54, 0x44, 0x20, +0x00, 0x18, 0x47, 0xc0, 0x04, 0x12, 0x46, 0x80, 0x04, 0x12, 0xdd, 0x26, 0x04, 0x9f, 0x80, 0x09, +0x58, 0x84, 0x07, 0x68, 0x50, 0xaf, 0x80, 0x3c, 0x50, 0x5f, 0x80, 0xa8, 0x38, 0x22, 0xa4, 0x00, +0x44, 0x11, 0x01, 0x00, 0xf0, 0x07, 0x94, 0x94, 0x40, 0x21, 0x04, 0x04, 0x44, 0x10, 0x02, 0x44, +0x49, 0xff, 0xd3, 0xf8, 0x46, 0x50, 0x92, 0xf5, 0xb4, 0x6a, 0x40, 0x74, 0xf0, 0x08, 0x58, 0x52, +0x89, 0x02, 0x40, 0x13, 0x94, 0x04, 0x14, 0x3e, 0x01, 0xc1, 0xb6, 0x28, 0x84, 0xc0, 0xf1, 0x08, +0x9d, 0xb1, 0xb4, 0x01, 0x97, 0xb1, 0x54, 0x10, 0x00, 0x08, 0x84, 0x05, 0xc1, 0x06, 0x49, 0xff, +0xd3, 0xd1, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf4, 0x46, 0x00, 0x92, 0xf5, 0x58, 0x00, 0x09, 0x04, +0x9e, 0x44, 0x40, 0x23, 0x80, 0x04, 0xb6, 0x28, 0xb6, 0x48, 0x84, 0xc0, 0xf1, 0x08, 0x9d, 0xb1, +0xb4, 0x01, 0x97, 0xb1, 0x54, 0x10, 0x00, 0x08, 0x84, 0x05, 0xc1, 0x06, 0x49, 0xff, 0xd3, 0xba, +0x44, 0x50, 0x03, 0xe8, 0xde, 0xf4, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x8d, 0x21, +0x84, 0x06, 0xb6, 0x28, 0x8d, 0x44, 0x4c, 0x90, 0x7f, 0xb9, 0xd5, 0x62, 0x50, 0x1f, 0x80, 0xcc, +0x84, 0x43, 0x50, 0x0f, 0x80, 0xa8, 0xdd, 0x26, 0x50, 0x0f, 0x80, 0x3c, 0x50, 0x1f, 0x80, 0x9c, +0x84, 0x4c, 0x47, 0xc0, 0x04, 0x12, 0x46, 0x80, 0x04, 0x12, 0xdd, 0x26, 0x04, 0x9f, 0x80, 0x09, +0x58, 0x84, 0x07, 0x68, 0x50, 0xaf, 0x80, 0x3c, 0x50, 0x1f, 0x80, 0xa8, 0x38, 0x20, 0xa4, 0x00, +0x44, 0x31, 0x01, 0x00, 0xf0, 0x07, 0x94, 0x94, 0x40, 0x21, 0x0c, 0x04, 0x44, 0x10, 0x02, 0x44, +0x49, 0xff, 0xd3, 0x98, 0x50, 0x14, 0x80, 0x03, 0x46, 0x00, 0x92, 0xf5, 0xb4, 0x6a, 0x40, 0x70, +0xf0, 0x08, 0x58, 0x00, 0x09, 0x02, 0x40, 0x23, 0x80, 0x04, 0x14, 0x3e, 0x01, 0xc1, 0xb6, 0x48, +0x84, 0xc0, 0xf1, 0x08, 0x9d, 0xb1, 0xb4, 0x01, 0x97, 0xb1, 0x54, 0x10, 0x00, 0x08, 0x84, 0x05, +0xc1, 0x06, 0x49, 0xff, 0xd3, 0x6f, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf4, 0x46, 0x00, 0x92, 0xf5, +0x58, 0x00, 0x09, 0x04, 0x9e, 0x84, 0x40, 0x13, 0x80, 0x04, 0xb6, 0x48, 0xb6, 0x28, 0x84, 0xc0, +0xf1, 0x08, 0x9d, 0xb1, 0xb4, 0x01, 0x97, 0xb1, 0x54, 0x10, 0x00, 0x08, 0x84, 0x05, 0xc1, 0x06, +0x49, 0xff, 0xd3, 0x58, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf4, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, +0x89, 0x00, 0x8d, 0x21, 0x84, 0x03, 0xb6, 0x28, 0x8d, 0x44, 0x4c, 0x90, 0x7f, 0xb7, 0xf1, 0x07, +0x84, 0x61, 0x4c, 0x11, 0xc0, 0x22, 0x46, 0x10, 0x04, 0x12, 0x80, 0x41, 0x80, 0x61, 0x80, 0x81, +0x80, 0xa1, 0x81, 0x01, 0x80, 0xe1, 0x80, 0xc1, 0x04, 0x10, 0x81, 0xe6, 0x04, 0x21, 0x01, 0xe7, +0x04, 0x31, 0x81, 0xe8, 0x04, 0x42, 0x01, 0xe9, 0x04, 0x52, 0x81, 0xf0, 0x04, 0x84, 0x01, 0xf1, +0x04, 0x73, 0x81, 0xf2, 0x04, 0x63, 0x01, 0xf3, 0x3e, 0x09, 0x66, 0x40, 0xb7, 0x1f, 0xf7, 0x81, +0xf6, 0x82, 0x49, 0xff, 0x9c, 0x8d, 0xf5, 0x0a, 0x84, 0x02, 0x9d, 0x69, 0xf5, 0x8a, 0x4c, 0x50, +0x7d, 0xcf, 0x49, 0xff, 0xd3, 0x4d, 0x49, 0xff, 0xdf, 0xc9, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, +0xdf, 0xeb, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x80, 0x04, 0x84, 0xe0, 0x84, 0x68, 0xb6, 0xe1, +0xb6, 0x61, 0xb6, 0xe1, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xdf, 0xb8, 0x84, 0x01, 0xa8, 0x34, +0x49, 0xff, 0xd3, 0x08, 0xa9, 0xf4, 0xf1, 0x0b, 0xc9, 0x1f, 0xf3, 0x07, 0x84, 0xa1, 0xdb, 0x1c, +0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x01, 0xda, 0x3c, 0x1e, 0x73, 0xbb, 0x46, 0x00, 0x04, 0x12, +0x58, 0x00, 0x07, 0x80, 0x3e, 0x39, 0xce, 0xec, 0x46, 0x5f, 0xfb, 0xed, 0xb4, 0x40, 0x98, 0x43, +0x58, 0x52, 0x88, 0x84, 0x98, 0x4d, 0xb6, 0x41, 0x46, 0x10, 0x04, 0x12, 0x9c, 0x04, 0x58, 0x10, +0x87, 0xd4, 0x4c, 0x00, 0xff, 0xf1, 0x3e, 0x09, 0x66, 0xa0, 0x49, 0xff, 0x9c, 0x49, 0xec, 0xd4, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xf4, 0x3e, 0x49, +0x80, 0x28, 0x96, 0x00, 0x96, 0x48, 0x96, 0x90, 0xf0, 0x8d, 0xf1, 0x8e, 0xf2, 0x90, 0x3a, 0x02, +0x08, 0x00, 0x50, 0x5f, 0x80, 0xe4, 0x3e, 0x49, 0x80, 0x20, 0x3a, 0x02, 0x84, 0x24, 0x50, 0x8f, +0x80, 0xf0, 0x3e, 0x79, 0x80, 0x18, 0x3a, 0x02, 0x04, 0x00, 0x96, 0xd8, 0x3a, 0x04, 0x04, 0x20, +0x3e, 0x49, 0x7f, 0xf0, 0x3a, 0x03, 0x84, 0x00, 0x50, 0x7f, 0x80, 0x70, 0xae, 0xa8, 0xf3, 0x91, +0xf0, 0xbe, 0x12, 0x14, 0x00, 0x06, 0x3a, 0x02, 0x0c, 0x04, 0x83, 0x87, 0x50, 0x5f, 0x80, 0x94, +0x50, 0x6f, 0x80, 0xb4, 0x3f, 0xe9, 0x7f, 0xd0, 0x3a, 0x0e, 0x0c, 0x24, 0x50, 0x0f, 0x80, 0xcc, +0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x84, 0x6c, 0x46, 0x80, 0x00, 0x87, 0x58, 0x84, 0x06, 0xa0, +0xf0, 0x89, 0x3a, 0x02, 0x0c, 0x04, 0xf5, 0x8b, 0xf6, 0x8a, 0x3a, 0x0e, 0x0c, 0x24, 0x3c, 0xac, +0x60, 0x05, 0x80, 0xbe, 0x3a, 0x02, 0x8c, 0x04, 0x40, 0x95, 0x40, 0x09, 0xb4, 0x84, 0x10, 0x9f, +0x81, 0x06, 0xb6, 0x9c, 0xf4, 0x0b, 0x12, 0xaf, 0x80, 0x82, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, +0x8c, 0x00, 0x3a, 0x02, 0x0c, 0x20, 0x3e, 0x49, 0x7f, 0xb8, 0x3a, 0x02, 0x0c, 0x04, 0xf5, 0x0a, +0x3a, 0x02, 0x8c, 0x24, 0x3e, 0x39, 0x7f, 0xac, 0x3a, 0x02, 0x04, 0x00, 0x3a, 0x02, 0x84, 0x20, +0x3a, 0x01, 0x88, 0x00, 0xf5, 0x09, 0x3a, 0x02, 0x88, 0x20, 0x44, 0x10, 0x02, 0x44, 0xf0, 0x0d, +0xdd, 0x27, 0x44, 0x00, 0x27, 0x00, 0x49, 0xff, 0xdf, 0x3f, 0x44, 0x00, 0x20, 0x04, 0x49, 0xff, +0xdf, 0x3b, 0x46, 0x40, 0x04, 0x12, 0x44, 0x00, 0x00, 0x42, 0xa8, 0x21, 0xf6, 0x0e, 0xc6, 0x75, +0xf0, 0x0d, 0x84, 0x20, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x06, 0x57, +0x84, 0x20, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x23, +0x80, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, +0x01, 0x14, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x44, 0x10, +0x01, 0x14, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, +0xab, 0x90, 0x58, 0x21, 0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, +0x02, 0x10, 0xdd, 0x27, 0xf0, 0x0d, 0x44, 0x20, 0xa8, 0xa8, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x28, +0x46, 0x40, 0x04, 0x10, 0x84, 0x08, 0x14, 0x02, 0x01, 0x48, 0x44, 0x10, 0x02, 0x0c, 0xf0, 0x0d, +0x50, 0x6f, 0x81, 0x00, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, +0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x50, 0x80, +0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x28, 0x84, 0xe0, 0xf0, 0x0d, 0x44, 0x10, +0x02, 0x00, 0x80, 0x46, 0x49, 0xff, 0xde, 0xf8, 0xf1, 0x40, 0x9d, 0xf9, 0x54, 0x10, 0x84, 0x00, +0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd1, 0xfd, 0x44, 0x00, 0x03, 0xe8, 0x4c, 0x70, +0x7f, 0xef, 0x46, 0x40, 0x04, 0x10, 0x84, 0x02, 0x14, 0x02, 0x01, 0x48, 0x3e, 0x09, 0x66, 0xb4, +0x49, 0xff, 0x9b, 0x56, 0x48, 0x00, 0x00, 0x78, 0xf0, 0x0d, 0xf1, 0x0e, 0x50, 0x6f, 0x81, 0x00, +0xdd, 0x27, 0xf1, 0x0e, 0xf0, 0x0d, 0x46, 0x2a, 0x00, 0x56, 0x58, 0x21, 0x0e, 0x53, 0xdd, 0x28, +0xf0, 0x0d, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x23, 0x80, 0x70, 0x58, 0x21, +0x00, 0x06, 0x44, 0x10, 0x00, 0x10, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x27, +0xf0, 0x0d, 0x46, 0x20, 0x04, 0x08, 0x58, 0x21, 0x02, 0x95, 0x44, 0x10, 0x01, 0x14, 0xdd, 0x28, +0xf0, 0x0d, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0xa8, 0x90, 0x58, 0x21, +0x03, 0xbc, 0x44, 0x10, 0x01, 0x30, 0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x27, +0xf0, 0x0d, 0x44, 0x20, 0xb8, 0xb8, 0x44, 0x10, 0x02, 0x10, 0xdd, 0x28, 0x3e, 0x09, 0x66, 0xc0, +0x49, 0xff, 0x9b, 0x16, 0x46, 0x40, 0x04, 0x10, 0x84, 0x08, 0x14, 0x02, 0x01, 0x48, 0x44, 0x10, +0x02, 0x0c, 0xf0, 0x0d, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x04, 0xf0, 0x44, 0x10, 0x02, 0x0c, +0xdd, 0x28, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x27, 0xf0, 0x0d, 0x46, 0x20, 0x50, 0x80, +0x58, 0x21, 0x04, 0x0f, 0x44, 0x10, 0x02, 0x00, 0xdd, 0x28, 0xf7, 0x0e, 0xf0, 0x0d, 0x44, 0x10, +0x02, 0x00, 0x80, 0x46, 0x49, 0xff, 0xde, 0x80, 0xf1, 0x40, 0x9d, 0xf9, 0x54, 0x10, 0x84, 0x00, +0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xd1, 0x85, 0x44, 0x10, 0x03, 0xe8, 0x4c, 0x70, +0xff, 0xef, 0x46, 0x40, 0x04, 0x10, 0x84, 0x02, 0x14, 0x02, 0x01, 0x48, 0x84, 0x21, 0xf0, 0x0d, +0x49, 0xff, 0xdc, 0xa0, 0x46, 0x40, 0x04, 0x12, 0x84, 0x60, 0x84, 0x01, 0xa8, 0x24, 0xa8, 0xe4, +0xf3, 0x8c, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, 0x80, 0x24, 0x44, 0x00, 0x20, 0x88, 0xdd, 0x27, +0x46, 0x80, 0x04, 0x12, 0x44, 0x00, 0x23, 0x00, 0x81, 0x28, 0xdd, 0x27, 0x44, 0x20, 0x74, 0x08, +0x84, 0xc2, 0x14, 0x64, 0x00, 0x22, 0x14, 0x24, 0x80, 0xc0, 0x44, 0x00, 0x10, 0x04, 0xdd, 0x27, +0x44, 0x00, 0x27, 0x04, 0xdd, 0x27, 0x44, 0x00, 0x20, 0x80, 0xdd, 0x27, 0x44, 0x00, 0x20, 0x84, +0xdd, 0x27, 0x46, 0x50, 0x04, 0x12, 0xf5, 0x8f, 0xf3, 0x0c, 0xf0, 0x0f, 0x46, 0x40, 0x04, 0x11, +0x58, 0x42, 0x00, 0x04, 0x58, 0x00, 0x00, 0x80, 0x87, 0x88, 0xf0, 0x8f, 0xb6, 0x64, 0x15, 0xc2, +0x00, 0x00, 0xb6, 0x64, 0x14, 0x64, 0x00, 0x22, 0x44, 0x60, 0x74, 0x08, 0x14, 0x64, 0x80, 0xc0, +0x44, 0x03, 0x00, 0x01, 0xf6, 0x0f, 0x80, 0x45, 0x83, 0xc2, 0x46, 0xa4, 0x00, 0x02, 0x80, 0xa2, +0x46, 0x18, 0x00, 0x00, 0xb6, 0x06, 0x58, 0xa5, 0x01, 0x01, 0x44, 0x02, 0x00, 0x00, 0xb6, 0x64, +0x15, 0xc2, 0x00, 0x00, 0xb6, 0x64, 0x14, 0x01, 0x00, 0x21, 0x14, 0xaf, 0x01, 0xc6, 0x14, 0x12, +0x81, 0xcf, 0xf3, 0x8c, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x27, 0x44, 0x00, 0x29, 0x34, 0xdd, 0x27, +0xf1, 0x0d, 0x46, 0x28, 0x00, 0x00, 0x46, 0x90, 0x04, 0x12, 0x40, 0x00, 0xf8, 0x08, 0x81, 0x09, +0x58, 0x21, 0x00, 0x12, 0x40, 0x00, 0x08, 0x04, 0x80, 0xa8, 0x46, 0x74, 0x80, 0x10, 0x80, 0x85, +0x58, 0xa0, 0x80, 0x80, 0x14, 0xa4, 0x81, 0xc5, 0x14, 0x04, 0x02, 0x4d, 0x58, 0x73, 0x80, 0x06, +0x44, 0x01, 0x00, 0x00, 0x14, 0x72, 0x82, 0x60, 0x14, 0x02, 0x01, 0xc0, 0xf5, 0x0e, 0xf3, 0x0c, +0x4e, 0x52, 0x00, 0xfb, 0x2e, 0x41, 0x8a, 0x72, 0xf0, 0x11, 0x50, 0x8f, 0x80, 0xd8, 0x40, 0x60, +0x70, 0x08, 0x44, 0x75, 0xb6, 0x58, 0x50, 0x9f, 0x80, 0x4c, 0xcc, 0x77, 0xf4, 0x8c, 0x50, 0x1f, +0x80, 0xe4, 0x84, 0x49, 0x80, 0x08, 0xdd, 0x27, 0x50, 0x1f, 0x80, 0x70, 0x80, 0x09, 0x44, 0x20, +0x00, 0x24, 0xdd, 0x27, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x01, 0x40, 0x13, 0x04, 0x04, +0xf4, 0x0c, 0x46, 0xa0, 0x04, 0x12, 0x83, 0x8a, 0xf1, 0x8e, 0x80, 0xc4, 0xf2, 0x10, 0xca, 0x2e, +0x50, 0x3f, 0x80, 0xd8, 0x38, 0x21, 0x98, 0x00, 0x44, 0x51, 0x01, 0x00, 0xf0, 0x0d, 0x94, 0x94, +0x40, 0x21, 0x14, 0x04, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd0, 0xd4, 0x38, 0x04, 0x9a, 0x02, +0x14, 0x05, 0x01, 0xc1, 0xe6, 0xc6, 0xe8, 0x0c, 0x46, 0x20, 0x92, 0xf5, 0x40, 0x03, 0x70, 0x08, +0x58, 0x21, 0x09, 0x01, 0x46, 0x10, 0x04, 0x12, 0x40, 0x00, 0x08, 0x04, 0xd5, 0x0c, 0x9c, 0x33, +0x46, 0x30, 0x92, 0xf5, 0x40, 0x00, 0x70, 0x08, 0x58, 0x31, 0x89, 0x01, 0x46, 0x10, 0x04, 0x12, +0x40, 0x00, 0x0c, 0x04, 0x14, 0x00, 0x81, 0xda, 0xd5, 0x13, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x44, +0x44, 0x21, 0x01, 0x80, 0x49, 0xff, 0xd0, 0xae, 0x44, 0x00, 0x04, 0x04, 0x14, 0x05, 0x01, 0xc1, +0x46, 0x10, 0x04, 0x12, 0xf5, 0x0e, 0x14, 0x50, 0x81, 0xda, 0x44, 0x60, 0x00, 0x64, 0x84, 0xe0, +0x04, 0x1e, 0x01, 0xdd, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, +0x49, 0xff, 0xd0, 0x88, 0x44, 0x20, 0x27, 0x10, 0x4c, 0x71, 0x7f, 0xf4, 0x9d, 0xb1, 0x46, 0x10, +0x04, 0x12, 0x46, 0x20, 0x92, 0xf5, 0x58, 0x21, 0x09, 0x00, 0x97, 0xb1, 0x14, 0x20, 0x81, 0xda, +0xe6, 0xc9, 0xe9, 0xa5, 0x48, 0x00, 0x01, 0x19, 0xf3, 0x8c, 0x80, 0x5c, 0x50, 0x1f, 0x80, 0xf0, +0x80, 0x08, 0xdd, 0x27, 0x80, 0x09, 0x50, 0x1f, 0x80, 0x94, 0x44, 0x20, 0x00, 0x20, 0xdd, 0x27, +0x46, 0x50, 0x92, 0xf5, 0x58, 0x52, 0x89, 0x01, 0x40, 0x53, 0x14, 0x04, 0xf3, 0x0c, 0x46, 0xa0, +0x04, 0x12, 0x83, 0x8a, 0xf5, 0x8e, 0x80, 0xc3, 0xf0, 0x10, 0xc8, 0x2f, 0x50, 0x1f, 0x80, 0xd8, +0x38, 0x20, 0x98, 0x00, 0x44, 0x31, 0x01, 0x00, 0xf0, 0x0d, 0x94, 0x94, 0x40, 0x21, 0x0c, 0x04, +0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xd0, 0x5e, 0x38, 0x04, 0x9a, 0x02, 0x14, 0x05, 0x01, 0xc1, +0xe6, 0xc5, 0xe8, 0x0d, 0x9c, 0x31, 0x46, 0x50, 0x92, 0xf5, 0x40, 0x00, 0x70, 0x08, 0x58, 0x52, +0x89, 0x01, 0x46, 0x10, 0x04, 0x12, 0x40, 0x00, 0x14, 0x04, 0xd5, 0x0c, 0x9c, 0x34, 0x46, 0x20, +0x92, 0xf5, 0x40, 0x00, 0x70, 0x08, 0x58, 0x21, 0x09, 0x01, 0x46, 0x10, 0x04, 0x12, 0x40, 0x00, +0x08, 0x04, 0x14, 0x00, 0x81, 0xda, 0xd5, 0x13, 0xf0, 0x0d, 0x44, 0x10, 0x02, 0x44, 0x44, 0x21, +0x01, 0x80, 0x49, 0xff, 0xd0, 0x37, 0x44, 0x00, 0x04, 0x04, 0x14, 0x05, 0x01, 0xc1, 0x46, 0x10, +0x04, 0x12, 0xf3, 0x0e, 0x14, 0x30, 0x81, 0xda, 0x44, 0x60, 0x00, 0x64, 0x84, 0xe0, 0x04, 0x1e, +0x01, 0xdd, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, +0xd0, 0x11, 0x44, 0x00, 0x27, 0x10, 0x4c, 0x70, 0x7f, 0xf4, 0x9d, 0xb1, 0x46, 0x10, 0x04, 0x12, +0x46, 0x20, 0x92, 0xf5, 0x58, 0x21, 0x09, 0x00, 0x97, 0xb1, 0x14, 0x20, 0x81, 0xda, 0xe6, 0xc8, +0xe9, 0xa4, 0x48, 0x00, 0x00, 0xa2, 0x2e, 0x01, 0x8a, 0x73, 0x50, 0x8f, 0x80, 0xd8, 0x44, 0x75, +0xb6, 0x58, 0x50, 0x9f, 0x80, 0x4c, 0xc8, 0x4d, 0x50, 0x1f, 0x80, 0xf8, 0x84, 0x46, 0x80, 0x08, +0xdd, 0x27, 0x46, 0x30, 0x04, 0x12, 0xf3, 0x8f, 0x80, 0x09, 0x50, 0x1f, 0x80, 0xb4, 0x44, 0x20, +0x00, 0x18, 0xdd, 0x27, 0xf5, 0x0f, 0x46, 0xa0, 0x04, 0x12, 0x58, 0x52, 0x87, 0x04, 0x83, 0x8a, +0xf6, 0x0e, 0xf5, 0x8f, 0x50, 0x0f, 0x80, 0xd8, 0x38, 0x20, 0x18, 0x00, 0x44, 0x11, 0x01, 0x00, +0xf0, 0x0d, 0x94, 0x94, 0x40, 0x21, 0x04, 0x04, 0x44, 0x10, 0x02, 0x44, 0x49, 0xff, 0xcf, 0xe2, +0x46, 0x50, 0x92, 0xf5, 0xb4, 0x49, 0xf0, 0x0f, 0x40, 0x13, 0x70, 0x08, 0x58, 0x52, 0x89, 0x01, +0x40, 0x10, 0x94, 0x04, 0xb6, 0x40, 0x14, 0x15, 0x01, 0xda, 0x84, 0xe0, 0x04, 0x1e, 0x01, 0xdd, +0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, 0x97, 0xf9, 0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xcf, 0xba, +0x44, 0x10, 0x27, 0x10, 0x4c, 0x70, 0xff, 0xf4, 0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, +0x9d, 0xb1, 0x84, 0x46, 0x14, 0x15, 0x01, 0xda, 0x8d, 0x24, 0x4c, 0x61, 0x7f, 0xcd, 0xd5, 0x4c, +0x50, 0x1f, 0x81, 0x04, 0x84, 0x43, 0x80, 0x08, 0xdd, 0x27, 0x46, 0x30, 0x04, 0x12, 0xf3, 0x8f, +0x80, 0x09, 0x50, 0x1f, 0x80, 0xcc, 0x84, 0x4c, 0xdd, 0x27, 0xf5, 0x0f, 0x46, 0xa0, 0x04, 0x12, +0x58, 0x52, 0x87, 0x04, 0x83, 0x8a, 0xf6, 0x0e, 0xf5, 0x8f, 0x50, 0x0f, 0x80, 0xd8, 0x38, 0x20, +0x18, 0x00, 0x44, 0x11, 0x01, 0x00, 0xf0, 0x0d, 0x94, 0x94, 0x40, 0x21, 0x04, 0x04, 0x44, 0x10, +0x02, 0x44, 0x49, 0xff, 0xcf, 0x97, 0x9c, 0x73, 0x46, 0x50, 0x92, 0xf5, 0xb4, 0x49, 0xf0, 0x0f, +0x40, 0x10, 0xf0, 0x08, 0x58, 0x52, 0x89, 0x01, 0x40, 0x10, 0x94, 0x04, 0xb6, 0x40, 0x14, 0x15, +0x01, 0xda, 0x84, 0xe0, 0x04, 0x1e, 0x01, 0xdd, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x08, 0x97, 0xf9, +0x84, 0x05, 0xc1, 0x07, 0x49, 0xff, 0xcf, 0x6e, 0x44, 0x10, 0x27, 0x10, 0x4c, 0x70, 0xff, 0xf4, +0x46, 0x10, 0x92, 0xf5, 0x58, 0x10, 0x89, 0x00, 0x9d, 0xb1, 0x84, 0x43, 0x14, 0x15, 0x01, 0xda, +0x8d, 0x24, 0x4c, 0x61, 0x7f, 0xcc, 0x46, 0x10, 0x04, 0x12, 0x84, 0x01, 0xa8, 0x0c, 0x84, 0x00, +0xa8, 0x0c, 0x84, 0x05, 0x49, 0xff, 0xcf, 0x56, 0x46, 0x10, 0x04, 0x12, 0x84, 0xe0, 0x14, 0x70, +0x82, 0x60, 0x49, 0xff, 0xcf, 0x7d, 0x49, 0xff, 0xdb, 0xf9, 0x44, 0x00, 0x10, 0x04, 0x49, 0xff, +0xdc, 0x1b, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x80, 0x04, 0x84, 0x08, 0xb6, 0xe1, 0xb6, 0x01, +0xb6, 0xe1, 0x46, 0x60, 0x04, 0x12, 0x49, 0xff, 0xdb, 0xe9, 0x84, 0x01, 0xa8, 0x34, 0x49, 0xff, +0xcf, 0x39, 0xa9, 0xf4, 0x84, 0xa1, 0xf3, 0x0d, 0xdb, 0x36, 0x46, 0x10, 0x04, 0x12, 0x80, 0x41, +0x80, 0x61, 0x80, 0x81, 0x80, 0xa1, 0x83, 0x81, 0x81, 0x41, 0x81, 0x21, 0x81, 0x01, 0x80, 0xe1, +0x80, 0xc1, 0x80, 0x01, 0x04, 0x10, 0x81, 0xe0, 0x04, 0x21, 0x01, 0xe1, 0x04, 0x31, 0x81, 0xe2, +0x04, 0x42, 0x01, 0xe3, 0x04, 0x52, 0x81, 0xe4, 0x05, 0xce, 0x01, 0xe5, 0x04, 0xa5, 0x01, 0xea, +0x04, 0x94, 0x81, 0xeb, 0x04, 0x84, 0x01, 0xec, 0x04, 0x73, 0x81, 0xed, 0x04, 0x63, 0x01, 0xee, +0x05, 0xe0, 0x01, 0xef, 0x3e, 0x09, 0x66, 0xcc, 0x15, 0xcf, 0x80, 0x00, 0x14, 0xaf, 0x80, 0x01, +0x14, 0x9f, 0x80, 0x02, 0x14, 0x8f, 0x80, 0x03, 0xf7, 0x84, 0xf6, 0x85, 0x15, 0xef, 0x80, 0x06, +0x49, 0xff, 0x98, 0x66, 0x3e, 0x09, 0x67, 0x34, 0x49, 0xff, 0x98, 0x62, 0xed, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x6c, 0x3e, 0x49, 0x7f, 0x30, 0x96, 0x00, +0x96, 0x48, 0xf0, 0x86, 0xf1, 0x87, 0x97, 0x90, 0x3a, 0x02, 0x08, 0x00, 0x50, 0x5f, 0x80, 0x7c, +0x3e, 0x49, 0x7f, 0x24, 0x3a, 0x02, 0x88, 0x20, 0x50, 0x7f, 0x80, 0x70, 0x3e, 0x59, 0x7f, 0x0c, +0x3a, 0x02, 0x08, 0x00, 0x50, 0x8f, 0x80, 0x58, 0x3e, 0x49, 0x7e, 0xf4, 0x3a, 0x03, 0x88, 0x20, +0x50, 0x7f, 0x80, 0x40, 0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x04, 0x0c, 0x24, 0x3a, 0x02, 0x84, 0x00, +0x3a, 0x04, 0x04, 0x20, 0x3a, 0x02, 0x0c, 0x04, 0x3a, 0x03, 0x8c, 0x24, 0x3a, 0x02, 0x04, 0x00, +0x3a, 0x03, 0x84, 0x20, 0x84, 0x01, 0x4c, 0x60, 0x40, 0x31, 0xf1, 0x07, 0xe6, 0x23, 0x4e, 0xf2, +0x02, 0x4f, 0x8c, 0x17, 0x42, 0x00, 0x80, 0x24, 0x3e, 0x39, 0xd2, 0x7c, 0x98, 0x03, 0x80, 0x60, +0xa3, 0x19, 0x46, 0x20, 0x04, 0x12, 0x14, 0x41, 0x02, 0x06, 0x84, 0xa3, 0xb4, 0x83, 0x42, 0x30, +0x94, 0x24, 0x14, 0x41, 0x02, 0x07, 0x9c, 0xd9, 0x3e, 0x19, 0xd2, 0x7c, 0x38, 0x20, 0x8f, 0x02, +0x46, 0x10, 0x04, 0x12, 0x14, 0x20, 0x82, 0x08, 0x40, 0x31, 0x94, 0x0c, 0x3e, 0x59, 0xd2, 0x7c, +0x98, 0xdd, 0xa0, 0x99, 0x14, 0x20, 0x82, 0x09, 0xa0, 0x84, 0x14, 0x20, 0x82, 0x0a, 0xa0, 0x05, +0x14, 0x00, 0x82, 0x0b, 0x48, 0x00, 0x02, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0x48, 0x3e, 0x09, +0xd2, 0x7c, 0x49, 0xfe, 0x6e, 0x9b, 0xf0, 0x06, 0x44, 0x10, 0x02, 0x8c, 0x50, 0x2f, 0x80, 0x88, +0x49, 0xff, 0xdb, 0x7a, 0xf0, 0x06, 0x46, 0x38, 0x30, 0xf0, 0x96, 0x84, 0x46, 0x50, 0x30, 0xf0, +0x40, 0x21, 0x6c, 0x08, 0x84, 0x20, 0x40, 0x31, 0x0c, 0x04, 0x40, 0x51, 0x14, 0x04, 0x58, 0x00, +0x00, 0x80, 0xf1, 0x84, 0xf3, 0x8c, 0xf5, 0x8b, 0xf1, 0x88, 0xf1, 0x83, 0xf0, 0x8f, 0x04, 0xaf, +0x80, 0x06, 0x48, 0x00, 0x01, 0x8c, 0xf1, 0x02, 0x84, 0xa2, 0x56, 0x60, 0x80, 0x01, 0x84, 0x83, +0xf2, 0x05, 0xf3, 0x0a, 0x40, 0x82, 0x18, 0x1b, 0x40, 0x82, 0x98, 0x1a, 0xf5, 0x09, 0x8c, 0x58, +0x8c, 0x78, 0x8c, 0xb8, 0xf2, 0x85, 0xf3, 0x8a, 0xf5, 0x89, 0xf2, 0x0e, 0x80, 0x0a, 0x44, 0x10, +0x02, 0x8c, 0x49, 0xff, 0xce, 0x67, 0xf0, 0x02, 0xc8, 0x08, 0x46, 0x50, 0x04, 0x12, 0x58, 0x52, +0x80, 0x04, 0x44, 0x40, 0x00, 0x42, 0xd5, 0x11, 0xf1, 0x02, 0x84, 0xa1, 0xd9, 0x08, 0x46, 0x50, +0x04, 0x12, 0x58, 0x52, 0x80, 0x04, 0x44, 0x40, 0x00, 0x52, 0xd5, 0x07, 0x46, 0x50, 0x04, 0x12, +0x58, 0x52, 0x80, 0x04, 0x44, 0x40, 0x00, 0x5a, 0xb6, 0x85, 0xf3, 0x03, 0x97, 0x19, 0xe6, 0x84, +0xe8, 0x14, 0xf5, 0x02, 0xcd, 0x12, 0xf1, 0x08, 0x50, 0x0f, 0x80, 0x7c, 0x38, 0x60, 0x04, 0x00, +0x84, 0x21, 0x80, 0x41, 0x80, 0x66, 0x80, 0x0a, 0x49, 0xff, 0xfb, 0x50, 0x84, 0x21, 0x80, 0x0a, +0x80, 0x66, 0x80, 0x41, 0x49, 0xff, 0xf6, 0xe8, 0x46, 0x50, 0x04, 0x12, 0x04, 0x42, 0x82, 0x60, +0x42, 0x42, 0x78, 0x09, 0x14, 0x42, 0x82, 0x60, 0x80, 0xc5, 0x04, 0x43, 0x03, 0x04, 0x58, 0x42, +0x00, 0x67, 0x14, 0x43, 0x03, 0x04, 0x04, 0x42, 0x83, 0x05, 0x46, 0x70, 0x00, 0x89, 0x58, 0x73, +0x84, 0x6c, 0x58, 0x42, 0x00, 0x0c, 0x14, 0x42, 0x83, 0x05, 0x80, 0x0a, 0x84, 0x20, 0xdd, 0x27, +0x46, 0x38, 0x00, 0x56, 0x58, 0x31, 0x87, 0x57, 0x40, 0x84, 0x60, 0x08, 0x40, 0x24, 0x0c, 0x04, +0x46, 0x60, 0x00, 0x87, 0x58, 0x63, 0x06, 0xa0, 0x84, 0x20, 0x80, 0x0a, 0xdd, 0x26, 0x80, 0x0a, +0x44, 0x10, 0x00, 0x10, 0xdd, 0x27, 0x46, 0x23, 0x0d, 0x70, 0x58, 0x21, 0x00, 0x06, 0x44, 0x10, +0x00, 0x10, 0x80, 0x0a, 0xdd, 0x26, 0x80, 0x0a, 0x44, 0x10, 0x02, 0x44, 0xdd, 0x27, 0x44, 0x21, +0x01, 0x80, 0x44, 0x10, 0x02, 0x44, 0x80, 0x0a, 0xdd, 0x26, 0x80, 0x0a, 0x44, 0x10, 0x01, 0x14, +0xdd, 0x27, 0x46, 0x20, 0x0c, 0x21, 0x58, 0x21, 0x01, 0xf1, 0x44, 0x10, 0x01, 0x14, 0x80, 0x0a, +0xdd, 0x26, 0x46, 0x50, 0x04, 0x10, 0x84, 0x88, 0x14, 0x42, 0x81, 0x48, 0x94, 0x66, 0x80, 0x0a, +0xdd, 0x27, 0x46, 0x20, 0x50, 0x00, 0x80, 0x0a, 0x58, 0x21, 0x01, 0x0f, 0x44, 0x10, 0x02, 0x00, +0xdd, 0x26, 0x84, 0xc0, 0x44, 0x10, 0x02, 0x00, 0x50, 0x2f, 0x80, 0x8c, 0x80, 0x0a, 0x49, 0xff, +0xda, 0xb3, 0xf1, 0x23, 0x9d, 0xb1, 0x54, 0x10, 0x81, 0x00, 0x97, 0xb1, 0x84, 0x05, 0xc1, 0x05, +0xdd, 0x3c, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xef, 0x46, 0x50, 0x04, 0x10, 0x84, 0x82, 0x14, 0x42, +0x81, 0x48, 0x46, 0x60, 0x00, 0x89, 0x58, 0x63, 0x00, 0x24, 0x44, 0x00, 0x27, 0x14, 0xdd, 0x26, +0x44, 0x00, 0x20, 0x04, 0xdd, 0x26, 0x44, 0x00, 0x2c, 0xf8, 0xdd, 0x26, 0x44, 0x00, 0x27, 0x04, +0xdd, 0x26, 0x44, 0x00, 0x28, 0x14, 0xdd, 0x26, 0x44, 0x00, 0x29, 0xf0, 0xdd, 0x26, 0x44, 0x00, +0x23, 0x00, 0xdd, 0x26, 0x46, 0x70, 0x04, 0x12, 0x44, 0x00, 0x10, 0x04, 0xdd, 0x26, 0x44, 0x50, +0x74, 0x08, 0x46, 0x80, 0x04, 0x11, 0x14, 0x53, 0x80, 0xc0, 0x84, 0x81, 0x58, 0x84, 0x00, 0x04, +0x50, 0x94, 0x10, 0x0c, 0x84, 0xc0, 0x84, 0xa8, 0xb6, 0xc8, 0xb6, 0xa8, 0xb6, 0xc8, 0xb6, 0x89, +0xf4, 0x81, 0x84, 0x05, 0xdd, 0x3c, 0xb6, 0xc9, 0x46, 0x50, 0x04, 0x12, 0xf1, 0x0f, 0x14, 0x12, +0x81, 0xc5, 0x50, 0x5f, 0x80, 0x40, 0xf2, 0x04, 0x84, 0x0a, 0x38, 0x72, 0x88, 0x02, 0x46, 0x50, +0x04, 0x12, 0x14, 0x72, 0x83, 0x3e, 0x50, 0x5f, 0x80, 0x58, 0x38, 0x82, 0x88, 0x02, 0x46, 0x50, +0x04, 0x12, 0x80, 0xe5, 0x14, 0x82, 0x81, 0xc1, 0x44, 0x53, 0x00, 0x21, 0x14, 0x53, 0x80, 0x20, +0x46, 0x70, 0x04, 0x12, 0xdd, 0x3c, 0xf3, 0x0d, 0x46, 0x50, 0x04, 0x12, 0x14, 0x32, 0x82, 0x05, +0x58, 0x73, 0x89, 0xf0, 0xf5, 0x0b, 0x84, 0x05, 0xb6, 0xa7, 0xf4, 0x01, 0xb6, 0x89, 0xdd, 0x3c, +0xb6, 0xc9, 0xf0, 0x0c, 0xb6, 0x07, 0xb4, 0x27, 0x9d, 0xb1, 0x97, 0xb1, 0x84, 0x0a, 0x4e, 0x14, +0x00, 0x06, 0xdd, 0x3c, 0x44, 0x50, 0x03, 0xe8, 0xde, 0xf7, 0x84, 0x0a, 0xdd, 0x3c, 0x4e, 0xa3, +0x00, 0x1e, 0x46, 0x60, 0x04, 0x12, 0x80, 0xe6, 0x46, 0x80, 0x04, 0x12, 0x58, 0x84, 0x08, 0x20, +0x04, 0x23, 0x02, 0x06, 0xf1, 0x03, 0x04, 0x33, 0x82, 0x07, 0xb4, 0x88, 0x3e, 0x09, 0x67, 0x48, +0x49, 0xff, 0x96, 0x96, 0x04, 0x43, 0x02, 0x06, 0xf2, 0x05, 0xb6, 0x82, 0x04, 0x43, 0x82, 0x07, +0xa9, 0x11, 0xb4, 0x88, 0xf3, 0x0a, 0xb6, 0x83, 0xd5, 0x1c, 0x46, 0x60, 0x04, 0x12, 0x80, 0xe6, +0x46, 0x80, 0x04, 0x12, 0x58, 0x84, 0x08, 0x2c, 0x04, 0x23, 0x02, 0x09, 0xf1, 0x03, 0x04, 0x33, +0x82, 0x0a, 0xb4, 0x88, 0x3e, 0x09, 0x67, 0x48, 0x49, 0xff, 0x96, 0x7a, 0x04, 0x43, 0x02, 0x09, +0xf5, 0x0a, 0xa9, 0x29, 0x04, 0x43, 0x82, 0x0a, 0xf0, 0x09, 0xb6, 0x80, 0xb4, 0x88, 0xa9, 0x01, +0x46, 0x70, 0x04, 0x12, 0x58, 0x73, 0x80, 0x10, 0x49, 0xff, 0xcd, 0x32, 0x49, 0xff, 0xd9, 0xae, +0xb4, 0xc7, 0x84, 0x01, 0x40, 0x63, 0x00, 0x04, 0xb6, 0xc7, 0xdd, 0x3c, 0x42, 0x43, 0x00, 0x09, +0xb6, 0x87, 0x84, 0x02, 0xdd, 0x3c, 0xf2, 0x02, 0x84, 0xa3, 0x9c, 0xd1, 0x96, 0xd9, 0xf3, 0x82, +0x4c, 0x32, 0xfe, 0x83, 0xf0, 0x03, 0xf1, 0x08, 0xf2, 0x04, 0x9c, 0x01, 0x9c, 0x4a, 0x9c, 0x94, +0x84, 0xa6, 0xf0, 0x83, 0xf1, 0x88, 0xf2, 0x84, 0xd0, 0x1f, 0xf5, 0x08, 0x50, 0x2f, 0x80, 0x70, +0x38, 0x21, 0x14, 0x01, 0x84, 0x20, 0x46, 0x30, 0x3e, 0x40, 0xf5, 0x03, 0x3e, 0x09, 0xd2, 0x7c, +0xf1, 0x82, 0x80, 0x20, 0xf0, 0x85, 0x40, 0x31, 0x0c, 0x04, 0x99, 0x6d, 0x8c, 0x08, 0x8c, 0x30, +0xf3, 0x8e, 0xf5, 0x8d, 0xf0, 0x8a, 0xf1, 0x89, 0x85, 0x00, 0x47, 0xc0, 0x00, 0x87, 0x59, 0xce, +0x06, 0x80, 0x48, 0xff, 0xfe, 0x6c, 0xf3, 0x07, 0x44, 0x20, 0x00, 0x18, 0x42, 0x21, 0x88, 0x24, +0x3e, 0x59, 0xd2, 0x7c, 0x98, 0x95, 0x80, 0x82, 0xa3, 0x61, 0x46, 0x30, 0x04, 0x12, 0x14, 0x51, +0x82, 0x06, 0xf0, 0x07, 0xf5, 0x02, 0xb4, 0x84, 0x42, 0x10, 0x14, 0x24, 0x14, 0x41, 0x82, 0x07, +0x9c, 0xc9, 0x3e, 0x19, 0xd2, 0x7c, 0x38, 0x40, 0x8f, 0x02, 0x46, 0x10, 0x04, 0x12, 0x14, 0x40, +0x82, 0x08, 0x3e, 0x09, 0xd2, 0x7c, 0x94, 0xdb, 0x98, 0xd8, 0xa0, 0xd9, 0x14, 0x30, 0x82, 0x09, +0xa0, 0xd4, 0x14, 0x30, 0x82, 0x0a, 0x80, 0x61, 0xa0, 0x95, 0x14, 0x21, 0x82, 0x0b, 0x84, 0x41, +0x14, 0x20, 0x82, 0x05, 0x44, 0x10, 0x02, 0x8c, 0xf2, 0x22, 0xf0, 0x06, 0x49, 0xff, 0xcc, 0xa2, +0x92, 0x00, 0xf1, 0x06, 0x84, 0xa1, 0xd9, 0x1b, 0x3c, 0x1c, 0x73, 0xbb, 0x46, 0x00, 0x04, 0x12, +0x14, 0x10, 0x01, 0xda, 0x46, 0x00, 0x04, 0x12, 0x58, 0x00, 0x07, 0x80, 0x3e, 0x39, 0xce, 0xec, +0x46, 0x5f, 0xfb, 0xed, 0x98, 0x43, 0x58, 0x52, 0x88, 0x84, 0x98, 0x4d, 0xb4, 0x21, 0xaa, 0x41, +0x46, 0x10, 0x04, 0x12, 0x58, 0x10, 0x87, 0xd4, 0x4c, 0x00, 0xff, 0xf2, 0xec, 0x94, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0x80, 0xe0, 0xe6, 0x24, +0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x01, 0xa4, 0xb4, 0xc0, 0x3e, 0x09, 0x67, 0x6c, 0x80, 0x26, +0x49, 0xff, 0x95, 0xc6, 0x46, 0x10, 0x04, 0x12, 0x46, 0x30, 0x04, 0x11, 0x46, 0x08, 0x00, 0x08, +0x80, 0x43, 0x44, 0x4f, 0xf5, 0x7c, 0x05, 0xc0, 0x80, 0x49, 0x14, 0x40, 0x80, 0x49, 0x14, 0x01, +0x80, 0x99, 0x14, 0x01, 0x00, 0x9a, 0x84, 0x08, 0x4c, 0x60, 0x00, 0x96, 0xe6, 0xc9, 0xe8, 0x16, +0x84, 0x24, 0x4c, 0x60, 0x80, 0x43, 0xe6, 0xc5, 0xe8, 0x0a, 0x84, 0x42, 0x4c, 0x61, 0x00, 0x30, +0xe6, 0xc3, 0xe8, 0x32, 0x84, 0x01, 0x4c, 0x60, 0x41, 0x67, 0xd5, 0x25, 0x84, 0x26, 0x4c, 0x60, +0x80, 0x43, 0x9d, 0xfc, 0xe6, 0xc7, 0xe8, 0x72, 0xd5, 0x38, 0x84, 0x4c, 0x4c, 0x61, 0x00, 0xc7, +0xe6, 0xcd, 0xe8, 0x0a, 0x84, 0x0a, 0x4c, 0x60, 0x00, 0x95, 0x9d, 0xfc, 0xe6, 0xcb, 0x4e, 0xf2, +0x00, 0xac, 0x48, 0x00, 0x00, 0x86, 0x84, 0x2e, 0x4c, 0x60, 0x80, 0xe1, 0xe2, 0xc1, 0x4e, 0xf3, +0x00, 0xc7, 0x84, 0x4f, 0x4c, 0x61, 0x01, 0x3a, 0x44, 0x00, 0x00, 0xff, 0x4c, 0x60, 0x41, 0x44, +0x48, 0x00, 0x01, 0x37, 0x49, 0xff, 0xec, 0xc0, 0x48, 0x00, 0x01, 0x3e, 0x80, 0x07, 0x49, 0xff, +0xd8, 0x59, 0x48, 0x00, 0x01, 0x39, 0x9d, 0xfc, 0xb4, 0xc7, 0x49, 0xff, 0xd0, 0x75, 0x96, 0x30, +0x49, 0xff, 0xcd, 0x70, 0x48, 0x00, 0x01, 0x30, 0x9d, 0xfc, 0xb4, 0xe7, 0x46, 0x60, 0x00, 0x8a, +0x58, 0x63, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x99, 0xb4, 0x07, 0x96, 0x00, 0x49, 0xff, 0xcc, 0x4a, +0x48, 0x00, 0x01, 0x22, 0x9d, 0xfc, 0xb5, 0x07, 0x3e, 0x69, 0xce, 0xa0, 0x54, 0x84, 0x00, 0x01, +0x4e, 0x82, 0x00, 0x1a, 0x46, 0x00, 0x04, 0x12, 0x58, 0x00, 0x07, 0x74, 0xb4, 0x20, 0x46, 0x2f, +0xf0, 0x0f, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x20, 0x2e, 0x11, 0x8a, 0x76, +0xb4, 0x40, 0x38, 0x13, 0x04, 0x00, 0x40, 0x10, 0xc0, 0x08, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, +0x48, 0x00, 0x01, 0x02, 0x49, 0xff, 0xd0, 0x40, 0x80, 0x08, 0x49, 0xff, 0xdf, 0x9d, 0x84, 0x01, +0x49, 0xff, 0xdf, 0x9a, 0x46, 0x00, 0x04, 0x12, 0x04, 0x10, 0x01, 0xdd, 0x2e, 0x01, 0x8a, 0x76, +0x92, 0x30, 0x38, 0x13, 0x00, 0x08, 0x48, 0x00, 0x00, 0xef, 0xb4, 0xe7, 0x49, 0xff, 0xd0, 0x2c, +0x97, 0xf8, 0x84, 0x00, 0x80, 0x27, 0x80, 0x40, 0x80, 0x60, 0x46, 0x60, 0x00, 0x8d, 0x58, 0x63, +0x00, 0xc8, 0xd5, 0x0e, 0x9d, 0xfc, 0xb4, 0xe7, 0x49, 0xff, 0xd0, 0x1e, 0x97, 0xf8, 0x84, 0x00, +0x80, 0x27, 0x80, 0x40, 0x80, 0x60, 0x46, 0x60, 0x00, 0x8c, 0x58, 0x63, 0x08, 0x04, 0xdd, 0x26, +0x84, 0x40, 0x80, 0x27, 0x84, 0x01, 0x80, 0x62, 0xdd, 0x26, 0x48, 0x00, 0x00, 0xcd, 0xb4, 0x07, +0xb4, 0x27, 0x96, 0x00, 0x92, 0x28, 0x96, 0x48, 0x49, 0xff, 0xda, 0xbc, 0x48, 0x00, 0x00, 0xc4, +0x50, 0x43, 0x80, 0x08, 0x9c, 0x7c, 0xb4, 0x01, 0xb4, 0xa1, 0xb4, 0x24, 0xb4, 0x44, 0xb4, 0x64, +0xb4, 0x84, 0x92, 0x48, 0x92, 0x70, 0x92, 0xa8, 0x96, 0x48, 0x96, 0x00, 0x96, 0x90, 0x96, 0xd8, +0x92, 0x98, 0x97, 0x68, 0x49, 0xff, 0xd3, 0xf8, 0x44, 0x10, 0x00, 0xff, 0x4c, 0x00, 0xc0, 0xac, +0xb6, 0x07, 0x48, 0x00, 0x00, 0xa9, 0x46, 0x60, 0x04, 0x10, 0x58, 0x63, 0x00, 0x40, 0xb4, 0x07, +0xb4, 0xe6, 0xb4, 0x26, 0x44, 0x2f, 0xff, 0x3f, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x26, 0x96, 0x00, +0x49, 0xff, 0xed, 0xa0, 0xb6, 0xe6, 0x48, 0x00, 0x00, 0x97, 0x9d, 0xfc, 0xb4, 0xe7, 0x46, 0x60, +0x00, 0x89, 0x58, 0x63, 0x07, 0x98, 0x97, 0xf8, 0x49, 0xff, 0xcf, 0xce, 0x80, 0x27, 0x84, 0x00, +0xdd, 0x26, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x26, 0x48, 0x00, 0x00, 0x86, 0x9d, 0xfc, 0xb4, 0xc7, +0xb5, 0x07, 0x97, 0xb0, 0xe6, 0xc3, 0x4e, 0xf2, 0x00, 0x7f, 0x42, 0x84, 0x20, 0x0b, 0x49, 0xff, +0xcf, 0xbb, 0x80, 0x26, 0x80, 0x48, 0x84, 0x00, 0x49, 0xff, 0xfc, 0x56, 0x80, 0x26, 0x80, 0x48, +0x84, 0x01, 0x49, 0xff, 0xfc, 0x51, 0x48, 0x00, 0x00, 0x6f, 0x9d, 0xfc, 0x49, 0xff, 0xeb, 0xec, +0xb4, 0xc7, 0x97, 0xb0, 0x80, 0x06, 0x49, 0xff, 0xcc, 0xa5, 0x84, 0x00, 0x80, 0x20, 0x49, 0xff, +0xe0, 0x67, 0x84, 0x01, 0x84, 0x20, 0x49, 0xff, 0xe0, 0x63, 0x46, 0x90, 0x00, 0x8d, 0x58, 0x94, +0x80, 0xc8, 0x46, 0x80, 0x00, 0x8c, 0x58, 0x84, 0x08, 0x04, 0xe6, 0xcf, 0xe9, 0x22, 0x84, 0x00, +0x49, 0xff, 0xde, 0xf2, 0x84, 0x01, 0x49, 0xff, 0xde, 0xef, 0x84, 0x00, 0x80, 0x40, 0x80, 0x60, +0x84, 0x21, 0xdd, 0x29, 0x84, 0x01, 0x84, 0x40, 0x80, 0x20, 0x80, 0x62, 0xdd, 0x29, 0x84, 0x00, +0x80, 0x40, 0x80, 0x60, 0x84, 0x21, 0xdd, 0x28, 0x84, 0x40, 0x84, 0x01, 0x80, 0x20, 0x80, 0x62, +0xdd, 0x28, 0x84, 0x00, 0x84, 0x21, 0x49, 0xff, 0xdb, 0x99, 0x84, 0x01, 0x80, 0x20, 0xd5, 0x1b, +0x84, 0x00, 0x80, 0x20, 0x80, 0x40, 0x80, 0x60, 0xdd, 0x29, 0x84, 0x20, 0x80, 0x41, 0x80, 0x61, +0x84, 0x01, 0xdd, 0x29, 0x84, 0x00, 0x80, 0x20, 0x80, 0x40, 0x80, 0x60, 0xdd, 0x28, 0x84, 0x20, +0x80, 0x41, 0x80, 0x61, 0x84, 0x01, 0xdd, 0x28, 0x84, 0x00, 0x80, 0x20, 0x49, 0xff, 0xdb, 0x7e, +0x84, 0x01, 0x84, 0x20, 0x49, 0xff, 0xdb, 0x7a, 0x80, 0x06, 0x49, 0xff, 0xd0, 0x5f, 0x9c, 0x03, +0x96, 0x00, 0x80, 0x26, 0x84, 0x41, 0xd5, 0x0d, 0x49, 0xff, 0xcd, 0xca, 0xd5, 0x0c, 0x9d, 0xfc, +0xb4, 0x07, 0xb4, 0x27, 0xb4, 0x47, 0x92, 0x28, 0x42, 0x00, 0x40, 0x0b, 0x96, 0x48, 0x96, 0x94, +0x49, 0xff, 0xd8, 0x80, 0x46, 0x40, 0x04, 0x11, 0x80, 0x44, 0x46, 0x38, 0x00, 0x08, 0x46, 0x10, +0x04, 0x12, 0x84, 0xc0, 0x14, 0x62, 0x00, 0x99, 0x14, 0x31, 0x00, 0x9a, 0x15, 0xc0, 0x80, 0x49, +0x3e, 0x09, 0x67, 0x80, 0x49, 0xff, 0x94, 0x2c, 0x92, 0x00, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x04, 0x21, 0x00, 0x20, 0x84, 0xa3, 0x54, 0x21, +0x00, 0x03, 0xd2, 0x09, 0xc8, 0x04, 0x3e, 0x09, 0x8a, 0x5b, 0xd5, 0x03, 0x3e, 0x09, 0x8a, 0x5c, +0xae, 0x40, 0xd5, 0x1b, 0xc8, 0x0a, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x40, +0x94, 0x4c, 0x44, 0x3f, 0xff, 0x0f, 0xd5, 0x0c, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x04, 0x10, +0x46, 0x3f, 0xff, 0x0f, 0xb4, 0x40, 0x40, 0x10, 0xc0, 0x08, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, +0x0c, 0x02, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x2e, 0x01, 0x8a, 0x5f, +0xc0, 0x04, 0x3e, 0x09, 0x8a, 0x14, 0xd5, 0x03, 0x3e, 0x09, 0x8a, 0x0c, 0xb4, 0x00, 0xdd, 0x9e, +0x2e, 0x01, 0x8a, 0x5f, 0xc0, 0x04, 0x3e, 0x09, 0x8a, 0x18, 0xd5, 0x03, 0x3e, 0x09, 0x8a, 0x10, +0xb4, 0x00, 0xdd, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x04, 0x21, 0x00, 0x20, 0x84, 0xa3, 0x54, 0x21, +0x00, 0x03, 0xda, 0x25, 0xe6, 0x0a, 0xe8, 0x23, 0x3e, 0x29, 0xd2, 0xc4, 0x38, 0x11, 0x02, 0x0a, +0x3c, 0x0e, 0x62, 0x8b, 0xe6, 0x04, 0xe8, 0x0e, 0x46, 0x10, 0x04, 0x10, 0x04, 0x30, 0x81, 0x04, +0x84, 0x41, 0x40, 0x01, 0x00, 0x0c, 0x40, 0x00, 0x0c, 0x04, 0x14, 0x00, 0x81, 0x04, 0x80, 0x02, +0xd5, 0x0f, 0x46, 0x10, 0x04, 0x10, 0x9c, 0x84, 0x04, 0x30, 0x81, 0x04, 0x84, 0x01, 0x40, 0x20, +0x08, 0x0c, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x81, 0x04, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, +0x46, 0x40, 0x04, 0x11, 0x46, 0x52, 0x22, 0x22, 0x58, 0x52, 0x82, 0x21, 0x80, 0x64, 0x80, 0x23, +0x14, 0x52, 0x00, 0x92, 0x9c, 0xa9, 0x44, 0x40, 0x02, 0x22, 0x80, 0x01, 0x14, 0x41, 0x80, 0x93, +0x14, 0x20, 0x80, 0x94, 0x44, 0x10, 0x01, 0x22, 0x14, 0x10, 0x00, 0x95, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x04, +0x3e, 0x01, 0x8a, 0x5d, 0xd5, 0x1a, 0xc0, 0x0d, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, +0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x04, 0xd5, 0x0c, +0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x42, 0x10, 0x88, 0x09, 0xb6, 0x20, +0xb4, 0x20, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x00, +0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x04, 0x3e, 0x19, 0x8a, 0x28, +0xd5, 0x0e, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x40, 0xb4, 0x41, 0x92, 0x50, 0x40, 0x21, +0x40, 0x08, 0xb6, 0x41, 0x96, 0x01, 0xb4, 0x41, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x01, 0xdd, 0x9e, +0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x04, +0x3e, 0x01, 0x8a, 0x5e, 0xd5, 0x22, 0xc0, 0x11, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0x8f, +0x46, 0x00, 0x04, 0x11, 0x42, 0x21, 0x60, 0x08, 0x14, 0x20, 0x80, 0x8f, 0x58, 0x00, 0x02, 0x44, +0xb4, 0x20, 0x42, 0x10, 0xfc, 0x08, 0xd5, 0x10, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0x8f, +0x42, 0x21, 0x60, 0x09, 0x14, 0x20, 0x80, 0x8f, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x44, +0xb4, 0x20, 0x42, 0x10, 0xfc, 0x09, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x10, 0x00, 0x8e, 0x58, 0x10, 0x82, 0x10, 0xc0, 0x06, 0x84, 0x01, 0xdd, 0x21, 0x3e, 0x09, +0x80, 0x38, 0xd5, 0x04, 0xdd, 0x21, 0x3e, 0x09, 0x80, 0x48, 0x49, 0xff, 0x93, 0x21, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0x30, 0x04, 0x00, 0x04, 0x31, 0x80, 0x20, +0x81, 0x20, 0x80, 0xc1, 0x54, 0x01, 0x80, 0x03, 0x84, 0x23, 0x81, 0x42, 0x4c, 0x00, 0x80, 0x03, +0xd5, 0x16, 0x49, 0xff, 0xff, 0x15, 0x81, 0x00, 0x84, 0x04, 0x4c, 0x80, 0x00, 0x0a, 0x3e, 0x19, +0xeb, 0xd0, 0x40, 0x04, 0x00, 0x0c, 0x98, 0x01, 0xb4, 0x00, 0x84, 0xa1, 0xd0, 0x0b, 0x84, 0xa1, +0xde, 0x08, 0x80, 0x28, 0x3e, 0x09, 0x80, 0x5c, 0x49, 0xff, 0x92, 0xfa, 0x84, 0x00, 0xd5, 0x54, +0x85, 0x01, 0x49, 0xff, 0xff, 0x07, 0x84, 0x24, 0x80, 0xe0, 0x4c, 0x00, 0x80, 0x0a, 0x40, 0x00, +0x04, 0x0c, 0x3e, 0x19, 0xeb, 0xd0, 0x98, 0x01, 0xb4, 0x00, 0x84, 0xa1, 0xd0, 0x08, 0x84, 0xa1, +0xde, 0x05, 0x80, 0x27, 0x3e, 0x09, 0x80, 0x90, 0xd5, 0xe8, 0x84, 0xe3, 0x4e, 0x93, 0x00, 0x1b, +0x84, 0xa1, 0xde, 0x16, 0x80, 0x28, 0x89, 0x08, 0x80, 0x09, 0x8d, 0x01, 0x49, 0xff, 0xfe, 0xb4, +0x40, 0x84, 0x0c, 0x08, 0x3e, 0x09, 0xeb, 0xd0, 0x89, 0x00, 0x04, 0x54, 0x00, 0x01, 0x46, 0x10, +0x00, 0x8e, 0x58, 0x10, 0x82, 0x90, 0xde, 0x02, 0xd5, 0x1d, 0x80, 0x09, 0xd5, 0x1e, 0x80, 0x08, +0xd5, 0x20, 0x3c, 0x5c, 0x62, 0xba, 0xd7, 0x03, 0x3c, 0x7e, 0x62, 0xba, 0x84, 0xa1, 0xde, 0x18, +0x80, 0x27, 0x99, 0xff, 0x80, 0x06, 0x9d, 0xf9, 0x49, 0xff, 0xfe, 0x96, 0x95, 0xfb, 0x3e, 0x19, +0xeb, 0xd0, 0x99, 0xf9, 0xa1, 0xf9, 0x84, 0xa2, 0x46, 0x10, 0x00, 0x8e, 0x58, 0x10, 0x82, 0x90, +0xdf, 0x03, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x21, 0x80, 0x06, 0xd5, 0x05, 0x80, 0x07, +0x80, 0x2a, 0x49, 0xff, 0xfe, 0xc1, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x20, 0x84, 0xa3, 0x54, 0x00, 0x00, 0x03, +0xd8, 0x26, 0x84, 0x00, 0x84, 0x21, 0x80, 0x40, 0x49, 0xff, 0xff, 0x76, 0xc8, 0x05, 0x3e, 0x09, +0x80, 0xc0, 0x49, 0xff, 0x92, 0x8d, 0x46, 0x10, 0x04, 0x11, 0x04, 0x20, 0x80, 0x8f, 0x84, 0x01, +0x58, 0x21, 0x00, 0x08, 0x14, 0x20, 0x80, 0x8f, 0x80, 0x20, 0x84, 0x40, 0x49, 0xff, 0xff, 0x64, +0xc8, 0x05, 0x3e, 0x09, 0x80, 0xfc, 0x49, 0xff, 0x92, 0x7b, 0x46, 0x00, 0x04, 0x11, 0x44, 0x10, +0x07, 0x01, 0x14, 0x10, 0x00, 0xfc, 0x49, 0xff, 0xfe, 0xbd, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x49, 0xff, 0xff, 0xca, 0x2e, 0x11, 0x8a, 0x5b, +0x44, 0x50, 0x00, 0xff, 0xd1, 0x09, 0x84, 0x00, 0x49, 0xff, 0xfe, 0x3e, 0x2e, 0x11, 0x8a, 0x5c, +0x84, 0x01, 0x49, 0xff, 0xfe, 0x39, 0x2e, 0x01, 0x8a, 0x5d, 0x44, 0x50, 0x00, 0xff, 0xd0, 0x03, +0x49, 0xff, 0xfe, 0xb8, 0x2e, 0x01, 0x8a, 0x5e, 0x44, 0x50, 0x00, 0xff, 0xd0, 0x03, 0x49, 0xff, +0xfe, 0xf1, 0x3c, 0x0c, 0x62, 0x8a, 0x84, 0xbf, 0xd0, 0x03, 0x49, 0xff, 0xfe, 0xd1, 0x84, 0x1f, +0x3e, 0x01, 0x8a, 0x5e, 0x84, 0x5f, 0x3c, 0x2e, 0x62, 0x8a, 0x3e, 0x01, 0x8a, 0x5b, 0x3e, 0x01, +0x8a, 0x5c, 0x3e, 0x01, 0x8a, 0x5d, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0xc0, 0x02, 0x84, 0x01, 0x3e, 0x01, 0x8a, 0x5f, 0x84, 0x00, 0x84, 0x21, 0x80, 0x40, +0x49, 0xff, 0xff, 0x12, 0xc8, 0x05, 0x3e, 0x09, 0x80, 0xc0, 0x49, 0xff, 0x92, 0x29, 0x46, 0x10, +0x04, 0x11, 0x04, 0x20, 0x80, 0x8f, 0x84, 0x01, 0x58, 0x21, 0x00, 0x08, 0x14, 0x20, 0x80, 0x8f, +0x80, 0x20, 0x84, 0x40, 0x49, 0xff, 0xff, 0x00, 0xc8, 0x05, 0x3e, 0x09, 0x80, 0xfc, 0x49, 0xff, +0x92, 0x17, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x20, 0x84, 0xa3, 0x54, 0x10, 0x80, 0x03, +0xd1, 0x03, 0x84, 0x00, 0xd5, 0x10, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x0d, 0xc8, 0x03, 0x80, 0x01, +0xd5, 0x07, 0x84, 0xa2, 0xd8, 0x02, 0xd5, 0x03, 0x84, 0xa3, 0xd8, 0x04, 0x84, 0x00, 0x49, 0xff, +0xff, 0xbf, 0x84, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xec, 0x80, 0xc0, 0x81, 0x41, 0x80, 0xe2, 0x81, 0x23, 0x81, 0x04, 0xe6, 0x0a, 0x4e, 0xf2, +0x01, 0x06, 0xe6, 0x64, 0x4e, 0xf2, 0x01, 0x03, 0xe6, 0x22, 0x4e, 0xf2, 0x01, 0x00, 0x9e, 0x11, +0xe6, 0x06, 0x4e, 0xf2, 0x00, 0xfc, 0x9e, 0x21, 0xe6, 0x04, 0x4e, 0xf2, 0x00, 0xf8, 0xe6, 0xc4, +0xe8, 0x03, 0x84, 0x20, 0xd5, 0x07, 0x80, 0x26, 0x3e, 0x09, 0x81, 0x38, 0x49, 0xff, 0x91, 0xd0, +0x84, 0x21, 0x41, 0xc3, 0x10, 0x08, 0x4e, 0xa3, 0x00, 0x19, 0x80, 0x29, 0x3e, 0x09, 0x81, 0x58, +0x80, 0x46, 0x49, 0xff, 0x91, 0xc5, 0x44, 0x00, 0x00, 0x28, 0x42, 0x94, 0x80, 0x24, 0x3e, 0x19, +0xeb, 0x30, 0x3e, 0x09, 0xeb, 0xd0, 0x41, 0xce, 0x00, 0x00, 0x89, 0x21, 0xb7, 0x5c, 0x80, 0x0a, +0x14, 0xa4, 0x80, 0x01, 0x48, 0x00, 0x00, 0xd4, 0x3e, 0x39, 0xeb, 0xd0, 0x98, 0xb6, 0x40, 0x0e, +0x0c, 0x00, 0x9c, 0x91, 0x1c, 0xa0, 0x00, 0x01, 0x80, 0x83, 0x94, 0xd3, 0x98, 0xdc, 0xb6, 0xe0, +0x38, 0x92, 0x0b, 0x0a, 0x14, 0x81, 0x80, 0x01, 0xc9, 0x40, 0x84, 0x03, 0x4c, 0x80, 0x00, 0x2f, +0x84, 0x24, 0x4c, 0x80, 0x80, 0x1e, 0x84, 0x62, 0x4c, 0x81, 0x80, 0x0e, 0x3c, 0x6e, 0x62, 0x85, +0x4c, 0x71, 0x80, 0x07, 0x4c, 0x70, 0x80, 0x05, 0x84, 0x85, 0x4c, 0x72, 0x40, 0x43, 0x3c, 0x6e, +0x62, 0x83, 0xd5, 0x3f, 0x3c, 0x6e, 0x62, 0x86, 0x4c, 0x74, 0x00, 0x08, 0x84, 0x04, 0x4c, 0x70, +0x00, 0x05, 0x84, 0x25, 0x4c, 0x70, 0xc0, 0x28, 0x3c, 0x6e, 0x62, 0x84, 0xd5, 0x24, 0x84, 0x61, +0x3c, 0x6e, 0x62, 0x87, 0x4c, 0x71, 0x80, 0x08, 0x84, 0x83, 0x4c, 0x72, 0x00, 0x05, 0x84, 0x06, +0x4c, 0x70, 0x40, 0x1d, 0x3e, 0x09, 0x8a, 0x0c, 0xd5, 0x0e, 0x84, 0x21, 0x3c, 0x6e, 0x62, 0x88, +0x4c, 0x70, 0x80, 0x08, 0x84, 0x63, 0x4c, 0x71, 0x80, 0x05, 0x84, 0x86, 0x4c, 0x72, 0x40, 0x0f, +0x3e, 0x09, 0x8a, 0x10, 0xb6, 0xc0, 0xd5, 0x0a, 0x84, 0x01, 0x4c, 0x80, 0x00, 0x13, 0x84, 0x22, +0x4c, 0x80, 0xc0, 0x05, 0x3e, 0x49, 0x81, 0x80, 0xd5, 0x0e, 0x56, 0x24, 0x00, 0x04, 0x3e, 0x09, +0x81, 0x88, 0x3e, 0x19, 0x81, 0x8c, 0x40, 0x40, 0x88, 0x1b, 0x40, 0x40, 0x08, 0x1a, 0xd5, 0x03, +0x3e, 0x49, 0x81, 0x90, 0x3c, 0xac, 0x62, 0x84, 0x3c, 0x5c, 0x62, 0x83, 0xb7, 0x5f, 0x3c, 0xac, +0x62, 0x85, 0x3e, 0x09, 0x81, 0x94, 0x14, 0xaf, 0x80, 0x01, 0x3c, 0xac, 0x62, 0x86, 0x80, 0x67, +0x80, 0x29, 0x80, 0x46, 0x14, 0xaf, 0x80, 0x02, 0x49, 0xff, 0x91, 0x3a, 0x44, 0x00, 0x00, 0x28, +0x42, 0x04, 0x80, 0x24, 0x3e, 0x39, 0xeb, 0x30, 0x98, 0x03, 0x84, 0x81, 0xa9, 0xc1, 0x4c, 0x82, +0x00, 0x05, 0x84, 0x24, 0x4c, 0x80, 0xc0, 0x0b, 0x44, 0x00, 0x00, 0x28, 0x42, 0x04, 0x80, 0x24, +0x98, 0x03, 0x14, 0x80, 0x00, 0x05, 0xa9, 0x87, 0xd5, 0x05, 0x14, 0x80, 0x00, 0x06, 0x14, 0x60, +0x00, 0x08, 0x99, 0xb6, 0x44, 0x00, 0x00, 0x28, 0x42, 0x04, 0x80, 0x24, 0x9d, 0xb1, 0x3e, 0x49, +0xeb, 0x30, 0x3e, 0x19, 0xeb, 0xd0, 0x95, 0xb3, 0x98, 0x04, 0x99, 0xb1, 0xa0, 0x81, 0xa0, 0x31, +0x44, 0x40, 0xff, 0x00, 0x54, 0x21, 0x00, 0x0f, 0x54, 0x00, 0x00, 0xf0, 0x94, 0x04, 0x40, 0x94, +0x90, 0x02, 0x42, 0x21, 0x4c, 0x08, 0x40, 0x21, 0x00, 0x04, 0x40, 0x94, 0xa0, 0x08, 0x40, 0x21, +0x24, 0x04, 0x44, 0x10, 0x00, 0x73, 0x84, 0x00, 0x49, 0xfb, 0xc4, 0xfe, 0x84, 0x00, 0x84, 0x21, +0x80, 0x40, 0x49, 0xff, 0xfd, 0xd9, 0xc8, 0x05, 0x3e, 0x09, 0x81, 0xf0, 0x49, 0xff, 0x90, 0xf0, +0x84, 0x01, 0x80, 0x20, 0x84, 0x40, 0x49, 0xff, 0xfd, 0xcf, 0xc0, 0x02, 0xd5, 0x05, 0x3e, 0x09, +0x82, 0x18, 0x49, 0xff, 0x90, 0xe5, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x14, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, 0x80, 0xe1, 0x81, 0x02, +0x3e, 0x09, 0x82, 0x40, 0x80, 0x23, 0x80, 0xc3, 0x80, 0x49, 0x80, 0x67, 0x80, 0x88, 0x49, 0xff, +0x90, 0xcf, 0x50, 0x04, 0xff, 0xff, 0xe6, 0x0e, 0xe8, 0x5b, 0x9e, 0x39, 0xe6, 0x03, 0xe8, 0x58, +0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0f, 0x84, 0x05, 0x42, 0x03, 0x00, 0x24, 0x3e, 0x29, 0xeb, 0x30, +0x9c, 0x01, 0x94, 0x43, 0x98, 0x4a, 0x14, 0x90, 0x80, 0x01, 0x38, 0x71, 0x03, 0x0a, 0xd5, 0x1c, +0x84, 0xa2, 0x4c, 0x82, 0xc0, 0x1a, 0x84, 0x25, 0x42, 0x13, 0x04, 0x24, 0x44, 0x20, 0x00, 0x28, +0x9c, 0x49, 0x42, 0x23, 0x08, 0x24, 0x3e, 0x09, 0xeb, 0x30, 0x95, 0x0b, 0x98, 0x90, 0x99, 0x20, +0x84, 0x00, 0xa8, 0x21, 0x9c, 0xd4, 0x3e, 0x49, 0xeb, 0x30, 0x50, 0x21, 0x00, 0x20, 0x38, 0x02, +0x07, 0x0a, 0xae, 0x14, 0xb6, 0x03, 0x44, 0x10, 0x00, 0x28, 0x84, 0x05, 0x42, 0x03, 0x00, 0x24, +0x42, 0x63, 0x04, 0x24, 0x3e, 0x19, 0xeb, 0x30, 0x99, 0xb1, 0x9c, 0x01, 0x14, 0x83, 0x00, 0x04, +0x94, 0x03, 0x98, 0x01, 0xa0, 0x01, 0x46, 0x20, 0x40, 0x00, 0x58, 0x21, 0x00, 0x10, 0x84, 0x22, +0x40, 0x60, 0x08, 0x04, 0x4c, 0x70, 0xc0, 0x08, 0x46, 0x20, 0x40, 0x00, 0x58, 0x21, 0x00, 0x90, +0x40, 0x60, 0x08, 0x04, 0x3e, 0x09, 0x82, 0x78, 0x80, 0x26, 0x49, 0xff, 0x90, 0x79, 0x80, 0x46, +0x84, 0x00, 0x44, 0x10, 0x00, 0x73, 0x49, 0xfb, 0xc4, 0x77, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x40, +0x3c, 0x2e, 0x62, 0xb9, 0x3e, 0x09, 0xec, 0x70, 0x49, 0xff, 0x90, 0xb0, 0x84, 0x01, 0x49, 0xff, +0xfc, 0xc1, 0x49, 0xff, 0xfc, 0xa7, 0x3e, 0x09, 0x82, 0xb8, 0x49, 0xff, 0x90, 0x59, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x3e, 0x09, +0x82, 0xd8, 0x49, 0xff, 0x90, 0x4d, 0x49, 0xff, 0xff, 0xe1, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x84, 0xa2, 0xf0, 0x81, 0x80, 0x5f, +0x84, 0x20, 0x84, 0x68, 0x84, 0x09, 0xb6, 0xbf, 0x49, 0xff, 0x9f, 0xfa, 0x92, 0x00, 0x84, 0x01, +0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc0, 0x3c, 0x00, +0xc5, 0x26, 0x49, 0xff, 0xff, 0xe9, 0x54, 0x03, 0x00, 0x04, 0xc0, 0x04, 0x44, 0x74, 0x00, 0x04, +0xd5, 0x3b, 0x54, 0x03, 0x00, 0x08, 0xc0, 0x04, 0x44, 0x74, 0x00, 0x06, 0xd5, 0x35, 0x54, 0x03, +0x00, 0x20, 0xc8, 0x30, 0x54, 0x03, 0x00, 0x10, 0xc0, 0x04, 0x44, 0x74, 0x00, 0x05, 0xd5, 0x2c, +0x54, 0x03, 0x00, 0x40, 0xc0, 0x04, 0x44, 0x74, 0x00, 0x07, 0xd5, 0x26, 0x54, 0x13, 0x00, 0x02, +0xc9, 0x21, 0x96, 0x34, 0xc0, 0x0b, 0x46, 0x24, 0x00, 0x00, 0x80, 0x01, 0x44, 0x10, 0x00, 0x73, +0x49, 0xfb, 0xc4, 0x0a, 0x44, 0x74, 0x00, 0x01, 0xd5, 0x17, 0x54, 0x13, 0x00, 0x80, 0xc1, 0x0a, +0x46, 0x28, 0x00, 0x00, 0x44, 0x10, 0x00, 0x73, 0x49, 0xfb, 0xc3, 0xfe, 0x44, 0x74, 0x00, 0x02, +0xd5, 0x0b, 0x3e, 0x09, 0x82, 0xfc, 0x80, 0x26, 0x49, 0xff, 0x8f, 0xf2, 0x44, 0x74, 0x00, 0x00, +0xd5, 0x03, 0x44, 0x74, 0x00, 0x03, 0x3e, 0x09, 0x83, 0x20, 0x80, 0x27, 0x49, 0xff, 0x8f, 0xe8, +0x44, 0x10, 0x00, 0x73, 0x80, 0x47, 0x84, 0x00, 0x49, 0xfb, 0xc3, 0xe6, 0x2e, 0x07, 0xef, 0xdc, +0x84, 0xa4, 0xd0, 0x2d, 0x84, 0x28, 0x4c, 0x00, 0x80, 0x2b, 0x40, 0x03, 0x04, 0x02, 0xc0, 0x1f, +0x3e, 0x09, 0x83, 0x30, 0x49, 0xff, 0x8f, 0xd4, 0x84, 0x61, 0x3c, 0x3e, 0x62, 0xb9, 0x3e, 0x09, +0xec, 0x70, 0x44, 0x10, 0x07, 0xd0, 0x49, 0xff, 0x90, 0xdf, 0x46, 0x40, 0x04, 0x11, 0x80, 0x64, +0x80, 0x43, 0x80, 0x22, 0x84, 0x00, 0x14, 0x02, 0x00, 0x92, 0x14, 0x01, 0x80, 0x93, 0x14, 0x01, +0x00, 0x94, 0x14, 0x00, 0x80, 0x95, 0x49, 0xff, 0xfc, 0x1d, 0xd5, 0x09, 0x54, 0x63, 0x00, 0x10, +0xc6, 0x06, 0x3c, 0x0c, 0x62, 0xb9, 0xc0, 0x03, 0x49, 0xff, 0xff, 0x48, 0x84, 0x01, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe1, 0x80, 0xc0, 0xf2, 0x81, +0xc9, 0x08, 0x3e, 0x09, 0x83, 0x50, 0x49, 0xff, 0x8f, 0xa3, 0x80, 0xc7, 0x48, 0x00, 0x01, 0xdf, +0x44, 0x80, 0x00, 0x28, 0x3e, 0x09, 0x83, 0x68, 0x80, 0x26, 0x80, 0x47, 0x42, 0x83, 0x20, 0x24, +0x49, 0xff, 0x8f, 0x96, 0x3e, 0x09, 0xeb, 0x30, 0x89, 0x00, 0x44, 0x50, 0x00, 0x1a, 0xb6, 0xe8, +0x4c, 0x72, 0x80, 0x96, 0xe6, 0xfb, 0xe8, 0x1b, 0xe6, 0xe8, 0xe8, 0x0f, 0xe6, 0xe6, 0x4e, 0xf2, +0x00, 0xae, 0x84, 0xa3, 0x4c, 0x72, 0x80, 0xab, 0xe6, 0xe4, 0x4e, 0xf2, 0x00, 0xb9, 0x84, 0xa1, +0xd7, 0x3a, 0x84, 0xa2, 0xdf, 0x35, 0xd5, 0x47, 0x9f, 0x6c, 0xd7, 0x64, 0xe6, 0xf7, 0x4e, 0xf2, +0x00, 0xbb, 0x9f, 0x6a, 0x4c, 0x72, 0x80, 0xb8, 0x9c, 0xe9, 0xd5, 0x13, 0x44, 0x50, 0x00, 0xb4, +0x4c, 0x72, 0x80, 0xb2, 0x5c, 0xf3, 0x80, 0xb5, 0xe8, 0x13, 0x9f, 0x6c, 0x4c, 0x72, 0x80, 0x9e, +0x5c, 0xf3, 0x80, 0xb1, 0xe8, 0x09, 0x44, 0x50, 0x00, 0x1b, 0x4c, 0x72, 0x80, 0xa5, 0x9c, 0xe9, +0x4c, 0x71, 0xc0, 0x17, 0xd5, 0x1b, 0x5c, 0xf3, 0x80, 0xb2, 0xe9, 0x12, 0xd5, 0x60, 0x5c, 0xf3, +0x80, 0xb9, 0xe8, 0x07, 0x5c, 0xf3, 0x80, 0xb7, 0xe8, 0x5a, 0x9d, 0x69, 0xdf, 0x09, 0xd5, 0x57, +0x9c, 0x6e, 0x4c, 0x70, 0x80, 0x55, 0xe2, 0xe1, 0xe9, 0x35, 0x9d, 0x49, 0xd7, 0x07, 0x84, 0xc0, +0x48, 0x00, 0x01, 0x85, 0x80, 0xc7, 0x48, 0x00, 0x00, 0x88, 0x44, 0x00, 0x00, 0x28, 0x42, 0x63, +0x00, 0x24, 0x3e, 0x39, 0xeb, 0x30, 0x99, 0xb3, 0x84, 0x01, 0x10, 0x03, 0x00, 0x24, 0x95, 0x84, +0x48, 0x00, 0x00, 0x7b, 0x49, 0xff, 0xfc, 0x94, 0x84, 0x01, 0x49, 0xff, 0xfc, 0x01, 0x84, 0x05, +0x42, 0x63, 0x00, 0x24, 0x3e, 0x09, 0xeb, 0x30, 0x9d, 0xb1, 0x94, 0x73, 0x50, 0x24, 0x00, 0x04, +0x98, 0x48, 0x84, 0x00, 0xb6, 0x02, 0x50, 0x34, 0x00, 0x20, 0x3e, 0x29, 0xeb, 0x30, 0x8d, 0x10, +0x38, 0x01, 0x1b, 0x0a, 0xb6, 0x08, 0x44, 0x60, 0x00, 0x80, 0xa8, 0x09, 0xae, 0x1c, 0xae, 0x1d, +0xd5, 0x5b, 0x84, 0x85, 0x42, 0x43, 0x10, 0x24, 0x44, 0x00, 0x00, 0x28, 0x42, 0x63, 0x00, 0x24, +0x9d, 0x21, 0x3e, 0x19, 0xeb, 0x30, 0x99, 0xb1, 0x80, 0x41, 0x94, 0x63, 0x84, 0x00, 0x98, 0x4a, +0x9c, 0xb4, 0xb6, 0x02, 0x50, 0x33, 0x00, 0x20, 0x3e, 0x29, 0xeb, 0x30, 0x8c, 0xd0, 0x38, 0x01, +0x13, 0x0a, 0xb6, 0x06, 0xa8, 0x09, 0xae, 0x1c, 0xae, 0x1d, 0xd5, 0x3b, 0x84, 0x85, 0x42, 0x43, +0x10, 0x24, 0x44, 0x00, 0x00, 0x28, 0x42, 0x63, 0x00, 0x24, 0x9d, 0x21, 0x3e, 0x39, 0xeb, 0x30, +0x99, 0xb3, 0x80, 0x03, 0x94, 0x63, 0x9c, 0xb4, 0x98, 0x48, 0x84, 0x00, 0xb6, 0x02, 0x50, 0x33, +0x00, 0x20, 0x3e, 0x29, 0xeb, 0x30, 0x8c, 0xd0, 0x38, 0x01, 0x13, 0x0a, 0xb6, 0x06, 0xa8, 0x09, +0x44, 0x60, 0x00, 0x20, 0xae, 0x1c, 0xae, 0x1d, 0xd5, 0x1f, 0x80, 0x26, 0x3e, 0x09, 0x83, 0x90, +0x49, 0xff, 0x8e, 0xd6, 0x44, 0x00, 0x00, 0x28, 0x42, 0x63, 0x00, 0x24, 0x3e, 0x19, 0xeb, 0x30, +0x99, 0xb1, 0x84, 0x01, 0x10, 0x03, 0x00, 0x25, 0x84, 0xc0, 0xd5, 0x0e, 0x3e, 0x09, 0x83, 0xa4, +0x84, 0x20, 0x49, 0xff, 0x8e, 0xc5, 0x50, 0x84, 0x00, 0x20, 0x84, 0x00, 0x10, 0x04, 0x00, 0x05, +0x84, 0xc2, 0xd5, 0x02, 0x84, 0xc8, 0x2e, 0x01, 0x8a, 0x54, 0xc0, 0x03, 0x58, 0x63, 0x00, 0x40, +0x3f, 0xc9, 0xeb, 0x38, 0x85, 0x00, 0xb5, 0x3c, 0x84, 0xa2, 0x4c, 0x92, 0x80, 0x13, 0x84, 0xa3, +0x4c, 0x92, 0x80, 0x18, 0x84, 0x01, 0x4c, 0x90, 0x00, 0x04, 0x84, 0x00, 0xd5, 0x1a, 0x3e, 0x09, +0x83, 0xb8, 0x80, 0x28, 0x49, 0xff, 0x8e, 0xa4, 0x42, 0x63, 0x40, 0x08, 0x80, 0x09, 0xd5, 0x11, +0x3e, 0x09, 0x83, 0xc4, 0x80, 0x28, 0x49, 0xff, 0x8e, 0x9b, 0x42, 0x63, 0x44, 0x08, 0xd5, 0x08, +0x80, 0x28, 0x3e, 0x09, 0x83, 0xd0, 0x49, 0xff, 0x8e, 0x93, 0x42, 0x63, 0x48, 0x08, 0x84, 0x01, +0x8d, 0x01, 0x84, 0xa4, 0x4c, 0x82, 0xc0, 0x06, 0x3e, 0x39, 0xeb, 0x55, 0x84, 0x00, 0xd5, 0x05, +0x51, 0xce, 0x00, 0x28, 0xc0, 0xd1, 0xd5, 0xf9, 0xa6, 0x98, 0x50, 0x31, 0x80, 0x28, 0xc2, 0x09, +0x80, 0x20, 0x3e, 0x09, 0x83, 0xdc, 0x58, 0x63, 0x00, 0x04, 0x49, 0xff, 0x8e, 0x79, 0xd5, 0x04, +0x9c, 0x01, 0x84, 0xa4, 0xd8, 0xf2, 0x3e, 0x09, 0xeb, 0x30, 0x00, 0x10, 0x00, 0x24, 0xc1, 0x03, +0x84, 0x00, 0xd5, 0x0f, 0x00, 0x10, 0x00, 0x4c, 0xc1, 0x03, 0x84, 0x01, 0xd5, 0x0a, 0x00, 0x10, +0x00, 0x74, 0xc1, 0x03, 0x84, 0x02, 0xd5, 0x05, 0x00, 0x00, 0x00, 0x9c, 0xc0, 0x14, 0x84, 0x03, +0x44, 0x10, 0x00, 0x28, 0x42, 0x10, 0x04, 0x24, 0x3e, 0x39, 0xeb, 0x30, 0x98, 0x4b, 0x00, 0x20, +0x80, 0x24, 0x58, 0x63, 0x00, 0x10, 0x80, 0x20, 0x3e, 0x09, 0x83, 0xec, 0x42, 0x63, 0x04, 0x09, +0x49, 0xff, 0x8e, 0x4e, 0x3e, 0x09, 0xeb, 0x30, 0xa0, 0x43, 0xc1, 0x03, 0x84, 0x00, 0xd5, 0x0f, +0x04, 0x20, 0x00, 0x0d, 0xc2, 0x03, 0x84, 0x01, 0xd5, 0x0a, 0x04, 0x30, 0x00, 0x17, 0xc3, 0x03, +0x84, 0x02, 0xd5, 0x05, 0x04, 0x00, 0x00, 0x21, 0xc0, 0x16, 0x84, 0x03, 0x84, 0x45, 0x42, 0x20, +0x08, 0x24, 0x80, 0x20, 0x9c, 0x11, 0x94, 0x03, 0x3e, 0x29, 0xeb, 0x30, 0x98, 0x02, 0xa0, 0x81, +0x3e, 0x09, 0x83, 0xfc, 0x54, 0x31, 0x00, 0x0f, 0x40, 0x31, 0xcc, 0x08, 0x40, 0x63, 0x0c, 0x04, +0x49, 0xff, 0x8e, 0x26, 0x3e, 0xa9, 0xeb, 0x34, 0x85, 0x00, 0xb4, 0x0a, 0x84, 0xa3, 0xd0, 0x1c, +0xe6, 0x04, 0xe8, 0x06, 0x84, 0xa1, 0xd0, 0x0c, 0x84, 0xa2, 0xd8, 0x2f, 0xd5, 0x0f, 0x84, 0x65, +0x4c, 0x01, 0x80, 0x1f, 0xe2, 0x03, 0xe9, 0x16, 0x84, 0xa6, 0xd8, 0x27, 0xd5, 0x1f, 0x3e, 0x09, +0x84, 0x0c, 0x80, 0x28, 0x58, 0x63, 0x01, 0x00, 0xd5, 0x1e, 0x3e, 0x09, 0x84, 0x20, 0x80, 0x28, +0x58, 0x63, 0x02, 0x00, 0xd5, 0x18, 0x3e, 0x09, 0x84, 0x34, 0x80, 0x28, 0x58, 0x63, 0x04, 0x00, +0xd5, 0x12, 0x3e, 0x09, 0x84, 0x48, 0x80, 0x28, 0x58, 0x63, 0x08, 0x00, 0xd5, 0x0c, 0x3e, 0x09, +0x84, 0x5c, 0x80, 0x28, 0x58, 0x63, 0x20, 0x00, 0xd5, 0x06, 0x3e, 0x09, 0x84, 0x70, 0x80, 0x28, +0x58, 0x63, 0x10, 0x00, 0x49, 0xff, 0x8d, 0xec, 0x8d, 0x01, 0x84, 0xa4, 0x50, 0xa5, 0x00, 0x28, +0x4c, 0x82, 0xff, 0xc5, 0x80, 0x26, 0x3e, 0x09, 0x84, 0x84, 0x49, 0xff, 0x8d, 0xe1, 0x80, 0x06, +0x49, 0xff, 0xfd, 0xac, 0x44, 0x30, 0x00, 0xb0, 0x80, 0xc0, 0x4c, 0x71, 0x80, 0x04, 0x9d, 0x5c, +0xdf, 0x04, 0xf1, 0x01, 0x84, 0x01, 0xd5, 0x0f, 0x9d, 0x6f, 0xdf, 0x04, 0x84, 0x00, 0x80, 0x20, +0xd5, 0x0a, 0x9f, 0x6a, 0xdf, 0x04, 0x84, 0x20, 0x84, 0x03, 0xd5, 0x05, 0x9d, 0x5a, 0xdf, 0x06, +0x84, 0x02, 0x84, 0x20, 0x49, 0xff, 0xfb, 0xb4, 0x92, 0x00, 0x80, 0x06, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x84, 0xc1, 0xf0, 0x81, 0x80, 0x5f, +0x84, 0x20, 0x84, 0x68, 0x84, 0x09, 0xb6, 0xdf, 0x49, 0xff, 0x9d, 0x72, 0x92, 0x00, 0x80, 0x06, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x40, 0x10, +0x40, 0x09, 0x40, 0x10, 0xc0, 0x08, 0x44, 0x51, 0x00, 0x00, 0xd1, 0x77, 0x46, 0x51, 0x00, 0x00, +0x4c, 0x12, 0xc0, 0x88, 0x54, 0x10, 0x00, 0x02, 0xf1, 0x81, 0x54, 0x80, 0x00, 0x01, 0x84, 0x21, +0xf2, 0x01, 0x40, 0x74, 0x20, 0x1a, 0x40, 0x70, 0xa0, 0x1b, 0x44, 0x10, 0x04, 0x00, 0x40, 0x64, +0x20, 0x1a, 0x40, 0x60, 0xa0, 0x1b, 0x96, 0x00, 0xc2, 0x03, 0x58, 0x63, 0x01, 0x00, 0x54, 0x10, +0x00, 0x04, 0xb6, 0x3f, 0xc1, 0x03, 0x58, 0x63, 0x00, 0x10, 0x55, 0xc0, 0x00, 0x08, 0x84, 0x21, +0x54, 0xa0, 0x00, 0x10, 0x40, 0x70, 0xf0, 0x1b, 0x4e, 0xa2, 0x00, 0x04, 0x58, 0x63, 0x10, 0x00, +0x54, 0x90, 0x00, 0x20, 0x4e, 0x92, 0x00, 0x04, 0x58, 0x63, 0x10, 0x00, 0xc7, 0x0a, 0x84, 0x01, +0x49, 0xff, 0xfa, 0x10, 0x44, 0x00, 0x02, 0x71, 0x49, 0xff, 0xf9, 0xf2, 0x84, 0x01, 0xd5, 0x09, +0x80, 0x07, 0x49, 0xff, 0xfa, 0x07, 0x44, 0x00, 0x13, 0x88, 0x49, 0xff, 0xf9, 0xe9, 0x80, 0x07, +0x49, 0xff, 0xfb, 0x26, 0x4e, 0x82, 0x00, 0x05, 0x3e, 0x19, 0x84, 0xa0, 0xd5, 0x1d, 0xf2, 0x01, +0xc2, 0x04, 0x3e, 0x19, 0x84, 0xa4, 0xd5, 0x18, 0xb4, 0x1f, 0xc0, 0x04, 0x3e, 0x19, 0x84, 0xac, +0xd5, 0x13, 0x4f, 0xc2, 0x00, 0x05, 0x3e, 0x19, 0x84, 0xb4, 0xd5, 0x0e, 0x4e, 0xa2, 0x00, 0x05, +0x3e, 0x19, 0x84, 0xb8, 0xd5, 0x09, 0x3e, 0x09, 0x84, 0xc0, 0x3e, 0x29, 0x84, 0xc8, 0x40, 0x11, +0x24, 0x1b, 0x40, 0x10, 0x24, 0x1a, 0x46, 0x00, 0x04, 0x11, 0x04, 0x30, 0x00, 0x8f, 0x80, 0x47, +0x42, 0x31, 0xe0, 0x0b, 0x3e, 0x09, 0x84, 0xd0, 0x49, 0xff, 0x8d, 0x32, 0x3c, 0x68, 0xc5, 0x26, +0x80, 0x06, 0x49, 0xff, 0xfc, 0xe9, 0xd5, 0x15, 0x54, 0x10, 0x00, 0x06, 0x84, 0xa6, 0xd9, 0x07, +0x3e, 0x09, 0x85, 0x04, 0x49, 0xff, 0x8d, 0x24, 0x84, 0x01, 0xd5, 0x08, 0x96, 0x04, 0xc0, 0x09, +0x3e, 0x09, 0x85, 0x1c, 0x49, 0xff, 0x8d, 0x1c, 0x84, 0x03, 0x49, 0xff, 0xff, 0x5d, 0x92, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x40, +0x3e, 0x09, 0xec, 0x70, 0x46, 0x10, 0x00, 0x8e, 0x58, 0x10, 0x88, 0xa8, 0x80, 0x62, 0x49, 0xff, +0x8d, 0x3b, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x10, 0x04, 0x10, +0x04, 0x20, 0x81, 0x01, 0x84, 0x61, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x08, 0x04, 0x14, 0x00, +0x81, 0x01, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x01, 0x58, 0x10, 0x80, 0x0f, +0x14, 0x10, 0x01, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x01, 0x01, +0x92, 0x24, 0x94, 0x4c, 0x14, 0x10, 0x01, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x11, +0x46, 0x10, 0xff, 0xff, 0x58, 0x10, 0x8f, 0x02, 0x14, 0x10, 0x00, 0x89, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0x3c, 0x85, 0x5f, 0x96, 0x00, 0x46, 0x90, 0x04, 0x11, 0x81, 0x09, 0x80, 0xe8, +0x80, 0xc7, 0x80, 0xa6, 0x80, 0x85, 0x80, 0x64, 0x80, 0x43, 0x40, 0x10, 0x00, 0x1a, 0x40, 0x15, +0x00, 0x1b, 0x14, 0x14, 0x80, 0x1b, 0x14, 0x14, 0x00, 0x1c, 0x14, 0x13, 0x80, 0x1d, 0x14, 0x13, +0x00, 0x1e, 0x14, 0x12, 0x80, 0x1f, 0x14, 0x12, 0x00, 0x20, 0x14, 0x11, 0x80, 0x21, 0x14, 0x11, +0x00, 0x22, 0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x41, 0x58, 0x10, +0x80, 0x04, 0xa8, 0x41, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x00, +0x04, 0x11, 0xa0, 0x41, 0x42, 0x10, 0x88, 0x09, 0x80, 0xe0, 0xa8, 0x41, 0x84, 0xc0, 0x44, 0xa0, +0x01, 0x2c, 0x9d, 0xb1, 0x40, 0x13, 0x28, 0x17, 0x05, 0xc3, 0x80, 0x80, 0xc8, 0x07, 0x3e, 0x09, +0x85, 0x34, 0x49, 0xff, 0x8c, 0x95, 0x49, 0xff, 0xff, 0xb3, 0x54, 0x0e, 0x00, 0x01, 0xc0, 0x04, +0x44, 0x50, 0x0b, 0xb8, 0xde, 0xef, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x84, 0x00, 0xd5, 0x0b, 0x92, 0x00, 0x84, 0x47, 0x9c, 0x49, 0x4c, 0x11, 0x7f, 0xfd, 0x9c, 0x01, +0x44, 0x10, 0x00, 0x1e, 0x4c, 0x00, 0x80, 0x04, 0x84, 0x20, 0xd5, 0xf5, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x96, 0x00, 0xc0, 0x08, 0x46, 0x00, 0x04, 0x09, 0xa0, 0x46, 0x42, 0x10, +0xdc, 0x08, 0xa8, 0x46, 0xd5, 0x1d, 0x46, 0x00, 0x04, 0x09, 0xa0, 0x46, 0x42, 0x10, 0xdc, 0x09, +0xa8, 0x46, 0x2e, 0x71, 0x8a, 0x60, 0xcf, 0x14, 0x80, 0xc0, 0xd5, 0x0d, 0x44, 0x50, 0x03, 0xe9, +0xdf, 0x07, 0x3e, 0x09, 0x85, 0x3c, 0x49, 0xff, 0x8c, 0x5b, 0x92, 0x00, 0xd5, 0x09, 0x9d, 0xf9, +0x49, 0xff, 0xff, 0xd0, 0x04, 0x03, 0x00, 0x40, 0x94, 0x05, 0x92, 0x19, 0xc8, 0xf0, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x70, 0x04, 0x10, 0x84, 0xc0, 0xd5, 0x20, +0x44, 0x50, 0x00, 0x65, 0xde, 0x1b, 0x3c, 0x5c, 0x62, 0x8c, 0x44, 0x00, 0x00, 0x1c, 0x42, 0x52, +0x80, 0x24, 0x3e, 0x39, 0xec, 0x8c, 0x80, 0x22, 0x80, 0x01, 0x04, 0x21, 0x02, 0x8c, 0x99, 0x6b, +0x04, 0x30, 0x81, 0x01, 0x04, 0x40, 0x01, 0x0d, 0xa6, 0x69, 0x3e, 0x09, 0x85, 0x54, 0x96, 0x90, +0x49, 0xff, 0x8c, 0x2e, 0x92, 0x00, 0x84, 0x00, 0xd5, 0x0b, 0x49, 0xff, 0xff, 0xa3, 0x04, 0x03, +0x82, 0x8c, 0x46, 0x20, 0x04, 0x10, 0x96, 0x00, 0x9d, 0xb1, 0xc8, 0xdb, 0x84, 0x01, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x40, 0xa0, 0x0c, 0x08, 0x80, 0xe0, +0x8d, 0x43, 0x46, 0x60, 0x04, 0x10, 0x44, 0x00, 0x00, 0x1f, 0x40, 0xa0, 0x28, 0x0c, 0x84, 0x60, +0xd5, 0x20, 0x44, 0x00, 0x00, 0x65, 0x4c, 0x80, 0x40, 0x1a, 0x3c, 0x1c, 0x62, 0x8c, 0x44, 0x00, +0x00, 0x1c, 0x42, 0x00, 0x80, 0x24, 0x3e, 0x19, 0xec, 0x8c, 0x98, 0x01, 0x50, 0x62, 0x7f, 0xd0, +0xa6, 0x41, 0xb4, 0xa4, 0xb5, 0x06, 0x3e, 0x09, 0x85, 0xa8, 0x80, 0x47, 0xb6, 0xdf, 0x14, 0x8f, +0x80, 0x01, 0x49, 0xff, 0x8b, 0xf5, 0x84, 0x00, 0xd5, 0x10, 0x49, 0xff, 0xff, 0x6b, 0x80, 0x68, +0x04, 0x03, 0x01, 0x0d, 0x46, 0x40, 0x04, 0x10, 0x40, 0x05, 0x00, 0x02, 0x50, 0x81, 0x80, 0x01, +0x58, 0x42, 0x04, 0x34, 0xc8, 0xd7, 0x84, 0x01, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x44, 0x46, 0x43, 0x20, 0xb4, 0xa4, 0x84, 0x40, 0x58, 0x52, 0x80, 0x10, +0xb6, 0xa4, 0x80, 0x62, 0x3e, 0x09, 0xec, 0xfc, 0x46, 0x10, 0x00, 0x8f, 0x58, 0x10, 0x81, 0xd0, +0x49, 0xff, 0x8c, 0x02, 0x84, 0x40, 0x3e, 0x09, 0xed, 0x38, 0x46, 0x10, 0x00, 0x8f, 0x58, 0x10, +0x85, 0x64, 0x80, 0x62, 0x49, 0xff, 0x8b, 0xf8, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x11, 0x04, 0x30, 0x00, 0x47, 0x3c, 0x3e, +0x62, 0xbd, 0x84, 0x20, 0x84, 0x0c, 0x49, 0xff, 0x9c, 0x2b, 0x92, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x96, 0x00, 0x96, 0x48, 0xc0, 0x1a, 0x84, 0x41, +0x4c, 0x01, 0x40, 0x08, 0x46, 0x00, 0x04, 0x1d, 0x58, 0x00, 0x0e, 0x00, 0x84, 0x4d, 0xd5, 0x16, +0x84, 0x82, 0x4c, 0x02, 0x40, 0x08, 0x46, 0x00, 0x04, 0x1d, 0x58, 0x00, 0x0a, 0x00, 0x84, 0x4b, +0xd5, 0x0d, 0x80, 0x20, 0x3e, 0x09, 0x86, 0x14, 0x49, 0xff, 0x8b, 0x92, 0x84, 0x1e, 0xd5, 0x4e, +0x46, 0x00, 0x04, 0x1d, 0x58, 0x00, 0x0c, 0x00, 0x84, 0x4c, 0x8c, 0x14, 0xa6, 0xc1, 0x44, 0x4f, +0xff, 0xef, 0x96, 0x4c, 0x40, 0x31, 0x90, 0x02, 0x94, 0x4c, 0x40, 0x11, 0x84, 0x04, 0xae, 0x41, +0x3e, 0x19, 0x8a, 0xfc, 0xb4, 0x81, 0x00, 0x50, 0x00, 0x16, 0x96, 0xe1, 0x54, 0x61, 0x80, 0x0f, +0x95, 0xb4, 0x54, 0x52, 0x80, 0x0f, 0x40, 0x52, 0x98, 0x04, 0x92, 0x64, 0x9d, 0x21, 0x10, 0x30, +0x00, 0x17, 0x10, 0x50, 0x00, 0x16, 0xb6, 0x81, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x04, 0x10, +0xb4, 0x20, 0x84, 0x61, 0x40, 0x21, 0x88, 0x0c, 0x40, 0x11, 0x04, 0x04, 0xb6, 0x20, 0x80, 0xa0, +0x84, 0x20, 0xd5, 0x18, 0x9c, 0x49, 0x44, 0x00, 0x00, 0x64, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x60, +0xd5, 0x0f, 0x49, 0xff, 0xfe, 0x75, 0x84, 0x1f, 0xd5, 0x11, 0x92, 0x00, 0x84, 0x07, 0x9d, 0x21, +0x4c, 0x40, 0x7f, 0xfd, 0x9c, 0xd9, 0x44, 0x40, 0x01, 0x2c, 0x4c, 0x32, 0x00, 0x04, 0x84, 0x80, +0xd5, 0xf5, 0xb4, 0x05, 0x40, 0x01, 0x00, 0x02, 0xc8, 0xe6, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xc4, 0x46, 0x60, 0x04, 0x11, 0x04, 0x13, 0x00, 0x47, 0x55, 0xc0, +0x00, 0xff, 0xf1, 0x83, 0x84, 0x00, 0x3e, 0x49, 0xed, 0x18, 0x44, 0x50, 0x00, 0x10, 0x40, 0x3e, +0x10, 0x08, 0x98, 0xdc, 0x40, 0x40, 0x70, 0x1b, 0x40, 0x42, 0xf0, 0x1a, 0x3e, 0x59, 0xed, 0x18, +0x38, 0x92, 0x90, 0x00, 0x3c, 0x1e, 0x62, 0xbe, 0x46, 0x80, 0x04, 0x11, 0xa6, 0xd8, 0x58, 0x84, +0x03, 0x40, 0xf3, 0x87, 0x49, 0xff, 0xfe, 0xa6, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x81, 0x14, +0x04, 0x43, 0x00, 0x47, 0xb4, 0xc3, 0x46, 0x0f, 0xfe, 0xff, 0xf6, 0x89, 0x58, 0x00, 0x0f, 0xff, +0xb4, 0x83, 0x44, 0x6c, 0xff, 0xff, 0x40, 0x42, 0x00, 0x02, 0xb6, 0x83, 0x46, 0x30, 0x04, 0x11, +0xb4, 0x28, 0x58, 0x31, 0x83, 0x68, 0xf1, 0x88, 0xb4, 0x88, 0x46, 0x70, 0x04, 0x11, 0x40, 0x42, +0x00, 0x02, 0xb6, 0x88, 0xb4, 0x83, 0xf4, 0x86, 0xb4, 0xa3, 0x50, 0x41, 0xff, 0xe4, 0x40, 0x52, +0x98, 0x02, 0xb6, 0xa3, 0xb4, 0x04, 0x50, 0x32, 0x7f, 0xf8, 0xf0, 0x82, 0xb4, 0xa4, 0x92, 0xb0, +0x40, 0x52, 0xc0, 0x08, 0xb6, 0xa4, 0x80, 0xa7, 0xb5, 0x43, 0xb4, 0x83, 0x92, 0x88, 0x40, 0x42, +0x20, 0x08, 0xb6, 0x83, 0x80, 0x85, 0x04, 0x02, 0x80, 0xc0, 0xf0, 0x8d, 0x80, 0xc4, 0x04, 0x12, +0x00, 0xc1, 0xf1, 0x8c, 0x44, 0x30, 0x01, 0x00, 0x04, 0x03, 0x00, 0xc2, 0xf0, 0x8b, 0x04, 0x13, +0x80, 0xc3, 0xf1, 0x8a, 0x14, 0x32, 0x80, 0xc0, 0x14, 0x32, 0x00, 0xc1, 0x14, 0x33, 0x00, 0xc2, +0x14, 0x33, 0x80, 0xc3, 0x49, 0xff, 0xfe, 0x80, 0x80, 0xe0, 0xc8, 0x22, 0x46, 0x30, 0x04, 0x11, +0x04, 0x11, 0x81, 0xc1, 0xb4, 0x48, 0x3e, 0x09, 0x86, 0x28, 0x49, 0xff, 0x8a, 0xc1, 0x46, 0x30, +0x04, 0x12, 0x04, 0x11, 0x80, 0x4c, 0x3e, 0x09, 0x86, 0x4c, 0x49, 0xff, 0x8a, 0xb9, 0x80, 0x09, +0x49, 0xff, 0xfd, 0xb6, 0x80, 0x07, 0x49, 0xff, 0xfd, 0xb3, 0x49, 0xff, 0xfd, 0xd1, 0x80, 0x09, +0x49, 0xff, 0xfe, 0x92, 0xc0, 0xfd, 0x84, 0x00, 0x49, 0xff, 0xfe, 0x8e, 0xc0, 0xf9, 0x49, 0xff, +0xfd, 0xbd, 0x49, 0xff, 0xfd, 0xc5, 0x84, 0x00, 0x49, 0xff, 0xfd, 0xcc, 0x46, 0x30, 0x04, 0x11, +0x04, 0x31, 0x80, 0x47, 0x40, 0x7e, 0x7c, 0x08, 0xf3, 0x85, 0x49, 0xff, 0xfd, 0xef, 0xf3, 0x02, +0x46, 0x50, 0x04, 0x11, 0x80, 0x85, 0x14, 0x32, 0x80, 0xd3, 0x14, 0xa2, 0x00, 0xd1, 0x46, 0x50, +0x04, 0x10, 0x58, 0x52, 0x82, 0x30, 0xb4, 0xc5, 0x42, 0x63, 0x7c, 0x09, 0xb6, 0xc5, 0x84, 0xc1, +0xb4, 0x85, 0x40, 0x43, 0x90, 0x04, 0xb6, 0x85, 0x49, 0xff, 0xfd, 0xd0, 0x4d, 0xc3, 0x40, 0x08, +0x3c, 0x2c, 0x62, 0xc2, 0x84, 0x00, 0x80, 0x3c, 0x49, 0xff, 0xfe, 0xce, 0x46, 0x60, 0x04, 0x11, +0x58, 0x63, 0x01, 0x1c, 0xb4, 0x06, 0xf0, 0x84, 0x3c, 0x7c, 0x62, 0xc1, 0xb4, 0xa6, 0x5c, 0xf3, +0x83, 0xe9, 0xe9, 0x09, 0x50, 0x73, 0xfc, 0x18, 0xd5, 0x02, 0xb4, 0xa6, 0xf1, 0x03, 0x9b, 0x69, +0xe2, 0xa7, 0xe9, 0xfc, 0x46, 0x50, 0x04, 0x10, 0x04, 0x62, 0x82, 0x8c, 0x97, 0xb0, 0xc6, 0x08, +0x04, 0x52, 0x82, 0x8c, 0x3e, 0x09, 0x86, 0x5c, 0x96, 0x68, 0x49, 0xff, 0x8a, 0x59, 0x40, 0x5e, +0x70, 0x00, 0x9d, 0x69, 0x3e, 0x39, 0xed, 0x18, 0x95, 0x6b, 0x40, 0x6e, 0x10, 0x08, 0x99, 0xb3, +0x99, 0x6b, 0xa6, 0xed, 0xa6, 0x31, 0xa6, 0xb2, 0x84, 0x82, 0x84, 0x20, 0x80, 0xa4, 0x84, 0xc1, +0xf6, 0x81, 0x15, 0xcf, 0x80, 0x00, 0x49, 0xff, 0xe0, 0x2f, 0x46, 0x50, 0x04, 0x11, 0x04, 0x52, +0x80, 0x47, 0xf5, 0x82, 0x4f, 0xc3, 0x00, 0x08, 0x3c, 0x2c, 0x62, 0xc2, 0x80, 0x1c, 0x80, 0x3c, +0x49, 0xff, 0xfe, 0x8a, 0xf4, 0x06, 0x46, 0x80, 0x04, 0x11, 0x81, 0x48, 0x04, 0x84, 0x00, 0x47, +0x14, 0x45, 0x00, 0xda, 0x81, 0x2a, 0xf0, 0x0d, 0x14, 0x04, 0x80, 0xc0, 0x80, 0xe9, 0xf1, 0x0c, +0x14, 0x13, 0x80, 0xc1, 0x80, 0xc7, 0xf3, 0x0b, 0x14, 0x33, 0x00, 0xc2, 0x80, 0xa6, 0xf4, 0x0a, +0x14, 0x42, 0x80, 0xc3, 0x80, 0xe5, 0xf0, 0x07, 0x49, 0xff, 0xfd, 0x1a, 0xf0, 0x09, 0x46, 0x60, +0x04, 0x11, 0x14, 0x03, 0x80, 0x45, 0xf1, 0x08, 0x84, 0x01, 0x14, 0x13, 0x00, 0xd0, 0x49, 0xff, +0xfd, 0x99, 0xf4, 0x02, 0xf6, 0x05, 0xf0, 0x03, 0x40, 0x54, 0x10, 0x01, 0xf4, 0x04, 0x40, 0x1e, +0x10, 0x08, 0x3e, 0x39, 0xed, 0x18, 0x9a, 0xb0, 0x98, 0x4b, 0x9a, 0xe6, 0xf6, 0x02, 0xa6, 0x49, +0x9b, 0x34, 0x3e, 0x09, 0x86, 0x74, 0x49, 0xff, 0x89, 0xfb, 0x84, 0x00, 0xec, 0x3c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x11, 0x04, 0x20, +0x00, 0x47, 0x3c, 0x2e, 0x62, 0xbc, 0x84, 0x00, 0x49, 0xff, 0xfe, 0xac, 0x49, 0xff, 0xfc, 0xf4, +0x84, 0x20, 0x84, 0x0d, 0x49, 0xff, 0x9a, 0x5c, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x84, 0x60, 0x54, 0x91, 0x00, 0xff, 0x96, 0x49, 0x44, 0x20, +0x00, 0x18, 0xf3, 0x81, 0x4c, 0x11, 0x00, 0x08, 0x3e, 0x09, 0x86, 0x8c, 0x49, 0xff, 0x89, 0xd0, +0x48, 0x00, 0x00, 0x98, 0x50, 0x10, 0x00, 0x10, 0xb4, 0xc1, 0x9d, 0x04, 0x50, 0x50, 0x00, 0x0c, +0x8c, 0x14, 0xce, 0x05, 0x46, 0x10, 0x04, 0x11, 0x04, 0x60, 0x80, 0x47, 0x46, 0x10, 0x04, 0x11, +0x04, 0x20, 0x80, 0x49, 0x3e, 0x39, 0xed, 0x18, 0x84, 0x22, 0xae, 0x58, 0x84, 0x23, 0x10, 0x11, +0x80, 0x10, 0x96, 0x91, 0xa6, 0x60, 0x94, 0x96, 0xae, 0x59, 0xa6, 0x61, 0x10, 0x11, 0x80, 0x11, +0xa6, 0x6b, 0x54, 0x10, 0x80, 0x03, 0x10, 0x11, 0x80, 0x0d, 0xa6, 0x6b, 0x92, 0x22, 0x54, 0x10, +0x80, 0x03, 0x10, 0x11, 0x80, 0x1d, 0xa6, 0x62, 0x54, 0x10, 0x80, 0x03, 0xae, 0x5a, 0xa6, 0x62, +0x92, 0x22, 0x54, 0x10, 0x80, 0x03, 0x10, 0x11, 0x80, 0x12, 0xb4, 0x24, 0x42, 0x10, 0xd0, 0x0b, +0xae, 0x5b, 0xc9, 0x03, 0x84, 0x21, 0xd5, 0x02, 0x84, 0x20, 0x10, 0x11, 0x80, 0x13, 0x44, 0x30, +0x4e, 0x20, 0xe2, 0x62, 0xe8, 0x05, 0x44, 0x3f, 0xb1, 0xe0, 0x98, 0x93, 0xd5, 0x02, 0x84, 0x40, +0x3c, 0x2e, 0x62, 0xc0, 0x44, 0x10, 0x03, 0xe8, 0xa4, 0xa8, 0x42, 0x21, 0x04, 0x24, 0x3c, 0x2e, +0x62, 0xc1, 0xa6, 0xaa, 0x3c, 0x2e, 0x62, 0xc2, 0xa4, 0x80, 0x3c, 0x2e, 0x62, 0xc3, 0xa4, 0x41, +0x3c, 0x1e, 0x62, 0xc4, 0xa6, 0xa2, 0x54, 0x21, 0x00, 0x10, 0x96, 0x90, 0xca, 0x14, 0x46, 0x10, +0x04, 0x11, 0x80, 0x01, 0x04, 0x30, 0x81, 0xe6, 0x04, 0x40, 0x01, 0xc6, 0x92, 0x68, 0x9c, 0x91, +0x97, 0x24, 0x96, 0xda, 0x96, 0x90, 0xc4, 0x07, 0x4e, 0x35, 0x00, 0x06, 0x44, 0x40, 0x00, 0x20, +0x4c, 0x22, 0x7f, 0xf2, 0x84, 0x01, 0x49, 0xff, 0xfe, 0x1d, 0x46, 0x20, 0x04, 0x11, 0x3c, 0x3c, +0x62, 0xc3, 0x84, 0x00, 0x9c, 0x01, 0x84, 0xac, 0x04, 0x11, 0x00, 0x47, 0xd0, 0x04, 0x9b, 0x0e, +0xe2, 0x83, 0xe9, 0xf9, 0x3c, 0x2c, 0x62, 0xc4, 0x98, 0x32, 0xe2, 0x01, 0xe8, 0x15, 0x9a, 0x4e, +0x3e, 0x09, 0x86, 0xb8, 0x49, 0xff, 0x89, 0x44, 0x84, 0x00, 0x49, 0xff, 0xfe, 0x03, 0x80, 0x29, +0x84, 0x01, 0x50, 0x2f, 0x80, 0x04, 0x84, 0x64, 0x84, 0x9e, 0xf4, 0x81, 0x49, 0xff, 0x98, 0xf8, +0x84, 0x01, 0x48, 0x00, 0x00, 0x6e, 0x3c, 0x2c, 0x62, 0xc2, 0x84, 0x01, 0x84, 0x20, 0x49, 0xff, +0xfd, 0x83, 0x81, 0x00, 0xc0, 0x11, 0x3c, 0x1c, 0x62, 0xc2, 0x3e, 0x09, 0x86, 0xd0, 0x49, 0xff, +0x89, 0x27, 0x84, 0x00, 0x49, 0xff, 0xfd, 0xe6, 0x80, 0x29, 0x84, 0x01, 0x50, 0x2f, 0x80, 0x04, +0x84, 0x64, 0x84, 0x9c, 0xd5, 0xe3, 0x46, 0x10, 0x04, 0x11, 0x3c, 0x3c, 0x62, 0xc4, 0x04, 0x70, +0x80, 0x47, 0x98, 0xf3, 0x51, 0xcf, 0x80, 0x04, 0xe2, 0x67, 0xe8, 0x13, 0x80, 0x27, 0x80, 0x43, +0x3e, 0x09, 0x86, 0xf4, 0x49, 0xff, 0x89, 0x0c, 0x80, 0x08, 0x49, 0xff, 0xfd, 0xcb, 0x84, 0x9d, +0xf4, 0x81, 0x80, 0x29, 0x80, 0x5c, 0x84, 0x64, 0x84, 0x01, 0x49, 0xff, 0x98, 0xc1, 0xd5, 0xc9, +0xf0, 0x81, 0x80, 0x29, 0x80, 0x5c, 0x84, 0x64, 0x49, 0xff, 0x98, 0xba, 0x3c, 0x0c, 0x62, 0xc0, +0x9a, 0x7e, 0xe2, 0x01, 0xe8, 0x03, 0x80, 0xc8, 0xd5, 0x06, 0x9b, 0xc7, 0x99, 0xbe, 0x5c, 0xf3, +0x27, 0x11, 0xe8, 0x0d, 0x44, 0x10, 0x03, 0xe8, 0x40, 0x13, 0x04, 0x17, 0x3e, 0x09, 0x87, 0x0c, +0x49, 0xff, 0x88, 0xe6, 0x3e, 0x09, 0xec, 0xfc, 0x84, 0x20, 0xd5, 0x0f, 0x50, 0x73, 0x58, 0xf0, +0x44, 0x00, 0x03, 0xe8, 0x40, 0x73, 0x80, 0x17, 0x3e, 0x09, 0x87, 0x18, 0x80, 0x27, 0x49, 0xff, +0x88, 0xd7, 0x80, 0x27, 0x3e, 0x09, 0xec, 0xfc, 0x49, 0xff, 0x89, 0xe6, 0x44, 0x10, 0x03, 0xe8, +0x40, 0x13, 0x04, 0xd7, 0x3e, 0x09, 0xed, 0x38, 0x49, 0xff, 0x89, 0xde, 0x84, 0x00, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, +0x96, 0x90, 0xe6, 0x25, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x16, 0xb4, 0x60, 0xc3, 0x05, 0x84, 0x01, +0x4c, 0x30, 0x40, 0x0c, 0xd5, 0x05, 0x49, 0xff, 0xfe, 0xd5, 0x92, 0x00, 0xd5, 0x0c, 0x3e, 0x09, +0x87, 0x28, 0x49, 0xff, 0x88, 0xad, 0xd5, 0x06, 0x80, 0x23, 0x3e, 0x09, 0x87, 0x40, 0x49, 0xff, +0x88, 0xa7, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x84, 0x00, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x43, 0x50, 0x1f, +0x80, 0x07, 0x84, 0x41, 0x49, 0xfe, 0x15, 0x34, 0x00, 0x0f, 0x80, 0x07, 0x84, 0x21, 0x92, 0x01, +0x54, 0x50, 0x00, 0x03, 0xd1, 0x10, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x8c, 0x42, 0x00, +0x78, 0x0b, 0xc8, 0x09, 0x46, 0x00, 0x04, 0x00, 0x46, 0x15, 0xc1, 0xfe, 0x58, 0x10, 0x8e, 0x80, +0x14, 0x10, 0x00, 0x47, 0x2e, 0x07, 0xef, 0xd1, 0x84, 0xa1, 0xd8, 0x05, 0x49, 0xfb, 0x95, 0x1a, +0x49, 0xfb, 0xaa, 0x7e, 0x2e, 0x07, 0xef, 0xd1, 0xc8, 0x36, 0x2e, 0x01, 0x8a, 0x50, 0x84, 0xa1, +0xd8, 0x0b, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x4a, 0x46, 0x20, 0x00, 0xff, 0x40, 0x10, +0x88, 0x04, 0x14, 0x10, 0x00, 0x4a, 0x46, 0x10, 0x04, 0x00, 0x04, 0x50, 0x80, 0x82, 0x46, 0x6f, +0xff, 0x0f, 0x58, 0x63, 0x0f, 0xff, 0x46, 0x00, 0x04, 0x50, 0x40, 0x52, 0x98, 0x02, 0x14, 0x50, +0x80, 0x82, 0x44, 0x10, 0x00, 0x83, 0x80, 0x80, 0xa8, 0x43, 0x44, 0x10, 0x00, 0x41, 0xb6, 0x24, +0x80, 0x60, 0x84, 0x23, 0xa8, 0x43, 0x80, 0x40, 0x44, 0x00, 0x00, 0xcf, 0x14, 0x01, 0x80, 0x0a, +0x44, 0x00, 0x00, 0x67, 0x14, 0x01, 0x00, 0x0b, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, 0x83, 0x34, +0x3c, 0x1f, 0xfb, 0x94, 0x49, 0xff, 0xb9, 0xd6, 0x3c, 0x2d, 0xfb, 0x87, 0x84, 0x21, 0x84, 0x03, +0xdd, 0x22, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x0e, 0x42, 0x00, 0x4c, 0x0b, 0xc0, 0x06, +0x46, 0x00, 0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x26, 0x25, 0x58, 0x00, +0x0a, 0x00, 0x49, 0xfe, 0x4d, 0x01, 0x84, 0x20, 0x44, 0x20, 0x00, 0xe0, 0x3e, 0x09, 0xde, 0x30, +0x49, 0xfe, 0x5e, 0xbc, 0x84, 0x20, 0x44, 0x20, 0x00, 0xe0, 0x3e, 0x09, 0xdf, 0x10, 0x49, 0xfe, +0x5e, 0xb5, 0x44, 0x20, 0x00, 0xe0, 0x84, 0x20, 0x3e, 0x09, 0xdf, 0xf0, 0x49, 0xfe, 0x5e, 0xae, +0x3c, 0x1c, 0x62, 0x7c, 0x3e, 0x09, 0x5a, 0xb0, 0x49, 0xff, 0x88, 0x02, 0x3e, 0x09, 0x5a, 0xc0, +0x49, 0xff, 0x87, 0xfe, 0x49, 0xff, 0x83, 0x5c, 0x3e, 0x09, 0x5a, 0xe0, 0x49, 0xff, 0x87, 0xf8, +0x49, 0xff, 0xa0, 0x6a, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x44, 0x3f, 0x00, 0x00, 0x46, 0x67, +0x66, 0x20, 0x40, 0x50, 0x8c, 0x02, 0xd6, 0x07, 0xb4, 0x00, 0x46, 0x17, 0x63, 0x20, 0x40, 0x50, +0x0c, 0x02, 0xd9, 0x03, 0x49, 0xff, 0xfa, 0xd2, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x02, 0x01, +0x40, 0x10, 0xa0, 0x08, 0x92, 0x28, 0x14, 0x10, 0x02, 0x01, 0x84, 0x0a, 0x84, 0x20, 0x49, 0xfb, +0x86, 0x4f, 0x84, 0x0c, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x80, 0x84, 0x49, 0xff, 0x87, 0x90, +0x84, 0x0f, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, 0x85, 0x40, 0x49, 0xff, 0x87, 0x89, 0x44, 0x00, +0x00, 0x10, 0x46, 0x10, 0x00, 0x87, 0x58, 0x10, 0x84, 0x70, 0x49, 0xff, 0x87, 0x81, 0x84, 0x07, +0x84, 0x20, 0x49, 0xfb, 0x86, 0x35, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x80, 0xe8, 0x3e, 0x29, +0x5a, 0xf8, 0x84, 0x07, 0x49, 0xfb, 0x86, 0xe4, 0x84, 0x07, 0x49, 0xfb, 0x86, 0x4d, 0x3e, 0x29, +0x5a, 0xf8, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x88, 0x48, 0x84, 0x0a, 0x49, 0xfb, 0x86, 0xd8, +0x84, 0x0a, 0x49, 0xfb, 0x86, 0x41, 0x84, 0x02, 0x49, 0xff, 0x89, 0x3a, 0x49, 0xff, 0x83, 0x30, +0x84, 0x00, 0x49, 0xfb, 0x98, 0xfb, 0x80, 0x40, 0x3e, 0x21, 0x8a, 0x6b, 0x80, 0x20, 0x84, 0x00, +0x49, 0xfb, 0x9e, 0x32, 0x46, 0x00, 0x04, 0x00, 0x04, 0x30, 0x00, 0x8c, 0x46, 0x20, 0x04, 0x0e, +0x58, 0x31, 0x80, 0x01, 0x14, 0x30, 0x00, 0x8c, 0x44, 0x00, 0x3e, 0x58, 0x80, 0x22, 0x14, 0x01, +0x00, 0x7e, 0x46, 0x00, 0x00, 0x87, 0x58, 0x00, 0x03, 0x44, 0x14, 0x00, 0x80, 0x7f, 0x80, 0x01, +0x04, 0x10, 0x00, 0x81, 0x47, 0xc0, 0x00, 0x80, 0x59, 0xce, 0x0c, 0xb8, 0x42, 0x10, 0xfc, 0x08, +0x14, 0x10, 0x00, 0x81, 0x49, 0xff, 0xfb, 0x96, 0x84, 0x02, 0x49, 0xfb, 0x9b, 0xf7, 0x80, 0xe0, +0x49, 0xfb, 0x9a, 0x1a, 0x81, 0x20, 0xa0, 0x3a, 0x44, 0x50, 0x00, 0x67, 0xd8, 0x05, 0xa0, 0x3b, +0x84, 0x21, 0x49, 0xff, 0xbb, 0xe9, 0xa0, 0xba, 0x44, 0x50, 0x00, 0x6d, 0xda, 0x32, 0x44, 0x80, +0x9c, 0x40, 0x40, 0x84, 0xa0, 0x17, 0x84, 0x05, 0x40, 0x14, 0x00, 0x17, 0xc8, 0x08, 0x3c, 0x2c, +0x62, 0x7a, 0x80, 0x28, 0x3e, 0x09, 0x5b, 0x00, 0x49, 0xff, 0x87, 0x52, 0x46, 0x20, 0x04, 0x00, +0x14, 0x81, 0x00, 0x8e, 0x04, 0x01, 0x00, 0x8c, 0x54, 0x00, 0x00, 0x10, 0xc0, 0x0c, 0x84, 0x21, +0x3e, 0x11, 0x8a, 0x50, 0x04, 0x01, 0x00, 0x4a, 0x46, 0x10, 0x00, 0xf0, 0x40, 0x00, 0x04, 0x04, +0x14, 0x01, 0x00, 0x4a, 0x2e, 0x01, 0x8a, 0x56, 0x84, 0xa1, 0xd8, 0x0b, 0x84, 0x00, 0x49, 0xff, +0xbb, 0x71, 0x3e, 0x09, 0x5b, 0x2c, 0x49, 0xff, 0x87, 0x33, 0x84, 0x00, 0x3e, 0x01, 0x8a, 0x56, +0xa0, 0xfa, 0x44, 0x50, 0x00, 0x2e, 0xdb, 0x14, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x02, 0x44, 0x1f, +0x00, 0x00, 0x46, 0x37, 0x66, 0x20, 0x40, 0x50, 0x04, 0x02, 0xd3, 0x07, 0xb4, 0x02, 0x40, 0x50, +0x04, 0x02, 0x46, 0x17, 0x63, 0x20, 0xd9, 0x04, 0xa0, 0x3b, 0x49, 0xff, 0xf9, 0x6f, 0xa0, 0xba, +0x44, 0x50, 0x00, 0x7c, 0xda, 0x08, 0xa0, 0xbb, 0x3c, 0x2e, 0x62, 0x7d, 0x3e, 0x09, 0x5b, 0x34, +0x49, 0xff, 0x87, 0x0e, 0xa0, 0x3a, 0x44, 0x50, 0x00, 0x71, 0xd8, 0x59, 0x84, 0x0a, 0x49, 0xfb, +0x85, 0xc1, 0x84, 0x07, 0x49, 0xfb, 0x85, 0xbe, 0x46, 0x30, 0x04, 0x00, 0x04, 0x01, 0x81, 0x06, +0x42, 0x00, 0x1c, 0x09, 0x14, 0x01, 0x81, 0x06, 0x80, 0x43, 0x04, 0x01, 0x00, 0x85, 0x42, 0x00, +0x30, 0x09, 0x14, 0x01, 0x00, 0x85, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x02, 0x0c, 0xb5, 0x46, +0x58, 0x05, 0x00, 0x10, 0xb6, 0x06, 0x3e, 0x09, 0x5b, 0x6c, 0x49, 0xff, 0x86, 0xe9, 0x84, 0x0a, +0x49, 0xfb, 0x99, 0x9c, 0x42, 0xa5, 0x10, 0x09, 0xb7, 0x46, 0x2e, 0x30, 0x07, 0x9c, 0x9e, 0xd9, +0x2e, 0x11, 0x8a, 0x6b, 0x3e, 0x30, 0x07, 0x9c, 0x84, 0x00, 0x49, 0xfb, 0x9d, 0xa7, 0x44, 0x10, +0x9c, 0x40, 0x40, 0x14, 0x85, 0x37, 0x84, 0x60, 0x3e, 0x37, 0xef, 0xde, 0x3e, 0x09, 0x5b, 0x78, +0x49, 0xff, 0x86, 0xce, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x8c, 0x42, 0x21, 0x00, 0x09, +0x14, 0x20, 0x00, 0x8c, 0x44, 0x10, 0x0a, 0x2c, 0x3e, 0x29, 0x5a, 0xf8, 0x84, 0x0a, 0x49, 0xfb, +0x85, 0xef, 0x84, 0x0a, 0x49, 0xfb, 0x85, 0x58, 0x49, 0xff, 0x88, 0x38, 0x80, 0x07, 0x49, 0xfb, +0x99, 0xdb, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x84, 0xa1, 0xd8, 0x03, +0x49, 0xff, 0x87, 0x50, 0xa0, 0xba, 0x44, 0x50, 0x00, 0x6f, 0xda, 0x0e, 0x04, 0x83, 0x80, 0x03, +0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0a, 0x80, 0x1f, 0x49, 0xfb, 0x92, 0x9a, 0xb4, 0x1f, 0x3e, 0x81, +0x8a, 0x4e, 0x49, 0xfb, 0x92, 0xab, 0x49, 0xff, 0xbc, 0xff, 0xd5, 0x17, 0xdd, 0x3c, 0x00, 0x20, +0x00, 0x14, 0x81, 0x00, 0x80, 0x20, 0xca, 0x0a, 0x3e, 0x09, 0xd9, 0xe8, 0x49, 0xff, 0x9d, 0xac, +0xc8, 0x0c, 0x80, 0x28, 0x3e, 0x09, 0xd3, 0x10, 0xd5, 0x06, 0x49, 0xff, 0xa5, 0x9f, 0x80, 0x28, +0x3e, 0x09, 0xd3, 0x00, 0x49, 0xff, 0x88, 0x5c, 0x3c, 0x3c, 0x76, 0xaa, 0x3e, 0x09, 0xda, 0xa0, +0xcb, 0xe6, 0x80, 0x07, 0x49, 0xfb, 0x99, 0xa0, 0x48, 0xff, 0xff, 0x08, 0x49, 0x6e, 0x76, 0x61, +0x6c, 0x69, 0x64, 0x20, 0x46, 0x43, 0x45, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, +0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, +0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2f, 0x66, 0x63, 0x65, 0x2f, +0x66, 0x63, 0x65, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x21, 0x20, +0x52, 0x78, 0x46, 0x53, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x66, 0x61, +0x69, 0x6c, 0x0a, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x21, 0x20, 0x54, 0x78, 0x46, 0x73, +0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x0a, 0x00, +0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, +0x74, 0x20, 0x28, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x70, 0x65, 0x72, 0x69, 0x2f, 0x6d, 0x63, 0x75, 0x63, 0x74, 0x6c, 0x2f, 0x6d, 0x63, 0x75, +0x63, 0x74, 0x6c, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x63, +0x00, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x61, 0x70, 0x69, +0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x68, 0x00, 0x00, 0x00, 0x00, +0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x71, 0x75, 0x65, +0x75, 0x65, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x63, 0x00, 0x4c, 0x65, 0x64, 0x4e, +0x6f, 0x3a, 0x25, 0x6c, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x64, 0x43, 0x74, 0x72, 0x6c, 0x3a, 0x25, +0x6c, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x3e, 0x20, 0x25, 0x73, +0x0a, 0x00, 0x00, 0x00, 0x3c, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x25, 0x73, 0x2c, 0x20, 0x4d, 0x41, +0x43, 0x5f, 0x53, 0x59, 0x53, 0x5f, 0x43, 0x54, 0x52, 0x4c, 0x3a, 0x30, 0x78, 0x25, 0x78, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x49, 0x50, 0x76, 0x36, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x20, +0x4e, 0x6f, 0x20, 0x75, 0x70, 0x70, 0x65, 0x72, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, +0x6c, 0x0a, 0x00, 0x00, 0x57, 0x6f, 0x77, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x6f, 0x77, 0x65, 0x72, +0x20, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x78, 0x28, 0x25, 0x64, 0x29, 0x20, 0x54, 0x42, 0x54, +0x54, 0x20, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x57, 0x6f, 0x77, 0x52, 0x61, 0x64, 0x69, 0x6f, +0x20, 0x6f, 0x6e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x61, 0x70, 0x69, 0x51, +0x55, 0x5f, 0x44, 0x65, 0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x21, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x20, 0x2d, 0x2d, 0x20, 0x4e, 0x75, 0x6c, 0x6c, 0x20, 0x66, +0x72, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x71, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, +0x2b, 0x2b, 0x2b, 0x20, 0x77, 0x72, 0x61, 0x70, 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, +0x4e, 0x75, 0x6c, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2b, 0x2b, 0x20, 0x4e, 0x75, 0x6c, 0x6c, +0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x70, 0x77, 0x73, 0x20, 0x2c, 0x20, 0x4e, 0x75, 0x6c, +0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x4e, 0x75, 0x6c, 0x6c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x61, +0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x71, 0x75, +0x65, 0x75, 0x65, 0x50, 0x73, 0x50, 0x6f, 0x6c, 0x6c, 0x20, 0x3e, 0x3e, 0x20, 0x0a, 0x00, 0x00, +0x25, 0x73, 0x2c, 0x20, 0x61, 0x70, 0x69, 0x51, 0x55, 0x5f, 0x44, 0x65, 0x71, 0x75, 0x65, 0x75, +0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x43, 0x68, 0x65, 0x63, +0x6b, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x54, 0x78, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, +0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x2d, 0x2d, 0x2d, +0x2d, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x61, 0x33, 0x30, 0x20, 0x3d, +0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x61, +0x33, 0x34, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x30, 0x78, 0x34, 0x33, 0x38, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, +0x30, 0x78, 0x30, 0x34, 0x33, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x52, 0x78, +0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x29, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x44, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, +0x20, 0x62, 0x79, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x73, +0x61, 0x76, 0x69, 0x6e, 0x67, 0x0a, 0x00, 0x00, 0x75, 0x63, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x62, +0x6c, 0x65, 0x57, 0x6f, 0x77, 0x53, 0x68, 0x61, 0x72, 0x65, 0x50, 0x69, 0x6e, 0x45, 0x6e, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x55, 0x53, 0x42, 0x20, 0x72, +0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x0a, 0x00, 0x00, +0x78, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x67, 0x50, 0x72, 0x55, 0x73, 0x62, +0x44, 0x70, 0x50, 0x75, 0x6c, 0x6c, 0x44, 0x6f, 0x77, 0x6e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, +0x65, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x75, 0x63, 0x55, 0x73, 0x62, 0x44, +0x70, 0x50, 0x64, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x57, 0x6f, 0x57, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20, 0x70, +0x69, 0x6e, 0x0a, 0x00, 0x47, 0x50, 0x49, 0x4f, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x52, 0x45, 0x47, 0x5f, 0x4c, 0x45, 0x44, 0x32, 0x5f, 0x53, 0x30, 0x3a, +0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x47, 0x5f, 0x4c, 0x45, 0x44, 0x32, +0x5f, 0x53, 0x31, 0x3a, 0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x65, 0x61, 0x63, +0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x73, 0x74, 0x20, 0x21, 0x0a, 0x00, 0x00, 0x6e, 0x6f, 0x20, 0x64, +0x61, 0x74, 0x61, 0x20, 0x2b, 0x2b, 0x2b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20, +0x64, 0x65, 0x73, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x52, 0x78, 0x57, 0x49, +0x5f, 0x62, 0x73, 0x73, 0x69, 0x64, 0x3a, 0x25, 0x64, 0x20, 0x2b, 0x2b, 0x2b, 0x0a, 0x00, 0x00, +0x44, 0x33, 0x20, 0x6c, 0x65, 0x6e, 0x3a, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x2b, 0x2b, 0x2b, +0x48, 0x54, 0x43, 0x2c, 0x20, 0x50, 0x48, 0x59, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x25, 0x64, +0x20, 0x0a, 0x00, 0x00, 0x4c, 0x4c, 0x43, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, +0x68, 0x0a, 0x00, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20, 0x6d, 0x61, 0x67, 0x69, +0x63, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x57, 0x61, 0x6b, 0x65, +0x75, 0x70, 0x20, 0x62, 0x79, 0x20, 0x55, 0x44, 0x50, 0x20, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, +0x72, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, +0x68, 0x0a, 0x00, 0x00, 0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x20, 0x62, 0x79, 0x20, 0x55, 0x44, +0x50, 0x20, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x32, +0x20, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x55, 0x44, 0x50, 0x20, +0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, +0x6e, 0x27, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, +0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, +0x63, 0x61, 0x6c, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x5f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, +0x54, 0x78, 0x52, 0x78, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x5f, 0x45, 0x6e, 0x61, +0x62, 0x6c, 0x65, 0x54, 0x78, 0x52, 0x78, 0x00, 0x53, 0x65, 0x6e, 0x64, 0x4e, 0x75, 0x6c, 0x6c, +0x46, 0x72, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x50, +0x73, 0x50, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x65, +0x6e, 0x67, 0x74, 0x68, 0x20, 0x3e, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x6e, 0x63, +0x61, 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x00, 0x00, 0x3d, 0x3d, 0x3d, 0x3e, 0x20, 0x54, 0x46, 0x20, +0x66, 0x6f, 0x72, 0x63, 0x65, 0x2c, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3d, 0x28, 0x25, 0x64, 0x29, +0x0a, 0x00, 0x00, 0x00, 0x50, 0x6b, 0x74, 0x43, 0x6d, 0x64, 0x3a, 0x20, 0x43, 0x6f, 0x65, 0x78, +0x20, 0x57, 0x69, 0x66, 0x69, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2c, 0x20, 0x6c, 0x65, +0x6e, 0x67, 0x74, 0x68, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, +0x3a, 0x25, 0x64, 0x2c, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x69, 0x6e, +0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, +0x50, 0x6b, 0x74, 0x43, 0x6d, 0x64, 0x3a, 0x20, 0x43, 0x6f, 0x65, 0x78, 0x20, 0x41, 0x46, 0x48, +0x2c, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, +0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x70, +0x61, 0x72, 0x61, 0x6d, 0x74, 0x65, 0x72, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, +0x6f, 0x6e, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x5b, 0x46, 0x57, 0x2d, 0x3e, 0x48, 0x4f, 0x53, +0x54, 0x5d, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x30, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x5b, 0x46, 0x57, 0x2d, 0x3e, 0x48, 0x4f, 0x53, 0x54, 0x5d, 0x20, 0x73, +0x74, 0x65, 0x70, 0x32, 0x0a, 0x00, 0x00, 0x00, 0x5b, 0x46, 0x57, 0x2d, 0x3e, 0x48, 0x4f, 0x53, +0x54, 0x5d, 0x20, 0x73, 0x74, 0x65, 0x70, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x38, 0x30, 0x43, 0x3d, +0x25, 0x30, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x5b, 0x48, 0x4f, 0x53, 0x54, 0x20, 0x2d, 0x3e, +0x20, 0x46, 0x57, 0x5d, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, +0x31, 0x20, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, +0x20, 0x0a, 0x00, 0x00, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3a, 0x25, 0x64, 0x20, 0x65, +0x78, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x0a, 0x00, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x74, +0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x77, 0x6f, 0x77, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x54, +0x79, 0x70, 0x65, 0x20, 0x20, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x77, 0x6f, 0x77, 0x20, +0x70, 0x6b, 0x74, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x73, 0x6b, 0x3a, 0x30, 0x78, +0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x53, 0x74, 0x61, 0x4d, 0x61, 0x63, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, +0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, +0x30, 0x32, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x70, 0x4d, 0x61, 0x63, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, +0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, 0x30, 0x32, 0x78, 0x2d, 0x25, +0x30, 0x32, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x46, 0x6c, +0x61, 0x67, 0x3a, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x52, 0x50, 0x4e, +0x53, 0x2c, 0x20, 0x6c, 0x65, 0x6e, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x00, 0x00, 0x49, 0x50, 0x61, 0x64, 0x64, 0x72, 0x28, 0x74, +0x79, 0x70, 0x65, 0x3d, 0x25, 0x64, 0x29, 0x20, 0x69, 0x64, 0x78, 0x5b, 0x25, 0x64, 0x5d, 0x20, +0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x41, 0x64, 0x64, 0x72, 0x3a, +0x30, 0x78, 0x00, 0x00, 0x25, 0x30, 0x32, 0x78, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, +0x53, 0x59, 0x4e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x5b, 0x25, 0x64, 0x5d, 0x20, 0x45, 0x6e, 0x61, +0x62, 0x6c, 0x65, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x53, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x3a, +0x25, 0x64, 0x2c, 0x20, 0x44, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x3a, 0x25, 0x64, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, 0x53, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x20, +0x3a, 0x30, 0x78, 0x00, 0x25, 0x30, 0x32, 0x78, 0x00, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, +0x44, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x20, 0x3a, 0x30, 0x78, 0x00, 0x41, 0x69, 0x64, 0x3a, +0x25, 0x64, 0x2c, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3a, 0x25, 0x64, 0x20, 0x0a, +0x0a, 0x00, 0x00, 0x00, 0x49, 0x50, 0x76, 0x34, 0x2f, 0x54, 0x43, 0x50, 0x20, 0x70, 0x6f, 0x72, +0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x50, 0x76, 0x36, +0x2f, 0x54, 0x43, 0x50, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x54, 0x43, 0x50, 0x20, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x4d, +0x61, 0x73, 0x6b, 0x3a, 0x25, 0x58, 0x0a, 0x00, 0x49, 0x50, 0x76, 0x34, 0x2f, 0x55, 0x44, 0x50, +0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x49, 0x50, 0x76, 0x34, 0x2f, 0x55, 0x44, 0x50, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x3a, 0x25, +0x64, 0x0a, 0x00, 0x00, 0x49, 0x50, 0x76, 0x36, 0x2f, 0x55, 0x44, 0x50, 0x20, 0x70, 0x6f, 0x72, +0x74, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x55, 0x44, 0x50, 0x20, +0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x4d, 0x61, 0x73, 0x6b, 0x3a, 0x25, 0x58, 0x0a, 0x00, +0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x6e, +0x61, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, +0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x4d, +0x43, 0x55, 0x20, 0x43, 0x52, 0x28, 0x30, 0x78, 0x33, 0x38, 0x29, 0x3d, 0x30, 0x78, 0x25, 0x78, +0x2c, 0x20, 0x43, 0x52, 0x28, 0x30, 0x78, 0x31, 0x32, 0x34, 0x29, 0x3d, 0x30, 0x78, 0x25, 0x78, +0x2c, 0x20, 0x43, 0x52, 0x28, 0x30, 0x78, 0x31, 0x32, 0x38, 0x29, 0x3d, 0x30, 0x78, 0x25, 0x78, +0x0a, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x6d, +0x61, 0x6e, 0x64, 0x20, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x0a, 0x00, 0x00, 0x61, 0x70, 0x70, 0x50, +0x6b, 0x74, 0x43, 0x6d, 0x64, 0x5f, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, +0x00, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x20, 0x0a, 0x0a, 0x00, 0x00, 0x4d, 0x41, 0x43, 0x20, +0x54, 0x78, 0x2f, 0x52, 0x78, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2e, +0x20, 0x42, 0x75, 0x73, 0x79, 0x20, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x0a, 0x00, +0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x49, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, +0x4c, 0x5f, 0x53, 0x57, 0x49, 0x54, 0x43, 0x48, 0x5f, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, +0x45, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x0a, 0x00, 0x50, 0x65, 0x65, 0x72, 0x41, 0x64, 0x64, 0x42, +0x41, 0x52, 0x65, 0x71, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x25, 0x73, 0x20, 0x63, +0x69, 0x70, 0x68, 0x65, 0x72, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x78, +0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x35, 0x47, 0x20, 0x63, +0x68, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x35, 0x47, 0x20, 0x63, +0x68, 0x20, 0x6d, 0x67, 0x6d, 0x74, 0x0a, 0x00, 0x49, 0x63, 0x76, 0x45, 0x72, 0x72, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x45, 0x72, 0x72, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x78, 0x52, 0x65, 0x73, +0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x1b, 0x5b, 0x33, 0x31, 0x6d, 0x5b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x55, 0x32, 0x4d, +0x20, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x5d, 0x20, 0x25, 0x64, 0x1b, 0x5b, 0x6d, 0x0a, 0x00, +0x5b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5d, 0x20, 0x25, +0x64, 0x2c, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x25, 0x64, 0x2c, +0x20, 0x74, 0x62, 0x74, 0x74, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x61, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x49, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x57, +0x49, 0x54, 0x43, 0x48, 0x5f, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x4d, 0x45, 0x4e, +0x54, 0x20, 0x0a, 0x00, 0x52, 0x78, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x20, +0x6b, 0x65, 0x65, 0x70, 0x20, 0x61, 0x77, 0x61, 0x6b, 0x65, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x52, 0x78, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x62, 0x6c, 0x65, +0x20, 0x74, 0x6f, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x0a, 0x00, 0x5b, 0x44, 0x61, 0x74, +0x61, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5d, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x73, 0x6c, 0x65, +0x65, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x6c, 0x65, 0x6e, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x78, 0x45, +0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x46, 0x20, 0x00, 0x53, 0x54, 0x41, 0x46, +0x69, 0x6e, 0x64, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, +0x68, 0x6d, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x57, 0x72, 0x69, 0x74, 0x65, 0x54, 0x78, 0x57, +0x49, 0x5f, 0x44, 0x61, 0x74, 0x61, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, 0x57, 0x72, 0x69, 0x74, +0x65, 0x54, 0x78, 0x57, 0x49, 0x5f, 0x4d, 0x67, 0x6d, 0x74, 0x00, 0x00, 0x52, 0x54, 0x4d, 0x50, +0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, +0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x30, 0x78, +0x66, 0x66, 0x20, 0x2a, 0x36, 0x20, 0x61, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x41, 0x6c, +0x67, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x42, 0x73, 0x73, 0x49, 0x64, 0x78, 0x3a, 0x25, 0x64, 0x2c, +0x20, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x78, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x25, 0x73, 0x20, 0x3a, 0x20, 0x28, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x54, 0x79, 0x70, 0x65, +0x2d, 0x25, 0x64, 0x29, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, +0x20, 0x0a, 0x00, 0x00, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x3a, 0x20, 0x47, 0x54, 0x4b, 0x20, 0x4b, +0x65, 0x79, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x73, 0x68, +0x6f, 0x72, 0x74, 0x20, 0x28, 0x25, 0x64, 0x29, 0x20, 0x0a, 0x00, 0x00, 0x3d, 0x3e, 0x47, 0x31, +0x2c, 0x20, 0x63, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x2d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x50, 0x65, 0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x4d, 0x73, 0x67, 0x31, 0x41, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x57, 0x50, 0x41, 0x49, 0x6e, 0x73, 0x74, 0x61, +0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x00, 0x57, 0x50, 0x41, 0x49, +0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x77, 0x69, 0x73, 0x65, 0x4b, 0x65, +0x79, 0x00, 0x00, 0x00, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x73, 0x67, +0x31, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, +0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x36, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, +0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, +0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, +0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, +0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, +0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, +0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, +0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, +0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, +0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, +0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, +0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, +0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, +0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, +0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, +0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, +0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, +0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, +0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, +0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, +0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, +0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, +0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, +0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, +0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, +0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, +0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, +0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, +0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, +0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, +0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, +0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, +0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, +0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, +0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, +0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, +0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, +0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, +0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, +0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, +0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, +0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, +0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, +0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, +0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, +0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, +0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, +0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, +0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, +0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, +0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, +0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, +0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, +0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, +0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, +0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, +0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, +0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, +0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, +0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, +0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, +0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, +0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, +0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, +0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, +0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, +0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, +0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, +0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, +0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, +0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, +0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, +0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, +0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, +0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, +0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, +0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, +0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, +0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, +0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, +0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, +0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, +0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, +0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, +0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, +0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, +0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, +0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, +0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, +0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, +0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, +0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, +0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, +0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, +0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, +0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, +0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, +0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x99, 0x79, 0x82, 0x5a, 0xa1, 0xeb, 0xd9, 0x6e, +0xdc, 0xbc, 0x1b, 0x8f, 0xd6, 0xc1, 0x62, 0xca, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, +0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf0, 0xe1, 0xd2, 0xc3, 0x98, 0x2f, 0x8a, 0x42, +0x91, 0x44, 0x37, 0x71, 0xcf, 0xfb, 0xc0, 0xb5, 0xa5, 0xdb, 0xb5, 0xe9, 0x5b, 0xc2, 0x56, 0x39, +0xf1, 0x11, 0xf1, 0x59, 0xa4, 0x82, 0x3f, 0x92, 0xd5, 0x5e, 0x1c, 0xab, 0x98, 0xaa, 0x07, 0xd8, +0x01, 0x5b, 0x83, 0x12, 0xbe, 0x85, 0x31, 0x24, 0xc3, 0x7d, 0x0c, 0x55, 0x74, 0x5d, 0xbe, 0x72, +0xfe, 0xb1, 0xde, 0x80, 0xa7, 0x06, 0xdc, 0x9b, 0x74, 0xf1, 0x9b, 0xc1, 0xc1, 0x69, 0x9b, 0xe4, +0x86, 0x47, 0xbe, 0xef, 0xc6, 0x9d, 0xc1, 0x0f, 0xcc, 0xa1, 0x0c, 0x24, 0x6f, 0x2c, 0xe9, 0x2d, +0xaa, 0x84, 0x74, 0x4a, 0xdc, 0xa9, 0xb0, 0x5c, 0xda, 0x88, 0xf9, 0x76, 0x52, 0x51, 0x3e, 0x98, +0x6d, 0xc6, 0x31, 0xa8, 0xc8, 0x27, 0x03, 0xb0, 0xc7, 0x7f, 0x59, 0xbf, 0xf3, 0x0b, 0xe0, 0xc6, +0x47, 0x91, 0xa7, 0xd5, 0x51, 0x63, 0xca, 0x06, 0x67, 0x29, 0x29, 0x14, 0x85, 0x0a, 0xb7, 0x27, +0x38, 0x21, 0x1b, 0x2e, 0xfc, 0x6d, 0x2c, 0x4d, 0x13, 0x0d, 0x38, 0x53, 0x54, 0x73, 0x0a, 0x65, +0xbb, 0x0a, 0x6a, 0x76, 0x2e, 0xc9, 0xc2, 0x81, 0x85, 0x2c, 0x72, 0x92, 0xa1, 0xe8, 0xbf, 0xa2, +0x4b, 0x66, 0x1a, 0xa8, 0x70, 0x8b, 0x4b, 0xc2, 0xa3, 0x51, 0x6c, 0xc7, 0x19, 0xe8, 0x92, 0xd1, +0x24, 0x06, 0x99, 0xd6, 0x85, 0x35, 0x0e, 0xf4, 0x70, 0xa0, 0x6a, 0x10, 0x16, 0xc1, 0xa4, 0x19, +0x08, 0x6c, 0x37, 0x1e, 0x4c, 0x77, 0x48, 0x27, 0xb5, 0xbc, 0xb0, 0x34, 0xb3, 0x0c, 0x1c, 0x39, +0x4a, 0xaa, 0xd8, 0x4e, 0x4f, 0xca, 0x9c, 0x5b, 0xf3, 0x6f, 0x2e, 0x68, 0xee, 0x82, 0x8f, 0x74, +0x6f, 0x63, 0xa5, 0x78, 0x14, 0x78, 0xc8, 0x84, 0x08, 0x02, 0xc7, 0x8c, 0xfa, 0xff, 0xbe, 0x90, +0xeb, 0x6c, 0x50, 0xa4, 0xf7, 0xa3, 0xf9, 0xbe, 0xf2, 0x78, 0x71, 0xc6, 0x67, 0xe6, 0x09, 0x6a, +0x85, 0xae, 0x67, 0xbb, 0x72, 0xf3, 0x6e, 0x3c, 0x3a, 0xf5, 0x4f, 0xa5, 0x7f, 0x52, 0x0e, 0x51, +0x8c, 0x68, 0x05, 0x9b, 0xab, 0xd9, 0x83, 0x1f, 0x19, 0xcd, 0xe0, 0x5b, 0x50, 0x45, 0x52, 0x5f, +0x50, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x43, 0x4e, 0x54, 0x31, 0x3a, +0x25, 0x64, 0x2c, 0x20, 0x50, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x4f, 0x54, +0x41, 0x4c, 0x5f, 0x43, 0x4e, 0x54, 0x32, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x54, 0x58, 0x52, 0x58, +0x51, 0x5f, 0x50, 0x43, 0x4e, 0x54, 0x20, 0x62, 0x75, 0x73, 0x79, 0x3a, 0x25, 0x78, 0x0a, 0x00, +0x54, 0x58, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x62, 0x75, 0x73, 0x79, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x50, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x43, +0x4e, 0x54, 0x31, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x20, 0x25, +0x73, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x63, 0x68, 0x69, 0x70, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x70, 0x73, 0x2e, 0x63, 0x00, +0x57, 0x49, 0x46, 0x49, 0x20, 0x50, 0x53, 0x20, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x74, 0x6f, 0x6f, +0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, +0x20, 0x61, 0x64, 0x76, 0x44, 0x65, 0x65, 0x70, 0x50, 0x77, 0x73, 0x2e, 0x20, 0x61, 0x64, 0x76, +0x44, 0x65, 0x65, 0x70, 0x50, 0x77, 0x73, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x41, 0x64, 0x76, 0x50, +0x53, 0x4d, 0x6f, 0x64, 0x65, 0x2e, 0x50, 0x77, 0x72, 0x4c, 0x76, 0x6c, 0x3a, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x32, 0x5d, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x33, 0x5d, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x35, 0x5d, 0x3a, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x41, 0x64, 0x76, 0x44, 0x65, 0x65, 0x70, 0x50, 0x77, 0x73, 0x45, 0x6e, +0x3a, 0x25, 0x64, 0x2c, 0x20, 0x41, 0x64, 0x76, 0x44, 0x65, 0x65, 0x70, 0x50, 0x77, 0x73, 0x54, +0x69, 0x6d, 0x65, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x61, 0x64, 0x76, +0x61, 0x6e, 0x63, 0x65, 0x64, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x2d, 0x73, 0x61, 0x76, 0x69, +0x6e, 0x67, 0x0a, 0x00, 0x25, 0x73, 0x3a, 0x3a, 0x20, 0x57, 0x61, 0x69, 0x74, 0x20, 0x75, 0x6e, +0x74, 0x69, 0x6c, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x30, 0x78, 0x31, 0x32, 0x30, 0x30, 0x28, 0x25, +0x78, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x42, 0x42, 0x50, 0x20, 0x30, 0x78, 0x32, 0x31, 0x33, +0x30, 0x20, 0x28, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x77, 0x69, 0x66, 0x69, 0x2f, 0x52, 0x41, 0x4d, +0x2f, 0x63, 0x68, 0x69, 0x70, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x2e, +0x63, 0x00, 0x00, 0x00, 0x46, 0x57, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, +0x25, 0x78, 0x0a, 0x00, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, +0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x20, 0x2d, 0x2d, 0x20, 0x57, 0x69, 0x46, 0x69, 0x5f, 0x54, 0x61, 0x73, +0x6b, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x20, 0x2d, 0x2d, 0x0a, 0x00, 0x00, 0x4e, 0x55, 0x4c, 0x4c, +0x00, 0x00, 0x00, 0x00, 0x57, 0x49, 0x46, 0x49, 0x20, 0x52, 0x41, 0x4d, 0x20, 0x43, 0x4f, 0x44, +0x45, 0x3a, 0x20, 0x54, 0x61, 0x73, 0x6b, 0x20, 0x6a, 0x69, 0x66, 0x66, 0x69, 0x65, 0x73, 0x28, +0x25, 0x64, 0x29, 0x20, 0x50, 0x4b, 0x54, 0x43, 0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, +0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x0a, 0x00, 0x57, 0x49, 0x46, 0x49, 0x20, 0x72, 0x65, 0x63, +0x65, 0x69, 0x76, 0x65, 0x20, 0x4d, 0x53, 0x47, 0x5f, 0x49, 0x44, 0x5f, 0x57, 0x4d, 0x54, 0x5f, +0x57, 0x49, 0x46, 0x49, 0x5f, 0x55, 0x53, 0x42, 0x5f, 0x44, 0x50, 0x5f, 0x50, 0x55, 0x4c, 0x4c, +0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x0a, 0x00, 0x00, +0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x46, 0x43, 0x45, 0x0a, 0x00, 0x00, 0x20, 0x21, 0x21, 0x2d, +0x2d, 0x3e, 0x20, 0x54, 0x61, 0x73, 0x6b, 0x20, 0x6a, 0x69, 0x66, 0x66, 0x69, 0x65, 0x73, 0x28, +0x25, 0x64, 0x29, 0x20, 0x52, 0x45, 0x53, 0x45, 0x54, 0x20, 0x52, 0x41, 0x4d, 0x0a, 0x00, 0x00, +0x5b, 0x44, 0x79, 0x56, 0x47, 0x41, 0x5d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x30, 0x78, 0x32, +0x33, 0x32, 0x30, 0x5b, 0x31, 0x35, 0x3a, 0x38, 0x5d, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, +0x0a, 0x00, 0x00, 0x00, 0x5b, 0x44, 0x79, 0x56, 0x47, 0x41, 0x5d, 0x4d, 0x69, 0x6e, 0x6f, 0x72, +0x20, 0x56, 0x47, 0x41, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x5b, 0x44, 0x79, 0x56, 0x47, 0x41, 0x5d, 0x53, 0x65, 0x74, 0x20, 0x30, +0x78, 0x32, 0x33, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, +0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, +0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, +0x78, 0x50, 0x41, 0x20, 0x72, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, +0x0a, 0x00, 0x00, 0x00, 0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x78, 0x4c, 0x4e, 0x41, +0x20, 0x72, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, +0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x72, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, +0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x25, 0x64, 0x20, 0x00, 0x0a, 0x57, 0x46, 0x49, +0x44, 0x3d, 0x25, 0x64, 0x20, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x54, 0x53, 0x53, 0x49, 0x20, +0x57, 0x52, 0x49, 0x54, 0x45, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x6c, 0x6f, 0x70, +0x65, 0x5b, 0x30, 0x5d, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x73, 0x6c, 0x6f, 0x70, 0x65, 0x5b, 0x31, +0x5d, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x30, 0x5d, 0x3d, +0x25, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x31, 0x5d, 0x3d, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x20, 0x54, 0x53, 0x53, 0x49, +0x21, 0x21, 0x0a, 0x00, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x6c, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, +0x63, 0x6e, 0x74, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x54, 0x53, 0x53, 0x49, 0x5b, 0x30, 0x5d, 0x20, +0x3d, 0x20, 0x25, 0x78, 0x2c, 0x20, 0x54, 0x53, 0x53, 0x49, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x25, +0x78, 0x0a, 0x00, 0x00, 0x4c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x5b, 0x30, 0x5d, 0x3d, 0x25, 0x64, +0x2c, 0x20, 0x5b, 0x31, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x62, 0x6f, 0x72, +0x74, 0x20, 0x64, 0x75, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x54, 0x58, 0x42, 0x46, 0x20, 0x6f, 0x72, +0x20, 0x42, 0x54, 0x2d, 0x43, 0x6f, 0x65, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, +0x72, 0x20, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x31, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x6e, 0x53, 0x54, 0x53, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0x72, 0x67, +0x65, 0x74, 0x5b, 0x30, 0x5d, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, +0x5b, 0x31, 0x5d, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x31, 0x2e, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x6d, +0x65, 0x61, 0x73, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x32, 0x2e, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x6d, +0x65, 0x61, 0x73, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x33, 0x2e, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x6d, +0x65, 0x61, 0x73, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x69, 0x64, 0x78, 0x3d, 0x25, 0x64, 0x20, 0x6d, +0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x64, 0x5f, 0x64, 0x62, 0x3d, 0x25, 0x64, 0x20, 0x2a, 0x20, +0x28, 0x30, 0x2e, 0x35, 0x29, 0x0a, 0x00, 0x00, 0x31, 0x2e, 0x20, 0x74, 0x73, 0x73, 0x69, 0x5f, +0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x74, 0x6d, 0x70, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, +0x32, 0x2e, 0x20, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x74, 0x6d, +0x70, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x64, 0x65, 0x6c, +0x74, 0x61, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x74, 0x73, 0x73, 0x69, 0x5f, 0x72, 0x65, 0x61, +0x64, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x5b, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5d, +0x20, 0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, +0x31, 0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x5b, 0x41, 0x66, 0x74, +0x65, 0x72, 0x5d, 0x20, 0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, +0x20, 0x30, 0x78, 0x31, 0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x5b, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x53, 0x53, 0x20, 0x70, 0x72, 0x6f, 0x63, +0x65, 0x73, 0x73, 0x5d, 0x20, 0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, +0x2c, 0x20, 0x30, 0x78, 0x31, 0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, +0x5b, 0x31, 0x53, 0x53, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5d, 0x20, 0x55, 0x73, +0x65, 0x20, 0x57, 0x46, 0x31, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20, +0x63, 0x6f, 0x6d, 0x70, 0x65, 0x6e, 0x73, 0x61, 0x74, 0x65, 0x20, 0x57, 0x46, 0x30, 0x0a, 0x00, +0x5b, 0x31, 0x53, 0x53, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5d, 0x20, 0x55, 0x73, +0x65, 0x20, 0x57, 0x46, 0x30, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20, +0x63, 0x6f, 0x6d, 0x70, 0x65, 0x6e, 0x73, 0x61, 0x74, 0x65, 0x20, 0x57, 0x46, 0x31, 0x0a, 0x00, +0x5b, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x31, 0x53, 0x53, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, +0x73, 0x73, 0x5d, 0x20, 0x30, 0x78, 0x31, 0x33, 0x42, 0x34, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x2c, +0x20, 0x30, 0x78, 0x31, 0x33, 0x41, 0x38, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x41, 0x4d, 0x53, 0x55, 0x4d, 0x3d, 0x25, 0x64, 0x20, 0x41, 0x4d, 0x31, 0x30, 0x3d, 0x25, 0x64, +0x20, 0x41, 0x4d, 0x5f, 0x44, 0x49, 0x46, 0x46, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x50, 0x41, 0x53, +0x53, 0x54, 0x68, 0x72, 0x65, 0x73, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x53, 0x4f, 0x46, 0x54, +0x41, 0x47, 0x43, 0x20, 0x52, 0x45, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x20, 0x65, 0x72, 0x72, 0x6f, +0x72, 0x0a, 0x00, 0x00, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x53, 0x4f, +0x46, 0x54, 0x41, 0x47, 0x43, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, +0x65, 0x0a, 0x00, 0x00, 0x54, 0x48, 0x45, 0x52, 0x4d, 0x41, 0x4c, 0x20, 0x25, 0x78, 0x0a, 0x00, +0x54, 0x68, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, +0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x4d, 0x41, 0x43, 0x2d, 0x43, 0x52, 0x20, 0x52, +0x45, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00, 0x00, 0x00, +0x45, 0x52, 0x52, 0x4f, 0x52, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x72, +0x72, 0x61, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x0a, 0x00, 0x00, 0x52, 0x46, 0x20, 0x72, +0x65, 0x61, 0x64, 0x20, 0x52, 0x25, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x2c, 0x20, 0x0a, 0x00, +0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4d, 0x43, 0x43, 0x49, 0x44, 0x3d, 0x25, 0x64, +0x0a, 0x00, 0x00, 0x00, 0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x54, 0x58, 0x42, 0x46, +0x20, 0x72, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, +0x45, 0x52, 0x52, 0x4f, 0x52, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x52, 0x46, 0x20, 0x61, 0x72, 0x72, +0x61, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x35, 0x47, 0x20, 0x65, +0x50, 0x41, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, +0x6c, 0x69, 0x62, 0x72, 0x61, 0x74, 0x65, 0x20, 0x54, 0x53, 0x53, 0x49, 0x0a, 0x00, 0x00, 0x00, +0x32, 0x47, 0x20, 0x65, 0x50, 0x41, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, +0x74, 0x20, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x74, 0x65, 0x20, 0x54, 0x53, 0x53, 0x49, +0x0a, 0x00, 0x00, 0x00, 0x52, 0x58, 0x49, 0x51, 0x20, 0x6d, 0x69, 0x3d, 0x30, 0x78, 0x25, 0x78, +0x2c, 0x20, 0x6d, 0x71, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x73, 0x69, 0x3d, 0x30, 0x78, +0x25, 0x78, 0x2c, 0x20, 0x73, 0x71, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x72, 0x69, 0x71, +0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x62, 0x62, 0x70, 0x76, 0x61, 0x6c, 0x3d, 0x25, 0x64, +0x20, 0x0a, 0x00, 0x00, 0x4c, 0x4e, 0x41, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x5b, 0x47, 0x5f, 0x69, +0x6d, 0x62, 0x3d, 0x30, 0x78, 0x25, 0x32, 0x78, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x50, 0x68, +0x5f, 0x72, 0x78, 0x3d, 0x30, 0x78, 0x25, 0x32, 0x78, 0x28, 0x25, 0x64, 0x29, 0x5d, 0x0a, 0x00, +0x20, 0x4c, 0x43, 0x2d, 0x54, 0x61, 0x6e, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x42, 0x42, 0x50, 0x20, 0x5b, +0x30, 0x78, 0x32, 0x37, 0x37, 0x34, 0x5d, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x28, 0x57, 0x46, 0x25, 0x64, 0x29, 0x2d, 0x43, 0x61, 0x6c, 0x20, 0x44, 0x6f, 0x6e, 0x65, 0x21, +0x21, 0x20, 0x42, 0x42, 0x50, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x37, 0x34, 0x5d, 0x20, 0x3d, +0x20, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x57, 0x43, 0x61, 0x6c, 0x20, 0x53, 0x74, +0x61, 0x72, 0x74, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x20, 0x57, 0x46, 0x20, 0x25, +0x64, 0x20, 0x2d, 0x2d, 0x2d, 0x0a, 0x00, 0x00, 0x52, 0x58, 0x31, 0x5f, 0x42, 0x57, 0x32, 0x30, +0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x32, 0x5f, +0x42, 0x57, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x52, 0x58, 0x31, 0x5f, 0x42, 0x57, 0x34, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x32, 0x5f, 0x42, 0x57, 0x34, 0x30, 0x20, 0x3d, 0x20, 0x30, +0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x31, 0x5f, 0x42, 0x57, 0x38, 0x30, +0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x32, 0x5f, +0x42, 0x57, 0x38, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x30, 0x78, 0x32, 0x34, 0x43, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x30, 0x78, 0x32, 0x35, +0x30, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x61, 0x70, 0x70, 0x50, 0x6b, 0x74, 0x43, 0x6d, +0x64, 0x5f, 0x49, 0x6e, 0x69, 0x74, 0x47, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, +0x21, 0x0a, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x30, 0x78, +0x34, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x34, 0x35, 0x3d, 0x25, 0x78, 0x2c, 0x20, +0x30, 0x78, 0x34, 0x39, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x34, 0x44, 0x3d, 0x25, 0x78, +0x21, 0x0a, 0x00, 0x00, 0x63, 0x68, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x63, 0x65, +0x3d, 0x25, 0x64, 0x2c, 0x20, 0x65, 0x66, 0x75, 0x73, 0x65, 0x47, 0x61, 0x69, 0x6e, 0x3d, 0x25, +0x64, 0x0a, 0x00, 0x00, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, +0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x3e, 0x20, +0x30, 0x78, 0x32, 0x33, 0x32, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, +0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x30, 0x3d, 0x25, 0x78, 0x2c, +0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, +0x31, 0x38, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x41, 0x66, 0x74, 0x65, 0x72, 0x3e, 0x20, 0x30, +0x78, 0x32, 0x33, 0x32, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x32, 0x34, +0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x31, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, +0x30, 0x78, 0x32, 0x33, 0x31, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x31, +0x38, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x20, 0x4d, 0x6f, +0x64, 0x65, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2d, 0x42, 0x61, +0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x65, 0x4c, 0x4e, 0x41, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x47, 0x2d, 0x42, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x3d, 0x25, +0x64, 0x2c, 0x20, 0x65, 0x4c, 0x4e, 0x41, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x43, 0x52, 0x5b, 0x25, +0x78, 0x5d, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x5b, 0x25, 0x78, 0x5d, 0x3d, 0x25, 0x78, 0x0a, 0x00, +0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, +0x66, 0x6f, 0x72, 0x20, 0x54, 0x58, 0x2f, 0x52, 0x58, 0x20, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, +0x0a, 0x00, 0x00, 0x00, 0x6d, 0x74, 0x37, 0x36, 0x36, 0x32, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, +0x68, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, +0x6c, 0x3d, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x73, 0x63, 0x61, 0x6e, 0x3d, 0x25, 0x64, 0x2c, 0x20, +0x42, 0x57, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x52, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3d, +0x25, 0x64, 0x2c, 0x20, 0x54, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3d, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x43, 0x52, 0x20, 0x4c, 0x6f, 0x61, 0x64, 0x20, 0x28, 0x6d, 0x6f, 0x64, +0x65, 0x3d, 0x25, 0x64, 0x29, 0x20, 0x28, 0x74, 0x65, 0x6d, 0x70, 0x3d, 0x25, 0x64, 0x29, 0x20, +0x28, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3d, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, +0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x43, 0x53, 0x41, 0x20, 0x63, 0x6d, 0x64, 0x2c, +0x20, 0x43, 0x53, 0x41, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3a, 0x25, 0x64, 0x2c, 0x20, +0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, 0x00, +0x47, 0x20, 0x62, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, +0x20, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x20, 0x44, 0x50, 0x44, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x41, 0x20, 0x62, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x50, 0x41, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, +0x20, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x20, 0x44, 0x50, 0x44, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x44, 0x50, 0x44, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x00, 0x00, 0x42, 0x59, 0x50, 0x41, +0x53, 0x53, 0x20, 0x57, 0x46, 0x30, 0x20, 0x44, 0x50, 0x44, 0x3a, 0x74, 0x78, 0x41, 0x4c, 0x43, +0x5f, 0x72, 0x65, 0x71, 0x5f, 0x73, 0x61, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x54, 0x78, 0x30, 0x5f, +0x44, 0x50, 0x44, 0x5f, 0x41, 0x4c, 0x43, 0x5f, 0x55, 0x70, 0x5f, 0x4c, 0x69, 0x6d, 0x69, 0x74, +0x3d, 0x25, 0x64, 0x2c, 0x54, 0x78, 0x30, 0x5f, 0x44, 0x50, 0x44, 0x5f, 0x41, 0x4c, 0x43, 0x5f, +0x4c, 0x72, 0x5f, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x20, 0x57, 0x46, 0x31, 0x20, 0x44, 0x50, 0x44, 0x3a, 0x74, +0x78, 0x41, 0x4c, 0x43, 0x5f, 0x72, 0x65, 0x71, 0x5f, 0x73, 0x61, 0x74, 0x3d, 0x25, 0x64, 0x2c, +0x54, 0x78, 0x31, 0x5f, 0x44, 0x50, 0x44, 0x5f, 0x41, 0x4c, 0x43, 0x5f, 0x55, 0x70, 0x5f, 0x4c, +0x69, 0x6d, 0x69, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x54, 0x78, 0x31, 0x5f, 0x44, 0x50, 0x44, 0x5f, +0x41, 0x4c, 0x43, 0x5f, 0x4c, 0x72, 0x5f, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x3d, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x28, 0x31, 0x29, 0x20, 0x30, 0x78, 0x31, 0x30, 0x45, 0x30, 0x3d, 0x25, +0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x45, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, +0x31, 0x30, 0x46, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x34, 0x3d, +0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x38, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, +0x78, 0x31, 0x30, 0x46, 0x43, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x28, 0x32, 0x29, 0x20, +0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x00, 0x28, 0x33, 0x29, 0x20, 0x30, 0x78, 0x31, 0x30, +0x45, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x45, 0x34, 0x3d, 0x25, 0x78, +0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x30, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, +0x30, 0x46, 0x34, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x38, 0x3d, 0x25, +0x78, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x30, 0x46, 0x43, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x28, 0x34, 0x29, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x00, 0x69, 0x64, 0x78, 0x3d, +0x25, 0x64, 0x2c, 0x20, 0x58, 0x59, 0x3d, 0x25, 0x78, 0x2c, 0x20, 0x41, 0x4d, 0x36, 0x33, 0x3d, +0x25, 0x64, 0x0a, 0x00, 0x69, 0x64, 0x78, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x58, 0x59, 0x5b, 0x5d, +0x3d, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x44, 0x50, 0x44, 0x20, 0x43, 0x61, 0x6c, 0x69, +0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x21, 0x20, +0x28, 0x69, 0x64, 0x78, 0x3d, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x50, 0x44, 0x20, +0x43, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x61, 0x69, 0x6c, +0x65, 0x64, 0x21, 0x20, 0x28, 0x52, 0x65, 0x74, 0x72, 0x79, 0x20, 0x43, 0x6e, 0x74, 0x3d, 0x35, +0x29, 0x0a, 0x00, 0x00, 0x57, 0x46, 0x30, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x39, 0x38, 0x7e, +0x30, 0x78, 0x32, 0x37, 0x41, 0x34, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x25, 0x30, 0x38, 0x78, +0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, +0x20, 0x20, 0x20, 0x20, 0x57, 0x46, 0x31, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x43, 0x30, 0x7e, +0x30, 0x78, 0x32, 0x37, 0x43, 0x43, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x25, 0x30, 0x38, 0x78, +0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x54, 0x58, 0x20, 0x49, 0x51, 0x43, 0x20, 0x43, 0x41, 0x4c, 0x20, 0x64, +0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x35, 0x47, 0x20, 0x54, 0x58, 0x20, 0x4c, 0x4f, +0x46, 0x54, 0x0a, 0x00, 0x32, 0x47, 0x20, 0x54, 0x58, 0x20, 0x4c, 0x4f, 0x46, 0x54, 0x0a, 0x00, +0x57, 0x46, 0x30, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x38, 0x30, 0x7e, 0x30, 0x78, 0x32, 0x37, +0x39, 0x34, 0x5d, 0x0a, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, +0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, +0x78, 0x0a, 0x57, 0x46, 0x31, 0x20, 0x5b, 0x30, 0x78, 0x32, 0x37, 0x41, 0x38, 0x7e, 0x30, 0x78, +0x32, 0x37, 0x42, 0x43, 0x5d, 0x0a, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, +0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, +0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x54, 0x58, 0x20, 0x4c, 0x4f, 0x46, 0x54, 0x20, +0x43, 0x41, 0x4c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x69, 0x3d, 0x25, 0x64, +0x20, 0x46, 0x44, 0x49, 0x51, 0x20, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x25, 0x30, 0x38, +0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x20, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x2d, 0x2d, 0x3e, 0x20, 0x4b, 0x20, 0x49, 0x44, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x20, 0x3c, 0x2d, +0x2d, 0x0a, 0x00, 0x00, 0x3d, 0x3d, 0x3d, 0x20, 0x45, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4b, +0x20, 0x3d, 0x3d, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, +0x52, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0x52, 0x00, 0x00, 0x00, +0x05, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, +0x04, 0x20, 0x41, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, +0xda, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0xda, 0x00, 0x00, 0x00, +0x30, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x08, 0x14, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +0x00, 0x23, 0x41, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, +0x08, 0x34, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x08, 0x14, 0x00, 0x00, +0x05, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, +0x00, 0x23, 0x41, 0x00, 0x08, 0x34, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, +0x00, 0x74, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x23, 0x41, 0x00, 0x08, 0x74, 0x00, 0x00, +0x04, 0x00, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, +0x04, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, +0x02, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, 0x02, 0x00, 0x00, 0x00, +0x09, 0x00, 0x00, 0x00, 0x08, 0x23, 0x41, 0x00, 0x70, 0x70, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, +0x08, 0x23, 0x41, 0x00, 0x70, 0x70, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x50, 0x9d, 0xe8, 0x15, 0x35, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x50, 0x9d, 0xe8, 0x15, +0x09, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x4e, 0x9b, 0xe7, 0x15, 0x39, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x4e, 0x9b, 0xe7, 0x15, 0x05, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, +0x50, 0x9d, 0xe8, 0x15, 0x35, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x50, 0x9d, 0xe8, 0x15, +0x09, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x4e, 0x9b, 0xe7, 0x15, 0x39, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x4e, 0x9b, 0xe7, 0x15, 0x09, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x02, 0x02, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x02, 0x02, 0x00, 0x00, +0x04, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x42, 0x1e, 0x34, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x42, 0x1e, 0x05, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x42, 0x1e, 0x35, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, +0x09, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x58, 0x42, 0x1e, 0x39, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x58, 0x42, 0x1e, 0x04, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5c, 0x42, 0x1e, 0x34, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x42, 0x1e, +0x05, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x35, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x09, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x58, 0x42, 0x1e, 0x39, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x58, 0x42, 0x1e, +0x00, 0x00, 0x00, 0x00, 0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x08, 0x30, 0x00, 0x00, 0x00, +0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 0x23, 0x41, 0x00, +0xf3, 0x00, 0x05, 0x07, 0x31, 0x00, 0x00, 0x00, 0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x07, +0x04, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, 0x34, 0x00, 0x00, 0x00, +0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, 0x01, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, +0x0b, 0x08, 0x0a, 0x04, 0x31, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x0b, 0x08, 0x0a, 0x04, +0x05, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, 0x35, 0x00, 0x00, 0x00, +0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0a, 0x04, 0x09, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, +0x05, 0x03, 0x0a, 0x04, 0x39, 0x00, 0x00, 0x00, 0x34, 0x23, 0x41, 0x00, 0x05, 0x03, 0x0a, 0x04, +0x09, 0x00, 0x00, 0x00, 0x8c, 0x23, 0x41, 0x00, 0x14, 0x10, 0x10, 0x10, 0x39, 0x00, 0x00, 0x00, +0x8c, 0x23, 0x41, 0x00, 0x14, 0x10, 0x10, 0x10, 0x04, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x32, 0x23, 0x2e, 0x2e, 0x34, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x32, 0x23, 0x2e, 0x2e, +0x05, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x32, 0x23, 0x2e, 0x2e, 0x35, 0x00, 0x00, 0x00, +0xa4, 0x23, 0x41, 0x00, 0x32, 0x23, 0x2e, 0x2e, 0x09, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x26, 0x22, 0x1c, 0x1c, 0x39, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x26, 0x22, 0x1c, 0x1c, +0x09, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, 0x17, 0x17, 0x16, 0x16, 0x39, 0x00, 0x00, 0x00, +0xac, 0x23, 0x41, 0x00, 0x17, 0x17, 0x16, 0x16, 0x04, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, +0x41, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x80, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, +0x00, 0x26, 0x41, 0x00, 0x80, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, +0x81, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x81, 0x00, 0x00, 0x00, +0x09, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x82, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, +0x00, 0x26, 0x41, 0x00, 0x82, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, +0x0b, 0x00, 0x03, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x00, 0x03, 0x00, +0x01, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x0f, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00, +0x04, 0x26, 0x41, 0x00, 0x0b, 0x0f, 0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, +0x0b, 0x2c, 0x01, 0x00, 0x35, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x2c, 0x01, 0x00, +0x09, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, 0x0b, 0x3c, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, +0x04, 0x26, 0x41, 0x00, 0x0b, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x26, 0x41, 0x00, +0x87, 0x00, 0x10, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0c, 0x26, 0x41, 0x00, 0x87, 0x00, 0x10, 0x00, +0x01, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, 0xf4, 0xa7, 0xab, 0x00, 0x31, 0x00, 0x00, 0x00, +0x14, 0x26, 0x41, 0x00, 0xf4, 0xa7, 0xab, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, +0xf5, 0xa7, 0xab, 0x00, 0x35, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, 0xf5, 0xa7, 0xab, 0x00, +0x09, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, 0xf6, 0xa7, 0xab, 0x00, 0x39, 0x00, 0x00, 0x00, +0x14, 0x26, 0x41, 0x00, 0xf6, 0xa7, 0xab, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, +0x00, 0x04, 0x0e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x0e, 0x00, +0x05, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x18, 0x00, 0x35, 0x00, 0x00, 0x00, +0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x18, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, +0x00, 0x04, 0x20, 0x00, 0x39, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x04, 0x20, 0x00, +0x05, 0x00, 0x00, 0x00, 0x34, 0x29, 0x41, 0x00, 0x92, 0x04, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, +0x34, 0x29, 0x41, 0x00, 0x92, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x29, 0x41, 0x00, +0x1e, 0x38, 0x00, 0x01, 0x31, 0x00, 0x00, 0x00, 0x40, 0x29, 0x41, 0x00, 0x1e, 0x38, 0x00, 0x01, +0x05, 0x00, 0x00, 0x00, 0x40, 0x29, 0x41, 0x00, 0x1e, 0x38, 0x00, 0x01, 0x35, 0x00, 0x00, 0x00, +0x40, 0x29, 0x41, 0x00, 0x1e, 0x38, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x48, 0x29, 0x41, 0x00, +0x91, 0xa9, 0x00, 0xf0, 0x39, 0x00, 0x00, 0x00, 0x48, 0x29, 0x41, 0x00, 0x91, 0xa9, 0x00, 0xf0, +0x09, 0x00, 0x00, 0x00, 0x4c, 0x29, 0x41, 0x00, 0xf9, 0x9f, 0xff, 0xf9, 0x39, 0x00, 0x00, 0x00, +0x4c, 0x29, 0x41, 0x00, 0xf9, 0x9f, 0xff, 0xf9, 0x04, 0x00, 0x00, 0x00, 0xac, 0x29, 0x41, 0x00, +0x00, 0x48, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xac, 0x29, 0x41, 0x00, 0x00, 0x48, 0x00, 0x00, +0x05, 0x00, 0x00, 0x00, 0xac, 0x29, 0x41, 0x00, 0x00, 0x48, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, +0xac, 0x29, 0x41, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x4e, 0xa5, 0xf3, 0x15, 0x30, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x4e, 0xa5, 0xf3, 0x15, +0x04, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x4e, 0xa4, 0xf3, 0x15, 0x34, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x4e, 0xa4, 0xf3, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x5b, 0xa6, 0xf3, 0x15, 0x31, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x5b, 0xa6, 0xf3, 0x15, +0x05, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x35, 0x00, 0x00, 0x00, +0x10, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x09, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x5b, 0xa8, 0xf3, 0x15, 0x39, 0x00, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, +0x00, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x4e, 0xa5, 0xf3, 0x15, 0x30, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x4e, 0xa5, 0xf3, 0x15, 0x04, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, +0x4e, 0xa4, 0xf3, 0x15, 0x34, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x4e, 0xa4, 0xf3, 0x15, +0x01, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa6, 0xf3, 0x15, 0x31, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x5b, 0xa6, 0xf3, 0x15, 0x05, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, +0x5b, 0xa8, 0xf3, 0x15, 0x35, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, +0x09, 0x00, 0x00, 0x00, 0x14, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x39, 0x00, 0x00, 0x00, +0x14, 0x23, 0x41, 0x00, 0x5b, 0xa8, 0xf3, 0x15, 0x00, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x10, 0x10, 0xff, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, +0x04, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x34, 0x00, 0x00, 0x00, +0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x10, 0x10, 0xff, 0x00, 0x31, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, +0x05, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x35, 0x00, 0x00, 0x00, +0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, 0x09, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, +0x10, 0x10, 0xff, 0x00, 0x39, 0x00, 0x00, 0x00, 0x18, 0x23, 0x41, 0x00, 0x10, 0x10, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x0f, 0x30, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x0f, 0x04, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x48, 0x36, 0x18, 0x34, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, +0x01, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x18, 0x31, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x18, 0x05, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x48, 0x36, 0x18, 0x35, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, +0x09, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x39, 0x00, 0x00, 0x00, +0x20, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x00, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x4a, 0x36, 0x0f, 0x30, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x0f, +0x04, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x34, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x01, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x4a, 0x36, 0x18, 0x31, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x4a, 0x36, 0x18, +0x05, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x35, 0x00, 0x00, 0x00, +0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, 0x09, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x48, 0x36, 0x18, 0x39, 0x00, 0x00, 0x00, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x48, 0x36, 0x18, +0x01, 0x00, 0x00, 0x00, 0x68, 0x23, 0x41, 0x00, 0x04, 0x20, 0x7c, 0x00, 0x31, 0x00, 0x00, 0x00, +0x68, 0x23, 0x41, 0x00, 0x04, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, +0x96, 0x0e, 0x9e, 0xba, 0x30, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, +0x04, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x34, 0x00, 0x00, 0x00, +0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x01, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, +0x96, 0x0e, 0x9e, 0xba, 0x31, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, +0x05, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x35, 0x00, 0x00, 0x00, +0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, 0x09, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, +0x96, 0x0e, 0x9e, 0xba, 0x39, 0x00, 0x00, 0x00, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0x9e, 0xba, +0x01, 0x00, 0x00, 0x00, 0x45, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x66, 0x66, 0x06, 0x00, +0x02, 0x00, 0x00, 0x00, 0x54, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x11, 0x11, 0x09, 0x00, +0x03, 0x00, 0x00, 0x00, 0x63, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xbb, 0xbb, 0x0b, 0x00, +0x04, 0x00, 0x00, 0x00, 0x72, 0x1c, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0e, 0x00, +0x05, 0x00, 0x00, 0x00, 0x81, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, +0x06, 0x00, 0x00, 0x00, 0x90, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0xbb, 0xbb, 0x03, 0x00, +0x07, 0x00, 0x00, 0x00, 0x9f, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x66, 0x66, 0x06, 0x00, +0x08, 0x00, 0x00, 0x00, 0xae, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x11, 0x09, 0x00, +0x09, 0x00, 0x00, 0x00, 0xbd, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0xbb, 0xbb, 0x0b, 0x00, +0x0a, 0x00, 0x00, 0x00, 0xcc, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0e, 0x00, +0x0b, 0x00, 0x00, 0x00, 0xdb, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, +0x0c, 0x00, 0x00, 0x00, 0xea, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xbb, 0xbb, 0x03, 0x00, +0x0d, 0x00, 0x00, 0x00, 0xf9, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x66, 0x66, 0x06, 0x00, +0x0e, 0x00, 0x00, 0x00, 0x1d, 0x1d, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0x0c, 0x00, +0x22, 0x00, 0x00, 0x00, 0x4c, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x24, 0x00, 0x00, 0x00, 0x5b, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x25, 0x00, 0x00, 0x00, 0x63, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x26, 0x00, 0x00, 0x00, 0x6a, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x27, 0x00, 0x00, 0x00, 0x72, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x28, 0x00, 0x00, 0x00, 0x79, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x29, 0x00, 0x00, 0x00, 0x81, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x2a, 0x00, 0x00, 0x00, 0x88, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x2b, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x2c, 0x00, 0x00, 0x00, 0x97, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x2d, 0x00, 0x00, 0x00, 0x9f, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x2e, 0x00, 0x00, 0x00, 0xa6, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x2f, 0x00, 0x00, 0x00, 0xae, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x30, 0x00, 0x00, 0x00, 0xb5, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x31, 0x00, 0x00, 0x00, 0xbd, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x32, 0x00, 0x00, 0x00, 0xc4, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x33, 0x00, 0x00, 0x00, 0xcc, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x34, 0x00, 0x00, 0x00, 0xd3, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x35, 0x00, 0x00, 0x00, 0xdb, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x36, 0x00, 0x00, 0x00, 0xe2, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x37, 0x00, 0x00, 0x00, 0xea, 0x1e, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x38, 0x00, 0x00, 0x00, 0xf1, 0x1e, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x39, 0x00, 0x00, 0x00, 0xf9, 0x1e, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x3a, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x3b, 0x00, 0x00, 0x00, 0x08, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x3c, 0x00, 0x00, 0x00, 0x0f, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x3d, 0x00, 0x00, 0x00, 0x17, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x3e, 0x00, 0x00, 0x00, 0x1e, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x3f, 0x00, 0x00, 0x00, 0x26, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x40, 0x00, 0x00, 0x00, 0x2d, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x41, 0x00, 0x00, 0x00, 0x35, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x42, 0x00, 0x00, 0x00, 0x3c, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x43, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x44, 0x00, 0x00, 0x00, 0x4b, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x45, 0x00, 0x00, 0x00, 0x53, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x46, 0x00, 0x00, 0x00, 0x5a, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x47, 0x00, 0x00, 0x00, 0x62, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x48, 0x00, 0x00, 0x00, 0x69, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x49, 0x00, 0x00, 0x00, 0x71, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x4a, 0x00, 0x00, 0x00, 0x78, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x4b, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x4c, 0x00, 0x00, 0x00, 0x87, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x4d, 0x00, 0x00, 0x00, 0x8f, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x4e, 0x00, 0x00, 0x00, 0x96, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x4f, 0x00, 0x00, 0x00, 0x9e, 0x1f, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x50, 0x00, 0x00, 0x00, 0xa5, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x51, 0x00, 0x00, 0x00, 0xad, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x52, 0x00, 0x00, 0x00, 0xb4, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x53, 0x00, 0x00, 0x00, 0xbc, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x54, 0x00, 0x00, 0x00, 0xc3, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x55, 0x00, 0x00, 0x00, 0xcb, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x56, 0x00, 0x00, 0x00, 0xd2, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x57, 0x00, 0x00, 0x00, 0xda, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x58, 0x00, 0x00, 0x00, 0xe1, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x59, 0x00, 0x00, 0x00, 0xe9, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x5a, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x5b, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x5c, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x5d, 0x00, 0x00, 0x00, 0x0e, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x5e, 0x00, 0x00, 0x00, 0x16, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x5f, 0x00, 0x00, 0x00, 0x1d, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x60, 0x00, 0x00, 0x00, 0x25, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x61, 0x00, 0x00, 0x00, 0x2c, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x62, 0x00, 0x00, 0x00, 0x34, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x63, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x64, 0x00, 0x00, 0x00, 0x3b, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x65, 0x00, 0x00, 0x00, 0x43, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x66, 0x00, 0x00, 0x00, 0x4a, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x67, 0x00, 0x00, 0x00, 0x52, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x68, 0x00, 0x00, 0x00, 0x59, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x69, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x6a, 0x00, 0x00, 0x00, 0x68, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x6b, 0x00, 0x00, 0x00, 0x70, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x6c, 0x00, 0x00, 0x00, 0x77, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x6d, 0x00, 0x00, 0x00, 0x7f, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x6e, 0x00, 0x00, 0x00, 0x86, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x6f, 0x00, 0x00, 0x00, 0x8e, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x70, 0x00, 0x00, 0x00, 0x95, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x71, 0x00, 0x00, 0x00, 0x9d, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x72, 0x00, 0x00, 0x00, 0xa4, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x73, 0x00, 0x00, 0x00, 0xac, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x74, 0x00, 0x00, 0x00, 0xb3, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x75, 0x00, 0x00, 0x00, 0xbb, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x76, 0x00, 0x00, 0x00, 0xc2, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x77, 0x00, 0x00, 0x00, 0xca, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x78, 0x00, 0x00, 0x00, 0xd1, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x79, 0x00, 0x00, 0x00, 0xd9, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x7a, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x7b, 0x00, 0x00, 0x00, 0xe8, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x7c, 0x00, 0x00, 0x00, 0xef, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x7d, 0x00, 0x00, 0x00, 0xf7, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x7e, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x7f, 0x00, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x80, 0x00, 0x00, 0x00, 0x0d, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x81, 0x00, 0x00, 0x00, 0x15, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x82, 0x00, 0x00, 0x00, 0x1c, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x83, 0x00, 0x00, 0x00, 0x24, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x84, 0x00, 0x00, 0x00, 0x2b, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x85, 0x00, 0x00, 0x00, 0x33, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x86, 0x00, 0x00, 0x00, 0x3a, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x87, 0x00, 0x00, 0x00, 0x42, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x88, 0x00, 0x00, 0x00, 0x49, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x89, 0x00, 0x00, 0x00, 0x51, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x8a, 0x00, 0x00, 0x00, 0x58, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x8b, 0x00, 0x00, 0x00, 0x60, 0x21, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x8c, 0x00, 0x00, 0x00, 0x67, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x8d, 0x00, 0x00, 0x00, 0x6f, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x8e, 0x00, 0x00, 0x00, 0x76, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x8f, 0x00, 0x00, 0x00, 0x7e, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x90, 0x00, 0x00, 0x00, 0x85, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x91, 0x00, 0x00, 0x00, 0x8d, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x92, 0x00, 0x00, 0x00, 0x94, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x93, 0x00, 0x00, 0x00, 0x9c, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0x94, 0x00, 0x00, 0x00, 0xa3, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x95, 0x00, 0x00, 0x00, 0xab, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0x96, 0x00, 0x00, 0x00, 0xb2, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0x97, 0x00, 0x00, 0x00, 0xba, 0x21, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0x98, 0x00, 0x00, 0x00, 0xc1, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x99, 0x00, 0x00, 0x00, 0xc9, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0x9a, 0x00, 0x00, 0x00, 0xd0, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, +0x9b, 0x00, 0x00, 0x00, 0xd8, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x9c, 0x00, 0x00, 0x00, 0xdf, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0x9d, 0x00, 0x00, 0x00, 0xe7, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0x9e, 0x00, 0x00, 0x00, 0xee, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, +0x9f, 0x00, 0x00, 0x00, 0xf6, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0xa0, 0x00, 0x00, 0x00, 0xfd, 0x21, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0xa1, 0x00, 0x00, 0x00, 0x05, 0x22, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0xa2, 0x00, 0x00, 0x00, 0x0c, 0x22, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x55, 0x55, 0x0d, 0x00, +0xa3, 0x00, 0x00, 0x00, 0x14, 0x22, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0xa4, 0x00, 0x00, 0x00, 0x1b, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xa5, 0x00, 0x00, 0x00, 0x23, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0xa7, 0x00, 0x00, 0x00, 0x32, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0xa9, 0x00, 0x00, 0x00, 0x41, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0xab, 0x00, 0x00, 0x00, 0x50, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x55, 0x55, 0x09, 0x00, +0xad, 0x00, 0x00, 0x00, 0x5f, 0x22, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, +0xb7, 0x00, 0x00, 0x00, 0xce, 0x1c, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0e, 0x00, +0xb8, 0x00, 0x00, 0x00, 0xd5, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xb9, 0x00, 0x00, 0x00, 0xdd, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, +0xbb, 0x00, 0x00, 0x00, 0xec, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0xbc, 0x00, 0x00, 0x00, 0xf3, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0xbd, 0x00, 0x00, 0x00, 0xfb, 0x1c, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x06, 0x00, +0xc0, 0x00, 0x00, 0x00, 0x11, 0x1d, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0xc4, 0x00, 0x00, 0x00, 0x2f, 0x1d, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xc8, 0x00, 0x00, 0x00, 0x4d, 0x1d, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0xcc, 0x00, 0x00, 0x00, 0x6b, 0x1d, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0xd0, 0x00, 0x00, 0x00, 0x89, 0x1d, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xd4, 0x00, 0x00, 0x00, 0xa7, 0x1d, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, +0xd8, 0x00, 0x00, 0x00, 0xc5, 0x1d, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x0a, 0x00, +0x01, 0x00, 0xb7, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x77, 0x77, 0x55, 0x33, 0x8f, 0xaa, 0x11, 0x66, +0x10, 0x1f, 0x1f, 0x3f, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, +0x00, 0x60, 0x9c, 0x0f, 0x05, 0x07, 0x00, 0x00, 0x77, 0x77, 0x44, 0x33, 0x8f, 0xaa, 0x33, 0x66, +0x00, 0xf3, 0x33, 0x03, 0x02, 0x00, 0xc8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x77, 0x77, 0x55, 0x33, +0x8f, 0xaa, 0x11, 0x66, 0x10, 0x1f, 0x1f, 0x3f, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, +0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x9c, 0x0f, 0x05, 0x07, 0x00, 0x00, 0x77, 0x77, 0x44, 0x22, +0x8f, 0xaa, 0x33, 0xaa, 0x00, 0xf3, 0x33, 0x03, 0x03, 0x00, 0x20, 0x00, 0x32, 0x00, 0x00, 0x00, +0x77, 0x77, 0x45, 0x33, 0x8f, 0xaa, 0x11, 0x66, 0x10, 0x1f, 0x1f, 0x3f, 0x16, 0x00, 0x00, 0x00, +0x17, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x9c, 0x0f, 0x05, 0x07, 0x00, 0x00, +0x77, 0x77, 0x33, 0x22, 0x8f, 0xaa, 0x66, 0xaa, 0x00, 0xf3, 0x33, 0x03, 0x04, 0x00, 0x34, 0x00, +0x44, 0x00, 0x00, 0x00, 0x77, 0x77, 0x44, 0x33, 0x8f, 0xaa, 0x33, 0x66, 0x10, 0x1f, 0x1f, 0x3f, +0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x9c, 0x0f, +0x05, 0x07, 0x00, 0x00, 0x77, 0x77, 0x33, 0x21, 0x8f, 0xaa, 0x66, 0xaf, 0x00, 0xf3, 0x33, 0x03, +0x05, 0x00, 0x64, 0x00, 0x74, 0x00, 0x00, 0x00, 0x77, 0x57, 0x44, 0x33, 0x8f, 0xaa, 0x33, 0x66, +0x10, 0x10, 0x10, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, +0x00, 0x60, 0x7c, 0x2f, 0x05, 0x07, 0x00, 0x00, 0x65, 0x46, 0x22, 0x21, 0x8f, 0xaa, 0xaa, 0xaf, +0x00, 0xf3, 0x03, 0x03, 0x06, 0x00, 0x78, 0x00, 0x90, 0x00, 0x00, 0x00, 0x77, 0x46, 0x33, 0x33, +0x8f, 0xaa, 0x66, 0x66, 0x10, 0x0f, 0x0f, 0x3f, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, +0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x7c, 0x2b, 0x05, 0x07, 0x00, 0x00, 0x64, 0x35, 0x22, 0x10, +0x8f, 0xaa, 0xaa, 0xff, 0x00, 0x83, 0xf3, 0x02, 0x07, 0x00, 0x95, 0x00, 0xa5, 0x00, 0x00, 0x00, +0x65, 0x34, 0x33, 0x33, 0x8f, 0xaa, 0x66, 0x66, 0x10, 0x0f, 0x0f, 0x3f, 0x12, 0x00, 0x00, 0x00, +0x12, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x0f, 0x00, 0x00, 0x60, 0x7c, 0x2b, 0x05, 0x07, 0x00, 0x00, +0x32, 0x03, 0x22, 0x10, 0x8f, 0xaa, 0xaa, 0xff, 0x00, 0x83, 0xf3, 0x02, 0x09, 0x00, 0x08, 0x00, +0x00, 0x00, 0x47, 0x10, 0x09, 0x00, 0x0c, 0x00, 0x47, 0x30, 0xc7, 0x11, 0x09, 0x00, 0x10, 0x00, +0x47, 0x10, 0x00, 0x00, 0x09, 0x00, 0x9c, 0x02, 0x10, 0x10, 0x10, 0x3f, 0x09, 0x00, 0x6c, 0x02, +0x57, 0x77, 0x50, 0x00, 0x00, 0x00, 0xa4, 0x02, 0x5f, 0x77, 0x2a, 0x25, 0x00, 0x00, 0x54, 0x01, +0xa1, 0x1e, 0xf6, 0xac, 0x00, 0x00, 0x48, 0x01, 0x00, 0x7c, 0x72, 0xa9, 0x00, 0x00, 0x08, 0x03, +0x00, 0x7c, 0x72, 0xa9, 0x00, 0x00, 0x58, 0x00, 0x00, 0x60, 0x7c, 0x2f, 0x01, 0x00, 0xa4, 0x02, +0x7e, 0x77, 0x2a, 0x26, 0x09, 0x00, 0x34, 0x01, 0x80, 0x38, 0x04, 0x20, 0x01, 0x00, 0x20, 0x03, +0x83, 0x68, 0x88, 0x04, 0x04, 0x2f, 0x41, 0x00, 0x01, 0x22, 0x00, 0x80, 0x0c, 0x2f, 0x41, 0x00, +0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x2f, 0x41, 0x00, 0xee, 0xff, 0x00, 0x00, 0xd8, 0x2f, 0x41, 0x00, +0x00, 0x01, 0x00, 0x00, 0x04, 0x20, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x20, 0x41, 0x00, +0x00, 0x00, 0x03, 0x00, 0x0c, 0x20, 0x41, 0x00, 0x0a, 0x03, 0x00, 0x03, 0x2c, 0x21, 0x41, 0x00, +0x01, 0x80, 0xde, 0x0f, 0x00, 0x23, 0x41, 0x00, 0x00, 0x14, 0x00, 0x00, 0x04, 0x23, 0x41, 0x00, +0x01, 0x00, 0x00, 0x00, 0x08, 0x23, 0x41, 0x00, 0x14, 0x14, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x44, 0x95, 0xe7, 0x15, 0x14, 0x23, 0x41, 0x00, 0x44, 0x95, 0xe7, 0x15, 0x18, 0x23, 0x41, 0x00, +0x40, 0x40, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5e, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5e, 0x36, 0x18, 0x30, 0x23, 0x41, 0x00, 0xf3, 0x00, 0x05, 0x05, 0x34, 0x23, 0x41, 0x00, +0x08, 0x04, 0x0a, 0x04, 0x38, 0x23, 0x41, 0x00, 0x38, 0x20, 0x0f, 0x11, 0x5c, 0x23, 0x41, 0x00, +0x2c, 0x27, 0x00, 0x00, 0x64, 0x23, 0x41, 0x00, 0x00, 0x00, 0x00, 0x80, 0x68, 0x23, 0x41, 0x00, +0x05, 0x20, 0x7c, 0x00, 0x6c, 0x23, 0x41, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, 0x23, 0x41, 0x00, +0x00, 0x08, 0x00, 0x00, 0x78, 0x23, 0x41, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, +0xe3, 0x0f, 0x00, 0x00, 0x84, 0x23, 0x41, 0x00, 0x70, 0x70, 0x00, 0x00, 0x8c, 0x23, 0x41, 0x00, +0x16, 0x15, 0x11, 0x11, 0x9c, 0x23, 0x41, 0x00, 0x45, 0x3e, 0x38, 0x38, 0xa4, 0x23, 0x41, 0x00, +0x2e, 0x2a, 0x2a, 0x2a, 0xac, 0x23, 0x41, 0x00, 0x30, 0x2b, 0x26, 0x26, 0xcc, 0x23, 0x41, 0x00, +0x1c, 0x1c, 0x16, 0x16, 0xd4, 0x23, 0x41, 0x00, 0x2f, 0x2a, 0x26, 0x26, 0xdc, 0x23, 0x41, 0x00, +0x66, 0x54, 0x40, 0x40, 0xec, 0x23, 0x41, 0x00, 0x96, 0x0e, 0xa2, 0xba, 0x00, 0x24, 0x41, 0x00, +0x03, 0x04, 0xe9, 0x02, 0x08, 0x24, 0x41, 0x00, 0xaa, 0x55, 0x00, 0x00, 0x04, 0x25, 0x41, 0x00, +0x3a, 0x00, 0x00, 0x00, 0x14, 0x25, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x25, 0x41, 0x00, +0x80, 0x00, 0x00, 0x00, 0x00, 0x26, 0x41, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x26, 0x41, 0x00, +0x0b, 0x06, 0x06, 0x00, 0x0c, 0x26, 0x41, 0x00, 0x07, 0x00, 0x10, 0x00, 0x10, 0x26, 0x41, 0x00, +0x07, 0x00, 0x00, 0x00, 0x14, 0x26, 0x41, 0x00, 0xf4, 0x03, 0xc0, 0x00, 0x18, 0x26, 0x41, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x26, 0x41, 0x00, +0x73, 0x77, 0x77, 0x00, 0x00, 0x27, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x27, 0x41, 0x00, +0x00, 0x00, 0x04, 0x01, 0x10, 0x27, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x27, 0x41, 0x00, +0x00, 0x00, 0x00, 0x00, 0x20, 0x27, 0x41, 0x00, 0x14, 0x00, 0x00, 0x80, 0x40, 0x27, 0x41, 0x00, +0x04, 0x00, 0x00, 0x00, 0x04, 0x25, 0x41, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x25, 0x41, 0x00, +0xec, 0xc4, 0x77, 0xf9, 0x00, 0x28, 0x41, 0x00, 0xe0, 0x00, 0x50, 0x3d, 0x34, 0x29, 0x41, 0x00, +0x92, 0x04, 0x00, 0x00, 0x38, 0x29, 0x41, 0x00, 0x11, 0x04, 0x56, 0x00, 0x3c, 0x29, 0x41, 0x00, +0x1c, 0x1b, 0xf2, 0xc8, 0x40, 0x29, 0x41, 0x00, 0x1e, 0x58, 0x00, 0x00, 0x44, 0x29, 0x41, 0x00, +0x20, 0x40, 0x07, 0x00, 0x48, 0x29, 0x41, 0x00, 0x91, 0xa9, 0x00, 0xc0, 0x4c, 0x29, 0x41, 0x00, +0xf9, 0x9f, 0xff, 0xb9, 0x50, 0x29, 0x41, 0x00, 0x6f, 0x00, 0x40, 0x26, 0x60, 0x29, 0x41, 0x00, +0x16, 0x00, 0x00, 0x00, 0x64, 0x29, 0x41, 0x00, 0x30, 0xf0, 0x8f, 0x89, 0x88, 0x29, 0x41, 0x00, +0x44, 0x44, 0x01, 0x00, 0x94, 0x29, 0x41, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xac, 0x29, 0x41, 0x00, +0x00, 0x44, 0x00, 0x00, 0xd4, 0x29, 0x41, 0x00, 0x00, 0x8a, 0x00, 0x00, 0xf0, 0x29, 0x41, 0x00, +0x00, 0x00, 0x02, 0x00, 0x50, 0x2c, 0x41, 0x00, 0x03, 0x00, 0x00, 0x00, 0xc4, 0x2c, 0x41, 0x00, +0x07, 0x4f, 0x03, 0x00, 0x08, 0x23, 0x41, 0x00, 0x18, 0x18, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, +0x4f, 0x9d, 0xe8, 0x15, 0x14, 0x23, 0x41, 0x00, 0x4f, 0x9d, 0xe8, 0x15, 0x18, 0x23, 0x41, 0x00, +0x04, 0x04, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5c, 0x36, 0x18, 0x38, 0x23, 0x41, 0x00, 0x38, 0x02, 0x0f, 0x11, 0x78, 0x23, 0x41, 0x00, +0x02, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, 0xf3, 0x0f, 0x00, 0x00, 0x84, 0x23, 0x41, 0x00, +0x78, 0x78, 0x00, 0x00, 0x8c, 0x23, 0x41, 0x00, 0x16, 0x11, 0x11, 0x11, 0xcc, 0x23, 0x41, 0x00, +0xff, 0xff, 0xff, 0xff, 0xd4, 0x23, 0x41, 0x00, 0xff, 0xff, 0xff, 0xff, 0xdc, 0x23, 0x41, 0x00, +0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, 0x41, 0x00, +0x3a, 0x00, 0x00, 0x00, 0x14, 0x25, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x26, 0x41, 0x00, +0x08, 0x00, 0x04, 0x00, 0x10, 0x26, 0x41, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x26, 0x41, 0x00, +0x70, 0x00, 0x00, 0x00, 0x44, 0x29, 0x41, 0x00, 0x21, 0x40, 0x07, 0x00, 0xd4, 0x29, 0x41, 0x00, +0x00, 0x0a, 0x00, 0x00, 0x10, 0x27, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x28, 0x41, 0x00, +0xe0, 0x00, 0x50, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x88, 0x90, 0x98, 0x9a, 0x9c, 0x9e, 0xb8, 0xba, 0xbc, 0xbe, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, +0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x00, 0xa8, 0xa8, 0x88, 0x00, 0xa0, 0xa0, 0x99, 0x00, +0x98, 0x98, 0xaa, 0x00, 0x90, 0x90, 0xbb, 0x00, 0x8b, 0x8b, 0xbb, 0x00, 0x87, 0x87, 0xbb, 0x00, +0x06, 0x06, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x27, 0x00, 0x25, 0x00, 0x65, 0x00, 0xe5, 0x00, +0xe5, 0x00, 0xe5, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, +0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x05, 0x07, 0x06, 0x00, +0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, 0x00, +0x0e, 0x0e, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0d, 0x0c, 0x08, 0x07, 0x06, 0x00, 0x00, +0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x06, 0x08, 0x07, 0x00, 0x00, +0x01, 0x01, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, +0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, +0x0a, 0x0a, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, +0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, +0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, +0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x07, 0x06, 0x00, 0x0b, 0x0a, 0x09, 0x08, +0x07, 0x06, 0x00, 0x00, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x0c, 0x0b, 0x0a, 0x09, +0x08, 0x07, 0x06, 0x05, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x20, 0x00, 0x54, 0x75, 0x72, 0x6e, +0x20, 0x6f, 0x6e, 0x20, 0x54, 0x44, 0x44, 0x2e, 0x2e, 0x2e, 0x0a, 0x00, 0x54, 0x75, 0x72, 0x6e, +0x20, 0x6f, 0x66, 0x66, 0x20, 0x54, 0x44, 0x44, 0x2e, 0x2e, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x48, 0x57, 0x20, 0x41, 0x55, 0x54, 0x4f, 0x20, 0x4d, 0x4f, 0x44, 0x45, 0x20, 0x66, 0x61, 0x69, +0x6c, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, +0x28, 0x25, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x21, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x48, 0x57, 0x20, 0x41, 0x55, 0x54, 0x4f, 0x20, 0x4d, 0x4f, 0x44, 0x45, +0x20, 0x66, 0x61, 0x69, 0x6c, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x72, +0x65, 0x61, 0x72, 0x28, 0x25, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, +0x79, 0x21, 0x0a, 0x00, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x48, 0x57, 0x20, 0x61, +0x75, 0x74, 0x6f, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, 0x5b, 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5d, +0x20, 0x50, 0x46, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x68, 0x6f, 0x73, 0x74, +0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x29, 0x2e, 0x0a, 0x00, 0x00, 0x00, +0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x48, 0x57, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, +0x6b, 0x69, 0x63, 0x6b, 0x20, 0x5b, 0x52, 0x45, 0x41, 0x52, 0x5d, 0x20, 0x50, 0x46, 0x20, 0x66, +0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, +0x72, 0x65, 0x61, 0x64, 0x79, 0x29, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x54, 0x72, 0x69, 0x67, +0x67, 0x65, 0x72, 0x5b, 0x25, 0x64, 0x5d, 0x2c, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x75, +0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x50, 0x46, 0x0a, 0x00, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x63, +0x65, 0x6c, 0x5b, 0x25, 0x64, 0x5d, 0x3a, 0x20, 0x20, 0x50, 0x46, 0x28, 0x25, 0x64, 0x29, 0x20, +0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x2e, 0x2e, +0x0a, 0x00, 0x00, 0x00, 0x43, 0x46, 0x2d, 0x45, 0x6e, 0x64, 0x00, 0x00, 0x50, 0x53, 0x31, 0x00, +0x50, 0x53, 0x30, 0x00, 0x43, 0x54, 0x53, 0x00, 0x20, 0x49, 0x4e, 0x46, 0x5b, 0x25, 0x64, 0x5d, +0x3a, 0x20, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x6d, +0x6f, 0x64, 0x65, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x74, +0x79, 0x70, 0x65, 0x3a, 0x20, 0x25, 0x73, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, +0x20, 0x70, 0x66, 0x20, 0x28, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x63, 0x75, +0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x74, 0x73, 0x20, 0x28, 0x25, 0x64, 0x2c, 0x20, 0x25, +0x64, 0x29, 0x0a, 0x00, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x48, 0x57, 0x20, 0x61, 0x75, +0x74, 0x6f, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, 0x5b, 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5d, 0x20, +0x50, 0x46, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2e, 0x0a, 0x00, 0x55, 0x70, 0x64, 0x61, +0x74, 0x65, 0x20, 0x48, 0x57, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, +0x5b, 0x52, 0x45, 0x41, 0x52, 0x5d, 0x20, 0x50, 0x46, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, +0x2e, 0x0a, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x57, 0x69, 0x66, 0x69, 0x20, +0x41, 0x46, 0x48, 0x20, 0x5b, 0x25, 0x64, 0x5d, 0x3a, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, +0x6c, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x62, 0x77, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x6c, +0x69, 0x6e, 0x6b, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, +0x74, 0x65, 0x20, 0x43, 0x48, 0x20, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x78, 0x20, 0x63, 0x6f, 0x6e, +0x66, 0x69, 0x67, 0x20, 0x6d, 0x73, 0x67, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x00, +0x25, 0x73, 0x3a, 0x20, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72, 0x69, 0x67, +0x67, 0x65, 0x72, 0x20, 0x6e, 0x75, 0x6d, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, +0x20, 0x57, 0x46, 0x20, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x20, 0x73, 0x74, +0x6f, 0x70, 0x65, 0x64, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00, 0x00, 0x57, 0x69, 0x46, 0x69, +0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x20, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, +0x67, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x21, 0x0a, 0x00, 0x00, 0x00, +0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x57, 0x49, 0x46, 0x49, 0x20, 0x73, 0x74, 0x61, +0x74, 0x75, 0x73, 0x3a, 0x20, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x28, 0x30, 0x78, 0x25, 0x78, +0x29, 0x0a, 0x00, 0x00, 0x57, 0x4c, 0x3d, 0x3e, 0x57, 0x4d, 0x54, 0x3a, 0x20, 0x30, 0x78, 0x25, +0x78, 0x0a, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x57, +0x46, 0x20, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, +0x0a, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x77, 0x69, 0x66, 0x69, +0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x29, 0x0a, 0x00, 0x3e, 0x3e, 0x3e, 0x20, +0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x57, 0x69, 0x66, 0x69, 0x20, 0x42, 0x53, 0x53, 0x5b, +0x25, 0x64, 0x5d, 0x3a, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5b, 0x30, 0x78, 0x25, 0x78, +0x5d, 0x0a, 0x00, 0x00, 0x53, 0x65, 0x74, 0x20, 0x69, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x5b, +0x25, 0x64, 0x5d, 0x3d, 0x31, 0x0a, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x20, 0x53, +0x63, 0x61, 0x6e, 0x5b, 0x25, 0x64, 0x5d, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x42, 0x57, 0x32, 0x30, +0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x42, 0x57, 0x34, 0x30, 0x5b, 0x25, 0x64, 0x5d, +0x0a, 0x00, 0x00, 0x00, 0x42, 0x57, 0x38, 0x30, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, +0x53, 0x43, 0x41, 0x4e, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x4f, 0x4e, 0x4e, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x25, 0x64, 0x0a, 0x00, +0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x53, 0x54, 0x41, 0x5b, 0x25, 0x64, 0x5d, +0x0a, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x41, 0x50, 0x5b, +0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, +0x20, 0x47, 0x43, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, +0x6f, 0x64, 0x65, 0x3a, 0x20, 0x47, 0x4f, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x42, 0x54, 0x33, 0x5b, 0x25, 0x64, 0x5d, +0x0a, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x41, 0x44, 0x48, +0x4f, 0x43, 0x5b, 0x25, 0x64, 0x5d, 0x0a, 0x00, 0x3d, 0x3d, 0x3d, 0x3e, 0x20, 0x66, 0x69, 0x6e, +0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x53, 0x43, 0x4f, 0x00, 0x41, 0x32, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, +0x43, 0x6f, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x48, 0x49, 0x44, 0x00, 0x50, 0x41, 0x47, 0x65, +0x00, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x49, 0x4e, 0x51, 0x52, +0x59, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x5b, 0x42, 0x54, 0x20, 0x25, 0x73, 0x5d, +0x3a, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x77, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, +0x43, 0x54, 0x53, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x25, 0x64, 0x29, 0x20, 0x3c, +0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x6e, 0x6f, 0x74, +0x69, 0x66, 0x79, 0x20, 0x54, 0x44, 0x44, 0x20, 0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x3e, 0x3e, 0x3e, 0x3e, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x20, 0x46, 0x44, 0x44, 0x20, +0x3c, 0x3c, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, +0x45, 0x52, 0x52, 0x4f, 0x52, 0x21, 0x20, 0x55, 0x44, 0x4d, 0x41, 0x20, 0x6e, 0x6f, 0x74, 0x20, +0x69, 0x64, 0x6c, 0x65, 0x21, 0x0a, 0x00, 0x00, 0x5b, 0x4d, 0x43, 0x43, 0x5d, 0x20, 0x63, 0x68, +0x5b, 0x25, 0x64, 0x5d, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x20, 0x46, 0x43, 0x45, 0x20, +0x77, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, +0x20, 0x28, 0x25, 0x64, 0x20, 0x70, 0x61, 0x67, 0x65, 0x73, 0x29, 0x2c, 0x20, 0x6f, 0x75, 0x74, +0x51, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, 0x73, 0x74, 0x61, +0x74, 0x75, 0x73, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x00, 0x5b, 0x4d, 0x43, 0x43, +0x5d, 0x20, 0x63, 0x68, 0x5b, 0x25, 0x64, 0x5d, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x21, 0x20, +0x51, 0x5b, 0x25, 0x64, 0x5d, 0x20, 0x46, 0x55, 0x4c, 0x4c, 0x20, 0x28, 0x25, 0x64, 0x20, 0x74, +0x72, 0x69, 0x65, 0x73, 0x29, 0x2c, 0x20, 0x43, 0x52, 0x5b, 0x30, 0x78, 0x25, 0x78, 0x5d, 0x3d, +0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x43, 0x52, 0x5b, 0x30, 0x78, 0x25, 0x78, 0x5d, 0x3d, 0x30, +0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20, 0x25, 0x70, 0x2c, 0x20, +0x6c, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x30, 0x78, 0x25, 0x30, +0x34, 0x78, 0x20, 0x3a, 0x20, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, +0x69, 0x64, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x45, 0x44, 0x43, +0x43, 0x41, 0x2d, 0x31, 0x37, 0x30, 0x34, 0x2c, 0x20, 0x45, 0x4e, 0x2d, 0x31, 0x33, 0x34, 0x30, +0x5d, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, +0x5b, 0x32, 0x31, 0x33, 0x30, 0x5d, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x2b, 0x2b, 0x2b, 0x20, 0x77, 0x20, 0x28, 0x25, 0x64, 0x20, 0x70, 0x6b, 0x74, 0x73, 0x29, 0x20, +0x2b, 0x2b, 0x2b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x43, 0x48, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, +0x2d, 0x25, 0x64, 0x2d, 0x5b, 0x25, 0x64, 0x5d, 0x2d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x54, 0x44, 0x4c, 0x53, +0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2c, +0x20, 0x6c, 0x65, 0x6e, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x53, 0x57, 0x20, 0x74, +0x69, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x31, 0x20, 0x28, 0x25, 0x64, 0x20, 0x3e, 0x20, 0x25, +0x64, 0x29, 0x0a, 0x00, 0x4e, 0x4f, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x20, 0x41, +0x43, 0x4b, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x25, 0x64, 0x20, 0x70, 0x6f, 0x6c, 0x6c, +0x69, 0x6e, 0x67, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x53, 0x57, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, +0x6f, 0x75, 0x74, 0x32, 0x20, 0x28, 0x25, 0x64, 0x20, 0x3e, 0x20, 0x25, 0x64, 0x29, 0x0a, 0x00, +0x73, 0x74, 0x61, 0x79, 0x28, 0x30, 0x29, 0x6d, 0x73, 0x0a, 0x00, 0x00, 0x73, 0x74, 0x61, 0x79, +0x20, 0x25, 0x64, 0x20, 0x6d, 0x73, 0x2e, 0x2e, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x67, 0x6e, 0x6f, +0x72, 0x65, 0x20, 0x42, 0x2d, 0x42, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x6f, 0x73, 0x74, +0x0a, 0x00, 0x00, 0x00, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x20, 0x54, 0x44, 0x4c, 0x53, 0x20, 0x4f, +0x50, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xac, 0x00, 0xaa, 0xaa, 0x03, 0x00, +0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, +0x88, 0x8e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x00, 0x00, 0x10, 0x23, 0x41, 0x00, 0x43, 0x94, 0xe5, 0x15, 0x14, 0x23, 0x41, 0x00, +0x43, 0x94, 0xe5, 0x15, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5e, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5e, 0x42, 0x1e, 0x34, 0x23, 0x41, 0x00, 0x08, 0x04, 0x0d, 0x04, 0x38, 0x23, 0x41, 0x00, +0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, +0x30, 0x2b, 0x26, 0x26, 0xcc, 0x23, 0x41, 0x00, 0x1c, 0x1c, 0x15, 0x15, 0x10, 0x23, 0x41, 0x00, +0x43, 0x94, 0xe5, 0x15, 0x14, 0x23, 0x41, 0x00, 0x43, 0x94, 0xe5, 0x15, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x60, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x60, 0x42, 0x1e, 0x34, 0x23, 0x41, 0x00, +0x0f, 0x04, 0x0d, 0x04, 0x38, 0x23, 0x41, 0x00, 0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, +0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, 0x30, 0x2b, 0x26, 0x26, 0xcc, 0x23, 0x41, 0x00, +0x1c, 0x1c, 0x15, 0x15, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x36, 0x18, 0x34, 0x23, 0x41, 0x00, 0x0a, 0x04, 0x0a, 0x04, 0x38, 0x23, 0x41, 0x00, +0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, +0x28, 0x23, 0x1e, 0x1e, 0xcc, 0x23, 0x41, 0x00, 0x1c, 0x1c, 0x15, 0x15, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5c, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5c, 0x36, 0x18, 0x34, 0x23, 0x41, 0x00, +0x0d, 0x08, 0x0a, 0x04, 0x38, 0x23, 0x41, 0x00, 0x38, 0x2e, 0x0f, 0x11, 0x6c, 0x23, 0x41, 0x00, +0xec, 0x00, 0x00, 0x00, 0xac, 0x23, 0x41, 0x00, 0x28, 0x23, 0x1e, 0x1e, 0xcc, 0x23, 0x41, 0x00, +0x1c, 0x1c, 0x15, 0x15, 0x20, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x42, 0x1e, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x42, 0x1e, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x42, 0x1e, 0x68, 0x23, 0x41, 0x00, +0x05, 0x20, 0x7c, 0x00, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x28, 0x24, 0x24, 0x24, 0xac, 0x23, 0x41, 0x00, 0x30, 0x2b, 0x26, 0x26, 0x20, 0x23, 0x41, 0x00, +0xf8, 0x5a, 0x36, 0x18, 0x24, 0x23, 0x41, 0x00, 0xf8, 0x5a, 0x36, 0x18, 0x34, 0x23, 0x41, 0x00, +0x0a, 0x08, 0x0a, 0x04, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, +0xf3, 0x0f, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x21, 0x1d, 0x1d, 0x1d, 0xac, 0x23, 0x41, 0x00, +0x28, 0x23, 0x1e, 0x1e, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x68, 0x23, 0x41, 0x00, +0x06, 0x20, 0x7c, 0x00, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, +0x32, 0x2e, 0x2e, 0x2e, 0xac, 0x23, 0x41, 0x00, 0x2a, 0x1c, 0x20, 0x20, 0x34, 0x23, 0x41, 0x00, +0x0b, 0x08, 0x0a, 0x04, 0x6c, 0x23, 0x41, 0x00, 0xec, 0x00, 0x00, 0x00, 0x7c, 0x23, 0x41, 0x00, +0xd3, 0x0f, 0x00, 0x00, 0xa4, 0x23, 0x41, 0x00, 0x21, 0x1d, 0x1d, 0x1d, 0xac, 0x23, 0x41, 0x00, +0x30, 0x2b, 0x26, 0x26, 0x09, 0x00, 0x54, 0x00, 0x00, 0x3a, 0x7a, 0x29, 0x09, 0x00, 0x58, 0x00, +0x00, 0x60, 0x6c, 0x22, 0x09, 0x00, 0x94, 0x02, 0xe3, 0x03, 0xe1, 0x03, 0x09, 0x00, 0x98, 0x02, +0x00, 0x03, 0x03, 0x03, 0x09, 0x00, 0x9c, 0x02, 0x10, 0x1f, 0x1f, 0x2e, 0x09, 0x00, 0x7c, 0x02, +0x27, 0x00, 0x25, 0x00, 0x09, 0x00, 0x80, 0x02, 0x24, 0x00, 0x67, 0x00, 0x09, 0x00, 0x84, 0x02, +0x65, 0x00, 0x64, 0x00, 0x09, 0x00, 0x88, 0x02, 0xe7, 0x00, 0xe5, 0x00, 0x09, 0x00, 0x8c, 0x02, +0xe4, 0x00, 0xe7, 0x03, 0x09, 0x00, 0x90, 0x02, 0xe5, 0x03, 0xe4, 0x03, 0x09, 0x00, 0x3c, 0x00, +0xc5, 0x59, 0xb5, 0x05, 0x09, 0x00, 0xa0, 0x02, 0x14, 0x14, 0x1a, 0xdc, 0x00, 0x00, 0xa4, 0x02, +0x7f, 0x47, 0x20, 0x20, 0x01, 0x00, 0xa4, 0x02, 0x7f, 0x47, 0x20, 0x20, 0x09, 0x00, 0xa8, 0x02, +0x28, 0xee, 0x0e, 0x00, 0x09, 0x00, 0x5c, 0x00, 0xa1, 0x0a, 0xb4, 0x14, 0x09, 0x00, 0x44, 0x00, +0x16, 0x20, 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x5f, 0x00, 0x00, 0x00, 0x62, 0xe3, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x05, 0xff, +0xff, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662t_rom_patch.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662t_rom_patch.h new file mode 100644 index 000000000..af66c5933 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mcu/mt7662t_rom_patch.h @@ -0,0 +1,5711 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR mt7662t_rom_patch[] = { +0x32, 0x30, 0x31, 0x36, 0x30, 0x31, 0x31, 0x35, 0x31, 0x35, 0x34, 0x31, 0x35, 0x39, 0x61, 0x0a, +0x41, 0x4c, 0x50, 0x53, 0x8a, 0x10, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x8b, 0xfe, 0xff, 0xff, +0xff, 0xe7, 0xff, 0x0f, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x00, 0x68, 0x22, 0x00, 0x00, 0x90, 0xb1, +0x03, 0x00, 0x14, 0x78, 0x00, 0x00, 0xb8, 0xac, 0x02, 0x00, 0x34, 0xcd, 0x03, 0x00, 0xdc, 0x2e, +0x00, 0x00, 0xfc, 0x1d, 0x03, 0x00, 0xc8, 0xb3, 0x02, 0x00, 0x20, 0x98, 0x02, 0x00, 0xac, 0x92, +0x02, 0x00, 0x60, 0x92, 0x02, 0x00, 0xac, 0x93, 0x02, 0x00, 0x00, 0xe9, 0x02, 0x00, 0xf0, 0x01, +0x01, 0x00, 0x24, 0x32, 0x01, 0x00, 0x58, 0x44, 0x03, 0x00, 0xe4, 0xe7, 0x02, 0x00, 0xc0, 0x51, +0x03, 0x00, 0x24, 0x2d, 0x03, 0x00, 0x38, 0xad, 0x01, 0x00, 0x20, 0x09, 0x02, 0x00, 0xc8, 0x52, +0x02, 0x00, 0x98, 0x31, 0x01, 0x00, 0x60, 0xe7, 0x00, 0x00, 0x00, 0x96, 0x03, 0x00, 0x7c, 0x21, +0x03, 0x00, 0x84, 0x02, 0x02, 0x00, 0x68, 0xf8, 0x02, 0x00, 0x7c, 0x78, 0x05, 0x00, 0x68, 0x0c, +0x02, 0x00, 0xa0, 0xc4, 0x01, 0x00, 0x30, 0xd4, 0x00, 0x00, 0x88, 0x96, 0x00, 0x00, 0x90, 0x3e, +0x00, 0x00, 0x58, 0x74, 0x01, 0x00, 0x30, 0x42, 0x01, 0x00, 0x64, 0x60, 0x02, 0x00, 0x20, 0x85, +0x01, 0x00, 0x5c, 0x09, 0x04, 0x00, 0xf4, 0x0f, 0x04, 0x00, 0x60, 0xd6, 0x03, 0x00, 0x34, 0x3f, +0x03, 0x00, 0xf4, 0x74, 0x03, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xc3, 0x0b, 0x00, 0x80, 0x75, 0x0c, 0x00, 0x7c, 0x74, +0x0c, 0x00, 0x28, 0x74, 0x0c, 0x00, 0xd8, 0xc4, 0x0b, 0x00, 0xf0, 0x73, 0x0c, 0x00, 0x64, 0x73, +0x0c, 0x00, 0x48, 0x7d, 0x0c, 0x00, 0x18, 0x49, 0x0c, 0x00, 0x00, 0x3e, 0x0c, 0x00, 0x5c, 0xcb, +0x0b, 0x00, 0x00, 0xcc, 0x0b, 0x00, 0xd8, 0x3b, 0x0c, 0x00, 0x7c, 0x3c, 0x0c, 0x00, 0x28, 0x34, +0x0c, 0x00, 0x10, 0x71, 0x0c, 0x00, 0x70, 0x17, 0x0c, 0x00, 0x94, 0x70, 0x0c, 0x00, 0x30, 0x70, +0x0c, 0x00, 0x78, 0x88, 0x0c, 0x00, 0xac, 0x29, 0x0c, 0x00, 0x30, 0xeb, 0x0b, 0x00, 0x78, 0x23, +0x0c, 0x00, 0x64, 0x22, 0x0c, 0x00, 0x34, 0x63, 0x0c, 0x00, 0xb4, 0x1e, 0x0c, 0x00, 0x84, 0x18, +0x0c, 0x00, 0x68, 0x41, 0x0c, 0x00, 0xc0, 0xf0, 0x0b, 0x00, 0x8c, 0x04, 0x0c, 0x00, 0x58, 0xf1, +0x0b, 0x00, 0xe8, 0xef, 0x0b, 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x28, 0xae, 0x0c, 0x00, 0xa0, 0xa5, +0x0c, 0x00, 0xb4, 0xe3, 0x0b, 0x00, 0x60, 0xe3, 0x0b, 0x00, 0xfc, 0xde, 0x0b, 0x00, 0xf8, 0xdb, +0x0b, 0x00, 0x50, 0xd9, 0x0b, 0x00, 0xd0, 0x7c, 0x0c, 0x00, 0xe8, 0xd8, 0x0b, 0x00, 0x04, 0x8a, +0x0c, 0x00, 0x1c, 0xd1, 0x0b, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x84, 0xa7, 0x51, 0xa7, 0x12, 0xa6, 0xd3, 0x40, 0x52, +0xa0, 0x08, 0x40, 0x22, 0x40, 0x08, 0xa7, 0x04, 0x98, 0xaa, 0x98, 0x94, 0x40, 0x31, 0xe0, 0x08, +0x98, 0x93, 0x94, 0x96, 0x92, 0x48, 0x94, 0x92, 0x40, 0x31, 0x48, 0x09, 0x40, 0x41, 0x08, 0x09, +0x92, 0x4a, 0xaf, 0x08, 0xae, 0x89, 0xae, 0xca, 0x00, 0x20, 0x00, 0x08, 0xae, 0x8b, 0x00, 0x30, +0x00, 0x0a, 0x00, 0x20, 0x00, 0x09, 0x40, 0x01, 0xa0, 0x08, 0x98, 0x02, 0x96, 0x01, 0x40, 0x20, +0x20, 0x09, 0xae, 0x8d, 0xae, 0x0c, 0xdd, 0x9e, 0x92, 0x00, 0x08, 0x20, 0x00, 0x01, 0x18, 0x20, +0x80, 0x01, 0x08, 0x20, 0x00, 0x01, 0x18, 0x20, 0x80, 0x01, 0x08, 0x20, 0x00, 0x01, 0x18, 0x20, +0x80, 0x01, 0x08, 0x20, 0x00, 0x01, 0x18, 0x20, 0x80, 0x01, 0xa6, 0x80, 0xae, 0x88, 0xa6, 0x01, +0xae, 0x09, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x80, 0xa0, 0x8c, 0x94, 0x06, 0x42, 0x21, +0x18, 0x09, 0x54, 0x00, 0x00, 0x40, 0x40, 0x00, 0x08, 0x04, 0xa8, 0x0c, 0xdd, 0x9e, 0x46, 0x10, +0x04, 0x90, 0x46, 0x30, 0x00, 0xf0, 0x40, 0x00, 0x40, 0x08, 0xa0, 0x8e, 0x40, 0x00, 0x0c, 0x02, +0x46, 0x3f, 0xff, 0x0f, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x00, 0x08, 0x04, +0xa8, 0x0e, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x49, 0x40, 0x20, 0xa0, 0x09, 0xae, 0x81, 0xae, 0x40, +0xdd, 0x9e, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x08, 0x00, 0x46, 0x10, 0x00, 0xd2, 0x58, 0x10, +0x82, 0x74, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x0a, 0x00, 0xd5, 0x03, 0xa2, 0xc9, 0xaa, 0xc1, +0xe2, 0x02, 0xe9, 0xfd, 0xdd, 0x9e, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x00, 0x46, 0x20, +0x01, 0x4e, 0x58, 0x21, 0x02, 0x5c, 0x84, 0x20, 0xd5, 0x02, 0xaa, 0x41, 0xe2, 0x02, 0xe9, 0xfe, +0xdd, 0x9e, 0x84, 0x23, 0x42, 0x00, 0x04, 0x24, 0x84, 0x20, 0xd5, 0x08, 0x84, 0x40, 0x92, 0x00, +0x84, 0x67, 0x9c, 0x91, 0x4c, 0x21, 0xff, 0xfd, 0x9c, 0x49, 0xe2, 0x20, 0xe9, 0xf8, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0xd4, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0xf8, 0xdd, 0x2f, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, +0x80, 0x82, 0x80, 0x01, 0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x80, 0x82, 0x04, 0x10, 0x00, 0x0e, +0x84, 0xa1, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x08, 0x04, 0x00, 0x00, 0x0e, 0x84, 0xa2, +0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd8, 0x09, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x02, 0x42, +0x42, 0x10, 0xb4, 0x09, 0x14, 0x10, 0x02, 0x42, 0x46, 0x00, 0x04, 0x00, 0xb4, 0x20, 0x44, 0x3f, +0x00, 0x00, 0x46, 0x27, 0x66, 0x20, 0x40, 0x50, 0x8c, 0x02, 0xd2, 0x07, 0xb4, 0x00, 0x40, 0x50, +0x0c, 0x02, 0x46, 0x37, 0x63, 0x20, 0xdb, 0x54, 0x46, 0x10, 0x00, 0xc7, 0x58, 0x10, 0x89, 0xec, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x80, 0x55, 0x46, 0x10, 0x00, 0xc7, 0x58, 0x10, 0x88, 0xd8, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x80, 0x42, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x48, +0xb4, 0x20, 0x46, 0x2f, 0xf8, 0x0f, 0x46, 0x30, 0x05, 0xf0, 0x40, 0x10, 0x88, 0x02, 0x58, 0x31, +0x80, 0x02, 0x40, 0x10, 0x8c, 0x04, 0xb6, 0x20, 0x81, 0x00, 0x84, 0xc0, 0x46, 0x70, 0x00, 0xbc, +0x58, 0x73, 0x83, 0x14, 0xb4, 0x08, 0x9d, 0xb1, 0x40, 0x10, 0x30, 0x09, 0x40, 0x20, 0x70, 0x09, +0x54, 0x10, 0x80, 0x03, 0x84, 0x0a, 0xca, 0x02, 0xc1, 0x06, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x50, +0x00, 0x64, 0xde, 0xf1, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, 0x80, 0x52, 0x92, 0x4c, 0x40, 0x21, +0x30, 0x08, 0x14, 0x20, 0x80, 0x52, 0x80, 0x01, 0x04, 0x20, 0x00, 0x20, 0x42, 0x21, 0x00, 0x09, +0x14, 0x20, 0x00, 0x20, 0x80, 0x20, 0x04, 0x20, 0x80, 0x19, 0x42, 0x21, 0x48, 0x08, 0x14, 0x20, +0x80, 0x19, 0x04, 0x10, 0x00, 0x83, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x00, 0x83, 0x46, 0x10, +0x00, 0xc7, 0x58, 0x10, 0x86, 0x40, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x80, 0x52, 0x46, 0x10, +0x00, 0xc5, 0x58, 0x10, 0x80, 0x54, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x17, 0x81, 0x4b, 0x46, 0x10, +0x04, 0x05, 0x04, 0x20, 0x81, 0xf2, 0x84, 0x00, 0x42, 0x21, 0x48, 0x08, 0x14, 0x20, 0x81, 0xf2, +0x46, 0x20, 0x00, 0xc0, 0x58, 0x21, 0x03, 0xd8, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x80, 0x90, +0x46, 0x20, 0x00, 0xc3, 0x58, 0x21, 0x0b, 0x68, 0x46, 0xf0, 0x01, 0x03, 0x14, 0x27, 0x83, 0xce, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xea, 0x46, 0x20, 0x00, 0xc2, 0x58, 0x21, 0x0a, 0xc0, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x80, 0x6c, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x07, 0x82, 0x38, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xeb, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xec, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x17, +0x84, 0x98, 0x80, 0xc0, 0xc1, 0x3b, 0x04, 0x00, 0x00, 0x0a, 0x84, 0x2a, 0xa0, 0x07, 0x4c, 0x00, +0x80, 0x31, 0x00, 0x13, 0x00, 0x22, 0x84, 0xa1, 0xd1, 0x03, 0x84, 0xa9, 0xd0, 0x2a, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x07, 0x80, 0x3f, 0xdd, 0x20, 0x80, 0x20, 0x20, 0x03, 0x00, 0x23, 0x98, 0xc0, +0x98, 0xd8, 0x98, 0xd9, 0xe0, 0x01, 0xe8, 0x03, 0x84, 0x41, 0xd5, 0x0a, 0x40, 0x00, 0x80, 0x07, +0x84, 0x80, 0x44, 0x50, 0x00, 0xff, 0x40, 0x22, 0x80, 0x1b, 0x40, 0x22, 0x00, 0x1a, 0x40, 0x01, +0x88, 0x0a, 0x42, 0x31, 0x84, 0x0b, 0x98, 0xd8, 0x98, 0x93, 0x96, 0x92, 0x10, 0x23, 0x00, 0x23, +0x10, 0x13, 0x00, 0x24, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x71, 0x80, 0x06, 0xdd, 0x22, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x17, 0x84, 0x98, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x96, 0x40, 0xe6, 0x2b, 0xe9, 0x02, 0x84, 0x0a, 0x96, 0x00, 0x8c, 0x15, 0x92, 0x02, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x88, 0x5e, 0xdd, 0x9e, 0x96, 0x40, 0xe6, 0x28, 0xe9, 0x02, +0x84, 0x07, 0x96, 0x00, 0x8c, 0x18, 0x92, 0x02, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, +0x50, 0x3f, 0x80, 0x0c, 0x3a, 0x01, 0x88, 0x20, 0x84, 0xc0, 0x46, 0x20, 0x00, 0xbc, 0x58, 0x21, +0x05, 0x64, 0x00, 0xa1, 0x80, 0x01, 0xa7, 0xda, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x88, 0x48, +0xf1, 0x81, 0xf2, 0x82, 0x80, 0x07, 0xdd, 0x22, 0x50, 0x83, 0x00, 0x01, 0x46, 0x30, 0x01, 0x38, +0x58, 0x31, 0x88, 0x40, 0x38, 0x41, 0x80, 0x00, 0x40, 0x94, 0x08, 0x08, 0x46, 0x00, 0x01, 0x00, +0x58, 0x00, 0x09, 0x28, 0x98, 0xf0, 0x8f, 0x21, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x08, 0x20, +0x9b, 0x3c, 0x40, 0x54, 0x80, 0x00, 0x38, 0x52, 0x90, 0x00, 0x80, 0x0a, 0xaf, 0x58, 0x46, 0xf0, +0x00, 0xbc, 0x58, 0xf7, 0x85, 0x7c, 0xdd, 0x2f, 0xf1, 0x01, 0x46, 0x40, 0x01, 0x00, 0x58, 0x42, +0x09, 0x38, 0x38, 0x30, 0x80, 0x00, 0x83, 0x80, 0x98, 0x34, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, +0x08, 0x00, 0x40, 0x35, 0x0c, 0x01, 0x89, 0x24, 0x38, 0x94, 0x8c, 0x00, 0x80, 0xc8, 0x10, 0x90, +0x00, 0x00, 0x84, 0xa8, 0xf2, 0x02, 0x4c, 0x82, 0xff, 0xc5, 0x46, 0x60, 0x01, 0x00, 0x58, 0x63, +0x09, 0x39, 0x46, 0x90, 0x01, 0x38, 0x58, 0x94, 0x88, 0x51, 0x46, 0x80, 0x01, 0x00, 0x58, 0x84, +0x09, 0x40, 0x46, 0x10, 0x00, 0xbc, 0x58, 0x10, 0x85, 0x64, 0xf1, 0x81, 0x80, 0x07, 0xdd, 0x21, +0xf1, 0x01, 0x4c, 0x0e, 0x00, 0x0a, 0xa6, 0xf0, 0x00, 0x44, 0x80, 0x00, 0x10, 0x33, 0x7f, 0xff, +0x10, 0x44, 0x00, 0x00, 0xd5, 0x05, 0x00, 0x04, 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, 0x9d, 0xb1, +0x46, 0x50, 0x01, 0x00, 0x58, 0x52, 0x89, 0x40, 0x8d, 0x21, 0x8d, 0x01, 0xde, 0xe7, 0x80, 0x07, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x85, 0x64, 0xdd, 0x2f, 0x80, 0xc0, 0x80, 0x0a, 0x46, 0xf0, +0x00, 0xbc, 0x58, 0xf7, 0x85, 0x7c, 0xdd, 0x2f, 0x4c, 0x60, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x17, 0x88, 0x1f, 0x46, 0xf0, 0x01, 0x00, 0x10, 0x17, 0x89, 0x3f, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x17, 0x88, 0x57, 0x46, 0xf0, 0x01, 0x00, 0x10, 0x17, 0x89, 0x47, 0xec, 0x1c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, +0x88, 0x58, 0xa6, 0x88, 0x96, 0x00, 0x4c, 0x20, 0x00, 0x63, 0x44, 0x50, 0x00, 0xff, 0xae, 0x08, +0xd0, 0x1e, 0x54, 0x20, 0x00, 0x0c, 0x40, 0x40, 0x10, 0x09, 0x92, 0x42, 0xa6, 0xcd, 0x54, 0x00, +0x00, 0x03, 0x99, 0x54, 0x10, 0x00, 0x80, 0x08, 0xaf, 0x0a, 0xae, 0x8b, 0xe0, 0x65, 0xe8, 0x03, +0x9a, 0x9a, 0xae, 0x8a, 0x80, 0x01, 0xa6, 0x44, 0xa6, 0xc3, 0xa6, 0x82, 0x9b, 0x0b, 0xe0, 0x44, +0xe8, 0x03, 0x84, 0x20, 0xd5, 0x03, 0x98, 0x9a, 0x9a, 0x51, 0xae, 0x41, 0x46, 0x60, 0x01, 0x38, +0x58, 0x63, 0x08, 0x58, 0xa6, 0x32, 0x46, 0x80, 0x00, 0xbc, 0x58, 0x84, 0x05, 0x64, 0x4b, 0xe0, +0x20, 0x01, 0x00, 0x13, 0x00, 0x08, 0xae, 0x36, 0x9a, 0x01, 0xae, 0x37, 0x3a, 0x03, 0x08, 0x00, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x85, 0x8c, 0xdd, 0x2f, 0xa7, 0xf2, 0x46, 0xf0, 0x01, 0x01, +0x10, 0x77, 0x85, 0xdd, 0x80, 0x07, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x47, +0x84, 0xb6, 0x44, 0x10, 0x00, 0x30, 0x42, 0x42, 0x04, 0x24, 0x94, 0x02, 0xa6, 0xf6, 0xa6, 0xb7, +0x9b, 0xf8, 0x46, 0x00, 0x01, 0x09, 0x58, 0x00, 0x07, 0xcc, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, +0x87, 0x14, 0x99, 0x20, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x77, 0x85, 0xde, 0x10, 0x22, 0x00, 0x25, +0x10, 0x30, 0x80, 0xcd, 0x10, 0x30, 0x80, 0xc9, 0x10, 0x20, 0x81, 0x51, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x80, 0xc1, 0x44, 0x10, 0x00, 0x41, 0xa6, 0x00, +0xae, 0x70, 0x9c, 0x49, 0xae, 0x72, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x17, 0x86, 0x06, 0x54, 0x81, +0x00, 0xff, 0x84, 0xa1, 0xd9, 0x0c, 0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x89, 0x38, 0x38, 0x70, +0x80, 0x00, 0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x89, 0x40, 0xd5, 0x0b, 0x46, 0x10, 0x01, 0x00, +0x58, 0x10, 0x89, 0x28, 0x38, 0x70, 0x80, 0x00, 0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x89, 0x30, +0x38, 0x10, 0x80, 0x00, 0xae, 0x73, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x80, 0x53, 0x50, 0x0f, +0x80, 0x04, 0xdd, 0x21, 0xc8, 0x04, 0x44, 0x00, 0x00, 0x19, 0xf0, 0x81, 0xf1, 0x01, 0x46, 0xf0, +0x01, 0x01, 0x20, 0x07, 0x86, 0x12, 0x46, 0x20, 0x01, 0x00, 0x58, 0x21, 0x09, 0x48, 0x38, 0x21, +0x1c, 0x00, 0x98, 0x01, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x27, 0x86, 0x13, 0xf0, 0x81, 0x5e, 0xf0, +0x7f, 0xd8, 0xe8, 0x04, 0x44, 0x0f, 0xff, 0xd8, 0xd5, 0x06, 0x5e, 0xf0, 0x00, 0x52, 0xe9, 0x04, +0x44, 0x00, 0x00, 0x51, 0xf0, 0x81, 0xf0, 0x01, 0x50, 0x00, 0x00, 0x2f, 0x90, 0x03, 0x96, 0x00, +0x46, 0x40, 0x01, 0x00, 0x58, 0x42, 0x09, 0x84, 0x46, 0x30, 0x01, 0x00, 0x58, 0x31, 0x89, 0x98, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8e, 0xc1, 0x38, 0x31, 0x80, 0x10, 0x38, 0x02, 0x00, 0x10, +0x46, 0xf0, 0x01, 0x01, 0x00, 0x47, 0x86, 0x15, 0xe2, 0x48, 0xe8, 0x03, 0x84, 0x42, 0xd5, 0x07, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8e, 0xc0, 0x40, 0x21, 0x20, 0x06, 0x46, 0x10, 0x01, 0x14, +0x58, 0x10, 0x8a, 0x38, 0x38, 0x20, 0x88, 0x00, 0x98, 0x63, 0x98, 0x4a, 0x96, 0x4a, 0x44, 0x20, +0x00, 0x18, 0x42, 0x10, 0x88, 0x01, 0x99, 0xf8, 0x9c, 0x94, 0x84, 0x00, 0x42, 0x73, 0x88, 0x01, +0x42, 0x10, 0x80, 0x00, 0x46, 0x20, 0x01, 0x00, 0x58, 0x21, 0x09, 0x68, 0x38, 0x11, 0x04, 0x00, +0x42, 0x03, 0x80, 0x00, 0xae, 0x71, 0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x89, 0x48, 0x38, 0x00, +0x80, 0x00, 0x40, 0x10, 0x20, 0x08, 0x40, 0x10, 0x80, 0x04, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x07, +0x86, 0x14, 0xac, 0x72, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0xa6, 0x80, +0x46, 0x10, 0x01, 0x14, 0x58, 0x10, 0x8a, 0x38, 0xae, 0x88, 0xa6, 0x81, 0xae, 0x89, 0xa6, 0x02, +0xae, 0x0a, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x01, 0x38, 0x46, 0xf0, 0x01, 0x06, 0x02, 0x27, +0x87, 0x18, 0x02, 0x30, 0x04, 0xea, 0x98, 0x9a, 0x46, 0xf0, 0x01, 0x06, 0x12, 0x27, 0x87, 0x18, +0x84, 0x20, 0x12, 0x10, 0x04, 0xea, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, +0x82, 0x39, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x50, 0x00, 0x10, 0x80, 0x17, 0x10, 0x10, +0x00, 0x20, 0x84, 0x20, 0xa8, 0x45, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x81, 0x00, 0x02, 0x10, +0x80, 0x53, 0x12, 0x10, 0x00, 0x0f, 0xdd, 0x9e, 0x92, 0x00, 0xa6, 0x40, 0x84, 0xa2, 0xd1, 0x0c, +0x84, 0xa3, 0xd1, 0x0c, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x19, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x01, +0x10, 0x17, 0x85, 0xc1, 0xd5, 0x12, 0x84, 0x20, 0xd5, 0x0c, 0xa6, 0x81, 0x46, 0xf0, 0x01, 0x01, +0x10, 0x27, 0x85, 0xc1, 0xa6, 0x43, 0xa6, 0x02, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x80, 0x04, +0x46, 0xf0, 0x01, 0x08, 0x12, 0x17, 0x83, 0x05, 0xdd, 0x9e, 0x42, 0x00, 0x00, 0x09, 0x9c, 0x02, +0xdd, 0x9e, 0x96, 0x00, 0x54, 0x10, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x10, 0x14, 0x07, 0x81, 0x94, +0xc9, 0x02, 0xc8, 0x06, 0x46, 0x00, 0x04, 0xa0, 0x84, 0x20, 0x14, 0x10, 0x00, 0x92, 0xdd, 0x9e, +0x92, 0x00, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x01, 0xd4, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, +0x01, 0xd4, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x8a, 0x19, 0xdd, 0x9e, 0x46, 0xf0, +0x01, 0x0a, 0x04, 0x17, 0x80, 0x90, 0x58, 0x10, 0x80, 0x03, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, +0x80, 0x90, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x80, 0xa0, 0x84, 0x46, 0x30, 0x0f, 0xff, +0x58, 0x31, 0x8f, 0x60, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x10, 0xe0, 0x08, 0x40, 0x11, 0x04, 0x04, +0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x80, 0x8c, 0xa8, 0x44, 0xa0, 0x45, 0x42, 0x10, 0xfc, 0x09, +0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x80, 0x8d, 0xa8, 0x45, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xb4, 0x96, 0x48, 0x96, 0x00, +0x92, 0x21, 0xdd, 0x22, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x27, 0x89, 0xe9, 0x96, 0x00, 0x46, 0x30, 0x01, 0x0a, 0x58, 0x31, 0x80, 0xbc, +0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x08, 0x64, 0x38, 0x31, 0x80, 0x00, 0x38, 0x42, 0x08, 0x00, +0xe2, 0x83, 0xe8, 0x06, 0xb4, 0x01, 0x58, 0x00, 0x00, 0x01, 0xb6, 0x01, 0xd5, 0x28, 0x46, 0x40, +0x01, 0x0a, 0x58, 0x42, 0x00, 0x6c, 0x38, 0x52, 0x00, 0x00, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, +0x08, 0x74, 0x38, 0x42, 0x08, 0x00, 0xe2, 0xa4, 0xe9, 0x1a, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, +0x08, 0x68, 0x38, 0x22, 0x08, 0x00, 0xe2, 0x43, 0xe9, 0x05, 0xb4, 0x41, 0x58, 0x21, 0x00, 0x04, +0xb6, 0x41, 0x84, 0x20, 0x46, 0x20, 0x01, 0x0a, 0x58, 0x21, 0x00, 0x6c, 0x38, 0x11, 0x00, 0x08, +0x46, 0x20, 0x01, 0x0a, 0x58, 0x21, 0x00, 0xbc, 0x38, 0x11, 0x00, 0x08, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0x3c, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x37, 0x89, 0xe9, 0x96, 0x00, 0x46, 0x20, 0x01, 0x0a, +0x58, 0x21, 0x01, 0x20, 0x38, 0x41, 0x00, 0x00, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x08, 0x6c, +0x38, 0x51, 0x0c, 0x00, 0xb4, 0x41, 0xe2, 0xa4, 0xe8, 0x05, 0x58, 0x21, 0x00, 0x01, 0xb6, 0x41, +0xd5, 0x29, 0x97, 0x54, 0xcd, 0x27, 0x46, 0x50, 0x01, 0x0a, 0x58, 0x52, 0x80, 0x0c, 0x38, 0x62, +0x80, 0x00, 0x46, 0x50, 0x01, 0x38, 0x58, 0x52, 0x88, 0x74, 0x38, 0x52, 0x8c, 0x00, 0xe2, 0xc5, +0xe9, 0x19, 0x46, 0x50, 0x01, 0x38, 0x58, 0x52, 0x88, 0x70, 0x38, 0x32, 0x8c, 0x00, 0xe2, 0x64, +0xe8, 0x04, 0x42, 0x21, 0x08, 0x09, 0xb6, 0x41, 0x84, 0x20, 0x46, 0x20, 0x01, 0x0a, 0x58, 0x21, +0x00, 0x0c, 0x38, 0x11, 0x00, 0x08, 0x46, 0x20, 0x01, 0x0a, 0x58, 0x21, 0x01, 0x20, 0x38, 0x11, +0x00, 0x08, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, 0x46, 0x70, +0x01, 0x38, 0x96, 0x80, 0x00, 0x03, 0x89, 0xe9, 0x99, 0x22, 0x46, 0x60, 0x01, 0x38, 0x58, 0x63, +0x08, 0x74, 0x38, 0x53, 0x00, 0x00, 0xa6, 0x20, 0x96, 0x48, 0xe2, 0xa0, 0xe8, 0x03, 0x84, 0x00, +0xd5, 0x3b, 0x98, 0x1a, 0xa7, 0x40, 0x98, 0x4d, 0xae, 0x40, 0x44, 0x50, 0x00, 0x10, 0xa6, 0x20, +0x9c, 0x01, 0x96, 0x00, 0xae, 0x20, 0x84, 0x80, 0x00, 0x13, 0x89, 0xe9, 0x38, 0x63, 0x04, 0x00, +0x40, 0x60, 0x18, 0x06, 0x40, 0x02, 0x18, 0x1b, 0x40, 0x02, 0x98, 0x1a, 0x46, 0x40, 0x01, 0x0a, +0x58, 0x42, 0x00, 0xbc, 0x4c, 0x32, 0x40, 0x0e, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x08, 0x64, +0x38, 0x62, 0x04, 0x00, 0x38, 0x41, 0x88, 0x00, 0x40, 0x43, 0x10, 0x06, 0x40, 0x02, 0x90, 0x1b, +0x46, 0x40, 0x01, 0x0a, 0x58, 0x42, 0x01, 0x20, 0x4c, 0x32, 0x40, 0x0f, 0x38, 0x21, 0x88, 0x00, +0x46, 0x30, 0x01, 0x38, 0x58, 0x31, 0x88, 0x6c, 0x38, 0x11, 0x84, 0x00, 0x40, 0x20, 0x88, 0x06, +0x80, 0x25, 0x40, 0x00, 0x88, 0x1b, 0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x00, 0x10, +0x00, 0x22, 0x46, 0x00, 0x04, 0x80, 0x84, 0x41, 0x04, 0x00, 0x00, 0x08, 0x4c, 0x11, 0x40, 0x0a, +0x54, 0x00, 0x3c, 0x00, 0x92, 0x0a, 0x9e, 0x01, 0x96, 0x00, 0x5c, 0x00, 0x00, 0x0f, 0xd5, 0x09, +0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xd9, 0x56, 0x00, 0x00, 0x10, 0x5c, 0x00, 0x00, 0x01, +0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0xef, 0xf8, 0x84, 0x40, 0xf2, 0x81, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x82, 0xc0, 0xa0, 0xc9, 0xd5, 0x14, 0xf4, 0x01, 0xa0, 0xca, 0xa1, 0x4c, 0x9e, 0xd9, +0x40, 0x31, 0x90, 0x02, 0x94, 0xda, 0x98, 0xeb, 0xb4, 0x63, 0xa0, 0xda, 0x4c, 0x30, 0x40, 0x07, +0x84, 0xa1, 0xda, 0x03, 0x80, 0x02, 0xd5, 0x0a, 0x84, 0x41, 0xf3, 0x01, 0x9c, 0xd9, 0xf3, 0x81, +0xf4, 0x01, 0xb4, 0x61, 0xe2, 0x83, 0xe9, 0xe9, 0x84, 0x00, 0xec, 0x08, 0xdd, 0x9e, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xee, 0x44, 0x50, 0x00, 0x18, 0xd8, 0x07, 0x84, 0x28, 0x46, 0x00, +0x01, 0x0a, 0x58, 0x00, 0x02, 0x08, 0xd5, 0x09, 0x84, 0xa8, 0xd8, 0x08, 0x46, 0x00, 0x01, 0x0a, +0x58, 0x00, 0x02, 0x08, 0x44, 0x10, 0x00, 0x18, 0xa8, 0x43, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, +0x01, 0x0a, 0x04, 0x07, 0x83, 0x18, 0x84, 0xa8, 0xd0, 0x05, 0x84, 0xaa, 0xd0, 0x03, 0x84, 0xa9, +0xd8, 0x07, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xd4, 0x84, 0xa2, 0xd0, 0x10, 0x46, 0xf0, +0x01, 0x0a, 0x04, 0x07, 0x82, 0xd4, 0x84, 0xa8, 0xd0, 0x0a, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, +0x82, 0xff, 0x56, 0x00, 0x00, 0x06, 0x5c, 0x00, 0x00, 0x01, 0xd5, 0x02, 0x84, 0x01, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x83, 0xcf, 0x81, 0x00, +0x9e, 0x11, 0x80, 0xe1, 0xe6, 0x03, 0xe8, 0x10, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x79, +0x80, 0x07, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0x74, 0x80, 0x27, 0x80, 0x08, +0xdd, 0x22, 0xc0, 0x0c, 0xd5, 0x16, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xf7, 0x44, 0x00, +0x00, 0xf3, 0xdd, 0x21, 0x44, 0x00, 0x00, 0x1f, 0xd5, 0x0c, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x0f, +0x10, 0x17, 0x8f, 0x50, 0x46, 0x10, 0x04, 0xa0, 0xa0, 0x8d, 0x42, 0x21, 0x0c, 0x09, 0xa8, 0x8d, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x96, 0x48, 0x96, 0x00, 0x98, 0x08, 0x94, 0x45, 0x46, 0x20, +0x01, 0x0c, 0x58, 0x21, 0x00, 0xb8, 0x98, 0x4a, 0x02, 0x10, 0x80, 0x0d, 0xe6, 0x22, 0xe9, 0x03, +0x84, 0x01, 0xd5, 0x0e, 0x84, 0xa1, 0xd1, 0x03, 0x84, 0x00, 0xd5, 0x0a, 0x98, 0x00, 0x9c, 0x01, +0x80, 0x22, 0x94, 0x04, 0x98, 0x01, 0xa4, 0x03, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x38, +0x84, 0xa8, 0xda, 0x03, 0x84, 0x02, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x8f, 0x78, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x38, 0x84, 0x68, 0x96, 0x00, 0x4c, 0x21, 0xc0, 0x04, +0x84, 0x02, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x8f, 0xe0, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x54, +0x58, 0xf7, 0x85, 0xf8, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, 0x09, 0xec, 0xc1, 0x22, +0x84, 0x20, 0x10, 0x10, 0x09, 0xec, 0x46, 0x60, 0x04, 0x09, 0x58, 0x63, 0x00, 0x14, 0xb4, 0x06, +0x46, 0x70, 0x00, 0x56, 0x58, 0x73, 0x85, 0x44, 0x58, 0x00, 0x00, 0x01, 0xb6, 0x06, 0x84, 0x01, +0x4b, 0xe0, 0x1c, 0x01, 0xb4, 0x26, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x26, 0x84, 0x02, 0xb4, 0x26, +0x40, 0x10, 0x80, 0x04, 0xb6, 0x26, 0x4b, 0xe0, 0x1c, 0x01, 0xb4, 0x06, 0x42, 0x00, 0x04, 0x09, +0xb6, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x97, 0xc0, +0x80, 0x07, 0x81, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x04, 0xa7, 0x81, 0xdd, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0x80, 0xc0, 0xc0, 0x78, 0xb4, 0x00, 0x54, 0x00, 0x00, 0x04, +0xc0, 0x74, 0x80, 0x07, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x88, 0xec, 0xdd, 0x2f, +0x81, 0x00, 0x4e, 0x93, 0x00, 0x48, 0x44, 0x90, 0x00, 0x30, 0x42, 0x93, 0xa4, 0x24, 0x40, 0x05, +0x24, 0x00, 0x04, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x37, 0xc0, 0x21, 0x02, 0xa3, 0x00, 0x62, +0x4e, 0xa2, 0x00, 0x1e, 0x04, 0x03, 0x00, 0x2b, 0x46, 0x10, 0xff, 0xff, 0x8a, 0x08, 0x58, 0x10, +0x8f, 0xff, 0x40, 0xa5, 0x08, 0x08, 0x40, 0x00, 0x04, 0x02, 0xe2, 0x0a, 0xe8, 0x10, 0x8f, 0x41, +0x89, 0x48, 0x40, 0xa5, 0x04, 0x02, 0x04, 0x13, 0x00, 0x2c, 0x80, 0x0a, 0x46, 0xf0, 0x00, 0x34, +0x58, 0xf7, 0x87, 0xf0, 0xdd, 0x2f, 0xc0, 0x03, 0x14, 0xa3, 0x00, 0x2b, 0x46, 0x00, 0x04, 0x80, +0x04, 0x10, 0x00, 0x08, 0x40, 0x10, 0xb4, 0x08, 0x92, 0x3e, 0x50, 0x04, 0x00, 0x04, 0x94, 0x04, +0x92, 0x06, 0x94, 0x02, 0x46, 0x20, 0x00, 0x34, 0x58, 0x21, 0x07, 0xf0, 0xc1, 0x05, 0x04, 0x13, +0x00, 0x2b, 0x9c, 0x4a, 0xd5, 0x03, 0x04, 0x13, 0x00, 0x2b, 0x4b, 0xe0, 0x08, 0x01, 0x80, 0x20, +0xc8, 0x19, 0x80, 0x48, 0x80, 0x06, 0x50, 0x13, 0x00, 0xac, 0x46, 0xf0, 0x00, 0x1d, 0x58, 0xf7, +0x89, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xd8, 0x80, 0x26, 0x84, 0x03, +0xdd, 0x22, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xbb, 0x84, 0x28, 0x80, 0x07, 0xdd, 0x22, +0xd5, 0x0c, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0xdd, 0x84, 0x40, 0x89, 0x20, 0x04, 0x04, +0x80, 0x0a, 0x10, 0x20, 0x00, 0x32, 0xd5, 0x02, 0x84, 0x20, 0x80, 0x01, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x00, 0x63, 0x00, 0xc0, 0xf0, 0x01, 0x56, 0x63, +0x00, 0x01, 0x97, 0xb4, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x80, 0x06, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf0, +0x80, 0xe1, 0x50, 0x60, 0x00, 0xb0, 0xc1, 0x21, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x39, 0x58, 0xf7, +0x83, 0x70, 0xdd, 0x2f, 0x81, 0x00, 0x4e, 0x03, 0x00, 0xac, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x87, +0x81, 0xca, 0x02, 0x23, 0x80, 0x08, 0x02, 0x33, 0x80, 0x09, 0xa5, 0x3b, 0xa5, 0x7c, 0x50, 0x03, +0x7f, 0x50, 0x84, 0x21, 0xdd, 0x28, 0xa4, 0x3e, 0x12, 0x03, 0x7f, 0xc9, 0x84, 0x01, 0xa5, 0xff, +0x10, 0x03, 0x7f, 0x9b, 0x12, 0x73, 0x7f, 0xca, 0x50, 0x0f, 0x80, 0x0c, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0xe6, 0x84, 0x21, +0x50, 0x03, 0x7f, 0x50, 0xdd, 0x22, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x71, 0x00, 0x03, 0x7f, 0x9b, +0x84, 0x22, 0xae, 0x73, 0xc0, 0x08, 0x02, 0x03, 0x7f, 0xf9, 0x50, 0x73, 0x7f, 0x8e, 0x58, 0x00, +0x04, 0x00, 0xd5, 0x0a, 0x00, 0x73, 0x7f, 0xa9, 0xc7, 0x0c, 0x02, 0x03, 0x7f, 0xf9, 0x50, 0x73, +0x7f, 0x9c, 0x42, 0x00, 0x28, 0x09, 0x12, 0x03, 0x7f, 0xf9, 0x14, 0x73, 0x7f, 0xda, 0xd5, 0x0b, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd7, 0xa6, 0x76, 0x44, 0x00, 0x70, 0x06, 0x80, 0x47, +0x84, 0x62, 0xdd, 0x24, 0xf0, 0x03, 0x46, 0x80, 0x00, 0xbc, 0x58, 0x84, 0x02, 0xc8, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x84, 0x00, 0x10, 0x0f, 0x80, 0x00, 0x50, 0x0f, +0x80, 0x02, 0x00, 0x33, 0x80, 0x0c, 0x10, 0x3f, 0x80, 0x01, 0xa4, 0x7d, 0xdd, 0x28, 0xa4, 0x79, +0x50, 0x0f, 0x80, 0x04, 0xdd, 0x28, 0xa4, 0x7a, 0x50, 0x0f, 0x80, 0x06, 0xdd, 0x28, 0xa4, 0x7b, +0x50, 0x0f, 0x80, 0x08, 0xdd, 0x28, 0xa6, 0x76, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x0b, 0x18, +0x8e, 0x29, 0x94, 0x0a, 0x98, 0x02, 0xa6, 0x82, 0x84, 0x61, 0x50, 0x0f, 0x80, 0x0a, 0x4c, 0x21, +0xc0, 0x09, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x0b, 0x18, 0x38, 0x11, 0x06, 0x01, 0xd5, 0x02, +0x84, 0x20, 0xdd, 0x28, 0x50, 0x03, 0x7f, 0x50, 0x80, 0x3f, 0x84, 0x4c, 0x46, 0xf0, 0x00, 0x39, +0x58, 0xf7, 0x87, 0xac, 0xdd, 0x2f, 0x81, 0x00, 0xc8, 0x06, 0xa6, 0x32, 0x42, 0x00, 0x00, 0x09, +0xae, 0x32, 0xd5, 0x0b, 0x84, 0x01, 0xae, 0x33, 0xd5, 0x08, 0xf0, 0x03, 0x85, 0x00, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xa6, 0xf6, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, +0x70, 0x4c, 0x80, 0x88, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x80, 0x08, +0xec, 0x10, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, +0x55, 0xc0, 0x80, 0xff, 0x54, 0x90, 0x00, 0xff, 0x80, 0x1c, 0x80, 0xc2, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0x81, 0x40, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x07, 0x81, 0x80, +0xc0, 0x11, 0x00, 0x50, 0x00, 0x20, 0x00, 0x05, 0x01, 0xae, 0xd8, 0x0c, 0x46, 0x14, 0x41, 0x00, +0x40, 0x03, 0x04, 0x02, 0xc0, 0x07, 0x46, 0x27, 0x6f, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x63, +0x08, 0x02, 0x44, 0x50, 0x00, 0x55, 0x4c, 0x92, 0xc0, 0x15, 0x4e, 0xa2, 0x00, 0x13, 0x46, 0x70, +0x00, 0x21, 0x58, 0x73, 0x84, 0x80, 0x80, 0x0a, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0xa1, 0x4c, 0x02, +0x81, 0x35, 0x80, 0x0a, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x20, 0x00, 0x10, 0x4c, 0x01, 0x01, 0x2e, +0x40, 0x7e, 0x24, 0x00, 0x46, 0x00, 0x01, 0x0c, 0x58, 0x00, 0x00, 0xb8, 0x95, 0xfd, 0x99, 0xf8, +0x02, 0x03, 0x80, 0x0d, 0x4e, 0x02, 0x01, 0x22, 0x84, 0x23, 0x04, 0x83, 0x80, 0x03, 0x4c, 0x90, +0xc0, 0x23, 0x50, 0x0f, 0x80, 0x0c, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, +0x22, 0x53, 0x80, 0x00, 0x22, 0x03, 0x80, 0x02, 0x80, 0x28, 0xd8, 0x05, 0xa4, 0xbb, 0x84, 0x00, +0xac, 0x38, 0xac, 0xba, 0xf0, 0x03, 0xf1, 0x81, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, +0xdd, 0x2f, 0x84, 0x00, 0x12, 0x03, 0x80, 0x0a, 0x84, 0x03, 0x10, 0x04, 0x00, 0x08, 0xf1, 0x01, +0x48, 0x00, 0x00, 0xfd, 0x44, 0x50, 0x00, 0x81, 0x80, 0x28, 0x4c, 0x92, 0xc0, 0x15, 0x54, 0x03, +0x00, 0x80, 0x4e, 0x03, 0x00, 0xf9, 0x54, 0x03, 0x00, 0x40, 0xc0, 0x04, 0x84, 0x46, 0x48, 0x00, +0x00, 0xc0, 0x54, 0x63, 0x01, 0x20, 0x84, 0x05, 0x40, 0x23, 0x18, 0x1a, 0x40, 0x20, 0x18, 0x1b, +0x48, 0x00, 0x00, 0xb7, 0x44, 0x50, 0x00, 0x55, 0x4c, 0x92, 0xc0, 0x0b, 0x50, 0x0e, 0x7f, 0xf7, +0x96, 0x00, 0x5c, 0xf0, 0x00, 0x20, 0xe8, 0x04, 0x84, 0x40, 0x48, 0x00, 0x00, 0x9f, 0x4e, 0xa2, +0x00, 0x3f, 0x04, 0xa5, 0x00, 0x06, 0x4e, 0xa3, 0x00, 0x3b, 0x02, 0x24, 0x00, 0x06, 0xe6, 0x52, +0xe8, 0x05, 0x54, 0x03, 0x00, 0x08, 0xc8, 0x78, 0xd5, 0x03, 0xe6, 0x5c, 0xe8, 0x05, 0x54, 0x03, +0x00, 0x10, 0xc8, 0x70, 0xd5, 0x04, 0x5c, 0xf1, 0x00, 0x7a, 0xe8, 0x05, 0x54, 0x03, 0x04, 0x00, +0xc8, 0x67, 0xd5, 0x04, 0x5c, 0xf1, 0x00, 0xb8, 0xe8, 0x05, 0x54, 0x03, 0x08, 0x00, 0xc8, 0x7a, +0xd5, 0x04, 0x5c, 0xf1, 0x00, 0xe1, 0xe8, 0x04, 0x54, 0x03, 0x40, 0x00, 0xc8, 0x57, 0x40, 0x03, +0x40, 0x08, 0x92, 0x1f, 0xc0, 0x03, 0x84, 0x4f, 0xd5, 0x6e, 0x54, 0x03, 0x40, 0x00, 0xc8, 0x4e, +0x54, 0x03, 0x08, 0x00, 0xc8, 0x67, 0x54, 0x03, 0x04, 0x00, 0xc8, 0x4a, 0x54, 0x03, 0x00, 0x10, +0xc8, 0x49, 0x54, 0x03, 0x01, 0x00, 0xc0, 0x3e, 0x84, 0x48, 0xd5, 0x5d, 0x02, 0x24, 0x00, 0x06, +0xe6, 0x52, 0xe8, 0x05, 0x54, 0x03, 0x00, 0x08, 0xc8, 0x3f, 0xd5, 0x04, 0x5c, 0xf1, 0x00, 0x37, +0xe8, 0x05, 0x42, 0x03, 0x50, 0x0b, 0xc8, 0x3a, 0xd5, 0x04, 0x5c, 0xf1, 0x00, 0x54, 0xe8, 0x05, +0x42, 0x03, 0x60, 0x0b, 0xc8, 0x36, 0xd5, 0x04, 0x5c, 0xf1, 0x01, 0x70, 0xe8, 0x05, 0x42, 0x03, +0x68, 0x0b, 0xc8, 0x32, 0xd5, 0x04, 0x5c, 0xf1, 0x02, 0x29, 0xe8, 0x05, 0x42, 0x03, 0x6c, 0x0b, +0xc8, 0x2e, 0xd5, 0x04, 0x5c, 0xf1, 0x02, 0xa8, 0xe8, 0x04, 0x42, 0x03, 0x78, 0x0b, 0xc8, 0x2a, +0x4e, 0x65, 0x00, 0x2c, 0x42, 0x03, 0x78, 0x0b, 0xc8, 0x25, 0x42, 0x03, 0x6c, 0x0b, 0xc8, 0x1f, +0x42, 0x03, 0x68, 0x0b, 0xc8, 0x19, 0x42, 0x03, 0x60, 0x0b, 0xc8, 0x13, 0x42, 0x03, 0x50, 0x0b, +0xc8, 0x0d, 0x54, 0x03, 0x02, 0x00, 0xc8, 0x1c, 0xd5, 0x07, 0x84, 0x4e, 0xd5, 0x1c, 0x84, 0x4a, +0xd5, 0x1a, 0x84, 0x44, 0xd5, 0x18, 0x84, 0x43, 0xd5, 0x16, 0x44, 0x20, 0x00, 0x24, 0xd5, 0x13, +0x44, 0x20, 0x00, 0x38, 0xd5, 0x10, 0x44, 0x20, 0x00, 0x2a, 0xd5, 0x0d, 0x44, 0x20, 0x00, 0x3b, +0xd5, 0x0a, 0x44, 0x20, 0x00, 0x2e, 0xd5, 0x07, 0x44, 0x20, 0x00, 0x3f, 0xd5, 0x04, 0x84, 0x49, +0xd5, 0x02, 0x84, 0x4b, 0x4c, 0x92, 0xc0, 0x0b, 0x51, 0xce, 0x7f, 0xf7, 0x55, 0xce, 0x00, 0xff, +0x5c, 0xfe, 0x00, 0x20, 0xe8, 0x03, 0x97, 0xb1, 0xd5, 0x14, 0xe6, 0x58, 0xe8, 0x08, 0x46, 0x00, +0x00, 0x09, 0x58, 0x00, 0x0d, 0xb4, 0x38, 0x60, 0x09, 0x01, 0xd5, 0x09, 0x54, 0x31, 0x00, 0x0f, +0x46, 0x00, 0x00, 0x09, 0x58, 0x00, 0x0d, 0xd4, 0x38, 0x60, 0x0d, 0x01, 0x10, 0x24, 0x00, 0x08, +0x02, 0x03, 0x80, 0x0b, 0xc0, 0x06, 0x02, 0x24, 0x00, 0x06, 0x98, 0x02, 0x12, 0x04, 0x00, 0x06, +0x02, 0x04, 0x00, 0x06, 0xe2, 0xc0, 0xe8, 0x0d, 0x44, 0x20, 0xff, 0xfc, 0x40, 0x63, 0x08, 0x02, +0x9a, 0x86, 0x12, 0x23, 0x80, 0x0b, 0x12, 0x03, 0x80, 0x0a, 0x12, 0x64, 0x00, 0x06, 0xd5, 0x06, +0x84, 0x00, 0x12, 0x03, 0x80, 0x0a, 0xd5, 0x02, 0x84, 0x20, 0x80, 0x01, 0xec, 0x14, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x84, 0x47, 0xd5, 0xcc, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x00, 0x3d, 0x58, 0xf7, 0x85, 0xc4, 0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x08, 0x46, 0xf0, +0x00, 0x3c, 0x58, 0xf7, 0x81, 0x14, 0xdd, 0x2f, 0x48, 0x00, 0x02, 0x2c, 0x46, 0x10, 0x04, 0x90, +0x80, 0x01, 0xa1, 0x8c, 0xa0, 0x46, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x17, 0x81, 0x62, 0x85, 0x20, +0x46, 0x70, 0x01, 0x00, 0x58, 0x73, 0x8e, 0xcc, 0x46, 0xa0, 0x01, 0x00, 0x58, 0xa5, 0x0f, 0x54, +0x47, 0xc0, 0x01, 0x13, 0x59, 0xce, 0x05, 0x7c, 0x40, 0x04, 0xa4, 0x05, 0x40, 0x00, 0x18, 0x02, +0x54, 0x10, 0x04, 0x00, 0xc1, 0x2e, 0x44, 0x20, 0x09, 0x00, 0x84, 0x24, 0x84, 0x02, 0x46, 0xf0, +0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x84, 0x0d, 0xdd, 0x21, 0x46, 0xf0, +0x00, 0x2c, 0x58, 0xf7, 0x8d, 0x4c, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x13, 0x04, 0x20, 0x81, 0x62, +0x46, 0x30, 0x40, 0x00, 0x58, 0x31, 0x82, 0x00, 0x46, 0x00, 0x04, 0x90, 0x40, 0x21, 0x0c, 0x04, +0x14, 0x20, 0x81, 0x62, 0xa8, 0x86, 0x84, 0x0e, 0xb4, 0x27, 0x58, 0x94, 0x84, 0x00, 0xdd, 0x21, +0x46, 0x10, 0x40, 0x00, 0xb4, 0x8a, 0xb4, 0x7c, 0x84, 0x02, 0x44, 0x20, 0x09, 0x01, 0xd5, 0x32, +0x54, 0x10, 0x00, 0x80, 0xc1, 0x32, 0x44, 0x20, 0x09, 0x08, 0x84, 0x28, 0x84, 0x02, 0x46, 0xf0, +0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x44, 0x00, 0x00, 0x10, 0xdd, 0x21, +0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8f, 0xbc, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x13, 0x04, 0x20, +0x81, 0x62, 0x46, 0x30, 0x28, 0x00, 0x58, 0x31, 0x82, 0x00, 0x46, 0x00, 0x04, 0x90, 0x40, 0x21, +0x0c, 0x04, 0x14, 0x20, 0x81, 0x62, 0xa8, 0x86, 0x44, 0x00, 0x00, 0x11, 0xb4, 0x27, 0x58, 0x94, +0x80, 0x80, 0xdd, 0x21, 0x46, 0x10, 0x80, 0x00, 0xb4, 0x8a, 0xb4, 0x7c, 0x84, 0x02, 0x44, 0x20, +0x09, 0x09, 0xdd, 0x24, 0x48, 0x00, 0x01, 0x89, 0x54, 0x10, 0x00, 0x40, 0xc1, 0x31, 0x44, 0x20, +0x09, 0x04, 0x44, 0x10, 0x00, 0x10, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, +0xdd, 0x2f, 0xb4, 0x27, 0x44, 0x00, 0x00, 0x13, 0xdd, 0x21, 0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, +0x83, 0x7c, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x13, 0x04, 0x20, 0x81, 0x62, 0x42, 0x21, 0x24, 0x09, +0x46, 0x30, 0x24, 0x00, 0x46, 0x00, 0x04, 0x90, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x81, 0x62, +0xa8, 0x86, 0x44, 0x00, 0x00, 0x14, 0xb4, 0x27, 0x58, 0x94, 0x80, 0x40, 0xdd, 0x21, 0x46, 0x11, +0x00, 0x00, 0xb4, 0x8a, 0xb4, 0x7c, 0x84, 0x02, 0x44, 0x20, 0x09, 0x05, 0xd5, 0xcb, 0x54, 0x10, +0x02, 0x00, 0xc1, 0x2c, 0x84, 0x02, 0x44, 0x20, 0x09, 0x02, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x35, +0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x44, 0x00, 0x00, 0x16, 0xdd, 0x21, 0x46, 0xf0, +0x00, 0x2d, 0x58, 0xf7, 0x82, 0x6c, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x13, 0x04, 0x20, 0x81, 0x62, +0x46, 0x00, 0x04, 0x90, 0x42, 0x21, 0x64, 0x08, 0x14, 0x20, 0x81, 0x62, 0xa8, 0x86, 0x44, 0x00, +0x00, 0x17, 0xb4, 0x27, 0x58, 0x94, 0x82, 0x00, 0xdd, 0x21, 0x46, 0x10, 0x20, 0x00, 0xb4, 0x8a, +0xb4, 0x7c, 0x84, 0x02, 0x44, 0x20, 0x09, 0x03, 0xd5, 0x9d, 0x54, 0x10, 0x00, 0x20, 0xc1, 0x2d, +0x44, 0x20, 0x09, 0x06, 0x84, 0x21, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, +0xdd, 0x2f, 0xb4, 0x27, 0x44, 0x00, 0x00, 0x19, 0xdd, 0x21, 0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, +0x85, 0x04, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x13, 0x04, 0x20, 0x81, 0x62, 0x46, 0x00, 0x04, 0x90, +0x42, 0x21, 0x54, 0x08, 0x14, 0x20, 0x81, 0x62, 0xa8, 0x86, 0x44, 0x00, 0x00, 0x1a, 0xb4, 0x27, +0x58, 0x94, 0x80, 0x20, 0xdd, 0x21, 0x46, 0x10, 0x10, 0x00, 0xb4, 0x8a, 0xb4, 0x7c, 0x84, 0x02, +0x44, 0x20, 0x09, 0x07, 0x48, 0xff, 0xff, 0x6f, 0x44, 0x10, 0x80, 0x10, 0x40, 0x00, 0x04, 0x02, +0xc0, 0x40, 0x44, 0x20, 0x09, 0x0c, 0x44, 0x10, 0x00, 0x20, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x35, +0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x44, 0x00, 0x00, 0x1c, 0xdd, 0x21, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x07, 0x80, 0xaf, 0x46, 0x60, 0x04, 0x90, 0x58, 0x63, 0x00, 0x18, 0xdd, 0x20, +0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8f, 0x08, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, +0x8a, 0x18, 0xdd, 0x2f, 0xb4, 0x26, 0x44, 0x30, 0x80, 0x10, 0x42, 0x10, 0xd0, 0x08, 0xb6, 0x26, +0x44, 0x00, 0x00, 0x1d, 0xb4, 0x26, 0x40, 0x94, 0x8c, 0x04, 0x42, 0x10, 0xfc, 0x08, 0xb6, 0x26, +0xb4, 0x27, 0xdd, 0x21, 0xb4, 0x7c, 0xb4, 0x8a, 0x46, 0x12, 0x00, 0x00, 0x84, 0x02, 0x44, 0x20, +0x09, 0x0d, 0xdd, 0x24, 0xb4, 0x06, 0x92, 0x04, 0x94, 0x04, 0xb6, 0x06, 0x48, 0x00, 0x00, 0xb5, +0x54, 0x03, 0x00, 0x0f, 0x4e, 0x02, 0x00, 0xb1, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8d, 0x74, +0xdd, 0x2f, 0xc8, 0x09, 0x84, 0x0f, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0xa0, 0xdd, 0x2f, +0x92, 0xc4, 0x95, 0xb4, 0x54, 0x03, 0x00, 0x04, 0xc0, 0x2c, 0x44, 0x20, 0x08, 0x04, 0x84, 0x24, +0x84, 0x01, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x84, 0x07, +0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xb7, 0x84, 0x01, 0xdd, 0x21, 0x46, 0xf0, +0x00, 0x2d, 0x58, 0xf7, 0x8a, 0x2c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x81, 0x7c, +0xdd, 0x2f, 0xb4, 0x27, 0x84, 0x08, 0xdd, 0x21, 0xb4, 0x8a, 0x46, 0x10, 0x40, 0x00, 0xb4, 0x7c, +0x84, 0x01, 0x44, 0x20, 0x08, 0x05, 0xdd, 0x24, 0x58, 0x94, 0x80, 0x04, 0x84, 0x04, 0xd5, 0x6f, +0x54, 0x83, 0x00, 0x08, 0x4e, 0x82, 0x00, 0x22, 0x44, 0x20, 0x08, 0x06, 0x84, 0x28, 0x84, 0x01, +0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x84, 0x0a, 0xdd, 0x21, +0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8f, 0x28, 0xdd, 0x2f, 0xb4, 0x27, 0x84, 0x0b, 0xdd, 0x21, +0xb4, 0x8a, 0x46, 0x10, 0x80, 0x00, 0xb4, 0x7c, 0x84, 0x01, 0x44, 0x20, 0x08, 0x07, 0xdd, 0x24, +0x58, 0x94, 0x80, 0x08, 0x84, 0x08, 0xd5, 0x4b, 0x96, 0x34, 0xc0, 0x27, 0x84, 0x01, 0x44, 0x20, +0x08, 0x00, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, 0xb4, 0x27, +0x84, 0x01, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xb7, 0x80, 0x08, 0xdd, 0x21, +0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, 0x86, 0x04, 0xdd, 0x2f, 0xb4, 0x27, 0x84, 0x02, 0xdd, 0x21, +0xb4, 0x8a, 0x46, 0x10, 0x10, 0x00, 0xb4, 0x7c, 0x84, 0x01, 0x44, 0x20, 0x08, 0x01, 0xdd, 0x24, +0x58, 0x94, 0x80, 0x01, 0x84, 0x01, 0xd5, 0x23, 0x54, 0x63, 0x00, 0x02, 0xc6, 0x25, 0x44, 0x20, +0x08, 0x02, 0x84, 0x22, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x04, 0xdd, 0x2f, +0xb4, 0x27, 0x84, 0x04, 0xdd, 0x21, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8d, 0xdc, 0xdd, 0x2f, +0xb4, 0x27, 0x84, 0x05, 0xdd, 0x21, 0xb4, 0x8a, 0x46, 0x10, 0x20, 0x00, 0xb4, 0x7c, 0x84, 0x01, +0x44, 0x20, 0x08, 0x03, 0xdd, 0x24, 0x58, 0x94, 0x80, 0x02, 0x84, 0x02, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x82, 0xa0, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x88, 0x0c, 0xdd, 0x2f, +0xc0, 0x0e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x80, 0xae, 0xdd, 0x20, 0x46, 0x00, 0x04, 0x90, +0x04, 0x10, 0x00, 0x1c, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x00, 0x1c, 0x46, 0xf0, 0x00, 0x33, +0x58, 0xf7, 0x88, 0x0c, 0xdd, 0x2f, 0xc0, 0x03, 0x84, 0xc0, 0xd5, 0x04, 0x46, 0x00, 0x04, 0x90, +0xa1, 0x84, 0x40, 0x04, 0xa4, 0x05, 0x96, 0x01, 0x40, 0x00, 0x18, 0x02, 0x4e, 0x03, 0xfd, 0xee, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xb2, 0xdd, 0x20, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x92, 0x00, 0x46, 0xf0, 0x00, 0xbd, 0x58, 0xf7, +0x83, 0xfc, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x97, 0x88, 0x96, 0x91, 0x96, 0xd9, 0x97, 0x21, 0x97, 0x69, 0x80, 0x26, +0x80, 0xe0, 0x46, 0xf0, 0x00, 0x39, 0x58, 0xf7, 0x82, 0x70, 0xdd, 0x2f, 0xce, 0x04, 0x50, 0x03, +0x80, 0xaa, 0xd5, 0x0b, 0xe6, 0xc2, 0xe8, 0x04, 0x50, 0x03, 0x80, 0x3e, 0xd5, 0x06, 0x84, 0x27, +0x50, 0x03, 0x80, 0x4c, 0x4c, 0x60, 0x80, 0x04, 0x84, 0x2a, 0xac, 0x40, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x3c, +0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x85, 0x84, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x7d, 0x84, 0x00, 0xdd, 0x21, 0x46, 0xf0, 0x00, 0x3f, +0x58, 0xf7, 0x8e, 0xdc, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x80, 0xdc, 0xdd, 0x2f, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x88, 0x64, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, +0x83, 0xc1, 0xdd, 0x20, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x17, 0x82, 0xd8, 0x46, 0xf0, 0x00, 0x2c, +0x58, 0xf7, 0x8e, 0xc4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xd8, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x67, +0x82, 0xda, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x8f, 0xf4, 0xdd, 0x2f, 0x44, 0x00, 0xf0, 0x00, +0x40, 0x23, 0x00, 0x02, 0x84, 0x20, 0x44, 0x00, 0x00, 0x10, 0x40, 0x70, 0x88, 0x1b, 0x40, 0x70, +0x08, 0x1a, 0x44, 0x50, 0x20, 0x00, 0xd6, 0x04, 0x44, 0x53, 0x00, 0x00, 0xde, 0x5f, 0x46, 0x10, +0x04, 0x90, 0x04, 0x00, 0x80, 0x0d, 0x44, 0x50, 0x20, 0x00, 0xde, 0x07, 0x46, 0xf0, 0x00, 0x40, +0x58, 0xf7, 0x81, 0xb0, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x81, 0x64, +0xdd, 0x2f, 0xc8, 0x41, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x8b, 0x5c, 0x04, 0x83, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x45, 0x58, 0xf7, 0x83, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, +0x85, 0x84, 0xdd, 0x2f, 0xa0, 0x39, 0x44, 0x10, 0x00, 0x1c, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, +0x80, 0x24, 0xdd, 0x2f, 0x44, 0x50, 0x20, 0x00, 0xb7, 0x07, 0x14, 0x83, 0x80, 0x01, 0x46, 0x00, +0x01, 0x0f, 0x58, 0x00, 0x04, 0x94, 0xde, 0x05, 0xa0, 0x47, 0x9c, 0x49, 0xa8, 0x47, 0xd5, 0x06, +0x04, 0x10, 0x00, 0x0b, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x0b, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x01, +0x10, 0x17, 0x88, 0x64, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x80, 0x68, 0x84, 0x04, +0x84, 0x21, 0x44, 0x20, 0x30, 0x40, 0xdd, 0x24, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xc2, +0xdd, 0x20, 0xd5, 0x10, 0x54, 0x10, 0x0f, 0x00, 0x80, 0x06, 0x40, 0x60, 0x9c, 0x04, 0x46, 0xf0, +0x00, 0x3f, 0x58, 0xf7, 0x8e, 0x8c, 0xdd, 0x2f, 0xd5, 0x03, 0x58, 0x63, 0x81, 0x00, 0x58, 0x03, +0x00, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x46, 0x70, 0x01, 0x06, 0x58, 0x73, 0x8f, 0xf0, 0x00, 0x33, 0x80, 0x2c, 0x80, 0xc0, 0x80, 0x81, +0x96, 0x90, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x87, 0x8f, 0x8f, 0x4e, 0x33, 0x00, 0x92, 0xc2, 0x12, +0x4e, 0x83, 0x00, 0x28, 0x46, 0x60, 0x01, 0x00, 0x58, 0x63, 0x03, 0xfc, 0x04, 0x13, 0x00, 0x09, +0x10, 0x83, 0x80, 0x29, 0x80, 0x07, 0xdd, 0x21, 0x80, 0x07, 0xa0, 0xf6, 0xa0, 0x7b, 0x80, 0x48, +0xd5, 0x7a, 0xa8, 0x7a, 0xa9, 0xb9, 0xce, 0x03, 0x80, 0x66, 0xd5, 0x03, 0x00, 0x33, 0x01, 0xae, +0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x96, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x89, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0x02, 0x80, 0x06, 0xd5, 0x66, +0xa0, 0x7b, 0x00, 0x63, 0x80, 0x29, 0xe6, 0x2a, 0xe9, 0x09, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, +0x83, 0xd7, 0x80, 0x43, 0x44, 0x00, 0x70, 0x1e, 0xdd, 0x24, 0x46, 0x80, 0x01, 0x06, 0x58, 0x84, +0x0f, 0xf0, 0x04, 0x44, 0x00, 0x03, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x97, +0x80, 0x66, 0x44, 0x70, 0x00, 0xff, 0x83, 0x88, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, +0xdd, 0x2f, 0x81, 0x07, 0x85, 0x20, 0x46, 0xa0, 0x00, 0x1c, 0x58, 0xa5, 0x03, 0xcc, 0x9c, 0x31, +0xe4, 0xc8, 0xe9, 0x03, 0x84, 0xc1, 0xd5, 0x02, 0x97, 0x80, 0x80, 0x06, 0x8d, 0x21, 0x4b, 0xe0, +0x28, 0x01, 0x54, 0x94, 0x80, 0xff, 0xc0, 0x0b, 0xb4, 0x20, 0x54, 0x10, 0xff, 0xc1, 0xc1, 0x07, +0x04, 0x00, 0x00, 0x6c, 0x40, 0x83, 0x00, 0x1a, 0x40, 0x73, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x29, +0x4c, 0x03, 0x00, 0x05, 0x84, 0x09, 0x4c, 0x90, 0x7f, 0xe4, 0x44, 0x00, 0x00, 0xff, 0x4c, 0x80, +0x40, 0x09, 0x40, 0x13, 0xa0, 0x03, 0x84, 0x00, 0x40, 0x83, 0x84, 0x1b, 0x40, 0x80, 0x04, 0x1a, +0x46, 0x70, 0x01, 0x06, 0x58, 0x73, 0x8f, 0xf0, 0x46, 0x60, 0x01, 0x00, 0x58, 0x63, 0x03, 0xfc, +0x04, 0x13, 0x00, 0x09, 0x10, 0x83, 0x80, 0x29, 0x80, 0x07, 0xdd, 0x21, 0xa0, 0xf6, 0x80, 0x07, +0x80, 0x48, 0x84, 0x2a, 0xdd, 0x23, 0xa0, 0x75, 0x84, 0x0a, 0xdd, 0x21, 0xd5, 0x28, 0x46, 0x50, +0x00, 0x35, 0x58, 0x52, 0x89, 0x64, 0xc6, 0x1b, 0xa8, 0x7a, 0xa9, 0xb9, 0x84, 0x06, 0x00, 0x33, +0x01, 0xae, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x99, 0x4b, 0xe0, 0x14, 0x01, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x81, 0x02, 0x84, 0x40, 0x84, 0x01, 0x80, 0x66, 0x80, 0x82, 0x80, 0xa0, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0xd5, 0x09, 0x80, 0x66, 0x84, 0x06, +0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x98, 0x4b, 0xe0, 0x14, 0x01, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xbc, 0x96, 0x49, 0x80, 0x80, +0x44, 0x00, 0x7f, 0x1a, 0x10, 0x2f, 0x80, 0x08, 0x12, 0x1f, 0x80, 0x0e, 0x80, 0x43, 0x4c, 0x10, +0x00, 0x21, 0x9c, 0x04, 0x4c, 0x10, 0x00, 0x29, 0x9e, 0x05, 0x4c, 0x10, 0x40, 0x29, 0x04, 0x52, +0x00, 0x6c, 0x84, 0x21, 0xd9, 0x16, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0x80, +0x80, 0x64, 0x46, 0x10, 0x00, 0x18, 0x58, 0x10, 0x85, 0x94, 0x80, 0x82, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xf1, 0xd5, 0x17, +0x00, 0x11, 0x00, 0x08, 0x10, 0x1f, 0x80, 0x3e, 0xa6, 0x50, 0x10, 0x1f, 0x80, 0x3c, 0xa6, 0x94, +0x10, 0x2f, 0x80, 0x3d, 0xd5, 0x04, 0xa6, 0x98, 0x10, 0x2f, 0x80, 0x13, 0x00, 0x02, 0x01, 0xae, +0x80, 0x3f, 0x46, 0xf0, 0x00, 0x16, 0x58, 0xf7, 0x84, 0x84, 0xdd, 0x2f, 0xec, 0x44, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf0, 0x46, 0x80, 0x00, 0x26, +0x58, 0x84, 0x09, 0x98, 0x50, 0x60, 0x01, 0xc4, 0x80, 0x41, 0x44, 0x00, 0x00, 0x10, 0x80, 0x3f, +0xdd, 0x28, 0x50, 0x03, 0x7f, 0xe4, 0x80, 0xff, 0x46, 0xf0, 0x00, 0x18, 0x58, 0xf7, 0x83, 0x3c, +0xdd, 0x2f, 0xc8, 0x29, 0xa6, 0xb2, 0x84, 0x2b, 0xae, 0xb3, 0x50, 0x03, 0x7e, 0x3c, 0x44, 0x30, +0x00, 0x17, 0x46, 0xf0, 0x00, 0x18, 0x58, 0xf7, 0x88, 0xdc, 0xdd, 0x2f, 0x50, 0x03, 0x7e, 0x3c, +0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x88, 0xd8, 0xdd, 0x2f, 0x84, 0xa1, 0xd0, 0x05, 0x00, 0x03, +0x7f, 0xfe, 0xe6, 0x03, 0xe8, 0x0a, 0x50, 0x03, 0x7e, 0x3c, 0x44, 0x10, 0x00, 0x17, 0x46, 0xf0, +0x00, 0x11, 0x58, 0xf7, 0x80, 0xc0, 0xdd, 0x2f, 0x50, 0x03, 0x7e, 0x3c, 0x44, 0x10, 0x00, 0x17, +0x48, 0x00, 0x00, 0x95, 0xa6, 0x36, 0x84, 0xa1, 0xd8, 0x0d, 0x94, 0x2c, 0x80, 0x5f, 0x50, 0x13, +0x7f, 0x60, 0xdd, 0x28, 0xa6, 0x35, 0x54, 0x00, 0x00, 0x08, 0x4e, 0x02, 0x00, 0xda, 0x84, 0x02, +0xd5, 0x40, 0xc8, 0x22, 0x94, 0x2c, 0x50, 0x13, 0x7f, 0x60, 0x80, 0x5f, 0xdd, 0x28, 0x50, 0x03, +0x7e, 0x3c, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8e, 0x5c, 0xdd, 0x2f, 0xc8, 0x0a, 0xa6, 0x72, +0x80, 0x5f, 0x50, 0x03, 0x7e, 0x3c, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8e, 0xb0, 0xdd, 0x2f, +0xa6, 0x35, 0x44, 0x50, 0x00, 0x40, 0x4c, 0x02, 0xc0, 0xbc, 0x04, 0x03, 0x7f, 0xfb, 0x84, 0xa1, +0x4c, 0x02, 0xc0, 0xb7, 0xd5, 0x43, 0x8c, 0xbb, 0xd8, 0x32, 0xa6, 0x75, 0x54, 0x00, 0x80, 0x04, +0x4e, 0x02, 0x00, 0xaf, 0x54, 0x80, 0x80, 0x08, 0x4e, 0x83, 0x00, 0x05, 0x96, 0x4a, 0x4e, 0x14, +0x00, 0x14, 0x04, 0x03, 0x7f, 0xfb, 0x4e, 0x02, 0x00, 0xa0, 0xa6, 0x74, 0x50, 0x03, 0x7e, 0x3c, +0x80, 0x5f, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8e, 0xb0, 0xdd, 0x2f, 0x44, 0x00, 0x00, 0x2c, +0xae, 0x36, 0x48, 0x00, 0x00, 0x96, 0x04, 0x13, 0x7f, 0xfb, 0x4e, 0x12, 0x00, 0x8e, 0x44, 0x00, +0x00, 0x29, 0xae, 0x36, 0xa6, 0x72, 0x50, 0x03, 0x7e, 0x3c, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x17, +0x58, 0xf7, 0x8e, 0xb0, 0xdd, 0x2f, 0x80, 0x08, 0x48, 0x00, 0x00, 0x84, 0x8c, 0xad, 0xd8, 0x17, +0xa6, 0x35, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x7c, 0xa6, 0x72, 0x80, 0x5f, 0x50, 0x03, 0x7e, 0x3c, +0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8e, 0xb0, 0xdd, 0x2f, 0xa6, 0x74, 0x50, 0x03, 0x7e, 0x3c, +0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8f, 0x08, 0xdd, 0x2f, 0xd5, 0x6a, 0x9d, 0x6a, 0xd8, 0x24, +0xa6, 0x35, 0x54, 0x10, 0x00, 0x08, 0xc9, 0x04, 0x44, 0x50, 0x00, 0x84, 0xd8, 0x15, 0xa6, 0x74, +0x50, 0x03, 0x7e, 0x3c, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8e, 0xb0, 0xdd, 0x2f, +0x84, 0x00, 0xae, 0x36, 0x84, 0x20, 0x50, 0x03, 0x7e, 0x3c, 0x46, 0xf0, 0x00, 0x18, 0x58, 0xf7, +0x81, 0x50, 0xdd, 0x2f, 0xd5, 0x4d, 0x54, 0x10, 0x00, 0x10, 0xc9, 0x04, 0x44, 0x50, 0x00, 0xc4, +0xd8, 0x47, 0xa6, 0x74, 0xd5, 0xcb, 0x8e, 0xb0, 0xd0, 0x41, 0x84, 0xa3, 0xd0, 0x3f, 0x9e, 0x04, +0x96, 0x00, 0xe6, 0x02, 0xe8, 0x21, 0xa6, 0x35, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x39, 0x04, 0x03, +0x7f, 0xfb, 0xc8, 0x04, 0x44, 0x00, 0x00, 0x2a, 0xd5, 0x34, 0x44, 0x00, 0x00, 0x10, 0x50, 0x13, +0x7f, 0x60, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x98, 0xdd, 0x2f, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x09, 0xf1, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, +0x84, 0x00, 0xae, 0x35, 0xd5, 0x1b, 0x44, 0x00, 0x00, 0x10, 0x80, 0x5f, 0x50, 0x13, 0x7f, 0x60, +0xdd, 0x28, 0x50, 0x03, 0x7e, 0x3c, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8e, 0x5c, 0xdd, 0x2f, +0xc8, 0x0f, 0xa6, 0x72, 0x50, 0x03, 0x7e, 0x3c, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, +0x8e, 0xb0, 0xdd, 0x2f, 0xd5, 0x05, 0x9c, 0x2f, 0xd5, 0x04, 0x84, 0x06, 0xd5, 0x02, 0x84, 0x00, +0xec, 0x10, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x1e, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x85, 0x90, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0x00, 0x01, 0x08, 0x58, 0x00, 0x0f, 0xf1, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x17, 0x83, 0xf5, 0x84, 0xa3, 0xd9, 0x67, 0x46, 0xf0, +0x01, 0x08, 0x00, 0x07, 0x8f, 0xf0, 0xc0, 0x21, 0x46, 0x60, 0x00, 0xbd, 0x58, 0x63, 0x0e, 0xdc, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0xbf, 0xd0, 0x13, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x06, +0x04, 0x17, 0x83, 0xdf, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0xf0, 0xdd, 0x2f, 0xc8, 0x07, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x81, 0x18, 0xdd, 0x2f, 0xd5, 0x07, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x81, 0x0a, 0x84, 0x05, 0xdd, 0x21, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, +0x82, 0xc8, 0xdd, 0x2f, 0x46, 0x20, 0x01, 0x08, 0x58, 0x21, 0x0f, 0xd4, 0x00, 0x11, 0x00, 0x1c, +0xc9, 0x0b, 0x84, 0x61, 0xb6, 0x62, 0x10, 0x11, 0x00, 0x1f, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x25, +0x58, 0xf7, 0x8c, 0x48, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xa3, 0x46, 0x2f, +0x9f, 0xfc, 0x58, 0x21, 0x0f, 0x7f, 0x40, 0x00, 0x08, 0x02, 0xc8, 0x20, 0x46, 0x60, 0x01, 0x08, +0x58, 0x63, 0x0f, 0xd4, 0x00, 0x13, 0x00, 0x20, 0x84, 0xa2, 0xd9, 0x18, 0x46, 0xf0, 0x00, 0x36, +0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0xa0, 0x75, 0x80, 0xe0, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x87, 0xf0, 0xdd, 0x2f, 0xc0, 0x0b, 0xa0, 0x35, 0x9a, 0x07, 0x94, 0x04, 0x92, 0x04, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x83, 0x9c, 0x92, 0x01, 0xdd, 0x21, 0x46, 0x60, 0x01, 0x08, 0x04, 0x23, +0x03, 0xf5, 0x84, 0xa4, 0xda, 0x0a, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x82, 0xc8, +0xdd, 0x2f, 0x84, 0x01, 0x14, 0x03, 0x03, 0xf5, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x0a, 0x10, 0x27, +0x8b, 0x84, 0x80, 0xe0, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, +0x80, 0x80, 0x46, 0x90, 0x00, 0x35, 0x58, 0x94, 0x89, 0x64, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, +0x44, 0x20, 0x70, 0xa0, 0x84, 0x62, 0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0f, 0xf0, 0xdd, 0x29, +0x00, 0xa3, 0x00, 0x2c, 0x4e, 0xa3, 0x01, 0x3e, 0x04, 0x83, 0x00, 0x03, 0x4c, 0x83, 0x80, 0x20, +0x80, 0x88, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x9e, 0x96, 0xf9, 0xdd, 0x29, +0xcf, 0x0a, 0xa0, 0x33, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x07, 0x00, 0x03, 0x00, 0x36, 0xc0, 0x03, +0x10, 0x73, 0x00, 0x36, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x17, 0x83, 0xb2, 0x84, 0xe1, 0x98, 0x4f, +0x46, 0xf0, 0x01, 0x08, 0x14, 0x17, 0x83, 0xb2, 0x48, 0x00, 0x01, 0x55, 0xa1, 0x34, 0x44, 0x20, +0x70, 0x9d, 0x40, 0x34, 0x00, 0x13, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0xdd, 0x29, 0xa0, 0xb4, +0x84, 0x6a, 0x4c, 0x21, 0x80, 0x07, 0x50, 0x01, 0x7f, 0xf1, 0xe6, 0x03, 0x4e, 0xf2, 0x00, 0xa8, +0x46, 0xf0, 0x01, 0x07, 0x00, 0x37, 0x80, 0x1e, 0xcb, 0x0c, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, +0x83, 0xd7, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x17, 0x83, 0xff, 0x44, 0x00, 0x70, 0x1f, 0xdd, 0x24, +0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0f, 0xf0, 0x00, 0x13, 0x00, 0x36, 0xc1, 0x06, 0xa0, 0x33, +0x4e, 0x02, 0x00, 0xb8, 0x48, 0x00, 0x00, 0xac, 0xa0, 0xb4, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x37, +0x85, 0xf9, 0x84, 0x8c, 0xa9, 0x34, 0xa8, 0xb3, 0x4e, 0x32, 0x01, 0x22, 0x84, 0x6a, 0x4c, 0x21, +0xc1, 0x1f, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x07, 0x81, 0x80, 0x84, 0x41, 0x00, 0x00, 0x00, 0x22, +0x4c, 0x01, 0x41, 0x16, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xdb, 0x00, 0x20, 0x00, 0x20, +0x4e, 0x22, 0x01, 0x0e, 0x00, 0xa0, 0x00, 0x22, 0x84, 0x61, 0x4c, 0xa1, 0xc1, 0x09, 0x46, 0x70, +0x01, 0x06, 0x58, 0x73, 0x8f, 0x00, 0x01, 0xc3, 0x80, 0x6c, 0x4f, 0xc2, 0x00, 0x2f, 0x00, 0x03, +0x00, 0x2e, 0xf1, 0x81, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x85, 0x90, 0xdd, 0x2f, 0xf1, 0x01, +0x83, 0x80, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x40, 0x0e, +0x00, 0x01, 0x96, 0x01, 0x92, 0x01, 0x5c, 0xf0, 0x01, 0x2c, 0x4e, 0xf2, 0x00, 0xe9, 0x04, 0x33, +0x80, 0x1c, 0x50, 0x23, 0x80, 0x62, 0x50, 0x13, 0x80, 0x60, 0xdd, 0x23, 0x97, 0xc0, 0x50, 0x03, +0x00, 0x2e, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0a, +0x10, 0xa7, 0x8b, 0x84, 0x84, 0x04, 0xd5, 0x30, 0x00, 0x03, 0x80, 0x84, 0x4e, 0x02, 0x00, 0xd0, +0x00, 0x03, 0x00, 0x2e, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x85, 0x90, 0xdd, 0x2f, 0x80, 0x20, +0x80, 0x1c, 0xf1, 0x81, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0xf1, 0x01, +0x9a, 0x08, 0x96, 0x01, 0x92, 0x01, 0x5c, 0xf0, 0x01, 0x2c, 0x4e, 0xf2, 0x00, 0xb9, 0x04, 0x33, +0x80, 0x22, 0x50, 0x23, 0x80, 0x7a, 0x50, 0x13, 0x80, 0x78, 0xdd, 0x23, 0x97, 0xc0, 0x50, 0x03, +0x00, 0x2e, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0a, +0x10, 0xa7, 0x8b, 0x84, 0x84, 0x05, 0xa8, 0x33, 0x48, 0x00, 0x00, 0xa3, 0x00, 0x03, 0x00, 0x2e, +0xc0, 0x0c, 0xa0, 0x73, 0xe6, 0x2a, 0xe8, 0x09, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd7, +0x80, 0x6a, 0x44, 0x00, 0x70, 0x21, 0xdd, 0x24, 0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0f, 0xf0, +0x00, 0x03, 0x00, 0x36, 0xc0, 0x1e, 0xa0, 0x73, 0xc1, 0x14, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, +0x83, 0xd7, 0xa0, 0xb4, 0x44, 0x00, 0x70, 0x22, 0x84, 0x60, 0xdd, 0x24, 0x46, 0xf0, 0x01, 0x08, +0x04, 0x17, 0x83, 0xb3, 0x9c, 0x49, 0x46, 0xf0, 0x01, 0x08, 0x14, 0x17, 0x83, 0xb3, 0xd5, 0x03, +0x84, 0x01, 0xa8, 0x33, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x07, 0x10, 0x17, 0x80, 0x26, 0xd5, 0x5b, +0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0xc8, 0x08, 0x00, 0x03, 0x00, 0x30, 0xc8, 0x05, +0x00, 0x13, 0x00, 0x33, 0xe6, 0x22, 0xe9, 0x10, 0x84, 0x2c, 0x46, 0xf0, 0x01, 0x06, 0x14, 0x17, +0x83, 0xff, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0x07, 0x46, 0x00, 0x7f, 0xff, 0x58, 0x00, +0x0f, 0xff, 0xdd, 0x21, 0xd5, 0x4e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x77, 0x81, 0x0b, 0x84, 0x2c, +0xa8, 0x73, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0xdd, 0x27, 0xc8, 0x03, +0x00, 0x03, 0x00, 0x2d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0x07, 0xdd, 0x21, 0xd5, 0x3f, +0x00, 0x13, 0x00, 0x30, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0x84, 0x40, 0x40, 0x21, +0x04, 0x06, 0x98, 0x90, 0xca, 0x22, 0x00, 0x03, 0x00, 0x34, 0x00, 0x13, 0x00, 0x33, 0x4c, 0x10, +0x40, 0x1d, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x77, 0x83, 0x7f, 0x80, 0x62, 0x80, 0x82, 0x46, 0x10, +0x00, 0x14, 0x58, 0x10, 0x8b, 0xec, 0x84, 0xa1, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x87, 0xb0, 0xdd, 0x2f, 0x84, 0x61, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x9f, +0x80, 0x83, 0xdd, 0x29, 0x84, 0xe1, 0xd5, 0x0e, 0x84, 0x60, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, +0x44, 0x20, 0x70, 0x9f, 0x80, 0x83, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, +0x84, 0xe0, 0x80, 0x07, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x84, 0xe0, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x81, 0x04, 0x54, 0x04, 0x00, 0xff, 0xdd, 0x21, 0xd5, 0xf3, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x00, 0xbd, 0x58, 0x63, 0x0e, 0xdc, 0x4b, 0xe0, 0x18, 0x01, +0x84, 0xbf, 0xd0, 0x15, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x77, 0x83, 0xd9, 0x4b, 0xe0, 0x18, 0x01, +0x80, 0x20, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0xf0, 0xdd, 0x2f, 0xc0, 0x07, +0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, 0x8a, 0x04, 0xdd, 0x2f, 0xd5, 0x07, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x81, 0x0a, 0x84, 0x04, 0xdd, 0x21, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xc4, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, 0x87, 0x14, +0x50, 0x60, 0x00, 0xf4, 0x3a, 0x00, 0x84, 0x00, 0x50, 0x3f, 0x80, 0x1c, 0xb6, 0x03, 0xac, 0x5a, +0x50, 0x2f, 0x80, 0x24, 0x3a, 0x01, 0x84, 0x00, 0x50, 0x4f, 0x80, 0x34, 0xb6, 0x02, 0xac, 0x52, +0x50, 0x7f, 0x80, 0x2c, 0x3a, 0x01, 0x04, 0x00, 0x46, 0xf0, 0x00, 0xd2, 0x04, 0x27, 0x80, 0x7a, +0xb6, 0x07, 0xb6, 0x44, 0x12, 0x11, 0x80, 0x0a, 0x50, 0x0f, 0x80, 0x0c, 0x04, 0x13, 0x00, 0x2f, +0x50, 0x83, 0x00, 0xb4, 0x46, 0x90, 0x00, 0x1c, 0x58, 0x94, 0x80, 0xc4, 0xc9, 0x0c, 0x46, 0x10, +0x01, 0x07, 0x58, 0x10, 0x83, 0x3c, 0x80, 0xa7, 0x50, 0x20, 0x80, 0x28, 0x50, 0x30, 0x80, 0x38, +0xb7, 0x1f, 0xd5, 0x0b, 0x46, 0x10, 0x01, 0x07, 0x58, 0x10, 0x83, 0x3c, 0xb6, 0xff, 0x80, 0xa8, +0x50, 0x20, 0x80, 0x38, 0x50, 0x30, 0x80, 0x28, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0x00, 0x00, 0x10, +0x50, 0x13, 0x00, 0x60, 0x50, 0x2f, 0x80, 0x0c, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0xac, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x17, 0x83, 0xbe, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x04, +0x84, 0x03, 0xd5, 0x19, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x83, 0xb9, 0x9e, 0x02, 0x96, 0x00, +0xe6, 0x02, 0xe9, 0x0e, 0xa0, 0x77, 0xa0, 0x34, 0x40, 0x00, 0x80, 0x04, 0x96, 0x04, 0xc0, 0x0a, +0xa0, 0x32, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x07, 0xa0, 0xb5, 0x4c, 0x20, 0x40, 0x04, 0x84, 0x05, +0xd5, 0x02, 0x84, 0x04, 0x10, 0x03, 0x00, 0xd9, 0xec, 0x3c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x00, 0x10, 0x00, 0xb6, 0x44, 0x80, 0x00, 0x30, 0x42, 0x80, +0xa0, 0x24, 0x50, 0x60, 0x00, 0x9c, 0x46, 0x00, 0x01, 0x09, 0x58, 0x00, 0x07, 0xcc, 0x89, 0x00, +0x04, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x24, 0xc0, 0x04, 0x84, 0xe0, 0x48, 0x00, 0x00, 0xa8, +0x46, 0x90, 0x00, 0x37, 0x58, 0x94, 0x84, 0xf4, 0x84, 0x03, 0x44, 0x20, 0x00, 0x1b, 0x84, 0x61, +0x4b, 0xe0, 0x24, 0x01, 0x80, 0xe0, 0xc0, 0x53, 0xb4, 0x00, 0xa6, 0x40, 0xc9, 0x39, 0x00, 0x10, +0x00, 0x0a, 0x04, 0x93, 0x7f, 0xdf, 0xc9, 0x04, 0x00, 0x20, 0x00, 0x0b, 0xc2, 0x0b, 0x00, 0x00, +0x00, 0x0b, 0xa4, 0xb4, 0x40, 0x00, 0x20, 0x08, 0x98, 0x4a, 0x98, 0x48, 0x12, 0x14, 0x80, 0x04, +0xd5, 0x08, 0x02, 0x13, 0x7f, 0xcc, 0xa4, 0x34, 0x98, 0x08, 0x9c, 0x06, 0x12, 0x04, 0x80, 0x04, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0xef, 0x50, 0x03, 0x7f, 0x64, 0xdd, 0x21, 0x96, 0x41, +0x12, 0x14, 0x80, 0x05, 0x46, 0xa0, 0x00, 0xbc, 0x58, 0xa5, 0x02, 0xc8, 0xb4, 0x07, 0x9c, 0x02, +0x4b, 0xe0, 0x28, 0x01, 0xb4, 0x07, 0x02, 0x14, 0x80, 0x04, 0x8c, 0x0a, 0x4b, 0xe0, 0x28, 0x01, +0x00, 0x04, 0x80, 0x0d, 0x58, 0x00, 0x00, 0x02, 0x10, 0x04, 0x80, 0x0d, 0xd5, 0x3d, 0x84, 0xa1, +0xd9, 0x3b, 0xa4, 0x34, 0x02, 0x13, 0x7f, 0xcc, 0x98, 0x48, 0x9c, 0x4e, 0x96, 0x49, 0xac, 0x76, +0xb4, 0x07, 0x9c, 0x06, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0xc8, 0xdd, 0x2f, 0x00, 0x03, +0x00, 0x38, 0x58, 0x00, 0x00, 0x02, 0x10, 0x03, 0x00, 0x38, 0xd5, 0x26, 0x50, 0x03, 0x7f, 0x64, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x8f, 0x64, 0xdd, 0x2f, 0xc0, 0x0c, 0x00, 0x13, 0x00, 0x1a, +0x44, 0x00, 0x00, 0x55, 0x44, 0x20, 0x00, 0x1b, 0x84, 0x61, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0xe0, +0xc8, 0x13, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x81, 0x14, 0xdd, 0x2f, 0x04, 0x14, +0x00, 0x06, 0x44, 0x00, 0x00, 0x20, 0x10, 0x00, 0x80, 0x08, 0x84, 0x01, 0x04, 0x14, 0x00, 0x06, +0x10, 0x00, 0x80, 0x09, 0xd5, 0x24, 0x44, 0x00, 0x00, 0x21, 0x14, 0x74, 0x00, 0x06, 0x10, 0x03, +0x80, 0x08, 0x00, 0x03, 0x80, 0x09, 0x04, 0x14, 0x00, 0x06, 0x10, 0x00, 0x80, 0x09, 0x84, 0xa3, +0xd8, 0x13, 0xb4, 0x27, 0x84, 0xa5, 0xa6, 0x48, 0xd9, 0x04, 0x04, 0x14, 0x00, 0x0b, 0xd5, 0x0a, +0x00, 0x03, 0x00, 0x19, 0x84, 0xa1, 0xd8, 0x08, 0x84, 0xab, 0xd9, 0x06, 0x04, 0x14, 0x00, 0x0b, +0x84, 0x05, 0x14, 0x00, 0x80, 0x0d, 0x84, 0x01, 0x10, 0x03, 0x00, 0x21, 0x00, 0xa3, 0x00, 0x1a, +0x46, 0x90, 0x00, 0xbc, 0x58, 0x94, 0x8d, 0x58, 0x84, 0x03, 0x80, 0x2a, 0x4b, 0xe0, 0x24, 0x01, +0xc8, 0x19, 0x80, 0x2a, 0x44, 0x00, 0x00, 0x55, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x09, 0x50, 0x03, +0x7f, 0x64, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x8f, 0x64, 0xdd, 0x2f, 0xc8, 0x0b, 0x00, 0x03, +0x00, 0x17, 0x84, 0xac, 0xd8, 0x05, 0xa4, 0x33, 0x54, 0x00, 0x01, 0x00, 0xc0, 0x03, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0x04, 0x14, 0x00, 0x0b, 0x84, 0x4c, 0x10, 0x00, 0x80, 0x27, 0x00, 0x03, +0x00, 0x18, 0x4c, 0x01, 0x40, 0x06, 0xa4, 0x33, 0x58, 0x00, 0x01, 0x00, 0xac, 0x33, 0x00, 0x33, +0x00, 0x1a, 0xcf, 0x03, 0x80, 0x87, 0xd5, 0x03, 0x00, 0x43, 0x80, 0x09, 0x84, 0x06, 0x84, 0x21, +0x44, 0x20, 0x70, 0x68, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x84, 0xc0, 0x50, 0x0f, +0x80, 0x04, 0xf6, 0x81, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x80, 0x9f, 0x84, 0x01, 0xdd, 0x21, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xa6, 0x44, 0x10, +0x00, 0xc8, 0x44, 0x00, 0x00, 0x20, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, 0x80, 0xbc, +0x84, 0x21, 0x80, 0x06, 0x44, 0x20, 0x00, 0xc8, 0xdd, 0x23, 0x46, 0x10, 0x04, 0xa0, 0x46, 0x00, +0x04, 0x90, 0x04, 0x30, 0x80, 0x92, 0x04, 0x40, 0x00, 0x0e, 0x96, 0xd9, 0x84, 0x07, 0x44, 0x10, +0x08, 0x00, 0x44, 0x20, 0x90, 0x4e, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x17, 0x81, 0x84, 0x96, 0x4c, 0xc1, 0x62, 0x46, 0xf0, 0x01, 0x10, +0x04, 0x27, 0x81, 0x70, 0x54, 0x21, 0x00, 0x80, 0xc2, 0x5b, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x17, +0x86, 0x60, 0xc1, 0x56, 0xe6, 0x1a, 0xe8, 0x54, 0x84, 0x21, 0x46, 0x30, 0x24, 0x80, 0x40, 0x10, +0x80, 0x0c, 0x40, 0x20, 0x8c, 0x02, 0xca, 0x05, 0x54, 0x10, 0x80, 0x82, 0xc9, 0x21, 0xd5, 0x48, +0x46, 0x10, 0x04, 0xa0, 0x04, 0x20, 0x80, 0x92, 0x54, 0x31, 0x02, 0x00, 0xc3, 0x41, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x47, 0x80, 0xd9, 0x46, 0x30, 0x0c, 0x00, 0x58, 0x31, 0x88, 0x00, 0x96, 0x90, +0x50, 0x21, 0x01, 0x00, 0x40, 0x42, 0x0c, 0x04, 0x40, 0x42, 0x08, 0x04, 0x14, 0x40, 0x80, 0x92, +0x96, 0xc1, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x72, 0xd5, 0x24, 0x46, 0x10, +0x04, 0xa0, 0x04, 0x10, 0x80, 0x92, 0x54, 0x20, 0x82, 0x00, 0xc2, 0x22, 0x96, 0x48, 0xc1, 0x03, +0x9e, 0x49, 0x96, 0x48, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x47, 0x80, 0xd9, 0x46, 0x20, 0x0c, 0x00, +0x58, 0x21, 0x08, 0x00, 0x50, 0x10, 0x81, 0x00, 0x40, 0x42, 0x08, 0x04, 0x46, 0x20, 0x04, 0xa0, +0x40, 0x42, 0x04, 0x04, 0x14, 0x41, 0x00, 0x92, 0x96, 0xc1, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, +0x44, 0x20, 0x90, 0x73, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x97, 0x81, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x80, 0xa7, 0x96, 0x49, 0x80, 0x06, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x10, +0x00, 0x07, 0x86, 0x78, 0xc0, 0x2b, 0x44, 0x50, 0x00, 0x20, 0xde, 0x03, 0x84, 0x2f, 0xd5, 0x02, +0x96, 0x70, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x05, 0xc0, 0x10, 0x11, 0x00, 0x1b, 0x10, 0x11, +0x00, 0x0c, 0x10, 0x11, 0x00, 0x0d, 0x10, 0x11, 0x00, 0x0e, 0x10, 0x11, 0x00, 0x0f, 0x10, 0x11, +0x00, 0x10, 0x10, 0x11, 0x00, 0x11, 0x10, 0x11, 0x00, 0x12, 0x10, 0x11, 0x00, 0x13, 0x10, 0x11, +0x00, 0x14, 0x10, 0x11, 0x00, 0x15, 0x10, 0x11, 0x00, 0x16, 0x10, 0x11, 0x00, 0x17, 0x10, 0x11, +0x00, 0x18, 0x10, 0x11, 0x00, 0x19, 0x10, 0x11, 0x00, 0x1a, 0x44, 0x50, 0x00, 0xff, 0xd6, 0x1a, +0x5c, 0xf3, 0x00, 0x20, 0xe9, 0x17, 0x46, 0x70, 0x01, 0x38, 0x00, 0x43, 0x8a, 0x01, 0x84, 0x07, +0x44, 0x10, 0x10, 0x00, 0x44, 0x20, 0x90, 0x76, 0x80, 0x66, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x85, 0x60, 0xdd, 0x2f, 0x84, 0x20, 0x10, 0x63, 0x8a, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x17, +0x82, 0x83, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x85, 0x20, 0x00, 0x70, 0x00, 0x29, 0x50, 0x60, 0x00, 0x24, 0x81, 0x49, 0x47, 0xc0, 0x01, 0x06, +0xe4, 0xe8, 0xe9, 0x03, 0x84, 0xe1, 0xd5, 0x03, 0x9d, 0xf9, 0x97, 0xf8, 0x80, 0x07, 0x46, 0xf0, +0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0xc0, 0x56, 0xb4, 0x20, 0x54, 0x10, 0xff, 0xc1, +0xc1, 0x52, 0x04, 0x10, 0x00, 0x6c, 0xc1, 0x1d, 0xa6, 0x77, 0x9c, 0x49, 0x96, 0x88, 0xae, 0xb7, +0x46, 0xf0, 0x01, 0x08, 0x00, 0x37, 0x8f, 0x8a, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x17, 0x8f, 0x8d, +0x9a, 0x59, 0x96, 0x48, 0xe2, 0x41, 0xe9, 0x05, 0x10, 0xa3, 0x00, 0x06, 0x10, 0xa3, 0x00, 0x07, +0x04, 0x1e, 0x03, 0xfc, 0x96, 0x4c, 0xc1, 0x1d, 0x44, 0x10, 0x00, 0x11, 0xa8, 0x44, 0xd5, 0x19, +0xa6, 0x36, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x57, 0x8f, 0x8a, 0x46, 0xf0, 0x01, 0x08, +0x00, 0x07, 0x8f, 0x8d, 0xd8, 0x28, 0x84, 0x01, 0xae, 0x36, 0x10, 0xa3, 0x00, 0x07, 0x04, 0x0e, +0x03, 0xfc, 0x96, 0x04, 0xc0, 0x06, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x89, 0x28, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x81, 0x05, 0x84, 0x2a, 0x50, 0x03, 0x7f, 0xdc, 0x80, 0x47, +0xdd, 0x23, 0xc8, 0x11, 0x84, 0x0a, 0x14, 0x03, 0x7f, 0xfa, 0xaf, 0xf5, 0x80, 0x07, 0x46, 0xf0, +0x00, 0x14, 0x58, 0xf7, 0x89, 0xb4, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x06, 0x58, 0x10, 0x8f, 0xf0, +0xc8, 0x0c, 0xd5, 0x12, 0xa6, 0x35, 0x4c, 0x03, 0x80, 0x1a, 0x8d, 0x21, 0x54, 0x94, 0x80, 0xff, +0x84, 0xa9, 0x4c, 0x92, 0xff, 0x97, 0xd5, 0x12, 0x00, 0x00, 0x80, 0x28, 0xa0, 0x4d, 0x94, 0x03, +0x98, 0x08, 0xa6, 0x03, 0xd5, 0x07, 0x00, 0x00, 0x80, 0x28, 0xa0, 0x4d, 0x94, 0x03, 0x98, 0x08, +0xa6, 0x05, 0x14, 0x03, 0x7f, 0xff, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x01, 0x08, +0x00, 0x27, 0x8f, 0x8f, 0x84, 0x20, 0x10, 0x1f, 0x80, 0x07, 0x80, 0xc0, 0x10, 0x1f, 0x80, 0x06, +0xc2, 0x08, 0x46, 0xf0, 0x00, 0x15, 0x58, 0xf7, 0x85, 0xc0, 0xdd, 0x2f, 0x10, 0x0f, 0x80, 0x07, +0x00, 0x0f, 0x80, 0x07, 0xc8, 0x09, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x14, 0x58, 0xf7, 0x86, 0x2c, +0xdd, 0x2f, 0x10, 0x0f, 0x80, 0x07, 0x00, 0x0f, 0x80, 0x07, 0xc8, 0x26, 0x46, 0xf0, 0x01, 0x08, +0x00, 0x07, 0x8f, 0x8f, 0xc0, 0x0a, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xbe, 0x58, 0xf7, 0x88, 0xbc, +0xdd, 0x2f, 0x10, 0x0f, 0x80, 0x07, 0xd5, 0x18, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x17, 0x87, 0x7c, +0x10, 0x13, 0x00, 0x29, 0x84, 0x2a, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x27, 0x87, 0x7c, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x37, 0x81, 0x05, 0x80, 0x06, 0xdd, 0x23, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x81, 0x08, 0x80, 0x06, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0xc0, 0x13, +0x00, 0x1f, 0x80, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x15, 0x58, 0xf7, 0x84, 0x1c, 0xdd, 0x2f, +0x00, 0x1f, 0x80, 0x07, 0xc1, 0x03, 0x84, 0x01, 0xd5, 0x03, 0x40, 0x00, 0x80, 0x06, 0x96, 0x00, +0x10, 0x0f, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x23, 0xc0, 0x0b, 0x00, 0x1f, +0x80, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x14, 0x58, 0xf7, 0x86, 0xd8, 0xdd, 0x2f, 0x10, 0x0f, +0x80, 0x06, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0xc0, 0x0f, 0xa0, 0x33, 0x84, 0xae, +0xd0, 0x0e, 0x00, 0x03, 0x00, 0x31, 0x00, 0x13, 0x00, 0x32, 0x9c, 0x01, 0x96, 0x00, 0x10, 0x03, +0x00, 0x31, 0xe2, 0x20, 0xe8, 0x04, 0x84, 0x00, 0x10, 0x03, 0x00, 0x31, 0x00, 0x0f, 0x80, 0x07, +0xc8, 0x04, 0x00, 0x0f, 0x80, 0x06, 0xc0, 0x10, 0x00, 0x43, 0x00, 0x29, 0xa4, 0xf6, 0x84, 0x06, +0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x8e, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, +0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x10, 0x00, 0x43, 0x00, 0x29, 0xa4, 0xf6, 0x84, 0x06, 0x44, 0x11, +0x00, 0x00, 0x44, 0x20, 0x70, 0x8f, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, +0x44, 0x00, 0x00, 0x1f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0xbc, 0x97, 0xd1, 0x40, 0x10, 0x9c, 0x04, 0x54, 0xa0, 0x80, 0x01, 0x50, 0x60, 0x00, 0xac, +0x96, 0xd9, 0x40, 0x82, 0x00, 0x13, 0x4e, 0xa3, 0x00, 0x55, 0xc3, 0x53, 0x12, 0x30, 0x00, 0x60, +0x00, 0x00, 0x01, 0xae, 0x80, 0x2a, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x88, 0xec, 0xdd, 0x2f, +0x02, 0x93, 0x00, 0x0a, 0x42, 0x40, 0x6c, 0x0b, 0x89, 0x29, 0x40, 0x94, 0x80, 0x13, 0x12, 0x83, +0x00, 0x0c, 0xad, 0xf7, 0x54, 0x84, 0x80, 0xff, 0x10, 0x43, 0x00, 0x22, 0xa4, 0x76, 0x80, 0x47, +0x80, 0x0a, 0x46, 0x70, 0x00, 0x24, 0x58, 0x73, 0x82, 0x88, 0x80, 0x68, 0x4b, 0xe0, 0x1c, 0x01, +0xc8, 0x0a, 0xa4, 0x76, 0xa4, 0xb7, 0x00, 0x43, 0x00, 0x22, 0x84, 0x01, 0x80, 0x68, 0x4b, 0xe0, +0x1c, 0x01, 0xc0, 0x29, 0xa5, 0xf7, 0x44, 0x00, 0x00, 0x10, 0x8a, 0xe9, 0x42, 0x73, 0x80, 0x01, +0x97, 0xf9, 0x46, 0xa0, 0x00, 0x24, 0x58, 0xa5, 0x02, 0x88, 0xd5, 0x14, 0xa4, 0xb7, 0x00, 0x43, +0x00, 0x22, 0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x0c, 0xa4, 0xb7, 0x00, 0x43, 0x00, 0x22, 0x80, 0x27, +0x84, 0x01, 0x80, 0x68, 0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x03, 0xad, 0xf6, 0xd5, 0x0c, 0x8a, 0xe9, +0x97, 0xf9, 0x80, 0x27, 0x80, 0x68, 0x84, 0x00, 0xcf, 0xea, 0xad, 0xf6, 0x80, 0x07, 0xd5, 0x03, +0x44, 0x00, 0x00, 0x1e, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x97, 0xc0, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0x50, 0x60, +0x01, 0xe3, 0xc0, 0x62, 0x00, 0x00, 0x01, 0xea, 0x46, 0x20, 0x01, 0x13, 0x58, 0x21, 0x04, 0x70, +0xc8, 0x28, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x81, 0xdd, 0x44, 0x00, 0x00, 0x30, 0x42, 0x13, +0x80, 0x73, 0x84, 0x02, 0xae, 0x10, 0x84, 0xa2, 0xa0, 0xc9, 0xdb, 0x21, 0x04, 0x00, 0x80, 0x0a, +0x84, 0x25, 0x00, 0x40, 0x00, 0x31, 0x80, 0xa0, 0x42, 0x52, 0x04, 0x73, 0x00, 0x12, 0x80, 0x35, +0xc1, 0x16, 0x00, 0x00, 0x00, 0x2c, 0x44, 0x10, 0xcf, 0x18, 0x54, 0x00, 0x00, 0x0f, 0x40, 0x00, +0x80, 0x0e, 0x96, 0x04, 0xc0, 0x0c, 0x44, 0x00, 0x00, 0x28, 0xae, 0x10, 0xae, 0xf7, 0xd5, 0x07, +0x44, 0x00, 0x00, 0x28, 0xae, 0x10, 0xa6, 0x37, 0x9e, 0x01, 0xae, 0x37, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x07, 0x88, 0x36, 0xc0, 0x0e, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, +0x84, 0xa2, 0xd8, 0x07, 0x44, 0x10, 0x00, 0x28, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x17, 0x84, 0x70, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x80, 0xc0, 0xdd, 0x20, 0xc0, 0x03, 0x84, 0x00, 0xae, 0x37, +0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xfc, 0x96, 0x04, 0xc0, 0x0e, 0x46, 0xf0, 0x01, 0x08, +0x00, 0x07, 0x8f, 0x8f, 0xe6, 0x02, 0xe9, 0x08, 0x84, 0x22, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x17, +0x84, 0x70, 0x84, 0x00, 0xae, 0x37, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x54, 0x80, 0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0xc0, 0x6f, +0x00, 0x00, 0x01, 0xae, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x17, 0x86, 0x04, 0x46, 0xf0, 0x00, 0x28, +0x58, 0xf7, 0x84, 0xa4, 0xdd, 0x2f, 0xc0, 0x07, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x77, 0x81, 0x80, +0x84, 0xbf, 0xdf, 0x12, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x08, 0x14, 0x07, 0x81, 0x80, 0x00, 0x63, 0x01, 0xae, 0x46, 0xf0, 0x01, 0x08, +0x10, 0x67, 0x86, 0x04, 0xd5, 0x4c, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x07, 0x85, 0xf9, 0xc8, 0x47, +0x46, 0xf0, 0x01, 0x06, 0x04, 0x17, 0x83, 0xfc, 0x96, 0x4c, 0xc1, 0x41, 0x4e, 0x92, 0x00, 0x40, +0x4e, 0x83, 0x00, 0x07, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x20, 0xc0, 0x38, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x80, 0xe0, 0x00, 0x03, 0x01, 0xae, +0x46, 0xf0, 0x01, 0x08, 0x04, 0x67, 0x81, 0x80, 0x46, 0xf0, 0x00, 0x14, 0x58, 0xf7, 0x89, 0xb4, +0xdd, 0x2f, 0x46, 0x10, 0x01, 0x06, 0x58, 0x10, 0x8f, 0xf0, 0xc0, 0x08, 0x00, 0x00, 0x80, 0x28, +0xa0, 0x4d, 0x94, 0x03, 0x98, 0x08, 0xa6, 0x42, 0xd5, 0x07, 0x00, 0x00, 0x80, 0x28, 0xa0, 0x4d, +0x94, 0x03, 0x98, 0x08, 0xa6, 0x44, 0x9a, 0x3e, 0x94, 0x04, 0x92, 0x04, 0x92, 0x01, 0xe2, 0x20, +0xe8, 0x0e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x81, 0x06, 0x84, 0x00, 0x80, 0x20, 0x80, 0x40, +0xdd, 0x23, 0x84, 0x3f, 0x46, 0xf0, 0x01, 0x08, 0x14, 0x17, 0x81, 0x80, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x97, 0x80, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x8c, 0xb0, 0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x03, 0x84, 0x00, 0xd5, 0x07, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x2f, 0x58, 0xf7, 0x89, 0xac, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x40, 0x50, 0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, +0x46, 0x20, 0x40, 0x00, 0x80, 0x60, 0xda, 0x57, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x05, 0xc0, +0x44, 0x00, 0x00, 0x4f, 0x54, 0x11, 0x80, 0x10, 0x10, 0x01, 0x00, 0x26, 0x10, 0x01, 0x00, 0x23, +0x10, 0x01, 0x00, 0x24, 0x10, 0x01, 0x00, 0x25, 0xc1, 0x37, 0x46, 0x00, 0x00, 0x5c, 0x58, 0x00, +0x04, 0x08, 0x54, 0x11, 0x80, 0x0f, 0x38, 0x40, 0x04, 0x00, 0x00, 0x01, 0x00, 0x27, 0xe2, 0x80, +0xe9, 0x03, 0x9a, 0x20, 0xd5, 0x02, 0x84, 0x00, 0x10, 0x01, 0x00, 0x23, 0x80, 0x02, 0x00, 0x20, +0x00, 0x27, 0x99, 0x22, 0x5e, 0xf2, 0x00, 0x50, 0xe8, 0x04, 0x10, 0x40, 0x00, 0x24, 0xd5, 0x05, +0x44, 0x20, 0x00, 0x4f, 0x10, 0x20, 0x00, 0x24, 0x54, 0x31, 0x80, 0x80, 0x46, 0x00, 0x01, 0x38, +0xc3, 0x05, 0x84, 0x41, 0x10, 0x20, 0x09, 0xf0, 0xd5, 0x0f, 0x10, 0x30, 0x09, 0xf0, 0x46, 0x00, +0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x00, 0x20, 0x00, 0x24, 0x10, 0x20, 0x00, 0x26, 0x00, 0x20, +0x00, 0x23, 0x10, 0x20, 0x00, 0x25, 0x96, 0x48, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x88, 0x0c, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xdc, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x07, 0x81, 0x70, +0xdd, 0x22, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x48, 0x58, 0xf7, 0x81, 0xb0, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x96, 0x48, 0x9e, 0x89, 0x96, 0x90, +0xe6, 0x4e, 0xe9, 0x0f, 0x46, 0x10, 0x01, 0x13, 0x04, 0x20, 0x81, 0x6c, 0x46, 0x60, 0x00, 0x5c, +0x58, 0x63, 0x04, 0x18, 0x58, 0x21, 0x04, 0x00, 0x14, 0x20, 0x81, 0x6c, 0x84, 0x20, 0xd5, 0x2a, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, 0x89, 0xf0, 0x84, 0xa1, 0xda, 0x1c, 0x9e, 0x8b, 0x96, 0x90, +0xe6, 0x47, 0xe9, 0x0e, 0x46, 0x20, 0x01, 0x13, 0x04, 0x31, 0x01, 0x6c, 0x46, 0x60, 0x00, 0x5c, +0x58, 0x63, 0x04, 0x18, 0x58, 0x31, 0x84, 0x00, 0x14, 0x31, 0x01, 0x6c, 0xd5, 0x13, 0x84, 0xca, +0x42, 0x60, 0x98, 0x24, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xa0, 0x8e, 0xde, 0x99, 0xb2, +0xd5, 0x09, 0x84, 0xca, 0x42, 0x60, 0x98, 0x24, 0x46, 0x30, 0x00, 0x5c, 0x58, 0x31, 0x84, 0x18, +0x99, 0xb3, 0x54, 0x20, 0x00, 0x80, 0xc2, 0x22, 0x96, 0x04, 0xc8, 0x06, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x07, 0x86, 0x3d, 0xc0, 0x1b, 0xc1, 0x1a, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x86, 0x3c, +0xc0, 0x06, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x57, 0x80, 0xde, 0xd6, 0x32, 0x84, 0x21, 0x46, 0xf0, +0x01, 0x01, 0x10, 0x17, 0x86, 0x3c, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x67, 0x80, 0xde, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x83, 0xaa, 0x84, 0x21, 0xd5, 0x12, 0x46, 0x00, 0x01, 0x01, 0x00, 0x10, +0x06, 0x3c, 0x84, 0xa1, 0xd9, 0x1d, 0x84, 0x40, 0x10, 0x20, 0x06, 0x3c, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x67, 0x80, 0xde, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0xaa, 0x80, 0x06, 0xdd, 0x22, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x4a, 0x58, 0xf7, 0x80, 0x70, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x37, 0x80, 0xb1, 0x80, 0x46, 0x44, 0x00, 0x00, 0x46, 0x84, 0x20, 0xdd, 0x23, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc0, 0xc0, 0x65, 0x85, 0x00, +0x44, 0x00, 0x00, 0x10, 0xb6, 0x06, 0x10, 0x83, 0x01, 0xa8, 0x10, 0x83, 0x01, 0xa9, 0x10, 0x83, +0x01, 0xaa, 0x10, 0x83, 0x01, 0xab, 0x10, 0x83, 0x01, 0xac, 0x10, 0x83, 0x01, 0xad, 0x46, 0x70, +0x00, 0x26, 0x58, 0x73, 0x86, 0x64, 0x50, 0x03, 0x01, 0xe1, 0xdd, 0x27, 0x50, 0x03, 0x01, 0xf4, +0xdd, 0x27, 0x50, 0x03, 0x01, 0xe3, 0xdd, 0x27, 0x50, 0x03, 0x01, 0xe4, 0xdd, 0x27, 0x50, 0x03, +0x01, 0xf0, 0xdd, 0x27, 0x50, 0x03, 0x01, 0xf1, 0xdd, 0x27, 0x50, 0x03, 0x01, 0xf2, 0xdd, 0x27, +0x50, 0x03, 0x01, 0xf3, 0xdd, 0x27, 0x50, 0x03, 0x00, 0xf5, 0xdd, 0x27, 0x50, 0x03, 0x01, 0xfb, +0xdd, 0x27, 0x50, 0x03, 0x01, 0xe5, 0xdd, 0x27, 0x84, 0x1f, 0x14, 0x03, 0x00, 0x0a, 0x10, 0x83, +0x01, 0xe8, 0x10, 0x83, 0x01, 0xe7, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x97, 0x02, 0x03, +0x00, 0xc4, 0xdd, 0x21, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x88, 0xb0, 0xdd, 0x2f, +0x00, 0x03, 0x01, 0xae, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x8b, 0xfc, 0xdd, 0x2f, 0x00, 0x03, +0x01, 0xc4, 0x46, 0x10, 0x01, 0x07, 0x58, 0x10, 0x83, 0xd0, 0x40, 0x00, 0x24, 0x08, 0x98, 0x01, +0x10, 0x80, 0x00, 0x00, 0x84, 0x40, 0x00, 0x13, 0x01, 0xae, 0x46, 0x00, 0x01, 0x08, 0x58, 0x00, +0x05, 0xd0, 0x38, 0x20, 0x06, 0x0a, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x0b, 0x5c, 0x00, 0x10, 0x00, 0x27, +0x84, 0xa1, 0xd9, 0x37, 0xa0, 0x42, 0xc1, 0x0e, 0xa0, 0x03, 0xc0, 0x0c, 0x84, 0xa2, 0xd0, 0x03, +0x8c, 0xbe, 0xd8, 0x2f, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x8d, 0x50, 0xdd, 0x2f, 0x84, 0xaa, +0xd8, 0x28, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0xdd, 0x46, 0xf0, 0x01, 0x01, 0x02, 0x27, +0x83, 0xbe, 0x44, 0x10, 0x00, 0x30, 0x42, 0x01, 0x04, 0x73, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x17, +0x82, 0xd7, 0x00, 0x00, 0x00, 0x21, 0x00, 0x50, 0x80, 0x21, 0xd8, 0x13, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x80, 0xc2, 0x84, 0x02, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0x44, 0x10, 0x00, 0x10, 0x84, 0x03, 0x44, 0x20, 0x10, 0x56, 0x84, 0x60, 0xdd, 0x24, 0xd5, 0x07, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xc2, 0x84, 0x00, 0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xe1, 0x04, 0x10, +0x00, 0x6c, 0x80, 0xc0, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x83, 0x08, 0xdd, 0x2f, +0xb4, 0x06, 0x54, 0x10, 0x00, 0x80, 0xc1, 0x04, 0x44, 0x00, 0x00, 0x80, 0xd5, 0x0a, 0x54, 0x30, +0x40, 0x00, 0x84, 0x21, 0x44, 0x20, 0x40, 0x00, 0x40, 0x01, 0x0c, 0x1b, 0x40, 0x00, 0x8c, 0x1a, +0x58, 0x00, 0x00, 0x01, 0xb6, 0x06, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x8d, 0x50, 0xdd, 0x2f, +0x84, 0xaa, 0xd0, 0x07, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x8d, 0x7c, 0xdd, 0x2f, 0xc0, 0x1c, +0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x88, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, +0x8d, 0x50, 0xdd, 0x2f, 0x84, 0xaa, 0xd8, 0x10, 0x04, 0x53, 0x00, 0x6c, 0x84, 0x21, 0xd9, 0x0c, +0x04, 0x23, 0x00, 0x2c, 0x00, 0x03, 0x01, 0xae, 0x98, 0x91, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x28, +0x58, 0xf7, 0x8b, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0x8b, 0x84, 0x28, +0x80, 0x06, 0xdd, 0x22, 0x80, 0x06, 0x84, 0x28, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x21, 0x58, 0xf7, +0x84, 0x78, 0xdd, 0x2f, 0x04, 0x03, 0x00, 0x6c, 0x84, 0xa1, 0xd8, 0x04, 0x84, 0x00, 0x12, 0x03, +0x00, 0x61, 0x80, 0x06, 0x80, 0x47, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x20, 0x58, 0xf7, 0x8b, 0x44, +0xdd, 0x2f, 0x04, 0x03, 0x00, 0x3c, 0xc0, 0x0d, 0x84, 0x00, 0x14, 0x03, 0x00, 0x3c, 0x46, 0xf0, +0x01, 0x08, 0x00, 0x17, 0x8f, 0x83, 0x9e, 0x49, 0x46, 0xf0, 0x01, 0x08, 0x10, 0x17, 0x8f, 0x83, +0x04, 0x13, 0x00, 0x2a, 0xc1, 0x0a, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x8f, 0x70, +0xdd, 0x2f, 0x84, 0x00, 0x14, 0x03, 0x00, 0x2a, 0x00, 0x23, 0x01, 0xae, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x07, 0x81, 0xdd, 0x44, 0x10, 0x00, 0x30, 0x42, 0x01, 0x04, 0x73, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x87, 0x3c, 0xdd, 0x2f, 0x00, 0x03, 0x01, 0xae, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x8c, 0x54, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x81, 0x06, 0x46, 0xf0, +0x01, 0x01, 0x00, 0x17, 0x85, 0xc2, 0x84, 0x40, 0x80, 0x06, 0xdd, 0x23, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x80, 0x9b, 0x46, 0x00, 0x0f, 0xff, 0x58, 0x00, 0x0f, 0xff, 0xdd, 0x21, 0xc6, 0x0b, +0x00, 0x03, 0x00, 0xf5, 0xc0, 0x08, 0x50, 0x03, 0x00, 0xf5, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x86, 0x64, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe0, 0xf1, 0x81, 0x83, 0x82, 0x84, 0x01, 0x84, 0x20, 0x44, 0x20, +0x00, 0x1b, 0x81, 0x44, 0x81, 0x25, 0x40, 0x81, 0x80, 0x13, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, +0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x31, 0xb4, 0xc0, 0x84, 0x0e, 0xae, 0x30, 0x8c, 0x0b, 0xae, 0x31, +0x84, 0x01, 0xae, 0x32, 0x44, 0x0f, 0xff, 0x9e, 0xae, 0x33, 0x84, 0x1c, 0xae, 0x34, 0x80, 0x27, +0x9c, 0x35, 0x46, 0x70, 0x00, 0x0d, 0x58, 0x73, 0x80, 0x48, 0xdd, 0x27, 0xf1, 0x01, 0x50, 0x03, +0x00, 0x09, 0xdd, 0x27, 0x80, 0x3c, 0x50, 0x03, 0x00, 0x0d, 0xdd, 0x27, 0x40, 0x04, 0x20, 0x09, +0x10, 0x03, 0x00, 0x12, 0x10, 0x83, 0x00, 0x11, 0x80, 0x2a, 0x50, 0x03, 0x00, 0x13, 0xdd, 0x27, +0x50, 0x03, 0x00, 0x17, 0x80, 0x29, 0xdd, 0x27, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xf4, 0x80, 0xc0, 0x80, 0x1e, 0xf0, 0x81, 0x80, 0x1f, 0xb6, 0x1f, 0x46, 0x00, +0x01, 0x00, 0x58, 0x00, 0x0f, 0x54, 0xb4, 0x80, 0x84, 0x21, 0x84, 0x04, 0x44, 0x20, 0x30, 0x01, +0x80, 0x66, 0xdd, 0x24, 0x44, 0x00, 0x00, 0xc8, 0x4c, 0x60, 0x00, 0x33, 0x44, 0x00, 0x00, 0xcc, +0x4c, 0x60, 0x00, 0x2f, 0x46, 0x90, 0x01, 0x13, 0x58, 0x94, 0x85, 0x7c, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x0b, 0x30, 0xf1, 0x01, 0xb4, 0x89, 0xb4, 0x5f, 0x04, 0x54, 0x00, 0x0a, 0x84, 0x00, +0x46, 0x70, 0x00, 0xbf, 0x58, 0x73, 0x82, 0xd0, 0x96, 0xf1, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, +0x00, 0xd6, 0x4c, 0x60, 0x40, 0x16, 0x46, 0xf0, 0x00, 0x3f, 0x58, 0xf7, 0x8e, 0x58, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x3d, 0x58, 0xf7, 0x86, 0x60, 0xdd, 0x2f, 0x84, 0x00, 0xb4, 0x89, 0x04, 0x54, +0x00, 0x0a, 0x80, 0x20, 0x80, 0x40, 0x44, 0x30, 0xff, 0xff, 0x4b, 0xe0, 0x1c, 0x01, 0xec, 0x0c, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x85, 0x23, 0x97, 0xc8, +0x42, 0x93, 0xa4, 0x24, 0x80, 0xc0, 0x80, 0x27, 0x46, 0x00, 0x00, 0xd1, 0x58, 0x00, 0x0e, 0x74, +0x89, 0x29, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x89, 0xd0, 0xdd, 0x2f, 0x50, 0x83, 0x00, 0x20, +0x50, 0x03, 0x00, 0x08, 0x89, 0x09, 0x89, 0x20, 0xcf, 0x03, 0x81, 0x49, 0xd5, 0x06, 0x9f, 0xf9, +0x97, 0xf8, 0xe6, 0xe2, 0xe8, 0x56, 0x81, 0x48, 0x46, 0x30, 0x01, 0x38, 0x58, 0x31, 0x8a, 0x8c, +0x50, 0x41, 0x80, 0x18, 0x46, 0x00, 0x00, 0xd1, 0x58, 0x00, 0x0e, 0xb4, 0x80, 0x29, 0x80, 0x48, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x89, 0xd0, 0xdd, 0x2f, 0x01, 0xc3, 0x00, 0x1c, 0xa6, 0x74, +0x84, 0x01, 0x41, 0xc0, 0x70, 0x0c, 0x40, 0x10, 0x04, 0x0c, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, +0x01, 0xbc, 0x40, 0x40, 0x84, 0x05, 0x40, 0x3e, 0x70, 0x05, 0x84, 0xe0, 0x46, 0x20, 0x00, 0x02, +0x58, 0x21, 0x0e, 0xb8, 0x39, 0xe4, 0x9c, 0x01, 0x38, 0x05, 0x1c, 0x01, 0x38, 0x54, 0x1c, 0x01, +0x41, 0xef, 0x3c, 0x09, 0x54, 0x00, 0x7f, 0xff, 0x92, 0xaf, 0x4f, 0xe2, 0x00, 0x07, 0x05, 0xe3, +0x00, 0x00, 0x41, 0xe0, 0xf8, 0x04, 0xd5, 0x05, 0x05, 0xe3, 0x00, 0x00, 0x41, 0xe2, 0x78, 0x02, +0x15, 0xe3, 0x00, 0x00, 0xc5, 0x05, 0xb4, 0xa6, 0x40, 0x5e, 0x14, 0x04, 0xd5, 0x04, 0xb4, 0xa6, +0x40, 0x51, 0x94, 0x02, 0xb6, 0xa6, 0xf1, 0x81, 0xb6, 0x5f, 0xf3, 0x83, 0xf4, 0x82, 0x94, 0x05, +0xdd, 0x22, 0x9d, 0xfa, 0x84, 0xa6, 0xf1, 0x01, 0xb4, 0x5f, 0xf3, 0x03, 0xf4, 0x02, 0xdf, 0xd3, +0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0xa6, 0x80, 0x96, 0x48, 0xca, 0x06, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x83, 0xf8, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x00, 0x1c, 0xb4, 0x06, 0x42, 0x00, 0x60, 0x0b, 0xc8, 0x55, +0x50, 0x73, 0x01, 0x14, 0xb4, 0x07, 0x44, 0x21, 0x00, 0x01, 0x40, 0x00, 0x08, 0x04, 0xb6, 0x07, +0x46, 0x90, 0x00, 0x02, 0x58, 0x94, 0x8e, 0xb8, 0x84, 0x01, 0x4b, 0xe0, 0x24, 0x01, 0xb4, 0x06, +0x92, 0x08, 0x40, 0x00, 0x20, 0x08, 0xb6, 0x06, 0x46, 0x80, 0x04, 0x00, 0xb4, 0x26, 0x58, 0x84, +0x01, 0x4c, 0x58, 0x10, 0x80, 0x30, 0xb6, 0x26, 0x84, 0x01, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, +0x83, 0x14, 0xdd, 0x2f, 0xb4, 0x28, 0x42, 0x10, 0xcc, 0x09, 0x42, 0x10, 0xd0, 0x09, 0xb6, 0x28, +0x84, 0x05, 0xb4, 0x27, 0x42, 0x10, 0xc4, 0x08, 0xb6, 0x27, 0x4b, 0xe0, 0x24, 0x01, 0xb4, 0x27, +0x42, 0x10, 0xc0, 0x09, 0xb6, 0x27, 0x84, 0x04, 0x4b, 0xe0, 0x24, 0x01, 0xb4, 0x06, 0x42, 0x00, +0x60, 0x0b, 0xc0, 0x05, 0xb4, 0x06, 0x42, 0x00, 0x64, 0x0b, 0xc0, 0x11, 0x46, 0x00, 0x00, 0xd1, +0x58, 0x00, 0x0f, 0x3c, 0x46, 0x10, 0x00, 0xd1, 0x58, 0x10, 0x8f, 0x4c, 0x44, 0x20, 0x06, 0x5a, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x89, 0xd0, 0xdd, 0x2f, 0xd5, 0x00, 0xb4, 0x08, 0x46, 0x10, +0x01, 0x80, 0x40, 0x00, 0x04, 0x04, 0xb6, 0x08, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0x7c, 0x80, 0xc0, 0xc0, 0x5a, 0x02, 0x00, 0x00, 0xc3, +0x84, 0x27, 0x4c, 0x00, 0x80, 0x90, 0x50, 0x73, 0x01, 0xa8, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x18, +0x58, 0xf7, 0x83, 0x3c, 0xdd, 0x2f, 0xc8, 0x05, 0x44, 0x00, 0x00, 0x17, 0x48, 0x00, 0x00, 0x84, +0xb4, 0x06, 0x44, 0x10, 0x02, 0x00, 0x4c, 0x00, 0xc0, 0x1c, 0x84, 0x00, 0x44, 0x10, 0x04, 0x11, +0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x84, 0x00, 0xb6, 0x1f, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x83, 0x77, 0x00, 0x03, 0x01, 0xd1, 0x80, 0x3f, 0x10, 0x0f, 0x80, 0x0a, +0x02, 0x03, 0x00, 0xc4, 0x12, 0x0f, 0x80, 0x06, 0x84, 0x06, 0xdd, 0x22, 0xd5, 0x70, 0x04, 0x13, +0x00, 0x08, 0xc1, 0x6d, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x17, 0x87, 0x3e, 0x54, 0x10, 0x86, 0x08, +0xc1, 0x66, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x87, 0x40, 0x96, 0x04, 0xc0, 0x60, 0x00, 0x03, +0x01, 0x22, 0x54, 0x00, 0x00, 0x08, 0xc0, 0x5b, 0x00, 0x03, 0x01, 0x14, 0x96, 0x04, 0xc0, 0x57, +0x00, 0x03, 0x01, 0x21, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x45, 0x80, 0x07, 0x84, 0x20, 0x50, 0x2f, +0x80, 0x4c, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x8d, 0xa4, 0xdd, 0x2f, 0xd5, 0x48, 0x44, 0x00, +0x00, 0x12, 0xd5, 0x39, 0x00, 0x23, 0x01, 0xf7, 0xca, 0x13, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, +0x81, 0x49, 0x46, 0x10, 0x00, 0x17, 0x58, 0x10, 0x87, 0xf4, 0x80, 0x66, 0x80, 0x82, 0x84, 0xa1, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x10, 0x03, 0x01, 0xf7, 0x84, 0x00, +0x44, 0x10, 0x04, 0x11, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x84, 0x0a, +0x10, 0x03, 0x01, 0xc9, 0x00, 0x03, 0x01, 0xb0, 0x10, 0x03, 0x01, 0xc8, 0x80, 0x06, 0x46, 0xf0, +0x00, 0x17, 0x58, 0xf7, 0x8e, 0x5c, 0xdd, 0x2f, 0xc8, 0x15, 0x84, 0x06, 0x10, 0x03, 0x01, 0xc9, +0x00, 0x13, 0x01, 0xb0, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8f, 0x08, 0xdd, 0x2f, +0xd5, 0x09, 0x84, 0x0c, 0x44, 0x10, 0x04, 0x11, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0x1c, +0xdd, 0x2f, 0x84, 0x00, 0xec, 0x84, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x04, 0x03, 0x00, 0x72, +0x40, 0x00, 0x20, 0x08, 0x92, 0x10, 0xc0, 0xb7, 0xd5, 0xed, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x97, 0xc0, 0x40, 0x63, 0x8c, 0x09, 0x5c, 0x03, 0x00, 0x0a, 0x84, 0x20, 0x44, 0x30, 0x23, 0x1e, +0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0x46, 0x30, 0x01, 0x0a, 0x58, 0x31, 0x8b, 0x24, 0x38, 0x41, 0x98, 0x00, 0x54, 0x03, +0x80, 0x07, 0x40, 0x12, 0x00, 0x0e, 0x96, 0x4c, 0xc1, 0x19, 0x46, 0x10, 0x01, 0x13, 0x46, 0x20, +0x01, 0x13, 0x00, 0x50, 0x84, 0x87, 0x84, 0xe1, 0x40, 0x03, 0x80, 0x0c, 0x00, 0x71, 0x04, 0x86, +0x40, 0x00, 0x00, 0x05, 0x99, 0x6d, 0x40, 0x40, 0x10, 0x02, 0x9d, 0xf9, 0x9d, 0x69, 0x38, 0x41, +0x98, 0x08, 0x10, 0x71, 0x04, 0x86, 0x10, 0x50, 0x84, 0x87, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0xf0, 0x00, 0xd2, 0x04, 0x37, 0x80, 0x7c, +0x46, 0xf0, 0x00, 0xd2, 0x04, 0x27, 0x80, 0x7b, 0x40, 0x51, 0xc0, 0x09, 0x40, 0x41, 0x40, 0x09, +0x50, 0x1f, 0x80, 0x0c, 0x50, 0x0f, 0x80, 0x08, 0x84, 0xe0, 0xaf, 0x46, 0xaf, 0x02, 0xac, 0xc8, +0xac, 0x80, 0x81, 0x07, 0x47, 0xc0, 0x01, 0x0a, 0x59, 0xce, 0x00, 0x6c, 0x46, 0xa0, 0x00, 0xbf, +0x58, 0xa5, 0x07, 0x2c, 0x38, 0x60, 0x9c, 0x00, 0x50, 0x0f, 0x80, 0x08, 0x38, 0x90, 0x1c, 0x00, +0x80, 0x06, 0xd5, 0x10, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x0b, 0x24, 0x38, 0x20, 0x08, 0x00, +0x96, 0x20, 0x40, 0x21, 0x14, 0x0e, 0x96, 0x94, 0xca, 0x03, 0x54, 0x81, 0x80, 0xff, 0xe7, 0x0b, +0xe8, 0x15, 0x40, 0x20, 0x0c, 0x09, 0x54, 0x50, 0x00, 0x07, 0x9d, 0x01, 0x50, 0x34, 0x00, 0x01, +0xe2, 0x09, 0xe9, 0xe9, 0xd5, 0x0d, 0x38, 0x0e, 0x18, 0x00, 0xc0, 0x06, 0x80, 0x06, 0xf1, 0x81, +0x4b, 0xe0, 0x28, 0x01, 0xf1, 0x01, 0x9d, 0xb1, 0x97, 0xb0, 0xe2, 0xc9, 0xe9, 0xf5, 0x9d, 0xf9, +0x84, 0x03, 0x4c, 0x70, 0x7f, 0xd1, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xe4, 0x4e, 0x03, 0x01, 0x88, 0x46, 0x20, 0x04, 0x03, 0x58, 0x21, 0x04, 0x7c, +0xb4, 0x22, 0x92, 0x28, 0x40, 0x10, 0xa0, 0x08, 0xb6, 0x22, 0xb4, 0x62, 0x9c, 0x14, 0x58, 0x31, +0x80, 0x26, 0xb6, 0x62, 0xb4, 0x60, 0x44, 0x6f, 0x00, 0xff, 0x92, 0x68, 0x40, 0x31, 0xa0, 0x08, +0xb6, 0x60, 0x46, 0x7f, 0x00, 0x0f, 0xb4, 0x60, 0x58, 0x73, 0x8f, 0xff, 0x58, 0x31, 0x80, 0x58, +0xb6, 0x60, 0x47, 0xc0, 0x7d, 0x00, 0xb4, 0x60, 0x40, 0x31, 0x98, 0x02, 0xb6, 0x60, 0xb4, 0x60, +0x9c, 0x44, 0x58, 0x31, 0xd8, 0x00, 0xb6, 0x60, 0xb4, 0x60, 0x9c, 0x8c, 0x40, 0x31, 0x9c, 0x02, +0xb6, 0x60, 0xb4, 0x60, 0x40, 0x31, 0xf0, 0x04, 0xb6, 0x60, 0xb4, 0x01, 0x50, 0x31, 0x00, 0x18, +0x92, 0x0c, 0x40, 0x00, 0x30, 0x08, 0xb6, 0x01, 0xf3, 0x84, 0xb4, 0x01, 0x80, 0x67, 0x58, 0x00, +0x00, 0x50, 0xb6, 0x01, 0xb4, 0x01, 0x51, 0xc1, 0x00, 0x24, 0x40, 0x00, 0x0c, 0x02, 0xb6, 0x01, +0x15, 0xcf, 0x80, 0x05, 0x46, 0x70, 0x05, 0x00, 0xb4, 0x01, 0x40, 0x00, 0x1c, 0x04, 0xb6, 0x01, +0xb4, 0x02, 0x9d, 0x14, 0x92, 0x0c, 0x40, 0x00, 0x30, 0x08, 0xb6, 0x02, 0xb4, 0x02, 0x58, 0x00, +0x07, 0xd0, 0xb6, 0x02, 0x51, 0xc2, 0x00, 0x8c, 0xb4, 0x04, 0x92, 0x0e, 0x40, 0x00, 0x38, 0x08, +0xb6, 0x04, 0x9d, 0x64, 0xb4, 0x04, 0x58, 0x00, 0x00, 0x50, 0xb6, 0x04, 0x15, 0xcf, 0x80, 0x01, +0x47, 0xcc, 0x00, 0x0f, 0xb4, 0x04, 0x59, 0xce, 0x0f, 0xff, 0x41, 0xc0, 0x70, 0x02, 0x15, 0xc2, +0x00, 0x00, 0x83, 0x87, 0xb4, 0x04, 0x41, 0xc0, 0x70, 0x04, 0x15, 0xc2, 0x00, 0x00, 0xb4, 0x05, +0x9d, 0xac, 0x41, 0xc0, 0x38, 0x09, 0x41, 0xce, 0x38, 0x08, 0x15, 0xc2, 0x80, 0x00, 0x47, 0xcf, +0xf0, 0x0f, 0xb4, 0x05, 0x59, 0xce, 0x0f, 0xff, 0x58, 0x00, 0x27, 0x10, 0xb6, 0x05, 0xb4, 0x05, +0x50, 0xa3, 0x00, 0x04, 0x41, 0xc0, 0x70, 0x02, 0x15, 0xc2, 0x80, 0x00, 0x47, 0xc0, 0x03, 0x20, +0xb4, 0x05, 0x41, 0xc0, 0x70, 0x04, 0x15, 0xc2, 0x80, 0x00, 0xb4, 0x06, 0x45, 0xcf, 0xc0, 0xff, +0x92, 0x04, 0x94, 0x04, 0xb6, 0x06, 0x46, 0x5f, 0xfc, 0x0f, 0xb4, 0x06, 0x58, 0x52, 0x8f, 0xff, +0x58, 0x00, 0x00, 0x05, 0xb6, 0x06, 0xb4, 0x06, 0x50, 0x95, 0x00, 0x04, 0x40, 0x00, 0x70, 0x02, +0xb6, 0x06, 0x47, 0xc0, 0x00, 0xf0, 0xb4, 0x06, 0x58, 0x00, 0x25, 0x00, 0xb6, 0x06, 0xb4, 0x06, +0x50, 0x84, 0x80, 0x0c, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x06, 0xb4, 0x06, 0x40, 0x00, 0x70, 0x04, +0xb6, 0x06, 0x44, 0x6f, 0x00, 0xff, 0xb4, 0x0a, 0x45, 0xc0, 0xc8, 0x00, 0x92, 0x07, 0x94, 0x07, +0xb6, 0x0a, 0x44, 0x5f, 0xff, 0x00, 0xb4, 0x0a, 0x51, 0xe4, 0x00, 0x08, 0x58, 0x00, 0x00, 0x3e, +0xb6, 0x0a, 0xb4, 0x0a, 0x50, 0x7f, 0x00, 0x5c, 0x40, 0x00, 0x18, 0x02, 0xb6, 0x0a, 0x44, 0x6f, +0xf0, 0xff, 0xb4, 0x0a, 0x40, 0x00, 0x70, 0x04, 0xb6, 0x0a, 0x9c, 0xfc, 0xb4, 0x09, 0x40, 0x00, +0x14, 0x02, 0xb6, 0x09, 0xb4, 0x09, 0x9c, 0x9c, 0x58, 0x00, 0x00, 0x7d, 0xb6, 0x09, 0xb4, 0x09, +0x50, 0x11, 0x00, 0x08, 0x40, 0x00, 0x18, 0x02, 0xb6, 0x09, 0x44, 0x6f, 0x00, 0xff, 0xb4, 0x09, +0x58, 0x00, 0x0a, 0x00, 0xb6, 0x09, 0x9d, 0x0c, 0x05, 0xcf, 0x80, 0x04, 0xb4, 0x1c, 0x40, 0x00, +0x14, 0x02, 0xb6, 0x1c, 0xb4, 0x1c, 0x58, 0x00, 0x00, 0x26, 0xb6, 0x1c, 0xb4, 0x08, 0x92, 0x06, +0x94, 0x06, 0xb6, 0x08, 0xb4, 0x08, 0x58, 0x00, 0x00, 0x12, 0xb6, 0x08, 0xb4, 0x08, 0x40, 0x00, +0x18, 0x02, 0xb6, 0x08, 0x46, 0x60, 0x00, 0xb7, 0xb4, 0x08, 0x58, 0x63, 0x01, 0xb0, 0x58, 0x00, +0x64, 0x00, 0xb6, 0x08, 0x05, 0xcf, 0x80, 0x05, 0xb4, 0x1c, 0x92, 0x14, 0x40, 0x00, 0x50, 0x08, +0xb6, 0x1c, 0x46, 0x5f, 0xff, 0x0f, 0xb4, 0x1c, 0x58, 0x52, 0x8f, 0xff, 0x40, 0x00, 0x18, 0x04, +0xb6, 0x1c, 0x45, 0xcf, 0xff, 0x00, 0xb4, 0x1e, 0x44, 0x66, 0x00, 0x00, 0x40, 0x00, 0x70, 0x02, +0xb6, 0x1e, 0xb4, 0x1e, 0x58, 0x00, 0x00, 0x14, 0xb6, 0x1e, 0xb4, 0x07, 0x40, 0x00, 0x70, 0x02, +0xb6, 0x07, 0x47, 0xcf, 0xf0, 0x0f, 0xb4, 0x07, 0x59, 0xce, 0x0f, 0xff, 0x58, 0x00, 0x00, 0x02, +0xb6, 0x07, 0xb4, 0x07, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x07, 0xb4, 0x07, 0x46, 0x50, 0x06, 0x40, +0x40, 0x00, 0x18, 0x04, 0xb6, 0x07, 0xb4, 0x03, 0x92, 0x05, 0x94, 0x05, 0xb6, 0x03, 0x44, 0x6f, +0xfc, 0x00, 0xb4, 0x03, 0x46, 0x7f, 0xc0, 0x0f, 0x58, 0x00, 0x00, 0x0c, 0xb6, 0x03, 0x58, 0x73, +0x8f, 0xff, 0xb4, 0x03, 0x40, 0x00, 0x70, 0x02, 0xb6, 0x03, 0x47, 0xc0, 0x16, 0x80, 0xb4, 0x03, +0x40, 0x00, 0x14, 0x04, 0xb6, 0x03, 0xb4, 0x02, 0x46, 0x50, 0x3e, 0x80, 0x40, 0x00, 0x18, 0x02, +0xb6, 0x02, 0xb4, 0x02, 0x58, 0x00, 0x01, 0x2c, 0xb6, 0x02, 0xb4, 0x02, 0x40, 0x00, 0x1c, 0x02, +0xb6, 0x02, 0xb4, 0x02, 0x40, 0x00, 0x70, 0x04, 0xb6, 0x02, 0xf2, 0x01, 0xb4, 0x02, 0x92, 0x08, +0x40, 0x00, 0x20, 0x08, 0xb6, 0x02, 0xb4, 0x02, 0x58, 0x00, 0x00, 0xbe, 0xb6, 0x02, 0xb4, 0x01, +0x40, 0x00, 0x18, 0x02, 0xb6, 0x01, 0x44, 0x6f, 0x00, 0xff, 0xb4, 0x01, 0x58, 0x00, 0x03, 0xe8, +0xb6, 0x01, 0xb4, 0x01, 0x40, 0x00, 0x1c, 0x02, 0xb6, 0x01, 0xb4, 0x01, 0x40, 0x00, 0x14, 0x04, +0xb6, 0x01, 0xb4, 0x04, 0x40, 0x00, 0x18, 0x02, 0xb6, 0x04, 0xb4, 0x04, 0x58, 0x00, 0x32, 0x00, +0x48, 0x00, 0x01, 0x80, 0x84, 0xa1, 0x4c, 0x02, 0xc1, 0x7f, 0x46, 0x20, 0x04, 0x03, 0x58, 0x21, +0x04, 0x7c, 0xb4, 0x22, 0x45, 0xcf, 0xff, 0x00, 0x40, 0x10, 0xf0, 0x02, 0xb6, 0x22, 0xb4, 0x62, +0x9c, 0x14, 0x58, 0x31, 0x80, 0x13, 0xb6, 0x62, 0x44, 0x6f, 0x00, 0xff, 0xb4, 0x60, 0x46, 0x7f, +0x00, 0x0f, 0x40, 0x31, 0xf0, 0x02, 0xb6, 0x60, 0x58, 0x73, 0x8f, 0xff, 0xb4, 0x60, 0x47, 0xc0, +0x3e, 0x80, 0x58, 0x31, 0x80, 0x2c, 0xb6, 0x60, 0xb4, 0x60, 0x40, 0x31, 0x98, 0x02, 0xb6, 0x60, +0x9c, 0x44, 0xb4, 0x60, 0x58, 0x31, 0xac, 0x00, 0xb6, 0x60, 0x9c, 0x8c, 0xb4, 0x60, 0x40, 0x31, +0x9c, 0x02, 0xb6, 0x60, 0xb4, 0x60, 0x9d, 0x14, 0x40, 0x31, 0xf0, 0x04, 0xb6, 0x60, 0xb4, 0x01, +0x50, 0x32, 0x00, 0x14, 0x92, 0x0c, 0x40, 0x00, 0x30, 0x08, 0xb6, 0x01, 0xf3, 0x84, 0xb4, 0x01, +0x80, 0x67, 0x58, 0x00, 0x00, 0x28, 0xb6, 0x01, 0xb4, 0x01, 0x51, 0xc2, 0x00, 0x20, 0x40, 0x00, +0x0c, 0x02, 0xb6, 0x01, 0x15, 0xcf, 0x80, 0x05, 0x46, 0x70, 0x02, 0x80, 0xb4, 0x01, 0x40, 0x00, +0x1c, 0x04, 0xb6, 0x01, 0xb4, 0x02, 0x92, 0x0c, 0x40, 0x00, 0x30, 0x08, 0xb6, 0x02, 0xb4, 0x02, +0x51, 0xc2, 0x00, 0x8c, 0x58, 0x00, 0x03, 0xe8, 0xb6, 0x02, 0xb4, 0x04, 0x9d, 0x64, 0x92, 0x0e, +0x40, 0x00, 0x38, 0x08, 0xb6, 0x04, 0xb4, 0x04, 0x9d, 0xac, 0x58, 0x00, 0x00, 0x28, 0xb6, 0x04, +0x15, 0xcf, 0x80, 0x01, 0x47, 0xcc, 0x00, 0x0f, 0xb4, 0x04, 0x59, 0xce, 0x0f, 0xff, 0x41, 0xc0, +0x70, 0x02, 0x15, 0xc2, 0x00, 0x00, 0x83, 0x87, 0xb4, 0x04, 0x41, 0xc0, 0x70, 0x04, 0x15, 0xc2, +0x00, 0x00, 0xb4, 0x05, 0x41, 0xc0, 0x38, 0x09, 0x41, 0xce, 0x38, 0x08, 0x15, 0xc2, 0x80, 0x00, +0x47, 0xcf, 0xf0, 0x0f, 0xb4, 0x05, 0x59, 0xce, 0x0f, 0xff, 0x58, 0x00, 0x13, 0x88, 0xb6, 0x05, +0x50, 0xa3, 0x00, 0x04, 0xb4, 0x05, 0x41, 0xc0, 0x70, 0x02, 0x15, 0xc2, 0x80, 0x00, 0x47, 0xc0, +0x01, 0x90, 0xb4, 0x05, 0x41, 0xc0, 0x70, 0x04, 0x15, 0xc2, 0x80, 0x00, 0xb4, 0x06, 0x45, 0xcf, +0xc0, 0xff, 0x92, 0x04, 0x94, 0x04, 0xb6, 0x06, 0x46, 0x5f, 0xfc, 0x0f, 0xb4, 0x06, 0x58, 0x52, +0x8f, 0xff, 0x58, 0x00, 0x00, 0x02, 0xb6, 0x06, 0x50, 0x95, 0x00, 0x04, 0xb4, 0x06, 0x40, 0x00, +0x70, 0x02, 0xb6, 0x06, 0x45, 0xcf, 0xff, 0x00, 0xb4, 0x06, 0x50, 0x84, 0x80, 0x0c, 0x58, 0x00, +0x12, 0x00, 0xb6, 0x06, 0xb4, 0x06, 0x51, 0xe4, 0x00, 0x08, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x06, +0xb4, 0x06, 0x42, 0x00, 0x4c, 0x08, 0xb6, 0x06, 0x44, 0x6f, 0x00, 0xff, 0xb4, 0x0a, 0x50, 0x7f, +0x00, 0x5c, 0x92, 0x07, 0x94, 0x07, 0xb6, 0x0a, 0x44, 0x5f, 0xf0, 0xff, 0xb4, 0x0a, 0x58, 0x00, +0x00, 0x1f, 0xb6, 0x0a, 0x9c, 0xfc, 0xb4, 0x0a, 0x40, 0x00, 0x18, 0x02, 0xb6, 0x0a, 0x9c, 0x9c, +0xb4, 0x0a, 0x58, 0x00, 0x64, 0x00, 0xb6, 0x0a, 0x50, 0x11, 0x00, 0x08, 0xb4, 0x09, 0x40, 0x00, +0x70, 0x02, 0xb6, 0x09, 0xb4, 0x09, 0x9d, 0x0c, 0x58, 0x00, 0x00, 0x3e, 0xb6, 0x09, 0xb4, 0x09, +0x40, 0x00, 0x14, 0x02, 0xb6, 0x09, 0x80, 0xa6, 0xb4, 0x09, 0x58, 0x00, 0x05, 0x00, 0xb6, 0x09, +0xf6, 0x04, 0xb4, 0x06, 0x40, 0x00, 0x70, 0x02, 0xb6, 0x06, 0xb4, 0x06, 0x58, 0x00, 0x00, 0x13, +0xb6, 0x06, 0xb4, 0x08, 0x92, 0x06, 0x94, 0x06, 0xb6, 0x08, 0xb4, 0x08, 0x58, 0x00, 0x00, 0x09, +0xb6, 0x08, 0xb4, 0x08, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x08, 0x44, 0x55, 0xb8, 0xd8, 0xb4, 0x08, +0x58, 0x00, 0x32, 0x00, 0xb6, 0x08, 0xf6, 0x05, 0xb4, 0x06, 0x92, 0x14, 0x40, 0x00, 0x50, 0x08, +0xb6, 0x06, 0x47, 0xcf, 0xff, 0x0f, 0xb4, 0x06, 0x59, 0xce, 0x0f, 0xff, 0x40, 0x00, 0x14, 0x04, +0xb6, 0x06, 0x44, 0x6f, 0xff, 0x00, 0xb4, 0x1e, 0x44, 0x53, 0x00, 0x00, 0x40, 0x00, 0x18, 0x02, +0xb6, 0x1e, 0xb4, 0x1e, 0x58, 0x00, 0x00, 0x28, 0xb6, 0x1e, 0xb4, 0x07, 0x40, 0x00, 0x18, 0x02, +0xb6, 0x07, 0xb4, 0x07, 0x58, 0x00, 0x00, 0x01, 0xb6, 0x07, 0xb4, 0x07, 0x40, 0x00, 0x70, 0x02, +0xb6, 0x07, 0xb4, 0x07, 0x47, 0xc0, 0x03, 0x20, 0x40, 0x00, 0x14, 0x04, 0xb6, 0x07, 0x46, 0x7f, +0xf0, 0x0f, 0xb4, 0x03, 0x58, 0x73, 0x8f, 0xff, 0x92, 0x05, 0x94, 0x05, 0xb6, 0x03, 0xb4, 0x03, +0x46, 0x5f, 0xc0, 0x0f, 0x58, 0x00, 0x00, 0x06, 0xb6, 0x03, 0x58, 0x52, 0x8f, 0xff, 0xb4, 0x03, +0x46, 0x60, 0x0b, 0x40, 0x40, 0x00, 0x1c, 0x02, 0xb6, 0x03, 0xb4, 0x03, 0x40, 0x00, 0x70, 0x04, +0xb6, 0x03, 0x44, 0x3f, 0xfc, 0x00, 0xb4, 0x02, 0x40, 0x00, 0x0c, 0x02, 0xb6, 0x02, 0xb4, 0x02, +0x58, 0x00, 0x00, 0x96, 0xb6, 0x02, 0xb4, 0x02, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x02, 0xb4, 0x02, +0x40, 0x00, 0x18, 0x04, 0xb6, 0x02, 0x46, 0x20, 0x1f, 0x40, 0xf7, 0x01, 0xb4, 0x07, 0x92, 0x08, +0x40, 0x00, 0x20, 0x08, 0xb6, 0x07, 0xb4, 0x07, 0x58, 0x00, 0x00, 0x5f, 0xb6, 0x07, 0xb4, 0x01, +0x40, 0x00, 0x0c, 0x02, 0xb6, 0x01, 0x44, 0x3f, 0x00, 0xff, 0xb4, 0x01, 0x58, 0x00, 0x01, 0xf4, +0xb6, 0x01, 0xb4, 0x01, 0x40, 0x00, 0x14, 0x02, 0xb6, 0x01, 0xb4, 0x01, 0x40, 0x00, 0x08, 0x04, +0xb6, 0x01, 0xb4, 0x04, 0x40, 0x00, 0x0c, 0x02, 0xb6, 0x04, 0xb4, 0x04, 0x58, 0x00, 0x19, 0x00, +0xb6, 0x04, 0xd5, 0x0e, 0x84, 0x00, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, +0x44, 0x30, 0x1a, 0x3f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xec, 0x1c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xc8, 0x18, 0x46, 0x10, +0x04, 0x03, 0x58, 0x10, 0x86, 0x00, 0xb4, 0x41, 0x84, 0x70, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, +0xb4, 0x41, 0x50, 0x00, 0x80, 0x08, 0x58, 0x21, 0x00, 0x08, 0xb6, 0x41, 0xb4, 0x20, 0x40, 0x10, +0x8c, 0x02, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x08, 0xd5, 0x19, 0x84, 0xa1, 0xd8, 0x19, +0x46, 0x10, 0x04, 0x03, 0x58, 0x10, 0x86, 0x00, 0xb4, 0x41, 0x84, 0x70, 0x40, 0x21, 0x0c, 0x02, +0xb6, 0x41, 0xb4, 0x41, 0x50, 0x00, 0x80, 0x08, 0x58, 0x21, 0x00, 0x0f, 0xb6, 0x41, 0xb4, 0x20, +0x40, 0x10, 0x8c, 0x02, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x0f, 0xb6, 0x20, 0xd5, 0x0e, +0x84, 0x00, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x19, 0x28, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xc8, 0x0d, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, +0x07, 0x9c, 0xb4, 0x20, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, +0xd5, 0x0a, 0x84, 0xa1, 0xd8, 0x0a, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, 0x07, 0x9c, 0xb4, 0x20, +0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0xd5, 0x0e, 0x84, 0x00, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, +0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x19, 0x09, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0xc8, 0x31, 0x46, 0x20, 0x04, 0x05, 0x58, 0x21, 0x09, 0x04, 0xb4, 0x22, 0x46, 0x3f, 0x0f, 0xff, +0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0x8c, 0x02, 0xb6, 0x22, 0xb4, 0x62, 0x9c, 0x14, 0x42, 0x31, +0xec, 0x08, 0xb6, 0x62, 0xb4, 0x40, 0x44, 0x4f, 0xe0, 0xff, 0x92, 0x45, 0x94, 0x95, 0xb6, 0x40, +0x46, 0x3e, 0x0f, 0xff, 0xb4, 0x40, 0x58, 0x31, 0x8f, 0xff, 0x58, 0x21, 0x00, 0x19, 0xb6, 0x40, +0xb4, 0x40, 0x9c, 0x44, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x40, 0x46, 0x41, 0xe0, 0x00, 0xb4, 0x40, +0x58, 0x21, 0x02, 0x00, 0xb6, 0x40, 0xb4, 0x40, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x40, 0xb4, 0x40, +0xd5, 0x32, 0x84, 0xa1, 0xd8, 0x3e, 0x46, 0x20, 0x04, 0x05, 0x58, 0x21, 0x09, 0x04, 0xb4, 0x22, +0x46, 0x4f, 0x0f, 0xff, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x10, 0x90, 0x02, 0xb6, 0x22, 0xb4, 0x62, +0x9c, 0x14, 0x42, 0x31, 0xe8, 0x08, 0xb6, 0x62, 0xb4, 0x40, 0x44, 0x4f, 0xe0, 0xff, 0x92, 0x45, +0x94, 0x95, 0xb6, 0x40, 0x46, 0x3e, 0x0f, 0xff, 0xb4, 0x40, 0x58, 0x31, 0x8f, 0xff, 0x58, 0x21, +0x00, 0x0d, 0xb6, 0x40, 0xb4, 0x40, 0x9c, 0x44, 0x40, 0x21, 0x10, 0x02, 0xb6, 0x40, 0x46, 0x40, +0xf0, 0x00, 0xb4, 0x40, 0x58, 0x21, 0x01, 0x00, 0xb6, 0x40, 0xb4, 0x40, 0x40, 0x21, 0x0c, 0x02, +0xb6, 0x40, 0xb4, 0x40, 0x40, 0x21, 0x10, 0x04, 0xb6, 0x40, 0x44, 0x2f, 0xe0, 0xff, 0xb4, 0x01, +0x40, 0x00, 0x08, 0x02, 0xb6, 0x01, 0xb4, 0x01, 0x58, 0x00, 0x01, 0x00, 0xb6, 0x01, 0xd5, 0x0e, +0x84, 0x00, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x18, 0xf3, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xc8, 0x6a, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, 0x0c, 0x6c, +0xb4, 0x20, 0x92, 0x22, 0x94, 0x4a, 0xb6, 0x20, 0xb4, 0x20, 0x50, 0x20, 0x7e, 0xcc, 0x58, 0x10, +0x80, 0x02, 0xb6, 0x20, 0xb4, 0x02, 0x92, 0x1f, 0x40, 0x00, 0x7c, 0x08, 0xb6, 0x02, 0x46, 0x51, +0x2c, 0x00, 0xb4, 0x82, 0x40, 0x42, 0x14, 0x04, 0xb6, 0x82, 0x46, 0x30, 0x04, 0x05, 0x04, 0x21, +0x82, 0xcc, 0x42, 0x21, 0x54, 0x09, 0x14, 0x21, 0x82, 0xcc, 0x46, 0x10, 0x04, 0x05, 0x58, 0x10, +0x8c, 0x08, 0xb4, 0x41, 0x44, 0x5f, 0xe3, 0xff, 0x40, 0x21, 0x14, 0x02, 0xb6, 0x41, 0xb4, 0xa1, +0x9c, 0x0c, 0x58, 0x52, 0x84, 0x00, 0xb6, 0xa1, 0x84, 0xd0, 0xb4, 0xa0, 0x40, 0x52, 0x98, 0x02, +0xb6, 0xa0, 0x9d, 0x04, 0xb4, 0xa0, 0x58, 0x52, 0x80, 0x01, 0xb6, 0xa0, 0x9c, 0xe4, 0xb4, 0xa4, +0x40, 0x52, 0x98, 0x02, 0xb6, 0xa4, 0x50, 0x21, 0x80, 0x50, 0xb4, 0xa4, 0x58, 0x52, 0x80, 0x04, +0xb6, 0xa4, 0xb4, 0x80, 0x42, 0x42, 0x50, 0x09, 0x42, 0x42, 0x54, 0x09, 0xb6, 0x80, 0xb4, 0x80, +0x50, 0x11, 0x7f, 0xf4, 0x42, 0x42, 0x54, 0x08, 0xb6, 0x80, 0xb4, 0x03, 0x92, 0x04, 0x94, 0x04, +0xb6, 0x03, 0xb4, 0x03, 0x58, 0x00, 0x00, 0x08, 0xb6, 0x03, 0xb4, 0x02, 0x42, 0x00, 0x1c, 0x09, +0xb6, 0x02, 0xb4, 0x02, 0x58, 0x00, 0x00, 0x80, 0xb6, 0x02, 0xb4, 0x01, 0x92, 0x03, 0x94, 0x03, +0xb6, 0x01, 0xb4, 0x01, 0x58, 0x00, 0x00, 0x01, 0xd5, 0x67, 0x84, 0xa1, 0xd8, 0x67, 0x46, 0x00, +0x04, 0x05, 0x58, 0x00, 0x0c, 0x6c, 0xb4, 0x40, 0x92, 0x42, 0x94, 0x92, 0xb6, 0x40, 0xb4, 0x60, +0x50, 0x10, 0x7e, 0xcc, 0x58, 0x31, 0x80, 0x01, 0xb6, 0x60, 0xb4, 0x01, 0x92, 0x1f, 0x40, 0x00, +0x7c, 0x08, 0xb6, 0x01, 0x46, 0x60, 0x96, 0x00, 0xb4, 0x61, 0x40, 0x31, 0x98, 0x04, 0xb6, 0x61, +0x46, 0x20, 0x04, 0x05, 0x04, 0x11, 0x02, 0xcc, 0x80, 0x82, 0x42, 0x10, 0xd4, 0x08, 0x14, 0x11, +0x02, 0xcc, 0x04, 0x12, 0x03, 0x02, 0x44, 0x6f, 0xe3, 0xff, 0x40, 0x10, 0x98, 0x02, 0x14, 0x12, +0x03, 0x02, 0x46, 0x00, 0x04, 0x05, 0x58, 0x00, 0x0c, 0x0c, 0xb4, 0x20, 0x92, 0x24, 0x94, 0x4c, +0xb6, 0x20, 0xb4, 0xa0, 0x9c, 0xc4, 0x58, 0x52, 0x80, 0x05, 0xb6, 0xa0, 0xb4, 0xa3, 0x92, 0xa4, +0x95, 0x6c, 0xb6, 0xa3, 0x46, 0x60, 0x03, 0x00, 0xb4, 0xa3, 0x58, 0x52, 0x80, 0x0a, 0xb6, 0xa3, +0xb4, 0x60, 0x42, 0x31, 0xd0, 0x09, 0x42, 0x31, 0xd4, 0x09, 0xb6, 0x60, 0x50, 0x20, 0x00, 0x08, +0xb4, 0x60, 0x40, 0x31, 0x98, 0x04, 0xb6, 0x60, 0xb4, 0x02, 0x92, 0x04, 0x94, 0x04, 0xb6, 0x02, +0xb4, 0x02, 0x58, 0x00, 0x00, 0x03, 0xb6, 0x02, 0x50, 0x11, 0x00, 0x44, 0x04, 0x02, 0x03, 0x19, +0x42, 0x00, 0x1c, 0x09, 0x14, 0x02, 0x03, 0x19, 0xb4, 0x01, 0x92, 0x03, 0x94, 0x03, 0xb6, 0x01, +0xb4, 0x01, 0x58, 0x00, 0x00, 0x03, 0xb6, 0x01, 0xd5, 0x0e, 0x84, 0x00, 0x80, 0x20, 0x46, 0x20, +0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x18, 0xbc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x86, 0x88, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x96, 0x00, 0xe6, 0x08, 0xe8, 0x06, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x20, 0xd5, 0x1d, +0xe6, 0x10, 0xe8, 0x06, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x24, 0xd5, 0x16, 0xe6, 0x15, +0xe8, 0x06, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x28, 0xd5, 0x0f, 0x84, 0x00, 0x80, 0x20, +0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x18, 0x65, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xa7, 0x80, 0x00, 0x80, 0x00, 0x01, 0x80, 0x06, 0x46, 0xf0, +0x00, 0xc0, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x4e, 0x82, 0x00, 0x0d, 0x46, 0x10, 0x04, 0x00, +0x58, 0x10, 0x81, 0xbc, 0xb4, 0x61, 0x84, 0x41, 0x40, 0x21, 0x18, 0x0c, 0x40, 0x21, 0x0c, 0x04, +0xd5, 0x0d, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x81, 0xbc, 0x84, 0x41, 0x40, 0x21, 0x18, 0x0c, +0xb4, 0x61, 0x40, 0x21, 0x08, 0x05, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x46, 0x70, 0x04, 0x00, +0x58, 0x73, 0x81, 0xb8, 0x84, 0x21, 0x54, 0x43, 0x00, 0x07, 0xb4, 0xa7, 0x95, 0x22, 0x40, 0x30, +0x98, 0x0c, 0x9c, 0xa3, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x94, 0x02, 0x40, 0x20, 0x88, 0x0c, +0xb6, 0x67, 0x40, 0x30, 0x90, 0x0c, 0x9e, 0x51, 0x40, 0x20, 0x88, 0x04, 0x52, 0x11, 0x80, 0x00, +0x40, 0x21, 0x04, 0x02, 0xb4, 0x20, 0x40, 0x21, 0x08, 0x05, 0x40, 0x20, 0x88, 0x02, 0xb6, 0x40, +0x80, 0x26, 0xb4, 0xa0, 0x80, 0x48, 0x40, 0x32, 0x8c, 0x04, 0xb6, 0x60, 0x46, 0x60, 0x00, 0x04, +0x58, 0x63, 0x09, 0xd0, 0x80, 0x60, 0x46, 0x00, 0x00, 0xd1, 0x58, 0x00, 0x0f, 0x64, 0x4b, 0xe0, +0x18, 0x01, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x6f, 0xb4, 0x47, 0x46, 0x00, 0x00, 0xd1, +0x58, 0x00, 0x0f, 0xcc, 0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x09, 0xd0, 0x81, 0x00, 0x46, 0x00, 0x00, 0xd1, +0x58, 0x00, 0x0f, 0xec, 0xdd, 0x26, 0x46, 0x70, 0x00, 0xc0, 0x58, 0x73, 0x82, 0x94, 0x50, 0x04, +0x00, 0x04, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x00, 0x00, 0xd2, 0x58, 0x00, 0x00, 0x00, 0xdd, 0x26, +0x50, 0x04, 0x00, 0x1c, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x04, 0x00, 0x80, 0x41, 0x80, 0x01, +0x04, 0x10, 0x80, 0x48, 0x04, 0x21, 0x00, 0x49, 0x04, 0x30, 0x00, 0x4a, 0x46, 0x00, 0x00, 0xd2, +0x58, 0x00, 0x00, 0x14, 0xdd, 0x26, 0x46, 0x10, 0x04, 0x00, 0x80, 0x01, 0x04, 0x10, 0x80, 0x6f, +0x04, 0x20, 0x00, 0x6e, 0x46, 0x00, 0x00, 0xd1, 0x58, 0x00, 0x0f, 0xcc, 0xdd, 0x26, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x97, 0x80, 0x40, 0x80, +0x80, 0x13, 0x46, 0x00, 0x00, 0xd2, 0x58, 0x00, 0x00, 0x54, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, +0x89, 0xd0, 0x80, 0x26, 0x80, 0xe2, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0x50, 0x00, 0x18, 0xde, 0x1c, +0x84, 0x81, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xef, 0x80, 0x27, 0x44, 0x20, 0x00, 0x34, +0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x84, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x80, +0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x84, 0x46, 0xf0, 0x00, 0xc0, 0x58, 0xf7, +0x83, 0x60, 0xdd, 0x2f, 0xd5, 0x27, 0x9d, 0x69, 0xde, 0x0f, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, +0x09, 0xef, 0xae, 0x78, 0x00, 0x10, 0x09, 0xef, 0x46, 0x00, 0x00, 0xd2, 0x58, 0x00, 0x00, 0x80, +0x4b, 0xe0, 0x24, 0x01, 0xd5, 0x17, 0x9d, 0x69, 0xde, 0x0d, 0x54, 0x14, 0x00, 0xff, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x0a, 0x84, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x84, 0xec, 0xdd, 0x2f, +0xd5, 0x09, 0x80, 0x06, 0x80, 0x28, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8c, 0xd0, +0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x84, 0x08, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x86, 0xc0, 0xdd, 0x2f, 0x84, 0x21, 0x46, 0xf0, +0x01, 0x13, 0x14, 0x17, 0x80, 0xb9, 0x46, 0x00, 0x04, 0x02, 0xb4, 0xe0, 0x54, 0x73, 0x80, 0x10, +0xc7, 0x0a, 0x46, 0x10, 0x04, 0x04, 0x80, 0x01, 0x04, 0x10, 0x81, 0x07, 0x04, 0x70, 0x01, 0x06, +0x40, 0x73, 0x84, 0x02, 0x46, 0x00, 0x04, 0x02, 0xb4, 0xc0, 0x54, 0x63, 0x00, 0x04, 0xc6, 0x0a, +0x46, 0x10, 0x04, 0x03, 0x80, 0x01, 0x04, 0x10, 0x81, 0x50, 0x04, 0x60, 0x01, 0x4f, 0x40, 0x63, +0x04, 0x02, 0x46, 0x10, 0x04, 0x02, 0x80, 0x01, 0x04, 0x10, 0x80, 0x20, 0x04, 0x20, 0x00, 0x21, +0x40, 0x21, 0x04, 0x02, 0x40, 0x11, 0x40, 0x09, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x17, 0x81, 0x99, +0x80, 0x60, 0x80, 0x20, 0x04, 0x31, 0x82, 0x15, 0x04, 0xa0, 0x82, 0x14, 0xb4, 0x00, 0x40, 0xa5, +0x0c, 0x02, 0x54, 0x00, 0x00, 0x10, 0x54, 0x91, 0x00, 0xff, 0xc0, 0x05, 0x46, 0x00, 0x04, 0x04, +0x14, 0x70, 0x01, 0x07, 0x80, 0x01, 0xb4, 0x00, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x05, 0x46, 0x00, +0x04, 0x03, 0x14, 0x60, 0x01, 0x50, 0x80, 0x01, 0x54, 0x33, 0x20, 0x00, 0x14, 0x20, 0x80, 0x20, +0x14, 0xa0, 0x02, 0x15, 0xc3, 0x2b, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xcc, 0x42, 0x21, +0x04, 0x09, 0x14, 0x20, 0x81, 0xcc, 0x80, 0x01, 0x04, 0x10, 0x01, 0xc2, 0x42, 0x10, 0x80, 0x09, +0x14, 0x10, 0x01, 0xc2, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x80, 0xbc, 0xc8, 0x0d, 0x80, 0x20, +0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x35, 0xaf, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x80, 0xbc, 0xdd, 0x20, +0x84, 0x00, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x07, 0x80, 0xb7, 0x54, 0x03, 0x82, 0x00, 0xc0, 0x1f, +0x46, 0x00, 0x04, 0x04, 0x04, 0x00, 0x01, 0x01, 0x54, 0x00, 0x04, 0x00, 0xc8, 0x18, 0x46, 0x00, +0x04, 0x05, 0x04, 0x20, 0x01, 0xc2, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x01, 0xc2, 0x80, 0x20, +0x04, 0x20, 0x81, 0xd4, 0x42, 0x21, 0x04, 0x09, 0x14, 0x20, 0x81, 0xd4, 0x46, 0x00, 0x04, 0x04, +0x04, 0x10, 0x01, 0x13, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x01, 0x13, 0x54, 0x03, 0x80, 0x02, +0xc0, 0x2f, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xc2, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, +0x81, 0xc2, 0x80, 0x01, 0x04, 0x10, 0x01, 0xd4, 0x42, 0x10, 0x84, 0x09, 0x14, 0x10, 0x01, 0xd4, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x80, 0xbc, 0xc8, 0x0d, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, +0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x35, 0xe6, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x80, 0xbc, 0xdd, 0x20, 0x84, 0x00, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x07, 0x8a, 0x1c, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x07, 0x80, 0xb7, 0x54, 0x03, +0x80, 0x04, 0xc0, 0x38, 0x46, 0x00, 0x04, 0x05, 0x04, 0x20, 0x01, 0xcc, 0x84, 0x7d, 0x40, 0x21, +0x0c, 0x02, 0x14, 0x20, 0x01, 0xcc, 0x80, 0x20, 0x04, 0x20, 0x81, 0xd4, 0x40, 0x21, 0x0c, 0x02, +0x14, 0x20, 0x81, 0xd4, 0x04, 0x10, 0x01, 0xc2, 0x42, 0x10, 0x80, 0x09, 0x14, 0x10, 0x01, 0xc2, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x80, 0xba, 0xc8, 0x0d, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, +0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x35, 0xfe, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x80, 0xba, 0xdd, 0x20, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x59, 0x58, 0xf7, 0x8d, 0xc0, 0xdd, 0x2f, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, +0x8a, 0x1c, 0x54, 0xa5, 0x00, 0x01, 0x4e, 0xa2, 0x00, 0x0d, 0x46, 0x00, 0x04, 0x02, 0x04, 0x00, +0x02, 0x00, 0x54, 0x00, 0x00, 0x07, 0x46, 0xf0, 0x00, 0x56, 0x58, 0xf7, 0x8e, 0xe8, 0xdd, 0x2f, +0x54, 0x03, 0x00, 0x02, 0xc0, 0x15, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x01, 0xd4, 0x42, 0x10, +0x80, 0x09, 0x14, 0x10, 0x01, 0xd4, 0x84, 0xc0, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x85, 0x90, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x8d, 0x70, 0xdd, 0x2f, 0xd5, 0x1e, 0x54, 0x03, +0x40, 0x00, 0xc0, 0x0b, 0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x02, 0x42, 0x42, 0x10, 0xf4, 0x09, +0x42, 0x10, 0xf8, 0x09, 0x14, 0x10, 0x02, 0x42, 0x54, 0x03, 0x00, 0x10, 0xc0, 0x06, 0x46, 0xf0, +0x00, 0x54, 0x58, 0xf7, 0x86, 0xbc, 0xdd, 0x2f, 0x54, 0x03, 0x00, 0x20, 0xc0, 0x06, 0x46, 0xf0, +0x00, 0x54, 0x58, 0xf7, 0x86, 0xbc, 0xdd, 0x2f, 0x54, 0x03, 0x80, 0x20, 0xc0, 0x20, 0x46, 0x10, +0x04, 0x05, 0x04, 0x20, 0x82, 0x42, 0x42, 0x21, 0x74, 0x09, 0x42, 0x21, 0x78, 0x09, 0x14, 0x20, +0x82, 0x42, 0x80, 0x01, 0x04, 0x20, 0x01, 0xc2, 0x42, 0x21, 0x00, 0x09, 0x14, 0x20, 0x01, 0xc2, +0x80, 0x20, 0x04, 0x20, 0x81, 0xcc, 0x84, 0x7d, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x81, 0xcc, +0x04, 0x10, 0x01, 0xd4, 0x40, 0x10, 0x8c, 0x02, 0x14, 0x10, 0x01, 0xd4, 0x46, 0xf0, 0x01, 0x13, +0x04, 0x07, 0x81, 0x99, 0x40, 0x14, 0x80, 0x04, 0x96, 0x4c, 0xc1, 0x23, 0x46, 0xf0, 0x01, 0x13, +0x04, 0x87, 0x80, 0xbd, 0x4e, 0x83, 0x00, 0x16, 0x80, 0x08, 0x46, 0x10, 0x00, 0xd2, 0x58, 0x10, +0x80, 0x9c, 0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, 0x36, 0x8d, 0x80, 0x88, +0x80, 0xa8, 0xb7, 0x1f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x38, 0xdd, 0x2f, 0xd5, 0x09, +0x96, 0x04, 0xc0, 0x06, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x17, 0x84, 0xce, 0xdd, 0x28, +0x46, 0x00, 0x04, 0x02, 0x04, 0x00, 0x00, 0x21, 0x40, 0x90, 0x24, 0x02, 0x93, 0x21, 0x4e, 0x92, +0x00, 0x20, 0x85, 0x01, 0x47, 0xc0, 0x00, 0x56, 0x59, 0xce, 0x09, 0x98, 0x46, 0xa0, 0x00, 0x57, +0x58, 0xa5, 0x04, 0xf4, 0x50, 0x04, 0x7f, 0xff, 0x84, 0x21, 0x40, 0x00, 0x80, 0x0c, 0x40, 0x00, +0x24, 0x02, 0xc0, 0x0a, 0x80, 0x08, 0xdd, 0x3c, 0xc0, 0x07, 0x84, 0x20, 0x80, 0x08, 0x80, 0x41, +0x84, 0x61, 0x4b, 0xe0, 0x28, 0x01, 0x8d, 0x01, 0x84, 0x4a, 0x4c, 0x81, 0x7f, 0xed, 0x46, 0x00, +0x04, 0x02, 0x04, 0x90, 0x00, 0x21, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x81, 0x99, 0x93, 0x31, +0x92, 0x01, 0x40, 0x94, 0x80, 0x02, 0x4e, 0x92, 0x00, 0x20, 0x85, 0x01, 0x47, 0xc0, 0x00, 0x56, +0x59, 0xce, 0x09, 0x6c, 0x46, 0xa0, 0x00, 0x57, 0x58, 0xa5, 0x04, 0xf4, 0x50, 0x04, 0x7f, 0xff, +0x84, 0x61, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x24, 0x02, 0xc0, 0x0a, 0x80, 0x08, 0xdd, 0x3c, +0xc0, 0x07, 0x80, 0x08, 0x84, 0x21, 0x84, 0x40, 0x84, 0x62, 0x4b, 0xe0, 0x28, 0x01, 0x8d, 0x01, +0x84, 0x0a, 0x4c, 0x80, 0x7f, 0xed, 0x96, 0x3c, 0xc0, 0x41, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, +0x80, 0xbb, 0xc8, 0x0d, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, 0x44, 0x30, +0x37, 0x1d, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, +0x04, 0x07, 0x80, 0xbb, 0xdd, 0x20, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x86, 0x61, 0x84, 0x21, +0x46, 0xf0, 0x01, 0x13, 0x14, 0x17, 0x80, 0xb7, 0xc0, 0x10, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, +0x81, 0xd4, 0x80, 0x01, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x81, 0xd4, 0x04, 0x10, 0x01, 0xc2, +0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x01, 0xc2, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x18, +0xa6, 0x40, 0x84, 0x41, 0x4c, 0x11, 0x40, 0x0b, 0xa6, 0x41, 0xc9, 0x08, 0xa6, 0x04, 0xc8, 0x06, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x89, 0xc4, 0xdd, 0x2f, 0x54, 0x73, 0x81, 0x00, 0xc7, 0x1c, +0x46, 0x10, 0x04, 0x04, 0x80, 0x01, 0x04, 0x10, 0x81, 0x11, 0x04, 0x10, 0x01, 0x01, 0x04, 0x00, +0x01, 0x01, 0x54, 0x00, 0x04, 0x00, 0xc8, 0x10, 0x46, 0x10, 0x04, 0x05, 0x04, 0x20, 0x81, 0xd4, +0x80, 0x01, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x81, 0xd4, 0x04, 0x10, 0x01, 0xc2, 0x58, 0x10, +0x80, 0x01, 0x14, 0x10, 0x01, 0xc2, 0x54, 0x63, 0x04, 0x00, 0xc6, 0x30, 0x46, 0xf0, 0x01, 0x13, +0x04, 0x07, 0x80, 0xbb, 0xc8, 0x0d, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd1, 0x58, 0x21, 0x0f, 0x4c, +0x44, 0x30, 0x37, 0x53, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x13, 0x04, 0x07, 0x80, 0xbb, 0xdd, 0x20, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x86, 0x61, +0x84, 0x21, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x17, 0x80, 0xb7, 0xc0, 0x10, 0x46, 0x10, 0x04, 0x05, +0x04, 0x20, 0x81, 0xcc, 0x80, 0x01, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x81, 0xcc, 0x04, 0x10, +0x01, 0xc2, 0x58, 0x10, 0x80, 0x01, 0x14, 0x10, 0x01, 0xc2, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x13, +0x14, 0x27, 0x80, 0xb9, 0x84, 0x08, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x86, 0x84, 0xdd, 0x2f, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x81, 0x01, +0x54, 0xa0, 0x00, 0xff, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x8c, 0xb0, 0xdd, 0x2f, 0x84, 0xa1, +0xd8, 0x0a, 0x00, 0x54, 0x00, 0xb3, 0x84, 0x23, 0xd1, 0x06, 0x00, 0x54, 0x00, 0xb4, 0xd1, 0x03, +0x48, 0x00, 0x00, 0xac, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xff, 0x8e, 0x0f, 0xe6, 0x03, +0x4e, 0xf3, 0x00, 0xc1, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x07, 0x85, 0xf9, 0x4e, 0x02, 0x00, 0xbb, +0x46, 0xf0, 0x01, 0x10, 0x02, 0x17, 0x83, 0x06, 0x44, 0x50, 0x00, 0xff, 0x4c, 0x12, 0x80, 0xb3, +0x80, 0x01, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xe0, 0xdd, 0x2f, 0x80, 0xc0, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x17, 0x81, 0xdd, 0x00, 0x23, 0x01, 0xae, 0x4e, 0x62, 0x00, 0xa4, 0x44, 0x00, +0x00, 0x30, 0x42, 0x11, 0x00, 0x73, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x57, 0x82, 0xd7, 0x4c, 0x50, +0xc0, 0x9a, 0x02, 0x04, 0x00, 0x19, 0x44, 0x70, 0x00, 0x10, 0x40, 0x03, 0x80, 0xf6, 0x84, 0x20, +0x40, 0x70, 0x9c, 0x06, 0x99, 0xf8, 0xa0, 0x76, 0x9f, 0xf9, 0x97, 0xf8, 0xc1, 0x0d, 0x46, 0xf0, +0x00, 0x24, 0x58, 0xf7, 0x8c, 0xb4, 0xdd, 0x2f, 0xc8, 0x1a, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, +0x8f, 0x89, 0xe6, 0x02, 0xe9, 0x14, 0x00, 0x13, 0x01, 0xae, 0x46, 0x90, 0x00, 0x36, 0x58, 0x94, +0x8d, 0x90, 0x44, 0x00, 0x00, 0x2c, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x45, 0x00, 0x13, 0x01, 0xae, +0x44, 0x00, 0x00, 0x55, 0x4b, 0xe0, 0x24, 0x01, 0xc8, 0x3f, 0xd5, 0x3d, 0x00, 0x13, 0x01, 0xae, +0x44, 0x00, 0x00, 0x55, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0xc0, 0x33, +0x46, 0xf0, 0x01, 0x10, 0x04, 0x07, 0x81, 0x7f, 0xa4, 0x00, 0xe6, 0x02, 0xe8, 0x2c, 0x04, 0x03, +0x00, 0x6c, 0x84, 0xa1, 0xd8, 0x11, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x81, 0xdd, 0x00, 0x23, +0x01, 0xae, 0x44, 0x00, 0x00, 0x30, 0x42, 0x11, 0x00, 0x73, 0x04, 0x00, 0x80, 0x0a, 0x00, 0x00, +0x00, 0x37, 0xc0, 0x02, 0xd5, 0x18, 0x00, 0x13, 0x01, 0xae, 0x46, 0x90, 0x00, 0x36, 0x58, 0x94, +0x8d, 0x90, 0x44, 0x00, 0x00, 0x2c, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x08, 0x00, 0x13, 0x01, 0xae, +0x44, 0x00, 0x00, 0x55, 0x4b, 0xe0, 0x24, 0x01, 0xc8, 0x07, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, +0x8a, 0x00, 0xc0, 0x02, 0xcf, 0x39, 0x00, 0x13, 0x01, 0xae, 0x46, 0x70, 0x00, 0x36, 0x58, 0x73, +0x8d, 0x90, 0x44, 0x00, 0x00, 0x2c, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x1d, 0xd5, 0x15, 0x84, 0x20, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x8a, 0x00, 0x84, 0x00, 0xd5, 0x23, 0x9c, 0x49, 0x9d, 0xf9, +0x40, 0x70, 0x9c, 0x16, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8a, 0x00, 0xc8, 0x02, 0xd5, 0x0f, +0x84, 0x00, 0xae, 0x08, 0xd5, 0xf2, 0x00, 0x13, 0x01, 0xae, 0x44, 0x00, 0x00, 0x55, 0x4b, 0xe0, +0x1c, 0x01, 0xc8, 0x08, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8a, 0x00, 0xa6, 0x08, 0x9c, 0x01, +0xae, 0x08, 0x80, 0x0a, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x8d, 0x8c, 0xdd, 0x2f, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x02, 0x14, 0x00, 0x56, 0xe2, 0x27, 0xe8, 0xd8, 0xd5, 0xd0, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x00, 0x84, 0x00, 0x80, 0xc2, 0x81, 0x21, +0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x80, 0xe0, 0x46, 0xf0, 0x00, 0x35, +0x58, 0xf7, 0x84, 0x2c, 0xdd, 0x2f, 0x44, 0x10, 0x00, 0xa0, 0x40, 0x10, 0x04, 0x17, 0x84, 0x21, +0xa4, 0xb1, 0x4c, 0x90, 0xc0, 0x1e, 0xca, 0x0b, 0x46, 0xf0, 0x01, 0x08, 0x02, 0x07, 0x87, 0xd8, +0xac, 0x31, 0x04, 0x84, 0x00, 0x07, 0x14, 0x83, 0x00, 0x02, 0xd5, 0x49, 0x5c, 0xf1, 0x00, 0x51, +0xe9, 0x04, 0x50, 0x21, 0x7f, 0xb0, 0x98, 0x90, 0xa0, 0x32, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x34, +0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, 0xa8, 0x32, 0x14, 0x04, 0x00, 0x07, 0xd5, 0x38, 0x4e, 0x93, +0x00, 0x10, 0x5c, 0xf1, 0x00, 0x51, 0xe9, 0x04, 0x50, 0x21, 0x7f, 0xb0, 0x98, 0x90, 0xa0, 0x32, +0x80, 0x27, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, 0xd5, 0x27, 0x84, 0xa2, +0x4c, 0x92, 0xc0, 0x1e, 0x00, 0x14, 0x00, 0x34, 0x00, 0x24, 0x00, 0x33, 0xa4, 0x30, 0x9a, 0x91, +0x46, 0x10, 0x01, 0x38, 0x4e, 0x27, 0x00, 0x0b, 0x02, 0x20, 0x84, 0xeb, 0x42, 0x10, 0x08, 0x24, +0x84, 0x4a, 0x40, 0x10, 0x88, 0x56, 0x94, 0x4c, 0xd5, 0x08, 0x02, 0x20, 0x84, 0xeb, 0x42, 0x10, +0x08, 0x24, 0x84, 0x4a, 0x40, 0x10, 0x88, 0x56, 0x80, 0x07, 0xd5, 0x03, 0x80, 0x07, 0x80, 0x22, +0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0x2c, 0xdd, 0x2f, 0xa8, 0x32, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x50, 0x70, 0x00, 0x30, +0x96, 0x90, 0x84, 0x0c, 0x80, 0xc1, 0xf2, 0x81, 0x4c, 0x10, 0x01, 0x42, 0xe6, 0x2d, 0xe8, 0x0b, +0x84, 0x2a, 0x4c, 0x60, 0x81, 0x2f, 0xe6, 0xcb, 0x4e, 0xf2, 0x01, 0x48, 0xe6, 0xc7, 0x4e, 0xf2, +0x01, 0x43, 0xd5, 0x09, 0xe6, 0x2f, 0x4e, 0xf3, 0x01, 0x25, 0xe6, 0x32, 0x4e, 0xf3, 0x01, 0x6b, +0x48, 0x00, 0x01, 0x3a, 0xf3, 0x01, 0x84, 0x06, 0x44, 0x12, 0x00, 0x00, 0x44, 0x20, 0x70, 0x92, +0x80, 0x86, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x9e, 0x34, 0xe6, 0x02, +0xe8, 0x0d, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x07, 0x81, 0x80, 0x84, 0xa1, 0x00, 0x00, 0x00, 0x22, +0xd8, 0x05, 0x46, 0xf0, 0x01, 0x0a, 0x10, 0x07, 0x8b, 0x84, 0x44, 0xa0, 0x00, 0x18, 0x42, 0xa3, +0x28, 0x24, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0x46, 0x10, 0x01, 0x06, 0x58, 0x10, +0x8f, 0x00, 0x89, 0x41, 0x4e, 0x03, 0x00, 0x93, 0xa6, 0x38, 0x4e, 0x03, 0x00, 0x90, 0x46, 0xf0, +0x01, 0x07, 0x00, 0x17, 0x80, 0x23, 0x4e, 0x12, 0x00, 0x8a, 0x00, 0x95, 0x00, 0x0e, 0x4e, 0x92, +0x00, 0x4b, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x18, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x27, +0x83, 0xfc, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x37, 0x80, 0x01, 0x94, 0x03, 0x98, 0x18, 0x54, 0x21, +0x00, 0x10, 0x02, 0x80, 0x00, 0x03, 0xc2, 0x1d, 0x84, 0xa2, 0xde, 0x0a, 0x46, 0xf0, 0x01, 0x0f, +0x02, 0x27, 0x81, 0xe1, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x37, 0x81, 0xe0, 0xd5, 0x0b, 0x84, 0xa3, +0xde, 0x10, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x27, 0x81, 0xeb, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x37, +0x81, 0xea, 0x98, 0x92, 0xe0, 0x43, 0xe9, 0x05, 0x02, 0x83, 0xff, 0xfb, 0x87, 0x81, 0xd5, 0x02, +0x87, 0x80, 0x4e, 0x83, 0x00, 0x62, 0xe6, 0x22, 0xe9, 0x09, 0xa6, 0xbb, 0xa6, 0x7c, 0x9a, 0x51, +0x4e, 0x17, 0x00, 0x0f, 0x44, 0x80, 0x00, 0x28, 0xd5, 0x57, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x27, +0x8f, 0x8d, 0xca, 0x06, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x17, 0x8f, 0x8e, 0xc1, 0x4d, 0x02, 0x80, +0x00, 0x00, 0xd5, 0x4a, 0x01, 0xc3, 0x80, 0x04, 0x4f, 0xc2, 0x00, 0x2e, 0x46, 0xf0, 0x01, 0x00, +0x05, 0xc7, 0x81, 0x0b, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, +0xdd, 0x3c, 0x96, 0x41, 0xc9, 0x0d, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x07, 0x80, 0x01, 0x46, 0xf0, +0x01, 0x07, 0x00, 0x27, 0x80, 0x18, 0x83, 0x81, 0x38, 0x80, 0x0b, 0x01, 0xd5, 0x2d, 0xa6, 0xbb, +0xa6, 0x3c, 0x9a, 0x10, 0xe4, 0x02, 0xe9, 0x26, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x07, 0x80, 0x01, +0x46, 0xf0, 0x01, 0x07, 0x00, 0x27, 0x80, 0x18, 0x38, 0x80, 0x0b, 0x01, 0xe3, 0x01, 0xe8, 0x1a, +0x83, 0x89, 0xd5, 0x1a, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x07, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x07, +0x00, 0x17, 0x80, 0x18, 0x38, 0x80, 0x07, 0x01, 0xd5, 0x0f, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x17, +0x80, 0x01, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x18, 0x87, 0x80, 0x38, 0x80, 0x83, 0x01, +0xd5, 0x03, 0x81, 0x01, 0x87, 0x80, 0x04, 0x35, 0x00, 0x04, 0x80, 0x08, 0x80, 0x2a, 0x50, 0x25, +0x00, 0x02, 0xdd, 0x23, 0x81, 0x20, 0x4e, 0x03, 0x00, 0xba, 0x00, 0x05, 0x00, 0x0e, 0x4e, 0x02, +0x00, 0xb6, 0x4f, 0xc2, 0x00, 0x06, 0x02, 0x03, 0xff, 0xfa, 0x12, 0x05, 0x00, 0x01, 0x80, 0x4a, +0x50, 0x03, 0xff, 0xd0, 0x80, 0x26, 0x46, 0xf0, 0x00, 0xc0, 0x58, 0xf7, 0x8b, 0x94, 0xdd, 0x2f, +0x4e, 0x63, 0x00, 0xa5, 0xf1, 0x01, 0x4e, 0x12, 0x00, 0xa2, 0x4e, 0x82, 0x00, 0x0f, 0x46, 0xf0, +0x01, 0x08, 0x04, 0x17, 0x83, 0xea, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x07, 0x83, 0xed, 0x98, 0x01, +0x9c, 0x04, 0xe2, 0x08, 0x4e, 0xf2, 0x00, 0x93, 0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0f, 0x00, +0x04, 0x33, 0x00, 0x0a, 0x80, 0x08, 0x50, 0x13, 0x00, 0x18, 0x50, 0x23, 0x00, 0x1a, 0xdd, 0x23, +0x4e, 0x03, 0x00, 0x85, 0x00, 0x03, 0x00, 0x24, 0x50, 0x23, 0x00, 0x18, 0x58, 0x00, 0x00, 0x02, +0x10, 0x03, 0x00, 0x24, 0x84, 0x01, 0xa6, 0x7d, 0xae, 0x3e, 0x9c, 0x49, 0xae, 0x7d, 0x50, 0x03, +0xff, 0xd0, 0x84, 0x21, 0x46, 0xf0, 0x00, 0xc0, 0x58, 0xf7, 0x8b, 0x94, 0xdd, 0x2f, 0xd5, 0x6e, +0xf4, 0x01, 0x84, 0x06, 0x96, 0xf1, 0x44, 0x12, 0x00, 0x00, 0x44, 0x20, 0x70, 0x90, 0x46, 0xf0, +0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0xf0, 0x01, 0xd5, 0x35, 0x80, 0x81, 0x84, 0x06, +0x44, 0x12, 0x00, 0x00, 0x44, 0x20, 0x70, 0x91, 0x84, 0x60, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x89, 0x64, 0xdd, 0x2f, 0x85, 0x20, 0xd5, 0x52, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x23, +0xc8, 0x08, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0xc8, 0x03, 0xa6, 0x38, 0xc0, 0x0b, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd7, 0x80, 0x41, 0x44, 0x00, 0x70, 0x1d, +0x80, 0x61, 0xdd, 0x24, 0x84, 0x06, 0x44, 0x12, 0x00, 0x00, 0x44, 0x20, 0x70, 0x94, 0x84, 0x60, +0x84, 0x8b, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x07, 0x87, 0x7c, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x82, 0xfc, 0xdd, 0x2f, +0xd5, 0xd2, 0xa6, 0x3b, 0xc0, 0x09, 0xa6, 0x7c, 0x4c, 0x10, 0x40, 0x07, 0x46, 0xf0, 0x01, 0x08, +0x00, 0x07, 0x8f, 0x8f, 0xc0, 0x0d, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xe2, 0x84, 0x01, +0xdd, 0x21, 0x84, 0xaf, 0xde, 0x05, 0xc0, 0x04, 0x44, 0x90, 0x00, 0x1f, 0xd5, 0x02, 0x85, 0x20, +0x80, 0x86, 0x84, 0x06, 0x44, 0x12, 0x00, 0x00, 0x44, 0x20, 0x70, 0x93, 0x40, 0x34, 0x80, 0x13, +0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x80, 0x09, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0xa2, 0xd8, 0x1b, +0x46, 0xf0, 0x01, 0x0f, 0x02, 0x27, 0x81, 0xe1, 0xc2, 0x11, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x37, +0x81, 0xe0, 0xe2, 0x43, 0xe8, 0x0b, 0x84, 0x8a, 0x42, 0x31, 0x90, 0x24, 0x40, 0x21, 0x88, 0x76, +0x46, 0xf0, 0x01, 0x38, 0x12, 0x27, 0x84, 0xeb, 0xd5, 0x06, 0x84, 0x6a, 0x46, 0xf0, 0x01, 0x38, +0x12, 0x37, 0x84, 0xeb, 0x46, 0xf0, 0x00, 0x15, 0x58, 0xf7, 0x87, 0x60, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x48, 0x46, 0xf0, +0x00, 0x14, 0x58, 0xf7, 0x88, 0x74, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x89, 0xe8, 0xdd, 0x2f, 0x81, 0x00, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x02, 0x03, 0x00, 0xd3, 0x44, 0x10, 0x00, 0x17, 0x4c, 0x00, +0xc0, 0x05, 0x84, 0x00, 0x12, 0x03, 0x00, 0xd3, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x81, 0x68, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0xb2, 0x4e, 0x02, 0x01, 0x01, +0x00, 0x03, 0x01, 0xca, 0x4e, 0x03, 0x00, 0xfd, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x88, 0x32, +0xc8, 0x07, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0xae, 0x4e, 0x02, 0x00, 0xf2, 0x02, 0x03, +0x00, 0xc3, 0x44, 0x20, 0x00, 0x17, 0x4c, 0x01, 0x00, 0xec, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x07, +0x8e, 0xa8, 0x4e, 0x03, 0x00, 0xe6, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xa3, 0x54, 0x10, +0x82, 0x00, 0x4e, 0x13, 0x00, 0xde, 0x04, 0x03, 0x00, 0x6c, 0xc8, 0x07, 0x46, 0xf0, 0x00, 0x36, +0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0xd5, 0x08, 0x00, 0x03, 0x01, 0xae, 0x46, 0xf0, 0x00, 0x28, +0x58, 0xf7, 0x88, 0xec, 0xdd, 0x2f, 0x81, 0x20, 0xb4, 0x26, 0x00, 0x03, 0x01, 0xc6, 0x84, 0x41, +0x10, 0x03, 0x01, 0xc7, 0x4c, 0x11, 0x40, 0x07, 0x02, 0x03, 0x00, 0xcf, 0x40, 0x00, 0x08, 0x02, +0xd5, 0x03, 0x00, 0x03, 0x01, 0xd3, 0xc0, 0x31, 0x00, 0x03, 0x01, 0xd2, 0xc0, 0x03, 0x84, 0xec, +0xd5, 0x30, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x87, 0x38, 0x54, 0x00, 0x00, 0x20, 0xc8, 0x04, +0x44, 0x70, 0x00, 0x1a, 0xd5, 0x26, 0x00, 0x73, 0x01, 0x1c, 0x44, 0x00, 0x00, 0x28, 0x54, 0x73, +0x80, 0x28, 0x4c, 0x70, 0x40, 0x1b, 0x40, 0x04, 0x84, 0x09, 0xe2, 0x08, 0xe8, 0x1a, 0x40, 0x04, +0x00, 0x01, 0x5c, 0xf0, 0x27, 0x11, 0xe9, 0x03, 0x95, 0xd5, 0xd5, 0x13, 0x46, 0xf0, 0x00, 0x22, +0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, 0xc0, 0x0c, 0x00, 0x03, 0x01, 0xae, 0x46, 0xf0, 0x00, 0x22, +0x58, 0xf7, 0x8f, 0xd0, 0xdd, 0x2f, 0xc0, 0x04, 0x44, 0x70, 0x00, 0x21, 0xd5, 0x02, 0x84, 0xe0, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x88, 0xd8, 0xdd, 0x2f, 0x84, 0x21, 0x4c, 0x00, +0x80, 0x80, 0x00, 0x03, 0x01, 0xd1, 0xc8, 0x7c, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x88, 0x2f, +0xc8, 0x0a, 0x04, 0x23, 0x00, 0x6c, 0xca, 0x07, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x89, +0xe6, 0x02, 0xe8, 0x6e, 0xcf, 0x6f, 0x84, 0x01, 0x10, 0x03, 0x01, 0xd2, 0x44, 0x00, 0x02, 0x00, +0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x82, 0x70, 0xdd, 0x2f, 0x04, 0x03, 0x00, 0x6c, 0x84, 0x21, +0x4c, 0x00, 0xc0, 0x0f, 0x44, 0x00, 0x00, 0x34, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, +0x81, 0xdc, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x00, 0xa7, 0x88, 0x3c, 0xd5, 0x05, 0x46, 0xf0, +0x01, 0x01, 0x00, 0xa7, 0x88, 0x3d, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8e, 0xcc, +0xdd, 0x2f, 0x80, 0x06, 0x44, 0x10, 0x00, 0x13, 0x46, 0xf0, 0x00, 0x16, 0x58, 0xf7, 0x84, 0x54, +0xdd, 0x2f, 0x00, 0x13, 0x01, 0xc2, 0x84, 0x43, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x20, 0xd5, 0x02, +0x84, 0x21, 0x93, 0x21, 0x8b, 0x09, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x85, 0xb0, +0x8b, 0x0a, 0x80, 0x66, 0x80, 0x82, 0x84, 0xa1, 0x46, 0x10, 0x00, 0x11, 0x58, 0x10, 0x8d, 0x40, +0x80, 0x08, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x10, 0x03, 0x01, 0xf1, +0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x87, 0xf0, 0x46, 0xf0, 0x01, 0x01, 0x02, 0x17, 0x83, 0xfa, +0x98, 0x08, 0x40, 0x04, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x54, 0xdd, 0x2f, +0x14, 0x03, 0x00, 0x0a, 0x00, 0x33, 0x01, 0xae, 0x80, 0x80, 0x84, 0x21, 0x84, 0x06, 0x44, 0x20, +0x70, 0x69, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0xd5, 0x03, 0x44, 0x70, +0x00, 0x21, 0x80, 0x07, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x27, 0x85, 0xc8, 0x81, 0x40, 0xca, 0x10, +0x46, 0xf0, 0x01, 0x10, 0x00, 0x17, 0x86, 0x2a, 0xc9, 0x0b, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, +0x8a, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x17, 0x82, 0x83, 0x48, 0x00, 0x00, 0x83, 0x46, 0x90, +0x01, 0x38, 0x00, 0x04, 0x8a, 0x01, 0xc0, 0x7d, 0x46, 0x80, 0x01, 0x38, 0x04, 0x14, 0x02, 0x83, +0xc1, 0x78, 0x46, 0x70, 0x01, 0x10, 0x58, 0x73, 0x85, 0xc0, 0x00, 0x63, 0x80, 0x74, 0xce, 0x05, +0x04, 0x03, 0x80, 0x1f, 0xe6, 0x0f, 0xe9, 0x0b, 0x84, 0x00, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, +0x8a, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x07, 0x82, 0x83, 0xd5, 0x63, 0x80, 0x01, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x5c, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x36, +0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x9c, 0x02, 0x04, 0x73, 0x80, 0x1e, 0x41, 0xc0, 0x10, 0x08, +0x41, 0xce, 0x14, 0x09, 0x41, 0xce, 0x04, 0x08, 0x8a, 0xfc, 0x40, 0x73, 0xc0, 0x08, 0x84, 0x22, +0x44, 0x00, 0x00, 0xff, 0x46, 0xf0, 0x00, 0xbe, 0x58, 0xf7, 0x88, 0x08, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x37, 0x80, 0xbc, 0x84, 0x21, 0x80, 0x0a, 0x84, 0x42, 0xdd, 0x23, 0x00, 0x04, +0x8a, 0x01, 0x92, 0xf1, 0xe2, 0xe0, 0xe8, 0x06, 0x10, 0x64, 0x8a, 0x01, 0x14, 0x64, 0x02, 0x83, +0xd5, 0x0b, 0x9e, 0x03, 0x98, 0x00, 0x41, 0xce, 0x00, 0x00, 0x41, 0xce, 0x10, 0x08, 0x41, 0xce, +0x10, 0x09, 0x15, 0xc4, 0x02, 0x83, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x83, 0x80, 0x67, +0x84, 0x07, 0x44, 0x10, 0x10, 0x00, 0x44, 0x20, 0x90, 0x74, 0x46, 0x60, 0x00, 0x35, 0x58, 0x63, +0x05, 0x60, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x8a, 0x01, 0x40, 0x00, +0x20, 0x08, 0x54, 0x35, 0x00, 0xff, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x47, 0x81, 0x8e, 0x40, 0x31, +0x80, 0x04, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x75, 0x4b, 0xe0, 0x18, 0x01, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, +0x01, 0x10, 0x58, 0x63, 0x05, 0xc0, 0x02, 0x13, 0x00, 0x39, 0x81, 0x00, 0x5c, 0xf0, 0x80, 0xff, +0xe8, 0x64, 0x04, 0x13, 0x00, 0x1b, 0xc1, 0x61, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x5a, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, +0xdd, 0x2f, 0x00, 0x13, 0x00, 0x8c, 0x80, 0x60, 0x04, 0x03, 0x00, 0x1e, 0xc9, 0x05, 0x04, 0x23, +0x00, 0x22, 0xe6, 0x4f, 0xe9, 0x20, 0x9c, 0xda, 0x94, 0xdc, 0x92, 0x65, 0x94, 0xd9, 0x9b, 0x83, +0x46, 0x10, 0x01, 0x10, 0x58, 0x10, 0x85, 0xc0, 0x40, 0x63, 0x40, 0x08, 0x02, 0x20, 0x80, 0x39, +0x92, 0xd1, 0xe2, 0x46, 0xe8, 0x0c, 0x00, 0x00, 0x80, 0x70, 0x80, 0xc2, 0x9a, 0x90, 0x98, 0x92, +0x98, 0xda, 0x94, 0xdc, 0x92, 0x64, 0x14, 0x30, 0x80, 0x1b, 0xd5, 0x08, 0x84, 0x00, 0x14, 0x00, +0x80, 0x1b, 0xd5, 0x04, 0x14, 0x13, 0x00, 0x1b, 0x80, 0xc1, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x77, +0x81, 0x94, 0x84, 0xa1, 0xdf, 0x22, 0x46, 0x20, 0x04, 0x90, 0x04, 0x41, 0x00, 0x0e, 0x46, 0xf0, +0x01, 0x10, 0x02, 0x17, 0x83, 0x1c, 0x40, 0x42, 0x40, 0x08, 0x40, 0x42, 0x04, 0x04, 0x84, 0x07, +0x44, 0x10, 0x08, 0x00, 0x44, 0x20, 0x90, 0x4b, 0x80, 0x66, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x85, 0x60, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x47, 0x80, 0xb6, 0x46, 0x00, 0x08, 0x00, +0x80, 0x27, 0x96, 0xb0, 0x84, 0x60, 0xdd, 0x24, 0x80, 0x08, 0x46, 0xf0, 0x00, 0xc1, 0x58, 0xf7, +0x82, 0xa0, 0xdd, 0x2f, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x46, 0x60, 0x01, 0x10, 0x58, 0x63, 0x05, 0xc0, 0x00, 0x13, 0x00, 0x74, 0x81, 0x00, 0xc1, 0x27, +0x46, 0x00, 0x04, 0x90, 0x04, 0x30, 0x00, 0x0e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0x84, 0x22, 0x84, 0x07, 0x44, 0x20, 0x90, 0x10, 0xdd, 0x24, 0x00, 0x13, 0x00, 0x88, 0x02, 0x43, +0x00, 0x3c, 0x02, 0x03, 0x00, 0x42, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x42, 0x40, 0x08, 0x54, 0x34, +0x00, 0xff, 0x40, 0x31, 0x84, 0x04, 0x40, 0x42, 0x00, 0x04, 0x84, 0x22, 0x84, 0x07, 0x44, 0x20, +0x90, 0x11, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x46, 0x60, 0x01, 0x10, +0x58, 0x63, 0x05, 0xc0, 0x00, 0x03, 0x00, 0x74, 0x4e, 0x02, 0x00, 0xed, 0x00, 0x33, 0x00, 0x8c, +0xc3, 0x19, 0x04, 0x13, 0x00, 0x1e, 0x04, 0x23, 0x00, 0x21, 0x9a, 0x91, 0x00, 0x73, 0x00, 0x8d, +0x46, 0xf0, 0x01, 0x10, 0x04, 0x17, 0x80, 0x99, 0x94, 0x94, 0x92, 0x44, 0x98, 0x91, 0x56, 0x73, +0x80, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x10, 0x14, 0x27, 0x80, 0x99, 0x40, 0x70, 0x9c, 0x06, +0xd5, 0x65, 0x04, 0x03, 0x00, 0x22, 0xe6, 0x0f, 0xe9, 0x18, 0x84, 0xa2, 0x4c, 0x82, 0xc0, 0xcb, +0x04, 0x13, 0x00, 0x1e, 0x04, 0x23, 0x00, 0x21, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, +0x9a, 0x91, 0x04, 0x30, 0x00, 0x0d, 0x94, 0x94, 0x92, 0x44, 0x98, 0xd3, 0x84, 0x21, 0x14, 0x20, +0x00, 0x0f, 0x14, 0x30, 0x00, 0x0d, 0xd5, 0x49, 0x04, 0x13, 0x00, 0x1e, 0x04, 0x23, 0x00, 0x21, +0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, 0x9a, 0x91, 0x04, 0x40, 0x00, 0x0c, 0x46, 0x90, +0x01, 0x38, 0x94, 0x94, 0x92, 0x44, 0x00, 0x14, 0x8a, 0x01, 0x99, 0x14, 0x14, 0x20, 0x00, 0x0e, +0x14, 0x40, 0x00, 0x0c, 0xc9, 0x02, 0xd5, 0x31, 0x46, 0x70, 0x01, 0x38, 0x58, 0x73, 0x8a, 0x0c, +0xb4, 0x07, 0xc8, 0x19, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x00, 0x14, +0x8a, 0x01, 0x9c, 0x02, 0x04, 0x33, 0x00, 0x21, 0x9e, 0x4b, 0x94, 0x04, 0x92, 0x05, 0x94, 0x01, +0x98, 0x49, 0x98, 0x41, 0x9a, 0xd8, 0x40, 0x31, 0xc0, 0x08, 0x94, 0x4c, 0x92, 0x24, 0xb6, 0x27, +0x92, 0x71, 0xd5, 0x04, 0x10, 0x34, 0x8a, 0x01, 0xb6, 0x67, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, +0x82, 0x83, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x77, 0x46, 0xf0, 0x00, 0x35, +0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0xe1, 0x46, 0x30, 0x01, 0x10, 0x58, 0x31, +0x85, 0xc0, 0x84, 0x00, 0x10, 0x01, 0x80, 0x74, 0x00, 0x01, 0x80, 0x8c, 0x04, 0x21, 0x80, 0x21, +0x10, 0x01, 0x80, 0x80, 0x04, 0x01, 0x80, 0x22, 0x14, 0x21, 0x80, 0x1e, 0x14, 0x01, 0x80, 0x1f, +0xc1, 0x08, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xd8, 0x84, 0x20, 0x84, 0x01, 0xdd, 0x22, +0x46, 0x60, 0x01, 0x10, 0x58, 0x63, 0x05, 0xc0, 0x00, 0x33, 0x00, 0x80, 0x40, 0x31, 0xa0, 0x08, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x40, 0x33, 0x8c, 0x04, 0x84, 0x07, 0x44, 0x10, +0x08, 0x00, 0x44, 0x20, 0x90, 0x4c, 0xdd, 0x24, 0xc7, 0x3d, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, +0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x9c, 0x01, 0x94, 0x04, 0x92, 0x05, 0x94, 0x01, 0x04, 0x73, +0x00, 0x1e, 0x96, 0x81, 0x9b, 0xfa, 0x40, 0x73, 0xc0, 0x08, 0x02, 0x13, 0x00, 0x39, 0x92, 0xf1, +0xe2, 0x27, 0xe8, 0x0b, 0x00, 0x33, 0x00, 0x70, 0x80, 0xe1, 0x9a, 0x4b, 0x98, 0x49, 0x98, 0x01, +0x94, 0x04, 0x92, 0x04, 0x14, 0x03, 0x00, 0x1b, 0x46, 0xf0, 0x01, 0x10, 0x02, 0x07, 0x83, 0x1c, +0x40, 0x21, 0x40, 0x08, 0x40, 0x41, 0x00, 0x04, 0x44, 0x10, 0x08, 0x00, 0x84, 0x07, 0x44, 0x20, +0x90, 0x4a, 0x80, 0x67, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x47, 0x80, 0xb6, 0x46, 0x00, 0x08, 0x00, 0x96, 0xb8, 0x84, 0x21, 0x84, 0x60, +0xdd, 0x24, 0x46, 0x60, 0x01, 0x10, 0x58, 0x63, 0x05, 0xc0, 0x04, 0x03, 0x00, 0x21, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x1f, 0x00, 0x03, 0x00, 0x74, 0xc0, 0x1c, +0x02, 0x03, 0x00, 0x42, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x40, 0x34, 0x40, 0x08, +0x40, 0x31, 0x80, 0x04, 0x44, 0x10, 0x08, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x50, 0xdd, 0x24, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd7, 0x04, 0x33, 0x00, 0x21, 0x80, 0x48, 0x44, 0x00, +0x90, 0x50, 0x84, 0x20, 0xdd, 0x24, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xe0, 0x00, 0x00, 0x00, 0x22, 0xc0, 0x03, 0x84, 0xc0, 0xd5, 0x30, +0x84, 0x21, 0x00, 0x83, 0x80, 0x20, 0x44, 0x00, 0x00, 0x26, 0x80, 0xa1, 0xe7, 0x08, 0xe9, 0x03, +0x97, 0x80, 0xd5, 0x02, 0x97, 0x88, 0x40, 0x23, 0x14, 0x09, 0x46, 0x30, 0x01, 0x13, 0x58, 0x31, +0x8a, 0x18, 0x94, 0x92, 0x98, 0x93, 0xb4, 0x62, 0x40, 0x42, 0x98, 0x0c, 0x40, 0x92, 0x0c, 0x02, +0x4e, 0x92, 0x00, 0x0b, 0x40, 0x42, 0x10, 0x05, 0x40, 0x32, 0x0c, 0x02, 0xb6, 0x62, 0x5c, 0xf0, +0x80, 0x27, 0xe9, 0x0e, 0xd5, 0x07, 0x9c, 0x49, 0x44, 0x20, 0x00, 0x27, 0x9e, 0x01, 0x4c, 0x11, +0x7f, 0xdf, 0x84, 0x09, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x8d, 0xe4, 0xdd, 0x2f, 0x80, 0x06, +0x10, 0x63, 0x80, 0x21, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x98, 0xbc, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x13, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x23, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x8c, 0x80, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x10, 0x00, 0x07, 0x85, 0xf9, 0x46, 0x10, 0x00, 0x34, 0x58, 0x10, 0x88, 0x54, +0xc0, 0x04, 0x44, 0x00, 0x18, 0x00, 0xd5, 0x03, 0x44, 0x00, 0x10, 0x00, 0x4b, 0xe0, 0x04, 0x01, +0x46, 0xf0, 0x01, 0x0a, 0x14, 0x07, 0x83, 0x13, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, 0x84, 0xc0, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xee, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xb9, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x15, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x80, 0x27, 0x84, 0x02, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x15, +0x84, 0x24, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, 0x86, 0x78, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe8, 0x54, 0x80, 0x00, 0xff, 0x4e, 0x82, 0x00, 0x05, +0x44, 0x70, 0x00, 0x11, 0xd5, 0x09, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x15, 0x04, 0x00, +0x00, 0x0a, 0x00, 0x70, 0x00, 0x2c, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x0c, 0x38, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x04, 0x33, 0x00, 0x0a, 0x84, 0x03, 0x44, 0x10, 0x08, 0x00, +0x44, 0x20, 0x10, 0x62, 0xdd, 0x24, 0x04, 0x33, 0x00, 0x0a, 0xcb, 0x58, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x07, 0x88, 0x2a, 0xc0, 0x31, 0x46, 0x20, 0x01, 0x38, 0x00, 0x01, 0x09, 0xed, 0x84, 0xa1, +0x46, 0x10, 0x00, 0x2a, 0x58, 0x10, 0x84, 0xb8, 0x46, 0x90, 0x01, 0x38, 0xd8, 0x20, 0x10, 0x31, +0x09, 0xed, 0x44, 0x00, 0x00, 0x18, 0x4b, 0xe0, 0x04, 0x01, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, +0x84, 0xc0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x27, 0x85, 0xf9, 0x10, 0x04, 0x89, 0xee, +0x46, 0x10, 0x00, 0x34, 0x58, 0x10, 0x88, 0x54, 0xc2, 0x04, 0x44, 0x00, 0x18, 0x00, 0xd5, 0x03, +0x44, 0x00, 0x10, 0x00, 0x4b, 0xe0, 0x04, 0x01, 0xa8, 0x35, 0xd5, 0x0d, 0x00, 0x04, 0x89, 0xee, +0x4b, 0xe0, 0x04, 0x01, 0xd5, 0x08, 0x44, 0x00, 0x00, 0x18, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, +0x84, 0xb8, 0xdd, 0x2f, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x0c, 0x38, 0xb4, 0x06, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x88, 0x54, 0xdd, 0x2f, 0xa8, 0x33, 0xa0, 0x77, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x2e, 0x58, 0xf7, 0x8a, 0x98, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x27, +0x84, 0x02, 0xdd, 0x21, 0x84, 0x03, 0x14, 0x03, 0x00, 0x0a, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, +0x0c, 0x38, 0x04, 0x13, 0x00, 0x0a, 0x85, 0x26, 0x4c, 0x14, 0x80, 0xb3, 0xe6, 0x27, 0xe8, 0x11, +0x85, 0x43, 0x4c, 0x15, 0x00, 0x23, 0xe6, 0x24, 0xe8, 0x06, 0x84, 0xa1, 0x4c, 0x12, 0xc1, 0xaf, +0x48, 0x00, 0x01, 0xb4, 0x84, 0xa4, 0xd1, 0x29, 0x84, 0xa5, 0x4c, 0x12, 0xc1, 0xa8, 0xd5, 0x7d, +0x85, 0x49, 0x4c, 0x15, 0x01, 0x32, 0xe6, 0x2a, 0xe8, 0x09, 0x84, 0xa7, 0x4c, 0x12, 0x80, 0xce, +0x84, 0xa8, 0x4c, 0x12, 0xc1, 0x9c, 0x48, 0x00, 0x01, 0x12, 0x84, 0xaa, 0x4c, 0x12, 0x81, 0x50, +0x84, 0xac, 0x4c, 0x12, 0xc1, 0x94, 0xd5, 0x3d, 0xa0, 0x33, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x03, 0x48, 0x00, 0x00, 0xfb, 0x46, 0xf0, 0x00, 0xc1, 0x58, 0xf7, +0x87, 0xf0, 0xdd, 0x2f, 0x48, 0x00, 0x01, 0x7d, 0x4e, 0x82, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0xc1, +0x58, 0xf7, 0x87, 0xf0, 0xdd, 0x2f, 0x84, 0x0c, 0x14, 0x03, 0x00, 0x0a, 0x48, 0x00, 0x01, 0x7e, +0x8c, 0xac, 0x4c, 0x72, 0xc0, 0xcb, 0xa0, 0xb7, 0x46, 0x00, 0x04, 0x90, 0x04, 0x10, 0x00, 0x0e, +0xa0, 0x15, 0x98, 0x08, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x84, 0x48, +0x46, 0xf0, 0x01, 0x0a, 0x14, 0x27, 0x82, 0xd4, 0xa0, 0x31, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x54, 0xdd, 0x2f, 0x84, 0x25, 0x14, 0x13, 0x00, 0x0a, 0xa8, 0x34, 0x48, 0x00, 0x01, 0x5e, +0x9d, 0x6c, 0xdf, 0x10, 0x84, 0x48, 0xa0, 0x31, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x27, 0x82, 0xd4, +0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x54, 0xdd, 0x2f, 0xa8, 0x34, 0x14, 0x93, 0x00, 0x0a, +0xd5, 0x13, 0xa0, 0x33, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x09, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x6a, 0x84, 0x02, 0xdd, 0x21, 0x84, 0x01, 0xd5, 0x02, +0x84, 0x04, 0x14, 0x03, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x86, 0x2e, 0x4e, 0x02, +0x01, 0x35, 0x84, 0x21, 0x48, 0x00, 0x00, 0xdf, 0xa0, 0x34, 0x46, 0x70, 0x00, 0x34, 0x58, 0x73, +0x88, 0x18, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x08, 0xa0, 0x33, 0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x02, +0x01, 0x13, 0x48, 0x00, 0x00, 0x8d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xb9, 0xa0, 0x37, +0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x27, 0x80, 0x0a, 0xdd, 0x21, 0xa0, 0x37, +0x84, 0x28, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, 0x82, 0x5c, 0xdd, 0x2f, 0xd5, 0x7b, 0x4e, 0x82, +0x00, 0x12, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xb9, 0xa0, 0x37, 0xdd, 0x21, 0xa0, 0x37, +0x84, 0x28, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, 0x82, 0x5c, 0xdd, 0x2f, 0x84, 0x07, 0x48, 0xff, +0xff, 0x7d, 0x44, 0x50, 0x00, 0x10, 0xdf, 0x1e, 0xa0, 0x32, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x54, 0xdd, 0x2f, 0x84, 0x42, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x27, 0x82, 0xd4, 0xa8, 0x36, +0x46, 0xf0, 0x00, 0x32, 0x58, 0xf7, 0x80, 0xc0, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x01, 0x58, 0x00, +0x07, 0x14, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x3c, 0xdd, 0x2f, 0x84, 0x08, 0x48, 0xff, +0xff, 0x5d, 0x84, 0x05, 0x48, 0xff, 0xff, 0x5a, 0x8c, 0xa9, 0xdf, 0x2b, 0xa0, 0x32, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x88, 0x54, 0xdd, 0x2f, 0x84, 0x42, 0xa8, 0x36, 0x46, 0xf0, 0x01, 0x0a, +0x14, 0x27, 0x82, 0xd4, 0x46, 0xf0, 0x00, 0x32, 0x58, 0xf7, 0x80, 0xc0, 0xdd, 0x2f, 0x46, 0x00, +0x01, 0x01, 0x58, 0x00, 0x07, 0x14, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x3c, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xb9, 0xa0, 0x37, 0xdd, 0x21, 0xa0, 0x37, 0x46, 0xf0, +0x00, 0x50, 0x58, 0xf7, 0x8f, 0xc0, 0xdd, 0x2f, 0x14, 0xa3, 0x00, 0x0a, 0x48, 0x00, 0x00, 0xae, +0xa0, 0x34, 0x46, 0x70, 0x00, 0x34, 0x58, 0x73, 0x88, 0x18, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x12, +0xa0, 0x33, 0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x02, 0x00, 0x8f, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, +0x85, 0xee, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x83, 0x00, 0xdd, 0x2f, 0x84, 0x01, 0x48, 0xff, +0xff, 0x15, 0x14, 0x93, 0x00, 0x0a, 0x48, 0x00, 0x00, 0x91, 0xa0, 0x36, 0x46, 0x70, 0x00, 0x34, +0x58, 0x73, 0x88, 0x18, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0xcc, 0xa0, 0x33, 0x4b, 0xe0, 0x1c, 0x01, +0xc0, 0x02, 0xd5, 0xed, 0xa0, 0x77, 0x04, 0x33, 0x00, 0x09, 0x04, 0x10, 0x80, 0x0a, 0x04, 0x23, +0x00, 0x08, 0xa8, 0xc9, 0xd5, 0x62, 0x4e, 0x82, 0x00, 0x11, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xb9, 0xa0, 0x37, 0xdd, 0x21, 0xa0, 0x37, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x8f, 0xc0, +0xdd, 0x2f, 0x84, 0x0a, 0x48, 0xff, 0xfe, 0xea, 0x8e, 0xf0, 0xe6, 0xe2, 0xe9, 0x12, 0xa0, 0x37, +0x84, 0x45, 0x04, 0x10, 0x00, 0x0a, 0x00, 0x30, 0x80, 0x31, 0x42, 0x11, 0x88, 0x73, 0x00, 0x10, +0x80, 0x35, 0xc9, 0x07, 0x84, 0x2b, 0x14, 0x13, 0x00, 0x0a, 0x84, 0x22, 0xa8, 0x41, 0xd5, 0x55, +0x84, 0x28, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x83, 0x18, 0xd5, 0x4f, 0x8e, 0xf0, 0xe6, 0xe2, +0xe9, 0x1f, 0xa0, 0x37, 0x84, 0x25, 0x04, 0x00, 0x00, 0x0a, 0x00, 0x20, 0x00, 0x31, 0x42, 0x01, +0x04, 0x73, 0x00, 0x70, 0x00, 0x35, 0xcf, 0x14, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x6a, +0x84, 0x07, 0xdd, 0x21, 0xa0, 0x37, 0x84, 0x2b, 0x14, 0x13, 0x00, 0x0a, 0x84, 0x22, 0xa8, 0x41, +0x80, 0x07, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x83, 0x00, 0xdd, 0x2f, 0xd5, 0x2e, 0xa0, 0x36, +0x46, 0x70, 0x00, 0x34, 0x58, 0x73, 0x88, 0x18, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x1c, 0xa0, 0x33, +0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x02, 0xd5, 0x82, 0xa0, 0x77, 0x04, 0x43, 0x00, 0x09, 0x04, 0x10, +0x80, 0x0a, 0x04, 0x23, 0x00, 0x08, 0xa9, 0x09, 0xb6, 0x41, 0xa0, 0x77, 0x04, 0x10, 0x80, 0x0a, +0x10, 0x00, 0x80, 0x33, 0x46, 0xf0, 0x00, 0x32, 0x58, 0xf7, 0x80, 0xf8, 0xdd, 0x2f, 0x84, 0x04, +0x48, 0xff, 0xfe, 0x8c, 0x84, 0x09, 0x48, 0xff, 0xfe, 0x89, 0x44, 0x00, 0x00, 0x20, 0x46, 0xf0, +0x00, 0x0d, 0x58, 0xf7, 0x8d, 0xe4, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x67, 0x83, 0x18, +0x84, 0xa1, 0xde, 0x33, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x8b, 0x90, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, 0x8c, 0x6c, 0xdd, 0x2f, 0x84, 0xa2, 0xd8, 0x0d, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x17, 0x80, 0x27, 0x84, 0x00, 0xdd, 0x21, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x2c, +0x58, 0xf7, 0x83, 0x00, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x67, 0x83, 0x15, 0x46, 0xf0, +0x00, 0x28, 0x58, 0xf7, 0x82, 0xf0, 0xdd, 0x2f, 0x00, 0x10, 0x00, 0x0e, 0x04, 0x03, 0x00, 0x0a, +0x54, 0x10, 0x80, 0x07, 0x10, 0x10, 0x00, 0x33, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x17, 0x83, 0xe1, +0x84, 0x44, 0x50, 0x0f, 0x80, 0x04, 0xd5, 0x1e, 0x84, 0xab, 0xde, 0x24, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x2e, 0x58, 0xf7, 0x8b, 0x90, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x02, 0x27, 0x83, 0xbe, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0xdd, 0x40, 0x14, 0x8c, 0x08, 0x42, 0x01, 0x04, 0x73, +0x84, 0x22, 0xa8, 0x41, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x17, 0x83, 0xe0, 0x84, 0x40, 0x50, 0x0f, +0x80, 0x04, 0xb6, 0x40, 0xc1, 0x02, 0xdd, 0x21, 0x84, 0x22, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, +0x83, 0x18, 0xec, 0x18, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x81, 0x21, 0x50, 0x60, 0x00, 0xac, 0x97, 0xd0, 0x04, 0x80, 0x00, 0x2d, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x8c, 0xb0, 0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x03, 0x84, 0xe0, 0xd5, 0x5e, 0x80, 0x47, +0x80, 0x29, 0x50, 0x03, 0x7f, 0x54, 0x46, 0xf0, 0x00, 0x1d, 0x58, 0xf7, 0x8d, 0xd4, 0xdd, 0x2f, +0x80, 0xe0, 0xa1, 0x72, 0x4c, 0x82, 0x80, 0x52, 0x84, 0x00, 0x10, 0x03, 0x00, 0x21, 0x46, 0xf0, +0x01, 0x10, 0x00, 0x17, 0x85, 0xf9, 0xc1, 0x49, 0x46, 0xf0, 0x01, 0x10, 0x02, 0x17, 0x83, 0x06, +0x44, 0x50, 0x00, 0xff, 0xd1, 0x42, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xe0, +0xdd, 0x2f, 0x04, 0x00, 0x00, 0x6c, 0x84, 0xa1, 0xd8, 0x38, 0x80, 0x08, 0x94, 0x6c, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x87, 0x58, 0xdd, 0x2f, 0xf0, 0x81, 0x85, 0x00, 0x47, 0xc0, 0x00, 0x34, +0x59, 0xce, 0x07, 0xf0, 0x46, 0xa0, 0x00, 0x34, 0x58, 0xa5, 0x07, 0x2c, 0x46, 0x90, 0x00, 0x1d, +0x58, 0x94, 0x88, 0x6c, 0xd5, 0x14, 0xa4, 0x77, 0xa0, 0x31, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x40, +0xa8, 0x31, 0x04, 0x03, 0x00, 0x41, 0x84, 0xa1, 0xd8, 0x08, 0xa0, 0x72, 0x50, 0x03, 0x7f, 0x54, +0x4b, 0xe0, 0x24, 0x01, 0xa8, 0x32, 0xd5, 0x02, 0xa8, 0xb2, 0x85, 0x01, 0xa0, 0x32, 0xf1, 0x01, +0xdd, 0x3c, 0xc8, 0xea, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x09, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0x9e, 0x00, 0x03, 0x01, 0x02, 0xdd, 0x21, 0x80, 0x07, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x90, 0xf3, 0x81, 0xb6, 0x5f, 0x80, 0xe0, +0x81, 0x21, 0x84, 0xc0, 0x47, 0xc0, 0x00, 0x34, 0x59, 0xce, 0x07, 0x58, 0x46, 0xa0, 0x00, 0x34, +0x58, 0xa5, 0x07, 0xf0, 0x80, 0x07, 0xce, 0x04, 0xb4, 0x3f, 0x84, 0xa2, 0xd9, 0x0d, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x81, 0xec, 0xdd, 0x21, 0x00, 0x03, 0x80, 0xb6, 0x46, 0xf0, 0x00, 0x3b, +0x58, 0xf7, 0x8d, 0xf0, 0xdd, 0x2f, 0x02, 0x13, 0x80, 0x19, 0xb4, 0x09, 0xdd, 0x3c, 0xb6, 0x09, +0x80, 0x20, 0xf0, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x9c, 0x71, 0xc8, 0x03, 0x97, 0x89, 0xd5, 0xe3, +0x80, 0x06, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc1, +0x80, 0xe0, 0xc1, 0x02, 0xc8, 0x07, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x0a, 0x10, 0x17, 0x8b, 0x7f, +0xd5, 0x5c, 0x46, 0xf0, 0x01, 0x0a, 0x00, 0x17, 0x8b, 0x7d, 0x84, 0xa1, 0xd1, 0x2b, 0x46, 0xf0, +0x00, 0x3f, 0x58, 0xf7, 0x8f, 0x24, 0xdd, 0x2f, 0xc8, 0x25, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, +0x82, 0xd7, 0x00, 0x53, 0x80, 0x21, 0x00, 0x00, 0x00, 0x21, 0xd0, 0x04, 0x44, 0x50, 0x00, 0x20, +0xde, 0x19, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xd9, 0x4c, 0x03, 0x00, 0x0c, 0x46, 0xf0, +0x01, 0x0a, 0x00, 0x17, 0x8b, 0x81, 0xc9, 0x06, 0x44, 0x50, 0x00, 0x20, 0xd0, 0x0b, 0x84, 0xa7, +0xd0, 0x09, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x0b, 0x5c, 0x00, 0x10, 0x00, 0x23, 0x84, 0xa1, +0xd9, 0x18, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x0b, 0x5c, 0x84, 0x21, 0x10, 0x10, 0x00, 0x21, +0x84, 0x20, 0x10, 0x10, 0x00, 0x23, 0xb4, 0x20, 0xa0, 0x02, 0x40, 0x43, 0x40, 0x08, 0x00, 0x30, +0x80, 0x20, 0x40, 0x42, 0x00, 0x04, 0x84, 0x28, 0x84, 0x03, 0x44, 0x20, 0x10, 0x43, 0xd5, 0x10, +0x84, 0x20, 0x10, 0x10, 0x00, 0x21, 0xb4, 0x20, 0xa0, 0x02, 0x40, 0x43, 0x40, 0x08, 0x00, 0x30, +0x80, 0x20, 0x40, 0x42, 0x00, 0x04, 0x94, 0x6d, 0x84, 0x03, 0x44, 0x20, 0x10, 0x44, 0x46, 0xf0, +0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x02, 0xec, 0xa4, 0x34, 0x54, 0x00, 0x02, 0x00, +0xc0, 0x0a, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xa4, 0x74, 0x42, 0x10, +0xa4, 0x09, 0xac, 0x74, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, +0x01, 0x0f, 0x02, 0x57, 0x81, 0x7a, 0x96, 0x00, 0x54, 0x62, 0x82, 0x00, 0x96, 0x48, 0x96, 0x90, +0x96, 0xd8, 0xc6, 0x04, 0x44, 0x00, 0x00, 0x1f, 0xd5, 0x0c, 0x58, 0x52, 0x82, 0x00, 0x46, 0xf0, +0x01, 0x0f, 0x12, 0x57, 0x81, 0x7a, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x8e, 0xfc, 0xdd, 0x2f, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x20, 0x00, 0x6c, 0x80, 0xe1, +0x56, 0x11, 0x00, 0x01, 0x00, 0x83, 0x80, 0x00, 0x10, 0x10, 0x01, 0xc7, 0x80, 0xc0, 0xa6, 0x78, +0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, 0x80, 0x38, 0xdd, 0x2f, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x1d, +0x00, 0x13, 0x01, 0xae, 0xe6, 0x29, 0xe8, 0x0f, 0x84, 0x0a, 0x42, 0x10, 0x80, 0x24, 0x46, 0x20, +0x01, 0x38, 0x58, 0x21, 0x0a, 0xb8, 0x98, 0x4a, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x98, 0xdd, 0x2f, 0x9c, 0xba, 0x84, 0x08, 0x50, 0x13, 0x01, 0x14, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x89, 0x98, 0xdd, 0x2f, 0x00, 0x13, 0x01, 0xf8, 0x84, 0x00, 0x58, 0x10, 0x80, 0x01, +0x10, 0x13, 0x01, 0xf8, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xe1, +0xa6, 0x48, 0x80, 0xc0, 0x84, 0x01, 0x00, 0x83, 0x80, 0x01, 0x4c, 0x10, 0x40, 0x1d, 0x00, 0x13, +0x01, 0xae, 0xe6, 0x29, 0xe8, 0x0f, 0x84, 0x0a, 0x42, 0x10, 0x80, 0x24, 0x46, 0x20, 0x01, 0x38, +0x58, 0x21, 0x0a, 0xb8, 0x98, 0x4a, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x98, +0xdd, 0x2f, 0x84, 0x08, 0x50, 0x13, 0x01, 0x14, 0x9c, 0xba, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x98, 0xdd, 0x2f, 0x02, 0x03, 0x00, 0xd1, 0x44, 0x50, 0x00, 0x8f, 0xd8, 0x0e, 0x02, 0x03, +0x00, 0xd2, 0x44, 0x50, 0x22, 0x32, 0xd8, 0x09, 0x4e, 0x83, 0x00, 0x08, 0x00, 0x03, 0x01, 0x14, +0x58, 0x00, 0x00, 0x01, 0x10, 0x03, 0x01, 0x14, 0x00, 0x03, 0x01, 0xc1, 0x84, 0xa1, 0xd8, 0x1f, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xa3, 0x42, 0x00, 0x5c, 0x0b, 0xc8, 0x44, 0x44, 0x00, +0x00, 0x3d, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0xb4, 0xdd, 0x2f, 0xc0, 0x08, 0x80, 0x27, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8f, 0x0c, 0xdd, 0x2f, 0x80, 0x06, 0x84, 0x20, +0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x81, 0x70, 0xdd, 0x2f, 0xd5, 0x2d, 0xb4, 0x06, 0x84, 0xa1, +0xd0, 0x05, 0x84, 0xa4, 0xd0, 0x03, 0x84, 0xa8, 0xd8, 0x0e, 0x00, 0x13, 0x01, 0xf8, 0x84, 0xa3, +0xd9, 0x0a, 0x80, 0x27, 0x80, 0x06, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8f, 0x94, +0xdd, 0x2f, 0xd5, 0x19, 0x04, 0x13, 0x00, 0x6c, 0xc9, 0x0c, 0x84, 0xa1, 0xd0, 0x0a, 0x44, 0x00, +0x00, 0x33, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x81, 0xdc, 0xdd, 0x2f, 0xd5, 0x0b, +0x00, 0x03, 0x01, 0xf8, 0x84, 0xa3, 0xd0, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, +0x8f, 0xd4, 0xdd, 0x2f, 0x00, 0x13, 0x01, 0xf8, 0x84, 0x00, 0x58, 0x10, 0x80, 0x01, 0x10, 0x13, +0x01, 0xf8, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x86, 0x18, 0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x88, 0xc8, 0xdd, 0x2f, 0xc8, 0x0a, 0x80, 0x20, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, +0x80, 0xb1, 0x80, 0x41, 0x44, 0x00, 0x00, 0x33, 0xdd, 0x23, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc0, 0x50, 0x00, 0x7f, 0xc0, 0x80, 0xe2, 0x54, 0x80, +0x80, 0xff, 0xe6, 0x02, 0xe9, 0x04, 0x44, 0x50, 0x00, 0x33, 0xde, 0x08, 0x80, 0x06, 0x46, 0xf0, +0x00, 0xbc, 0x58, 0xf7, 0x8c, 0x38, 0xdd, 0x2f, 0xc8, 0x0a, 0x80, 0x08, 0x80, 0x46, 0x80, 0x67, +0x84, 0x21, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x58, 0xdd, 0x2f, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x97, 0x81, 0x80, 0x06, 0x81, 0x01, 0x46, 0xf0, 0x00, 0x23, +0x58, 0xf7, 0x80, 0x00, 0xdd, 0x2f, 0x80, 0xe0, 0xc0, 0x2f, 0x00, 0x00, 0x00, 0x42, 0x46, 0xf0, +0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0x80, 0xc0, 0xc0, 0x6f, 0x44, 0x10, 0x00, 0x16, +0x14, 0x10, 0x00, 0x29, 0x00, 0x10, 0x01, 0xb0, 0x84, 0x41, 0x10, 0x10, 0x01, 0xc7, 0xb6, 0x47, +0xa0, 0x7b, 0x84, 0x42, 0x4c, 0x11, 0x40, 0x11, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x23, 0x58, 0xf7, +0x84, 0xc0, 0xdd, 0x2f, 0x80, 0x06, 0x80, 0x27, 0x80, 0x48, 0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, +0x81, 0x7c, 0xdd, 0x2f, 0xd5, 0x52, 0x80, 0x27, 0x80, 0x48, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, +0x80, 0x80, 0xdd, 0x2f, 0xd5, 0x4a, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xe0, +0xdd, 0x2f, 0x80, 0xc0, 0xc0, 0x44, 0x02, 0x00, 0x00, 0xc3, 0x84, 0x27, 0x4c, 0x00, 0x80, 0x40, +0x50, 0x03, 0x01, 0xf0, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x04, 0x13, +0x00, 0x27, 0x84, 0x06, 0x42, 0x00, 0x80, 0x24, 0x80, 0x47, 0x46, 0x10, 0x00, 0x13, 0x58, 0x10, +0x85, 0x40, 0x80, 0x66, 0x80, 0x87, 0x84, 0xa1, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, +0xdd, 0x2f, 0xb4, 0x46, 0x10, 0x03, 0x01, 0xf0, 0x84, 0x04, 0x4c, 0x20, 0x40, 0x0b, 0x14, 0x83, +0x00, 0x2a, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x20, 0x58, 0xf7, 0x8b, 0x0c, 0xdd, 0x2f, 0xd5, 0x08, +0x80, 0x28, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x8f, 0x70, 0xdd, 0x2f, 0x00, 0x03, +0x01, 0xf0, 0xc0, 0x0b, 0x00, 0x03, 0x01, 0xf4, 0xc0, 0x08, 0x50, 0x03, 0x01, 0xf4, 0x46, 0xf0, +0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x12, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x01, 0x00, 0x04, 0x20, +0x83, 0xa3, 0x80, 0xc0, 0x40, 0x00, 0x00, 0x05, 0x40, 0x20, 0x08, 0x02, 0x54, 0x03, 0x02, 0x00, +0x14, 0x20, 0x83, 0xa3, 0xc0, 0x11, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x88, 0xc8, +0xdd, 0x2f, 0xc8, 0x0a, 0x80, 0x20, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x80, 0xb1, 0x80, 0x41, +0x44, 0x00, 0x00, 0x33, 0xdd, 0x23, 0x46, 0x50, 0x04, 0x00, 0xde, 0x06, 0x46, 0xf0, 0x00, 0x10, +0x58, 0xf7, 0x82, 0xa8, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x97, 0x88, 0x81, 0x00, 0x81, 0x22, 0x84, 0x01, 0x84, 0x20, 0x9c, 0xb6, +0x97, 0xd9, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x1d, 0xb4, 0x80, +0x9c, 0x74, 0x40, 0x03, 0xa0, 0x09, 0x84, 0x4e, 0xae, 0x61, 0x84, 0x21, 0xae, 0xa0, 0xae, 0x62, +0xae, 0x24, 0x10, 0x92, 0x00, 0x05, 0xaf, 0xe3, 0x80, 0x28, 0x9c, 0x26, 0x80, 0x46, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0xef, 0xe8, 0x81, 0x00, 0xa6, 0x00, 0x84, 0xa1, 0xd8, 0x5b, 0x46, 0xf0, 0x01, 0x10, +0x00, 0x67, 0x85, 0xf9, 0xce, 0x04, 0x81, 0x46, 0x80, 0x26, 0xd5, 0x26, 0x46, 0xf0, 0x01, 0x10, +0x04, 0x07, 0x81, 0x80, 0x00, 0x00, 0x00, 0x20, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, +0xdd, 0x2f, 0x04, 0x60, 0x00, 0x6d, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x35, 0x46, 0xf0, +0x01, 0x38, 0x04, 0xa7, 0x82, 0x36, 0xe6, 0xc3, 0xe9, 0x06, 0x9f, 0xb2, 0x97, 0xb0, 0x84, 0xa3, +0xd6, 0x04, 0xd5, 0x0a, 0x97, 0xb0, 0xd5, 0x08, 0x00, 0x20, 0x01, 0x1f, 0x84, 0x02, 0x54, 0x21, +0x00, 0x04, 0x40, 0x60, 0x08, 0x1a, 0x50, 0x7f, 0x80, 0x04, 0x46, 0x90, 0x00, 0x0d, 0x58, 0x94, +0x80, 0x48, 0x80, 0x07, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x2a, 0x50, 0x0f, 0x80, 0x08, 0x4b, 0xe0, +0x24, 0x01, 0x80, 0x07, 0x84, 0x29, 0x84, 0x40, 0x44, 0x30, 0xfc, 0x4d, 0x10, 0x63, 0x80, 0x08, +0x46, 0xf0, 0x00, 0xc2, 0x58, 0xf7, 0x83, 0xd0, 0xdd, 0x2f, 0x00, 0x04, 0x00, 0x01, 0x84, 0xa1, +0xd0, 0x06, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x07, 0x85, 0xf9, 0xc8, 0x15, 0x84, 0x00, 0x46, 0xf0, +0x01, 0x38, 0x14, 0x07, 0x82, 0x36, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x07, 0x82, 0x35, 0xd5, 0x0b, +0x84, 0x00, 0x80, 0x20, 0x84, 0x41, 0x44, 0x30, 0xfc, 0x4d, 0x46, 0xf0, 0x00, 0xc2, 0x58, 0xf7, +0x83, 0xd0, 0xdd, 0x2f, 0xec, 0x18, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0x54, 0x80, 0x80, 0xff, 0x80, 0x28, 0x80, 0xe0, 0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, +0x8e, 0x08, 0xdd, 0x2f, 0xc8, 0x4d, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8d, 0xfc, 0xdd, 0x2f, +0x80, 0xc0, 0xc0, 0x46, 0x44, 0x20, 0x00, 0x18, 0x80, 0x27, 0x8c, 0x08, 0x46, 0xf0, 0x00, 0x41, +0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xb4, 0x27, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x28, 0xdd, 0x2f, 0xa9, 0xb2, 0x10, 0x83, 0x00, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x0f, +0x58, 0xf7, 0x8e, 0x24, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x77, 0x81, 0x47, 0xa6, 0x3e, +0x54, 0x10, 0x00, 0x02, 0xc9, 0x27, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xa3, 0x42, 0x10, +0xd8, 0x0b, 0xc9, 0x20, 0x84, 0xa1, 0xd0, 0x04, 0x44, 0x60, 0x00, 0x1f, 0xd5, 0x1c, 0x84, 0x03, +0xae, 0x3e, 0x80, 0x28, 0x50, 0x03, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x14, 0x58, 0xf7, 0x80, 0x8c, +0xdd, 0x2f, 0x80, 0xc0, 0xc0, 0x10, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8e, 0x54, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, 0x82, 0xa8, 0xdd, 0x2f, 0xd5, 0x04, 0x84, 0xcc, +0xd5, 0x02, 0x84, 0xc0, 0x80, 0x06, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x97, 0xc9, 0x9c, 0x03, 0x80, 0x3f, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x82, 0x5c, 0xdd, 0x2f, 0xa6, 0xb2, 0x80, 0x06, 0x9c, 0x53, 0x84, 0x60, 0x44, 0x20, +0xff, 0xfe, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x8a, 0xf0, 0xdd, 0x2f, 0x44, 0x50, 0x08, 0x07, +0x81, 0x1f, 0xdf, 0x26, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x0f, 0x02, 0x17, 0x81, 0x7a, 0xc0, 0x1b, 0xb4, 0x00, 0x84, 0xa4, 0xd8, 0x18, +0x54, 0x00, 0x80, 0x30, 0xc0, 0x15, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x83, 0xc7, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x83, 0xe4, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x37, 0x89, 0xe6, 0x84, 0x00, +0x80, 0x20, 0xdd, 0x22, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xe5, 0x80, 0x06, +0x80, 0x27, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x8a, 0xe0, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x9c, 0x83, 0x81, 0x20, +0xa6, 0x11, 0xa6, 0x90, 0x40, 0x00, 0x20, 0x08, 0x98, 0x02, 0x96, 0x01, 0x50, 0x20, 0x7e, 0x00, +0x96, 0x91, 0x40, 0x80, 0x80, 0x13, 0x5c, 0xf1, 0x00, 0x20, 0xe8, 0x08, 0x46, 0xf0, 0x00, 0x38, +0x58, 0xf7, 0x81, 0x98, 0xdd, 0x2f, 0x84, 0xc0, 0xd5, 0x07, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, +0x84, 0x18, 0xdd, 0x2f, 0x80, 0xc0, 0x44, 0x50, 0x04, 0x01, 0x4c, 0x82, 0xc0, 0x14, 0x00, 0x04, +0x80, 0x07, 0xc0, 0x07, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x17, 0x84, 0x7e, 0xe2, 0x20, 0xe8, 0x03, +0x84, 0x20, 0xd5, 0x02, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x88, 0x3b, 0x48, 0x00, +0x00, 0xc5, 0x8c, 0xba, 0x4c, 0x82, 0x80, 0x4b, 0x5c, 0xf4, 0x04, 0x1c, 0xe8, 0x08, 0x8e, 0xaa, +0x4c, 0x82, 0x80, 0x0e, 0x9d, 0x6a, 0x4c, 0x82, 0xc0, 0xb9, 0xd5, 0x13, 0x9d, 0x69, 0x4c, 0x82, +0x80, 0x63, 0x8c, 0xac, 0x4c, 0x82, 0xc0, 0xb2, 0x48, 0x00, 0x00, 0x95, 0x4e, 0x62, 0x00, 0xc4, +0x80, 0x06, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x85, 0xd4, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0xbe, +0xce, 0x03, 0x48, 0x00, 0x00, 0xb9, 0x00, 0x14, 0x80, 0x05, 0xe6, 0x22, 0x4e, 0xf2, 0x00, 0xbc, +0x00, 0x53, 0x01, 0xd1, 0xd9, 0x12, 0x80, 0x28, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, +0x81, 0x1c, 0xdd, 0x2f, 0x80, 0x06, 0x84, 0x28, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x1a, 0x58, 0xf7, +0x80, 0xe4, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0xa2, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x1a, 0x58, 0xf7, +0x8d, 0x38, 0xdd, 0x2f, 0x80, 0xe0, 0x4e, 0x03, 0x00, 0x9a, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x0d, +0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0x92, 0x4e, 0x62, 0x00, 0x8d, 0x00, 0x03, +0x01, 0xc3, 0x84, 0xa3, 0xd0, 0x0a, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x82, 0x90, +0xdd, 0x2f, 0x80, 0xe0, 0x4e, 0x03, 0x00, 0x83, 0x84, 0x00, 0x44, 0x10, 0x04, 0x1b, 0x46, 0xf0, +0x00, 0x0d, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x00, 0x03, 0x01, 0xc3, 0x84, 0xa3, 0xd8, 0x75, +0x80, 0x06, 0x50, 0x13, 0x01, 0x1c, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8f, 0x6c, +0xdd, 0x2f, 0xd5, 0x6b, 0xc6, 0x68, 0x00, 0x03, 0x01, 0xf8, 0x84, 0xa3, 0xd8, 0x05, 0x00, 0x04, +0x80, 0x05, 0x84, 0xa1, 0xd0, 0x0b, 0x00, 0x14, 0x80, 0x05, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x10, +0x58, 0xf7, 0x81, 0x50, 0xdd, 0x2f, 0x80, 0xe0, 0xc8, 0x59, 0x84, 0x00, 0x44, 0x10, 0x04, 0x1c, +0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x00, 0x03, 0x01, 0xf8, 0x84, 0xa3, +0xd8, 0x4c, 0x00, 0x04, 0x80, 0x05, 0x84, 0xa1, 0xd8, 0x48, 0x00, 0x03, 0x01, 0xae, 0xe6, 0x09, +0xe8, 0x44, 0x84, 0x2a, 0x42, 0x10, 0x04, 0x24, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x0a, 0xb8, +0x98, 0x4a, 0x80, 0x06, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8f, 0x94, 0xdd, 0x2f, +0xd5, 0x34, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x27, 0x81, 0x95, 0x9e, 0x93, 0x84, 0x60, 0xf0, 0x01, 0x46, 0xf0, +0x01, 0x12, 0x10, 0x37, 0x8a, 0xaf, 0x46, 0xf0, 0x01, 0x12, 0x10, 0x27, 0x8a, 0xac, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x80, 0x09, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x0a, +0x58, 0xf7, 0x85, 0xf0, 0xdd, 0x2f, 0x80, 0xe0, 0x44, 0x50, 0x04, 0x05, 0x4c, 0x82, 0x80, 0x05, +0x8c, 0xb4, 0x4c, 0x82, 0xc0, 0x0c, 0xcf, 0x0a, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, +0x89, 0xed, 0xd5, 0x04, 0x84, 0xe2, 0xd5, 0x02, 0x84, 0xe0, 0x80, 0x07, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x44, 0x70, 0x00, 0x12, 0xd5, 0xf9, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc0, +0x80, 0xe1, 0x84, 0x08, 0x50, 0x13, 0x01, 0x1c, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x98, 0xdd, 0x2f, 0x00, 0x83, 0x01, 0xc1, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x2a, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x07, 0x83, 0xa3, 0x42, 0x00, 0x5c, 0x0b, 0xc8, 0x6c, 0x44, 0x00, 0x00, 0x3d, +0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0xb4, 0xdd, 0x2f, 0xc0, 0x12, 0x20, 0x03, 0x01, 0x23, +0x4e, 0x04, 0x00, 0x0f, 0x00, 0x03, 0x01, 0xf8, 0x54, 0x00, 0x00, 0x02, 0xc8, 0x09, 0x80, 0x06, +0x80, 0x28, 0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, 0x81, 0x50, 0xdd, 0x2f, 0xd5, 0x53, 0x80, 0x06, +0x84, 0x20, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x81, 0x70, 0xdd, 0x2f, 0xd5, 0x4b, 0xb4, 0x06, +0x84, 0xa1, 0xd0, 0x05, 0x84, 0xa4, 0xd0, 0x03, 0x84, 0xa8, 0xd8, 0x0e, 0x00, 0x13, 0x01, 0xc3, +0x84, 0xa3, 0xd9, 0x0a, 0x80, 0x27, 0x80, 0x06, 0x84, 0x40, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, +0x8f, 0x6c, 0xdd, 0x2f, 0xd5, 0x31, 0x04, 0x13, 0x00, 0x6c, 0xc9, 0x16, 0x84, 0x41, 0x4c, 0x01, +0x00, 0x14, 0x20, 0x03, 0x01, 0x23, 0x4e, 0x04, 0x00, 0x07, 0x10, 0x13, 0x01, 0xc7, 0x80, 0x06, +0x80, 0x22, 0xd5, 0x16, 0x44, 0x00, 0x00, 0x33, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, +0x81, 0xdc, 0xdd, 0x2f, 0xd5, 0x19, 0x00, 0x03, 0x01, 0xc3, 0x84, 0xa3, 0xd0, 0x15, 0x20, 0x03, +0x01, 0x23, 0x4e, 0x04, 0x00, 0x0c, 0x10, 0x13, 0x01, 0xc7, 0x80, 0x06, 0x84, 0x21, 0x46, 0xf0, +0x00, 0x10, 0x58, 0xf7, 0x80, 0xe4, 0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x11, +0x58, 0xf7, 0x8f, 0xd4, 0xdd, 0x2f, 0x00, 0x03, 0x01, 0xc3, 0x58, 0x00, 0x00, 0x01, 0x10, 0x03, +0x01, 0xc3, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x80, 0xc0, 0x02, 0x00, 0x00, 0xc3, 0x80, 0xe1, 0x84, 0x27, 0x4c, 0x00, 0x80, 0x51, 0x00, 0x03, +0x01, 0xd1, 0x4c, 0x03, 0xc0, 0x05, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x4c, 0x00, 0x03, 0x01, 0xce, +0xc0, 0x46, 0x04, 0x03, 0x00, 0x6c, 0xc8, 0x10, 0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x80, 0x40, +0xdd, 0x2f, 0xc8, 0x0a, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x88, 0xd8, 0xdd, 0x2f, +0x84, 0x21, 0x4c, 0x00, 0x80, 0x35, 0x00, 0x23, 0x01, 0xf7, 0xca, 0x11, 0x44, 0x00, 0xbb, 0x80, +0x46, 0x10, 0x00, 0x17, 0x58, 0x10, 0x87, 0xf4, 0x80, 0x66, 0x80, 0x82, 0x84, 0xa1, 0x46, 0xf0, +0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x10, 0x03, 0x01, 0xf7, 0x00, 0x03, 0x01, 0xcc, +0x50, 0x10, 0x7f, 0xe0, 0x96, 0x48, 0xe6, 0x22, 0xe9, 0x1c, 0x44, 0x10, 0x00, 0x24, 0x4c, 0x00, +0x80, 0x19, 0x9e, 0x49, 0x4c, 0x00, 0x80, 0x16, 0x9c, 0x4a, 0x4c, 0x00, 0x80, 0x13, 0x9c, 0x49, +0x4c, 0x00, 0x80, 0x10, 0x00, 0x03, 0x01, 0xb0, 0x80, 0x27, 0x10, 0x03, 0x01, 0xc8, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x17, 0x58, 0xf7, 0x8a, 0x84, 0xdd, 0x2f, 0xd5, 0x03, 0x84, 0x0c, 0xd5, 0x02, +0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x07, 0x82, 0x38, 0x84, 0xa8, 0xd8, 0x20, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, +0x89, 0xea, 0xc8, 0x1b, 0x46, 0x60, 0x00, 0x37, 0x58, 0x63, 0x08, 0xc8, 0x84, 0x01, 0x4b, 0xe0, +0x18, 0x01, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x2c, 0x4b, 0xe0, 0x18, 0x01, 0xc8, 0x0e, 0x84, 0x61, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x37, 0x89, 0xea, 0x44, 0x00, 0x00, 0x13, 0x84, 0x20, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x80, 0x68, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0xef, 0x80, 0x97, 0x80, 0x50, 0x03, 0x7f, 0xf8, 0x96, 0x00, 0xe6, 0x02, 0xe8, 0x57, +0x46, 0xf0, 0x01, 0x38, 0x14, 0x67, 0x82, 0x38, 0x84, 0x09, 0x4c, 0x60, 0x40, 0x19, 0x84, 0x62, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x37, 0x89, 0xea, 0x8c, 0x0a, 0x84, 0x21, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x80, 0x68, 0xdd, 0x2f, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x17, 0x83, 0xe0, +0x84, 0x21, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x17, 0x83, 0xdf, 0xd5, 0x1d, 0x46, 0x00, 0x01, 0x38, +0x58, 0x00, 0x09, 0xeb, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x84, 0x40, +0x46, 0x10, 0x00, 0xc3, 0x58, 0x10, 0x85, 0xf4, 0x44, 0x00, 0x00, 0xc8, 0x80, 0x62, 0x80, 0x82, +0x80, 0xa2, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x07, 0x89, 0xeb, 0x84, 0x00, 0x84, 0x42, 0x84, 0x63, 0x10, 0x0f, 0x80, 0x04, 0x10, 0x0f, +0x80, 0x03, 0x10, 0x2f, 0x80, 0x02, 0x10, 0x2f, 0x80, 0x00, 0x10, 0x3f, 0x80, 0x01, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x80, 0x66, 0x10, 0x6f, 0x80, 0x05, 0x80, 0x1f, 0x84, 0x26, 0xdd, 0x22, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x80, 0x68, 0xdd, 0x20, 0xd5, 0x07, 0x80, 0x06, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8b, 0x1c, 0xdd, 0x2f, 0xec, 0x80, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x84, 0x08, 0x4c, 0x60, 0x40, 0x07, 0x46, 0xf0, +0x00, 0xc2, 0x58, 0xf7, 0x8a, 0x6c, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, +0x80, 0x9c, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x81, 0xf9, 0x80, 0xc0, 0x4e, 0x12, 0x01, 0x3e, 0x46, 0xf0, +0x01, 0x01, 0x00, 0x07, 0x88, 0x37, 0xc8, 0x0b, 0x84, 0x04, 0x4c, 0x10, 0x40, 0x09, 0x46, 0xf0, +0x00, 0x35, 0x58, 0xf7, 0x8f, 0x5c, 0xdd, 0x2f, 0x4e, 0x02, 0x01, 0x2f, 0x46, 0xf0, 0x01, 0x09, +0x00, 0x07, 0x87, 0xae, 0x4e, 0x02, 0x01, 0x29, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xac, +0xdd, 0x20, 0x4e, 0x02, 0x01, 0x22, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8f, 0x4e, 0x03, +0x01, 0x1c, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, 0x4e, 0x03, 0x01, 0x15, +0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x80, 0xe0, 0x4e, 0x03, 0x01, 0x0d, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x89, 0x78, 0xdd, 0x2f, 0x4e, 0x02, +0x01, 0x04, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0x8a, 0xdd, 0x20, 0x4e, 0x02, 0x00, 0xfd, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0x9e, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x94, +0xdd, 0x21, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0x81, 0x20, 0x80, 0x07, +0xb7, 0x3f, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x80, 0xe0, 0xb4, 0x3f, +0xf0, 0x01, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x86, 0xa0, 0xdd, 0x2f, 0xb6, 0x1f, +0xc6, 0x04, 0xe2, 0xc0, 0xe8, 0x02, 0xb6, 0xdf, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0x0b, +0x80, 0x07, 0xdd, 0x21, 0xc0, 0x05, 0xb4, 0x3f, 0xe2, 0x01, 0xe8, 0x02, 0xb6, 0x1f, 0x46, 0xf0, +0x00, 0x3b, 0x58, 0xf7, 0x80, 0x58, 0xdd, 0x2f, 0xb4, 0x3f, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x86, 0xa0, 0xdd, 0x2f, 0xb6, 0x1f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x83, 0xab, +0x80, 0x3f, 0x84, 0x01, 0x80, 0x47, 0xdd, 0x23, 0xb4, 0x1f, 0x9e, 0x01, 0x5c, 0xf0, 0x7f, 0xfe, +0x4e, 0xf2, 0x00, 0xb3, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, 0x87, 0x14, 0x00, 0x00, 0x81, 0x23, +0xc8, 0x08, 0x04, 0x00, 0x80, 0x34, 0x84, 0x22, 0x4c, 0x00, 0x80, 0x0c, 0x84, 0x23, 0xd5, 0x07, +0x04, 0x00, 0x80, 0x34, 0x84, 0x25, 0x4c, 0x00, 0x80, 0x05, 0x84, 0x26, 0x4c, 0x00, 0xc0, 0x1c, +0x46, 0x80, 0x01, 0x03, 0x04, 0x04, 0x03, 0xf0, 0xdd, 0x20, 0x9a, 0x38, 0x94, 0x04, 0x92, 0x04, +0x46, 0xf0, 0x01, 0x01, 0x02, 0xa7, 0x83, 0xf4, 0x92, 0x01, 0xe2, 0x0a, 0xe8, 0x0c, 0x04, 0x04, +0x03, 0xf0, 0xdd, 0x20, 0x9b, 0xf8, 0x95, 0xfc, 0x92, 0xe4, 0x40, 0x63, 0x84, 0x09, 0x40, 0x65, +0x18, 0x01, 0xd5, 0x02, 0x84, 0xc0, 0xb5, 0x1f, 0x46, 0x70, 0x00, 0x35, 0x58, 0x73, 0x8f, 0x3c, +0x4b, 0xe0, 0x1c, 0x01, 0xe2, 0x08, 0xe8, 0x78, 0xce, 0x39, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x8f, 0x64, 0xdd, 0x2f, 0xc0, 0x0d, 0x46, 0x70, 0x01, 0x13, 0x58, 0x73, 0x84, 0x74, 0xa6, 0x38, +0xc8, 0x04, 0x80, 0x46, 0x84, 0x06, 0xd5, 0x4b, 0x80, 0x07, 0x84, 0x26, 0xd5, 0x60, 0xb4, 0x9f, +0x84, 0x06, 0x80, 0x66, 0x84, 0x21, 0x44, 0x20, 0x70, 0x7d, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x85, 0x60, 0xdd, 0x2f, 0xb4, 0x1f, 0x4c, 0x04, 0xc0, 0x13, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x17, +0x8f, 0x94, 0x8e, 0x29, 0x96, 0x48, 0x5c, 0xf0, 0x80, 0x20, 0xe8, 0x09, 0x46, 0xf0, 0x01, 0x0a, +0x04, 0x17, 0x82, 0xd7, 0xc1, 0x04, 0x00, 0x10, 0x80, 0x20, 0xd5, 0x02, 0x84, 0x20, 0x46, 0xf0, +0x00, 0x28, 0x58, 0xf7, 0x8b, 0xa0, 0xdd, 0x2f, 0xd5, 0x3f, 0xb5, 0x1f, 0x4b, 0xe0, 0x1c, 0x01, +0x98, 0x06, 0xe2, 0x08, 0xe8, 0x39, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x88, 0x37, 0xc8, 0x34, +0x46, 0x70, 0x01, 0x13, 0x58, 0x73, 0x84, 0x74, 0x00, 0x83, 0x80, 0x00, 0x46, 0x50, 0x00, 0x35, +0x58, 0x52, 0x85, 0x60, 0x4e, 0x83, 0x00, 0x1a, 0x44, 0x20, 0x70, 0x7e, 0x84, 0x06, 0x84, 0x21, +0x80, 0x68, 0x80, 0x86, 0x4b, 0xe0, 0x14, 0x01, 0x80, 0x06, 0x80, 0x48, 0x46, 0x10, 0x00, 0x1c, +0x58, 0x10, 0x86, 0xbc, 0x80, 0x62, 0x80, 0x82, 0x84, 0xa1, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x87, 0xb0, 0xdd, 0x2f, 0xae, 0x38, 0xd5, 0x10, 0x84, 0x21, 0x84, 0x06, 0x80, 0x61, 0x44, 0x20, +0x70, 0x7e, 0x80, 0x86, 0x4b, 0xe0, 0x14, 0x01, 0x80, 0x07, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x80, 0xc0, 0x84, 0x0f, 0x4c, 0x60, 0x00, 0xc3, 0xe6, 0xd0, 0xe8, 0x08, 0x84, 0xa6, +0xd6, 0x45, 0x84, 0xa9, 0xd6, 0x5f, 0xc6, 0x0c, 0x48, 0x00, 0x00, 0xd4, 0x9d, 0x46, 0xd6, 0x7a, +0x9d, 0x6b, 0xd6, 0x67, 0x9d, 0x43, 0x4c, 0x62, 0xc0, 0xcd, 0x48, 0x00, 0x00, 0x88, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x37, 0x81, 0x5f, 0x84, 0x21, +0x84, 0x03, 0x44, 0x20, 0x10, 0x0b, 0xdd, 0x24, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x81, 0x8b, +0x44, 0x20, 0x00, 0x16, 0x04, 0x10, 0x00, 0x0a, 0xa1, 0x4f, 0xda, 0x14, 0x00, 0x20, 0x80, 0x32, +0x84, 0x05, 0x42, 0x11, 0x00, 0x73, 0x10, 0x60, 0x80, 0x35, 0x46, 0xf0, 0x01, 0x0a, 0x00, 0x17, +0x8b, 0x7d, 0xc1, 0x08, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8e, 0xe4, 0xdd, 0x2f, 0x48, 0x00, +0x00, 0xa1, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x17, 0x81, 0x5f, 0x46, 0xf0, 0x00, 0x2d, +0x58, 0xf7, 0x86, 0x04, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0x95, 0x46, 0x00, 0x04, 0x80, 0x04, 0x30, +0x00, 0x0a, 0x46, 0x60, 0x01, 0x13, 0x04, 0x43, 0x01, 0x5f, 0x54, 0x31, 0x80, 0x03, 0x84, 0x03, +0x84, 0x21, 0x44, 0x20, 0x10, 0x0d, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, +0x84, 0x02, 0x14, 0x03, 0x01, 0x5f, 0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, 0x8a, 0x2c, 0xdd, 0x2f, +0xd5, 0x78, 0x46, 0x00, 0x04, 0x80, 0x04, 0x30, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x47, +0x81, 0x5f, 0x54, 0x31, 0x80, 0x03, 0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x0e, 0xd5, 0x20, +0x46, 0x60, 0x01, 0x13, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x04, 0x33, 0x01, 0x5f, +0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x12, 0xdd, 0x24, 0x84, 0x00, 0x14, 0x03, 0x01, 0x5f, +0xd5, 0x58, 0x46, 0x00, 0x04, 0x80, 0x04, 0x30, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x47, +0x81, 0x5f, 0x54, 0x31, 0x80, 0x03, 0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x10, 0x46, 0xf0, +0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0xd5, 0x44, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, +0x83, 0xd5, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x37, 0x81, 0x5f, 0x84, 0x21, 0x84, 0x03, 0x44, 0x20, +0x10, 0x0f, 0xdd, 0x24, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x81, 0x8b, 0x44, 0x20, 0x00, 0x16, +0x04, 0x00, 0x00, 0x0a, 0xa1, 0x47, 0xda, 0x0a, 0x00, 0x20, 0x00, 0x32, 0x84, 0x25, 0x42, 0x01, +0x04, 0x73, 0x84, 0x20, 0x50, 0x00, 0x00, 0x30, 0xae, 0x45, 0x46, 0x00, 0x01, 0x13, 0x04, 0x10, +0x01, 0x5f, 0xc1, 0x1f, 0x84, 0x22, 0x14, 0x10, 0x01, 0x5f, 0xd5, 0x1b, 0x46, 0x00, 0x04, 0x80, +0x04, 0x30, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x47, 0x81, 0x5f, 0x54, 0x31, 0x80, 0x03, +0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x11, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, +0xdd, 0x2f, 0x44, 0x00, 0x00, 0x80, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, 0x8c, 0xec, 0xdd, 0x2f, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x70, 0x01, 0x0f, +0x58, 0x73, 0x84, 0xf4, 0xa0, 0x3e, 0x44, 0x10, 0x40, 0x00, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, +0x80, 0x64, 0xdd, 0x2f, 0x80, 0xc0, 0x04, 0x03, 0x80, 0x0a, 0xc8, 0x07, 0x46, 0xf0, 0x00, 0x3e, +0x58, 0xf7, 0x86, 0xc8, 0xdd, 0x2f, 0xd5, 0x05, 0xc6, 0x04, 0x84, 0x02, 0x14, 0x03, 0x80, 0x0a, +0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x84, 0xf4, 0x04, 0x13, 0x80, 0x0a, 0x84, 0xa3, 0xd1, 0x36, +0xe6, 0x24, 0xe8, 0x06, 0x84, 0xa1, 0xd1, 0x4e, 0x84, 0xa2, 0xd9, 0x40, 0xd5, 0x0f, 0x84, 0xa4, +0xd1, 0x37, 0x84, 0xa5, 0xd9, 0x3b, 0xce, 0x0a, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x7d, +0x80, 0x06, 0xdd, 0x21, 0x84, 0x01, 0x10, 0x03, 0x80, 0x0b, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x3e, +0x58, 0xf7, 0x84, 0x48, 0xdd, 0x2f, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x84, 0xf4, 0xc8, 0x12, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x80, 0x01, 0xdd, 0x20, 0xa7, 0x78, 0x84, 0x23, 0xd1, 0x2a, +0x14, 0x13, 0x80, 0x0a, 0x44, 0x10, 0x01, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x82, 0xd2, +0xd5, 0x21, 0x84, 0x01, 0x14, 0x03, 0x80, 0x0a, 0xd5, 0x1d, 0xa6, 0x38, 0x84, 0xa1, 0xd0, 0x06, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x80, 0x02, 0xdd, 0x20, 0x84, 0x24, 0xd5, 0x0f, 0x46, 0xf0, +0x00, 0x3e, 0x58, 0xf7, 0x85, 0x30, 0xdd, 0x2f, 0xd5, 0x0d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xf7, 0x44, 0x00, 0x00, 0x1f, 0xdd, 0x21, 0x84, 0x26, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, +0x81, 0x47, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x81, 0x47, 0x84, 0xa1, 0xd8, 0x07, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x3e, 0x58, 0xf7, 0x85, 0xd0, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x01, 0x08, 0x58, 0x63, 0x0f, 0x9c, +0x04, 0x13, 0x00, 0x08, 0x80, 0xe0, 0xa0, 0x02, 0x50, 0x10, 0x81, 0xa8, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x82, 0x08, 0xdd, 0x2f, 0xa0, 0x3a, 0x9c, 0x06, 0x04, 0x13, 0x00, 0x08, 0xa7, 0x07, +0xa6, 0xc5, 0xa6, 0x86, 0x84, 0x00, 0xae, 0x30, 0x40, 0x21, 0x20, 0x08, 0x40, 0x02, 0x40, 0x08, +0x98, 0x90, 0x00, 0x00, 0x81, 0xae, 0x98, 0x93, 0x50, 0x10, 0x81, 0xa8, 0x46, 0xf0, 0x00, 0x12, +0x58, 0xf7, 0x85, 0x98, 0xdd, 0x2f, 0x84, 0x00, 0x14, 0x03, 0x00, 0x08, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xc0, 0x80, 0xc0, 0xa6, 0x00, +0x84, 0xa1, 0xd0, 0x17, 0x84, 0xa3, 0x50, 0x7f, 0x80, 0x04, 0xd8, 0x24, 0x50, 0x8f, 0x80, 0x38, +0x80, 0x28, 0x9c, 0x31, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0x5c, 0xdd, 0x2f, 0x80, 0x08, +0x9c, 0x77, 0x80, 0x47, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x87, 0x48, 0xdd, 0x2f, 0xd5, 0x14, +0x50, 0x7f, 0x80, 0x38, 0x9c, 0x31, 0x80, 0x27, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0x5c, +0xdd, 0x2f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x86, 0xb0, 0xdd, 0x2f, 0xf0, 0x85, +0xd5, 0x03, 0x84, 0x01, 0xa8, 0x3c, 0xf1, 0x05, 0x44, 0x00, 0xfc, 0xf3, 0x46, 0xf0, 0x00, 0x0f, +0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0xec, 0x40, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0xa6, 0x01, 0x84, 0xa4, 0xd0, 0x3f, 0xe6, 0x05, 0xe8, 0x08, 0x84, 0xa2, +0xd0, 0x1f, 0xe6, 0x03, 0xe8, 0x2b, 0x84, 0xa1, 0xd8, 0x72, 0xd5, 0x0c, 0x84, 0x26, 0x4c, 0x00, +0x80, 0x4f, 0xe2, 0x01, 0xe9, 0x3f, 0x84, 0xa8, 0xd0, 0x5d, 0x44, 0x50, 0x00, 0xff, 0xd8, 0x67, +0xd5, 0x53, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, +0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x01, 0xb0, 0xd5, 0x65, 0x46, 0x00, +0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, +0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x01, 0x20, 0xd5, 0x57, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, +0x05, 0xc0, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, +0x44, 0x10, 0x00, 0xd8, 0xd5, 0x49, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x44, 0x10, +0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0xb4, +0xd5, 0x3b, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x8c, 0x32, 0x12, 0x10, 0x00, 0x57, +0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0x90, 0xd5, 0x2e, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x05, 0xc0, 0x8c, 0x32, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, +0x44, 0x10, 0x00, 0x6c, 0xd5, 0x21, 0x84, 0x24, 0x46, 0xf0, 0x01, 0x10, 0x14, 0x17, 0x81, 0x9d, +0xd5, 0x1d, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x8c, 0x3e, 0x12, 0x10, 0x00, 0x57, +0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0x48, 0xd5, 0x0e, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x05, 0xc0, 0x44, 0x10, 0x00, 0x24, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, +0x00, 0x2d, 0x44, 0x10, 0x00, 0x60, 0x12, 0x10, 0x00, 0x56, 0x44, 0x00, 0xfc, 0x22, 0x84, 0x20, +0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x50, 0x80, 0x00, 0x05, 0x80, 0xc0, 0x00, 0x04, +0x00, 0x00, 0x46, 0x90, 0x00, 0x0f, 0x58, 0x94, 0x8a, 0xac, 0x8e, 0x10, 0x96, 0x00, 0x5c, 0xf0, +0x00, 0xef, 0xe8, 0x0a, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x86, 0xc8, 0xdd, 0x2f, 0x44, 0x00, +0xfc, 0x79, 0x84, 0x20, 0xd5, 0x43, 0xa6, 0x30, 0x46, 0x70, 0x01, 0x01, 0x58, 0x73, 0x87, 0x14, +0x10, 0x03, 0x80, 0xc9, 0x46, 0x30, 0x01, 0x08, 0x58, 0x31, 0x8e, 0xd4, 0xa6, 0xb2, 0xa6, 0x31, +0x40, 0x21, 0x20, 0x08, 0x98, 0x90, 0x96, 0x91, 0x12, 0x21, 0x80, 0x54, 0x50, 0x01, 0x80, 0xc4, +0x80, 0x22, 0x12, 0x23, 0x80, 0x63, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x13, 0x00, 0x17, 0x84, 0xb6, 0x9d, 0xb4, 0x44, 0x00, 0x00, 0x30, 0x42, 0x00, +0x80, 0x24, 0xa6, 0x70, 0x10, 0x13, 0x81, 0x51, 0x46, 0x10, 0x01, 0x09, 0x58, 0x10, 0x87, 0xcc, +0xa7, 0xb0, 0x98, 0x01, 0x10, 0x60, 0x00, 0x25, 0x00, 0x24, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x07, 0x85, 0xde, 0x95, 0x12, 0x99, 0x20, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x47, 0x85, 0xdd, +0x10, 0x23, 0x80, 0xcd, 0x44, 0x00, 0xfc, 0x79, 0x84, 0x20, 0x4b, 0xe0, 0x24, 0x01, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xa7, 0x40, 0x84, 0x41, +0xda, 0x07, 0x98, 0x02, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x88, 0xf0, 0xdd, 0x2f, 0x44, 0x00, +0xfc, 0xc5, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x06, +0x04, 0x07, 0x83, 0xb3, 0x84, 0xa3, 0xd8, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf7, +0xc8, 0x12, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x67, 0x89, 0xfe, 0xce, 0x0d, 0x84, 0x08, 0x80, 0x26, +0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xec, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x06, 0x14, 0x67, +0x83, 0xb3, 0xd5, 0x0b, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8e, 0x34, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x80, 0x9c, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x46, 0x60, 0x01, 0x03, 0x58, 0x63, 0x0e, 0x38, +0xa6, 0x73, 0x54, 0x80, 0x00, 0xff, 0xc1, 0x4e, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x84, 0x09, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x85, 0xf0, +0xdd, 0x2f, 0x84, 0xe0, 0x46, 0xf0, 0x01, 0x03, 0x04, 0x17, 0x83, 0xee, 0x46, 0xf0, 0x01, 0x00, +0x10, 0x77, 0x83, 0x0e, 0xa6, 0x37, 0x46, 0xf0, 0x00, 0x09, 0x58, 0xf7, 0x84, 0x10, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x17, 0x80, 0xb7, 0x84, 0xa1, 0xaf, 0xf3, 0xd1, 0x14, 0x46, 0x60, +0x04, 0x09, 0x58, 0x63, 0x00, 0x14, 0xb4, 0x26, 0x84, 0x02, 0x40, 0x10, 0x80, 0x04, 0xb6, 0x26, +0x46, 0xf0, 0x00, 0x56, 0x58, 0xf7, 0x85, 0x44, 0xdd, 0x2f, 0xb4, 0x06, 0x42, 0x00, 0x04, 0x09, +0xb6, 0x06, 0xd5, 0x0b, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0x38, 0x84, 0xa8, 0xd8, 0x05, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xec, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x81, 0x68, 0xdd, 0x2f, 0x4e, 0x82, 0x00, 0x07, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8e, 0x34, +0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, +0x46, 0x60, 0x01, 0x03, 0x58, 0x63, 0x0e, 0x38, 0xa6, 0x75, 0x97, 0xc0, 0xc1, 0x4e, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x84, 0x09, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x85, 0xf0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x03, 0x04, 0x17, 0x83, 0xed, +0x00, 0x03, 0x00, 0x09, 0x46, 0xf0, 0x00, 0x09, 0x58, 0xf7, 0x84, 0x10, 0xdd, 0x2f, 0x84, 0x40, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x17, 0x80, 0xb7, 0x46, 0xf0, 0x01, 0x00, 0x10, 0x27, 0x83, 0x0d, +0x84, 0x01, 0xae, 0xb5, 0x4c, 0x10, 0x00, 0x14, 0x46, 0x60, 0x04, 0x09, 0x58, 0x63, 0x00, 0x14, +0xb4, 0x26, 0x40, 0x10, 0x80, 0x04, 0xb6, 0x26, 0x46, 0xf0, 0x00, 0x56, 0x58, 0xf7, 0x85, 0x44, +0xdd, 0x2f, 0xb4, 0x06, 0x42, 0x00, 0x00, 0x09, 0xb6, 0x06, 0xd5, 0x0b, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x07, 0x82, 0x38, 0x84, 0xa8, 0xd8, 0x05, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xec, +0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xc7, 0x06, 0x46, 0xf0, +0x00, 0x36, 0x58, 0xf7, 0x8e, 0x34, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x00, 0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, +0x85, 0x3c, 0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, 0x84, 0x84, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8e, 0x34, 0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x07, 0x89, 0xea, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xf7, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x07, 0x89, 0xfe, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xf4, 0x46, 0x00, 0x01, 0x06, 0x58, 0x00, 0x0e, 0xc0, 0x84, 0x20, 0xae, 0x40, +0xa0, 0x43, 0x84, 0xa3, 0x4c, 0x12, 0xc0, 0x99, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x89, 0xf7, +0xc9, 0x08, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x89, 0xfe, 0xc9, 0x03, 0xa8, 0x43, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0x9c, 0xdd, 0x2f, 0x84, 0xc0, 0x46, 0x90, 0x00, 0x1c, +0x58, 0x94, 0x83, 0xcc, 0x44, 0x80, 0x00, 0x13, 0x46, 0x70, 0x00, 0x13, 0x58, 0x73, 0x82, 0xbc, +0x9d, 0xb1, 0x80, 0x06, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x0d, 0xb4, 0x60, 0x40, 0x21, 0xbc, 0x08, +0x92, 0x5e, 0x44, 0x50, 0x00, 0x10, 0xd3, 0x06, 0xca, 0x05, 0x14, 0x80, 0x00, 0x29, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x08, 0x4c, 0x60, 0x7f, 0xee, 0x85, 0x00, 0x50, 0x6f, 0x80, 0x04, 0x46, 0xa0, +0x00, 0x02, 0x58, 0xa5, 0x01, 0x68, 0x47, 0xc0, 0x00, 0x26, 0x59, 0xce, 0x06, 0x64, 0x50, 0x04, +0x00, 0x09, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x81, 0x80, 0xdd, 0x2f, 0x80, 0xe0, 0xc0, 0x2d, +0x02, 0x00, 0x00, 0x51, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x28, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x57, 0x81, 0x6e, 0xdf, 0x12, +0x02, 0x03, 0x80, 0x51, 0x44, 0x10, 0x00, 0x13, 0x58, 0x00, 0x01, 0x00, 0x10, 0x13, 0x80, 0xbc, +0x12, 0x03, 0x80, 0x51, 0xf0, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x50, 0x03, 0x80, 0xb7, 0xdd, 0x3c, +0xd5, 0x0c, 0xf0, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0xcb, +0x80, 0x07, 0x44, 0x10, 0x00, 0x13, 0xdd, 0x22, 0x8d, 0x01, 0x44, 0x50, 0x00, 0x20, 0x4c, 0x82, +0xff, 0xc8, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf7, 0xc8, 0x0d, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x17, 0x89, 0xfe, 0xc9, 0x08, 0x84, 0x08, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xec, +0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8e, 0x34, 0xdd, 0x2f, 0x84, 0x00, +0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, 0x85, 0x3c, 0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0xc3, +0x58, 0xf7, 0x84, 0x84, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0xef, 0xe8, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8d, 0xbc, 0xdd, 0x2f, 0xc0, 0x06, +0x84, 0x21, 0x4c, 0x00, 0xc1, 0xac, 0x48, 0x00, 0x01, 0x8a, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, +0x83, 0xb3, 0x84, 0x41, 0x4c, 0x01, 0x00, 0x0d, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xfe, +0xc8, 0x07, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf7, 0x4e, 0x02, 0x01, 0x98, 0x84, 0x63, +0x46, 0xf0, 0x01, 0x06, 0x14, 0x37, 0x83, 0xb3, 0x84, 0x20, 0x84, 0x40, 0x50, 0x0f, 0x80, 0x17, +0xae, 0x80, 0x10, 0x1f, 0x80, 0x02, 0x12, 0x1f, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, +0x8c, 0x6c, 0xdd, 0x2f, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x82, 0x24, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xa3, 0x42, 0x00, 0x68, 0x0b, 0xc0, 0x08, 0x46, 0x00, +0x40, 0x00, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x82, 0xc8, 0xdd, 0x2f, 0x84, 0xc0, 0x80, 0xe6, +0x46, 0x90, 0x00, 0x1c, 0x58, 0x94, 0x83, 0xcc, 0x46, 0x80, 0x00, 0x13, 0x58, 0x84, 0x01, 0x98, +0x9d, 0xb1, 0x80, 0x06, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x14, 0xb4, 0x20, 0x40, 0x20, 0xbc, 0x08, +0x92, 0x5e, 0x44, 0x30, 0x00, 0x10, 0x4c, 0x11, 0x80, 0x0d, 0x8c, 0x70, 0x4c, 0x11, 0x80, 0x0a, +0xca, 0x08, 0x02, 0x00, 0x00, 0xc4, 0x44, 0x10, 0x00, 0x13, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0xe1, +0x84, 0x08, 0x4c, 0x60, 0x7f, 0xe7, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xa3, 0x46, 0x20, +0x05, 0x00, 0x40, 0x10, 0x08, 0x02, 0xc1, 0x1f, 0x54, 0x00, 0x00, 0x80, 0xc8, 0x1c, 0x84, 0x04, +0xb6, 0x1f, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x8a, 0x88, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x09, +0x04, 0x17, 0x83, 0xe1, 0xc1, 0x03, 0x80, 0x1f, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x07, +0x8e, 0xa8, 0xc8, 0x02, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, 0x8a, 0x04, 0xdd, 0x2f, +0x84, 0xc1, 0xd5, 0x02, 0x84, 0xc0, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x37, 0x83, 0xf5, 0x84, 0x03, +0x4c, 0x30, 0x40, 0x13, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x8a, 0x24, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x08, 0x00, 0x07, 0x8f, 0xf0, 0xc8, 0x02, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x81, 0x18, 0xdd, 0x2f, 0x84, 0xc1, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf7, 0xc8, 0x0f, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xfe, 0xc8, 0x0a, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, +0x85, 0x6c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x06, 0x14, 0x07, 0x83, 0xb4, 0x46, 0xf0, 0x00, 0x25, +0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, 0xc0, 0x07, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, +0x89, 0x84, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xfe, 0xc0, 0x07, 0x84, 0x02, +0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x89, 0x84, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x07, +0x81, 0x7a, 0x54, 0x00, 0x00, 0x40, 0xc0, 0x07, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x8b, 0x68, +0xdd, 0x2f, 0x84, 0xc1, 0x46, 0x80, 0x01, 0x00, 0x84, 0x00, 0x04, 0x24, 0x03, 0xe4, 0x80, 0x20, +0xdd, 0x22, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x89, 0xf7, 0x56, 0x00, 0x00, 0x0c, 0x85, 0x21, +0x40, 0x64, 0x80, 0x1b, 0xc1, 0x0d, 0x44, 0x00, 0x01, 0x40, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8e, 0xb8, 0xdd, 0x2f, 0x04, 0x24, 0x03, 0xe4, 0x80, 0x09, 0x84, 0x20, 0xdd, 0x22, 0x46, 0xf0, +0x01, 0x0f, 0x02, 0x07, 0x81, 0x7a, 0x54, 0x00, 0x00, 0x0f, 0xc0, 0x0e, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x84, 0x06, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x08, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, +0x89, 0xf7, 0xc8, 0x07, 0xd5, 0x02, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x06, 0x10, 0x17, 0x8e, 0xd5, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xe9, 0x84, 0x00, 0xdd, 0x21, 0x56, 0x00, 0x00, 0x0c, +0x84, 0x21, 0x40, 0x60, 0x80, 0x1b, 0x85, 0x00, 0x46, 0xa0, 0x00, 0x38, 0x58, 0xa5, 0x01, 0x80, +0x50, 0x04, 0x00, 0x09, 0x8d, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0xc0, 0x0e, 0x02, 0x10, 0x00, 0x51, +0x54, 0x10, 0x80, 0x02, 0xc1, 0x09, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0xd4, 0x44, 0x10, +0x00, 0x13, 0xdd, 0x22, 0x84, 0xe1, 0x40, 0x24, 0x94, 0x08, 0x4c, 0x81, 0x7f, 0xeb, 0x84, 0x61, +0x4c, 0x71, 0xc0, 0x18, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xb1, 0x80, 0xa7, +0x46, 0x10, 0x00, 0xc3, 0x58, 0x10, 0x86, 0x40, 0x80, 0x62, 0x80, 0x82, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x06, 0x10, 0x07, 0x8e, 0xc0, 0xd5, 0x15, +0x84, 0x01, 0x4c, 0x60, 0x40, 0x16, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xb2, +0x80, 0xa6, 0x46, 0x10, 0x00, 0x10, 0x58, 0x10, 0x81, 0xf0, 0x80, 0x62, 0x80, 0x82, 0x46, 0xf0, +0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x44, 0x00, 0x00, 0x1f, 0xd5, 0x48, 0x84, 0x00, +0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, 0x85, 0x3c, 0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0xc3, +0x58, 0xf7, 0x84, 0x84, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf7, 0xc8, 0x0b, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xfe, 0xc8, 0x06, 0x46, 0xf0, 0x01, 0x06, 0x14, 0x07, +0x83, 0xb3, 0xd5, 0x2d, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8e, 0x34, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x80, 0x9c, 0xdd, 0x2f, 0xd5, 0x21, 0x46, 0x60, 0x01, 0x06, 0x58, 0x63, +0x0e, 0xc0, 0xa1, 0xf3, 0xcf, 0x1b, 0xa0, 0x74, 0xa8, 0x33, 0xc1, 0x08, 0x80, 0x01, 0x46, 0xf0, +0x00, 0x25, 0x58, 0xf7, 0x89, 0x84, 0xdd, 0x2f, 0xa9, 0xf4, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x07, +0x8e, 0xd5, 0xc0, 0x0c, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xe9, 0x84, 0x01, 0xdd, 0x21, +0x84, 0x00, 0x46, 0xf0, 0x01, 0x06, 0x10, 0x07, 0x8e, 0xd5, 0x84, 0x00, 0xec, 0x18, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xa6, 0x40, 0xc9, 0x07, +0x46, 0xf0, 0x01, 0x06, 0x00, 0x17, 0x8e, 0xcc, 0x84, 0x07, 0xd5, 0x1d, 0x84, 0xa1, 0xd9, 0x18, +0xa6, 0x01, 0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, 0x87, 0x90, 0xdd, 0x2f, 0xc8, 0x19, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xf7, 0xc8, 0x14, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xfe, +0xc8, 0x0f, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x17, 0x8e, 0xcc, 0x84, 0x08, 0xd5, 0x04, 0x84, 0x08, +0x44, 0x10, 0x00, 0xff, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xec, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x17, 0x89, 0xfe, 0xc9, 0x0b, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x89, 0xf7, 0xc9, 0x06, +0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x87, 0x64, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x30, 0x0c, 0x03, 0x96, 0x49, 0x46, 0x20, +0x00, 0x0c, 0x58, 0x21, 0x05, 0x00, 0x4c, 0x11, 0xc0, 0x12, 0x44, 0x40, 0x00, 0xaa, 0x46, 0xf0, +0x01, 0x38, 0x14, 0x47, 0x82, 0x74, 0x84, 0x80, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xf7, +0x84, 0x9f, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xfa, 0x4b, 0xe0, 0x08, 0x01, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x80, 0x96, 0x08, +0xc2, 0x13, 0x46, 0xf0, 0x01, 0x0a, 0x00, 0x17, 0x8b, 0x3c, 0xc9, 0x0e, 0x46, 0x20, 0x01, 0x13, +0x00, 0x11, 0x04, 0x89, 0x9c, 0x49, 0x10, 0x11, 0x04, 0x89, 0x46, 0xf0, 0x00, 0x29, 0x58, 0xf7, +0x83, 0x60, 0xdd, 0x2f, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x20, 0x04, 0x80, 0x04, 0x41, 0x00, 0x0b, +0x97, 0x80, 0x42, 0x22, 0x38, 0x0b, 0x80, 0xe1, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, 0x81, 0xdd, +0xca, 0x1a, 0x44, 0x00, 0x00, 0x30, 0x42, 0x33, 0x00, 0x73, 0x84, 0x25, 0x04, 0x01, 0x80, 0x0a, +0x00, 0x50, 0x00, 0x32, 0x42, 0x02, 0x84, 0x73, 0x00, 0x00, 0x00, 0x37, 0xc0, 0x0c, 0x4e, 0x44, +0x00, 0x0b, 0x80, 0x03, 0x84, 0x24, 0x80, 0x62, 0x80, 0x82, 0x46, 0xf0, 0x00, 0x29, 0x58, 0xf7, +0x89, 0xec, 0xdd, 0x2f, 0x80, 0x06, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x1e, 0x58, 0xf7, 0x81, 0x78, +0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, +0x50, 0x6f, 0x80, 0x04, 0x84, 0x4a, 0x81, 0x20, 0x81, 0x01, 0x80, 0x06, 0x46, 0x10, 0x01, 0x0a, +0x58, 0x10, 0x8b, 0x24, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x80, 0x66, +0x84, 0x40, 0x38, 0x01, 0x88, 0x00, 0x38, 0x14, 0x08, 0x00, 0x40, 0x00, 0x80, 0x02, 0x38, 0x01, +0x88, 0x08, 0x9c, 0x91, 0x84, 0xaa, 0xda, 0xf6, 0x80, 0x03, 0x80, 0xc3, 0x46, 0xf0, 0x00, 0x2e, +0x58, 0xf7, 0x85, 0x78, 0xdd, 0x2f, 0x85, 0x41, 0x47, 0xc0, 0x00, 0x29, 0x59, 0xce, 0x01, 0x00, +0x80, 0xe0, 0xd5, 0x39, 0x84, 0x60, 0x40, 0x45, 0x10, 0x08, 0x80, 0x43, 0x40, 0x11, 0x0c, 0x0a, +0x54, 0x01, 0x00, 0x07, 0x40, 0x05, 0x00, 0x0c, 0x38, 0x53, 0x04, 0x00, 0x96, 0x00, 0x40, 0x50, +0x14, 0x02, 0xcd, 0x11, 0x38, 0x54, 0x04, 0x00, 0x47, 0xe0, 0x01, 0x0a, 0x59, 0xef, 0x01, 0x20, +0x40, 0x00, 0x14, 0x02, 0x40, 0x11, 0x78, 0x00, 0xc0, 0x06, 0xa7, 0x48, 0xe2, 0xa4, 0xe8, 0x03, +0x96, 0xd0, 0xd5, 0x02, 0x80, 0xa4, 0x9c, 0x91, 0x44, 0x00, 0x00, 0x4f, 0x4c, 0x20, 0x00, 0x04, +0x80, 0x85, 0xd5, 0xdd, 0x40, 0x11, 0x8c, 0x09, 0x38, 0x03, 0x04, 0x00, 0x54, 0x21, 0x80, 0x07, +0x40, 0x25, 0x08, 0x0c, 0x40, 0x21, 0x00, 0x04, 0x38, 0x23, 0x04, 0x08, 0x80, 0x03, 0x9d, 0xf9, +0xdd, 0x3c, 0x97, 0xf8, 0xe6, 0xf4, 0xe9, 0xc7, 0x84, 0x20, 0x80, 0x41, 0x80, 0xc1, 0x50, 0x5f, +0x80, 0x04, 0x38, 0x42, 0x88, 0x00, 0x38, 0x34, 0x88, 0x00, 0x9c, 0x09, 0x9c, 0x91, 0x4c, 0x41, +0x80, 0x04, 0x96, 0x40, 0x84, 0xc1, 0x87, 0xca, 0x4c, 0x2f, 0x7f, 0xf5, 0xe6, 0x22, 0xe9, 0x33, +0x46, 0x00, 0x01, 0x38, 0x00, 0x10, 0x09, 0xe9, 0xc9, 0x33, 0x84, 0x41, 0x10, 0x20, 0x09, 0xe9, +0x46, 0x50, 0x01, 0x0a, 0x58, 0x52, 0x80, 0xbc, 0x98, 0xcd, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, +0x00, 0x6c, 0x47, 0xe0, 0x01, 0x0a, 0x59, 0xef, 0x00, 0x0c, 0x46, 0x50, 0x01, 0x0a, 0x58, 0x52, +0x81, 0x20, 0x99, 0x08, 0x40, 0x20, 0xf8, 0x00, 0x98, 0x0d, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x81, +0x80, 0x00, 0xa7, 0xd0, 0xa7, 0x40, 0x93, 0x41, 0x93, 0x01, 0x92, 0xe1, 0x92, 0xa1, 0x9c, 0x49, +0x87, 0xca, 0x10, 0xa2, 0x00, 0x00, 0x10, 0x81, 0x80, 0x00, 0xaf, 0xd0, 0xaf, 0x40, 0x4c, 0x1f, +0x7f, 0xd9, 0xd5, 0x06, 0xc9, 0x05, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xe9, 0xc6, 0x0a, +0x80, 0x09, 0x50, 0x1f, 0x80, 0x04, 0x84, 0x4a, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, +0xdd, 0x2f, 0x80, 0x06, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xf4, 0x84, 0xe0, 0xf7, 0x81, 0x80, 0xdf, 0x46, 0x80, 0x00, 0x29, 0x58, 0x84, +0x07, 0x6c, 0xd5, 0x6b, 0x4b, 0xe0, 0x20, 0x01, 0x9d, 0xf9, 0xc8, 0x03, 0x97, 0xf8, 0xd5, 0x65, +0x84, 0xe0, 0x85, 0x5f, 0x81, 0x07, 0x47, 0xc0, 0x01, 0x0a, 0x59, 0xce, 0x0b, 0x24, 0x50, 0x6f, +0x80, 0x04, 0x54, 0x93, 0x80, 0xff, 0x40, 0x04, 0x8c, 0x09, 0x38, 0x1e, 0x00, 0x00, 0x54, 0x03, +0x80, 0x07, 0x40, 0x00, 0x80, 0x0e, 0x96, 0x04, 0xc0, 0x4a, 0x84, 0x40, 0x80, 0x07, 0x80, 0x26, +0xf2, 0x81, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x8a, 0x50, 0xdd, 0x2f, 0x80, 0x07, 0x80, 0x26, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x8a, 0xd0, 0xdd, 0x2f, 0xf0, 0x01, 0x96, 0x44, 0xc1, 0x09, +0x80, 0x07, 0x58, 0x84, 0x00, 0x02, 0x46, 0x10, 0x00, 0xbf, 0x58, 0x10, 0x87, 0x2c, 0xd5, 0x2e, +0x54, 0x00, 0x00, 0x04, 0xc0, 0x2c, 0x4e, 0x92, 0x00, 0x19, 0x40, 0x05, 0x0c, 0x0a, 0x38, 0x1e, +0x00, 0x00, 0x54, 0x05, 0x00, 0x07, 0x40, 0x00, 0x80, 0x0e, 0x96, 0x04, 0xc8, 0x0a, 0x54, 0x05, +0x00, 0xff, 0x58, 0x84, 0x00, 0x02, 0x46, 0xf0, 0x00, 0x29, 0x58, 0xf7, 0x81, 0x00, 0xdd, 0x2f, +0x44, 0x50, 0x00, 0x4e, 0x4c, 0x92, 0x80, 0x14, 0x9c, 0x39, 0x40, 0x10, 0x0c, 0x0a, 0x38, 0x2e, +0x04, 0x00, 0x54, 0x10, 0x00, 0x07, 0x40, 0x11, 0x04, 0x0e, 0x96, 0x4c, 0xc9, 0x08, 0x58, 0x84, +0x00, 0x02, 0x46, 0x10, 0x00, 0x29, 0x58, 0x10, 0x81, 0x00, 0xdd, 0x21, 0x9d, 0xf9, 0x44, 0x50, +0x00, 0x4f, 0x8d, 0x41, 0xdf, 0xa7, 0xd5, 0x0b, 0x46, 0xf0, 0x01, 0x01, 0x02, 0x37, 0x83, 0xb7, +0x80, 0x07, 0x84, 0x20, 0x80, 0x5f, 0xe2, 0xe3, 0xe9, 0x8e, 0x81, 0x01, 0x46, 0xf0, 0x00, 0xbf, +0x58, 0xf7, 0x87, 0xa4, 0xdd, 0x2f, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x29, 0x58, 0xf7, 0x87, 0xb8, +0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x05, 0xc0, 0x00, 0x31, 0x00, 0x8c, 0x97, 0xc0, 0x84, 0x01, +0x97, 0x88, 0x4c, 0x30, 0x40, 0x15, 0x04, 0x01, 0x00, 0x1f, 0xe6, 0x0f, 0xe8, 0x10, 0x00, 0x01, +0x00, 0x8d, 0xc8, 0x0d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x80, 0xa5, 0xdd, 0x20, 0xc8, 0x07, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, 0x80, 0xd8, 0x80, 0x20, 0xdd, 0x23, 0x80, 0x07, 0x80, 0x26, +0x46, 0xf0, 0x00, 0x48, 0x58, 0xf7, 0x88, 0xd0, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x67, 0x80, 0x20, 0x81, 0x00, +0x80, 0xe2, 0xc6, 0x0a, 0x84, 0x01, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x67, 0x85, 0xc8, 0x46, 0xf0, +0x01, 0x10, 0x10, 0x07, 0x85, 0xc8, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xe2, 0x84, 0x01, +0xdd, 0x21, 0x80, 0x20, 0x80, 0x47, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x49, 0x58, 0xf7, 0x82, 0xf8, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x07, 0x00, 0x07, 0x80, 0x20, 0xc0, 0x05, 0x46, 0xf0, 0x01, 0x10, +0x10, 0x67, 0x85, 0xc8, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x17, 0x86, 0x4c, 0xc1, 0x0d, 0x84, 0x20, +0x46, 0xf0, 0x01, 0x10, 0x10, 0x17, 0x86, 0x4d, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x80, 0xd8, +0x84, 0x20, 0x84, 0x01, 0xdd, 0x22, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0xef, 0xf8, 0x84, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0xf6, 0x81, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x80, 0x9f, 0x80, 0x06, +0xdd, 0x21, 0xf0, 0x01, 0x46, 0x60, 0x01, 0x10, 0x58, 0x63, 0x05, 0xc0, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0xb2, 0x46, 0x10, +0x08, 0x00, 0x44, 0x00, 0x00, 0x4a, 0xdd, 0x22, 0x00, 0x03, 0x00, 0x08, 0xc0, 0x1a, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x81, 0x07, 0x00, 0x03, 0x00, 0xa2, 0xdd, 0x21, 0x46, 0x00, 0x04, 0x90, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xc9, 0x04, 0x00, 0x00, 0x0e, 0xdd, 0x21, 0x00, 0x13, +0x00, 0xa2, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0x64, 0xdd, 0x2f, 0x14, 0x03, 0x00, 0x1e, +0x46, 0xf0, 0x01, 0x10, 0x00, 0x07, 0x86, 0x50, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xc4, +0x54, 0x00, 0x00, 0xf7, 0xdd, 0x21, 0x46, 0x00, 0x04, 0x90, 0x04, 0x40, 0x00, 0x0e, 0x46, 0xf0, +0x01, 0x10, 0x02, 0x37, 0x83, 0x28, 0x84, 0x07, 0x44, 0x10, 0x08, 0x00, 0x44, 0x20, 0x90, 0x4f, +0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x27, 0x8f, 0x6c, +0x96, 0x00, 0xca, 0x06, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x17, 0x8f, 0x84, 0xc1, 0x08, 0x46, 0xf0, +0x01, 0x08, 0x00, 0x17, 0x8f, 0x8f, 0xc9, 0x03, 0x80, 0x01, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x4a, +0x58, 0xf7, 0x84, 0x2c, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x20, 0x01, 0x10, 0x58, 0x21, 0x05, 0xc0, 0x00, 0x41, 0x00, 0x1e, +0xc4, 0x2f, 0x84, 0xa1, 0xd8, 0x28, 0x46, 0x10, 0x01, 0x13, 0x02, 0x30, 0x82, 0x78, 0x84, 0x0f, +0x54, 0x41, 0x80, 0x20, 0x10, 0x01, 0x00, 0x13, 0x10, 0x01, 0x00, 0x0e, 0x10, 0x01, 0x00, 0x0f, +0x10, 0x01, 0x00, 0x12, 0xc4, 0x0c, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x8f, 0x8c, 0xc8, 0x07, +0x44, 0x0f, 0xff, 0x9f, 0x40, 0x31, 0x80, 0x02, 0x12, 0x30, 0x82, 0x78, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xd6, 0x44, 0x10, 0x08, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x4d, 0x84, 0x61, +0xdd, 0x24, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x48, 0x58, 0xf7, 0x8a, 0xe4, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x46, 0xf0, 0x01, 0x10, +0x02, 0x07, 0x83, 0x06, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xe0, 0xdd, 0x2f, 0xc0, 0x11, +0x46, 0xf0, 0x01, 0x10, 0x00, 0x17, 0x85, 0xf9, 0xc1, 0x0c, 0x04, 0x10, 0x00, 0x26, 0x46, 0x24, +0x41, 0x00, 0x40, 0x10, 0x88, 0x02, 0xc1, 0x05, 0xa0, 0x42, 0x40, 0x10, 0x88, 0x04, 0xa8, 0x42, +0x46, 0xf0, 0x01, 0x0b, 0x04, 0x07, 0x80, 0x44, 0x84, 0xa1, 0xd8, 0x05, 0x84, 0xe0, 0x83, 0x87, +0x48, 0x00, 0x01, 0xa5, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x07, 0x84, 0x6f, 0x84, 0xa8, 0xd8, 0x06, +0x85, 0x01, 0x14, 0x8f, 0x80, 0x07, 0x81, 0x48, 0xd5, 0x06, 0x9c, 0x01, 0x54, 0xa0, 0x00, 0xff, +0x14, 0xaf, 0x80, 0x07, 0x84, 0x00, 0x84, 0x21, 0xf0, 0x83, 0xf1, 0x82, 0xf1, 0x84, 0xf1, 0x85, +0xf0, 0x86, 0x81, 0x00, 0x83, 0x80, 0x81, 0x20, 0x80, 0x0a, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, +0x83, 0xcc, 0xdd, 0x2f, 0x80, 0xc0, 0x4e, 0x02, 0x01, 0x09, 0x04, 0x30, 0x00, 0x6c, 0x4e, 0x33, +0x01, 0x05, 0xb4, 0x40, 0x54, 0x21, 0x00, 0x24, 0x4e, 0x23, 0x01, 0x00, 0x04, 0x40, 0x00, 0x25, +0x4e, 0x43, 0x00, 0xfc, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x27, 0x86, 0x04, 0x44, 0x00, 0x00, 0xff, +0x4c, 0x20, 0x40, 0x06, 0x46, 0xf0, 0x01, 0x08, 0x10, 0xa7, 0x86, 0x04, 0x80, 0x0a, 0x46, 0xf0, +0x00, 0xbe, 0x58, 0xf7, 0x8b, 0xfc, 0xdd, 0x2f, 0xb4, 0x46, 0x54, 0x21, 0x1b, 0xe1, 0x4e, 0x22, +0x00, 0xe4, 0x22, 0x43, 0x00, 0xcb, 0x4e, 0x47, 0x00, 0x09, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x27, +0x84, 0x70, 0x9a, 0xa2, 0x12, 0x23, 0x00, 0xcb, 0x22, 0x43, 0x00, 0xc5, 0x4e, 0x47, 0x00, 0x09, +0x46, 0xf0, 0x01, 0x13, 0x00, 0x27, 0x84, 0x70, 0x9a, 0xa2, 0x12, 0x23, 0x00, 0xc5, 0x44, 0x20, +0x00, 0x30, 0x42, 0x75, 0x08, 0x24, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x81, 0xdd, 0x22, 0x43, +0x00, 0xcb, 0x98, 0x97, 0x04, 0x31, 0x00, 0x0a, 0x5e, 0x42, 0x00, 0x01, 0x00, 0x21, 0x80, 0x53, +0xf3, 0x05, 0x85, 0x00, 0x40, 0x81, 0x90, 0x1a, 0xb4, 0xa6, 0x14, 0x8f, 0x80, 0x05, 0x04, 0x8f, +0x80, 0x03, 0x84, 0x81, 0x40, 0x44, 0x08, 0x1b, 0xf2, 0x04, 0x97, 0x6c, 0x40, 0x22, 0x94, 0x1a, +0x84, 0x03, 0x80, 0x2a, 0xf4, 0x83, 0xf2, 0x84, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8d, 0x90, +0xdd, 0x2f, 0x04, 0x8f, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x81, 0xdd, 0x40, 0x80, +0x00, 0x1a, 0x14, 0x8f, 0x80, 0x02, 0x98, 0x97, 0x04, 0x21, 0x00, 0x0a, 0x00, 0x21, 0x00, 0x2d, +0xc2, 0x0d, 0x44, 0x00, 0x00, 0x55, 0x80, 0x2a, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x8d, 0x90, +0xdd, 0x2f, 0x40, 0x80, 0x00, 0x1a, 0x14, 0x8f, 0x80, 0x02, 0x4e, 0x93, 0x00, 0x86, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x1f, 0x58, 0xf7, 0x80, 0x5c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, +0x81, 0xdd, 0x83, 0x80, 0x99, 0xd7, 0x04, 0x23, 0x80, 0x0a, 0x00, 0x21, 0x00, 0x37, 0xca, 0x10, +0x22, 0x23, 0x00, 0xcb, 0x4e, 0x26, 0x00, 0x04, 0x84, 0x41, 0xd5, 0x08, 0xc8, 0x03, 0x80, 0x40, +0xd5, 0x05, 0x22, 0x23, 0x00, 0xc5, 0x5e, 0x21, 0x00, 0x01, 0x96, 0x90, 0xc2, 0x65, 0x46, 0xf0, +0x01, 0x13, 0x10, 0xa7, 0x84, 0x6f, 0x04, 0x23, 0x80, 0x0a, 0x00, 0x21, 0x00, 0x37, 0xc2, 0x29, +0x00, 0x23, 0x01, 0xe8, 0xc2, 0x19, 0xa0, 0xbe, 0x84, 0xa3, 0x00, 0x21, 0x00, 0x09, 0xd2, 0x14, +0x00, 0x23, 0x01, 0xe6, 0x54, 0x21, 0x00, 0x08, 0xca, 0x0f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x1f, +0x58, 0xf7, 0x8f, 0x58, 0xdd, 0x2f, 0x00, 0x33, 0x01, 0xe6, 0x81, 0x06, 0x58, 0x21, 0x80, 0x08, +0x10, 0x23, 0x01, 0xe6, 0xd5, 0x3f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0x8c, 0x80, 0x07, +0xdd, 0x22, 0x85, 0x01, 0x40, 0x94, 0x00, 0x1b, 0x40, 0x70, 0x00, 0x1a, 0x81, 0x06, 0xd5, 0x36, +0x4f, 0xc2, 0x00, 0x05, 0x15, 0xc3, 0x80, 0x06, 0xd5, 0x2c, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x34, +0x58, 0xf7, 0x83, 0x94, 0xdd, 0x2f, 0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x06, 0x88, 0x40, 0x0e, +0x1c, 0x06, 0x80, 0x3c, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x00, 0xa0, 0x44, 0x30, 0x02, 0x68, +0x04, 0x93, 0x00, 0x28, 0x4b, 0xe0, 0x20, 0x01, 0xa0, 0xfe, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x00, 0xa0, 0x40, 0x0e, 0x0c, 0x06, 0x80, 0x3c, 0x44, 0x30, 0x02, 0x69, 0x4b, 0xe0, 0x20, 0x01, +0xa0, 0xbe, 0x84, 0x62, 0x10, 0x91, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x37, 0x84, 0x70, +0x81, 0x06, 0x85, 0x21, 0xd5, 0x03, 0x81, 0x06, 0xf7, 0x06, 0x8d, 0x41, 0x54, 0xa5, 0x00, 0xff, +0x5c, 0x25, 0x00, 0x09, 0x84, 0x01, 0xf1, 0x07, 0x40, 0xa0, 0x08, 0x1a, 0x4c, 0xa0, 0x80, 0x05, +0xf7, 0x86, 0x48, 0xff, 0xfe, 0xe3, 0x80, 0x9c, 0x83, 0x89, 0x4e, 0x93, 0x00, 0x25, 0x80, 0x09, +0x46, 0xf0, 0x00, 0x1f, 0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0xc0, 0x14, 0x46, 0xf0, 0x01, 0x01, +0x02, 0x27, 0x83, 0xbe, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x77, 0x81, 0xdd, 0x44, 0x10, 0x00, 0x30, +0x42, 0x71, 0x04, 0x73, 0x84, 0x42, 0xa8, 0x3e, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x27, 0x84, 0x70, +0xd5, 0x5d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x83, 0x9f, 0xf1, 0x05, 0xf2, 0x04, 0x80, 0x08, +0xdd, 0x23, 0xd5, 0x54, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x07, 0x84, 0x6f, 0xf4, 0x81, 0x46, 0xf0, +0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0x04, 0x33, 0x80, 0x0a, 0x80, 0xc0, 0x00, 0x31, +0x80, 0x37, 0xf4, 0x01, 0xcb, 0x0a, 0xcc, 0x0a, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, 0x80, 0xcd, +0xdd, 0x23, 0x12, 0x03, 0x00, 0xcb, 0xd5, 0x06, 0xc4, 0x05, 0x02, 0x23, 0x00, 0x48, 0x12, 0x23, +0x00, 0xc5, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x37, 0x81, 0x80, 0x84, 0x9f, 0x4c, 0x32, 0x00, 0x07, +0xf0, 0x03, 0xc0, 0x04, 0xf1, 0x02, 0x84, 0xa1, 0xd9, 0x18, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, +0x83, 0x9f, 0xf1, 0x05, 0xf2, 0x04, 0x80, 0x08, 0xdd, 0x23, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x27, +0x86, 0x34, 0x84, 0xa1, 0xda, 0x0a, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x27, 0x81, 0x92, 0x84, 0x20, +0x5c, 0x21, 0x00, 0x0f, 0x41, 0xc0, 0x88, 0x1a, 0xcf, 0x03, 0x80, 0x67, 0xd5, 0x03, 0x00, 0x33, +0x80, 0x20, 0x84, 0x06, 0x84, 0x21, 0x44, 0x20, 0x70, 0x83, 0x80, 0x9c, 0x46, 0xf0, 0x00, 0x35, +0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x40, 0x7e, 0x70, 0x1a, 0x80, 0x07, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x17, +0x85, 0xc8, 0xc9, 0x24, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0x00, 0x84, 0x0f, 0xdd, 0x22, +0x84, 0x01, 0x46, 0xf0, 0x01, 0x10, 0x10, 0x07, 0x85, 0xc8, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x67, +0x80, 0x9a, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x83, 0x2c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x22, +0x58, 0xf7, 0x8f, 0xd0, 0xdd, 0x2f, 0xdd, 0x26, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x9b, +0x46, 0x00, 0x0f, 0xff, 0x58, 0x00, 0x0f, 0xff, 0xdd, 0x21, 0x84, 0x00, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x17, 0x81, 0x84, +0x80, 0xc0, 0x96, 0x0c, 0x4e, 0x02, 0x00, 0xe5, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x07, 0x81, 0x70, +0x54, 0x00, 0x00, 0x80, 0x4e, 0x02, 0x00, 0xdd, 0x46, 0x70, 0x00, 0x28, 0x58, 0x73, 0x83, 0x2c, +0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x00, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x97, 0x81, 0xdd, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x8f, 0xd0, 0xdd, 0x2f, 0xc0, 0x2b, 0xb4, 0x20, +0xe6, 0x26, 0xe8, 0x07, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x86, 0x2c, 0xd5, 0x26, +0x80, 0x49, 0x44, 0x30, 0x00, 0x30, 0x42, 0x24, 0x0c, 0x73, 0x00, 0x01, 0x00, 0x22, 0x84, 0x41, +0x4c, 0x01, 0x40, 0x0d, 0x4c, 0x60, 0x40, 0x1b, 0x56, 0x10, 0x80, 0x09, 0x40, 0x10, 0x88, 0x06, +0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x86, 0x2c, 0xd5, 0x14, 0x84, 0xa7, 0xde, 0x0f, 0x56, 0x00, +0x80, 0x0f, 0x5c, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x07, 0x86, 0x2c, 0x48, 0x00, +0x00, 0xa0, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x07, 0x86, 0x2c, 0x44, 0x50, 0x00, 0x13, 0xd6, 0x05, +0x44, 0x00, 0x00, 0x16, 0x4c, 0x60, 0x40, 0x4f, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xd9, +0x54, 0x00, 0x00, 0x11, 0xc0, 0x34, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x86, 0x2c, 0xc0, 0x18, +0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, +0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x07, 0x04, 0x10, 0x00, 0x08, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x08, +0xd5, 0x77, 0x04, 0x10, 0x00, 0x09, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x09, 0xd5, 0x71, 0x46, 0x00, +0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, 0x42, 0x10, +0xc0, 0x0b, 0xc9, 0x07, 0x04, 0x10, 0x00, 0x0a, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x0a, 0xd5, 0x60, +0x04, 0x10, 0x00, 0x0b, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x0b, 0xd5, 0x5a, 0x46, 0x00, 0x04, 0xa0, +0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, 0x42, 0x10, 0xc0, 0x0b, +0xc9, 0x05, 0xa0, 0x42, 0x9c, 0x49, 0xa8, 0x42, 0xd5, 0x4b, 0xa0, 0x43, 0x9c, 0x49, 0xa8, 0x43, +0xd5, 0x47, 0x9d, 0x43, 0xde, 0x45, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x82, 0xd9, 0x54, 0x00, +0x00, 0x11, 0xc0, 0x2c, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x86, 0x2c, 0xc0, 0x14, 0x46, 0x00, +0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, 0x42, 0x10, +0xc0, 0x0b, 0xc9, 0x05, 0xa0, 0x44, 0x9c, 0x49, 0xa8, 0x44, 0xd5, 0x2a, 0xa0, 0x45, 0x9c, 0x49, +0xa8, 0x45, 0xd5, 0x26, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x10, +0x58, 0x00, 0x02, 0x24, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x05, 0xa0, 0x46, 0x9c, 0x49, 0xa8, 0x46, +0xd5, 0x17, 0xa0, 0x47, 0x9c, 0x49, 0xa8, 0x47, 0xd5, 0x13, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, +0x01, 0x01, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x02, 0x24, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x05, +0xb4, 0x20, 0x9c, 0x49, 0xb6, 0x20, 0xd5, 0x04, 0xa0, 0x41, 0x9c, 0x49, 0xa8, 0x41, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x07, +0x00, 0x27, 0x80, 0x20, 0x96, 0x00, 0xca, 0x1c, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x27, 0x81, 0x8f, +0xe6, 0x4f, 0xe9, 0x09, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x17, 0x83, 0xff, 0x46, 0xf0, 0x01, 0x10, +0x14, 0x17, 0x81, 0x8f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x85, 0xbc, 0xdd, 0x2f, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x10, 0x10, 0x17, 0x86, 0x34, 0x48, 0x00, 0x00, 0xb2, 0x46, 0xf0, +0x01, 0x08, 0x00, 0x87, 0x8f, 0x8f, 0xe7, 0x02, 0xe9, 0x03, 0x84, 0x41, 0xd5, 0x06, 0x84, 0x40, +0x46, 0xf0, 0x01, 0x10, 0x10, 0x27, 0x86, 0x64, 0x46, 0xf0, 0x01, 0x10, 0x10, 0x27, 0x86, 0x63, +0x50, 0x10, 0x7f, 0xf1, 0x84, 0x42, 0xe2, 0x41, 0x4e, 0xf3, 0x00, 0x96, 0x4e, 0x83, 0x00, 0x58, +0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0f, 0xf0, 0x00, 0x03, 0x00, 0x33, 0xc0, 0x50, 0x00, 0x53, +0x00, 0x34, 0xd8, 0x4d, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0x0b, 0x81, 0x20, 0xdd, 0x21, 0x80, 0xe0, 0x46, 0x10, +0x00, 0x26, 0x58, 0x10, 0x85, 0x90, 0xc8, 0x14, 0x00, 0x03, 0x00, 0x2e, 0x4b, 0xe0, 0x04, 0x01, +0x80, 0xe0, 0x84, 0xbf, 0xdf, 0x3e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd7, 0x00, 0x33, +0x00, 0x2e, 0xa0, 0xb3, 0x80, 0x28, 0x44, 0x00, 0x70, 0x1b, 0xdd, 0x24, 0xd5, 0x32, 0x00, 0x03, +0x00, 0x2e, 0x4b, 0xe0, 0x04, 0x01, 0x84, 0x3f, 0x81, 0x00, 0x4c, 0x00, 0xc0, 0x0d, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd7, 0x00, 0x33, 0x00, 0x2e, 0xa0, 0xb3, 0x44, 0x00, 0x70, 0x1b, +0x84, 0x21, 0xdd, 0x24, 0x80, 0x27, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0x2c, +0xdd, 0x2f, 0x84, 0x3f, 0x80, 0xe0, 0x4c, 0x80, 0x80, 0x15, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x34, +0x58, 0xf7, 0x87, 0xf0, 0xdd, 0x2f, 0x40, 0x74, 0x00, 0x1b, 0xd5, 0x0b, 0x46, 0xf0, 0x01, 0x07, +0x00, 0x07, 0x80, 0x1e, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x85, 0x90, 0xdd, 0x2f, 0x80, 0xe0, +0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xff, 0x46, 0x10, 0x00, 0x28, 0x58, 0x10, 0x85, 0xbc, +0x8e, 0x0f, 0xe6, 0x03, 0xe8, 0x0a, 0x84, 0x01, 0x4b, 0xe0, 0x04, 0x01, 0x84, 0x3f, 0x46, 0xf0, +0x01, 0x08, 0x14, 0x17, 0x81, 0x80, 0xd5, 0x04, 0x84, 0x00, 0x4b, 0xe0, 0x04, 0x01, 0x46, 0xf0, +0x01, 0x06, 0x02, 0x37, 0x87, 0xfe, 0x84, 0x06, 0x44, 0x11, 0x00, 0x00, 0x44, 0x20, 0x70, 0x95, +0x80, 0x87, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x89, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x37, 0x80, 0xe3, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xff, 0x80, 0x47, 0x84, 0x20, +0xdd, 0x23, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x15, 0x58, 0xf7, 0x82, 0x44, 0xdd, 0x2f, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x80, +0x04, 0x80, 0x80, 0x0b, 0x50, 0x60, 0x00, 0x1c, 0x46, 0x02, 0x20, 0x00, 0x40, 0x34, 0x00, 0x02, +0x04, 0xa0, 0x80, 0x19, 0xa7, 0xf4, 0x4e, 0x33, 0x01, 0x26, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, +0x85, 0xe7, 0x4e, 0x02, 0x01, 0x20, 0x40, 0x04, 0x34, 0x08, 0x92, 0x1d, 0xc8, 0x1a, 0x54, 0x74, +0x3c, 0x00, 0x92, 0xea, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x57, 0xc3, 0x80, 0x02, +0x44, 0x50, 0x00, 0x12, 0x44, 0xa0, 0x00, 0x11, 0x84, 0x03, 0x84, 0x24, 0x44, 0x20, 0x10, 0x25, +0x80, 0x68, 0x40, 0x95, 0x70, 0x1a, 0x40, 0x92, 0xf0, 0x1b, 0xdd, 0x24, 0x48, 0x00, 0x01, 0x56, +0xa0, 0x73, 0x50, 0x10, 0x80, 0x2c, 0x96, 0x00, 0xa7, 0x4f, 0xd8, 0x03, 0xae, 0xce, 0xd5, 0x16, +0xa6, 0xce, 0x84, 0x45, 0x50, 0x40, 0xff, 0xd4, 0x42, 0x41, 0x88, 0x73, 0x00, 0x52, 0x00, 0x33, +0x4c, 0x50, 0x41, 0x95, 0x84, 0x01, 0xae, 0x0e, 0xd5, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, +0x82, 0x37, 0x84, 0xa1, 0xd0, 0x03, 0x48, 0x00, 0x01, 0x02, 0x04, 0x33, 0x7f, 0xfa, 0xc3, 0x17, +0x54, 0x94, 0x3c, 0x00, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x27, 0x83, 0xdf, 0x93, 0x2a, 0x80, 0x29, +0x80, 0x07, 0xdd, 0x22, 0x50, 0x03, 0x7f, 0xe4, 0x54, 0x25, 0x00, 0x1f, 0x80, 0x69, 0x84, 0x26, +0x84, 0x80, 0x46, 0xf0, 0x00, 0x29, 0x58, 0xf7, 0x89, 0xec, 0xdd, 0x2f, 0xa0, 0x73, 0x40, 0x04, +0x20, 0x05, 0x92, 0x1f, 0x10, 0x00, 0x80, 0x53, 0x4e, 0x85, 0x00, 0x09, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x80, 0xcb, 0x50, 0x03, 0x7f, 0xe4, 0xdd, 0x21, 0x42, 0x04, 0x38, 0x0b, 0xc0, 0x36, +0xa0, 0x33, 0x84, 0x25, 0x00, 0x20, 0x00, 0x32, 0x42, 0x01, 0x04, 0x73, 0x50, 0x00, 0x00, 0x30, +0xa6, 0x47, 0xc1, 0x2c, 0x84, 0x20, 0xae, 0x47, 0xa0, 0x73, 0x50, 0x10, 0x80, 0x2d, 0xa6, 0x0d, +0xc8, 0x51, 0xa6, 0x8f, 0x56, 0x21, 0x00, 0x01, 0xae, 0x8f, 0xa0, 0x73, 0x10, 0x00, 0x80, 0x52, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x81, 0x65, 0xe6, 0x02, 0xe9, 0x07, 0x04, 0x03, 0x7f, 0xff, +0x84, 0xa3, 0x00, 0x00, 0x00, 0x09, 0xd8, 0x3e, 0xa0, 0x73, 0x80, 0x07, 0x02, 0x20, 0x80, 0x13, +0x9c, 0x91, 0x12, 0x20, 0x80, 0x13, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x17, 0x83, 0xfc, 0xdd, 0x21, +0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x02, 0x60, 0xd5, 0x28, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, +0x81, 0x65, 0x84, 0xa7, 0xd8, 0x27, 0xa0, 0x33, 0x84, 0x45, 0x00, 0x10, 0x00, 0x32, 0x42, 0x00, +0x88, 0x73, 0x50, 0x00, 0x00, 0x30, 0xa6, 0x47, 0xc1, 0x1d, 0x04, 0x13, 0x7f, 0xff, 0x84, 0xa3, +0x00, 0x10, 0x80, 0x09, 0xd1, 0x17, 0x84, 0x20, 0xae, 0x47, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, +0x02, 0x60, 0xa0, 0x73, 0x00, 0x30, 0x80, 0x32, 0x42, 0x11, 0x88, 0x73, 0x50, 0x10, 0x80, 0x30, +0xa6, 0x8c, 0x56, 0x21, 0x00, 0x01, 0xae, 0x8c, 0x04, 0x10, 0x00, 0x54, 0x9c, 0x49, 0x14, 0x10, +0x00, 0x54, 0x46, 0x00, 0x04, 0x80, 0xa0, 0x07, 0x54, 0x74, 0x3c, 0x00, 0x96, 0x04, 0x92, 0xea, +0xc0, 0x09, 0x9e, 0x3e, 0xe6, 0x02, 0xe9, 0x18, 0x84, 0xac, 0xd7, 0x16, 0x84, 0xad, 0xdf, 0x02, +0xd5, 0x13, 0x46, 0x00, 0x04, 0x80, 0xa0, 0x07, 0x42, 0x00, 0x04, 0x0b, 0xc0, 0x18, 0x84, 0xa4, +0xd7, 0x0b, 0x84, 0xa8, 0xd7, 0x09, 0x84, 0xaa, 0xd7, 0x07, 0x84, 0xab, 0xd7, 0x05, 0x84, 0xae, +0xd7, 0x03, 0x84, 0xaf, 0xdf, 0x0c, 0xa0, 0x73, 0x84, 0x01, 0x10, 0x00, 0x80, 0x56, 0x46, 0x00, +0x00, 0x09, 0x58, 0x00, 0x0d, 0xf4, 0x38, 0x70, 0x1c, 0x00, 0xd5, 0x05, 0xa0, 0x73, 0x84, 0x00, +0x10, 0x00, 0x80, 0x56, 0x84, 0xa7, 0xdf, 0x12, 0xa0, 0x33, 0x00, 0x00, 0x00, 0x32, 0xc8, 0x0c, +0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, 0x81, 0x65, 0xc0, 0x09, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, +0x82, 0xe9, 0x8c, 0xb0, 0xd8, 0x03, 0x44, 0x70, 0x00, 0x17, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x27, +0x83, 0xfd, 0xa6, 0x34, 0x80, 0x27, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0x84, 0x24, 0x84, 0x03, 0x44, 0x20, 0x10, 0x28, 0x80, 0x68, 0xdd, 0x24, 0x44, 0x90, 0x00, 0x11, +0xd5, 0x54, 0x42, 0x04, 0x74, 0x0b, 0xc0, 0x1c, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0xe7, +0xc0, 0x17, 0xa0, 0x33, 0x84, 0x25, 0x00, 0x20, 0x00, 0x32, 0x80, 0x68, 0x42, 0x01, 0x04, 0x73, +0x84, 0x20, 0x50, 0x00, 0x00, 0x30, 0xae, 0x45, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0x84, 0x03, 0x84, 0x24, 0x44, 0x20, 0x10, 0x26, 0xdd, 0x24, 0x85, 0x29, 0xd5, 0x34, 0xa0, 0x33, +0x84, 0x25, 0x00, 0x20, 0x00, 0x32, 0x42, 0x01, 0x04, 0x73, 0x84, 0x20, 0x50, 0x00, 0x00, 0x30, +0xae, 0x45, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0xe7, 0xc0, 0x1a, 0x84, 0x40, 0x50, 0x03, +0x7f, 0xe4, 0x84, 0x23, 0x80, 0x62, 0x80, 0x82, 0x46, 0xf0, 0x00, 0x29, 0x58, 0xf7, 0x89, 0xec, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x8c, 0xa0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0a, +0x04, 0x17, 0x80, 0x9b, 0x9c, 0x49, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x80, 0x9b, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x84, 0x24, 0x84, 0x03, 0x44, 0x20, 0x10, 0x27, 0x80, 0x68, +0xdd, 0x24, 0x85, 0x2a, 0x44, 0x70, 0x00, 0x11, 0xa0, 0x73, 0x46, 0x00, 0x04, 0x80, 0x10, 0x70, +0x80, 0x2c, 0xa0, 0x73, 0x84, 0x81, 0x14, 0x90, 0x80, 0x07, 0xa0, 0x04, 0x42, 0x50, 0x18, 0x0b, +0xdc, 0x4e, 0x46, 0x00, 0x20, 0x00, 0x40, 0x84, 0x00, 0x02, 0x4e, 0x83, 0x00, 0x49, 0x46, 0xf0, +0x00, 0x29, 0x58, 0xf7, 0x8b, 0x70, 0xdd, 0x2f, 0x81, 0x20, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, +0x88, 0x78, 0xdd, 0x2f, 0x80, 0xe0, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, +0xdd, 0x2f, 0x80, 0x20, 0x5c, 0xf3, 0x82, 0x72, 0xe9, 0x05, 0x54, 0x00, 0x00, 0x02, 0xc8, 0x02, +0x9e, 0x4c, 0x46, 0x20, 0x04, 0x90, 0x04, 0x01, 0x00, 0x0f, 0x96, 0x05, 0x5c, 0xf0, 0x02, 0x72, +0xe9, 0x10, 0x46, 0x30, 0xff, 0xff, 0x58, 0x31, 0x8f, 0xfc, 0x40, 0x24, 0x8c, 0x02, 0x40, 0x10, +0x8c, 0x02, 0x9a, 0x51, 0x14, 0x13, 0x7f, 0xfe, 0xad, 0xf0, 0x14, 0x23, 0x7f, 0xf9, 0xd5, 0x17, +0x80, 0x02, 0x04, 0x30, 0x00, 0x0d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x84, 0x21, +0x84, 0x03, 0x44, 0x20, 0x10, 0x2f, 0xdd, 0x24, 0xd5, 0x0a, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x07, +0x81, 0x65, 0x84, 0xa8, 0x4c, 0x02, 0xfe, 0x6b, 0x48, 0xff, 0xfe, 0x71, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x30, 0x04, 0x80, +0x80, 0xc1, 0x80, 0x43, 0x04, 0x11, 0x80, 0x08, 0x54, 0x73, 0x00, 0x0f, 0x46, 0x18, 0x00, 0x24, +0xa0, 0xd7, 0x40, 0x23, 0xa8, 0x08, 0x04, 0x50, 0x00, 0x0a, 0x40, 0x21, 0x04, 0x04, 0x92, 0x62, +0x94, 0xda, 0x84, 0x80, 0x10, 0x42, 0x80, 0x57, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x37, 0x80, 0x91, +0x46, 0xf0, 0x01, 0x0a, 0x14, 0x27, 0x80, 0x8e, 0x84, 0x25, 0x04, 0x00, 0x00, 0x0a, 0x00, 0x20, +0x00, 0x31, 0x42, 0x01, 0x04, 0x73, 0x00, 0x00, 0x00, 0x33, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, +0x89, 0xd4, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x02, 0x60, 0xe6, 0xd8, 0xe8, 0x08, +0x8c, 0xc8, 0x38, 0x10, 0x1a, 0x02, 0x9c, 0x49, 0x38, 0x10, 0x1a, 0x0a, 0xd5, 0x08, 0x50, 0x13, +0x80, 0x34, 0x38, 0x20, 0x06, 0x02, 0x9c, 0x91, 0x38, 0x20, 0x06, 0x0a, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x01, 0x0a, +0x58, 0x63, 0x0c, 0x08, 0xa0, 0x34, 0x84, 0x41, 0x04, 0x00, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x17, 0x87, 0x17, 0x10, 0x20, 0x00, 0x33, 0x44, 0x00, 0x01, 0x00, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x89, 0xf8, 0xdd, 0x2f, 0xa0, 0x34, 0x84, 0x20, 0x46, 0xf0, 0x00, 0xc4, 0x58, 0xf7, +0x8c, 0xe8, 0xdd, 0x2f, 0xa1, 0xb4, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x27, 0x46, 0xf0, +0x01, 0x0a, 0x14, 0x67, 0x80, 0x95, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xe7, 0x46, 0x70, +0x01, 0x38, 0x58, 0x73, 0x8a, 0x80, 0xae, 0x38, 0x84, 0x03, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x27, 0x80, 0x2c, 0x84, 0x21, 0x80, 0x07, 0xdd, 0x22, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x89, 0xe7, +0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x0a, 0x80, 0x46, 0x60, 0x01, 0x01, 0x58, 0x63, 0x07, 0x14, +0xae, 0x52, 0x46, 0xf0, 0x01, 0x0a, 0x10, 0x17, 0x81, 0x72, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, +0x80, 0x2c, 0x00, 0x83, 0x00, 0x03, 0x80, 0xe0, 0x84, 0x24, 0x80, 0x02, 0xdd, 0x23, 0x80, 0x28, +0x44, 0x00, 0x01, 0x00, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x89, 0xe0, 0xdd, 0x2f, 0x80, 0x28, +0x44, 0x00, 0x01, 0x00, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x89, 0xf8, 0xdd, 0x2f, 0xa6, 0xb2, +0xa6, 0x31, 0xa6, 0x70, 0x40, 0x21, 0x40, 0x08, 0x40, 0x00, 0x20, 0x08, 0x98, 0x10, 0x98, 0x01, +0x80, 0x5f, 0x50, 0x1f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x89, 0xb0, 0xdd, 0x2f, +0x80, 0x1f, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, 0x8b, 0x88, 0xdd, 0x2f, 0x04, 0x03, 0x80, 0x0a, +0xb4, 0x3f, 0xf6, 0x01, 0xb6, 0x20, 0xa9, 0x81, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x77, 0x80, 0x94, +0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x01, 0x84, 0x20, 0x44, 0x20, 0x00, 0x13, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, +0xdd, 0x2f, 0xc0, 0x1f, 0xb4, 0x00, 0x84, 0x5a, 0xae, 0x80, 0x8c, 0x57, 0x84, 0x3f, 0xae, 0x81, +0x84, 0x40, 0xae, 0x47, 0x10, 0x20, 0x00, 0x08, 0xae, 0x42, 0xae, 0x43, 0xae, 0x44, 0xae, 0x45, +0xae, 0x46, 0x84, 0x4a, 0x8c, 0x09, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x54, 0x81, +0x00, 0xff, 0x80, 0xc0, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, +0x4e, 0x82, 0x00, 0x08, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x8c, 0xe8, 0xdd, 0x2f, 0xd5, 0x25, +0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x8c, 0x80, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x56, 0x58, 0xf7, +0x84, 0x0c, 0xdd, 0x2f, 0x84, 0xa3, 0xd8, 0x05, 0x46, 0x30, 0x04, 0x03, 0x14, 0x81, 0x81, 0x07, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0x57, 0xdd, 0x20, 0x84, 0x0a, 0x46, 0xf0, 0x00, 0x59, +0x58, 0xf7, 0x84, 0x1c, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x02, 0x84, 0x00, 0x80, 0x43, 0x14, 0x01, +0x82, 0x14, 0x84, 0x01, 0x14, 0x01, 0x02, 0x15, 0x46, 0xf0, 0x00, 0x54, 0x58, 0xf7, 0x85, 0x28, +0xdd, 0x2f, 0x44, 0x00, 0x00, 0x32, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x84, 0x1c, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x8c, 0x80, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, +0x8d, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x8e, 0x00, 0xdd, 0x2f, 0x84, 0xa4, +0xde, 0x0d, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x8e, 0x88, 0xdd, 0x2f, 0x80, 0x07, +0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x88, 0x50, 0xdd, 0x2f, 0x46, 0x70, 0x01, 0x11, 0x58, 0x73, +0x8d, 0x4c, 0x50, 0x03, 0x80, 0x2e, 0x3a, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x02, 0xc0, 0x14, +0x46, 0xf0, 0x00, 0x56, 0x58, 0xf7, 0x84, 0x88, 0xdd, 0x2f, 0x04, 0x03, 0x83, 0x2d, 0x02, 0x10, +0x00, 0x0b, 0x40, 0x00, 0xa0, 0x09, 0x54, 0x00, 0x00, 0x0f, 0x92, 0x2c, 0x46, 0xf0, 0x00, 0x56, +0x58, 0xf7, 0x86, 0x6c, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x59, 0x58, 0xf7, 0x88, 0xbc, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0x58, 0xdd, 0x20, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x46, 0xf0, 0x00, 0xc0, 0x58, 0xf7, 0x80, 0x74, +0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x8f, 0x6c, 0xdd, 0x2f, 0x80, 0x06, +0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x8f, 0x14, 0xdd, 0x2f, 0x80, 0x26, 0x84, 0x04, 0x84, 0x41, +0x46, 0xf0, 0x00, 0xc4, 0x58, 0xf7, 0x8e, 0xfc, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xa4, 0x8b, 0xa5, 0xc9, 0xa5, 0x8a, 0x46, 0xf0, +0x01, 0x13, 0x14, 0x27, 0x81, 0x92, 0x84, 0x03, 0x4c, 0x70, 0x00, 0x91, 0x84, 0x24, 0x4c, 0x70, +0x80, 0x9b, 0x84, 0x61, 0x4c, 0x71, 0xc1, 0x7f, 0x80, 0x26, 0x46, 0x00, 0x00, 0xd2, 0x58, 0x00, +0x00, 0xcc, 0x54, 0x83, 0x03, 0xe0, 0x54, 0xa3, 0x00, 0x18, 0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, +0x09, 0xd0, 0xdd, 0x3c, 0x93, 0x43, 0x93, 0x05, 0x54, 0x63, 0x00, 0x07, 0x87, 0xc0, 0x84, 0x80, +0x46, 0xf0, 0x01, 0x38, 0x11, 0xe7, 0x8a, 0x1c, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x67, 0x8a, 0x18, +0x46, 0xf0, 0x01, 0x38, 0x10, 0xa7, 0x8a, 0x1a, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, 0x8a, 0x1b, +0x46, 0xf0, 0x01, 0x38, 0x11, 0xe7, 0x8a, 0x19, 0x80, 0x26, 0x46, 0x00, 0x00, 0xd2, 0x58, 0x00, +0x00, 0xfc, 0x80, 0x4a, 0x80, 0x68, 0x80, 0xa4, 0xdd, 0x3c, 0x4e, 0xa2, 0x00, 0x4b, 0x80, 0x08, +0x46, 0xf0, 0x00, 0xc0, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x54, 0x24, 0x00, 0x07, 0x94, 0x92, +0x9c, 0x53, 0x40, 0x13, 0x84, 0x0c, 0x40, 0x23, 0x88, 0x0c, 0x9e, 0xc9, 0x40, 0x11, 0x84, 0x04, +0x52, 0x31, 0x00, 0x00, 0x40, 0x10, 0x8c, 0x02, 0xb4, 0x60, 0x40, 0x10, 0x84, 0x05, 0x40, 0x11, +0x84, 0x02, 0xb6, 0x20, 0x46, 0x10, 0x04, 0x00, 0xb4, 0x60, 0x40, 0x21, 0x88, 0x04, 0xb6, 0x40, +0x40, 0x23, 0xa0, 0x0c, 0x04, 0x00, 0x80, 0x6e, 0x40, 0x01, 0x00, 0x04, 0x14, 0x00, 0x80, 0x6e, +0xe7, 0x0b, 0xe8, 0x1f, 0x89, 0x08, 0x50, 0x14, 0x00, 0x01, 0x40, 0x13, 0x84, 0x0c, 0x9e, 0x89, +0x40, 0x73, 0xa0, 0x0c, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x58, 0x40, 0x11, 0x04, 0x04, +0x52, 0x73, 0x80, 0x00, 0xb4, 0x40, 0x40, 0x10, 0x9c, 0x02, 0x40, 0x10, 0x84, 0x05, 0x40, 0x10, +0x88, 0x02, 0xb6, 0x20, 0x40, 0x85, 0x20, 0x0c, 0xb4, 0x20, 0x40, 0x84, 0x04, 0x04, 0xb7, 0x00, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9d, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8a, 0x18, +0x44, 0x00, 0x00, 0x7c, 0xdd, 0x22, 0x48, 0x00, 0x00, 0xf6, 0xce, 0x02, 0xd5, 0x04, 0x84, 0x81, +0x4c, 0x62, 0x40, 0xf1, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xc5, 0x58, 0xf7, 0x80, 0x14, 0xdd, 0x2f, +0x48, 0x00, 0x00, 0xe9, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x8c, 0xb4, 0xdd, 0x2f, 0x96, 0x70, +0x9e, 0x8a, 0x54, 0x21, 0x00, 0x03, 0x92, 0xc8, 0x94, 0x94, 0xc0, 0x04, 0x84, 0xa2, 0x4c, 0x02, +0xc0, 0x84, 0x54, 0x33, 0x00, 0x02, 0xc3, 0x1a, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x37, 0x83, 0xb0, +0x84, 0xa1, 0xae, 0x5b, 0x46, 0x30, 0x04, 0x02, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x47, 0x83, 0xb0, +0x58, 0x31, 0x81, 0x14, 0xaf, 0x66, 0x44, 0x5f, 0xff, 0xcf, 0xb4, 0x83, 0x40, 0x42, 0x14, 0x02, +0xb6, 0x83, 0xb4, 0x83, 0x40, 0x41, 0x10, 0x04, 0xb6, 0x83, 0x54, 0x33, 0x00, 0x04, 0xc3, 0x1a, +0x46, 0xf0, 0x01, 0x11, 0x04, 0x37, 0x83, 0xb1, 0x84, 0xa1, 0xae, 0x5b, 0x46, 0x30, 0x04, 0x02, +0x46, 0xf0, 0x01, 0x11, 0x04, 0x47, 0x83, 0xb1, 0x58, 0x31, 0x81, 0x24, 0xaf, 0x66, 0x44, 0x5f, +0xff, 0xcf, 0xb4, 0x83, 0x40, 0x42, 0x14, 0x02, 0xb6, 0x83, 0xb4, 0x83, 0x40, 0x41, 0x10, 0x04, +0xb6, 0x83, 0x54, 0x33, 0x00, 0x08, 0xc3, 0x1a, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x37, 0x80, 0x07, +0x84, 0xa1, 0xae, 0x5b, 0x46, 0x30, 0x04, 0x02, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x47, 0x80, 0x07, +0x58, 0x31, 0x81, 0x34, 0xaf, 0x66, 0x44, 0x5f, 0xff, 0xcf, 0xb4, 0x83, 0x40, 0x42, 0x14, 0x02, +0xb6, 0x83, 0xb4, 0x83, 0x40, 0x41, 0x10, 0x04, 0xb6, 0x83, 0x84, 0x62, 0x4c, 0x01, 0xc0, 0x67, +0x54, 0x03, 0x00, 0x10, 0xc0, 0x1a, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x07, 0x80, 0x5e, 0x84, 0x81, +0xae, 0x43, 0x46, 0x00, 0x04, 0x02, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x37, 0x80, 0x5e, 0x58, 0x00, +0x01, 0x44, 0xaf, 0x1e, 0x44, 0x4f, 0xff, 0xcf, 0xb4, 0x60, 0x40, 0x31, 0x90, 0x02, 0xb6, 0x60, +0xb4, 0x60, 0x40, 0x31, 0x0c, 0x04, 0xb6, 0x60, 0x54, 0x63, 0x00, 0x20, 0xc6, 0x47, 0x46, 0xf0, +0x01, 0x12, 0x04, 0x07, 0x80, 0x5f, 0xae, 0x43, 0x46, 0x00, 0x04, 0x02, 0x46, 0xf0, 0x01, 0x12, +0x04, 0x17, 0x80, 0x5f, 0xd5, 0x2d, 0x84, 0x61, 0x4c, 0x01, 0xc0, 0x39, 0x54, 0x33, 0x00, 0x10, +0xc3, 0x19, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x57, 0x83, 0xb0, 0x46, 0x30, 0x04, 0x02, 0xae, 0x6b, +0x58, 0x31, 0x81, 0x44, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x47, 0x83, 0xb0, 0xae, 0x26, 0x44, 0x4f, +0xff, 0xcf, 0xb4, 0x03, 0x40, 0x00, 0x10, 0x02, 0xb6, 0x03, 0xb4, 0x03, 0x40, 0x01, 0x00, 0x04, +0xb6, 0x03, 0x54, 0x63, 0x00, 0x20, 0xc6, 0x1a, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x07, 0x83, 0xb1, +0xae, 0x43, 0x46, 0x00, 0x04, 0x02, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x17, 0x83, 0xb1, 0x84, 0x61, +0xae, 0xce, 0x58, 0x00, 0x01, 0x54, 0xb4, 0x20, 0x44, 0x5f, 0xff, 0xcf, 0x40, 0x10, 0x94, 0x02, +0xb6, 0x20, 0xb4, 0x20, 0x40, 0x21, 0x04, 0x04, 0xb6, 0x40, 0x46, 0x00, 0x04, 0x02, 0x04, 0x00, +0x02, 0x00, 0x84, 0x24, 0x54, 0x00, 0x00, 0x07, 0x4c, 0x00, 0xc0, 0x07, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x37, 0x81, 0x59, 0xd5, 0x0c, 0x84, 0x61, 0x4c, 0x01, 0x80, 0x05, 0x84, 0x83, 0x4c, 0x02, +0x40, 0x0a, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, 0x81, 0x59, 0x84, 0x03, 0x84, 0x20, 0x84, 0x41, +0xdd, 0x23, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x84, 0xa4, 0x96, 0x00, 0xd9, 0x09, 0x46, 0x50, 0x04, 0xb0, 0x04, 0x62, 0x80, 0x20, 0x42, 0x63, +0x1c, 0x09, 0x14, 0x62, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x43, 0x58, 0xf7, 0x8d, 0x64, 0xdd, 0x2f, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x84, 0xe0, +0x80, 0xc0, 0x80, 0x27, 0x40, 0x03, 0x80, 0x06, 0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x06, 0x88, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x00, 0xa0, 0x44, 0x30, 0x02, 0x51, 0x4b, 0xe0, 0x20, 0x01, +0xa0, 0x36, 0x80, 0x27, 0x40, 0x03, 0x80, 0x06, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x00, 0xa0, +0x44, 0x30, 0x02, 0x52, 0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x36, 0x00, 0x70, 0x00, 0x08, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x17, 0x80, 0x27, 0x84, 0x03, 0xdd, 0x21, 0xc7, 0x3d, 0x84, 0xa1, 0xdf, 0x02, +0xd5, 0x33, 0x04, 0x03, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x53, 0xc9, 0x2a, 0x84, 0x41, 0x10, 0x20, +0x00, 0x37, 0x84, 0x42, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x8e, 0xb0, 0xdd, 0x2f, +0x80, 0x27, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x2b, 0x58, 0xf7, 0x8d, 0x08, 0xdd, 0x2f, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x2b, 0x58, 0xf7, 0x8b, 0xa8, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x17, +0x85, 0xf9, 0xc1, 0x1f, 0x46, 0xf0, 0x01, 0x10, 0x04, 0x57, 0x81, 0x80, 0xde, 0x1a, 0x46, 0x00, +0x01, 0x38, 0x04, 0x10, 0x02, 0x35, 0x9c, 0x49, 0x14, 0x10, 0x02, 0x35, 0xd5, 0x12, 0x00, 0x03, +0x00, 0x22, 0x84, 0xa1, 0xd8, 0x08, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x8f, 0xc0, +0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x8f, 0xec, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x0a, 0x14, 0x67, 0x80, 0x95, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x27, 0x85, 0xf9, 0x96, 0x00, 0xc2, 0x0f, +0x46, 0xf0, 0x01, 0x10, 0x04, 0x17, 0x81, 0x80, 0x00, 0x50, 0x80, 0x20, 0xd8, 0x08, 0x46, 0x10, +0x01, 0x38, 0x04, 0x20, 0x82, 0x36, 0x9c, 0x91, 0x14, 0x20, 0x82, 0x36, 0x46, 0xf0, 0x00, 0x1f, +0x58, 0xf7, 0x84, 0x04, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x46, 0xf0, 0x00, 0x45, 0x58, 0xf7, 0x85, 0x18, 0xdd, 0x2f, 0x80, 0xc0, 0xc8, 0x07, +0x84, 0x01, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x89, 0x14, 0xdd, 0x2f, 0x80, 0x06, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf0, 0x97, 0xa0, 0x81, 0x21, +0x54, 0xa1, 0x80, 0xff, 0x80, 0xe0, 0xe6, 0xcf, 0xe8, 0x22, 0x80, 0x3f, 0x84, 0x41, 0x46, 0xf0, +0x00, 0x52, 0x58, 0xf7, 0x80, 0x04, 0xdd, 0x2f, 0x44, 0x50, 0x00, 0xff, 0x81, 0x1f, 0xd0, 0x17, +0x80, 0x89, 0x80, 0x3f, 0x54, 0x63, 0x00, 0x0f, 0x84, 0x40, 0xd5, 0x06, 0x08, 0x02, 0x00, 0x01, +0x9c, 0x91, 0x38, 0x01, 0x98, 0x08, 0x96, 0x10, 0x98, 0xca, 0xe2, 0x0a, 0xe9, 0xf8, 0x80, 0x07, +0x46, 0xf0, 0x00, 0x52, 0x58, 0xf7, 0x81, 0x4c, 0xdd, 0x2f, 0xc0, 0x02, 0x84, 0x0c, 0xec, 0x10, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xa7, 0xc0, 0x80, 0x40, +0xa7, 0x02, 0xa6, 0x01, 0xe6, 0xf1, 0xe9, 0x03, 0x84, 0x0c, 0xd5, 0x2e, 0x40, 0x42, 0x20, 0x08, +0x40, 0x42, 0x00, 0x04, 0x50, 0x83, 0xff, 0xff, 0x89, 0x04, 0x44, 0x00, 0xff, 0xf0, 0x40, 0x92, +0x00, 0x02, 0x40, 0x84, 0x00, 0x02, 0x54, 0x42, 0x00, 0x0f, 0x4c, 0x94, 0x40, 0x04, 0x80, 0xc7, +0xd5, 0x04, 0x52, 0x62, 0x00, 0x10, 0x97, 0xb0, 0x51, 0xc1, 0x00, 0x03, 0x46, 0xa0, 0x00, 0xc5, +0x58, 0xa5, 0x04, 0xf8, 0x80, 0x09, 0x80, 0x3c, 0x84, 0x41, 0x80, 0x66, 0x4b, 0xe0, 0x28, 0x01, +0x4c, 0x94, 0x00, 0x0b, 0x9a, 0xfe, 0x40, 0x1e, 0x18, 0x00, 0x80, 0x08, 0x96, 0xd8, 0x84, 0x41, +0x84, 0x80, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x20, 0x44, 0x00, 0xfc, 0x6b, 0x46, 0xf0, 0x00, 0x0f, +0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x46, 0x60, 0x01, 0x38, 0x84, 0x61, 0x10, 0x33, 0x0a, 0x04, 0x46, 0xf0, 0x00, 0x3b, +0x58, 0xf7, 0x8e, 0xd4, 0xdd, 0x2f, 0x84, 0x20, 0x10, 0x13, 0x0a, 0x04, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x57, 0x81, 0x00, +0x80, 0xc2, 0x81, 0x24, 0x54, 0x80, 0x00, 0xff, 0x97, 0xc8, 0x54, 0xa1, 0x80, 0xff, 0xc5, 0x07, +0x46, 0xf0, 0x01, 0x0f, 0x01, 0xc7, 0x84, 0x11, 0x11, 0xc2, 0x80, 0xbe, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x07, 0x8a, 0x02, 0xc0, 0x37, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, 0x80, 0x26, +0x80, 0x07, 0xdd, 0x22, 0xc0, 0x2f, 0x80, 0x08, 0x80, 0x27, 0x80, 0x46, 0x80, 0x6a, 0x80, 0x89, +0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, 0x87, 0x70, 0xdd, 0x2f, 0x80, 0xa0, 0xc0, 0x17, 0x84, 0x01, +0xd8, 0x03, 0x84, 0x00, 0xd5, 0x29, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x84, 0x06, 0x84, 0x21, +0x4c, 0x00, 0x80, 0x23, 0x80, 0x25, 0x80, 0x1f, 0x84, 0x46, 0x80, 0xdf, 0xa7, 0xee, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xd5, 0x0d, 0x84, 0x05, 0x4c, 0x80, 0x40, 0x0b, +0x46, 0xf0, 0x01, 0x44, 0x00, 0x07, 0x87, 0x44, 0x56, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x01, +0xd5, 0x0b, 0x80, 0x08, 0x80, 0x27, 0x80, 0x46, 0x80, 0x6a, 0x80, 0x89, 0x46, 0xf0, 0x00, 0x38, +0x58, 0xf7, 0x80, 0x30, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x8a, 0x02, 0x80, 0xc0, 0xc1, 0x2c, +0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, 0x50, 0x73, 0x00, 0x08, 0xa6, 0x35, 0x80, 0x27, +0xdd, 0x22, 0xc0, 0x22, 0x80, 0x27, 0x84, 0x46, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, 0x84, 0x98, +0x80, 0x1f, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x01, 0x38, 0x04, 0x10, 0x02, 0x84, 0x84, 0x40, +0x81, 0x1f, 0x14, 0x20, 0x02, 0x84, 0xc1, 0x10, 0xa0, 0x8e, 0xc2, 0x0e, 0xb4, 0xbf, 0xb4, 0x62, +0xdb, 0x0b, 0x02, 0x5f, 0x80, 0x02, 0xa4, 0x12, 0xd8, 0x07, 0xa6, 0x0e, 0x84, 0x46, 0xae, 0x35, +0x80, 0x07, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x86, 0xac, +0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xc8, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x7d, 0x84, 0x00, 0xdd, 0x21, 0x50, 0x7f, 0x80, 0x34, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x81, 0x54, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, +0x88, 0xf0, 0xdd, 0x2f, 0xa6, 0xb8, 0x84, 0xa4, 0xd2, 0x04, 0x84, 0x00, 0x48, 0x00, 0x00, 0x8d, +0x50, 0x6f, 0x80, 0x08, 0xa6, 0x7b, 0xae, 0xb0, 0x50, 0x8f, 0x80, 0x0c, 0x80, 0x08, 0x46, 0xf0, +0x00, 0x3c, 0x58, 0xf7, 0x89, 0x78, 0xdd, 0x2f, 0xa6, 0xbb, 0xa7, 0x79, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x85, 0x3e, 0x9e, 0x96, 0xae, 0xb2, 0xaf, 0x71, 0xd8, 0x6c, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x37, 0x81, 0x55, 0xa6, 0x75, 0x9c, 0xde, 0x00, 0x93, 0x00, 0x06, 0x00, 0xa1, 0x80, 0x02, +0xa6, 0x99, 0x40, 0xa5, 0x40, 0x08, 0x40, 0x21, 0x20, 0x08, 0x40, 0x94, 0xc0, 0x08, 0x40, 0x10, +0xa0, 0x08, 0xa7, 0x58, 0xa7, 0x34, 0x88, 0x4a, 0x88, 0x29, 0x98, 0x95, 0x98, 0x4c, 0x4c, 0x20, +0xc0, 0x52, 0xa7, 0x5b, 0xa6, 0x77, 0xd9, 0x4e, 0xa6, 0x9d, 0x00, 0x13, 0x00, 0x09, 0xa7, 0x1c, +0x00, 0x33, 0x00, 0x08, 0x40, 0x21, 0x20, 0x08, 0x40, 0x10, 0xa0, 0x08, 0x98, 0x94, 0x98, 0x4b, +0x97, 0x51, 0x96, 0x49, 0xd9, 0x3f, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x8a, 0x02, 0xc1, 0x21, +0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, 0x80, 0x28, 0xdd, 0x22, 0xc0, 0x1a, 0x84, 0x60, +0xa6, 0x38, 0xa6, 0x71, 0x80, 0x83, 0x80, 0x48, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, 0x89, 0x68, +0xdd, 0x2f, 0x80, 0x60, 0xc0, 0x0e, 0x84, 0x01, 0x4c, 0x30, 0x00, 0x25, 0x80, 0x23, 0xa6, 0xde, +0x80, 0x08, 0xae, 0xf1, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x81, 0x54, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x8d, 0x34, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x81, 0x54, 0x50, 0x0f, 0x80, 0x04, 0x00, 0x10, +0x80, 0x24, 0xae, 0x47, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x81, 0x07, 0xdd, 0x21, 0x84, 0x01, +0xd5, 0x02, 0x84, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x81, 0x36, 0x9c, 0x91, 0x46, 0xf0, +0x01, 0x0f, 0x14, 0x27, 0x81, 0x36, 0x46, 0xf0, 0x00, 0x3f, 0x58, 0xf7, 0x89, 0x2c, 0xdd, 0x2f, +0xec, 0x38, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xb8, +0x50, 0x6f, 0x80, 0x40, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x81, 0x54, 0x80, 0x26, 0x46, 0xf0, +0x00, 0x3c, 0x58, 0xf7, 0x88, 0xf0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0xa6, 0xf0, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x74, 0xdd, 0x24, 0xa6, 0x30, 0x84, 0x21, +0x4c, 0x00, 0x80, 0x0b, 0xc0, 0x0e, 0x84, 0x82, 0x4c, 0x02, 0x00, 0x06, 0x84, 0x26, 0x4c, 0x00, +0xc1, 0xb3, 0xd5, 0x06, 0x84, 0x03, 0x10, 0x0f, 0x80, 0x04, 0x84, 0xe0, 0xd5, 0x05, 0x84, 0x02, +0x10, 0x0f, 0x80, 0x04, 0x84, 0xe1, 0x50, 0x6f, 0x80, 0x40, 0x50, 0x8f, 0x80, 0x08, 0xa6, 0x73, +0x80, 0x08, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x89, 0x78, 0xdd, 0x2f, 0x3a, 0x04, 0x04, 0x00, +0x50, 0x9f, 0x80, 0x38, 0xb6, 0x09, 0x12, 0x14, 0x80, 0x02, 0xa7, 0x33, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x27, 0x8a, 0x02, 0x00, 0x83, 0x00, 0x01, 0x3a, 0x04, 0x84, 0x00, 0x9f, 0x26, 0x50, 0xaf, +0x80, 0x30, 0x10, 0x4f, 0x80, 0x06, 0xb6, 0x0a, 0x12, 0x15, 0x00, 0x02, 0x10, 0x8f, 0x80, 0x05, +0xc2, 0x35, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, 0x80, 0x29, 0x80, 0x08, 0xdd, 0x22, +0xc0, 0x2d, 0xa6, 0xf2, 0xa6, 0x30, 0x80, 0x49, 0x80, 0x28, 0x50, 0x4f, 0x80, 0x0e, 0x46, 0xf0, +0x00, 0xcf, 0x58, 0xf7, 0x89, 0x68, 0xdd, 0x2f, 0x80, 0x60, 0xc0, 0x20, 0x84, 0x81, 0x4c, 0x02, +0x40, 0x14, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x80, 0x7d, 0x84, 0x00, 0xdd, 0x21, 0x84, 0x22, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, +0x81, 0x56, 0x48, 0x00, 0x01, 0x59, 0x80, 0x0a, 0x80, 0x23, 0x84, 0x46, 0xa7, 0x9e, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xd5, 0x02, 0x80, 0xc8, 0x50, 0x3f, 0x80, 0x40, +0xa6, 0x18, 0x84, 0x81, 0x50, 0x2f, 0x80, 0x30, 0x4c, 0x02, 0x40, 0x0b, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x57, 0x81, 0x0d, 0xa6, 0xda, 0x80, 0x26, 0x50, 0x4f, 0x80, 0x0e, 0xd5, 0x08, 0x84, 0x60, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x57, 0x81, 0x0d, 0x80, 0x83, 0x80, 0x26, 0xdd, 0x25, 0x80, 0xc0, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf8, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x61, 0x4c, 0x60, +0xc0, 0x5f, 0x00, 0x0f, 0x80, 0x40, 0xc0, 0x04, 0x84, 0x82, 0x4c, 0x02, 0x40, 0x40, 0x00, 0x2f, +0x80, 0x06, 0x84, 0x60, 0x50, 0x0f, 0x80, 0x47, 0x50, 0x1f, 0x80, 0x0e, 0x81, 0x3f, 0xae, 0xc0, +0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x87, 0xc8, 0xdd, 0x2f, 0xc0, 0x30, 0x46, 0x10, 0x01, 0x38, +0x00, 0x2f, 0x80, 0x47, 0x00, 0x00, 0x89, 0xfa, 0x4c, 0x01, 0x00, 0x1d, 0x84, 0x81, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x47, 0x89, 0xf8, 0x10, 0x20, 0x89, 0xfa, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x83, 0xfc, 0xdd, 0x2f, 0x84, 0x40, 0x84, 0x01, 0x46, 0x10, 0x00, 0xcc, 0x58, 0x10, +0x81, 0x28, 0x80, 0x62, 0x80, 0x82, 0x80, 0xa0, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x00, 0x3f, 0x80, 0x47, 0x84, 0x04, +0x84, 0x21, 0x44, 0x20, 0x30, 0xab, 0x48, 0x00, 0x00, 0xe6, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x97, +0x89, 0xf7, 0x84, 0x01, 0x4c, 0x90, 0x40, 0x14, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x82, 0xfc, +0xdd, 0x2f, 0xc8, 0x0d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x00, 0x3f, 0x80, 0x40, +0x80, 0x29, 0x84, 0x04, 0x44, 0x20, 0x30, 0xac, 0x48, 0x00, 0x00, 0xcd, 0x84, 0x21, 0x4c, 0x70, +0xc0, 0x68, 0x4c, 0x63, 0xc0, 0x66, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x85, 0x3c, 0xa6, 0x38, +0x4c, 0x03, 0x40, 0x5f, 0x02, 0xa3, 0x80, 0x04, 0x8f, 0x41, 0x40, 0xa5, 0x00, 0x13, 0x12, 0xa3, +0x80, 0x04, 0x4e, 0xa3, 0x00, 0x56, 0x46, 0x00, 0x04, 0x90, 0x04, 0x90, 0x00, 0x4f, 0x40, 0x94, +0x9c, 0x08, 0x93, 0x37, 0x46, 0xf0, 0x00, 0x45, 0x58, 0xf7, 0x83, 0x6c, 0xdd, 0x2f, 0xe2, 0x09, +0xe9, 0x03, 0x4e, 0x93, 0x00, 0x0d, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x81, 0x39, 0x84, 0x00, +0x9c, 0x91, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x27, 0x81, 0x39, 0xd5, 0x34, 0x46, 0xf0, 0x01, 0x0a, +0x00, 0x07, 0x8b, 0x7d, 0xc0, 0x03, 0x80, 0x0a, 0xd5, 0x2d, 0xa0, 0x3e, 0x84, 0x46, 0x10, 0x83, +0x80, 0x02, 0x98, 0x02, 0x50, 0x1f, 0x80, 0x38, 0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x58, +0xdd, 0x2f, 0xa0, 0x3d, 0x44, 0x10, 0x20, 0x00, 0x46, 0xf0, 0x00, 0x3d, 0x58, 0xf7, 0x81, 0x74, +0xdd, 0x2f, 0x84, 0x03, 0x44, 0x10, 0x20, 0x00, 0xa8, 0x3f, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, +0x82, 0xd2, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x8e, 0x14, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xd5, 0x80, 0x69, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x72, 0xdd, 0x24, +0x80, 0x06, 0x84, 0x41, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x27, 0x82, 0xa2, 0xc8, 0x1c, 0x46, 0xf0, +0x00, 0x3c, 0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x7d, +0x84, 0x00, 0xdd, 0x21, 0x84, 0x22, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x81, 0x56, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x44, 0x10, 0x02, 0x00, 0x84, 0x04, 0x44, 0x20, 0x30, 0x73, +0x80, 0x66, 0xdd, 0x24, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x82, 0xfc, 0xdd, 0x2f, 0xc0, 0x05, +0x84, 0x01, 0x4c, 0x60, 0x40, 0x03, 0xd5, 0x12, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x07, 0x8e, 0xc4, +0xc0, 0x05, 0x84, 0x21, 0x4c, 0x60, 0xc0, 0x03, 0xd5, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, +0x89, 0xf7, 0xc8, 0x1b, 0x84, 0x81, 0x4c, 0x62, 0x40, 0x19, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, +0x81, 0x54, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x8d, 0x34, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x17, 0x81, 0x54, 0x80, 0x1f, 0x00, 0x10, 0x80, 0x24, 0x10, 0x1f, 0x80, 0x07, 0x46, 0xf0, +0x01, 0x0f, 0x04, 0x17, 0x81, 0x09, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x81, 0x34, +0x44, 0x20, 0x30, 0x75, 0x9c, 0x49, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x81, 0x34, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x37, 0x81, 0x56, 0x84, 0x22, +0x84, 0x04, 0xdd, 0x24, 0xec, 0x48, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x05, 0x3c, 0x54, 0x90, 0x00, 0xff, +0xa0, 0x35, 0x44, 0x15, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x80, 0x64, 0xdd, 0x2f, +0x81, 0x00, 0xa0, 0x37, 0xc8, 0x23, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x07, 0x8e, 0xc6, 0x84, 0xa1, +0xd0, 0x07, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x82, 0xfc, 0xdd, 0x2f, 0xc0, 0x0c, 0x46, 0xf0, +0x01, 0x49, 0x04, 0x07, 0x83, 0xb6, 0x9c, 0x01, 0x42, 0x00, 0x7c, 0x09, 0x46, 0xf0, 0x01, 0x49, +0x14, 0x07, 0x83, 0xb6, 0x46, 0xf0, 0x00, 0x3f, 0x58, 0xf7, 0x8b, 0x40, 0xdd, 0x2f, 0x84, 0x22, +0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x81, 0x56, 0xd5, 0x0c, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0a, +0x84, 0x02, 0x46, 0x10, 0x20, 0x00, 0xa8, 0x37, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x82, 0xd4, +0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x05, 0x3c, 0xa1, 0xf7, 0x84, 0xa3, 0xd7, 0x68, 0xe6, 0xe4, +0xe8, 0x07, 0x84, 0xa1, 0xd7, 0x0c, 0x84, 0xa2, 0x4c, 0x72, 0xc0, 0x8f, 0xd5, 0x4c, 0x84, 0xa4, +0xd7, 0x7d, 0x84, 0xa5, 0x4c, 0x72, 0xc0, 0x89, 0x48, 0x00, 0x00, 0x93, 0x8c, 0xb2, 0x4c, 0x92, +0xc0, 0x0d, 0xa6, 0x30, 0x84, 0xa1, 0x4c, 0x02, 0xc0, 0x8c, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, +0x80, 0x07, 0xdd, 0x20, 0x48, 0x00, 0x00, 0x85, 0x9d, 0x6a, 0x4c, 0x92, 0xc0, 0x22, 0x46, 0xf0, +0x00, 0xc5, 0x58, 0xf7, 0x88, 0x9c, 0xdd, 0x2f, 0xa0, 0x37, 0x84, 0xa1, 0xd8, 0x79, 0x46, 0xf0, +0x00, 0x3c, 0x58, 0xf7, 0x85, 0x6c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x7d, +0x84, 0x00, 0xdd, 0x21, 0x84, 0x02, 0xa8, 0x37, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0xa6, 0xf0, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x76, 0xdd, 0x24, 0xd5, 0x61, 0xa0, 0x34, +0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x5a, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xd5, 0xa0, 0xf4, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x77, 0xdd, 0x24, +0x84, 0x05, 0xd5, 0x13, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0xa0, 0xf3, 0x44, 0x10, +0x02, 0x00, 0x44, 0x20, 0x30, 0x6f, 0x84, 0x04, 0xdd, 0x24, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x3f, +0x58, 0xf7, 0x88, 0xe4, 0xdd, 0x2f, 0x84, 0x01, 0xa8, 0x37, 0xd5, 0x3a, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xd5, 0xa4, 0xf5, 0x44, 0x20, 0x30, 0x70, 0x44, 0x10, 0x02, 0x00, 0x84, 0x04, +0xdd, 0x24, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x7d, 0x84, 0x01, 0xdd, 0x21, 0xa0, 0x35, +0x44, 0x10, 0x80, 0x00, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x3d, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, +0x84, 0x04, 0xa8, 0x37, 0x44, 0x10, 0x80, 0x00, 0xd5, 0x0a, 0x46, 0xf0, 0x00, 0xc5, 0x58, 0xf7, +0x87, 0x3c, 0xdd, 0x2f, 0x84, 0x02, 0xa8, 0x37, 0x44, 0x10, 0x10, 0x00, 0x46, 0xf0, 0x01, 0x0a, +0x14, 0x17, 0x82, 0xd2, 0xd5, 0x0d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xf7, 0x44, 0x00, +0x00, 0x3c, 0xdd, 0x21, 0x84, 0x26, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x81, 0x56, 0x46, 0xf0, +0x01, 0x0f, 0x04, 0x07, 0x81, 0x56, 0x84, 0xa5, 0xd8, 0x0e, 0x46, 0xf0, 0x00, 0x45, 0x58, 0xf7, +0x82, 0x34, 0xdd, 0x2f, 0x84, 0xa9, 0xd8, 0x07, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x3f, 0x58, 0xf7, +0x8a, 0x84, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0xbc, 0xef, 0xf8, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x57, 0x8a, 0x02, 0x80, 0xc2, 0x81, 0x04, +0x54, 0xa0, 0x00, 0xff, 0x97, 0xc8, 0x54, 0x91, 0x80, 0xff, 0xc5, 0x23, 0x46, 0xf0, 0x01, 0x4d, +0x04, 0x27, 0x80, 0xe1, 0x80, 0x26, 0x80, 0x07, 0xdd, 0x22, 0xc0, 0x1b, 0x80, 0x0a, 0x80, 0x27, +0x80, 0x46, 0x80, 0x69, 0x80, 0x88, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, 0x88, 0xb8, 0xdd, 0x2f, +0x80, 0xa0, 0xc0, 0x0f, 0x84, 0x01, 0xd8, 0x03, 0x84, 0x00, 0xd5, 0x15, 0x80, 0x25, 0x80, 0x1f, +0x84, 0x46, 0x80, 0xdf, 0xa7, 0xee, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, +0x80, 0x0a, 0x80, 0x27, 0x80, 0x46, 0x80, 0x69, 0x80, 0x88, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, +0x8f, 0x80, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0x80, 0x01, 0x38, 0x00, 0x74, 0x09, 0xf3, 0x84, 0xa2, 0xdf, 0x44, 0x46, 0x10, +0x01, 0x38, 0x58, 0x10, 0x8a, 0x50, 0x44, 0x00, 0x00, 0x55, 0x46, 0x60, 0x01, 0x38, 0x46, 0xf0, +0x00, 0xcb, 0x58, 0xf7, 0x81, 0xe0, 0xdd, 0x2f, 0x04, 0x03, 0x02, 0x39, 0x46, 0xf0, 0x00, 0xc8, +0x58, 0xf7, 0x8b, 0xc0, 0xdd, 0x2f, 0x00, 0x54, 0x09, 0xf3, 0xdf, 0x2d, 0x04, 0x03, 0x02, 0x39, +0xa6, 0x46, 0xe6, 0x22, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x04, 0x04, 0x00, 0x00, 0x17, 0xc8, 0xf9, +0x46, 0x60, 0x01, 0x0f, 0x04, 0x13, 0x01, 0x00, 0xc9, 0x18, 0xc0, 0x17, 0x46, 0xf0, 0x00, 0x38, +0x58, 0xf7, 0x82, 0xac, 0xdd, 0x2f, 0x14, 0x03, 0x01, 0x00, 0xc8, 0x08, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x83, 0xf7, 0x44, 0x00, 0x00, 0x1e, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, +0x81, 0x00, 0x84, 0x21, 0x10, 0x10, 0x00, 0xb5, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xe9, +0x84, 0x01, 0xdd, 0x21, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x17, 0x8a, 0x02, 0x81, 0x00, 0xc1, 0x7e, 0x46, 0x60, 0x01, 0x44, 0x58, 0x63, +0x07, 0x44, 0xa6, 0x30, 0x84, 0xa1, 0xd8, 0x41, 0x46, 0x70, 0x01, 0x13, 0x58, 0x73, 0x85, 0xb0, +0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x89, 0x2c, 0xdd, 0x2f, 0xb4, 0x27, 0x42, 0x10, 0xcc, 0x08, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x81, 0x00, 0xb6, 0x27, 0x80, 0x08, 0x14, 0x23, 0x00, 0x0b, +0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, 0x8e, 0x74, 0xdd, 0x2f, 0xb4, 0x07, 0x42, 0x00, 0x4c, 0x09, +0xb6, 0x07, 0x04, 0x13, 0x00, 0x0b, 0xa6, 0x31, 0x46, 0x70, 0x00, 0x5b, 0x58, 0x73, 0x86, 0x58, +0x10, 0x00, 0x80, 0xbf, 0x84, 0x46, 0x04, 0x03, 0x00, 0x0b, 0x9c, 0x72, 0x50, 0x00, 0x00, 0xc9, +0x4b, 0xe0, 0x1c, 0x01, 0x04, 0x03, 0x00, 0x0b, 0x9c, 0x72, 0x84, 0x46, 0x8c, 0x1c, 0x4b, 0xe0, +0x1c, 0x01, 0x04, 0x03, 0x00, 0x0b, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x84, 0xac, +0xdd, 0x2f, 0x84, 0x00, 0xae, 0x30, 0xd5, 0x4a, 0x84, 0xa2, 0xd8, 0x35, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x89, 0x2c, 0xdd, 0x2f, 0x46, 0x70, 0x01, 0x13, 0x58, 0x73, 0x85, 0xb0, 0x80, 0x28, +0x44, 0x20, 0x00, 0x22, 0x50, 0x03, 0x00, 0x08, 0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x58, +0xdd, 0x2f, 0xb4, 0x27, 0x42, 0x10, 0xcc, 0x08, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x81, 0x00, +0xb6, 0x27, 0x80, 0x08, 0x14, 0x23, 0x00, 0x0b, 0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, 0x8e, 0x74, +0xdd, 0x2f, 0xb4, 0x07, 0x42, 0x00, 0x4c, 0x09, 0xb6, 0x07, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, +0x80, 0xb1, 0x84, 0x20, 0x44, 0x00, 0x00, 0x49, 0x44, 0x20, 0xbd, 0xca, 0xdd, 0x23, 0x84, 0x00, +0xae, 0x30, 0xd5, 0x19, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x89, 0x2c, 0xdd, 0x2f, 0x46, 0x10, +0x01, 0x13, 0x04, 0x20, 0x81, 0x6c, 0x42, 0x21, 0x4c, 0x09, 0x14, 0x20, 0x81, 0x6c, 0x80, 0x08, +0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, 0x8e, 0x74, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xc5, 0x58, 0xf7, +0x8e, 0xd0, 0xdd, 0x2f, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x96, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x27, 0x81, 0x7a, 0xc0, 0x64, 0x54, 0x21, 0x00, 0x0f, +0xc2, 0x04, 0x84, 0xcc, 0x48, 0x00, 0x00, 0x99, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x04, 0x00, +0xb4, 0x06, 0xc8, 0x11, 0xa6, 0x36, 0xe6, 0x02, 0xe8, 0x0e, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, +0x82, 0xac, 0xdd, 0x2f, 0xb6, 0x06, 0xc8, 0x04, 0x84, 0xc7, 0x48, 0x00, 0x00, 0x86, 0x84, 0x21, +0x10, 0x10, 0x00, 0xb5, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x17, 0x89, 0xf3, 0x84, 0x01, 0x4c, 0x10, +0x40, 0x12, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x84, 0x06, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x37, +0x81, 0x7a, 0x40, 0x10, 0x88, 0x0c, 0x40, 0x10, 0x8c, 0x04, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x17, +0x81, 0x7a, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x84, 0x00, 0x84, 0x00, 0xa7, 0xbe, 0xae, 0x3c, +0x84, 0x01, 0x4c, 0x60, 0x40, 0x0f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0x00, 0x44, 0x10, +0x10, 0x00, 0x84, 0x06, 0xdd, 0x22, 0xc8, 0x05, 0x10, 0x63, 0x80, 0x13, 0x80, 0xc0, 0xd5, 0x54, +0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x04, 0x00, 0x84, 0xe0, 0x84, 0x20, 0xb4, 0x66, 0x10, 0x73, +0x00, 0x13, 0x84, 0x02, 0x46, 0x20, 0x00, 0x3b, 0x58, 0x21, 0x01, 0x90, 0x84, 0x81, 0x80, 0xa1, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x10, 0x03, 0x00, 0x10, 0x84, 0xc0, +0xd5, 0x3b, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf3, 0xc8, 0x10, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x84, 0x06, 0x84, 0x61, 0x40, 0x01, 0x80, 0x0c, 0x40, 0x00, 0x00, 0x05, 0x40, 0x20, +0x08, 0x02, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x27, 0x81, 0x7a, 0x84, 0x02, 0x46, 0x70, 0x01, 0x0f, +0x58, 0x73, 0x84, 0x00, 0xae, 0x3c, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xf1, 0xdd, 0x20, +0x80, 0xc0, 0xc0, 0x09, 0x84, 0x20, 0xae, 0x7c, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, +0x8f, 0xd8, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x84, 0x13, 0xc1, 0x0d, 0x84, 0x20, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x17, 0x84, 0x13, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0x01, +0x84, 0x20, 0x84, 0x06, 0xdd, 0x22, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, 0x89, 0xf4, +0x97, 0x80, 0x80, 0xe1, 0xc2, 0x07, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x50, 0x80, 0x06, +0xdd, 0x22, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, 0x0a, 0x06, 0xc1, 0x16, 0x84, 0x20, 0x10, 0x10, +0x0a, 0x06, 0x84, 0x05, 0x4c, 0x60, 0x40, 0x11, 0x84, 0x40, 0x84, 0x01, 0x46, 0x10, 0x00, 0xc8, +0x58, 0x10, 0x8d, 0x24, 0x80, 0x62, 0x80, 0x82, 0x80, 0xa0, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x87, 0xb0, 0xdd, 0x2f, 0xd5, 0x69, 0x44, 0x10, 0x00, 0x10, 0x4c, 0x60, 0xc0, 0x08, 0x00, 0x03, +0x80, 0x09, 0x94, 0x89, 0x4c, 0x01, 0x40, 0x59, 0xd5, 0x5f, 0x84, 0x0d, 0x4c, 0x60, 0x40, 0x18, +0x46, 0x10, 0x01, 0x38, 0x00, 0x00, 0x89, 0xe5, 0x84, 0x41, 0x4c, 0x01, 0x40, 0x4e, 0x85, 0x20, +0x46, 0x80, 0x01, 0x38, 0x10, 0x90, 0x89, 0xe5, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0xe4, +0x00, 0x14, 0x09, 0xe6, 0xdd, 0x22, 0x10, 0x94, 0x09, 0xe6, 0xd5, 0x3e, 0x84, 0x05, 0x4c, 0x60, +0x40, 0x3c, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x5b, 0x00, 0x87, 0x88, 0x0d, 0x46, 0xf0, 0x00, 0x0d, +0x58, 0xf7, 0x81, 0xb4, 0xdd, 0x2f, 0xc0, 0x38, 0x84, 0x20, 0x84, 0x01, 0x50, 0x24, 0x00, 0x02, +0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0x80, 0x20, 0xc8, 0x03, 0x84, 0x07, +0xd5, 0x2c, 0xb4, 0x40, 0xca, 0x04, 0x44, 0x00, 0x00, 0x1f, 0xd5, 0x27, 0xaf, 0x90, 0x10, 0x81, +0x00, 0x01, 0x4e, 0x82, 0x00, 0x04, 0xa6, 0x38, 0xae, 0x12, 0x00, 0x03, 0x80, 0x0c, 0xae, 0x13, +0xa4, 0x3e, 0x92, 0x08, 0xae, 0x14, 0x84, 0x01, 0x00, 0x73, 0x80, 0x18, 0xaf, 0xd5, 0x46, 0x20, +0x00, 0xbc, 0x58, 0x21, 0x09, 0x08, 0xa8, 0x89, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, +0x87, 0x80, 0xdd, 0x2f, 0xd5, 0x09, 0x80, 0x06, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, +0x87, 0x20, 0xdd, 0x2f, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x81, 0xdd, 0x97, 0x80, +0x44, 0x00, 0x00, 0x30, 0x42, 0x13, 0x00, 0x73, 0x04, 0x00, 0x80, 0x0a, 0x84, 0x20, 0x10, 0x10, +0x00, 0x37, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x07, 0x8e, 0x34, 0x96, 0x04, 0xc0, 0x10, 0x46, 0x70, +0x01, 0x38, 0x02, 0x83, 0x84, 0xea, 0x44, 0x00, 0x00, 0x2c, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x82, 0x4c, 0xdd, 0x2f, 0x88, 0x08, 0x12, 0x03, 0x84, 0xea, 0x80, 0x06, 0x46, 0xf0, +0x00, 0x37, 0x58, 0xf7, 0x82, 0x70, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, +0x8a, 0x8c, 0xdd, 0x2f, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x44, 0x50, 0x00, 0x44, 0xd8, 0x31, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x82, 0xfc, 0xdd, 0x2f, +0xc0, 0x07, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x81, 0x60, 0xdd, 0x2f, 0xd5, 0x43, 0x46, 0xf0, +0x01, 0x49, 0x00, 0x17, 0x8e, 0xc4, 0xc1, 0x0e, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x07, 0x8e, 0xc6, +0x84, 0xa1, 0xd8, 0x08, 0x46, 0xf0, 0x00, 0xd2, 0x04, 0x07, 0x80, 0x99, 0x04, 0x00, 0x00, 0x08, +0xd5, 0x2a, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0x59, 0xdd, 0x20, 0xc0, 0x06, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x09, 0x84, 0xd5, 0x05, 0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x0f, 0x94, +0xb4, 0x00, 0xdd, 0x20, 0xd5, 0x1f, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, 0x8a, 0x02, 0xc2, 0x15, +0x9d, 0x6d, 0xd8, 0x13, 0x44, 0x50, 0xab, 0xcd, 0xd1, 0x05, 0x44, 0x50, 0xbd, 0xca, 0xd9, 0x0d, +0xd5, 0x06, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x07, 0x80, 0xe2, 0xd5, 0x05, 0x46, 0xf0, 0x01, 0x4d, +0x04, 0x07, 0x80, 0xe3, 0xdd, 0x20, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x88, 0xe8, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0x51, 0x42, 0x10, 0xc4, 0x09, 0x14, 0x10, 0x00, 0x51, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x80, 0x51, 0x84, 0x02, 0x84, 0x21, 0xdd, 0x22, 0x84, 0x60, 0x46, 0xf0, +0x01, 0x03, 0x00, 0x17, 0x8d, 0xfc, 0x46, 0xf0, 0x01, 0x03, 0x10, 0x37, 0x8d, 0xfd, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x84, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8b, 0xa4, +0xdd, 0x2f, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, +0x84, 0xdf, 0x44, 0x00, 0x01, 0x33, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0xaf, 0x88, 0x46, 0xf0, +0x00, 0x52, 0x58, 0xf7, 0x82, 0x9c, 0xdd, 0x2f, 0xc0, 0x04, 0x44, 0x00, 0x00, 0xff, 0xd5, 0x08, +0x00, 0x0f, 0x80, 0x07, 0xc8, 0x03, 0x10, 0x6f, 0x80, 0x07, 0x00, 0x0f, 0x80, 0x07, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x46, 0xf0, 0x00, 0xc6, +0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x80, 0x20, 0x44, 0x50, 0x00, 0xff, 0xd1, 0x0e, 0xa6, 0x35, +0x8e, 0x10, 0x96, 0x00, 0x5c, 0x20, 0x00, 0xef, 0x40, 0x00, 0x88, 0x1a, 0x46, 0xf0, 0x00, 0xbc, +0x58, 0xf7, 0x86, 0xc8, 0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x58, 0xf7, +0x8c, 0x60, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x96, 0x00, +0x80, 0xc1, 0x98, 0x48, 0x00, 0x50, 0xff, 0xff, 0xd0, 0x03, 0x84, 0x01, 0xd5, 0x24, 0x9c, 0x32, +0x46, 0xf0, 0x00, 0x0e, 0x58, 0xf7, 0x8d, 0x08, 0xdd, 0x2f, 0x50, 0x03, 0x00, 0x08, 0x46, 0xf0, +0x00, 0xc6, 0x58, 0xf7, 0x84, 0xf8, 0xdd, 0x2f, 0x50, 0x03, 0x00, 0x0e, 0x46, 0xf0, 0x00, 0x0e, +0x58, 0xf7, 0x8c, 0xa0, 0xdd, 0x2f, 0x50, 0x03, 0x00, 0x11, 0x46, 0xf0, 0x00, 0x0e, 0x58, 0xf7, +0x8c, 0xc0, 0xdd, 0x2f, 0x50, 0x03, 0x00, 0x27, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x89, 0x5c, +0xdd, 0x2f, 0x84, 0x00, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x00, 0xc6, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, +0x86, 0xc8, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x3a, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x46, 0xf0, +0x00, 0x52, 0x58, 0xf7, 0x82, 0x9c, 0xdd, 0x2f, 0x00, 0x0f, 0x80, 0x07, 0x96, 0x42, 0x4e, 0x15, +0x00, 0x16, 0x46, 0x40, 0x04, 0x00, 0x46, 0x10, 0x00, 0xa0, 0x80, 0x64, 0x80, 0x43, 0x9f, 0x41, +0x58, 0x10, 0x8a, 0x3f, 0x97, 0x68, 0x14, 0x12, 0x00, 0x41, 0x14, 0x11, 0x80, 0x42, 0x14, 0x11, +0x00, 0x43, 0x5c, 0xf2, 0x80, 0xfe, 0xe8, 0x53, 0xd5, 0x23, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, +0x80, 0x19, 0x42, 0x10, 0xf4, 0x0b, 0x9f, 0xc1, 0xc1, 0x26, 0x46, 0x50, 0x04, 0x00, 0x46, 0x60, +0x00, 0x80, 0x80, 0x65, 0x46, 0x40, 0x00, 0x90, 0x80, 0x43, 0x46, 0x10, 0x00, 0xa1, 0x58, 0x63, +0x00, 0x0f, 0x58, 0x42, 0x0a, 0x1e, 0x58, 0x10, 0x8e, 0x7f, 0x97, 0xf8, 0x14, 0x62, 0x80, 0x41, +0x14, 0x41, 0x80, 0x42, 0x14, 0x11, 0x00, 0x43, 0x5c, 0xf3, 0x80, 0xfe, 0xe8, 0x30, 0x54, 0x10, +0x00, 0x7f, 0x46, 0x00, 0x00, 0xb8, 0x40, 0x10, 0xa0, 0x08, 0x58, 0x00, 0x00, 0x7f, 0x40, 0x10, +0x80, 0x04, 0xd5, 0x25, 0x46, 0x50, 0x04, 0x00, 0x46, 0x60, 0x00, 0x80, 0x80, 0x65, 0x46, 0x40, +0x00, 0x90, 0x80, 0x43, 0x46, 0x10, 0x00, 0xa1, 0x58, 0x63, 0x00, 0x1e, 0x58, 0x42, 0x0a, 0x3c, +0x58, 0x10, 0x8e, 0x7f, 0x97, 0xf8, 0x14, 0x62, 0x80, 0x41, 0x14, 0x41, 0x80, 0x42, 0x14, 0x11, +0x00, 0x43, 0x5c, 0xf3, 0x80, 0xfe, 0xe8, 0x0b, 0x54, 0x10, 0x00, 0x7f, 0x46, 0x20, 0x00, 0xb8, +0x40, 0x10, 0xa0, 0x08, 0x58, 0x21, 0x00, 0xe0, 0x40, 0x10, 0x88, 0x04, 0x46, 0x20, 0x04, 0x00, +0x14, 0x11, 0x00, 0x44, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xf4, 0x44, 0x00, 0x00, 0x3a, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x46, 0xf0, +0x00, 0x52, 0x58, 0xf7, 0x82, 0x9c, 0xdd, 0x2f, 0x20, 0x0f, 0x80, 0x07, 0x4e, 0x05, 0x00, 0x12, +0x46, 0x40, 0x04, 0x00, 0x80, 0x64, 0x80, 0x43, 0x80, 0x22, 0x44, 0x06, 0x0a, 0x3f, 0x14, 0x02, +0x00, 0x41, 0x14, 0x01, 0x80, 0x42, 0x14, 0x01, 0x00, 0x43, 0x14, 0x00, 0x80, 0x44, 0xd5, 0x36, +0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x19, 0x42, 0x00, 0x74, 0x0b, 0xc0, 0x18, 0x46, 0x30, +0x04, 0x00, 0x80, 0x43, 0x44, 0x46, 0x9e, 0x3f, 0x14, 0x41, 0x80, 0x41, 0x80, 0x22, 0x44, 0x35, +0x94, 0x2f, 0x14, 0x31, 0x00, 0x42, 0x46, 0x00, 0x04, 0x00, 0x44, 0x24, 0x8a, 0x0f, 0x14, 0x20, +0x80, 0x43, 0x58, 0x00, 0x01, 0x10, 0x44, 0x14, 0x00, 0x07, 0xd5, 0x17, 0x46, 0x30, 0x04, 0x00, +0x80, 0x43, 0x44, 0x46, 0x9e, 0xe0, 0x14, 0x41, 0x80, 0x41, 0x80, 0x22, 0x44, 0x35, 0x94, 0x7f, +0x14, 0x31, 0x00, 0x42, 0x46, 0x00, 0x04, 0x00, 0x44, 0x24, 0x8a, 0x3f, 0x14, 0x20, 0x80, 0x43, +0x58, 0x00, 0x01, 0x10, 0x44, 0x14, 0x00, 0x0f, 0xb6, 0x20, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x01, 0x01, 0x58, 0x63, 0x01, 0x88, +0xb4, 0x46, 0x44, 0x00, 0x80, 0xe0, 0x84, 0x21, 0xdd, 0x22, 0xb4, 0x46, 0x44, 0x00, 0x87, 0xff, +0x84, 0x21, 0xdd, 0x22, 0xb4, 0x46, 0x44, 0x00, 0x88, 0xdc, 0x84, 0x21, 0xdd, 0x22, 0x46, 0x70, +0x04, 0xb0, 0xb4, 0x46, 0x58, 0x73, 0x80, 0x80, 0x84, 0x21, 0x44, 0x00, 0xeb, 0x00, 0xdd, 0x22, +0xb4, 0x27, 0x44, 0x2f, 0xff, 0xe7, 0x40, 0x10, 0x88, 0x02, 0xb6, 0x27, 0x46, 0x00, 0x04, 0xa0, +0x04, 0x10, 0x01, 0x40, 0x42, 0x10, 0xdc, 0x09, 0x14, 0x10, 0x01, 0x40, 0x46, 0x80, 0x04, 0xa0, +0x58, 0x84, 0x00, 0x1c, 0xb4, 0x28, 0x84, 0x03, 0x58, 0x10, 0x81, 0x00, 0xb6, 0x28, 0x46, 0xa0, +0x04, 0xb0, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x89, 0x14, 0xdd, 0x2f, 0xb4, 0x28, 0x42, 0x10, +0xa0, 0x09, 0xb6, 0x28, 0x46, 0x00, 0x04, 0xb0, 0x05, 0xe0, 0x00, 0x38, 0x41, 0xef, 0x08, 0x09, +0x41, 0xef, 0x08, 0x08, 0x47, 0xc0, 0x04, 0x20, 0x59, 0xef, 0x00, 0x01, 0x81, 0x20, 0x80, 0xa0, +0x46, 0x80, 0x09, 0xe0, 0x80, 0x60, 0x46, 0x4a, 0x68, 0x34, 0x80, 0x20, 0x59, 0xce, 0x00, 0x63, +0x15, 0xe0, 0x00, 0x38, 0x15, 0xc5, 0x00, 0x04, 0x58, 0x84, 0x00, 0x80, 0x58, 0x42, 0x03, 0x70, +0x50, 0x22, 0x2d, 0x13, 0x44, 0xa0, 0x00, 0x25, 0x14, 0xa4, 0x80, 0x05, 0x14, 0x82, 0x80, 0x51, +0xa9, 0x1e, 0x14, 0x20, 0x80, 0x52, 0x80, 0x20, 0x04, 0x80, 0x80, 0x5a, 0x93, 0x08, 0x40, 0x84, +0x20, 0x08, 0x80, 0x80, 0x46, 0x59, 0x17, 0x33, 0x80, 0x40, 0x58, 0x52, 0x83, 0x60, 0x50, 0x32, +0xac, 0xd3, 0x58, 0x84, 0x00, 0xc9, 0x14, 0x80, 0x80, 0x5a, 0xa9, 0x67, 0x46, 0x10, 0x04, 0xb0, +0x14, 0x31, 0x00, 0x5b, 0x58, 0x10, 0x81, 0x84, 0xb4, 0x61, 0x92, 0x68, 0x40, 0x31, 0xa0, 0x08, +0x58, 0x31, 0x80, 0xc9, 0xb6, 0x61, 0x46, 0x4f, 0xf0, 0x0f, 0xb4, 0x61, 0x58, 0x42, 0x0f, 0xff, +0x40, 0x31, 0x90, 0x02, 0x46, 0x40, 0x0b, 0x50, 0x40, 0x31, 0x90, 0x04, 0x80, 0x40, 0xb6, 0x61, +0x84, 0x20, 0x14, 0x11, 0x00, 0x58, 0x80, 0x20, 0x04, 0x30, 0x80, 0x5e, 0x46, 0x4f, 0xf8, 0x0f, +0x58, 0x42, 0x0f, 0xff, 0x40, 0x31, 0x90, 0x02, 0x46, 0x40, 0x04, 0x60, 0x40, 0x31, 0x90, 0x04, +0x14, 0x30, 0x80, 0x5e, 0x80, 0x40, 0x04, 0x30, 0x00, 0x38, 0x42, 0x31, 0xc0, 0x08, 0x14, 0x30, +0x00, 0x38, 0x46, 0x4f, 0xff, 0x0f, 0x04, 0x31, 0x00, 0x41, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x31, +0x90, 0x02, 0x44, 0x46, 0x00, 0x00, 0x40, 0x31, 0x90, 0x04, 0x14, 0x31, 0x00, 0x41, 0x80, 0x20, +0xb4, 0x41, 0x46, 0x00, 0x04, 0xb0, 0x58, 0x21, 0x00, 0x08, 0xb6, 0x41, 0xb4, 0x27, 0x58, 0x00, +0x00, 0x04, 0x42, 0x10, 0x9c, 0x09, 0xb6, 0x27, 0xb4, 0x20, 0x42, 0x10, 0xa8, 0x09, 0xb6, 0x20, +0xb4, 0x20, 0x42, 0x10, 0xac, 0x09, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x04, 0xb6, 0x20, +0x46, 0xf0, 0x00, 0x4a, 0x58, 0xf7, 0x80, 0x40, 0xdd, 0x2f, 0x80, 0xe0, 0xe6, 0x08, 0xe8, 0x39, +0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x09, 0x30, 0x38, 0x00, 0x1c, 0x00, 0xb4, 0x46, 0x44, 0x10, +0xec, 0x00, 0x40, 0x00, 0x04, 0x04, 0x84, 0x21, 0xdd, 0x22, 0x46, 0x00, 0x01, 0x00, 0x58, 0x00, +0x09, 0x40, 0x38, 0x00, 0x1c, 0x00, 0x44, 0x30, 0xed, 0x00, 0xb4, 0x46, 0x40, 0x00, 0x0c, 0x04, +0x84, 0x21, 0xdd, 0x22, 0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x09, 0x28, 0x38, 0x10, 0x1c, 0x00, +0x46, 0x00, 0x04, 0xb0, 0x40, 0x20, 0xa0, 0x08, 0x40, 0x11, 0x04, 0x04, 0x46, 0x47, 0xf7, 0xf0, +0x04, 0x20, 0x00, 0x6c, 0x46, 0x38, 0x08, 0x0f, 0x40, 0x10, 0xc0, 0x08, 0x58, 0x31, 0x8f, 0xff, +0x40, 0x10, 0x90, 0x02, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0x6c, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x8c, +0xa6, 0x82, 0x97, 0x89, 0x50, 0x8f, 0x80, 0x1c, 0x12, 0x64, 0x00, 0x00, 0x9c, 0x53, 0x84, 0x60, +0x44, 0x20, 0xff, 0xfe, 0x80, 0xe0, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x8a, 0xf0, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x49, 0x00, 0x17, 0x8e, 0xc4, 0x50, 0x93, 0x80, 0x03, 0xc1, 0x10, 0x46, 0xf0, +0x01, 0x49, 0x00, 0x07, 0x8e, 0xc6, 0xc0, 0x0b, 0x50, 0x03, 0x5f, 0xf5, 0x96, 0x01, 0xe6, 0x02, +0xe8, 0x1b, 0x84, 0x2c, 0x80, 0x08, 0x14, 0x14, 0x00, 0x04, 0xd5, 0x2a, 0x44, 0x50, 0x20, 0x0c, +0xde, 0x13, 0x00, 0x04, 0x80, 0x00, 0x4e, 0x03, 0x01, 0x04, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, +0x82, 0xfc, 0xdd, 0x2f, 0x4e, 0x02, 0x00, 0xfd, 0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x87, 0x0c, +0xdd, 0x2f, 0x48, 0x00, 0x00, 0xf6, 0x44, 0x50, 0x20, 0x0d, 0xd6, 0x24, 0x8c, 0xb2, 0x4c, 0x62, +0x80, 0xaa, 0x8e, 0xb5, 0x4c, 0x62, 0xc0, 0xed, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, 0x09, 0xf3, +0x84, 0xa2, 0xd9, 0x0d, 0x50, 0x1f, 0x80, 0x1c, 0x84, 0x4c, 0xa8, 0x8c, 0x80, 0x01, 0x46, 0xf0, +0x00, 0x0d, 0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0xe3, 0x00, 0x14, 0x80, 0x00, +0x84, 0xa1, 0xd9, 0x02, 0xd5, 0x03, 0x4e, 0x13, 0x00, 0xd4, 0x10, 0x10, 0x09, 0xf3, 0x48, 0x00, +0x00, 0xd0, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x02, 0xec, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, +0x00, 0x0f, 0x98, 0x51, 0x44, 0x50, 0x00, 0x20, 0xd9, 0x03, 0x84, 0x09, 0xd5, 0x73, 0xa4, 0x04, +0x54, 0x00, 0x00, 0x40, 0xc0, 0x03, 0x84, 0x0c, 0xd5, 0x6d, 0x00, 0x74, 0x80, 0x17, 0x00, 0x14, +0x80, 0x03, 0x00, 0x04, 0x80, 0x01, 0x00, 0x64, 0x80, 0x0e, 0x01, 0xe4, 0x80, 0x10, 0x00, 0x54, +0x80, 0x12, 0x00, 0x44, 0x80, 0x14, 0x00, 0x34, 0x80, 0x16, 0x00, 0x24, 0x80, 0x18, 0xf7, 0x85, +0x40, 0x00, 0x20, 0x08, 0x00, 0xa4, 0x80, 0x0f, 0x00, 0x74, 0x80, 0x02, 0x01, 0xc4, 0x80, 0x00, +0x00, 0x84, 0x80, 0x0d, 0x14, 0xaf, 0x80, 0x01, 0x41, 0xc0, 0x70, 0x00, 0x00, 0xa4, 0x80, 0x11, +0xf0, 0x01, 0x14, 0xaf, 0x80, 0x02, 0x41, 0xef, 0x20, 0x08, 0x00, 0xa4, 0x80, 0x13, 0x40, 0x52, +0xa0, 0x08, 0x14, 0xaf, 0x80, 0x03, 0x40, 0x42, 0x20, 0x08, 0x00, 0xa4, 0x80, 0x15, 0x40, 0x31, +0xa0, 0x08, 0x14, 0xaf, 0x80, 0x04, 0x40, 0xa0, 0xa0, 0x08, 0x89, 0x47, 0x40, 0x7f, 0x00, 0x00, +0xf0, 0x02, 0x40, 0x63, 0x20, 0x08, 0x99, 0x68, 0xf0, 0x03, 0x40, 0x21, 0x20, 0x08, 0x99, 0x20, +0xf0, 0x04, 0x50, 0x1f, 0x80, 0x50, 0x98, 0xd8, 0xf0, 0x05, 0x89, 0x06, 0x98, 0x90, 0x50, 0x64, +0x80, 0x06, 0xad, 0xcb, 0x13, 0xc0, 0x80, 0x02, 0x12, 0xa0, 0x80, 0x05, 0xb6, 0xc1, 0x12, 0x80, +0x80, 0x04, 0xad, 0x4e, 0xad, 0x0f, 0x12, 0x30, 0x80, 0x09, 0x12, 0x20, 0x80, 0x08, 0x80, 0x01, +0x00, 0x24, 0x80, 0x04, 0x10, 0x20, 0x80, 0x18, 0x00, 0x74, 0x80, 0x05, 0x10, 0x70, 0x80, 0x16, +0x00, 0x94, 0x80, 0x0c, 0x10, 0x90, 0x80, 0x15, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x8c, 0xd8, +0xdd, 0x2f, 0x44, 0x10, 0x20, 0x0d, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, +0xd5, 0x4f, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x67, 0x81, 0x7a, 0x54, 0x63, 0x02, 0x00, 0xce, 0x31, +0x84, 0x01, 0x80, 0x26, 0x84, 0x4c, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, +0xc0, 0x3f, 0xb4, 0x40, 0x84, 0x2e, 0xae, 0x50, 0x84, 0x2a, 0xb4, 0x40, 0xae, 0x51, 0x84, 0x21, +0xb4, 0x40, 0xae, 0x52, 0x44, 0x20, 0x00, 0x1f, 0xb4, 0x60, 0x80, 0x26, 0xae, 0x9b, 0x9c, 0x91, +0xb4, 0x60, 0xae, 0x9c, 0xb4, 0x40, 0xaf, 0x95, 0xb4, 0x40, 0xaf, 0x96, 0xb4, 0x40, 0xaf, 0x97, +0xb4, 0x00, 0x8c, 0x08, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x80, 0x48, 0xdd, 0x2f, 0x84, 0x01, +0x80, 0x26, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0x80, 0x06, 0xd5, 0x19, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xf3, 0xdd, 0x20, 0xc0, 0x12, 0x84, 0x00, 0x80, 0x20, +0x80, 0x40, 0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, 0x8b, 0xa8, 0xdd, 0x2f, 0xd5, 0x09, 0x80, 0x07, +0x80, 0x26, 0x46, 0xf0, 0x00, 0x0b, 0x58, 0xf7, 0x8d, 0xf0, 0xdd, 0x2f, 0xd5, 0x02, 0x84, 0x00, +0xec, 0x74, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xc4, +0x50, 0x90, 0x00, 0x02, 0x00, 0x34, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x47, 0x84, 0xee, +0x96, 0x49, 0x80, 0xc0, 0x81, 0x1f, 0x12, 0x1f, 0x80, 0x00, 0x80, 0x43, 0x9d, 0xc3, 0x4c, 0x40, +0xc0, 0x0b, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4b, 0x80, 0x27, 0x80, 0x02, 0xdd, 0x23, +0x48, 0x00, 0x00, 0x87, 0x44, 0x40, 0xfc, 0xee, 0x4c, 0x12, 0x01, 0x37, 0xe2, 0x81, 0xe9, 0x27, +0x44, 0x20, 0xfc, 0x79, 0x4c, 0x11, 0x00, 0x63, 0xe2, 0x41, 0xe9, 0x0e, 0x44, 0x30, 0xfc, 0x4d, +0x4c, 0x11, 0x80, 0x4f, 0x44, 0x40, 0xfc, 0x6b, 0x4c, 0x12, 0x00, 0x52, 0x9e, 0x19, 0x4c, 0x10, +0x41, 0xc6, 0x48, 0x00, 0x01, 0x4a, 0x44, 0x20, 0xfc, 0xc3, 0x4c, 0x11, 0x00, 0x2f, 0xe2, 0x41, +0xe9, 0x06, 0x44, 0x30, 0xfc, 0xb9, 0x4c, 0x11, 0xc1, 0xba, 0xd5, 0x5d, 0x9d, 0x12, 0x4c, 0x12, +0x00, 0x54, 0x9c, 0x16, 0x4c, 0x10, 0x41, 0xb3, 0x48, 0x00, 0x00, 0x9a, 0x44, 0x30, 0xfd, 0x54, +0x4c, 0x11, 0x80, 0x5a, 0xe2, 0x61, 0xe9, 0x0c, 0x8c, 0x92, 0x4c, 0x12, 0x00, 0xe1, 0x9e, 0x19, +0x4c, 0x10, 0x00, 0x82, 0x44, 0x20, 0xfc, 0xf3, 0x4c, 0x11, 0x41, 0xa1, 0xd5, 0x36, 0x44, 0x30, +0xfd, 0x56, 0x4c, 0x11, 0x80, 0x62, 0xe2, 0x23, 0xe9, 0x56, 0x9d, 0x19, 0x4c, 0x12, 0x00, 0x65, +0x9c, 0x1b, 0x4c, 0x10, 0x41, 0x94, 0xd5, 0x6f, 0xa6, 0x38, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x04, +0x80, 0x01, 0xd5, 0x09, 0x9e, 0x19, 0x96, 0x00, 0x9c, 0x74, 0x46, 0xf0, 0x00, 0xc6, 0x58, 0xf7, +0x85, 0x3c, 0xdd, 0x2f, 0x80, 0x20, 0x44, 0x00, 0xfc, 0xc3, 0x48, 0x00, 0x01, 0x79, 0x80, 0x07, +0x46, 0xf0, 0x00, 0xc2, 0x58, 0xf7, 0x84, 0x30, 0xdd, 0x2f, 0xd5, 0x22, 0x80, 0x07, 0x46, 0xf0, +0x00, 0xc5, 0x58, 0xf7, 0x85, 0x58, 0xdd, 0x2f, 0xd5, 0x1b, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc3, +0x58, 0xf7, 0x83, 0x34, 0xdd, 0x2f, 0xd5, 0x14, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, +0x81, 0x88, 0xdd, 0x2f, 0xd5, 0x0d, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc3, 0x58, 0xf7, 0x83, 0xf8, +0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x83, 0x78, 0xdd, 0x2f, 0x84, 0x00, +0x48, 0x00, 0x01, 0x5b, 0xa6, 0xb8, 0x9c, 0x44, 0x80, 0x02, 0x10, 0x2f, 0x80, 0x37, 0x46, 0xf0, +0x00, 0xd1, 0x58, 0xf7, 0x87, 0x48, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x37, 0xf0, 0x84, 0xf1, 0x83, +0x80, 0x1f, 0xd5, 0x1b, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x85, 0xa6, 0x78, 0x80, 0x02, +0x9c, 0xb4, 0xdd, 0x23, 0xd5, 0xe5, 0xa6, 0x38, 0x9c, 0x74, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, +0x8a, 0xbc, 0xdd, 0x2f, 0xd5, 0xdd, 0xa6, 0x38, 0x9c, 0x74, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, +0x82, 0x04, 0xdd, 0x2f, 0xf0, 0x84, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x89, 0x44, +0xdd, 0x2f, 0xd5, 0xce, 0x84, 0xc0, 0x14, 0x64, 0x00, 0x04, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0xd1, +0x58, 0xf7, 0x89, 0x44, 0xdd, 0x2f, 0x80, 0x06, 0x48, 0x00, 0x01, 0x1f, 0xa6, 0x34, 0x84, 0x4e, +0x4c, 0x01, 0x40, 0x46, 0x50, 0x83, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x98, 0x4a, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x17, 0x88, 0x98, 0x84, 0x00, 0xd5, 0x05, 0xa6, 0x97, 0x96, 0x20, 0x10, 0x21, +0x80, 0x0f, 0x00, 0x14, 0x00, 0x00, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x08, 0x98, 0x98, 0xc2, +0x9d, 0x01, 0x98, 0xb0, 0xe2, 0x01, 0xe9, 0xf2, 0xa6, 0x35, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, +0x80, 0xa8, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x03, 0xc0, 0x44, 0x10, 0x04, 0x20, +0xac, 0x40, 0x44, 0x10, 0x00, 0x32, 0xac, 0x41, 0x00, 0x24, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, +0x9a, 0x91, 0xe4, 0x45, 0xe9, 0x14, 0x98, 0x71, 0x00, 0x30, 0x80, 0x08, 0xa6, 0x8f, 0x40, 0x11, +0xa0, 0x08, 0x98, 0x4a, 0xac, 0x40, 0x00, 0x14, 0x00, 0x00, 0x99, 0xb1, 0x00, 0x13, 0x00, 0x0a, +0x00, 0x23, 0x00, 0x09, 0x40, 0x10, 0xa0, 0x08, 0x98, 0x4a, 0xac, 0x41, 0x80, 0x07, 0x46, 0xf0, +0x00, 0xc3, 0x58, 0xf7, 0x8b, 0x08, 0xdd, 0x2f, 0x48, 0xff, 0xff, 0x73, 0x00, 0x03, 0x00, 0x08, +0x00, 0x83, 0x00, 0x04, 0xa6, 0xf5, 0x00, 0x23, 0x00, 0x09, 0xa7, 0x78, 0x40, 0x84, 0x20, 0x08, +0x40, 0x70, 0x20, 0x08, 0x00, 0x13, 0x00, 0x0a, 0xa6, 0x36, 0xa7, 0x37, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x21, 0x40, 0x08, 0x88, 0x68, 0x98, 0xba, 0x98, 0xdd, 0x98, 0x94, 0x40, 0x00, 0x60, 0x08, +0x40, 0x10, 0xe0, 0x08, 0x98, 0x18, 0x98, 0x51, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x81, 0x78, +0xdd, 0x2f, 0x48, 0xff, 0xff, 0x4e, 0x00, 0x83, 0x80, 0x00, 0xe7, 0x05, 0xe9, 0x03, 0x48, 0xff, +0xff, 0x48, 0xa7, 0xc5, 0x01, 0xc0, 0x00, 0x04, 0x00, 0xa0, 0x00, 0x06, 0x00, 0x90, 0x00, 0x07, +0xcf, 0x0d, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0b, 0x98, 0x80, 0x27, 0x44, 0x20, 0x01, 0x00, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x47, +0x80, 0x6a, 0x50, 0x43, 0x00, 0x08, 0x80, 0xa9, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x85, 0x08, +0xdd, 0x2f, 0x48, 0xff, 0xff, 0x26, 0xa6, 0xf4, 0xa6, 0x35, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x00, +0x40, 0x08, 0xa6, 0xb8, 0xa6, 0x76, 0x98, 0x18, 0x98, 0x02, 0x40, 0x10, 0xe0, 0x08, 0x46, 0x3f, +0xf0, 0x02, 0x98, 0x01, 0x58, 0x31, 0x80, 0x04, 0x4c, 0x01, 0x80, 0x04, 0x84, 0x21, 0xd5, 0x5d, +0x00, 0x03, 0x00, 0x08, 0xa6, 0x77, 0x40, 0x00, 0x20, 0x08, 0x98, 0x01, 0x96, 0x01, 0xc0, 0x3b, +0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x81, 0x98, 0xdd, 0x2f, 0xc0, 0x4e, 0x00, 0x23, 0x00, 0x0a, +0x00, 0x13, 0x00, 0x09, 0x40, 0x21, 0x20, 0x08, 0x98, 0x91, 0x96, 0x91, 0xc2, 0x17, 0x00, 0x10, +0x00, 0xb6, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x0b, 0x18, 0x8e, 0x29, 0x94, 0x4a, 0x98, 0x4c, +0x84, 0x61, 0xae, 0xca, 0x5c, 0x31, 0x00, 0x06, 0x00, 0x10, 0x00, 0xb6, 0x84, 0x06, 0x40, 0x20, +0x0c, 0x1b, 0x8e, 0x29, 0x38, 0x22, 0x06, 0x09, 0xd5, 0x2f, 0x00, 0x10, 0x00, 0xb6, 0x46, 0x30, +0x01, 0x38, 0x58, 0x31, 0x8b, 0x18, 0x8e, 0x29, 0x94, 0x4a, 0x98, 0x4b, 0xae, 0x8a, 0x80, 0x22, +0x00, 0x30, 0x00, 0xb6, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0b, 0x18, 0x8e, 0x69, 0x38, 0x20, +0x0e, 0x09, 0xd5, 0x1b, 0x44, 0x30, 0x00, 0xee, 0x84, 0x06, 0x84, 0x21, 0x44, 0x20, 0x70, 0xa8, +0x80, 0x83, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, +0x58, 0x00, 0x0b, 0x1a, 0x84, 0x20, 0x18, 0x10, 0x00, 0x04, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, +0x0b, 0x9a, 0x4c, 0x02, 0x7f, 0xfa, 0x84, 0x20, 0x44, 0x00, 0xfc, 0x4c, 0x46, 0xf0, 0x00, 0x0f, +0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0x48, 0xff, 0xfe, 0xac, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x0e, +0x58, 0xf7, 0x8d, 0xc4, 0xdd, 0x2f, 0xec, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0xef, 0xc8, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x8d, 0x50, 0xdd, 0x2f, 0x84, 0xaa, +0xd8, 0x04, 0x44, 0x00, 0x00, 0x1f, 0xd5, 0x21, 0x46, 0xf0, 0x00, 0x2e, 0x58, 0xf7, 0x81, 0x58, +0xdd, 0x2f, 0x84, 0xc0, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0xcb, 0x58, 0xf7, 0x83, 0x3c, 0xdd, 0x2f, 0x50, 0x0f, 0x80, 0x04, 0x44, 0x20, 0x0c, 0x03, +0xac, 0x80, 0xa9, 0x84, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x01, 0x10, 0x67, 0x85, 0xf2, 0x80, 0x06, 0xec, 0x38, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x96, 0xc8, 0x80, 0xe2, 0x96, 0x00, 0xe6, 0x68, +0xe8, 0x32, 0x46, 0xf0, 0x01, 0x13, 0x04, 0x47, 0x81, 0x5b, 0x95, 0x9b, 0x46, 0x10, 0x01, 0x0a, +0x58, 0x10, 0x83, 0xb4, 0x99, 0xb1, 0x84, 0x20, 0xae, 0x74, 0x84, 0x28, 0xae, 0x75, 0xc4, 0x09, +0x00, 0x52, 0x01, 0xae, 0xdb, 0x06, 0x46, 0x00, 0x01, 0x0a, 0x58, 0x00, 0x04, 0x04, 0xd5, 0x13, +0xe6, 0x07, 0xe9, 0x08, 0x84, 0x09, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x8d, 0xe4, 0xdd, 0x2f, +0x84, 0x00, 0x44, 0x10, 0x00, 0xe4, 0x42, 0x00, 0x04, 0x24, 0x46, 0x10, 0x01, 0x0a, 0x58, 0x10, +0x84, 0xe8, 0x98, 0x01, 0xb6, 0x06, 0x80, 0x27, 0xb4, 0x06, 0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, +0x80, 0xd8, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xa4, 0x80, 0xe1, 0x81, 0x00, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x84, 0x40, +0xdd, 0x2f, 0x80, 0xc0, 0xc0, 0x1e, 0x04, 0x00, 0x00, 0x6c, 0x84, 0xa1, 0xd8, 0x1a, 0x02, 0x03, +0x00, 0xc3, 0x84, 0xa7, 0xd8, 0x16, 0x00, 0x03, 0x01, 0xc1, 0x84, 0xa1, 0xd8, 0x12, 0x46, 0xf0, +0x01, 0x08, 0x02, 0x57, 0x87, 0xba, 0xd8, 0x5e, 0x50, 0x03, 0x01, 0xa8, 0x46, 0x10, 0x01, 0x06, +0x58, 0x10, 0x8e, 0xaa, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x52, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x83, 0xa3, 0x42, 0x00, 0x5c, 0x0b, 0xc0, 0x08, 0x80, 0x08, +0x84, 0x20, 0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, 0x88, 0x4c, 0xdd, 0x2f, 0x46, 0x30, 0x01, 0x08, +0x58, 0x31, 0x8e, 0xd4, 0x04, 0x11, 0x80, 0x16, 0x50, 0x0f, 0x80, 0x04, 0xa8, 0x47, 0xcf, 0x06, +0x00, 0x31, 0x80, 0x54, 0x10, 0x30, 0x00, 0x09, 0xd5, 0x0f, 0x84, 0x40, 0x80, 0x02, 0x04, 0x11, +0x80, 0x16, 0x38, 0x00, 0x88, 0x08, 0x9c, 0x91, 0x44, 0x50, 0x00, 0xf8, 0xda, 0xf9, 0x50, 0x1f, +0x80, 0x04, 0x10, 0x00, 0x80, 0x09, 0x50, 0x9f, 0x80, 0x50, 0x80, 0x28, 0x84, 0x46, 0x80, 0x09, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x04, 0x84, 0x00, +0x46, 0xf0, 0x01, 0x08, 0x12, 0x07, 0x87, 0xba, 0x14, 0x90, 0x80, 0x04, 0xb6, 0xe1, 0x46, 0xf0, +0x01, 0x08, 0x04, 0x27, 0x83, 0xbc, 0x84, 0x07, 0xdd, 0x22, 0xc6, 0x05, 0x00, 0x03, 0x01, 0xc1, +0xe6, 0x02, 0xe8, 0x08, 0x46, 0x00, 0x04, 0x00, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x82, 0xc8, +0xdd, 0x2f, 0xec, 0x5c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0e, 0x8c, 0x46, 0x80, 0x01, 0x00, 0x80, 0xe0, 0xb5, 0x46, +0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0x81, 0x20, 0x04, 0x04, 0x03, 0xa3, +0x42, 0x00, 0x50, 0x0b, 0xc0, 0x25, 0x47, 0xc0, 0x00, 0x26, 0x59, 0xce, 0x09, 0x3c, 0x80, 0x07, +0x50, 0x15, 0x01, 0xa8, 0xdd, 0x3c, 0xc0, 0x14, 0x04, 0x04, 0x03, 0xa3, 0x54, 0x00, 0x00, 0x02, +0xc0, 0x28, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x8a, 0x88, 0xdd, 0x2f, 0x81, 0x00, 0x84, 0x02, +0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x82, 0xc8, 0xdd, 0x2f, 0x84, 0xc1, 0xd5, 0x68, 0x00, 0x03, +0x00, 0x1c, 0x84, 0xa1, 0xd8, 0x16, 0xa0, 0x31, 0x80, 0x27, 0xdd, 0x3c, 0xd5, 0x11, 0x00, 0x03, +0x00, 0x1c, 0x84, 0xa1, 0xd8, 0x0e, 0xa0, 0x31, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x06, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x07, 0x8f, 0x6c, 0xc8, 0x4d, +0x85, 0x00, 0xd5, 0x39, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x06, 0x10, 0x17, 0x8e, 0xa8, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x81, 0x01, 0x84, 0x20, 0x84, 0x04, 0xdd, 0x22, 0x84, 0xa1, 0xde, 0x07, +0x80, 0x0a, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x84, 0xa0, 0xdd, 0x2f, 0x80, 0x27, 0x80, 0x1f, +0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x83, 0xa3, 0x46, 0x00, 0x04, 0x00, 0x40, 0x10, 0x80, 0x02, 0x80, 0xdf, 0xc1, 0x0a, +0x80, 0x1f, 0x44, 0x10, 0x00, 0x2a, 0x46, 0xf0, 0x00, 0xc7, 0x58, 0xf7, 0x81, 0x10, 0xdd, 0x2f, +0xd5, 0x0a, 0x80, 0x01, 0x80, 0x5f, 0x84, 0x2b, 0x80, 0x60, 0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, +0x86, 0x50, 0xdd, 0x2f, 0x4e, 0x92, 0x00, 0x0d, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, +0x8e, 0x54, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x10, 0x58, 0xf7, 0x82, 0xa8, 0xdd, 0x2f, 0x80, 0x08, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x84, 0xc0, 0x81, 0x06, 0x46, 0xf0, 0x01, 0x13, +0x02, 0x07, 0x82, 0x7a, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xa5, 0x44, 0x20, 0xff, 0xef, +0x40, 0x00, 0x08, 0x02, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x17, 0x8e, 0xa8, 0xc1, 0xb7, +0xd5, 0xa2, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0xa4, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x03, 0x00, 0x17, 0x8d, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, +0x82, 0xab, 0x84, 0x61, 0x40, 0x11, 0x84, 0x0c, 0x40, 0x10, 0x88, 0x02, 0x46, 0xf0, 0x01, 0x03, +0x14, 0x07, 0x83, 0xa5, 0xc1, 0x08, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x3e, 0x54, 0x10, +0x81, 0x00, 0xc9, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x82, 0xae, 0xc8, 0x0d, 0x46, 0xf0, +0x01, 0x03, 0x00, 0x07, 0x8e, 0x6c, 0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x80, 0x00, 0x38, 0x00, +0x80, 0x00, 0xc8, 0x02, 0xd5, 0x07, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x8a, 0xc7, 0x84, 0xa1, +0xd8, 0x06, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x80, 0x55, 0xdd, 0x20, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x8a, 0x78, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x8b, 0x80, 0xe0, 0xdd, 0x21, +0x80, 0xc0, 0x80, 0x26, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x81, 0x8c, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x70, 0x80, 0x26, 0x80, 0x07, 0xdd, 0x22, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0x20, 0x01, 0x03, 0x58, 0x21, +0x0d, 0xfc, 0xa6, 0x11, 0x84, 0xa1, 0xd8, 0x0a, 0x84, 0x60, 0xa6, 0x50, 0xae, 0xd1, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x84, 0xdd, 0x2f, 0x84, 0x03, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x84, 0x20, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, +0xdd, 0x2f, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x0f, 0x02, 0x77, 0x81, 0x7a, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x47, 0x84, 0x04, +0x84, 0x06, 0x84, 0x22, 0x44, 0x20, 0x70, 0x28, 0x80, 0x67, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x89, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x84, 0x06, 0x84, 0xa1, 0xd0, 0x30, +0x46, 0xf0, 0x01, 0x13, 0x00, 0x67, 0x84, 0xb3, 0xc6, 0x08, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x84, 0x2c, 0xdd, 0x2f, 0x54, 0x60, 0x00, 0x0f, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x88, 0x00, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf3, 0x84, 0xa2, 0x46, 0x20, 0x01, 0x0f, +0x58, 0x21, 0x04, 0x00, 0x46, 0x30, 0x00, 0x26, 0x58, 0x31, 0x87, 0x40, 0xd8, 0x0b, 0xa4, 0x54, +0x84, 0x06, 0x98, 0x71, 0x5c, 0x40, 0x80, 0x06, 0x40, 0x10, 0x10, 0x1b, 0x50, 0x01, 0x00, 0x10, +0xd5, 0x05, 0xa4, 0x54, 0x50, 0x01, 0x00, 0x10, 0x98, 0x71, 0x4b, 0xe0, 0x0c, 0x01, 0x54, 0x73, +0x80, 0x0f, 0xc7, 0x32, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x04, 0x00, 0xa7, 0xf4, 0xcf, 0x2c, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0xc8, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x22, 0xc0, 0x24, +0xa6, 0x36, 0xe6, 0x02, 0xe9, 0x03, 0x80, 0x07, 0xd5, 0x04, 0xb4, 0x06, 0x00, 0x00, 0x00, 0xb6, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x83, 0xf0, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x17, 0x84, 0xb4, +0x44, 0x20, 0x08, 0x00, 0xdd, 0x23, 0xc0, 0x03, 0x84, 0x00, 0xd5, 0x0a, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x57, 0x84, 0x06, 0x84, 0x21, 0xd1, 0x03, 0x80, 0x01, 0xd5, 0x02, 0x84, 0x03, 0x46, 0xf0, +0x01, 0x0f, 0x10, 0x07, 0x84, 0x04, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x82, 0x96, 0x04, 0xc8, 0x06, +0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x84, 0xe4, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0xbc, 0x46, 0xf0, +0x01, 0x00, 0x14, 0x07, 0x80, 0x4a, 0x46, 0x30, 0x00, 0xc8, 0x58, 0x31, 0x80, 0xc0, 0x46, 0xf0, +0x01, 0x00, 0x14, 0x37, 0x80, 0x45, 0x46, 0x10, 0x01, 0x38, 0x46, 0x30, 0x00, 0xc6, 0x58, 0x31, +0x8c, 0x2c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x80, 0x46, 0x00, 0x20, 0x89, 0xf7, 0x46, 0x30, +0x00, 0xc6, 0x58, 0x31, 0x85, 0x9c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x80, 0x47, 0x46, 0x30, +0x00, 0xc6, 0x58, 0x31, 0x87, 0x74, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x1e, 0xc2, 0x09, +0x84, 0x00, 0x10, 0x00, 0x89, 0xf7, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x06, 0x14, 0x17, 0x83, 0xb3, +0x46, 0x10, 0x01, 0x38, 0x84, 0x9f, 0x84, 0x00, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xfa, +0x00, 0x20, 0x89, 0xfe, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xfd, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x07, 0x89, 0xf8, 0xc2, 0x08, 0x10, 0x00, 0x89, 0xfe, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x06, +0x14, 0x17, 0x83, 0xb3, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x84, 0xa1, 0x46, 0x20, 0x01, 0x03, 0x58, 0x21, 0x0e, 0x6c, +0xdf, 0x07, 0xa6, 0x10, 0x40, 0x63, 0x98, 0x0c, 0x40, 0x63, 0x00, 0x04, 0xd5, 0x0b, 0xa6, 0x10, +0x84, 0x21, 0x40, 0x60, 0x98, 0x0c, 0x54, 0x00, 0x00, 0x0f, 0x40, 0x63, 0x18, 0x05, 0x40, 0x60, +0x18, 0x02, 0x46, 0xf0, 0x01, 0x00, 0x00, 0x07, 0x82, 0xf9, 0x84, 0xa1, 0xaf, 0x90, 0xd8, 0x03, +0x48, 0x00, 0x01, 0x18, 0x46, 0xf0, 0x01, 0x03, 0x00, 0x07, 0x8e, 0x6c, 0x84, 0xa4, 0x4c, 0x02, +0xc0, 0x89, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x85, 0x0c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x03, +0x04, 0x07, 0x83, 0xb5, 0xc8, 0x1b, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x53, 0x46, 0x10, +0x04, 0x00, 0x42, 0x21, 0x60, 0x08, 0x14, 0x20, 0x00, 0x53, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, +0x44, 0x3f, 0xf8, 0xff, 0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x46, 0x00, 0x1e, 0x84, 0xb4, 0x41, +0x58, 0x00, 0x08, 0x00, 0x58, 0x21, 0x14, 0x00, 0xd5, 0x1a, 0x84, 0xa1, 0xd8, 0x1f, 0x46, 0x00, +0x04, 0x00, 0x04, 0x20, 0x00, 0x53, 0x46, 0x10, 0x04, 0x00, 0x42, 0x21, 0x60, 0x08, 0x14, 0x20, +0x00, 0x53, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, 0xf8, 0xff, 0x40, 0x21, 0x0c, 0x02, +0xb6, 0x41, 0x46, 0x00, 0x3d, 0x09, 0xb4, 0x41, 0x58, 0x21, 0x10, 0x00, 0xb6, 0x41, 0x46, 0xf0, +0x00, 0x07, 0x58, 0xf7, 0x8a, 0x48, 0xdd, 0x2f, 0xd5, 0x1e, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, +0x00, 0x82, 0x42, 0x21, 0x30, 0x09, 0x14, 0x20, 0x00, 0x82, 0x80, 0x20, 0x04, 0x00, 0x80, 0x19, +0x42, 0x00, 0x74, 0x0b, 0x46, 0x10, 0x00, 0x07, 0x58, 0x10, 0x8a, 0x48, 0xc0, 0x06, 0x46, 0x00, +0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x26, 0x25, 0x58, 0x00, 0x0a, 0x00, +0x4b, 0xe0, 0x04, 0x01, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x0e, 0x46, 0x30, 0x03, 0x00, +0x46, 0x10, 0x02, 0x00, 0x40, 0x50, 0x0c, 0x02, 0x4c, 0x50, 0x80, 0x9e, 0x46, 0x10, 0x04, 0x00, +0x04, 0x20, 0x80, 0x53, 0x42, 0x21, 0x4c, 0x09, 0x42, 0x21, 0x50, 0x09, 0x14, 0x20, 0x80, 0x53, +0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x30, 0xb4, 0x20, 0x44, 0x2c, 0xff, 0xff, 0x40, 0x10, +0x88, 0x02, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0x48, 0x00, 0x00, 0x84, +0x84, 0xa8, 0xd0, 0x03, 0x84, 0xac, 0xd8, 0x26, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x85, 0x0c, +0xdd, 0x2f, 0x46, 0x00, 0x04, 0x00, 0x04, 0x20, 0x00, 0x53, 0x42, 0x21, 0x60, 0x09, 0x14, 0x20, +0x00, 0x53, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, 0xf8, 0xff, +0x40, 0x21, 0x0c, 0x02, 0xb6, 0x41, 0x46, 0x00, 0x72, 0x70, 0xb4, 0x41, 0x58, 0x00, 0x0e, 0x00, +0x58, 0x21, 0x10, 0x00, 0xb6, 0x41, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x8a, 0x48, 0xdd, 0x2f, +0xd5, 0x5a, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x02, 0x08, 0xb4, 0x06, 0x42, 0x00, 0x30, 0x09, +0xb6, 0x06, 0x46, 0xf0, 0x00, 0xbf, 0x58, 0xf7, 0x85, 0x0c, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x00, +0xa0, 0x07, 0x42, 0x00, 0x60, 0x0b, 0xc0, 0x0f, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x53, +0x42, 0x10, 0xe0, 0x09, 0x14, 0x10, 0x00, 0x53, 0x44, 0x1f, 0xf8, 0xff, 0xb4, 0x06, 0x40, 0x00, +0x04, 0x02, 0xb6, 0x06, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x0e, 0x46, 0x20, 0x03, 0x00, +0x46, 0x30, 0x02, 0x00, 0x40, 0x50, 0x08, 0x02, 0xd3, 0x19, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, +0x80, 0x53, 0x42, 0x21, 0x4c, 0x09, 0x42, 0x21, 0x50, 0x09, 0x14, 0x20, 0x80, 0x53, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x01, 0x30, 0xb4, 0x20, 0x44, 0x2c, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, +0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x19, 0x42, 0x00, 0x74, 0x0b, 0x46, 0x10, 0x00, 0x07, 0x58, 0x10, 0x8a, 0x48, 0xc0, 0x06, +0x46, 0x00, 0x13, 0x12, 0x58, 0x00, 0x0d, 0x00, 0xd5, 0x05, 0x46, 0x00, 0x26, 0x25, 0x58, 0x00, +0x0a, 0x00, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x07, 0x80, 0x56, 0xc0, 0x02, 0xdd, 0x20, +0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x04, 0x00, +0x04, 0x00, 0x00, 0x83, 0x96, 0x04, 0xc0, 0x11, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x38, +0xb4, 0x20, 0x84, 0xa1, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0xd1, 0x07, 0xb4, 0x20, 0x84, 0xa2, +0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0xd9, 0x07, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x87, 0x50, +0xdd, 0x2f, 0xd5, 0x68, 0x46, 0x10, 0x04, 0x10, 0x46, 0x20, 0x08, 0x5f, 0x58, 0x21, 0x09, 0x10, +0x14, 0x20, 0x80, 0x19, 0x84, 0xa3, 0xb4, 0x00, 0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd8, 0x08, +0x80, 0x01, 0x46, 0x10, 0x20, 0x40, 0x58, 0x10, 0x84, 0x05, 0x14, 0x10, 0x00, 0x4c, 0x46, 0xf0, +0x00, 0xc6, 0x58, 0xf7, 0x85, 0xc0, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x10, 0x84, 0x25, 0x14, 0x10, +0x00, 0x40, 0x04, 0x10, 0x00, 0x40, 0x40, 0x10, 0xbc, 0x08, 0x92, 0x3f, 0xc1, 0xfb, 0x04, 0x10, +0x00, 0x40, 0x44, 0x31, 0x00, 0x00, 0x40, 0x10, 0x8c, 0x02, 0xc9, 0xfa, 0x04, 0x20, 0x00, 0x53, +0x42, 0x21, 0x68, 0x09, 0x14, 0x20, 0x00, 0x53, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xe4, +0x46, 0xf0, 0x01, 0x00, 0x10, 0x17, 0x82, 0xf8, 0x84, 0xa1, 0xd8, 0x10, 0x46, 0x10, 0x04, 0x00, +0x04, 0x20, 0x81, 0x00, 0x80, 0x01, 0x58, 0x21, 0x00, 0x11, 0x14, 0x20, 0x81, 0x00, 0x04, 0x10, +0x01, 0x06, 0x58, 0x10, 0x80, 0x80, 0x14, 0x10, 0x01, 0x06, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, 0x97, 0x40, 0x00, 0x40, 0x08, 0x92, 0x1f, 0xc0, 0x0b, 0x46, 0xf0, 0x01, 0x12, 0x00, 0x17, +0x8a, 0x05, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x84, 0xdd, 0x2f, 0x46, 0x00, +0x04, 0x00, 0x04, 0x10, 0x00, 0x96, 0x42, 0x10, 0xf8, 0x09, 0x42, 0x10, 0xfc, 0x09, 0x14, 0x10, +0x00, 0x96, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x02, 0x0c, 0xb4, 0x00, 0x96, 0x04, 0xc0, 0x13, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x38, 0xb4, 0x20, 0x84, 0x41, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0x4c, 0x11, +0x00, 0x09, 0xb4, 0x00, 0x84, 0x62, 0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0x4c, 0x01, 0xc0, 0x09, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8a, 0x7c, 0xdd, 0x2f, 0x48, 0x00, 0x01, 0x38, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x04, 0x18, 0xb4, 0x20, 0x46, 0x20, 0x01, 0x38, 0x58, 0x21, 0x09, 0xe4, +0x54, 0x10, 0x80, 0x80, 0xc1, 0x12, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x84, 0x00, 0xb4, 0x61, +0x58, 0x31, 0x80, 0x11, 0xb6, 0x61, 0x44, 0x3f, 0xff, 0x7f, 0xb4, 0x20, 0x40, 0x10, 0x8c, 0x02, +0xb6, 0x20, 0x84, 0x01, 0xae, 0x10, 0xd5, 0x02, 0xae, 0x50, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x80, 0x44, 0xdd, 0x2f, 0x84, 0x21, 0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x02, 0xf8, 0xae, 0x40, +0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x08, 0xb4, 0x41, 0x44, 0x3f, 0xef, 0xff, 0x40, 0x21, +0x0c, 0x02, 0xb6, 0x41, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x38, 0xb4, 0x20, 0x84, 0x43, +0x92, 0x34, 0x54, 0x10, 0x80, 0x03, 0x4c, 0x11, 0x00, 0x08, 0xb4, 0x00, 0x92, 0x14, 0x40, 0x00, +0x08, 0x02, 0x4e, 0x03, 0x00, 0x94, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x18, 0xa7, 0xc0, +0xcf, 0x56, 0x46, 0x50, 0x04, 0x05, 0x46, 0x30, 0x04, 0x05, 0x46, 0x40, 0x01, 0x20, 0x46, 0x10, +0x04, 0x05, 0x46, 0x20, 0x20, 0x20, 0x58, 0x10, 0x87, 0xbc, 0x85, 0x0f, 0x46, 0x00, 0x04, 0x05, +0x58, 0x52, 0x87, 0xb0, 0x58, 0x31, 0x87, 0xb4, 0x58, 0x42, 0x00, 0x12, 0x58, 0x21, 0x02, 0x02, +0xb7, 0x05, 0x58, 0x00, 0x07, 0xc0, 0xb6, 0x83, 0x46, 0x60, 0x04, 0x05, 0xb6, 0x41, 0x84, 0x25, +0xb6, 0x20, 0x58, 0x63, 0x07, 0xc4, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x0e, 0xb8, 0xd5, 0x25, +0x84, 0x65, 0x4c, 0x71, 0xc0, 0x21, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x89, 0xe4, 0xa6, 0x08, +0x84, 0x41, 0x4c, 0x01, 0x40, 0x0c, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x04, 0x18, 0xb4, 0x40, +0x58, 0x21, 0x00, 0x80, 0xb6, 0x40, 0x84, 0x00, 0xae, 0x08, 0x84, 0x20, 0x46, 0x00, 0x01, 0x00, +0x58, 0x00, 0x02, 0xf8, 0xae, 0x40, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x80, 0x54, 0xdd, 0x2f, +0x48, 0x00, 0x00, 0xa5, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0x26, 0x9d, 0xf9, 0x54, 0x10, 0x80, 0x90, +0x44, 0x30, 0x00, 0x90, 0x97, 0xf8, 0x84, 0x01, 0x4c, 0x11, 0xff, 0xd4, 0x46, 0x00, 0x04, 0x10, +0x58, 0x00, 0x00, 0x80, 0x84, 0x2e, 0xb6, 0x20, 0x46, 0xf0, 0x00, 0xc6, 0x58, 0xf7, 0x86, 0xc0, +0xdd, 0x2f, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x01, 0x00, 0x84, 0x25, 0xb6, 0x20, 0x84, 0x27, +0xb6, 0x20, 0xb4, 0x20, 0x44, 0x25, 0x00, 0x00, 0x40, 0x10, 0x88, 0x02, 0x4c, 0x11, 0x7f, 0xfb, +0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x01, 0x00, 0xb4, 0x20, 0x44, 0x34, 0x00, 0x00, 0x40, 0x10, +0x8c, 0x02, 0xc1, 0xfb, 0x46, 0x20, 0x04, 0x10, 0x46, 0x30, 0x20, 0x40, 0x46, 0x00, 0x04, 0x10, +0x46, 0x10, 0x08, 0x40, 0x58, 0x21, 0x01, 0x30, 0x58, 0x31, 0x84, 0x04, 0x58, 0x00, 0x00, 0x64, +0x58, 0x10, 0x81, 0x30, 0xb6, 0x62, 0xb6, 0x20, 0xd5, 0x3e, 0x46, 0x70, 0x04, 0x10, 0x46, 0x80, +0x00, 0xe9, 0x46, 0x50, 0x04, 0x10, 0x46, 0x60, 0x00, 0xd8, 0x46, 0x30, 0x04, 0x10, 0x46, 0x40, +0x00, 0xc8, 0x46, 0x10, 0x04, 0x10, 0x46, 0x20, 0x00, 0xc0, 0x58, 0x10, 0x81, 0x10, 0x46, 0x00, +0x04, 0x10, 0x58, 0x73, 0x81, 0x04, 0x58, 0x84, 0x0f, 0xe0, 0x58, 0x52, 0x81, 0x08, 0x58, 0x63, +0x0f, 0x7f, 0x58, 0x31, 0x81, 0x0c, 0x58, 0x42, 0x07, 0x3f, 0x58, 0x21, 0x03, 0x1f, 0xb7, 0x07, +0x58, 0x00, 0x01, 0x00, 0xb6, 0xc5, 0xb6, 0x83, 0xb6, 0x41, 0x84, 0x25, 0xb6, 0x20, 0x84, 0x27, +0xb6, 0x20, 0xb4, 0x20, 0x44, 0x25, 0x00, 0x00, 0x40, 0x10, 0x88, 0x02, 0x4c, 0x11, 0x7f, 0xfb, +0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x01, 0x00, 0xb4, 0x20, 0x44, 0x34, 0x00, 0x00, 0x40, 0x10, +0x8c, 0x02, 0xc1, 0xfb, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x01, 0x40, 0xb4, 0x40, 0x44, 0x3f, +0xf0, 0x00, 0x40, 0x21, 0x0c, 0x02, 0x58, 0x21, 0x01, 0x31, 0xb6, 0x40, 0x46, 0x10, 0x04, 0x10, +0x58, 0x10, 0x81, 0x4c, 0xb4, 0x41, 0x46, 0x00, 0x04, 0x00, 0x42, 0x21, 0x68, 0x08, 0xb6, 0x41, +0x58, 0x00, 0x02, 0x58, 0xb4, 0x20, 0x42, 0x10, 0xf8, 0x08, 0xb6, 0x20, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x80, 0x54, 0xdd, 0x2f, 0x64, 0x00, 0x00, 0x20, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x46, 0x10, 0x04, 0x80, 0x04, 0x20, 0x83, 0xc0, 0x42, 0x21, 0x74, 0x09, 0x42, 0x21, +0x7c, 0x09, 0x46, 0x32, 0x00, 0x00, 0x40, 0x00, 0x74, 0x08, 0x42, 0x21, 0x7c, 0x08, 0x40, 0x00, +0x0c, 0x02, 0x40, 0x01, 0x00, 0x04, 0x14, 0x00, 0x83, 0xc0, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x98, 0xbc, 0x80, 0xc0, 0x46, 0xf0, 0x00, 0x3e, 0x58, 0xf7, 0x8d, 0x40, 0xdd, 0x2f, 0x84, 0x21, +0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x88, 0x64, 0x84, 0xa1, 0x00, 0x03, 0x00, 0x22, 0xd8, 0x0d, +0x84, 0x00, 0x46, 0xf0, 0x00, 0xc7, 0x58, 0xf7, 0x8c, 0xa4, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x90, +0x84, 0x20, 0x14, 0x10, 0x00, 0x09, 0xd5, 0x16, 0x02, 0x33, 0x00, 0x0e, 0x44, 0x00, 0x02, 0x71, +0xa0, 0xb5, 0x4c, 0x30, 0x00, 0x03, 0x9e, 0x94, 0x46, 0x10, 0x04, 0x90, 0x80, 0x01, 0x14, 0x20, +0x80, 0x0b, 0x14, 0x30, 0x00, 0x09, 0x84, 0x01, 0x46, 0xf0, 0x00, 0xc7, 0x58, 0xf7, 0x8c, 0xa4, +0xdd, 0x2f, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x89, 0x14, 0xdd, 0x2f, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xe8, 0x46, 0xf0, 0x01, 0x0a, +0x04, 0x17, 0x83, 0x06, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x09, 0x04, 0x10, 0x80, 0x0a, +0x00, 0x80, 0x80, 0x2c, 0xc8, 0x06, 0x46, 0xf0, 0x00, 0x31, 0x58, 0xf7, 0x8c, 0x8c, 0xdd, 0x2f, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x0c, 0x08, 0xa0, 0x37, 0x84, 0xa7, 0x4c, 0x02, 0x80, 0xdd, +0xe6, 0x08, 0xe8, 0x05, 0x84, 0xa3, 0x4c, 0x02, 0xc1, 0x7d, 0xd5, 0x09, 0x84, 0xa8, 0x4c, 0x02, +0x80, 0x83, 0x84, 0xa9, 0x4c, 0x02, 0xc1, 0x76, 0x48, 0x00, 0x01, 0x17, 0x8c, 0xad, 0x4c, 0x82, +0xc0, 0x03, 0xd5, 0x7c, 0xb4, 0x06, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x18, 0xdd, 0x2f, +0xc0, 0x38, 0x04, 0x03, 0x00, 0x09, 0x84, 0xa1, 0xd8, 0x1a, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x2a, +0x58, 0xf7, 0x84, 0xb8, 0xdd, 0x2f, 0xa0, 0x34, 0x44, 0x10, 0x01, 0x00, 0x46, 0xf0, 0x00, 0x51, +0x58, 0xf7, 0x86, 0x34, 0xdd, 0x2f, 0xa0, 0x32, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x54, +0xdd, 0x2f, 0x84, 0x28, 0xa8, 0x77, 0xb6, 0x06, 0x48, 0x00, 0x01, 0x4c, 0xc8, 0x02, 0xd5, 0x64, +0x46, 0x00, 0x04, 0x90, 0x04, 0x00, 0x00, 0x0e, 0x54, 0x00, 0x0f, 0xff, 0x52, 0x00, 0x10, 0x00, +0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x3c, 0xdd, 0x2f, 0xb6, 0x06, 0xa0, 0x34, 0x44, 0x10, +0x01, 0x00, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, 0x86, 0x34, 0xdd, 0x2f, 0x48, 0x00, 0x01, 0x32, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x80, 0x2b, 0xdd, 0x20, 0x84, 0xa1, 0x4c, 0x02, 0x81, 0x2a, +0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, 0xc8, 0x08, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x86, 0xd8, 0xdd, 0x2f, 0x4e, 0x02, 0x01, 0x1d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xb5, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x06, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x17, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x06, +0x44, 0x10, 0x01, 0x00, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, 0x86, 0x34, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x44, 0x10, 0x10, 0x00, 0x84, 0x03, 0x44, 0x20, 0x10, 0x68, +0x84, 0x60, 0xd5, 0x4f, 0x8c, 0xa8, 0x4c, 0x82, 0xc0, 0x09, 0x46, 0xf0, 0x00, 0x31, 0x58, 0xf7, +0x8c, 0x24, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0xee, 0xb4, 0x06, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x05, 0x84, 0x01, 0xa8, 0x37, 0x48, 0x00, 0x00, 0xe3, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x07, 0x80, 0x2b, 0xdd, 0x20, 0x84, 0xa1, 0x4c, 0x02, 0x80, 0xdb, 0x46, 0xf0, +0x00, 0x22, 0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, 0xc8, 0x08, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, +0x86, 0xd8, 0xdd, 0x2f, 0x4e, 0x02, 0x00, 0xce, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xb5, +0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x06, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, +0x80, 0x27, 0x84, 0x01, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x06, 0x44, 0x10, +0x01, 0x00, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, 0x86, 0x34, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xd5, 0x44, 0x10, 0x10, 0x00, 0x84, 0x03, 0x44, 0x20, 0x10, 0x68, 0x84, 0x61, +0xdd, 0x24, 0x48, 0x00, 0x00, 0xa7, 0x46, 0x70, 0x00, 0x28, 0x58, 0x73, 0x82, 0xf0, 0x4b, 0xe0, +0x1c, 0x01, 0xa6, 0x07, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x28, 0x46, 0xf0, 0x00, 0x31, 0x58, 0xf7, +0x8b, 0xc4, 0xdd, 0x2f, 0x84, 0x09, 0xa8, 0x37, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x01, 0x03, +0x04, 0x17, 0x83, 0xa8, 0x54, 0x10, 0x80, 0x02, 0xc9, 0x05, 0xa6, 0x47, 0x42, 0x10, 0x88, 0x09, +0xae, 0x47, 0x84, 0x06, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x88, 0x54, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x38, 0x14, 0x07, 0x82, 0xc5, 0x46, 0xf0, 0x01, 0x0a, 0x00, 0x17, 0x81, 0x70, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x17, 0x89, 0xe7, 0xd5, 0x75, 0x84, 0xe1, 0x50, 0x8f, 0x80, 0x04, 0x10, 0x74, +0x00, 0x11, 0x46, 0xf0, 0x00, 0x31, 0x58, 0xf7, 0x8d, 0x44, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x09, +0x04, 0x17, 0x83, 0xe8, 0x46, 0xf0, 0x01, 0x0a, 0x10, 0x77, 0x8b, 0x3c, 0x84, 0x02, 0xa8, 0x37, +0xc1, 0x60, 0x80, 0x08, 0xd5, 0x5d, 0x46, 0x70, 0x01, 0x38, 0x58, 0x73, 0x88, 0xdc, 0xb4, 0x07, +0xc8, 0x17, 0x44, 0x10, 0x01, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x17, 0x82, 0xd4, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x17, 0x80, 0x27, 0x84, 0x01, 0xdd, 0x21, 0xa0, 0x34, 0x84, 0x22, 0x46, 0xf0, +0x00, 0xc4, 0x58, 0xf7, 0x8d, 0xf4, 0xdd, 0x2f, 0x84, 0x01, 0xb6, 0x07, 0xd5, 0x42, 0x84, 0xa1, +0xd8, 0x1c, 0x84, 0xa3, 0x4c, 0x82, 0xc0, 0x0f, 0x46, 0xf0, 0x00, 0xc4, 0x58, 0xf7, 0x8d, 0x78, +0xdd, 0x2f, 0x84, 0x02, 0xb6, 0x07, 0x46, 0xf0, 0x00, 0xc4, 0x58, 0xf7, 0x8e, 0x9c, 0xdd, 0x2f, +0xd5, 0x30, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0xc5, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x88, 0x18, 0xdd, 0x2f, 0xc0, 0x26, 0xd5, 0x09, 0x84, 0xa2, 0xd8, 0x09, 0xa0, 0x34, 0x84, 0x20, +0x04, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x33, 0x84, 0x00, 0xb6, 0x07, 0x84, 0xc1, 0x50, 0x7f, +0x80, 0x04, 0x10, 0x63, 0x80, 0x11, 0x46, 0xf0, 0x00, 0x31, 0x58, 0xf7, 0x8d, 0x44, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x09, 0x04, 0x17, 0x83, 0xe8, 0x46, 0xf0, 0x01, 0x0a, 0x10, 0x67, 0x8b, 0x3c, +0x84, 0x42, 0x46, 0xf0, 0x01, 0x0a, 0x14, 0x27, 0x83, 0x09, 0xc1, 0x03, 0x80, 0x07, 0xdd, 0x21, +0x46, 0xf0, 0x01, 0x0a, 0x04, 0x07, 0x83, 0x09, 0x84, 0xa1, 0xd8, 0x16, 0x46, 0xf0, 0x00, 0x31, +0x58, 0xf7, 0x8d, 0x44, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x17, 0x83, 0xe7, 0xc1, 0x07, +0x50, 0x0f, 0x80, 0x04, 0x84, 0x40, 0x10, 0x20, 0x00, 0x11, 0xdd, 0x21, 0x84, 0x22, 0x46, 0xf0, +0x01, 0x0a, 0x14, 0x17, 0x83, 0x09, 0xec, 0x18, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x30, 0x00, 0xbc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x80, 0x4a, +0x46, 0x40, 0x00, 0xc5, 0x58, 0x42, 0x03, 0x7c, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x47, 0x80, 0x3d, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0x8c, 0x84, 0x02, 0x46, 0x10, 0x00, 0xbd, 0x58, 0x10, +0x88, 0x84, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x87, 0xac, 0xdd, 0x2f, 0x46, 0x30, 0x00, 0xc5, +0x58, 0x31, 0x84, 0xd0, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x84, 0x46, 0x30, 0x00, 0xbc, +0x58, 0x31, 0x8c, 0xf4, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x85, 0x46, 0x30, 0x00, 0xbf, +0x58, 0x31, 0x83, 0x60, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x83, 0xf7, 0x46, 0x30, 0x00, 0xbe, +0x58, 0x31, 0x88, 0x08, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xa6, 0x46, 0x30, 0x00, 0xbe, +0x58, 0x31, 0x87, 0x2c, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xbd, 0x46, 0x30, 0x00, 0xbc, +0x58, 0x31, 0x89, 0x9c, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xc9, 0x46, 0x30, 0x00, 0xc4, +0x58, 0x31, 0x85, 0x84, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x92, 0x46, 0x30, 0x00, 0xc3, +0x58, 0x31, 0x82, 0x00, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x9e, 0x46, 0x20, 0x00, 0xc4, +0x58, 0x21, 0x07, 0x68, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x81, 0x04, 0x46, 0x30, 0x00, 0xc3, +0x58, 0x31, 0x8f, 0x1c, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xb3, 0x46, 0x30, 0x00, 0xbc, +0x58, 0x31, 0x8a, 0x30, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x8c, 0x46, 0x30, 0x00, 0xc4, +0x58, 0x31, 0x81, 0x68, 0x46, 0xf0, 0x01, 0x09, 0x14, 0x37, 0x83, 0xef, 0x46, 0x30, 0x00, 0xc1, +0x58, 0x31, 0x84, 0xcc, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xc2, 0x46, 0x30, 0x00, 0xc4, +0x58, 0x31, 0x85, 0x28, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xd3, 0x46, 0x30, 0x00, 0xc4, +0x58, 0x31, 0x80, 0xb4, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xe2, 0x46, 0x30, 0x00, 0xbe, +0x58, 0x31, 0x86, 0xa8, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x90, 0x46, 0x30, 0x00, 0xc3, +0x58, 0x31, 0x8f, 0xf0, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x91, 0x46, 0x30, 0x00, 0xc3, +0x58, 0x31, 0x8f, 0x74, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xc1, 0x46, 0x30, 0x00, 0xc1, +0x58, 0x31, 0x83, 0xdc, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0xc3, 0x46, 0x20, 0x00, 0xbe, +0x58, 0x21, 0x09, 0xd8, 0x46, 0x40, 0x01, 0x10, 0x58, 0x42, 0x05, 0xc0, 0x46, 0x60, 0x01, 0x00, +0x58, 0x63, 0x03, 0xbc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x81, 0x03, 0x84, 0xec, 0x44, 0x90, +0x00, 0x32, 0x85, 0x00, 0x46, 0x30, 0x00, 0xc4, 0x58, 0x31, 0x80, 0xf0, 0x84, 0xa5, 0x10, 0x73, +0x00, 0x34, 0x10, 0x82, 0x00, 0xa3, 0x10, 0x82, 0x00, 0xa4, 0x10, 0x73, 0x00, 0x0a, 0x10, 0x73, +0x00, 0x1a, 0x10, 0x73, 0x00, 0x22, 0x10, 0x73, 0x00, 0x32, 0x10, 0x73, 0x00, 0x14, 0x10, 0x73, +0x00, 0x24, 0x10, 0x73, 0x00, 0x2c, 0x10, 0x93, 0x00, 0x0e, 0x10, 0x93, 0x00, 0x1e, 0x10, 0x93, +0x00, 0x26, 0x10, 0x93, 0x00, 0x2e, 0x10, 0x93, 0x00, 0x36, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, +0x80, 0xd8, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x57, 0x86, 0x37, 0x84, 0x67, 0x46, 0xf0, 0x01, 0x01, +0x10, 0x37, 0x86, 0x38, 0x46, 0x30, 0x00, 0xbc, 0x58, 0x31, 0x89, 0xa4, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x37, 0x80, 0xc4, 0x47, 0xe0, 0x30, 0x61, 0x84, 0x63, 0x59, 0xef, 0x01, 0xdf, 0x46, 0xf0, +0x01, 0x01, 0x10, 0x37, 0x88, 0x5e, 0x46, 0xf0, 0x01, 0x00, 0x15, 0xe7, 0x83, 0xbd, 0x46, 0x30, +0x00, 0xc5, 0x58, 0x31, 0x83, 0xac, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x81, 0x3b, 0x46, 0xf0, +0x01, 0x00, 0x15, 0xe7, 0x83, 0xbc, 0x85, 0x40, 0x87, 0x8f, 0x46, 0xf0, 0x01, 0x38, 0x14, 0xa7, +0x82, 0x35, 0x10, 0x52, 0x00, 0x0c, 0x10, 0x52, 0x00, 0x0d, 0x10, 0x52, 0x00, 0x0e, 0x10, 0x52, +0x00, 0x10, 0x10, 0x52, 0x00, 0x11, 0x10, 0x52, 0x00, 0x12, 0x10, 0x52, 0x00, 0x14, 0x10, 0x52, +0x00, 0x15, 0x10, 0x52, 0x00, 0x16, 0x10, 0x52, 0x00, 0x18, 0x10, 0x52, 0x00, 0x19, 0x10, 0x52, +0x00, 0x1a, 0x11, 0xc2, 0x00, 0x1b, 0x11, 0xc2, 0x00, 0x0f, 0x11, 0xc2, 0x00, 0x13, 0x11, 0xc2, +0x00, 0x17, 0x46, 0xf0, 0x01, 0x38, 0x14, 0xa7, 0x82, 0x36, 0x44, 0x00, 0x00, 0x1d, 0x46, 0x10, +0x00, 0xc5, 0x58, 0x10, 0x84, 0x90, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x84, 0x2c, 0xdd, 0x2f, +0x46, 0x30, 0x00, 0xbc, 0x58, 0x31, 0x87, 0xa4, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x65, +0x46, 0x30, 0x00, 0xc6, 0x58, 0x31, 0x84, 0x4c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x80, 0xaf, +0x84, 0x03, 0x46, 0x10, 0x00, 0xc3, 0x58, 0x10, 0x81, 0x24, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, +0x84, 0x2c, 0xdd, 0x2f, 0x46, 0x10, 0x04, 0x90, 0x04, 0x30, 0x80, 0x20, 0x46, 0x4e, 0x0f, 0xff, +0x58, 0x42, 0x0f, 0xff, 0x46, 0x00, 0x70, 0x00, 0x40, 0x31, 0x90, 0x02, 0x40, 0x31, 0x80, 0x04, +0x14, 0x30, 0x80, 0x20, 0x80, 0x41, 0x04, 0x31, 0x00, 0x1d, 0x44, 0x4f, 0xf0, 0xff, 0x40, 0x31, +0x90, 0x02, 0x58, 0x31, 0x88, 0x00, 0x14, 0x31, 0x00, 0x1d, 0x04, 0x20, 0x80, 0x22, 0x92, 0x48, +0x40, 0x21, 0x20, 0x08, 0x58, 0x21, 0x00, 0x09, 0x14, 0x20, 0x80, 0x22, 0x46, 0x40, 0x00, 0xc2, +0x58, 0x42, 0x05, 0xd0, 0x46, 0x20, 0x01, 0x00, 0x58, 0x21, 0x03, 0x18, 0xa9, 0x12, 0x46, 0x50, +0x00, 0xc5, 0x58, 0x52, 0x8c, 0x50, 0x46, 0x30, 0x00, 0xc6, 0x58, 0x31, 0x82, 0x04, 0x46, 0xf0, +0x01, 0x01, 0x14, 0x57, 0x80, 0x06, 0x46, 0xf0, 0x01, 0x08, 0x14, 0x37, 0x83, 0xbb, 0x46, 0x50, +0x00, 0xc5, 0x58, 0x52, 0x88, 0x9c, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x57, 0x80, 0x08, 0x46, 0x50, +0x00, 0xc5, 0x58, 0x52, 0x85, 0xe0, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x57, 0x83, 0xf4, 0x46, 0x50, +0x00, 0xc6, 0x58, 0x52, 0x83, 0x9c, 0x46, 0xf0, 0x01, 0x03, 0x14, 0x57, 0x83, 0xd6, 0x46, 0x40, +0x00, 0xc6, 0x58, 0x42, 0x09, 0xac, 0x14, 0x41, 0x00, 0x08, 0x46, 0x40, 0x00, 0xc3, 0x58, 0x42, +0x0b, 0x94, 0xa9, 0x13, 0x46, 0x40, 0x00, 0xc2, 0x58, 0x42, 0x06, 0x68, 0xa9, 0x11, 0x46, 0xf0, +0x01, 0x00, 0x14, 0x37, 0x83, 0x77, 0x46, 0x60, 0x00, 0x3b, 0x58, 0x63, 0x0d, 0xa8, 0x84, 0x07, +0x46, 0x10, 0x00, 0xc5, 0x58, 0x10, 0x86, 0x04, 0xdd, 0x26, 0x84, 0x09, 0x46, 0x10, 0x00, 0xc5, +0x58, 0x10, 0x8e, 0x50, 0xdd, 0x26, 0x84, 0x02, 0x46, 0x10, 0x00, 0xc5, 0x58, 0x10, 0x86, 0xc0, +0xdd, 0x26, 0x84, 0x04, 0x46, 0x10, 0x00, 0xc5, 0x58, 0x10, 0x86, 0xc0, 0xdd, 0x26, 0x84, 0x05, +0x46, 0x10, 0x00, 0xc5, 0x58, 0x10, 0x8f, 0x6c, 0xdd, 0x26, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, +0x8e, 0x04, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8c, 0xbc, 0xdd, 0x2f, 0x46, 0x40, +0x00, 0xbd, 0x58, 0x42, 0x0c, 0x88, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x47, 0x81, 0x17, 0x46, 0x50, +0x00, 0xc2, 0x58, 0x52, 0x85, 0x10, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x57, 0x83, 0x7c, 0x46, 0x50, +0x00, 0xc2, 0x58, 0x52, 0x81, 0xec, 0x46, 0xf0, 0x01, 0x03, 0x14, 0x57, 0x83, 0xd1, 0x46, 0x50, +0x00, 0xc2, 0x58, 0x52, 0x82, 0x24, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x57, 0x80, 0xb1, 0x46, 0x40, +0x00, 0xc2, 0x58, 0x42, 0x00, 0x58, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x47, 0x81, 0x51, 0x46, 0x50, +0x00, 0xc2, 0x58, 0x52, 0x80, 0x1c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x57, 0x83, 0xf2, 0x46, 0x50, +0x00, 0xc1, 0x58, 0x52, 0x8f, 0xf0, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x57, 0x83, 0xf3, 0x46, 0x40, +0x00, 0xc2, 0x58, 0x42, 0x08, 0x9c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x47, 0x81, 0x34, 0x46, 0xf0, +0x01, 0x01, 0x10, 0xa7, 0x85, 0xfd, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, 0x89, 0xe5, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x87, 0x89, 0xe6, 0x46, 0x30, 0x00, 0xc2, 0x58, 0x31, 0x80, 0xcc, 0x46, 0xf0, +0x01, 0x00, 0x14, 0x37, 0x81, 0x52, 0x80, 0x0a, 0x46, 0x10, 0x00, 0xc3, 0x58, 0x10, 0x8c, 0x14, +0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x84, 0x2c, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, +0x09, 0xf9, 0x44, 0x50, 0x00, 0xff, 0xd9, 0x33, 0x10, 0x80, 0x09, 0xf9, 0x46, 0x10, 0x04, 0x00, +0x58, 0x10, 0x81, 0x28, 0xb4, 0x01, 0x44, 0x4f, 0x0f, 0xff, 0x40, 0x00, 0x10, 0x02, 0xb6, 0x01, +0xb4, 0x41, 0x50, 0x60, 0x80, 0x90, 0x58, 0x21, 0x10, 0x00, 0xb6, 0x41, 0xb4, 0x46, 0x42, 0x21, +0x4c, 0x09, 0xb6, 0x46, 0x9c, 0x3f, 0x84, 0x21, 0x46, 0x70, 0x00, 0xca, 0x58, 0x73, 0x80, 0x68, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x01, 0x20, 0xb4, 0x22, 0x42, 0x10, +0xd0, 0x09, 0xb6, 0x22, 0x84, 0x05, 0xb4, 0x62, 0x84, 0x21, 0x42, 0x31, 0xd0, 0x08, 0xb6, 0x62, +0xb4, 0x46, 0x42, 0x21, 0x14, 0x09, 0xb6, 0x46, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x41, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x27, 0x89, 0xf8, 0x44, 0x10, 0x00, 0x32, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x17, +0x81, 0xe1, 0x44, 0x10, 0x04, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x17, 0x81, 0xe0, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0x74, +0x84, 0xa1, 0xd8, 0x2a, 0x44, 0x00, 0x20, 0x00, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, +0x44, 0x20, 0x01, 0x00, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x83, 0x50, 0xdd, 0x2f, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x0b, 0x98, 0xa6, 0x40, 0x44, 0x50, 0x00, 0xc9, 0xd9, 0x05, 0xa6, 0x41, +0x44, 0x50, 0x00, 0xfc, 0xd1, 0x05, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x08, 0xcc, 0x44, 0x10, +0xfc, 0xc9, 0x46, 0xf0, 0x00, 0xc6, 0x58, 0xf7, 0x8c, 0x2c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xcb, +0x58, 0xf7, 0x8c, 0xa4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0x04, 0xdd, 0x2f, +0x46, 0x20, 0x01, 0x38, 0x04, 0x41, 0x02, 0x38, 0x84, 0xa9, 0xdc, 0x10, 0x84, 0x60, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x37, 0x89, 0xea, 0x14, 0x31, 0x02, 0x38, 0x44, 0x00, 0x00, 0x13, 0x84, 0x21, +0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0x68, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0xc2, 0x58, 0x21, +0x0b, 0x94, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0xb3, 0x46, 0x20, 0x00, 0xbc, 0x58, 0x21, +0x0d, 0xe8, 0x46, 0xf0, 0x01, 0x13, 0x14, 0x27, 0x80, 0xbc, 0x46, 0x20, 0x00, 0xbc, 0x58, 0x21, +0x0d, 0x94, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x80, 0xb9, 0x46, 0x20, 0x00, 0xbc, 0x58, 0x21, +0x0d, 0xbc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x80, 0xba, 0x46, 0x20, 0x00, 0xc3, 0x58, 0x21, +0x00, 0x18, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0xfe, 0x46, 0x20, 0x00, 0xc2, 0x58, 0x21, +0x0e, 0x50, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0xb1, 0x46, 0x20, 0x00, 0xc2, 0x58, 0x21, +0x0b, 0xbc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0x9c, 0x46, 0x20, 0x00, 0xc1, 0x58, 0x21, +0x0f, 0x1c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0xc3, 0x46, 0x20, 0x00, 0xc1, 0x58, 0x21, +0x0d, 0xcc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0x99, 0x46, 0x20, 0x00, 0xc1, 0x58, 0x21, +0x00, 0x44, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x81, 0x1f, 0x46, 0x20, 0x00, 0xc0, 0x58, 0x21, +0x09, 0xbc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x81, 0xee, 0x46, 0x20, 0x00, 0xbe, 0x58, 0x21, +0x0e, 0xd8, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x27, 0x80, 0xdc, 0x46, 0x20, 0x00, 0xbe, 0x58, 0x21, +0x0e, 0x04, 0x46, 0x60, 0x01, 0x00, 0x58, 0x63, 0x03, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x27, +0x80, 0xa1, 0x46, 0x10, 0x00, 0xbd, 0x58, 0x10, 0x8a, 0x5c, 0x84, 0xe0, 0xa8, 0x77, 0x46, 0xf0, +0x01, 0x38, 0x12, 0x77, 0x84, 0xea, 0x46, 0x10, 0x00, 0xc0, 0x58, 0x10, 0x8f, 0xd8, 0xa8, 0x71, +0x46, 0x10, 0x00, 0xc1, 0x58, 0x10, 0x80, 0x28, 0xa8, 0x72, 0x46, 0x10, 0x00, 0xc0, 0x58, 0x10, +0x8c, 0x78, 0xa8, 0x76, 0x84, 0x09, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x8a, 0x8c, 0xdd, 0x2f, +0x46, 0x00, 0x01, 0x13, 0x04, 0x10, 0x01, 0x6c, 0x42, 0x10, 0x80, 0x09, 0x46, 0x30, 0x00, 0xca, +0x58, 0x31, 0x8b, 0x00, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x37, 0x80, 0x98, 0x46, 0x30, 0x00, 0xbe, +0x58, 0x31, 0x8d, 0xd8, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x83, 0xc6, 0x14, 0x10, 0x01, 0x6c, +0x46, 0x10, 0x00, 0xbe, 0x58, 0x10, 0x84, 0xa4, 0x46, 0x30, 0x00, 0xbe, 0x58, 0x31, 0x8c, 0xe0, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x81, 0xed, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x83, 0x9f, +0x46, 0x10, 0x00, 0xbd, 0x58, 0x10, 0x88, 0xa0, 0x46, 0x20, 0x00, 0xbe, 0x58, 0x21, 0x00, 0x14, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x81, 0xca, 0x14, 0x23, 0x00, 0x0b, 0x46, 0x10, 0x00, 0xbc, +0x58, 0x10, 0x8f, 0x9c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x81, 0xcf, 0x80, 0x27, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x0b, 0x1a, 0x18, 0x10, 0x00, 0x04, 0x46, 0x50, 0x01, 0x38, 0x58, 0x52, +0x8b, 0x9a, 0xd8, 0xfa, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x85, 0xbf, 0x46, 0x10, 0x00, 0xbc, +0x58, 0x10, 0x8e, 0x4c, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x83, 0x98, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x0c, 0x6c, 0x04, 0x14, 0x00, 0x06, 0x54, 0x90, 0x00, 0xff, 0x04, 0x00, 0x80, 0x0a, +0x04, 0x14, 0x00, 0x07, 0x84, 0x45, 0x00, 0x00, 0x00, 0x2c, 0x4c, 0x11, 0x40, 0xa9, 0x84, 0xa2, +0x4c, 0x02, 0xc0, 0xa6, 0x46, 0x10, 0x04, 0x80, 0x04, 0x00, 0x83, 0xe5, 0x8c, 0x0c, 0xb4, 0x00, +0x40, 0x00, 0x34, 0x08, 0x92, 0x1d, 0x4e, 0x02, 0x00, 0x9b, 0x50, 0x04, 0x00, 0x28, 0x46, 0xf0, +0x00, 0x2a, 0x58, 0xf7, 0x8f, 0x24, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0xbc, 0x58, 0x73, 0x82, 0x08, +0x80, 0x3f, 0x50, 0x04, 0x00, 0x28, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0xc7, +0x58, 0xf7, 0x82, 0x0c, 0xdd, 0x2f, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x84, 0x80, +0xdd, 0x2f, 0x80, 0xc0, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x17, 0x83, 0xef, 0x50, 0x04, 0x00, 0x28, +0x50, 0x10, 0x81, 0xa8, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x8e, 0x8c, +0xdd, 0x2f, 0x80, 0xe0, 0xc8, 0x72, 0xc6, 0x6b, 0x84, 0x08, 0x14, 0x04, 0x00, 0x07, 0x84, 0x01, +0x10, 0x04, 0x00, 0x20, 0x84, 0xa7, 0x02, 0x03, 0x00, 0xc3, 0xd0, 0x67, 0x10, 0x73, 0x01, 0xf5, +0x00, 0x03, 0x01, 0xae, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x87, 0x81, 0xdd, 0x44, 0xa0, 0x00, 0x30, +0x42, 0x80, 0x28, 0x73, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, 0x86, 0x88, 0x40, 0x03, 0xa0, 0x06, +0x80, 0x27, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x00, 0xa0, 0x44, 0x30, 0x02, 0x8e, 0x4b, 0xe0, +0x24, 0x01, 0x04, 0x04, 0x00, 0x0a, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x00, 0xa0, 0x10, 0x70, +0x00, 0x2d, 0x80, 0x27, 0x00, 0x03, 0x01, 0xae, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x87, 0x81, 0xdd, +0x44, 0x30, 0x02, 0xa1, 0x42, 0x80, 0x28, 0x73, 0x40, 0x03, 0xa0, 0x06, 0x4b, 0xe0, 0x24, 0x01, +0x04, 0x04, 0x00, 0x0a, 0x10, 0x70, 0x00, 0x2e, 0x44, 0x00, 0x00, 0x13, 0x04, 0x23, 0x00, 0x6c, +0x14, 0x03, 0x00, 0x29, 0x84, 0xa1, 0xda, 0x0e, 0xb4, 0x06, 0x54, 0x00, 0x40, 0xc0, 0xc0, 0x0a, +0x46, 0x00, 0x01, 0x08, 0x58, 0x00, 0x0f, 0x82, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, +0xdd, 0x2f, 0x50, 0x03, 0x01, 0xf0, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, +0xb4, 0x06, 0x58, 0x00, 0x08, 0x00, 0xb6, 0x06, 0x84, 0x07, 0x12, 0x03, 0x00, 0xc3, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, 0x82, 0xbc, 0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x09, 0x46, 0xf0, +0x00, 0x32, 0x58, 0xf7, 0x88, 0x44, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x22, 0x84, 0xa1, 0xd8, 0x1d, +0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x88, 0x64, 0xc8, 0x0c, 0x46, 0x00, 0x04, 0x80, 0x58, 0x00, +0x0f, 0x00, 0xb4, 0x20, 0x4e, 0x14, 0x00, 0x06, 0xb4, 0x20, 0x42, 0x10, 0xfc, 0x09, 0xb6, 0x20, +0x84, 0x00, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0x88, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x90, +0x58, 0x00, 0x00, 0x24, 0x84, 0x20, 0xd5, 0x25, 0x02, 0x33, 0x00, 0x0e, 0x44, 0x00, 0x02, 0x71, +0xa0, 0xb5, 0x4c, 0x30, 0x00, 0x03, 0x9e, 0x94, 0x46, 0x10, 0x04, 0x90, 0x80, 0x01, 0x14, 0x20, +0x80, 0x0b, 0x14, 0x30, 0x00, 0x09, 0x84, 0x01, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x82, 0x88, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x88, 0x64, 0xc8, 0x0c, 0x46, 0x00, 0x04, 0x80, +0x58, 0x00, 0x0f, 0x00, 0xb4, 0x20, 0x4e, 0x14, 0x00, 0x06, 0xb4, 0x20, 0x42, 0x10, 0xfc, 0x09, +0xb6, 0x20, 0x46, 0x00, 0x01, 0x01, 0x58, 0x00, 0x07, 0x14, 0x02, 0x30, 0x00, 0x34, 0x04, 0x10, +0x00, 0x18, 0x44, 0x20, 0x00, 0x30, 0x42, 0x11, 0x88, 0x73, 0xa0, 0xb1, 0xa8, 0x89, 0x84, 0xa1, +0x00, 0x13, 0x00, 0x22, 0xd9, 0x07, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x3c, 0xdd, 0x2f, +0xd5, 0x0a, 0x04, 0x13, 0x00, 0x0a, 0x46, 0x00, 0x04, 0x80, 0xa0, 0x8a, 0xb6, 0x40, 0x02, 0x10, +0x80, 0x10, 0xa8, 0x41, 0x84, 0x03, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x89, 0x14, 0xdd, 0x2f, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x44, 0x10, 0x00, 0x30, 0x96, 0x00, 0x42, 0x10, 0x04, 0x24, +0x46, 0x20, 0x01, 0x0f, 0x58, 0x21, 0x03, 0x00, 0x98, 0x4a, 0x84, 0x5f, 0xae, 0x8e, 0x46, 0xf0, +0x01, 0x13, 0x10, 0x07, 0x84, 0xac, 0xdd, 0x9e, 0x92, 0x00, 0x44, 0x20, 0xfd, 0x55, 0x96, 0x01, +0x96, 0x48, 0x4c, 0x01, 0x00, 0x18, 0xe2, 0x40, 0xe9, 0x07, 0x9e, 0x52, 0x4c, 0x00, 0x80, 0x11, +0x9d, 0x49, 0xd8, 0x21, 0xd5, 0x0b, 0x44, 0x20, 0xfd, 0x57, 0x4c, 0x01, 0x00, 0x13, 0xe2, 0x02, +0xe9, 0x05, 0x9c, 0x52, 0x4c, 0x00, 0xc0, 0x18, 0xd5, 0x13, 0x84, 0x02, 0xd5, 0x15, 0x84, 0x09, +0xd5, 0x13, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x8a, 0x05, 0x9c, 0x02, 0x96, 0x00, 0xd5, 0x0c, +0x84, 0x44, 0x84, 0x63, 0x40, 0x01, 0x84, 0x1a, 0x40, 0x01, 0x04, 0x1b, 0xd5, 0x05, 0x44, 0x00, +0x00, 0x11, 0xd5, 0x02, 0x84, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x60, 0xd5, 0x0a, 0x38, 0x50, +0x0c, 0x00, 0x38, 0x40, 0x8c, 0x00, 0x9e, 0x91, 0x9c, 0xd9, 0xd4, 0x03, 0x84, 0x00, 0xd5, 0x03, +0xca, 0xf7, 0x84, 0x01, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0x3c, 0x84, 0xa0, 0xd5, 0x13, 0x38, 0x90, +0x14, 0x00, 0x38, 0x70, 0x94, 0x00, 0x38, 0x81, 0x14, 0x00, 0x38, 0x61, 0x94, 0x00, 0x40, 0x73, +0xa4, 0x02, 0x40, 0x63, 0x20, 0x02, 0x9d, 0x69, 0x9f, 0x21, 0x4c, 0x73, 0x00, 0x04, 0x84, 0x00, +0xd5, 0x03, 0xcc, 0xee, 0x84, 0x01, 0x3a, 0x6f, 0xa4, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0x80, 0x01, 0x38, 0x04, 0x14, 0x02, 0x39, 0x80, 0xc0, 0xc1, 0x34, 0xc0, 0x33, +0xa6, 0x00, 0xc0, 0x31, 0x04, 0x70, 0x80, 0x17, 0x00, 0x03, 0x00, 0x17, 0x00, 0x20, 0x80, 0x17, +0xc7, 0x12, 0x80, 0x60, 0x4c, 0x20, 0x40, 0x0c, 0xd5, 0x1a, 0x00, 0x50, 0x00, 0x17, 0xdb, 0x06, +0x04, 0x00, 0x00, 0x17, 0x14, 0x00, 0x80, 0x17, 0xd5, 0x23, 0x80, 0x20, 0x04, 0x00, 0x80, 0x17, +0xc8, 0xf5, 0xd5, 0x19, 0x4c, 0x01, 0x40, 0x18, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xe9, +0x80, 0x07, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x77, 0x89, 0xf3, 0x14, 0x74, 0x02, 0x39, +0xd5, 0x0f, 0xa7, 0x4e, 0xda, 0x03, 0x84, 0x00, 0xd5, 0x08, 0x04, 0x10, 0x80, 0x17, 0xa6, 0xb6, +0xc9, 0xf9, 0xd5, 0x0d, 0x44, 0x00, 0x00, 0x1f, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x84, 0x00, +0xae, 0x30, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x39, 0xd5, 0xf2, 0x84, 0x61, 0x40, 0x21, +0x88, 0x0c, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x37, 0x81, 0x7a, 0x40, 0x21, 0x08, 0x05, 0x40, 0x21, +0x0c, 0x02, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x27, 0x81, 0x7a, 0x80, 0x01, 0xd5, 0xe6, 0x3a, 0x6f, +0x98, 0x3c, 0x46, 0x30, 0x01, 0x38, 0x04, 0x11, 0x82, 0x39, 0x04, 0x00, 0x80, 0x17, 0xa4, 0x89, +0xc0, 0x48, 0xa5, 0x02, 0xe2, 0x44, 0xe8, 0x06, 0x9a, 0xa2, 0xac, 0x82, 0x84, 0x00, 0xa4, 0x89, +0xd5, 0x2f, 0x14, 0x01, 0x82, 0x39, 0x04, 0x30, 0x80, 0x17, 0xa4, 0x9a, 0xd5, 0x1a, 0xa5, 0x09, +0xe0, 0x82, 0xe9, 0x14, 0xa5, 0x42, 0x99, 0x55, 0xe0, 0x85, 0xe8, 0x10, 0x14, 0x00, 0x80, 0x17, +0x14, 0x11, 0x80, 0x17, 0x84, 0x00, 0xa5, 0x49, 0x04, 0x40, 0x80, 0x17, 0x9b, 0x6a, 0x97, 0x69, +0xad, 0x4a, 0xa5, 0xa2, 0x9b, 0x75, 0xad, 0x62, 0xd5, 0x09, 0xa5, 0x02, 0x80, 0x60, 0x98, 0x94, +0x04, 0x01, 0x80, 0x17, 0xc8, 0xe5, 0x44, 0x00, 0x00, 0x1f, 0x04, 0x41, 0x80, 0x17, 0xcc, 0x09, +0x14, 0x11, 0x80, 0x17, 0x14, 0x40, 0x80, 0x17, 0xa4, 0xc9, 0x80, 0x04, 0x9a, 0x9a, 0xac, 0x8a, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x39, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x89, 0xd8, +0x04, 0x41, 0x00, 0x17, 0xa4, 0xd1, 0xa4, 0xa2, 0xe2, 0x62, 0xe8, 0x07, 0xac, 0xc8, 0xd5, 0x06, +0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x89, 0xd8, 0xac, 0x88, 0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x83, 0xe9, +0x84, 0x01, 0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, +0x01, 0x4d, 0x00, 0x07, 0x87, 0x50, 0x46, 0xf0, 0x01, 0x4d, 0x00, 0x17, 0x87, 0x52, 0x9a, 0x08, +0x96, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x8a, 0x02, 0x84, 0x00, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x07, 0x81, 0xde, +0xdd, 0x20, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x01, 0x4d, 0x58, 0x21, +0x07, 0x50, 0xa4, 0x50, 0xa4, 0x11, 0xe2, 0x20, 0xe8, 0x0e, 0xa0, 0x52, 0xc1, 0x0c, 0xa0, 0x0f, +0x4c, 0x00, 0xc0, 0x05, 0x84, 0x20, 0xa8, 0x52, 0xd5, 0x04, 0xa0, 0x87, 0xa8, 0x8f, 0x84, 0x20, +0xa8, 0x47, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xa0, 0xcb, +0x97, 0xd0, 0x00, 0x81, 0x80, 0x06, 0x4e, 0x83, 0x00, 0x24, 0x46, 0x60, 0x01, 0x44, 0x58, 0x63, +0x0d, 0xe8, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x44, 0xa0, 0xf2, 0x80, 0x41, 0x9e, 0x46, +0xdd, 0x23, 0x80, 0x40, 0xc7, 0x0b, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x4c, 0xa0, 0xf3, +0x50, 0x10, 0x7f, 0xf6, 0xdd, 0x23, 0x80, 0x08, 0xd5, 0x16, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, +0x07, 0x48, 0xa0, 0xf3, 0x50, 0x10, 0x7f, 0xf8, 0xdd, 0x23, 0x80, 0x07, 0xd5, 0x0c, 0xb4, 0x20, +0xb4, 0xa3, 0xd1, 0x03, 0x84, 0x00, 0xd5, 0x07, 0xa4, 0x42, 0xa4, 0x1a, 0x40, 0x00, 0x80, 0x03, +0x5c, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x97, 0x8a, 0x04, 0x80, 0xc0, 0x83, 0x81, 0x4e, 0x92, 0x00, 0x04, +0x84, 0x0f, 0xd5, 0x36, 0x50, 0x8f, 0x80, 0x10, 0x46, 0xa0, 0x00, 0x5b, 0x58, 0xa5, 0x06, 0x98, +0x80, 0x29, 0x44, 0x20, 0x00, 0x10, 0x80, 0x08, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x29, 0x44, 0x20, +0x00, 0x10, 0x80, 0x1f, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x83, 0xf4, +0xa6, 0x33, 0x80, 0x28, 0x10, 0x04, 0x00, 0x00, 0x80, 0x5f, 0xa6, 0x34, 0x80, 0xff, 0x10, 0x04, +0x00, 0x01, 0xa6, 0x35, 0x10, 0x04, 0x00, 0x02, 0x80, 0x1c, 0xdd, 0x23, 0x00, 0x5f, 0x80, 0x00, +0xa6, 0x30, 0xd8, 0x0d, 0x00, 0x5f, 0x80, 0x01, 0xa6, 0x31, 0xd8, 0x09, 0x00, 0x1f, 0x80, 0x02, +0xa6, 0x32, 0x40, 0x00, 0x80, 0x03, 0x5c, 0x00, 0x00, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x24, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x20, 0x01, 0x4d, +0x58, 0x21, 0x07, 0x50, 0xa1, 0x91, 0x81, 0x00, 0x81, 0x21, 0xce, 0x04, 0x80, 0x06, 0x80, 0x46, +0xd5, 0x2b, 0xa1, 0xf7, 0x83, 0x82, 0x84, 0xc0, 0xd5, 0x0a, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, +0x80, 0xde, 0x9d, 0xb1, 0xdd, 0x22, 0x80, 0x40, 0xc8, 0x08, 0xa1, 0xff, 0xbd, 0x01, 0x50, 0x13, +0x80, 0x08, 0x80, 0x09, 0xdf, 0xf3, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x07, 0x81, 0xd5, +0x4c, 0x70, 0x40, 0x0c, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xde, 0x50, 0x13, 0x80, 0x08, +0x80, 0x09, 0xdd, 0x22, 0x80, 0x40, 0x9d, 0xb1, 0x56, 0x31, 0x00, 0x01, 0x84, 0x20, 0x40, 0x03, +0x8c, 0x1a, 0x40, 0x00, 0x8c, 0x1b, 0x14, 0x04, 0x00, 0x01, 0x80, 0x08, 0x10, 0x24, 0x00, 0x08, +0xb6, 0xc8, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, +0x46, 0xf0, 0x01, 0x41, 0x04, 0x77, 0x80, 0xaf, 0xc7, 0x2f, 0xa6, 0x3e, 0x84, 0xaf, 0xd8, 0x2c, +0x85, 0x00, 0x50, 0x6f, 0x80, 0x04, 0x87, 0x81, 0x81, 0x48, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, +0x80, 0xdf, 0x80, 0x27, 0x80, 0x06, 0xdd, 0x22, 0x00, 0x03, 0x00, 0x08, 0x84, 0xaf, 0xa0, 0x71, +0xd0, 0x1b, 0x84, 0xa1, 0x11, 0xc3, 0x80, 0x07, 0xd8, 0x0f, 0xa0, 0xce, 0x80, 0x40, 0xc3, 0x09, +0xb4, 0x07, 0xb6, 0x03, 0xa0, 0x0e, 0xa4, 0x7a, 0xac, 0x42, 0x10, 0xa3, 0x80, 0x07, 0xd5, 0x07, +0xa8, 0x7a, 0xa9, 0xce, 0xd5, 0x04, 0x14, 0x83, 0x80, 0x02, 0x80, 0x48, 0xa0, 0x3b, 0xae, 0xbe, +0xc0, 0x03, 0x80, 0xe0, 0xd5, 0xdb, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x96, 0x00, +0xa6, 0x4d, 0xc0, 0x07, 0x40, 0x00, 0x98, 0x09, 0x56, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x01, +0xdd, 0x9e, 0xc0, 0x19, 0xc1, 0x18, 0x46, 0x50, 0x01, 0x49, 0x58, 0x52, 0x8e, 0xbc, 0xd9, 0x04, +0x50, 0x22, 0xff, 0xec, 0xd5, 0x07, 0x9d, 0x6c, 0xd9, 0x0e, 0x46, 0x20, 0x01, 0x49, 0x58, 0x21, +0x0e, 0xb0, 0x4c, 0x01, 0x40, 0x09, 0xb4, 0x21, 0xb4, 0x21, 0x40, 0x00, 0x80, 0x03, 0x5c, 0x00, +0x00, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x50, +0x01, 0x49, 0x58, 0x52, 0x8e, 0xa8, 0xd8, 0x04, 0x50, 0x60, 0x00, 0x14, 0xd5, 0x0e, 0x46, 0x10, +0x01, 0x49, 0x58, 0x10, 0x8e, 0xb0, 0x40, 0x30, 0x04, 0x03, 0x50, 0x20, 0x80, 0x10, 0x84, 0x20, +0x40, 0x61, 0x0c, 0x1a, 0x40, 0x60, 0x8c, 0x1b, 0x80, 0x26, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, +0x8f, 0xb4, 0xdd, 0x2f, 0x40, 0x60, 0x00, 0x1a, 0x80, 0x06, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x80, 0x40, 0x80, 0x61, 0xc0, 0x1a, 0xc1, 0x19, 0xa6, 0x0d, 0x9d, 0x14, 0x10, 0x01, +0x00, 0x0a, 0x50, 0x00, 0x80, 0x08, 0x3a, 0x00, 0x04, 0x00, 0xaa, 0x21, 0x46, 0x00, 0x04, 0x90, +0xac, 0x60, 0xa6, 0xdf, 0x10, 0x31, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x0e, 0xb6, 0x02, 0x46, 0xf0, +0x01, 0x13, 0x00, 0x07, 0x84, 0xba, 0x10, 0x01, 0x00, 0x0b, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, +0x01, 0x49, 0x58, 0x10, 0x8e, 0xa4, 0x00, 0x20, 0x80, 0x22, 0xca, 0x1f, 0x00, 0x30, 0x80, 0x20, +0xc3, 0x1c, 0xa6, 0xc0, 0x5c, 0xf1, 0x80, 0x65, 0xe8, 0x1a, 0xa7, 0x01, 0x5c, 0xf2, 0x00, 0x65, +0xe8, 0x16, 0xa6, 0x02, 0x5c, 0xf0, 0x00, 0x65, 0xe8, 0x12, 0x84, 0xa5, 0x42, 0x42, 0x14, 0x24, +0x44, 0x50, 0x00, 0xcc, 0x42, 0x00, 0x14, 0x24, 0x12, 0x30, 0x80, 0x12, 0x12, 0x00, 0x80, 0x14, +0x12, 0x40, 0x80, 0x13, 0x80, 0x02, 0xd5, 0x05, 0x84, 0x0c, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x12, +0xdd, 0x9e, 0x96, 0x00, 0x96, 0x48, 0xe6, 0x04, 0xe8, 0x1f, 0xe6, 0x22, 0xe8, 0x1d, 0x46, 0xf0, +0x01, 0x49, 0x00, 0x27, 0x8e, 0xc4, 0xc2, 0x1b, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x57, 0x8e, 0xc5, +0xd0, 0x16, 0xc0, 0x08, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x17, 0x81, 0x7a, 0x54, 0x10, 0x80, 0x30, +0xc9, 0x0e, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x17, 0x8e, 0xc6, 0xc1, 0x0b, 0xc8, 0x08, 0x84, 0x02, +0x4c, 0x10, 0x40, 0x08, 0xd5, 0x04, 0x44, 0x00, 0x00, 0x20, 0xd5, 0x04, 0x84, 0x0c, 0xd5, 0x02, +0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x01, 0x49, 0x58, 0x63, +0x0e, 0xa4, 0x84, 0x00, 0x10, 0x03, 0x00, 0x2a, 0x10, 0x03, 0x00, 0x22, 0x10, 0x03, 0x00, 0x21, +0x04, 0x03, 0x00, 0x16, 0xdd, 0x20, 0x84, 0x00, 0x14, 0x03, 0x00, 0x0d, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe0, 0x00, 0xa0, 0x00, 0x0a, 0x00, 0x80, 0x00, 0x00, +0x80, 0xe0, 0x80, 0x2a, 0x80, 0x08, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x80, 0xc4, 0xdd, 0x2f, +0x80, 0xc0, 0xc8, 0x5a, 0x4e, 0x83, 0x00, 0x1e, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x27, 0x8e, 0xc6, +0x84, 0xa1, 0xd2, 0x04, 0x44, 0x60, 0x00, 0x1f, 0xd5, 0x4f, 0x84, 0x42, 0x46, 0xf0, 0x01, 0x49, +0x10, 0x27, 0x8e, 0xc6, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0xe4, 0x80, 0x20, 0xdd, 0x22, +0x80, 0xc0, 0xc0, 0x42, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x81, 0x18, 0xdd, 0x2f, 0xd5, 0x3c, +0xa6, 0xba, 0xa6, 0x7e, 0xa6, 0xf9, 0xa6, 0x3d, 0x40, 0x21, 0x20, 0x08, 0x40, 0x10, 0xa0, 0x08, +0x85, 0x21, 0x98, 0x93, 0x98, 0x48, 0x40, 0x34, 0xa0, 0x06, 0x12, 0x1f, 0x80, 0x02, 0x10, 0x6f, +0x80, 0x18, 0x10, 0x3f, 0x80, 0x14, 0x12, 0x2f, 0x80, 0x05, 0x00, 0x73, 0x80, 0x09, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x83, 0xe3, 0x10, 0x7f, 0x80, 0x15, 0x80, 0x1f, 0xdd, 0x21, 0x80, 0xc0, +0xc8, 0x1b, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0xe4, 0x80, 0x26, 0x80, 0x09, 0xdd, 0x22, +0x80, 0xc0, 0xc8, 0x12, 0x46, 0x70, 0x01, 0x49, 0x58, 0x73, 0x8e, 0xa4, 0x04, 0x03, 0x80, 0x16, +0xdd, 0x20, 0x10, 0x83, 0x80, 0x21, 0x10, 0xa3, 0x80, 0x30, 0x10, 0x93, 0x80, 0x22, 0x10, 0x63, +0x80, 0x2a, 0x14, 0x63, 0x80, 0x0d, 0x80, 0x06, 0xec, 0x20, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x81, 0x00, 0x9d, 0xcc, 0xc0, 0x61, 0xc1, 0x60, +0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa8, 0x4c, 0x80, 0x00, 0x06, 0x50, 0x10, 0x00, 0x08, +0x4c, 0x80, 0xc0, 0x57, 0xb4, 0xc8, 0x51, 0xc3, 0x80, 0x0a, 0x46, 0xa0, 0x00, 0xc8, 0x58, 0xa5, +0x0b, 0x6c, 0xd5, 0x4c, 0xa7, 0x79, 0x00, 0x03, 0x00, 0x0e, 0xd8, 0x47, 0xa7, 0x7e, 0xa6, 0x7d, +0x00, 0x43, 0x00, 0x0a, 0x00, 0x03, 0x00, 0x09, 0x40, 0x52, 0xc0, 0x08, 0x40, 0x10, 0xa0, 0x08, +0x40, 0x42, 0x40, 0x08, 0x40, 0x00, 0x20, 0x08, 0xa6, 0xfc, 0x00, 0x23, 0x00, 0x08, 0x98, 0x69, +0x98, 0x20, 0x98, 0x4b, 0x98, 0x02, 0x4c, 0x10, 0x40, 0x31, 0xa7, 0x7f, 0x00, 0x03, 0x00, 0x0b, +0xd8, 0x2c, 0x00, 0x13, 0x80, 0x09, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x33, 0x80, 0x08, 0x00, 0x23, +0x00, 0x0c, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x00, 0x20, 0x08, 0x98, 0x4b, 0x98, 0x02, 0x97, 0x49, +0x96, 0x01, 0xd8, 0x1b, 0x46, 0x50, 0x01, 0x49, 0x58, 0x52, 0x8e, 0xa8, 0x4c, 0x82, 0xc0, 0x09, +0xa1, 0x75, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xb6, 0xd8, 0x0f, 0xd5, 0x12, 0xa6, 0x38, +0x84, 0xa4, 0xd0, 0x0b, 0xa7, 0x7a, 0x00, 0x23, 0x00, 0x14, 0xda, 0x07, 0x50, 0x03, 0x00, 0x15, +0x80, 0x3c, 0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x05, 0xb4, 0xc6, 0x4c, 0x64, 0x7f, 0xb5, 0x84, 0xc0, +0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x07, +0x82, 0xe0, 0xdd, 0x9e, 0x92, 0x00, 0x44, 0x20, 0x00, 0x34, 0x96, 0x00, 0x42, 0x20, 0x08, 0x24, +0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x98, 0x90, 0xa6, 0x10, 0xc0, 0x03, 0x84, 0x01, +0xd5, 0x36, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x47, 0x82, 0xe1, 0x9f, 0x21, 0x46, 0xf0, 0x01, 0x40, +0x10, 0x47, 0x82, 0xe1, 0x84, 0x61, 0xae, 0xd0, 0xa6, 0xc9, 0xa7, 0x08, 0x40, 0x31, 0xa0, 0x08, +0x98, 0xdc, 0xac, 0xd1, 0xa6, 0xcb, 0xa7, 0x0a, 0x40, 0x31, 0xa0, 0x08, 0x98, 0xdc, 0xac, 0xd2, +0xa6, 0xcc, 0xae, 0xd6, 0xa6, 0xcd, 0xae, 0xd7, 0xa6, 0xce, 0x10, 0x31, 0x00, 0x08, 0x00, 0x30, +0x80, 0x08, 0xa7, 0x0f, 0x40, 0x31, 0xa0, 0x08, 0x98, 0xdc, 0xac, 0xd5, 0x00, 0x30, 0x80, 0x09, +0x10, 0x31, 0x00, 0x0c, 0x00, 0x30, 0x80, 0x0a, 0x10, 0x31, 0x00, 0x0d, 0x00, 0x40, 0x80, 0x0c, +0x00, 0x30, 0x80, 0x0b, 0x40, 0x12, 0x20, 0x08, 0x98, 0x4b, 0xac, 0x57, 0xdd, 0x9e, 0x84, 0x40, +0x80, 0x02, 0x84, 0x61, 0xb4, 0x81, 0x84, 0xbf, 0xdc, 0x06, 0x40, 0x41, 0x88, 0x0c, 0x40, 0x02, +0x00, 0x04, 0x96, 0x00, 0x9c, 0x91, 0x84, 0xa7, 0x9c, 0x4c, 0xda, 0xf5, 0xdd, 0x9e, 0xa6, 0x86, +0x84, 0x61, 0x96, 0x48, 0xa4, 0x01, 0x4c, 0x21, 0xc0, 0x0b, 0x54, 0x00, 0x00, 0x7f, 0x40, 0x10, +0x80, 0x02, 0x40, 0x00, 0x80, 0x03, 0x40, 0x00, 0x0c, 0x06, 0xd5, 0x13, 0x96, 0x00, 0x54, 0x20, +0x00, 0x07, 0x40, 0x50, 0x88, 0x02, 0xd2, 0x03, 0x84, 0x00, 0xd5, 0x0b, 0x54, 0x00, 0x00, 0x78, +0xc8, 0x03, 0x84, 0x01, 0xd5, 0x06, 0x40, 0x00, 0x80, 0x02, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, +0xdd, 0x9e, 0x96, 0x49, 0x96, 0x90, 0x96, 0xd8, 0xc1, 0x0d, 0x84, 0x21, 0x4c, 0x30, 0x80, 0x10, +0x40, 0x20, 0x88, 0x0c, 0xb4, 0x20, 0x40, 0x21, 0x08, 0x05, 0x40, 0x20, 0x88, 0x02, 0xb6, 0x40, +0xd5, 0x06, 0x84, 0x41, 0x4c, 0x31, 0x40, 0x03, 0x84, 0x3f, 0xb6, 0x20, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xec, 0x81, 0x00, 0xa4, 0x01, 0x84, 0x7f, 0x96, 0x48, 0x54, 0x00, 0x00, 0x40, +0xf3, 0x83, 0xf2, 0x81, 0xb6, 0x3f, 0xc0, 0x34, 0x04, 0x74, 0x00, 0x0a, 0x50, 0xa4, 0x00, 0x28, +0x4c, 0x75, 0x40, 0x05, 0x84, 0x00, 0xf0, 0x83, 0xd5, 0x2b, 0x85, 0x20, 0x50, 0x6f, 0x80, 0x0c, +0x47, 0xc0, 0x00, 0xc9, 0x59, 0xce, 0x03, 0xf4, 0xa7, 0x3c, 0xb4, 0x1f, 0xe2, 0x04, 0xe9, 0x0e, +0x50, 0x13, 0x80, 0x22, 0xf2, 0x01, 0x80, 0x61, 0x9c, 0x3d, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, +0x8b, 0x88, 0xdd, 0x2f, 0xc0, 0x03, 0x84, 0x61, 0xd5, 0x02, 0x84, 0x60, 0x02, 0x14, 0x00, 0x02, +0x80, 0x49, 0x54, 0x10, 0x80, 0x40, 0x80, 0x06, 0xdd, 0x3c, 0xf0, 0x03, 0x84, 0x3f, 0x8d, 0x21, +0x4c, 0x00, 0x80, 0x07, 0xb4, 0xe7, 0x54, 0x94, 0x80, 0xff, 0x4c, 0x75, 0x7f, 0xdf, 0xf0, 0x03, +0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, +0x81, 0x00, 0xa4, 0x01, 0x84, 0x7f, 0x96, 0x48, 0x54, 0x00, 0x00, 0x20, 0xf3, 0x83, 0xf2, 0x81, +0xb6, 0x3f, 0xc0, 0x35, 0x04, 0x74, 0x00, 0x09, 0x50, 0xa4, 0x00, 0x24, 0x4c, 0x75, 0x40, 0x05, +0x84, 0x00, 0xf0, 0x83, 0xd5, 0x2c, 0x85, 0x20, 0x50, 0x6f, 0x80, 0x0c, 0x47, 0xc0, 0x00, 0xc9, +0x59, 0xce, 0x03, 0xf4, 0x00, 0x43, 0x80, 0x3e, 0xb4, 0x1f, 0xe2, 0x04, 0xe9, 0x0e, 0x50, 0x13, +0x80, 0x21, 0xf2, 0x01, 0x80, 0x61, 0x9c, 0x3c, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, +0xdd, 0x2f, 0xc0, 0x03, 0x84, 0x61, 0xd5, 0x02, 0x84, 0x60, 0x02, 0x14, 0x00, 0x02, 0x80, 0x49, +0x54, 0x10, 0x80, 0x20, 0x80, 0x06, 0xdd, 0x3c, 0xf0, 0x03, 0x84, 0x3f, 0x8d, 0x21, 0x4c, 0x00, +0x80, 0x07, 0xb4, 0xe7, 0x54, 0x94, 0x80, 0xff, 0x4c, 0x75, 0x7f, 0xde, 0xf0, 0x03, 0xec, 0x14, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x81, 0x00, 0xa4, 0x01, +0x84, 0x7f, 0x54, 0x00, 0x00, 0x10, 0xf3, 0x83, 0xf2, 0x81, 0x55, 0xc0, 0x80, 0xff, 0xc0, 0x32, +0x04, 0x74, 0x00, 0x08, 0x50, 0xa4, 0x00, 0x20, 0x4c, 0x75, 0x40, 0x05, 0x84, 0x00, 0xf0, 0x83, +0xd5, 0x29, 0x85, 0x20, 0x50, 0x6f, 0x80, 0x0c, 0x00, 0x53, 0x80, 0x21, 0x4c, 0x5e, 0x40, 0x0d, +0xf1, 0x01, 0x80, 0x5c, 0x9c, 0x3c, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x6c, 0xdd, 0x2f, +0xc0, 0x03, 0x84, 0x61, 0xd5, 0x02, 0x84, 0x60, 0x02, 0x04, 0x00, 0x02, 0x80, 0x49, 0x54, 0x10, +0x00, 0x10, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x83, 0xf4, 0xdd, 0x2f, 0xf0, 0x03, +0x84, 0x3f, 0x8d, 0x21, 0x4c, 0x00, 0x80, 0x07, 0xb4, 0xe7, 0x54, 0x94, 0x80, 0xff, 0x4c, 0x75, +0x7f, 0xdd, 0xf0, 0x03, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xec, 0x81, 0x00, 0xa4, 0x01, 0x84, 0x7f, 0x54, 0x00, 0x00, 0x08, 0xf3, 0x83, +0xf2, 0x81, 0x55, 0xc0, 0x80, 0xff, 0xc0, 0x34, 0x04, 0x74, 0x00, 0x07, 0x50, 0xa4, 0x00, 0x1c, +0x4c, 0x75, 0x40, 0x05, 0x84, 0x00, 0xf0, 0x83, 0xd5, 0x2b, 0x85, 0x20, 0x50, 0x6f, 0x80, 0x0c, +0x00, 0x03, 0x80, 0x24, 0x4c, 0x0e, 0x40, 0x10, 0x50, 0x13, 0x80, 0x14, 0xf2, 0x01, 0x80, 0x61, +0x80, 0x9c, 0x9c, 0x3c, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, 0xdd, 0x2f, 0xc0, 0x03, +0x84, 0x61, 0xd5, 0x02, 0x84, 0x60, 0x02, 0x14, 0x00, 0x02, 0x80, 0x49, 0x80, 0x06, 0x54, 0x10, +0x80, 0x08, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x83, 0xf4, 0xdd, 0x2f, 0xf5, 0x03, 0x84, 0x1f, +0x8d, 0x21, 0xd0, 0x06, 0xb4, 0xe7, 0x54, 0x94, 0x80, 0xff, 0x4c, 0x75, 0x7f, 0xdb, 0xf0, 0x03, +0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, +0x81, 0x00, 0xa4, 0x01, 0x84, 0x7f, 0x54, 0x00, 0x00, 0x04, 0xf3, 0x83, 0xf2, 0x81, 0x55, 0xc0, +0x80, 0xff, 0xc0, 0x34, 0x04, 0x74, 0x00, 0x06, 0x50, 0xa4, 0x00, 0x18, 0x4c, 0x75, 0x40, 0x05, +0x84, 0x00, 0xf0, 0x83, 0xd5, 0x2b, 0x85, 0x20, 0x50, 0x6f, 0x80, 0x0c, 0x00, 0x03, 0x80, 0x24, +0x4c, 0x0e, 0x40, 0x10, 0x50, 0x13, 0x80, 0x14, 0xf2, 0x01, 0x80, 0x61, 0x80, 0x9c, 0x9c, 0x3c, +0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, 0xdd, 0x2f, 0xc0, 0x03, 0x84, 0x61, 0xd5, 0x02, +0x84, 0x60, 0x02, 0x14, 0x00, 0x02, 0x80, 0x49, 0x80, 0x06, 0x54, 0x10, 0x80, 0x04, 0x46, 0xf0, +0x00, 0xc9, 0x58, 0xf7, 0x83, 0xf4, 0xdd, 0x2f, 0xf5, 0x03, 0x84, 0x1f, 0x8d, 0x21, 0xd0, 0x06, +0xb4, 0xe7, 0x54, 0x94, 0x80, 0xff, 0x4c, 0x75, 0x7f, 0xdb, 0xf0, 0x03, 0xec, 0x14, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x81, 0x00, 0xa4, 0x01, +0x84, 0x7f, 0x96, 0x90, 0x96, 0x04, 0xf3, 0x83, 0xb6, 0x3f, 0xf2, 0x81, 0xc0, 0x33, 0x04, 0x74, +0x00, 0x04, 0x50, 0xa4, 0x00, 0x10, 0x4c, 0x75, 0x40, 0x05, 0x84, 0x00, 0xf0, 0x83, 0xd5, 0x2a, +0x85, 0x20, 0x50, 0x6f, 0x80, 0x0c, 0x47, 0xc0, 0x00, 0xc9, 0x59, 0xce, 0x03, 0xf4, 0xb4, 0x3f, +0x9c, 0x3c, 0x84, 0x46, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x6c, 0xdd, 0x2f, 0xc8, 0x03, +0x80, 0x60, 0xd5, 0x08, 0x00, 0x33, 0x80, 0x0a, 0xf0, 0x01, 0x40, 0x31, 0x80, 0x03, 0x5c, 0x31, +0x80, 0x01, 0x02, 0x04, 0x00, 0x02, 0x80, 0x49, 0x96, 0x44, 0x80, 0x06, 0xdd, 0x3c, 0xf1, 0x03, +0x84, 0x7f, 0x8d, 0x21, 0x4c, 0x11, 0x80, 0x07, 0xb4, 0xe7, 0x54, 0x94, 0x80, 0xff, 0x4c, 0x75, +0x7f, 0xe0, 0xf0, 0x03, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xdc, 0x80, 0x61, 0x83, 0x82, 0xa7, 0x1e, 0xa6, 0x8d, 0xb4, 0xdc, 0x8c, 0x28, +0x80, 0xe0, 0xf4, 0x82, 0x50, 0xa1, 0x80, 0x0e, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x86, 0xd8, +0xdd, 0x2f, 0x40, 0x10, 0x18, 0x04, 0xb6, 0x3c, 0x50, 0x0e, 0x00, 0x0c, 0x84, 0x3f, 0xb9, 0x81, +0x50, 0x3e, 0x00, 0x18, 0x50, 0x4e, 0x00, 0x14, 0xf0, 0x83, 0x50, 0x0e, 0x00, 0x08, 0x15, 0xcf, +0x80, 0x07, 0xf3, 0x84, 0xf4, 0x85, 0xf0, 0x86, 0x83, 0x87, 0x48, 0x00, 0x00, 0xa2, 0x80, 0xea, +0x08, 0x13, 0x80, 0x02, 0x00, 0x35, 0x00, 0x01, 0x9e, 0x49, 0x54, 0x90, 0x80, 0xff, 0xe6, 0x6a, +0xe8, 0x0c, 0xe6, 0x68, 0xe8, 0x44, 0xe6, 0x66, 0xe8, 0x27, 0xe6, 0x64, 0xe8, 0x23, 0xe6, 0x62, +0x4e, 0xf3, 0x00, 0x83, 0x48, 0x00, 0x00, 0x91, 0x44, 0x40, 0x00, 0x1f, 0x4c, 0x32, 0x00, 0x19, +0x5c, 0xf1, 0x80, 0x20, 0xe8, 0x0d, 0x44, 0x00, 0x00, 0x15, 0x4c, 0x30, 0x00, 0x41, 0x9d, 0x01, +0x4c, 0x32, 0x00, 0x56, 0x9e, 0x01, 0x4c, 0x30, 0x40, 0x70, 0x48, 0x00, 0x00, 0x80, 0x5c, 0xf1, +0x80, 0x22, 0xe9, 0x4d, 0x44, 0x40, 0x00, 0xff, 0x4c, 0x32, 0x40, 0x67, 0xd5, 0x57, 0x85, 0x04, +0xd5, 0x40, 0x85, 0x04, 0xd5, 0x12, 0x44, 0x80, 0x00, 0x10, 0xd5, 0x0f, 0xf3, 0x06, 0x8b, 0x28, +0xb4, 0xc3, 0xf5, 0x81, 0x54, 0x94, 0x80, 0xff, 0xdd, 0x25, 0xf4, 0x06, 0x40, 0x30, 0x18, 0x04, +0xb6, 0x64, 0x88, 0xe8, 0xf5, 0x01, 0xd5, 0x05, 0x46, 0x50, 0x00, 0xc9, 0x58, 0x52, 0x86, 0x4c, +0x80, 0x47, 0x80, 0x1c, 0x80, 0x28, 0x4e, 0x93, 0xff, 0xeb, 0xd5, 0x46, 0xf0, 0x07, 0x80, 0x29, +0x50, 0x60, 0x00, 0x10, 0x80, 0x47, 0x80, 0x1c, 0xb4, 0xe6, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, +0x85, 0x38, 0xdd, 0x2f, 0x40, 0x10, 0x1c, 0x04, 0xb6, 0x26, 0xd5, 0x36, 0x44, 0x80, 0x00, 0x10, +0xd5, 0x10, 0xf3, 0x03, 0x8b, 0x28, 0xb4, 0xc3, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x85, 0xc0, +0xdd, 0x2f, 0x40, 0x30, 0x18, 0x04, 0xf0, 0x03, 0x54, 0x94, 0x80, 0xff, 0xb6, 0x60, 0x88, 0xe8, +0x80, 0x47, 0x80, 0x1c, 0x80, 0x28, 0x4e, 0x93, 0xff, 0xee, 0xd5, 0x1e, 0xf3, 0x04, 0x80, 0x29, +0xb4, 0xc3, 0x80, 0x47, 0x80, 0x1c, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x84, 0x20, 0xdd, 0x2f, +0xf4, 0x04, 0x40, 0x10, 0x18, 0x04, 0xb6, 0x24, 0xd5, 0x0f, 0xf0, 0x05, 0x80, 0x29, 0xb4, 0xc0, +0x80, 0x47, 0x80, 0x1c, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x84, 0xac, 0xdd, 0x2f, 0xf3, 0x05, +0x40, 0x10, 0x18, 0x04, 0xb6, 0x23, 0x00, 0x15, 0x00, 0x00, 0xf4, 0x02, 0x9e, 0x49, 0x96, 0x48, +0x52, 0x30, 0xff, 0xfe, 0x98, 0xa3, 0x96, 0x90, 0x9c, 0x4a, 0xf2, 0x82, 0x89, 0x41, 0xf0, 0x02, +0x4e, 0x03, 0xff, 0x5f, 0xd5, 0x05, 0x85, 0x02, 0xd5, 0xa0, 0x85, 0x02, 0xd5, 0xca, 0xec, 0x24, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x01, 0x49, 0x58, 0x63, +0x0e, 0xa4, 0x00, 0x03, 0x00, 0x20, 0xc0, 0x13, 0x00, 0x03, 0x00, 0x21, 0x84, 0x22, 0x4c, 0x00, +0x80, 0x0a, 0x84, 0xa3, 0xd0, 0x04, 0x84, 0xa1, 0xd8, 0x1c, 0xd5, 0x12, 0x04, 0x03, 0x00, 0x1b, +0xdd, 0x20, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xc5, 0xd5, 0x12, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x85, 0x3c, 0xc0, 0x05, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x0c, 0xd5, 0x04, 0x04, 0x03, +0x00, 0x1b, 0xd5, 0x06, 0x04, 0x03, 0x00, 0x1b, 0xdd, 0x20, 0x04, 0x03, 0x00, 0x1c, 0xdd, 0x20, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x81, 0x03, 0x81, 0x21, +0x96, 0xd0, 0xb4, 0xc1, 0x51, 0xc4, 0x00, 0x08, 0x46, 0xa0, 0x00, 0xc8, 0x58, 0xa5, 0x0b, 0x6c, +0xd5, 0x0e, 0xa7, 0x79, 0xdb, 0x0b, 0xf3, 0x81, 0x4b, 0xe0, 0x28, 0x01, 0xf3, 0x01, 0xc0, 0x06, +0x00, 0x53, 0x80, 0x08, 0x00, 0x04, 0x00, 0x05, 0xd0, 0x0b, 0xb4, 0xc6, 0x50, 0x73, 0x7f, 0xec, +0x50, 0x03, 0x7f, 0xee, 0x80, 0x3c, 0x84, 0x46, 0x4c, 0x64, 0xff, 0xed, 0x84, 0xe0, 0x80, 0x07, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0xb4, 0x20, 0x40, 0x00, 0x80, 0x03, +0x5c, 0x00, 0x00, 0x01, 0xdd, 0x9e, 0xb6, 0x00, 0xdd, 0x9e, 0xa0, 0xc2, 0x96, 0x49, 0x96, 0x91, +0x38, 0x21, 0x85, 0x09, 0x44, 0x30, 0x00, 0x18, 0xa0, 0x03, 0x42, 0x01, 0x0c, 0x73, 0xac, 0x43, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x4c, 0x00, 0xc0, 0x04, 0x84, 0x01, 0xd5, 0x09, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x41, 0xdd, 0x22, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x01, 0x98, 0x00, 0x9c, 0x01, +0x96, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x01, 0x9c, 0x01, 0x98, 0x00, 0x96, 0x01, 0xdd, 0x9e, +0x92, 0x00, 0x96, 0x49, 0xc1, 0x0a, 0xa4, 0x01, 0xe2, 0x20, 0xe8, 0x07, 0x9e, 0x49, 0x84, 0x02, +0x40, 0x00, 0x80, 0x36, 0x96, 0x01, 0xd5, 0x03, 0x44, 0x00, 0xff, 0xff, 0xdd, 0x9e, 0xa0, 0x82, +0x96, 0x49, 0x38, 0x21, 0x05, 0x01, 0xa0, 0x03, 0x44, 0x10, 0x00, 0x18, 0x42, 0x01, 0x04, 0x73, +0xa0, 0x03, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x97, 0xc9, 0x81, 0x00, 0x80, 0x07, +0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8a, 0x0c, 0xdd, 0x2f, 0x02, 0x94, 0x00, 0x01, 0x80, 0xc0, +0xe2, 0x09, 0xe9, 0x04, 0x44, 0x60, 0xff, 0xff, 0xd5, 0x20, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc9, +0x58, 0xf7, 0x8a, 0x18, 0xdd, 0x2f, 0x80, 0xe0, 0xe2, 0x09, 0xe8, 0x17, 0x80, 0x26, 0x46, 0x90, +0x00, 0xc9, 0x58, 0x94, 0x8a, 0x40, 0x80, 0x08, 0x4b, 0xe0, 0x24, 0x01, 0x81, 0x40, 0x80, 0x27, +0x80, 0x08, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x20, 0x80, 0x0a, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, +0x89, 0xe4, 0xdd, 0x2f, 0x40, 0x63, 0x80, 0x1a, 0x80, 0x06, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x98, 0x08, 0x94, 0x04, 0x92, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, +0x01, 0x38, 0x04, 0x73, 0x02, 0x3c, 0x81, 0x00, 0x99, 0xcf, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, +0x82, 0x41, 0x80, 0x27, 0xdd, 0x22, 0xc0, 0x06, 0x40, 0x03, 0xa0, 0x01, 0x94, 0x04, 0x92, 0x04, +0xd5, 0x03, 0x04, 0x03, 0x02, 0x3c, 0x92, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0xa4, 0x81, 0x96, 0x49, 0xe2, 0x22, 0xe9, 0x04, 0x44, 0x30, 0x00, 0x11, +0xd5, 0x1c, 0xa0, 0x82, 0x38, 0x21, 0x05, 0x01, 0xca, 0x04, 0x44, 0x30, 0x00, 0x22, 0xd5, 0x15, +0xa4, 0xc2, 0xe2, 0x43, 0xe9, 0x04, 0x44, 0x30, 0x00, 0x33, 0xd5, 0x0f, 0xa0, 0x03, 0x44, 0x30, +0x00, 0x18, 0x42, 0x01, 0x0c, 0x73, 0xb4, 0x40, 0xc2, 0x04, 0x44, 0x30, 0x00, 0x44, 0xd5, 0x05, +0xa5, 0x43, 0xd1, 0x0c, 0x44, 0x30, 0x00, 0x55, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, +0x84, 0x21, 0x84, 0x06, 0x44, 0x20, 0x70, 0xb3, 0xdd, 0x24, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x40, 0x80, 0x80, 0x13, 0x46, 0x20, 0x00, 0xc9, 0x58, 0x21, +0x0a, 0x58, 0x80, 0x28, 0x81, 0x42, 0x80, 0xe0, 0xdd, 0x22, 0x46, 0x90, 0x00, 0xc9, 0x58, 0x94, +0x89, 0xcc, 0x80, 0xc0, 0x80, 0x68, 0xd5, 0x12, 0xa1, 0x3a, 0x38, 0x22, 0x19, 0x01, 0x38, 0x82, +0x0d, 0x01, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x26, 0x80, 0x07, 0x80, 0x48, 0x4b, 0xe0, 0x24, 0x01, +0x80, 0x26, 0x80, 0x07, 0xdd, 0x2a, 0x80, 0x66, 0x80, 0xc0, 0x44, 0x50, 0xff, 0xff, 0x80, 0x23, +0x80, 0x07, 0xde, 0xeb, 0x80, 0x03, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0xa4, 0x81, 0x97, 0xc9, 0x80, 0xc0, 0xe2, 0xe2, 0xe8, 0x3e, 0x46, 0x80, +0x01, 0x38, 0x04, 0x24, 0x02, 0x40, 0x80, 0x27, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, +0x82, 0x3e, 0xa0, 0xf2, 0x80, 0x27, 0x80, 0x06, 0x38, 0x91, 0x9d, 0x01, 0xdd, 0x22, 0xa4, 0x71, +0x80, 0xe0, 0x9e, 0x49, 0x4c, 0x00, 0x80, 0x1a, 0x04, 0x24, 0x02, 0x40, 0x96, 0x49, 0x80, 0x06, +0xdd, 0x22, 0xa4, 0x31, 0xa0, 0x72, 0x9e, 0x01, 0x38, 0x20, 0x81, 0x01, 0x80, 0x06, 0x80, 0x27, +0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x89, 0xcc, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, +0x82, 0x3d, 0x80, 0x27, 0x80, 0x06, 0xdd, 0x22, 0xa4, 0x31, 0xa0, 0xb2, 0x9e, 0x01, 0x84, 0x20, +0x38, 0x11, 0x01, 0x09, 0x44, 0x20, 0x00, 0x18, 0xa4, 0x71, 0xa0, 0x33, 0x9e, 0x49, 0x42, 0x04, +0x88, 0x73, 0xac, 0x71, 0x84, 0x3f, 0xac, 0x43, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x44, +0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x80, 0xc1, 0x80, 0xa2, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x77, 0x82, 0x46, 0x97, 0x18, 0x80, 0x20, +0x80, 0x46, 0x80, 0x65, 0x46, 0x00, 0x01, 0x3a, 0x58, 0x00, 0x00, 0x60, 0xdd, 0x27, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x27, 0x82, 0x47, 0x80, 0x20, 0x46, 0x00, 0x01, 0x3a, 0x58, 0x00, 0x00, 0x60, 0xdd, 0x22, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x00, 0x46, 0xf0, 0x01, 0x4a, +0x10, 0x07, 0x8f, 0x7c, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xf4, 0x46, 0xf0, 0x01, 0x4a, +0x10, 0x07, 0x8f, 0x7d, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xe4, 0x50, 0x6f, 0x80, 0x04, +0x97, 0xc9, 0x54, 0x90, 0x00, 0xff, 0x40, 0x81, 0x00, 0x10, 0x84, 0x20, 0x44, 0x20, 0x00, 0x14, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0x84, 0x01, 0xae, 0x30, +0x40, 0x13, 0xa0, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4d, 0x50, 0x2f, 0x80, 0x09, +0xae, 0x73, 0x10, 0x93, 0x00, 0x01, 0x10, 0x83, 0x00, 0x04, 0x9a, 0x96, 0xaf, 0xf2, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xf5, 0x80, 0x26, 0x96, 0x90, 0xdd, 0x23, 0xec, 0x1c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, 0x01, 0x4a, 0x00, 0x27, 0x8f, 0x7d, 0x96, 0x00, +0x4c, 0x20, 0x00, 0x0a, 0xe6, 0x02, 0xe8, 0x07, 0x46, 0xf0, 0x01, 0x4a, 0x10, 0x07, 0x8f, 0x7d, +0x84, 0x00, 0xd5, 0x02, 0x84, 0x0c, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xec, +0x80, 0xc0, 0xa0, 0x04, 0x4e, 0x07, 0x00, 0x07, 0xa0, 0xb5, 0x40, 0x21, 0x00, 0x16, 0x96, 0x92, +0xd5, 0x1d, 0x50, 0x7f, 0x80, 0x0c, 0x84, 0x00, 0xb6, 0x07, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, +0x82, 0x51, 0xa4, 0x34, 0xdd, 0x21, 0x40, 0x20, 0x40, 0x09, 0x40, 0x10, 0x60, 0x09, 0x40, 0x30, +0x20, 0x09, 0x10, 0x3f, 0x80, 0x01, 0x10, 0x2f, 0x80, 0x02, 0x10, 0x1f, 0x80, 0x03, 0x10, 0x0f, +0x80, 0x00, 0xb4, 0x1f, 0xb6, 0x07, 0x20, 0x23, 0x80, 0x03, 0x84, 0x00, 0xa8, 0x35, 0xa8, 0x34, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4e, 0xa4, 0x74, 0xdd, 0x23, 0xec, 0x14, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x70, 0x01, 0x38, +0x04, 0x13, 0x82, 0x4a, 0x80, 0xc0, 0x8c, 0x0a, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x4e, 0xa4, 0x74, 0x20, 0x23, 0x00, 0x02, 0x84, 0x00, 0xdd, 0x23, 0x04, 0x13, 0x82, 0x4a, +0x50, 0x03, 0x00, 0x0c, 0xdd, 0x21, 0x84, 0x00, 0xae, 0x31, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x52, +0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x53, 0xdd, 0x21, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0xa6, 0x81, 0x96, 0x4a, 0xc2, 0x09, 0xa4, 0x86, 0xc2, 0x07, 0xa0, 0xc5, 0xa0, 0x84, +0x98, 0x59, 0x9c, 0x91, 0xa8, 0x84, 0xa8, 0x45, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x37, 0x89, 0xf4, 0x96, 0x8a, 0xc3, 0x09, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x37, 0x82, 0x55, 0x00, 0x10, 0x00, 0x20, 0x84, 0x01, 0xdd, 0x23, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x37, 0x89, 0xf4, 0x96, 0x8a, 0xc3, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x55, +0x00, 0x10, 0x00, 0x20, 0x84, 0x00, 0xdd, 0x23, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x84, 0x00, 0xdd, 0x9e, 0x46, 0xf0, 0x01, 0x4a, 0x00, 0x07, 0x8f, 0x7c, 0xdd, 0x9e, +0x92, 0x00, 0x84, 0x01, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x50, 0x61, 0x00, 0x0c, +0x00, 0x80, 0x80, 0x05, 0xb5, 0x26, 0xf0, 0x81, 0x80, 0x61, 0xa7, 0x5e, 0x50, 0x71, 0x80, 0x08, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x64, 0xb6, 0xbf, 0x81, 0x42, 0x80, 0x28, 0x80, 0x47, +0x51, 0xc1, 0x80, 0x0e, 0xdd, 0x24, 0x40, 0x10, 0x24, 0x04, 0xb6, 0x26, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x47, 0x82, 0x67, 0x50, 0x65, 0x00, 0x08, 0xf0, 0x01, 0x80, 0x28, 0x80, 0x47, 0xb4, 0xe6, +0xdd, 0x24, 0x40, 0x10, 0x1c, 0x04, 0xb6, 0x26, 0x50, 0x05, 0x00, 0x04, 0xb5, 0x3f, 0xf0, 0x82, +0x14, 0xaf, 0x80, 0x03, 0xd5, 0x2d, 0x08, 0x13, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x01, 0x9e, 0x49, +0x97, 0xc8, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x65, 0xf1, 0x03, 0x80, 0x66, 0xb5, 0x41, +0x80, 0x48, 0x80, 0x27, 0xdd, 0x24, 0x40, 0x40, 0x28, 0x04, 0xf0, 0x03, 0xb6, 0x80, 0x80, 0x66, +0xf0, 0x02, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x66, 0xb4, 0xc0, 0xf0, 0x01, 0x80, 0x48, +0x80, 0x27, 0xdd, 0x24, 0xf1, 0x02, 0x40, 0x20, 0x18, 0x04, 0x52, 0x43, 0xff, 0xfe, 0x40, 0x34, +0x90, 0x00, 0xb6, 0x41, 0x9c, 0x7a, 0x41, 0xce, 0x04, 0x00, 0x54, 0x91, 0x80, 0xff, 0x80, 0xdc, +0xf0, 0x01, 0x4e, 0x93, 0xff, 0xd2, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa0, 0xbc, 0xa6, 0x45, 0x54, 0x10, 0x80, 0x04, 0xc1, 0x12, 0xa1, 0x84, 0x50, 0x80, 0x00, 0x10, +0xd5, 0x08, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x68, 0xdd, 0x21, 0xc8, 0x08, 0xb4, 0xc6, +0x50, 0x03, 0x7f, 0xe8, 0x4c, 0x64, 0x7f, 0xf7, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x1f, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x01, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xd8, +0x80, 0xc0, 0x00, 0x00, 0x00, 0x16, 0x44, 0x50, 0x00, 0xff, 0xd0, 0x13, 0x00, 0x03, 0x00, 0x08, +0x50, 0x1f, 0x80, 0x04, 0x10, 0x03, 0x00, 0x47, 0x10, 0x03, 0x00, 0x17, 0x50, 0x03, 0x00, 0x10, +0xa8, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x6d, 0x80, 0x46, 0x84, 0x02, 0xdd, 0x23, +0x84, 0x1f, 0x10, 0x03, 0x00, 0x46, 0x10, 0x03, 0x00, 0x16, 0xec, 0x28, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0x3c, 0x46, 0x40, 0x01, 0x00, 0x46, 0x30, 0x01, 0x38, 0x46, 0x20, +0x04, 0x20, 0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x00, 0xc4, 0x58, 0x31, 0x88, 0x00, 0x84, 0xc4, +0x46, 0x10, 0x00, 0x9c, 0x46, 0xf0, 0x01, 0x03, 0x14, 0x67, 0x83, 0xb9, 0x58, 0x10, 0x8b, 0xe0, +0x84, 0xa0, 0xb6, 0x80, 0xa8, 0xc2, 0x44, 0x41, 0x58, 0x00, 0x44, 0x31, 0x78, 0x00, 0xa8, 0x84, +0x44, 0x20, 0x90, 0x00, 0xa9, 0x47, 0xa9, 0x01, 0xa8, 0xc3, 0xa8, 0x85, 0xa8, 0x46, 0x3a, 0x6f, +0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x6f, 0x40, 0x00, +0x80, 0x0d, 0x96, 0x04, 0xdd, 0x9e, 0x96, 0x4a, 0x96, 0x02, 0xe4, 0x22, 0xe8, 0x12, 0x46, 0x20, +0x04, 0x00, 0x84, 0x61, 0x40, 0x31, 0x80, 0x0c, 0x04, 0x41, 0x00, 0x6f, 0x40, 0x31, 0x8c, 0x05, +0x40, 0x31, 0x90, 0x02, 0x40, 0x10, 0x80, 0x0c, 0x40, 0x01, 0x84, 0x04, 0x14, 0x01, 0x00, 0x6f, +0xdd, 0x9e, 0x44, 0x00, 0x00, 0x13, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x2a, 0x46, 0xf0, 0x01, 0x06, +0x14, 0x17, 0x83, 0xb3, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0xc8, 0x09, +0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0x94, 0xdd, 0x2f, 0x96, 0x02, 0x84, 0x21, 0xd5, 0x0a, +0x84, 0xa1, 0xd8, 0x0d, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0x94, 0xdd, 0x2f, 0x96, 0x02, +0x84, 0x20, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0x68, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, 0x89, 0xfb, 0x80, 0x60, +0x9e, 0x94, 0x96, 0x90, 0x96, 0x48, 0xe6, 0x42, 0xe9, 0x05, 0x44, 0x40, 0x00, 0x1f, 0x84, 0x00, +0xd5, 0x13, 0x46, 0x00, 0x00, 0xd2, 0x58, 0x00, 0x02, 0x6c, 0x38, 0x40, 0x08, 0x00, 0x46, 0x00, +0x00, 0xd2, 0x58, 0x00, 0x02, 0x68, 0x38, 0x00, 0x08, 0x00, 0xd5, 0x06, 0x38, 0x21, 0x80, 0x00, +0x9c, 0x91, 0x98, 0x02, 0x96, 0x00, 0x98, 0x98, 0xe2, 0x01, 0xe8, 0x07, 0xe2, 0x80, 0xe9, 0x05, +0xa6, 0x91, 0x44, 0x50, 0x00, 0xff, 0xda, 0xf3, 0xdd, 0x9e, 0x84, 0x00, 0x46, 0x10, 0x01, 0x4d, +0x58, 0x10, 0x83, 0xb0, 0x10, 0x00, 0x80, 0x45, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x8a, 0x07, +0xae, 0x08, 0x10, 0x00, 0x80, 0x17, 0x10, 0x00, 0x80, 0x2e, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, +0x01, 0x4d, 0x58, 0x00, 0x03, 0xb0, 0xa6, 0x40, 0xc1, 0x15, 0x00, 0x10, 0x00, 0x17, 0xc9, 0x03, +0x8c, 0x17, 0xd5, 0x10, 0x00, 0x10, 0x00, 0x2e, 0xc9, 0x04, 0x50, 0x00, 0x00, 0x2e, 0xd5, 0x0a, +0x00, 0x30, 0x00, 0x45, 0x50, 0x20, 0x00, 0x45, 0x84, 0x20, 0x40, 0x01, 0x0c, 0x1a, 0x40, 0x00, +0x8c, 0x1b, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x40, 0xd5, 0x0b, 0xa4, 0xc0, 0x9e, 0x4a, 0x98, 0x93, +0x4e, 0x24, 0x00, 0x06, 0x40, 0x31, 0x40, 0x0a, 0x96, 0x91, 0x98, 0x9a, 0x9c, 0x02, 0xe4, 0x22, +0xe8, 0xf5, 0xc1, 0x05, 0xa6, 0x00, 0x98, 0x82, 0xd5, 0x02, 0x98, 0x88, 0x40, 0x01, 0x40, 0x0a, +0x96, 0x51, 0xc8, 0xfc, 0x40, 0x01, 0x08, 0x05, 0x96, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, +0x05, 0x00, 0x84, 0x46, 0xae, 0x8c, 0x46, 0x10, 0x04, 0x00, 0x96, 0x00, 0x04, 0x20, 0x80, 0x88, +0x54, 0x21, 0x00, 0x08, 0xca, 0xfc, 0x46, 0x10, 0x05, 0x00, 0x80, 0x61, 0x44, 0x40, 0x00, 0x52, +0xaf, 0x08, 0xae, 0x08, 0xae, 0x88, 0x46, 0x00, 0x04, 0x00, 0xae, 0x9c, 0x80, 0x61, 0x84, 0x85, +0xaf, 0x08, 0x10, 0x21, 0x80, 0x1c, 0x04, 0x50, 0x00, 0x89, 0x42, 0x52, 0xe0, 0x0b, 0xcd, 0xf9, +0xdd, 0x9e, 0x46, 0x10, 0x05, 0x00, 0x84, 0x46, 0xae, 0x8c, 0x46, 0x10, 0x04, 0x00, 0x04, 0x20, +0x80, 0x88, 0x54, 0x21, 0x00, 0x08, 0xca, 0xfc, 0x40, 0x40, 0x20, 0x09, 0x46, 0x10, 0x05, 0x00, +0x92, 0x10, 0x80, 0x61, 0x96, 0x00, 0x97, 0x20, 0x44, 0x50, 0x00, 0x20, 0xaf, 0x48, 0xae, 0x08, +0xaf, 0x08, 0x46, 0x00, 0x04, 0x00, 0xae, 0x9c, 0x80, 0x61, 0x84, 0x85, 0xaf, 0x08, 0x10, 0x21, +0x80, 0x1c, 0x04, 0x50, 0x00, 0x89, 0x42, 0x52, 0xe0, 0x0b, 0xcd, 0xf9, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0x3c, 0x46, 0x30, 0x05, 0x00, 0x84, 0x86, 0xaf, 0x1c, 0x46, 0x30, 0x04, 0x00, 0x96, 0x91, +0x04, 0x41, 0x80, 0x88, 0x54, 0x42, 0x00, 0x08, 0xcc, 0xfc, 0x40, 0x60, 0x40, 0x09, 0x40, 0x50, +0x20, 0x09, 0x46, 0x30, 0x05, 0x00, 0x97, 0xb0, 0x97, 0x68, 0x96, 0x00, 0x84, 0xe2, 0x97, 0x11, +0xaf, 0xd8, 0xaf, 0x98, 0xaf, 0x58, 0xae, 0x18, 0x5c, 0xf2, 0x01, 0x01, 0xe9, 0x02, 0x94, 0xbf, +0x80, 0x03, 0x96, 0x91, 0xd5, 0x0a, 0x84, 0xa1, 0xa7, 0x08, 0xda, 0x03, 0xaf, 0x04, 0xd5, 0x02, +0xaf, 0x18, 0x9e, 0x91, 0x96, 0x91, 0x9c, 0x49, 0xca, 0xf7, 0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x47, 0xc0, 0x05, 0x00, 0x80, 0xc0, 0x81, 0x5c, +0x80, 0x81, 0x81, 0x22, 0x81, 0x01, 0x80, 0xe0, 0x84, 0xa0, 0x80, 0x62, 0xd5, 0x22, 0x44, 0x20, +0x01, 0x00, 0x80, 0x07, 0x80, 0x28, 0xf3, 0x81, 0xf4, 0x82, 0xf5, 0x83, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x82, 0x60, 0xdd, 0x2f, 0x46, 0x20, 0x04, 0x00, 0xf4, 0x02, 0xf3, 0x01, 0xf5, 0x03, +0x84, 0x05, 0x10, 0x0e, 0x00, 0x00, 0x10, 0x55, 0x00, 0x1c, 0x04, 0x01, 0x00, 0x89, 0x42, 0x00, +0x60, 0x0b, 0xc8, 0xf7, 0x50, 0x73, 0x81, 0x00, 0x50, 0x84, 0x01, 0x00, 0x50, 0x94, 0xff, 0x00, +0x5c, 0xf4, 0x81, 0x00, 0xe8, 0xdd, 0x80, 0x03, 0x96, 0x80, 0x80, 0x66, 0x80, 0xc0, 0x92, 0xc8, +0x40, 0x63, 0x20, 0x08, 0x98, 0x66, 0x98, 0x33, 0xc2, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, +0x82, 0x60, 0xdd, 0x2f, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0x3c, 0x46, 0x40, 0x05, 0x00, 0x40, 0x90, 0x40, 0x09, 0x40, 0x80, 0x20, 0x09, 0x96, 0x00, +0x54, 0x94, 0x80, 0xff, 0x54, 0x84, 0x00, 0xff, 0x84, 0x60, 0x80, 0xe4, 0x80, 0xc4, 0x46, 0x50, +0x04, 0x00, 0x85, 0x43, 0x10, 0xa2, 0x00, 0x00, 0x10, 0x92, 0x00, 0x00, 0x10, 0x82, 0x00, 0x00, +0xae, 0x20, 0x80, 0x03, 0xd5, 0x0f, 0x4c, 0x41, 0x40, 0x05, 0x10, 0x03, 0x00, 0x1c, 0xd5, 0x03, +0x10, 0x03, 0x80, 0x18, 0x04, 0x82, 0x80, 0x89, 0x9d, 0x19, 0x93, 0x18, 0x38, 0x80, 0x8c, 0x08, +0x96, 0xe1, 0x9d, 0x19, 0xe2, 0x62, 0xe9, 0xf0, 0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xff, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x20, 0x96, 0x00, 0x40, 0x00, +0x80, 0x06, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xff, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x20, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x8a, 0x08, 0x84, 0x3f, 0x46, 0xf0, 0x01, 0x38, 0x12, 0x17, +0x84, 0xf1, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x03, 0x90, 0x84, 0x20, 0xaa, 0x41, 0x46, 0x50, +0x01, 0x4d, 0x58, 0x52, 0x83, 0xb0, 0xd8, 0xfb, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x44, 0x20, 0x00, 0x30, 0x80, 0x20, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x04, 0x0c, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xd4, 0x81, 0x01, 0xa6, 0x4c, 0x80, 0xc0, 0x44, 0x00, +0x00, 0xff, 0x80, 0xe2, 0x4c, 0x10, 0x00, 0x51, 0xc9, 0x0b, 0x50, 0x1f, 0x80, 0x04, 0xa8, 0x89, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0x78, 0x84, 0x02, 0xdd, 0x22, 0xd5, 0x45, 0x00, 0x03, +0x00, 0x16, 0x44, 0x50, 0x00, 0xff, 0xd8, 0x14, 0x80, 0x22, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, +0x84, 0x80, 0x44, 0x20, 0x00, 0x30, 0x50, 0x03, 0x00, 0x10, 0x4b, 0xe0, 0x24, 0x01, 0x50, 0x03, +0x00, 0x40, 0x50, 0x13, 0x80, 0x30, 0x44, 0x20, 0x00, 0x30, 0x4b, 0xe0, 0x24, 0x01, 0x20, 0x03, +0x00, 0x08, 0xc8, 0x07, 0x20, 0x13, 0x80, 0x07, 0x84, 0x04, 0x40, 0x00, 0x80, 0x36, 0xd5, 0x04, +0x84, 0x24, 0x40, 0x00, 0x04, 0x36, 0x84, 0x23, 0x20, 0x23, 0x80, 0x07, 0x42, 0x00, 0x04, 0x24, +0x84, 0x24, 0x40, 0x21, 0x04, 0x36, 0x96, 0x00, 0xa4, 0x76, 0x98, 0x02, 0x10, 0x03, 0x00, 0x08, +0xc9, 0x13, 0x00, 0x13, 0x00, 0x0a, 0x44, 0x00, 0x00, 0xa0, 0x42, 0x00, 0x80, 0x24, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x47, 0x82, 0x49, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x6b, 0x80, 0x46, +0x84, 0x61, 0xdd, 0x24, 0xac, 0x36, 0xa4, 0xf7, 0xcb, 0x11, 0x00, 0x13, 0x00, 0x0b, 0x44, 0x00, +0x06, 0x40, 0x42, 0x00, 0x80, 0x24, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x49, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x17, 0x82, 0x6c, 0x80, 0x46, 0xd5, 0x1e, 0x20, 0x03, 0x80, 0x07, 0x20, 0x14, +0x00, 0x02, 0xe0, 0x20, 0xe8, 0x1a, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, +0x00, 0x0e, 0xdd, 0x21, 0x00, 0x13, 0x00, 0x0b, 0x44, 0x00, 0x06, 0x40, 0x42, 0x00, 0x80, 0x24, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x49, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x6c, +0x80, 0x46, 0x84, 0x60, 0xdd, 0x24, 0xac, 0x37, 0x84, 0x00, 0xec, 0x2c, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x97, 0xc9, 0x84, 0x02, 0x84, 0x20, +0x46, 0xf0, 0x00, 0x56, 0x58, 0xf7, 0x88, 0x80, 0xdd, 0x2f, 0x80, 0x07, 0x80, 0x26, 0x46, 0xf0, +0x00, 0x57, 0x58, 0xf7, 0x86, 0xe4, 0xdd, 0x2f, 0x84, 0x02, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x56, +0x58, 0xf7, 0x82, 0x88, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x09, 0x04, 0x20, 0x00, 0x09, 0x80, 0x20, +0x42, 0x21, 0x04, 0x0b, 0xc2, 0xfb, 0x04, 0x20, 0x80, 0x09, 0x84, 0x01, 0x58, 0x21, 0x00, 0x02, +0x14, 0x20, 0x80, 0x09, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x37, 0x88, 0x73, 0x80, 0x40, 0x84, 0x02, +0x80, 0xc1, 0x4c, 0x30, 0x40, 0x1c, 0x46, 0x70, 0x01, 0x03, 0x58, 0x73, 0x81, 0xe8, 0x44, 0x00, +0xfc, 0x6f, 0x40, 0x10, 0xc0, 0x08, 0x98, 0x48, 0x80, 0x07, 0xaa, 0x41, 0x80, 0x22, 0x80, 0x46, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, 0x9c, 0x74, 0x80, 0x07, 0x96, 0x49, +0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x85, 0x44, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8a, 0x08, 0xa7, 0x08, +0x46, 0x30, 0x01, 0x4d, 0x58, 0x31, 0x83, 0x90, 0x50, 0x22, 0x00, 0x10, 0x96, 0x90, 0x92, 0x84, +0x84, 0xa0, 0x40, 0x01, 0x10, 0x09, 0x38, 0x61, 0x92, 0x02, 0xae, 0x88, 0x38, 0x51, 0x92, 0x0a, +0xe6, 0x08, 0xe9, 0x04, 0x54, 0x21, 0x00, 0x0f, 0xae, 0x88, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x80, 0x06, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, 0x84, 0xf1, +0x96, 0x01, 0x96, 0x48, 0x4c, 0x20, 0x40, 0x5b, 0xe6, 0x22, 0xe9, 0x30, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x07, 0x8a, 0x08, 0x40, 0x20, 0x10, 0x09, 0x54, 0x50, 0x00, 0x0f, 0xda, 0x27, 0x84, 0xa8, +0xd9, 0x14, 0x46, 0x30, 0x01, 0x4d, 0x58, 0x31, 0x83, 0x90, 0x38, 0x31, 0x8a, 0x02, 0xc3, 0x0d, +0xd5, 0x1d, 0x96, 0x38, 0x54, 0x20, 0x00, 0x0f, 0x38, 0x32, 0x1a, 0x0a, 0xe4, 0x48, 0xe9, 0x03, +0x54, 0x00, 0x00, 0xf0, 0x96, 0xa8, 0xd5, 0x08, 0x84, 0x40, 0x9e, 0x49, 0x46, 0x40, 0x01, 0x4d, +0x58, 0x42, 0x03, 0x90, 0x80, 0x62, 0x9d, 0xc1, 0x54, 0x60, 0x00, 0x0f, 0x9d, 0x51, 0xe0, 0x41, +0xe9, 0xe9, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x8a, 0x08, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x08, +0xa6, 0xc0, 0x46, 0x20, 0x04, 0x90, 0x9c, 0x59, 0x04, 0x51, 0x00, 0x0e, 0x96, 0x48, 0x54, 0x31, +0x80, 0x0f, 0x46, 0x40, 0x01, 0x4d, 0x58, 0x42, 0x03, 0x90, 0x54, 0x20, 0x80, 0x0f, 0x38, 0x52, +0x0e, 0x0a, 0xae, 0x40, 0xe4, 0x48, 0xe9, 0x04, 0x92, 0x24, 0x94, 0x4c, 0xae, 0x40, 0xf0, 0x01, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x80, 0x20, 0xc8, 0x1f, 0x50, 0x0f, 0x80, 0x04, +0xf1, 0x81, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x44, 0x00, 0x0f, 0xff, +0x46, 0xf0, 0x01, 0x38, 0x14, 0x07, 0x82, 0x72, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, +0x84, 0x41, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x80, 0x20, 0xc8, 0x2b, 0x50, 0x0f, 0x80, 0x04, +0xf1, 0x81, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x44, 0x00, 0x30, 0x00, +0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x82, 0x14, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, +0x84, 0xef, 0x44, 0x00, 0x40, 0x00, 0x9a, 0xc2, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x37, 0x82, 0x72, +0x80, 0x03, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, +0x82, 0xc4, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, +0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, +0x84, 0x20, 0xf1, 0x81, 0x84, 0xa1, 0xd0, 0x25, 0xc0, 0x04, 0x84, 0xa2, 0xd8, 0x62, 0xd5, 0x3e, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x44, 0x00, +0x20, 0x00, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x82, 0x14, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, +0x02, 0x17, 0x84, 0xef, 0x44, 0x30, 0x20, 0x00, 0x80, 0x41, 0x99, 0x4b, 0x80, 0x03, 0x46, 0x10, +0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x09, 0xcc, 0xd5, 0x18, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0x40, +0x01, 0x38, 0x58, 0x42, 0x09, 0xcc, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x17, 0x84, 0xef, 0xb4, 0x64, +0x80, 0x41, 0x99, 0x4b, 0x80, 0x03, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0xb6, 0xa4, +0x46, 0xf0, 0x01, 0x38, 0x14, 0x37, 0x82, 0x72, 0xd5, 0x19, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x73, +0x46, 0xf0, 0x01, 0x38, 0x14, 0x37, 0x82, 0x72, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, 0x84, 0xef, +0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, +0x82, 0xc4, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, +0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, +0x80, 0xc0, 0x84, 0x00, 0xf0, 0x81, 0x84, 0xa1, 0xd6, 0x25, 0xc6, 0x04, 0x84, 0xa2, 0xde, 0x63, +0xd5, 0x3f, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, +0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x82, 0x14, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, +0x02, 0x37, 0x84, 0xef, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x67, 0x82, 0x72, 0x80, 0x06, 0x80, 0x43, +0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x09, 0xcc, +0xd5, 0x1d, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, +0x46, 0x40, 0x01, 0x38, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x17, 0x84, 0xef, 0x04, 0x32, 0x02, 0x73, +0x80, 0x41, 0x99, 0x4b, 0x14, 0x52, 0x02, 0x73, 0x80, 0x03, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, +0x8b, 0x98, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x09, 0xc8, 0xb6, 0x64, 0xd5, 0x19, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x37, 0x82, 0x73, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x37, 0x82, 0x72, 0x46, 0xf0, 0x01, 0x38, +0x02, 0x27, 0x84, 0xef, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x80, 0x03, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x81, 0x68, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xf4, 0x84, 0x20, 0xf1, 0x81, 0x84, 0xa1, 0xd0, 0x2c, 0xc0, 0x04, 0x84, 0xa2, +0xd8, 0x69, 0xd5, 0x45, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, +0xdd, 0x2f, 0x44, 0x60, 0x30, 0x00, 0x46, 0x70, 0x00, 0xca, 0x58, 0x73, 0x82, 0x14, 0x80, 0x06, +0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x63, 0x10, 0x00, 0x44, 0x53, 0x80, 0x00, 0xde, 0xf9, 0x46, 0xf0, +0x01, 0x38, 0x02, 0x17, 0x84, 0xef, 0x44, 0x30, 0x40, 0x00, 0x80, 0x41, 0x99, 0x4b, 0x80, 0x03, +0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x09, 0xcc, +0xd5, 0x18, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, +0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x09, 0xcc, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x17, 0x84, 0xef, +0xb4, 0x64, 0x80, 0x41, 0x99, 0x4b, 0x80, 0x03, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, +0xb6, 0xa4, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x37, 0x82, 0x72, 0xd5, 0x19, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x73, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x37, 0x82, 0x72, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, +0x84, 0xef, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8b, 0x98, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, +0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x96, 0x00, 0xe6, 0x09, 0xe9, 0x13, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x83, 0xd0, 0xdd, 0x2f, +0x46, 0x00, 0x01, 0x0c, 0x58, 0x00, 0x0b, 0x75, 0x84, 0x20, 0x18, 0x10, 0x00, 0x20, 0x46, 0x50, +0x01, 0x0c, 0x58, 0x52, 0x8c, 0x95, 0xd8, 0xfa, 0xd5, 0x1f, 0x50, 0x10, 0x00, 0x55, 0x46, 0x20, +0x01, 0x0c, 0x58, 0x21, 0x00, 0xb8, 0x94, 0x4d, 0x98, 0x4a, 0x84, 0x40, 0x10, 0x20, 0x80, 0x1d, +0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0xc0, 0x0e, 0x46, 0xf0, 0x01, 0x38, +0x02, 0x17, 0x84, 0xf1, 0x02, 0x00, 0x00, 0xc4, 0x4c, 0x10, 0x40, 0x07, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x83, 0xd0, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xfc, 0x54, 0x90, 0x00, 0xff, 0x44, 0x00, 0x00, 0x2c, 0x54, 0x80, 0x80, 0xff, +0x4c, 0x90, 0x00, 0x06, 0x44, 0x10, 0x00, 0x55, 0x4c, 0x90, 0xc1, 0x2b, 0x46, 0x70, 0x01, 0x10, +0x58, 0x73, 0x85, 0xc0, 0x00, 0x03, 0x80, 0x49, 0x4e, 0x03, 0x01, 0x23, 0x80, 0x08, 0x46, 0xf0, +0x00, 0x1c, 0x58, 0xf7, 0x83, 0xcc, 0xdd, 0x2f, 0x4e, 0x02, 0x01, 0x1b, 0x40, 0x64, 0x24, 0x00, +0x46, 0x20, 0x01, 0x0c, 0x58, 0x21, 0x00, 0xb8, 0x95, 0xb5, 0x99, 0xb2, 0xa0, 0x74, 0x02, 0x30, +0x00, 0xc4, 0xb4, 0x41, 0xa6, 0x53, 0xa7, 0x12, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x90, 0x04, +0x84, 0x81, 0x4c, 0x12, 0x40, 0x6d, 0xa7, 0x14, 0x84, 0xa2, 0xdc, 0x1b, 0x00, 0x03, 0x80, 0x54, +0xc8, 0x18, 0xa6, 0xd5, 0x10, 0x33, 0x80, 0x55, 0x00, 0x41, 0x00, 0x09, 0x00, 0x31, 0x00, 0x08, +0x40, 0x22, 0x20, 0x08, 0x40, 0x21, 0x0c, 0x04, 0x44, 0x40, 0x00, 0x19, 0x4c, 0x22, 0x40, 0x06, +0x10, 0x13, 0x80, 0x54, 0x48, 0x00, 0x00, 0xc6, 0x10, 0x03, 0x80, 0x54, 0x48, 0x00, 0x00, 0xc2, +0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x05, 0xc0, 0x00, 0x10, 0x00, 0x54, 0x4e, 0x12, 0x00, 0xba, +0x84, 0xa3, 0x4c, 0x42, 0xc0, 0xb7, 0x00, 0x40, 0x00, 0x55, 0xa6, 0x55, 0x4c, 0x40, 0xc0, 0xb2, +0x00, 0x11, 0x00, 0x0d, 0x00, 0x41, 0x00, 0x0c, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, 0x90, 0x04, +0xc9, 0x2f, 0x46, 0x00, 0x01, 0x01, 0x04, 0x40, 0x00, 0x94, 0xe2, 0x85, 0xe9, 0x03, 0x14, 0x10, +0x00, 0x94, 0x46, 0x10, 0x01, 0x01, 0x04, 0x40, 0x80, 0x94, 0x84, 0x06, 0x42, 0x02, 0x00, 0x24, +0x46, 0x50, 0x01, 0x10, 0x58, 0x52, 0x86, 0x18, 0x98, 0x05, 0x9d, 0x21, 0x14, 0x40, 0x80, 0x94, +0xac, 0xc0, 0x00, 0x11, 0x00, 0x09, 0x00, 0x31, 0x00, 0x08, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x10, +0x8c, 0x04, 0xac, 0x41, 0x00, 0x11, 0x00, 0x0b, 0x00, 0x21, 0x00, 0x0a, 0x40, 0x10, 0xa0, 0x08, +0x40, 0x10, 0x88, 0x04, 0xac, 0x42, 0x84, 0x20, 0x50, 0x02, 0xff, 0xa8, 0xd5, 0x05, 0x84, 0x41, +0x4c, 0x11, 0x00, 0x78, 0x84, 0x20, 0x10, 0x10, 0x00, 0x54, 0xd5, 0x73, 0x50, 0x23, 0x80, 0x58, +0xa5, 0x10, 0x4c, 0x41, 0xc0, 0x67, 0xa5, 0x11, 0x4c, 0x40, 0x80, 0x05, 0xa5, 0x12, 0x4c, 0x40, +0xc0, 0x61, 0x44, 0x2f, 0xff, 0x90, 0x46, 0xf0, 0x01, 0x10, 0x12, 0x37, 0x83, 0x06, 0x46, 0xf0, +0x01, 0x10, 0x10, 0x27, 0x86, 0x0a, 0x84, 0x81, 0x04, 0x30, 0x00, 0x6c, 0x4c, 0x32, 0x40, 0x13, +0x04, 0x10, 0x00, 0x27, 0xe6, 0x33, 0xe9, 0x0e, 0x84, 0x22, 0x44, 0x20, 0x97, 0x56, 0x44, 0x30, +0xea, 0x60, 0x44, 0x40, 0x2b, 0xf2, 0x84, 0xbf, 0x46, 0xf0, 0x00, 0x21, 0x58, 0xf7, 0x8e, 0x98, +0xdd, 0x2f, 0x46, 0x70, 0x01, 0x10, 0x58, 0x73, 0x85, 0xc0, 0x00, 0x23, 0x80, 0x39, 0xca, 0x41, +0x46, 0xf0, 0x01, 0x01, 0x04, 0xa7, 0x81, 0xdd, 0x51, 0xc4, 0x00, 0x55, 0x44, 0x00, 0x00, 0x30, +0x42, 0xa4, 0x00, 0x73, 0x46, 0x50, 0x01, 0x0c, 0x58, 0x52, 0x80, 0xb8, 0x41, 0xce, 0x14, 0x08, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x99, 0x41, 0xce, 0x14, 0x00, 0x04, 0x03, 0x80, 0x14, +0x87, 0xc1, 0x51, 0xce, 0x00, 0x1a, 0x80, 0x62, 0x80, 0x82, 0x84, 0xa1, 0x11, 0xe3, 0x80, 0x39, +0x15, 0xc3, 0x80, 0x0f, 0x14, 0xa3, 0x80, 0x10, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x13, 0x02, 0x17, 0x82, 0x7a, 0x10, 0x03, 0x80, 0x56, 0x58, 0x00, +0x80, 0x02, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0xa5, 0x96, 0x01, 0xdd, 0x21, 0xd5, 0x09, +0x46, 0x40, 0x01, 0x10, 0x58, 0x42, 0x06, 0x24, 0x4c, 0x22, 0x00, 0x04, 0x9c, 0x96, 0xd5, 0x91, +0x44, 0x50, 0x00, 0x55, 0x4c, 0x92, 0xc0, 0x25, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, +0x83, 0xcc, 0xdd, 0x2f, 0x00, 0x33, 0x00, 0x1d, 0x9c, 0xd9, 0x46, 0xf0, 0x01, 0x10, 0x00, 0x27, +0x85, 0xf9, 0x10, 0x33, 0x00, 0x1d, 0x84, 0x61, 0x4c, 0x21, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x10, +0x02, 0x17, 0x83, 0x06, 0x46, 0xf0, 0x01, 0x38, 0x12, 0x17, 0x84, 0xf1, 0x02, 0x00, 0x00, 0xc4, +0x00, 0x13, 0x00, 0x1d, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x86, 0x54, 0xdd, 0x2f, 0xec, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf0, 0x85, 0x00, 0x14, 0x8f, +0x80, 0x03, 0xb4, 0xc0, 0x50, 0x0f, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, +0xdd, 0x2f, 0x46, 0x00, 0x04, 0x90, 0x04, 0x10, 0x00, 0x0e, 0x9c, 0x31, 0xf1, 0x83, 0x44, 0x10, +0x00, 0x13, 0xa7, 0xc0, 0x14, 0x8f, 0x80, 0x01, 0xa7, 0x70, 0xd9, 0x34, 0x9c, 0x74, 0x50, 0x83, +0xff, 0xfe, 0x00, 0xa0, 0x80, 0x00, 0x9c, 0x33, 0x89, 0x06, 0x00, 0x90, 0x00, 0x00, 0x80, 0x28, +0x50, 0x0f, 0x80, 0x04, 0x84, 0x44, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, +0x40, 0x05, 0x20, 0x08, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x57, 0x84, 0xf1, 0x40, 0x00, 0x24, 0x04, +0xd8, 0x19, 0xf0, 0x01, 0xc0, 0x17, 0xf1, 0x03, 0xe2, 0x01, 0xe8, 0x14, 0x9a, 0x08, 0x9c, 0x79, +0x98, 0x71, 0x96, 0x80, 0xf0, 0x83, 0xae, 0x88, 0x98, 0x77, 0x00, 0x2f, 0x80, 0x0d, 0x50, 0x0f, +0x80, 0x0e, 0xae, 0x88, 0x9f, 0xf9, 0xa6, 0x40, 0x99, 0xb7, 0xae, 0x70, 0xa6, 0x01, 0x10, 0x04, +0x00, 0x00, 0xf0, 0x02, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xec, 0x10, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, +0x82, 0x34, 0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x09, 0x46, 0x00, 0x04, 0x90, 0x04, 0x10, 0x00, 0x0e, +0x46, 0xf0, 0x01, 0x03, 0x14, 0x17, 0x83, 0xf4, 0x46, 0xf0, 0x01, 0x00, 0x00, 0x07, 0x83, 0x0d, +0x84, 0xa1, 0xd8, 0x0a, 0x46, 0x00, 0x01, 0x03, 0x58, 0x00, 0x0f, 0x9c, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x8d, 0x78, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, +0xdd, 0x2f, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xfe, 0xc0, 0x23, 0x46, 0x60, 0x01, 0x08, 0x58, 0x63, 0x0f, 0x9c, +0x04, 0x13, 0x00, 0x08, 0x84, 0x46, 0x50, 0x10, 0x81, 0xa8, 0x46, 0x00, 0x01, 0x44, 0x58, 0x00, +0x07, 0xa0, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x84, 0x01, 0x84, 0x40, +0x50, 0x33, 0x00, 0x20, 0x46, 0x10, 0x00, 0xcb, 0x58, 0x10, 0x8f, 0x90, 0x80, 0x82, 0x80, 0xa0, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x84, 0x01, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe8, 0x50, 0x6f, 0x80, 0x04, 0x81, 0x41, 0x54, 0x90, +0x00, 0xff, 0x54, 0x81, 0x00, 0xff, 0x84, 0x20, 0x44, 0x20, 0x00, 0x14, 0x80, 0x06, 0x97, 0xd8, +0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0x84, 0x46, 0x80, 0x2a, 0x40, 0x0f, +0x88, 0x00, 0x84, 0x62, 0xae, 0xf0, 0x10, 0x93, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4d, 0x50, 0x2f, 0x80, 0x0e, +0x10, 0x83, 0x00, 0x08, 0x10, 0x73, 0x00, 0x09, 0x9a, 0x96, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, +0x89, 0xf5, 0x80, 0x26, 0x54, 0x21, 0x00, 0xfe, 0xdd, 0x23, 0xec, 0x18, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0xa7, 0xc0, 0xe6, 0xe2, 0xe8, 0x18, 0x9c, 0x41, +0x84, 0x46, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xb4, 0x3f, +0x80, 0xdf, 0xc9, 0x04, 0x02, 0x0f, 0x80, 0x02, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x37, +0x81, 0xe0, 0x02, 0x2f, 0x80, 0x02, 0x80, 0x07, 0xdd, 0x23, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x12, +0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, +0x00, 0x70, 0x00, 0x10, 0x80, 0xc0, 0xe6, 0xe2, 0xe8, 0x25, 0x50, 0x90, 0x00, 0x11, 0x80, 0x29, +0x80, 0x1f, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xb4, 0x3f, +0x81, 0x1f, 0xc9, 0x04, 0x02, 0x0f, 0x80, 0x02, 0xc0, 0x15, 0x84, 0xa1, 0xdf, 0x09, 0x00, 0x04, +0x80, 0x05, 0x96, 0x82, 0x4e, 0x24, 0x00, 0x0f, 0x54, 0x00, 0x00, 0x40, 0xc0, 0x0b, 0x46, 0xf0, +0x01, 0x44, 0x04, 0x47, 0x81, 0xdf, 0x02, 0x2f, 0x80, 0x02, 0x80, 0x07, 0x80, 0x66, 0xdd, 0x24, +0xd5, 0x03, 0x44, 0x00, 0x00, 0x12, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xec, 0x96, 0x00, 0x95, 0xc2, 0x84, 0xc0, 0x50, 0x83, 0x80, 0x07, 0xb6, 0x1f, +0x81, 0x21, 0x81, 0x42, 0x84, 0x01, 0x80, 0x26, 0x80, 0x48, 0xf6, 0x83, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0x83, 0x80, 0xc0, 0x75, 0xb4, 0x00, 0x44, 0x10, 0x00, 0x13, +0x80, 0xa0, 0x18, 0x12, 0x80, 0x01, 0x8f, 0x02, 0x18, 0x82, 0x80, 0x01, 0x9c, 0x03, 0xb4, 0x3f, +0x98, 0x07, 0x18, 0x12, 0x80, 0x01, 0x80, 0x86, 0x80, 0x65, 0xd5, 0x11, 0x38, 0x14, 0x90, 0x00, +0xae, 0x58, 0x38, 0x14, 0x90, 0x01, 0x92, 0x28, 0xae, 0x59, 0x38, 0x15, 0x10, 0x00, 0xae, 0x5a, +0x38, 0x15, 0x10, 0x01, 0x9d, 0x22, 0x92, 0x28, 0xae, 0x5b, 0x9c, 0xdc, 0x4c, 0x30, 0x7f, 0xf0, +0x99, 0xef, 0x84, 0xc0, 0xf7, 0x81, 0x80, 0xe6, 0xd5, 0x3a, 0x38, 0x04, 0x98, 0x01, 0x46, 0xf0, +0x00, 0x1c, 0x58, 0xf7, 0x83, 0xe0, 0xdd, 0x2f, 0xc0, 0x19, 0x00, 0x00, 0x01, 0xae, 0x46, 0x10, +0x01, 0x0c, 0x58, 0x10, 0x80, 0xb8, 0x50, 0x00, 0x00, 0x55, 0x94, 0x05, 0x98, 0x01, 0xc0, 0x0e, +0x84, 0x20, 0xd5, 0x07, 0x00, 0x20, 0x00, 0x1d, 0x96, 0x58, 0x9e, 0x91, 0x10, 0x20, 0x00, 0x1d, +0x38, 0x25, 0x18, 0x01, 0x9c, 0xc9, 0xe2, 0x22, 0xe9, 0xf6, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x57, +0x84, 0xf1, 0x38, 0x04, 0x98, 0x01, 0xd8, 0x10, 0x85, 0x00, 0xd5, 0x0a, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x85, 0xf4, 0xdd, 0x2f, 0x8d, 0x01, 0xf0, 0x83, 0x54, 0x84, 0x00, 0xff, 0x38, 0x05, +0x18, 0x01, 0xe3, 0x00, 0xe9, 0xf4, 0x9d, 0xf9, 0x97, 0xf9, 0x9d, 0xb2, 0xb4, 0x1f, 0xe2, 0xe0, +0xe9, 0xc5, 0xf0, 0x01, 0x50, 0x1f, 0x80, 0x0c, 0x84, 0x44, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, +0xdd, 0x2f, 0x84, 0x00, 0x40, 0x00, 0x70, 0x06, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x81, 0x01, 0x97, 0xc1, 0x97, 0x91, 0x84, 0x01, 0x84, 0x20, +0x84, 0x48, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x19, 0xb4, 0x60, +0x40, 0x13, 0x20, 0x09, 0xae, 0x5f, 0x84, 0x2e, 0xae, 0x58, 0x84, 0x26, 0x40, 0x03, 0xa0, 0x09, +0xae, 0x59, 0x84, 0x21, 0xae, 0x5a, 0xae, 0x1c, 0x10, 0x81, 0x80, 0x05, 0xaf, 0xdb, 0xaf, 0x9e, +0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x97, 0xc4, 0xcf, 0x09, +0xc1, 0x08, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x81, 0x98, 0xdd, 0x2f, 0x80, 0xc0, 0xd5, 0x04, +0x44, 0x70, 0x00, 0x12, 0x84, 0xc0, 0x84, 0x01, 0x84, 0x20, 0x84, 0x48, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x18, 0xb4, 0x20, 0x40, 0x03, 0x20, 0x09, 0xae, 0x0f, +0x84, 0x0e, 0xae, 0x08, 0x84, 0x06, 0xae, 0x09, 0x84, 0x01, 0xae, 0x0a, 0x84, 0x00, 0xae, 0x0b, +0x84, 0x1d, 0xae, 0x0c, 0xaf, 0xcd, 0xaf, 0x8e, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x54, 0x80, 0x00, 0xff, 0x50, 0x04, 0x7f, 0xac, 0x96, 0x00, 0x50, 0x70, +0x80, 0x1c, 0xe6, 0x03, 0xe9, 0x02, 0xd5, 0x46, 0x46, 0x10, 0x00, 0xd2, 0x58, 0x10, 0x82, 0x5c, +0x40, 0x04, 0x04, 0x00, 0x00, 0x90, 0x7f, 0xac, 0x84, 0x20, 0x84, 0x01, 0x50, 0x24, 0x80, 0x02, +0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x36, 0xb4, 0xc0, 0xc6, 0x34, +0x84, 0x1f, 0xae, 0x30, 0x44, 0x50, 0x00, 0x55, 0x10, 0x93, 0x00, 0x01, 0x10, 0x83, 0x00, 0x02, +0x4c, 0x82, 0x80, 0x06, 0x9d, 0x69, 0x4c, 0x82, 0xc0, 0x1f, 0xd5, 0x0c, 0xa6, 0x3c, 0xae, 0x33, +0x00, 0x13, 0xff, 0xf8, 0xae, 0x74, 0xa6, 0x3a, 0xae, 0x35, 0xa4, 0x39, 0x92, 0x08, 0xae, 0x36, +0xd5, 0x12, 0xa6, 0x7a, 0x84, 0x46, 0xae, 0x73, 0xa6, 0x3e, 0xae, 0x34, 0x9c, 0x35, 0x04, 0x13, +0xff, 0xf9, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x00, 0x73, 0xff, 0xf8, +0x10, 0x73, 0x00, 0x0b, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, +0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x07, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xd4, 0x50, 0x6f, 0x80, 0x04, 0xa7, 0x01, 0x9c, 0xc2, +0x97, 0xc8, 0xb6, 0x66, 0x46, 0x30, 0x01, 0x0f, 0x58, 0x31, 0x83, 0x00, 0x12, 0x43, 0x00, 0x0f, +0xa8, 0xf1, 0xa9, 0xf5, 0x80, 0x40, 0x00, 0x21, 0x00, 0x08, 0x44, 0x00, 0x00, 0x56, 0x80, 0x26, +0x10, 0x23, 0x00, 0x22, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x81, 0xe0, 0xdd, 0x2f, 0xcf, 0x08, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0x78, 0x80, 0x26, 0x84, 0x02, 0xdd, 0x22, 0xec, 0x2c, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x20, 0x01, 0x49, +0x58, 0x21, 0x0e, 0xa4, 0x02, 0x31, 0x00, 0x14, 0xc3, 0x1c, 0x00, 0x11, 0x00, 0x2a, 0xc9, 0x19, +0x02, 0x41, 0x00, 0x16, 0x44, 0x00, 0x00, 0x4b, 0x42, 0x02, 0x00, 0x24, 0x02, 0x51, 0x00, 0x17, +0x84, 0x8b, 0x42, 0x02, 0x90, 0x73, 0xe0, 0x03, 0xe9, 0x0c, 0x84, 0x61, 0x10, 0x31, 0x00, 0x2a, +0x44, 0x00, 0x00, 0x54, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x81, 0xe0, 0xdd, 0x2f, 0xd5, 0x02, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xd8, +0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x83, 0xb0, 0xdd, 0x2f, 0xc0, 0x30, 0x46, 0x60, 0x00, 0x38, +0x58, 0x63, 0x05, 0x58, 0x84, 0x00, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x83, 0xbc, 0xdd, 0x2f, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0x81, 0x46, 0xf0, 0x01, 0x13, 0x10, 0x47, 0x84, 0xac, 0x46, 0x10, +0x01, 0x4d, 0x58, 0x10, 0x84, 0x0c, 0x44, 0x20, 0x00, 0x30, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, +0x03, 0x00, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x04, +0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x03, 0x00, 0xa8, 0x09, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, +0x83, 0x78, 0x84, 0x02, 0xdd, 0x22, 0x4b, 0xe0, 0x18, 0x01, 0xec, 0x28, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x85, 0x3c, +0x84, 0xa1, 0xd8, 0x2b, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x83, 0x04, 0xc0, 0x03, 0x84, 0xa2, +0xd8, 0x24, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x03, 0x00, 0x00, 0x03, 0x00, 0x36, 0x44, 0x50, +0x00, 0xff, 0xd0, 0x7b, 0x00, 0x03, 0x00, 0x34, 0x84, 0xa4, 0xd8, 0x03, 0x87, 0x81, 0xd5, 0x16, +0x50, 0x13, 0x00, 0x30, 0x44, 0x20, 0x00, 0x30, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x80, 0xdd, 0x2f, 0x84, 0x01, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8a, 0xe8, 0xdd, 0x2f, +0xa6, 0x34, 0xc0, 0x63, 0x84, 0xa2, 0xd0, 0x61, 0x87, 0x80, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, +0x83, 0x06, 0x44, 0x50, 0x00, 0xff, 0xd0, 0x54, 0x46, 0xf0, 0x01, 0x4a, 0x04, 0x87, 0x83, 0xe0, +0x80, 0xdf, 0x46, 0x90, 0x01, 0x38, 0xd5, 0x46, 0x50, 0x74, 0x7f, 0xe8, 0xc7, 0x42, 0x46, 0xf0, +0x01, 0x4a, 0x00, 0x07, 0x8f, 0x7d, 0x84, 0xa1, 0xd8, 0x32, 0x84, 0x20, 0x94, 0xac, 0x80, 0x1f, +0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0x04, 0x34, 0x82, 0x63, 0x80, 0x07, +0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x83, 0x00, 0x80, 0x5f, 0xdd, 0x23, 0x4f, 0xc2, 0x00, 0x0b, +0x04, 0x34, 0x82, 0x63, 0x80, 0x07, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x83, 0x30, 0x80, 0x5f, +0xdd, 0x23, 0x84, 0x20, 0x80, 0x66, 0x80, 0x41, 0xb4, 0x03, 0x84, 0xbf, 0xd8, 0x07, 0x84, 0x81, +0x40, 0x02, 0x04, 0x0c, 0x40, 0x20, 0x08, 0x04, 0x96, 0x90, 0x9c, 0x49, 0x84, 0xa4, 0x9c, 0xdc, +0xd9, 0xf4, 0xa6, 0x3d, 0x40, 0x21, 0x00, 0x02, 0x4c, 0x20, 0x40, 0x0c, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x27, 0x82, 0x69, 0x80, 0x07, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x83, 0x00, 0xdd, 0x22, +0xb5, 0x08, 0x46, 0x50, 0x01, 0x4a, 0x58, 0x52, 0x8f, 0x80, 0x4c, 0x82, 0xff, 0xb7, 0x46, 0xf0, +0x00, 0x38, 0x58, 0xf7, 0x85, 0x58, 0xdd, 0x2f, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0xbc, 0x58, 0xf7, 0x83, 0x34, +0xdd, 0x2f, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x17, 0x82, 0x74, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x54, 0x82, 0x80, 0xff, +0x80, 0xe0, 0x83, 0x82, 0x80, 0xc3, 0x81, 0x44, 0x54, 0x90, 0x80, 0xff, 0x5c, 0xf4, 0x00, 0x81, +0xe9, 0x0a, 0x44, 0x00, 0xfc, 0xee, 0x44, 0x10, 0x00, 0x12, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, +0x8a, 0xac, 0xdd, 0x2f, 0x4f, 0xc3, 0x00, 0x1d, 0x80, 0x2a, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, +0x0b, 0x98, 0x80, 0x48, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x38, 0x12, 0x87, 0x84, 0xef, 0x4e, 0x93, 0x00, 0x2b, 0x80, 0x29, 0x44, 0x00, 0xfc, 0xee, +0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0x9e, 0x84, 0x01, +0x4d, 0xc0, 0x40, 0x15, 0x80, 0x2a, 0x80, 0x48, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0c, 0x18, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, 0x02, 0x10, +0x04, 0xef, 0x89, 0x01, 0x12, 0x80, 0x04, 0xef, 0xd5, 0x0a, 0x44, 0x00, 0xfc, 0xee, 0x44, 0x10, +0x00, 0x12, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x8a, 0xac, 0xdd, 0x2f, 0x84, 0x01, 0x4c, 0x90, +0x40, 0x7c, 0x4c, 0x74, 0xc0, 0x18, 0x46, 0x00, 0x01, 0x38, 0x02, 0x10, 0x04, 0xef, 0x46, 0xf0, +0x01, 0x38, 0x12, 0x17, 0x84, 0xf0, 0x5c, 0xf0, 0x81, 0x01, 0xe8, 0x05, 0x44, 0x10, 0x01, 0x00, +0x12, 0x10, 0x04, 0xef, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x89, 0xa0, 0xdd, 0x2f, +0xd5, 0x57, 0xcf, 0x17, 0x46, 0x00, 0x01, 0x38, 0x02, 0x10, 0x04, 0xef, 0x46, 0xf0, 0x01, 0x38, +0x12, 0x17, 0x84, 0xf0, 0x5c, 0xf0, 0x81, 0x01, 0xe8, 0x05, 0x44, 0x10, 0x01, 0x00, 0x12, 0x10, +0x04, 0xef, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x88, 0xbc, 0xdd, 0x2f, 0xd5, 0x40, +0x84, 0x02, 0x4c, 0x70, 0x40, 0x11, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, 0x84, 0xef, 0x46, 0xf0, +0x01, 0x38, 0x12, 0x27, 0x84, 0xf0, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x87, 0x74, +0xdd, 0x2f, 0xd5, 0x2e, 0x84, 0x03, 0x4c, 0x70, 0x40, 0x11, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, +0x84, 0xef, 0x46, 0xf0, 0x01, 0x38, 0x12, 0x27, 0x84, 0xf0, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, +0x58, 0xf7, 0x87, 0x24, 0xdd, 0x2f, 0xd5, 0x1c, 0x84, 0x04, 0x4c, 0x70, 0x00, 0x05, 0x44, 0x10, +0x00, 0x12, 0xd5, 0x17, 0x46, 0x00, 0x01, 0x38, 0x02, 0x10, 0x04, 0xef, 0x46, 0xf0, 0x01, 0x38, +0x12, 0x17, 0x84, 0xf0, 0x5c, 0xf0, 0x81, 0x01, 0xe8, 0x05, 0x44, 0x10, 0x01, 0x00, 0x12, 0x10, +0x04, 0xef, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x87, 0xdc, 0xdd, 0x2f, 0x84, 0x20, +0x46, 0xf0, 0x01, 0x38, 0x02, 0x27, 0x84, 0xf0, 0x44, 0x00, 0xfc, 0xee, 0x46, 0xf0, 0x00, 0xcb, +0x58, 0xf7, 0x81, 0x24, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0x60, 0x01, 0x4d, 0x58, 0x63, 0x03, 0xb0, 0x81, 0x00, 0x46, 0x70, 0x00, 0x26, +0x58, 0x73, 0x89, 0x3c, 0xa6, 0x30, 0xc0, 0x12, 0x50, 0x03, 0x00, 0x11, 0x80, 0x28, 0x4b, 0xe0, +0x1c, 0x01, 0xc0, 0x0c, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, 0x0a, 0x07, 0x84, 0x40, 0x9e, 0x49, +0xae, 0xb0, 0x10, 0x10, 0x0a, 0x07, 0x84, 0x00, 0xd5, 0x09, 0x8c, 0xd7, 0x46, 0x50, 0x01, 0x4d, +0x58, 0x52, 0x84, 0x0c, 0xde, 0xe8, 0x44, 0x00, 0x00, 0x12, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0x70, 0x01, 0x4d, 0x58, 0x73, 0x83, 0xb0, 0x81, 0x40, +0x84, 0xc0, 0x46, 0x90, 0x00, 0x26, 0x58, 0x94, 0x89, 0x3c, 0xa6, 0x38, 0x81, 0x07, 0xc0, 0x07, +0x50, 0x03, 0x80, 0x11, 0x80, 0x2a, 0x4b, 0xe0, 0x24, 0x01, 0xc8, 0x07, 0x9d, 0xb1, 0x97, 0xb0, +0x84, 0xa4, 0x8c, 0xf7, 0xde, 0xf3, 0xd5, 0x03, 0xe6, 0xc4, 0xe9, 0x02, 0x85, 0x00, 0x80, 0x08, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x81, 0x21, 0x80, 0xe2, 0x81, 0x40, +0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x87, 0x04, 0xdd, 0x2f, 0x81, 0x00, 0xc0, 0x0c, 0x9c, 0x01, +0x80, 0x29, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, +0x84, 0x00, 0xd5, 0x26, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x81, 0x60, 0xdd, 0x2f, 0x80, 0xc0, +0xc0, 0x1e, 0x80, 0x29, 0x44, 0x20, 0x00, 0x10, 0x9c, 0x01, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x80, 0x2a, 0x50, 0x03, 0x00, 0x11, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x28, 0xdd, 0x2f, 0x84, 0x01, 0xae, 0x30, 0x46, 0x00, 0x01, 0x38, 0x00, 0x10, 0x0a, 0x07, +0x9c, 0x49, 0x10, 0x10, 0x0a, 0x07, 0x14, 0x83, 0x80, 0x04, 0xd5, 0x03, 0x84, 0x07, 0xa8, 0x3c, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x77, +0x89, 0xfb, 0x81, 0x00, 0x84, 0x01, 0x80, 0xc1, 0x96, 0x50, 0x4c, 0x70, 0x40, 0x14, 0x50, 0x03, +0x00, 0x0c, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, 0x87, 0x14, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x6e, 0x00, 0x63, 0x00, 0x0b, 0x80, 0x07, 0x10, 0x64, 0x00, 0x00, +0xd5, 0x69, 0x84, 0xa4, 0xdf, 0x18, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x80, 0xe8, +0xdd, 0x2f, 0x8c, 0x08, 0x97, 0xc0, 0x9c, 0x39, 0x98, 0x30, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, +0x87, 0x14, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x52, 0x38, 0x63, +0x1c, 0x00, 0xd5, 0x27, 0x84, 0xa3, 0xdf, 0x10, 0x50, 0x03, 0x00, 0x16, 0x46, 0x10, 0x01, 0x01, +0x58, 0x10, 0x87, 0x14, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x41, +0x00, 0x63, 0x00, 0x1c, 0xd5, 0x16, 0x84, 0xa2, 0xdf, 0x18, 0xa6, 0x30, 0x44, 0x10, 0x00, 0x13, +0x4c, 0x00, 0xc0, 0x38, 0x50, 0x03, 0x00, 0x08, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, 0x87, 0x14, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x2b, 0x00, 0x63, 0x00, 0x0e, +0x10, 0x64, 0x00, 0x00, 0x84, 0x01, 0xd5, 0x26, 0x84, 0xa5, 0xdf, 0x23, 0x80, 0x06, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x80, 0xe8, 0xdd, 0x2f, 0x46, 0x70, 0x01, 0x38, 0x10, 0x03, 0x89, 0xfd, +0x38, 0x13, 0x00, 0x00, 0xe6, 0x2e, 0xe9, 0x15, 0x9c, 0x05, 0x98, 0x30, 0x46, 0x10, 0x01, 0x01, +0x58, 0x10, 0x87, 0x14, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x89, 0x3c, 0xdd, 0x2f, 0xc0, 0x09, +0x00, 0x13, 0x89, 0xfd, 0x84, 0x01, 0x99, 0xb1, 0xa7, 0xb4, 0x10, 0x64, 0x00, 0x00, 0xd5, 0x02, +0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, +0xa7, 0x05, 0x96, 0x90, 0x54, 0x42, 0x00, 0x02, 0xf2, 0x81, 0xcc, 0x03, 0x85, 0x1f, 0xd5, 0x48, +0xf1, 0x01, 0x87, 0x81, 0xa1, 0xc3, 0x40, 0x4e, 0x04, 0x0c, 0x8c, 0x0c, 0x54, 0x12, 0x00, 0x0c, +0xf0, 0x82, 0x54, 0x02, 0x00, 0xc0, 0x54, 0x42, 0x00, 0x30, 0xf1, 0x85, 0x85, 0x40, 0x85, 0x1f, +0xf0, 0x83, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, 0x84, 0xcc, 0xf4, 0x84, 0x80, 0xc3, 0xd5, 0x2e, +0xf1, 0x01, 0x50, 0x03, 0xff, 0xec, 0xe6, 0x28, 0xe8, 0x1f, 0xf1, 0x03, 0xc9, 0x13, 0xf1, 0x04, +0xc9, 0x0a, 0xf1, 0x05, 0xc1, 0x19, 0x11, 0xc0, 0x00, 0x00, 0x80, 0x26, 0x50, 0x03, 0xff, 0xed, +0x84, 0x42, 0xd5, 0x0f, 0x84, 0x42, 0xae, 0x80, 0x80, 0x26, 0x50, 0x03, 0xff, 0xed, 0x84, 0x44, +0xd5, 0x08, 0x84, 0x23, 0xae, 0x40, 0x44, 0x20, 0x00, 0x10, 0x50, 0x03, 0xff, 0xed, 0x80, 0x26, +0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x07, 0x40, 0x0e, 0x28, 0x0c, 0x40, 0x00, 0x00, 0x05, 0x40, 0x84, +0x00, 0x02, 0x8d, 0x41, 0xb4, 0xe7, 0x54, 0xa5, 0x00, 0xff, 0xf5, 0x02, 0xdf, 0xd2, 0x80, 0x08, +0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, +0xa7, 0x05, 0x96, 0x90, 0x97, 0x24, 0x97, 0x48, 0xf2, 0x83, 0xcc, 0x03, 0x84, 0xff, 0xd5, 0x2e, +0xa1, 0x82, 0x51, 0xc0, 0x00, 0x08, 0x85, 0x00, 0x84, 0xff, 0x85, 0x41, 0x46, 0x90, 0x00, 0x41, +0x58, 0x94, 0x84, 0xcc, 0xd5, 0x1f, 0xa6, 0x21, 0xf1, 0x03, 0x4c, 0x00, 0xc0, 0x12, 0xa6, 0xa0, +0xa6, 0x62, 0x9e, 0x92, 0x98, 0x11, 0xe0, 0xa0, 0xe9, 0x0b, 0x98, 0x59, 0x50, 0x03, 0x7f, 0xdb, +0xf3, 0x81, 0xf5, 0x82, 0x4b, 0xe0, 0x24, 0x01, 0xf3, 0x01, 0xf5, 0x02, 0xc0, 0x07, 0x40, 0x05, +0x20, 0x0c, 0x40, 0x00, 0x00, 0x05, 0x40, 0x73, 0x80, 0x02, 0x8d, 0x01, 0xb4, 0xc6, 0x54, 0x84, +0x00, 0xff, 0x50, 0x43, 0x7f, 0xd8, 0x4c, 0x6e, 0x7f, 0xe0, 0x80, 0x07, 0xec, 0x14, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xa6, 0xc5, 0x81, 0x42, 0x54, 0x21, +0x80, 0x08, 0x54, 0x90, 0x80, 0xff, 0xc2, 0x18, 0xa1, 0x85, 0x50, 0x80, 0x00, 0x14, 0x46, 0x70, +0x00, 0x41, 0x58, 0x73, 0x84, 0xcc, 0xd5, 0x0c, 0x00, 0x03, 0x7f, 0xf8, 0x4c, 0x04, 0xc0, 0x08, +0x9e, 0x37, 0x80, 0x2a, 0x84, 0x46, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x06, 0xb4, 0xc6, 0x4c, 0x64, +0x7f, 0xf5, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x1f, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xcc, 0x96, 0x00, 0x46, 0xf0, 0x01, 0x4a, 0x04, 0x27, 0x83, 0xe0, 0xf1, 0x84, +0xf0, 0x85, 0x9c, 0x49, 0x84, 0x00, 0xf2, 0x83, 0xf0, 0x82, 0xf1, 0x89, 0x48, 0x00, 0x00, 0xce, +0xf2, 0x03, 0xf3, 0x05, 0x8e, 0x58, 0x84, 0x02, 0xf2, 0x87, 0x4c, 0x30, 0x00, 0x60, 0xe6, 0x63, +0xe8, 0x05, 0x84, 0x21, 0x4c, 0x30, 0xc0, 0xbf, 0xd5, 0x0a, 0xf2, 0x05, 0x84, 0x63, 0x4c, 0x21, +0x80, 0x84, 0x84, 0x04, 0x4c, 0x20, 0x40, 0xb7, 0x48, 0x00, 0x00, 0x98, 0x84, 0x20, 0xf1, 0x86, +0xf2, 0x04, 0xf3, 0x03, 0xa6, 0x90, 0xf5, 0x09, 0x8e, 0x70, 0xf2, 0x8a, 0xf3, 0x8b, 0xf1, 0x88, +0x80, 0xe5, 0xd5, 0x37, 0x00, 0x83, 0x80, 0x00, 0xa7, 0x79, 0xa7, 0x3a, 0xf0, 0x07, 0x51, 0xc3, +0x80, 0x03, 0x50, 0xa4, 0x7f, 0xfe, 0x81, 0x28, 0xa1, 0x82, 0x81, 0x05, 0x80, 0xa7, 0x80, 0xe4, +0xd5, 0x1b, 0xa6, 0x18, 0x4c, 0x04, 0xc0, 0x18, 0xa6, 0x19, 0x4c, 0x04, 0x40, 0x15, 0xa6, 0x1a, +0x4c, 0x03, 0xc0, 0x12, 0x80, 0x3c, 0x50, 0x03, 0x7f, 0xdb, 0x80, 0x4a, 0xf5, 0x81, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0xcc, 0xdd, 0x2f, 0xf1, 0x06, 0xf5, 0x01, 0x9c, 0xc9, 0xc8, 0x03, +0x96, 0xd8, 0xf3, 0x86, 0xb4, 0xc6, 0xf2, 0x0b, 0x50, 0x33, 0x7f, 0xd8, 0x4c, 0x61, 0x7f, 0xe3, +0xf3, 0x08, 0x50, 0x14, 0x80, 0x01, 0x9c, 0x19, 0x96, 0x00, 0xf0, 0x88, 0x81, 0x09, 0x99, 0xe9, +0xf0, 0x08, 0xf1, 0x0a, 0xe2, 0x01, 0xe9, 0xc7, 0xf3, 0x06, 0x84, 0x01, 0x40, 0x21, 0x84, 0x03, +0xf1, 0x02, 0x40, 0x00, 0x88, 0x1b, 0xf0, 0x82, 0xd5, 0x65, 0xf3, 0x04, 0xf0, 0x03, 0xa6, 0x98, +0x50, 0x80, 0x7f, 0xf4, 0x9e, 0x91, 0x96, 0x90, 0xe6, 0x43, 0xe9, 0x03, 0x84, 0xe0, 0xd5, 0x07, +0x46, 0x10, 0x00, 0xd2, 0x58, 0x10, 0x82, 0x70, 0x38, 0x70, 0x88, 0x00, 0xf2, 0x07, 0x04, 0x9f, +0x80, 0x02, 0xa1, 0x93, 0xd5, 0x14, 0xf0, 0x04, 0x00, 0x43, 0x7f, 0xec, 0xa6, 0xc0, 0x4c, 0x41, +0xc0, 0x0e, 0xf1, 0x09, 0x50, 0x03, 0x7f, 0xed, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0xcc, 0xdd, 0x2f, 0x84, 0x21, 0x40, 0x90, 0x80, 0x1a, 0xb4, 0xc6, 0x4c, 0x64, 0x7f, 0xed, +0x14, 0x9f, 0x80, 0x02, 0xd5, 0x37, 0xf2, 0x07, 0xf3, 0x03, 0xa1, 0x94, 0x50, 0x71, 0xff, 0xf8, +0x04, 0x8f, 0x80, 0x02, 0xd5, 0x0a, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xcc, 0xdd, 0x2f, +0x84, 0x21, 0xb4, 0xc6, 0x40, 0x80, 0x80, 0x1a, 0x50, 0x03, 0x7f, 0xe8, 0xf1, 0x04, 0x44, 0x20, +0x00, 0x10, 0x4c, 0x63, 0xff, 0xf2, 0xd5, 0x1c, 0xf2, 0x07, 0xf3, 0x03, 0xa1, 0x95, 0x9f, 0xdc, +0x04, 0x8f, 0x80, 0x02, 0xd5, 0x13, 0xf1, 0x04, 0x00, 0x23, 0x7f, 0xf8, 0xa6, 0x08, 0x4c, 0x20, +0x40, 0x0d, 0xf1, 0x09, 0x9e, 0x37, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xcc, +0xdd, 0x2f, 0x84, 0x21, 0x40, 0x80, 0x80, 0x1a, 0xb4, 0xc6, 0x4c, 0x63, 0xff, 0xee, 0x14, 0x8f, +0x80, 0x02, 0xf2, 0x03, 0xb4, 0x42, 0xf2, 0x83, 0xf3, 0x03, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, +0x0f, 0x80, 0x4c, 0x30, 0x7f, 0x2f, 0xf0, 0x02, 0xec, 0x34, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0x96, 0x90, 0x4c, 0x01, 0x00, 0x04, +0x84, 0x00, 0xd5, 0x0b, 0x80, 0x01, 0x84, 0x46, 0x80, 0x23, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0xcc, 0xdd, 0x2f, 0x5c, 0x00, 0x00, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x07, 0x81, 0xf9, +0x46, 0x20, 0x00, 0x35, 0x58, 0x21, 0x0f, 0x54, 0xc8, 0x02, 0xd5, 0x02, 0x84, 0x01, 0x4b, 0xe0, +0x08, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x00, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x8f, 0x54, 0xdd, 0x2f, 0xc0, 0x07, 0x84, 0x00, +0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8c, 0x54, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x8f, 0x54, 0xdd, 0x2f, 0xc0, 0x0e, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x88, 0x37, 0x46, 0x10, +0x00, 0xcb, 0x58, 0x10, 0x8c, 0x54, 0xc8, 0x03, 0x84, 0x03, 0xd5, 0x02, 0x84, 0x05, 0xdd, 0x21, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0x60, 0x00, 0xca, 0x58, 0x63, 0x00, 0x68, 0x84, 0x21, 0x44, 0x00, 0x00, 0x13, 0x46, 0x70, +0x00, 0x02, 0x58, 0x73, 0x8e, 0xb8, 0xdd, 0x26, 0x44, 0x00, 0x06, 0x40, 0xdd, 0x27, 0x84, 0x20, +0x44, 0x00, 0x00, 0x13, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xa0, 0xdd, 0x27, 0x84, 0x21, 0x44, 0x00, +0x00, 0x13, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xa0, 0xdd, 0x27, 0x84, 0x20, 0x44, 0x00, 0x00, 0x13, +0xdd, 0x26, 0x44, 0x00, 0x00, 0xa0, 0xdd, 0x27, 0x84, 0x21, 0x44, 0x00, 0x00, 0x13, 0xdd, 0x26, +0x44, 0x00, 0x00, 0xa0, 0xdd, 0x27, 0x44, 0x00, 0x00, 0x13, 0x84, 0x20, 0xdd, 0x26, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, +0x81, 0x20, 0xb4, 0x61, 0x46, 0x4f, 0xff, 0x0f, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x31, 0x90, 0x02, +0xb6, 0x61, 0x97, 0xc2, 0xb4, 0x61, 0x46, 0x20, 0x04, 0x00, 0x42, 0x01, 0xc0, 0x08, 0xb6, 0x01, +0x04, 0x01, 0x00, 0x6e, 0x42, 0x00, 0x10, 0x09, 0x14, 0x01, 0x00, 0x6e, 0x46, 0x60, 0x00, 0xca, +0x58, 0x63, 0x00, 0x68, 0x84, 0x21, 0x80, 0x07, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x80, 0x00, 0x02, +0x58, 0x84, 0x0e, 0xb8, 0x44, 0x00, 0x00, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x84, 0x20, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x84, 0x21, +0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0xaa, +0xd8, 0x0d, 0x44, 0x10, 0x01, 0x90, 0x46, 0xf0, 0x01, 0x08, 0x14, 0x17, 0x83, 0xe9, 0x84, 0x21, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xfe, 0xd5, 0x0f, 0x84, 0xac, 0xd0, 0x36, 0xe6, 0x0d, +0xe8, 0x06, 0x84, 0xaa, 0xd0, 0x09, 0x84, 0xab, 0xd8, 0x77, 0xd5, 0x06, 0x84, 0xad, 0xd0, 0x4f, +0x84, 0xae, 0xd8, 0x72, 0xd5, 0x40, 0x84, 0x81, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xf7, +0x84, 0x84, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xfb, 0x44, 0x30, 0x00, 0x32, 0x46, 0xf0, +0x01, 0x0f, 0x12, 0x37, 0x81, 0xe1, 0x44, 0x30, 0x00, 0xf0, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x37, +0x81, 0xe0, 0x46, 0x60, 0x00, 0xca, 0x58, 0x63, 0x00, 0x68, 0x44, 0x00, 0x00, 0x13, 0x84, 0x21, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0x05, 0x84, 0x21, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0x46, 0x00, +0x01, 0x0f, 0x58, 0x00, 0x05, 0x3c, 0xd5, 0x21, 0x84, 0x41, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x27, +0x89, 0xf7, 0x84, 0x43, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x27, 0x89, 0xfb, 0x94, 0x53, 0x46, 0xf0, +0x01, 0x0f, 0x12, 0x17, 0x81, 0xe1, 0x44, 0x10, 0x02, 0x80, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x17, +0x81, 0xe0, 0xd5, 0x35, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xf7, 0x84, 0x25, +0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x09, 0xfb, 0xae, 0x40, 0xd5, 0x29, 0x84, 0x81, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x47, 0x89, 0xf7, 0x84, 0x82, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xfb, +0x44, 0x30, 0x00, 0x32, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x37, 0x81, 0xe1, 0x44, 0x30, 0x04, 0x20, +0x46, 0xf0, 0x01, 0x0f, 0x12, 0x37, 0x81, 0xe0, 0x44, 0x00, 0x00, 0x13, 0x84, 0x20, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x80, 0x68, 0xdd, 0x2f, 0x84, 0x04, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, +0x8d, 0x48, 0xdd, 0x2f, 0xd5, 0x04, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x84, 0x00, 0x46, 0xf0, +0x01, 0x38, 0x10, 0x07, 0x89, 0xf8, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x07, 0x89, 0xfc, 0x46, 0xf0, +0x00, 0xcb, 0x58, 0xf7, 0x8c, 0xa4, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0xee, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0x97, 0x82, 0x46, 0x70, 0x00, 0xca, 0x58, 0x73, 0x80, 0x58, 0x80, 0x06, 0x4b, 0xe0, +0x1c, 0x01, 0x81, 0x00, 0xc8, 0x08, 0x80, 0x06, 0x46, 0x70, 0x00, 0xca, 0x58, 0x73, 0x80, 0x68, +0x84, 0x21, 0xd5, 0x0e, 0x80, 0x06, 0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x00, 0x84, 0xa1, 0x4c, 0x82, +0xc0, 0x13, 0x80, 0x06, 0x84, 0x20, 0x46, 0x70, 0x00, 0xca, 0x58, 0x73, 0x80, 0x68, 0xdd, 0x27, +0x44, 0x00, 0x0c, 0x80, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0xb8, 0xdd, 0x2f, 0x80, 0x06, +0x80, 0x28, 0xdd, 0x27, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x44, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, 0x89, 0x84, 0xdd, 0x2f, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x17, 0x89, 0xfe, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x98, 0xbc, 0x80, 0xc0, 0x46, 0x00, 0x01, 0x44, 0x58, 0x00, 0x07, 0xa0, 0x46, 0xf0, 0x00, 0xcb, +0x58, 0xf7, 0x87, 0x04, 0xdd, 0x2f, 0xc0, 0x0f, 0xc6, 0x09, 0x80, 0x06, 0x44, 0x10, 0x00, 0x16, +0x46, 0xf0, 0x00, 0x11, 0x58, 0xf7, 0x8f, 0x70, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, +0x8f, 0x5c, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x70, +0x01, 0x38, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8c, 0x7c, 0xdd, 0x2f, 0x00, 0x53, 0x89, 0xfc, +0x85, 0x01, 0x4c, 0x54, 0x00, 0x94, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x67, 0x89, 0xfb, 0x4c, 0x64, +0x40, 0x0d, 0x44, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, +0x10, 0x63, 0x89, 0xfc, 0x48, 0x00, 0x00, 0x83, 0x84, 0xa4, 0xde, 0x11, 0x80, 0x08, 0x46, 0xf0, +0x00, 0xca, 0x58, 0xf7, 0x83, 0xbc, 0xdd, 0x2f, 0x44, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0xcb, +0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, 0x10, 0x83, 0x89, 0xfc, 0xd5, 0x70, 0x84, 0xa3, 0xde, 0x43, +0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x04, 0x0c, 0x00, 0x10, 0x00, 0x2c, 0x44, 0x50, 0x00, 0xf0, +0xd9, 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x44, 0x50, 0x00, 0x30, 0xd0, 0x1c, 0x44, 0x50, 0x00, 0xb0, +0xd8, 0x0a, 0xd5, 0x18, 0x9d, 0x6a, 0xd9, 0x1e, 0x00, 0x00, 0x00, 0x2b, 0x44, 0x50, 0x00, 0x23, +0xd8, 0x55, 0xd5, 0x10, 0x44, 0x50, 0x00, 0x70, 0xd0, 0x0d, 0x8c, 0xb9, 0xd0, 0x0b, 0x8c, 0xb3, +0xd0, 0x09, 0x9d, 0x69, 0xd0, 0x07, 0x5c, 0xf0, 0x00, 0x20, 0xe9, 0x48, 0x5c, 0xf0, 0x00, 0x2a, +0xe8, 0x45, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x80, 0x90, 0x84, 0x21, 0x44, 0x00, 0x00, 0x1a, +0xd5, 0x0f, 0x9f, 0x69, 0xd9, 0x3b, 0x00, 0x00, 0x00, 0x2b, 0x44, 0x50, 0x00, 0x91, 0xd8, 0x36, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x80, 0x90, 0x84, 0x22, 0x44, 0x00, 0x00, 0x1a, 0x84, 0x40, +0xdd, 0x23, 0xd5, 0x2c, 0x84, 0xa2, 0xde, 0x07, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8c, 0xdc, +0xdd, 0x2f, 0xd5, 0x24, 0x84, 0xa5, 0xde, 0x09, 0x44, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0xcb, +0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, 0xd5, 0x1a, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, +0xb4, 0x20, 0x42, 0x10, 0xcc, 0x0b, 0xc1, 0x05, 0xb4, 0x20, 0x42, 0x10, 0xcc, 0x09, 0xd5, 0x04, +0xb4, 0x20, 0x42, 0x10, 0xcc, 0x08, 0xb6, 0x20, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x04, 0x0c, +0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x86, 0xac, 0xdd, 0x2f, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x17, 0x89, 0xf8, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8c, 0xa4, 0xdd, 0x2f, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x07, 0x89, 0xfb, 0xc8, 0x08, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8f, 0xcc, 0xdd, 0x2f, +0x48, 0x00, 0x00, 0xce, 0x84, 0xa1, 0x4c, 0x02, 0x80, 0xcb, 0x84, 0xa4, 0xd8, 0x69, 0x46, 0x00, +0x01, 0x4d, 0x58, 0x00, 0x04, 0x0c, 0xa0, 0x44, 0x46, 0x22, 0xdf, 0xf1, 0x40, 0x50, 0xa0, 0x09, +0x40, 0x52, 0xa0, 0x08, 0x58, 0x21, 0x02, 0x00, 0xda, 0x12, 0x46, 0x10, 0x10, 0x00, 0xa1, 0x45, +0x58, 0x10, 0x82, 0x01, 0xd9, 0x0c, 0x00, 0x10, 0x00, 0x18, 0xc9, 0x09, 0x46, 0x26, 0xb0, 0x00, +0x04, 0x50, 0x00, 0x08, 0x58, 0x21, 0x01, 0x00, 0x4c, 0x51, 0x00, 0xa0, 0xa4, 0x47, 0x44, 0x50, +0x19, 0x03, 0x4c, 0x12, 0xc0, 0xa0, 0x02, 0x10, 0x00, 0x08, 0x44, 0x50, 0x80, 0x01, 0x4c, 0x12, +0xc0, 0x9a, 0x02, 0x10, 0x00, 0x09, 0x44, 0x50, 0x01, 0x02, 0x4c, 0x12, 0xc0, 0x94, 0x00, 0x10, +0x00, 0x14, 0x84, 0xa5, 0x4c, 0x12, 0xc0, 0x8f, 0xa0, 0x45, 0x46, 0x21, 0x80, 0x30, 0x40, 0x50, +0xa0, 0x09, 0x40, 0x52, 0xa0, 0x08, 0x58, 0x21, 0x03, 0x00, 0x4c, 0x51, 0x40, 0x84, 0x00, 0x10, +0x00, 0x18, 0x44, 0x50, 0x00, 0x12, 0xd9, 0x7e, 0x00, 0x10, 0x00, 0x1b, 0x8c, 0xbb, 0xd9, 0x7a, +0x00, 0x10, 0x00, 0x1c, 0x84, 0xa1, 0xd9, 0x76, 0xa0, 0x47, 0x40, 0x10, 0xa0, 0x08, 0x92, 0x30, +0x40, 0x10, 0xa0, 0x08, 0x44, 0x50, 0x02, 0x00, 0xd9, 0x6d, 0x00, 0x00, 0x00, 0x1f, 0x84, 0xa1, +0xd8, 0x69, 0x46, 0xf0, 0x01, 0x4d, 0x00, 0x17, 0x84, 0x2c, 0x84, 0xa1, 0xd9, 0x63, 0x46, 0xf0, +0x01, 0x4d, 0x00, 0x07, 0x84, 0x34, 0x84, 0xa7, 0xd0, 0x58, 0x84, 0x2c, 0xd5, 0x54, 0x84, 0xa3, +0xd8, 0x13, 0x46, 0xf0, 0x01, 0x4d, 0x00, 0x57, 0x84, 0x2e, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, +0x88, 0x8c, 0xda, 0x50, 0x46, 0xf0, 0x01, 0x4d, 0x00, 0x17, 0x84, 0x2f, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x07, 0x88, 0x8d, 0xd5, 0x40, 0x84, 0xa2, 0xd8, 0x17, 0x46, 0x10, 0x01, 0x4d, 0x58, 0x10, +0x84, 0x0c, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x08, 0x78, 0x00, 0x50, 0x80, 0x0e, 0xa6, 0x80, +0xda, 0x39, 0x9c, 0x04, 0x8c, 0x32, 0x84, 0x44, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xcc, +0xdd, 0x2f, 0xc8, 0x30, 0xd5, 0x2a, 0x84, 0xa5, 0xd8, 0x32, 0x46, 0x70, 0x01, 0x38, 0x00, 0x13, +0x89, 0xfd, 0x46, 0x20, 0x01, 0x4d, 0x58, 0x21, 0x04, 0x0c, 0x98, 0x0a, 0x46, 0x60, 0x01, 0x38, +0x58, 0x63, 0x08, 0x98, 0x00, 0x50, 0x00, 0x0f, 0xa6, 0x31, 0xd8, 0x1c, 0x80, 0x06, 0x08, 0x20, +0x00, 0x0f, 0x46, 0x30, 0x01, 0x4d, 0x58, 0x31, 0x84, 0x29, 0x98, 0x4b, 0x8e, 0x4e, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0xcc, 0xdd, 0x2f, 0xc0, 0x08, 0x00, 0x03, 0x89, 0xfd, 0x84, 0x2e, +0x38, 0x03, 0x00, 0x00, 0x4c, 0x00, 0xc0, 0x07, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x8f, 0xcc, +0xdd, 0x2f, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xf8, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x01, 0x40, 0x10, +0x40, 0x08, 0x92, 0x39, 0xc9, 0x04, 0x44, 0x0f, 0xff, 0xec, 0xd5, 0x08, 0x54, 0x00, 0x01, 0xff, +0x46, 0xf0, 0x00, 0x43, 0x58, 0xf7, 0x80, 0x54, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x84, 0x01, 0x84, 0x20, 0x84, 0x48, 0x46, 0xf0, +0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x22, 0xb4, 0xc0, 0x84, 0x0e, 0xae, 0x30, +0x84, 0x06, 0xae, 0x31, 0x84, 0x01, 0xae, 0x32, 0x44, 0x0f, 0xff, 0xb9, 0xae, 0x33, 0x84, 0xe0, +0x84, 0x1c, 0xae, 0x34, 0xaf, 0xf5, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x80, 0x40, 0xdd, 0x20, +0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x82, 0xe8, 0xdd, 0x2f, 0xae, 0x36, 0xaf, 0xf7, 0x84, 0x20, +0x84, 0x01, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0xa6, 0x02, 0x84, 0xa1, +0xd8, 0x07, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x83, 0x14, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, +0x00, 0x50, 0x58, 0xf7, 0x82, 0x04, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x80, 0x01, 0x0f, 0x58, 0x84, 0x03, 0x00, +0x54, 0x90, 0x00, 0xff, 0x47, 0xc0, 0x00, 0x37, 0x59, 0xce, 0x07, 0x80, 0x50, 0xa4, 0x00, 0x90, +0x00, 0x64, 0x00, 0x06, 0x44, 0x10, 0x00, 0xff, 0x44, 0x00, 0x00, 0x3e, 0x4c, 0x60, 0x80, 0x59, +0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0xb4, 0xdd, 0x2f, 0xc0, 0x52, 0x80, 0x09, 0x8c, 0xcc, +0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0x90, 0xdd, 0x2f, 0x97, 0xb0, 0x84, 0x20, 0x9c, 0xb2, +0xc0, 0x47, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0x50, 0x44, +0x00, 0x0c, 0x50, 0x14, 0x00, 0x0e, 0xc0, 0x42, 0xb4, 0x40, 0x50, 0x71, 0x00, 0x0d, 0x50, 0x31, +0x00, 0x0a, 0x80, 0x07, 0xc2, 0x3b, 0x44, 0x50, 0x00, 0x3e, 0xaf, 0x50, 0x84, 0xa1, 0xaf, 0x91, +0x10, 0x91, 0x00, 0x02, 0xaf, 0x53, 0x00, 0x54, 0x00, 0x04, 0xaf, 0x54, 0x00, 0x54, 0x00, 0x05, +0xaf, 0x55, 0x00, 0x54, 0x00, 0x08, 0xaf, 0x56, 0x00, 0x54, 0x00, 0x09, 0xaf, 0x57, 0x00, 0x54, +0x00, 0x0a, 0x10, 0x51, 0x00, 0x08, 0x00, 0x54, 0x00, 0x0b, 0x10, 0x51, 0x00, 0x09, 0xa7, 0x60, +0xaf, 0x58, 0xa7, 0x21, 0xaf, 0x19, 0x00, 0x34, 0x00, 0x06, 0x10, 0x31, 0x00, 0x0c, 0x00, 0x24, +0x00, 0x06, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x00, 0x14, 0x00, 0x06, +0x00, 0x24, 0x00, 0x07, 0x84, 0x01, 0x38, 0x23, 0x84, 0x08, 0x84, 0x20, 0xdd, 0x3c, 0x50, 0x84, +0x00, 0x30, 0xe3, 0x48, 0xe8, 0x9e, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x07, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xd4, 0x50, 0x1f, 0x80, 0x04, +0xa8, 0x89, 0x84, 0x02, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x83, 0xa4, 0xdd, 0x2f, 0xec, 0x2c, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x50, 0x61, 0x00, 0x10, +0x54, 0xa0, 0x00, 0xff, 0x51, 0xc1, 0x00, 0x40, 0x80, 0x26, 0x85, 0x00, 0x85, 0x22, 0xa6, 0x0e, +0x44, 0x40, 0x00, 0xff, 0x50, 0x30, 0x00, 0x0a, 0x50, 0x10, 0x80, 0x30, 0x88, 0x69, 0x50, 0x24, +0x00, 0x01, 0x4c, 0x02, 0x00, 0x06, 0x54, 0x91, 0x80, 0xff, 0x54, 0x81, 0x00, 0xff, 0x40, 0xfe, +0x04, 0x06, 0xe8, 0xee, 0x4e, 0x83, 0x00, 0x04, 0x84, 0x01, 0xd5, 0x61, 0x44, 0x00, 0x00, 0x3e, +0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, 0x81, 0xb4, 0xdd, 0x2f, 0xc0, 0x58, 0x80, 0x0a, 0x46, 0xf0, +0x00, 0x0d, 0x58, 0xf7, 0x81, 0x90, 0xdd, 0x2f, 0xc0, 0x51, 0x84, 0x01, 0x84, 0x20, 0x50, 0x24, +0x80, 0x02, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc0, 0x45, 0xb4, 0xe0, +0xc7, 0x43, 0x44, 0x00, 0x00, 0x3e, 0xae, 0x38, 0x84, 0xa2, 0x10, 0x93, 0x80, 0x01, 0x10, 0xa3, +0x80, 0x02, 0x4c, 0xa2, 0xc0, 0x32, 0x10, 0x83, 0x80, 0x03, 0x46, 0xa0, 0x00, 0x0d, 0x58, 0xa5, +0x00, 0x70, 0x9d, 0xfc, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, 0x84, 0x98, 0xa6, 0xb6, 0x44, 0x30, +0x00, 0xff, 0x80, 0x07, 0x50, 0x13, 0x00, 0x08, 0x50, 0x83, 0x80, 0x09, 0x4c, 0x21, 0x80, 0x18, +0xa7, 0x34, 0x18, 0x40, 0x00, 0x01, 0xa6, 0xb5, 0x18, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, +0xa6, 0xf6, 0x50, 0x13, 0x00, 0x0e, 0x10, 0x33, 0x80, 0x08, 0x80, 0x08, 0xa6, 0xb6, 0x4b, 0xe0, +0x24, 0x01, 0xa7, 0xf6, 0xa7, 0x37, 0x88, 0xe8, 0x18, 0x43, 0x80, 0x01, 0x50, 0x63, 0x00, 0x30, +0x40, 0xfe, 0x18, 0x06, 0xe8, 0xdc, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, +0x87, 0x80, 0xdd, 0x2f, 0xd5, 0x03, 0x84, 0x07, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x0f, +0x02, 0x07, 0x81, 0x7a, 0x54, 0x00, 0x00, 0x30, 0xc8, 0x08, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, +0x85, 0x58, 0xdd, 0x2f, 0x84, 0x02, 0xd5, 0x14, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0xc4, +0xdd, 0x2f, 0xc8, 0x03, 0x84, 0x01, 0xd5, 0x0c, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0x62, +0xdd, 0x20, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0x98, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x0f, +0x02, 0x07, 0x81, 0x7a, 0x54, 0x00, 0x00, 0x30, 0xc8, 0x07, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, +0x85, 0x58, 0xdd, 0x2f, 0xd5, 0x2d, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0xc4, 0xdd, 0x2f, +0xc0, 0x27, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa4, 0x00, 0x10, 0x00, 0x21, 0x84, 0xa2, +0xd1, 0x0b, 0x84, 0xa3, 0xd1, 0x06, 0x84, 0xa1, 0xd9, 0x0c, 0x04, 0x00, 0x00, 0x1b, 0xd5, 0x08, +0x04, 0x00, 0x00, 0x1b, 0xdd, 0x20, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xc5, 0xdd, 0x20, +0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xc1, 0xdd, 0x20, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, +0x85, 0x58, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0x98, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0x80, 0x46, 0xf0, 0x01, 0x4a, +0x10, 0x47, 0x8f, 0x7c, 0x46, 0xf0, 0x01, 0x4a, 0x10, 0x47, 0x8f, 0x7d, 0x46, 0x60, 0x00, 0x41, +0x58, 0x63, 0x04, 0xbc, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0f, 0x1c, 0x84, 0x20, 0x44, 0x20, +0x07, 0x00, 0xdd, 0x26, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x5c, 0x84, 0x20, 0x44, 0x20, +0x0b, 0x00, 0xdd, 0x26, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x02, 0xc4, 0x84, 0x20, 0x44, 0x20, +0x06, 0x00, 0xdd, 0x26, 0x46, 0x00, 0x01, 0x4c, 0x58, 0x00, 0x0c, 0x78, 0x84, 0x20, 0x44, 0x20, +0x07, 0x00, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x20, 0x03, 0x00, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, +0x04, 0x3c, 0xdd, 0x26, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0x57, 0xdd, 0x20, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x07, 0x82, 0x58, 0xdd, 0x20, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8c, 0x98, 0x96, 0x01, 0x84, 0xe0, +0xb4, 0xc1, 0x9c, 0x4c, 0xc6, 0x26, 0xa5, 0x74, 0xd8, 0x24, 0xa4, 0x35, 0xc0, 0x08, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, 0x00, 0x0a, 0xdd, 0x21, 0xa4, 0x36, 0xc0, 0x08, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, 0x00, 0x0c, 0xdd, 0x21, 0x80, 0x06, +0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, +0x84, 0x00, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8c, 0x98, 0x38, 0x00, 0x9e, 0x0a, 0xd5, 0x07, +0x9d, 0xf9, 0x44, 0x50, 0x00, 0x42, 0xdf, 0xd5, 0x44, 0x00, 0x00, 0x12, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, +0x89, 0xf4, 0x80, 0xc1, 0x96, 0x00, 0xc2, 0x12, 0x84, 0xa5, 0xd8, 0x10, 0xa4, 0x36, 0x46, 0xf0, +0x00, 0xcc, 0x58, 0xf7, 0x87, 0x20, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4c, +0x80, 0x46, 0x80, 0x20, 0x44, 0x00, 0x00, 0xd2, 0xdd, 0x23, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x80, 0x01, 0x38, 0x00, 0x64, 0x09, 0xf4, 0xce, 0x48, +0x46, 0x70, 0x00, 0x41, 0x58, 0x73, 0x84, 0xbc, 0x46, 0x00, 0x01, 0x3a, 0x58, 0x00, 0x00, 0x60, +0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0xdd, 0x27, 0x46, 0x00, 0x01, 0x44, 0x58, 0x00, 0x06, 0x14, +0x80, 0x26, 0x44, 0x20, 0x01, 0x2c, 0xdd, 0x27, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x00, 0x84, +0x80, 0x26, 0x44, 0x20, 0x0e, 0x10, 0xdd, 0x27, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0xa0, +0x80, 0x26, 0x44, 0x20, 0x03, 0xd8, 0xdd, 0x27, 0x80, 0x26, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, +0x0c, 0x98, 0x44, 0x20, 0x01, 0x08, 0xdd, 0x27, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x45, +0x46, 0x10, 0x01, 0x44, 0x58, 0x10, 0x86, 0x14, 0x46, 0x00, 0x01, 0x3a, 0x58, 0x00, 0x00, 0x60, +0x46, 0x20, 0x01, 0x49, 0x58, 0x21, 0x00, 0x84, 0x44, 0x30, 0x00, 0x96, 0xdd, 0x24, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x07, 0x82, 0x56, 0xdd, 0x20, 0x84, 0x01, 0x10, 0x04, 0x09, 0xf4, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x41, 0x58, 0x63, +0x04, 0xbc, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa4, 0x84, 0x20, 0x44, 0x20, 0x00, 0x78, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, 0x01, 0x3d, 0x58, 0x00, 0x04, 0x00, 0x84, 0x20, 0x44, 0x20, +0x2e, 0xe0, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, 0x01, 0x3a, 0x58, 0x00, 0x00, 0x70, 0x84, 0x20, +0x44, 0x20, 0x20, 0xd0, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa4, +0x46, 0x20, 0x00, 0xcb, 0x58, 0x21, 0x02, 0xe8, 0x14, 0x20, 0x00, 0x18, 0x46, 0x20, 0x00, 0xcf, +0x58, 0x21, 0x06, 0x7c, 0x14, 0x20, 0x00, 0x16, 0x46, 0x20, 0x00, 0xd0, 0x58, 0x21, 0x08, 0xcc, +0x14, 0x20, 0x00, 0x17, 0x46, 0x20, 0x00, 0xc9, 0x58, 0x21, 0x02, 0x24, 0x14, 0x20, 0x00, 0x19, +0x46, 0x20, 0x00, 0xcf, 0x58, 0x21, 0x05, 0xec, 0x14, 0x20, 0x00, 0x1a, 0x46, 0x20, 0x00, 0xcc, +0x58, 0x21, 0x06, 0x18, 0x14, 0x20, 0x00, 0x1d, 0x46, 0x20, 0x00, 0xcf, 0x58, 0x21, 0x04, 0xb8, +0x46, 0x10, 0x00, 0xcc, 0x58, 0x10, 0x89, 0x38, 0x14, 0x20, 0x00, 0x1b, 0x46, 0x20, 0x00, 0xcf, +0x58, 0x21, 0x02, 0x80, 0x14, 0x20, 0x00, 0x1c, 0x14, 0x10, 0x00, 0x15, 0xdd, 0x21, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x01, 0x49, 0x58, 0x63, +0x0e, 0xa4, 0x04, 0x03, 0x00, 0x16, 0xdd, 0x20, 0x44, 0x50, 0x01, 0xf4, 0x84, 0x60, 0x84, 0x80, +0x50, 0x03, 0x00, 0x38, 0x12, 0x53, 0x00, 0x13, 0x84, 0x20, 0x44, 0x50, 0x00, 0x64, 0x44, 0x20, +0x00, 0x1c, 0x12, 0x53, 0x00, 0x12, 0x10, 0x43, 0x00, 0x30, 0x10, 0x33, 0x00, 0x22, 0x10, 0x33, +0x00, 0x20, 0x10, 0x33, 0x00, 0x21, 0x12, 0x43, 0x00, 0x14, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0xbc, 0xdd, 0x2f, 0x84, 0x00, 0x14, 0x03, 0x00, 0x0d, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x97, 0x81, 0x9e, 0x71, 0x96, 0x49, 0x46, 0x30, 0x01, 0x4d, +0x58, 0x31, 0x87, 0x3c, 0x84, 0x80, 0x84, 0xa0, 0x5c, 0x10, 0x80, 0x31, 0x44, 0x00, 0x00, 0x32, +0x40, 0x60, 0x04, 0x1a, 0xad, 0x5b, 0xa9, 0x1b, 0xad, 0x59, 0xad, 0x5a, 0xa9, 0x1c, 0xa9, 0x1a, +0x80, 0x24, 0x46, 0x00, 0x01, 0x39, 0x58, 0x00, 0x0d, 0x40, 0x94, 0xb4, 0x46, 0xf0, 0x00, 0x41, +0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x39, 0x58, 0x00, 0x0d, 0x40, 0x84, 0x21, +0xd5, 0x03, 0xa8, 0x1b, 0x9c, 0x49, 0x80, 0x60, 0x8c, 0x10, 0xe0, 0x26, 0xe9, 0xfb, 0x46, 0x40, +0x01, 0x4d, 0x58, 0x42, 0x07, 0x3c, 0x46, 0x50, 0x01, 0x39, 0x58, 0x52, 0x8d, 0x40, 0xad, 0xa0, +0xa9, 0x5b, 0xa8, 0xe4, 0xad, 0xa3, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x02, 0xb0, 0x84, 0x20, +0x44, 0x20, 0x00, 0x14, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x46, 0x00, +0x01, 0x41, 0x58, 0x00, 0x02, 0xb0, 0x84, 0x20, 0xa8, 0x43, 0xa8, 0x04, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x97, 0x81, 0x9e, 0x71, 0x96, 0x49, 0x84, 0x60, 0x5c, 0x10, +0x80, 0x31, 0x44, 0x00, 0x00, 0x32, 0x84, 0xa0, 0x40, 0x60, 0x04, 0x1a, 0x46, 0xf0, 0x01, 0x4d, +0x12, 0x57, 0x83, 0xa8, 0x46, 0xf0, 0x01, 0x4d, 0x14, 0x37, 0x81, 0xd5, 0x80, 0x23, 0x46, 0x00, +0x01, 0x44, 0x58, 0x00, 0x07, 0xa8, 0x94, 0xb5, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x46, 0x00, 0x01, 0x44, 0x58, 0x00, 0x07, 0xa8, 0x80, 0x20, 0x84, 0x41, 0xd5, 0x04, +0xa8, 0x0f, 0x9c, 0x91, 0x80, 0x20, 0x50, 0x00, 0x00, 0x20, 0xe0, 0x46, 0xe9, 0xfa, 0x46, 0x20, +0x01, 0x44, 0x58, 0x21, 0x07, 0xa8, 0x46, 0xf0, 0x01, 0x4d, 0x12, 0x67, 0x83, 0xa9, 0xa8, 0x8f, +0x46, 0xf0, 0x01, 0x4d, 0x14, 0x17, 0x81, 0xd6, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xf4, 0x80, 0x40, 0x08, 0x91, 0x00, 0x01, 0x80, 0xe1, 0x46, 0x80, 0x00, 0x41, +0x58, 0x84, 0x04, 0x98, 0x80, 0x22, 0x80, 0x1f, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xf0, +0x01, 0x44, 0x04, 0x37, 0x81, 0xe4, 0x02, 0x2f, 0x80, 0x02, 0xb4, 0x3f, 0x80, 0x09, 0x80, 0xdf, +0xdd, 0x23, 0xc8, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x13, 0xa1, 0x86, 0xc6, 0x08, 0x80, 0x07, +0x80, 0x26, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0x00, 0xd5, 0x0a, 0x80, 0x07, 0x80, 0x26, +0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x80, 0x06, 0xec, 0x0c, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc1, 0x97, 0xc0, 0x84, 0x20, +0x80, 0x06, 0x44, 0x20, 0x00, 0x1e, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, +0xaf, 0xf7, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x17, 0x81, 0xe1, 0x80, 0x07, 0xdd, 0x21, 0x80, 0xe0, +0xc8, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x1e, 0xa6, 0x06, 0x46, 0x80, 0x00, 0x41, 0x58, 0x84, +0x04, 0x98, 0xae, 0x36, 0x80, 0x27, 0x84, 0x46, 0x80, 0x06, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x13, +0x80, 0x08, 0x50, 0x03, 0x00, 0x08, 0x44, 0x20, 0x00, 0x10, 0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x7e, +0xc9, 0x03, 0x80, 0x01, 0xd5, 0x07, 0x50, 0x03, 0x00, 0x18, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, +0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x85, 0x00, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, 0x8a, 0x02, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, 0x8a, 0x03, +0x84, 0xe0, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, 0x8a, 0x04, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x77, +0x82, 0x84, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x77, 0x8a, 0x05, 0x80, 0x27, 0x46, 0x00, 0x01, 0x44, +0x58, 0x00, 0x07, 0x44, 0x44, 0x20, 0x00, 0x30, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x46, 0x50, 0x00, 0xd1, 0x58, 0x52, 0x8c, 0x1c, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, +0x8a, 0x06, 0x46, 0x20, 0x01, 0x44, 0x58, 0x21, 0x07, 0x74, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x57, +0x82, 0x85, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0e, 0xf4, 0x46, 0x30, 0x01, 0x4d, 0x58, 0x31, +0x83, 0x78, 0xa9, 0x17, 0x46, 0x40, 0x00, 0xd1, 0x58, 0x42, 0x03, 0x74, 0xa9, 0x1d, 0x46, 0x40, +0x00, 0xd0, 0x58, 0x42, 0x00, 0xec, 0xa9, 0x11, 0x46, 0x40, 0x00, 0xd0, 0x58, 0x42, 0x00, 0x10, +0xa9, 0x12, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0f, 0xa0, 0xa9, 0x13, 0x46, 0x40, 0x00, 0xcf, +0x58, 0x42, 0x0f, 0x4c, 0xa9, 0x14, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0e, 0x8c, 0xa9, 0x15, +0x46, 0x40, 0x00, 0xc8, 0x58, 0x42, 0x0d, 0x7c, 0xa9, 0x16, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, +0x0e, 0x08, 0x46, 0x60, 0x01, 0x44, 0x58, 0x63, 0x0d, 0xe8, 0x14, 0x41, 0x00, 0x08, 0x46, 0x40, +0x00, 0xcc, 0x58, 0x42, 0x09, 0x94, 0xb6, 0x86, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0d, 0xa4, +0xa9, 0x31, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0d, 0x2c, 0xa9, 0x32, 0x46, 0x40, 0x00, 0xcf, +0x58, 0x42, 0x0c, 0xe4, 0xa9, 0x33, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0b, 0xcc, 0xa9, 0x34, +0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x0a, 0xa0, 0xa9, 0x35, 0x46, 0x40, 0x00, 0xc8, 0x58, 0x42, +0x0d, 0xac, 0xa9, 0x36, 0x46, 0x40, 0x00, 0xc8, 0x58, 0x42, 0x0e, 0x1c, 0xb6, 0x83, 0x46, 0x40, +0x00, 0xc8, 0x58, 0x42, 0x0e, 0xa8, 0xa9, 0x19, 0x46, 0x40, 0x00, 0xc8, 0x58, 0x42, 0x0f, 0x2c, +0xa9, 0x1c, 0x46, 0x40, 0x00, 0xc8, 0x58, 0x42, 0x0f, 0xa0, 0xa9, 0x1b, 0x46, 0x10, 0x00, 0xcc, +0x58, 0x10, 0x8a, 0x34, 0x46, 0x40, 0x00, 0xcf, 0x58, 0x42, 0x09, 0xf0, 0xb6, 0x22, 0xa9, 0x1a, +0x80, 0x07, 0xdd, 0x21, 0xb4, 0x26, 0x80, 0x07, 0xdd, 0x21, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0xc6, 0x84, 0x80, 0x46, 0xf0, 0x01, 0x38, 0x12, 0x67, +0x84, 0xec, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x47, 0x89, 0xf3, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x38, +0x10, 0x47, 0x89, 0xf2, 0x46, 0xf0, 0x01, 0x38, 0x14, 0x17, 0x82, 0x39, 0x46, 0x00, 0x01, 0x46, +0x58, 0x00, 0x0b, 0x04, 0x44, 0x20, 0x25, 0x80, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x54, 0x80, +0x80, 0xff, 0x5c, 0x14, 0x00, 0x21, 0x97, 0x80, 0x97, 0xd2, 0x80, 0x01, 0x46, 0x20, 0x00, 0xd2, +0x58, 0x21, 0x01, 0xf4, 0x84, 0x20, 0x44, 0x30, 0x21, 0xf5, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x86, 0x88, 0xdd, 0x2f, 0xc6, 0x05, 0x50, 0x84, 0x00, 0x21, 0x54, 0x84, 0x00, 0xff, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x0c, 0x98, 0x38, 0x60, 0x22, 0x02, 0xc6, 0x64, 0xa6, 0x31, 0xaf, 0xf2, +0xc8, 0x32, 0x20, 0x13, 0x00, 0x04, 0xe0, 0xe1, 0xe9, 0x4d, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x4e, 0xa4, 0x74, 0x80, 0x47, 0xdd, 0x23, 0xa6, 0x37, 0x84, 0x21, 0x9e, 0x01, 0x96, 0x00, +0xae, 0x71, 0x5c, 0xf0, 0x00, 0xfe, 0xe8, 0x3e, 0xa4, 0x36, 0xc0, 0x08, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, 0x00, 0x0c, 0xdd, 0x21, 0xa6, 0x77, 0x44, 0x00, 0x00, 0xa0, +0x42, 0x00, 0x80, 0x24, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x49, 0x80, 0x46, 0x46, 0x10, +0x00, 0xc9, 0x58, 0x10, 0x8e, 0x04, 0x84, 0x61, 0xdd, 0x24, 0x84, 0x20, 0xac, 0x36, 0xa8, 0x74, +0xa8, 0x75, 0xd5, 0x20, 0x20, 0x03, 0x00, 0x05, 0xa4, 0xf5, 0xe0, 0x07, 0xe9, 0x13, 0xcb, 0x1a, +0xa6, 0x76, 0x44, 0x00, 0x06, 0x40, 0x42, 0x00, 0x80, 0x24, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, +0x82, 0x49, 0x80, 0x46, 0x46, 0x10, 0x00, 0xc9, 0x58, 0x10, 0x8e, 0x1c, 0xdd, 0x24, 0xac, 0x35, +0xd5, 0x09, 0xc3, 0x08, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, 0x00, 0x0a, +0xdd, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x54, 0x80, 0x27, 0x80, 0x06, 0xdd, 0x22, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4c, 0x80, 0x28, 0x80, 0x46, 0x44, 0x00, 0x00, 0xd3, +0xdd, 0x23, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, +0x80, 0xc0, 0xc8, 0x02, 0xd5, 0x05, 0xb4, 0x20, 0x84, 0x00, 0x40, 0x00, 0x04, 0x06, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x21, 0x17, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x81, 0x3c, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x89, 0xbc, 0xdd, 0x2f, +0xc0, 0x03, 0x84, 0xe0, 0xd5, 0x04, 0xb4, 0xe6, 0xb4, 0x07, 0xb6, 0x06, 0xf0, 0x01, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x80, 0x07, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x81, 0x00, 0x80, 0xc1, 0x46, 0xf0, 0x01, 0x4a, +0x04, 0x77, 0x83, 0xe6, 0x51, 0xc0, 0x80, 0x08, 0x46, 0xa0, 0x00, 0x41, 0x58, 0xa5, 0x04, 0xcc, +0xd5, 0x18, 0x00, 0x14, 0x80, 0x00, 0x00, 0x54, 0x00, 0x00, 0xd9, 0x12, 0x00, 0x54, 0x80, 0x01, +0xa6, 0x35, 0xd8, 0x0e, 0x50, 0x03, 0xff, 0x92, 0x80, 0x3c, 0x84, 0x46, 0x4b, 0xe0, 0x28, 0x01, +0xc8, 0x07, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x6a, 0x80, 0x09, 0xd5, 0x3b, 0xb4, 0xe7, +0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x98, 0x50, 0x93, 0xff, 0x90, 0x4c, 0x70, 0x7f, 0xe3, +0x20, 0x13, 0x00, 0x07, 0x20, 0x04, 0x00, 0x01, 0xe0, 0x20, 0xe9, 0x2f, 0x46, 0x90, 0x00, 0xcc, +0x58, 0x94, 0x8e, 0x4c, 0x9c, 0x3c, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x02, 0xd5, 0x0c, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x17, 0x82, 0x6f, 0x20, 0x03, 0x00, 0x07, 0xdd, 0x21, 0xc0, 0x1e, 0x9c, 0x3c, +0x4b, 0xe0, 0x24, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x6e, 0x80, 0x46, 0x80, 0x28, +0xdd, 0x23, 0x80, 0xe0, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x4f, 0x00, 0x33, 0x80, 0x09, +0xa6, 0xb8, 0xa6, 0x39, 0x9c, 0x7a, 0xdd, 0x24, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x6a, +0x80, 0x07, 0x80, 0x28, 0x80, 0x46, 0xdd, 0x23, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x80, 0x20, 0x20, 0x30, 0x80, 0x02, 0x00, 0x90, +0x00, 0x01, 0x01, 0xc0, 0x80, 0x05, 0xa6, 0x00, 0xf3, 0x81, 0x40, 0x94, 0xa0, 0x08, 0x20, 0x30, +0x80, 0x03, 0x89, 0x20, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x51, 0xb6, 0x7f, 0x40, 0x94, +0x80, 0x13, 0x80, 0x09, 0x00, 0xa0, 0x80, 0x04, 0xdd, 0x22, 0x40, 0x10, 0x60, 0x09, 0x40, 0x30, +0x20, 0x09, 0x40, 0x20, 0x40, 0x09, 0x10, 0x1f, 0x80, 0x0b, 0x10, 0x3f, 0x80, 0x09, 0x10, 0x2f, +0x80, 0x0a, 0x10, 0x0f, 0x80, 0x08, 0x50, 0x1f, 0x80, 0x14, 0xf6, 0x02, 0xb6, 0xc1, 0x97, 0xb0, +0xa6, 0x09, 0xa7, 0xca, 0xc8, 0x03, 0x84, 0x02, 0xd5, 0x52, 0x50, 0x05, 0x7f, 0xff, 0x96, 0x01, +0x5c, 0xf0, 0x00, 0x3c, 0xe9, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x49, 0x5e, 0x03, 0x80, 0x21, +0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x20, 0xcd, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xc6, 0x03, 0x50, 0x73, 0x80, 0x21, 0x46, 0x00, +0x01, 0x38, 0x58, 0x00, 0x0c, 0x98, 0x38, 0x00, 0x1e, 0x02, 0xc0, 0x03, 0x84, 0x0c, 0xd5, 0x2f, +0x46, 0x60, 0x01, 0x4a, 0x58, 0x63, 0x0f, 0xa0, 0x00, 0x83, 0x00, 0x00, 0x4e, 0x82, 0x00, 0x09, +0x8c, 0xd8, 0x46, 0x50, 0x01, 0x4b, 0x58, 0x52, 0x83, 0x78, 0xde, 0xf7, 0xd5, 0x1f, 0xc6, 0x1e, +0x80, 0x06, 0x80, 0x28, 0x44, 0x20, 0x00, 0x18, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0c, 0x98, 0x38, 0x60, 0x1e, 0x0a, 0x84, 0x01, +0xae, 0x30, 0xf3, 0x01, 0xae, 0xf4, 0xb4, 0x1f, 0x10, 0xa3, 0x00, 0x06, 0xae, 0x35, 0x11, 0xc3, +0x00, 0x07, 0x12, 0x93, 0x00, 0x04, 0x80, 0x08, 0xd5, 0x02, 0x84, 0x07, 0xec, 0x1c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x81, 0x41, 0x54, 0x80, 0x00, 0xff, +0x97, 0xd0, 0xc1, 0x74, 0xc7, 0x73, 0x84, 0xae, 0x4c, 0x82, 0xc0, 0x05, 0x50, 0x93, 0x80, 0x03, +0xd5, 0x0e, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x57, 0x89, 0xf5, 0x4c, 0x54, 0x00, 0x04, 0x81, 0x27, +0xd5, 0x08, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x97, 0x89, 0xf6, 0x89, 0x27, 0x54, 0x94, 0x80, 0xff, +0x84, 0x01, 0x84, 0x20, 0x50, 0x24, 0x80, 0x02, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, +0xdd, 0x2f, 0xc0, 0x54, 0xb4, 0x40, 0xc2, 0x52, 0x18, 0x81, 0x00, 0x01, 0x84, 0xae, 0x80, 0xc2, +0x18, 0x93, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x11, 0x80, 0x06, 0x84, 0x21, 0x18, 0x10, 0x00, 0x01, +0x46, 0x10, 0x01, 0x38, 0x00, 0x30, 0x89, 0xdc, 0x9d, 0x94, 0xae, 0xc0, 0x02, 0x10, 0x84, 0xee, +0x92, 0x28, 0xae, 0x41, 0xd5, 0x2a, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x57, 0x89, 0xf5, 0x4c, 0x54, +0x40, 0x25, 0x46, 0x90, 0x01, 0x38, 0x00, 0x04, 0x89, 0xf6, 0x5c, 0x00, 0x00, 0x05, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x20, 0x64, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x87, 0x82, 0x48, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0x00, +0xd5, 0x05, 0x18, 0x33, 0x00, 0x01, 0x93, 0x08, 0x96, 0x10, 0x00, 0x14, 0x89, 0xf6, 0x54, 0x34, +0x00, 0xff, 0x9c, 0x81, 0xe2, 0x01, 0xe9, 0xf6, 0x80, 0x2a, 0x80, 0x47, 0x80, 0x06, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, +0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x97, 0xd9, 0x9e, 0xfa, 0x80, 0xc0, 0x96, 0xd9, +0x44, 0x00, 0xff, 0xfc, 0x81, 0x02, 0x40, 0x01, 0x80, 0x06, 0x83, 0x81, 0x44, 0x30, 0x1e, 0x05, +0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x86, 0x88, 0xdd, 0x2f, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, 0x84, 0xbc, 0x84, 0x20, 0x44, 0x20, +0x00, 0x10, 0x80, 0x06, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0xa0, 0x00, 0x18, 0x80, 0x1c, 0x84, 0x20, +0x98, 0xbf, 0x4b, 0xe0, 0x24, 0x01, 0x42, 0x23, 0xa8, 0x24, 0x80, 0x08, 0x84, 0x20, 0x4b, 0xe0, +0x24, 0x01, 0x9e, 0x39, 0x80, 0x28, 0x42, 0x10, 0x28, 0x73, 0x15, 0xc3, 0x00, 0x02, 0x81, 0x41, +0xad, 0xf2, 0x14, 0x83, 0x00, 0x03, 0x80, 0x48, 0x84, 0x1f, 0xd5, 0x05, 0xac, 0x13, 0x8c, 0x58, +0x14, 0x21, 0x7f, 0xfa, 0x4c, 0x25, 0x7f, 0xfc, 0x84, 0x1f, 0xac, 0x13, 0x84, 0x00, 0xa0, 0x73, +0x80, 0x66, 0xb6, 0x22, 0x80, 0x80, 0x46, 0x10, 0x00, 0xc9, 0x58, 0x10, 0x8c, 0x54, 0x80, 0x40, +0x80, 0xa0, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0xae, 0x30, 0xec, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xc0, 0xa4, 0x01, +0x40, 0x80, 0x80, 0x13, 0x40, 0x04, 0x00, 0x06, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x1d, 0x66, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, +0x46, 0x20, 0x00, 0xc9, 0x58, 0x21, 0x0a, 0x24, 0x80, 0x06, 0x80, 0x28, 0x4b, 0xe0, 0x08, 0x01, +0x80, 0xe0, 0x47, 0xc0, 0x00, 0xc9, 0x59, 0xce, 0x0a, 0x40, 0x46, 0x90, 0x00, 0xc9, 0x58, 0x94, +0x89, 0xcc, 0xd5, 0x18, 0xa0, 0xf2, 0x80, 0x06, 0x38, 0x21, 0xa1, 0x01, 0x38, 0x31, 0x9d, 0x01, +0xf3, 0x81, 0x4b, 0xe0, 0x24, 0x01, 0xf2, 0x01, 0x80, 0x28, 0x80, 0x06, 0x4b, 0xe0, 0x24, 0x01, +0x80, 0x27, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8a, 0x24, 0xdd, 0x2f, 0x81, 0x07, +0x80, 0xe0, 0x44, 0x50, 0xff, 0xff, 0x80, 0x28, 0x80, 0x06, 0xd7, 0x11, 0xdd, 0x3c, 0x80, 0x40, +0xf2, 0x81, 0x80, 0x27, 0x80, 0x06, 0xdd, 0x3c, 0xf2, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x41, 0x80, 0x20, 0x80, 0x02, 0xdd, 0x23, 0x80, 0x27, 0xc8, 0xd5, 0x80, 0x08, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xc0, 0x80, 0xe1, +0xc0, 0x02, 0xc9, 0x0e, 0x84, 0x00, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, +0x44, 0x30, 0x1c, 0x8e, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0xb4, 0xe7, 0xf0, 0x01, +0xb6, 0xe6, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xe0, 0x80, 0xc1, +0xc0, 0x02, 0xc9, 0x0e, 0x84, 0x00, 0x80, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, +0x44, 0x30, 0x1c, 0x7c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0xb4, 0x06, 0xb6, 0x07, +0xb6, 0xe6, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xec, 0x0c, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x84, 0x00, +0x10, 0x03, 0x00, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x4f, 0xa6, 0xb0, 0xa6, 0x31, +0x9c, 0x72, 0x84, 0x60, 0xdd, 0x24, 0xa4, 0x36, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, +0x82, 0x4a, 0x50, 0x03, 0x00, 0x0c, 0xdd, 0x21, 0x84, 0x00, 0xac, 0x36, 0x46, 0x10, 0x01, 0x4a, +0x58, 0x10, 0x8f, 0x7c, 0x50, 0x00, 0x80, 0x1c, 0xa1, 0xcf, 0xd5, 0x16, 0x4c, 0x60, 0xc0, 0x13, +0x80, 0x27, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x82, 0xf8, 0xdd, 0x2f, 0x80, 0x07, 0x46, 0x10, +0x01, 0x4a, 0x58, 0x10, 0x8f, 0x9c, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, +0xd5, 0x0a, 0x80, 0x07, 0xb4, 0xe7, 0x46, 0x50, 0x01, 0x4a, 0x58, 0x52, 0x8f, 0x98, 0x50, 0x13, +0xff, 0x90, 0xdf, 0xe5, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x7c, 0x85, 0x00, 0x50, 0x20, 0x80, 0x1c, +0x96, 0x02, 0xa0, 0x4f, 0x80, 0xc8, 0xd5, 0x0a, 0x20, 0x30, 0xff, 0x98, 0xe0, 0x60, 0xe8, 0x04, +0x81, 0x02, 0x80, 0x03, 0x80, 0xc1, 0x80, 0x41, 0xb4, 0x21, 0x46, 0x50, 0x01, 0x4a, 0x58, 0x52, +0x8f, 0x98, 0xd9, 0xf3, 0xce, 0x03, 0x80, 0x06, 0xd5, 0x38, 0x50, 0x73, 0x7f, 0x90, 0x84, 0x00, +0x10, 0x03, 0x80, 0x09, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x47, 0x82, 0x4f, 0xa6, 0xb8, 0xa6, 0x39, +0x50, 0x13, 0x7f, 0x92, 0x84, 0x60, 0xdd, 0x24, 0xa4, 0x3e, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, 0x7f, 0x9c, 0xdd, 0x21, 0x84, 0x00, 0xac, 0x3e, 0xa4, 0x3f, +0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x4a, 0x50, 0x03, 0x80, 0x0e, 0xdd, 0x21, +0x84, 0x00, 0xac, 0x3f, 0x80, 0x08, 0x80, 0x26, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x82, 0xf8, +0xdd, 0x2f, 0x80, 0x06, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x9c, 0x46, 0xf0, 0x00, 0xcd, +0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0x84, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x50, 0x60, 0x7f, 0x90, 0x80, 0xe0, 0x81, 0x01, 0x81, 0x22, 0xc6, 0x2f, +0x50, 0x11, 0x00, 0x08, 0x50, 0x00, 0x7f, 0x92, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x00, 0x94, 0x80, 0x05, 0x84, 0x01, 0x10, 0x93, 0x00, 0x01, 0x10, 0x03, +0x00, 0x09, 0x84, 0x20, 0x00, 0x04, 0x00, 0x00, 0xae, 0x30, 0x00, 0x04, 0x00, 0x04, 0x10, 0x03, +0x00, 0x0a, 0x84, 0x1f, 0x00, 0x84, 0x00, 0x03, 0xac, 0x77, 0x10, 0x03, 0x00, 0x46, 0xac, 0x76, +0x10, 0x03, 0x00, 0x16, 0x10, 0x83, 0x00, 0x0b, 0x80, 0x07, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, +0x8f, 0x98, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0x80, 0x06, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x81, 0x00, 0x46, 0x00, 0x01, 0x4a, +0x58, 0x00, 0x0f, 0x94, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8e, 0x4c, 0xdd, 0x2f, +0x80, 0xc0, 0xc8, 0x03, 0x84, 0x07, 0xd5, 0x1b, 0x50, 0x30, 0x7f, 0xf8, 0xcb, 0x03, 0x80, 0x03, +0xd5, 0x16, 0x80, 0x48, 0x08, 0x01, 0x00, 0x01, 0xae, 0x18, 0x80, 0x22, 0x9e, 0x37, 0x84, 0x46, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x80, 0x06, 0x50, 0x13, 0x80, 0x14, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, +0x0f, 0x90, 0x81, 0x01, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8e, 0x4c, 0xdd, 0x2f, 0x80, 0xe0, +0xc8, 0x03, 0x84, 0x07, 0xd5, 0x1e, 0x50, 0x60, 0x7f, 0xe8, 0xce, 0x03, 0x80, 0x06, 0xd5, 0x19, +0x44, 0x20, 0x00, 0x10, 0x80, 0x29, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x60, 0x80, 0x06, 0xdd, 0x21, 0x80, 0x07, +0x50, 0x14, 0x00, 0x10, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0x84, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x81, 0x40, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x8c, 0x83, 0x81, 0x00, 0x75, 0x00, 0x00, +0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8e, 0x4c, 0xdd, 0x2f, 0x80, 0xc0, 0xc8, 0x03, 0x84, 0x07, +0xd5, 0x33, 0x50, 0x80, 0x7f, 0xec, 0x4e, 0x83, 0x00, 0x04, 0x80, 0x08, 0xd5, 0x2d, 0x50, 0x90, +0x7f, 0xed, 0x80, 0x09, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0xbc, 0xdd, 0x2f, 0x84, 0xa2, 0xd7, 0x07, 0x84, 0xa3, 0xd7, 0x09, 0x84, 0x01, 0x4c, 0x70, +0x00, 0x05, 0xd5, 0x1a, 0x84, 0x44, 0xd5, 0x05, 0x84, 0x42, 0xd5, 0x03, 0x44, 0x20, 0x00, 0x10, +0x10, 0x74, 0x00, 0x00, 0x50, 0x15, 0x00, 0x01, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x80, 0x06, 0x50, 0x1e, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, +0x83, 0x48, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xf4, 0x8c, 0x28, 0xf1, 0x81, 0x81, 0x40, 0x08, 0x05, 0x00, 0x01, 0x87, 0x80, +0xb6, 0x1f, 0xd5, 0x2f, 0x00, 0x75, 0x00, 0x00, 0x00, 0x95, 0x00, 0x01, 0x00, 0x85, 0x00, 0x02, +0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8e, 0x4c, 0xdd, 0x2f, 0x80, 0xc0, 0x50, 0x15, 0x00, 0x03, +0x50, 0x00, 0x7f, 0xdb, 0x9e, 0xba, 0x50, 0x33, 0x7f, 0xd8, 0xce, 0x03, 0x84, 0x07, 0xd5, 0x22, +0xc3, 0x12, 0x10, 0x81, 0x80, 0x02, 0x10, 0x91, 0x80, 0x01, 0xaf, 0xd8, 0x46, 0xf0, 0x00, 0x41, +0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xf1, 0x01, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, +0x83, 0x48, 0xdd, 0x2f, 0x9c, 0x39, 0x51, 0xce, 0x00, 0x01, 0x89, 0x40, 0x55, 0xce, 0x00, 0xff, +0xb4, 0x7f, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x88, 0x40, 0xfe, 0x0c, 0x06, 0xe9, 0xcb, +0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xa0, +0x00, 0xcd, 0x58, 0xa5, 0x02, 0xf8, 0x80, 0xc0, 0x50, 0x80, 0x00, 0x08, 0xa1, 0xc2, 0x46, 0x90, +0x00, 0xcd, 0x58, 0x94, 0x83, 0x48, 0xd5, 0x0b, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x07, 0x46, 0x10, +0x01, 0x4a, 0x58, 0x10, 0x8f, 0x88, 0x4b, 0xe0, 0x24, 0x01, 0xa1, 0xf2, 0x80, 0x27, 0x80, 0x08, +0x4c, 0x74, 0x7f, 0xf4, 0x50, 0x83, 0x00, 0x0c, 0xa1, 0xf3, 0x46, 0xa0, 0x00, 0xcd, 0x58, 0xa5, +0x02, 0xf8, 0x46, 0x90, 0x00, 0xcd, 0x58, 0x94, 0x83, 0x48, 0xd5, 0x0b, 0x4b, 0xe0, 0x28, 0x01, +0x80, 0x07, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x8c, 0x4b, 0xe0, 0x24, 0x01, 0xa1, 0xf3, +0x80, 0x27, 0x80, 0x08, 0x4c, 0x74, 0x7f, 0xf4, 0x50, 0x83, 0x00, 0x10, 0xa1, 0xf4, 0x46, 0xa0, +0x00, 0xcd, 0x58, 0xa5, 0x02, 0xf8, 0x46, 0x90, 0x00, 0xcd, 0x58, 0x94, 0x83, 0x48, 0xd5, 0x0b, +0x4b, 0xe0, 0x28, 0x01, 0x80, 0x07, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x90, 0x4b, 0xe0, +0x24, 0x01, 0xa1, 0xf4, 0x80, 0x27, 0x80, 0x08, 0x4c, 0x74, 0x7f, 0xf4, 0x50, 0x83, 0x00, 0x14, +0xa1, 0xf5, 0x46, 0xa0, 0x00, 0xcd, 0x58, 0xa5, 0x02, 0xf8, 0x46, 0x90, 0x00, 0xcd, 0x58, 0x94, +0x83, 0x48, 0xd5, 0x0b, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x07, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, +0x8f, 0x94, 0x4b, 0xe0, 0x24, 0x01, 0xa1, 0xf5, 0x80, 0x27, 0x80, 0x08, 0x4c, 0x74, 0x7f, 0xf4, +0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, +0x00, 0xc9, 0x58, 0x63, 0x09, 0xc8, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x9c, 0x4b, 0xe0, +0x18, 0x01, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x98, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x80, +0x00, 0x74, 0x84, 0xc0, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, 0x83, 0x48, 0x42, 0x03, 0x20, 0x24, +0x46, 0x10, 0x01, 0x44, 0x58, 0x10, 0x8e, 0x04, 0x50, 0x00, 0x00, 0x70, 0x98, 0x01, 0x46, 0x10, +0x01, 0x4a, 0x58, 0x10, 0x8f, 0x9c, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x40, +0xde, 0xee, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x46, 0x60, 0x00, 0xc9, 0x58, 0x63, 0x09, 0xc8, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x80, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x84, 0xdd, 0x26, 0x46, 0x00, 0x01, 0x4a, +0x58, 0x00, 0x0f, 0x88, 0xdd, 0x26, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x8c, 0xdd, 0x26, +0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x0f, 0x90, 0xdd, 0x26, 0x46, 0x00, 0x01, 0x4a, 0x58, 0x00, +0x0f, 0x94, 0xdd, 0x26, 0x81, 0x06, 0x45, 0xc0, 0x00, 0x1c, 0x84, 0xc0, 0x46, 0x70, 0x00, 0xcd, +0x58, 0x73, 0x83, 0x48, 0x42, 0x93, 0x70, 0x24, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0f, 0x1c, +0x50, 0xa4, 0x80, 0x08, 0x89, 0x40, 0x80, 0x0a, 0xdd, 0x28, 0x50, 0x05, 0x00, 0x04, 0xdd, 0x28, +0x50, 0xa4, 0x80, 0x10, 0x46, 0x10, 0x01, 0x49, 0x58, 0x10, 0x8f, 0x1c, 0x89, 0x41, 0x80, 0x0a, +0xdd, 0x28, 0x50, 0x05, 0x00, 0x04, 0xdd, 0x28, 0x8d, 0x38, 0x46, 0x20, 0x01, 0x49, 0x58, 0x21, +0x0f, 0x1c, 0x40, 0x04, 0x88, 0x00, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x84, 0xdd, 0x27, +0x44, 0x00, 0x00, 0x2c, 0x42, 0x03, 0x00, 0x24, 0x46, 0x20, 0x01, 0x4d, 0x58, 0x21, 0x07, 0x5c, +0x50, 0x00, 0x00, 0x28, 0x98, 0x02, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x88, 0xdd, 0x27, +0x44, 0x00, 0x00, 0x18, 0x42, 0x03, 0x00, 0x24, 0x46, 0x20, 0x01, 0x41, 0x58, 0x21, 0x02, 0xd8, +0x98, 0x02, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x8c, 0xdd, 0x27, 0x46, 0x10, 0x01, 0x4c, +0x58, 0x10, 0x8c, 0x78, 0x40, 0x04, 0x84, 0x00, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x90, +0xdd, 0x27, 0x84, 0x0c, 0x42, 0x03, 0x00, 0x24, 0x46, 0x20, 0x01, 0x4d, 0x58, 0x21, 0x04, 0x3c, +0x8c, 0x08, 0x98, 0x02, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x94, 0xdd, 0x27, 0x9d, 0xb1, +0x44, 0x50, 0x00, 0x40, 0xde, 0xa0, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x7c, 0x55, 0xc0, 0x00, 0xff, +0x9d, 0xcc, 0xa1, 0x89, 0x46, 0xa0, 0x00, 0xcd, 0x58, 0xa5, 0x02, 0xf8, 0x46, 0x90, 0x00, 0xcd, +0x58, 0x94, 0x83, 0x48, 0xd5, 0x17, 0xa7, 0x40, 0x4c, 0x5e, 0x40, 0x13, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x17, 0x82, 0x5a, 0xdd, 0x21, 0x80, 0x26, 0x80, 0x07, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0x06, +0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x84, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0xc7, 0x80, 0xe6, +0xb4, 0xc6, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x80, 0x50, 0x03, 0x7f, 0xe8, 0x4c, 0x60, +0xff, 0xe4, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x89, 0xbc, 0xdd, 0x2f, 0xc0, 0x06, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x4a, 0x10, 0x17, 0x8f, 0x7c, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x81, 0x00, 0x20, 0x34, +0x00, 0x00, 0x20, 0x24, 0x00, 0x01, 0x81, 0x41, 0x00, 0x14, 0x00, 0x02, 0x46, 0x00, 0x01, 0x4a, +0x58, 0x00, 0x0f, 0x84, 0x01, 0xc4, 0x00, 0x03, 0x00, 0x74, 0x00, 0x04, 0xf1, 0x83, 0xf2, 0x82, +0xf3, 0x81, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8e, 0x4c, 0xdd, 0x2f, 0x81, 0x20, 0xf1, 0x03, +0xf2, 0x02, 0xf3, 0x01, 0xc8, 0x04, 0x84, 0xe7, 0x48, 0x00, 0x00, 0x81, 0x50, 0x60, 0x7f, 0xe8, +0xce, 0x03, 0x80, 0xe6, 0xd5, 0x7b, 0x46, 0x40, 0x01, 0x49, 0x58, 0x42, 0x0f, 0x1c, 0x9b, 0x34, +0x46, 0x0b, 0x6d, 0xb6, 0x90, 0x82, 0x58, 0x00, 0x0d, 0xb7, 0x42, 0x02, 0x00, 0x24, 0xae, 0x73, +0x84, 0x20, 0xae, 0x75, 0xae, 0x30, 0xae, 0xf1, 0xae, 0xb2, 0x11, 0xc3, 0x00, 0x04, 0x8d, 0x05, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x5b, 0x80, 0x28, 0x80, 0x07, 0xdd, 0x22, 0xc0, 0x03, +0x84, 0xec, 0xd5, 0x4c, 0x84, 0xa2, 0xd7, 0x15, 0xe6, 0xe3, 0xe8, 0x04, 0x84, 0xa1, 0xdf, 0x5b, +0xd5, 0x06, 0x84, 0xa3, 0xd7, 0x18, 0x84, 0xa4, 0xdf, 0x56, 0xd5, 0x1f, 0xa6, 0x35, 0x46, 0x10, +0x01, 0x38, 0x58, 0x10, 0x89, 0x70, 0x58, 0x00, 0x00, 0x01, 0xae, 0x35, 0x80, 0x08, 0xd5, 0x1e, +0xa6, 0x35, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x89, 0x74, 0x58, 0x00, 0x00, 0x02, 0xae, 0x35, +0x80, 0x08, 0xd5, 0x14, 0xa6, 0x35, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x89, 0x78, 0x58, 0x00, +0x00, 0x04, 0xae, 0x35, 0x80, 0x08, 0xd5, 0x0a, 0xa6, 0x35, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, +0x89, 0x7c, 0x58, 0x00, 0x00, 0x08, 0xae, 0x35, 0x80, 0x08, 0xb4, 0x41, 0x80, 0x26, 0xdd, 0x22, +0x80, 0xe0, 0xc8, 0x14, 0x80, 0x09, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x80, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0xa7, 0xb0, 0x84, 0x21, 0x10, 0x65, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x4a, 0x10, 0x17, 0x8f, 0x7c, 0xd5, 0x11, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, +0x82, 0x5a, 0x80, 0x06, 0xdd, 0x21, 0x80, 0x09, 0x46, 0x10, 0x01, 0x4a, 0x58, 0x10, 0x8f, 0x84, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0x80, 0x07, 0xec, 0x14, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x84, 0xe1, 0xd5, 0xea, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xd8, +0xa7, 0x88, 0x80, 0xe1, 0x54, 0x80, 0x00, 0xff, 0x84, 0x20, 0x50, 0x0f, 0x80, 0x0c, 0x44, 0x20, +0x00, 0x14, 0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0xe6, 0xc7, 0xe8, 0x0b, +0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0xc8, 0x06, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, +0x87, 0xd4, 0xdd, 0x2f, 0x84, 0xa3, 0xd6, 0x5e, 0xe6, 0xc4, 0xe8, 0x06, 0x84, 0xa1, 0xd6, 0x32, +0xe6, 0xc2, 0xe8, 0x40, 0xd5, 0x0f, 0x84, 0x05, 0x4c, 0x60, 0x00, 0x86, 0xe2, 0xc0, 0xe9, 0x70, +0x84, 0xa6, 0x4c, 0x62, 0x80, 0x96, 0x44, 0x50, 0x00, 0xdd, 0x4c, 0x62, 0xc0, 0xe2, 0x48, 0x00, +0x00, 0xd5, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0xe3, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x37, 0x89, 0xf6, +0x84, 0x2f, 0x50, 0x0f, 0x80, 0x0c, 0x84, 0x80, 0x50, 0x2f, 0x80, 0x17, 0xae, 0x42, 0x10, 0x30, +0x00, 0x0a, 0xaf, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x48, 0xaf, 0x00, 0x98, 0xd3, +0xd5, 0x04, 0x18, 0x01, 0x00, 0x01, 0x92, 0x28, 0x96, 0x08, 0x4c, 0x21, 0xff, 0xfc, 0x48, 0x00, +0x00, 0xc2, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0x4e, 0x02, 0x00, 0xc0, 0x84, 0xa7, +0x4c, 0x82, 0xc0, 0xbd, 0x9c, 0x39, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8f, 0x84, 0xdd, 0x2f, +0xd5, 0x58, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0x4e, 0x02, 0x00, 0xb0, 0x84, 0xa3, +0x4c, 0x82, 0xc0, 0xad, 0xa6, 0x3a, 0xa6, 0x79, 0x40, 0x00, 0x20, 0x08, 0x98, 0x01, 0x96, 0x01, +0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x87, 0x20, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x0c, 0x84, 0x42, +0xd5, 0x30, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0x4e, 0x02, 0x00, 0x98, 0xe7, 0x07, +0x4e, 0xf3, 0x00, 0x95, 0x84, 0x40, 0x50, 0x1f, 0x80, 0x27, 0x9c, 0x39, 0xae, 0x88, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x8a, 0x18, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x0c, 0xae, 0x08, 0x00, 0x0f, +0x80, 0x27, 0xaf, 0x89, 0xae, 0x0a, 0x50, 0x2f, 0x80, 0x0f, 0x48, 0x00, 0x00, 0x85, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0xc0, 0x7a, 0x84, 0xa2, 0x4c, 0x82, 0xc0, 0x78, 0xa6, 0x39, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x89, 0x90, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x0c, 0x84, 0x44, +0xae, 0x89, 0xd5, 0x12, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0xc0, 0x67, 0x84, 0xa2, +0x4c, 0x82, 0xc0, 0x65, 0xa6, 0x39, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8d, 0x38, 0xdd, 0x2f, +0x50, 0x1f, 0x80, 0x0c, 0xaf, 0x89, 0xae, 0x08, 0x50, 0x2f, 0x80, 0x0e, 0xd5, 0x5c, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x89, 0xf4, 0xc0, 0x52, 0x84, 0xa3, 0x4c, 0x82, 0xc0, 0x50, 0x50, 0xa3, +0x80, 0x02, 0x00, 0x05, 0x00, 0x00, 0x9d, 0xf9, 0xa6, 0x78, 0x40, 0x00, 0x20, 0x08, 0x50, 0x8f, +0x80, 0x20, 0x98, 0x01, 0x85, 0x20, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x51, 0xb7, 0x28, +0x96, 0x01, 0xdd, 0x21, 0x40, 0x10, 0x60, 0x09, 0x40, 0x30, 0x20, 0x09, 0x40, 0x20, 0x40, 0x09, +0x10, 0x2f, 0x80, 0x02, 0x10, 0x3f, 0x80, 0x01, 0x10, 0x1f, 0x80, 0x03, 0x10, 0x0f, 0x80, 0x00, +0x50, 0x2f, 0x80, 0x11, 0xb4, 0x1f, 0x00, 0x15, 0x00, 0x00, 0xb6, 0x08, 0x50, 0x0f, 0x80, 0x0c, +0x00, 0x54, 0x00, 0x01, 0xa6, 0xf8, 0x20, 0x44, 0x00, 0x03, 0xc5, 0x05, 0xaf, 0x04, 0x10, 0x90, +0x00, 0x00, 0xd5, 0x07, 0x44, 0x40, 0x00, 0x7f, 0xaf, 0x04, 0x44, 0x40, 0x00, 0x12, 0xaf, 0x00, +0xaf, 0x81, 0xae, 0xc2, 0xae, 0x43, 0xd5, 0x17, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, 0x82, 0x4c, +0x9c, 0xb9, 0x44, 0x00, 0x00, 0xd1, 0x84, 0x20, 0xdd, 0x23, 0xc0, 0x08, 0xd5, 0x16, 0x50, 0x2f, +0x80, 0x0c, 0x50, 0x0f, 0x80, 0x0c, 0x4c, 0x20, 0x40, 0x07, 0x84, 0x01, 0x10, 0x0f, 0x80, 0x0c, +0x50, 0x2f, 0x80, 0x0d, 0x50, 0x1f, 0x80, 0x0c, 0x9a, 0x91, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x4d, 0x96, 0x90, 0x84, 0x0e, 0xdd, 0x23, 0xec, 0x28, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0xa0, 0x02, 0x81, 0x01, 0xc0, 0x07, +0xa4, 0xb2, 0xc2, 0x05, 0xa0, 0x73, 0xc1, 0x03, 0xa6, 0x30, 0xc8, 0x0d, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xd5, 0x84, 0x21, 0x84, 0x06, 0x44, 0x20, 0x70, 0xb3, 0x44, 0x30, 0x00, 0x66, +0xdd, 0x24, 0xd5, 0x54, 0x02, 0x04, 0x00, 0x00, 0xc0, 0x03, 0xe2, 0x02, 0xe9, 0x05, 0x84, 0x00, +0x12, 0x04, 0x00, 0x00, 0xd5, 0x4b, 0x44, 0x70, 0x00, 0x18, 0x42, 0x10, 0x1c, 0x73, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x80, 0x01, 0xb4, 0x00, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x01, +0x44, 0x30, 0x1e, 0x9a, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x02, 0x14, 0x00, 0x00, +0xa0, 0x33, 0x42, 0x00, 0x9c, 0x73, 0xa4, 0x43, 0x44, 0x50, 0xff, 0xff, 0xd1, 0x07, 0x46, 0xf0, +0x01, 0x38, 0x04, 0x27, 0x82, 0x3f, 0x80, 0x06, 0xdd, 0x22, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x02, 0x04, 0x00, 0x00, 0xa1, 0xf3, 0x44, 0x20, 0x00, 0x18, +0x42, 0x70, 0x08, 0x73, 0x84, 0x20, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x84, 0x1f, 0xac, 0x3b, 0x84, 0x00, 0x12, 0x04, 0x00, 0x00, 0x80, 0x07, 0xa0, 0x73, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x83, 0x48, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xe0, 0x80, 0xc1, 0xc8, 0x02, 0xd5, 0x04, +0x84, 0x00, 0x40, 0x00, 0x04, 0x06, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x02, 0x18, +0x44, 0x30, 0x01, 0x2a, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xb4, 0x06, +0xb6, 0x07, 0x84, 0x00, 0xb6, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x80, 0xe1, 0xc8, 0x02, 0xd5, 0x04, 0x84, 0x00, 0x40, 0x00, +0x04, 0x06, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x02, 0x18, 0x44, 0x30, 0x01, 0x19, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xb4, 0x06, 0xb6, 0x07, 0xb6, 0xe6, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x80, 0xc0, 0x80, 0xe1, 0xc0, 0x07, 0xb4, 0x00, 0xc0, 0x05, 0x84, 0x00, 0x40, 0x00, 0x04, 0x06, +0xd5, 0x02, 0x84, 0x00, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x02, 0x18, 0x44, 0x30, 0x01, 0x22, +0x84, 0x20, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x80, 0x06, 0x80, 0x27, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x90, 0x9e, 0x93, 0x84, 0x62, 0x40, 0x41, +0x0c, 0x56, 0x96, 0x00, 0x44, 0x20, 0x00, 0x34, 0x42, 0x00, 0x08, 0x24, 0x81, 0x01, 0x46, 0x10, +0x01, 0x41, 0x58, 0x10, 0x88, 0xc4, 0x98, 0x01, 0x51, 0xc0, 0x00, 0x28, 0x04, 0x60, 0x00, 0x0a, +0x81, 0x3c, 0x97, 0xe0, 0x40, 0x24, 0x1c, 0x00, 0xf2, 0x81, 0xd5, 0x28, 0x4e, 0x82, 0x00, 0x0a, +0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, 0xdd, 0x2f, 0xc0, 0x1e, 0xa7, 0x74, 0xdf, 0x1c, +0x80, 0x26, 0x80, 0x09, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x80, 0x26, +0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xfc, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe7, 0x80, 0xc9, 0x9c, 0x09, 0x46, 0xf0, +0x01, 0x40, 0x10, 0x07, 0x82, 0xe7, 0x81, 0x26, 0xb4, 0xc6, 0x50, 0x13, 0x00, 0x22, 0x9c, 0x35, +0x80, 0x48, 0xf3, 0x01, 0x80, 0x87, 0x4c, 0x6e, 0x7f, 0xd3, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x20, 0x80, 0x41, +0x96, 0x00, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x64, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x90, 0x9e, 0x93, +0x84, 0x62, 0x40, 0x41, 0x0c, 0x56, 0x96, 0x00, 0x44, 0x20, 0x00, 0x34, 0x42, 0x00, 0x08, 0x24, +0x81, 0x21, 0x46, 0x10, 0x01, 0x41, 0x58, 0x10, 0x88, 0xc4, 0x99, 0xc1, 0x50, 0xa3, 0x80, 0x24, +0xb7, 0x5f, 0x04, 0x63, 0x80, 0x09, 0x54, 0x82, 0x00, 0xff, 0x40, 0x54, 0xa0, 0x00, 0xf5, 0x81, +0xd5, 0x2f, 0x4e, 0x92, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, 0xdd, 0x2f, +0xc0, 0x25, 0x00, 0x53, 0x00, 0x3e, 0x4c, 0x54, 0x40, 0x22, 0x80, 0x26, 0x80, 0x0a, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x00, 0x53, 0x80, 0x31, 0x80, 0x26, 0x9f, 0x69, +0x10, 0x53, 0x80, 0x31, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xf8, 0x46, 0xf0, 0x00, 0xcd, +0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe6, 0x80, 0xca, +0x9c, 0x09, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x07, 0x82, 0xe6, 0x81, 0x46, 0xb4, 0xc6, 0xb4, 0xbf, +0x50, 0x13, 0x00, 0x21, 0x9c, 0x34, 0x80, 0x49, 0xf3, 0x01, 0x80, 0x88, 0xde, 0xcb, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x20, 0x80, 0x41, 0x96, 0x00, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x80, 0x28, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x44, 0x70, 0x00, 0x34, 0x96, 0x00, 0x42, 0x70, 0x1c, 0x24, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, +0x08, 0xc4, 0x99, 0xf8, 0xf1, 0x81, 0x9e, 0x93, 0x50, 0xa3, 0x80, 0x20, 0x55, 0xc1, 0x00, 0xff, +0x04, 0x63, 0x80, 0x08, 0x81, 0x0a, 0xd5, 0x2f, 0xf3, 0x01, 0xc3, 0x0b, 0x46, 0xf0, 0x00, 0xc8, +0x58, 0xf7, 0x8b, 0x6c, 0xdd, 0x2f, 0xc0, 0x25, 0x00, 0x53, 0x00, 0x21, 0x4c, 0x5e, 0x40, 0x22, +0x80, 0x26, 0x80, 0x08, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x00, 0x23, +0x80, 0x30, 0x80, 0x26, 0x9e, 0x91, 0x10, 0x23, 0x80, 0x30, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, +0x02, 0xf4, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, +0x00, 0x07, 0x82, 0xe5, 0x80, 0xc8, 0x9c, 0x01, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x07, 0x82, 0xe5, +0x81, 0x06, 0xb4, 0xc6, 0x9c, 0x34, 0x80, 0x5c, 0xf1, 0x01, 0x4c, 0x65, 0x7f, 0xcf, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x20, 0x80, 0x41, 0x96, 0x00, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x80, 0xfc, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x96, 0x90, 0x9e, 0x93, 0x84, 0x62, 0x40, 0x41, 0x0c, 0x56, 0x96, 0x00, 0x44, 0x20, 0x00, 0x34, +0x42, 0x00, 0x08, 0x24, 0x81, 0x21, 0x46, 0x10, 0x01, 0x41, 0x58, 0x10, 0x88, 0xc4, 0x99, 0xc1, +0x50, 0xa3, 0x80, 0x1c, 0xb7, 0x5f, 0xa1, 0xbf, 0x54, 0x82, 0x00, 0xff, 0x40, 0x54, 0xa0, 0x00, +0xf5, 0x81, 0xd5, 0x2f, 0x4e, 0x92, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, +0xdd, 0x2f, 0xc0, 0x25, 0x00, 0x53, 0x00, 0x24, 0x4c, 0x54, 0x40, 0x22, 0x80, 0x26, 0x80, 0x0a, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x00, 0x53, 0x80, 0x2f, 0x80, 0x26, +0x9f, 0x69, 0x10, 0x53, 0x80, 0x2f, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xf0, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe4, +0x80, 0xca, 0x9c, 0x09, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x07, 0x82, 0xe4, 0x81, 0x46, 0xb4, 0xc6, +0xb4, 0xbf, 0x50, 0x13, 0x00, 0x14, 0x9c, 0x34, 0x80, 0x49, 0xf3, 0x01, 0x80, 0x88, 0xde, 0xcb, +0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x20, 0x80, 0x41, 0x96, 0x00, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x81, 0xbc, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x96, 0x90, 0x9e, 0x93, 0x84, 0x62, 0x40, 0x41, 0x0c, 0x56, 0x96, 0x00, 0x44, 0x20, 0x00, 0x34, +0x42, 0x00, 0x08, 0x24, 0x81, 0x21, 0x46, 0x10, 0x01, 0x41, 0x58, 0x10, 0x88, 0xc4, 0x99, 0xc1, +0x50, 0xa3, 0x80, 0x18, 0xb7, 0x5f, 0xa1, 0xbe, 0x54, 0x82, 0x00, 0xff, 0x40, 0x54, 0xa0, 0x00, +0xf5, 0x81, 0xd5, 0x2f, 0x4e, 0x92, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x88, +0xdd, 0x2f, 0xc0, 0x25, 0x00, 0x53, 0x00, 0x24, 0x4c, 0x54, 0x40, 0x22, 0x80, 0x26, 0x80, 0x0a, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x00, 0x53, 0x80, 0x2e, 0x80, 0x26, +0x9f, 0x69, 0x10, 0x53, 0x80, 0x2e, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xec, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe3, +0x80, 0xca, 0x9c, 0x09, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x07, 0x82, 0xe3, 0x81, 0x46, 0xb4, 0xc6, +0xb4, 0xbf, 0x50, 0x13, 0x00, 0x14, 0x9c, 0x34, 0x80, 0x49, 0xf3, 0x01, 0x80, 0x88, 0xde, 0xcb, +0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x20, 0x80, 0x41, 0x96, 0x00, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x82, 0x8c, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, +0x44, 0x70, 0x00, 0x34, 0x96, 0x00, 0x42, 0x70, 0x1c, 0x24, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, +0x08, 0xc4, 0x99, 0xf8, 0x51, 0xc3, 0x80, 0x10, 0x81, 0x21, 0xa1, 0xbc, 0x81, 0x1c, 0xd5, 0x30, +0x4e, 0x92, 0x00, 0x0d, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x6c, 0xdd, 0x2f, 0xc0, 0x26, +0x00, 0x53, 0x00, 0x0a, 0x00, 0x04, 0x80, 0x06, 0xd8, 0x21, 0x80, 0x26, 0x80, 0x08, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x00, 0x23, 0x80, 0x2c, 0x80, 0x26, 0x9e, 0x91, +0x10, 0x23, 0x80, 0x2c, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe8, 0x46, 0xf0, 0x00, 0xcd, +0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x07, 0x82, 0xe2, 0x80, 0xc8, +0x9c, 0x01, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x07, 0x82, 0xe2, 0x81, 0x06, 0xb4, 0xc6, 0x9c, 0x34, +0x84, 0x46, 0x80, 0x29, 0x4c, 0x6e, 0x7f, 0xce, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x20, 0x96, 0x00, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x83, 0x5c, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x00, 0x34, 0x97, 0x80, 0x42, 0x23, +0x08, 0x24, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x98, 0x90, 0xa7, 0x50, 0x84, 0x21, +0xd1, 0x03, 0x80, 0x01, 0xd5, 0x49, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x77, 0x82, 0xe1, 0x84, 0x60, +0x84, 0x80, 0x9d, 0xf9, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x77, 0x82, 0xe1, 0xad, 0x17, 0x10, 0x31, +0x00, 0x0d, 0xae, 0xd0, 0xad, 0x11, 0xad, 0x12, 0xaf, 0x16, 0xae, 0xd7, 0x10, 0x31, 0x00, 0x08, +0xad, 0x15, 0x10, 0x31, 0x00, 0x0c, 0x84, 0x20, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x83, 0x5c, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x41, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x82, 0x8c, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x41, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x81, 0xbc, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x41, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x80, 0xfc, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x41, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x80, 0x28, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x06, 0x80, 0x41, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, +0x8f, 0x64, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x84, 0xc0, 0x46, 0x70, 0x00, 0xce, 0x58, 0x73, 0x84, 0x14, 0x80, 0x06, +0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xfa, 0x84, 0x00, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x84, 0x61, 0x96, 0x80, 0xa6, 0x08, +0x4c, 0x21, 0x80, 0x10, 0xc2, 0x07, 0x84, 0x02, 0x4c, 0x20, 0x00, 0x13, 0x44, 0x60, 0x00, 0x12, +0xd5, 0x1e, 0x9c, 0x49, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x83, 0x08, 0xdd, 0x2f, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x84, 0x14, 0xdd, 0x2f, 0x80, 0xc0, 0xd5, 0x10, 0x84, 0xe0, +0x80, 0xc7, 0x46, 0x80, 0x00, 0xce, 0x58, 0x84, 0x04, 0x14, 0x80, 0x07, 0x4b, 0xe0, 0x20, 0x01, +0x9d, 0xf9, 0x44, 0x50, 0x00, 0x64, 0x40, 0x63, 0x00, 0x04, 0xdf, 0xf8, 0x80, 0x06, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0xcd, +0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x84, 0x20, 0x80, 0xc0, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x02, 0x18, 0x44, 0x30, +0x01, 0x36, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xb4, 0x06, 0x4c, 0x03, +0x40, 0x04, 0x84, 0x00, 0xd5, 0x03, 0xb4, 0x20, 0xb6, 0x26, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x90, 0x9f, 0xd3, 0x84, 0x62, 0x40, 0x73, +0x8c, 0x76, 0x96, 0x00, 0x44, 0x80, 0x00, 0x34, 0x42, 0x80, 0x20, 0x24, 0x46, 0x00, 0x01, 0x41, +0x58, 0x00, 0x08, 0xc4, 0x89, 0x00, 0x81, 0x41, 0x50, 0x54, 0x00, 0x28, 0x04, 0x64, 0x00, 0x0a, +0x47, 0xc0, 0x00, 0xc8, 0x59, 0xce, 0x0b, 0x88, 0x97, 0xf8, 0x40, 0x90, 0x9c, 0x00, 0xd5, 0x0c, +0xf5, 0x81, 0xdd, 0x3c, 0xf5, 0x01, 0xc0, 0x07, 0xa6, 0x34, 0x4c, 0x03, 0xc0, 0x05, 0x44, 0x00, +0x00, 0x12, 0xd5, 0x3c, 0xb4, 0xc6, 0x9c, 0x35, 0x50, 0x13, 0x00, 0x22, 0x80, 0x4a, 0x80, 0x69, +0x80, 0x87, 0xde, 0xef, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xfc, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0x81, 0x20, 0xc8, 0x03, 0x84, 0x07, 0xd5, 0x27, 0x47, 0xc0, +0x00, 0x41, 0x59, 0xce, 0x04, 0x98, 0x80, 0x2a, 0x80, 0x47, 0x9c, 0x05, 0xdd, 0x3c, 0x80, 0x47, +0x40, 0x15, 0x1c, 0x00, 0x50, 0x04, 0x80, 0x22, 0xdd, 0x3c, 0x10, 0x74, 0x80, 0x04, 0x80, 0x06, +0x80, 0x29, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, +0x00, 0x17, 0x82, 0xe7, 0x00, 0x24, 0x00, 0x32, 0x9e, 0x49, 0x9c, 0x91, 0x10, 0x24, 0x00, 0x32, +0x46, 0xf0, 0x01, 0x40, 0x10, 0x17, 0x82, 0xe7, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x81, 0x96, 0xc0, 0x96, 0x90, 0xa6, 0x08, +0x4c, 0x32, 0x00, 0x10, 0xc3, 0x07, 0x84, 0x22, 0x4c, 0x30, 0x80, 0x0e, 0x44, 0x00, 0x00, 0x12, +0xd5, 0x11, 0x9c, 0x49, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0xa4, 0xdd, 0x2f, 0xd5, 0x0a, +0x9c, 0x49, 0xd5, 0x03, 0x84, 0x20, 0x80, 0x41, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x64, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x96, 0x90, 0x9f, 0xd3, 0x84, 0x62, 0x40, 0x73, 0x8c, 0x76, 0x96, 0x00, 0x44, 0x80, 0x00, 0x34, +0x42, 0x80, 0x20, 0x24, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x89, 0x00, 0x81, 0x41, +0x50, 0x54, 0x00, 0x24, 0x04, 0x64, 0x00, 0x09, 0x47, 0xc0, 0x00, 0xc8, 0x59, 0xce, 0x0b, 0x88, +0x97, 0xf8, 0x40, 0x90, 0x9c, 0x00, 0xd5, 0x0d, 0xf5, 0x81, 0xdd, 0x3c, 0xf5, 0x01, 0xc0, 0x08, +0x00, 0x03, 0x00, 0x3e, 0x4c, 0x03, 0xc0, 0x05, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x3c, 0xb4, 0xc6, +0x9c, 0x34, 0x50, 0x13, 0x00, 0x21, 0x80, 0x4a, 0x80, 0x69, 0x80, 0x87, 0xde, 0xee, 0x46, 0x00, +0x01, 0x40, 0x58, 0x00, 0x02, 0xf8, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, +0x81, 0x20, 0xc8, 0x03, 0x84, 0x07, 0xd5, 0x27, 0x47, 0xc0, 0x00, 0x41, 0x59, 0xce, 0x04, 0x98, +0x80, 0x2a, 0x80, 0x47, 0x9c, 0x04, 0xdd, 0x3c, 0x80, 0x47, 0x40, 0x15, 0x1c, 0x00, 0x50, 0x04, +0x80, 0x21, 0xdd, 0x3c, 0x10, 0x74, 0x80, 0x3e, 0x80, 0x06, 0x80, 0x29, 0x46, 0xf0, 0x00, 0xcd, +0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe6, 0x00, 0x24, +0x00, 0x31, 0x9e, 0x49, 0x9c, 0x91, 0x10, 0x24, 0x00, 0x31, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x17, +0x82, 0xe6, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x81, 0x96, 0xc0, 0x96, 0x90, 0xa6, 0x08, 0x4c, 0x32, 0x00, 0x10, +0xc3, 0x07, 0x84, 0x22, 0x4c, 0x30, 0x80, 0x0e, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x11, 0x9c, 0x49, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x86, 0xbc, 0xdd, 0x2f, 0xd5, 0x0a, 0x9c, 0x49, 0xd5, 0x03, +0x84, 0x20, 0x80, 0x41, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x80, 0x28, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x44, 0x70, 0x00, 0x34, +0x96, 0x00, 0x42, 0x70, 0x1c, 0x24, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x99, 0xf8, +0x9e, 0x93, 0x81, 0x41, 0x54, 0x91, 0x00, 0xff, 0x51, 0xc3, 0x80, 0x20, 0x04, 0x63, 0x80, 0x08, +0x46, 0x80, 0x00, 0xc8, 0x58, 0x84, 0x0b, 0x6c, 0xd5, 0x0c, 0x4b, 0xe0, 0x20, 0x01, 0xc0, 0x08, +0x00, 0x53, 0x00, 0x21, 0x4c, 0x54, 0xc0, 0x05, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x34, 0xb4, 0xc6, +0x9c, 0x34, 0x80, 0x2a, 0x80, 0x49, 0x4c, 0x6e, 0x7f, 0xf2, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, +0x02, 0xf4, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0x81, 0x00, 0xc8, 0x03, +0x84, 0x07, 0xd5, 0x21, 0x80, 0x49, 0x80, 0x2a, 0x9c, 0x04, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x10, 0x94, 0x00, 0x21, 0x80, 0x06, 0x80, 0x28, 0x46, 0xf0, 0x00, 0xcd, +0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe5, 0x00, 0x23, +0x80, 0x30, 0x9e, 0x49, 0x9c, 0x91, 0x10, 0x23, 0x80, 0x30, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x17, +0x82, 0xe5, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x81, 0x96, 0xc0, 0x96, 0x90, 0xa6, 0x08, 0x4c, 0x32, 0x00, 0x10, +0xc3, 0x07, 0x84, 0x22, 0x4c, 0x30, 0x80, 0x0e, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x11, 0x9c, 0x49, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x87, 0xd8, 0xdd, 0x2f, 0xd5, 0x0a, 0x9c, 0x49, 0xd5, 0x03, +0x84, 0x20, 0x80, 0x41, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x80, 0xfc, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x90, 0x9f, 0xd3, +0x84, 0x62, 0x40, 0x73, 0x8c, 0x76, 0x96, 0x00, 0x44, 0x80, 0x00, 0x34, 0x42, 0x80, 0x20, 0x24, +0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x89, 0x00, 0x81, 0x41, 0x50, 0x54, 0x00, 0x1c, +0x04, 0x64, 0x00, 0x07, 0x47, 0xc0, 0x00, 0xc8, 0x59, 0xce, 0x0b, 0x88, 0x97, 0xf8, 0x40, 0x90, +0x9c, 0x00, 0xd5, 0x0d, 0xf5, 0x81, 0xdd, 0x3c, 0xf5, 0x01, 0xc0, 0x08, 0x00, 0x03, 0x00, 0x24, +0x4c, 0x03, 0xc0, 0x05, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x3c, 0xb4, 0xc6, 0x9c, 0x34, 0x50, 0x13, +0x00, 0x14, 0x80, 0x4a, 0x80, 0x69, 0x80, 0x87, 0xde, 0xee, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, +0x02, 0xf0, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0x81, 0x20, 0xc8, 0x03, +0x84, 0x07, 0xd5, 0x27, 0x47, 0xc0, 0x00, 0x41, 0x59, 0xce, 0x04, 0x98, 0x80, 0x2a, 0x80, 0x47, +0x9c, 0x04, 0xdd, 0x3c, 0x80, 0x47, 0x40, 0x15, 0x1c, 0x00, 0x50, 0x04, 0x80, 0x14, 0xdd, 0x3c, +0x10, 0x74, 0x80, 0x24, 0x80, 0x06, 0x80, 0x29, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe4, 0x00, 0x24, 0x00, 0x2f, 0x9e, 0x49, +0x9c, 0x91, 0x10, 0x24, 0x00, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x17, 0x82, 0xe4, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x81, 0x96, 0xc0, 0x96, 0x90, 0xa6, 0x08, 0x4c, 0x32, 0x00, 0x10, 0xc3, 0x07, 0x84, 0x22, +0x4c, 0x30, 0x80, 0x0e, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x11, 0x9c, 0x49, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x88, 0xd8, 0xdd, 0x2f, 0xd5, 0x0a, 0x9c, 0x49, 0xd5, 0x03, 0x84, 0x20, 0x80, 0x41, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x81, 0xbc, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x90, 0x9f, 0xd3, 0x84, 0x62, 0x40, 0x73, +0x8c, 0x76, 0x96, 0x00, 0x44, 0x80, 0x00, 0x34, 0x42, 0x80, 0x20, 0x24, 0x46, 0x00, 0x01, 0x41, +0x58, 0x00, 0x08, 0xc4, 0x89, 0x00, 0x81, 0x41, 0x50, 0x54, 0x00, 0x18, 0x04, 0x64, 0x00, 0x06, +0x47, 0xc0, 0x00, 0xc8, 0x59, 0xce, 0x0b, 0x88, 0x97, 0xf8, 0x40, 0x90, 0x9c, 0x00, 0xd5, 0x0d, +0xf5, 0x81, 0xdd, 0x3c, 0xf5, 0x01, 0xc0, 0x08, 0x00, 0x03, 0x00, 0x24, 0x4c, 0x03, 0xc0, 0x05, +0x44, 0x00, 0x00, 0x12, 0xd5, 0x3c, 0xb4, 0xc6, 0x9c, 0x34, 0x50, 0x13, 0x00, 0x14, 0x80, 0x4a, +0x80, 0x69, 0x80, 0x87, 0xde, 0xee, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xec, 0x46, 0xf0, +0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0x81, 0x20, 0xc8, 0x03, 0x84, 0x07, 0xd5, 0x27, +0x47, 0xc0, 0x00, 0x41, 0x59, 0xce, 0x04, 0x98, 0x80, 0x2a, 0x80, 0x47, 0x9c, 0x04, 0xdd, 0x3c, +0x80, 0x47, 0x40, 0x15, 0x1c, 0x00, 0x50, 0x04, 0x80, 0x14, 0xdd, 0x3c, 0x10, 0x74, 0x80, 0x24, +0x80, 0x06, 0x80, 0x29, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x40, 0x00, 0x17, 0x82, 0xe3, 0x00, 0x24, 0x00, 0x2e, 0x9e, 0x49, 0x9c, 0x91, 0x10, 0x24, +0x00, 0x2e, 0x46, 0xf0, 0x01, 0x40, 0x10, 0x17, 0x82, 0xe3, 0x84, 0x00, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x81, 0x96, 0xc0, +0x96, 0x90, 0xa6, 0x08, 0x4c, 0x32, 0x00, 0x10, 0xc3, 0x07, 0x84, 0x22, 0x4c, 0x30, 0x80, 0x0e, +0x44, 0x00, 0x00, 0x12, 0xd5, 0x11, 0x9c, 0x49, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x89, 0xf4, +0xdd, 0x2f, 0xd5, 0x0a, 0x9c, 0x49, 0xd5, 0x03, 0x84, 0x20, 0x80, 0x41, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x82, 0x8c, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0x44, 0x70, 0x00, 0x34, 0x96, 0x00, 0x42, 0x70, 0x1c, 0x24, 0x46, 0x00, 0x01, 0x41, +0x58, 0x00, 0x08, 0xc4, 0x99, 0xf8, 0x81, 0x21, 0x50, 0xa3, 0x80, 0x10, 0xa1, 0xbc, 0x46, 0x80, +0x00, 0xc8, 0x58, 0x84, 0x0b, 0x6c, 0xd5, 0x0d, 0x4b, 0xe0, 0x20, 0x01, 0xc0, 0x09, 0x00, 0x53, +0x00, 0x0a, 0x00, 0x04, 0x80, 0x06, 0xd8, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x36, 0xb4, 0xc6, +0x9c, 0x34, 0x80, 0x29, 0x84, 0x46, 0x4c, 0x65, 0x7f, 0xf1, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, +0x02, 0xe8, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0x81, 0x00, 0xc8, 0x03, +0x84, 0x07, 0xd5, 0x23, 0x80, 0x29, 0x84, 0x46, 0x9c, 0x04, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x00, 0x94, 0x80, 0x06, 0x80, 0x06, 0x10, 0x94, 0x00, 0x0a, 0x80, 0x28, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, +0x82, 0xe2, 0x00, 0x23, 0x80, 0x2c, 0x9e, 0x49, 0x9c, 0x91, 0x10, 0x23, 0x80, 0x2c, 0x46, 0xf0, +0x01, 0x40, 0x10, 0x17, 0x82, 0xe2, 0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x61, 0x96, 0x80, 0xa6, 0x08, 0x4c, 0x21, 0x80, 0x10, 0xc2, 0x07, +0x84, 0x22, 0x4c, 0x20, 0x80, 0x0e, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x10, 0x9c, 0x49, 0x46, 0xf0, +0x00, 0xce, 0x58, 0xf7, 0x8b, 0x10, 0xdd, 0x2f, 0xd5, 0x09, 0x9c, 0x49, 0xd5, 0x02, 0x84, 0x20, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x83, 0x5c, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x70, 0x01, 0x49, 0x58, 0x73, 0x8e, 0xa4, +0x80, 0xc0, 0x4c, 0x03, 0xc0, 0x14, 0x02, 0x20, 0x00, 0x17, 0x02, 0x10, 0x00, 0x13, 0xe2, 0x41, +0xe8, 0x24, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0xc0, 0x1f, 0x02, 0x13, +0x00, 0x17, 0x9c, 0x49, 0x12, 0x13, 0x00, 0x17, 0xd5, 0x19, 0x46, 0x50, 0x01, 0x49, 0x58, 0x52, +0x8e, 0xac, 0xd8, 0x13, 0x02, 0x23, 0x80, 0x16, 0x02, 0x13, 0x80, 0x12, 0xe2, 0x41, 0xe8, 0x0d, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0xc0, 0x08, 0x02, 0x13, 0x80, 0x16, +0x9c, 0x49, 0x12, 0x13, 0x80, 0x16, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0xa0, 0x01, 0x40, 0x58, 0xa5, 0x02, 0xe8, +0x50, 0x65, 0x7f, 0xf8, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x86, 0x88, 0x80, 0x0a, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x01, 0xdd, 0x27, 0x50, 0x93, +0x00, 0x0c, 0x14, 0xa3, 0x00, 0x02, 0x80, 0x09, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x12, 0x02, 0xdd, 0x27, 0x50, 0x83, 0x00, 0x10, 0x14, 0x93, 0x00, 0x03, +0x80, 0x08, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x03, +0xdd, 0x27, 0x50, 0xa3, 0x00, 0x14, 0x14, 0x83, 0x00, 0x04, 0x80, 0x0a, 0x84, 0x20, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x04, 0xdd, 0x27, 0x50, 0x93, 0x00, 0x18, +0x14, 0xa3, 0x00, 0x05, 0x80, 0x09, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, +0x44, 0x30, 0x12, 0x05, 0xdd, 0x27, 0x50, 0x83, 0x00, 0x1c, 0x14, 0x93, 0x00, 0x06, 0x80, 0x08, +0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x06, 0xdd, 0x27, +0x14, 0x83, 0x00, 0x07, 0x46, 0x60, 0x01, 0x41, 0x58, 0x63, 0x08, 0xdc, 0x50, 0x93, 0x00, 0x08, +0x85, 0x00, 0x44, 0x50, 0x00, 0x34, 0x42, 0xa4, 0x14, 0x24, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, +0x08, 0xc4, 0x50, 0x45, 0x00, 0x10, 0x99, 0x20, 0xb6, 0xbf, 0xf4, 0x81, 0x80, 0x04, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x0b, 0xdd, 0x27, 0x51, 0xc5, +0x00, 0x18, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x41, 0xce, 0x00, 0x00, 0xf4, 0x01, +0x50, 0x0e, 0x00, 0x04, 0xf0, 0x83, 0x14, 0x43, 0x7f, 0xfe, 0x80, 0x1c, 0x84, 0x20, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x0c, 0xdd, 0x27, 0xf0, 0x03, 0x15, 0xc3, +0x00, 0x00, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x0d, +0xdd, 0x27, 0x51, 0xc5, 0x00, 0x20, 0x46, 0x40, 0x01, 0x41, 0x58, 0x42, 0x08, 0xc4, 0x41, 0xce, +0x10, 0x00, 0xf4, 0x03, 0x50, 0x0e, 0x00, 0x04, 0xf0, 0x82, 0xa9, 0x31, 0x80, 0x1c, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x0e, 0xdd, 0x27, 0xf0, 0x02, +0x15, 0xc4, 0x80, 0x00, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, +0x12, 0x0f, 0xdd, 0x27, 0xf4, 0x02, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x50, 0xa5, +0x00, 0x28, 0x89, 0x40, 0x14, 0x44, 0x80, 0x01, 0x80, 0x0a, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, +0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x10, 0xdd, 0x27, 0x14, 0xa3, 0x00, 0x04, 0x8d, 0x01, +0x44, 0x00, 0x00, 0x64, 0x50, 0x94, 0x80, 0x34, 0x50, 0x63, 0x00, 0x34, 0xb4, 0xbf, 0x4c, 0x80, +0x7f, 0x8c, 0x84, 0xc0, 0x85, 0x0c, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, 0x8f, 0x1c, 0x42, 0x13, +0x20, 0x24, 0x46, 0x40, 0x01, 0x3c, 0x58, 0x42, 0x01, 0x40, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, +0x02, 0xe8, 0x98, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, +0x84, 0xc0, 0x8d, 0x1c, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, 0x8f, 0x1c, 0x42, 0x13, 0x20, 0x24, +0x46, 0x40, 0x01, 0x38, 0x58, 0x42, 0x0d, 0xa0, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xec, +0x98, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, 0x84, 0xc0, +0x44, 0x80, 0x00, 0x28, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, 0x8f, 0x1c, 0x42, 0x13, 0x20, 0x24, +0x46, 0x40, 0x01, 0x40, 0x58, 0x42, 0x03, 0x10, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xf0, +0x98, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, 0x84, 0xc0, +0x44, 0x80, 0x00, 0x24, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, 0x8f, 0x1c, 0x42, 0x13, 0x20, 0x24, +0x46, 0x40, 0x01, 0x3c, 0x58, 0x42, 0x05, 0xf0, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xf4, +0x98, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, 0x84, 0xc0, +0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, 0x8f, 0x1c, 0x94, 0x76, 0x46, 0x40, 0x01, 0x42, 0x58, 0x42, +0x0d, 0x14, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xf8, 0x98, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, +0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf1, 0x84, 0xc0, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, +0x8f, 0x1c, 0x94, 0x76, 0x46, 0x40, 0x01, 0x4b, 0x58, 0x42, 0x03, 0x78, 0x46, 0x00, 0x01, 0x40, +0x58, 0x00, 0x02, 0xfc, 0x98, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, +0xde, 0xf1, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x49, 0x04, 0x37, 0x83, 0xad, 0x80, 0xc1, 0x97, 0xc0, 0xcb, 0x03, 0x80, 0x03, +0xd5, 0x08, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xae, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, +0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x10, 0x8a, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0xa1, 0x46, 0x40, 0x01, 0x49, 0x58, 0x42, +0x0e, 0xa4, 0xdf, 0x1e, 0xa0, 0xe4, 0xc3, 0x0e, 0x9d, 0x64, 0xdb, 0x0c, 0x84, 0x00, 0x80, 0x40, +0xa8, 0x24, 0xd5, 0x39, 0x96, 0xa0, 0x9f, 0x2b, 0x96, 0x08, 0xb4, 0x63, 0x4c, 0x22, 0x40, 0x05, +0xd5, 0x32, 0x84, 0x40, 0x80, 0x02, 0x46, 0x50, 0x01, 0x49, 0x58, 0x52, 0x8e, 0xa8, 0x9d, 0x11, +0x50, 0x10, 0x00, 0x0b, 0xd3, 0x28, 0x44, 0x50, 0x00, 0x17, 0xda, 0xed, 0xd5, 0x24, 0xa0, 0xe5, +0xc3, 0x16, 0x50, 0x52, 0x00, 0x0c, 0xdb, 0x13, 0x84, 0x00, 0x80, 0x40, 0xa8, 0x25, 0xd5, 0x1b, +0x00, 0x51, 0x80, 0x14, 0x00, 0x41, 0x80, 0x34, 0x96, 0x88, 0x98, 0x6c, 0x8c, 0x2d, 0x98, 0x08, +0x84, 0x23, 0x96, 0x00, 0xb4, 0x63, 0x4c, 0x20, 0xc0, 0x05, 0xd5, 0x0d, 0x84, 0x40, 0x80, 0x02, +0x46, 0x40, 0x01, 0x49, 0x58, 0x42, 0x0e, 0xb0, 0x9c, 0x51, 0x4c, 0x32, 0x00, 0x05, 0x5c, 0xf0, +0x00, 0xf7, 0xe9, 0xe7, 0xae, 0xb0, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0xa1, 0xca, 0x80, 0xc0, 0x02, 0x90, 0x80, 0x08, 0x44, 0x30, 0x10, 0x65, 0x81, 0x01, +0x80, 0x07, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x80, 0x06, 0x08, 0x10, 0x00, 0x01, 0x46, 0xa0, 0x00, 0x41, +0x58, 0xa5, 0x04, 0x98, 0x38, 0x13, 0xa4, 0x08, 0x8d, 0x21, 0xa6, 0xb0, 0x40, 0x94, 0x80, 0x13, +0x80, 0x20, 0x40, 0x03, 0xa4, 0x00, 0x4b, 0xe0, 0x28, 0x01, 0xa6, 0x30, 0x50, 0x13, 0x00, 0x21, +0x89, 0x20, 0x00, 0x03, 0x00, 0x20, 0x40, 0x94, 0x80, 0x13, 0x38, 0x03, 0xa4, 0x08, 0x8d, 0x21, +0x40, 0x94, 0x80, 0x13, 0x00, 0x23, 0x00, 0x20, 0x40, 0x03, 0xa4, 0x00, 0x4b, 0xe0, 0x28, 0x01, +0x00, 0x03, 0x00, 0x20, 0x89, 0x20, 0x12, 0x94, 0x00, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xa1, 0xca, 0x80, 0xc0, 0x02, 0xa0, 0x80, 0x08, 0x81, 0x01, +0x80, 0x07, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x10, 0x3f, +0x04, 0x94, 0x00, 0x05, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xa6, 0x74, +0x40, 0x03, 0xa8, 0x00, 0x18, 0x10, 0x00, 0x01, 0x50, 0x33, 0x00, 0x08, 0xa6, 0xb5, 0x18, 0x20, +0x00, 0x01, 0x50, 0x25, 0x00, 0x06, 0xa6, 0x76, 0x96, 0x91, 0x18, 0x10, 0x00, 0x01, 0xa6, 0x77, +0x18, 0x10, 0x00, 0x01, 0xa6, 0x58, 0xae, 0x40, 0x9c, 0x51, 0xa6, 0xd9, 0x96, 0x49, 0xae, 0xc1, +0x00, 0x03, 0x00, 0x0a, 0x38, 0x03, 0x88, 0x08, 0x9c, 0x09, 0x00, 0x23, 0x00, 0x0b, 0x96, 0x01, +0x38, 0x23, 0x84, 0x08, 0x00, 0x13, 0x00, 0x0c, 0x38, 0x13, 0x80, 0x08, 0x44, 0x10, 0x00, 0xa0, +0xb4, 0x86, 0x9c, 0x01, 0x40, 0x44, 0x90, 0x01, 0x40, 0x42, 0x04, 0x57, 0x96, 0x01, 0x98, 0xf8, +0x9c, 0x82, 0x38, 0x43, 0x80, 0x08, 0xb4, 0x06, 0x8b, 0x20, 0x40, 0x14, 0x85, 0x37, 0x92, 0x28, +0xae, 0x59, 0x12, 0x24, 0x00, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x98, 0xbc, 0x80, 0xc0, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa8, 0x4c, 0x60, 0x40, 0x04, +0x84, 0x01, 0xd5, 0x07, 0x50, 0x10, 0x00, 0x08, 0x40, 0x03, 0x04, 0x03, 0x5c, 0x00, 0x00, 0x01, +0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0c, 0x00, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xb4, 0x06, 0x4c, 0x03, 0x40, 0x04, 0x84, 0x00, +0xd5, 0x0e, 0xb4, 0x20, 0xd5, 0x0a, 0x00, 0x30, 0x80, 0x10, 0x00, 0x20, 0x00, 0x10, 0x40, 0x21, +0x88, 0x06, 0x40, 0x00, 0x88, 0x1b, 0xb4, 0x21, 0x4c, 0x13, 0x7f, 0xf7, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xe0, 0x80, 0xc1, 0xc8, 0x02, 0xd5, 0x04, 0x84, 0x00, +0x40, 0x00, 0x04, 0x06, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0b, 0xcc, +0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x06, 0x88, 0x84, 0x20, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x26, +0x80, 0x07, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8f, 0xb4, 0xdd, 0x2f, 0x84, 0x20, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0b, 0xcd, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0xc0, 0x10, 0xb4, 0xa6, 0xd8, 0x0e, +0x46, 0x50, 0x01, 0x49, 0x58, 0x52, 0x8e, 0xbc, 0x50, 0x22, 0xff, 0xe8, 0xde, 0x04, 0x9c, 0x54, +0xa8, 0x56, 0xd5, 0x04, 0x50, 0x11, 0x00, 0x0c, 0xa8, 0x57, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x67, 0x8e, 0xd4, 0x81, 0x00, +0xce, 0x1b, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8f, 0xec, 0xdd, 0x2f, 0x80, 0xe0, 0x80, 0x26, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0c, 0xb6, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x80, 0x08, 0x80, 0x27, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, +0x81, 0xa4, 0xdd, 0x2f, 0xd5, 0x0a, 0x84, 0xa1, 0xd6, 0x03, 0x84, 0x00, 0xd5, 0x06, 0x46, 0xf0, +0x00, 0xcf, 0x58, 0xf7, 0x81, 0x40, 0xdd, 0x2f, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xf4, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x03, 0x06, 0x85, 0x40, 0x46, 0x70, +0x01, 0x38, 0x58, 0x73, 0x8a, 0x20, 0xa6, 0x30, 0x44, 0x50, 0x00, 0xff, 0x51, 0xc3, 0x7f, 0xfa, +0x4c, 0x02, 0x80, 0xfe, 0x00, 0x03, 0x7f, 0xfe, 0x84, 0xa2, 0x4c, 0x02, 0x80, 0xde, 0xe6, 0x03, +0xe8, 0x05, 0x4e, 0x02, 0x00, 0xda, 0x48, 0x00, 0x00, 0xf3, 0x84, 0xa3, 0x4c, 0x02, 0x80, 0x8c, +0x84, 0xa4, 0x4c, 0x02, 0xc0, 0xed, 0xa7, 0x7c, 0x4c, 0x50, 0x00, 0xea, 0xa7, 0x7d, 0x00, 0x03, +0x7f, 0xff, 0xd8, 0x74, 0x00, 0x53, 0x80, 0x0a, 0x00, 0x13, 0x80, 0x09, 0xa7, 0x34, 0xa6, 0x33, +0x40, 0x52, 0xc0, 0x08, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x42, 0x40, 0x08, 0x40, 0x00, 0x20, 0x08, +0x00, 0x33, 0x80, 0x08, 0xa6, 0xb2, 0x98, 0x69, 0x98, 0x20, 0x98, 0x4b, 0x98, 0x02, 0x4c, 0x10, +0x40, 0x5e, 0x00, 0x53, 0x80, 0x0b, 0xa6, 0x35, 0xd8, 0x59, 0x00, 0x13, 0x80, 0x0d, 0xa6, 0x37, +0x00, 0x33, 0x80, 0x0c, 0xa6, 0xb6, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x00, 0x20, 0x08, 0x98, 0x4b, +0x98, 0x02, 0x97, 0x49, 0x96, 0x01, 0xd8, 0x4a, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xac, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x8c, 0x04, 0xdd, 0x2f, 0x81, 0x00, 0xc8, 0x0f, 0x46, 0x00, +0x01, 0x49, 0x58, 0x00, 0x0e, 0xb0, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, 0x82, 0x24, 0xdd, 0x2f, +0x81, 0x00, 0xc8, 0x03, 0x85, 0x41, 0xd5, 0x32, 0x85, 0x41, 0x50, 0x04, 0x00, 0x04, 0x46, 0x10, +0x01, 0x38, 0x58, 0x10, 0x8a, 0x20, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, +0xa6, 0xfe, 0x46, 0x10, 0x01, 0x38, 0x58, 0x10, 0x8a, 0x2e, 0x10, 0x34, 0x00, 0x14, 0x46, 0x30, +0x00, 0x41, 0x58, 0x31, 0x84, 0x98, 0xa6, 0xbe, 0xf3, 0x81, 0x50, 0x04, 0x00, 0x15, 0xdd, 0x23, +0xa6, 0x30, 0x50, 0x1e, 0x00, 0x0e, 0x10, 0x04, 0x00, 0x34, 0x50, 0x04, 0x00, 0x35, 0xa6, 0xb0, +0xf3, 0x01, 0xdd, 0x23, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x37, 0x83, 0xc3, 0x80, 0x28, 0x46, 0x00, +0x01, 0x49, 0x58, 0x00, 0x0e, 0xb0, 0x80, 0x4a, 0xdd, 0x23, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, +0x0a, 0x20, 0x84, 0x20, 0x44, 0x20, 0x00, 0x30, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0xd5, 0x65, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x27, 0x83, 0xc2, 0x46, 0x00, 0x01, 0x49, +0x58, 0x00, 0x0e, 0xb0, 0x80, 0x3c, 0xdd, 0x22, 0xc0, 0x02, 0xd5, 0x49, 0x46, 0x00, 0x01, 0x49, +0x58, 0x00, 0x0e, 0xac, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x8c, 0x04, 0xdd, 0x2f, 0x81, 0x00, +0xc8, 0x0f, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xb0, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, +0x82, 0x24, 0xdd, 0x2f, 0x81, 0x00, 0xc8, 0x03, 0x85, 0x41, 0xd5, 0x41, 0x85, 0x41, 0x50, 0x04, +0x00, 0x04, 0x80, 0x3c, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xa6, 0x30, +0x50, 0x1e, 0x00, 0x0e, 0x10, 0x04, 0x00, 0x14, 0x50, 0x04, 0x00, 0x15, 0xa6, 0xb0, 0x46, 0xf0, +0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x84, 0x00, 0x10, 0x04, 0x00, 0x34, 0x80, 0x28, +0x46, 0xf0, 0x01, 0x49, 0x04, 0x37, 0x83, 0xc3, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xb0, +0x80, 0x4a, 0xdd, 0x23, 0xd5, 0x1c, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x27, 0x83, 0xc2, 0x46, 0x00, +0x01, 0x49, 0x58, 0x00, 0x0e, 0xb0, 0x80, 0x3c, 0xdd, 0x22, 0xc0, 0x05, 0xa6, 0x71, 0x10, 0x10, +0x00, 0x10, 0xd5, 0x0d, 0x80, 0x3c, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0a, 0x20, 0x44, 0x20, +0x00, 0x30, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x80, 0xdd, 0x2f, 0x50, 0x63, 0x00, 0x30, +0x46, 0x50, 0x01, 0x0f, 0x58, 0x52, 0x83, 0xc6, 0x4c, 0x62, 0xfe, 0xf7, 0xec, 0x0c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x46, 0x60, +0x01, 0x0f, 0x58, 0x63, 0x03, 0x07, 0x81, 0x49, 0xd5, 0x55, 0x00, 0x03, 0x7f, 0xfd, 0x84, 0xa4, +0x51, 0xc3, 0x7f, 0xf9, 0xd0, 0x4c, 0x84, 0xa1, 0xd0, 0x4a, 0x00, 0x03, 0x7f, 0xff, 0x44, 0x50, +0x00, 0xff, 0xd0, 0x45, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x27, 0x83, 0xc2, 0x46, 0x00, 0x01, 0x49, +0x58, 0x00, 0x0e, 0xa8, 0x80, 0x3c, 0xdd, 0x22, 0xc0, 0x0a, 0x20, 0x23, 0x00, 0x00, 0x00, 0x10, +0x00, 0x10, 0x98, 0x51, 0x90, 0x21, 0x10, 0x10, 0x00, 0x10, 0xd5, 0x31, 0x46, 0x00, 0x01, 0x49, +0x58, 0x00, 0x0e, 0xa4, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x8c, 0x04, 0xdd, 0x2f, 0x80, 0xe0, +0xc8, 0x0f, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa8, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, +0x82, 0x24, 0xdd, 0x2f, 0x80, 0xe0, 0xc8, 0x03, 0x85, 0x41, 0xd5, 0x19, 0x85, 0x41, 0x46, 0xf0, +0x01, 0x49, 0x04, 0x27, 0x83, 0xb6, 0x80, 0x3c, 0xa8, 0xbd, 0x9c, 0x3c, 0x46, 0xf0, 0x00, 0xc9, +0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x37, 0x83, 0xc3, 0x80, 0x27, +0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa8, 0x80, 0x4a, 0xdd, 0x23, 0x8d, 0x21, 0x50, 0x63, +0x00, 0x30, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x07, 0x84, 0xac, 0xe3, 0x20, 0xe9, 0xa7, 0xec, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x00, 0x80, 0xc1, +0x80, 0xe2, 0xc0, 0x06, 0xc1, 0x05, 0x84, 0x00, 0x40, 0x00, 0x08, 0x06, 0xd5, 0x02, 0x84, 0x00, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0b, 0xb4, 0x46, 0x90, 0x00, 0x04, +0x58, 0x94, 0x86, 0x88, 0x84, 0x20, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x26, 0x80, 0x08, 0x46, 0xf0, +0x00, 0xc8, 0x58, 0xf7, 0x8f, 0xb4, 0xdd, 0x2f, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x0b, 0xb5, 0x4b, 0xe0, 0x24, 0x01, 0xb7, 0x07, 0xb4, 0x06, 0xb6, 0xe0, +0xb6, 0xe6, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x80, 0xc1, 0x96, 0x90, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x97, 0x8e, 0xd4, 0xf2, 0x81, 0x80, 0xe0, +0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, 0x06, 0x88, 0x80, 0x06, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, +0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0c, 0xec, 0x5c, 0xa4, 0x80, 0x01, 0xdd, 0x3c, 0x4e, 0x92, +0x00, 0x04, 0x85, 0x00, 0xd5, 0x10, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8f, 0xec, +0xdd, 0x2f, 0x80, 0x29, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0c, 0xf3, +0x81, 0x00, 0xdd, 0x3c, 0xf0, 0x01, 0xc8, 0x0c, 0x4e, 0xa2, 0x00, 0x03, 0xd5, 0x0b, 0x80, 0x07, +0x80, 0x26, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x85, 0x58, 0xdd, 0x2f, 0xd5, 0x0b, 0x4e, 0xa2, +0x00, 0x0a, 0x80, 0x07, 0x80, 0x28, 0x80, 0x46, 0x46, 0xf0, 0x00, 0xcf, 0x58, 0xf7, 0x85, 0x88, +0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0x60, +0x01, 0x49, 0x58, 0x63, 0x0e, 0xa4, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x86, 0x88, 0x80, 0x06, +0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0b, 0x6a, 0xdd, 0x27, +0x50, 0x93, 0x00, 0x04, 0xb6, 0xc6, 0x80, 0x09, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x0b, 0x6b, 0xdd, 0x27, 0x50, 0xa3, 0x00, 0x08, 0x14, 0x93, 0x00, 0x01, +0x80, 0x0a, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0b, 0x6c, +0xdd, 0x27, 0x50, 0x83, 0x00, 0x0c, 0x14, 0xa3, 0x00, 0x02, 0x80, 0x08, 0x84, 0x20, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0b, 0x6d, 0xdd, 0x27, 0x84, 0x20, 0x14, 0x83, +0x00, 0x07, 0x14, 0x83, 0x00, 0x03, 0x14, 0x93, 0x00, 0x06, 0x12, 0x13, 0x00, 0x16, 0xa8, 0x74, +0xa8, 0x75, 0x12, 0x13, 0x00, 0x17, 0x44, 0x80, 0x00, 0x18, 0x80, 0xc1, 0x46, 0x70, 0x00, 0xcd, +0x58, 0x73, 0x8f, 0x1c, 0x42, 0x13, 0x20, 0x24, 0x46, 0x00, 0x01, 0x3d, 0x58, 0x00, 0x04, 0x00, +0x98, 0x48, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa4, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, +0x44, 0x50, 0x01, 0xf4, 0xde, 0xf0, 0x84, 0xc0, 0x44, 0x80, 0x00, 0x54, 0x46, 0x70, 0x00, 0xcd, +0x58, 0x73, 0x8f, 0x1c, 0x42, 0x13, 0x20, 0x24, 0x46, 0x00, 0x01, 0x3a, 0x58, 0x00, 0x00, 0x70, +0x98, 0x48, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xac, 0x4b, 0xe0, 0x1c, 0x01, 0x9d, 0xb1, +0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0xbc, 0x54, 0x80, 0x80, 0xff, 0x80, 0xe2, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, +0x97, 0x80, 0x80, 0x27, 0x80, 0x08, 0x54, 0xa1, 0x80, 0xff, 0x81, 0x24, 0xdd, 0x22, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x0a, 0x27, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0xa3, 0xde, 0x16, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, +0x84, 0x06, 0x84, 0xa2, 0xd8, 0x03, 0x84, 0x01, 0xd5, 0x03, 0x5c, 0x00, 0x00, 0x01, 0xc0, 0x77, +0x46, 0xf0, 0x01, 0x4d, 0x04, 0x37, 0x80, 0xe0, 0x80, 0x47, 0x84, 0x01, 0x84, 0x23, 0xdd, 0x23, +0x80, 0xc0, 0xd5, 0x6e, 0x84, 0xa5, 0xde, 0x6b, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x04, 0x00, +0xa6, 0x76, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x44, 0x10, 0x27, 0x87, 0x44, 0xb4, 0x06, 0xe6, 0x22, +0xe8, 0x5e, 0xc0, 0x5d, 0x46, 0x10, 0x01, 0x01, 0x58, 0x10, 0x87, 0x14, 0x00, 0x03, 0x00, 0x11, +0x50, 0x50, 0x81, 0x34, 0x80, 0x69, 0x40, 0x12, 0x80, 0x1b, 0x80, 0x4a, 0x46, 0x90, 0x00, 0xcb, +0x58, 0x94, 0x8c, 0x24, 0x4b, 0xe0, 0x24, 0x01, 0xc0, 0x4a, 0xa6, 0x36, 0x84, 0xa1, 0xd8, 0x0b, +0x00, 0x23, 0x00, 0x12, 0x50, 0x33, 0x00, 0x0a, 0x80, 0x08, 0x80, 0x27, 0x4b, 0xe0, 0x24, 0x01, +0xc8, 0x16, 0xd5, 0x3d, 0x10, 0x83, 0x00, 0x12, 0xa7, 0x38, 0x10, 0x43, 0x00, 0x0a, 0xa6, 0x39, +0x10, 0x03, 0x00, 0x0b, 0xa6, 0x7a, 0x10, 0x13, 0x00, 0x0c, 0xa7, 0x3b, 0x10, 0x43, 0x00, 0x0d, +0xa6, 0x3c, 0x10, 0x03, 0x00, 0x0e, 0xa6, 0x7d, 0x10, 0x13, 0x00, 0x0f, 0x46, 0xf0, 0x01, 0x4d, +0x04, 0x37, 0x80, 0xe0, 0x84, 0x25, 0x84, 0x01, 0x80, 0x47, 0xdd, 0x23, 0x80, 0xc0, 0x46, 0x30, +0x01, 0x44, 0x58, 0x31, 0x87, 0x44, 0xc0, 0x0e, 0x84, 0x01, 0xae, 0x18, 0x80, 0x26, 0xa7, 0x36, +0x9c, 0x1a, 0xaf, 0x19, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, +0xd5, 0x0f, 0x84, 0x82, 0xaf, 0x18, 0x10, 0x81, 0x80, 0x01, 0x9c, 0x1a, 0x80, 0x27, 0x84, 0x46, +0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x58, 0xdd, 0x2f, 0xd5, 0x02, 0x84, 0xc1, 0x80, 0x06, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xc2, 0x46, 0xf0, 0x01, 0x4d, +0x04, 0x27, 0x80, 0xe1, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x87, 0x80, 0xf2, 0x97, 0xc0, 0x96, 0x08, +0x80, 0x26, 0x54, 0xa1, 0x80, 0xff, 0x81, 0x24, 0xdd, 0x22, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, +0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x09, 0xf8, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0x4e, 0x82, 0x00, 0x35, 0x46, 0x20, 0x01, 0x01, 0x58, 0x21, 0x07, 0x14, 0x00, 0x54, +0x00, 0xbe, 0x50, 0x01, 0x01, 0x34, 0x40, 0x31, 0x14, 0x1a, 0x40, 0x30, 0x14, 0x1b, 0x84, 0x01, +0x4c, 0x70, 0x40, 0x0b, 0x80, 0x0a, 0x80, 0x29, 0x80, 0x45, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, +0x8c, 0x24, 0xdd, 0x2f, 0xc0, 0x1c, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x37, 0x80, 0xe0, 0x80, 0x46, +0x80, 0x27, 0x84, 0x02, 0xdd, 0x23, 0x80, 0xc0, 0xc0, 0x13, 0xa7, 0x36, 0x46, 0x30, 0x01, 0x0f, +0x58, 0x31, 0x83, 0xc8, 0x10, 0x41, 0x80, 0x17, 0x50, 0x01, 0x80, 0x10, 0x80, 0x26, 0x84, 0x46, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xd5, 0x02, 0x84, 0xc1, 0x80, 0x06, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xe2, 0x46, 0xf0, +0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, 0x97, 0x80, 0x96, 0x08, 0x80, 0x27, 0x54, 0x91, 0x80, 0xff, +0x81, 0x04, 0xdd, 0x22, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, +0x09, 0xca, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0xa1, 0xde, 0x17, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x83, 0xc5, 0x46, 0x50, 0x01, 0x01, 0x58, 0x52, 0x87, 0x14, +0x50, 0x32, 0x81, 0x34, 0x40, 0x32, 0x88, 0x1a, 0x80, 0x09, 0x80, 0x28, 0x46, 0xf0, 0x00, 0xcb, +0x58, 0xf7, 0x8c, 0x24, 0xdd, 0x2f, 0xc8, 0x03, 0x80, 0x06, 0xd5, 0x0d, 0x46, 0xf0, 0x01, 0x4d, +0x04, 0x37, 0x80, 0xe0, 0x80, 0x26, 0x80, 0x47, 0x84, 0x03, 0xdd, 0x23, 0x46, 0xf0, 0x01, 0x38, +0x14, 0x07, 0x82, 0x84, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa0, 0xbc, 0x46, 0x70, 0x01, 0x44, 0x58, 0x73, 0x8d, 0xe8, 0xa0, 0x3c, 0x81, 0x02, 0xdd, 0x20, +0xa0, 0x7d, 0x80, 0x08, 0xdd, 0x21, 0x80, 0xc0, 0xc0, 0x05, 0xa6, 0x06, 0xc0, 0x45, 0xa0, 0x32, +0xd5, 0x44, 0xa0, 0x39, 0xdd, 0x20, 0x80, 0xe0, 0xc0, 0x3f, 0x44, 0x20, 0x00, 0x10, 0x80, 0x26, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, 0xdd, 0x2f, 0x80, 0x28, 0x84, 0x46, 0x80, 0x07, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x84, 0x0f, 0xae, 0x3e, 0x84, 0x01, +0xae, 0x3f, 0xa9, 0xba, 0x46, 0xf0, 0x01, 0x41, 0x04, 0x07, 0x80, 0xb0, 0x80, 0x26, 0xa0, 0x03, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x5c, 0x00, 0x00, 0x01, 0x44, 0x30, 0x09, 0x70, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xa9, 0xbb, 0x44, 0x00, 0x00, 0x49, +0x46, 0xf0, 0x01, 0x41, 0x04, 0x17, 0x80, 0xb0, 0x44, 0x20, 0xab, 0xcd, 0xa9, 0xcb, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x37, 0x80, 0xb1, 0x46, 0xf0, 0x01, 0x41, 0x14, 0x77, 0x80, 0xb0, 0x80, 0x26, +0xdd, 0x23, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0xef, 0xf8, 0x46, 0x20, 0x01, 0x38, 0x00, 0x71, 0x0a, 0x03, 0x80, 0x20, 0xc7, 0x05, +0x84, 0x00, 0x10, 0x01, 0x0a, 0x03, 0x84, 0xe1, 0x80, 0x1f, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x41, +0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x67, 0x81, 0xd1, 0x81, 0x5f, +0xce, 0x10, 0xd5, 0x2a, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x37, 0x83, 0x80, 0xdd, 0x23, 0xc8, 0x15, +0xa0, 0x73, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x57, 0x81, 0xd1, 0xd1, 0x0f, 0x80, 0xc1, 0xd5, 0x02, +0x81, 0x5f, 0xa0, 0xf3, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x47, 0x81, 0xd1, 0x80, 0x26, 0x80, 0x1f, +0x80, 0x47, 0x4c, 0x32, 0x7f, 0xe9, 0x84, 0x00, 0xa1, 0x73, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x17, +0x81, 0xd1, 0xd9, 0x09, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x37, 0x83, 0x80, 0x80, 0x47, 0x80, 0x1f, +0x80, 0x26, 0xdd, 0x23, 0xc8, 0x4b, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x3c, 0xa1, 0xc3, +0xcf, 0x13, 0xd5, 0x46, 0xa6, 0x26, 0x5c, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x3b, +0xb4, 0xa6, 0xb4, 0x80, 0xdc, 0x07, 0xa5, 0x72, 0xa4, 0x42, 0xd9, 0x04, 0x80, 0xc7, 0x85, 0x01, +0xd5, 0x16, 0x80, 0xe0, 0xd5, 0x07, 0x81, 0x20, 0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x06, 0x88, +0x80, 0xdf, 0xa1, 0x3b, 0x04, 0x54, 0x80, 0x03, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x08, 0x5b, 0xdc, 0xdf, 0x80, 0xc7, 0x81, 0x01, 0xa0, 0x3b, 0x46, 0xf0, +0x01, 0x4d, 0x04, 0x57, 0x81, 0xd2, 0xd8, 0x18, 0xa6, 0x06, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x5c, 0x00, 0x00, 0x01, 0x44, 0x30, 0x08, 0x65, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xa0, 0x3b, 0xb4, 0xbf, 0xb4, 0x60, 0xdb, 0x05, 0x02, 0x5f, +0x80, 0x02, 0xa4, 0x02, 0xd0, 0x03, 0x4e, 0x82, 0x00, 0x04, 0xa0, 0x33, 0xd5, 0x02, 0x84, 0x00, +0xec, 0x08, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xf0, +0x01, 0x38, 0x00, 0x07, 0x8a, 0x03, 0xc0, 0x6b, 0x46, 0x60, 0x01, 0x4d, 0x58, 0x63, 0x07, 0x3c, +0xa0, 0x73, 0xc9, 0x10, 0xa4, 0x32, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x5c, 0x00, +0x00, 0x01, 0x44, 0x30, 0x07, 0xdb, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, +0xd5, 0x56, 0xa0, 0xb4, 0xca, 0x15, 0xa4, 0x33, 0x80, 0x22, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x07, 0xe1, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x86, 0x88, 0xdd, 0x2f, 0xa4, 0x32, 0xa1, 0x73, 0xac, 0x33, 0xa9, 0x74, 0xd5, 0x0a, 0xa0, 0x93, +0xa0, 0x0b, 0xa8, 0x8b, 0xa0, 0x74, 0xa8, 0x0b, 0xa4, 0x33, 0xa4, 0x72, 0x98, 0x08, 0xac, 0x33, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x4d, 0x12, 0x17, 0x83, 0xa0, 0x46, 0xf0, 0x01, 0x4d, 0x14, 0x17, +0x81, 0xd2, 0xd5, 0x2d, 0xa7, 0x36, 0x84, 0xaf, 0x5c, 0x02, 0x00, 0x02, 0xd4, 0x3f, 0x4b, 0xe0, +0x28, 0x01, 0xa0, 0x33, 0x14, 0x04, 0x00, 0x03, 0x14, 0x93, 0x00, 0x03, 0x04, 0x54, 0x00, 0x04, +0xde, 0x03, 0x14, 0x84, 0x00, 0x04, 0xa6, 0x37, 0xc0, 0x10, 0xa6, 0xf6, 0x46, 0x00, 0x01, 0x4d, +0x58, 0x00, 0x07, 0x48, 0x80, 0x46, 0x50, 0x10, 0x7f, 0xf8, 0xcb, 0x03, 0xa0, 0xfb, 0xd5, 0x0d, +0x9e, 0x04, 0xa0, 0xfb, 0x9e, 0x46, 0xd5, 0x09, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x4c, +0xa0, 0xfb, 0x80, 0x46, 0x50, 0x10, 0x7f, 0xf6, 0xdd, 0x23, 0xd5, 0x0e, 0x46, 0x80, 0x01, 0x41, +0x58, 0x84, 0x02, 0xb0, 0x46, 0xa0, 0x00, 0x04, 0x58, 0xa5, 0x06, 0x88, 0x85, 0x20, 0x46, 0x70, +0x01, 0x44, 0x58, 0x73, 0x8d, 0xe8, 0x04, 0x64, 0x00, 0x03, 0x44, 0x30, 0x08, 0x04, 0x84, 0x20, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0xce, 0xbe, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0xb4, 0x60, 0x81, 0x00, 0x80, 0xc1, 0x80, 0xe2, 0xcb, 0x14, +0xa4, 0x08, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x80, 0x23, 0x5c, 0x00, 0x00, 0x01, +0x44, 0x30, 0x07, 0xbe, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0xa9, 0xfb, +0x84, 0x01, 0xb6, 0xe8, 0xd5, 0x07, 0xa0, 0xdb, 0xa8, 0xd3, 0xb4, 0x00, 0xa8, 0x83, 0xa4, 0x08, +0x9c, 0x01, 0xac, 0x30, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0xa1, 0x93, 0x81, 0x00, 0x80, 0xe1, 0x4c, 0x61, 0x40, 0x26, 0xb4, 0x00, 0x46, 0x90, 0x00, 0x04, +0x58, 0x94, 0x86, 0x88, 0x40, 0x00, 0x18, 0x03, 0x5c, 0x00, 0x00, 0x01, 0x84, 0x20, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x07, 0xa5, 0x4b, 0xe0, 0x24, 0x01, 0xa4, 0x38, +0x84, 0x20, 0x56, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x07, 0xa6, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x00, 0xa8, 0x33, 0xb6, 0x08, +0xd5, 0x0a, 0xa0, 0x33, 0xa8, 0x13, 0x84, 0x00, 0xa8, 0x33, 0xb4, 0xa8, 0xde, 0x02, 0xb6, 0x48, +0xa4, 0x38, 0x9e, 0x01, 0xac, 0x38, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x01, 0x4d, 0x58, 0x63, 0x07, 0x3c, +0xa1, 0xf4, 0xcf, 0x17, 0xa4, 0x33, 0x80, 0x27, 0x5c, 0x00, 0x00, 0x01, 0x46, 0x20, 0x00, 0xd2, +0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x07, 0x8c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0xa0, 0x33, 0xc0, 0x06, 0xa8, 0x34, 0xa4, 0x32, 0xa9, 0xf3, 0xac, 0x33, 0xad, 0xf2, +0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x3c, 0xa0, 0x84, 0xca, 0x03, 0x80, 0x02, 0xd5, 0x08, +0x46, 0xf0, 0x01, 0x44, 0x04, 0x37, 0x83, 0x7c, 0x9c, 0x46, 0x8c, 0x10, 0xdd, 0x23, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0xa1, 0x87, 0xa0, 0x76, +0xc1, 0x05, 0x84, 0x40, 0xa8, 0x8a, 0xa8, 0xb6, 0xae, 0x8e, 0x46, 0x70, 0x01, 0x4d, 0x58, 0x73, +0x87, 0x50, 0x4c, 0x03, 0x40, 0x17, 0xa4, 0x38, 0x84, 0x20, 0x56, 0x00, 0x00, 0x01, 0x5c, 0x00, +0x00, 0x01, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x07, 0x42, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0x00, 0xa8, 0x39, 0xac, 0x38, 0xd5, 0x0d, +0xa1, 0x79, 0xde, 0x02, 0xa8, 0x39, 0xa0, 0x77, 0xa8, 0x47, 0x46, 0x00, 0x01, 0x4d, 0x02, 0x10, +0x03, 0xa8, 0x9e, 0x49, 0x12, 0x10, 0x03, 0xa8, 0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x50, +0xa0, 0x42, 0xc9, 0x04, 0xa9, 0xb7, 0xa9, 0x82, 0xd5, 0x05, 0xa0, 0x4f, 0xa8, 0x77, 0xa0, 0x02, +0xa9, 0x87, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, +0x01, 0x4d, 0x04, 0x67, 0x81, 0xd5, 0x96, 0x49, 0xc6, 0x03, 0x80, 0x66, 0xd5, 0x1a, 0x46, 0xf0, +0x01, 0x4d, 0x02, 0x07, 0x83, 0xa8, 0x80, 0x26, 0x40, 0x03, 0x00, 0x06, 0x46, 0x20, 0x00, 0xd2, +0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x06, 0xf2, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, +0xdd, 0x2f, 0x80, 0x06, 0xd5, 0x10, 0xb4, 0xa2, 0xd8, 0x03, 0xa5, 0x52, 0xd1, 0x0b, 0x80, 0x62, +0xa0, 0x9f, 0x4c, 0x23, 0x7f, 0xfa, 0xd5, 0x0a, 0xa4, 0x32, 0x4c, 0x00, 0x80, 0x04, 0x84, 0x00, +0xd5, 0x02, 0x80, 0x03, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0xb4, 0xa6, 0xd8, 0xf9, 0xd5, 0xf5, +0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x97, 0x80, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x07, 0x81, 0xd5, +0x81, 0x01, 0x97, 0xd1, 0xc0, 0x1e, 0x46, 0xf0, 0x01, 0x4d, 0x02, 0x47, 0x83, 0xa8, 0x84, 0x20, +0x40, 0x00, 0x90, 0x06, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x06, 0xd9, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x37, +0x81, 0xe2, 0x80, 0x27, 0x80, 0x08, 0xdd, 0x23, 0xc0, 0x04, 0xa0, 0x07, 0xa7, 0x46, 0xd6, 0x02, +0x84, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, +0x01, 0x4d, 0x58, 0x10, 0x87, 0x50, 0xa1, 0x89, 0x96, 0x80, 0xce, 0x12, 0xa4, 0x08, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x40, 0x03, 0x00, 0x06, 0x80, 0x26, 0x44, 0x30, 0x06, 0xbf, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x80, 0x06, 0xd5, 0x0d, 0xa4, 0x08, +0xe2, 0x40, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x08, 0xa0, 0x37, 0x84, 0x20, 0xd5, 0x03, 0xa0, 0x07, +0x9c, 0x49, 0xe0, 0x22, 0xe9, 0xfd, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0xbc, 0x54, 0x80, 0x00, 0xff, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x07, 0x81, 0xd5, 0x81, 0x41, +0x40, 0x91, 0x00, 0x13, 0xc0, 0x27, 0x46, 0xf0, 0x01, 0x4d, 0x02, 0x37, 0x83, 0xa8, 0x84, 0xc0, +0x40, 0x03, 0x0c, 0x06, 0x80, 0x26, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, +0x06, 0xa5, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x44, +0x04, 0x27, 0x81, 0xe2, 0x80, 0x0a, 0x80, 0x29, 0xdd, 0x22, 0xc0, 0x0c, 0xa0, 0x47, 0xa7, 0x4e, +0x4c, 0x54, 0x40, 0x09, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x17, 0x81, 0xe5, 0xdd, 0x21, 0x80, 0x06, +0xd5, 0x03, 0x44, 0x00, 0x00, 0x12, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa8, 0xbc, 0x97, 0xc0, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x07, 0x81, 0xd5, 0x81, 0x21, 0x81, 0x43, +0x40, 0x81, 0x00, 0x13, 0xc0, 0x27, 0x46, 0xf0, 0x01, 0x4d, 0x02, 0x07, 0x83, 0xa8, 0x84, 0xc0, +0x40, 0x03, 0x00, 0x06, 0x80, 0x26, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, +0x06, 0x70, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x44, +0x04, 0x27, 0x81, 0xe2, 0x80, 0x28, 0x80, 0x09, 0xdd, 0x22, 0xc0, 0x0c, 0xa0, 0x07, 0x44, 0x10, +0x00, 0x12, 0xa6, 0x06, 0x40, 0x70, 0x1c, 0x03, 0x40, 0x00, 0x9c, 0x1b, 0x40, 0x03, 0x1c, 0x1a, +0xd5, 0x39, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x07, 0x81, 0xe3, 0xdd, 0x20, 0x80, 0xc0, 0xc8, 0x03, +0x84, 0x07, 0xd5, 0x30, 0x84, 0x20, 0x44, 0x20, 0x00, 0x20, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0xbc, 0xdd, 0x2f, 0xb7, 0x26, 0x12, 0x83, 0x00, 0x02, 0xaf, 0xf6, 0x80, 0x2a, 0x50, 0x03, +0x00, 0x08, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, +0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x50, 0xa0, 0x41, 0xc9, 0x06, 0x84, 0x21, 0xa9, 0xb7, +0xac, 0x40, 0xa9, 0x81, 0xd5, 0x09, 0xa0, 0x4f, 0xa8, 0x77, 0xa0, 0x41, 0xa9, 0x8f, 0xa9, 0x81, +0xa4, 0x40, 0x9c, 0x49, 0xac, 0x40, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x8a, 0x03, +0x84, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x46, 0x00, 0x01, 0x4d, 0x58, 0x00, 0x07, 0x50, 0xa0, 0x41, 0xc9, 0x11, 0xa4, 0x00, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x5c, 0x00, 0x00, 0x01, 0x44, 0x30, 0x06, 0x59, 0xd5, 0x1f, +0x46, 0xf0, 0x01, 0x44, 0x04, 0x17, 0x81, 0xe5, 0xdd, 0x21, 0xd5, 0x02, 0x80, 0xe0, 0xa1, 0x79, +0xa0, 0xaf, 0x80, 0x05, 0xda, 0xf6, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x17, 0x81, 0xe5, 0x80, 0x02, +0xdd, 0x21, 0x46, 0xf0, 0x01, 0x4d, 0x02, 0x07, 0x83, 0xa8, 0x84, 0x20, 0x5c, 0x00, 0x00, 0x01, +0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x06, 0x63, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0xe6, 0x04, 0xe8, 0x06, 0xe6, 0x02, +0xe8, 0x0c, 0x84, 0xa1, 0xd8, 0x11, 0xd5, 0x06, 0x84, 0xa4, 0xd0, 0x0a, 0x84, 0xa5, 0xd8, 0x0c, +0xd5, 0x09, 0x00, 0x00, 0x80, 0x15, 0xd5, 0x16, 0x00, 0x00, 0x80, 0x20, 0xd5, 0x13, 0xa6, 0x0e, +0xd5, 0x11, 0xa6, 0x09, 0xd5, 0x0f, 0x84, 0x01, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x04, 0x87, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0x88, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, +0x96, 0x01, 0x50, 0x10, 0x7e, 0x00, 0x96, 0x49, 0x5c, 0xf0, 0x80, 0x20, 0xe8, 0x1b, 0x46, 0xf0, +0x00, 0x38, 0x58, 0xf7, 0x81, 0x98, 0xdd, 0x2f, 0xc8, 0x05, 0x44, 0x20, 0x00, 0x7f, 0x84, 0x21, +0xd5, 0x1a, 0x00, 0x00, 0x00, 0xb6, 0x44, 0x20, 0x00, 0x30, 0x42, 0x20, 0x08, 0x24, 0x46, 0x30, +0x01, 0x09, 0x58, 0x31, 0x87, 0xcc, 0x98, 0x93, 0x84, 0x21, 0x20, 0x21, 0x00, 0x23, 0x80, 0x61, +0xd5, 0x1a, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x84, 0x18, 0xdd, 0x2f, 0xc8, 0x06, 0x44, 0x20, +0x00, 0x7f, 0x80, 0x20, 0x80, 0x60, 0xd5, 0x0f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x27, 0x81, 0xdd, +0x00, 0x00, 0x01, 0xae, 0x44, 0x10, 0x00, 0x30, 0x42, 0x20, 0x04, 0x73, 0x84, 0x61, 0x20, 0x21, +0x00, 0x23, 0x84, 0x20, 0x96, 0xd8, 0x40, 0x31, 0xa0, 0x08, 0x96, 0x48, 0x96, 0x00, 0x40, 0x10, +0x8c, 0x04, 0x40, 0x00, 0x40, 0x08, 0x40, 0x00, 0x80, 0x04, 0x40, 0x21, 0x60, 0x08, 0x40, 0x00, +0x08, 0x04, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, +0x97, 0x20, 0xb6, 0x5f, 0xf3, 0x82, 0xf4, 0x83, 0x80, 0xc0, 0x04, 0xa0, 0x00, 0x03, 0x4e, 0x12, +0x00, 0xc9, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x07, 0x82, 0x3b, 0x41, 0xc0, 0x84, 0x00, 0x40, 0xfe, +0x00, 0x06, 0x4e, 0xf2, 0x00, 0xbf, 0x4e, 0x22, 0x00, 0xbd, 0xa0, 0x32, 0xc0, 0x07, 0xa4, 0x32, +0xc0, 0x05, 0x4e, 0xa2, 0x00, 0x04, 0xa6, 0x70, 0xc9, 0x0c, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, +0x83, 0xd5, 0x84, 0x21, 0x84, 0x06, 0x44, 0x20, 0x70, 0xb3, 0x44, 0x30, 0x00, 0x66, 0xd5, 0x0e, +0xa4, 0x71, 0xe2, 0x20, 0xe9, 0x0e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x84, 0x21, +0x84, 0x06, 0x44, 0x20, 0x70, 0xb3, 0x44, 0x30, 0x00, 0x88, 0xdd, 0x24, 0x48, 0x00, 0x00, 0x9a, +0x50, 0x0f, 0x80, 0x14, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0xb4, 0xea, +0xc7, 0x03, 0x4c, 0x75, 0x40, 0x15, 0xf0, 0x05, 0x85, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x81, 0x68, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xd5, 0x84, 0x21, 0x84, 0x06, +0x44, 0x20, 0x70, 0xb3, 0x44, 0x30, 0x00, 0x77, 0xdd, 0x24, 0xd5, 0x7c, 0xb4, 0x27, 0x85, 0x20, +0x40, 0x83, 0xa8, 0x01, 0x46, 0x0a, 0xaa, 0xaa, 0xb6, 0x2a, 0x58, 0x00, 0x0a, 0xab, 0xb7, 0x27, +0x91, 0x03, 0x42, 0x84, 0x00, 0x24, 0xf0, 0x05, 0x40, 0x84, 0x00, 0x13, 0x46, 0xa0, 0x00, 0x02, +0x58, 0xa5, 0x01, 0x68, 0x4b, 0xe0, 0x28, 0x01, 0x44, 0x30, 0x1e, 0x5c, 0x80, 0x29, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x40, 0x04, 0xa0, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x86, 0x88, 0xdd, 0x2f, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, +0xf1, 0x03, 0xf0, 0x81, 0x40, 0x94, 0x84, 0x06, 0x84, 0x3f, 0xac, 0x7b, 0xb4, 0x3f, 0xa8, 0x7d, +0xf1, 0x02, 0x10, 0x93, 0x80, 0x04, 0xa8, 0x7c, 0x15, 0xc3, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x38, +0x04, 0x27, 0x82, 0x42, 0x80, 0x3c, 0xdd, 0x22, 0xa8, 0x3b, 0x50, 0x0f, 0x80, 0x14, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0xa5, 0xf1, 0x80, 0x48, 0x80, 0x06, 0x80, 0x27, +0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x89, 0xcc, 0xdd, 0x2f, 0xa4, 0x31, 0x80, 0x27, 0x9c, 0x01, +0xac, 0x31, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x3d, 0x80, 0x06, 0xdd, 0x22, 0xf0, 0x05, +0x4b, 0xe0, 0x28, 0x01, 0xa6, 0x31, 0xc0, 0x05, 0xa0, 0x32, 0xa5, 0x40, 0x4c, 0x54, 0x40, 0x1b, +0x84, 0x20, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8a, 0x40, 0xdd, 0x2f, 0x80, 0x20, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x43, 0xf0, 0x01, 0xdd, 0x22, 0x80, 0x20, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0x84, 0x01, 0xae, 0x31, 0xd5, 0x02, +0x85, 0x00, 0x80, 0x08, 0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xf4, 0x81, 0x20, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, +0xdd, 0x2f, 0x50, 0x6f, 0x80, 0x04, 0x81, 0x40, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x81, 0x3c, 0xdd, 0x2f, 0xd5, 0x4d, 0x04, 0x24, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x3f, 0x80, 0x09, 0x02, 0x81, 0x00, 0x00, 0xdd, 0x23, 0x04, 0x64, 0x80, 0x03, 0x44, 0x20, +0x00, 0x18, 0x42, 0x64, 0x08, 0x73, 0xa6, 0xf4, 0xc3, 0x20, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x42, 0xa0, 0x72, 0x80, 0x0a, 0xdd, 0x23, 0xa8, 0x33, 0x80, 0x48, 0x02, 0x74, 0x80, 0x01, +0x80, 0x09, 0x80, 0x27, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x89, 0xcc, 0xdd, 0x2f, 0x02, 0x34, +0x80, 0x01, 0x80, 0x27, 0x9c, 0xd9, 0x12, 0x34, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x37, +0x82, 0x3d, 0x80, 0x09, 0xdd, 0x23, 0xd5, 0x03, 0x84, 0x1f, 0xac, 0x33, 0xf0, 0x01, 0x46, 0x70, +0x01, 0x38, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0xa0, 0xb5, 0xc2, 0x09, +0x12, 0x83, 0x84, 0xed, 0xa0, 0xb5, 0xa0, 0x34, 0xdd, 0x22, 0x84, 0x40, 0x12, 0x23, 0x84, 0xed, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x3c, 0xdd, 0x2f, 0x02, 0x24, +0x80, 0x01, 0x80, 0x09, 0x84, 0x20, 0xc2, 0x0e, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8a, 0x40, +0xdd, 0x2f, 0x80, 0x2a, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x89, 0xe4, 0xdd, 0x2f, 0x84, 0x20, +0xc8, 0xa3, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x81, 0x68, 0xdd, 0x2f, 0x02, 0x24, +0x80, 0x01, 0xc2, 0x1a, 0x84, 0x20, 0x80, 0x09, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x8a, 0x40, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x27, 0x82, 0x43, 0x80, 0x20, 0x80, 0x0a, 0xdd, 0x22, +0x80, 0x20, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0x84, 0x21, +0x10, 0x14, 0x80, 0x01, 0xd5, 0x03, 0x10, 0x24, 0x80, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0xf0, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x9c, 0x04, 0x40, 0x90, +0x10, 0x08, 0x93, 0x26, 0x40, 0x94, 0x88, 0x08, 0x50, 0x24, 0x80, 0x01, 0x46, 0x00, 0x01, 0x40, +0x58, 0x00, 0x02, 0xe0, 0x50, 0x80, 0x00, 0x24, 0x04, 0x60, 0x00, 0x09, 0xf2, 0x81, 0x47, 0xc0, +0x00, 0xcd, 0x59, 0xce, 0x0e, 0xa4, 0x46, 0xa0, 0x00, 0xcd, 0x58, 0xa5, 0x0f, 0x1c, 0xd5, 0x32, +0xa0, 0x3b, 0x84, 0xa3, 0xd8, 0x2d, 0xf1, 0x01, 0xa0, 0x3c, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x87, 0xf0, 0xdd, 0x2f, 0x84, 0x21, 0xc0, 0x13, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, +0x82, 0x94, 0xdd, 0x2f, 0x80, 0x26, 0x80, 0x08, 0xdd, 0x3c, 0x80, 0x26, 0x46, 0x00, 0x01, 0x40, +0x58, 0x00, 0x03, 0x00, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0xc8, 0xd5, 0x12, 0xa0, 0x7c, 0x40, 0x90, +0xa4, 0x01, 0x40, 0x14, 0x90, 0x08, 0x92, 0x24, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x03, 0x0c, +0x92, 0x21, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0xd5, 0x0a, 0x81, 0x06, +0xb4, 0xc6, 0x46, 0x50, 0x01, 0x40, 0x58, 0x52, 0x83, 0x04, 0x50, 0x73, 0x7f, 0xec, 0xde, 0xc9, +0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x04, 0x50, 0x00, 0x09, 0x50, 0x20, 0x00, 0x24, +0xda, 0x08, 0x50, 0x00, 0x00, 0x2c, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, +0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x9c, 0x04, 0x40, 0x90, +0x10, 0x08, 0x93, 0x26, 0x40, 0x94, 0x88, 0x08, 0x50, 0x24, 0x80, 0x01, 0x46, 0x00, 0x01, 0x40, +0x58, 0x00, 0x02, 0xe0, 0x50, 0x80, 0x00, 0x28, 0x04, 0x60, 0x00, 0x0a, 0xf2, 0x81, 0x47, 0xc0, +0x00, 0xcd, 0x59, 0xce, 0x0e, 0xa4, 0x46, 0xa0, 0x00, 0xcd, 0x58, 0xa5, 0x0f, 0x1c, 0xd5, 0x2b, +0xa0, 0x3b, 0x84, 0xa1, 0xd8, 0x26, 0xf1, 0x01, 0xa0, 0x3c, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, +0x87, 0xf0, 0xdd, 0x2f, 0x80, 0x26, 0xc0, 0x0c, 0x80, 0x08, 0xdd, 0x3c, 0x80, 0x26, 0x46, 0x00, +0x01, 0x40, 0x58, 0x00, 0x03, 0x00, 0x4b, 0xe0, 0x28, 0x01, 0x80, 0xc8, 0xd5, 0x12, 0xa0, 0x7c, +0x40, 0x90, 0xa4, 0x01, 0x40, 0x14, 0x90, 0x08, 0x92, 0x24, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, +0x03, 0x0d, 0x92, 0x21, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0xd5, 0x0a, +0x81, 0x06, 0xb4, 0xc6, 0x46, 0x50, 0x01, 0x40, 0x58, 0x52, 0x83, 0x08, 0x50, 0x73, 0x7f, 0xec, +0xde, 0xd0, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x04, 0x50, 0x00, 0x0a, 0x50, 0x20, +0x00, 0x28, 0xda, 0x08, 0x50, 0x00, 0x00, 0x2d, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, +0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0x00, +0x01, 0x4a, 0x58, 0x00, 0x06, 0x1c, 0x84, 0x20, 0x44, 0x20, 0x09, 0x60, 0x46, 0xa0, 0x01, 0x40, +0x58, 0xa5, 0x03, 0x08, 0x50, 0x65, 0x7f, 0xd8, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0xbc, +0xdd, 0x2f, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x86, 0x88, 0x80, 0x0a, 0x84, 0x20, 0x46, 0x20, +0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, 0x12, 0x40, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x93, +0x00, 0x24, 0x14, 0xa3, 0x00, 0x0a, 0x80, 0x09, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, +0x01, 0xf4, 0x44, 0x30, 0x12, 0x41, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x83, 0x00, 0x20, 0x14, 0x93, +0x00, 0x09, 0x80, 0x08, 0x84, 0x20, 0x46, 0x20, 0x00, 0xd2, 0x58, 0x21, 0x01, 0xf4, 0x44, 0x30, +0x12, 0x42, 0x4b, 0xe0, 0x1c, 0x01, 0x14, 0x83, 0x00, 0x08, 0x46, 0x70, 0x00, 0xcd, 0x58, 0x73, +0x8f, 0x1c, 0x84, 0xc0, 0x44, 0x80, 0x00, 0x18, 0x42, 0x13, 0x20, 0x24, 0x46, 0x00, 0x01, 0x4a, +0x58, 0x00, 0x06, 0x30, 0x98, 0x48, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x03, 0x00, 0x4b, 0xe0, +0x1c, 0x01, 0x9d, 0xb1, 0x44, 0x50, 0x00, 0x64, 0xde, 0xf0, 0x46, 0x60, 0x01, 0x40, 0x58, 0x63, +0x02, 0xe0, 0x00, 0x03, 0x00, 0x2d, 0xc0, 0x0b, 0x50, 0x03, 0x00, 0x2d, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x84, 0x00, 0x10, 0x03, 0x00, 0x2d, 0x46, 0x60, 0x01, 0x40, +0x58, 0x63, 0x02, 0xe0, 0x00, 0x03, 0x00, 0x2c, 0xc0, 0x0b, 0x50, 0x03, 0x00, 0x2c, 0x46, 0xf0, +0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x84, 0x00, 0x10, 0x03, 0x00, 0x2c, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x41, 0x58, 0x63, +0x04, 0xbc, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x84, 0x20, 0x44, 0x20, 0x00, 0x30, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x41, 0x58, 0x00, 0x08, 0xc4, 0x84, 0x20, 0x44, 0x20, 0x14, 0x50, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x3c, 0x58, 0x00, 0x01, 0x40, 0x84, 0x20, 0x44, 0x20, 0x04, 0xb0, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x38, 0x58, 0x00, 0x0d, 0xa0, 0x84, 0x20, 0x44, 0x20, 0x0f, 0xa0, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x03, 0x10, 0x84, 0x20, 0x44, 0x20, 0x0f, 0xa0, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x3c, 0x58, 0x00, 0x05, 0xf0, 0x84, 0x20, 0x44, 0x20, 0x0e, 0x10, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x42, 0x58, 0x00, 0x0d, 0x14, 0x84, 0x20, 0x44, 0x20, 0x19, 0x00, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x4b, 0x58, 0x00, 0x03, 0x78, 0x84, 0x20, 0x44, 0x20, 0x19, 0x00, +0xdd, 0x26, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x44, 0x10, 0x00, 0x64, 0x84, 0x40, +0xae, 0x47, 0xae, 0x80, 0xae, 0x41, 0xae, 0x42, 0xae, 0x43, 0xae, 0x44, 0xae, 0x45, 0xae, 0x46, +0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x87, 0x0c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x8c, 0x74, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, +0x84, 0x20, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xe0, 0x10, 0x1f, 0x80, 0x07, 0x46, 0xf0, +0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa4, +0xa0, 0x44, 0xc9, 0x03, 0xa0, 0x81, 0xa8, 0x84, 0xa0, 0x45, 0xc9, 0x03, 0xa0, 0x83, 0xa8, 0x85, +0x46, 0xf0, 0x01, 0x49, 0x04, 0x17, 0x83, 0xae, 0xc1, 0x06, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, +0x83, 0xad, 0xc8, 0x07, 0x44, 0x10, 0x00, 0x1f, 0x46, 0xf0, 0x01, 0x49, 0x14, 0x17, 0x83, 0xb7, +0x46, 0xf0, 0x01, 0x49, 0x04, 0x27, 0x83, 0xb7, 0xc2, 0x04, 0x84, 0xe4, 0x84, 0xc0, 0xd5, 0x10, +0x46, 0xf0, 0x01, 0x49, 0x00, 0x07, 0x8e, 0xf4, 0x50, 0x1f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x8f, 0x3c, 0xdd, 0x2f, 0x9c, 0x04, 0x00, 0x6f, 0x80, 0x07, 0x97, 0xc0, 0x84, 0x01, +0x84, 0x20, 0x9c, 0xbd, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0xc8, 0x04, +0x84, 0x07, 0x48, 0x00, 0x00, 0x85, 0xb4, 0x20, 0x84, 0x0e, 0xae, 0x08, 0x9d, 0xfb, 0x84, 0x01, +0xae, 0x0a, 0xaf, 0xc9, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, 0x0e, 0xa4, 0x00, 0x20, 0x00, 0x44, +0xae, 0x8b, 0x02, 0x20, 0x00, 0x22, 0x92, 0x48, 0xae, 0x8c, 0x00, 0x20, 0x00, 0x38, 0xae, 0x8d, +0x00, 0x20, 0x00, 0x46, 0xae, 0x8e, 0x00, 0x20, 0x00, 0x50, 0x10, 0x60, 0x80, 0x08, 0xae, 0x8f, +0x84, 0x49, 0x12, 0x20, 0x00, 0x24, 0x14, 0x10, 0x00, 0x10, 0xc6, 0x59, 0x04, 0x20, 0x00, 0x0e, +0xca, 0x56, 0x00, 0x10, 0x00, 0x50, 0x10, 0x2f, 0x80, 0x07, 0x84, 0xa1, 0xd9, 0x22, 0xa1, 0x84, +0x46, 0x70, 0x00, 0xcf, 0x58, 0x73, 0x80, 0x94, 0xd5, 0x0a, 0xc6, 0x03, 0x4b, 0xe0, 0x1c, 0x01, +0x00, 0x0f, 0x80, 0x07, 0xb4, 0xc6, 0x9c, 0x01, 0x10, 0x0f, 0x80, 0x07, 0x00, 0x2f, 0x80, 0x07, +0x9c, 0x34, 0x46, 0x10, 0x01, 0x49, 0x58, 0x10, 0x8e, 0xdc, 0xe6, 0x54, 0xe8, 0x05, 0x50, 0x20, +0xff, 0xcc, 0x4c, 0x61, 0x7f, 0xec, 0x46, 0xf0, 0x01, 0x49, 0x14, 0x67, 0x83, 0xad, 0xd5, 0x2f, +0x84, 0xa2, 0xd9, 0x2d, 0xa1, 0x85, 0x46, 0x80, 0x00, 0xcf, 0x58, 0x84, 0x00, 0x94, 0x46, 0x70, +0x00, 0xcf, 0x58, 0x73, 0x80, 0x10, 0xd5, 0x12, 0xc6, 0x0b, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x03, +0x00, 0x14, 0x46, 0x10, 0x01, 0x49, 0x58, 0x10, 0x8e, 0xdc, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x0f, +0x80, 0x07, 0xb4, 0xc6, 0x9c, 0x01, 0x10, 0x0f, 0x80, 0x07, 0x00, 0x2f, 0x80, 0x07, 0x9c, 0x34, +0x46, 0x10, 0x01, 0x49, 0x58, 0x10, 0x8e, 0xdc, 0xe6, 0x43, 0xe8, 0x05, 0x50, 0x20, 0xff, 0xd4, +0x4c, 0x61, 0x7f, 0xe4, 0x46, 0xf0, 0x01, 0x49, 0x14, 0x67, 0x83, 0xae, 0x84, 0x01, 0x84, 0x20, +0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x87, 0x80, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x08, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x01, 0x49, 0x58, 0x00, +0x0e, 0xe0, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x86, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x38, +0x58, 0xf7, 0x85, 0xc4, 0xdd, 0x2f, 0xc0, 0x0c, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xc0, +0xdd, 0x20, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0x98, 0xdd, 0x2f, 0xd5, 0x13, 0x80, 0x20, +0x84, 0x01, 0x46, 0x20, 0x00, 0xd0, 0x58, 0x21, 0x0a, 0x78, 0x80, 0x61, 0x80, 0x80, 0x80, 0xa1, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x49, 0x10, 0x07, +0x8e, 0xe0, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xc0, +0x84, 0x00, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x02, 0xa3, +0x00, 0x07, 0x84, 0x2a, 0x40, 0xa5, 0x10, 0x08, 0x40, 0xa5, 0x04, 0x36, 0x9c, 0x04, 0x40, 0x80, +0x10, 0x08, 0x93, 0x06, 0x40, 0x84, 0x08, 0x08, 0x80, 0x28, 0x80, 0x08, 0x80, 0x4a, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, 0xa8, 0x3c, 0x46, 0x10, 0x01, 0x40, 0x58, 0x10, +0x82, 0xe0, 0x50, 0x00, 0x80, 0x24, 0x04, 0x30, 0x80, 0x09, 0xd5, 0x0c, 0x4c, 0x70, 0xc0, 0x09, +0x80, 0x23, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0xd5, 0x0a, 0x80, 0x03, +0xb4, 0x63, 0x46, 0x50, 0x01, 0x40, 0x58, 0x52, 0x83, 0x04, 0x50, 0x11, 0xff, 0xec, 0xdb, 0xef, +0x46, 0x90, 0x01, 0x40, 0x58, 0x94, 0x82, 0xe0, 0x04, 0x64, 0x80, 0x09, 0x50, 0x04, 0x80, 0x24, +0x4c, 0x60, 0x40, 0x0e, 0x50, 0x13, 0x80, 0x14, 0x80, 0x06, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, +0x8f, 0x1c, 0xdd, 0x2f, 0x50, 0x03, 0x00, 0x08, 0x80, 0x2a, 0xd5, 0x29, 0x50, 0x94, 0x80, 0x24, +0x46, 0xa0, 0x00, 0x34, 0x58, 0xa5, 0x07, 0xf0, 0x04, 0x13, 0x7f, 0xff, 0xa0, 0x3c, 0x9c, 0x49, +0x4b, 0xe0, 0x28, 0x01, 0xc0, 0x03, 0x80, 0x09, 0xd5, 0x21, 0xb4, 0x06, 0x46, 0x50, 0x01, 0x40, +0x58, 0x52, 0x83, 0x04, 0x81, 0x26, 0xd0, 0x19, 0x80, 0xc0, 0xd5, 0xef, 0x46, 0x00, 0x01, 0x40, +0x58, 0x00, 0x02, 0xe0, 0x04, 0x10, 0x00, 0x09, 0x04, 0x10, 0xff, 0xff, 0x40, 0x80, 0xa0, 0x01, +0x40, 0x14, 0x10, 0x08, 0x92, 0x24, 0x50, 0x00, 0x00, 0x2c, 0x92, 0x21, 0x46, 0xf0, 0x00, 0x26, +0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0xd5, 0x0a, 0x80, 0x06, 0x50, 0x13, 0x80, 0x14, 0x46, 0xf0, +0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0xd5, 0xe2, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xe0, 0x80, 0xc1, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x36, +0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x00, 0x13, 0x00, 0x09, 0x00, 0x23, 0x80, 0x0c, 0xe2, 0x41, +0x4e, 0xf2, 0x00, 0x99, 0x02, 0xa3, 0x80, 0x07, 0x84, 0x2a, 0x40, 0xa5, 0x10, 0x08, 0x40, 0xa5, +0x04, 0x36, 0x50, 0x80, 0x00, 0x04, 0x40, 0x84, 0x10, 0x08, 0x93, 0x06, 0x40, 0x84, 0x08, 0x08, +0x80, 0x28, 0x80, 0x08, 0x80, 0x4a, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, +0xa8, 0x34, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x50, 0x30, 0x00, 0x28, 0x04, 0x10, +0x00, 0x0a, 0xd5, 0x0c, 0x4c, 0x60, 0x40, 0x09, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, +0x8e, 0xa4, 0xdd, 0x2f, 0xd5, 0x0b, 0x80, 0x61, 0xb4, 0x21, 0x46, 0x20, 0x01, 0x40, 0x58, 0x21, +0x03, 0x08, 0x50, 0x00, 0xff, 0xec, 0x4c, 0x11, 0x7f, 0xef, 0x46, 0x90, 0x01, 0x40, 0x58, 0x94, +0x82, 0xe0, 0x04, 0x74, 0x80, 0x09, 0x50, 0x04, 0x80, 0x24, 0x4c, 0x70, 0x40, 0x1b, 0x80, 0x07, +0x50, 0x13, 0x00, 0x14, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, 0xdd, 0x2f, 0x84, 0x20, +0x80, 0x0a, 0x46, 0x20, 0x00, 0xd0, 0x58, 0x21, 0x05, 0x5c, 0x80, 0x61, 0x84, 0x81, 0x80, 0xa1, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x10, 0x04, 0x80, 0x2c, 0xd5, 0x2f, +0x50, 0x94, 0x80, 0x24, 0x46, 0xa0, 0x00, 0x34, 0x58, 0xa5, 0x07, 0xf0, 0x04, 0x13, 0xff, 0xff, +0xa0, 0x34, 0x9c, 0x49, 0x4b, 0xe0, 0x28, 0x01, 0xc0, 0x03, 0x80, 0x09, 0xd5, 0x2b, 0xb4, 0x07, +0x46, 0x10, 0x01, 0x40, 0x58, 0x10, 0x83, 0x04, 0x81, 0x27, 0x4c, 0x00, 0x80, 0x23, 0x80, 0xe0, +0xd5, 0xee, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x04, 0x10, 0x00, 0x09, 0x04, 0x10, +0xff, 0xff, 0x40, 0x80, 0xa0, 0x01, 0x40, 0x14, 0x10, 0x08, 0x92, 0x24, 0x50, 0x00, 0x00, 0x2c, +0x92, 0x21, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0x80, 0x06, 0x84, 0x20, +0x46, 0xf0, 0x00, 0xcb, 0x58, 0xf7, 0x82, 0x94, 0xdd, 0x2f, 0x84, 0x03, 0xa8, 0x33, 0xd5, 0x0a, +0x80, 0x07, 0x50, 0x13, 0x00, 0x14, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, +0xd5, 0xd9, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xc0, +0x84, 0x00, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x88, 0x8c, 0xdd, 0x2f, 0x02, 0xa3, +0x00, 0x05, 0x84, 0x2a, 0x40, 0xa5, 0x10, 0x08, 0x40, 0xa5, 0x04, 0x36, 0x9c, 0x04, 0x40, 0x80, +0x10, 0x08, 0x93, 0x06, 0x40, 0x84, 0x08, 0x08, 0x80, 0x08, 0x80, 0x28, 0x46, 0x90, 0x01, 0x40, +0x58, 0x94, 0x82, 0xe0, 0x80, 0x4a, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, +0xa8, 0x3c, 0x46, 0x20, 0x01, 0x40, 0x58, 0x21, 0x03, 0x08, 0x04, 0x64, 0x80, 0x0a, 0x4c, 0x61, +0x40, 0x1b, 0x80, 0x06, 0x50, 0x13, 0x80, 0x14, 0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8f, 0x1c, +0xdd, 0x2f, 0x84, 0x20, 0x80, 0x0a, 0x46, 0x20, 0x00, 0xd0, 0x58, 0x21, 0x06, 0x3c, 0x80, 0x61, +0x84, 0x81, 0x80, 0xa1, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0xb0, 0xdd, 0x2f, 0x10, 0x04, +0x80, 0x2d, 0xd5, 0x2f, 0x50, 0x94, 0x80, 0x28, 0x46, 0xa0, 0x00, 0x34, 0x58, 0xa5, 0x07, 0xf0, +0x04, 0x13, 0x7f, 0xff, 0xa0, 0x3c, 0x9c, 0x49, 0x4b, 0xe0, 0x28, 0x01, 0xc0, 0x03, 0x80, 0x09, +0xd5, 0x26, 0xb4, 0x06, 0x46, 0x10, 0x01, 0x40, 0x58, 0x10, 0x83, 0x08, 0x81, 0x26, 0x4c, 0x00, +0x80, 0x1e, 0x80, 0xc0, 0xd5, 0xee, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x02, 0xe0, 0x04, 0x10, +0x00, 0x0a, 0x04, 0x10, 0xff, 0xff, 0x40, 0x80, 0xa0, 0x01, 0x40, 0x14, 0x10, 0x08, 0x92, 0x24, +0x50, 0x00, 0x00, 0x2d, 0x92, 0x21, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, +0x84, 0x01, 0xa8, 0x3b, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x80, 0x06, 0x50, 0x13, 0x80, 0x14, +0x46, 0xf0, 0x00, 0xcd, 0x58, 0xf7, 0x8e, 0xe0, 0xdd, 0x2f, 0xd5, 0xde, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x00, 0x40, 0x80, 0x09, 0xa0, 0xcb, 0x9d, 0x21, 0x84, 0xa1, 0x10, 0x40, +0x80, 0x09, 0xd3, 0x0b, 0xc3, 0x04, 0x84, 0xa3, 0xdb, 0x13, 0xd5, 0x0d, 0x46, 0xf0, 0x00, 0xd0, +0x58, 0xf7, 0x8d, 0x4c, 0xdd, 0x2f, 0xd5, 0x0c, 0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x8b, 0xf4, +0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x8a, 0xdc, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xe2, 0x54, 0x80, 0x00, 0xff, +0x81, 0x41, 0x46, 0x90, 0x00, 0xc9, 0x58, 0x94, 0x89, 0x68, 0x84, 0x00, 0x46, 0x10, 0x01, 0x40, +0x58, 0x10, 0x83, 0x08, 0x80, 0x48, 0x80, 0x67, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0xc0, 0xc8, 0x2b, +0x46, 0x10, 0x01, 0x40, 0x58, 0x10, 0x83, 0x04, 0x80, 0x48, 0x80, 0x67, 0x4b, 0xe0, 0x24, 0x01, +0x80, 0xc0, 0xc8, 0x21, 0x46, 0x00, 0x01, 0x40, 0x58, 0x00, 0x03, 0x00, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x85, 0x70, 0xdd, 0x2f, 0xc0, 0x17, 0x50, 0x60, 0x7f, 0xec, 0x84, 0x40, 0x84, 0x20, +0xa8, 0xb3, 0xa8, 0xb4, 0x10, 0x83, 0x00, 0x01, 0x10, 0x13, 0x00, 0x09, 0x8e, 0x12, 0xa6, 0x7d, +0x84, 0x46, 0x10, 0x13, 0x00, 0x08, 0x50, 0x13, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x98, 0xdd, 0x2f, 0x80, 0x0a, 0x80, 0x26, 0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x8e, 0x50, +0xdd, 0x2f, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x00, 0x30, 0x80, 0x08, 0x84, 0x81, 0x96, 0x00, 0x4c, 0x32, 0x00, 0x0c, 0xc3, 0x04, 0x84, 0xa2, +0xdb, 0x13, 0xd5, 0x0d, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xd5, 0x0c, +0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x8e, 0x98, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0xc9, +0x58, 0xf7, 0x89, 0x08, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0xd4, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x83, 0x66, 0x44, 0x20, 0x00, 0xff, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x85, 0x3c, 0x4c, 0x01, 0x00, 0x09, 0x46, 0x00, 0x01, 0x38, +0x04, 0x20, 0x02, 0x3a, 0x9c, 0x91, 0x14, 0x20, 0x02, 0x3a, 0x84, 0xa1, 0xd9, 0x30, 0x46, 0xf0, +0x01, 0x0f, 0x00, 0x07, 0x83, 0x04, 0xc0, 0x04, 0x84, 0x22, 0x4c, 0x00, 0xc0, 0x29, 0x46, 0x60, +0x01, 0x0f, 0x58, 0x63, 0x03, 0x00, 0x00, 0x03, 0x00, 0x36, 0x44, 0x50, 0x00, 0xff, 0x4c, 0x02, +0x80, 0xcb, 0x00, 0x03, 0x00, 0x34, 0x84, 0xa4, 0xd8, 0x04, 0x84, 0x01, 0xf0, 0x81, 0xd5, 0x19, +0x50, 0x13, 0x00, 0x30, 0x44, 0x20, 0x00, 0x30, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, +0x84, 0x80, 0xdd, 0x2f, 0x84, 0x01, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8a, 0xe8, 0xdd, 0x2f, +0xa6, 0x34, 0x4e, 0x02, 0x00, 0xb1, 0x84, 0xa2, 0x4c, 0x02, 0x80, 0xae, 0x84, 0x40, 0xf2, 0x81, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x83, 0x06, 0x44, 0x50, 0x00, 0xff, 0x4c, 0x02, 0x80, 0x9f, +0x85, 0x00, 0x46, 0x70, 0x01, 0x41, 0x58, 0x73, 0x88, 0xc4, 0xb7, 0x1f, 0x50, 0x93, 0x80, 0x08, +0x81, 0x48, 0x50, 0x6f, 0x80, 0x0c, 0x47, 0xc0, 0x00, 0xc9, 0x59, 0xce, 0x07, 0x60, 0xa6, 0xb8, +0x84, 0xa1, 0x4c, 0x22, 0xc0, 0x83, 0x44, 0x20, 0x00, 0x1c, 0x80, 0x06, 0x84, 0x20, 0x46, 0xf0, +0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0f, 0x20, 0x37, 0x83, 0x07, +0x20, 0x23, 0x80, 0x07, 0xe0, 0x62, 0xe9, 0x71, 0x20, 0x24, 0x80, 0x05, 0xe0, 0x62, 0xe8, 0x05, +0x00, 0x24, 0x80, 0x00, 0x84, 0xa1, 0xd2, 0x69, 0x00, 0x24, 0x80, 0x00, 0xca, 0x05, 0xb4, 0x5f, +0x84, 0xa1, 0xda, 0x07, 0xd5, 0x62, 0x84, 0xa2, 0xda, 0x04, 0x84, 0xa1, 0x4c, 0xa2, 0x80, 0x5e, +0x80, 0x46, 0x80, 0x07, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x83, 0x00, 0xdd, 0x3c, 0xf2, 0x01, +0x84, 0xa1, 0xda, 0x08, 0x80, 0x07, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x83, 0x30, 0x80, 0x46, +0xdd, 0x3c, 0x80, 0x26, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x83, 0x90, 0xdd, 0x2f, +0x80, 0x20, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x83, 0xb0, 0xdd, 0x2f, 0xc0, 0x3d, +0x00, 0x24, 0x80, 0x00, 0xca, 0x04, 0x84, 0x01, 0xb6, 0x1f, 0xd5, 0x06, 0x56, 0x21, 0x00, 0x02, +0x84, 0x61, 0x40, 0xa1, 0x88, 0x1a, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, 0x89, 0xf7, 0xca, 0x0d, +0x80, 0x08, 0x80, 0x27, 0x46, 0x20, 0x01, 0x0f, 0x58, 0x21, 0x03, 0x00, 0x46, 0xf0, 0x00, 0xd0, +0x58, 0xf7, 0x8f, 0x2c, 0xdd, 0x2f, 0xd5, 0x21, 0x46, 0x30, 0x01, 0x38, 0x00, 0x21, 0x89, 0xf8, +0xca, 0x1c, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x27, 0x89, 0xfb, 0x84, 0xa4, 0xda, 0x16, 0x84, 0x41, +0x10, 0x21, 0x89, 0xf8, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x81, 0x20, 0xb4, 0x43, 0x42, 0x21, +0x50, 0x09, 0xb6, 0x43, 0x84, 0x05, 0xb4, 0x43, 0x42, 0x21, 0x50, 0x08, 0xb6, 0x43, 0x46, 0xf0, +0x00, 0xcb, 0x58, 0xf7, 0x8f, 0x00, 0xdd, 0x2f, 0x8d, 0x01, 0x44, 0x20, 0x00, 0x64, 0x50, 0x73, +0x80, 0x34, 0x50, 0x94, 0x80, 0x34, 0x4c, 0x81, 0x7f, 0x74, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, +0x85, 0x58, 0xdd, 0x2f, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x07, 0x81, 0x7a, 0x54, 0x00, 0x00, 0x30, +0xc8, 0x08, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0x58, 0xdd, 0x2f, 0x84, 0x02, 0xd5, 0x14, +0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x85, 0xc4, 0xdd, 0x2f, 0xc8, 0x03, 0x84, 0x01, 0xd5, 0x0c, +0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x8f, 0x70, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, +0x85, 0x98, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x57, 0x82, 0xe0, 0xa6, 0x30, +0xd0, 0x1c, 0x84, 0xa1, 0x46, 0x70, 0x00, 0x02, 0x58, 0x73, 0x8a, 0xc8, 0xd8, 0x09, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xbe, 0xdd, 0x20, 0xd5, 0x09, 0x46, 0xf0, +0x00, 0xd0, 0x58, 0xf7, 0x87, 0x0c, 0xdd, 0x2f, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xa7, 0xb0, +0x46, 0xf0, 0x01, 0x40, 0x10, 0x67, 0x82, 0xe0, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xe1, 0x08, 0x30, 0x80, 0x01, 0x97, 0x00, +0x46, 0x60, 0x01, 0x44, 0x58, 0x63, 0x07, 0x40, 0x84, 0x03, 0x96, 0x90, 0xaf, 0x30, 0xae, 0xf2, +0x4c, 0x40, 0x00, 0x33, 0xe6, 0x84, 0xe8, 0x06, 0x84, 0xa1, 0xd4, 0x18, 0xe6, 0x82, 0xe8, 0x21, +0xd5, 0x0c, 0x84, 0x05, 0x4c, 0x40, 0x00, 0x3f, 0xe2, 0x80, 0xe9, 0x31, 0x84, 0xa6, 0xd4, 0x45, +0x84, 0xa7, 0xd4, 0x4e, 0x8c, 0x0d, 0xd5, 0x57, 0x80, 0x07, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, +0x81, 0xb0, 0xdd, 0x2f, 0xa7, 0xf8, 0xaf, 0xf1, 0xd5, 0x4e, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xce, +0x58, 0xf7, 0x84, 0xf8, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe1, 0xd5, 0x42, +0x80, 0x03, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x8b, 0xc0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, +0x00, 0x17, 0x82, 0xe2, 0xd5, 0x37, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x8a, 0xc8, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe3, 0xd5, 0x2c, 0x80, 0x03, 0x46, 0xf0, +0x00, 0xce, 0x58, 0xf7, 0x89, 0xac, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe4, +0xd5, 0x21, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x88, 0x90, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x40, 0x00, 0x17, 0x82, 0xe5, 0xd5, 0x16, 0x80, 0x03, 0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, +0x87, 0x90, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, 0x82, 0xe6, 0xd5, 0x0b, 0x80, 0x03, +0x46, 0xf0, 0x00, 0xce, 0x58, 0xf7, 0x86, 0x74, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x40, 0x00, 0x17, +0x82, 0xe7, 0xae, 0x73, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x97, 0x80, 0xe6, 0xc2, 0xe9, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x2d, +0x46, 0x70, 0x01, 0x49, 0x58, 0x73, 0x8e, 0xa4, 0x00, 0x53, 0x80, 0x20, 0xde, 0x02, 0xd5, 0x24, +0xc6, 0x03, 0x84, 0x01, 0xd5, 0x13, 0x00, 0x03, 0x80, 0x22, 0x84, 0xa1, 0xd8, 0x0e, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x83, 0xe4, 0x80, 0x26, 0x80, 0x06, 0xdd, 0x22, 0x10, 0x63, 0x80, 0x22, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x67, 0x83, 0xc4, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8a, 0xc8, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x07, 0x83, 0xbe, 0xdd, 0x20, 0x46, 0xf0, +0x01, 0x49, 0x10, 0x67, 0x8e, 0xc4, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xbc, 0x46, 0x50, 0x01, 0x44, 0x58, 0x52, 0x87, 0x44, +0x3a, 0x02, 0x8c, 0x04, 0x50, 0x6f, 0x80, 0x04, 0x80, 0x86, 0x50, 0x9f, 0x80, 0x06, 0x3a, 0x02, +0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x00, 0x3a, 0x02, +0x0c, 0x20, 0x80, 0x29, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x27, 0x80, 0xe1, 0xa6, 0x31, 0xdd, 0x22, +0xc0, 0x66, 0x50, 0x7f, 0x80, 0x34, 0x46, 0xf0, 0x01, 0x4d, 0x04, 0x87, 0x80, 0xdf, 0x84, 0x4c, +0x80, 0x07, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0x80, 0x07, +0x80, 0x29, 0xdd, 0x28, 0x00, 0x83, 0x80, 0x08, 0x84, 0xa1, 0xa1, 0xf9, 0x4c, 0x82, 0xc0, 0x3b, +0x04, 0x03, 0x00, 0x0b, 0xa6, 0x7e, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, 0x84, 0x98, 0x10, 0x10, +0x00, 0xbf, 0x84, 0x46, 0x04, 0x03, 0x00, 0x0b, 0x80, 0x27, 0x50, 0x00, 0x00, 0xc9, 0x4b, 0xe0, +0x24, 0x01, 0x04, 0x03, 0x00, 0x0b, 0x80, 0x27, 0x8c, 0x1c, 0x84, 0x46, 0x4b, 0xe0, 0x24, 0x01, +0x46, 0xf0, 0x01, 0x0d, 0x00, 0x07, 0x86, 0x08, 0x54, 0x00, 0x00, 0x03, 0xc8, 0x1b, 0xa6, 0x3e, +0x80, 0x27, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x8a, 0x08, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, +0x00, 0x57, 0x85, 0xf4, 0xd8, 0x0f, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x87, 0x8a, 0x06, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x81, 0xd4, 0x04, 0x03, 0x00, 0x0b, 0x44, 0x10, 0x00, 0x1f, 0xdd, 0x22, +0xd5, 0x16, 0x50, 0x6f, 0x80, 0x04, 0x04, 0x03, 0x00, 0x0b, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x0d, +0x58, 0xf7, 0x84, 0xac, 0xdd, 0x2f, 0x04, 0x03, 0x00, 0x0b, 0x84, 0xa1, 0x00, 0x00, 0x00, 0xb5, +0xd8, 0x06, 0x46, 0xf0, 0x00, 0xc5, 0x58, 0xf7, 0x8e, 0xd0, 0xdd, 0x2f, 0xec, 0x44, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0xc0, 0x5d, +0xa6, 0x00, 0x84, 0xa1, 0xd0, 0x5a, 0x46, 0x70, 0x01, 0x0f, 0x04, 0x23, 0x81, 0x00, 0xca, 0x11, +0xa6, 0x36, 0xe6, 0x02, 0xe8, 0x0e, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x82, 0xac, 0xdd, 0x2f, +0x14, 0x03, 0x81, 0x00, 0xc8, 0x03, 0x84, 0x07, 0xd5, 0x4a, 0x84, 0x21, 0x10, 0x10, 0x00, 0xb5, +0x46, 0xf0, 0x01, 0x38, 0x04, 0x17, 0x82, 0x39, 0xc9, 0x21, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, +0x89, 0xf3, 0x84, 0xa1, 0xd8, 0x03, 0x84, 0x0c, 0xd5, 0x3a, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, +0x04, 0x00, 0xae, 0x44, 0x00, 0x23, 0x00, 0x15, 0xae, 0x85, 0xa4, 0xb1, 0xac, 0x84, 0xa6, 0xb6, +0xae, 0x86, 0xa6, 0xb7, 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x00, 0x11, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x83, 0xe9, 0x84, 0x01, 0xdd, 0x21, 0xc8, 0x22, 0x46, 0x00, 0x01, 0x38, 0x04, 0x10, +0x02, 0x39, 0x14, 0x13, 0x00, 0x17, 0x14, 0x60, 0x02, 0x39, 0x84, 0x01, 0xae, 0x30, 0x84, 0x22, +0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x89, 0xf3, 0xa6, 0xb6, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x37, +0x81, 0x7a, 0x84, 0x21, 0x40, 0x10, 0x88, 0x0c, 0x40, 0x10, 0x8c, 0x04, 0x46, 0xf0, 0x01, 0x0f, +0x12, 0x17, 0x81, 0x7a, 0x84, 0x00, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x1f, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x84, 0x63, 0x96, 0x00, +0x96, 0x90, 0x80, 0xe1, 0x4c, 0x01, 0x80, 0xa6, 0xe6, 0x04, 0xe8, 0x08, 0x84, 0xa1, 0xd0, 0x0e, +0x84, 0xa2, 0x4c, 0x02, 0xc0, 0xe3, 0x48, 0x00, 0x00, 0x8b, 0x84, 0xa4, 0x4c, 0x02, 0x80, 0xab, +0x84, 0xa5, 0x4c, 0x02, 0xc0, 0xdb, 0x48, 0x00, 0x00, 0xb8, 0xa7, 0x7a, 0xa6, 0x78, 0xa7, 0x39, +0xa6, 0xfb, 0x98, 0x69, 0x40, 0x42, 0x20, 0x08, 0x98, 0x4c, 0x40, 0x31, 0xa0, 0x08, 0x44, 0x60, +0x00, 0x60, 0x42, 0x61, 0x18, 0x24, 0x98, 0x4b, 0x90, 0x21, 0x46, 0x20, 0x01, 0x46, 0x58, 0x21, +0x0b, 0x04, 0x99, 0xb2, 0x96, 0x89, 0x9c, 0x7c, 0xa7, 0x48, 0xac, 0xb2, 0xac, 0xb1, 0x40, 0x52, +0x80, 0x03, 0xa6, 0x48, 0x84, 0x80, 0xae, 0x76, 0x44, 0x30, 0x00, 0x12, 0x40, 0x82, 0x14, 0x1b, +0x40, 0x81, 0x94, 0x1a, 0xa6, 0xfd, 0x46, 0x90, 0x00, 0x41, 0x58, 0x94, 0x84, 0x98, 0xae, 0xf7, +0x9c, 0x7e, 0x84, 0x46, 0x50, 0x03, 0x00, 0x08, 0x4b, 0xe0, 0x24, 0x01, 0x00, 0x33, 0x80, 0x0c, +0x50, 0x13, 0x80, 0x0d, 0x10, 0x33, 0x00, 0x0e, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0f, 0x4b, 0xe0, +0x24, 0x01, 0x00, 0x03, 0x80, 0x13, 0x10, 0x03, 0x00, 0x15, 0x00, 0x13, 0x80, 0x14, 0x10, 0x13, +0x00, 0x16, 0x00, 0x23, 0x80, 0x15, 0x10, 0x23, 0x00, 0x17, 0x00, 0x13, 0x80, 0x16, 0x50, 0x00, +0xff, 0xf8, 0x96, 0x00, 0xe6, 0x0d, 0xe8, 0x03, 0x84, 0x07, 0xd5, 0x06, 0x9e, 0x0c, 0x96, 0x00, +0xe6, 0x04, 0xe8, 0x06, 0x84, 0x06, 0x10, 0x03, 0x00, 0x18, 0x48, 0x00, 0x00, 0x81, 0xe6, 0x24, +0xe8, 0x03, 0x84, 0x05, 0xd5, 0xf9, 0x9c, 0x0c, 0x96, 0x00, 0xe6, 0x04, 0xe8, 0x03, 0x84, 0x04, +0xd5, 0xf3, 0x50, 0x00, 0x80, 0x08, 0x96, 0x00, 0xe6, 0x04, 0xe8, 0x03, 0x84, 0x03, 0xd5, 0xec, +0x50, 0x00, 0x80, 0x0c, 0x96, 0x00, 0xe6, 0x04, 0xe8, 0x03, 0x84, 0x02, 0xd5, 0xe5, 0x50, 0x00, +0x80, 0x10, 0x96, 0x00, 0xe6, 0x04, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0xde, 0x50, 0x10, 0x80, 0x46, +0x96, 0x48, 0x5c, 0xf0, 0x80, 0x36, 0xe8, 0x59, 0x84, 0x00, 0xd5, 0xd6, 0x44, 0x60, 0x00, 0x60, +0x42, 0x21, 0x18, 0x24, 0x80, 0x27, 0x08, 0x30, 0x80, 0x01, 0x46, 0x00, 0x01, 0x46, 0x58, 0x00, +0x0b, 0x04, 0x99, 0x90, 0x50, 0x03, 0x00, 0x1a, 0x80, 0x43, 0x10, 0x33, 0x00, 0x19, 0xd5, 0x1d, +0x44, 0x60, 0x00, 0x60, 0x42, 0x21, 0x18, 0x24, 0x08, 0x30, 0x80, 0x01, 0x46, 0x00, 0x01, 0x46, +0x58, 0x00, 0x0b, 0x04, 0x99, 0x90, 0x50, 0x03, 0x00, 0x3a, 0x80, 0x43, 0x10, 0x33, 0x00, 0x39, +0xd5, 0x0c, 0x44, 0x00, 0x00, 0x60, 0x42, 0x01, 0x00, 0x24, 0x46, 0x30, 0x01, 0x46, 0x58, 0x31, +0x8b, 0x04, 0x98, 0x03, 0x84, 0x46, 0x8c, 0x08, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, +0xdd, 0x2f, 0x85, 0x00, 0xd5, 0x24, 0xa6, 0x38, 0x84, 0xa1, 0xd8, 0x0f, 0x95, 0x9d, 0x42, 0x21, +0x18, 0x24, 0x46, 0x30, 0x01, 0x46, 0x58, 0x31, 0x8b, 0x04, 0x98, 0x13, 0x46, 0xf0, 0x00, 0xd1, +0x58, 0xf7, 0x84, 0x88, 0xdd, 0x2f, 0xd5, 0x0f, 0x44, 0x60, 0x00, 0x60, 0x42, 0x21, 0x18, 0x24, +0x46, 0x10, 0x01, 0x46, 0x58, 0x10, 0x8b, 0x04, 0x98, 0x11, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, +0x8b, 0xc0, 0xdd, 0x2f, 0x81, 0x00, 0xd5, 0x03, 0x44, 0x80, 0x00, 0x12, 0x80, 0x08, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x97, 0xc0, 0x80, 0x07, 0x81, 0x41, +0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x81, 0x64, 0xdd, 0x2f, 0x81, 0x20, 0x46, 0xf0, 0x01, 0x38, +0x00, 0x17, 0x89, 0xf2, 0x84, 0xc0, 0x46, 0x00, 0x01, 0x46, 0x58, 0x00, 0x0b, 0x1b, 0xd5, 0x10, +0x08, 0x50, 0x00, 0x60, 0x4c, 0x54, 0xc0, 0x0c, 0x80, 0x46, 0x80, 0x07, 0x80, 0x2a, 0x46, 0xf0, +0x00, 0xd1, 0x58, 0xf7, 0x85, 0x58, 0xdd, 0x2f, 0x80, 0x40, 0xd5, 0x07, 0x97, 0x90, 0x9c, 0xb1, +0xe2, 0xc1, 0xe9, 0xef, 0x44, 0x20, 0x00, 0x1f, 0x46, 0x80, 0x01, 0x38, 0x00, 0x54, 0x09, 0xf2, +0xde, 0x2b, 0x84, 0xa5, 0xd7, 0x29, 0x5c, 0xf3, 0x00, 0x64, 0xe8, 0x25, 0x80, 0x2a, 0x80, 0x46, +0x80, 0x07, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x85, 0x58, 0xdd, 0x2f, 0x00, 0x14, 0x09, 0xf2, +0x80, 0x40, 0x44, 0x00, 0x00, 0x60, 0x42, 0x30, 0x80, 0x24, 0x46, 0x00, 0x01, 0x46, 0x58, 0x00, +0x0b, 0x04, 0x98, 0xd8, 0x84, 0x00, 0x14, 0x01, 0x80, 0x17, 0x10, 0x91, 0x80, 0x17, 0xca, 0x04, +0x9c, 0x49, 0x10, 0x14, 0x09, 0xf2, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf2, 0x5c, 0xf0, +0x00, 0x65, 0xe9, 0x02, 0x84, 0x47, 0x80, 0x02, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x38, 0x00, 0x07, 0x89, 0xf3, 0x84, 0xa2, 0x4c, 0x02, +0xc0, 0x95, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x84, 0x00, 0xa6, 0x3c, 0x4e, 0x03, 0x00, 0x86, +0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8c, 0x70, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x38, 0x04, 0x67, +0x82, 0x39, 0x84, 0x21, 0x00, 0x03, 0x00, 0x16, 0x40, 0x10, 0x80, 0x0c, 0x46, 0xf0, 0x01, 0x0d, +0x10, 0x17, 0x86, 0x08, 0x50, 0x13, 0x00, 0x08, 0x00, 0x23, 0x00, 0x15, 0xae, 0xbd, 0xa6, 0xf6, +0xae, 0xfe, 0xa6, 0x37, 0x10, 0x03, 0x80, 0x11, 0x46, 0x00, 0x01, 0x01, 0x58, 0x00, 0x08, 0x48, +0x08, 0x20, 0x80, 0x01, 0x46, 0x50, 0x01, 0x01, 0x58, 0x52, 0x88, 0x4e, 0x18, 0x20, 0x00, 0x01, +0xd8, 0xf8, 0x46, 0xf0, 0x01, 0x38, 0x02, 0x07, 0x84, 0xec, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, +0x84, 0x00, 0xac, 0x3c, 0x84, 0x21, 0xa7, 0x76, 0xd1, 0x04, 0x84, 0x60, 0x80, 0x83, 0xd5, 0x13, +0x00, 0x33, 0x00, 0x0e, 0x50, 0x03, 0x80, 0x0a, 0x50, 0x13, 0x00, 0x0f, 0x84, 0x46, 0x10, 0x33, +0x80, 0x12, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x00, 0x33, 0x80, 0x12, +0x50, 0x43, 0x80, 0x0a, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x84, 0x00, 0x00, 0x23, 0x80, 0x11, +0xa6, 0x7d, 0xa6, 0x3e, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x8e, 0x28, 0xdd, 0x2f, 0x00, 0x03, +0x00, 0x19, 0x50, 0x13, 0x00, 0x1a, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x8e, 0x14, 0xdd, 0x2f, +0x00, 0x03, 0x00, 0x39, 0x50, 0x13, 0x00, 0x3a, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x8e, 0x44, +0xdd, 0x2f, 0x00, 0x23, 0x00, 0x18, 0xa6, 0x3e, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x27, 0x88, 0x65, +0xc0, 0x03, 0x84, 0x00, 0xd5, 0x04, 0xb4, 0x07, 0x00, 0x00, 0x00, 0xb6, 0x44, 0x10, 0x00, 0x30, +0x42, 0x00, 0x04, 0x24, 0x46, 0x30, 0x01, 0x09, 0x58, 0x31, 0x87, 0xcc, 0x00, 0x63, 0x00, 0x18, +0x98, 0x03, 0x10, 0x60, 0x00, 0x25, 0xd5, 0x09, 0x50, 0x03, 0x80, 0x10, 0x84, 0x26, 0x46, 0xf0, +0x00, 0x26, 0x58, 0xf7, 0x87, 0x40, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x80, 0xe0, 0xa4, 0x00, 0x46, 0x10, 0x00, 0xd2, 0x58, 0x10, +0x82, 0x44, 0xa5, 0x48, 0x9c, 0x4c, 0xd0, 0x08, 0x46, 0x50, 0x00, 0xd2, 0x58, 0x52, 0x82, 0x5c, +0xd9, 0xf9, 0x85, 0x41, 0xd5, 0x0b, 0x46, 0xf0, 0x01, 0x44, 0x00, 0x17, 0x87, 0x40, 0x46, 0xf0, +0x00, 0xc8, 0x58, 0xf7, 0x8b, 0x0c, 0xdd, 0x2f, 0x81, 0x40, 0x50, 0x25, 0x00, 0x05, 0x96, 0x91, +0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, 0x4e, 0x02, +0x00, 0x93, 0xa4, 0x78, 0xb4, 0xc0, 0x44, 0x00, 0xfd, 0x55, 0x4c, 0x10, 0x00, 0x32, 0xe2, 0x01, +0xe9, 0x07, 0x9f, 0x42, 0xd1, 0x0d, 0x9f, 0x41, 0x4c, 0x12, 0xc0, 0x86, 0xd5, 0x25, 0x9c, 0x82, +0x4c, 0x11, 0x00, 0x3c, 0xe2, 0x22, 0xe9, 0x35, 0x9d, 0x44, 0xd9, 0x7d, 0xd5, 0x47, 0x46, 0x10, +0x01, 0x44, 0x58, 0x10, 0x87, 0x98, 0xa6, 0x88, 0xae, 0xb6, 0xa6, 0x09, 0xae, 0x37, 0xa6, 0x8a, +0x10, 0x23, 0x00, 0x08, 0xa4, 0x09, 0x92, 0x08, 0x10, 0x03, 0x00, 0x09, 0xa6, 0x0c, 0x10, 0x03, +0x00, 0x0a, 0xa6, 0x8d, 0x10, 0x23, 0x00, 0x0b, 0xa6, 0x0e, 0x10, 0x03, 0x00, 0x0c, 0xa6, 0x4f, +0x10, 0x13, 0x00, 0x0d, 0xd5, 0x4a, 0xa0, 0x3b, 0xa6, 0x00, 0xae, 0x36, 0xd5, 0x46, 0x46, 0xf0, +0x01, 0x44, 0x00, 0x07, 0x87, 0x40, 0xae, 0x36, 0xa0, 0x7b, 0xc1, 0x3f, 0x00, 0x23, 0x80, 0x1a, +0xc2, 0x3c, 0x9c, 0x37, 0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0xd5, 0x35, +0x00, 0x13, 0x80, 0x1a, 0xae, 0x76, 0xd5, 0x31, 0x46, 0x10, 0x01, 0x44, 0x58, 0x10, 0x87, 0x40, +0xa6, 0x08, 0xc8, 0x05, 0xae, 0x36, 0xa6, 0x49, 0xae, 0x77, 0xd5, 0x27, 0xae, 0x36, 0xa6, 0x8a, +0xae, 0xb7, 0xa6, 0x4b, 0x10, 0x13, 0x00, 0x08, 0xd5, 0x20, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x17, +0x83, 0xa5, 0x46, 0x80, 0x00, 0x0d, 0x58, 0x84, 0x00, 0x48, 0x9c, 0x36, 0xdd, 0x28, 0x46, 0xf0, +0x01, 0x49, 0x04, 0x17, 0x83, 0xa6, 0x50, 0x03, 0x00, 0x0a, 0xdd, 0x28, 0x46, 0xf0, 0x01, 0x49, +0x04, 0x17, 0x83, 0xa7, 0x50, 0x03, 0x00, 0x0e, 0xdd, 0x28, 0x46, 0xf0, 0x01, 0x49, 0x04, 0x17, +0x83, 0xa8, 0x50, 0x03, 0x00, 0x12, 0xdd, 0x28, 0x84, 0x0e, 0xae, 0x30, 0x8d, 0x43, 0x84, 0x01, +0xae, 0x32, 0x10, 0xa3, 0x00, 0x01, 0x84, 0x01, 0xa6, 0x78, 0xae, 0x73, 0x84, 0x20, 0xa4, 0xb8, +0x92, 0x48, 0xae, 0xb4, 0x00, 0x73, 0x80, 0x10, 0xaf, 0xf5, 0x46, 0xf0, 0x00, 0x37, 0x58, 0xf7, +0x87, 0x80, 0xdd, 0x2f, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xc4, +0x44, 0x3f, 0xfd, 0x56, 0x96, 0x80, 0x50, 0x0f, 0x80, 0x04, 0xac, 0xc0, 0x10, 0x20, 0x00, 0x1a, +0x84, 0xa2, 0x80, 0xe1, 0xd2, 0x17, 0xe6, 0x43, 0xe8, 0x04, 0x84, 0xa1, 0xda, 0x06, 0xd5, 0x0b, +0x84, 0xa3, 0xd2, 0x17, 0x84, 0xa4, 0xd2, 0x1d, 0x84, 0x03, 0x44, 0x60, 0x00, 0x12, 0x4c, 0x20, +0x40, 0x52, 0xd5, 0x53, 0xa6, 0x08, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x83, 0x00, 0xdd, 0x2f, +0xd5, 0x4f, 0x80, 0x01, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x80, 0x70, 0xdd, 0x2f, 0xd5, 0x48, +0x80, 0x01, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x81, 0x44, 0xdd, 0x2f, 0x80, 0xc0, 0xd5, 0x3d, +0x46, 0xf0, 0x01, 0x49, 0x00, 0x07, 0x8e, 0xc4, 0xc8, 0x09, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, +0x82, 0xfc, 0xdd, 0x2f, 0xc8, 0x03, 0x84, 0xcc, 0xd5, 0x02, 0x84, 0xc0, 0xa6, 0x78, 0x44, 0x00, +0x00, 0x12, 0x9e, 0x49, 0x96, 0x48, 0x5c, 0x10, 0x80, 0x02, 0x40, 0x60, 0x04, 0x1a, 0x46, 0x10, +0x01, 0x49, 0x58, 0x10, 0x8e, 0xa4, 0x44, 0x0f, 0xfd, 0x56, 0x12, 0x00, 0x80, 0x22, 0x84, 0x04, +0x10, 0x00, 0x80, 0x46, 0x14, 0x60, 0x80, 0x0e, 0xa7, 0xf8, 0x10, 0x70, 0x80, 0x50, 0xce, 0x0e, +0x46, 0x00, 0x04, 0x90, 0x04, 0x20, 0x00, 0x0e, 0x80, 0x06, 0x14, 0x20, 0x80, 0x13, 0x46, 0xf0, +0x00, 0xd0, 0x58, 0xf7, 0x8a, 0x78, 0xdd, 0x2f, 0xd5, 0x14, 0x04, 0x00, 0x80, 0x17, 0xdd, 0x20, +0xd5, 0x10, 0x84, 0xa4, 0xda, 0x06, 0xd5, 0x0d, 0xa6, 0x38, 0xc8, 0x03, 0xc6, 0x0a, 0x80, 0xc0, +0x50, 0x0f, 0x80, 0x04, 0xa9, 0x84, 0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x89, 0x44, 0xdd, 0x2f, +0x80, 0x06, 0xec, 0x3c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xc4, +0x46, 0xf0, 0x01, 0x49, 0x00, 0x17, 0x8e, 0xc4, 0xc1, 0x20, 0x46, 0xf0, 0x01, 0x49, 0x00, 0x07, +0x8e, 0xc6, 0x84, 0xa2, 0xd8, 0x1a, 0x46, 0xf0, 0x00, 0xc9, 0x58, 0xf7, 0x81, 0x18, 0xdd, 0x2f, +0x84, 0x60, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x37, 0x83, 0xc4, 0x84, 0x40, +0xa8, 0x84, 0x44, 0x2f, 0xfd, 0x56, 0xac, 0x80, 0x84, 0x43, 0x10, 0x20, 0x00, 0x1a, 0x46, 0xf0, +0x00, 0xd1, 0x58, 0xf7, 0x89, 0x44, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x38, 0x58, 0xf7, 0x87, 0x24, +0xdd, 0x2f, 0xec, 0x3c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x74, +0x50, 0x8f, 0x80, 0x40, 0x97, 0xc8, 0x81, 0x22, 0x84, 0x20, 0x54, 0xa0, 0x00, 0xff, 0x44, 0x20, +0x00, 0x20, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x5b, 0x58, 0xf7, 0x86, 0x98, 0xdd, 0x2f, 0x50, 0x6f, +0x80, 0x0c, 0x44, 0x0f, 0xfd, 0x55, 0xac, 0x30, 0x84, 0x01, 0x47, 0xc0, 0x01, 0x44, 0x84, 0x20, +0xa8, 0x34, 0x84, 0xa4, 0x10, 0x7e, 0x07, 0x40, 0x14, 0x83, 0x00, 0x03, 0x10, 0x13, 0x00, 0x1a, +0xd7, 0x3a, 0xe6, 0xe5, 0xe8, 0x09, 0x84, 0xa2, 0xd7, 0x22, 0xe6, 0xe3, 0xe8, 0x2a, 0x84, 0xa1, +0x4c, 0x72, 0xc0, 0xb7, 0xd5, 0x0b, 0x84, 0x66, 0x4c, 0x71, 0x80, 0x70, 0xe2, 0xe3, 0xe9, 0x3d, +0x95, 0x5d, 0x4c, 0x72, 0xc0, 0xae, 0x48, 0x00, 0x00, 0x86, 0x84, 0xa2, 0x4c, 0xa2, 0xc0, 0xa9, +0x00, 0x04, 0x80, 0x00, 0xf1, 0x81, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8d, 0x58, 0xdd, 0x2f, +0xf1, 0x01, 0xa8, 0x34, 0x10, 0x13, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x9b, 0x8c, 0xb6, 0x4c, 0xa2, +0xc0, 0x23, 0x80, 0x09, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x8f, 0x9c, 0xdd, 0x2f, 0xd5, 0x13, +0x84, 0xa8, 0x4c, 0xa2, 0xc0, 0x19, 0x80, 0x09, 0x46, 0xf0, 0x00, 0xca, 0x58, 0xf7, 0x8f, 0x54, +0xdd, 0x2f, 0xd5, 0x09, 0x84, 0xa1, 0x4c, 0xa2, 0xc0, 0x0f, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, +0x8d, 0x64, 0xdd, 0x2f, 0xa8, 0x34, 0x46, 0xf0, 0x00, 0xc8, 0x58, 0xf7, 0x8d, 0x40, 0xdd, 0x2f, +0x10, 0x04, 0x00, 0x00, 0x84, 0x01, 0xd5, 0x4b, 0x84, 0xa2, 0x4c, 0xa2, 0xc0, 0x2c, 0x50, 0x7f, +0x80, 0x60, 0x00, 0x04, 0x80, 0x00, 0x80, 0x27, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8b, 0x18, +0xdd, 0x2f, 0xa6, 0xff, 0xa8, 0x34, 0x10, 0x34, 0x00, 0x00, 0x46, 0x60, 0x00, 0x41, 0x58, 0x63, +0x04, 0x98, 0x50, 0x1f, 0x80, 0x68, 0x44, 0x20, 0x00, 0x10, 0x50, 0x0f, 0x80, 0x41, 0x4b, 0xe0, +0x18, 0x01, 0x80, 0x27, 0xa7, 0xfe, 0x84, 0x46, 0x10, 0x74, 0x00, 0x11, 0x50, 0x0f, 0x80, 0x52, +0x4b, 0xe0, 0x18, 0x01, 0x50, 0x0f, 0x80, 0x58, 0x50, 0x1f, 0x80, 0x78, 0x84, 0x46, 0x4b, 0xe0, +0x18, 0x01, 0x44, 0x00, 0x00, 0x1e, 0xd5, 0x1b, 0x84, 0xa8, 0x4c, 0xa2, 0xc0, 0x18, 0x50, 0xaf, +0x80, 0x80, 0x84, 0x40, 0x12, 0x25, 0x00, 0x02, 0xb6, 0x4a, 0x80, 0x2a, 0x80, 0x09, 0x46, 0xf0, +0x00, 0xcc, 0x58, 0xf7, 0x8a, 0xb0, 0xdd, 0x2f, 0xa8, 0x34, 0x80, 0x2a, 0x80, 0x08, 0x80, 0x47, +0x46, 0xf0, 0x00, 0x41, 0x58, 0xf7, 0x84, 0x98, 0xdd, 0x2f, 0x84, 0x06, 0x10, 0x0f, 0x80, 0x26, +0xd5, 0x27, 0x84, 0xa3, 0x4c, 0xa2, 0xc0, 0x25, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x17, 0x81, 0xdd, +0x00, 0x04, 0x80, 0x00, 0xdd, 0x21, 0x46, 0xf0, 0x01, 0x44, 0x04, 0x17, 0x83, 0x7a, 0x00, 0x04, +0x80, 0x01, 0xdd, 0x21, 0x44, 0x0f, 0xff, 0xc0, 0x10, 0x0e, 0x07, 0x40, 0x84, 0x02, 0x10, 0x03, +0x00, 0x1a, 0x84, 0x00, 0xa8, 0x34, 0x46, 0xf0, 0x01, 0x4d, 0x00, 0x07, 0x87, 0x3c, 0x10, 0x04, +0x00, 0x01, 0x46, 0xf0, 0x01, 0x4d, 0x00, 0x07, 0x87, 0x52, 0x10, 0x04, 0x00, 0x00, 0x50, 0x1f, +0x80, 0x0c, 0x80, 0x01, 0x00, 0x10, 0x80, 0x1a, 0x46, 0xf0, 0x01, 0x38, 0x10, 0x17, 0x8a, 0x05, +0x46, 0xf0, 0x00, 0xd1, 0x58, 0xf7, 0x89, 0x44, 0xdd, 0x2f, 0xec, 0x8c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x01, 0x44, 0x58, 0x00, 0x07, 0x98, +0x84, 0x60, 0xae, 0xc7, 0x44, 0x30, 0x4f, 0xb0, 0x44, 0x20, 0x00, 0x64, 0x84, 0x21, 0xac, 0xc1, +0x44, 0x30, 0x00, 0x32, 0xae, 0xc4, 0xae, 0x86, 0xae, 0x80, 0xae, 0x45, 0xae, 0x41, 0x46, 0xf0, +0x00, 0xcc, 0x58, 0xf7, 0x8c, 0xf4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x8b, 0x8c, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0xcc, 0x58, 0xf7, 0x88, 0x78, 0xdd, 0x2f, 0x84, 0x03, 0x46, 0x10, +0x00, 0xd1, 0x58, 0x10, 0x8b, 0xbc, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x8d, 0xa8, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0xd0, 0x58, 0xf7, 0x88, 0x08, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x57, 0x6f, 0x42, 0x4c, 0x45, 0x5f, 0x57, 0x6f, 0x57, 0x5f, 0x47, 0x50, 0x49, 0x4f, +0x5f, 0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x5f, 0x48, 0x6f, 0x73, 0x74, 0x5f, 0x54, 0x77, 0x6f, +0x5f, 0x50, 0x69, 0x6e, 0x5f, 0x4d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x75, 0x63, 0x54, 0x72, 0x69, +0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x25, 0x64, +0x0a, 0x00, 0x70, 0x75, 0x64, 0x57, 0x6f, 0x77, 0x47, 0x70, 0x69, 0x6f, 0x4c, 0x65, 0x76, 0x65, +0x6c, 0x54, 0x69, 0x6d, 0x65, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x70, 0x75, +0x64, 0x57, 0x6f, 0x62, 0x6c, 0x65, 0x47, 0x70, 0x69, 0x6f, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, +0x69, 0x6d, 0x65, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x75, 0x64, 0x57, 0x6f, +0x77, 0x47, 0x70, 0x69, 0x6f, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, +0x69, 0x6f, 0x31, 0x54, 0x69, 0x6d, 0x65, 0x31, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, +0x20, 0x75, 0x64, 0x57, 0x6f, 0x62, 0x6c, 0x65, 0x47, 0x70, 0x69, 0x6f, 0x4c, 0x65, 0x76, 0x65, +0x6c, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x31, 0x54, 0x69, 0x6d, 0x65, 0x31, 0x3d, +0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, +0x20, 0x25, 0x73, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2f, +0x73, 0x79, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x62, 0x69, 0x6e, 0x5f, 0x74, 0x2e, +0x63, 0x00, 0x75, 0x63, 0x47, 0x70, 0x69, 0x6f, 0x50, 0x69, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, +0x72, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x75, 0x63, 0x47, 0x70, 0x69, 0x6f, 0x50, 0x69, +0x6e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x30, 0x78, +0x25, 0x78, 0x2c, 0x20, 0x75, 0x34, 0x5f, 0x52, 0x45, 0x47, 0x5f, 0x49, 0x4f, 0x5f, 0x4d, 0x4f, +0x44, 0x45, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, +0x20, 0x75, 0x63, 0x5f, 0x52, 0x45, 0x47, 0x5f, 0x49, 0x4f, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, +0x42, 0x69, 0x74, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x47, 0x50, 0x4f, 0x3d, 0x30, 0x78, +0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x5f, 0x4f, 0x45, 0x4e, 0x3d, 0x30, +0x78, 0x25, 0x30, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +0x20, 0x57, 0x6f, 0x57, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, +0x6e, 0x66, 0x69, 0x67, 0x20, 0x57, 0x6f, 0x42, 0x4c, 0x45, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x0a, +0x00, 0x00, 0x52, 0x45, 0x47, 0x5f, 0x49, 0x4f, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x30, 0x3d, 0x30, +0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x52, 0x45, 0x47, 0x5f, 0x49, 0x4f, 0x5f, 0x4d, 0x4f, +0x44, 0x45, 0x31, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x2c, 0x20, 0x52, 0x45, 0x47, 0x5f, +0x49, 0x4f, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x32, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x0a, +0x00, 0x00, 0x50, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x77, 0x6d, 0x74, 0x5f, 0x74, 0x61, 0x73, 0x6b, +0x5f, 0x72, 0x78, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x3a, 0x20, +0x6f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x67, 0x5f, +0x75, 0x63, 0x57, 0x6f, 0x62, 0x6c, 0x65, 0x57, 0x6f, 0x77, 0x53, 0x68, 0x61, 0x72, 0x65, 0x50, +0x69, 0x6e, 0x45, 0x6e, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x62, 0x6c, +0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6c, 0x63, 0x2f, +0x64, 0x6c, 0x2f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x2f, 0x64, 0x6c, 0x5f, 0x64, 0x65, +0x76, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x68, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x55, 0x53, +0x42, 0x20, 0x44, 0x50, 0x20, 0x70, 0x75, 0x6c, 0x6c, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x66, +0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x77, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x3d, 0x30, +0x78, 0x25, 0x30, 0x34, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x75, 0x63, 0x55, 0x73, 0x62, 0x44, +0x70, 0x50, 0x64, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x2c, +0x20, 0x75, 0x63, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x47, 0x70, 0x69, 0x6f, 0x49, 0x6e, 0x74, +0x4d, 0x6f, 0x64, 0x65, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x2c, 0x20, 0x75, 0x63, 0x4e, +0x6f, 0x74, 0x69, 0x66, 0x79, 0x47, 0x70, 0x69, 0x6f, 0x53, 0x65, 0x6c, 0x3d, 0x30, 0x78, 0x25, +0x30, 0x32, 0x58, 0x2c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x63, 0x55, 0x73, 0x62, 0x44, 0x70, +0x50, 0x64, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, +0x2c, 0x20, 0x75, 0x63, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x47, 0x70, 0x69, 0x6f, 0x53, 0x74, +0x61, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x0a, 0x00, 0x42, 0x54, 0x20, 0x48, 0x57, 0x20, +0x49, 0x52, 0x51, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, +0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0x7f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0xff, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, +0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x62, 0x74, 0x6c, 0x6b, 0x15, 0x2e, 0x47, 0x00, 0x01, 0x18, +0x31, 0x00, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2f, 0x73, 0x79, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x63, +0x68, 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, +0x63, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2f, 0x69, 0x6e, 0x63, 0x6c, +0x75, 0x64, 0x65, 0x2f, 0x73, 0x79, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x76, 0x65, +0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2e, 0x68, 0x00, +0x00, 0x00, 0x53, 0xfd, 0x09, 0x00, 0x54, 0xfd, 0x02, 0x00, 0x55, 0xfd, 0x01, 0x00, 0x56, 0xfd, +0x02, 0x00, 0x57, 0xfd, 0x04, 0x00, 0x59, 0xfd, 0x11, 0x00, 0x01, 0x05, 0x0a, 0x00, 0xa4, 0x9e, +0x14, 0x00, 0xf8, 0x9e, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x10, 0x00, 0x00, 0x02, 0x04, +0x10, 0x00, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x0f, 0x11, 0x13, 0x15, 0x15, 0x17, +0x19, 0x1b, 0x13, 0x15, 0x17, 0x19, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, +0x19, 0x1b, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x0f, 0x11, 0x13, 0x15, 0x15, 0x17, +0x19, 0x1b, 0x13, 0x15, 0x17, 0x19, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, 0x19, 0x1b, 0x15, 0x17, +0x19, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x03, 0x07, 0x01, 0x01, 0x03, 0x24, 0x07, 0x0b, 0x31, 0x3f, 0xff, 0x0a, 0x07, 0x00, 0x03, 0x0a, +0x07, 0x07, 0x02, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x0c, 0x06, +0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x13, 0xff, 0x0d, 0x00, 0x01, 0x00, +0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xc9, 0xfc, 0x0e, 0x01, 0x0e, 0x00, +0x06, 0x43, 0x48, 0x42, 0x54, 0x52, 0x43, 0x20, 0x04, 0x32, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xfc, +0x02, 0x01, 0x0d, 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, 0xff, 0xff, +0xff, 0x07, 0x03, 0x00, 0x00, 0x00, 0x48, 0xd2, 0x0c, 0x00, 0x64, 0x9b, 0x0c, 0x00, 0xc0, 0x9b, +0x0c, 0x00, 0x00, 0x9b, 0x0c, 0x00, 0x44, 0x05, 0x0d, 0x00, 0xc4, 0x9a, 0x0c, 0x00, 0xcc, 0x9a, +0x0c, 0x00, 0x10, 0x04, 0x0d, 0x00, 0x94, 0xd1, 0x0c, 0x00, 0x5c, 0x02, 0x0d, 0x00, 0xc4, 0xdd, +0x0c, 0x00, 0xee, 0xff, 0x00, 0x00, 0x6c, 0x9c, 0x0c, 0x00, 0x98, 0x9c, 0x0c, 0x00, 0x6c, 0xdb, +0x0c, 0x00, 0xa4, 0x9e, 0x0c, 0x00, 0x98, 0xd0, 0x0c, 0x00, 0xd8, 0x9c, 0x0c, 0x00, 0xe4, 0xae, +0x0c, 0x00, 0x98, 0xc7, 0x0c, 0x00, 0xbc, 0x01, 0x0d, 0x00, 0x5c, 0x9d, 0x0c, 0x00, 0xc8, 0x9d, +0x0c, 0x00, 0x34, 0x9e, 0x0c, 0x00, 0x3c, 0xcd, 0x0c, 0x00, 0x98, 0xc6, 0x0c, 0x00, 0x6c, 0xd8, +0x0c, 0x00, 0x0c, 0xd8, 0x0c, 0x00, 0xa8, 0x9e, 0x0c, 0x00, 0x2c, 0xd7, 0x0c, 0x00, 0x50, 0xba, +0x0c, 0x00, 0xa0, 0xd6, 0x0c, 0x00, 0x0c, 0xd6, 0x0c, 0x00, 0xa4, 0xd5, 0x0c, 0x00, 0x48, 0xd5, +0x0c, 0x00, 0xb4, 0x9e, 0x0c, 0x00, 0xc8, 0xc5, 0x0c, 0x00, 0xb4, 0xb3, 0x0c, 0x00, 0xb8, 0x9e, +0x0c, 0x00, 0x08, 0xba, 0x0c, 0x00, 0x8c, 0xb9, 0x0c, 0x00, 0xdc, 0xb8, 0x0c, 0x00, 0x80, 0x9f, +0x0c, 0x00, 0xb8, 0x9f, 0x0c, 0x00, 0xb4, 0xce, 0x0c, 0x00, 0x24, 0xa4, 0x0c, 0x00, 0xbc, 0x9f, +0x0c, 0x00, 0x98, 0xd3, 0x0c, 0x00, 0xb8, 0xc4, 0x0c, 0x00, 0xd0, 0xd4, 0x0c, 0x00, 0x20, 0xd4, +0x0c, 0x00, 0x4c, 0x9e, 0x0c, 0x00, 0x78, 0x9e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0xfd, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x05, 0x00, 0x00, +0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/misc.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/misc.h new file mode 100644 index 000000000..2248bd3e8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/misc.h @@ -0,0 +1,32 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + + Handling Misc Problem + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sean Wang 2009-08-12 Create + John Li 2009-12-23 Modified +*/ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/misc_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/misc_cmm.h new file mode 100644 index 000000000..aa91c8056 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/misc_cmm.h @@ -0,0 +1,32 @@ +/* + *************************************************************************** + * 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_cmm.h + + Abstract: + + Handling Misc Problem + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sean Wang 2009-08-12 Create + John Li 2009-12-23 Modified +*/ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mlme.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mlme.h new file mode 100644 index 000000000..f482a9a4d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mlme.h @@ -0,0 +1,1477 @@ +/* + *************************************************************************** + * 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: + mlme.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2003-08-28 Created + John Chang 2004-09-06 modified for RT2600 + +*/ +#ifndef __MLME_H__ +#define __MLME_H__ + +#include "rtmp_dot11.h" + +#ifdef DOT11R_FT_SUPPORT +#include "link_list.h" +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +/* maximum supported capability information - */ +/* ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot */ +#define SUPPORTED_CAPABILITY_INFO 0x0533 + +#define END_OF_ARGS -1 +#define LFSR_MASK 0x80000057 +#define MLME_TASK_EXEC_INTV 100 /*200*/ +#define LEAD_TIME 5 + +#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ /* MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec */ +#define REORDER_EXEC_INTV 100 /* 0.1 sec */ + +#ifdef CONFIG_STA_SUPPORT +#define STAY_10_SECONDS_AWAKE 100/* */ +#endif /* CONFIG_STA_SUPPORT */ +/*#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps */ + +/* The definition of Radar detection duration region */ +#define CE 0 +#define FCC 1 +#define JAP 2 +#define JAP_W53 3 +#define JAP_W56 4 +#define MAX_RD_REGION 5 +#if defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#define BEACON_LOST_TIME 12 * OS_HZ /* 2048 msec = 2 sec */ +#else +#define BEACON_LOST_TIME 4 * OS_HZ /* 2048 msec = 2 sec */ +#endif /* defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) */ + +#define DLS_TIMEOUT 1200 /* unit: msec */ +#define AUTH_TIMEOUT 300 /* unit: msec */ +#define ASSOC_TIMEOUT 300 /* unit: msec */ +#define JOIN_TIMEOUT 2000 /* unit: msec */ +#define SHORT_CHANNEL_TIME 90 /* unit: msec */ +#define MIN_CHANNEL_TIME 110 /* unit: msec, for dual band scan */ +#define MAX_CHANNEL_TIME 140 /* unit: msec, for single band scan */ +#define FAST_ACTIVE_SCAN_TIME 30 /* Active scan waiting for probe response time */ + +#define AUTO_CHANNEL_SEL_TIMEOUT 400 /* uint: msec */ +#define LINK_DOWN_TIMEOUT 20000 /* unit: msec */ +#define AUTO_WAKEUP_TIMEOUT 70 /*unit: msec */ + +/* Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). */ +/* SHould not refer to this constant anymore */ +/*#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm */ +#define RSSI_FOR_MID_TX_POWER -55 /* -55 db is considered mid-distance */ +#define RSSI_FOR_LOW_TX_POWER -45 /* -45 db is considered very short distance and */ + /* eligible to use a lower TX power */ +#define RSSI_FOR_LOWEST_TX_POWER -30 +/*#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP */ +#define LOW_TX_POWER_DELTA 6 /* -3 db from full TX power upon very short distance. 1 grade is 0.5 db */ +#define LOWEST_TX_POWER_DELTA 16 /* -8 db from full TX power upon shortest distance. 1 grade is 0.5 db */ + +#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0 +#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1 +#define RSSI_THRESHOLD_FOR_ROAMING 25 +#define RSSI_DELTA 5 + +/* Channel Quality Indication */ +#define CQI_IS_GOOD(cqi) ((cqi) >= 50) +/*#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) */ +#define CQI_IS_POOR(cqi) (cqi < 50) /*(((cqi) >= 5) && ((cqi) < 20)) */ +#define CQI_IS_BAD(cqi) (cqi < 5) +#define CQI_IS_DEAD(cqi) (cqi == 0) + +/* weighting factor to calculate Channel quality, total should be 100% */ +#define RSSI_WEIGHTING 50 +#define TX_WEIGHTING 30 +#define RX_WEIGHTING 20 + + +#define BSS_NOT_FOUND 0xFFFFFFFF + +#ifdef EAPOL_QUEUE_SUPPORT +#define MAX_LEN_OF_EAP_QUEUE (40) +#endif /* EAPOL_QUEUE_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +#ifndef CONFIG_STA_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 64 /*20*/ /*10 */ +#endif +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 40 /*10 */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef TXBF_SUPPORT +#define SOUND_PERIOD_TIME 50 /* 50ms */ +#endif + +enum SCAN_MODE{ + /* Active scan, send probe request, and wait beacon and probe response */ + SCAN_ACTIVE = 0x00, /* all channels */ + SCAN_CISCO_ACTIVE = 0x1, /* single channel only */ + FAST_SCAN_ACTIVE = 0x2, +#ifdef WSC_INCLUDED + SCAN_WSC_ACTIVE = 0x3, +#endif /* WSC_INCLUDED */ +#ifdef DOT11N_DRAFT3 + SCAN_2040_BSS_COEXIST = 0x4, +#endif /* DOT11N_DRAFT3 */ + SCAN_ACTIVE_MAX, + + /* Passive scan, no probe request, only wait beacon and probe response */ + SCAN_PASSIVE = 0x80, /* all channels */ + SCAN_CISCO_PASSIVE = 0x81, /* single channel only */ + SCAN_CISCO_NOISE = 0x82, /* single channel only, for noise histogram collection */ + SCAN_CISCO_CHANNEL_LOAD = 0x83, /* single channel only, for channel load collection */ + SCAN_PASSIVE_MAX, + + SCAN_TYPE_MAX +}; + +#define SCAN_MASK 0x80 +#define SCAN_MODE_ACT(_x) (((_x) & SCAN_MASK) == 0) +#define SCAN_MODE_PSV(_x) (((_x) & SCAN_MASK) == SCAN_MASK) +#define SCAN_MODE_VALID(_x) ((SCAN_MODE_ACT(_x) && ((_x) < SCAN_ACTIVE_MAX)) ||\ + (SCAN_MODE_PSV(_x) && ((_x) < SCAN_PASSIVE_MAX))) + +/*#define BSS_TABLE_EMPTY(x) ((x).BssNr == 0) */ +#define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01)) +#define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define MAC_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) & (HASH_TABLE_SIZE - 1)) +#define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) & (HASH_TABLE_SIZE - 1)) + + +/* bit definition of the 2-byte pBEACON->Capability field */ +#define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0) +#define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0) +#define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0) +#define CAP_IS_CF_POLL_REQ_ON(x) (((x) & 0x0008) != 0) +#define CAP_IS_PRIVACY_ON(x) (((x) & 0x0010) != 0) +#define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0) +#define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0) +#define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0) +#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) /* 802.11e d9 */ +#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) /* 802.11e d9 */ +#define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0) +#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) /* 802.11e d9 */ +#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) /* 802.11e d9 */ +#define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0) +#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) /* 802.11e d9 */ + +#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000)) + +/*#define STA_QOS_CAPABILITY 0 // 1-byte. see 802.11e d9.0 for bit definition */ + +#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) /* 802.11g */ +#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) /* 802.11g */ +#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) /* 802.11g */ + +#define DRS_TX_QUALITY_WORST_BOUND 8/* 3 // just test by gary */ +#define DRS_PENALTY 8 + +#define BA_NOTUSE 2 +/*BA Policy subfiled value in ADDBA frame */ +#define IMMED_BA 1 +#define DELAY_BA 0 + +/* BA Initiator subfield in DELBA frame */ +#define ORIGINATOR 1 +#define RECIPIENT 0 + +/* ADDBA Status Code */ +#define ADDBA_RESULTCODE_SUCCESS 0 +#define ADDBA_RESULTCODE_REFUSED 37 +#define ADDBA_RESULTCODE_INVALID_PARAMETERS 38 + +/* DELBA Reason Code */ +#define DELBA_REASONCODE_QSTA_LEAVING 36 +#define DELBA_REASONCODE_END_BA 37 +#define DELBA_REASONCODE_UNKNOWN_BA 38 +#define DELBA_REASONCODE_TIMEOUT 39 + +/* reset all OneSecTx counters */ +#ifdef FIFO_EXT_SUPPORT +#define RESET_ONE_SEC_TX_CNT(__pEntry) \ +if (((__pEntry)) != NULL) \ +{ \ + (__pEntry)->OneSecTxRetryOkCount = 0; \ + (__pEntry)->OneSecTxFailCount = 0; \ + (__pEntry)->OneSecTxNoRetryOkCount = 0; \ + (__pEntry)->OneSecRxLGICount = 0; \ + (__pEntry)->OneSecRxSGICount = 0; \ + (__pEntry)->fifoTxSucCnt = 0;\ + (__pEntry)->fifoTxRtyCnt = 0;\ +} +#else +#define RESET_ONE_SEC_TX_CNT(__pEntry) \ +if (((__pEntry)) != NULL) \ +{ \ + (__pEntry)->OneSecTxRetryOkCount = 0; \ + (__pEntry)->OneSecTxFailCount = 0; \ + (__pEntry)->OneSecTxNoRetryOkCount = 0; \ + (__pEntry)->OneSecRxLGICount = 0; \ + (__pEntry)->OneSecRxSGICount = 0; \ +} +#endif /* FIFO_EXT_SUPPORT */ + + +/* + 802.11 frame formats +*/ + + +typedef struct _TRIGGER_EVENTA{ + BOOLEAN bValid; + UCHAR BSSID[6]; + UCHAR RegClass; /* Regulatory Class */ + USHORT Channel; +} TRIGGER_EVENTA, *PTRIGGER_EVENTA; + + +/* 20/40 trigger event table */ +/* If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. */ +#define MAX_TRIGGER_EVENT 64 +typedef struct _TRIGGER_EVENT_TAB{ + UCHAR EventANo; + TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT]; + ULONG EventBCountDown; /* Count down counter for Event B. */ +} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB; + + +/* + Extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY) + +*/ +typedef struct GNU_PACKED _EXT_CAP_INFO_ELEMENT{ +#ifdef RT_BIG_ENDIAN + UINT32 interworking:1; + UINT32 TDLSChSwitchSupport:1; /* bit30: TDLS Channel Switching */ + UINT32 TDLSPeerPSMSupport:1; /* bit29: TDLS Peer PSM Support */ + UINT32 UAPSDBufSTASupport:1; /* bit28: Peer U-APSD Buffer STA Support */ + UINT32 utc_tsf_offset:1; + UINT32 DMSSupport:1; + UINT32 ssid_list:1; + UINT32 channel_usage:1; + UINT32 timing_measurement:1; + UINT32 mbssid:1; + UINT32 ac_sta_cnt:1; + UINT32 qos_traffic_cap:1; + UINT32 BssTransitionManmt:1; + UINT32 tim_bcast:1; + UINT32 WNMSleepSupport:1;/*bit 17*/ + UINT32 TFSSupport:1;/*bit 16*/ + UINT32 geospatial_location:1; + UINT32 civic_location:1; + UINT32 collocated_interference_report:1; + UINT32 proxy_arp:1; + UINT32 FMSSupport:1;/*bit 11*/ + UINT32 location_tracking:1; + UINT32 mcast_diagnostics:1; + UINT32 diagnostics:1; + UINT32 event:1; + UINT32 s_psmp_support:1; + UINT32 rsv5:1; + UINT32 psmp_cap:1; + UINT32 rsv3:1; + UINT32 ExtendChannelSwitch:1; + UINT32 rsv1:1; + UINT32 BssCoexistMgmtSupport:1; +#else + UINT32 BssCoexistMgmtSupport:1; + UINT32 rsv1:1; + UINT32 ExtendChannelSwitch:1; + UINT32 rsv3:1; + UINT32 psmp_cap:1; + UINT32 rsv5:1; + UINT32 s_psmp_support:1; + UINT32 event:1; + UINT32 diagnostics:1; + UINT32 mcast_diagnostics:1; + UINT32 location_tracking:1; + UINT32 FMSSupport:1;/*bit 11*/ + UINT32 proxy_arp:1; + UINT32 collocated_interference_report:1; + UINT32 civic_location:1; + UINT32 geospatial_location:1; + UINT32 TFSSupport:1;/*bit 16*/ + UINT32 WNMSleepSupport:1;/*bit 17*/ + UINT32 tim_bcast:1; + UINT32 BssTransitionManmt:1; + UINT32 qos_traffic_cap:1; + UINT32 ac_sta_cnt:1; + UINT32 mbssid:1; + UINT32 timing_measurement:1; + UINT32 channel_usage:1; + UINT32 ssid_list:1; + UINT32 DMSSupport:1; + UINT32 utc_tsf_offset:1; + UINT32 UAPSDBufSTASupport:1; /* bit28: Peer U-APSD Buffer STA Support */ + UINT32 TDLSPeerPSMSupport:1; /* bit29: TDLS Peer PSM Support */ + UINT32 TDLSChSwitchSupport:1; /* bit30: TDLS Channel Switching */ + UINT32 interworking:1; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN + UINT32 rsv63:1; + UINT32 operating_mode_notification:1; + UINT32 tdls_wider_bw:1; + UINT32 rsv49:12; + UINT32 utf8_ssid:1; + UINT32 rsv47:1; + UINT32 wnm_notification:1; + UINT32 uapsd_coex:1; + UINT32 id_location:1; + UINT32 service_interval_granularity:3; + UINT32 reject_unadmitted_frame:1; + UINT32 TDLSChSwitchProhibited:1; /* bit39: TDLS Channel Switching Prohibited */ + UINT32 TDLSProhibited:1; /* bit38: TDLS Prohibited */ + UINT32 TDLSSupport:1; /* bit37: TDLS Support */ + UINT32 msgcf_cap:1; + UINT32 rsv35:1; + UINT32 sspn_inf:1; + UINT32 ebr:1; + UINT32 qosmap:1; +#else + UINT32 qosmap:1; + UINT32 ebr:1; + UINT32 sspn_inf:1; + UINT32 rsv35:1; + UINT32 msgcf_cap:1; + UINT32 TDLSSupport:1; /* bit37: TDLS Support */ + UINT32 TDLSProhibited:1; /* bit38: TDLS Prohibited */ + UINT32 TDLSChSwitchProhibited:1; /* bit39: TDLS Channel Switching Prohibited */ + UINT32 reject_unadmitted_frame:1; + UINT32 service_interval_granularity:3; + UINT32 id_location:1; + UINT32 uapsd_coex:1; + UINT32 wnm_notification:1; + UINT32 rsv47:1; + UINT32 utf8_ssid:1; + UINT32 rsv49:12; + UINT32 tdls_wider_bw:1; + UINT32 operating_mode_notification:1; + UINT32 rsv63:1; +#endif // RT_BIG_ENDIAN // +}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT; + + +/* 802.11n 7.3.2.61 */ +typedef struct GNU_PACKED _BSS_2040_COEXIST_ELEMENT{ + UCHAR ElementID; /* ID = IE_2040_BSS_COEXIST = 72 */ + UCHAR Len; + BSS_2040_COEXIST_IE BssCoexistIe; +}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT; + + +/*802.11n 7.3.2.59 */ +typedef struct GNU_PACKED _BSS_2040_INTOLERANT_CH_REPORT{ + UCHAR ElementID; /* ID = IE_2040_BSS_INTOLERANT_REPORT = 73 */ + UCHAR Len; + UCHAR RegulatoryClass; + UCHAR ChList[0]; +}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT; + + +/* The structure for channel switch annoucement IE. This is in 802.11n D3.03 */ +typedef struct GNU_PACKED _CHA_SWITCH_ANNOUNCE_IE{ + UCHAR SwitchMode; /*channel switch mode */ + UCHAR NewChannel; + UCHAR SwitchCount; +} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE; + + +/* The structure for channel switch annoucement IE. This is in 802.11n D3.03 */ +typedef struct GNU_PACKED _SEC_CHA_OFFSET_IE{ + UCHAR SecondaryChannelOffset; /* 1: Secondary above, 3: Secondary below, 0: no Secondary */ +} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE; + + +/* This structure is extracted from struct RT_HT_CAPABILITY and RT_VHT_CAP */ +typedef struct _RT_PHY_INFO{ + BOOLEAN bHtEnable; /* If we should use ht rate. */ + BOOLEAN bPreNHt; /* If we should use ht rate. */ + /*Substract from HT Capability IE */ + UCHAR MCSSet[16]; +#ifdef DOT11_VHT_AC + BOOLEAN bVhtEnable; + UCHAR vht_bw; + VHT_MCS_SET vht_mcs_set; +#endif /* DOT11_VHT_AC */ +} RT_PHY_INFO; + + +#ifdef DOT11_VHT_AC +typedef struct _RT_VHT_CAP{ + UINT32 vht_bw:2; + UINT32 vht_txstbc:1; + UINT32 vht_rxstbc:3; + UINT32 sgi_80m:1; + UINT32 vht_htc:1; + + UINT32 vht_mcs_ss1:2; + UINT32 vht_mcs_ss2:2; + UINT32 vht_rx_rate:2; + UINT32 vht_tx_rate:2; + + UINT32 rsv:16; +}RT_VHT_CAP; +#endif /* DOT11_VHT_AC */ + + +/* + This structure substracts ralink supports from all 802.11n-related features. + Features not listed here but contained in 802.11n spec are not supported in rt2860 +*/ +typedef struct { +#ifdef RT_BIG_ENDIAN + USHORT rsv:5; + USHORT AmsduSize:1; /* Max receiving A-MSDU size */ + USHORT AmsduEnable:1; /* Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n */ + USHORT RxSTBC:2; + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; /*for40MHz */ + USHORT ShortGIfor20:1; + USHORT GF:1; /*green field */ + USHORT MimoPs:2;/*mimo power safe MMPS_ */ + USHORT ChannelWidth:1; +#else + USHORT ChannelWidth:1; + USHORT MimoPs:2;/*mimo power safe MMPS_ */ + USHORT GF:1; /*green field */ + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; /*for 40MHz */ + USHORT TxSTBC:1; /* 0:not supported, 1:if supported */ + USHORT RxSTBC:2; /* 2 bits */ + USHORT AmsduEnable:1; /* Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n */ + USHORT AmsduSize:1; /* Max receiving A-MSDU size */ + USHORT rsv:5; +#endif + + /*Substract from Addiont HT INFO IE */ +#ifdef RT_BIG_ENDIAN + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; /* Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n */ + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR ExtChanOffset:2; /* Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n */ + UCHAR RecomWidth:1; +#endif + +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv3:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv3:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif + + /* New Extension Channel Offset IE */ + UCHAR NewExtChannelOffset; + /* Extension Capability IE = 127 */ + UCHAR BSSCoexist2040; +} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY; + + +typedef struct GNU_PACKED _NEW_EXT_CHAN_IE{ + UCHAR NewExtChanOffset; +} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE; + +typedef struct GNU_PACKED _FRAME_802_11 { + HEADER_802_11 Hdr; + UCHAR Octet[1]; +} FRAME_802_11, *PFRAME_802_11; + +/* QoSNull embedding of management action. When HT Control MA field set to 1. */ +typedef struct GNU_PACKED _MA_BODY { + UCHAR Category; + UCHAR Action; + UCHAR Octet[1]; +} MA_BODY, *PMA_BODY; + +typedef struct GNU_PACKED _HEADER_802_3 { + UCHAR DAAddr1[MAC_ADDR_LEN]; + UCHAR SAAddr2[MAC_ADDR_LEN]; + UCHAR Octet[2]; +} HEADER_802_3, *PHEADER_802_3; + + +/* Block ACK related format */ +/* 2-byte BA Parameter field in DELBA frames to terminate an already set up bA */ +typedef struct GNU_PACKED _DELBA_PARM{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; /* value of TC os TS */ + USHORT Initiator:1; /* 1: originator 0:recipient */ + USHORT Rsv:11; /* always set to 0 */ +#else + USHORT Rsv:11; /* always set to 0 */ + USHORT Initiator:1; /* 1: originator 0:recipient */ + USHORT TID:4; /* value of TC os TS */ +#endif /* RT_BIG_ENDIAN */ +} DELBA_PARM, *PDELBA_PARM; + +/* 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA */ +typedef struct GNU_PACKED _BA_PARM{ +#ifdef RT_BIG_ENDIAN + USHORT BufSize:10; /* number of buffe of size 2304 octetsr */ + USHORT TID:4; /* value of TC os TS */ + USHORT BAPolicy:1; /* 1: immediately BA 0:delayed BA */ + USHORT AMSDUSupported:1; /* 0: not permitted 1: permitted */ +#else + USHORT AMSDUSupported:1; /* 0: not permitted 1: permitted */ + USHORT BAPolicy:1; /* 1: immediately BA 0:delayed BA */ + USHORT TID:4; /* value of TC os TS */ + USHORT BufSize:10; /* number of buffe of size 2304 octetsr */ +#endif /* RT_BIG_ENDIAN */ +} BA_PARM, *PBA_PARM; + +/* 2-byte BA Starting Seq CONTROL field */ +typedef union GNU_PACKED _BASEQ_CONTROL{ + struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT StartSeq:12; /* sequence number of the 1st MSDU for which this BAR is sent */ + USHORT FragNum:4; /* always set to 0 */ +#else + USHORT FragNum:4; /* always set to 0 */ + USHORT StartSeq:12; /* sequence number of the 1st MSDU for which this BAR is sent */ +#endif /* RT_BIG_ENDIAN */ + } field; + USHORT word; +} BASEQ_CONTROL, *PBASEQ_CONTROL; + +/*BAControl and BARControl are the same */ +/* 2-byte BA CONTROL field in BA frame */ +typedef struct GNU_PACKED _BA_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv:9; + USHORT Compressed:1; + USHORT MTID:1; /*EWC V1.24 */ + USHORT ACKPolicy:1; /* only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK */ +#else + USHORT ACKPolicy:1; /* only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK */ + USHORT MTID:1; /*EWC V1.24 */ + USHORT Compressed:1; + USHORT Rsv:9; + USHORT TID:4; +#endif /* RT_BIG_ENDIAN */ +} BA_CONTROL, *PBA_CONTROL; + +/* 2-byte BAR CONTROL field in BAR frame */ +typedef struct GNU_PACKED _BAR_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; /*if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ */ + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; /* 0:normal ack, 1:no ack. */ + USHORT MTID:1; /*if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ */ + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} BAR_CONTROL, *PBAR_CONTROL; + +/* BARControl in MTBAR frame */ +typedef struct GNU_PACKED _MTBAR_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT NumTID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; + USHORT MTID:1; + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT NumTID:4; +#endif /* RT_BIG_ENDIAN */ +} MTBAR_CONTROL, *PMTBAR_CONTROL; + +typedef struct GNU_PACKED _PER_TID_INFO{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:12; +#else + USHORT Rsv1:12; + USHORT TID:4; +#endif /* RT_BIG_ENDIAN */ +} PER_TID_INFO, *PPER_TID_INFO; + +typedef struct { + PER_TID_INFO PerTID; + BASEQ_CONTROL BAStartingSeq; +} EACH_TID, *PEACH_TID; + + +/* BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. */ +typedef struct GNU_PACKED _FRAME_BA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BARControl; + BASEQ_CONTROL BAStartingSeq; +} FRAME_BA_REQ, *PFRAME_BA_REQ; + +typedef struct GNU_PACKED _FRAME_MTBA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + MTBAR_CONTROL MTBARControl; + PER_TID_INFO PerTIDInfo; + BASEQ_CONTROL BAStartingSeq; +} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ; + +/* Compressed format is mandantory in HT STA */ +typedef struct GNU_PACKED _FRAME_MTBA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BA_CONTROL BAControl; + BASEQ_CONTROL BAStartingSeq; + UCHAR BitMap[8]; +} FRAME_MTBA, *PFRAME_MTBA; + +typedef struct GNU_PACKED _FRAME_SMPS_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR smps; /* 7.3.1.22 */ +} FRAME_SMPS_ACTION; + +typedef struct GNU_PACKED _FRAME_ACTION_HDR { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; +} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR; + +/*Action Frame */ +/*Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 */ +typedef struct GNU_PACKED _CHAN_SWITCH_ANNOUNCE { + UCHAR ElementID; /* ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 */ + UCHAR Len; + CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe; +} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE; + + +/*802.11n : 7.3.2.20a */ +typedef struct GNU_PACKED _SECOND_CHAN_OFFSET { + UCHAR ElementID; /* ID = IE_SECONDARY_CH_OFFSET = 62 */ + UCHAR Len; + SEC_CHA_OFFSET_IE SecChOffsetIe; +} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET; + + +typedef struct GNU_PACKED _FRAME_SPETRUM_CS { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + CHAN_SWITCH_ANNOUNCE CSAnnounce; + SECOND_CHAN_OFFSET SecondChannel; +} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS; + + +typedef struct GNU_PACKED _FRAME_ADDBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; /* 1 */ + BA_PARM BaParm; /* 2 - 10 */ + USHORT TimeOutValue; /* 0 - 0 */ + BASEQ_CONTROL BaStartSeq; /* 0-0 */ +} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ; + +typedef struct GNU_PACKED _FRAME_ADDBA_RSP { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT StatusCode; + BA_PARM BaParm; /*0 - 2 */ + USHORT TimeOutValue; +} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP; + +typedef struct GNU_PACKED _FRAME_DELBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + DELBA_PARM DelbaParm; + USHORT ReasonCode; +} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ; + + +/*7.2.1.7 */ +typedef struct GNU_PACKED _FRAME_BAR { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; +} FRAME_BAR, *PFRAME_BAR; + +/*7.2.1.7 */ +typedef struct GNU_PACKED _FRAME_BA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; + UCHAR bitmask[8]; +} FRAME_BA, *PFRAME_BA; + + +/* Radio Measuement Request Frame Format */ +typedef struct GNU_PACKED _FRAME_RM_REQ_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT Repetition; + UCHAR data[0]; +} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION; + +typedef struct GNU_PACKED _HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE{ + UCHAR ID; + UCHAR Length; + UCHAR ChannelSwitchMode; + UCHAR NewRegClass; + UCHAR NewChannelNum; + UCHAR ChannelSwitchCount; +} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE; + + +/* */ +/* _Limit must be the 2**n - 1 */ +/* _SEQ1 , _SEQ2 must be within 0 ~ _Limit */ +/* */ +#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit))) +#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1))) +#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))) +#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \ + SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit)) + +/* + Contention-free parameter (without ID and Length) +*/ +typedef struct GNU_PACKED _CF_PARM{ + BOOLEAN bValid; /* 1: variable contains valid value */ + UCHAR CfpCount; + UCHAR CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; +} CF_PARM, *PCF_PARM; + + +typedef struct _CIPHER_SUITE { + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher 1, this one has more secured cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; /* Unicast cipher 2 if AP announce two unicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Group cipher */ + USHORT RsnCapability; /* RSN capability from beacon */ + BOOLEAN bMixMode; /* Indicate Pair & Group cipher might be different */ +} CIPHER_SUITE, *PCIPHER_SUITE; + + +/* EDCA configuration from AP's BEACON/ProbeRsp */ +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + BOOLEAN bAdd; /* 1: variable contains valid value */ + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; + BOOLEAN bAPSDCapable; +/* BOOLEAN bMoreDataAck; */ + UCHAR EdcaUpdateCount; + UCHAR Aifsn[4]; /* 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO */ + UCHAR Cwmin[4]; + UCHAR Cwmax[4]; + USHORT Txop[4]; /* in unit of 32-us */ + BOOLEAN bACM[4]; /* 1: Admission Control of AC_BK is mandattory */ +} EDCA_PARM, *PEDCA_PARM; + + +/* QBSS LOAD information from QAP's BEACON/ProbeRsp */ +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + USHORT StaNum; + UCHAR ChannelUtilization; + USHORT RemainingAdmissionControl; /* in unit of 32-us */ +} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM; + + +/* QBSS Info field in QSTA's assoc req */ +typedef struct GNU_PACKED _QBSS_STA_INFO_PARM{ +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR MaxSPLength:2; + UCHAR Rsv1:1; + UCHAR UAPSD_AC_BE:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_VO:1; +#else + UCHAR UAPSD_AC_VO:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_BE:1; + UCHAR Rsv1:1; + UCHAR MaxSPLength:2; + UCHAR Rsv2:1; +#endif /* RT_BIG_ENDIAN */ +} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM; + +typedef struct { + QBSS_STA_INFO_PARM QosInfo; + UCHAR Rsv; + UCHAR Q_AC_BE[4]; + UCHAR Q_AC_BK[4]; + UCHAR Q_AC_VI[4]; + UCHAR Q_AC_VO[4]; +} QBSS_STA_EDCA_PARM, *PQBSS_STA_EDCA_PARM; + +/* QBSS Info field in QAP's Beacon/ProbeRsp */ +typedef struct GNU_PACKED _QBSS_AP_INFO_PARM{ +#ifdef RT_BIG_ENDIAN + UCHAR UAPSD:1; + UCHAR Rsv:3; + UCHAR ParamSetCount:4; +#else + UCHAR ParamSetCount:4; + UCHAR Rsv:3; + UCHAR UAPSD:1; +#endif /* RT_BIG_ENDIAN */ +} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM; + +/* QOS Capability reported in QAP's BEACON/ProbeRsp */ +/* QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq */ +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; +/* BOOLEAN bMoreDataAck; */ + UCHAR EdcaUpdateCount; +} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM; + +#ifdef CONFIG_STA_SUPPORT +typedef struct { + UCHAR IELen; + UCHAR IE[MAX_CUSTOM_LEN]; +} WPA_IE_; +#endif /* CONFIG_STA_SUPPORT */ + + +typedef struct _BSS_ENTRY{ + UCHAR MacAddr[MAC_ADDR_LEN]; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR CentralChannel; /*Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. */ + ULONG ClientStatusFlags; + UCHAR BssType; + USHORT AtimWin; + USHORT BeaconPeriod; + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR Erp; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + UCHAR AddHtInfoLen; + EXT_CAP_INFO_ELEMENT ExtCapInfo; /* this is the extened capibility IE appreed in MGMT frames. Doesn't need to update once set in Init. */ + UCHAR NewExtChanOffset; + CHAR Rssi; +#ifdef CUSTOMER_DCC_FEATURE + UCHAR Snr0; + UCHAR Snr1; +#endif +#ifdef CFG80211_SCAN_SIGNAL_AVG + SHORT AvgRssiX8; + CHAR AvgRssi; +#endif /* CFG80211_SCAN_SIGNAL_AVG */ + +#ifdef DOT11_VHT_AC + UCHAR vht_cap_len; + UCHAR vht_op_len; + VHT_CAP_IE vht_cap_ie; + VHT_OP_IE vht_op_ie; +#endif /* DOT11_VHT_AC */ + + + CHAR MinSNR; + UCHAR Privacy; /* Indicate security function ON/OFF. Don't mess up with auth mode. */ + UCHAR Hidden; + + USHORT DtimPeriod; + USHORT CapabilityInfo; + + USHORT CfpCount; + USHORT CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + UCHAR SameRxTimeCount; + ULONG LastBeaconRxTimeA; /* OS's timestamp */ + ULONG LastBeaconRxTime; /* OS's timestamp */ + + BOOLEAN bSES; + + /* New for WPA2 */ + CIPHER_SUITE WPA; /* AP announced WPA cipher suite */ + CIPHER_SUITE WPA2; /* AP announced WPA2 cipher suite */ +#ifdef WAPI_SUPPORT + CIPHER_SUITE WAPI; /* AP announced WAPI cipher suite */ +#endif /* WAPI_SUPPORT */ + + /* New for microsoft WPA support */ + NDIS_802_11_FIXED_IEs FixIEs; + NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; /* Addition mode for WPA2 / WPA capable AP */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; /* Unicast Encryption Algorithm extract from VAR_IE */ + USHORT VarIELen; /* Length of next VIE include EID & Length */ + UCHAR VarIEs[MAX_VIE_LEN]; + USHORT VarIeFromProbeRspLen; + UCHAR *pVarIeFromProbRsp; +#ifdef DOT11W_PMF_SUPPORT + BOOLEAN IsSupportSHA256KeyDerivation; +#endif /* DOT11W_PMF_SUPPORT */ + + /* CCX Ckip information */ + UCHAR CkipFlag; + + /* CCX 2 TSF */ + UCHAR PTSF[4]; /* Parent TSF */ + UCHAR TTSF[8]; /* Target TSF */ + + /* 802.11e d9, and WMM */ + EDCA_PARM EdcaParm; + QOS_CAPABILITY_PARM QosCapability; + QBSS_LOAD_PARM QbssLoad; + +#ifdef WSC_INCLUDED + UCHAR WpsAP; /* 0x00: not support WPS, 0x01: support normal WPS, 0x02: support Ralink auto WPS, 0x04: support WAC AP */ + USHORT WscDPIDFromWpsAP; +#endif /* WSC_INCLUDED */ + + +#ifdef CONFIG_STA_SUPPORT + WPA_IE_ WpaIE; + WPA_IE_ RsnIE; + WPA_IE_ WpsIE; +#ifdef WAPI_SUPPORT + WPA_IE_ WapiIE; +#endif /* WAPI_SUPPORT */ + +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR CountryString[3]; + BOOLEAN bHasCountryIE; +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* CONFIG_STA_SUPPORT */ +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) + BOOLEAN bHasMDIE; + FT_MDIE FT_MDIE; +#endif /* (DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) */ + +#ifdef DOT11K_RRM_SUPPORT + UINT8 RegulatoryClass; + UINT8 CondensedPhyType; + UINT8 RSNI; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef SMART_MESH + BOOLEAN bDfsAP; /* Determine If specified peer is in DFS channel */ + BOOLEAN bSupportSmartMesh; /* Determine If own smart mesh capability */ + BOOLEAN bHyperFiPeer; /* Determine If peer is Hyper-Fi device */ + UCHAR VIEFlag; /* Store the flag byte inside VIE */ + USHORT BW; +#endif /* SMART_MESH */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + BOOLEAN bSupportHiddenWPS; /* Determine If own HiddenWPS capability */ + BOOLEAN bRunningHiddenWPS; /* Determine If HiddenWPS is running now */ + BOOLEAN bHiddenWPSRegistrar;/* Determine which role for this bss with HiddenWPS */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +} BSS_ENTRY; + +typedef struct { + UCHAR BssNr; + UCHAR BssOverlapNr; + BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; +} BSS_TABLE, *PBSS_TABLE; + + +struct raw_rssi_info{ + CHAR raw_rssi[3]; + UCHAR raw_snr; +}; + +typedef struct _MLME_QUEUE_ELEM { + UCHAR Msg[MGMT_DMA_BUFFER_SIZE]; /* move here to fix alignment issue for ARM CPU */ + ULONG Machine; + ULONG MsgType; + ULONG MsgLen; + LARGE_INTEGER TimeStamp; + UCHAR Rssi0; + UCHAR Rssi1; + UCHAR Rssi2; +#ifdef CUSTOMER_DCC_FEATURE + UCHAR Snr0; + UCHAR Snr1; +#endif + UCHAR Signal; + UCHAR Channel; + UCHAR Wcid; + BOOLEAN Occupied; + UCHAR OpMode; + ULONG Priv; +} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; + +#ifdef EAPOL_QUEUE_SUPPORT +typedef struct _EAP_MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; +#ifdef SMART_MESH + ULONG QueueFullCnt; +#endif /* SMART_MESH */ + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_EAP_QUEUE]; +} EAP_MLME_QUEUE, *PEAP_MLME_QUEUE; +#endif /* EAPOL_QUEUE_SUPPORT */ + +typedef struct _MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; +#ifdef SMART_MESH + ULONG QueueFullCnt; +#endif /* SMART_MESH */ + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; +} MLME_QUEUE, *PMLME_QUEUE; + +typedef VOID (*STATE_MACHINE_FUNC)(VOID *pAd, MLME_QUEUE_ELEM *Elem); + +typedef struct _STATE_MACHINE { + ULONG Base; + ULONG NrState; + ULONG NrMsg; + ULONG CurrState; + STATE_MACHINE_FUNC *TransFunc; +} STATE_MACHINE, *PSTATE_MACHINE; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +typedef VOID (*APCLI_STATE_MACHINE_FUNC)(VOID *pAd, MLME_QUEUE_ELEM *Elem, PULONG pCurrState, USHORT ifIndex); + +typedef struct _STA_STATE_MACHINE { + ULONG Base; + ULONG NrState; + ULONG NrMsg; + ULONG CurrState; + APCLI_STATE_MACHINE_FUNC *TransFunc; +} APCLI_STATE_MACHINE, *PSTA_STATE_MACHINE; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +/* MLME AUX data structure that hold temporarliy settings during a connection attempt. */ +/* Once this attemp succeeds, all settings will be copy to pAd->StaActive. */ +/* A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of */ +/* several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely */ +/* separate this under-trial settings away from pAd->StaActive so that once */ +/* this new attempt failed, driver can auto-recover back to the active settings. */ +typedef struct _MLME_AUX { + UCHAR BssType; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID]; + UCHAR AutoReconnectSsidLen; + USHORT Alg; + UCHAR ScanType; + UCHAR Channel; +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + BOOLEAN ScanGivenChannel; + UINT ScanTime; +#endif +#endif + UCHAR CentralChannel; + USHORT Aid; + USHORT CapabilityInfo; + USHORT BeaconPeriod; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + USHORT AtimWin; + + /* Copy supported rate from desired AP's beacon. We are trying to match */ + /* AP's supported and extended rate settings. */ + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; /* this is the extened capibility IE appreed in MGMT frames. Doesn't need to update once set in Init. */ + UCHAR NewExtChannelOffset; + /*RT_HT_CAPABILITY SupportedHtPhy; */ + +#ifdef DOT11_VHT_AC + UCHAR vht_cap_len; + UCHAR vht_op_len; + VHT_CAP_IE vht_cap; + VHT_OP_IE vht_op; + UCHAR vht_cent_ch; +#endif /* DOT11_VHT_AC */ + + /* new for QOS */ + QOS_CAPABILITY_PARM APQosCapability; /* QOS capability of the current associated AP */ + EDCA_PARM APEdcaParm; /* EDCA parameters of the current associated AP */ + QBSS_LOAD_PARM APQbssLoad; /* QBSS load of the current associated AP */ + + /* new to keep Ralink specific feature */ + ULONG APRalinkIe; + + BSS_TABLE SsidBssTab; /* AP list for the same SSID */ + BSS_TABLE RoamTab; /* AP list eligible for roaming */ + ULONG BssIdx; + ULONG RoamIdx; + BOOLEAN CurrReqIsFromNdis; + INT ScanInfType; + RALINK_TIMER_STRUCT BeaconTimer, ScanTimer, APScanTimer; + RALINK_TIMER_STRUCT AuthTimer; + RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer; +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + USHORT VarIELen; /* Length of next VIE include EID & Length */ + UCHAR VarIEs[MAX_VIE_LEN]; + LONG Rssi; /* Record the rssi value when receive Probe Rsp. */ + RALINK_TIMER_STRUCT ProbeTimer, ApCliAssocTimer, ApCliAuthTimer; + RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11R_FT_SUPPORT + RALINK_TIMER_STRUCT FtOtdActTimer; + RALINK_TIMER_STRUCT FtOtaAuthTimer; + FT_MDIE_INFO MdIeInfo; + FT_FTIE_INFO FtIeInfo; + + UINT8 InitialMDIE[5]; + UINT8 InitialFTIE[256]; + UINT InitialFTIE_Len; +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef SMART_MESH + BOOLEAN bSupportSmartMesh; /* Determine If own smart mesh capability */ + BOOLEAN bHyperFiPeer; /* Determine If peer is Hyper-Fi device */ +#endif /* SMART_MESH */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* MWDS */ +} MLME_AUX, *PMLME_AUX; + +typedef struct _MLME_ADDBA_REQ_STRUCT{ + UCHAR Wcid; + UCHAR pAddr[MAC_ADDR_LEN]; + UCHAR BaBufSize; + USHORT TimeOutValue; + UCHAR TID; + UCHAR Token; + USHORT BaStartSeq; +} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT; + + +typedef struct _MLME_DELBA_REQ_STRUCT{ + UCHAR Wcid; /* */ + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR TID; + UCHAR Initiator; +} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT; + +/* assoc struct is equal to reassoc */ +typedef struct _MLME_ASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + USHORT ListenIntv; + ULONG Timeout; +} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT; + +typedef struct _MLME_DISASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT; + +typedef struct _MLME_AUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + ULONG Timeout; +#ifdef MAC_REPEATER_SUPPORT + UCHAR BssIdx; + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ +} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT; + +typedef struct _MLME_DEAUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; + +typedef struct { + ULONG BssIdx; +} MLME_JOIN_REQ_STRUCT; + +typedef struct _MLME_SCAN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR BssType; + UCHAR ScanType; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + UINT Channel; + UINT Timeout; +#endif +#endif +} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT; + +typedef struct _MLME_START_REQ_STRUCT { + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT; + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +/* structure for DLS */ +typedef struct _RT_802_11_DLS { + USHORT TimeOut; /* Use to time out while slience, unit: second , set by UI */ + USHORT CountDownTimer; /* Use to time out while slience,unit: second , used by driver only */ + NDIS_802_11_MAC_ADDRESS MacAddr; /* set by UI */ + UCHAR Status; /* 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only */ + BOOLEAN Valid; /* 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link */ + RALINK_TIMER_STRUCT Timer; /* Use to time out while handshake */ + USHORT Sequence; + USHORT MacTabMatchWCID; /* ASIC */ + BOOLEAN bHTCap; + PVOID pAd; +} RT_802_11_DLS, *PRT_802_11_DLS; + +typedef struct _MLME_DLS_REQ_STRUCT { + PRT_802_11_DLS pDLS; + USHORT Reason; +} MLME_DLS_REQ_STRUCT, *PMLME_DLS_REQ_STRUCT; +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +typedef struct GNU_PACKED _EID_STRUCT{ + UCHAR Eid; + UCHAR Len; + UCHAR Octet[1]; +} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT; + + +/* ========================== AP mlme.h =============================== */ +#define TBTT_PRELOAD_TIME 384 /* usec. LomgPreamble + 24-byte at 1Mbps */ +#define DEFAULT_DTIM_PERIOD 1 + +/* weighting factor to calculate Channel quality, total should be 100% */ +/*#define RSSI_WEIGHTING 0 */ +/*#define TX_WEIGHTING 40 */ +/*#define RX_WEIGHTING 60 */ + +#define MAC_TABLE_AGEOUT_TIME 300 /* unit: sec */ +#define MAC_TABLE_MIN_AGEOUT_TIME 60 /* unit: sec */ +#define MAC_TABLE_ASSOC_TIMEOUT 5 /* unit: sec */ +#define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE) + +/* AP shall drop the sta if contine Tx fail count reach it. */ +#define MAC_ENTRY_LIFE_CHECK_CNT 1024 /* packet cnt. */ + +/* Value domain of pMacEntry->Sst */ +typedef enum _Sst { + SST_NOT_AUTH, /* 0: equivalent to IEEE 802.11/1999 state 1 */ + SST_AUTH, /* 1: equivalent to IEEE 802.11/1999 state 2 */ + SST_ASSOC /* 2: equivalent to IEEE 802.11/1999 state 3 */ +} SST; + +/* value domain of pMacEntry->AuthState */ +typedef enum _AuthState { + AS_NOT_AUTH, + AS_AUTH_OPEN, /* STA has been authenticated using OPEN SYSTEM */ + AS_AUTH_KEY, /* STA has been authenticated using SHARED KEY */ + AS_AUTHENTICATING /* STA is waiting for AUTH seq#3 using SHARED KEY */ +} AUTH_STATE; + + +typedef struct _IE_lists { + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR ApAddr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + USHORT ListenInterval; + UCHAR SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + UCHAR RSNIE_Len; + BOOLEAN bWmmCapable; +#ifdef WSC_AP_SUPPORT + BOOLEAN bWscCapable; +#endif /* WSC_AP_SUPPORT */ + ULONG RalinkIe; + ULONG MediatekIe; + EXT_CAP_INFO_ELEMENT ExtCapInfo; +#ifdef DOT11R_FT_SUPPORT + FT_INFO FtInfo; +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11K_RRM_SUPPORT + RRM_EN_CAP_IE RrmEnCap; +#endif /* DOT11K_RRM_SUPPORT */ + UCHAR ht_cap_len; + HT_CAPABILITY_IE HTCapability; +#ifdef DOT11_VHT_AC + VHT_CAP_IE vht_cap; + VHT_OP_IE vht_op; + UCHAR vht_cap_len; + UCHAR vht_op_len; + UCHAR operating_mode_len; + OPERATING_MODE operating_mode; +#endif /* DOT11_VHT_AC */ +}IE_LISTS; + + +typedef struct _bcn_ie_list { + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Bssid[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR BssType; + USHORT BeaconPeriod; + UCHAR Channel; + UCHAR NewChannel; + USHORT AtimWin; + USHORT CapabilityInfo; + UCHAR Erp; + UCHAR DtimCount; + UCHAR DtimPeriod; + UCHAR BcastFlag; + UCHAR MessageToMe; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + LARGE_INTEGER TimeStamp; + CF_PARM CfParm; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + ULONG MediatekIe; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + UCHAR HtCapabilityLen; + UCHAR PreNHtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + UCHAR AddHtInfoLen; + ADD_HT_INFO_IE AddHtInfo; + UCHAR NewExtChannelOffset; +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + UCHAR selReg; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef DOT11_VHT_AC + VHT_CAP_IE vht_cap_ie; + VHT_OP_IE vht_op_ie; + UCHAR vht_cap_len; + UCHAR vht_op_len; + OPERATING_MODE operating_mode; + UCHAR vht_op_mode_len; +#endif /* DOT11_VHT_AC */ +#ifdef SMART_MESH + UCHAR VIEFlag; /* Store the flag byte inside VIE*/ + BOOLEAN bSupportSmartMesh; /* Determine If own smart mesh capability */ +#endif /* SMART_MESH */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + BOOLEAN bSupportHiddenWPS; /* Determine If own HiddenWPS capability */ + BOOLEAN bRunningHiddenWPS; /* Determine HiddenWPS is running */ + BOOLEAN bHiddenWPSRegistrar;/* Determine which role for this bss with HiddenWPS */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#ifdef SMART_MESH_MONITOR + UCHAR vendor_ie_len; + UCHAR vendor_ie[NTGR_IE_TOTAL_LEN]; +#endif /* SMART_MESH_MONITOR */ +}BCN_IE_LIST; + +#define ACTION_QOSMAP_CONFIG 4 + +typedef struct _QOSMAP_SET { + UCHAR DSCP_Field_Len; + USHORT DSCP_Field[29]; /* Use to time out while slience, unit: second , set by UI */ +} QOSMAP_SET, *PQOSMAP_SET; + +typedef struct _MLME_QOS_ACTION_STRUCT{ + UCHAR ActionField; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR apidx; + QOSMAP_SET QOSMap; +} MLME_QOS_ACTION_STRUCT, *PMLME_QOS_ACTION_STRUCT; + +#endif /* MLME_H__ */ + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mlme_sys.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mlme_sys.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mlme_sys.h rename to package/lean/mt/drivers/mt7612e/src/mt76x2/include/mlme_sys.h diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mwds.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mwds.h new file mode 100644 index 000000000..334d26666 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/mwds.h @@ -0,0 +1,151 @@ +#ifndef __MWDS_H__ +#define __MWDS_H__ +/* + *************************************************************************** + * 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.h + + Abstract: + This is MWDS feature used to process those 4-addr of connected APClient or STA. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ +#ifdef MWDS +#include "rtmp_def.h" + +enum MWDS_ENTRY { + MWDS_ENTRY_NONE = 0, + MWDS_ENTRY_AP, + MWDS_ENTRY_CLIENT +}; + +#define IS_ENTRY_MWDS(_x) ((_x)->MWDSEntry != MWDS_ENTRY_NONE) +#define IS_MWDS_OPMODE_APCLI(_x) ((_x)->MWDSEntry == MWDS_ENTRY_AP) +#define IS_MWDS_OPMODE_AP(_x) ((_x)->MWDSEntry == MWDS_ENTRY_CLIENT) +#define SET_MWDS_OPMODE_NONE(_x) ((_x)->MWDSEntry = MWDS_ENTRY_NONE) +#define SET_MWDS_OPMODE_APCLI(_x) ((_x)->MWDSEntry = MWDS_ENTRY_AP) /* We operate as MWDS APCLI*/ +#define SET_MWDS_OPMODE_AP(_x) ((_x)->MWDSEntry = MWDS_ENTRY_CLIENT) /* We operate as MWDS AP*/ + +typedef struct _MWDS_CONNECT_ENTRY { + DL_LIST List; + UCHAR Valid; + UCHAR wcid; +} MWDS_CONNECT_ENTRY, *PMWDS_CONNECT_ENTRY; + +VOID MWDSConnEntryListInit( + IN PRTMP_ADAPTER pAd); + +VOID MWDSConnEntryListClear( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MWDSConnEntryLookupByWCID( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid); + +BOOLEAN MWDSConnEntryLookupByAddr( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac); + +VOID MWDSConnEntryUpdate( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid); + +VOID MWDSConnEntryDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid); + +INT MWDSGetConnEntryCount( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ISMWDSValid( + IN PRTMP_ADAPTER pAd); + +VOID MWDSProxyEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac); + +BOOLEAN MWDSProxyLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac, + IN BOOLEAN bUpdateAliveTime, + OUT UCHAR *pWcid); + +VOID MWDSProxyTabUpdate( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pMac); + +VOID MWDSProxyTabMaintain( + IN PRTMP_ADAPTER pAd); + +void MWDSSendClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pExcludeMac); + +BOOLEAN MWDSARPLookupUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +INT MWDSEnable( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN isAP); + +INT MWDSDisable( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN isAP); + +INT MWDSAPUP( + IN PRTMP_ADAPTER pAd); + +INT MWDSAPDown( + IN PRTMP_ADAPTER pAd); + + +INT Set_Ap_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ap_MWDS_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_MWDS_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_APProxy_Status_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID rtmp_read_MWDS_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + +#endif /* MWDS */ +#endif /* __MWDS_H__*/ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/netif_block.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/netif_block.h new file mode 100644 index 000000000..3714bf069 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/netif_block.h @@ -0,0 +1,31 @@ + +#ifndef __NET_IF_BLOCK_H__ +#define __NET_IF_BLOCK_H__ + +#include "link_list.h" +#include "rtmp.h" + +#define FREE_NETIF_POOL_SIZE 32 + +typedef struct _NETIF_ENTRY +{ + struct _NETIF_ENTRY *pNext; + PNET_DEV pNetDev; +} NETIF_ENTRY, *PNETIF_ENTRY; + +void initblockQueueTab( + IN PRTMP_ADAPTER pAd); + +BOOLEAN blockNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, + IN PNET_DEV pNetDev); + +VOID releaseNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry); + +VOID StopNetIfQueue( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); +#endif /* __NET_IF_BLOCK_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/nfc.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/nfc.h new file mode 100644 index 000000000..63cc7c623 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/nfc.h @@ -0,0 +1,58 @@ +#ifndef __WSC_NFC_H__ +#define __WSC_NFC_H__ + +VOID NfcParseRspCommand( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN USHORT DataLen); + +VOID NfcCommand( + IN PRTMP_ADAPTER pAd, + IN UCHAR Action, + IN UCHAR Type, + IN SHORT DataLen, + IN PUCHAR pData); + +VOID NfcGenRandomPasswd( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl); + +INT NfcBuildWscProfileTLV( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl, + OUT UCHAR *pbuf, + OUT USHORT *pBufLen); + +INT NfcBuildOOBDevPasswdTLV( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl, + IN UCHAR HandoverType, + OUT UCHAR *pbuf, + OUT USHORT *pBufLen); + +INT Set_NfcStatus_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_NfcPasswdToken_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_NfcConfigurationToken_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Get_NfcStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DoWpsByNFC_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_NfcRegenPK_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +#endif /* __WSC_NFC_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/oid.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/oid.h new file mode 100644 index 000000000..70ee33020 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/oid.h @@ -0,0 +1,1784 @@ +/* + *************************************************************************** + * 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: + oid.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef _OID_H_ +#define _OID_H_ + +/*#include */ + + + +/* new types for Media Specific Indications */ +/* Extension channel offset */ +#define EXTCHA_NONE 0 +#define EXTCHA_ABOVE 0x1 +#define EXTCHA_BELOW 0x3 + +/* BW */ +#define BAND_WIDTH_20 0 +#define BAND_WIDTH_40 1 +#define BAND_WIDTH_80 2 +#define BAND_WIDTH_BOTH 3 +#define BAND_WIDTH_10 4 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ +#define BAND_WIDTH_160 3 + + +/* SHORTGI */ +#define GAP_INTERVAL_400 1 /* only support in HT mode */ +#define GAP_INTERVAL_800 0 +#define GAP_INTERVAL_BOTH 2 + +#define NdisMediaStateConnected 1 +#define NdisMediaStateDisconnected 0 + +#define NdisApMediaStateConnected 1 +#define NdisApMediaStateDisconnected 0 + + +#define NDIS_802_11_LENGTH_SSID 32 + +#define MAC_ADDR_LEN 6 +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ +#define IEEE80211_NWID_LEN 32 + +#define NDIS_802_11_LENGTH_RATES 8 +#define NDIS_802_11_LENGTH_RATES_EX 16 + +#define OID_P2P_DEVICE_NAME_LEN 32 +/*#define MAX_NUM_OF_CHS 49 */ /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc */ +/*#define MAX_NUM_OF_CHS 54 */ /* 14 channels @2.4G + 12@UNII(lower/middle) + 16@HiperLAN2 + 11@UNII(upper) + 0 @Japan + 1 as NULL termination */ +#define MAX_NUMBER_OF_EVENT 10 /* entry # in EVENT table */ + +#ifdef CONFIG_RT_MAX_CLIENTS +#define MAX_NUMBER_OF_MAC CONFIG_RT_MAX_CLIENTS +#else +#define MAX_NUMBER_OF_MAC 32 +#endif + +#define MAX_NUMBER_OF_ACL 64 +#define MAX_LENGTH_OF_SUPPORT_RATES 12 /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ +#define MAX_NUMBER_OF_DLS_ENTRY 4 + +#define RT_QUERY_SIGNAL_CONTEXT 0x0402 +#define RT_SET_IAPP_PID 0x0404 +#define RT_SET_APD_PID 0x0405 +#define RT_SET_DEL_MAC_ENTRY 0x0406 +#define RT_QUERY_EVENT_TABLE 0x0407 +#ifdef DOT11R_FT_SUPPORT +#define RT_SET_FT_STATION_NOTIFY 0x0408 +#define RT_SET_FT_KEY_REQ 0x0409 +#define RT_SET_FT_KEY_RSP 0x040a +#define RT_FT_KEY_SET 0x040b +#define RT_FT_DATA_ENCRYPT 0x040c +#define RT_FT_DATA_DECRYPT 0x040d +#define RT_FT_NEIGHBOR_REPORT 0x040e +#define RT_FT_NEIGHBOR_REQUEST 0x040f +#define RT_FT_NEIGHBOR_RESPONSE 0x0410 +#define RT_FT_ACTION_FORWARD 0x0411 +#endif /* DOT11R_FT_SUPPORT */ +/* */ +/* IEEE 802.11 OIDs */ +/* */ +#define OID_GET_SET_TOGGLE 0x8000 +#define OID_GET_SET_FROM_UI 0x4000 + +#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0103 +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0104 +#define OID_802_11_RSSI_TRIGGER 0x0107 +#define RT_OID_802_11_RSSI 0x0108 /* rt2860 only */ +#define RT_OID_802_11_RSSI_1 0x0109 /* rt2860 only */ +#define RT_OID_802_11_RSSI_2 0x010A /* rt2860 only */ +#define OID_802_11_NUMBER_OF_ANTENNAS 0x010B +#define OID_802_11_RX_ANTENNA_SELECTED 0x010C +#define OID_802_11_TX_ANTENNA_SELECTED 0x010D +#define OID_802_11_SUPPORTED_RATES 0x010E +#define OID_802_11_ADD_WEP 0x0112 +#define OID_802_11_REMOVE_WEP 0x0113 +#define OID_802_11_DISASSOCIATE 0x0114 +#define OID_802_11_PRIVACY_FILTER 0x0118 +#define OID_802_11_ASSOCIATION_INFORMATION 0x011E +#define OID_802_11_TEST 0x011F + + +#define RT_OID_802_11_COUNTRY_REGION 0x0507 +#define OID_802_11_BSSID_LIST_SCAN 0x0508 +#define OID_802_11_SSID 0x0509 +#define OID_802_11_BSSID 0x050A +#define RT_OID_802_11_RADIO 0x050B +#define RT_OID_802_11_PHY_MODE 0x050C +#define RT_OID_802_11_STA_CONFIG 0x050D +#define OID_802_11_DESIRED_RATES 0x050E +#define RT_OID_802_11_PREAMBLE 0x050F +#define OID_802_11_WEP_STATUS 0x0510 +#define OID_802_11_AUTHENTICATION_MODE 0x0511 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 +#define RT_OID_802_11_RESET_COUNTERS 0x0513 +#define OID_802_11_RTS_THRESHOLD 0x0514 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0515 +#define OID_802_11_POWER_MODE 0x0516 +#define OID_802_11_TX_POWER_LEVEL 0x0517 +#define RT_OID_802_11_ADD_WPA 0x0518 +#define OID_802_11_REMOVE_KEY 0x0519 +#define RT_OID_802_11_QUERY_PID 0x051A +#define RT_OID_802_11_QUERY_VID 0x051B +#define OID_802_11_ADD_KEY 0x0520 +#define OID_802_11_CONFIGURATION 0x0521 +#define OID_802_11_TX_PACKET_BURST 0x0522 +#define RT_OID_802_11_QUERY_NOISE_LEVEL 0x0523 +#define RT_OID_802_11_EXTRA_INFO 0x0524 +#define RT_OID_802_11_HARDWARE_REGISTER 0x0525 +#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS +#define OID_802_11_DEAUTHENTICATION 0x0526 +#define OID_802_11_DROP_UNENCRYPTED 0x0527 +#define OID_802_11_MIC_FAILURE_REPORT_FRAME 0x0528 +#define OID_802_11_EAP_METHOD 0x0529 +#define OID_802_11_ACL_LIST 0x052A + +#define OID_802_11_PASSPHRASE 0x052B +#define OID_802_11_CHANNEL_WIDTH 0x052C +#define OID_802_11_BEACON_PERIOD 0x052D +#define OID_802_11_HT_STBC 0x052E +#define OID_802_11_UAPSD 0x052F +#define OID_802_11_COEXISTENCE 0x0530 +#define OID_802_11_AMSDU 0x0531 +#define OID_802_11_AMPDU 0x0532 +#define OID_802_11_APCFG 0x0533 +#define OID_802_11_ASSOLIST 0x0534 + +/* For 802.1x daemin using */ +#ifdef DOT1X_SUPPORT +#define OID_802_DOT1X_CONFIGURATION 0x0540 +#define OID_802_DOT1X_PMKID_CACHE 0x0541 +#define OID_802_DOT1X_RADIUS_DATA 0x0542 +#define OID_802_DOT1X_WPA_KEY 0x0543 +#define OID_802_DOT1X_STATIC_WEP_COPY 0x0544 +#define OID_802_DOT1X_IDLE_TIMEOUT 0x0545 +#define OID_802_DOT1X_RADIUS_ACL_NEW_CACHE 0x0546 +#define OID_802_DOT1X_RADIUS_ACL_DEL_CACHE 0x0547 +#define OID_802_DOT1X_RADIUS_ACL_CLEAR_CACHE 0x0548 +#define OID_802_DOT1X_QUERY_STA_AID 0x0549 +#endif /* DOT1X_SUPPORT */ + +#define RT_OID_DEVICE_NAME 0x0607 +#define RT_OID_VERSION_INFO 0x0608 +#define OID_802_11_BSSID_LIST 0x0609 +#define OID_802_3_CURRENT_ADDRESS 0x060A +#define OID_GEN_MEDIA_CONNECT_STATUS 0x060B +#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C +#define OID_802_11_RSSI 0x060D +#define OID_802_11_STATISTICS 0x060E +#define OID_GEN_RCV_OK 0x060F +#define OID_GEN_RCV_NO_BUFFER 0x0610 +#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611 +#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612 +#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613 +#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614 +#define RT_OID_802_11_QUERY_PIDVID 0x0615 +/*for WPA_SUPPLICANT_SUPPORT */ +#define OID_SET_COUNTERMEASURES 0x0616 +#define OID_802_11_SET_IEEE8021X 0x0617 +#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 +#define OID_802_11_PMKID 0x0620 +#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 +#define RT_OID_WE_VERSION_COMPILED 0x0622 +#define RT_OID_NEW_DRIVER 0x0623 +#define OID_AUTO_PROVISION_BSSID_LIST 0x0624 +#define RT_OID_WPS_PROBE_REQ_IE 0x0625 + +#define RT_OID_802_11_SNR_0 0x0630 +#define RT_OID_802_11_SNR_1 0x0631 +#define RT_OID_802_11_QUERY_LAST_TX_RATE 0x0632 +#define RT_OID_802_11_QUERY_HT_PHYMODE 0x0633 +#define RT_OID_802_11_SET_HT_PHYMODE 0x0634 +#define OID_802_11_RELOAD_DEFAULTS 0x0635 +#define RT_OID_802_11_QUERY_APSD_SETTING 0x0636 +#define RT_OID_802_11_SET_APSD_SETTING 0x0637 +#define RT_OID_802_11_QUERY_APSD_PSM 0x0638 +#define RT_OID_802_11_SET_APSD_PSM 0x0639 +#define RT_OID_802_11_QUERY_DLS 0x063A +#define RT_OID_802_11_SET_DLS 0x063B +#define RT_OID_802_11_QUERY_DLS_PARAM 0x063C +#define RT_OID_802_11_SET_DLS_PARAM 0x063D +#define RT_OID_802_11_QUERY_WMM 0x063E +#define RT_OID_802_11_SET_WMM 0x063F +#define RT_OID_802_11_QUERY_IMME_BA_CAP 0x0640 +#define RT_OID_802_11_SET_IMME_BA_CAP 0x0641 +#define RT_OID_802_11_QUERY_BATABLE 0x0642 +#define RT_OID_802_11_ADD_IMME_BA 0x0643 +#define RT_OID_802_11_TEAR_IMME_BA 0x0644 +#define RT_OID_DRIVER_DEVICE_NAME 0x0645 +#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE 0x0646 +#define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT 0x0647 +#define OID_802_11_SET_PSPXLINK_MODE 0x0648 +/*+++ add by woody +++*/ +#define OID_802_11_SET_PASSPHRASE 0x0649 +#define RT_OID_802_11_QUERY_TX_PHYMODE 0x0650 +#define RT_OID_802_11_QUERY_MAP_REAL_TX_RATE 0x0678 +#define RT_OID_802_11_QUERY_MAP_REAL_RX_RATE 0x0679 +#define RT_OID_802_11_SNR_2 0x067A +#define RT_OID_802_11_PER_BSS_STATISTICS 0x067D + +#ifdef TXBF_SUPPORT +#define RT_OID_802_11_QUERY_TXBF_TABLE 0x067C +#endif + +#ifdef RTMP_RBUS_SUPPORT +#define OID_802_11_QUERY_WirelessMode 0x0718 +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT +#define SIOCSIWGENIE 0x8B30 +#define OID_HOSTAPD_SUPPORT 0x0661 + +#define HOSTAPD_OID_STATIC_WEP_COPY 0x0662 +#define HOSTAPD_OID_GET_1X_GROUP_KEY 0x0663 + +#define HOSTAPD_OID_SET_STA_AUTHORIZED 0x0664 +#define HOSTAPD_OID_SET_STA_DISASSOC 0x0665 +#define HOSTAPD_OID_SET_STA_DEAUTH 0x0666 +#define HOSTAPD_OID_DEL_KEY 0x0667 +#define HOSTAPD_OID_SET_KEY 0x0668 +#define HOSTAPD_OID_SET_802_1X 0x0669 +#define HOSTAPD_OID_GET_SEQ 0x0670 +#define HOSTAPD_OID_GETWPAIE 0x0671 +#define HOSTAPD_OID_COUNTERMEASURES 0x0672 +#define HOSTAPD_OID_SET_WPAPSK 0x0673 +#define HOSTAPD_OID_SET_WPS_BEACON_IE 0x0674 +#define HOSTAPD_OID_SET_WPS_PROBE_RESP_IE 0x0675 + +#define RT_HOSTAPD_OID_HOSTAPD_SUPPORT (OID_GET_SET_TOGGLE | OID_HOSTAPD_SUPPORT) +#define RT_HOSTAPD_OID_STATIC_WEP_COPY (OID_GET_SET_TOGGLE | HOSTAPD_OID_STATIC_WEP_COPY) +#define RT_HOSTAPD_OID_GET_1X_GROUP_KEY (OID_GET_SET_TOGGLE | HOSTAPD_OID_GET_1X_GROUP_KEY) +#define RT_HOSTAPD_OID_SET_STA_AUTHORIZED (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_STA_AUTHORIZED) +#define RT_HOSTAPD_OID_SET_STA_DISASSOC (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_STA_DISASSOC) +#define RT_HOSTAPD_OID_SET_STA_DEAUTH (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_STA_DEAUTH) +#define RT_HOSTAPD_OID_DEL_KEY (OID_GET_SET_TOGGLE | HOSTAPD_OID_DEL_KEY) +#define RT_HOSTAPD_OID_SET_KEY (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_KEY) +#define RT_HOSTAPD_OID_SET_802_1X (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_802_1X) +#define RT_HOSTAPD_OID_COUNTERMEASURES (OID_GET_SET_TOGGLE | HOSTAPD_OID_COUNTERMEASURES) +#define RT_HOSTAPD_OID_SET_WPAPSK (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_WPAPSK) +#define RT_HOSTAPD_OID_SET_WPS_BEACON_IE (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_WPS_BEACON_IE) +#define RT_HOSTAPD_OID_SET_WPS_PROBE_RESP_IE (OID_GET_SET_TOGGLE | HOSTAPD_OID_SET_WPS_PROBE_RESP_IE) + +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) +#define IEEE80211_KEYBUF_SIZE 16 +#define IEEE80211_MICBUF_SIZE (8 + 8) /* space for both tx+rx keys */ +#define IEEE80211_TID_SIZE 17 /* total number of TIDs */ + +#define IEEE80211_MLME_ASSOC 1 /* associate station */ +#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */ +#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */ +#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */ +#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */ +#define IEEE80211_MLME_CLEAR_STATS 6 /* clear station statistic */ +#define IEEE80211_1X_COPY_KEY 7 /* copy static-wep unicast key */ + +#define IEEE80211_MAX_OPT_IE 256 +#define IWEVEXPIRED 0x8C04 + +struct ieee80211req_mlme { + UINT8 im_op; /* operation to perform */ + UINT8 im_ssid_len; /* length of optional ssid */ + UINT16 im_reason; /* 802.11 reason code */ + UINT8 im_macaddr[IEEE80211_ADDR_LEN]; + UINT8 im_ssid[IEEE80211_NWID_LEN]; +}; + +struct ieee80211req_key { + UINT8 ik_type; /* key/cipher type */ + UINT8 ik_pad; + UINT16 ik_keyix; /* key index */ + UINT8 ik_keylen; /* key length in bytes */ + UINT8 ik_flags; + UINT8 ik_macaddr[IEEE80211_ADDR_LEN]; + UINT64 ik_keyrsc; /* key receive sequence counter */ + UINT64 ik_keytsc; /* key transmit sequence counter */ + UINT8 ik_keydata[IEEE80211_KEYBUF_SIZE + IEEE80211_MICBUF_SIZE]; + int txkey; +}; + +struct ieee80211req_del_key { + UINT8 idk_keyix; /* key index */ + UINT8 idk_macaddr[IEEE80211_ADDR_LEN]; +}; + +struct default_group_key { + UINT16 ik_keyix; /* key index */ + UINT8 ik_keylen; /* key length in bytes */ + UINT8 ik_keydata[IEEE80211_KEYBUF_SIZE + IEEE80211_MICBUF_SIZE]; +}; + +struct ieee80211req_wpaie { + UINT8 wpa_macaddr[IEEE80211_ADDR_LEN]; + UINT8 rsn_ie[IEEE80211_MAX_OPT_IE]; +}; + +struct hostapd_wpa_psk { + struct hostapd_wpa_psk *next; + int group; + UCHAR psk[32]; + UCHAR addr[6]; +}; + +#endif /*HOSTAPD_SUPPORT */ + +#define RT_OID_802_11_QUERY_TDLS_PARAM 0x0676 +#define RT_OID_802_11_QUERY_TDLS 0x0677 + +/* Ralink defined OIDs */ +/* Dennis Lee move to platform specific */ + +#define RT_OID_802_11_BSSID (OID_GET_SET_TOGGLE | OID_802_11_BSSID) +#define RT_OID_802_11_SSID (OID_GET_SET_TOGGLE | OID_802_11_SSID) +#define RT_OID_802_11_INFRASTRUCTURE_MODE (OID_GET_SET_TOGGLE | OID_802_11_INFRASTRUCTURE_MODE) +#define RT_OID_802_11_ADD_WEP (OID_GET_SET_TOGGLE | OID_802_11_ADD_WEP) +#define RT_OID_802_11_ADD_KEY (OID_GET_SET_TOGGLE | OID_802_11_ADD_KEY) +#define RT_OID_802_11_REMOVE_WEP (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_WEP) +#define RT_OID_802_11_REMOVE_KEY (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_KEY) +#define RT_OID_802_11_DISASSOCIATE (OID_GET_SET_TOGGLE | OID_802_11_DISASSOCIATE) +#define RT_OID_802_11_AUTHENTICATION_MODE (OID_GET_SET_TOGGLE | OID_802_11_AUTHENTICATION_MODE) +#define RT_OID_802_11_PRIVACY_FILTER (OID_GET_SET_TOGGLE | OID_802_11_PRIVACY_FILTER) +#define RT_OID_802_11_BSSID_LIST_SCAN (OID_GET_SET_TOGGLE | OID_802_11_BSSID_LIST_SCAN) +#define RT_OID_802_11_WEP_STATUS (OID_GET_SET_TOGGLE | OID_802_11_WEP_STATUS) +#define RT_OID_802_11_RELOAD_DEFAULTS (OID_GET_SET_TOGGLE | OID_802_11_RELOAD_DEFAULTS) +#define RT_OID_802_11_NETWORK_TYPE_IN_USE (OID_GET_SET_TOGGLE | OID_802_11_NETWORK_TYPE_IN_USE) +#define RT_OID_802_11_TX_POWER_LEVEL (OID_GET_SET_TOGGLE | OID_802_11_TX_POWER_LEVEL) +#define RT_OID_802_11_RSSI_TRIGGER (OID_GET_SET_TOGGLE | OID_802_11_RSSI_TRIGGER) +#define RT_OID_802_11_FRAGMENTATION_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_FRAGMENTATION_THRESHOLD) +#define RT_OID_802_11_RTS_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_RTS_THRESHOLD) +#define RT_OID_802_11_RX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_RX_ANTENNA_SELECTED) +#define RT_OID_802_11_TX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_TX_ANTENNA_SELECTED) +#define RT_OID_802_11_SUPPORTED_RATES (OID_GET_SET_TOGGLE | OID_802_11_SUPPORTED_RATES) +#define RT_OID_802_11_DESIRED_RATES (OID_GET_SET_TOGGLE | OID_802_11_DESIRED_RATES) +#define RT_OID_802_11_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_CONFIGURATION) +#define RT_OID_802_11_POWER_MODE (OID_GET_SET_TOGGLE | OID_802_11_POWER_MODE) +#define RT_OID_802_11_SET_PSPXLINK_MODE (OID_GET_SET_TOGGLE | OID_802_11_SET_PSPXLINK_MODE) +#define RT_OID_802_11_EAP_METHOD (OID_GET_SET_TOGGLE | OID_802_11_EAP_METHOD) +#define RT_OID_802_11_SET_PASSPHRASE (OID_GET_SET_TOGGLE | OID_802_11_SET_PASSPHRASE) + +#ifdef DOT1X_SUPPORT +#define RT_OID_802_DOT1X_PMKID_CACHE (OID_GET_SET_TOGGLE | OID_802_DOT1X_PMKID_CACHE) +#define RT_OID_802_DOT1X_RADIUS_DATA (OID_GET_SET_TOGGLE | OID_802_DOT1X_RADIUS_DATA) +#define RT_OID_802_DOT1X_WPA_KEY (OID_GET_SET_TOGGLE | OID_802_DOT1X_WPA_KEY) +#define RT_OID_802_DOT1X_STATIC_WEP_COPY (OID_GET_SET_TOGGLE | OID_802_DOT1X_STATIC_WEP_COPY) +#define RT_OID_802_DOT1X_IDLE_TIMEOUT (OID_GET_SET_TOGGLE | OID_802_DOT1X_IDLE_TIMEOUT) +#endif /* DOT1X_SUPPORT */ + +#define RT_OID_802_11_SET_TDLS_PARAM (OID_GET_SET_TOGGLE | RT_OID_802_11_QUERY_TDLS_PARAM) +#define RT_OID_802_11_SET_TDLS (OID_GET_SET_TOGGLE | RT_OID_802_11_QUERY_TDLS) + +#ifdef WAPI_SUPPORT +#define OID_802_11_WAPI_PID 0x06A0 +#define OID_802_11_PORT_SECURE_STATE 0x06A1 +#define OID_802_11_UCAST_KEY_INFO 0x06A2 +#define OID_802_11_MCAST_TXIV 0x06A3 +#define OID_802_11_MCAST_KEY_INFO 0x06A4 +#define OID_802_11_WAPI_CONFIGURATION 0x06A5 +#define OID_802_11_WAPI_IE 0x06A6 + +#define RT_OID_802_11_WAPI_PID (OID_GET_SET_TOGGLE | OID_802_11_WAPI_PID) +#define RT_OID_802_11_PORT_SECURE_STATE (OID_GET_SET_TOGGLE | OID_802_11_PORT_SECURE_STATE) +#define RT_OID_802_11_UCAST_KEY_INFO (OID_GET_SET_TOGGLE | OID_802_11_UCAST_KEY_INFO) +#define RT_OID_802_11_MCAST_TXIV (OID_GET_SET_TOGGLE | OID_802_11_MCAST_TXIV) +#define RT_OID_802_11_MCAST_KEY_INFO (OID_GET_SET_TOGGLE | OID_802_11_MCAST_KEY_INFO) +#define RT_OID_802_11_WAPI_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_WAPI_CONFIGURATION) +#define RT_OID_802_11_WAPI_IE (OID_GET_SET_TOGGLE | OID_802_11_WAPI_IE) +#endif /* WAPI_SUPPORT */ + +#ifdef CUSTOMER_DCC_FEATURE +#define OID_802_11_GET_CURRENT_CHANNEL_FALSE_CCA_AVG 0x0690 +#define OID_802_11_GET_CURRENT_CHANNEL_CST_TIME_AVG 0x0691 +#define OID_802_11_GET_CURRENT_CHANNEL_BUSY_TIME_AVG 0x0692 +#define OID_802_11_GET_CURRENT_CHANNEL_STATS 0x0693 +#define OID_802_11_GET_CURRENT_CHANNEL_AP_ACTIVITY_AVG 0x0694 +#define OID_802_11_STA_STATISTICS 0x0695 +#define OID_802_11_GET_CURRENT_CHANNEL_AP_TABLE 0x0696 +#define OID_802_11_GET_ACCESS_CATEGORY_TRAFFIC_STATUS 0x0697 +#define OID_802_11_GET_SCAN_RESULTS 0x0698 +#define OID_802_11_GET_RADIO_STATS_COUNT 0x0699 +#define OID_802_11_MBSS_STATISTICS 0x069a + + +typedef struct _CURRENT_CHANNEL_STATS{ + UINT32 SamplePeriod; + UINT32 FalseCCACount; + UINT32 ChannelApActivity; + UINT32 EdCcaBusyTime; + UINT32 ChannelBusyTime; +} CURRENT_CHANNEL_STATISTICS, *PCURRENT_CHANNEL_STATISTICS; + +#ifdef MBSS_802_11_STATISTICS +typedef struct __RT_MBSS_STAT_ENTRY{ + // DATA counter + UINT32 RxCount; + UINT32 TxCount; + UINT32 ReceivedByteCount; + UINT32 TransmittedByteCount; + UINT32 RxErrorCount; + UINT32 RxDropCount; + UINT32 TxErrorCount; + UINT32 TxDropCount; + UINT32 UnicastPktsRx; + UINT32 UnicastPktsTx; + UINT32 MulticastPktsRx; + UINT32 MulticastPktsTx; + UINT32 BroadcastPktsRx; + UINT32 BroadcastPktsTx; + UINT32 TxRetriedPktCount; + UINT32 ChannelUseTime; + // MGMT counter + UINT32 MGMTRxCount; + UINT32 MGMTTxCount; + UINT32 MGMTReceivedByteCount; + UINT32 MGMTTransmittedByteCount; + UINT32 MGMTRxErrorCount; + UINT32 MGMTRxDropCount; + UINT32 MGMTTxErrorCount; + UINT32 MGMTTxDropCount; +} RT_MBSS_STAT_ENTRY; + +typedef struct __RT_MBSS_STATISTICS_TABLE{ + UINT32 Num; + RT_MBSS_STAT_ENTRY MbssEntry[8]; +} RT_MBSS_STATISTICS_TABLE; + +typedef struct __RT_STA_STAT_ENTRY +{ + UCHAR ApIdx; + UCHAR Addr[MAC_ADDR_LEN]; + UINT32 RxCount; + UINT32 TxCount; + UINT32 ReceivedByteCount; + UINT32 TransmittedByteCount; + UINT32 RxErrorCount; + UINT32 RxDropCount; + UINT32 TxErrorCount; + UINT32 TxDropCount; + UINT32 TxRetriedPktCount; + UINT32 ChannelUseTime; +} RT_STA_STAT_ENTRY; + +typedef struct __RT_STA_STATISTICS_TABLE +{ + int Num; + RT_STA_STAT_ENTRY STAEntry[MAX_NUMBER_OF_MAC]; +} RT_STA_STATISTICS_TABLE; +#endif + +typedef struct _BSS_ENTRY_TABLE +{ + UINT8 Bssid[MAC_ADDR_LEN]; + UINT16 SsidLen; + UINT8 Ssid[33]; + UINT8 Channel; + UINT8 ChannelWidth; + UINT8 ExtChannel; + CHAR RSSI; + UINT8 SNR; + UINT8 PhyMode; + UINT8 NumSpatialStream; +}BSS_ENTRY_TABLE, *PBSS_ENTRY_TABLE; + +typedef struct _BEACON_TABLE +{ + UINT8 Num; + BSS_ENTRY_TABLE BssTable[MAX_LEN_OF_BSS_TABLE]; +} BEACON_TABLE, *PBEACON_TABLE; + +typedef struct _SCAN_RESULTS +{ + UINT32 ch_busy_time; + UINT32 cca_err_cnt; + UINT32 num_ap; + BSS_ENTRY_TABLE BssTable[MAX_LEN_OF_BSS_TABLE]; +}SCAN_RESULTS, *PSCAN_RESULTS; +#endif + +typedef enum _NDIS_802_11_STATUS_TYPE { + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusTypeMax /* not a real type, defined as an upper bound */ +} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; + +typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; + +typedef struct _NDIS_802_11_STATUS_INDICATION { + NDIS_802_11_STATUS_TYPE StatusType; +} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION; + +/* mask for authentication/integrity fields */ +#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f + +#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 +#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 +#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 +#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E + +typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST { + ULONG Length; /* Length of structure */ + NDIS_802_11_MAC_ADDRESS Bssid; + ULONG Flags; +} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST; + +/*Added new types for PMKID Candidate lists. */ +typedef struct _PMKID_CANDIDATE { + NDIS_802_11_MAC_ADDRESS BSSID; + ULONG Flags; +} PMKID_CANDIDATE, *PPMKID_CANDIDATE; + +typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST { + ULONG Version; /* Version of the structure */ + ULONG NumCandidates; /* No. of pmkid candidates */ + PMKID_CANDIDATE CandidateList[1]; +} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; + +/*Flags for PMKID Candidate list structure */ +#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +/* Added new types for OFDM 5G and 2.4G */ +typedef enum _NDIS_802_11_NETWORK_TYPE { + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM24, + Ndis802_11Automode, + Ndis802_11OFDM5_N, + Ndis802_11OFDM24_N, + Ndis802_11OFDM5_AC, + Ndis802_11NetworkTypeMax /* not a real type, defined as an upper bound */ +} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; + +typedef struct _NDIS_802_11_NETWORK_TYPE_LIST { + UINT NumberOfItems; /* in list below, at least 1 */ + NDIS_802_11_NETWORK_TYPE NetworkType[1]; +} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST; + +typedef enum _NDIS_802_11_POWER_MODE { + Ndis802_11PowerModeCAM, + Ndis802_11PowerModeMAX_PSP, + Ndis802_11PowerModeFast_PSP, + Ndis802_11PowerModeLegacy_PSP, + Ndis802_11PowerModeMax /* not a real mode, defined as an upper bound */ +} NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE; + +typedef ULONG NDIS_802_11_TX_POWER_LEVEL; /* in milliwatts */ + +/* */ +/* Received Signal Strength Indication */ +/* */ +typedef LONG NDIS_802_11_RSSI; /* in dBm */ + +typedef struct _NDIS_802_11_CONFIGURATION_FH { + ULONG Length; /* Length of structure */ + ULONG HopPattern; /* As defined by 802.11, MSB set */ + ULONG HopSet; /* to one if non-802.11 */ + ULONG DwellTime; /* units are Kusec */ +} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; + +typedef struct _NDIS_802_11_CONFIGURATION { + ULONG Length; /* Length of structure */ + ULONG BeaconPeriod; /* units are Kusec */ + ULONG ATIMWindow; /* units are Kusec */ + ULONG DSConfig; /* Frequency, units are kHz */ + NDIS_802_11_CONFIGURATION_FH FHConfig; +} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; + +typedef struct _NDIS_802_11_STATISTICS { + ULONG Length; /* Length of structure */ + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; + LARGE_INTEGER TransmittedFrameCount; + LARGE_INTEGER WEPUndecryptableCount; + LARGE_INTEGER TKIPLocalMICFailures; + LARGE_INTEGER TKIPRemoteMICErrors; + LARGE_INTEGER TKIPICVErrors; + LARGE_INTEGER TKIPCounterMeasuresInvoked; + LARGE_INTEGER TKIPReplays; + LARGE_INTEGER CCMPFormatErrors; + LARGE_INTEGER CCMPReplays; + LARGE_INTEGER CCMPDecryptErrors; + LARGE_INTEGER FourWayHandshakeFailures; +} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS; + +typedef struct _MBSS_STATISTICS { + LONG TxCount; + ULONG RxCount; + ULONG ReceivedByteCount; + ULONG TransmittedByteCount; + ULONG RxErrorCount; + ULONG RxDropCount; + ULONG TxErrorCount; + ULONG TxDropCount; + ULONG ucPktsTx; + ULONG ucPktsRx; + ULONG mcPktsTx; + ULONG mcPktsRx; + ULONG bcPktsTx; + ULONG bcPktsRx; +} MBSS_STATISTICS, *PMBSS_STATISTICS; + +typedef ULONG NDIS_802_11_KEY_INDEX; +typedef ULONGLONG NDIS_802_11_KEY_RSC; + +#ifdef DOT1X_SUPPORT +#define MAX_RADIUS_SRV_NUM 2 /* 802.1x failover number */ + +/* The dot1x related structure. + It's used to communicate with DOT1X daemon */ +typedef struct GNU_PACKED _RADIUS_SRV_INFO { + UINT32 radius_ip; + UINT32 radius_port; + UCHAR radius_key[64]; + UCHAR radius_key_len; +} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO; + +typedef struct GNU_PACKED _DOT1X_BSS_INFO { + UCHAR radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + UCHAR ieee8021xWEP; /* dynamic WEP */ + UCHAR key_index; + UCHAR key_length; /* length of key in bytes */ + UCHAR key_material[13]; + UCHAR nasId[IFNAMSIZ]; + UCHAR nasId_len; +} DOT1X_BSS_INFO, *PDOT1X_BSS_INFO; + +typedef struct GNU_PACKED _DOT1X_CMM_CONF { + UINT32 Length; /* Length of this structure */ + UCHAR mbss_num; /* indicate multiple BSS number */ + UINT32 own_ip_addr; + UINT32 retry_interval; + UINT32 session_timeout_interval; + UINT32 quiet_interval; + UCHAR EAPifname[8][IFNAMSIZ]; + UCHAR EAPifname_len[8]; + UCHAR PreAuthifname[8][IFNAMSIZ]; + UCHAR PreAuthifname_len[8]; + DOT1X_BSS_INFO Dot1xBssInfo[8]; +} DOT1X_CMM_CONF, *PDOT1X_CMM_CONF; + +typedef struct GNU_PACKED _DOT1X_IDLE_TIMEOUT { + UCHAR StaAddr[6]; + UINT32 idle_timeout; +} DOT1X_IDLE_TIMEOUT, *PDOT1X_IDLE_TIMEOUT; + +typedef struct GNU_PACKED _DOT1X_QUERY_STA_AID { + UCHAR StaAddr[MAC_ADDR_LEN]; + UINT aid; +} DOT1X_QUERY_STA_AID, *PDOT1X_QUERY_STA_AID; +#endif /* DOT1X_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +typedef struct _NDIS_AP_802_11_KEY { + UINT Length; /* Length of this structure */ + UCHAR addr[6]; + UINT KeyIndex; + UINT KeyLength; /* length of key in bytes */ + UCHAR KeyMaterial[1]; /* variable length depending on above field */ +} NDIS_AP_802_11_KEY, *PNDIS_AP_802_11_KEY; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT +typedef struct _NDIS_APCLI_802_11_KEY +{ + UINT Length; + UINT KeyIndex; + UINT KeyLength; + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_KEY_RSC KeyRSC; + UCHAR KeyMaterial[1]; +} NDIS_APCLI_802_11_KEY, *PNDIS_APCLI_802_11_KEY; +#endif/* WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +/* Key mapping keys require a BSSID */ +typedef struct _NDIS_802_11_KEY { + UINT Length; /* Length of this structure */ + UINT KeyIndex; + UINT KeyLength; /* length of key in bytes */ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_KEY_RSC KeyRSC; + UCHAR KeyMaterial[1]; /* variable length depending on above field */ +} NDIS_802_11_KEY, *PNDIS_802_11_KEY; + +typedef struct _NDIS_802_11_PASSPHRASE { + UINT KeyLength; /* length of key in bytes */ + NDIS_802_11_MAC_ADDRESS BSSID; + UCHAR KeyMaterial[1]; /* variable length depending on above field */ +} NDIS_802_11_PASSPHRASE, *PNDIS_802_11_PASSPHRASE; +#endif /* CONFIG_STA_SUPPORT */ + +typedef struct _NDIS_802_11_REMOVE_KEY { + UINT Length; /* Length of this structure */ + UINT KeyIndex; + NDIS_802_11_MAC_ADDRESS BSSID; +} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; + +typedef struct _NDIS_802_11_WEP { + UINT Length; /* Length of this structure */ + UINT KeyIndex; /* 0 is the per-client key, 1-N are the */ + /* global keys */ + UINT KeyLength; /* length of key in bytes */ + UCHAR KeyMaterial[1]; /* variable length depending on above field */ +} NDIS_802_11_WEP, *PNDIS_802_11_WEP; + + +/* Add new authentication modes */ +typedef enum _NDIS_802_11_AUTHENTICATION_MODE { + Ndis802_11AuthModeOpen, + Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, + Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, + Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, + Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeWPA1WPA2, + Ndis802_11AuthModeWPA1PSKWPA2PSK, +#ifdef WAPI_SUPPORT + Ndis802_11AuthModeWAICERT, /* WAI certificate authentication */ + Ndis802_11AuthModeWAIPSK, /* WAI pre-shared key */ +#endif /* WAPI_SUPPORT */ + Ndis802_11AuthModeMax /* Not a real mode, defined as upper bound */ +} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; + +typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; /* Set of 8 data rates */ +typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; /* Set of 16 data rates */ + +typedef struct GNU_PACKED _NDIS80211PSK +{ + UINT WPAKeyLen; + UCHAR WPAKey[64]; +} NDIS80211PSK; + +typedef struct GNU_PACKED _NDIS_802_11_SSID { + UINT SsidLength; /* length of SSID field below, in bytes; */ + /* this can be zero. */ + UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; /* SSID information field */ +} NDIS_802_11_SSID, *PNDIS_802_11_SSID; + +typedef struct GNU_PACKED _NDIS_WLAN_BSSID { + ULONG Length; /* Length of this structure */ + NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; /* SSID */ + ULONG Privacy; /* WEP encryption requirement */ + NDIS_802_11_RSSI Rssi; /* receive signal strength in dBm */ + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES SupportedRates; +} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; + +typedef struct GNU_PACKED _NDIS_802_11_BSSID_LIST { + UINT NumberOfItems; /* in list below, at least 1 */ + NDIS_WLAN_BSSID Bssid[1]; +} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; + +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + USHORT StaNum; + UCHAR ChannelUtilization; + USHORT RemainingAdmissionControl; /* in unit of 32-us */ +} QBSS_LOAD_UI, *PQBSS_LOAD_UI; + +/* Added Capabilities, IELength and IEs for each BSSID */ +typedef struct GNU_PACKED _NDIS_WLAN_BSSID_EX { + ULONG Length; /* Length of this structure */ + NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ + UCHAR WpsAP; /* 0x00: not support WPS, 0x01: support normal WPS, 0x02: support Ralink auto WPS, 0x04: support Samsung WAC */ + CHAR MinSNR; + NDIS_802_11_SSID Ssid; /* SSID */ + UINT Privacy; /* WEP encryption requirement */ + NDIS_802_11_RSSI Rssi; /* receive signal */ + /* strength in dBm */ + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES_EX SupportedRates; + ULONG IELength; + UCHAR IEs[1]; + +} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; + +typedef struct GNU_PACKED _NDIS_802_11_BSSID_LIST_EX { + UINT NumberOfItems; /* in list below, at least 1 */ + NDIS_WLAN_BSSID_EX Bssid[1]; +} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; + +typedef struct GNU_PACKED _NDIS_802_11_FIXED_IEs { + UCHAR Timestamp[8]; + USHORT BeaconInterval; + USHORT Capabilities; +} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; + +typedef struct _NDIS_802_11_VARIABLE_IEs { + UCHAR ElementID; + UCHAR Length; /* Number of bytes in data field */ + UCHAR data[1]; +} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs; + +typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD; + +typedef ULONG NDIS_802_11_RTS_THRESHOLD; + +typedef ULONG NDIS_802_11_ANTENNA; + +typedef enum _NDIS_802_11_PRIVACY_FILTER { + Ndis802_11PrivFilterAcceptAll, + Ndis802_11PrivFilter8021xWEP +} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER; + +/* Added new encryption types */ +/* Also aliased typedef to new name */ +typedef enum _NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11TKIPEnable, + Ndis802_11Encryption2Enabled = Ndis802_11TKIPEnable, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11AESEnable, + Ndis802_11Encryption3Enabled = Ndis802_11AESEnable, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11TKIPAESMix, + Ndis802_11Encryption4Enabled = Ndis802_11TKIPAESMix, /* TKIP or AES mix */ + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, +#ifdef WAPI_SUPPORT + Ndis802_11EncryptionSMS4Enabled, /* WPI SMS4 support */ +#endif /* WAPI_SUPPORT */ +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +typedef enum _NDIS_802_11_RELOAD_DEFAULTS { + Ndis802_11ReloadWEPKeys +} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; + +#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 +#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 +#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 + +#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 +#define NDIS_802_11_AI_RESFI_STATUSCODE 2 +#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 + +typedef struct _NDIS_802_11_AI_REQFI { + USHORT Capabilities; + USHORT ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; + +typedef struct _NDIS_802_11_AI_RESFI { + USHORT Capabilities; + USHORT StatusCode; + USHORT AssociationId; +} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; + +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION { + ULONG Length; + USHORT AvailableRequestFixedIEs; + NDIS_802_11_AI_REQFI RequestFixedIEs; + ULONG RequestIELength; + ULONG OffsetRequestIEs; + USHORT AvailableResponseFixedIEs; + NDIS_802_11_AI_RESFI ResponseFixedIEs; + ULONG ResponseIELength; + ULONG OffsetResponseIEs; +} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; + +typedef struct _NDIS_802_11_AUTHENTICATION_EVENT { + NDIS_802_11_STATUS_INDICATION Status; + NDIS_802_11_AUTHENTICATION_REQUEST Request[1]; +} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT; + +/* +typedef struct _NDIS_802_11_TEST +{ + ULONG Length; + ULONG Type; + union + { + NDIS_802_11_AUTHENTICATION_EVENT AuthenticationEvent; + NDIS_802_11_RSSI RssiTrigger; + }; +} NDIS_802_11_TEST, *PNDIS_802_11_TEST; + */ + +/* 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE */ +typedef enum _NDIS_802_11_MEDIA_STREAM_MODE { + Ndis802_11MediaStreamOff, + Ndis802_11MediaStreamOn, +} NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE; + +/* PMKID Structures */ +typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; + +#if defined(CONFIG_STA_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) +typedef struct _BSSID_INFO { + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +} BSSID_INFO, *PBSSID_INFO; + +typedef struct _NDIS_802_11_PMKID { + UINT Length; + UINT BSSIDInfoCount; + BSSID_INFO BSSIDInfo[1]; +} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; +#endif /* defined(CONFIG_STA_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT +typedef struct _NDIS_APCLI_802_11_PMKID +{ + UINT Length; + UINT BSSIDInfoCount; + BSSID_INFO BSSIDInfo[1]; +} NDIS_APCLI_802_11_PMKID, *PNDIS_APCLI_802_11_PMKID; +#endif/*WPA_SUPPLICANT_SUPPORT*/ +#endif /* APCLI_SUPPORT */ + +typedef struct _AP_BSSID_INFO { + NDIS_802_11_MAC_ADDRESS MAC; + NDIS_802_11_PMKID_VALUE PMKID; + UCHAR PMK[32]; + ULONG RefreshTime; + BOOLEAN Valid; +} AP_BSSID_INFO, *PAP_BSSID_INFO; + +#define MAX_PMKID_COUNT 8 +typedef struct _NDIS_AP_802_11_PMKID { + AP_BSSID_INFO BSSIDInfo[MAX_PMKID_COUNT]; +} NDIS_AP_802_11_PMKID, *PNDIS_AP_802_11_PMKID; +#endif /* CONFIG_AP_SUPPORT */ + +typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION { + NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; + NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; +} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION; + +typedef struct _NDIS_802_11_CAPABILITY { + ULONG Length; + ULONG Version; + ULONG NoOfPMKIDs; + ULONG NoOfAuthEncryptPairsSupported; + NDIS_802_11_AUTHENTICATION_ENCRYPTION + AuthenticationEncryptionSupported[1]; +} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY; + + + +#if defined(DBG) || defined(RALINK_ATE) +/* + When use private ioctl oid get/set the configuration, we can use following flags to provide specific rules when handle the cmd + */ +#define RTPRIV_IOCTL_FLAG_UI 0x0001 /* Notidy this private cmd send by UI. */ +#define RTPRIV_IOCTL_FLAG_NODUMPMSG 0x0002 /* Notify driver cannot dump msg to stdio/stdout when run this private ioctl cmd */ +#define RTPRIV_IOCTL_FLAG_NOSPACE 0x0004 /* Notify driver didn't need copy msg to caller due to the caller didn't reserve space for this cmd */ +#endif /* DBG */ + + +#ifdef SNMP_SUPPORT +/*SNMP ieee 802dot11 , 2008_0220 */ +/* dot11res(3) */ +#define RT_OID_802_11_MANUFACTUREROUI 0x0700 +#define RT_OID_802_11_MANUFACTURERNAME 0x0701 +#define RT_OID_802_11_RESOURCETYPEIDNAME 0x0702 + +/* dot11smt(1) */ +#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703 +#define RT_OID_802_11_POWERMANAGEMENTMODE 0x0704 +#define OID_802_11_WEPDEFAULTKEYVALUE 0x0705 /* read , write */ +#define OID_802_11_WEPDEFAULTKEYID 0x0706 +#define RT_OID_802_11_WEPKEYMAPPINGLENGTH 0x0707 +#define OID_802_11_SHORTRETRYLIMIT 0x0708 +#define OID_802_11_LONGRETRYLIMIT 0x0709 +#define RT_OID_802_11_PRODUCTID 0x0710 +#define RT_OID_802_11_MANUFACTUREID 0x0711 + +/* //dot11Phy(4) */ +#endif /* SNMP_SUPPORT */ + +#define OID_802_11_CURRENTCHANNEL 0x0712 + +/*dot11mac */ +#define RT_OID_802_11_MAC_ADDRESS 0x0713 +#define OID_802_11_BUILD_CHANNEL_EX 0x0714 +#define OID_802_11_GET_CH_LIST 0x0715 +#define OID_802_11_GET_COUNTRY_CODE 0x0716 +#define OID_802_11_GET_CHANNEL_GEOGRAPHY 0x0717 + +/*#define RT_OID_802_11_STATISTICS (OID_GET_SET_TOGGLE | OID_802_11_STATISTICS) */ + + + +#ifdef WSC_INCLUDED +#define RT_OID_WAC_REQ 0x0736 +#define RT_OID_WSC_AUTO_PROVISION_WITH_BSSID 0x0737 +#define RT_OID_WSC_AUTO_PROVISION 0x0738 +#ifdef WSC_LED_SUPPORT +/*WPS LED MODE 10 for Dlink WPS LED */ +#define RT_OID_LED_WPS_MODE10 0x0739 +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ +#ifdef CONFIG_STA_SUPPORT +#define RT_OID_WSC_SET_PASSPHRASE 0x0740 /* passphrase for wpa(2)-psk */ +#define RT_OID_WSC_DRIVER_AUTO_CONNECT 0x0741 +#define RT_OID_WSC_QUERY_DEFAULT_PROFILE 0x0742 +#define RT_OID_WSC_SET_CONN_BY_PROFILE_INDEX 0x0743 +#define RT_OID_WSC_SET_ACTION 0x0744 +#define RT_OID_WSC_SET_SSID 0x0745 +#define RT_OID_WSC_SET_PIN_CODE 0x0746 +#define RT_OID_WSC_SET_MODE 0x0747 /* PIN or PBC */ +#define RT_OID_WSC_SET_CONF_MODE 0x0748 /* Enrollee or Registrar */ +#define RT_OID_WSC_SET_PROFILE 0x0749 +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#define RT_OID_APCLI_WSC_PIN_CODE 0x074A +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#define RT_OID_WSC_FRAGMENT_SIZE 0x074D +#define RT_OID_WSC_V2_SUPPORT 0x074E +#define RT_OID_WSC_CONFIG_STATUS 0x074F +#define RT_OID_802_11_WSC_QUERY_PROFILE 0x0750 +/* for consistency with RT61 */ +#define RT_OID_WSC_QUERY_STATUS 0x0751 +#define RT_OID_WSC_PIN_CODE 0x0752 +#define RT_OID_WSC_UUID 0x0753 +#define RT_OID_WSC_SET_SELECTED_REGISTRAR 0x0754 +#define RT_OID_WSC_EAPMSG 0x0755 +#define RT_OID_WSC_MANUFACTURER 0x0756 +#define RT_OID_WSC_MODEL_NAME 0x0757 +#define RT_OID_WSC_MODEL_NO 0x0758 +#define RT_OID_WSC_SERIAL_NO 0x0759 +#define RT_OID_WSC_READ_UFD_FILE 0x075A +#define RT_OID_WSC_WRITE_UFD_FILE 0x075B +#define RT_OID_WSC_QUERY_PEER_INFO_ON_RUNNING 0x075C +#define RT_OID_WSC_MAC_ADDRESS 0x0760 + +#ifdef LLTD_SUPPORT +/* for consistency with RT61 */ +#define RT_OID_GET_PHY_MODE 0x761 +#ifdef CONFIG_AP_SUPPORT +#define RT_OID_GET_LLTD_ASSO_TABLE 0x762 +#ifdef APCLI_SUPPORT +#define RT_OID_GET_REPEATER_AP_LINEAGE 0x763 +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* LLTD_SUPPORT */ + +#ifdef WSC_NFC_SUPPORT +#define RT_OID_NFC_STATUS 0x0930 +#endif /* WSC_NFC_SUPPORT */ + +#ifdef CON_WPS +#define RT_OID_WSC_SET_CON_WPS_STOP 0x0764 +#endif /* CON_WPS */ + +#ifdef SMART_MESH +#define RT_OID_LAST_TX_RX_STATS 0x0765 +#define RT_OID_SET_PKT_TX_RX_STATS 0x0766 +#define RT_OID_GET_PKT_TX_RX_STATS 0x0767 +#define RT_OID_GET_AP_LIST 0x0768 +#endif /* SMART_MESH */ + + +#ifdef DOT11R_FT_SUPPORT +#define OID_802_11R_SUPPORT 0x0780 +#define OID_802_11R_MDID 0x0781 +#define OID_802_11R_R0KHID 0x0782 +#define OID_802_11R_RIC 0x0783 +#define OID_802_11R_OTD 0x0784 +#define OID_802_11R_INFO 0x0785 + +#define RT_OID_802_11R_SUPPORT (OID_GET_SET_TOGGLE | OID_802_11R_SUPPORT) +#define RT_OID_802_11R_MDID (OID_GET_SET_TOGGLE | OID_802_11R_MDID) +#define RT_OID_802_11R_R0KHID (OID_GET_SET_TOGGLE | OID_802_11R_R0KHID) +#define RT_OID_802_11R_RIC (OID_GET_SET_TOGGLE | OID_802_11R_RIC) +#define RT_OID_802_11R_OTD (OID_GET_SET_TOGGLE | OID_802_11R_OTD) +#define RT_OID_802_11R_INFO (OID_GET_SET_TOGGLE | OID_802_11R_INFO) +#endif /* DOT11R_FT_SUPPORT */ + + +/* New for MeetingHouse Api support */ +#define OID_MH_802_1X_SUPPORTED 0xFFEDC100 + +/* MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! */ +typedef union _HTTRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT MODE:3; /* Use definition MODE_xxx. */ + USHORT iTxBF:1; + USHORT eTxBF:1; + USHORT STBC:1; /* only support in HT/VHT mode with MCS0~7 */ + USHORT ShortGI:1; + USHORT BW:2; /* channel bandwidth 20MHz/40/80 MHz */ + USHORT ldpc:1; + USHORT MCS:6; /* MCS */ + } field; +#else + struct { + USHORT MCS:6; + USHORT ldpc:1; + USHORT BW:2; + USHORT ShortGI:1; + USHORT STBC:1; + USHORT eTxBF:1; + USHORT iTxBF:1; + USHORT MODE:3; + } field; +#endif + USHORT word; +} HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; + +typedef enum _RT_802_11_PREAMBLE { + Rt802_11PreambleLong, + Rt802_11PreambleShort, + Rt802_11PreambleAuto +} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE; + +typedef enum _RT_802_11_PHY_MODE { + PHY_11BG_MIXED = 0, + PHY_11B = 1, + PHY_11A = 2, + PHY_11ABG_MIXED = 3, + PHY_11G = 4, +#ifdef DOT11_N_SUPPORT + PHY_11ABGN_MIXED = 5, /* both band 5 */ + PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */ + PHY_11GN_MIXED = 7, /* 2.4G band 7 */ + PHY_11AN_MIXED = 8, /* 5G band 8 */ + PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */ + PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */ + PHY_11N_5G = 11, /* 11n-only with 5G band 11 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */ + PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */ + PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */ + PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */ +#endif /* DOT11_VHT_AC */ + PHY_MODE_MAX, +} RT_802_11_PHY_MODE; + +#ifdef DOT11_VHT_AC +#define PHY_MODE_IS_5G_BAND(__Mode) \ + ((__Mode == PHY_11A) || \ + (__Mode == PHY_11ABG_MIXED) || \ + (__Mode == PHY_11ABGN_MIXED) || \ + (__Mode == PHY_11AN_MIXED) || \ + (__Mode == PHY_11AGN_MIXED) || \ + (__Mode == PHY_11N_5G) ||\ + (__Mode == PHY_11VHT_N_MIXED) ||\ + (__Mode == PHY_11VHT_N_A_MIXED)) +#elif defined(DOT11_N_SUPPORT) +#define PHY_MODE_IS_5G_BAND(__Mode) \ + ((__Mode == PHY_11A) || \ + (__Mode == PHY_11ABG_MIXED) || \ + (__Mode == PHY_11ABGN_MIXED) || \ + (__Mode == PHY_11AN_MIXED) || \ + (__Mode == PHY_11AGN_MIXED) || \ + (__Mode == PHY_11N_5G)) +#else + +#define PHY_MODE_IS_5G_BAND(__Mode) \ + ((__Mode == PHY_11A) || \ + (__Mode == PHY_11ABG_MIXED)) +#endif /* DOT11_N_SUPPORT */ + +/* put all proprietery for-query objects here to reduce # of Query_OID */ +typedef struct _RT_802_11_LINK_STATUS { + ULONG CurrTxRate; /* in units of 0.5Mbps */ + ULONG ChannelQuality; /* 0..100 % */ + ULONG TxByteCount; /* both ok and fail */ + ULONG RxByteCount; /* both ok and fail */ + ULONG CentralChannel; /* 40MHz central channel number */ +} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS; + +#ifdef SYSTEM_LOG_SUPPORT +typedef struct _RT_802_11_EVENT_LOG { + LARGE_INTEGER SystemTime; /* timestammp via NdisGetCurrentSystemTime() */ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Event; /* EVENT_xxx */ +} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG; + +typedef struct _RT_802_11_EVENT_TABLE { + ULONG Num; + ULONG Rsv; /* to align Log[] at LARGE_INEGER boundary */ + RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT]; +} RT_802_11_EVENT_TABLE, *PRT_802_11_EVENT_TABLE; +#endif /* SYSTEM_LOG_SUPPORT */ + +/* MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! */ +typedef union _MACHTTRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT MODE:3; /* Use definition MODE_xxx. */ + USHORT iTxBF:1; + USHORT eTxBF:1; + USHORT STBC:1; /* only support in HT/VHT mode with MCS0~7 */ + USHORT ShortGI:1; + USHORT BW:2; /* channel bandwidth 20MHz/40/80 MHz */ + USHORT ldpc:1; + USHORT MCS:6; /* MCS */ + } field; +#else + struct { + USHORT MCS:6; + USHORT ldpc:1; + USHORT BW:2; + USHORT ShortGI:1; + USHORT STBC:1; + USHORT eTxBF:1; + USHORT iTxBF:1; + USHORT MODE:3; + } field; +#endif + USHORT word; +} MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; + +typedef struct _RT_802_11_MAC_ENTRY { + UCHAR ApIdx; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR Aid; + UCHAR Psm; /* 0:PWR_ACTIVE, 1:PWR_SAVE */ + UCHAR MimoPs; /* 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled */ + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + UINT32 ConnectedTime; + MACHTTRANSMIT_SETTING TxRate; + UINT32 LastRxRate; +} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY; + +typedef struct _RT_802_11_MAC_TABLE { + ULONG Num; + RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE; + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT +typedef + struct { + ULONG TxSuccessCount; + ULONG TxRetryCount; + ULONG TxFailCount; + ULONG ETxSuccessCount; + ULONG ETxRetryCount; + ULONG ETxFailCount; + ULONG ITxSuccessCount; + ULONG ITxRetryCount; + ULONG ITxFailCount; +} RT_COUNTER_TXBF; + +typedef + struct { + ULONG Num; + RT_COUNTER_TXBF Entry[MAX_NUMBER_OF_MAC]; +} RT_802_11_TXBF_TABLE; +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +/* structure for query/set hardware register - MAC, BBP, RF register */ +typedef struct _RT_802_11_HARDWARE_REGISTER { + ULONG HardwareType; /* 0:MAC, 1:BBP, 2:RF register, 3:EEPROM */ + ULONG Offset; /* Q/S register offset addr */ + ULONG Data; /* R/W data buffer */ +} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER; + +typedef struct _RT_802_11_AP_CONFIG { + ULONG EnableTxBurst; /* 0-disable, 1-enable */ + ULONG EnableTurboRate; /* 0-disable, 1-enable 72/100mbps turbo rate */ + ULONG IsolateInterStaTraffic; /* 0-disable, 1-enable isolation */ + ULONG HideSsid; /* 0-disable, 1-enable hiding */ + ULONG UseBGProtection; /* 0-AUTO, 1-always ON, 2-always OFF */ + ULONG UseShortSlotTime; /* 0-no use, 1-use 9-us short slot time */ + ULONG Rsv1; /* must be 0 */ + ULONG SystemErrorBitmap; /* ignore upon SET, return system error upon QUERY */ +} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG; + +/* structure to query/set STA_CONFIG */ +typedef struct _RT_802_11_STA_CONFIG { + ULONG EnableTxBurst; /* 0-disable, 1-enable */ + ULONG EnableTurboRate; /* 0-disable, 1-enable 72/100mbps turbo rate */ + ULONG UseBGProtection; /* 0-AUTO, 1-always ON, 2-always OFF */ + ULONG UseShortSlotTime; /* 0-no use, 1-use 9-us short slot time when applicable */ + ULONG AdhocMode; /* 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only */ + ULONG HwRadioStatus; /* 0-OFF, 1-ON, default is 1, Read-Only */ + ULONG Rsv1; /* must be 0 */ + ULONG SystemErrorBitmap; /* ignore upon SET, return system error upon QUERY */ +} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG; + +/* */ +/* For OID Query or Set about BA structure */ +/* */ +typedef struct _OID_BACAP_STRUC { + UCHAR RxBAWinLimit; + UCHAR TxBAWinLimit; + UCHAR Policy; /* 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid */ + UCHAR MpduDensity; /* 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid */ + UCHAR AmsduEnable; /*Enable AMSDU transmisstion */ + UCHAR AmsduSize; /* 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; */ + UCHAR MMPSmode; /* MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable */ + BOOLEAN AutoBA; /* Auto BA will automatically */ +} OID_BACAP_STRUC, *POID_BACAP_STRUC; + +typedef struct _RT_802_11_ACL_ENTRY { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Rsv; +} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY; + +typedef struct GNU_PACKED _RT_802_11_ACL { + ULONG Policy; /* 0-disable, 1-positive list, 2-negative list */ + ULONG Num; + RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL]; +} RT_802_11_ACL, *PRT_802_11_ACL; + +typedef struct _RT_802_11_WDS { + ULONG Num; + NDIS_802_11_MAC_ADDRESS Entry[24 /*MAX_NUM_OF_WDS_LINK */ ]; + ULONG KeyLength; + UCHAR KeyMaterial[32]; +} RT_802_11_WDS, *PRT_802_11_WDS; + +typedef struct _RT_802_11_TX_RATES_ { + UCHAR SupRateLen; + UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; + UCHAR ExtRateLen; + UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; +} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES; + +/* Definition of extra information code */ +#define GENERAL_LINK_UP 0x0 /* Link is Up */ +#define GENERAL_LINK_DOWN 0x1 /* Link is Down */ +#define HW_RADIO_OFF 0x2 /* Hardware radio off */ +#define SW_RADIO_OFF 0x3 /* Software radio off */ +#define AUTH_FAIL 0x4 /* Open authentication fail */ +#define AUTH_FAIL_KEYS 0x5 /* Shared authentication fail */ +#define ASSOC_FAIL 0x6 /* Association failed */ +#define EAP_MIC_FAILURE 0x7 /* Deauthencation because MIC failure */ +#define EAP_4WAY_TIMEOUT 0x8 /* Deauthencation on 4-way handshake timeout */ +#define EAP_GROUP_KEY_TIMEOUT 0x9 /* Deauthencation on group key handshake timeout */ +#define EAP_SUCCESS 0xa /* EAP succeed */ +#define DETECT_RADAR_SIGNAL 0xb /* Radar signal occur in current channel */ +#define EXTRA_INFO_MAX 0xb /* Indicate Last OID */ + +#define EXTRA_INFO_CLEAR 0xffffffff + +/* This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. */ +typedef struct { + RT_802_11_PHY_MODE PhyMode; /* */ + UCHAR TransmitNo; + UCHAR HtMode; /*HTMODE_GF or HTMODE_MM */ + UINT8 ExtOffset; /*extension channel above or below */ + UCHAR MCS; + UCHAR BW; + UCHAR STBC; + UCHAR SHORTGI; + UCHAR rsv; +} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE; + + +#ifdef LLTD_SUPPORT +typedef struct _RT_LLTD_ASSOICATION_ENTRY { + UCHAR Addr[MAC_ADDR_LEN]; + unsigned short MOR; /* maximum operational rate */ + UCHAR phyMode; +} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY; + +typedef struct _RT_LLTD_ASSOICATION_TABLE { + unsigned int Num; + RT_LLTD_ASSOICATION_ENTRY Entry[64]; /* sync from LLTD daemon */ +} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; +#endif /* LLTD_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +/*rt2860, 2007-0118 */ +/* structure for DLS */ +typedef struct _RT_802_11_DLS_UI { + USHORT TimeOut; /* unit: second , set by UI */ + USHORT CountDownTimer; /* unit: second , used by driver only */ + NDIS_802_11_MAC_ADDRESS MacAddr; /* set by UI */ + UCHAR Status; /* 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only */ + BOOLEAN Valid; /* 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link */ +} RT_802_11_DLS_UI, *PRT_802_11_DLS_UI; + +typedef struct _RT_802_11_DLS_INFO { + RT_802_11_DLS_UI Entry[MAX_NUMBER_OF_DLS_ENTRY]; + UCHAR num; +} RT_802_11_DLS_INFO, *PRT_802_11_DLS_INFO; + +typedef enum _RT_802_11_DLS_MODE { + DLS_NONE, + DLS_WAIT_KEY, + DLS_FINISH +} RT_802_11_DLS_MODE; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +typedef struct _RT_802_11_TDLS_UI { + USHORT TimeOut; /* unit: second , set by UI */ + USHORT CountDownTimer; /* unit: second , used by driver only */ + NDIS_802_11_MAC_ADDRESS MacAddr; /* set by UI */ + UCHAR Status; /* 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only */ + BOOLEAN Valid; /* 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link */ +} RT_802_11_TDLS_UI, *PRT_802_11_TDLS_UI; +#endif /* DOT11Z_TDLS_SUPPORT */ + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_INCLUDED +#define RT_WSC_UPNP_EVENT_FLAG 0x109 +#endif /* WSC_INCLUDED */ + + + +/*#define MAX_CUSTOM_LEN 128 */ + +#ifdef CONFIG_STA_SUPPORT +typedef enum _RT_802_11_D_CLIENT_MODE { + Rt802_11_D_None, + Rt802_11_D_Flexible, + Rt802_11_D_Strict, +} RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE; +#endif /* CONFIG_STA_SUPPORT */ + +typedef struct _RT_CHANNEL_LIST_INFO { + UCHAR ChannelList[MAX_NUM_OF_CHS]; /* list all supported channels for site survey */ + UCHAR ChannelListNum; /* number of channel in ChannelList[] */ +} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO; + +#ifdef IWSC_SUPPORT +#define IWSC_MAX_SUB_MASK_LIST_COUNT 3 +#endif /* IWSC_SUPPORT */ + +/* WSC configured credential */ +typedef struct _WSC_CREDENTIAL { + NDIS_802_11_SSID SSID; /* mandatory */ + USHORT AuthType; /* mandatory, 1: open, 2: wpa-psk, 4: shared, 8:wpa, 0x10: wpa2, 0x20: wpa2-psk */ + USHORT EncrType; /* mandatory, 1: none, 2: wep, 4: tkip, 8: aes */ + UCHAR Key[64 + 1]; /* mandatory, Maximum 64 byte */ + USHORT KeyLength; + UCHAR MacAddr[MAC_ADDR_LEN]; /* mandatory, AP MAC address */ + UCHAR KeyIndex; /* optional, default is 1 */ + UCHAR bFromUPnP; /* TRUE: This credential is from external UPnP registrar */ + UCHAR Rsvd[2]; /* Make alignment */ +#ifdef IWSC_SUPPORT + USHORT IpConfigMethod; + UINT32 RegIpv4Addr; + UINT32 Ipv4SubMask; + UINT32 EnrIpv4Addr; + UINT32 AvaIpv4SubmaskList[IWSC_MAX_SUB_MASK_LIST_COUNT]; +#endif /* IWSC_SUPPORT */ +} WSC_CREDENTIAL, *PWSC_CREDENTIAL; + +/* WSC configured profiles */ +typedef struct _WSC_PROFILE { + UINT ProfileCnt; + UINT ApplyProfileIdx; /* add by johnli, fix WPS test plan 5.1.1 */ + WSC_CREDENTIAL Profile[8]; /* Support up to 8 profiles */ +} WSC_PROFILE, *PWSC_PROFILE; + +#ifdef WAPI_SUPPORT +typedef enum _WAPI_PORT_SECURE_STATE { + WAPI_PORT_NOT_SECURED, + WAPI_PORT_SECURED, +} WAPI_PORT_SECURE_STATE, *PWAPI_PORT_SECURE_STATE; + +typedef struct _WAPI_PORT_SECURE_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT state; +} WAPI_PORT_SECURE_STRUCT, *PWAPI_PORT_SECURE_STRUCT; + +typedef struct _WAPI_UCAST_KEY_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT key_id; + UCHAR PTK[64]; /* unicast and additional key */ +} WAPI_UCAST_KEY_STRUCT, *PWAPI_UCAST_KEY_STRUCT; + +typedef struct _WAPI_MCAST_KEY_STRUCT { + UINT32 key_id; + UCHAR m_tx_iv[16]; + UCHAR key_announce[16]; + UCHAR NMK[16]; /* notify master key */ +} WAPI_MCAST_KEY_STRUCT, *PWAPI_MCAST_KEY_STRUCT; + +typedef struct _WAPI_WIE_STRUCT { + UCHAR addr[6]; + UINT32 wie_len; + UCHAR wie[90]; /* wapi information element */ +} WAPI_WIE_STRUCT, *PWAPI_WIE_STRUCT; + +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +typedef struct _FT_CONFIG_INFO { + UCHAR MdId[2]; + UCHAR R0KHId[49]; + UCHAR R0KHIdLen; + BOOLEAN FtSupport; + BOOLEAN FtRicSupport; + BOOLEAN FtOtdSupport; +} FT_CONFIG_INFO, *PFT_CONFIG_INFO; +#endif /* DOT11R_FT_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT +#define RT_ASSOC_EVENT_FLAG 0x0101 +#define RT_DISASSOC_EVENT_FLAG 0x0102 +#define RT_REQIE_EVENT_FLAG 0x0103 +#define RT_RESPIE_EVENT_FLAG 0x0104 +#define RT_ASSOCINFO_EVENT_FLAG 0x0105 +#define RT_PMKIDCAND_FLAG 0x0106 +#define RT_INTERFACE_DOWN 0x0107 +#define RT_INTERFACE_UP 0x0108 +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + + + + + +#ifdef IWSC_SUPPORT +#define RT_OID_IWSC_SELF_IPV4 0x0900 +#define RT_OID_IWSC_REGISTRAR_IPV4 0x0901 +#define RT_OID_IWSC_SMPBC_ENROLLEE_COUNT 0x0902 +#endif // IWSC_SUPPORT // + +#ifdef AIRPLAY_SUPPORT +#define OID_AIRPLAY_IE_INSERT (0x0872) +#define OID_AIRPLAY_ENABLE (0x0873) +#endif/* AIRPLAY_SUPPORT*/ + + +enum { + OID_WIFI_TEST_BBP = 0x1000, + OID_WIFI_TEST_RF = 0x1001, + OID_WIFI_TEST_RF_BANK = 0x1002, + OID_WIFI_TEST_MEM_MAP_INFO = 0x1003, + OID_WIFI_TEST_BBP_NUM = 0x1004, + OID_WIFI_TEST_RF_NUM = 0x1005, + OID_WIFI_TEST_RF_BANK_OFFSET = 0x1006, + OID_WIFI_TEST_MEM_MAP_NUM = 0x1007, + OID_WIFI_TEST_BBP32 = 0x1008, + OID_WIFI_TEST_MAC = 0x1009, + OID_WIFI_TEST_MAC_NUM = 0x1010, + OID_WIFI_TEST_E2P = 0x1011, + OID_WIFI_TEST_E2P_NUM = 0x1012, + OID_WIFI_TEST_PHY_MODE = 0x1013, + OID_WIFI_TEST_RF_INDEX = 0x1014, + OID_WIFI_TEST_RF_INDEX_OFFSET = 0x1015, +}; + +struct bbp_info { + UINT32 bbp_start; + UINT32 bbp_end; + UINT8 bbp_value[0]; +}; + +struct bbp32_info { + UINT32 bbp_start; + UINT32 bbp_end; + UINT32 bbp_value[0]; +}; + +struct rf_info { + UINT16 rf_start; + UINT16 rf_end; + UINT8 rf_value[0]; +}; + +struct rf_bank_info { + UINT8 rf_bank; + UINT16 rf_start; + UINT16 rf_end; + UINT8 rf_value[0]; +}; + +struct rf_index_info { + UINT8 rf_index; + UINT16 rf_start; + UINT16 rf_end; + UINT32 rf_value[0]; +}; + +struct mac_info { + UINT32 mac_start; + UINT32 mac_end; + UINT32 mac_value[0]; +}; + +struct mem_map_info { + u32 base; + UINT16 mem_map_start; + UINT16 mem_map_end; + UINT32 mem_map_value[0]; +}; + +struct e2p_info { + UINT16 e2p_start; + UINT16 e2p_end; + UINT16 e2p_value[0]; +}; + +struct phy_mode_info { + int data_phy; + u8 data_bw; + u8 data_ldpc; + u8 data_mcs; + u8 data_gi; + u8 data_stbc; +}; + +struct anqp_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 anqp_req_len; + UCHAR anqp_req[0]; +}; + +struct anqp_rsp_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT16 status; + UINT32 anqp_rsp_len; + UCHAR anqp_rsp[0]; +}; + +struct hs_onoff { + UINT32 ifindex; + UCHAR hs_onoff; + UCHAR event_trigger; + UCHAR event_type; +}; + +struct hs_param_setting { + UINT32 param; + UINT32 value; +}; + + +struct btm_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 btm_req_len; + UCHAR btm_req[0]; +}; + +struct btm_query_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 btm_query_len; + UCHAR btm_query[0]; +}; + +struct btm_rsp_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 btm_rsp_len; + UCHAR btm_rsp[0]; +}; + +struct proxy_arp_entry { + UINT32 ifindex; + UCHAR ip_type; + UCHAR from_ds; + UCHAR IsDAD; + UCHAR source_mac_addr[6]; + UCHAR target_mac_addr[6]; + UCHAR ip_addr[0]; +}; + +struct wnm_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 type; + UINT32 wnm_req_len; + UCHAR wnm_req[0]; +}; + +struct qosmap_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 qosmap_len; + UCHAR qosmap[0]; +}; + +struct security_type { + u32 ifindex; + u8 auth_mode; + u8 encryp_type; +}; + +#define OID_802_11_WIFI_VER 0x0920 +#define OID_802_11_HS_TEST 0x0921 +#define OID_802_11_HS_IE 0x0922 +#define OID_802_11_HS_ANQP_REQ 0x0923 +#define OID_802_11_HS_ANQP_RSP 0x0924 +#define OID_802_11_HS_ONOFF 0x0925 +#define OID_802_11_HS_PARAM_SETTING 0x0927 +#define OID_802_11_WNM_BTM_REQ 0x0928 +#define OID_802_11_WNM_BTM_QUERY 0x0929 +#define OID_802_11_WNM_BTM_RSP 0x093a +#define OID_802_11_WNM_PROXY_ARP 0x093b +#define OID_802_11_WNM_IPV4_PROXY_ARP_LIST 0x093c +#define OID_802_11_WNM_IPV6_PROXY_ARP_LIST 0x093d +#define OID_802_11_SECURITY_TYPE 0x093e +#define OID_802_11_HS_RESET_RESOURCE 0x093f +#define OID_802_11_HS_AP_RELOAD 0x0940 +#define OID_802_11_HS_BSSID 0x0941 +#define OID_802_11_HS_OSU_SSID 0x0942 +//#define OID_802_11_HS_OSU_NONTX 0x0944 +#define OID_802_11_HS_SASN_ENABLE 0x0943 +#define OID_802_11_WNM_NOTIFY_REQ 0x0944 +#define OID_802_11_QOSMAP_CONFIGURE 0x0945 +#define OID_802_11_GET_STA_HSINFO 0x0946 +#define OID_802_11_BSS_LOAD 0x0947 + +#endif /* _OID_H_ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/bb_soc.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/bb_soc.h new file mode 100644 index 000000000..3f72aae92 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/bb_soc.h @@ -0,0 +1,55 @@ + +#ifndef __BBU_SOC_H__ +#define __BBU_SOC_H__ + + +//#include "rt_config.h" + + +#define POLLING_MODE_DETECT_INTV 300 +extern void os_TCIfQuery (unsigned short query_id, void* result, void* result2); + + +typedef struct _BBUPollingMode{ + RALINK_TIMER_STRUCT PollingModeDetect; + BOOLEAN PollingModeDetectRunning; + struct work_struct PollingDataBH; + UINT32 pAd_va; + NDIS_SPIN_LOCK PollingModeLock; +}BBUPollingMode,*PBBUPollingMode; + +extern void tc3162_enable_irq(unsigned int irq); +extern void tc3162_disable_irq(unsigned int irq); +extern VOID PeriodicPollingModeDetect( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +DECLARE_TIMER_FUNCTION(PeriodicPollingModeDetect); + +extern VOID PollingModeIsr(struct work_struct *work); +/* + ======================================================================== + + Routine Description: + Trendchip DMT Trainning status detect + + Arguments: + data Point to RTMP_ADAPTER + + Return Value: + NONE + + Note: + + ======================================================================== +*/ +extern void pcieReset(void); +extern int pcieRegInitConfig(void); +extern void BBU_PCIE_Init(void); +extern VOID BBUPollingModeClose(IN RTMP_ADAPTER *pAd); +extern VOID BBUPollingModeInit(IN RTMP_ADAPTER *pAd); +extern VOID BBUPollingModeStart(IN RTMP_ADAPTER *pAd); +extern VOID BBUPrepareMAC(IN RTMP_ADAPTER *pAd, PUCHAR macaddr ); +#endif + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/pkt_meta.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/pkt_meta.h new file mode 100644 index 000000000..86b8dc266 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/pkt_meta.h @@ -0,0 +1,391 @@ +/* + +*/ + +#define MIN_NET_DEVICE_FOR_MBSSID 0x00 /*0x00,0x10,0x20,0x30 */ +#define MIN_NET_DEVICE_FOR_WDS 0x10 /*0x40,0x50,0x60,0x70 */ +#define MIN_NET_DEVICE_FOR_APCLI 0x20 +#define MIN_NET_DEVICE_FOR_MESH 0x30 + +#define MIN_NET_DEVICE_FOR_DLS 0x40 +#define MIN_NET_DEVICE_FOR_TDLS 0x50 +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +#define MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_CLI (MIN_NET_DEVICE_FOR_TDLS + 0x21) +#define MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO (MIN_NET_DEVICE_FOR_TDLS + 0x22) +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#define NET_DEVICE_REAL_IDX_MASK 0x0f /* for each operation mode, we maximum support 15 entities. */ + + +/****************************************************************************** + Packet Meta info fields + NOTE: the meta info may stored in some os-dependent packet buffer and may + have extra limitations. + 1. Linux: + a).re-use sk_budd->cb[] + b).Max space of skb->cb = 48B = [CB_OFF+38] + 2. VxWorks: + a). + b).Max space: 32!! +******************************************************************************/ +/* [CB_OFF + 0] */ +/* User Priority */ +#define RTMP_SET_PACKET_UP(_p, _prio) (PACKET_CB(_p, 0) = _prio) +#define RTMP_GET_PACKET_UP(_p) (PACKET_CB(_p, 0)) + +/* [CB_OFF + 1] */ +/* Fragment # */ +#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (PACKET_CB(_p, 1) = _num) +#define RTMP_GET_PACKET_FRAGMENTS(_p) (PACKET_CB(_p, 1)) + +/* [CB_OFF + 2] */ +/* + 0x0 ~ 0xff: index mapping to MAC_TABLE_ENTRY + for Tx, search by eth_hdr.addr1 + for Rx, get from ASIC(RxWI)/search by wlan_hdr.addr2 +*/ +#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (PACKET_CB(_p, 2) = _wdsidx) +#define RTMP_GET_PACKET_WCID(_p) (PACKET_CB(_p, 2)) + + +/* [CB_OFF + 3] */ +/* From which Interface */ +#define RTMP_SET_PACKET_IF(_p, _ifdx) (PACKET_CB(_p, 3) = _ifdx) +#define RTMP_GET_PACKET_IF(_p) (PACKET_CB(_p, 3)) +#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) \ + RTMP_SET_PACKET_IF((_p), (_bss)) +#define RTMP_SET_PACKET_NET_DEVICE_WDS(_p, _bss) \ + RTMP_SET_PACKET_IF((_p), ((_bss) + MIN_NET_DEVICE_FOR_WDS)) +#define RTMP_SET_PACKET_NET_DEVICE_APCLI(_p, _idx) \ + RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_APCLI)) +#define RTMP_SET_PACKET_NET_DEVICE_MESH(_p, _idx) \ + RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_MESH)) +#define RTMP_SET_PACKET_NET_DEVICE_P2P(_p, _idx) \ + RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_P2P_GO)) +#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p) \ + RTMP_GET_PACKET_IF((_p)) +#define RTMP_GET_PACKET_NET_DEVICE(_p) \ + RTMP_GET_PACKET_IF((_p)) + + +/* [CB_OFF + 4] */ +/* If this flag is set, it indicates that this EAPoL frame MUST be clear. */ +#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (PACKET_CB(_p, 4) = _flg) +#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (PACKET_CB(_p, 4)) + + +/* [CB_OFF + 5] */ +#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (PACKET_CB(_p, 5) = _morebit) +#define RTMP_GET_PACKET_MOREDATA(_p) (PACKET_CB(_p, 5)) + + +/* [CB_OFF + 6] */ +/* + Sepcific Pakcet Type definition +*/ +#define RTMP_PACKET_SPECIFIC_CB_OFFSET 6 + +#define RTMP_PACKET_SPECIFIC_DHCP 0x01 +#define RTMP_PACKET_SPECIFIC_EAPOL 0x02 +#define RTMP_PACKET_SPECIFIC_IPV4 0x04 +#define RTMP_PACKET_SPECIFIC_WAI 0x08 +#define RTMP_PACKET_SPECIFIC_VLAN 0x10 +#define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20 +#define RTMP_PACKET_SPECIFIC_TDLS 0x40 +#define RTMP_PACKET_SPECIFIC_DISASSOC 0x80 + +/* Specific */ +#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (PACKET_CB(_p, 6) = _flg) + +/* DHCP */ +#define RTMP_SET_PACKET_DHCP(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_DHCP); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_DHCP); \ + }while(0) +#define RTMP_GET_PACKET_DHCP(_p)\ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_DHCP) + +/* EAPOL */ +#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_EAPOL); \ + }while(0) +#define RTMP_GET_PACKET_EAPOL(_p)\ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_EAPOL) + +/* WAI */ +#define RTMP_SET_PACKET_WAI(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_WAI); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_WAI); \ + }while(0) +#define RTMP_GET_PACKET_WAI(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_WAI) + +#define RTMP_GET_PACKET_FORCE_TX(_p)\ + (PACKET_CB(_p, 6) & (RTMP_PACKET_SPECIFIC_EAPOL | \ + RTMP_PACKET_SPECIFIC_WAI)) + +#define RTMP_GET_PACKET_LOWRATE(_p) \ + (PACKET_CB(_p, 6) & (RTMP_PACKET_SPECIFIC_EAPOL |\ + RTMP_PACKET_SPECIFIC_DHCP |\ + RTMP_PACKET_SPECIFIC_WAI)) + +/* VLAN */ +#define RTMP_SET_PACKET_VLAN(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_VLAN); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_VLAN); \ + }while(0) +#define RTMP_GET_PACKET_VLAN(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_VLAN) + +/* LLC/SNAP */ +#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_LLCSNAP); \ + }while(0) + +#define RTMP_GET_PACKET_LLCSNAP(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_LLCSNAP) + +/* IP */ +#define RTMP_SET_PACKET_IPV4(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_IPV4); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_IPV4); \ + }while(0) + +#define RTMP_GET_PACKET_IPV4(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_IPV4) + +/* TDLS */ +#define RTMP_SET_PACKET_TDLS(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_TDLS); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_TDLS); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_TDLS) + +/* DISASSOC */ +#define RTMP_SET_PACKET_DISASSOC(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DISASSOC); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_DISASSOC); \ + }while(0) +#define RTMP_GET_PACKET_DISASSOC(_p) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DISASSOC) + + + +/* [CB_OFF + 7] */ +/* wdev index */ +#define RTMP_SET_PACKET_WDEV(_p, _wdev_idx) (PACKET_CB(_p, 7) = _wdev_idx) +#define RTMP_GET_PACKET_WDEV(_p) (PACKET_CB(_p, 7)) + + +/* [CB_OFF + 8 ~ 9] */ +#ifdef UAPSD_SUPPORT +/* if we queue a U-APSD packet to any software queue, we will set the U-APSD + flag and its physical queue ID for it */ +#define RTMP_SET_PACKET_UAPSD(_p, _flg_uapsd, _que_id) \ + (PACKET_CB(_p, 8) = ((_flg_uapsd<<7) | _que_id)) + +#define RTMP_SET_PACKET_QOS_NULL(_p) (PACKET_CB(_p, 8) = 0xff) +#define RTMP_GET_PACKET_QOS_NULL(_p) (PACKET_CB(_p, 8)) +#define RTMP_SET_PACKET_NON_QOS_NULL(_p) (PACKET_CB(_p, 8) = 0x00) +#define RTMP_GET_PACKET_UAPSD_Flag(_p) ((PACKET_CB(_p, 8) & 0x80) >> 7) +#define RTMP_GET_PACKET_UAPSD_QUE_ID(_p) (PACKET_CB(_p, 8) & 0x7f) + +#define RTMP_SET_PACKET_EOSP(_p, _flg) (PACKET_CB(_p, 9) = _flg) +#define RTMP_GET_PACKET_EOSP(_p) (PACKET_CB(_p, 9)) +#endif /* UAPSD_SUPPORT */ + + +/* [CB_OFF + 10 ~ 11] */ +#define RTMP_SET_PACKET_PROTOCOL(_p, _protocol) {\ + (PACKET_CB(_p, 10) = (UINT8)((_protocol) & 0x00ff)); \ + (PACKET_CB(_p, 11) = (UINT8)(((_protocol) & 0xff00) >> 8)); \ +} + +#define RTMP_GET_PACKET_PROTOCOL(_p) \ + ((((UINT16)PACKET_CB(_p, 11)) << 8) \ + | ((UINT16)PACKET_CB(_p, 10))) + + +/* [CB_OFF + 12] */ +//#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) +#define RTMP_SET_PACKET_OPMODE(_p, _flg) (PACKET_CB(_p, 12) = _flg) +#define RTMP_GET_PACKET_OPMODE(_p) (PACKET_CB(_p, 12)) +//#endif /* P2P_SUPPORT */ + + +/* [CB_OFF + 13] */ +/* TX rate index */ +#define RTMP_SET_PACKET_TXRATE(_p, _rate) (PACKET_CB(_p, 13) = _rate) +#define RTMP_GET_PACKET_TXRATE(_p) (PACKET_CB(_p, 13)) + + +/* [CB_OFF + 14] */ +#ifdef MAC_REPEATER_SUPPORT +#define RTMP_SET_PKT_MAT_FREE(_p, _flg) (PACKET_CB(_p, 14) = (_flg)) +#define RTMP_GET_PKT_MAT_FREE(_p) (PACKET_CB(_p, 14)) +#endif /* MAC_REPEATER_SUPPORT */ + + +/* [CB_OFF + 15 ~ 19] */ + +/* use bit3 of cb[CB_OFF+16] */ +#define RTMP_SET_PACKET_MGMT_PKT(_p, _flg) \ + PACKET_CB(_p, 16) = (PACKET_CB(_p, 16) & 0xF7) | ((_flg & 0x01) << 3); +#define RTMP_GET_PACKET_MGMT_PKT(_p) \ + ((PACKET_CB(_p, 16) & 0x08) >> 3) + +/* use bit0 of cb[CB_OFF+20] */ +#define RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(_p, _flg) \ + PACKET_CB(_p, 20) = (PACKET_CB(_p, 20) & 0xFE) | (_flg & 0x01); +#define RTMP_GET_PACKET_MGMT_PKT_DATA_QUE(_p) \ + (PACKET_CB(_p, 20) & 0x01) + + +/* [CB_OFF+21 ~ 22] */ + +#ifdef DATA_QUEUE_RESERVE +// tmply use mesh part! +#define RTMP_SET_PACKET_ICMP(_p, _flg) (PACKET_CB(_p, 21) = _flg) +#define RTMP_GET_PACKET_ICMP(_p) (PACKET_CB(_p, 21)) +#else /* DATA_QUEUE_RESERVE */ + + +#endif /* !DATA_QUEUE_RESERVE */ + + +/* [CB_OFF + 23] */ +/* + * TDLS Sepcific Pakcet Type definition +*/ +#define RTMP_TDLS_SPECIFIC_WAIT_ACK 0x01 +#define RTMP_TDLS_SPECIFIC_NOACK 0x02 +#define RTMP_TDLS_SPECIFIC_PKTQ_HCCA 0x04 +#define RTMP_TDLS_SPECIFIC_PKTQ_EDCA 0x08 + +#define RTMP_SET_PACKET_TDLS_WAIT_ACK(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 23) |= (RTMP_TDLS_SPECIFIC_WAIT_ACK); \ + else \ + PACKET_CB(_p, 23) &= (~RTMP_TDLS_SPECIFIC_WAIT_ACK); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS_WAIT_ACK(_p) (PACKET_CB(_p, 23) & RTMP_TDLS_SPECIFIC_WAIT_ACK) + +#define RTMP_SET_PACKET_TDLS_NO_ACK(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 23) |= (RTMP_TDLS_SPECIFIC_NOACK); \ + else \ + PACKET_CB(_p, 23) &= (~RTMP_TDLS_SPECIFIC_NOACK); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS_NO_ACK(_p) (PACKET_CB(_p, 23) & RTMP_TDLS_SPECIFIC_NOACK) + +#define RTMP_SET_TDLS_SPECIFIC_PACKET(_p, _flg) (PACKET_CB(_p, 23) = _flg) +#define RTMP_GET_TDLS_SPECIFIC_PACKET(_p) (PACKET_CB(_p, 23)) + + +/* [CB_OFF + 24] */ +#ifdef INF_AMAZON_SE +/* [CB_OFF+25], 1B, Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ +#define RTMP_SET_PACKET_NOBULKOUT(_p, _morebit) (PACKET_CB(_p, 24) = _morebit) +#define RTMP_GET_PACKET_NOBULKOUT(_p) (PACKET_CB(_p, 24)) +#else +#define RTMP_SET_PACKET_ETHTYPE(_p, _morebit) (PACKET_CB(_p, 24) = _morebit) +#define RTMP_GET_PACKET_ETHTYPE(_p) (PACKET_CB(_p, 24)) +#endif /* INF_AMAZON_SE */ +/* Max skb->cb = 48B = [CB_OFF+38] */ + + +/* [CB_OFF + 25] */ + + +/* [CB_OFF + 26] */ + + +/* [CB_OFF + 27 ~ 31] */ + + +/* [CB_OFF + 32] */ +/* RTS/CTS-to-self protection method */ +#define RTMP_SET_PACKET_RTS(_p, _num) (PACKET_CB(_p, 32) = _num) +#define RTMP_GET_PACKET_RTS(_p) (PACKET_CB(_p, 32)) +/* see RTMP_S(G)ET_PACKET_EMACTAB */ + +/* [CB_OFF + 33] */ +#ifdef CONFIG_5VT_ENHANCE +#define RTMP_SET_PACKET_5VT(_p, _flg) (PACKET_CB(_p, 33) = _flg) +#define RTMP_GET_PACKET_5VT(_p) (PACKET_CB(_p, 33)) +#endif /* CONFIG_5VT_ENHANCE */ + +/* [CB_OFF + 34] */ +#if defined (CONFIG_WIFI_PKT_FWD) +/* set link cover packet send by 5G or 2G */ +#define RTMP_PACKET_SPECIFIC_2G 0x1 +#define RTMP_PACKET_SPECIFIC_5G 0x2 +#define RTMP_PACKET_SPECIFIC_ETHER 0x4 + +#define RTMP_SET_PACKET_BAND(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 34) |= (_flg); \ + else \ + PACKET_CB(_p, 34) &= (~_flg); \ + }while(0) + +#define RTMP_GET_PACKET_BAND(_p) (PACKET_CB(_p, 34)) + +/* [CB_OFF + 35]: tag the packet received from which net device */ +#define RTMP_PACKET_RECV_FROM_2G_CLIENT 0x01 +#define RTMP_PACKET_RECV_FROM_5G_CLIENT 0x02 +#define RTMP_PACKET_RECV_FROM_2G_AP 0x04 +#define RTMP_PACKET_RECV_FROM_5G_AP 0x08 +#define RTMP_PACKET_RECV_FROM_2G_GUEST_CLIENT 0x10 +#define RTMP_PACKET_RECV_FROM_5G_GUEST_CLIENT 0x20 +#define RTMP_PACKET_RECV_FROM_2G_GUEST_AP 0x40 +#define RTMP_PACKET_RECV_FROM_5G_GUEST_AP 0x80 + +#define RTMP_SET_PACKET_RECV_FROM(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 35) |= (_flg); \ + else \ + PACKET_CB(_p, 35) &= (~_flg); \ + }while(0) + +#define RTMP_GET_PACKET_RECV_FROM(_p) (PACKET_CB(_p, 35)) + +#endif /* CONFIG_WIFI_PKT_FWD */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_drv.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_drv.h new file mode 100644 index 000000000..e9b6c5308 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_drv.h @@ -0,0 +1,901 @@ +/**************************************************************************** + * 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: + rt_drv.h + + Abstract: + Put all virtual OS related definition/structure/MACRO here except + standard ANSI C function. + + Note: + No any OS related definition/MACRO is defined here. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +/* same as rt_linux.h to warn users the two files can not be used simultaneously */ +#ifndef __RT_LINUX_H__ +#define __RT_LINUX_H__ + +#include "os/rt_linux_cmm.h" +#include +#include + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_AP_SUPPORT +#define AP_WSC_INCLUDED +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT +#define STA_WSC_INCLUDED +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#if defined(WSC_AP_SUPPORT) || defined(WSC_STA_SUPPORT) +#define WSC_INCLUDED +#endif + +/*#ifdef RTMP_USB_SUPPORT */ +typedef VOID *PUSB_DEV; +typedef VOID *purbb_t; +typedef VOID pregs; +/*typedef struct usb_ctrlrequest devctrlrequest; */ +/*#endif */ + +/*********************************************************************************** + * Profile related sections + ***********************************************************************************/ +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI +#define AP_PROFILE_PATH "/etc/Wireless/RT2860AP/RT2860AP.dat" +#define AP_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860AP/RT2860AP.bin" +#define AP_DRIVER_VERSION "3.0.0.0" +#ifdef MULTIPLE_CARD_SUPPORT +#define CARD_INFO_PATH "/etc/Wireless/RT2860AP/RT2860APCard.dat" +#endif /* MULTIPLE_CARD_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef RTMP_RBUS_SUPPORT +/* This used for rbus-based chip, maybe we can integrate it together. */ +#define RTMP_FIRMWARE_FILE_NAME "/etc_ro/Wireless/RT2860AP/RT2860AP.bin" +#define PROFILE_PATH "/etc/Wireless/RT2860i.dat" +#define AP_PROFILE_PATH_RBUS "/etc/Wireless/RT2860/RT2860.dat" +#define RT2880_AP_DRIVER_VERSION "1.0.0.0" +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI +#define STA_PROFILE_PATH "/etc/Wireless/RT2860STA/RT2860STA.dat" +#define STA_DRIVER_VERSION "3.0.0.0" +#ifdef MULTIPLE_CARD_SUPPORT +#define CARD_INFO_PATH "/etc/Wireless/RT2860STA/RT2860STACard.dat" +#endif /* MULTIPLE_CARD_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef RTMP_RBUS_SUPPORT +#define RTMP_FIRMWARE_FILE_NAME "/etc_ro/Wireless/RT2860STA/RT2860STA.bin" +#define PROFILE_PATH "/etc/Wireless/RT2860i.dat" +#define STA_PROFILE_PATH_RBUS "/etc/Wireless/RT2860/RT2860.dat" +#define RT2880_STA_DRIVER_VERSION "1.0.0.0" +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef SINGLE_SKU_V2 +#define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/RT2870STA/SingleSKU.dat" +#endif /* SINGLE_SKU_V2 */ + + +/*********************************************************************************** + * Compiler related definitions + ***********************************************************************************/ +#undef __inline +#define __inline static inline +#define IN +#define OUT +#define INOUT +#define NDIS_STATUS INT + + +/*********************************************************************************** + * OS Specific definitions and data structures + ***********************************************************************************/ +typedef void * PPCI_DEV; +typedef void * PNET_DEV; +typedef void * PNDIS_PACKET; +typedef char NDIS_PACKET; +typedef PNDIS_PACKET * PPNDIS_PACKET; +typedef ra_dma_addr_t NDIS_PHYSICAL_ADDRESS; +typedef ra_dma_addr_t * PNDIS_PHYSICAL_ADDRESS; +typedef void * NDIS_HANDLE; +typedef char * PNDIS_BUFFER; + +#undef KERN_ERR +#define KERN_ERR + + +/*********************************************************************************** + * Network related constant definitions + ***********************************************************************************/ +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +#define MAC_ADDR_LEN 6 + +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 +#define NDIS_STATUS_MICERROR 0x04 + +#define NDIS_SET_PACKET_STATUS(_p, _status) do{} while(0) +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) do{} while(0) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + + +/*********************************************************************************** + * Ralink Specific network related constant definitions + ***********************************************************************************/ +#ifdef CONFIG_STA_SUPPORT +#define NDIS_PACKET_TYPE_DIRECTED 0 +#define NDIS_PACKET_TYPE_MULTICAST 1 +#define NDIS_PACKET_TYPE_BROADCAST 2 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 3 +#define NDIS_PACKET_TYPE_PROMISCUOUS 4 +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11_VHT_AC +#ifdef NOISE_TEST_ADJUST +#define MAX_PACKETS_IN_QUEUE 2048 /*(512)*/ +#else +#define MAX_PACKETS_IN_QUEUE 1024 /*(512)*/ +#endif /* NOISE_TEST_ADJUST */ +#else +#define MAX_PACKETS_IN_QUEUE (512) +#endif /* DOT11_VHT_AC */ + + +#ifdef DATA_QUEUE_RESERVE +/* + This value must small than MAX_PACKETS_IN_QUEUE +*/ +#define FIFO_RSV_FOR_HIGH_PRIORITY 64 +#endif /* DATA_QUEUE_RESERVE */ + +/*********************************************************************************** + * OS signaling related constant definitions + ***********************************************************************************/ + +/*********************************************************************************** + * OS file operation related data structure definitions + ***********************************************************************************/ +typedef VOID * RTMP_OS_FD; + +#define IS_FILE_OPEN_ERR(_fd) RtmpOsFileIsErr((_fd)) + +#ifndef O_RDONLY +#define O_RDONLY RTMP_FILE_RDONLY +#endif /* O_RDONLY */ + +#ifndef O_WRONLY +#define O_WRONLY RTMP_FILE_WRONLY +#endif /* O_WRONLY */ + +#ifndef O_CREAT +#define O_CREAT RTMP_FILE_CREAT +#endif /* O_CREAT */ + +#ifndef O_TRUNC +#define O_TRUNC RTMP_FILE_TRUNC +#endif /* O_TRUNC */ + + +/*********************************************************************************** + * OS semaphore related data structure and definitions + ***********************************************************************************/ +#define RTCMDUp RtmpOsCmdUp + + +/*********************************************************************************** + * OS Memory Access related data structure and definitions + ***********************************************************************************/ +#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define NdisCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) +#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define NdisCmpMemory(Destination, Source, Length) memcmp(Destination, Source, Length) +#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) + +#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) +#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) + +#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) + + +/*********************************************************************************** + * OS task related data structure and definitions + ***********************************************************************************/ +#define RTMP_OS_PID ULONG /* value or pointer */ + +#define RTMP_GET_OS_PID(_a, _b) RtmpOsGetPid(&_a, _b); +#define CHECK_TASK_LEGALITY(_task) RtmpOsCheckTaskLegality(_task) +#define ATE_KILL_THREAD_PID RtmpThreadPidKill + +typedef INT (*RTMP_OS_TASK_CALLBACK)(ULONG); + + +/*********************************************************************************** + * IOCTL related definitions and data structures. + **********************************************************************************/ +#define NET_IOCTL VOID +#define PNET_IOCTL VOID * + +/* undef them to avoid compile errors in rt_symb.c */ +#undef EINVAL +#undef EOPNOTSUPP +#undef EFAULT +#undef ENETDOWN +#undef E2BIG +#undef ENOMEM +#undef EAGAIN +#undef ENOTCONN + +#define EINVAL (-RTMP_IO_EINVAL) +#define EOPNOTSUPP (-RTMP_IO_EOPNOTSUPP) +#define EFAULT (-RTMP_IO_EFAULT) +#define ENETDOWN (-RTMP_IO_ENETDOWN) +#define E2BIG (-RTMP_IO_E2BIG) +#define ENOMEM (-RTMP_IO_ENOMEM) +#define EAGAIN (-RTMP_IO_EAGAIN) +#define ENOTCONN (-RTMP_IO_ENOTCONN) + + +/*********************************************************************************** + * Timer related definitions and data structures. + **********************************************************************************/ +#define OS_HZ RtmpOsTickUnitGet() + +typedef void (*TIMER_FUNCTION)(ULONG); + +#define OS_WAIT RtmpOsWait + +#define RTMP_TIME_AFTER RtmpOsTimerAfter +#define RTMP_TIME_BEFORE RtmpOsTimerBefore + +#define ONE_TICK 1 + +#define NdisGetSystemUpTime RtmpOsGetSystemUpTime + + +/*********************************************************************************** + * OS specific cookie data structure binding to RTMP_ADAPTER + ***********************************************************************************/ + +/* do not have compile option in the structure for UTIL module */ +struct os_cookie { +#ifdef RTMP_MAC_PCI + VOID *pci_dev; + VOID *parent_pci_dev; + USHORT DeviceID; +#endif /* RTMP_MAC_PCI */ + + +#ifdef WORKQUEUE_BH + UINT32 pAd_va; +#endif /* WORKQUEUE_BH */ + + RTMP_NET_TASK_STRUCT rx_done_task; + RTMP_NET_TASK_STRUCT cmd_rsp_event_task; + RTMP_NET_TASK_STRUCT mgmt_dma_done_task; + RTMP_NET_TASK_STRUCT ac0_dma_done_task; +#ifdef RALINK_ATE + RTMP_NET_TASK_STRUCT ate_ac0_dma_done_task; +#endif /* RALINK_ATE */ + RTMP_NET_TASK_STRUCT ac1_dma_done_task; + RTMP_NET_TASK_STRUCT ac2_dma_done_task; + RTMP_NET_TASK_STRUCT ac3_dma_done_task; + RTMP_NET_TASK_STRUCT hcca_dma_done_task; + RTMP_NET_TASK_STRUCT tbtt_task; + RTMP_NET_TASK_STRUCT pretbtt_task; + +#ifdef RTMP_MAC_PCI + RTMP_NET_TASK_STRUCT fifo_statistic_full_task; +#ifdef CONFIG_ANDES_SUPPORT + RTMP_NET_TASK_STRUCT rx1_done_task; +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +#ifdef UAPSD_SUPPORT + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_task; +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +#ifdef DFS_SOFTWARE_SUPPORT + RTMP_NET_TASK_STRUCT pulse_radar_detect_task; + RTMP_NET_TASK_STRUCT width_radar_detect_task; +#endif /* DFS_SOFTWARE_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + RTMP_NET_TASK_STRUCT carrier_sense_task; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT + RTMP_NET_TASK_STRUCT dfs_task; +#endif /* DFS_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + + + RTMP_OS_PID apd_pid; /*802.1x daemon pid */ + unsigned long apd_pid_nr; +#ifdef CONFIG_AP_SUPPORT +#ifdef IAPP_SUPPORT +/* RT_SIGNAL_STRUC RTSignal; */ + RTMP_OS_PID IappPid; /*IAPP daemon pid */ + unsigned long IappPid_nr; +#endif /* IAPP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef WAPI_SUPPORT + RTMP_OS_PID wapi_pid; /*wapi daemon pid */ + unsigned long wapi_pid_nr; +#endif /* WAPI_SUPPORT */ + INT ioctl_if_type; + INT ioctl_if; +}; + +typedef struct os_cookie * POS_COOKIE; + + +/*********************************************************************************** + * OS debugging and printing related definitions and data structure + ***********************************************************************************/ +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + +#ifdef DBG +extern ULONG RTDebugLevel; +extern ULONG RTDebugFunc; + +#define DBGPRINT_RAW(Level, Fmt) \ +do{ \ + ULONG __gLevel = (Level) & 0xff;\ + ULONG __fLevel = ((Level) & 0xffffff00);\ + if (__gLevel <= RTDebugLevel) \ + { \ + if ((RTDebugFunc == 0) || \ + ((RTDebugFunc != 0) && (((__fLevel & RTDebugFunc)!= 0) || (__gLevel <= RT_DEBUG_ERROR))))\ + printk Fmt; \ + } \ +}while(0) + +#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) + + +#define DBGPRINT_ERR(Fmt) \ +{ \ + printk("ERROR!!! "); \ + printk Fmt; \ +} + +#define DBGPRINT_S(Status, Fmt) \ +{ \ + printk Fmt; \ +} +#else +#define DBGPRINT(Level, Fmt) do{}while(0) +#define DBGPRINT_RAW(Level, Fmt) do{}while(0) +#define DBGPRINT_S(Status, Fmt) do{}while(0) +#define DBGPRINT_ERR(Fmt) do{}while(0) +#endif + +#undef ASSERT +#ifdef DBG +#define ASSERT(x) \ +{ \ + if (!(x)) \ + { \ + printk(__FILE__ ":%d assert " #x "failed\n", __LINE__); \ + } \ +} +#else +#define ASSERT(x) +#endif /* DBG */ + +#ifdef DBG +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); +#else +#define hex_dump(x,y,z) +#endif /* DBG */ + + +/********************************************************************************************************* + The following code are not revised, temporary put it here. + *********************************************************************************************************/ + + +/*********************************************************************************** + * Device DMA Access related definitions and data structures. + **********************************************************************************/ +/*#ifdef RTMP_MAC_PCI*/ +#define size_t ULONG + +ra_dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction); +void linux_pci_unmap_single(void *handle, ra_dma_addr_t dma_addr, size_t size, int direction); + +#define pci_enable_msi RtmpOsPciMsiEnable +#define pci_disable_msi RtmpOsPciMsiDisable + +#define PCI_MAP_SINGLE_DEV(_handle, _ptr, _size, _sd_idx, _dir) \ + linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) + +#define PCI_UNMAP_SINGLE(_pAd, _ptr, _size, _dir) \ + linux_pci_unmap_single(((POS_COOKIE)(_pAd->OS_Cookie))->pci_dev, _ptr, _size, _dir) + +#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ + pci_alloc_consistent(_pci_dev, _size, _ptr) + +#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ + pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) +/*#endif RTMP_MAC_PCI*/ + +#define DEV_ALLOC_SKB(_pAd, _Pkt, _length) \ + _Pkt = RtmpOSNetPktAlloc(_pAd, _length); + +/*#ifdef RTMP_MAC_USB */ +/*#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (ULONG)0 */ +/*#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) */ +/*#endif RTMP_MAC_USB */ + + +/* + * ULONG + * RTMP_GetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressLow(phy_addr) (phy_addr) + +/* + * ULONG + * RTMP_GetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressHigh(phy_addr) (0) + +/* + * VOID + * RTMP_SetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressLow(phy_addr, Value) \ + phy_addr = Value; + +/* + * VOID + * RTMP_SetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressHigh(phy_addr, Value) + +#define NdisMIndicateStatus(_w, _x, _y, _z) + + + +/*********************************************************************************** + * Device Register I/O Access related definitions and data structures. + **********************************************************************************/ +#define readl RTMP_PCI_Readl +#define readw RTMP_PCI_Readw +#define readb RTMP_PCI_Readb +#define writel RTMP_PCI_Writel +#define writew RTMP_PCI_Writew +#define writeb RTMP_PCI_Writeb + +/* TODO: We can merge two readl to a function to speed up or one real/writel */ + +#ifdef RTMP_MAC_PCI +#if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(INF_AR9) || defined(IKANOS_VX_1X0) +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ +} + +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ + } \ +} + +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + UINT32 _Val; \ + _Val = SWAP32(_V); \ + writel(_Val, (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} + +#ifdef INF_VR9 +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + UINT32 _Val; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = SWAP32(Val); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((ULONG)(_V) << ((_i)*8)); \ + Val = SWAP32(Val); \ + writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ +} +#else +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#endif + +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + writew(SWAP16((_V)), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#else +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + } \ + else \ + *_pV = 0; \ +} + +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + /*if ((_R) != 0x404)*/ /* TODO:shiang-6590, depends on sw porting guide, don't acccess it now */\ + writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} + +#define RTMP_IO_FORCE_WRITE32(_A, _R, _V) \ +{ \ + /* if ((_R) != 0x404)*/ /* TODO:shiang-6590, depends on sw porting guide, don't acccess it now */\ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +#ifdef RTMP_RBUS_SUPPORT +/* This is actually system IO */ +#define RTMP_SYS_IO_READ32(_R, _pV) \ +{ \ + (*_pV = readl((void *)(_R))); \ +} + +#define RTMP_SYS_IO_WRITE32(_R, _V) \ +{ \ + writel(_V, (void *)(_R)); \ +} +#endif /* RTMP_RBUS_SUPPORT */ + + +#if defined(BRCM_6358) || defined(RALINK_2880) || defined(RALINK_3052) || defined(RALINK_2883) || defined(RTMP_RBUS_SUPPORT) || defined(MT76x2) +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((ULONG)(_V) << ((_i)*8)); \ + writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ +} +#else +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#endif /* #if defined(BRCM_6358) || defined(RALINK_2880) */ + +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#endif /* #if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) */ +#endif /* RTMP_MAC_PCI */ + + +#define pci_read_config_word RtmpOsPciConfigReadWord +#define pci_write_config_word RtmpOsPciConfigWriteWord +#define pci_read_config_dword RtmpOsPciConfigReadDWord +#define pci_write_config_dword RtmpOsPciConfigWriteDWord +#define pci_find_capability RtmpOsPciFindCapability + +#define RTMP_USB_URB_DATA_GET RtmpOsUsbUrbDataGet +#define RTMP_USB_URB_STATUS_GET RtmpOsUsbUrbStatusGet +#define RTMP_USB_URB_LEN_GET RtmpOsUsbUrbLenGet + +#define IW_SCAN_MAX_DATA RTMP_OS_MAX_SCAN_DATA_GET() + +/*********************************************************************************** + * Network Related data structure and marco definitions + ***********************************************************************************/ +#define PKTSRC_NDIS 0x7f +#define PKTSRC_DRIVER 0x0f + +#define RTMP_OS_NETDEV_GET_PHYADDR RtmpOsNetDevGetPhyAddr +#define SET_OS_PKT_NETDEV RtmpOsSetPktNetDev +#define RTMP_OS_NETDEV_GET_DEVNAME RtmpOsGetNetDevName +#define RTMP_OS_NETDEV_SET_TYPE RtmpOsSetNetDevType +#define RTMP_OS_NETDEV_SET_TYPE_MONITOR RtmpOsSetNetDevTypeMonitor + +#define QUEUE_ENTRY_TO_PACKET(pEntry) \ + (PNDIS_PACKET)(pEntry) + +#define PACKET_TO_QUEUE_ENTRY(pPacket) \ + (PQUEUE_ENTRY)(pPacket) + +#define RTMP_OS_NETDEV_STATE_RUNNING(_pNetDev) (RtmpOSNetDevIsUp(_pNetDev) == TRUE) + +#define RELEASE_NDIS_PACKET(_pReserved, _pPacket, _Status) \ +{ \ + RTMPFreeNdisPacket(_pReserved, _pPacket); \ +} + +/* + * packet helper + * - convert internal rt packet to os packet or + * os packet to rt packet + */ +extern ULONG RTPktOffsetData, RTPktOffsetLen, RTPktOffsetCB; + +#define RTPKT_TO_OSPKT(_p) (_p) +#define OSPKT_TO_RTPKT(_p) (_p) + +#define GET_OS_PKT_DATAPTR(_pkt) \ + ((UCHAR *)(*(ULONG *)((UCHAR *)_pkt + RTPktOffsetData))) + +#define SET_OS_PKT_DATAPTR \ + RtmpOsPktDataPtrAssign + +#define GET_OS_PKT_LEN(_pkt) \ + (*(UINT32 *)((UCHAR *)_pkt + RTPktOffsetLen)) + +#define SET_OS_PKT_LEN \ + RtmpOsPktLenAssign + +#define GET_OS_PKT_CB(_pkt) \ + ((UCHAR *)((UCHAR *)_pkt + RTPktOffsetCB)) + +#define GET_OS_PKT_NETDEV(_pkt) RtmpOsPktNetDevGet + +#define OS_PKT_CLONED \ + RtmpOsIsPktCloned + +#define OS_PKT_COPY \ + RtmpOsPktCopy + +#define OS_PKT_TAIL_ADJUST \ + RtmpOsPktTailAdjust + +#define OS_PKT_HEAD_BUF_EXTEND \ + RtmpOsPktHeadBufExtend + +#define OS_PKT_TAIL_BUF_EXTEND \ + RtmpOsPktTailBufExtend + +#define OS_PKT_RESERVE \ + RtmpOsPktReserve + +#define OS_PKT_CLONE(_pAd, _pkt, _src, _flag) \ + _src = RtmpOsPktClone((_pkt)); + +#define RTMP_OS_PKT_INIT RtmpOsPktInit + +extern UINT32 RtmpOsGetUnaligned32( + IN UINT32 *pWord); + +extern ULONG RtmpOsGetUnalignedlong( + IN ULONG *pWord); + +#define get_unaligned RtmpOsGetUnaligned +#define get_unaligned32 RtmpOsGetUnaligned32 +#define get_unalignedlong RtmpOsGetUnalignedlong + +#define OS_NTOHS RtmpOsNtohs +#define OS_HTONS RtmpOsHtons +#define OS_NTOHL RtmpOsNtohl +#define OS_HTONL RtmpOsHtonl + +#ifndef ntohs +#define ntohs OS_NTOHS +#endif /* ntohs */ +#ifndef htons +#define htons OS_HTONS +#endif /* htons */ +#ifndef ntohl +#define ntohl OS_NTOHL +#endif /* ntohl */ +#ifndef htonl +#define htonl OS_HTONL +#endif /* htonl */ + +#define RTMP_OS_NETDEV_START_QUEUE RtmpOsNetQueueStart +#define RTMP_OS_NETDEV_STOP_QUEUE RtmpOsNetQueueStop +#define RTMP_OS_NETDEV_WAKE_QUEUE RtmpOsNetQueueWake + + +#define CB_OFF 10 + +#define PACKET_CB_ASSIGN(_p, _offset) \ + (*((UINT8 *)_p + RTPktOffsetCB + _offset)) + +#define PACKET_CB(_p, _offset) \ + (*((UINT8 *)_p + RTPktOffsetCB + CB_OFF + _offset)) + + + + +/*********************************************************************************** + * Other function prototypes definitions + ***********************************************************************************/ +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); + + +#ifdef RTMP_RBUS_SUPPORT +#ifndef CONFIG_RALINK_FLASH_API +void FlashWrite(UCHAR * p, ULONG a, ULONG b); +void FlashRead(UCHAR * p, ULONG a, ULONG b); +#endif /* CONFIG_RALINK_FLASH_API */ + +int wl_proc_init(void); +int wl_proc_exit(void); + +#ifdef LINUX +#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) +extern volatile unsigned long classifier_cur_cycle; +extern int (*ra_classifier_hook_rx) (struct sk_buff *skb, unsigned long cycle); +#endif /* defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) */ +#endif /* LINUX */ +#endif /* RTMP_RBUS_SUPPORT */ + + + + +#ifdef RALINK_ATE +/****************************************************************************** + + ATE related definitions + +******************************************************************************/ +#define ate_print printk +#define ATEDBGPRINT DBGPRINT +#ifdef RTMP_MAC_PCI +#ifdef CONFIG_AP_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860AP/e2p.bin" +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + +#endif /* RALINK_ATE */ + + +/* OS definition re-declaration */ +#ifndef NULL +#define NULL 0 +#endif + +#ifndef ETH_P_IPV6 +#define ETH_P_IPV6 0x86DD +#endif + +#ifndef ETH_P_IP +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#endif + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +#undef KERN_EMERG +#define KERN_EMERG +#undef KERN_WARNING +#define KERN_WARNING + +#undef copy_from_user +#undef copy_to_user + +#define RTMP_OS_MAX_SCAN_DATA_GET RtmpOsMaxScanDataGet +#define vmalloc RtmpOsVmalloc +#define vfree RtmpOsVfree +#define copy_from_user RtmpOsCopyFromUser +#define copy_to_user RtmpOsCopyToUser +#define simple_strtol RtmpOsSimpleStrtol + +#undef atomic_read +#undef atomic_dec +#undef InterlockedExchange +#define atomic_read RtmpOsAtomicRead +#define atomic_dec RtmpOsAtomicDec +#define InterlockedExchange RtmpOsAtomicInterlockedExchange + +extern int sprintf(char * buf, const char * fmt, ...); +extern int sscanf(const char *, const char *, ...); + +#define printk pRaOsOps->ra_printk +#define snprintf pRaOsOps->ra_snprintf + +#define RA_WEXT 0 +#define RA_NETLINK 1 + +#endif /* __RT_LINUX_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_linux.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_linux.h new file mode 100644 index 000000000..b940de694 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_linux.h @@ -0,0 +1,1596 @@ +/**************************************************************************** + + Module Name: + rt_linux.h + + Abstract: + Any OS related definition/MACRO is defined here. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RT_LINUX_H__ +#define __RT_LINUX_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef INF_PPA_SUPPORT +#include +#include +#endif /* INF_PPA_SUPPORT */ + +/* load firmware */ +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include /* for get_unaligned() */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#include +#endif + +#ifdef RT_CFG80211_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) +#include +//#define EXT_BUILD_CHANNEL_LIST /* must define with CRDA */ +#else /* LINUX_VERSION_CODE */ +#undef RT_CFG80211_SUPPORT +#endif /* LINUX_VERSION_CODE */ +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef MAT_SUPPORT +#include +#include +#include +#endif /* MAT_SUPPORT */ + +/* must put the definition before include "os/rt_linux_cmm.h" */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#define KTHREAD_SUPPORT 1 +#endif /* LINUX_VERSION_CODE */ + +#ifdef KTHREAD_SUPPORT +#include +#include +#endif /* KTHREAD_SUPPORT */ + + +#include "os/rt_linux_cmm.h" + +#ifdef RT_CFG80211_SUPPORT +#include "cfg80211.h" +#endif /* RT_CFG80211_SUPPORT */ + +#include + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_AP_SUPPORT +#define AP_WSC_INCLUDED +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT +#define STA_WSC_INCLUDED +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#if defined(WSC_AP_SUPPORT) || defined(WSC_STA_SUPPORT) +#define WSC_INCLUDED +#endif + +#ifdef KTHREAD_SUPPORT +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) +#error "This kerne version doesn't support kthread!!" +#endif +#endif /* KTHREAD_SUPPORT */ + +/*#ifdef RTMP_USB_SUPPORT // os abl move */ +typedef struct usb_device *PUSB_DEV; +typedef struct urb *purbb_t; +typedef struct usb_ctrlrequest devctrlrequest; +/*#endif */ + +/*********************************************************************************** + * Profile related sections + ***********************************************************************************/ +#ifdef CONFIG_AP_SUPPORT + +#ifdef RTMP_MAC_PCI + #define AP_PROFILE_PATH_RBUS "/etc/Wireless/RT2860/RT2860AP.dat" +#if (CONFIG_RT_FIRST_CARD == 7602 || CONFIG_RT_FIRST_CARD == 7612 || CONFIG_RT_FIRST_CARD == 7620) + #define AP_PROFILE_PATH "/etc/Wireless/RT2860/RT2860AP.dat" + #define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/RT2860/SingleSKU.dat" + #define CARD_INFO_PATH "/etc/Wireless/RT2860/RT2860APCard.dat" +#else + #define AP_PROFILE_PATH "/etc/wireless/mt7615/mt7615.2.dat" + #define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/iNIC/SingleSKU.dat" + #define CARD_INFO_PATH "/etc/Wireless/iNIC/RT2860APCard.dat" +#endif +#define AP_DRIVER_VERSION "3.0.5.0" +#endif /* RTMP_MAC_PCI */ + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + +#ifdef RTMP_MAC_PCI + #define STA_PROFILE_PATH_RBUS "/etc/Wireless/RT2860/RT2860STA.dat" +#if (CONFIG_RT_FIRST_CARD == 7602 || CONFIG_RT_FIRST_CARD == 7612 || CONFIG_RT_FIRST_CARD == 7620) + #define STA_PROFILE_PATH "/etc/Wireless/RT2860/RT2860STA.dat" + #define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/RT2860/SingleSKU.dat" + #define CARD_INFO_PATH "/etc/Wireless/RT2860/RT2860STACard.dat" +#else + #define STA_PROFILE_PATH "/etc/Wireless/iNIC/iNIC_sta.dat" + #define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/iNIC/SingleSKU.dat" + #define CARD_INFO_PATH "/etc/Wireless/iNIC/RT2860STACard.dat" +#endif +#define STA_DRIVER_VERSION "3.0.1.0" +#endif /* RTMP_MAC_PCI */ + +extern const struct iw_handler_def rt28xx_iw_handler_def; + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern const struct iw_handler_def rt28xx_ap_iw_handler_def; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +/*********************************************************************************** + * Compiler related definitions + ***********************************************************************************/ +#undef __inline +#define __inline static inline +#define IN +#define OUT +#define INOUT +#define NDIS_STATUS INT + + +/*********************************************************************************** + * OS Specific definitions and data structures + ***********************************************************************************/ +typedef struct net_device_stats NET_DEV_STATS; +typedef struct pci_dev * PPCI_DEV; +typedef struct net_device * PNET_DEV; +typedef struct wireless_dev * PWIRELESS_DEV; +typedef void * PNDIS_PACKET; +typedef char NDIS_PACKET; +typedef PNDIS_PACKET * PPNDIS_PACKET; +typedef ra_dma_addr_t NDIS_PHYSICAL_ADDRESS; +typedef ra_dma_addr_t * PNDIS_PHYSICAL_ADDRESS; +typedef void * NDIS_HANDLE; +typedef char * PNDIS_BUFFER; + +typedef struct ifreq NET_IOCTL; +typedef struct ifreq * PNET_IOCTL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +typedef struct pid * RTMP_OS_PID; +#else +typedef pid_t RTMP_OS_PID; +#endif + +typedef struct semaphore OS_SEM; + +typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev); + +#ifdef RTMP_MAC_PCI +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif /* PCI_DEVICE */ +#endif /* RTMP_MAC_PCI */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RT_MOD_INC_USE_COUNT() \ + if (!try_module_get(THIS_MODULE)) \ + { \ + DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __FUNCTION__)); \ + return -1; \ + } + +#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); +#else +#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT; +#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT; +#endif + +#define RTMP_INC_REF(_A) 0 +#define RTMP_DEC_REF(_A) 0 +#define RTMP_GET_REF(_A) 0 + + +#if WIRELESS_EXT >= 12 +/* This function will be called when query /proc */ +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev); +#endif + + +/*********************************************************************************** + * Network related constant definitions + ***********************************************************************************/ +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +#define MAC_ADDR_LEN 6 + +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 +#define NDIS_STATUS_MICERROR 0x04 + +#define NDIS_SET_PACKET_STATUS(_p, _status) do{} while(0) +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) do{} while(0) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + + +/*********************************************************************************** + * Ralink Specific network related constant definitions + ***********************************************************************************/ +#ifdef CONFIG_STA_SUPPORT +#define NDIS_PACKET_TYPE_DIRECTED 0 +#define NDIS_PACKET_TYPE_MULTICAST 1 +#define NDIS_PACKET_TYPE_BROADCAST 2 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 3 +#define NDIS_PACKET_TYPE_PROMISCUOUS 4 +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11_VHT_AC +#ifdef NOISE_TEST_ADJUST +#define MAX_PACKETS_IN_QUEUE 2048 /*(512)*/ +#else +#define MAX_PACKETS_IN_QUEUE 1024 /*(512)*/ +#endif /* NOISE_TEST_ADJUST */ +#else +#define MAX_PACKETS_IN_QUEUE (512) +#endif /* DOT11_VHT_AC */ + + +#ifdef DATA_QUEUE_RESERVE +/* + This value must small than MAX_PACKETS_IN_QUEUE +*/ +#define FIFO_RSV_FOR_HIGH_PRIORITY 64 +#endif /* DATA_QUEUE_RESERVE */ + + +/*********************************************************************************** + * OS signaling related constant definitions + ***********************************************************************************/ + + +/*********************************************************************************** + * OS file operation related data structure definitions + ***********************************************************************************/ +typedef struct file* RTMP_OS_FD; + +typedef struct _OS_FS_INFO_ +{ + uid_t fsuid; + gid_t fsgid; + mm_segment_t fs; +} OS_FS_INFO; + +#define IS_FILE_OPEN_ERR(_fd) ((_fd == NULL) || IS_ERR((_fd))) + + +/*********************************************************************************** + * OS semaphore related data structure and definitions + ***********************************************************************************/ +struct os_lock { + spinlock_t lock; + unsigned long flags; +}; + +typedef spinlock_t OS_NDIS_SPIN_LOCK; + +/* */ +/* spin_lock enhanced for Nested spin lock */ +/* */ +#define OS_NdisAllocateSpinLock(__lock) \ +{ \ + spin_lock_init((spinlock_t *)(__lock)); \ +} + +#define OS_NdisFreeSpinLock(lock) \ + do{}while(0) + + +#define OS_SEM_LOCK(__lock) \ +{ \ + spin_lock_bh((spinlock_t *)(__lock)); \ +} + +#define OS_SEM_UNLOCK(__lock) \ +{ \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} + + +/* sample, use semaphore lock to replace IRQ lock, 2007/11/15 */ +#ifdef MULTI_CORE_SUPPORT + +#define OS_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + typecheck(unsigned long, __irqflags); \ + spin_lock_irqsave((spinlock_t *)(__lock), __irqflags); \ +} + +#define OS_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_irqrestore((spinlock_t *)(__lock), __irqflag); \ +} +#else +#define OS_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + typecheck(unsigned long, __irqflags); \ + spin_lock_bh((spinlock_t *)(__lock)); \ +} + +#define OS_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} +#endif // MULTI_CORE_SUPPORT // +#define OS_INT_LOCK(__lock, __irqflags) \ +{ \ + spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \ +} + +#define OS_INT_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ +} + +#define OS_NdisAcquireSpinLock OS_SEM_LOCK +#define OS_NdisReleaseSpinLock OS_SEM_UNLOCK + +/* + Following lock/unlock definition used for BBP/RF register read/write. + Currently we don't use it to protect MAC register access. + + For USB: + we use binary semaphore to do the protection because all register + access done in kernel thread and should allow task go sleep when + in protected status. + + For PCI/PCI-E/RBUS: + We use interrupt to do the protection because the register may accessed + in thread/tasklet/timer/inteerupt, so we use interrupt_disable to protect + the access. +*/ +#define RTMP_MCU_RW_LOCK(_pAd, _irqflags) \ + do{ \ + if (_pAd->infType == RTMP_DEV_INF_USB) \ + {\ + RTMP_SEM_EVENT_WAIT(&_pAd->McuCmdSem, _irqflags);\ + }\ + else\ + {\ + RTMP_SEM_LOCK(&_pAd->McuCmdLock, _irqflags);\ + }\ + }while(0) + +#define RTMP_MCU_RW_UNLOCK(_pAd, _irqflags) \ + do{ \ + if(_pAd->infType == RTMP_DEV_INF_USB)\ + { \ + RTMP_SEM_EVENT_UP(&_pAd->McuCmdSem);\ + } \ + else\ + {\ + RTMP_SEM_UNLOCK(&_pAd->McuCmdLock, _irqflags);\ + }\ + }while(0) + + +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif + +#define OS_SEM_EVENT_INIT_LOCKED(_pSema) sema_init((_pSema), 0) +#define OS_SEM_EVENT_INIT(_pSema) sema_init((_pSema), 1) +#define OS_SEM_EVENT_DESTORY(_pSema) do{}while(0) +#define OS_SEM_EVENT_WAIT(_pSema, _status) ((_status) = down_interruptible((_pSema))) +#define OS_SEM_EVENT_UP(_pSema) up(_pSema) + +#define RTCMDUp OS_RTCMDUp + +#ifdef KTHREAD_SUPPORT +#define RTMP_WAIT_EVENT_INTERRUPTIBLE(_Status, _pTask) \ +do { \ + wait_event_interruptible(_pTask->kthread_q, \ + _pTask->kthread_running || kthread_should_stop()); \ + _pTask->kthread_running = FALSE; \ + if (kthread_should_stop()) \ + { \ + (_Status) = -1; \ + break; \ + } \ + else (_Status) = 0; \ +} while(0) +#endif + +#ifdef KTHREAD_SUPPORT +#define WAKE_UP(_pTask) \ + do{ \ + if ((_pTask)->kthread_task) \ + { \ + (_pTask)->kthread_running = TRUE; \ + wake_up(&(_pTask)->kthread_q); \ + } \ + }while(0) +#endif + +/*********************************************************************************** + * OS Memory Access related data structure and definitions + ***********************************************************************************/ +#define MEM_ALLOC_FLAG (GFP_ATOMIC) /*(GFP_DMA | GFP_ATOMIC) */ + +#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define NdisCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) +#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define NdisCmpMemory(Destination, Source, Length) memcmp(Destination, Source, Length) +#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) + +#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) +#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) + +#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) + + +/*********************************************************************************** + * OS task related data structure and definitions + ***********************************************************************************/ +#define RTMP_OS_MGMT_TASK_FLAGS CLONE_VM + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +/*typedef struct pid * THREAD_PID; // no use */ +#define THREAD_PID_INIT_VALUE NULL +/* TODO: Use this IOCTL carefully when linux kernel version larger than 2.6.27, because the PID only correct when the user space task do this ioctl itself. */ +/*#define RTMP_GET_OS_PID(_x, _y) _x = get_task_pid(current, PIDTYPE_PID); */ +#define RT_GET_OS_PID(_x, _y) do {rcu_read_lock(); _x = current->thread_pid; rcu_read_unlock(); } while (0) +#ifdef OS_ABL_FUNC_SUPPORT +#define RTMP_GET_OS_PID(_a, _b) RtmpOsGetPid(&_a, _b) +#else +#define RTMP_GET_OS_PID(_a, _b) RT_GET_OS_PID(_a, _b) +#endif /* OS_ABL_FUNC_SUPPORT */ +#define GET_PID_NUMBER(_v) pid_nr((_v)) +#define CHECK_PID_LEGALITY(_pid) if (pid_nr((_pid)) > 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_pid((_A), (_B), (_C)) +#else +/*typedef pid_t THREAD_PID; // no use */ +#define THREAD_PID_INIT_VALUE -1 +#define RT_GET_OS_PID(_x, _pid) _x = _pid +#define RTMP_GET_OS_PID(_x, _pid) _x = _pid +#define GET_PID_NUMBER(_v) (_v) +#define CHECK_PID_LEGALITY(_pid) if ((_pid) >= 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_proc((_A), (_B), (_C)) +#endif + +#define ATE_KILL_THREAD_PID(PID) KILL_THREAD_PID(PID, SIGTERM, 1) + +typedef int (*cast_fn)(void *); +typedef INT (*RTMP_OS_TASK_CALLBACK)(ULONG); + +#ifdef WORKQUEUE_BH +typedef struct work_struct OS_NET_TASK_STRUCT; +typedef struct work_struct *POS_NET_TASK_STRUCT; +#else +typedef struct tasklet_struct OS_NET_TASK_STRUCT; +typedef struct tasklet_struct *POS_NET_TASK_STRUCT; +#endif /* WORKQUEUE_BH */ + +/*********************************************************************************** + * Timer related definitions and data structures. + **********************************************************************************/ +#define OS_HZ HZ + +typedef struct timer_list OS_NDIS_MINIPORT_TIMER; +typedef struct timer_list OS_TIMER; + +typedef void (*TIMER_FUNCTION)(struct timer_list *); + + +#define OS_WAIT(_time) \ +{ \ + if (in_interrupt()) \ + {\ + RtmpusecDelay(_time * 1000);\ + }else \ + {\ + int _i; \ + long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ + wait_queue_head_t _wait; \ + init_waitqueue_head(&_wait); \ + for (_i=0; _i<(_loop); _i++) \ + wait_event_interruptible_timeout(_wait, 0, ONE_TICK); \ + }\ +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RTMP_TIME_AFTER(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(b) - (long)(a) < 0)) + +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#else +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#define RTMP_TIME_AFTER(a,b) time_after(a, b) +#endif + +#define ONE_TICK 1 + +static inline void NdisGetSystemUpTime(ULONG *time) +{ + *time = jiffies; +} + + +/*********************************************************************************** + * OS specific cookie data structure binding to RTMP_ADAPTER + ***********************************************************************************/ + +struct os_cookie { +#ifdef RTMP_MAC_PCI + struct pci_dev *pci_dev; + struct pci_dev *parent_pci_dev; + USHORT DeviceID; +#endif /* RTMP_MAC_PCI */ + + +#ifdef WORKQUEUE_BH + UINT32 pAd_va; +#endif /* WORKQUEUE_BH */ + + RTMP_NET_TASK_STRUCT rx_done_task; + RTMP_NET_TASK_STRUCT cmd_rsp_event_task; + RTMP_NET_TASK_STRUCT mgmt_dma_done_task; + RTMP_NET_TASK_STRUCT ac0_dma_done_task; +#ifdef RALINK_ATE + RTMP_NET_TASK_STRUCT ate_ac0_dma_done_task; +#endif /* RALINK_ATE */ + RTMP_NET_TASK_STRUCT ac1_dma_done_task; + RTMP_NET_TASK_STRUCT ac2_dma_done_task; + RTMP_NET_TASK_STRUCT ac3_dma_done_task; + RTMP_NET_TASK_STRUCT hcca_dma_done_task; + RTMP_NET_TASK_STRUCT tbtt_task; + RTMP_NET_TASK_STRUCT pretbtt_task; + +#ifdef RTMP_MAC_PCI + RTMP_NET_TASK_STRUCT fifo_statistic_full_task; +#ifdef CONFIG_ANDES_SUPPORT + RTMP_NET_TASK_STRUCT rx1_done_task; +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +#ifdef UAPSD_SUPPORT + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_task; +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +#ifdef DFS_SOFTWARE_SUPPORT + RTMP_NET_TASK_STRUCT pulse_radar_detect_task; + RTMP_NET_TASK_STRUCT width_radar_detect_task; +#endif /* DFS_SOFTWARE_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + RTMP_NET_TASK_STRUCT carrier_sense_task; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT + struct tasklet_struct dfs_task; +#endif /* DFS_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + + + RTMP_OS_PID apd_pid; /*802.1x daemon pid */ + unsigned long apd_pid_nr; +#ifdef CONFIG_AP_SUPPORT +#ifdef IAPP_SUPPORT +/* RT_SIGNAL_STRUC RTSignal; */ + RTMP_OS_PID IappPid; /*IAPP daemon pid */ + unsigned long IappPid_nr; +#endif /* IAPP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef WAPI_SUPPORT + RTMP_OS_PID wapi_pid; /*wapi daemon pid */ + unsigned long wapi_pid_nr; +#endif /* WAPI_SUPPORT */ + INT ioctl_if_type; + INT ioctl_if; +}; + +typedef struct os_cookie * POS_COOKIE; + + + +/*********************************************************************************** + * OS debugging and printing related definitions and data structure + ***********************************************************************************/ +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + +#ifdef DBG +extern ULONG RTDebugLevel; +extern ULONG RTDebugFunc; + +#define DBGPRINT_RAW(Level, Fmt) \ +do{ \ + ULONG __gLevel = (Level) & 0xff;\ + ULONG __fLevel = ((Level) & 0xffffff00);\ + if (__gLevel <= RTDebugLevel) \ + { \ + if ((RTDebugFunc == 0) || \ + ((RTDebugFunc != 0) && (((__fLevel & RTDebugFunc)!= 0) || (__gLevel <= RT_DEBUG_ERROR))))\ + printk Fmt; \ + } \ +}while(0) + +#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) + + +#define DBGPRINT_ERR(Fmt) \ +{ \ + printk("ERROR!!! "); \ + printk Fmt; \ +} + +#define DBGPRINT_S(Status, Fmt) \ +{ \ + printk Fmt; \ +} +#else +#define DBGPRINT(Level, Fmt) do{}while(0) +#define DBGPRINT_RAW(Level, Fmt) do{}while(0) +#define DBGPRINT_S(Status, Fmt) do{}while(0) +#define DBGPRINT_ERR(Fmt) do{}while(0) +#endif + +#undef ASSERT +#ifdef DBG +#define ASSERT(x) \ +{ \ + if (!(x)) \ + { \ + printk(KERN_WARNING __FILE__ ":%d assert " #x "failed\n", __LINE__); \ + } \ +} +#else +#define ASSERT(x) +#endif /* DBG */ + +#ifdef DBG +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); +#else +#define hex_dump(x,y,z) +#endif /* DBG */ + + +/********************************************************************************************************* + The following code are not revised, temporary put it here. + *********************************************************************************************************/ + + +/*********************************************************************************** + * Device DMA Access related definitions and data structures. + **********************************************************************************/ +ra_dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction); +void linux_pci_unmap_single(void *handle, ra_dma_addr_t dma_addr, size_t size, int direction); + +#define PCI_MAP_SINGLE_DEV(_handle, _ptr, _size, _sd_idx, _dir) \ + linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) + +#define PCI_UNMAP_SINGLE(_pAd, _ptr, _size, _dir) \ + linux_pci_unmap_single(((POS_COOKIE)(_pAd->OS_Cookie))->pci_dev, _ptr, _size, _dir) + +#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ + pci_alloc_consistent(_pci_dev, _size, _ptr) + +#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ + pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) + +#ifdef VENDOR_FEATURE2_SUPPORT +#define DEV_ALLOC_SKB(_pAd, _Pkt, _length) \ + _Pkt = dev_alloc_skb(_length); \ + if (_Pkt != NULL) {MEM_DBG_PKT_ALLOC_INC(_Pkt);}; +#else + +#define DEV_ALLOC_SKB(_pAd, _Pkt, _length) \ + _Pkt = dev_alloc_skb(_length); +#endif /* VENDOR_FEATURE2_SUPPORT */ + +/*#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (ULONG)0 */ +/*#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) */ + + +/* + * ULONG + * RTMP_GetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress) + +/* + * ULONG + * RTMP_GetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0) + +/* + * VOID + * RTMP_SetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \ + PhysicalAddress = Value; + +/* + * VOID + * RTMP_SetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value) + +#define NdisMIndicateStatus(_w, _x, _y, _z) + + + +/*********************************************************************************** + * Device Register I/O Access related definitions and data structures. + **********************************************************************************/ +#ifdef RTMP_MAC_PCI +#if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(INF_AR9) || defined(IKANOS_VX_1X0) +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*(_pV) = SWAP32(*((UINT32 *)(_pV)))); \ +} + +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*(_pV) = SWAP32(*((UINT32 *)(_pV)))); \ + } \ +} + +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*(_pV) = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define _RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + UINT32 _Val; \ + _Val = SWAP32(_V); \ + writel(_Val, (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} + +#ifdef INF_VR9 +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + UINT32 _Val; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = SWAP32(Val); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((ULONG)(_V) << ((_i)*8)); \ + Val = SWAP32(Val); \ + writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ +} +#else +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#endif + +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + writew(SWAP16((_V)), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#else +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + } \ + else \ + *(_pV) = 0; \ +} + +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#if defined(BRCM_6358) || defined(RALINK_2880) || defined(RALINK_3052) || defined(RALINK_2883) || defined(RTMP_RBUS_SUPPORT) +#define RTMP_IO_READ8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = (Val >> ((_i)*8)) & (0x000000ff); \ + *((PUCHAR)_V) = (UCHAR) Val; \ +} +#else +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*(_pV) = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} +#endif /* #if defined(BRCM_6358) || defined(RALINK_2880) */ + +#define _RTMP_IO_WRITE32(_A, _R, _V) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ +}while(0) + +#define RTMP_IO_FORCE_WRITE32(_A, _R, _V) \ +{ \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +/* This is actually system IO */ +#define RTMP_SYS_IO_READ32(_R, _pV) \ +{ \ + (*_pV = readl((void *)(_R))); \ +} + +#define RTMP_SYS_IO_WRITE32(_R, _V) \ +{ \ + writel(_V, (void *)(_R)); \ +} + + + +#if defined(BRCM_6358) || defined(RALINK_2880) || defined(RALINK_3052) || defined(RALINK_2883) || defined(RTMP_RBUS_SUPPORT) || defined(MT76x2) +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((ULONG)(_V) << ((_i)*8)); \ + writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ +} +#else +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#endif /* #if defined(BRCM_6358) || defined(RALINK_2880) */ + +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#endif /* #if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) */ + + +#ifndef VENDOR_FEATURE3_SUPPORT +#define RTMP_IO_WRITE32 _RTMP_IO_WRITE32 +#endif /* VENDOR_FEATURE3_SUPPORT */ + +#endif /* RTMP_MAC_PCI */ + + +#define RTMP_USB_URB_DATA_GET(__pUrb) ((purbb_t)__pUrb)->context +#define RTMP_USB_URB_STATUS_GET(__pUrb) ((purbb_t)__pUrb)->status +#define RTMP_USB_URB_LEN_GET(__pUrb) ((purbb_t)__pUrb)->actual_length + +/*********************************************************************************** + * Network Related data structure and marco definitions + ***********************************************************************************/ +#define PKTSRC_NDIS 0x7f +#define PKTSRC_DRIVER 0x0f + +#define RTMP_OS_NETDEV_STATE_RUNNING(_pNetDev) ((_pNetDev)->flags & IFF_UP) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#define _RTMP_OS_NETDEV_GET_PRIV(_pNetDev) (NULL /*(_pNetDev)->ml_priv*/) +#else +#define _RTMP_OS_NETDEV_GET_PRIV(_pNetDev) ((_pNetDev)->priv) +#endif + +#define RTMP_OS_NETDEV_GET_DEVNAME(_pNetDev) ((_pNetDev)->name) +#define RTMP_OS_NETDEV_GET_PHYADDR(_pNetDev) ((_pNetDev)->dev_addr) + +/* Get & Set NETDEV interface hardware type */ +#define RTMP_OS_NETDEV_GET_TYPE(_pNetDev) ((_pNetDev)->type) +#define RTMP_OS_NETDEV_SET_TYPE(_pNetDev, _type) ((_pNetDev)->type = (_type)) +#define RTMP_OS_NETDEV_SET_TYPE_MONITOR(_pNetDev) RTMP_OS_NETDEV_SET_TYPE(_pNetDev, ARPHRD_IEEE80211_PRISM) + +#define RTMP_OS_NETDEV_START_QUEUE(_pNetDev) netif_start_queue((_pNetDev)) +#define RTMP_OS_NETDEV_STOP_QUEUE(_pNetDev) netif_stop_queue((_pNetDev)) +#define RTMP_OS_NETDEV_WAKE_QUEUE(_pNetDev) netif_wake_queue((_pNetDev)) +#define RTMP_OS_NETDEV_CARRIER_OFF(_pNetDev) netif_carrier_off((_pNetDev)) + +#define QUEUE_ENTRY_TO_PACKET(pEntry) \ + (PNDIS_PACKET)(pEntry) + +#define PACKET_TO_QUEUE_ENTRY(pPacket) \ + (PQUEUE_ENTRY)(pPacket) + +#ifdef CONFIG_5VT_ENHANCE +#define BRIDGE_TAG 0x35564252 /* depends on 5VT define in br_input.c */ +#endif + +#define GET_SG_LIST_FROM_PACKET(_p, _sc) \ + rt_get_sg_list_from_packet(_p, _sc) + +#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \ +{ \ + RTMPFreeNdisPacket(_pAd, _pPacket); \ +} + + +/* + * packet helper + * - convert internal rt packet to os packet or + * os packet to rt packet + */ +#define RTPKT_TO_OSPKT(_p) ((struct sk_buff *)(_p)) +#define OSPKT_TO_RTPKT(_p) ((PNDIS_PACKET)(_p)) + +#define GET_OS_PKT_DATAPTR(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->data) +#define SET_OS_PKT_DATAPTR(_pkt, _dataPtr) \ + (RTPKT_TO_OSPKT(_pkt)->data) = (_dataPtr) + +#define GET_OS_PKT_LEN(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->len) +#define SET_OS_PKT_LEN(_pkt, _len) \ + (RTPKT_TO_OSPKT(_pkt)->len) = (_len) + +#define GET_OS_PKT_DATATAIL(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->tail) +#define SET_OS_PKT_DATATAIL(_pkt, _start, _len) \ + ((RTPKT_TO_OSPKT(_pkt))->tail) = (PUCHAR)((_start) + (_len)) + +#define GET_OS_PKT_HEAD(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->head) + +#define GET_OS_PKT_END(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->end) + +#define GET_OS_PKT_NETDEV(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->dev) +#define SET_OS_PKT_NETDEV(_pkt, _pNetDev) \ + (RTPKT_TO_OSPKT(_pkt)->dev) = (_pNetDev) + +#define GET_OS_PKT_TYPE(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)) + +#define GET_OS_PKT_NEXT(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->next) + + +#define OS_PKT_CLONED(_pkt) skb_cloned(RTPKT_TO_OSPKT(_pkt)) +#define OS_PKT_COPY(_pkt) skb_copy(RTPKT_TO_OSPKT(_pkt), GFP_ATOMIC) + +#define OS_PKT_TAIL_ADJUST(_pkt, _removedTagLen) \ + SET_OS_PKT_DATATAIL(_pkt, GET_OS_PKT_DATATAIL(_pkt), (-_removedTagLen)); \ + GET_OS_PKT_LEN(_pkt) -= _removedTagLen; + +#define OS_PKT_HEAD_BUF_EXTEND(_pkt, _offset) \ + skb_push(RTPKT_TO_OSPKT(_pkt), _offset) + +#define OS_PKT_TAIL_BUF_EXTEND(_pkt, _Len) \ + skb_put(RTPKT_TO_OSPKT(_pkt), _Len) + +#define OS_PKT_RESERVE(_pkt, _Len) \ + skb_reserve(RTPKT_TO_OSPKT(_pkt), _Len) + +#define OS_PKT_COPY_EXPAND(_pkt, headroom, tailroom) \ + skb_copy_expand(RTPKT_TO_OSPKT(_pkt), headroom, tailroom, GFP_ATOMIC) + +#define RTMP_OS_PKT_INIT(__pRxPacket, __pNetDev, __pData, __DataSize) \ +{ \ + PNDIS_PACKET __pRxPkt; \ + __pRxPkt = RTPKT_TO_OSPKT(__pRxPacket); \ + SET_OS_PKT_NETDEV(__pRxPkt, __pNetDev); \ + SET_OS_PKT_DATAPTR(__pRxPkt, __pData); \ + SET_OS_PKT_LEN(__pRxPkt, __DataSize); \ + SET_OS_PKT_DATATAIL(__pRxPkt, __pData, __DataSize); \ +} + +#ifdef VENDOR_FEATURE2_SUPPORT +#define OS_PKT_CLONE(_pAd, _pkt, _src, _flag) \ + _src = skb_clone(RTPKT_TO_OSPKT(_pkt), _flag); \ + if (_src != NULL) OS_NumOfPktAlloc ++; +#else + +#define OS_PKT_CLONE(_pAd, _pkt, _src, _flag) \ + _src = skb_clone(RTPKT_TO_OSPKT(_pkt), _flag); +#endif /* VENDOR_FEATURE2_SUPPORT */ + +#define get_unaligned32 get_unaligned +#define get_unalignedlong get_unaligned + +#define OS_NTOHS(_Val) \ + (ntohs((_Val))) +#define OS_HTONS(_Val) \ + (htons((_Val))) +#define OS_NTOHL(_Val) \ + (ntohl((_Val))) +#define OS_HTONL(_Val) \ + (htonl((_Val))) + +#define CB_OFF 10 +#define GET_OS_PKT_CB(_p) (RTPKT_TO_OSPKT(_p)->cb) +#define PACKET_CB(_p, _offset) ((RTPKT_TO_OSPKT(_p)->cb[CB_OFF + (_offset)])) + + + + +/*********************************************************************************** + * Other function prototypes definitions + ***********************************************************************************/ + +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) +#if !defined(CONFIG_RA_NAT_NONE) +extern int (*ra_sw_nat_hook_rx)(VOID *skb); +extern int (*ra_sw_nat_hook_tx)(VOID *skb, int gmac_no); +#endif +#endif + +#if defined (CONFIG_WIFI_PKT_FWD) +struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT { + struct net_device *rcvd_net_dev; + unsigned char src_addr[ETH_ALEN]; + unsigned char entry_from; + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pBefore; + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pNext; +}; + +struct APCLI_BRIDGE_LEARNING_MAPPING_MAP { + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pHead; + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pTail; + unsigned int entry_num; +}; + +extern int (*wf_fwd_tx_hook) (struct sk_buff *skb); +extern int (*wf_fwd_rx_hook) (struct sk_buff *skb); +extern unsigned char (*wf_fwd_entry_insert_hook) (struct net_device *src, struct net_device *dest, void *adapter); +extern unsigned char (*wf_fwd_entry_delete_hook) (struct net_device *src, struct net_device *dest, unsigned char link_down); +extern void (*wf_fwd_get_rep_hook) (unsigned char idx); +extern void (*wf_fwd_pro_active_hook) (void); +extern void (*wf_fwd_pro_halt_hook) (void); +extern void (*wf_fwd_access_schedule_active_hook) (void); +extern void (*wf_fwd_access_schedule_halt_hook) (void); +extern void (*wf_fwd_hijack_active_hook) (void); +extern void (*wf_fwd_hijack_halt_hook) (void); +extern void (*wf_fwd_show_entry_hook) (void); +extern void (*wf_fwd_delete_entry_hook) (unsigned char idx); +extern void (*packet_source_show_entry_hook) (void); +extern void (*packet_source_delete_entry_hook) (unsigned char idx); +extern void (*wf_fwd_feedback_map_table) (void *adapter, void *peer, void *opp_peer); +extern void (*wf_fwd_probe_adapter) (void *adapter); +extern void (*wf_fwd_insert_bridge_mapping_hook) (struct sk_buff *skb); +extern void (*wf_fwd_insert_repeater_mapping_hook) (void *adapter, void *lock, void *cli_mapping, void *map_mapping, void *ifAddr_mapping); +extern int (*wf_fwd_search_mapping_table_hook) (struct sk_buff *skb, struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT **tbl_entry); +extern void (*wf_fwd_delete_entry_inform_hook) (unsigned char *addr); +extern void (*wf_fwd_add_entry_inform_hook) (unsigned char *addr); + +#endif /* CONFIG_WIFI_PKT_FWD */ + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); +int rt28xx_packet_xmit(VOID *skb); + +#ifdef RTMP_RBUS_SUPPORT +#ifndef CONFIG_RALINK_FLASH_API +void FlashWrite(UCHAR * p, ULONG a, ULONG b); +void FlashRead(UCHAR * p, ULONG a, ULONG b); +#endif /* CONFIG_RALINK_FLASH_API */ + +int wl_proc_init(void); +int wl_proc_exit(void); + +#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) +extern volatile unsigned long classifier_cur_cycle; +extern int (*ra_classifier_hook_rx) (struct sk_buff *skb, unsigned long cycle); +#endif /* defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) */ +#endif /* RTMP_RBUS_SUPPORT */ + +#if LINUX_VERSION_CODE <= 0x20402 /* Red Hat 7.1 */ +struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)); +#endif /* LINUX_VERSION_CODE */ + + +#ifdef RTMP_MAC_PCI +/* function declarations */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define IRQ_HANDLE_TYPE irqreturn_t +#else +#define IRQ_HANDLE_TYPE void +#endif + +IRQ_HANDLE_TYPE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +rt2860_interrupt(int irq, void *dev_instance); +#else +rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +#endif + +#endif /* RTMP_MAC_PCI */ + +INT rt28xx_ioctl(PNET_DEV net_dev, struct ifreq *rq, INT cmd); +int rt28xx_send_packets(struct sk_buff *skb, struct net_device *ndev); + +extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf); +extern int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); + + +#define GET_PAD_FROM_NET_DEV(_pAd, _net_dev) \ + _pAd = RTMP_OS_NETDEV_GET_PRIV(_net_dev); +#define GET_WDEV_FROM_NET_DEV(_wdev, _net_dev) \ + _wdev = RTMP_OS_NETDEV_GET_WDEV(_net_dev); + + +/*#ifdef RTMP_USB_SUPPORT */ +/****************************************************************************** + + USB related definitions + +******************************************************************************/ + +#define RTMP_USB_PKT_COPY(__pNetDev, __pNetPkt, __Len, __pData) \ +{ \ + memcpy(skb_put(__pNetPkt, __Len), __pData, __Len); \ + GET_OS_PKT_NETDEV(__pNetPkt) = __pNetDev; \ +} + +typedef struct usb_device_id USB_DEVICE_ID; + +// TODO: shiang-usw, fine tune BULKAGGRE_SIZE, origianl is 60 +#ifdef INF_AMAZON_SE +#define BULKAGGRE_SIZE 30 +#else +#define BULKAGGRE_SIZE 100 /* 100 */ +#endif /* INF_AMAZON_SE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#ifndef OS_ABL_SUPPORT +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC) +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) +#define RTUSB_URB_ALLOC_BUFFER(_dev, _size, _dma) usb_alloc_coherent(_dev, _size, GFP_ATOMIC, _dma) +#define RTUSB_URB_FREE_BUFFER(_dev, _size, _addr, _dma) usb_free_coherent(_dev, _size, _addr, _dma) +#else +#define RTUSB_URB_ALLOC_BUFFER(_dev, _size, _dma) usb_buffer_alloc(_dev, _size, GFP_ATOMIC, _dma) +#define RTUSB_URB_FREE_BUFFER(_dev, _size, _addr, _dma) usb_buffer_free(_dev, _size, _addr, _dma) +#endif /* LINUX_VERSION_CODE */ + +#define RTUSB_FILL_BULK_URB(_urb, _dev, _pipe, _buffer, _buffer_len, _complete_fn, _context) usb_fill_bulk_urb(_urb, _dev, _pipe, _buffer, _buffer_len, _complete_fn, _context) +#else + +#define RTUSB_ALLOC_URB(iso) rausb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) rausb_submit_urb(pUrb) +#define RTUSB_URB_ALLOC_BUFFER rausb_buffer_alloc +#define RTUSB_URB_FREE_BUFFER rausb_buffer_free +#endif /* OS_ABL_SUPPORT */ + +#else + +#define RT28XX_PUT_DEVICE(dev_p) + +#ifndef OS_ABL_SUPPORT +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb) +#else +#define RTUSB_ALLOC_URB(iso) rausb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) rausb_submit_urb(pUrb) +#endif /* OS_ABL_SUPPORT */ + +#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) kmalloc(BufSize, GFP_ATOMIC) +#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) kfree(pTransferBuf) +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) */ + + +#ifndef OS_ABL_SUPPORT +#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb) +#else +#define RTUSB_FREE_URB(pUrb) rausb_free_urb(pUrb) +#endif /* OS_ABL_SUPPORT */ + +/* unlink urb */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) + +#ifndef OS_ABL_SUPPORT +#define RTUSB_UNLINK_URB(pUrb) usb_kill_urb(pUrb) +#else +#define RTUSB_UNLINK_URB(pUrb) rausb_kill_urb(pUrb) +#endif /* OS_ABL_SUPPORT */ + +#else +#define RTUSB_UNLINK_URB(pUrb) usb_unlink_urb(pUrb) +#endif /* LINUX_VERSION_CODE */ + +/* Prototypes of completion funuc. */ +#define RtmpUsbBulkOutDataPacketComplete RTUSBBulkOutDataPacketComplete +#define RtmpUsbBulkOutMLMEPacketComplete RTUSBBulkOutMLMEPacketComplete +#define RtmpUsbBulkOutNullFrameComplete RTUSBBulkOutNullFrameComplete +#define RtmpUsbBulkOutRTSFrameComplete RTUSBBulkOutRTSFrameComplete +#define RtmpUsbBulkOutPsPollComplete RTUSBBulkOutPsPollComplete +#define RtmpUsbBulkRxComplete RTUSBBulkRxComplete +#define RtmpUsbBulkCmdRspEventComplete RTUSBBulkCmdRspEventComplete + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 51)) || (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))) +#define RTUSBBulkOutDataPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutDataPacketComplete(pURB) +#define RTUSBBulkOutMLMEPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutMLMEPacketComplete(pURB) +#define RTUSBBulkOutNullFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutNullFrameComplete(pURB) +#define RTUSBBulkOutRTSFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutRTSFrameComplete(pURB) +#define RTUSBBulkOutPsPollComplete(Status, pURB, pt_regs) RTUSBBulkOutPsPollComplete(pURB) +#define RTUSBBulkRxComplete(Status, pURB, pt_regs) RTUSBBulkRxComplete(pURB) +#define RTUSBBulkCmdRspEventComplete(Status, pURB, pt_regs) RTUSBBulkCmdRspEventComplete(pURB) +#else +#define RTUSBBulkOutDataPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutDataPacketComplete(pURB, pt_regs) +#define RTUSBBulkOutMLMEPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutMLMEPacketComplete(pURB, pt_regs) +#define RTUSBBulkOutNullFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutNullFrameComplete(pURB, pt_regs) +#define RTUSBBulkOutRTSFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutRTSFrameComplete(pURB, pt_regs) +#define RTUSBBulkOutPsPollComplete(Status, pURB, pt_regs) RTUSBBulkOutPsPollComplete(pURB, pt_regs) +#define RTUSBBulkRxComplete(Status, pURB, pt_regs) RTUSBBulkRxComplete(pURB, pt_regs) +#define RTUSBBulkCmdRspEventComplete(Status, pURB, pt_regs) RTUSBBulkCmdRspEventComplete(pURB, pt_regs) +#endif + +/*extern void dump_urb(struct urb *purb); */ + +#define InterlockedIncrement atomic_inc +#define NdisInterlockedIncrement atomic_inc +#define InterlockedDecrement atomic_dec +#define NdisInterlockedDecrement atomic_dec +#define InterlockedExchange atomic_set + +typedef void USBHST_STATUS; +typedef INT32 URBCompleteStatus; +typedef struct pt_regs pregs; + +USBHST_STATUS RTUSBBulkOutDataPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutMLMEPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutNullFrameComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutRTSFrameComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutPsPollComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkRxComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkCmdRspEventComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); + +/* Fill Bulk URB Macro */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RTUSB_FILL_TX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + usb_fill_bulk_urb(pUrb, pUsb_Dev, usb_sndbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + pUrb->transfer_dma = TransferDma; \ + pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; \ + }while(0) + +#define RTUSB_FILL_HTTX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + usb_fill_bulk_urb(pUrb, pUsb_Dev, usb_sndbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + pUrb->transfer_dma = TransferDma; \ + pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; \ + }while(0) + +#define RTUSB_FILL_RX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + usb_fill_bulk_urb(pUrb, pUsb_Dev, usb_rcvbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + pUrb->transfer_dma = TransferDma; \ + pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; \ + }while(0) +/* pRxContext->data_dma + pAd->NextRxBulkInPosition; */ + +#define RTUSB_URB_DMA_MAPPING(pUrb) \ + { \ + pUrb->transfer_dma = 0; \ + pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); \ + } + +#else +#define RTUSB_FILL_TX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + FILL_BULK_URB(pUrb, pUsb_Dev, usb_sndbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + }while(0) + +#define RTUSB_FILL_HTTX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + FILL_BULK_URB(pUrb, pUsb_Dev, usb_sndbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + }while(0) + +#define RTUSB_FILL_RX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + FILL_BULK_URB(pUrb, pUsb_Dev, usb_rcvbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + }while(0) + +#define RTUSB_URB_DMA_MAPPING(pUrb) +#endif /* LINUX_VERSION_CODE */ + + +#define RTUSB_CONTROL_MSG(pUsb_Dev, uEndpointAddress, Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, timeout, ret) \ + do{ \ + if ((RequestType == DEVICE_VENDOR_REQUEST_OUT) || (RequestType == DEVICE_CLASS_REQUEST_OUT)) \ + ret = USB_CONTROL_MSG(pUsb_Dev, usb_sndctrlpipe(pUsb_Dev, uEndpointAddress), Request, RequestType, Value, Index, tmpBuf, TransferBufferLength, timeout); \ + else if (RequestType == DEVICE_VENDOR_REQUEST_IN) \ + ret = USB_CONTROL_MSG(pUsb_Dev, usb_rcvctrlpipe(pUsb_Dev, uEndpointAddress), Request, RequestType, Value, Index, tmpBuf, TransferBufferLength, timeout); \ + else \ + { \ + DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n")); \ + ret = -1; \ + } \ + }while(0) + +#define rtusb_urb_context context +#define rtusb_urb_status status + +#define RTMP_OS_USB_CONTEXT_GET(__pURB) __pURB->rtusb_urb_context +#define RTMP_OS_USB_STATUS_GET(__pURB) __pURB->rtusb_urb_status + +#ifndef OS_ABL_SUPPORT +#define USB_CONTROL_MSG usb_control_msg + +#else + +#define USB_CONTROL_MSG rausb_control_msg + +/*extern int rausb_register(struct usb_driver * new_driver); */ +/*extern void rausb_deregister(struct usb_driver * driver); */ + +extern struct urb *rausb_alloc_urb(int iso_packets); +extern void rausb_free_urb(VOID *urb); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +extern void rausb_put_dev(VOID *dev); +extern struct usb_device *rausb_get_dev(VOID *dev); +#endif /* LINUX_VERSION_CODE */ + +extern int rausb_submit_urb(VOID *urb); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifndef gfp_t +#define gfp_t INT32 +#endif /* gfp_t */ + +extern void *rausb_buffer_alloc(VOID *dev, + size_t size, + ra_dma_addr_t *dma); +extern void rausb_buffer_free(VOID *dev, + size_t size, + void *addr, + ra_dma_addr_t dma); +#endif /* LINUX_VERSION_CODE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) +extern void rausb_kill_urb(VOID *urb); +#endif /* LINUX_VERSION_CODE */ + +extern int rausb_control_msg(VOID *dev, + unsigned int pipe, + __u8 request, + __u8 requesttype, + __u16 value, + __u16 index, + void *data, + __u16 size, + int timeout); + +#endif /* OS_ABL_SUPPORT */ + +/*#endif // RTMP_USB_SUPPORT */ + +#ifdef RALINK_ATE +/****************************************************************************** + + ATE related definitions + +******************************************************************************/ +#define ate_print printk +#define ATEDBGPRINT DBGPRINT +#ifdef RTMP_MAC_PCI +#ifdef CONFIG_AP_SUPPORT +#ifndef CONFIG_STA_SUPPORT /* avoid wrong usage when enabling P2P_SUPPORT */ +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860AP/e2p.bin" +#endif /* CONFIG_STA_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef RTMP_RBUS_SUPPORT +int __init rt2880_module_init(void); +VOID __exit rt2880_module_exit(void); +#endif /* RTMP_RBUS_SUPPORT */ + +#endif /* RALINK_ATE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +INT RtmpOSNetDevOpsAlloc( + IN PVOID *pNetDevOps); +#endif + +#define RTMP_OS_MAX_SCAN_DATA_GET() IW_SCAN_MAX_DATA + +#include "os/rt_os.h" + + +#ifdef MULTI_INF_SUPPORT + +#ifdef RTMP_PCI_SUPPORT +int __init rt_pci_init_module(void); +void __exit rt_pci_cleanup_module(void); +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef RTMP_RBUS_SUPPORT +int __init rt2880_module_init(void); +VOID __exit rt2880_module_exit(void); +#endif /* RTMP_RBUS_SUPPORT */ + +#endif /* MULTI_INF_SUPPORT */ + + +#define RA_WEXT 0 +#define RA_NETLINK 1 + + +#endif /* __RT_LINUX_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_linux_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_linux_cmm.h new file mode 100644 index 000000000..4313d3a37 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_linux_cmm.h @@ -0,0 +1,467 @@ +/**************************************************************************** + * 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: + rt_linux_cmm.h + + Abstract: + Common OS structure/definition in LINUX whatever OS ABL. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + + +#ifndef __RT_LINUX_CMM_H__ +#define __RT_LINUX_CMM_H__ + + +typedef struct _OS_RSTRUC { + UCHAR *pContent; /* pointer to real structure content */ +} OS_RSTRUC; + + +/* declare new chipset function here */ +#ifdef OS_ABL_FUNC_SUPPORT + +#define RTMP_DECLARE_DRV_OPS_FUNCTION(_func) \ + void Rtmp_Drv_Ops_##_func(VOID *__pDrvOps, VOID *__pNetOps, \ + VOID *__pPciConfig, VOID *__pUsbConfig) + +#define RTMP_BUILD_DRV_OPS_FUNCTION(_func) \ +void Rtmp_Drv_Ops_##_func(VOID *__pDrvOps, VOID *__pNetOps, \ + VOID *__pPciConfig, VOID *__pUsbConfig) \ +{ \ + RtmpDrvOpsInit(__pDrvOps, __pNetOps, __pPciConfig, __pUsbConfig);\ +} + +#define RTMP_GET_DRV_OPS_FUNCTION(_func) \ + (PVOID)Rtmp_Drv_Ops_##_func + +#define RTMP_DRV_OPS_FUNCTION_BODY(_func) \ + Rtmp_Drv_Ops_##_func + + +#define xdef_to_str(s) def_to_str(s) +#define def_to_str(s) #s + +#ifdef RTMP_MAC_PCI +#define RTMP_DRV_NAME "rtpci" xdef_to_str(RT28xx_MODE) +RTMP_DECLARE_DRV_OPS_FUNCTION(pci); +#define RTMP_DRV_OPS_FUNCTION RTMP_DRV_OPS_FUNCTION_BODY(pci) +#define RTMP_BUILD_DRV_OPS_FUNCTION_BODY RTMP_BUILD_DRV_OPS_FUNCTION(pci) +#endif /* RTMP_MAC_PCI */ + + +#else + +#define RTMP_DRV_NAME "rtpci" + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS task related data structure and definitions + ******************************************************************************/ +#define RTMP_OS_TASK_INIT(__pTask, __pTaskName, __pAd) \ + RtmpOSTaskInit(__pTask, __pTaskName, __pAd, &(__pAd)->RscTaskMemList, &(__pAd)->RscSemMemList); + +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define RTMP_OS_TASK OS_TASK + +#define RTMP_OS_TASK_GET(__pTask) \ + (__pTask) + +#define RTMP_OS_TASK_DATA_GET(__pTask) \ + ((__pTask)->priv) + +#define RTMP_OS_TASK_IS_KILLED(__pTask) \ + ((__pTask)->task_killed) + +#ifdef KTHREAD_SUPPORT +#define RTMP_OS_TASK_WAKE_UP(__pTask) \ + WAKE_UP(pTask); +#else +#define RTMP_OS_TASK_WAKE_UP(__pTask) \ + RTMP_SEM_EVENT_UP(&(pTask)->taskSema); +#endif /* KTHREAD_SUPPORT */ + +#ifdef KTHREAD_SUPPORT +#define RTMP_OS_TASK_LEGALITY(__pTask) \ + if ((__pTask)->kthread_task != NULL) +#else +#define RTMP_OS_TASK_LEGALITY(__pTask) \ + CHECK_PID_LEGALITY((__pTask)->taskPID) +#endif /* KTHREAD_SUPPORT */ + +#else + +/* rt_linux_cmm.h */ +#define RTMP_OS_TASK OS_RSTRUC + +#define RTMP_OS_TASK_GET(__pTask) \ + ((OS_TASK *)((__pTask)->pContent)) + +#define RTMP_OS_TASK_DATA_GET(__pTask) \ + RtmpOsTaskDataGet(__pTask) + +#define RTMP_OS_TASK_IS_KILLED(__pTask) \ + RtmpOsTaskIsKilled(__pTask) + +#define RTMP_OS_TASK_WAKE_UP(__pTask) \ + RtmpOsTaskWakeUp(pTask) + +#define RTMP_OS_TASK_LEGALITY(__pTask) \ + if (RtmpOsCheckTaskLegality(__pTask)) + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * Timer related definitions and data structures. + ******************************************************************************/ +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define NDIS_MINIPORT_TIMER OS_NDIS_MINIPORT_TIMER +#define RTMP_OS_TIMER OS_TIMER + +#define RTMP_OS_FREE_TIMER(__pAd) +#define RTMP_OS_FREE_LOCK(__pAd) +#define RTMP_OS_FREE_TASKLET(__pAd) +#define RTMP_OS_FREE_TASK(__pAd) +#define RTMP_OS_FREE_SEM(__pAd) +#define RTMP_OS_FREE_ATOMIC(__pAd) + +#else + +/* rt_linux_cmm.h */ +#define NDIS_MINIPORT_TIMER OS_RSTRUC +#define RTMP_OS_TIMER OS_RSTRUC + +#define RTMP_OS_FREE_TIMER(__pAd) +#define RTMP_OS_FREE_LOCK(__pAd) +#define RTMP_OS_FREE_TASKLET(__pAd) +#define RTMP_OS_FREE_TASK(__pAd) +#define RTMP_OS_FREE_SEM(__pAd) +#define RTMP_OS_FREE_ATOMIC(__pAd) + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS file operation related data structure definitions + ******************************************************************************/ +/* if you add any new type, please also modify RtmpOSFileOpen() */ +#define RTMP_FILE_RDONLY 0x0F01 +#define RTMP_FILE_WRONLY 0x0F02 +#define RTMP_FILE_CREAT 0x0F03 +#define RTMP_FILE_TRUNC 0x0F04 + +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define RTMP_OS_FS_INFO OS_FS_INFO + +#else + +/* rt_linux_cmm.h */ +#define RTMP_OS_FS_INFO OS_RSTRUC + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS semaphore related data structure and definitions + ******************************************************************************/ + +#ifndef OS_ABL_FUNC_SUPPORT + +#define NDIS_SPIN_LOCK OS_NDIS_SPIN_LOCK +#define NdisAllocateSpinLock(__pReserved, __pLock) OS_NdisAllocateSpinLock(__pLock) +#define NdisFreeSpinLock OS_NdisFreeSpinLock +#define RTMP_SEM_LOCK OS_SEM_LOCK +#define RTMP_SEM_UNLOCK OS_SEM_UNLOCK +#define RTMP_SPIN_LOCK OS_SPIN_LOCK +#define RTMP_SPIN_UNLOCK OS_SPIN_UNLOCK +#define RTMP_SPIN_LOCK_IRQ OS_SPIN_LOCK_IRQ +#define RTMP_SPIN_UNLOCK_IRQ OS_SPIN_UNLOCK_IRQ +#define RTMP_SPIN_LOCK_IRQSAVE OS_SPIN_LOCK_IRQSAVE +#define RTMP_SPIN_UNLOCK_IRQRESTORE OS_SPIN_UNLOCK_IRQRESTORE +#define RTMP_IRQ_LOCK OS_IRQ_LOCK +#define RTMP_IRQ_UNLOCK OS_IRQ_UNLOCK +#define RTMP_INT_LOCK OS_INT_LOCK +#define RTMP_INT_UNLOCK OS_INT_UNLOCK +#define RTMP_OS_SEM OS_SEM +#define RTMP_OS_ATOMIC atomic_t + +#define NdisAcquireSpinLock RTMP_SEM_LOCK +#define NdisReleaseSpinLock RTMP_SEM_UNLOCK + +#define RTMP_SEM_EVENT_INIT_LOCKED(__pSema, __pSemaList) OS_SEM_EVENT_INIT_LOCKED(__pSema) +#define RTMP_SEM_EVENT_INIT(__pSema, __pSemaList) OS_SEM_EVENT_INIT(__pSema) +#define RTMP_SEM_EVENT_DESTORY OS_SEM_EVENT_DESTORY +#define RTMP_SEM_EVENT_WAIT OS_SEM_EVENT_WAIT +#define RTMP_SEM_EVENT_UP OS_SEM_EVENT_UP + +#define RtmpMLMEUp OS_RTMP_MlmeUp + +#define RTMP_OS_ATMOIC_INIT(__pAtomic, __pAtomicList) +#define RTMP_OS_ATMOIC_DESTROY(__pAtomic) +#define RTMP_THREAD_PID_KILL(__PID) KILL_THREAD_PID(__PID, SIGTERM, 1) + +#else + +#define NDIS_SPIN_LOCK OS_RSTRUC +#define RTMP_OS_SEM OS_RSTRUC +#define RTMP_OS_ATOMIC OS_RSTRUC + +#define RTMP_SEM_EVENT_INIT_LOCKED RtmpOsSemaInitLocked +#define RTMP_SEM_EVENT_INIT RtmpOsSemaInit +#define RTMP_SEM_EVENT_DESTORY RtmpOsSemaDestory +#define RTMP_SEM_EVENT_WAIT(_pSema, _status) ((_status) = RtmpOsSemaWaitInterruptible((_pSema))) +#define RTMP_SEM_EVENT_UP RtmpOsSemaWakeUp + +#define RtmpMLMEUp RtmpOsMlmeUp + +#define RTMP_OS_ATMOIC_INIT RtmpOsAtomicInit +#define RTMP_OS_ATMOIC_DESTROY RtmpOsAtomicDestroy +#define RTMP_THREAD_PID_KILL RtmpThreadPidKill + +/* */ +/* spin_lock enhanced for Nested spin lock */ +/* */ +#define NdisAllocateSpinLock(__pAd, __pLock) RtmpOsAllocateLock(__pLock, &(__pAd)->RscLockMemList) +#define NdisFreeSpinLock RtmpOsFreeSpinLock + +#define RTMP_SEM_LOCK(__lock) \ +{ \ + RtmpOsSpinLockBh(__lock); \ +} + +#define RTMP_SEM_UNLOCK(__lock) \ +{ \ + RtmpOsSpinUnLockBh(__lock); \ +} +#define RTMP_SPIN_LOCK_IRQ RtmpOsSpinLockIrq +#define RTMP_SPIN_UNLOCK_IRQ RtmpOsSpinUnlockIrq +#define RTMP_SPIN_LOCK_IRQSAVE RtmpOsSpinLockIrqSave +#define RTMP_SPIN_UNLOCK_IRQRESTORE RtmpOsSpinUnlockIrqRestore + +/* sample, use semaphore lock to replace IRQ lock, 2007/11/15 */ +#ifdef MULTI_CORE_SUPPORT + +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + typecheck(unsigned long, __irqflags); \ + spin_lock_irqsave((spinlock_t *)(__lock), __irqflags); \ +} + +#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_irqrestore((spinlock_t *)(__lock), __irqflag); \ +} +#else +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + typecheck(unsigned long, __irqflags); \ + RtmpOsSpinLockBh(__lock); \ +} + +#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + RtmpOsSpinUnLockBh(__lock); \ +} +#endif // MULTI_CORE_SUPPORT // +#define RTMP_INT_LOCK(__Lock, __Flag) RtmpOsIntLock(__Lock, &__Flag) +#define RTMP_INT_UNLOCK RtmpOsIntUnLock + +#define NdisAcquireSpinLock RTMP_SEM_LOCK +#define NdisReleaseSpinLock RTMP_SEM_UNLOCK + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS task related data structure and definitions + ******************************************************************************/ + +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define RTMP_NET_TASK_STRUCT OS_NET_TASK_STRUCT +#define PRTMP_NET_TASK_STRUCT POS_NET_TASK_STRUCT + +typedef struct completion RTMP_OS_COMPLETION; + +#define RTMP_OS_INIT_COMPLETION(__pCompletion) \ + init_completion(__pCompletion) + +#define RTMP_OS_EXIT_COMPLETION(__pCompletion) + +#define RTMP_OS_COMPLETE(__pCompletion) \ + complete(__pCompletion) + +#define RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(__pCompletion, __Timeout) \ + wait_for_completion_timeout(__pCompletion, __Timeout) + +#ifdef WORKQUEUE_BH +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + schedule_work(__pTasklet) +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \ + INIT_WORK((struct work_struct *)__pTasklet, (work_func_t)__pFunc) +#define RTMP_OS_TASKLET_KILL(__pTasklet) \ + cancel_work_sync(__pTasklet) +#else +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + tasklet_hi_schedule(__pTasklet) +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \ + tasklet_init(__pTasklet, __pFunc, __Data) +#define RTMP_OS_TASKLET_KILL(__pTasklet) \ + tasklet_kill(__pTasklet) +#endif /* WORKQUEUE_BH */ + +#define RTMP_NET_TASK_DATA_ASSIGN(__Tasklet, __Data) \ + (__Tasklet)->data = (unsigned long)__Data + +#else + +/* rt_linux_cmm.h */ +typedef OS_RSTRUC RTMP_NET_TASK_STRUCT; +typedef OS_RSTRUC *PRTMP_NET_TASK_STRUCT; +typedef OS_RSTRUC RTMP_OS_COMPLETION; +typedef OS_RSTRUC *PRTMP_OS_COMPLETION; + +#define RTMP_OS_INIT_COMPLETION(__pCompletion) \ + RtmpOsInitCompletion(__pCompletion) + +#define RTMP_OS_EXIT_COMPLETION(__pCompletion) \ + RtmpOsExitCompletion(__pCompletion) + +#define RTMP_OS_COMPLETE(__pCompletion) \ + RtmpOsComplete(__pCompletion) + +#define RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(__pCompletion, __Timeout) \ + RtmpOsWaitForCompletionTimeout(__pCompletion, __Timeout) + +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + RtmpOsTaskletSche(__pTasklet) + +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \ + RtmpOsTaskletInit(__pTasklet, __pFunc, __Data, &(__pAd)->RscTaskletMemList) + +#define RTMP_OS_TASKLET_KILL(__pTasklet) \ + RtmpOsTaskletKill(__pTasklet) + +#define RTMP_NET_TASK_DATA_ASSIGN(__pTasklet, __Data) \ + RtmpOsTaskletDataAssign(__pTasklet, __Data) + +#endif /* OS_ABL_FUNC_SUPPORT */ + + + + +/***************************************************************************** + * OS definition related data structure and definitions + ******************************************************************************/ + +#ifdef OS_ABL_SUPPORT + +#define RTMP_USB_CONTROL_MSG_ENODEV -1 +#define RTMP_USB_CONTROL_MSG_FAIL -2 + +typedef struct __RTMP_PCI_CONFIG { + UINT32 ConfigVendorID; +} RTMP_PCI_CONFIG; + +typedef struct __RTMP_USB_CONFIG { + UINT32 Reserved; +} RTMP_USB_CONFIG; + +extern RTMP_PCI_CONFIG *pRtmpPciConfig; +extern RTMP_USB_CONFIG *pRtmpUsbConfig; + +#define RTMP_OS_PCI_VENDOR_ID pRtmpPciConfig->ConfigVendorID + +/* + Declare dma_addr_t here, can not define it in rt_drv.h + + If you define it in include/os/rt_drv.h, then the size in DRIVER module + will be 64-bit, but in UTIL/NET modules, it maybe 32-bit. + This will cause size mismatch problem when OS_ABL = yes. +*/ +/* + In big-endian & 32-bit DMA address platform, if you use long long to + record DMA address, when you call kernel function to set DMA address, + the address will be 0 because you need to do swap I think. + So if you sure your DMA address is 32-bit, do not use RTMP_DMA_ADDR_64. +*/ +#define ra_dma_addr_t unsigned long long + +#else + + +#define RTMP_OS_PCI_VENDOR_ID PCI_VENDOR_ID +#define RTMP_OS_PCI_DEVICE_ID PCI_DEVICE_ID + +#define ra_dma_addr_t dma_addr_t + +#endif /* OS_ABL_SUPPORT */ + +#define PCI_MAP_SINGLE RtmpDrvPciMapSingle + + +/*********************************************************************************** + * Others + ***********************************************************************************/ +#define APCLI_IF_UP_CHECK(pAd, ifidx) (RtmpOSNetDevIsUp((pAd)->ApCfg.ApCliTab[(ifidx)].wdev.if_dev) == TRUE) + +#ifdef RTMP_MAC_PCI +#ifdef MEMORY_OPTIMIZATION +#define TX_RING_SIZE 64 +#define MGMT_RING_SIZE 32 +#define RX_RING_SIZE 64 +#else +#ifdef DOT11_VHT_AC +#define TX_RING_SIZE 256 +#define RX_RING_SIZE 256 +#else +#define TX_RING_SIZE 128 +#define RX_RING_SIZE 128 +#endif /* DOT11_VHT_AC */ +#define MGMT_RING_SIZE 128 +#endif +#define MAX_TX_PROCESS TX_RING_SIZE +#define MAX_DMA_DONE_PROCESS TX_RING_SIZE +#define MAX_TX_DONE_PROCESS TX_RING_SIZE +#define LOCAL_TXBUF_SIZE 2 + +#define RX1_RING_SIZE 32 +#endif /* RTMP_MAC_PCI */ + +#define RTMP_OS_NETDEV_SET_PRIV RtmpOsSetNetDevPriv +#define RTMP_OS_NETDEV_GET_PRIV RtmpOsGetNetDevPriv +#define RTMP_OS_NETDEV_SET_WDEV RtmpOsSetNetDevWdev +#define RTMP_OS_NETDEV_GET_WDEV RtmpOsGetNetDevWdev +#define RT_DEV_PRIV_FLAGS_GET RtmpDevPrivFlagsGet +#define RT_DEV_PRIV_FLAGS_SET RtmpDevPrivFlagsSet + +#endif /* __RT_LINUX_CMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_os.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_os.h new file mode 100644 index 000000000..9061d09a6 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/os/rt_os.h @@ -0,0 +1,117 @@ +/* + *************************************************************************** + * 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_os.h + + Abstract: + Put all OS related definition/structure/MACRO here. + + Note: + Used in UTIL/NETIF module. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef _RT_OS_H_ +#define _RT_OS_H_ + + +#ifdef LINUX +#if WIRELESS_EXT <= 11 +#ifndef SIOCDEVPRIVATE +#define SIOCDEVPRIVATE 0x8BE0 +#endif +#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE +#endif +#endif /* LINUX */ + + +#ifdef CONFIG_STA_SUPPORT +#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x01) /* Sync. with AP for wsc upnp daemon */ +#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) + +#if defined(DBG) ||defined(RALINK_ATE) +#define RTPRIV_IOCTL_BBP (SIOCIWFIRSTPRIV + 0x03) +#define RTPRIV_IOCTL_MAC (SIOCIWFIRSTPRIV + 0x05) + +#ifdef RTMP_RF_RW_SUPPORT +#define RTPRIV_IOCTL_RF (SIOCIWFIRSTPRIV + 0x13) /* edit by johnli, fix read rf register problem */ +#endif /* RTMP_RF_RW_SUPPORT */ +#define RTPRIV_IOCTL_E2P (SIOCIWFIRSTPRIV + 0x07) +#endif /* DBG */ + +#define RTPRIV_IOCTL_ATE (SIOCIWFIRSTPRIV + 0x08) + +#define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09) +#define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A) +#define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C) +#define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D) +#define RT_PRIV_IOCTL_EXT (SIOCIWFIRSTPRIV + 0x0E) /* Sync. with RT61 (for wpa_supplicant) */ +#define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F) +#define RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT (SIOCIWFIRSTPRIV + 0x1F) /* modified by Red@Ralink, 2009/09/30 */ + +#define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11) + + +#ifdef WSC_STA_SUPPORT +#define RTPRIV_IOCTL_SET_WSC_PROFILE_U32_ITEM (SIOCIWFIRSTPRIV + 0x14) +#define RTPRIV_IOCTL_SET_WSC_PROFILE_STRING_ITEM (SIOCIWFIRSTPRIV + 0x16) +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +/* Ralink defined OIDs */ +#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x01) +#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) +#define RT_PRIV_IOCTL_EXT (SIOCIWFIRSTPRIV + 0x0E) /* Sync. with RT61 (for wpa_supplicant) */ +#if defined(DBG) || defined(BB_SOC) +#define RTPRIV_IOCTL_BBP (SIOCIWFIRSTPRIV + 0x03) +#define RTPRIV_IOCTL_MAC (SIOCIWFIRSTPRIV + 0x05) + +#ifdef RTMP_RF_RW_SUPPORT +#define RTPRIV_IOCTL_RF (SIOCIWFIRSTPRIV + 0x13) +#endif /* RTMP_RF_RW_SUPPORT */ + +#endif /* DBG */ +#define RTPRIV_IOCTL_E2P (SIOCIWFIRSTPRIV + 0x07) + +#define RTPRIV_IOCTL_ATE (SIOCIWFIRSTPRIV + 0x08) + +#define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09) +#define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A) +#define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C) +#define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D) +#define RTPRIV_IOCTL_ADD_WPA_KEY (SIOCIWFIRSTPRIV + 0x0E) +#define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F) +#define RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT (SIOCIWFIRSTPRIV + 0x1F) /* modified by Red@Ralink, 2009/09/30 */ +#define RTPRIV_IOCTL_STATIC_WEP_COPY (SIOCIWFIRSTPRIV + 0x10) + +#define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11) +#define RTPRIV_IOCTL_WSC_PROFILE (SIOCIWFIRSTPRIV + 0x12) +#define RTPRIV_IOCTL_QUERY_BATABLE (SIOCIWFIRSTPRIV + 0x16) +#if defined(INF_AR9) || defined(BB_SOC) +#define RTPRIV_IOCTL_GET_AR9_SHOW (SIOCIWFIRSTPRIV + 0x17) +#endif/* INF_AR9 */ +#define RTPRIV_IOCTL_SET_WSCOOB (SIOCIWFIRSTPRIV + 0x19) +#define RTPRIV_IOCTL_WSC_CALLBACK (SIOCIWFIRSTPRIV + 0x1A) +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* _RT_OS_H_ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/mt_rf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/mt_rf.h new file mode 100644 index 000000000..f2a454aa5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/mt_rf.h @@ -0,0 +1,138 @@ +#ifndef __MT_RF_H__ +#define __MT_RF_H__ + +struct _RTMP_ADAPTER; + +enum { + CHL_GRP1 = 0x01, + CHL_GRP2, + CHL_GRP3, + CHL_GRP4, + CHL_GRP5, + CHL_GRP6, + CHL_GRP7, + CHL_GRP_MAX = CHL_GRP7, +}; + +#define RFDIGI_TOP0 0x000 +#define RFDIGI_TOP1 0x004 +#define RFDIGI_TOP2 0x008 +#define RFDIGI_TOP3 0x00C +#define RFDIGI_TOP4 0x010 +#define RG_WF0_RXG_TOP 0x44 +#define A_BAND_IQM_TSSI_DIV_LPF 0x054 +#define A_BAND_PA 0x058 +#define RFDIGI_ABB_TO_AFE5 0x114 +#define RF_ABB 0x130 +#define RFDIGI_TO_SX2 0x144 +#define SX2_FCAL_TARGET_MASK (0x3fff << 11) +#define SX2_FCAL_TARGET(p) (((p) & 0x3fff) << 11) +#define RFDIGI_TO_SX5 0x150 +#define RFDIGI_TO_SX7 0x158 +#define SX7_INTCS_MASK (0x3ff) +#define SX7_INTCS(p) (((p) & 0x3ff)) +#define SX7_FRACES_MASK (0xfffff << 12) +#define SX7_FRACES(p) (((p) & 0xfffff) << 12) +#define SX5_REPA_NRBIAS_2_0_MASK (0x7 << 9) +#define SX5_REPA_NRBIAS_2_0(p) (((p) & 0x07) << 9) +#define RFDIGI_TRX0 0x200 +#define TRX0_SW_TXIQ_CANCEL_EN (0x1 << 10) +#define RFDIGI_TRX4 0x210 +#define RFDIGI_TRX5 0x214 +#define RFDIGI_TRX7 0x21C +#define RFDIGI_TRX8 0x220 +#define RFDIGI_TRX9 0x224 +#define RFDIGI_TRX10 0x228 +#define RFDIGI_TRX17 0x244 +#define RFDIGI_TRX19 0x24C +#define RFDIGI_TRX20 0x250 +#define RFDIGI_TRX21 0x254 +#define TRX21_LNA_OUTCAP_A_HG_MASK (0x07 << 0) +#define TRX21_LNA_OUTCAP_A_HG(p) (((p) & 0x07) << 0) +#define TRX21_LNA_OUTCAP_A_MG_MASK (0x07 << 4) +#define TRX21_LNA_OUTCAP_A_MG(p) (((p) & 0x07) << 4) +#define TRX21_LNA_OUTCAP_A_LG_MASK (0x07 << 8) +#define TRX21_LNA_OUTCAP_A_LG(p) (((p) & 0x07) << 8) +#define TRX21_LNA_OUTCAP_A_ULG_MASK (0x07 << 12) +#define TRX21_LNA_OUTCAP_A_ULG(p) (((p) & 0x07) << 12) +#define TRX21_TZ_GCR_A_HG_MASK (0x07 << 16) +#define TRX21_TZ_GCR_A_HG(p) (((p) & 0x07) << 16) +#define TRX21_TZ_GCR_A_MG_MASK (0x07 << 20) +#define TRX21_TZ_GCR_A_MG(p) (((p) & 0x07) << 20) +#define TRX21_TZ_GCR_A_LG_MASK (0x07 << 24) +#define TRX21_TZ_GCR_A_LG(p) (((p) & 0x07) << 24) +#define TRX21_TZ_GCR_A_ULG_MASK (0x07 << 28) +#define TRX21_TZ_GCR_A_ULG(p) (((p) & 0x07) << 28) +#define RFDIGI_TRX24 0x260 +#define RFDIGI_TRX25 0x264 +#define TRX24_GM_GC_A_HG_MASK (0x0f << 0) +#define TRX24_GM_GC_A_HG(p) (((p) & 0x0f) << 0) +#define TRX24_GM_GC_A_MG_MASK (0x0f << 4) +#define TRX24_GM_GC_A_MG(p) (((p) & 0x0f) << 4) +#define TRX24_GM_GC_A_LG_MASK (0x0f << 8) +#define TRX24_GM_GC_A_LG(p) (((p) & 0x0f) << 8) +#define TRX24_GM_GC_A_ULG_MASK (0x0f << 12) +#define TRX24_GM_GC_A_ULG(p) (((p) & 0x0f) << 12) +#define TRX24_TZ_FBC_A_HG_MASK (0x0f << 16) +#define TRX24_TZ_FBC_A_HG(p) (((p) & 0x0f) << 16) +#define TRX24_TZ_FBC_A_MG_MASK (0x0f << 20) +#define TRX24_TZ_FBC_A_MG(p) (((p) & 0x0f) << 20) +#define TRX24_TZ_FBC_A_LG_MASK (0x0f << 24) +#define TRX24_TZ_FBC_A_LG(p) (((p) & 0x0f) << 24) +#define TRX24_TZ_FBC_A_ULG_MASK (0x0f << 28) +#define TRX24_TZ_FBC_A_ULG(p) (((p) & 0x0f) << 28) +#define RFDIGI_TRX27 0x26C +#define RFDIGI_TRX28 0x270 +#define RFDIGI_TRX29 0x274 +#define RFDIGI_TRX30 0x278 +#define RFDIGI_TRX38 0x298 +#define RFDIGI_TRX39 0x29C +#define RFDIGI_TRX42 0x2A8 +#define RFDIGI_SX7 0x31C +#define RFDIGI_SX8 0x320 +#define RFDIGI_SX10 0x328 +#define RFDIGI_SX13 0x334 +#define RFDIGI_ID 0xFFF + + +typedef struct _MT_RF_REG { + u8 rf_idx; + u16 offset; + u32 data; +} MT_RF_REG, *PMT_RF_REG; + +typedef struct _CHL_GRP_RF_REG { + u8 chl_grp; + u16 chl_start; + u16 chl_end; + u8 lna_outcap_a_hg; + u8 lna_outcap_a_mg; + u8 lna_outcap_a_lg; + u8 lna_outcap_a_ulg; + u8 tz_gcr_a_hg; + u8 tz_gcr_a_mg; + u8 tz_gcr_a_lg; + u8 tz_gcr_a_ulg; + u8 tz_fbc_a_hg; + u8 tz_fbc_a_mg; + u8 tz_fbc_a_lg; + u8 tz_fbc_a_ulg; + u8 gm_gc_a_hg; + u8 gm_gc_a_mg; + u8 gm_gc_a_lg; + u8 gm_gc_a_ulg; +} CHL_GRP_RF_REG, *PCHL_GRP_RF_REG; + +int mt_rf_write( + struct _RTMP_ADAPTER *ad, + u8 rf_idx, + u16 offset, + u32 data); + +int mt_rf_read( + struct _RTMP_ADAPTER *ad, + u8 rf_idx, + u16 offset, + u32 *data); + +#endif /* __MT_RF_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/rlt_bbp.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/rlt_bbp.h new file mode 100644 index 000000000..d14bf4468 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/rlt_bbp.h @@ -0,0 +1,343 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __RLT_BBP_H__ +#define __RLT_BBP_H__ + + +#define BBP_CORE 0x2000 +#define BBP_IBI 0x2100 +#define BBP_AGC1 0x2300 +#define BBP_TXC 0x2400 +#define BBP_RXC 0x2500 +#define BBP_TXO 0x2600 +#define BBP_TXBE 0x2700 +#define BBP_RXFE 0x2800 +#define BBP_RXO 0x2900 +#define BBP_DFS 0x2a00 +#define BBP_TR 0x2b00 +#define BBP_CAL 0x2c00 +#define BBP_DSC 0x2e00 +#define BBP_PFMU 0x2f00 + + +/* 0x2000 ~ */ +#define CORE_R0 (BBP_CORE + 0x00) +#define CORE_R1 (BBP_CORE + 0x04) +#define CORE_R4 (BBP_CORE + 0x10) +#define CORE_R24 (BBP_CORE + 0x60) +#define CORE_R32 (BBP_CORE + 0x80) +#define CORE_R33 (BBP_CORE + 0x84) +#define CORE_R34 (BBP_CORE + 0x88) +#define CORE_R35 (BBP_CORE + 0x8c) +#define CORE_R42 (BBP_CORE + 0xa8) +#define CORE_R44 (BBP_CORE + 0xb0) + +/* 0x2100 ~ */ +#define IBI_R0 (BBP_IBI + 0x00) +#define IBI_R1 (BBP_IBI + 0x04) +#define IBI_R2 (BBP_IBI + 0x08) +#define IBI_R3 (BBP_IBI + 0x0c) +#define IBI_R4 (BBP_IBI + 0x10) +#define IBI_R5 (BBP_IBI + 0x14) +#define IBI_R6 (BBP_IBI + 0x18) +#define IBI_R7 (BBP_IBI + 0x1c) +#define IBI_R9 (BBP_IBI + 0x24) +#define IBI_R11 (BBP_IBI + 0x2c) +#define IBI_R15 (BBP_IBI + 0x3c) + +/* 0x2300 ~ */ +#define AGC1_R0 (BBP_AGC1 + 0x00) +#define AGC1_R0_PRIMARY_CHL_INDEX_MASK (0x3 << 8) +#define AGC1_R0_RPIMARY_CHL_INDEX(p) (((p) & 0x3) << 8) +#define GET_PRIMARY_CHL_INDEX(p) (((p) & AGC1_R0_PRIMARY_CHL_INDEX_MASK) >> 8) + +#define AGC1_R1 (BBP_AGC1 + 0x04) +#define AGC1_R2 (BBP_AGC1 + 0x08) +#define AGC1_R4 (BBP_AGC1 + 0x10) +#define AGC1_R5 (BBP_AGC1 + 0x14) +#define AGC1_R6 (BBP_AGC1 + 0x18) +#define AGC1_R7 (BBP_AGC1 + 0x1C) +#define AGC1_R8 (BBP_AGC1 + 0x20) +#define AGC1_R9 (BBP_AGC1 + 0x24) +#define AGC1_R11 (BBP_AGC1 + 0x2C) +#define AGC1_R12 (BBP_AGC1 + 0x30) +#define AGC1_R13 (BBP_AGC1 + 0x34) +#define AGC1_R14 (BBP_AGC1 + 0x38) +#define AGC1_R15 (BBP_AGC1 + 0x3C) +#define AGC1_R16 (BBP_AGC1 + 0x40) +#define AGC1_R18 (BBP_AGC1 + 0x48) +#define AGC1_R19 (BBP_AGC1 + 0x4c) +#define AGC1_R20 (BBP_AGC1 + 0x50) +#define AGC1_R21 (BBP_AGC1 + 0x54) +#define AGC1_R22 (BBP_AGC1 + 0x58) +#define AGC1_R23 (BBP_AGC1 + 0x5c) +#define AGC1_R24 (BBP_AGC1 + 0x60) +#define AGC1_R25 (BBP_AGC1 + 0x64) +#define AGC1_R26 (BBP_AGC1 + 0x68) +#define AGC1_R27 (BBP_AGC1 + 0x6c) +#define AGC1_R28 (BBP_AGC1 + 0x70) +#define AGC1_R30 (BBP_AGC1 + 0x78) +#define AGC1_R31 (BBP_AGC1 + 0x7c) +#define AGC1_R32 (BBP_AGC1 + 0x80) +#define AGC1_R33 (BBP_AGC1 + 0x84) +#define AGC1_R34 (BBP_AGC1 + 0x88) +#define AGC1_R35 (BBP_AGC1 + 0x8c) +#define AGC1_R37 (BBP_AGC1 + 0x94) +#define AGC1_R39 (BBP_AGC1 + 0x9c) +#define AGC1_R41 (BBP_AGC1 + 0xa4) +#define AGC1_R43 (BBP_AGC1 + 0xac) +#define AGC1_R45 (BBP_AGC1 + 0xb4) +#define AGC1_R47 (BBP_AGC1 + 0xbc) +#define AGC1_R49 (BBP_AGC1 + 0xc4) +#define AGC1_R51 (BBP_AGC1 + 0xcc) +#define AGC1_R53 (BBP_AGC1 + 0xd4) +#define AGC1_R55 (BBP_AGC1 + 0xdc) +#define AGC1_R57 (BBP_AGC1 + 0xe4) +#define AGC1_R58 (BBP_AGC1 + 0xe8) +#define AGC1_R59 (BBP_AGC1 + 0xec) +#define AGC1_R60 (BBP_AGC1 + 0xf0) +#define AGC1_R61 (BBP_AGC1 + 0xf4) +#define AGC1_R62 (BBP_AGC1 + 0xf8) +#define AGC1_R63 (BBP_AGC1 + 0xfc) + +/* 0x2400 ~ */ +#define TXC_R0 (BBP_TXC + 0x00) +#define TXC_R1 (BBP_TXC + 0x04) +#define TXC_R2 (BBP_TXC + 0x08) + +/* 0x2500 ~ */ +#define RXC_R0 (BBP_RXC + 0x00) +#define RXC_R1 (BBP_RXC + 0x04) +#define RXC_R2 (BBP_RXC + 0x08) +#define RXC_R3 (BBP_RXC + 0x0c) +#define RXC_R4 (BBP_RXC + 0x10) +#define RXC_R5 (BBP_RXC + 0x14) +#define RXC_R7 (BBP_RXC + 0x1C) +#define RXC_R9 (BBP_RXC + 0x28) + +/* 0x2600 ~ */ +#define TXO_R0 (BBP_TXO + 0x00) +#define TXO_R1 (BBP_TXO + 0x04) +#define TXO_R2 (BBP_TXO + 0x08) +#define TXO_R3 (BBP_TXO + 0x0c) +#define TXO_R4 (BBP_TXO + 0x10) +#define TXO_R5 (BBP_TXO + 0x14) +#define TXO_R6 (BBP_TXO + 0x18) +#define TXO_R7 (BBP_TXO + 0x1c) +#define TXO_R8 (BBP_TXO + 0x20) +#define TXO_R13 (BBP_TXO + 0x34) + +/* 0x2700 ~ */ +#define TXBE_R0 (BBP_TXBE + 0x00) +#define TXBE_R1 (BBP_TXBE + 0x04) +#define TXBE_R2 (BBP_TXBE + 0x08) +#define TXBE_R3 (BBP_TXBE + 0x0c) +#define TXBE_R4 (BBP_TXBE + 0x10) +#define TXBE_R5 (BBP_TXBE + 0x14) +#define TXBE_R6 (BBP_TXBE + 0x18) +#define TXBE_R8 (BBP_TXBE + 0x20) +#define TXBE_R9 (BBP_TXBE + 0x24) +#define TXBE_R10 (BBP_TXBE + 0x28) +#define TXBE_R12 (BBP_TXBE + 0x30) +#define TXBE_R13 (BBP_TXBE + 0x34) +#define TXBE_R14 (BBP_TXBE + 0x38) +#define TXBE_R15 (BBP_TXBE + 0x3c) +#define TXBE_R16 (BBP_TXBE + 0x40) +#define TXBE_R17 (BBP_TXBE + 0x44) +#define TXBE_R52 (BBP_TXBE + 0xd0) + +/* 0x2800 ~ */ +#define RXFE_R0 (BBP_RXFE + 0x00) +#define RXFE_R1 (BBP_RXFE + 0x04) +#define RXFE_R2 (BBP_RXFE + 0x08) +#define RXFE_R3 (BBP_RXFE + 0x0c) +#define RXFE_R4 (BBP_RXFE + 0x10) +#define RXFE_R17 (BBP_RXFE + 0x44) + +/* 0x2900 ~ */ +#define RXO_R0 (BBP_RXO + 0x00) +#define RXO_R9 (BBP_RXO + 0x24) +#define RXO_R13 (BBP_RXO + 0x34) +#define RXO_R14 (BBP_RXO + 0x38) +#define RXO_R15 (BBP_RXO + 0x3c) +#define RXO_R16 (BBP_RXO + 0x40) +#define RXO_R17 (BBP_RXO + 0x44) +#define RXO_R18 (BBP_RXO + 0x48) +#define RXO_R19 (BBP_RXO + 0x4C) +#define RXO_R20 (BBP_RXO + 0x50) +#define RXO_R21 (BBP_RXO + 0x54) +#define RXO_R24 (BBP_RXO + 0x60) +#define RXO_R28 (BBP_RXO + 0x70) +#define RXO_R29 (BBP_RXO + 0x74) +#define RXO_R63 (BBP_RXO + 0xfc) + +/* 0x2a00 ~ */ +#define DFS_R0 (BBP_DFS + 0x00) +#define DFS_R1 (BBP_DFS + 0x04) +#define DFS_R2 (BBP_DFS + 0x08) +#define DFS_R3 (BBP_DFS + 0x0c) +#define DFS_R4 (BBP_DFS + 0x10) +#define DFS_R5 (BBP_DFS + 0x14) +#define DFS_R7 (BBP_DFS + 0x1c) +#define DFS_R9 (BBP_DFS + 0x24) +#define DFS_R11 (BBP_DFS + 0x2c) +#define DFS_R13 (BBP_DFS + 0x34) +#define DFS_R14 (BBP_DFS + 0x38) +#define DFS_R15 (BBP_DFS + 0x3c) +#define DFS_R17 (BBP_DFS + 0x44) +#define DFS_R19 (BBP_DFS + 0x4c) +#define DFS_R20 (BBP_DFS + 0x50) +#define DFS_R22 (BBP_DFS + 0x58) +#define DFS_R23 (BBP_DFS + 0x5c) +#define DFS_R25 (BBP_DFS + 0x64) +#define DFS_R26 (BBP_DFS + 0x68) +#define DFS_R28 (BBP_DFS + 0x70) +#define DFS_R30 (BBP_DFS + 0x78) +#define DFS_R31 (BBP_DFS + 0x7c) +#define DFS_R32 (BBP_DFS + 0x80) +#define DFS_R36 (BBP_DFS + 0x90) +#define DFS_R37 (BBP_DFS + 0x94) + +/* 0x2b00 ~ */ +#define TR_R0 (BBP_TR + 0x00) +#define TR_R1 (BBP_TR + 0x04) +#define TR_R2 (BBP_TR + 0x08) +#define TR_R3 (BBP_TR + 0x0c) +#define TR_R4 (BBP_TR + 0x10) +#define TR_R5 (BBP_TR + 0x14) +#define TR_R6 (BBP_TR + 0x18) +#define TR_R9 (BBP_TR + 0x24) + +/* 0x2c00 ~ */ +#define CAL_R0 (BBP_CAL + 0x00) +#define CAL_R1 (BBP_CAL + 0x04) +#define CAL_R2 (BBP_CAL + 0x08) +#define CAL_R3 (BBP_CAL + 0x0c) +#define CAL_R4 (BBP_CAL + 0x10) +#define CAL_R5 (BBP_CAL + 0x14) +#define CAL_R6 (BBP_CAL + 0x18) +#define CAL_R7 (BBP_CAL + 0x1C) +#define CAL_R8 (BBP_CAL + 0x20) +#define CAL_R9 (BBP_CAL + 0x24) +#define CAL_R10 (BBP_CAL + 0x28) +#define CAL_R11 (BBP_CAL + 0x2C) +#define CAL_R12 (BBP_CAL + 0x30) +#define CAL_R13 (BBP_CAL + 0x34) +#define CAL_R14 (BBP_CAL + 0x38) +#define CAL_R15 (BBP_CAL + 0x3C) +#define CAL_R16 (BBP_CAL + 0x40) +#define CAL_R17 (BBP_CAL + 0x44) +#define CAL_R18 (BBP_CAL + 0x48) +#define CAL_R19 (BBP_CAL + 0x4C) +#define CAL_R20 (BBP_CAL + 0x50) +#define CAL_R21 (BBP_CAL + 0x54) +#define CAL_R22 (BBP_CAL + 0x58) +#define CAL_R23 (BBP_CAL + 0x5C) +#define CAL_R24 (BBP_CAL + 0x60) +#define CAL_R25 (BBP_CAL + 0x64) +#define CAL_R26 (BBP_CAL + 0x68) +#define CAL_R27 (BBP_CAL + 0x6C) +#define CAL_R28 (BBP_CAL + 0x70) +#define CAL_R29 (BBP_CAL + 0x74) +#define CAL_R30 (BBP_CAL + 0x78) +#define CAL_R31 (BBP_CAL + 0x7C) +#define CAL_R32 (BBP_CAL + 0x80) +#define CAL_R33 (BBP_CAL + 0x84) +#define CAL_R34 (BBP_CAL + 0x88) +#define CAL_R35 (BBP_CAL + 0x8C) +#define CAL_R36 (BBP_CAL + 0x90) +#define CAL_R37 (BBP_CAL + 0x94) +#define CAL_R38 (BBP_CAL + 0x98) +#define CAL_R39 (BBP_CAL + 0x9C) +#define CAL_R40 (BBP_CAL + 0xA0) +#define CAL_R41 (BBP_CAL + 0xA4) +#define CAL_R42 (BBP_CAL + 0xA8) +#define CAL_R43 (BBP_CAL + 0xAC) +#define CAL_R44 (BBP_CAL + 0xB0) +#define CAL_R45 (BBP_CAL + 0xB4) +#define CAL_R46 (BBP_CAL + 0xB8) +#define CAL_R47 (BBP_CAL + 0xBC) +#define CAL_R48 (BBP_CAL + 0xC0) +#define CAL_R49 (BBP_CAL + 0xC4) +#define CAL_R50 (BBP_CAL + 0xC8) +#define CAL_R51 (BBP_CAL + 0xCC) +#define CAL_R52 (BBP_CAL + 0xD0) +#define CAL_R53 (BBP_CAL + 0xD4) +#define CAL_R54 (BBP_CAL + 0xD8) +#define CAL_R55 (BBP_CAL + 0xDC) +#define CAL_R56 (BBP_CAL + 0xE0) +#define CAL_R57 (BBP_CAL + 0xE4) +#define CAL_R58 (BBP_CAL + 0xE8) +#define CAL_R59 (BBP_CAL + 0xEC) +#define CAL_R60 (BBP_CAL + 0xF0) +#define CAL_R61 (BBP_CAL + 0xF4) +#define CAL_R62 (BBP_CAL + 0xF8) +#define CAL_R63 (BBP_CAL + 0xFC) +#define CAL_R64 (BBP_CAL + 0x100) +#define CAL_R65 (BBP_CAL + 0x104) +#define CAL_R66 (BBP_CAL + 0x108) +#define CAL_R67 (BBP_CAL + 0x10C) +#define CAL_R68 (BBP_CAL + 0x110) +#define CAL_R69 (BBP_CAL + 0x114) +#define CAL_R70 (BBP_CAL + 0x118) + +/* 0x2e00 ~ */ +#define DSC_R0 (BBP_DSC + 0x00) +#define DSC_R8 (BBP_DSC + 0x20) +#define DSC_R10 (BBP_DSC + 0x28) + +/* 0x2f00 ~ */ +#define PFMU_R0 (BBP_PFMU + 0x00) +#define PFMU_R1 (BBP_PFMU + 0x04) +#define PFMU_R8 (BBP_PFMU + 0x20) +#define PFMU_R9 (BBP_PFMU + 0x24) +#define PFMU_R10 (BBP_PFMU + 0x28) +#define PFMU_R11 (BBP_PFMU + 0x2C) +#define PFMU_R12 (BBP_PFMU + 0x30) +#define PFMU_R13 (BBP_PFMU + 0x34) +#define PFMU_R14 (BBP_PFMU + 0x38) +#define PFMU_R15 (BBP_PFMU + 0x3C) +#define PFMU_R19 (BBP_PFMU + 0x4C) +#define PFMU_R20 (BBP_PFMU + 0x50) +#define PFMU_R21 (BBP_PFMU + 0x54) +#define PFMU_R22 (BBP_PFMU + 0x58) +#define PFMU_R23 (BBP_PFMU + 0x5C) +#define PFMU_R51 (BBP_PFMU + 0xCC) +#define PFMU_R54 (BBP_PFMU + 0xD8) +#define PFMU_R57 (BBP_PFMU + 0xE4) + + +#define RTMP_BBP_IO_READ32(_p, _i, _pV) RTMP_IO_READ32(_p, _i, _pV) +#define RTMP_BBP_IO_WRITE32(_p, _i, _v) RTMP_IO_WRITE32(_p, _i, _v) + + +struct _RTMP_ADAPTER; +INT rlt_phy_probe(struct _RTMP_ADAPTER *pAd); + +#endif /* __RLT_BBP_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/rtmp_bbp.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/rtmp_bbp.h new file mode 100644 index 000000000..1b3c602f4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/phy/rtmp_bbp.h @@ -0,0 +1,765 @@ +/* + *************************************************************************** + * 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_bbp.h + + Abstract: + Ralink Wireless Chip PHY(BBP) related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_BBP_H__ +#define __RTMP_BBP_H__ + + +/* + BBP sections +*/ +#define BBP_R0 0 /* version */ +#define BBP_R1 1 /* TSSI */ +#define BBP_R2 2 /* TX configure */ +#define BBP_R3 3 +#define BBP_R4 4 +#define BBP_R5 5 +#define BBP_R6 6 +#define BBP_R10 10 /* Rate report */ +#define BBP_R11 11 +#define BBP_R12 12 +#define BBP_R13 13 +#define BBP_R14 14 /* RX configure */ +#define BBP_R15 15 +#define BBP_R16 16 +#define BBP_R17 17 /* RX sensibility */ +#define BBP_R18 18 +#define BBP_R19 19 +#define BBP_R20 20 +#define BBP_R21 21 +#define BBP_R22 22 +#define BBP_R23 23 +#define BBP_R24 24 +#define BBP_R25 25 +#define BBP_R26 26 +#define BBP_R27 27 +#define BBP_R28 28 +#define BBP_R30 30 +#define BBP_R31 31 +#define BBP_R47 47 +#define BBP_R49 49 /*TSSI */ +#define BBP_R50 50 +#define BBP_R51 51 +#define BBP_R52 52 +#define BBP_R53 53 +#define BBP_R54 54 +#define BBP_R55 55 +#define BBP_R58 58 +#define BBP_R60 60 +#define BBP_R57 57 +#define BBP_R61 61 +#define BBP_R62 62 /* Rx SQ0 Threshold HIGH */ +#define BBP_R63 63 +#define BBP_R64 64 +#define BBP_R65 65 +#define BBP_R66 66 +#define BBP_R67 67 +#define BBP_R68 68 +#define BBP_R69 69 +#define BBP_R70 70 /* Rx AGC SQ CCK Xcorr threshold */ +#define BBP_R73 73 +#define BBP_R74 74 +#define BBP_R75 75 +#define BBP_R76 76 +#define BBP_R77 77 +#define BBP_R78 78 +#define BBP_R79 79 +#define BBP_R80 80 +#define BBP_R81 81 +#define BBP_R82 82 +#define BBP_R83 83 +#define BBP_R84 84 +#define BBP_R86 86 +#define BBP_R87 87 +#define BBP_R88 88 +#define BBP_R91 91 +#define BBP_R92 92 +#define BBP_R93 93 +#define BBP_R94 94 /* Tx Gain Control */ +#define BBP_R95 95 +#define BBP_R96 96 +#define BBP_R98 98 +#define BBP_R99 99 +#define BBP_R101 101 +#define BBP_R103 103 +#define BBP_R104 104 +#define BBP_R105 105 +#define BBP_R106 106 +#define BBP_R107 107 +#define BBP_R108 108 +#define BBP_R109 109 +#define BBP_R110 110 +#define BBP_R113 113 +#define BBP_R114 114 +#define BBP_R115 115 +#define BBP_R116 116 +#define BBP_R117 117 +#define BBP_R118 118 +#define BBP_R119 119 +#define BBP_R120 120 +#define BBP_R121 121 +#define BBP_R122 122 +#define BBP_R123 123 +#define BBP_R126 126 +#define BBP_R127 127 +#define BBP_R128 128 +#define BBP_R129 129 +#define BBP_R130 130 +#define BBP_R131 131 +#define BBP_R132 132 +#define BBP_R133 133 +#define BBP_R134 134 +#define BBP_R135 135 +#define BBP_R137 137 +#define BBP_R138 138 /* add by johnli, RF power sequence setup, ADC dynamic on/off control */ +#define BBP_R139 139 +#define BBP_R140 140 +#define BBP_R141 141 +#define BBP_R142 142 +#define BBP_R143 143 +#define BBP_R144 144 +#define BBP_R145 145 +#define BBP_R146 146 +#define BBP_R147 147 +#define BBP_R148 148 +#define BBP_R149 149 +#define BBP_R150 150 +#define BBP_R151 151 +#define BBP_R152 152 +#define BBP_R153 153 +#define BBP_R154 154 +#define BBP_R155 155 +#define BBP_R156 156 +#define BBP_R157 157 +#define BBP_R158 158 /* Calibration register are accessed through R158 and R159 */ +#define BBP_R159 159 +#define BBP_R160 160 /* Tx BF control */ +#define BBP_R161 161 +#define BBP_R162 162 +#define BBP_R163 163 +#define BBP_R164 164 +#define BBP_R165 165 +#define BBP_R166 166 +#define BBP_R167 167 +#define BBP_R168 168 +#define BBP_R169 169 +#define BBP_R170 170 +#define BBP_R171 171 +#define BBP_R172 172 +#define BBP_R173 173 +#define BBP_R174 174 +#define BBP_R175 175 +#define BBP_R176 176 +#define BBP_R177 177 +#define BBP_R178 178 +#define BBP_R179 179 +#define BBP_R180 180 +#define BBP_R181 181 +#define BBP_R182 182 +#define BBP_R183 183 +#define BBP_R184 184 +#define BBP_R185 185 +#define BBP_R186 186 +#define BBP_R187 187 +#define BBP_R188 188 +#define BBP_R189 189 +#define BBP_R190 190 +#define BBP_R191 191 +#define BBP_R195 195 +#define BBP_R196 196 +#define BBP_R200 200 +#define BBP_R201 201 +#define BBP_R202 202 +#define BBP_R203 203 +#define BBP_R204 204 +#define BBP_R205 205 +#define BBP_R206 206 +#define BBP_R207 207 +#define BBP_R208 208 +#define BBP_R209 209 +#define BBP_R210 210 +#define BBP_R211 211 + +#define BBP_R241 241 +#define BBP_R242 242 +#define BBP_R244 244 + +#define BBP_R250 250 +#define BBP_R253 253 +#define BBP_R254 254 +#define BBP_R255 255 + +#define BBPR94_DEFAULT 0x06 /* Add 1 value will gain 1db */ + + +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R47_STRUC { + struct + { + UCHAR Adc6On:1; + UCHAR Reserved:2; + UCHAR TssiMode:2; + UCHAR TssiUpdateReq:1; + UCHAR TssiReportSel:2; + } field; + + UCHAR byte; +} BBP_R47_STRUC, *PBBP_R47_STRUC; +#else +typedef union _BBP_R47_STRUC { + struct + { + UCHAR TssiReportSel:2; + UCHAR TssiUpdateReq:1; + UCHAR TssiMode:2; + UCHAR Reserved:2; + UCHAR Adc6On:1; + } field; + + UCHAR byte; +} BBP_R47_STRUC, *PBBP_R47_STRUC; +#endif + + +/* */ +/* BBP R105 (FEQ control, MLD control and SIG remodulation) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R105_STRUC { + struct + { + UCHAR Reserve1:4; /* Reserved field */ + UCHAR EnableSIGRemodulation:1; /* Enable the channel estimation updates based on remodulation of L-SIG and HT-SIG symbols. */ + UCHAR MLDFor2Stream:1; /* Apply Maximum Likelihood Detection (MLD) for 2 stream case (reserved field if single RX) */ + UCHAR IndependentFeedForwardCompensation:1; /* Apply independent feed-forward compensation for independent stream. */ + UCHAR DetectSIGOnPrimaryChannelOnly:1; /* Under 40 MHz band, detect SIG on primary channel only. */ + } field; + + UCHAR byte; +} BBP_R105_STRUC, *PBBP_R105_STRUC; +#else +typedef union _BBP_R105_STRUC { + struct + { + UCHAR DetectSIGOnPrimaryChannelOnly:1; /* Under 40 MHz band, detect SIG on primary channel only. */ + UCHAR IndependentFeedForwardCompensation:1; /* Apply independent feed-forward compensation for independent stream. */ + UCHAR MLDFor2Stream:1; /* Apply Maximum Likelihood Detection (MLD) for 2 stream case (reserved field if single RX) */ + UCHAR EnableSIGRemodulation:1; /* Enable the channel estimation updates based on remodulation of L-SIG and HT-SIG symbols. */ + UCHAR Reserve1:4; /* Reserved field */ + } field; + + UCHAR byte; +} BBP_R105_STRUC, *PBBP_R105_STRUC; +#endif + +/* */ +/* BBP R106 (GI remover) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R106_STRUC { + struct + { + UCHAR EnableLowPowerFSD:1; /* enable/disable the low power FSD */ + UCHAR ShortGI_Offset40:4; /* Delay GI remover when the short GI is detected in 40MHz band (40M sampling rate) */ + UCHAR ShortGI_Offset20:3; /* Delay GI remover when the short GI is detected in 20MHz band (20M sampling rate) */ + } field; + + UCHAR byte; +} BBP_R106_STRUC, *PBBP_R106_STRUC; +#else +typedef union _BBP_R106_STRUC { + struct + { + UCHAR ShortGI_Offset20:3; /* Delay GI remover when the short GI is detected in 20MHz band (20M sampling rate) */ + UCHAR ShortGI_Offset40:4; /* Delay GI remover when the short GI is detected in 40MHz band (40M sampling rate) */ + UCHAR EnableLowPowerFSD:1; /* enable/disable the low power FSD */ + } field; + + UCHAR byte; +} BBP_R106_STRUC, *PBBP_R106_STRUC; +#endif + +/* */ +/* BBP R109 (Tx power control in 0.1dB step) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R109_STRUC { + struct + { + UCHAR Tx1PowerCtrl:4; /* Tx1 power control in 0.1dB step (valid: 0~10) */ + UCHAR Tx0PowerCtrl:4; /* Tx0 power control in 0.1dB step (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R109_STRUC, *PBBP_R109_STRUC; +#else +typedef union _BBP_R109_STRUC { + struct + { + UCHAR Tx0PowerCtrl:4; /* Tx0 power control in 0.1dB step (valid: 0~10) */ + UCHAR Tx1PowerCtrl:4; /* Tx0 power control in 0.1dB step (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R109_STRUC, *PBBP_R109_STRUC; +#endif + +/* */ +/* BBP R110 (Tx power control in 0.1dB step) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R110_STRUC { + struct + { + UCHAR Tx2PowerCtrl:4; /* Tx2 power control in 0.1dB step (valid: 0~10) */ + UCHAR AllTxPowerCtrl:4; /* All transmitters' fine power control in 0.1dB (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R110_STRUC, *PBBP_R110_STRUC; +#else +typedef union _BBP_R110_STRUC { + struct + { + UCHAR AllTxPowerCtrl:4; /* All transmitters' fine power control in 0.1dB (valid: 0~10) */ + UCHAR Tx2PowerCtrl:4; /* Tx2 power control in 0.1dB step (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R110_STRUC, *PBBP_R110_STRUC; +#endif + +/* */ +/* BBP R179 (Test config #1) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R179_STRUC { + struct + { + UCHAR DataIndex1:8; /* Data index #1 */ + } field; + + UCHAR byte; +} BBP_R179_STRUC, *PBBP_R179_STRUC; +#else +typedef union _BBP_R179_STRUC { + struct + { + UCHAR DataIndex1:8; /* Data index #1 */ + } field; + + UCHAR byte; +} BBP_R179_STRUC, *PBBP_R179_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* */ +/* BBP R180 (Test config #2) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R180_STRUC { + struct + { + UCHAR DataIndex2:8; /* Data index #2 */ + } field; + + UCHAR byte; +} BBP_R180_STRUC, *PBBP_R180_STRUC; +#else +typedef union _BBP_R180_STRUC { + struct + { + UCHAR DataIndex2:8; /* Data index #2 */ + } field; + + UCHAR byte; +} BBP_R180_STRUC, *PBBP_R180_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* */ +/* BBP R182 (Test data port) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R182_STRUC { + struct + { + UCHAR DataArray:8; /* Data array indexed by BBP R179 and R180 */ + } field; + + UCHAR byte; +} BBP_R182_STRUC, *PBBP_R182_STRUC; +#else +typedef union _BBP_R182_STRUC { + struct + { + UCHAR DataArray:8; /* Data array indexed by BBP R179 and R180 */ + } field; + + UCHAR byte; +} BBP_R182_STRUC, *PBBP_R182_STRUC; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RTMP_RBUS_SUPPORT +/* TODO: for this definition, need to modify it!! */ + /*#define MAX_BBP_ID 255 */ + #define MAX_BBP_ID 200 + +#else + #define MAX_BBP_ID 136 + +#endif /* RTMP_RBUS_SUPPORT */ + + +#if defined(RT5572) || defined(RT6352) +#undef MAX_BBP_ID +#define MAX_BBP_ID 248 +#undef MAX_BBP_MSG_SIZE +#define MAX_BBP_MSG_SIZE 4096 +#endif /* defined(RT5572) || defined(RT6352) */ + + +/* */ +/* BBP & RF are using indirect access. Before write any value into it. */ +/* We have to make sure there is no outstanding command pending via checking busy bit. */ +/* */ +#define MAX_BUSY_COUNT 100 /* Number of retry before failing access BBP & RF indirect register */ +#define MAX_BUSY_COUNT_US 2000 /* Number of retry before failing access BBP & RF indirect register */ + +/*#define PHY_TR_SWITCH_TIME 5 // usec */ + +/*#define BBP_R17_LOW_SENSIBILITY 0x50 */ +/*#define BBP_R17_MID_SENSIBILITY 0x41 */ +/*#define BBP_R17_DYNAMIC_UP_BOUND 0x40 */ + +#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 +#define RSSI_FOR_LOW_SENSIBILITY -58 +#define RSSI_FOR_MID_LOW_SENSIBILITY -65 /*-80*/ +#define RSSI_FOR_MID_SENSIBILITY -90 + +/***************************************************************************** + RF register Read/Write marco definition + *****************************************************************************/ +#ifdef RTMP_MAC_PCI +#define RTMP_RF_IO_WRITE32(_A, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + RF_CSR_CFG0_STRUC _value; \ + ULONG _busyCnt = 0; \ + \ + do { \ + RTMP_IO_READ32((_A), RF_CSR_CFG0, &_value.word); \ + if (_value.field.Busy == IDLE) \ + break; \ + _busyCnt++; \ + }while (_busyCnt < MAX_BUSY_COUNT); \ + if(_busyCnt < MAX_BUSY_COUNT) \ + { \ + RTMP_IO_WRITE32((_A), RF_CSR_CFG0, (_V)); \ + } \ + } \ + if ((_A)->ShowRf) \ + { \ + printk("RF:%x\n", _V); \ + } \ +} +#endif /* RTMP_MAC_PCI */ + + + +/***************************************************************************** + BBP register Read/Write marco definitions. + we read/write the bbp value by register's ID. + Generate PER to test BA + *****************************************************************************/ +#ifdef RTMP_MAC_PCI +/* + basic marco for BBP read operation. + _pAd: the data structure pointer of RTMP_ADAPTER + _bbpID : the bbp register ID + _pV: data pointer used to save the value of queried bbp register. + _bViaMCU: if we need access the bbp via the MCU. +*/ +#ifdef RELASE_INCLUDE +/* + The RTMP_PCIE_PS_L3_BBP_IO_READ8 is used to support PCIE power-saving solution3. + "brc =AsicSendCommandToMcuBBP" is used to avoid any muc command is executed during + RF_OFF command. +*/ +#endif /* RELASE_INCLUDE */ + + +#ifdef CONFIG_STA_SUPPORT +#define IS_SUPPORT_PCIE_PS_L3(_pAd) (((_pAd)->OpMode == OPMODE_STA) &&\ + (IS_RT3090((_pAd)) || IS_RT3572((_pAd)) || IS_RT3390((_pAd)) || IS_RT3593((_pAd)) || IS_RT5390((_pAd)) || IS_RT5392((_pAd)) || IS_RT3290((_pAd))) && \ + ((_pAd)->StaCfg.PSControl.field.rt30xxPowerMode == 3)&& \ + ((_pAd)->StaCfg.PSControl.field.EnableNewPS == TRUE)) + +#define RTMP_PCIE_PS_L3_BBP_IO_READ8(_pAd, _bbpID, _pV, _bViaMCU) \ + do{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int _busyCnt, _secCnt, _regID; \ + BOOLEAN brc; \ + ULONG __IrqFlags = 0; \ + \ + if ((_bViaMCU) == TRUE) \ + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(_pAd, __IrqFlags); \ + _regID = ((_bViaMCU) == TRUE ? H2M_BBP_AGENT : BBP_CSR_CFG); \ + BbpCsr.field.Busy = IDLE; \ + if (((_pAd)->bPCIclkOff == FALSE) \ + && (((_pAd)->LastMCUCmd== WAKE_MCU_CMD) || ((_pAd)->LastMCUCmd==0x72))\ + && ((_pAd)->brt30xxBanMcuCmd == FALSE)) \ + { \ + for (_busyCnt=0; _busyCntbPCIclkOff == TRUE)) \ + { \ + DBGPRINT_ERR(("RTMP_PCIE_PS_L3_BBP_IO_READ8(viaMCU=%d) read R%d fail(reason:clk=%d,busy=%x)\n", (_bViaMCU), _bbpID,(_pAd)->bPCIclkOff ,BbpCsr.field.Busy)); \ + *(_pV) = (_pAd)->BbpWriteLatch[_bbpID]; \ + } \ + if ((_bViaMCU) == TRUE) \ + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(_pAd, __IrqFlags); \ +}while(0) +#else +#define IS_SUPPORT_PCIE_PS_L3(_pAd) FALSE +#define RTMP_PCIE_PS_L3_BBP_IO_READ8(_pAd, _bbpID, _pV, _bViaMCU) +#endif /* CONFIG_STA_SUPPORT */ + + +/* + This marco used for the BBP read operation which didn't need via MCU. +*/ +#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ + RTMP_BBP_IO_READ8((_A), (_I), (_pV), TRUE) + + +/* + basic marco for BBP write operation. + _pAd: the data structure pointer of RTMP_ADAPTER + _bbpID : the bbp register ID + _pV: data used to save the value of queried bbp register. + _bViaMCU: if we need access the bbp via the MCU. +*/ +#ifdef CONFIG_STA_SUPPORT +#define RTMP_PCIE_PS_L3_BBP_IO_WRITE8(_pAd, _bbpID, _pV, _bViaMCU) \ + do{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int k, _busyCnt=0, _regID; \ + BOOLEAN brc; \ + ULONG __IrqFlags = 0; \ + if ((_bViaMCU) == TRUE) \ + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(_pAd, __IrqFlags); \ + _regID = ((_bViaMCU) == TRUE ? H2M_BBP_AGENT : BBP_CSR_CFG); \ + if (((_pAd)->bPCIclkOff == FALSE) \ + && ((_pAd)->brt30xxBanMcuCmd == FALSE)) \ + { \ + if (_pAd->AccessBBPFailCount > 20) \ + { \ + AsicResetBBPAgent(_pAd); \ + _pAd->AccessBBPFailCount = 0; \ + } \ + for (_busyCnt=1; _busyCntOpMode == OPMODE_AP) \ + RtmpusecDelay(1000); \ + } \ + if (brc == TRUE) \ + { \ + for (k=0; kBbpWriteLatch[_bbpID] = _pV; \ + } \ + else \ + { \ + BbpCsr.field.Busy = 0; \ + RTMP_IO_WRITE32(_pAd, _regID, BbpCsr.word); \ + } \ + break; \ + } \ + } \ + else \ + { \ + DBGPRINT_ERR((" brt30xxBanMcuCmd = %d. Write BBP %d \n", (_pAd)->brt30xxBanMcuCmd, (_regID))); \ + } \ + if ((_busyCnt == MAX_BUSY_COUNT) || ((_pAd)->bPCIclkOff == TRUE)) \ + { \ + if (_busyCnt == MAX_BUSY_COUNT) \ + (_pAd)->AccessBBPFailCount++; \ + DBGPRINT_ERR(("BBP write R%d=0x%x fail. BusyCnt= %d.bPCIclkOff = %d. \n", _regID, BbpCsr.word, _busyCnt, (_pAd)->bPCIclkOff )); \ + } \ + if ((_bViaMCU) == TRUE) \ + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(_pAd, __IrqFlags); \ + }while(0) +#else +#define RTMP_PCIE_PS_L3_BBP_IO_WRITE8(_pAd, _bbpID, _pV, _bViaMCU) +#endif /* CONFIG_STA_SUPPORT */ + + +/* + This marco used for the BBP write operation which didn't need via MCU. +*/ +#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _pV) RTMP_BBP_IO_WRITE8((_A), (_I), (_pV), FALSE) + + +/* + Hardware Periodic Timer interrupt setting. + Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. +*/ +#define RTMP_HW_TIMER_INT_SET(_pAd, _V) \ + { \ + UINT32 temp; \ + RTMP_IO_READ32(_pAd, INT_TIMER_CFG, &temp); \ + temp &= 0x0000ffff; \ + temp |= _V << 20; \ + RTMP_IO_WRITE32(_pAd, INT_TIMER_CFG, temp); \ + } + +/* Enable Hardware Periodic Timer interrupt */ +#define RTMP_HW_TIMER_INT_ENABLE(_pAd) \ + { \ + UINT32 temp; \ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &temp); \ + temp |=0x2; \ + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, temp); \ + } + +/* Disable Hardware Periodic Timer interrupt */ +#define RTMP_HW_TIMER_INT_DISABLE(_pAd) \ + { \ + UINT32 temp; \ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &temp); \ + temp &=~(0x2); \ + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, temp); \ + } +#endif /* RTMP_MAC_PCI */ + +#ifdef CARRIER_DETECTION_SUPPORT +/*TONE_RADAR_DETECT_V2*/ +#define RTMP_CARRIER_IO_READ8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R184, _I); \ + RTMP_BBP_IO_READ8_BY_REG_ID(_A, BBP_R185, _V); \ +} +#define RTMP_CARRIER_IO_WRITE8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R184, _I); \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R185, _V); \ +} +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT +#define RTMP_DFS_IO_READ8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R140, _I); \ + RTMP_BBP_IO_READ8_BY_REG_ID(_A, BBP_R141, _V); \ +} + +#define RTMP_DFS_IO_WRITE8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R140, _I); \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R141, _V); \ +} +#endif /*DFS_SUPPORT*/ + + + + + +struct _RMTP_ADAPTER; + +INT rtmp_phy_probe(struct _RTMP_ADAPTER *pAd); + +VOID RTMP_BBP_IO_READ8(struct _RTMP_ADAPTER *pAd, UCHAR Offset, UINT8 *pVal, BOOLEAN FlgValidMCR); +VOID RTMP_BBP_IO_WRITE8(struct _RTMP_ADAPTER *pAd, UCHAR Offset, UINT8 Val, BOOLEAN FlgValidMCR); + +NTSTATUS RTMP_BBP_IO_READ8_BY_REG_ID(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT8 *pVal); +NTSTATUS RTMP_BBP_IO_WRITE8_BY_REG_ID(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT8 Val); + +#endif /* __RTMP_BBP_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/pmf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/pmf.h new file mode 100644 index 000000000..86235cd6c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/pmf.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * 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. + **************************************************************************** + + Abstract: + IEEE P802.11w + + */ +#ifndef __PMF_H +#define __PMF_H +#ifdef DOT11W_PMF_SUPPORT + +VOID PMF_PeerAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PMF_MlmeSAQueryReq( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PMF_PeerSAQueryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PMF_PeerSAQueryRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PMF_DerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len); + +VOID PMF_DeriveIGTK( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *output); + +VOID PMF_InsertIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +BOOLEAN PMF_ExtractIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT buf_len); + +VOID PMF_MakeRsnIeGMgmtCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len); + +NTSTATUS PMF_RsnCapableValidation( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pRsnie, + IN UINT rsnie_len, + IN BOOLEAN self_MFPC, + IN BOOLEAN self_MFPR, + IN PMAC_TABLE_ENTRY pEntry); + +BOOLEAN PMF_PerformTxFrameAction( + IN PRTMP_ADAPTER pAd, + OUT PNDIS_PACKET pPacket); + +BOOLEAN PMF_PerformRxFrameAction( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +void rtmp_read_pmf_parameters_from_file( + IN PRTMP_ADAPTER pAd, + IN PSTRING tmpbuf, + IN PSTRING pBuffer); + +INT Set_PMFMFPC_Proc ( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PMFMFPR_Proc ( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PMFSHA256_Proc ( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /* __PMF_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/pmf_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/pmf_cmm.h new file mode 100644 index 000000000..345546fe2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/pmf_cmm.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * 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: + Management Frame Protection Required is defined in IEEE802.11w + + Define all structures, data types that rtmp.h needed in this file. Don't + put any sturctures and functions definition which refer to RTMP_ADAPTER + Here. + +***************************************************************************/ + + +#ifdef DOT11W_PMF_SUPPORT + +#ifndef __PMF_CMM_H__ +#define __PMF_CMM_H__ + +#include "rtmp_type.h" +#include "dot11w_pmf.h" + +#define NORMAL_FRAME 0 +#define ERROR_FRAME 1 +#define NOT_ROBUST_GROUP_FRAME 2 +#define NOT_ROBUST_UNICAST_FRAME 3 +#define UNICAST_ROBUST_FRAME 4 +#define GROUP_ROBUST_FRAME 5 + +typedef enum _PMF_STATUS_NUM +{ + PMF_STATUS_SUCCESS, + PMF_POLICY_VIOLATION, + PMF_UNICAST_ENCRYPT_FAILURE, + PMF_ENCAP_BIP_FAILURE, + PMF_UNICAST_DECRYPT_FAILURE, + PMF_EXTRACT_BIP_FAILURE, + PMF_STATUS_RESV +} PMF_STATUS_NUM; + +/* + * Management Frame Protection Required is defined in IEEE802.11w + */ +typedef struct GNU_PACKED _PMF_CFG +{ + /* + * A STA sets this bit to 1 to advertise that protection of Robust + * Management Frames is enabled. + */ + BOOLEAN MFPC; /* This is actual active */ + BOOLEAN Desired_MFPC; /* This is user desired */ + + /* + * A STA sets this bit to 1 to advertise that protection of + * Robust Management Frames is mandatory. + * If a STA sets this bit to 1, then that STA only allows RSNAs + * from STAs which provide Management Frame Protection. + */ + BOOLEAN MFPR; /* This is actual active */ + BOOLEAN Desired_MFPR; /* This is user desired */ + + BOOLEAN PMFSHA256; /* This is actual active */ + BOOLEAN Desired_PMFSHA256; /* This is user desired */ + + UINT8 IGTK_KeyIdx; /* It shall be 4 or 5 */ + UCHAR IGTK[2][LEN_AES_GTK]; + UCHAR IPN[2][LEN_WPA_TSC]; +} PMF_CFG, *PPMF_CFG; + + +#endif /* __PMF_CMM_H__ */ +#endif /* DOT11W_PMF_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/radar.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/radar.h new file mode 100644 index 000000000..666ef8d75 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/radar.h @@ -0,0 +1,108 @@ +/* + *************************************************************************** + * 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: + radar.h + + Abstract: + CS/DFS common functions. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __RADAR_H__ +#define __RADAR_H__ + +#define DEFAULT_CAL_BUF_TIME 60 +#define DEFAULT_CAL_BUF_TIME_MAX 0x10000 + +/* RESTRICTION_BAND_1: 5600MHz ~ 5650MHz */ +#define RESTRICTION_BAND_1(_pAd) \ + ((_pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 || _pAd->CommonCfg.RegTransmitSetting.field.BW == BW_80) ? \ + ((_pAd->CommonCfg.Channel >= 116) && (_pAd->CommonCfg.Channel <= 128)) : \ + ((_pAd->CommonCfg.Channel >= 120) && (_pAd->CommonCfg.Channel <= 128))) + +#define IS_DOT11_H_RADAR_STATE(_pAd, _RadarState) \ + ( (_pAd->CommonCfg.Channel > 14) \ + && (_pAd->CommonCfg.bIEEE80211H == 1) \ + && RadarChannelCheck(_pAd, _pAd->CommonCfg.Channel) \ + && _pAd->Dot11_H.RDMode == _RadarState) + +/* 802.11H */ +typedef struct _DOT11_H { + /* 802.11H and DFS related params */ + UCHAR CSCount; /*Channel switch counter */ + UCHAR CSPeriod; /*Channel switch period (beacon count) */ + USHORT RDCount; /*Radar detection counter, if RDCount > ChMovingTime, start to send beacons*/ + UCHAR RDMode; /*Radar Detection mode */ + UCHAR org_ch; + UCHAR new_channel; + USHORT ChMovingTime; + BOOLEAN bDFSIndoor; + ULONG InServiceMonitorCount; /* unit: sec */ + ULONG CalBufTime; /* A Timing buffer for befroe calibrations which generates Tx signals */ +} DOT11_H, *PDOT11_H; + +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch); + +VOID RadarStateCheck( + IN PRTMP_ADAPTER pAd); + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd); + +UCHAR get_channel_by_reference( + IN PRTMP_ADAPTER pAd, + IN UINT8 mode); + +#ifdef CONFIG_AP_SUPPORT +VOID ChannelSwitchingCountDownProc( + IN PRTMP_ADAPTER pAd); +#endif /* CONFIG_AP_SUPPORT */ + +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd); + +INT Set_CSPeriod_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ChMovingTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BlockChReset_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#if defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) +INT Set_RadarShow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID CckMrcStatusCtrl( + IN PRTMP_ADAPTER pAd); + +VOID RadarGLRTCompensate( + IN PRTMP_ADAPTER pAd); + +#endif /*defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT)*/ + +#endif /* __RADAR_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/routing_tab.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/routing_tab.h new file mode 100644 index 000000000..f6111d7d5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/routing_tab.h @@ -0,0 +1,139 @@ +#ifndef __ROUTING_TAB_H__ +#define __ROUTING_TAB_H__ +/* + *************************************************************************** + * 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.h + + 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 "rtmp_def.h" + +#define ROUTING_ENTRY_AGEOUT (30*OS_HZ) /* seconds */ +#define ROUTING_ENTRY_MAX_RETRY 2 +#define ROUTING_POOL_SIZE 128 +#define ROUTING_HASH_TAB_SIZE 64 /* the legth of hash table must be power of 2. */ + +enum ROUTING_ENTRY_FLAG { + ROUTING_ENTRY_NONE = 0x0, + ROUTING_ENTRY_MWDS = 0x1, + ROUTING_ENTRY_IGMP = 0x2, + ROUTING_ALL_MASK = 0x3 +}; + +#define IS_VALID_ROUTING_ENTRY_FLAG(_x) (((_x) & ROUTING_ALL_MASK) != 0) +#define IS_ROUTING_ENTRY(_x) ((_x)->EntryFlag != ROUTING_ENTRY_NONE) +#define SET_ROUTING_ENTRY(_x, _y) ((_x)->EntryFlag |= (_y)) +#define CLEAR_ROUTING_ENTRY(_x, _y) ((_x)->EntryFlag &= ~(_y)) +#define ROUTING_ENTRY_TEST_FLAG(_x, _y) (((_x)->EntryFlag & (_y)) != 0) + +typedef struct _ROUTING_ENTRY { + struct _ROUTING_ENTRY *pNext; + UINT32 EntryFlag; + ULONG KeepAliveTime; + UCHAR RetryKeepAlive; + UCHAR Valid; + UCHAR Wcid; + UINT32 IPAddr; + UCHAR Mac[MAC_ADDR_LEN]; +} ROUTING_ENTRY, *PROUTING_ENTRY; + + +VOID RoutingTabInit( + IN PRTMP_ADAPTER pAd, + IN UINT32 Flag); + +VOID RoutingTabDestory( + IN PRTMP_ADAPTER pAd, + IN UINT32 Flag); + +VOID RoutingTabClear( + IN PRTMP_ADAPTER pAd, + IN UINT32 Flag); + +PROUTING_ENTRY RoutingTabGetFree( + IN PRTMP_ADAPTER pAd); + +VOID RoutingTabSetAllFree( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UINT32 Flag); + +VOID RoutingTabSetOneFree( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac, + IN UINT32 Flag); + +VOID RoutingEntryRefresh( + IN PRTMP_ADAPTER pAd, + IN PROUTING_ENTRY pRoutingEntry); + +VOID RoutingEntrySet( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN PUCHAR pMac, + IN PROUTING_ENTRY pRoutingEntry); + +INT RoutingTabGetEntryCount( + IN PRTMP_ADAPTER pAd); + + +INT32 GetHashID( + IN PUCHAR pMac); + +PROUTING_ENTRY GetRoutingTabHead( + IN PRTMP_ADAPTER pAd, + IN INT32 Index); + +BOOLEAN GetRoutingEntryAll( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UINT32 Flag, + IN INT32 BufMaxCount, + OUT const ROUTING_ENTRY **pEntryListBuf, + OUT PUINT32 pCount); + +PROUTING_ENTRY RoutingTabLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMac, + IN BOOLEAN bUpdateAliveTime, + OUT UCHAR* pWcid); + +VOID RoutingTabARPLookupUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +INT RoutingEntrySendAliveCheck( + IN PRTMP_ADAPTER pAd, + IN PROUTING_ENTRY pRoutingEntry, + IN UCHAR *pSrcMAC, + IN UINT32 SrcIP); + +VOID RoutingTabMaintain( + IN PRTMP_ADAPTER pAd); + +#endif /* ROUTING_TAB_SUPPORT */ +#endif /* __ROUTING_TAB_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rrm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rrm.h new file mode 100644 index 000000000..1c83c7f23 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rrm.h @@ -0,0 +1,471 @@ +/* + *************************************************************************** + * 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: + +***************************************************************************/ + + +#ifndef __RRM_H +#define __RRM_H + +#ifdef DOT11K_RRM_SUPPORT +#include "rtmp_type.h" +#include "rrm_cmm.h" + +#define RRM_QUIET_CNT_DEC(_V, _M) \ + ((_V) == 0 ? (_V = _M) : (_V)--) + +#define IS_RRM_ENABLE(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].RrmCfg.bDot11kRRMEnable == TRUE) + +#define IS_RRM_CAPABLE(_P) \ + ((_P)->CapabilityInfo & RRM_CAP_BIT) + +#define IS_RRM_BEACON_MEASURE(_P) \ + ((_P)->RrmEnCap.field.BeaconActiveMeasureCap == 1) + +#define IS_RRM_QUIET(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].RrmCfg.QuietCB.QuietState == RRM_QUIET_SILENT) + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +void RRM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_Dot11kRRM_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_BeaconReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_LinkMeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_TxStreamMeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_RRM_Selftest_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT RRM_InfoDisplay_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_CfgInit( + IN PRTMP_ADAPTER pAd); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_QuietUpdata( + IN PRTMP_ADAPTER pAd); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBcnReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBcnReq); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBcnReqSsidSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pSsid, + IN UINT8 SsidLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBcnReqRepCndSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 RepCnd, + IN UINT8 Threshold); + +VOID RRM_InsertBcnReqRepDetailSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Detail); + +/* + ========================================================================== + 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); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +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); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertNeighborTSFOffsetSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 TSFOffset, + IN UINT16 BcnInterval); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +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); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBssACDelayIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBssAvailableACIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertRequestIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertTxStreamReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBuf); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertTxStreamReqTriggerReportSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBuf); + + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_EnqueueBcnReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 IfIdx, + IN PRRM_MLME_BCN_REQ_INFO pMlmeBcnReq); + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_EnqueueNeighborReq( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pDA, + IN PUINT8 pSsid, + IN UINT8 SsidLen); +#endif /* CONFIG_STA_SUPPORT */ + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_EnqueueNeighborRep( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UINT8 DialogToken, + IN PCHAR pSsid, + IN UINT8 SsidLen); + +VOID RRM_EnqueueLinkMeasureReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 apidx); + +VOID RRM_EnqueueTxStreamMeasureReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 apidx, + IN PRRM_MLME_TRANSMIT_REQ_INFO pMlmeTxMeasureReq); +/* + ========================================================================== + 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); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +BOOLEAN RRM_PeerMeasureReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REPORT_INFO pMeasureReportInfo, + OUT PVOID *pMeasureRep); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_PeerNeighborReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) ; + +VOID RRM_PeerMeasureRepAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* DOT11K_RRM_SUPPORT */ + +#endif /* __RRM_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rrm_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rrm_cmm.h new file mode 100644 index 000000000..e348f8bd6 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rrm_cmm.h @@ -0,0 +1,106 @@ +/* + *************************************************************************** + * 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: + +***************************************************************************/ + + +#ifndef __RRM_CMM_H +#define __RRM_CMM_H + + +#ifdef DOT11K_RRM_SUPPORT +#include "rtmp_type.h" +#include "dot11k_rrm.h" + + +#define RRM_DEFAULT_QUIET_PERIOD 200 +#define RRM_DEFAULT_QUIET_DURATION 30 +#define RRM_DEFAULT_QUIET_OFFSET 20 + +#define RRM_QUIET_IDLE 0 +#define RRM_QUIET_SILENT 1 +typedef struct _RRM_QUIET_CB +{ + BOOLEAN QuietState; + UINT16 CurAid; + UINT8 MeasureCh; + RALINK_TIMER_STRUCT QuietOffsetTimer; + RALINK_TIMER_STRUCT QuietTimer; + + + UINT8 QuietCnt; + UINT8 QuietPeriod; + UINT8 QuietDuration; + UINT8 QuietOffset; +} RRM_QUIET_CB, *PRRM_QUIET_CB; + +typedef struct _RRM_CONFIG +{ + BOOLEAN bDot11kRRMEnableSet; + BOOLEAN bDot11kRRMEnable; + BOOLEAN bDot11kRRMNeighborRepTSFEnable; + RRM_QUIET_CB QuietCB; +} RRM_CONFIG, *PRRM_CONFIG; + +typedef union _RRM_BCN_REQ_CAP +{ + struct + { + UINT8 ReportCondition:1; + UINT8 ChannelRep:1; + UINT8 :6; + } field; + UINT8 word; +} RRM_BCN_REQ_CAP, *PRRM_BCN_REQ_CAP; + +typedef struct _RRM_MLME_BCN_REQ_INFO +{ + UINT16 MeasureDuration; + UINT8 Bssid[MAC_ADDR_LEN]; + PUINT8 pSsid; + UINT8 SsidLen; + UINT8 RegulatoryClass; + UINT8 MeasureCh; + UINT8 MeasureMode; + RRM_BCN_REQ_CAP BcnReqCapFlag; + UINT8 ChRepRegulatoryClass[MAX_NUM_OF_REGULATORY_CLASS]; +} RRM_MLME_BCN_REQ_INFO, *PRRM_MLME_BCN_REQ_INFO; + +typedef struct _RRM_MLME_TRANSMIT_REQ_INFO +{ + UINT16 MeasureDuration; + UINT8 Tid; + UINT8 BinRange; + BOOLEAN bTriggerReport; + BOOLEAN ArvCondition; + BOOLEAN ConsecutiveCondition; + BOOLEAN DelayCondition; + UINT8 AvrErrorThreshold; + UINT8 ConsecutiveErrorThreshold; + UINT8 DelayThreshold; + UINT8 MeasureCnt; + UINT8 TriggerTimeout; + UINT8 bDurationMandatory; +} RRM_MLME_TRANSMIT_REQ_INFO, *PRRM_MLME_TRANSMIT_REQ_INFO; + +#endif /* DOT11K_RRM_SUPPORT */ + +#endif /* __RRM_CMM_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_cal.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_cal.h new file mode 100644 index 000000000..27a08cb4f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_cal.h @@ -0,0 +1,96 @@ +/* + *************************************************************************** + * 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: + cmm_rf_cal.c + + Abstract: + RF calibration and profile related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Arvin Tai 2012/05/02 +*/ + +#define DPD_CAL_PASS_THRES 5 +#define DPD_CAL_MAX_RETRY 5 + +INT32 CalcRCalibrationCode( + IN PRTMP_ADAPTER pAd, + IN INT32 D1, + IN INT32 D2); + +INT Set_TestRxIQCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +VOID R_Calibration( + IN PRTMP_ADAPTER pAd); + +VOID RtmpKickOutHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPrepareContent, + IN BOOLEAN bTransmit); + +VOID DPD_IQ_Swap_AM_PM_Inversion( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx); + +VOID DPD_AM_AM_LUT_Scaling( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx); + +UCHAR DPD_Calibration( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx); + +VOID DoDPDCalibration( + IN PRTMP_ADAPTER pAd); + +INT Set_DPDCalPassThres_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TestDPDCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TestDPDCalibrationTX0_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_TestDPDCalibrationTX1_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +VOID LOFT_IQ_Calibration( + IN RTMP_ADAPTER *pAd); + +BOOLEAN BW_Filter_Calibration( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bTxCal); + +VOID RxDCOC_Calibration( + IN PRTMP_ADAPTER pAd); + +VOID RXIQ_Calibration( + IN PRTMP_ADAPTER pAd); + +VOID RF_SELF_TXDC_CAL( + IN PRTMP_ADAPTER pAd); + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_config.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_config.h new file mode 100644 index 000000000..a898edeb3 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_config.h @@ -0,0 +1,308 @@ +/* + *************************************************************************** + * 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_config.h + + Abstract: + Central header file to maintain all include files for all NDIS + miniport driver routines. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + +*/ +#ifndef __RT_CONFIG_H__ +#define __RT_CONFIG_H__ + +#if (CONFIG_RT_FIRST_CARD == 7602 || CONFIG_RT_FIRST_CARD == 7612 || CONFIG_RT_FIRST_CARD == 7620) && \ + (CONFIG_RT_SECOND_CARD == 7602 || CONFIG_RT_SECOND_CARD == 7612) +#define DRIVER_HAS_MULTI_DEV +#endif + +#include "rtmp_comm.h" + +#include "rtmp_def.h" +#include "rtmp_chip.h" +#include "rtmp_timer.h" + + +#ifdef AGS_SUPPORT +#include "ags.h" +#endif /* AGS_SUPPORT */ +#ifdef BAND_STEERING +#include "band_steering_def.h" +#endif /* BAND_STEERING */ +#ifdef CONFIG_FPGA_MODE +#include "fpga/fpga_ctl.h" +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef SMART_MESH +#include "smart_mesh/smart_mesh_def.h" +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + +#include "mlme.h" +#include "crypt_md5.h" +#include "crypt_sha2.h" +#include "crypt_hmac.h" +#include "crypt_aes.h" +#include "crypt_arc4.h" +/*#include "rtmp_cmd.h" */ +#include "rtmp.h" +#include "wpa.h" +#include "chlist.h" +#include "spectrum.h" +#ifdef CONFIG_AP_SUPPORT +#include "ap.h" +#include "ap_autoChSel.h" +#endif /* CONFIG_AP_SUPPORT */ +#include "rt_os_util.h" + +#include "eeprom.h" +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) +#include "mcu/mcu.h" +#endif + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + +#include "rt_os_net.h" + +#ifdef RT6352 +#include "rt_cal.h" +#endif /* RT6352 */ + +#ifdef UAPSD_SUPPORT +#include "uapsd.h" +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +#include "ap_mbss.h" +#endif /* MBSS_SUPPORT */ + +#ifdef WDS_SUPPORT +#include "ap_wds.h" +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT +#include "ap_apcli.h" +#endif /* APCLI_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +#define AP_WSC_INCLUDED +#endif /* WSC_AP_SUPPORT */ + +#include "ap_ids.h" +#include "ap_cfg.h" + +#ifdef CLIENT_WDS +#include "client_wds.h" +#endif /* CLIENT_WDS */ + +#ifdef SMART_MESH +#include "smart_mesh/smart_mesh_func.h" +#endif /* SMART_MESH */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MAT_SUPPORT +#include "mat.h" +#endif /* MAT_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#include "sta.h" +#ifdef WSC_STA_SUPPORT +#define STA_WSC_INCLUDED +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef BLOCK_NET_IF +#include "netif_block.h" +#endif /* BLOCK_NET_IF */ + +#ifdef IGMP_SNOOP_SUPPORT +#include "igmp_snoop.h" +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef RALINK_ATE +#include "rt_ate.h" +#endif /* RALINK_ATE */ + +#ifdef RALINK_QA +#include "rt_qa.h" +#endif /* RALINK_QA */ + +#ifdef RALINK_QA +#ifndef RALINK_ATE +#error "For supporting QA GUI, please set HAS_ATE=y and HAS_QA_SUPPORT=y." +#endif /* RALINK_ATE */ +#endif /* RALINK_QA */ + + +#ifdef RTMP_RBUS_SUPPORT +#ifdef RT3XXX_ANTENNA_DIVERSITY_SUPPORT +#include "ap_diversity.h" +#endif /* RT3XXX_ANTENNA_DIVERSITY_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef WAPI_SUPPORT +#include "wapi.h" +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "rrm.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +#include "tdls.h" +#include "tdls_uapsd.h" +#endif /* DOT11Z_TDLS_SUPPORT */ + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef WDS_SUPPORT +#define RALINK_PASSPHRASE "Ralink" +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +#ifndef APCLI_SUPPORT +#error "Build Apcli for being controlled by NetworkManager or wext, please set HAS_APCLI_SUPPORT=y and HAS_APCLI_WPA_SUPPLICANT=y" +#endif /* APCLI_SUPPORT */ +#define WPA_SUPPLICANT_SUPPORT +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifndef WPA_SUPPLICANT_SUPPORT +#error "Build for being controlled by NetworkManager or wext, please set HAS_WPA_SUPPLICANT=y and HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y" +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_INCLUDED +#include "crypt_biginteger.h" +#include "crypt_dh.h" +#include "wsc_tlv.h" + +#ifdef WSC_NFC_SUPPORT +#include "nfc.h" +#endif /* WSC_NFC_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#ifdef IKANOS_VX_1X0 +#include "vr_ikans.h" +#endif /* IKANOS_VX_1X0 */ + +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "rrm.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT +#include "pmf.h" +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#include "wnm.h" +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef WAPI_SUPPORT +#include "wapi.h" +#endif /* WAPI_SUPPORT */ + + +#ifdef WFD_SUPPORT +#include "wfd.h" +#endif /* WFD_SUPPORT */ + +#ifdef DOT11_VHT_AC +#include "vht.h" +#endif /* DOT11_VHT_AC */ +#ifdef CONFIG_STA_SUPPORT +#include "sta_cfg.h" +#endif /* CONFIG_STA_SUPPORT */ + + + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT +#include "video.h" +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef WORKQUEUE_BH +#include +#endif /* WORKQUEUE_BH / */ + + +#ifdef BAND_STEERING +#include "band_steering.h" +#endif /* BAND_STEERING */ + +#ifdef TXBF_SUPPORT +#include "rt_txbf.h" +#endif /* TXBF_SUPPORT */ + + +#ifdef RLT_MAC +#include "mac_ral/fce.h" +#endif /* RLT_MAC */ + +#ifdef CONFIG_SNIFFER_SUPPORT +#include "sniffer/sniffer.h" +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT +#include "cfg80211extr.h" +#include "cfg80211_cmm.h" +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + +#ifdef CONFIG_DOT11U_INTERWORKING +#include "dot11u_interworking.h" +#include "gas.h" +#endif + +#ifdef CONFIG_DOT11V_WNM +#include "dot11v_wnm.h" +#include "wnm.h" +#endif + +#ifdef CONFIG_HOTSPOT +#include "hotspot.h" +#endif + +#endif /* __RT_CONFIG_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_led.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_led.h new file mode 100644 index 000000000..93b508171 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_led.h @@ -0,0 +1,516 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002-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. + **************************************************************************** + + Module Name: + rt_led.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT_LED_H__ +#define __RT_LED_H__ + +/* LED MCU command */ +#define MCU_SET_LED_MODE 0x50 +#define MCU_SET_LED_GPIO_SIGNAL_CFG 0x51 +#define MCU_SET_LED_AG_CFG 0x52 +#define MCU_SET_LED_ACT_CFG 0x53 +#define MCU_SET_LED_POLARITY 0x54 +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +#define MCU_SET_WPS_LED_MODE 0x55 /* Set WPS LED mode (based on WPS specification V1.0). */ +#define MCU_SET_ANT_DIVERSITY 0x73 +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* LED Mode */ +#define LED_MODE(pAd) ((pAd)->LedCntl.MCULedCntl.field.LedMode & 0x7F) +#define LED_HW_CONTROL 19 /* set LED to controll by MAC registers instead of by firmware */ +#define LED_MODE_DEFAULT 0 /* value domain of pAd->LedCntl.LedMode and E2PROM */ +#define LED_MODE_TWO_LED 1 +#define LED_MODE_8SEC_SCAN 2 /* Same as LED mode 1; except that fast blink for 8sec when doing scanning. */ +#define LED_MODE_SITE_SURVEY_SLOW_BLINK 3 /* Same as LED mode 1; except that make ACT slow blinking during site survey period and blink once at power-up. */ +#define LED_MODE_WPS_LOW_POLARITY 4 /* Same as LED mode 1; except that make ACT steady on during WPS period */ +#define LED_MODE_WPS_HIGH_POLARITY 5 /* Same as LED mode 1; except that make ACT steady on during WPS period */ +/*#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 */ +#define LED_MODE_SIGNAL_STREGTH 0x40 /* EEPROM define = 64 */ +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +#define LED_WPS_MODE10_TURN_ON 16 /* For Dlink WPS LED, turn the WPS LED on */ +#define LED_WPS_MODE10_FLASH 17 /* For Dlink WPS LED, let the WPS LED flash */ +#define LED_WPS_MODE10_TURN_OFF 18 /* For Dlink WPS LED, turn the WPS LED off */ +#define WPS_LED_MODE_7 0x07 +#define WPS_LED_MODE_8 0x08 +#define WPS_LED_MODE_9 0x09 +#define WPS_LED_MODE_10 0x0a +/* */ +/* Chungwa Telecom (WPS LED and SD/HD LEDs) use WPS LED mode #11 and it is based on mode #7 */ +/* */ +/* GPIO #1: WPS LED */ +/* GPIO #2: SD (Standard Definition) LED */ +/* GPIO #4: HD (High Definition) LED */ +/* */ +#define WPS_LED_MODE_11 0x0b +#define WPS_LED_MODE_12 0x0c +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* Driver LED Status */ +#define LED_LINK_DOWN 0 +#define LED_LINK_UP 1 +#define LED_RADIO_OFF 2 +#define LED_RADIO_ON 3 +#define LED_HALT 4 +#define LED_WPS 5 +#define LED_ON_SITE_SURVEY 6 +#define LED_POWER_UP 7 +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +/* For LED mode = 7 only */ +#define LED_WPS_IN_PROCESS 8 /* The protocol is searching for a partner, connecting, or exchanging network parameters. */ +#define LED_WPS_ERROR 9 /* Some error occurred which was not related to security, such as failed to find any partner or protocol prematurely aborted. */ +#define LED_WPS_SESSION_OVERLAP_DETECTED 10 /* The Protocol detected overlapping operation (more than one Registrar in PBC mode): could be a security risk. */ +#define LED_WPS_SUCCESS 11 /* The protocol is finished: no uncorrectable errors occured. Normally after guard time period. */ +#define LED_WPS_TURN_LED_OFF 12 /* Turn the WPS LEDs off. */ +#define LED_WPS_TURN_ON_BLUE_LED 13 /* Turn on the WPS blue LED. */ +#define LED_NORMAL_CONNECTION_WITHOUT_SECURITY 14 /* Successful connection with an AP using OPEN-NONE. */ +#define LED_NORMAL_CONNECTION_WITH_SECURITY 15 /* Successful connection with an AP using an encryption algorithm. */ +/* For LED Share Mode */ +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* MCU Led Link Status */ +#define LINK_STATUS_LINK_DOWN 0x20 +#define LINK_STATUS_ABAND_LINK_UP 0xa0 +#define LINK_STATUS_GBAND_LINK_UP 0x60 +#define LINK_STATUS_RADIO_ON 0x20 +#define LINK_STATUS_RADIO_OFF 0x00 +#define LINK_STATUS_WPS 0x10 +#define LINK_STATUS_ON_SITE_SURVEY 0x08 +#define LINK_STATUS_POWER_UP 0x04 +#define LINK_STATUS_HW_CONTROL 0x00 +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +/* LED mode = 7 and 8 only */ +#define LINK_STATUS_WPS_IN_PROCESS 0x00 /* The protocol is searching for a partner, connecting, or exchanging network parameters. */ +#define LINK_STATUS_WPS_SUCCESS_WITH_SECURITY 0x01 /* The protocol is finished (with security): no uncorrectable errors occured. Normally after guard time period. */ +#define LINK_STATUS_WPS_ERROR 0x02 /* Some error occurred which was not related to security, such as failed to find any partner or protocol prematurely aborted. */ +#define LINK_STATUS_WPS_SESSION_OVERLAP_DETECTED 0x03 /* The Protocol detected overlapping operation (more than one Registrar in PBC mode): could be a security risk. */ +#define LINK_STATUS_WPS_TURN_LED_OFF 0x04 /* Turn the WPS LEDs off. */ +#define LINK_STATUS_WPS_SUCCESS_WITHOUT_SECURITY 0X05 /* The protocol is finished (without security): no uncorrectable errors occured. Normally after guard time period. */ +#define LINK_STATUS_NORMAL_CONNECTION_WITHOUT_SECURITY 0x06 /* Successful connection with an AP using OPEN-NONE. */ +#define LINK_STATUS_NORMAL_CONNECTION_WITH_SECURITY 0x0E /* Successful connection with an AP using an encryption algorithm. */ +#define LINK_STATUS_WPS_BLUE_LED 0x01 /* WPS blue LED. */ +/* LED moe = 10 */ +#define LINK_STATUS_WPS_MODE10_TURN_ON 0x00 /*Use only on Dlink WPS LED (mode 10), turn the WPS LED on. */ +#define LINK_STATUS_WPS_MODE10_FLASH 0x01 /*Use only on Dlink WPS LED (mode 10), let the WPS LED flash, three times persecond. */ +#define LINK_STATUS_WPS_MODE10_TURN_OFF 0x02 /*Use only on Dlink WPS LED (mode 10), turn the WPS LED off. */ +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_SWMCU_SUPPORT +/* SWMCU Led Status */ +/* LED G*/ +#define MCU_LED_G_OFF 0 +#define MCU_LED_G_SOLID_ON 1 +#define MCU_LED_G_SLOW_BLINK 2 +#define MCU_LED_G_FAST_BLINK 3 +/* LED A */ +#define MCU_LED_A_OFF 0 +#define MCU_LED_A_SOLID_ON 1 +#define MCU_LED_A_SLOW_BLINK 2 +#define MCU_LED_A_FAST_BLINK 3 +/* LED ACT */ +#define MCU_LED_ACT_OFF 0 +#define MCU_LED_ACT_SOLID_ON 1 +#define MCU_LED_ACT_BLINK_UPON_TX_DATA_MNG 2 +#define MCU_LED_ACT_BLINK_UPON_TX_DATA_MNG_BEN 3 +#define MCU_LED_ACT_WPS_IN_PROCESS 6 +#define MCU_LED_ACT_WPS_ERROR 7 +#define MCU_LED_ACT_WPS_SESSION_OVERLAP_DETECTED 8 +#define MCU_LED_ACT_WPS_SUCCESS_WITH_SECURITY 9 +#define MCU_LED_ACT_WPS_SUCCESS_WITHOUT_SECURITY 10 +#define MCU_LED_ACT_WPS_TURN_LED_OFF 11 +#define MCU_LED_ACT_WPS_NORMAL_CONNECTION_WITHOUT_SECURITY 12 +#define MCU_LED_ACT_WPS_NORMAL_CONNECTION_WITH_SECURITY 13 +#endif /* CONFIG_SWMCU_SUPPORT */ + +#define ACTIVE_LOW 0 +#define ACTIVE_HIGH 1 + +/* */ +/* MCU_LEDCS: MCU LED Control Setting. */ +/* */ +typedef union _MCU_LEDCS_STRUC { + struct { +#ifdef RT_BIG_ENDIAN + UCHAR Polarity:1; + UCHAR LedMode:7; +#else + UCHAR LedMode:7; + UCHAR Polarity:1; +#endif /* RT_BIG_ENDIAN */ + } field; + UCHAR word; +} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; + +void RTMPGetLEDSetting(IN RTMP_ADAPTER *pAd); +void RTMPInitLEDMode(IN RTMP_ADAPTER *pAd); +void RTMPExitLEDMode(IN RTMP_ADAPTER *pAd); + +VOID RTMPSetLEDStatus( + IN PRTMP_ADAPTER pAd, + IN UCHAR Status); + + +#ifdef RTMP_MAC_PCI +#ifdef LED_CONTROL_SUPPORT +#define RTMPSetLED(pAd, Status) RTMPSetLEDStatus(pAd, Status) +#else +#define RTMPSetLED(pAd, Status) +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +VOID RTMPSetSignalLED( + IN PRTMP_ADAPTER pAd, + IN NDIS_802_11_RSSI Dbm); + +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT +VOID LEDConnectionStart( + IN PRTMP_ADAPTER pAd); + +VOID LEDConnectionCompletion( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bSuccess); +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + +#ifdef CONFIG_SWMCU_SUPPORT +/************************************************************************* + * + * LED related data type and MARCO definitions. + * + ************************************************************************/ +#define GetBitX(x, y) ( ((x) & (1 << (y)))>>y ) +#define GetBit(x, y) ( ((x) & (1 << (y))) ) +#define GetBitX(x, y) ( ((x) & (1 << (y)))>>y ) +#define SetBit(x, y) ( (x) = (x) | (1 << (y)) ) +#define ClearBit(x, y) { (x) &= (~(1 << (y))); } +#define DSetBit(x, y) ( (x) = (1 << (y)) ) +#define MakeWord(HI, LO) ( ((WORD)(LO)) | (((WORD)(HI))<<8) ) /* Note! LO must be read first */ +#define HiByte(W) ( (BYTE)(((WORD)W) >> 8) ) +#define LoByte(W) ( (BYTE)(W) ) +#define FireInterruptToHost() { IntToHost = 0xff; } + +#define LED_CHECK_INTERVAL 50 /* 50ms */ + +#define LED_G 0 +#define LED_A 1 +#define LED_ACT 2 + +#define MCU_INT_STATUS 0x0414 +#define GPIO_DAT 0x0228 +#define GPIO_DIR 0x0229 +#define MAC_LED_CFG 0x102c + +typedef unsigned char BYTE; + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* SWMCU LED Current Operation Mode */ +typedef union _LED_OPERATION_MODE +{ + struct { + UINT32 :20; + UINT32 LedGMode:2; /* + * 0: MCU_LED_G_OFF + * 1: MCU_LED_G_SOLID_ON, + * 2: MCU_LED_G_SLOW_BLINK + * 3: MCU_LED_G_FAST_BLINK + */ + + UINT32 LedAMode:2; /* + * 0: MCU_LED_A_OFF + * 1: MCU_LED_A_SOLID_ON, + * 2: MCU_LED_A_SLOW_BLINK + * 3: MCU_LED_A_FAST_BLINK. + */ + + UINT32 LedActMode:4; /* + * 0: MCU_LED_ACT_OFF + * 1: MCU_LED_ACT_SOLID_ON + * 2: MCU_LED_ACT_BLINK_UPON_TX_DATA_MNG + * 3: MCU_LED_ACT_BLINK_UPON_TX_DATA_MNG_BEN + * 6: MCU_LED_ACT_WPS_IN_PROCESS, + * 7: MCU_LED_ACT_WPS_ERROR + * 8: MCU_LED_ACT_WPS_SESSION_OVERLAP_DETECTED + * 9: MCU_LED_ACT_WPS_SUCCESS_WITH_SECURITY + * 10:MCU_LED_ACT_WPS_SUCCESS_WITHOUT_SECURITY + * 11:MCU_LED_ACT_WPS_TURN_LED_OFF + * 12:MCU_LED_ACT_NORMAL_CONNECTION_WITHOUT_SECURITY + * 13:MCU_LED_ACT_NORMAL_CONNECTION_WITH_SECURITY + * 14:MCU_LED_ACT_WPS_PRE_STAGE + * 15:MCU_LED_ACT_WPS_POST_STAGE + */ + UINT32 LedActModeNoTx:1; + UINT32 LedGPolarity:1; + UINT32 LedAPolarity:1; + UINT32 LedActPolarity:1; + } field; + UINT word; +} LED_OPERATION_MODE, *PLED_OPERATION_MODE; + +/* MCU_LEDCS: MCU LED A/G Configure Setting */ +typedef union _LED_AG_CFG +{ + struct { +#ifdef RT_BIG_ENDIAN + UINT16 LedAMode_RadioOnLinkA:2; + UINT16 LedGMode_RadioOnLinkA:2; + UINT16 LedAMode_RadioOnLinkG:2; + UINT16 LedGMode_RadioOnLinkG:2; + UINT16 LedAMode_RadioOnLinkDown:2; + UINT16 LedGMode_RadioOnLinkDown:2; + UINT16 LedAMode_RadioOff:2; + UINT16 LedGMode_RadioOff:2; +#else + UINT16 LedGMode_RadioOff:2; + UINT16 LedAMode_RadioOff:2; + UINT16 LedGMode_RadioOnLinkDown:2; + UINT16 LedAMode_RadioOnLinkDown:2; + UINT16 LedGMode_RadioOnLinkG:2; + UINT16 LedAMode_RadioOnLinkG:2; + UINT16 LedGMode_RadioOnLinkA:2; + UINT16 LedAMode_RadioOnLinkA:2; +#endif + } field; + UINT16 word; +} LED_AG_CFG, *PLED_AG_CFG; + +/* MCU_LEDCS: MCU LED ACT Configure Setting */ +typedef union _LED_ACT_CFG +{ + struct { +#ifdef RT_BIG_ENDIAN + UINT16 :1; + UINT16 LedActModeNoTx_RadioOnLinkA:1; + UINT16 LedActMode_RadioOnLinkA:2; + UINT16 :1; + UINT16 LedActModeNoTx_RadioOnLinkG:1; + UINT16 LedActMode_RadioOnLinkG:2; + UINT16 :1; + UINT16 LedActModeNoTx_RadioOnLinkDown:1; + UINT16 LedActMode_RadioOnLinkDown:2; + UINT16 :1; + UINT16 LedActModeNoTx_RadioOff:1; + UINT16 LedActMode_RadioOff:2; +#else + UINT16 LedActMode_RadioOff:2; + UINT16 LedActModeNoTx_RadioOff:1; + UINT16 :1; + UINT16 LedActMode_RadioOnLinkDown:2; + UINT16 LedActModeNoTx_RadioOnLinkDown:1; + UINT16 :1; + UINT16 LedActMode_RadioOnLinkG:2; + UINT16 LedActModeNoTx_RadioOnLinkG:1; + UINT16 :1; + UINT16 LedActMode_RadioOnLinkA:2; + UINT16 LedActModeNoTx_RadioOnLinkA:1; + UINT16 :1; +#endif + } field; + UINT16 word; +} LED_ACT_CFG, *PLED_ACT_CFG; + +/* MCU_LEDCS: MCU LED POLARITY Configure Setting. */ +typedef union _LED_POLARITY +{ + struct { +#ifdef RT_BIG_ENDIAN + UINT16 :1; + UINT16 LedActPolarity_RadioOnLinkA:1; + UINT16 LedAPolarity_RadioOnLinkA:1; + UINT16 LedGPolarity_RadioOnLinkA:1; + UINT16 :1; + UINT16 LedActPolarity_RadioOnLinkG:1; + UINT16 LedAPolarity_RadioOnLinkG:1; + UINT16 LedGPolarity_RadioOnLinkG:1; + UINT16 :1; + UINT16 LedActPolarity_RadioOnLinkDown:1; + UINT16 LedAPolarity_RadioOnLinkDown:1; + UINT16 LedGPolarity_RadioOnLinkDown:1; + UINT16 :1; + UINT16 LedActPolarity_RadioOff:1; + UINT16 LedAPolarity_RadioOff:1; + UINT16 LedGPolarity_RadioOff:1; +#else + UINT16 LedGPolarity_RadioOff:1; + UINT16 LedAPolarity_RadioOff:1; + UINT16 LedActPolarity_RadioOff:1; + UINT16 :1; + UINT16 LedGPolarity_RadioOnLinkDown:1; + UINT16 LedAPolarity_RadioOnLinkDown:1; + UINT16 LedActPolarity_RadioOnLinkDown:1; + UINT16 :1; + UINT16 LedGPolarity_RadioOnLinkG:1; + UINT16 LedAPolarity_RadioOnLinkG:1; + UINT16 LedActPolarity_RadioOnLinkG:1; + UINT16 :1; + UINT16 LedGPolarity_RadioOnLinkA:1; + UINT16 LedAPolarity_RadioOnLinkA:1; + UINT16 LedActPolarity_RadioOnLinkA:1; + UINT16 :1; +#endif + } field; + UINT16 word; +} LED_POLARITY, *PLED_POLARITY; + +/* SWMCU LED Current Parameters */ +typedef struct _ULED_PARAMETER +{ + LED_AG_CFG LedAgCfg; + LED_ACT_CFG LedActCfg; + LED_POLARITY LedPolarityCfg; + UINT8 LedMode; +}ULED_PARAMETER, *PULED_PARAMETER; + +/* Mac LED_CFG macro and definition */ +#define MAC_LED_OFF 0 +#define MAC_LED_BLINK_UPON_TX 1 +#define MAC_LED_SLOW_BLINK 2 +#define MAC_LED_ON 3 + +typedef union _LED_CFG_T +{ + struct{ +#ifdef RT_BIG_ENDIAN + UINT32 :1; + UINT32 LED_POL:1; /* 0: active low, 1:active high. */ + UINT32 Y_LED_MODE:2; /* 0: off, 1: blinking upon Tx, + 2:Periodic slow blinking, 3:sloid on. */ + UINT32 G_LED_MODE:2; /* same as Y_LED_MODE. */ + UINT32 R_LED_MODE:2; /* same as Y_LED_MODE. */ + UINT32 :2; + UINT32 SLOW_BLK_TIME:6; /* slow blinking period (uint: 1sec). */ + UINT32 LED_OFF_TIIME:8; /* Tx blinking off period (unit: 1ms). */ + UINT32 LED_ON_TIME:8; /* Tx blinking on period (uint: 1ms). */ +#else + UINT32 LED_ON_TIME:8; /* Tx blinking on period (uint: 1ms). */ + UINT32 LED_OFF_TIME:8; /* Tx blinking off period (unit: 1ms). */ + UINT32 SLOW_BLK_TIME:6; /* slow blinking period (uint: 1sec). */ + UINT32 :2; + UINT32 R_LED_MODE:2; /* same as Y_LED_MODE. */ + UINT32 G_LED_MODE:2; /* same as Y_LED_MODE. */ + UINT32 Y_LED_MODE:2; /* 0: off, 1: blinking upon Tx, + 2:Periodic slow blinking, 3:sloid on. */ + UINT32 LED_POL:1; /* 0: active low, 1:active high. */ + UINT32 :1; +#endif + } field; + UINT32 word; +} LED_CFG_T, *PLED_CFG_T; + +#define INFINITE_PERIOD (-1) +/* + * WPS User Feedback Time Unit + * Time unit is LED_CHECK_INTERVAL + */ +typedef struct _WPS_LED_TIME_UNIT { + INT32 OnPeriod, LeftOnPeriod; + INT32 OffPeriod, LeftOffPeriod; + INT32 BlinkPeriod, LeftBlinkPeriod; + INT32 RestPeriod, LeftRestPeriod; +}WPS_LED_TIME_UNIT, *PWPS_LED_TIME_UNIT; + +typedef struct _SWMCU_LED_CONTROL { + RALINK_TIMER_STRUCT LedCheckTimer; + ULED_PARAMETER LedParameter; + LED_OPERATION_MODE CurrentLedCfg; + unsigned char LinkStatus; + unsigned char GPIOPolarity; + unsigned char SignalStrength; + unsigned char LedBlinkTimer; + unsigned long BlinkFor8sTimer; + BOOLEAN bWlanLed; + WPS_LED_TIME_UNIT WPSLedTimeUnit; +}SWMCU_LED_CONTROL, *PSWMCU_LED_CONTROL; + +INT Show_LedCfg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_LedCfg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_LedCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID SetLedCfg( + IN PRTMP_ADAPTER pAd, + IN INT ledPolarity, + IN INT ledOnTime, + IN INT ledOffTime, + IN INT slowBlkTime); + +VOID SetLedMode( + IN PRTMP_ADAPTER pAd, + IN INT LedSel, + IN INT LedMode); + +void SWMCULedCtrlMain( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +DECLARE_TIMER_FUNCTION(SWMCULedCtrlMain); + +void SetLedLinkStatus( + IN PRTMP_ADAPTER pAd); + + +#endif /* CONFIG_SWMCU_SUPPORT */ + +typedef struct _LED_CONTROL +{ + MCU_LEDCS_STRUC MCULedCntl; /* LED Mode EEPROM 0x3b */ + USHORT LedAGCfg; /* LED A/G Configuration EEPROM 0x3c */ + USHORT LedACTCfg; /* LED ACT Configuration EEPROM 0x3e */ + USHORT LedPolarity;/* LED A/G/ACT polarity EEPROM 0x40 */ + UCHAR LedIndicatorStrength; + UCHAR RssiSingalstrengthOffet; + BOOLEAN bLedOnScanning; + UCHAR LedStatus; +#ifdef CONFIG_SWMCU_SUPPORT + SWMCU_LED_CONTROL SWMCULedCntl; +#endif /* CONFIG_SWMCU_SUPPORT */ +}LED_CONTROL, *PLED_CONTROL; + +void RTMPStartLEDMode(IN RTMP_ADAPTER *pAd); + +#endif /* __RT_LED_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_os_net.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_os_net.h new file mode 100644 index 000000000..9f9191f09 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_os_net.h @@ -0,0 +1,693 @@ +/**************************************************************************** + + Module Name: + rt_os_net.h + + Abstract: + All function prototypes are defined in NETIF modules. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RT_OS_NET_H__ +#define __RT_OS_NET_H__ + +#include "chip/chip_id.h" + +typedef VOID *(*RTMP_NET_ETH_CONVERT_DEV_SEARCH)(VOID *net_dev, UCHAR *pData); +typedef int (*RTMP_NET_PACKET_TRANSMIT)(VOID *pPacket); + +#ifdef LINUX +#ifdef OS_ABL_FUNC_SUPPORT + +/* ========================================================================== */ +/* operators used in NETIF module */ +/* Note: No need to put any compile option here */ +typedef struct _RTMP_DRV_ABL_OPS { + +NDIS_STATUS (*RTMPAllocAdapterBlock)(PVOID handle, VOID **ppAdapter); +VOID (*RTMPFreeAdapter)(VOID *pAd); +BOOLEAN (*RtmpRaDevCtrlExit)(VOID *pAd); +INT (*RtmpRaDevCtrlInit)(VOID *pAd, RTMP_INF_TYPE infType); +VOID (*RTMPHandleInterrupt)(VOID *pAd); +INT (*RTMP_COM_IoctlHandle)( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +int (*RTMPSendPackets)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets, + IN UINT32 PktTotalLen, + IN RTMP_NET_ETH_CONVERT_DEV_SEARCH Func); + +int (*P2P_PacketSend)( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +INT (*RTMP_AP_IoctlHandle)( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +INT (*RTMP_STA_IoctlHandle)( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data, + IN USHORT priv_flags); + +VOID (*RTMPDrvOpen)(VOID *pAd); +VOID (*RTMPDrvClose)(VOID *pAd, VOID *net_dev); +VOID (*RTMPInfClose)(VOID *pAd); +int (*rt28xx_init)(VOID *pAd, PSTRING pDefaultMac, PSTRING pHostName); +} RTMP_DRV_ABL_OPS; + +extern RTMP_DRV_ABL_OPS *pRtmpDrvOps; + +VOID RtmpDrvOpsInit( + OUT VOID *pDrvOpsOrg, + INOUT VOID *pDrvNetOpsOrg, + IN RTMP_PCI_CONFIG *pPciConfig, + IN RTMP_USB_CONFIG *pUsbConfig); +#endif /* OS_ABL_FUNC_SUPPORT */ +#endif /* LINUX */ + + + + +/* ========================================================================== */ +/* operators used in DRIVER module */ +typedef void (*RTMP_DRV_USB_COMPLETE_HANDLER)(VOID *pURB); + +typedef struct _RTMP_NET_ABL_OPS { + + +} RTMP_NET_ABL_OPS; + +extern RTMP_NET_ABL_OPS *pRtmpDrvNetOps; + +VOID RtmpNetOpsInit(VOID *pNetOpsOrg); +VOID RtmpNetOpsSet(VOID *pNetOpsOrg); + + +/* ========================================================================== */ +#if defined(RTMP_MODULE_OS) && defined(OS_ABL_FUNC_SUPPORT) +/* for UTIL/NETIF module in OS ABL mode */ + +#define RTMPAllocAdapterBlock (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPAllocAdapterBlock) +#define RTMPFreeAdapter (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPFreeAdapter) +#define RtmpRaDevCtrlExit (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RtmpRaDevCtrlExit) +#define RtmpRaDevCtrlInit (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RtmpRaDevCtrlInit) +#define RTMPHandleInterrupt (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPHandleInterrupt) +#define RTMP_COM_IoctlHandle (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMP_COM_IoctlHandle) +#define RTMPSendPackets (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPSendPackets) +#define P2P_PacketSend (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->P2P_PacketSend) +#define RTMP_AP_IoctlHandle (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMP_AP_IoctlHandle) +#define RTMP_STA_IoctlHandle (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMP_STA_IoctlHandle) +#define RTMPDrvOpen (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPDrvOpen) +#define RTMPDrvClose (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPDrvClose) +#define RTMPInfClose (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPInfClose) +#define rt28xx_init (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->rt28xx_init) + +#else /* RTMP_MODULE_OS && OS_ABL_FUNC_SUPPORT */ + +NDIS_STATUS RTMPAllocAdapterBlock(PVOID handle, VOID **ppAdapter); +VOID RTMPFreeAdapter(VOID *pAd); +BOOLEAN RtmpRaDevCtrlExit(VOID *pAd); +INT RtmpRaDevCtrlInit(VOID *pAd, RTMP_INF_TYPE infType); +VOID RTMPHandleInterrupt(VOID *pAd); + +INT RTMP_COM_IoctlHandle( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +int RTMPSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets, + IN UINT32 PktTotalLen, + IN RTMP_NET_ETH_CONVERT_DEV_SEARCH Func); + +int P2P_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +#ifdef CONFIG_AP_SUPPORT +INT RTMP_AP_IoctlHandle( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +INT RTMP_STA_IoctlHandle( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data, + IN USHORT priv_flags ); +#endif /* CONFIG_STA_SUPPORT */ + +VOID RTMPDrvOpen(VOID *pAd); +VOID RTMPDrvClose(VOID *pAd, VOID *net_dev); +VOID RTMPInfClose(VOID *pAd); + +int rt28xx_init( + IN VOID *pAd, + IN PSTRING pDefaultMac, + IN PSTRING pHostName); + +PNET_DEV RtmpPhyNetDevMainCreate(VOID *pAd); +#endif /* RTMP_MODULE_OS */ + +/* ========================================================================== */ +int rt28xx_close(VOID *dev); +int rt28xx_open(VOID *dev); + +__inline INT VIRTUAL_IF_UP(VOID *pAd) +{ + RT_CMD_INF_UP_DOWN InfConf = { rt28xx_open, rt28xx_close }; + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP, + 0, &InfConf, 0) != NDIS_STATUS_SUCCESS) + return -1; + return 0; +} + +__inline VOID VIRTUAL_IF_DOWN(VOID *pAd) +{ + RT_CMD_INF_UP_DOWN InfConf = { rt28xx_open, rt28xx_close }; + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_DOWN, + 0, &InfConf, 0); + return; +} + +#ifdef RTMP_MODULE_OS + +#ifdef CONFIG_AP_SUPPORT +INT rt28xx_ap_ioctl( + IN PNET_DEV net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +INT rt28xx_sta_ioctl( + IN PNET_DEV net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); +#endif /* CONFIG_STA_SUPPORT */ + +PNET_DEV RtmpPhyNetDevInit( + IN VOID *pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetHook); + +BOOLEAN RtmpPhyNetDevExit( + IN VOID *pAd, + IN PNET_DEV net_dev); + +#endif /* RTMP_MODULE_OS && OS_ABL_FUNC_SUPPORT */ + + +VOID RT28xx_MBSS_Init(VOID *pAd, PNET_DEV main_dev_p); +INT MBSS_VirtualIF_Open(PNET_DEV dev_p); +INT MBSS_VirtualIF_Close(PNET_DEV dev_p); +VOID RT28xx_MBSS_Remove(VOID *pAd); + + +VOID RT28xx_WDS_Init(VOID *pAd, PNET_DEV net_dev); +INT WdsVirtualIF_open(PNET_DEV dev); +INT WdsVirtualIF_close(PNET_DEV dev); +VOID RT28xx_WDS_Remove(VOID *pAd); + +VOID RT28xx_Monitor_Init(VOID *pAd, PNET_DEV main_dev_p); +VOID RT28xx_Monitor_Remove(VOID *pAd); + + +VOID RT28xx_ApCli_Init(VOID *pAd, PNET_DEV main_dev_p); +INT ApCli_VirtualIF_Open(PNET_DEV dev_p); +INT ApCli_VirtualIF_Close(PNET_DEV dev_p); +VOID RT28xx_ApCli_Remove(VOID *pAd); + + +VOID RTMP_Mesh_Init(VOID *pAd, PNET_DEV main_dev_p, PSTRING pHostName); +INT Mesh_VirtualIF_Open(PNET_DEV pDev); +INT Mesh_VirtualIF_Close(PNET_DEV pDev); +VOID RTMP_Mesh_Remove(VOID *pAd); + +VOID RTMP_P2P_Init(VOID *pAd, PNET_DEV main_dev_p); + INT P2P_VirtualIF_Open(PNET_DEV dev_p); + INT P2P_VirtualIF_Close(PNET_DEV dev_p); + INT P2P_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p); + VOID RTMP_P2P_Remove(VOID *pAd); + + +#ifdef RT_CFG80211_P2P_SUPPORT +#define CFG_P2PGO_ON(__pAd) RTMP_CFG80211_VIF_P2P_GO_ON(__pAd) +#define CFG_P2PCLI_ON(__pAd) RTMP_CFG80211_VIF_P2P_CLI_ON(__pAd) + +BOOLEAN RTMP_CFG80211_VIF_P2P_GO_ON( + IN VOID *pAdSrc); + +BOOLEAN RTMP_CFG80211_VIF_P2P_CLI_ON( + IN VOID *pAdSrc); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +VOID RTMP_CFG80211_DummyP2pIf_Init(VOID *pAdSrc); +VOID RTMP_CFG80211_DummyP2pIf_Remove(VOID *pAdSrc); + +BOOLEAN RTMP_CFG80211_VIF_P2P_CLI_ON(VOID *pAdSrc); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + +PNET_DEV RTMP_CFG80211_FindVifEntry_ByType(VOID *pAdSrc, UINT32 devType); +PWIRELESS_DEV RTMP_CFG80211_FindVifEntryWdev_ByType(VOID *pAdSrc, UINT32 devType); +VOID RTMP_CFG80211_AddVifEntry(VOID *pAdSrc, PNET_DEV pNewNetDev, UINT32 DevType); +VOID RTMP_CFG80211_RemoveVifEntry(VOID *pAdSrc, PNET_DEV pNewNetDev); + +PNET_DEV RTMP_CFG80211_VirtualIF_Get(VOID *pAdSrc); +VOID RTMP_CFG80211_VirtualIF_CancelP2pClient(VOID *pAdSrc); +VOID RTMP_CFG80211_VirtualIF_Init(VOID *pAd, CHAR *pIfName, UINT32 DevType); +VOID RTMP_CFG80211_VirtualIF_Remove(VOID *pAd,PNET_DEV dev_p, UINT32 DevType); +VOID RTMP_CFG80211_AllVirtualIF_Remove(VOID *pAdSrc); + + +#ifdef RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT +INT rt_android_private_command_entry( + VOID *pAdSrc, struct net_device *net_dev, struct ifreq *ifr, int cmd); +#endif /* RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT */ + + +/* FOR communication with RALINK DRIVER module in NET module */ +/* general */ +#define RTMP_DRIVER_NET_DEV_GET(__pAd, __pNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_NETDEV_GET, 0, __pNetDev, 0) + +#define RTMP_DRIVER_NET_DEV_SET(__pAd, __pNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_NETDEV_SET, 0, __pNetDev, 0) + +#define RTMP_DRIVER_OP_MODE_GET(__pAd, __pOpMode) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_OPMODE_GET, 0, __pOpMode, 0) + +#define RTMP_DRIVER_IW_STATS_GET(__pAd, __pIwStats) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_IW_STATUS_GET, 0, __pIwStats, 0) + +#define RTMP_DRIVER_INF_STATS_GET(__pAd, __pInfStats) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_STATS_GET, 0, __pInfStats, 0) + +#define RTMP_DRIVER_INF_TYPE_GET(__pAd, __pInfType) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_TYPE_GET, 0, __pInfType, 0) + +#define RTMP_DRIVER_TASK_LIST_GET(__pAd, __pList) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_TASK_LIST_GET, 0, __pList, 0) + +#define RTMP_DRIVER_NIC_NOT_EXIST_SET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_NIC_NOT_EXIST, 0, NULL, 0) + +#define RTMP_DRIVER_MCU_SLEEP_CLEAR(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR, 0, NULL, 0) + +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + +#define RTMP_DRIVER_USB_DEV_GET(__pAd, __pUsbDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_DEV_GET, 0, __pUsbDev, 0) + +#define RTMP_DRIVER_USB_INTF_GET(__pAd, __pUsbIntf) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_INTF_GET, 0, __pUsbIntf, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_SET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_CLEAR(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_END_DISSASSOCIATE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SEND_DISSASSOCIATE, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_TEST, 0, __flag, 0) + +#define RTMP_DRIVER_ADAPTER_IDLE_RADIO_OFF_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_IDLE_RADIO_OFF_TEST, 0, __flag, 0) +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +#define RTMP_DRIVER_ADAPTER_RT28XX_WOW_STATUS(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_STATUS, 0, __flag, 0) + +#define RTMP_DRIVER_ADAPTER_RT28XX_WOW_ENABLE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_ENABLE, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_RT28XX_WOW_DISABLE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_DISABLE, 0, NULL, 0) +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +#endif /* CONFIG_PM */ + +#define RTMP_DRIVER_AP_SSID_GET(__pAd, pData) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_AP_BSSID_GET, 0, pData, 0) +#endif /* CONFIG_STA_SUPPORT */ + +#define RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_OFF(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_OFF, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_ON(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_SET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_CLEAR(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR, 0, NULL, 0) + +#define RTMP_DRIVER_VIRTUAL_INF_NUM_GET(__pAd, __pIfNum) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_GET, 0, __pIfNum, 0) + +#define RTMP_DRIVER_CHANNEL_GET(__pAd, __Channel) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SIOCGIWFREQ, 0, __Channel, 0) + +#define RTMP_DRIVER_IOCTL_SANITY_CHECK(__pAd, __SetCmd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SANITY_CHECK, 0, __SetCmd, 0) + +#define RTMP_DRIVER_BITRATE_GET(__pAd, __pBitRate) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ, 0, __pBitRate, 0) + +#define RTMP_DRIVER_MAIN_INF_CREATE(__pAd, __ppNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_MAIN_CREATE, 0, __ppNetDev, 0) + +#define RTMP_DRIVER_MAIN_INF_GET(__pAd, __pInfId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_MAIN_ID_GET, 0, __pInfId, 0) + +#define RTMP_DRIVER_MAIN_INF_CHECK(__pAd, __InfId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_MAIN_CHECK, 0, NULL, __InfId) + +#define RTMP_DRIVER_P2P_INF_CHECK(__pAd, __InfId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_P2P_CHECK, 0, NULL, __InfId) + +#ifdef EXT_BUILD_CHANNEL_LIST +#define RTMP_DRIVER_SET_PRECONFIG_VALUE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_SET_PRECONFIG_VALUE, 0, NULL, 0) +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +#ifdef RT_CFG80211_SUPPORT +/* General Part */ +#define RTMP_DRIVER_CFG80211_START(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_CFG80211_CFG_START, 0, NULL, 0) + +#define RTMP_DRIVER_80211_UNREGISTER(__pAd, __pNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_UNREGISTER, 0, __pNetDev, 0) + +#define RTMP_DRIVER_80211_CB_GET(__pAd, __ppCB) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CB_GET, 0, __ppCB, 0) + +#define RTMP_DRIVER_80211_CB_SET(__pAd, __pCB) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CB_SET, 0, __pCB, 0) + +#define RTMP_DRIVER_80211_RESET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_RESET, 0, NULL, 0) + +/* STA Part */ +#define RTMP_DRIVER_80211_SCAN_CHANNEL_LIST_SET(__pAd, __pData, __Len ) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CHANNEL_LIST_SET, 0, __pData, __Len) + +#define RTMP_DRIVER_80211_SCAN(__pAd, __IfType) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_SCAN, 0, NULL, __IfType) + +#define RTMP_DRIVER_80211_SCAN_STATUS_LOCK_INIT(__pAd, __isInit) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_SCAN_STATUS_LOCK_INIT, 0, NULL, __isInit) + +#define RTMP_DRIVER_80211_SCAN_EXTRA_IE_SET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_EXTRA_IES_SET, 0, NULL, 0) + +#define RTMP_DRIVER_80211_GEN_IE_SET(__pAd, __pData, __Len) \ + RTMP_STA_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWGENIE, 0, __pData, __Len, 0) + +#define RTMP_DRIVER_80211_STA_KEY_ADD(__pAd, __pKeyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_STA_KEY_ADD, 0, __pKeyInfo, 0) + +#define RTMP_DRIVER_80211_STA_KEY_DEFAULT_SET(__pAd, __KeyId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_STA_KEY_DEFAULT_SET, 0, NULL, __KeyId) + +#ifdef DOT11W_PMF_SUPPORT +#define RTMP_DRIVER_80211_STA_MGMT_KEY_DEFAULT_SET(__pAd, __KeyId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_STA_MGMT_KEY_DEFAULT_SET, 0, NULL, __KeyId) +#endif /* DOT11W_PMF_SUPPORT */ + +#define RTMP_DRIVER_80211_POWER_MGMT_SET(__pAd, __enable) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_POWER_MGMT_SET, 0, NULL, __enable) + +#define RTMP_DRIVER_80211_STA_LEAVE(__pAd, __ifType) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_STA_LEAVE, 0, NULL, __ifType) + +#define RTMP_DRIVER_80211_STA_GET(__pAd, __pStaInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_STA_GET, 0, __pStaInfo, 0) + +#define RTMP_DRIVER_80211_CONNECT(__pAd, __pConnInfo, __devType) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CONNECT_TO, 0, __pConnInfo, __devType) + +#define RTMP_DRIVER_80211_IBSS_JOIN(__pAd, __pInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_IBSS_JOIN, 0, __pInfo, 0) + +#define RTMP_DRIVER_80211_PMKID_CTRL(__pAd, __pPmkidInfo) \ + RTMP_STA_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWPMKSA, 0, __pPmkidInfo, 0, 0) + + +/* Information Part */ +#define RTMP_DRIVER_80211_BANDINFO_GET(__pAd, __pBandInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_BANDINFO_GET, 0, __pBandInfo, 0) + +#define RTMP_DRIVER_80211_CHANGE_BSS_PARM(__pAd, __pBssInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CHANGE_BSS_PARM, 0, __pBssInfo, 0) + +#define RTMP_DRIVER_80211_CHAN_SET(__pAd, __pChan) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CHAN_SET, 0, __pChan, 0) + +#define RTMP_DRIVER_80211_RFKILL(__pAd, __pActive) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_RFKILL, 0, __pActive, 0) + +#define RTMP_DRIVER_80211_REG_NOTIFY(__pAd, __pNotify) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_REG_NOTIFY_TO, 0, __pNotify, 0) + +#define RTMP_DRIVER_80211_SURVEY_GET(__pAd, __pSurveyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_SURVEY_GET, 0, __pSurveyInfo, 0) + +#define RTMP_DRIVER_80211_NETDEV_EVENT(__pAd, __pDev, __state) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_NETDEV_EVENT, 0, __pDev, __state) + +/* AP Part */ +#define RTMP_DRIVER_80211_BEACON_DEL(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_BEACON_DEL, 0, NULL, 0) + +#define RTMP_DRIVER_80211_BEACON_ADD(__pAd, __pBeacon) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_BEACON_ADD, 0, __pBeacon, 0) + +#define RTMP_DRIVER_80211_BEACON_SET(__pAd, __pBeacon) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_BEACON_SET, 0, __pBeacon, 0) + +#define RTMP_DRIVER_80211_BITRATE_SET(__pAd, __pMask) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_BITRATE_SET, 0, __pMask, 0) + +#define RTMP_DRIVER_80211_AP_KEY_DEL(__pAd, __pKeyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_AP_KEY_DEL, 0, __pKeyInfo, 0) + +#define RTMP_DRIVER_80211_AP_KEY_ADD(__pAd, __pKeyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_AP_KEY_ADD, 0, __pKeyInfo, 0) + +#define RTMP_DRIVER_80211_RTS_THRESHOLD_ADD(__pAd, __Rts_thresold) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_RTS_THRESHOLD_ADD, 0, __Rts_thresold, 0) + +#define RTMP_DRIVER_80211_FRAG_THRESHOLD_ADD(__pAd, __Frag_thresold) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_FRAG_THRESHOLD_ADD, 0, __Frag_thresold, 0) + +#define RTMP_DRIVER_80211_AP_KEY_DEFAULT_SET(__pAd, __KeyId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_AP_KEY_DEFAULT_SET, 0, NULL, __KeyId) + +#define RTMP_DRIVER_80211_AP_PROBE_RSP(__pAd, __pFrame, __Len) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_AP_PROBE_RSP_EXTRA_IE, 0, __pFrame, __Len) + +#define RTMP_DRIVER_80211_AP_ASSOC_RSP(__pAd, __pFrame, __Len) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_AP_ASSOC_RSP_EXTRA_IE, 0, __pFrame, __Len) + +#define RTMP_DRIVER_80211_AP_MLME_PORT_SECURED(__pAd, __pMac, __Reg) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_PORT_SECURED, 0, __pMac, __Reg) + +#define RTMP_DRIVER_80211_AP_STA_DEL(__pAd, __pMac) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_AP_STA_DEL, 0, __pMac, 0) + +/* P2P Part */ +#define RTMP_DRIVER_80211_ACTION_FRAME_REG(__pAd, __devPtr, __Reg) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_ACTION_FRAME_REG, 0, __devPtr, __Reg) + +#define RTMP_DRIVER_80211_REMAIN_ON_CHAN_DUR_IMER_INIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_REMAIN_ON_CHAN_DUR_TIMER_INIT, 0, NULL, 0) + +#define RTMP_DRIVER_80211_REMAIN_ON_CHAN_SET(__pAd, __pChan, __Duration) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_REMAIN_ON_CHAN_SET, 0, __pChan, __Duration) + +#define RTMP_DRIVER_80211_CANCEL_REMAIN_ON_CHAN_SET(__pAd, __cookie) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CANCEL_REMAIN_ON_CHAN_SET, 0, NULL, __cookie) + +#define RTMP_DRIVER_80211_CHANNEL_LOCK(__pAd, __Chan) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CHANNEL_LOCK, 0, NULL , __Chan) + +#define RTMP_DRIVER_80211_MGMT_FRAME_REG(__pAd, __devPtr, __Reg) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_REG, 0, __devPtr, __Reg) + +#define RTMP_DRIVER_80211_MGMT_FRAME_SEND(__pAd, __pFrame, __Len) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_SEND, 0, __pFrame, __Len) + +#define RTMP_DRIVER_80211_P2P_CHANNEL_RESTORE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CHANNEL_RESTORE, 0, NULL, 0) + +#define RTMP_DRIVER_80211_P2PCLI_ASSSOC_IE_SET(__pAd, __pFrame, __Len) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_P2PCLI_ASSSOC_IE_SET, 0, __pFrame, __Len) + +#define RTMP_DRIVER_80211_P2P_CLIENT_KEY_ADD(__pAd, __pKeyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_P2P_CLIENT_KEY_ADD, 0, __pKeyInfo, 0) + +/* VIF Part */ +#define RTMP_DRIVER_80211_VIF_ADD(__pAd, __pInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_VIF_ADD, 0, __pInfo, 0) + +#define RTMP_DRIVER_80211_VIF_DEL(__pAd, __devPtr, __type) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_VIF_DEL, 0, __devPtr, __type) + +#define RTMP_DRIVER_80211_VIF_CHG(__pAd, __pVifInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_VIF_CHG, 0, __pVifInfo, 0) + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT +#define RTMP_DRIVER_80211_SEND_WIRELESS_EVENT(__pAd, __pMacAddr) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_SEND_WIRELESS_EVENT, 0, __pMacAddr, 0) +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ +#endif /* RT_CFG80211_SUPPORT */ + +/* mesh */ +#define RTMP_DRIVER_MESH_REMOVE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MESH_REMOVE, 0, NULL, 0) + +/* inf ppa */ +#define RTMP_DRIVER_INF_PPA_INIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_PPA_INIT, 0, NULL, 0) + +#define RTMP_DRIVER_INF_PPA_EXIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_PPA_EXIT, 0, NULL, 0) + +/* pci */ +#define RTMP_DRIVER_IRQ_INIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_IRQ_INIT, 0, NULL, 0) + +#define RTMP_DRIVER_IRQ_RELEASE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_IRQ_RELEASE, 0, NULL, 0) + +#define RTMP_DRIVER_PCI_MSI_ENABLE(__pAd, __pPciDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MSI_ENABLE, 0, __pPciDev, 0) + +#define RTMP_DRIVER_PCI_SUSPEND(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCI_SUSPEND, 0, NULL, 0) + +#define RTMP_DRIVER_PCI_RESUME(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCI_RESUME, 0, NULL, 0) + +#define RTMP_DRIVER_PCI_CSR_SET(__pAd, __Address) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCI_CSR_SET, 0, NULL, __Address) + +#define RTMP_DRIVER_PCIE_INIT(__pAd, __pPciDev) \ +{ \ + RT_CMD_PCIE_INIT __Config, *__pConfig = &__Config; \ + __pConfig->pPciDev = __pPciDev; \ + __pConfig->ConfigDeviceID = PCI_DEVICE_ID; \ + __pConfig->ConfigSubsystemVendorID = PCI_SUBSYSTEM_VENDOR_ID; \ + __pConfig->ConfigSubsystemID = PCI_SUBSYSTEM_ID; \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCIE_INIT, 0, __pConfig, 0);\ +} + +/* usb */ +#define RTMP_DRIVER_USB_MORE_FLAG_SET(__pAd, __pConfig) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_MORE_FLAG_SET, 0, __pConfig, 0) + +#define RTMP_DRIVER_USB_CONFIG_INIT(__pAd, __pConfig) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_CONFIG_INIT, 0, __pConfig, 0) + +#define RTMP_DRIVER_USB_SUSPEND(__pAd, __bIsRunning) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_SUSPEND, 0, NULL, __bIsRunning) + +#define RTMP_DRIVER_USB_RESUME(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_RESUME, 0, NULL, 0) + +#define RTMP_DRIVER_USB_INIT(__pAd, __pUsbDev, __driver_info) \ +do { \ + RT_CMD_USB_INIT __Config, *__pConfig = &__Config; \ + __pConfig->pUsbDev = __pUsbDev; \ + __pConfig->driver_info = __driver_info; \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_INIT, 0, __pConfig, 0); \ +} while (0) + +/* ap */ +#define RTMP_DRIVER_AP_BITRATE_GET(__pAd, __pConfig) \ + RTMP_AP_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ, 0, __pConfig, 0) + +#define RTMP_DRIVER_AP_MAIN_OPEN(__pAd) \ + RTMP_AP_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MAIN_OPEN, 0, NULL, 0) + +/* sta */ +#define RTMP_DRIVER_STA_DEV_TYPE_SET(__pAd, __Type) \ + RTMP_STA_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ORI_DEV_TYPE_SET, 0, NULL, __Type, __Type) + +#define RTMP_DRIVER_MAC_ADDR_GET(__pAd, __pMacAddr) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MAC_ADDR_GET, 0, __pMacAddr, 0) + +#define RTMP_DRIVER_ADAPTER_CSO_SUPPORT_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_CSO_SUPPORT_TEST, 0, __flag, 0) + +#define RTMP_DRIVER_ADAPTER_TSO_SUPPORT_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_TSO_SUPPORT_TEST, 0, __flag, 0) + +#ifdef CONFIG_HAS_EARLYSUSPEND +#define RTMP_DRIVER_SET_SUSPEND_FLAG(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SET_SUSPEND_FLAG, 0, NULL, 0) + +#define RTMP_DRIVER_LOAD_FIRMWARE_CHECK(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_LOAD_FIRMWARE_CHECK, 0, NULL, 0) + +#define RTMP_DRIVER_OS_COOKIE_GET(__pAd, __os_cookie) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_OS_COOKIE_GET, 0, __os_cookie, 0) + +#define RTMP_DRIVER_ADAPTER_REGISTER_EARLYSUSPEND(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_REGISTER_EARLYSUSPEND, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_UNREGISTER_EARLYSUSPEND(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_UNREGISTER_EARLYSUSPEND, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_CHECK_EARLYSUSPEND(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_CHECK_EARLYSUSPEND, 0, __flag, 0) +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +#endif /* __RT_OS_NET_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_os_util.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_os_util.h new file mode 100644 index 000000000..f4e8e5d16 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_os_util.h @@ -0,0 +1,857 @@ +/**************************************************************************** + + Module Name: + rt_os_util.h + + Abstract: + All function prototypes are provided from UTIL modules. + + Note: + But can not use any OS key word and compile option here. + All functions are provided from UTIL modules. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RT_OS_UTIL_H__ +#define __RT_OS_UTIL_H__ + +/* ============================ rt_linux.c ================================== */ +/* General */ +VOID RtmpUtilInit(VOID); + +/* OS Time */ +VOID RtmpusecDelay(ULONG usec); +VOID RtmpOsMsDelay(ULONG msec); + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); + +ULONG RTMPMsecsToJiffies(UINT msec); +void RTMP_GetCurrentSystemTick(ULONG *pNow); + +VOID RtmpOsWait(UINT32 Time); +UINT32 RtmpOsTimerAfter(ULONG a, ULONG b); +UINT32 RtmpOsTimerBefore(ULONG a, ULONG b); +VOID RtmpOsGetSystemUpTime(ULONG *pTime); +UINT32 RtmpOsTickUnitGet(VOID); + + +/* + OS Memory +*/ +/* + Function: + allocate memory + Parameters: + + Return: + + mem shall be set as NULL if allocation failed +*/ +NDIS_STATUS os_alloc_mem(VOID *pReserved, UCHAR **mem, ULONG size); +NDIS_STATUS os_alloc_mem_suspend(VOID *pReserved, UCHAR **mem, ULONG size); + +NDIS_STATUS os_free_mem(VOID *pReserved, VOID *mem); + +NDIS_STATUS AdapterBlockAllocateMemory( + IN VOID *handle, + OUT VOID **ppAd, + IN UINT32 SizeOfpAd); + +VOID *RtmpOsVmalloc(ULONG Size); +VOID RtmpOsVfree(VOID *pMem); + +ULONG RtmpOsCopyFromUser(VOID *to, const void *from, ULONG n); +ULONG RtmpOsCopyToUser(VOID *to, const void *from, ULONG n); + +BOOLEAN RtmpOsStatsAlloc(VOID **ppIwStats); + +/* OS Packet */ +PNDIS_PACKET RtmpOSNetPktAlloc(VOID *pReserved, int size); + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer(VOID *pReserved, ULONG Length); + +NDIS_STATUS RTMPAllocateNdisPacket( + IN VOID *pReserved, + OUT PNDIS_PACKET *ppPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen); + +VOID RTMPFreeNdisPacket(VOID *pReserved, PNDIS_PACKET pPacket); + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen); + +PNDIS_PACKET DuplicatePacket( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + +PNDIS_PACKET duplicate_pkt( + IN PNET_DEV pNetDev, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN VOID *pReserved, + IN PNDIS_PACKET pOldPkt); + +PNDIS_PACKET duplicate_pkt_with_VLAN( + IN PNET_DEV pNetDev, + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID); + +typedef void (*RTMP_CB_8023_PACKET_ANNOUNCE)( + IN VOID *pCtrlBkPtr, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode); + +BOOLEAN RTMPL2FrameTxAction( + IN VOID *pCtrlBkPtr, + IN PNET_DEV pNetDev, + IN RTMP_CB_8023_PACKET_ANNOUNCE _announce_802_3_packet, + IN UCHAR apidx, + IN PUCHAR pData, + IN UINT32 data_len, + IN UCHAR OpMode); + +PNDIS_PACKET ExpandPacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket, + IN UINT32 ext_head_len, + IN UINT32 ext_tail_len); + +PNDIS_PACKET ClonePacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize); + + +void wlan_802_11_to_802_3_packet( + IN PNET_DEV pNetDev, + IN UCHAR OpMode, + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PNDIS_PACKET pRxPacket, + IN UCHAR *pData, + IN ULONG DataSize, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID); +#ifdef CONFIG_SNIFFER_SUPPORT +void send_prism_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR BssMonitorFlag11n, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UINT32 MaxRssi); + +void send_radiotap_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR LDPC, + UCHAR LDPC_EX_SYM, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UCHAR sideband_index, + CHAR MaxRssi, + UINT32 timestamp); + +#ifdef PPI_HEADER +void send_ppi_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR LDPC, + UCHAR LDPC_EX_SYM, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UCHAR sideband_index, + CHAR MaxRssi, + UINT32 timestamp); +#endif //PPI_HEADER +#endif /* CONFIG_SNIFFER_SUPPORT */ + +UCHAR VLAN_8023_Header_Copy( + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + OUT PUCHAR pData, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID); + +VOID RtmpOsPktBodyCopy( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pNetPkt, + IN ULONG ThisFrameLen, + IN PUCHAR pData); + +INT RtmpOsIsPktCloned(PNDIS_PACKET pNetPkt); +PNDIS_PACKET RtmpOsPktCopy(PNDIS_PACKET pNetPkt); +PNDIS_PACKET RtmpOsPktClone(PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktDataPtrAssign(PNDIS_PACKET pNetPkt, UCHAR *pData); + +VOID RtmpOsPktLenAssign(PNDIS_PACKET pNetPkt, LONG Len); +VOID RtmpOsPktTailAdjust(PNDIS_PACKET pNetPkt, UINT removedTagLen); + +PUCHAR RtmpOsPktTailBufExtend(PNDIS_PACKET pNetPkt, UINT len); +PUCHAR RtmpOsPktHeadBufExtend(PNDIS_PACKET pNetPkt, UINT len); +VOID RtmpOsPktReserve(PNDIS_PACKET pNetPkt, UINT len); + +VOID RtmpOsPktInfPpaSend(PNDIS_PACKET pNetPkt); +VOID RtmpOsPktInit(PNDIS_PACKET pNetPkt, PNET_DEV pNetDev, UCHAR *buf, USHORT len); + +PNDIS_PACKET RtmpOsPktIappMakeUp(PNET_DEV pNetDev, UINT8 *pMac); + +BOOLEAN RtmpOsPktOffsetInit(VOID); + +UINT16 RtmpOsNtohs(UINT16 Value); +UINT16 RtmpOsHtons(UINT16 Value); +UINT32 RtmpOsNtohl(UINT32 Value); +UINT32 RtmpOsHtonl(UINT32 Value); + +/* OS File */ +RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode); +int RtmpOSFileClose(RTMP_OS_FD osfd); +void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset); +int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen); +int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen); + +INT32 RtmpOsFileIsErr(VOID *pFile); + +void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet); + +/* OS Network Interface */ +int RtmpOSNetDevAddrSet( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN PUCHAR pMacAddr, + IN PUCHAR dev_name); + +void RtmpOSNetDevClose(PNET_DEV pNetDev); +void RtmpOSNetDevFree(PNET_DEV pNetDev); +INT RtmpOSNetDevAlloc(PNET_DEV *new_dev_p, UINT32 privDataSize); +INT RtmpOSNetDevOpsAlloc(PVOID *pNetDevOps); + + +#ifdef CONFIG_STA_SUPPORT +INT RtmpOSNotifyRawData(PNET_DEV pNetDev, UCHAR *buf, INT len, ULONG type, USHORT proto); + +#endif /* CONFIG_STA_SUPPORT */ + +PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName); + +void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev); + +INT RtmpOSNetDevDestory(VOID *pReserved, PNET_DEV pNetDev); +void RtmpOSNetDevDetach(PNET_DEV pNetDev); +int RtmpOSNetDevAttach( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook); + +void RtmpOSNetDevProtect( + IN BOOLEAN lock_it); + +PNET_DEV RtmpOSNetDevCreate( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN INT devType, + IN INT devNum, + IN INT privMemSize, + IN PSTRING pNamePrefix); + +BOOLEAN RtmpOSNetDevIsUp(VOID *pDev); + +unsigned char *RtmpOsNetDevGetPhyAddr(VOID *pDev); + +VOID RtmpOsNetQueueStart(PNET_DEV pDev); +VOID RtmpOsNetQueueStop(PNET_DEV pDev); +VOID RtmpOsNetQueueWake(PNET_DEV pDev); + +VOID RtmpOsSetPktNetDev(VOID *pPkt, VOID *pDev); +PNET_DEV RtmpOsPktNetDevGet(VOID *pPkt); + +char *RtmpOsGetNetDevName(VOID *pDev); + +UINT32 RtmpOsGetNetIfIndex(IN VOID *pDev); + +VOID RtmpOsSetNetDevPriv(VOID *pDev, VOID *pPriv); +VOID *RtmpOsGetNetDevPriv(VOID *pDev); + +VOID RtmpOsSetNetDevWdev(VOID *net_dev, VOID *wdev); +VOID *RtmpOsGetNetDevWdev(VOID *pDev); + +USHORT RtmpDevPrivFlagsGet(VOID *pDev); +VOID RtmpDevPrivFlagsSet(VOID *pDev, USHORT PrivFlags); + +VOID RtmpOsSetNetDevType(VOID *pDev, USHORT Type); +VOID RtmpOsSetNetDevTypeMonitor(VOID *pDev); +UCHAR get_sniffer_mode(VOID *pDev); +VOID set_sniffer_mode(VOID *pDev, UCHAR mode); + +/* OS Semaphore */ +VOID RtmpOsCmdUp(RTMP_OS_TASK *pCmdQTask); +BOOLEAN RtmpOsSemaInitLocked(RTMP_OS_SEM *pSemOrg, LIST_HEADER *pSemList); +BOOLEAN RtmpOsSemaInit(RTMP_OS_SEM *pSemOrg, LIST_HEADER *pSemList); +BOOLEAN RtmpOsSemaDestory(RTMP_OS_SEM *pSemOrg); +INT RtmpOsSemaWaitInterruptible(RTMP_OS_SEM *pSemOrg); +VOID RtmpOsSemaWakeUp(RTMP_OS_SEM *pSemOrg); +VOID RtmpOsMlmeUp(RTMP_OS_TASK *pMlmeQTask); + +VOID RtmpOsInitCompletion(RTMP_OS_COMPLETION *pCompletion); +VOID RtmpOsExitCompletion(RTMP_OS_COMPLETION *pCompletion); +VOID RtmpOsComplete(RTMP_OS_COMPLETION *pCompletion); +ULONG RtmpOsWaitForCompletionTimeout(RTMP_OS_COMPLETION *pCompletion, ULONG Timeout); + +/* OS Task */ +BOOLEAN RtmpOsTaskletSche(RTMP_NET_TASK_STRUCT *pTasklet); + +BOOLEAN RtmpOsTaskletInit( + RTMP_NET_TASK_STRUCT *pTasklet, + VOID (*pFunc)(unsigned long data), + ULONG Data, + LIST_HEADER *pTaskletList); + +BOOLEAN RtmpOsTaskletKill(RTMP_NET_TASK_STRUCT *pTasklet); +VOID RtmpOsTaskletDataAssign(RTMP_NET_TASK_STRUCT *pTasklet, ULONG Data); + +VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTaskOrg); +INT32 RtmpOsTaskIsKilled(RTMP_OS_TASK *pTaskOrg); + +BOOLEAN RtmpOsCheckTaskLegality(RTMP_OS_TASK *pTaskOrg); + +BOOLEAN RtmpOSTaskAlloc(RTMP_OS_TASK *pTask, LIST_HEADER *pTaskList); + +VOID RtmpOSTaskFree(RTMP_OS_TASK *pTask); + +NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTaskOrg); + +INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTaskOrg); + +VOID RtmpOSTaskCustomize(RTMP_OS_TASK *pTaskOrg); + +NDIS_STATUS RtmpOSTaskAttach( + IN RTMP_OS_TASK *pTaskOrg, + IN RTMP_OS_TASK_CALLBACK fn, + IN ULONG arg); + +NDIS_STATUS RtmpOSTaskInit( + IN RTMP_OS_TASK *pTaskOrg, + IN PSTRING pTaskName, + IN VOID *pPriv, + IN LIST_HEADER *pTaskList, + IN LIST_HEADER *pSemList); + +BOOLEAN RtmpOSTaskWait( + IN VOID *pReserved, + IN RTMP_OS_TASK *pTaskOrg, + IN INT32 *pStatus); + +VOID *RtmpOsTaskDataGet(RTMP_OS_TASK *pTaskOrg); + +INT32 RtmpThreadPidKill(RTMP_OS_PID PID); + +/* OS Cache */ +VOID RtmpOsDCacheFlush(ULONG AddrStart, ULONG Size); + +/* OS Timer */ +VOID RTMP_SetPeriodicTimer( + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout); + +VOID RTMP_OS_Init_Timer( + IN VOID *pReserved, + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN TIMER_FUNCTION function, + IN PVOID data, + IN LIST_HEADER *pTimerList); + +VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout); +VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout); +VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled); +VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg); + +BOOLEAN RTMP_OS_Alloc_Rsc(LIST_HEADER *pRscList, VOID *pRsc, UINT32 RscLen); +VOID RTMP_OS_Free_Rscs(LIST_HEADER *pRscList); + +/* OS Lock */ +BOOLEAN RtmpOsAllocateLock(NDIS_SPIN_LOCK *pLock, LIST_HEADER *pLockList); +VOID RtmpOsFreeSpinLock(NDIS_SPIN_LOCK *pLockOrg); +VOID RtmpOsSpinLockBh(NDIS_SPIN_LOCK *pLockOrg); +VOID RtmpOsSpinUnLockBh(NDIS_SPIN_LOCK *pLockOrg); +VOID RtmpOsIntLock(NDIS_SPIN_LOCK *pLockOrg, ULONG *pIrqFlags); +VOID RtmpOsIntUnLock(NDIS_SPIN_LOCK *pLockOrg, ULONG IrqFlags); + +/* OS PID */ +VOID RtmpOsGetPid(ULONG *pDst, ULONG PID); +VOID RtmpOsTaskPidInit(RTMP_OS_PID *pPid); + +/* OS I/O */ +VOID RTMP_PCI_Writel(ULONG Value, VOID *pAddr); +VOID RTMP_PCI_Writew(ULONG Value, VOID *pAddr); +VOID RTMP_PCI_Writeb(ULONG Value, VOID *pAddr); +ULONG RTMP_PCI_Readl(VOID *pAddr); +ULONG RTMP_PCI_Readw(VOID *pAddr); +ULONG RTMP_PCI_Readb(VOID *pAddr); + +int RtmpOsPciConfigReadWord( + IN VOID *pDev, + IN UINT32 Offset, + OUT UINT16 *pValue); + +int RtmpOsPciConfigWriteWord(VOID *pDev, UINT32 Offset, UINT16 Value); +int RtmpOsPciConfigReadDWord(VOID *pDev, UINT32 Offset, UINT32 *pValue); +int RtmpOsPciConfigWriteDWord(VOID *pDev, UINT32 Offset, UINT32 Value); + +int RtmpOsPciFindCapability(VOID *pDev, INT Cap); + +VOID *RTMPFindHostPCIDev(VOID *pPciDevSrc); + +int RtmpOsPciMsiEnable(VOID *pDev); +VOID RtmpOsPciMsiDisable(VOID *pDev); + +/* OS Wireless */ +ULONG RtmpOsMaxScanDataGet(VOID); + +/* OS Interrutp */ +INT32 RtmpOsIsInInterrupt(VOID); + +/* OS USB */ +VOID *RtmpOsUsbUrbDataGet(VOID *pUrb); +NTSTATUS RtmpOsUsbUrbStatusGet(VOID *pUrb); +ULONG RtmpOsUsbUrbLenGet(VOID *pUrb); + +/* OS Atomic */ +BOOLEAN RtmpOsAtomicInit(RTMP_OS_ATOMIC *pAtomic, LIST_HEADER *pAtomicList); +VOID RtmpOsAtomicDestroy(RTMP_OS_ATOMIC *pAtomic); +LONG RtmpOsAtomicRead(RTMP_OS_ATOMIC *pAtomic); +VOID RtmpOsAtomicDec(RTMP_OS_ATOMIC *pAtomic); +VOID RtmpOsAtomicInterlockedExchange(RTMP_OS_ATOMIC *pAtomicSrc, LONG Value); + +/* OS Utility */ + +typedef VOID (*RTMP_OS_SEND_WLAN_EVENT)( + IN VOID *pAdSrc, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi); + +VOID RtmpOsSendWirelessEvent( + IN VOID *pAd, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi, + IN RTMP_OS_SEND_WLAN_EVENT pFunc); + +#ifdef CONFIG_AP_SUPPORT +void SendSignalToDaemon( + IN INT sig, + IN RTMP_OS_PID pid, + IN unsigned long pid_no); +#endif /* CONFIG_AP_SUPPORT */ + +int RtmpOSWrielessEventSend( + IN PNET_DEV pNetDev, + IN UINT32 eventType, + IN INT flags, + IN PUCHAR pSrcMac, + IN PUCHAR pData, + IN UINT32 dataLen); + +int RtmpOSWrielessEventSendExt( + IN PNET_DEV pNetDev, + IN UINT32 eventType, + IN INT flags, + IN PUCHAR pSrcMac, + IN PUCHAR pData, + IN UINT32 dataLen, + IN UINT32 family); + +UINT RtmpOsWirelessExtVerGet(VOID); + +VOID RtmpDrvAllMacPrint( + IN VOID *pReserved, + IN UINT32 *pBufMac, + IN UINT32 AddrStart, + IN UINT32 AddrEnd, + IN UINT32 AddrStep); + +VOID RtmpDrvAllE2PPrint( + IN VOID *pReserved, + IN USHORT *pMacContent, + IN UINT32 AddrEnd, + IN UINT32 AddrStep); + +VOID RtmpDrvAllRFPrint( + IN VOID *pReserved, + IN UCHAR *pBuf, + IN UINT32 BufLen); + +int RtmpOSIRQRelease( + IN PNET_DEV pNetDev, + IN UINT32 infType, + IN PPCI_DEV pci_dev, + IN BOOLEAN *pHaveMsi); + +VOID RtmpOsWlanEventSet( + IN VOID *pReserved, + IN BOOLEAN *pCfgWEnt, + IN BOOLEAN FlgIsWEntSup); + +UINT16 RtmpOsGetUnaligned(UINT16 *pWord); + +UINT32 RtmpOsGetUnaligned32(UINT32 *pWord); + +ULONG RtmpOsGetUnalignedlong(ULONG *pWord); + +long RtmpOsSimpleStrtol( + IN const char *cp, + IN char **endp, + IN unsigned int base); + +VOID RtmpOsOpsInit(RTMP_OS_ABL_OPS *pOps); + +/* ============================ rt_os_util.c ================================ */ +VOID RtmpDrvRateGet( + IN VOID *pReserved, + IN UINT8 MODE, + IN UINT8 ShortGI, + IN UINT8 BW, + IN UINT8 MCS, + IN UINT8 Antenna, + OUT UINT32 *pRate); + +char * rtstrchr(const char * s, int c); + +PSTRING WscGetAuthTypeStr(USHORT authFlag); + +PSTRING WscGetEncryTypeStr(USHORT encryFlag); + +USHORT WscGetAuthTypeFromStr(PSTRING arg); + +USHORT WscGetEncrypTypeFromStr(PSTRING arg); + +VOID RtmpMeshDown( + IN VOID *pDrvCtrlBK, + IN BOOLEAN WaitFlag, + IN BOOLEAN (*RtmpMeshLinkCheck)(IN VOID *pAd)); + +USHORT RtmpOsNetPrivGet(PNET_DEV pDev); + +BOOLEAN RtmpOsCmdDisplayLenCheck( + IN UINT32 LenSrc, + IN UINT32 Offset); + +VOID WpaSendMicFailureToWpaSupplicant( + IN PNET_DEV pNetDev, + IN const PUCHAR src_addr, + IN BOOLEAN bUnicast, + IN INT key_id, + IN const PUCHAR tsc); + +int wext_notify_event_assoc( + IN PNET_DEV pNetDev, + IN UCHAR *ReqVarIEs, + IN UINT32 ReqVarIELen); + +VOID SendAssocIEsToWpaSupplicant( + IN PNET_DEV pNetDev, + IN UCHAR *ReqVarIEs, + IN UINT32 ReqVarIELen); + +/* ============================ rt_rbus_pci_util.c ========================== */ +void RtmpAllocDescBuf( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT VOID **VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RtmpFreeDescBuf( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN VOID *VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT VOID **VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_FreeFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +PNDIS_PACKET RTMP_AllocateRxPacketBuffer( + IN VOID *pReserved, + IN VOID *pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + +int RTMP_Usb_AutoPM_Put_Interface( + IN VOID *pUsb_Dev, + IN VOID *intf); + +int RTMP_Usb_AutoPM_Get_Interface( + IN VOID *pUsb_Dev, + IN VOID *intf); + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ +#endif /* CONFIG_STA_SUPPORT */ + + + +ra_dma_addr_t linux_pci_map_single(void *pPciDev, void *ptr, size_t size, int sd_idx, int direction); + +void linux_pci_unmap_single(void *pPciDev, ra_dma_addr_t dma_addr, size_t size, int direction); + +/* ============================ rt_usb_util.c =============================== */ + +#if defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) +void RtmpFlashRead( + UCHAR * p, + ULONG a, + ULONG b); + +void RtmpFlashWrite( + UCHAR * p, + ULONG a, + ULONG b); +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + +UINT32 RtmpOsGetUsbDevVendorID( + IN VOID *pUsbDev); + +UINT32 RtmpOsGetUsbDevProductID( + IN VOID *pUsbDev); + +/* CFG80211 */ +#ifdef RT_CFG80211_SUPPORT +typedef struct __CFG80211_BAND { + + UINT8 RFICType; + UINT8 MpduDensity; + UINT8 TxStream; + UINT8 RxStream; + UINT32 MaxTxPwr; + UINT32 MaxBssTable; + + UINT16 RtsThreshold; + UINT16 FragmentThreshold; + UINT32 RetryMaxCnt; /* bit0~7: short; bit8 ~ 15: long */ + BOOLEAN FlgIsBMode; +} CFG80211_BAND; + +VOID CFG80211OS_UnRegister( + IN VOID *pCB, + IN VOID *pNetDev); + +BOOLEAN CFG80211_SupBandInit( + IN VOID *pCB, + IN CFG80211_BAND *pBandInfo, + IN VOID *pWiphyOrg, + IN VOID *pChannelsOrg, + IN VOID *pRatesOrg); + +BOOLEAN CFG80211OS_SupBandReInit( + IN VOID *pCB, + IN CFG80211_BAND *pBandInfo); + +VOID CFG80211OS_RegHint( + IN VOID *pCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen); + +VOID CFG80211OS_RegHint11D( + IN VOID *pCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen); + +BOOLEAN CFG80211OS_BandInfoGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + OUT VOID **ppBand24, + OUT VOID **ppBand5); + +UINT32 CFG80211OS_ChanNumGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + IN UINT32 IdBand); + +BOOLEAN CFG80211OS_ChanInfoGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + IN UINT32 IdBand, + IN UINT32 IdChan, + OUT UINT32 *pChanId, + OUT UINT32 *pPower, + OUT BOOLEAN *pFlgIsRadar); + +BOOLEAN CFG80211OS_ChanInfoInit( + IN VOID *pCB, + IN UINT32 InfoIndex, + IN UCHAR ChanId, + IN UCHAR MaxTxPwr, + IN BOOLEAN FlgIsNMode, + IN BOOLEAN FlgIsBW20M); + +VOID CFG80211OS_Scaning( + IN VOID *pCB, + IN UINT32 ChanId, + IN UCHAR *pFrame, + IN UINT32 FrameLen, + IN INT32 RSSI, + IN BOOLEAN FlgIsNMode, + IN UINT8 BW); + +VOID CFG80211OS_ScanEnd( + IN VOID *pCB, + IN BOOLEAN FlgIsAborted); + +void CFG80211OS_ConnectResultInform( + IN VOID *pCB, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess); + +void CFG80211OS_P2pClientConnectResultInform( + IN PNET_DEV pNetDev, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess); + +BOOLEAN CFG80211OS_RxMgmt(IN PNET_DEV pNetDev, IN INT32 freq, IN PUCHAR frame, IN UINT32 len); +VOID CFG80211OS_TxStatus(IN PNET_DEV pNetDev, IN INT32 cookie, IN PUCHAR frame, IN UINT32 len, IN BOOLEAN ack); +VOID CFG80211OS_NewSta(IN PNET_DEV pNetDev, IN const PUCHAR mac_addr, IN const PUCHAR assoc_frame, IN UINT32 assoc_len); +VOID CFG80211OS_DelSta(IN PNET_DEV pNetDev, IN const PUCHAR mac_addr); +VOID CFG80211OS_MICFailReport(IN PNET_DEV pNetDev, IN const PUCHAR src_addr, IN BOOLEAN unicast, IN INT key_id, IN const PUCHAR tsc ); +VOID CFG80211OS_Roamed(PNET_DEV pNetDev, IN UCHAR *pBSSID, + UCHAR *pReqIe, UINT32 ReqIeLen, UCHAR *pRspIe, UINT32 RspIeLen); +VOID CFG80211OS_RecvObssBeacon(VOID *pCB, const PUCHAR pFrame, INT frameLen, INT freq); +#endif /* RT_CFG80211_SUPPORT */ + + + + +/* ================================ MACRO =================================== */ +#define RTMP_UTIL_DCACHE_FLUSH(__AddrStart, __Size) + +/* ================================ EXTERN ================================== */ +extern UCHAR SNAP_802_1H[6]; +extern UCHAR SNAP_BRIDGE_TUNNEL[6]; +extern UCHAR EAPOL[2]; +extern UCHAR TPID[]; +extern UCHAR IPX[2]; +extern UCHAR APPLE_TALK[2]; +extern UCHAR NUM_BIT8[8]; +extern ULONG RTPktOffsetData, RTPktOffsetLen, RTPktOffsetCB; + +extern ULONG OS_NumOfMemAlloc, OS_NumOfMemFree; + +extern UINT32 RalinkRate_Legacy[]; +extern UINT32 RalinkRate_HT_1NSS[Rate_BW_MAX][Rate_GI_MAX][Rate_MCS]; +extern UINT32 RalinkRate_VHT_1NSS[Rate_BW_MAX][Rate_GI_MAX][Rate_MCS]; +extern UINT8 newRateGetAntenna(UINT8 MCS, UINT8 PhyMode); + + +#ifdef PLATFORM_UBM_IPX8 +#include "vrut_ubm.h" +#endif /* PLATFORM_UBM_IPX8 */ + +INT32 RtPrivIoctlSetVal(VOID); + +void OS_SPIN_LOCK(NDIS_SPIN_LOCK *lock); +void OS_SPIN_UNLOCK(NDIS_SPIN_LOCK *lock); +void OS_SPIN_LOCK_IRQSAVE(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void OS_SPIN_UNLOCK_IRQRESTORE(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void OS_SPIN_LOCK_IRQ(NDIS_SPIN_LOCK *lock); +void OS_SPIN_UNLOCK_IRQ(NDIS_SPIN_LOCK *lock); +void RtmpOsSpinLockIrqSave(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void RtmpOsSpinUnlockIrqRestore(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void RtmpOsSpinLockIrq(NDIS_SPIN_LOCK *lock); +void RtmpOsSpinUnlockIrq(NDIS_SPIN_LOCK *lock); +int OS_TEST_BIT(int bit, unsigned long *flags); +void OS_SET_BIT(int bit, unsigned long *flags); +void OS_CLEAR_BIT(int bit, unsigned long *flags); +void OS_LOAD_CODE_FROM_BIN(unsigned char **image, char *bin_name, void *inf_dev, UINT32 *code_len); + +#endif /* __RT_OS_UTIL_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_txbf.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_txbf.h new file mode 100644 index 000000000..ca02ef61c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rt_txbf.h @@ -0,0 +1,364 @@ +/* + *************************************************************************** + * 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: + cmm_txbf.c + + Abstract: + Tx Beamforming related constants and data structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Shiang 2010/06/29 +*/ + + +#ifndef _RT_TXBF_H_ +#define _RT_TXBF_H_ + +#ifdef TXBF_SUPPORT + +#ifdef MT76x2 +// Divider phase calibration closed loop definition +#define RX0TX0 0 +#define RX0TX1 1 +#define RX1TX0 4 +#define RX1TX1 5 + +#define ADC0_RX0_2R 8 +#define ADC1_RX1_2R 8 +#endif + +//#define MRQ_FORCE_TX //Force MRQ regardless the capability of the station + + +// TxSndgPkt Sounding type definitions +#define SNDG_TYPE_DISABLE 0 +#define SNDG_TYPE_SOUNDING 1 +#define SNDG_TYPE_NDP 2 + +// Explicit TxBF feedback mechanism +#define ETXBF_FB_DISABLE 0 +#define ETXBF_FB_CSI 1 +#define ETXBF_FB_NONCOMP 2 +#define ETXBF_FB_COMP 4 + + +//#define MRQ_FORCE_TX //Force MRQ regardless the capability of the station + +/* + eTxBfEnCond values: + 0:no etxbf, + 1:etxbf update periodically, + 2:etxbf updated if mcs changes in RateSwitchingAdapt() or APQuickResponeForRateUpExecAdapt(). + 3:auto-selection: if mfb changes or timer expires, then send sounding packets <------not finished yet!!! + note: + when = 1 or 3, NO_SNDG_CNT_THRD controls the frequency to update the + matrix(ETXBF_EN_COND=1) or activate the whole bf evaluation process(not defined) +*/ + +// Defines to include optional code. +// NOTE: Do not define these options. ETxBfEnCond==3 and +// MCS Feedback are not fully implemented +//#define ETXBF_EN_COND3_SUPPORT // Include ETxBfEnCond==3 code +//#define MFB_SUPPORT // Include MCS Feedback code + +// MCS FB definitions +#define MSI_TOGGLE_BF 6 +#define TOGGLE_BF_PKTS 5// the number of packets with inverted BF status + +// TXBF State definitions +#define READY_FOR_SNDG0 0//jump to WAIT_SNDG_FB0 when channel change or periodically +#define WAIT_SNDG_FB0 1//jump to WAIT_SNDG_FB1 when bf report0 is received +#define WAIT_SNDG_FB1 2 +#define WAIT_MFB 3 +#define WAIT_USELESS_RSP 4 +#define WAIT_BEST_SNDG 5 + +#define NO_SNDG_CNT_THRD 0//send sndg packet if there is no sounding for (NO_SNDG_CNT_THRD+1)*500msec. If this =0, bf matrix is updated at each call of APMlmeDynamicTxRateSwitchingAdapt() + + +// ------------ BEAMFORMING PROFILE HANDLING ------------ + +#define IMP_MAX_BYTES 14 // Implicit: 14 bytes per subcarrier +#define IMP_MAX_BYTES_ONE_COL 7 // Implicit: 7 bytes per subcarrier, when reading first column +#define EXP_MAX_BYTES 18 // Explicit: 18 bytes per subcarrier +#ifdef MT76x2 +#define MAX_BYTES 2 // 2 bytes per subcarrier for implicit and explicit TxBf +#endif +#define IMP_COEFF_SIZE 9 // 9 bits/coeff +#define IMP_COEFF_MASK 0x1FF + +#define PROFILE_MAX_CARRIERS_20 56 // Number of subcarriers in 20 MHz mode +#define PROFILE_MAX_CARRIERS_40 114 // Number of subcarriers in 40 MHz mode +#ifdef MT76x2 +#define PROFILE_MAX_CARRIERS_80 242 // Number of subcarriers in 80 MHz mode +#endif + +#ifdef MT76x2 +#define NUM_CHAIN 3 +#endif + +// Indices of valid rows in Implicit and Explicit profiles for 20 and 40 MHz +typedef struct { + int lwb1, upb1; + int lwb2, upb2; +} SC_TABLE_ENTRY; + + +typedef struct { + BOOLEAN impProfile; + BOOLEAN fortyMHz; + int rows, columns; + int grouping; + UCHAR tag[EXP_MAX_BYTES]; + UCHAR data[PROFILE_MAX_CARRIERS_40][EXP_MAX_BYTES]; +} PROFILE_DATA; + +extern PROFILE_DATA profData; + +#ifdef MT76x2 +typedef struct { + UCHAR ng, cw, nrow, ncol, LM; + UCHAR LD, EO, IO, I_E; + UCHAR DMAC[6]; + UCHAR Tx1_scale_2ss, Tx0_scale_2ss, Tx1_scale_1ss, Tx0_scale_1ss; + UCHAR STS1_SNR, STS0_SNR; + USHORT timeout; + UCHAR validFlg; + UCHAR CMDInIdx; +} PFMU_PROFILE; + +typedef struct { + UCHAR dCMDInIdx; + UCHAR psi21, phill; + UCHAR data[PROFILE_MAX_CARRIERS_80][MAX_BYTES]; +} PFMU_DATA; +#endif + + +typedef +struct { + +#ifdef MT76x2 + UCHAR E1gBeg; + UCHAR E1gEnd; + UCHAR E1aHighBeg; + UCHAR E1aHighEnd; + UCHAR E1aLowBeg; + UCHAR E1aLowEnd; + UCHAR E1aMidBeg; + UCHAR E1aMidMid; + UCHAR E1aMidEnd; + UCHAR E1aPhase[13]; + UCHAR E1aPhaseErr[13]; +#endif +} ITXBF_PHASE_PARAMS; // ITxBF BBP reg phase calibration parameters + +typedef +struct { + +#ifdef MT76x2 + UCHAR E1gBeg[3]; + UCHAR E1gEnd[3]; + UCHAR E1aHighBeg[3]; + UCHAR E1aHighEnd[3]; + UCHAR E1aLowBeg[3]; + UCHAR E1aLowEnd[3]; + UCHAR E1aMidBeg[3]; + UCHAR E1aMidMid[3]; + UCHAR E1aMidEnd[3]; +#endif +} ITXBF_LNA_PARAMS; // ITxBF BBP reg LNA calibration parameters + +typedef +struct { + +#ifdef MT76x2 + UCHAR E1gBeg; + UCHAR E1gEnd; + UCHAR E1aHighBeg; + UCHAR E1aHighEnd; + UCHAR E1aLowBeg; + UCHAR E1aLowEnd; + UCHAR E1aMidBeg; + UCHAR E1aMidMid; + UCHAR E1aMidEnd; + UCHAR E1aDivPhase[5]; +#endif +} ITXBF_DIV_PARAMS; // ITxBF Divider Calibration parameters + +typedef +struct { +#ifdef MT76x2 + UCHAR TankCode[10]; +#endif +} ITXBF_TANK_PARAMS; // ITxBF Divider Calibration parameters + +BOOLEAN ITxBFGetEEPROM( + IN RTMP_ADAPTER *pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams, + IN ITXBF_TANK_PARAMS *tankParams); + +void ITxBFSetEEPROM( + IN RTMP_ADAPTER *pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams, + IN ITXBF_TANK_PARAMS *tankParams); + +#ifdef MT76x2 +INT ITxBFDividerCalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + OUT UCHAR *divPhase); + +INT ITxBFLoPhaseCalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN eepromUpdateFlg, + OUT UCHAR *LoPhase); + +INT ITxBFLNACalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN INT calMethod, + IN BOOLEAN gBand); + +INT ITxBFPhaseCalibrationStartUp( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN BOOLEAN loOffsetCkFlg, + IN USHORT ch); +#endif + +INT ITxBFDividerCalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + OUT UCHAR *divPhase); + +VOID ITxBFLoadLNAComp( + IN RTMP_ADAPTER *pAd); + +int ITxBFLNACalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + IN BOOLEAN gBand); + +#ifdef MT76x2 +INT mt76x2_ITxBFDividerCalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + OUT UCHAR *divPhase); + +INT mt76x2_ITxBFLoPhaseCalibration( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN eepromUpdateFlg, + OUT UCHAR *LoPhase); + +VOID mt76x2_ITxBFLoadLNAComp( + IN RTMP_ADAPTER *pAd); + +int mt76x2_ITxBFLNACalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + IN BOOLEAN gBand); + +INT mt76x2_ITxBFPhaseCalibration( + IN RTMP_ADAPTER *pAd, + IN INT calFunction, + IN BOOLEAN loOffsetCkFlg, + IN USHORT ch); +#endif + +void Read_TxBfProfile( + IN RTMP_ADAPTER *pAd, + IN PROFILE_DATA *prof, + IN int profileNum, + IN BOOLEAN implicitProfile); + +void Write_TxBfProfile( + IN RTMP_ADAPTER *pAd, + IN PROFILE_DATA *prof, + IN int profileNum); + +void Read_TagField( + IN PRTMP_ADAPTER pAd, + IN UCHAR *row, + IN int profileNum); + +// Write_TagField - write a profile tagfield +void Write_TagField( + IN RTMP_ADAPTER *pAd, + IN UCHAR *row, + IN int profileNum); + +#ifdef MT76x2 +INT TxBfProfileTagRead( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN UCHAR profileIdx); + +INT TxBfProfileTagWrite( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN UCHAR profileIdx); + +INT TxBfProfileDataRead( + IN PRTMP_ADAPTER pAd, + IN PFMU_DATA *pData, + IN UCHAR profileIdx, + IN UCHAR subcarrierIdx); + +INT TxBfProfileDataWrite( + IN PRTMP_ADAPTER pAd, + IN PFMU_DATA *pData, + IN UCHAR profileIdx, + IN UCHAR subcarrierIdx); + +INT TxBfProfileTagValid( + IN PRTMP_ADAPTER pAd, + IN PFMU_PROFILE *prof, + IN UCHAR profileIdx); +#endif + +// displayTagfield - display one tagfield +void displayTagfield( + IN RTMP_ADAPTER *pAd, + IN int profileNum, + IN BOOLEAN implicitProfile); + +// Unpack an ITxBF matrix element from a row of bytes +int Unpack_IBFValue( + IN UCHAR *row, + IN int elemNum); + +int iCalcCalibration( + IN RTMP_ADAPTER *pAd, + IN int calParams[2], + IN int profileNum); + +#endif // TXBF_SUPPORT // + +#endif // _RT_TXBF_H_ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp.h new file mode 100644 index 000000000..f9509a7f9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp.h @@ -0,0 +1,11196 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + James Tan 2002-09-06 modified (Revise NTCRegTable) + John Chang 2004-09-06 modified for RT2600 +*/ +#ifndef __RTMP_H__ +#define __RTMP_H__ + +#include "link_list.h" +#include "spectrum_def.h" + +#include "rtmp_dot11.h" +#include "wpa_cmm.h" + +#ifdef CONFIG_AP_SUPPORT +#include "ap_autoChSel_cmm.h" +#endif /* CONFIG_AP_SUPPORT */ + +#include "wsc.h" +#ifdef MAT_SUPPORT +#include "mat.h" +#endif /* MAT_SUPPORT */ + + +#ifdef WAPI_SUPPORT +#include "wapi_def.h" +#endif /* WAPI_SUPPORT */ + +#include "rtmp_chip.h" + +#ifdef DOT11R_FT_SUPPORT +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "rrm_cmm.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT +#include "pmf_cmm.h" +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +#include "tdls_cmm.h" +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef CLIENT_WDS +#include "client_wds_cmm.h" +#endif /* CLIENT_WDS */ + +#ifdef DOT11V_WNM_SUPPORT +#include "wnm_cmm.h" +#endif /* DOT11V_WNM_SUPPORT */ + + + +#ifdef RT_CFG80211_SUPPORT +#include "cfg80211_cmm.h" +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef WFD_SUPPORT +#include "wfd_cmm.h" +#endif /* WFD_SUPPORT */ + +#include "drs_extr.h" + +struct _RTMP_RA_LEGACY_TB; + +typedef struct _RTMP_ADAPTER RTMP_ADAPTER; +typedef struct _RTMP_ADAPTER *PRTMP_ADAPTER; + +typedef struct _RTMP_CHIP_OP_ RTMP_CHIP_OP; +typedef struct _RTMP_CHIP_CAP_ RTMP_CHIP_CAP; + +#ifdef BB_SOC +#include "os/bb_soc.h" +#endif + +typedef struct _UAPSD_INFO { + BOOLEAN bAPSDCapable; +} UAPSD_INFO; + +#include "mcu/mcu.h" + + +#ifdef CONFIG_ANDES_SUPPORT +#include "mcu/mcu_and.h" +#endif /* CONFIG_ANDES_SUPPORT */ + +#include "radar.h" + +#ifdef CARRIER_DETECTION_SUPPORT +#include "cs.h" +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT +#include "dfs.h" +#endif /* DFS_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT +#include "rt_led.h" +#endif /* LED_CONTROL_SUPPORT */ + + +#ifdef RALINK_ATE +#include "rt_ate.h" +#endif /* RALINK_ATE */ + + +#ifdef CONFIG_DOT11U_INTERWORKING +#include "dot11u_interworking.h" +#include "gas.h" +#endif + +#ifdef CONFIG_DOT11V_WNM +#include "dot11v_wnm.h" +#include "wnm.h" +#endif + +#ifdef CONFIG_HOTSPOT +#include "hotspot.h" +#endif + +#ifdef CONFIG_SNIFFER_SUPPORT +#include "sniffer/sniffer.h" +#endif + + +#ifdef REDUCE_TCP_ACK_SUPPORT +#include "reduce_tcpack.h" +#endif /* REDUCE_TCP_ACK_SUPPORT */ + +#ifdef ROUTING_TAB_SUPPORT +#include "routing_tab.h" +#endif /* ROUTING_TAB_SUPPORT */ + +#ifdef MWDS +#include "mwds.h" +#endif /* MWDS */ + +// TODO: shiang-6590, remove it after ATE fully re-organized! copy from rtmp_bbp.h +#ifndef MAX_BBP_ID +#ifdef RTMP_RBUS_SUPPORT +/* TODO: for this definition, need to modify it!! */ + /*#define MAX_BBP_ID 255 */ + #define MAX_BBP_ID 200 + +#else + #define MAX_BBP_ID 136 + +#endif /* RTMP_RBUS_SUPPORT */ + + +#if defined(RT5572) || defined(RT6352) +#undef MAX_BBP_ID +#define MAX_BBP_ID 248 +#undef MAX_BBP_MSG_SIZE +#define MAX_BBP_MSG_SIZE 4096 +#endif /* defined(RT5572) || defined(RT6352) */ +#endif +// TODO: ---End + + +/*#define DBG 1 */ + +/*#define DBG_DIAGNOSE 1 */ + + +/*+++Used for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ +#define MAX_DATAMM_RETRY 3 +#define MGMT_USE_QUEUE_FLAG 0x80 +#define MGMT_USE_PS_FLAG 0x40 +/*---Used for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ +/* The number of channels for per-channel Tx power offset */ +#ifdef CUSTOMER_DCC_FEATURE +#define MOV_AVG_CONST 8 +#define MOV_AVG_CONST_SHIFT 3 +#define CHANNEL_SWITCHING_MODE 1 +#define NORMAL_MODE 0 +typedef struct _MultiplicationShiftFactor{ +UINT64 Multiplication; +UINT64 Shift; +}MultiplicationShiftFactor, *PMultiplicationShiftFactor ; + +extern MultiplicationShiftFactor RateMultiplicationShiftFactor[224]; +#endif + +#define MAXSEQ (0xFFF) + +#ifdef DOT11N_SS3_SUPPORT +#define MAX_MCS_SET 24 /* From MCS 0 ~ MCS 23 */ +#else +#ifdef DOT11_VHT_AC +#define MAX_MCS_SET 20 /* for 1SS~2SS with MCS0~9 */ +#else +#define MAX_MCS_SET 16 /* From MCS 0 ~ MCS 15 */ +#endif /* DOT11_VHT_AC */ +#endif /* DOT11N_SS3_SUPPORT */ +#define MAX_VHT_MCS_SET 20 /* for 1ss~ 2ss with MCS0~9 */ +#define MAX_FAST_MCS_SET 33 + + +#define MAX_TXPOWER_ARRAY_SIZE 5 + +#define MAX_EEPROM_BUFFER_SIZE 1024 + +extern unsigned char CISCO_OUI[]; +extern UCHAR BaSizeArray[4]; + +extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; +extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; +extern char *CipherName[]; +extern UCHAR SNAP_802_1H[6]; +extern UCHAR SNAP_BRIDGE_TUNNEL[6]; +extern UCHAR EAPOL[2]; +extern UCHAR IPX[2]; +extern UCHAR TPID[]; +extern UCHAR APPLE_TALK[2]; +#ifdef DOT11Z_TDLS_SUPPORT +extern UCHAR TDLS_LLC_SNAP_WITH_CATEGORY[10]; +#ifdef WFD_SUPPORT +extern UCHAR TDLS_LLC_SNAP_WITH_WFD_CATEGORY[10]; +#endif /* WFD_SUPPORT */ +extern UCHAR TDLS_ETHERTYPE[2]; +#endif /* DOT11Z_TDLS_SUPPORT */ +extern UCHAR OfdmRateToRxwiMCS[]; +extern UCHAR WMM_UP2AC_MAP[8]; + +extern unsigned char RateIdToMbps[]; +extern USHORT RateIdTo500Kbps[]; + +extern UCHAR CipherSuiteWpaNoneTkip[]; +extern UCHAR CipherSuiteWpaNoneTkipLen; + +extern UCHAR CipherSuiteWpaNoneAes[]; +extern UCHAR CipherSuiteWpaNoneAesLen; + +extern UCHAR SsidIe; +extern UCHAR SupRateIe; +extern UCHAR ExtRateIe; + +#ifdef DOT11_N_SUPPORT +extern UCHAR HtCapIe; +extern UCHAR AddHtInfoIe; +extern UCHAR NewExtChanIe; +extern UCHAR BssCoexistIe; +extern UCHAR ExtHtCapIe; +#endif /* DOT11_N_SUPPORT */ +extern UCHAR ExtCapIe; + +extern UCHAR ErpIe; +extern UCHAR DsIe; +extern UCHAR TimIe; +extern UCHAR WpaIe; +extern UCHAR Wpa2Ie; +extern UCHAR IbssIe; +extern UCHAR WapiIe; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WAPI_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR MTK_OUI[]; +extern UCHAR PowerConstraintIE[]; + +struct _RX_BLK; + +typedef union _CAPTURE_MODE_PACKET_BUFFER { + struct + { + UINT32 BYTE0:8; + UINT32 BYTE1:8; + UINT32 BYTE2:8; + UINT32 BYTE3:8; + } field; + UINT32 Value; +}CAPTURE_MODE_PACKET_BUFFER, *PCAPTURE_MODE_PACKET_BUFFER; + +typedef struct _RSSI_SAMPLE { + CHAR LastRssi0; /* last received RSSI */ + CHAR LastRssi1; /* last received RSSI */ + CHAR LastRssi2; /* last received RSSI */ + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + SHORT AvgRssi0X8; + SHORT AvgRssi1X8; + SHORT AvgRssi2X8; + CHAR LastSnr0; + CHAR LastSnr1; + CHAR LastSnr2; + CHAR AvgSnr0; + CHAR AvgSnr1; + CHAR AvgSnr2; + SHORT AvgSnr0X8; + SHORT AvgSnr1X8; + SHORT AvgSnr2X8; + CHAR LastNoiseLevel0; + CHAR LastNoiseLevel1; + CHAR LastNoiseLevel2; +} RSSI_SAMPLE; + +#ifdef SMART_MESH_MONITOR +typedef struct _MNT_STA_ENTRY { + BOOLEAN bValid; + ULONG Count; + UCHAR addr[MAC_ADDR_LEN]; + RSSI_SAMPLE RssiSample; + VOID *pMacEntry; +} MNT_STA_ENTRY, *PMNT_STA_ENTRY; +#endif /* SMART_MESH_MONITOR */ + +struct raw_rssi_info; + +struct rx_signal_info{ + CHAR raw_rssi[3]; + UCHAR raw_snr[3]; + CHAR freq_offset; +}; + + +/* + Queue structure and macros +*/ +#define InitializeQueueHeader(QueueHeader) \ +{ \ + (QueueHeader)->Head = (QueueHeader)->Tail = NULL; \ + (QueueHeader)->Number = 0; \ +} + +#define RemoveHeadQueue(QueueHeader) \ +(QueueHeader)->Head; \ +{ \ + PQUEUE_ENTRY pNext; \ + if ((QueueHeader)->Head != NULL) \ + { \ + pNext = (QueueHeader)->Head->Next; \ + (QueueHeader)->Head->Next = NULL; \ + (QueueHeader)->Head = pNext; \ + if (pNext == NULL) \ + (QueueHeader)->Tail = NULL; \ + (QueueHeader)->Number--; \ + } \ +} + +#define InsertHeadQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + if ((QueueHeader)->Tail == NULL) \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +#define InsertTailQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + else \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +#define InsertTailQueueAc(pAd, pEntry, QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + else \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + + +/* */ +/* Macros for flag and ref count operations */ +/* */ +#define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) +#define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) +#define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) +#define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) +#define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) +/* Macro for power save flag. */ +#define RTMP_SET_PSFLAG(_M, _F) ((_M)->PSFlags |= (_F)) +#define RTMP_CLEAR_PSFLAG(_M, _F) ((_M)->PSFlags &= ~(_F)) +#define RTMP_CLEAR_PSFLAGS(_M) ((_M)->PSFlags = 0) +#define RTMP_TEST_PSFLAG(_M, _F) (((_M)->PSFlags & (_F)) != 0) +#define RTMP_TEST_PSFLAGS(_M, _F) (((_M)->PSFlags & (_F)) == (_F)) + +#define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) +#define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) +#define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0) + +#define WIFI_TEST_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.WiFiTestFlags |= (_F)) +#define WIFI_TEST_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.WiFiTestFlags &= ~(_F)) +#define WIFI_TEST_CHECK_FLAG(_pAd, _F) (((_pAd)->CommonCfg.WiFiTestFlags & (_F)) != 0) + +#define CLIENT_STATUS_SET_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags |= (_F)) +#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags &= ~(_F)) +#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F) (((_pEntry)->ClientStatusFlags & (_F)) != 0) + +#define RX_FILTER_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter |= (_F)) +#define RX_FILTER_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter &= ~(_F)) +#define RX_FILTER_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0) + +#define RTMP_SET_MORE_FLAG(_M, _F) ((_M)->MoreFlags |= (_F)) +#define RTMP_TEST_MORE_FLAG(_M, _F) (((_M)->MoreFlags & (_F)) != 0) +#define RTMP_CLEAR_MORE_FLAG(_M, _F) ((_M)->MoreFlags &= ~(_F)) + +#define SET_ASIC_CAP(_pAd, _caps) ((_pAd)->chipCap.asic_caps |= (_caps)) +#define IS_ASIC_CAP(_pAd, _caps) (((_pAd)->chipCap.asic_caps & (_caps)) != 0) +#define CLR_ASIC_CAP(_pAd, _caps) ((_pAd)->chipCap.asic_caps &= ~(_caps)) + + +#ifdef CONFIG_STA_SUPPORT +#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11EncryptionDisabled) +#define STA_WEP_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11WEPEnabled) +#define STA_TKIP_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11TKIPEnable) +#define STA_AES_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) + +#define STA_TGN_WIFI_ON(_p) (_p->StaCfg.bTGnWifiTest == TRUE) +#endif /* CONFIG_STA_SUPPORT */ + +#define CKIP_KP_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) +#define CKIP_CMIC_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +#ifdef USB_BULK_BUF_ALIGMENT +#define CUR_WRITE_IDX_INC(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} +#endif /* USB_BULK_BUF_ALIGMENT */ + +#ifdef DOT11_N_SUPPORT +/* StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. */ +#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \ + _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs; \ + _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40; \ + _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC; \ + _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC; \ + _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset; \ + _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \ + _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \ + _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \ + NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\ +} + +#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \ +{ \ + _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \ + _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \ + _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ +} +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC +#define COPY_VHT_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ +} +#endif /* DOT11_VHT_AC */ + + +/* + Common fragment list structure - Identical to the scatter gather frag list structure +*/ +#define NIC_MAX_PHYS_BUF_COUNT 8 + +typedef struct _RTMP_SCATTER_GATHER_ELEMENT { + PVOID Address; + ULONG Length; + PULONG Reserved; +} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT; + +typedef struct _RTMP_SCATTER_GATHER_LIST { + ULONG NumberOfElements; + PULONG Reserved; + RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT]; +} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST; + + +/* + Some utility macros +*/ +#ifndef min +#define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif + +#ifndef max +#define max(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) +#endif + +#define GET_LNA_GAIN(_pAd) ((_pAd->LatchRfRegs.Channel <= 14) ? (_pAd->BLNAGain) : ((_pAd->LatchRfRegs.Channel <= 64) ? (_pAd->ALNAGain0) : ((_pAd->LatchRfRegs.Channel <= 128) ? (_pAd->ALNAGain1) : (_pAd->ALNAGain2)))) + +#define INC_COUNTER64(Val) (Val.QuadPart++) + +#define INFRA_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_INFRA_ON)) +#define ADHOC_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_ADHOC_ON)) +#ifdef CONFIG_STA_SUPPORT +#define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR) +#else +#define MONITOR_ON(_p) (((_p)->ApCfg.BssType) == BSS_MONITOR) +#endif + +#define IDLE_ON(_p) (!INFRA_ON(_p) && !ADHOC_ON(_p)) + +/* Check LEAP & CCKM flags */ +#define LEAP_ON(_p) (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) +#define LEAP_CCKM_ON(_p) ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE)) + +/* if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required */ +#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap) \ +{ \ + if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500) \ + { \ + _pExtraLlcSnapEncap = SNAP_802_1H; \ + if (NdisEqualMemory(IPX, _pBufVA + 12, 2) || \ + NdisEqualMemory(APPLE_TALK, _pBufVA + 12, 2)) \ + { \ + _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ + } \ + } \ + else \ + { \ + _pExtraLlcSnapEncap = NULL; \ + } \ +} + +/* New Define for new Tx Path. */ +#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap) \ +{ \ + if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500) \ + { \ + _pExtraLlcSnapEncap = SNAP_802_1H; \ + if (NdisEqualMemory(IPX, _pBufVA, 2) || \ + NdisEqualMemory(APPLE_TALK, _pBufVA, 2)) \ + { \ + _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ + } \ + } \ + else \ + { \ + _pExtraLlcSnapEncap = NULL; \ + } \ +} + +#define MAKE_802_3_HEADER(_buf, _pMac1, _pMac2, _pType) \ +{ \ + NdisMoveMemory(_buf, _pMac1, MAC_ADDR_LEN); \ + NdisMoveMemory((_buf + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \ + NdisMoveMemory((_buf + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \ +} + +/* + if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), + keep it that way. + else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, + preserve the LLC/SNAP field + else remove the LLC/SNAP field from the result Ethernet frame + + Patch for WHQL only, which did not turn on Netbios but use IPX within its payload + Note: + _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO + _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed +*/ +#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \ +{ \ + char LLC_Len[2]; \ + \ + _pRemovedLLCSNAP = NULL; \ + if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \ + { \ + PUCHAR pProto = _pData + 6; \ + \ + if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \ + NdisEqualMemory(SNAP_802_1H, _pData, 6)) \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize >> 8); \ + LLC_Len[1] = (UCHAR)(_DataSize & (256 - 1)); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ + else \ + { \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto); \ + _pRemovedLLCSNAP = _pData; \ + _DataSize -= LENGTH_802_1_H; \ + _pData += LENGTH_802_1_H; \ + } \ + } \ + else \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize >> 8); \ + LLC_Len[1] = (UCHAR)(_DataSize & (256 - 1)); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ +} + +/* + Enqueue this frame to MLME engine + We need to enqueue the whole frame because MLME need to pass data type + information from 802.11 header +*/ +#ifdef RTMP_MAC_PCI +#ifndef CUSTOMER_DCC_FEATURE +#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _MinSNR, _OpMode) \ +{ \ + UINT32 High32TSF, Low32TSF; \ + RTMP_IO_READ32(_pAd, TSF_TIMER_DW1, &High32TSF); \ + RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \ + MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_MinSNR, _OpMode); \ +} +#else +#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _Snr0, _Snr1, _MinSNR, _OpMode) \ +{ \ + UINT32 High32TSF, Low32TSF; \ + RTMP_IO_READ32(_pAd, TSF_TIMER_DW1, &High32TSF); \ + RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \ + MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2, (UCHAR)_Snr0, (UCHAR)_Snr1, _FrameSize, _pFrame, (UCHAR)_MinSNR, _OpMode); \ +} +#endif +#endif /* RTMP_MAC_PCI */ + +#define IPV4_ADDR_EQUAL(pAddr1, pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), 4) +#define IPV6_ADDR_EQUAL(pAddr1, pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), 16) +#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN) +#define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1))) + + +#ifdef CONFIG_STA_SUPPORT +#define STA_EXTRA_SETTING(_pAd) +#ifdef DOT11R_FT_SUPPORT +#undef STA_EXTRA_SETTING +#define STA_EXTRA_SETTING(_pAd) \ +{ \ + if ((_pAd)->StaCfg.Dot11RCommInfo.bFtSupport && \ + (_pAd)->MlmeAux.MdIeInfo.Len && \ + (_pAd)->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) \ + (_pAd)->StaCfg.Dot11RCommInfo.bInMobilityDomain = TRUE; \ +} +#endif /* DOT11R_FT_SUPPORT */ + +#define STA_PORT_SECURED(_pAd) \ +{ \ + BOOLEAN Cancelled; \ + (_pAd)->StaCfg.wdev.PortSecured = WPA_802_1X_PORT_SECURED; \ + RTMP_IndicateMediaState(_pAd, NdisMediaStateConnected); \ + NdisAcquireSpinLock(&((_pAd)->MacTabLock)); \ + (_pAd)->MacTab.Content[BSSID_WCID].PortSecured = (_pAd)->StaCfg.wdev.PortSecured; \ + (_pAd)->MacTab.Content[BSSID_WCID].PrivacyFilter = Ndis802_11PrivFilterAcceptAll;\ + NdisReleaseSpinLock(&(_pAd)->MacTabLock); \ + RTMPCancelTimer(&((_pAd)->Mlme.LinkDownTimer), &Cancelled);\ + STA_EXTRA_SETTING(_pAd); \ +} +#endif /* CONFIG_STA_SUPPORT */ + +/* + Data buffer for DMA operation, the buffer must be contiguous physical memory + Both DMA to / from CPU use the same structure. +*/ +typedef struct _RTMP_DMABUF { + ULONG AllocSize; + PVOID AllocVa; /* TxBuf virtual address */ + NDIS_PHYSICAL_ADDRESS AllocPa; /* TxBuf physical address */ +} RTMP_DMABUF, *PRTMP_DMABUF; + + +/* + Control block (Descriptor) for all ring descriptor DMA operation, buffer must be + contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor + which won't be released, driver has to wait until upper layer return the packet + before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair + to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor + which driver should ACK upper layer when the tx is physically done or failed. +*/ +typedef struct _RTMP_DMACB { + ULONG AllocSize; /* Control block size */ + PVOID AllocVa; /* Control block virtual address */ + NDIS_PHYSICAL_ADDRESS AllocPa; /* Control block physical address */ + PNDIS_PACKET pNdisPacket; + PNDIS_PACKET pNextNdisPacket; + + RTMP_DMABUF DmaBuf; /* Associated DMA buffer structure */ +#ifdef CACHE_LINE_32B + RXD_STRUC LastBDInfo; +#endif /* CACHE_LINE_32B */ +} RTMP_DMACB, *PRTMP_DMACB; + +typedef struct _RTMP_TX_RING { + RTMP_DMACB Cell[TX_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_TX_RING; + +typedef struct _RTMP_RX_RING { + RTMP_DMACB Cell[RX_RING_SIZE]; + UINT32 RxCpuIdx; + UINT32 RxDmaIdx; + INT32 RxSwReadIdx; /* software next read index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_RX_RING; + +typedef struct _RTMP_MGMT_RING { + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_MGMT_RING, *PRTMP_MGMT_RING; + +typedef struct _RTMP_CTRL_RING { + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_CTRL_RING, *PRTMP_CTRL_RING; + +/* + Statistic counter structure +*/ +typedef struct _COUNTER_802_3 { + /* General Stats */ + ULONG GoodTransmits; + ULONG GoodReceives; + ULONG TxErrors; + ULONG RxErrors; + ULONG RxNoBuffer; +} COUNTER_802_3, *PCOUNTER_802_3; + +typedef struct _COUNTER_802_11 { + ULONG Length; +/* LARGE_INTEGER LastTransmittedFragmentCount; */ + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; + LARGE_INTEGER TransmittedFrameCount; + LARGE_INTEGER WEPUndecryptableCount; + LARGE_INTEGER TransmitCountFrmOs; +} COUNTER_802_11, *PCOUNTER_802_11; + + + +typedef struct _COUNTER_RALINK { + UINT32 OneSecStart; /* for one sec count clear use */ + UINT32 OneSecBeaconSentCnt; + UINT32 OneSecFalseCCACnt; /* CCA error count, for debug purpose, might move to global counter */ + UINT32 OneSecRxFcsErrCnt; /* CRC error */ + UINT32 OneSecRxOkCnt; /* RX without error */ + UINT32 OneSecTxFailCount; + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecRxOkDataCnt; /* unicast-to-me DATA frame count */ + UINT32 OneSecTransmittedByteCount; /* both successful and failure, used to calculate TX throughput */ + + ULONG OneSecOsTxCount[NUM_OF_TX_RING]; + ULONG OneSecDmaDoneCount[NUM_OF_TX_RING]; + UINT32 OneSecTxDoneCount; + ULONG OneSecRxCount; + UINT32 OneSecReceivedByteCount; + UINT32 OneSecTxAggregationCount; + UINT32 OneSecRxAggregationCount; + UINT32 OneSecEnd; /* for one sec count clear use */ + + ULONG TransmittedByteCount; /* both successful and failure, used to calculate TX throughput */ + ULONG ReceivedByteCount; /* both CRC okay and CRC error, used to calculate RX throughput */ + ULONG BadCQIAutoRecoveryCount; + ULONG PoorCQIRoamingCount; + ULONG MgmtRingFullCount; + ULONG RxCountSinceLastNULL; + ULONG RxCount; + ULONG KickTxCount; + LARGE_INTEGER RealFcsErrCount; + ULONG PendingNdisPacketCount; + ULONG FalseCCACnt; /* CCA error count */ + + UINT32 LastOneSecTotalTxCount; /* OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount */ + UINT32 LastOneSecRxOkDataCnt; /* OneSecRxOkDataCnt */ + ULONG DuplicateRcv; + ULONG TxAggCount; + ULONG TxNonAggCount; + ULONG TxAgg1MPDUCount; + ULONG TxAgg2MPDUCount; + ULONG TxAgg3MPDUCount; + ULONG TxAgg4MPDUCount; + ULONG TxAgg5MPDUCount; + ULONG TxAgg6MPDUCount; + ULONG TxAgg7MPDUCount; + ULONG TxAgg8MPDUCount; + ULONG TxAgg9MPDUCount; + ULONG TxAgg10MPDUCount; + ULONG TxAgg11MPDUCount; + ULONG TxAgg12MPDUCount; + ULONG TxAgg13MPDUCount; + ULONG TxAgg14MPDUCount; + ULONG TxAgg15MPDUCount; + ULONG TxAgg16MPDUCount; + + LARGE_INTEGER TransmittedOctetsInAMSDU; + LARGE_INTEGER TransmittedAMSDUCount; + LARGE_INTEGER ReceivedOctesInAMSDUCount; + LARGE_INTEGER ReceivedAMSDUCount; + LARGE_INTEGER TransmittedAMPDUCount; + LARGE_INTEGER TransmittedMPDUsInAMPDUCount; + LARGE_INTEGER TransmittedOctetsInAMPDUCount; + LARGE_INTEGER MPDUInReceivedAMPDUCount; + + ULONG PhyErrCnt; + ULONG PlcpErrCnt; +} COUNTER_RALINK, *PCOUNTER_RALINK; + +#ifdef SMART_MESH +typedef struct _COUNTER_TIME { + UINT32 EdBusyTime; + UINT32 ChBusyTime; + UINT32 ChIdleTime; +} COUNTER_TIME, *PCOUNTER_TIME; +#endif /* SMART_MESH */ + +typedef struct _COUNTER_DRS { + /* to record the each TX rate's quality. 0 is best, the bigger the worse. */ + USHORT TxQuality[MAX_TX_RATE_INDEX+1]; + UCHAR PER[MAX_TX_RATE_INDEX+1]; + UCHAR TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ + ULONG CurrTxRateStableTime; /* # of second in current TX rate */ + /*BOOLEAN fNoisyEnvironment; */ + BOOLEAN fLastSecAccordingRSSI; + UCHAR LastSecTxRateChangeAction; /* 0: no change, 1:rate UP, 2:rate down */ + UCHAR LastTimeTxRateChangeAction; /*Keep last time value of LastSecTxRateChangeAction */ + ULONG LastTxOkCount; +} COUNTER_DRS, *PCOUNTER_DRS; + + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT +typedef struct _COUNTER_TXBF{ + ULONG TxSuccessCount; + ULONG TxRetryCount; + ULONG TxFailCount; + ULONG ETxSuccessCount; + ULONG ETxRetryCount; + ULONG ETxFailCount; + ULONG ITxSuccessCount; + ULONG ITxRetryCount; + ULONG ITxFailCount; +} COUNTER_TXBF; +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + +#ifdef STREAM_MODE_SUPPORT +typedef struct _STREAM_MODE_ENTRY_{ +#define STREAM_MODE_STATIC 1 + USHORT flag; + UCHAR macAddr[MAC_ADDR_LEN]; +}STREAM_MODE_ENTRY; +#endif /* STREAM_MODE_SUPPORT */ + +/* for Microwave oven */ +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) +typedef struct _MO_CFG_STRUCT { + BOOLEAN bEnable; + UINT8 nPeriod_Cnt; /* measurement period 100ms, mitigate the interference period 900 ms */ + UINT16 nFalseCCACnt; + UINT16 nFalseCCATh; /* default is 100 */ +#ifdef RT6352 + UCHAR Stored_BBP_R65; + UCHAR Stored_RF_B5_R6; + UCHAR Stored_RF_B5_R7; + UCHAR Stored_RF_B7_R6; + UCHAR Stored_RF_B7_R7; +#endif /* RT6352 */ +} MO_CFG_STRUCT, *PMO_CFG_STRUCT; +#endif /* MICROWAVE_OVEN_SUPPORT || DYNAMIC_VGA_SUPPORT */ + +/* TODO: need to integrate with MICROWAVE_OVEN_SUPPORT */ +#ifdef DYNAMIC_VGA_SUPPORT +/* for dynamic vga */ +typedef struct _LNA_VGA_CTL_STRUCT { + BOOLEAN bEnable; + BOOLEAN bDyncVgaEnable; + UINT8 long_range_compensate_level; + UINT8 nPeriod_Cnt; /* measurement period 100ms, mitigate the interference period 900 ms */ + UINT16 nFalseCCACnt; + UINT16 nFalseCCATh; /* default is 100 */ + UINT16 nLowFalseCCATh; + UINT32 agc1_r8_backup; + UCHAR agc_vga_init_0; + UCHAR agc_vga_ori_0; /* the original vga gain initialized by firmware at start up */ + UINT16 agc_0_vga_set1_2; + UINT32 agc1_r9_backup; + UCHAR agc_vga_init_1; + UCHAR agc_vga_ori_1; /* the original vga gain initialized by firmware at start up */ + UINT16 agc_1_vga_set1_2; +} LNA_VGA_CTL_STRUCT, *PLNA_VGA_CTL_STRUCT; +#endif /* DYNAMIC_VGA_SUPPORT */ + +/*************************************************************************** + * security key related data structure + **************************************************************************/ + +/* structure to define WPA Group Key Rekey Interval */ +typedef struct GNU_PACKED _RT_802_11_WPA_REKEY { + ULONG ReKeyMethod; /* mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based */ + ULONG ReKeyInterval; /* time-based: seconds, packet-based: kilo-packets */ +} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY; + + + +typedef struct { + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR ErrorCode[2]; /*00 01-Invalid authentication type */ + /*00 02-Authentication timeout */ + /*00 03-Challenge from AP failed */ + /*00 04-Challenge to AP failed */ + BOOLEAN Reported; +} ROGUEAP_ENTRY, *PROGUEAP_ENTRY; + +typedef struct { + UCHAR RogueApNr; + ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE]; +} ROGUEAP_TABLE, *PROGUEAP_TABLE; + +/* + * Fragment Frame structure + */ +typedef struct _FRAGMENT_FRAME { + PNDIS_PACKET pFragPacket; + ULONG RxSize; + USHORT Sequence; + USHORT LastFrag; + ULONG Flags; /* Some extra frame information. bit 0: LLC presented */ +} FRAGMENT_FRAME, *PFRAGMENT_FRAME; + + +/* + Tkip Key structure which RC4 key & MIC calculation +*/ +typedef struct _TKIP_KEY_INFO { + UINT nBytesInM; /* # bytes in M for MICKEY */ + ULONG IV16; + ULONG IV32; + ULONG K0; /* for MICKEY Low */ + ULONG K1; /* for MICKEY Hig */ + ULONG L; /* Current state for MICKEY */ + ULONG R; /* Current state for MICKEY */ + ULONG M; /* Message accumulator for MICKEY */ + UCHAR RC4KEY[16]; + UCHAR MIC[8]; +} TKIP_KEY_INFO, *PTKIP_KEY_INFO; + + +/* + Private / Misc data, counters for driver internal use +*/ +typedef struct __PRIVATE_STRUC { + UINT SystemResetCnt; /* System reset counter */ + /* Tx ring full occurrance number */ + UINT TxRingFullCnt; + UINT PhyRxErrCnt; /* PHY Rx error count, for debug purpose, might move to global counter */ + /* Variables for WEP encryption / decryption in rtmp_wep.c */ + /* Tkip stuff */ + TKIP_KEY_INFO Tx; + TKIP_KEY_INFO Rx; +} PRIVATE_STRUC, *PPRIVATE_STRUC; + + +/*************************************************************************** + * Channel and BBP related data structures + **************************************************************************/ +/* structure to tune BBP R66 (BBP TUNING) */ +typedef struct _BBP_R66_TUNING { + BOOLEAN bEnable; + USHORT FalseCcaLowerThreshold; /* default 100 */ + USHORT FalseCcaUpperThreshold; /* default 512 */ + UCHAR R66Delta; + UCHAR R66CurrentValue; + BOOLEAN R66LowerUpperSelect; /*Before LinkUp, Used LowerBound or UpperBound as R66 value. */ +} BBP_R66_TUNING, *PBBP_R66_TUNING; + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +#define EFFECTED_CH_SECONDARY 0x1 +#define EFFECTED_CH_PRIMARY 0x2 +#define EFFECTED_CH_LEGACY 0x4 +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +/* structure to store channel TX power */ +typedef struct _CHANNEL_TX_POWER { + USHORT RemainingTimeForUse; /*unit: sec */ + UCHAR Channel; +#ifdef DOT11N_DRAFT3 + BOOLEAN bEffectedChannel; /* For BW 40 operating in 2.4GHz , the "effected channel" is the channel that is covered in 40Mhz. */ +#endif /* DOT11N_DRAFT3 */ + CHAR Power; + CHAR Power2; +#ifdef DOT11N_SS3_SUPPORT + CHAR Power3; +#endif /* DOT11N_SS3_SUPPORT */ + UCHAR MaxTxPwr; + UCHAR DfsReq; + UCHAR RegulatoryDomain; +#ifdef SMART_MESH + BOOLEAN bDfsAPExist; + ULONG FalseCCA; +#endif /* SMART_MESH */ + +/* + Channel property: + + CHANNEL_DISABLED: The channel is disabled. + CHANNEL_PASSIVE_SCAN: Only passive scanning is allowed. + CHANNEL_NO_IBSS: IBSS is not allowed. + CHANNEL_RADAR: Radar detection is required. + CHANNEL_NO_FAT_ABOVE: Extension channel above this channel is not allowed. + CHANNEL_NO_FAT_BELOW: Extension channel below this channel is not allowed. + CHANNEL_40M_CAP: 40 BW channel group + CHANNEL_80M_CAP: 800 BW channel group + */ +#define CHANNEL_DEFAULT_PROP 0x00 +#define CHANNEL_DISABLED 0x01 /* no use */ +#define CHANNEL_PASSIVE_SCAN 0x02 +#define CHANNEL_NO_IBSS 0x04 +#define CHANNEL_RADAR 0x08 +#define CHANNEL_NO_FAT_ABOVE 0x10 +#define CHANNEL_NO_FAT_BELOW 0x20 +#define CHANNEL_40M_CAP 0x40 +#define CHANNEL_80M_CAP 0x80 + + UCHAR Flags; + +} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER; + +/* Channel list subset */ +typedef struct _CHANNEL_LIST_SUB { + UCHAR Channel; + UCHAR IdxMap; /* Index mapping to original channel list */ +} CHANNEL_LIST_SUB, *PCHANNEL_LIST_SUB; + + +typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT { + UCHAR EvaluatePeriod; /* 0:not evalute status, 1: evaluate status, 2: switching status */ + UCHAR EvaluateStableCnt; + UCHAR Pair1PrimaryRxAnt; /* 0:Ant-E1, 1:Ant-E2 */ + UCHAR Pair1SecondaryRxAnt; /* 0:Ant-E1, 1:Ant-E2 */ +#ifdef CONFIG_STA_SUPPORT + SHORT Pair1AvgRssi[2]; /* AvgRssi[0]:E1, AvgRssi[1]:E2 */ + SHORT Pair2AvgRssi[2]; /* AvgRssi[0]:E3, AvgRssi[1]:E4 */ +#endif /* CONFIG_STA_SUPPORT */ + SHORT Pair1LastAvgRssi; /* */ + SHORT Pair2LastAvgRssi; /* */ + ULONG RcvPktNumWhenEvaluate; + BOOLEAN FirstPktArrivedWhenEvaluate; +#ifdef CONFIG_AP_SUPPORT + LONG Pair1AvgRssiGroup1[2]; + LONG Pair1AvgRssiGroup2[2]; + ULONG RcvPktNum[2]; +#endif /* CONFIG_AP_SUPPORT */ +} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY; + +typedef enum _ABGBAND_STATE_ { + UNKNOWN_BAND, + BG_BAND, + A_BAND, +} ABGBAND_STATE; + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI +/* Power save method control */ +typedef union _PS_CONTROL { + struct { + ULONG EnablePSinIdle:1; /* Enable radio off when not connect to AP. radio on only when sitesurvey, */ + ULONG EnableNewPS:1; /* Enable new Chip power save fucntion . New method can only be applied in chip version after 2872. and PCIe. */ + ULONG rt30xxPowerMode:2; /* Power Level Mode for rt30xx chip */ + ULONG rt30xxFollowHostASPM:1; /* Card Follows Host's setting for rt30xx chip. */ + ULONG rt30xxForceASPMTest:1; /* Force enable L1 for rt30xx chip. This has higher priority than rt30xxFollowHostASPM Mode. */ +/* ULONG rsv:26; // Radio Measurement Enable */ + ULONG AMDNewPSOn:1; /* Enable for AMD L1 (toggle) */ + ULONG LedMode:2; /* 0: Blink normal. 1: Slow blink not normal. */ + ULONG rt30xxForceL0:1; /* Force only use L0 for rt30xx */ + + /* PCIe config space [Completion TimeOut Disable], compatible issue with Intel HM55 */ + ULONG CTO:1; /* 0: default, update the CTO bit to disable; 1: Keep BIOS config value */ + ULONG PM4PCIeCLKOn:1; /* 0: default, turn off PCIE CLk at PM4; 1: FW MCU cmd arg1 as "0x5a" which will not turn off PCIE CLK */ + + ULONG rsv:20; /* Rsvd */ + } field; + ULONG word; +} PS_CONTROL, *PPS_CONTROL; +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_STA_SUPPORT */ +/*************************************************************************** + * structure for MLME state machine + **************************************************************************/ +typedef struct _MLME_STRUCT { +#ifdef CONFIG_STA_SUPPORT + /* STA state machines */ + STATE_MACHINE CntlMachine; + STATE_MACHINE AssocMachine; + STATE_MACHINE AuthMachine; + STATE_MACHINE AuthRspMachine; + STATE_MACHINE SyncMachine; + STATE_MACHINE WpaPskMachine; + STATE_MACHINE LeapMachine; + STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE]; + STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE]; +#ifdef DOT11R_FT_SUPPORT + STATE_MACHINE FtOtaAuthMachine; + STATE_MACHINE_FUNC FtOtaAuthFunc[FT_OTA_AUTH_FUNC_SIZE]; + STATE_MACHINE FtOtdActMachine; + STATE_MACHINE_FUNC FtOtdActFunc[FT_OTD_FUNC_SIZE]; +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* CONFIG_STA_SUPPORT */ + STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; + /* Action */ + STATE_MACHINE ActMachine; + +#ifdef WSC_INCLUDED + STATE_MACHINE WscMachine; + STATE_MACHINE_FUNC WscFunc[WSC_FUNC_SIZE]; + +#ifdef IWSC_SUPPORT + STATE_MACHINE IWscMachine; + STATE_MACHINE_FUNC IWscFunc[IWSC_FUNC_SIZE]; +#endif /* IWSC_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef QOS_DLS_SUPPORT + STATE_MACHINE DlsMachine; + STATE_MACHINE_FUNC DlsFunc[DLS_FUNC_SIZE]; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + STATE_MACHINE TdlsMachine; + STATE_MACHINE_FUNC TdlsFunc[TDLS_FUNC_SIZE]; + STATE_MACHINE TdlsChSwMachine; + STATE_MACHINE_FUNC TdlsChSwFunc[TDLS_CHSW_FUNC_SIZE]; +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef CONFIG_HOTSPOT + STATE_MACHINE HSCtrlMachine; + STATE_MACHINE_FUNC HSCtrlFunc[GAS_FUNC_SIZE]; +#endif + +#ifdef CONFIG_DOT11U_INTERWORKING + STATE_MACHINE GASMachine; + STATE_MACHINE_FUNC GASFunc[GAS_FUNC_SIZE]; +#endif + +#ifdef CONFIG_DOT11V_WNM + STATE_MACHINE BTMMachine; + STATE_MACHINE_FUNC BTMFunc[BTM_FUNC_SIZE]; + STATE_MACHINE WNMNotifyMachine; + STATE_MACHINE_FUNC WNMNotifyFunc[WNM_NOTIFY_FUNC_SIZE]; +#endif + +#ifdef CONFIG_AP_SUPPORT + /* AP state machines */ + STATE_MACHINE ApAssocMachine; + STATE_MACHINE ApAuthMachine; + STATE_MACHINE ApSyncMachine; + STATE_MACHINE_FUNC ApAssocFunc[AP_ASSOC_FUNC_SIZE]; +/* STATE_MACHINE_FUNC ApDlsFunc[DLS_FUNC_SIZE]; */ + STATE_MACHINE_FUNC ApAuthFunc[AP_AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC ApSyncFunc[AP_SYNC_FUNC_SIZE]; +#ifdef APCLI_SUPPORT + STATE_MACHINE ApCliAuthMachine; + STATE_MACHINE ApCliAssocMachine; + STATE_MACHINE ApCliCtrlMachine; + STATE_MACHINE ApCliSyncMachine; + STATE_MACHINE ApCliWpaPskMachine; + + STATE_MACHINE_FUNC ApCliAuthFunc[APCLI_AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC ApCliAssocFunc[APCLI_ASSOC_FUNC_SIZE]; + STATE_MACHINE_FUNC ApCliCtrlFunc[APCLI_CTRL_FUNC_SIZE]; + STATE_MACHINE_FUNC ApCliSyncFunc[APCLI_SYNC_FUNC_SIZE]; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* common WPA state machine */ + STATE_MACHINE WpaMachine; + STATE_MACHINE_FUNC WpaFunc[WPA_FUNC_SIZE]; + + + ULONG ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ + ULONG Now32; /* latch the value of NdisGetSystemUpTime() */ + ULONG LastSendNULLpsmTime; + + BOOLEAN bRunning; + NDIS_SPIN_LOCK TaskLock; + +#ifdef EAPOL_QUEUE_SUPPORT + EAP_MLME_QUEUE EAP_Queue; +#endif /* EAPOL_QUEUE_SUPPORT */ + + MLME_QUEUE Queue; + + UINT ShiftReg; + + RALINK_TIMER_STRUCT PeriodicTimer; + RALINK_TIMER_STRUCT APSDPeriodicTimer; + RALINK_TIMER_STRUCT LinkDownTimer; + RALINK_TIMER_STRUCT LinkUpTimer; + +#ifdef TXBF_SUPPORT + RALINK_TIMER_STRUCT SoundingTimer; +#endif + +#ifdef RTMP_MAC_PCI + UCHAR bPsPollTimerRunning; + RALINK_TIMER_STRUCT PsPollTimer; +#ifdef PCIE_PS_SUPPORT + RALINK_TIMER_STRUCT RadioOnOffTimer; +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + ULONG PeriodicRound; + ULONG GPIORound; + ULONG OneSecPeriodicRound; + + UCHAR RealRxPath; + BOOLEAN bLowThroughput; + BOOLEAN bEnableAutoAntennaCheck; + RALINK_TIMER_STRUCT RxAntEvalTimer; + + + +} MLME_STRUCT, *PMLME_STRUCT; + +#ifdef DOT11_N_SUPPORT +/*************************************************************************** + * 802.11 N related data structures + **************************************************************************/ +struct reordering_mpdu { + struct reordering_mpdu *next; + PNDIS_PACKET pPacket; /* coverted to 802.3 frame */ + int Sequence; /* sequence number of MPDU */ + BOOLEAN bAMSDU; + UCHAR OpMode; +}; + +struct reordering_list { + struct reordering_mpdu *next; + int qlen; +}; + +struct reordering_mpdu_pool { + PVOID mem; + NDIS_SPIN_LOCK lock; + struct reordering_list freelist; +}; + +typedef enum _REC_BLOCKACK_STATUS { + Recipient_NONE = 0, + Recipient_USED, + Recipient_HandleRes, + Recipient_Accept +} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS; + +typedef enum _ORI_BLOCKACK_STATUS { + Originator_NONE = 0, + Originator_USED, + Originator_WaitRes, + Originator_Done +} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; + +typedef struct _BA_ORI_ENTRY { + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; + UCHAR Token; + UCHAR amsdu_cap; +/* Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. */ + USHORT Sequence; + USHORT TimeOutValue; + ORI_BLOCKACK_STATUS ORI_BA_Status; + RALINK_TIMER_STRUCT ORIBATimer; + PVOID pAdapter; +} BA_ORI_ENTRY, *PBA_ORI_ENTRY; + +typedef struct _BA_REC_ENTRY { + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; /* 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. */ + /*UCHAR NumOfRxPkt; */ + /*UCHAR Curindidx; // the head in the RX reordering buffer */ + USHORT LastIndSeq; +/* USHORT LastIndSeqAtTimer; */ + USHORT TimeOutValue; + RALINK_TIMER_STRUCT RECBATimer; + ULONG LastIndSeqAtTimer; + ULONG nDropPacket; + ULONG rcvSeq; + REC_BLOCKACK_STATUS REC_BA_Status; +/* UCHAR RxBufIdxUsed; */ + /* corresponding virtual address for RX reordering packet storage. */ + /*RTMP_REORDERDMABUF MAP_RXBuf[MAX_RX_REORDERBUF]; */ + NDIS_SPIN_LOCK RxReRingLock; /* Rx Ring spinlock */ +/* struct _BA_REC_ENTRY *pNext; */ + PVOID pAdapter; + struct reordering_list list; +} BA_REC_ENTRY, *PBA_REC_ENTRY; + + +typedef struct { + ULONG numAsRecipient; /* I am recipient of numAsRecipient clients. These client are in the BARecEntry[] */ + ULONG numAsOriginator; /* I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] */ + ULONG numDoneOriginator; /* count Done Originator sessions */ + BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; + BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; +} BA_TABLE, *PBA_TABLE; + +/*For QureyBATableOID use; */ +typedef struct GNU_PACKED _OID_BA_REC_ENTRY { + UCHAR MACAddr[MAC_ADDR_LEN]; + UCHAR BaBitmap; /* if (BaBitmap&(1<MaxHTPhyMode.field.MODE == MODE_VHT) +#define IS_HT_STA(_pMacEntry) \ + (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) + +#define IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#ifdef DOT11_VHT_AC +#define IS_VHT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE == MODE_VHT) +#endif +#define PEER_IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#endif /* DOT11_N_SUPPORT */ + +/*This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second. (Details see MLMEPeriodic) */ +typedef struct _IOT_STRUC { + BOOLEAN bRTSLongProtOn; +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bLastAtheros; + //BOOLEAN bCurrentAtheros; + //BOOLEAN bNowAtherosBurstOn; + //BOOLEAN bNextDisableRxBA; + BOOLEAN bToggle; +#endif /* CONFIG_STA_SUPPORT */ +} IOT_STRUC; + +/* This is the registry setting for 802.11n transmit setting. Used in advanced page. */ +typedef union _REG_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + UINT32 rsv:13; + UINT32 EXTCHA:2; + UINT32 HTMODE:1; + UINT32 TRANSNO:2; + UINT32 STBC:1; /*SPACE */ + UINT32 ShortGI:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 TxBF:1; /* 3*3 */ + UINT32 ITxBfEn:1; + UINT32 rsv0:9; + /*UINT32 MCS:7; // MCS */ + /*UINT32 PhyMode:4; */ + } field; +#else + struct { + /*UINT32 PhyMode:4; */ + /*UINT32 MCS:7; // MCS */ + UINT32 rsv0:9; + UINT32 ITxBfEn:1; + UINT32 TxBF:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:1; /*SPACE */ + UINT32 TRANSNO:2; + UINT32 HTMODE:1; + UINT32 EXTCHA:2; + UINT32 rsv:13; + } field; +#endif + UINT32 word; +} REG_TRANSMIT_SETTING; + + +typedef union _DESIRED_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT rsv:2; + USHORT FixedTxMode:3; /* If MCS isn't AUTO, fix rate in CCK, OFDM, HT or VHT mode. */ + USHORT PhyMode:4; + USHORT MCS:7; /* MCS */ + } field; +#else + struct { + USHORT MCS:7; + USHORT PhyMode:4; + USHORT FixedTxMode:3; + USHORT rsv:2; + } field; +#endif + USHORT word; + } DESIRED_TRANSMIT_SETTING; + + +struct hw_setting{ + UCHAR prim_ch; + UCHAR cent_ch; + UINT8 bbp_bw; + UCHAR rf_band; + UCHAR cur_ch_pwr[3]; + CHAR lan_gain; +}; + + +#define WDEV_TYPE_AP 0x01 +#define WDEV_TYPE_STA 0x02 +#define WDEV_TYPE_ADHOC 0x04 +#define WDEV_TYPE_WDS 0x08 +#define WDEV_TYPE_MESH 0x10 + +#define WDEV_NUM_MAX 16 +struct wifi_dev{ + PNET_DEV if_dev; + VOID *func_dev; + VOID *sys_handle; + + CHAR wdev_idx; /* index refer from pAd->wdev_list[] */ + CHAR func_idx; /* index refer to func_dev which pointer to */ + UCHAR tr_tb_idx; /* index refer to BSS which this device belong */ + UCHAR wdev_type; + UCHAR PhyMode; + UCHAR channel; +#ifdef APCLI_AUTO_BW_SUPPORT + UCHAR bw; +#endif /* APCLI_AUTO_BW_SUPPORT */ + UCHAR if_addr[MAC_ADDR_LEN]; + UCHAR bssid[MAC_ADDR_LEN]; + + /* security segment */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + WPA_MIX_PAIR_CIPHER WpaMixPairCipher; + UCHAR DefaultKeyId; + UCHAR PortSecured; +#if defined(DOT1X_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) + BOOLEAN IEEE8021X; /* Only indicate if we are running in dynamic WEP mode (WEP+802.1x) */ +#endif /* DOT1X_SUPPORT */ + BOOLEAN bWpaAutoMode; + BOOLEAN bEncryptAutoMode; + + + /* transmit segment */ + BOOLEAN allow_data_tx; + BOOLEAN IgmpSnoopEnable; /* Only enabled for AP/WDS mode */ + RT_PHY_INFO DesiredHtPhyInfo; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; /* Desired transmit setting. this is for reading registry setting only. not useful. */ + BOOLEAN bAutoTxRateSwitch; + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + + /* 802.11 protocol related characters */ + BOOLEAN bWmmCapable; /* 0:disable WMM, 1:enable WMM */ + /* UAPSD information: such as enable or disable, do not remove */ + UAPSD_INFO UapsdInfo; + + + /* VLAN related */ + BOOLEAN bVLAN_Tag; + USHORT VLAN_VID; + USHORT VLAN_Priority; + + /* operations */ + INT (*tx_pkt_allowed)(struct _RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket, UCHAR *pWcid); + INT (*tx_pkt_handle)(struct _RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket); + INT (*rx_pkt_allowed)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT (*rx_pkt_hdr_chk)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT (*rx_ps_handle)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT (*rx_pkt_foward)(struct _RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket); + + /* last received packet's SNR for each antenna */ + UCHAR LastSNR0; + UCHAR LastSNR1; +#ifdef DOT11N_SS3_SUPPORT + UCHAR LastSNR2; + INT32 BF_SNR[3]; /* Last RXWI BF SNR. Units=0.25 dB */ +#endif /* DOT11N_SS3_SUPPORT */ + RSSI_SAMPLE RssiSample; + ULONG NumOfAvgRssiSample; +#if defined(RT_CFG80211_SUPPORT) || defined(HOSTAPD_SUPPORT) + NDIS_HOSTAPD_STATUS Hostapd; +#endif + +#ifdef APCLI_AUTO_BW_SUPPORT + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; +#endif /* APCLI_AUTO_BW_SUPPORT */ +}; + + + +/*************************************************************************** + * Multiple SSID related data structures + **************************************************************************/ +#define WLAN_MAX_NUM_OF_TIM ((MAX_LEN_OF_MAC_TABLE >> 3) + 1) /* /8 + 1 */ +#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */ + +/* clear bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~NUM_BIT8[0]; + +/* set bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_SET(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= NUM_BIT8[0]; + +/* clear a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, _aid) \ + { UCHAR tim_offset = _aid >> 3; \ + UCHAR bit_offset = _aid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~NUM_BIT8[bit_offset]); } + +/* set a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, _aid) \ + { UCHAR tim_offset = _aid >> 3; \ + UCHAR bit_offset = _aid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= NUM_BIT8[bit_offset]; } + + +#ifdef CONFIG_AP_SUPPORT +typedef struct _MULTISSID_STRUCT { + struct wifi_dev wdev; + + INT mbss_idx; + +#ifdef HOSTAPD_SUPPORT + NDIS_HOSTAPD_STATUS Hostapd; + BOOLEAN HostapdWPS; +#endif + +#ifdef SMART_MESH + BOOLEAN bSmartMeshACL; + SMART_MESH_CFG SmartMeshCfg; +#endif /* SMART_MESH */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* MWDS */ + + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + BOOLEAN bHideSsid; + + USHORT CapabilityInfo; + + UCHAR MaxStaNum; /* Limit the STA connection number per BSS */ + UCHAR StaCount; + UINT16 StationKeepAliveTime; /* unit: second */ + + PNET_DEV MSSIDDev; + /* + Security segment + */ + UCHAR RSNIE_Len[2]; + UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE]; + + /* WPA */ + UCHAR WPAKeyString[65]; + UCHAR GMK[32]; + UCHAR PMK[32]; + UCHAR GTK[32]; + UCHAR GNonce[32]; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; + + /* for Group Rekey, AP ONLY */ + RT_WPA_REKEY WPAREKEY; + ULONG REKEYCOUNTER; + RALINK_TIMER_STRUCT REKEYTimer; + UCHAR REKEYTimerRunning; + UINT8 RekeyCountDown; + + /* For PMK Cache using, AP ONLY */ + ULONG PMKCachePeriod; /* unit : jiffies */ + NDIS_AP_802_11_PMKID PMKIDCache; + +#ifdef DOT1X_SUPPORT + BOOLEAN PreAuth; + + /* For 802.1x daemon setting per BSS */ + UINT8 radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + UINT8 NasId[IFNAMSIZ]; + UINT8 NasIdLen; +#endif /* DOT1X_SUPPORT */ + +#ifdef WAPI_SUPPORT + UCHAR WAPIPassPhrase[64]; /* WAPI PSK pass phrase */ + UINT WAPIPassPhraseLen; /* the length of WAPI PSK pass phrase */ + UINT WapiPskType; /* 0 - Hex, 1 - ASCII */ + UCHAR WAPI_BK[16]; /* WAPI base key */ + + UCHAR NMK[LEN_WAPI_NMK]; + UCHAR key_announce_flag[LEN_WAPI_TSC]; + BOOLEAN sw_wpi_encrypt; /* WPI data encrypt by SW */ +#endif /* WAPI_SUPPORT */ + + + /* + Transmitting segment + */ + UCHAR TxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11, ... */ + UCHAR DesiredRates[MAX_LEN_OF_SUPPORTED_RATES]; /* OID_802_11_DESIRED_RATES */ + UCHAR DesiredRatesIndex; + UCHAR MaxTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + + + /* + Statistics segment + */ + LARGE_INTEGER ReceivedByteCount; + LARGE_INTEGER TransmittedByteCount; + ULONG TxCount; + ULONG RxCount; + ULONG RxErrorCount; + ULONG RxDropCount; +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + // Retry Packet Count + ULONG TxRetriedPktCount; + UINT64 ChannelUseTime; + // MGMT counter + ULONG MGMTRxCount; + ULONG MGMTTxCount; + ULONG MGMTReceivedByteCount; + ULONG MGMTTransmittedByteCount; + ULONG MGMTRxErrorCount; + ULONG MGMTRxDropCount; + ULONG MGMTTxErrorCount; + ULONG MGMTTxDropCount; +#endif +#endif + + ULONG TxErrorCount; + ULONG TxDropCount; + ULONG ucPktsTx; + ULONG ucPktsRx; + ULONG mcPktsTx; + ULONG mcPktsRx; + ULONG bcPktsTx; + ULONG bcPktsRx; + + ULONG StatTxRetryOkCount; + ULONG StatTxFailCount; + + UCHAR BANClass3Data; + BOOLEAN IsolateInterStaTraffic; + BOOLEAN IsolateInterStaMBCast; + + /* outgoing BEACON frame buffer and corresponding TXWI */ + BOOLEAN bBcnSntReq; /* used in if beacon send or stop */ + UCHAR BcnBufIdx; + CHAR BeaconBuf[MAX_BEACON_SIZE]; /* NOTE: BeaconBuf should be 4-byte aligned */ + UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM]; + UCHAR TimIELocationInBeacon; + UCHAR CapabilityInfoLocationInBeacon; + +#ifdef DOT11V_WNM_SUPPORT + UCHAR DMSEntrycount; + UCHAR totalDMScount; +#endif /* DOT11V_WNM_SUPPORT */ + + RT_802_11_ACL AccessControlList; + + /* EDCA Qos */ + /*BOOLEAN bWmmCapable;*/ /* 0:disable WMM, 1:enable WMM */ + BOOLEAN bDLSCapable; /* 0:disable DLS, 1:enable DLS */ +#ifdef QOS_DLS_SUPPORT + UCHAR DlsPTK[64]; /* Due to windows dirver count on meetinghouse to handle 4-way shake */ +#endif /* QOS_DLS_SUPPORT */ + + /* + Why need the parameter: 2009/09/22 + + 1. iwpriv ra0 set WmmCapable=0 + 2. iwpriv ra0 set WirelessMode=9 + 3. iwpriv ra0 set WirelessMode=0 + 4. iwpriv ra0 set SSID=SampleAP + + After the 4 commands, WMM is still enabled. + So we need the parameter to recover WMM Capable flag. + + No the problem in station mode. + */ + BOOLEAN bWmmCapableOrg; /* origin Wmm Capable in non-11n mode */ + + /* UAPSD information: such as enable or disable, do not remove */ + UAPSD_INFO UapsdInfo; + + + /* +` WPS segment + */ + WSC_LV_INFO WscIEBeacon; + WSC_LV_INFO WscIEProbeResp; +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; + WSC_SECURITY_MODE WscSecurityMode; +#endif /* WSC_AP_SUPPORT */ + +#ifdef IDS_SUPPORT + UINT32 RcvdConflictSsidCount; + UINT32 RcvdSpoofedAssocRespCount; + UINT32 RcvdSpoofedReassocRespCount; + UINT32 RcvdSpoofedProbeRespCount; + UINT32 RcvdSpoofedBeaconCount; + UINT32 RcvdSpoofedDisassocCount; + UINT32 RcvdSpoofedAuthCount; + UINT32 RcvdSpoofedDeauthCount; + UINT32 RcvdSpoofedUnknownMgmtCount; + UINT32 RcvdReplayAttackCount; + + CHAR RssiOfRcvdConflictSsid; + CHAR RssiOfRcvdSpoofedAssocResp; + CHAR RssiOfRcvdSpoofedReassocResp; + CHAR RssiOfRcvdSpoofedProbeResp; + CHAR RssiOfRcvdSpoofedBeacon; + CHAR RssiOfRcvdSpoofedDisassoc; + CHAR RssiOfRcvdSpoofedAuth; + CHAR RssiOfRcvdSpoofedDeauth; + CHAR RssiOfRcvdSpoofedUnknownMgmt; + CHAR RssiOfRcvdReplayAttack; +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_CFG FtCfg; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + WNM_CONFIG WnmCfg; +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_CONFIG RrmCfg; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + PMF_CFG PmfCfg; +#endif /* DOT11W_PMF_SUPPORT */ + + + /* YF@20120417: Avoid connecting to AP in Poor Env, value 0 fOr disable. */ + CHAR AssocReqFailRssiThreshold; + CHAR AssocReqNoRspRssiThreshold; + CHAR AuthFailRssiThreshold; + CHAR AuthNoRspRssiThreshold; + CHAR RssiLowForStaKickOut; + CHAR ProbeRspRssiThreshold; + + CHAR FilterUnusedPacket; +#ifdef CONFIG_DOT11U_INTERWORKING + GAS_CTRL GASCtrl; +#endif + +#ifdef CONFIG_HOTSPOT + HOTSPOT_CTRL HotSpotCtrl; +#endif + +#ifdef CONFIG_DOT11V_WNM + WNM_CTRL WNMCtrl; +#endif + +#ifdef SPECIFIC_TX_POWER_SUPPORT + CHAR TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + CHAR ProbeRspTimes; +} MULTISSID_STRUCT, *PMULTISSID_STRUCT; + +#ifdef CUSTOMER_DCC_FEATURE +typedef struct _CHANNEL_SWITCH{ + UCHAR CHSWCount; + UCHAR CHSWPeriod; + UCHAR CHSWMode; +} CHANNEL_SWITCH, *PCHANNEL_SWITCH; +#endif + +#define FILTER_NONE 0x00 +#define FILTER_IPV6_MC 0x01 +#define FILTER_IPV4_MC 0x02 +#define FILTER_IPV6_ALL 0x04 +#define FILTER_TOTAL 0x08 +#endif /* CONFIG_AP_SUPPORT */ +/* configuration common to OPMODE_AP as well as OPMODE_STA */ +typedef struct _COMMON_CONFIG { + BOOLEAN bCountryFlag; + UCHAR CountryCode[3]; +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR Geography; + UCHAR DfsType; + PUCHAR pChDesp; +#endif /* EXT_BUILD_CHANNEL_LIST */ + UCHAR CountryRegion; /* Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel */ + UCHAR CountryRegionForABand; /* Enum of country region for A band */ + UCHAR PhyMode; + UCHAR cfg_wmode; + UCHAR SavedPhyMode; + USHORT Dsifs; /* in units of usec */ + ULONG PacketFilter; /* Packet filter for receiving */ + UINT8 RegulatoryClass[MAX_NUM_OF_REGULATORY_CLASS]; + + CHAR Ssid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + UCHAR SsidLen; /* the actual ssid length in used */ + UCHAR LastSsidLen; /* the actual ssid length in used */ + CHAR LastSsid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + UCHAR LastBssid[MAC_ADDR_LEN]; + + UCHAR Bssid[MAC_ADDR_LEN]; + USHORT BeaconPeriod; + UCHAR Channel; + UCHAR CentralChannel; /* Central Channel when using 40MHz is indicating. not real channel. */ +#ifdef CUSTOMER_DCC_FEATURE + CHANNEL_SWITCH channelSwitch; +#endif + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; /* OID_802_11_DESIRED_RATES */ + UCHAR MaxDesiredRate; + UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; + + ULONG BasicRateBitmap; /* backup basic ratebitmap */ + ULONG BasicRateBitmapOld; /* backup basic ratebitmap */ + + BOOLEAN bInServicePeriod; + + UCHAR EtherTrafficBand; + + + BOOLEAN bAPSDAC_BE; + BOOLEAN bAPSDAC_BK; + BOOLEAN bAPSDAC_VI; + BOOLEAN bAPSDAC_VO; + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + BOOLEAN TDLS_bAPSDAC_BE; + BOOLEAN TDLS_bAPSDAC_BK; + BOOLEAN TDLS_bAPSDAC_VI; + BOOLEAN TDLS_bAPSDAC_VO; + UCHAR TDLS_MaxSPLength; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + /* because TSPEC can modify the APSD flag, we need to keep the APSD flag + requested in association stage from the station; + we need to recover the APSD flag after the TSPEC is deleted. */ + BOOLEAN bACMAPSDBackup[4]; /* for delivery-enabled & trigger-enabled both */ + BOOLEAN bACMAPSDTr[4]; /* no use */ + UCHAR MaxSPLength; + + BOOLEAN bNeedSendTriggerFrame; + BOOLEAN bAPSDForcePowerSave; /* Force power save mode, should only use in APSD-STAUT */ + ULONG TriggerTimerCount; + UCHAR BBPCurrentBW; /* BW_10, BW_20, BW_40, BW_80 */ + REG_TRANSMIT_SETTING RegTransmitSetting; /*registry transmit setting. this is for reading registry setting only. not useful. */ + UCHAR TxRate; /* Same value to fill in TXD. TxRate is 6-bit */ + UCHAR MaxTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + UCHAR TxRateIndex; /* Tx rate index in Rate Switch Table */ + UCHAR MinTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + UCHAR RtsRate; /* RATE_xxx */ + HTTRANSMIT_SETTING MlmeTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + UCHAR MlmeRate; /* RATE_xxx, used to send MLME frames */ + UCHAR BasicMlmeRate; /* Default Rate for sending MLME frames */ + + USHORT RtsThreshold; /* in unit of BYTE */ + USHORT FragmentThreshold; /* in unit of BYTE */ + + UCHAR TxPower; /* in unit of mW */ + ULONG TxPowerPercentage; /* 0~100 % */ + ULONG TxPowerDefault; /* keep for TxPowerPercentage */ + BOOLEAN TxPowerPercentageWithBBP; /* if true , we're using BBP 2710 to do power percentage, disable TSSI */ + UINT8 PwrConstraint; + +#ifdef DOT11_N_SUPPORT + BACAP_STRUC BACapability; /* NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 */ + BACAP_STRUC REGBACapability; /* NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + BOOLEAN force_vht; + UCHAR vht_bw; + UCHAR vht_sgi_80; + UCHAR vht_stbc; + UCHAR vht_bw_signal; + UCHAR vht_cent_ch; + UCHAR vht_cent_ch2; +#ifdef WFA_VHT_PF + UCHAR vht_mcs_cap; + UCHAR vht_nss_cap; + USHORT vht_tx_hrate; + USHORT vht_rx_hrate; +#endif /* WFA_VHT_PF */ + BOOLEAN vht_ldpc; +#endif /* DOT11_VHT_AC */ + + IOT_STRUC IOTestParm; /* 802.11n InterOpbility Test Parameter; */ + ULONG TxPreamble; /* Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto */ + BOOLEAN bUseZeroToDisableFragment; /* Microsoft use 0 as disable */ + ULONG UseBGProtection; /* 0: auto, 1: always use, 2: always not use */ + BOOLEAN bUseShortSlotTime; /* 0: disable, 1 - use short slot (9us) */ + BOOLEAN bEnableTxBurst; /* 1: enble TX PACKET BURST (when BA is established or AP is not a legacy WMM AP), 0: disable TX PACKET BURST */ + BOOLEAN bAggregationCapable; /* 1: enable TX aggregation when the peer supports it */ + BOOLEAN bPiggyBackCapable; /* 1: enable TX piggy-back according MAC's version */ + BOOLEAN bIEEE80211H; /* 1: enable IEEE802.11h spec. */ + UCHAR RDDurRegion; /* Region of radar detection */ + ULONG DisableOLBCDetect; /* 0: enable OLBC detect; 1 disable OLBC detect */ + +#ifdef DOT11_N_SUPPORT + BOOLEAN bRdg; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + BOOLEAN b256QAM_2G; +#endif /* DOT11_VHT_AC */ + + BOOLEAN bWmmCapable; /* 0:disable WMM, 1:enable WMM */ + QOS_CAPABILITY_PARM APQosCapability; /* QOS capability of the current associated AP */ + EDCA_PARM APEdcaParm; /* EDCA parameters of the current associated AP */ +#ifdef MULTI_CLIENT_SUPPORT + BOOLEAN bWmm; /* have BSS enable/disable WMM */ + UCHAR APCwmin; /* record ap cwmin */ + UCHAR APCwmax; /* record ap cwmax */ + UCHAR BSSCwmin; /* record BSS cwmin */ +#endif /* MULTI_CLIENT_SUPPORT */ + QBSS_LOAD_PARM APQbssLoad; /* QBSS load of the current associated AP */ + UCHAR AckPolicy[4]; /* ACK policy of the specified AC. see ACK_xxx */ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bDLSCapable; /* 0:disable DLS, 1:enable DLS */ +#endif /* CONFIG_STA_SUPPORT */ + /* a bitmap of BOOLEAN flags. each bit represent an operation status of a particular */ + /* BOOLEAN control, either ON or OFF. These flags should always be accessed via */ + /* OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. */ + /* see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition */ + ULONG OpStatusFlags; + + BOOLEAN NdisRadioStateOff; /*For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. */ + ABGBAND_STATE BandState; /* For setting BBP used on B/G or A mode. */ + + +#ifdef DFS_SUPPORT + /* IEEE802.11H--DFS. */ + RADAR_DETECT_STRUCT RadarDetect; +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + CARRIER_DETECTION_STRUCT CarrierDetect; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* HT */ + RT_HT_CAPABILITY DesiredHtPhy; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHTInfo; /* Useful as AP. */ + /*This IE is used with channel switch announcement element when changing to a new 40MHz. */ + /*This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. */ + NEW_EXT_CHAN_IE NewExtChanOffset; /*7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present */ + + EXT_CAP_INFO_ELEMENT ExtCapIE; /* this is the extened capibility IE appreed in MGMT frames. Doesn't need to update once set in Init. */ + +#ifdef DOT11N_DRAFT3 + BOOLEAN bBssCoexEnable; + /* + Following two paramters now only used for the initial scan operation. the AP only do + bandwidth fallback when BssCoexApCnt > BssCoexApCntThr + By default, the "BssCoexApCntThr" is set as 0 in "UserCfgInit()". + */ + UCHAR BssCoexApCntThr; + UCHAR BssCoexApCnt; + + UCHAR Bss2040CoexistFlag; /* bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo. */ + RALINK_TIMER_STRUCT Bss2040CoexistTimer; + UCHAR Bss2040NeedFallBack; /* 1: Need Fall back to 20MHz */ + + /*This IE is used for 20/40 BSS Coexistence. */ + BSS_2040_COEXIST_IE BSS2040CoexistInfo; + + USHORT Dot11OBssScanPassiveDwell; /* Unit : TU. 5~1000 */ + USHORT Dot11OBssScanActiveDwell; /* Unit : TU. 10~1000 */ + USHORT Dot11BssWidthTriggerScanInt; /* Unit : Second */ + USHORT Dot11OBssScanPassiveTotalPerChannel; /* Unit : TU. 200~10000 */ + USHORT Dot11OBssScanActiveTotalPerChannel; /* Unit : TU. 20~10000 */ + USHORT Dot11BssWidthChanTranDelayFactor; + USHORT Dot11OBssScanActivityThre; /* Unit : percentage */ + + ULONG Dot11BssWidthChanTranDelay; /* multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) */ + ULONG CountDownCtr; /* CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) */ + + BSS_2040_COEXIST_IE LastBSSCoexist2040; + BSS_2040_COEXIST_IE BSSCoexist2040; + TRIGGER_EVENT_TAB TriggerEventTab; + UCHAR ChannelListIdx; + + BOOLEAN bOverlapScanning; + BOOLEAN bBssCoexNotify; + UCHAR ori_bw_before_2040_coex; + UCHAR ori_ext_channel_before_2040_coex; +#endif /* DOT11N_DRAFT3 */ + + BOOLEAN bHTProtect; + BOOLEAN bMIMOPSEnable; + BOOLEAN bBADecline; + BOOLEAN bDisableReordering; +#ifdef DOT11N_DRAFT3 + BOOLEAN bForty_Mhz_Intolerant; +#endif /* DOT11N_DRAFT3 */ + BOOLEAN bExtChannelSwitchAnnouncement; + BOOLEAN bRcvBSSWidthTriggerEvents; + ULONG LastRcvBSSWidthTriggerEventsTime; + + UCHAR TxBASize; + + BOOLEAN bRalinkBurstMode; + UINT32 RestoreBurstMode; + BOOLEAN ht_ldpc; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + UINT32 cfg_vht; + VHT_CAP_INFO vht_info; + VHT_CAP_IE vht_cap_ie; + BOOLEAN bNonVhtDisallow; /* Disallow non-VHT connection */ +#endif /* DOT11_VHT_AC */ + +#ifdef SYSTEM_LOG_SUPPORT + /* Enable wireless event */ + BOOLEAN bWirelessEvent; +#endif /* SYSTEM_LOG_SUPPORT */ + + BOOLEAN bWiFiTest; /* Enable this parameter for WiFi test */ + BOOLEAN bMcastTest; + + /* Tx & Rx Stream number selection */ + UCHAR TxStream; + UCHAR RxStream; + + /* transmit phy mode, trasmit rate for Multicast. */ +#ifdef MCAST_RATE_SPECIFIC + UCHAR McastTransmitMcs; + UCHAR McastTransmitPhyMode; +#endif /* MCAST_RATE_SPECIFIC */ + + BOOLEAN bHardwareRadio; /* Hardware controlled Radio enabled */ + + +#ifdef WSC_INCLUDED + /* WSC hardware push button function 0811 */ + UINT8 WscHdrPshBtnCheckCount; +#endif /* WSC_INCLUDED */ + + + NDIS_SPIN_LOCK MeasureReqTabLock; + PMEASURE_REQ_TAB pMeasureReqTab; + + NDIS_SPIN_LOCK TpcReqTabLock; + PTPC_REQ_TAB pTpcReqTab; + + /* transmit phy mode, trasmit rate for Multicast. */ +#ifdef MCAST_RATE_SPECIFIC + HTTRANSMIT_SETTING MCastPhyMode; +#endif /* MCAST_RATE_SPECIFIC */ + +#ifdef SINGLE_SKU + UINT16 DefineMaxTxPwr; + BOOLEAN bSKUMode; + UINT16 AntGain; + UINT16 BandedgeDelta; + UINT16 ModuleTxpower; +#endif /* SINGLE_SKU */ + +#ifdef SINGLE_SKU_V2 +#ifdef RT6352 + UCHAR SkuChannel; +#endif /* RT6352 */ +#endif /* SINGLE_SKU_V2 */ + +#ifdef WAPI_SUPPORT + COMMON_WAPI_INFO comm_wapi_info; + + /* rekey related parameter */ + /* USK update parameter */ + UINT8 wapi_usk_rekey_method; /* 0:disable , 1:time, 2:packet */ + UINT32 wapi_usk_rekey_threshold; /* the rekey threshold */ + + /* MSK update parameter */ + UINT8 wapi_msk_rekey_method; /* 0:disable , 1:time, 2:packet */ + UINT32 wapi_msk_rekey_threshold; /* the rekey threshold */ + + UINT32 wapi_msk_rekey_cnt; + RALINK_TIMER_STRUCT WapiMskRekeyTimer; + UCHAR WapiMskRekeyTimerRunning; +#endif /* WAPI_SUPPORT */ +#ifdef RTMP_RBUS_SUPPORT + ULONG CID; + ULONG CN; +#ifdef RT6352 + UCHAR PKG_ID; + UCHAR Chip_VerID; + UCHAR Chip_E_Number; +#endif /* RT6352 */ +#endif /* RTMP_RBUS_SUPPORT */ + + + BOOLEAN HT_DisallowTKIP; /* Restrict the encryption type in 11n HT mode */ +#ifdef DOT11K_RRM_SUPPORT + BOOLEAN VoPwrConstraintTest; +#endif /* DOT11K_RRM_SUPPORT */ + + BOOLEAN HT_Disable; /* 1: disable HT function; 0: enable HT function */ + + +#ifdef PRE_ANT_SWITCH + BOOLEAN PreAntSwitch; /* Preamble Antenna Switch */ + SHORT PreAntSwitchRSSI; /* Preamble Antenna Switch RSSI threshold */ + SHORT PreAntSwitchTimeout; /* Preamble Antenna Switch timeout in seconds */ +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK + SHORT CFOTrack; /* CFO Tracking. 0=>use default, 1=>track, 2-7=> track 8-n times, 8=>done tracking */ +#endif /* CFO_TRACK */ + +#ifdef NEW_RATE_ADAPT_SUPPORT + USHORT lowTrafficThrd; /* Threshold for reverting to default MCS when traffic is low */ + SHORT TrainUpRuleRSSI; /* If TrainUpRule=2 then use Hybrid rule when RSSI < TrainUpRuleRSSI */ + USHORT TrainUpLowThrd; /* QuickDRS Hybrid train up low threshold */ + USHORT TrainUpHighThrd; /* QuickDRS Hybrid train up high threshold */ + BOOLEAN TrainUpRule; /* QuickDRS train up criterion: 0=>Throughput, 1=>PER, 2=> Throughput & PER */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT +#define STREAM_MODE_STA_NUM 4 + + UCHAR StreamMode; /* 0=disabled, 1=enable for 1SS, 2=enable for 2SS, 3=enable for 1,2SS */ + UCHAR StreamModeMac[STREAM_MODE_STA_NUM][MAC_ADDR_LEN]; + UINT16 StreamModeMCS; /* Bit map for enabling Stream Mode based on MCS */ +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT + ULONG ITxBfTimeout; + ULONG ETxBfTimeout; + BOOLEAN ETxBfeeEn; /* Enable BFee feature */ + ULONG ETxBfEnCond; /* Enable sending of sounding and beamforming */ + BOOLEAN ETxBfNoncompress; /* Force non-compressed Sounding Response */ + BOOLEAN ETxBfIncapable; /* Report Incapable of BF in TX BF Capabilities */ + UCHAR ITxBfCalibMode; /* ITxBF calibration mode, 1:5 channel, 2: 13 channel */ +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + ULONG DebugFlags; /* Temporary debug flags */ +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef RTMP_MAC_PCI + BOOLEAN bPCIeBus; /* The adapter runs over PCIe bus */ +#endif /* RTMP_MAC_PCI */ + +#ifdef WSC_INCLUDED + BOOLEAN WscPBCOverlap; + WSC_STA_PBC_PROBE_INFO WscStaPbcProbeInfo; +#endif /* WSC_INCLUDED */ + + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) + MO_CFG_STRUCT MO_Cfg; /* data structure for mitigating microwave interference */ +#endif /* MICROWAVE_OVEN_SUPPORT || DYNAMIC_VGA_SUPPORT */ + +#ifdef RT6352 + BOOLEAN bEnTemperatureTrack; +#endif /* RT6352 */ + +/* TODO: need to integrate with MICROWAVE_OVEN_SUPPORT */ +#ifdef DYNAMIC_VGA_SUPPORT + LNA_VGA_CTL_STRUCT lna_vga_ctl; +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef DELAYED_TCP_ACK +#define TCP_ACK_BURST_LEVEL 10 + BOOLEAN ACKQEN; + UCHAR AckWaitTime; + UCHAR Acklen; + UINT AckTimeout; + UINT AckNOTimeout; + UINT TcpAck[TCP_ACK_BURST_LEVEL+1]; /* 0~TCP_ACK_BURST_LEVEL */ +#endif /* DELAYED_TCP_ACK */ + + BOOLEAN bStopReadTemperature; /* avoid race condition between FW/driver */ + +#ifdef REDUCE_TCP_ACK_SUPPORT + UINT32 ReduceAckEnable; + UINT32 ReduceAckProbability; + UINT32 ReduceAckTimeout; + UINT32 ReduceAckCnxTimeout; + UINT32 ReduceAckGainLevel; +#endif /* REDUCE_TCP_ACK_SUPPORT */ + + ULONG ManualTxopThreshold; + UCHAR ManualTxopUpBound; + UCHAR ManualTxopLowBound; +} COMMON_CONFIG, *PCOMMON_CONFIG; + +#ifdef DBG_CTRL_SUPPORT +/* DebugFlag definitions */ +#define DBF_NO_BF_AWARE_RA 0x0001 /* Revert to older Rate Adaptation that is not BF aware */ +#define DBF_SHOW_BF_STATS 0x0002 /* Display BF statistics in AP "iwpriv stat" display */ +#define DBF_NO_TXBF_3SS 0x0004 /* Disable TXBF for MCS > 20 */ +#define DBF_UNUSED0008 0x0008 /* Unused */ +#define DBF_DBQ_RA_LOG 0x0010 /* Log RA information in DBQ */ +#define DBF_INIT_MCS_MARGIN 0x0020 /* Use 6 dB margin when selecting initial MCS */ +#define DBF_INIT_MCS_DIS1 0x0040 /* Disable highest MCSs when selecting initial MCS */ +#define DBF_FORCE_QUICK_DRS 0x0080 /* Force Quick DRS even if rate didn't change */ +#define DBF_FORCE_SGI 0x0100 /* Force Short GI */ +#define DBF_DBQ_NO_BCN 0x0200 /* Disable logging of RX Beacon frames */ +#define DBF_LOG_VCO_CAL 0x0400 /* Log VCO cal */ +#define DBF_DISABLE_CAL 0x0800 /* Disable Divider Calibration at channel change */ +#ifdef INCLUDE_DEBUG_QUEUE +#define DBF_DBQ_TXFIFO 0x1000 /* Enable logging of TX information from FIFO */ +#define DBF_DBQ_TXFRAME 0x2000 /* Enable logging of Frames queued for TX */ +#define DBF_DBQ_RXWI_FULL 0x4000 /* Enable logging of full RXWI */ +#define DBF_DBQ_RXWI 0x8000 /* Enable logging of partial RXWI */ +#endif /* INCLUDE_DEBUG_QUEUE */ + +#define DBF_SHOW_RA_LOG 0x010000 /* Display concise Rate Adaptation information */ +#define DBF_SHOW_ZERO_RA_LOG 0x020000 /* Include RA Log entries when TxCount is 0 */ +#define DBF_FORCE_20MHZ 0x040000 /* Force 20 MHz TX */ +#define DBF_FORCE_40MHZ 0x080000 /* Force 40 MHz Tx */ +#define DBF_DISABLE_CCK 0x100000 /* Disable CCK */ +#define DBF_UNUSED200000 0x200000 /* Unused */ +#define DBF_ENABLE_HT_DUP 0x400000 /* Allow HT Duplicate mode in TX rate table */ +#define DBF_ENABLE_CCK_5G 0x800000 /* Enable CCK rates in 5G band */ +#define DBF_UNUSED0100000 0x0100000 /* Unused */ +#define DBF_ENABLE_20MHZ_MCS8 0x02000000 /* Substitute 20MHz MCS8 for 40MHz MCS8 */ +#define DBF_DISABLE_20MHZ_MCS0 0x04000000 /* Disable substitution of 20MHz MCS0 for 40MHz MCS32 */ +#define DBF_DISABLE_20MHZ_MCS1 0x08000000 /* Disable substitution of 20MHz MCS1 for 40MHz MCS0 */ +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + +typedef struct _WPA_SUPPLICANT_INFO{ + /* + 802.1x WEP + MD5 will set key to driver before assoc, but we need to apply the key to + ASIC after get EAPOL-Success frame, so we use this flag to indicate that + */ + BOOLEAN IEEE8021x_required_keys; + CIPHER_KEY DesireSharedKey[4]; /* Record user desired WEP keys */ + UCHAR DesireSharedKeyId; + + /* 0x00: driver ignores wpa_supplicant */ + /* 0x01: wpa_supplicant initiates scanning and AP selection */ + /* 0x02: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters */ + /* 0x80: wpa_supplicant trigger driver to do WPS */ + UCHAR WpaSupplicantUP; + UCHAR WpaSupplicantScanCount; + BOOLEAN bRSN_IE_FromWpaSupplicant; + BOOLEAN bLostAp; + UCHAR *pWpsProbeReqIe; + UINT WpsProbeReqIeLen; + UCHAR *pWpaAssocIe; + UINT WpaAssocIeLen; +}WPA_SUPPLICANT_INFO; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + +#ifdef CREDENTIAL_STORE +typedef struct _STA_CONNECT_INFO { + BOOLEAN Changeable; + BOOLEAN IEEE8021X; + CHAR Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated + UCHAR SsidLen; // the actual ssid length in used + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + UCHAR DefaultKeyId; + UCHAR PMK[LEN_PMK]; // WPA PSK mode PMK + UCHAR WpaPassPhrase[64]; // WPA PSK pass phrase + UINT WpaPassPhraseLen; // the length of WPA PSK pass phrase + UINT8 WpaState; + CIPHER_KEY SharedKey[1][4]; // STA always use SharedKey[BSS0][0..3] + NDIS_SPIN_LOCK Lock; +} STA_CONNECT_INFO, *P_STA_CONNECT_INFO; +#endif /* CREDENTIAL_STORE */ + + +#ifdef DOT11Z_TDLS_SUPPORT +typedef struct _TDLS_STRUCT +{ + BOOLEAN bTDLSCapable; /* 0:disable TDLS, 1:enable TDLS */ + BOOLEAN bAcceptWeakSecurity; + BOOLEAN TdlsChSwitchSupp; + BOOLEAN TdlsPsmSupp; + UINT8 TdlsDialogToken; + UINT32 TdlsKeyLifeTime; + UINT8 TdlsLinkSize; /* record how much links establish already. */ + RT_802_11_TDLS TDLSEntry[MAX_NUM_OF_TDLS_ENTRY]; + NDIS_SPIN_LOCK TDLSEntryLock; + NDIS_SPIN_LOCK TDLSUapsdLock; +#ifdef TDLS_AUTOLINK_SUPPORT + BOOLEAN TdlsAutoLink; + LIST_HEADER TdlsDiscovPeerList; + NDIS_SPIN_LOCK TdlsDiscovPeerListSemLock; + LIST_HEADER TdlsBlackList; + NDIS_SPIN_LOCK TdlsBlackListSemLock; + + CHAR TdlsAutoSetupRssiThreshold; + CHAR TdlsAutoTeardownRssiThreshold; + USHORT TdlsRssiMeasurementPeriod; + USHORT TdlsDisabledPeriodByTeardown; + USHORT TdlsAutoDiscoveryPeriod; +#endif /* TDLS_AUTOLINK_SUPPORT */ + + /* Channel Switch */ + NDIS_SPIN_LOCK TdlsChSwLock; + NDIS_SPIN_LOCK TdlsInitChannelLock; + RALINK_TIMER_STRUCT TdlsPeriodGoBackBaseChTimer; + RALINK_TIMER_STRUCT TdlsPeriodGoOffChTimer; + RALINK_TIMER_STRUCT TdlsDisableChannelSwitchTimer; + + BOOLEAN TdlsForcePowerSaveWithAP; + BOOLEAN bDoingPeriodChannelSwitch; + BOOLEAN bChannelSwitchInitiator; + BOOLEAN bChannelSwitchWaitSuccess; + UCHAR TdlsCurrentTargetChannel; + UCHAR TdlsDesireChannel; + UCHAR TdlsDesireChannelBW; + UCHAR TdlsDesireChSwMacAddr[MAC_ADDR_LEN]; + UCHAR TdlsAsicOperateChannel; + UCHAR TdlsAsicOperateChannelBW; + + UCHAR TdlsChannelSwitchPairCount; + UCHAR TdlsChannelSwitchRetryCount; + ULONG TdlsGoBackStartTime; + ULONG TdlsChSwSilenceTime; + ULONG TdlsActiveSwitchTime; + ULONG TdlsActiveSwitchTimeOut; + UCHAR TdlsDtimCount; + + /* record old power save mode */ +#define TDLS_POWER_SAVE_ACTIVE_COUNT_DOWN_NUM (5*1000/MLME_TASK_EXEC_INTV) + BOOLEAN TdlsFlgIsKeepingActiveCountDown; /* keep active until 0 */ + UINT8 TdlsPowerSaveActiveCountDown; +}TDLS_STRUCT, *PTDLS_STRUCT; +#endif // DOT11Z_TDLS_SUPPORT // + + + + +/* Modified by Wu Xi-Kun 4/21/2006 */ +/* STA configuration and status */ +typedef struct _STA_ADMIN_CONFIG { + struct wifi_dev wdev; + + /* + GROUP 1 - + User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe + the user intended configuration, but not necessary fully equal to the final + settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either + AP or IBSS holder). + Once initialized, user configuration can only be changed via OID_xxx + */ + UCHAR BssType; /* BSS_INFRA or BSS_ADHOC */ + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT +#define MONITOR_FLAG_11N_SNIFFER 0x01 + UCHAR BssMonitorFlag; /* Specific flag for monitor */ +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + + USHORT AtimWin; /* used when starting a new IBSS */ + + /* + GROUP 2 - + User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe + the user intended configuration, and should be always applied to the final + settings in ACTIVE BSS without compromising with the BSS holder. + Once initialized, user configuration can only be changed via OID_xxx + */ + USHORT DefaultListenCount; /* default listen count; */ + USHORT ThisTbttNumToNextWakeUp; + ULONG WindowsPowerMode; /* Power mode for AC power */ + ULONG WindowsBatteryPowerMode; /* Power mode for battery if exists */ + BOOLEAN bWindowsACCAMEnable; /* Enable CAM power mode when AC on */ + BOOLEAN bAutoReconnect; /* Set to TRUE when setting OID_802_11_SSID with no matching BSSID */ + UCHAR RssiTrigger; + UCHAR RssiTriggerMode; /* RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD */ + + ULONG WindowsPowerProfile; /* Windows power profile, for NDIS5.1 PnP */ + + BOOLEAN FlgPsmCanNotSleep; /* TRUE: can not switch ASIC to sleep */ + /* MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1) */ + USHORT Psm; /* power management mode (PWR_ACTIVE|PWR_SAVE) */ + USHORT DisassocReason; + UCHAR DisassocSta[MAC_ADDR_LEN]; + USHORT DeauthReason; + UCHAR DeauthSta[MAC_ADDR_LEN]; + USHORT AuthFailReason; + UCHAR AuthFailSta[MAC_ADDR_LEN]; + + /* + Security segment + */ + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + + /* Add to support different cipher suite for WPA2/WPA mode */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Multicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher suite */ + BOOLEAN bMixCipher; /* Indicate current Pair & Group use different cipher suites */ + USHORT RsnCapability; + + UCHAR WpaPassPhrase[64]; /* WPA PSK pass phrase */ + UINT WpaPassPhraseLen; /* the length of WPA PSK pass phrase */ + UCHAR PMK[LEN_PMK]; /* WPA PSK mode PMK */ + UCHAR PTK[LEN_PTK]; /* WPA PSK mode PTK */ + UCHAR GMK[LEN_GMK]; /* WPA PSK mode GMK */ + UCHAR GTK[MAX_LEN_GTK]; /* GTK from authenticator */ + UCHAR GNonce[32]; /* GNonce for WPA2PSK from authenticator */ + CIPHER_KEY TxGTK; + BSSID_INFO SavedPMK[PMKID_NO]; + UINT SavedPMKNum; /* Saved PMKID number */ + +#ifdef WAPI_SUPPORT + UCHAR WAPIPassPhrase[64]; /* WAPI PSK pass phrase */ + UINT WAPIPassPhraseLen; /* the length of WAPI PSK pass phrase */ + UINT WapiPskType; /* 0 - Hex, 1 - ASCII */ + UCHAR WAPI_BK[16]; /* WAPI base key */ + + UCHAR NMK[16]; /* WAPI notify master key */ +#endif /* WAPI_SUPPORT */ + + /* For WPA countermeasures */ + ULONG LastMicErrorTime; /* record last MIC error time */ + ULONG MicErrCnt; /* Should be 0, 1, 2, then reset to zero (after disassoiciation). */ + BOOLEAN bBlockAssoc; /* Block associate attempt for 60 seconds after counter measure occurred. */ + /* For WPA-PSK supplicant state */ + UINT8 WpaState; /* Default is SS_NOTUSE and handled by microsoft 802.1x */ + UCHAR ReplayCounter[8]; + UCHAR ANonce[32]; /* ANonce for WPA-PSK from aurhenticator */ + UCHAR SNonce[32]; /* SNonce for WPA-PSK */ + + UCHAR LastSNR0; /* last received BEACON's SNR */ + UCHAR LastSNR1; /* last received BEACON's SNR for 2nd antenna */ +#ifdef DOT11N_SS3_SUPPORT + UCHAR LastSNR2; /* last received BEACON's SNR for 3nd antenna */ + INT32 BF_SNR[3]; /* Last RXWI BF SNR. Units=0.25 dB */ +#endif /* DOT11N_SS3_SUPPORT */ + RSSI_SAMPLE RssiSample; + ULONG NumOfAvgRssiSample; + + ULONG LastBeaconRxTime; /* OS's timestamp of the last BEACON RX time */ + + ULONG LastScanTime; /* Record last scan time for issue BSSID_SCAN_LIST */ + BOOLEAN bNotFirstScan; /* Sam add for ADHOC flag to do first scan when do initialization */ + BOOLEAN bSwRadio; /* Software controlled Radio On/Off, TRUE: On */ + BOOLEAN bHwRadio; /* Hardware controlled Radio On/Off, TRUE: On */ + BOOLEAN bRadio; /* Radio state, And of Sw & Hw radio state */ + BOOLEAN bHardwareRadio; /* Hardware controlled Radio enabled */ + BOOLEAN bShowHiddenSSID; /* Show all known SSID in SSID list get operation */ + + /* New for WPA, windows want us to to keep association information and */ + /* Fixed IEs from last association response */ + NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; + USHORT ReqVarIELen; /* Length of next VIE include EID & Length */ + UCHAR ReqVarIEs[MAX_VIE_LEN]; /* The content saved here should be little-endian format. */ + USHORT ResVarIELen; /* Length of next VIE include EID & Length */ + UCHAR ResVarIEs[MAX_VIE_LEN]; + + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; /* The content saved here should be little-endian format. */ + + //ULONG CLBusyBytes; /* Save the total bytes received durning channel load scan time */ + USHORT RPIDensity[8]; /* Array for RPI density collection */ + + UCHAR RMReqCnt; /* Number of measurement request saved. */ + UCHAR CurrentRMReqIdx; /* Number of measurement request saved. */ + BOOLEAN ParallelReq; /* Parallel measurement, only one request performed, */ + /* It must be the same channel with maximum duration */ + USHORT ParallelDuration; /* Maximum duration for parallel measurement */ + UCHAR ParallelChannel; /* Only one channel with parallel measurement */ + USHORT IAPPToken; /* IAPP dialog token */ + /* Hack for channel load and noise histogram parameters */ + UCHAR NHFactor; /* Parameter for Noise histogram */ + UCHAR CLFactor; /* Parameter for channel load */ + + RALINK_TIMER_STRUCT StaQuickResponeForRateUpTimer; + BOOLEAN StaQuickResponeForRateUpTimerRunning; + + UCHAR DtimCount; /* 0.. DtimPeriod-1 */ + UCHAR DtimPeriod; /* default = 3 */ + +#ifdef QOS_DLS_SUPPORT + RT_802_11_DLS DLSEntry[MAX_NUM_OF_DLS_ENTRY]; + UCHAR DlsReplayCounter[8]; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + TDLS_STRUCT TdlsInfo; +#endif /* DOT11Z_TDLS_SUPPORT */ + + RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer; + /* Fast Roaming */ + BOOLEAN bAutoRoaming; /* 0:disable auto roaming by RSSI, 1:enable auto roaming by RSSI */ + CHAR dBmToRoam; /* the condition to roam when receiving Rssi less than this value. It's negative value. */ + +#ifdef WPA_SUPPLICANT_SUPPORT + WPA_SUPPLICANT_INFO wpa_supplicant_info; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + +#ifdef WSC_STA_SUPPORT + WSC_LV_INFO WpsIEBeacon; + WSC_LV_INFO WpsIEProbeResp; + WSC_CTRL WscControl; +#ifdef IWSC_SUPPORT + IWSC_INFO IWscInfo; +#endif /* IWSC_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + CHAR dev_name[16]; + USHORT OriDevType; + + BOOLEAN bTGnWifiTest; + BOOLEAN bSkipAutoScanConn; + +#ifdef RTMP_MAC_PCI + UCHAR BBPR3; + + /* PS Control has 2 meanings for advanced power save function. */ + /* 1. EnablePSinIdle : When no connection, always radio off except need to do site survey. */ + /* 2. EnableNewPS : will save more current in sleep or radio off mode. */ + PS_CONTROL PSControl; +#endif /* RTMP_MAC_PCI */ + +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR IEEE80211dClientMode; + UCHAR StaOriCountryCode[3]; + UCHAR StaOriGeography; +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef ETH_CONVERT_SUPPORT + BOOLEAN bFragFlag; +#endif /* ETH_CONVERT_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + DOT11R_CMN_STRUC Dot11RCommInfo; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + WNM_CONFIG WnmCfg; + BOOLEAN bBSSMantAPSupport; + BOOLEAN bDMSAPSupport; + BOOLEAN BTMQuerySend; + BOOLEAN bDMSSetUp; + UCHAR BTMQueryDialogToken; + UCHAR DMSREQDialogToken; +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + PMF_CFG PmfCfg; +#endif /* DOT11W_PMF_SUPPORT */ + + BOOLEAN bAutoConnectByBssid; + ULONG BeaconLostTime; /* seconds */ + BOOLEAN bForceTxBurst; /* 1: force enble TX PACKET BURST, 0: disable */ +#ifdef XLINK_SUPPORT + BOOLEAN PSPXlink; /* 0: Disable. 1: Enable */ +#endif /* XLINK_SUPPORT */ + BOOLEAN bAutoConnectIfNoSSID; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + UCHAR RegClass; /*IE_SUPP_REG_CLASS: 2009 PF#3: For 20/40 Intolerant Channel Report */ +#endif /* DOT11N_DRAFT3 */ + BOOLEAN bAdhocN; +#endif /* DOT11_N_SUPPORT */ + BOOLEAN bAdhocCreator; /*TRUE indicates divice is Creator. */ + + + /* + Enhancement Scanning Mechanism + To decrease the possibility of ping loss + */ + BOOLEAN bImprovedScan; + BOOLEAN BssNr; + UCHAR ScanChannelCnt; /* 0 at the beginning of scan, stop at 7 */ + UCHAR LastScanChannel; + /************************************/ + + BOOLEAN bFastConnect; + +/*connectinfo for tmp store connect info from UI*/ + BOOLEAN Connectinfoflag; + UCHAR ConnectinfoBssid[MAC_ADDR_LEN]; + UCHAR ConnectinfoChannel; + UCHAR ConnectinfoSsidLen; + CHAR ConnectinfoSsid[MAX_LEN_OF_SSID]; + UCHAR ConnectinfoBssType; + + + + + /* UAPSD information: such as enable or disable, do not remove */ + UAPSD_INFO UapsdInfo; + + +#ifdef CONFIG_DOT11U_INTERWORKING + GAS_CTRL GASCtrl; +#endif + +#ifdef CONFIG_HOTSPOT + HOTSPOT_CTRL HotSpotCtrl; +#endif + +#ifdef CONFIG_DOT11V_WNM + WNM_CTRL WNMCtrl; +#endif + +#ifdef WFD_SUPPORT + RT_WFD_CONFIG WfdCfg; +#endif /* WFD_SUPPORT */ +} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG; + + +/* + This data structure keep the current active BSS/IBSS's configuration that + this STA had agreed upon joining the network. Which means these parameters + are usually decided by the BSS/IBSS creator instead of user configuration. + Data in this data structurre is valid only when either ADHOC_ON()/INFRA_ON() + is TRUE. Normally, after SCAN or failed roaming attempts, we need to + recover back to the current active settings +*/ +typedef struct _STA_ACTIVE_CONFIG { + USHORT Aid; + USHORT AtimWin; /* in kusec; IBSS parameter set element */ + USHORT CapabilityInfo; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + + /* Copy supported rate from desired AP's beacon. We are trying to match */ + /* AP's supported and extended rate settings. */ + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + /* Copy supported ht from desired AP's beacon. We are trying to match */ + RT_PHY_INFO SupportedPhyInfo; + RT_HT_CAPABILITY SupportedHtPhy; +#ifdef DOT11_VHT_AC + RT_VHT_CAP SupVhtCap; +#endif /* DOT11_VHT_AC */ +} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG; + + +#ifdef ETH_CONVERT_SUPPORT +#define ETH_CONVERT_NODE_MAX 256 + +/* Ethernet Convertor operation mode definitions. */ +typedef enum { + ETH_CONVERT_MODE_DISABLE = 0, + ETH_CONVERT_MODE_DONGLE = 1, /* Multiple client support, dispatch to AP by device mac address. */ + ETH_CONVERT_MODE_CLONE = 2, /* Single client support, dispatch to AP by client's mac address. */ + ETH_CONVERT_MODE_HYBRID = 3, /* Multiple client supprot, dispatch to AP by client's mac address. */ +} ETH_CONVERT_MODE; + +typedef struct _ETH_CONVERT_STRUCT_ { + UCHAR EthCloneMac[MAC_ADDR_LEN]; /*Only meanful when ECMode = Clone/Hybrid mode. */ + UCHAR ECMode; /* 0 = Disable, 1 = Dongle mode, 2 = Clone mode, 3 = Hybrid mode. */ + BOOLEAN CloneMacVaild; /* 1 if the CloneMac is valid for connection. 0 if not valid. */ +/* UINT32 nodeCount; // the number of nodes which connect to Internet via us. */ + UCHAR SSIDStr[MAX_LEN_OF_SSID]; + UCHAR SSIDStrLen; + BOOLEAN macAutoLearn; /*0: disabled, 1: enabled. */ +} ETH_CONVERT_STRUCT; +#endif /* ETH_CONVERT_SUPPORT */ + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT +/* Video Mode related configuration */ +typedef struct _AP_VIDEO_CONFIG { + BOOLEAN Enable; + BOOLEAN ClassifierEnable; + BOOLEAN HighTxMode; + UCHAR TxPwr; + BOOLEAN VideoMCSEnable; + UCHAR VideoMCS; + UCHAR TxBASize; + BOOLEAN TxLifeTimeMode; /* 1: Packet Life Time mode, 0: Retry Limit mode */ + UCHAR TxLifeTime; + UINT16 TxRetryLimit; +} AP_VIDEO_STRUCT, *PAP_VIDEO_STRUCT; + +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +/*************************************************************************** + * AP related data structures + **************************************************************************/ +/* AUTH-RSP State Machine Aux data structure */ +typedef struct _AP_MLME_AUX { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + CHAR Challenge[CIPHER_TEXT_LEN]; +} AP_MLME_AUX, *PAP_MLME_AUX; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef ADHOC_WPA2PSK_SUPPORT +typedef struct _FOUR_WAY_HANDSHAKE_PROFILE { + UCHAR ANonce[LEN_KEY_DESC_NONCE]; + UCHAR SNonce[LEN_KEY_DESC_NONCE]; + UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; + UCHAR PTK[64]; + UINT8 WpaState; + UCHAR MsgType; + RALINK_TIMER_STRUCT MsgRetryTimer; + UCHAR MsgRetryCounter; +} FOUR_WAY_HANDSHAKE_PROFILE, *PFOUR_WAY_HANDSHAKE_PROFILE; +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + +typedef struct _MAC_TABLE_ENTRY { + /* + 0:Invalid, + Bit 0: AsCli, Bit 1: AsWds, Bit 2: AsAPCLI, + Bit 3: AsMesh, Bit 4: AsDls, Bit 5: AsTDls + */ + UINT32 EntryType; + UINT32 ent_status; + struct wifi_dev *wdev; + PVOID pAd; + struct _MAC_TABLE_ENTRY *pNext; + + /* + A bitmap of BOOLEAN flags. each bit represent an operation status of a particular + BOOLEAN control, either ON or OFF. These flags should always be accessed via + CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros. + see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED + */ + ULONG ClientStatusFlags; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode; /* For transmit phy setting in TXWI. */ + HTTRANSMIT_SETTING MinHTPhyMode; + +/* + wcid: + + tr_tb_idx: + + func_tb_idx used to indicate following index: + in ApCfg.ApCliTab + in pAd->MeshTab + in WdsTab.MacTab + + apidx: should remove this +*/ + UCHAR wcid; + UCHAR tr_tb_idx; + UCHAR func_tb_idx; + UCHAR apidx; /* MBSS number */ + + BOOLEAN isCached; + + BOOLEAN isRalink; + BOOLEAN bIAmBadAtheros; /* Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. */ +#ifdef SMART_MESH + BOOLEAN bHyperFiPeer; /* Determine If peer is Hyper-Fi device */ + BOOLEAN bSupportSmartMesh; /* Determine If own smart mesh capability */ + BOOLEAN bEnableSmartMesh; /* Determine If own smart mesh feature each other */ + UCHAR CliPktStatTxIdx; /* Record current tx index for client packet statistics */ + UCHAR CliPktStatRxIdx; /* Record current rx index for client packet statistics */ + CLINET_PKT_STATS_INFO CliPktStat[MAX_LAST_PKT_STATS]; /* Record last packet info of specified client */ +#endif /* SMART_MESH */ +#ifdef MWDS + UCHAR MWDSEntry; /* Determine if this entry act which MWDS role */ + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ + BOOLEAN bEnableMWDS; /* Determine If do 3-address to 4-address */ +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + BOOLEAN bSupportHiddenWPS; /* Determine If own Hidden WPS capability */ + BOOLEAN bRunningHiddenWPS; /* Determine If HiddenWPS is running now */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + UCHAR Addr[MAC_ADDR_LEN]; +#ifdef CONFIG_AP_SUPPORT + MULTISSID_STRUCT *pMbss; +#endif /* CONFIG_AP_SUPPORT */ + + /* + STATE MACHINE Status + */ + USHORT Aid; /* in range 1~2007, with bit 14~15 = b'11, e.g., 0xc001~0xc7d7 */ + SST Sst; + AUTH_STATE AuthState; /* for SHARED KEY authentication state machine used only */ + +#ifdef RT_CFG80211_P2P_SUPPORT + CFG_P2P_ENTRY_PARM CFGP2pInfo; +#endif /* RT_CFG80211_SUPPORT */ +#ifdef WFD_SUPPORT + BOOLEAN bWfdClient; +#endif /* WFD_SUPPORT */ + +#ifdef VENDOR_FEATURE1_SUPPORT + /* total 128B, use UINT32 to avoid alignment problem */ + UINT32 HeaderBuf[32]; /* (total 128B) TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP */ + + UCHAR HdrPadLen; /* recording Header Padding Length; */ + UCHAR MpduHeaderLen; + UINT16 Protocol; +#endif /* VENDOR_FEATURE1_SUPPORT */ + + USHORT TxSeq[NUM_OF_TID]; + USHORT NonQosDataSeq; + INT TxBarSeq[NUM_OF_TID]; + + /* Rx status related parameters */ + UCHAR LastRssi; + RSSI_SAMPLE RssiSample; + UINT32 LastTxRate; + UINT32 LastRxRate; + SHORT freqOffset; /* Last RXWI FOFFSET */ + SHORT freqOffsetValid; /* Set when freqOffset field has been updated */ + +#ifdef SMART_MESH_MONITOR + RSSI_SAMPLE MgmtRssiSample; + UINT32 LastMgmtRxRate; + UCHAR MonitorWCID; +#endif /* SMART_MESH_MONITOR */ + +#ifdef CONFIG_AP_SUPPORT +#define MAX_LAST_DATA_RSSI_LEN 5 + CHAR LastDataRssi[MAX_LAST_DATA_RSSI_LEN]; + CHAR curLastDataRssiIndex; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + USHORT NoBADataCountDown; + + UINT32 CachedBuf[16]; /* UINT (4 bytes) for alignment */ +#endif /* DOT11_N_SUPPORT */ + + + /* WPA/WPA2 4-way database */ + UCHAR EnqueueEapolStartTimerRunning; /* Enqueue EAPoL-Start for triggering EAP SM */ + RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; /* A timer which enqueue EAPoL-Start for triggering PSK SM */ +#ifdef ADHOC_WPA2PSK_SUPPORT + FOUR_WAY_HANDSHAKE_PROFILE WPA_Supplicant; + FOUR_WAY_HANDSHAKE_PROFILE WPA_Authenticator; + CIPHER_KEY RxGTK; + BOOLEAN bPeerHigherMAC; +#ifdef IWSC_SUPPORT + BOOLEAN bUpdateInfoFromPeerBeacon; +#endif /* IWSC_SUPPORT */ +#endif /* ADHOC_WPA2PSK_SUPPORT */ + +#ifdef IWSC_SUPPORT + BOOLEAN bIWscSmpbcAccept; +#endif /* IWSC_SUPPORT */ + +#ifdef DROP_MASK_SUPPORT + RALINK_TIMER_STRUCT dropmask_timer; +#endif /* DROP_MASK_SUPPORT */ + +#ifdef PS_ENTRY_MAITENANCE + UINT8 continuous_ps_count; +#endif /* PS_ENTRY_MAITENANCE */ + + /* record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB */ + UCHAR CMTimerRunning; + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + UCHAR ANonce[LEN_KEY_DESC_NONCE]; + UCHAR SNonce[LEN_KEY_DESC_NONCE]; + UCHAR R_Counter[LEN_KEY_DESC_REPLAY]; + UCHAR PTK[64]; + UCHAR ReTryCounter; + RALINK_TIMER_STRUCT RetryTimer; + NDIS_802_11_AUTHENTICATION_MODE AuthMode; /* This should match to whatever microsoft defined */ + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + UINT8 WpaState; + UINT8 GTKState; + USHORT PortSecured; + BOOLEAN AllowInsPTK; + UCHAR LastGroupKeyId; + UCHAR LastGTK[MAX_LEN_GTK]; + UCHAR LastTK[LEN_TK]; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + CIPHER_KEY PairwiseKey; + INT PMKID_CacheIdx; + UCHAR PMKID[LEN_PMKID]; + UCHAR NegotiatedAKM[LEN_OUI_SUITE]; /* It indicate the negotiated AKM suite */ + +#ifdef WAPI_SUPPORT + UCHAR usk_id; /* unicast key index for WPI */ +#endif /* WAPI_SUPPORT */ + + UCHAR bssid[MAC_ADDR_LEN]; + BOOLEAN IsReassocSta; /* Indicate whether this is a reassociation procedure */ + ULONG NoDataIdleCount; + ULONG AssocDeadLine; + UINT16 StationKeepAliveCount; /* unit: second */ + USHORT CapabilityInfo; + UCHAR PsMode; + UCHAR FlgPsModeIsWakeForAWhile; /* wake up for a while until a condition */ + UCHAR VirtualTimeout; /* peer power save virtual timeout */ + ULONG PsQIdleCount; + QUEUE_HEADER PsQueue; + +#ifdef WDS_SUPPORT + BOOLEAN LockEntryTx; /* TRUE = block to WDS Entry traffic, FALSE = not. */ +#endif /* WDS_SUPPORT */ + +/* + wdev_idx used to indicate following index: + in ApCfg.ApCliTab + in pAd->MeshTab + in WdsTab.MacTab +*/ + UCHAR wdev_idx; +#ifdef QOS_DLS_SUPPORT +#ifdef CONFIG_STA_SUPPORT + UCHAR MatchDlsEntryIdx; /* indicate the index in pAd->StaCfg.DLSEntry */ +#endif /* CONFIG_STA_SUPPORT */ + BOOLEAN bDlsInit; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bReptCli; + BOOLEAN bReptEthCli; + UCHAR MatchReptCliIdx; + UCHAR ReptCliAddr[MAC_ADDR_LEN]; + ULONG ReptCliIdleCount; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + UINT32 StaConnectTime; /* the live time of this station since associated with AP */ + UINT32 StaIdleTimeout; /* idle timeout per entry */ + +#ifdef UAPSD_SUPPORT + /* these UAPSD states are used on the fly */ + /* 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO */ + BOOLEAN bAPSDCapablePerAC[4]; /* for trigger-enabled */ + BOOLEAN bAPSDDeliverEnabledPerAC[4]; /* for delivery-enabled */ + + + UCHAR MaxSPLength; + + BOOLEAN bAPSDAllAC; /* 1: all AC are delivery-enabled U-APSD */ + + QUEUE_HEADER UAPSDQueue[WMM_NUM_OF_AC]; /* queue for each U-APSD */ + USHORT UAPSDQIdleCount; /* U-APSD queue timeout */ + + PQUEUE_ENTRY pUAPSDEOSPFrame; /* the last U-APSD frame */ + USHORT UAPSDTxNum; /* total U-APSD frame number */ + BOOLEAN bAPSDFlagEOSPOK; /* 1: EOSP frame is tx by ASIC */ + BOOLEAN bAPSDFlagSPStart; /* 1: SP is started */ + + /* need to use unsigned long, because time parameters in OS is defined as + unsigned long */ + unsigned long UAPSDTimeStampLast; /* unit: 1000000/OS_HZ */ + BOOLEAN bAPSDFlagSpRoughUse; /* 1: use rough SP (default: accurate) */ + + /* we will set the flag when PS-poll frame is received and + clear it when statistics handle. + if the flag is set when PS-poll frame is received then calling + statistics handler to clear it. */ + BOOLEAN bAPSDFlagLegacySent; /* 1: Legacy PS sent but yet statistics handle */ + +#endif /* UAPSD_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + UINT32 StreamModeMACReg; /* MAC reg used to control stream mode for this client. 0=>No stream mode */ +#endif /* STREAM_MODE_SUPPORT */ + + UINT FIFOCount; + UINT DebugFIFOCount; + UINT DebugTxCount; + +/* ==================================================== */ + enum RATE_ADAPT_ALG rateAlg; + UCHAR RateLen; + UCHAR MaxSupportedRate; + BOOLEAN bAutoTxRateSwitch; + UCHAR CurrTxRate; + UCHAR CurrTxRateIndex; + UCHAR lastRateIdx; + UCHAR *pTable; /* Pointer to this entry's Tx Rate Table */ + + UCHAR lowTrafficCount; + UCHAR LowTrafficTag; +#ifdef NEW_RATE_ADAPT_SUPPORT + UCHAR fewPktsCnt; + BOOLEAN perThrdAdj; + UCHAR mcsGroup;/* the mcs group to be tried */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + AGS_CONTROL AGSCtrl; /* AGS control */ +#endif /* AGS_SUPPORT */ + + /* to record the each TX rate's quality. 0 is best, the bigger the worse. */ + USHORT TxQuality[MAX_TX_RATE_INDEX + 1]; + BOOLEAN fLastSecAccordingRSSI; + UCHAR LastSecTxRateChangeAction; /* 0: no change, 1:rate UP, 2:rate down */ + CHAR LastTimeTxRateChangeAction; /* Keep last time value of LastSecTxRateChangeAction */ + ULONG LastTxOkCount; /* TxSuccess count in last Rate Adaptation interval */ + UCHAR LastTxPER; /* Tx PER in last Rate Adaptation interval */ + UCHAR PER[MAX_TX_RATE_INDEX + 1]; + UINT32 CurrTxRateStableTime; /* # of second in current TX rate */ + UCHAR TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ + + UCHAR SupportRateMode; /* 1: CCK 2:OFDM 4: HT, 8:VHT */ + BOOLEAN SupportCCKMCS[MAX_LEN_OF_CCK_RATES]; + BOOLEAN SupportOFDMMCS[MAX_LEN_OF_OFDM_RATES]; +#ifdef DOT11_N_SUPPORT + BOOLEAN SupportHTMCS[MAX_LEN_OF_HT_RATES]; +#ifdef DOT11_VHT_AC + BOOLEAN SupportVHTMCS[MAX_LEN_OF_VHT_RATES]; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef PEER_DELBA_TX_ADAPT + UINT32 bPeerDelBaTxAdaptEn; + RALINK_TIMER_STRUCT DelBA_tx_AdaptTimer; +#endif /* PEER_DELBA_TX_ADAPT */ + +#ifdef MFB_SUPPORT + UCHAR lastLegalMfb; /* last legal mfb which is used to set rate */ + BOOLEAN isMfbChanged; /* purpose: true when mfb has changed but the new mfb is not adopted for Tx */ + struct _RTMP_RA_LEGACY_TB *LegalMfbRS; + BOOLEAN fLastChangeAccordingMfb; + NDIS_SPIN_LOCK fLastChangeAccordingMfbLock; +/* Tx MRQ */ + BOOLEAN toTxMrq; + UCHAR msiToTx, mrqCnt; /*mrqCnt is used to count down the inverted-BF mrq to be sent */ +/* Rx mfb */ + UCHAR pendingMfsi; +/* Tx MFB */ + BOOLEAN toTxMfb; + UCHAR mfbToTx; + UCHAR mfb0, mfb1; +#endif /* MFB_SUPPORT */ +#ifdef TXBF_SUPPORT + UCHAR TxSndgType; + NDIS_SPIN_LOCK TxSndgLock; + +/* ETxBF */ + UCHAR bfState; + UCHAR sndgMcs; + UCHAR sndgBW; + UCHAR sndg0Mcs; + INT sndg0Snr0, sndg0Snr1, sndg0Snr2; + +#ifdef ETXBF_EN_COND3_SUPPORT + UCHAR bestMethod; + UCHAR sndgRateIdx; + UCHAR bf0Mcs, sndg0RateIdx, bf0RateIdx; + UCHAR sndg1Mcs, bf1Mcs, sndg1RateIdx, bf1RateIdx; + INT sndg1Snr0, sndg1Snr1, sndg1Snr2; +#endif /* ETXBF_EN_COND3_SUPPORT */ + UCHAR noSndgCnt; + UCHAR eTxBfEnCond; + UCHAR noSndgCntThrd, ndpSndgStreams; + UCHAR iTxBfEn; + RALINK_TIMER_STRUCT eTxBfProbeTimer; + + BOOLEAN phyETxBf; /* True=>Set ETxBF bit in PHY rate */ + BOOLEAN phyITxBf; /* True=>Set ITxBF bit in PHY rate */ + UCHAR lastNonBfRate; /* Last good non-BF rate */ + BOOLEAN lastRatePhyTxBf; /* For Quick Check. True if last rate was BF */ + USHORT BfTxQuality[MAX_TX_RATE_INDEX + 1]; /* Beamformed TX Quality */ + + COUNTER_TXBF TxBFCounters; /* TxBF Statistics */ + UINT LastETxCount; /* Used to compute %BF statistics */ + UINT LastITxCount; + UINT LastTxCount; +#endif /* TXBF_SUPPORT */ + +#ifdef VHT_TXBF_SUPPORT + UINT8 snd_dialog_token; +#ifdef SOFT_SOUNDING + BOOLEAN snd_reqired; + HTTRANSMIT_SETTING snd_rate; +#endif /* SOFT_SOUNDING */ +#endif /* VHT_TXBF_SUPPORT */ + + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 OneSecRxLGICount; /* unicast-to-me Long GI count */ + UINT32 OneSecRxSGICount; /* unicast-to-me Short GI count */ + UINT32 TotalTxFailCount; + +#ifdef DYNAMIC_VGA_SUPPORT + UINT32 DyncVgaOneSecTxCount; + UINT32 DyncVgaOneSecRxCount; +#endif + UINT32 StatTxRetryOkCount; + UINT32 StatTxFailCount; + + INT32 DownTxMCSRate[NUM_OF_SWFB]; + UINT32 LowPacket; + UCHAR LastSaveRateIdx; + +#ifdef FIFO_EXT_SUPPORT + UINT32 fifoTxSucCnt; + UINT32 fifoTxRtyCnt; + BOOLEAN bUseHwFifoExt; /* Tx counter is by hardware FIFO Ext */ + UCHAR hwFifoExtIdx; /* The index of hardware Tx Counter. This variable is valid only if bUseHwFifoExt is TRUE. */ +#endif /* FIFO_EXT_SUPPORT */ + + UINT32 ContinueTxFailCnt; + ULONG TimeStamp_toTxRing; + +/*==================================================== */ + EXT_CAP_INFO_ELEMENT ext_cap; + +#ifdef DOT11_N_SUPPORT + HT_CAPABILITY_IE HTCapability; + + USHORT RXBAbitmap; /* fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format */ + USHORT TXBAbitmap; /* This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI */ + USHORT TXAutoBAbitmap; + USHORT BADeclineBitmap; + USHORT BARecWcidArray[NUM_OF_TID]; /* The mapping wcid of recipient session. if RXBAbitmap bit is masked */ + USHORT BAOriWcidArray[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + USHORT BAOriSequence[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + + UCHAR MpduDensity; + UCHAR MaxRAmpduFactor; + UCHAR VhtMaxRAmpduFactor; + UCHAR AMsduSize; + UCHAR MmpsMode; /* MIMO power save mode. */ + +#ifdef DOT11N_DRAFT3 + UCHAR BSS2040CoexistenceMgmtSupport; + BOOLEAN bForty_Mhz_Intolerant; +#endif /* DOT11N_DRAFT3 */ + +#ifdef DOT11_VHT_AC + VHT_CAP_IE vht_cap_ie; + + /* only take effect if ext_cap.operating_mode_notification = 1 */ + BOOLEAN force_op_mode; + OPERATING_MODE operating_mode; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + UCHAR BssTransitionManmtSupport; + UCHAR DMSSupport; + BOOLEAN Beclone; +#endif /* DOT11V_WNM_SUPPORT */ + + BOOLEAN bWscCapable; + UCHAR Receive_EapolStart_EapRspId; + + UINT32 TXMCSExpected[MAX_FAST_MCS_SET]; + UINT32 TXMCSSuccessful[MAX_FAST_MCS_SET]; + UINT32 TXMCSFailed[MAX_FAST_MCS_SET]; + UINT32 TXMCSAutoFallBack[MAX_FAST_MCS_SET][MAX_FAST_MCS_SET]; + + CHAR RX_RSSI_MCS; + +#ifdef CONFIG_STA_SUPPORT + ULONG LastBeaconRxTime; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WAPI_SUPPORT + BOOLEAN WapiUskRekeyTimerRunning; + RALINK_TIMER_STRUCT WapiUskRekeyTimer; + UINT32 wapi_usk_rekey_cnt; +#endif /* WAPI_SUPPORT */ + +#ifdef DELAYED_TCP_ACK + struct sk_buff_head ack_queue; + RALINK_TIMER_STRUCT QueueAckTimer; + BOOLEAN QueueAckTimerRunning; +#endif /* DELAYED_TCP_ACK */ + + +#ifdef DOT11R_FT_SUPPORT + FT_MDIE_INFO MdIeInfo; + FT_FTIE_INFO FtIeInfo; + + UINT8 InitialMDIE[5]; + UINT8 InitialFTIE[256]; + UINT InitialFTIE_Len; + + UCHAR FT_PMK_R0[32]; + UCHAR FT_PMK_R0_NAME[16]; + UCHAR FT_PMK_R1[32]; + UCHAR FT_PMK_R1_NAME[16]; + UCHAR PTK_NAME[16]; + + UCHAR FT_UCipher[4]; + UCHAR FT_Akm[4]; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_EN_CAP_IE RrmEnCap; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + UCHAR PmfTxTsc[LEN_WPA_TSC]; + UCHAR PmfRxTsc[LEN_WPA_TSC]; + RALINK_TIMER_STRUCT SAQueryTimer; + RALINK_TIMER_STRUCT SAQueryConfirmTimer; + UCHAR SAQueryStatus; + USHORT TransactionID; +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bBSSMantSTASupport; + BOOLEAN bDMSSTASupport; + UCHAR BTMQueryDialogToken; + BOOLEAN DisassociationImminent; + BOOLEAN BSSTerminationIncluded; + RALINK_TIMER_STRUCT DisassocTimer; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + LARGE_INTEGER TxPackets; + LARGE_INTEGER RxPackets; + ULONG TxBytes; + ULONG RxBytes; + ULONG OneSecTxBytes; + ULONG OneSecRxBytes; + UINT32 RxDecryptErrCnt; +#endif /* CONFIG_AP_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + UINT16 TdlsTxFailCount; + UINT32 TdlsKeyLifeTimeCount; + UCHAR MatchTdlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry +#endif // defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) // + + + ULONG ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ +#ifdef CUSTOMER_DCC_FEATURE +#ifdef MBSS_802_11_STATISTICS + UINT32 RxCount; + UINT32 TxCount; + UINT32 ReceivedByteCount; + UINT32 TransmittedByteCount; + UINT32 RxErrorCount; + UINT32 RxDropCount; + UINT32 TxErrorCount; + UINT32 TxDropCount; + UINT32 TxRetriedPktCount; + UINT64 ChannelUseTime; +#endif +#endif + +#ifdef CONFIG_HOTSPOT_R2 + UINT16 BTMDisassocCount; + UCHAR IsWNMReqValid; + UCHAR IsBTMReqValid; + UCHAR QosMapSupport; + UCHAR DscpExceptionCount; + USHORT DscpRange[8]; + USHORT DscpException[21]; + struct wnm_req_data *ReqData; + struct btm_req_data *ReqbtmData; + struct _sta_hs_info hs_info; + UCHAR IsKeep; +#endif /* CONFIG_HOTSPOT_R2 */ +#ifdef PN_UC_REPLAY_DETECTION_SUPPORT + UINT64 CCMP_UC_PN[NUM_OF_TID]; +#endif /* PN_UC_REPLAY_DETECTION_SUPPORT */ + UINT64 CCMP_BC_PN; + BOOLEAN AllowUpdateRSC; + BOOLEAN init_ccmp_bc_pn_passed; +} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; + +#ifdef DELAYED_TCP_ACK +VOID RTMPQueueAckPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* DELAYED_TCP_ACK */ + +typedef enum _MAC_ENT_STATUS_{ + /* fAnyStationInPsm */ + MAC_TB_ANY_PSM = 0x1, + /* + fAnyStationBadAtheros + Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. + */ + MAC_TB_ANY_ATH = 0x2, + /* + fAnyTxOPForceDisable + Check if it is necessary to disable BE TxOP + */ + MAC_TB_FORCE_TxOP = 0x4, + /* + fAllStationAsRalink + Check if all stations are ralink-chipset + */ + MAC_TB_ALL_RALINK = 0x8, + /* + fAnyStationIsLegacy + Check if I use legacy rate to transmit to my BSS Station + */ + MAC_TB_ANY_LEGACY = 0x10, + /* + fAnyStationNonGF + Check if any Station can't support GF + */ + MAC_TB_ANY_NON_GF = 0x20, + /* fAnyStation20Only */ + MAC_TB_ANY_HT20 = 0x40, + /* + fAnyStationMIMOPSDynamic + Check if any Station is MIMO Dynamic + */ + MAC_TB_ANY_MIMO_DYNAMIC = 0x80, + /* + fAnyBASession + Check if there is BA session. Force turn on RTS/CTS + */ + MAC_TB_ANY_BA = 0x100, + /* fAnyStaFortyIntolerant */ + MAC_TB_ANY_40_INTOlERANT = 0x200, + /* + fAllStationGainGoodMCS + Check if all stations more than MCS threshold + */ + MAC_TB_ALL_GOOD_MCS = 0x400, + /* + fAnyStationIsHT + Check if still has any station set the Intolerant bit on! + */ + MAC_TB_ANY_HT = 0x800, + /* fAnyWapiStation */ + MAC_TB_ANY_WAPI = 0x1000, +}MAC_ENT_STATUS; + +typedef struct _MAC_TABLE { + MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; + + MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + USHORT Size; + QUEUE_HEADER McastPsQueue; + ULONG PsQIdleCount; + BOOLEAN fAnyStationInPsm; + BOOLEAN fAnyStationBadAtheros; /* Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. */ + BOOLEAN fAnyTxOPForceDisable; /* Check if it is necessary to disable BE TxOP */ + BOOLEAN fAllStationAsRalink; /* Check if all stations are ralink-chipset */ +#ifdef DOT11_N_SUPPORT + BOOLEAN fAnyStationIsLegacy; /* Check if I use legacy rate to transmit to my BSS Station/ */ + BOOLEAN fAnyStationNonGF; /* Check if any Station can't support GF. */ + BOOLEAN fAnyStation20Only; /* Check if any Station can't support GF. */ + BOOLEAN fAnyStationMIMOPSDynamic; /* Check if any Station is MIMO Dynamic */ + BOOLEAN fAnyBASession; /* Check if there is BA session. Force turn on RTS/CTS */ +#ifdef DOT11N_DRAFT3 + BOOLEAN fAnyStaFortyIntolerant; /* Check if still has any station set the Intolerant bit on! */ +#endif /* DOT11N_DRAFT3 */ + BOOLEAN fAllStationGainGoodMCS; /* Check if all stations more than MCS threshold */ + +#ifdef CONFIG_AP_SUPPORT + BOOLEAN fAnyStationIsHT; /* Check if there is 11n STA. Force turn off AP MIMO PS */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef WAPI_SUPPORT + BOOLEAN fAnyWapiStation; +#endif /* WAPI_SUPPORT */ + + USHORT MsduLifeTime; /* life time for PS packet */ + BOOLEAN fMcastPsQEnable; +} MAC_TABLE, *PMAC_TABLE; + +#ifdef CONFIG_SNIFFER_SUPPORT +#define MONITOR_MODE_OFF 0 +#define MONITOR_MODE_REGULAR_RX 1 +#define MONITOR_MODE_FULL 2 +#define MONITOR_MODE_FULL_NO_CLONE 3 + + +typedef struct _MONITOR_STRUCT +{ + struct wifi_dev monitor_wdev; + INT current_monitor_mode; + BOOLEAN monitor_initiated; +}MONITOR_STRUCT; +#endif /*CONFIG_SNIFFER_SUPPORT*/ + + +#ifdef CONFIG_AP_SUPPORT +/*************************************************************************** + * AP WDS related data structures + **************************************************************************/ +#ifdef WDS_SUPPORT +typedef struct _WDS_COUNTER { + LARGE_INTEGER ReceivedByteCount; + LARGE_INTEGER TransmittedByteCount; + ULONG ReceivedFragmentCount; + ULONG TransmittedFragmentCount; + ULONG RxErrors; + ULONG MulticastReceivedFrameCount; +} WDS_COUNTER, *PWDS_COUNTER; + +typedef struct _WDS_ENTRY { + BOOLEAN Valid; + UCHAR Addr[MAC_ADDR_LEN]; + ULONG NoDataIdleCount; + struct _WDS_ENTRY *pNext; +} WDS_ENTRY, *PWDS_ENTRY; + +typedef struct _WDS_TABLE_ENTRY { + USHORT Size; + UCHAR WdsAddr[MAC_ADDR_LEN]; + WDS_ENTRY *Hash[HASH_TABLE_SIZE]; + WDS_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + USHORT TxQuality[MAX_LEN_OF_SUPPORTED_RATES]; + USHORT OneSecTxOkCount; + USHORT OneSecTxRetryOkCount; + USHORT OneSecTxFailCount; + ULONG CurrTxRateStableTime; /* # of second in current TX rate */ + UCHAR TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ +} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY; + + +typedef struct _RT_802_11_WDS_ENTRY { + struct wifi_dev wdev; + UCHAR Valid; + UCHAR PeerWdsAddr[MAC_ADDR_LEN]; + UCHAR MacTabMatchWCID; /* ASIC */ + UCHAR KeyIdx; + CIPHER_KEY WdsKey; + + WDS_COUNTER WdsCounter; +} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY; + +typedef struct _WDS_TABLE { + UCHAR Mode; + UINT Size; + RT_802_11_WDS_ENTRY WdsEntry[MAX_WDS_ENTRY]; +} WDS_TABLE, *PWDS_TABLE; +#endif /* WDS_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +typedef struct _REPEATER_CLIENT_ENTRY { + //BOOLEAN bValid; + BOOLEAN CliEnable; + BOOLEAN CliValid; + BOOLEAN bEthCli; + UCHAR MatchApCliIdx; + UCHAR MatchLinkIdx; + UCHAR MacTabWCID; + UCHAR CliConnectState; /* 0: disconnect 1: connecting 2: connected */ + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + + RALINK_TIMER_STRUCT ApCliAssocTimer, ApCliAuthTimer; + + USHORT AuthReqCnt; + USHORT AssocReqCnt; + ULONG CliTriggerTime; + + /* For WPA countermeasures */ + ULONG LastMicErrorTime; /* record last MIC error time */ + BOOLEAN bBlockAssoc; /* Block associate attempt for 60 seconds after counter measure occurred. */ + + UCHAR OriginalAddress[MAC_ADDR_LEN]; + UCHAR CurrentAddress[MAC_ADDR_LEN]; + PVOID pAd; + struct _REPEATER_CLIENT_ENTRY *pNext; +} REPEATER_CLIENT_ENTRY, *PREPEATER_CLIENT_ENTRY; + +typedef struct _REPEATER_CLIENT_ENTRY_MAP { + PREPEATER_CLIENT_ENTRY pReptCliEntry; + struct _REPEATER_CLIENT_ENTRY_MAP *pNext; +} REPEATER_CLIENT_ENTRY_MAP, *PREPEATER_CLIENT_ENTRY_MAP; + +typedef struct _INVAILD_TRIGGER_MAC_ENTRY { + UCHAR MacAddr[MAC_ADDR_LEN]; + BOOLEAN bInsert; + struct _INVAILD_TRIGGER_MAC_ENTRY *pNext; +} INVAILD_TRIGGER_MAC_ENTRY, *PINVAILD_TRIGGER_MAC_ENTRY; + +typedef struct _REPEATER_CTRL_STRUCT { + INVAILD_TRIGGER_MAC_ENTRY RepeaterInvaildEntry[32]; + INVAILD_TRIGGER_MAC_ENTRY *ReptInvaildHash[HASH_TABLE_SIZE]; + UCHAR ReptInVaildMacSize; +} REPEATER_CTRL_STRUCT, *PREPEATER_CTRL_STRUCT; + +typedef struct _REPEATER_ADAPTER_DATA_TABLE { + bool Enabled; + void *EntryLock; + void **CliHash; + void **MapHash; + void *Wdev_ifAddr; +} REPEATER_ADAPTER_DATA_TABLE; + +#endif /* MAC_REPEATER_SUPPORT */ + +/*************************************************************************** + * AP APCLI related data structures + **************************************************************************/ +typedef struct _APCLI_COUNTER { + LARGE_INTEGER ReceivedByteCount; + LARGE_INTEGER TransmittedByteCount; + ULONG ReceivedFragmentCount; + ULONG TransmittedFragmentCount; + ULONG RxErrors; + ULONG MulticastReceivedFrameCount; +} APCLI_COUNTER, *PAPCLI_COUNTER; + +typedef struct _APCLI_STRUCT { + struct wifi_dev wdev; + + BOOLEAN Enable; /* Set it as 1 if the apcli interface was configured to "1" or by iwpriv cmd "ApCliEnable" */ + BOOLEAN Valid; /* Set it as 1 if the apcli interface associated success to remote AP. */ + + MLME_AUX MlmeAux; /* temporary settings used during MLME state machine */ + + UCHAR MacTabWCID; /*WCID value, which point to the entry of ASIC Mac table. */ + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + +#ifdef APCLI_CONNECTION_TRIAL + UCHAR TrialCh; /* the channel that Apcli interface will try to connect the rootap locates */ + RALINK_TIMER_STRUCT TrialConnectTimer; + RALINK_TIMER_STRUCT TrialConnectPhase2Timer; + RALINK_TIMER_STRUCT TrialConnectRetryTimer; + MAC_TABLE_ENTRY oldRootAP; + USHORT NewRootApRetryCnt; + UCHAR ifIndex; + PVOID pAd; +#endif /* APCLI_CONNECTION_TRIAL */ + + UCHAR CfgSsidLen; + CHAR CfgSsid[MAX_LEN_OF_SSID]; + UCHAR CfgApCliBssid[MAC_ADDR_LEN]; + + ULONG ApCliRcvBeaconTime; + ULONG ApCliLinkUpTime; + USHORT ApCliBeaconPeriod; + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + ULONG WpaPskCurrState; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + USHORT ProbeReqCnt; + USHORT ApCliSiteSurveyPeriod; + BOOLEAN AutoConnectFlag; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + USHORT AuthReqCnt; + USHORT AssocReqCnt; + + UCHAR MpduDensity; + BOOLEAN OpenWEPErrPktChk; /* See if Open WEP check enabled */ + ULONG OpenWEPErrPktCnt; /* Error Unicast Packet Count */ + ULONG OpenWEPErrMCPktCnt; /* Error Multicast Packet Count */ + + /* + Security segment + */ + /* Add to support different cipher suite for WPA2/WPA mode */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Multicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher suite */ + BOOLEAN bMixCipher; /* Indicate current Pair & Group use different cipher suites */ + USHORT RsnCapability; + + UCHAR PSK[100]; /* reserve PSK key material */ + UCHAR PSKLen; + UCHAR PMK[32]; /* WPA PSK mode PMK */ + UCHAR PTK[64]; /* WPA PSK mode PTK */ + UCHAR GTK[32]; /* GTK from authenticator */ + + /*CIPHER_KEY PairwiseKey; */ + CIPHER_KEY SharedKey[SHARE_KEY_NUM]; + + /* store RSN_IE built by driver */ + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; /* The content saved here should be convert to little-endian format. */ + UCHAR RSNIE_Len; + + /* For WPA countermeasures */ + ULONG LastMicErrorTime; /* record last MIC error time */ + ULONG MicErrCnt; /* Should be 0, 1, 2, then reset to zero (after disassoiciation). */ + BOOLEAN bBlockAssoc; /* Block associate attempt for 60 seconds after counter measure occurred. */ + + /* For WPA-PSK supplicant state */ + UCHAR ReplayCounter[8]; + UCHAR SNonce[32]; /* SNonce for WPA-PSK */ + UCHAR GNonce[32]; /* GNonce for WPA-PSK from authenticator */ + +#ifdef WPA_SUPPLICANT_SUPPORT + WPA_SUPPLICANT_INFO wpa_supplicant_info; + + BOOLEAN bScanReqIsFromWebUI; + BSSID_INFO SavedPMK[PMKID_NO]; + UINT SavedPMKNum; /* Saved PMKID number */ + BOOLEAN bConfigChanged; + NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; + USHORT ReqVarIELen; /* Length of next VIE include EID & Length */ + UCHAR ReqVarIEs[MAX_VIE_LEN]; /* The content saved here should be little-endian format. */ + USHORT ResVarIELen; /* Length of next VIE include EID & Length */ + UCHAR ResVarIEs[MAX_VIE_LEN]; + UCHAR LastSsidLen; /* the actual ssid length in used */ + CHAR LastSsid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + UCHAR LastBssid[MAC_ADDR_LEN]; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + + /* + WPS segment + */ +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; +#endif /* WSC_AP_SUPPORT */ + + /* + Transmitting segment + */ + UCHAR RxMcsSet[16]; + + + PSPOLL_FRAME PsPollFrame; + HEADER_802_11 NullFrame; + + UAPSD_INFO UapsdInfo; + + BOOLEAN bPeerExist; /* TRUE if we hear Root AP's beacon */ + +#ifdef MAC_REPEATER_SUPPORT + REPEATER_CLIENT_ENTRY RepeaterCli[MAX_EXT_MAC_ADDR_SIZE]; + REPEATER_CLIENT_ENTRY_MAP RepeaterCliMap[MAX_EXT_MAC_ADDR_SIZE]; +#endif /* MAC_REPEATER_SUPPORT */ + + APCLI_COUNTER ApCliCounter; +#ifdef SMART_MESH + SMART_MESH_CFG SmartMeshCfg; +#endif /* SMART_MESH */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ + BOOLEAN bEnableMWDS; /* Determine If do 3-address to 4-address */ +#endif /* MWDS */ +} APCLI_STRUCT, *PAPCLI_STRUCT; + + +typedef struct _AP_ADMIN_CONFIG { + USHORT CapabilityInfo; + /* Multiple SSID */ + UCHAR BssidNum; + UCHAR MacMask; + MULTISSID_STRUCT MBSSID[HW_BEACON_MAX_NUM]; + BOOLEAN IsolateInterStaTrafficBTNBSSID; +#ifdef CONFIG_SNIFFER_SUPPORT + UCHAR BssType; /* Infra mode or monitor mode */ +#endif /*CONFIG_SNIFFER_SUPPORT*/ +#ifdef APCLI_SUPPORT + UCHAR ApCliInfRunned; /* Number of ApClient interface which was running. value from 0 to MAX_APCLI_INTERFACE */ + UINT8 ApCliNum; + BOOLEAN FlgApCliIsUapsdInfoUpdated; + APCLI_STRUCT ApCliTab[MAX_APCLI_NUM]; /*AP-client */ +#ifdef APCLI_AUTO_CONNECT_SUPPORT + BOOLEAN ApCliAutoConnectRunning; + BOOLEAN ApCliAutoConnectChannelSwitching; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + NDIS_SPIN_LOCK ReptCliEntryLock; + REPEATER_CLIENT_ENTRY *ReptCliHash[HASH_TABLE_SIZE]; + REPEATER_CLIENT_ENTRY_MAP *ReptMapHash[HASH_TABLE_SIZE]; + UCHAR BridgeAddress[MAC_ADDR_LEN]; + REPEATER_CTRL_STRUCT ReptControl; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef AP_PARTIAL_SCAN_SUPPORT + BOOLEAN bPartialScanning; +#define DEFLAUT_PARTIAL_SCAN_CH_NUM 1 /* Must be move to other place */ + UINT8 PartialScanChannelNum; /* How many channels to scan each time */ + UINT8 LastPartialScanChannel; +#define DEFLAUT_PARTIAL_SCAN_BREAK_TIME 4 /* Period of partial scaning: unit: 100ms *//* Must be move to other place */ + UINT8 PartialScanBreakTime; /* Period of partial scaning: unit: 100ms */ +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#ifdef SMART_MESH + ULONG ScanTime; + UCHAR scan_channel_index; +#endif /* SMART_MESH */ + + /* for wpa */ + RALINK_TIMER_STRUCT CounterMeasureTimer; + + UCHAR CMTimerRunning; + UCHAR BANClass3Data; + LARGE_INTEGER aMICFailTime; + LARGE_INTEGER PrevaMICFailTime; + ULONG MICFailureCounter; + + RSSI_SAMPLE RssiSample; + ULONG NumOfAvgRssiSample; + + BOOLEAN bAutoChannelAtBootup; /* 0: disable, 1: enable */ + ChannelSel_Alg AutoChannelAlg; /* Alg for selecting Channel */ +#ifdef AP_SCAN_SUPPORT + UINT32 ACSCheckTime; /* Periodic timer to trigger Auto Channel Selection (unit: second) */ + UINT32 ACSCheckCount; /* if ACSCheckCount > ACSCheckTime, then do ACS check */ +#endif /* AP_SCAN_SUPPORT */ + BOOLEAN bAvoidDfsChannel; /* 0: disable, 1: enable */ + BOOLEAN bHideSsid; + + /* temporary latch for Auto channel selection */ + ULONG ApCnt; /* max RSSI during Auto Channel Selection period */ + UCHAR AutoChannel_Channel; /* channel number during Auto Channel Selection */ + UCHAR current_channel_index; /* current index of channel list */ + UCHAR AutoChannelSkipListNum; /* number of rejected channel list */ + UCHAR AutoChannelSkipList[10]; + UCHAR DtimCount; /* 0.. DtimPeriod-1 */ + UCHAR DtimPeriod; /* default = 3 */ + UCHAR ErpIeContent; + ULONG LastOLBCDetectTime; + ULONG LastNoneHTOLBCDetectTime; + ULONG LastScanTime; /* Record last scan time for issue BSSID_SCAN_LIST */ + + UCHAR LastSNR0; /* last received BEACON's SNR */ + UCHAR LastSNR1; /* last received BEACON's SNR for 2nd antenna */ +#ifdef DOT11N_SS3_SUPPORT + UCHAR LastSNR2; /* last received BEACON's SNR for 2nd antenna */ +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* dot1x related parameter */ + UINT32 own_ip_addr; + UINT32 retry_interval; + UINT32 session_timeout_interval; + UINT32 quiet_interval; + UCHAR EAPifname[HW_BEACON_MAX_NUM][IFNAMSIZ]; /* indicate as the binding interface for EAP negotiation. */ + UCHAR EAPifname_len[HW_BEACON_MAX_NUM]; + UCHAR PreAuthifname[HW_BEACON_MAX_NUM][IFNAMSIZ]; /* indicate as the binding interface for WPA2 Pre-authentication. */ + UCHAR PreAuthifname_len[HW_BEACON_MAX_NUM]; +#endif /* DOT1X_SUPPORT */ + + /* EDCA parameters to be announced to its local BSS */ + EDCA_PARM BssEdcaParm; + + RALINK_TIMER_STRUCT ApQuickResponeForRateUpTimer; + BOOLEAN ApQuickResponeForRateUpTimerRunning; + +#ifdef IDS_SUPPORT + /* intrusion detection parameter */ + BOOLEAN IdsEnable; + UINT32 AuthFloodThreshold; /* Authentication frame flood threshold */ + UINT32 AssocReqFloodThreshold; /* Association request frame flood threshold */ + UINT32 ReassocReqFloodThreshold; /* Re-association request frame flood threshold */ + UINT32 ProbeReqFloodThreshold; /* Probe request frame flood threshold */ + UINT32 DisassocFloodThreshold; /* Disassociation frame flood threshold */ + UINT32 DeauthFloodThreshold; /* Deauthentication frame flood threshold */ + UINT32 EapReqFloodThreshold; /* EAP request frame flood threshold */ + UINT32 DataFloodThreshold; /* Malicious data frame flood threshold */ + + UINT32 RcvdAuthCount; + UINT32 RcvdAssocReqCount; + UINT32 RcvdReassocReqCount; + UINT32 RcvdProbeReqCount; + UINT32 RcvdDisassocCount; + UINT32 RcvdDeauthCount; + UINT32 RcvdEapReqCount; + UINT32 RcvdMaliciousDataCount; /* Data Frame DDOS */ + + RALINK_TIMER_STRUCT IDSTimer; + BOOLEAN IDSTimerRunning; +#endif /* IDS_SUPPORT */ + + /* Indicate the maximum idle timeout */ + UINT32 StaIdleTimeout; + + ULONG EntryLifeCheck; + +#ifdef IGMP_SNOOP_SUPPORT + BOOLEAN IgmpSnoopEnable; /* 0: disable, 1: enable. */ +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_TAB FtTab; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef CLIENT_WDS + NDIS_SPIN_LOCK CliWdsTabLock; + PCLIWDS_PROXY_ENTRY pCliWdsEntryPool; + LIST_HEADER CliWdsEntryFreeList; + LIST_HEADER CliWdsProxyTb[CLIWDS_HASH_TAB_SIZE]; +#endif /* CLIENT_WDS */ + +#ifdef SMART_MESH + BOOLEAN bDFSAPScanEnable; + BOOLEAN bCliPktStatEnable; /* Determine If enable to record current tx/rx for clinet packet statistics */ + UCHAR CliPktMac[MAC_ADDR_LEN]; /* Determine which one is used for RT_OID_GET_LAST_TX_RX_STATS */ +#endif /* SMART_MESH */ + +#ifdef ROUTING_TAB_SUPPORT + BOOLEAN bRoutingTabInit; + UINT32 RoutingTabFlag; + NDIS_SPIN_LOCK RoutingTabLock; + ROUTING_ENTRY *pRoutingEntryPool; + LIST_HEADER RoutingEntryFreeList; + LIST_HEADER RoutingTab[ROUTING_HASH_TAB_SIZE]; +#endif /* ROUTING_TAB_SUPPORT */ +#ifdef MWDS + BOOLEAN bMWDSAPInit; + NDIS_SPIN_LOCK MWDSConnEntryLock; + DL_LIST MWDSConnEntryList; +#endif /* MWDS */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + UCHAR GreenAPLevel; + BOOLEAN bGreenAPEnable; + BOOLEAN bGreenAPActive; +#endif /* GREENAP_SUPPORT */ + +#endif /* DOT11_N_SUPPORT */ + + UCHAR EntryClientCount; + +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bMACRepeaterEn; + UCHAR MACRepeaterOuiMode; + UINT8 EthApCliIdx; + UCHAR RepeaterCliSize; +#endif /* MAC_REPEATER_SUPPORT */ + UCHAR ChangeTxOpClient; +#ifdef BAND_STEERING + /* + This is used to let user config band steering on/off by profile. + 0: OFF / 1: ON / 2: Auto ONOFF + */ + BOOLEAN BandSteering; + BND_STRG_CLI_TABLE BndStrgTable; +#endif /* BAND_STEERING */ +} AP_ADMIN_CONFIG, *PAP_ADMIN_CONFIG; + +#ifdef IGMP_SNOOP_SUPPORT +typedef enum _IGMP_GROUP_TYPE { + MODE_IS_INCLUDE = 1, + MODE_IS_EXCLUDE, + CHANGE_TO_INCLUDE_MODE, + CHANGE_TO_EXCLUDE_MODE, + ALLOW_NEW_SOURCES, + BLOCK_OLD_SOURCES +} IgmpGroupType; + +typedef enum _MULTICAST_FILTER_ENTRY_TYPE { + MCAT_FILTER_STATIC = 0, + MCAT_FILTER_DYNAMIC, +} MulticastFilterEntryType; + +typedef struct _MEMBER_ENTRY { + struct _MEMBER_ENTRY *pNext; + UCHAR Addr[MAC_ADDR_LEN]; +/* USHORT Aid; */ +} MEMBER_ENTRY, *PMEMBER_ENTRY; + +typedef struct _MULTICAST_FILTER_TABLE_ENTRY { + BOOLEAN Valid; + MulticastFilterEntryType type; /* 0: static, 1: dynamic. */ + UINT lastTime; + PNET_DEV net_dev; + UCHAR Addr[MAC_ADDR_LEN]; + LIST_HEADER MemberList; + struct _MULTICAST_FILTER_TABLE_ENTRY *pNext; +} MULTICAST_FILTER_TABLE_ENTRY, *PMULTICAST_FILTER_TABLE_ENTRY; + +typedef struct _MULTICAST_FILTER_TABLE { + UCHAR Size; + PMULTICAST_FILTER_TABLE_ENTRY + Hash[MAX_LEN_OF_MULTICAST_FILTER_HASH_TABLE]; + MULTICAST_FILTER_TABLE_ENTRY Content[MAX_LEN_OF_MULTICAST_FILTER_TABLE]; + NDIS_SPIN_LOCK MulticastFilterTabLock; + NDIS_SPIN_LOCK FreeMemberPoolTabLock; + MEMBER_ENTRY freeMemberPool[FREE_MEMBER_POOL_SIZE]; + LIST_HEADER freeEntryList; +} MULTICAST_FILTER_TABLE, *PMULTICAST_FILTER_TABLE; +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + +typedef struct _DMSID_TABLE { + struct _DMSID_TABLE *pNext; + UCHAR DMSIDs; + UINT32 DMSID_DestIP; +} DMSID_TABLE, PDMSID_TABLE; +typedef struct _DMS_ENTRY { + struct _DMS_ENTRY *pNext; + LIST_HEADER DMSIDList; + PMAC_TABLE_ENTRY pEntry; + UCHAR apidx; +} DMS_ENTRY, *PDMS_ENTRY; + + +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT +typedef enum _RT_GREEN_AP_LEVEL { + GREENAP_11BGN_STAS = 0, + GREENAP_ONLY_11BG_STAS, + GREENAP_WITHOUT_ANY_STAS_CONNECT +} RT_GREEN_AP_LEVEL; +#endif /* DOT11_N_SUPPORT */ +#endif /* GREENAP_SUPPORT */ + +/* ----------- end of AP ---------------------------- */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef BLOCK_NET_IF +typedef struct _BLOCK_QUEUE_ENTRY { + BOOLEAN SwTxQueueBlockFlag; + LIST_HEADER NetIfList; +} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY; +#endif /* BLOCK_NET_IF */ + + +struct wificonf { + BOOLEAN bShortGI; + BOOLEAN bGreenField; +}; + +typedef struct _RTMP_DEV_INFO_ { + UCHAR chipName[16]; + RTMP_INF_TYPE infType; +} RTMP_DEV_INFO; + +#ifdef DBG_DIAGNOSE +#define DIAGNOSE_TIME 10 /* 10 sec */ + + +struct dbg_diag_info{ + USHORT TxDataCnt; /* Tx total data count */ + USHORT TxFailCnt; + USHORT RxDataCnt; /* Rx Total Data count. */ + USHORT RxCrcErrCnt; + +#ifdef DBG_TXQ_DEPTH + /* TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8 */ + USHORT TxSWQueCnt[4][9]; +#endif /* DBG_TXQ_DEPTH */ + +#ifdef DBG_TX_RING_DEPTH + /* TxDesc queue length in scale of 0~14, >=15 */ + USHORT TxDescCnt[24]; +#endif /* DBG_TX_RING_DEPTH */ + +#ifdef DBG_TX_AGG_CNT + USHORT TxAggCnt; + USHORT TxNonAggCnt; + /* TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. */ + USHORT TxAMPDUCnt[MAX_MCS_SET]; +#endif /* DBG_TX_AGG_CNT */ + +#ifdef DBG_TX_MCS + /* TxDate MCS Count in range from 0 to 15, step in 1 */ + USHORT TxMcsCnt_HT[MAX_MCS_SET]; +#ifdef DOT11_VHT_AC + UINT TxMcsCnt_VHT[MAX_VHT_MCS_SET]; +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + +#ifdef DBG_RX_MCS + USHORT RxCrcErrCnt_HT[MAX_MCS_SET]; + /* Rx HT MCS Count in range from 0 to 15, step in 1 */ + USHORT RxMcsCnt_HT[MAX_MCS_SET]; +#ifdef DOT11_VHT_AC + USHORT RxCrcErrCnt_VHT[MAX_VHT_MCS_SET]; + /* for VHT80MHz only, not calcuate 20/40 MHz packets */ + UINT RxMcsCnt_VHT[MAX_VHT_MCS_SET]; +#endif /* DOT11_VHT_AC */ +#endif /* DBG_RX_MCS */ +}; + +typedef struct _RtmpDiagStrcut_ { /* Diagnosis Related element */ + unsigned char inited; + unsigned char qIdx; + unsigned char ArrayStartIdx; + unsigned char ArrayCurIdx; + + struct dbg_diag_info diag_info[DIAGNOSE_TIME]; +} RtmpDiagStruct; +#endif /* DBG_DIAGNOSE */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* + The number of channels for per-channel Tx power offset +*/ +#define NUM_OF_CH_FOR_PER_CH_TX_PWR_OFFSET 14 + +/* The Tx power control using the internal ALC */ +#ifdef RT8592 +// TODO: shiang-6590, fix me for this ugly definition! +#define LOOKUP_TB_SIZE 45 +#else +#define LOOKUP_TB_SIZE 33 +#endif /* RT8592 */ + +typedef struct _TX_POWER_CONTROL { + BOOLEAN bInternalTxALC; /* Internal Tx ALC */ + BOOLEAN bExtendedTssiMode; /* The extended TSSI mode (each channel has different Tx power if needed) */ + CHAR PerChTxPwrOffset[NUM_OF_CH_FOR_PER_CH_TX_PWR_OFFSET + 1]; /* Per-channel Tx power offset */ + CHAR idxTxPowerTable; /* The index of the Tx power table for ant0 */ + CHAR idxTxPowerTable2; /* The index of the Tx power table for ant1 */ + CHAR RF_TX_ALC; /* 3390: RF R12[4:0]: Tx0 ALC, 3352: RF R47[4:0]: Tx0 ALC, 5390: RF R49[5:0]: Tx0 ALC */ + CHAR MAC_PowerDelta; /* Tx power control over MAC 0x1314~0x1324 */ + CHAR MAC_PowerDelta2; /* Tx power control for Tx1 */ + CHAR TotalDeltaPower2; /* Tx power control for Tx1 */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + INT LookupTable[IEEE80211_BAND_NUMS][LOOKUP_TB_SIZE]; + INT RefTemp[IEEE80211_BAND_NUMS]; + UCHAR TssiGain[IEEE80211_BAND_NUMS]; + /* Index offset, -7....25. */ + INT LookupTableIndex; +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +} TX_POWER_CONTROL, *PTX_POWER_CONTROL; +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + +/* */ +/* The entry of transmit power control over MAC */ +/* */ +typedef struct _TX_POWER_CONTROL_OVER_MAC_ENTRY { + USHORT MACRegisterOffset; /* MAC register offset */ + ULONG RegisterValue; /* Register value */ +} TX_POWER_CONTROL_OVER_MAC_ENTRY, *PTX_POWER_CONTROL_OVER_MAC_ENTRY; + +/* */ +/* The maximum registers of transmit power control */ +/* */ +#define MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS 5 + + + + +/* */ +/* The configuration of the transmit power control over MAC */ +/* */ +typedef struct _CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC { + UCHAR NumOfEntries; /* Number of entries */ + TX_POWER_CONTROL_OVER_MAC_ENTRY TxPwrCtrlOverMAC[MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS]; +} CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC, *PCONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC; + +/* */ +/* The extension of the transmit power control over MAC */ +/* */ +typedef struct _TX_POWER_CONTROL_EXT_OVER_MAC { + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW20Over2Dot4G; + + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW40Over2Dot4G; + + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW20Over5G; + + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW40Over5G; +} TX_POWER_CONTROL_EXT_OVER_MAC, *PTX_POWER_CONTROL_EXT_OVER_MAC; + +/* For Wake on Wireless LAN */ +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +typedef struct _WOW_CFG_STRUCT { + BOOLEAN bEnable; /* Enable WOW function*/ + BOOLEAN bWOWFirmware; /* Enable WOW function, trigger to reload WOW-support firmware */ + BOOLEAN bInBand; /* use in-band signal to wakeup system */ + UINT8 nSelectedGPIO; /* Side band signal to wake up system */ + UINT8 nDelay; /* Delay number is multiple of 3 secs, and it used to postpone the WOW function */ + UINT8 nHoldTime; /* GPIO puls hold time, unit: 10ms */ +} WOW_CFG_STRUCT, *PWOW_CFG_STRUCT; +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +#ifdef NEW_WOW_SUPPORT +typedef enum { + WOW_PKT_TO_HOST, + WOW_PKT_TO_ANDES +} WOW_PKT_FLOW_T; + +typedef enum { + WOW_WAKEUP_BY_PCIE, + WOW_WAKEUP_BY_USB, + WOW_WAKEUP_BY_GPIO +} WOW_WAKEUP_METHOD_T; + +typedef enum { + WOW_ENABLE = 1, + WOW_TRAFFIC = 3, + WOW_WAKEUP = 4 +} WOW_FEATURE_T; + +typedef enum { + WOW_MASK_CFG = 1, + WOW_SEC_CFG, + WOW_INFRA_CFG, + WOW_P2P_CFG, +} WOW_CONFIG_T; + +enum { + WOW_MAGIC_PKT, + WOW_BITMAP, + WOW_IPV4_TCP_SYNC, + WOW_IPV6_TCP_SYNC +}; + +typedef struct NEW_WOW_MASK_CFG_STRUCT { + UINT32 Config_Type; + UINT32 Function_Enable; + UINT32 Detect_Mask; + UINT32 Event_Mask; +} NEW_WOW_MASK_CFG_STRUCT, PNEW_WOW_MASK_CFG_STRUCT; + +typedef struct NEW_WOW_SEC_CFG_STRUCT { + UINT32 Config_Type; + UINT32 WPA_Ver; + UCHAR PTK[64]; + UCHAR R_COUNTER[8]; + UCHAR Key_Id; + UCHAR Cipher_Alg; + UCHAR WCID; + UCHAR Group_Cipher; +} NEW_WOW_SEC_CFG_STRUCT, PNEW_WOW_SEC_CFG_STRUCT; + +typedef struct NEW_WOW_INFRA_CFG_STRUCT { + UINT32 Config_Type; + UCHAR STA_MAC[6]; + UCHAR AP_MAC[6]; + UINT32 AP_Status; +} NEW_WOW_INFRA_CFG_STRUCT, PNEW_WOW_INFRA_CFG_STRUCT; + +typedef struct _NEW_WOW_P2P_CFG_STRUCT { + UINT32 Config_Type; + UCHAR GO_MAC[6]; + UCHAR CLI_MAC[6]; + UINT32 P2P_Status; +} NEW_WOW_P2P_CFG_STRUCT, *PNEW_WOW_P2P_CFG_STRUCT; + +typedef struct _NEW_WOW_PARAM_STRUCT { + UINT32 Parameter; + UINT32 Value; +} NEW_WOW_PARAM_STRUCT, *PNEW_WOW_PARAM_STRUCT; +#endif /* NEW_WOW_SUPPORT */ + +/* + Packet drop reason code +*/ +typedef enum{ + PKT_ATE_ON = 1 << 8, + PKT_RADAR_ON = 2 << 8, + PKT_RRM_QUIET = 3 << 8, + PKT_TX_STOP = 4 <<8, + PKT_TX_JAM = 5 << 8, + + PKT_NETDEV_DOWN = 6 < 8, + PKT_NETDEV_NO_MATCH = 7 << 8, + PKT_NOT_ALLOW_SEND = 8 << 8, + + PKT_INVALID_DST = 9<< 8, + PKT_INVALID_SRC = 10 << 8, + PKT_INVALID_PKT_DATA = 11 << 8, + PKT_INVALID_PKT_LEN = 12 << 8, + PKT_INVALID_ETH_TYPE = 13 << 8, + PKT_INVALID_TXBLK_INFO = 14 << 8, + PKT_INVALID_SW_ENCRYPT = 15 << 8, + PKT_INVALID_PKT_TYPE = 16 << 8, + PKT_INVALID_PKT_MIC = 17 << 8, + + PKT_PORT_NOT_SECURE = 18 << 8, + PKT_TSPEC_NO_MATCH = 19 << 8, + PKT_NO_ASSOCED_STA = 20 << 8, + PKT_INVALID_MAC_ENTRY = 21 << 8, + + PKT_TX_QUE_FULL = 22 << 8, + PKT_TX_QUE_ADJUST = 23<<8, + + PKT_PS_QUE_TIMEOUT = 24 <<8, + PKT_PS_QUE_CLEAN = 25 << 8, + PKT_MCAST_PS_QUE_FULL = 26 << 8, + PKT_UCAST_PS_QUE_FULL = 27 << 8, + + PKT_RX_EAPOL_SANITY_FAIL = 28 <<8, + PKT_RX_NOT_TO_KERNEL = 29 << 8, + PKT_RX_MESH_SIG_FAIL = 30 << 8, + PKT_APCLI_FAIL = 31 << 8, + PKT_ZERO_DATA = 32 <<8, + PKT_SW_DECRYPT_FAIL = 33 << 8, + PKT_TX_SW_ENC_FAIL = 34 << 8, + + PKT_ACM_FAIL = 35 << 8, + PKT_IGMP_GRP_FAIL = 36 << 8, + PKT_MGMT_FAIL = 37 << 8, + PKT_AMPDU_OUT_ORDER = 38 << 8, + PKT_UAPSD_EOSP = 39 << 8, + PKT_UAPSD_Q_FULL = 40 << 8, + + PKT_DRO_REASON_MAX = 41, +}PKT_DROP_REASON; + +/* Packet drop Direction code */ +typedef enum{ + PKT_TX = 0, + PKT_RX = 1 << 31, +}PKT_DROP_DIECTION; + + + +#ifdef FIFO_EXT_SUPPORT +#define FIFO_EXT_HW_SIZE 8 +typedef struct _FIFO_EXT_ENTRY +{ + UCHAR wcid; + UINT32 hwTxCntCROffset; +} FIFO_EXT_ENTRY, *PFIFO_EXT_ENTRY; +#endif /* FIFO_EXT_SUPPORT */ + + +typedef struct _BBP_RESET_CTL +{ +#define BBP_RECORD_NUM 48 + + REG_PAIR BBPRegDB[BBP_RECORD_NUM]; + BOOLEAN AsicCheckEn; +} BBP_RESET_CTL, *PBBP_RESET_CTL; + +#ifdef CUSTOMER_DCC_FEATURE +typedef struct _STREAMING_TYPE_STATUS{ + BOOLEAN BE; + UINT64 BE_Time; + BOOLEAN BK; + UINT64 BK_Time; + BOOLEAN VI; + UINT64 VI_Time; + BOOLEAN VO; + UINT64 VO_Time; +}STREAMING_TYPE_STATUS, *PSTREAMING_TYPE_STATUS; + +typedef struct _ALLOWED_STA{ + UCHAR MacAddr[6]; + UINT64 DissocTime; +}ALLOWED_STA, *PALLOWED_STA; + +typedef struct _ALLOWED_STA_LIST{ + ALLOWED_STA AllowedSta[MAX_LEN_OF_MAC_TABLE]; + UINT32 StaCount; +}ALLOWED_STA_LIST, *PALLOWED_STA_LIST; + +typedef struct _CHANNEL_STATS{ + UINT32 TotalDuration; + UINT64 LastReadTime; + UINT32 msec100counts; + UINT32 ChBusytime; + UINT32 ChBusyTimeAvg; + UINT32 ChBusyTime100msecValue; + UINT32 ChBusyTime1secValue; + UINT32 CCABusytime; + UINT32 CCABusyTimeAvg; + UINT32 CCABusyTime1secValue; + UINT32 FalseCCACount; + UINT32 FalseCCACountAvg; + UINT32 FalseCCACount1secValue; + UINT64 ChannelApActivity; + UINT64 ChannelApActivityAvg; + UINT64 ChannelApActivity1secValue; +}CHANNEL_STATS, *PCHANNEL_STATS; +#endif + +typedef struct _SCAN_CTRL_{ + UCHAR ScanType; + UCHAR BssType; + UCHAR Channel; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR Bssid[MAC_ADDR_LEN]; + +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT APScanTimer; +#endif /* CONFIG_AP_SUPPORT */ +}SCAN_CTRL; + +#ifdef CUSTOMER_DCC_FEATURE +typedef struct _RADIO_STATS_COUNTER{ + UINT32 TotalBeaconSentCount; + UINT32 TotalTxCount; + UINT32 TotalRxCount; + UINT32 TxDataCount; + UINT32 RxDataCount; + UINT32 TxRetriedPktCount; + UINT32 TxRetryCount; +}RADIO_STATS_COUNTER, *PRADIO_STATS_COUNTER; +#endif + +#ifdef RT_CFG80211_SUPPORT +typedef struct _CFG80211_VIF_DEV +{ + struct _CFG80211_VIF_DEV *pNext; + BOOLEAN isMainDev; + UINT32 devType; + PNET_DEV net_dev; + UCHAR CUR_MAC[MAC_ADDR_LEN]; + + /* ProbeReq Frame */ + BOOLEAN Cfg80211RegisterProbeReqFrame; + CHAR Cfg80211ProbeReqCount; + + /* Action Frame */ + BOOLEAN Cfg80211RegisterActionFrame; + CHAR Cfg80211ActionCount; +} CFG80211_VIF_DEV, *PCFG80211_VIF_DEV; + +typedef struct _CFG80211_VIF_DEV_SET +{ +#define MAX_CFG80211_VIF_DEV_NUM 2 + + BOOLEAN inUsed; + UINT32 vifDevNum; + LIST_HEADER vifDevList; + BOOLEAN isGoingOn; /* To check any vif in list */ +} CFG80211_VIF_DEV_SET; + +/* TxMmgt Related */ +typedef struct _CFG80211_TX_PACKET +{ + struct _CFG80211_TX_PACKET *pNext; + UINT32 TxStatusSeq; /* TxMgmt Packet ID from sequence */ + UCHAR *pTxStatusBuf; /* TxMgmt Packet buffer content */ + UINT32 TxStatusBufLen; /* TxMgmt Packet buffer Length */ + +} CFG80211_TX_PACKET, *PCFG80211_TX_PACKET; + +/* CFG80211 Total CTRL Point */ +typedef struct _CFG80211_CONTROL +{ + BOOLEAN FlgCfg8021Disable2040Scan; + BOOLEAN FlgCfg80211Scanning; /* Record it When scanReq from wpa_supplicant */ + BOOLEAN FlgCfg80211Connecting; /* Record it When ConnectReq from wpa_supplicant*/ + BOOLEAN FlgCfg80211ApBeaconUpdate; + /* Scan Related */ + UINT32 *pCfg80211ChanList; /* the channel list from from wpa_supplicant */ + UCHAR Cfg80211ChanListLen; /* channel list length */ + UCHAR Cfg80211CurChanIndex; /* current index in channel list when driver in scanning */ + + UCHAR *pExtraIe; /* Carry on Scan action from supplicant */ + UINT ExtraIeLen; + + UCHAR *pAssocRspIe; /* Buffer to keep association response IE from AP. Used in informing Linux kernel. */ + UINT32 assocRspIeLen; /* length of the association response IE */ + + UCHAR Cfg_pending_Ssid[MAX_LEN_OF_SSID+1]; /* Record the ssid, When ScanTable Full */ + UCHAR Cfg_pending_SsidLen; + + /* ROC Related */ + RALINK_TIMER_STRUCT Cfg80211RocTimer; + CMD_RTPRIV_IOCTL_80211_CHAN Cfg80211ChanInfo; + BOOLEAN Cfg80211RocTimerInit; + BOOLEAN Cfg80211RocTimerRunning; + + /* Tx_Mmgt Related */ + UINT32 TxStatusSeq; /* TxMgmt Packet ID from sequence */ + UCHAR *pTxStatusBuf; /* TxMgmt Packet buffer content */ + UINT32 TxStatusBufLen; /* TxMgmt Packet buffer Length */ + BOOLEAN TxStatusInUsed; + LIST_HEADER cfg80211TxPacketList; + + /* P2P Releated*/ + UCHAR P2PCurrentAddress[MAC_ADDR_LEN]; /* User changed MAC address */ + BOOLEAN isCfgDeviceInP2p; /* For BaseRate 6 */ + + /* MainDevice Info. */ + CFG80211_VIF_DEV cfg80211MainDev; + + /* For add_virtual_intf */ + CFG80211_VIF_DEV_SET Cfg80211VifDevSet; + +#ifdef RT_CFG80211_P2P_SUPPORT + BOOLEAN bP2pCliPmEnable; + + BOOLEAN bPreKeepSlient; + BOOLEAN bKeepSlient; + + UCHAR MyGOwcid; + UCHAR NoAIndex; + UCHAR CTWindows; /* CTWindows and OppPS parameter field */ + + P2PCLIENT_NOA_SCHEDULE GONoASchedule; + RALINK_TIMER_STRUCT P2pCTWindowTimer; + RALINK_TIMER_STRUCT P2pSwNoATimer; + RALINK_TIMER_STRUCT P2pPreAbsenTimer; + + UCHAR P2pSupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR P2pSupRateLen; + UCHAR P2pExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR P2pExtRateLen; + + + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* Dummy P2P Device for ANDROID JB */ + PNET_DEV dummy_p2p_net_dev; + BOOLEAN flg_cfg_dummy_p2p_init; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE + ULONG P2POpStatusFlags; /* P2P_CLI_UP / P2P_GO_UP*/ +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + + /* In AP Mode */ + UINT8 isCfgInApMode; /* Is any one Device in AP Mode */ + UCHAR *beacon_tail_buf; /* Beacon buf from upper layer */ + UINT32 beacon_tail_len; + + UCHAR *pCfg80211ExtraIeAssocRsp; + UINT32 Cfg80211ExtraIeAssocRspLen; + + /* TODO: need fix it */ + UCHAR Cfg80211_Alpha2[2]; +} CFG80211_CTRL, *PCFG80211_CTRL; +#endif /* RT_CFG80211_SUPPORT */ + +typedef struct rtmp_phy_ctrl{ + UINT8 rf_band_cap; + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_QLOAD_SUPPORT + UINT8 FlgQloadEnable; /* 1: any BSS WMM is enabled */ + ULONG QloadUpTimeLast; /* last up time */ + UINT8 QloadChanUtil; /* last QBSS Load, unit: us */ + ULONG QloadChanUtilTotal; /* current QBSS Load Total */ + UINT8 QloadChanUtilBeaconCnt; /* 1~100, default: 50 */ + UINT8 QloadChanUtilBeaconInt; /* 1~100, default: 50 */ + UINT32 QloadLatestChannelBusyTimePri; + UINT32 QloadLatestChannelBusyTimeSec; + + /* + ex: For 100ms beacon interval, + if the busy time in last TBTT is smaller than 5ms, QloadBusyCount[0] ++; + if the busy time in last TBTT is between 5 and 10ms, QloadBusyCount[1] ++; + ...... + if the busy time in last TBTT is larger than 95ms, QloadBusyCount[19] ++; + + Command: "iwpriv ra0 qload show". + */ + +/* provide busy time alarm mechanism */ +/* use the function to avoid to locate in some noise environments */ +#define QLOAD_FUNC_BUSY_TIME_ALARM + +#ifdef QLOAD_FUNC_BUSY_TIME_STATS +#define QLOAD_BUSY_INTERVALS 20 /* partition TBTT to QLOAD_BUSY_INTERVALS */ + /* for primary channel & secondary channel */ + UINT32 QloadBusyCountPri[QLOAD_BUSY_INTERVALS]; + UINT32 QloadBusyCountSec[QLOAD_BUSY_INTERVALS]; +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM +#define QLOAD_DOES_ALARM_OCCUR(pAd) (pAd->phy_ctrl.FlgQloadAlarmIsSuspended == TRUE) +#define QLOAD_ALARM_EVER_OCCUR(pAd) (pAd->phy_ctrl.QloadAlarmNumber > 0) + BOOLEAN FlgQloadAlarmIsSuspended; /* 1: suspend */ + + UINT8 QloadAlarmBusyTimeThreshold; /* unit: 1/100 */ + UINT8 QloadAlarmBusyNumThreshold; /* unit: 1 */ + UINT8 QloadAlarmBusyNum; + UINT8 QloadAlarmDuration; /* unit: TBTT */ + + UINT32 QloadAlarmNumber; /* total alarm times */ + BOOLEAN FlgQloadAlarm; /* 1: alarm occurs */ + + /* speed up use */ + UINT32 QloadTimePeriodLast; + UINT32 QloadBusyTimeThreshold; +#else + +#define QLOAD_DOES_ALARM_OCCUR(pAd) 0 +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +}RTMP_PHY_CTRL; + +#ifdef ED_MONITOR +enum ed_state +{ + ED_OFF_AND_LEARNING=0, + ED_TESTING=1 +}; +#endif /* ED_MONITOR */ + +/* + The miniport adapter structure +*/ +struct _RTMP_ADAPTER { + VOID *OS_Cookie; /* save specific structure relative to OS */ + PNET_DEV net_dev; + +#ifdef RTMP_MAC_PCI +/*****************************************************************************************/ +/* PCI related parameters */ +/*****************************************************************************************/ + PUCHAR CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; + +#ifdef PCI_MSI_SUPPORT + BOOLEAN HaveMsi; +#endif /* PCI_MSI_SUPPORT */ + + USHORT RLnkCtrlConfiguration; + USHORT RLnkCtrlOffset; + USHORT HostLnkCtrlConfiguration; + USHORT HostLnkCtrlOffset; + USHORT PCIePowerSaveLevel; +#ifdef CONFIG_STA_SUPPORT + USHORT LnkCtrlBitMask; + ULONG Rt3xxHostLinkCtrl; /* USed for 3090F chip */ + ULONG Rt3xxRalinkLinkCtrl; /* USed for 3090F chip */ + ULONG HostVendor; +#endif /* CONFIG_STA_SUPPORT */ + USHORT DeviceID; /* Read from PCI config */ + ULONG AccessBBPFailCount; + BOOLEAN bPCIclkOff; /* flag that indicate if the PICE power status in Configuration SPace.. */ + BOOLEAN bPCIclkOffDisableTx; + + BOOLEAN brt30xxBanMcuCmd; /* when = 0xff means all commands are ok to set . */ + BOOLEAN b3090ESpecialChip; /* 3090E special chip that write EEPROM 0x24=0x9280. */ + /* ULONG CheckDmaBusyCount; // Check Interrupt Status Register Count. */ + + UINT32 int_enable_reg; + UINT32 int_disable_mask; + UINT32 int_pending; + + UINT32 int_cpu_analysis; + ULONG fake_int_counter; + ULONG rx_coherent_counter; + ULONG tx_coherent_counter; + ULONG fifo_int_counter; + ULONG hcca_int_counter; + ULONG tx_ac3_int_counter; + ULONG tx_ac2_int_counter; + ULONG tx_ac1_int_counter; + + /* tx ac0 tasklet related */ + ULONG tx_tasklet_counter; + ULONG tx_int_counter; + ULONG tx_packet_counter; + + /* rx tasklet related */ + ULONG rx_tasklet_counter; + ULONG rx_int_counter; + ULONG rx_packet_counter; + ULONG rx_tasklet_resche_counter; + ULONG rx_packet_1_counter; + ULONG rx_packet_2_counter; + ULONG rx_packet_3_counter; + ULONG rx_packet_4_counter; + ULONG rx_packet_5_counter; + ULONG rx_packet_6_10_counter; + ULONG rx_packet_11_15_counter; + ULONG rx_packet_16_20_counter; + ULONG rx_packet_21_25_counter; + ULONG rx_packet_26_31_counter; + ULONG rx_packet_32_max_counter; + + RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; /* Shared memory of all 1st pre-allocated TxBuf associated with each TXD */ + RTMP_DMABUF RxDescRing[2]; /* Shared memory for RX descriptors */ + RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; /* Shared memory for Tx descriptors */ + RTMP_TX_RING TxRing[NUM_OF_TX_RING]; /* AC0~3 + HCCA */ + RTMP_RX_RING RxRing[NUM_OF_RX_RING]; +#ifdef RT_SECURE_DMA + RTMP_DMABUF TxSecureDMA[NUM_OF_TX_RING]; /* Secure DMA area bounce buffers for rings, TX */ + RTMP_DMABUF RxSecureDMA[NUM_OF_RX_RING]; /* Secure DMA area bounce buffers for rings, RX */ + RTMP_DMABUF MgmtSecureDMA; /* Secure DMA area bounce buffers for Mgmt ring */ + RTMP_DMABUF CtrlSecureDMA; /* Secure DMA area bounce buffers for Ctrl (MCU) ring */ +#endif + NDIS_SPIN_LOCK RxRingLock[NUM_OF_RX_RING]; /* Rx Ring spinlock */ + NDIS_SPIN_LOCK LockInterrupt; + NDIS_SPIN_LOCK tssi_lock; +#endif /* RTMP_MAC_PCI */ + + NDIS_SPIN_LOCK irq_lock; + + /*======Cmd Thread in PCI/RBUS/USB */ + CmdQ CmdQ; + NDIS_SPIN_LOCK CmdQLock; /* CmdQLock spinlock */ + RTMP_OS_TASK cmdQTask; + +/*********************************************************/ +/* Both PCI/USB related parameters */ +/*********************************************************/ + /*RTMP_DEV_INFO chipInfo; */ + RTMP_INF_TYPE infType; + +/*********************************************************/ +/* Driver Mgmt related parameters */ +/*********************************************************/ + /* OP mode: either AP or STA */ + UCHAR OpMode; /* OPMODE_STA, OPMODE_AP */ + + struct wifi_dev *wdev_list[WDEV_NUM_MAX]; + + RTMP_OS_TASK mlmeTask; +#ifdef RTMP_TIMER_TASK_SUPPORT + /* If you want use timer task to handle the timer related jobs, enable this. */ + RTMP_TIMER_TASK_QUEUE TimerQ; + NDIS_SPIN_LOCK TimerQLock; + RTMP_OS_TASK timerTask; +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +/*********************************************************/ +/* Tx related parameters */ +/*********************************************************/ + BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; /* for ensuring RTUSBDeQueuePacket get call once */ + NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING]; + +#ifdef CONFIG_STA_SUPPORT + SHORT CountDowntoPsm; +#endif /* CONFIG_STA_SUPPORT */ + + /* resource for software backlog queues */ + QUEUE_HEADER TxSwQueue[NUM_OF_TX_RING]; /* 4 AC + 1 HCCA */ + NDIS_SPIN_LOCK TxSwQueueLock[NUM_OF_TX_RING]; /* TxSwQueue spinlock */ + + /* Maximum allowed tx software Queue length */ + UINT32 TxSwQMaxLen; + +#ifdef DATA_QUEUE_RESERVE + UINT32 TxRsvLen; /* High priority data Queue reserve len */ +#endif /* DATA_QUEUE_RESERVE */ + + RTMP_DMABUF MgmtDescRing; /* Shared memory for MGMT descriptors */ + RTMP_MGMT_RING MgmtRing; + NDIS_SPIN_LOCK MgmtRingLock; /* Prio Ring spinlock */ + +#ifdef RTMP_PCI_SUPPORT +#ifdef CONFIG_ANDES_SUPPORT + RTMP_DMABUF CtrlDescRing; /* Shared memory for CTRL descriptors */ + RTMP_CTRL_RING CtrlRing; + NDIS_SPIN_LOCK mcu_atomic; + NDIS_SPIN_LOCK CtrlRingLock; /* Ctrl Ring spinlock */ +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_MAC_PCI + RALINK_TIMER_STRUCT TxDoneCleanupTimer; +#endif + UCHAR LastMCUCmd; + +/*********************************************************/ +/* Rx related parameters */ +/*********************************************************/ + +#ifdef RTMP_MAC_PCI + // TODO: shiang, check the purpose of following lock "McuCmdLock" + NDIS_SPIN_LOCK McuCmdLock; /*MCU Command Queue spinlock for RT3090/3592/3390/3593/5390/5392/5592/3290 */ +#endif /* RTMP_MAC_PCI */ + + + /* RX re-assembly buffer for fragmentation */ + FRAGMENT_FRAME FragFrame; /* Frame storage for fragment frame */ + +/***********************************************************/ +/* ASIC related parameters */ +/***********************************************************/ + RTMP_CHIP_OP chipOps; + RTMP_CHIP_CAP chipCap; + struct phy_ops *phy_op; + struct hw_setting hw_cfg; + + UINT32 MACVersion; /* MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. */ + UINT32 ChipID; + UINT16 ChipId; /* Chip version. Read from EEPROM 0x00 to identify RT5390H */ + INT dev_idx; + + /* --------------------------- */ + /* E2PROM */ + /* --------------------------- */ + enum EEPROM_STORAGE_TYPE eeprom_type; + + ULONG EepromVersion; /* byte 0: version, byte 1: revision, byte 2~3: unused */ + ULONG FirmwareVersion; /* byte 0: Minor version, byte 1: Major version, otherwise unused. */ + USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; + UCHAR EEPROMAddressNum; /* 93c46=6 93c66=8 */ + BOOLEAN EepromAccess; + UCHAR EFuseTag; + +#ifdef RTMP_EFUSE_SUPPORT + BOOLEAN bUseEfuse; +#endif /* RTMP_EFUSE_SUPPORT */ + + UCHAR EEPROMImage[MAX_EEPROM_BUFFER_SIZE]; + UCHAR E2pAccessMode; /* Used to identify flash, efuse, eeprom or bin from start-up */ + +#ifdef RTMP_FLASH_SUPPORT + UCHAR *eebuf; + UINT32 flash_offset; +#endif /* RTMP_FLASH_SUPPORT */ + + EEPROM_ANTENNA_STRUC Antenna; /* Since ANtenna definition is different for a & g. We need to save it for future reference. */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; +#if defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(MT76x2) + EEPROM_NIC_CONFIG3_STRUC NicConfig3; +#endif /* defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) */ + + /* --------------------------- */ + /* BBP Control */ + /* --------------------------- */ +#if defined(RTMP_BBP) || defined(RALINK_ATE) + // TODO: shiang-6590, remove "defined(RALINK_ATE)" after ATE has fully re-organized! + UCHAR BbpWriteLatch[MAX_BBP_ID + 1]; /* record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID */ + UCHAR Bbp94; +#endif /* defined(RTMP_BBP) || defined(RALINK_ATE) */ + + CHAR BbpRssiToDbmDelta; /* change from UCHAR to CHAR for high power */ + BBP_R66_TUNING BbpTuning; + + /* ---------------------------- */ + /* RFIC control */ + /* ---------------------------- */ + struct rtmp_phy_ctrl phy_ctrl; + + UCHAR RfIcType; /* RFIC_xxx */ + UCHAR RfFreqOffset; /* Frequency offset for channel switching */ + + RTMP_RF_REGS LatchRfRegs; /* latch th latest RF programming value since RF IC doesn't support READ */ + +#ifdef RTMP_RBUS_SUPPORT + UCHAR RfFreqDelta; /* Frequency Delta */ +#endif /* RTMP_RBUS_SUPPORT */ +#ifdef RTMP_MAC_PCI + UCHAR ShowRf; /* Show RF register write for 2880 */ +#endif /* RTMP_MAC_PCI */ + + /* This soft Rx Antenna Diversity mechanism is used only when user set */ + /* RX Antenna = DIVERSITY ON */ + SOFT_RX_ANT_DIVERSITY RxAnt; + + /* ---------------------------- */ + /* TxPower control */ + /* ---------------------------- */ + CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; /* Store Tx power value for all channels. */ + CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; /* list all supported channels for site survey */ + + + + UCHAR ChannelListNum; /* number of channel in ChannelList[] */ + BOOLEAN BbpForCCK; + ULONG Tx20MPwrCfgABand[MAX_TXPOWER_ARRAY_SIZE]; + ULONG Tx20MPwrCfgGBand[MAX_TXPOWER_ARRAY_SIZE]; + ULONG Tx40MPwrCfgABand[MAX_TXPOWER_ARRAY_SIZE]; + ULONG Tx40MPwrCfgGBand[MAX_TXPOWER_ARRAY_SIZE]; +#ifdef DOT11_VHT_AC + ULONG Tx80MPwrCfgABand[MAX_TXPOWER_ARRAY_SIZE]; // Per-rate Tx power control for VHT BW80 (5GHz only) + BOOLEAN force_vht_op_mode; +#endif /* DOT11_VHT_AC */ + + + + BOOLEAN bAutoTxAgcA; /* Enable driver auto Tx Agc control */ + UCHAR TssiRefA; /* Store Tssi reference value as 25 temperature. */ + UCHAR TssiPlusBoundaryA[2][8]; /* Tssi boundary for increase Tx power to compensate. [Group][Boundary Index]*/ + UCHAR TssiMinusBoundaryA[2][8]; /* Tssi boundary for decrease Tx power to compensate. [Group][Boundary Index]*/ + UCHAR TxAgcStepA; /* Store Tx TSSI delta increment / decrement value */ + CHAR TxAgcCompensateA; /* Store the compensation (TxAgcStep * (idx-1)) */ + + BOOLEAN bAutoTxAgcG; /* Enable driver auto Tx Agc control */ +#if defined(RT6352) || defined(MT76x0) + CHAR TssiRefG; /* Store Tssi reference value as 25 degrees. */ + CHAR TssiPlusBoundaryG[8]; /* Tssi boundary for increase Tx power to compensate. */ + CHAR TssiMinusBoundaryG[8]; /* Tssi boundary for decrease Tx power to compensate. */ + CHAR TssiCalibratedOffset; /* reference temperature(e2p[D1h]) */ + CHAR mp_delta_pwr; +#else + UCHAR TssiRefG; /* Store Tssi reference value as 25 temperature. */ + UCHAR TssiPlusBoundaryG[5]; /* Tssi boundary for increase Tx power to compensate. */ + UCHAR TssiMinusBoundaryG[5]; /* Tssi boundary for decrease Tx power to compensate. */ +#endif /* RT6352 */ + UCHAR TxAgcStepG; /* Store Tx TSSI delta increment / decrement value */ + CHAR TxAgcCompensateG; /* Store the compensation (TxAgcStep * (idx-1)) */ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + UCHAR ChBndryIdx; /* 5G Channel Group Boundary Index for Temperature Compensation */ + TX_POWER_CONTROL TxPowerCtrl; /* The Tx power control using the internal ALC */ + CHAR curr_temp; + CHAR rx_temp_base[2]; /* initial VGA value for chain 0/1, used for base of rx temp compensation power base */ + CHAR DeltaPwrBeforeTempComp; + CHAR LastTempCompDeltaPwr; +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + INT32 CurrTemperature; + +#ifdef RT6352 + UCHAR rf_pa_mode_over_cck[4]; + UCHAR rf_pa_mode_over_ofdm[8]; + UCHAR rf_pa_mode_over_ht[16]; +#endif /* RT6352 */ + +#ifdef MT76x2 /* obtw , tx power boost related */ + #define OBTW_DELTA_ELEMENT 14 + UINT8 obtw_delta_array[OBTW_DELTA_ELEMENT]; + BOOLEAN obtw_anyEnable; + BOOLEAN obtw_debug_on; +#endif + +#ifdef THERMAL_PROTECT_SUPPORT + BOOLEAN force_one_tx_stream; + INT32 last_thermal_pro_temp; + INT32 thermal_pro_criteria; +#ifdef MT76x2 + UINT8 thermal_HighEn; + CHAR thermal_HighTempTh; + UINT8 thermal_LowEn; + CHAR thermal_LowTempTh; +#endif /* MT76x2 */ +#endif /* THERMAL_PROTECT_SUPPORT */ + + + + signed char BGRssiOffset[3]; /* Store B/G RSSI #0/1/2 Offset value on EEPROM 0x46h */ + signed char ARssiOffset[3]; /* Store A RSSI 0/1/2 Offset value on EEPROM 0x4Ah */ + + CHAR BLNAGain; /* Store B/G external LNA#0 value on EEPROM 0x44h */ + CHAR ALNAGain0; /* Store A external LNA#0 value for ch36~64 */ + CHAR ALNAGain1; /* Store A external LNA#1 value for ch100~128 */ + CHAR ALNAGain2; /* Store A external LNA#2 value for ch132~165 */ + UCHAR TxMixerGain24G; /* Tx mixer gain value from EEPROM to improve Tx EVM / Tx DAC, 2.4G */ + UCHAR TxMixerGain5G; + + +#ifdef LED_CONTROL_SUPPORT + /* LED control */ + LED_CONTROL LedCntl; +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef IGMP_MESH + USHORT CloneCnt; +#endif + + /* ---------------------------- */ + /* MAC control */ + /* ---------------------------- */ +#ifdef SPECIFIC_BCN_BUF_SUPPORT + UCHAR ShrMSel; + NDIS_SPIN_LOCK ShrMemLock; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + UCHAR wmm_cw_min; /* CW_MIN_IN_BITS, actual CwMin = 2^CW_MIN_IN_BITS - 1 */ + UCHAR wmm_cw_max; /* CW_MAX_IN_BITS, actual CwMax = 2^CW_MAX_IN_BITS - 1 */ + +#ifdef RT8592 + CHAR bw_cal[3]; // bw cal value for RF_R32, 0:20M, 1:40M, 2:80M +// TODO: shiang-6590, temporary get from windows and need to revise it!! + /* IQ Calibration */ + UCHAR IQGainTx[3][4]; + UCHAR IQPhaseTx[3][4]; + USHORT IQControl; +#endif /* RT8592 */ + +#if defined(RT3290) || defined(RLT_MAC) +#ifdef RTMP_MAC_PCI + NDIS_SPIN_LOCK WlanEnLock; + NDIS_SPIN_LOCK CalLock; +#endif + + + WLAN_FUN_CTRL_STRUC WlanFunCtrl; +#endif /* defined(RT3290) || defined(RLT_MAC) */ + +#ifdef DROP_MASK_SUPPORT + NDIS_SPIN_LOCK drop_mask_lock; +#endif /* DROP_MASK_SUPPORT */ + +/*****************************************************************************************/ +/* 802.11 related parameters */ +/*****************************************************************************************/ + /* outgoing BEACON frame buffer and corresponding TXD */ + TXWI_STRUC BeaconTxWI; + PUCHAR BeaconBuf; + USHORT BeaconOffset[HW_BEACON_MAX_NUM]; + + /* pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. */ +#ifdef CONFIG_STA_SUPPORT + PSPOLL_FRAME PsPollFrame; +#endif /* CONFIG_STA_SUPPORT */ + HEADER_802_11 NullFrame; + + + +#ifdef UAPSD_SUPPORT + NDIS_SPIN_LOCK UAPSDEOSPLock; /* EOSP frame access lock use */ + BOOLEAN bAPSDFlagSPSuspend; /* 1: SP is suspended; 0: SP is not */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT +MONITOR_STRUCT monitor_ctrl; +#endif /* CONFIG_SNIFFER_SUPPORT */ + + + +/*=========AP=========== */ +#ifdef CONFIG_AP_SUPPORT + /* ----------------------------------------------- */ + /* AP specific configuration & operation status */ + /* used only when pAd->OpMode == OPMODE_AP */ + /* ----------------------------------------------- */ + AP_ADMIN_CONFIG ApCfg; /* user configuration when in AP mode */ + AP_MLME_AUX ApMlmeAux; + + +#ifdef SMART_MESH +#ifdef MAC_REPEATER_SUPPORT + UCHAR vMacAddrPrefix[3]; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* SMART_MESH */ + +#ifdef WDS_SUPPORT + WDS_TABLE WdsTab; /* WDS table when working as an AP */ + NDIS_SPIN_LOCK WdsTabLock; +#endif /* WDS_SUPPORT */ + +#ifdef MBSS_SUPPORT + BOOLEAN FlgMbssInit; +#endif /* MBSS_SUPPORT */ + +#ifdef WDS_SUPPORT + BOOLEAN flg_wds_init; +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + BOOLEAN flg_apcli_init; +#endif /* APCLI_SUPPORT */ + + PBSSINFO pBssInfoTab; + PCHANNELINFO pChannelInfo; + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef PS_ENTRY_MAITENANCE + UINT32 ps_timeout; +#endif /* PS_ENTRY_MAITENANCE */ + +/*=======STA=========== */ +#ifdef CONFIG_STA_SUPPORT + /* ----------------------------------------------- */ + /* STA specific configuration & operation status */ + /* used only when pAd->OpMode == OPMODE_STA */ + /* ----------------------------------------------- */ + STA_ADMIN_CONFIG StaCfg; /* user desired settings */ + STA_ACTIVE_CONFIG StaActive; /* valid only when ADHOC_ON(pAd) || INFRA_ON(pAd) */ + CHAR nickname[IW_ESSID_MAX_SIZE + 1]; /* nickname, only used in the iwconfig i/f */ + NDIS_MEDIA_STATE PreMediaState; +#endif /* CONFIG_STA_SUPPORT */ + +/*=======Common=========== */ + enum RATE_ADAPT_ALG rateAlg; /* Rate adaptation algorithm */ + + NDIS_MEDIA_STATE IndicateMediaState; /* Base on Indication state, default is NdisMediaStateDisConnected */ + +#ifdef PROFILE_STORE + RTMP_OS_TASK WriteDatTask; + BOOLEAN bWriteDat; +#endif /* PROFILE_STORE */ + +#ifdef CREDENTIAL_STORE + STA_CONNECT_INFO StaCtIf; +#endif /* CREDENTIAL_STORE */ + +#ifdef WSC_INCLUDED + RTMP_OS_TASK wscTask; + UCHAR WriteWscCfgToDatFile; + BOOLEAN WriteWscCfgToAr9DatFile; + NDIS_SPIN_LOCK WscElmeLock; + MLME_QUEUE_ELEM *pWscElme; + + /* WSC hardware push button function 0811 */ + BOOLEAN WscHdrPshBtnFlag; /* 1: support, read from EEPROM */ +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bWscDriverAutoUpdateCfg; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef RTMP_RBUS_SUPPORT +#ifdef RT3XXX_ANTENNA_DIVERSITY_SUPPORT + RTMP_OS_TASK ADTask; +#endif /* RT3XXX_ANTENNA_DIVERSITY_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + + /* MAT related parameters */ +#ifdef MAT_SUPPORT + MAT_STRUCT MatCfg; +#endif /* MAT_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + AP_VIDEO_STRUCT VideoTurbine; +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + + /* + Frequency setting for rate adaptation + @ra_interval: for baseline time interval + @ra_fast_interval: for quick response time interval + */ + UINT32 ra_interval; + UINT32 ra_fast_interval; + + /* configuration: read from Registry & E2PROM */ + BOOLEAN bLocalAdminMAC; /* Use user changed MAC */ + UCHAR PermanentAddress[MAC_ADDR_LEN]; /* Factory default MAC address */ + UCHAR CurrentAddress[MAC_ADDR_LEN]; /* User changed MAC address */ + + /* ------------------------------------------------------ */ + /* common configuration to both OPMODE_STA and OPMODE_AP */ + /* ------------------------------------------------------ */ + UINT VirtualIfCnt; + + COMMON_CONFIG CommonCfg; + MLME_STRUCT Mlme; + + /* AP needs those vaiables for site survey feature. */ + MLME_AUX MlmeAux; /* temporary settings used during MLME state machine */ +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) + SCAN_CTRL ScanCtrl; + BSS_TABLE ScanTab; /* store the latest SCAN result */ +#endif /* defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + BSS_TABLE AvailableBSS; // stores the information of the BSS on the channel on which AP is operating + CHANNELINFO ChannelInfo; + STREAMING_TYPE_STATUS StreamingTypeStatus; + BOOLEAN ApDisableSTAConnectFlag; + ALLOWED_STA_LIST AllowedStaList; + CHANNEL_STATS ChannelStats; + BOOLEAN EnableChannelStatsCheck; + BOOLEAN ApEnableBeaconTable; + RADIO_STATS_COUNTER RadioStatsCounter; +#endif +#endif + /*About MacTab, the sta driver will use #0 and #1 for multicast and AP. */ + MAC_TABLE MacTab; /* ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. */ + NDIS_SPIN_LOCK MacTabLock; + +#ifdef DOT11_N_SUPPORT + BA_TABLE BATable; + NDIS_SPIN_LOCK BATabLock; + RALINK_TIMER_STRUCT RECBATimer; + + BOOLEAN HTCEnable; +#endif /* DOT11_N_SUPPORT */ + + EXT_CAP_INFO_ELEMENT ExtCapInfo; + +#ifdef SMART_MESH_MONITOR + UCHAR MntEnable; + MNT_STA_ENTRY MntTable[MAX_NUM_OF_MONITOR_STA]; + UCHAR MntIdx; + UCHAR curMntAddr[MAC_ADDR_LEN]; +#endif /* SMART_MESH_MONITOR */ + + /* DOT11_H */ + DOT11_H Dot11_H; + + /* encryption/decryption KEY tables */ + CIPHER_KEY SharedKey[HW_BEACON_MAX_NUM + MAX_P2P_NUM][4]; /* STA always use SharedKey[BSS0][0..3] */ + + /* various Counters */ + COUNTER_802_3 Counters8023; /* 802.3 counters */ + COUNTER_802_11 WlanCounters; /* 802.11 MIB counters */ + COUNTER_RALINK RalinkCounters; /* Ralink propriety counters */ + /* COUNTER_DRS DrsCounters; */ /* counters for Dynamic TX Rate Switching */ +#ifdef SMART_MESH + COUNTER_TIME ChannelTimerCounters; /* Ralink propriety counters */ +#endif /* SMART_MESH */ + PRIVATE_STRUC PrivateInfo; /* Private information & counters */ +#ifdef FIFO_EXT_SUPPORT + FIFO_EXT_ENTRY FifoExtTbl[FIFO_EXT_HW_SIZE]; +#endif /* FIFO_EXT_SUPPORT */ + + /* flags, see fRTMP_ADAPTER_xxx flags */ + ULONG Flags; /* Represent current device status */ + ULONG PSFlags; /* Power Save operation flag. */ + ULONG MoreFlags; /* Represent specific requirement */ + + /* current TX sequence # */ + USHORT Sequence; + + /* Control disconnect / connect event generation */ + /*+++Didn't used anymore */ + ULONG LinkDownTime; + /*--- */ + ULONG LastRxRate; + ULONG LastTxRate; + /*+++Used only for Station */ + BOOLEAN bConfigChanged; /* Config Change flag for the same SSID setting */ + /*--- */ + + ULONG ExtraInfo; /* Extra information for displaying status of UI */ + ULONG SystemErrorBitmap; /* b0: E2PROM version error */ + +#ifdef SMART_MESH_MONITOR + UINT32 MonitrCnt; + UINT32 LastMgmtRxRate; +#endif /* SMART_MESH_MONITOR */ + +#ifdef SYSTEM_LOG_SUPPORT + /* --------------------------- */ + /* System event log */ + /* --------------------------- */ + RT_802_11_EVENT_TABLE EventTab; +#endif /* SYSTEM_LOG_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + UINT32 IoctlIF; +#endif /* HOSTAPD_SUPPORT */ +#ifdef INF_PPA_SUPPORT + UINT32 g_if_id; + BOOLEAN PPAEnable; + PPA_DIRECTPATH_CB *pDirectpathCb; +#endif /* INF_PPA_SUPPORT */ + + /**********************************************************/ + /* Statistic related parameters */ + /**********************************************************/ + + BOOLEAN bUpdateBcnCntDone; + + ULONG macwd; +#ifdef RT6352 + BOOLEAN bEnableMacWD; +#endif /* RT6352 */ + /* ---------------------------- */ + /* DEBUG paramerts */ + /* ---------------------------- */ + + /* ---------------------------- */ + /* rt2860c emulation-use Parameters */ + /* ---------------------------- */ + BOOLEAN bLinkAdapt; + BOOLEAN bForcePrintTX; + BOOLEAN bForcePrintRX; + BOOLEAN bStaFifoTest; + BOOLEAN bProtectionTest; + BOOLEAN bHCCATest; + BOOLEAN bGenOneHCCA; + BOOLEAN bBroadComHT; + /*+++Following add from RT2870 USB. */ + ULONG BulkOutReq; + ULONG BulkOutComplete; + ULONG BulkOutCompleteOther; + ULONG BulkOutCompleteCancel; /* seems not use now? */ + ULONG BulkInReq; + ULONG BulkInComplete; + ULONG BulkInCompleteFail; + /*--- */ + + INT32 rts_tx_retry_num; + struct wificonf WIFItestbed; + + UCHAR TssiGain; +#ifdef RALINK_ATE + ATE_INFO ate; + RTMP_OS_TASK AteMPSTask; +#endif /* RALINK_ATE */ + +#ifdef DOT11_N_SUPPORT + struct reordering_mpdu_pool mpdu_blk_pool; +#endif /* DOT11_N_SUPPORT */ + + /* statistics count */ + + VOID *iw_stats; + +#ifdef BLOCK_NET_IF + BLOCK_QUEUE_ENTRY blockQueueTab[NUM_OF_TX_RING]; +#endif /* BLOCK_NET_IF */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef IGMP_SNOOP_SUPPORT + PMULTICAST_FILTER_TABLE pMulticastFilterTable; + UCHAR IgmpGroupTxRate; +#endif /* IGMP_SNOOP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef ETH_CONVERT_SUPPORT + ETH_CONVERT_STRUCT EthConvert; +#endif /* ETH_CONVERT_SUPPORT */ + +#ifdef MULTIPLE_CARD_SUPPORT + INT32 MC_RowID; + STRING MC_FileName[256]; + UINT32 E2P_OFFSET_IN_FLASH[MAX_NUM_OF_MULTIPLE_CARD]; +#endif /* MULTIPLE_CARD_SUPPORT */ + + ULONG TbttTickCount; /* beacon timestamp work-around */ + +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT PeriodicTimer; +#endif /* CONFIG_AP_SUPPORT */ + /* for detect_wmm_traffic() BE TXOP use */ + ULONG OneSecondnonBEpackets; /* record non BE packets per second */ + UCHAR is_on; + + /* for detect_wmm_traffic() BE/BK TXOP use */ +#define TIME_BASE (1000000/OS_HZ) +#define TIME_ONE_SECOND (1000000/TIME_BASE) + UCHAR flg_be_adjust; + ULONG be_adjust_last_time; + + +#ifdef WSC_INCLUDED + /* for multiple card */ + UCHAR *pHmacData; + +#ifdef CON_WPS +#define CON_WPS_STATUS_DISABLED 0x00 +#define CON_WPS_STATUS_AP_RUNNING 0x01 +#define CON_WPS_STATUS_APCLI_RUNNING 0x02 + + INT conWscStatus; /* 0x0 Disabled, 0x01 ApRunning, 0x02 ApCliRunning */ +#endif /* CON_WPS */ + +#endif /* WSC_INCLUDED */ + +#ifdef IKANOS_VX_1X0 + struct IKANOS_TX_INFO IkanosTxInfo; + struct IKANOS_TX_INFO IkanosRxInfo[HW_BEACON_MAX_NUM + MAX_WDS_ENTRY + + MAX_APCLI_NUM + MAX_MESH_NUM]; +#endif /* IKANOS_VX_1X0 */ + + + + UINT8 FlgCtsEnabled; + UINT8 PM_FlgSuspend; + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11R_FT_SUPPORT + /* RIC */ +#define FT_RIC_CB ((FT_RIC_CTRL_BLOCK *)(pAd->pFT_RIC_Ctrl_BK)) + VOID *pFT_RIC_Ctrl_BK; + NDIS_SPIN_LOCK FT_RicLock; +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + LIST_HEADER DMSEntryList; + LIST_HEADER FMSEntryList; +#endif /* DOT11V_WNM_SUPPORT */ + + UCHAR FifoUpdateDone, FifoUpdateRx; + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + CFG80211_CTRL cfg80211_ctrl; + VOID *pCfg80211_CB; +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + +#ifdef OS_ABL_SUPPORT +#ifdef MAT_SUPPORT + /* used in OS_ABL */ + BOOLEAN (*MATPktRxNeedConvert) (RTMP_ADAPTER *pAd, PNET_DEV net_dev); + + PUCHAR (*MATEngineRxHandle)(RTMP_ADAPTER *pAd, PNDIS_PACKET pPkt, UINT infIdx); +#endif /* MAT_SUPPORT */ +#endif /* OS_ABL_SUPPORT */ + + UINT32 ContinueMemAllocFailCount; + + struct { + INT IeLen; + UCHAR *pIe; + } ProbeRespIE[MAX_LEN_OF_BSS_TABLE]; + + /* purpose: We free all kernel resources when module is removed */ + LIST_HEADER RscTimerMemList; /* resource timers memory */ + LIST_HEADER RscTaskMemList; /* resource tasks memory */ + LIST_HEADER RscLockMemList; /* resource locks memory */ + LIST_HEADER RscTaskletMemList; /* resource tasklets memory */ + LIST_HEADER RscSemMemList; /* resource semaphore memory */ + LIST_HEADER RscAtomicMemList; /* resource atomic memory */ + + /* purpose: Cancel all timers when module is removed */ + LIST_HEADER RscTimerCreateList; /* timers list */ + +#ifdef OS_ABL_SUPPORT +#ifdef RTMP_PCI_SUPPORT + RTMP_PCI_CONFIG PciConfig; +#endif /* RTMP_PCI_SUPPORT */ +#endif /* OS_ABL_SUPPORT */ + + + + +#ifdef CONFIG_MULTI_CHANNEL + CHAR NullFrBuf[256]; + UINT32 MultiChannelFlowCtl; + RTMP_OS_TASK MultiChannelTask; + UCHAR MultiChannelAction; +#endif /* CONFIG_MULTI_CHANNEL */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + WOW_CFG_STRUCT WOW_Cfg; /* data structure for wake on wireless */ +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + + TXWI_STRUC NullTxWI; + USHORT NullBufOffset[2]; + +#ifdef APCLI_CERT_SUPPORT + BOOLEAN bApCliCertTest; +#endif /* APCLI_CERT_SUPPORT */ +#ifdef MULTI_MAC_ADDR_EXT_SUPPORT + BOOLEAN bUseMultiMacAddrExt; +#endif /* MULTI_MAC_ADDR_EXT_SUPPORT */ + +#ifdef MCS_LUT_SUPPORT + BOOLEAN bUseHwTxLURate; +#endif /* MCS_LUT_SUPPORT */ + +#ifdef RT6352 + UCHAR RfBank; + UCHAR VGA_Gain0_idx; + UCHAR VGA_Gain1_idx; + BOOLEAN bCalibrationDone; + CHAR tx_bw_cal[2]; // bw cal value for RF_R32, 0:20M, 1:40M + CHAR rx_bw_cal[2]; // bw cal value for RF_R32, 0:20M, 1:40M + UCHAR Tx0_DPD_ALC_tag0; + UCHAR Tx0_DPD_ALC_tag1; + UCHAR Tx1_DPD_ALC_tag0; + UCHAR Tx1_DPD_ALC_tag1; + + UCHAR Tx0_DPD_ALC_tag0_flag; + UCHAR Tx0_DPD_ALC_tag1_flag; + UCHAR Tx1_DPD_ALC_tag0_flag; + UCHAR Tx1_DPD_ALC_tag1_flag; + INT32 DoDPDCurrTemperature; + UINT16 E2p_D0_Value; + CHAR TemperatureRef25C; + BOOLEAN bRef25CVaild; + BOOLEAN bLowTemperatureTrigger; + CHAR BW_Power_Delta; + BOOLEAN bExtPA; +#endif /* RT6352 */ + +#ifdef CONFIG_ANDES_SUPPORT + struct MCU_CTRL MCUCtrl; +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef WLAN_SKB_RECYCLE + struct sk_buff_head rx0_recycle; +#endif /* WLAN_SKB_RECYCLE */ + +#ifdef CONFIG_MULTI_CHANNEL + USHORT NullBufOffset[2]; + CHAR NullFrBuf[100]; + UINT32 NullFrLen; + /* + UINT32 MultiChannelFlowCtl; + RTMP_OS_TASK MultiChannelTask; + UCHAR MultiChannelAction; + */ +#endif /* CONFIG_MULTI_CHANNEL */ + +#ifdef SINGLE_SKU_V2 + DL_LIST SingleSkuPwrList; + UCHAR DefaultTargetPwr; + CHAR SingleSkuRatePwrDiff[18]; + BOOLEAN bOpenFileSuccess; + BOOLEAN sku_init_done; + UCHAR tc_init_val; + BOOLEAN bSingleSkuDebug; +#endif /* SINGLE_SKU_V2 */ + +#ifdef AIRPLAY_SUPPORT +/* +* Value: +* 0: Disable airplay +* 1: Enable airplay +*/ + BOOLEAN bAirplayEnable; +/* +*Beacon, probe Resp(opt), Action frames(opt) need append airplay IE. +*Now above three type of frame use same IE info, +*maybe later would be modified. +*/ + PUCHAR pAirplayIe; + UCHAR AirplayIeLen; + +#endif /* AIRPLAY_SUPPORT */ + + /* + move ed_chk to common part , should always be false + except when (ED_MONITOR is defined && in EU region) + */ + BOOLEAN ed_chk; +#ifdef ED_MONITOR + BOOLEAN ed_debug; + BOOLEAN ed_vga_at_lowest_gain; + UINT ed_learning_time_threshold; //50 * 100ms = 5 sec + +//for AP Mode's threshold +#ifdef CONFIG_AP_SUPPORT + UCHAR ed_sta_threshold; + UCHAR ed_ap_threshold; +#endif /* CONFIG_AP_SUPPORT */ + +//for STA Mode's threshold +#ifdef CONFIG_STA_SUPPORT + UCHAR ed_ap_scaned; + UCHAR ed_current_ch_aps; +#endif /* CONFIG_STA_SUPPORT */ + //move to common part! + CHAR ed_rssi_threshold; + + UCHAR ed_threshold; + UINT ed_false_cca_threshold; + UINT false_cca_threshold; + UINT ed_block_tx_threshold; + INT ed_chk_period; // in unit of ms + + UCHAR ed_stat_sidx; + UCHAR ed_stat_lidx; + BOOLEAN ed_tx_stoped; + UINT ed_trigger_cnt; + UINT ed_silent_cnt; + UINT ed_false_cca_cnt; + +#define ED_STAT_CNT 20 + UINT32 ed_stat[ED_STAT_CNT]; + UINT32 ed_trigger_stat[ED_STAT_CNT]; + UINT32 ed_silent_stat[ED_STAT_CNT]; + UINT32 ed_2nd_stat[ED_STAT_CNT]; + UINT32 ch_idle_stat[ED_STAT_CNT]; + UINT32 ch_busy_stat[ED_STAT_CNT]; + UINT32 false_cca_stat[ED_STAT_CNT]; + ULONG chk_time[ED_STAT_CNT]; + RALINK_TIMER_STRUCT ed_timer; + BOOLEAN ed_timer_inited; + enum ed_state ed_current_state; +#define EDCCA_OFF 0 +#define EDCCA_ON 1 +#ifdef ED_SMART +#define EDCCA_SMART 2 +#endif /* ED_SMART */ +#endif /* ED_MONITOR */ + +#ifdef WFA_VHT_PF + BOOLEAN force_amsdu; + BOOLEAN force_noack; + BOOLEAN vht_force_sgi; + BOOLEAN vht_force_tx_stbc; + + BOOLEAN force_vht_op_mode; + UCHAR vht_pf_op_ss; + UCHAR vht_pf_op_bw; +#endif /* WFA_VHT_PF */ + +#ifdef CONFIG_FPGA_MODE +struct fpga_ctrl fpga_ctl; +#ifdef CAPTURE_MODE + BOOLEAN cap_support; /* 0: no cap mode; 1: cap mode enable */ + UCHAR cap_type; /* 1: ADC6, 2: ADC8, 3: FEQ */ + UCHAR cap_trigger; /* 1: manual trigger, 2: auto trigger */ + BOOLEAN do_cap; /* 1: start to do cap, if auto, will triggered depends on trigger condition, if manual, start immediately */ + BOOLEAN cap_done; /* 1: capture done, 0: capture not finish yet */ + UINT32 trigger_offset; /* in unit of bytes */ + UCHAR *cap_buf; +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef DBG_DIAGNOSE + RtmpDiagStruct DiagStruct; +#endif /* DBG_DIAGNOSE */ + +#ifdef CONFIG_SNIFFER_SUPPORT + struct sniffer_control sniffer_ctl; +#endif + + +#ifdef CONFIG_CALIBRATION_COLLECTION + struct mt76x2_calibration_info calibration_info[MAX_MT76x2_CALIBRATION_ID]; +#endif + +#ifdef TXBF_SUPPORT + BOOLEAN ceBfCertificationFlg; + ULONG sounding_periodic_count; + UCHAR timeout_flg; + UCHAR txDmaIdx_backup; + UCHAR soundingMode; + UCHAR soundingPacketDone; + UCHAR txLengthBackup; + UCHAR divPhaseBackup[2]; + BOOLEAN iBFPhaseErrorBackup; +#endif + +#ifdef VHT_TXBF_SUPPORT + BOOLEAN NDPA_Request; + BOOLEAN BeaconSndDimensionFlag; // Peer sounding dimension flag +#endif + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT + BOOLEAN PDMAWatchDogEn; + BOOLEAN PDMAWatchDogDbg; + UINT8 TxDMACheckTimes; + UINT8 RxDMACheckTimes; + ULONG TxDMAResetCount; + ULONG RxDMAResetCount; +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + +#ifdef REDUCE_TCP_ACK_SUPPORT + struct hlist_head ackCnxHashTbl[REDUCE_ACK_MAX_HASH_BUCKETS]; + struct list_head ackCnxList; + UINT32 ReduceAckConnections; + struct delayed_work ackFlushWork; + struct delayed_work cnxFlushWork; + NDIS_SPIN_LOCK ReduceAckLock; +#endif /* REDUCE_TCP_ACK_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP + UCHAR StaTxopAbledCnt; + UCHAR ApClientTxopAbledCnt; +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + +}; + + +#ifdef BTCOEX_CONCURRENT +typedef struct _BT_COEX_VAL +{ +#ifdef RT_BIG_ENDIAN + UCHAR rsv; + UCHAR eeprom25; + UCHAR eeprom24; + UCHAR eeprom23; +#else + UCHAR eeprom23; + UCHAR eeprom24; + UCHAR eeprom25; + UCHAR rsv; +#endif +} BT_COEX_VAL, *PBT_COEX_VAL; // ITxBF BBP reg phase calibration parameters +#endif + +#ifdef ED_MONITOR +INT ed_status_read(RTMP_ADAPTER *pAd); +INT ed_monitor_init(RTMP_ADAPTER *pAd); +INT ed_monitor_exit(RTMP_ADAPTER *pAd); +#ifdef ED_SMART +INT ed_state_judge(RTMP_ADAPTER *pAd); +VOID ed_testing_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* ED_SMART */ +#endif /* ED_MONITOR */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* The offset of the Tx power tuning entry (zero-based array) */ +#define TX_POWER_TUNING_ENTRY_OFFSET 30 + +/* The lower-bound of the Tx power tuning entry */ +#define LOWERBOUND_TX_POWER_TUNING_ENTRY -30 + +/* The upper-bound of the Tx power tuning entry in G band */ +#define UPPERBOUND_TX_POWER_TUNING_ENTRY(__pAd) ((__pAd)->chipCap.TxAlcTxPowerUpperBound_2G) + +#ifdef A_BAND_SUPPORT +/* The upper-bound of the Tx power tuning entry in A band */ +#define UPPERBOUND_TX_POWER_TUNING_ENTRY_5G(__pAd) ((__pAd)->chipCap.TxAlcTxPowerUpperBound_5G) +#endif /* A_BAND_SUPPORT */ + +/* Temperature compensation lookup table */ + +#define TEMPERATURE_COMPENSATION_LOOKUP_TABLE_OFFSET 7 + +/* The lower/upper power delta index for the TSSI rate table */ + +#define LOWER_POWER_DELTA_INDEX 0 +#define UPPER_POWER_DELTA_INDEX 24 + +/* The offset of the TSSI rate table */ + +#define TSSI_RATIO_TABLE_OFFSET 12 + + +/* Get the power delta bound */ + +#define GET_TSSI_RATE_TABLE_INDEX(x) (((x) > UPPER_POWER_DELTA_INDEX) ? (UPPER_POWER_DELTA_INDEX) : (((x) < LOWER_POWER_DELTA_INDEX) ? (LOWER_POWER_DELTA_INDEX) : ((x)))) + +/* 802.11b CCK TSSI information */ + +typedef union _CCK_TSSI_INFO +{ +#ifdef RT_BIG_ENDIAN + struct + { + UCHAR Reserved:1; + UCHAR ShortPreamble:1; + UCHAR Rate:2; + UCHAR Tx40MSel:2; + UCHAR TxType:2; + } field; +#else + struct + { + UCHAR TxType:2; + UCHAR Tx40MSel:2; + UCHAR Rate:2; + UCHAR ShortPreamble:1; + UCHAR Reserved:1; + } field; +#endif /* RT_BIG_ENDIAN */ + + UCHAR value; +} CCK_TSSI_INFO, *PCCK_TSSI_INFO; + + +/* 802.11a/g OFDM TSSI information */ + +typedef union _OFDM_TSSI_INFO +{ +#ifdef RT_BIG_ENDIAN + struct + { + UCHAR Rate:4; + UCHAR Tx40MSel:2; + UCHAR TxType:2; + } field; +#else + struct + { + UCHAR TxType:2; + UCHAR Tx40MSel:2; + UCHAR Rate:4; + } field; +#endif /* RT_BIG_ENDIAN */ + + UCHAR value; +} OFDM_TSSI_INFO, *POFDM_TSSI_INFO; + + +/* 802.11n HT TSSI information */ + +typedef struct _HT_TSSI_INFO { + union { +#ifdef RT_BIG_ENDIAN + struct { + UCHAR SGI:1; + UCHAR STBC:2; + UCHAR Aggregation:1; + UCHAR Tx40MSel:2; + UCHAR TxType:2; + } field; +#else + struct { + UCHAR TxType:2; + UCHAR Tx40MSel:2; + UCHAR Aggregation:1; + UCHAR STBC:2; + UCHAR SGI:1; + } field; +#endif /* RT_BIG_ENDIAN */ + + UCHAR value; + } PartA; + + union { +#ifdef RT_BIG_ENDIAN + struct { + UCHAR BW:1; + UCHAR MCS:7; + } field; +#else + struct { + UCHAR MCS:7; + UCHAR BW:1; + } field; +#endif /* RT_BIG_ENDIAN */ + UCHAR value; + } PartB; +} HT_TSSI_INFO, *PHT_TSSI_INFO; + +typedef struct _TSSI_INFO_{ + UCHAR tssi_info_0; + union { + CCK_TSSI_INFO cck_tssi_info; + OFDM_TSSI_INFO ofdm_tssi_info; + HT_TSSI_INFO ht_tssi_info_1; + UCHAR byte; + }tssi_info_1; + HT_TSSI_INFO ht_tssi_info_2; +}TSSI_INFO; + +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + +typedef struct _PEER_PROBE_REQ_PARAM { + UCHAR Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + BOOLEAN bRequestRssi; +#ifdef CONFIG_HOTSPOT + BOOLEAN IsIWIE; + BOOLEAN IsIWCapability; + UCHAR Hessid[MAC_ADDR_LEN]; + BOOLEAN IsHessid; + UINT8 AccessNetWorkType; +#endif /* CONFIG_HOTSPOT */ +#ifdef SMART_MESH + UCHAR VIEFlag; /* Store the flag byte inside VIE */ +#endif /* SMART_MESH */ +#ifdef SMART_MESH_MONITOR + IE_LISTS ie_list; + UCHAR vendor_ie_len; + UCHAR vendor_ie[NTGR_IE_TOTAL_LEN]; +#endif /* SMART_MESH_MONITOR */ +} PEER_PROBE_REQ_PARAM, *PPEER_PROBE_REQ_PARAM; + + +/*************************************************************************** + * Rx Path software control block related data structures + **************************************************************************/ +typedef enum RX_BLK_FLAGS{ + fRX_AMPDU = 0x0001, + fRX_AMSDU = 0x0002, + fRX_ARALINK = 0x0004, + fRX_HTC = 0x0008, + fRX_PAD = 0x0010, + fRX_QOS = 0x0020, + fRX_EAP = 0x0040, + fRX_WPI = 0x0080, + fRX_AP = 0x0100, // Packet received from AP + fRX_STA = 0x0200, // Packet received from Client(Infra moed) + fRX_ADHOC = 0x400, // packet received from AdHoc peer + fRX_WDS = 0x0800, // Packet received from WDS + fRX_MESH = 0x1000, // Packet received from MESH + fRX_DLS = 0x2000, // Packet received from DLS peer + fRX_TDLS = 0x4000, // Packet received from TDLS peer +}RX_BLK_FLAGS; + +typedef struct _RX_BLK +{ + UCHAR hw_rx_info[RXD_SIZE]; /* include "RXD_STRUC RxD" and "RXINFO_STRUC rx_info " */ + RXINFO_STRUC *pRxInfo; /* for RLT, in head of frame buffer, for RTMP, in hw_rx_info[RXINFO_OFFSET] */ +#ifdef RLT_MAC + RXFCE_INFO *pRxFceInfo; /* for RLT, in in hw_rx_info[RXINFO_OFFSET], for RTMP, no such field */ +#endif /* RLT_MAC */ + RXWI_STRUC *pRxWI; /*in frame buffer and after "rx_info" fields */ + HEADER_802_11 *pHeader; /* poiter of 802.11 header, pointer to frame buffer and shall not shift this pointer */ + PNDIS_PACKET pRxPacket; /* os_packet pointer, shall not change */ + UCHAR *pData; /* init to pRxPacket->data, refer to frame buffer, may changed depends on processing */ + USHORT DataSize; /* init to RXWI->MPDUtotalByteCnt, and may changes depends on processing */ + USHORT Flags; + + /* Mirror info of partial fields of RxWI and RxInfo */ + USHORT MPDUtotalByteCnt; /* Refer to RXWI->MPDUtotalByteCnt */ + UCHAR UserPriority; /* for calculate TKIP MIC using */ + UCHAR OpMode; /* 0:OPMODE_STA 1:OPMODE_AP */ + UCHAR wcid; /* copy of pRxWI->wcid */ + UCHAR U2M; + UCHAR key_idx; + UCHAR bss_idx; + UCHAR TID; + CHAR rssi[3]; + CHAR snr[3]; + CHAR freq_offset; + CHAR ldpc_ex_sym; + HTTRANSMIT_SETTING rx_rate; +#ifdef HDR_TRANS_SUPPORT + BOOLEAN bHdrRxTrans; /* this packet's header is translated to 802.3 by HW */ + BOOLEAN bHdrVlanTaged; /* VLAN tag is added to this header */ + UCHAR *pTransData; + USHORT TransDataSize; +#endif /* HDR_TRANS_SUPPORT */ + +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU + UCHAR CriticalPkt; +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + UINT64 CCMP_PN; +} RX_BLK; + + +#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) +#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) +#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) + + +#define fRX_WDS 0x0001 +#define fRX_AMSDU 0x0002 +#define fRX_ARALINK 0x0004 +#define fRX_HTC 0x0008 +#define fRX_PAD 0x0010 +#define fRX_AMPDU 0x0020 +#define fRX_QOS 0x0040 +#define fRX_INFRA 0x0080 +#define fRX_EAP 0x0100 +#define fRX_MESH 0x0200 +#define fRX_APCLI 0x0400 +#define fRX_DLS 0x0800 +#define fRX_WPI 0x1000 +#define fRX_P2PGO 0x2000 +#define fRX_P2PCLI 0x4000 + +#define AMSDU_SUBHEAD_LEN 14 +#define ARALINK_SUBHEAD_LEN 14 +#define ARALINK_HEADER_LEN 2 + + +/*************************************************************************** + * Tx Path software control block related data structures + **************************************************************************/ +#define TX_UNKOWN_FRAME 0x00 +#define TX_MCAST_FRAME 0x01 +#define TX_LEGACY_FRAME 0x02 +#define TX_AMPDU_FRAME 0x04 +#define TX_AMSDU_FRAME 0x08 +#define TX_RALINK_FRAME 0x10 +#define TX_FRAG_FRAME 0x20 +#define TX_NDPA_FRAME 0x40 + + +/* Currently the sizeof(TX_BLK) is 148 bytes. */ +typedef struct _TX_BLK { + UCHAR QueIdx; + UCHAR TxFrameType; /* Indicate the Transmission type of the all frames in one batch */ + UCHAR TotalFrameNum; /* Total frame number want to send-out in one batch */ + USHORT TotalFragNum; /* Total frame fragments required in one batch */ + USHORT TotalFrameLen; /* Total length of all frames want to send-out in one batch */ + + QUEUE_HEADER TxPacketList; + MAC_TABLE_ENTRY *pMacEntry; /* NULL: packet with 802.11 RA field is multicast/broadcast address */ + HTTRANSMIT_SETTING *pTransmit; + + /* Following structure used for the characteristics of a specific packet. */ + PNDIS_PACKET pPacket; + UCHAR *pSrcBufHeader; /* Reference to the head of sk_buff->data */ + UCHAR *pSrcBufData; /* Reference to the sk_buff->data, will changed depends on hanlding progresss */ + UINT SrcBufLen; /* Length of packet payload which not including Layer 2 header */ + + PUCHAR pExtraLlcSnapEncap; /* NULL means no extra LLC/SNAP is required */ +#ifndef VENDOR_FEATURE1_SUPPORT + /* + Note: Can not insert any other new parameters + between pExtraLlcSnapEncap & HeaderBuf; Or + the start address of HeaderBuf will not be aligned by 4. + + But we can not change HeaderBuf[128] to HeaderBuf[32] because + many codes use HeaderBuf[index]. + */ + UCHAR HeaderBuf[128]; /* TempBuffer for TX_INFO + TX_WI + TSO_INFO + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP */ +#else + UINT32 HeaderBuffer[32]; /* total 128B, use UINT32 to avoid alignment problem */ + UCHAR *HeaderBuf; +#endif /* VENDOR_FEATURE1_SUPPORT */ + UCHAR MpduHeaderLen; /* 802.11 header length NOT including the padding */ + UCHAR HdrPadLen; /* recording Header Padding Length; */ + UCHAR UserPriority; /* priority class of packet */ + UCHAR FrameGap; /* what kind of IFS this packet use */ + UCHAR MpduReqNum; /* number of fragments of this frame */ +// TODO: shiang-6590, potential to remove + UCHAR TxRate; /* TODO: Obsoleted? Should change to MCS? */ + UCHAR CipherAlg; /* cipher alogrithm */ + PCIPHER_KEY pKey; + UCHAR KeyIdx; /* Indicate the transmit key index */ + UCHAR OpMode; + UCHAR Wcid; /* The MAC entry associated to this packet */ + UCHAR apidx; /* The interface associated to this packet */ + UCHAR wdev_idx; // Used to replace apidx + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + UINT ApCliIfidx; + PAPCLI_STRUCT pApCliEntry; +#endif /* APCLI_SUPPORT */ + + MULTISSID_STRUCT *pMbss; + +#endif /* CONFIG_AP_SUPPORT */ +// TODO: ---End + + UINT32 Flags; /*See following definitions for detail. */ + + /*YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. */ + ULONG Priv; /* Hardware specific value saved in here. */ + +#ifdef TXBF_SUPPORT + UCHAR TxSndgPkt; /* 1: sounding 2: NDP sounding */ + UCHAR TxNDPSndgBW; + UCHAR TxNDPSndgMcs; +#endif /* TXBF_SUPPORT */ + +#ifdef TX_PKT_SG + PACKET_INFO pkt_info; +#endif /* TX_PKT_SG */ + +#ifdef HDR_TRANS_SUPPORT + BOOLEAN NeedTrans; /* indicate the packet needs to do hw header translate */ +#endif /* HDR_TRANS_SUPPORT */ + + struct wifi_dev *wdev; +} TX_BLK; + + +#define fTX_bRtsRequired 0x0001 /* Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. */ +#define fTX_bAckRequired 0x0002 /* the packet need ack response */ +#define fTX_bPiggyBack 0x0004 /* Legacy device use Piggback or not */ +#define fTX_bHTRate 0x0008 /* allow to use HT rate */ +#define fTX_bForceNonQoS 0x0010 /* force to transmit frame without WMM-QoS in HT mode */ +#define fTX_bAllowFrag 0x0020 /* allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment */ +#define fTX_bMoreData 0x0040 /* there are more data packets in PowerSave Queue */ +#define fTX_bWMM 0x0080 /* QOS Data */ +#define fTX_bClearEAPFrame 0x0100 + +#define fTX_bSwEncrypt 0x0400 /* this packet need to be encrypted by software before TX */ +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#define fTX_bApCliPacket 0x0200 +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT +#define fTX_bWDSEntry 0x1000 /* Used when WDS_SUPPORT */ +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef UAPSD_SUPPORT +#define fTX_bWMM_UAPSD_EOSP 0x0800 /* Used when UAPSD_SUPPORT */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT +#define fTX_bDonglePkt 0x2000 /* Used when ETH_CONVERT_SUPPORT */ +#endif /* ETH_CONVERT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef WAPI_SUPPORT +#define fTX_bWPIDataFrame 0x8000 /* indicate this packet is an WPI data frame, it need to be encrypted by software */ +#endif /* WAPI_SUPPORT */ + +#ifdef CLIENT_WDS +#define fTX_bClientWDSFrame 0x10000 +#endif /* CLIENT_WDS */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#define fTX_bTdlsEntry 0x20000 /* Used when DOT11Z_TDLS_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef WFA_VHT_PF +#define fTX_AmsduInAmpdu 0x40000 +#endif /* WFA_VHT_PF */ + +#ifdef MWDS +#define fTX_bMWDSFrame 0x80000 +#endif /* MWDS */ + +#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag) +#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0) +#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag)) + + + +typedef struct dequeue_info{ + UCHAR qidx; + UCHAR wcid; + INT pkt_bytes; + INT pkt_cnt; +}DEQUE_INFO; + + +#ifdef RT_BIG_ENDIAN +/*************************************************************************** + * Endian conversion related functions + **************************************************************************/ +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +static inline VOID RTMPWIEndianChange( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pData, + IN ULONG DescriptorType) +{ + int size; + int i; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 RXWISize = pAd->chipCap.RXWISize; + + size = ((DescriptorType == TYPE_TXWI) ? TXWISize : RXWISize); + + if(DescriptorType == TYPE_TXWI) + { + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); /* Byte 0~3 */ + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4))); /* Byte 4~7 */ + if (size > 16) + *((UINT32 *)(pData + 16)) = SWAP32(*((UINT32 *)(pData + 16))); /* Byte 16~19 */ + } + else + { + for(i=0; i < size/4 ; i++) + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } +} + + +#ifdef RTMP_MAC_PCI +static inline VOID WriteBackToDescriptor( + IN UCHAR *Dest, + IN UCHAR *Src, + IN BOOLEAN DoEncrypt, + IN ULONG DescriptorType) +{ + UINT32 *p1, *p2; + + p1 = ((UINT32 *)Dest); + p2 = ((UINT32 *)Src); + + *p1 = *p2; + *(p1+2) = *(p2+2); + *(p1+3) = *(p2+3); + *(p1+1) = *(p2+1); /* Word 1; this must be written back last */ +} +#endif /* RTMP_MAC_PCI */ + + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +#ifdef RTMP_MAC_PCI +static inline VOID RTMPDescriptorEndianChange(UCHAR *pData, ULONG DescType) +{ + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); /* Byte 0~3 */ + *((UINT32 *)(pData + 8)) = SWAP32(*((UINT32 *)(pData+8))); /* Byte 8~11 */ + *((UINT32 *)(pData +12)) = SWAP32(*((UINT32 *)(pData + 12))); /* Byte 12~15 */ + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData + 4))); /* Byte 4~7, this must be swapped last */ +} +#endif /* RTMP_MAC_PCI */ + +/* + ======================================================================== + + Routine Description: + Endian conversion of all kinds of 802.11 frames . + + Arguments: + pAd Pointer to our adapter + pData Pointer to the 802.11 frame structure + Dir Direction of the frame + FromRxDoneInt Caller is from RxDone interrupt + + Return Value: + None + + Note: + Call this function when read or update buffer data + ======================================================================== +*/ +static inline VOID RTMPFrameEndianChange( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt) +{ + PHEADER_802_11 pFrame; + PUCHAR pMacHdr; + + /* swab 16 bit fields - Frame Control field */ + if(Dir == DIR_READ) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } + + pFrame = (PHEADER_802_11) pData; + pMacHdr = (PUCHAR) pFrame; + + /* swab 16 bit fields - Duration/ID field */ + *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2)); + + if (pFrame->FC.Type != FC_TYPE_CNTL) + { + /* swab 16 bit fields - Sequence Control field */ + *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22)); + } + + if(pFrame->FC.Type == FC_TYPE_MGMT) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + case SUBTYPE_REASSOC_REQ: + /* swab 16 bit fields - CapabilityInfo field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Listen Interval field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_ASSOC_RSP: + case SUBTYPE_REASSOC_RSP: + /* swab 16 bit fields - CapabilityInfo field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Status Code field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - AID field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_AUTH: + /* When the WEP bit is on, don't do the conversion here. + This is only shared WEP can hit this condition. + For AP, it shall do conversion after decryption. + For STA, it shall do conversion before encryption. */ + if (pFrame->FC.Wep == 1) + break; + else + { + /* swab 16 bit fields - Auth Alg No. field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Auth Seq No. field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Status Code field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } + break; + + case SUBTYPE_BEACON: + case SUBTYPE_PROBE_RSP: + /* swab 16 bit fields - BeaconInterval field */ + pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - CapabilityInfo field */ + pMacHdr += sizeof(USHORT); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_DEAUTH: + case SUBTYPE_DISASSOC: + /* If the PMF is negotiated, those frames shall be encrypted */ + if(!FromRxDoneInt && pFrame->FC.Wep == 1) + break; + else + { + /* swab 16 bit fields - Reason code field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } + break; + } + } + else if( pFrame->FC.Type == FC_TYPE_DATA ) + { + } + else if(pFrame->FC.Type == FC_TYPE_CNTL) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: + { + PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame; + *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl)); + pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word); + } + break; + case SUBTYPE_BLOCK_ACK: + /* For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3 */ + *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0])); + break; + + case SUBTYPE_ACK: + /*For ACK packet, the HT_CONTROL field is in the same offset with Addr2 */ + *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0])); + break; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n")); + } + + /* swab 16 bit fields - Frame Control */ + if(Dir == DIR_WRITE) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } +} +#endif /* RT_BIG_ENDIAN */ + + +/*************************************************************************** + * Other static inline function definitions + **************************************************************************/ +static inline VOID ConvertMulticastIP2MAC( + IN PUCHAR pIpAddr, + IN PUCHAR *ppMacAddr, + IN UINT16 ProtoType) +{ + if (pIpAddr == NULL) + return; + + if (ppMacAddr == NULL || *ppMacAddr == NULL) + return; + + switch (ProtoType) + { + case ETH_P_IPV6: +/* memset(*ppMacAddr, 0, MAC_ADDR_LEN); */ + *(*ppMacAddr) = 0x33; + *(*ppMacAddr + 1) = 0x33; + *(*ppMacAddr + 2) = pIpAddr[12]; + *(*ppMacAddr + 3) = pIpAddr[13]; + *(*ppMacAddr + 4) = pIpAddr[14]; + *(*ppMacAddr + 5) = pIpAddr[15]; + break; + + case ETH_P_IP: + default: +/* memset(*ppMacAddr, 0, MAC_ADDR_LEN); */ + *(*ppMacAddr) = 0x01; + *(*ppMacAddr + 1) = 0x00; + *(*ppMacAddr + 2) = 0x5e; + *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; + *(*ppMacAddr + 4) = pIpAddr[2]; + *(*ppMacAddr + 5) = pIpAddr[3]; + break; + } + + return; +} + + +char *get_phymode_str(int phy_mode); +char *get_bw_str(int bandwidth); + + +BOOLEAN RTMPCheckForHang( + IN NDIS_HANDLE MiniportAdapterContext); + +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd); + +#ifdef RESOURCE_PRE_ALLOC +NDIS_STATUS RTMPInitTxRxRingMemory(RTMP_ADAPTER *pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +VOID get_dev_config_idx(RTMP_ADAPTER *pAd); +UCHAR *get_dev_name_prefix(RTMP_ADAPTER *pAd, INT dev_type); + +NDIS_STATUS RTMPReadParametersHook(RTMP_ADAPTER *pAd); +NDIS_STATUS RTMPSetProfileParameters(RTMP_ADAPTER *pAd, PSTRING pBuffer); + +INT RTMPGetKeyParameter( + IN PSTRING key, + OUT PSTRING dest, + IN INT destsize, + IN PSTRING buffer, + IN BOOLEAN bTrimSpace); + +#ifdef WSC_INCLUDED +VOID rtmp_read_wsc_user_parms_from_file( + IN RTMP_ADAPTER *pAd, + IN char *tmpbuf, + IN char *buffer); +#endif/*WSC_INCLUDED*/ + +#ifdef SINGLE_SKU_V2 +NDIS_STATUS RTMPSetSingleSKUParameters(IN RTMP_ADAPTER *pAd, CHAR *sku_path); + +VOID UpdateSkuRatePwr(RTMP_ADAPTER *pAd, UCHAR ch, UCHAR bw, CHAR base_pwr); +INT Set_Single_Sku_Debug_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#endif /* SINGLE_SKU_V2 */ + + +#ifdef RTMP_RF_RW_SUPPORT +VOID NICInitRFRegisters( + IN PRTMP_ADAPTER pAd); + +VOID RTMP_ReadRF( + IN RTMP_ADAPTER *pAd, + IN UCHAR RegID, + OUT PUCHAR pValue1, + OUT PUCHAR pValue2, + IN UCHAR BitMask); + +VOID RTMP_WriteRF( + IN RTMP_ADAPTER *pAd, + IN UCHAR RegID, + IN UCHAR Value, + IN UCHAR BitMask); + +NDIS_STATUS RT30xxWriteRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS RT30xxReadRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR regID, + IN PUCHAR pValue); + +NDIS_STATUS RT635xWriteRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS RT635xReadRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN PUCHAR pValue); + +BOOLEAN RTMPAdjustFrequencyOffset( + IN RTMP_ADAPTER *pAd, + INOUT PUCHAR pRefFreqOffset); +#endif /* RTMP_RF_RW_SUPPORT */ + +BOOLEAN RTMPCheckPhyMode( + IN RTMP_ADAPTER *pAd, + IN UINT8 BandSupported, + INOUT UCHAR *pPhyMode); + +#ifdef RLT_RF +NDIS_STATUS rlt_rf_write( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS rlt_rf_read( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR *pValue); +#endif /* RLT_RF */ + +NDIS_STATUS rtmp_rf_write( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS rtmp_rf_read( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR *pValue); + +VOID NICReadEEPROMParameters(RTMP_ADAPTER *pAd, PSTRING mac_addr); +VOID NICInitAsicFromEEPROM(RTMP_ADAPTER *pAd); + +NDIS_STATUS NICInitializeAdapter(RTMP_ADAPTER *pAd, BOOLEAN bHardReset); +NDIS_STATUS NICInitializeAsic(RTMP_ADAPTER *pAd, BOOLEAN bHardReset); + +#ifdef RTMP_RBUS_SUPPORT +VOID NICResetFromError(RTMP_ADAPTER *pAd); +#endif /* RTMP_RBUS_SUPPORT */ + +VOID RTMPRingCleanUp( + IN RTMP_ADAPTER *pAd, + IN UCHAR RingType); + +VOID UserCfgExit(RTMP_ADAPTER *pAd); +VOID UserCfgInit(RTMP_ADAPTER *pAd); + +int load_patch(RTMP_ADAPTER *ad); +VOID erase_patch(RTMP_ADAPTER *ad); +NDIS_STATUS NICLoadFirmware(RTMP_ADAPTER *pAd); +VOID NICEraseFirmware(RTMP_ADAPTER *pAd); + +VOID NICUpdateFifoStaCounters(RTMP_ADAPTER *pAd); +VOID NICUpdateRawCounters(RTMP_ADAPTER *pAd); +#ifdef CONFIG_AP_SUPPORT +VOID ClearTxRingClientAck(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID ApTxFailCntUpdate(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, ULONG TxSuccess, ULONG TxRetransmit); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef FIFO_EXT_SUPPORT +BOOLEAN NicGetMacFifoTxCnt( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN IsFifoExtTblAvailable(IN RTMP_ADAPTER *pAd, IN UCHAR *pTblIdx); +VOID FifoExtTblUpdateEntry(IN RTMP_ADAPTER *pAd, IN UCHAR tblIdx, IN UCHAR wcid); +VOID FifoExtTblRmReptEntry(IN RTMP_ADAPTER *pAd, IN UCHAR wcid); +VOID FifoExtTableInit(RTMP_ADAPTER *pAd); +VOID AsicFifoExtSet(RTMP_ADAPTER *pAd); +VOID AsicFifoExtEntryClean(RTMP_ADAPTER * pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* FIFO_EXT_SUPPORT */ + +VOID NicResetRawCounters(RTMP_ADAPTER *pAd); + +VOID NicGetTxRawCounters( + IN RTMP_ADAPTER *pAd, + IN TX_STA_CNT0_STRUC *pStaTxCnt0, + IN TX_STA_CNT1_STRUC *pStaTxCnt1); + +VOID NicGetTxRTSCounters( + IN RTMP_ADAPTER *pAd, + IN RTS_TX_CNT_STRUC *pRtsTxCnt); + +VOID RTMPZeroMemory(VOID *pSrc, ULONG Length); +ULONG RTMPCompareMemory(VOID *pSrc1, VOID *pSrc2, ULONG Length); +VOID RTMPMoveMemory(VOID *pDest, VOID *pSrc, ULONG Length); + +VOID AtoH(PSTRING src, UCHAR *dest, INT srclen); +UCHAR BtoH(char ch); + +VOID RTMP_TimerListAdd(RTMP_ADAPTER *pAd, VOID *pRsc); +VOID RTMP_TimerListRelease(RTMP_ADAPTER *pAd, VOID *pRsc); +VOID RTMP_AllTimerListRelease(RTMP_ADAPTER *pAd); + +VOID RTMPInitTimer( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer, + IN VOID *pTimerFunc, + IN VOID *pData, + IN BOOLEAN Repeat); + +VOID RTMPSetTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value); +VOID RTMPModTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value); +VOID RTMPCancelTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled); +VOID RTMPReleaseTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled); + +VOID RTMPEnableRxTx(RTMP_ADAPTER *pAd); + +VOID AntCfgInit(RTMP_ADAPTER *pAd); + +/* */ +/* prototype in action.c */ +/* */ +VOID ActHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT HEADER_802_11 *pHdr80211, + IN UCHAR *da, + IN UCHAR *sa, + IN UCHAR *bssid); + +VOID ActionStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeADDBAAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDELBAAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID SendSMPSAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR smps); + +#ifdef CONFIG_AP_SUPPORT +VOID SendBeaconRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +VOID DlsParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, + IN PRT_802_11_DLS pDls, + IN USHORT reason); +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +VOID RECBATimerTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID SendRefreshBAR( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +#ifdef DOT11N_DRAFT3 +VOID RTMP_11N_D3_TimerInit( + IN RTMP_ADAPTER *pAd); + +VOID SendBSS2040CoexistMgmtAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq); + +VOID SendNotifyBWActionFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR apidx); + +BOOLEAN ChannelSwitchSanityCheck( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary); + +VOID ChannelSwitchAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR Channel, + IN UCHAR Secondary); + +ULONG BuildIntolerantChannelRep( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDest); + +VOID Update2040CoexistFrameAndNotify( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID Send2040CoexistAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID UpdateBssScanParm( + IN RTMP_ADAPTER *pAd, + IN OVERLAP_BSS_SCAN_IE APBssScan); +#endif /* DOT11N_DRAFT3 */ + +INT AsicSetRalinkBurstMode(RTMP_ADAPTER *pAd, BOOLEAN enable); +#endif /* DOT11_N_SUPPORT */ + +VOID AsicSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble); + +VOID BarHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA); + +VOID InsertActField( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +BOOLEAN QosBADataParse( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bAMSDU, + IN PUCHAR p8023Header, + IN UCHAR WCID, + IN UCHAR TID, + IN USHORT Sequence, + IN UCHAR DataOffset, + IN USHORT Datasize, + IN UINT CurRxIndex); + +#ifdef DOT11_N_SUPPORT +BOOLEAN CntlEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg); + +VOID BaAutoManSwitch( + IN RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID HTIOTCheck( + IN RTMP_ADAPTER *pAd, + IN UCHAR BatRecIdx); + + +INT rtmp_wdev_idx_reg(RTMP_ADAPTER *pAd, struct wifi_dev *wdev); +INT rtmp_wdev_idx_unreg(RTMP_ADAPTER *pAd, struct wifi_dev *wdev); +VOID wdev_tx_pkts(NDIS_HANDLE dev_hnd, PPNDIS_PACKET pkt_list, UINT pkt_cnt, struct wifi_dev *wdev); + +#ifdef DOT11_N_SUPPORT +VOID RTMP_BASetup( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN UINT8 UserPriority); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPDeQueuePacket( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bIntContext, + IN UCHAR QueIdx, + IN INT Max_Tx_Packets); +#ifdef CUSTOMER_DCC_FEATURE +VOID APGetStreamingStatus( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN TX_BLK TxBlk); + +VOID RTMPCalculateAPTxRxActivityTime( + IN PRTMP_ADAPTER pAd, + IN UINT32 Index, + IN UINT32 Length, + IN PMULTISSID_STRUCT pMbss, + IN PMAC_TABLE_ENTRY pMacEntry); + +VOID GetMultShiftFactorIndex( + IN HTTRANSMIT_SETTING HTSetting, + IN INT32 *Index); + +VOID InitRateMultiplicationAndShiftFactor( + IN PRTMP_ADAPTER pAd); +#endif + +NDIS_STATUS RTMPFreeTXDRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR RingType, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs); + +NDIS_STATUS MlmeHardTransmit( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgDataQForce, + IN BOOLEAN FlgIsLocked, + IN BOOLEAN FlgIsCheckPS); + + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +#ifdef RTMP_MAC_PCI +NDIS_STATUS MlmeHardTransmitTxRing( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeDataHardTransmit( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +VOID ral_write_txd( + IN RTMP_ADAPTER *pAd, + IN TXD_STRUC *pTxD, + IN TXINFO_STRUC *pTxInfo, + IN BOOLEAN bWIV, + IN UCHAR QSEL); +#endif /* RTMP_MAC_PCI */ + +USHORT RTMPCalcDuration( + IN RTMP_ADAPTER *pAd, + IN UCHAR Rate, + IN ULONG Size); + +VOID RTMPWriteTxWI( + IN RTMP_ADAPTER *pAd, + IN TXWI_STRUC *pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, /* HW new a sequence. */ + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN HTTRANSMIT_SETTING *pTransmit); + + +VOID RTMPWriteTxWI_Data( + IN RTMP_ADAPTER *pAd, + INOUT TXWI_STRUC *pTxWI, + IN TX_BLK *pTxBlk); + + +VOID RTMPWriteTxWI_Cache( + IN RTMP_ADAPTER *pAd, + INOUT TXWI_STRUC *pTxWI, + IN TX_BLK *pTxBlk); + +VOID RTMPSuspendMsduTransmission( + IN RTMP_ADAPTER *pAd); + +VOID RTMPResumeMsduTransmission( + IN RTMP_ADAPTER *pAd); + +NDIS_STATUS MiniportMMRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN UCHAR *pData, + IN UINT Length); + +VOID RTMPSendNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN USHORT PwrMgmt); + +#ifdef APCLI_SUPPORT +VOID ApCliRTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey, + IN INT ifIndex); + +VOID ApCliWpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif/*APCLI_SUPPORT*/ + + + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx); + +BOOLEAN RTMPCheckEtherType( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN struct wifi_dev *wdev, + OUT PUCHAR pUserPriority, + OUT PUCHAR pQueIdx); + +#ifdef FORCE_ANNOUNCE_CRITICAL_AMPDU +VOID RTMP_RxPacketClassify( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry); +#endif /* FORCE_ANNOUNCE_CRITICAL_AMPDU */ + +VOID RTMPCckBbpTuning( + IN RTMP_ADAPTER *pAd, + IN UINT TxRate); + +#ifdef RT6352 +VOID InitRfPaModeTable( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RT6352 */ + +/* + MLME routines +*/ + +/* Asic/RF/BBP related functions */ +VOID AsicGetTxPowerOffset( + IN PRTMP_ADAPTER pAd, + IN PULONG TxPwr); + +VOID AsicGetAutoAgcOffsetForExternalTxAlc( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + +VOID AsicExtraPowerOverMAC(RTMP_ADAPTER *pAd); + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID AsicGetAutoAgcOffsetForTemperatureSensor( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#ifdef SINGLE_SKU +VOID GetSingleSkuDeltaPower( + IN RTMP_ADAPTER *pAd, + IN PCHAR pTotalDeltaPower, + INOUT PULONG pSingleSKUTotalDeltaPwr, + INOUT PUCHAR pSingleSKUBbpR1Offset); +#endif /* SINGLE_SKU*/ + +VOID AsicPercentageDeltaPower( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + INOUT PCHAR pDeltaPwr, + INOUT PCHAR pDeltaPowerByBbpR1); + +VOID AsicCompensatePowerViaBBP( + IN RTMP_ADAPTER *pAd, + INOUT CHAR *pTotalDeltaPower); + +VOID AsicAdjustTxPower(RTMP_ADAPTER *pAd); + +VOID AsicUpdateProtect( + IN RTMP_ADAPTER *pAd, + IN USHORT OperaionMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist); + +VOID AsicBBPAdjust( + IN RTMP_ADAPTER *pAd); + +VOID AsicSwitchChannel( + IN RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +INT AsicSetChannel( + IN RTMP_ADAPTER *pAd, + IN UCHAR ch, + IN UINT8 bw, + IN UINT8 ext_ch, + IN BOOLEAN bScan); + +#ifdef THERMAL_PROTECT_SUPPORT +VOID thermal_protection( + IN PRTMP_ADAPTER pAd); +#endif /* THERMAL_PROTECT_SUPPORT */ + +VOID AsicLockChannel(RTMP_ADAPTER *pAd, UCHAR Channel); +VOID AsicAntennaSelect(RTMP_ADAPTER *pAd, UCHAR Channel); + +VOID AsicResetBBPAgent(RTMP_ADAPTER *pAd); + +#ifdef CONFIG_STA_SUPPORT +VOID AsicSleepThenAutoWakeup(RTMP_ADAPTER *pAd, USHORT TbttNumToNextWakeUp); +VOID AsicForceSleep(RTMP_ADAPTER *pAd); +VOID AsicForceWakeup(RTMP_ADAPTER *pAd, BOOLEAN bFromTx); +#endif /* CONFIG_STA_SUPPORT */ + +INT AsicSetDevMac(RTMP_ADAPTER *pAd, UCHAR *addr); +VOID AsicSetBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid); + +VOID AsicDelWcidTab(RTMP_ADAPTER *pAd, UCHAR Wcid); + +#ifdef MAC_APCLI_SUPPORT +VOID AsicSetApCliBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid, UCHAR index); +#endif /* MAC_APCLI_SUPPORT */ + +INT AsicSetRxFilter(RTMP_ADAPTER *pAd); + +#ifdef DOT11_N_SUPPORT +INT AsicSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable); +#endif /* DOT11_N_SUPPORT */ + +VOID AsicCtrlBcnMask(PRTMP_ADAPTER pAd, INT mask); +INT AsicSetPreTbtt(RTMP_ADAPTER *pAd, BOOLEAN enable); +INT AsicSetGPTimer(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 timeout); + +VOID AsicDisableSync(RTMP_ADAPTER *pAd); +VOID AsicEnableBssSync(RTMP_ADAPTER *pAd); +VOID AsicEnableApBssSync(RTMP_ADAPTER *pAd); +VOID AsicEnableIbssSync(RTMP_ADAPTER *pAd); + +VOID AsicSetEdcaParm(RTMP_ADAPTER *pAd, PEDCA_PARM pEdcaParm); + +INT AsicSetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type, UINT32 limit); +UINT32 AsicGetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type); + +VOID AsicSetSlotTime(RTMP_ADAPTER *pAd, BOOLEAN bUseShortSlotTime); + +VOID AsicAddSharedKeyEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey); + +VOID AsicRemoveSharedKeyEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx); + +VOID AsicUpdateWCIDIVEIV( + IN RTMP_ADAPTER *pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV); + +VOID AsicUpdateRxWCIDTable( + IN RTMP_ADAPTER *pAd, + IN USHORT WCID, + IN PUCHAR pAddr); + +VOID AsicUpdateWcidAttributeEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN UINT8 Wcid, + IN UINT8 KeyTabFlag); + +VOID AsicAddPairwiseKeyEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR WCID, + IN PCIPHER_KEY pCipherKey); + +VOID AsicRemovePairwiseKeyEntry(RTMP_ADAPTER *pAd, UCHAR Wcid); + +#ifdef CONFIG_AP_SUPPORT +VOID AsicSetMbssMode(RTMP_ADAPTER *pAd, UCHAR NumOfBcns); +#endif /* CONFIG_AP_SUPPORT */ + +BOOLEAN AsicSendCommandToMcu( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic); + +BOOLEAN AsicSendCmdToMcuAndWait( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic); + +BOOLEAN AsicSendCommandToMcuBBP( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked); + +#ifdef RTMP_RBUS_SUPPORT +int RtmpAsicSendCommandToSwMcu( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked); +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef RTMP_MAC_PCI +BOOLEAN AsicCheckCommanOk(RTMP_ADAPTER *pAd, UCHAR Command); +#endif /* RTMP_MAC_PCI */ + +#ifdef WAPI_SUPPORT +VOID AsicUpdateWAPIPN( + IN RTMP_ADAPTER *pAd, + IN USHORT WCID, + IN ULONG pn_low, + IN ULONG pn_high); +#endif /* WAPI_SUPPORT */ + +#ifdef VCORECAL_SUPPORT +VOID AsicVCORecalibration(RTMP_ADAPTER *pAd); +#endif /* VCORECAL_SUPPORT */ + +#ifdef MCS_LUT_SUPPORT +VOID asic_mcs_lut_update( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); +#endif /* MCS_LUT_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT +UINT32 StreamModeRegVal( + IN RTMP_ADAPTER *pAd); + +VOID AsicSetStreamMode( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddr, + IN INT chainIdx, + IN BOOLEAN bEnabled); + +VOID RtmpStreamModeInit( + IN RTMP_ADAPTER *pAd); + +/* + Update the Tx chain address + Parameters + pAd: The adapter data structure + pMacAddress: The MAC address of the peer STA + + Return Value: + None +*/ +VOID AsicUpdateTxChainAddress( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddress); + +INT Set_StreamMode_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_StreamModeMac_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_StreamModeMCS_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* STREAM_MODE_SUPPORT */ + + +VOID MacAddrRandomBssid( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pAddr); + +VOID MgtMacHeaderInit( + IN RTMP_ADAPTER *pAd, + INOUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pDA, + IN UCHAR *pSA, + IN UCHAR *pBssid); + +VOID MgtMacHeaderInitExt( + IN RTMP_ADAPTER *pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pBssid); + +VOID MlmeRadioOff( + IN RTMP_ADAPTER *pAd); + +VOID MlmeRadioOn( + IN RTMP_ADAPTER *pAd); + + +VOID BssTableInit( + IN BSS_TABLE *Tab); + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN RTMP_ADAPTER *pAd, + IN BA_TABLE *Tab); + +VOID BATableExit( + IN RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef ED_MONITOR +ULONG BssChannelAPCount( + IN PRTMP_ADAPTER pAd, + IN BSS_TABLE *Tab, + IN UCHAR Channel); +#endif /* ED_MONITOR */ + +ULONG BssTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +ULONG BssSsidTableSearchBySSID( + IN BSS_TABLE *Tab, + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID BssTableDeleteEntry( + IN OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +ULONG BssTableSetEntry( + IN RTMP_ADAPTER *pAd, + OUT BSS_TABLE *Tab, + IN BCN_IE_LIST *ie_list, + IN CHAR Rssi, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE +#ifdef CUSTOMER_DCC_FEATURE + , + IN UCHAR Snr0, + IN UCHAR Snr1 +#endif + ); + + +#ifdef DOT11_N_SUPPORT +VOID BATableInsertEntry( + IN RTMP_ADAPTER *pAd, + IN USHORT Aid, + IN USHORT TimeOutValue, + IN USHORT StartingSeq, + IN UCHAR TID, + IN UCHAR BAWinSize, + IN UCHAR OriginatorStatus, + IN BOOLEAN IsRecipient); + +#ifdef DOT11N_DRAFT3 +VOID Bss2040CoexistTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID TriEventInit( + IN RTMP_ADAPTER *pAd); + +INT TriEventTableSetEntry( + IN RTMP_ADAPTER *pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo); + +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +VOID BssTableSsidSort( + IN RTMP_ADAPTER *pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab, + IN BOOLEAN isInverseOrder); + +VOID BssCipherParse(BSS_ENTRY *pBss); + +NDIS_STATUS MlmeQueueInit( + IN RTMP_ADAPTER *pAd, +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *EAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *Queue); + +VOID MlmeQueueDestroy( +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *EAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *Queue); + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeEnqueue( + IN PRTMP_ADAPTER pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv); + +BOOLEAN MlmeEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, +#ifdef CUSTOMER_DCC_FEATURE + IN UCHAR Snr0, + IN UCHAR Snr1, +#endif + IN ULONG MsgLen, + IN PVOID Msg, + IN UCHAR Signal, + IN UCHAR OpMode); + +#ifdef WSC_INCLUDED +BOOLEAN MlmeEnqueueForWsc( + IN RTMP_ADAPTER *pAd, + IN ULONG eventID, + IN LONG senderID, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg); +#endif /* WSC_INCLUDED */ + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeDequeue( + IN EAP_MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); + +VOID MlmeRestartStateMachine( + IN RTMP_ADAPTER *pAd); + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueEmpty( + IN EAP_MLME_QUEUE *Queue); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue); + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueFull( + IN EAP_MLME_QUEUE *Queue); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue, + IN UCHAR SendId); + +BOOLEAN MsgTypeSubst( + IN RTMP_ADAPTER *pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID StateMachineInit( + IN STATE_MACHINE *Sm, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base); + +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + ULONG Msg, + IN STATE_MACHINE_FUNC F); + +VOID StateMachinePerformAction( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem, + IN ULONG CurrState); + +VOID Drop( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ReassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID DisassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +/*---------------------------------------------- */ +VOID MlmeDisassocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeAssocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeReassocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDisassocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAssocRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerReassocRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDisassocAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID DisassocTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReassocTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls3errAction( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr); + +VOID InvalidStateWhenAssoc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenReassoc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenDisassociate( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID ComposePsPoll( + IN RTMP_ADAPTER *pAd); + +VOID ComposeNullFrame( + IN RTMP_ADAPTER *pAd); + +VOID AssocPostProc( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN IE_LISTS *ie_list, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +VOID AuthStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN PSTATE_MACHINE sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeAuthReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq2Action( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq4Action( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AuthTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls2errAction( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr); + +VOID MlmeDeauthReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenAuth( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +/*============================================= */ + +VOID AuthRspStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID PeerDeauthAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthSimpleRspGenAndSend( + IN RTMP_ADAPTER *pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status); + +/* */ +/* Private routines in dls.c */ +/* */ +#ifdef CONFIG_AP_SUPPORT +#ifdef QOS_DLS_SUPPORT +VOID APDLSStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APPeerDlsReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDlsRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDlsTearDownAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +void DlsStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeDlsReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDlsTearDownAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsTearDownAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID RTMPCheckDLSTimeOut( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RTMPRcvFrameDLSCheck( + IN RTMP_ADAPTER *pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN RXINFO_STRUC *pRxInfo); + +INT RTMPCheckDLSFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pDA); + +VOID RTMPSendDLSTearDownFrame( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyRequest( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDA); + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN MlmeDlsReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason); + +INT Set_DlsEntryInfo_Display_Proc( + IN RTMP_ADAPTER *pAd, + IN PUCHAR arg); + +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx); + +BOOLEAN MacTableDeleteDlsEntry( + IN RTMP_ADAPTER *pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN RTMP_ADAPTER *pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +INT Set_DlsAddEntry_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_DlsTearDownEntry_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef QOS_DLS_SUPPORT +BOOLEAN PeerDlsReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pDlsTimeout, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDlsRspSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDlsTearDownSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason); +#endif /* QOS_DLS_SUPPORT */ + +BOOLEAN PeerProbeReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PEER_PROBE_REQ_PARAM *Param); + +/*======================================== */ + +VOID SyncStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenScan( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenJoin( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenStart( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID EnqueueProbeRequest( + IN RTMP_ADAPTER *pAd); + +BOOLEAN ScanRunning( + IN RTMP_ADAPTER *pAd); +/*========================================= */ + +VOID MlmeCntlInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeCntlMachinePerformAction( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlIdleProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidScanProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidSsidProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlOidRTBssidProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlMlmeRoamingProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlWaitDisassocProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitJoinProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitReassocProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitStartProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc2( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAssocProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID CntlOidDLSSetupProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#ifdef CONFIG_AP_SUPPORT +VOID APPeerWNMBTMQueryAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerWNMBTMRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerWNMDMSReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +VOID MlmeWNMBTMQueryAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeWNMDMSRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerWNMBTMReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +#endif /* CONFIG_STA_SUPPORT */ +#endif /* DOT11V_WNM_SUPPORT */ + +VOID LinkUp( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssType); + +VOID LinkDown( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN IsReqFromAP); + +VOID IterateOnBssTab( + IN RTMP_ADAPTER *pAd); + +VOID IterateOnBssTab2( + IN RTMP_ADAPTER *pAd); + +VOID JoinParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx); + +VOID AssocParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv); + +VOID ScanParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN STRING Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType); + +VOID DisassocParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason); + +VOID StartParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID AuthParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg); + +VOID EnqueuePsPoll( + IN RTMP_ADAPTER *pAd); + +VOID EnqueueBeaconFrame( + IN RTMP_ADAPTER *pAd); + +VOID MlmeJoinReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeStartReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeForceJoinReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeForceScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID BeaconTimeoutAtJoinAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtScanAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtJoinAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerProbeReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanNextChannel( + IN RTMP_ADAPTER *pAd, + IN UCHAR OpMode, + IN INT IfType); + + +ULONG MakeIbssBeacon( + IN RTMP_ADAPTER *pAd); + +BOOLEAN MlmeScanReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *BssType, + OUT CHAR ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *ScanType +#ifdef CONFIG_AP_SUPPORT +#ifdef CUSTOMER_DCC_FEATURE + , + OUT UINT *pChannel, + OUT UINT *pTimeout +#endif +#endif + ); + + +BOOLEAN PeerBeaconAndProbeRspSanity_Old( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + OUT UCHAR *pPreNHtCapabilityLen, +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + OUT UCHAR *pSelReg, +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + OUT HT_CAPABILITY_IE *pHtCapability, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannel, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE); + + +BOOLEAN PeerBeaconAndProbeRspSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT BCN_IE_LIST *ie_list, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE); + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN OVERLAP_BSS_SCAN_IE *BssScan, + OUT UCHAR *RegClass); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN PeerAddBAReqActionSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +BOOLEAN PeerAddBARspActionSanity( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN PeerDelBAActionSanity( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN MlmeAssocReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *CapabilityInfo, + OUT ULONG *Timeout, + OUT USHORT *ListenIntv); + +BOOLEAN MlmeAuthReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *Timeout, + OUT USHORT *Alg); + +BOOLEAN MlmeStartReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *Ssidlen); + +BOOLEAN PeerAuthSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *Alg, + OUT USHORT *Seq, + OUT USHORT *Status, + OUT CHAR ChlgText[]); + +BOOLEAN PeerAssocRspSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *ie_list); + +BOOLEAN PeerDisassocSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerDeauthSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr1, + OUT PUCHAR pAddr2, + OUT PUCHAR pAddr3, + OUT USHORT *Reason); + +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe); + +UCHAR ChannelSanity( + IN RTMP_ADAPTER *pAd, + IN UCHAR channel); + +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN BSS_ENTRY *pBss); + +BOOLEAN MlmeDelBAReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +BOOLEAN MlmeAddBAReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +ULONG MakeOutgoingFrame( + OUT UCHAR *Buffer, + OUT ULONG *Length, ...); + +UCHAR RandomByte( + IN RTMP_ADAPTER *pAd); + +UCHAR RandomByte2( + IN RTMP_ADAPTER *pAd); + +VOID AsicUpdateAutoFallBackTable(RTMP_ADAPTER *pAd, UCHAR *pTxRate); +INT AsicSetAutoFallBack(RTMP_ADAPTER *pAd, BOOLEAN enable); +INT AsicAutoFallbackInit(RTMP_ADAPTER *pAd); + + + +VOID MlmePeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID STAMlmePeriodicExec( + RTMP_ADAPTER *pAd); + +VOID MlmeAutoScan( + IN RTMP_ADAPTER *pAd); + +VOID MlmeAutoReconnectLastSSID( + IN RTMP_ADAPTER *pAd); + +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID MlmeCheckForRoaming( + IN RTMP_ADAPTER *pAd, + IN ULONG Now32); + +BOOLEAN MlmeCheckForFastRoaming( + IN RTMP_ADAPTER *pAd); + +#ifdef TXBF_SUPPORT +BOOLEAN MlmeTxBfAllowed( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN struct _RTMP_RA_LEGACY_TB *pTxRate); +#endif /* TXBF_SUPPORT */ + +VOID MlmeCalculateChannelQuality( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN ULONG Now); + +VOID MlmeCheckPsmChange( + IN RTMP_ADAPTER *pAd, + IN ULONG Now32); + +VOID MlmeSetPsmBit( + IN RTMP_ADAPTER *pAd, + IN USHORT psm); + +VOID MlmeSetTxPreamble( + IN RTMP_ADAPTER *pAd, + IN USHORT TxPreamble); + +VOID UpdateBasicRateBitmap( + IN RTMP_ADAPTER *pAd); + +VOID MlmeUpdateTxRates( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bLinkUp, + IN UCHAR apidx); + +#ifdef DOT11_N_SUPPORT +VOID MlmeUpdateHtTxRates( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPCheckRates( + IN RTMP_ADAPTER *pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen); + +BOOLEAN RTMPCheckHt( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + INOUT HT_CAPABILITY_IE *pHtCapability, + INOUT ADD_HT_INFO_IE *pAddHtInfo); + +#ifdef DOT11_VHT_AC +BOOLEAN RTMPCheckVht( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op); +#endif /* DOT11_VHT_AC */ + +VOID RTMPUpdateMlmeRate( + IN RTMP_ADAPTER *pAd); + +CHAR RTMPMaxRssi( + IN RTMP_ADAPTER *pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +CHAR RTMPAvgRssi( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi); + + +CHAR RTMPMinSnr( + IN RTMP_ADAPTER *pAd, + IN CHAR Snr0, + IN CHAR Snr1); + +VOID AsicSetRxAnt( + IN RTMP_ADAPTER *pAd, + IN UCHAR Ant); + +#ifdef MICROWAVE_OVEN_SUPPORT +INT Set_MO_FalseCCATh_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +VOID AsicMeasureFalseCCA( + IN RTMP_ADAPTER *pAd +); + +VOID AsicMitigateMicrowave( + IN RTMP_ADAPTER *pAd +); +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef RTMP_EFUSE_SUPPORT +INT set_eFuseGetFreeBlockCount_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT set_eFusedump_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT set_eFuseLoadFromBin_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +UCHAR eFuseReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData); + +VOID eFusePhysicalReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT *pData); + +int RtmpEfuseSupportCheck( + IN RTMP_ADAPTER *pAd); + +VOID eFuseGetFreeBlockCount( + IN PRTMP_ADAPTER pAd, + INOUT PUINT EfuseFreeBlock); + +INT eFuse_init( + IN PRTMP_ADAPTER pAd); + +INT efuse_probe( + IN RTMP_ADAPTER *pAd); + +NTSTATUS eFuseRead( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUSHORT pData, + IN USHORT Length); + +NTSTATUS eFuseWrite( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUSHORT pData, + IN USHORT length); + +#ifdef RALINK_ATE +INT Set_LoadEepromBufferFromEfuse_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT set_eFuseBufferModeWriteBack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef TXBF_SUPPORT +INT set_BinModeWriteBack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* TXBF_SUPPORT */ + +#endif /* RALINK_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ + + + + +VOID AsicEvaluateRxAnt( + IN RTMP_ADAPTER *pAd); + +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef TXBF_SUPPORT +VOID APTxSounding( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif + +VOID RTMPSetPiggyBack( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bPiggyBack); + +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +UCHAR RTMPStaFixedTxMode( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPUpdateLegacyTxSetting( + UCHAR fixed_tx_mode, + PMAC_TABLE_ENTRY pEntry); + +BOOLEAN RTMPAutoRateSwitchCheck( + IN RTMP_ADAPTER *pAd); + + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID InitLookupTable(RTMP_ADAPTER *pAd); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +VOID MlmeHalt(RTMP_ADAPTER *pAd); +NDIS_STATUS MlmeInit(RTMP_ADAPTER *pAd); + +VOID MlmeResetRalinkCounters(RTMP_ADAPTER *pAd); + +VOID BuildChannelList(RTMP_ADAPTER *pAd); +UCHAR FirstChannel(RTMP_ADAPTER *pAd); +UCHAR NextChannel(RTMP_ADAPTER *pAd, UCHAR channel); + +UCHAR RTMPFindScanChannel( + IN PRTMP_ADAPTER pAd, + IN UINT8 LastScanChannel); + +VOID ChangeToCellPowerLimit(RTMP_ADAPTER *pAd, UCHAR AironetCellPowerLimit); + + +VOID RTMPInitMICEngine( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey); + +BOOLEAN RTMPTkipCompareMICValue( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len); + +VOID RTMPCalculateMICValue( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx); + +VOID RTMPTkipAppendByte( + IN PTKIP_KEY_INFO pTkip, + IN UCHAR uChar); + +VOID RTMPTkipAppend( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pSrc, + IN UINT nBytes); + +VOID RTMPTkipGetMIC(TKIP_KEY_INFO *pTkip); + + +INT RT_CfgSetCountryRegion( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg, + IN INT band); + +INT RT_CfgSetWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg); + +RT_802_11_PHY_MODE wmode_2_cfgmode(UCHAR wmode); +UCHAR cfgmode_2_wmode(UCHAR cfg_mode); +UCHAR *wmode_2_str(UCHAR wmode); +BOOLEAN wmode_valid(RTMP_ADAPTER *pAd, enum WIFI_MODE wmode); + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +INT RT_CfgSetMbssWirelessMode( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT RT_CfgSetShortSlot( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT RT_CfgSetWepKey( + IN RTMP_ADAPTER *pAd, + IN PSTRING keyString, + IN CIPHER_KEY *pSharedKey, + IN INT keyIdx); + +INT RT_CfgSetWPAPSKKey( + IN RTMP_ADAPTER *pAd, + IN PSTRING keyString, + IN INT keyStringLen, + IN UCHAR *pHashStr, + IN INT hashStrLen, + OUT PUCHAR pPMKBuf); + +INT RT_CfgSetFixedTxPhyMode(PSTRING arg); +INT RT_CfgSetMacAddress(RTMP_ADAPTER *pAd, PSTRING arg); +INT RT_CfgSetTxMCSProc(PSTRING arg, BOOLEAN *pAutoRate); +INT RT_CfgSetAutoFallBack(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef WSC_INCLUDED +INT RT_CfgSetWscPinCode( + IN RTMP_ADAPTER *pAd, + IN PSTRING pPinCodeStr, + OUT PWSC_CTRL pWscControl); +#endif /* WSC_INCLUDED */ + +INT Set_Antenna_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + + +#ifdef RT6352 +INT Set_RfBankSel_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT Set_TemperatureCAL_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#endif /* RT6352 */ + +#ifdef MULTI_MAC_ADDR_EXT_SUPPORT +INT Set_EnMultiMacAddrExt_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_MultiMacAddrExt_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* MULTI_MAC_ADDR_EXT_SUPPORT */ + +INT set_tssi_enable(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef CONFIG_WIFI_TEST +INT set_pbf_loopback(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_pbf_rx_drop(RTMP_ADAPTER *pAd, PSTRING arg); +#endif + +#ifdef CONFIG_ANDES_SUPPORT +INT set_fw_debug(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* CONFIG_ANDES_SUPPORT */ + +INT set_power_compensate(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef MT76x2 +INT set_obtw_delta_proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT set_obtw_debug_proc(PRTMP_ADAPTER pAd, PSTRING arg); +#endif /* MT76x2 */ + +INT set_cal_test(RTMP_ADAPTER *pAd, PSTRING arg); +#ifdef RTMP_PCI_SUPPORT +INT set_cpu_int_analysis(RTMP_ADAPTER *pAd, PSTRING arg); +#endif + +NDIS_STATUS RTMPWPARemoveKeyProc( + IN RTMP_ADAPTER *pAd, + IN PVOID pBuf); + +VOID RTMPWPARemoveAllKeys( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen); + +VOID RTMPSetPhyMode( + IN RTMP_ADAPTER *pAd, + IN ULONG phymode); + +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID RTMPAddWcidAttributeEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry); + +PSTRING GetEncryptType(CHAR enc); +PSTRING GetAuthMode(CHAR auth); + +#ifdef DOT11_N_SUPPORT +VOID RTMPSetHT( + IN RTMP_ADAPTER *pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode); + +VOID RTMPSetIndividualHT(RTMP_ADAPTER *pAd, UCHAR apidx); + +UCHAR get_cent_ch_by_htinfo( + RTMP_ADAPTER *pAd, + ADD_HT_INFO_IE *ht_op, + HT_CAPABILITY_IE *ht_cap); + +INT get_ht_cent_ch(RTMP_ADAPTER *pAd, UINT8 *rf_bw, UINT8 *ext_ch); +INT ht_mode_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, HT_CAPABILITY_IE *peer, RT_HT_CAPABILITY *my); +INT set_ht_fixed_mcs(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR fixed_mcs, UCHAR mcs_bound); +INT get_ht_max_mcs(RTMP_ADAPTER *pAd, UCHAR *desire_mcs, UCHAR *cap_mcs); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPDisableDesiredHtInfo( + IN RTMP_ADAPTER *pAd); + +#ifdef SYSTEM_LOG_SUPPORT +VOID RtmpDrvSendWirelessEvent( + IN VOID *pAdSrc, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi); +#else +#define RtmpDrvSendWirelessEvent(_pAd, _Event_flag, _pAddr, _BssIdx, _Rssi) +#endif /* SYSTEM_LOG_SUPPORT */ + +CHAR ConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber); + +CHAR ConvertToSnr(RTMP_ADAPTER *pAd, UCHAR Snr); + +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN RTMP_ADAPTER *pAd); + + +VOID DeleteEffectedChannelList(RTMP_ADAPTER *pAd); + +VOID CntlChannelWidth( + IN RTMP_ADAPTER *pAd, + IN UCHAR PrimaryChannel, + IN UCHAR CentralChannel, + IN UCHAR ChannelWidth, + IN UCHAR SecondaryChannelOffset); + +#endif /* DOT11N_DRAFT3 */ + + +VOID APAsicEvaluateRxAnt( + IN RTMP_ADAPTER *pAd); + + +VOID APAsicRxAntEvalTimeout( + IN RTMP_ADAPTER *pAd); + + +VOID RTMPGetTxTscFromAsic(RTMP_ADAPTER *pAd, UCHAR apidx, UCHAR *pTxTsc); + +MAC_TABLE_ENTRY *PACInquiry(RTMP_ADAPTER *pAd, UCHAR Wcid); + +UINT APValidateRSNIE( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pRsnIe, + IN UCHAR rsnie_len); + +VOID HandleCounterMeasure( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WPAStart4WayHS( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval); + +VOID WPAStart2WayGroupHS( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PeerPairMsg1Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg2Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg3Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg4Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID WPAPairMsg3Retry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval +); + +VOID PeerGroupMsg1Action( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGroupMsg2Action( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN VOID *Msg, + IN UINT MsgLen); + +VOID CMTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WPARetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef TXBF_SUPPORT +VOID eTxBfProbeTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* TXBF_SUPPORT */ + +VOID EnqueueStartForPSKExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPHandleSTAKey( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDeAuthAction( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason, + IN BOOLEAN bDataFrameFirst); + +#ifdef DOT11W_PMF_SUPPORT +VOID PMF_SAQueryTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID PMF_SAQueryConfirmTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* DOT11W_PMF_SUPPORT */ + +VOID GREKEYPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AES_128_CMAC( + IN PUCHAR key, + IN PUCHAR input, + IN INT len, + OUT PUCHAR mac); + +#ifdef DOT1X_SUPPORT +VOID WpaSend( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pPacket, + IN ULONG Len); + +VOID RTMPAddPMKIDCache( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK); + +INT RTMPSearchPMKIDCache( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN PUCHAR pAddr); + +VOID RTMPDeletePMKIDCache( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN INT idx); + +VOID RTMPMaintainPMKIDCache( + IN RTMP_ADAPTER *pAd); +#else +#define RTMPMaintainPMKIDCache(_pAd) +#endif /* DOT1X_SUPPORT */ + +#ifdef RESOURCE_PRE_ALLOC +VOID RTMPResetTxRxRingMemory( + IN RTMP_ADAPTER *pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +VOID RTMPFreeTxRxRingMemory( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RTMP_FillTxBlkInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk); + + void announce_802_3_packet( + IN VOID *pAdSrc, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode); + +#ifdef DOT11_N_SUPPORT +UINT BA_Reorder_AMSDU_Annnounce( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode); +#endif /* DOT11_N_SUPPORT */ + +PNET_DEV get_netdev_from_bssid(RTMP_ADAPTER *pAd, UCHAR FromWhichBSSID); + +#ifdef DOT11_N_SUPPORT +void ba_flush_reordering_timeout_mpdus( + IN RTMP_ADAPTER *pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32); + + +VOID BAOriSessionSetUp( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced); + +VOID BASessionTearDownALL( + IN OUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid); + +VOID BAOriSessionTearDown( + IN OUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend); + +VOID BARecSessionTearDown( + IN OUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive); +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN ba_reordering_resource_init(RTMP_ADAPTER *pAd, int num); +void ba_reordering_resource_release(RTMP_ADAPTER *pAd); + +INT ComputeChecksum( + IN UINT PIN); + +UINT GenerateWpsPinCode( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bFromApcli, + IN UCHAR apidx); + +#ifdef WSC_INCLUDED +INT Set_WscGenPinCode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef BB_SOC +INT Set_WscResetPinCode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif + +INT Set_WscVendorPinCode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef WSC_AP_SUPPORT +VOID RTMPIoctlSetWSCOOB(IN RTMP_ADAPTER *pAd); +#endif + +#ifdef WSC_STA_SUPPORT +VOID CntlWscIterate( + IN RTMP_ADAPTER *pAd); + +USHORT WscGetAuthTypeFromStr( + IN PSTRING arg); + +USHORT WscGetEncrypTypeFromStr( + IN PSTRING arg); +#endif /* WSC_STA_SUPPORT */ +/* */ +/* prototype in wsc.c */ +/* */ +BOOLEAN WscMsgTypeSubst( + IN UCHAR EAPType, + IN UCHAR EAPCode, + OUT INT *MsgType); + +VOID WscStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +#ifdef IWSC_SUPPORT +void IWSC_StateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID IWSC_Init( + IN IN RTMP_ADAPTER *pAd); +#endif // IWSC_SUPPORT // + +VOID WscEAPOLStartAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscEAPAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscEapEnrolleeAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); + +#ifdef CONFIG_AP_SUPPORT +VOID WscEapApProxyAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscEapRegistrarAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); + +VOID WscEAPOLTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID Wsc2MinsTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +UCHAR WscRxMsgType( + IN RTMP_ADAPTER *pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID WscInitRegistrarPair( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN UCHAR apidx); + +VOID WscSendEapReqId( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurOpMode); + +VOID WscSendEapolStart( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pBssid, + IN UCHAR CurOpMode); + +VOID WscSendEapRspId( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PWSC_CTRL pWscControl); + +VOID WscMacHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PHEADER_802_11 Hdr, + IN PUCHAR pAddr1, + IN PUCHAR pBSSID, + IN BOOLEAN bFromApCli); + +VOID WscSendMessage( + IN RTMP_ADAPTER *pAd, + IN UCHAR OpCode, + IN PUCHAR pData, + IN INT Len, + IN PWSC_CTRL pWscControl, + IN UCHAR OpMode, /* 0: AP Mode, 1: AP Client Mode, 2: STA Mode */ + IN UCHAR EapType); + +VOID WscSendEapReqAck( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID WscSendEapReqDone( + IN RTMP_ADAPTER *pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID WscSendEapFail( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bSendDeAuth); + +VOID WscM2DTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscUPnPMsgTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +int WscSendUPnPConfReqMsg( + IN RTMP_ADAPTER *pAd, + IN UCHAR apIdx, + IN PUCHAR ssidStr, + IN PUCHAR macAddr, + IN INT Status, + IN UINT eventID, + IN UCHAR CurOpMode); + + +int WscSendUPnPMessage( + IN RTMP_ADAPTER *pAd, + IN UCHAR apIdx, + IN USHORT msgType, + IN USHORT msgSubType, + IN PUCHAR pData, + IN INT dataLen, + IN UINT eventID, + IN UINT toIPAddr, + IN PUCHAR pMACAddr, + IN UCHAR CurOpMode); + +VOID WscUPnPErrHandle( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN UINT eventID); + +VOID WscBuildBeaconIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR b_configured, + IN BOOLEAN b_selRegistrar, + IN USHORT devPwdId, + IN USHORT selRegCfgMethods, + IN UCHAR apidx, + IN UCHAR *pAuthorizedMACs, + IN UCHAR AuthorizedMACsLen, + IN UCHAR CurOpMode); + +VOID WscBuildProbeRespIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR respType, + IN UCHAR scState, + IN BOOLEAN b_selRegistrar, + IN USHORT devPwdId, + IN USHORT selRegCfgMethods, + IN UCHAR apidx, + IN UCHAR *pAuthorizedMACs, + IN INT AuthorizedMACsLen, + IN UCHAR CurOpMode); + + +#ifdef CONFIG_AP_SUPPORT +VOID WscBuildAssocRespIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN UCHAR Reason, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +VOID WscSelectedRegistrar( + IN RTMP_ADAPTER *pAd, + IN PUCHAR RegInfo, + IN UINT length, + IN UCHAR apidx); + +VOID WscInformFromWPA( + IN PMAC_TABLE_ENTRY pEntry); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscBuildProbeReqIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR CurOpMode, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +VOID WscBuildAssocReqIE( + IN PWSC_CTRL pWscControl, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT +VOID IWSC_Stop(RTMP_ADAPTER *pAd, BOOLEAN bSendNotification); + +VOID IWSC_T1TimerAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID IWSC_T2TimerAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID IWSC_EntryTimerAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID IWSC_DevQueryAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN IWSC_PeerEapolStart( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID IWSC_AddSmpbcEnrollee( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pPeerAddr); + +BOOLEAN IWSC_IpContentForCredential( + IN RTMP_ADAPTER *pAd); +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +VOID WscProfileRetryTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscPBCTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscScanTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +INT WscGenerateUUID( + RTMP_ADAPTER *pAd, + UCHAR *uuidHexStr, + UCHAR *uuidAscStr, + int apIdx, + BOOLEAN bUseCurrentTime); + +VOID WscStop( + IN RTMP_ADAPTER *pAd, +#ifdef CONFIG_AP_SUPPORT + IN BOOLEAN bFromApcli, +#endif /* CONFIG_AP_SUPPORT */ + IN PWSC_CTRL pWscControl); + +VOID WscInit( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bFromApcli, + IN UCHAR BssIndex); + +#ifdef CON_WPS +VOID WscConWpsStop( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApCli, + IN PWSC_CTRL pWscControl); +#endif /* CON_WPS */ + +BOOLEAN ValidateChecksum(UINT PIN); + +UINT WscRandomGen4digitPinCode(RTMP_ADAPTER *pAd); + +UINT WscRandomGeneratePinCode( + IN RTMP_ADAPTER *pAd, + IN UCHAR apidx); + +int BuildMessageM1( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM2( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM2D( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM3( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM4( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM5( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM6( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM7( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM8( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromApCli, + OUT VOID *pbuf); + +int BuildMessageDONE( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageACK( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageNACK( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int ProcessMessageM1( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM2( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + IN UCHAR apidx, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM2D( + IN RTMP_ADAPTER *pAd, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM3( + IN RTMP_ADAPTER *pAd, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM4( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM5( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM6( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM7( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM8( + IN RTMP_ADAPTER *pAd, + IN VOID *precv, + IN INT Length, + IN PWSC_CTRL pWscControl); + +USHORT WscGetAuthType( + IN NDIS_802_11_AUTHENTICATION_MODE authType); + +USHORT WscGetEncryType( + IN NDIS_802_11_WEP_STATUS encryType); + +NDIS_STATUS WscThreadInit(RTMP_ADAPTER *pAd); + +BOOLEAN WscThreadExit(RTMP_ADAPTER *pAd); + +int AppendWSCTLV( + IN USHORT index, + OUT UCHAR * obuf, + IN UCHAR * ibuf, + IN USHORT varlen); + +VOID WscGetRegDataPIN( + IN RTMP_ADAPTER *pAd, + IN UINT PinCode, + IN PWSC_CTRL pWscControl); + +VOID WscPushPBCAction( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +VOID WscScanExec( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +BOOLEAN WscPBCExec( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bFromM2, + IN PWSC_CTRL pWscControl); + +VOID WscPBCBssTableSort( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +VOID WscGenRandomKey( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + INOUT PUCHAR pKey, + INOUT PUSHORT pKeyLen); + +VOID WscCreateProfileFromCfg( + IN RTMP_ADAPTER *pAd, + IN UCHAR OpMode, /* 0: AP Mode, 1: AP Client Mode, 2: STA Mode */ + IN PWSC_CTRL pWscControl, + OUT PWSC_PROFILE pWscProfile); + +void WscWriteConfToPortCfg( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee); + +#ifdef APCLI_SUPPORT +void WscWriteConfToApCliCfg( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee); +#endif /* APCLI_SUPPORT */ + +VOID WpsSmProcess( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscPBCSessionOverlapCheck( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +VOID WscPBC_DPID_FromSTA( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddr); + +#ifdef CONFIG_AP_SUPPORT +INT WscGetConfWithoutTrigger( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromUPnP); + +BOOLEAN WscReadProfileFromUfdFile( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN PSTRING pUfdFileName); + +BOOLEAN WscWriteProfileToUfdFile( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN PSTRING pUfdFileName); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckWpsIeFromWpsAP( + IN RTMP_ADAPTER *pAd, + IN PEID_STRUCT pEid, + OUT PUSHORT pDPIDFromAP); + +#ifdef CONFIG_STA_SUPPORT +VOID PeerProbeRespAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +ULONG WscSearchWpsApBySSID( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN INT WscMode); +#endif /* CONFIG_STA_SUPPORT */ + +/* WSC hardware push button function 0811 */ +VOID WSC_HDR_BTN_Init(RTMP_ADAPTER *pAd); +VOID WSC_HDR_BTN_Stop(RTMP_ADAPTER *pAd); +VOID WSC_HDR_BTN_CheckHandler(RTMP_ADAPTER *pAd); +#ifdef WSC_LED_SUPPORT +BOOLEAN WscSupportWPSLEDMode(RTMP_ADAPTER *pAd); +BOOLEAN WscSupportWPSLEDMode10(RTMP_ADAPTER *pAd); + +BOOLEAN WscAPHasSecuritySetting(RTMP_ADAPTER *pAd,PWSC_CTRL pWscControl); + +VOID WscLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscSkipTurnOffLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* WSC_LED_SUPPORT */ + + + +#ifdef CONFIG_AP_SUPPORT +VOID WscUpdatePortCfgTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckPeerDPID( + IN RTMP_ADAPTER *pAd, + IN PFRAME_802_11 Fr, + IN PUCHAR eid_data, + IN INT eid_len); + +VOID WscClearPeerList(PLIST_HEADER pWscEnList); + +PWSC_PEER_ENTRY WscFindPeerEntry(PLIST_HEADER pWscEnList, UCHAR *pMacAddr); +VOID WscDelListEntryByMAC(PLIST_HEADER pWscEnList, UCHAR *pMacAddr); +VOID WscInsertPeerEntryByMAC(PLIST_HEADER pWscEnList, UCHAR *pMacAddr); + +#ifdef CONFIG_AP_SUPPORT +INT WscApShowPeerList(RTMP_ADAPTER *pAd, PSTRING arg); + +VOID WscSetupLockTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscCheckPinAttackCount(RTMP_ADAPTER *pAd, PWSC_CTRL pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +INT WscStaShowPeerList(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* CONFIG_STA_SUPPORT */ + +VOID WscMaintainPeerList(RTMP_ADAPTER *pAd, PWSC_CTRL pWpsCtrl); + +VOID WscAssignEntryMAC(RTMP_ADAPTER *pAd, PWSC_CTRL pWpsCtrl); + +#ifdef WSC_V2_SUPPORT +#ifdef CONFIG_AP_SUPPORT +VOID WscOnOff(RTMP_ADAPTER *pAd, INT ApIdx, BOOLEAN bOff); + +VOID WscAddEntryToAclList(RTMP_ADAPTER *pAd, INT ApIdx, UCHAR *pMacAddr); +#endif /* CONFIG_AP_SUPPORT */ + +BOOLEAN WscGenV2Msg( + IN PWSC_CTRL pWpsCtrl, + IN BOOLEAN bSelRegistrar, + IN PUCHAR pAuthorizedMACs, + IN INT AuthorizedMACsLen, + OUT UCHAR **pOutBuf, + OUT INT *pOutBufLen); + +BOOLEAN WscParseV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN USHORT DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen); + +VOID WscSendEapFragAck( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry); + +VOID WscSendEapFragData( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry); +#endif /* WSC_V2_SUPPORT */ + +BOOLEAN WscGetDataFromPeerByTag( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pIeData, + IN INT IeDataLen, + IN USHORT WscTag, + OUT PUCHAR pWscBuf, + OUT PUSHORT pWscBufLen); + +#endif /* WSC_INCLUDED */ + + + + +BOOLEAN rtstrmactohex(PSTRING s1, PSTRING s2); +BOOLEAN rtstrcasecmp(PSTRING s1, PSTRING s2); +PSTRING rtstrstruncasecmp(PSTRING s1, PSTRING s2); + +PSTRING rtstrstr( PSTRING s1, const PSTRING s2); +PSTRING rstrtok( PSTRING s, const PSTRING ct); +int rtinet_aton(const PSTRING cp, unsigned int *addr); + +INT SetManualTxOPThreshold(RTMP_ADAPTER *pAd, PSTRING arg); +INT SetManualTxOPUpBound(RTMP_ADAPTER *pAd, PSTRING arg); +INT SetManualTxOPLowBound(RTMP_ADAPTER *pAd, PSTRING arg); + +/*//////// common ioctl functions ////////*/ +INT Set_DriverVersion_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_CountryRegion_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_CountryRegionABand_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WirelessMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_MBSS_WirelessMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Channel_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#ifdef RT_CFG80211_SUPPORT +INT Set_DisableCfg2040Scan_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif +#ifdef CUSTOMER_DCC_FEATURE +INT Set_ApChannelSwitch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif +INT Set_ShortSlot_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_TxPower_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_BGProtection_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_TxPreamble_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_RTSThreshold_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_FragThreshold_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_TxBurst_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef RTMP_MAC_PCI +INT Set_ShowRF_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* RTMP_MAC_PCI */ + +#ifdef AGGREGATION_SUPPORT +INT Set_PktAggregate_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* AGGREGATION_SUPPORT */ + +#ifdef INF_PPA_SUPPORT +INT Set_INF_AMAZON_SE_PPA_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +INT ifx_ra_start_xmit ( + IN struct net_device *rx_dev, + IN struct net_device *tx_dev, + IN struct sk_buff *skb, + IN int len); +#endif /* INF_PPA_SUPPORT */ + +INT Set_IEEE80211H_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_ExtCountryCode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ExtDfsType_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ChannelListAdd_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ChannelListShow_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ChannelListDel_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DBG +INT Set_Debug_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_DebugFunc_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif + +#ifdef TXBF_SUPPORT +INT Set_ReadITxBf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ReadETxBf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WriteITxBf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WriteETxBf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_StatITxBf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_StatETxBf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_TxBfTag_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ITxBfTimeout_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfTimeout_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_InvTxBfTag_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ITxBfCal_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#ifdef MT76x2 +INT mt76x2_Set_ITxBfCal_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif +INT Set_ITxBfDivCal_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ITxBfLnaCal_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfEnCond_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfEnCond_ApCliProc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfCodebook_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfCoefficient_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfGrouping_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfNoncompress_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ETxBfIncapable_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_StaETxBfEnCond_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_NoSndgCntThrd_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_NdpSndgStreams_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Trigger_Sounding_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ITxBfEn_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ITxBf_Calib_Mode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef MT76x2 +INT Set_TxBfProfileTag_Help( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileTagValid( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileTagRead( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileTagWrite( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileDataRead( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileDataWrite( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileDataWriteAll( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileDataReadAll( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileTag_TimeOut( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_TxBfProfileTag_Matrix( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_TxBfProfileTag_SNR( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_TxBfProfileTag_TxScale( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_TxBfProfileTag_MAC( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfProfileTag_Flg( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif + +#endif /* TXBF_SUPPORT */ + +#ifdef VHT_TXBF_SUPPORT +INT Set_VhtNDPA_Sounding_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* VHT_TXBF_SUPPORT */ + +#if defined (CONFIG_WIFI_PKT_FWD) +INT Set_WifiFwd_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_WifiFwdAccessSchedule_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_WifiFwdHijack_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_WifiFwdRepDevice(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_WifiFwdShowEntry(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_WifiFwdDeleteEntry(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_PacketSourceShowEntry(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_PacketSourceDeleteEntry(PRTMP_ADAPTER pAd, PSTRING arg); +#endif /* CONFIG_WIFI_PKT_FWD */ + +INT Set_RateAdaptInterval(RTMP_ADAPTER *pAd, PSTRING arg); + + +#ifdef PRE_ANT_SWITCH +INT Set_PreAntSwitch_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_PreAntSwitchRSSI_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_PreAntSwitchTimeout_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#endif /* PRE_ANT_SWITCH */ + + + +#ifdef CFO_TRACK +INT Set_CFOTrack_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef CFO_TRACK +#ifdef CONFIG_AP_SUPPORT +INT rtmp_cfo_track(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, INT lastClient); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CFO_TRACK */ + +#endif // CFO_TRACK // + +#ifdef DBG_CTRL_SUPPORT +INT Set_DebugFlags_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef INCLUDE_DEBUG_QUEUE +INT Set_DebugQueue_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +void dbQueueEnqueue(UCHAR type, UCHAR *data); +void dbQueueEnqueueTxFrame(UCHAR *pTxWI, UCHAR *pDot11Hdr); +void dbQueueEnqueueRxFrame(UCHAR *pRxWI, UCHAR *pDot11Hdr ULONG flags); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + +INT Show_DescInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Show_MacTable_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Show_sta_tr_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT show_stainfo_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT show_devinfo_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT show_sysinfo_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT show_trinfo_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Show_TxInfo_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +INT Set_ResetStatCounter_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_BADecline_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_BAOriTearDown_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_BARecTearDown_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtBw_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtMcs_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtGi_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtOpMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtStbc_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtHtc_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtExtcha_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtMpduDensity_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtBaWinSize_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtRdg_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtLinkAdapt_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtAmsdu_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtAutoBa_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtProtect_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtMimoPs_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef DOT11N_DRAFT3 +INT Set_HT_BssCoex_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HT_BssCoexApCntThr_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* DOT11N_DRAFT3 */ + + +#ifdef CONFIG_AP_SUPPORT +INT Set_HtTxStream_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtRxStream_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT +INT Set_GreenAP_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT SetCommonHT(RTMP_ADAPTER *pAd); + +INT Set_ForceShortGI_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ForceGF_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_SendSMPSAction_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +INT Set_HtMIMOPSmode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtTxBASize_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_HtDisallowTKIP_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_BurstMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC +INT Set_VhtBw_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_VhtStbc_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_VhtBwSignal_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_VhtDisallowNonVHT_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* DOT11_VHT_AC */ + + +#ifdef APCLI_SUPPORT +INT RTMPIoctlConnStatus(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /*APCLI_SUPPORT*/ + +#ifdef ETH_CONVERT_SUPPORT +INT Set_EthConvertMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_EthCloneMac_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* ETH_CONVERT_SUPPORT */ + + + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPSendDLSTearDownFrame(RTMP_ADAPTER *pAd, UCHAR *pDA); + +#ifdef DOT11_N_SUPPORT +VOID QueryBATABLE( + IN PRTMP_ADAPTER pAd, + OUT PQUERYBA_TABLE pBAT); +#endif /* DOT11_N_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT +INT WpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet); +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID detect_wmm_traffic(RTMP_ADAPTER *pAd, UCHAR up, UCHAR bOutput); +VOID dynamic_tune_be_tx_op(RTMP_ADAPTER *pAd, ULONG nonBEpackets); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID Handle_BSS_Width_Trigger_Events(RTMP_ADAPTER *pAd); +#endif /* DOT11N_DRAFT3 */ + +void build_ext_channel_switch_ie( + IN RTMP_ADAPTER *pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); + +#ifdef CUSTOMER_DCC_FEATURE +void build_ext_channel_switch_ie_New( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); +#endif +void assoc_ht_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR ht_cap_len, + IN HT_CAPABILITY_IE *pHTCapability); +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN rtmp_rx_done_handle(RTMP_ADAPTER *pAd); + +#ifdef RTMP_PCI_SUPPORT +#ifdef CONFIG_ANDES_SUPPORT +BOOLEAN RxRing1DoneInterruptHandle(RTMP_ADAPTER *pAd); +VOID RTMPHandleTxRing8DmaDoneInterrupt(RTMP_ADAPTER *pAd); +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +VOID Indicate_AMPDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +#ifdef HDR_TRANS_SUPPORT +VOID Indicate_AMPDU_Packet_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); +#endif /* HDR_TRANS_SUPPORT */ + +/* AMSDU packet indication */ +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID BaReOrderingBufferMaintain( + IN PRTMP_ADAPTER pAd); +#endif /* DOT11_N_SUPPORT */ + +/* Normal legacy Rx packet indication */ +VOID Indicate_Legacy_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +#ifdef HDR_TRANS_SUPPORT +VOID Indicate_Legacy_Packet_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); +#endif /* HDR_TRANS_SUPPORT */ + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +UINT deaggregate_AMSDU_announce( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR OpMode); + +#ifdef TXBF_SUPPORT +BOOLEAN clientSupportsETxBF(RTMP_ADAPTER *pAd, HT_BF_CAP *pTxBFCap); +void setETxBFCap(RTMP_ADAPTER *pAd, HT_BF_CAP *pTxBFCap); +#ifdef VHT_TXBF_SUPPORT +BOOLEAN clientSupportsVHTETxBF(RTMP_ADAPTER *pAd, VHT_CAP_INFO *pTxBFCapInfo); +void setVHTETxBFCap(RTMP_ADAPTER *pAd, VHT_CAP_INFO *pTxBFCap); +#endif /* VHT_TXBF_SUPPORT */ + +#ifdef ETXBF_EN_COND3_SUPPORT +VOID txSndgSameMcs(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY * pEnt, UCHAR smoothMfb); +VOID txSndgOtherGroup(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID txMrqInvTxBF(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID chooseBestMethod(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR mfb); +VOID rxBestSndg(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* ETXBF_EN_COND3_SUPPORT */ + +VOID handleBfFb(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +VOID TxBFInit(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, BOOLEAN supETxBF); + +VOID eTxBFProbing(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); + +#ifdef VHT_TXBF_SUPPORT +VOID AP_NDPA_Frame_Tx(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pMacEntry); +VOID STA_NDPA_Frame_Tx(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pMacEntry); +#endif /* VHT_TXBF_SUPPORT */ + +VOID Trigger_Sounding_Packet( + IN RTMP_ADAPTER *pAd, + IN UCHAR SndgType, + IN UCHAR SndgBW, + IN UCHAR SndgMcs, + IN MAC_TABLE_ENTRY *pEntry); + +VOID rtmp_asic_set_bf(RTMP_ADAPTER *pAd); +BOOLEAN rtmp_chk_itxbf_calibration(RTMP_ADAPTER *pAd); + +#endif /* TXBF_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +/* remove LLC and get 802_3 Header */ +#define RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \ +{ \ + PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \ + \ + \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_WDS) || RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_APCLI)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + _pSA = _pRxBlk->pHeader->Addr3; \ + } \ + else \ + { \ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + \ + CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \ + _pRxBlk->DataSize, _pRemovedLLCSNAP); \ + if (_pRemovedLLCSNAP == NULL) {} \ +} +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +/* remove LLC and get 802_3 Header */ +#define RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \ +{ \ + PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \ + \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_WDS) || RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \ + } \ + else \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_INFRA)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS)) \ + _pSA = _pRxBlk->pHeader->Addr2; \ + else \ + _pSA = _pRxBlk->pHeader->Addr3; \ + } \ + else \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + } \ + \ + CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \ + _pRxBlk->DataSize, _pRemovedLLCSNAP); \ + if (_pRemovedLLCSNAP == NULL) {} \ +} +#endif /* CONFIG_STA_SUPPORT */ + + +BOOLEAN APFowardWirelessStaToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID); + +VOID Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + +#ifdef CONFIG_AP_SUPPORT +#define AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\ + Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\ + Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS); + /*announce_802_3_packet(_pAd, _pPacket); */ +#endif /* CONFIG_STA_SUPPORT */ + + +/* Normal, AMPDU or AMSDU */ +VOID CmmRxnonRalinkFrameIndicate( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +#ifdef HDR_TRANS_SUPPORT +VOID CmmRxnonRalinkFrameIndicate_Hdr_Trns( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); +#endif /* HDR_TRANS_SUPPORT */ + +VOID CmmRxRalinkFrameIndicate( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID Update_Rssi_Sample( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi, + IN RXWI_STRUC *pRxWI); + +PNDIS_PACKET GetPacketFromRxRing( + IN RTMP_ADAPTER *pAd, + OUT RX_BLK *pRxBlk, + OUT BOOLEAN *pbReschedule, + INOUT UINT32 *pRxPending, + BOOLEAN *bCmdRspPacket, + UCHAR RxRingNo); + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk); + +/*////////////////////////////////////*/ + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) +VOID RTMPIoctlGetSiteSurvey( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif + +#ifdef CUSTOMER_DCC_FEATURE +VOID RTMPIoctlGetApTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetStreamType( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +UINT32 GetNumberofSpatialStreams( + IN HT_CAPABILITY_IE htCapabilityIE); + +VOID RTMPIoctlGetScanResults( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetRadioStatsCount( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#ifdef MBSS_802_11_STATISTICS +VOID RTMPIoctlQueryMbssStat( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +VOID RTMPIoctlQuerySTAStat( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +INT Set_ApCli_AuthMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ApCli_EncrypType_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ApCli_Enable_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +INT Set_ApCli_Ssid_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); + + +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef MAT_SUPPORT + +VOID getIPv6MacTbInfo(MAT_STRUCT *, char *, ULONG); + +VOID getIPMacTbInfo( + IN MAT_STRUCT *pMatCfg, + IN char *pOutBuf, + IN ULONG BufLen); + +NDIS_STATUS MATEngineInit(RTMP_ADAPTER *pAd); +NDIS_STATUS MATEngineExit(RTMP_ADAPTER *pAd); + +PUCHAR MATEngineRxHandle(RTMP_ADAPTER *pAd, PNDIS_PACKET pPkt, UINT infIdx); +PUCHAR MATEngineTxHandle(RTMP_ADAPTER *pAd, PNDIS_PACKET pPkt, UINT infIdx, UCHAR OpMode); + +BOOLEAN MATPktRxNeedConvert(RTMP_ADAPTER *pAd, PNET_DEV net_dev); + +#endif /* MAT_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +typedef struct CountryCodeToCountryRegion { + USHORT CountryNum; + UCHAR IsoName[3]; + /*UCHAR CountryName[40]; */ + PSTRING pCountryName; + BOOLEAN SupportABand; + /*ULONG RegDomainNum11A; */ + UCHAR RegDomainNum11A; + BOOLEAN SupportGBand; + /*ULONG RegDomainNum11G; */ + UCHAR RegDomainNum11G; +} COUNTRY_CODE_TO_COUNTRY_REGION; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef SNMP_SUPPORT +/*for snmp */ +typedef struct _DefaultKeyIdxValue +{ + UCHAR KeyIdx; + UCHAR Value[16]; +} DefaultKeyIdxValue, *PDefaultKeyIdxValue; +#endif + + + +void STA_MonPktSend(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +#ifdef CONFIG_STA_SUPPORT +VOID RTMPSetDesiredRates(RTMP_ADAPTER *pAd, LONG Rates); + +#ifdef XLINK_SUPPORT +INT Set_XlinkMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* XLINK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +INT Set_FixedTxMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +INT Set_LongRetryLimit_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ShortRetryLimit_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_AutoFallBack_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +VOID RT28XXDMADisable(RTMP_ADAPTER *pAd); +VOID RT28XXDMAEnable(RTMP_ADAPTER *pAd); + +#ifdef DMA_BUSY_RESET +#ifdef RTMP_PCI_SUPPORT +INT Set_PDMAWatchDog_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WlanResetB_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +VOID PDMAWatchDog(RTMP_ADAPTER *pAd); +BOOLEAN MonitorRxRing(RTMP_ADAPTER *pAd); +BOOLEAN MonitorTxRing(RTMP_ADAPTER *pAd); +#endif /* RTMP_PCI_SUPPORT */ +#endif /* DMA_BUSY_RESET */ + + +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER * pAd, + IN INT apidx, + IN ULONG BeaconLen, + IN ULONG UpdatePos); + +void CfgInitHook(RTMP_ADAPTER *pAd); + + +NDIS_STATUS RtmpNetTaskInit(RTMP_ADAPTER *pAd); +NDIS_STATUS RtmpMgmtTaskInit(RTMP_ADAPTER *pAd); +VOID RtmpNetTaskExit(RTMP_ADAPTER *pAd); +VOID RtmpMgmtTaskExit(RTMP_ADAPTER *pAd); + +void tbtt_tasklet(unsigned long data); + +#ifdef WORKQUEUE_BH +void pretbtt_workq(struct work_struct *work); +#else +void pretbtt_tasklet(unsigned long data); +#endif /* WORKQUEUE_BH */ + +#ifdef RTMP_MAC_PCI +/* */ +/* Function Prototype in cmm_data_pci.c */ +/* */ +USHORT RtmpPCI_WriteSingleTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteMultiTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteFragTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber); + +VOID RtmpPCI_FinalWriteTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx); + +int RtmpPCIMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN PUCHAR pSrcBufVA, + IN UINT SrcBufLen); + +BOOLEAN RT28xxPciAsicRadioOff( + IN RTMP_ADAPTER *pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp); + +BOOLEAN RT28xxPciAsicRadioOn(RTMP_ADAPTER *pAd, UCHAR Level); +VOID RTMPInitPCIeDevice(RT_CMD_PCIE_INIT *pConfig, VOID *pAd); + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_PCI_SUPPORT +VOID PsPollWakeExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#ifdef PCIE_PS_SUPPORT +VOID RTMPInitPCIeLinkCtrlValue(RTMP_ADAPTER *pAd); +VOID RTMPPCIeLinkCtrlValueRestore(RTMP_ADAPTER *pAd, UCHAR Level); +VOID RTMPPCIeLinkCtrlSetting(RTMP_ADAPTER *pAd, USHORT Max); +VOID RTMPrt3xSetPCIePowerLinkCtrl(RTMP_ADAPTER *pAd); + +VOID RadioOnExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_PCI_SUPPORT */ + +VOID RT28xxPciStaAsicForceWakeup(RTMP_ADAPTER *pAd, BOOLEAN bFromTx); + +VOID RT28xxPciStaAsicSleepThenAutoWakeup( + IN RTMP_ADAPTER *pAd, + IN USHORT TbttNumToNextWakeUp); + +#endif /* CONFIG_STA_SUPPORT */ + +VOID RT28xxPciMlmeRadioOn(RTMP_ADAPTER *pAd); +VOID RT28xxPciMlmeRadioOFF(RTMP_ADAPTER *pAd); + +ra_dma_addr_t RtmpDrvPciMapSingle( + IN RTMP_ADAPTER *pAd, + IN VOID *ptr, + IN size_t size, + IN INT sd_idx, + IN INT direction); + +INT rtmp_irq_init(RTMP_ADAPTER *pAd); +VOID TxDoneCleanupExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef CREDENTIAL_STORE +NDIS_STATUS RecoverConnectInfo(RTMP_ADAPTER *pAd); +NDIS_STATUS StoreConnectInfo(RTMP_ADAPTER *pAd); +#endif /* CREDENTIAL_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + +VOID AsicTurnOffRFClk(RTMP_ADAPTER *pAd, UCHAR Channel); + + + +#ifdef RTMP_TIMER_TASK_SUPPORT +INT RtmpTimerQThread(ULONG Context); + +RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer); + +BOOLEAN RtmpTimerQRemove( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer); + +void RtmpTimerQExit(RTMP_ADAPTER *pAd); +void RtmpTimerQInit(RTMP_ADAPTER *pAd); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +#ifdef NEW_WOW_SUPPORT +VOID RT28xxAndesWOWEnable(RTMP_ADAPTER *pAd); +VOID RT28xxAndesWOWDisable(RTMP_ADAPTER *pAd); +#endif /* NEW_WOW_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +VOID RT28xxAsicWOWEnable(RTMP_ADAPTER *pAd); +VOID RT28xxAsicWOWDisable(RTMP_ADAPTER *pAd); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +/*////////////////////////////////////*/ + +#ifdef AP_QLOAD_SUPPORT +VOID QBSS_LoadInit(RTMP_ADAPTER *pAd); +VOID QBSS_LoadAlarmReset(RTMP_ADAPTER *pAd); +VOID QBSS_LoadAlarmResume(RTMP_ADAPTER *pAd); +UINT32 QBSS_LoadBusyTimeGet(RTMP_ADAPTER *pAd); +BOOLEAN QBSS_LoadIsAlarmIssued(RTMP_ADAPTER *pAd); +BOOLEAN QBSS_LoadIsBusyTimeAccepted(RTMP_ADAPTER *pAd, UINT32 BusyTime); +UINT32 QBSS_LoadElementAppend(RTMP_ADAPTER *pAd, UINT8 *buf_p); +UINT32 QBSS_LoadElementParse( + IN RTMP_ADAPTER *pAd, + IN UINT8 *pElement, + OUT UINT16 *pStationCount, + OUT UINT8 *pChanUtil, + OUT UINT16 *pAvalAdmCap); + +VOID QBSS_LoadUpdate(RTMP_ADAPTER *pAd, ULONG UpTime); +VOID QBSS_LoadStatusClear(RTMP_ADAPTER *pAd); + +INT Show_QoSLoad_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#ifdef CONFIG_HOTSPOT_R2 +UINT32 QBSS_LoadElementAppend_HSTEST( + IN RTMP_ADAPTER *pAd, + OUT UINT8 *pBeaconBuf, + IN UCHAR apidx); +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* AP_QLOAD_SUPPORT */ + +/*///////////////////////////////////*/ +INT RTMPShowCfgValue(RTMP_ADAPTER *pAd, PSTRING name, PSTRING buf, UINT32 MaxLen); +PSTRING RTMPGetRalinkAuthModeStr(NDIS_802_11_AUTHENTICATION_MODE authMode); +PSTRING RTMPGetRalinkEncryModeStr(USHORT encryMode); +/*//////////////////////////////////*/ + +#ifdef CONFIG_STA_SUPPORT +VOID AsicStaBbpTuning(RTMP_ADAPTER *pAd); + +BOOLEAN StaUpdateMacTableEntry( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR MaxSupportedRateIn500Kbps, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo, + IN UCHAR AddHtInfoLen, + IN IE_LISTS *ie_list, + IN USHORT CapabilityInfo); + +#ifdef DOT11R_FT_SUPPORT +VOID FT_OTA_AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID FT_OTD_TimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* DOT11R_FT_SUPPORT */ + +BOOLEAN AUTH_ReqSend( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem, + IN PRALINK_TIMER_STRUCT pAuthTimer, + IN PSTRING pSMName, + IN USHORT SeqNo, + IN PUCHAR pNewElement, + IN ULONG ElementLen); +#endif /* CONFIG_STA_SUPPORT */ + + +VOID ReSyncBeaconTime(RTMP_ADAPTER *pAd); +VOID RTMPSetAGCInitValue(RTMP_ADAPTER *pAd, UCHAR BandWidth); + +#ifdef TXBF_SUPPORT +VOID handleHtcField(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +#endif /* TXBF_SUPPORT */ + +#ifdef MFB_SUPPORT +VOID MFB_PerPareMRQ(RTMP_ADAPTER *pAd, VOID* pBuf, MAC_TABLE_ENTRY *pEntry); +VOID MFB_PerPareMFB(RTMP_ADAPTER *pAd, VOID *pBuf, MAC_TABLE_ENTRY *pEntry); +#endif /* MFB_SUPPORT */ + +#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) +#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) +#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) + + + + +#ifdef SOFT_ENCRYPT +BOOLEAN RTMPExpandPacketForSwEncrypt(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk); +VOID RTMPUpdateSwCacheCipherInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR *pHdr); +#endif /* SOFT_ENCRYPT */ + + +/* + OS Related funciton prototype definitions. + TODO: Maybe we need to move these function prototypes to other proper place. +*/ +VOID RTInitializeCmdQ(PCmdQ cmdq); + +INT RTPCICmdThread(ULONG Context); + +VOID CMDHandler(RTMP_ADAPTER *pAd); + +VOID RTThreadDequeueCmd(PCmdQ cmdq, PCmdQElmt *pcmdqelmt); + +NDIS_STATUS RTEnqueueInternalCmd( + IN RTMP_ADAPTER *pAd, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength); + +#ifdef HOSTAPD_SUPPORT +VOID ieee80211_notify_michael_failure( + IN RTMP_ADAPTER *pAd, + IN PHEADER_802_11 pHeader, + IN UINT keyix, + IN INT report); + +const CHAR* ether_sprintf(const UINT8 *mac); +#endif/*HOSTAPD_SUPPORT*/ + + +#ifdef VENDOR_FEATURE3_SUPPORT +VOID RTMP_IO_WRITE32(RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value); +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +INT AsicGetMacVersion(RTMP_ADAPTER *pAd); + +INT WaitForAsicReady(RTMP_ADAPTER *pAd); + +BOOLEAN CHAN_PropertyCheck(RTMP_ADAPTER *pAd, UINT32 ChanNum, UCHAR Property); + +#ifdef CONFIG_STA_SUPPORT + +/* command */ +INT Set_SSID_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +INT Set_WmmCapable_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +INT Set_NetworkType_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +INT Set_AuthMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_EncrypType_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +INT Set_DefaultKeyID_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Wep_Key_Proc(RTMP_ADAPTER *pAd, PSTRING Key, INT KeyLen, INT KeyId); +INT Set_Key1_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Key2_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Key3_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_Key4_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WPAPSK_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_PSMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef WPA_SUPPLICANT_SUPPORT +INT Set_Wpa_Support(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef DBG +VOID RTMPIoctlMAC(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq); +VOID RTMPIoctlE2PROM(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* DBG */ + +#ifdef WSC_STA_SUPPORT +INT Set_WscConfMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscConfStatus_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscSsid_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscBssid_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscUUIDE_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscGetConf_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscStop_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_WscPinCode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef WSC_V2_SUPPORT +INT Set_WscForceSetAP_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* WSC_V2_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + +NDIS_STATUS RTMPWPANoneAddKeyProc(RTMP_ADAPTER *pAd, VOID *pBuf); + +INT Set_FragTest_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef DOT11_N_SUPPORT +INT Set_TGnWifiTest_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* DOT11_N_SUPPORT */ + +INT Set_LongRetryLimit_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ShortRetryLimit_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +INT Show_Adhoc_MacTable_Proc(RTMP_ADAPTER *pAd, PSTRING extra, UINT32 size); + +#ifdef RTMP_RF_RW_SUPPORT +VOID RTMPIoctlRF( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* RTMP_RF_RW_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +INT Set_FtApBssid_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_FtSupport_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* DOT11R_FT_SUPPORT */ + +INT Set_BeaconLostTime_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_AutoRoaming_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_SiteSurvey_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_ForceTxBurst_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +VOID RTMPAddKey(RTMP_ADAPTER *pAd, PNDIS_802_11_KEY pKey); +VOID StaSiteSurvey(RTMP_ADAPTER *pAd, PNDIS_802_11_SSID pSsid, UCHAR ScanType); + +VOID MaintainBssTable( + IN RTMP_ADAPTER *pAd, + IN OUT BSS_TABLE *Tab, + IN ULONG MaxRxTimeDiff, + IN UCHAR MaxSameRxTimeCount); +#endif /* CONFIG_STA_SUPPORT */ + +void getRate(HTTRANSMIT_SETTING HTSetting, UINT32* fLastTxRxRate); + +#ifdef APCLI_SUPPORT +#ifdef WPA_SUPPLICANT_SUPPORT +VOID ApcliSendAssocIEsToWpaSupplicant( + IN RTMP_ADAPTER *pAd, + IN UINT ifIndex); + +INT ApcliWpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet); + +VOID ApcliWpaSendEapolStart( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pBssid, + IN PMAC_TABLE_ENTRY pMacEntry, + IN PAPCLI_STRUCT pApCliEntry); +#endif/*WPA_SUPPLICANT_SUPPORT*/ + +VOID ApCliRTMPSendNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN MAC_TABLE_ENTRY *pMacEntry, + IN USHORT PwrMgmt); + +#endif/*APCLI_SUPPORT*/ + + +void RTMP_IndicateMediaState( + IN RTMP_ADAPTER *pAd, + IN NDIS_MEDIA_STATE media_state); + +#if defined(RT3350) || defined(RT33xx) +VOID RTMP_TxEvmCalibration( + IN RTMP_ADAPTER *pAd); +#endif /* defined(RT3350) || defined(RT33xx) */ + +INT RTMPSetInformation( + IN RTMP_ADAPTER *pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +INT RTMPQueryInformation( + IN RTMP_ADAPTER *pAd, + INOUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +VOID RTMPIoctlShow( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *rq, + IN UINT32 subcmd, + IN VOID *pData, + IN ULONG Data); + +INT RTMP_COM_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +#ifdef CONFIG_AP_SUPPORT +INT RTMP_AP_IoctlPrepare(RTMP_ADAPTER *pAd, VOID *pCB); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_MonitorMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* CONFIG_SNIFFER_SUPPORT */ + +INT Set_VcoPeriod_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Set_RateAlg_Proc(RTMP_ADAPTER *pAd, PSTRING arg); + +#ifdef SINGLE_SKU +INT Set_ModuleTxpower_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* SINGLE_SKU */ + +VOID RtmpEnqueueNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR TxRate, + IN UCHAR AID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP); + +VOID RtmpCleanupPsQueue( + IN RTMP_ADAPTER *pAd, + IN PQUEUE_HEADER pQueue); + +NDIS_STATUS RtmpInsertPsQueue( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR QueIdx); + +VOID RtmpHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT Aid, BOOLEAN isActive); +BOOLEAN RtmpPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm); + +#ifdef CONFIG_MULTI_CHANNEL +VOID RtmpEnqueueLastNullFrame( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP, + IN UCHAR PwrMgmt, + IN UCHAR OpMode); + +VOID EnableMACTxPacket( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR PwrMgmt, + IN BOOLEAN bTxNullFramei, + IN UCHAR QSel); + +VOID DisableMACTxPacket( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR PwrMgmt, + IN BOOLEAN bWaitACK, + IN UCHAR QSel); + +VOID InitMultiChannelRelatedValue( + IN RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN UCHAR CentralChannel); + +VOID EDCA_ActionTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID HCCA_ActionTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +NDIS_STATUS MultiChannelThreadInit(RTMP_ADAPTER *pAd); +BOOLEAN MultiChannelThreadExit(RTMP_ADAPTER *pAd); +VOID MultiChannelTimerStop(RTMP_ADAPTER *pAd); +VOID MultiChannelTimerStart(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* CONFIG_MULTI_CHANNEL */ + +VOID RtmpPrepareHwNullFrame( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP, + IN UCHAR OpMode, + IN UCHAR PwrMgmt, + IN BOOLEAN bWaitACK, + IN CHAR Index); + + +VOID dev_rx_mgmt_frm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +VOID dev_rx_ctrl_frm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN RtmpPktPmBitCheck(RTMP_ADAPTER *pAd); +VOID RtmpPsActiveExtendCheck(RTMP_ADAPTER *pAd); +VOID RtmpPsModeChange(RTMP_ADAPTER *pAd, UINT32 PsMode); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +void DisplayTxAgg (RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID set_default_ap_edca_param(RTMP_ADAPTER *pAd); +VOID set_default_sta_edca_param(RTMP_ADAPTER *pAd); + +UCHAR dot11_2_ra_rate(UCHAR MaxSupportedRateIn500Kbps); +UCHAR dot11_max_sup_rate(INT SupRateLen, UCHAR *SupRate, INT ExtRateLen, UCHAR *ExtRate); + +VOID mgmt_tb_set_mcast_entry(RTMP_ADAPTER *pAd); +VOID set_entry_phy_cfg(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID MacTableReset(RTMP_ADAPTER *pAd); +MAC_TABLE_ENTRY *MacTableLookup(RTMP_ADAPTER *pAd, UCHAR *pAddr); +BOOLEAN MacTableDeleteEntry(RTMP_ADAPTER *pAd, USHORT wcid, UCHAR *pAddr); +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN struct wifi_dev *wdev, + IN UCHAR apidx, + IN UCHAR OpMode, + IN BOOLEAN CleanAll); + +#ifdef MAC_REPEATER_SUPPORT +REPEATER_CLIENT_ENTRY *RTMPLookupRepeaterCliEntry( + IN VOID *pData, + IN BOOLEAN bRealMAC, + IN PUCHAR pAddr, + IN BOOLEAN bIsPad, + OUT PUCHAR pIsLinkValid); + + +BOOLEAN RTMPQueryLookupRepeaterCliEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID RTMPInsertRepeaterAsicEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr); + +VOID RTMPRemoveRepeaterAsicEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR CliIdx); + +VOID RTMPInsertRepeaterEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR apidx, + IN PUCHAR pAddr); + +VOID RTMPRemoveRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + IN UCHAR CliIdx); + +VOID RTMPRemoveRepeaterDisconnectEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR apIdx, + IN UCHAR CliIdx); + +VOID RTMPRepeaterReconnectionCheck( + IN RTMP_ADAPTER *pAd); + +MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN struct wifi_dev *wdev, + IN UCHAR apIdx, + IN UCHAR cliIdx, + IN BOOLEAN CleanAll); + +BOOLEAN RTMPRepeaterVaildMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr); + +INVAILD_TRIGGER_MAC_ENTRY *RepeaterInvaildMacLookup( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr); + +VOID RTMPRepeaterInsertInvaildMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr); + +BOOLEAN RTMPRepeaterRemoveInvaildMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR idx, + IN UCHAR *pAddr); + +INT Show_Repeater_Cli_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT Show_Repeater_Cli_Dump_Proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* MAC_REPEATER_SUPPORT */ + +VOID dump_txwi(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI); +VOID dump_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI); +VOID dump_txinfo(RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo); +VOID dump_rxinfo(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo); +VOID dump_rxblk(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + + +#ifdef RTMP_MAC_PCI +VOID dump_rxd(RTMP_ADAPTER *pAd, RXD_STRUC *pRxD); +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_FPGA_MODE +INT set_vco_cal(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_tr_stop(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_tx_kickcnt(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_data_phy_mode(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_data_bw(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_data_ldpc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_data_mcs(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_data_gi(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_data_basize(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_fpga_mode(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_loopback_mode(RTMP_ADAPTER *pAd, PSTRING arg); +#ifdef CAPTURE_MODE +VOID cap_mode_init(RTMP_ADAPTER *pAd); +VOID cap_mode_deinit(RTMP_ADAPTER *pAd); +INT set_cap_start(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_cap_trigger(RTMP_ADAPTER *pAd, PSTRING arg); +INT asic_cap_start(RTMP_ADAPTER *pAd); +INT asic_cap_stop(RTMP_ADAPTER *pAd); +INT cap_status_chk_and_get(RTMP_ADAPTER *pAd); +INT set_cap_dump(RTMP_ADAPTER *pAd, PSTRING arg); +VOID cap_dump(RTMP_ADAPTER *pAd, CHAR *bank1, CHAR *bank2, INT len); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef WFA_VHT_PF +/* for SIGMA */ +INT set_vht_nss_mcs_cap(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_vht_nss_mcs_opt(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_vht_opmode_notify_ie(RTMP_ADAPTER *pAd, PSTRING arg); + +INT set_force_operating_mode(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_force_amsdu(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_force_noack(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_force_vht_sgi(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_force_vht_tx_stbc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_force_ext_cca(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_rx_rts_cts(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* WFA_VHT_PF */ + + + +#ifdef DROP_MASK_SUPPORT +VOID asic_set_drop_mask( + RTMP_ADAPTER *ad, + USHORT wcid, + BOOLEAN enable); + +VOID asic_drop_mask_reset( + RTMP_ADAPTER *ad); + +VOID drop_mask_init_per_client( + RTMP_ADAPTER *ad, + MAC_TABLE_ENTRY *entry); + +VOID drop_mask_release_per_client( + RTMP_ADAPTER *ad, + MAC_TABLE_ENTRY *entry); + +VOID drop_mask_set_per_client( + RTMP_ADAPTER *ad, + MAC_TABLE_ENTRY *entry, + BOOLEAN enable); + +VOID drop_mask_timer_action( + PVOID SystemSpecific1, + PVOID FunctionContext, + PVOID SystemSpecific2, + PVOID SystemSpecific3); +#endif /* DROP_MASK_SUPPORT */ + +#ifdef PEER_DELBA_TX_ADAPT +VOID Peer_DelBA_Tx_Adapt_Init( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID PeerDelBATxAdaptTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* PEER_DELBA_TX_ADAPT */ + +#ifdef MULTI_CLIENT_SUPPORT +VOID asic_change_tx_retry( + IN RTMP_ADAPTER *pAd, + IN USHORT num); + +VOID pkt_aggr_num_change( + IN RTMP_ADAPTER *pAd, + IN USHORT num); + +VOID asic_tune_be_wmm( + IN RTMP_ADAPTER *pAd, + IN USHORT num); +#endif /* MULTI_CLIENT_SUPPORT */ + +INT set_rf(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_rf_bit(RTMP_ADAPTER *pAd, PSTRING arg); +int write_reg(RTMP_ADAPTER *ad, u32 base, u16 offset, u32 value); +int read_reg(struct _RTMP_ADAPTER *ad, u32 base, u16 offset, u32 *value); +INT show_pwr_info(RTMP_ADAPTER *ad, PSTRING arg); +#ifdef DBG_DIAGNOSE +INT Show_Diag_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +#endif +#ifdef CONFIG_CALIBRATION_COLLECTION +INT Show_Cal_Info(struct _RTMP_ADAPTER *pAd, PSTRING arg); +#endif + +#ifdef WSC_NFC_SUPPORT +INT RtmpOSNotifyRawData( + IN PNET_DEV pNetDev, + IN PUCHAR buff, + IN INT len, + IN ULONG type, + IN USHORT protocol); + +BOOLEAN WscProcessCredential( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPlainData, + IN INT PlainLength, + IN PWSC_CTRL pWscCtrl); +#endif /* WSC_NFC_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT +VOID Monitor_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); +VOID Monitor_Remove(RTMP_ADAPTER *pAd); +BOOLEAN Monitor_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +BOOLEAN Monitor_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +#endif /* CONFIG_SNIFFER_SUPPORT */ +int gen_radiotap_header(RTMP_ADAPTER *pAd,RX_BLK *pRxBlk); +#ifdef APCLI_SUPPORT +BOOLEAN check_rx_pkt_pn_allowed(RTMP_ADAPTER *pAd, RX_BLK *rx_blk); +void rx_get_pn(RX_BLK *pRxBlk,RXINFO_STRUC *pRxInfo); +#endif /* APCLI_SUPPORT */ + + +#endif /* __RTMP_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_chip.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_chip.h new file mode 100644 index 000000000..f294bc904 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_chip.h @@ -0,0 +1,1669 @@ +/* + *************************************************************************** + * 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_chip.h + + Abstract: + Ralink Wireless Chip related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_CHIP_H__ +#define __RTMP_CHIP_H__ + +#include "rtmp_type.h" + +struct _RTMP_ADAPTER; +struct _RSSI_SAMPLE; + +#include "mac_ral/pbf.h" + +#include "eeprom.h" + +#ifdef RTMP_MAC_PCI +#include "iface/rtmp_reg_pcirbs.h" +#include "mac_ral/rtmp_mac.h" +#include "mac_ral/mac_pci.h" +#endif /* RTMP_MAC_PCI */ + + + + + + + + + + + + + + + + + + + + +#ifdef RT6352 +#include "chip/rt6352.h" +#endif /* RT6352 */ + + +#ifdef RT65xx +#include "chip/rt65xx.h" + + +#ifdef MT76x2 +#include "chip/mt76x2.h" +#endif /* MT76x2 */ + +#ifdef RT8592 +#include "chip/rt8592.h" +#endif /* RT8592 */ +#endif /* RT65xx */ + + +#include "mcu/mcu.h" + +#define IS_RT3090A(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30900000)) + +/* We will have a cost down version which mac version is 0x3090xxxx */ +#define IS_RT3090(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30710000) || (IS_RT3090A(_pAd))) + +#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) +#define IS_RT3071(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30710000) +#define IS_RT2070(_pAd) (((_pAd)->RfIcType == RFIC_2020) || ((_pAd)->EFuseTag == 0x27)) + +#define IS_RT2860(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x28600000) +#define IS_RT2870(_pAd) (IS_RT2860(_pAd) && IS_USB_INF(_pAd)) +#define IS_RT2872(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x28720000) +#define IS_RT2880(_pAd) (IS_RT2860(_pAd) && IS_RBUS_INF(_pAd)) + +#define IS_RT30xx(_pAd) (((_pAd)->MACVersion & 0xfff00000) == 0x30700000||IS_RT3090A(_pAd)||IS_RT3390(_pAd)) + +#define IS_RT3052B(_pAd) (((_pAd)->CommonCfg.CID == 0x102) && (((_pAd)->CommonCfg.CN >> 16) == 0x3033)) +#define IS_RT3052(_pAd) (((_pAd)->MACVersion == 0x28720200) && (_pAd->Antenna.field.TxPath == 2)) +#define IS_RT3050(_pAd) (((_pAd)->MACVersion == 0x28720200) && ((_pAd)->RfIcType == RFIC_3020)) +#define IS_RT3350(_pAd) (((_pAd)->MACVersion == 0x28720200) && ((_pAd)->RfIcType == RFIC_3320)) +#define IS_RT3352(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x33520000) +#define IS_RT5350(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x53500000) +#define IS_RT305x(_pAd) (IS_RT3050(_pAd) || IS_RT3052(_pAd) || IS_RT3350(_pAd) || IS_RT3352(_pAd) || IS_RT5350(_pAd)) +#define IS_RT3050_3052_3350(_pAd) (\ + ((_pAd)->MACVersion == 0x28720200) && \ + ((((_pAd)->CommonCfg.CN >> 16) == 0x3333) || (((_pAd)->CommonCfg.CN >> 16) == 0x3033)) \ +) +#define IS_RT6352(_pAd) ((((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) && ((_pAd)->infType == RTMP_DEV_INF_RBUS)) + + +/* RT3572, 3592, 3562, 3062 share the same MAC version */ +#define IS_RT3572(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x35720000) + +/* Check if it is RT3xxx, or Specified ID in registry for debug */ +#define IS_DEV_RT3xxx(_pAd)( \ + (_pAd->DeviceID == NIC3090_PCIe_DEVICE_ID) || \ + (_pAd->DeviceID == NIC3091_PCIe_DEVICE_ID) || \ + (_pAd->DeviceID == NIC3092_PCIe_DEVICE_ID) || \ + (_pAd->DeviceID == NIC3592_PCIe_DEVICE_ID) || \ + ((_pAd->DeviceID == NIC3593_PCI_OR_PCIe_DEVICE_ID) && (RT3593OverPCIe(_pAd))) \ +) + +#define RT3593_DEVICE_ID_CHECK(__DevId) \ + (0) + +#define RT3592_DEVICE_ID_CHECK(__DevId) \ + (__DevId == NIC3592_PCIe_DEVICE_ID) + +#define IS_RT2883(_pAd) (0) + +#define IS_RT3883(_pAd) (0) + +#define IS_VERSION_BEFORE_F(_pAd) (((_pAd)->MACVersion&0xffff) <= 0x0211) +/* F version is 0x0212, E version is 0x0211. 309x can save more power after F version. */ +#define IS_VERSION_AFTER_F(_pAd) ((((_pAd)->MACVersion&0xffff) >= 0x0212) || (((_pAd)->b3090ESpecialChip == TRUE))) + +#define IS_RT3290(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x32900000) +#define IS_RT3290LE(_pAd) ((((_pAd)->MACVersion & 0xffffffff) >= 0x32900011)) + +/* 3593 */ +#define IS_RT3593(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x35930000) + +/* RT5392 */ +#define IS_RT5392(_pAd) ((_pAd->MACVersion & 0xFFFF0000) == 0x53920000) /* Include RT5392, RT5372 and RT5362 */ + +/* RT5390 */ +#define IS_RT5390(_pAd) (((((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) || IS_RT5390H(_pAd)) && ((_pAd)->infType != RTMP_DEV_INF_RBUS)) /* Include RT5390, RT5370 and RT5360 */ + +/* RT5390F */ +#define IS_RT5390F(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0502)) + +/* RT5370G */ +#define IS_RT5370G(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0503)) /* support HW PPAD ( the hardware rx antenna diversity ) */ + +/* RT5390R */ +#define IS_RT5390R(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) == 0x1502)) /* support HW PPAD ( the hardware rx antenna diversity ) */ + +/* PCIe interface NIC */ +#define IS_MINI_CARD(_pAd) ((_pAd)->Antenna.field.BoardType == BOARD_TYPE_MINI_CARD) + +/* 5390U (5370 using PCIe interface) */ +#define IS_RT5390U(_pAd) (IS_MINI_CARD(_pAd) && (((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) && ((_pAd)->infType != RTMP_DEV_INF_RBUS)) + +/* RT5390H */ +#define IS_RT5390H(_pAd) (((_pAd->MACVersion & 0xFFFF0000) == 0x53910000) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x1500)) + +/* RT5390BC8 (WiFi + BT) */ + + +/* RT5390D */ +#define IS_RT5390D(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0502)) + +/* RT5392C */ +#define IS_RT5392C(_pAd) ((IS_RT5392(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0222)) /* Include RT5392, RT5372 and RT5362 */ + +#define IS_RT5592(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x55920000) +#define REV_RT5592C 0x0221 + +#define IS_RT8592(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x85590000) + +#define IS_MT7601(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x76010000) +#define IS_MT7601U(_pAd) (IS_MT7601(_pAd) && (IS_USB_INF(_pAd))) + +#define IS_MT7650(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76500000) +#define IS_MT7650E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76500000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7650U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76500000) && (IS_USB_INF(_pAd))) +#define IS_MT7630(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76300000) +#define IS_MT7630E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76300000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7630U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76300000) && (IS_USB_INF(_pAd))) +#define IS_MT7610(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76100000) +#define IS_MT7610E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76100000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7610U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76100000) && (IS_USB_INF(_pAd))) +#define IS_MT76x0(_pAd) (IS_MT7610(_pAd) || IS_MT7630(_pAd) || IS_MT7650(_pAd)) +#define IS_MT76x0E(_pAd) (IS_MT7650E(_pAd) || IS_MT7630E(_pAd) || IS_MT7610E(_pAd)) +#define IS_MT76x0U(_pAd) (IS_MT7650U(_pAd) || IS_MT7630U(_pAd) || IS_MT7610U(_pAd)) + +#define IS_MT7662(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76620000) +#define IS_MT7662E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76620000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7662U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76620000) && (IS_USB_INF(_pAd))) +#define IS_MT7632(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76320000) +#define IS_MT7632E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76320000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7632U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76320000) && (IS_USB_INF(_pAd))) +#define IS_MT7612(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76120000) +#define IS_MT7612E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76120000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7612U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76120000) && (IS_USB_INF(_pAd))) +#define IS_MT7602(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76020000) +#define IS_MT7602E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76020000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7662T(_pAd) ((((_pAd)->ChipID & 0xffff0f00) == 0x76620100) && (IS_USB_INF(_pAd))) +#define IS_MT7632T(_pAd) ((((_pAd)->ChipID & 0xffff0f00) == 0x76320100) && (IS_USB_INF(_pAd))) +#define IS_MT7612T(_pAd) ((((_pAd)->ChipID & 0xffff0f00) == 0x76120100) && (IS_USB_INF(_pAd))) +#define IS_MT76x2(_pAd) (IS_MT7662(_pAd) || IS_MT7632(_pAd) || IS_MT7612(_pAd) || IS_MT7602(_pAd)) +#define IS_MT76x2E(_pAd) (IS_MT7662E(_pAd) || IS_MT7632E(_pAd) || IS_MT7612E(_pAd) || IS_MT7602E(_pAd)) +#define IS_MT76x2U(_pAd) (IS_MT7662U(_pAd) || IS_MT7632U(_pAd) || IS_MT7612U(_pAd)) +#define IS_MT76x2T(_pAd) (IS_MT7662T(_pAd) || IS_MT7632T(_pAd) || IS_MT7612T(_pAd)) +#define REV_MT76x2E3 0x0022 +#define REV_MT76x2E4 0x0033 + +#define IS_MT76xx(_pAd) (IS_MT76x0(_pAd) || IS_MT76x2(_pAd)) + +#define IS_RT65XX(_pAd) ((((_pAd)->MACVersion & 0xFFFF0000) == 0x65900000) ||\ + (IS_RT8592(_pAd))||\ + (IS_MT76x0(_pAd)) ||\ + (IS_MT76x2(_pAd))) + + +/* RT3592BC8 (WiFi + BT) */ + +#define IS_USB_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_USB) +#define IS_USB3_INF(_pAd) ((IS_USB_INF(_pAd)) && ((_pAd)->BulkOutMaxPacketSize == 1024)) +#define IS_PCIE_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_PCIE) +#define IS_PCI_INF(_pAd) (((_pAd)->infType == RTMP_DEV_INF_PCI) || IS_PCIE_INF(_pAd)) +#define IS_PCI_ONLY_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_PCI) +#define IS_RBUS_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_RBUS) + +#define RT_REV_LT(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->MACVersion & 0x0000FFFF) < (_rev)) + +#define RT_REV_GTE(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->MACVersion & 0x0000FFFF) >= (_rev)) + +#define MT_REV_LT(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->ChipID & 0x0000FFFF) < (_rev)) + +#define MT_REV_ET(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->ChipID & 0x0000FFFF) == (_rev)) + +#define MT_REV_GTE(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->ChipID & 0x0000FFFF) >= (_rev)) + +/* Dual-band NIC (RF/BBP/MAC are in the same chip.) */ + +#define IS_RT_NEW_DUAL_BAND_NIC(_pAd) ((FALSE)) + + +/* Is the NIC dual-band NIC? */ + +#define IS_DUAL_BAND_NIC(_pAd) (((_pAd->RfIcType == RFIC_2850) || (_pAd->RfIcType == RFIC_2750) || (_pAd->RfIcType == RFIC_3052) \ + || (_pAd->RfIcType == RFIC_3053) || (_pAd->RfIcType == RFIC_2853) || (_pAd->RfIcType == RFIC_3853) \ + || IS_RT_NEW_DUAL_BAND_NIC(_pAd)) && !IS_RT5390(_pAd)) + + +/* RT3593 over PCIe bus */ +#define RT3593OverPCIe(_pAd) (IS_RT3593(_pAd) && (_pAd->CommonCfg.bPCIeBus == TRUE)) + +/* RT3593 over PCI bus */ +#define RT3593OverPCI(_pAd) (IS_RT3593(_pAd) && (_pAd->CommonCfg.bPCIeBus == FALSE)) + +/*RT3390,RT3370 */ +#define IS_RT3390(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x33900000) + +#define CCA_AVG_MAX_COUNT 5 + +/* ------------------------------------------------------ */ +/* PCI registers - base address 0x0000 */ +/* ------------------------------------------------------ */ +#define CHIP_PCI_CFG 0x0000 +#define CHIP_PCI_EECTRL 0x0004 +#define CHIP_PCI_MCUCTRL 0x0008 + +#define OPT_14 0x114 + +#define RETRY_LIMIT 10 + +/* ------------------------------------------------------ */ +/* BBP & RF definition */ +/* ------------------------------------------------------ */ +#define BUSY 1 +#define IDLE 0 + +/*------------------------------------------------------------------------- */ +/* EEPROM definition */ +/*------------------------------------------------------------------------- */ +#define EEDO 0x08 +#define EEDI 0x04 +#define EECS 0x02 +#define EESK 0x01 +#define EERL 0x80 + +#define EEPROM_WRITE_OPCODE 0x05 +#define EEPROM_READ_OPCODE 0x06 +#define EEPROM_EWDS_OPCODE 0x10 +#define EEPROM_EWEN_OPCODE 0x13 + +#define NUM_EEPROM_BBP_PARMS 19 /* Include NIC Config 0, 1, CR, TX ALC step, BBPs */ +#define NUM_EEPROM_TX_G_PARMS 7 + +#define VALID_EEPROM_VERSION 1 +#define EEPROM_VERSION_OFFSET 0x02 +#define EEPROM_NIC1_OFFSET 0x34 /* The address is from NIC config 0, not BBP register ID */ +#define EEPROM_NIC2_OFFSET 0x36 /* The address is from NIC config 1, not BBP register ID */ + + +#define EEPROM_COUNTRY_REGION 0x38 +#define COUNTRY_REGION_A_BAND_MASK (0xff) +#define COUNTRY_REGION_G_BAND (0xff << 8) + +#define EEPROM_DEFINE_MAX_TXPWR 0x4e +#define MAX_EIRP_TX_PWR_G_BAND_MASK (0xff) +#define MAX_EIRP_TX_PWR_A_BAND_MASK (0xff << 8) + +#define EEPROM_FREQ_OFFSET 0x3a +#define FREQ_OFFSET_MASK (0x7f) +#define FREQ_OFFSET_DIP (1 << 7) +#define LED_MODE_MASK (0xff << 8) + +#define EEPROM_LEDAG_CONF_OFFSET 0x3c +#define EEPROM_LEDACT_CONF_OFFSET 0x3e +#define EEPROM_LED_POLARITY_OFFSET 0x40 +#if defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(RT6352) || defined(MT76x2) +#define EEPROM_NIC3_OFFSET 0x42 +#endif /* defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) || defined(RT8592) || defined(RT6352) || defined(MT76x2) */ + +#define EEPROM_LNA_OFFSET 0x44 +#define LNA_GAIN_G_BAND_MASK (0x7f) +#define LNA_GAIN_G_BAND_EN (1 << 7) +#define LNA_GAIN_A_BAND_CH36_64_MASK (0x7f << 8) +#define LNA_GAIN_A_BAND_CH36_64_EN (1 << 15) + +#define EEPROM_RSSI_BG_OFFSET 0x46 +#define RSSI0_OFFSET_G_BAND_MASK (0x3f) +#define RSSI0_OFFSET_G_BAND_SIGN (1 << 6) +#define RSSI0_OFFSET_G_BAND_EN (1 << 7) +#define RSSI1_OFFSET_G_BAND_MASK (0x3f << 8) +#define RSSI1_OFFSET_G_BAND_SIGN (1 << 14) +#define RSSI1_OFFSET_G_BAND_EN (1 << 15) + +#define EEPROM_TXMIXER_GAIN_2_4G 0x48 +#define LNA_GAIN_A_BAND_CH100_128_MASK (0x7f << 8) +#define LNA_GAIN_A_BAND_CH100_128_EN (1 << 15) + +#define EEPROM_RSSI_A_OFFSET 0x4a +#define RSSI0_OFFSET_A_BAND_MASK (0x3f) +#define RSSI0_OFFSET_A_BAND_SIGN (1 << 6) +#define RSSI0_OFFSET_A_BANE_EN (1 << 7) +#define RSSI1_OFFSET_A_BAND_MASK (0x3f << 8) +#define RSSI1_OFFSET_A_BAND_SIGN (1 << 14) +#define RSSI1_OFFSET_A_BAND_EN (1 << 15) + +#define EEPROM_TXMIXER_GAIN_5G 0x4c +#define LNA_GAIN_A_BAND_CH132_165_MASK (0x7f << 8) +#define LNA_GAIN_A_BAND_CH132_165_EN (1 << 15) + +#define EEPROM_TXPOWER_DELTA 0x50 /* 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. */ + +#define EEPROM_G_TX_PWR_OFFSET 0x52 +#define EEPROM_G_TX2_PWR_OFFSET 0x60 + +#define EEPROM_G_TSSI_BOUND1 0x6e +#define EEPROM_G_TSSI_BOUND2 0x70 +#define EEPROM_G_TSSI_BOUND3 0x72 +#define EEPROM_G_TSSI_BOUND4 0x74 +#define EEPROM_G_TSSI_BOUND5 0x76 + + + +#define EEPROM_A_TX_PWR_OFFSET 0x78 +#define EEPROM_A_TX2_PWR_OFFSET 0xa6 + +#define MBSSID_MODE0 0 +#define MBSSID_MODE1 1 /* Enhance NEW MBSSID MODE mapping to mode 0 */ +#ifdef ENHANCE_NEW_MBSSID_MODE +#define MBSSID_MODE2 2 /* Enhance NEW MBSSID MODE mapping to mode 1 */ +#define MBSSID_MODE3 3 /* Enhance NEW MBSSID MODE mapping to mode 2 */ +#define MBSSID_MODE4 4 /* Enhance NEW MBSSID MODE mapping to mode 3 */ +#define MBSSID_MODE5 5 /* Enhance NEW MBSSID MODE mapping to mode 4 */ +#define MBSSID_MODE6 6 /* Enhance NEW MBSSID MODE mapping to mode 5 */ +#endif /* ENHANCE_NEW_MBSSID_MODE */ + +enum FREQ_CAL_INIT_MODE { + FREQ_CAL_INIT_MODE0, + FREQ_CAL_INIT_MODE1, + FREQ_CAL_INIT_MODE2, + FREQ_CAL_INIT_UNKNOW, +}; + +enum FREQ_CAL_MODE { + FREQ_CAL_MODE0, + FREQ_CAL_MODE1, + FREQ_CAL_MODE2, +}; + +enum RXWI_FRQ_OFFSET_FIELD { + RXWI_FRQ_OFFSET_FIELD0, /* SNR1 */ + RXWI_FRQ_OFFSET_FIELD1, /* Frequency Offset */ +}; + + + +#define EEPROM_A_TSSI_BOUND1 0xd4 +#define EEPROM_A_TSSI_BOUND2 0xd6 +#define EEPROM_A_TSSI_BOUND3 0xd8 +#define EEPROM_A_TSSI_BOUND4 0xda +#define EEPROM_A_TSSI_BOUND5 0xdc + + +#ifdef MT76x2 +/* ITxBF calibration values EEPROM locations 0xC0 to 0xF1 */ +#define EEPROM1_ITXBF_CAL 0xc0 +#define EEPROM1_ITXBF_CAL_TANK 0x180 +#define EEPROM1_ITXBF_CAL_DIVPHASE 0x18A +#define EEPROM1_ITXBF_CAL_RESPHASE 0x190 +#define EEPROM1_ITXBF_CAL_RESPHASE_ERR 0x19E +#endif + +#define EEPROM_TXPOWER_BYRATE 0xde /* 20MHZ power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde /* 20MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee /* 40MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa /* 20MHZ 5G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a /* 40MHZ 5G tx power. */ + +#define EEPROM_BBP_BASE_OFFSET 0xf0 /* The address is from NIC config 0, not BBP register ID */ + +/* */ +/* Bit mask for the Tx ALC and the Tx fine power control */ +/* */ +#define GET_TX_ALC_BIT_MASK 0x1F /* Valid: 0~31, and in 0.5dB step */ +#define GET_TX_FINE_POWER_CTRL_BIT_MASK 0xE0 /* Valid: 0~4, and in 0.1dB step */ +#define NUMBER_OF_BITS_FOR_TX_ALC 5 /* The length, in bit, of the Tx ALC field */ + + +/* TSSI gain and TSSI attenuation */ + +#define EEPROM_TSSI_GAIN_AND_ATTENUATION 0x76 + +/*#define EEPROM_Japan_TX_PWR_OFFSET 0x90 // 802.11j */ +/*#define EEPROM_Japan_TX2_PWR_OFFSET 0xbe */ +/*#define EEPROM_TSSI_REF_OFFSET 0x54 */ +/*#define EEPROM_TSSI_DELTA_OFFSET 0x24 */ +/*#define EEPROM_CCK_TX_PWR_OFFSET 0x62 */ +/*#define EEPROM_CALIBRATE_OFFSET 0x7c */ + +#define EEPROM_NIC_CFG1_OFFSET 0 +#define EEPROM_NIC_CFG2_OFFSET 1 +#define EEPROM_NIC_CFG3_OFFSET 2 +#define EEPROM_COUNTRY_REG_OFFSET 3 +#define EEPROM_BBP_ARRAY_OFFSET 4 + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* */ +/* The TSSI over OFDM 54Mbps */ +/* */ +#define EEPROM_TSSI_OVER_OFDM_54 0x6E + +/* */ +/* The TSSI value/step (0.5 dB/unit) */ +/* */ +#define EEPROM_TSSI_STEP_OVER_2DOT4G 0x77 +#define EEPROM_TSSI_STEP_OVER_5DOT5G 0xDD +#define TSSI_READ_SAMPLE_NUM 3 + +/* */ +/* Per-channel Tx power offset (for the extended TSSI mode) */ +/* */ +#define EEPROM_TX_POWER_OFFSET_OVER_CH_1 0x6F +#define EEPROM_TX_POWER_OFFSET_OVER_CH_3 0x70 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_5 0x71 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_7 0x72 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_9 0x73 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_11 0x74 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_13 0x75 + +/* */ +/* Tx power configuration (bit3:0 for Tx0 power setting and bit7:4 for Tx1 power setting) */ +/* */ +#define EEPROM_CCK_MCS0_MCS1 0xDE +#define EEPROM_CCK_MCS2_MCS3 0xDF +#define EEPROM_OFDM_MCS0_MCS1 0xE0 +#define EEPROM_OFDM_MCS2_MCS3 0xE1 +#define EEPROM_OFDM_MCS4_MCS5 0xE2 +#define EEPROM_OFDM_MCS6_MCS7 0xE3 +#define EEPROM_HT_MCS0_MCS1 0xE4 +#define EEPROM_HT_MCS2_MCS3 0xE5 +#define EEPROM_HT_MCS4_MCS5 0xE6 +#define EEPROM_HT_MCS6_MCS7 0xE7 +#define EEPROM_HT_MCS8_MCS9 0xE8 +#define EEPROM_HT_MCS10_MCS11 0xE9 +#define EEPROM_HT_MCS12_MCS13 0xEA +#define EEPROM_HT_MCS14_MCS15 0xEB +#define EEPROM_HT_USING_STBC_MCS0_MCS1 0xEC +#define EEPROM_HT_USING_STBC_MCS2_MCS3 0xED +#define EEPROM_HT_USING_STBC_MCS4_MCS5 0xEE +#define EEPROM_HT_USING_STBC_MCS6_MCS7 0xEF + +/* */ +/* Bit mask for the Tx ALC and the Tx fine power control */ +/* */ + +#define DEFAULT_BBP_TX_FINE_POWER_CTRL 0 + +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT RssiIndicationMode:1; /* RSSI indication mode */ + USHORT Rsv:1; + USHORT BoardType:2; /* 0: mini card; 1: USB pen */ + USHORT RfIcType:4; /* see E2PROM document */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#else +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT RfIcType:4; /* see E2PROM document */ + USHORT BoardType:2; /* 0: mini card; 1: USB pen */ + USHORT Rsv:1; + USHORT RssiIndicationMode:1; /* RSSI indication mode */ + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#endif + + +/* + * EEPROM operation related marcos + */ +#define RT28xx_EEPROM_READ16(_pAd, _offset, _value) \ + (_pAd)->chipOps.eeread((RTMP_ADAPTER *)(_pAd), (USHORT)(_offset), (PUSHORT)&(_value)) + +#define RT28xx_EEPROM_WRITE16(_pAd, _offset, _value) \ + (_pAd)->chipOps.eewrite((RTMP_ADAPTER *)(_pAd), (USHORT)(_offset), (USHORT)(_value)) + + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* The Tx power tuning entry */ +typedef struct _TX_POWER_TUNING_ENTRY_STRUCT { + CHAR RF_TX_ALC; /* 3390: RF R12[4:0]: Tx0 ALC, 5390: RF R49[5:0]: Tx0 ALC */ + CHAR MAC_PowerDelta; /* Tx power control over MAC 0x1314~0x1324 */ +} TX_POWER_TUNING_ENTRY_STRUCT, *PTX_POWER_TUNING_ENTRY_STRUCT; +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + +struct RF_BANK_OFFSET { + UINT8 RFBankIndex; + UINT16 RFStart; + UINT16 RFEnd; +}; + +struct RF_INDEX_OFFSET { + UINT8 RFIndex; + UINT16 RFStart; + UINT16 RFEnd; +}; + +/* + 2860: 28xx + 2870: 28xx + + 30xx: + 3090 + 3070 + 2070 3070 + + 33xx: 30xx + 3390 3090 + 3370 3070 + + 35xx: 30xx + 3572, 2870, 28xx + 3062, 2860, 28xx + 3562, 2860, 28xx + + 3593, 28xx, 30xx, 35xx + + < Note: 3050, 3052, 3350 can not be compiled simultaneously. > + 305x: + 3052 + 3050 + 3350, 3050 + + 3352: 305x + + 2880: 28xx + 2883: + 3883: +*/ + +struct _RTMP_CHIP_CAP_ { + /* register */ + REG_PAIR *pRFRegTable; + REG_PAIR *pBBPRegTable; + UCHAR bbpRegTbSize; + + UINT32 MaxNumOfRfId; + UINT32 MaxNumOfBbpId; + +#define RF_REG_WT_METHOD_NONE 0 +#define RF_REG_WT_METHOD_STEP_ON 1 + UCHAR RfReg17WtMethod; + + /* beacon */ + BOOLEAN FlgIsSupSpecBcnBuf; /* SPECIFIC_BCN_BUF_SUPPORT */ + UINT8 BcnMaxNum; /* software use */ + UINT8 BcnMaxHwNum; /* hardware limitation */ + UINT8 WcidHwRsvNum; /* hardware available WCID number */ + UINT16 BcnMaxHwSize; /* hardware maximum beacon size */ + UINT16 BcnBase[HW_BEACON_MAX_NUM]; /* hardware beacon base address */ + + /* function */ + /* use UINT8, not bit-or to speed up driver */ + BOOLEAN FlgIsHwWapiSup; + +#ifdef THERMAL_PROTECT_SUPPORT + BOOLEAN ThermalProtectSup; +#endif /* THERMAL_PROTECT_SUPPORT */ + + /* VCO calibration mode */ + UINT8 VcoPeriod; /* default 10s */ +#define VCO_CAL_DISABLE 0 /* not support */ +#define VCO_CAL_MODE_1 1 /* toggle RF7[0] */ +#define VCO_CAL_MODE_2 2 /* toggle RF3[7] */ +#define VCO_CAL_MODE_3 3 /* toggle RF4[7] or RF5[7] */ + UINT8 FlgIsVcoReCalMode; + + BOOLEAN FlgIsHwAntennaDiversitySup; + BOOLEAN Flg7662ChipCap; +#ifdef STREAM_MODE_SUPPORT + BOOLEAN FlgHwStreamMode; +#endif /* STREAM_MODE_SUPPORT */ +#ifdef TXBF_SUPPORT + BOOLEAN FlgHwTxBfCap; + BOOLEAN FlgITxBfBinWrite; +#endif /* TXBF_SUPPORT */ +#ifdef FIFO_EXT_SUPPORT + BOOLEAN FlgHwFifoExtCap; +#endif /* FIFO_EXT_SUPPORT */ + + UCHAR ba_max_cnt; + +#ifdef RTMP_MAC_PCI +#ifdef CONFIG_STA_SUPPORT + BOOLEAN HW_PCIE_PS_SUPPORT; + BOOLEAN HW_PCIE_PS_L3_ENABLE; +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + enum ASIC_CAP asic_caps; + enum PHY_CAP phy_caps; + enum HIF_TYPE hif_type; + enum MAC_TYPE mac_type; + enum BBP_TYPE bbp_type; + enum MCU_TYPE MCUType; + enum RF_TYPE rf_type; + +#ifdef TXRX_SW_ANTDIV_SUPPORT + BOOLEAN bTxRxSwAntDiv; +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + + BOOLEAN temp_tx_alc_enable; + INT32 temp_25_ref; /* a quantification value of temperature, but not J */ + INT32 current_temp; /* unit J */ + INT32 temp_val; +#ifdef RTMP_TEMPERATURE_TX_ALC + UINT32 high_temp_slope_a_band; /* slope with unit (J /dB) */ + UINT32 low_temp_slope_a_band; /* slope with unit (J /dB) */ + UINT32 high_temp_slope_g_band; /* slope with unit (J /dB) */ + UINT32 low_temp_slope_g_band; /* slope with unit (J /dB) */ + INT32 tc_upper_bound_a_band; /* unit dB */ + INT32 tc_lower_bound_a_band; /* unit dB */ + INT32 tc_upper_bound_g_band; /* unit dB */ + INT32 tc_lower_bound_g_band; /* unit dB */ +#endif /* RTMP_TEMPERATURE_TX_ALC */ + +#ifdef DYNAMIC_VGA_SUPPORT + BOOLEAN dynamic_vga_support; + INT32 compensate_level; + INT32 avg_rssi_0; + INT32 avg_rssi_1; + INT32 avg_rssi_all; + UCHAR dynamic_chE_mode; + BOOLEAN dynamic_chE_trigger; + BOOLEAN skip_long_range_dync_vga; + /* for 76x2 runtime turn long_range_dync_vga on/off , default do long_range_dync_vga */ +#ifdef CONFIG_AP_SUPPORT + INT32 dynamic_lna_trigger_timer; + BOOLEAN microwave_enable; + INT32 agc1_r35_backup; + INT32 agc1_r39_backup; + INT32 agc1_r41_backup; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DYNAMIC_VGA_SUPPORT */ + + /* ---------------------------- signal ---------------------------------- */ +#define SNR_FORMULA1 0 /* ((0xeb - pAd->StaCfg.LastSNR0) * 3) / 16; */ +#define SNR_FORMULA2 1 /* (pAd->StaCfg.LastSNR0 * 3 + 8) >> 4; */ +#define SNR_FORMULA3 2 /* (pAd->StaCfg.LastSNR0) * 3) / 16; */ + UINT8 SnrFormula; + + UINT8 max_nss; /* maximum Nss, 3 for 3883 or 3593 */ + UINT8 max_vht_mcs; /* Maximum Vht MCS */ + +#ifdef DOT11_VHT_AC + UINT8 ac_off_mode; /* 11AC off mode */ +#endif /* DOT11_VHT_AC */ + + BOOLEAN bTempCompTxALC; + BOOLEAN rx_temp_comp; + + BOOLEAN bLimitPowerRange; /* TSSI compensation range limit */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + UINT8 TxAlcTxPowerUpperBound_2G; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable_2G; +#ifdef A_BAND_SUPPORT + UINT8 TxAlcTxPowerUpperBound_5G; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable_5G; +#endif /* A_BAND_SUPPORT */ + +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(SINGLE_SKU_V2) + INT16 PAModeCCK[4]; + INT16 PAModeOFDM[8]; + INT16 PAModeHT[16]; +#ifdef DOT11_VHT_AC + INT16 PAModeVHT[10]; +#endif /* DOT11_VHT_AC */ +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(SINGLE_SKU_V2) */ + + /* ---------------------------- packet ---------------------------------- */ + UINT8 TXWISize; + UINT8 RXWISize; + + /* ---------------------------- others ---------------------------------- */ +#ifdef RTMP_EFUSE_SUPPORT + UINT16 EFUSE_USAGE_MAP_START; + UINT16 EFUSE_USAGE_MAP_END; + UINT8 EFUSE_USAGE_MAP_SIZE; + UINT8 EFUSE_RESERVED_SIZE; +#endif /* RTMP_EFUSE_SUPPORT */ + + UCHAR *EEPROM_DEFAULT_BIN; + UINT16 EEPROM_DEFAULT_BIN_SIZE; + +#ifdef RTMP_FLASH_SUPPORT + BOOLEAN ee_inited; +#endif /* RTMP_FLASH_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + UCHAR carrier_func; +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef DFS_SUPPORT + UINT8 DfsEngineNum; +#endif /* DFS_SUPPORT */ + + /* + Define the burst size of WPDMA of PCI + 0 : 4 DWORD (16bytes) + 1 : 8 DWORD (32 bytes) + 2 : 16 DWORD (64 bytes) + 3 : 32 DWORD (128 bytes) + */ + UINT8 WPDMABurstSIZE; + + /* + * 0: MBSSID_MODE0 + * (The multiple MAC_ADDR/BSSID are distinguished by [bit2:bit0] of byte5) + * 1: MBSSID_MODE1 + * (The multiple MAC_ADDR/BSSID are distinguished by [bit4:bit2] of byte0) + */ + UINT8 MBSSIDMode; + +#ifdef DOT11W_PMF_SUPPORT +#define PMF_ENCRYPT_MODE_0 0 /* All packets must software encryption. */ +#define PMF_ENCRYPT_MODE_1 1 /* Data packets do hardware encryption, management packet do software encryption. */ + UINT8 FlgPMFEncrtptMode; +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RT5592EP_SUPPORT + UINT32 Priv; /* Flag for RT5592 EP */ +#endif /* RT5592EP_SUPPORT */ + +#ifdef RT6352 + INT16 DPDCalPassThres; + INT16 DPDCalPassLowThresTX0; + INT16 DPDCalPassLowThresTX1; + INT16 DPDCalPassHighThresTX0; + INT16 DPDCalPassHighThresTX1; +#endif /* RT6352 */ +#ifdef RT65xx + UINT8 PAType; /* b'00: 2.4G+5G external PA, b'01: 5G external PA, b'10: 2.4G external PA, b'11: Internal PA */ + UINT8 LNA_type; /* b'00: 2.4G+5G external LNA, b'01: 5G external LNA, b'10: 2.4G external LNA, b'11: Internal LNA */ +#endif /* RT65xx */ + +#ifdef CONFIG_ANDES_SUPPORT + UINT32 WlanMemmapOffset; + UINT32 InbandPacketMaxLen; /* must be 48 multible */ + UINT8 CmdRspRxRing; + BOOLEAN IsComboChip; + BOOLEAN need_load_fw; + BOOLEAN need_load_rom_patch; + u8 ram_code_protect; + u8 rom_code_protect; + u8 load_iv; + u32 ilm_offset; + u32 dlm_offset; + u32 rom_patch_offset; +#endif /* CONFIG_ANDES_SUPPORT */ + + UINT8 cmd_header_len; + UINT8 cmd_padding_len; + +#ifdef SINGLE_SKU_V2 + CHAR Apwrdelta; + CHAR Gpwrdelta; +#endif /* SINGLE_SKU_V2 */ + + +#ifdef CONFIG_SWITCH_CHANNEL_OFFLOAD + UINT16 ChannelParamsSize; + UCHAR *ChannelParam; + INT XtalType; +#endif + + UCHAR load_code_method; + UCHAR *FWImageName; + UCHAR *fw_header_image; + UCHAR *fw_bin_file_name; + UCHAR *rom_patch; + UCHAR *rom_patch_header_image; + UCHAR *rom_patch_bin_file_name; + UINT32 rom_patch_len; + UINT32 fw_len; + UCHAR *MACRegisterVer; + UCHAR *BBPRegisterVer; + UCHAR *RFRegisterVer; + +#ifdef CONFIG_WIFI_TEST + UINT32 MemMapStart; + UINT32 MemMapEnd; + UINT32 BBPMemMapOffset; + UINT16 BBPStart; + UINT16 BBPEnd; + UINT16 RFStart; + UINT16 RFEnd; +#ifdef RLT_RF + UINT8 RFBankNum; + struct RF_BANK_OFFSET *RFBankOffset; +#endif +#ifdef MT_RF + UINT8 RFIndexNum; + struct RF_INDEX_OFFSET *RFIndexOffset; +#endif + UINT32 MacMemMapOffset; + UINT32 MacStart; + UINT32 MacEnd; + UINT16 E2PStart; + UINT16 E2PEnd; + BOOLEAN pbf_loopback; + BOOLEAN pbf_rx_drop; +#endif + + BOOLEAN tssi_enable; + BOOLEAN ed_cca_enable; + +#ifdef MT76x2 +#define TSSI_INIT_STAGE 0 +#define TSSI_CAL_STAGE 1 +#define TSSI_TRIGGER_STAGE 2 +#define TSSI_COMP_STAGE 3 + UINT8 tssi_stage; +#define TSSI_0_SLOPE_G_BAND_DEFAULT_VALUE 0x84 +#define TSSI_1_SLOPE_G_BAND_DEFAULT_VALUE 0x83 + UINT8 tssi_0_slope_g_band; + UINT8 tssi_1_slope_g_band; +#define TSSI_0_OFFSET_G_BAND_DEFAULT_VALUE 0x0A +#define TSSI_1_OFFSET_G_BAND_DEFAULT_VALUE 0x0B + UINT8 tssi_0_offset_g_band; + UINT8 tssi_1_offset_g_band; +#define A_BAND_GRP0_CHL 0 +#define A_BAND_GRP1_CHL 1 +#define A_BAND_GRP2_CHL 2 +#define A_BAND_GRP3_CHL 3 +#define A_BAND_GRP4_CHL 4 +#define A_BAND_GRP5_CHL 5 +#define A_BAND_GRP_NUM 6 +#define TSSI_0_SLOPE_A_BAND_GRP0_DEFAULT_VALUE 0x7A +#define TSSI_1_SLOPE_A_BAND_GRP0_DEFAULT_VALUE 0x79 +#define TSSI_0_SLOPE_A_BAND_GRP1_DEFAULT_VALUE 0x7A +#define TSSI_1_SLOPE_A_BAND_GRP1_DEFAULT_VALUE 0x79 +#define TSSI_0_SLOPE_A_BAND_GRP2_DEFAULT_VALUE 0x78 +#define TSSI_1_SLOPE_A_BAND_GRP2_DEFAULT_VALUE 0x7B +#define TSSI_0_SLOPE_A_BAND_GRP3_DEFAULT_VALUE 0x7E +#define TSSI_1_SLOPE_A_BAND_GRP3_DEFAULT_VALUE 0x77 +#define TSSI_0_SLOPE_A_BAND_GRP4_DEFAULT_VALUE 0x76 +#define TSSI_1_SLOPE_A_BAND_GRP4_DEFAULT_VALUE 0x7E +#define TSSI_0_SLOPE_A_BAND_GRP5_DEFAULT_VALUE 0x75 +#define TSSI_1_SLOPE_A_BAND_GRP5_DEFAULT_VALUE 0x79 + UINT8 tssi_0_slope_a_band[A_BAND_GRP_NUM]; + UINT8 tssi_1_slope_a_band[A_BAND_GRP_NUM]; +#define TSSI_0_OFFSET_A_BAND_GRP0_DEFAULT_VALUE 0x06 +#define TSSI_1_OFFSET_A_BAND_GRP0_DEFAULT_VALUE 0x0A +#define TSSI_0_OFFSET_A_BAND_GRP1_DEFAULT_VALUE 0x06 +#define TSSI_1_OFFSET_A_BAND_GRP1_DEFAULT_VALUE 0x0A +#define TSSI_0_OFFSET_A_BAND_GRP2_DEFAULT_VALUE 0x08 +#define TSSI_1_OFFSET_A_BAND_GRP2_DEFAULT_VALUE 0x06 +#define TSSI_0_OFFSET_A_BAND_GRP3_DEFAULT_VALUE 0x02 +#define TSSI_1_OFFSET_A_BAND_GRP3_DEFAULT_VALUE 0x14 +#define TSSI_0_OFFSET_A_BAND_GRP4_DEFAULT_VALUE 0x16 +#define TSSI_1_OFFSET_A_BAND_GRP4_DEFAULT_VALUE 0x05 +#define TSSI_0_OFFSET_A_BAND_GRP5_DEFAULT_VALUE 0x1C +#define TSSI_1_OFFSET_A_BAND_GRP5_DEFAULT_VALUE 0x11 + UINT8 tssi_0_offset_a_band[A_BAND_GRP_NUM]; + UINT8 tssi_1_offset_a_band[A_BAND_GRP_NUM]; +#define TX_TARGET_PWR_DEFAULT_VALUE 0x14 + CHAR tx_0_target_pwr_g_band; + CHAR tx_1_target_pwr_g_band; + CHAR tx_0_target_pwr_a_band[A_BAND_GRP_NUM]; + CHAR tx_1_target_pwr_a_band[A_BAND_GRP_NUM]; +#define G_BAND_LOW 0 +#define G_BAND_MID 1 +#define G_BAND_HI 2 + CHAR tx_0_chl_pwr_delta_g_band[3]; + CHAR tx_1_chl_pwr_delta_g_band[3]; +#define A_BAND_LOW 0 +#define A_BAND_HI 1 + CHAR tx_0_chl_pwr_delta_a_band[A_BAND_GRP_NUM][2]; + CHAR tx_1_chl_pwr_delta_a_band[A_BAND_GRP_NUM][2]; + CHAR delta_tx_pwr_bw40_g_band; + CHAR delta_tx_pwr_bw40_a_band; + CHAR delta_tx_pwr_bw80; + + CHAR tx_pwr_cck_1_2; + CHAR tx_pwr_cck_5_11; + CHAR tx_pwr_g_band_ofdm_6_9; + CHAR tx_pwr_g_band_ofdm_12_18; + CHAR tx_pwr_g_band_ofdm_24_36; + CHAR tx_pwr_g_band_ofdm_48_54; + CHAR tx_pwr_ht_mcs_0_1; + CHAR tx_pwr_ht_mcs_2_3; + CHAR tx_pwr_ht_mcs_4_5; + CHAR tx_pwr_ht_mcs_6_7; + CHAR tx_pwr_ht_mcs_8_9; + CHAR tx_pwr_ht_mcs_10_11; + CHAR tx_pwr_ht_mcs_12_13; + CHAR tx_pwr_ht_mcs_14_15; + CHAR tx_pwr_a_band_ofdm_6_9; + CHAR tx_pwr_a_band_ofdm_12_18; + CHAR tx_pwr_a_band_ofdm_24_36; + CHAR tx_pwr_a_band_ofdm_48_54; + CHAR tx_pwr_vht_mcs_0_1; + CHAR tx_pwr_vht_mcs_2_3; + CHAR tx_pwr_vht_mcs_4_5; + CHAR tx_pwr_vht_mcs_6_7; + CHAR tx_pwr_2g_vht_mcs_8_9; + CHAR tx_pwr_5g_vht_mcs_8_9; + + CHAR tx_pwr_cck_1_2_compensate; + CHAR tx_pwr_cck_5_11_compensate; + CHAR tx_pwr_g_band_ofdm_6_9_compensate; + CHAR tx_pwr_g_band_ofdm_12_18_compensate; + CHAR tx_pwr_a_band_ofdm_6_9_compensate; + CHAR tx_pwr_a_band_ofdm_12_18_compensate; + CHAR tx_pwr_g_band_ht_mcs_0_1_compensate; /*cover 8_9*/ + CHAR tx_pwr_g_band_ht_mcs_2_3_compensate; /*cover 10_11*/ + CHAR tx_pwr_a_band_ht_mcs_0_1_compensate; /*cover 8_9*/ + CHAR tx_pwr_a_band_ht_mcs_2_3_compensate; /*cover 10_11*/ + CHAR tx_pwr_5g_vht_mcs_8_9_compensate; + + CHAR rf0_2g_rx_high_gain; + CHAR rf1_2g_rx_high_gain; + CHAR rf0_5g_grp0_rx_high_gain; + CHAR rf1_5g_grp0_rx_high_gain; + CHAR rf0_5g_grp1_rx_high_gain; + CHAR rf1_5g_grp1_rx_high_gain; + CHAR rf0_5g_grp2_rx_high_gain; + CHAR rf1_5g_grp2_rx_high_gain; + CHAR rf0_5g_grp3_rx_high_gain; + CHAR rf1_5g_grp3_rx_high_gain; + CHAR rf0_5g_grp4_rx_high_gain; + CHAR rf1_5g_grp4_rx_high_gain; + CHAR rf0_5g_grp5_rx_high_gain; + CHAR rf1_5g_grp5_rx_high_gain; + BOOLEAN chl_smth_enable; + + MT76x2_RATE_PWR_Table rate_pwr_table; + +#ifdef SINGLE_SKU_V2 + UCHAR tssi_54m_target_pwr_a_band[A_BAND_GRP_NUM]; + UCHAR tssi_54m_target_pwr_g_band; + UCHAR tssi_off_54m_target_pwr_a_band; + UCHAR tssi_off_54m_target_pwr_g_band; +#endif /* SINGLE_SKU_V2 */ +#endif + +}; + +typedef VOID (*CHIP_SPEC_FUNC)(VOID *pAd, VOID *pData, ULONG Data); + +/* The chip specific function ID */ +typedef enum _CHIP_SPEC_ID +{ + CHIP_SPEC_RESV_FUNC +} CHIP_SPEC_ID; + +#define CHIP_SPEC_ID_NUM CHIP_SPEC_RESV_FUNC + + +struct _RTMP_CHIP_OP_ { + int (*sys_onoff)(struct _RTMP_ADAPTER *pAd, BOOLEAN on, BOOLEAN reser); + + /* Calibration access related callback functions */ + int (*eeinit)(struct _RTMP_ADAPTER *pAd); + int (*eeread)(struct _RTMP_ADAPTER *pAd, USHORT offset, PUSHORT pValue); + int (*eewrite)(struct _RTMP_ADAPTER *pAd, USHORT offset, USHORT value); + + /* ITxBf calibration */ + int (*fITxBfDividerCalibration)(struct _RTMP_ADAPTER *pAd, int calFunction, int calMethod, UCHAR *divPhase); + void (*fITxBfLNAPhaseCompensate)(struct _RTMP_ADAPTER *pAd); + int (*fITxBfCal)(struct _RTMP_ADAPTER *pAd, PSTRING arg); + int (*fITxBfLNACalibration)(struct _RTMP_ADAPTER *pAd, int calFunction, int calMethod, BOOLEAN gBand); + + /* MCU related callback functions */ + int (*load_rom_patch)(struct _RTMP_ADAPTER *ad); + int (*erase_rom_patch)(struct _RTMP_ADAPTER *ad); + int (*loadFirmware)(struct _RTMP_ADAPTER *pAd); + int (*eraseFirmware)(struct _RTMP_ADAPTER *pAd); + int (*sendCommandToMcu)(struct _RTMP_ADAPTER *pAd, UCHAR cmd, UCHAR token, UCHAR arg0, UCHAR arg1, BOOLEAN FlgIsNeedLocked); /* int (*sendCommandToMcu)(RTMP_ADAPTER *pAd, UCHAR cmd, UCHAR token, UCHAR arg0, UCHAR arg1); */ +#ifdef CONFIG_ANDES_SUPPORT + int (*sendCommandToAndesMcu)(struct _RTMP_ADAPTER *pAd, UCHAR QueIdx, UCHAR cmd, UCHAR *pData, USHORT DataLen, BOOLEAN FlgIsNeedLocked); +#endif /* CONFIG_ANDES_SUPPORT */ + + void (*AsicRfInit)(struct _RTMP_ADAPTER *pAd); + void (*AsicBbpInit)(struct _RTMP_ADAPTER *pAd); + void (*AsicMacInit)(struct _RTMP_ADAPTER *pAd); + + void (*AsicRfTurnOn)(struct _RTMP_ADAPTER *pAd); + void (*AsicRfTurnOff)(struct _RTMP_ADAPTER *pAd); + void (*AsicReverseRfFromSleepMode)(struct _RTMP_ADAPTER *pAd, BOOLEAN FlgIsInitState); + void (*AsicHaltAction)(struct _RTMP_ADAPTER *pAd); + + /* Power save */ + void (*EnableAPMIMOPS)(struct _RTMP_ADAPTER *pAd, IN BOOLEAN ReduceCorePower); + void (*DisableAPMIMOPS)(struct _RTMP_ADAPTER *pAd); + INT (*PwrSavingOP)(struct _RTMP_ADAPTER *pAd, UINT32 PwrOP, UINT32 PwrLevel, + UINT32 ListenInterval, UINT32 PreTBTTLeadTime, + UINT8 TIMByteOffset, UINT8 TIMBytePattern); + + /* Chip tuning */ + VOID (*RxSensitivityTuning)(IN struct _RTMP_ADAPTER *pAd); + + /* MAC */ + VOID (*BeaconUpdate)(struct _RTMP_ADAPTER *pAd, USHORT Offset, UINT32 Value, UINT8 Unit); + + /* BBP adjust */ + VOID (*ChipBBPAdjust)(IN struct _RTMP_ADAPTER *pAd); + + /* AGC */ + VOID (*ChipAGCInit)(struct _RTMP_ADAPTER *pAd, UCHAR bw); + UCHAR (*ChipAGCAdjust)(struct _RTMP_ADAPTER *pAd, CHAR Rssi, UCHAR OrigR66Value); + + /* Channel */ + VOID (*ChipSwitchChannel)(struct _RTMP_ADAPTER *pAd, UCHAR ch, BOOLEAN bScan); + + /* EDCCA */ + VOID (*ChipSetEDCCA)(struct _RTMP_ADAPTER *pAd, BOOLEAN bOn); + +#ifdef RLT_MAC + /* SkuTxPwrAdj */ + INT32 (*SkuTxPwrAdj)(struct _RTMP_ADAPTER *pAd,struct _TXWI_NMAC *txwi_n); +#endif /*RLT_MAC*/ + +#ifdef RLT_MAC + INT32 (*TxPwrBoost)(struct _RTMP_ADAPTER *pAd,struct _TXWI_NMAC *txwi_n); +#endif /*RLT_MAC*/ + + /* IQ Calibration */ + VOID (*ChipIQCalibration)(struct _RTMP_ADAPTER *pAd, UCHAR Channel); + + UINT32 (*ChipGetCurrentTemp)(struct _RTMP_ADAPTER *pAd); +#ifdef THERMAL_PROTECT_SUPPORT + VOID (*ThermalProDefaultCond)(struct _RTMP_ADAPTER *pAd); + VOID (*ThermalPro1stCond)(struct _RTMP_ADAPTER *pAd); + VOID (*ThermalPro2ndCond)(struct _RTMP_ADAPTER *pAd); +#endif /* THERMAL_PROTECT_SUPPORT */ + + /* TX ALC */ + UINT32 (*TSSIRatio)(INT32 delta_power); + VOID (*InitDesiredTSSITable)(IN struct _RTMP_ADAPTER *pAd); + int (*ATETssiCalibration)(struct _RTMP_ADAPTER *pAd, PSTRING arg); + int (*ATETssiCalibrationExtend)(struct _RTMP_ADAPTER *pAd, PSTRING arg); + int (*ATEReadExternalTSSI)(struct _RTMP_ADAPTER *pAd, PSTRING arg); + + VOID (*AsicTxAlcGetAutoAgcOffset)( + IN struct _RTMP_ADAPTER *pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + + VOID (*AsicGetTxPowerOffset)(struct _RTMP_ADAPTER *pAd, ULONG *TxPwr); + VOID (*AsicExtraPowerOverMAC)(struct _RTMP_ADAPTER *pAd); + + VOID (*AsicAdjustTxPower)(struct _RTMP_ADAPTER *pAd); + + /* Antenna */ + VOID (*AsicAntennaDefaultReset)(struct _RTMP_ADAPTER *pAd, union _EEPROM_ANTENNA_STRUC *pAntenna); + VOID (*SetRxAnt)(struct _RTMP_ADAPTER *pAd, UCHAR Ant); + + /* EEPROM */ + VOID (*NICInitAsicFromEEPROM)(IN struct _RTMP_ADAPTER *pAd); + + /* Temperature Compensation */ + VOID (*InitTemperCompensation)(IN struct _RTMP_ADAPTER *pAd); + VOID (*TemperCompensation)(IN struct _RTMP_ADAPTER *pAd); + + /* high power tuning */ + VOID (*HighPowerTuning)(struct _RTMP_ADAPTER *pAd, struct _RSSI_SAMPLE *pRssi); + + /* Others */ + VOID (*NetDevNickNameInit)(IN struct _RTMP_ADAPTER *pAd); +#ifdef CAL_FREE_IC_SUPPORT + BOOLEAN (*is_cal_free_ic)(IN struct _RTMP_ADAPTER *pAd); + VOID (*cal_free_data_get)(IN struct _RTMP_ADAPTER *pAd); +#endif /* CAL_FREE_IC_SUPPORT */ + + /* The chip specific function list */ + CHIP_SPEC_FUNC ChipSpecFunc[CHIP_SPEC_ID_NUM]; + + VOID (*AsicResetBbpAgent)(IN struct _RTMP_ADAPTER *pAd); + +#ifdef CARRIER_DETECTION_SUPPORT + VOID (*ToneRadarProgram)(struct _RTMP_ADAPTER *pAd, ULONG threshold); +#endif /* CARRIER_DETECTION_SUPPORT */ + VOID (*CckMrcStatusCtrl)(struct _RTMP_ADAPTER *pAd); + VOID (*RadarGLRTCompensate)(struct _RTMP_ADAPTER *pAd); + VOID (*SecondCCADetection)(struct _RTMP_ADAPTER *pAd); + + /* MCU */ + void (*MCUCtrlInit)(struct _RTMP_ADAPTER *ad); + void (*MCUCtrlExit)(struct _RTMP_ADAPTER *ad); +#ifdef CONFIG_ANDES_SUPPORT + void (*fw_init)(struct _RTMP_ADAPTER *ad); + int (*BurstWrite)(struct _RTMP_ADAPTER *ad, UINT32 Offset, UINT32 *Data, UINT32 Cnt); + int (*BurstRead)(struct _RTMP_ADAPTER *ad, UINT32 Offset, UINT32 Cnt, UINT32 *Data); + int (*RandomRead)(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *RegPair, UINT32 Num); + int (*RFRandomRead)(struct _RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *RegPair, UINT32 Num); + int (*ReadModifyWrite)(struct _RTMP_ADAPTER *ad, R_M_W_REG *RegPair, UINT32 Num); + int (*RFReadModifyWrite)(struct _RTMP_ADAPTER *ad, RF_R_M_W_REG *RegPair, UINT32 Num); + int (*RandomWrite)(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *RegPair, UINT32 Num); + int (*RFRandomWrite)(struct _RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *RegPair, UINT32 Num); + int (*sc_random_write)(struct _RTMP_ADAPTER *ad, CR_REG *table, u32 num, u32 flags); + int (*sc_rf_random_write)(struct _RTMP_ADAPTER *ad, BANK_RF_CR_REG *table, u32 num, u32 flags); + int (*Calibration)(struct _RTMP_ADAPTER *pAd, UINT32 CalibrationID, ANDES_CALIBRATION_PARAM *param); +#endif /* CONFIG_ANDES_SUPPORT */ + void (*DisableTxRx)(struct _RTMP_ADAPTER *ad, UCHAR Level); + BOOLEAN (*AsicRadioOn)(struct _RTMP_ADAPTER *ad, UCHAR Level); + BOOLEAN (*AsicRadioOff)(struct _RTMP_ADAPTER *ad, UCHAR Level, USHORT TbttNumToNextWakeUp); + +#ifdef MICROWAVE_OVEN_SUPPORT + VOID (*AsicMeasureFalseCCA)(IN struct _RTMP_ADAPTER *pAd); + + VOID (*AsicMitigateMicrowave)(IN struct _RTMP_ADAPTER *pAd); +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + VOID (*AsicDynamicVgaGainControl)(IN struct _RTMP_ADAPTER *pAd); + VOID (*UpdateRssiForDynamicVga)(IN struct _RTMP_ADAPTER *pAd); +#endif /* DYNAMIC_VGA_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + VOID (*AsicWOWEnable)(struct _RTMP_ADAPTER *ad); + VOID (*AsicWOWDisable)(struct _RTMP_ADAPTER *ad); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + + void (*usb_cfg_read)(struct _RTMP_ADAPTER *ad, u32 *value); + void (*usb_cfg_write)(struct _RTMP_ADAPTER *ad, u32 value); + void (*show_pwr_info)(struct _RTMP_ADAPTER *ad); + void (*cal_test)(struct _RTMP_ADAPTER *ad, UINT32 type); +}; + +#define RTMP_CHIP_ENABLE_AP_MIMOPS(__pAd, __ReduceCorePower) \ +do { \ + if (__pAd->chipOps.EnableAPMIMOPS != NULL) \ + __pAd->chipOps.EnableAPMIMOPS(__pAd, __ReduceCorePower); \ +} while (0) + +#define RTMP_CHIP_DISABLE_AP_MIMOPS(__pAd) \ +do { \ + if (__pAd->chipOps.DisableAPMIMOPS != NULL) \ + __pAd->chipOps.DisableAPMIMOPS(__pAd); \ +} while (0) + +#define PWR_SAVING_OP(__pAd, __PwrOP, __PwrLevel, __ListenInterval, \ + __PreTBTTLeadTime, __TIMByteOffset, __TIMBytePattern) \ +do { \ + if (__pAd->chipOps.PwrSavingOP != NULL) \ + __pAd->chipOps.PwrSavingOP(__pAd, __PwrOP, __PwrLevel, \ + __ListenInterval,__PreTBTTLeadTime, \ + __TIMByteOffset, __TIMBytePattern); \ +} while (0) + +#define RTMP_CHIP_RX_SENSITIVITY_TUNING(__pAd) \ +do { \ + if (__pAd->chipOps.RxSensitivityTuning != NULL) \ + __pAd->chipOps.RxSensitivityTuning(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_AGC_ADJUST(__pAd, __Rssi, __R66) \ +do { \ + if (__pAd->chipOps.ChipAGCAdjust != NULL) \ + __R66 = __pAd->chipOps.ChipAGCAdjust(__pAd, __Rssi, __R66); \ +} while (0) + +#define RTMP_CHIP_ASIC_TSSI_TABLE_INIT(__pAd) \ +do { \ + if (__pAd->chipOps.InitDesiredTSSITable != NULL) \ + __pAd->chipOps.InitDesiredTSSITable(__pAd); \ +} while (0) + +#define RTMP_CHIP_ATE_TSSI_CALIBRATION(__pAd, __pData) \ +do { \ + if (__pAd->chipOps.ATETssiCalibration != NULL) \ + __pAd->chipOps.ATETssiCalibration(__pAd, __pData); \ +} while (0) + +#define RTMP_CHIP_ATE_TSSI_CALIBRATION_EXTEND(__pAd, __pData) \ +do { \ + if (__pAd->chipOps.ATETssiCalibrationExtend != NULL) \ + __pAd->chipOps.ATETssiCalibrationExtend(__pAd, __pData); \ +} while (0) + +#define RTMP_CHIP_ATE_READ_EXTERNAL_TSSI(__pAd, __pData) \ +do { \ + if (__pAd->chipOps.ATEReadExternalTSSI != NULL) \ + __pAd->chipOps.ATEReadExternalTSSI(__pAd, __pData); \ +} while (0) + +#define RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(__pAd, __pCfgOfTxPwrCtrlOverMAC) \ +do { \ + if (__pAd->chipOps.AsicGetTxPowerOffset != NULL) \ + __pAd->chipOps.AsicGetTxPowerOffset(__pAd, __pCfgOfTxPwrCtrlOverMAC); \ +} while (0) + +#define RTMP_CHIP_ASIC_AUTO_AGC_OFFSET_GET( \ + __pAd, __pDeltaPwr, __pTotalDeltaPwr, __pAgcCompensate, __pDeltaPowerByBbpR1) \ +do { \ + if (__pAd->chipOps.AsicTxAlcGetAutoAgcOffset != NULL) \ + __pAd->chipOps.AsicTxAlcGetAutoAgcOffset( \ + __pAd, __pDeltaPwr, __pTotalDeltaPwr, __pAgcCompensate, __pDeltaPowerByBbpR1); \ +} while (0) + +#define RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(__pAd) \ +do { \ + if (__pAd->chipOps.AsicExtraPowerOverMAC != NULL) \ + __pAd->chipOps.AsicExtraPowerOverMAC(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_GET_TSSI_RATIO(__pAd, __DeltaPwr) \ +do { \ + if (__pAd->chipOps.AsicFreqCalStop != NULL) \ + __pAd->chipOps.TSSIRatio(__DeltaPwr); \ +} while (0) + +#define RTMP_CHIP_GET_CURRENT_TEMP(__pAd, __pCurrentTemp) \ +do { \ + if (__pAd->chipOps.ChipGetCurrentTemp != NULL) \ + __pCurrentTemp = __pAd->chipOps.ChipGetCurrentTemp(__pAd); \ +} while (0) + +#ifdef THERMAL_PROTECT_SUPPORT +#define RTMP_CHIP_THERMAL_PRO_DEFAULT_COND(__pAd) \ +do { \ + if (__pAd->chipOps.ThermalProDefaultCond != NULL) \ + __pAd->chipOps.ThermalProDefaultCond(__pAd); \ +} while (0) + +#define RTMP_CHIP_THERMAL_PRO_1st_COND(__pAd) \ +do { \ + if (__pAd->chipOps.ThermalPro1stCond != NULL) \ + __pAd->chipOps.ThermalPro1stCond(__pAd); \ +} while (0) + +#define RTMP_CHIP_THERMAL_PRO_2nd_COND(__pAd) \ +do { \ + if (__pAd->chipOps.ThermalPro2ndCond != NULL) \ + __pAd->chipOps.ThermalPro2ndCond(__pAd); \ +} while (0) +#endif /* THERMAL_PROTECT_SUPPORT */ + +#define RTMP_CHIP_ASIC_FREQ_CAL_STOP(__pAd) \ +do { \ + if (__pAd->chipOps.AsicFreqCalStop != NULL) \ + __pAd->chipOps.AsicFreqCalStop(__pAd); \ +} while (0) + +#define RTMP_CHIP_IQ_CAL(__pAd, __pChannel) \ +do { \ + if (__pAd->chipOps.ChipIQCalibration != NULL) \ + __pAd->chipOps.ChipIQCalibration(__pAd, __pChannel); \ +} while (0) + +#define RTMP_CHIP_HIGH_POWER_TUNING(__pAd, __pRssi) \ +do { \ + if (__pAd->chipOps.HighPowerTuning != NULL) \ + __pAd->chipOps.HighPowerTuning(__pAd, __pRssi); \ +} while (0) + +#define RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(__pAd, __pAntenna) \ +do { \ + if (__pAd->chipOps.AsicAntennaDefaultReset != NULL) \ + __pAd->chipOps.AsicAntennaDefaultReset(__pAd, __pAntenna); \ +} while (0) + +#define RTMP_NET_DEV_NICKNAME_INIT(__pAd) \ +do { \ + if (__pAd->chipOps.NetDevNickNameInit != NULL) \ + __pAd->chipOps.NetDevNickNameInit(__pAd); \ +} while (0) + +#ifdef CAL_FREE_IC_SUPPORT +#define RTMP_CAL_FREE_IC_CHECK(__pAd, __is_cal_free) \ +do { \ + if (__pAd->chipOps.is_cal_free_ic != NULL) \ + __is_cal_free = __pAd->chipOps.is_cal_free_ic(__pAd); \ + else \ + __is_cal_free = FALSE; \ +} while (0) + +#define RTMP_CAL_FREE_DATA_GET(__pAd) \ +do { \ + if (__pAd->chipOps.cal_free_data_get != NULL) \ + __pAd->chipOps.cal_free_data_get(__pAd); \ +} while (0) +#endif /* CAL_FREE_IC_SUPPORT */ + +#define RTMP_EEPROM_ASIC_INIT(__pAd) \ +do { \ + if (__pAd->chipOps.NICInitAsicFromEEPROM != NULL) \ + __pAd->chipOps.NICInitAsicFromEEPROM(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_INIT_TEMPERATURE_COMPENSATION(__pAd) \ +do { \ + if (__pAd->chipOps.InitTemperCompensation != NULL) \ + __pAd->chipOps.InitTemperCompensation(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_SET_EDCCA(__pAd, __bOn) \ +do { \ + if (__pAd->chipOps.ChipSetEDCCA != NULL) \ + __pAd->chipOps.ChipSetEDCCA(__pAd, __bOn); \ +} while (0) + +#define RTMP_CHIP_ASIC_SKU_TX_POWER_ADJUST(__pAd, __pTxWI) \ +do { \ + if (__pAd->chipOps.SkuTxPwrAdj != NULL) \ + __pTxWI->TxPwrAdj += __pAd->chipOps.SkuTxPwrAdj(__pAd, __pTxWI); \ +} while (0) + +#define RTMP_CHIP_ASIC_TX_POWER_BOOST(__pAd, __pTxWI) \ +do { \ + if (__pAd->chipOps.TxPwrBoost != NULL) \ + __pTxWI->TxPwrAdj += __pAd->chipOps.TxPwrBoost(__pAd, __pTxWI); \ +} while (0) + + +#define RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(__pAd) \ +do { \ + if (__pAd->chipOps.TemperCompensation != NULL) \ + __pAd->chipOps.TemperCompensation(__pAd); \ +} while (0) + +#define RTMP_CHIP_SPECIFIC(__pAd, __FuncId, __pData, __Data) \ +do { \ + if ((__FuncId >= 0) && (__FuncId < CHIP_SPEC_RESV_FUNC)) \ + { \ + if (__pAd->chipOps.ChipSpecFunc[__FuncId] != NULL) \ + __pAd->chipOps.ChipSpecFunc[__FuncId](__pAd, __pData, __Data); \ + } \ +} while (0) + +#define RTMP_CHIP_UPDATE_BEACON(__pAd, Offset, Value, Unit) \ +do { \ + if (__pAd->chipOps.BeaconUpdate != NULL) \ + __pAd->chipOps.BeaconUpdate(__pAd, Offset, Value, Unit); \ +} while (0) + +#ifdef CARRIER_DETECTION_SUPPORT +#define RTMP_CHIP_CARRIER_PROGRAM(__pAd, threshold) \ +do { \ + if(__pAd->chipOps.ToneRadarProgram != NULL) \ + __pAd->chipOps.ToneRadarProgram(__pAd, threshold); \ +} while (0) +#endif /* CARRIER_DETECTION_SUPPORT */ + +#define RTMP_CHIP_CCK_MRC_STATUS_CTRL(__pAd) \ +do { \ + if(__pAd->chipOps.CckMrcStatusCtrl != NULL) \ + __pAd->chipOps.CckMrcStatusCtrl(__pAd); \ +} while (0) + +#define RTMP_CHIP_RADAR_GLRT_COMPENSATE(__pAd) \ +do { \ + if(__pAd->chipOps.RadarGLRTCompensate != NULL) \ + __pAd->chipOps.RadarGLRTCompensate(__pAd); \ +} while (0) + + +#define CHIP_CALIBRATION(__pAd, __CalibrationID, param) \ +do { \ + ANDES_CALIBRATION_PARAM calibration_param; \ + calibration_param.generic = param; \ + if(__pAd->chipOps.Calibration != NULL) \ + __pAd->chipOps.Calibration(__pAd, __CalibrationID, &calibration_param); \ +} while (0) + +#define BURST_WRITE(_pAd, _Offset, _pData, _Cnt) \ +do { \ + if (_pAd->chipOps.BurstWrite != NULL) \ + _pAd->chipOps.BurstWrite(_pAd, _Offset, _pData, _Cnt);\ +} while (0) + +#define BURST_READ(_pAd, _Offset, _Cnt, _pData) \ +do { \ + if (_pAd->chipOps.BurstRead != NULL) \ + _pAd->chipOps.BurstRead(_pAd, _Offset, _Cnt, _pData); \ +} while (0) + +#define RANDOM_READ(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RandomRead != NULL) \ + _pAd->chipOps.RandomRead(_pAd, _RegPair, _Num); \ +} while (0) + +#define RF_RANDOM_READ(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RFRandomRead != NULL) \ + _pAd->chipOps.RFRandomRead(_pAd, _RegPair, _Num); \ +} while (0) + +#define READ_MODIFY_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.ReadModifyWrite != NULL) \ + _pAd->chipOps.ReadModifyWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RF_READ_MODIFY_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RFReadModifyWrite != NULL) \ + _pAd->chipOps.RFReadModifyWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RANDOM_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RandomWrite != NULL) \ + _pAd->chipOps.RandomWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RF_RANDOM_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RFRandomWrite != NULL) \ + _pAd->chipOps.RFRandomWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RTMP_SECOND_CCA_DETECTION(__pAd) \ +do { \ + if (__pAd->chipOps.SecondCCADetection != NULL) \ + { \ + __pAd->chipOps.SecondCCADetection(__pAd); \ + } \ +} while (0) + +#define SC_RANDOM_WRITE(_ad, _table, _num, _flags) \ +do { \ + if (_ad->chipOps.sc_random_write != NULL) \ + _ad->chipOps.sc_random_write(_ad, _table, _num, _flags); \ +} while (0) + +#define SC_RF_RANDOM_WRITE(_ad, _table, _num, _flags) \ +do { \ + if (_ad->chipOps.sc_rf_random_write != NULL) \ + _ad->chipOps.sc_rf_random_write(_ad, _table, _num, _flags); \ +} while (0) + +#define DISABLE_TX_RX(_pAd, _Level) \ +do { \ + if (_pAd->chipOps.DisableTxRx != NULL) \ + _pAd->chipOps.DisableTxRx(_pAd, _Level); \ +} while (0) + +#define ASIC_RADIO_ON(_pAd, _Stage) \ +do { \ + if (_pAd->chipOps.AsicRadioOn != NULL) \ + _pAd->chipOps.AsicRadioOn(_pAd, _Stage); \ +} while (0) + +#define ASIC_RADIO_OFF(_pAd, _Stage) \ +do { \ + if (_pAd->chipOps.AsicRadioOff != NULL) \ + _pAd->chipOps.AsicRadioOff(_pAd, _Stage, 0); \ +} while (0) + +#ifdef MICROWAVE_OVEN_SUPPORT +#define ASIC_MEASURE_FALSE_CCA(_pAd) \ +do { \ + if (_pAd->chipOps.AsicMeasureFalseCCA != NULL) \ + _pAd->chipOps.AsicMeasureFalseCCA(_pAd); \ +} while (0) + +#define ASIC_MITIGATE_MICROWAVE(_pAd) \ +do { \ + if (_pAd->chipOps.AsicMitigateMicrowave != NULL) \ + _pAd->chipOps.AsicMitigateMicrowave(_pAd); \ +} while (0) +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +#define ASIC_WOW_ENABLE(_pAd) \ +do { \ + if (_pAd->chipOps.AsicWOWEnable != NULL) \ + _pAd->chipOps.AsicWOWEnable(_pAd); \ +} while (0) + +#define ASIC_WOW_DISABLE(_pAd) \ +do { \ + if (_pAd->chipOps.AsicWOWDisable != NULL) \ + _pAd->chipOps.AsicWOWDisable(_pAd); \ +} while(0) +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +#define MCU_CTRL_INIT(_pAd) \ +do { \ + if (_pAd->chipOps.MCUCtrlInit != NULL) \ + _pAd->chipOps.MCUCtrlInit(_pAd); \ +} while (0) + +#define MCU_CTRL_EXIT(_pAd) \ +do { \ + if (_pAd->chipOps.MCUCtrlExit != NULL) \ + _pAd->chipOps.MCUCtrlExit(_pAd); \ +} while (0) + +#define USB_CFG_READ(_ad, _pvalue) \ +do { \ + if (_ad->chipOps.usb_cfg_read != NULL) \ + _ad->chipOps.usb_cfg_read(_ad, _pvalue); \ + else {\ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): usb_cfg_read not inited!\n", __FUNCTION__));\ + }\ +} while (0) + +#define USB_CFG_WRITE(_ad, _value) \ +do { \ + if (_ad->chipOps.usb_cfg_write != NULL) \ + _ad->chipOps.usb_cfg_write(_ad, _value); \ + else {\ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): usb_cfg_write not inited!\n", __FUNCTION__));\ + }\ +} while (0) + +#ifdef DYNAMIC_VGA_SUPPORT +#define RTMP_ASIC_DYNAMIC_VGA_GAIN_CONTROL(_pAd) \ + do { \ + if (_pAd->chipOps.AsicDynamicVgaGainControl != NULL) \ + _pAd->chipOps.AsicDynamicVgaGainControl(_pAd); \ + } while (0) + +#define RTMP_UPDATE_RSSI_FOR_DYNAMIC_VGA(_pAd) \ + do { \ + if (_pAd->chipOps.UpdateRssiForDynamicVga != NULL) \ + _pAd->chipOps.UpdateRssiForDynamicVga(_pAd); \ + } while (0) + +#endif /* DYNAMIC_VGA_SUPPORT */ + +int RtmpChipOpsHook(VOID *pCB); +VOID RtmpChipBcnInit(struct _RTMP_ADAPTER *pAd); +VOID RtmpChipBcnSpecInit(struct _RTMP_ADAPTER *pAd); +#ifdef RLT_MAC +VOID rlt_bcn_buf_init(struct _RTMP_ADAPTER *pAd); +#endif /* RLT_MAC */ + +VOID RtmpChipWriteHighMemory( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UINT32 Value, + IN UINT8 Unit); + +VOID RtmpChipWriteMemory( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UINT32 Value, + IN UINT8 Unit); + +VOID RTMPReadChannelPwr(struct _RTMP_ADAPTER *pAd); +VOID RTMPReadTxPwrPerRate(struct _RTMP_ADAPTER *pAd); +#ifdef RTMP_TEMPERATURE_COMPENSATION +BOOLEAN LoadTempCompTableFromEEPROM( + IN struct _RTMP_ADAPTER *pAd, + IN const USHORT E2P_OFFSET_START, + IN const USHORT E2P_OFFSET_END, + OUT PUCHAR TssiTable, + IN const INT StartIndex, + IN const UINT32 TABLE_SIZE); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + +VOID NetDevNickNameInit(IN struct _RTMP_ADAPTER *pAd); + + + +#ifdef GREENAP_SUPPORT +VOID EnableAPMIMOPSv2(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); +VOID DisableAPMIMOPSv2(struct _RTMP_ADAPTER *pAd); +VOID EnableAPMIMOPSv1(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); +VOID DisableAPMIMOPSv1(struct _RTMP_ADAPTER *pAd); +#endif /* GREENAP_SUPPORT */ + +#ifdef RTMP_MAC +VOID RTxx_default_Init(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_MAC */ + +/* global variable */ +extern FREQUENCY_ITEM RtmpFreqItems3020[]; +extern FREQUENCY_ITEM FreqItems3020_Xtal20M[]; +extern UCHAR NUM_OF_3020_CHNL; +extern FREQUENCY_ITEM *FreqItems3020; +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + +BOOLEAN AsicWaitPDMAIdle(struct _RTMP_ADAPTER *pAd, INT round, INT wait_us); +INT AsicSetPreTbttInt(struct _RTMP_ADAPTER *pAd, BOOLEAN enable); +INT AsicReadAggCnt(struct _RTMP_ADAPTER *pAd, ULONG *aggCnt, int cnt_len); + +INT rtmp_asic_top_init(struct _RTMP_ADAPTER *pAd); + +INT StopDmaTx(struct _RTMP_ADAPTER *pAd, UCHAR Level); +INT StopDmaRx(struct _RTMP_ADAPTER *pAd, UCHAR Level); + +#ifdef RT65xx +BOOLEAN isExternalPAMode(struct _RTMP_ADAPTER *ad, INT channel); +BOOLEAN is_external_lna_mode(struct _RTMP_ADAPTER *ad, INT channel); +#endif /* RT65xx */ +#endif /* __RTMP_CHIP_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_cmd.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_cmd.h new file mode 100644 index 000000000..fb08512f1 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_cmd.h @@ -0,0 +1,922 @@ +#ifndef __RTMP_CMD_H__ +#define __RTMP_CMD_H__ + +#include "rtmp_type.h" + +typedef struct _CmdQElmt { + UINT command; + PVOID buffer; + ULONG bufferlength; + BOOLEAN CmdFromNdis; + BOOLEAN SetOperation; + struct _CmdQElmt *next; +} CmdQElmt, *PCmdQElmt; + +typedef struct _CmdQ { + UINT size; + CmdQElmt *head; + CmdQElmt *tail; + UINT32 CmdQState; +} CmdQ, *PCmdQ; + +#define EnqueueCmd(cmdq, cmdqelmt) \ +{ \ + if (cmdq->size == 0) \ + cmdq->head = cmdqelmt; \ + else \ + cmdq->tail->next = cmdqelmt; \ + cmdq->tail = cmdqelmt; \ + cmdqelmt->next = NULL; \ + cmdq->size++; \ +} + +#define NDIS_OID UINT + +/* OS_RTCMDUp is only used in UTIL/NETIF module */ +#define OS_RTCMDUp RtmpOsCmdUp + + +#if defined(RTMP_MAC_PCI) || defined(RTMP_RBUS_SUPPORT) +#define CMDTHREAD_CHAN_RESCAN 0x0D730101 +#define CMDTHREAD_REG_HINT 0x0D730102 +#define CMDTHREAD_REG_HINT_11D 0x0D730103 +#define CMDTHREAD_SCAN_END 0x0D730104 +#define CMDTHREAD_CONNECT_RESULT_INFORM 0x0D730105 +#endif /* RTMP_MAC_PCI || RTMP_RBUS_SUPPORT */ + +#define CMDTHREAD_RESPONSE_EVENT_CALLBACK 0x0D730123 + +/* RALINK command status code */ +#define RTMP_IO_EINVAL 30000 +#define RTMP_IO_EOPNOTSUPP 30001 +#define RTMP_IO_EFAULT 30002 +#define RTMP_IO_ENETDOWN 30003 +#define RTMP_IO_E2BIG 30004 +#define RTMP_IO_ENOMEM 30005 +#define RTMP_IO_EAGAIN 30006 +#define RTMP_IO_ENOTCONN 30007 + +enum { +#ifdef MAT_SUPPORT + SHOW_IPV4_MAT_INFO = 1, + SHOW_IPV6_MAT_INFO = 2, + SHOW_ETH_CLONE_MAC = 3, +#endif /* MAT_SUPPORT */ + SHOW_CONN_STATUS = 4, + SHOW_DRVIER_VERION = 5, + SHOW_BA_INFO = 6, + SHOW_DESC_INFO = 7, + RAIO_OFF = 10, + RAIO_ON = 11, +#ifdef QOS_DLS_SUPPORT + SHOW_DLS_ENTRY_INFO = 20, +#endif /* QOS_DLS_SUPPORT */ + SHOW_CFG_VALUE = 21, + SHOW_ADHOC_ENTRY_INFO = 22, +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + SHOW_TDLS_ENTRY_INFO = 25, +#endif /* DOT11Z_TDLS_SUPPORT */ + SHOW_DEV_INFO = 26, + SHOW_STA_INFO = 27, + SHOW_TR_INFO = 28, + SHOW_SYS_INFO = 29, + SHOW_PWR_INFO = 30, + SHOW_DIAGNOSE_INFO = 31, +}; + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT +enum { + WSC_CREDENTIAL_COUNT = 1, + WSC_CREDENTIAL_SSID = 2, + WSC_CREDENTIAL_AUTH_MODE = 3, + WSC_CREDENTIAL_ENCR_TYPE = 4, + WSC_CREDENTIAL_KEY_INDEX = 5, + WSC_CREDENTIAL_KEY = 6, + WSC_CREDENTIAL_MAC = 7, + WSC_SET_DRIVER_CONNECT_BY_CREDENTIAL_IDX = 8, + WSC_SET_DRIVER_AUTO_CONNECT = 9, + WSC_SET_CONF_MODE = 10, /* Enrollee or Registrar */ + WSC_SET_MODE = 11, /* PIN or PBC */ + WSC_SET_PIN = 12, + WSC_SET_SSID = 13, + WSC_START = 14, + WSC_STOP = 15, + WSC_GEN_PIN_CODE = 16, + WSC_AP_BAND = 17, + WSC_SET_BSSID = 18, +}; +#endif /* WSC_STA_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +#define RT_ASSOC_EVENT_FLAG 0x0101 +#define RT_DISASSOC_EVENT_FLAG 0x0102 +#define RT_REQIE_EVENT_FLAG 0x0103 +#define RT_RESPIE_EVENT_FLAG 0x0104 +#define RT_ASSOCINFO_EVENT_FLAG 0x0105 +#define RT_PMKIDCAND_FLAG 0x0106 +#define RT_INTERFACE_DOWN 0x0107 +#define RT_INTERFACE_UP 0x0108 +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +/* RALINK command handle ID */ +/* ap commands */ +typedef enum _CMD_RTPRIV_IOCTL_AP { + + /* general */ + CMD_RTPRIV_IOCTL_SET_WSCOOB = 0x0001, + CMD_RTPRIV_IOCTL_GET_MAC_TABLE, + CMD_RTPRIV_IOCTL_GSITESURVEY, + CMD_RTPRIV_IOCTL_STATISTICS, + CMD_RTPRIV_IOCTL_QUERY_BATABLE, + CMD_RTPRIV_IOCTL_E2P, + CMD_RTPRIV_IOCTL_BBP, + CMD_RTPRIV_IOCTL_MAC, + CMD_RTPRIV_IOCTL_RF, + CMD_RT_PRIV_IOCTL, + CMD_RTPRIV_IOCTL_SET, + CMD_RTPRIV_IOCTL_SHOW, + CMD_RTPRIV_IOCTL_GET_AR9_SHOW, + CMD_RTPRIV_IOCTL_ATE, + CMD_RTPRIV_IOCTL_CHID_2_FREQ, + CMD_RTPRIV_IOCTL_FREQ_2_CHID, + CMD_RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT, + + /* mbss */ + CMD_RTPRIV_IOCTL_MBSS_BEACON_UPDATE, + CMD_RTPRIV_IOCTL_MBSS_OPEN, + CMD_RTPRIV_IOCTL_MBSS_CLOSE, + CMD_RTPRIV_IOCTL_MBSS_INIT, + CMD_RTPRIV_IOCTL_MBSS_REMOVE, + + /* wsc */ + CMD_RTPRIV_IOCTL_WSC_PROFILE, + CMD_RTPRIV_IOCTL_WSC_INIT, + + /* apc */ + CMD_RTPRIV_IOCTL_APC_UP, + CMD_RTPRIV_IOCTL_APC_DISCONNECT, + CMD_RTPRIV_IOCTL_APC_INIT, + CMD_RTPRIV_IOCTL_APC_OPEN, + CMD_RTPRIV_IOCTL_APC_CLOSE, + CMD_RTPRIV_IOCTL_APC_REMOVE, + + /* interface */ + CMD_RTPRIV_IOCTL_MAIN_OPEN, + + /* ioctl */ + CMD_RTPRIV_IOCTL_PREPARE, + CMD_RTPRIV_IOCTL_AP_SIOCGIWAP, + CMD_RTPRIV_IOCTL_AP_SIOCGIFHWADDR, + CMD_RTPRIV_IOCTL_AP_SIOCGIWESSID, + CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ, + CMD_RTPRIV_IOCTL_AP_SIOCSIWGENIE, + + /* can not exceed 0x5000 */ +} CMD_RTPRIV_IOCTL_AP; + +/* common commands */ +typedef enum _CMD_RTPRIV_IOCTL_COMMON { + + /* general */ + CMD_RTPRIV_IOCTL_NETDEV_GET = 0x5000, + CMD_RTPRIV_IOCTL_NETDEV_SET, + CMD_RTPRIV_IOCTL_OPMODE_GET, + CMD_RTPRIV_IOCTL_TASK_LIST_GET, + CMD_RTPRIV_IOCTL_IRQ_INIT, + CMD_RTPRIV_IOCTL_IRQ_RELEASE, + CMD_RTPRIV_IOCTL_MSI_ENABLE, + CMD_RTPRIV_IOCTL_NIC_NOT_EXIST, + CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR, +#ifdef CONFIG_STA_SUPPORT + CMD_RTPRIV_IOCTL_USB_DEV_GET, + CMD_RTPRIV_IOCTL_USB_INTF_GET, + CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET, + CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR, + CMD_RTPRIV_IOCTL_ADAPTER_SEND_DISSASSOCIATE, + CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_TEST, + CMD_RTPRIV_IOCTL_ADAPTER_IDLE_RADIO_OFF_TEST, + CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_OFF, + CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON, + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_STATUS, + CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_ENABLE, + CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_WOW_DISABLE, +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + + CMD_RTPRIV_IOCTL_AP_BSSID_GET, +#endif /* CONFIG_STA_SUPPORT */ + CMD_RTPRIV_IOCTL_SANITY_CHECK, + CMD_RTPRIV_IOCTL_SANITY_CHECK_ON_SET_CMD, +#ifdef EXT_BUILD_CHANNEL_LIST + CMD_RTPRIV_SET_PRECONFIG_VALUE, +#endif /* EXT_BUILD_CHANNEL_LIST */ + + /* sniffer */ + CMD_RTPRIV_IOCTL_SNIFF_UP, + CMD_RTPRIV_IOCTL_SNIFF_DISCONNECT, + CMD_RTPRIV_IOCTL_SNIFF_INIT, + CMD_RTPRIV_IOCTL_SNIFF_OPEN, + CMD_RTPRIV_IOCTL_SNIFF_CLOSE, + CMD_RTPRIV_IOCTL_SNIFF_REMOVE, + + /* mesh */ + CMD_RTPRIV_IOCTL_MESH_INIT, + CMD_RTPRIV_IOCTL_MESH_REMOVE, + CMD_RTPRIV_IOCTL_MESH_OPEN_PRE, + CMD_RTPRIV_IOCTL_MESH_OPEN_POST, + CMD_RTPRIV_IOCTL_MESH_IS_VALID, + CMD_RTPRIV_IOCTL_MESH_CLOSE, + + /* p2p */ + CMD_RTPRIV_IOCTL_P2P_INIT, + CMD_RTPRIV_IOCTL_P2P_REMOVE, + CMD_RTPRIV_IOCTL_P2P_OPEN_PRE, + CMD_RTPRIV_IOCTL_P2P_OPEN_POST, + CMD_RTPRIV_IOCTL_P2P_IS_VALID, + CMD_RTPRIV_IOCTL_P2P_CLOSE, + + /* usb */ + CMD_RTPRIV_IOCTL_USB_MORE_FLAG_SET, + CMD_RTPRIV_IOCTL_USB_CONFIG_INIT, + CMD_RTPRIV_IOCTL_USB_SUSPEND, + CMD_RTPRIV_IOCTL_USB_RESUME, + CMD_RTPRIV_IOCTL_USB_INIT, + + /* pci */ + CMD_RTPRIV_IOCTL_PCI_SUSPEND, + CMD_RTPRIV_IOCTL_PCI_RESUME, + CMD_RTPRIV_IOCTL_PCI_CSR_SET, + CMD_RTPRIV_IOCTL_PCIE_INIT, + + /* cfg80211 */ + CMD_RTPRIV_IOCTL_CFG80211_CFG_START, + + /* inf ppa */ + CMD_RTPRIV_IOCTL_INF_PPA_INIT, + CMD_RTPRIV_IOCTL_INF_PPA_EXIT, + + /* wireless */ + CMD_RTPRIV_IOCTL_BEACON_UPDATE, + CMD_RTPRIV_IOCTL_RXPATH_GET, + CMD_RTPRIV_IOCTL_CHAN_LIST_NUM_GET, + CMD_RTPRIV_IOCTL_CHAN_LIST_GET, + CMD_RTPRIV_IOCTL_FREQ_LIST_GET, + + /* interface */ + CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP, + CMD_RTPRIV_IOCTL_VIRTUAL_INF_DOWN, + CMD_RTPRIV_IOCTL_VIRTUAL_INF_GET, + CMD_RTPRIV_IOCTL_INF_TYPE_GET, + CMD_RTPRIV_IOCTL_INF_STATS_GET, + CMD_RTPRIV_IOCTL_INF_IW_STATUS_GET, + CMD_RTPRIV_IOCTL_INF_MAIN_CREATE, + CMD_RTPRIV_IOCTL_INF_MAIN_ID_GET, + CMD_RTPRIV_IOCTL_INF_MAIN_CHECK, + CMD_RTPRIV_IOCTL_INF_P2P_CHECK, + + /* ioctl */ + CMD_RTPRIV_IOCTL_SIOCGIWFREQ, + CMD_RTPRIV_IOCTL_SIOCGIWNAME, + + /* wds */ + CMD_RTPRIV_IOCTL_WDS_INIT, + CMD_RTPRIV_IOCTL_WDS_REMOVE, + CMD_RTPRIV_IOCTL_WDS_STATS_GET, + + /* apcli */ + CMD_RTPRIV_IOCTL_APCLI_STATS_GET, + + CMD_RTPRIV_IOCTL_MAC_ADDR_GET, + +#ifdef RT_CFG80211_SUPPORT + /* cfg802.11 */ + /* Note: All cfg commands must be continue. */ + CMD_RTPRIV_IOCTL_80211_START, + CMD_RTPRIV_IOCTL_80211_CB_GET, + CMD_RTPRIV_IOCTL_80211_CB_SET, + CMD_RTPRIV_IOCTL_80211_CHAN_SET, + CMD_RTPRIV_IOCTL_80211_VIF_CHG, + CMD_RTPRIV_IOCTL_80211_SCAN, + CMD_RTPRIV_IOCTL_80211_IBSS_JOIN, + CMD_RTPRIV_IOCTL_80211_STA_LEAVE, + CMD_RTPRIV_IOCTL_80211_STA_GET, + CMD_RTPRIV_IOCTL_80211_STA_KEY_ADD, + CMD_RTPRIV_IOCTL_80211_STA_KEY_DEFAULT_SET, +#ifdef DOT11W_PMF_SUPPORT + CMD_RTPRIV_IOCTL_80211_STA_MGMT_KEY_DEFAULT_SET, +#endif /* DOT11W_PMF_SUPPORT */ + CMD_RTPRIV_IOCTL_80211_POWER_MGMT_SET, + CMD_RTPRIV_IOCTL_80211_AP_KEY_DEFAULT_SET, + CMD_RTPRIV_IOCTL_80211_CONNECT_TO, + CMD_RTPRIV_IOCTL_80211_RFKILL, + CMD_RTPRIV_IOCTL_80211_REG_NOTIFY_TO, + CMD_RTPRIV_IOCTL_80211_UNREGISTER, + CMD_RTPRIV_IOCTL_80211_BANDINFO_GET, + CMD_RTPRIV_IOCTL_80211_SURVEY_GET, + CMD_RTPRIV_IOCTL_80211_EXTRA_IES_SET, + CMD_RTPRIV_IOCTL_80211_REMAIN_ON_CHAN_SET, + CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_REG, + CMD_RTPRIV_IOCTL_80211_CHANNEL_LOCK, + CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_SEND, + CMD_RTPRIV_IOCTL_80211_CHANNEL_LIST_SET, + CMD_RTPRIV_IOCTL_80211_ACTION_FRAME_REG, + CMD_RTPRIV_IOCTL_80211_BEACON_ADD, + CMD_RTPRIV_IOCTL_80211_BEACON_SET, + CMD_RTPRIV_IOCTL_80211_BEACON_DEL, + CMD_RTPRIV_IOCTL_80211_AP_KEY_ADD, + CMD_RTPRIV_IOCTL_80211_RTS_THRESHOLD_ADD, + CMD_RTPRIV_IOCTL_80211_FRAG_THRESHOLD_ADD, + CMD_RTPRIV_IOCTL_80211_CHANGE_BSS_PARM, + CMD_RTPRIV_IOCTL_80211_AP_KEY_DEL, + CMD_RTPRIV_IOCTL_80211_AP_PROBE_RSP_EXTRA_IE, + CMD_RTPRIV_IOCTL_80211_AP_ASSOC_RSP_EXTRA_IE, + CMD_RTPRIV_IOCTL_80211_PORT_SECURED, + CMD_RTPRIV_IOCTL_80211_AP_STA_DEL, + CMD_RTPRIV_IOCTL_80211_CANCEL_REMAIN_ON_CHAN_SET, + CMD_RTPRIV_IOCTL_80211_BITRATE_SET, + CMD_RTPRIV_IOCTL_80211_VIF_ADD, + CMD_RTPRIV_IOCTL_80211_VIF_DEL, + CMD_RTPRIV_IOCTL_80211_RESET, + CMD_RTPRIV_IOCTL_80211_P2PCLI_ASSSOC_IE_SET, + CMD_RTPRIV_IOCTL_80211_P2P_CLIENT_KEY_ADD, + CMD_RTPRIV_IOCTL_80211_CHANNEL_RESTORE, + CMD_RTPRIV_IOCTL_80211_SCAN_STATUS_LOCK_INIT, + CMD_RTPRIV_IOCTL_80211_NETDEV_EVENT, +#ifdef RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT + CMD_RTPRIV_IOCTL_80211_ANDROID_PRIV_CMD, +#endif /* RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT */ +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + CMD_RTPRIV_IOCTL_80211_SEND_WIRELESS_EVENT, +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + CMD_RTPRIV_IOCTL_80211_END, +#endif /* RT_CFG80211_SUPPORT */ + + CMD_RTPRIV_IOCTL_ADAPTER_CSO_SUPPORT_TEST, + CMD_RTPRIV_IOCTL_ADAPTER_TSO_SUPPORT_TEST, +#ifdef CONFIG_HAS_EARLYSUSPEND + CMD_RTPRIV_IOCTL_LOAD_FIRMWARE_CHECK, + CMD_RTPRIV_IOCTL_REGISTER_EARLYSUSPEND, + CMD_RTPRIV_IOCTL_UNREGISTER_EARLYSUSPEND, + CMD_RTPRIV_IOCTL_CHECK_EARLYSUSPEND, + CMD_RTPRIV_IOCTL_OS_COOKIE_GET, + CMD_RTPRIV_IOCTL_SET_SUSPEND_FLAG, +#endif /* CONFIG_HAS_EARLYSUSPEND */ + /* can not exceed 0xa000 */ + CMD_RTPRIV_IOCTL_80211_COM_LATEST_ONE, +} CMD_RTPRIV_IOCTL_COMMON; + +#ifdef RT_CFG80211_SUPPORT +typedef struct __CMD_RTPRIV_IOCTL_80211_VIF_SET { + INT vifType; + char vifName[IFNAMSIZ]; + INT vifNameLen; +} CMD_RTPRIV_IOCTL_80211_VIF_SET; + +typedef struct __CMD_RTPRIV_IOCTL_80211_BSS_PARM { + INT use_cts_prot; + INT use_short_preamble; + INT use_short_slot_time; + UINT8 *basic_rates; + UINT8 basic_rates_len; + INT ap_isolate; + INT ht_opmode; + +} CMD_RTPRIV_IOCTL_80211_BSS_PARM; + +typedef struct __CMD_RTPRIV_IOCTL_80211_BEACON { + INT32 interval; + INT32 dtim_period; + UCHAR *beacon_head; + UCHAR *beacon_tail; + UINT32 beacon_head_len; /* Before TIM IE */ + UINT32 beacon_tail_len; /* After TIM IE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + UCHAR *beacon_ies; + UINT32 beacon_ies_len; + UCHAR *proberesp_ies; + UINT32 proberesp_ies_len; + UCHAR *assocresp_ies; + UINT32 assocresp_ies_len; + UCHAR *probe_resp; + UINT32 probe_resp_len; + ULONG ssid_len; + UCHAR hidden_ssid; + struct cfg80211_crypto_settings crypto; + BOOLEAN privacy; + UCHAR auth_type; + INT32 inactivity_timeout; +#endif +} CMD_RTPRIV_IOCTL_80211_BEACON; + +#define RT_CMD_80211_IFTYPE_UNSPECIFIED 0x00 +#define RT_CMD_80211_IFTYPE_ADHOC 0x01 +#define RT_CMD_80211_IFTYPE_STATION 0x02 +#define RT_CMD_80211_IFTYPE_AP 0x03 +#define RT_CMD_80211_IFTYPE_MONITOR 0x06 +#define RT_CMD_80211_IFTYPE_P2P_CLIENT 0x08 +#define RT_CMD_80211_IFTYPE_P2P_GO 0x09 +#define RT_CMD_80211_IFTYPE_P2P_DEVICE 0x10 + +/* Must sync with nl80211_channel_type@nl80211.h */ +#define RT_CMD_80211_CHANTYPE_NOHT 0x00 +#define RT_CMD_80211_CHANTYPE_HT20 0x01 +#define RT_CMD_80211_CHANTYPE_HT40MINUS 0X02 +#define RT_CMD_80211_CHANTYPE_HT40PLUS 0X03 + +typedef struct __CMD_RTPRIV_IOCTL_80211_CHAN { + UINT8 ChanId; + UINT8 IfType; + UINT8 ChanType; + + UINT32 MonFilterFlag; + + UINT64 cookie; + PVOID chan; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + PWIRELESS_DEV pWdev; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ +} CMD_RTPRIV_IOCTL_80211_CHAN; + +#define RT_CMD_80211_FILTER_FCSFAIL 0x01 +#define RT_CMD_80211_FILTER_PLCPFAIL 0x02 +#define RT_CMD_80211_FILTER_CONTROL 0x04 +#define RT_CMD_80211_FILTER_OTHER_BSS 0x08 + +typedef struct __CMD_RTPRIV_IOCTL_80211_VIF_PARM { + PNET_DEV net_dev; + UINT8 newIfType; + UINT8 oldIfType; + + UINT32 MonFilterFlag; + +} CMD_RTPRIV_IOCTL_80211_VIF_PARM; + +typedef struct __CMD_RTPRIV_IOCTL_80211_IBSS { + UINT BeaconInterval; + UCHAR Ssid[33]; + UINT privacy; + PUCHAR BeaconExtraIe; + UINT BeaconExtraIeLen; +} CMD_RTPRIV_IOCTL_80211_IBSS; + +#define RT_CMD_80211_TXRATE_LEGACY 0x01 +#define RT_CMD_80211_TXRATE_BW_40 0x02 +#define RT_CMD_80211_TXRATE_SHORT_GI 0x04 + +typedef struct __CMD_RTPRIV_IOCTL_80211_STA { + UINT8 MAC[MAC_ADDR_LEN]; + ULONG DataRate; + + UINT32 TxRateFlags; + + UINT32 TxRateMCS; + INT32 Signal; + UINT32 TxPacketCnt; + UINT32 InactiveTime; +} CMD_RTPRIV_IOCTL_80211_STA; + +#define RT_CMD_80211_KEY_WEP40 0x00 +#define RT_CMD_80211_KEY_WEP104 0x01 +#define RT_CMD_80211_KEY_WPA 0x02 +#ifdef DOT11W_PMF_SUPPORT +#define RT_CMD_80211_KEY_AES_CMAC 0x03 +#endif /* DOT11W_PMF_SUPPORT */ + +typedef struct __CMD_RTPRIV_IOCTL_80211_KEY { + UINT8 KeyType; + UINT8 KeyBuf[50]; + UINT8 KeyId; + BOOLEAN bPairwise; + UINT8 KeyLen; + UINT32 cipher; + UINT8 MAC[MAC_ADDR_LEN]; +} CMD_RTPRIV_IOCTL_80211_KEY; + +#define RT_CMD_80211_CONN_ENCRYPT_NONE 0x01 +#define RT_CMD_80211_CONN_ENCRYPT_WEP 0x02 +#define RT_CMD_80211_CONN_ENCRYPT_TKIP 0x04 +#define RT_CMD_80211_CONN_ENCRYPT_CCMP 0x08 + +typedef struct __CMD_RTPRIV_IOCTL_80211_CONNECT { + UINT8 WpaVer; + BOOLEAN FlgIs8021x; + UINT8 AuthType; + + UINT8 PairwiseEncrypType; + UINT8 GroupwiseEncrypType; + + UINT8 *pKey; + UINT32 KeyLen; + UINT8 KeyIdx; + + UINT8 *pSsid; + UINT32 SsidLen; + + UINT8 *pBssid; + + BOOLEAN bWpsConnection; +#ifdef DOT11W_PMF_SUPPORT + BOOLEAN mfp; +#endif /* DOT11W_PMF_SUPPORT */ + +} CMD_RTPRIV_IOCTL_80211_CONNECT; + +typedef struct __CMD_RTPRIV_IOCTL_80211_REG_NOTIFY { + + UCHAR Alpha2[2]; + VOID *pWiphy; +} CMD_RTPRIV_IOCTL_80211_REG_NOTIFY; + +typedef struct __CMD_RTPRIV_IOCTL_80211_SURVEY { + + VOID *pCfg80211; +/* UINT64 ChannelTime; */ /* idle + busy, not support */ + UINT64 ChannelTimeBusy; + UINT64 ChannelTimeExtBusy; +} CMD_RTPRIV_IOCTL_80211_SURVEY; + +#endif /* RT_CFG80211_SUPPORT */ + +/* station commands */ +#ifdef CONFIG_STA_SUPPORT +typedef enum _CMD_RTPRIV_IOCTL_STATION { + + /* general */ + CMD_RTPRIV_IOCTL_PARAM_SET = 0xa000, + CMD_RTPRIV_IOCTL_SITESURVEY_GET, + CMD_RTPRIV_IOCTL_SITESURVEY, + CMD_RTPRIV_IOCTL_ORI_DEV_TYPE_SET, + CMD_RTPRIV_IOCTL_STA_SCAN_SANITY_CHECK, + CMD_RTPRIV_IOCTL_STA_SCAN_END, + + /* wireless */ + CMD_RTPRIV_IOCTL_BSS_LIST_GET, + + /* standard ioctl */ + CMD_RTPRIV_IOCTL_STA_SIOCSIWFREQ, + CMD_RTPRIV_IOCTL_STA_SIOCGIWFREQ, + CMD_RTPRIV_IOCTL_STA_SIOCSIWMODE, + CMD_RTPRIV_IOCTL_STA_SIOCGIWMODE, + CMD_RTPRIV_IOCTL_STA_SIOCSIWAP, + CMD_RTPRIV_IOCTL_STA_SIOCGIWAP, + CMD_RTPRIV_IOCTL_STA_SIOCSIWSCAN, + CMD_RTPRIV_IOCTL_STA_SIOCGIWSCAN, + CMD_RTPRIV_IOCTL_STA_SIOCSIWESSID, + CMD_RTPRIV_IOCTL_STA_SIOCGIWESSID, + CMD_RTPRIV_IOCTL_STA_SIOCSIWNICKN, + CMD_RTPRIV_IOCTL_STA_SIOCGIWNICKN, + CMD_RTPRIV_IOCTL_STA_SIOCSIWRTS, + CMD_RTPRIV_IOCTL_STA_SIOCGIWRTS, + CMD_RTPRIV_IOCTL_STA_SIOCSIWFRAG, + CMD_RTPRIV_IOCTL_STA_SIOCGIWFRAG, + CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODE, + CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODE, + CMD_RTPRIV_IOCTL_STA_SIOCSIWMLME, + CMD_RTPRIV_IOCTL_STA_SIOCSIWAUTH, + CMD_RTPRIV_IOCTL_STA_SIOCGIWAUTH, + CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODEEXT, + CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODEEXT, + CMD_RTPRIV_IOCTL_STA_SIOCSIWGENIE, + CMD_RTPRIV_IOCTL_STA_SIOCGIWGENIE, + CMD_RTPRIV_IOCTL_STA_SIOCSIWPMKSA, + CMD_RTPRIV_IOCTL_STA_SIOCSIWRATE, + CMD_RTPRIV_IOCTL_STA_SIOCGIWRATE, + CMD_RTPRIV_IOCTL_STA_SIOCGIFHWADDR, + CMD_RTPRIV_IOCTL_STA_SIOCSIWPRIVRSSI, + + CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_U32_ITEM, + CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_STR_ITEM, + CMD_RTPRIV_IOCTL_STA_IW_GET_STATISTICS, +} CMD_RTPRIV_IOCTL_STATION; + +#define RT_CMD_MODE_ADHOC 0x01 +#define RT_CMD_MODE_INFRA 0x02 +#define RT_CMD_MODE_MONITOR 0x03 +#endif /* CONFIG_STA_SUPPORT */ + +/* when adding any new type, please also add codes in LINUX_WEVENT_TRANSLATE */ +#define RT_WLAN_EVENT_CUSTOM 0x01 +#define RT_WLAN_EVENT_CGIWAP 0x02 +#define RT_WLAN_EVENT_ASSOC_REQ_IE 0x03 +#define RT_WLAN_EVENT_SCAN 0x04 +#define RT_WLAN_EVENT_EXPIRED 0x05 +#define RT_WLAN_EVENT_SHOWPIN 0x06 +#define RT_WLAN_EVENT_PIN 0x07 + +typedef struct __RT_CMD_RATE_SET { + IN UINT32 Rate; + IN UINT32 Fixed; +} RT_CMD_RATE_SET; + +typedef struct __RT_CMD_PARAM_SET { + IN PSTRING pThisChar; + IN PSTRING pValue; +} RT_CMD_PARAM_SET; + +typedef struct __RT_CMD_SHARED_KEY_ADD { + IN UCHAR KeyIdx; + IN BOOLEAN FlgHaveGTK; +} RT_CMD_SHARED_KEY_ADD; + +typedef struct __RT_CMD_MBSS_KICKOUT { + IN INT BssId; + IN USHORT Reason; +} RT_CMD_MBSS_KICKOUT; + +typedef struct __RT_CMD_USB_MORE_FLAG_CONFIG { + IN UINT32 VendorID; + IN UINT32 ProductID; +} RT_CMD_USB_MORE_FLAG_CONFIG; + +typedef struct __RT_CMD_USB_DEV_CONFIG { + IN UINT NumberOfPipes; + IN UINT8 BulkInEpAddr[2]; + IN USHORT BulkInMaxPacketSize; + IN UINT8 BulkOutEpAddr[6]; + IN USHORT BulkOutMaxPacketSize; + IN VOID *pConfig; +} RT_CMD_USB_DEV_CONFIG; + +typedef struct __RT_CMD_CFG80211_CONFIG { + IN VOID *pCfgDev; + IN VOID( + *CFG80211_Register) ( + IN VOID * pAd, + IN VOID * pDev, + IN VOID * pNetDev); +} RT_CMD_CFG80211_CONFIG; + +typedef struct __RT_CMD_WAIT_QUEUE_LIST { + OUT RTMP_OS_TASK *pMlmeTask; + OUT RTMP_OS_TASK *pTimerTask; + OUT RTMP_OS_TASK *pCmdQTask; + OUT RTMP_OS_TASK *pWscTask; +} RT_CMD_WAIT_QUEUE_LIST; + +typedef struct __RT_CMD_INF_UP_DOWN { + + IN int (*rt28xx_open)(VOID *net_dev); + IN int (*rt28xx_close)(VOID *net_dev); +} RT_CMD_INF_UP_DOWN; + +typedef struct __RT_CMD_STATS64 { + IN VOID *pNetDev; + + OUT UINT64 rx_bytes; /* total bytes received */ + OUT UINT64 tx_bytes; /* total bytes transmitted */ + OUT unsigned long rx_packets; /* total packets received */ + OUT unsigned long tx_packets; /* total packets transmitted */ + OUT unsigned long rx_errors; /* bad packets received */ + OUT unsigned long tx_errors; /* packet transmit problems */ + OUT unsigned long multicast; /* multicast packets received */ + OUT unsigned long collisions; + + OUT unsigned long rx_over_errors; /* receiver ring buff overflow */ + OUT unsigned long rx_crc_errors; /* recved pkt with crc error */ + OUT unsigned long rx_frame_errors; /* recv'd frame alignment error */ + OUT unsigned long rx_fifo_errors; /* recv'r fifo overrun */ +} RT_CMD_STATS64; + +typedef struct __RT_CMD_IW_STATS { + + ULONG priv_flags; + UCHAR *dev_addr; + + VOID *pStats; /* point to pAd->iw_stats */ + + UINT8 qual; + UINT8 level; + UINT8 noise; + UINT8 updated; +} RT_CMD_IW_STATS; + +typedef struct __RT_CMD_PCIE_INIT { + + IN VOID *pPciDev; + IN UINT32 ConfigDeviceID; + IN UINT32 ConfigSubsystemVendorID; + IN UINT32 ConfigSubsystemID; +} RT_CMD_PCIE_INIT; + +typedef struct __RT_CMD_AP_IOCTL_CONFIG { + IN VOID *net_dev; + IN VOID *wdev; + IN ULONG priv_flags; + IN char *pCmdData; + IN INT32 CmdId_RTPRIV_IOCTL_SET; + IN char *name; + IN INT apidx; + + OUT INT32 Status; +} RT_CMD_AP_IOCTL_CONFIG; + +typedef struct __RT_CMD_AP_IOCTL_SSID { + IN ULONG priv_flags; + IN INT apidx; + + OUT char *pSsidStr; + OUT INT32 length; +} RT_CMD_AP_IOCTL_SSID; + +typedef struct __RT_CMD_IOCTL_RATE { + IN ULONG priv_flags; + OUT UINT32 BitRate; +} RT_CMD_IOCTL_RATE; + +#define RTMP_CMD_STA_MODE_AUTO 0x00 +#define RTMP_CMD_STA_MODE_ADHOC 0x01 +#define RTMP_CMD_STA_MODE_INFRA 0x02 +#define RTMP_CMD_STA_MODE_MONITOR 0x03 + +typedef struct __RT_CMD_STA_IOCTL_FREQ { + IN INT32 m; /* Mantissa */ + IN INT16 e; /* Exponent */ +} RT_CMD_STA_IOCTL_FREQ; + +typedef struct __RT_CMD_STA_IOCTL_BSS { + OUT UCHAR Bssid[6]; + OUT UCHAR ChannelQuality; + OUT CHAR Rssi; + OUT CHAR Noise; +} RT_CMD_STA_IOCTL_BSS; + +typedef struct __RT_CMD_STA_IOCTL_BSS_LIST { + IN UINT32 MaxNum; + OUT UINT32 BssNum; + OUT RT_CMD_STA_IOCTL_BSS *pList; +} RT_CMD_STA_IOCTL_BSS_LIST; + +typedef struct __RT_CMD_STA_IOCTL_SCAN { + IN UCHAR FlgScanThisSsid; + IN UINT32 SsidLen; + IN CHAR *pSsid; + OUT INT32 Status; +} RT_CMD_STA_IOCTL_SCAN; + +typedef struct __RT_CMD_STA_IOCTL_BSS_TABLE { + OUT UCHAR Bssid[6]; + OUT UCHAR Channel; + OUT UCHAR BssType; + OUT UCHAR HtCapabilityLen; + OUT UCHAR VHTCapabilityLen; + + OUT UCHAR SupRate[12]; + OUT UCHAR SupRateLen; + OUT UCHAR ExtRate[12]; + OUT UCHAR ExtRateLen; + + OUT UCHAR SsidLen; + OUT CHAR Ssid[32]; + + OUT USHORT CapabilityInfo; + OUT UCHAR ChannelWidth, ShortGIfor40, ShortGIfor20, MCSSet; + + OUT USHORT WpaIeLen; + OUT UCHAR *pWpaIe; + + OUT USHORT RsnIeLen; + OUT UCHAR *pRsnIe; + + OUT USHORT WpsIeLen; + OUT UCHAR *pWpsIe; + + OUT UCHAR FlgIsPrivacyOn; + + OUT RT_CMD_STA_IOCTL_BSS Signal; +} RT_CMD_STA_IOCTL_BSS_TABLE; + +typedef struct __RT_CMD_STA_IOCTL_SCAN_TABLE { + IN ULONG priv_flags; + OUT UINT32 BssNr; + OUT RT_CMD_STA_IOCTL_BSS_TABLE *pBssTable; /* must be freed by caller */ + OUT UCHAR MainSharedKey[4][16]; +} RT_CMD_STA_IOCTL_SCAN_TABLE; + +typedef struct __RT_CMD_STA_IOCTL_SSID { + IN UCHAR FlgAnySsid; + INOUT UINT32 SsidLen; + INOUT CHAR *pSsid; + OUT INT32 Status; +} RT_CMD_STA_IOCTL_SSID; + +typedef struct __RT_CMD_STA_IOCTL_NICK_NAME { + OUT UINT NameLen; + OUT CHAR *pName; +} RT_CMD_STA_IOCTL_NICK_NAME; + +typedef struct __RT_CMD_STA_IOCTL_SECURITY { + INOUT CHAR *pData; + INOUT UINT16 length; + IN INT32 KeyIdx; + IN INT32 MaxKeyLen; + +#define RT_CMD_STA_IOCTL_SECURITY_ALG_NONE 0x01 +#define RT_CMD_STA_IOCTL_SECURITY_ALG_WEP 0x02 +#define RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP 0x03 +#define RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP 0x04 + IN UINT32 Alg; + +#define RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY 0x01 +#define RT_CMD_STA_IOCTL_SECURTIY_EXT_GROUP_KEY 0x02 + IN UINT16 ext_flags; + +#define RT_CMD_STA_IOCTL_SECURITY_DISABLED 0x01 +#define RT_CMD_STA_IOCTL_SECURITY_ENABLED 0x02 +#define RT_CMD_STA_IOCTL_SECURITY_RESTRICTED 0x04 +#define RT_CMD_STA_IOCTL_SECURITY_OPEN 0x08 +#define RT_CMD_STA_IOCTL_SECURITY_NOKEY 0x10 +#define RT_CMD_STA_IOCTL_SECURITY_MODE 0x20 + INOUT UINT16 flags; + + OUT INT32 Status; +} RT_CMD_STA_IOCTL_SECURITY; + +typedef struct __RT_CMD_STA_IOCTL_WSC_U32_ITEM { + IN UINT32 *pUWrq; + OUT INT32 Status; +} RT_CMD_STA_IOCTL_WSC_U32_ITEM; + +typedef struct __RT_CMD_STA_IOCTL_WSC_STR_ITEM { + IN UINT32 Subcmd; + IN CHAR *pData; + IN UINT32 length; + + OUT INT32 Status; +} RT_CMD_STA_IOCTL_WSC_STR_ITEM; + +typedef struct __RT_CMD_STA_IOCTL_SHOW { + IN CHAR *pData; + IN UINT32 MaxSize; + IN UINT32 InfType; +} RT_CMD_STA_IOCTL_SHOW; + +#define RT_CMD_STA_IOCTL_IW_MLME_DEAUTH 0x01 +#define RT_CMD_STA_IOCTL_IW_MLME_DISASSOC 0x02 + +typedef struct __RT_CMD_STA_IOCTL_SECURITY_ADV { + +#define RT_CMD_STA_IOCTL_WPA_VERSION 0x10 +#define RT_CMD_STA_IOCTL_WPA_VERSION1 0x11 +#define RT_CMD_STA_IOCTL_WPA_VERSION2 0x12 + +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE 0x20 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_NONE 0x21 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP40 0x22 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP104 0x23 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_TKIP 0x24 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_CCMP 0x25 + +#define RT_CMD_STA_IOCTL_WPA_GROUP 0x30 +#define RT_CMD_STA_IOCTL_WPA_GROUP_NONE 0x31 +#define RT_CMD_STA_IOCTL_WPA_GROUP_WEP40 0x32 +#define RT_CMD_STA_IOCTL_WPA_GROUP_WEP104 0x33 +#define RT_CMD_STA_IOCTL_WPA_GROUP_TKIP 0x34 +#define RT_CMD_STA_IOCTL_WPA_GROUP_CCMP 0x35 + +#define RT_CMD_STA_IOCTL_WPA_KEY_MGMT 0x40 +#define RT_CMD_STA_IOCTL_WPA_KEY_MGMT_1X 0x41 +#define RT_CMD_STA_IOCTL_WPA_KEY_MGMT_WPS 0x42 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_RX_UNENCRYPTED_EAPOL 0x50 +#define RT_CMD_STA_IOCTL_WPA_AUTH_PRIVACY_INVOKED 0x60 +#define RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED 0x70 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG 0x80 +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_SHARED 0x81 +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_OPEN 0x82 +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_LEAP 0x83 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED 0x90 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_COUNTERMEASURES 0xA0 + + IN UINT32 flags; + IN UINT32 value; +} RT_CMD_STA_IOCTL_SECURITY_ADV; + +typedef struct __RT_CMD_STA_IOCTL_RSN_IE { + INOUT UINT32 length; + INOUT UCHAR *pRsnIe; +} RT_CMD_STA_IOCTL_RSN_IE; + +typedef struct __RT_CMD_STA_IOCTL_PMA_SA { +#define RT_CMD_STA_IOCTL_PMA_SA_FLUSH 0x01 +#define RT_CMD_STA_IOCTL_PMA_SA_REMOVE 0x02 +#define RT_CMD_STA_IOCTL_PMA_SA_ADD 0x03 + IN UINT32 Cmd; + IN UCHAR *pBssid; + IN UCHAR *pPmkid; +} RT_CMD_STA_IOCTL_PMA_SA; + +typedef struct __RT_CMD_USB_INIT { + VOID *pUsbDev; + UINT32 driver_info; +} RT_CMD_USB_INIT; + +#endif /* __RTMP_CMD_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_comm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_comm.h new file mode 100644 index 000000000..0517f1831 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_comm.h @@ -0,0 +1,408 @@ +/**************************************************************************** + + Module Name: + rtmp_comm.h + + Abstract: + All common definitions and macros for UTIL/DRIVER/NETIF. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RT_COMM_H__ +#define __RT_COMM_H__ + +#define VENDOR_FEATURE1_SUPPORT +//#ifdef BB_SOC +//#define VENDOR_FEATURE3_SUPPORT +//#endif + + +/*#define MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +/*#define AGS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef VENDOR_FEATURE3_SUPPORT +#ifndef BB_SOC +#ifdef DOT1X_SUPPORT +#undef DOT1X_SUPPORT +#endif /* DOT1X_SUPPORT */ +#ifdef SYSTEM_LOG_SUPPORT +#undef SYSTEM_LOG_SUPPORT +#endif /* SYSTEM_LOG_SUPPORT */ +#endif /* !BB_SOC */ +#ifdef LED_CONTROL_SUPPORT +#undef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ +#ifdef WSC_LED_SUPPORT +#undef WSC_LED_SUPPORT +#endif /* WSC_LED_SUPPORT */ +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +#ifdef VENDOR_FEATURE1_SUPPORT +#define FIFO_STAT_READ_PERIOD 4 +#else +#define FIFO_STAT_READ_PERIOD 0 +#endif /* VENDOR_FEATURE1_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + +#ifndef VENDOR_FEATURE3_SUPPORT +#ifdef CONFIG_HOTSPOT_R2 +#define AP_QLOAD_SUPPORT +#endif /*CONFIG_HOTSPOT_R2*/ +#endif /* VENDOR_FEATURE3_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + + +/* ======================== Before include files ============================ */ +/* + 14 channels @2.4G + 12@UNII(lower/middle) + 16@HiperLAN2 + 11@UNII(upper) + 0 @Japan + 1 as NULL termination + Refer to CH_HZ_ID_MAP[] in rt_channel.c +*/ +#ifdef DOT11_VHT_AC +#define MAX_NUM_OF_CHS (54 + 5) /* 5 channels for central channel of VHT 80MHz */ +#else +#define MAX_NUM_OF_CHS 54 +#endif /* DOT11_VHT_AC*/ +/* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS +#define MAX_NUM_OF_SUB_CHANNELS MAX_NUM_OF_CHANNELS/2 /*Assume half size for sub channels*/ + + +#include "rtmp_type.h" +#include "rtmp_os.h" +#include "link_list.h" +#include "rtmp_cmd.h" +#include "iface/iface_util.h" + +#ifdef CONFIG_SNIFFER_SUPPORT +#include "sniffer/sniffer.h" +#endif /* CONFIG_SNIFFER_SUPPORT */ + + + +/* ======================== Debug =========================================== */ +/* */ +/* Debug information verbosity: lower values indicate higher urgency */ +/* */ +#define RT_DEBUG_OFF 0 +#define RT_DEBUG_ERROR 1 +#define RT_DEBUG_WARN 2 +#define RT_DEBUG_TRACE 3 +#define RT_DEBUG_INFO 4 +#define RT_DEBUG_LOUD 5 + +typedef enum{ + DBG_FUNC_RA = 0x100, /* debug flag for rate adaptation */ + DBG_FUNC_SA = 0x200, /* debug flag for smart antenna */ + DBG_FUNC_MAX = DBG_FUNC_SA, +}RT_DEBUG_FUNC; + + +/* ======================== Definition ====================================== */ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* definition of pAd->OpMode */ +#define OPMODE_STA 0 +#define OPMODE_AP 1 +#define OPMODE_APSTA 2 /* as AP and STA at the same time */ + +#define MAIN_MBSSID 0 +#define FIRST_MBSSID 1 + +/* Endian byte swapping codes */ +#define SWAP16(x) \ + ((UINT16) (\ + (((UINT16) (x) & (UINT16) 0x00ffU) << 8) | \ + (((UINT16) (x) & (UINT16) 0xff00U) >> 8))) + +#define SWAP32(x) \ + ((UINT32) (\ + (((UINT32) (x) & (UINT32) 0x000000ffUL) << 24) | \ + (((UINT32) (x) & (UINT32) 0x0000ff00UL) << 8) | \ + (((UINT32) (x) & (UINT32) 0x00ff0000UL) >> 8) | \ + (((UINT32) (x) & (UINT32) 0xff000000UL) >> 24))) + +#define SWAP64(x) \ + ((UINT64)( \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) << 8) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >> 8) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) )) + +#ifdef RT_BIG_ENDIAN + +#define cpu2le64(x) SWAP64((x)) +#define le2cpu64(x) SWAP64((x)) +#define cpu2le32(x) SWAP32((x)) +#define le2cpu32(x) SWAP32((x)) +#define cpu2le16(x) SWAP16((x)) +#define le2cpu16(x) SWAP16((x)) +#define cpu2be64(x) ((UINT64)(x)) +#define be2cpu64(x) ((UINT64)(x)) +#define cpu2be32(x) ((UINT32)(x)) +#define be2cpu32(x) ((UINT32)(x)) +#define cpu2be16(x) ((UINT16)(x)) +#define be2cpu16(x) ((UINT16)(x)) + +#else /* Little_Endian */ + +#define cpu2le64(x) ((UINT64)(x)) +#define le2cpu64(x) ((UINT64)(x)) +#define cpu2le32(x) ((UINT32)(x)) +#define le2cpu32(x) ((UINT32)(x)) +#define cpu2le16(x) ((UINT16)(x)) +#define le2cpu16(x) ((UINT16)(x)) +#define cpu2be64(x) SWAP64((x)) +#define be2cpu64(x) SWAP64((x)) +#define cpu2be32(x) SWAP32((x)) +#define be2cpu32(x) SWAP32((x)) +#define cpu2be16(x) SWAP16((x)) +#define be2cpu16(x) SWAP16((x)) + +#endif /* RT_BIG_ENDIAN */ + + +#define MAX_CUSTOM_LEN 128 + +/* */ +/* IEEE 802.11 Structures and definitions */ +/* */ +#define MAX_TX_POWER_LEVEL 100 /* mW */ +#define MAX_RSSI_TRIGGER -10 /* dBm */ +#define MIN_RSSI_TRIGGER -200 /* dBm */ +#define MAX_FRAG_THRESHOLD 2346 /* byte count */ +#define MIN_FRAG_THRESHOLD 256 /* byte count */ +#define MAX_RTS_THRESHOLD 2347 /* byte count */ + +typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE + { +Ndis802_11IBSS, +Ndis802_11Infrastructure, +Ndis802_11AutoUnknown, +Ndis802_11Monitor, +Ndis802_11InfrastructureMax /* Not a real value, defined as upper bound */ +} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; + + + + +/* ======================== Memory ========================================== */ +#ifdef VENDOR_FEATURE2_SUPPORT + +extern ULONG OS_NumOfPktAlloc, OS_NumOfPktFree; + +#define MEM_DBG_PKT_ALLOC_INC(__pPacket) OS_NumOfPktAlloc ++; +#define MEM_DBG_PKT_FREE_INC(__pPacket) OS_NumOfPktFree ++; +#else +#define MEM_DBG_PKT_ALLOC_INC(__pPacket) +#define MEM_DBG_PKT_FREE_INC(__pPacket) +#endif /* VENDOR_FEATURE2_SUPPORT */ + +/* value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header */ +#define BTYPE_MGMT 0 +#define BTYPE_CNTL 1 +#define BTYPE_DATA 2 + +/* All PHY rate summary in TXD */ +/* Preamble MODE in TxD */ +#define MODE_CCK 0 +#define MODE_OFDM 1 +#ifdef DOT11_N_SUPPORT +#define MODE_HTMIX 2 +#define MODE_HTGREENFIELD 3 +#endif /* DOT11_N_SUPPORT */ +#define MODE_VHT 4 + +#ifdef NO_CONSISTENT_MEM_SUPPORT +/* current support RXD_SIZE = 16B and cache line = 16 or 32B */ +#define RTMP_DCACHE_FLUSH(__AddrStart, __Size) \ + RtmpOsDCacheFlush((ULONG)(__AddrStart), (ULONG)(__Size)) +#else +#define RTMP_DCACHE_FLUSH(__AddrStart, __Size) +#endif /* NO_CONSISTENT_MEM_SUPPORT */ + + +/* ======================== Interface ======================================= */ +typedef enum _RTMP_INF_TYPE_ +{ + RTMP_DEV_INF_UNKNOWN = 0, + RTMP_DEV_INF_PCI = 1, + RTMP_DEV_INF_USB = 2, + RTMP_DEV_INF_RBUS = 4, + RTMP_DEV_INF_PCIE = 5, +}RTMP_INF_TYPE; + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) if(_pAd->OpMode == OPMODE_AP) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) if(_pAd->OpMode == OPMODE_STA) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) if (__OpMode == OPMODE_AP) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) if (__OpMode == OPMODE_STA) +#else +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) +#endif + + + +/*********************************************************************************** + * IOCTL related definitions and data structures. + **********************************************************************************/ +typedef struct __RTMP_IOCTL_INPUT_STRUCT +{ + union + { + CHAR *name; + struct + { + CHAR *pointer; + UINT16 length; + UINT16 flags; + } data; + } u; +} RTMP_IOCTL_INPUT_STRUCT; + + +#define RT_CMD_STATUS_TRANSLATE(__Status) \ + { \ + if (__Status == RTMP_IO_EINVAL) \ + __Status = -EINVAL; \ + else if (__Status == RTMP_IO_EOPNOTSUPP) \ + __Status = -EOPNOTSUPP; \ + else if (__Status == RTMP_IO_EFAULT) \ + __Status = -EFAULT; \ + else if (__Status == RTMP_IO_E2BIG) \ + __Status = -E2BIG; \ + else if (__Status == RTMP_IO_ENOMEM) \ + __Status = -ENOMEM; \ + else if (__Status == RTMP_IO_EAGAIN) \ + __Status = -EAGAIN; \ + else if (__Status == RTMP_IO_ENOTCONN) \ + __Status = -ENOTCONN; \ + } + + + + +/* ======================== Timer =========================================== */ +typedef struct _LIST_RESOURCE_OBJ_ENTRY +{ + struct _LIST_RESOURCE_OBJ_ENTRY *pNext; + VOID *pRscObj; +} LIST_RESOURCE_OBJ_ENTRY, *PLIST_RESOURCE_OBJ_ENTRY; + + + + +/* ======================== IC =========================================== */ +#define RFIC_24GHZ 0x01 +#define RFIC_5GHZ 0x02 +#define RFIC_DUAL_BAND (RFIC_24GHZ | RFIC_5GHZ) + + + + +/* ======================== CFG80211 ======================================== */ +#define RT_CFG80211_DEBUG /* debug use */ + +#ifdef RT_CFG80211_DEBUG +#define CFG80211DBG(__Flg, __pMsg) DBGPRINT(__Flg, __pMsg) +#else +#define CFG80211DBG(__Flg, __pMsg) +#endif /* RT_CFG80211_DEBUG */ + +/* 1 ~ 14 */ +#define CFG80211_NUM_OF_CHAN_2GHZ 14 + +/* 36 ~ 64, 100 ~ 136, 140 ~ 161 */ +#define CFG80211_NUM_OF_CHAN_5GHZ \ + (sizeof(Cfg80211_Chan)-CFG80211_NUM_OF_CHAN_2GHZ) + + + + +/* ======================== Packet ========================================== */ +#define LENGTH_802_11 24 +#define LENGTH_802_11_AND_H 30 +#define LENGTH_802_11_CRC_H 34 +#define LENGTH_802_11_CRC 28 +#define LENGTH_802_11_WITH_ADDR4 30 +#define LENGTH_802_3 14 +#define LENGTH_802_3_TYPE 2 +#define LENGTH_802_1_H 8 +#define LENGTH_EAPOL_H 4 +#define LENGTH_WMMQOS_H 2 +#define LENGTH_CRC 4 +#define MAX_SEQ_NUMBER 0x0fff +#define LENGTH_802_3_NO_TYPE 12 +#define LENGTH_802_1Q 4 /* VLAN related */ + + +#ifdef TX_PKT_SG +#ifndef MAX_SKB_FRAGS +#define MAX_SKB_FRAGS (65536/(1UL << 12) + 2) +#endif +typedef struct _PTK_SG_T{ + VOID *data; + INT len; +}PKT_SG_T; +#endif /* TX_PKT_SG */ +/* + Packet information for NdisQueryPacket +*/ +typedef struct _PACKET_INFO { + UINT PhysicalBufferCount; /* Physical breaks of buffer descripor chained */ + UINT BufferCount; /* Number of Buffer descriptor chained */ + UINT TotalPacketLength ; /* Self explained */ + PNDIS_BUFFER pFirstBuffer; /* Pointer to first buffer descriptor */ +#ifdef TX_PKT_SG + PKT_SG_T sg_list[MAX_SKB_FRAGS]; +#endif /* TX_PKT_SG */ +} PACKET_INFO, *PPACKET_INFO; + + +#define MAC_ADDR_LEN 6 + + + + +#define RLT_MAC_BASE 0x01 + +/* rate table params */ +enum Rate_BW +{ + Rate_BW_20=0, + Rate_BW_40, + Rate_BW_80, + Rate_BW_MAX +}; +enum Rate_GI +{ + Rate_800ns_GI=0, + Rate_400ns_GI, + Rate_GI_MAX +}; +#define Rate_MCS 10 + + +#endif /* __RT_COMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_def.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_def.h new file mode 100644 index 000000000..1ade01768 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_def.h @@ -0,0 +1,2223 @@ +/* + *************************************************************************** + * 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_def.h + + Abstract: + Miniport related definition header + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + John Chang 08-05-2003 add definition for 11g & other drafts +*/ +#ifndef __RTMP_DEF_H__ +#define __RTMP_DEF_H__ + +#include "oid.h" + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_AP_SUPPORT +#define AP_WSC_INCLUDED +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT +#define STA_WSC_INCLUDED +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + + +#define BAND_5G 1 +#define BAND_24G 2 +#define BAND_BOTH (BAND_5G | BAND_24G) + + +#ifdef SNMP_SUPPORT +/* for snmp, to get manufacturer OUI, 2008_0220 */ +#define ManufacturerOUI_LEN 3 +#define ManufacturerNAME ("Ralink Technology Company.") +#define ResourceTypeIdName ("Ralink_ID") +#endif + +#define RALINK_2883_VERSION ((UINT32)0x28830300) +#define RALINK_2880E_VERSION ((UINT32)0x28720200) +#define RALINK_3883_VERSION ((UINT32)0x38830400) +#define RALINK_3070_VERSION ((UINT32)0x30700200) + +#define MAX_RX_PKT_LEN 1520 + + +#define PCI_VIRT_TO_PHYS(__Addr) (((UINT32)(__Addr)) & 0x0FFFFFFF) + + +#ifdef MULTIPLE_CARD_SUPPORT +/* MC: Multple Cards */ +#define MAX_NUM_OF_MULTIPLE_CARD 32 +#endif /* MULTIPLE_CARD_SUPPORT */ + +#ifdef MEMORY_OPTIMIZATION +#define MAX_RX_PROCESS 32 +#else +#define MAX_RX_PROCESS 128 /*64 //32 */ +#endif +#define NUM_OF_LOCAL_TXBUF 2 +#define TXD_SIZE 16 /* TXD_SIZE = TxD + TxInfo */ +#define RXD_SIZE 16 + +#define RXINFO_OFFSET 12 + +/* TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header */ +#define TX_DMA_1ST_BUFFER_SIZE 96 /* only the 1st physical buffer is pre-allocated */ + +/*#define MGMT_DMA_BUFFER_SIZE 1536 //2048 */ +/* + Note 20100212 by SampleLin: do not set MGMT_DMA_BUFFER_SIZE smaller than + 1600; Or kernel will crash in deaggregate_AMSDU_announce() for EAPOL packet + in enterprise WPA mode. +*/ +#define MGMT_DMA_BUFFER_SIZE 1600 /*2048 */ + +#define RX_BUFFER_AGGRESIZE 3840 /*3904 //3968 //4096 //2048 //4096 */ +//#define RX_BUFFER_AGGRESIZE 2000 /*3904 //3968 //4096 //2048 //4096 */ +#define RX_BUFFER_NORMSIZE 3840 /*3904 //3968 //4096 //2048 //4096 */ +#define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE +#define MAX_FRAME_SIZE 2346 /* Maximum 802.11 frame size */ +#define MAX_AGGREGATION_SIZE 3840 /*3904 //3968 //4096 */ +#define MAX_NUM_OF_TUPLE_CACHE 2 +#define MAX_MCAST_LIST_SIZE 32 +#define MAX_LEN_OF_VENDOR_DESC 64 +/*#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ */ +#define MAX_SIZE_OF_MCAST_PSQ 32 + +#define MAX_RX_PROCESS_CNT (RX_RING_SIZE) + +#ifdef WLAN_SKB_RECYCLE +#define NUM_RX_DESC 128 +#endif /* WLAN_SKB_RECYCLE */ + +/* + WMM Note: If memory of your system is not much, please reduce the definition; + or when you do WMM test, the queue for low priority AC will be full, i.e. + TX_RING_SIZE + MAX_PACKETS_IN_QUEUE packets for the AC will be buffered in + WLAN, maybe no any packet buffer can be got in Ethernet driver. + + Sometimes no packet buffer can be got in Ethernet driver, the system will + send flow control packet to the sender to slow down its sending rate. + So no WMM can be saw in the air. +*/ + +/* + Need to use 64 in vxworks for test case WMM A5-T07 + Two dnlink (10Mbps) from a WMM station to a non-WMM station. + If use 256, queue is not enough. + And in rt_main_end.c, clConfig.clNum = RX_RING_SIZE * 3; is changed to + clConfig.clNum = RX_RING_SIZE * 4; +*/ + +#ifdef NOISE_TEST_ADJUST +#define MAX_PACKETS_IN_MCAST_PS_QUEUE 128 /*64*/ +#define MAX_PACKETS_IN_PS_QUEUE 256 /*32 */ +#else +#define MAX_PACKETS_IN_MCAST_PS_QUEUE 32 +#define MAX_PACKETS_IN_PS_QUEUE 128 /*32 */ +#endif /* NOISE_TEST_ADJUST */ +#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef IGMP_SNOOP_SUPPORT +#ifdef MEMORY_OPTIMIZATION +#define MAX_LEN_OF_MULTICAST_FILTER_TABLE 16 +#else +#define MAX_LEN_OF_MULTICAST_FILTER_TABLE 64 +#endif +/* Size of hash tab must be power of 2. */ +#define MAX_LEN_OF_MULTICAST_FILTER_HASH_TABLE ((MAX_LEN_OF_MULTICAST_FILTER_TABLE) * 2) +#define FREE_MEMBER_POOL_SIZE 64 +#endif /* IGMP_SNOOP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#define MAX_AGG_3SS_BALIMIT 31 + +/* RxFilter */ +#define STANORMAL 0x17f97 +#define APNORMAL 0x15f97 +#ifdef CONFIG_STA_SUPPORT +#ifdef XLINK_SUPPORT +#define PSPXLINK 0x17f93 +#endif /* XLINK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef EXT_BUILD_CHANNEL_LIST +#define MAX_PRECONFIG_DESP_ENTRY_SIZE 11 +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +/* + RTMP_ADAPTER flags +*/ +#define fRTMP_ADAPTER_MAP_REGISTER 0x00000001 +#define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002 +#define fRTMP_HW_ERR 0x00000004 +#define fRTMP_SG 0x00000008 /* Scatter and Gather */ + +#define fRTMP_PKT_TX_ERR 0x00000010 +#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020 +#define fRTMP_ADAPTER_HALT_IN_PROGRESS 0x00000040 +#define fRTMP_ADAPTER_RESET_IN_PROGRESS 0x00000080 + +#define fRTMP_ADAPTER_NIC_NOT_EXIST 0x00000100 +#define fRTMP_ADAPTER_TX_RING_ALLOCATED 0x00000200 +#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS 0x00000400 +#define fRTMP_ADAPTER_MIMORATE_INUSED 0x00000800 + +#define fRTMP_ADAPTER_RX_RING_ALLOCATED 0x00001000 +#define fRTMP_ADAPTER_INTERRUPT_ACTIVE 0x00002000 +#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS 0x00004000 +#define fRTMP_ADAPTER_REASSOC_IN_PROGRESS 0x00008000 + +#define fRTMP_ADAPTER_MEDIA_STATE_PENDING 0x00010000 +#define fRTMP_ADAPTER_RADIO_OFF 0x00020000 +#define fRTMP_ADAPTER_BULKOUT_RESET 0x00040000 +#define fRTMP_ADAPTER_BULKIN_RESET 0x00080000 + +#define fRTMP_ADAPTER_RDG_ACTIVE 0x00100000 +#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000 +#define fRTMP_ADAPTER_RALINK_BURST_MODE 0x00400000 +#define fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET 0x00800000 + +#define fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD 0x01000000 +#define fRTMP_ADAPTER_CMD_RADIO_OFF 0x02000000 +#define fRTMP_ADAPTER_SCAN_2040 0x04000000 +#define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000 + +#define fRTMP_ADAPTER_START_UP 0x10000000 /*Devive already initialized and enabled Tx/Rx. */ +//#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000 + +//#ifdef CONFIG_PM +//#ifdef USB_SUPPORT_SELECTIVE_SUSPEND +#define fRTMP_ADAPTER_SUSPEND 0x20000000 +//#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +//#endif /* CONFIG_PM */ + +#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 +#define fRTMP_ADAPTER_POLL_IDLE 0x80000000 + +enum ASIC_CAP{ + fASIC_CAP_RX_SC = 0x1, + fASIC_CAP_CSO = 0x2, + fASIC_CAP_TSO = 0x4, + fASIC_CAP_MCS_LUT = 0x8, + + fASIC_CAP_PMF_ENC = 0x10, +}; + +#define fRTMP_ADAPTER_DISABLE_DOT_11N 0x00000001 +#define fRTMP_ADAPTER_WSC_PBC_PIN0 0x00000002 +#define fRTMP_ADAPTER_DISABLE_DEQUEUE 0x00000004 + +enum PHY_CAP{ + fPHY_CAP_24G = 0x1, + fPHY_CAP_5G = 0x2, + + fPHY_CAP_HT = 0x10, + fPHY_CAP_VHT = 0x20, + + fPHY_CAP_TXBF = 0x100, + fPHY_CAP_LDPC = 0x200, +}; + +enum HIF_TYPE{ + HIF_RTMP = 0x0, + HIF_RLT = 0x1, + HIF_MT = 0x2, +}; + +enum MAC_TYPE{ + MAC_RTMP = 0x0, + MAC_MT = 0x1, +}; + +enum RF_TYPE { + RF_RT, + RF_RLT, + RF_MT, +}; + +enum BBP_TYPE{ + BBP_RTMP = 0x0, + BBP_RLT = 0x1, + BBP_MT = 0x2, +}; + +#define PHY_CAP_2G(_x) (((_x) & fPHY_CAP_24G) == fPHY_CAP_24G) +#define PHY_CAP_5G(_x) (((_x) & fPHY_CAP_5G) == fPHY_CAP_5G) + +enum WIFI_MODE{ + WMODE_INVALID = 0, + WMODE_A = 1 << 0, + WMODE_B = 1 << 1, + WMODE_G = 1 << 2, + WMODE_GN = 1 << 3, + WMODE_AN = 1 << 4, + WMODE_AC = 1 << 5, + WMODE_COMP = 6, /* total types of supported wireless mode, add this value once yow add new type */ +}; + +#define WMODE_CAP_5G(_x) (((_x) & (WMODE_A | WMODE_AN | WMODE_AC)) != 0) +#define WMODE_CAP_2G(_x) (((_x) & (WMODE_B | WMODE_G | WMODE_GN)) != 0) +#define WMODE_CAP_N(_x) (((_x) & (WMODE_GN | WMODE_AN)) != 0) +#define WMODE_CAP_AC(_x) (((_x) & (WMODE_AC)) != 0) +#define WMODE_CAP(_x, _mode) (((_x) & (_mode)) != 0) + +#define WMODE_EQUAL(_x, _mode) ((_x) == (_mode)) + +#define WMODE_5G_ONLY(_x) (((_x) & (WMODE_B | WMODE_G | WMODE_GN)) == 0) +#define WMODE_2G_ONLY(_x) (((_x) & (WMODE_A | WMODE_AN | WMODE_AC)) == 0) +#define WMODE_HT_ONLY(_x) (((_x) & (~(WMODE_GN | WMODE_AN | WMODE_AC))) == 0) +#define WMODE_VHT_ONLY(_x) (((_x) & (~(WMODE_AC))) == 0) + + +/* + STA operation status flags +*/ +#define fOP_STATUS_INFRA_ON 0x00000001 +#define fOP_STATUS_ADHOC_ON 0x00000002 +#define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004 +#define fOP_STATUS_SHORT_SLOT_INUSED 0x00000008 +#define fOP_STATUS_SHORT_PREAMBLE_INUSED 0x00000010 +#define fOP_STATUS_RECEIVE_DTIM 0x00000020 +/*#define fOP_STATUS_TX_RATE_SWITCH_ENABLED 0x00000040 */ +#define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080 +#define fOP_STATUS_WMM_INUSED 0x00000100 +#define fOP_STATUS_AGGREGATION_INUSED 0x00000200 +#define fOP_STATUS_DOZE 0x00000400 /* debug purpose */ +#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 /* piggy-back, and aggregation */ +#define fOP_STATUS_APSD_INUSED 0x00001000 +#define fOP_STATUS_TX_AMSDU_INUSED 0x00002000 +#define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000 +#define fOP_STATUS_WAKEUP_NOW 0x00008000 +#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000 + +#ifdef DOT11V_WNM_SUPPORT +#define fOP_STATUS_FMS_ENABLE 0x00400000 +#endif /* DOT11V_WNM_SUPPORT */ +#define fOP_AP_STATUS_MEDIA_STATE_CONNECTED 0x00200000 + +/* + RTMP_ADAPTER PSFlags : related to advanced power save +*/ +/* Indicate whether driver can go to sleep mode from now. This flag is useful AFTER link up */ +#define fRTMP_PS_CAN_GO_SLEEP 0x00000001 +/* Indicate whether driver has issue a LinkControl command to PCIe L1 */ +#define fRTMP_PS_SET_PCI_CLK_OFF_COMMAND 0x00000002 +/* Indicate driver should disable kick off hardware to send packets from now. */ +#define fRTMP_PS_DISABLE_TX 0x00000004 +/* Indicate driver should IMMEDIATELY fo to sleep after receiving AP's beacon in which doesn't indicate unicate nor multicast packets for me */ +/* This flag is used ONLY in RTMPHandleRxDoneInterrupt routine. */ +#define fRTMP_PS_GO_TO_SLEEP_NOW 0x00000008 +#define fRTMP_PS_TOGGLE_L1 0x00000010 /* Use Toggle L1 mechanism for rt28xx PCIe */ + +#define fRTMP_PS_MCU_SLEEP 0x00000020 + +#define WAKE_MCU_CMD 0x31 +#define SLEEP_MCU_CMD 0x30 +#define RFOFF_MCU_CMD 0x35 + +#ifdef DOT11N_DRAFT3 +#define fOP_STATUS_SCAN_2040 0x00040000 +#endif /* DOT11N_DRAFT3 */ + +#define CCKSETPROTECT 0x1 +#define OFDMSETPROTECT 0x2 +#define MM20SETPROTECT 0x4 +#define MM40SETPROTECT 0x8 +#define GF20SETPROTECT 0x10 +#define GR40SETPROTECT 0x20 +#define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT) + +/* + AP's client table operation status flags +*/ +#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 /* CLIENT can parse QOS DATA frame */ +#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 /* CLIENT can receive Ralink's proprietary TX aggregation frame */ +#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 /* CLIENT support piggy-back */ +#define fCLIENT_STATUS_AMSDU_INUSED 0x00000008 +#define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010 +#define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020 +#define fCLIENT_STATUS_TxSTBC_CAPABLE 0x00000040 +#define fCLIENT_STATUS_RxSTBC_CAPABLE 0x00000080 +#define fCLIENT_STATUS_HTC_CAPABLE 0x00000100 +#define fCLIENT_STATUS_RDG_CAPABLE 0x00000200 +#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400 +#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ + +#ifdef DOT11N_DRAFT3 +#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE 0x00001000 +#endif /* DOT11N_DRAFT3 */ +#define fCLIENT_STATUS_SOFTWARE_ENCRYPT 0x00002000 /* Indicate the client encrypt/decrypt by software */ +#ifdef DOT11W_PMF_SUPPORT +#define fCLIENT_STATUS_PMF_CAPABLE 0x00004000 +#define fCLIENT_STATUS_USE_SHA256 0x00008000 +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11_VHT_AC +#define fCLIENT_STATUS_SGI80_CAPABLE 0x00010000 +#define fCLIENT_STATUS_SGI160_CAPABLE 0x00020000 +#define fCLIENT_STATUS_VHT_TXSTBC_CAPABLE 0x00040000 +#define fCLIENT_STATUS_VHT_RXSTBC_CAPABLE 0x00080000 +#endif /* DOT11_VHT_AC */ + +#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 + +#ifdef CLIENT_WDS +#define fCLIENT_STATUS_CLI_WDS 0x00200000 +#endif /* CLIENT_WDS */ + + +#define fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE 0x00800000 +#define fCLIENT_STATUS_HT_RX_LDPC_CAPABLE 0x01000000 +#define fCLIENT_STATUS_2G_256QAM_CAPABLE 0x02000000 /* CLIENT support 2.4G 256QAM */ +#ifdef CONFIG_HOTSPOT_R2 +#define fCLIENT_STATUS_OSEN_CAPABLE 0x04000000 +#endif + +/* + STA configuration flags +*/ +/*#define fSTA_CFG_ENABLE_TX_BURST 0x00000001 */ + +/* 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case */ +#define HT_NO_PROTECT 0 +#define HT_LEGACY_PROTECT 1 +#define HT_40_PROTECT 2 +#define HT_2040_PROTECT 3 +#define HT_RTSCTS_6M 7 +/*following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. */ +#define HT_ATHEROS 8 /* rt2860c has problem with atheros chip. we need to turn on RTS/CTS . */ +#define HT_FORCERTSCTS 9 /* Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. */ + +/* + RX Packet Filter control flags. Apply on pAd->PacketFilter +*/ +#define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED +#define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST +#define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST +#define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST +#define fRX_FILTER_ACCEPT_PROMISCUOUS NDIS_PACKET_TYPE_PROMISCUOUS + +/* + Error code section +*/ +/* NDIS_ERROR_CODE_ADAPTER_NOT_FOUND */ +#define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L +#define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L +#define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L + +/* NDIS_ERROR_CODE_ADAPTER_DISABLED */ +#define ERRLOG_BUS_MASTER_DISABLED 0x00000201L + +/* NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION */ +#define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L +#define ERRLOG_SET_SECONDARY_FAILED 0x00000302L + +/* NDIS_ERROR_CODE_OUT_OF_RESOURCES */ +#define ERRLOG_OUT_OF_MEMORY 0x00000401L +#define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L +#define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L +#define ERRLOG_OUT_OF_BUFFER_POOL 0x00000404L +#define ERRLOG_OUT_OF_NDIS_BUFFER 0x00000405L +#define ERRLOG_OUT_OF_PACKET_POOL 0x00000406L +#define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L +#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L + +/* NDIS_ERROR_CODE_HARDWARE_FAILURE */ +#define ERRLOG_SELFTEST_FAILED 0x00000501L +#define ERRLOG_INITIALIZE_ADAPTER 0x00000502L +#define ERRLOG_REMOVE_MINIPORT 0x00000503L + +/* NDIS_ERROR_CODE_RESOURCE_CONFLICT */ +#define ERRLOG_MAP_IO_SPACE 0x00000601L +#define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L +#define ERRLOG_NO_IO_RESOURCE 0x00000603L +#define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L +#define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L + +/* WDS definition */ +#define MAX_WDS_ENTRY 0 +#ifdef WDS_SUPPORT +#undef MAX_WDS_ENTRY +#define MAX_WDS_ENTRY 4 +#endif /* WDS_SUPPORT */ +#define WDS_PAIRWISE_KEY_OFFSET 60 /* WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table */ + +#define WDS_DISABLE_MODE 0 +#define WDS_RESTRICT_MODE 1 +#define WDS_BRIDGE_MODE 2 +#define WDS_REPEATER_MODE 3 +#define WDS_LAZY_MODE 4 + +#define MAX_MESH_NUM 0 + +#define MAX_APCLI_NUM 0 +#ifdef APCLI_SUPPORT +#undef MAX_APCLI_NUM +#define MAX_APCLI_NUM 1 +#ifdef APCLI_CONNECTION_TRIAL +#undef MAX_APCLI_NUM +#define MAX_APCLI_NUM 2 +#endif /* APCLI_CONNECTION_TRIAL */ +#endif /* APCLI_SUPPORT */ + +#define MAX_P2P_NUM 0 + +#define MAX_MBSSID_NUM(__pAd) 1 + +#ifdef MAC_APCLI_SUPPORT +#define APCLI_BSS_BASE 8 +#else +#define APCLI_BSS_BASE 0 +#endif /* MAC_APCLI_SUPPORT */ + + +#ifdef MBSS_SUPPORT +#undef MAX_MBSSID_NUM + +#define HW_BEACON_MAX_COUNT(__pAd) ((__pAd)->chipCap.BcnMaxHwNum) +#define MAX_MBSSID_NUM(__pAd) ((__pAd)->chipCap.BcnMaxNum) + +#else +#define HW_BEACON_MAX_COUNT(__pAd) 8 +#endif /* MBSS_SUPPORT */ + +#define HW_BEACON_MAX_NUM 16 + +/* sanity check for apidx */ +#define MBSS_MR_APIDX_SANITY_CHECK(__pAd, apidx) \ + { if ((apidx >= MAX_MBSSID_NUM(__pAd)) || \ + (apidx >= HW_BEACON_MAX_NUM)) { \ + DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __FUNCTION__, apidx)); \ + apidx = MAIN_MBSSID; } } + +#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) + +#define VALID_MBSS(_pAd, _apidx) ((_apidx < MAX_MBSSID_NUM(_pAd)) && (_apidx < HW_BEACON_MAX_NUM)) + +#define MAX_BEACON_SIZE 512 + + +#define HW_RESERVED_WCID(__pAd) ((__pAd)->chipCap.WcidHwRsvNum) + +/* Then dedicate wcid of DFS and Carrier-Sense. */ +#define DFS_CTS_WCID(__pAd) (HW_RESERVED_WCID(__pAd) - 1) +#define CS_CTS_WCID(__pAd) (HW_RESERVED_WCID(__pAd) - 2) +#define LAST_SPECIFIC_WCID(__pAd) (HW_RESERVED_WCID(__pAd) - 2) + +/* If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211. */ +/* If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228. */ +#define MAX_AVAILABLE_CLIENT_WCID(__pAd) (LAST_SPECIFIC_WCID(__pAd) - MAX_MBSSID_NUM(__pAd) - 1) + +/* TX need WCID to find Cipher Key */ +/* these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8. */ +#define GET_GroupKey_WCID(__pAd, __wcid, __bssidx) \ + { \ + __wcid = LAST_SPECIFIC_WCID(__pAd) - (MAX_MBSSID_NUM(__pAd)) + __bssidx; \ + } + +/*#define IsGroupKeyWCID(__pAd, __wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM(__pAd))))) */ + +/* definition to support multiple BSSID */ +#define BSS0 0 +#define BSS1 1 +#define BSS2 2 +#define BSS3 3 +#define BSS4 4 +#define BSS5 5 +#define BSS6 6 +#define BSS7 7 + +/*============================================================ */ +/* Length definitions */ +#define PEER_KEY_NO 2 +#define TIMESTAMP_LEN 8 +#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ +#define MAX_NUM_OF_REGULATORY_CLASS 16 +#define MAX_LEN_OF_KEY 32 /* 32 octets == 256 bits, Redefine for WPA */ +/* #define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS */ /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_NUM_OF_11JCHANNELS 20 /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_LEN_OF_SSID 32 +#define CIPHER_TEXT_LEN 128 +#define HASH_TABLE_SIZE 256 /* Size of hash tab must be power of 2. */ +#define MAX_VIE_LEN 1024 /* New for WPA cipher suite variable IE sizes. */ +#define MAX_SUPPORT_MCS 32 +#define MAX_NUM_OF_BBP_LATCH 256 +#undef MAX_NUM_OF_BBP_LATCH +#define MAX_NUM_OF_BBP_LATCH 255 + +#define MAX_LEN_OF_CCK_RATES 4 +#define MAX_LEN_OF_OFDM_RATES 8 +#define MAX_LEN_OF_HT_RATES 24 +#ifdef DOT11_VHT_AC +#define MAX_LEN_OF_VHT_RATES 20 +#endif /* DOT11_VHT_AC */ +#define SUPPORT_CCK_MODE 1 +#define SUPPORT_OFDM_MODE 2 +#define SUPPORT_HT_MODE 4 +#define SUPPORT_VHT_MODE 8 + +/*============================================================ */ +/* ASIC WCID Table definition. */ +/*============================================================ */ +#define BSSID_WCID 1 /* in infra mode, always put bssid with this WCID */ +#define MCAST_WCID 0x0 +#define BSS0Mcast_WCID 0x0 +#define BSS1Mcast_WCID 0xf8 +#define BSS2Mcast_WCID 0xf9 +#define BSS3Mcast_WCID 0xfa +#define BSS4Mcast_WCID 0xfb +#define BSS5Mcast_WCID 0xfc +#define BSS6Mcast_WCID 0xfd +#define BSS7Mcast_WCID 0xfe +#define RESERVED_WCID 0xff +#define WCID_ALL 0xff + + +#define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL + +#ifdef MAC_REPEATER_SUPPORT +#define MAX_LEN_OF_MAC_TABLE (MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * MAX_APCLI_NUM)) +#else +#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ +#endif + +#define MAX_LEN_OF_TR_TABLE (MAX_LEN_OF_MAC_TABLE + HW_BEACON_MAX_NUM) + +#define VALID_TR_WCID(_wcid) ((_wcid) < MAX_LEN_OF_TR_TABLE) + +/*#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID */ +/*#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!! */ +/*#endif */ + +#define MAX_NUM_OF_WDS_LINK_PERBSSID 3 +/*#define MAX_NUM_OF_WDS_LINK (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM) // no use */ +#define MAX_NUM_OF_EVENT MAX_NUMBER_OF_EVENT +#define WDS_LINK_START_WCID (MAX_LEN_OF_MAC_TABLE-1) + +#define NUM_OF_SWFB 10 + +#define NUM_OF_TID 8 +#define MAX_AID_BA 4 + +#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient */ +#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator */ +#ifdef MEMORY_OPTIMIZATION +#define MAX_LEN_OF_BSS_TABLE 1 +#define MAX_REORDERING_MPDU_NUM 256 +#else +#define MAX_LEN_OF_BSS_TABLE 128 /* 64 */ +#define MAX_REORDERING_MPDU_NUM 512 +#endif + +/* key related definitions */ +#define SHARE_KEY_NUM 4 +#define MAX_LEN_OF_SHARE_KEY 16 /* byte count */ +#define MAX_LEN_OF_PEER_KEY 16 /* byte count */ +#define PAIRWISE_KEY_NUM 64 /* in MAC ASIC pairwise key table */ +#define GROUP_KEY_NUM 4 +#define PMK_LEN 32 +#define WDS_PAIRWISE_KEY_OFFSET 60 /* WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table */ +#define PMKID_NO 4 /* Number of PMKID saved supported */ +#define MAX_LEN_OF_MLME_BUFFER 2048 + +/* power status related definitions */ +#define PWR_ACTIVE 0 +#define PWR_SAVE 1 +#define PWR_MMPS 2 /*MIMO power save */ +/*#define PWR_UNKNOWN 2 */ + +/* Auth and Assoc mode related definitions */ +#define AUTH_MODE_OPEN 0x00 +#define AUTH_MODE_KEY 0x01 +#define AUTH_MODE_FT 0x02 +#define AUTH_MODE_SAE 0x03 +#define AUTH_MODE_VENDOR 0xffff + +/* BSS Type definitions */ +#define BSS_ADHOC 0 /* = Ndis802_11IBSS */ +#define BSS_INFRA 1 /* = Ndis802_11Infrastructure */ +#define BSS_ANY 2 /* = Ndis802_11AutoUnknown */ +#define BSS_MONITOR 3 /* = Ndis802_11Monitor */ + +/* Reason code definitions */ +#define REASON_RESERVED 0 +#define REASON_UNSPECIFY 1 +#define REASON_NO_LONGER_VALID 2 +#define REASON_DEAUTH_STA_LEAVING 3 +#define REASON_DISASSOC_INACTIVE 4 +#define REASON_DISASSPC_AP_UNABLE 5 +#define REASON_CLS2ERR 6 +#define REASON_CLS3ERR 7 +#define REASON_DISASSOC_STA_LEAVING 8 +#define REASON_STA_REQ_ASSOC_NOT_AUTH 9 +#define REASON_INVALID_IE 13 +#define REASON_MIC_FAILURE 14 +#define REASON_4_WAY_TIMEOUT 15 +#define REASON_GROUP_KEY_HS_TIMEOUT 16 +#define REASON_IE_DIFFERENT 17 +#define REASON_MCIPHER_NOT_VALID 18 +#define REASON_UCIPHER_NOT_VALID 19 +#define REASON_AKMP_NOT_VALID 20 +#define REASON_UNSUPPORT_RSNE_VER 21 +#define REASON_INVALID_RSNE_CAP 22 +#define REASON_8021X_AUTH_FAIL 23 +#define REASON_CIPHER_SUITE_REJECTED 24 +#define REASON_DECLINED 37 + +#define REASON_QOS_UNSPECIFY 32 +#define REASON_QOS_LACK_BANDWIDTH 33 +#define REASON_POOR_CHANNEL_CONDITION 34 +#define REASON_QOS_OUTSIDE_TXOP_LIMITION 35 +#define REASON_QOS_QSTA_LEAVING_QBSS 36 +#define REASON_QOS_UNWANTED_MECHANISM 37 +#define REASON_QOS_MECH_SETUP_REQUIRED 38 +#define REASON_QOS_REQUEST_TIMEOUT 39 +#define REASON_QOS_CIPHER_NOT_SUPPORT 45 + +#ifdef DOT11V_WNM_SUPPORT +#define REASON_DISASSOC_DUE_TO_BSS_TRANSITION_MANAGEMENT 12 +#endif /* DOT11V_WNM_SUPPORT */ + +#define REASON_FT_INVALID_FTIE 55 + +/* Status code definitions */ +#define MLME_SUCCESS 0 +#define MLME_UNSPECIFY_FAIL 1 +#define MLME_SECURITY_WEAK 5 +#define MLME_CANNOT_SUPPORT_CAP 10 +#define MLME_REASSOC_DENY_ASSOC_EXIST 11 +#define MLME_ASSOC_DENY_OUT_SCOPE 12 +#define MLME_ALG_NOT_SUPPORT 13 +#define MLME_SEQ_NR_OUT_OF_SEQUENCE 14 +#define MLME_REJ_CHALLENGE_FAILURE 15 +#define MLME_REJ_TIMEOUT 16 +#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA 17 +#define MLME_ASSOC_REJ_DATA_RATE 18 + +#define MLME_ASSOC_REJ_NO_EXT_RATE 22 +#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC 23 +#define MLME_ASSOC_REJ_NO_CCK_OFDM 24 + +#ifdef DOT11W_PMF_SUPPORT +#define MLME_ASSOC_REJ_TEMPORARILY 30 +#define MLME_ROBUST_MGMT_POLICY_VIOLATION 31 +#endif /* DOT11W_PMF_SUPPORT */ + +#define MLME_QOS_UNSPECIFY 32 +#define MLME_REQUEST_DECLINED 37 +#define MLME_REQUEST_WITH_INVALID_PARAM 38 +#define MLME_INVALID_INFORMATION_ELEMENT 40 +#define MLME_INVALID_GROUP_CIPHER 41 +#define MLME_INVALID_PAIRWISE_CIPHER 42 +#define MLME_INVALID_AKMP 43 +#define MLME_NOT_SUPPORT_RSN_VERSION 44 +#define MLME_INVALID_RSN_CAPABILITIES 45 +#define MLME_INVALID_SECURITY_POLICY 46 /* Cipher suite rejected because of security policy */ +#define MLME_DLS_NOT_ALLOW_IN_QBSS 48 +#define MLME_DEST_STA_NOT_IN_QBSS 49 +#define MLME_DEST_STA_IS_NOT_A_QSTA 50 + +#define MLME_INVALID_FORMAT 0x51 +#define MLME_FAIL_NO_RESOURCE 0x52 +#define MLME_STATE_MACHINE_REJECT 0x53 +#define MLME_MAC_TABLE_FAIL 0x54 + +/* IE code */ +#define IE_SSID 0 +#define IE_SUPP_RATES 1 +#define IE_FH_PARM 2 +#define IE_DS_PARM 3 +#define IE_CF_PARM 4 +#define IE_TIM 5 +#define IE_IBSS_PARM 6 +#define IE_COUNTRY 7 /* 802.11d */ +#define IE_802_11D_REQUEST 10 /* 802.11d */ +#define IE_QBSS_LOAD 11 /* 802.11e d9 */ +#define IE_EDCA_PARAMETER 12 /* 802.11e d9 */ +#define IE_TSPEC 13 /* 802.11e d9 */ +#define IE_TCLAS 14 /* 802.11e d9 */ +#define IE_SCHEDULE 15 /* 802.11e d9 */ +#define IE_CHALLENGE_TEXT 16 +#define IE_POWER_CONSTRAINT 32 /* 802.11h d3.3 */ +#define IE_POWER_CAPABILITY 33 /* 802.11h d3.3 */ +#define IE_TPC_REQUEST 34 /* 802.11h d3.3 */ +#define IE_TPC_REPORT 35 /* 802.11h d3.3 */ +#define IE_SUPP_CHANNELS 36 /* 802.11h d3.3 */ +#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 /* 802.11h d3.3 */ +#define IE_MEASUREMENT_REQUEST 38 /* 802.11h d3.3 */ +#define IE_MEASUREMENT_REPORT 39 /* 802.11h d3.3 */ +#define IE_QUIET 40 /* 802.11h d3.3 */ +#define IE_IBSS_DFS 41 /* 802.11h d3.3 */ +#define IE_ERP 42 /* 802.11g */ +#define IE_TS_DELAY 43 /* 802.11e d9 */ +#define IE_TCLAS_PROCESSING 44 /* 802.11e d9 */ +#define IE_QOS_CAPABILITY 46 /* 802.11e d6 */ +#define IE_HT_CAP 45 /* 802.11n d1. HT CAPABILITY. ELEMENT ID TBD */ +#define IE_AP_CHANNEL_REPORT 51 /* 802.11k d6 */ +#define IE_HT_CAP2 52 /* 802.11n d1. HT CAPABILITY. ELEMENT ID TBD */ +#define IE_RSN 48 /* 802.11i d3.0 */ +#define IE_WPA2 48 /* WPA2 */ +#define IE_EXT_SUPP_RATES 50 /* 802.11g */ +#define IE_TIMEOUT_INTERVAL 56 /* 802.11w */ +#define IE_SUPP_REG_CLASS 59 /* 802.11y. Supported regulatory classes. */ +#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 /* 802.11n */ +#define IE_ADD_HT 61 /* 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD */ +#define IE_ADD_HT2 53 /* 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD */ + +/* For 802.11n D3.03 */ +/*#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet */ +#define IE_SECONDARY_CH_OFFSET 62 /* 802.11n D3.03 Secondary Channel Offset element */ +#define IE_WAPI 68 /* WAPI information element. Same as Bss Ac Access Dealy Element. */ +#define IE_TIME_ADVERTISEMENT 69 // 802.11p +#define IE_2040_BSS_COEXIST 72 /* 802.11n D3.0.3 */ +#define IE_2040_BSS_INTOLERANT_REPORT 73 /* 802.11n D3.03 */ +#define IE_OVERLAPBSS_SCAN_PARM 74 /* 802.11n D3.03 */ +#define IE_CHANNEL_USAGE 97 /* Cisco advertises suggested channel using this IE. */ +#define IE_TIME_ZONE 98 /* 802.11V */ +#define IE_INTERWORKING 107 /* 802.11u */ +#define IE_ADVERTISEMENT_PROTO 108 /* 802.11u */ +#define IE_QOS_MAP_SET 110 /* 802.11u */ +#define IE_ROAMING_CONSORTIUM 111 /* 802.11u */ +#define IE_EXT_CAPABILITY 127 /* 802.11n D3.03 */ +#define IE_OPERATING_MODE_NOTIFY 199 + +#define IE_WPA 221 /* WPA */ +#define IE_VENDOR_SPECIFIC 221 /* Wifi WMM (WME) */ +#define IE_WFA_WSC 221 + +#define OUI_P2P 0x09 +#define OUI_HS2_INDICATION 0x10 +#define OUI_BROADCOM_HT 51 /* */ +#define OUI_BROADCOM_HTADD 52 /* */ +#define OUI_PREN_HT_CAP 51 /* */ +#define OUI_PREN_ADD_HT 52 /* */ + +/* CCX information */ +#define IE_AIRONET_CKIP 133 /* CCX1.0 ID 85H for CKIP */ +#define IE_AP_TX_POWER 150 /* CCX 2.0 for AP transmit power */ +#define IE_MEASUREMENT_CAPABILITY 221 /* CCX 2.0 */ +#define IE_CCX_V2 221 +#define IE_AIRONET_IPADDRESS 149 /* CCX ID 95H for IP Address */ +#define IE_AIRONET_CCKMREASSOC 156 /* CCX ID 9CH for CCKM Reassociation Request element */ +#define CKIP_NEGOTIATION_LENGTH 30 +#define AIRONET_IPADDRESS_LENGTH 10 +#define AIRONET_CCKMREASSOC_LENGTH 24 + +/* ======================================================== */ +/* MLME state machine definition */ +/* ======================================================== */ + +/* STA MLME state mahcines */ +#define ASSOC_STATE_MACHINE 1 +#define AUTH_STATE_MACHINE 2 +#define AUTH_RSP_STATE_MACHINE 3 +#define SYNC_STATE_MACHINE 4 +#define MLME_CNTL_STATE_MACHINE 5 +#define WPA_PSK_STATE_MACHINE 6 +/*#define LEAP_STATE_MACHINE 7 */ +#define AIRONET_STATE_MACHINE 8 +#define ACTION_STATE_MACHINE 9 + +/* AP MLME state machines */ +#define AP_ASSOC_STATE_MACHINE 11 +#define AP_AUTH_STATE_MACHINE 12 +#define AP_SYNC_STATE_MACHINE 14 +#define AP_CNTL_STATE_MACHINE 15 +#define WSC_STATE_MACHINE 17 +#define WSC_UPNP_STATE_MACHINE 18 + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#define APCLI_AUTH_STATE_MACHINE 19 +#define APCLI_ASSOC_STATE_MACHINE 20 +#define APCLI_SYNC_STATE_MACHINE 21 +#define APCLI_CTRL_STATE_MACHINE 22 +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#define WPA_STATE_MACHINE 23 + + +#ifdef QOS_DLS_SUPPORT +#define DLS_STATE_MACHINE 26 +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +#define FT_OTA_AUTH_STATE_MACHINE 27 +#define FT_OTD_ACT_STATE_MACHINE 28 +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +#define TDLS_STATE_MACHINE 29 +#define TDLS_CHSW_STATE_MACHINE 39 +#endif /* DOT11Z_TDLS_SUPPORT */ + + + +#ifdef DOT11V_WNM_SUPPORT +#define WNM_BSS_TM_STATE_MACHINE 37 +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef IWSC_SUPPORT +#define IWSC_STATE_MACHINE 38 +#endif /* IWSC_SUPPORT */ + + +#ifdef CONFIG_DOT11U_INTERWORKING +#define GAS_STATE_MACHINE 39 +#endif + +#ifdef CONFIG_DOT11V_WNM +#define BTM_STATE_MACHINE 40 +#define WNM_NOTIFY_STATE_MACHINE 41 +#endif + +#ifdef CONFIG_HOTSPOT +#define HSCTRL_STATE_MACHINE 42 +#endif + +/* + STA's CONTROL/CONNECT state machine: states, events, total function # +*/ +#define CNTL_IDLE 0 +#define CNTL_WAIT_DISASSOC 1 +#define CNTL_WAIT_JOIN 2 +#define CNTL_WAIT_REASSOC 3 +#define CNTL_WAIT_START 4 +#define CNTL_WAIT_AUTH 5 +#define CNTL_WAIT_ASSOC 6 +#define CNTL_WAIT_AUTH2 7 +#define CNTL_WAIT_OID_LIST_SCAN 8 +#define CNTL_WAIT_OID_DISASSOC 9 +#define CNTL_WAIT_SCAN_FOR_CONNECT 10 + + +#define MT2_ASSOC_CONF 34 +#define MT2_AUTH_CONF 35 +#define MT2_DEAUTH_CONF 36 +#define MT2_DISASSOC_CONF 37 +#define MT2_REASSOC_CONF 38 +#define MT2_PWR_MGMT_CONF 39 +#define MT2_JOIN_CONF 40 +#define MT2_SCAN_CONF 41 +#define MT2_START_CONF 42 +#define MT2_GET_CONF 43 +#define MT2_SET_CONF 44 +#define MT2_RESET_CONF 45 +#define MT2_FT_OTD_CONF 46 +#define MT2_MLME_ROAMING_REQ 52 + +#define CNTL_FUNC_SIZE 1 + +/* + STA's ASSOC state machine: states, events, total function # +*/ +#define ASSOC_IDLE 0 +#define ASSOC_WAIT_RSP 1 +#define REASSOC_WAIT_RSP 2 +#define DISASSOC_WAIT_RSP 3 +#define MAX_ASSOC_STATE 4 + +#define ASSOC_MACHINE_BASE 0 +#define MT2_MLME_ASSOC_REQ 0 +#define MT2_MLME_REASSOC_REQ 1 +#define MT2_MLME_DISASSOC_REQ 2 +#define MT2_PEER_DISASSOC_REQ 3 +#define MT2_PEER_ASSOC_REQ 4 +#define MT2_PEER_ASSOC_RSP 5 +#define MT2_PEER_REASSOC_REQ 6 +#define MT2_PEER_REASSOC_RSP 7 +#define MT2_DISASSOC_TIMEOUT 8 +#define MT2_ASSOC_TIMEOUT 9 +#define MT2_REASSOC_TIMEOUT 10 +#define MAX_ASSOC_MSG 11 + +#define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG) + +/* + ACT state machine: states, events, total function # +*/ +#define ACT_IDLE 0 +#define MAX_ACT_STATE 1 + +#define ACT_MACHINE_BASE 0 + +/* + Those PEER_xx_CATE number is based on real Categary value in IEEE spec. + Please doesn't modify it by yourself. + */ +/*Category */ +#define MT2_PEER_SPECTRUM_CATE 0 +#define MT2_PEER_QOS_CATE 1 +#define MT2_PEER_DLS_CATE 2 +#define MT2_PEER_BA_CATE 3 +#define MT2_PEER_PUBLIC_CATE 4 +#define MT2_PEER_RM_CATE 5 +/* "FT_CATEGORY_BSS_TRANSITION equal to 6" is defined file of "dot11r_ft.h" */ +#define MT2_PEER_HT_CATE 7 /* 7.4.7 */ +#define MT2_PEER_PMF_CATE 8 /* defined in IEEE 802.11w-D8.0 7.3.1.11 */ +#define MT2_PEER_RESV_9 9 +#define MT2_PEER_RESV_10 10 +#define MT2_PEER_RESV_11 11 +#define MT2_PEER_RESV_12 12 +#define MT2_PEER_RESV_13 13 +#define MT2_PEER_RESV_14 14 +#define MT2_PEER_RESV_15 15 +#define MT2_PEER_RESV_16 16 +/* + In WMM spec v1.1. the category must be 17 + (see Table 7 Management Action Frame Fields) +*/ +#define MT2_PEER_WMM 17 +#define WNM_CATEGORY_BSS_TRANSITION 18 +#define MT2_PEER_RESV_19 19 +#define MT2_PEER_RESV_20 20 +#define MT2_PEER_VHT_CATE 21 +#define MAX_IEEE_STD_CATE 21 /* Indicate the maximum category code defined in IEEE-802.11-Std */ +#define MAX_PEER_CATE_MSG MAX_IEEE_STD_CATE + +#define MT2_MLME_ADD_BA_CATE (MAX_IEEE_STD_CATE + 1) +#define MT2_MLME_ORI_DELBA_CATE (MAX_IEEE_STD_CATE + 2) +#define MT2_MLME_REC_DELBA_CATE (MAX_IEEE_STD_CATE + 3) +#define MT2_MLME_QOS_CATE (MAX_IEEE_STD_CATE + 4) +#define MT2_MLME_DLS_CATE (MAX_IEEE_STD_CATE + 5) +#define MT2_ACT_INVALID (MAX_IEEE_STD_CATE + 6) + +#define MAX_ACT_MSG (MAX_IEEE_STD_CATE + 7) + +#ifdef DOT11V_WNM_SUPPORT +#define WNM_CATEGORY_BSS_TRANSITION 18 +#undef MAX_ACT_MSG +#define MAX_ACT_MSG (MAX_IEEE_STD_CATE + 8) +#undef MAX_PEER_CATE_MSG +#define MAX_PEER_CATE_MSG (MAX_IEEE_STD_CATE + 8) +#endif /* DOT11V_WNM_SUPPORT */ + +#define MT2_ACT_VENDOR 0x7F + +/* Category field */ +#define CATEGORY_SPECTRUM 0 +#define CATEGORY_QOS 1 +#define CATEGORY_DLS 2 +#define CATEGORY_BA 3 +#define CATEGORY_PUBLIC 4 +#define CATEGORY_RM 5 +#define CATEGORY_FT 6 +#define CATEGORY_HT 7 +#ifdef DOT11W_PMF_SUPPORT +#define CATEGORY_SA 8 /* defined in IEEE 802.11w-D8.0 7.3.1.11*/ +#define CATEGORY_PD 9 /* Protected Dual of Action defined in IEEE 802.11w */ +#define CATEGORY_WNM 10 +#define CATEGORY_VSP 126 /* Vendor-specific Protected defined in IEEE 802.11w */ +#endif // DOT11W_PMF_SUPPORT // +#ifdef DOT11Z_TDLS_SUPPORT +#define CATEGORY_TDLS 12 +#endif /* DOT11Z_TDLS_SUPPORT */ +#define CATEGORY_VENDOR_SPECIFIC_WFD 0x7F + + +#ifdef DOT11_VHT_AC +#define CATEGORY_VHT 21 + +#define ACT_VHT_COMPRESS_BF 0 /* VHT Compressed Beamforming */ +#define ACT_VHT_GRP_ID_MGMT 1 /* Group ID Management */ +#define ACT_VHT_OPMODE_NOTIFY 2 /* Operating Mode Notification */ +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11W_PMF_SUPPORT +/* SA Query Action frame definition */ +#define ACTION_SAQ_REQUEST 0 +#define ACTION_SAQ_RESPONSE 1 +#endif // DOT11W_PMF_SUPPORT // + +/* DLS Action frame definition */ +#define ACTION_DLS_REQUEST 0 +#define ACTION_DLS_RESPONSE 1 +#define ACTION_DLS_TEARDOWN 2 + +/* Spectrum Action field value 802.11h 7.4.1 */ +#define SPEC_MRQ 0 /* Request */ +#define SPEC_MRP 1 /*Report */ +#define SPEC_TPCRQ 2 +#define SPEC_TPCRP 3 +#define SPEC_CHANNEL_SWITCH 4 + +/* BA Action field value */ +#define ADDBA_REQ 0 +#define ADDBA_RESP 1 +#define DELBA 2 + +/* Public's Action field value in Public Category. Some in 802.11y and some in 11n */ +#define ACTION_BSS_2040_COEXIST 0 /* 11n */ +#define ACTION_DSE_ENABLEMENT 1 /* 11y D9.0 */ +#define ACTION_DSE_DEENABLEMENT 2 /* 11y D9.0 */ +#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 /* 11y D9.0 */ +#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 /* 11y D9.0 */ +#define ACTION_DSE_MEASUREMENT_REQ 5 /* 11y D9.0 */ +#define ACTION_DSE_MEASUREMENT_REPORT 6 /* 11y D9.0 */ +#define ACTION_MEASUREMENT_PILOT_ACTION 7 /* 11y D9.0 */ +#define ACTION_DSE_POWER_CONSTRAINT 8 /* 11y D9.0 */ +#define ACTION_WIFI_DIRECT 9 /* 11y */ +#define ACTION_GAS_INITIAL_REQ 10 /* 11U */ +#define ACTION_GAS_INITIAL_RSP 11 /* 11U */ +#define ACTION_GAS_COMEBACK_REQ 12 /* 11U */ +#define ACTION_GAS_COMEBACK_RSP 13 /* 11U */ +#define ACTION_TDLS_DISCOVERY_RSP 14 /* 11z D13.0 */ +#define ACTION_VENDOR_USAGE 221 + +/*HT Action field value */ +#define NOTIFY_BW_ACTION 0 +#define SMPS_ACTION 1 +#define PSMP_ACTION 2 +#define SETPCO_ACTION 3 +#define MIMO_CHA_MEASURE_ACTION 4 +#define MIMO_N_BEACONFORM 5 /* non-compressed beamforming report */ +#define MIMO_BEACONFORM 6 /* compressed beamforming report */ +#define ANTENNA_SELECT 7 + +/* VHT Action field value */ +#define ACT_VHT_COMP_BFING 0 /* VHT Compressed Beamforming */ +#define ACT_VHT_GRP_ID_MGMT 1 /* Group ID Management */ +#define ACT_VHT_OPMODE_NOTIFY 2 /* Operating Mode Notification */ + + +#define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG) +/* + STA's AUTHENTICATION state machine: states, evvents, total function # +*/ +#define AUTH_REQ_IDLE 0 +#define AUTH_WAIT_SEQ2 1 +#define AUTH_WAIT_SEQ4 2 +#define MAX_AUTH_STATE 3 + +#define AUTH_MACHINE_BASE 0 +#define MT2_MLME_AUTH_REQ 0 +#define MT2_PEER_AUTH_EVEN 1 +#define MT2_AUTH_TIMEOUT 2 +#define MAX_AUTH_MSG 3 + +#define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG) + +/* + STA's AUTH_RSP state machine: states, events, total function # +*/ +#define AUTH_RSP_IDLE 0 +#define AUTH_RSP_WAIT_CHAL 1 +#define MAX_AUTH_RSP_STATE 2 + +#define AUTH_RSP_MACHINE_BASE 0 +#define MT2_AUTH_CHALLENGE_TIMEOUT 0 +#define MT2_PEER_AUTH_ODD 1 +#define MT2_PEER_DEAUTH 2 +#define MAX_AUTH_RSP_MSG 3 + +#define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG) + +/* + STA's SYNC state machine: states, events, total function # +*/ +#define SYNC_IDLE 0 /* merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state */ +#define JOIN_WAIT_BEACON 1 +#define SCAN_LISTEN 2 +#define SCAN_PENDING 3 +#define MAX_SYNC_STATE 4 + +#define SYNC_MACHINE_BASE 0 +#define MT2_MLME_SCAN_REQ 0 +#define MT2_MLME_JOIN_REQ 1 +#define MT2_MLME_START_REQ 2 +#define MT2_PEER_BEACON 3 +#define MT2_PEER_PROBE_RSP 4 +#define MT2_PEER_ATIM 5 +#define MT2_SCAN_TIMEOUT 6 +#define MT2_BEACON_TIMEOUT 7 +#define MT2_ATIM_TIMEOUT 8 +#define MT2_PEER_PROBE_REQ 9 +#define MT2_MLME_FORCE_JOIN_REQ 10 +#define MT2_MLME_FORCE_SCAN_REQ 11 +#define MAX_SYNC_MSG 12 + +#define SYNC_FUNC_SIZE (MAX_SYNC_STATE * MAX_SYNC_MSG) + +/*Messages for the DLS state machine */ +#define DLS_IDLE 0 +#define MAX_DLS_STATE 1 + +#define DLS_MACHINE_BASE 0 +#define MT2_MLME_DLS_REQ 0 +#define MT2_PEER_DLS_REQ 1 +#define MT2_PEER_DLS_RSP 2 +#define MT2_MLME_DLS_TEAR_DOWN 3 +#define MT2_PEER_DLS_TEAR_DOWN 4 +#define MAX_DLS_MSG 5 + +#define DLS_FUNC_SIZE (MAX_DLS_STATE * MAX_DLS_MSG) + +#ifdef DOT11Z_TDLS_SUPPORT +/*Messages for the TDLS state machine */ +#define TDLS_IDLE 0 +#define MAX_TDLS_STATE 1 + +#define TDLS_MACHINE_BASE 0 +#define MT2_MLME_TDLS_SETUP_REQ 0 +#define MT2_PEER_TDLS_SETUP_REQ 1 +#define MT2_PEER_TDLS_SETUP_RSP 2 +#define MT2_PEER_TDLS_SETUP_CONF 3 +#define MT2_MLME_TDLS_TEAR_DOWN 4 +#define MT2_PEER_TDLS_TEAR_DOWN 5 +#define MT2_PEER_TDLS_TRAFFIC_IND 6 /* for TDLS UAPSD */ +#define MT2_MLME_TDLS_PEER_PSM_REQ 7 +#define MT2_PEER_TDLS_PEER_PSM_REQ 8 +#define MT2_PEER_TDLS_PEER_PSM_RESP 9 +#define MT2_PEER_TDLS_TRAFFIC_RSP 10 /* for TDLS UAPSD */ +#define MT2_MLME_TDLS_DISCOVER_REQ 11 +#define MT2_PEER_TDLS_DISCOVER_REQ 12 +#define MT2_PEER_TDLS_DISCOVER_RSP 13 +#define MAX_TDLS_MSG 14 + +#define TDLS_FUNC_SIZE (MAX_TDLS_STATE * MAX_TDLS_MSG) + +#define TDLS_CHSW_MACHINE_BASE 0 +#define MT2_MLME_TDLS_CH_SWITCH_REQ 0 +#define MT2_MLME_TDLS_CH_SWITCH_RSP 1 +#define MT2_PEER_TDLS_CH_SWITCH_REQ 2 +#define MT2_PEER_TDLS_CH_SWITCH_RSP 3 +#define MT2_MLME_TDLS_CH_SWITCH_REQ_DISABLE 4 +#define MAX_TDLS_CHSW_MSG 5 + +#define TDLS_CHSW_FUNC_SIZE (MAX_TDLS_STATE * MAX_TDLS_CHSW_MSG) +#endif /* DOT11Z_TDLS_SUPPORT */ + +/* + WSC State machine: states, events, total function # +*/ +#ifdef WSC_INCLUDED +/*Messages for the WSC State machine */ +#define WSC_IDLE 0 +#define MAX_WSC_STATE 1 +#define WSC_FUNC_SIZE (MAX_WSC_STATE * MAX_WSC_MSG) + +#ifdef IWSC_SUPPORT +#define IWSC_IDLE 0 +#define IWSC_START 1 +#define IWSC_SCAN 2 +#define IWSC_WAIT_PIN 3 +#define IWSC_WAIT_JOIN 4 +#define MAX_IWSC_STATE 5 + +#define IWSC_MACHINE_BASE 0 +#define IWSC_MT2_MLME_START 0 +#define IWSC_MT2_MLME_STOP 1 +#define IWSC_MT2_MLME_SCAN_DONE 2 +#define IWSC_MT2_MLME_RECONNECT 3 +#define IWSC_MT2_PEER_ACTION_FRAME 4 +#define IWSC_MT2_PEER_PROBE_REQ 5 +#define IWSC_MT2_PEER_PROBE_RSP 6 +#define IWSC_MT2_PEER_PIN 7 +#define MAX_IWSC_MSG 8 + +#define IWSC_FUNC_SIZE (MAX_IWSC_STATE * MAX_IWSC_MSG) +#endif /* IWSC_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* + AP's CONTROL/CONNECT state machine: states, events, total function # +*/ +#define AP_CNTL_FUNC_SIZE 1 + +/* + AP's ASSOC state machine: states, events, total function # +*/ +#define AP_ASSOC_IDLE 0 +#define AP_MAX_ASSOC_STATE 1 + +#define AP_ASSOC_MACHINE_BASE 0 +#define APMT2_MLME_DISASSOC_REQ 0 +#define APMT2_PEER_DISASSOC_REQ 1 +#define APMT2_PEER_ASSOC_REQ 2 +#define APMT2_PEER_REASSOC_REQ 3 +#define APMT2_CLS3ERR 4 +#define AP_MAX_ASSOC_MSG 5 + +#define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG) + +/* + AP's AUTHENTICATION state machine: states, events, total function # +*/ +#define AP_AUTH_REQ_IDLE 0 +#define AP_MAX_AUTH_STATE 1 + +#define AP_AUTH_MACHINE_BASE 0 +#define APMT2_MLME_DEAUTH_REQ 0 +#define APMT2_CLS2ERR 1 +#define APMT2_PEER_DEAUTH 2 +#define APMT2_PEER_AUTH_REQ 3 +#define APMT2_PEER_AUTH_CONFIRM 4 +#define AP_MAX_AUTH_MSG 5 + +#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) + +/* + AP's SYNC state machine: states, events, total function # +*/ +#define AP_SYNC_IDLE 0 +#ifdef AP_SCAN_SUPPORT +#define AP_SCAN_LISTEN 1 +#define AP_MAX_SYNC_STATE 2 +#else +#define AP_MAX_SYNC_STATE 1 +#endif + +#define AP_SYNC_MACHINE_BASE 0 +#define APMT2_PEER_PROBE_REQ 0 +#define APMT2_PEER_BEACON 1 +#define APMT2_PEER_PROBE_RSP 2 +#ifdef AP_SCAN_SUPPORT +#define APMT2_MLME_SCAN_REQ 3 +#define APMT2_SCAN_TIMEOUT 4 +#define APMT2_MLME_SCAN_CNCL 5 +#ifdef CON_WPS +#define APMT2_MLME_SCAN_COMPLETE 6 +#define AP_MAX_SYNC_MSG 7 +#else +#define AP_MAX_SYNC_MSG 6 +#endif /* CON_WPS */ +#else +#define AP_MAX_SYNC_MSG 3 +#endif + +#define AP_SYNC_FUNC_SIZE (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG) + +#ifdef APCLI_SUPPORT +/*ApCli authentication state machine */ +#define APCLI_AUTH_REQ_IDLE 0 +#define APCLI_AUTH_WAIT_SEQ2 1 +#define APCLI_AUTH_WAIT_SEQ4 2 +#define APCLI_MAX_AUTH_STATE 3 + +#define APCLI_AUTH_MACHINE_BASE 0 +#define APCLI_MT2_MLME_AUTH_REQ 0 +#define APCLI_MT2_MLME_DEAUTH_REQ 1 +#define APCLI_MT2_PEER_AUTH_EVEN 2 +#define APCLI_MT2_PEER_DEAUTH 3 +#define APCLI_MT2_AUTH_TIMEOUT 4 +#define APCLI_MAX_AUTH_MSG 5 + +#define APCLI_AUTH_FUNC_SIZE (APCLI_MAX_AUTH_STATE * APCLI_MAX_AUTH_MSG) + +/*ApCli association state machine */ +#define APCLI_ASSOC_IDLE 0 +#define APCLI_ASSOC_WAIT_RSP 1 +#define APCLI_MAX_ASSOC_STATE 2 + +#define APCLI_ASSOC_MACHINE_BASE 0 +#define APCLI_MT2_MLME_ASSOC_REQ 0 +#define APCLI_MT2_MLME_DISASSOC_REQ 1 +#define APCLI_MT2_PEER_DISASSOC_REQ 2 +#define APCLI_MT2_PEER_ASSOC_RSP 3 +#define APCLI_MT2_ASSOC_TIMEOUT 4 +#define APCLI_MAX_ASSOC_MSG 5 + +#define APCLI_ASSOC_FUNC_SIZE (APCLI_MAX_ASSOC_STATE * APCLI_MAX_ASSOC_MSG) + +#define APCLI_MAX_PROBE_RETRY_NUM 4 + +/*ApCli sync state machine */ +#define APCLI_SYNC_IDLE 0 /* merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state */ +#define APCLI_JOIN_WAIT_PROBE_RSP 1 +#define APCLI_MAX_SYNC_STATE 2 + +#define APCLI_SYNC_MACHINE_BASE 0 +#define APCLI_MT2_MLME_PROBE_REQ 0 +#define APCLI_MT2_MLME_SCAN_REQ 1 +#define APCLI_MT2_PEER_PROBE_RSP 2 +#define APCLI_MT2_PEER_BEACON 3 +#define APCLI_MT2_PROBE_TIMEOUT 4 +#define APCLI_MAX_SYNC_MSG 5 + +#define APCLI_SYNC_FUNC_SIZE (APCLI_MAX_SYNC_STATE * APCLI_MAX_SYNC_MSG) + +/*ApCli ctrl state machine */ +#define APCLI_CTRL_DISCONNECTED 0 /* merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state */ +#define APCLI_CTRL_PROBE 1 +#define APCLI_CTRL_AUTH 2 +#define APCLI_CTRL_AUTH_2 3 +#define APCLI_CTRL_ASSOC 4 +#define APCLI_CTRL_DEASSOC 5 +#define APCLI_CTRL_CONNECTED 6 +#ifndef APCLI_CONNECTION_TRIAL +#define APCLI_MAX_CTRL_STATE 7 +#else +#undef APCLI_MAC_CTRL_STATE +#define APCLI_CTRL_TRIAL_TRIGGERED 7 +#define APCLI_MAX_CTRL_STATE 8 +#endif /* APCLI_CONNECTION_TRIAL */ + +#define APCLI_CTRL_MACHINE_BASE 0 +#define APCLI_CTRL_JOIN_REQ 0 +#define APCLI_CTRL_PROBE_RSP 1 +#define APCLI_CTRL_AUTH_RSP 2 +#define APCLI_CTRL_DISCONNECT_REQ 3 +#define APCLI_CTRL_PEER_DISCONNECT_REQ 4 +#define APCLI_CTRL_ASSOC_RSP 5 +#define APCLI_CTRL_DEASSOC_RSP 6 +#define APCLI_CTRL_JOIN_REQ_TIMEOUT 7 +#define APCLI_CTRL_AUTH_REQ_TIMEOUT 8 +#define APCLI_CTRL_ASSOC_REQ_TIMEOUT 9 +#define APCLI_CTRL_MT2_AUTH_REQ 10 +#define APCLI_CTRL_MT2_ASSOC_REQ 11 +#define APCLI_CTRL_SCAN_DONE 12 +#define APCLI_MIC_FAILURE_REPORT_FRAME 13 +#ifndef APCLI_CONNECTION_TRIAL +#define APCLI_MAX_CTRL_MSG 14 +#else +#undef APCLI_MAX_CTRL_MSG +#define APCLI_CTRL_TRIAL_CONNECT 14 +#define APCLI_MAX_CTRL_MSG 15 +#endif + +#define APCLI_CTRL_FUNC_SIZE (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG) + + +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +/* ============================================================================= */ + + +/* ACK policy of QOS Control field bit 6:5 */ +#define NORMAL_ACK 0x00 /* b6:5 = 00 */ +#define NO_ACK 0x20 /* b6:5 = 01 */ +#define NO_EXPLICIT_ACK 0x40 /* b6:5 = 10 */ +#define BLOCK_ACK 0x60 /* b6:5 = 11 */ + +#ifdef USB_BULK_BUF_ALIGMENT +#define BUF_ALIGMENT_RINGSIZE 6 /*BUF_ALIGMENT_RINGSIZE must >= 3 */ +#endif /* USB_BULK_BUF_ALIGMENT */ + + +/* STA_CSR4.field.TxResult */ +#define TX_RESULT_SUCCESS 0 +#define TX_RESULT_ZERO_LENGTH 1 +#define TX_RESULT_UNDER_RUN 2 +#define TX_RESULT_OHY_ERROR 4 +#define TX_RESULT_RETRY_FAIL 6 + + +/* MCS for CCK. BW.SGI.STBC are reserved */ +#define MCS_LONGP_RATE_1 0 /* long preamble CCK 1Mbps */ +#define MCS_LONGP_RATE_2 1 /* long preamble CCK 1Mbps */ +#define MCS_LONGP_RATE_5_5 2 +#define MCS_LONGP_RATE_11 3 +#define MCS_SHORTP_RATE_1 8 /* long preamble CCK 1Mbps. short is forbidden in 1Mbps */ +#define MCS_SHORTP_RATE_2 9 /* short preamble CCK 2Mbps */ +#define MCS_SHORTP_RATE_5_5 10 +#define MCS_SHORTP_RATE_11 11 +/* To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved */ +#define MCS_RATE_6 0 /* legacy OFDM */ +#define MCS_RATE_9 1 /* OFDM */ +#define MCS_RATE_12 2 /* OFDM */ +#define MCS_RATE_18 3 /* OFDM */ +#define MCS_RATE_24 4 /* OFDM */ +#define MCS_RATE_36 5 /* OFDM */ +#define MCS_RATE_48 6 /* OFDM */ +#define MCS_RATE_54 7 /* OFDM */ +/* HT */ +#define MCS_0 0 /* 1S */ +#define MCS_1 1 +#define MCS_2 2 +#define MCS_3 3 +#define MCS_4 4 +#define MCS_5 5 +#define MCS_6 6 +#define MCS_7 7 +#define MCS_8 8 /* 2S */ +#define MCS_9 9 +#define MCS_10 10 +#define MCS_11 11 +#define MCS_12 12 +#define MCS_13 13 +#define MCS_14 14 +#define MCS_15 15 +#define MCS_16 16 /* 3*3 */ +#define MCS_17 17 +#define MCS_18 18 +#define MCS_19 19 +#define MCS_20 20 +#define MCS_21 21 +#define MCS_22 22 +#define MCS_23 23 +#define MCS_32 32 +#define MCS_AUTO 33 + +#ifdef DOT11_VHT_AC +#define MCS_VHT_2SS_MCS9 0x29 +#define MCS_VHT_2SS_MCS8 0x28 +#define MCS_VHT_2SS_MCS7 0x27 +#define MCS_VHT_2SS_MCS6 0x26 +#define MCS_VHT_2SS_MCS5 0x25 +#define MCS_VHT_2SS_MCS4 0x24 +#define MCS_VHT_2SS_MCS3 0x23 +#define MCS_VHT_2SS_MCS2 0x22 +#define MCS_VHT_2SS_MCS1 0x21 +#define MCS_VHT_2SS_MCS0 0x20 + +#define MCS_VHT_1SS_MCS9 0x19 +#define MCS_VHT_1SS_MCS8 0x18 +#define MCS_VHT_1SS_MCS7 0x17 +#define MCS_VHT_1SS_MCS6 0x16 +#define MCS_VHT_1SS_MCS5 0x15 +#define MCS_VHT_1SS_MCS4 0x14 +#define MCS_VHT_1SS_MCS3 0x13 +#define MCS_VHT_1SS_MCS2 0x12 +#define MCS_VHT_1SS_MCS1 0x11 +#define MCS_VHT_1SS_MCS0 0x10 + +#define VHT_RATE_IDX_1SS_MCS0 0 +#define VHT_RATE_IDX_1SS_MCS1 1 +#define VHT_RATE_IDX_1SS_MCS2 2 +#define VHT_RATE_IDX_1SS_MCS3 3 +#define VHT_RATE_IDX_1SS_MCS4 4 +#define VHT_RATE_IDX_1SS_MCS5 5 +#define VHT_RATE_IDX_1SS_MCS6 6 +#define VHT_RATE_IDX_1SS_MCS7 7 +#define VHT_RATE_IDX_1SS_MCS8 8 +#define VHT_RATE_IDX_1SS_MCS9 9 + +#define VHT_RATE_IDX_2SS_MCS0 10 +#define VHT_RATE_IDX_2SS_MCS1 11 +#define VHT_RATE_IDX_2SS_MCS2 12 +#define VHT_RATE_IDX_2SS_MCS3 13 +#define VHT_RATE_IDX_2SS_MCS4 14 +#define VHT_RATE_IDX_2SS_MCS5 15 +#define VHT_RATE_IDX_2SS_MCS6 16 +#define VHT_RATE_IDX_2SS_MCS7 17 +#define VHT_RATE_IDX_2SS_MCS8 18 +#define VHT_RATE_IDX_2SS_MCS9 19 +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT +/* OID_HTPHYMODE */ +/* MODE */ +#define HTMODE_MM 0 +#define HTMODE_GF 1 +#endif /* DOT11_N_SUPPORT */ + +/* Fixed Tx MODE - HT, CCK or OFDM */ +#define FIXED_TXMODE_HT 0 +#define FIXED_TXMODE_CCK 1 +#define FIXED_TXMODE_OFDM 2 +#define FIXED_TXMODE_VHT 3 + +/* BW */ +#define BW_20 BAND_WIDTH_20 +#define BW_40 BAND_WIDTH_40 +#define BW_80 BAND_WIDTH_80 +#define BW_160 BAND_WIDTH_160 + +#define BW_10 BAND_WIDTH_10 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ + + + +#define RF_BW_20 1 +#define RF_BW_40 2 +#define RF_BW_10 4 +#define RF_BW_80 8 + +#define RF_MODE_CCK 1 +#define RF_MODE_OFDM 2 + +#ifdef DOT11_N_SUPPORT +#define HT_BW_20 0 +#define HT_BW_40 1 +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC +#define VHT_BW_2040 0 +#define VHT_BW_80 1 +#define VHT_BW_160 2 +#define VHT_BW_8080 3 +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT +/* SHORTGI */ +#define GI_400 GAP_INTERVAL_400 /* only support in HT mode */ +#define GI_BOTH GAP_INTERVAL_BOTH +#endif /* DOT11_N_SUPPORT */ +#define GI_800 GAP_INTERVAL_800 + +/* STBC */ +#define STBC_NONE 0 +#ifdef DOT11_N_SUPPORT +#define STBC_USE 1 /* limited use in rt2860b phy */ +#define RXSTBC_ONE 1 /* rx support of one spatial stream */ +#define RXSTBC_TWO 2 /* rx support of 1 and 2 spatial stream */ +#define RXSTBC_THR 3 /* rx support of 1~3 spatial stream */ +/* MCS FEEDBACK */ +#define MCSFBK_NONE 0 /* not support mcs feedback / */ +#define MCSFBK_RSV 1 /* reserved */ +#define MCSFBK_UNSOLICIT 2 /* only support unsolict mcs feedback */ +#define MCSFBK_MRQ 3 /* response to both MRQ and unsolict mcs feedback */ + +/* MIMO power safe */ +#define MMPS_STATIC 0 +#define MMPS_DYNAMIC 1 +#define MMPS_RSV 2 +#define MMPS_DISABLE 3 + +/* A-MSDU size */ +#define AMSDU_0 0 +#define AMSDU_1 1 + +#endif /* DOT11_N_SUPPORT */ + +/* MCS use 7 bits */ +#define TXRATEMIMO 0x80 +#define TXRATEMCS 0x7F +#define TXRATEOFDM 0x7F +#define RATE_1 0 +#define RATE_2 1 +#define RATE_5_5 2 +#define RATE_11 3 +#define RATE_6 4 /* OFDM */ +#define RATE_9 5 /* OFDM */ +#define RATE_12 6 /* OFDM */ +#define RATE_18 7 /* OFDM */ +#define RATE_24 8 /* OFDM */ +#define RATE_36 9 /* OFDM */ +#define RATE_48 10 /* OFDM */ +#define RATE_54 11 /* OFDM */ +#define RATE_FIRST_OFDM_RATE RATE_6 +#define RATE_LAST_OFDM_RATE RATE_54 +#define RATE_6_5 12 /* HT mix */ +#define RATE_13 13 /* HT mix */ +#define RATE_19_5 14 /* HT mix */ +#define RATE_26 15 /* HT mix */ +#define RATE_39 16 /* HT mix */ +#define RATE_52 17 /* HT mix */ +#define RATE_58_5 18 /* HT mix */ +#define RATE_65 19 /* HT mix */ +#define RATE_78 20 /* HT mix */ +#define RATE_104 21 /* HT mix */ +#define RATE_117 22 /* HT mix */ +#define RATE_130 23 /* HT mix */ +/*#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only */ +#define HTRATE_0 12 +#define RATE_FIRST_MM_RATE HTRATE_0 +#define RATE_FIRST_HT_RATE HTRATE_0 +#define RATE_LAST_HT_RATE HTRATE_0 + +/* pTxWI->txop */ +#define IFS_HTTXOP 0 /* The txop will be handles by ASIC. */ +#define IFS_PIFS 1 +#define IFS_SIFS 2 +#define IFS_BACKOFF 3 + +/* pTxD->RetryMode */ +#define LONG_RETRY 1 +#define SHORT_RETRY 0 + +/* Country Region definition */ +#define REGION_MINIMUM_BG_BAND 0 +#define REGION_0_BG_BAND 0 /* 1-11 */ +#define REGION_1_BG_BAND 1 /* 1-13 */ +#define REGION_2_BG_BAND 2 /* 10-11 */ +#define REGION_3_BG_BAND 3 /* 10-13 */ +#define REGION_4_BG_BAND 4 /* 14 */ +#define REGION_5_BG_BAND 5 /* 1-14 */ +#define REGION_6_BG_BAND 6 /* 3-9 */ +#define REGION_7_BG_BAND 7 /* 5-13 */ +#define REGION_31_BG_BAND 31 /* 5-13 */ +#define REGION_32_BG_BAND 32 /* 1 - 13 */ +#define REGION_33_BG_BAND 33 /* 1 - 14 */ +#define REGION_MAXIMUM_BG_BAND 7 + +#define REGION_MINIMUM_A_BAND 0 +#define REGION_0_A_BAND 0 /* 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 */ +#define REGION_1_A_BAND 1 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 */ +#define REGION_2_A_BAND 2 /* 36, 40, 44, 48, 52, 56, 60, 64 */ +#define REGION_3_A_BAND 3 /* 52, 56, 60, 64, 149, 153, 157, 161 */ +#define REGION_4_A_BAND 4 /* 149, 153, 157, 161, 165 */ +#define REGION_5_A_BAND 5 /* 149, 153, 157, 161 */ +#define REGION_6_A_BAND 6 /* 36, 40, 44, 48 */ +#define REGION_7_A_BAND 7 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173 */ +#define REGION_8_A_BAND 8 /* 52, 56, 60, 64 */ +#define REGION_9_A_BAND 9 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 */ +#define REGION_10_A_BAND 10 /* 36, 40, 44, 48, 149, 153, 157, 161, 165 */ +#define REGION_11_A_BAND 11 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 */ +#define REGION_12_A_BAND 12 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 */ +#define REGION_13_A_BAND 13 /* 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161 */ +#define REGION_14_A_BAND 14 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165 */ +#define REGION_15_A_BAND 15 /* 149, 153, 157, 161, 165, 169, 173 */ +#define REGION_16_A_BAND 16 /* 52, 56, 60, 64, 149, 153, 157, 161, 165 */ +#define REGION_17_A_BAND 17 +#define REGION_18_A_BAND 18 +#define REGION_19_A_BAND 19 +#define REGION_20_A_BAND 20 +#define REGION_21_A_BAND 21 +#define REGION_22_A_BAND 22 +#define REGION_MAXIMUM_A_BAND 37 + +/* The security mode definition in MAC register */ +#define CIPHER_NONE 0 +#define CIPHER_WEP64 1 +#define CIPHER_WEP128 2 +#define CIPHER_TKIP 3 +#define CIPHER_AES 4 +#define CIPHER_CKIP64 5 +#define CIPHER_CKIP128 6 +#define CIPHER_CKIP152 7 +#define CIPHER_SMS4 8 + + + +/* RC4 init value, used fro WEP & TKIP */ +#define PPPINITFCS32 0xffffffff /* Initial FCS value */ + +/* value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition */ +#define WPA_802_1X_PORT_SECURED 1 +#define WPA_802_1X_PORT_NOT_SECURED 2 + +#define PAIRWISE_KEY 1 +#define GROUP_KEY 2 + + + +/* Rate Adaptation timing */ +#define RA_RATE 5 /* RA every fifth 100msec period */ +#define RA_INTERVAL (RA_RATE*100) /* RA Interval in msec */ + +/* Rate Adaptation simpling interval setting */ +#define DEF_QUICK_RA_TIME_INTERVAL 100 + +#define DEF_RA_TIME_INTRVAL 500 + +/*definition of DRS */ +#define MAX_TX_RATE_INDEX 50 /* Maximum Tx Rate Table Index value */ + +/* pre-allocated free NDIS PACKET/BUFFER poll for internal usage */ +#define MAX_NUM_OF_FREE_NDIS_PACKET 128 + +/*Block ACK */ +#define MAX_TX_REORDERBUF 64 +#define MAX_RX_REORDERBUF 64 +#define DEFAULT_TX_TIMEOUT 30 +#define DEFAULT_RX_TIMEOUT 30 +#ifdef CONFIG_AP_SUPPORT +#define MAX_BARECI_SESSION 16 +#endif /* CONFIG_AP_SUPPORT */ + +/* definition of Recipient or Originator */ +#define I_RECIPIENT TRUE +#define I_ORIGINATOR FALSE + +#define DEFAULT_BBP_TX_POWER 0 +#define DEFAULT_RF_TX_POWER 5 +#define DEFAULT_BBP_TX_FINE_POWER_CTRL 0 + +#define MAX_INI_BUFFER_SIZE 10000 /* 4096 */ +#define MAX_PARAM_BUFFER_SIZE (2048) /* enough for ACL (18*64) */ + /*18 : the length of Mac address acceptable format "01:02:03:04:05:06;") */ + /*64 : MAX_NUM_OF_ACL_LIST */ + +#ifdef RT_BIG_ENDIAN +#define DIR_READ 0 +#define DIR_WRITE 1 +#define TYPE_TXD 0 +#define TYPE_RXD 1 +#define TYPE_TXINFO 0 +#define TYPE_RXINFO 1 +#define TYPE_TXWI 0 +#define TYPE_RXWI 1 +#endif + +/* ========================= AP rtmp_def.h =========================== */ +/* value domain for pAd->EventTab.Log[].Event */ +#define EVENT_RESET_ACCESS_POINT 0 /* Log = "hh:mm:ss Restart Access Point" */ +#define EVENT_ASSOCIATED 1 /* Log = "hh:mm:ss STA 00:01:02:03:04:05 associated" */ +#define EVENT_DISASSOCIATED 2 /* Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS" */ +#define EVENT_AGED_OUT 3 /* Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS" */ +#define EVENT_COUNTER_M 4 +#define EVENT_INVALID_PSK 5 +#define EVENT_MAX_EVENT_TYPE 6 +/* ==== end of AP rtmp_def.h ============ */ + +/* definition RSSI Number */ +#define RSSI_0 0 +#define RSSI_1 1 +#define RSSI_2 2 + +/* definition of radar detection */ +#define RD_NORMAL_MODE 0 /* Not found radar signal */ +#define RD_SWITCHING_MODE 1 /* Found radar signal, and doing channel switch */ +#define RD_SILENCE_MODE 2 /* After channel switch, need to be silence a while to ensure radar not found */ + +/*Driver defined cid for mapping status and command. */ +#define SLEEPCID 0x11 +#define WAKECID 0x22 +#define QUERYPOWERCID 0x33 +#define OWNERMCU 0x1 +#define OWNERCPU 0x0 + +/* MBSSID definition */ +#define ENTRY_NOT_FOUND 0xFF + +/* The signal threshold (RSSI) over new rate adaption */ +#define SIGNAL_THRESHOLD_OVER_NEW_RATE_ADAPT -65 + +/* After Linux 2.6.9, + * VLAN module use Private (from user) interface flags (netdevice->priv_flags). + * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h + * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c + * + * For this reason, we MUST use EVEN value in priv_flags + */ +#define INT_MAIN 0x0100 +#define INT_MBSSID 0x0200 +#define INT_WDS 0x0300 +#define INT_APCLI 0x0400 +#define INT_MESH 0x0500 +#define INT_P2P 0x0600 +#define INT_MONITOR 0x0700 + +#define ENTRY_NONE 0 +#define ENTRY_CLIENT 1 +#define ENTRY_WDS 2 +#define ENTRY_APCLI 3 +#define ENTRY_MESH 4 +#define ENTRY_DLS 5 +#define ENTRY_TDLS 6 +#define ENTRY_MCAST 7 +#define ENTRY_WDEV 8 + + +#define IS_ENTRY_NONE(_x) ((_x)->EntryType == ENTRY_NONE) +#define IS_ENTRY_CLIENT(_x) ((_x)->EntryType == ENTRY_CLIENT) +#define IS_ENTRY_WDS(_x) ((_x)->EntryType == ENTRY_WDS) +#define IS_ENTRY_APCLI(_x) ((_x)->EntryType == ENTRY_APCLI) +#define IS_ENTRY_MESH(_x) ((_x)->EntryType == ENTRY_MESH) +#define IS_ENTRY_DLS(_x) ((_x)->EntryType == ENTRY_DLS) +#define IS_ENTRY_TDLS(_x) ((_x)->EntryType == ENTRY_TDLS) +#ifdef CLIENT_WDS +#define IS_ENTRY_CLIWDS(_x) CLIENT_STATUS_TEST_FLAG((_x), fCLIENT_STATUS_CLI_WDS) +#endif /* CLIENT_WDS */ + +#define IS_VALID_ENTRY(_x) (((_x) != NULL) && ((_x)->EntryType != ENTRY_NONE)) + +#define SET_ENTRY_NONE(_x) ((_x)->EntryType = ENTRY_NONE) +#define SET_ENTRY_CLIENT(_x) ((_x)->EntryType = ENTRY_CLIENT) +#define SET_ENTRY_WDS(_x) ((_x)->EntryType = ENTRY_WDS) +#define SET_ENTRY_APCLI(_x) ((_x)->EntryType = ENTRY_APCLI) +#define SET_ENTRY_MESH(_x) ((_x)->EntryType = ENTRY_MESH) +#define SET_ENTRY_DLS(_x) ((_x)->EntryType = ENTRY_DLS) +#define SET_ENTRY_TDLS(_x) ((_x)->EntryType = ENTRY_TDLS) +#ifdef CLIENT_WDS +#define SET_ENTRY_CLIWDS(_x) CLIENT_STATUS_SET_FLAG((_x), fCLIENT_STATUS_CLI_WDS) +#endif /* CLIENT_WDS */ +#define SET_PKT_OPMODE_AP(_x) ((_x)->OpMode = OPMODE_AP) +#define SET_PKT_OPMODE_STA(_x) ((_x)->OpMode = OPMODE_STA) +#define IS_PKT_OPMODE_AP(_x) ((_x)->OpMode == OPMODE_AP) +#define IS_PKT_OPMODE_STA(_x) ((_x)->OpMode == OPMODE_STA) + +#define IS_OPMODE_AP(_x) ((_x)->OpMode == OPMODE_AP) +#define IS_OPMODE_STA(_x) ((_x)->OpMode == OPMODE_STA) + +#if (CONFIG_RT_FIRST_CARD == 7602 || CONFIG_RT_FIRST_CARD == 7612 || CONFIG_RT_FIRST_CARD == 7620) +#define INF_MAIN_DEV_NAME "ra" +#define INF_MBSSID_DEV_NAME "ra" +#define INF_WDS_DEV_NAME "wds" +#define INF_APCLI_DEV_NAME "apcli" +#define INF_MESH_DEV_NAME "mesh" +#define INF_P2P_DEV_NAME "p2p" +#define INF_MONITOR_DEV_NAME "mon" +#else +#define INF_MAIN_DEV_NAME "rai" +#define INF_MBSSID_DEV_NAME "rai" +#define INF_WDS_DEV_NAME "wdsi" +#define INF_APCLI_DEV_NAME "apclii" +#define INF_MESH_DEV_NAME "meshi" +#define INF_P2P_DEV_NAME "p2pi" +#define INF_MONITOR_DEV_NAME "moni" +#endif + +/* WEP Key TYPE */ +#define WEP_HEXADECIMAL_TYPE 0 +#define WEP_ASCII_TYPE 1 + +/* WIRELESS EVENTS definition */ +/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */ +#define IW_CUSTOM_MAX_LEN 255 /* In bytes */ + +/* For system event - start */ +#define IW_SYS_EVENT_FLAG_START 0x0200 +#define IW_ASSOC_EVENT_FLAG 0x0200 +#define IW_DISASSOC_EVENT_FLAG 0x0201 +#define IW_DEAUTH_EVENT_FLAG 0x0202 +#define IW_AGEOUT_EVENT_FLAG 0x0203 +#define IW_COUNTER_MEASURES_EVENT_FLAG 0x0204 +#define IW_REPLAY_COUNTER_DIFF_EVENT_FLAG 0x0205 +#define IW_RSNIE_DIFF_EVENT_FLAG 0x0206 +#define IW_MIC_DIFF_EVENT_FLAG 0x0207 +#define IW_ICV_ERROR_EVENT_FLAG 0x0208 +#define IW_MIC_ERROR_EVENT_FLAG 0x0209 +#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG 0x020A +#define IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG 0x020B +#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG 0x020C +#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG 0x020D +#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG 0x020E +#define IW_STA_LINKUP_EVENT_FLAG 0x020F +#define IW_STA_LINKDOWN_EVENT_FLAG 0x0210 +#define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211 +#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212 +#define IW_CHANNEL_CHANGE_EVENT_FLAG 0x0213 +#define IW_STA_MODE_EVENT_FLAG 0x0214 +#define IW_MAC_FILTER_LIST_EVENT_FLAG 0x0215 +#define IW_AUTH_REJECT_CHALLENGE_FAILURE 0x0216 +#define IW_SCANNING_EVENT_FLAG 0x0217 +#define IW_START_IBSS_FLAG 0x0218 +#define IW_JOIN_IBSS_FLAG 0x0219 +#define IW_SHARED_WEP_FAIL 0x021A +#define IW_WPS_END_EVENT_FLAG 0x021B +/* if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END */ +#define IW_SYS_EVENT_FLAG_END 0x021B +#define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1) +/* For system event - end */ + +#ifdef IDS_SUPPORT +/* For spoof attack event - start */ +#define IW_SPOOF_EVENT_FLAG_START 0x0300 +#define IW_CONFLICT_SSID_EVENT_FLAG 0x0300 +#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301 +#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG 0x0302 +#define IW_SPOOF_PROBE_RESP_EVENT_FLAG 0x0303 +#define IW_SPOOF_BEACON_EVENT_FLAG 0x0304 +#define IW_SPOOF_DISASSOC_EVENT_FLAG 0x0305 +#define IW_SPOOF_AUTH_EVENT_FLAG 0x0306 +#define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307 +#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308 +#define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309 +/* if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END */ +#define IW_SPOOF_EVENT_FLAG_END 0x0309 +#define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1) +/* For spoof attack event - end */ + +/* For flooding attack event - start */ +#define IW_FLOOD_EVENT_FLAG_START 0x0400 +#define IW_FLOOD_AUTH_EVENT_FLAG 0x0400 +#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401 +#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG 0x0402 +#define IW_FLOOD_PROBE_REQ_EVENT_FLAG 0x0403 +#define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404 +#define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405 +#define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406 +/* if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END */ +#define IW_FLOOD_EVENT_FLAG_END 0x0406 +#define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1) +/* For flooding attack - end */ +#endif /* IDS_SUPPORT */ + +#ifdef WSC_INCLUDED +/* For WSC wireless event - start */ +#define IW_WSC_EVENT_FLAG_START 0x0500 +#define IW_WSC_PBC_SESSION_OVERLAP 0x0500 +#define IW_WSC_REGISTRAR_SUPPORT_PBC 0x0501 +#define IW_WSC_REGISTRAR_SUPPORT_PIN 0x0502 +#define IW_WSC_STATUS_SUCCESS 0x0503 +#define IW_WSC_STATUS_FAIL 0x0504 +#define IW_WSC_2MINS_TIMEOUT 0x0505 +#define IW_WSC_SEND_EAPOL_START 0x0506 +#define IW_WSC_SEND_WSC_START 0x0507 +#define IW_WSC_SEND_M1 0x0508 +#define IW_WSC_SEND_M2 0x0509 +#define IW_WSC_SEND_M3 0x050a +#define IW_WSC_SEND_M4 0x050b +#define IW_WSC_SEND_M5 0x050c +#define IW_WSC_SEND_M6 0x050d +#define IW_WSC_SEND_M7 0x050e +#define IW_WSC_SEND_M8 0x050f +#define IW_WSC_SEND_DONE 0x0510 +#define IW_WSC_SEND_ACK 0x0511 +#define IW_WSC_SEND_NACK 0x0512 +#define IW_WSC_RECEIVE_WSC_START 0x0513 +#define IW_WSC_RECEIVE_M1 0x0514 +#define IW_WSC_RECEIVE_M2 0x0515 +#define IW_WSC_RECEIVE_M3 0x0516 +#define IW_WSC_RECEIVE_M4 0x0517 +#define IW_WSC_RECEIVE_M5 0x0518 +#define IW_WSC_RECEIVE_M6 0x0519 +#define IW_WSC_RECEIVE_M7 0x051a +#define IW_WSC_RECEIVE_M8 0x051b +#define IW_WSC_RECEIVE_DONE 0x051c +#define IW_WSC_RECEIVE_ACK 0x051d +#define IW_WSC_RECEIVE_NACK 0x051e +#define IW_WSC_MANY_CANDIDATE 0x051f +#define IW_WSC_NEXT_CANDIDATE 0x0520 +#define IW_WSC_T1_TIMER_TIMEOUT 0x0521 +#define IW_WSC_T2_TIMER_TIMEOUT 0x0522 +#define IW_WSC_EVENT_FLAG_END 0x0522 +#define IW_WSC_EVENT_TYPE_NUM (IW_WSC_EVENT_FLAG_END - IW_WSC_EVENT_FLAG_START + 1) +/* For WSC wireless event - end */ +#endif /* WSC_INCLUDED */ +/* End - WIRELESS EVENTS definition */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT +// For WSC wireless event - start +#define IW_IWSC_EVENT_FLAG_START 0x0600 +#define IW_IWSC_T1_TIMER_TIMEOUT 0x0600 +#define IW_IWSC_T2_TIMER_TIMEOUT 0x0601 +#define IW_IWSC_BECOME_REGISTRAR 0x0602 +#define IW_IWSC_BECOME_ENROLLEE 0x0603 +#define IW_IWSC_ENTRY_TIMER_TIMEOUT 0x0604 +#define IW_IWSC_EVENT_FLAG_END 0x0604 +#define IW_IWSC_EVENT_TYPE_NUM (IW_IWSC_EVENT_FLAG_END - IW_IWSC_EVENT_FLAG_START + 1) +/* For WSC wireless event - end */ +#endif /* IWSC_SUPPORT */ + +/* definition for DLS */ +#define MAX_NUM_OF_INIT_DLS_ENTRY 1 +#define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY + +/*Block ACK */ +#define MAX_TX_REORDERBUF 64 +#define MAX_RX_REORDERBUF 64 +#define DEFAULT_TX_TIMEOUT 30 +#define DEFAULT_RX_TIMEOUT 30 +#ifndef CONFIG_AP_SUPPORT +#define MAX_BARECI_SESSION 8 +#endif + +#ifndef IW_ESSID_MAX_SIZE +/* Maximum size of the ESSID and pAd->nickname strings */ +#define IW_ESSID_MAX_SIZE 32 +#endif +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MCAST_RATE_SPECIFIC +#define MCAST_DISABLE 0 +#define MCAST_CCK 1 +#define MCAST_OFDM 2 +#define MCAST_HTMIX 3 +#define MCAST_VHT 4 +#endif /* MCAST_RATE_SPECIFIC */ + +/* For AsicRadioOff/AsicRadioOn function */ +// TODO: shiang-usw, check those RADIO ON/OFF values here!!! +#define DOT11POWERSAVE 0 +#define GUIRADIO_OFF 1 +#define RTMP_HALT 2 +#define GUI_IDLE_POWER_SAVE 3 + +enum { + RESUME_RADIO_ON, + SUSPEND_RADIO_OFF, + MLME_RADIO_ON, + MLME_RADIO_OFF, + DOT11_RADIO_ON, + DOT11_RADIO_OFF, +}; + +/* -- */ + +/* definition for WpaSupport flag */ +#define WPA_SUPPLICANT_DISABLE 0x00 +#define WPA_SUPPLICANT_ENABLE 0x01 +#define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 0x02 +#define WPA_SUPPLICANT_ENABLE_WPS 0x80 + +#ifdef MICROWAVE_OVEN_SUPPORT +/* definition for mitigating microwave interference */ +#define MO_FALSE_CCA_TH 600 +#define MO_MEAS_PERIOD 0 /* 0 ~ 100 ms */ +#define MO_IDLE_PERIOD 1 /* 100 ~ 1000 ms */ +#endif /* MICROWAVE_OVEN_SUPPORT */ + +typedef enum _ETHER_BAND_BINDDING { + EtherTrafficBand2G, + EtherTrafficBand5G, +} ETHER_BAND_BINDDING, *PETHER_BAND_BINDDING; + +/* definition for Antenna Diversity flag */ +typedef enum { + ANT_DIVERSITY_DISABLE, + ANT_DIVERSITY_ENABLE , + ANT_FIX_ANT0, + ANT_FIX_ANT1, + ANT_SW_DIVERSITY_ENABLE, + ANT_HW_DIVERSITY_ENABLE, + ANT_DIVERSITY_DEFAULT +}ANT_DIVERSITY_TYPE; + +enum IEEE80211_BAND { + IEEE80211_BAND_2G, + IEEE80211_BAND_5G, + IEEE80211_BAND_NUMS +}; + +#ifdef CONFIG_SWITCH_CHANNEL_OFFLOAD +#define CHANNEL_SWITCH_OFFLOAD 0x68 +#define CHANNEL_MCU_READY 0x7064 +#endif /* CONFIG_SWITCH_CHANNEL_OFFLOAD */ + +#if defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) +#define HW_NULL_FRAME_1_OFFSET 0x7700 +#define HW_NULL_FRAME_2_OFFSET 0x7780 + +enum { + EDCA_AC0_DEQUEUE_DISABLE = (1 << 0), + EDCA_AC1_DEQUEUE_DISABLE = (1 << 1), + EDCA_AC2_DEQUEUE_DISABLE = (1 << 2), + EDCA_AC3_DEQUEUE_DISBALE = (1 << 3), + HCCA_DEQUEUE_DISABLE = (1 << 4) +}; + +enum { + HCCA_TO_EDCA, + EDCA_TO_HCCA = 0x55 +}; + +#define MUL_CHANNEL_ENABLE 0x77 +#define HCCA_TIMEOUT 400 +#define EDCA_TIMEOUT 400 +#endif /* defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) */ + + +#define ABS(_x, _y) ((_x) > (_y)) ? ((_x) -(_y)) : ((_y) -(_x)) +#define ABS_One(_x) ((_x) < 0x0) ? (0x0 - (_x)) : (_x) + +#define A2Dec(_X, _p) \ +{ \ + UCHAR *p; \ + _X = 0; \ + p = _p; \ + while (((*p >= '0') && (*p <= '9'))) \ + { \ + if ((*p >= '0') && (*p <= '9')) \ + _X = _X * 10 + *p - 48; \ + p++; \ + } \ +} + +#define A2Hex(_X, _p) \ +do{ \ + char *__p; \ + (_X) = 0; \ + __p = (char *)(_p); \ + while (((*__p >= 'a') && (*__p <= 'f')) || ((*__p >= 'A') && (*__p <= 'F')) || ((*__p >= '0') && (*__p <= '9'))) \ + { \ + if ((*__p >= 'a') && (*__p <= 'f')) \ + (_X) = (_X) * 16 + *__p - 87; \ + else if ((*__p >= 'A') && (*__p <= 'F')) \ + (_X) = (_X) * 16 + *__p - 55; \ + else if ((*__p >= '0') && (*__p <= '9')) \ + (_X) = (_X) * 16 + *__p - 48; \ + __p++; \ + } \ +}while(0) + +/* ========================================================================== */ +/* + The full range (1-4,095) of VLAN IDs must be supported by the 802.1Q + implementation. + VLAN ID 0 is reserved. +*/ + +#define RT_VLAN_8023_HEADER_COPY(__pAd, __VLAN_VID, __VLAN_Priority, \ + __pHeader8023, __HdrLen, __pData, \ + __FromWhichBSSID, __TPID) \ +{ \ + VLAN_8023_Header_Copy(__VLAN_VID, __VLAN_Priority, \ + __pHeader8023, __HdrLen, __pData, \ + __FromWhichBSSID, __TPID); \ +} + + +#define RT_VLAN_PKT_DUPLICATE(__pPacket, __pAd, __VLAN_VID, __VLAN_Priority,\ + __pHeader8023, __HdrLen, __pData, \ + __DataSize, __FromWhichBSSID, __TPID) \ +{ \ + __pPacket = duplicate_pkt_with_VLAN( \ + get_netdev_from_bssid(__pAd, __FromWhichBSSID), \ + __VLAN_VID, \ + __VLAN_Priority, \ + __pHeader8023, __HdrLen, __pData, __DataSize, \ + __FromWhichBSSID, __TPID); \ +} + + +#define RT_80211_TO_8023_PACKET(__pAd, __VLAN_VID, __VLAN_Priority, \ + __pRxBlk, __pHeader802_3, \ + __FromWhichBSSID, __TPID) \ +{ \ + wlan_802_11_to_802_3_packet( \ + get_netdev_from_bssid(__pAd, __FromWhichBSSID), \ + __pRxBlk->OpMode, \ + __VLAN_VID, __VLAN_Priority, \ + __pRxBlk->pRxPacket, __pRxBlk->pData, __pRxBlk->DataSize, \ + __pHeader802_3, __FromWhichBSSID, __TPID); \ +} + +#define RTMP_L2_FRAME_TX_ACTION(__pAd, __ApIdx, __FrameBuf, __FrameLen) \ + RTMPL2FrameTxAction(__pAd, get_netdev_from_bssid(__pAd, __ApIdx), \ + announce_802_3_packet, __ApIdx, __FrameBuf, __FrameLen, __pAd->OpMode) + +#define RTMP_DUPLICATE_PACKET(__pAd, __pPacket, __FromWhichBSSID) \ + DuplicatePacket(get_netdev_from_bssid(__pAd, __FromWhichBSSID), \ + __pPacket, __FromWhichBSSID) + +#define RTMP_UPDATE_OS_PACKET_INFO(__pAd, __pRxBlk, __FromWhichBSSID) \ + RtmpOsPktInit(__pRxBlk->pRxPacket, \ + get_netdev_from_bssid(__pAd, __FromWhichBSSID), \ + __pRxBlk->pData, __pRxBlk->DataSize); + +#ifdef SYSTEM_LOG_SUPPORT +/* + RTMPSendWirelessEvent --> RtmpOsSendWirelessEvent --> RtmpDrvSendWirelessEvent +*/ +#define RTMPSendWirelessEvent(__pAd, __Event_flag, __pAddr, __BssIdx, __Rssi) \ + RtmpOsSendWirelessEvent(__pAd, __Event_flag, __pAddr, __BssIdx, __Rssi, \ + RtmpDrvSendWirelessEvent); +#else +#define RTMPSendWirelessEvent(__pAd, __Event_flag, __pAddr, __BssIdx, __Rssi) +#endif /* SYSTEM_LOG_SUPPORT */ + +#define RTMP_OS_TASK_INIT(__pTask, __pTaskName, __pAd) \ + RtmpOSTaskInit(__pTask, __pTaskName, __pAd, &(__pAd)->RscTaskMemList, &(__pAd)->RscSemMemList); + +#endif /* __RTMP_DEF_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_dot11.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_dot11.h new file mode 100644 index 000000000..fe8633e23 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_dot11.h @@ -0,0 +1,109 @@ +/* + +*/ + +#ifndef __DOT11_BASE_H__ +#define __DOT11_BASE_H__ + +#include "rtmp_type.h" +#include "dot11_base.h" +#include "dot11i_wpa.h" + +#ifdef DOT11_N_SUPPORT +#include "dot11n_ht.h" + +#ifdef DOT11_VHT_AC +#include "dot11ac_vht.h" +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "dot11k_rrm.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef TXBF_SUPPORT +/* CSI/Steering values */ +#define DOT11N_BF_FB_NONE 0 +#define DOT11N_BF_FB_CSI 1 +#define DOT11N_BF_FB_NOCOMP 2 +#define DOT11N_BF_FB_COMP 3 +#endif /* TXBF_SUPPORT */ + +/* 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. */ +typedef struct GNU_PACKED _HT_CONTROL{ +#ifdef RT_BIG_ENDIAN + UINT32 RDG:1; + UINT32 ACConstraint:1; + UINT32 rsv2:5; + UINT32 NDPAnnounce:1; + UINT32 CSISTEERING:2; + UINT32 rsv1:2; + UINT32 CalSeq:2; + UINT32 CalPos:2; + UINT32 MFBorASC:7; + UINT32 MFSI:3; + UINT32 MSI:3; + UINT32 MRQ:1; + UINT32 TRQ:1; + UINT32 vht:1; +#else + UINT32 vht:1; /* indicate for VHT variant or HT variant */ + UINT32 TRQ:1; /*sounding request */ + UINT32 MRQ:1; /*MCS feedback. Request for a MCS feedback */ + UINT32 MSI:3; /*MCS Request, MRQ Sequence identifier */ + UINT32 MFSI:3; /*SET to the received value of MRS. 0x111 for unsolicited MFB. */ + UINT32 MFBorASC:7; /*Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available */ + UINT32 CalPos:2; /* calibration position */ + UINT32 CalSeq:2; /*calibration sequence */ + UINT32 rsv1:2; /* Reserved */ + UINT32 CSISTEERING:2; /*CSI/ STEERING */ + UINT32 NDPAnnounce:1; /* ZLF announcement */ + UINT32 rsv2:5; /*calibration sequence */ + UINT32 ACConstraint:1; /*feedback request */ + UINT32 RDG:1; /*RDG / More PPDU */ +#endif /* !RT_BIG_ENDIAN */ +} HT_CONTROL, *PHT_CONTROL; + +/* 2-byte QOS CONTROL field */ +typedef struct GNU_PACKED _QOS_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT Txop_QueueSize:8; + USHORT AMsduPresent:1; + USHORT AckPolicy:2; /*0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA */ + USHORT EOSP:1; + USHORT TID:4; +#else + USHORT TID:4; + USHORT EOSP:1; + USHORT AckPolicy:2; /*0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA */ + USHORT AMsduPresent:1; + USHORT Txop_QueueSize:8; +#endif /* !RT_BIG_ENDIAN */ +} QOS_CONTROL, *PQOS_CONTROL; + + +typedef struct GNU_PACKED _AC_PARAM_RECORD{ + UINT8 aci_aifsn; + UINT8 ecw_max:4; + UINT8 ecw_min: 4; + UINT16 txop_limit; +}AC_PARAM_RECORD; + + +typedef struct GNU_PACKED _PSPOLL_FRAME { + FRAME_CONTROL FC; + USHORT Aid; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Ta[MAC_ADDR_LEN]; +} PSPOLL_FRAME, *PPSPOLL_FRAME; + + +typedef struct GNU_PACKED _RTS_FRAME { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; +} RTS_FRAME, *PRTS_FRAME; + +#endif /* __DOT11_BASE_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_iface.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_iface.h new file mode 100644 index 000000000..6243b5a4e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_iface.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * 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: + rt_iface.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RTMP_IFACE_H__ +#define __RTMP_IFACE_H__ + +#ifdef RTMP_PCI_SUPPORT +#include "iface/rtmp_pci.h" +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#include "iface/rtmp_rbs.h" +#endif /* RTMP_RBUS_SUPPORT */ + + +typedef struct _INF_PCI_CONFIG_ { + unsigned long CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; +} INF_PCI_CONFIG; + +typedef struct _INF_USB_CONFIG_ { + unsigned char BulkInEpAddr; /* bulk-in endpoint address */ + unsigned char BulkOutEpAddr[6]; /* bulk-out endpoint address */ +} INF_USB_CONFIG; + +typedef struct _INF_RBUS_CONFIG_ { + unsigned long csr_addr; + unsigned int irq; +} INF_RBUS_CONFIG; + + +typedef union _RTMP_INF_CONFIG_ { + struct _INF_PCI_CONFIG_ pciConfig; + struct _INF_USB_CONFIG_ usbConfig; + struct _INF_RBUS_CONFIG_ rbusConfig; +} RTMP_INF_CONFIG; + +#endif /* __RTMP_IFACE_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_os.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_os.h new file mode 100644 index 000000000..85cac0fb0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_os.h @@ -0,0 +1,143 @@ +/**************************************************************************** + * 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: + rtmp_os.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RTMP_OS_H__ +#define __RTMP_OS_H__ + +/* Driver Operators */ +typedef int (*RTMP_PRINTK)(const char *ftm, ...); +typedef int (*RTMP_SNPRINTF)(char *, ULONG, const char *ftm, ...); + +typedef struct _RTMP_OS_ABL_OPS { + int (*ra_printk)(const char *ftm, ...); + int (*ra_snprintf)(char *, ULONG, const char *ftm, ...); +} RTMP_OS_ABL_OPS; + +extern RTMP_OS_ABL_OPS *pRaOsOps; + +#ifndef CONFIG_RTPCI_AP_RF_OFFSET +#define CONFIG_RTPCI_AP_RF_OFFSET 0 +#endif + +#ifdef LINUX +#ifndef OS_ABL_FUNC_SUPPORT +#include "os/rt_linux.h" + +#else + +#ifdef RTMP_MODULE_OS +/* for util/netif */ +#include "os/rt_linux.h" +#else +/* for core */ +#include "os/rt_drv.h" +#endif /* RTMP_MODULE_OS */ +#endif /* OS_ABL_FUNC_SUPPORT */ +#endif /* LINUX */ + + + + + +// TODO: shiang, temporary put it here! +#include "os/pkt_meta.h" + +/* + This data structure mainly strip some callback function defined in + "struct net_device" in kernel source "include/linux/netdevice.h". + + The definition of this data structure may various depends on different + OS. Use it carefully. +*/ +typedef struct _RTMP_OS_NETDEV_OP_HOOK_ { + void *open; + void *stop; + void *xmit; + void *ioctl; + void *get_stats; + void *priv; + void *get_wstats; + void *iw_handler; + void *wdev; + int priv_flags; + unsigned char devAddr[6]; + unsigned char devName[16]; + unsigned char needProtcted; +} RTMP_OS_NETDEV_OP_HOOK, *PRTMP_OS_NETDEV_OP_HOOK; + + +typedef enum _RTMP_TASK_STATUS_ { + RTMP_TASK_STAT_UNKNOWN = 0, + RTMP_TASK_STAT_INITED = 1, + RTMP_TASK_STAT_RUNNING = 2, + RTMP_TASK_STAT_STOPED = 4, +} RTMP_TASK_STATUS; +#define RTMP_TASK_CAN_DO_INSERT (RTMP_TASK_STAT_INITED |RTMP_TASK_STAT_RUNNING) + +#define RTMP_OS_TASK_NAME_LEN 16 + +#if defined(RTMP_MODULE_OS) || !defined(OS_ABL_FUNC_SUPPORT) +/* used in UTIL/NETIF module */ +typedef struct _RTMP_OS_TASK_ { + char taskName[RTMP_OS_TASK_NAME_LEN]; + void *priv; + /*unsigned long taskFlags; */ + RTMP_TASK_STATUS taskStatus; +#ifndef KTHREAD_SUPPORT + RTMP_OS_SEM taskSema; + RTMP_OS_PID taskPID; + struct completion taskComplete; +#endif + unsigned char task_killed; +#ifdef KTHREAD_SUPPORT + struct task_struct *kthread_task; + wait_queue_head_t kthread_q; + BOOLEAN kthread_running; +#endif +} OS_TASK; +#endif /* RTMP_MODULE_OS || ! OS_ABL_FUNC_SUPPORT */ + + +int RtmpOSIRQRequest(PNET_DEV pNetDev); + + +#ifndef OS_ABL_SUPPORT +#define RTMP_MATOpsInit(__pAd) +#define RTMP_MATPktRxNeedConvert(__pAd, __pDev) \ + MATPktRxNeedConvert(__pAd, __pDev) +#define RTMP_MATEngineRxHandle(__pAd, __pPkt, __InfIdx) \ + MATEngineRxHandle(__pAd, __pPkt, __InfIdx) +#else + +#define RTMP_MATOpsInit(__pAd) \ + (__pAd)->MATPktRxNeedConvert = MATPktRxNeedConvert; \ + (__pAd)->MATEngineRxHandle = MATEngineRxHandle; +#define RTMP_MATPktRxNeedConvert(__pAd, __pDev) \ + ((__pAd)->MATPktRxNeedConvert(__pAd, __pDev)) +#define RTMP_MATEngineRxHandle(__pAd, __pPkt, __InfIdx) \ + ((__pAd)->MATEngineRxHandle(__pAd, __pPkt, __InfIdx)) +#endif /* OS_ABL_SUPPORT */ + +#endif /* __RMTP_OS_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_osabl.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_osabl.h new file mode 100644 index 000000000..36cf4a91f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_osabl.h @@ -0,0 +1,69 @@ +/**************************************************************************** + + Module Name: + OS/rtmp_osabl.h + + Abstract: + Some structure/definitions for OS ABL function. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RTMP_OS_ABL_H__ +#define __RTMP_OS_ABL_H__ + +#ifdef OS_ABL_FUNC_SUPPORT + +#ifdef OS_ABL_OS_PCI_SUPPORT +#ifndef RTMP_MAC_PCI +#define RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ +#ifndef RTMP_PCI_SUPPORT +#define RTMP_PCI_SUPPORT +#endif /* RTMP_PCI_SUPPORT */ +#endif /* OS_ABL_OS_PCI_SUPPORT */ + +#ifdef OS_ABL_OS_USB_SUPPORT +#include + +#define RTMP_MAC_USB +#define RTMP_USB_SUPPORT +#endif /* OS_ABL_OS_USB_SUPPORT */ + +#ifdef OS_ABL_OS_RBUS_SUPPORT +#ifndef RTMP_RBUS_SUPPORT +#define RTMP_RBUS_SUPPORT +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* OS_ABL_OS_RBUS_SUPPORT */ + +#ifdef OS_ABL_OS_AP_SUPPORT +#ifndef CONFIG_AP_SUPPORT +#define CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ +#endif /* OS_ABL_OS_AP_SUPPORT */ + +#ifdef OS_ABL_OS_STA_SUPPORT +#ifndef CONFIG_STA_SUPPORT +#define CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ +#endif /* OS_ABL_OS_STA_SUPPORT */ + +/* AP & STA con-current */ +#undef RT_CONFIG_IF_OPMODE_ON_AP +#undef RT_CONFIG_IF_OPMODE_ON_STA + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) if (__OpMode == OPMODE_AP) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) if (__OpMode == OPMODE_STA) +#else +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) +#endif + +#endif /* OS_ABL_FUNC_SUPPORT */ + +#endif /* __RTMP_OS_ABL_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_timer.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_timer.h new file mode 100644 index 000000000..947d95891 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_timer.h @@ -0,0 +1,274 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2008, 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_timer.h + + Abstract: + Ralink Wireless Driver timer related data structures and delcarations + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Shiang Tu Aug-28-2008 init version + +*/ + +#ifndef __RTMP_TIMER_H__ +#define __RTMP_TIMER_H__ + +#include "rtmp_os.h" + +#define DECLARE_TIMER_FUNCTION(_func) \ + void rtmp_timer_##_func(unsigned long data) + +#define GET_TIMER_FUNCTION(_func) \ + (PVOID)rtmp_timer_##_func + +/* ----------------- Timer Related MARCO ---------------*/ +/* In some os or chipset, we have a lot of timer functions and will read/write register, */ +/* it's not allowed in Linux USB sub-system to do it ( because of sleep issue when */ +/* submit to ctrl pipe). So we need a wrapper function to take care it. */ + +#ifdef RTMP_TIMER_TASK_SUPPORT +typedef VOID( + *RTMP_TIMER_TASK_HANDLE) ( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +typedef struct _RALINK_TIMER_STRUCT { + RTMP_OS_TIMER TimerObj; /* Ndis Timer object */ + BOOLEAN Valid; /* Set to True when call RTMPInitTimer */ + BOOLEAN State; /* True if timer cancelled */ + BOOLEAN PeriodicType; /* True if timer is periodic timer */ + BOOLEAN Repeat; /* True if periodic timer */ + ULONG TimerValue; /* Timer value in milliseconds */ + ULONG cookie; /* os specific object */ + void *pAd; +#ifdef RTMP_TIMER_TASK_SUPPORT + RTMP_TIMER_TASK_HANDLE handle; +#endif /* RTMP_TIMER_TASK_SUPPORT */ +} RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT; + + +#ifdef RTMP_TIMER_TASK_SUPPORT +typedef struct _RTMP_TIMER_TASK_ENTRY_ { + RALINK_TIMER_STRUCT *pRaTimer; + struct _RTMP_TIMER_TASK_ENTRY_ *pNext; +} RTMP_TIMER_TASK_ENTRY; + +#define TIMER_QUEUE_SIZE_MAX 128 +typedef struct _RTMP_TIMER_TASK_QUEUE_ { + unsigned int status; + unsigned char *pTimerQPoll; + RTMP_TIMER_TASK_ENTRY *pQPollFreeList; + RTMP_TIMER_TASK_ENTRY *pQHead; + RTMP_TIMER_TASK_ENTRY *pQTail; +} RTMP_TIMER_TASK_QUEUE; + +#define BUILD_TIMER_FUNCTION(_func) \ +void rtmp_timer_##_func(unsigned long data) \ +{ \ + PRALINK_TIMER_STRUCT _pTimer = (PRALINK_TIMER_STRUCT)data; \ + RTMP_TIMER_TASK_ENTRY *_pQNode; \ + RTMP_ADAPTER *_pAd; \ + \ + _pTimer->handle = _func; \ + _pAd = (RTMP_ADAPTER *)_pTimer->pAd; \ + _pQNode = RtmpTimerQInsert(_pAd, _pTimer); \ + if ((_pQNode == NULL) && (_pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT)) \ + RTMP_OS_Add_Timer(&_pTimer->TimerObj, OS_HZ); \ +} +#else /* !RTMP_TIMER_TASK_SUPPORT */ +#define BUILD_TIMER_FUNCTION(_func) \ +void rtmp_timer_##_func(unsigned long data) \ +{ \ + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) data; \ + \ + _func(NULL, (PVOID) pTimer->cookie, NULL, pTimer); \ + if (pTimer->Repeat) \ + RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); \ +} +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +DECLARE_TIMER_FUNCTION(MlmePeriodicExec); +DECLARE_TIMER_FUNCTION(MlmeRssiReportExec); +DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout); +DECLARE_TIMER_FUNCTION(APSDPeriodicExec); +DECLARE_TIMER_FUNCTION(EnqueueStartForPSKExec); + +#ifdef TXBF_SUPPORT +DECLARE_TIMER_FUNCTION(APTxSounding); +#endif /*TXBF_SUPPORT*/ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT +DECLARE_TIMER_FUNCTION(Adhoc_WpaRetryExec); +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT +DECLARE_TIMER_FUNCTION(PMF_SAQueryTimeOut); +DECLARE_TIMER_FUNCTION(PMF_SAQueryConfirmTimeOut); +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(APDetectOverlappingExec); + +#ifdef DOT11N_DRAFT3 +DECLARE_TIMER_FUNCTION(Bss2040CoexistTimeOut); +#endif /* DOT11N_DRAFT3 */ + +DECLARE_TIMER_FUNCTION(GREKEYPeriodicExec); +DECLARE_TIMER_FUNCTION(CMTimerExec); +DECLARE_TIMER_FUNCTION(WPARetryExec); +#ifdef AP_SCAN_SUPPORT +DECLARE_TIMER_FUNCTION(APScanTimeout); +#endif /* AP_SCAN_SUPPORT */ +DECLARE_TIMER_FUNCTION(APQuickResponeForRateUpExec); + +#ifdef IDS_SUPPORT +DECLARE_TIMER_FUNCTION(RTMPIdsPeriodicExec); +#endif /* IDS_SUPPORT */ + +#ifdef DROP_MASK_SUPPORT +DECLARE_TIMER_FUNCTION(drop_mask_timer_action); +#endif /* DROP_MASK_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +DECLARE_TIMER_FUNCTION(FT_KDP_InfoBroadcast); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +DECLARE_TIMER_FUNCTION(BeaconTimeout); +DECLARE_TIMER_FUNCTION(ScanTimeout); +DECLARE_TIMER_FUNCTION(AuthTimeout); +DECLARE_TIMER_FUNCTION(AssocTimeout); +DECLARE_TIMER_FUNCTION(ReassocTimeout); +DECLARE_TIMER_FUNCTION(DisassocTimeout); +DECLARE_TIMER_FUNCTION(LinkDownExec); +DECLARE_TIMER_FUNCTION(StaQuickResponeForRateUpExec); +DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); + +#ifdef RTMP_PCI_SUPPORT +DECLARE_TIMER_FUNCTION(PsPollWakeExec); +#ifdef PCIE_PS_SUPPORT +DECLARE_TIMER_FUNCTION(RadioOnExec); +#endif /* PCIE_PS_SUPPORT */ +#endif /* RTMP_PCI_SUPPORT */ +#ifdef QOS_DLS_SUPPORT +DECLARE_TIMER_FUNCTION(DlsTimeoutAction); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +DECLARE_TIMER_FUNCTION(TDLS_OffChExpired); +DECLARE_TIMER_FUNCTION(TDLS_BaseChExpired); +DECLARE_TIMER_FUNCTION(TDLS_LinkTimeoutAction); +DECLARE_TIMER_FUNCTION(TDLS_ChannelSwitchTimeAction); +DECLARE_TIMER_FUNCTION(TDLS_ChannelSwitchTimeOutAction); +DECLARE_TIMER_FUNCTION(TDLS_DisablePeriodChannelSwitchAction); +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +DECLARE_TIMER_FUNCTION(FT_OTA_AuthTimeout); +DECLARE_TIMER_FUNCTION(FT_OTD_TimeoutAction); +#endif /* DOT11R_FT_SUPPORT */ + + +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef TXBF_SUPPORT +DECLARE_TIMER_FUNCTION(eTxBfProbeTimerExec); +#endif // TXBF_SUPPORT // + +#ifdef WSC_INCLUDED +DECLARE_TIMER_FUNCTION(WscEAPOLTimeOutAction); +DECLARE_TIMER_FUNCTION(Wsc2MinsTimeOutAction); +DECLARE_TIMER_FUNCTION(WscUPnPMsgTimeOutAction); +DECLARE_TIMER_FUNCTION(WscM2DTimeOutAction); +DECLARE_TIMER_FUNCTION(WscPBCTimeOutAction); +DECLARE_TIMER_FUNCTION(WscScanTimeOutAction); +DECLARE_TIMER_FUNCTION(WscProfileRetryTimeout); +#ifdef WSC_LED_SUPPORT +DECLARE_TIMER_FUNCTION(WscLEDTimer); +DECLARE_TIMER_FUNCTION(WscSkipTurnOffLEDTimer); +#endif /* WSC_LED_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(WscUpdatePortCfgTimeout); +#ifdef WSC_V2_SUPPORT +DECLARE_TIMER_FUNCTION(WscSetupLockTimeout); +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef IWSC_SUPPORT +DECLARE_TIMER_FUNCTION(IWSC_T1TimerAction); +DECLARE_TIMER_FUNCTION(IWSC_T2TimerAction); +DECLARE_TIMER_FUNCTION(IWSC_EntryTimerAction); +DECLARE_TIMER_FUNCTION(IWSC_DevQueryAction); +#endif /* IWSC_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#ifdef CONFIG_HOTSPOT +#ifdef CONFIG_STA_SUPPORT +DECLARE_TIMER_FUNCTION(GASResponseTimeout); +DECLARE_TIMER_FUNCTION(GASCBDelayTimeout); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(PostReplyTimeout); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CONFIG_HOTSPOT */ + + + +#ifdef RT_CFG80211_P2P_SUPPORT +DECLARE_TIMER_FUNCTION(CFG80211_P2PCTWindowTimer); +DECLARE_TIMER_FUNCTION(CFG80211_P2pSwNoATimeOut); +DECLARE_TIMER_FUNCTION(CFG80211_P2pPreAbsenTimeOut); +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#if defined(BAND_STEERING) && !defined(BNDSTRG_DAEMON) +DECLARE_TIMER_FUNCTION(BndStrg_PeriodicExec); +#endif /* BAND_STEERING && !BNDSTRG_DAEMON */ + +#ifdef RALINK_ATE +DECLARE_TIMER_FUNCTION(ATEPeriodicExec); +#endif /* RALINK_ATE */ + +#ifdef PEER_DELBA_TX_ADAPT +DECLARE_TIMER_FUNCTION(PeerDelBATxAdaptTimeOut); +#endif /* PEER_DELBA_TX_ADAPT */ + +#ifdef APCLI_SUPPORT +DECLARE_TIMER_FUNCTION(ApCliWpaDisassocApAndBlockAssoc); +#endif /* APCLI_SUPPORT */ +#if defined (ED_MONITOR) && defined (ED_SMART) +DECLARE_TIMER_FUNCTION(ed_testing_timeout); +#endif /*ED_MONITOR*/ + +#ifdef RTMP_MAC_PCI +DECLARE_TIMER_FUNCTION(TxDoneCleanupExec); +#endif + +#endif /* __RTMP_TIMER_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_type.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_type.h new file mode 100644 index 000000000..caa58ca7b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/rtmp_type.h @@ -0,0 +1,194 @@ +/* + *************************************************************************** + * 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_type.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 1-2-2004 +*/ + +#ifndef __RTMP_TYPE_H__ +#define __RTMP_TYPE_H__ + + + +#ifndef GNU_PACKED +#define GNU_PACKED __attribute__ ((packed)) +#endif /* GNU_PACKED */ + + +#ifdef LINUX +/* Put platform dependent declaration here */ +/* For example, linux type definition */ +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned long long UINT64; +typedef short INT16; +typedef int INT32; +typedef long long INT64; + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; +#endif /* LINUX */ + +typedef unsigned char *PUINT8; +typedef unsigned short *PUINT16; +typedef unsigned int *PUINT32; +typedef unsigned long long *PUINT64; +typedef int *PINT32; +typedef long long *PINT64; + +/* modified for fixing compile warning on Sigma 8634 platform */ +typedef char STRING; + +typedef signed char CHAR; + +typedef signed short SHORT; +typedef signed int INT; +typedef signed long LONG; +typedef signed long long LONGLONG; + +typedef unsigned long long ULONGLONG; + +typedef unsigned char BOOLEAN; +#ifdef LINUX +typedef void VOID; +#endif /* LINUX */ + +typedef char *PSTRING; +typedef VOID *PVOID; +typedef CHAR *PCHAR; +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef LONG *PLONG; +typedef ULONG *PULONG; +typedef UINT *PUINT; + +typedef unsigned int NDIS_MEDIA_STATE; + +typedef union _LARGE_INTEGER { + struct { +#ifdef RT_BIG_ENDIAN + INT32 HighPart; + UINT LowPart; +#else + UINT LowPart; + INT32 HighPart; +#endif + } u; + INT64 QuadPart; +} LARGE_INTEGER; + + +/* Register set pair for initialzation register set definition */ +typedef struct _RTMP_REG_PAIR { + UINT32 Register; + UINT32 Value; +} RTMP_REG_PAIR, *PRTMP_REG_PAIR; + +typedef struct _REG_PAIR { + UCHAR Register; + UCHAR Value; +} REG_PAIR, *PREG_PAIR; + +typedef struct _REG_PAIR_CHANNEL { + UCHAR Register; + UCHAR FirstChannel; + UCHAR LastChannel; + UCHAR Value; +} REG_PAIR_CHANNEL, *PREG_PAIR_CHANNEL; + +typedef struct _REG_PAIR_BW { + UCHAR Register; + UCHAR BW; + UCHAR Value; +} REG_PAIR_BW, *PREG_PAIR_BW; + + +typedef struct _REG_PAIR_PHY{ + UCHAR reg; + UCHAR s_ch; + UCHAR e_ch; + UCHAR phy; /* RF_MODE_XXX */ + UCHAR bw; /* RF_BW_XX */ + UCHAR val; +}REG_PAIR_PHY; + + +/* Register set pair for initialzation register set definition */ +typedef struct _RTMP_RF_REGS { + UCHAR Channel; + UINT32 R1; + UINT32 R2; + UINT32 R3; + UINT32 R4; +} RTMP_RF_REGS, *PRTMP_RF_REGS; + +typedef struct _FREQUENCY_ITEM { + UCHAR Channel; + UCHAR N; + UCHAR R; + UCHAR K; +} FREQUENCY_ITEM, *PFREQUENCY_ITEM; + +typedef int NTSTATUS; + +#define STATUS_SUCCESS 0x00 +#define STATUS_UNSUCCESSFUL 0x01 + +typedef struct _QUEUE_ENTRY { + struct _QUEUE_ENTRY *Next; +} QUEUE_ENTRY, *PQUEUE_ENTRY; + +/* Queue structure */ +typedef struct _QUEUE_HEADER { + PQUEUE_ENTRY Head; + PQUEUE_ENTRY Tail; + UINT Number; +} QUEUE_HEADER, *PQUEUE_HEADER; + +typedef struct _CR_REG { + UINT32 flags; + UINT32 offset; + UINT32 value; +} CR_REG, *PCR_REG; + +typedef struct _BANK_RF_CR_REG { + UINT32 flags; + UCHAR bank; + UCHAR offset; + UCHAR value; +} BANK_RF_CR_REG, *PBANK_RF_CR_REG; + +struct mt_dev_priv{ + void *sys_handle; + void *wifi_dev; + unsigned long priv_flags; + UCHAR sniffer_mode; +}; + +#endif /* __RTMP_TYPE_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/smart_mesh/smart_mesh_def.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/smart_mesh/smart_mesh_def.h new file mode 100644 index 000000000..173f36d7a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/smart_mesh/smart_mesh_def.h @@ -0,0 +1,471 @@ +#ifndef __SMART_MESH_DEF_H__ +#define __SMART_MESH_DEF_H__ + +/* +NTGR VIE---> +The 1st byte contains the following information: + Bit Description + 0 WLAN driver support DWDS + 1 System support SmartMesh + 2 System supports Orbi + 3-4 Used by Orbi daemon + 5 Orbi WPS capability + 6-7 reserved + +The 3rd byte contains the following information: + Bit Description + 0 Orbi WPS trigger status + 1-7 reserved +*/ + +#define NTGR_IE_TOTAL_LEN 160 +#define NTGR_OUI_LEN 3 +#define NTGR_CUSTOM_IE_MAX_LEN 3 +#define NTGR_IE_PRIV_LEN (NTGR_IE_TOTAL_LEN - NTGR_OUI_LEN) +extern UCHAR NETGEAR_OUI[NTGR_OUI_LEN]; + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +enum hidde_wps_state_type { + HIDDEN_WPS_STATE_STOP = 0, + HIDDEN_WPS_STATE_RUNNING = (1<<0) +}; + +enum hidde_wps_role_type { + HIDDEN_WPS_ROLE_ENROLLEE = 0, + HIDDEN_WPS_ROLE_REGISTRAR = (1<<1) +}; +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef SMART_MESH_MONITOR +#define NSMP_MAX_HT_CHANNELS 8 +#define MAX_NUM_OF_MONITOR_STA 7 +#define WCID_OF_MONITOR_STA_BASE (MAX_NUMBER_OF_MAC - MAX_NUM_OF_MONITOR_STA) +#define MAX_WCID_OF_MONITOR_STA (MAX_NUMBER_OF_MAC - 1) + +/* WLAN capability information */ +#define NSMP_WLCAP_80211_N (0x00000001) +#define NSMP_WLCAP_80211_AC (0x00000002) +#define NSMP_WLCAP_RESERVE_1 (0x00000004) +#define NSMP_WLCAP_RESERVE_2 (0x00000008) +#define NSMP_WLCAP_HT40 (0x00000010) +#define NSMP_WLCAP_HT80 (0x00000020) +#define NSMP_WLCAP_HT160 (0x00000040) +#define NSMP_WLCAP_RESERVE_3 (0x00000080) +#define NSMP_WLCAP_RX_2_STREAMS (0x00000100) +#define NSMP_WLCAP_RX_3_STREAMS (0x00000200) +#define NSMP_WLCAP_RX_4_STREAMS (0x00000400) +#define NSMP_WLCAP_TX_2_STREAMS (0x00000800) +#define NSMP_WLCAP_TX_3_STREAMS (0x00001000) +#define NSMP_WLCAP_TX_4_STREAMS (0x00002000) +#define NSMP_WLCAP_RESERVE_4 (0x00004000) +#define NSMP_WLCAP_RESERVE_5 (0x00008000) + +#define NSMP_UPLINK_STAT_DISCONNECT (0) +#define NSMP_UPLINK_STAT_CONNECTED (1) + +#define NSMP_WPS_PBC_STAT_BEGIN (0) +#define NSMP_WPS_PBC_STAT_END_SUCCESS (1) +#define NSMP_WPS_PBC_STAT_END_TIMEOUT (2) + + +enum nsmpif_driver_event_type { + NSMPIF_DRVEVNT_RESPONSE = 0, + NSMPIF_DRVEVNT_STA_PROBE_REQ, /* Driver receive a ProbeReq */ + NSMPIF_DRVEVNT_STA_AUTH_REQ, /* Not used currently */ + NSMPIF_DRVEVNT_STA_ASSOC_REQ, /* Not used currently */ + NSMPIF_DRVEVNT_STA_JOIN, /* Once a station is AUTHORISED. If WPA used, it need to finish 4 ways handshake; otherwise when station complete ASSOC Req/Resp */ + NSMPIF_DRVEVNT_STA_LEAVE, /* Receive or Send DEAUTH to a station */ + NSMPIF_DRVEVNT_STA_TIMEOUT, /* Station leave due to inactivity timeout */ + /* The event is optional, if driver is using LEAVE event for timeout client */ + NSMPIF_DRVEVNT_EXT_UPLINK_STAT, /* For Extender only, triggered when link to Root-AP established or dropped */ + NSMPIF_DRVEVNT_WPS_PBC_STAT, /* Triggered when device WPS PBC for AP interface is started or end */ + NSMPIF_DRVEVNT_STA_AUTH_REJECT, /* Triggered when a STA rejected due to ACL rule */ + NSMPIF_DRVEVNT_CHANNEL_CHANGE, /* Triggered when a AP interface changes channel, such as ACSD */ + NSMPIF_DRVEVNT_STA_WPA_KEYERR, /* Triggered when a station using incorrect password during WPA handshake */ + NSMPIF_DRVEVNT_AP_PROBE_RESP, /* Driver receive a ProbeResp */ + NSMPIF_DRVEVNT_MAX, +}; +/* Note: Smart Mesh daemon will use "struct nsmpif_drvevnt_response" to reponse all event types */ + +struct nsmpif_drvevnt_sta_probe_req { + unsigned short type; /* NSMPIF_DRVEVNT_STA_PROBE_REQ */ + unsigned short channel; /* Wireless channel that receive probe request frame. */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + unsigned short is_ucast; /* if unicast frame */ + unsigned int cap; /* refer to NSMP_WLCAP_XXX in nsmp_common.h */ + int rate; /* RX data rate when recv frame, Kbps */ + short rssi; /* RSSI when recv frame */ + short snr; /* SNR when recv frame */ + unsigned short ntgr_vie_len; /* Length of NETGEAR Vendor Information Element */ + char ntgr_vie[NTGR_IE_TOTAL_LEN]; /* NTGR Vendor Information Element without OUI */ +}; + +struct nsmpif_drvevnt_sta_auth_req { + unsigned short type; /* NSMPIF_DRVEVNT_STA_AUTH_REQ */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + unsigned short reserved_1; + unsigned int reserved_2; + int rate; /* RX data rate when recv frame, Kbps */ + short rssi; /* RSSI when recv frame */ + short snr; /* SNR when recv frame */ + unsigned short ntgr_vie_len; /* Length of NETGEAR Vendor Information Element */ + unsigned char ntgr_vie[NTGR_IE_TOTAL_LEN]; /* NTGR Vendor Information Element without OUI */ +}; + +struct nsmpif_drvevnt_sta_assoc_req { + unsigned short type; /* NSMPIF_DRVEVNT_STA_ASSOC_REQ */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + unsigned int cap; /* Refer to NSMP_WLCAP_XXX in nsmp_common.h */ + unsigned short ntgr_vie_len; /* Length of NETGEAR Vendor Information Element */ + unsigned char ntgr_vie[NTGR_IE_TOTAL_LEN]; /* NTGR Vendor Information Element without OUI */ +}; + +struct nsmpif_drvevnt_sta_join { + unsigned short type; /* NSMPIF_DRVEVNT_STA_JOIN */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + unsigned int aid; /* Station's association ID */ +}; + +struct nsmpif_drvevnt_sta_leave { + unsigned short type; /* NSMPIF_DRVEVNT_STA_LEAVE */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ +}; + +struct nsmpif_drvevnt_sta_timeout { + unsigned short type; /* NSMPIF_DRVEVNT_STA_TIMEOUT */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ +}; + +struct nsmpif_drvevnt_ext_uplink_stat { + unsigned short type; /* NSMPIF_DRVEVNT_EXT_UPLINK_STAT */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned short op_channels[NSMP_MAX_HT_CHANNELS]; /* + * operating channels up to HT160 (8 channels) + * channel[0] to channel[7] (set to zero if not used) + * Ex: If radio is HT40 44(P) + 48(S) + * Set channel as: + * channel[0] = 44; + * channel[1] = 48; + * channel[2] = 0; + * ... + * channel[7] = 0; + */ + unsigned short link_state; /* NSMP_UPLINK_STAT_DISCONNECT or other defined in nsmp_common.h */ + unsigned char bssid[6]; /* RootAP's BSSID when event is NSMP_UPLINK_STAT_CONNECTED, else NULL */ +}; + +struct nsmpif_drvevnt_wps_pbc_stat { + unsigned short type; /* NSMPIF_DRVEVNT_WPS_PBC_STAT */ + unsigned short stat; /* NSMP_WPS_PBC_STAT_BEGIN or others definied in nsmp_common.h */ + unsigned short reason; /* Success:0, Fail: none-zero */ + unsigned short channel; /* Wireless channel, current channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC if stat is NSMP_PBC_STAT_END_SUCCESS, else NULL */ + unsigned short reserve; +}; + +struct nsmpif_drvevnt_sta_auth_reject_req { + unsigned short type; /* NSMPIF_DRVEVNT_STA_AUTH_REJECT */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + unsigned short is_ucast; /* Not used. For aligning struct nsmpif_drvevnt_sta_probe_req */ + unsigned int cap; /* Not used. For aligning struct nsmpif_drvevnt_sta_probe_req */ + int rate; /* RX data rate when recv frame, Kbps */ + short rssi; /* RSSI when recv frame */ + short snr; /* SNR when recv frame */ + unsigned short ntgr_vie_len; /* Length of NETGEAR Vendor Information Element */ + unsigned char ntgr_vie[NTGR_IE_TOTAL_LEN]; /* NTGR Vendor Information Element without OUI */ +}; + +struct nsmpif_drvevnt_channel_change_req { + unsigned short type; /* NSMPIF_DRVEVNT_CHANNEL_CHANGE */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned short op_channels[NSMP_MAX_HT_CHANNELS]; /* + * operating channels up to HT160 (8 channels) + * channel[0] to channel[7] (set to zero if not used) + * Ex: If radio is HT40 44(P) + 48(S) + * Set channel as: + * channel[0] = 44; + * channel[1] = 48; + * channel[2] = 0; + * ... + * channel[7] = 0; + */ +}; + +struct nsmpif_drvevnt_sta_wpa_keyerr { + unsigned short type; /* NSMPIF_DRVEVNT_STA_WPA_KEYERR */ + unsigned short channel; /* Wireless channel, main channel only */ + unsigned char sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + unsigned short reserve; +}; + +struct nsmpif_drvevnt_ap_probe_resp { + unsigned short type; /* NSMPIF_DRVEVNT_STA_PROBE_RSP */ + unsigned short channel; /* Wireless channel that receive probe response frame. */ + unsigned char ap_mac[MAC_ADDR_LEN]; /* AP's MAC address */ + unsigned short is_ucast; /* if unicast frame */ + unsigned int cap; /* refer to NSMP_WLCAP_XXX in nsmp_common.h */ + int rate; /* RX data rate when recv frame */ + short rssi; /* RSSI when recv frame */ + short snr; /* SNR when recv frame */ + char ssid[MAX_LEN_OF_SSID]; /* SSID in Probe Resp, non-used bytes must be zero */ + unsigned short ntgr_vie_len; /* Length of NTGR Vendor Information Element */ + char ntgr_vie[NTGR_IE_TOTAL_LEN]; /* NTGR Vendor Information Element without OUI */ +}; + +struct nsmpif_drvevnt_response { + int response; /* NSMP_RETURN_SUCCESS or NSMP_RETURN_FAILURE defined in nsmp_common.h */ +}; + +/* used to cast buffer for examining message type */ +struct nsmpif_drvevnt_hdr { + unsigned short type; + unsigned short channel; /* Wireless channel, main channel only */ +}; + +/* a larger buffer able to handle all kind of messages */ +struct nsmpif_drvevnt_buf { + union { + struct nsmpif_drvevnt_sta_probe_req probereq; + struct nsmpif_drvevnt_sta_auth_req authreq; + struct nsmpif_drvevnt_sta_assoc_req assocreq; + struct nsmpif_drvevnt_sta_join join; + struct nsmpif_drvevnt_sta_leave leave; + struct nsmpif_drvevnt_sta_timeout timeout; + struct nsmpif_drvevnt_ext_uplink_stat linkstate; + struct nsmpif_drvevnt_response response; + struct nsmpif_drvevnt_wps_pbc_stat wps_pbc_stat; + struct nsmpif_drvevnt_sta_auth_reject_req authreject; + struct nsmpif_drvevnt_channel_change_req channel_change; + struct nsmpif_drvevnt_sta_wpa_keyerr sta_wpa_keyerr; + struct nsmpif_drvevnt_ap_probe_resp proberesp; + } data; +}; + +typedef struct GNU_PACKED _HEADER_802_11_4_ADDR { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; +#ifdef RT_BIG_ENDIAN + USHORT Sequence:12; + USHORT Frag:4; +#else + USHORT Frag:4; + USHORT Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Addr4[MAC_ADDR_LEN]; +} HEADER_802_11_4_ADDR, *PHEADER_802_11_4_ADDR; + +typedef struct GNU_PACKED _SMART_RADIO_INFO{ + CHAR RSSI0; + CHAR RSSI1; + CHAR SNR0; + CHAR SNR1; + CHAR PHYMODE; + CHAR MCS; + CHAR BW; + CHAR ShortGI; + UINT32 RATE; +} SMART_RADIO_INFO, *PSMART_RADIO_INFO; + +typedef struct GNU_PACKED _SMART_MESH_RAW { + SMART_RADIO_INFO wlan_radio_tap; + HEADER_802_11_4_ADDR wlan_header; +} SMART_MESH_RAW, *PSMART_MESH_RAW; + +#endif /*SMART_MESH_MONITOR*/ + +#ifdef SMART_MESH +#define MAX_TX_RX_STREAMS 3 +#define MAX_LAST_PKT_STATS 20 +#define ETH_TYPE_SMART_MESH 0x99AA + +enum SMART_MESH_IE_CTRL_FLAG { + SM_IE_BEACON = (1<<0), + SM_IE_PROBE_RSP = (1<<1), + SM_IE_ASSOC_RSP = (1<<2), + SM_IE_AUTH_RSP = (1<<3), + SM_IE_PROBE_REQ = (1<<4), + SM_IE_AUTH_REQ = (1<<5), + SM_IE_ASSOC_REQ = (1<<6), + SM_IE_ALL = 0xFFFF +}; + + +/* +Character Bit Information Provided + 0 0 value 1: DWDS is enabled, + value 0: DWDS is disabled +------------------------------------------ + 0 1 value 1: SmartMesh is + enabled, value 0: SmartMesh + is disabled +------------------------------------------ +x x Others are Reserved +------------------------------------------ +*/ +typedef struct _NTGR_IE { + UINT8 id; /* 221 */ + UINT8 len; + UINT8 oui[NTGR_OUI_LEN]; /* 0x00 0x14 0x6C Netgear OUI */ + UINT8 private[NTGR_IE_PRIV_LEN]; +}NTGR_IE, *PNTGR_IE; + +typedef struct _UNI_PROBE_REQ_CFG { + UINT8 ssid_len; + UCHAR addr1[MAC_ADDR_LEN]; + UCHAR addr2[MAC_ADDR_LEN]; + CHAR ssid[MAX_LEN_OF_SSID]; +}UNI_PROBE_REQ_CFG, *PUNI_PROBE_REQ_CFG; + +typedef struct _SMART_MESH_CFG { + UINT32 ie_ctrl_flags; + BOOLEAN bSupportSmartMesh; /* Determine If own smart mesh capability */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS + BOOLEAN bSupportHiddenWPS; /* Determine If own Hidden WPS capability */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + BOOLEAN bHiFiPeerFilter; /* Only allow Hi-Fi target device to negotiate */ + CHAR HiFiFlagMask; /* A mask for identifying Hi-Fi bit in vendor IE */ + UCHAR HiFiFlagValue; /* A desired match value for identifying Hi-Fi device in vendor IE */ + NTGR_IE Ntgr_IE; + UNI_PROBE_REQ_CFG UniProbeReqCfg; +}SMART_MESH_CFG, *PSMART_MESH_CFG; + +typedef struct _SMART_MESH_CLI_INFO { + USHORT aid; + CHAR rssi; + CHAR snr; + + /* RX Info */ + UINT8 rx_mcs; + UINT8 rx_stream; + UINT8 rx_bw; + UINT8 rx_sgi; + UINT8 rx_phymode; + CHAR last_rssi[MAX_TX_RX_STREAMS]; + CHAR last_snr[MAX_TX_RX_STREAMS]; + + /* TX Info */ + HTTRANSMIT_SETTING TX_HTSetting; + UINT8 tx_mcs; + UINT8 tx_stream; + UINT8 tx_bw; + UINT8 tx_sgi; + UINT8 tx_phymode; + + /* statistics */ + INT64 rx_total_packets; + ULONG rx_total_bytes; + ULONG rx_fail_cnt; + INT64 tx_total_packets; + ULONG tx_total_bytes; + ULONG tx_fail_cnt; +} SMART_MESH_CLI_INFO, *PSMART_MESH_CLI_INFO; + +/* For RT_OID_SET_LAST_TX_RX_STATS */ +typedef struct _SET_PKT_STATS_INFO { + BOOLEAN bCliPktStatEnable; + UCHAR Mac[MAC_ADDR_LEN]; +} SET_PKT_STATS_INFO, *PSET_PKT_STATS_INFO; + +/* For RT_OID_GET_LAST_TX_RX_STATS */ +typedef struct _CLINET_PKT_STATS_INFO { + BOOLEAN bTxValid; + BOOLEAN bRxValid; + + /* RX Info */ + CHAR last_rssi[MAX_TX_RX_STREAMS]; + UINT32 rx_seq; + UINT8 rx_mcs; + UINT8 rx_stream; + UINT8 rx_bw; + UINT8 rx_sgi; + UINT8 rx_phymode; + UINT32 rx_rate; + ULONG rx_time_sec; + + /* TX Info */ + UINT32 tx_seq; + UINT8 tx_mcs; + UINT8 tx_stream; + UINT8 tx_bw; + UINT8 tx_sgi; + UINT8 tx_phymode; + UINT32 tx_rate; + ULONG tx_time_sec; +} CLINET_PKT_STATS_INFO, *PCLINET_PKT_STATS_INFO; + +/* For RT_OID_SET_PKT_TX_RX_STATS */ +typedef struct _SET_PKT_TX_RX_STATS { +#ifdef ED_MONITOR + BOOLEAN timer_en; +#endif /* ED_MONITOR */ + ULONG scan_time; /* unit: msec */ + BOOLEAN trigger_site_survey; + BOOLEAN channel_time_init; + //UCHAR Mac[MAC_ADDR_LEN]; +} SET_PKT_TX_RX_STATS, *PSET_PKT_TX_RX_STATS; + +typedef enum FalseCCASET { + CCA_RESET, + CCA_STORE +} False_CCA_SET; + +typedef struct _CHANNEL_INFO { + UCHAR channel; + ULONG false_cca; +}CHANNEL_INFO, *PCHANNEL_INFO; + +typedef struct _CLIENT_PKT_INFO{ + UCHAR mac[MAC_ADDR_LEN]; + USHORT aid; + ULONG tx_per; + ULONG tx_acked_packet; + ULONG agg_size; +} CLIENT_PKT_INFO, *PCLIENT_PKT_INFO; + +typedef struct _PKT_TX_RX_INFO { + ULONG tx_acked_num; + ULONG rx_pkt_error_rate; + ULONG false_cca_count; + ULONG edcca_busy_time; + ULONG rts_success_count; + ULONG rts_fail_count; + ULONG channel_busy_time; + ULONG channel_idle_time; + UCHAR channel_list_num; + CHANNEL_INFO channel_list[MAX_NUM_OF_CHANNELS]; + USHORT entry_num; + CLIENT_PKT_INFO entry[MAX_NUMBER_OF_MAC]; + +} PKT_TX_RX_INFO, *PPKT_TX_RX_INFO; + +typedef struct _AP_INFO{ + UCHAR ssid[MAX_LEN_OF_SSID]; + UCHAR ssid_len; + USHORT channel; + CHAR bw; + CHAR rssi; +} AP_INFO, *PAP_INFO; + +typedef struct _AP_LIST_INFO { + UCHAR num; + UCHAR channel_ap_num; + USHORT channel; + AP_INFO ap[MAX_LEN_OF_BSS_TABLE]; +} AP_LIST_INFO, *PAP_LIST_INFO; + +#endif /* SMART_MESH */ +#endif /* __SMART_MESH_DEF_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/smart_mesh/smart_mesh_func.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/smart_mesh/smart_mesh_func.h new file mode 100644 index 000000000..3fb9e3e0f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/smart_mesh/smart_mesh_func.h @@ -0,0 +1,204 @@ +#ifndef __SMART_MESH_FUNC_H__ +#define __SMART_MESH_FUNC_H__ + +#ifdef SMART_MESH_MONITOR +INT Set_Enable_Monitor_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorIndex_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorShowAll_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorClearCounter_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget0_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget5_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_MonitorTarget6_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Smart_Mesh_Pkt_Report_Action( + IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN RXWI_STRUC *pRxWI, + IN PUCHAR buff); + +INT UpdateMonitorEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR MntWCID, + IN UCHAR *MntAddr, + IN BOOLEAN bClear); + +BOOLEAN IsValidUnicastToMe(IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PUCHAR pDA); +#endif /*SMART_MESH_MONITOR*/ + +#ifdef SMART_MESH +INT smart_mesh_init(PSMART_MESH_CFG pSmartMeshCfg); +INT smart_mesh_enable(PSMART_MESH_CFG pSmartMeshCfg,BOOLEAN Enable); +#ifdef MWDS +INT dwds_enable(PSMART_MESH_CFG pSmartMeshCfg, BOOLEAN Enable); +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT hidden_wps_enable(PSMART_MESH_CFG pSmartMeshCfg, BOOLEAN Enable); +INT Set_HiddenWps_State(PSMART_MESH_CFG pSmartMeshCfg, UINT8 state); +INT Set_HiddenWps_Role(PSMART_MESH_CFG pSmartMeshCfg, UINT8 role); +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +INT Set_SmartMesh_IE_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_IE_Crtl_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_IE_Show_Proc(PRTMP_ADAPTER pAd,PSTRING arg); +INT Set_SmartMesh_Unicast_ProbeReq_SSID_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_Unicast_ProbeReq_Send_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_DFSScanAP_Enable_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_DFSScanAP_Show_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +VOID Set_Check_RadarChannelAP(PRTMP_ADAPTER pAd,UCHAR Ch,BSS_ENTRY *pBss); +VOID Set_Check_RadarChannelAPExist(PRTMP_ADAPTER pAd); +BOOLEAN IsRadarChannelAPExist(PRTMP_ADAPTER pAd, UCHAR Ch); +BOOLEAN Set_Scan_False_CCA(PRTMP_ADAPTER pAd,UCHAR ch_index, UCHAR type); +INT Set_SmartMesh_HyperFiPeer_Filter_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_HyperFiFlagMask_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +INT Set_SmartMesh_HyperFiFlagValue_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +#ifdef WSC_AP_SUPPORT +ULONG Get_BssSsidTableSearchByMAC(BSS_TABLE *Tab, UCHAR *pBssAddr); +INT Set_SmartMesh_WscPBCMAC_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +#endif /* WSC_AP_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT +INT Set_vMacPrefix_Show_Proc(PRTMP_ADAPTER pAd,PSTRING arg); +#endif /* MAC_REPEATER_SUPPORT */ +VOID rtmp_read_smart_mesh_from_file(IN PRTMP_ADAPTER pAd,PSTRING tmpbuf,PSTRING buffer); +#ifdef MWDS +VOID rtmp_read_DWDS_from_file(IN PRTMP_ADAPTER pAd,PSTRING tmpbuf,PSTRING buffer); +#endif /* MWDS */ + +INT Set_Ap_SmartMesh_ACL_Proc(PRTMP_ADAPTER pAd, PSTRING arg); +#ifdef APCLI_SUPPORT +INT Set_ApCli_SmartMesh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_SmartMesh_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_DWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT Set_ApCli_HiddenWPS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_HiddenWPS_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +INT Set_Ap_SmartMesh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ap_SmartMesh_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ap_DWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_AP_SUPPORT +#ifdef SMART_MESH_HIDDEN_WPS +INT Set_Ap_HiddenWPS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ap_HiddenWPS_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* WSC_AP_SUPPORT */ + +INT Set_Cli_Status_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID Update_CliPktStats( + IN PRTMP_ADAPTER pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UINT32 MacSeq, + IN BOOLEAN bFromTx); + +INT Set_Cli_Pkt_Stats_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Cli_Pkt_Stats_TX_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Cli_Pkt_Stats_RX_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MLME_Queue_Full_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +#define SMART_MESH_INSERT_IE(_SmartMeshCfg, _pBuffer, _FrameLen, _ie_ctrl_flag) \ +{ \ + ULONG TmpLen,TotalLen; \ + PSMART_MESH_CFG pSmartMeshCfg = &_SmartMeshCfg; \ + PNTGR_IE pNtgr_IE = &pSmartMeshCfg->Ntgr_IE;\ +\ + if ((pNtgr_IE->id == IE_VENDOR_SPECIFIC) && (pSmartMeshCfg->ie_ctrl_flags & _ie_ctrl_flag)) \ + { \ + TotalLen = pNtgr_IE->len + 2;\ + MakeOutgoingFrame(_pBuffer+_FrameLen, &TmpLen, TotalLen, pNtgr_IE, END_OF_ARGS); \ + _FrameLen += TmpLen;\ + } \ +} + +#endif /* SMART_MESH */ + +#endif /* __SMART_MESH_FUNC_H__ */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/ppi.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/ppi.h new file mode 100644 index 000000000..235302b26 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/ppi.h @@ -0,0 +1,118 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + * Per Packet Information Header + + Module Name: + ppi.h +*/ + +#define SIZE_PPI_FIELD_80211_COMMON 20 +#define SIZE_PPI_FIELD_80211n_MACPHYEXT 48 +#define MAX_MCS_INDEX 76 +#define MAX_MCS_VHT_INDEX 9 + +typedef struct ppi_packetheader { + uint8_t pph_version; + uint8_t pph_flags; + uint16_t pph_len; + uint32_t pph_dlt; +}ppi_packetheader_t; + +typedef struct ppi_fieldheader { + uint16_t pfh_type; + uint16_t pfh_datalen; +}ppi_fieldheader_t; + +static const uint16_t ieee80211_vhtinfo[MAX_MCS_VHT_INDEX+1][4][2][4] = { + /* MCS 0 */ + { + /* 20 Mhz */ { {6,13,19,26,}, /* SGI */ { 7,14,22,29,}, }, + /* 40 Mhz */ { {13,27,40,54,}, /* SGI */ { 15,30,45,60,}, }, + /* 80 Mhz */ { {29,59,88,117,}, /* SGI */ { 32,65,97,130,}, }, + /* 160 Mhz */ { {58,117,175,234,}, /* SGI */ { 65,130,195,260,}, } + + }, + /* MCS 1 */ + { + /* 20 Mhz */ { {13,26,39,52,}, /* SGI */ {14,29,43,58,},}, + /* 40 Mhz */ { {27,54,81,108,}, /* SGI */ {30,60,90,120,},}, + /* 80 Mhz */ { {58,117,175,234,}, /* SGI */{65,130,195,260,},}, + /* 160 Mhz */ { {117,234,351,468,}, /* SGI */{130,260,390,520,},} + + }, + /* MCS 2 */ + { + /* 20 Mhz */ { {19,39,58,78,}, /* SGI */ {22,43,65,87,}, }, + /* 40 Mhz */ { {40,81,121,162,}, /* SGI */ {45,90,135,180,}, }, + /* 80 Mhz */ { {88,176,263,351,}, /* SGI */{97,195,292,390,}, }, + /* 160 Mhz */ { {175,351,526,702,}, /* SGI */{195,390,585,780,}, } + + }, + /* MCS 3 */ + { + /* 20 Mhz */ { {26,52,78,104,}, /* SGI */ {29,58,87,116,}, }, + /* 40 Mhz */ { {54,108,162,216,}, /* SGI */{60,120,180,240,}, }, + /* 80 Mhz */ { {117,234,351,468,}, /* SGI */{130,260,390,520,}, }, + /* 160 Mhz */ { {234,468,702,936,}, /* SGI */{260,520,780,1040,}, } + + }, + /* MCS 4 */ + { + /* 20 Mhz */ { {39,78,117,156,}, /* SGI */ {43,87,130,173,}, }, + /* 40 Mhz */ { {81,162,243,324,}, /* SGI */ {90,180,270,360,}, }, + /* 80 Mhz */ { {175,351,526,702,}, /* SGI */ {195,390,585,780,}, }, + /* 160 Mhz */ { {351,702,1053,1404,}, /* SGI */{390,780,1170,1560,}, } + + }, + /* MCS 5 */ + { + /* 20 Mhz */ { {52,104,156,208,}, /* SGI */ {58,116,173,351,}, }, + /* 40 Mhz */ { {108,216,324,432,}, /* SGI */ {120,240,360,480,}, }, + /* 80 Mhz */ { {234,468,702,936,}, /* SGI */ {260,520,780,1040,}, }, + /* 160 Mhz */ { {468,936,1404,1872,}, /* SGI */{520,1040,1560,2080,}, } + + }, + /* MCS 6 */ + { + /* 20 Mhz */ { {58,117,175,234,}, /* SGI */ {65,130,195,260,}, }, + /* 40 Mhz */ { {121,243,364,486,}, /* SGI */ {135,270,405,540,}, }, + /* 80 Mhz */ { {263,527,790,1053,}, /* SGI */ {292,585,877,1170,}, }, + /* 160 Mhz */ { {526,1053,1579,2106,}, /* SGI */{585,1170,1755,2340,}, } + + }, + /* MCS 7 */ + { + /* 20 Mhz */ { {65,130,195,260,}, /* SGI */ {72,144,217,289,}, }, + /* 40 Mhz */ { {135,270,405,540,}, /* SGI */ {150,300,450,600,}, }, + /* 80 Mhz */ { {292,585,877,1170,}, /* SGI */ {325,650,975,1300,}, }, + /* 160 Mhz */ { {585,1170,1755,2340,}, /* SGI */{650,1300,1950,2600,}, } + + }, + /* MCS 8 */ + { + /* 20 Mhz */ { {78,156,234,312,}, /* SGI */ {87,173,260,347,}, }, + /* 40 Mhz */ { {162,324,486,648,}, /* SGI */ {180,360,540,720,}, }, + /* 80 Mhz */ { {351,702,1053,1404,}, /* SGI */{390,780,1170,1560,}, }, + /* 160 Mhz */ { {702,1404,2106,2808,}, /* SGI */{780,1560,2340,3120,}, } + + }, + /* MCS 9 */ + { + /* 20 Mhz */ { {0,0,0,0,}, /* SGI */ {0,0,0,0,}, }, + /* 40 Mhz */ { {180,360,540,720,}, /* SGI */ {200,400,600,800,}, }, + /* 80 Mhz */ { {390,780,1170,1560,}, /* SGI */{433,867,1300,1733,}, }, + /* 160 Mhz */ { {780,1560,2340,3120,}, /* SGI */{867,1733,2600,3467,}, } + + } +}; diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/radiotap.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/radiotap.h new file mode 100644 index 000000000..dc74da402 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/radiotap.h @@ -0,0 +1,301 @@ +/*- + * Copyright (c) 2003, 2004 David Young. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of David Young may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID + * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + +/* + * Modifications to fit into the linux IEEE 802.11 stack, + * Mike Kershaw (dragorn@kismetwireless.net) + */ + +#ifndef IEEE80211RADIOTAP_H +#define IEEE80211RADIOTAP_H + +/* Base version of the radiotap packet header data */ +#define PKTHDR_RADIOTAP_VERSION 0 + +/* A generic radio capture format is desirable. There is one for + * Linux, but it is neither rigidly defined (there were not even + * units given for some fields) nor easily extensible. + * + * I suggest the following extensible radio capture format. It is + * based on a bitmap indicating which fields are present. + * + * I am trying to describe precisely what the application programmer + * should expect in the following, and for that reason I tell the + * units and origin of each measurement (where it applies), or else I + * use sufficiently weaselly language ("is a monotonically nondecreasing + * function of...") that I cannot set false expectations for lawyerly + * readers. + */ + +/* The radio capture header precedes the 802.11 header. + * All data in the header is little endian on all platforms. + */ +struct ieee80211_radiotap_header { + uint8_t it_version; /* Version 0. Only increases + * for drastic changes, + * introduction of compatible + * new fields does not count. + */ + uint8_t it_pad; + uint16_t it_len; /* length of the whole + * header in bytes, including + * it_version, it_pad, + * it_len, and data fields. + */ + uint32_t it_present; /* A bitmap telling which + * fields are present. Set bit 31 + * (0x80000000) to extend the + * bitmap by another 32 bits. + * Additional extensions are made + * by setting bit 31. + */ +}; + +/* Name Data type Units + * ---- --------- ----- + * + * IEEE80211_RADIOTAP_TSFT __le64 microseconds + * + * Value in microseconds of the MAC's 64-bit 802.11 Time + * Synchronization Function timer when the first bit of the + * MPDU arrived at the MAC. For received frames, only. + * + * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap + * + * Tx/Rx frequency in MHz, followed by flags (see below). + * + * IEEE80211_RADIOTAP_FHSS uint16_t see below + * + * For frequency-hopping radios, the hop set (first byte) + * and pattern (second byte). + * + * IEEE80211_RADIOTAP_RATE u8 500kb/s + * + * Tx/Rx data rate + * + * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from + * one milliwatt (dBm) + * + * RF signal power at the antenna, decibel difference from + * one milliwatt. + * + * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from + * one milliwatt (dBm) + * + * RF noise power at the antenna, decibel difference from one + * milliwatt. + * + * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) + * + * RF signal power at the antenna, decibel difference from an + * arbitrary, fixed reference. + * + * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) + * + * RF noise power at the antenna, decibel difference from an + * arbitrary, fixed reference point. + * + * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless + * + * Quality of Barker code lock. Unitless. Monotonically + * nondecreasing with "better" lock strength. Called "Signal + * Quality" in datasheets. (Is there a standard way to measure + * this?) + * + * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless + * + * Transmit power expressed as unitless distance from max + * power set at factory calibration. 0 is max power. + * Monotonically nondecreasing with lower power levels. + * + * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) + * + * Transmit power expressed as decibel distance from max power + * set at factory calibration. 0 is max power. Monotonically + * nondecreasing with lower power levels. + * + * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from + * one milliwatt (dBm) + * + * Transmit power expressed as dBm (decibels from a 1 milliwatt + * reference). This is the absolute power level measured at + * the antenna port. + * + * IEEE80211_RADIOTAP_FLAGS u8 bitmap + * + * Properties of transmitted and received frames. See flags + * defined below. + * + * IEEE80211_RADIOTAP_ANTENNA u8 antenna index + * + * Unitless indication of the Rx/Tx antenna for this packet. + * The first antenna is antenna 0. + * + * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap + * + * Properties of received frames. See flags defined below. + * + * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap + * + * Properties of transmitted frames. See flags defined below. + * + * IEEE80211_RADIOTAP_RTS_RETRIES u8 data + * + * Number of rts retries a transmitted frame used. + * + * IEEE80211_RADIOTAP_DATA_RETRIES u8 data + * + * Number of unicast retries a transmitted frame used. + * + * IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless + * + * Contains a bitmap of known fields/flags, the flags, and + * the MCS index. + * + * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss + * + * Contains the AMPDU information for the subframe. + * + * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 + * + * Contains VHT information about this frame. + */ +enum ieee80211_radiotap_type { + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13, + IEEE80211_RADIOTAP_RX_FLAGS = 14, + IEEE80211_RADIOTAP_TX_FLAGS = 15, + IEEE80211_RADIOTAP_RTS_RETRIES = 16, + IEEE80211_RADIOTAP_DATA_RETRIES = 17, + + IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, + IEEE80211_RADIOTAP_VHT = 21, + + /* valid in every it_present bitmap, even vendor namespaces */ + IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, + IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, + IEEE80211_RADIOTAP_EXT = 31 +}; + +/* Channel flags. */ +#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ +#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ +#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ + +/* For IEEE80211_RADIOTAP_FLAGS */ +#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received + * during CFP + */ +#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received + * with short + * preamble + */ +#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received + * with WEP encryption + */ +#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received + * with fragmentation + */ +#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ +#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between + * 802.11 header and payload + * (to 32-bit boundary) + */ +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* frame failed FCS check */ + +/* For IEEE80211_RADIOTAP_RX_FLAGS */ +#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* bad PLCP */ + +/* For IEEE80211_RADIOTAP_TX_FLAGS */ +#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive + * retries */ +#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ +#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ + +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 + +/* For IEEE80211_RADIOTAP_MCS */ +#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01 +#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02 +#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 +#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 +#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 + +#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 +#define IEEE80211_RADIOTAP_MCS_BW_20 0 +#define IEEE80211_RADIOTAP_MCS_BW_40 1 +#define IEEE80211_RADIOTAP_MCS_BW_20L 2 +#define IEEE80211_RADIOTAP_MCS_BW_20U 3 +#define IEEE80211_RADIOTAP_MCS_SGI 0x04 +#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 +#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 + +/* For IEEE80211_RADIOTAP_VHT */ +#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001 +#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002 +#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 +#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008 +#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010 +#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020 +#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 +#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080 +#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100 + +#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 +#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02 +#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 +#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08 +#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 +#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 + +#endif /* IEEE80211_RADIOTAP_H */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/sniffer.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/sniffer.h new file mode 100644 index 000000000..961a9b800 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sniffer/sniffer.h @@ -0,0 +1,172 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + sniffer.h +*/ + +#ifndef __SNIFFER_H__ +#define __SNIFFER_H__ + +#include "radiotap.h" +#include "ppi.h" + +struct sniffer_control { + UINT8 sniffer_type; +}; + +#define RADIOTAP_TYPE 0 +#define PRISM_TYPE 1 + +enum { + DIDmsg_lnxind_wlansniffrm = 0x00000044, + DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, + DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, + DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, + DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, + DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, + DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, + DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, + DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, + DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, + DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 +}; +enum { +P80211ENUM_msgitem_status_no_value = 0x00 +}; + +enum { +P80211ENUM_truth_false = 0x00, +P80211ENUM_truth_true = 0x01 +}; + + +/* Definition from madwifi */ +typedef struct { + UINT32 did; + UINT16 status; + UINT16 len; + UINT32 data; +} p80211item_uint32_t; + +typedef struct { + UINT32 msgcode; + UINT32 msglen; +#define WLAN_DEVNAMELEN_MAX 16 + UINT8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t hosttime; + p80211item_uint32_t mactime; + p80211item_uint32_t channel; + p80211item_uint32_t rssi; + p80211item_uint32_t sq; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_uint32_t rate; + p80211item_uint32_t istx; + p80211item_uint32_t frmlen; +} wlan_ng_prism2_header; + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT +/* + Note: 2009/11/10 + Used in WiFi Sigma Test Engine RT3593 (replace RT2883). +*/ +#ifdef RT_BIG_ENDIAN +typedef struct _ETHEREAL_RADIO { + UCHAR Flag_80211n; + UCHAR signal_level; /* dBm */ + UCHAR data_rate; /* rate index */ + UCHAR channel; /* Channel number */ +} ETHEREAL_RADIO, *PETHEREAL_RADIO; +#else +typedef struct _ETHEREAL_RADIO { + UCHAR channel; /* Channel number */ + UCHAR data_rate; /* rate index */ + UCHAR signal_level; /* dBm */ + UCHAR Flag_80211n; +} ETHEREAL_RADIO, *PETHEREAL_RADIO; +#endif + +#define WIRESHARK_11N_FLAG_3x3 0x01 +#define WIRESHARK_11N_FLAG_GF 0x02 +#define WIRESHARK_11N_FLAG_AMPDU 0x04 +#define WIRESHARK_11N_FLAG_STBC 0x08 +#define WIRESHARK_11N_FLAG_SGI 0x10 +#define WIRESHARK_11N_FLAG_BW20U 0x20 +#define WIRESHARK_11N_FLAG_BW20D 0x40 +#define WIRESHARK_11N_FLAG_BW40 0x80 +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + +struct mtk_radiotap_header { + struct ieee80211_radiotap_header rt_hdr; + UCHAR variable[0]; +}; + +#define HT_BW(p) ((p) & IEEE80211_RADIOTAP_MCS_BW_MASK) +#define HT_GI(p) ((p << 2) & IEEE80211_RADIOTAP_MCS_SGI) +#define HT_FORMAT(p) ((p << 3) & IEEE80211_RADIOTAP_MCS_FMT_GF) +#define HT_FEC_TYPE(p) ((p << 4) & IEEE80211_RADIOTAP_MCS_FEC_LDPC) + +#define VHT_MCS_MASK 0x0f +#define GET_VHT_MCS(p) (((p) & VHT_MCS_MASK)) +#define VHT_NSS_MASK (0x03 << 4) +#define GET_VHT_NSS(p) ((((p) & VHT_NSS_MASK) >> 4) + 1) + + +// copy from dot11_base.h, here we duplicate this only for sniffer use! +/* 2-byte Frame control field */ +typedef struct GNU_PACKED _FC_FIELD{ +#ifdef RT_BIG_ENDIAN + UINT16 Order:1; /* Strict order expected */ + UINT16 Wep:1; /* Wep data */ + UINT16 MoreData:1; /* More data bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 SubType:4; /* MSDU subtype */ + UINT16 Type:2; /* MSDU type */ + UINT16 Ver:2; /* Protocol version */ +#else + UINT16 Ver:2; /* Protocol version */ + UINT16 Type:2; /* MSDU type, refer to FC_TYPE_XX */ + UINT16 SubType:4; /* MSDU subtype, refer to SUBTYPE_XXX */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 MoreData:1; /* More data bit */ + UINT16 Wep:1; /* Wep data */ + UINT16 Order:1; /* Strict order expected */ +#endif /* !RT_BIG_ENDIAN */ +} FC_FIELD; + +typedef struct GNU_PACKED _DOT_11_HDR { + FC_FIELD FC; + UINT16 Duration; + UCHAR Addr1[6]; + UCHAR Addr2[6]; + UCHAR Addr3[6]; +#ifdef RT_BIG_ENDIAN + UINT16 Sequence:12; + UINT16 Frag:4; +#else + UINT16 Frag:4; + UINT16 Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Octet[0]; +}DOT_11_HDR; + + +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/spectrum.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/spectrum.h new file mode 100644 index 000000000..182f0d9ce --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/spectrum.h @@ -0,0 +1,233 @@ + +#ifndef __SPECTRUM_H__ +#define __SPECTRUM_H__ + +#include "rtmp_type.h" +#include "spectrum_def.h" + + +UINT8 GetRegulatoryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel); + +CHAR RTMP_GetTxPwr( + IN PRTMP_ADAPTER pAd, + IN HTTRANSMIT_SETTING HTTxMode); + +/* + ========================================================================== + Description: + Prepare Measurement request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID MakeMeasurementReqFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuffer, + OUT PULONG pFrameLen, + IN UINT8 TotalLen, + IN UINT8 Category, + IN UINT8 Action, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT16 NumOfRepetitions); + +/* + ========================================================================== + Description: + Prepare Measurement report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo); + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken); + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin); + +#ifdef WDS_SUPPORT +/* + ========================================================================== + Description: + Prepare Channel Switch Announcement action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + 2. Channel switch announcement mode. + 2. a New selected channel. + + Return : None. + ========================================================================== + */ +VOID EnqueueChSwAnn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh); +#endif /* WDS_SUPPORT */ + +/* + ========================================================================== + Description: + Spectrun action frames Handler such as channel switch annoucement, + measurement report, measurement request actions frames. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +VOID PeerSpectrumAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_MeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TpcReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PwrConstraint( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DOT11K_RRM_SUPPORT +INT Set_VoPwrConsTest( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DOT11K_RRM_SUPPORT */ + +NDIS_STATUS MeasureReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd); + +PMEASURE_REQ_ENTRY MeasureReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken); + +PMEASURE_REQ_ENTRY MeasureReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken); + +VOID MeasureReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken); + +VOID InsertChannelRepIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PSTRING pCountry, + IN UINT8 RegulatoryClass); + +VOID InsertTpcReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TxPwr, + IN UINT8 LinkMargin); + +VOID InsertDialogToken( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 DialogToken); + +NDIS_STATUS TpcReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID TpcReqTabExit( + IN PRTMP_ADAPTER pAd); + +VOID NotifyChSwAnnToPeerAPs( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRA, + IN PUCHAR pTA, + IN UINT8 ChSwMode, + IN UINT8 Channel); + +VOID RguClass_BuildBcnChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen); + +#ifdef CUSTOMER_DCC_FEATURE +VOID NotifyChSwAnnToConnectedSTAs( + IN PRTMP_ADAPTER pAd, + IN UINT8 ChSwMode, + IN UINT8 Channel); + +VOID EnqueueChSwAnnNew( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh); +#endif +#endif /* __SPECTRUM_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/spectrum_def.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/spectrum_def.h new file mode 100644 index 000000000..316956c13 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/spectrum_def.h @@ -0,0 +1,249 @@ +/**************************************************************************** + * 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: + spectrum_def.h + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 2008 created for 802.11h + */ + +#ifndef __SPECTRUM_DEF_H__ +#define __SPECTRUM_DEF_H__ + + +#define MAX_MEASURE_REQ_TAB_SIZE 32 +/* Size of hash tab must be power of 2. */ +#define MAX_HASH_MEASURE_REQ_TAB_SIZE MAX_MEASURE_REQ_TAB_SIZE + +#define MAX_TPC_REQ_TAB_SIZE 32 +/* Size of hash tab must be power of 2. */ +#define MAX_HASH_TPC_REQ_TAB_SIZE MAX_TPC_REQ_TAB_SIZE + +#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ + +#define TPC_REQ_AGE_OUT 500 /* ms */ +#define MQ_REQ_AGE_OUT 500 /* ms */ + +#define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) & (MAX_HASH_TPC_REQ_TAB_SIZE - 1)) +#define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) & (MAX_MEASURE_REQ_TAB_SIZE - 1)) + +typedef struct _MEASURE_REQ_ENTRY +{ + struct _MEASURE_REQ_ENTRY *pNext; + ULONG lastTime; + BOOLEAN Valid; + UINT8 DialogToken; + UINT8 MeasureDialogToken[3]; /* 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure. */ +} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY; + +typedef struct _MEASURE_REQ_TAB +{ + UCHAR Size; + PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE]; + MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE]; +} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB; + +typedef struct _TPC_REQ_ENTRY +{ + struct _TPC_REQ_ENTRY *pNext; + ULONG lastTime; + BOOLEAN Valid; + UINT8 DialogToken; +} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY; + +typedef struct _TPC_REQ_TAB +{ + UCHAR Size; + PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE]; + TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE]; +} TPC_REQ_TAB, *PTPC_REQ_TAB; + + +/* The regulatory information */ +typedef struct _DOT11_CHANNEL_SET +{ + UCHAR NumberOfChannels; + UINT8 MaxTxPwr; + UCHAR ChannelList[16]; +} DOT11_CHANNEL_SET, *PDOT11_CHANNEL_SET; + +typedef struct _DOT11_REGULATORY_INFORMATION +{ + UCHAR RegulatoryClass; + DOT11_CHANNEL_SET ChannelSet; +} DOT11_REGULATORY_INFORMATION, *PDOT11_REGULATORY_INFORMATION; + + + +#define RM_TPC_REQ 0 +#define RM_MEASURE_REQ 1 + +#define RM_BASIC 0 +#define RM_CCA 1 +#define RM_RPI_HISTOGRAM 2 +#define RM_CH_LOAD 3 +#define RM_NOISE_HISTOGRAM 4 + + +typedef struct GNU_PACKED _TPC_REPORT_INFO +{ + UINT8 TxPwr; + UINT8 LinkMargin; +} TPC_REPORT_INFO, *PTPC_REPORT_INFO; + +typedef struct GNU_PACKED _CH_SW_ANN_INFO +{ + UINT8 ChSwMode; + UINT8 Channel; + UINT8 ChSwCnt; +} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO; + +typedef union GNU_PACKED _MEASURE_REQ_MODE +{ +#ifdef RT_BIG_ENDIAN + struct GNU_PACKED + { + + UINT8 :3; + UINT8 DurationMandatory:1; + UINT8 Report:1; + UINT8 Request:1; + UINT8 Enable:1; + UINT8 Parallel:1; + } field; +#else + struct GNU_PACKED + { + UINT8 Parallel:1; + UINT8 Enable:1; + UINT8 Request:1; + UINT8 Report:1; + UINT8 DurationMandatory:1; + UINT8 :3; + } field; +#endif /* RT_BIG_ENDIAN */ + UINT8 word; +} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; + +typedef struct GNU_PACKED _MEASURE_REQ +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; +} MEASURE_REQ, *PMEASURE_REQ; + +typedef struct GNU_PACKED _MEASURE_REQ_INFO +{ + UINT8 Token; + MEASURE_REQ_MODE ReqMode; + UINT8 ReqType; + UINT8 Oct[0]; +} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO; + +typedef union GNU_PACKED _MEASURE_BASIC_REPORT_MAP +{ +#ifdef RT_BIG_ENDIAN + struct GNU_PACKED + { + UINT8 Rev:3; + + UINT8 Unmeasure:1; + UINT8 Radar:1; + UINT8 UnidentifiedSignal:1; + UINT8 OfdmPreamble:1; + UINT8 BSS:1; + } field; +#else + struct GNU_PACKED + { + UINT8 BSS:1; + + UINT8 OfdmPreamble:1; + UINT8 UnidentifiedSignal:1; + UINT8 Radar:1; + UINT8 Unmeasure:1; + UINT8 Rev:3; + } field; +#endif /* RT_BIG_ENDIAN */ + UINT8 word; +} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; + +typedef struct GNU_PACKED _MEASURE_BASIC_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + MEASURE_BASIC_REPORT_MAP Map; +} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT; + +typedef struct GNU_PACKED _MEASURE_CCA_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 CCA_Busy_Fraction; +} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT; + +typedef struct GNU_PACKED _MEASURE_RPI_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 RPI_Density[8]; +} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT; + +typedef union GNU_PACKED _MEASURE_REPORT_MODE +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 Rev:5; + UINT8 Refused:1; + UINT8 Incapable:1; + UINT8 Late:1; +#else + UINT8 Late:1; + UINT8 Incapable:1; + UINT8 Refused:1; + UINT8 Rev:5; +#endif /* RT_BIG_ENDIAN */ + } field; + UINT8 word; +} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; + +typedef struct GNU_PACKED _MEASURE_REPORT_INFO +{ + UINT8 Token; + UINT8 ReportMode; + UINT8 ReportType; + UINT8 Octect[0]; +} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO; + +typedef struct GNU_PACKED _QUIET_INFO +{ + UINT8 QuietCnt; + UINT8 QuietPeriod; + UINT16 QuietDuration; + UINT16 QuietOffset; +} QUIET_INFO, *PQUIET_INFO; + +#endif /* __SPECTRUM_DEF_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sta.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sta.h new file mode 100644 index 000000000..5d752905c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sta.h @@ -0,0 +1,110 @@ +/* + *************************************************************************** + * 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: + sta.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __STA_H__ +#define __STA_H__ + + +BOOLEAN RTMPCheckChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel); + +VOID InitChannelRelatedValue( + IN PRTMP_ADAPTER pAd); + +VOID AdjustChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *pBwFallBack, + IN USHORT ifIndex, + IN BOOLEAN BandWidth, + IN UCHAR PriCh, + IN UCHAR ExtraCh); + +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey); + +INT RTMPCheckRxError( + IN RTMP_ADAPTER *pAd, + IN HEADER_802_11 *pHeader, + IN RX_BLK *pRxBlk, + IN RXINFO_STRUC *pRxInfo); + +VOID WpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WpaStaPairwiseKeySetting( + IN PRTMP_ADAPTER pAd); + +VOID WpaStaGroupKeySetting( + IN PRTMP_ADAPTER pAd); + +VOID WpaSendEapolStart( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pBssid); + + +VOID STAHandleRxDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +#ifdef TXBF_SUPPORT +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx, + IN UCHAR TxSndgTypePerEntry); + +#else + +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); +#endif + +INT STASendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket); + +INT STAInitialize(RTMP_ADAPTER *pAd); + +#endif /* __STA_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sta_cfg.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sta_cfg.h new file mode 100644 index 000000000..72048bfd1 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/sta_cfg.h @@ -0,0 +1,62 @@ +/* + *************************************************************************** + * 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: + sta_cfg.h + + Abstract: + + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __STA_CFG_H__ +#define __STA_CFG_H__ + +INT RTMPSTAPrivIoctlSet( + IN RTMP_ADAPTER *pAd, + IN PSTRING SetProcName, + IN PSTRING ProcArg); + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +/* set WOW enable */ +INT Set_WOW_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +/* set GPIO pin for wake-up signal */ +INT Set_WOW_GPIO( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +/* set delay time for WOW really enable */ +INT Set_WOW_Delay( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +/* set wake up hold time */ +INT Set_WOW_Hold( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +/* set wakeup signal type */ +INT Set_WOW_InBand( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +#endif /* __STA_CFG_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls.h new file mode 100644 index 000000000..26ed991ad --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls.h @@ -0,0 +1,1125 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT + +#ifndef __TDLS_H +#define __TDLS_H + +#include "dot11z_tdls.h" +//#include "dot11r_ft.h" + +#define LENGTH_TDLS_H 24 +#define LENGTH_TDLS_PAYLOAD_H 3 /* payload type(1 byte) + category(1 byte) + action(1 byte) */ +#define TDLS_TIMEOUT 5000 // unit: msec +#define TDLS_DISCOVERY_TRY_COUNT 2 +#define TDLS_AUTO_DISCOVERY_INTERVAL 600 /* unit: msec */ +#define TDLS_RSSI_MEASUREMENT_PERIOD 10 /* unit: sec */ +#define TDLS_AUTO_DISCOVERY_PERIOD 120 /* unit: sec */ +#define TDLS_DISABLE_PERIOD_BY_TEARDOWN 120 /* unit: sec */ +#define TDLS_AUTO_SETUP_RSSI_THRESHOLD -70 /* unit: dbm */ +#define TDLS_AUTO_TEARDOWN_RSSI_THRESHOLD -75 /* unit: dbm */ + +#define TDLS_AUTO_DISCOVERY_TRY_COUNT 2 + +extern UCHAR CipherSuiteTDLSWpa2PskAes[]; +extern UCHAR CipherSuiteTDLSLen; + +#define IS_TDLS_SUPPORT(_P) \ + ((_P)->StaCfg.TdlsInfo.bTDLSCapable == TRUE) + +// TDLS State +typedef enum _TDLS_STATE { + TDLS_MODE_NONE, /* Init state */ + TDLS_MODE_WAIT_RESPONSE, /* Wait a response from the Responder */ + TDLS_MODE_WAIT_CONFIRM, /* Wait an confirm from the Initiator */ + TDLS_MODE_CONNECTED, /* Tunneled Direct Link estabilished */ +/* TDLS_MODE_SWITCH_CHANNEL, */ +/* TDLS_MODE_PSM, */ +/* TDLS_MODE_UAPSD */ +} TDLS_STATE; + +// TDLS State +typedef enum _TDLS_CHANNEL_SWITCH_STATE { + TDLS_CHANNEL_SWITCH_NONE, // Init state + TDLS_CHANNEL_SWITCH_WAIT_RSP, // Wait a response from the Responder + TDLS_CHANNEL_SWITCH_DONE, // Channel Switch Finish +} TDLS_CHANNEL_SWITCH_STATE; + +typedef struct _MLME_TDLS_REQ_STRUCT { + PRT_802_11_TDLS pTDLS; + USHORT Reason; + UCHAR Action; + BOOLEAN IsViaAP; +} MLME_TDLS_REQ_STRUCT, *PMLME_TDLS_REQ_STRUCT; + +typedef struct _MLME_TDLS_DISCOVERY_STRUCT { + UCHAR BSSID[MAC_ADDR_LEN]; + UCHAR InitiatorAddr[MAC_ADDR_LEN]; + UCHAR ResponderAddr[MAC_ADDR_LEN]; + UINT8 DialogToken; +} MLME_TDLS_DISCOVERY_STRUCT, *PMLME_TDLS_DISCOVERY_STRUCT; + +typedef struct _MLME_TDLS_CH_SWITCH_STRUCT { + UCHAR PeerMacAddr[MAC_ADDR_LEN]; + //UINT8 DialogToken; + UINT8 TargetChannel; + UINT8 TargetChannelBW; +} MLME_TDLS_CH_SWITCH_STRUCT, *PMLME_TDLS_CH_SWITCH_STRUCT; + +#define TDLS_DISCOVERY_PEER_ENTRY_SIZE 32 +typedef struct _TDLS_DISCOVERY_ENTRY { + struct _TDLS_DISCOVERY_ENTRY *pNext; + ULONG InitRefTime; + UCHAR Responder[MAC_ADDR_LEN]; + UCHAR RetryCount; + UCHAR DialogToken; + TDLS_CTRL_STATE CurrentState; + CHAR AvgRssi0; + BOOLEAN bTDLSCapable; + BOOLEAN bConnected; + BOOLEAN bFirstTime; + BOOLEAN bConnectedFirstTime; +} TDLS_DISCOVERY_ENTRY, *PTDLS_DISCOVERY_ENTRY; + +typedef struct _TDLS_BLACK_ENTRY { + struct _TDLS_BLACK_ENTRY *pNext; + ULONG InitRefTime; + UCHAR MacAddr[MAC_ADDR_LEN]; + UCHAR CurrentState; +} TDLS_BLACK_ENTRY, *PTDLS_BLACK_ENTRY; + +VOID +TDLS_Table_Init( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_Table_Destory( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_SearchTabMaintain( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_StateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID +TDLS_ChSwStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID +TDLS_CntlOidTDLSRequestProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +INT +TDLS_SearchLinkId( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID +TDLS_MlmeParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_TDLS_REQ_STRUCT *pTdlsReq, + IN PRT_802_11_TDLS pTdls, + IN USHORT Reason, + IN BOOLEAN IsViaAP); + +INT Set_TdlsCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsSetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsDiscoveryReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WFD_SUPPORT +INT Set_TdlsTunneledReqProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WFD_SUPPORT */ + +INT Set_TdlsAcceptWeakSecurityProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsTPKLifeTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef TDLS_AUTOLINK_SUPPORT +INT +Set_TdlsAutoLinkProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsRssiMeasurementPeriodProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsAutoDiscoveryPeriodProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsAutoSetupRssiThresholdProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsDisabledPeriodByTeardownProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsAutoTeardownRssiThresholdProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* TDLS_AUTOLINK_SUPPORT */ + +INT Set_TdlsSendHwNullFrameProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsChannelSwitch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsChannelSwitchBW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsChannelSwitchDisable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsManualInsEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +NDIS_STATUS +TDLS_SetupRequestAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS); + +NDIS_STATUS +TDLS_SetupResponseAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode); + +NDIS_STATUS +TDLS_SetupConfirmAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode); + +NDIS_STATUS +TDLS_DiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr); + +#ifdef WFD_SUPPORT +NDIS_STATUS +TDLS_TunneledProbeRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr); + +NDIS_STATUS +TDLS_TunneledProbeResponse( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr); +#endif /* WFD_SUPPORT */ + +NDIS_STATUS +TDLS_DiscoveryRspAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerToken, + IN PUCHAR pPeerMac); + +VOID +TDLS_DiscoveryRspPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN VOID *Msg, + IN ULONG MsgLen); + +NDIS_STATUS +TDLS_ChannelSwitchReqAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pPeerAddr, + IN UCHAR TargetChannel, + IN UCHAR TargetChannelBW); + +NDIS_STATUS +TDLS_ChannelSwitchRspAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN USHORT ChSwitchTime, + IN USHORT ChSwitchTimeOut, + IN UINT16 StatusCode, + IN UCHAR FrameType); + +VOID +TDLS_TriggerChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR DtimCount); + +#ifdef TDLS_AUTOLINK_SUPPORT +VOID +TDLS_ClearEntryList( + IN PLIST_HEADER pTdlsEnList); + +PTDLS_DISCOVERY_ENTRY +TDLS_FindDiscoveryEntry( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr); + +BOOLEAN +TDLS_InsertDiscoveryPeerEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr, + IN BOOLEAN bConnected); + +VOID +TDLS_DelDiscoveryEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr); + +VOID +TDLS_MaintainDiscoveryEntryList( + IN PRTMP_ADAPTER pAd); + +PTDLS_BLACK_ENTRY +TDLS_FindBlackEntry( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr); + +VOID +TDLS_InsertBlackEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr, + IN UCHAR CurrentState); + +VOID +TDLS_DelBlackEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr); + +VOID +TDLS_MaintainBlackList( + IN PRTMP_ADAPTER pAd, + IN PLIST_HEADER pTdlsBlackenList); +#endif // TDLS_AUTOLINK_SUPPORT // + +VOID +TDLS_InitPeerEntryRateCapability( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT *pCapabilityInfo, + IN UCHAR SupportRateLens, + IN UCHAR *pSupportRates, + IN UCHAR HtCapabilityLen, + IN HT_CAPABILITY_IE *pHtCapability); + +VOID +TDLS_BuildSetupRequest( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS); + +VOID +TDLS_BuildSetupResponse( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode); + +VOID +TDLS_BuildSetupConfirm( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode); + +VOID +TDLS_BuildTeardown( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UINT16 ReasonCode); + +VOID +TDLS_BuildChannelSwitchRequest( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pPeerAddr, + IN USHORT ChSwitchTime, + IN USHORT ChSwitchTimeOut, + IN UCHAR TargetChannel, + IN UCHAR TargetChannelBW); + +VOID +TDLS_BuildChannelSwitchResponse( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN USHORT ChSwitchTime, + IN USHORT ChSwitchTimeOut, + IN UINT16 ReasonCode); + +VOID +TDLS_InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +VOID +TDLS_InsertStatusCode( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 StatusCode); + +VOID +TDLS_InsertReasonCode( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 ReasonCode); + +VOID +TDLS_InsertDialogToken( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 DialogToken); + +VOID +TDLS_InsertLinkIdentifierIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pInitAddr, + IN PUCHAR pPeerAddr); + +VOID +TDLS_InsertCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertSSIDIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertSupportRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertCountryIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertSupportChannelIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertExtRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertQosCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertEDCAParameterSetIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS); + +VOID +TDLS_InsertWMMIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN BOOLEAN bEnable); + +VOID +TDLS_InsertWMMParameterIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +#ifdef DOT11_N_SUPPORT +VOID +TDLS_InsertHtCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +#ifdef DOT11N_DRAFT3 +VOID +TDLS_InsertBSSCoexistenceIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +VOID +TDLS_InsertExtCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_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); + +VOID +TDLS_InsertTimeoutIntervalIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN FT_TIMEOUT_INTERVAL_TYPE Type, + IN UINT32 TimeOutValue); + +VOID +TDLS_InsertTargetChannel( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TargetCh); + +VOID +TDLS_InsertRegulatoryClass( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TargetCh, + IN UINT8 ChWidth); + +VOID +TDLS_InsertSecondaryChOffsetIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR ChOffset); + +VOID +TDLS_SupportedRegulatoryClasses( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID +TDLS_InsertChannelSwitchTimingIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN USHORT SwitchTime, + IN USHORT SwitchTimeOut); + +UCHAR +TDLS_GetRegulatoryClass( + IN PRTMP_ADAPTER pAd, + IN UCHAR ChannelWidth, + IN UCHAR TargetChannel); + +BOOLEAN +TDLS_IsValidChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +UCHAR +TDLS_GetExtCh( + IN UCHAR Channel, + IN UCHAR Direction); + +VOID +TDLS_InsertPuBufferStatus( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR *pPeerMac); + +VOID +TDLS_PeerSetupReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerSetupRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerSetupConfAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_MlmeSetupReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_MlmeTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef WFD_SUPPORT +VOID TDLS_MlmeTunneledReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID TDLS_PeerTunneledReqRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* WFD_SUPPORT */ + +VOID +TDLS_MlmeDiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerDiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_MlmeChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_MlmeChannelSwitchRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerChannelSwitchReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerChannelSwitchRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_SendChannelSwitchActionFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN UCHAR FrameType); + +BOOLEAN +TDLS_MsgTypeSubst( + IN UCHAR TDLSActionType, + OUT INT *MsgType); + +BOOLEAN +TDLS_CheckTDLSframe( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCount); + +VOID +TDLS_LinkTearDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bDirect); + +VOID +TDLS_TearDownPeerLink( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerAddr, + IN BOOLEAN bDirect); + +VOID +TDLS_ForceSendChannelSwitchResponse( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS); + +BOOLEAN +MlmeTdlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_TDLS *pTDLS, + OUT PUINT16 pReason, + OUT BOOLEAN *pIsViaAP); + +ULONG +PeerTdlsBasicSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN BOOLEAN bInitiator, + OUT UCHAR *pToken, + OUT UCHAR *pSA); + +BOOLEAN +PeerTdlsSetupReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, +#ifdef WFD_SUPPORT + OUT ULONG *pWfdSubelementLen, + OUT PUCHAR pWfdSubelement, +#endif /* WFD_SUPPORT */ + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pSupRateLen, + OUT UCHAR SupRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR ExtRate[], + OUT BOOLEAN *pbWmmCapable, + OUT UCHAR *pQosCapability, + OUT UCHAR *pHtCapLen, + OUT HT_CAPABILITY_IE *pHtCap, + OUT UCHAR *pExtCapLen, + OUT EXT_CAP_INFO_ELEMENT *pExtCap, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]); + +BOOLEAN +PeerTdlsSetupRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, +#ifdef WFD_SUPPORT + OUT ULONG *pWfdSubelementLen, + OUT PUCHAR pWfdSubelement, +#endif /* WFD_SUPPORT */ + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pSupRateLen, + OUT UCHAR SupRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR ExtRate[], + OUT BOOLEAN *pbWmmCapable, + OUT UCHAR *pQosCapability, + OUT UCHAR *pHtCapLen, + OUT HT_CAPABILITY_IE *pHtCap, + OUT UCHAR *pExtCapLen, + OUT EXT_CAP_INFO_ELEMENT *pExtCap, + OUT USHORT *pStatusCode, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]); + +BOOLEAN +PeerTdlsSetupConfSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT EDCA_PARM *pEdcaParm, + OUT USHORT *pStatusCode, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]); + +BOOLEAN +PeerTdlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pSA, + OUT BOOLEAN *pIsInitator, + OUT USHORT *pReasonCode, + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[]); + +BOOLEAN +PeerTdlsDiscovReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pSA, + OUT UCHAR *pToken); + +BOOLEAN +PeerTdlsDiscovRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pSupRateLen, + OUT UCHAR SupRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pHtCapLen, + OUT HT_CAPABILITY_IE *pHtCap, + OUT UCHAR *pTdlsExtCapLen, + OUT EXT_CAP_INFO_ELEMENT *pTdlsExtCap, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]); + +BOOLEAN +PeerTdlsChannelSwitchReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pPeerAddr, + OUT BOOLEAN *pIsInitator, + OUT UCHAR *pTargetChannel, + OUT UCHAR *pRegulatoryClass, + OUT UCHAR *pNewExtChannelOffset, + OUT USHORT *pChSwitchTime, + OUT USHORT *pChSwitchTimeOut); + +BOOLEAN +PeerTdlsChannelSwitchRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pPeerAddr, + OUT USHORT *pStatusCode, + OUT USHORT *pChSwitchTime, + OUT USHORT *pChSwitchTimeOut); + +VOID +TDLS_FTDeriveTPK( + IN PUCHAR mac_i, + IN PUCHAR mac_r, + IN PUCHAR a_nonce, + IN PUCHAR s_nonce, + IN PUCHAR bssid, + IN UINT key_len, + OUT PUCHAR tpk, + OUT PUCHAR tpk_name); + +USHORT +TDLS_TPKMsg1Process( + IN PRTMP_ADAPTER pAd, +#ifdef WFD_SUPPORT + IN ULONG WfdSubelementLen, +#endif /* WFD_SUPPORT */ + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pRsnIe, + IN UCHAR RsnLen, + IN PUCHAR pFTIe, + IN UCHAR FTLen, + IN PUCHAR pTIIe, + IN UCHAR TILen); + +USHORT +TDLS_TPKMsg2Process( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pRsnIe, + IN UCHAR RsnLen, + IN PUCHAR pFTIe, + IN UCHAR FTLen, + IN PUCHAR pTIIe, + IN UCHAR TILen, + OUT PUCHAR pTPK, + OUT PUCHAR pTPKName); + +USHORT +TDLS_TPKMsg3Process( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pRsnIe, + IN UCHAR RsnLen, + IN PUCHAR pFTIe, + IN UCHAR FTLen, + IN PUCHAR pTIIe, + IN UCHAR TILen); + +NDIS_STATUS +TDLS_TearDownAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN UINT16 ReasonCode, + IN BOOLEAN bDirect); + +VOID +TDLS_SendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull); + +VOID +TDLS_LinkMaintenance( + IN PRTMP_ADAPTER pAd); + +INT +Set_TdlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +VOID +TDLS_LinkTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_OffChExpired( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_BaseChExpired( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_ChannelSwitchTimeAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_ChannelSwitchTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_DisablePeriodChannelSwitchAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_DisableMacTxRx( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_EnableMacTx( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_EnableMacRx( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_EnableMacTxRx( + IN PRTMP_ADAPTER pAd); + +VOID +TDLS_DisablePktChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR QSel); + +VOID +TDLS_EnablePktChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR QSel); + +VOID +TDLS_InitChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bEnableMACTxRx, + IN UCHAR TargetChannel, + IN UCHAR TargetChannelBW); + +VOID +TDLS_UpdateHwNullFramePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR PwrMgmt, + IN CHAR Index); + +VOID TDLS_KickOutHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR PwrMgmt, + IN CHAR Index); + +NDIS_STATUS +TDLS_SendOutActionFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN UCHAR FrameType); + +VOID +TDLS_SendOutNullFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN bQosNull, + IN BOOLEAN bWaitACK); + +VOID +TdlsMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid); + +VOID +TDLS_SoftwareRecovery( + IN PRTMP_ADAPTER pAd); + +#ifdef TDLS_AUTOLINK_SUPPORT +UCHAR +TDLS_ValidIdLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID +TDLS_AutoSetupByRcvFrame( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader); +#endif // TDLS_AUTOLINK_SUPPORT // + +#ifdef WFD_SUPPORT +BOOLEAN TDLS_PeerTunneledProbeReqRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT UCHAR *pChannel, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, + OUT ULONG *pWfdSubelementLen, + OUT PUCHAR pWfdSubelement); +#endif /* WFD_SUPPORT */ + +#endif /* __TDLS_H */ +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls_cmm.h new file mode 100644 index 000000000..9ba4a5fed --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls_cmm.h @@ -0,0 +1,217 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT + +#ifndef __TDLS_CMM_H +#define __TDLS_CMM_H + +#ifdef WFD_SUPPORT +#include "wfd_cmm.h" +#endif /* WFD_SUPPORT */ + +#define TDLS_MAX_BLACL_LIST_SZIE 64 +#define MAX_NUM_OF_TDLS_ENTRY 4 +#define TDLS_ENTRY_AGEOUT_TIME 30 /* unit: sec */ +#define TDLS_MAX_SEARCH_TABLE_SZIE 64 + +#define TDLS_SEARCH_ENTRY_AGEOUT 5000 /* seconds */ +#define TDLS_SEARCH_ENTRY_AGEOUT_LIMIT 600000 /* seconds */ +#define TDLS_SEARCH_POOL_SIZE 64 +#define TDLS_SEARCH_HASH_TAB_SIZE 32 /* the legth of hash table must be power of 2. */ + +#define TDLS_ENTRY_POOL_SIZE 8 +#define TDLS_ENTRY_HASH_TAB_SIZE 4 /* the legth of hash table must be power of 2. */ + +#ifdef WFD_SUPPORT +#define WFD_TUNNELED_PROBE_REQ 4 +#define WFD_TUNNELED_PROBE_RSP 5 +#endif /* WFD_SUPPORT */ + +#define TDLS_DISCOVERY_IDLE 0 +#define TDLS_DISCOVERY_FIRST_TIME 1 +#define TDLS_DISCOVERY_TO_SETUP 2 +#define TDLS_DISCOVERY_TO_SETUP_DONE 3 +#define TDLS_DISCOVERY_TO_SETUP_FAIL 4 +#define TDLS_CHANNEL_SWITCH_TIME 11000 /* micro seconds */ +#define TDLS_CHANNEL_SWITCH_TIMEOUT 19000 /* micro seconds */ + +#define TDLS_POWER_SAVE_ACTIVE_COUNT_DOWN_NUM (5*1000/MLME_TASK_EXEC_INTV) + +#define TDLS_FIFO_MGMT 0 +#define TDLS_FIFO_HCCA 1 +#define TDLS_FIFO_EDCA 2 +#define TDLS_FIFO_ALL 3 + +// states of tdls ctrl state machine +typedef enum _TDLS_CTRL_STATE +{ + TDLS_CTRL_IDLE, + TDLS_CTRL_CHANNEL_SWITCH, + TDLS_CTRL_MAX_STATES, +} TDLS_CTRL_STATE; + +// events of tdls ctrl state machine +typedef enum _TDLS_CTRL_EVENT +{ + // Events from SME. + TDLS_MLME_CHANNEL_SWITCH_REQ, + TDLS_MLME_CHANNEL_SWITCH_RSP, + TDLS_PEER_CHANNEL_SWITCH_REQ, + TDLS_PEER_CHANNEL_SWITCH_RSP, + TDLS_CTRL_MAX_EVENTS, +} TDLS_CTRL_EVENT; + +#define TDLS_CTRL_FUNC_SIZE (TDLS_CTRL_MAX_STATES * TDLS_CTRL_MAX_EVENTS) + +// states of tdls link management state machine +typedef enum _TDLS_LINK_MNG_STATE +{ + TDLS_LINK_IDLE, + TDLS_LINK_SETUP_REQ, + TDLS_LINK_SETUP_RSP, + TDLS_LINK_ESTAB, + TDLS_LINK_TEAR_DOWN, + TDLS_LINK_MAX_STATES, +} TDLS_LINK_MNG_STATE; + +// events of tdls link management state machine +typedef enum _TDLS_LINK_MNG_EVENT +{ + // Events from SME. + TDLS_LINK_MLME_SETUP_REQ, + TDLS_LINK_PEER_SETUP_REQ, + TDLS_LINK_PEER_SETUP_RSP, + TDLS_LINK_PEER_SETUP_CONF, + TDLS_LINK_MLME_TEARDOWN, + TDLS_LINK_PEER_TEARDOWN, + TDLS_LINK_MAX_EVENTS, +} TDLS_LINK_MNG_EVENT; + +#define TDLS_BLACK_NONE 0 +#define TDLS_BLACK_WAIT_NEXT_TRY 1 +#define TDLS_BLACK_AUTO_DISCOVERY 2 +#define TDLS_BLACK_TDLS_BY_TEARDOWN 3 + +typedef struct _TDLS_SEARCH_ENTRY { + struct _TDLS_SEARCH_ENTRY * pNext; + ULONG LastRefTime; + UCHAR RetryCount; + UCHAR InitRefTime; + UCHAR Addr[MAC_ADDR_LEN]; +} TDLS_SEARCH_ENTRY, *PTDLS_SEARCH_ENTRY; + +/* TDLS Settings for each link entry */ +typedef struct _RT_802_11_TDLS { + USHORT TimeOut; /* unit: second , set by UI */ + USHORT CountDownTimer; /* unit: second , used by driver only */ + UCHAR MacAddr[MAC_ADDR_LEN]; /* set by UI */ + UCHAR Status; /* 0: none , 1: wait result, 2: wait add , 3: connected */ + BOOLEAN Valid; /* 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link */ + /* The above parameters are the same as RT_802_11_DLS_UI */ + +#ifdef UAPSD_SUPPORT + BOOLEAN FlgIsWaitingUapsdTraRsp; /* 1: waiting for traffic rsp frame */ + UCHAR UapsdTraIndDelayCnt; /* used to send a detect traffic ind */ + BOOLEAN FlgIsUapsdTraRspRcv; /* if we have ever received rsp frame */ +#endif /* UAPSD_SUPPORT */ + + UCHAR Token; /* Dialog token */ + RALINK_TIMER_STRUCT Timer; /* Use to time out while handshake */ + BOOLEAN bInitiator; /* TRUE: I am TDLS Initiator STA, FALSE: I am TDLS Responder STA */ + UCHAR MacTabMatchWCID; + PVOID pAd; + USHORT CapabilityInfo; + + /* Copy supported rate from desired Initiator. We are trying to match */ + /* Initiator's supported and extended rate settings. */ + UCHAR SupRateLen; + UCHAR ExtRateLen; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + + /* For TPK handshake */ + UCHAR ANonce[32]; /* Generated in Message 1, random variable */ + UCHAR SNonce[32]; /* Generated in Message 2, random variable */ + ULONG KeyLifetime; /* Use type= 'Key Lifetime Interval' unit: Seconds, min lifetime = 300 seconds */ + UCHAR TPK[LEN_PMK]; /* TPK-KCK(16 bytes) for MIC + TPK-TP (16 bytes) for data */ + UCHAR TPKName[LEN_PMK_NAME]; + + /* For QOS */ + BOOLEAN bWmmCapable; /* WMM capable of the peer TDLS */ + UCHAR QosCapability; /* QOS capability of the current connecting Initiator */ + EDCA_PARM EdcaParm; /* EDCA parameters of the Initiator */ + + /* Features */ + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + UCHAR TdlsExtCapLen; + EXT_CAP_INFO_ELEMENT TdlsExtCap; + +#ifdef DOT11_VHT_AC + UCHAR vht_cap_len; + VHT_CAP_IE *vht_cap; +#endif /* DOT11_VHT_AC */ + + /* Channel Switch */ + BOOLEAN bDoingPeriodChannelSwitch; + UCHAR ChannelSwitchCurrentState; + USHORT ChSwitchTime; + RALINK_TIMER_STRUCT ChannelSwitchTimer; // Use to channel switch + USHORT ChSwitchTimeout; + RALINK_TIMER_STRUCT ChannelSwitchTimeoutTimer; // Use to channel switch + +#ifdef WFD_SUPPORT + WFD_ENTRY_INFO WfdEntryInfo; +#endif /* WFD_SUPPORT */ + +} RT_802_11_TDLS, *PRT_802_11_TDLS; + +/* change PS mode to ACTIVE mode before building a TDLS link */ +#define TDLS_CHANGE_TO_ACTIVE(__pAd) \ +{ \ + BOOLEAN __FlgOld = (__pAd)->StaCfg.TdlsInfo.TdlsFlgIsKeepingActiveCountDown; \ + (__pAd)->StaCfg.TdlsInfo.TdlsFlgIsKeepingActiveCountDown = TRUE; \ + (__pAd)->StaCfg.TdlsInfo.TdlsPowerSaveActiveCountDown = \ + TDLS_POWER_SAVE_ACTIVE_COUNT_DOWN_NUM; \ + if (__FlgOld == FALSE) \ + { \ + /* send a null frame to trigger asic wake up */ \ + RTMPSendNullFrame(__pAd, __pAd->CommonCfg.TxRate, TRUE, FALSE); \ + } \ +} + +/* recover PS mode when TdlsPowerSaveActiveCountDown = 0 */ +#define TDLS_RECOVER_POWER_SAVE(__pAd) \ +{ \ + (__pAd)->StaCfg.TdlsInfo.TdlsFlgIsKeepingActiveCountDown = FALSE; \ + (__pAd)->StaCfg.TdlsInfo.TdlsPowerSaveActiveCountDown = 0; \ + /* send a null frame to trigger asic sleep */ \ + RTMPSendNullFrame(__pAd, __pAd->CommonCfg.TxRate, TRUE, __pAd->StaCfg.Psm); \ +} +#endif /* __TDLS_CMM_H */ +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls_uapsd.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls_uapsd.h new file mode 100644 index 000000000..cbe5a4469 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/tdls_uapsd.h @@ -0,0 +1,303 @@ +/**************************************************************************** + * 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 TDLS UAPSD definitions & function prototype. + +***************************************************************************/ + + +/* sub function enable/disable */ +#define TDLS_UAPSD_DEBUG /* debug use */ +#define TDLS_UAPSD_SLEEP_MODE_CHECK /* check peer ps mode after link built */ + + +/* extern MACRO & function */ +#ifndef MODULE_TDLS_UAPSD + +#define TDLS_UAPSD_EXTERN extern + + +#else + +#define TDLS_UAPSD_EXTERN + +/* check if TDLS UAPSD function is disabled */ +#define TDLS_UAPSD_IS_DISABLED(__pAd) \ + (__pAd->CommonCfg.ExtCapIE.TdlsUAPSD == 0) + +/* assign a new dialog token */ +#define TDLS_UAPSD_DIALOG_GET(__pAd, __Token) \ + __pAd->StaCfg.TdlsInfo.TdlsDialogToken ++; \ + if (__pAd->StaCfg.TdlsInfo.TdlsDialogToken == 0) \ + __pAd->StaCfg.TdlsInfo.TdlsDialogToken ++; \ + __Token = __pAd->StaCfg.TdlsInfo.TdlsDialogToken; + +/* get self MAC address */ +#define TDLS_UAPSD_MY_MAC_GET(__pAd) \ + __pAd->CurrentAddress + +/* get self BSSID */ +#define TDLS_UAPSD_MY_BSSID_GET(__pAd) \ + __pAd->CommonCfg.Bssid + +/* get self WMM capability information */ +#define TDLS_UAPSD_CAP_INFO_GET(__pAd) \ + __pAd->StaActive.CapabilityInfo + +/* get tx rate for QoS null frame */ +#define TDLS_UAPSD_QOS_NULL_RATE_GET(__pAd) \ + __pAd->CommonCfg.TxRate + +/* check if we are in sleep mode */ +#define TDLS_UAPSD_ARE_WE_IN_PS(__pAd) \ + (__pAd->StaCfg.Psm == PWR_SAVE) + +/* check if we are in active mode */ +#define TDLS_UAPSD_ARE_WE_IN_ACTIVE(__pAd) \ + (__pAd->StaCfg.Psm != PWR_SAVE) + +/* check if the peer is in sleep mode */ +#define TDLS_UAPSD_ARE_PEER_IN_PS(__pEntry) \ + (__pEntry->PsMode == PWR_SAVE) + +/* check if the peer is in active mode */ +#define TDLS_UAPSD_ARE_PEER_IN_ACTIVE(__pEntry) \ + (__pEntry->PsMode != PWR_SAVE) + +/* get support rate element information */ +#define TDLS_UAPSD_SUP_RATE_GET(__pAd, __RateLen, __pRate) \ + __RateLen = __pAd->CommonCfg.SupRateLen; \ + NdisMoveMemory(__pRate, __pAd->CommonCfg.SupRate, __RateLen); + +/* get extended rate element information */ +#define TDLS_UAPSD_EXT_RATE_GET(__pAd, __RateLen, __pRate) \ + __RateLen = __pAd->CommonCfg.ExtRateLen; \ + NdisMoveMemory(__pRate, __pAd->CommonCfg.ExtRate, __RateLen); + +/* get extended capability element information */ +#define TDLS_UAPSD_EXT_CAP_IE_GET(__pAd, __pIE) \ + NdisMoveMemory(__pIE, &__pAd->CommonCfg.ExtCapIE, sizeof(EXT_CAP_INFO_ELEMENT)); + +/* get TDLS entry */ +#define TDLS_UAPSD_ENTRY_GET(__pAd, __LinkId) \ + &(__pAd)->StaCfg.TdlsInfo.TDLSEntry[__LinkId] + +/* send a TDLS action frame to the peer through AP */ +#define TDLS_UAPSD_PKT_SEND_THROUGH_AP(__pAd, __pHeader8023, __pFme, __FmeLen) \ + RTMPToWirelessSta(__pAd, &__pAd->MacTab.Content[BSSID_WCID], \ + __pHeader8023, LENGTH_802_3, __pFme, (UINT)__FmeLen, FALSE); + +/* send a TDLS action frame to the peer without AP's help */ +#define TDLS_UAPSD_PKT_SEND_TO_PEER(__pAd, __pHeader8023, __pFme, __FmeLen, __pTDLS) \ + RTMPToWirelessSta(__pAd, &__pAd->MacTab.Content[__pTDLS->MacTabMatchWCID], \ + __pHeader8023, LENGTH_802_3, __pFme, (UINT)__FmeLen, FALSE); + +/* resource protection */ +#define TDLS_SEMLOCK(__pAd) +#define TDLS_SEMUNLOCK(__pAd) + +/* connection sanity check */ +#define TDLS_UAPSD_IS_CONN_NOT_BUILT(__pTDLS) \ + (((__pTDLS)->Valid == 0) || ((__pTDLS)->Status < TDLS_MODE_CONNECTED)) + +/* link ID sanity check */ +#define TDLS_UAPSD_IS_LINK_INVALID(__LinkId) \ + (((__LinkId) == -1) || ((__LinkId) >= MAX_NUM_OF_TDLS_ENTRY)) + +/* rebuild a TDLS link */ +#define TDLS_UAPSD_REBUILD_LINK(__pAd, __pPeerMac) + +#define TDLS_UAPSD_ELM_PU_BUFFER_STATUS 106 +#define TDLS_UAPSD_ELM_LEN_PU_BUFFER_STATUS 3 + +#ifdef RT_BIG_ENDIAN +typedef struct __TDLS_UAPSD_PU_BUFFER_STATUS_ELM { + + UINT8 AC_BK: 1; /* bit0: AC_BK traffic available field */ + UINT8 AC_BE: 1; /* bit1: AC_BE traffic available field */ + UINT8 AC_VI: 1; /* bit2: AC_VI traffic available field */ + UINT8 AC_VO: 1; /* bit3: AC_VO traffic available field */ + + UINT8 Reserved: 4; + +} TDLS_UAPSD_PU_BUFFER_STATUS_ELM; +#else /* RT_BIG_ENDIAN */ + +typedef struct __TDLS_UAPSD_PU_BUFFER_STATUS_ELM { + + UINT8 Reserved: 4; + + UINT8 AC_VO: 1; /* bit3: AC_VO traffic available field */ + UINT8 AC_VI: 1; /* bit2: AC_VI traffic available field */ + UINT8 AC_BE: 1; /* bit1: AC_BE traffic available field */ + UINT8 AC_BK: 1; /* bit0: AC_BK traffic available field */ + +} TDLS_UAPSD_PU_BUFFER_STATUS_ELM; +#endif /* RT_BIG_ENDIAN */ + +#endif /* MODULE_WMM_UAPSD */ + + +#ifdef UAPSD_SUPPORT +#define TDLS_UAPSD_ENTRY_INIT(__pTDLS) \ + __pTDLS->FlgIsWaitingUapsdTraRsp = FALSE; +#else /* UAPSD_SUPPORT */ + +#define TDLS_UAPSD_ENTRY_INIT(__pTDLS) +#endif /* UAPSD_SUPPORT */ + + + + +/* Public function list */ +/* +======================================================================== +Routine Description: + Initialze TDLS UAPSD function. + +Arguments: + pAd - WLAN control block pointer + pFSM - TDLS Finite State Machine + +Return Value: + TRUE - init ok + FALSE - init fail + +Note: + Peer U-APSD Sleep STA is default feature in spec. + Peer U-APSD Buffer STA is optional feature in spec. +======================================================================== +*/ +TDLS_UAPSD_EXTERN BOOLEAN TDLS_UAPSDP_Init( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *pFSM); + +/* +======================================================================== +Routine Description: + Release TDLS UAPSD function. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + TRUE - release ok + FALSE - release fail + +Note: +======================================================================== +*/ +TDLS_UAPSD_EXTERN BOOLEAN TDLS_UAPSDP_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Send a traffic indication frame. + +Arguments: + pAd - WLAN control block pointer + pPeerMac - the peer MAC + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +TDLS_UAPSD_EXTERN NDIS_STATUS TDLS_UAPSDP_TrafficIndSend( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac); + +/* +======================================================================== +Routine Description: + Check if ASIC can go to sleep mode. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + Check all TDLS entries and return TRUE if all SPs are closed. +======================================================================== +*/ +TDLS_UAPSD_EXTERN BOOLEAN TDLS_UAPSDP_AsicCanSleep( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Check if ASIC can go to sleep mode. + +Arguments: + pAd - WLAN control block pointer + PsmOld - Current power save mode + PsmNew - New power save mode + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TDLS_UAPSDP_PsmModeChange( + IN PRTMP_ADAPTER pAd, + IN USHORT PsmOld, + IN USHORT PsmNew); + +/* +======================================================================== +Routine Description: + Test command. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + 0 - OK + others - FAIL +======================================================================== +*/ +TDLS_UAPSD_EXTERN INT TDLS_Ioctl( + IN PRTMP_ADAPTER pAd, + IN PSTRING pArgvIn); + +/* +======================================================================== +Routine Description: + Set our UAPSD. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + 0 - OK + others - FAIL +======================================================================== +*/ +TDLS_UAPSD_EXTERN INT Set_TdlsUapsdProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING pArgvIn); + +/* End of ap_uapsd.h */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/uapsd.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/uapsd.h new file mode 100644 index 000000000..dc98dd079 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/uapsd.h @@ -0,0 +1,769 @@ +/**************************************************************************** + * 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 WMM UAPSD definitions & function prototype. + +***************************************************************************/ + + +/* only for UAPSD_TIMING_RECORD */ + + +#define UAPSD_TIMING_RECORD_MAX 1000 +#define UAPSD_TIMING_RECORD_DISPLAY_TIMES 10 + +#define UAPSD_QUEUE_TIMEOUT 5 /* unit: seconds */ + +#define UAPSD_TIMING_RECORD_ISR 1 +#define UAPSD_TIMING_RECORD_TASKLET 2 +#define UAPSD_TIMING_RECORD_TRG_RCV 3 +#define UAPSD_TIMING_RECORD_MOVE2TX 4 +#define UAPSD_TIMING_RECORD_TX2AIR 5 + +#define UAPSD_TIMING_CTRL_STOP 0 +#define UAPSD_TIMING_CTRL_START 1 +#define UAPSD_TIMING_CTRL_SUSPEND 2 + +#ifdef UAPSD_TIMING_RECORD_FUNC +#define UAPSD_TIMING_RECORD_START() \ + UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_START); +#define UAPSD_TIMING_RECORD_STOP() \ + UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_STOP); +#define UAPSD_TIMING_RECORD(__pAd, __Type) \ + UAPSD_TimingRecord(__pAd, __Type); +#define UAPSD_TIMING_RECORD_INDEX(__LoopIndex) \ + UAPSD_TimeingRecordLoopIndex(__LoopIndex); +#else + +#define UAPSD_TIMING_RECORD_START() +#define UAPSD_TIMING_RECORD_STOP() +#define UAPSD_TIMING_RECORD(__pAd, __type) +#define UAPSD_TIMING_RECORD_INDEX(__LoopIndex) +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + +/* timing */ +#define UAPSD_TIMESTAMP_GET(__pAd, __TimeStamp) \ + { \ + UINT32 __CSR=0; UINT64 __Value64; \ + RTMP_IO_READ32((__pAd), TSF_TIMER_DW0, &__CSR); \ + __TimeStamp = (UINT64)__CSR; \ + RTMP_IO_READ32((__pAd), TSF_TIMER_DW1, &__CSR); \ + __Value64 = (UINT64)__CSR; \ + __TimeStamp |= (__Value64 << 32); \ + } + + +#define UAPSD_TIME_GET(__pAd, __Time) \ + { \ + NdisGetSystemUpTime(&__Time); \ + } + +/* uapsd packet */ +#ifdef VENDOR_FEATURE3_SUPPORT +#define UAPSD_INSERT_QUEUE_AC UAPSD_InsertTailQueueAc +#else +#define UAPSD_INSERT_QUEUE_AC InsertTailQueueAc +#endif /* VENDOR_FEATURE3_SUPPORT */ + +/* uapsd initialization */ +#define UAPSD_INFO_INIT(__pInfo) \ +{ \ + (__pInfo)->bAPSDCapable = FALSE; \ +} + +#define UAPSD_SP_START(__pAd, __pEntry) \ + __pEntry->bAPSDFlagSPStart = 1; + +#ifdef CONFIG_STA_SUPPORT +#define UAPSD_SP_END(__pAd, __pEntry) \ + __pEntry->bAPSDFlagSPStart = 0; \ + RtmpAsicSleepHandle(__pAd); +#else +/* for AP, we maybe sleep until all SPs are closed */ +#define UAPSD_SP_END(__pAd, __pEntry) \ + __pEntry->bAPSDFlagSPStart = 0; +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + +/* ASIC power save behavior */ +/* TODO: maybe need to do protection */ +#define ASIC_PS_CAN_SLEEP(__pAd) \ + __pAd->StaCfg.FlgPsmCanNotSleep = FALSE; + +#define ASIC_PS_CAN_NOT_SLEEP(__pAd) \ + __pAd->StaCfg.FlgPsmCanNotSleep = TRUE; + +/* we will recover ps mode after 5 second if no packet is received. */ +#define RTMP_PS_VIRTUAL_MAX_TIME_OUT 5 + +/* reset virtual ps mode timeout when we receive any packet from the peer */ +#define RTMP_PS_VIRTUAL_TIMEOUT_RESET(__pMacEntry) \ + if (__pMacEntry->VirtualTimeout > 0) \ + __pMacEntry->VirtualTimeout = RTMP_PS_VIRTUAL_MAX_TIME_OUT; + +/* wake up the peer virtually */ +#define RTMP_PS_VIRTUAL_WAKEUP_PEER(__pMacEntry) \ +{ \ + __pMacEntry->FlgPsModeIsWakeForAWhile = TRUE; \ + __pMacEntry->VirtualTimeout = RTMP_PS_VIRTUAL_MAX_TIME_OUT; \ + DBGPRINT(RT_DEBUG_TRACE, \ + ("%02x:%02x:%02x:%02x:%02x:%02x will not sleep for a while!\n", \ + __pMacEntry->Addr[0], __pMacEntry->Addr[1], __pMacEntry->Addr[2], \ + __pMacEntry->Addr[3], __pMacEntry->Addr[4], __pMacEntry->Addr[5])); \ +} +#endif /* CONFIG_STA_SUPPORT */ + +/* recover the peer power save mode virtually */ +#define RTMP_PS_VIRTUAL_SLEEP(__pMacEntry) \ +{ \ + __pMacEntry->FlgPsModeIsWakeForAWhile = FALSE; \ + __pMacEntry->VirtualTimeout = 0; \ + DBGPRINT(RT_DEBUG_TRACE, \ + ("%02x:%02x:%02x:%02x:%02x:%02x can sleep (ps mode = %d)!\n", \ + __pMacEntry->Addr[0], __pMacEntry->Addr[1], __pMacEntry->Addr[2], \ + __pMacEntry->Addr[3], __pMacEntry->Addr[4], __pMacEntry->Addr[5], \ + __pMacEntry->PsMode)); \ +} + +/* check if the peer virtual ps mode timeout */ +#define RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(__pMacEntry) \ +{ \ + if (__pMacEntry->VirtualTimeout > 0) \ + { \ + __pMacEntry->VirtualTimeout --; \ + if (__pMacEntry->VirtualTimeout == 0) \ + { \ + DBGPRINT(RT_DEBUG_TRACE, \ + ("tdls uapsd> virtual ps timeout!\n")); \ + RTMP_PS_VIRTUAL_SLEEP(__pMacEntry); \ + } \ + } \ +} + +/* extern MACRO & function */ +#ifndef MODULE_WMM_UAPSD + +#define UAPSD_EXTERN extern + +/* Public Marco list */ + +/* + Init some parameters in packet structure for QoS Null frame; + purpose: is for management frame tx done use +*/ +#define UAPSD_MR_QOS_NULL_HANDLE(__pAd, __pData, __pPacket) \ + { \ + PHEADER_802_11 __pHeader = (PHEADER_802_11)(__pData); \ + MAC_TABLE_ENTRY *__pEntry; \ + if (__pHeader->FC.SubType == SUBTYPE_QOS_NULL) \ + { \ + RTMP_SET_PACKET_QOS_NULL((__pPacket)); \ + __pEntry = MacTableLookup((__pAd), __pHeader->Addr1); \ + if (__pEntry != NULL) \ + { \ + RTMP_SET_PACKET_WCID((__pPacket), __pEntry->wcid); \ + } \ + } \ + else \ + { \ + RTMP_SET_PACKET_NON_QOS_NULL((__pPacket)); \ + } \ + } + +/* + Init MAC entry UAPSD parameters; + purpose: initialize UAPSD PS queue and control parameters +*/ +#define UAPSD_MR_ENTRY_INIT(__pEntry) \ + { \ + UINT16 __IdAc; \ + for(__IdAc=0; __IdAcUAPSDQueue[__IdAc]); \ + (__pEntry)->UAPSDTxNum = 0; \ + (__pEntry)->pUAPSDEOSPFrame = NULL; \ + (__pEntry)->bAPSDFlagSPStart = 0; \ + (__pEntry)->bAPSDFlagEOSPOK = 0; \ + (__pEntry)->MaxSPLength = 0; \ + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> MaxSPLength = 0!\n")); \ + } + +/* + Reset MAC entry UAPSD parameters; + purpose: clean all UAPSD PS queue; release the EOSP frame if exists; + reset control parameters +*/ +#define UAPSD_MR_ENTRY_RESET(__pAd, __pEntry) \ + { \ + MAC_TABLE_ENTRY *__pSta; \ + UINT32 __IdAc; \ + __pSta = (__pEntry); \ + /* clear all U-APSD queues */ \ + for(__IdAc=0; __IdAcUAPSDQueue[__IdAc]); \ + /* clear EOSP frame */ \ + __pSta->UAPSDTxNum = 0; \ + if (__pSta->pUAPSDEOSPFrame != NULL) { \ + RELEASE_NDIS_PACKET((__pAd), \ + QUEUE_ENTRY_TO_PACKET(__pSta->pUAPSDEOSPFrame), \ + NDIS_STATUS_FAILURE); \ + __pSta->pUAPSDEOSPFrame = NULL; } \ + __pSta->bAPSDFlagSPStart = 0; \ + __pSta->bAPSDFlagEOSPOK = 0; \ + UAPSD_SP_END(__pAd, __pSta); \ + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> clear UAPSD queues!\n")); } + +/* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ +#define UAPSD_MR_EOSP_SET(__pQosCtrl, __pTxBlk) \ + if (CLIENT_STATUS_TEST_FLAG((__pTxBlk)->pMacEntry, \ + fCLIENT_STATUS_APSD_CAPABLE)) { \ + if (TX_BLK_TEST_FLAG((__pTxBlk), fTX_bWMM_UAPSD_EOSP)) \ + *(__pQosCtrl) |= (1 << 4); \ + } + +/* + Enable or disable UAPSD flag in WMM element in beacon frame; + purpose: set UAPSD enable/disable bit +*/ +#define UAPSD_MR_IE_FILL(__QosCtrlField, __pUapsdInfo) \ + (__QosCtrlField) |= ((__pUapsdInfo)->bAPSDCapable) ? 0x80 : 0x00; + +/* + Check if we do NOT need to control TIM bit for the station; + note: we control TIM bit only when all AC are UAPSD AC +*/ +#define UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(__pMacEntry, __QueIdx) \ + (CLIENT_STATUS_TEST_FLAG((__pMacEntry), fCLIENT_STATUS_APSD_CAPABLE) && \ + (!(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_VO] || \ + !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_VI] || \ + !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_BE] || \ + !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_BK]) && \ + (__pMacEntry)->bAPSDDeliverEnabledPerAC[__QueIdx]) + +/* check if the AC is UAPSD delivery-enabled AC */ +#define UAPSD_MR_IS_UAPSD_AC(__pMacEntry, __AcId) \ + (CLIENT_STATUS_TEST_FLAG((__pMacEntry), fCLIENT_STATUS_APSD_CAPABLE) && \ + ((0 <= (__AcId)) && ((__AcId) < WMM_NUM_OF_AC)) && /* 0 ~ 3 */ \ + (__pMacEntry)->bAPSDDeliverEnabledPerAC[(__AcId)]) + +/* check if all AC are UAPSD delivery-enabled AC */ +#define UAPSD_MR_IS_ALL_AC_UAPSD(__FlgIsActive, __pMacEntry) \ + (((__FlgIsActive) == FALSE) && ((__pMacEntry)->bAPSDAllAC == 1)) + +/* suspend SP */ +#define UAPSD_MR_SP_SUSPEND(__pAd) \ + (__pAd)->bAPSDFlagSPSuspend = 1; + +/* resume SP */ +#define UAPSD_MR_SP_RESUME(__pAd) \ + (__pAd)->bAPSDFlagSPSuspend = 0; + +/* mark PS poll frame sent in mix mode */ +#ifdef RTMP_MAC_PCI +/* + Note: + (1) When SP is not started, try to mark a flag to record if the legacy ps + packet is handled in statistics handler; + (2) When SP is started, increase the UAPSD count number for the legacy PS. +*/ +#define UAPSD_MR_MIX_PS_POLL_RCV(__pAd, __pMacEntry) \ + if ((__pMacEntry)->bAPSDFlagSpRoughUse == 0) \ + { \ + if ((__pMacEntry)->bAPSDFlagSPStart == 0) \ + { \ + if ((__pMacEntry)->bAPSDFlagLegacySent == 1) \ + NICUpdateFifoStaCounters((__pAd)); \ + (__pMacEntry)->bAPSDFlagLegacySent = 1; \ + } \ + else \ + { \ + (__pMacEntry)->UAPSDTxNum ++; \ + } \ + } +#endif /* RTMP_MAC_PCI */ + + +#else + +#define UAPSD_EXTERN +#define UAPSD_QOS_NULL_QUE_ID 0x7f + +#ifdef RTMP_MAC_PCI +/* + In RT2870, FIFO counter is for all stations, not for per-entry, + so we can not use accurate method in RT2870 +*/ + +/* + Note for SP ACCURATE Mechanism: + 1. When traffic is busy for the PS station + Statistics FIFO counter maybe overflow before we read it, so UAPSD + counting mechanism will not accurately. + + Solution: + We need to avoid the worse case so we suggest a maximum interval for + a SP that the interval between last frame from QAP and data frame from + QSTA is larger than UAPSD_EPT_SP_INT. + + 2. When traffic use CCK/1Mbps from QAP + Statistics FIFO will not count the packet. There are 2 cases: + (1) We force to downgrage ARP response & DHCP packet to 1Mbps; + (2) After rate switch mechanism, tx rate is fixed to 1Mbps. + + Solution: + Use old DMA UAPSD mechanism. + + 3. When part of AC uses legacy PS mode + Statistics count will inclue packet statistics for legacy PS packets + so we can not know which one is UAPSD, which one is legacy. + + Solution: + Cound the legacy PS packet. + + 4. Check FIFO statistics count in Rx Done function + We can not to check TX FIFO statistics count in Rx Done function or + the real packet tx/rx sequence will be disarranged. + + Solution: + Suspend SP handle before rx done and resume SP handle after rx done. +*/ +#endif /* RTMP_MAC_PCI */ + +#define UAPSD_EPT_SP_INT (100000/(1000000/OS_HZ)) /* 100ms */ + +#endif /* MODULE_WMM_UAPSD */ + + +/* max UAPSD buffer queue size */ +#define MAX_PACKETS_IN_UAPSD_QUEUE 16 /* for each AC = 16*4 = 64 */ + + +/* Public function list */ +/* +======================================================================== +Routine Description: + UAPSD Module Init. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_Init( + IN PRTMP_ADAPTER pAd); + + +/* +======================================================================== +Routine Description: + UAPSD Module Release. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_Release( + IN PRTMP_ADAPTER pAd); + + +/* +======================================================================== +Routine Description: + Check if ASIC can enter sleep mode. Not software sleep. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID RtmpAsicSleepHandle( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + pEntry Close the SP of the entry + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_Close( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +/* +======================================================================== +Routine Description: + Check if the SP for entry is closed. + +Arguments: + pAd Pointer to our adapter + pEntry the peer entry + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN BOOLEAN UAPSD_SP_IsClosed( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +/* +======================================================================== +Routine Description: + Deliver all queued packets. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + SMP protection by caller for packet enqueue. +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_AllPacketDeliver( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + + +/* +======================================================================== +Routine Description: + Parse the UAPSD field in WMM element in (re)association request frame. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + *pElm QoS information field + FlgApsdCapable TRUE: Support UAPSD + +Return Value: + None + +Note: + No protection is needed. + + 1. Association -> TSPEC: + use static UAPSD settings in Association + update UAPSD settings in TSPEC + + 2. Association -> TSPEC(11r) -> Reassociation: + update UAPSD settings in TSPEC + backup static UAPSD settings in Reassociation + + 3. Association -> Reassociation: + update UAPSD settings in TSPEC + backup static UAPSD settings in Reassociation +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_AssocParse( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pElm, + IN BOOLEAN FlgApsdCapable); + + +/* +======================================================================== +Routine Description: + Enqueue a UAPSD packet. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + pPacket UAPSD dnlink packet + IdAc UAPSD AC ID (0 ~ 3) + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_PacketEnqueue( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PNDIS_PACKET pPacket, + IN UINT32 IdAc); + + +/* +======================================================================== +Routine Description: + Handle QoS Null Frame Tx Done or Management Tx Done interrupt. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_QoSNullTxMgmtTxDoneHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac); + + +/* +======================================================================== +Routine Description: + Maintenance our UAPSD PS queue. Release all queued packet if timeout. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + If in RT2870, pEntry can not be removed during UAPSD_QueueMaintenance() +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_QueueMaintenance( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + + +/* +======================================================================== +Routine Description: + Close SP in Tx Done, not Tx DMA Done. + +Arguments: + pAd Pointer to our adapter + pEntry destination entry + FlgSuccess 0:tx success, 1:tx fail + +Return Value: + None + +Note: + For RT28xx series, for packetID=0 or multicast frame, no statistics + count can be got, ex: ARP response or DHCP packets, we will use + low rate to set (CCK, MCS=0=packetID). + So SP will not be close until UAPSD_EPT_SP_INT timeout. + + So if the tx rate is 1Mbps for a entry, we will use DMA done, not + use UAPSD_SP_AUE_Handle(). +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_AUE_Handle( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FlgSuccess); + + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: + When we receive EOSP frame tx done interrupt and a uplink packet + from the station simultaneously, we will regard it as a new trigger + frame because the packet is received when EOSP frame tx done interrupt. + + We can not sure the uplink packet is sent after old SP or in the old SP. + So we must close the old SP in receive done ISR to avoid the problem. +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_CloseInRVDone( + IN PRTMP_ADAPTER pAd); + + +/* +======================================================================== +Routine Description: + Check if we need to close current SP. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: + 1. We need to call the function in TxDone ISR. + 2. SMP protection by caller for packet enqueue. +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_PacketCheck( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac); + + +#ifdef UAPSD_TIMING_RECORD_FUNC +/* +======================================================================== +Routine Description: + Enable/Disable Timing Record Function. + +Arguments: + pAd Pointer to our adapter + Flag 1 (Enable) or 0 (Disable) + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TimingRecordCtrl( + IN UINT32 Flag); + +/* +======================================================================== +Routine Description: + Record some timings. + +Arguments: + pAd Pointer to our adapter + Type The timing is for what type + +Return Value: + None + +Note: + UAPSD_TIMING_RECORD_ISR + UAPSD_TIMING_RECORD_TASKLET + UAPSD_TIMING_RECORD_TRG_RCV + UAPSD_TIMING_RECORD_MOVE2TX + UAPSD_TIMING_RECORD_TX2AIR +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TimingRecord( + IN PRTMP_ADAPTER pAd, + IN UINT32 Type); + +/* +======================================================================== +Routine Description: + Record the loop index for received packet handle. + +Arguments: + pAd Pointer to our adapter + LoopIndex The RxProcessed in rtmp_rx_done_handle() + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TimeingRecordLoopIndex( + IN UINT32 LoopIndex); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + +/* +======================================================================== +Routine Description: + Get the queue status for delivery-enabled AC. + +Arguments: + pAd Pointer to our adapter + pEntry the peer entry + pFlgIsAnyPktForBK TRUE: At lease a BK packet is queued + pFlgIsAnyPktForBE TRUE: At lease a BE packet is queued + pFlgIsAnyPktForVI TRUE: At lease a VI packet is queued + pFlgIsAnyPktForVO TRUE: At lease a VO packet is queued + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_QueueStatusGet( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + OUT BOOLEAN *pFlgIsAnyPktForBK, + OUT BOOLEAN *pFlgIsAnyPktForBE, + OUT BOOLEAN *pFlgIsAnyPktForVI, + OUT BOOLEAN *pFlgIsAnyPktForVO); + + +/* +======================================================================== +Routine Description: + Handle UAPSD Trigger Frame. + +Arguments: + pAd Pointer to our adapter + *pEntry the source STATION + UpOfFrame the UP of the trigger frame + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TriggerFrameHandle( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR UpOfFrame); + + + +/* End of ap_uapsd.h */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vht.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vht.h new file mode 100644 index 000000000..c7c2c8e74 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vht.h @@ -0,0 +1,58 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "dot11ac_vht.h" + + +struct _RTMP_ADAPTER; +struct _RT_PHY_INFO; + + +VOID dump_vht_cap(struct _RTMP_ADAPTER *pAd, VHT_CAP_IE *vht_ie); +VOID dump_vht_op(struct _RTMP_ADAPTER *pAd, VHT_OP_IE *vht_ie); + +INT build_vht_txpwr_envelope(struct _RTMP_ADAPTER *pAd, UCHAR *buf); +INT build_vht_ies(struct _RTMP_ADAPTER *pAd, UCHAR *buf, UCHAR frm); +INT build_vht_cap_ie(struct _RTMP_ADAPTER *pAd, UCHAR *buf); + +UCHAR vht_prim_ch_idx(UCHAR vht_cent_ch, UCHAR prim_ch); +UCHAR vht_cent_ch_freq(struct _RTMP_ADAPTER *pAd, UCHAR prim_ch); +INT vht_mode_adjust(struct _RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, VHT_CAP_IE *cap, VHT_OP_IE *op); +INT SetCommonVHT(struct _RTMP_ADAPTER *pAd); +VOID rtmp_set_vht(struct _RTMP_ADAPTER *pAd, struct _RT_PHY_INFO *phy_info); + +#ifdef VHT_TXBF_SUPPORT +VOID trigger_vht_ndpa(struct _RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *entry); +#endif /* VHT_TXBF_SUPPORT */ + +void assoc_vht_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op); + +BOOLEAN vht80_channel_group( struct _RTMP_ADAPTER *pAd, UCHAR channel); + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/video.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/video.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/video.h rename to package/lean/mt/drivers/mt7612e/src/mt76x2/include/video.h diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vr_ikans.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vr_ikans.h new file mode 100644 index 000000000..c5694cb85 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vr_ikans.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * 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: + vr_ikans.h + + Abstract: + Only for IKANOS Vx160 or Vx180 platform. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sample Lin 01-28-2008 Created + + */ + +#ifndef __VR_IKANS_H__ +#define __VR_IKANS_H__ + +#ifndef MODULE_IKANOS +#define IKANOS_EXTERN extern +#else +#define IKANOS_EXTERN +#endif /* MODULE_IKANOS */ + +#ifdef IKANOS_VX_1X0 + typedef void (*IkanosWlanTxCbFuncP)(void *, void *); + + struct IKANOS_TX_INFO + { + struct net_device *netdev; + IkanosWlanTxCbFuncP *fp; + }; +#endif /* IKANOS_VX_1X0 */ + + +IKANOS_EXTERN void VR_IKANOS_FP_Init(UINT8 BssNum, UINT8 *pApMac); + +IKANOS_EXTERN INT32 IKANOS_DataFramesTx(struct sk_buff *pSkb, + struct net_device *pNetDev); + +IKANOS_EXTERN void IKANOS_DataFrameRx(PRTMP_ADAPTER pAd, + struct sk_buff *pSkb); + +#endif /* __VR_IKANS_H__ */ + +/* End of vr_ikans.h */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vrut_ubm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vrut_ubm.h new file mode 100644 index 000000000..fab13c4ea --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/vrut_ubm.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * 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 Structure & Definition for UBICOM platform. + + Only used in UTIL module. + +***************************************************************************/ + +#ifndef __VR_UBICOM_H__ +#define __VR_UBICOM_H__ + +#ifdef PLATFORM_UBM_IPX8 + +#include + +#undef RTMP_UTIL_DCACHE_FLUSH +#define RTMP_UTIL_DCACHE_FLUSH(__AddrStart, __Size) \ + flush_dcache_range((ULONG)(__AddrStart), \ + (ULONG)(((UCHAR *)(__AddrStart)) + __Size - 1)) + +#endif /* PLATFORM_UBM_IPX8 */ + +#endif /* __VR_UBICOM_H__ */ + +/* End of vrut_ubm.h */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi.h new file mode 100644 index 000000000..2fbc79f56 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi.h @@ -0,0 +1,200 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2005, 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 attempt + * 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: + wapi.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Albert 2008-4-3 Supoort WAPI protocol +*/ + +#ifndef __WAPI_H__ +#define __WAPI_H__ + +#include "wpa_cmm.h" + +/* Increase TxIV value for next transmission */ +/* Todo - When overflow occurred, do re-key mechanism */ +#define INC_TX_IV(_V, NUM) \ +{ \ + UCHAR cnt = LEN_WAPI_TSC; \ + do \ + { \ + cnt--; \ + _V[cnt] = _V[cnt] + NUM; \ + if (cnt == 0) \ + { \ + DBGPRINT(RT_DEBUG_TRACE, ("PN overflow!!!!\n")); \ + break; \ + } \ + }while (_V[cnt] == 0); \ +} + +#define IS_WAPI_CAPABILITY(a) (((a) >= Ndis802_11AuthModeWAICERT) && ((a) <= Ndis802_11AuthModeWAIPSK)) + +/* The underlying chip supports hardware-based WPI-SMS4 encryption and de-encryption. */ +#define IS_HW_WAPI_SUPPORT(__pAd) (__pAd->chipCap.FlgIsHwWapiSup) +/* + ===================================== + function prototype in wapi_crypt.c + ===================================== +*/ +int wpi_cbc_mac_engine( + unsigned char * maciv_in, + unsigned char * in_data1, + unsigned int in_data1_len, + unsigned char * in_data2, + unsigned int in_data2_len, + unsigned char * pkey, + unsigned char * mac_out); + +int wpi_sms4_ofb_engine( + unsigned char * pofbiv_in, + unsigned char * pbw_in, + unsigned int plbw_in, + unsigned char * pkey, + unsigned char * pcw_out); + +VOID RTMPInsertWapiIe( + IN UINT AuthMode, + IN UINT WepStatus, + OUT PUCHAR pWIe, + OUT UCHAR *w_len); + +BOOLEAN RTMPCheckWAIframe( + IN PUCHAR pData, + IN ULONG DataByteCount); + +VOID RTMPConstructWPIIVHdr( + IN UCHAR key_id, + IN UCHAR *tx_iv, + OUT UCHAR *iv_hdr); + +#ifdef RTMP_RBUS_SUPPORT +INT RTMPSoftEncryptSMS4( + IN PUCHAR pHeader, + IN PUCHAR pData, + IN UINT32 data_len, + IN UCHAR key_id, + IN PUCHAR pKey, + IN PUCHAR pIv); + +INT RTMPSoftDecryptSMS4( + IN PUCHAR pHdr, + IN BOOLEAN bSanityIV, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt); +#else +extern INT RTMPSoftEncryptSMS4( + IN PUCHAR pHeader, + IN PUCHAR pData, + IN UINT32 data_len, + IN UCHAR key_id, + IN PUCHAR pKey, + IN PUCHAR pIv); +extern INT RTMPSoftDecryptSMS4( + IN PUCHAR pHdr, + IN BOOLEAN bSanityIV, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt); +#endif /* RTMP_RBUS_SUPPORT */ + +VOID RTMPDeriveWapiGTK( + IN PUCHAR nmk, + OUT PUCHAR gtk_ptr); + +VOID RT_SMS4_TEST( + IN UINT8 test); + +INT SMS4_TEST(void); + +/* + ===================================== + function prototype in wapi.c + ===================================== +*/ + +BOOLEAN RTMPIsWapiCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); + +VOID RTMPIoctlQueryWapiConf( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +void rtmp_read_wapi_parms_from_file( + IN PRTMP_ADAPTER pAd, + char *tmpbuf, + char *buffer); + +VOID RTMPWapiUskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPWapiMskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPInitWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPStartWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPCancelWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPGetWapiTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UINT Wcid, + OUT UCHAR *tx_tsc); + +VOID WAPIInstallPairwiseKey( + PRTMP_ADAPTER pAd, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE); + +VOID WAPIInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + PUINT8 pGtk); + +BOOLEAN WAPI_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR apidx, + IN PUCHAR pAddr, + IN UCHAR flag); + +#endif /* __WAPI_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi_def.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi_def.h new file mode 100644 index 000000000..774bdae1c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi_def.h @@ -0,0 +1,179 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2005, 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 attempt + * 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: + wapi_def.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __WAPI_DEF_H__ +#define __WAPI_DEF_H__ + +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define WAPI_IFNAMSIZ 16 +#define MAX_WAPI_MBSSID_NUM 8 +#define MAX_ID_NO 10 + +#define LENGTH_WAI_H 12 +#define LEN_WAPI_TSC 16 +#define LEN_WPI_MIC 16 +#define LEN_WPI_IV_HDR 18 +#define LEN_WAPI_NMK 16 +#define LEN_WAPI_GTK 32 + +/* trigger message from driver */ +#define WAI_MLME_CERT_AUTH_START 1 +#define WAI_MLME_KEY_HS_START 2 +#define WAI_MLME_UPDATE_BK 3 +#define WAI_MLME_UPDATE_USK 4 +#define WAI_MLME_UPDATE_MSK 5 +#define WAI_MLME_DISCONNECT 0xff + +#define WAPI_KEY_UPDATE_EXEC_INTV 1000 /* 1 sec */ + +/* WAPI rekey method */ +#define REKEY_METHOD_DISABLE 0 +#define REKEY_METHOD_TIME 1 +#define REKEY_METHOD_PKT 2 +/*#define REKEY_METHOD_TIME_PKT 3 */ + +#define STATUS_WAPI_KEY_INVALID 1 +#define STATUS_WAPI_IV_MISMATCH 2 +#define STATUS_WAPI_MIC_DIFF 3 + +extern UCHAR AE_BCAST_PN[LEN_WAPI_TSC]; +extern UCHAR ASUE_UCAST_PN[LEN_WAPI_TSC]; +extern UCHAR AE_UCAST_PN[LEN_WAPI_TSC]; + +/* WAPI authentication mode */ +typedef enum _WAPI_AUTH_MODE +{ + WAPI_AUTH_DISABLE, + WAPI_AUTH_PSK, + WAPI_AUTH_CERT, +} WAPI_AUTH_MODE, *PWAPI_AUTH_MODE; + +/* WAPI authentication mode */ +typedef enum _KEY_TYPE_MODE +{ + HEX_MODE, + ASCII_MODE +} KEY_TYPE_MODE, *PKEY_TYPE_MODE; + +/* the defintion of WAI header */ +typedef struct GNU_PACKED _HEADER_WAI { + USHORT version; + UCHAR type; + UCHAR sub_type; + USHORT reserved; + USHORT length; + USHORT pkt_seq; + UCHAR frag_seq; + UCHAR flag; +} HEADER_WAI, *PHEADER_WAI; + +/* For WAPI */ +typedef struct GNU_PACKED _WAPIIE { + USHORT version; + USHORT acount; + struct GNU_PACKED { + UCHAR oui[4]; + }auth[1]; +} WAPIIE, *PWAPIIE; + +/* unicast key suite */ +typedef struct GNU_PACKED _WAPIIE_UCAST { + USHORT ucount; + struct GNU_PACKED { + UCHAR oui[4]; + }ucast[1]; +} WAPIIE_UCAST,*PWAPIIE_UCAST; + +/* multi-cast key suite and capability */ +typedef struct GNU_PACKED _WAPIIE_MCAST { + UCHAR mcast[4]; + USHORT capability; +} WAPIIE_MCAST,*PWAPIIE_MCAST; + +/* the relative to wapi daemon */ +typedef struct GNU_PACKED _COMMON_WAPI_INFO +{ + UINT8 wapi_ifname[WAPI_IFNAMSIZ]; /* wai negotiation */ + UINT8 wapi_ifname_len; + UINT8 preauth_ifname[WAPI_IFNAMSIZ]; /* pre-authentication */ + UINT8 preauth_ifname_len; + UINT8 as_cert_no; + UINT8 as_cert_path[MAX_ID_NO][128]; /* the path of as certification */ + UINT8 as_cert_path_len[MAX_ID_NO]; + UINT8 ca_cert_path[128]; /* the path of ca certification */ + UINT8 ca_cert_path_len; + UINT8 user_cert_path[128]; /* the path of local user certification */ + UINT8 user_cert_path_len; + UINT32 wapi_as_ip; /* the ip address of authentication server */ + UINT32 wapi_as_port; /* the port of authentication server */ +} COMMON_WAPI_INFO, *PCOMMON_WAPI_INFO; + +typedef struct GNU_PACKED _MBSS_WAPI_INFO +{ + UINT8 ifname[WAPI_IFNAMSIZ]; + UINT8 ifname_len; + UINT8 auth_mode; + UINT8 psk[64]; + UINT8 psk_len; + UINT8 wie[128]; + UINT8 wie_len; +} MBSS_WAPI_INFO, *PMBSS_WAPI_INFO; + +/* It's used by wapi daemon to require relative configuration */ +typedef struct GNU_PACKED _WAPI_CONF +{ + UINT8 mbss_num; /* indicate multiple BSS number */ + COMMON_WAPI_INFO comm_wapi_info; + MBSS_WAPI_INFO mbss_wapi_info[MAX_WAPI_MBSSID_NUM]; +} WAPI_CONF, *PWAPI_CONF; + +#ifdef LINUX +#define WapiMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define WapiZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define WapiEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#endif /* LINUX */ + +#endif /* __WAPI_DEF_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi_sms4.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi_sms4.h new file mode 100644 index 000000000..ef90f2a46 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wapi_sms4.h @@ -0,0 +1,12 @@ + + +/* SMS4 encryption/decryption definition */ +/* Parameter : */ +/* Input - the incoming message packet */ +/* Ouput - the result ouput */ +/* rk - key */ +void SMS4Crypt(unsigned char *Input, unsigned char *Output, unsigned int *rk); + +/* SMS4 key extend algorithm */ +void SMS4KeyExt(unsigned char *Key, unsigned int *rk, unsigned int CryptFlag); + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfa_p2p.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfa_p2p.h new file mode 100644 index 000000000..d7af1bdbc --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfa_p2p.h @@ -0,0 +1,167 @@ +/**************************************************************************** + * 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: + wfa_p2p.h + + Abstract: + Defined status code, IE and frame structures that WiFi Direct needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + + */ + + +#ifndef __WFA_P2P_H +#define __WFA_P2P_H + +#include "rtmp_type.h" + + +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_SUPPORT) + +typedef struct _P2P_PUBLIC_FRAME { + HEADER_802_11 p80211Header; + UCHAR Category; + UCHAR Action; + UCHAR OUI[3]; + UCHAR OUIType; + UCHAR Subtype; + UCHAR Token; + UCHAR ElementID; + UCHAR Length; + UCHAR OUI2[3]; + UCHAR OUIType2; + UCHAR Octet[1]; +} + P2P_PUBLIC_FRAME, *PP2P_PUBLIC_FRAME; + +typedef struct _P2P_ACTION_FRAME { + HEADER_802_11 p80211Header; + UCHAR Category; + UCHAR OUI[3]; + UCHAR OUIType; + UCHAR Subtype; + UCHAR Token; + UCHAR Octet[1]; +} P2P_ACTION_FRAME, *PP2P_ACTION_FRAME; + +typedef struct _FRAME_P2P_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR OUI[3]; + UCHAR OUIType; /* 1 */ + UCHAR OUISubType; /* 1 */ + UCHAR Token; /* 1 */ +} FRAME_P2P_ACTION, *PFRAME_P2P_ACTION; + +typedef struct _MLME_P2P_ACTION_STRUCT { + UCHAR TabIndex; /* sometimes it's Mactable index, sometime it's P2P table index. depend on the command. */ + UCHAR Addr[MAC_ADDR_LEN]; +} MLME_P2P_ACTION_STRUCT, *PMLME_P2P_ACTION_STRUCT; + +typedef struct _P2P_NOA_DESC { + UCHAR Count; + UCHAR Duration[4]; + UCHAR Interval[4]; + UCHAR StartTime[4]; +} P2P_NOA_DESC, *PP2P_NOA_DESC; + + +/* General format of P2P attribut(4.1.1) */ +#define SUBID_P2P_STATUS 0 +#define SUBID_P2P_MINOR_REASON 1 +#define SUBID_P2P_CAP 2 +#define SUBID_P2P_DEVICE_ID 3 +#define SUBID_P2P_OWNER_INTENT 4 +#define SUBID_P2P_CONFIG_TIMEOUT 5 +#define SUBID_P2P_LISTEN_CHANNEL 6 +#define SUBID_P2P_GROUP_BSSID 7 +#define SUBID_P2P_EXT_LISTEN_TIMING 8 +#define SUBID_P2P_INTERFACE_ADDR 9 +#define SUBID_P2P_MANAGEABILITY 10 +#define SUBID_P2P_CHANNEL_LIST 11 +#define SUBID_P2P_NOA 12 +#define SUBID_P2P_DEVICE_INFO 13 +#define SUBID_P2P_GROUP_INFO 14 +#define SUBID_P2P_GROUP_ID 15 +#define SUBID_P2P_INTERFACE 16 +#define SUBID_P2P_OP_CHANNEL 17 +#define SUBID_P2P_INVITE_FLAG 18 +#define SUBID_P2P_VENDOR 221 + +/* Status Code definitions(4.1.2) */ +#define P2PSTATUS_SUCCESS 0 +#define P2PSTATUS_PASSED 1 +#define P2PSTATUS_IMCOMPA_PARM 2 +#define P2PSTATUS_LIMIT 3 +#define P2PSTATUS_INVALID_PARM 4 +#define P2PSTATUS_UNABLE 5 +#define P2PSTATUS_NO_CHANNEL 7 +#define P2PSTATUS_UNKNOWN_GROUP 8 +#define P2PSTATUS_BOTH_INTENT15 9 +#define P2PSTATUS_INCOMPATIBLE_PROVISION 10 +#define P2PSTATUS_REJECT_BY_USER 11 + +//bitmap of P2P Capability/ 1st byte is DEVCAP, 2nd byte is GRPCAP +/* Device Capability Bitmap definitio(4.1.4) */ +#define DEVCAP_SD 0x1 //Service discovery +#define DEVCAP_CLIENT_DISCOVER 0x2 +#define DEVCAP_CLIENT_CONCURRENT 0x4 +#define DEVCAP_INFRA_MANAGED 0x8 +#define DEVCAP_DEVICE_LIMIT 0x10 +#define DEVCAP_INVITE 0x20 + +/*Group Capability Bitmap definition(4.1.4) */ +#define GRPCAP_OWNER 0x1 +#define GRPCAP_PERSISTENT 0x2 +#define GRPCAP_LIMIT 0x4 +#define GRPCAP_INTRA_BSS 0x8 +#define GRPCAP_CROSS_CONNECT 0x10 +#define GRPCAP_PERSISTENT_RECONNECT 0x20 +#define GRPCAP_GROUP_FORMING 0x40 + + +/* P2P public action frame typ(4.2.8) */ +#define GO_NEGOCIATION_REQ 0 +#define GO_NEGOCIATION_RSP 1 +#define GO_NEGOCIATION_CONFIRM 2 +#define P2P_INVITE_REQ 3 +#define P2P_INVITE_RSP 4 +#define P2P_DEV_DIS_REQ 5 +#define P2P_DEV_DIS_RSP 6 +#define P2P_PROVISION_REQ 7 +#define P2P_PROVISION_RSP 8 + +/* P2P action frame typ(4.2.9) */ +#define P2PACT_NOA 0 +#define P2PACT_PERSENCE_REQ 1 +#define P2PACT_PERSENCE_RSP 2 +#define P2PACT_GO_DISCOVER_REQ 3 + +/* Service Protocol Type */ +#define SERVICE_PROTOCOL_TYPE_ALL 0 +#define SERVICE_PROTOCOL_TYPE_BONJOUR 1 +#define SERVICE_PROTOCOL_TYPE_UPNP 2 +#define SERVICE_PROTOCOL_TYPE_WS_DISCOVERY 3 +#define SERVICE_PROTOCOL_TYPE_WFD 4 +#define SERVICE_PROTOCOL_TYPE_VENDOR_SPECIFIC 255 + +#endif /* P2P_SUPPORT */ + +#endif /* __WFA_P2P_H */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfd.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfd.h new file mode 100644 index 000000000..beb88fa47 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfd.h @@ -0,0 +1,149 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2005-2011 Ralink Technology Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Ralink Technology Corporation + 5F, No.5, Tai-Yuen 1st St., Jhubei City, + HsinChu Hsien 30265, Taiwan, R.O.C. + + + BSD LICENSE + + Copyright(c) 2005-2011 Ralink Technology Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +/* + Module Name: + wfd.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + + +#ifndef __WFD_H__ +#define __WFD_H__ + +#ifdef WFD_SUPPORT + +#include "rtmp_type.h" + +INT Set_WfdEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RT_CFG80211_SUPPORT +INT Set_WfdInsertIe_Proc +( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT_CFG80211_SUPPORT */ + +INT Set_WfdDeviceType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WfdCouple_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WfdSessionAvailable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WfdCP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WfdRtspPort_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WfdMaxThroughput_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WfdLocalIp_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PeerRtspPort_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID WfdMakeWfdIE( + IN PRTMP_ADAPTER pAd, + IN ULONG WfdIeBitmap, + OUT PUCHAR pOutBuf, + OUT PULONG pIeLen); + +ULONG InsertWfdSubelmtTlv( + IN PRTMP_ADAPTER pAd, + IN UCHAR SubId, + IN PUCHAR pInBuffer, + IN PUCHAR pOutBuffer, + IN UINT Action); + +VOID WfdParseSubElmt( + IN PRTMP_ADAPTER pAd, + IN PWFD_ENTRY_INFO pWfdEntryInfo, + IN VOID *Msg, + IN ULONG MsgLen); + +VOID WfdCfgInit( + IN PRTMP_ADAPTER pAd); + +#endif /* WFD_SUPPORT */ +#endif /* __WFD_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfd_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfd_cmm.h new file mode 100644 index 000000000..4d58fc541 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wfd_cmm.h @@ -0,0 +1,293 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2005-2011 Ralink Technology Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Ralink Technology Corporation + 5F, No.5, Tai-Yuen 1st St., Jhubei City, + HsinChu Hsien 30265, Taiwan, R.O.C. + + + BSD LICENSE + + Copyright(c) 2005-2011 Ralink Technology Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +/* + Module Name: + wfd.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + + +#ifndef __WFD_CMM_H__ +#define __WFD_CMM_H__ + +#ifdef WFD_SUPPORT + +#include "rtmp_type.h" + +#define WFD_OUI 0x506F9A + +/* Subelement ID Definitions */ +#define SUBID_WFD_DEVICE_INFO 0 +#define SUBID_WFD_ASSOCIATED_BSSID 1 +#define SUBID_WFD_AUDIO_FORMATS 2 +#define SUBID_WFD_VIDEO_FORMATS 3 +#define SUBID_WFD_3D_VIDEO_FORMATS 4 +#define SUBID_WFD_CONTENT_PROTECTION 5 +#define SUBID_WFD_COUPLED_SINK_INFO 6 +#define SUBID_WFD_EXTENDED_CAP 7 +#define SUBID_WFD_LOCAL_IP_ADDR 8 +#define SUBID_WFD_SESSION_INFO 9 +#define SUBID_WFD_ALTERNATE_MAC_ADDR 10 +#define SUBID_WFD_END 11 + +/* Subelement ID Definitions */ +#define SUBID_WFD_DEVICE_INFO_LEN 6 +#define SUBID_WFD_ASSOCIATED_BSSID_LEN 6 +#define SUBID_WFD_AUDIO_FORMATS_LEN 15 +#define SUBID_WFD_VIDEO_FORMATS_LEN 21 +#define SUBID_WFD_3D_VIDEO_FORMATS_LEN 13 +#define SUBID_WFD_CONTENT_PROTECTION_LEN 1 +#define SUBID_WFD_COUPLED_SINK_INFO_LEN 1 +#define SUBID_WFD_EXTENDED_CAP_LEN 2 +#define SUBID_WFD_LOCAL_IP_ADDR_LEN 5 +#define SUBID_WFD_ALTERNATE_MAC_ADDR_LEN 6 +#define WFD_SOURCE 0x0 +#define WFD_PRIMARY_SINK 0x1 +#define WFD_SECONDARY_SINK 0x2 +#define WFD_SOURCE_PRIMARY_SINK 0x3 +#define WFD_DEVICE_TYPE_END 0x4 + +#define WFD_COUPLED_NOT_SUPPORT 0x0 +#define WFD_COUPLED_SUPPORT 0x1 + +#define WFD_SESSION_NOT_AVAILABLE 0x0 +#define WFD_SESSION_AVAILABLE 0x1 + +#define WFD_WSD_NOT_SUPPORT 0x0 +#define WFD_WSD_SUPPORT 0x1 + +#define WFD_PC_P2P 0x0 +#define WFD_PC_TDLS 0x1 + +#define WFD_CP_NOT_SUPPORT 0x0 +#define WFD_CP_HDCP20 0x1 + +#define WFD_TIME_SYNC_NOT_SUPPORT 0x0 +#define WFD_TIME_SYNC_SUPPORT 0x1 /* Time Synchronization using 802.1AS */ + +#define WFD_TDLS_WEAK_SECURITY 0x0 +#define WFD_TDLS_STRONG_SECURITY 0x1 + +/* Coupled Sink Status Bitmap */ +#define WFD_AVAILABLE_FOR_COUPLING 0x0 +#define WFD_COUPLED_SUCCESS 0x1 +#define WFD_TEARDOWN_COUPLING 0x2 + +/* WFD RTSP Default Port */ +#define WFD_RTSP_DEFAULT_PORT 7236 + +/* Version of Local IP Address Subelement */ +#define WFD_LOCAL_IP_ADDR_VERSION_IPV4 1 + +/* Default max throughput */ +#define WFD_MAX_THROUGHPUT_DEFAULT 150 + +/* Default content protection bit */ +#define WFD_CONTENT_PROTECT_DEFAULT WFD_CP_NOT_SUPPORT + +typedef struct GNU_PACKED _WFD_DEVICE_INFO +{ +#ifndef RT_BIG_ENDIAN + USHORT DeviceType:2; + USHORT SourceCoupled:1; + USHORT SinkCoupled:1; + USHORT SessionAvail:2; + USHORT WSD:1; + USHORT PC:1; /* Preferred Connectivity */ + USHORT CP:1; + USHORT TimeSync:1; + USHORT Rsvd:6; +#else + USHORT Rsvd:6; + USHORT TimeSync:1; /* 802.1AS Support */ + USHORT CP:1; /* Content Protection */ + USHORT PC:1; /* Preferred Connectivity */ + USHORT WSD:1; /* WFD Service Discovery */ + USHORT SessionAvail:2; + USHORT SinkCoupled:1; + USHORT SourceCoupled:1; + USHORT DeviceType:2; +#endif +} WFD_DEVICE_INFO, *PWFD_DEVICE_INFO; + + +typedef struct GNU_PACKED _WFD_COUPLED_SINK_INFO +{ +#ifndef RT_BIG_ENDIAN + UCHAR CoupledStat:2; + UCHAR Rsvd:6; +#else + UCHAR Rsvd:6; + UCHAR CoupledStat:2; +#endif +} WFD_COUPLED_SINK_INFO, *PWFD_COUPLED_SINK_INFO; + + +typedef struct GNU_PACKED _WFD_SESSION_INFO +{ +#ifndef RT_BIG_ENDIAN + UCHAR Length; + UCHAR DeviceAddr[MAC_ADDR_LEN]; + UCHAR Bssid[MAC_ADDR_LEN]; + WFD_DEVICE_INFO WfdDevInfo; + USHORT MaxThroughput; + WFD_COUPLED_SINK_INFO CoupledSinkInfo; + UCHAR CoupledPeerAddr[MAC_ADDR_LEN]; +#else + UCHAR CoupledPeerAddr[MAC_ADDR_LEN]; + WFD_COUPLED_SINK_INFO CoupledSinkInfo; + USHORT MaxThroughput; + WFD_DEVICE_INFO WfdDevInfo; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR DeviceAddr[MAC_ADDR_LEN]; + UCHAR Length; +#endif +} WFD_SESSION_INFO, *PWFD_SESSION_INFO; + +typedef struct _WFD_SERV_DISC_QUERY_INFO +{ + BOOLEAN bWfd_device_info_ie; + UCHAR wfd_device_info_ie[SUBID_WFD_DEVICE_INFO_LEN]; + BOOLEAN bWfd_associate_bssid_ie; + UCHAR wfd_associate_bssid_ie[SUBID_WFD_ASSOCIATED_BSSID_LEN]; + BOOLEAN bWfd_audio_format_ie; + UCHAR wfd_audio_format_ie[SUBID_WFD_AUDIO_FORMATS_LEN]; + BOOLEAN bWfd_video_format_ie; + UCHAR wfd_video_format_ie[SUBID_WFD_VIDEO_FORMATS_LEN]; + BOOLEAN bWfd_3d_video_format_ie; + UCHAR wfd_3d_video_format_ie[SUBID_WFD_3D_VIDEO_FORMATS_LEN]; + BOOLEAN bWfd_content_proctection; + UCHAR wfd_content_proctection[SUBID_WFD_CONTENT_PROTECTION_LEN]; + BOOLEAN bWfd_couple_sink_info_ie; + UCHAR wfd_couple_sink_info_ie[SUBID_WFD_COUPLED_SINK_INFO_LEN]; + BOOLEAN bWfd_extent_capability_ie; + UCHAR wfd_extent_capability_ie[SUBID_WFD_EXTENDED_CAP_LEN]; + BOOLEAN bWfd_local_ip_ie; + UCHAR wfd_local_ip_ie[SUBID_WFD_LOCAL_IP_ADDR_LEN]; + BOOLEAN bWfd_session_info_ie; + UCHAR wfd_session_info_ie[120]; + BOOLEAN bWfd_alternate_mac_addr_ie; + UCHAR wfd_alternate_mac_addr_ie[SUBID_WFD_ALTERNATE_MAC_ADDR_LEN]; +} WFD_SERV_DISC_QUERY_INFO, *PWFD_SERV_DISC_QUERY_INFO; + +/* Store for WFD Entry Configuration */ +typedef struct _WFD_ENTRY_INFO +{ + UCHAR bWfdClient; + UCHAR wfd_devive_type; + UCHAR source_coupled; + UCHAR sink_coupled; + UCHAR session_avail; + UCHAR wfd_service_discovery; + UCHAR wfd_PC; + UCHAR wfd_CP; + UCHAR wfd_time_sync; + UCHAR sink_audio_unsupport; + UCHAR source_audio_only; + UCHAR tdls_persistent_group; + USHORT rtsp_port; + USHORT max_throughput; + UCHAR assoc_addr[MAC_ADDR_LEN]; + WFD_COUPLED_SINK_INFO coupled_sink_status; + UCHAR coupled_peer_addr[MAC_ADDR_LEN]; + /* Service Discovery */ + WFD_SERV_DISC_QUERY_INFO wfd_serv_disc_query_info; +} WFD_ENTRY_INFO, *PWFD_ENTRY_INFO; + +/* Store for WFD Configuration */ +typedef struct _RT_WFD_CONFIG +{ + BOOLEAN bWfdEnable; +#ifdef RT_CFG80211_SUPPORT + BOOLEAN bSuppInsertWfdIe; /* Insert WFD IE to management frames from wpa_supplicant */ + BOOLEAN bSuppGoOn; /* wpa_supplicant P2P GO is on */ +#endif /* RT_CFG80211_SUPPORT */ + UCHAR DeviceType; + UCHAR SourceCoupled; + UCHAR SinkCoupled; + UCHAR SessionAvail; + UCHAR WSD; + UCHAR PC; + UCHAR CP; /* WFD Content Protection capability */ + UCHAR TimeSync; + USHORT RtspPort; /* Deafult WFD_RTSP_DEFAULT_PORT */ + USHORT MaxThroughput; /* Maximum average throughput capability */ + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR IPv4Addr[4]; + UCHAR TdlsSecurity; + UCHAR PeerSessionAvail; + UCHAR PeerPC; + WFD_COUPLED_SINK_INFO CoupledSinkStatus; + /* Service Discovery */ + UINT32 WfdSerDiscCapable; + WFD_SERV_DISC_QUERY_INFO wfd_serv_disc_query_info; +} RT_WFD_CONFIG, *PRT_WFD_CONFIG; + +#endif /* WFD_SUPPORT */ +#endif /* __WFD_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wnm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wnm.h new file mode 100644 index 000000000..61513a3a5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wnm.h @@ -0,0 +1,633 @@ +/* + *************************************************************************** + * 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: + +***************************************************************************/ + +#ifndef __WNM_H__ +#define __WNM_H__ + +#include "ipv6.h" +#include "mat.h" + +#define BTM_MACHINE_BASE 0 +#define WaitPeerBTMRspTimeoutVale 1024 + +/* BTM states */ +enum BTM_STATE { + WAIT_BTM_QUERY, + WAIT_PEER_BTM_QUERY, + WAIT_BTM_REQ, + WAIT_BTM_RSP, + WAIT_PEER_BTM_REQ, + WAIT_PEER_BTM_RSP, + BTM_UNKNOWN, + MAX_BTM_STATE, +}; + + +/* BTM events */ +enum BTM_EVENT { + BTM_QUERY, + PEER_BTM_QUERY, + BTM_REQ, + BTM_RSP, + PEER_BTM_REQ, + PEER_BTM_RSP, + MAX_BTM_MSG, +}; + +#define BTM_FUNC_SIZE (MAX_BTM_STATE * MAX_BTM_MSG) + +enum IPV6_TYPE{ + IPV6_LINK_LOCAL, + IPV6_GLOBAL, +}; + +typedef struct GNU_PACKED _BTM_EVENT_DATA { + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UINT16 EventType; + union { +#ifdef CONFIG_STA_SUPPORT + struct { + UCHAR DialogToken; + UINT16 BTMQueryLen; + UCHAR BTMQuery[0]; + } GNU_PACKED BTM_QUERY_DATA; + + struct { + UCHAR DialogToken; + UINT16 BTMRspLen; + UCHAR BTMRsp[0]; + } GNU_PACKED BTM_RSP_DATA; + + struct { + UCHAR DialogToken; + UINT16 BTMReqLen; + UCHAR BTMReq[0]; + } GNU_PACKED PEER_BTM_REQ_DATA; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + struct { + UCHAR DialogToken; + UINT16 BTMReqLen; + UCHAR BTMReq[0]; + } GNU_PACKED BTM_REQ_DATA; + + struct { + UCHAR DialogToken; + UINT16 BTMQueryLen; + UCHAR BTMQuery[0]; + } GNU_PACKED PEER_BTM_QUERY_DATA; + + struct { + UCHAR DialogToken; + UINT16 BTMRspLen; + UCHAR BTMRsp[0]; + } GNU_PACKED PEER_BTM_RSP_DATA; +#endif /* CONFIG_AP_SUPPORT */ + }u; +} BTM_EVENT_DATA, *PBTM_EVENT_DATA; + +typedef struct _BTM_PEER_ENTRY { + DL_LIST List; + enum BTM_STATE CurrentState; + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UCHAR DialogToken; + void *Priv; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT WaitPeerBTMRspTimer; +#endif /* CONFIG_AP_SUPPORT */ +} BTM_PEER_ENTRY, *PBTM_PEER_ENTRY; + +typedef struct _PROXY_ARP_IPV4_ENTRY { + DL_LIST List; + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPAddr[4]; +} PROXY_ARP_IPV4_ENTRY, *PPROXY_ARP_IPV4_ENTRY; + +typedef struct _PROXY_ARP_IPV4_UNIT { + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPAddr[4]; +} PROXY_ARP_IPV4_UNIT, *PPROXY_ARP_IPV4_UNIT; + +typedef struct _PROXY_ARP_IPV6_ENTRY { + DL_LIST List; + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPType; + UCHAR TargetIPAddr[16]; +} PROXY_ARP_IPV6_ENTRY, *PPROXY_ARP_IPV6_ENTRY; + +typedef struct _PROXY_ARP_IPV6_UNIT { + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPType; + UCHAR TargetIPAddr[16]; +} PROXY_ARP_IPV6_UNIT, *PPROXY_ARP_IPV6_UNIT; + +typedef struct _WNM_CTRL { + UINT32 TimeadvertisementIELen; + UINT32 TimezoneIELen; + PUCHAR TimeadvertisementIE; + PUCHAR TimezoneIE; + RTMP_OS_SEM BTMPeerListLock; + RTMP_OS_SEM WNMNotifyPeerListLock; + BOOLEAN ProxyARPEnable; + BOOLEAN WNMNotifyEnable; + RTMP_OS_SEM ProxyARPListLock; + RTMP_OS_SEM ProxyARPIPv6ListLock; + DL_LIST IPv4ProxyARPList; + DL_LIST IPv6ProxyARPList; + DL_LIST BTMPeerList; + DL_LIST WNMNotifyPeerList; +} WNM_CTRL, *PWNM_CTRL; + + +enum IPTYPE { + IPV4, + IPV6 +}; + +struct _MULTISSID_STRUCT; + +BOOLEAN IsGratuitousARP(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR *DAMacAddr, + IN struct _MULTISSID_STRUCT *pMbss); + +BOOLEAN IsUnsolicitedNeighborAdver(PRTMP_ADAPTER pAd, + PUCHAR pData); + +BOOLEAN IsIPv4ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6DHCPv6Solicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6RouterSolicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6RouterAdvertisement(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN PUCHAR pOffset); + +BOOLEAN IsTDLSPacket(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IPv4ProxyARP(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS); + +BOOLEAN IsIpv6DuplicateAddrDetect(PRTMP_ADAPTER pAd, + PUCHAR pData, + PUCHAR pOffset); + + +BOOLEAN IPv6ProxyARP(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS); + +UINT32 AddIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + IN PUCHAR pTargetMACAddr, + IN PUCHAR pTargetIPAddr); + +UINT32 AddIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + IN PUCHAR pTargetMACAddr, + IN PUCHAR pTargetIPAddr); + +UINT32 IPv4ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss); + +UINT32 IPv6ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss); + +BOOLEAN GetIPv4ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + OUT PUCHAR *ProxyARPTable); + +BOOLEAN GetIPv6ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + OUT PUCHAR *ProxyARPTable); + +VOID RemoveIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + PUCHAR pTargetMACAddr); + +VOID RemoveIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _MULTISSID_STRUCT *pMbss, + PUCHAR pTargetMACAddr); + +VOID WNMCtrlInit(IN PRTMP_ADAPTER pAd); +VOID WNMCtrlExit(IN PRTMP_ADAPTER pAd); +VOID Clear_All_PROXY_TABLE(IN PRTMP_ADAPTER pAd); +#ifdef CONFIG_AP_SUPPORT +VOID WNMIPv4ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + USHORT srcPort, + USHORT dstPort, + PUCHAR pSrcBuf); + +VOID WNMIPv6ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + PUCHAR pSrcBuf); + +DECLARE_TIMER_FUNCTION(WaitPeerBTMRspTimeout); +DECLARE_TIMER_FUNCTION(WaitPeerWNMNotifyRspTimeout); + +VOID BTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +enum BTM_STATE BTMPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReceiveWNMNotifyRsp(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID SendWNMNotifyConfirm(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WNMNotifyStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +#define WNM_NOTIFY_MACHINE_BASE 0 +#define WaitPeerWNMNotifyRspTimeoutVale 1024 + +/* WNM Notification states */ +enum WNM_NOTIFY_STATE { + WAIT_WNM_NOTIFY_REQ, + WAIT_WNM_NOTIFY_RSP, + WNM_NOTIFY_UNKNOWN, + MAX_WNM_NOTIFY_STATE, +}; + +/* WNM Notification events */ +enum WNM_NOTIFY_EVENT { + WNM_NOTIFY_REQ, + WNM_NOTIFY_RSP, + MAX_WNM_NOTIFY_MSG, +}; + +#define WNM_NOTIFY_FUNC_SIZE (MAX_WNM_NOTIFY_STATE * MAX_WNM_NOTIFY_MSG) + +typedef struct GNU_PACKED _WNM_NOTIFY_EVENT_DATA { + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UINT16 EventType; + union { + +#ifdef CONFIG_AP_SUPPORT + struct { + UCHAR DialogToken; + UINT16 WNMNotifyReqLen; + UCHAR WNMNotifyReq[0]; + } GNU_PACKED WNM_NOTIFY_REQ_DATA; + + struct { + UCHAR DialogToken; + UINT16 WNMNotifyRspLen; + UCHAR WNMNotifyRsp[0]; + } GNU_PACKED WNM_NOTIFY_RSP_DATA; +#endif /* CONFIG_AP_SUPPORT */ + }u; +} WNM_NOTIFY_EVENT_DATA, *PWNM_NOTIFY_EVENT_DATA; + +typedef struct _WNM_NOTIFY_PEER_ENTRY { + DL_LIST List; + enum WNM_NOTIFY_STATE CurrentState; + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UCHAR DialogToken; + void *Priv; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT WaitPeerWNMNotifyRspTimer; +#endif /* CONFIG_AP_SUPPORT */ +} WNM_NOTIFY_PEER_ENTRY, *PWNM_NOTIFY_PEER_ENTRY; + +INT Send_BTM_Req( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING BTMReq, + IN UINT32 BTMReqLen); + +INT Send_WNM_Notify_Req( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING WNMNotifyReq, + IN UINT32 WNMNotifyReqLen, + IN UINT32 type); + +INT Send_QOSMAP_Configure( + IN PRTMP_ADAPTER pAd, + IN PSTRING PeerMACAddr, + IN PSTRING QosMapBuf, + IN UINT32 QosMapLen, + IN UINT8 Apidx); + +#ifdef CONFIG_HOTSPOT_R2 +VOID WNMSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN enum WNM_NOTIFY_STATE State); + +enum WNM_NOTIFY_STATE WNMNotifyPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WNMNotifyStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); +#endif /* CONFIG_HOTSPOT_R2 */ + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#include "rtmp_type.h" +#include "wnm_cmm.h" + +#ifdef CONFIG_AP_SUPPORT +#define IS_BSS_TRANSIT_MANMT_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_BSSEnable == TRUE) + +#define IS_WNMDMS_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_DMSEnable == TRUE) + + +#define IS_WNMFMS_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_FMSEnable == TRUE) + +#define IS_WNMSleepMode_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_SleepModeEnable == TRUE) + +#define IS_WNMTFS_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_TFSEnable == TRUE) + + +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + +#define IS_BSS_TRANSIT_MANMT_SUPPORT(_P) \ + ((_P)->StaCfg.WnmCfg.bDot11vWNM_BSSEnable == TRUE) + +#define IS_WNMDMS_SUPPORT(_P) \ + ((_P)->StaCfg.WnmCfg.bDot11vWNM_DMSEnable == TRUE) + +#define IS_WNMFMS_SUPPORT(_P) \ + ((_P)->StaCfg.WnmCfg.bDot11vWNM_FMSEnable == TRUE) + +#define IS_WNMSleepMode_SUPPORT(_P) \ + ((_P)->StaCfg.WnmCfg.bDot11vWNM_SleepModeEnable == TRUE) + +#define IS_WNMTFS_SUPPORT(_P) \ + ((_P)->StaCfg.WnmCfg.bDot11vWNM_TFSEnable == TRUE) + + +#endif /* CONFIG_STA_SUPPORT */ + + +#define WNM_MEM_COPY(__Dst, __Src, __Len) memcpy(__Dst, __Src, __Len) +#define WNMR_ARG_ATOI(__pArgv) simple_strtol((PSTRING) __pArgv, 0, 10) +#define WNMR_ARG_ATOH(__Buf, __Hex) AtoH((PSTRING) __Buf, __Hex, 1) + + + +VOID WNMAPBTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + + +VOID WNMSTABTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID WNM_Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +void WNM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + + +#ifdef CONFIG_AP_SUPPORT + +BOOLEAN DeleteDMSEntry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID FMSTable_Release( + IN PRTMP_ADAPTER pAd); + +VOID DMSTable_Release( + IN PRTMP_ADAPTER pAd); + +BOOLEAN DeleteTFSID( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +NDIS_STATUS FMSPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN UCHAR apidx, + IN UCHAR QueIdx, + IN UINT8 UserPriority); + +NDIS_STATUS TFSPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN UCHAR apidx, + IN UCHAR QueIdx, + IN UINT8 UserPriority); + +/* */ +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_WNMTransMantREQ_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_APWNMDMSShow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + Insert WNM Max Idle Capabilitys IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ +VOID WNM_InsertMaxIdleCapIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR aoidx, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID WNM_InsertFMSDescripotr( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ElementID, + IN UINT8 Length, + IN UINT8 NumOfFMSCs); + +VOID WNM_InsertFMSStSubEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_STATUS_SUBELMENT FMSSubElement); + +VOID InsertFMSRspSubElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_RESPONSE_ELEMENT FMSReqElement); +#endif /* CONFIG_AP_SUPPORT */ +VOID WNM_Init(IN PRTMP_ADAPTER pAd); + +VOID IS_WNM_DMS( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pRxPacket, + IN PHEADER_802_11 pHeader); + +VOID InsertDMSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_DMS_REQUEST_ELEMENT DMSReqElement); + + +VOID WNM_InsertDMS( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN UCHAR DMSID, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr); + +VOID WNM_InsertFMSReqSubEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_SUBELEMENT FMSSubElement, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr); + +VOID InsertFMSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_REQUEST_ELEMENT FMSReqElement); + +VOID WNM_InsertTFSReqSubEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_TFS_SUBELEMENT TFSSubElement, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr); + + +VOID InsertTFSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_TFS_REQUEST_ELEMENT FMSReqElement); + + +VOID WNM_InsertSleepModeEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_SLEEP_MODE_ELEMENT Sleep_Mode_Elmt); + +VOID InsertRequestTyppe( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR RequestTyppe); + + +BOOLEAN RxDMSHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt); + +#endif /* DOT11V_WNM_SUPPORT */ + +#endif /* __WNM_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wnm_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wnm_cmm.h new file mode 100644 index 000000000..92b0f48c0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wnm_cmm.h @@ -0,0 +1,54 @@ +/* + *************************************************************************** + * 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: + +***************************************************************************/ + +#ifndef __WNM_CONFIG_H__ +#define __WNM_CONFIG_H__ + +#ifdef DOT11V_WNM_SUPPORT +#include "rtmp_type.h" +#include "dot11v_wnm.h" + + +#define WNM_DEFAULT_QUIET_PERIOD 200 + + +typedef struct _WNM_CONFIG +{ + BOOLEAN bDot11vWNM_BSSEnable; + BOOLEAN bDot11vWNM_DMSEnable; + BOOLEAN bDot11vWNM_FMSEnable; + BOOLEAN bDot11vWNM_SleepModeEnable; + BOOLEAN bDot11vWNM_TFSEnable; +#ifdef CONFIG_AP_SUPPORT + VOID *DMSEntry[10]; +#endif /* CONFIG_AP_SUPPORT */ + +} WNM_CONFIG; + + + +#endif /* DOT11V_WNM_SUPPORT */ + +#endif /* __WNM_CONFIG_H__ */ + + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wpa.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wpa.h new file mode 100644 index 000000000..b808b402e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wpa.h @@ -0,0 +1,620 @@ +/* + *************************************************************************** + * 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: + wpa.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __WPA_H__ +#define __WPA_H__ + +#ifndef ROUND_UP +#define ROUND_UP(__x, __y) \ + (((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1))) +#endif + +#define SET_UINT16_TO_ARRARY(_V, _LEN) \ +{ \ + _V[0] = ((UINT16)_LEN) >> 8; \ + _V[1] = ((UINT16)_LEN & 0xFF); \ +} + +#define INC_UINT16_TO_ARRARY(_V, _LEN) \ +{ \ + UINT16 var_len; \ + \ + var_len = (_V[0]<<8) | (_V[1]); \ + var_len += _LEN; \ + \ + _V[0] = (var_len & 0xFF00) >> 8; \ + _V[1] = (var_len & 0xFF); \ +} + +#define CONV_ARRARY_TO_UINT16(_V) ((_V[0]<<8) | (_V[1])) + +#define ADD_ONE_To_64BIT_VAR(_V) \ +{ \ + UCHAR cnt = LEN_KEY_DESC_REPLAY; \ + do \ + { \ + cnt--; \ + _V[cnt]++; \ + if (cnt == 0) \ + break; \ + }while (_V[cnt] == 0); \ +} + +#define INC_TX_TSC(_tsc, _cnt) \ +{ \ + INT i=0; \ + while (++_tsc[i] == 0x0) \ + { \ + i++; \ + if (i == (_cnt)) \ + break; \ + } \ +} + +#define IS_WPA_CAPABILITY(a) (((a) >= Ndis802_11AuthModeWPA) && ((a) <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + +/* + WFA recommend to restrict the encryption type in 11n-HT mode. + So, the WEP and TKIP shall not be allowed to use HT rate. + */ +#define IS_INVALID_HT_SECURITY(_mode) \ + (((_mode) == Ndis802_11Encryption1Enabled) || \ + ((_mode) == Ndis802_11Encryption2Enabled)) + +#define MIX_CIPHER_WPA_TKIP_ON(x) (((x) & 0x08) != 0) +#define MIX_CIPHER_WPA_AES_ON(x) (((x) & 0x04) != 0) +#define MIX_CIPHER_WPA2_TKIP_ON(x) (((x) & 0x02) != 0) +#define MIX_CIPHER_WPA2_AES_ON(x) (((x) & 0x01) != 0) + +/* Some definition are different between Keneral mode and Daemon mode */ +#ifdef WPA_DAEMON_MODE +/* The definition for Daemon mode */ +#define WPA_GET_BSS_NUM(_pAd) (_pAd)->mbss_num + +#define WPA_GET_PMK(_pAd, _pEntry, _pmk) \ +{ \ + _pmk = _pAd->MBSS[_pEntry->apidx].PMK; \ +} + +#define WPA_GET_GTK(_pAd, _pEntry, _gtk) \ +{ \ + _gtk = _pAd->MBSS[_pEntry->apidx].GTK; \ +} + +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ +{ \ + _cipher = (_pAd)->MBSS[_pEntry->apidx].GroupEncrypType; \ +} + +#define WPA_GET_DEFAULT_KEY_ID(_pAd, _pEntry, _idx) \ +{ \ + _idx = (_pAd)->MBSS[_pEntry->apidx].DefaultKeyId; \ +} + +#define WPA_GET_BMCST_TSC(_pAd, _pEntry, _tsc) \ +{ \ + _tsc = 1; \ +} + +#define WPA_BSSID(_pAd, _apidx) (_pAd)->MBSS[_apidx].wlan_addr + +#define WPA_OS_MALLOC(_p, _s) \ +{ \ + _p = os_malloc(_s); \ +} + +#define WPA_OS_FREE(_p) \ +{ \ + os_free(_p); \ +} + +#define WPA_GET_CURRENT_TIME(_time) \ +{ \ + struct timeval tv; \ + gettimeofday(&tv, NULL); \ + *(_time) = tv.tv_sec; \ +} + +#else +/* The definition for Driver mode */ + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define WPA_GET_BSS_NUM(_pAd) (((_pAd)->OpMode == OPMODE_AP) ? (_pAd)->ApCfg.BssidNum : 1) +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + do \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if ((_pAd)->OpMode == OPMODE_AP) \ + { \ + if (IS_ENTRY_APCLI(_pEntry) && \ + ((_pEntry)->wdev_idx < MAX_APCLI_NUM)) \ + _cipher = (_pAd)->ApCfg.ApCliTab[(_pEntry)->wdev_idx].GroupCipher; \ + else if ((_pEntry)->apidx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->apidx].wdev.GroupKeyWepStatus;\ + } \ + else \ + _cipher = (_pAd)->StaCfg.GroupCipher; \ + }while(0) +#define WPA_BSSID(_pAd, _apidx) (((_pAd)->OpMode == OPMODE_AP) ?\ + (_pAd)->ApCfg.MBSSID[_apidx].Bssid :\ + (_pAd)->CommonCfg.Bssid) +#elif defined(CONFIG_AP_SUPPORT) +#define WPA_GET_BSS_NUM(_pAd) (_pAd)->ApCfg.BssidNum +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + do \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if (IS_ENTRY_APCLI(_pEntry) && \ + ((_pEntry)->wdev_idx < MAX_APCLI_NUM)) \ + _cipher = (_pAd)->ApCfg.ApCliTab[(_pEntry)->wdev_idx].GroupCipher; \ + else if ((_pEntry)->apidx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->apidx].wdev.GroupKeyWepStatus;\ + }while(0) + +#define WPA_BSSID(_pAd, _apidx) (_pAd)->ApCfg.MBSSID[_apidx].Bssid + +#elif defined(CONFIG_STA_SUPPORT) +#define WPA_GET_BSS_NUM(_pAd) 1 +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + do \ + { \ + _cipher = (_pAd)->StaCfg.GroupCipher; \ + }while(0) +#define WPA_BSSID(_pAd, _apidx) (_pAd)->CommonCfg.Bssid +#endif /* defined(CONFIG_STA_SUPPORT) */ + +#define WPA_OS_MALLOC(_p, _s) \ +{ \ + os_alloc_mem(NULL, (PUCHAR *)&_p, _s); \ +} + +#define WPA_OS_FREE(_p) \ +{ \ + os_free_mem(NULL, _p); \ +} + +#define WPA_GET_CURRENT_TIME(_time) NdisGetSystemUpTime(_time); + +#endif /* End of Driver Mode */ + +#ifdef CONFIG_AP_SUPPORT +/*======================================== + The prototype is defined in ap_wpa.c + ========================================*/ +VOID WPA_APSetGroupRekeyAction( + IN PRTMP_ADAPTER pAd); + +#endif /* CONFIG_AP_SUPPORT */ + +/*======================================== + The prototype is defined in cmm_wpa.c + ========================================*/ +void inc_iv_byte( + UCHAR *iv, + UINT len, + UINT cnt); + +BOOLEAN WpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType); + +VOID PRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *prefix, + IN INT prefix_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len); + +int RtmpPasswordHash( + char *password, + unsigned char *ssid, + int ssidlength, + unsigned char *output); + + VOID KDF( + IN PUINT8 key, + IN INT key_len, + IN PUINT8 label, + IN INT label_len, + IN PUINT8 data, + IN INT data_len, + OUT PUINT8 output, + IN USHORT len); + +PUINT8 WPA_ExtractSuiteFromRSNIE( + IN PUINT8 rsnie, + IN UINT rsnie_len, + IN UINT8 type, + OUT UINT8 *count); + +VOID WpaShowAllsuite( + IN PUINT8 rsnie, + IN UINT rsnie_len); + +VOID RTMPInsertRSNIE( + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 rsnie_ptr, + IN UINT8 rsnie_len, + IN PUINT8 pmkid_ptr, + IN UINT8 pmkid_len); + +/* + ===================================== + function prototype in cmm_wpa.c + ===================================== +*/ +VOID WpaStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN bClearFrame); + +VOID WpaDerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len); + +VOID WpaDeriveGTK( + IN UCHAR *PMK, + IN UCHAR *GNonce, + IN UCHAR *AA, + OUT UCHAR *output, + IN UINT len); + +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random); + +BOOLEAN RTMPCheckWPAframe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID); + +#ifdef HDR_TRANS_SUPPORT +BOOLEAN RTMPCheckWPAframe_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID); +#endif /* HDR_TRANS_SUPPORT */ + +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WPA_ConstructKdeHdr( + IN UINT8 data_type, + IN UINT8 data_len, + OUT PUCHAR pBuf); + +VOID ConstructEapolMsg( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + OUT PEAPOL_PACKET pMsg); + +PCIPHER_KEY RTMPSwCipherKeySelection( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pIV, + IN RX_BLK *pRxBlk, + IN PMAC_TABLE_ENTRY pEntry); + +NDIS_STATUS RTMPSoftDecryptionAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN UCHAR UserPriority, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt); + +VOID RTMPSoftConstructIVHdr( + IN UCHAR CipherAlg, + IN UCHAR key_id, + IN PUCHAR pTxIv, + OUT PUCHAR pHdrIv, + OUT UINT8 *hdr_iv_len); + +VOID RTMPSoftEncryptionAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR CipherAlg, + IN PUCHAR pHdr, + IN PUCHAR pSrcBufData, + IN UINT32 SrcBufLen, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pKey, + OUT UINT8 *ext_len); + +VOID RTMPMakeRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN UCHAR apidx); + +VOID WPAInstallPairwiseKey( + PRTMP_ADAPTER pAd, + UINT8 BssIdx, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE); + +VOID WPAInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + BOOLEAN bAE, + PUINT8 pGtk, + UINT8 GtkLen); + +VOID RTMPSetWcidSecurityInfo( + PRTMP_ADAPTER pAd, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 CipherAlg, + UINT8 Wcid, + UINT8 KeyTabFlag); + +VOID CalculateMIC( + IN UCHAR KeyDescVer, + IN UCHAR *PTK, + OUT PEAPOL_PACKET pMsg); + +BOOLEAN rtmp_chk_tkip_mic(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk); + +#ifdef WPA_SUPPLICANT_SUPPORT +INT WpaCheckEapCode( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pFrame, + IN USHORT FrameLen, + IN USHORT OffSet); +#endif /* WPA_SUPPLICANT_SUPPORT */ + + +PSTRING GetEapolMsgType(CHAR msg); + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT +/* + ===================================== + function prototype in cmm_wpa_adhoc.c + ===================================== +*/ +VOID Adhoc_WpaEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_WpaStart4WayHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval); + +VOID Adhoc_PeerPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_PeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_PeerPairMsg4Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_PeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID Adhoc_Wpa4WayComplete( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID Adhoc_WpaRetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID Adhoc_ConstructEapolMsg( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile, + OUT PEAPOL_PACKET pMsg); + +VOID Adhoc_ConstructEapolKeyData( + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR GroupKeyWepStatus, + IN UCHAR keyDescVer, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile, + OUT PEAPOL_PACKET pMsg); + +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +/* + ===================================== + function prototype in cmm_wep.c + ===================================== +*/ +UINT RTMP_CALC_FCS32( + IN UINT Fcs, + IN PUCHAR Cp, + IN INT Len); + +VOID RTMPConstructWEPIVHdr( + IN UINT8 key_idx, + IN UCHAR *pn, + OUT UCHAR *iv_hdr); + +BOOLEAN RTMPSoftEncryptWEP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pIvHdr, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + IN ULONG DataByteCnt); + +BOOLEAN RTMPSoftDecryptWEP( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt); + +/* + ===================================== + function prototype in cmm_tkip.c + ===================================== +*/ +NDIS_STATUS RTMPSoftDecryptTKIP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN UCHAR UserPriority, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + IN UINT16 *DataByteCnt); + +VOID TKIP_GTK_KEY_WRAP( + IN UCHAR *key, + IN UCHAR *iv, + IN UCHAR *input_text, + IN UINT32 input_len, + OUT UCHAR *output_text); + +VOID TKIP_GTK_KEY_UNWRAP( + IN UCHAR *key, + IN UCHAR *iv, + IN UCHAR *input_text, + IN UINT32 input_len, + OUT UCHAR *output_text); + +/* + ===================================== + function prototype in cmm_aes.c + ===================================== +*/ +BOOLEAN RTMPSoftDecryptAES( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pWpaKey); + +VOID RTMPConstructCCMPHdr( + IN UINT8 key_idx, + IN UCHAR *pn, + OUT UCHAR *ccmp_hdr); + +BOOLEAN RTMPSoftEncryptCCMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN PUCHAR pIV, + IN PUCHAR pKey, + INOUT PUCHAR pData, + IN UINT32 DataLen); + +BOOLEAN RTMPSoftDecryptCCMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataLen); + +VOID CCMP_test_vector( + IN PRTMP_ADAPTER pAd, + IN INT input); + +void inc_byte_array(UCHAR *counter, int len); + +#ifdef RT_CFG80211_SUPPORT +BOOLEAN RTMPIsValidIEs( + IN UCHAR *Ies, + IN INT32 Len); +const UCHAR *RTMPFindIE( + IN UCHAR Eid, + IN const UCHAR *Ies, + IN INT32 Len); +const UCHAR *RTMPFindWPSIE( + IN const UCHAR *Ies, + IN INT32 Len); +#endif /* RT_CFG80211_SUPPORT */ + +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wpa_cmm.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wpa_cmm.h new file mode 100644 index 000000000..d8947ead2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wpa_cmm.h @@ -0,0 +1,214 @@ + +#ifndef WPA_CMM_H +#define WPA_CMM_H + +#include "rtmp_type.h" +#include "dot11i_wpa.h" + +#define CACHE_NOT_FOUND -1 + +#define TX_EAPOL_BUFFER 1500 + +/* Retry timer counter initial value */ +#define PEER_MSG1_RETRY_TIMER_CTR 0 +#define PEER_MSG3_RETRY_TIMER_CTR 10 +#define GROUP_MSG1_RETRY_TIMER_CTR 20 + +/* WPA mechanism retry timer interval */ +#define PEER_MSG1_RETRY_EXEC_INTV 1000 /* 1 sec */ +#define PEER_MSG3_RETRY_EXEC_INTV 3000 /* 3 sec */ +#define GROUP_KEY_UPDATE_EXEC_INTV 1000 /* 1 sec */ +#define PEER_GROUP_KEY_UPDATE_INIV 2000 /* 2 sec */ + +#define EAPOL_MSG_INVALID 0 +#define EAPOL_PAIR_MSG_1 1 +#define EAPOL_PAIR_MSG_2 2 +#define EAPOL_PAIR_MSG_3 3 +#define EAPOL_PAIR_MSG_4 4 +#define EAPOL_GROUP_MSG_1 5 +#define EAPOL_GROUP_MSG_2 6 + +#define ENQUEUE_EAPOL_START_TIMER 200 /* 200 ms */ + +/* group rekey interval */ +#define TIME_REKEY 0 +#define PKT_REKEY 1 +#define DISABLE_REKEY 2 +#define MAX_REKEY 2 + +#define MAX_REKEY_INTER 0x3ffffff + +#define EAPOL_START_DISABLE 0 +#define EAPOL_START_PSK 1 +#define EAPOL_START_1X 2 + +/* */ +/* Common WPA state machine: states, events, total function # */ +/* */ +#define WPA_PTK 0 +#define MAX_WPA_PTK_STATE 1 + +#define WPA_MACHINE_BASE 0 +#define MT2_EAPPacket 0 +#define MT2_EAPOLStart 1 +#define MT2_EAPOLLogoff 2 +#define MT2_EAPOLKey 3 +#define MT2_EAPOLASFAlert 4 +#define MAX_WPA_MSG 5 + +#define WPA_FUNC_SIZE (MAX_WPA_PTK_STATE * MAX_WPA_MSG) + +typedef enum _WpaRole { + WPA_NONE, /* 0 */ + WPA_Authenticator, /* 1 */ + WPA_Supplicant, /* 2 */ + WPA_BOTH, /* 3: Authenticator and Supplicant */ +} WPA_ROLE; + +/*for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 */ +typedef enum _ApWpaState { + AS_NOTUSE, /* 0 */ + AS_DISCONNECT, /* 1 */ + AS_DISCONNECTED, /* 2 */ + AS_INITIALIZE, /* 3 */ + AS_AUTHENTICATION, /* 4 */ + AS_AUTHENTICATION2, /* 5 */ + AS_INITPMK, /* 6 */ + AS_INITPSK, /* 7 */ + AS_PTKSTART, /* 8 */ + AS_PTKINIT_NEGOTIATING, /* 9 */ + AS_PTKINITDONE, /* 10 */ + AS_UPDATEKEYS, /* 11 */ + AS_INTEGRITY_FAILURE, /* 12 */ + AS_KEYUPDATE, /* 13 */ +} AP_WPA_STATE; + +/* For supplicant state machine states. 802.11i Draft 4.1, p. 97 */ +/* We simplified it */ +typedef enum _WpaState { + SS_NOTUSE, /* 0 */ + SS_START, /* 1 */ + SS_WAIT_MSG_3, /* 2 */ + SS_WAIT_GROUP, /* 3 */ + SS_FINISH, /* 4 */ + SS_KEYUPDATE, /* 5 */ +} WPA_STATE; + +/* for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 */ +typedef enum _GTKState { + REKEY_NEGOTIATING, + REKEY_ESTABLISHED, + KEYERROR, +} GTK_STATE; + +/* for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 */ +typedef enum _WpaGTKState { + SETKEYS, + SETKEYS_DONE, +} WPA_GTK_STATE; + +/* WPA internal command type */ +#define WPA_SM_4WAY_HS_START 1 +#define WPA_SM_DISCONNECT 0xff + +/* WPA element IDs */ +typedef enum _WPA_VARIABLE_ELEMENT_ID { + WPA_ELEM_CMD = 1, + WPA_ELEM_PEER_RSNIE, + WPA_ELEM_LOCAL_RSNIE, + WPA_ELEM_PMK, + WPA_ELEM_RESV +} WPA_VARIABLE_ELEMENT_ID; + +#define GROUP_SUITE 0 +#define PAIRWISE_SUITE 1 +#define AKM_SUITE 2 +#define RSN_CAP_INFO 3 +#define PMKID_LIST 4 +#define G_MGMT_SUITE 5 + +/* */ +/* The definition of the cipher combination */ +/* */ +/* bit3 bit2 bit1 bit0 */ +/* +------------+------------+ */ +/* | WPA | WPA2 | */ +/* +------+-----+------+-----+ */ +/* | TKIP | AES | TKIP | AES | */ +/* | 0 | 1 | 1 | 0 | -> 0x06 */ +/* | 0 | 1 | 1 | 1 | -> 0x07 */ +/* | 1 | 0 | 0 | 1 | -> 0x09 */ +/* | 1 | 0 | 1 | 1 | -> 0x0B */ +/* | 1 | 1 | 0 | 1 | -> 0x0D */ +/* | 1 | 1 | 1 | 0 | -> 0x0E */ +/* | 1 | 1 | 1 | 1 | -> 0x0F */ +/* +------+-----+------+-----+ */ +/* */ +typedef enum _WpaMixPairCipher { + MIX_CIPHER_NOTUSE = 0x00, + WPA_NONE_WPA2_TKIPAES = 0x03, /* WPA2-TKIPAES */ + WPA_AES_WPA2_TKIP = 0x06, + WPA_AES_WPA2_TKIPAES = 0x07, + WPA_TKIP_WPA2_AES = 0x09, + WPA_TKIP_WPA2_TKIPAES = 0x0B, + WPA_TKIPAES_WPA2_NONE = 0x0C, /* WPA-TKIPAES */ + WPA_TKIPAES_WPA2_AES = 0x0D, + WPA_TKIPAES_WPA2_TKIP = 0x0E, + WPA_TKIPAES_WPA2_TKIPAES = 0x0F, +} WPA_MIX_PAIR_CIPHER; + +/* The internal command list for ralink dot1x daemon using */ +typedef enum _Dot1xInternalCmd { + DOT1X_DISCONNECT_ENTRY, + DOT1X_RELOAD_CONFIG, +} DOT1X_INTERNAL_CMD; + +/* 802.1x authentication format */ +typedef struct _IEEE8021X_FRAME { + UCHAR Version; /* 1.0 */ + UCHAR Type; /* 0 = EAP Packet */ + USHORT Length; +} IEEE8021X_FRAME, *PIEEE8021X_FRAME; + +typedef struct GNU_PACKED _RSN_IE_HEADER_STRUCT { + UCHAR Eid; + UCHAR Length; + USHORT Version; /* Little endian format */ +} RSN_IE_HEADER_STRUCT, *PRSN_IE_HEADER_STRUCT; + +/* Cipher suite selector types */ +typedef struct GNU_PACKED _CIPHER_SUITE_STRUCT { + UCHAR Oui[3]; + UCHAR Type; +} CIPHER_SUITE_STRUCT, *PCIPHER_SUITE_STRUCT; + +/* Authentication and Key Management suite selector */ +typedef struct GNU_PACKED _AKM_SUITE_STRUCT { + UCHAR Oui[3]; + UCHAR Type; +} AKM_SUITE_STRUCT, *PAKM_SUITE_STRUCT; + +/* RSN capability */ +typedef struct GNU_PACKED _RSN_CAPABILITY { + USHORT Rsv:10; + USHORT GTKSAReplayCnt:2; + USHORT PTKSAReplayCnt:2; + USHORT NoPairwise:1; + USHORT PreAuth:1; +} RSN_CAPABILITY, *PRSN_CAPABILITY; + +typedef struct _CIPHER_KEY { + UCHAR Key[16]; /* 128 bits max */ + UCHAR TxMic[8]; + UCHAR RxMic[8]; + UCHAR TxTsc[16]; /* TSC value. Change it from 48bit to 128bit */ + UCHAR RxTsc[16]; /* TSC value. Change it from 48bit to 128bit */ + UCHAR CipherAlg; /* 0:none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128 */ + UCHAR KeyLen; /* Key length for each key, 0: entry is invalid */ +#ifdef CONFIG_STA_SUPPORT + UCHAR BssId[6]; +#endif /* CONFIG_STA_SUPPORT */ + UCHAR Type; /* Indicate Pairwise/Group when reporting MIC error */ +} CIPHER_KEY, *PCIPHER_KEY; + +#endif /* WPA_CMM_H */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wsc.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wsc.h new file mode 100644 index 000000000..ff398fe11 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wsc.h @@ -0,0 +1,991 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 06-08-08 Initial +*/ + +#ifndef __WSC_H__ +#define __WSC_H__ + +/* WSC OUI SMI */ +#define WSC_OUI 0x0050f204 +#define WSC_SMI 0x00372A +#define WSC_VENDOR_TYPE 0x00000001 + +/* EAP code */ +#define EAP_CODE_REQ 0x01 +#define EAP_CODE_RSP 0x02 +#define EAP_CODE_FAIL 0x04 +#define EAP_TYPE_ID 0x01 +#define EAP_TYPE_NOTIFY 0x02 +#define EAP_TYPE_WSC 0xfe + +#ifdef CON_WPS +typedef struct GNU_PACKED _WSC_UPNP_CTRL_WSC_BAND_STOP +{ + char ifName[IFNAMSIZ]; + CHAR is2gBand; + CHAR isApCli; + INT status; +} WSC_UPNP_CTRL_WSC_BAND_STOP, *PWSC_UPNP_CTRL_WSC_BAND_STOP; +#endif /* CON_WPS */ + +/* structure to store Simple Config Attributes Info */ +typedef struct GNU_PACKED _WSC_LV_INFO { + USHORT ValueLen; + UCHAR Value[512]; +} WSC_LV_INFO; + +typedef struct GNU_PACKED _WSC_IE_HEADER { + UCHAR elemId; + UCHAR length; + UCHAR oui[4]; +} WSC_IE_HEADER; + +/* WSC IE structure */ +typedef struct GNU_PACKED _WSC_IE +{ + USHORT Type; + USHORT Length; + UCHAR Data[1]; /* variable length data */ +} WSC_IE, *PWSC_IE; + +/* WSC fixed information within EAP */ +typedef struct GNU_PACKED _WSC_FRAME +{ + UCHAR SMI[3]; + UINT VendorType; + UCHAR OpCode; + UCHAR Flags; +} WSC_FRAME, *PWSC_FRAME; + +/* EAP frame format */ +typedef struct GNU_PACKED _EAP_FRAME { + UCHAR Code; /* 1 = Request, 2 = Response */ + UCHAR Id; + USHORT Length; + UCHAR Type; /* 1 = Identity, 0xfe = reserved, used by WSC */ +} EAP_FRAME, *PEAP_FRAME; + +static inline BOOLEAN WscCheckWSCHeader(UCHAR *pData) +{ + WSC_FRAME *pWsc = (WSC_FRAME *)pData; + + /* Verify SMI first */ + if (((pWsc->SMI[0] * 256 + pWsc->SMI[1]) * 256 + pWsc->SMI[2]) != WSC_SMI) + return FALSE; /* Wrong WSC SMI Vendor ID, Update WSC status */ + + /* Verify Vendor Type */ + if (cpu2be32(get_unaligned32(&pWsc->VendorType)) != WSC_VENDOR_TYPE) + return FALSE; /* Wrong WSC Vendor Type, Update WSC status */ + + return TRUE; +} + +#ifdef WSC_INCLUDED + +#ifdef IWSC_SUPPORT +/* + IP Address Configuration Methods +*/ +#define IWSC_IPV4_ASSIGNMENT 0x0001 +#define IWSC_DHCP_IPV4 0x0002 +#define IWSC_STATIC_IPV4 0x0004 +#define IWSC_LINK_LOCAL_IPV4 0x0008 +#define IWSC_NFC_IPV4_ASSIGNMENT 0x0010 +#define IWSC_NFC_LINK_LOCAL_IPV4 0x0020 +#define IWSC_IPV6_DEVICE_UNIQUE 0x0040 + +#define IWSC_DEFAULT_REG_IPV4_ADDR 0x0a000001 +#define IWSC_DEFAULT_IPV4_SUBMASK 0xFF000000 +#define IWSC_DEFAULT_IPV4_RANGE 0xFFFFFFC0 +#define IWSC_IPV4_RANGE0 0xFFFFFFC0 +#define IWSC_IPV4_RANGE1 0xFFFFF03F +#define IWSC_IPV4_RANGE2 0xFFFC0FFF +#define IWSC_IPV4_RANGE3 0xFF03FFFF + +#define IWSC_MAX_IP_DEV_COUNT 62 +#endif /* IWSC_SUPPORT */ + +/* WSC HDR PSH BTN FUNC */ +/* WSC hardware push button function 0811 */ +#define WSC_HDR_BTN_CHECK_PERIOD MLME_TASK_EXEC_INTV /* unit: ms, check pin every 100ms */ +#define WSC_HDR_BTN_PRESS_TIME 2000 /* unit: ms, press button for 2s */ +#define WSC_HDR_BTN_CONT_TIMES (WSC_HDR_BTN_PRESS_TIME/WSC_HDR_BTN_CHECK_PERIOD) +#define WSC_HDR_BTN_GPIO_0 ((UINT32)0x00000001) /* bit 0 for RT2860/RT2870 */ +#define WSC_HDR_BTN_GPIO_3 ((UINT32)0x00000008) /* bit 3 for RT2860/RT2870 */ + +/* bit7: WPS PBC (0:off, 1:on) */ +#define WSC_HDR_BTN_MR_HDR_SUPPORT_SET(__pAd, __FlgIsSup) \ + (__pAd)->WscHdrPshBtnFlag = __FlgIsSup; + +/* check if hardware push button is supported */ +#define WSC_HDR_BTN_MR_IS_HDR_SUPPORT(__pAd) \ + ((__pAd)->WscHdrPshBtnFlag) + +/* run hardware push button handler */ +#define WSC_HDR_BTN_MR_HANDLE(__pAd) \ + if ((__pAd)->WscHdrPshBtnFlag) WSC_HDR_BTN_CheckHandler(__pAd); + +/* bit3: WPS PBC function is controlled through GPIO[3] */ +/* currently only for RT2860 & RT2870 */ +#define WSC_HDR_BTN_MR_PRESS_FLG_GET(__pAd, __FlgIsPressed) \ + { \ + UINT32 __gpio_value, mask; \ + RTMP_IO_READ32(__pAd, GPIO_CTRL_CFG, (&__gpio_value)); \ + if (RTMP_TEST_MORE_FLAG(__pAd, fRTMP_ADAPTER_WSC_PBC_PIN0)) \ + mask = WSC_HDR_BTN_GPIO_0; \ + else \ + mask = WSC_HDR_BTN_GPIO_3; \ + if (__gpio_value & mask) \ + __FlgIsPressed = 0; \ + else \ + __FlgIsPressed = 1; \ + } +/* WSC HDR PSH BTN FUNC */ + + +#define WSC_TIMER_INIT(_pAd, _pData, _time_var, _time_flg, _time_fn) \ + do{ \ + RTMPInitTimer((_pAd), (_time_var), GET_TIMER_FUNCTION(_time_fn), (_pData), FALSE); \ + (_time_flg) = FALSE; \ + }while(0) + + +/*Messages for the WSC state machine, */ +#define WSC_MACHINE_BASE 34 +#define WSC_EAPOL_PACKET_MSG 34 +#define WSC_EAPOL_START_MSG 35 +#define WSC_EAPOL_UPNP_MSG 36 + +#define MAX_WSC_MSG 3 + +/* WSC Opcode */ +#define WSC_OPCODE_START 0x01 +#define WSC_OPCODE_ACK 0x02 +#define WSC_OPCODE_NACK 0x03 +#define WSC_OPCODE_MSG 0x04 +#define WSC_OPCODE_DONE 0x05 +#define WSC_OPCODE_FRAG_ACK 0x06 + +/* Flags */ +#define WSC_MSG_FLAG_MF 0x01 /* More fragments */ +#define WSC_MSG_FLAG_LF 0x02 /* Length field */ + +#define WSC_OPCODE_UPNP_MASK 0x10 +#define WSC_OPCODE_UPNP_DATA 0x11 +#define WSC_OPCODE_UPNP_MGMT 0x12 +#define WSC_OPCODE_UPNP_CTRL 0x13 + +#define WSC_UPNP_MGMT_SUB_PROBE_REQ 0x01 +#define WSC_UPNP_MGMT_SUB_CONFIG_REQ 0x02 +#define WSC_UPNP_MGMT_SUB_REG_SELECT 0x03 + + +/*patch for Atheros External registrar */ +#define WSC_UPNP_DATA_SUB_INCLUDE_MAC 0x0100 + +#define WSC_UPNP_DATA_SUB_NORMAL 0x00 +#define WSC_UPNP_DATA_SUB_TO_ALL 0x01 +#define WSC_UPNP_DATA_SUB_TO_ONE 0x02 +#define WSC_UPNP_DATA_SUB_ACK 0x03 +#define WSC_UPNP_DATA_SUB_M1 0x04 +#define WSC_UPNP_DATA_SUB_M2 0x05 +#define WSC_UPNP_DATA_SUB_M2D 0x06 +#define WSC_UPNP_DATA_SUB_M3 0x07 +#define WSC_UPNP_DATA_SUB_M4 0x08 +#define WSC_UPNP_DATA_SUB_M5 0x09 +#define WSC_UPNP_DATA_SUB_M6 0x0A +#define WSC_UPNP_DATA_SUB_M7 0x0B +#define WSC_UPNP_DATA_SUB_M8 0x0C +#define WSC_UPNP_DATA_SUB_WSC_ACK 0x0D +#define WSC_UPNP_DATA_SUB_WSC_NACK 0x0E +#define WSC_UPNP_DATA_SUB_WSC_DONE 0x0F +#define WSC_UPNP_DATA_SUB_PBC_OVERLAP 0x10 +#define WSC_UPNP_DATA_SUB_WSC_TIMEOUT 0x20 +#define WSC_UPNP_DATA_SUB_WSC_UNKNOWN 0xff + + +/* Wsc EAP Messges type */ +#define WSC_MSG_EAP_RSP_ID 0x21 +#define WSC_MSG_EAP_REG_RSP_ID 0x22 +#define WSC_MSG_EAP_ENR_RSP_ID 0x23 +#define WSC_MSG_EAP_UPNP_RSP_ID 0x24 +#define WSC_MSG_EAP_REQ_ID 0x25 +#define WSC_MSG_EAP_REQ_START 0x26 +#define WSC_MSG_EAP_FAIL 0x27 +#define WSC_MSG_EAP_FRAG_ACK 0x28 +#define WSC_MSG_PROB_RSP 0x01 +#define WSC_MSG_EAPOL_START 0x02 +#define WSC_MSG_M1 0x04 +#define WSC_MSG_M2 0x05 +#define WSC_MSG_M2D 0x06 +#define WSC_MSG_M3 0x07 +#define WSC_MSG_M4 0x08 +#define WSC_MSG_M5 0x09 +#define WSC_MSG_M6 0x0A +#define WSC_MSG_M7 0x0B +#define WSC_MSG_M8 0x0C +#define WSC_MSG_WSC_ACK 0x0D +#define WSC_MSG_WSC_NACK 0x0E +#define WSC_MSG_WSC_DONE 0x0F +#define WSC_MSG_UNKNOWN 0xff + +/* WSC connection mode */ +#define WSC_PIN_MODE 1 +#define WSC_PBC_MODE 2 +#define WSC_SMPBC_MODE 3 + +/* Value of WSC_IE_DEV_PASS_ID 0x1012 */ +#define DEV_PASS_ID_PIN 0x0000 +#define DEV_PASS_ID_USER 0x0001 +#define DEV_PASS_ID_MACHINE 0x0002 +#define DEV_PASS_ID_REKEY 0x0003 +#define DEV_PASS_ID_PBC 0x0004 +#define DEV_PASS_ID_REG 0x0005 +#define DEV_PASS_ID_SMPBC 0x0006 +#ifdef WSC_NFC_SUPPORT +#define DEV_PASS_ID_NFC_HANDOVER 0x0007 /* 0006 */ +#endif /* WSC_NFC_SUPPORT */ +#define DEV_PASS_ID_NOSPEC 0xffff + + +/* Common definition */ +#define WSC_VERSION 0x10 +#define WSC_CONFIG_METHODS 0x008C + +/* Wsc status code */ +#define STATUS_WSC_NOTUSED 0 +#define STATUS_WSC_IDLE 1 +#define STATUS_WSC_FAIL 2 /* WSC Process Fail */ +#define STATUS_WSC_LINK_UP 3 /* Start WSC Process */ +#define STATUS_WSC_EAPOL_START_RECEIVED 4 /* Received EAPOL-Start */ +#define STATUS_WSC_EAP_REQ_ID_SENT 5 /* Sending EAP-Req(ID) */ +#define STATUS_WSC_EAP_RSP_ID_RECEIVED 6 /* Receive EAP-Rsp(ID) */ +#define STATUS_WSC_EAP_RSP_WRONG_SMI 7 /* Receive EAP-Req with wrong WSC SMI Vendor Id */ +#define STATUS_WSC_EAP_RSP_WRONG_VENDOR_TYPE 8 /* Receive EAPReq with wrong WSC Vendor Type */ +#define STATUS_WSC_EAP_REQ_WSC_START 9 /* Sending EAP-Req(WSC_START) */ +#define STATUS_WSC_EAP_M1_SENT 10 /* Send M1 */ +#define STATUS_WSC_EAP_M1_RECEIVED 11 /* Received M1 */ +#define STATUS_WSC_EAP_M2_SENT 12 /* Send M2 */ +#define STATUS_WSC_EAP_M2_RECEIVED 13 /* Received M2 */ +#define STATUS_WSC_EAP_M2D_RECEIVED 14 /* Received M2D */ +#define STATUS_WSC_EAP_M3_SENT 15 /* Send M3 */ +#define STATUS_WSC_EAP_M3_RECEIVED 16 /* Received M3 */ +#define STATUS_WSC_EAP_M4_SENT 17 /* Send M4 */ +#define STATUS_WSC_EAP_M4_RECEIVED 18 /* Received M4 */ +#define STATUS_WSC_EAP_M5_SENT 19 /* Send M5 */ +#define STATUS_WSC_EAP_M5_RECEIVED 20 /* Received M5 */ +#define STATUS_WSC_EAP_M6_SENT 21 /* Send M6 */ +#define STATUS_WSC_EAP_M6_RECEIVED 22 /* Received M6 */ +#define STATUS_WSC_EAP_M7_SENT 23 /* Send M7 */ +#define STATUS_WSC_EAP_M7_RECEIVED 24 /* Received M7 */ +#define STATUS_WSC_EAP_M8_SENT 25 /* Send M8 */ +#define STATUS_WSC_EAP_M8_RECEIVED 26 /* Received M8 */ +#define STATUS_WSC_EAP_RAP_RSP_ACK 27 /* Processing EAP Response (ACK) */ +#define STATUS_WSC_EAP_RAP_REQ_DONE_SENT 28 /* Processing EAP Request (Done) */ +#define STATUS_WSC_EAP_RAP_RSP_DONE_SENT 29 /* Processing EAP Response (Done) */ +#define STATUS_WSC_EAP_FAIL_SENT 30 /* Sending EAP-Fail */ +#define STATUS_WSC_ERROR_HASH_FAIL 31 /* WSC_ERROR_HASH_FAIL */ +#define STATUS_WSC_ERROR_HMAC_FAIL 32 /* WSC_ERROR_HMAC_FAIL */ +#define STATUS_WSC_ERROR_DEV_PWD_AUTH_FAIL 33 /* WSC_ERROR_DEV_PWD_AUTH_FAIL */ +#define STATUS_WSC_CONFIGURED 34 +#define STATUS_WSC_SCAN_AP 35 /* Scanning AP */ +#define STATUS_WSC_EAPOL_START_SENT 36 +#define STATUS_WSC_EAP_RSP_DONE_SENT 37 +#define STATUS_WSC_WAIT_PIN_CODE 38 +#define STATUS_WSC_START_ASSOC 39 +#define STATUS_WSC_IBSS_WAIT_NEXT_SMPBC_ENROLLEE 40 +#define STATUS_WSC_IBSS_NEW_RANDOM_PIN 41 +#define STATUS_WSC_IBSS_FIXED_PIN 42 + +/* All error message dtarting from 0x0100 */ +#define STATUS_WSC_PBC_TOO_MANY_AP 0x0101 /* Too many PBC AP avaliable */ +#define STATUS_WSC_PBC_NO_AP 0x0102 /* No PBC AP avaliable */ +#define STATUS_WSC_EAP_FAIL_RECEIVED 0x0103 /* Received EAP-FAIL */ +#define STATUS_WSC_EAP_NONCE_MISMATCH 0x0104 /* Receive EAP with wrong NONCE */ +#define STATUS_WSC_EAP_INVALID_DATA 0x0105 /* Receive EAP without integrity (Hmac mismatch) */ +#define STATUS_WSC_PASSWORD_MISMATCH 0x0106 /* Error PIN Code (R-Hash mismatch) */ +#define STATUS_WSC_EAP_REQ_WRONG_SMI 0x0107 /* Receive EAP-Req with wrong WPS SMI Vendor Id */ +#define STATUS_WSC_EAP_REQ_WRONG_VENDOR_TYPE 0x0108 /* Receive EAPReq with wrong WPS Vendor Type */ +#define STATUS_WSC_PBC_SESSION_OVERLAP 0x0109 /* AP PBC session overlap */ +#define STATUS_WSC_SMPBC_TOO_MANY_REGISTRAR 0x010a /* Too many SMPBC Registrars avaliable */ +#define STATUS_WSC_EMPTY_IPV4_SUBMASK_LIST 0x010b /* Empty available IPv4 Submask list */ +#define STATUS_WSC_SMPBC_NO_AP 0x010c /* No SMPBC AP avaliable */ + +#define WSC_DISABLE 0x0 +#define WSC_ENROLLEE 0x1 +#define WSC_PROXY 0x2 +#define WSC_REGISTRAR 0x4 +#define WSC_ENROLLEE_PROXY (WSC_ENROLLEE | WSC_PROXY) +#define WSC_ENROLLEE_REGISTRAR (WSC_ENROLLEE | WSC_REGISTRAR) +#define WSC_PROXY_REGISTRAR (WSC_PROXY | WSC_REGISTRAR) +#define WSC_ENROLLEE_PROXY_REGISTRAR (WSC_ENROLLEE | WSC_PROXY | WSC_REGISTRAR) + +/* Device request/response type */ +#define WSC_MSGTYPE_ENROLLEE_INFO_ONLY 0x00 +#define WSC_MSGTYPE_ENROLLEE_OPEN_8021X 0x01 +#define WSC_MSGTYPE_REGISTRAR 0x02 +#define WSC_MSGTYPE_AP_WLAN_MGR 0x03 +#ifdef IWSC_SUPPORT +#define WSC_MSGTYPE_IWSC_NOTIFIER 0x04 +#endif /* IWSC_SUPPORT */ + +/* RF Band */ +#define WSC_RFBAND_24GHZ 0x01 +#define WSC_RFBAND_50GHZ 0x02 + +/* Simple Config state */ +#define WSC_SCSTATE_UNCONFIGURED 0x01 +#define WSC_SCSTATE_CONFIGURED 0x02 + +/* Common definition */ +#define WSC_MANUFACTURE "Ralink Technology, Corp." +#ifdef CONFIG_AP_SUPPORT +#define AP_WSC_MODEL_NAME "Ralink Wireless Access Point" +#define AP_WSC_DEVICE_NAME "RalinkAPS" +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#define STA_WSC_MODEL_NAME "Ralink Wireless Linux Client" +#define STA_WSC_DEVICE_NAME "RalinkLinuxClient" +#define WSC_DEVICE_NAME_R "Ralink EX-Registrar" +#endif /* CONFIG_STA_SUPPORT */ +#define WSC_MODEL_NUMBER "RT2860" +#define WSC_MODEL_SERIAL "12345678" + +/* Time-Out, param for timer func, count by micro-sec, not ticks */ +#define WSC_EAPOL_START_TIME_OUT 2000 +#define WSC_EAP_ID_TIME_OUT 5000 +#define WSC_EAP_MSG_TIME_OUT 5000 +#ifdef SMART_MESH_HIDDEN_WPS +#undef WSC_EAP_MSG_TIME_OUT +#define WSC_EAP_MSG_TIME_OUT 2000 +#endif /* SMART_MESH_HIDDEN_WPS */ +#define WSC_EAP_MSG_ACK_TIME_OUT 1000 +#define WSC_EAP_EAP_FAIL_TIME_OUT 1000 +#define WSC_TWO_MINS_TIME_OUT 120000 +#define WSC_UPNP_M2D_TIME_OUT 15000 +#define WSC_UPNP_MSG_TIME_OUT 15000 +#define WSC_PROFILE_RETRY_TIME_OUT 10000 +#ifdef WSC_LED_SUPPORT +#define WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT 300000 /* 300 seconds */ +#define WSC_WPS_FAIL_LED_PATTERN_TIMEOUT 15000 /* 15 seconds. */ +#define WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT 2500 /* 2.5 seconds. */ +#define WSC_WPS_TURN_OFF_LED_TIMEOUT 1000 /* 1 second. */ +#endif /* WSC_LED_SUPPORT */ + +#define WSC_WPS_AP_SETUP_LOCK_TIME 60 /* 60 mins */ +#define WSC_WPS_AP_MAX_PIN_ATTACK 3 +#define WSC_LOCK_FOREVER_PIN_ATTACK 10 + +#define WSC_INIT_ENTRY_APIDX 0xFF +#define WSC_MAX_DATA_LEN 1024 + +#define WSC_ENTRY_GET_EAPOL_START 0x1 +#define WSC_ENTRY_GET_EAP_RSP_ID 0x2 + +#define WSC_WR_FILE_MAX_BUF 1500 +/* Pack struct to align at byte */ +/*#pragma pack(1) */ + +/* General used field */ + +/* UUID related definition */ +#define UUID_LEN_HEX 16 /* 128 bits => 16 bytes */ +#define UUID_LEN_STR 37 /* hex to string, plus 4 dash, plus 1 '\0' */ +#define UUID_VERSION 1 /* We currently just support version 1 */ + +/* user define length add by woody */ +#define WSC_MANUFACTURE_LEN 64 +#define WSC_MODELNAME_LEN 32 +#define WSC_MODELNUNBER_LEN 32 +#define WSC_DEVICENAME_LEN 32 +#define WSC_SERIALNUNBER_LEN 32 +#define MAX_2ND_DEV_TYPE_LIST 2 +#define MAX_2ND_DEV_TYPE_LIST_BUFFER (1+(8*MAX_2ND_DEV_TYPE_LIST)) + +typedef struct _WSC_UUID_T{ + UINT32 timeLow; + UINT16 timeMid; + UINT16 timeHi_Version; + UCHAR clockSeqHi_Var; + UCHAR clockSeqLow; + UCHAR node[6]; +}WSC_UUID_T; + +/* For WSC state machine states. */ +/* We simplified it */ +typedef enum _WscState +{ + WSC_STATE_OFF, + WSC_STATE_INIT, + WSC_STATE_START, + WSC_STATE_FAIL, + WSC_STATE_CONFIGURED, + WSC_STATE_LINK_UP, + WSC_STATE_SEND_EAPOL_START, + WSC_STATE_WAIT_EAPOL_START, + WSC_STATE_WAIT_UPNP_START, + WSC_STATE_WAIT_REQ_ID, + WSC_STATE_WAIT_RESP_ID, + WSC_STATE_WAIT_WSC_START, + WSC_STATE_WAIT_M1, + WSC_STATE_SENT_M1, + WSC_STATE_SENT_M2D, + WSC_STATE_WAIT_M2, + WSC_STATE_RX_M2D, + WSC_STATE_WAIT_PIN, + WSC_STATE_WAIT_M3, + WSC_STATE_WAIT_M4, + WSC_STATE_WAIT_M5, + WSC_STATE_WAIT_M6, + WSC_STATE_WAIT_M7, + WSC_STATE_WAIT_M8, + WSC_STATE_WAIT_DONE, + WSC_STATE_WAIT_ACK, + WSC_STATE_WAIT_EAPFAIL, + WSC_STATE_WAIT_DISCONN +} WSC_STATE; + +/* WSC saved message */ +typedef struct _WSC_MESSAGE +{ + INT Length; /* Length of saved message */ + UCHAR Data[2048]; /* Contents */ +} WSC_MESSAGE, *PWSC_MESSAGE; + + +/* Data structure to hold Enrollee and Registrar information */ +typedef struct _WSC_DEV_INFO +{ + UCHAR Version; + UCHAR Version2; + UCHAR Uuid[16]; + UCHAR MacAddr[6]; + UCHAR DeviceName[32]; + UCHAR PriDeviceType[8]; + UCHAR SecDevTypList[MAX_2ND_DEV_TYPE_LIST_BUFFER]; /* 2nd Device Type List, ref. P2P Spec. v1.1 Table 29*/ + USHORT AuthTypeFlags; + USHORT EncrTypeFlags; + UCHAR ConnTypeFlags; + USHORT ConfigMethods; + UCHAR ScState; + UCHAR Manufacturer[64]; + UCHAR ModelName[32]; + UCHAR ModelNumber[32]; + UCHAR SerialNumber[32]; + UCHAR RfBand; + UINT OsVersion; + UINT FeatureId; + USHORT AssocState; + USHORT DevPwdId; + USHORT ConfigError; + UCHAR Ssid[32]; + UCHAR NewKey[64 + 1]; /* not sure sprintf would add '\0' or not, add one byte for \0' */ + INT NewKeyLen; + UCHAR NewKeyIndex; +} WSC_DEV_INFO, *PWSC_DEV_INFO; + +/* data structure to store info of the instance of Registration protocol */ +typedef struct _WSC_REG_DATA +{ + /* filled in by device self */ + WSC_DEV_INFO SelfInfo; + /* filled in by wps peer */ + WSC_DEV_INFO PeerInfo; + + /*Diffie Hellman parameters */ +/* BIGNUM *DH_PubKey_Peer; //peer's pub key stored in bignum format */ +/* DH *DHSecret; //local key pair in bignum format */ + UCHAR EnrolleeRandom[192]; /* Saved random byte for public key generation */ + + UCHAR ReComputePke; + UCHAR Pke[192]; /*enrollee's raw pub key */ + UCHAR Pkr[192]; /*registrar's raw pub key */ + + UCHAR SecretKey[192]; /* Secret key calculated by enrollee */ + + UCHAR StaEncrSettings[128]; /* to be sent in M2/M8 by reg & M7 by enrollee */ + UCHAR ApEncrSettings[1024]; + + /* Saved Message content for authenticator calculation */ + WSC_MESSAGE LastTx; + WSC_MESSAGE LastRx; + + /* Device password */ + UCHAR PIN[8]; + UCHAR PinCodeLen; + + /* From KDF Key */ + UCHAR AuthKey[32]; + UCHAR KeyWrapKey[16]; + UCHAR Emsk[32]; + + USHORT EnrolleePwdId; + UCHAR EnrolleeNonce[16]; /*N1, from enrollee */ + UCHAR RegistrarNonce[16]; /*N2, from registrar */ + UCHAR SelfNonce[16]; + + UCHAR Psk1[16]; + UCHAR Psk2[16]; + + UCHAR EHash1[32]; + UCHAR EHash2[32]; + UCHAR Es1[16]; + UCHAR Es2[16]; + + UCHAR RHash1[32]; + UCHAR RHash2[32]; + UCHAR Rs1[16]; + UCHAR Rs2[16]; +} WSC_REG_DATA, *PWSC_REG_DATA; + + +/* WSC UPnP node info. */ +typedef struct _WSC_UPNP_NODE_INFO{ + BOOLEAN bUPnPInProgress; + BOOLEAN bUPnPMsgTimerRunning; + BOOLEAN bUPnPMsgTimerPending; + UINT registrarID; + RALINK_TIMER_STRUCT UPnPMsgTimer; +}WSC_UPNP_NODE_INFO, *PWSC_UPNP_NODE_INFO; + +#define MAX_PBC_STA_TABLE_SIZE 4 +typedef struct _WSC_STA_PBC_PROBE_INFO { + ULONG ReciveTime[MAX_PBC_STA_TABLE_SIZE]; + UCHAR WscPBCStaProbeCount; + UCHAR StaMacAddr[MAX_PBC_STA_TABLE_SIZE][MAC_ADDR_LEN]; + UCHAR Valid[MAX_PBC_STA_TABLE_SIZE]; +} WSC_STA_PBC_PROBE_INFO, *PWSC_STA_PBC_PROBE_INFO; + +#ifdef IWSC_SUPPORT +typedef struct _IWSC_INFO +{ + RALINK_TIMER_STRUCT IWscT1Timer; + RALINK_TIMER_STRUCT IWscT2Timer; + RALINK_TIMER_STRUCT IWscEntryTimer; + RALINK_TIMER_STRUCT IWscDevQueryTimer; + UCHAR DialogToken; + UCHAR PeerDialogToken; + BOOLEAN bSelRegStart; + BOOLEAN bReStart; + BOOLEAN bIWscT1TimerRunning; + BOOLEAN bIWscT2TimerRunning; + BOOLEAN bIWscEntryTimerRunning; + BOOLEAN bIWscDevQueryReqTimerRunning; + BOOLEAN bIWscDevQueryRspTimerRunning; + BOOLEAN bLimitedUI; // own device is limited UI device + BOOLEAN bSinglePIN; // use Physical PIN + BOOLEAN bDoNotChangeBSSID; + BOOLEAN bSendEapolStart; + UCHAR RegMacAddr[MAC_ADDR_LEN]; + UINT8 IWscSmpbcAcceptCount; + USHORT IpConfMethod; // Bitwise OR values + USHORT IpMethod; // Single Method in WSC Credential + UINT32 SelfIpv4Addr; // Device own IPv4 Address + UINT32 PeerIpv4Addr; // IPv4 Address for peer in credtential + UINT32 RegIpv4Addr; // Registrar's IPv4 Address + UINT32 Ipv4SubMask; // 255.0.0.0 + UINT32 CurrentIpRange; + UINT32 AvaSubMaskList[IWSC_MAX_SUB_MASK_LIST_COUNT]; + UINT8 IpDevCount; // Maximal value is 62 + UINT8 RegDepth; // 0: Root Regitrar + UINT8 AvaSubMaskListCount;// Available Submask List Count for peer. Maximal value is 3 + BOOLEAN bAssignWscIPv4; // TRUE: Can be registrar and assign WSC IPv4 to peer, FALSE: Cannot assign WSC IPv4 to peer anymore + BOOLEAN bDoNotStop; + UCHAR IWscDevQueryReqMacAddr[MAC_ADDR_LEN]; + UINT8 SmpbcEnrolleeCount; +#ifdef IWSC_TEST_SUPPORT + UINT8 IWscConfMode; // 1: Enrollee, 2: Registrar + UINT8 IWscDefaultSecurity; // 1: OPEN-NONE, 2: OPEN-WEP, 3: WPA2PSK-AES + BOOLEAN bIwscSmpbcScanningOnly; + BOOLEAN bEmptySubmaskList; + BOOLEAN bBlockConnection; // TRUE: block connection with peers (i.e. Not to do security handshaking with peers) +#endif // IWSC_TEST_SUPPORT // +} IWSC_INFO, *PIWSC_INFO; +#endif // IWSC_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +typedef struct GNU_PACKED _WSC_PEER_DEV_INFO { + UCHAR WscPeerDeviceName[32]; + UCHAR WscPeerManufacturer[64]; + UCHAR WscPeerModelName[32]; + UCHAR WscPeerModelNumber[32]; + UCHAR WscPeerSerialNumber[32]; + UCHAR WscPeerMAC[6]; +} WSC_PEER_DEV_INFO, *PWSC_PEER_DEV_INFO; + +#ifdef WSC_V2_SUPPORT +#define WSC_PIN_ATTACK_CHECK 600 +#define WSC_V2_VERSION 0x20 +#define TLV_ASCII 0 +#define TLV_HEX 1 + +#ifdef WSC_NFC_SUPPORT +/* + 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) + 6 V Wireless Radio Status (1byte) +*/ +#define TYPE_CMD_RESULT 0 +#define TYPE_CONFIGURATION 1 +#define TYPE_PASSWORD 2 +#define TYPE_IP_ADDR 3 +#define TYPE_RTSP_PORT 4 +#define TYPE_NFC_STATUS 5 +#define TYPE_WIFI_RADIO_STATUS 6 +#define TYPE_PASSWDHO_S 7 /* handover Select */ +#define TYPE_PASSWDHO_R 8 /* handover Request */ + +#define NFC_DEV_PASSWD_LEN 32 +#define NFC_DEV_PASSWD_HASH_LEN 20 + +/* NFC usage models */ +#define MODEL_PASSWORD_TOKEN 0 +#define MODEL_CONFIGURATION_TOKEN 1 +#define MODEL_HANDOVER 2 +#endif /* WSC_NFC_SUPPORT */ + +typedef struct _WSC_TLV { + USHORT TlvTag; + USHORT TlvLen; + PUCHAR pTlvData; + UCHAR TlvType; /* 0: ASCII, 1: Hex */ +} WSC_TLV, *PWSC_TLV; + +typedef struct _WSC_V2_INFO { + WSC_TLV ExtraTlv; + BOOLEAN bWpsEnable; /* FALSE: disable WSC , TRUE: enable WSC */ + BOOLEAN bEnableWpsV2; /* FALSE: not support WSC 2.0, TRUE: support WSC 2.0 */ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bForceSetAP; /* FALSE: do not change AP's setting when AP is configured, TRUE: force to change AP's setting when AP is configured */ +#endif /* CONFIG_STA_SUPPORT */ +} WSC_V2_INFO, *PWSC_V2_INFO; +#endif /* WSC_V2_SUPPORT */ + +/* WSC control block */ +typedef struct _WSC_CTRL +{ + INT WscConfMode; /* 0 Wsc not enable; 1 un-configure AP ; 3 un-configure AP with Proxy ; */ + /* 5 un-configure AP with Registrar ; 7 un-configure AP with proxy and Registrar */ + INT WscMode; /* 1 PIN ;2 PBC set from UI dynamically */ + UCHAR WscConfStatus; /* 1 un-configured; 2 configured; need to update to .dat */ + USHORT WscConfigMethods; /* Registrar support list. The List is bitwise. PBC:0x0080 Lable:0x0004 Display:0x0008 */ + INT WscStatus; /* for user to monitor the status */ + INT WscState; /* WSC Protocl State: M1 to M8 */ + UINT WscPinCode; /* record the UI's PIN code input when we are registrar */ + UCHAR WscPinCodeLen; /* record the UI's PIN code input length when we are registrar */ + BOOLEAN WscEnrollee4digitPinCode; /* flag to use 4 or 8 digit Device own PIN code. */ + UINT WscEnrolleePinCode; /* recored Device own PIN code. */ + UCHAR WscEnrolleePinCodeLen; /* recored Device own PIN code length */ + INT WscSelReg; /* record the UI's PIN code input when we are registrar */ + NDIS_802_11_SSID WscSsid; /* select a desired ssid to connect for PIN mode */ + UCHAR WscPBCBssCount; /* Count of PBC activated APs. */ + UCHAR WscBssid[MAC_ADDR_LEN]; /* select a desired bssid to connect */ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN WscEnAssociateIE; /* Add WSC IE on Associate frame. */ + BOOLEAN WscEnProbeReqIE; /* Add WSC IE on Probe-Req frame. */ + UCHAR WscPeerMAC[MAC_ADDR_LEN]; /* peer Mac Address */ +#endif /* CONFIG_STA_SUPPORT */ + WSC_REG_DATA RegData; /* Registrar pair data */ + UCHAR lastId; + UCHAR WscUseUPnP; + BOOLEAN EapMsgRunning; /* already recived Eap-Rsp(Identity) and sent M1 or Eap-Req(Start) */ + UCHAR WscRetryCount; + UCHAR EntryIfIdx; + UCHAR EntryAddr[MAC_ADDR_LEN]; + BOOLEAN Wsc2MinsTimerRunning; + RALINK_TIMER_STRUCT Wsc2MinsTimer; + WSC_PROFILE WscProfile; /* Saved WSC profile after M8 */ + WSC_PROFILE WscM7Profile; /* Saved WSC profile from AP Settings in M7 */ + BOOLEAN bConfiguredAP; /* True: AP is in the configured state. FALSE: others */ + WSC_UPNP_NODE_INFO WscUPnPNodeInfo; /*Use to save UPnP node related info. */ + + BOOLEAN EapolTimerRunning; + BOOLEAN EapolTimerPending; + RALINK_TIMER_STRUCT EapolTimer; + + BOOLEAN WscPBCTimerRunning; + RALINK_TIMER_STRUCT WscPBCTimer; + BOOLEAN WscScanTimerRunning; + RALINK_TIMER_STRUCT WscScanTimer; + BOOLEAN WscProfileRetryTimerRunning; + RALINK_TIMER_STRUCT WscProfileRetryTimer; +#ifdef CONFIG_STA_SUPPORT + /* 0x00: disable, 0x01: Auto Connect first credential only, 0x02: Auto Connect and rotate all crentials */ + UCHAR WscDriverAutoConnect; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef WSC_LED_SUPPORT + ULONG WscLEDMode; /* WPS LED mode: LED_WPS_XXX definitions. */ + ULONG WscLastWarningLEDMode; /* LED_WPS_ERROR or LED_WPS_SESSION_OVERLAP_DETECTED */ + BOOLEAN bSkipWPSTurnOffLED; /* Skip the WPS turn off LED command. */ + BOOLEAN WscLEDTimerRunning; + RALINK_TIMER_STRUCT WscLEDTimer; + BOOLEAN WscSkipTurnOffLEDTimerRunning; + RALINK_TIMER_STRUCT WscSkipTurnOffLEDTimer; + /* This variable is TRUE after the 120 seconds WPS walk time expiration. */ + /* Note that in the case of LED mode 9, the error LED should be turned on only after WPS walk time expiration */ + /* if the NIC cannot find any WPS PBC-enabled APs in the last scanning result. */ + BOOLEAN bWPSWalkTimeExpiration; +#endif /* WSC_LED_SUPPORT */ + UCHAR WpaPsk[64]; + INT WpaPskLen; + BOOLEAN bWscTrigger; /* TRUE: AP-Enrollee & AP-Registrar work, FALSE: AP-Enrollee & AP-Registrar stop working */ + PVOID pAd; + UINT WscLastPinFromEnrollee; + BOOLEAN WscRejectSamePinFromEnrollee; +#ifdef CONFIG_AP_SUPPORT + NDIS_802_11_SSID WscDefaultSsid; /* Default WPS SSID after WPS process complete with Enrollee when AP is un-configured Registrar. */ + BOOLEAN bWCNTest; +#endif /* CONFIG_AP_SUPPORT */ + INT WscKeyASCII; /*WscKeyASCII (0:Hex, 1:ASCII(random length), others: ASCII length(8~63, default 8)) */ + INT WscActionMode; + UCHAR Wsc_Uuid_E[UUID_LEN_HEX]; + UCHAR Wsc_Uuid_Str[UUID_LEN_STR]; + + UCHAR WpsApBand; /* Preferred WPS AP PHY type. Ref: PREFERRED_WPS_AP_PHY_TYPE */ +/*add by woody */ + UCHAR Flags; + + WSC_PEER_DEV_INFO WscPeerInfo; + BOOLEAN bCheckMultiByte; +#ifdef WSC_V2_SUPPORT + WSC_V2_INFO WscV2Info; +#endif /* WSC_V2_SUPPORT */ + RALINK_TIMER_STRUCT WscUpdatePortCfgTimer; + BOOLEAN WscUpdatePortCfgTimerRunning; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT WscSetupLockTimer; + BOOLEAN WscSetupLockTimerRunning; + RALINK_TIMER_STRUCT WscPinAttackCountCheckTimer; + BOOLEAN WscPinAttackCountCheckTimerRunning; + BOOLEAN bSetupLock; + UCHAR PinAttackCount; + UCHAR MaxPinAttack; + UINT SetupLockTime; /* unit: minute */ +#endif /* CONFIG_AP_SUPPORT */ + BOOLEAN bWscAutoTigeer; + BOOLEAN bWscFragment; + PUCHAR pWscRxBuf; + INT WscRxBufLen; + USHORT WscFragSize; + INT WscTxBufLen; + PUCHAR pWscTxBuf; + BOOLEAN bWscLastOne; + BOOLEAN bWscFirstOne; + PUCHAR pWscCurBufIdx; + NDIS_SPIN_LOCK WscPeerListSemLock; + LIST_HEADER WscPeerList; + RALINK_TIMER_STRUCT M2DTimer; + BOOLEAN bM2DTimerRunning; + INT M2DACKBalance; +#ifdef IWSC_SUPPORT + NDIS_SPIN_LOCK WscConfiguredPeerListSemLock; + LIST_HEADER WscConfiguredPeerList; +#endif /* IWSC_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + BOOLEAN bTriggerByNFC; + UCHAR NfcPasswdLen; + UCHAR NfcPasswd[NFC_DEV_PASSWD_LEN]; + USHORT NfcPasswdID; + UCHAR NfcPasswdHash[NFC_DEV_PASSWD_HASH_LEN]; + UCHAR PeerNfcPasswdLen; + UCHAR PeerNfcPasswd[NFC_DEV_PASSWD_LEN]; + USHORT PeerNfcPasswdID; + UCHAR PeerNfcPasswdHash[NFC_DEV_PASSWD_HASH_LEN]; + UCHAR NfcStatus; /* b'0: 1 - ON, 0 - OFF; b'1: 1 - nfc device detect */ + UCHAR NfcPasswdCaculate; + BOOLEAN bRegenPublicKey; /* For negative test */ + UCHAR NfcModel; /* 0:Password_Token, 1:Configuration_Token, 2:Handover */ +#endif /* WSC_NFC_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bWscAutoTriggerDisable; /* Default setting is FALSE */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef SMART_MESH + BOOLEAN bWscPBCAddrMode; + UCHAR WscPBCAddr[MAC_ADDR_LEN]; +#ifdef SMART_MESH_HIDDEN_WPS + BOOLEAN bRunningHiddenWPS; /* Determine If HiddenWPS is running now */ +#endif /* SMART_MESH_HIDDEN_WPS */ +#endif /* SMART_MESH */ + BOOLEAN bFromApCli; +} WSC_CTRL, *PWSC_CTRL; + +typedef struct GNU_PACKED _WSC_CONFIGURED_VALUE { + USHORT WscConfigured; /* 1 un-configured; 2 configured */ + UCHAR WscSsid[32+1]; + USHORT WscAuthMode; /* mandatory, 0x01: open, 0x02: wpa-psk, 0x04: shared, 0x08:wpa, 0x10: wpa2, 0x20: wpa2-psk */ + USHORT WscEncrypType; /* 0x01: none, 0x02: wep, 0x04: tkip, 0x08: aes */ + UCHAR DefaultKeyIdx; + UCHAR WscWPAKey[64+1]; + UCHAR WscSsidLen; + UCHAR WscWPAKeyLen; +} WSC_CONFIGURED_VALUE; + +/* + Following definitions are used for UPnP module to communicate msg. +*/ + +/* Ralink specific message header for Linux specific NETLINK socket. */ +#define RTMP_WSC_NLMSG_HDR_LEN 30 /*signature(8) + envID(4) + ackID(4) + msgLen(4) + Flag(2) + segLen(2) + devAddr(6) */ +typedef struct GNU_PACKED _RTMP_WSC_NLMSG_HDR{ + UCHAR signature[8]; /* Signature used to identify that this's a Ralink specific NETLINK message. + MUST be "RAWSCMSG" currently. + */ + UINT envID; /* Unique event Identification assigned by sender. */ + UINT ackID; /* Notify that this message is a repsone for the message whose event identifier is "ackID". */ + UINT msgLen; /* Totally length for this message. This message may seperate in serveral packets. */ + USHORT flags; + USHORT segLen; /* The "segLen" means the actual data length in this one msg packet. + Because the NETLINK socket just support 256bytes for "IWCUSTOM" typed message, so we may + need to do fragement for our msg. If one message was fragemented as serveral pieces, the + user space receiver need to re-assemble it. + */ + UCHAR devAddr[MAC_ADDR_LEN]; /* MAC address of the net device which send this netlink msg. */ +}RTMP_WSC_NLMSG_HDR; + + +/* + Ralink specific WSC Mesage Header definition. +*/ +#define RTMP_WSC_MSG_HDR_LEN 12 /*msgType(2) + msgSubType(2) + ipAddr(4) + len(4) */ +typedef struct GNU_PACKED _RTMP_WSC_MSG_HDR{ + USHORT msgType; + USHORT msgSubType; + UINT ipAddr; + UINT msgLen; /*Not include this header. */ +}RTMP_WSC_MSG_HDR; + +#define WSC_MSG_TYPE_ENROLLEE 0x1 +#define WSC_MSG_TYPE_PROXY 0x2 +#define WSC_MSG_TYPE_REGISTRAR 0x3 +#define WSC_MSG_TYPE_CTRL 0x4 +#define WSC_MSG_TYPE_MGMT 0x5 + +PSTRING WscGetAuthTypeStr( + IN USHORT authFlag); + +PSTRING WscGetEncryTypeStr( + IN USHORT encryFlag); + +#define IWEVCUSTOM_MSG_MAX_LEN 255 /*refer to kernel definition. */ +#define IWEVCUSTOM_PAYLOD_MAX_LEN (IWEVCUSTOM_MSG_MAX_LEN - RTMP_WSC_NLMSG_HDR_LEN) + + +#define WSC_U2KMSG_HDR_LEN 41 +typedef struct GNU_PACKED _RTMP_WSC_U2KMSG_HDR{ + UINT envID; /*Event ID. */ + UCHAR Addr1[MAC_ADDR_LEN]; /*RA, should be the MAC address of the AP. */ + UCHAR Addr2[MAC_ADDR_LEN]; /*TA, should be the ipAddress of remote UPnP Device/CotrnolPoint. */ + UCHAR Addr3[MAC_ADDR_LEN]; /*DA, Not used now. */ + UCHAR rsvWLHdr[2]; /*Reserved space for remained 802.11 hdr content. */ + UCHAR rsv1HHdr[LENGTH_802_1_H];/*Reserved space for 802.1h header */ + IEEE8021X_FRAME IEEE8021XHdr; /*802.1X header */ + EAP_FRAME EAPHdr; /*EAP frame header. */ +}RTMP_WSC_U2KMSG_HDR; +/*--- Used for UPnP module to communicate msg. */ + +/* define OpMode for WscSendMessage */ +#undef AP_MODE +#undef AP_CLIENT_MODE +#undef STA_MODE + +#define AP_MODE 0x00 +#define AP_CLIENT_MODE 0x01 +#define STA_MODE 0x02 +#define REGISTRAR_ACTION 0x40 +#define ENROLLEE_ACTION 0x80 + +/* Definition for Config Methods */ +#define WPS_CONFIG_METHODS_USBA 0x0001 +#define WPS_CONFIG_METHODS_ETHERNET 0x0002 +#define WPS_CONFIG_METHODS_LABEL 0x0004 +#define WPS_CONFIG_METHODS_DISPLAY 0x0008 +#define WPS_CONFIG_METHODS_ENT 0x0010 /* External NFC Token */ +#define WPS_CONFIG_METHODS_INT 0x0020 /* Integrated NFC Token */ +#define WPS_CONFIG_METHODS_NFCI 0x0040 /* NFC Interface */ +#define WPS_CONFIG_METHODS_PBC 0x0080 +#define WPS_CONFIG_METHODS_KEYPAD 0x0100 + +typedef struct _UUID_BSSID_CH_INFO { + UCHAR Uuid[16]; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR Band; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR MacAddr[MAC_ADDR_LEN]; +#ifdef IWSC_SUPPORT + UINT8 RspType; +#endif /* IWSC_SUPPORT */ +} UUID_BSSID_CH_INFO, *PUUID_BSSID_CH_INFO; + +/* + Preferred WPS AP type. + + a) PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST + Select 2.4G WPS AP first. Otherwise select 5G WPS AP. + b) PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST + Select the 5G WPS AP first. Otherwise select the 2.4G WPS AP. + c) PREFERRED_WPS_AP_PHY_TYPE_AUTO_SELECTION + Automactically select WPS AP. +*/ +typedef enum _PREFERRED_WPS_AP_PHY_TYPE +{ + PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST = 0, + PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST, + PREFERRED_WPS_AP_PHY_TYPE_AUTO_SELECTION, + PREFERRED_WPS_AP_PHY_TYPE_MAXIMUM, +} PREFERRED_WPS_AP_PHY_TYPE; + +typedef enum _WscSecurityMode{ + WPA2PSKAES, + WPA2PSKTKIP, + WPAPSKAES, + WPAPSKTKIP, + WPAPSKWPA2PSKTKIPAES, +}WSC_SECURITY_MODE; + +typedef struct _WSC_PEER_ENTRY { + struct _WSC_PEER_ENTRY *pNext; + ULONG receive_time; + UCHAR mac_addr[MAC_ADDR_LEN]; +#ifdef IWSC_SUPPORT + BOOLEAN bIWscSmpbcAccept; +#endif /* IWSC_SUPPORT */ +} WSC_PEER_ENTRY, *PWSC_PEER_ENTRY; + + +#endif /* WSC_INCLUDED */ + +#endif /* __WSC_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wsc_tlv.h b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wsc_tlv.h new file mode 100644 index 000000000..6f47fd563 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/include/wsc_tlv.h @@ -0,0 +1,290 @@ +/* + *************************************************************************** + * 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_tlv.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + JuemingChen 06-09-11 Initial +*/ + +#ifndef __WSC_TLV_H__ +#define __WSC_TLV_H__ + +/* Data Element Definitions */ +#define WSC_ID_AP_CHANNEL 0x1001 +#define WSC_ID_ASSOC_STATE 0x1002 +#define WSC_ID_AUTH_TYPE 0x1003 +#define WSC_ID_AUTH_TYPE_FLAGS 0x1004 +#define WSC_ID_AUTHENTICATOR 0x1005 +#define WSC_ID_CONFIG_METHODS 0x1008 +#define WSC_ID_CONFIG_ERROR 0x1009 +#define WSC_ID_CONF_URL4 0x100A +#define WSC_ID_CONF_URL6 0x100B +#define WSC_ID_CONN_TYPE 0x100C +#define WSC_ID_CONN_TYPE_FLAGS 0x100D +#define WSC_ID_CREDENTIAL 0x100E +#define WSC_ID_ENCR_TYPE 0x100F +#define WSC_ID_ENCR_TYPE_FLAGS 0x1010 +#define WSC_ID_DEVICE_NAME 0x1011 +#define WSC_ID_DEVICE_PWD_ID 0x1012 +#define WSC_ID_E_HASH1 0x1014 +#define WSC_ID_E_HASH2 0x1015 +#define WSC_ID_E_SNONCE1 0x1016 +#define WSC_ID_E_SNONCE2 0x1017 +#define WSC_ID_ENCR_SETTINGS 0x1018 +#define WSC_ID_ENROLLEE_NONCE 0x101A +#define WSC_ID_FEATURE_ID 0x101B +#define WSC_ID_IDENTITY 0x101C +#define WSC_ID_IDENTITY_PROOF 0x101D +#define WSC_ID_KEY_WRAP_AUTH 0x101E +#define WSC_ID_KEY_IDENTIFIER 0x101F +#define WSC_ID_MAC_ADDR 0x1020 +#define WSC_ID_MANUFACTURER 0x1021 +#define WSC_ID_MSG_TYPE 0x1022 +#define WSC_ID_MODEL_NAME 0x1023 +#define WSC_ID_MODEL_NUMBER 0x1024 +#define WSC_ID_NW_INDEX 0x1026 +#define WSC_ID_NW_KEY 0x1027 +#define WSC_ID_NW_KEY_INDEX 0x1028 +#define WSC_ID_NEW_DEVICE_NAME 0x1029 +#define WSC_ID_NEW_PWD 0x102A +#define WSC_ID_OOB_DEV_PWD 0x102C +#define WSC_ID_OS_VERSION 0x102D +#define WSC_ID_POWER_LEVEL 0x102F +#define WSC_ID_PSK_CURRENT 0x1030 +#define WSC_ID_PSK_MAX 0x1031 +#define WSC_ID_PUBLIC_KEY 0x1032 +#define WSC_ID_RADIO_ENABLED 0x1033 +#define WSC_ID_REBOOT 0x1034 +#define WSC_ID_REGISTRAR_CURRENT 0x1035 +#define WSC_ID_REGISTRAR_ESTBLSHD 0x1036 +#define WSC_ID_REGISTRAR_LIST 0x1037 +#define WSC_ID_REGISTRAR_MAX 0x1038 +#define WSC_ID_REGISTRAR_NONCE 0x1039 +#define WSC_ID_REQ_TYPE 0x103A +#define WSC_ID_RESP_TYPE 0x103B +#define WSC_ID_RF_BAND 0x103C +#define WSC_ID_R_HASH1 0x103D +#define WSC_ID_R_HASH2 0x103E +#define WSC_ID_R_SNONCE1 0x103F +#define WSC_ID_R_SNONCE2 0x1040 +#define WSC_ID_SEL_REGISTRAR 0x1041 +#define WSC_ID_SERIAL_NUM 0x1042 +#define WSC_ID_SC_STATE 0x1044 +#define WSC_ID_SSID 0x1045 +#define WSC_ID_TOT_NETWORKS 0x1046 +#define WSC_ID_UUID_E 0x1047 +#define WSC_ID_UUID_R 0x1048 +#define WSC_ID_VENDOR_EXT 0x1049 +#define WSC_ID_VERSION 0x104A +#define WSC_ID_X509_CERT_REQ 0x104B +#define WSC_ID_X509_CERT 0x104C +#define WSC_ID_EAP_IDENTITY 0x104D +#define WSC_ID_MSG_COUNTER 0x104E +#define WSC_ID_PUBKEY_HASH 0x104F +#define WSC_ID_REKEY_KEY 0x1050 +#define WSC_ID_KEY_LIFETIME 0x1051 +#define WSC_ID_PERM_CFG_METHODS 0x1052 +#define WSC_ID_SEL_REG_CFG_METHODS 0x1053 +#define WSC_ID_PRIM_DEV_TYPE 0x1054 +#define WSC_ID_SEC_DEV_TYPE_LIST 0x1055 +#define WSC_ID_PORTABLE_DEVICE 0x1056 +#define WSC_ID_AP_SETUP_LOCKED 0x1057 +#define WSC_ID_APP_LIST 0x1058 +#define WSC_ID_EAP_TYPE 0x1059 +#define WSC_ID_INIT_VECTOR 0x1060 +#define WSC_ID_KEY_PROVIDED_AUTO 0x1061 +#define WSC_ID_8021X_ENABLED 0x1062 +#define WSC_ID_APPSESSIONKEY 0x1063 +#define WSC_ID_WEPTRANSMITKEY 0x1064 +#ifdef IWSC_SUPPORT +#define WSC_ID_ENTRY_ACCEPTABLE 0x106D +#define WSC_ID_REGISTRATON_READY 0x106E +#define WSC_ID_REGISTRAR_IPV4 0x106F +#define WSC_ID_IPV4_SUBMASK 0x1070 +#define WSC_ID_ENROLLEE_IPV4 0x1071 +#define WSC_ID_IPV4_SUBMASK_LIST 0x1072 +#define WSC_ID_IP_ADDR_CONF_METHOD 0x1073 +#endif /* IWSC_SUPPORT */ + +/* WFA Vendor Extension Subelements */ +#define WFA_EXT_ID_VERSION2 0x00 +#define WFA_EXT_ID_AUTHORIZEDMACS 0x01 +#define WFA_EXT_ID_NW_KEY_SHAREABLE 0x02 +#define WFA_EXT_ID_REQ_TO_ENROLL 0x03 +#define WFA_EXT_ID_SETTINGS_DELAY_TIME 0x04 + +/* Association states */ +#define WSC_ASSOC_NOT_ASSOCIATED 0 +#define WSC_ASSOC_CONN_SUCCESS 1 +#define WSC_ASSOC_CONFIG_FAIL 2 +#define WSC_ASSOC_ASSOC_FAIL 3 +#define WSC_ASSOC_IP_FAIL 4 + +/* Authentication types */ +#define WSC_AUTHTYPE_OPEN 0x0001 +#define WSC_AUTHTYPE_WPAPSK 0x0002 +#define WSC_AUTHTYPE_SHARED 0x0004 +#define WSC_AUTHTYPE_WPA 0x0008 +#define WSC_AUTHTYPE_WPA2 0x0010 +#define WSC_AUTHTYPE_WPA2PSK 0x0020 +#define WSC_AUTHTYPE_WPANONE 0x0080 + +/* Config methods */ +#define WSC_CONFMET_USBA 0x0001 +#define WSC_CONFMET_ETHERNET 0x0002 +#define WSC_CONFMET_LABEL 0x0004 +#define WSC_CONFMET_DISPLAY 0x0008 +#define WSC_CONFMET_EXT_NFC_TOK 0x0010 +#define WSC_CONFMET_INT_NFC_TOK 0x0020 +#define WSC_CONFMET_NFC_INTF 0x0040 +#define WSC_CONFMET_PBC 0x0080 +#define WSC_CONFMET_KEYPAD 0x0100 + +/* WSC error messages */ +#define WSC_ERROR_NO_ERROR 0 +#define WSC_ERROR_OOB_INT_READ_ERR 1 +#define WSC_ERROR_DECRYPT_CRC_FAIL 2 +#define WSC_ERROR_CHAN24_NOT_SUPP 3 +#define WSC_ERROR_CHAN50_NOT_SUPP 4 +#define WSC_ERROR_SIGNAL_WEAK 5 +#define WSC_ERROR_NW_AUTH_FAIL 6 +#define WSC_ERROR_NW_ASSOC_FAIL 7 +#define WSC_ERROR_NO_DHCP_RESP 8 +#define WSC_ERROR_FAILED_DHCP_CONF 9 +#define WSC_ERROR_IP_ADDR_CONFLICT 10 +#define WSC_ERROR_FAIL_CONN_REGISTRAR 11 +#define WSC_ERROR_MULTI_PBC_DETECTED 12 +#define WSC_ERROR_ROGUE_SUSPECTED 13 +#define WSC_ERROR_DEVICE_BUSY 14 +#define WSC_ERROR_SETUP_LOCKED 15 +#define WSC_ERROR_MSG_TIMEOUT 16 +#define WSC_ERROR_REG_SESSION_TIMEOUT 17 +#define WSC_ERROR_DEV_PWD_AUTH_FAIL 18 +#define WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH 20 +#define WSC_ERROR_DO_MULTI_PBC_DETECTION 251 +#define WSC_ERROR_CAN_NOT_ALLOCMEM 252 +#define WSC_ERROR_WANTING_FIELD 253 +#define WSC_ERROR_HASH_FAIL 254 +#define WSC_ERROR_HMAC_FAIL 255 + +/* Connection types */ +#define WSC_CONNTYPE_ESS 0x01 +#define WSC_CONNTYPE_IBSS 0x02 + +/* Device password ID */ +#define WSC_DEVICEPWDID_DEFAULT 0x0000 +#define WSC_DEVICEPWDID_USER_SPEC 0x0001 +#define WSC_DEVICEPWDID_MACHINE_SPEC 0x0002 +#define WSC_DEVICEPWDID_REKEY 0x0003 +#define WSC_DEVICEPWDID_PUSH_BTN 0x0004 +#define WSC_DEVICEPWDID_REG_SPEC 0x0005 + +/* Device type */ +#define WSC_DEVICETYPE_COMPUTER "Computer" +#define WSC_DEVICETYPE_AP "Access_Point" +#define WSC_DEVICETYPE_ROUTER_AP "Router_AP" +#define WSC_DEVICETYPE_PRINTER "Printer" +#define WSC_DEVICETYPE_PRINTER_BRIDGE "Printer_Brigde" +#define WSC_DEVICETYPE_ELECT_PIC_FRAME "Electronic_Picture_Frame" +#define WSC_DEVICETYPE_DIG_AUDIO_RECV "Digital_Audio_Receiver" +#define WSC_DEVICETYPE_WIN_MCE "Windows_Media_Center_Extender" +#define WSC_DEVICETYPE_WIN_MOBILE "Windows_Mobile" +#define WSC_DEVICETYPE_PVR "Personal_Video_Recorder" +#define WSC_DEVICETYPE_VIDEO_STB "Video_STB" +#define WSC_DEVICETYPE_PROJECTOR "Projector" +#define WSC_DEVICETYPE_IP_TV "IP_TV" +#define WSC_DEVICETYPE_DIG_STILL_CAM "Digital_Still_Camera" +#define WSC_DEVICETYPE_PHONE "Phone" +#define WSC_DEVICETYPE_VOID_PHONE "VoIP_Phone" +#define WSC_DEVICETYPE_GAME_CONSOLE "Game_console" +#define WSC_DEVICETYPE_OTHER "Other" + +/* Encryption type */ +#define WSC_ENCRTYPE_NONE 0x0001 +#define WSC_ENCRTYPE_WEP 0x0002 +#define WSC_ENCRTYPE_TKIP 0x0004 +#define WSC_ENCRTYPE_AES 0x0008 + +/* WSC Message Types */ +#define WSC_ID_BEACON 0x01 +#define WSC_ID_PROBE_REQ 0x02 +#define WSC_ID_PROBE_RESP 0x03 +#define WSC_ID_MESSAGE_M1 0x04 +#define WSC_ID_MESSAGE_M2 0x05 +#define WSC_ID_MESSAGE_M2D 0x06 +#define WSC_ID_MESSAGE_M3 0x07 +#define WSC_ID_MESSAGE_M4 0x08 +#define WSC_ID_MESSAGE_M5 0x09 +#define WSC_ID_MESSAGE_M6 0x0A +#define WSC_ID_MESSAGE_M7 0x0B +#define WSC_ID_MESSAGE_M8 0x0C +#define WSC_ID_MESSAGE_ACK 0x0D +#define WSC_ID_MESSAGE_NACK 0x0E +#define WSC_ID_MESSAGE_DONE 0x0F +#define WSC_ID_MESSAGE_EAP_REQ_ID 0x21 +#define WSC_ID_MESSAGE_EAP_REQ_START 0x22 +#define WSC_ID_MESSAGE_EAP_FAIL 0x23 +#define WSC_ID_MESSAGE_UNKNOWN 0xFF + +/* Device Type categories for primary and secondary device types */ +#define WSC_DEVICE_TYPE_CAT_COMPUTER 1 +#define WSC_DEVICE_TYPE_CAT_INPUT_DEVICE 2 +#define WSC_DEVICE_TYPE_CAT_PRINTER 3 +#define WSC_DEVICE_TYPE_CAT_CAMERA 4 +#define WSC_DEVICE_TYPE_CAT_STORAGE 5 +#define WSC_DEVICE_TYPE_CAT_NW_INFRA 6 +#define WSC_DEVICE_TYPE_CAT_DISPLAYS 7 +#define WSC_DEVICE_TYPE_CAT_MM_DEVICES 8 +#define WSC_DEVICE_TYPE_CAT_GAME_DEVICES 9 +#define WSC_DEVICE_TYPE_CAT_TELEPHONE 10 + +/* Device Type sub categories for primary and secondary device types */ +#define WSC_DEVICE_TYPE_SUB_CAT_COMP_PC 1 +#define WSC_DEVICE_TYPE_SUB_CAT_COMP_SERVER 2 +#define WSC_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR 3 +#define WSC_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER 1 +#define WSC_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER 2 +#define WSC_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL 1 +#define WSC_DEVICE_TYPE_SUB_CAT_STOR_NAS 1 +#define WSC_DEVICE_TYPE_SUB_CAT_NW_AP 1 +#define WSC_DEVICE_TYPE_SUB_CAT_NW_ROUTER 2 +#define WSC_DEVICE_TYPE_SUB_CAT_NW_SWITCH 3 +#define WSC_DEVICE_TYPE_SUB_CAT_DISP_TV 1 +#define WSC_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME 2 +#define WSC_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR 3 +#define WSC_DEVICE_TYPE_SUB_CAT_MM_DAR 1 +#define WSC_DEVICE_TYPE_SUB_CAT_MM_PVR 2 +#define WSC_DEVICE_TYPE_SUB_CAT_MM_MCX 3 +#define WSC_DEVICE_TYPE_SUB_CAT_GAM_XBOX 1 +#define WSC_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360 2 +#define WSC_DEVICE_TYPE_SUB_CAT_GAM_PS 3 +#define WSC_DEVICE_TYPE_SUB_CAT_PHONE_WM 1 + +typedef struct _WSC_TLV_0B { + /*USHORT tag;*/ + USHORT len; +} WSC_TLV_0B, *PWSC_TLV_0B; + +#endif /* __WSC_TLV_H__ */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/ral_nmac.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/ral_nmac.c new file mode 100644 index 000000000..ea4f947c4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/ral_nmac.c @@ -0,0 +1,454 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +INT rlt_get_rxwi_phymode(RXWI_STRUC *rxwi) +{ + return rxwi->RXWI_N.phy_mode; +} + + +INT rlt_get_rxwi_rssi(RXWI_STRUC *rxwi, INT size, CHAR *rssi) +{ + if (size < (sizeof(rxwi->RXWI_N.rssi) / sizeof(UINT8))) + NdisMoveMemory(rssi, &rxwi->RXWI_N.rssi[0], size); + + return 0; +} + + +INT rlt_get_rxwi_snr(RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi, INT size, UCHAR *snr) +{ + if (IS_MT76x2(pAd)) { + NdisMoveMemory(snr, &rxwi->RXWI_N.bbp_rxinfo[2], size); + } + + // TODO: shiang-6590, fix me for SNR info of RXWI!! + if (size < 3) + NdisMoveMemory(snr, &rxwi->RXWI_N.bbp_rxinfo[0], size); + + return 0; +} + +#ifdef DBG +#ifdef RLT_MAC +VOID dumpRxFCEInfo(RTMP_ADAPTER *pAd, RXFCE_INFO *pRxFceInfo) +{ + hex_dump("RxFCEInfo Raw Data", (UCHAR *)pRxFceInfo, sizeof(RXFCE_INFO)); + + DBGPRINT(RT_DEBUG_OFF, ("RxFCEInfo Fields:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tinfo_type=%d\n", pRxFceInfo->info_type)); + DBGPRINT(RT_DEBUG_OFF, ("\ts_port=%d\n", pRxFceInfo->s_port)); + DBGPRINT(RT_DEBUG_OFF, ("\tqsel=%d\n", pRxFceInfo->qsel)); + DBGPRINT(RT_DEBUG_OFF, ("\tpcie_intr=%d\n", pRxFceInfo->pcie_intr)); + DBGPRINT(RT_DEBUG_OFF, ("\tmac_len=%d\n", pRxFceInfo->mac_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tl3l4_done=%d\n", pRxFceInfo->l3l4_done)); + DBGPRINT(RT_DEBUG_OFF, ("\tpkt_80211=%d\n", pRxFceInfo->pkt_80211)); + DBGPRINT(RT_DEBUG_OFF, ("\tip_err=%d\n", pRxFceInfo->ip_err)); + DBGPRINT(RT_DEBUG_OFF, ("\ttcp_err=%d\n", pRxFceInfo->tcp_err)); + DBGPRINT(RT_DEBUG_OFF, ("\tudp_err=%d\n", pRxFceInfo->udp_err)); + DBGPRINT(RT_DEBUG_OFF, ("\tpkt_len=%d\n", pRxFceInfo->pkt_len)); +} +#endif /* RLT_MAC */ + + +static UCHAR *txwi_txop_str[]={"HT_TXOP", "PIFS", "SIFS", "BACKOFF", "Invalid"}; +#define TXWI_TXOP_STR(_x) ((_x) <= 3 ? txwi_txop_str[(_x)]: txwi_txop_str[4]) + +VOID dump_rlt_txwi(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI) +{ + struct _TXWI_NMAC *txwi_nmac = (struct _TXWI_NMAC *)pTxWI; + + ASSERT((sizeof(struct _TXWI_NMAC) == pAd->chipCap.TXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tPHYMODE=%d(%s)\n", txwi_nmac->PHYMODE, get_phymode_str(txwi_nmac->PHYMODE))); + DBGPRINT(RT_DEBUG_OFF, ("\tITxBf=%d\n", txwi_nmac->iTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tETxBf=%d\n", txwi_nmac->eTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tSounding=%d\n", txwi_nmac->Sounding)); + DBGPRINT(RT_DEBUG_OFF, ("\tNDP Sounding BW=%d\n", txwi_nmac->NDPSndBW)); + DBGPRINT(RT_DEBUG_OFF, ("\tNDP Sounding Rate=%d\n", txwi_nmac->NDPSndRate)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", txwi_nmac->STBC)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI=%d\n", txwi_nmac->ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d(%sMHz)\n", txwi_nmac->BW, get_bw_str(txwi_nmac->BW))); + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", txwi_nmac->MCS)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxOP=%d(%s)\n", txwi_nmac->txop, TXWI_TXOP_STR(txwi_nmac->txop))); + DBGPRINT(RT_DEBUG_OFF, ("\tMpduDensity=%d\n", txwi_nmac->MpduDensity)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", txwi_nmac->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tTS=%d\n", txwi_nmac->TS)); + DBGPRINT(RT_DEBUG_OFF, ("\tCF-ACK=%d\n", txwi_nmac->CFACK)); + DBGPRINT(RT_DEBUG_OFF, ("\tMIMO-PS=%d\n", txwi_nmac->MIMOps)); + DBGPRINT(RT_DEBUG_OFF, ("\tNSEQ=%d\n", txwi_nmac->NSEQ)); + DBGPRINT(RT_DEBUG_OFF, ("\tACK=%d\n", txwi_nmac->ACK)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", txwi_nmac->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", txwi_nmac->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tBAWinSize=%d\n", txwi_nmac->BAWinSize)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", txwi_nmac->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tPID=%d\n", txwi_nmac->TxPktId)); +} + + +VOID dump_rlt_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI) +{ + struct _RXWI_NMAC *rxwi_n = (struct _RXWI_NMAC *)pRxWI; + + ASSERT((sizeof(struct _RXWI_NMAC) == pAd->chipCap.RXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", rxwi_n->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tPhyMode=%d(%s)\n", rxwi_n->phy_mode, get_phymode_str(rxwi_n->phy_mode))); + + if (rxwi_n->phy_mode == MODE_VHT) + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d(Nss:%d, MCS:%d)\n", + rxwi_n->mcs, (rxwi_n->mcs >> 4), (rxwi_n->mcs & 0xf))); + else + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", rxwi_n->mcs)); + + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d\n", rxwi_n->bw)); + DBGPRINT(RT_DEBUG_OFF, ("\tSGI=%d\n", rxwi_n->sgi)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", rxwi_n->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tTID=%d\n", rxwi_n->tid)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", rxwi_n->stbc)); + DBGPRINT(RT_DEBUG_OFF, ("\tkey_idx=%d\n", rxwi_n->key_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\tBSS_IDX=%d\n", rxwi_n->bss_idx)); + DBGPRINT(RT_DEBUG_OFF,("\tRSSI=%d:%d:%d!\n", (CHAR)(rxwi_n->rssi[0]), (CHAR)(rxwi_n->rssi[1]), (CHAR)(rxwi_n->rssi[2]))); + DBGPRINT(RT_DEBUG_OFF,("\tSNR=%d:%d:%d!\n", (CHAR)rxwi_n->bbp_rxinfo[0], (CHAR)rxwi_n->bbp_rxinfo[1], (CHAR)rxwi_n->bbp_rxinfo[2])); + DBGPRINT(RT_DEBUG_OFF,("\tFreqOffset=%d!\n", (CHAR)rxwi_n->bbp_rxinfo[4])); +} + + +static UCHAR *txinfo_type_str[]={"PKT", "", "CMD", "RSV", "Invalid"}; +static UCHAR *txinfo_d_port_str[]={"WLAN", "CPU_RX", "CPU_TX", "HOST", "VIRT_RX", "VIRT_TX", "DROP", "Invalid"}; +static UCHAR *txinfo_que_str[]={"MGMT", "HCCA", "EDCA_1", "EDCA_2", "Invalid"}; + +#define TXINFO_TYPE_STR(_x) ((_x)<=3 ? txinfo_type_str[_x] : txinfo_type_str[4]) +#define TXINFO_DPORT_STR(_x) ((_x) <= 6 ? txinfo_d_port_str[_x]: txinfo_d_port_str[7]) +#define TXINFO_QUE_STR(_x) ((_x) <= 3 ? txinfo_que_str[_x]: txinfo_que_str[4]) + +VOID dump_rlt_txinfo(RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo) +{ + struct _TXINFO_NMAC_PKT *pkt_txinfo = (struct _TXINFO_NMAC_PKT *)pTxInfo; + + DBGPRINT(RT_DEBUG_OFF, ("\tInfo_Type=%d(%s)\n", pkt_txinfo->info_type, TXINFO_TYPE_STR(pkt_txinfo->info_type))); + DBGPRINT(RT_DEBUG_OFF, ("\td_port=%d(%s)\n", pkt_txinfo->d_port, TXINFO_DPORT_STR(pkt_txinfo->d_port))); + DBGPRINT(RT_DEBUG_OFF, ("\tQSEL=%d(%s)\n", pkt_txinfo->QSEL, TXINFO_QUE_STR(pkt_txinfo->QSEL))); + DBGPRINT(RT_DEBUG_OFF, ("\tWIV=%d\n", pkt_txinfo->wiv)); + DBGPRINT(RT_DEBUG_OFF, ("\t802.11=%d\n", pkt_txinfo->pkt_80211)); + DBGPRINT(RT_DEBUG_OFF, ("\tcso=%d\n", pkt_txinfo->cso)); + DBGPRINT(RT_DEBUG_OFF, ("\ttso=%d\n", pkt_txinfo->tso)); + DBGPRINT(RT_DEBUG_OFF, ("\tpkt_len=0x%x\n", pkt_txinfo->pkt_len)); +} +#endif /* DBG */ + +#ifdef RTMP_MAC_PCI +VOID rlt_asic_init_txrx_ring(RTMP_ADAPTER *pAd) +{ + DELAY_INT_CFG_STRUC IntCfg; + WPDMA_GLO_CFG_STRUC GloCfg; + UINT32 phy_addr, offset; + INT i; + + /* Reset DMA Index */ + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0xFFFFFFFF); + + /* + Write Tx Ring base address registers + + The Tx Ring arrangement: + RingIdx SwRingIdx AsicPriority WMM QID + 0 TxSw0 L QID_AC_BE + 1 TxSw1 L QID_AC_BK + 2 TxSw2 L QID_AC_VI + 3 TxSw3 L QID_AC_VO + + 4 CTRL M - + 5 MGMT H - + + 6 - L QID_AC_BE + 7 - L QID_AC_BK + 8 - L QID_AC_VI + 9 - L QID_AC_VO + + Ring 0~3 for TxChannel 0 + Ring 6~9 for TxChannel 1 + */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->TxRing[i].Cell[0].AllocPa); + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + pAd->TxRing[i].hw_desc_base = TX_RING_BASE + offset; + pAd->TxRing[i].hw_cidx_addr = TX_RING_CIDX + offset; + pAd->TxRing[i].hw_didx_addr = TX_RING_DIDX + offset; + pAd->TxRing[i].hw_cnt_addr = TX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cidx_addr, pAd->TxRing[i].TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cnt_addr, TX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, pAd->TxRing[i].hw_desc_base, phy_addr, TX_RING_SIZE)); + } + + /* init MGMT ring Base/Size/Index pointer CSR */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + +#define TX_MGMT_CNT (pAd->MgmtRing.hw_desc_base + 0x04) +#define TX_MGMT_CIDX (pAd->MgmtRing.hw_desc_base + 0x08) +#define TX_MGMT_DIDX (pAd->MgmtRing.hw_desc_base + 0x0c) + + if (IS_RT8592(pAd)) + pAd->MgmtRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 5); + else + pAd->MgmtRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 9); + pAd->MgmtRing.hw_cidx_addr = TX_MGMT_CIDX; + pAd->MgmtRing.hw_didx_addr = TX_MGMT_DIDX; + pAd->MgmtRing.hw_cnt_addr = TX_MGMT_CNT; + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cnt_addr, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_MGMT[0x%x]: Base=0x%x, Cnt=%d!\n", + pAd->MgmtRing.hw_desc_base, phy_addr, MGMT_RING_SIZE)); + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->CtrlRing.Cell[0].AllocPa); + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; + +#define TX_CTRL_CNT (pAd->CtrlRing.hw_desc_base + 0x04) +#define TX_CTRL_CIDX (pAd->CtrlRing.hw_desc_base + 0x08) +#define TX_CTRL_DIDX (pAd->CtrlRing.hw_desc_base + 0x0c) + + if (IS_RT8592(pAd)) + pAd->CtrlRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 4); + else + pAd->CtrlRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 8); + pAd->CtrlRing.hw_cidx_addr = TX_CTRL_CIDX; + pAd->CtrlRing.hw_didx_addr = TX_CTRL_DIDX; + pAd->CtrlRing.hw_cnt_addr = TX_CTRL_CNT; + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cnt_addr, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_CTRL: Base=0x%x, Cnt=%d!\n", + phy_addr, TX_RING_SIZE)); +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Init RX Ring0 Base/Size/Index pointer CSR */ + for (i = 0; i < NUM_OF_RX_RING; i++) { + RTMP_RX_RING *rx_ring; + UINT16 RxRingSize = (i == 0) ? RX_RING_SIZE : RX1_RING_SIZE; + + rx_ring = &pAd->RxRing[i]; + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(rx_ring->Cell[0].AllocPa); + rx_ring->RxSwReadIdx = 0; + rx_ring->RxCpuIdx = RxRingSize - 1; + rx_ring->hw_desc_base = RX_RING_BASE + offset; + rx_ring->hw_cidx_addr = RX_RING_CIDX + offset; + rx_ring->hw_didx_addr = RX_RING_DIDX + offset; + rx_ring->hw_cnt_addr = RX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, rx_ring->hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, rx_ring->hw_cidx_addr, rx_ring->RxCpuIdx); + RTMP_IO_WRITE32(pAd, rx_ring->hw_cnt_addr, RxRingSize); + DBGPRINT(RT_DEBUG_TRACE, ("-->RX_RING%d[0x%x]: Base=0x%x, Cnt=%d\n", + i, rx_ring->hw_desc_base, phy_addr, RxRingSize)); + } + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + AsicWaitPDMAIdle(pAd, 100, 1000); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + IntCfg.word = 0; + RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); +} +#endif /* RTMP_MAC_PCI */ + + +static UINT32 asic_set_wlan_func(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 reg; + + RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, ®); + + if (enable == TRUE) + { + /* + Enable WLAN function and clock + WLAN_FUN_CTRL[1:0] = 0x3 + */ + reg |= WLAN_FUN_CTRL_WLAN_CLK_EN; + reg |= WLAN_FUN_CTRL_WLAN_EN; + } + else + { + /* + Diable WLAN function and clock + WLAN_FUN_CTRL[1:0] = 0x0 + */ + if (IS_PCIE_INF(pAd)) + reg &= ~WLAN_FUN_CTRL_PCIE_APP0_CLK_REQ; + + reg &= ~WLAN_FUN_CTRL_WLAN_EN; + reg &= ~WLAN_FUN_CTRL_WLAN_CLK_EN; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WlanFunCtrl= 0x%x\n", reg)); + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + RtmpusecDelay(20); + + return reg; +} + + +#define MAX_CHECK_COUNT 200 + +INT rlt_wlan_chip_onoff(RTMP_ADAPTER *pAd, BOOLEAN bOn, BOOLEAN bResetWLAN) +{ + UINT32 reg = 0; + + +#ifdef RTMP_PCI_SUPPORT + if (IS_PCI_INF(pAd)) + RTMP_SEM_LOCK(&pAd->WlanEnLock); +#endif /* RTMP_PCI_SUPPORT */ + + + RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, ®); + DBGPRINT(RT_DEBUG_OFF, ("==>%s(): OnOff:%d, Reset= %d, pAd->WlanFunCtrl:0x%x, Reg-WlanFunCtrl=0x%x\n", + __FUNCTION__, bOn, bResetWLAN, pAd->WlanFunCtrl.word, reg)); + + if (bResetWLAN == TRUE) + { +#ifdef MT76x2 + if (!IS_MT76x2(pAd)) +#endif /* MT76x2 */ + reg &= ~WLAN_FUN_CTRL_GPIO0_OUT_OE_N_MASK; + + reg &= ~WLAN_FUN_CTRL_FRC_WL_ANT_SEL; + + if (pAd->WlanFunCtrl.field.WLAN_EN) + { + /* + Restore all HW default value and reset RF. + */ +#ifdef MT76x2 + if (!IS_MT76x2(pAd)) +#endif /* MT76x2 */ + reg |= WLAN_FUN_CTRL_WLAN_RESET; + + reg |= WLAN_FUN_CTRL_WLAN_RESET_RF; + DBGPRINT(RT_DEBUG_TRACE, ("Reset(1) WlanFunCtrl.word = 0x%x\n", reg)); + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + RtmpusecDelay(20); + +#ifdef MT76x2 + if (!IS_MT76x2(pAd)) +#endif /* MT76x2 */ + reg &= ~WLAN_FUN_CTRL_WLAN_RESET; + + reg &= ~WLAN_FUN_CTRL_WLAN_RESET_RF; + + DBGPRINT(RT_DEBUG_TRACE, ("Reset(2) WlanFunCtrl.word = 0x%x\n", reg)); + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + RtmpusecDelay(20); + } else + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + } + + reg = asic_set_wlan_func(pAd, bOn); + + if (bOn) + { + RTMP_IO_FORCE_READ32(pAd, MAC_CSR0, &pAd->MACVersion); + DBGPRINT(RT_DEBUG_TRACE, ("MACVersion = 0x%08x\n", pAd->MACVersion)); + } + + if (bOn == TRUE +#ifdef MT76x2 + && (!IS_MT76x2(pAd)) +#endif /* MT76x2 */ + ) + { + UINT index = 0; + u32 value; + + do + { + do + { + RTMP_IO_FORCE_READ32(pAd, CMB_CTRL, &value); + + /* + Check status of PLL_LD & XTAL_RDY. + HW issue: Must check PLL_LD&XTAL_RDY when setting EEP to disable PLL power down + */ + if (((value & CMB_CTRL_PLL_LD) == CMB_CTRL_PLL_LD) && + ((value & CMB_CTRL_XTAL_RDY) == CMB_CTRL_XTAL_RDY)) + break; + + RtmpusecDelay(20); + } while (index++ < MAX_CHECK_COUNT); + + if (index >= MAX_CHECK_COUNT) + { + DBGPRINT(RT_DEBUG_ERROR, + ("Lenny:[boundary]Check PLL_LD ..CMB_CTRL 0x%08x, index=%d!\n", + value, index)); + /* + Disable WLAN then enable WLAN again + */ + reg = asic_set_wlan_func(pAd, 0); + reg = asic_set_wlan_func(pAd, 1); + + index = 0; + } + else + { + break; + } + } while (TRUE); + } + + pAd->WlanFunCtrl.word = reg; + RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, ®); + DBGPRINT(RT_DEBUG_TRACE, + ("<== %s():pAd->WlanFunCtrl.word = 0x%x, Reg->WlanFunCtrl=0x%x!\n", + __FUNCTION__, pAd->WlanFunCtrl.word, reg)); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd)) + RTMP_SEM_UNLOCK(&pAd->WlanEnLock); +#endif /* RTMP_MAC_PCI */ + + + return 0; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/ral_omac.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/ral_omac.c new file mode 100644 index 000000000..e49aba102 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/ral_omac.c @@ -0,0 +1,218 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +INT rtmp_get_rxwi_phymode(RXWI_STRUC *rxwi) +{ + return rxwi->RXWI_O.phy_mode; +} + +INT rtmp_get_rxwi_rssi(RXWI_STRUC *rxwi, INT size, CHAR *rssi) +{ + struct _RXWI_OMAC *rxwi_o = (struct _RXWI_OMAC *)rxwi; + + switch (size) { + case 3: + rssi[2] = rxwi_o->RSSI2; + case 2: + rssi[1] = rxwi_o->RSSI1; + case 1: + default: + rssi[0] = rxwi_o->RSSI0; + break; + } + + return 0; +} + + +INT rtmp_get_rxwi_snr(RXWI_STRUC *rxwi, INT size, UCHAR *snr) +{ + struct _RXWI_OMAC *rxwi_o = (struct _RXWI_OMAC *)rxwi; + + switch (size) { + case 3: + snr[2] = rxwi_o->SNR2; + case 2: + snr[1] = rxwi_o->SNR1; + case 1: + default: + snr[0] = rxwi_o->SNR0; + break; + } + + return 0; +} + + +#ifdef DBG +static UCHAR *txwi_txop_str[]={"HT_TXOP", "PIFS", "SIFS", "BACKOFF", "Invalid"}; +#define TXWI_TXOP_STR(_x) ((_x) <= 3 ? txwi_txop_str[(_x)]: txwi_txop_str[4]) +VOID dump_rtmp_txwi(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI) +{ + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + ASSERT((sizeof(struct _TXWI_OMAC) == pAd->chipCap.TXWISize)); + + if (pAd->chipCap.TXWISize != (sizeof(struct _TXWI_OMAC))) + DBGPRINT(RT_DEBUG_TRACE, ("%s():sizeof(struct _TXWI_OMAC)=%d, pAd->chipCap.TXWISize=%d\n", + __FUNCTION__, sizeof(struct _TXWI_OMAC), pAd->chipCap.TXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tPHYMODE=%d(%s)\n", txwi_o->PHYMODE, get_phymode_str(txwi_o->PHYMODE))); + DBGPRINT(RT_DEBUG_OFF, ("\tiTxBF=%d\n", txwi_o->iTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tSounding=%d\n", txwi_o->Sounding)); + DBGPRINT(RT_DEBUG_OFF, ("\teTxBF=%d\n", txwi_o->eTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", txwi_o->STBC)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI=%d\n", txwi_o->ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d(%sMHz)\n", txwi_o->BW, get_bw_str(txwi_o->BW))); + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", txwi_o->MCS)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxOP=%d(%s)\n", txwi_o->txop, TXWI_TXOP_STR(txwi_o->txop))); + DBGPRINT(RT_DEBUG_OFF, ("\tMpduDensity=%d\n", txwi_o->MpduDensity)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", txwi_o->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tTS=%d\n", txwi_o->TS)); + DBGPRINT(RT_DEBUG_OFF, ("\tCF-ACK=%d\n", txwi_o->CFACK)); + DBGPRINT(RT_DEBUG_OFF, ("\tMIMO-PS=%d\n", txwi_o->MIMOps)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", txwi_o->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tPID=%d\n", txwi_o->PacketId)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", txwi_o->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", txwi_o->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tBAWinSize=%d\n", txwi_o->BAWinSize)); + DBGPRINT(RT_DEBUG_OFF, ("\tNSEQ=%d\n", txwi_o->NSEQ)); + DBGPRINT(RT_DEBUG_OFF, ("\tACK=%d\n", txwi_o->ACK)); +} + + +VOID dump_rtmp_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI) +{ + struct _RXWI_OMAC *rxwi_o = (struct _RXWI_OMAC *)pRxWI; + + ASSERT((sizeof(struct _RXWI_OMAC) == pAd->chipCap.RXWISize)); + + if (pAd->chipCap.RXWISize != (sizeof(struct _RXWI_OMAC))) + DBGPRINT(RT_DEBUG_TRACE, ("%s():sizeof(struct _RXWI_OMAC)=%d, pAd->chipCap.RXWISize=%d\n", + __FUNCTION__, sizeof(struct _RXWI_OMAC), pAd->chipCap.RXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", rxwi_o->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", rxwi_o->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tPhyMode=%d(%s)\n", rxwi_o->phy_mode, get_phymode_str(rxwi_o->phy_mode))); + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", rxwi_o->mcs)); + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d\n", rxwi_o->bw)); + DBGPRINT(RT_DEBUG_OFF, ("\tSGI=%d\n", rxwi_o->sgi)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", rxwi_o->stbc)); + + + DBGPRINT(RT_DEBUG_OFF, ("\tSequence=%d\n", rxwi_o->SEQUENCE)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", rxwi_o->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tTID=%d\n", rxwi_o->tid)); + + DBGPRINT(RT_DEBUG_OFF, ("\tkey_idx=%d\n", rxwi_o->key_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\tBSS_IDX=%d\n", rxwi_o->bss_idx)); + + DBGPRINT(RT_DEBUG_OFF, ("\tRSSI=%d:%d:%d\n", rxwi_o->RSSI0, rxwi_o->RSSI1, rxwi_o->RSSI2)); + DBGPRINT(RT_DEBUG_OFF, ("\tSNR=%d:%d:%d\n", rxwi_o->SNR0, rxwi_o->SNR1, rxwi_o->SNR2)); + DBGPRINT(RT_DEBUG_OFF, ("\tFreqOffset=%d\n", rxwi_o->FOFFSET)); +} +#endif + + +VOID rtmp_asic_init_txrx_ring(RTMP_ADAPTER *pAd) +{ + DELAY_INT_CFG_STRUC IntCfg; + WPDMA_GLO_CFG_STRUC GloCfg; + UINT32 phy_addr, offset; + INT i; + + + /* + Write Tx Ring base address registers + + The Tx Ring arrangement: + RingIdx SwRingIdx AsicPriority WMM QID + 0 TxSw0 L QID_AC_BE + 1 TxSw1 L QID_AC_BK + 2 TxSw2 L QID_AC_VI + 3 TxSw3 L QID_AC_VO + + 4 HCCA M - + 5 MGMT H - + + Ring 0~3 for TxChannel 0 + Ring 6~9 for TxChannel 1 + */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->TxRing[i].Cell[0].AllocPa); + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + pAd->TxRing[i].hw_desc_base = TX_BASE_PTR0 + offset; + pAd->TxRing[i].hw_cidx_addr = TX_CTX_IDX0 + offset; + pAd->TxRing[i].hw_didx_addr = TX_DTX_IDX0 + offset; + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cidx_addr, pAd->TxRing[i].TxCpuIdx); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT0 + offset, TX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, pAd->TxRing[i].hw_desc_base, phy_addr, TX_RING_SIZE)); + } + + /* init MGMT ring index pointer */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + pAd->MgmtRing.hw_desc_base = TX_BASE_PTR5; + pAd->MgmtRing.hw_cidx_addr = TX_MGMTCTX_IDX; + pAd->MgmtRing.hw_didx_addr = TX_MGMTDTX_IDX; + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_MGMT[0x%x]: Base=0x%x, Cnt=%d!\n", + pAd->MgmtRing.hw_desc_base, phy_addr, MGMT_RING_SIZE)); + + /* Init RX Ring Base/Size/Index pointer CSR */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->RxRing[0].Cell[0].AllocPa); + pAd->RxRing[0].RxSwReadIdx = 0; + pAd->RxRing[0].RxCpuIdx = RX_RING_SIZE - 1; + pAd->RxRing[0].hw_desc_base = RX_BASE_PTR; + pAd->RxRing[0].hw_cidx_addr = RX_CRX_IDX; + pAd->RxRing[0].hw_didx_addr = RX_DRX_IDX; + RTMP_IO_WRITE32(pAd, pAd->RxRing[0].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->RxRing[0].hw_cidx_addr, pAd->RxRing[0].RxCpuIdx); + RTMP_IO_WRITE32(pAd, RX_MAX_CNT, RX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->RX_RING[0x%x]: Base=0x%x, Cnt=%d\n", + pAd->RxRing[0].hw_desc_base, phy_addr, RX_RING_SIZE)); + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + AsicWaitPDMAIdle(pAd, 100, 1000); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + IntCfg.word = 0; + RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/rtmp_mac.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/rtmp_mac.c new file mode 100644 index 000000000..54f5e85eb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mac/rtmp_mac.c @@ -0,0 +1,1591 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxWI Pointer to head of each MPDU to HW. + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + See also : BASmartHardTransmit() !!! + + ======================================================================== +*/ +VOID RTMPWriteTxWI( + IN RTMP_ADAPTER *pAd, + IN TXWI_STRUC *pOutTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, /* HW new a sequence.*/ + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN HTTRANSMIT_SETTING *pTransmit) +{ + PMAC_TABLE_ENTRY pMac = NULL; + TXWI_STRUC TxWI, *pTxWI; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT TxEAPId_Cal = 0; + UCHAR stbc, bw, mcs, sgi, phy_mode, mpdu_density = 0, mimops = 0, ldpc = 0; + UCHAR tx_stream_mode = 0; +#ifdef TXBF_SUPPORT + UCHAR eTxBf, iTxBf, sounding, ndp_rate; +#endif /* TXBF_SUPPORT */ + + if (WCID < MAX_LEN_OF_MAC_TABLE) + pMac = &pAd->MacTab.Content[WCID]; + + /* + Always use Long preamble before verifiation short preamble functionality works well. + Todo: remove the following line if short preamble functionality works + */ + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWISize); + pTxWI = &TxWI; + +#ifdef DOT11_N_SUPPORT + BASize = 0; + stbc = pTransmit->field.STBC; +#endif /* DOT11_N_SUPPORT */ + +#ifdef VHT_TXBF_SUPPORT + /* If CCK or OFDM, BW must be 20*/ + if (TxRate == SNDG_TYPE_NDP) + { + bw = pTransmit->field.BW; + } + else +#endif + { + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (bw) + bw = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + phy_mode = pTransmit->field.MODE; + sgi = pTransmit->field.ShortGI; + +#ifdef MT76x2 +#ifdef THERMAL_PROTECT_SUPPORT + if (IS_MT76x2(pAd) && pAd->force_one_tx_stream == TRUE) + { + tx_stream_mode = 0; /* SKIP 1SS2T when 1T Status on */ + } + else +#endif /* THERMAL_PROTECT_SUPPORT */ + if (MT_REV_GTE(pAd, MT76x2, REV_MT76x2E4)) + tx_stream_mode = 0x13; + else if (MT_REV_ET(pAd, MT76x2, REV_MT76x2E3)) + tx_stream_mode = (pTransmit->field.MODE <= MODE_OFDM) ? 0x93 : 0x0; +#endif /* MT76x2 */ + +#ifdef DOT11_N_SUPPORT + if (pMac) + { + if (pAd->CommonCfg.bMIMOPSEnable) + { + UCHAR MaxMcs_1ss; + + /* 10.2.4 SM power save, IEEE 802.11/2012, p.1010 + A STA in static SM power save mode maintains only a single receive chain active. + + An HT STA may use the SM Power Save frame to communicate its SM Power Save state. A non-AP HT + STA may also use SM Power Save bits in the HT Capabilities element of its Association Request to achieve + the same purpose. The latter allows the STA to use only a single receive chain immediately after association. + */ +#ifdef DOT11_VHT_AC + if (IS_VHT_STA(pMac)) + MaxMcs_1ss = 9; + else +#endif /* DOT11_VHT_AC */ + MaxMcs_1ss = 7; + + if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > MaxMcs_1ss)) + { + /* Dynamic MIMO Power Save Mode*/ + mimops = 1; + } + else if (pMac->MmpsMode == MMPS_STATIC) + { + /* Static MIMO Power Save Mode*/ + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > MaxMcs_1ss) + { + mcs = MaxMcs_1ss; + mimops = 0; + } + } + } + + mpdu_density = pMac->MpduDensity; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + AMPDU = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef TXBF_SUPPORT + eTxBf = pTransmit->field.eTxBF; + iTxBf = pTransmit->field.iTxBF; + + // Calculate the partial AID + TxEAPId_Cal = WCID + (UINT)((pAd->CommonCfg.Bssid[5] >> 4) ^ (pAd->CommonCfg.Bssid[5] & 0x0F))*32; + TxEAPId_Cal -= ((TxEAPId_Cal >> 9) << 9); + + if (pMac && pAd->chipCap.FlgHwTxBfCap) + { + if (pMac->TxSndgType == SNDG_TYPE_NDP || pMac->TxSndgType == SNDG_TYPE_SOUNDING) + { + stbc = FALSE; + eTxBf = FALSE; + iTxBf = FALSE; + sounding = FALSE; + ndp_rate = 1; + //phy_mode = 1; + //mcs = MCS_RATE_24; + + DBGPRINT(RT_DEBUG_TRACE, ("%s : NDP Sounding and NDPSndRate = %d\n", __FUNCTION__, ndp_rate)); + DBGPRINT(RT_DEBUG_TRACE, ("%s : BSSID[5] = %x, txwi_n->TxEAPId = %d\n", __FUNCTION__, pAd->CommonCfg.Bssid[5], TxEAPId_Cal)); + } + } + + if (iTxBf || eTxBf) stbc = 0; // Force STBC = 0 when TxBf is enabled + +#endif /* TXBF_SUPPORT */ + + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + txwi_n->FRAG = FRAG; + txwi_n->CFACK= CFACK; + txwi_n->TS = InsTimestamp; + txwi_n->AMPDU = AMPDU; + txwi_n->ACK = Ack; + txwi_n->txop = Txopmode; + txwi_n->NSEQ = NSeq; + txwi_n->BAWinSize = BASize; + txwi_n->ShortGI = sgi; + txwi_n->STBC = stbc; + txwi_n->LDPC = ldpc; +#ifdef CONFIG_AP_SUPPORT + if((phy_mode == MODE_CCK) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + ) + { + if (mcs == MCS_LONGP_RATE_2) + txwi_n->MCS = MCS_SHORTP_RATE_2; + else if (mcs == MCS_LONGP_RATE_5_5) + txwi_n->MCS = MCS_SHORTP_RATE_5_5; + else if (mcs == MCS_LONGP_RATE_11) + txwi_n->MCS = MCS_SHORTP_RATE_11; + } + else +#endif /* CONFIG_AP_SUPPORT */ + txwi_n->MCS = mcs; + + txwi_n->BW = bw; + txwi_n->PHYMODE= phy_mode; + txwi_n->MpduDensity = mpdu_density; + txwi_n->MIMOps = mimops; + txwi_n->wcid = WCID; + txwi_n->MPDUtotalByteCnt = Length; + txwi_n->TxPktId = mcs; // PID is not used now! + +#ifdef CONFIG_AP_SUPPORT + txwi_n->GroupID = TRUE; + txwi_n->TxEAPId = TxEAPId_Cal; +#endif /*CONFIG_AP_SUPPORT*/ + +#ifdef CONFIG_STA_SUPPORT + txwi_n->GroupID = FALSE; + txwi_n->TxEAPId = pAd->CommonCfg.Bssid[5]; +#endif /*CONFIG_STA_SUPPORT*/ + + txwi_n->TxStreamMode = tx_stream_mode; +#ifdef TXBF_SUPPORT + txwi_n->Sounding = sounding; + txwi_n->eTxBF = eTxBf; + txwi_n->iTxBF = iTxBf; + txwi_n->NDPSndRate = ndp_rate; + txwi_n->NDPSndBW = bw; + txwi_n->TXBF_PT_SCA = (eTxBf | iTxBf) ? TRUE : FALSE; +#endif /* TXBF_SUPPORT */ + + /* Calculate TxPwrAdj */ + txwi_n->TxPwrAdj = 0; + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (pMac) + { + txwi_n->TxPwrAdj += pAd->ApCfg.MBSSID[pMac->apidx].TxPwrAdj; + DBGPRINT(RT_DEBUG_TRACE, ("%s :%d pMac->apidx = %d, txwi_n->TxPwrAdj = %d\n" + , __FUNCTION__,__LINE__,pMac->apidx, txwi_n->TxPwrAdj)); + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + RTMP_CHIP_ASIC_SKU_TX_POWER_ADJUST(pAd,txwi_n); +#endif /* SINGLE_SKU_V2 */ + + /* increase low rate Tx Power by TXWI */ + RTMP_CHIP_ASIC_TX_POWER_BOOST(pAd,txwi_n); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + txwi_o->FRAG = FRAG; + txwi_o->CFACK = CFACK; + txwi_o->TS = InsTimestamp; + txwi_o->AMPDU = AMPDU; + txwi_o->ACK = Ack; + txwi_o->txop = Txopmode; + txwi_o->NSEQ = NSeq; + txwi_o->BAWinSize = BASize; + txwi_o->ShortGI = sgi; + txwi_o->STBC = stbc; +#ifdef CONFIG_AP_SUPPORT + if((phy_mode == MODE_CCK) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + ) + { + if (mcs == MCS_LONGP_RATE_2) + txwi_o->MCS = MCS_SHORTP_RATE_2; + else if (mcs == MCS_LONGP_RATE_5_5) + txwi_o->MCS = MCS_SHORTP_RATE_5_5; + else if (mcs == MCS_LONGP_RATE_11) + txwi_o->MCS = MCS_SHORTP_RATE_11; + } + else +#endif /* CONFIG_AP_SUPPORT */ + txwi_o->MCS = mcs; + txwi_o->BW = bw; + txwi_o->PHYMODE = phy_mode; + txwi_o->MpduDensity = mpdu_density; + txwi_o->MIMOps = mimops; + txwi_o->wcid = WCID; + txwi_o->MPDUtotalByteCnt = Length; + txwi_o->PacketId = mcs; // PID is not used now! + } +#endif /* RTMP_MAC */ + + NdisMoveMemory(pOutTxWI, &TxWI, TXWISize); +#ifdef DBG +//+++Add by shiang for debug +if (0){ + hex_dump("TxWI", (UCHAR *)pOutTxWI, TXWISize); + dump_txwi(pAd, pOutTxWI); +} +//---Add by shiang for debug +#endif +} + + +VOID RTMPWriteTxWI_Data(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI, TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit; + MAC_TABLE_ENTRY *pMacEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UCHAR wcid, pkt_id; + UCHAR sgi, mcs, bw, stbc, phy_mode, ldpc; +#ifdef DOT11_N_SUPPORT + UCHAR basize, ampdu, mimops = 0, mpdu_density = 0; +#endif /* DOT11_N_SUPPORT */ +#ifdef TXBF_SUPPORT + UCHAR iTxBf, eTxBf, sounding, ndp_rate, ndp_bw; +#endif /* TXBF_SUPPORT */ +#ifdef MCS_LUT_SUPPORT + BOOLEAN lut_enable = 0; + UCHAR mbc_wcid; +#endif /* MCS_LUT_SUPPORT */ + UCHAR tx_stream_mode = 0; + + + ASSERT(pTxWI); + + pTransmit = pTxBlk->pTransmit; + pMacEntry = pTxBlk->pMacEntry; + + /* + Always use Long preamble before verifiation short preamble functionality works well. + Todo: remove the following line if short preamble functionality works + */ + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(pTxWI, TXWISize); + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (pMacEntry && IS_ENTRY_DLS(pMacEntry) && + (pAd->StaCfg.BssType == BSS_INFRA)) + wcid = BSSID_WCID; + else +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + wcid = pTxBlk->Wcid; + + sgi = pTransmit->field.ShortGI; + stbc = pTransmit->field.STBC; + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + phy_mode = pTransmit->field.MODE; + /* If CCK or OFDM, BW must be 20 */ + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + +#ifdef MT76x2 +#ifdef THERMAL_PROTECT_SUPPORT + if (IS_MT76x2(pAd) && pAd->force_one_tx_stream == TRUE) + { + tx_stream_mode = 0; + } + else +#endif /* THERMAL_PROTECT_SUPPORT */ + if (MT_REV_GTE(pAd, MT76x2, REV_MT76x2E4)) + tx_stream_mode = 0x13; + else if (MT_REV_ET(pAd, MT76x2, REV_MT76x2E3)) + tx_stream_mode = (pTransmit->field.MODE <= MODE_OFDM) ? 0x93 : 0x0; +#endif /* MT76x2 */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (bw) + bw = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ + + ampdu = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); + basize = pAd->CommonCfg.TxBASize; + if(ampdu && pMacEntry) + { + /* + * Under HT20, 2x2 chipset, OPEN, and with some atero chipsets + * reduce BASize to 7 to add one bulk A-MPDU during one TXOP + * to improve throughput + */ + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pAd->Antenna.field.TxPath == 2) + && (pMacEntry->bIAmBadAtheros) && (pMacEntry->WepStatus == Ndis802_11EncryptionDisabled)) + { + basize = 7; + } + else + { + UCHAR RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + basize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; + } + } + +#ifdef TXBF_SUPPORT + if(pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + ampdu = FALSE; + + sounding = ndp_bw = ndp_rate = iTxBf = eTxBf = 0; + if (pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING) + { + sounding = 1; + iTxBf = FALSE; + eTxBf = FALSE; + stbc = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in %s(): sending normal sounding, eTxBF=%d\n", + __FUNCTION__, pTransmit->field.eTxBF)); + iTxBf = 0; + } + else if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP) + { + ndp_bw = pTransmit->field.BW; + iTxBf = FALSE; + eTxBf = FALSE; + stbc = FALSE; + if (pTxBlk->TxNDPSndgMcs >= 16) + ndp_rate = 2; + else if (pTxBlk->TxNDPSndgMcs >= 8) + ndp_rate = 1; + else + ndp_rate = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in %s(): NDP sounding, eTxBF=%d, ndp_rate = %d\n", + __FUNCTION__, eTxBf, ndp_rate)); + } + else + { +#ifdef MFB_SUPPORT + if (pMacEntry && (pMacEntry->mrqCnt >0) && (pMacEntry->toTxMrq == TRUE)) + eTxBf = ~(pTransmit->field.eTxBF); + else +#endif /* MFB_SUPPORT */ + eTxBf = pTransmit->field.eTxBF; + iTxBf = pTransmit->field.iTxBF; + } + + if (iTxBf || eTxBf) stbc = FALSE; // Force STBC = FALSE when TxBf is enabled + +#endif /* TXBF_SUPPORT */ + +#endif /* DOT11_N_SUPPORT */ + + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + { + mcs = 0; + ampdu = FALSE; + } +#endif /* TXBF_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (pMacEntry) + { + UCHAR MaxMcs_1ss; + + /* 10.2.4 SM power save, IEEE 802.11/2012, p.1010 + A STA in static SM power save mode maintains only a single receive chain active. + + An HT STA may use the SM Power Save frame to communicate its SM Power Save state. A non-AP HT + STA may also use SM Power Save bits in the HT Capabilities element of its Association Request to achieve + the same purpose. The latter allows the STA to use only a single receive chain immediately after association. + */ +#ifdef DOT11_VHT_AC + if (IS_VHT_STA(pMacEntry)) + MaxMcs_1ss = 9; + else +#endif /* DOT11_VHT_AC */ + MaxMcs_1ss = 7; + + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (mcs > MaxMcs_1ss)) + mimops = 1; + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + if ((pTransmit->field.MODE == MODE_HTMIX || pTransmit->field.MODE == MODE_HTGREENFIELD) && + (mcs > MaxMcs_1ss)) + { + mcs = MaxMcs_1ss; + mimops = 0; + } + } + + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros)) + mpdu_density = 7; + else + mpdu_density = pMacEntry->MpduDensity; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxDataCnt++; +#ifdef DBG_TX_MCS + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_HT[mcs]++; +#endif /* DBG_TX_MCS */ + } +#endif /* DBG_DIAGNOSE */ + + /* for rate adapation*/ + pkt_id = mcs; + +#ifdef INF_AMAZON_SE + /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ + if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket)) + { + if(phy_mode == MODE_CCK) + pkt_id = 6; + } +#endif /* INF_AMAZON_SE */ + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + ampdu = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x6) + { + phy_mode = pAd->fpga_ctl.tx_data_phy; + mcs = pAd->fpga_ctl.tx_data_mcs; + ldpc = pAd->fpga_ctl.tx_data_ldpc; + bw = pAd->fpga_ctl.tx_data_bw; + sgi = pAd->fpga_ctl.tx_data_gi; + if (pAd->fpga_ctl.data_basize) + basize = pAd->fpga_ctl.data_basize; + } +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MCS_LUT_SUPPORT + if ((RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT)) && + (wcid < 128) && + (pMacEntry && pMacEntry->bAutoTxRateSwitch == TRUE)) + { + HTTRANSMIT_SETTING rate_ctrl; + + rate_ctrl.field.MODE = phy_mode; +#ifdef TXBF_SUPPORT + rate_ctrl.field.iTxBF = iTxBf; + rate_ctrl.field.eTxBF = eTxBf; +#endif /* TXBF_SUPPORT */ + rate_ctrl.field.STBC = stbc; + rate_ctrl.field.ShortGI = sgi; + rate_ctrl.field.BW = bw; + rate_ctrl.field.ldpc = ldpc; + rate_ctrl.field.MCS = mcs; + if (rate_ctrl.word == pTransmit->word) + lut_enable = TRUE; + } +#ifdef PEER_DELBA_TX_ADAPT + GET_GroupKey_WCID(pAd, mbc_wcid, pTxBlk->apidx); + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket) || (wcid == mbc_wcid) || + (pMacEntry && (pMacEntry->MmpsMode == MMPS_STATIC))) + lut_enable = FALSE; + else + lut_enable = TRUE; +#endif /* PEER_DELBA_TX_ADAPT */ +#endif /* MCS_LUT_SUPPORT */ + +#ifdef TXBF_SUPPORT +#ifdef MCS_LUT_SUPPORT + if (pMacEntry && pAd->chipCap.FlgHwTxBfCap) + { + if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP || pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING) + lut_enable = FALSE; + } +#endif /* MCS_LUT_SUPPORT */ +#endif /* TXBF_SUPPORT */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + + txwi_n->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + txwi_n->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); + if (RTMP_GET_PACKET_TDLS_WAIT_ACK(pTxBlk->pPacket)) + { + txwi_n->TxPktId |= 0x80; + DBGPRINT(RT_DEBUG_INFO,("PktID |= 0x80 : [%x]\n",txwi_n->TxPktId)); + } + else + { + txwi_n->TxPktId &= 0x7f; + DBGPRINT(RT_DEBUG_INFO,("PktID : [%x]\n",txwi_n->TxPktId)); + } +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_n->ACK = 0; +#endif /* WFA_VHT_PF */ + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + txwi_n->txop = IFS_BACKOFF; // Reserve larger TXOP to prevent sounding packet from collision + else +#endif /* WFA_VHT_PF */ + txwi_n->txop = pTxBlk->FrameGap; + txwi_n->wcid = wcid; + txwi_n->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_n->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + txwi_n->ShortGI = sgi; + txwi_n->STBC = stbc; + txwi_n->LDPC = ldpc; + txwi_n->TxStreamMode = tx_stream_mode; + +#ifdef CONFIG_AP_SUPPORT + if((phy_mode == MODE_CCK) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + ) + { + if (mcs == MCS_LONGP_RATE_2) + txwi_n->MCS = MCS_SHORTP_RATE_2; + else if (mcs == MCS_LONGP_RATE_5_5) + txwi_n->MCS = MCS_SHORTP_RATE_5_5; + else if (mcs == MCS_LONGP_RATE_11) + txwi_n->MCS = MCS_SHORTP_RATE_11; + } + else +#endif /* CONFIG_AP_SUPPORT */ + txwi_n->MCS = mcs; + txwi_n->PHYMODE = phy_mode; + txwi_n->BW = bw; + txwi_n->TxPktId = pkt_id; + +#ifdef DOT11_N_SUPPORT + txwi_n->AMPDU = ampdu; + txwi_n->BAWinSize = basize; + txwi_n->MIMOps = mimops; + txwi_n->MpduDensity = mpdu_density; +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + txwi_n->Sounding = sounding; + txwi_n->iTxBF = iTxBf; + txwi_n->eTxBF = eTxBf; + txwi_n->NDPSndRate = ndp_rate; + txwi_n->NDPSndBW = ndp_bw; + txwi_n->TXBF_PT_SCA = (eTxBf | iTxBf) ? TRUE : FALSE; +#endif /* TXBF_SUPPORT */ + +#ifdef MCS_LUT_SUPPORT + txwi_n->lut_en = lut_enable; +#endif /* MCS_LUT_SUPPORT */ + + + /* Calculate TxPwrAdj */ + txwi_n->TxPwrAdj = 0; + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (pMacEntry) + { + txwi_n->TxPwrAdj += pAd->ApCfg.MBSSID[pMacEntry->apidx].TxPwrAdj; + DBGPRINT(RT_DEBUG_TRACE, ("%s :%d pMacEntry->apidx = %d, txwi_n->TxPwrAdj = %d\n" + , __FUNCTION__,__LINE__,pMacEntry->apidx, txwi_n->TxPwrAdj)); + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + RTMP_CHIP_ASIC_SKU_TX_POWER_ADJUST(pAd,txwi_n); +#endif /* SINGLE_SKU_V2 */ + + /* increase low rate Tx Power by TXWI */ + RTMP_CHIP_ASIC_TX_POWER_BOOST(pAd,txwi_n); + + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + txwi_o->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + txwi_o->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_o->ACK = 0; +#endif /* WFA_VHT_PF */ + txwi_o->txop = pTxBlk->FrameGap; + txwi_o->wcid = wcid; + txwi_o->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_o->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + txwi_o->ShortGI = sgi; + txwi_o->STBC = stbc; +#ifdef CONFIG_AP_SUPPORT + if((phy_mode == MODE_CCK) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + ) + { + if (mcs == MCS_LONGP_RATE_2) + txwi_o->MCS = MCS_SHORTP_RATE_2; + else if (mcs == MCS_LONGP_RATE_5_5) + txwi_o->MCS = MCS_SHORTP_RATE_5_5; + else if (mcs == MCS_LONGP_RATE_11) + txwi_o->MCS = MCS_SHORTP_RATE_11; + } + else +#endif /* CONFIG_AP_SUPPORT */ + txwi_o->MCS = mcs; + txwi_o->PHYMODE = phy_mode; + txwi_o->BW = bw; + txwi_o->PacketId = pkt_id; + +#ifdef DOT11_N_SUPPORT + txwi_o->AMPDU = ampdu; + txwi_o->BAWinSize = basize; + txwi_o->MIMOps = mimops; + txwi_o->MpduDensity= mpdu_density; +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + txwi_o->Sounding = sounding; + txwi_o->iTxBF = iTxBf; + txwi_o->eTxBF = eTxBf; + txwi_o->NDPSndRate = ndp_rate; + txwi_o->NDPSndBW = ndp_bw; +#endif /* TXBF_SUPPORT */ +#ifdef MCS_LUT_SUPPORT + txwi_o->TXLUT = lut_enable; +#endif /* MCS_LUT_SUPPORT */ + } +#endif /* RTMP_MAC */ +} + + +VOID RTMPWriteTxWI_Cache(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI, TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit = pTxBlk->pTransmit; + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + UCHAR pkt_id; + UCHAR bw, mcs, stbc, phy_mode, sgi, ldpc; +#ifdef DOT11_N_SUPPORT + UCHAR ampdu, basize = 0, mimops, mpdu_density = 0; +#endif /* DOT11_N_SUPPORT */ +#ifdef TXBF_SUPPORT + UCHAR sounding, iTxBf, eTxBf, ndp_rate, ndp_bw; +#endif /* TXBF_SUPPORT */ +#ifdef MCS_LUT_SUPPORT + BOOLEAN lut_enable; +#endif /* MCS_LUT_SUPPORT */ + UCHAR tx_stream_mode = 0; + + + /* If CCK or OFDM, BW must be 20*/ + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + sgi = pTransmit->field.ShortGI; + stbc = pTransmit->field.STBC; + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + phy_mode = pTransmit->field.MODE; + pMacEntry->LastTxRate = pTransmit->word; + +#ifdef MT76x2 +#ifdef THERMAL_PROTECT_SUPPORT + if (IS_MT76x2(pAd) && pAd->force_one_tx_stream == TRUE) + { + tx_stream_mode = 0; + } + else +#endif /* THERMAL_PROTECT_SUPPORT */ + if (MT_REV_GTE(pAd, MT76x2, REV_MT76x2E4)) + tx_stream_mode = 0x13; + else if (MT_REV_ET(pAd, MT76x2, REV_MT76x2E3)) + tx_stream_mode = (pTransmit->field.MODE <= MODE_OFDM) ? 0x93 : 0x0; +#endif /* MT76x2 */ + +#ifdef DOT11_N_SUPPORT + ampdu = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); +#ifdef TXBF_SUPPORT + if(pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + ampdu = FALSE; +#endif /* TXBF_SUPPORT */ + +#ifdef DOT11N_DRAFT3 + if (bw) + bw = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ + + mimops = 0; + if (pAd->CommonCfg.bMIMOPSEnable) + { + UCHAR MaxMcs_1ss; + + /* 10.2.4 SM power save, IEEE 802.11/2012, p.1010 + A STA in static SM power save mode maintains only a single receive chain active. + + An HT STA may use the SM Power Save frame to communicate its SM Power Save state. A non-AP HT + STA may also use SM Power Save bits in the HT Capabilities element of its Association Request to achieve + the same purpose. The latter allows the STA to use only a single receive chain immediately after association. + */ +#ifdef DOT11_VHT_AC + if (IS_VHT_STA(pMacEntry)) + MaxMcs_1ss = 9; + else +#endif /* DOT11_VHT_AC */ + MaxMcs_1ss = 7; + + /* MIMO Power Save Mode*/ + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > MaxMcs_1ss)) + mimops = 1; + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > MaxMcs_1ss)) + { + mcs = MaxMcs_1ss; + mimops = 0; + } + } + } + + if(ampdu && pMacEntry) + { + /* + * Under HT20, 2x2 chipset, OPEN, and with some atero chipsets + * reduce BASize to 7 to add one bulk A-MPDU during one TXOP + * to improve throughput + */ + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros)) + { + mpdu_density = 7; + if ((pAd->Antenna.field.TxPath == 2) && + (pMacEntry->WepStatus == Ndis802_11EncryptionDisabled)) + { + basize = 7; + } + } + + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxDataCnt++; +#ifdef DBG_TX_MCS + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_HT[mcs]++; +#endif /* DBG_TX_MCS */ + } +#endif /* DBG_DIAGNOSE */ + +#ifdef TXBF_SUPPORT + sounding = eTxBf = iTxBf = ndp_bw = ndp_rate = 0; + if (pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING) + { + sounding = 1; + stbc = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in %s(): sending normal sounding, eTxBF=%d\n", + __FUNCTION__, pTransmit->field.eTxBF)); + } + else if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP) + { + stbc = FALSE; + if (pTxBlk->TxNDPSndgMcs>=16) + ndp_rate = 2; + else if (pTxBlk->TxNDPSndgMcs>=8) + ndp_rate = 1; + else + ndp_rate = 0; + ndp_bw = pTransmit->field.BW; + + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in %s(): NDP sounding, eTxBF=%d, ndp_rate = %d\n", + __FUNCTION__, eTxBf, ndp_rate)); + } + else + { +#ifdef MFB_SUPPORT + if (pMacEntry && pMacEntry->mrqCnt >0 && pMacEntry->toTxMrq == 1) + { + eTxBf = ~(pTransmit->field.eTxBF); + DBGPRINT_RAW(RT_DEBUG_TRACE,("ETxBF in AP_AMPDU_Frame_Tx(): invert eTxBF\n")); + } + else +#endif /* MFB_SUPPORT */ + eTxBf = pTransmit->field.eTxBF; + + iTxBf = pTransmit->field.iTxBF; + } + + if (eTxBf || iTxBf) stbc = FALSE; //Force STBC = FALSE when TxBf is enabled + + if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + { + mcs = 0; + ampdu = FALSE; + } +#endif /* TXBF_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + ampdu = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x6) + { + HTTRANSMIT_SETTING tmpTransmit; + + phy_mode = pAd->fpga_ctl.tx_data_phy; + mcs = pAd->fpga_ctl.tx_data_mcs; + ldpc = pAd->fpga_ctl.tx_data_ldpc; + bw = pAd->fpga_ctl.tx_data_bw; + sgi = pAd->fpga_ctl.tx_data_gi; + stbc = pAd->fpga_ctl.tx_data_stbc; + if (pAd->fpga_ctl.data_basize) + basize = pAd->fpga_ctl.data_basize; + + tmpTransmit.field.BW = bw; + tmpTransmit.field.ShortGI = sgi; + tmpTransmit.field.STBC = stbc; + tmpTransmit.field.ldpc = ldpc; + tmpTransmit.field.MCS = mcs; + tmpTransmit.field.MODE = phy_mode; + + pMacEntry->LastTxRate = tmpTransmit.word; + } +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MCS_LUT_SUPPORT + lut_enable = FALSE; + if (RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) && + (pTxBlk->Wcid < 128) && + (pMacEntry && pMacEntry->bAutoTxRateSwitch == TRUE)) + { + HTTRANSMIT_SETTING rate_ctrl; + + rate_ctrl.field.MODE = phy_mode; +#ifdef TXBF_SUPPORT + rate_ctrl.field.iTxBF = iTxBf; + rate_ctrl.field.eTxBF = eTxBf; +#endif /* TXBF_SUPPORT */ + rate_ctrl.field.STBC = stbc; + rate_ctrl.field.ShortGI = sgi; + rate_ctrl.field.BW = bw; + rate_ctrl.field.ldpc = ldpc; + rate_ctrl.field.MCS = mcs; + if (rate_ctrl.word == pTransmit->word) + lut_enable = TRUE; + } +#endif /* MCS_LUT_SUPPORT */ + + /* set PID for TxRateSwitching*/ + pkt_id = mcs; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + txwi_n->txop = IFS_BACKOFF; // Reserve larger TXOP to prevent sounding packet from collision + else +#endif + txwi_n->txop = IFS_HTTXOP; + txwi_n->BW = bw; + txwi_n->ShortGI = sgi; + txwi_n->STBC = stbc; + txwi_n->LDPC = ldpc; + txwi_n->TxStreamMode = tx_stream_mode; + txwi_n->MCS = mcs; + txwi_n->PHYMODE = phy_mode; + txwi_n->TxPktId = pkt_id; + txwi_n->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_n->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_n->ACK = 0; +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_N_SUPPORT + txwi_n->AMPDU = ampdu; + if (basize) + txwi_n->BAWinSize = basize; + txwi_n->MIMOps = mimops; + if (mpdu_density) + txwi_n->MpduDensity = mpdu_density; +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + txwi_n->Sounding = sounding; + txwi_n->eTxBF = eTxBf; + txwi_n->iTxBF = iTxBf; + txwi_n->NDPSndRate = ndp_rate; + txwi_n->NDPSndBW = ndp_bw; + txwi_n->TXBF_PT_SCA = (eTxBf | iTxBf) ? TRUE : FALSE; +#endif /* TXBF_SUPPORT */ + + /* Calculate TxPwrAdj */ + txwi_n->TxPwrAdj = 0; + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (pMacEntry) + { + txwi_n->TxPwrAdj = pAd->ApCfg.MBSSID[pMacEntry->apidx].TxPwrAdj; + DBGPRINT(RT_DEBUG_INFO, ("%s :%d pMacEntry->apidx = %d, txwi_n->TxPwrAdj = %d\n" + , __FUNCTION__,__LINE__,pMacEntry->apidx, txwi_n->TxPwrAdj)); + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + RTMP_CHIP_ASIC_SKU_TX_POWER_ADJUST(pAd,txwi_n); +#endif /* SINGLE_SKU_V2 */ + + /* increase low rate Tx Power by TXWI */ + RTMP_CHIP_ASIC_TX_POWER_BOOST(pAd,txwi_n); + +#ifdef MCS_LUT_SUPPORT + txwi_n->lut_en = lut_enable; +#endif /* MCS_LUT_SUPPORT */ + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + txwi_o->txop = IFS_HTTXOP; + txwi_o->BW = bw; + txwi_o->ShortGI = sgi; + txwi_o->STBC = stbc; + txwi_o->MCS = mcs; + txwi_o->PHYMODE = phy_mode; + txwi_o->PacketId = pkt_id; + txwi_o->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_o->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_o->ACK = 0; +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_N_SUPPORT + txwi_o->AMPDU = ampdu; + if (basize) + txwi_o->BAWinSize = basize; + txwi_o->MIMOps = mimops; + if (mpdu_density) + txwi_o->MpduDensity = mpdu_density; +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + txwi_o->Sounding = sounding; + txwi_o->eTxBF = eTxBf; + txwi_o->iTxBF = iTxBf; + txwi_o->NDPSndRate = ndp_rate; + txwi_o->NDPSndBW = ndp_bw; +#endif /* TXBF_SUPPORT */ +#ifdef MCS_LUT_SUPPORT + txwi_o->TXLUT = lut_enable; +#endif /* MCS_LUT_SUPPORT */ + } +#endif /* RTMP_MAC */ +} + + +INT get_pkt_rssi_by_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi, INT size, CHAR *rssi) +{ + INT status = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + status = rlt_get_rxwi_rssi(rxwi, size, rssi); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + status = rtmp_get_rxwi_rssi(rxwi, size, rssi); +#endif /* RTMP_MAC */ + + return status; +} + + +INT get_pkt_snr_by_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi, INT size, UCHAR *snr) +{ + INT status = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + status = rlt_get_rxwi_snr(pAd, rxwi, size, snr); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + status = rtmp_get_rxwi_snr(rxwi, size, snr); +#endif /* RTMP_MAC */ + + return status; +} + + +INT get_pkt_phymode_by_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *rxwi) +{ + INT status = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + status = rlt_get_rxwi_phymode(rxwi); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + status = rtmp_get_rxwi_phymode(rxwi); +#endif /* RTMP_MAC */ + + return status; + +} + +#ifdef MCS_LUT_SUPPORT +INT set_lut_phy_rate( + RTMP_ADAPTER *pAd, UINT8 wcid, + UINT8 mcs, UINT8 bw, UINT8 gi, + UINT8 stbc, UINT8 mode) +{ + UINT32 mac_reg = 0; + USHORT reg_id = 0x1C00 + (wcid << 3); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + mac_reg = (mcs | (bw << 7) | (gi << 9) | (stbc << 10) | (mode << 13)); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + mac_reg = (mcs | (bw << 7) | (gi << 8) | (stbc << 9) | (mode << 14)); + } +#endif /* RTMP_MAC */ + + if (mac_reg) + RTMP_IO_WRITE32(pAd, reg_id, mac_reg); + + return TRUE; +} +#endif /* MCS_LUT_SUPPORT */ + +INT rtmp_mac_set_band(RTMP_ADAPTER *pAd, int band) +{ + UINT32 val, band_cfg; + + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &band_cfg); + val = band_cfg & (~0x6); + switch (band) + { + case BAND_5G: + val |= 0x02; + break; + case BAND_24G: + default: + val |= 0x4; + break; + } + + if (val != band_cfg) + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, val); + + return TRUE; +} + + +INT rtmp_mac_set_ctrlch(RTMP_ADAPTER *pAd, UINT8 extch) +{ + UINT32 val, band_cfg; + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &band_cfg); + val = band_cfg & (~0x1); + switch (extch) + { + case EXTCHA_ABOVE: + val &= (~0x1); + break; + case EXTCHA_BELOW: + val |= (0x1); + break; + case EXTCHA_NONE: + val &= (~0x1); + break; + } + + if (val != band_cfg) + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, val); + + return TRUE; +} + + +INT rtmp_mac_set_mmps(RTMP_ADAPTER *pAd, INT ReduceCorePower) +{ + UINT32 mac_val, org_val; + + RTMP_IO_READ32(pAd, 0x1210, &org_val); + mac_val = org_val; + if (ReduceCorePower) + mac_val |= 0x09; + else + mac_val &= ~0x09; + + if (mac_val != org_val) + RTMP_IO_WRITE32(pAd, 0x1210, mac_val); + + return TRUE; +} + + +#define BCN_TBTT_OFFSET 64 /*defer 64 us*/ +VOID ReSyncBeaconTime(RTMP_ADAPTER *pAd) +{ + UINT32 Offset; + BCN_TIME_CFG_STRUC csr; + + Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); + pAd->TbttTickCount++; + + /* + The updated BeaconInterval Value will affect Beacon Interval after two TBTT + beacasue the original BeaconInterval had been loaded into next TBTT_TIMER + */ + if (Offset == (BCN_TBTT_OFFSET-2)) + { + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + + /* ASIC register in units of 1/16 TU = 64us*/ + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + else if (Offset == (BCN_TBTT_OFFSET-1)) + { + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } +} + + +VOID rtmp_mac_bcn_buf_init(IN RTMP_ADAPTER *pAd) +{ + int idx, tb_size; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) + pAd->BeaconOffset[idx] = pChipCap->BcnBase[idx]; + + DBGPRINT(RT_DEBUG_TRACE, ("< Beacon Information: >\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tFlgIsSupSpecBcnBuf = %s\n", pChipCap->FlgIsSupSpecBcnBuf ? "TRUE" : "FALSE")); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwNum = %d\n", pChipCap->BcnMaxHwNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxNum = %d\n", pChipCap->BcnMaxNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwSize = 0x%x\n", pChipCap->BcnMaxHwSize)); + DBGPRINT(RT_DEBUG_TRACE, ("\tWcidHwRsvNum = %d\n", pChipCap->WcidHwRsvNum)); + for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) { + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBcnBase[%d] = 0x%x, pAd->BeaconOffset[%d]=0x%x\n", + idx, pChipCap->BcnBase[idx], idx, pAd->BeaconOffset[idx])); + } + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) + { + RTMP_REG_PAIR BcnSpecMACRegTable[] = { + /* + That means all beacon's size are 512 bytes + and their starting address are "0x4000, 0x4200, 0x4400, 0x4600, ....." + in the second(higher) 8KB shared memory . + + The formula is : 0x4000 + BCNx_OFFSET*64 + ex : the address of BSS0 = 0x4000 + 0x00 * 64 = 0x4000 + the address of BSS1 = 0x4000 + 0x08 * 64 = 0x4200 + */ + {BCN_OFFSET0, 0x18100800}, + {BCN_OFFSET1, 0x38302820}, + {BCN_OFFSET2, 0x58504840}, + {BCN_OFFSET3, 0x78706860}, + }; + + tb_size = (sizeof(BcnSpecMACRegTable) / sizeof(RTMP_REG_PAIR)); + /* re-set beacon offset */ + for(idx = 0; idx < tb_size; idx++) + { + RTMP_IO_WRITE32(pAd, (USHORT)BcnSpecMACRegTable[idx].Register, + BcnSpecMACRegTable[idx].Value); + } + } + else +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + { + RTMP_REG_PAIR bcn_legacy_reg_tb[] = { +#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) + {BCN_OFFSET0, 0xf8f0e8e0}, + {BCN_OFFSET1, 0x6f77d0c8}, +#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) + {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ + {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ +#endif /* HW_BEACON_OFFSET */ + }; + + tb_size = (sizeof(bcn_legacy_reg_tb) / sizeof(RTMP_REG_PAIR)); + for (idx = 0; idx < tb_size; idx++) + { + RTMP_IO_WRITE32(pAd, (USHORT)bcn_legacy_reg_tb[idx].Register, + bcn_legacy_reg_tb[idx].Value); + } + } + } +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_REG_PAIR bcn_mac_reg_tb[] = { + {RLT_BCN_OFFSET0, 0x18100800}, + {RLT_BCN_OFFSET1, 0x38302820}, + {RLT_BCN_OFFSET2, 0x58504840}, + {RLT_BCN_OFFSET3, 0x78706860}, + }; + + tb_size = (sizeof(bcn_mac_reg_tb) / sizeof(RTMP_REG_PAIR)); + for (idx = 0; idx < tb_size; idx ++) + { + RTMP_IO_WRITE32(pAd, (USHORT)bcn_mac_reg_tb[idx].Register, + bcn_mac_reg_tb[idx].Value); + } + } +#endif /* RLT_MAC */ +} + + +INT rtmp_mac_pbf_init(RTMP_ADAPTER *pAd) +{ + INT idx, tb_size = 0; + RTMP_REG_PAIR *pbf_regs = NULL; +#ifdef RLT_MAC + RTMP_REG_PAIR rlt_pbf_regs[]={ + {TX_MAX_PCNT, 0xefef3f1f}, + {RX_MAX_PCNT, 0xfebf}, + }; +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + RTMP_REG_PAIR rtmp_pbf_regs[]={ +#ifdef INF_AMAZON_SE + /* + iverson modify for usb issue, 2008/09/19 + 6F + 6F < total page count FE + so that RX doesn't occupy TX's buffer space when WMM congestion. + */ + {PBF_MAX_PCNT, 0x1F3F6F6F}, +#else + {PBF_MAX_PCNT, 0x1F3FBF9F}, /* 0x1F3f7f9f}, Jan, 2006/04/20 */ +#endif /* INF_AMAZON_SE */ + }; +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + pbf_regs = &rlt_pbf_regs[0]; + tb_size = (sizeof(rlt_pbf_regs) / sizeof(RTMP_REG_PAIR)); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pbf_regs = &rtmp_pbf_regs[0]; + tb_size = (sizeof(rtmp_pbf_regs) / sizeof(RTMP_REG_PAIR)); + } +#endif /* RTMP_MAC */ + + if ((pbf_regs != NULL) && (tb_size > 0)) + { + for (idx = 0; idx < tb_size; idx++) { + RTMP_IO_WRITE32(pAd, pbf_regs->Register, pbf_regs->Value); + pbf_regs++; + } + } + return TRUE; +} + + +/* + ASIC register initialization sets +*/ +RTMP_REG_PAIR MACRegTable[] = { + {LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap*/ + {HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.*/ + {MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX*/ + {RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */ + {BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */ + {TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */ + {TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */ + /*{TX_TIMEOUT_CFG, 0x00182090}, CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT*/ + {TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT , Modify for 2860E ,2007-08-01*/ + + // TODO: shiang-usw, why MT7601 don't need to set this register?? + {LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23*/ + + /*{TX_RTY_CFG, 0x6bb80408}, Jan, 2006/11/16*/ +/* WMM_ACM_SUPPORT*/ +/* {TX_RTY_CFG, 0x6bb80101}, sample*/ + {TX_RTY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03*/ + + {AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/ + {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ + {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ + + + {GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS*/ + {GF40_PROT_CFG, 0x03F44084}, + {MM20_PROT_CFG, 0x01744004}, + +#ifdef RTMP_MAC_PCI + {MM40_PROT_CFG, 0x03F54084}, +#endif /* RTMP_MAC_PCI */ + + {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, /*Extension channel backoff.*/ + {TX_RTS_CFG, 0x00092b20}, + + {EXP_ACK_TIME, 0x002400ca}, /* default value */ + {TXOP_HLDR_ET, 0x00000002}, + + /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us + is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 + and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping + will always lost. So we change the SIFS of CCK from 10us to 16us. */ + {XIFS_TIME_CFG, 0x33a41010}, +}; + +#ifdef RTMP_MAC +RTMP_REG_PAIR MACRegTable_RTMP[] = { + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes.*/ + {PWR_PIN_CFG, 0x3}, /* patch for 2880-E*/ + /*{TX_SW_CFG0, 0x40a06}, Gary,2006-08-23 */ + {TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */ +}; +#endif /* RTMP_MAC */ + +#ifdef CONFIG_AP_SUPPORT +RTMP_REG_PAIR APMACRegTable[] = { + {WMM_AIFSN_CFG, 0x00001173}, + {WMM_CWMIN_CFG, 0x00002344}, + {WMM_CWMAX_CFG, 0x000034a6}, + {WMM_TXOP0_CFG, 0x00100020}, + {WMM_TXOP1_CFG, 0x002F0038}, + {TBTT_SYNC_CFG, 0x00012000}, +#ifdef STREAM_MODE_SUPPORT + {TX_CHAIN_ADDR0_L, 0xFFFFFFFF}, /* Broadcast frames are in stream mode*/ + {TX_CHAIN_ADDR0_H, 0x3FFFF}, +#endif /* STREAM_MODE_SUPPORT */ +}; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +RTMP_REG_PAIR STAMACRegTable[] = { + {WMM_AIFSN_CFG, 0x00002273}, + {WMM_CWMIN_CFG, 0x00002344}, + {WMM_CWMAX_CFG, 0x000034aa}, +}; +#endif /* CONFIG_STA_SUPPORT */ + + +#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR)) +#ifdef CONFIG_AP_SUPPORT +#define NUM_AP_MAC_REG_PARMS (sizeof(APMACRegTable) / sizeof(RTMP_REG_PAIR)) +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR)) +#endif /* CONFIG_STA_SUPPORT */ +#ifdef RTMP_MAC +#define NUM_RTMP_MAC_REG_PARAMS (sizeof(MACRegTable_RTMP)/ sizeof(RTMP_REG_PAIR)) +#endif /* RTMP_MAC */ + +INT rtmp_mac_init(RTMP_ADAPTER *pAd) +{ + INT idx; + + for (idx = 0; idx < NUM_MAC_REG_PARMS; idx++) + { + RTMP_IO_WRITE32(pAd, MACRegTable[idx].Register, MACRegTable[idx].Value); + } + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + UINT32 reg, val; + + for (idx = 0; idx < NUM_RTMP_MAC_REG_PARAMS; idx++){ + reg = MACRegTable_RTMP[idx].Register; + val = MACRegTable_RTMP[idx].Value; + RTMP_IO_WRITE32(pAd, reg, val); + } + } +#endif /* RTMP_MAC */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (idx = 0; idx < NUM_AP_MAC_REG_PARMS; idx++) + { + RTMP_IO_WRITE32(pAd, + APMACRegTable[idx].Register, + APMACRegTable[idx].Value); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + for (idx = 0; idx < NUM_STA_MAC_REG_PARMS; idx++) + { + RTMP_IO_WRITE32(pAd, + STAMACRegTable[idx].Register, + STAMACRegTable[idx].Value); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + rtmp_mac_pbf_init(pAd); + + /* re-set specific MAC registers for individual chip */ + if (pAd->chipOps.AsicMacInit != NULL) + pAd->chipOps.AsicMacInit(pAd); + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_firmware_e3_v1.8.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_firmware_e3_v1.8.bin new file mode 100644 index 000000000..c2bc80263 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_firmware_e3_v1.8.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_firmware_e3_v1.9.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_firmware_e3_v1.9.bin new file mode 100644 index 000000000..26c6fbb27 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_firmware_e3_v1.9.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P48.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P48.bin new file mode 100644 index 000000000..2213b2a83 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P48.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P69.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P69.bin new file mode 100644 index 000000000..10b245e9c Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P69.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_release_history.xlsx b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_release_history.xlsx new file mode 100644 index 000000000..17cf64654 Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662_patch_release_history.xlsx differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662t_firmware_e1.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662t_firmware_e1.bin new file mode 100644 index 000000000..d608b98db Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662t_firmware_e1.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662t_patch_e1_hdr.bin b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662t_patch_e1_hdr.bin new file mode 100644 index 000000000..28c684daa Binary files /dev/null and b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/bin/mt7662t_patch_e1_hdr.bin differ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/mcu.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/mcu.c new file mode 100644 index 000000000..9c4fa1830 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/mcu.c @@ -0,0 +1,131 @@ +/* + *************************************************************************** + * 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_mcu.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + +INT MCUBurstWrite(PRTMP_ADAPTER pAd, UINT32 Offset, UINT32 *Data, UINT32 Cnt) +{ + return 0; +} + + +INT MCURandomWrite(PRTMP_ADAPTER pAd, RTMP_REG_PAIR *RegPair, UINT32 Num) +{ + UINT32 Index; + + for (Index = 0; Index < Num; Index++) + RTMP_IO_WRITE32(pAd, RegPair->Register, RegPair->Value); + + return 0; +} + + +INT mcu_sys_init(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status; + + /* Load MCU firmware*/ + MCU_CTRL_INIT(pAd); + + Status = load_patch(pAd); + + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("load patch failed, Status[=0x%08x]\n", Status)); + return FALSE; + } + + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); + return FALSE; + } + + return TRUE; +} + + +VOID ChipOpsMCUHook(PRTMP_ADAPTER pAd, enum MCU_TYPE MCUType) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + +#ifdef CONFIG_SWMCU_SUPPORT + if (MCUType == SWMCU) + { + pChipOps->eraseFirmware = NULL; + pChipOps->loadFirmware = NULL; + pChipOps->sendCommandToMcu = RtmpAsicSendCommandToSwMcu; + + return; + } +#endif /* CONFIG_SWMCU_SUPPORT */ + + +#ifdef CONFIG_ANDES_SUPPORT + if (MCUType == ANDES) + { + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + +#ifdef RTMP_PCI_SUPPORT + if (pChipCap->need_load_rom_patch) { + pChipOps->load_rom_patch = andes_pci_load_rom_patch; + pChipOps->erase_rom_patch = andes_pci_erase_rom_patch; + } + + if (pChipCap->need_load_fw) { + pChipOps->loadFirmware = andes_pci_loadfw; + pChipOps->eraseFirmware = andes_pci_erasefw; + } + + pChipOps->fw_init = andes_pci_fw_init; +#endif /* RTMP_PCI_SUPPORT */ + + + if (pChipCap->need_load_fw) + { + //pChipOps->sendCommandToMcu = andes_send_cmd_msg; + pChipOps->MCUCtrlInit = andes_ctrl_init; + pChipOps->MCUCtrlExit = andes_ctrl_exit; + pChipOps->Calibration = andes_calibration; + pChipOps->BurstWrite = andes_burst_write; + pChipOps->BurstRead = andes_burst_read; + pChipOps->RandomRead = andes_random_read; + pChipOps->RFRandomRead = andes_rf_random_read; + pChipOps->ReadModifyWrite = andes_read_modify_write; + pChipOps->RFReadModifyWrite = andes_rf_read_modify_write; + pChipOps->RandomWrite = andes_random_write; + pChipOps->RFRandomWrite = andes_rf_random_write; + pChipOps->sc_random_write = andes_sc_random_write; + pChipOps->sc_rf_random_write = andes_sc_rf_random_write; + pChipOps->PwrSavingOP = andes_pwr_saving; + } + } +#endif /* CONFIG_ANDES_SUPPORT */ +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/mcu_and.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/mcu_and.c new file mode 100644 index 000000000..79adb54ed --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mcu/mcu_and.c @@ -0,0 +1,2525 @@ +/* + *************************************************************************** + * 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: + mcu_and.c + + Abstract: + on-chip CPU related codes + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +#ifdef BTCOEX_CONCURRENT +extern int CoexCenctralChannel; +extern int CoexChannel; +extern int CoexChannelBw; +#endif + +#ifdef RTMP_PCI_SUPPORT +int andes_pci_load_rom_patch(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + UINT32 start_offset, end_offset; + UINT32 loop = 0, idx = 0, val = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + UINT32 mac_value; + POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; + + if (cap->rom_code_protect) { +loadfw_protect: + RTMP_IO_READ32(ad, SEMAPHORE_03, &mac_value); + loop++; + + if (((mac_value & 0x01) == 0x00) && (loop < GET_SEMAPHORE_RETRY_MAX)) { + RtmpOsMsDelay(1); + goto loadfw_protect; + } + + if (loop >= GET_SEMAPHORE_RETRY_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: can not get the hw semaphore\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + } + + /* check rom patch if ready */ + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + RTMP_IO_READ32(ad, CLOCK_CTL, &mac_value); + } else { + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + } + + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + if (((mac_value & 0x01) == 0x01) && (cap->rom_code_protect)) { + goto done; + } + } else { + if (((mac_value & 0x02) == 0x02) && (cap->rom_code_protect)) { + goto done; + } + } + +#ifndef BB_SOC + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load rom patch from /lib/firmware/%s\n", cap->rom_patch_bin_file_name)); + OS_LOAD_CODE_FROM_BIN(&cap->rom_patch, cap->rom_patch_bin_file_name, obj->pci_dev, &cap->rom_patch_len); + } else +#endif /* !BB_SOC */ + { + cap->rom_patch = cap->rom_patch_header_image; + } + + if (!cap->rom_patch) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a rom patch(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->rom_patch_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a rom patch, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + +#ifdef DBG + /* get rom patch information */ + DBGPRINT(RT_DEBUG_OFF, ("build time = ")); + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#endif + + if (IS_MT76x2(ad)) { + if (((strncmp(cap->rom_patch, "20130809", 8) >= 0)) && (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3))) { + DBGPRINT(RT_DEBUG_OFF, ("rom patch for E3 IC\n")); + } else if (((strncmp(cap->rom_patch, "20130809", 8) < 0)) && (MT_REV_LT(ad, MT76x2, REV_MT76x2E3))){ + DBGPRINT(RT_DEBUG_OFF, ("rom patch for E2 IC\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("rom patch do not match IC version\n")); + RTMP_IO_READ32(ad, 0x0, &mac_value); + DBGPRINT(RT_DEBUG_OFF, ("IC version(%x)\n", mac_value)); + ret = NDIS_STATUS_FAILURE; + goto done; + } + } + +#ifdef DBG + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("platform = ")); + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 16 + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("hw/sw version = ")); + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%x", *(cap->rom_patch + 20 + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("patch version = ")); + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%x", *(cap->rom_patch + 24 + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#endif + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->rom_patch_offset - 10000); + + start_offset = PATCH_INFO_SIZE; + end_offset = cap->rom_patch_len; + + /* Load rom patch code */ + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->rom_patch + idx)) + + (*(cap->rom_patch + idx + 3) << 24) + + (*(cap->rom_patch + idx + 2) << 16) + + (*(cap->rom_patch + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x90000 + (idx - PATCH_INFO_SIZE), val); + } + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, 0x0); + + /* Trigger rom */ + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x04); + + /* check rom if ready */ + loop = 0; + do + { + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + RTMP_IO_READ32(ad, CLOCK_CTL, &mac_value); + if ((mac_value & 0x01)== 0x01) + break; + } else { + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + if ((mac_value & 0x02)== 0x02) + break; + } + + RtmpOsMsDelay(10); + loop++; + } while (loop <= 200); + + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s: CLOCK_CTL(0x%x) = 0x%x\n", __FUNCTION__, CLOCK_CTL, mac_value)); + if ((mac_value & 0x01) != 0x01) + ret = NDIS_STATUS_FAILURE; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("%s: COM_REG0(0x%x) = 0x%x\n", __FUNCTION__, COM_REG0, mac_value)); + if ((mac_value & 0x02) != 0x02) + ret = NDIS_STATUS_FAILURE; + } + +done: + if (cap->rom_code_protect) + RTMP_IO_WRITE32(ad, SEMAPHORE_03, 0x1); + + return ret; +} + +int andes_pci_erase_rom_patch(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (cap->load_code_method == BIN_FILE_METHOD) { + if (cap->rom_patch) + os_free_mem(NULL, cap->rom_patch); + cap->rom_patch = NULL; + } + + return 0; +} + +int andes_pci_erasefw(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + u32 ilm_len, dlm_len; + u16 fw_ver, build_ver; + u32 loop = 0, idx = 0/*, val = 0*/; + u32 mac_value; + u32 start_offset, end_offset; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (!ad->chipCap.ram_code_protect) { + + ilm_len = (*(cap->FWImageName + 3) << 24) | (*(cap->FWImageName + 2) << 16) | + (*(cap->FWImageName + 1) << 8) | (*cap->FWImageName); + + dlm_len = (*(cap->FWImageName + 7) << 24) | (*(cap->FWImageName + 6) << 16) | + (*(cap->FWImageName + 5) << 8) | (*(cap->FWImageName + 4)); + + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + +#ifdef DBG + DBGPRINT(RT_DEBUG_TRACE, ("FW Version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_TRACE, ("Build:%x\n", build_ver)); + + DBGPRINT(RT_DEBUG_TRACE, ("Build Time:")); + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_TRACE, ("%c", *(cap->FWImageName + 16 + loop))); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("ILM Length = %d(bytes)\n", ilm_len)); + DBGPRINT(RT_DEBUG_TRACE, ("DLM Length = %d(bytes)\n", dlm_len)); +#endif + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->ilm_offset); + + if (IS_MT76x2(ad)) { + start_offset = FW_INFO_SIZE; + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x1); + RtmpOsMsDelay(20); + } else { + if (cap->ram_code_protect) { + RTMP_IO_WRITE32(ad, CPU_CTL, 0x0); + RTMP_IO_WRITE32(ad, CPU_CTL, (0x1<<20)); + RTMP_IO_WRITE32(ad, RESET_CTL, 0x10); + RTMP_IO_WRITE32(ad, RESET_CTL, 0x300); + RTMP_IO_WRITE32(ad, COM_REG0, 0x0); + + start_offset = FW_INFO_SIZE + IV_SIZE; + } else { + RTMP_IO_WRITE32(ad, RESET_CTL, 0x10); /* reset fce */ + RTMP_IO_WRITE32(ad, RESET_CTL, 0x200); /* reset cpu */ + RTMP_IO_WRITE32(ad, COM_REG0, 0x0); /* clear mcu ready bit */ + + start_offset = FW_INFO_SIZE; + } + } + + end_offset = FW_INFO_SIZE + ilm_len; + + if (!IS_MT76x2(ad)) { + /* erase ilm */ + for (idx = start_offset; idx < end_offset; idx += 4) { + RTMP_IO_WRITE32(ad, 0x80000 + (idx - FW_INFO_SIZE), 0); + } + + if (cap->ram_code_protect) { + /* Loading IV part into last 64 bytes of ILM */ + start_offset = FW_INFO_SIZE; + end_offset = FW_INFO_SIZE + IV_SIZE; + + for (idx = start_offset; idx < end_offset; idx += 4) + { + RTMP_IO_WRITE32(ad, 0x80000 + (0x54000 - IV_SIZE) + (idx - FW_INFO_SIZE), 0); + } + } + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->dlm_offset); + + start_offset = 32 + ilm_len; + end_offset = 32 + ilm_len + dlm_len; + + /* erase dlm */ + for (idx = start_offset; idx < end_offset; idx += 4) { + RTMP_IO_WRITE32(ad, 0x80000 + (0x54000 - IV_SIZE) + (idx - FW_INFO_SIZE), 0); + } + } + + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + DBGPRINT(RT_DEBUG_TRACE, ("%s: COM_REG0(0x%x) = 0x%x\n", __FUNCTION__, COM_REG0, mac_value)); + RTMP_IO_READ32(ad, RESET_CTL, &mac_value); + DBGPRINT(RT_DEBUG_TRACE, ("%s: RESET_CTL(0x%x) = 0x%x\n", __FUNCTION__, RESET_CTL, mac_value)); + } + + if (cap->load_code_method == BIN_FILE_METHOD) { + if (cap->FWImageName) + os_free_mem(NULL, cap->FWImageName); + cap->FWImageName = NULL; + } + + return ret; +} + +NDIS_STATUS andes_pci_loadfw(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + UINT32 ilm_len, dlm_len; + USHORT fw_ver, build_ver; + UINT32 loop = 0, idx = 0, val = 0; + UINT32 mac_value; + UINT32 start_offset, end_offset; + RTMP_CHIP_CAP *cap = &ad->chipCap; + POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; + + if (cap->ram_code_protect) { +loadfw_protect: + RTMP_IO_READ32(ad, SEMAPHORE_00, &mac_value); + loop++; + + if (((mac_value & 0x01) == 0) && (loop < GET_SEMAPHORE_RETRY_MAX)) { + RtmpOsMsDelay(1); + goto loadfw_protect; + } + + if (loop >= GET_SEMAPHORE_RETRY_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: can not get the hw semaphore\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + } + + /* check MCU if ready */ + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + + if (((mac_value & 0x01) == 0x01) && (cap->ram_code_protect)) { + goto done; + } + +#ifndef BB_SOC + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name)); + OS_LOAD_CODE_FROM_BIN(&cap->FWImageName, cap->fw_bin_file_name, obj->pci_dev, &cap->fw_len); + } else +#endif /* !BB_SOC */ + { + cap->FWImageName = cap->fw_header_image; + } + + if (!cap->FWImageName) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + + ilm_len = (*(cap->FWImageName + 3) << 24) | (*(cap->FWImageName + 2) << 16) | + (*(cap->FWImageName + 1) << 8) | (*cap->FWImageName); + + dlm_len = (*(cap->FWImageName + 7) << 24) | (*(cap->FWImageName + 6) << 16) | + (*(cap->FWImageName + 5) << 8) | (*(cap->FWImageName + 4)); + + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + +#ifdef DBG + DBGPRINT(RT_DEBUG_OFF, ("FW Version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_OFF, ("Build:%x\n", build_ver)); + + DBGPRINT(RT_DEBUG_OFF, ("Build Time:")); + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + 16 + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#endif + + if (IS_MT76x2(ad)) { + if (((strncmp(cap->FWImageName + 16, "20130811", 8) >= 0)) && (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3))) { + DBGPRINT(RT_DEBUG_OFF, ("fw for E3 IC\n")); + } else if (((strncmp(cap->FWImageName + 16, "20130811", 8) < 0)) && (MT_REV_LT(ad, MT76x2, REV_MT76x2E3))){ + DBGPRINT(RT_DEBUG_OFF, ("fw for E2 IC\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("fw do not match IC version\n")); + RTMP_IO_READ32(ad, 0x0, &mac_value); + DBGPRINT(RT_DEBUG_OFF, ("IC version(%x)\n", mac_value)); + ret = NDIS_STATUS_FAILURE; + goto done; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("ILM Length = %d(bytes)\n", ilm_len)); + DBGPRINT(RT_DEBUG_TRACE, ("DLM Length = %d(bytes)\n", dlm_len)); + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->ilm_offset); + + if (cap->ram_code_protect) + start_offset = FW_INFO_SIZE + IV_SIZE; + else + start_offset = FW_INFO_SIZE; + + end_offset = FW_INFO_SIZE + ilm_len; + + /* Load ILM code */ + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (idx - FW_INFO_SIZE), val); + } + + if (cap->ram_code_protect) + { + /* Loading IV part into last 64 bytes of ILM */ + start_offset = FW_INFO_SIZE; + end_offset = FW_INFO_SIZE + IV_SIZE; + + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (0x54000 - IV_SIZE) + (idx - FW_INFO_SIZE), val); + } + } + + if (IS_MT76x2(ad)) { + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->dlm_offset - 0x10000); + } else + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->dlm_offset); + + start_offset = FW_INFO_SIZE + ilm_len; + end_offset = FW_INFO_SIZE + ilm_len + dlm_len; + + /* Load DLM code */ + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + if (IS_MT76x2(ad)) { + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) + RTMP_IO_WRITE32(ad, 0x90800 + (idx - FW_INFO_SIZE - ilm_len), val); + else + RTMP_IO_WRITE32(ad, 0x90000 + (idx - FW_INFO_SIZE - ilm_len), val); + } else + RTMP_IO_WRITE32(ad, 0x80000 + (idx - FW_INFO_SIZE - ilm_len), val); + } + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, 0x0); + +#ifdef RTMP_FLASH_SUPPORT +#ifdef MT76x2 + if (IS_MT76x2(ad)) + { + UCHAR e2p_type; + e2p_type = ad->E2pAccessMode; + e2p_type = ((e2p_type != 0) && (e2p_type < NUM_OF_E2P_MODE)) ? e2p_type : RtmpEepromGetDefault(ad); + + + if (e2p_type == E2P_FLASH_MODE) + { + USHORT ee_val = 0; + + rtmp_nv_init(ad); + rtmp_ee_flash_read(ad, EEPROM_NIC3_OFFSET, &ee_val); + ad->NicConfig3.word = ee_val; + if (ad->NicConfig3.field.XtalOption == 0x1) + { + /* + MAC 730 bit [30] = 1: Co-Clock Enable + */ + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + mac_value |= (1 << 30); + RTMP_IO_WRITE32(ad, COM_REG0, mac_value); + } + } + } +#endif /* MT76x2 */ +#endif /* RTMP_FLASH_SUPPORT */ + + + if (cap->ram_code_protect) + { + /* Trigger Firmware */ + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x03); + } + else + { + if (IS_MT76x2(ad)) + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x2); + else + RTMP_IO_WRITE32(ad, RESET_CTL, 0x300); + } + + /* check MCU if ready */ + loop = 0; + do + { + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + if ((mac_value & 0x01)== 0x1) + break; + RtmpOsMsDelay(10); + loop++; + } while (loop <= 200); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: COM_REG0(0x%x) = 0x%x\n", __FUNCTION__, COM_REG0, mac_value)); + + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + mac_value |= (1 << 1); + RTMP_IO_WRITE32(ad, COM_REG0, mac_value); + + if ((mac_value & 0x01 ) != 0x1) + ret = NDIS_STATUS_FAILURE; + +done: + if (cap->ram_code_protect) + RTMP_IO_WRITE32(ad, SEMAPHORE_00, 0x1); + + return ret; +} +#endif + + +int andes_usb_erasefw(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (cap->load_code_method == BIN_FILE_METHOD) { + if (cap->FWImageName) + os_free_mem(NULL, cap->FWImageName); + cap->FWImageName = NULL; + } + + return 0; +} + +struct cmd_msg *andes_alloc_cmd_msg(RTMP_ADAPTER *ad, unsigned int length) +{ + struct cmd_msg *msg = NULL; + RTMP_CHIP_CAP *cap = &ad->chipCap; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + PNDIS_PACKET net_pkt = NULL; + + net_pkt = RTMP_AllocateFragPacketBuffer(ad, cap->cmd_header_len + length + cap->cmd_padding_len); + + if (!net_pkt) { + DBGPRINT(RT_DEBUG_ERROR, ("can not allocate net_pkt\n")); + goto error0; + } + + OS_PKT_RESERVE(net_pkt, cap->cmd_header_len); + + os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(*msg)); + + if (!msg) { + DBGPRINT(RT_DEBUG_ERROR, ("can not allocate cmd msg\n")); + goto error1; + } + + CMD_MSG_CB(net_pkt)->msg = msg; + + memset(msg, 0x00, sizeof(*msg)); + + + msg->priv = (void *)ad; + msg->net_pkt = net_pkt; + + ctl->alloc_cmd_msg++; + + return msg; + + os_free_mem(NULL, msg); +error1: + RTMPFreeNdisPacket(ad, net_pkt); +error0: + return NULL; +} + +void andes_init_cmd_msg(struct cmd_msg *msg, u8 type, BOOLEAN need_wait, u16 timeout, + BOOLEAN need_retransmit, BOOLEAN need_rsp, u16 rsp_payload_len, + char *rsp_payload, MSG_RSP_HANDLER rsp_handler) +{ + msg->type = type; + msg->need_wait= FALSE; + msg->timeout = timeout; + + if (need_wait) { +#ifdef RTMP_PCI_SUPPORT + msg->ack_done = FALSE; +#endif + + } + + msg->need_retransmit = 0; + + msg->retransmit_times = 0; + + msg->need_rsp = FALSE; + msg->rsp_payload_len = rsp_payload_len; + msg->rsp_payload = rsp_payload; + msg->rsp_handler = rsp_handler; +} + +void andes_append_cmd_msg(struct cmd_msg *msg, char *data, unsigned int len) +{ + PNDIS_PACKET net_pkt = msg->net_pkt; + + if (data) + memcpy(OS_PKT_TAIL_BUF_EXTEND(net_pkt, len), data, len); +} + +void andes_free_cmd_msg(struct cmd_msg *msg) +{ + PNDIS_PACKET net_pkt = msg->net_pkt; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)(msg->priv); + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (msg->need_wait) { +#ifdef RTMP_PCI_SUPPORT + msg->ack_done = FALSE; +#endif + + } + + + os_free_mem(NULL, msg); + + RTMPFreeNdisPacket(ad, net_pkt); + ctl->free_cmd_msg++; +} + +BOOLEAN is_inband_cmd_processing(RTMP_ADAPTER *ad) +{ + BOOLEAN ret = 0; + + return ret; +} + +UCHAR get_cmd_rsp_num(RTMP_ADAPTER *ad) +{ + UCHAR Num = 0; + + return Num; +} + +static inline void andes_inc_error_count(struct MCU_CTRL *ctl, enum cmd_msg_error_type type) +{ + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + switch (type) { + case error_tx_kickout_fail: + ctl->tx_kickout_fail_count++; + break; + case error_tx_timeout_fail: + ctl->tx_timeout_fail_count++; + break; + case error_rx_receive_fail: + ctl->rx_receive_fail_count++; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s:unknown cmd_msg_error_type(%d)\n", __FUNCTION__, type)); + } + } +} + +static NDIS_SPIN_LOCK *andes_get_spin_lock(struct MCU_CTRL *ctl, DL_LIST *list) +{ + NDIS_SPIN_LOCK *lock = NULL; + + if (list == &ctl->txq) + lock = &ctl->txq_lock; + else if (list == &ctl->rxq) + lock = &ctl->rxq_lock; + else if (list == &ctl->ackq) + lock = &ctl->ackq_lock; + else if (list == &ctl->kickq) + lock = &ctl->kickq_lock; + else if (list == &ctl->tx_doneq) + lock = &ctl->tx_doneq_lock; + else if (list == &ctl->rx_doneq) + lock = &ctl->rx_doneq_lock; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:illegal list\n", __FUNCTION__)); + + return lock; +} + +static inline UCHAR andes_get_cmd_msg_seq(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + struct cmd_msg *msg; + unsigned long flags; + + RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +get_seq: + ctl->cmd_seq >= 0xf ? ctl->cmd_seq = 1 : ctl->cmd_seq++; + DlListForEach(msg, &ctl->ackq, struct cmd_msg, list) { + if (msg->seq == ctl->cmd_seq) { + DBGPRINT(RT_DEBUG_ERROR, ("command(seq: %d) is still running\n", ctl->cmd_seq)); + DBGPRINT(RT_DEBUG_ERROR, ("command response nums = %d\n", get_cmd_rsp_num(ad))); + goto get_seq; + } + } + RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); + + return ctl->cmd_seq; +} + +static void _andes_queue_tail_cmd_msg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + msg->state = state; + DlListAddTail(list, &msg->list); +} + +static void andes_queue_tail_cmd_msg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + unsigned long flags; + NDIS_SPIN_LOCK *lock; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + _andes_queue_tail_cmd_msg(list, msg, state); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + +static void _andes_queue_head_cmd_msg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + msg->state = state; + DlListAdd(list, &msg->list); +} + +static void andes_queue_head_cmd_msg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + unsigned long flags; + NDIS_SPIN_LOCK *lock; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + _andes_queue_head_cmd_msg(list, msg, state); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + +static u32 andes_queue_len(struct MCU_CTRL *ctl, DL_LIST *list) +{ + u32 qlen; + unsigned long flags; + NDIS_SPIN_LOCK *lock; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + qlen = DlListLen(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); + + return qlen; +} + + +static void andes_queue_init(struct MCU_CTRL *ctl, DL_LIST *list) +{ + + unsigned long flags; + NDIS_SPIN_LOCK *lock; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + DlListInit(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + +static void _andes_unlink_cmd_msg(struct cmd_msg *msg, DL_LIST *list) +{ + if (!msg) + return; + + DlListDel(&msg->list); +} + +static void andes_unlink_cmd_msg(struct cmd_msg *msg, DL_LIST *list) +{ + unsigned long flags; + NDIS_SPIN_LOCK *lock; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + _andes_unlink_cmd_msg(msg, list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + +static struct cmd_msg *_andes_dequeue_cmd_msg(DL_LIST *list) +{ + struct cmd_msg *msg; + + msg = DlListFirst(list, struct cmd_msg, list); + + _andes_unlink_cmd_msg(msg, list); + + return msg; +} + +static struct cmd_msg *andes_dequeue_cmd_msg(struct MCU_CTRL *ctl, DL_LIST *list) +{ + unsigned long flags; + struct cmd_msg *msg; + NDIS_SPIN_LOCK *lock; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + msg = _andes_dequeue_cmd_msg(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); + + return msg; +} + +void andes_rx_process_cmd_msg(RTMP_ADAPTER *ad, struct cmd_msg *rx_msg) +{ + PNDIS_PACKET net_pkt = rx_msg->net_pkt; + struct cmd_msg *msg, *msg_tmp; + RXFCE_INFO_CMD *rx_info = (RXFCE_INFO_CMD *)GET_OS_PKT_DATAPTR(net_pkt); + struct MCU_CTRL *ctl = &ad->MCUCtrl; + unsigned long flags; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)rx_info, TYPE_RXINFO); +#endif + + DBGPRINT(RT_DEBUG_INFO, ("(andex_rx_cmd)info_type=%d,evt_type=%d,d_port=%d," + "qsel=%d,pcie_intr=%d,cmd_seq=%d," + "self_gen=%d,pkt_len=%d\n", + rx_info->info_type, rx_info->evt_type,rx_info->d_port, + rx_info->qsel, rx_info->pcie_intr, rx_info->cmd_seq, + rx_info->self_gen, rx_info->pkt_len)); + + if ((rx_info->info_type != CMD_PACKET)) { + DBGPRINT(RT_DEBUG_ERROR, ("packet is not command response/self event\n")); + return; + } +#ifdef DBG + #define LOG2HOST 3 + if (rx_info->evt_type == LOG2HOST) + { + PUCHAR pRxRspEvtPayload = GET_OS_PKT_DATAPTR(net_pkt) + sizeof(RXFCE_INFO_CMD); + DBGPRINT(RT_DEBUG_WARN, ("[FW]%s\n", pRxRspEvtPayload)); + } +#endif + if (rx_info->self_gen) { + /* if have callback function */ + RTEnqueueInternalCmd(ad, CMDTHREAD_RESPONSE_EVENT_CALLBACK, + GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*rx_info), rx_info->pkt_len); + } else { + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +#endif + DlListForEachSafe(msg, msg_tmp, &ctl->ackq, struct cmd_msg, list) { + if (msg->seq == rx_info->cmd_seq) + { + _andes_unlink_cmd_msg(msg, &ctl->ackq); + +#ifdef RTMP_PCI_SUPPORT + //RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); +#endif + + if ((msg->rsp_payload_len == rx_info->pkt_len) && (msg->rsp_payload_len != 0)) + { + msg->rsp_handler(msg, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*rx_info), rx_info->pkt_len); + } + else if ((msg->rsp_payload_len == 0) && (rx_info->pkt_len == 8)) + { + DBGPRINT(RT_DEBUG_INFO, ("command response(ack) success\n")); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("expect response len(%d), command response len(%d) invalid\n", msg->rsp_payload_len, rx_info->pkt_len)); + msg->rsp_payload_len = rx_info->pkt_len; + } + + if (msg->need_wait) { +#ifdef RTMP_PCI_SUPPORT + msg->ack_done = TRUE; +#endif + + } else { + andes_free_cmd_msg(msg); + } + +#ifdef RTMP_PCI_SUPPORT + //RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +#endif + break; + } + } + + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); +#endif + } +} + +#ifdef RTMP_PCI_SUPPORT +void pci_rx_cmd_msg_complete(RTMP_ADAPTER *ad, RXFCE_INFO *fce_info, PUCHAR payload) +{ + struct cmd_msg *msg; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + msg = andes_alloc_cmd_msg(ad, sizeof(*fce_info) + fce_info->pkt_len); + + if (!msg) + return; +#ifdef MT76x2 + andes_append_cmd_msg(msg, (char *)fce_info, sizeof(*fce_info)); + andes_append_cmd_msg(msg, (char *)payload, fce_info->pkt_len); +#else + andes_append_cmd_msg(msg, (char *)fce_info, sizeof(*fce_info) + fce_info->pkt_len); +#endif /* MT76x2 */ + + andes_rx_process_cmd_msg(ad, msg); + + andes_free_cmd_msg(msg); +} + +#endif + + +void andes_cmd_msg_bh(unsigned long param) +{ + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)param; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + struct cmd_msg *msg = NULL; + + while ((msg = andes_dequeue_cmd_msg(ctl, &ctl->rx_doneq))) { + switch (msg->state) { + case rx_done: + andes_rx_process_cmd_msg(ad, msg); + andes_free_cmd_msg(msg); + continue; + case rx_receive_fail: + andes_free_cmd_msg(msg); + continue; + default: + DBGPRINT(RT_DEBUG_ERROR, ("unknow msg state(%d)\n", msg->state)); + } + } + + while ((msg = andes_dequeue_cmd_msg(ctl, &ctl->tx_doneq))) { + switch (msg->state) { + case tx_done: + case tx_kickout_fail: + case tx_timeout_fail: + andes_free_cmd_msg(msg); + continue; + default: + DBGPRINT(RT_DEBUG_ERROR, ("unknow msg state(%d)\n", msg->state)); + } + } + + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + andes_bh_schedule(ad); + } +} + +void andes_bh_schedule(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return; + + if (((andes_queue_len(ctl, &ctl->rx_doneq) > 0) + || (andes_queue_len(ctl, &ctl->tx_doneq) > 0)) + && OS_TEST_BIT(MCU_INIT, &ctl->flags)) { +#ifndef WORKQUEUE_BH + RTMP_NET_TASK_DATA_ASSIGN(&ctl->cmd_msg_task, (unsigned long)(ad)); + RTMP_OS_TASKLET_SCHE(&ctl->cmd_msg_task); +#else + tasklet_hi_schedule(&ctl->cmd_msg_task); +#endif + } +} + +#ifdef RTMP_PCI_SUPPORT +#ifdef DBG +static UCHAR *txinfo_type_str[]={"PKT", "CMD", "RSV"}; +static UCHAR *txinfo_d_port_str[]={"WLAN", "CPU_RX", "CPU_TX", "HOST", "VIRT_RX", "VIRT_TX", "DROP"}; + +VOID dump_cmd_txinfo(RTMP_ADAPTER *ad, TXINFO_STRUC *pTxInfo) +{ + DBGPRINT(RT_DEBUG_OFF, ("TxInfo:\n")); + { + struct _TXINFO_NMAC_CMD *cmd_txinfo = (struct _TXINFO_NMAC_CMD *)pTxInfo; + + hex_dump("Raw Data: ", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC)); + DBGPRINT(RT_DEBUG_OFF, ("\t Info_Type=%d(%s)\n", cmd_txinfo->info_type, txinfo_type_str[cmd_txinfo->info_type])); + DBGPRINT(RT_DEBUG_OFF, ("\t d_port=%d(%s)\n", cmd_txinfo->d_port, txinfo_d_port_str[cmd_txinfo->d_port])); + DBGPRINT(RT_DEBUG_OFF, ("\t cmd_type=%d\n", cmd_txinfo->cmd_type)); + DBGPRINT(RT_DEBUG_OFF, ("\t cmd_seq=%d\n", cmd_txinfo->cmd_seq)); + DBGPRINT(RT_DEBUG_OFF, ("\t pkt_len=0x%x\n", cmd_txinfo->pkt_len)); + } + + DBGPRINT(RT_DEBUG_OFF, ("\t")); +} +#endif + +int pci_kick_out_cmd_msg( + PRTMP_ADAPTER ad, + struct cmd_msg *msg) +{ + int ret = NDIS_STATUS_SUCCESS; + unsigned long flags = 0; + ULONG FreeNum; + PNDIS_PACKET net_pkt = msg->net_pkt; + u32 SwIdx = 0, SrcBufPA; + UCHAR *pSrcBufVA; + UINT SrcBufLen = 0; + PACKET_INFO PacketInfo; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; + struct MCU_CTRL *ctl = &ad->MCUCtrl; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return -1; + + FreeNum = GET_CTRLRING_FREENO(ad); + + if (FreeNum == 0) { + DBGPRINT(RT_DEBUG_WARN, ("%s FreeNum == 0 (TxCpuIdx = %d, TxDmaIdx = %d, TxSwFreeIdx = %d)\n", + __FUNCTION__, ad->CtrlRing.TxCpuIdx, ad->CtrlRing.TxDmaIdx, ad->CtrlRing.TxSwFreeIdx)); + return NDIS_STATUS_FAILURE; + } + + RTMP_SPIN_LOCK_IRQSAVE(&ad->CtrlRingLock, &flags); + + RTMP_QueryPacketInfo(net_pkt, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) { + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->CtrlRingLock, &flags); + return NDIS_STATUS_FAILURE; + } + + SwIdx = ad->CtrlRing.TxCpuIdx; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)ad->CtrlRing.Cell[SwIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (PTXD_STRUC)&tx_hw_info[0]; +#else + pTxD = (PTXD_STRUC)ad->CtrlRing.Cell[SwIdx].AllocVa; +#endif + + pTxInfo = (TXINFO_STRUC *)((UCHAR *)pTxD + sizeof(TXD_STRUC)); + NdisMoveMemory(pTxInfo, pSrcBufVA, TXINFO_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + ad->CtrlRing.Cell[SwIdx].pNdisPacket = net_pkt; + ad->CtrlRing.Cell[SwIdx].pNextNdisPacket = NULL; + +#ifndef RT_SECURE_DMA + SrcBufPA = PCI_MAP_SINGLE(ad, (pSrcBufVA) + 4, (SrcBufLen) - 4, 0, RTMP_PCI_DMA_TODEVICE); +#else + NdisMoveMemory(ad->CtrlSecureDMA.AllocVa + (SwIdx * 4096), pSrcBufVA + 4, (SrcBufLen - TXINFO_SIZE)); + SrcBufPA = ad->CtrlSecureDMA.AllocPa + (SwIdx * 4096); +#endif + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = (SrcBufLen - TXINFO_SIZE); + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = SrcBufPA; + pTxD->DMADONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen); + RTMP_DCACHE_FLUSH(ad->CtrlRing.Cell[SwIdx].AllocPa, TXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(ad->CtrlRing.TxCpuIdx, MGMT_RING_SIZE); + + if (msg->need_rsp) + andes_queue_tail_cmd_msg(&ctl->ackq, msg, wait_cmd_out_and_ack); + else + andes_queue_tail_cmd_msg(&ctl->kickq, msg, wait_cmd_out); + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->CtrlRingLock, &flags); + return -1; + } + + RTMP_IO_WRITE32(ad, ad->CtrlRing.hw_cidx_addr, ad->CtrlRing.TxCpuIdx); + + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->CtrlRingLock, &flags); + + return ret; +} + +void pci_kick_out_cmd_msg_complete(PNDIS_PACKET net_pkt) +{ + struct cmd_msg *msg =CMD_MSG_CB(net_pkt)->msg; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return; + + if (!msg->need_rsp) { + andes_unlink_cmd_msg(msg, &ctl->kickq); + andes_queue_tail_cmd_msg(&ctl->tx_doneq, msg, tx_done); + } else { + msg->state = wait_ack; + } + + andes_bh_schedule(ad); +} +#endif + + + +void andes_cleanup_cmd_msg(RTMP_ADAPTER *ad, DL_LIST *list) +{ + unsigned long flags; + struct cmd_msg *msg, *msg_tmp; + NDIS_SPIN_LOCK *lock; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = andes_get_spin_lock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + DlListForEachSafe(msg, msg_tmp, list, struct cmd_msg, list) { + _andes_unlink_cmd_msg(msg, list); + andes_free_cmd_msg(msg); + } + DlListInit(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + +#ifdef RTMP_PCI_SUPPORT +static void andes_ctrl_pci_init(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + RTMP_SPIN_LOCK_IRQ(&ad->mcu_atomic); + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + ctl->cmd_seq = 0; +#ifndef WORKQUEUE_BH + RTMP_OS_TASKLET_INIT(ad, &ctl->cmd_msg_task, andes_cmd_msg_bh, (unsigned long)ad); +#else + tasklet_init(&ctl->cmd_msg_task, andes_cmd_msg_bh, (unsigned long)ad); +#endif + NdisAllocateSpinLock(ad, &ctl->txq_lock); + andes_queue_init(ctl, &ctl->txq); + NdisAllocateSpinLock(ad, &ctl->rxq_lock); + andes_queue_init(ctl, &ctl->rxq); + NdisAllocateSpinLock(ad, &ctl->ackq_lock); + andes_queue_init(ctl, &ctl->ackq); + NdisAllocateSpinLock(ad, &ctl->kickq_lock); + andes_queue_init(ctl, &ctl->kickq); + NdisAllocateSpinLock(ad, &ctl->tx_doneq_lock); + andes_queue_init(ctl, &ctl->tx_doneq); + NdisAllocateSpinLock(ad, &ctl->rx_doneq_lock); + andes_queue_init(ctl, &ctl->rx_doneq); + ctl->tx_kickout_fail_count = 0; + ctl->tx_timeout_fail_count = 0; + ctl->rx_receive_fail_count = 0; + ctl->alloc_cmd_msg = 0; + ctl->free_cmd_msg = 0; + OS_SET_BIT(MCU_INIT, &ctl->flags); + ctl->ad = ad; + RTMP_SPIN_UNLOCK_IRQ(&ad->mcu_atomic); +} +#endif + + +void andes_ctrl_init(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { +#ifdef RTMP_PCI_SUPPORT + andes_ctrl_pci_init(ad); +#endif + + } + + ctl->power_on = FALSE; + ctl->dpd_on = FALSE; +} + + +#ifdef RTMP_PCI_SUPPORT +static void andes_ctrl_pci_exit(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + unsigned long flags; + + RTMP_SPIN_LOCK_IRQSAVE(&ad->mcu_atomic, &flags); + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + OS_CLEAR_BIT(MCU_INIT, &ctl->flags); + RTMP_OS_TASKLET_KILL(&ctl->cmd_msg_task); + andes_cleanup_cmd_msg(ad, &ctl->txq); + NdisFreeSpinLock(&ctl->txq_lock); + andes_cleanup_cmd_msg(ad, &ctl->ackq); + NdisFreeSpinLock(&ctl->ackq_lock); + andes_cleanup_cmd_msg(ad, &ctl->rxq); + NdisFreeSpinLock(&ctl->rxq_lock); + andes_cleanup_cmd_msg(ad, &ctl->kickq); + NdisFreeSpinLock(&ctl->kickq_lock); + andes_cleanup_cmd_msg(ad, &ctl->tx_doneq); + NdisFreeSpinLock(&ctl->tx_doneq_lock); + andes_cleanup_cmd_msg(ad, &ctl->rx_doneq); + NdisFreeSpinLock(&ctl->rx_doneq_lock); + DBGPRINT(RT_DEBUG_OFF, ("tx_kickout_fail_count = %ld\n", ctl->tx_kickout_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("tx_timeout_fail_count = %ld\n", ctl->tx_timeout_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("rx_receive_fail_count = %ld\n", ctl->rx_receive_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("alloc_cmd_msg = %ld\n", ctl->alloc_cmd_msg)); + DBGPRINT(RT_DEBUG_OFF, ("free_cmd_msg = %ld\n", ctl->free_cmd_msg)); + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->mcu_atomic, &flags); +} +#endif + +void andes_ctrl_exit(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { +#ifdef RTMP_PCI_SUPPORT + andes_ctrl_pci_exit(ad); +#endif + + } + + ctl->power_on = FALSE; + ctl->dpd_on = FALSE; +} + +static int andes_dequeue_and_kick_out_cmd_msgs(RTMP_ADAPTER *ad) +{ + struct cmd_msg *msg = NULL; + PNDIS_PACKET net_pkt = NULL; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + int ret = NDIS_STATUS_SUCCESS; + TXINFO_NMAC_CMD *tx_info; + + while ((msg = andes_dequeue_cmd_msg(ctl, &ctl->txq)) != NULL) { + if (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_SUSPEND)) { + if (!msg->need_rsp) + andes_free_cmd_msg(msg); + continue; + } + + if (andes_queue_len(ctl, &ctl->ackq) > 0) { + andes_queue_head_cmd_msg(&ctl->txq, msg, msg->state); + ret = NDIS_STATUS_FAILURE; + continue; + } + + net_pkt = msg->net_pkt; + + if (msg->state != tx_retransmit) { + if (msg->need_rsp) + msg->seq = andes_get_cmd_msg_seq(ad); + else + msg->seq = 0; + + tx_info = (TXINFO_NMAC_CMD *)OS_PKT_HEAD_BUF_EXTEND(net_pkt, sizeof(*tx_info)); + tx_info->info_type = CMD_PACKET; + tx_info->d_port = CPU_TX_PORT; + tx_info->cmd_type = msg->type; + tx_info->cmd_seq = msg->seq; + tx_info->pkt_len = GET_OS_PKT_LEN(net_pkt) - sizeof(*tx_info); + +#ifdef RT_BIG_ENDIAN + *(UINT32 *)tx_info = le2cpu32(*(UINT32 *)tx_info); + //RTMPDescriptorEndianChange((PUCHAR)tx_info, TYPE_TXINFO); +#endif + } + + + +#ifdef RTMP_PCI_SUPPORT + ret = pci_kick_out_cmd_msg(ad, msg); +#endif + + if (ret) { + DBGPRINT(RT_DEBUG_ERROR, ("kick out msg fail\n")); + break; + } + } + + andes_bh_schedule(ad); + + return ret; +} + +static int andes_wait_for_complete_timeout(struct cmd_msg *msg, long timeout) +{ + int ret = 0; + +#ifdef RTMP_PCI_SUPPORT + timeout = CMD_MSG_TIMEOUT; + + do { + if (msg->ack_done == TRUE) + return -1; + + OS_WAIT(1); + timeout --; + } while (timeout != 0); +#endif + + + return ret; +} + +int andes_send_cmd_msg(PRTMP_ADAPTER ad, struct cmd_msg *msg) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + int ret = 0; + BOOLEAN need_wait = msg->need_wait; + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_LOCK(&ad->mcu_atomic); +#endif + + + if (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_SUSPEND)) { + andes_free_cmd_msg(msg); +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_UNLOCK(&ad->mcu_atomic); +#endif + + return NDIS_STATUS_FAILURE; + } + + andes_queue_tail_cmd_msg(&ctl->txq, msg, tx_start); + +retransmit: + andes_dequeue_and_kick_out_cmd_msgs(ad); + + /* Wait for response */ + if (need_wait) { + enum cmd_msg_state state; + if (!andes_wait_for_complete_timeout(msg, msg->timeout)) { + ret = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("command (%d) timeout(%dms)\n", msg->type, CMD_MSG_TIMEOUT)); + DBGPRINT(RT_DEBUG_ERROR, ("txq qlen = %d\n", andes_queue_len(ctl, &ctl->txq))); + DBGPRINT(RT_DEBUG_ERROR, ("rxq qlen = %d\n", andes_queue_len(ctl, &ctl->rxq))); + DBGPRINT(RT_DEBUG_ERROR, ("kickq qlen = %d\n", andes_queue_len(ctl, &ctl->kickq))); + DBGPRINT(RT_DEBUG_ERROR, ("ackq qlen = %d\n", andes_queue_len(ctl, &ctl->ackq))); + DBGPRINT(RT_DEBUG_ERROR, ("tx_doneq.qlen = %d\n", andes_queue_len(ctl, &ctl->tx_doneq))); + DBGPRINT(RT_DEBUG_ERROR, ("rx_done qlen = %d\n", andes_queue_len(ctl, &ctl->rx_doneq))); + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + if (msg->state == wait_cmd_out_and_ack) { + } else if (msg->state == wait_ack) { + andes_unlink_cmd_msg(msg, &ctl->ackq); + } + } + + andes_inc_error_count(ctl, error_tx_timeout_fail); + state = tx_timeout_fail; + if (msg->retransmit_times > 0) + msg->retransmit_times--; + DBGPRINT(RT_DEBUG_ERROR, ("msg->retransmit_times = %d\n", msg->retransmit_times)); + } else { + if (msg->state == tx_kickout_fail) { + state = tx_kickout_fail; + msg->retransmit_times--; + } else { + state = tx_done; + msg->retransmit_times = 0; + } + } + + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + if (msg->need_retransmit && (msg->retransmit_times > 0)) { +#ifdef RTMP_PCI_SUPPORT + msg->ack_done = FALSE; +#endif + + state = tx_retransmit; + andes_queue_head_cmd_msg(&ctl->txq, msg, state); + goto retransmit; + } else { + andes_queue_tail_cmd_msg(&ctl->tx_doneq, msg, state); + } + } else { + andes_free_cmd_msg(msg); + } + } + + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_UNLOCK(&ad->mcu_atomic); + RtmpOsMsDelay(10); +#endif + + return ret; +} + +static void andes_pwr_event_handler(RTMP_ADAPTER *ad, char *payload, u16 payload_len) +{ + + +} + + +static void andes_wow_event_handler(RTMP_ADAPTER *ad, char *payload, u16 payload_len) +{ + + +} + +static void andes_carrier_detect_event_handler(RTMP_ADAPTER *ad, char *payload, u16 payload_len) +{ + + + +} + +static void andes_dfs_detect_event_handler(PRTMP_ADAPTER ad, char *payload, u16 payload_len) +{ + + + +} + +MSG_EVENT_HANDLER msg_event_handler_tb[] = +{ + andes_pwr_event_handler, + andes_wow_event_handler, + andes_carrier_detect_event_handler, + andes_dfs_detect_event_handler, +}; + + +int andes_burst_write(RTMP_ADAPTER *ad, u32 offset, u32 *data, u32 cnt) +{ + struct cmd_msg *msg; + unsigned int var_len, offset_num, cur_len = 0, sent_len; + u32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!data) + return -1; + + offset_num = cnt / ((cap->InbandPacketMaxLen - sizeof(offset)) / 4); + + if (cnt % ((cap->InbandPacketMaxLen - sizeof(offset)) / 4)) + var_len = sizeof(offset) * (offset_num + 1) + 4 * cnt; + else + var_len = sizeof(offset) * offset_num + 4 * cnt; + + while (cur_len < var_len) { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if (((sent_len < cap->InbandPacketMaxLen) || ((cur_len + cap->InbandPacketMaxLen) == var_len))) + last_packet = TRUE; + + msg = andes_alloc_cmd_msg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) { + andes_init_cmd_msg(msg, CMD_BURST_WRITE, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + }else { + andes_init_cmd_msg(msg, CMD_BURST_WRITE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + } + + + value = cpu2le32(offset + cap->WlanMemmapOffset + cur_index * 4); + andes_append_cmd_msg(msg, (char *)&value, 4); + + for (i = 0; i < ((sent_len - 4) / 4); i++) { + value = cpu2le32(data[i + cur_index]); + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + + + cur_index += ((sent_len - 4) / 4); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +static void andes_burst_read_callback(struct cmd_msg *msg, char *rsp_payload, u16 rsp_payload_len) +{ + u32 i; + u32 *data; + NdisMoveMemory(msg->rsp_payload, rsp_payload + 4, rsp_payload_len - 4); + + for (i = 0; i < (msg->rsp_payload_len - 4) / 4; i++) { + data = (u32 *)(msg->rsp_payload + i * 4); + *data = le2cpu32(*data); + } +} + +int andes_burst_read(RTMP_ADAPTER *ad, u32 offset, u32 cnt, u32 *data) +{ + struct cmd_msg *msg; + unsigned int cur_len = 0, rsp_len, offset_num, receive_len; + u32 value, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + if (!data) + return -1; + + offset_num = cnt / ((cap->InbandPacketMaxLen - sizeof(offset)) / 4); + + if (cnt % ((cap->InbandPacketMaxLen - sizeof(offset)) / 4)) + rsp_len = sizeof(offset) * (offset_num + 1) + 4 * cnt; + else + rsp_len = sizeof(offset) * offset_num + 4 * cnt; + + while (cur_len < rsp_len) { + receive_len = (rsp_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen + : (rsp_len - cur_len); + + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_BURST_READ, TRUE, 0, TRUE, TRUE, receive_len, + (char *)(&data[cur_index]), andes_burst_read_callback); + + value = cpu2le32(offset + cap->WlanMemmapOffset + cur_index * 4); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = cpu2le32((receive_len - 4) / 4); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + + if (ret) { + if (cnt == 1) + *data = 0xffffffff; + } + + cur_index += ((receive_len - 4) / 4); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +static void andes_random_read_callback(struct cmd_msg *msg, char *rsp_payload, u16 rsp_payload_len) +{ + u32 i; + RTMP_REG_PAIR *reg_pair = (RTMP_REG_PAIR *)msg->rsp_payload; + + for (i = 0; i < msg->rsp_payload_len / 8; i++) { + NdisMoveMemory(®_pair[i].Value, rsp_payload + 8 * i + 4, 4); + reg_pair[i].Value = le2cpu32(reg_pair[i].Value); + } +} + +int andes_random_read(RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, u32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, receive_len; + u32 i, value, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + receive_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen + : (var_len - cur_len); + + msg = andes_alloc_cmd_msg(ad, receive_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_RANDOM_READ, TRUE, 0, TRUE, TRUE, receive_len, + (char *)®_pair[cur_index], andes_random_read_callback); + + for (i = 0; i < receive_len / 8; i++) { + value = cpu2le32(reg_pair[i + cur_index].Register + cap->WlanMemmapOffset); + andes_append_cmd_msg(msg, (char *)&value, 4); + value = 0; + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + + ret = andes_send_cmd_msg(ad, msg); + + + cur_index += receive_len / 8; + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +static void andes_rf_random_read_callback(struct cmd_msg *msg, char *rsp_payload, u16 rsp_payload_len) +{ + u32 i; + BANK_RF_REG_PAIR *reg_pair = (BANK_RF_REG_PAIR *)msg->rsp_payload; + + for (i = 0; i < msg->rsp_payload_len / 8; i++) { + NdisMoveMemory(®_pair[i].Value, rsp_payload + 8 * i + 4, 1); + } +} + +int andes_rf_random_read(RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *reg_pair, u32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, receive_len; + u32 i, value, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + receive_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen + : (var_len - cur_len); + + msg = andes_alloc_cmd_msg(ad, receive_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_RANDOM_READ, TRUE, 0, TRUE, TRUE, receive_len, + (char *)®_pair[cur_index], andes_rf_random_read_callback); + + for (i = 0; i < (receive_len) / 8; i++) + { + value = 0; + + /* RF selection */ + value = (value & ~0x80000000) | 0x80000000; + + /* RF bank */ + value = (value & ~0x00ff0000) | (reg_pair[i + cur_index].Bank << 16); + + /* RF Index */ + value = (value & ~0x0000ffff) | reg_pair[i + cur_index].Register; + + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + value = 0; + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + + + cur_index += receive_len / 8; + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +int andes_read_modify_write(RTMP_ADAPTER *ad, R_M_W_REG *reg_pair, u32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 12, cur_len = 0, sent_len; + u32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = andes_alloc_cmd_msg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + andes_init_cmd_msg(msg, CMD_READ_MODIFY_WRITE, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + andes_init_cmd_msg(msg, CMD_READ_MODIFY_WRITE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 12); i++) + { + /* Address */ + value = cpu2le32(reg_pair[i + cur_index].Register + cap->WlanMemmapOffset); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* ClearBitMask */ + value = cpu2le32(reg_pair[i + cur_index].ClearBitMask); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* UpdateData */ + value = cpu2le32(reg_pair[i + cur_index].Value); + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + + + cur_index += (sent_len / 12); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +int andes_rf_read_modify_write(RTMP_ADAPTER *ad, RF_R_M_W_REG *reg_pair, u32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 12, cur_len = 0, sent_len; + u32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = andes_alloc_cmd_msg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + andes_init_cmd_msg(msg, CMD_READ_MODIFY_WRITE, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + andes_init_cmd_msg(msg, CMD_READ_MODIFY_WRITE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < sent_len / 12; i++) + { + value = 0; + /* RF selection */ + value = (value & ~0x80000000) | 0x80000000; + + /* RF bank */ + value = (value & ~0x00ff0000) | (reg_pair[i + cur_index].Bank << 16); + + /* RF Index */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Register; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = 0; + /* ClearBitMask */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].ClearBitMask; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = 0; + /* UpdateData */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Value; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + + cur_index += (sent_len / 12); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +int andes_random_write(RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, u32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, sent_len; + u32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = andes_alloc_cmd_msg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + andes_init_cmd_msg(msg, CMD_RANDOM_WRITE, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + andes_init_cmd_msg(msg, CMD_RANDOM_WRITE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 8); i++) + { + /* Address */ + value = cpu2le32(reg_pair[i + cur_index].Register + cap->WlanMemmapOffset); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* UpdateData */ + value = cpu2le32(reg_pair[i + cur_index].Value); + andes_append_cmd_msg(msg, (char *)&value, 4); + }; + + ret = andes_send_cmd_msg(ad, msg); + + + cur_index += (sent_len / 8); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +int andes_rf_random_write(RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *reg_pair, u32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, sent_len; + u32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = andes_alloc_cmd_msg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + andes_init_cmd_msg(msg, CMD_RANDOM_WRITE, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + andes_init_cmd_msg(msg, CMD_RANDOM_WRITE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 8); i++) { + value = 0; + /* RF selection */ + value = (value & ~0x80000000) | 0x80000000; + + /* RF bank */ + value = (value & ~0x00ff0000) | (reg_pair[i + cur_index].Bank << 16); + + /* RF Index */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Register; + + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = 0; + /* UpdateData */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Value; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + + + cur_index += (sent_len / 8); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + +int andes_sc_random_write(RTMP_ADAPTER *ad, CR_REG *table, u32 nums, u32 flags) +{ + u32 varlen = 0, i, j; + RTMP_REG_PAIR *sw_ch_table = NULL, temp; + + if (!table) + return -1; + + for (i = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + varlen += sizeof(RTMP_REG_PAIR); + } + } + + os_alloc_mem(NULL, (UCHAR **)&sw_ch_table, varlen); + + if (!sw_ch_table) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: memory is not available for allocating switch channel table\n", __FUNCTION__)); + return -1; + } + + for (i = 0, j = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + temp.Register = table[i].offset; + temp.Value = table[i].value; + NdisMoveMemory(&sw_ch_table[j], &temp, sizeof(temp)); + j++; + } + } + + andes_random_write(ad, sw_ch_table, varlen / sizeof(RTMP_REG_PAIR)); + + os_free_mem(NULL, sw_ch_table); + + return 0; +} + +int andes_sc_rf_random_write(RTMP_ADAPTER *ad, BANK_RF_CR_REG *table, u32 nums, u32 flags) +{ + u32 varlen = 0, i, j; + BANK_RF_REG_PAIR *sw_ch_table = NULL, temp; + + if (!table) + return -1; + + for (i = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + varlen += sizeof(BANK_RF_REG_PAIR); + } + } + + os_alloc_mem(NULL, (UCHAR **)&sw_ch_table, varlen); + + if (!sw_ch_table) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: memory is not available for allocating switch channel table\n", __FUNCTION__)); + return -1; + } + + for (i = 0, j = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + temp.Bank = table[i].bank; + temp.Register = table[i].offset; + temp.Value = table[i].value; + NdisMoveMemory(&sw_ch_table[j], &temp, sizeof(temp)); + j++; + } + } + + andes_rf_random_write(ad, sw_ch_table, varlen / sizeof(BANK_RF_REG_PAIR)); + + os_free_mem(NULL, sw_ch_table); + + return 0; +} + + +int andes_pwr_saving(RTMP_ADAPTER *ad, u32 op, u32 level, + u32 listen_interval, u32 pre_tbtt_lead_time, + u8 tim_byte_offset, u8 tim_byte_pattern) +{ + struct cmd_msg *msg; + unsigned int var_len; + u32 value; + int ret = 0; + BOOLEAN need_wait = FALSE; + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI + need_wait = TRUE; +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_STA_SUPPORT */ + + /* Power operation and Power Level */ + var_len = 8; + + if (op == RADIO_OFF_ADVANCE_PWR_SAVING) + { + /* Listen interval, Pre-TBTT, TIM info */ + var_len += 12; + } + + msg = andes_alloc_cmd_msg(ad, var_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_POWER_SAVING_OP, need_wait, 0, FALSE, FALSE, 0, NULL, NULL); + + /* Power operation */ + value = cpu2le32(op); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* Power Level */ + value = cpu2le32(level); + + andes_append_cmd_msg(msg, (char *)&value, 4); + + if (op == RADIO_OFF_ADVANCE_PWR_SAVING) + { + /* Listen interval */ + value = cpu2le32(listen_interval); + andes_append_cmd_msg(msg, (char *)&value, 4); + + + /* Pre TBTT lead time */ + value = cpu2le32(pre_tbtt_lead_time); + andes_append_cmd_msg(msg, (char*)&value, 4); + + /* TIM Info */ + value = (value & ~0x000000ff) | tim_byte_pattern; + value = (value & ~0x0000ff00) | (tim_byte_offset << 8); + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + +int andes_fun_set(RTMP_ADAPTER *ad, u32 fun_id, u32 param) +{ + struct cmd_msg *msg; + u32 value; + int ret = 0; + + /* Function ID and Parameter */ + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (fun_id != Q_SELECT +#ifdef BTCOEX_CONCURRENT + && fun_id != 11 +#endif + ) + andes_init_cmd_msg(msg, CMD_FUN_SET_OP, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + andes_init_cmd_msg(msg, CMD_FUN_SET_OP, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + /* Function ID */ + value = cpu2le32(fun_id); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* Parameter */ + value = cpu2le32(param); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + + +int andes_calibration(RTMP_ADAPTER *ad, u32 cal_id, ANDES_CALIBRATION_PARAM *param) +{ + struct cmd_msg *msg; + u32 value; + int ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s:cal_id(%d)\n ", __FUNCTION__, cal_id)); + +#ifdef MT76x2 +#ifdef RTMP_PCI_SUPPORT + if (IS_MT76x2(ad) && (cal_id != TSSI_COMPENSATION_7662)) { + ANDES_CALIBRATION_START(ad); + } +#endif /* RTMP_PCI_SUPPORT */ +#endif /* MT76x2 */ + +#ifdef MT76x2 + /* Calibration ID and Parameter */ + if (cal_id == TSSI_COMPENSATION_7662 && IS_MT76x2(ad)) + msg = andes_alloc_cmd_msg(ad, 12); + else +#endif /* MT76x2 */ + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_CALIBRATION_OP, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* Calibration ID */ + value = cpu2le32(cal_id); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* Parameter */ +#ifdef MT76x2 + if (cal_id == TSSI_COMPENSATION_7662 && IS_MT76x2(ad)) { + value = cpu2le32(param->mt76x2_tssi_comp_param.pa_mode); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = cpu2le32(param->mt76x2_tssi_comp_param.tssi_slope_offset); + andes_append_cmd_msg(msg, (char *)&value, 4); + } else +#endif /* MT76x2 */ + { + value = cpu2le32(param->generic); + andes_append_cmd_msg(msg, (char *)&value, 4); + } + + ret = andes_send_cmd_msg(ad, msg); + +#ifdef MT76x2 +#ifdef RTMP_PCI_SUPPORT + if (IS_MT76x2(ad) && ((cal_id != TSSI_COMPENSATION_7662))) { + ANDES_WAIT_CALIBRATION_DONE(ad); + } +#endif /* RTMP_PCI_SUPPORT */ +#endif /* MT76x2 */ + +error: + return ret; +} + +int andes_load_cr(RTMP_ADAPTER *ad, u32 cr_type, UINT8 temp_level, UINT8 channel) +{ + struct cmd_msg *msg; + u32 value = 0; + int ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s:cr_type(%d)\n", __FUNCTION__, cr_type)); + + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_LOAD_CR, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* CR type */ + value &= ~LOAD_CR_MODE_MASK; + value |= LOAD_CR_MODE(cr_type); + + if (cr_type == HL_TEMP_CR_UPDATE) { + value &= ~LOAD_CR_TEMP_LEVEL_MASK; + value |= LOAD_CR_TEMP_LEVEL(temp_level); + + value &= ~LOAD_CR_CHL_MASK; + value |= LOAD_CR_CHL(channel); + } + + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = 0x80000000; + value |= ((ad->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET] >> 8) & 0xFF); + value |= ((ad->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] & 0xFF) << 8 ); + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + +int andes_switch_channel(RTMP_ADAPTER *ad, u8 channel, BOOLEAN scan, unsigned int bw, unsigned int tx_rx_setting, u8 bbp_ch_idx) +{ + struct cmd_msg *msg; + u32 value = 0; + int ret; + + DBGPRINT(RT_DEBUG_INFO, ("%s:channel(%d),scan(%d),bw(%d),trx(0x%x)\n", __FUNCTION__, channel, scan, bw, tx_rx_setting)); + + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_SWITCH_CHANNEL_OP, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* + * switch channel related param + * channel, scan, bw, tx_rx_setting + */ + value &= ~SC_PARAM1_CHL_MASK; + value |= SC_PARAM1_CHL(channel); + value &= ~SC_PARAM1_SCAN_MASK; + value |= SC_PARAM1_SCAN(scan); + value &= ~SC_PARAM1_BW_MASK; + value |= SC_PARAM1_BW(bw); + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = 0; + value |= SC_PARAM2_TR_SETTING(tx_rx_setting); + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + + mdelay(5); + + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_SWITCH_CHANNEL_OP, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* + * switch channel related param + * channel, scan, bw, tx_rx_setting, extension channel + */ + value &= ~SC_PARAM1_CHL_MASK; + value |= SC_PARAM1_CHL(channel); + value &= ~SC_PARAM1_SCAN_MASK; + value |= SC_PARAM1_SCAN(scan); + value &= ~SC_PARAM1_BW_MASK; + value |= SC_PARAM1_BW(bw); + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + value = 0; + value |= SC_PARAM2_TR_SETTING(tx_rx_setting); + value &= ~SC_PARAM2_EXTENSION_CHL_MASK; + + if (bbp_ch_idx == 0) + value |= SC_PARAM2_EXTENSION_CHL(0xe0); + else if (bbp_ch_idx == 1) + value |= SC_PARAM2_EXTENSION_CHL(0xe1); + else if (bbp_ch_idx == 2) + value |= SC_PARAM2_EXTENSION_CHL(0xe2); + else if (bbp_ch_idx == 3) + value |= SC_PARAM2_EXTENSION_CHL(0xe3); + + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + +int andes_init_gain(RTMP_ADAPTER *ad, UINT8 channel, BOOLEAN force_mode, unsigned int gain_from_e2p) +{ + struct cmd_msg *msg; + u32 value = 0; + int ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s:channel(%d), force mode(%d), init gain parameter(0x%08x)\n", + __FUNCTION__, channel, force_mode, gain_from_e2p)); + + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_INIT_GAIN_OP, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* init gain parameter#1 */ + if (force_mode == TRUE) + value = 0x80000000; + + value |= channel; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* init gain parameter#2 while force mode is enabled */ + value = gain_from_e2p; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + +int andes_dynamic_vga(RTMP_ADAPTER *ad, UINT8 channel, BOOLEAN mode, BOOLEAN ext, int rssi, unsigned int false_cca) +{ + struct cmd_msg *msg; + u32 value = 0; + int rssi_val = 0, ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s:channel(%d), ap/sta mode(%d), extension(%d), rssi(%d), false cca count(%d)\n", + __FUNCTION__, channel, mode, ext, rssi, false_cca)); + + msg = andes_alloc_cmd_msg(ad, 12); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_DYNC_VGA_OP, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* dynamic VGA parameter#1: TRUE = AP mode ; FALSE = STA mode */ + if (mode == TRUE) + value |= 0x80000000; + + if (ext == TRUE) + value |= 0x40000000; + + if (ad->ed_chk == TRUE) + value |= 0x20000000; + + value |= channel; + value = cpu2le32(value); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* dynamic VGA parameter#2: RSSI (signed value) */ + rssi_val = cpu2le32(rssi); + andes_append_cmd_msg(msg, (char *)&rssi_val, 4); + + /* dynamic VGA parameter#3: false CCA count */ + value = cpu2le32(false_cca); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + +int andes_led_op(RTMP_ADAPTER *ad, u32 led_idx, u32 link_status) +{ + struct cmd_msg *msg; + u32 value = 0; + int ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s:led_idx(%d), link_status(%d)\n ", + __FUNCTION__, led_idx, link_status)); + + msg = andes_alloc_cmd_msg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + andes_init_cmd_msg(msg, CMD_LED_MODE_OP, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + /* Led index */ + value = cpu2le32(led_idx); + andes_append_cmd_msg(msg, (char *)&value, 4); + + /* Link status */ + value = cpu2le32(link_status); + andes_append_cmd_msg(msg, (char *)&value, 4); + + ret = andes_send_cmd_msg(ad, msg); + +error: + return ret; +} + + +#ifdef RTMP_PCI_SUPPORT +void andes_pci_fw_init(RTMP_ADAPTER *ad) +{ + u32 value; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + /* Enable Interrupt*/ + RTMP_IRQ_ENABLE(ad); + RTMPEnableRxTx(ad); + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_START_UP); + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + /* clear garbage interrupts*/ + RTMP_IO_READ32(ad, 0x1300, &value); + if (value) { + DBGPRINT(RT_DEBUG_OFF, ("0x1300 = %08x\n", value)); + } + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(ad, HEADER_TRANS_CTRL_REG, 0X2); + RTMP_IO_WRITE32(ad, TSO_CTRL, 0x7050); +#else + RTMP_IO_WRITE32(ad, HEADER_TRANS_CTRL_REG, 0x0); + RTMP_IO_WRITE32(ad, TSO_CTRL, 0x0); +#endif + + andes_fun_set(ad, Q_SELECT, ad->chipCap.CmdRspRxRing); + PWR_SAVING_OP(ad, RADIO_ON, 0, 0, 0, 0, 0); +} +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef BTCOEX_CONCURRENT +void MT7662ReceCoexFromOtherCHip( + IN UCHAR channel, + IN UCHAR centralchannel, + IN UCHAR channel_bw + ) +{ + CoexChannel = channel; + CoexCenctralChannel=centralchannel; + CoexChannelBw=channel_bw; + + DBGPRINT(RT_DEBUG_TRACE, ("-->MT7662ReceCoexFromOtherCHip channel=%d centralchannel=%d channel_bw=%d\n",CoexChannel, CoexCenctralChannel, CoexChannelBw)); + +} +EXPORT_SYMBOL(MT7662ReceCoexFromOtherCHip); +#endif diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_dev.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_dev.c new file mode 100644 index 000000000..162dda027 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_dev.c @@ -0,0 +1,87 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +struct wifi_dev *get_wdev_by_idx(RTMP_ADAPTER *pAd, INT idx) +{ + struct wifi_dev *wdev = NULL; + + do + { + + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (idx >= MIN_NET_DEVICE_FOR_APCLI) + { + idx -= MIN_NET_DEVICE_FOR_APCLI; + if (idx < MAX_APCLI_NUM) + { + wdev = &pAd->ApCfg.ApCliTab[idx].wdev; + break; + } + } +#endif /* APCLI_SUPPORT */ + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + +#ifdef WDS_SUPPORT + if (idx >= MIN_NET_DEVICE_FOR_WDS) + { + idx -= MIN_NET_DEVICE_FOR_WDS; + if (idx < MAX_WDS_ENTRY) + { + wdev = &&pAd->WdsTab.WdsEntry[idx].wdev; + break; + } + } +#endif /* WDS_SUPPORT */ + if ((idx < pAd->ApCfg.BssidNum) && (idx < MAX_MBSSID_NUM(pAd)) && (idx < HW_BEACON_MAX_NUM)) + wdev = &pAd->ApCfg.MBSSID[idx].wdev; + + break; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + wdev = &pAd->StaCfg.wdev; + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while (FALSE); + + if (wdev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid idx(%d)\n", idx)); + } + + return wdev; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_entrytb.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_entrytb.c new file mode 100644 index 000000000..c4cf66dba --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_entrytb.c @@ -0,0 +1,1406 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include + + +// TODO: this function not finish yet!! +VOID mgmt_tb_set_mcast_entry(RTMP_ADAPTER *pAd) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; + + pEntry->EntryType = ENTRY_WDEV; + pEntry->Sst = SST_ASSOC; + pEntry->Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index*/ + pEntry->wcid = MCAST_WCID; + pEntry->PsMode = PWR_ACTIVE; + pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd){ + pEntry->wdev = &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd){ + pEntry->wdev = &pAd->StaCfg.wdev; + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID set_entry_phy_cfg(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } +} + + +/* + ========================================================================== + Description: + Look up the MAC address in the MAC table. Return NULL if not found. + Return: + pEntry - pointer to the MAC entry; NULL is not found + ========================================================================== +*/ +MAC_TABLE_ENTRY *MacTableLookup(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + ULONG HashIdx; + MAC_TABLE_ENTRY *pEntry = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry && !IS_ENTRY_NONE(pEntry)) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + break; + else + pEntry = pEntry->pNext; + } + + return pEntry; +} + + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN StaUpdateMacTableEntry( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR MaxSupportedRateIn500Kbps, + IN HT_CAPABILITY_IE *ht_cap, + IN UCHAR htcap_len, + IN ADD_HT_INFO_IE *pAddHtInfo, + IN UCHAR AddHtInfoLen, + IN IE_LISTS *ie_list, + IN USHORT cap_info) +{ + UCHAR MaxSupportedRate = RATE_11; + BOOLEAN bSupportN = FALSE; +#ifdef TXBF_SUPPORT + BOOLEAN supportsETxBf = FALSE; +#endif + struct wifi_dev *wdev; + + if (!pEntry) + return FALSE; + + if (ADHOC_ON(pAd)) + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_G) + && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) + return FALSE; + +#ifdef DOT11_N_SUPPORT + /* 11n only */ + if (WMODE_HT_ONLY(pAd->CommonCfg.PhyMode) + && (htcap_len == 0)) + return FALSE; +#endif /* DOT11_N_SUPPORT */ + + NdisAcquireSpinLock(&pAd->MacTabLock); + if (pEntry) { + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) || + WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) { + pEntry->RateLen = 4; + if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE) + MaxSupportedRate = RATE_11; + } else + pEntry->RateLen = 12; + + pEntry->MaxHTPhyMode.word = 0; + pEntry->MinHTPhyMode.word = 0; + pEntry->HTPhyMode.word = 0; + pEntry->MaxSupportedRate = MaxSupportedRate; + + set_entry_phy_cfg(pAd, pEntry); + + pEntry->CapabilityInfo = cap_info; + pEntry->isCached = FALSE; + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + } + + wdev = &pAd->StaCfg.wdev; +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pEntry->HTCapability, sizeof (pEntry->HTCapability)); + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (((wdev->WepStatus != Ndis802_11WEPEnabled) + && (wdev->WepStatus != Ndis802_11TKIPEnable)) + || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) { + if ((pAd->StaCfg.BssType == BSS_INFRA) && + (htcap_len != 0) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + bSupportN = TRUE; + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->StaCfg.bAdhocN == TRUE) && + (htcap_len != 0) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + bSupportN = TRUE; + } + + if (bSupportN) { + if (ADHOC_ON(pAd)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + ht_mode_adjust(pAd, pEntry, ht_cap, &pAd->CommonCfg.DesiredHtPhy); + +#ifdef TXBF_SUPPORT +#ifdef VHT_TXBF_SUPPORT + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (ie_list->vht_cap_len)) + { + supportsETxBf = clientSupportsVHTETxBF(pAd, &ie_list->vht_cap.vht_cap); + DBGPRINT(RT_DEBUG_TRACE, ("%s : VHT mode!\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_TRACE, ("AP Bfee Cap =%d, AP Bfer Cap =%d!\n", + ie_list->vht_cap.vht_cap.bfee_cap_su , ie_list->vht_cap.vht_cap.bfer_cap_su)); + } + else +#endif /* VHT_TXBF_SUPPORT */ + supportsETxBf = clientSupportsETxBF(pAd, &ht_cap->TxBFCap); +#endif /* TXBF_SUPPORT */ + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], &ht_cap->MCSSet[0]); + + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + + pEntry->MaxHTPhyMode.field.STBC = (ht_cap->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = ht_cap->HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = ht_cap->HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR) ht_cap->HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR) ht_cap->HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable + && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + if (ht_cap->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (ht_cap->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (ht_cap->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (ht_cap->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (ht_cap->ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg + && ht_cap->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (ht_cap->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + NdisMoveMemory(&pEntry->HTCapability, ht_cap, htcap_len); + + assoc_ht_info_debugshow(pAd, pEntry, htcap_len, ht_cap); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (ie_list != NULL) && (ie_list->vht_cap_len) && (ie_list->vht_op_len)) + { + vht_mode_adjust(pAd, pEntry, &ie_list->vht_cap, &ie_list->vht_op); + assoc_vht_info_debugshow(pAd, pEntry, &ie_list->vht_cap, &ie_list->vht_op); + NdisMoveMemory(&pEntry->vht_cap_ie, &ie_list->vht_cap, sizeof(VHT_CAP_IE)); + } +#endif /* DOT11_VHT_AC */ + } else { + pAd->MacTab.fAnyStationIsLegacy = TRUE; + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + +#ifdef MFB_SUPPORT + pEntry->lastLegalMfb = 0; + pEntry->isMfbChanged = FALSE; + pEntry->fLastChangeAccordingMfb = FALSE; + + pEntry->toTxMrq = TRUE; + pEntry->msiToTx = 0; /* has to increment whenever a mrq is sent */ + pEntry->mrqCnt = 0; + + pEntry->pendingMfsi = 0; + + pEntry->toTxMfb = FALSE; + pEntry->mfbToTx = 0; + pEntry->mfb0 = 0; + pEntry->mfb1 = 0; +#endif /* MFB_SUPPORT */ + + pEntry->freqOffsetValid = FALSE; + +#ifdef TXBF_SUPPORT + TxBFInit(pAd, pEntry, supportsETxBf); + + RTMPInitTimer(pAd, &pEntry->eTxBfProbeTimer, GET_TIMER_FUNCTION(eTxBfProbeTimerExec), pEntry, FALSE); + NdisAllocateSpinLock(pAd, &pEntry->TxSndgLock); +#endif /* TXBF_SUPPORT */ + + MlmeRAInit(pAd, pEntry); + + /* Set asic auto fall back */ + if (wdev->bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = wdev->HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->Sst = SST_ASSOC; + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->AuthMode = wdev->AuthMode; + pEntry->WepStatus = wdev->WepStatus; + pEntry->wdev = wdev; + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) { + pEntry->WpaState = AS_NOTUSE; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } else { + pEntry->WpaState = AS_INITPSK; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + + if (pAd->StaCfg.BssType == BSS_INFRA) { + UCHAR HashIdx = 0; + MAC_TABLE_ENTRY *pCurrEntry = NULL; + HashIdx = MAC_ADDR_HASH_INDEX(pAd->MlmeAux.Bssid); + if (pAd->MacTab.Hash[HashIdx] == NULL) { + pAd->MacTab.Hash[HashIdx] = pEntry; + } else { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) { + pCurrEntry = pCurrEntry->pNext; + } + pCurrEntry->pNext = pEntry; + } + RTMPMoveMemory(pEntry->Addr, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + pEntry->Aid = BSSID_WCID; + pEntry->wcid = BSSID_WCID; + +#ifdef RT_CFG80211_P2P_SUPPORT + { + pAd->cfg80211_ctrl.MyGOwcid = BSSID_WCID; + } +#endif /* RT_CFG80211_P2P_SUPPORT */ + + pEntry->pAd = pAd; + SET_ENTRY_CLIENT(pEntry); + pAd->MacTab.Size ++; + } + +#ifdef DOT11W_PMF_SUPPORT + RTMPInitTimer(pAd, &pEntry->SAQueryTimer, GET_TIMER_FUNCTION(PMF_SAQueryTimeOut), pEntry, FALSE); + RTMPInitTimer(pAd, &pEntry->SAQueryConfirmTimer, GET_TIMER_FUNCTION(PMF_SAQueryConfirmTimeOut), pEntry, FALSE); +#endif /* DOT11W_PMF_SUPPORT */ + NdisReleaseSpinLock(&pAd->MacTabLock); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) { + SendAssocIEsToWpaSupplicant(pAd->net_dev, pAd->StaCfg.ReqVarIEs, + pAd->StaCfg.ReqVarIELen); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, + RT_ASSOC_EVENT_FLAG, NULL, NULL, 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + wext_notify_event_assoc(pAd->net_dev, pAd->StaCfg.ReqVarIEs, + pAd->StaCfg.ReqVarIELen); + + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CGIWAP, -1, + pAd->MlmeAux.Bssid, NULL, 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + + + return TRUE; +} +#endif /* CONFIG_STA_SUPPORT */ + + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN struct wifi_dev *wdev, + IN UCHAR apidx, + IN UCHAR OpMode, + IN BOOLEAN CleanAll) +{ + UCHAR HashIdx; + int i, FirstWcid; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + BOOLEAN Cancelled; + + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + FirstWcid = 1; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + if (pAd->StaCfg.BssType == BSS_INFRA) + FirstWcid = 2; +#endif /* CONFIG_STA_SUPPORT */ + + /* allocate one MAC entry*/ + NdisAcquireSpinLock(&pAd->MacTabLock); + for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup*/ + { + /* pick up the first available vacancy*/ + if (IS_ENTRY_NONE(&pAd->MacTab.Content[i])) + { + pEntry = &pAd->MacTab.Content[i]; + + /* ENTRY PREEMPTION: initialize the entry */ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); +#ifdef DOT11W_PMF_SUPPORT + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef FIFO_EXT_SUPPORT + UCHAR hwFifoExtIdx = 0; + BOOLEAN bUseHwFifoExt = FALSE; + + hwFifoExtIdx = pEntry->hwFifoExtIdx; + bUseHwFifoExt = pEntry->bUseHwFifoExt; +#endif /* FIFO_EXT_SUPPORT */ + + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + +#ifdef FIFO_EXT_SUPPORT + pEntry->hwFifoExtIdx = hwFifoExtIdx; + pEntry->bUseHwFifoExt = bUseHwFifoExt; +#endif /* FIFO_EXT_SUPPORT */ + + if (CleanAll == TRUE) + { + pEntry->MaxSupportedRate = RATE_11; + pEntry->CurrTxRate = RATE_11; + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); +#ifdef FIFO_EXT_SUPPORT + pEntry->hwFifoExtIdx = hwFifoExtIdx; + pEntry->bUseHwFifoExt = bUseHwFifoExt; +#endif /* FIFO_EXT_SUPPORT */ + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + } + + do + { +#ifdef CONFIG_STA_SUPPORT +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (apidx >= MIN_NET_DEVICE_FOR_TDLS) + { + SET_ENTRY_TDLS(pEntry); + break; + } + else +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ +#ifdef QOS_DLS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_DLS) + { + SET_ENTRY_DLS(pEntry); + break; + } + else +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + SET_ENTRY_APCLI(pEntry); + break; + } +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + SET_ENTRY_WDS(pEntry); + break; + } +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { /* be a regular-entry*/ + if ((apidx < pAd->ApCfg.BssidNum) && + (apidx < MAX_MBSSID_NUM(pAd)) && + ((apidx < HW_BEACON_MAX_NUM)) && + (pAd->ApCfg.MBSSID[apidx].MaxStaNum != 0) && + (pAd->ApCfg.MBSSID[apidx].StaCount >= pAd->ApCfg.MBSSID[apidx].MaxStaNum)) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: The connection table is full in ra%d.\n", __FUNCTION__, apidx)); + NdisReleaseSpinLock(&pAd->MacTabLock); + return NULL; + } + } +#endif /* CONFIG_AP_SUPPORT */ + SET_ENTRY_CLIENT(pEntry); + +#ifdef IWSC_SUPPORT +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry->bIWscSmpbcAccept = FALSE; + pEntry->bUpdateInfoFromPeerBeacon = FALSE; + } +#endif /* CONFIG_STA_SUPPORT */ +#endif // IWSC_SUPPORT // + } while (FALSE); + + pEntry->wdev = wdev; + pEntry->wcid = i; + pEntry->isCached = FALSE; + pEntry->bIAmBadAtheros = FALSE; + + RTMPInitTimer(pAd, &pEntry->EnqueueStartForPSKTimer, GET_TIMER_FUNCTION(EnqueueStartForPSKExec), pEntry, FALSE); + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPInitTimer(pAd, &pEntry->WPA_Authenticator.MsgRetryTimer, GET_TIMER_FUNCTION(Adhoc_WpaRetryExec), pEntry, FALSE); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (IS_ENTRY_CLIENT(pEntry)) /* Only Client entry need the retry timer.*/ + { + RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE); +#ifdef DOT11W_PMF_SUPPORT + RTMPInitTimer(pAd, &pEntry->SAQueryTimer, GET_TIMER_FUNCTION(PMF_SAQueryTimeOut), pEntry, FALSE); + RTMPInitTimer(pAd, &pEntry->SAQueryConfirmTimer, GET_TIMER_FUNCTION(PMF_SAQueryConfirmTimeOut), pEntry, FALSE); +#endif /* DOT11W_PMF_SUPPORT */ + + /* RTMP_OS_Init_Timer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pAd);*/ + } +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + RTMPInitTimer(pAd, &pEntry->eTxBfProbeTimer, GET_TIMER_FUNCTION(eTxBfProbeTimerExec), pEntry, FALSE); +#endif /* TXBF_SUPPORT */ + + pEntry->pAd = pAd; + pEntry->CMTimerRunning = FALSE; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + pEntry->RSNIE_Len = 0; + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pEntry->AllowInsPTK = TRUE; + + if (IS_ENTRY_MESH(pEntry)) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); +#ifdef CONFIG_AP_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); + else if (IS_ENTRY_WDS(pEntry)) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + else if (IS_ENTRY_DLS(pEntry)) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS); +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + else if (IS_ENTRY_TDLS(pEntry)) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_TDLS); +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ +#endif /* CONFIG_STA_SUPPORT */ + else + pEntry->apidx = apidx; + +#ifdef CONFIG_AP_SUPPORT + if ((apidx < pAd->ApCfg.BssidNum) && + (apidx < MAX_MBSSID_NUM(pAd)) && + (apidx < HW_BEACON_MAX_NUM)) + pEntry->pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + else + pEntry->pMbss = NULL; +#endif /* CONFIG_AP_SUPPORT */ + + do + { + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + pEntry->AuthMode = pAd->ApCfg.ApCliTab[pEntry->apidx].wdev.AuthMode; + pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->apidx].wdev.WepStatus; + pEntry->wdev_idx = pEntry->apidx; + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + { + pEntry->WpaState = AS_NOTUSE; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + else + { + pEntry->WpaState = AS_PTKSTART; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + break; + } +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry)) + { + pEntry->AuthMode = Ndis802_11AuthModeOpen; + pEntry->WepStatus = Ndis802_11EncryptionDisabled; + + pEntry->wdev_idx = pEntry->apidx; + break; + } +#endif /* WDS_SUPPORT */ +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) +#ifdef RT_CFG80211_P2P_SUPPORT + if (pEntry->wdev->wdev_type == WDEV_TYPE_AP) +#else + if (OpMode == OPMODE_AP) +#endif /* RT_CFG80211_P2P_SUPPORT */ +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { + MBSS_MR_APIDX_SANITY_CHECK(pAd, apidx); + pEntry->AuthMode = pAd->ApCfg.MBSSID[apidx].wdev.AuthMode; + pEntry->WepStatus = pAd->ApCfg.MBSSID[apidx].wdev.WepStatus; + pEntry->GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; + pEntry->wdev_idx = pEntry->apidx; + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + pEntry->WpaState = AS_NOTUSE; + else + pEntry->WpaState = AS_INITIALIZE; + + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->StaIdleTimeout = pAd->ApCfg.StaIdleTimeout; + pAd->ApCfg.MBSSID[apidx].StaCount++; + pAd->ApCfg.EntryClientCount++; + break; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (OpMode == OPMODE_STA) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { + pEntry->AuthMode = pAd->StaCfg.wdev.AuthMode; + pEntry->WepStatus = pAd->StaCfg.wdev.WepStatus; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } +#endif /* CONFIG_STA_SUPPORT */ + } while (FALSE); + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (IS_ENTRY_DLS(pEntry)) + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + else +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + COPY_MAC_ADDR(pEntry->Addr, pAddr); + + if (IS_ENTRY_TDLS(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("#########SET_ENTRY_TDLS pEntry->mac %02x:%02x:%02x:%02x:%02x:%02x \n",PRINT_MAC(pEntry->Addr))); //Kyle Debug + } + + do + { +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + COPY_MAC_ADDR(pEntry->bssid, pAddr); + break; + } +#endif // APCLI_SUPPORT // +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry)) + { + COPY_MAC_ADDR(pEntry->bssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.bssid); + break; + } +#endif // WDS_SUPPORT // +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { + COPY_MAC_ADDR(pEntry->bssid, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + break; + } +#endif // CONFIG_AP_SUPPORT // +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + COPY_MAC_ADDR(pEntry->bssid, pAddr); + break; + } +#endif // CONFIG_STA_SUPPORT // + } while (FALSE); + + pEntry->Sst = SST_NOT_AUTH; + pEntry->AuthState = AS_NOT_AUTH; + pEntry->Aid = (USHORT)i; + pEntry->CapabilityInfo = 0; + pEntry->PsMode = PWR_ACTIVE; + pEntry->PsQIdleCount = 0; + pEntry->NoDataIdleCount = 0; + pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; + pEntry->ContinueTxFailCnt = 0; + pEntry->StatTxRetryOkCount = 0; + pEntry->StatTxFailCount = 0; + { + int tid; + for (tid=0; tidTxBarSeq[tid] = -1; + } +#ifdef WDS_SUPPORT + pEntry->LockEntryTx = FALSE; +#endif /* WDS_SUPPORT */ + pEntry->TimeStamp_toTxRing = 0; + InitializeQueueHeader(&pEntry->PsQueue); + +#ifdef PS_ENTRY_MAITENANCE + pEntry->continuous_ps_count = 0; +#endif /* PS_ENTRY_MAITENANCE */ + +#ifdef STREAM_MODE_SUPPORT + /* Enable Stream mode for first three entries in MAC table */ + +#endif /* STREAM_MODE_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + /* init U-APSD enhancement related parameters */ + UAPSD_MR_ENTRY_INIT(pEntry); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */ + { +#ifdef UAPSD_SUPPORT + if (IS_ENTRY_CLIENT(pEntry)) /* Ralink WDS doesn't support any power saving.*/ + { + /* init U-APSD enhancement related parameters */ + UAPSD_MR_ENTRY_INIT(pEntry); + } +#endif /* UAPSD_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + pAd->MacTab.Size ++; + + /* Set the security mode of this entry as OPEN-NONE in ASIC */ + RTMP_REMOVE_PAIRWISE_KEY_ENTRY(pAd, (UCHAR)i); + + /* Add this entry into ASIC RX WCID search table */ + RTMP_STA_ENTRY_ADD(pAd, pEntry); + +#ifdef PEER_DELBA_TX_ADAPT + Peer_DelBA_Tx_Adapt_Init(pAd, pEntry); +#endif /* PEER_DELBA_TX_ADAPT */ + +#ifdef DROP_MASK_SUPPORT + drop_mask_init_per_client(pAd, pEntry); +#endif /* DROP_MASK_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WSC_AP_SUPPORT + pEntry->bWscCapable = FALSE; + pEntry->Receive_EapolStart_EapRspId = 0; +#endif /* WSC_AP_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + NdisAllocateSpinLock(pAd, &pEntry->TxSndgLock); +#endif /* TXBF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): alloc entry #%d, Total= %d\n", + __FUNCTION__, i, pAd->MacTab.Size)); + break; + } + } + + /* add this MAC entry into HASH table */ + if (pEntry) + { +#ifdef IWSC_SUPPORT + PWSC_PEER_ENTRY pWscPeerEntry = NULL; +#endif /* IWSC_SUPPORT */ + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + if (pAd->MacTab.Hash[HashIdx] == NULL) + pAd->MacTab.Hash[HashIdx] = pEntry; + else + { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DOT11V_WNM_SUPPORT + pEntry->Beclone = FALSE; + pEntry->bBSSMantSTASupport = FALSE; + pEntry->bDMSSTASupport = FALSE; +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef WSC_AP_SUPPORT + if (IS_ENTRY_CLIENT(pEntry) && + (pEntry->apidx < pAd->ApCfg.BssidNum) && + MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr)) + { + NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, MAC_ADDR_LEN); + } +#endif /* WSC_AP_SUPPORT */ + + +#ifdef CONFIG_WIFI_PKT_FWD + if(IS_ENTRY_CLIENT(pEntry) && + wf_fwd_add_entry_inform_hook) + { + wf_fwd_add_entry_inform_hook(pEntry->Addr); + } +#endif /* CONFIG_WIFI_PKT_FWD */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + pWscPeerEntry = WscFindPeerEntry(&pAd->StaCfg.WscControl.WscPeerList, pEntry->Addr); + if (pWscPeerEntry && pWscPeerEntry->bIWscSmpbcAccept) + IWSC_AddSmpbcEnrollee(pAd, pEntry->Addr); + } +#endif /* IWSC_SUPPORT */ + + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef MULTI_CLIENT_SUPPORT + if (pAd->MacTab.Size < MAX_LEN_OF_MAC_TABLE) + { + USHORT size; + + size = pAd->ApCfg.EntryClientCount; + asic_change_tx_retry(pAd, size); + + pkt_aggr_num_change(pAd, size); + + if (pAd->CommonCfg.bWmm) + asic_tune_be_wmm(pAd, size); + } +#endif /* MULTI_CLIENT_SUPPORT */ +#endif // CONFIG_AP_SUPPORT // + + NdisReleaseSpinLock(&pAd->MacTabLock); + return pEntry; +} + + +/* + ========================================================================== + Description: + Delete a specified client from MAC table + ========================================================================== + */ +BOOLEAN MacTableDeleteEntry(RTMP_ADAPTER *pAd, USHORT wcid, UCHAR *pAddr) +{ + USHORT HashIdx; + MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + BOOLEAN Cancelled; + + if (wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableDelete Entry->wcid=%d\n",wcid)); + + if (pAddr != NULL) + DBGPRINT(RT_DEBUG_TRACE, ("MacTableDelete %02x:%02x:%02x:%02x:%02x:%02x\n",PRINT_MAC(pAddr))); + + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = &pAd->MacTab.Content[wcid]; + + if (pEntry && !IS_ENTRY_NONE(pEntry)) + { +#ifdef SMART_MESH_MONITOR + if(pEntry->MonitorWCID > 0) + UpdateMonitorEntry(pAd,pEntry->MonitorWCID,NULL,TRUE); +#endif /* SMART_MESH_MONITOR */ +#ifdef SMART_MESH + pEntry->bHyperFiPeer = FALSE; + pEntry->bSupportSmartMesh= FALSE; + pEntry->bEnableSmartMesh = FALSE; +#endif /* SMART_MESH */ +#ifdef MWDS + pEntry->bSupportMWDS = FALSE; + pEntry->bEnableMWDS= FALSE; + if(IS_MWDS_OPMODE_AP(pEntry)) + MWDSConnEntryDelete(pAd,pEntry->wcid); + SET_MWDS_OPMODE_NONE(pEntry); +#endif /* MWDS */ +#ifdef CONFIG_WIFI_PKT_FWD + if(wf_fwd_delete_entry_inform_hook) + wf_fwd_delete_entry_inform_hook(pEntry->Addr); +#endif /* CONFIG_WIFI_PKT_FWD */ + + /* ENTRY PREEMPTION: Cancel all timers */ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); +#ifdef DOT11W_PMF_SUPPORT + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); +#endif /* DOT11W_PMF_SUPPORT */ + + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_DOT11V_WNM) + if (pAd->ApCfg.MBSSID[pEntry->apidx].WNMCtrl.ProxyARPEnable) + { + RemoveIPv4ProxyARPEntry(pAd, &pAd->ApCfg.MBSSID[pEntry->apidx], pEntry->Addr); + RemoveIPv6ProxyARPEntry(pAd, &pAd->ApCfg.MBSSID[pEntry->apidx], pEntry->Addr); + } +#endif +#ifdef CONFIG_HOTSPOT_R2 + pEntry->IsKeep = 0; +#endif /* CONFIG_HOTSPOT_R2 */ + + +#ifdef DOT11V_WNM_SUPPORT +#ifdef CONFIG_AP_SUPPORT + DeleteDMSEntry(pAd, pEntry); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pEntry->wcid); +#endif /* DOT11_N_SUPPORT */ + + /* Delete this entry from ASIC on-chip WCID Table*/ + RTMP_STA_ENTRY_MAC_RESET(pAd, wcid); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + RTMPReleaseTimer(&pEntry->eTxBfProbeTimer, &Cancelled); +#endif /* TXBF_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + /* Clear Stream Mode register for this client */ + if (pEntry->StreamModeMACReg != 0) + RTMP_IO_WRITE32(pAd, pEntry->StreamModeMACReg+4, 0); +#endif // STREAM_MODE_SUPPORT // + +#ifdef DOT11W_PMF_SUPPORT + RTMPReleaseTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPReleaseTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPReleaseTimer(&pEntry->WPA_Authenticator.MsgRetryTimer, &Cancelled); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (IS_ENTRY_CLIENT(pEntry) + ) + { +#ifdef DOT1X_SUPPORT + INT PmkCacheIdx = -1; +#endif /* DOT1X_SUPPORT */ +#ifdef CUSTOMER_DCC_FEATURE + if(pEntry->Sst == SST_ASSOC) + { + INT32 i; + INT32 count = pAd->AllowedStaList.StaCount; + BOOLEAN Flag = FALSE; + + for(i = 0; i < count; i++) + { + if(NdisEqualMemory(&pAd->AllowedStaList.AllowedSta[i].MacAddr[0], pAddr , MAC_ADDR_LEN)) + { + pAd->AllowedStaList.AllowedSta[count].DissocTime = jiffies_to_msecs(jiffies); + Flag = TRUE; + } + } + if((!Flag) && (pAd->AllowedStaList.StaCount++ < MAX_LEN_OF_MAC_TABLE)) + { + NdisCopyMemory(&(pAd->AllowedStaList.AllowedSta[count].MacAddr[0]), pEntry->Addr,MAC_ADDR_LEN); + pAd->AllowedStaList.AllowedSta[count].DissocTime = jiffies_to_msecs(jiffies); + pAd->AllowedStaList.StaCount++; + } + } +#endif + + RTMPReleaseTimer(&pEntry->RetryTimer, &Cancelled); + +#ifdef DELAYED_TCP_ACK + RTMPCancelTimer(&pEntry->QueueAckTimer, &Cancelled); + RTMPReleaseTimer(&pEntry->QueueAckTimer, &Cancelled); + pEntry->QueueAckTimerRunning = FALSE; +#endif /* DELAYED_TCP_ACK */ + +#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); + + /* Delete the PMK cache for this entry if it exists.*/ + if ((PmkCacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->apidx, pEntry->Addr)) != -1) + { + RTMPDeletePMKIDCache(pAd, pEntry->apidx, PmkCacheIdx); + } +#endif /* DOT1X_SUPPORT */ + +#ifdef WAPI_SUPPORT + RTMPCancelWapiRekeyTimerAction(pAd, pEntry); +#endif /* WAPI_SUPPORT */ + +#ifdef IGMP_SNOOP_SUPPORT + IgmpGroupDelMembers(pAd, (PUCHAR)pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.if_dev); +#endif /* IGMP_SNOOP_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].StaCount--; + pAd->ApCfg.EntryClientCount--; + +#ifdef HOSTAPD_SUPPORT + if(pEntry && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == Hostapd_EXT ) + { + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, pEntry->Addr, + NULL, 0,pEntry->apidx); + } +#endif /* HOSTAPD_SUPPORT */ +#ifdef RT_CFG80211_SUPPORT +#ifdef RT_CFG80211_P2P_SUPPORT + if (CFG_P2PGO_ON(pAd) || (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP)) + CFG80211_ApStaDelSendEvent(pAd, pEntry->Addr); +#else + CFG80211_ApStaDelSendEvent(pAd, pEntry->Addr); +#endif /* RT_CFG80211_P2P_SUPPORT */ +#endif /*RT_CFG80211_SUPPORT*/ + } +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + { + RTMPReleaseTimer(&pEntry->RetryTimer, &Cancelled); +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap && pEntry->bUseHwFifoExt) + FifoExtTblRmReptEntry(pAd, wcid); +#endif + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + pPrevEntry = NULL; + pProbeEntry = pAd->MacTab.Hash[HashIdx]; + ASSERT(pProbeEntry); + if (pProbeEntry != NULL) + { + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + pAd->MacTab.Hash[HashIdx] = pEntry->pNext; + else + pPrevEntry->pNext = pEntry->pNext; + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + } + + /* not found !!!*/ + ASSERT(pProbeEntry != NULL); + +#ifdef CONFIG_AP_SUPPORT + APCleanupPsQueue(pAd, &pEntry->PsQueue); /* return all NDIS packet in PSQ*/ +#endif /* CONFIG_AP_SUPPORT */ + /*RTMP_REMOVE_PAIRWISE_KEY_ENTRY(pAd, wcid);*/ + +#ifdef UAPSD_SUPPORT +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + hex_dump("mac=", pEntry->Addr, 6); + UAPSD_MR_ENTRY_RESET(pAd, pEntry); +#else +#ifdef CONFIG_AP_SUPPORT + UAPSD_MR_ENTRY_RESET(pAd, pEntry); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ +#endif /* UAPSD_SUPPORT */ + + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + RTMPReleaseTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_AP_SUPPORT + if (IS_ENTRY_CLIENT(pEntry)) + { + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl; + if (MAC_ADDR_EQUAL(pEntry->Addr, pWscControl->EntryAddr)) + { + /* + Some WPS Client will send dis-assoc close to WSC_DONE. + If AP misses WSC_DONE, WPS Client still sends dis-assoc to AP. + Do not cancel timer if WscState is WSC_STATE_WAIT_DONE. + */ + if ((pWscControl->EapolTimerRunning == TRUE) && + (pWscControl->WscState != WSC_STATE_WAIT_DONE)) + { + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + pWscControl->EapMsgRunning = FALSE; + NdisZeroMemory(&(pWscControl->EntryAddr[0]), MAC_ADDR_LEN); + } + } + pEntry->Receive_EapolStart_EapRspId = 0; + pEntry->bWscCapable = FALSE; + } +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DROP_MASK_SUPPORT + drop_mask_release_per_client(pAd, pEntry); +#endif /* DROP_MASK_SUPPORT */ + + +#ifdef PEER_DELBA_TX_ADAPT + RTMPCancelTimer(&pEntry->DelBA_tx_AdaptTimer, &Cancelled); +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + UINT32 MacReg = 0; + + if (pEntry->bPeerDelBaTxAdaptEn) + { + /* Disable Tx Mac look up table (Ressume original setting) */ + RTMP_IO_READ32(pAd, TX_FBK_LIMIT, &MacReg); + MacReg &= ~(1 << 18); + RTMP_IO_WRITE32(pAd, TX_FBK_LIMIT, MacReg); + DBGPRINT(RT_DEBUG_TRACE, ("%s():TX_FBK_LIMIT = 0x%08x\n", __FUNCTION__, MacReg)); + } + } +#endif /* RT6352 */ + pEntry->bPeerDelBaTxAdaptEn = 0; + RTMPReleaseTimer(&pEntry->DelBA_tx_AdaptTimer, &Cancelled); +#endif /* PEER_DELBA_TX_ADAPT */ + +// NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + NdisZeroMemory(pEntry->Addr, MAC_ADDR_LEN); + /* invalidate the entry */ + SET_ENTRY_NONE(pEntry); + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + pAd->MacTab.Size--; + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + NdisFreeSpinLock(&pEntry->TxSndgLock); +#endif /* TXBF_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid)); + } + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + + /*Reset operating mode when no Sta.*/ + if (pAd->MacTab.Size == 0) + { +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; +#endif /* DOT11_N_SUPPORT */ + RTMP_UPDATE_PROTECT(pAd, 0, ALLN_SETPROTECT, TRUE, 0); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef MULTI_CLIENT_SUPPORT + if (pAd->MacTab.Size < MAX_LEN_OF_MAC_TABLE) + { + USHORT size; + + size = pAd->ApCfg.EntryClientCount; + asic_change_tx_retry(pAd, size); + + pkt_aggr_num_change(pAd, size); + + if (pAd->CommonCfg.bWmm) + asic_tune_be_wmm(pAd, size); + } +#endif /* MULTI_CLIENT_SUPPORT */ + + /*APUpdateCapabilityAndErpIe(pAd);*/ + RTMP_AP_UPDATE_CAPABILITY_AND_ERPIE(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet*/ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* + ========================================================================== + Description: + This routine reset the entire MAC table. All packets pending in + the power-saving queues are freed here. + ========================================================================== + */ +VOID MacTableReset(RTMP_ADAPTER *pAd) +{ + int i; + BOOLEAN Cancelled; +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags=0; +#endif /* RTMP_MAC_PCI */ + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DeAuthHdr; + USHORT Reason; + UCHAR apidx = MAIN_MBSSID; +#endif /* CONFIG_AP_SUPPORT */ + MAC_TABLE_ENTRY *pMacEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); + /*NdisAcquireSpinLock(&pAd->MacTabLock);*/ + + + for (i=1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pMacEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_CLIENT(pMacEntry)) + { + RTMPReleaseTimer(&pMacEntry->EnqueueStartForPSKTimer, &Cancelled); +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPReleaseTimer(&pMacEntry->WPA_Authenticator.MsgRetryTimer, &Cancelled); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + pMacEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* Before reset MacTable, send disassociation packet to client.*/ + if (pMacEntry->Sst == SST_ASSOC) + { + /* send out a De-authentication request frame*/ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n")); + /*NdisReleaseSpinLock(&pAd->MacTabLock);*/ + return; + } + + Reason = REASON_NO_LONGER_VALID; + DBGPRINT(RT_DEBUG_WARN, ("Send DeAuth (Reason=%d) to %02x:%02x:%02x:%02x:%02x:%02x\n", + Reason, PRINT_MAC(pMacEntry->Addr))); + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pMacEntry->Addr, + pAd->ApCfg.MBSSID[pMacEntry->apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[pMacEntry->apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + RtmpusecDelay(5000); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* Delete a entry via WCID */ + MacTableDeleteEntry(pAd, i, pMacEntry->Addr); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (apidx = MAIN_MBSSID; apidx < pAd->ApCfg.BssidNum; apidx++) + { +#ifdef WSC_AP_SUPPORT + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->ApCfg.MBSSID[apidx].WscControl.EapolTimer, &Cancelled); + pAd->ApCfg.MBSSID[apidx].WscControl.EapolTimerRunning = FALSE; + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].WscControl.EntryAddr, MAC_ADDR_LEN); + pAd->ApCfg.MBSSID[apidx].WscControl.EapMsgRunning = FALSE; +#endif /* WSC_AP_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].StaCount = 0; + } +#ifdef RTMP_MAC_PCI + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + DBGPRINT(RT_DEBUG_TRACE, ("McastPsQueue.Number %u...\n", pAd->MacTab.McastPsQueue.Number)); + if (pAd->MacTab.McastPsQueue.Number > 0) + APCleanupPsQueue(pAd, &pAd->MacTab.McastPsQueue); + DBGPRINT(RT_DEBUG_TRACE, ("2McastPsQueue.Number %u...\n", pAd->MacTab.McastPsQueue.Number)); + + /* ENTRY PREEMPTION: Zero Mac Table but entry's content */ +/* NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));*/ + NdisZeroMemory(&pAd->MacTab.Size, + sizeof(MAC_TABLE)- + sizeof(pAd->MacTab.Hash)- + sizeof(pAd->MacTab.Content)); + + InitializeQueueHeader(&pAd->MacTab.McastPsQueue); + /*NdisReleaseSpinLock(&pAd->MacTabLock);*/ +#ifdef RTMP_MAC_PCI + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + } +#endif /* CONFIG_AP_SUPPORT */ + return; +} + + +#ifdef MAC_REPEATER_SUPPORT +MAC_TABLE_ENTRY *InsertMacRepeaterEntry(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR IfIdx) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + PAPCLI_STRUCT pApCliEntry = NULL; + + os_alloc_mem(NULL, (UCHAR **)&pEntry, sizeof(MAC_TABLE_ENTRY)); + + if (pEntry) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIdx]; + pEntry->Aid = pApCliEntry->MacTabWCID + 1; // TODO: We need to record count of STAs + COPY_MAC_ADDR(pEntry->Addr, pApCliEntry->MlmeAux.Bssid); + DBGPRINT(RT_DEBUG_OFF, ("sn - InsertMacRepeaterEntry: Aid = %d\n", pEntry->Aid)); + hex_dump("sn - InsertMacRepeaterEntry pEntry->Addr", pEntry->Addr, 6); + /* Add this entry into ASIC RX WCID search table */ + RTMP_STA_ENTRY_ADD(pAd, pEntry); + os_free_mem(NULL, pEntry); + } + + return pEntry; +} + +#endif /* MAC_REPEATER_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_ht.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_ht.c new file mode 100644 index 000000000..2ded79e98 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_ht.c @@ -0,0 +1,862 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +#ifdef DOT11_N_SUPPORT + + +INT ht_mode_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, HT_CAPABILITY_IE *peer, RT_HT_CAPABILITY *my) +{ + if ((peer->HtCapInfo.GF) && (my->GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + pAd->MacTab.fAnyStationNonGF = TRUE; + } + + if ((peer->HtCapInfo.ChannelWidth) && (my->ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((my->ShortGIfor40) & (peer->HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((my->ShortGIfor20) & (peer->HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + return TRUE; +} + + +INT set_ht_fixed_mcs(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR fixed_mcs, UCHAR mcs_bound) +{ + if (fixed_mcs == 32) + { + /* Fix MCS as HT Duplicated Mode */ + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > mcs_bound) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = mcs_bound; + } + + return TRUE; +} + + +INT get_ht_max_mcs(RTMP_ADAPTER *pAd, UCHAR *desire_mcs, UCHAR *cap_mcs) +{ + INT i, j; + UCHAR bitmask; + + + for (i=23; i>=0; i--) + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ((desire_mcs[j] & bitmask) && (cap_mcs[j] & bitmask)) + { + /*pEntry->MaxHTPhyMode.field.MCS = i; */ + /* find it !!*/ + break; + } + if (i==0) + break; + } + + return i; +} + + +INT get_ht_cent_ch(RTMP_ADAPTER *pAd, UINT8 *rf_bw, UINT8 *ext_ch) +{ + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + ) + { + *rf_bw = BW_40; + *ext_ch = EXTCHA_ABOVE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else if ((pAd->CommonCfg.Channel > 2) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + *rf_bw = BW_40; + *ext_ch = EXTCHA_BELOW; + if (pAd->CommonCfg.Channel == 14) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + } else { + return FALSE; + } + + return TRUE; +} + + +UCHAR get_cent_ch_by_htinfo( + RTMP_ADAPTER *pAd, + ADD_HT_INFO_IE *ht_op, + HT_CAPABILITY_IE *ht_cap) +{ + UCHAR cent_ch; + + if ((ht_op->ControlChan > 2)&& + (ht_op->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && + (ht_cap->HtCapInfo.ChannelWidth == BW_40)) + cent_ch = ht_op->ControlChan - 2; + else if ((ht_op->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && + (ht_cap->HtCapInfo.ChannelWidth == BW_40)) + cent_ch = ht_op->ControlChan + 2; + else + cent_ch = ht_op->ControlChan; + + return cent_ch; +} + + +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetHT( + IN RTMP_ADAPTER *pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode) +{ + UCHAR RxStream = pAd->CommonCfg.RxStream; +#ifdef CONFIG_AP_SUPPORT + INT apidx; +#endif /* CONFIG_AP_SUPPORT */ + INT bw; + RT_HT_CAPABILITY *rt_ht_cap = &pAd->CommonCfg.DesiredHtPhy; + HT_CAPABILITY_IE *ht_cap= &pAd->CommonCfg.HtCapability; + +#ifdef CONFIG_AP_SUPPORT + /* sanity check for extention channel */ + if (CHAN_PropertyCheck(pAd, pAd->CommonCfg.Channel, + CHANNEL_NO_FAT_BELOW | CHANNEL_NO_FAT_ABOVE) == TRUE) + { + /* only 20MHz is allowed */ + pHTPhyMode->BW = 0; + } + else if (pHTPhyMode->ExtOffset == EXTCHA_BELOW) + { + /* extension channel below this channel is not allowed */ + if (CHAN_PropertyCheck(pAd, pAd->CommonCfg.Channel, + CHANNEL_NO_FAT_BELOW) == TRUE) + { + pHTPhyMode->ExtOffset = EXTCHA_ABOVE; + } + } + else if (pHTPhyMode->ExtOffset == EXTCHA_ABOVE) + { + /* extension channel above this channel is not allowed */ + if (CHAN_PropertyCheck(pAd, pAd->CommonCfg.Channel, + CHANNEL_NO_FAT_ABOVE) == TRUE) + { + pHTPhyMode->ExtOffset = EXTCHA_BELOW; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, + pHTPhyMode->MCS, pHTPhyMode->BW, + pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + + /* Don't zero supportedHyPhy structure.*/ + RTMPZeroMemory(ht_cap, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset)); + RTMPZeroMemory(rt_ht_cap, sizeof(RT_HT_CAPABILITY)); + + if (pAd->CommonCfg.bRdg) + { + ht_cap->ExtHtCapInfo.PlusHTC = 1; + ht_cap->ExtHtCapInfo.RDGSupport = 1; + } + else + { + ht_cap->ExtHtCapInfo.PlusHTC = 0; + ht_cap->ExtHtCapInfo.RDGSupport = 0; + } + + + if (RxStream == 1) + { + ht_cap->HtCapParm.MaxRAmpduFactor = 2; + rt_ht_cap->MaxRAmpduFactor = 2; + } + else + { + ht_cap->HtCapParm.MaxRAmpduFactor = 3; + rt_ht_cap->MaxRAmpduFactor = 3; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + /* Mimo power save, A-MSDU size, */ + rt_ht_cap->AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + rt_ht_cap->AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize; + rt_ht_cap->MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode; + rt_ht_cap->MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + ht_cap->HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + ht_cap->HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + + if (pAd->CommonCfg.ht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) + ht_cap->HtCapInfo.ht_rx_ldpc = 1; + else + ht_cap->HtCapInfo.ht_rx_ldpc = 0; + + ht_cap->HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", + rt_ht_cap->AmsduSize, + rt_ht_cap->MimoPs, + rt_ht_cap->MpduDensity, + rt_ht_cap->MaxRAmpduFactor)); + + if(pHTPhyMode->HtMode == HTMODE_GF) + { + ht_cap->HtCapInfo.GF = 1; + rt_ht_cap->GF = 1; + } + else + rt_ht_cap->GF = 0; + + /* Decide Rx MCSSet*/ + switch (RxStream) + { + case 3: + ht_cap->MCSSet[2] = 0xff; + case 2: + ht_cap->MCSSet[1] = 0xff; + case 1: + default: + ht_cap->MCSSet[0] = 0xff; + break; + } + +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pHTPhyMode->BW == BW_40)) + { + pHTPhyMode->BW = BW_20; + ht_cap->HtCapInfo.Forty_Mhz_Intolerant = 1; + } +#endif /* DOT11N_DRAFT3 */ + + // TODO: shiang-6590, how about the "bw" when channel 14 for JP region??? + //CFG_TODO + bw = BW_20; + if(pHTPhyMode->BW == BW_40) + { + ht_cap->MCSSet[4] = 0x1; /* MCS 32*/ + ht_cap->HtCapInfo.ChannelWidth = 1; + if (pAd->CommonCfg.Channel <= 14) + ht_cap->HtCapInfo.CCKmodein40 = 1; + + rt_ht_cap->ChannelWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE; + /* Set Regsiter for extension channel position.*/ + rtmp_mac_set_ctrlch(pAd, pHTPhyMode->ExtOffset); + + /* Turn on BBP 40MHz mode now only as AP . */ + /* Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection.*/ + if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) + ) + { + bbp_set_ctrlch(pAd, pHTPhyMode->ExtOffset); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + bw = BW_20; + else +#endif /* GREENAP_SUPPORT */ + bw = BW_40; + } + } + else + { + ht_cap->HtCapInfo.ChannelWidth = 0; + rt_ht_cap->ChannelWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + /* Turn on BBP 20MHz mode by request here.*/ + bw = BW_20; + } + +#ifdef DOT11_VHT_AC + if (pHTPhyMode->BW == BW_40 && + pAd->CommonCfg.vht_bw == VHT_BW_80 && + pAd->CommonCfg.vht_cent_ch) + bw = BW_80; +#endif /* DOT11_VHT_AC */ + bbp_set_bw(pAd, bw); + + + if(pHTPhyMode->STBC == STBC_USE) + { + if (pAd->Antenna.field.TxPath >= 2) + { + ht_cap->HtCapInfo.TxSTBC = 1; + rt_ht_cap->TxSTBC = 1; + } + else + { + ht_cap->HtCapInfo.TxSTBC = 0; + rt_ht_cap->TxSTBC = 0; + } + + /* + RxSTBC + 0: not support, + 1: support for 1SS + 2: support for 1SS, 2SS + 3: support for 1SS, 2SS, 3SS + */ + if (pAd->Antenna.field.RxPath >= 1) + { + ht_cap->HtCapInfo.RxSTBC = 1; + rt_ht_cap->RxSTBC = 1; + } + else + { + ht_cap->HtCapInfo.RxSTBC = 0; + rt_ht_cap->RxSTBC = 0; + } + } + else + { + rt_ht_cap->TxSTBC = 0; + rt_ht_cap->RxSTBC = 0; + } + + if(pHTPhyMode->SHORTGI == GI_400) + { + ht_cap->HtCapInfo.ShortGIfor20 = 1; + ht_cap->HtCapInfo.ShortGIfor40 = 1; + rt_ht_cap->ShortGIfor20 = 1; + rt_ht_cap->ShortGIfor40 = 1; + } + else + { + ht_cap->HtCapInfo.ShortGIfor20 = 0; + ht_cap->HtCapInfo.ShortGIfor40 = 0; + rt_ht_cap->ShortGIfor20 = 0; + rt_ht_cap->ShortGIfor40 = 0; + } + + /* We support link adaptation for unsolicit MCS feedback, set to 2.*/ + pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; + /* 1, the extension channel above the control channel. */ + + /* EDCA parameters used for AP's own transmission*/ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + set_default_ap_edca_param(pAd); + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + /* Set ETxBF */ + setETxBFCap(pAd, &ht_cap->TxBFCap); + + /* Check ITxBF */ + pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn &= rtmp_chk_itxbf_calibration(pAd); + + /* Apply to ASIC */ + rtmp_asic_set_bf(pAd); + } +#endif /* TXBF_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + RTMPSetIndividualHT(pAd, apidx); +#ifdef WDS_SUPPORT + for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++) + RTMPSetIndividualHT(pAd, apidx + MIN_NET_DEVICE_FOR_WDS); +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + RTMPSetIndividualHT(pAd, apidx + MIN_NET_DEVICE_FOR_APCLI); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + +#ifdef RT_CFG80211_P2P_SUPPORT + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + RTMPSetIndividualHT(pAd, apidx + MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + RTMPSetIndividualHT(pAd, apidx + MIN_NET_DEVICE_FOR_APCLI); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + + RTMPSetIndividualHT(pAd, 0); + } +#endif /* CONFIG_STA_SUPPORT */ + +} + +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetIndividualHT(RTMP_ADAPTER *pAd, UCHAR apidx) +{ + RT_PHY_INFO *pDesired_ht_phy = NULL; + UCHAR TxStream = pAd->CommonCfg.TxStream; + UCHAR DesiredMcs = MCS_AUTO; + UCHAR encrypt_mode = Ndis802_11EncryptionDisabled; + struct wifi_dev *wdev; + + do + { + +#ifdef RT_CFG80211_P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO; + + pDesired_ht_phy = &pAd->ApCfg.MBSSID[idx].wdev.DesiredHtPhyInfo; + DesiredMcs = pAd->ApCfg.MBSSID[idx].wdev.DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->ApCfg.MBSSID[idx].wdev.WepStatus; + pAd->ApCfg.MBSSID[idx].wdev.bWmmCapable = TRUE; + pAd->ApCfg.MBSSID[idx].wdev.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } +#endif /* RT_CFG80211_P2P_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + pDesired_ht_phy = &pAd->ApCfg.ApCliTab[idx].wdev.DesiredHtPhyInfo; + DesiredMcs = pAd->ApCfg.ApCliTab[idx].wdev.DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->ApCfg.ApCliTab[idx].wdev.WepStatus; + pAd->ApCfg.ApCliTab[idx].wdev.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid idx(%d)\n", idx)); + return; + } + } +#endif /* APCLI_SUPPORT */ + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS; + + if (idx < MAX_WDS_ENTRY) + { + pDesired_ht_phy = &pAd->WdsTab.WdsEntry[idx].wdev.DesiredHtPhyInfo; + DesiredMcs = pAd->WdsTab.WdsEntry[idx].wdev.DesiredTransmitSetting.field.MCS; + /*encrypt_mode = pAd->WdsTab.WdsEntry[idx].WepStatus;*/ + pAd->WdsTab.WdsEntry[idx].wdev.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + if ((apidx < pAd->ApCfg.BssidNum) && (apidx < MAX_MBSSID_NUM(pAd)) && (apidx < HW_BEACON_MAX_NUM)) + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + pDesired_ht_phy = &wdev->DesiredHtPhyInfo; + DesiredMcs = wdev->DesiredTransmitSetting.field.MCS; +#ifdef WFA_VHT_PF + // TODO: Sigma, this code segment used to work around for Sigma Automation! + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (DesiredMcs != MCS_AUTO)) { + DesiredMcs += ((TxStream - 1) << 4); + pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.FixedTxMode = FIXED_TXMODE_VHT; + RT_CfgSetAutoFallBack(pAd, "0"); + } else { + RT_CfgSetAutoFallBack(pAd, "1"); + } +#endif /* WFA_VHT_PF */ + encrypt_mode = wdev->WepStatus; + pAd->ApCfg.MBSSID[apidx].wdev.bWmmCapable = TRUE; + wdev->bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } + + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); + return; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + wdev = &pAd->StaCfg.wdev; + + pDesired_ht_phy = &wdev->DesiredHtPhyInfo; + DesiredMcs = wdev->DesiredTransmitSetting.field.MCS; + encrypt_mode = wdev->WepStatus; + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while (FALSE); + + if (pDesired_ht_phy == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); + return; + } + RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_PHY_INFO)); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); + /* Check the validity of MCS */ + if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); + DesiredMcs = MCS_7; + } + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); + DesiredMcs = MCS_0; + } + +#ifdef APCLI_AUTO_BW_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + if (idx < MAX_APCLI_NUM) + { + if (WMODE_CAP_N(pAd->ApCfg.ApCliTab[idx].wdev.PhyMode)) + goto ht_enable; + } + } +#endif /* APCLI_AUTO_BW_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && (pAd->StaCfg.BssType == BSS_INFRA) && (apidx == MIN_NET_DEVICE_FOR_MBSSID)) + ; + else +#endif /* CONFIG_STA_SUPPORT */ + /* + WFA recommend to restrict the encryption type in 11n-HT mode. + So, the WEP and TKIP are not allowed in HT rate. + */ + if (pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(encrypt_mode)) + { +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.bAdhocN = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_WARN, ("%s : Use legacy rate in WEP/TKIP encryption mode (apidx=%d)\n", + __FUNCTION__, apidx)); + return; + } + + if (pAd->CommonCfg.HT_Disable) + { +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.bAdhocN = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("%s : HT is disabled\n", __FUNCTION__)); + return; + } + +#ifdef APCLI_AUTO_BW_SUPPORT +ht_enable: +#endif /* APCLI_AUTO_BW_SUPPORT */ + + pDesired_ht_phy->bHtEnable = TRUE; + + /* Decide desired Tx MCS*/ + switch (TxStream) + { + case 1: + if (DesiredMcs == MCS_AUTO) + pDesired_ht_phy->MCSSet[0]= 0xff; + else if (DesiredMcs <= MCS_7) + pDesired_ht_phy->MCSSet[0]= 1<MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0xff; + } + else if (DesiredMcs <= MCS_15) + { + ULONG mode; + + mode = DesiredMcs / 8; + if (mode < 2) + pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); + } + break; + + case 3: + if (DesiredMcs == MCS_AUTO) + { + /* MCS0 ~ MCS23, 3 bytes */ + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0xff; + pDesired_ht_phy->MCSSet[2]= 0xff; + } + else if (DesiredMcs <= MCS_23) + { + ULONG mode; + + mode = DesiredMcs / 8; + if (mode < 3) + pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); + } + break; + } + + if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) + { + if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) + pDesired_ht_phy->MCSSet[4] = 0x1; + } + + /* update HT Rate setting */ + if (pAd->OpMode == OPMODE_STA) + { + MlmeUpdateHtTxRates(pAd, BSS0); + } + else + MlmeUpdateHtTxRates(pAd, apidx); + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { + pDesired_ht_phy->bVhtEnable = TRUE; + rtmp_set_vht(pAd, pDesired_ht_phy); + } +#endif /* DOT11_VHT_AC */ +} + +/* + ======================================================================== + Routine Description: + Clear the desire HT info per interface + + Arguments: + + ======================================================================== +*/ +VOID RTMPDisableDesiredHtInfo(RTMP_ADAPTER *pAd) +{ + struct wifi_dev *wdev; + +#ifdef CONFIG_AP_SUPPORT + UINT8 idx = 0; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + wdev = &pAd->ApCfg.MBSSID[idx].wdev; + RTMPZeroMemory(&wdev->DesiredHtPhyInfo, sizeof(RT_PHY_INFO)); + } +#ifdef WDS_SUPPORT + for (idx = 0; idx < MAX_WDS_ENTRY; idx++) + { + RTMPZeroMemory(&pAd->WdsTab.WdsEntry[idx].wdev.DesiredHtPhyInfo, sizeof(RT_PHY_INFO)); + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (idx = 0; idx < MAX_APCLI_NUM; idx++) + { +#ifdef APCLI_AUTO_BW_SUPPORT + if (!WMODE_CAP_N(pAd->ApCfg.ApCliTab[idx].wdev.PhyMode)) +#endif /* APCLI_AUTO_BW_SUPPORT */ + { + RTMPZeroMemory(&pAd->ApCfg.ApCliTab[idx].wdev.DesiredHtPhyInfo, sizeof(RT_PHY_INFO)); + } + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPZeroMemory(&pAd->StaCfg.wdev.DesiredHtPhyInfo, sizeof(RT_PHY_INFO)); + } +#endif /* CONFIG_STA_SUPPORT */ + +} + + +INT SetCommonHT(RTMP_ADAPTER *pAd) +{ + OID_SET_HT_PHYMODE SetHT; + + if (!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + /* Clear previous HT information */ + RTMPDisableDesiredHtInfo(pAd); + +#ifdef APCLI_AUTO_BW_SUPPORT + UINT apidx = 0; + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + /* Recover the sub-Device PhyMode when MainPhyInfo clear */ + if (!ApCliSetPhyMode(pAd, apidx, pAd->ApCfg.ApCliTab[apidx].wdev.PhyMode)) + { + DBGPRINT(RT_DEBUG_OFF, ("AUTOBW(%s): skip unknown ApCliEntry[%d].WMODE=%d\n", + __FUNCTION__, apidx, pAd->ApCfg.ApCliTab[apidx].wdev.PhyMode)); + } + } +#endif /* APCLI_AUTO_BW_SUPPORT */ + return FALSE; + } + + N_ChannelCheck(pAd); + +#ifdef DOT11_VHT_AC + SetCommonVHT(pAd); +#endif /* DOT11_VHT_AC */ + + SetHT.PhyMode = (RT_802_11_PHY_MODE)pAd->CommonCfg.PhyMode; + SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath); + SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; + SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + SetHT.MCS = MCS_AUTO; + SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; + SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; + SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; + + RTMPSetHT(pAd, &SetHT); + +#ifdef DOT11N_DRAFT3 + if(pAd->CommonCfg.bBssCoexEnable && pAd->CommonCfg.Bss2040NeedFallBack) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 1; + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; + pAd->CommonCfg.Bss2040NeedFallBack = 1; + } +#endif /* DOT11N_DRAFT3 */ + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Update HT IE from our capability. + + Arguments: + Send all HT IE in beacon/probe rsp/assoc rsp/action frame. + + + ======================================================================== +*/ +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo) +{ + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + + pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; + pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; + pHtCapability->HtCapInfo.GF = pRtHt->GF; + pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; + pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; + pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; + pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; + pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; + pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; + pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; + + pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ; + pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; + pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; + pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; + RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); /* rt2860 only support MCS max=32, no need to copy all 16 uchar.*/ + + DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n")); +} + +#endif /* DOT11_N_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_hw.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_hw.c new file mode 100644 index 000000000..96aa527ec --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_hw.c @@ -0,0 +1,57 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include + + +INT dev_adjust_radio(RTMP_ADAPTER *pAd) +{ + struct hw_setting new_cfg, *hw_cfg = &pAd->hw_cfg; + + + NdisZeroMemory(&new_cfg, sizeof(struct hw_setting)); + + + /* For all wdev, find the maximum inter-set */ + + + if (hw_cfg->bbp_bw != new_cfg.bbp_bw) + { + bbp_set_bw(pAd, new_cfg.bbp_bw); + hw_cfg->bbp_bw = new_cfg.bbp_bw; + } + + if (hw_cfg->cent_ch != new_cfg.cent_ch) + { + UINT8 ext_ch = EXTCHA_NONE; + + bbp_set_ctrlch(pAd, ext_ch); + rtmp_mac_set_ctrlch(pAd, ext_ch); + } + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_vht.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_vht.c new file mode 100644 index 000000000..97ab614d2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/mgmt/mgmt_vht.c @@ -0,0 +1,92 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +#ifdef DOT11_VHT_AC + +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11ac support. + Calls at setting VHT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetVHT( + IN RTMP_ADAPTER *pAd) +{ +#ifdef VHT_TXBF_SUPPORT + VHT_CAP_INFO *vht_cap= &pAd->CommonCfg.vht_cap_ie.vht_cap; + + if (pAd->chipCap.FlgHwTxBfCap) + { + /* Set ETxBF */ + setVHTETxBFCap(pAd, vht_cap); + } +#endif /* VHT_TXBF_SUPPORT */ +} + + +VOID rtmp_set_vht(RTMP_ADAPTER *pAd, RT_PHY_INFO *phy_info) +{ + if (!phy_info) + return; + + if (phy_info->bVhtEnable && + (pAd->CommonCfg.vht_bw == VHT_BW_80)) + phy_info->vht_bw = VHT_BW_80; + else + phy_info->vht_bw = VHT_BW_2040; + +} + + +INT SetCommonVHT(RTMP_ADAPTER *pAd) +{ + UCHAR cent_ch = 0; + + if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + { + /* Clear previous VHT information */ + return FALSE; + } + + RTMPSetVHT(pAd); + + pAd->CommonCfg.vht_cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Config VHT parameters!cent_ch=%d!vht_cent_ch = %d, vht_cent_ch2 = %d\n", + __FUNCTION__, cent_ch, pAd->CommonCfg.vht_cent_ch, pAd->CommonCfg.vht_cent_ch2)); + return TRUE; +} + +#endif /* DOT11_VHT_AC */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/cso.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/cso.c new file mode 100644 index 000000000..fd35f2ada --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/cso.c @@ -0,0 +1,27 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/net_acc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/net_acc.c new file mode 100644 index 000000000..a5455b236 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/net_acc.c @@ -0,0 +1,31 @@ +/* + *************************************************************************** + * 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: + + Abstract: + Network Acceleration related function + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/tso.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/tso.c new file mode 100644 index 000000000..fd35f2ada --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/naf/tso.c @@ -0,0 +1,27 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/android_priv_cmd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/android_priv_cmd.c new file mode 100644 index 000000000..419d99c17 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/android_priv_cmd.c @@ -0,0 +1,120 @@ + +#define RTMP_MODULE_OS + +#include "rt_config.h" +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + +#ifdef RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT + +#define ANDROID_CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define ANDROID_CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" + +typedef struct android_priv_cmd { + char *buf; + int used_len; + int total_len; +} android_priv_cmd; + +static INT priv_cmd_get_p2p_dev_addr(PNET_DEV net_dev, PCHAR command, INT total_len) +{ + VOID *pAdSrc; + pAdSrc = RTMP_OS_NETDEV_GET_PRIV(net_dev); + ASSERT(pAdSrc); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + INT bytes_written = 0; + + COPY_MAC_ADDR(command, pAd->cfg80211_ctrl.P2PCurrentAddress, MAC_ADDR_LEN); + bytes_written = MAC_ADDR_LEN; + + return bytes_written; +} + +static INT priv_cmd_set_ap_wps_p2p_ie(PNET_DEV net_dev, PCHAR buf, INT len, INT type) +{ + //0x1: BEACON + //0x2: PROBE_RESP + //0x4: ASSOC_RESP + + INT ret = 0; + + return ret; +} + +int rt_android_private_command_entry( + VOID *pAdSrc, PNET_DEV net_dev, struct ifreq *ifr, INT cmd) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + android_priv_cmd priv_cmd; + UCHAR *command = NULL; + INT ret = 0, bytes_written = 0; + + if (!ifr->ifr_data) + return -EINVAL; + + if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) + return -EFAULT; + + os_alloc_mem(NULL, (UCHAR **)&command, priv_cmd.total_len); + if (!command) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: MEM ALLOC ERROR\n", __FUNCTION__)); + return -ENOMEM; + } + + if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) + { + ret = -EFAULT; + goto FREE; + } + + if (strnicmp(command, ANDROID_CMD_SET_AP_WPS_P2P_IE, strlen(ANDROID_CMD_SET_AP_WPS_P2P_IE)) == 0) + { + int skip = strlen(ANDROID_CMD_SET_AP_WPS_P2P_IE) + 3; + bytes_written = priv_cmd_set_ap_wps_p2p_ie(net_dev, command + skip, + priv_cmd.total_len - skip, *(command + skip - 2) - '0'); + } + else if (strnicmp(command, ANDROID_CMD_P2P_DEV_ADDR, strlen(ANDROID_CMD_P2P_DEV_ADDR)) == 0) + { + bytes_written = priv_cmd_get_p2p_dev_addr(net_dev, command, priv_cmd.total_len); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unsupport priv_cmd !!!\n", command)); + snprintf(command, 3, "OK"); + bytes_written = strlen("OK"); + } + +RESPONSE: + if (bytes_written >= 0) + { + /* priv_cmd in but no response */ + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) + command[0] = '\0'; + + if (bytes_written >= priv_cmd.total_len) + { + bytes_written = priv_cmd.total_len; + } + else + { + bytes_written++; + } + priv_cmd.used_len = bytes_written; + + if (copy_to_user(priv_cmd.buf, command, bytes_written)) + ret = -EFAULT; + } + else + { + ret = bytes_written; + } + +FREE: + if (command) + os_free_mem(NULL, command); + + return ret; +} +#endif /* RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/ap_ioctl.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/ap_ioctl.c new file mode 100644 index 000000000..f40706304 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/ap_ioctl.c @@ -0,0 +1,447 @@ +/**************************************************************************** + * 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_ioctl.c + + Abstract: + IOCTL related subroutines + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ +#define RTMP_MODULE_OS + +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +#include + +struct iw_priv_args ap_privtab[] = { +{ RTPRIV_IOCTL_SET, +/* 1024 --> 1024 + 512 */ +/* larger size specific to allow 64 ACL MAC addresses to be set up all at once. */ + IW_PRIV_TYPE_CHAR | 1536, 0, + "set"}, +{ RTPRIV_IOCTL_SHOW, + IW_PRIV_TYPE_CHAR | 1024, 0, + "show"}, +{ RTPRIV_IOCTL_GSITESURVEY, +#ifdef AIRPLAY_SUPPORT + IW_PRIV_TYPE_CHAR | 1024 , +#else + 0 , +#endif /* AIRPLAY_SUPPORT */ + IW_PRIV_TYPE_CHAR | 1024 , + "get_site_survey"}, +#ifdef INF_AR9 + { RTPRIV_IOCTL_GET_AR9_SHOW, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , + "ar9_show"}, +#endif +#ifdef WSC_AP_SUPPORT + { RTPRIV_IOCTL_SET_WSCOOB, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , + "set_wsc_oob"}, +#endif +{ RTPRIV_IOCTL_GET_MAC_TABLE, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , + "get_mac_table"}, +{ RTPRIV_IOCTL_E2P, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "e2p"}, +#if defined(DBG) || defined(RALINK_ATE) +{ RTPRIV_IOCTL_BBP, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "bbp"}, +{ RTPRIV_IOCTL_MAC, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "mac"}, +#ifdef RTMP_RF_RW_SUPPORT +{ RTPRIV_IOCTL_RF, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "rf"}, +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /* defined(DBG) ||(defined(BB_SOC)&&defined(RALINK_ATE)) */ + +#ifdef WSC_AP_SUPPORT +{ RTPRIV_IOCTL_WSC_PROFILE, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , + "get_wsc_profile"}, +#endif /* WSC_AP_SUPPORT */ +{ RTPRIV_IOCTL_QUERY_BATABLE, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , + "get_ba_table"}, +{ RTPRIV_IOCTL_STATISTICS, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "stat"} +}; + + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +const struct iw_handler_def rt28xx_ap_iw_handler_def = +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + .private_args = (struct iw_priv_args *) ap_privtab, + .num_private_args = N(ap_privtab), +#if IW_HANDLER_VERSION >= 7 + .get_wireless_stats = rt28xx_get_wireless_stats, +#endif +}; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + +INT rt28xx_ap_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) +{ + VOID *pAd = NULL; + struct iwreq *wrqin = (struct iwreq *) rq; + RTMP_IOCTL_INPUT_STRUCT rt_wrq, *wrq = &rt_wrq; + INT Status = NDIS_STATUS_SUCCESS; + USHORT subcmd; + INT apidx=0; + UINT32 org_len; + RT_CMD_AP_IOCTL_CONFIG IoctlConfig, *pIoctlConfig = &IoctlConfig; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + wrq->u.data.pointer = wrqin->u.data.pointer; + wrq->u.data.length = wrqin->u.data.length; + wrq->u.data.flags = wrqin->u.data.flags; + org_len = wrq->u.data.length; + + pIoctlConfig->Status = 0; + pIoctlConfig->net_dev = net_dev; + pIoctlConfig->wdev = RTMP_OS_NETDEV_GET_WDEV(net_dev); + pIoctlConfig->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); + pIoctlConfig->pCmdData = wrqin->u.data.pointer; + pIoctlConfig->CmdId_RTPRIV_IOCTL_SET = RTPRIV_IOCTL_SET; + pIoctlConfig->name = net_dev->name; + pIoctlConfig->apidx = 0; + + if ((cmd != SIOCGIWPRIV) && + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_PREPARE, 0, + pIoctlConfig, 0) != NDIS_STATUS_SUCCESS) + { + /* prepare error */ + Status = pIoctlConfig->Status; + goto LabelExit; + } + + apidx = pIoctlConfig->apidx; + + /*+ patch for SnapGear Request even the interface is down */ + if(cmd== SIOCGIWNAME){ + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWNAME\n")); + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_SIOCGIWNAME, 0, wrqin->u.name, 0); + return Status; + }/*- patch for SnapGear */ + + + switch(cmd) + { + case RTPRIV_IOCTL_ATE: + { + RTMP_COM_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_ATE, 0, wrqin->ifr_name, 0); + } + break; + + case SIOCGIFHWADDR: + DBGPRINT(RT_DEBUG_TRACE, ("IOCTLIOCTLIOCTL::SIOCGIFHWADDR\n")); + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_AP_SIOCGIFHWADDR, 0, NULL, 0); +/* if (pObj->ioctl_if < MAX_MBSSID_NUM(pAd)) */ +/* strcpy((PSTRING) wrq->u.name, (PSTRING) pAd->ApCfg.MBSSID[pObj->ioctl_if].Bssid); */ + break; + case SIOCSIWESSID: /*Set ESSID */ + break; + case SIOCGIWESSID: /*Get ESSID */ + { + RT_CMD_AP_IOCTL_SSID IoctlSSID, *pIoctlSSID = &IoctlSSID; + struct iw_point *erq = &wrqin->u.essid; + PCHAR pSsidStr = NULL; + + erq->flags=1; + /*erq->length = pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen; */ + + pIoctlSSID->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); + pIoctlSSID->apidx = apidx; + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_AP_SIOCGIWESSID, 0, pIoctlSSID, 0); + + pSsidStr = (PCHAR)pIoctlSSID->pSsidStr; + erq->length = pIoctlSSID->length; + + + if((erq->pointer) && (pSsidStr != NULL)) + { + /*if(copy_to_user(erq->pointer, pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, erq->length)) */ + if(copy_to_user(erq->pointer, pSsidStr, erq->length)) + { + Status = RTMP_IO_EFAULT; + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWESSID (Len=%d, ssid=%s...)\n", erq->length, (char *)erq->pointer)); + } + break; + case SIOCGIWNWID: /* get network id */ + case SIOCSIWNWID: /* set network id (the cell) */ + Status = RTMP_IO_EOPNOTSUPP; + break; + case SIOCGIWFREQ: /* get channel/frequency (Hz) */ + { + ULONG Channel; + RTMP_DRIVER_CHANNEL_GET(pAd, &Channel); + wrqin->u.freq.m = Channel; /*pAd->CommonCfg.Channel; */ + wrqin->u.freq.e = 0; + wrqin->u.freq.i = 0; + } + break; + case SIOCSIWFREQ: /*set channel/frequency (Hz) */ + Status = RTMP_IO_EOPNOTSUPP; + break; + case SIOCGIWNICKN: + case SIOCSIWNICKN: /*set node name/nickname */ + Status = RTMP_IO_EOPNOTSUPP; + break; + case SIOCGIWRATE: /*get default bit rate (bps) */ + { + RT_CMD_IOCTL_RATE IoctlRate, *pIoctlRate = &IoctlRate; + + pIoctlRate->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); + RTMP_DRIVER_BITRATE_GET(pAd, pIoctlRate); + + + wrqin->u.bitrate.value = pIoctlRate->BitRate; + wrqin->u.bitrate.disabled = 0; + } + break; + case SIOCSIWRATE: /*set default bit rate (bps) */ + case SIOCGIWRTS: /* get RTS/CTS threshold (bytes) */ + case SIOCSIWRTS: /*set RTS/CTS threshold (bytes) */ + case SIOCGIWFRAG: /*get fragmentation thr (bytes) */ + case SIOCSIWFRAG: /*set fragmentation thr (bytes) */ + case SIOCGIWENCODE: /*get encoding token & mode */ + case SIOCSIWENCODE: /*set encoding token & mode */ + Status = RTMP_IO_EOPNOTSUPP; + break; + case SIOCGIWAP: /*get access point MAC addresses */ + { +/* PCHAR pBssidStr; */ + + wrqin->u.ap_addr.sa_family = ARPHRD_ETHER; + /*memcpy(wrqin->u.ap_addr.sa_data, &pAd->ApCfg.MBSSID[pObj->ioctl_if].Bssid, ETH_ALEN); */ + + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_AP_SIOCGIWAP, 0, + wrqin->u.ap_addr.sa_data, RT_DEV_PRIV_FLAGS_GET(net_dev)); + } + break; + case SIOCGIWMODE: /*get operation mode */ + wrqin->u.mode = IW_MODE_INFRA; /*SoftAP always on INFRA mode. */ + break; + case SIOCSIWAP: /*set access point MAC addresses */ + case SIOCSIWMODE: /*set operation mode */ + case SIOCGIWSENS: /*get sensitivity (dBm) */ + case SIOCSIWSENS: /*set sensitivity (dBm) */ + case SIOCGIWPOWER: /*get Power Management settings */ + case SIOCSIWPOWER: /*set Power Management settings */ + case SIOCGIWTXPOW: /*get transmit power (dBm) */ + case SIOCSIWTXPOW: /*set transmit power (dBm) */ + /*case SIOCGIWRANGE: //Get range of parameters */ + case SIOCGIWRETRY: /*get retry limits and lifetime */ + case SIOCSIWRETRY: /*set retry limits and lifetime */ + Status = RTMP_IO_EOPNOTSUPP; + break; + case SIOCGIWRANGE: /*Get range of parameters */ + { +/* struct iw_range range; */ + struct iw_range *prange = NULL; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&prange, sizeof(struct iw_range)); + if (prange == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + break; + } + + memset(prange, 0, sizeof(struct iw_range)); + prange->we_version_compiled = WIRELESS_EXT; + prange->we_version_source = 14; + + /* + what is correct max? This was not + documented exactly. At least + 69 has been observed. + */ + prange->max_qual.qual = 100; + prange->max_qual.level = 0; /* dB */ + prange->max_qual.noise = 0; /* dB */ + copy_to_user(wrq->u.data.pointer, prange, sizeof(struct iw_range)); + os_free_mem(NULL, prange); + } + break; + + case RT_PRIV_IOCTL: + case RT_PRIV_IOCTL_EXT: + { + subcmd = wrqin->u.data.flags; + + Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RT_PRIV_IOCTL, subcmd, wrqin->u.data.pointer, 0); + } + break; + +#ifdef HOSTAPD_SUPPORT + case SIOCSIWGENIE: + DBGPRINT(RT_DEBUG_TRACE,("ioctl SIOCSIWGENIE apidx=%d\n",apidx)); + DBGPRINT(RT_DEBUG_TRACE,("ioctl SIOCSIWGENIE length=%d, pointer=%x\n", wrqin->u.data.length, wrqin->u.data.pointer)); + + + RTMP_AP_IoctlHandle(pAd, wrqin, CMD_RTPRIV_IOCTL_AP_SIOCSIWGENIE, 0, NULL, 0); + break; +#endif /* HOSTAPD_SUPPORT */ + + case SIOCGIWPRIV: + if (wrqin->u.data.pointer) + { + if (access_ok(wrqin->u.data.pointer, sizeof(ap_privtab)) != TRUE) + break; + if ((sizeof(ap_privtab) / sizeof(ap_privtab[0])) <= wrq->u.data.length) + { + wrqin->u.data.length = sizeof(ap_privtab) / sizeof(ap_privtab[0]); + if (copy_to_user(wrqin->u.data.pointer, ap_privtab, sizeof(ap_privtab))) + Status = RTMP_IO_EFAULT; + } + else + Status = RTMP_IO_E2BIG; + } + break; + case RTPRIV_IOCTL_SET: + { + if(access_ok(wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) + Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SET, 0, NULL, 0); + } + break; + + case RTPRIV_IOCTL_SHOW: + { + if(access_ok(wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) + Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SHOW, 0, NULL, 0); + } + break; + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) + case RTPRIV_IOCTL_GET_AR9_SHOW: + { + if( access_ok(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) + Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GET_AR9_SHOW, 0, NULL, 0); + } + break; +#endif /* defined(INF_AR9) || defined(BB_SOC) */ +#endif /* defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) */ + +#ifdef WSC_AP_SUPPORT + case RTPRIV_IOCTL_SET_WSCOOB: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SET_WSCOOB, 0, NULL, 0); + break; +#endif/*WSC_AP_SUPPORT*/ + +/* modified by Red@Ralink, 2009/09/30 */ + case RTPRIV_IOCTL_GET_MAC_TABLE: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GET_MAC_TABLE, 0, NULL, 0); + break; + + case RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT, 0, NULL, 0); + break; +/* end of modification */ + +#ifdef AP_SCAN_SUPPORT + case RTPRIV_IOCTL_GSITESURVEY: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GSITESURVEY, 0, NULL, 0); + break; +#endif /* AP_SCAN_SUPPORT */ + + case RTPRIV_IOCTL_STATISTICS: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_STATISTICS, 0, NULL, 0); + break; + +#ifdef WSC_AP_SUPPORT + case RTPRIV_IOCTL_WSC_PROFILE: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_WSC_PROFILE, 0, NULL, 0); + break; +#endif /* WSC_AP_SUPPORT */ +#ifdef DOT11_N_SUPPORT + case RTPRIV_IOCTL_QUERY_BATABLE: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_QUERY_BATABLE, 0, NULL, 0); + break; +#endif /* DOT11_N_SUPPORT */ + case RTPRIV_IOCTL_E2P: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_E2P, 0, NULL, 0); + break; + +#if defined(DBG) || defined(RALINK_ATE) + case RTPRIV_IOCTL_BBP: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_BBP, 0, NULL, 0); + break; + + case RTPRIV_IOCTL_MAC: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_MAC, 0, NULL, 0); + break; + +#ifdef RTMP_RF_RW_SUPPORT + case RTPRIV_IOCTL_RF: + RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_RF, 0, NULL, 0); + break; +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /* defined(DBG) ||(defined(BB_SOC)&&defined(RALINK_ATE)) */ + + default: +/* DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); */ + Status = RTMP_IO_EOPNOTSUPP; + break; + } + +LabelExit: + if (Status != 0) + { + RT_CMD_STATUS_TRANSLATE(Status); + } + else + { + /* + If wrq length is modified, we reset the lenght of origin wrq; + + Or we can not modify it because the address of wrq->u.data.length + maybe same as other union field, ex: iw_range, etc. + + if the length is not changed but we change it, the value for other + union will also be changed, this is not correct. + */ + if (wrq->u.data.length != org_len) + wrqin->u.data.length = wrq->u.data.length; + } + + return Status; +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/bb_soc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/bb_soc.c new file mode 100644 index 000000000..b6db913d2 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/bb_soc.c @@ -0,0 +1,190 @@ +#include "rt_config.h" + +#include "os/bb_soc.h" +//#include "rtmp_timer.h" +//#include "rt_config.h" +#ifdef WSC_AP_SUPPORT +extern int wscTimerRunning; +extern int wscStatus; +extern int statusprobe; +extern unsigned short wsc_done; +#endif + +/* + ======================================================================== + + Routine Description: + Trendchip DMT Trainning status detect + + Arguments: + data Point to RTMP_ADAPTER + + Return Value: + NONE + + Note: + + ======================================================================== +*/ + +static UCHAR dslStateChg=0; +VOID PeriodicPollingModeDetect( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3){ + unsigned long irqFlags; + UCHAR modem_status=0; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + POS_COOKIE _pObj = (POS_COOKIE)(pAd->OS_Cookie); + + os_TCIfQuery(0x0002, &modem_status, NULL); + + if ((modem_status==0x08)||(modem_status==0x10)) + { + if(!(dslStateChg & (1<<0))){ + RTMP_INT_LOCK(&pAd->irq_lock, irqFlags); + dslStateChg|=(1<<0); + RTMP_INT_UNLOCK(&pAd->irq_lock, irqFlags); + // disable enterrupt + tc3162_disable_irq(_pObj->pci_dev->irq); + } + schedule_work(&pAd->Pollingmode.PollingDataBH); + //slow down the POLLING MODE DETECT while the dmt in wait init state + //pAd->PollingModeDetect.expires = jiffies + POLLING_MODE_DETECT_INTV; + + RTMPModTimer(&pAd->Pollingmode.PollingModeDetect, 10); + pAd->Pollingmode.PollingModeDetectRunning = TRUE; + return; + } + else{ + if(dslStateChg & (1<<0)){ + tc3162_enable_irq(_pObj->pci_dev->irq); + RTMP_INT_LOCK(&pAd->irq_lock, irqFlags); + dslStateChg &=~(1<<0); + RTMP_INT_UNLOCK(&pAd->irq_lock, irqFlags); + } + } + RTMPModTimer(&pAd->Pollingmode.PollingModeDetect, POLLING_MODE_DETECT_INTV); + pAd->Pollingmode.PollingModeDetectRunning = TRUE; +#ifdef WSC_AP_SUPPORT +{ + static int lastWscStatus=0; + PWSC_CTRL pWscControl= &pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl; + + wscTimerRunning=pWscControl->Wsc2MinsTimerRunning; + wscStatus=pWscControl->WscStatus; + + if((wscStatus==STATUS_WSC_CONFIGURED)&&(lastWscStatus!=STATUS_WSC_CONFIGURED)){ + #ifndef LED_WPSSPEC_COMPLY + wsc_done = 10; + #else + wsc_done = 600; + #endif + //ledTurnOff(LED_WLAN_WPS_ACT_STATUS);//xyyou??? + //ledTurnOn(LED_WLAN_WPS_STATUS); + //ledTurnOn(LED_WLAN_WPS_NOACT_STATUS); + + } + lastWscStatus=wscStatus; +} +#endif + return; +} + + +VOID PollingModeIsr(struct work_struct *work) +{ + + PBBUPollingMode pPollingmode=container_of(work, BBUPollingMode, PollingDataBH); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pPollingmode->pAd_va; + struct net_device *net_dev = pAd->net_dev; + rt2860_interrupt(0, net_dev); +} + + +VOID BBUPollingModeClose(IN RTMP_ADAPTER *pAd){ + BOOLEAN Cancelled; + + pAd->Pollingmode.PollingModeDetectRunning = FALSE; + RTMPCancelTimer(&pAd->Pollingmode.PollingModeDetect, &Cancelled); +} + +BUILD_TIMER_FUNCTION(PeriodicPollingModeDetect); + + +VOID BBUPollingModeInit(IN RTMP_ADAPTER *pAd){ + + NdisAllocateSpinLock(&pAd->Pollingmode.PollingModeLock);//for polling mode + + RTMPInitTimer(pAd, &pAd->Pollingmode.PollingModeDetect, GET_TIMER_FUNCTION(PeriodicPollingModeDetect), pAd, FALSE); + pAd->Pollingmode.PollingModeDetectRunning = FALSE; +} + +VOID BBUPollingModeStart(IN RTMP_ADAPTER *pAd){ + + if (pAd->Pollingmode.PollingModeDetectRunning == FALSE) + { + printk("jiffies=%08lx, POLLING_MODE_DETECT_INTV=%d\r\n", jiffies, POLLING_MODE_DETECT_INTV); + RTMPSetTimer(&pAd->Pollingmode.PollingModeDetect, POLLING_MODE_DETECT_INTV); + } + // init a BH task here + INIT_WORK(&(pAd->Pollingmode.PollingDataBH), PollingModeIsr); + +} + +VOID BBU_PCIE_Init(){ + pcieReset(); + pcieRegInitConfig(); +} + +VOID BBUPrepareMAC(IN RTMP_ADAPTER *pAd, PUCHAR macaddr ){ + UCHAR FourByteOffset = 0; + UCHAR NWlanExt = 0; + + FourByteOffset = macaddr[5]%4; + DBGPRINT(RT_DEBUG_WARN, ("\r\nFourByteOffset is %d", FourByteOffset)); + NWlanExt = pAd->ApCfg.BssidNum; + DBGPRINT(RT_DEBUG_WARN, ("\r\nNWlanExt is %d", NWlanExt)); + + + switch(NWlanExt){ + case 1: + break; + case 2: + switch(FourByteOffset){ + case 1: + case 3: + macaddr[5]--; + break; + case 0: + case 2: + break; + } + break; + case 3: + case 4: + switch(FourByteOffset){ + case 0: + break; + case 1: + macaddr[5]--; + break; + case 2: + macaddr[5] -= 2; + break; + case 3: + macaddr[5] -= 3; + break; + } + break; + default: + break; + } + + DBGPRINT(RT_DEBUG_WARN,("current MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], + macaddr[2], macaddr[3], + macaddr[4], macaddr[5])); + /*generate bssid from cpe mac address end, merge from linos, 20100208*/ +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/br_ftph.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/br_ftph.c new file mode 100644 index 000000000..b012e50ab --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/br_ftph.c @@ -0,0 +1,194 @@ +/**************************************************************************** + * 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: + bg_ftph.c + + Abstract: + Provide fast path between LAN and WLAN. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sample Lin 01-22-2008 Created + + */ + +#include "rt_config.h" + +#ifdef BG_FT_SUPPORT +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +#include +#include "../net/bridge/br_private.h" + +/* extern export symbol in other drivers */ +/* + Example in other drivers: + UINT32 (*RALINK_FP_Handle)(PNDIS_PACKET pPacket); + EXPORT_SYMBOL(RALINK_FP_Handle); + + packet_forward() + { + UINT32 HandRst = 1; + + ...... + + if (RALINK_FP_Handle != NULL) + HandRst = RALINK_FP_Handle(skb); + + if (HandRst != 0) + { + // pass the packet to upper layer + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); + } + } +*/ +UINT32 BG_FTPH_PacketFromApHandle(PNDIS_PACKET pPacket); + +#ifdef BG_FT_OPEN_SUPPORT +extern UINT32 (*RALINK_FP_Handle)(PNDIS_PACKET pPacket); +#else +UINT32 (*RALINK_FP_Handle)(PNDIS_PACKET pPacket); +#endif /* BG_FT_OPEN_SUPPORT */ + + + + +/* --------------------------------- Public -------------------------------- */ + +/* +======================================================================== +Routine Description: + Init bridge fast path module. + +Arguments: + None + +Return Value: + None + +Note: + Used in module init. +======================================================================== +*/ +VOID BG_FTPH_Init(VOID) +{ + RALINK_FP_Handle = BG_FTPH_PacketFromApHandle; +} + + +/* +======================================================================== +Routine Description: + Remove bridge fast path module. + +Arguments: + None + +Return Value: + None + +Note: + Used in module remove. +======================================================================== +*/ +VOID BG_FTPH_Remove(VOID) +{ + RALINK_FP_Handle = NULL; +} /* End of BG_FTPH_Init */ + + + + +/* +======================================================================== +Routine Description: + Forward the received packet. + +Arguments: + pPacket - the received packet + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 BG_FTPH_PacketFromApHandle( + IN PNDIS_PACKET pPacket) +{ + struct net_device *pNetDev; + struct sk_buff *pRxPkt; + struct net_bridge_fdb_entry *pSrcFdbEntry, *pDstFdbEntry; + + + /* init */ + pRxPkt = RTPKT_TO_OSPKT(pPacket); + pNetDev = pRxPkt->dev; + + /* if pNetDev is promisc mode ??? */ + DBGPRINT(RT_DEBUG_INFO, ("ft bg> BG_FTPH_PacketFromApHandle\n")); + + if (pNetDev != NULL) + { + if (pNetDev->br_port != NULL) + { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) + pDstFdbEntry = br_fdb_get_hook(pNetDev->br_port->br, pRxPkt->data); + pSrcFdbEntry = br_fdb_get_hook(pNetDev->br_port->br, pRxPkt->data + 6); +#else + /* br_fdb_get is not exported symbol, need exported in net/bridge/br.c */ + pDstFdbEntry = br_fdb_get(pNetDev->br_port->br, pRxPkt->data); + pSrcFdbEntry = br_fdb_get(pNetDev->br_port->br, pRxPkt->data + 6); +#endif + + /* check destination address in bridge forwarding table */ + if ((pSrcFdbEntry == NULL) || + (pDstFdbEntry == NULL) || + (pDstFdbEntry->is_local) || + (pDstFdbEntry->dst == NULL) || + (pDstFdbEntry->dst->dev == NULL) || + (pDstFdbEntry->dst->dev == pNetDev) || + (pNetDev->br_port->state != BR_STATE_FORWARDING) || + ((pSrcFdbEntry->dst != NULL) && + (pSrcFdbEntry->dst->dev != NULL) && + (pSrcFdbEntry->dst->dev != pNetDev))) + { + + goto LabelPassToUpperLayer; + } /* End of if */ + + if ((!pDstFdbEntry->is_local) && + (pDstFdbEntry->dst != NULL) && + (pDstFdbEntry->dst->dev != NULL)) + { + pRxPkt->dev = pDstFdbEntry->dst->dev; + pDstFdbEntry->dst->dev->hard_start_xmit(pRxPkt, pDstFdbEntry->dst->dev); + return 0; + } /* End of if */ + } /* End of if */ + } /* End of if */ + +LabelPassToUpperLayer: + DBGPRINT(RT_DEBUG_TRACE, ("ft bg> Pass packet to bridge module.\n")); + return 1; +} /* End of BG_FTPH_PacketFromApHandle */ + + +#endif /* CONFIG_BRIDGE || CONFIG_BRIDGE_MODULE */ +#endif /* BG_FT_SUPPORT */ + +/* End of bg_ftph.c */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211.c new file mode 100644 index 000000000..3d3b8193e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211.c @@ -0,0 +1,3295 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 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. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related CFG80211 function body. + + History: + 1. 2009/09/17 Sample Lin + (1) Init version. + 2. 2009/10/27 Sample Lin + (1) Do not use ieee80211_register_hw() to create virtual interface. + Use wiphy_register() to register nl80211 command handlers. + (2) Support iw utility. + 3. 2009/11/03 Sample Lin + (1) Change name MAC80211 to CFG80211. + (2) Modify CFG80211_OpsChannelSet(). + (3) Move CFG80211_Register()/CFG80211_UnRegister() to open/close. + 4. 2009/12/16 Sample Lin + (1) Patch for Linux 2.6.32. + (2) Add more supported functions in CFG80211_Ops. + 5. 2010/12/10 Sample Lin + (1) Modify for OS_ABL. + 6. 2011/04/19 Sample Lin + (1) Add more supported functions in CFG80211_Ops v33 ~ 38. + + Note: + The feature is supported only in "LINUX" 2.6.28 ~ 2.6.38. + +***************************************************************************/ + + +#define RTMP_MODULE_OS + +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +#include "rt_config.h" +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) +#ifdef RT_CFG80211_SUPPORT + +/* 36 ~ 64, 100 ~ 136, 140 ~ 161 */ +#define CFG80211_NUM_OF_CHAN_5GHZ (sizeof(Cfg80211_Chan)-CFG80211_NUM_OF_CHAN_2GHZ) + +#ifdef OS_ABL_FUNC_SUPPORT +/* + Array of bitrates the hardware can operate with + in this band. Must be sorted to give a valid "supported + rates" IE, i.e. CCK rates first, then OFDM. + + For HT, assign MCS in another structure, ieee80211_sta_ht_cap. +*/ +const struct ieee80211_rate Cfg80211_SupRate[12] = { + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 10, /* bitrate in units of 100 Kbps */ + .hw_value = 0, + .hw_value_short = 0, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 20, + .hw_value = 1, + .hw_value_short = 1, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 55, + .hw_value = 2, + .hw_value_short = 2, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 110, + .hw_value = 3, + .hw_value_short = 3, + }, + { + .flags = 0, + .bitrate = 60, + .hw_value = 4, + .hw_value_short = 4, + }, + { + .flags = 0, + .bitrate = 90, + .hw_value = 5, + .hw_value_short = 5, + }, + { + .flags = 0, + .bitrate = 120, + .hw_value = 6, + .hw_value_short = 6, + }, + { + .flags = 0, + .bitrate = 180, + .hw_value = 7, + .hw_value_short = 7, + }, + { + .flags = 0, + .bitrate = 240, + .hw_value = 8, + .hw_value_short = 8, + }, + { + .flags = 0, + .bitrate = 360, + .hw_value = 9, + .hw_value_short = 9, + }, + { + .flags = 0, + .bitrate = 480, + .hw_value = 10, + .hw_value_short = 10, + }, + { + .flags = 0, + .bitrate = 540, + .hw_value = 11, + .hw_value_short = 11, + }, +}; +#endif /* OS_ABL_FUNC_SUPPORT */ + +/* all available channels */ +static const UCHAR Cfg80211_Chan[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + + /* 802.11 UNI / HyperLan 2 */ + 36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64, + + /* 802.11 HyperLan 2 */ + 100, 104, 108, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136, + + /* 802.11 UNII */ + 140, 149, 151, 153, 157, 159, 161, 165, 167, 169, 171, 173, + + /* Japan */ + 184, 188, 192, 196, 208, 212, 216, +}; + + +static const UINT32 CipherSuites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +#ifdef DOT11W_PMF_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + WLAN_CIPHER_SUITE_AES_CMAC, +#endif /* LINUX_VERSION_CODE */ +#endif /* DOT11W_PMF_SUPPORT */ +}; + +/* + The driver's regulatory notification callback. +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +static INT32 CFG80211_RegNotifier( + IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest); +#else +static INT32 CFG80211_RegNotifier( + IN struct wiphy *pWiphy, + IN enum reg_set_by Request); +#endif /* LINUX_VERSION_CODE */ + + +/* get RALINK pAd control block in 80211 Ops */ +#define MAC80211_PAD_GET(__pAd, __pWiphy) \ + { \ + ULONG *__pPriv; \ + __pPriv = (ULONG *)(wiphy_priv(__pWiphy)); \ + __pAd = (VOID *)(*__pPriv); \ + if (__pAd == NULL) \ + { \ + DBGPRINT(RT_DEBUG_ERROR, \ + ("80211> %s but pAd = NULL!", __FUNCTION__)); \ + return -EINVAL; \ + } \ + } + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static int CFG80211_OpsMonitorChannelSet(struct wiphy *pWiphy, + struct cfg80211_chan_def *chandef) +{ + VOID *pAd; + CFG80211_CB *p80211CB; + CMD_RTPRIV_IOCTL_80211_CHAN ChanInfo; + UINT32 ChanId; + + struct device *pDev = pWiphy->dev.parent; + struct net_device *pNetDev = dev_get_drvdata(pDev); + struct ieee80211_channel *pChan; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + //return 0; + MAC80211_PAD_GET(pAd, pWiphy); + pChan=chandef->chan; + + + + printk("control:%d MHz width:%d center: %d/%d MHz", + pChan->center_freq, chandef->width, + chandef->center_freq1, chandef->center_freq2); + + + /* get channel number */ + ChanId = ieee80211_frequency_to_channel(pChan->center_freq); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Channel = %d\n", ChanId)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> ChannelType = %d\n", chandef->width)); + + /* init */ + memset(&ChanInfo, 0, sizeof(ChanInfo)); + ChanInfo.ChanId = ChanId; + + p80211CB = NULL; + RTMP_DRIVER_80211_CB_GET(pAd, &p80211CB); + + if (p80211CB == NULL) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> p80211CB == NULL!\n")); + return 0; + } + + ChanInfo.IfType = pNetDev->ieee80211_ptr->iftype; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> ChanInfo.IfType == %d!\n",ChanInfo.IfType)); + + if (cfg80211_get_chandef_type(chandef) == NL80211_CHAN_NO_HT) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_NOHT; + else if (cfg80211_get_chandef_type(chandef) == NL80211_CHAN_HT20) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_HT20; + else if (cfg80211_get_chandef_type(chandef) == NL80211_CHAN_HT40MINUS) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_HT40MINUS; + else if (cfg80211_get_chandef_type(chandef) == NL80211_CHAN_HT40PLUS) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_HT40PLUS; + + ChanInfo.MonFilterFlag = p80211CB->MonFilterFlag; + + /* set channel */ + RTMP_DRIVER_80211_CHAN_SET(pAd, &ChanInfo); + + return 0; +} /* End of CFG80211_OpsChannelSet */ +#endif + + +/* +======================================================================== +Routine Description: + Set channel. + +Arguments: + pWiphy - Wireless hardware description + pChan - Channel information + ChannelType - Channel type + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: set channel, set freq + + enum nl80211_channel_type { + NL80211_CHAN_NO_HT, + NL80211_CHAN_HT20, + NL80211_CHAN_HT40MINUS, + NL80211_CHAN_HT40PLUS + }; +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) +static int CFG80211_OpsChannelSet( + IN struct wiphy *pWiphy, + IN struct net_device *pDev, + IN struct ieee80211_channel *pChan, + IN enum nl80211_channel_type ChannelType) + +#else +static int CFG80211_OpsChannelSet( + IN struct wiphy *pWiphy, + IN struct ieee80211_channel *pChan, + IN enum nl80211_channel_type ChannelType) +#endif /* LINUX_VERSION_CODE */ +{ + VOID *pAd; + CFG80211_CB *p80211CB; + CMD_RTPRIV_IOCTL_80211_CHAN ChanInfo; + UINT32 ChanId; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + /* get channel number */ + ChanId = ieee80211_frequency_to_channel(pChan->center_freq); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Channel = %d, Type = %d\n", ChanId, ChannelType)); + + /* init */ + memset(&ChanInfo, 0, sizeof(ChanInfo)); + ChanInfo.ChanId = ChanId; + + p80211CB = NULL; + RTMP_DRIVER_80211_CB_GET(pAd, &p80211CB); + + if (p80211CB == NULL) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> p80211CB == NULL!\n")); + return 0; + } + + ChanInfo.IfType = pDev->ieee80211_ptr->iftype; + + if (ChannelType == NL80211_CHAN_NO_HT) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_NOHT; + else if (ChannelType == NL80211_CHAN_HT20) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_HT20; + else if (ChannelType == NL80211_CHAN_HT40MINUS) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_HT40MINUS; + else if (ChannelType == NL80211_CHAN_HT40PLUS) + ChanInfo.ChanType = RT_CMD_80211_CHANTYPE_HT40PLUS; + + ChanInfo.MonFilterFlag = p80211CB->MonFilterFlag; + + /* set channel */ + RTMP_DRIVER_80211_CHAN_SET(pAd, &ChanInfo); + + return 0; +} + + +/* +======================================================================== +Routine Description: + Change type/configuration of virtual interface. + +Arguments: + pWiphy - Wireless hardware description + IfIndex - Interface index + Type - Interface type, managed/adhoc/ap/station, etc. + pFlags - Monitor flags + pParams - Mesh parameters + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: set type, set monitor +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) +static int CFG80211_OpsVirtualInfChg( + IN struct wiphy *pWiphy, + IN struct net_device *pNetDevIn, + IN enum nl80211_iftype Type, + IN u32 *pFlags, + struct vif_params *pParams) +#else +static int CFG80211_OpsVirtualInfChg( + IN struct wiphy *pWiphy, + IN int IfIndex, + IN enum nl80211_iftype Type, + IN u32 *pFlags, + struct vif_params *pParams) +#endif /* LINUX_VERSION_CODE */ +{ + VOID *pAd; + CFG80211_CB *pCfg80211_CB; + struct net_device *pNetDev; + CMD_RTPRIV_IOCTL_80211_VIF_PARM VifInfo; + UINT oldType = pNetDevIn->ieee80211_ptr->iftype; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> IfTypeChange %d ==> %d\n", oldType, Type)); + MAC80211_PAD_GET(pAd, pWiphy); + + /* sanity check */ +#ifdef CONFIG_STA_SUPPORT + if ((Type != NL80211_IFTYPE_ADHOC) && + (Type != NL80211_IFTYPE_STATION) && + (Type != NL80211_IFTYPE_MONITOR) && + (Type != NL80211_IFTYPE_AP) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + && (Type != NL80211_IFTYPE_P2P_CLIENT) + && (Type != NL80211_IFTYPE_P2P_GO) +#endif /* LINUX_VERSION_CODE 2.6.37 */ + ) +#endif /* CONFIG_STA_SUPPORT */ + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Wrong interface type %d!\n", Type)); + return -EINVAL; + } /* End of if */ + + /* update interface type */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + pNetDev = pNetDevIn; +#else + pNetDev = __dev_get_by_index(&init_net, IfIndex); +#endif /* LINUX_VERSION_CODE */ + + if (pNetDev == NULL) + return -ENODEV; + + pNetDev->ieee80211_ptr->iftype = Type; + + VifInfo.net_dev = pNetDev; + VifInfo.newIfType = Type; + VifInfo.oldIfType = oldType; + + if (pFlags != NULL) + { + VifInfo.MonFilterFlag = 0; + + if (((*pFlags) & NL80211_MNTR_FLAG_FCSFAIL) == NL80211_MNTR_FLAG_FCSFAIL) + VifInfo.MonFilterFlag |= RT_CMD_80211_FILTER_FCSFAIL; + + if (((*pFlags) & NL80211_MNTR_FLAG_FCSFAIL) == NL80211_MNTR_FLAG_PLCPFAIL) + VifInfo.MonFilterFlag |= RT_CMD_80211_FILTER_PLCPFAIL; + + if (((*pFlags) & NL80211_MNTR_FLAG_CONTROL) == NL80211_MNTR_FLAG_CONTROL) + VifInfo.MonFilterFlag |= RT_CMD_80211_FILTER_CONTROL; + + if (((*pFlags) & NL80211_MNTR_FLAG_CONTROL) == NL80211_MNTR_FLAG_OTHER_BSS) + VifInfo.MonFilterFlag |= RT_CMD_80211_FILTER_OTHER_BSS; + } + + /* Type transer from linux to driver defined */ + if (Type == NL80211_IFTYPE_STATION) + { + Type = RT_CMD_80211_IFTYPE_STATION; + } + else if (Type == NL80211_IFTYPE_ADHOC) + { + Type = RT_CMD_80211_IFTYPE_ADHOC; + } + else if (Type == NL80211_IFTYPE_MONITOR) + { + Type = RT_CMD_80211_IFTYPE_MONITOR; + } +#ifdef CONFIG_AP_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + else if (Type == NL80211_IFTYPE_P2P_CLIENT) + { + Type = RT_CMD_80211_IFTYPE_P2P_CLIENT; + } + else if (Type == NL80211_IFTYPE_P2P_GO) + { + Type = RT_CMD_80211_IFTYPE_P2P_GO; + } +#endif /* LINUX_VERSION_CODE 2.6.37 */ +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_DRIVER_80211_VIF_CHG(pAd, &VifInfo); + + /*CFG_TODO*/ + RTMP_DRIVER_80211_CB_GET(pAd, &pCfg80211_CB); + pCfg80211_CB->MonFilterFlag = VifInfo.MonFilterFlag; + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#if defined(SIOCGIWSCAN) || defined(RT_CFG80211_SUPPORT) +extern int rt_ioctl_siwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wreq, char *extra); +#endif /* LINUX_VERSION_CODE: 2.6.30 */ +/* +======================================================================== +Routine Description: + Request to do a scan. If returning zero, the scan request is given + the driver, and will be valid until passed to cfg80211_scan_done(). + For scan results, call cfg80211_inform_bss(); you can call this outside + the scan/scan_done bracket too. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + pRequest - Scan request + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: scan + + struct cfg80211_scan_request { + struct cfg80211_ssid *ssids; + int n_ssids; + struct ieee80211_channel **channels; + u32 n_channels; + const u8 *ie; + size_t ie_len; + + * @ssids: SSIDs to scan for (active scan only) + * @n_ssids: number of SSIDs + * @channels: channels to scan on. + * @n_channels: number of channels for each band + * @ie: optional information element(s) to add into Probe Request or %NULL + * @ie_len: length of ie in octets +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static int CFG80211_OpsScan( + IN struct wiphy *pWiphy, + IN struct cfg80211_scan_request *pRequest) +#else +static int CFG80211_OpsScan( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_scan_request *pRequest) +#endif /* LINUX_VERSION_CODE: 3.6.0 */ +{ +#ifdef CONFIG_STA_SUPPORT + VOID *pAd; + CFG80211_CB *pCfg80211_CB; + + struct iw_scan_req IwReq; + union iwreq_data Wreq; + + MAC80211_PAD_GET(pAd, pWiphy); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct net_device *pNdev = NULL; + RTMP_DRIVER_NET_DEV_GET(pAd, &pNdev); +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + CFG80211DBG(RT_DEBUG_TRACE, ("========================================================================\n")); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==> %s(%d)\n", __FUNCTION__, pNdev->name, pNdev->ieee80211_ptr->iftype)); + + + /* YF_TODO: record the scan_req per netdevice */ + RTMP_DRIVER_80211_CB_GET(pAd, &pCfg80211_CB); + pCfg80211_CB->pCfg80211_ScanReq = pRequest; /* used in scan end */ + + if (pNdev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) + { + CFG80211OS_ScanEnd(pCfg80211_CB, TRUE); + return 0; + } + /* sanity check */ + if ((pNdev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) && + (pNdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) && + (pNdev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + && (pNdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) +#endif + ) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> DeviceType Not Support Scan ==> %d\n", pNdev->ieee80211_ptr->iftype)); + CFG80211OS_ScanEnd(pCfg80211_CB, TRUE); + return -EOPNOTSUPP; + } + + /* Driver Internal SCAN SM Check */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Network is down!\n")); + CFG80211OS_ScanEnd(pCfg80211_CB, TRUE); + return -ENETDOWN; + } + + if (RTMP_DRIVER_80211_SCAN(pAd, pNdev->ieee80211_ptr->iftype) != NDIS_STATUS_SUCCESS) + { + CFG80211DBG(RT_DEBUG_ERROR, ("\n\n\n\n\n80211> BUSY - SCANING \n\n\n\n\n")); + CFG80211OS_ScanEnd(pCfg80211_CB, TRUE); + return 0; + } + + + if (pRequest->ie_len != 0 ) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> ExtraIEs Not Null in ProbeRequest from upper layer...\n")); + /* YF@20120321: Using Cfg80211_CB carry on pAd struct to overwirte the pWpsProbeReqIe. */ + RTMP_DRIVER_80211_SCAN_EXTRA_IE_SET(pAd); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> ExtraIEs Null in ProbeRequest from upper layer...\n")); + } + + memset(&Wreq, 0, sizeof(Wreq)); + memset(&IwReq, 0, sizeof(IwReq)); + + DBGPRINT(RT_DEBUG_INFO, ("80211> Num %d of SSID & ssidLen %d from upper layer...\n", + pRequest->n_ssids, pRequest->ssids->ssid_len)); + + /* %NULL or zero-length SSID is used to indicate wildcard */ + if ((pRequest->n_ssids == 1) && (pRequest->ssids->ssid_len ==0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Wildcard SSID In ProbeRequest.\n")); + Wreq.data.flags |= IW_SCAN_ALL_ESSID; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Named SSID [%s] In ProbeRequest.\n", pRequest->ssids->ssid)); + Wreq.data.flags |= IW_SCAN_THIS_ESSID; + + /* Fix kernel crash when ssid is null instead of wildcard ssid */ + if (pRequest->ssids->ssid == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Scanning failed!!!\n")); + CFG80211OS_ScanEnd(pCfg80211_CB, TRUE); + return -1; + } + } + + /* Set Channel List for this Scan Action */ + DBGPRINT(RT_DEBUG_INFO, ("80211> [%d] Channels In ProbeRequest.\n", pRequest->n_channels)); + if ( pRequest->n_channels > 0 ) + { + UINT32 *pChanList; + UINT idx; + os_alloc_mem(NULL, (UCHAR **)&pChanList, sizeof(UINT32 *) * pRequest->n_channels); + if (pChanList == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Alloc memory fail\n", __FUNCTION__)); + return FALSE; + } + + for(idx=0; idx < pRequest->n_channels; idx++) + { + pChanList[idx] = ieee80211_frequency_to_channel(pRequest->channels[idx]->center_freq); + CFG80211DBG(RT_DEBUG_INFO, ("%d,", pChanList[idx])); + } + CFG80211DBG(RT_DEBUG_INFO, ("\n")); + + RTMP_DRIVER_80211_SCAN_CHANNEL_LIST_SET(pAd, pChanList, pRequest->n_channels); + + if (pChanList) + os_free_mem(NULL, pChanList); + } + + /* use 1st SSID in the requested SSID list */ + IwReq.essid_len = pRequest->ssids->ssid_len; + memcpy(IwReq.essid, pRequest->ssids->ssid, sizeof(IwReq.essid)); + Wreq.data.length = sizeof(struct iw_scan_req); + + rt_ioctl_siwscan(pNdev, NULL, &Wreq, (char *)&IwReq); + return 0; + +#else + return -EOPNOTSUPP; +#endif /* CONFIG_STA_SUPPORT */ +} +#endif /* LINUX_VERSION_CODE */ + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) +#ifdef CONFIG_STA_SUPPORT +/* +======================================================================== +Routine Description: + Join the specified IBSS (or create if necessary). Once done, call + cfg80211_ibss_joined(), also call that function when changing BSSID due + to a merge. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + pParams - IBSS parameters + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: ibss join + + No fixed-freq and fixed-bssid support. +======================================================================== +*/ +static int CFG80211_OpsIbssJoin( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_ibss_params *pParams) +{ + VOID *pAd; + UCHAR *beacon_buf = NULL; + CMD_RTPRIV_IOCTL_80211_IBSS IbssInfo; + UINT channel = 0; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + /* init */ + memset(&IbssInfo, 0, sizeof(IbssInfo)); + IbssInfo.BeaconInterval = pParams->beacon_interval; + memcpy(&IbssInfo.Ssid, pParams->ssid, pParams->ssid_len); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + channel = pParams->chandef.chan->center_freq; +#else + channel = pParams->channel->center_freq; +#endif /* LINUX_VERSION_CODE 3.8.0 */ + CFG80211DBG(RT_DEBUG_OFF, ("80211> SSID = %s, BI = %d, CH = %d, CH_FIX = %d, Privacy = %d\n", + IbssInfo.Ssid, pParams->beacon_interval, + channel, pParams->channel_fixed, pParams->privacy)); + + if (pParams->ie && (pParams->ie_len > 0)) + { + hex_dump("ADHOC_IE", pParams->ie , pParams->ie_len); + IbssInfo.BeaconExtraIeLen = pParams->ie_len; + + os_alloc_mem(NULL, &beacon_buf, pParams->ie_len); + NdisCopyMemory(beacon_buf, pParams->ie, pParams->ie_len); + IbssInfo.BeaconExtraIe = beacon_buf; + } + + if (pParams->privacy) + { + IbssInfo.privacy = pParams->privacy; + } + + if (pParams->bssid) + { + CFG80211DBG(RT_DEBUG_OFF, ("Join this BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", + PRINT_MAC(pParams->bssid))); + } + else + { + CFG80211DBG(RT_DEBUG_OFF, ("Can't find any AdHoc, create IBSS\n")); + + } + /* ibss join */ + RTMP_DRIVER_80211_IBSS_JOIN(pAd, &IbssInfo); + + return 0; +} + + +/* +======================================================================== +Routine Description: + Leave the IBSS. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: ibss leave +======================================================================== +*/ +static int CFG80211_OpsIbssLeave( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev) +{ + VOID *pAd; + + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + //CFG_TODO + RTMP_DRIVER_80211_STA_LEAVE(pAd, pNdev->ieee80211_ptr->iftype); + return 0; +} +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) +/* +======================================================================== +Routine Description: + Set the transmit power according to the parameters. + +Arguments: + pWiphy - Wireless hardware description + Type - + dBm - dBm + +Return Value: + 0 - success + -x - fail + +Note: + Type - + enum nl80211_tx_power_setting - TX power adjustment + @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power + @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter + @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter +======================================================================== +*/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) +static int CFG80211_OpsTxPwrSet( + IN struct wiphy *pWiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + IN struct wireless_dev *wdev, +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) + IN enum nl80211_tx_power_setting Type, +#else + IN enum tx_power_setting Type, +#endif /* LINUX_VERSION_CODE */ + IN int dBm) +{ + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + return -EOPNOTSUPP; +} + + +/* +======================================================================== +Routine Description: + Store the current TX power into the dbm variable. + +Arguments: + pWiphy - Wireless hardware description + pdBm - dBm + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsTxPwrGet( + IN struct wiphy *pWiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + IN struct wireless_dev *wdev, +#endif + IN int *pdBm) +{ + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + return -EOPNOTSUPP; +} /* End of CFG80211_OpsTxPwrGet */ + +#endif + + +/* +======================================================================== +Routine Description: + Power management. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + FlgIsEnabled - + Timeout - + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsPwrMgmt( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN bool enabled, + IN INT32 timeout) +{ + VOID *pAd; + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==> power save %s\n", __FUNCTION__,(enabled ? "enable" : "disable"))); + + MAC80211_PAD_GET(pAd, pWiphy); + + RTMP_DRIVER_80211_POWER_MGMT_SET(pAd,enabled); + return 0; +} /* End of CFG80211_OpsPwrMgmt */ + + +/* +======================================================================== +Routine Description: + Get information for a specific station. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + pMac - STA MAC + pSinfo - STA INFO + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsStaGet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 *pMac, + IN struct station_info *pSinfo) +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_STA StaInfo; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + /* init */ + memset(pSinfo, 0, sizeof(*pSinfo)); + memset(&StaInfo, 0, sizeof(StaInfo)); + + memcpy(StaInfo.MAC, pMac, 6); + + /* get sta information */ + if (RTMP_DRIVER_80211_STA_GET(pAd, &StaInfo) != NDIS_STATUS_SUCCESS) + return -ENOENT; + + if (StaInfo.TxRateFlags != RT_CMD_80211_TXRATE_LEGACY) + { + pSinfo->txrate.flags = RATE_INFO_FLAGS_MCS; + if (StaInfo.TxRateFlags & RT_CMD_80211_TXRATE_BW_40) + pSinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + + if (StaInfo.TxRateFlags & RT_CMD_80211_TXRATE_SHORT_GI) + pSinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + + + pSinfo->txrate.mcs = StaInfo.TxRateMCS; + } + else + { + pSinfo->txrate.legacy = StaInfo.TxRateMCS; + } + + pSinfo->filled |= STATION_INFO_TX_BITRATE; + + /* fill signal */ + pSinfo->signal = StaInfo.Signal; + pSinfo->filled |= STATION_INFO_SIGNAL; + +#ifdef CONFIG_AP_SUPPORT + /* fill tx count */ + pSinfo->tx_packets = StaInfo.TxPacketCnt; + pSinfo->filled |= STATION_INFO_TX_PACKETS; + + /* fill inactive time */ + pSinfo->inactive_time = StaInfo.InactiveTime; + pSinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif /* CONFIG_AP_SUPPORT */ + + return 0; +} + + +/* +======================================================================== +Routine Description: + List all stations known, e.g. the AP on managed interfaces. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + Idx - + pMac - + pSinfo - + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsStaDump( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN int Idx, + IN UINT8 *pMac, + IN struct station_info *pSinfo) +{ + VOID *pAd; + + if (Idx != 0) + return -ENOENT; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + +#ifdef CONFIG_STA_SUPPORT + if (RTMP_DRIVER_AP_SSID_GET(pAd, pMac) != NDIS_STATUS_SUCCESS) + return -EBUSY; + else + return CFG80211_OpsStaGet(pWiphy, pNdev, pMac, pSinfo); +#endif /* CONFIG_STA_SUPPORT */ + + return -EOPNOTSUPP; +} /* End of CFG80211_OpsStaDump */ + + +/* +======================================================================== +Routine Description: + Notify that wiphy parameters have changed. + +Arguments: + pWiphy - Wireless hardware description + Changed - + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsWiphyParamsSet( + IN struct wiphy *pWiphy, + IN UINT32 Changed) +{ + VOID *pAd; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + if (Changed & WIPHY_PARAM_RTS_THRESHOLD) + { + RTMP_DRIVER_80211_RTS_THRESHOLD_ADD(pAd, pWiphy->rts_threshold); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==> rts_threshold(%d)\n", __FUNCTION__,pWiphy->rts_threshold)); + return 0; + } else if (Changed & WIPHY_PARAM_FRAG_THRESHOLD) { + RTMP_DRIVER_80211_FRAG_THRESHOLD_ADD(pAd, pWiphy->frag_threshold); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==> frag_threshold(%d)\n", __FUNCTION__,pWiphy->frag_threshold)); + return 0; + } + + return -EOPNOTSUPP; +} /* End of CFG80211_OpsWiphyParamsSet */ + + +/* +======================================================================== +Routine Description: + Add a key with the given parameters. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + KeyIdx - + Pairwise - + pMacAddr - + pParams - + +Return Value: + 0 - success + -x - fail + +Note: + pMacAddr will be NULL when adding a group key. +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) +static int CFG80211_OpsKeyAdd( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN bool Pairwise, + IN const UINT8 *pMacAddr, + IN struct key_params *pParams) +#else + +static int CFG80211_OpsKeyAdd( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN const UINT8 *pMacAddr, + IN struct key_params *pParams) +#endif /* LINUX_VERSION_CODE */ +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_KEY KeyInfo; + CFG80211_CB *p80211CB; + p80211CB = NULL; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + +#ifdef RT_CFG80211_DEBUG + hex_dump("KeyBuf=", (UINT8 *)pParams->key, pParams->key_len); +#endif /* RT_CFG80211_DEBUG */ + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> KeyIdx = %d, pParams->cipher=%x\n", KeyIdx,pParams->cipher)); + + if (pParams->key_len >= sizeof(KeyInfo.KeyBuf)) + return -EINVAL; + /* End of if */ + + + /* init */ + memset(&KeyInfo, 0, sizeof(KeyInfo)); + memcpy(KeyInfo.KeyBuf, pParams->key, pParams->key_len); + KeyInfo.KeyBuf[pParams->key_len] = 0x00; + KeyInfo.KeyId = KeyIdx; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + KeyInfo.bPairwise = Pairwise; +#endif + KeyInfo.KeyLen = pParams->key_len; + + + if ((pParams->cipher == WLAN_CIPHER_SUITE_WEP40)) + { + KeyInfo.KeyType = RT_CMD_80211_KEY_WEP40; + } + else if ((pParams->cipher == WLAN_CIPHER_SUITE_WEP104)) + { + KeyInfo.KeyType = RT_CMD_80211_KEY_WEP104; + } + else if ((pParams->cipher == WLAN_CIPHER_SUITE_TKIP) || + (pParams->cipher == WLAN_CIPHER_SUITE_CCMP)) + { + KeyInfo.KeyType = RT_CMD_80211_KEY_WPA; + if (pParams->cipher == WLAN_CIPHER_SUITE_TKIP) + KeyInfo.cipher = Ndis802_11TKIPEnable; + else if (pParams->cipher == WLAN_CIPHER_SUITE_CCMP) + KeyInfo.cipher = Ndis802_11AESEnable; + } +#ifdef DOT11W_PMF_SUPPORT +//PMF IGTK +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + else if (pParams->cipher == WLAN_CIPHER_SUITE_AES_CMAC) + { + KeyInfo.KeyType = RT_CMD_80211_KEY_AES_CMAC; + KeyInfo.KeyId = KeyIdx; + KeyInfo.bPairwise = FALSE; + KeyInfo.KeyLen = pParams->key_len; + } +#endif /* LINUX_VERSION_CODE */ +#endif /* DOT11W_PMF_SUPPORT */ + else + return -ENOTSUPP; + + /* add key */ + RTMP_DRIVER_80211_CB_GET(pAd, &p80211CB); + +#ifdef CONFIG_AP_SUPPORT + if ((pNdev->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_AP) || + (pNdev->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_P2P_GO)) + { + if(pMacAddr) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> KeyAdd STA(%02X:%02X:%02X:%02X:%02X:%02X) ==>\n", + PRINT_MAC(pMacAddr))); + NdisCopyMemory(KeyInfo.MAC, pMacAddr, MAC_ADDR_LEN); + } + CFG80211DBG(RT_DEBUG_OFF, ("80211> AP Key Add\n")); + RTMP_DRIVER_80211_AP_KEY_ADD(pAd, &KeyInfo); + } + else +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (pNdev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> APCLI Key Add\n")); + RTMP_DRIVER_80211_P2P_CLIENT_KEY_ADD(pAd, &KeyInfo); + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + { +#ifdef CONFIG_STA_SUPPORT + CFG80211DBG(RT_DEBUG_TRACE, ("80211> STA Key Add\n")); + RTMP_DRIVER_80211_STA_KEY_ADD(pAd, &KeyInfo); +#endif + } + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + if(pMacAddr) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> P2pSendWirelessEvent(%02X:%02X:%02X:%02X:%02X:%02X) ==>\n", + PRINT_MAC(pMacAddr))); + RTMP_DRIVER_80211_SEND_WIRELESS_EVENT(pAd, pMacAddr); + } +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + + return 0; + + +} + + +/* +======================================================================== +Routine Description: + Get information about the key with the given parameters. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + KeyIdx - + Pairwise - + pMacAddr - + pCookie - + pCallback - + +Return Value: + 0 - success + -x - fail + +Note: + pMacAddr will be NULL when requesting information for a group key. + + All pointers given to the pCallback function need not be valid after + it returns. + + This function should return an error if it is not possible to + retrieve the key, -ENOENT if it doesn't exist. +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) +static int CFG80211_OpsKeyGet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN bool Pairwise, + IN const UINT8 *pMacAddr, + IN void *pCookie, + IN void (*pCallback)(void *cookie, + struct key_params *)) +#else + +static int CFG80211_OpsKeyGet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN const UINT8 *pMacAddr, + IN void *pCookie, + IN void (*pCallback)(void *cookie, + struct key_params *)) +#endif /* LINUX_VERSION_CODE */ +{ + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + return -ENOTSUPP; +} + + +/* +======================================================================== +Routine Description: + Remove a key given the pMacAddr (NULL for a group key) and KeyIdx. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + KeyIdx - + pMacAddr - + +Return Value: + 0 - success + -x - fail + +Note: + return -ENOENT if the key doesn't exist. +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) +static int CFG80211_OpsKeyDel( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN bool Pairwise, + IN const UINT8 *pMacAddr) +#else + +static int CFG80211_OpsKeyDel( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN const UINT8 *pMacAddr) +#endif /* LINUX_VERSION_CODE */ +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_KEY KeyInfo; + CFG80211_CB *p80211CB; + p80211CB = NULL; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + if (pMacAddr) + { + CFG80211DBG(RT_DEBUG_OFF, ("80211> KeyDel STA(%02X:%02X:%02X:%02X:%02X:%02X) ==>\n", + PRINT_MAC(pMacAddr))); + NdisCopyMemory(KeyInfo.MAC, pMacAddr, MAC_ADDR_LEN); + } + + MAC80211_PAD_GET(pAd, pWiphy); + RTMP_DRIVER_80211_CB_GET(pAd, &p80211CB); + + memset(&KeyInfo, 0, sizeof(KeyInfo)); + KeyInfo.KeyId = KeyIdx; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + CFG80211DBG(RT_DEBUG_TRACE, ("80211> KeyDel isPairwise %d\n", Pairwise)); + KeyInfo.bPairwise = Pairwise; +#endif /* LINUX_VERSION_CODE 2.6.37 */ + +#ifdef CONFIG_AP_SUPPORT + if ((pNdev->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_AP) || + (pNdev->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_P2P_GO)) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> AP Key Del\n")); + RTMP_DRIVER_80211_AP_KEY_DEL(pAd, &KeyInfo); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> STA Key Del\n")); + + if (pMacAddr) + { + CFG80211DBG(RT_DEBUG_OFF, ("80211> STA Key Del -- DISCONNECT\n")); + RTMP_DRIVER_80211_STA_LEAVE(pAd, pNdev->ieee80211_ptr->iftype); + } + } + + return 0; +} + + +/* +======================================================================== +Routine Description: + Set the default key on an interface. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + KeyIdx - + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) +static int CFG80211_OpsKeyDefaultSet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx, + IN bool Unicast, + IN bool Multicast) +#else + +static int CFG80211_OpsKeyDefaultSet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx) +#endif /* LINUX_VERSION_CODE */ +{ + VOID *pAd; + + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Default KeyIdx = %d\n", KeyIdx)); + +#ifdef CONFIG_AP_SUPPORT + if ((pNdev->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_AP) || + (pNdev->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_P2P_GO)) + RTMP_DRIVER_80211_AP_KEY_DEFAULT_SET(pAd, KeyIdx); + else +#endif /* CONFIG_AP_SUPPORT */ + RTMP_DRIVER_80211_STA_KEY_DEFAULT_SET(pAd, KeyIdx); + + return 0; +} /* End of CFG80211_OpsKeyDefaultSet */ + + + +/* +======================================================================== +Routine Description: + Set the Mgmt default key on an interface. + +Arguments: + pWiphy - Wireless hardware description + pNdev - + KeyIdx - + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +#ifdef DOT11W_PMF_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +static int CFG80211_OpsMgmtKeyDefaultSet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN UINT8 KeyIdx) +{ + VOID *pAd; + + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Mgmt Default KeyIdx = %d\n", KeyIdx)); + + RTMP_DRIVER_80211_STA_MGMT_KEY_DEFAULT_SET(pAd, KeyIdx); + + return 0; +} /* End of CFG80211_OpsMgmtKeyDefaultSet */ +#endif /* LINUX_VERSION_CODE */ +#endif /* DOT11W_PMF_SUPPORT */ + +/* +======================================================================== +Routine Description: + Connect to the ESS with the specified parameters. When connected, + call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. + If the connection fails for some reason, call cfg80211_connect_result() + with the status from the AP. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + pSme - + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: connect + + You must use "iw ra0 connect xxx", then "iw ra0 disconnect"; + You can not use "iw ra0 connect xxx" twice without disconnect; + Or you will suffer "command failed: Operation already in progress (-114)". + + You must support add_key and set_default_key function; + Or kernel will crash without any error message in linux 2.6.32. + + + struct cfg80211_connect_params - Connection parameters + + This structure provides information needed to complete IEEE 802.11 + authentication and association. + + @channel: The channel to use or %NULL if not specified (auto-select based + on scan results) + @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan + results) + @ssid: SSID + @ssid_len: Length of ssid in octets + @auth_type: Authentication type (algorithm) + + @ie: IEs for association request + @ie_len: Length of assoc_ie in octets + + @privacy: indicates whether privacy-enabled APs should be used + @crypto: crypto settings + @key_len: length of WEP key for shared key authentication + @key_idx: index of WEP key for shared key authentication + @key: WEP key for shared key authentication +======================================================================== +*/ +static int CFG80211_OpsConnect( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_connect_params *pSme) +{ +#ifdef CONFIG_STA_SUPPORT + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_CONNECT ConnInfo; + struct ieee80211_channel *pChannel = pSme->channel; + INT32 Pairwise = 0; + INT32 Groupwise = 0; + INT32 Keymgmt = 0; + INT32 WpaVersion = 0; + INT32 Chan = -1, Idx; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + MAC80211_PAD_GET(pAd, pWiphy); + + if (pChannel != NULL) + Chan = ieee80211_frequency_to_channel(pChannel->center_freq); + + CFG80211DBG(RT_DEBUG_TRACE, ("Groupwise: %x\n", pSme->crypto.cipher_group)); + Groupwise = pSme->crypto.cipher_group; + //for(Idx=0; Idxcrypto.n_ciphers_pairwise; Idx++) + Pairwise |= pSme->crypto.ciphers_pairwise[0]; + + CFG80211DBG(RT_DEBUG_TRACE, ("Pairwise %x\n", pSme->crypto.ciphers_pairwise[0])); + + for(Idx=0; Idxcrypto.n_akm_suites; Idx++) + Keymgmt |= pSme->crypto.akm_suites[Idx]; + + WpaVersion = pSme->crypto.wpa_versions; + CFG80211DBG(RT_DEBUG_TRACE, ("Wpa_versions %x\n", WpaVersion)); + + memset(&ConnInfo, 0, sizeof(ConnInfo)); + ConnInfo.WpaVer = 0; + + if (WpaVersion & NL80211_WPA_VERSION_1) { + ConnInfo.WpaVer = 1; + } + + if (WpaVersion & NL80211_WPA_VERSION_2) { + ConnInfo.WpaVer = 2; + } + + CFG80211DBG(RT_DEBUG_TRACE, ("Keymgmt %x\n", Keymgmt)); + if (Keymgmt == WLAN_AKM_SUITE_8021X) + ConnInfo.FlgIs8021x = TRUE; + else + ConnInfo.FlgIs8021x = FALSE; + + CFG80211DBG(RT_DEBUG_TRACE, ("Auth_type %x\n", pSme->auth_type)); + if (pSme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) + ConnInfo.AuthType = Ndis802_11AuthModeShared; + else if (pSme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) + ConnInfo.AuthType = Ndis802_11AuthModeOpen; + else + ConnInfo.AuthType = Ndis802_11AuthModeAutoSwitch; + + if (Pairwise == WLAN_CIPHER_SUITE_CCMP) + { + CFG80211DBG(RT_DEBUG_TRACE, ("WLAN_CIPHER_SUITE_CCMP...\n")); + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_CCMP; + } + else if (Pairwise == WLAN_CIPHER_SUITE_TKIP) + { + CFG80211DBG(RT_DEBUG_TRACE, ("WLAN_CIPHER_SUITE_TKIP...\n")); + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_TKIP; + } + else if ((Pairwise == WLAN_CIPHER_SUITE_WEP40) || + (Pairwise & WLAN_CIPHER_SUITE_WEP104)) + { + CFG80211DBG(RT_DEBUG_TRACE, ("WLAN_CIPHER_SUITE_WEP...\n")); + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_WEP; + } + else + { + CFG80211DBG(RT_DEBUG_TRACE, ("NONE...\n")); + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_NONE; + } + + if (Groupwise == WLAN_CIPHER_SUITE_CCMP) + { + ConnInfo.GroupwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_CCMP; + } + else if (Groupwise == WLAN_CIPHER_SUITE_TKIP) + { + ConnInfo.GroupwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_TKIP; + } + else + { + ConnInfo.GroupwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_NONE; + } + + CFG80211DBG(RT_DEBUG_TRACE, ("ConnInfo.KeyLen ===> %d\n", pSme->key_len)); + CFG80211DBG(RT_DEBUG_TRACE, ("ConnInfo.KeyIdx ===> %d\n", pSme->key_idx)); + + ConnInfo.pKey = (UINT8 *)(pSme->key); + ConnInfo.KeyLen = pSme->key_len; + ConnInfo.pSsid = pSme->ssid; + ConnInfo.SsidLen = pSme->ssid_len; + ConnInfo.KeyIdx = pSme->key_idx; + /* YF@20120328: Reset to default */ + ConnInfo.bWpsConnection= FALSE; + + //hex_dump("AssocInfo:", pSme->ie, pSme->ie_len); + + /* YF@20120328: Use SIOCSIWGENIE to make out the WPA/WPS IEs in AssocReq. */ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if(pNdev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) + { + if (pSme->ie_len > 0) + RTMP_DRIVER_80211_P2PCLI_ASSSOC_IE_SET(pAd, pSme->ie, pSme->ie_len); + else + RTMP_DRIVER_80211_P2PCLI_ASSSOC_IE_SET(pAd, NULL, 0); + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + { + if (pSme->ie_len > 0) + RTMP_DRIVER_80211_GEN_IE_SET(pAd, pSme->ie, pSme->ie_len); + else + RTMP_DRIVER_80211_GEN_IE_SET(pAd, NULL, 0); + } + +#ifdef DOT11W_PMF_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + CFG80211DBG(RT_DEBUG_OFF, ("80211> PMF Connect %d\n", pSme->mfp)); + if (pSme->mfp) + { + ConnInfo.mfp = TRUE; + } + else + { + ConnInfo.mfp = FALSE; + } +#endif /* LINUX_VERSION_CODE */ +#endif /* DOT11W_PMF_SUPPORT */ + + /* Check if WPS is triggerred */ + if (pSme->ie && pSme->ie_len) + { + if (RTMPFindWPSIE(pSme->ie, (UINT32)pSme->ie_len) != NULL) + ConnInfo.bWpsConnection= TRUE; + } + + /* %NULL if not specified (auto-select based on scan)*/ + if (pSme->bssid != NULL) + { + CFG80211DBG(RT_DEBUG_OFF, ("80211> Connect bssid %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pSme->bssid))); + ConnInfo.pBssid = pSme->bssid; + } + + RTMP_DRIVER_80211_CONNECT(pAd, &ConnInfo, pNdev->ieee80211_ptr->iftype); +#endif /*CONFIG_STA_SUPPORT*/ + return 0; +} /* End of CFG80211_OpsConnect */ + + +/* +======================================================================== +Routine Description: + Disconnect from the BSS/ESS. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + ReasonCode - + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: connect +======================================================================== +*/ +static int CFG80211_OpsDisconnect( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN u16 ReasonCode) +{ +#ifdef CONFIG_STA_SUPPORT + + VOID *pAd; + + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> ReasonCode = %d\n", ReasonCode)); + + MAC80211_PAD_GET(pAd, pWiphy); + + RTMP_DRIVER_80211_STA_LEAVE(pAd, pNdev->ieee80211_ptr->iftype); +#endif /*CONFIG_STA_SUPPORT*/ + return 0; +} + +#endif /* LINUX_VERSION_CODE */ + + +#ifdef RFKILL_HW_SUPPORT +static int CFG80211_OpsRFKill( + IN struct wiphy *pWiphy) +{ + VOID *pAd; + BOOLEAN active; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + RTMP_DRIVER_80211_RFKILL(pAd, &active); + wiphy_rfkill_set_hw_state(pWiphy, !active); + return active; +} + + +VOID CFG80211_RFKillStatusUpdate( + IN PVOID pAd, + IN BOOLEAN active) +{ + struct wiphy *pWiphy; + CFG80211_CB *pCfg80211_CB; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + RTMP_DRIVER_80211_CB_GET(pAd, &pCfg80211_CB); + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + wiphy_rfkill_set_hw_state(pWiphy, !active); + return; +} +#endif /* RFKILL_HW_SUPPORT */ + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) +/* +======================================================================== +Routine Description: + Get site survey information. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + Idx - + pSurvey - + +Return Value: + 0 - success + -x - fail + +Note: + For iw utility: survey dump +======================================================================== +*/ +static int CFG80211_OpsSurveyGet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN int Idx, + IN struct survey_info *pSurvey) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_SURVEY SurveyInfo; + + + if (Idx != 0) + return -ENOENT; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + MAC80211_PAD_GET(pAd, pWiphy); + + /* get information from driver */ + RTMP_DRIVER_80211_SURVEY_GET(pAd, &SurveyInfo); + + /* return the information to upper layer */ + pSurvey->channel = ((CFG80211_CB *)(SurveyInfo.pCfg80211))->pCfg80211_Channels; + pSurvey->filled = SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_EXT_BUSY; + pSurvey->channel_time_busy = SurveyInfo.ChannelTimeBusy; /* unit: us */ + pSurvey->channel_time_ext_busy = SurveyInfo.ChannelTimeExtBusy; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> busy time = %ld %ld\n", + (ULONG)SurveyInfo.ChannelTimeBusy, + (ULONG)SurveyInfo.ChannelTimeExtBusy)); + return 0; +#else + + return -ENOTSUPP; +#endif /* LINUX_VERSION_CODE */ +} /* End of CFG80211_OpsSurveyGet */ + + +/* +======================================================================== +Routine Description: + Cache a PMKID for a BSSID. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + pPmksa - PMKID information + +Return Value: + 0 - success + -x - fail + +Note: + This is mostly useful for fullmac devices running firmwares capable of + generating the (re) association RSN IE. + It allows for faster roaming between WPA2 BSSIDs. +======================================================================== +*/ +static int CFG80211_OpsPmksaSet( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_pmksa *pPmksa) +{ +#ifdef CONFIG_STA_SUPPORT + VOID *pAd; + RT_CMD_STA_IOCTL_PMA_SA IoctlPmaSa, *pIoctlPmaSa = &IoctlPmaSa; + + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + if ((pPmksa->bssid == NULL) || (pPmksa->pmkid == NULL)) + return -ENOENT; + + pIoctlPmaSa->Cmd = RT_CMD_STA_IOCTL_PMA_SA_ADD; + pIoctlPmaSa->pBssid = (UCHAR *)pPmksa->bssid; + pIoctlPmaSa->pPmkid = pPmksa->pmkid; + + RTMP_DRIVER_80211_PMKID_CTRL(pAd, pIoctlPmaSa); +#endif /* CONFIG_STA_SUPPORT */ + + return 0; +} /* End of CFG80211_OpsPmksaSet */ + + +/* +======================================================================== +Routine Description: + Delete a cached PMKID. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + pPmksa - PMKID information + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsPmksaDel( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_pmksa *pPmksa) +{ +#ifdef CONFIG_STA_SUPPORT + VOID *pAd; + RT_CMD_STA_IOCTL_PMA_SA IoctlPmaSa, *pIoctlPmaSa = &IoctlPmaSa; + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + if ((pPmksa->bssid == NULL) || (pPmksa->pmkid == NULL)) + return -ENOENT; + + pIoctlPmaSa->Cmd = RT_CMD_STA_IOCTL_PMA_SA_REMOVE; + pIoctlPmaSa->pBssid = (UCHAR *)pPmksa->bssid; + pIoctlPmaSa->pPmkid = pPmksa->pmkid; + + RTMP_DRIVER_80211_PMKID_CTRL(pAd, pIoctlPmaSa); +#endif /* CONFIG_STA_SUPPORT */ + + return 0; +} /* End of CFG80211_OpsPmksaDel */ + + +/* +======================================================================== +Routine Description: + Flush a cached PMKID. + +Arguments: + pWiphy - Wireless hardware description + pNdev - Network device interface + +Return Value: + 0 - success + -x - fail + +Note: +======================================================================== +*/ +static int CFG80211_OpsPmksaFlush( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev) +{ +#ifdef CONFIG_STA_SUPPORT + VOID *pAd; + RT_CMD_STA_IOCTL_PMA_SA IoctlPmaSa, *pIoctlPmaSa = &IoctlPmaSa; + + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + pIoctlPmaSa->Cmd = RT_CMD_STA_IOCTL_PMA_SA_FLUSH; + RTMP_DRIVER_80211_PMKID_CTRL(pAd, pIoctlPmaSa); +#endif /* CONFIG_STA_SUPPORT */ + + return 0; +} /* End of CFG80211_OpsPmksaFlush */ +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static int CFG80211_OpsRemainOnChannel( + IN struct wiphy *pWiphy, + IN struct wireless_dev *pWdev, + IN struct ieee80211_channel *pChan, + IN unsigned int duration, + OUT u64 *cookie) +#else +static int CFG80211_OpsRemainOnChannel( + IN struct wiphy *pWiphy, + IN struct net_device *dev, + IN struct ieee80211_channel *pChan, + IN enum nl80211_channel_type ChannelType, + IN unsigned int duration, + OUT u64 *cookie) +#endif /* LINUX_VERSION_CODE: 3.6.0 */ +{ + VOID *pAd; + UINT32 ChanId; + CMD_RTPRIV_IOCTL_80211_CHAN ChanInfo; + u32 rndCookie; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct net_device *dev = NULL; + INT ChannelType = RT_CMD_80211_CHANTYPE_HT20; + dev = pWdev->netdev; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + rndCookie = 0x1234; +#else + rndCookie = random32() | 1; +#endif + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + MAC80211_PAD_GET(pAd, pWiphy); + + /*CFG_TODO: Shall check channel type*/ + + /* get channel number */ + ChanId = ieee80211_frequency_to_channel(pChan->center_freq); + CFG80211DBG(RT_DEBUG_TRACE, ("%s: CH = %d, Type = %d, duration = %d, cookie=%d\n", __FUNCTION__, + ChanId, ChannelType, duration, rndCookie)); + + /* init */ + *cookie = rndCookie; + memset(&ChanInfo, 0, sizeof(ChanInfo)); + ChanInfo.ChanId = ChanId; + ChanInfo.IfType = dev->ieee80211_ptr->iftype; + ChanInfo.ChanType = ChannelType; + ChanInfo.chan = pChan; + ChanInfo.cookie = rndCookie; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + ChanInfo.pWdev = pWdev; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + /* set channel */ + RTMP_DRIVER_80211_REMAIN_ON_CHAN_SET(pAd, &ChanInfo, duration); + return 0; +} + +static void CFG80211_OpsMgmtFrameRegister( + struct wiphy *pWiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + u16 frame_type, bool reg) +{ + VOID *pAd; + MAC80211_PAD_GET(pAd, pWiphy); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct net_device *dev = NULL; + RTMP_DRIVER_NET_DEV_GET(pAd, &dev); +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + CFG80211DBG(RT_DEBUG_INFO, ("80211> %s ==>\n", __FUNCTION__)); + CFG80211DBG(RT_DEBUG_INFO, ("frame_type = %x, req = %d , (%d)\n", frame_type, reg, dev->ieee80211_ptr->iftype)); + + if (frame_type == IEEE80211_STYPE_PROBE_REQ) + RTMP_DRIVER_80211_MGMT_FRAME_REG(pAd, dev, reg); + else if (frame_type == IEEE80211_STYPE_ACTION) + RTMP_DRIVER_80211_ACTION_FRAME_REG(pAd, dev, reg); + else + CFG80211DBG(RT_DEBUG_ERROR, ("Unkown frame_type = %x, req = %d\n", frame_type, reg)); + + +} + +//Supplicant_NEW_TDLS + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static int CFG80211_OpsMgmtTx( + IN struct wiphy *pWiphy, + IN struct wireless_dev *wdev, + IN struct ieee80211_channel *pChan, + IN bool Offchan, + IN unsigned int Wait, + IN const u8 *pBuf, + IN size_t Len, + IN bool no_cck, + IN bool done_wait_for_ack, + IN u64 *pCookie) +#else +static int CFG80211_OpsMgmtTx( + IN struct wiphy *pWiphy, + IN struct net_device *pDev, + IN struct ieee80211_channel *pChan, + IN bool Offchan, + IN enum nl80211_channel_type ChannelType, + IN bool ChannelTypeValid, + IN unsigned int Wait, + IN const u8 *pBuf, + IN size_t Len, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + IN bool no_cck, +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) + IN bool done_wait_for_ack, +#endif + IN u64 *pCookie) +#endif /* LINUX_VERSION_CODE: 3.6.0 */ +{ + VOID *pAd; + UINT32 ChanId; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct net_device *dev = NULL; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + CFG80211DBG(RT_DEBUG_INFO, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + RTMP_DRIVER_NET_DEV_GET(pAd, &dev); +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + /* get channel number */ + ChanId = ieee80211_frequency_to_channel(pChan->center_freq); + CFG80211DBG(RT_DEBUG_INFO, ("80211> Mgmt Channel = %d\n", ChanId)); + + /* Send the Frame with basic rate 6 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + if (no_cck) + ; //pAd->isCfgDeviceInP2p = TRUE; +#else + +#endif + + *pCookie = 5678; + RTMP_DRIVER_80211_CHANNEL_LOCK(pAd, ChanId); + RTMP_DRIVER_80211_MGMT_FRAME_SEND(pAd, pBuf, Len); + + /* Mark it for using Supplicant-Based off-channel wait + if (Offchan) + RTMP_DRIVER_80211_CHANNEL_RESTORE(pAd); + */ + + return 0; +} + + +static int CFG80211_OpsTxCancelWait( + IN struct wiphy *pWiphy, + IN struct net_device *pDev, + u64 cookie) +{ + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s ==>\n", __FUNCTION__)); + return 0; +} + +static int CFG80211_OpsCancelRemainOnChannel( + struct wiphy *pWiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + u64 cookie) +{ + VOID *pAd; + CFG80211DBG(RT_DEBUG_INFO, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + /* It cause the Supplicant-based OffChannel Hang */ + RTMP_DRIVER_80211_CANCEL_REMAIN_ON_CHAN_SET(pAd, cookie); + return 0; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) +static int CFG80211_OpsSetBeacon( + struct wiphy *pWiphy, + struct net_device *netdev, + struct beacon_parameters *info) +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_BEACON bcn; + UCHAR *beacon_head_buf, *beacon_tail_buf; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + hex_dump("Beacon head", info->head, info->head_len); + hex_dump("Beacon tail", info->tail, info->tail_len); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>dtim_period = %d \n", info->dtim_period)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>interval = %d \n", info->interval)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + CFG80211DBG(RT_DEBUG_TRACE, ("80211>ssid = %s \n", info->ssid)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>ssid_len = %s \n", info->ssid_len)); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211>beacon_ies_len = %d \n", info->beacon_ies_len)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>proberesp_ies_len = %d \n", info->proberesp_ies_len)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>assocresp_ies_len = %d \n", info->assocresp_ies_len)); + + if (info->proberesp_ies_len > 0 && info->proberesp_ies) + RTMP_DRIVER_80211_AP_PROBE_RSP(pAd, info->proberesp_ies, info->proberesp_ies_len); + + if (info->assocresp_ies_len > 0 && info->assocresp_ies) + RTMP_DRIVER_80211_AP_ASSOC_RSP(pAd, info->assocresp_ies, info->assocresp_ies_len); +#endif + + os_alloc_mem(NULL, &beacon_head_buf, info->head_len); + NdisCopyMemory(beacon_head_buf, info->head, info->head_len); + + os_alloc_mem(NULL, &beacon_tail_buf, info->tail_len); + NdisCopyMemory(beacon_tail_buf, info->tail, info->tail_len); + + bcn.beacon_head_len = info->head_len; + bcn.beacon_tail_len = info->tail_len; + bcn.beacon_head = beacon_head_buf; + bcn.beacon_tail = beacon_tail_buf; + bcn.dtim_period = info->dtim_period; + bcn.interval = info->interval; + + + RTMP_DRIVER_80211_BEACON_SET(pAd, &bcn); + + if (beacon_head_buf) + os_free_mem(NULL, beacon_head_buf); + + if (beacon_tail_buf) + os_free_mem(NULL, beacon_tail_buf); + + return 0; +} + +static int CFG80211_OpsAddBeacon( + struct wiphy *pWiphy, + struct net_device *netdev, + struct beacon_parameters *info) +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_BEACON bcn; + UCHAR *beacon_head_buf, *beacon_tail_buf; + + MAC80211_PAD_GET(pAd, pWiphy); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + hex_dump("Beacon head", info->head, info->head_len); + hex_dump("Beacon tail", info->tail, info->tail_len); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>dtim_period = %d \n", info->dtim_period)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>interval = %d \n", info->interval)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + CFG80211DBG(RT_DEBUG_TRACE, ("80211>ssid = %s \n", info->ssid)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>ssid_len = %s \n", info->ssid_len)); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211>beacon_ies_len = %d \n", info->beacon_ies_len)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>proberesp_ies_len = %d \n", info->proberesp_ies_len)); + CFG80211DBG(RT_DEBUG_TRACE, ("80211>assocresp_ies_len = %d \n", info->assocresp_ies_len)); + + if (info->proberesp_ies_len > 0 && info->proberesp_ies) + RTMP_DRIVER_80211_AP_PROBE_RSP(pAd, info->proberesp_ies, info->proberesp_ies_len); + + if (info->assocresp_ies_len > 0 && info->assocresp_ies) + RTMP_DRIVER_80211_AP_ASSOC_RSP(pAd, info->assocresp_ies, info->assocresp_ies_len); +#endif + + os_alloc_mem(NULL, &beacon_head_buf, info->head_len); + NdisCopyMemory(beacon_head_buf, info->head, info->head_len); + + os_alloc_mem(NULL, &beacon_tail_buf, info->tail_len); + NdisCopyMemory(beacon_tail_buf, info->tail, info->tail_len); + + bcn.beacon_head_len = info->head_len; + bcn.beacon_tail_len = info->tail_len; + bcn.beacon_head = beacon_head_buf; + bcn.beacon_tail = beacon_tail_buf; + bcn.dtim_period = info->dtim_period; + bcn.interval = info->interval; + + + RTMP_DRIVER_80211_BEACON_ADD(pAd, &bcn); + + if (beacon_head_buf) + os_free_mem(NULL, beacon_head_buf); + + if (beacon_tail_buf) + os_free_mem(NULL, beacon_tail_buf); + + return 0; +} + +static int CFG80211_OpsDelBeacon( + struct wiphy *pWiphy, + struct net_device *netdev) +{ + VOID *pAd; + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s ==>\n", __FUNCTION__)); + + RTMP_DRIVER_80211_BEACON_DEL(pAd); + return 0; +} +#else +static int CFG80211_OpsStartAp( + struct wiphy *pWiphy, + struct net_device *netdev, + struct cfg80211_ap_settings *settings) +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_BEACON bcn; + UCHAR *beacon_head_buf, *beacon_tail_buf; + + MAC80211_PAD_GET(pAd, pWiphy); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + NdisZeroMemory(&bcn,sizeof(CMD_RTPRIV_IOCTL_80211_BEACON)); + + if (settings->beacon.head_len > 0) + { + os_alloc_mem(NULL, &beacon_head_buf, settings->beacon.head_len); + NdisCopyMemory(beacon_head_buf, settings->beacon.head, settings->beacon.head_len); + } + + if (settings->beacon.tail_len > 0) + { + os_alloc_mem(NULL, &beacon_tail_buf, settings->beacon.tail_len); + NdisCopyMemory(beacon_tail_buf, settings->beacon.tail, settings->beacon.tail_len); + } + + bcn.beacon_head_len = settings->beacon.head_len; + bcn.beacon_tail_len = settings->beacon.tail_len; + bcn.beacon_head = beacon_head_buf; + bcn.beacon_tail = beacon_tail_buf; + bcn.dtim_period = settings->dtim_period; + bcn.interval = settings->beacon_interval; + bcn.hidden_ssid = settings->hidden_ssid; + + + RTMP_DRIVER_80211_BEACON_ADD(pAd, &bcn); + + if (beacon_head_buf) + os_free_mem(NULL, beacon_head_buf); + if (beacon_tail_buf) + os_free_mem(NULL, beacon_tail_buf); + + return 0; +} + +static int CFG80211_OpsChangeBeacon( + struct wiphy *pWiphy, + struct net_device *netdev, + struct cfg80211_beacon_data *info) +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_BEACON bcn; + UCHAR *beacon_head_buf, *beacon_tail_buf; + + MAC80211_PAD_GET(pAd, pWiphy); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + if (info->head_len > 0) + { + os_alloc_mem(NULL, &beacon_head_buf, info->head_len); + NdisCopyMemory(beacon_head_buf, info->head, info->head_len); + } + + if (info->tail_len > 0) { + os_alloc_mem(NULL, &beacon_tail_buf, info->tail_len); + NdisCopyMemory(beacon_tail_buf, info->tail, info->tail_len); + } + + bcn.beacon_head_len = info->head_len; + bcn.beacon_tail_len = info->tail_len; + bcn.beacon_head = beacon_head_buf; + bcn.beacon_tail = beacon_tail_buf; + + RTMP_DRIVER_80211_BEACON_SET(pAd, &bcn); + + if (beacon_head_buf) + os_free_mem(NULL, beacon_head_buf); + if (beacon_tail_buf) + os_free_mem(NULL, beacon_tail_buf); + return 0; + +} + +static int CFG80211_OpsStopAp( + struct wiphy *pWiphy, + struct net_device *netdev) +{ + VOID *pAd; + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s ==>\n", __FUNCTION__)); + + RTMP_DRIVER_80211_BEACON_DEL(pAd); + return 0; +} +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) */ + +static int CFG80211_OpsChangeBss( + struct wiphy *pWiphy, + struct net_device *netdev, + struct bss_parameters *params) +{ + + VOID *pAd; + MAC80211_PAD_GET(pAd, pWiphy); + CMD_RTPRIV_IOCTL_80211_BSS_PARM bssInfo; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + bssInfo.use_short_preamble = params->use_short_preamble; + bssInfo.use_short_slot_time = params->use_short_slot_time; + bssInfo.use_cts_prot = params->use_cts_prot; + + RTMP_DRIVER_80211_CHANGE_BSS_PARM(pAd, &bssInfo); + + return 0; +} + +static int CFG80211_OpsStaDel( + struct wiphy *pWiphy, + struct net_device *dev, + UINT8 *pMacAddr) +{ + VOID *pAd; + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + if (pMacAddr == NULL) + { + RTMP_DRIVER_80211_AP_STA_DEL(pAd, NULL); + } + else + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Delete STA(%02X:%02X:%02X:%02X:%02X:%02X) ==>\n", + PRINT_MAC(pMacAddr))); + RTMP_DRIVER_80211_AP_STA_DEL(pAd, pMacAddr); + } + + return 0; +} + +static int CFG80211_OpsStaAdd( + struct wiphy *wiphy, + struct net_device *dev, + UINT8 *mac, + struct station_parameters *params) +{ + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + return 0; +} + +static int CFG80211_OpsStaChg( + struct wiphy *pWiphy, + struct net_device *dev, + UINT8 *pMacAddr, + struct station_parameters *params) +{ + void *pAd; + CFG80211_CB *p80211CB; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Change STA(%02X:%02X:%02X:%02X:%02X:%02X) ==>\n", PRINT_MAC(pMacAddr))); + MAC80211_PAD_GET(pAd, pWiphy); + + p80211CB = NULL; + RTMP_DRIVER_80211_CB_GET(pAd, &p80211CB); + + if ((dev->ieee80211_ptr->iftype != RT_CMD_80211_IFTYPE_AP) && + (dev->ieee80211_ptr->iftype != RT_CMD_80211_IFTYPE_P2P_GO)) + return -EOPNOTSUPP; + + if(!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %x ==>\n", params->sta_flags_mask)); + return -EOPNOTSUPP; + } + + if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> STA(%02X:%02X:%02X:%02X:%02X:%02X) ==> PortSecured\n", + PRINT_MAC(pMacAddr))); + RTMP_DRIVER_80211_AP_MLME_PORT_SECURED(pAd, pMacAddr, 1); + } + else + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> STA(%02X:%02X:%02X:%02X:%02X:%02X) ==> PortNotSecured\n", + PRINT_MAC(pMacAddr))); + RTMP_DRIVER_80211_AP_MLME_PORT_SECURED(pAd, pMacAddr, 0); + } + return 0; +} + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static struct wireless_dev* CFG80211_OpsVirtualInfAdd( + IN struct wiphy *pWiphy, + IN char *name, + IN enum nl80211_iftype Type, + IN u32 *pFlags, + struct vif_params *pParams) +#else +static struct net_device* CFG80211_OpsVirtualInfAdd( + IN struct wiphy *pWiphy, + IN char *name, + IN enum nl80211_iftype Type, + IN u32 *pFlags, + struct vif_params *pParams) +#endif /* LINUX_VERSION_CODE: 3.6.0 */ +{ + VOID *pAd; + CMD_RTPRIV_IOCTL_80211_VIF_SET vifInfo; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + PWIRELESS_DEV pDev = NULL; +#else + PNET_DEV pDev = NULL; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s [%s,%d, %d] ==>\n", __FUNCTION__, name, Type, strlen(name))); + + vifInfo.vifType = Type; + vifInfo.vifNameLen = strlen(name); + memset(vifInfo.vifName, 0, sizeof(vifInfo.vifName)); + NdisCopyMemory(vifInfo.vifName, name, vifInfo.vifNameLen); + + if (RTMP_DRIVER_80211_VIF_ADD(pAd, &vifInfo) != NDIS_STATUS_SUCCESS) + return NULL; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + pDev = RTMP_CFG80211_FindVifEntryWdev_ByType(pAd, Type); +#else + /* Return NetDevice */ + pDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, Type); +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + return pDev; +} + +static int CFG80211_OpsVirtualInfDel( + IN struct wiphy *pWiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + IN struct wireless_dev *pwdev +#else + IN struct net_device *dev +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + ) +{ + void *pAd; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct net_device *dev = NULL; + dev = pwdev->netdev; + + if (!dev) + return 0; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s, %s [%d]==>\n", __FUNCTION__, dev->name, dev->ieee80211_ptr->iftype)); + MAC80211_PAD_GET(pAd, pWiphy); + + RTMP_DRIVER_80211_VIF_DEL(pAd, dev, dev->ieee80211_ptr->iftype); + return 0; +} + + +static int CFG80211_OpsBitrateSet( + IN struct wiphy *pWiphy, + IN struct net_device *dev, + IN const u8 *peer, + IN const struct cfg80211_bitrate_mask *mask) +{ + return 0; +} + +#ifdef CONFIG_NL80211_TESTMODE +static int CFG80211_OpsTestModeCmd(IN struct wiphy *pWiphy, void *Data, int len) +{ +} +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static int CFG80211_start_p2p_device( + struct wiphy *pWiphy, + struct wireless_dev *wdev) +{ + void *pAd; + struct net_device *dev = wdev->netdev; + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s, %s [%d]==>\n", __FUNCTION__, dev->name, dev->ieee80211_ptr->iftype)); + MAC80211_PAD_GET(pAd, pWiphy); + return 0; +} + +static int CFG80211_stop_p2p_device( + struct wiphy *pWiphy, + struct wireless_dev *wdev) +{ + void *pAd; + struct net_device *dev = wdev->netdev; + CFG80211DBG(RT_DEBUG_OFF, ("80211> %s, %s [%d]==>\n", __FUNCTION__, dev->name, dev->ieee80211_ptr->iftype)); + MAC80211_PAD_GET(pAd, pWiphy); + return 0; +} +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) +static const struct ieee80211_txrx_stypes +ralink_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_STATION] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4), + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4), + }, + +}; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +static const struct ieee80211_iface_limit ra_p2p_sta_go_limits[] = +{ + { + .max = 3, + .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP), + }, +}; +#else +static const struct ieee80211_iface_limit ra_p2p_sta_go_limits[] = +{ + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_AP), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_CLIENT), + }, +}; +#endif +static const struct ieee80211_iface_combination +ra_iface_combinations_p2p[] = { + { +#ifdef RT_CFG80211_P2P_MULTI_CHAN_SUPPORT + .num_different_channels = 2, +#else + .num_different_channels = 1, +#endif /* RT_CFG80211_P2P_MULTI_CHAN_SUPPORT */ + .max_interfaces = 3, + .beacon_int_infra_match = true, + .limits = ra_p2p_sta_go_limits, + .n_limits = ARRAY_SIZE(ra_p2p_sta_go_limits), + }, +}; +#endif + +struct cfg80211_ops CFG80211_Ops = { + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) + .set_beacon = CFG80211_OpsSetBeacon, + .add_beacon = CFG80211_OpsAddBeacon, + .del_beacon = CFG80211_OpsDelBeacon, +#else + .start_ap = CFG80211_OpsStartAp, + .change_beacon = CFG80211_OpsChangeBeacon, + .stop_ap = CFG80211_OpsStopAp, +#endif /* LINUX_VERSION_CODE 3.4 */ + + /* set channel for a given wireless interface */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + //CFG_TODO + .set_monitor_channel = CFG80211_OpsMonitorChannelSet, +#else + .set_channel = CFG80211_OpsChannelSet, +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + /* change type/configuration of virtual interface */ + .change_virtual_intf = CFG80211_OpsVirtualInfChg, + .add_virtual_intf = CFG80211_OpsVirtualInfAdd, + .del_virtual_intf = CFG80211_OpsVirtualInfDel, + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + .start_p2p_device = CFG80211_start_p2p_device, + .stop_p2p_device = CFG80211_stop_p2p_device, +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) + /* request to do a scan */ + /* + Note: must exist whatever AP or STA mode; Or your kernel will crash + in v2.6.38. + */ + .scan = CFG80211_OpsScan, +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) +#ifdef CONFIG_STA_SUPPORT + /* join the specified IBSS (or create if necessary) */ + .join_ibss = CFG80211_OpsIbssJoin, + /* leave the IBSS */ + .leave_ibss = CFG80211_OpsIbssLeave, +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) + /* set the transmit power according to the parameters */ + .set_tx_power = CFG80211_OpsTxPwrSet, + /* store the current TX power into the dbm variable */ + .get_tx_power = CFG80211_OpsTxPwrGet, +#endif /* LINUX_VERSION_CODE: 3.8.0 */ + .set_power_mgmt = CFG80211_OpsPwrMgmt, + /* get station information for the station identified by @mac */ + .get_station = CFG80211_OpsStaGet, + /* dump station callback */ + .dump_station = CFG80211_OpsStaDump, + /* notify that wiphy parameters have changed */ + .set_wiphy_params = CFG80211_OpsWiphyParamsSet, + /* add a key with the given parameters */ + .add_key = CFG80211_OpsKeyAdd, + /* get information about the key with the given parameters */ + .get_key = CFG80211_OpsKeyGet, + /* remove a key given the @mac_addr */ + .del_key = CFG80211_OpsKeyDel, + /* set the default key on an interface */ + .set_default_key = CFG80211_OpsKeyDefaultSet, +#ifdef DOT11W_PMF_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + .set_default_mgmt_key = CFG80211_OpsMgmtKeyDefaultSet, +#endif /* LINUX_VERSION_CODE */ +#endif /* DOT11W_PMF_SUPPORT */ + + /* connect to the ESS with the specified parameters */ + .connect = CFG80211_OpsConnect, + /* disconnect from the BSS/ESS */ + .disconnect = CFG80211_OpsDisconnect, +#endif /* LINUX_VERSION_CODE */ + +#ifdef RFKILL_HW_SUPPORT + /* polls the hw rfkill line */ + .rfkill_poll = CFG80211_OpsRFKill, +#endif /* RFKILL_HW_SUPPORT */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) + /* get site survey information */ + //.dump_survey = CFG80211_OpsSurveyGet, + /* cache a PMKID for a BSSID */ + .set_pmksa = CFG80211_OpsPmksaSet, + /* delete a cached PMKID */ + .del_pmksa = CFG80211_OpsPmksaDel, + /* flush all cached PMKIDs */ + .flush_pmksa = CFG80211_OpsPmksaFlush, +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + /* + Request the driver to remain awake on the specified + channel for the specified duration to complete an off-channel + operation (e.g., public action frame exchange). + */ + .remain_on_channel = CFG80211_OpsRemainOnChannel, + /* cancel an on-going remain-on-channel operation */ + .cancel_remain_on_channel = CFG80211_OpsCancelRemainOnChannel, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) + /* transmit an action frame */ + .action = NULL, +#else + .mgmt_tx = CFG80211_OpsMgmtTx, +#endif /* LINUX_VERSION_CODE */ +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) + .mgmt_tx_cancel_wait = CFG80211_OpsTxCancelWait, +#endif /* LINUX_VERSION_CODE */ + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) + /* configure connection quality monitor RSSI threshold */ + .set_cqm_rssi_config = NULL, +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + /* notify driver that a management frame type was registered */ + .mgmt_frame_register = CFG80211_OpsMgmtFrameRegister, +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) + /* set antenna configuration (tx_ant, rx_ant) on the device */ + .set_antenna = NULL, + /* get current antenna configuration from device (tx_ant, rx_ant) */ + .get_antenna = NULL, +#endif /* LINUX_VERSION_CODE */ + .change_bss = CFG80211_OpsChangeBss, + .del_station = CFG80211_OpsStaDel, + .add_station = CFG80211_OpsStaAdd, + .change_station = CFG80211_OpsStaChg, +// .set_bitrate_mask = CFG80211_OpsBitrateSet, +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = CFG80211_OpsTestModeCmd, +#endif /* CONFIG_NL80211_TESTMODE */ +}; + +/* =========================== Global Function ============================== */ + +static INT CFG80211NetdevNotifierEvent( + struct notifier_block *nb, ULONG state, VOID *ndev) +{ + VOID *pAd; + struct net_device *pNev = ndev; + struct wireless_dev *pWdev = pNev->ieee80211_ptr; + + if (!ndev || !pWdev || !pWdev->wiphy) + return NOTIFY_DONE; + + MAC80211_PAD_GET(pAd, pWdev->wiphy); + + if (!pAd) + return NOTIFY_DONE; + + switch (state) { + case NETDEV_UNREGISTER: + break; + + case NETDEV_GOING_DOWN: + RTMP_DRIVER_80211_NETDEV_EVENT(pAd, pNev, state); + break; + } + + return NOTIFY_DONE; +} + +struct notifier_block cfg80211_netdev_notifier = { + .notifier_call = CFG80211NetdevNotifierEvent, +}; + +static const struct ieee80211_regdomain rtmp_custom_regd = { + .n_reg_rules = 2, + .alpha2 = "00", + .reg_rules = { + REG_RULE(5260-20, 5320+20, 40, 6, 20, NL80211_RRF_DFS | NL80211_RRF_PASSIVE_SCAN), + REG_RULE(5725-10, 5850+10, 40, 0, 30, NL80211_RRF_DFS), + } +}; +/* +======================================================================== +Routine Description: + Allocate a wireless device. + +Arguments: + pAd - WLAN control block pointer + pDev - Generic device interface + +Return Value: + wireless device + +Note: +======================================================================== +*/ +static struct wireless_dev *CFG80211_WdevAlloc( + IN CFG80211_CB *pCfg80211_CB, + IN CFG80211_BAND *pBandInfo, + IN VOID *pAd, + IN struct device *pDev) +{ + struct wireless_dev *pWdev; + ULONG *pPriv; + + + /* + * We're trying to have the following memory layout: + * + * +------------------------+ + * | struct wiphy | + * +------------------------+ + * | pAd pointer | + * +------------------------+ + */ + + pWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (pWdev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Wireless device allocation fail!\n")); + return NULL; + } /* End of if */ + + pWdev->wiphy = wiphy_new(&CFG80211_Ops, sizeof(ULONG *)); + if (pWdev->wiphy == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Wiphy device allocation fail!\n")); + goto LabelErrWiphyNew; + } /* End of if */ + + /* keep pAd pointer */ + pPriv = (ULONG *)(wiphy_priv(pWdev->wiphy)); + *pPriv = (ULONG)pAd; + + set_wiphy_dev(pWdev->wiphy, pDev); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) + pWdev->wiphy->max_scan_ssids = pBandInfo->MaxBssTable; +#endif /* KERNEL_VERSION */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + /* @NL80211_FEATURE_INACTIVITY_TIMER: + This driver takes care of freeingup + the connected inactive stations in AP mode.*/ + + /*what if you get compile error for below flag, please add the patch into your kernel*/ + /* http://www.permalink.gmane.org/gmane.linux.kernel.wireless.general/86454 */ + pWdev->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; +#endif + + pWdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) +#ifdef CONFIG_SNIFFER_SUPPORT + | BIT(NL80211_IFTYPE_MONITOR) +#endif /* CONFIG_SNIFFER_SUPPORT */ + ; + +#ifdef CONFIG_STA_SUPPORT + + pWdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); + +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pWdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + pWdev->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); +#endif /* LINUX_VERSION_CODE 3.7.0 */ +#endif /* LINUX_VERSION_CODE 2.6.37 */ +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RT_CFG80211_P2P_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)) + pWdev->wiphy->software_iftypes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)); + + /* NL80211_IFTYPE_P2P_DEVICE Kernel Symbol start from 3.7 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + pWdev->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); +#endif /* LINUX_VERSION_CODE 3.7.0 */ +#endif /* LINUX_VERSION_CODE 3.0.0 */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + + //pWdev->wiphy->reg_notifier = CFG80211_RegNotifier; + + /* init channel information */ + CFG80211_SupBandInit(pCfg80211_CB, pBandInfo, pWdev->wiphy, NULL, NULL); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) + /* CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */ + pWdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + pWdev->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) + pWdev->wiphy->max_num_pmkids = 4; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) + pWdev->wiphy->max_remain_on_channel_duration = 5000; +#endif /* KERNEL_VERSION */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pWdev->wiphy->mgmt_stypes = ralink_mgmt_stypes; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + pWdev->wiphy->cipher_suites = CipherSuites; + pWdev->wiphy->n_cipher_suites = ARRAY_SIZE(CipherSuites); +#endif /* LINUX_VERSION_CODE */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + pWdev->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) + /*what if you get compile error for below flag, please add the patch into your kernel*/ + /* 018-cfg80211-internal-ap-mlme.patch */ + pWdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; + + /*what if you get compile error for below flag, please add the patch into your kernel*/ + /* 008-cfg80211-offchan-flags.patch */ + pWdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + //CFG_TODO + //pWdev->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; +#endif + + //Driver Report Support TDLS to supplicant +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + pWdev->wiphy->iface_combinations = ra_iface_combinations_p2p; + pWdev->wiphy->n_iface_combinations = ARRAY_SIZE(ra_iface_combinations_p2p); +#endif /* LINUX_VERSION_CODE: 3.8.0 */ + + if (wiphy_register(pWdev->wiphy) < 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Register wiphy device fail!\n")); + goto LabelErrReg; + } + + return pWdev; + + LabelErrReg: + wiphy_free(pWdev->wiphy); + + LabelErrWiphyNew: + os_free_mem(NULL, pWdev); + + return NULL; +} /* End of CFG80211_WdevAlloc */ + + +/* +======================================================================== +Routine Description: + Register MAC80211 Module. + +Arguments: + pAdCB - WLAN control block pointer + pDev - Generic device interface + pNetDev - Network device + +Return Value: + NONE + +Note: + pDev != pNetDev + #define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev)) + + Can not use pNetDev to replace pDev; Or kernel panic. +======================================================================== +*/ +BOOLEAN CFG80211_Register( + IN VOID *pAd, + IN struct device *pDev, + IN struct net_device *pNetDev) +{ + CFG80211_CB *pCfg80211_CB = NULL; + CFG80211_BAND BandInfo; + INT err; + + DBGPRINT(RT_DEBUG_OFF, ("80211> CFG80211_Register!\n")); + + /* allocate Main Device Info structure */ + os_alloc_mem(NULL, (UCHAR **)&pCfg80211_CB, sizeof(CFG80211_CB)); + if (pCfg80211_CB == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Allocate MAC80211 CB fail!\n")); + return FALSE; + } + + /* allocate wireless device */ + RTMP_DRIVER_80211_BANDINFO_GET(pAd, &BandInfo); + + pCfg80211_CB->pCfg80211_Wdev = \ + CFG80211_WdevAlloc(pCfg80211_CB, &BandInfo, pAd, pDev); + if (pCfg80211_CB->pCfg80211_Wdev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Allocate Wdev fail!\n")); + os_free_mem(NULL, pCfg80211_CB); + return FALSE; + } + + /* bind wireless device with net device */ +#ifdef CONFIG_AP_SUPPORT + /* default we are AP mode */ + pCfg80211_CB->pCfg80211_Wdev->iftype = NL80211_IFTYPE_AP; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + /* default we are station mode */ + pCfg80211_CB->pCfg80211_Wdev->iftype = NL80211_IFTYPE_STATION; +#endif /* CONFIG_STA_SUPPORT */ + + + pNetDev->ieee80211_ptr = pCfg80211_CB->pCfg80211_Wdev; + SET_NETDEV_DEV(pNetDev, wiphy_dev(pCfg80211_CB->pCfg80211_Wdev->wiphy)); + pCfg80211_CB->pCfg80211_Wdev->netdev = pNetDev; + +#ifdef RFKILL_HW_SUPPORT + wiphy_rfkill_start_polling(pCfg80211_CB->pCfg80211_Wdev->wiphy); +#endif /* RFKILL_HW_SUPPORT */ + + RTMP_DRIVER_80211_CB_SET(pAd, pCfg80211_CB); + RTMP_DRIVER_80211_RESET(pAd); + RTMP_DRIVER_80211_SCAN_STATUS_LOCK_INIT(pAd, TRUE); + + + +/*#ifdef CONFIG_STA_SUPPORT //reg notifier in AP case 7620&7612 will hang + err = register_netdevice_notifier(&cfg80211_netdev_notifier); + if (err) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Failed to register notifierl %d\n", err)); + } +#endif CONFIG_STA_SUPPORT*/ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211_Register\n")); + return TRUE; +} /* End of CFG80211_Register */ + + + + +/* =========================== Local Function =============================== */ + +/* +======================================================================== +Routine Description: + The driver's regulatory notification callback. + +Arguments: + pWiphy - Wireless hardware description + pRequest - Regulatory request + +Return Value: + 0 + +Note: +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +static INT32 CFG80211_RegNotifier( + IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest) +{ + VOID *pAd; + ULONG *pPriv; + + + /* sanity check */ + pPriv = (ULONG *)(wiphy_priv(pWiphy)); + pAd = (VOID *)(*pPriv); + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("crda> reg notify but pAd = NULL!")); + return 0; + } /* End of if */ + + /* + Change the band settings (PASS scan, IBSS allow, or DFS) in mac80211 + based on EEPROM. + + IEEE80211_CHAN_DISABLED: This channel is disabled. + IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted + on this channel. + IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. + IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel + is not permitted. + IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel + is not permitted. + */ + + /* + Change regulatory rule here. + + struct ieee80211_channel { + enum ieee80211_band band; + u16 center_freq; + u8 max_bandwidth; + u16 hw_value; + u32 flags; + int max_antenna_gain; + int max_power; + bool beacon_found; + u32 orig_flags; + int orig_mag, orig_mpwr; + }; + + In mac80211 layer, it will change flags, max_antenna_gain, + max_bandwidth, max_power. + */ + + switch(pRequest->initiator) + { + case NL80211_REGDOM_SET_BY_CORE: + /* + Core queried CRDA for a dynamic world regulatory domain. + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by core: ")); + break; + + case NL80211_REGDOM_SET_BY_USER: + /* + User asked the wireless core to set the regulatory domain. + (when iw, network manager, wpa supplicant, etc.) + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by user: ")); + break; + + case NL80211_REGDOM_SET_BY_DRIVER: + /* + A wireless drivers has hinted to the wireless core it thinks + its knows the regulatory domain we should be in. + (when driver initialization, calling regulatory_hint) + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by driver: ")); + break; + + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + /* + The wireless core has received an 802.11 country information + element with regulatory information it thinks we should consider. + (when beacon receive, calling regulatory_hint_11d) + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by country IE: ")); + break; + } /* End of switch */ + + CFG80211DBG(RT_DEBUG_OFF, ("%c%c\n", pRequest->alpha2[0], pRequest->alpha2[1])); + + /* only follow rules from user */ + if (pRequest->initiator == NL80211_REGDOM_SET_BY_USER) + { + /* keep Alpha2 and we can re-call the function when interface is up */ + CMD_RTPRIV_IOCTL_80211_REG_NOTIFY RegInfo; + + RegInfo.Alpha2[0] = pRequest->alpha2[0]; + RegInfo.Alpha2[1] = pRequest->alpha2[1]; + RegInfo.pWiphy = pWiphy; + + RTMP_DRIVER_80211_REG_NOTIFY(pAd, &RegInfo); + } /* End of if */ + + return 0; +} /* End of CFG80211_RegNotifier */ + +#else + +static INT32 CFG80211_RegNotifier( + IN struct wiphy *pWiphy, + IN enum reg_set_by Request) +{ + struct device *pDev = pWiphy->dev.parent; + struct net_device *pNetDev = dev_get_drvdata(pDev); + VOID *pAd = (VOID *)RTMP_OS_NETDEV_GET_PRIV(pNetDev); + UINT32 ReqType = Request; + + + /* sanity check */ + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("crda> reg notify but pAd = NULL!")); + return 0; + } /* End of if */ + + /* + Change the band settings (PASS scan, IBSS allow, or DFS) in mac80211 + based on EEPROM. + + IEEE80211_CHAN_DISABLED: This channel is disabled. + IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted + on this channel. + IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. + IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel + is not permitted. + IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel + is not permitted. + */ + + /* + Change regulatory rule here. + + struct ieee80211_channel { + enum ieee80211_band band; + u16 center_freq; + u8 max_bandwidth; + u16 hw_value; + u32 flags; + int max_antenna_gain; + int max_power; + bool beacon_found; + u32 orig_flags; + int orig_mag, orig_mpwr; + }; + + In mac80211 layer, it will change flags, max_antenna_gain, + max_bandwidth, max_power. + */ + + switch(ReqType) + { + case REGDOM_SET_BY_CORE: + /* + Core queried CRDA for a dynamic world regulatory domain. + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by core: ")); + break; + + case REGDOM_SET_BY_USER: + /* + User asked the wireless core to set the regulatory domain. + (when iw, network manager, wpa supplicant, etc.) + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by user: ")); + break; + + case REGDOM_SET_BY_DRIVER: + /* + A wireless drivers has hinted to the wireless core it thinks + its knows the regulatory domain we should be in. + (when driver initialization, calling regulatory_hint) + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by driver: ")); + break; + + case REGDOM_SET_BY_COUNTRY_IE: + /* + The wireless core has received an 802.11 country information + element with regulatory information it thinks we should consider. + (when beacon receive, calling regulatory_hint_11d) + */ + CFG80211DBG(RT_DEBUG_ERROR, ("crda> requlation requestion by country IE: ")); + break; + } /* End of switch */ + + DBGPRINT(RT_DEBUG_OFF, ("00\n")); + + /* only follow rules from user */ + if (ReqType == REGDOM_SET_BY_USER) + { + /* keep Alpha2 and we can re-call the function when interface is up */ + CMD_RTPRIV_IOCTL_80211_REG_NOTIFY RegInfo; + + RegInfo.Alpha2[0] = '0'; + RegInfo.Alpha2[1] = '0'; + RegInfo.pWiphy = pWiphy; + + RTMP_DRIVER_80211_REG_NOTIFY(pAd, &RegInfo); + } /* End of if */ + + return 0; +} /* End of CFG80211_RegNotifier */ +#endif /* LINUX_VERSION_CODE */ + + +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ + +/* End of crda.c */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_ap.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_ap.c new file mode 100644 index 000000000..1861bf883 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_ap.c @@ -0,0 +1,822 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 function body. + + History: + +***************************************************************************/ +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT +#ifdef CONFIG_AP_SUPPORT + +#include "rt_config.h" + +static INT CFG80211DRV_UpdateTimIE(PRTMP_ADAPTER pAd, UINT mbss_idx, PUCHAR pBeaconFrame, UINT32 tim_ie_pos) +{ + UCHAR ID_1B, TimFirst, TimLast, *pTim, *ptr, New_Tim_Len; + UINT i; + + ptr = pBeaconFrame + tim_ie_pos; /* TIM LOCATION */ + *ptr = IE_TIM; + *(ptr + 2) = pAd->ApCfg.DtimCount; + *(ptr + 3) = pAd->ApCfg.DtimPeriod; + + TimFirst = 0; /* record first TIM byte != 0x00 */ + TimLast = 0; /* record last TIM byte != 0x00 */ + + pTim = pAd->ApCfg.MBSSID[mbss_idx].TimBitmaps; + + for(ID_1B=0; ID_1B < WLAN_MAX_NUM_OF_TIM; ID_1B++) + { + /* get the TIM indicating PS packets for 8 stations */ + UCHAR tim_1B = pTim[ID_1B]; + + if (ID_1B == 0) + tim_1B &= 0xfe; /* skip bit0 bc/mc */ + + if (tim_1B == 0) + continue; /* find next 1B */ + + if (TimFirst == 0) + TimFirst = ID_1B; + + TimLast = ID_1B; + } + + /* fill TIM content to beacon buffer */ + if (TimFirst & 0x01) + TimFirst --; /* find the even offset byte */ + + *(ptr + 1) = 3 + (TimLast - TimFirst + 1); /* TIM IE length */ + *(ptr + 4) = TimFirst; + + for(i=TimFirst; i <= TimLast; i++) + *(ptr + 5 + i - TimFirst) = pTim[i]; + + /* bit0 means backlogged mcast/bcast */ + if (pAd->ApCfg.DtimCount == 0) + *(ptr + 4) |= (pAd->ApCfg.MBSSID[mbss_idx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); + + /* adjust BEACON length according to the new TIM */ + New_Tim_Len = (2 + *(ptr+1)); + + return New_Tim_Len; +} + +static INT CFG80211DRV_UpdateApSettingFromBeacon(PRTMP_ADAPTER pAd, UINT mbss_idx, CMD_RTPRIV_IOCTL_80211_BEACON *pBeacon) +{ + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[mbss_idx]; + struct wifi_dev *wdev = &pMbss->wdev; + + const UCHAR *ssid_ie = NULL, *wpa_ie = NULL, *rsn_ie = NULL; + const UINT WFA_OUI = 0x0050F2; + const UCHAR WMM_OUI_TYPE = 0x2; + UCHAR *wmm_ie = NULL; + + const UCHAR *supp_rates_ie = NULL; + const UCHAR *ext_supp_rates_ie = NULL, *ht_cap = NULL, *ht_info = NULL; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + const UCHAR CFG_HT_OP_EID = WLAN_EID_HT_OPERATION; +#else + const UCHAR CFG_HT_OP_EID = WLAN_EID_HT_INFORMATION; +#endif /* LINUX_VERSION_CODE: 3.5.0 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + const UCHAR CFG_WPA_EID = WLAN_EID_VENDOR_SPECIFIC; +#else + const UCHAR CFG_WPA_EID = WLAN_EID_WPA; +#endif /* LINUX_VERSION_CODE: 3.8.0 */ + + ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, pBeacon->beacon_head+36, pBeacon->beacon_head_len-36); + supp_rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pBeacon->beacon_head+36, pBeacon->beacon_head_len-36); + /* if it doesn't find WPA_IE in tail first 30 bytes. treat it as is not found */ + wpa_ie = cfg80211_find_ie(CFG_WPA_EID, pBeacon->beacon_tail, pBeacon->beacon_tail_len); + rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, pBeacon->beacon_tail, pBeacon->beacon_tail_len); + wmm_ie = cfg80211_find_vendor_ie(WFA_OUI, WMM_OUI_TYPE, pBeacon->beacon_tail, pBeacon->beacon_tail_len); + ht_cap = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pBeacon->beacon_tail, pBeacon->beacon_tail_len); + ht_info = cfg80211_find_ie(CFG_HT_OP_EID, pBeacon->beacon_tail, pBeacon->beacon_tail_len); + + /* SSID */ + NdisZeroMemory(pMbss->Ssid, pMbss->SsidLen); + if (ssid_ie == NULL) + { + NdisMoveMemory(pMbss->Ssid, "CFG_Linux_GO", 12); + pMbss->SsidLen = 12; + DBGPRINT(RT_DEBUG_ERROR,("CFG: SSID Not Found In Packet\n")); + } + else + { + pMbss->SsidLen = ssid_ie[1]; + NdisCopyMemory(pMbss->Ssid, ssid_ie+2, pMbss->SsidLen); + DBGPRINT(RT_DEBUG_TRACE,("CFG : SSID: %s, %d\n", pMbss->Ssid, pMbss->SsidLen)); + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + if (pBeacon->hidden_ssid > 0 && pBeacon->hidden_ssid < 3) { + pMbss->bHideSsid = TRUE; + } + else + pMbss->bHideSsid = FALSE; + + if (pBeacon->hidden_ssid == 1) + pMbss->SsidLen = 0; +#endif /* LINUX_VERSION_CODE 3.4.0 */ + + /* WMM EDCA Paramter */ + CFG80211_SyncPacketWmmIe(pAd, pBeacon->beacon_tail, pBeacon->beacon_tail_len); + + /* Security */ + CFG80211_ParseBeaconIE(pAd, pMbss, wdev, wpa_ie, rsn_ie); + + pMbss->CapabilityInfo = CAP_GENERATE(1, 0, (wdev->WepStatus != Ndis802_11EncryptionDisabled), + (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1), pAd->CommonCfg.bUseShortSlotTime, /*SpectrumMgmt*/FALSE); + + /* Disable Driver-Internal Rekey */ + pMbss->WPAREKEY.ReKeyInterval = 0; + pMbss->WPAREKEY.ReKeyMethod = DISABLE_REKEY; + + if (pBeacon->interval != 0) + { + DBGPRINT(RT_DEBUG_TRACE,("CFG_TIM New BI %d\n", pBeacon->interval)); + pAd->CommonCfg.BeaconPeriod = pBeacon->interval; + } + + if (pBeacon->dtim_period != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG_TIM New DP %d\n", pBeacon->dtim_period)); + pAd->ApCfg.DtimPeriod = pBeacon->dtim_period; + } + +} + +VOID CFG80211DRV_DisableApInterface(PRTMP_ADAPTER pAd) +{ + /*CFG_TODO: IT Should be set fRTMP_ADAPTER_HALT_IN_PROGRESS */ + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + struct wifi_dev *wdev = &pMbss->wdev; + + pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = FALSE; + wdev->Hostapd = Hostapd_Diable; + + /* For AP - STA switch */ + if (pAd->CommonCfg.BBPCurrentBW != BW_40) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s, switch to BW_20\n", __FUNCTION__)); + bbp_set_bw(pAd, BW_20); + } + + /* Disable pre-TBTT interrupt */ + AsicSetPreTbtt(pAd, FALSE); + + if (!INFRA_ON(pAd)) + { + /* Disable piggyback */ + RTMPSetPiggyBack(pAd, FALSE); + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + } + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + AsicDisableSync(pAd); + } + + + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); +#ifdef CONFIG_STA_SUPPORT + /* re-assoc to STA's wdev */ + RTMP_OS_NETDEV_SET_WDEV(pAd->net_dev, &pAd->StaCfg.wdev); +#endif /*CONFIG_STA_SUPPORT*/ +} + +VOID CFG80211_UpdateBeacon( + VOID *pAdOrg, + UCHAR *beacon_head_buf, + UINT32 beacon_head_len, + UCHAR *beacon_tail_buf, + UINT32 beacon_tail_len, + BOOLEAN isAllUpdate) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[MAIN_MBSSID].BeaconBuf; + TXWI_STRUC *pTxWI = &pAd->BeaconTxWI; + UCHAR New_Tim_Len; + UINT32 beacon_len; + + /* Invoke From CFG80211 OPS For setting Beacon buffer */ + if (isAllUpdate) + { + /* 1. Update the Before TIM IE */ + NdisCopyMemory(pBeaconFrame, beacon_head_buf, beacon_head_len); + + /* 2. Update the TIM IE */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon = beacon_head_len; + + /* 3. Store the Tail Part For appending later */ + if (pCfg80211_ctrl->beacon_tail_buf != NULL) + os_free_mem(NULL, pCfg80211_ctrl->beacon_tail_buf); + + os_alloc_mem(NULL, (UCHAR **)&pCfg80211_ctrl->beacon_tail_buf, beacon_tail_len); + if (pCfg80211_ctrl->beacon_tail_buf != NULL) + { + NdisCopyMemory(pCfg80211_ctrl->beacon_tail_buf, beacon_tail_buf, beacon_tail_len); + pCfg80211_ctrl->beacon_tail_len = beacon_tail_len; + } + else + { + pCfg80211_ctrl->beacon_tail_len = 0; + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211 Beacon: MEM ALLOC ERROR\n")); + } + + return; + } + else /* Invoke From Beacon Timer */ + { + if (pAd->ApCfg.DtimCount == 0) + pAd->ApCfg.DtimCount = pAd->ApCfg.DtimPeriod - 1; + else + pAd->ApCfg.DtimCount -= 1; + } + + /* 4. Update the TIM IE */ + New_Tim_Len = CFG80211DRV_UpdateTimIE(pAd, MAIN_MBSSID, pBeaconFrame, + pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon); + + /* 5. Update the AFTER TIM IE */ + if (pCfg80211_ctrl->beacon_tail_buf != NULL) + { + NdisCopyMemory(pAd->ApCfg.MBSSID[MAIN_MBSSID].BeaconBuf + + pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon + New_Tim_Len, + pCfg80211_ctrl->beacon_tail_buf, pCfg80211_ctrl->beacon_tail_len); + + beacon_len = pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon + pCfg80211_ctrl->beacon_tail_len + + New_Tim_Len; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("BEACON ====> CFG80211_UpdateBeacon OOPS\n")); + return; + } + + BeaconTransmit.word = 0; +#ifdef RT_CFG80211_P2P_SUPPORT + + /* Should be Find the P2P IE Then Set Basic Rate to 6M */ + if (RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) + BeaconTransmit.field.MODE = MODE_OFDM; /* Use 6Mbps */ + else +#endif + BeaconTransmit.field.MODE = MODE_CCK; + BeaconTransmit.field.MCS = MCS_RATE_6; + + //YF + RTMPWriteTxWI(pAd, (UCHAR *)pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, + beacon_len, PID_MGMT, 0, 0, IFS_HTTXOP, &BeaconTransmit); + + updateAllBeacon(pAd, MAIN_MBSSID, beacon_len); +} + +BOOLEAN CFG80211DRV_OpsBeaconSet(VOID *pAdOrg, VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_BEACON *pBeacon; + pBeacon = (CMD_RTPRIV_IOCTL_80211_BEACON *)pData; + + CFG80211DRV_UpdateApSettingFromBeacon(pAd, MAIN_MBSSID, pBeacon); + CFG80211_UpdateBeacon(pAd, pBeacon->beacon_head, pBeacon->beacon_head_len, + pBeacon->beacon_tail, pBeacon->beacon_tail_len, + TRUE); +} + +BOOLEAN CFG80211DRV_OpsBeaconAdd(VOID *pAdOrg, VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_BEACON *pBeacon; + UINT32 rx_filter_flag; + BOOLEAN Cancelled; + INT i; + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + struct wifi_dev *wdev = &pMbss->wdev; + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> %s ==>\n", __FUNCTION__)); + + pBeacon = (CMD_RTPRIV_IOCTL_80211_BEACON *)pData; + +#ifdef UAPSD_SUPPORT + + pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable = TRUE; + wdev->UapsdInfo.bAPSDCapable = TRUE; + + pMbss->CapabilityInfo |= 0x0800; +#endif /* UAPSD_SUPPORT */ + + CFG80211DRV_UpdateApSettingFromBeacon(pAd, MAIN_MBSSID, pBeacon); + + rx_filter_flag = APNORMAL; + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block */ + + pAd->ApCfg.BssidNum = 1; + pAd->MacTab.MsduLifeTime = 20; /* default 5 seconds */ + /* CFG_TODO */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].BcnBufIdx = 0 ; + for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++) + pAd->ApCfg.MBSSID[MAIN_MBSSID].TimBitmaps[i] = 0; + + pMbss->bBcnSntReq = TRUE; + + /* For GO Timeout */ + pAd->ApCfg.StaIdleTimeout = 300; + pMbss->StationKeepAliveTime = 0; + + AsicDisableSync(pAd); + + if (pAd->CommonCfg.Channel > 14) + pAd->CommonCfg.PhyMode = (WMODE_A | WMODE_AN); + else + pAd->CommonCfg.PhyMode = (WMODE_B | WMODE_G |WMODE_GN); + + /* cfg_todo */ + wdev->bWmmCapable = TRUE; + + wdev->wdev_type = WDEV_TYPE_AP; + wdev->tx_pkt_allowed = ApAllowToSendPacket; + wdev->allow_data_tx = TRUE; + wdev->func_dev = (void *)&pAd->ApCfg.MBSSID[MAIN_MBSSID]; + wdev->sys_handle = (void *)pAd; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* Using netDev ptr from VifList if VifDevList Exist */ + PNET_DEV pNetDev = NULL; + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_GO)) != NULL)) + { + pMbss->MSSIDDev = pNetDev; + wdev->if_dev = pNetDev; + COPY_MAC_ADDR(wdev->bssid, pNetDev->dev_addr); + COPY_MAC_ADDR(wdev->if_addr, pNetDev->dev_addr); + + RTMP_OS_NETDEV_SET_WDEV(pNetDev, wdev); + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + { + pMbss->MSSIDDev = pAd->net_dev; + wdev->if_dev = pAd->net_dev; + COPY_MAC_ADDR(wdev->bssid, pAd->CurrentAddress); + COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); + + /* assoc to MBSSID's wdev */ + RTMP_OS_NETDEV_SET_WDEV(pAd->net_dev, wdev); + } + + DBGPRINT(RT_DEBUG_TRACE, ("New AP BSSID %02x:%02x:%02x:%02x:%02x:%02x (%d)\n", + PRINT_MAC(wdev->bssid), pAd->CommonCfg.PhyMode)); + + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->Antenna.field.TxPath == 2)) + bbp_set_txdac(pAd, 2); + else +#endif /* DOT11_N_SUPPORT */ + bbp_set_txdac(pAd, 0); + + /* Receiver Antenna selection */ + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) || wdev->bWmmCapable) + { + /* EDCA parameters used for AP's own transmission */ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + set_default_ap_edca_param(pAd); + + /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ + if (pAd->ApCfg.BssEdcaParm.bValid == FALSE) + set_default_sta_edca_param(pAd); + + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + } + else + AsicSetEdcaParm(pAd, NULL); + } + +#ifdef DOT11_N_SUPPORT + AsicSetRDG(pAd, pAd->CommonCfg.bRdg); + + AsicSetRalinkBurstMode(pAd, pAd->CommonCfg.bRalinkBurstMode); +#endif /* DOT11_N_SUPPORT */ + + AsicSetBssid(pAd, pAd->CurrentAddress); + mgmt_tb_set_mcast_entry(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s():Reset WCID Table\n", __FUNCTION__)); + AsicDelWcidTab(pAd, WCID_ALL); + + pAd->MacTab.Content[0].Addr[0] = 0x01; + pAd->MacTab.Content[0].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[0].HTPhyMode.field.MCS = 3; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + + AsicBBPAdjust(pAd); + //MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* P2P_GO */ + MlmeUpdateTxRates(pAd, FALSE, MAIN_MBSSID + MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /*AP */ +#ifdef RT_CFG80211_P2P_SUPPORT + if (!RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) +#endif + MlmeUpdateTxRates(pAd, FALSE, MIN_NET_DEVICE_FOR_MBSSID); + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + MlmeUpdateHtTxRates(pAd, MIN_NET_DEVICE_FOR_MBSSID); +#endif /* DOT11_N_SUPPORT */ + + /* Disable Protection first. */ + if (!INFRA_ON(pAd)) + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + + APUpdateCapabilityAndErpIe(pAd); +#ifdef DOT11_N_SUPPORT + APUpdateOperationMode(pAd); +#endif /* DOT11_N_SUPPORT */ + CFG80211_UpdateBeacon(pAd, pBeacon->beacon_head, pBeacon->beacon_head_len, + pBeacon->beacon_tail, pBeacon->beacon_tail_len, + TRUE); + + + + /* Enable BSS Sync*/ + AsicEnableApBssSync(pAd); + //pAd->P2pCfg.bSentProbeRSP = TRUE; + + AsicSetPreTbtt(pAd, TRUE); + + + OPSTATUS_SET_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); +#ifdef RT_CFG80211_SUPPORT +#ifdef RT_CFG80211_P2P_SUPPORT + if (!RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) +#endif /*RT_CFG80211_P2P_SUPPORT*/ + wdev->Hostapd=Hostapd_CFG; +#endif /*RT_CFG80211_SUPPORT*/ + return TRUE; +} + +BOOLEAN CFG80211DRV_ApKeyDel( + VOID *pAdOrg, + VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_KEY *pKeyInfo; + MAC_TABLE_ENTRY *pEntry; + + pKeyInfo = (CMD_RTPRIV_IOCTL_80211_KEY *)pData; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + if (pKeyInfo->bPairwise == FALSE ) +#else + if (pKeyInfo->KeyId > 0) +#endif + { + DBGPRINT(RT_DEBUG_TRACE,("CFG: AsicRemoveSharedKeyEntry %d\n", pKeyInfo->KeyId)); + AsicRemoveSharedKeyEntry(pAd, MAIN_MBSSID, pKeyInfo->KeyId); + } + else + { + pEntry = MacTableLookup(pAd, pKeyInfo->MAC); + + if (pEntry && (pEntry->Aid != 0)) + { + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + AsicRemovePairwiseKeyEntry(pAd, (UCHAR)pEntry->Aid); + } + } + + return TRUE; +} + + +VOID CFG80211DRV_RtsThresholdAdd( + VOID *pAdOrg, + UINT threshold) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + + if((threshold > 0) && (threshold <= MAX_RTS_THRESHOLD)) + pAd->CommonCfg.RtsThreshold = (USHORT)threshold; +#ifdef CONFIG_STA_SUPPORT + else if (threshold== 0) + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; +#endif /* CONFIG_STA_SUPPORT */ +} + + +VOID CFG80211DRV_FragThresholdAdd( + VOID *pAdOrg, + UINT threshold) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + if (threshold > MAX_FRAG_THRESHOLD || threshold < MIN_FRAG_THRESHOLD) + { + /*Illegal FragThresh so we set it to default*/ + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + } + else if (threshold % 2 == 1) + { + /* + The length of each fragment shall always be an even number of octets, + except for the last fragment of an MSDU or MMPDU, which may be either + an even or an odd number of octets. + */ + pAd->CommonCfg.FragmentThreshold = (USHORT)(threshold - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)threshold; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD) + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + else + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + } +#endif /* CONFIG_STA_SUPPORT */ +} + + +BOOLEAN CFG80211DRV_ApKeyAdd( + VOID *pAdOrg, + VOID *pData) +{ +#ifdef CONFIG_AP_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_KEY *pKeyInfo; + MAC_TABLE_ENTRY *pEntry; + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + struct wifi_dev *pWdev = &pMbss->wdev; + UINT8 Wcid; +#ifdef RT_CFG80211_SUPPORT + UINT apidx = MAIN_MBSSID; +#endif /*RT_CFG80211_P2P_SUPPORT*/ + + DBGPRINT(RT_DEBUG_TRACE,("%s =====> \n", __FUNCTION__)); + pKeyInfo = (CMD_RTPRIV_IOCTL_80211_KEY *)pData; + + if (pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP40 || pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP104) + { + pWdev->WepStatus = Ndis802_11WEPEnabled; + { + UCHAR CipherAlg; + CIPHER_KEY *pSharedKey; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + pSharedKey = &pAd->SharedKey[apidx][pKeyInfo->KeyId]; + NdisMoveMemory(pSharedKey->Key, pKeyInfo->KeyBuf, pKeyInfo->KeyLen); + + + if (pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP40) + pAd->SharedKey[apidx][pKeyInfo->KeyId].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[apidx][pKeyInfo->KeyId].CipherAlg = CIPHER_WEP128; + + AsicAddSharedKeyEntry(pAd, apidx, pKeyInfo->KeyId, pSharedKey); + } + } + else if(pKeyInfo->KeyType == RT_CMD_80211_KEY_WPA) + { + if (pKeyInfo->cipher == Ndis802_11AESEnable) + { + /* AES */ + //pWdev->WepStatus = Ndis802_11Encryption3Enabled; + //pWdev->GroupKeyWepStatus = Ndis802_11Encryption3Enabled; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + if (pKeyInfo->bPairwise == FALSE ) +#else + if (pKeyInfo->KeyId > 0) +#endif /* LINUX_VERSION_CODE 2.6.37 */ + { + if (pWdev->GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG: Set AES Security Set. (GROUP) %d\n", pKeyInfo->KeyLen)); + pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].KeyLen= LEN_TK; + NdisMoveMemory(pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].Key, pKeyInfo->KeyBuf, pKeyInfo->KeyLen); + + pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].CipherAlg = CIPHER_AES; + + AsicAddSharedKeyEntry(pAd, MAIN_MBSSID, pKeyInfo->KeyId, + &pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId]); + + GET_GroupKey_WCID(pAd, Wcid, MAIN_MBSSID); + RTMPSetWcidSecurityInfo(pAd, MAIN_MBSSID, (UINT8)(pKeyInfo->KeyId), + pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].CipherAlg, Wcid, SHAREDKEYTABLE); + + } + } + else + { + if (pKeyInfo->MAC) + pEntry = MacTableLookup(pAd, pKeyInfo->MAC); + + if(pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG: Set AES Security Set. (PAIRWISE) %d\n", pKeyInfo->KeyLen)); + pEntry->PairwiseKey.KeyLen = LEN_TK; + NdisCopyMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pKeyInfo->KeyBuf, OFFSET_OF_PTK_TK); + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], pKeyInfo->KeyLen); + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; + + AsicAddPairwiseKeyEntry(pAd, (UCHAR)pEntry->Aid, &pEntry->PairwiseKey); + RTMPSetWcidSecurityInfo(pAd, pEntry->apidx, (UINT8)(pKeyInfo->KeyId & 0x0fff), + pEntry->PairwiseKey.CipherAlg, pEntry->Aid, PAIRWISEKEYTABLE); + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("CFG: Set AES Security Set. (PAIRWISE) But pEntry NULL\n")); + } + + } + }else if (pKeyInfo->cipher == Ndis802_11TKIPEnable) { + /* TKIP */ + //pWdev->WepStatus = Ndis802_11Encryption2Enabled; + //pWdev->GroupKeyWepStatus = Ndis802_11Encryption2Enabled; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + if (pKeyInfo->bPairwise == FALSE ) +#else + if (pKeyInfo->KeyId > 0) +#endif /* LINUX_VERSION_CODE 2.6.37 */ + { + if (pWdev->GroupKeyWepStatus == Ndis802_11Encryption2Enabled) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG: Set TKIP Security Set. (GROUP) %d\n", pKeyInfo->KeyLen)); + pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].KeyLen= LEN_TK; + NdisMoveMemory(pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].Key, pKeyInfo->KeyBuf, pKeyInfo->KeyLen); + + pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].CipherAlg = CIPHER_TKIP; + + AsicAddSharedKeyEntry(pAd, MAIN_MBSSID, pKeyInfo->KeyId, + &pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId]); + + GET_GroupKey_WCID(pAd, Wcid, MAIN_MBSSID); + RTMPSetWcidSecurityInfo(pAd, MAIN_MBSSID, (UINT8)(pKeyInfo->KeyId), + pAd->SharedKey[MAIN_MBSSID][pKeyInfo->KeyId].CipherAlg, Wcid, SHAREDKEYTABLE); + + } + } + else + { + if (pKeyInfo->MAC) + pEntry = MacTableLookup(pAd, pKeyInfo->MAC); + + if(pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG: Set TKIP Security Set. (PAIRWISE) %d\n", pKeyInfo->KeyLen)); + pEntry->PairwiseKey.KeyLen = LEN_TK; + NdisCopyMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pKeyInfo->KeyBuf, OFFSET_OF_PTK_TK); + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], pKeyInfo->KeyLen); + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + + AsicAddPairwiseKeyEntry(pAd, (UCHAR)pEntry->Aid, &pEntry->PairwiseKey); + RTMPSetWcidSecurityInfo(pAd, pEntry->apidx, (UINT8)(pKeyInfo->KeyId & 0x0fff), + pEntry->PairwiseKey.CipherAlg, pEntry->Aid, PAIRWISEKEYTABLE); + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("CFG: Set TKIP Security Set. (PAIRWISE) But pEntry NULL\n")); + } + + } + } + + } +#endif /* CONFIG_AP_SUPPORT */ + return TRUE; + +} + +INT CFG80211_StaPortSecured( + IN VOID *pAdCB, + IN UCHAR *pMac, + IN UINT flag) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + MAC_TABLE_ENTRY *pEntry; + + pEntry = MacTableLookup(pAd, pMac); + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't find pEntry in CFG80211_StaPortSecured\n")); + } + else + { + if (flag) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->WpaState = AS_PTKINITDONE; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + DBGPRINT(RT_DEBUG_TRACE,("AID:%d, PortSecured\n", pEntry->Aid)); + } + else + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE,("AID:%d, PortNotSecured\n", pEntry->Aid)); + } + } + + return 0; +} + +INT CFG80211_ApStaDel( + IN VOID *pAdCB, + IN UCHAR *pMac) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + MAC_TABLE_ENTRY *pEntry; + + if (pMac == NULL) + { +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* From WCID=2 */ + if (INFRA_ON(pAd)) + ;//P2PMacTableReset(pAd); + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + MacTableReset(pAd); + } + else + { + pEntry = MacTableLookup(pAd, pMac); + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_NO_LONGER_VALID, FALSE); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Can't find pEntry in ApStaDel\n")); + } +} + +INT CFG80211_setApDefaultKey( + IN VOID *pAdCB, + IN UINT Data +) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + DBGPRINT(RT_DEBUG_TRACE, ("Set Ap Default Key: %d\n", Data)); + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId = Data; + return 0; +} + +INT CFG80211_ApStaDelSendEvent(PRTMP_ADAPTER pAd, const PUCHAR mac_addr) +{ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + PNET_DEV pNetDev = NULL; + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_GO)) != NULL)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CONCURRENT_DEVICE CFG : GO NOITFY THE CLIENT Disconnected\n")); + CFG80211OS_DelSta(pNetDev, mac_addr); + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + { + DBGPRINT(RT_DEBUG_TRACE, ("SINGLE_DEVICE CFG : GO NOITFY THE CLIENT Disconnected\n")); + CFG80211OS_DelSta(pAd->net_dev, mac_addr); + } +} + +#endif /* CONFIG_AP_SUPPORT */ +#endif /* RT_CFG80211_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_inf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_inf.c new file mode 100644 index 000000000..2c3c07b36 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_inf.c @@ -0,0 +1,971 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2012, 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: + cfg80211_inf.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + YF Luo 06-28-2012 Init version + 12-26-2013 Integration of NXTC +*/ +#define RTMP_MODULE_OS + +#include "rt_config.h" +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) +#ifdef RT_CFG80211_SUPPORT + +extern INT ApCliAllowToSendPacket( + RTMP_ADAPTER *pAd, struct wifi_dev *wdev, + PNDIS_PACKET pPacket, UCHAR *pWcid); + +BOOLEAN CFG80211DRV_OpsChgVirtualInf(RTMP_ADAPTER *pAd, VOID *pData) +{ + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + CFG80211_CB *p80211CB = pAd->pCfg80211_CB; + UINT newType, oldType; + CMD_RTPRIV_IOCTL_80211_VIF_PARM *pVifParm; + pVifParm = (CMD_RTPRIV_IOCTL_80211_VIF_PARM *)pData; + + newType = pVifParm->newIfType; + oldType = pVifParm->oldIfType; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* After P2P NEGO phase, the device type may be change from GC to GO + or no change. We remove the GC in VIF list if nego as GO case. + */ + if ((newType == RT_CMD_80211_IFTYPE_P2P_GO) && + (oldType == RT_CMD_80211_IFTYPE_P2P_CLIENT)) + { + RTMP_CFG80211_VirtualIF_CancelP2pClient(pAd); + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> @@@ Change from %u to %u Mode\n",oldType,newType)); + + pCfg80211_ctrl->P2POpStatusFlags = CFG_P2P_DISABLE; + if (newType == RT_CMD_80211_IFTYPE_P2P_CLIENT) + { + pCfg80211_ctrl->P2POpStatusFlags = CFG_P2P_CLI_UP; + + } + else if (newType == RT_CMD_80211_IFTYPE_P2P_GO) + { + pCfg80211_ctrl->P2POpStatusFlags = CFG_P2P_GO_UP; + } +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ + +#ifdef CONFIG_STA_SUPPORT + /* Change Device Type */ + if (newType == RT_CMD_80211_IFTYPE_ADHOC) + { + Set_NetworkType_Proc(pAd, "Adhoc"); + } + else if ((newType == RT_CMD_80211_IFTYPE_STATION) || + (newType == RT_CMD_80211_IFTYPE_P2P_CLIENT)) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Change the Interface to STA Mode\n")); + +#ifdef CONFIG_AP_SUPPORT + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + CFG80211DRV_DisableApInterface(pAd); +#endif /* CONFIG_AP_SUPPORT */ + + pAd->cfg80211_ctrl.isCfgInApMode = RT_CMD_80211_IFTYPE_STATION; + } + else +#endif /*CONFIG_STA_SUPPORT*/ + if ((newType == RT_CMD_80211_IFTYPE_AP) || + (newType == RT_CMD_80211_IFTYPE_P2P_GO)) + { + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Change the Interface to AP Mode\n")); + pAd->cfg80211_ctrl.isCfgInApMode = RT_CMD_80211_IFTYPE_AP; + } +#ifdef CONFIG_STA_SUPPORT + else if (newType == RT_CMD_80211_IFTYPE_MONITOR) + { + /* set packet filter */ + Set_NetworkType_Proc(pAd, "Monitor"); + + if (pVifParm->MonFilterFlag != 0) + { + UINT32 Filter; + + RTMP_IO_READ32(pAd, RX_FILTR_CFG, &Filter); + + if ((pVifParm->MonFilterFlag & RT_CMD_80211_FILTER_FCSFAIL) == RT_CMD_80211_FILTER_FCSFAIL) + { + Filter = Filter & (~0x01); + } + else + { + Filter = Filter | 0x01; + } + + if ((pVifParm->MonFilterFlag & RT_CMD_80211_FILTER_PLCPFAIL) == RT_CMD_80211_FILTER_PLCPFAIL) + { + Filter = Filter & (~0x02); + } + else + { + Filter = Filter | 0x02; + } + + if ((pVifParm->MonFilterFlag & RT_CMD_80211_FILTER_CONTROL) == RT_CMD_80211_FILTER_CONTROL) + { + Filter = Filter & (~0xFF00); + } + else + { + Filter = Filter | 0xFF00; + } + + if ((pVifParm->MonFilterFlag & RT_CMD_80211_FILTER_OTHER_BSS) == RT_CMD_80211_FILTER_OTHER_BSS) + { + Filter = Filter & (~0x08); + } + else + { + Filter = Filter | 0x08; + } + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Filter); + pVifParm->MonFilterFlag = Filter; + } + } +#endif /*CONFIG_STA_SUPPORT*/ + + if ((newType == RT_CMD_80211_IFTYPE_P2P_CLIENT) || + (newType == RT_CMD_80211_IFTYPE_P2P_GO)) + { + COPY_MAC_ADDR(pAd->cfg80211_ctrl.P2PCurrentAddress, pVifParm->net_dev->dev_addr); + } + else + { +#ifdef RT_CFG80211_P2P_SUPPORT + pCfg80211_ctrl->bP2pCliPmEnable = FALSE; + pCfg80211_ctrl->bPreKeepSlient = FALSE; + pCfg80211_ctrl->bKeepSlient = FALSE; + pCfg80211_ctrl->NoAIndex = MAX_LEN_OF_MAC_TABLE; + pCfg80211_ctrl->MyGOwcid = MAX_LEN_OF_MAC_TABLE; + pCfg80211_ctrl->CTWindows= 0; /* CTWindows and OppPS parameter field */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + } + + return TRUE; +} + +#ifdef RT_CFG80211_P2P_SUPPORT +BOOLEAN RTMP_CFG80211_VIF_P2P_GO_ON(VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + PNET_DEV pNetDev = NULL; + + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_GO)) != NULL)) + return TRUE; + else + return FALSE; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE + if(CFG80211_P2P_TEST_BIT(pAd->cfg80211_ctrl.P2POpStatusFlags, CFG_P2P_GO_UP)) + return TRUE; + else + return FALSE; +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ + + return FALSE; +} + +BOOLEAN RTMP_CFG80211_VIF_P2P_CLI_ON(VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + PNET_DEV pNetDev = NULL; + + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_CLIENT)) != NULL)) + return TRUE; + else + return FALSE; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE + if(CFG80211_P2P_TEST_BIT(pAd->cfg80211_ctrl.P2POpStatusFlags, CFG_P2P_CLI_UP)) + return TRUE; + else + return FALSE; +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ + + return FALSE; +} +#endif /* RT_CFG80211_P2P_SUPPORT */ + + +BOOLEAN CFG80211DRV_OpsVifAdd(VOID *pAdOrg, VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_VIF_SET *pVifInfo; + pVifInfo = (CMD_RTPRIV_IOCTL_80211_VIF_SET *)pData; + + /* Already one VIF in list */ + if (pAd->cfg80211_ctrl.Cfg80211VifDevSet.isGoingOn) + return FALSE; + + pAd->cfg80211_ctrl.Cfg80211VifDevSet.isGoingOn = TRUE; + RTMP_CFG80211_VirtualIF_Init(pAd, pVifInfo->vifName, pVifInfo->vifType); + return TRUE; +} + +BOOLEAN RTMP_CFG80211_VIF_ON(VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + return pAd->cfg80211_ctrl.Cfg80211VifDevSet.isGoingOn; +} + + +static +PCFG80211_VIF_DEV RTMP_CFG80211_FindVifEntry_ByMac(VOID *pAdSrc, PNET_DEV pNewNetDev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + while (pDevEntry != NULL) + { + if (RTMPEqualMemory(pDevEntry->net_dev->dev_addr, pNewNetDev->dev_addr, MAC_ADDR_LEN)) + return pDevEntry; + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } + + return NULL; +} + +PNET_DEV RTMP_CFG80211_FindVifEntry_ByType(VOID *pAdSrc, UINT32 devType) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + while (pDevEntry != NULL) + { + if (pDevEntry->devType == devType) + return pDevEntry->net_dev; + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } + + return NULL; +} + +PWIRELESS_DEV RTMP_CFG80211_FindVifEntryWdev_ByType( + IN VOID *pAdSrc, + UINT32 devType) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + while (pDevEntry != NULL) + { + if (pDevEntry->devType == devType) + return pDevEntry->net_dev->ieee80211_ptr; + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } + + return NULL; +} + +VOID RTMP_CFG80211_AddVifEntry(VOID *pAdSrc, PNET_DEV pNewNetDev, UINT32 DevType) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PCFG80211_VIF_DEV pNewVifDev = NULL; + + os_alloc_mem(NULL, (UCHAR **)&pNewVifDev, sizeof(CFG80211_VIF_DEV)); + if (pNewVifDev) + { + NdisZeroMemory(pNewVifDev, sizeof(CFG80211_VIF_DEV)); + + pNewVifDev->pNext = NULL; + pNewVifDev->net_dev = pNewNetDev; + pNewVifDev->devType = DevType; + NdisZeroMemory(pNewVifDev->CUR_MAC, MAC_ADDR_LEN); + NdisCopyMemory(pNewVifDev->CUR_MAC, pNewNetDev->dev_addr, MAC_ADDR_LEN); + + insertTailList(&pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList, (PLIST_ENTRY)pNewVifDev); + DBGPRINT(RT_DEBUG_TRACE, ("Add CFG80211 VIF Device, Type: %d.\n", pNewVifDev->devType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Error in alloc mem in New CFG80211 VIF Function.\n")); + } +} + +VOID RTMP_CFG80211_RemoveVifEntry(VOID *pAdSrc, PNET_DEV pNewNetDev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = (PLIST_ENTRY)RTMP_CFG80211_FindVifEntry_ByMac(pAd, pNewNetDev); + + if (pListEntry) + { + delEntryList(&pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList, pListEntry); + os_free_mem(NULL, pListEntry); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Error in RTMP_CFG80211_RemoveVifEntry.\n")); + } +} + +PNET_DEV RTMP_CFG80211_VirtualIF_Get( + IN VOID *pAdSrc +) +{ + //PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + //return pAd->Cfg80211VifDevSet.Cfg80211VifDev[0].net_dev; + return NULL; +} + +#ifdef RT_CFG80211_P2P_SUPPORT +VOID RTMP_CFG80211_VirtualIF_CancelP2pClient(VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("==> %s\n", __FUNCTION__)); + + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + while (pDevEntry != NULL) + { + if (pDevEntry->devType == RT_CMD_80211_IFTYPE_P2P_CLIENT) + { + DBGPRINT(RT_DEBUG_ERROR, ("==> RTMP_CFG80211_VirtualIF_CancelP2pClient HIT.\n")); + pDevEntry->devType = RT_CMD_80211_IFTYPE_P2P_GO; + break; + } + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } + + pAd->flg_apcli_init = FALSE; + pAd->ApCfg.ApCliTab[MAIN_MBSSID].wdev.if_dev = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("<== %s\n", __FUNCTION__)); +} +#endif /* RT_CFG80211_P2P_SUPPORT */ + +static INT CFG80211_VirtualIF_Open(PNET_DEV dev_p) +{ + VOID *pAdSrc; + + pAdSrc = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAdSrc); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %d,%s\n", __FUNCTION__, dev_p->ifindex, + RTMP_OS_NETDEV_GET_DEVNAME(dev_p))); + + //if (VIRTUAL_IF_UP(pAd) != 0) + // return -1; + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + +#ifdef RT_CFG80211_P2P_SUPPORT + if (dev_p->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_P2P_CLIENT) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_VirtualIF_Open\n")); + pAd->flg_apcli_init = TRUE; + ApCli_Open(pAd, dev_p); + return 0; + } +#endif /* RT_CFG80211_P2P_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef CONFIG_AP_SUPPORT + if(dev_p->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_MONITOR) + { + pAd->ApCfg.BssType = BSS_MONITOR; + pAd->sniffer_ctl.sniffer_type = RADIOTAP_TYPE; + AsicSetRxFilter(pAd); + } +#endif /*CONFIG_AP_SUPPORT*/ +#endif /* CONFIG_SNIFFER_SUPPORT */ + RTMP_OS_NETDEV_START_QUEUE(dev_p); + DBGPRINT(RT_DEBUG_TRACE, ("%s: <=== %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(dev_p))); + + return 0; +} + +static INT CFG80211_VirtualIF_Close(PNET_DEV dev_p) +{ + VOID *pAdSrc; + + pAdSrc = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAdSrc); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + +#ifdef RT_CFG80211_P2P_SUPPORT + if (dev_p->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_P2P_CLIENT) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_VirtualIF_Close\n")); + CFG80211OS_ScanEnd(pAd->pCfg80211_CB, TRUE); + RT_MOD_DEC_USE_COUNT(); + return ApCli_Close(pAd, dev_p); + } +#endif /* RT_CFG80211_P2P_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef CONFIG_AP_SUPPORT + if(dev_p->ieee80211_ptr->iftype == RT_CMD_80211_IFTYPE_MONITOR) + { + pAd->ApCfg.BssType = BSS_INFRA; + AsicSetRxFilter(pAd); + } +#endif /*CONFIG_AP_SUPPORT*/ +#endif /*CONFIG_SNIFFER_SUPPORT*/ + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(dev_p))); + + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); + + if (netif_carrier_ok(dev_p)) + netif_carrier_off(dev_p); +#ifdef CONFIG_STA_SUPPORT + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + + else if (ADHOC_ON(pAd)) + AsicEnableIbssSync(pAd); +#else + else + AsicDisableSync(pAd); +#endif + + //VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + return 0; +} + +static INT CFG80211_PacketSend(PNDIS_PACKET pPktSrc, PNET_DEV pDev, RTMP_NET_PACKET_TRANSMIT Func) +{ + PRTMP_ADAPTER pAd; + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + + /* To Indicate from Which VIF */ + switch (pDev->ieee80211_ptr->iftype) + { + case RT_CMD_80211_IFTYPE_AP: + //minIdx = MIN_NET_DEVICE_FOR_CFG80211_VIF_AP; + RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); + break; + + case RT_CMD_80211_IFTYPE_P2P_GO:; + //minIdx = MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO; + if(!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Drop the Packet due P2P GO not in ready state\n")); + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } + RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); + break; + + case RT_CMD_80211_IFTYPE_P2P_CLIENT: + //minIdx = MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_CLI; + RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); + break; + + case RT_CMD_80211_IFTYPE_STATION: + default: + DBGPRINT(RT_DEBUG_TRACE, ("Unknown CFG80211 I/F Type(%d)\n", pDev->ieee80211_ptr->iftype)); + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } + + DBGPRINT(RT_DEBUG_INFO, ("CFG80211 Packet Type [%s](%d)\n", + pDev->name, pDev->ieee80211_ptr->iftype)); + + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPktSrc, MAIN_MBSSID); + + return Func(RTPKT_TO_OSPKT(pPktSrc)); +} + +static INT CFG80211_VirtualIF_PacketSend( + struct sk_buff *skb, PNET_DEV dev_p) +{ + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_INFO, ("%s ---> %d\n", __FUNCTION__, dev_p->ieee80211_ptr->iftype)); + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(dev_p))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(NULL, skb, NDIS_STATUS_FAILURE); + return 0; + } + + /* The device not ready to send packt. */ + wdev = RTMP_OS_NETDEV_GET_WDEV(dev_p); + ASSERT(wdev); + if (!wdev) return -1; + + return CFG80211_PacketSend(skb, dev_p, rt28xx_packet_xmit); +} + +static INT CFG80211_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd) +{ + + RTMP_ADAPTER *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + return -ENETDOWN; + + DBGPRINT(RT_DEBUG_TRACE, ("%s --->\n", __FUNCTION__)); + + return rt28xx_ioctl(dev_p, rq_p, cmd); + +} + +VOID RTMP_CFG80211_VirtualIF_Init( + IN VOID *pAdSrc, + IN CHAR *pDevName, + IN UINT32 DevType) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + RTMP_OS_NETDEV_OP_HOOK netDevHook, *pNetDevOps; + PNET_DEV new_dev_p; +#ifdef RT_CFG80211_P2P_SUPPORT + APCLI_STRUCT *pApCliEntry; +#endif /* RT_CFG80211_P2P_SUPPORT */ + struct wifi_dev *wdev; + + CHAR preIfName[12]; + UINT devNameLen = strlen(pDevName); + UINT preIfIndex = pDevName[devNameLen-1] - 48; + CFG80211_CB *p80211CB = pAd->pCfg80211_CB; + struct wireless_dev *pWdev; + UINT32 MC_RowID = 0, IoctlIF = 0, Inf = INT_P2P; + + memset(preIfName, 0, sizeof(preIfName)); + NdisCopyMemory(preIfName, pDevName, devNameLen-1); + + pNetDevOps=&netDevHook; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ---> (%s, %s, %d)\n", __FUNCTION__, pDevName, preIfName, preIfIndex)); + + /* init operation functions and flags */ + NdisZeroMemory(&netDevHook, sizeof(netDevHook)); + netDevHook.open = CFG80211_VirtualIF_Open; /* device opem hook point */ + netDevHook.stop = CFG80211_VirtualIF_Close; /* device close hook point */ + netDevHook.xmit = CFG80211_VirtualIF_PacketSend; /* hard transmit hook point */ + netDevHook.ioctl = CFG80211_VirtualIF_Ioctl; /* ioctl hook point */ + +#if WIRELESS_EXT >= 12 + //netDevHook.iw_handler = (void *)&rt28xx_ap_iw_handler_def; +#endif /* WIRELESS_EXT >= 12 */ + + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, Inf, preIfIndex, sizeof(PRTMP_ADAPTER), preIfName); + + if (new_dev_p == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (CFG80211)...\n")); + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Register CFG80211 I/F (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(new_dev_p))); + } + + new_dev_p->destructor = free_netdev; + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + pNetDevOps->needProtcted = TRUE; + + NdisMoveMemory(&pNetDevOps->devAddr[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + + //CFG_TODO + /* + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + pNetDevOps->devAddr[0] += 2; /* NEW BSSID */ + else + { +#ifdef P2P_ODD_MAC_ADJUST + if (pNetDevOps->devAddr[5] & 0x01 == 0x01) + pNetDevOps->devAddr[5] -= 1; + else +#endif /* P2P_ODD_MAC_ADJUST */ + pNetDevOps->devAddr[5] += FIRST_MBSSID; + } + + switch (DevType) + { + case RT_CMD_80211_IFTYPE_MONITOR: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211 I/F Monitor Type\n")); + + //RTMP_OS_NETDEV_SET_TYPE_MONITOR(new_dev_p); + break; +#ifdef RT_CFG80211_P2P_SUPPORT + case RT_CMD_80211_IFTYPE_P2P_CLIENT: + pApCliEntry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + wdev = &pApCliEntry->wdev; + wdev->wdev_type = WDEV_TYPE_STA; + wdev->func_dev = pApCliEntry; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = new_dev_p; + wdev->tx_pkt_allowed = ApCliAllowToSendPacket; + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + RTMP_OS_NETDEV_SET_WDEV(new_dev_p, wdev); + if (rtmp_wdev_idx_reg(pAd, wdev) < 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Assign wdev idx for %s failed, free net device!\n", + __FUNCTION__,RTMP_OS_NETDEV_GET_DEVNAME(new_dev_p))); + RtmpOSNetDevFree(new_dev_p); + break; + } + + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(wdev->if_addr, pNetDevOps->devAddr); + break; + case RT_CMD_80211_IFTYPE_P2P_GO: + pNetDevOps->priv_flags = INT_P2P; + pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = NULL; + /* The Behivaor in SetBeacon Ops */ + //pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = new_dev_p; + pAd->cfg80211_ctrl.isCfgInApMode = RT_CMD_80211_IFTYPE_AP; + COPY_MAC_ADDR(pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.if_addr, pNetDevOps->devAddr); + COPY_MAC_ADDR(pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.bssid, pNetDevOps->devAddr); + break; +#endif /* RT_CFG80211_P2P_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR, ("Unknown CFG80211 I/F Type (%d)\n", DevType)); + } + + //CFG_TODO : should be move to VIF_CHG + if ((DevType == RT_CMD_80211_IFTYPE_P2P_CLIENT) || + (DevType == RT_CMD_80211_IFTYPE_P2P_GO)) + { + COPY_MAC_ADDR(pAd->cfg80211_ctrl.P2PCurrentAddress, pNetDevOps->devAddr); + } + + pWdev = kzalloc(sizeof(*pWdev), GFP_KERNEL); + + new_dev_p->ieee80211_ptr = pWdev; + pWdev->wiphy = p80211CB->pCfg80211_Wdev->wiphy; + SET_NETDEV_DEV(new_dev_p, wiphy_dev(pWdev->wiphy)); + pWdev->netdev = new_dev_p; + pWdev->iftype = DevType; + + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + + AsicSetBssid(pAd, pAd->CurrentAddress); + + /* Record the pNetDevice to Cfg80211VifDevList */ + RTMP_CFG80211_AddVifEntry(pAd, new_dev_p, DevType); + + DBGPRINT(RT_DEBUG_TRACE, ("%s <---\n", __FUNCTION__)); +} + +VOID RTMP_CFG80211_VirtualIF_Remove( + IN VOID *pAdSrc, + IN PNET_DEV dev_p, + IN UINT32 DevType) +{ + + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + BOOLEAN isGoOn = FALSE; + struct wifi_dev *wdev; + + if (dev_p) + { + RTMP_CFG80211_RemoveVifEntry(pAd, dev_p); + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); +#ifdef RT_CFG80211_P2P_SUPPORT + pAd->cfg80211_ctrl.Cfg80211VifDevSet.isGoingOn = FALSE; + isGoOn = RTMP_CFG80211_VIF_P2P_GO_ON(pAd); + + if (isGoOn) + { + RtmpOSNetDevDetach(dev_p); + pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = NULL; + } + else if (pAd->flg_apcli_init) + { + wdev = &pAd->ApCfg.ApCliTab[MAIN_MBSSID].wdev; + + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + cfg80211_disconnected(dev_p, 0, NULL, 0, GFP_KERNEL); + + NdisZeroMemory(pAd->ApCfg.ApCliTab[MAIN_MBSSID].CfgApCliBssid, MAC_ADDR_LEN); + RtmpOSNetDevDetach(dev_p); + rtmp_wdev_idx_unreg(pAd, wdev); + pAd->flg_apcli_init = FALSE; + wdev->if_dev = NULL; + } + else +#endif /* RT_CFG80211_P2P_SUPPORT */ + { + /* Never Opened When New Netdevice on */ + RtmpOSNetDevDetach(dev_p); + } + + + if (dev_p->ieee80211_ptr) + { + kfree(dev_p->ieee80211_ptr); + dev_p->ieee80211_ptr = NULL; + } + } +} + +VOID RTMP_CFG80211_AllVirtualIF_Remove( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + + while ((pDevEntry != NULL) && (pCacheList->size != 0)) + { + RtmpOSNetDevProtect(1); + RTMP_CFG80211_VirtualIF_Remove(pAd, pDevEntry->net_dev, pDevEntry->net_dev->ieee80211_ptr->iftype); + RtmpOSNetDevProtect(0); + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } +} +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +static INT CFG80211_DummyP2pIf_Open( + IN PNET_DEV dev_p) +{ + struct wireless_dev *wdev = dev_p->ieee80211_ptr; + + if (!wdev) + return -EINVAL; + + wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + wdev->wiphy->interface_modes |= BIT(RT_CMD_80211_IFTYPE_P2P_DEVICE); +#ifndef RT_CFG80211_P2P_STATIC_CONCURRENT_DEVICE + wdev->iftype = RT_CMD_80211_IFTYPE_P2P_CLIENT; +#endif /* RT_CFG80211_P2P_STATIC_CONCURRENT_DEVICE */ +#endif /* LINUX_VERSION_CODE: 3.7.0 */ + return 0; +} + +static INT CFG80211_DummyP2pIf_Close( + IN PNET_DEV dev_p) +{ + struct wireless_dev *wdev = dev_p->ieee80211_ptr; + + if (!wdev) + return -EINVAL; + + wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) + & (~(BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + | BIT(RT_CMD_80211_IFTYPE_P2P_DEVICE) +#endif /* LINUX_VERSION_CODE: 3.7.0 */ + )); + return 0; +} + +static INT CFG80211_DummyP2pIf_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd) +{ + RTMP_ADAPTER *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + return -ENETDOWN; + + DBGPRINT(RT_DEBUG_TRACE, ("%s --->\n", __FUNCTION__)); + + return rt28xx_ioctl(dev_p, rq_p, cmd); + +} + +static INT CFG80211_DummyP2pIf_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p) +{ + return 0; +} + +VOID RTMP_CFG80211_DummyP2pIf_Remove( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + PNET_DEV dummy_p2p_net_dev = (PNET_DEV)cfg80211_ctrl->dummy_p2p_net_dev; + + DBGPRINT(RT_DEBUG_TRACE, (" %s =====> \n", __FUNCTION__)); + RtmpOSNetDevProtect(1); + if (dummy_p2p_net_dev) + { + RTMP_OS_NETDEV_STOP_QUEUE(dummy_p2p_net_dev); + RtmpOSNetDevDetach(dummy_p2p_net_dev); + if (dummy_p2p_net_dev->ieee80211_ptr) + { + kfree(dummy_p2p_net_dev->ieee80211_ptr); + dummy_p2p_net_dev->ieee80211_ptr = NULL; + } + + RtmpOSNetDevProtect(0); + RtmpOSNetDevFree(dummy_p2p_net_dev); + RtmpOSNetDevProtect(1); + + cfg80211_ctrl->flg_cfg_dummy_p2p_init = FALSE; + } + RtmpOSNetDevProtect(0); + DBGPRINT(RT_DEBUG_TRACE, (" %s <=====\n", __FUNCTION__)); +} + +VOID RTMP_CFG80211_DummyP2pIf_Init( + IN VOID *pAdSrc) +{ +#define INF_CFG80211_DUMMY_P2P_NAME "p2p" + + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + CFG80211_CB *p80211CB = pAd->pCfg80211_CB; + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + RTMP_OS_NETDEV_OP_HOOK netDevHook, *pNetDevOps; + PNET_DEV new_dev_p; + UINT32 MC_RowID = 0, IoctlIF = 0, Inf = INT_P2P; + UINT preIfIndex = 0; + struct wireless_dev *pWdev; + + DBGPRINT(RT_DEBUG_TRACE, (" %s =====> \n", __FUNCTION__)); + if (cfg80211_ctrl->flg_cfg_dummy_p2p_init != FALSE) + return; + +#if RT_CFG80211_P2P_SUPPORT + cfg80211_ctrl->bP2pCliPmEnable = FALSE; + cfg80211_ctrl->bPreKeepSlient = FALSE; + cfg80211_ctrl->bKeepSlient = FALSE; + cfg80211_ctrl->NoAIndex = MAX_LEN_OF_MAC_TABLE; + cfg80211_ctrl->MyGOwcid = MAX_LEN_OF_MAC_TABLE; + cfg80211_ctrl->CTWindows=0; /* CTWindows and OppPS parameter field */ +#endif /* RT_CFG80211_P2P_SUPPORT */ + + pNetDevOps=&netDevHook; + + /* init operation functions and flags */ + NdisZeroMemory(&netDevHook, sizeof(netDevHook)); + netDevHook.open = CFG80211_DummyP2pIf_Open; /* device opem hook point */ + netDevHook.stop = CFG80211_DummyP2pIf_Close; /* device close hook point */ + netDevHook.xmit = CFG80211_DummyP2pIf_PacketSend; /* hard transmit hook point */ + netDevHook.ioctl = CFG80211_DummyP2pIf_Ioctl; /* ioctl hook point */ + + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, Inf, preIfIndex, sizeof(PRTMP_ADAPTER), INF_CFG80211_DUMMY_P2P_NAME); + + if (new_dev_p == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (CFG80211: Dummy P2P IF)...\n")); + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Register CFG80211 I/F (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(new_dev_p))); + } + + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + NdisMoveMemory(&pNetDevOps->devAddr[0], &pAd->CurrentAddress[0], MAC_ADDR_LEN); + pNetDevOps->needProtcted = TRUE; + + pWdev = kzalloc(sizeof(*pWdev), GFP_KERNEL); + if (unlikely(!pWdev)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Could not allocate wireless device\n")); + return; + } + + new_dev_p->ieee80211_ptr = pWdev; + pWdev->wiphy = p80211CB->pCfg80211_Wdev->wiphy; + SET_NETDEV_DEV(new_dev_p, wiphy_dev(pWdev->wiphy)); + pWdev->netdev = new_dev_p; + //pWdev->iftype = RT_CMD_80211_IFTYPE_STATION; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + pWdev->iftype = RT_CMD_80211_IFTYPE_P2P_DEVICE; +#else + pWdev->iftype = RT_CMD_80211_IFTYPE_P2P_CLIENT; +#endif /* LINUX_VERSION_CODE: 3.7.0 */ + /* interface_modes move from IF open to init */ + + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + cfg80211_ctrl->dummy_p2p_net_dev = new_dev_p; + cfg80211_ctrl->flg_cfg_dummy_p2p_init = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, (" %s <=====\n", __FUNCTION__)); +} +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_p2p.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_p2p.c new file mode 100644 index 000000000..e37238fcc --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_p2p.c @@ -0,0 +1,1271 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 P2P function body. + + History: + +***************************************************************************/ + +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + +UCHAR CFG_WPS_OUI[4] = {0x00, 0x50, 0xf2, 0x04}; +UCHAR CFG_P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9}; /* spec. 1.14 OUI */ + +BUILD_TIMER_FUNCTION(CFG80211RemainOnChannelTimeout); + +static +VOID CFG80211_RemainOnChannelInit(RTMP_ADAPTER *pAd) +{ + if (pAd->cfg80211_ctrl.Cfg80211RocTimerInit == FALSE) + { + CFG80211DBG(RT_DEBUG_TRACE, ("CFG80211_ROC : INIT Cfg80211RocTimer\n")); + RTMPInitTimer(pAd, &pAd->cfg80211_ctrl.Cfg80211RocTimer, + GET_TIMER_FUNCTION(CFG80211RemainOnChannelTimeout), pAd, FALSE); + pAd->cfg80211_ctrl.Cfg80211RocTimerInit = TRUE; + } +} + +VOID CFG80211RemainOnChannelTimeout( + PVOID SystemSpecific1, PVOID FunctionContext, + PVOID SystemSpecific2, PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + + DBGPRINT(RT_DEBUG_INFO, ("CFG80211_ROC: RemainOnChannelTimeout\n")); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +#define RESTORE_COM_CH_TIME 100 + APCLI_STRUCT *pApCliEntry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + + if (pApCliEntry->Valid && + RTMP_CFG80211_VIF_P2P_CLI_ON(pAd) && + (pAd->LatchRfRegs.Channel != pApCliEntry->MlmeAux.Channel)) + { + /* Extend the ROC_TIME for Common Channel When P2P_CLI on */ + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_ROC: ROC_Timeout APCLI_ON Channel: %d\n", + pApCliEntry->MlmeAux.Channel)); + + AsicSwitchChannel(pAd, pApCliEntry->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pApCliEntry->MlmeAux.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: P2P_CLI PWR_ACTIVE ROC_END\n")); + CFG80211_P2pClientSendNullFrame(pAd, PWR_ACTIVE); +#ifdef CONFIG_STA_SUPPORT + if (INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: CONCURRENT STA PWR_ACTIVE ROC_END\n")); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + } +#endif /*CONFIG_STA_SUPPORT*/ + RTMPSetTimer(&pCfg80211_ctrl->Cfg80211RocTimer, RESTORE_COM_CH_TIME); + } + else if (INFRA_ON(pAd) && + (pAd->LatchRfRegs.Channel != pAd->CommonCfg.Channel)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_ROC: ROC_Timeout INFRA_ON Channel: %d\n", + pAd->CommonCfg.Channel)); + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: INFRA_ON PWR_ACTIVE ROC_END\n")); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); +#endif /*CONFIG_STA_SUPPORT*/ + RTMPSetTimer(&pCfg80211_ctrl->Cfg80211RocTimer, RESTORE_COM_CH_TIME); + } + else +#endif /*RT_CFG80211_P2P_CONCURRENT_DEVICE */ + { +/* CFG TODO: move to cfg802_util */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + PWIRELESS_DEV pwdev = NULL; + pwdev = pCfg80211_ctrl->Cfg80211ChanInfo.pWdev; + cfg80211_remain_on_channel_expired(pwdev, pCfg80211_ctrl->Cfg80211ChanInfo.cookie, + pCfg80211_ctrl->Cfg80211ChanInfo.chan, GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + cfg80211_remain_on_channel_expired( CFG80211_GetEventDevice(pAd), + pCfg80211_ctrl->Cfg80211ChanInfo.cookie, pCfg80211_ctrl->Cfg80211ChanInfo.chan, + pCfg80211_ctrl->Cfg80211ChanInfo.ChanType, GFP_ATOMIC); +#endif /* LINUX_VERSION_CODE 2.6.34 */ +#endif /* LINUX_VERSION_CODE 3.8.0 */ + + pCfg80211_ctrl->Cfg80211RocTimerRunning = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_ROC: RemainOnChannelTimeout -- FINISH\n")); + } +} + +/* Set a given time on specific channel to listen action Frame */ +BOOLEAN CFG80211DRV_OpsRemainOnChannel(VOID *pAdOrg, VOID *pData, UINT32 duration) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_CHAN *pChanInfo; + BOOLEAN Cancelled; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + UCHAR lock_channel; + + pChanInfo = (CMD_RTPRIV_IOCTL_80211_CHAN *) pData; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + PWIRELESS_DEV pwdev = NULL; + pwdev = pChanInfo->pWdev; +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + CFG80211DBG(RT_DEBUG_INFO, ("%s\n", __FUNCTION__)); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + APCLI_STRUCT *pApCliEntry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + /* Will be Exit the ApCli Connected Channel so send Null frame on current */ + if (pApCliEntry->Valid && + RTMP_CFG80211_VIF_P2P_CLI_ON(pAd) && + (pApCliEntry->MlmeAux.Channel != pChanInfo->ChanId) && + (pApCliEntry->MlmeAux.Channel == pAd->LatchRfRegs.Channel)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: APCLI PWR_SAVE ROC_START\n")); + CFG80211_P2pClientSendNullFrame(pAd, PWR_SAVE); + } + + if (INFRA_ON(pAd) && + (pAd->CommonCfg.Channel != pChanInfo->ChanId) && + (pAd->CommonCfg.Channel == pAd->LatchRfRegs.Channel)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: STA PWR_SAVE ROC_START\n")); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + PWR_SAVE); + } +#endif /*RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* Channel Switch Case: + * 1. P2P_FIND: [SOCIAL_CH]->[COM_CH]->[ROC_CH]--N_TUs->[ROC_TIMEOUT] + * Set COM_CH to ROC_CH for merge COM_CH & ROC_CH dwell section. + * + * 2. OFF_CH_WAIT: [ROC_CH]--200ms-->[ROC_TIMEOUT]->[COM_CH] + * Most in GO case. + * + */ + //lock_channel = CFG80211_getCenCh(pAd, pChanInfo->ChanId); + lock_channel = pChanInfo->ChanId; + if (pAd->LatchRfRegs.Channel != lock_channel +#ifdef CONFIG_STA_SUPPORT + || (INFRA_ON(pAd) && (pAd->CommonCfg.BBPCurrentBW == BW_40)) +#endif /* CONFIG_STA_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_PKT: ROC CHANNEL_LOCK %d\n", pChanInfo->ChanId)); + //AsicSetChannel(pAd, lock_channel, BW_20, EXTCHA_NONE, FALSE); + bbp_set_bw(pAd, BW_20); + AsicSwitchChannel(pAd, lock_channel, FALSE); + AsicLockChannel(pAd, lock_channel); + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("80211> ComCH == ROC_CH \n")); + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + cfg80211_ready_on_channel(pwdev, pChanInfo->cookie, pChanInfo->chan, duration, GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + cfg80211_ready_on_channel(CFG80211_GetEventDevice(pAd), pChanInfo->cookie, + pChanInfo->chan, pChanInfo->ChanType, duration, GFP_ATOMIC); +#endif /* LINUX_VERSION_CODE: 2.6.34 */ +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + + NdisCopyMemory(&pCfg80211_ctrl->Cfg80211ChanInfo, pChanInfo, sizeof(CMD_RTPRIV_IOCTL_80211_CHAN)); + + CFG80211_RemainOnChannelInit(pAd); + + if (pCfg80211_ctrl->Cfg80211RocTimerRunning == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_ROC : CANCEL Cfg80211RocTimer\n")); + RTMPCancelTimer(&pCfg80211_ctrl->Cfg80211RocTimer, &Cancelled); + pCfg80211_ctrl->Cfg80211RocTimerRunning = FALSE; + } + + RTMPSetTimer(&pCfg80211_ctrl->Cfg80211RocTimer, duration + 20); + pCfg80211_ctrl->Cfg80211RocTimerRunning = TRUE; + + return TRUE; +} + +BOOLEAN CFG80211DRV_OpsCancelRemainOnChannel(VOID *pAdOrg, UINT32 cookie) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + BOOLEAN Cancelled; + CFG80211DBG(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (pAd->cfg80211_ctrl.Cfg80211RocTimerRunning == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG_ROC : CANCEL Cfg80211RocTimer\n")); + RTMPCancelTimer(&pAd->cfg80211_ctrl.Cfg80211RocTimer, &Cancelled); + pAd->cfg80211_ctrl.Cfg80211RocTimerRunning = FALSE; + } +} + +INT CFG80211_setPowerMgmt(VOID *pAdCB, UINT Enable) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + DBGPRINT(RT_DEBUG_TRACE, ("@@@ %s: %d\n", __FUNCTION__, Enable)); + +#ifdef RT_CFG80211_P2P_SUPPORT + pAd->cfg80211_ctrl.bP2pCliPmEnable = Enable; +#endif /* RT_CFG80211_P2P_SUPPORT */ + + return 0; +} + +#ifdef RT_CFG80211_P2P_SUPPORT +/* + ========================================================================== + Description: + Make a P2P Fake NoA Attribute to trigger myself to restart NoA. + The Start time is changed. Duration and Interval and Count is + the same as GO's beacon + + Parameters: + StartTime : A new Start time. + pOutBuffer : pointer to buffer that should put data to. + Note: + + ========================================================================== + */ +VOID CFG80211_P2PMakeFakeNoATlv(PRTMP_ADAPTER pAd, ULONG StartTime, PUCHAR pOutBuffer) +{ + PUCHAR pDest; + PP2PCLIENT_NOA_SCHEDULE pNoa = &pAd->cfg80211_ctrl.GONoASchedule; + pDest = pOutBuffer; + + *(pDest) = SUBID_P2P_NOA; + /* Length is 13*n + 2 = 15 when n = 1 */ + *(pDest+1) = 15; + /* Lenght 2nd byte */ + *(pDest+2) = 0; + /* Index. */ + *(pDest+3) = pNoa->Token; + /* CT Windows and OppPS parm. Don't turn on both. So Set CTWindows = 0 */ + *(pDest+4) = 0; + /* Count. Test Plan set to 255. */ + *(pDest+5) = pNoa->Count; + /* Duration */ + RTMPMoveMemory((pDest+6), pNoa->Duration, 4); + /* Interval */ + RTMPMoveMemory((pDest+10), pNoa->Interval, 4); + RTMPMoveMemory((pDest+14), &StartTime, 4); +} + + +BOOLEAN CFG80211_P2pAdjustSwNoATimer(PRTMP_ADAPTER pAd, ULONG CurrentTimeStamp, ULONG NextTimePoint) +{ + PCFG80211_CTRL pP2PCtrl = &pAd->cfg80211_ctrl; + ULONG AwakeDuration, NewStartTime; + UCHAR FakeNoAAttribute[32]; + + RTMPZeroMemory(FakeNoAAttribute, 32); + AwakeDuration = pP2PCtrl->GONoASchedule.Interval - pP2PCtrl->GONoASchedule.Duration; + if (CurrentTimeStamp < pP2PCtrl->GONoASchedule.CurrentTargetTimePoint) + { + /* If offset is more than 1/4 of duration. */ + if ((pP2PCtrl->GONoASchedule.OngoingAwakeTime) >= (AwakeDuration>> 2)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2pAdjustSwNoATimer HERE HERE!!!! \n")); + DBGPRINT(RT_DEBUG_TRACE,("OngoingAwakeTime = %ld. CurrentTimeStamp = %ld.!!!! \n", + pP2PCtrl->GONoASchedule.OngoingAwakeTime, CurrentTimeStamp)); + + CFG80211_P2pStopNoA(pAd, &pAd->MacTab.Content[pP2PCtrl->MyGOwcid]); + FakeNoAAttribute[0] = SUBID_P2P_NOA; + NewStartTime = pP2PCtrl->GONoASchedule.StartTime + + (pP2PCtrl->GONoASchedule.SwTimerTickCounter - 1) * (pP2PCtrl->GONoASchedule.Interval); + + CFG80211_P2PMakeFakeNoATlv(pAd, NewStartTime, &FakeNoAAttribute[0]); + + pAd->MacTab.Content[pP2PCtrl->MyGOwcid].CFGP2pInfo.NoADesc[0].Token--; + + CFG80211_P2pHandleNoAAttri(pAd, &pAd->MacTab.Content[pP2PCtrl->MyGOwcid], &FakeNoAAttribute[0]); + } + + /* Update expected next Current Target Time Point with NextTimePoint */ + pP2PCtrl->GONoASchedule.CurrentTargetTimePoint = NextTimePoint; + /* Can immediately dequeue packet because peer already in awake period. */ + return TRUE; + } + else + { + /* Update expected next Current Target Time Point with NextTimePoint */ + pP2PCtrl->GONoASchedule.CurrentTargetTimePoint = NextTimePoint; + return FALSE; + } +} + +VOID CFG80211_P2pGPTimeOutHandle(PRTMP_ADAPTER pAd) +{ + PCFG80211_CTRL pP2PCtrl = &pAd->cfg80211_ctrl; + MAC_TABLE_ENTRY *pEntry=NULL; + ULONG MacValue, Value, GPDiff, NextDiff, SavedNextTargetTimePoint; + + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &= 0xfffffffd; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + + /* GO operating or Autonomous GO */ + if (CFG_P2PGO_ON(pAd)) + { + /* Not Yet Ready */ + } + else if (CFG_P2PCLI_ON(pAd)) + { + if (pP2PCtrl->NoAIndex >= MAX_LEN_OF_MAC_TABLE) + return; + + if (pP2PCtrl->NoAIndex != pP2PCtrl->MyGOwcid) + DBGPRINT(RT_DEBUG_TRACE,("%s: !bug, please check driver %d. \n", + __FUNCTION__, pP2PCtrl->NoAIndex)); + + pEntry = &pAd->MacTab.Content[pP2PCtrl->NoAIndex]; + if (pEntry && pEntry->CFGP2pInfo.NoADesc[0].bValid == TRUE) + { + if ((pEntry->CFGP2pInfo.NoADesc[0].Count > 0) && (pEntry->CFGP2pInfo.NoADesc[0].Count < 255)) + { + /* + Sometimes go to awake, sometime go to silence. Two state counts One count down. + so only minus Count when I change from Sleep to Awake + */ + if (pEntry->CFGP2pInfo.NoADesc[0].bInAwake == FALSE) + pEntry->CFGP2pInfo.NoADesc[0].Count--; + } + + if (pEntry->CFGP2pInfo.NoADesc[0].Count == 0) + { + CFG80211_P2pStopNoA(pAd, pEntry); + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS %s: Count down to zero!!StopGP. return.1 \n", __FUNCTION__)); + return; + } + + /* To enter absence period, stop transmission a little bit earlier to leave HW to clean the queue. */ + if (pEntry->CFGP2pInfo.NoADesc[0].bInAwake == FALSE) + NextDiff = pEntry->CFGP2pInfo.NoADesc[0].Duration - 0x200; + else + NextDiff = pEntry->CFGP2pInfo.NoADesc[0].Interval - pEntry->CFGP2pInfo.NoADesc[0].Duration + 0x200; + + /* Prepare next time. */ + + + /*RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &MacValue); */ + MacValue = pAd->cfg80211_ctrl.GONoASchedule.LastBeaconTimeStamp; + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS 2 Tsf Timer = %ld, NextTargetTimePoint = %ld.\n", + MacValue, pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint)); + + SavedNextTargetTimePoint = pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint; + if (MacValue <= pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint) + { + GPDiff = pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint - MacValue; + + pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint += NextDiff; + CFG80211_P2pResetNoATimer(pAd, GPDiff); + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS 3 Continue next NOA NextTargetTimePoint = %ld. \n", + pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint)); + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS 3 Value = %ld. NextDiff = %ld.\n", MacValue, NextDiff)); + } + else + { + CFG80211_P2pStopNoA(pAd, pEntry); + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS 4 NOA NextTargetTimePoint = %ld. \n", + pEntry->CFGP2pInfo.NoADesc[0].NextTargetTimePoint)); + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS 4 Value = %ld = 0x%lx. NextDiff = %ld.\n", MacValue, MacValue, NextDiff)); + return; + } + + if (pEntry->CFGP2pInfo.NoADesc[0].bInAwake == TRUE) + { + pEntry->CFGP2pInfo.NoADesc[0].bInAwake = FALSE; + pP2PCtrl->bKeepSlient = TRUE; + pP2PCtrl->bPreKeepSlient = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS Enter Absence now ======> %d\n", pP2PCtrl->bKeepSlient)); + } + else + { + pEntry->CFGP2pInfo.NoADesc[0].bInAwake = TRUE; + pP2PCtrl->bKeepSlient = FALSE; + pP2PCtrl->bPreKeepSlient = FALSE; + if (IS_SW_NOA_TIMER(pAd) && (pP2PCtrl->GONoASchedule.Count > 100)) + { + if (TRUE == CFG80211_P2pAdjustSwNoATimer(pAd, Value, SavedNextTargetTimePoint)) + { + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + } + else + { + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS Enter Awake now ======= %d\n", pAd->cfg80211_ctrl.bKeepSlient)); + + } + + } + + } +} + +VOID CFG80211_P2PCTWindowTimer( + PVOID SystemSpecific1, PVOID FunctionContext, + PVOID SystemSpecific2, PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + PCFG80211_CTRL pP2pCtrl = &pAd->cfg80211_ctrl; + + if (CFG80211_P2P_TEST_BIT(pP2pCtrl->CTWindows, P2P_OPPS_BIT)) + pP2pCtrl->bKeepSlient = TRUE; +} + + +/* + ========================================================================== + Description: + When I am P2P Client , Handle NoA Attribute. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID CFG80211_P2pSwNoATimeOut( + PVOID SystemSpecific1, PVOID FunctionContext, + PVOID SystemSpecific2, PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + CFG80211_P2pGPTimeOutHandle(pAd); +} + +VOID CFG80211_P2pPreAbsenTimeOut( + PVOID SystemSpecific1, PVOID FunctionContext, + PVOID SystemSpecific2, PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + pAd->cfg80211_ctrl.bPreKeepSlient = TRUE; +} + + +BOOLEAN CFG80211_P2pResetNoATimer(PRTMP_ADAPTER pAd, ULONG DiffTimeInUs) +{ + ULONG GPDiff; + BOOLEAN brc = FALSE; + + /* + Software based timer means don't use GP interrupt to get precise timer calculation. + So need to check time offset caused by software timer. + */ + if (IS_SW_NOA_TIMER(pAd)) + { + GPDiff = (DiffTimeInUs>>10) & 0xffff; + printk("P2P_PS ==========> P2pResetNoATimer, %ld ==> %d\n", DiffTimeInUs, GPDiff); + if (GPDiff > 0) + { + GPDiff++; + RTMPSetTimer(&pAd->cfg80211_ctrl.P2pSwNoATimer, GPDiff); + + /* Increase timer tick counter. */ + pAd->cfg80211_ctrl.GONoASchedule.SwTimerTickCounter++; + + brc = TRUE; + /* Will go to awake later. Set a pre-enter-absence timer that the time out is smaller the GPDiff. */ + if (pAd->cfg80211_ctrl.GONoASchedule.bInAwake == FALSE) + { + if (GPDiff > 10) + { + printk("P2P_PS ==========> P2pPreAbsenTimer, %d\n", (GPDiff - 10)); + RTMPSetTimer(&pAd->cfg80211_ctrl.P2pPreAbsenTimer, (GPDiff - 10)); + } + } + } + } + return brc; + +} + + +VOID CFG80211_P2pGOStartNoA(PRTMP_ADAPTER pAd) +{ + +} + +VOID CFG80211_P2pStopNoA(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY pMacClient) +{ + ULONG Value; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS %s .!!!! \n",__FUNCTION__)); + + RTMPCancelTimer(&pAd->cfg80211_ctrl.P2pPreAbsenTimer, &Cancelled); + pAd->cfg80211_ctrl.bKeepSlient = FALSE; + pAd->cfg80211_ctrl.bPreKeepSlient = FALSE; + if (pMacClient != NULL) + { + pMacClient->CFGP2pInfo.NoADesc[0].Count = 0xf3; + pMacClient->CFGP2pInfo.NoADesc[0].bValid = FALSE; + pMacClient->CFGP2pInfo.NoADesc[0].bInAwake = TRUE; + /* + Try set Token to a value that has smallest chane the same as the Next Token GO will use. + So decrease 1 + */ + pMacClient->CFGP2pInfo.NoADesc[0].Token--; + } + RTMPCancelTimer(&pAd->cfg80211_ctrl.P2pSwNoATimer, &Cancelled); + pAd->cfg80211_ctrl.GONoASchedule.bValid = FALSE; + pAd->cfg80211_ctrl.GONoASchedule.bInAwake = TRUE; + + + /* If need not resume NoA. Can reset all parameters. */ + { + pAd->cfg80211_ctrl.GONoASchedule.Count = 1; + pAd->cfg80211_ctrl.GONoASchedule.Duration = 0xc800; + pAd->cfg80211_ctrl.GONoASchedule.Interval = 0x19000; + } + + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &= (0xfffffffd); + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + + pAd->cfg80211_ctrl.GONoASchedule.SwTimerTickCounter = 0; + + /* Set to false again. */ + pAd->cfg80211_ctrl.bPreKeepSlient = FALSE; + +} + +VOID CFG80211_P2pStartOpPS(PRTMP_ADAPTER pAd) +{ + if (pAd->cfg80211_ctrl.GONoASchedule.bValid == TRUE) + CFG80211_P2pStopNoA(pAd, NULL); + + DBGPRINT(RT_DEBUG_TRACE,("P2P : !! %s \n",__FUNCTION__)); + pAd->cfg80211_ctrl.CTWindows = 0x8a; + /* Wait next beacon period to really start queue packet. */ + pAd->cfg80211_ctrl.bKeepSlient = FALSE; + +} + +VOID CFG80211_P2pStopOpPS(PRTMP_ADAPTER pAd) +{ + if (pAd->cfg80211_ctrl.GONoASchedule.bValid == FALSE) + pAd->cfg80211_ctrl.bKeepSlient = FALSE; + pAd->cfg80211_ctrl.CTWindows = 0; +} + +static +ULONG CFG80211_P2pGetTimeStamp(PRTMP_ADAPTER pAd) +{ + ULONG Value = 0; + /* RTMP_IO_FORCE_READ32(pAd, TSF_TIMER_DW0, &Value); */ + Value = pAd->cfg80211_ctrl.GONoASchedule.LastBeaconTimeStamp; + + return Value; +} + +BOOLEAN CFG80211_P2pHandleNoAAttri(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY pMacClient, PUCHAR pData) +{ + PP2P_NOA_DESC pNoADesc; + ULONG Value, GPDiff, NoALen, StartTime; + UCHAR index; + + if (pMacClient == NULL) + return FALSE; + + if (*pData == SUBID_P2P_NOA) + { + NoALen = *(pData+1); + if (NoALen == 2) + { + pMacClient->CFGP2pInfo.CTWindow = *(pData+4); + if (pMacClient->CFGP2pInfo.NoADesc[0].bValid == TRUE) + CFG80211_P2pStopNoA(pAd, pMacClient); + /* + Copy my GO's CTWindow to P2Pcfg.CTWindow parameters, + Then As Client, I don't need to search for Client when I want to use CTWindow Value. + */ + pAd->cfg80211_ctrl.CTWindows = *(pData+4); + return TRUE; + } + + index = *(pData+3); + + pMacClient->CFGP2pInfo.CTWindow = *(pData+4); + pAd->cfg80211_ctrl.CTWindows = *(pData+4); + + pNoADesc = (PP2P_NOA_DESC)(pData+5); + pMacClient->CFGP2pInfo.NoADesc[0].Count = pNoADesc->Count; + pMacClient->CFGP2pInfo.NoADesc[0].Duration = *(PUINT32)&pNoADesc->Duration[0]; + pMacClient->CFGP2pInfo.NoADesc[0].Interval = *(PUINT32)&pNoADesc->Interval[0]; + pMacClient->CFGP2pInfo.NoADesc[0].StartTime = *(PUINT32)&pNoADesc->StartTime[0]; + StartTime = *(PUINT32)&pNoADesc->StartTime[0]; + + if (pMacClient->CFGP2pInfo.NoADesc[0].Token == index) + { + /* The same NoA. Doesn't need to set this NoA again. */ + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS : !!!NEW NOA Here =[%d, %d] Count = %d. Duration = %ld \n", + pMacClient->CFGP2pInfo.NoADesc[0].Token, index, pNoADesc->Count, + pMacClient->CFGP2pInfo.NoADesc[0].Duration)); + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS : CTWindow = %x \n", pMacClient->CFGP2pInfo.CTWindow)); + + pMacClient->CFGP2pInfo.NoADesc[0].Token = index; + + + /* RTMP_IO_FORCE_READ32(pAd, TSF_TIMER_DW0, &Value); */ + Value = pAd->cfg80211_ctrl.GONoASchedule.LastBeaconTimeStamp; + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS Interval = %ld. StartTime = %ld. TSF timer = %ld\n", + pMacClient->CFGP2pInfo.NoADesc[0].Interval, pMacClient->CFGP2pInfo.NoADesc[0].StartTime, Value)); + + if ((pMacClient->CFGP2pInfo.NoADesc[0].Duration <= 0x40) || (pMacClient->CFGP2pInfo.NoADesc[0].Interval <= 0x40)) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P_PS !!!!!Interval or Duration too small. ignore. = %lx return 1\n", Value)); + return FALSE; + } + else if ((pMacClient->CFGP2pInfo.NoADesc[0].Duration >= pMacClient->CFGP2pInfo.NoADesc[0].Interval) + && (pMacClient->CFGP2pInfo.NoADesc[0].Count > 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P_PS !!!!!Duration > Inveral. return 2\n")); + return FALSE; + } + + /* if Start time point is in the future. */ + pAd->cfg80211_ctrl.GONoASchedule.CurrentTargetTimePoint = pMacClient->CFGP2pInfo.NoADesc[0].StartTime; + if (Value < StartTime) + { + GPDiff = pMacClient->CFGP2pInfo.NoADesc[0].StartTime - Value; + pMacClient->CFGP2pInfo.NoADesc[0].NextTargetTimePoint = + pMacClient->CFGP2pInfo.NoADesc[0].StartTime + pMacClient->CFGP2pInfo.NoADesc[0].Duration; + pAd->cfg80211_ctrl.GONoASchedule.OngoingAwakeTime = + pMacClient->CFGP2pInfo.NoADesc[0].NextTargetTimePoint; + + + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS !!!!! GPDiff = %ld. NextTargetTimePoint = %ld\n", + GPDiff, pMacClient->CFGP2pInfo.NoADesc[0].NextTargetTimePoint)); + + /* try to set General Timer. */ + pAd->cfg80211_ctrl.GONoASchedule.LastBeaconTimeStamp += GPDiff; + if (CFG80211_P2pResetNoATimer(pAd, GPDiff)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS !!!!!Start NoA 1 GPDiff = %ld \n", GPDiff)); + pMacClient->CFGP2pInfo.NoADesc[0].bValid = TRUE; + pMacClient->CFGP2pInfo.NoADesc[0].bInAwake = TRUE; + pMacClient->CFGP2pInfo.NoADesc[0].Token = index; + return TRUE; + } + } + else if (Value >= StartTime) + { + /* Start time point is in the past. */ + do + { + StartTime += pMacClient->CFGP2pInfo.NoADesc[0].Interval; + if ((StartTime > Value) && ((StartTime-Value) > 0x80)) + { + GPDiff = StartTime - Value; + pMacClient->CFGP2pInfo.NoADesc[0].NextTargetTimePoint = StartTime + /* + pMacClient->P2pInfo.NoADesc[0].Interval */ + - pMacClient->CFGP2pInfo.NoADesc[0].Duration; + + pAd->cfg80211_ctrl.GONoASchedule.OngoingAwakeTime = + pMacClient->CFGP2pInfo.NoADesc[0].NextTargetTimePoint; + pAd->cfg80211_ctrl.GONoASchedule.LastBeaconTimeStamp += GPDiff; + + if (CFG80211_P2pResetNoATimer(pAd, GPDiff)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2P_PS !!!!!Start NoA 2 GPDiff = %ld\n", GPDiff)); + pMacClient->CFGP2pInfo.NoADesc[0].bValid = TRUE; + pMacClient->CFGP2pInfo.NoADesc[0].bInAwake = TRUE; + pMacClient->CFGP2pInfo.NoADesc[0].Token = index; + return TRUE; + } + } + + } while(TRUE); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Start time out of ctrl ..need Check \n")); + } + } + + return FALSE; +} + + +VOID CFG80211_P2pParseNoASubElmt(PRTMP_ADAPTER pAd, VOID *Msg, ULONG MsgLen, + UCHAR wcidindex, UINT32 Sequence) +{ + PCFG80211_CTRL pP2PCtrl = &pAd->cfg80211_ctrl; + ULONG Length = 0, AttriLen = 0, LeftLength = 0; + PP2PEID_STRUCT pP2pEid; + PEID_STRUCT pEid; + BOOLEAN brc = FALSE, bNoAAttriExist = FALSE; + PUCHAR pPtrEid = NULL; + + /* Intel sends multiple P2P IE... So I can't give each input a default value.. */ + if (MsgLen == 0) + return; + + LeftLength = MsgLen; + pEid = (PEID_STRUCT)Msg; + while ((ULONG)(pEid->Len + 2) <= LeftLength) + { + /* might contains P2P IE and WPS IE. So use if else if enough for locate P2P IE. */ + if (RTMPEqualMemory(&pEid->Octet[0], CFG_P2POUIBYTE, 4)) + { + /* Get Request content capability */ + pP2pEid = (PP2PEID_STRUCT) &pEid->Octet[4]; + pPtrEid = (PUCHAR) pP2pEid; + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + Length = 0; + + while ((Length + 3 + AttriLen) <= pEid->Len) + { + switch(pP2pEid->Eid) + { + case SUBID_P2P_NOA: + { + PUCHAR pData = &pEid->Octet[0]; + DBGPRINT(RT_DEBUG_TRACE, ("P2P_PS Get NoA Attr: %x %x %x %x %x %x %x %x %x \n", + *(pData+0), *(pData+1), *(pData+2), *(pData+3), + *(pData+4), *(pData+5), *(pData+6), *(pData+7), *(pData+8))); + + bNoAAttriExist = TRUE; + brc = CFG80211_P2pHandleNoAAttri(pAd, &pAd->MacTab.Content[wcidindex], pPtrEid); + + /* Got a NoA Attribute from this p2pindex. In fact, This should be GO. */ + if (brc == TRUE) + pP2PCtrl->NoAIndex = wcidindex; + } + break; + + default: + break; + + } + + Length = Length + 3 + AttriLen; /* Eid[1] + Len[1]+ content[Len] */ + pP2pEid = (PP2PEID_STRUCT)((UCHAR*)pP2pEid + 3 + AttriLen); + pPtrEid = (PUCHAR) pP2pEid; + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + } + } + LeftLength = LeftLength - pEid->Len - 2; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + if (bNoAAttriExist == FALSE) + { + if (CFG80211_P2P_TEST_BIT(pAd->cfg80211_ctrl.CTWindows, P2P_OPPS_BIT)) + { + DBGPRINT(RT_DEBUG_TRACE,("Beacon and no NoA Attribute! \n")); + CFG80211_P2pStopOpPS(pAd); + } + + if ((pAd->MacTab.Content[wcidindex].CFGP2pInfo.NoADesc[0].bValid == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE,("Beacon and no NoA Attribute!Stop active NoA [%d]\n", Sequence)); + CFG80211_P2pStopNoA(pAd, &pAd->MacTab.Content[wcidindex]); + } + } + else + printk("P2P_PS Debug: %s() %d ===> Get Entry\n", __FUNCTION__, __LINE__); + +} + + +BOOLEAN CFG8211_PeerP2pBeaconSanity( + PRTMP_ADAPTER pAd, VOID *Msg, ULONG MsgLen, + PUCHAR pAddr2, CHAR Ssid[], UCHAR *pSsidLen, + ULONG *Peerip, ULONG *P2PSubelementLen, + PUCHAR pP2pSubelement) +{ + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc = FALSE, bFirstP2pOUI = TRUE; + PUCHAR Ptr; + + pFrame = (PFRAME_802_11)Msg; + Length += LENGTH_802_11; + + *P2PSubelementLen = 0; + *pSsidLen = 0; + *Peerip = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + Ptr = pFrame->Octet; + + /* get timestamp from payload and advance the pointer */ + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer */ + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer */ + Ptr += 2; + Length += 2; + + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_SSID: + if(pEid->Len <= MAX_LEN_OF_SSID) + { + RTMPMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + } + break; + case IE_VENDOR_SPECIFIC: + /* Check the OUI version, filter out non-standard usage */ + if (NdisEqualMemory(pEid->Octet, CFG_WPS_OUI, 4) && (pEid->Len >= 4)) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, pEid->Len +2); + *P2PSubelementLen = pEid->Len +2; + } + else if (*P2PSubelementLen > 0) + { + if (((*P2PSubelementLen) + (pEid->Len+2)) <= MAX_VIE_LEN) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! 111 Sum of P2PSubelementLen= %lu, > MAX_VIE_LEN !!\n", __FUNCTION__, ((*P2PSubelementLen) + (pEid->Len+2)))); + return FALSE; + } + } + + } + else if (NdisEqualMemory(pEid->Octet, CFG_P2POUIBYTE, 4) && (pEid->Len >= 4)) + { + /* + If this is the first P2P OUI. Then also append P2P OUI. + Beacon 's P2P attribute doesn't exceed 256 bytes. So not use acumulcated form. + */ + if (bFirstP2pOUI == TRUE) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, pEid->Len +2); + *P2PSubelementLen = (pEid->Len +2); + brc = TRUE; + } + else if (*P2PSubelementLen > 0) + { + if (((*P2PSubelementLen) + (pEid->Len+2)) <= MAX_VIE_LEN) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + brc = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! 222 Sum of P2PSubelementLen= %lu, > MAX_VIE_LEN !!\n", __FUNCTION__, ((*P2PSubelementLen) + (pEid->Len+2)))); + return FALSE; + } + } + bFirstP2pOUI = FALSE; + } + else + { + /* + If this is not the first P2P OUI. Then don't append P2P OUI. + because our parse function doesn't need so many P2P OUI. + */ + if ((*P2PSubelementLen > 0) && (pEid->Len > 4)) + { + if (((*P2PSubelementLen) + (pEid->Len+2)) <= MAX_VIE_LEN) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + brc = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! 333 Sum of P2PSubelementLen= %lu, > MAX_VIE_LEN !!\n", __FUNCTION__, ((*P2PSubelementLen) + (pEid->Len+2)))); + return FALSE; + } + } + } + } + break; + } + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + + } + return brc; +} + + +VOID CFG80211_PeerP2pBeacon(PRTMP_ADAPTER pAd, + PUCHAR pAddr2, MLME_QUEUE_ELEM *Elem, LARGE_INTEGER TimeStamp) +{ + PCFG80211_CTRL pP2PCtrl = &pAd->cfg80211_ctrl; + + UCHAR Addr2[6], SsidLen, Ssid[32]; + ULONG PeerIp, P2PSubelementLen; + PUCHAR P2pSubelement = NULL; + PFRAME_802_11 pFrame; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + pFrame = (PFRAME_802_11)Elem->Msg; + /* Only check beacon . */ + if (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_RSP) + return; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; + + /* Init P2pSubelement */ + if (P2pSubelement) + { + os_free_mem(NULL, P2pSubelement); + P2pSubelement = NULL; + } + + os_alloc_mem(pAd, &P2pSubelement, MAX_VIE_LEN); + if (P2pSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN)); + goto CleanUp; + } + + if (CFG8211_PeerP2pBeaconSanity(pAd, Elem->Msg, Elem->MsgLen, + Addr2, Ssid, &SsidLen, &PeerIp, + &P2PSubelementLen,P2pSubelement)) + { + /* Parse the power managemenr parameters in here. */ + pP2PCtrl->GONoASchedule.LastBeaconTimeStamp = TimeStamp.u.LowPart; + CFG80211_P2pParseNoASubElmt(pAd, P2pSubelement, P2PSubelementLen, Elem->Wcid, pFrame->Hdr.Sequence); + + /* Since we get beacon, check if GO enable and OppPS. */ + if (CFG80211_P2P_TEST_BIT(pAd->cfg80211_ctrl.CTWindows, P2P_OPPS_BIT)) + { + pAd->cfg80211_ctrl.bKeepSlient = FALSE; + /* TO DO : sync with windows if necessary */ + /*RTMPDeQueueNoAMgmtPacket(pAd);*/ + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + if (((pAd->cfg80211_ctrl.CTWindows&0x7f) > 0) && ((pAd->cfg80211_ctrl.CTWindows&0x7f) < 80)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s:: set P2P CTWindows timer.\n", __FUNCTION__)); + RTMPSetTimer(&pAd->cfg80211_ctrl.P2pCTWindowTimer, (pAd->cfg80211_ctrl.CTWindows&0x7f)); + } + } + } + +CleanUp: + if (P2pSubelement) + { + os_free_mem(NULL, P2pSubelement); + P2pSubelement = NULL; + } + +} + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +VOID CFG80211_P2pClientSendNullFrame(VOID *pAdCB, INT PwrMgmt) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + MAC_TABLE_ENTRY *pEntry; + + pEntry = MacTableLookup(pAd, pAd->ApCfg.ApCliTab[MAIN_MBSSID].MlmeAux.Bssid); + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_ROC: Can't Find In Table: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->ApCfg.ApCliTab[MAIN_MBSSID].MlmeAux.Bssid))); + } + else + { + ApCliRTMPSendNullFrame(pAd, + RATE_6, + (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) ? TRUE:FALSE, + pEntry, PwrMgmt); + OS_WAIT(20); + } +} + +VOID CFG80211DRV_P2pClientKeyAdd(VOID *pAdOrg, VOID *pData) +{ + + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_KEY *pKeyInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("CFG Debug: CFG80211DRV_P2pClientKeyAdd\n")); + pKeyInfo = (CMD_RTPRIV_IOCTL_80211_KEY *)pData; + + if (pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP40 || pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP104) + ; + else + { + INT BssIdx; + PAPCLI_STRUCT pApCliEntry; + MAC_TABLE_ENTRY *pMacEntry=(MAC_TABLE_ENTRY *)NULL; + + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + MAIN_MBSSID; + pApCliEntry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + if (pKeyInfo->bPairwise == FALSE ) +#else + if (pKeyInfo->KeyId > 0) +#endif + { + + if (pApCliEntry->wdev.WepStatus == Ndis802_11Encryption3Enabled) + { + printk("APCLI: Set AES Security Set. [%d] (GROUP) %d\n", BssIdx, pKeyInfo->KeyLen); + NdisZeroMemory(&pApCliEntry->SharedKey[pKeyInfo->KeyId], sizeof(CIPHER_KEY)); + pApCliEntry->SharedKey[pKeyInfo->KeyId].KeyLen = LEN_TK; + NdisMoveMemory(pApCliEntry->SharedKey[pKeyInfo->KeyId].Key, pKeyInfo->KeyBuf, pKeyInfo->KeyLen); + + pApCliEntry->SharedKey[pKeyInfo->KeyId].CipherAlg = CIPHER_AES; + + AsicAddSharedKeyEntry(pAd, BssIdx, pKeyInfo->KeyId, + &pApCliEntry->SharedKey[pKeyInfo->KeyId]); + + RTMPAddWcidAttributeEntry(pAd, BssIdx, pKeyInfo->KeyId, + pApCliEntry->SharedKey[pKeyInfo->KeyId].CipherAlg, + NULL); + + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + { + /* set 802.1x port control */ + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + } + } + else + { + if(pMacEntry) + { + printk("APCLI: Set AES Security Set. [%d] (PAIRWISE) %d\n", BssIdx, pKeyInfo->KeyLen); + NdisZeroMemory(&pMacEntry->PairwiseKey, sizeof(CIPHER_KEY)); + pMacEntry->PairwiseKey.KeyLen = LEN_TK; + + NdisCopyMemory(&pMacEntry->PTK[OFFSET_OF_PTK_TK], pKeyInfo->KeyBuf, OFFSET_OF_PTK_TK); + NdisMoveMemory(pMacEntry->PairwiseKey.Key, &pMacEntry->PTK[OFFSET_OF_PTK_TK], pKeyInfo->KeyLen); + + pMacEntry->PairwiseKey.CipherAlg = CIPHER_AES; + + AsicAddPairwiseKeyEntry(pAd, (UCHAR)pMacEntry->Aid, &pMacEntry->PairwiseKey); + RTMPSetWcidSecurityInfo(pAd, BssIdx, 0, pMacEntry->PairwiseKey.CipherAlg, pMacEntry->Aid, PAIRWISEKEYTABLE); + } + else + { + printk("APCLI: Set AES Security Set. (PAIRWISE) But pMacEntry NULL\n"); + } + } + } +} + +VOID CFG80211DRV_SetP2pCliAssocIe(VOID *pAdOrg, VOID *pData, UINT ie_len) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + APCLI_STRUCT *apcli_entry; + hex_dump("P2PCLI=", pData, ie_len); + + apcli_entry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + + if (ie_len > 0) + { + if (apcli_entry->wpa_supplicant_info.pWpaAssocIe) + { + os_free_mem(NULL, apcli_entry->wpa_supplicant_info.pWpaAssocIe); + apcli_entry->wpa_supplicant_info.pWpaAssocIe = NULL; + } + + os_alloc_mem(NULL, (UCHAR **)&apcli_entry->wpa_supplicant_info.pWpaAssocIe, ie_len); + if (apcli_entry->wpa_supplicant_info.pWpaAssocIe) + { + apcli_entry->wpa_supplicant_info.WpaAssocIeLen = ie_len; + NdisMoveMemory(apcli_entry->wpa_supplicant_info.pWpaAssocIe, pData, apcli_entry->wpa_supplicant_info.WpaAssocIeLen); + } + else + apcli_entry->wpa_supplicant_info.WpaAssocIeLen = 0; + } + else + { + if (apcli_entry->wpa_supplicant_info.pWpaAssocIe) + { + os_free_mem(NULL, apcli_entry->wpa_supplicant_info.pWpaAssocIe); + apcli_entry->wpa_supplicant_info.pWpaAssocIe = NULL; + } + apcli_entry->wpa_supplicant_info.WpaAssocIeLen = 0; + } +} + +/* For P2P_CLIENT Connection Setting in AP_CLI SM */ +BOOLEAN CFG80211DRV_P2pClientConnect(VOID *pAdOrg, VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_CONNECT *pConnInfo; + UCHAR Connect_SSID[NDIS_802_11_LENGTH_SSID]; + UINT32 Connect_SSIDLen; + + APCLI_STRUCT *apcli_entry; + apcli_entry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj->ioctl_if_type = INT_APCLI; + + pConnInfo = (CMD_RTPRIV_IOCTL_80211_CONNECT *)pData; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI Connection onGoing.....\n")); + + Connect_SSIDLen = pConnInfo->SsidLen; + if (Connect_SSIDLen > NDIS_802_11_LENGTH_SSID) + Connect_SSIDLen = NDIS_802_11_LENGTH_SSID; + + memset(&Connect_SSID, 0, sizeof(Connect_SSID)); + memcpy(Connect_SSID, pConnInfo->pSsid, Connect_SSIDLen); + + apcli_entry->wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + + /* Check the connection is WPS or not */ + if (pConnInfo->bWpsConnection) + { + DBGPRINT(RT_DEBUG_TRACE, ("AP_CLI WPS Connection onGoing.....\n")); + apcli_entry->wpa_supplicant_info.WpaSupplicantUP |= WPA_SUPPLICANT_ENABLE_WPS; + } + + /* Set authentication mode */ + if (pConnInfo->WpaVer == 2) + { + if (!pConnInfo->FlgIs8021x == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE,("APCLI WPA2PSK\n")); + Set_ApCli_AuthMode_Proc(pAd, "WPA2PSK"); + } + } + else if (pConnInfo->WpaVer == 1) + { + if (!pConnInfo->FlgIs8021x) + { + DBGPRINT(RT_DEBUG_TRACE,("APCLI WPAPSK\n")); + Set_ApCli_AuthMode_Proc(pAd, "WPAPSK"); + } + } + else + Set_ApCli_AuthMode_Proc(pAd, "OPEN"); + + /* Set PTK Encryption Mode */ + if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) { + DBGPRINT(RT_DEBUG_TRACE,("AES\n")); + Set_ApCli_EncrypType_Proc(pAd, "AES"); + } + else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) { + DBGPRINT(RT_DEBUG_TRACE,("TKIP\n")); + Set_ApCli_EncrypType_Proc(pAd, "TKIP"); + } + else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_WEP) + { + DBGPRINT(RT_DEBUG_TRACE,("WEP\n")); + Set_ApCli_EncrypType_Proc(pAd, "WEP"); + } + + + if (pConnInfo->pBssid != NULL) + { + NdisZeroMemory(apcli_entry->CfgApCliBssid, MAC_ADDR_LEN); + NdisCopyMemory(apcli_entry->CfgApCliBssid, pConnInfo->pBssid, MAC_ADDR_LEN); + } + + OPSTATUS_SET_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + pAd->cfg80211_ctrl.FlgCfg80211Connecting = TRUE; + Set_ApCli_Ssid_Proc(pAd, (PSTRING)Connect_SSID); + Set_ApCli_Enable_Proc(pAd, "1"); + CFG80211DBG(RT_DEBUG_OFF, ("80211> APCLI CONNECTING SSID = %s\n", Connect_SSID)); + + return TRUE; +} + +VOID CFG80211_P2pClientConnectResultInform( + VOID *pAdCB, UCHAR *pBSSID, + UCHAR *pReqIe, UINT32 ReqIeLen, + UCHAR *pRspIe, UINT32 RspIeLen, + UCHAR FlgIsSuccess) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + CFG80211OS_P2pClientConnectResultInform(pAd->ApCfg.ApCliTab[MAIN_MBSSID].wdev.if_dev, pBSSID, + pReqIe, ReqIeLen, pRspIe, RspIeLen, FlgIsSuccess); + + pAd->cfg80211_ctrl.FlgCfg80211Connecting = FALSE; +} + +VOID CFG80211_LostP2pGoInform(VOID *pAdCB) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_CB *p80211CB = pAd->pCfg80211_CB; + PNET_DEV pNetDev = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("80211> CFG80211_LostGoInform ==> \n")); + + pAd->cfg80211_ctrl.FlgCfg80211Connecting = FALSE; + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_CLIENT)) != NULL)) + { + if (pNetDev->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) + { + cfg80211_connect_result(pNetDev, NULL, NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); + } + else if (pNetDev->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTED) + { + cfg80211_disconnected(pNetDev, 0, NULL, 0, GFP_KERNEL); + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("80211> BUG CFG80211_LostGoInform, BUT NetDevice not exist.\n")); + + Set_ApCli_Enable_Proc(pAd, "0"); +} +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* RT_CFG80211_P2P_SUPPORT */ +#endif /* RT_CFG80211_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_rx.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_rx.c new file mode 100644 index 000000000..999220d37 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_rx.c @@ -0,0 +1,260 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2013, 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + +extern UCHAR CFG_P2POUIBYTE[]; + +VOID CFG80211_Convert802_3Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR *pHeader802_3) +{ +#ifdef CONFIG_AP_SUPPORT + if (IS_PKT_OPMODE_AP(pRxBlk)) + { + RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, pHeader802_3); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { +#ifdef CONFIG_STA_SUPPORT + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, pHeader802_3); +#endif /*CONFIG_STA_SUPPORT*/ + } +} + +VOID CFG80211_Announce802_3Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR FromWhichBSSID) +{ +#ifdef CONFIG_AP_SUPPORT + if (IS_PKT_OPMODE_AP(pRxBlk)) + { + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { +#ifdef CONFIG_STA_SUPPORT + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); +#endif /*CONFIG_STA_SUPPORT*/ + } + +} + +BOOLEAN CFG80211_CheckActionFrameType( + IN RTMP_ADAPTER *pAd, + IN PUCHAR preStr, + IN PUCHAR pData, + IN UINT32 length) +{ + BOOLEAN isP2pFrame = FALSE; + struct ieee80211_mgmt *mgmt; + mgmt = (struct ieee80211_mgmt *)pData; + if (ieee80211_is_mgmt(mgmt->frame_control)) + { + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)pData; + + if (ieee80211_is_probe_resp(mgmt->frame_control)) + { + DBGPRINT(RT_DEBUG_INFO, ("CFG80211_PKT: %s ProbeRsp Frame %d\n", preStr, pAd->LatchRfRegs.Channel)); + if (!mgmt->u.probe_resp.timestamp) + { + struct timeval tv; + do_gettimeofday(&tv); + mgmt->u.probe_resp.timestamp = ((UINT64) tv.tv_sec * 1000000) + tv.tv_usec; + } + } + else if (ieee80211_is_disassoc(mgmt->frame_control)) + { + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s DISASSOC Frame\n", preStr)); + } + else if (ieee80211_is_deauth(mgmt->frame_control)) + { + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s Deauth Frame\n", preStr, pAd->LatchRfRegs.Channel)); + } + else if (ieee80211_is_action(mgmt->frame_control)) + { + if ((pFrame->p80211Header.FC.SubType == SUBTYPE_ACTION) && + (pFrame->Category == CATEGORY_PUBLIC) && + (pFrame->Action == ACTION_WIFI_DIRECT)) + { + isP2pFrame = TRUE; + switch (pFrame->Subtype) + { + case GO_NEGOCIATION_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s GO_NEGOCIACTION_REQ %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + + case GO_NEGOCIATION_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s GO_NEGOCIACTION_RSP %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + + case GO_NEGOCIATION_CONFIRM: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s GO_NEGOCIACTION_CONFIRM %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + + case P2P_PROVISION_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2P_PROVISION_REQ %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + + case P2P_PROVISION_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2P_PROVISION_RSP %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + + case P2P_INVITE_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2P_INVITE_REQ %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + + case P2P_INVITE_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2P_INVITE_RSP %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + case P2P_DEV_DIS_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2P_DEV_DIS_REQ %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + case P2P_DEV_DIS_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2P_DEV_DIS_RSP %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + } + } + else if ((pFrame->p80211Header.FC.SubType == SUBTYPE_ACTION) && + (pFrame->Category == CATEGORY_PUBLIC) && + ((pFrame->Action == ACTION_GAS_INITIAL_REQ) || + (pFrame->Action == ACTION_GAS_INITIAL_RSP) || + (pFrame->Action == ACTION_GAS_COMEBACK_REQ ) || + (pFrame->Action == ACTION_GAS_COMEBACK_RSP))) + { + isP2pFrame = TRUE; + } + else if ((pFrame->Category == CATEGORY_VENDOR_SPECIFIC_WFD) && + RTMPEqualMemory(&pFrame->Octet[1], CFG_P2POUIBYTE, 4)) + { + isP2pFrame = TRUE; + switch (pFrame->Subtype) + { + case P2PACT_NOA: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2PACT_NOA %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + case P2PACT_PERSENCE_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2PACT_PERSENCE_REQ %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + case P2PACT_PERSENCE_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2PACT_PERSENCE_RSP %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + case P2PACT_GO_DISCOVER_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s P2PACT_GO_DISCOVER_REQ %d\n", + preStr, pAd->LatchRfRegs.Channel)); + break; + } + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("CFG80211_PKT: %s ACTION Frame with Channel%d\n", preStr, pAd->LatchRfRegs.Channel)); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s UNKOWN MGMT FRAME TYPE\n", preStr)); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("CFG80211_PKT: %s UNKOWN FRAME TYPE\n", preStr)); + } + + return isP2pFrame; +} +BOOLEAN CFG80211_HandleP2pMgmtFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR OpMode) +{ + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNET_DEV pNetDev = NULL; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + UINT32 freq; + + if ((pHeader->FC.SubType == SUBTYPE_PROBE_REQ) || + ((pHeader->FC.SubType == SUBTYPE_ACTION) && + CFG80211_CheckActionFrameType(pAd, "RX", pHeader, pRxWI->RXWI_N.MPDUtotalByteCnt))) + { + MAP_CHANNEL_ID_TO_KHZ(pAd->LatchRfRegs.Channel, freq); + freq /= 1000; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + /* Check the P2P_GO exist in the VIF List */ + if (pCfg80211_ctrl->Cfg80211VifDevSet.vifDevList.size > 0) + { + if ((pNetDev = RTMP_CFG80211_FindVifEntry_ByType(pAd, RT_CMD_80211_IFTYPE_P2P_GO)) != NULL) + { + DBGPRINT(RT_DEBUG_INFO, ("VIF STA GO RtmpOsCFG80211RxMgmt OK!! TYPE = %d, freq = %d, %02x:%02x:%02x:%02x:%02x:%02x\n", + pHeader->FC.SubType, freq, PRINT_MAC(pHeader->Addr2))); + CFG80211OS_RxMgmt(pNetDev, freq, (PUCHAR)pHeader, pRxWI->RXWI_N.MPDUtotalByteCnt); + + if (OpMode == OPMODE_AP) + return TRUE; + } + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + if ( ((pHeader->FC.SubType == SUBTYPE_PROBE_REQ) && + (pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterProbeReqFrame == TRUE) ) || + ((pHeader->FC.SubType == SUBTYPE_ACTION) /*&& ( pAd->Cfg80211RegisterActionFrame == TRUE)*/ )) + { + DBGPRINT(RT_DEBUG_INFO,("MAIN STA RtmpOsCFG80211RxMgmt OK!! TYPE = %d, freq = %d, %02x:%02x:%02x:%02x:%02x:%02x\n", + pHeader->FC.SubType, freq, PRINT_MAC(pHeader->Addr2))); +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (pAd->cfg80211_ctrl.dummy_p2p_net_dev == NULL) //Fix crash problem when hostapd boot up. + { + DBGPRINT(RT_DEBUG_INFO, ("pAd->dummy_p2p_net_dev is NULL!!!!!!!!!!!\n")); + + return FALSE; + } + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + CFG80211OS_RxMgmt(CFG80211_GetEventDevice(pAd), freq, (PUCHAR)pHeader, pRxWI->RXWI_N.MPDUtotalByteCnt); + + if (OpMode == OPMODE_AP) + return TRUE; + } + } + + return FALSE; +} + + +#endif /* RT_CFG80211_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_scan.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_scan.c new file mode 100644 index 000000000..731dc8aa0 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_scan.c @@ -0,0 +1,425 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 Scan function body. + + History: + +***************************************************************************/ + +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + +#ifdef CONFIG_STA_SUPPORT +VOID CFG80211DRV_OpsScanInLinkDownAction( + VOID *pAdOrg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("---> CFG80211_MLME Disconnect in Scaning, ORI ==> %d\n", + pAd->Mlme.CntlMachine.CurrState)); + + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + + pAd->cfg80211_ctrl.FlgCfg80211Scanning = FALSE; + CFG80211OS_ScanEnd(pAd->pCfg80211_CB, TRUE); + + ScanNextChannel(pAd, OPMODE_STA, INT_MAIN); + DBGPRINT(RT_DEBUG_TRACE, ("<--- CFG80211_MLME Disconnect in Scan END, ORI ==> %d\n", + pAd->Mlme.CntlMachine.CurrState)); +} + +BOOLEAN CFG80211DRV_OpsScanRunning( + VOID *pAdOrg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + return pAd->cfg80211_ctrl.FlgCfg80211Scanning; +} +#endif /*CONFIG_STA_SUPPORT*/ + + +/* Refine on 2013/04/30 for two functin into one */ +INT CFG80211DRV_OpsScanGetNextChannel( + VOID *pAdOrg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + + if (cfg80211_ctrl->pCfg80211ChanList != NULL) + { + if (cfg80211_ctrl->Cfg80211CurChanIndex < cfg80211_ctrl->Cfg80211ChanListLen) + { + return cfg80211_ctrl->pCfg80211ChanList[cfg80211_ctrl->Cfg80211CurChanIndex++]; + } + else + { + os_free_mem(NULL, cfg80211_ctrl->pCfg80211ChanList); + cfg80211_ctrl->pCfg80211ChanList = NULL; + cfg80211_ctrl->Cfg80211ChanListLen = 0; + cfg80211_ctrl->Cfg80211CurChanIndex = 0; + + return 0; + } + } + + return 0; +} + +BOOLEAN CFG80211DRV_OpsScanSetSpecifyChannel( + VOID *pAdOrg, + VOID *pData, + UINT8 dataLen) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + UINT32 *pChanList = (UINT32 *) pData; + + if (pChanList != NULL) + { + if (cfg80211_ctrl->pCfg80211ChanList != NULL) + os_free_mem(NULL, cfg80211_ctrl->pCfg80211ChanList); + + os_alloc_mem(NULL, (UCHAR **)&cfg80211_ctrl->pCfg80211ChanList, sizeof(UINT32 *) * dataLen); + if (cfg80211_ctrl->pCfg80211ChanList != NULL) + { + NdisCopyMemory(cfg80211_ctrl->pCfg80211ChanList, pChanList, sizeof(UINT32 *) * dataLen); + cfg80211_ctrl->Cfg80211ChanListLen = dataLen; + cfg80211_ctrl->Cfg80211CurChanIndex = 0 ; /* Start from index 0 */ + return NDIS_STATUS_SUCCESS; + } + else + { + return NDIS_STATUS_FAILURE; + } + } + + return NDIS_STATUS_FAILURE; +} + +BOOLEAN CFG80211DRV_OpsScanCheckStatus( + VOID *pAdOrg, + UINT8 IfType) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + + /* CFG_TODO */ + if (CFG80211DRV_OpsScanRunning(pAd)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("SCAN_FAIL: CFG80211 Internal SCAN Flag On\n")); + return FALSE; + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("SCAN_FAIL: BSS_SCAN_IN_PROGRESS\n")); + return FALSE; + } + + /* To avoid the scan cmd come-in during driver init */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SCAN_FAIL: Scan cmd before Startup finish\n")); + return FALSE; + } + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (RTMP_CFG80211_VIF_P2P_CLI_ON(pAd) && + (pAd->cfg80211_ctrl.FlgCfg80211Connecting == TRUE) && + (IfType == RT_CMD_80211_IFTYPE_STATION)) + { + DBGPRINT(RT_DEBUG_ERROR,("SCAN_FAIL: P2P_CLIENT In Connecting & Canncel Scan with Infra Side\n")); + return FALSE; + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +#ifdef RT_CFG80211_SUPPORT + if (pAd->cfg80211_ctrl.FlgCfg8021Disable2040Scan == TRUE && + (IfType == RT_CMD_80211_IFTYPE_AP)) + { + DBGPRINT(RT_DEBUG_ERROR,("Disable 20/40 scan!!\n")); + return FALSE; + } +#endif /* RT_CFG80211_SUPPORT */ + + /* do scan */ + pAd->cfg80211_ctrl.FlgCfg80211Scanning = TRUE; +#endif /*CONFIG_STA_SUPPORT*/ + return TRUE; +} + +BOOLEAN CFG80211DRV_OpsScanExtraIesSet( + VOID *pAdOrg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CFG80211_CB *pCfg80211_CB = pAd->pCfg80211_CB; + UINT ie_len = 0; + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + + if (pCfg80211_CB->pCfg80211_ScanReq) + ie_len = pCfg80211_CB->pCfg80211_ScanReq->ie_len; + + CFG80211DBG(RT_DEBUG_INFO, ("80211> CFG80211DRV_OpsExtraIesSet ==> %d\n", ie_len)); +#ifdef CONFIG_STA_SUPPORT + CFG80211DBG(RT_DEBUG_INFO, ("80211> is_wpa_supplicant_up ==> %d\n", + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP)); +#endif /*CONFIG_STA_SUPPORT*/ + if (ie_len == 0) + return FALSE; + + /* Reset the ExtraIe and Len */ + if (cfg80211_ctrl->pExtraIe) + { + os_free_mem(NULL, cfg80211_ctrl->pExtraIe); + cfg80211_ctrl->pExtraIe = NULL; + } + cfg80211_ctrl->ExtraIeLen = 0; + + os_alloc_mem(pAd, (UCHAR **)&(cfg80211_ctrl->pExtraIe), ie_len); + if (cfg80211_ctrl->pExtraIe) + { + NdisCopyMemory(cfg80211_ctrl->pExtraIe, pCfg80211_CB->pCfg80211_ScanReq->ie, ie_len); + cfg80211_ctrl->ExtraIeLen = ie_len; + hex_dump("CFG8021_SCAN_EXTRAIE", cfg80211_ctrl->pExtraIe, cfg80211_ctrl->ExtraIeLen); + } + else + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211DRV_OpsExtraIesSet ==> allocate fail. \n")); + return FALSE; + } + + return TRUE; +} + +#ifdef CFG80211_SCAN_SIGNAL_AVG +static void CFG80211_CalBssAvgRssi( + IN BSS_ENTRY *pBssEntry) +{ + BOOLEAN bInitial = FALSE; + + if (!(pBssEntry->AvgRssiX8 | pBssEntry->AvgRssi)) + { + bInitial = TRUE; + } + + if (bInitial) + { + pBssEntry->AvgRssiX8 = pBssEntry->Rssi << 3; + pBssEntry->AvgRssi = pBssEntry->Rssi; + } + else + { + /* For smooth purpose, oldRssi for 7/8, newRssi for 1/8 */ + pBssEntry->AvgRssiX8 = + (pBssEntry->AvgRssiX8 - pBssEntry->AvgRssi) + pBssEntry->Rssi; + } + + pBssEntry->AvgRssi = pBssEntry->AvgRssiX8 >> 3; + +} + +static void CFG80211_UpdateBssTableRssi( + IN VOID *pAdCB) +{ + + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pAd->pCfg80211_CB; + struct wiphy *pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + struct ieee80211_channel *chan; + struct cfg80211_bss *bss; + BSS_ENTRY *pBssEntry; + UINT index; + UINT32 CenFreq; + + for (index = 0; index < pAd->ScanTab.BssNr; index++) + { + pBssEntry = &pAd->ScanTab.BssEntry[index]; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) + if (pAd->ScanTab.BssEntry[index].Channel > 14) + CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel , IEEE80211_BAND_5GHZ); + else + CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel , IEEE80211_BAND_2GHZ); +#else + CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel); +#endif + + chan = ieee80211_get_channel(pWiphy, CenFreq); + bss = cfg80211_get_bss(pWiphy, chan, pBssEntry->Bssid, pBssEntry->Ssid, pBssEntry->SsidLen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (bss == NULL) + { + /* ScanTable Entry not exist in kernel buffer */ + } + else + { + /* HIT */ + CFG80211_CalBssAvgRssi(pBssEntry); + bss->signal = pBssEntry->AvgRssi * 100; //UNIT: MdBm +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) + cfg80211_put_bss(pWiphy, bss); +#else + cfg80211_put_bss(bss); +#endif /* LINUX_VERSION_CODE: 3.9.0 */ + } + } +} +#endif /* CFG80211_SCAN_SIGNAL_AVG */ + +/* +======================================================================== +Routine Description: + Inform us that a scan is got. + +Arguments: + pAdCB - WLAN control block pointer + +Return Value: + NONE + +Note: + Call RT_CFG80211_SCANNING_INFORM, not CFG80211_Scaning +======================================================================== +*/ +VOID CFG80211_Scaning( + IN VOID *pAdCB, + IN UINT32 BssIdx, + IN UINT32 ChanId, + IN UCHAR *pFrame, + IN UINT32 FrameLen, + IN INT32 RSSI) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + VOID *pCfg80211_CB = pAd->pCfg80211_CB; + BOOLEAN FlgIsNMode; + UINT8 BW; + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Network is down!\n")); + return; + } + + /* + In connect function, we also need to report BSS information to cfg80211; + Not only scan function. + */ + if ((!CFG80211DRV_OpsScanRunning(pAd)) && + (pAd->cfg80211_ctrl.FlgCfg80211Connecting == FALSE)) + { + return; /* no scan is running from wpa_supplicant */ + } + + + /* init */ + /* Note: Can not use local variable to do pChan */ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + FlgIsNMode = TRUE; + else + FlgIsNMode = FALSE; + + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20) + BW = 0; + else + BW = 1; + + CFG80211OS_Scaning(pCfg80211_CB, + ChanId, + pFrame, + FrameLen, + RSSI, + FlgIsNMode, + BW); +#endif /* CONFIG_STA_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Inform us that scan ends. + +Arguments: + pAdCB - WLAN control block pointer + FlgIsAborted - 1: scan is aborted + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID CFG80211_ScanEnd( + IN VOID *pAdCB, + IN BOOLEAN FlgIsAborted) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Network is down!\n")); + return; + } + + if (!CFG80211DRV_OpsScanRunning(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> No scan is running!\n")); + return; /* no scan is running */ + } + + if (FlgIsAborted == TRUE) + FlgIsAborted = 1; + else + { + FlgIsAborted = 0; +#ifdef CFG80211_SCAN_SIGNAL_AVG + CFG80211_UpdateBssTableRssi(pAd); +#endif /* CFG80211_SCAN_SIGNAL_AVG */ + } + + CFG80211OS_ScanEnd(CFG80211CB, FlgIsAborted); + pAd->cfg80211_ctrl.FlgCfg80211Scanning = FALSE; +#endif /* CONFIG_STA_SUPPORT */ +} + +VOID CFG80211_ScanStatusLockInit( + IN VOID *pAdCB, + IN UINT init) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pAd->pCfg80211_CB; + + if (init) + { + NdisAllocateSpinLock(pAd, &pCfg80211_CB->scan_notify_lock); + } + else + { + NdisFreeSpinLock(&pCfg80211_CB->scan_notify_lock); + } +} + +#endif /* RT_CFG80211_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_tdls.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_tdls.c new file mode 100644 index 000000000..88f0b9056 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_tdls.c @@ -0,0 +1,33 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 TDLS function body. + + History: + +***************************************************************************/ + +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + + +#endif /* RT_CFG80211_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_tx.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_tx.c new file mode 100644 index 000000000..4d37c6884 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_tx.c @@ -0,0 +1,490 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 P2P function body. + + History: + +***************************************************************************/ + +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + +VOID CFG80211_SwitchTxChannel(RTMP_ADAPTER *pAd, ULONG Data) +{ + //UCHAR lock_channel = CFG80211_getCenCh(pAd, Data); + UCHAR lock_channel = Data; + if (pAd->LatchRfRegs.Channel != lock_channel) + { + AsicSwitchChannel(pAd, lock_channel, FALSE); + AsicLockChannel(pAd, lock_channel); + + DBGPRINT(RT_DEBUG_INFO, ("Off-Channel Send Packet: From(%d)-To(%d)\n", + pAd->LatchRfRegs.Channel, lock_channel)); + } + else + DBGPRINT(RT_DEBUG_INFO, ("Off-Channel Channel Equal: %d\n", pAd->LatchRfRegs.Channel)); + +} + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN CFG80211_SyncPacketWmmIe(RTMP_ADAPTER *pAd, VOID *pData, ULONG dataLen) +{ + const UINT WFA_OUI = 0x0050F2; + const UCHAR WMM_OUI_TYPE = 0x2; + UCHAR *wmm_ie = NULL; + + return;//???? + //hex_dump("probe_rsp_in:", pData, dataLen); + wmm_ie = cfg80211_find_vendor_ie(WFA_OUI, WMM_OUI_TYPE, pData, dataLen); + + if (wmm_ie != NULL) + { +#ifdef UAPSD_SUPPORT + if (pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable == TRUE) + { + wmm_ie[8] |= 0x80; + } +#endif /* UAPSD_SUPPORT */ + + + UINT i = QID_AC_BE; + /* WMM: sync from driver's EDCA paramter */ + for (i = QID_AC_BE; i <= QID_AC_VO; i++) + { + + wmm_ie[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ + ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ + (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ + + wmm_ie[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ + (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ + wmm_ie[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff);/* low byte of TXOP */ + wmm_ie[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ + } + + return TRUE; + } + + return FALSE; +} +VOID CFG80211_ParseBeaconIE(RTMP_ADAPTER *pAd, MULTISSID_STRUCT *pMbss, struct wifi_dev *wdev,UCHAR *wpa_ie,UCHAR *rsn_ie) +{ + PEID_STRUCT pEid; + PUCHAR pTmp; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher 1, this one has more secured cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; /* Unicast cipher 2 if AP announce two unicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Group cipher */ + PAKM_SUITE_STRUCT pAKM; + USHORT Count; + BOOLEAN bWPA = FALSE; + BOOLEAN bWPA2 = FALSE; + BOOLEAN bMix = FALSE; + + /* Security */ + PairCipher = Ndis802_11WEPDisabled; + PairCipherAux = Ndis802_11WEPDisabled; + + if ((wpa_ie == NULL) && (rsn_ie == NULL)) //open case + { + DBGPRINT(RT_DEBUG_TRACE,("%s:: Open/None case\n", __FUNCTION__)); + wdev->AuthMode = Ndis802_11AuthModeOpen; + wdev->WepStatus = Ndis802_11WEPDisabled; + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + } + + if ((wpa_ie != NULL)) //wpapsk/tkipaes case + { + pEid = wpa_ie; + pTmp = pEid; + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + wdev->AuthMode = Ndis802_11AuthModeOpen; + DBGPRINT(RT_DEBUG_TRACE,("%s:: WPA case\n", __FUNCTION__)); + bWPA = TRUE; + pTmp += 11; + switch (*pTmp) + { + case 1: + DBGPRINT(RT_DEBUG_TRACE,("Group Ndis802_11GroupWEP40Enabled\n")); + wdev->GroupKeyWepStatus = Ndis802_11GroupWEP40Enabled; + break; + case 5: + DBGPRINT(RT_DEBUG_TRACE,("Group Ndis802_11GroupWEP104Enabled\n")); + wdev->GroupKeyWepStatus = Ndis802_11GroupWEP104Enabled; + break; + case 2: + DBGPRINT(RT_DEBUG_TRACE,("Group Ndis802_11TKIPEnable\n")); + wdev->GroupKeyWepStatus = Ndis802_11TKIPEnable; + break; + case 4: + DBGPRINT(RT_DEBUG_TRACE,(" Group Ndis802_11AESEnable\n")); + wdev->GroupKeyWepStatus = Ndis802_11AESEnable; + break; + default: + break; + } + /* number of unicast suite*/ + pTmp += 1; + + /* skip all unicast cipher suites*/ + /*Count = *(PUSHORT) pTmp; */ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + /* Skip OUI*/ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + PairCipherAux = PairCipher; + PairCipher = TmpCipher; + } + else + { + PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + switch (*pTmp) + { + case 1: + /* Set AP support WPA-enterprise mode*/ + wdev->AuthMode = Ndis802_11AuthModeWPA; + break; + case 2: + /* Set AP support WPA-PSK mode*/ + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + pTmp += 1; + + DBGPRINT(RT_DEBUG_TRACE,("AuthMode = %s\n",GetAuthMode(wdev->AuthMode))); + if (wdev->GroupKeyWepStatus == PairCipher) + { + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + pMbss->wdev.WepStatus=wdev->GroupKeyWepStatus; + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("WPA Mix TKIPAES\n")); + + bMix = TRUE; + } + pMbss->RSNIE_Len[0] = wpa_ie[1]; + NdisMoveMemory(pMbss->RSN_IE[0], wpa_ie+2, wpa_ie[1]);//copy rsn ie + } + else { + DBGPRINT(RT_DEBUG_TRACE,("%s:: Open/None case\n", __FUNCTION__)); + wdev->AuthMode = Ndis802_11AuthModeOpen; + } + } + if ((rsn_ie != NULL)) + { + PRSN_IE_HEADER_STRUCT pRsnHeader; + PCIPHER_SUITE_STRUCT pCipher; + + pEid = rsn_ie; + pTmp = pEid; + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + /* 0. Version must be 1*/ + if (le2cpu16(pRsnHeader->Version) == 1) + { + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Check group cipher*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + + if (NdisEqualMemory(pTmp, RSN_OUI, 3)) + { + DBGPRINT(RT_DEBUG_TRACE,("%s:: WPA2 case\n", __FUNCTION__)); + bWPA2 = TRUE; + wdev->AuthMode = Ndis802_11AuthModeOpen; + switch (pCipher->Type) + { + case 1: + DBGPRINT(RT_DEBUG_TRACE,("Ndis802_11GroupWEP40Enabled\n")); + wdev->GroupKeyWepStatus = Ndis802_11GroupWEP40Enabled; + break; + case 5: + DBGPRINT(RT_DEBUG_TRACE,("Ndis802_11GroupWEP104Enabled\n")); + wdev->GroupKeyWepStatus = Ndis802_11GroupWEP104Enabled; + break; + case 2: + DBGPRINT(RT_DEBUG_TRACE,("Ndis802_11TKIPEnable\n")); + wdev->GroupKeyWepStatus = Ndis802_11TKIPEnable; + break; + case 4: + DBGPRINT(RT_DEBUG_TRACE,("Ndis802_11AESEnable\n")); + wdev->GroupKeyWepStatus = Ndis802_11AESEnable; + break; + default: + break; + } + + /* set to correct offset for next parsing*/ + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + /* 2. Get pairwise cipher counts*/ + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* 3. Get pairwise cipher*/ + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + /* Skip OUI*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + + //pMbss->wdev.WepStatus = TmpCipher; + if (TmpCipher > PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + PairCipherAux = PairCipher; + PairCipher = TmpCipher; + } + else + { + PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + /* 4. get AKM suite counts*/ + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* 5. Get AKM ciphers*/ + /* Parsing all AKM ciphers*/ + while (Count > 0) + { + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 0: + wdev->AuthMode = Ndis802_11AuthModeWPANone; + break; + case 1: + /* Set AP support WPA-enterprise mode*/ + wdev->AuthMode = Ndis802_11AuthModeWPA2; + break; + case 2: + /* Set AP support WPA-PSK mode*/ + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + break; + default: + wdev->AuthMode = Ndis802_11AuthModeMax; + break; + } + pTmp += sizeof(AKM_SUITE_STRUCT); + Count--; + } + DBGPRINT(RT_DEBUG_TRACE,("AuthMode = %s\n",GetAuthMode(wdev->AuthMode))); + if (wdev->GroupKeyWepStatus == PairCipher) + { + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + pMbss->wdev.WepStatus=wdev->GroupKeyWepStatus; + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("WPA2 Mix TKIPAES\n")); + bMix= TRUE; + } + pMbss->RSNIE_Len[0] = rsn_ie[1]; + NdisMoveMemory(pMbss->RSN_IE[0], rsn_ie+2, rsn_ie[1]);//copy rsn ie + } + else { + DBGPRINT(RT_DEBUG_TRACE,("%s:: Open/None case\n", __FUNCTION__)); + wdev->AuthMode = Ndis802_11AuthModeOpen; + } + } + } + + + if (bWPA2 && bWPA) + { + if (bMix) + { + DBGPRINT(RT_DEBUG_TRACE,("WPAPSK/WPA2PSK Mix TKIPAES\n")); + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + wdev->WepStatus = Ndis802_11TKIPAESMix; + } + } else if (bWPA2) { + if (bMix) + { + DBGPRINT(RT_DEBUG_TRACE,("WPA2PSK Mix TKIPAES\n")); + wdev->WpaMixPairCipher = WPA_NONE_WPA2_TKIPAES; + wdev->WepStatus = Ndis802_11TKIPAESMix; + } + } else if (bWPA) { + if (bMix) + { + DBGPRINT(RT_DEBUG_TRACE,("WPAPSK Mix TKIPAES\n")); + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_NONE; + wdev->WepStatus = Ndis802_11TKIPAESMix; + } + } + } + +#endif /* CONFIG_AP_SUPPORT */ + +static +PCFG80211_TX_PACKET CFG80211_TxMgmtFrameSearch(RTMP_ADAPTER *pAd, USHORT Sequence) +{ + PLIST_HEADER pPacketList = &pAd->cfg80211_ctrl.cfg80211TxPacketList; + PCFG80211_TX_PACKET pTxPkt = NULL; + PLIST_ENTRY pListEntry = NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("CFG_TX_STATUS: Search %d\n", Sequence)); + pListEntry = pPacketList->pHead; + pTxPkt = (PCFG80211_TX_PACKET)pListEntry; + + while (pTxPkt != NULL) + { + if (pTxPkt->TxStatusSeq == Sequence) + { + DBGPRINT(RT_DEBUG_ERROR, ("CFG_TX_STATUS: got %d\n", Sequence)); + return pTxPkt; + } + + pListEntry = pListEntry->pNext; + pTxPkt = (PCFG80211_TX_PACKET)pListEntry; + } + +} + +INT CFG80211_SendMgmtFrame(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + if (pData != NULL) + { + { + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + + pCfg80211_ctrl->TxStatusInUsed = TRUE; + pCfg80211_ctrl->TxStatusSeq = pAd->Sequence; + + if (pCfg80211_ctrl->pTxStatusBuf != NULL) + { + os_free_mem(NULL, pCfg80211_ctrl->pTxStatusBuf); + pCfg80211_ctrl->pTxStatusBuf = NULL; + } + + os_alloc_mem(NULL, (UCHAR **)&pCfg80211_ctrl->pTxStatusBuf, Data); + if (pCfg80211_ctrl->pTxStatusBuf != NULL) + { + NdisCopyMemory(pCfg80211_ctrl->pTxStatusBuf, pData, Data); + pCfg80211_ctrl->TxStatusBufLen = Data; + } + else + { + pCfg80211_ctrl->TxStatusBufLen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("CFG_TX_STATUS: MEM ALLOC ERROR\n")); + return NDIS_STATUS_FAILURE; + } + CFG80211_CheckActionFrameType(pAd, "TX", pData, Data); + +#ifdef CONFIG_AP_SUPPORT + struct ieee80211_mgmt *mgmt; + mgmt = (struct ieee80211_mgmt *)pData; + if (ieee80211_is_probe_resp(mgmt->frame_control)) + { + //BOOLEAN res; + INT offset = sizeof(HEADER_802_11) + 12; + CFG80211_SyncPacketWmmIe(pAd, pData + offset , Data - offset); + //hex_dump("probe_rsp:", pData, Data); + } +#endif /* CONFIG_AP_SUPPORT */ + + MiniportMMRequest(pAd, 0, pData, Data); + } + } + +} + +VOID CFG80211_SendMgmtFrameDone(RTMP_ADAPTER *pAd, USHORT Sequence) +{ +//RTMP_USB_SUPPORT/RTMP_PCI_SUPPORT + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + + if (pCfg80211_ctrl->TxStatusInUsed && pCfg80211_ctrl->pTxStatusBuf + /*&& (pAd->TxStatusSeq == pHeader->Sequence)*/) + { + DBGPRINT(RT_DEBUG_INFO, ("CFG_TX_STATUS: REAL send %d\n", Sequence)); + + CFG80211OS_TxStatus(CFG80211_GetEventDevice(pAd), 5678, + pCfg80211_ctrl->pTxStatusBuf, pCfg80211_ctrl->TxStatusBufLen, + TRUE); + pCfg80211_ctrl->TxStatusSeq = 0; + pCfg80211_ctrl->TxStatusInUsed = FALSE; + } + + +} + +#endif /* RT_CFG80211_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_util.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_util.c new file mode 100644 index 000000000..cf154917b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211_util.c @@ -0,0 +1,1188 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, 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 CFG80211 function body. + + History: + +***************************************************************************/ +#ifdef RT_CFG80211_SUPPORT +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" + +/* all available channels */ +UCHAR Cfg80211_Chan[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + + /* 802.11 UNI / HyperLan 2 */ + 36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64, + + /* 802.11 HyperLan 2 */ + 100, 104, 108, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136, + + /* 802.11 UNII */ + 140, 149, 151, 153, 157, 159, 161, 165, 167, 169, 171, 173, + + /* Japan */ + 184, 188, 192, 196, 208, 212, 216, +}; + +UCHAR Cfg80211_RadarChan[] = { + 52, 54, 56, 60, 62, 64, 100, 104, +}; + +/* + Array of bitrates the hardware can operate with + in this band. Must be sorted to give a valid "supported + rates" IE, i.e. CCK rates first, then OFDM. + + For HT, assign MCS in another structure, ieee80211_sta_ht_cap. +*/ +const struct ieee80211_rate Cfg80211_SupRate[12] = { + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 10, + .hw_value = 0, + .hw_value_short = 0, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 20, + .hw_value = 1, + .hw_value_short = 1, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 55, + .hw_value = 2, + .hw_value_short = 2, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 110, + .hw_value = 3, + .hw_value_short = 3, + }, + { + .flags = 0, + .bitrate = 60, + .hw_value = 4, + .hw_value_short = 4, + }, + { + .flags = 0, + .bitrate = 90, + .hw_value = 5, + .hw_value_short = 5, + }, + { + .flags = 0, + .bitrate = 120, + .hw_value = 6, + .hw_value_short = 6, + }, + { + .flags = 0, + .bitrate = 180, + .hw_value = 7, + .hw_value_short = 7, + }, + { + .flags = 0, + .bitrate = 240, + .hw_value = 8, + .hw_value_short = 8, + }, + { + .flags = 0, + .bitrate = 360, + .hw_value = 9, + .hw_value_short = 9, + }, + { + .flags = 0, + .bitrate = 480, + .hw_value = 10, + .hw_value_short = 10, + }, + { + .flags = 0, + .bitrate = 540, + .hw_value = 11, + .hw_value_short = 11, + }, +}; + +static const UINT32 CipherSuites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +#ifdef DOT11W_PMF_SUPPORT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + WLAN_CIPHER_SUITE_AES_CMAC, +#endif /* LINUX_VERSION_CODE */ +#endif /* DOT11W_PMF_SUPPORT */ +}; + +static BOOLEAN IsRadarChannel(UCHAR ch) +{ + UINT idx = 0; + for (idx = 0; idxpCfg80211_Wdev != NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> unregister/free wireless device\n")); + + /* + Must unregister, or you will suffer problem when you change + regulatory domain by using iw. + */ + +#ifdef RFKILL_HW_SUPPORT + wiphy_rfkill_stop_polling(pCfg80211_CB->pCfg80211_Wdev->wiphy); +#endif /* RFKILL_HW_SUPPORT */ + wiphy_unregister(pCfg80211_CB->pCfg80211_Wdev->wiphy); + wiphy_free(pCfg80211_CB->pCfg80211_Wdev->wiphy); + kfree(pCfg80211_CB->pCfg80211_Wdev); + + if (pCfg80211_CB->pCfg80211_Channels != NULL) + kfree(pCfg80211_CB->pCfg80211_Channels); + + if (pCfg80211_CB->pCfg80211_Rates != NULL) + kfree(pCfg80211_CB->pCfg80211_Rates); + + pCfg80211_CB->pCfg80211_Wdev = NULL; + pCfg80211_CB->pCfg80211_Channels = NULL; + pCfg80211_CB->pCfg80211_Rates = NULL; + + /* must reset to NULL; or kernel will panic in unregister_netdev */ + pNetDev->ieee80211_ptr = NULL; + SET_NETDEV_DEV(pNetDev, NULL); + } + + os_free_mem(NULL, pCfg80211_CB); +} + + +/* +======================================================================== +Routine Description: + Initialize wireless channel in 2.4GHZ and 5GHZ. + +Arguments: + pAd - WLAN control block pointer + pWiphy - WLAN PHY interface + pChannels - Current channel info + pRates - Current rate info + +Return Value: + TRUE - init successfully + FALSE - init fail + +Note: + TX Power related: + + 1. Suppose we can send power to 15dBm in the board. + 2. A value 0x0 ~ 0x1F for a channel. We will adjust it based on 15dBm/ + 54Mbps. So if value == 0x07, the TX power of 54Mbps is 15dBm and + the value is 0x07 in the EEPROM. + 3. Based on TX power value of 54Mbps/channel, adjust another value + 0x0 ~ 0xF for other data rate. (-6dBm ~ +6dBm) + + Other related factors: + 1. TX power percentage from UI/users; + 2. Maximum TX power limitation in the regulatory domain. +======================================================================== +*/ +BOOLEAN CFG80211_SupBandInit( + IN VOID *pCB, + IN CFG80211_BAND *pDriverBandInfo, + IN VOID *pWiphyOrg, + IN VOID *pChannelsOrg, + IN VOID *pRatesOrg) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + struct ieee80211_channel *pChannels = (struct ieee80211_channel *)pChannelsOrg; + struct ieee80211_rate *pRates = (struct ieee80211_rate *)pRatesOrg; + struct ieee80211_supported_band *pBand; + UINT32 NumOfChan = 0, NumOfRate = 0; + UINT32 IdLoop = 0; + UINT32 CurTxPower; + + /* sanity check */ + if (pDriverBandInfo->RFICType == 0) + pDriverBandInfo->RFICType = RFIC_24GHZ | RFIC_5GHZ; + + + /* 1. Calcute the Channel Number */ + if (pDriverBandInfo->RFICType & RFIC_5GHZ) + NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ + CFG80211_NUM_OF_CHAN_5GHZ; + else + NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ; + + /* 2. Calcute the Rate Number */ + if (pDriverBandInfo->FlgIsBMode == TRUE) + NumOfRate = 4; + else + NumOfRate = 4 + 8; + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> RFICType= %d, NumOfChan= %d\n", pDriverBandInfo->RFICType, NumOfChan)); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of rate = %d\n", NumOfRate)); + + /* 3. Allocate the Channel instance */ + if (pChannels == NULL) + { + pChannels = kzalloc(sizeof(*pChannels) * NumOfChan, GFP_KERNEL); + if (!pChannels) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_channel allocation fail!\n")); + return FALSE; + } + } + + /* 4. Allocate the Rate instance */ + if (pRates == NULL) + { + pRates = kzalloc(sizeof(*pRates) * NumOfRate, GFP_KERNEL); + if (!pRates) + { + os_free_mem(NULL, pChannels); + DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_rate allocation fail!\n")); + return FALSE; + } + } + + /* get TX power */ +#ifdef SINGLE_SKU + CurTxPower = pDriverBandInfo->DefineMaxTxPwr; /* dBm */ +#else + CurTxPower = 20; /* unknown */ +#endif /* SINGLE_SKU */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> CurTxPower = %d dBm\n", CurTxPower)); + + /* 5. init channel */ + for(IdLoop=0; IdLoop= KERNEL_VERSION(2,6,39)) + if (IdLoop >= 14) + { + pChannels[IdLoop].band = IEEE80211_BAND_5GHZ; + pChannels[IdLoop].center_freq = \ + ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop], IEEE80211_BAND_5GHZ); + } + else + { + pChannels[IdLoop].band = IEEE80211_BAND_2GHZ; + pChannels[IdLoop].center_freq = \ + ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop], IEEE80211_BAND_2GHZ); + } +#else + pChannels[IdLoop].center_freq = ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop]); +#endif + pChannels[IdLoop].hw_value = IdLoop; + + if (IdLoop < CFG80211_NUM_OF_CHAN_2GHZ) + pChannels[IdLoop].max_power = CurTxPower; + else + pChannels[IdLoop].max_power = CurTxPower; + + pChannels[IdLoop].max_antenna_gain = 0xff; + + /* if (RadarChannelCheck(pAd, Cfg80211_Chan[IdLoop])) */ + if (IsRadarChannel(Cfg80211_Chan[IdLoop])) + { + pChannels[IdLoop].flags = 0; + CFG80211DBG(RT_DEBUG_TRACE, ("====> Rader Channel %d\n", Cfg80211_Chan[IdLoop])); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + pChannels[IdLoop].flags |= (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR); +#else + pChannels[IdLoop].flags |= (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN); +#endif + } +/* CFG_TODO: + pChannels[IdLoop].flags + enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, + IEEE80211_CHAN_NO_IBSS = 1<<2, + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, + }; + */ + } + + /* 6. init rate */ + for(IdLoop=0; IdLoopCfg80211_bands[IEEE80211_BAND_2GHZ]; + if (pDriverBandInfo->RFICType & RFIC_24GHZ) + { + pBand->n_channels = CFG80211_NUM_OF_CHAN_2GHZ; + pBand->n_bitrates = NumOfRate; + pBand->channels = pChannels; + pBand->bitrates = pRates; + +#ifdef DOT11_N_SUPPORT + /* for HT, assign pBand->ht_cap */ + pBand->ht_cap.ht_supported = true; + pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40; + pBand->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; /* 2 ^ 16 */ + pBand->ht_cap.ampdu_density = pDriverBandInfo->MpduDensity; /* YF_TODO */ + + memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> TxStream = %d\n", pDriverBandInfo->TxStream)); + + switch(pDriverBandInfo->TxStream) + { + case 1: + default: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_highest = cpu_to_le16(150); + break; + + case 2: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + pBand->ht_cap.mcs.rx_highest = cpu_to_le16(300); + break; + + case 3: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + pBand->ht_cap.mcs.rx_mask[2] = 0xff; + pBand->ht_cap.mcs.rx_highest = cpu_to_le16(450); + break; + } + + pBand->ht_cap.mcs.rx_mask[4] = 0x01; /* 40MHz*/ + pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +#endif /* DOT11_N_SUPPORT */ + + pWiphy->bands[IEEE80211_BAND_2GHZ] = pBand; + } + else + { + pWiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + pBand->channels = NULL; + pBand->bitrates = NULL; + } + + /* 8. Fill the Band 5GHz */ + pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_5GHZ]; + if (pDriverBandInfo->RFICType & RFIC_5GHZ) + { + pBand->n_channels = CFG80211_NUM_OF_CHAN_5GHZ; + pBand->n_bitrates = NumOfRate - 4; /*Disable 11B rate*/ + pBand->channels = &pChannels[CFG80211_NUM_OF_CHAN_2GHZ]; + pBand->bitrates = &pRates[4]; + +#ifdef DOT11_N_SUPPORT + /* for HT, assign pBand->ht_cap */ + pBand->ht_cap.ht_supported = true; + pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40; + pBand->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; /* 2 ^ 16 */ + pBand->ht_cap.ampdu_density = pDriverBandInfo->MpduDensity; /* YF_TODO */ + + memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); + switch(pDriverBandInfo->RxStream) + { + case 1: + default: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_highest = cpu_to_le16(150); + break; + + case 2: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + pBand->ht_cap.mcs.rx_highest = cpu_to_le16(300); + break; + + case 3: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + pBand->ht_cap.mcs.rx_mask[2] = 0xff; + pBand->ht_cap.mcs.rx_highest = cpu_to_le16(450); + break; + } + + pBand->ht_cap.mcs.rx_mask[4] = 0x01; /* 40MHz*/ + pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +#endif /* DOT11_N_SUPPORT */ + + pWiphy->bands[IEEE80211_BAND_5GHZ] = pBand; + } + else + { + pWiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + pBand->channels = NULL; + pBand->bitrates = NULL; + } + + /* 9. re-assign to mainDevice info */ + pCfg80211_CB->pCfg80211_Channels = pChannels; + pCfg80211_CB->pCfg80211_Rates = pRates; + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Re-Initialize wireless channel/PHY in 2.4GHZ and 5GHZ. + +Arguments: + pCB - CFG80211 control block pointer + pBandInfo - Band information + +Return Value: + TRUE - re-init successfully + FALSE - re-init fail + +Note: + CFG80211_SupBandInit() is called in xx_probe(). + But we do not have complete chip information in xx_probe() so we + need to re-init bands in xx_open(). +======================================================================== +*/ +BOOLEAN CFG80211OS_SupBandReInit( + IN VOID *pCB, + IN CFG80211_BAND *pBandInfo) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy; + + + if ((pCfg80211_CB == NULL) || (pCfg80211_CB->pCfg80211_Wdev == NULL)) + return FALSE; + + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + + if (pWiphy != NULL) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> re-init bands...\n")); + + /* re-init bands */ + CFG80211_SupBandInit(pCfg80211_CB, pBandInfo, pWiphy, + pCfg80211_CB->pCfg80211_Channels, + pCfg80211_CB->pCfg80211_Rates); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + /* re-init PHY */ + pWiphy->rts_threshold = pBandInfo->RtsThreshold; + pWiphy->frag_threshold = pBandInfo->FragmentThreshold; + pWiphy->retry_short = pBandInfo->RetryMaxCnt & 0xff; + pWiphy->retry_long = (pBandInfo->RetryMaxCnt & 0xff00)>>8; +#endif /* LINUX_VERSION_CODE */ + + return TRUE; + } + + return FALSE; +} + + +/* +======================================================================== +Routine Description: + Hint to the wireless core a regulatory domain from driver. + +Arguments: + pAd - WLAN control block pointer + pCountryIe - pointer to the country IE + CountryIeLen - length of the country IE + +Return Value: + NONE + +Note: + Must call the function in kernel thread. +======================================================================== +*/ +VOID CFG80211OS_RegHint( + IN VOID *pCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + + CFG80211DBG(RT_DEBUG_ERROR, + ("crda> regulatory domain hint: %c%c\n", + pCountryIe[0], pCountryIe[1])); + + if ((pCfg80211_CB->pCfg80211_Wdev == NULL) || (pCountryIe == NULL)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> regulatory domain hint not support!\n")); + return; + } + + /* hints a country IE as a regulatory domain "without" channel/power info. */ + regulatory_hint(pCfg80211_CB->pCfg80211_Wdev->wiphy, (const char *)pCountryIe); +} + + +/* +======================================================================== +Routine Description: + Hint to the wireless core a regulatory domain from country element. + +Arguments: + pAdCB - WLAN control block pointer + pCountryIe - pointer to the country IE + CountryIeLen - length of the country IE + +Return Value: + NONE + +Note: + Must call the function in kernel thread. +======================================================================== +*/ +VOID CFG80211OS_RegHint11D( + IN VOID *pCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen) +{ + /* no regulatory_hint_11d() in 2.6.32 */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + if ((pCfg80211_CB->pCfg80211_Wdev == NULL) || (pCountryIe == NULL)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> regulatory domain hint not support!\n")); + return; + } + + CFG80211DBG(RT_DEBUG_ERROR, + ("crda> regulatory domain hint: %c%c\n", + pCountryIe[0], pCountryIe[1])); + + /* + hints a country IE as a regulatory domain "with" channel/power info. + but if you use regulatory_hint(), it only hint "regulatory domain". + */ + regulatory_hint_11d(pCfg80211_CB->pCfg80211_Wdev->wiphy, pCountryIe, CountryIeLen); +#endif /* LINUX_VERSION_CODE */ +} + + +BOOLEAN CFG80211OS_BandInfoGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + OUT VOID **ppBand24, + OUT VOID **ppBand5) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + + + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + } + + if (pWiphy == NULL) + return FALSE; + + *ppBand24 = pWiphy->bands[IEEE80211_BAND_2GHZ]; + *ppBand5 = pWiphy->bands[IEEE80211_BAND_5GHZ]; + return TRUE; +} + + +UINT32 CFG80211OS_ChanNumGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + IN UINT32 IdBand) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + + + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + } + + if (pWiphy == NULL) + return 0; + + if (pWiphy->bands[IdBand] != NULL) + return pWiphy->bands[IdBand]->n_channels; + + return 0; +} + + +BOOLEAN CFG80211OS_ChanInfoGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + IN UINT32 IdBand, + IN UINT32 IdChan, + OUT UINT32 *pChanId, + OUT UINT32 *pPower, + OUT BOOLEAN *pFlgIsRadar) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + struct ieee80211_supported_band *pSband; + struct ieee80211_channel *pChan; + + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + } + + if (pWiphy == NULL) + return FALSE; + + pSband = pWiphy->bands[IdBand]; + pChan = &pSband->channels[IdChan]; + + *pChanId = ieee80211_frequency_to_channel(pChan->center_freq); + + if (pChan->flags & IEEE80211_CHAN_DISABLED) + { + CFG80211DBG(RT_DEBUG_ERROR, ("Chan %03d (frq %d):\tnot allowed!\n", + (*pChanId), pChan->center_freq)); + return FALSE; + } + + *pPower = pChan->max_power; + + if (pChan->flags & IEEE80211_CHAN_RADAR) + *pFlgIsRadar = TRUE; + else + *pFlgIsRadar = FALSE; + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Initialize a channel information used in scan inform. + +Arguments: + +Return Value: + TRUE - Successful + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN CFG80211OS_ChanInfoInit( + IN VOID *pCB, + IN UINT32 InfoIndex, + IN UCHAR ChanId, + IN UCHAR MaxTxPwr, + IN BOOLEAN FlgIsNMode, + IN BOOLEAN FlgIsBW20M) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct ieee80211_channel *pChan; + + + if (InfoIndex >= MAX_NUM_OF_CHANNELS) + return FALSE; + + pChan = (struct ieee80211_channel *)&(pCfg80211_CB->ChanInfo[InfoIndex]); + memset(pChan, 0, sizeof(*pChan)); + + if (ChanId > 14) + pChan->band = IEEE80211_BAND_5GHZ; + else + pChan->band = IEEE80211_BAND_2GHZ; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) + pChan->center_freq = ieee80211_channel_to_frequency(ChanId, pChan->band); +#else + pChan->center_freq = ieee80211_channel_to_frequency(ChanId); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) + if (FlgIsNMode == TRUE) + { + if (FlgIsBW20M == TRUE) + pChan->max_bandwidth = 20; /* 20MHz */ + else + pChan->max_bandwidth = 40; /* 40MHz */ + } + else + pChan->max_bandwidth = 5; /* 5MHz for non-HT device */ +#endif /* LINUX_VERSION_CODE */ + +/* no use currently in 2.6.30 */ +/* if (ieee80211_is_beacon(((struct ieee80211_mgmt *)pFrame)->frame_control)) */ +/* pChan->beacon_found = 1; */ + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Inform us that a scan is got. + +Arguments: + pAdCB - WLAN control block pointer + +Return Value: + NONE + +Note: + Call RT_CFG80211_SCANNING_INFORM, not CFG80211_Scaning +======================================================================== +*/ +VOID CFG80211OS_Scaning( + IN VOID *pCB, + IN UINT32 ChanId, + IN UCHAR *pFrame, + IN UINT32 FrameLen, + IN INT32 RSSI, + IN BOOLEAN FlgIsNMode, + IN UINT8 BW) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#ifdef CONFIG_STA_SUPPORT + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct ieee80211_supported_band *pBand; + UINT32 IdChan; + UINT32 CenFreq; + UINT CurBand; + struct wiphy *pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + struct cfg80211_bss *bss = NULL; + struct ieee80211_mgmt *mgmt; + mgmt = (struct ieee80211_mgmt *) pFrame; + + if (ChanId == 0) + ChanId = 1; + + /* get channel information */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) + if (ChanId > 14) + CenFreq = ieee80211_channel_to_frequency(ChanId, IEEE80211_BAND_5GHZ); + else + CenFreq = ieee80211_channel_to_frequency(ChanId, IEEE80211_BAND_2GHZ); +#else + CenFreq = ieee80211_channel_to_frequency(ChanId); +#endif + + if (ChanId > 14) + CurBand = IEEE80211_BAND_5GHZ; + else + CurBand = IEEE80211_BAND_2GHZ; + + pBand = &pCfg80211_CB->Cfg80211_bands[CurBand]; + + for(IdChan=0; IdChan < pBand->n_channels; IdChan++) + { + if (pBand->channels[IdChan].center_freq == CenFreq) + break; + } + + if (IdChan >= pBand->n_channels) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Can not find any chan info! ==> %d[%d],[%d] \n", + ChanId, CenFreq, pBand->n_channels)); + return; + } + + if(pWiphy->signal_type == CFG80211_SIGNAL_TYPE_MBM) + { + /* CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */ + RSSI = RSSI * 100; + } + + if (!mgmt->u.probe_resp.timestamp) + { + struct timeval tv; + do_gettimeofday(&tv); + mgmt->u.probe_resp.timestamp = ((UINT64) tv.tv_sec * 1000000) + tv.tv_usec; + } + + /* inform 80211 a scan is got */ + /* we can use cfg80211_inform_bss in 2.6.31, it is easy more than the one */ + /* in cfg80211_inform_bss_frame(), it will memcpy pFrame but pChan */ + bss = cfg80211_inform_bss_frame(pWiphy, &pBand->channels[IdChan], + mgmt, FrameLen, + RSSI, GFP_ATOMIC); + + if (unlikely(!bss)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> bss inform fail ==> %d\n", IdChan)); + return; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) + cfg80211_put_bss(pWiphy,bss); +#else + cfg80211_put_bss(bss); +#endif /* LINUX_VERSION_CODE: 3.9.0 */ + +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ +} + + +/* +======================================================================== +Routine Description: + Inform us that scan ends. + +Arguments: + pAdCB - WLAN control block pointer + FlgIsAborted - 1: scan is aborted + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID CFG80211OS_ScanEnd( + IN VOID *pCB, + IN BOOLEAN FlgIsAborted) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#ifdef CONFIG_STA_SUPPORT + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + NdisAcquireSpinLock(&pCfg80211_CB->scan_notify_lock); + if (pCfg80211_CB->pCfg80211_ScanReq) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_scan_done\n")); + cfg80211_scan_done(pCfg80211_CB->pCfg80211_ScanReq, FlgIsAborted); + pCfg80211_CB->pCfg80211_ScanReq = NULL; + } + else + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_scan_done ==> NULL\n")); + } + NdisReleaseSpinLock(&pCfg80211_CB->scan_notify_lock); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ +} + + +/* +======================================================================== +Routine Description: + Inform CFG80211 about association status. + +Arguments: + pAdCB - WLAN control block pointer + pBSSID - the BSSID of the AP + pReqIe - the element list in the association request frame + ReqIeLen - the request element length + pRspIe - the element list in the association response frame + RspIeLen - the response element length + FlgIsSuccess - 1: success; otherwise: fail + +Return Value: + None + +Note: +======================================================================== +*/ +void CFG80211OS_ConnectResultInform( + IN VOID *pCB, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + + if ((pCfg80211_CB->pCfg80211_Wdev->netdev == NULL) || (pBSSID == NULL)) + return; + + if (FlgIsSuccess) + { + cfg80211_connect_result(pCfg80211_CB->pCfg80211_Wdev->netdev, + pBSSID, + pReqIe, + ReqIeLen, + pRspIe, + RspIeLen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + else + { + cfg80211_connect_result(pCfg80211_CB->pCfg80211_Wdev->netdev, + pBSSID, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } +#endif /* LINUX_VERSION_CODE */ +} + +/* CFG_TODO: should be merge totoger */ +void CFG80211OS_P2pClientConnectResultInform( + IN PNET_DEV pNetDev, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess) +{ + if ((pNetDev == NULL) || (pBSSID == NULL)) + return; + + if (FlgIsSuccess) + { + printk("APCLI: ReqIeLen %d, RspIeLen, %d\n", ReqIeLen, RspIeLen); + hex_dump("APCLI Req:", pReqIe, ReqIeLen); + hex_dump("APCLI Rsp:", pRspIe, RspIeLen); + cfg80211_connect_result(pNetDev, + pBSSID, + pReqIe, + ReqIeLen, + pRspIe, + RspIeLen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + else + { + cfg80211_connect_result(pNetDev, + pBSSID, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } +} + +BOOLEAN CFG80211OS_RxMgmt(IN PNET_DEV pNetDev, IN INT32 freq, IN PUCHAR frame, IN UINT32 len) +{ + if (pNetDev == NULL) + { + CFG80211DBG(RT_DEBUG_ERROR, ("%s: pNetDev == NULL\n", __FUNCTION__)); + return FALSE; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) + return cfg80211_rx_mgmt(pNetDev->ieee80211_ptr, + freq, + 0, //CFG_TODO return 0 in dbm + frame, + len, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + return cfg80211_rx_mgmt(pNetDev->ieee80211_ptr, + freq, + 0, //CFG_TODO return 0 in dbm + frame, + len, + GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + return cfg80211_rx_mgmt(pNetDev, + freq, + 0, //CFG_TODO return 0 in dbm + frame, + len, + GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + return cfg80211_rx_mgmt(pNetDev, freq, frame, len, GFP_ATOMIC); +#else + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + return cfg80211_rx_action(pNetDev, freq, frame, len, GFP_ATOMIC); +#else + return FALSE; +#endif /* LINUX_VERSION_CODE: 2.6.34 */ +#endif /* LINUX_VERSION_CODE: 2.6.37 */ +#endif /* LINUX_VERSION_CODE: 3.4.0 */ +#endif /* LINUX_VERSION_CODE: 3.6.0 */ +#endif /* LINUX_VERSION_CODE: 3.12.0 */ + +} + +VOID CFG80211OS_TxStatus(IN PNET_DEV pNetDev, IN INT32 cookie, IN PUCHAR frame, IN UINT32 len, IN BOOLEAN ack) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + return cfg80211_mgmt_tx_status(pNetDev->ieee80211_ptr, cookie, frame, len, ack, GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + return cfg80211_mgmt_tx_status(pNetDev, cookie, frame, len, ack, GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + return cfg80211_action_tx_status(pNetDev, cookie, frame, len, ack, GFP_ATOMIC); +#else + return FALSE; +#endif /*2.6.34*/ +#endif /*2.6.37*/ +#endif /* LINUX_VERSION_CODE: 3.6.0 */ + +} + +VOID CFG80211OS_NewSta(IN PNET_DEV pNetDev, IN const PUCHAR mac_addr, IN const PUCHAR assoc_frame, IN UINT32 assoc_len) +{ + struct station_info sinfo; + struct ieee80211_mgmt *mgmt; + + NdisZeroMemory(&sinfo, sizeof(sinfo)); + +/* If get error here, be sure patch the cfg80211_new_sta.patch into kernel. */ + if (pNetDev->ieee80211_ptr->iftype != RT_CMD_80211_IFTYPE_ADHOC) + { + sinfo.filled = STATION_INFO_ASSOC_REQ_IES; + mgmt = (struct ieee80211_mgmt *) assoc_frame; + + if (ieee80211_is_reassoc_req(mgmt->frame_control)) + { + /* Re-AssocReq more than one BSSID for current AP */ + sinfo.assoc_req_ies_len = assoc_len - LENGTH_802_11_CRC - MAC_ADDR_LEN; + sinfo.assoc_req_ies = mgmt->u.reassoc_req.variable; + } + else + { + sinfo.assoc_req_ies_len = assoc_len - LENGTH_802_11_CRC; + sinfo.assoc_req_ies = mgmt->u.assoc_req.variable; + } + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + return cfg80211_new_sta(pNetDev, mac_addr, &sinfo, GFP_ATOMIC); +#endif /* LINUX_VERSION_CODE: 2.6.34 */ +} + +VOID CFG80211OS_DelSta(IN PNET_DEV pNetDev, IN const PUCHAR mac_addr) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)) + return cfg80211_del_sta(pNetDev, mac_addr, GFP_ATOMIC); +#endif +} + +VOID CFG80211OS_MICFailReport(PNET_DEV pNetDev, const PUCHAR src_addr, BOOLEAN unicast, INT key_id, const PUCHAR tsc) +{ + cfg80211_michael_mic_failure(pNetDev, src_addr, + (unicast ? NL80211_KEYTYPE_PAIRWISE : NL80211_KEYTYPE_GROUP), + key_id, tsc, GFP_ATOMIC); +} + +VOID CFG80211OS_Roamed( + PNET_DEV pNetDev, IN UCHAR *pBSSID, + IN UCHAR *pReqIe, IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, IN UINT32 RspIeLen) +{ + cfg80211_roamed(pNetDev, +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) + NULL, +#endif + pBSSID, + pReqIe, ReqIeLen, + pRspIe, RspIeLen, + GFP_KERNEL); +} + +VOID CFG80211OS_RecvObssBeacon(VOID *pCB, const PUCHAR pFrame, INT frameLen, INT freq) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy; + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; /* To avoid compile warning: unused variable @20140529 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + cfg80211_report_obss_beacon(pWiphy, pFrame,frameLen, freq, 0 /*dbm*/); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + cfg80211_report_obss_beacon(pWiphy, pFrame,frameLen, freq, 0 /*dbm*/, GFP_ATOMIC); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) + cfg80211_report_obss_beacon(pWiphy, pFrame,frameLen, freq, GFP_ATOMIC); +#endif /* LINUX_VERSION_CODE: 3.3.0 */ +#endif /* LINUX_VERSION_CODE: 3.4.0 */ +#endif /* LINUX_VERSION_CODE: 3.8.0 */ +} + +#endif /* RT_CFG80211_SUPPORT */ \ No newline at end of file diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211drv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211drv.c new file mode 100644 index 000000000..245e76cb9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/cfg80211/cfg80211drv.c @@ -0,0 +1,1841 @@ +/**************************************************************************** + * 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 CFG80211 function body. + + History: + +***************************************************************************/ +#define RTMP_MODULE_OS + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + +extern struct notifier_block cfg80211_netdev_notifier; + +extern INT RtmpIoctl_rt_ioctl_siwauth( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data); + +extern INT RtmpIoctl_rt_ioctl_siwauth( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data); + + +INT CFG80211DRV_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + + switch(cmd) + { + case CMD_RTPRIV_IOCTL_80211_START: + case CMD_RTPRIV_IOCTL_80211_END: + /* nothing to do */ + break; + + case CMD_RTPRIV_IOCTL_80211_CB_GET: + *(VOID **)pData = (VOID *)(pAd->pCfg80211_CB); + break; + + case CMD_RTPRIV_IOCTL_80211_CB_SET: + pAd->pCfg80211_CB = pData; + break; + + case CMD_RTPRIV_IOCTL_80211_CHAN_SET: + if (CFG80211DRV_OpsSetChannel(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_80211_VIF_CHG: + if (CFG80211DRV_OpsChgVirtualInf(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_80211_SCAN: + if (CFG80211DRV_OpsScanCheckStatus(pAd, Data) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_80211_SCAN_STATUS_LOCK_INIT: + CFG80211_ScanStatusLockInit(pAd, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_IBSS_JOIN: + CFG80211DRV_OpsJoinIbss(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_STA_LEAVE: + CFG80211DRV_OpsLeave(pAd, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_STA_GET: + if (CFG80211DRV_StaGet(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + case CMD_RTPRIV_IOCTL_80211_STA_KEY_ADD: + CFG80211DRV_StaKeyAdd(pAd, pData); + break; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + case CMD_RTPRIV_IOCTL_80211_P2P_CLIENT_KEY_ADD: + CFG80211DRV_P2pClientKeyAdd(pAd, pData); + break; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + case CMD_RTPRIV_IOCTL_80211_POWER_MGMT_SET: + CFG80211_setPowerMgmt(pAd, Data); + break; + +#ifdef CONFIG_STA_SUPPORT + case CMD_RTPRIV_IOCTL_80211_STA_KEY_DEFAULT_SET: + CFG80211_setStaDefaultKey(pAd, Data); + break; + +#ifdef DOT11W_PMF_SUPPORT + case CMD_RTPRIV_IOCTL_80211_STA_MGMT_KEY_DEFAULT_SET: + CFG80211_setStaMgmtDefaultKey(pAd, Data); + break; +#endif /* DOT11W_PMF_SUPPORT*/ + +#endif /*CONFIG_STA_SUPPORT*/ + case CMD_RTPRIV_IOCTL_80211_CONNECT_TO: +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (Data == RT_CMD_80211_IFTYPE_P2P_CLIENT) + CFG80211DRV_P2pClientConnect(pAd, pData); + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + CFG80211DRV_Connect(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_REG_NOTIFY_TO: + CFG80211DRV_RegNotify(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_UNREGISTER: + CFG80211_UnRegister(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_BANDINFO_GET: + { + CFG80211_BAND *pBandInfo = (CFG80211_BAND *)pData; + CFG80211_BANDINFO_FILL(pAd, pBandInfo); + } + break; + + case CMD_RTPRIV_IOCTL_80211_SURVEY_GET: + CFG80211DRV_SurveyGet(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_EXTRA_IES_SET: + CFG80211DRV_OpsScanExtraIesSet(pAd); + break; + + case CMD_RTPRIV_IOCTL_80211_REMAIN_ON_CHAN_SET: + CFG80211DRV_OpsRemainOnChannel(pAd, pData, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_CANCEL_REMAIN_ON_CHAN_SET: + CFG80211DRV_OpsCancelRemainOnChannel(pAd, Data); + break; + + /* CFG_TODO */ + case CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_REG: + CFG80211DRV_OpsMgmtFrameProbeRegister(pAd, pData, Data); + break; + + /* CFG_TODO */ + case CMD_RTPRIV_IOCTL_80211_ACTION_FRAME_REG: + CFG80211DRV_OpsMgmtFrameActionRegister(pAd, pData, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_CHANNEL_LOCK: + CFG80211_SwitchTxChannel(pAd, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_CHANNEL_RESTORE: + break; + + case CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_SEND: + CFG80211_SendMgmtFrame(pAd, pData, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_CHANNEL_LIST_SET: + return CFG80211DRV_OpsScanSetSpecifyChannel(pAd,pData, Data); + +#ifdef CONFIG_AP_SUPPORT + case CMD_RTPRIV_IOCTL_80211_BEACON_SET: + CFG80211DRV_OpsBeaconSet(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_BEACON_ADD: + CFG80211DRV_OpsBeaconAdd(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_BEACON_DEL: + { + INT i; + for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++) + pAd->ApCfg.MBSSID[MAIN_MBSSID].TimBitmaps[i] = 0; + if (pAd->cfg80211_ctrl.beacon_tail_buf != NULL) + { + os_free_mem(NULL, pAd->cfg80211_ctrl.beacon_tail_buf); + pAd->cfg80211_ctrl.beacon_tail_buf = NULL; + } + pAd->cfg80211_ctrl.beacon_tail_len = 0; + } + break; + + case CMD_RTPRIV_IOCTL_80211_AP_KEY_ADD: + CFG80211DRV_ApKeyAdd(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_RTS_THRESHOLD_ADD: + CFG80211DRV_RtsThresholdAdd(pAd, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_FRAG_THRESHOLD_ADD: + CFG80211DRV_FragThresholdAdd(pAd, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_AP_KEY_DEL: + CFG80211DRV_ApKeyDel(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_AP_KEY_DEFAULT_SET: + CFG80211_setApDefaultKey(pAd, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_PORT_SECURED: + CFG80211_StaPortSecured(pAd, pData, Data); + break; + + case CMD_RTPRIV_IOCTL_80211_AP_STA_DEL: + CFG80211_ApStaDel(pAd, pData); + break; +#endif /* CONFIG_AP_SUPPORT */ + + case CMD_RTPRIV_IOCTL_80211_CHANGE_BSS_PARM: + CFG80211DRV_OpsChangeBssParm(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_AP_PROBE_RSP_EXTRA_IE: + break; + + case CMD_RTPRIV_IOCTL_80211_BITRATE_SET: + break; + + case CMD_RTPRIV_IOCTL_80211_RESET: + CFG80211_reSetToDefault(pAd); + break; + + case CMD_RTPRIV_IOCTL_80211_NETDEV_EVENT: + { + /* + CFG_TODO: For Scan_req per netdevice + struct wireless_dev *pWdev = pAd->pCfg80211_CB->pCfg80211_Wdev; + if (RTMPEqualMemory(pNetDev->dev_addr, pNewNetDev->dev_addr, MAC_ADDR_LEN)) + */ + PNET_DEV pNetDev = (PNET_DEV) pData; + if (pAd->cfg80211_ctrl.FlgCfg80211Scanning == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("CFG_SCAN: close the scan cmd in device close phase\n")); + CFG80211OS_ScanEnd(pAd->pCfg80211_CB, TRUE); + pAd->cfg80211_ctrl.FlgCfg80211Scanning = FALSE; + } + } + break; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + case CMD_RTPRIV_IOCTL_80211_P2PCLI_ASSSOC_IE_SET: + CFG80211DRV_SetP2pCliAssocIe(pAd, pData, Data); + break; +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + case CMD_RTPRIV_IOCTL_80211_VIF_ADD: + if (CFG80211DRV_OpsVifAdd(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_80211_VIF_DEL: + RTMP_CFG80211_VirtualIF_Remove(pAd, pData, Data); + break; + + +#ifdef RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT + case CMD_RTPRIV_IOCTL_80211_ANDROID_PRIV_CMD: + //rt_android_private_command_entry(pAd, ); + break; +#endif /* RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT */ + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + case CMD_RTPRIV_IOCTL_80211_SEND_WIRELESS_EVENT: + CFG80211_SendWirelessEvent(pAd, pData); + break; +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + +#ifdef RFKILL_HW_SUPPORT + case CMD_RTPRIV_IOCTL_80211_RFKILL: + { + UINT32 data = 0; + BOOLEAN active; + + /* Read GPIO pin2 as Hardware controlled radio state */ + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); + active = !!(data & 0x04); + + if (!active) + { + RTMPSetLED(pAd, LED_RADIO_OFF); + *(UINT8 *)pData = 0; + } + else + *(UINT8 *)pData = 1; + } + break; +#endif /* RFKILL_HW_SUPPORT */ + + default: + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + +VOID CFG80211DRV_OpsMgmtFrameProbeRegister( + VOID *pAdOrg, + VOID *pData, + BOOLEAN isReg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pAdOrg; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + PNET_DEV pNewNetDev = (PNET_DEV) pData; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + /* Search the CFG80211 VIF List First */ + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + while (pDevEntry != NULL) + { + if (RTMPEqualMemory(pDevEntry->net_dev->dev_addr, pNewNetDev->dev_addr, MAC_ADDR_LEN)) + break; + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } + + /* Check The Registration is for VIF Device */ + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + (pDevEntry != NULL)) + { + if (isReg) + pDevEntry->Cfg80211ProbeReqCount++; + else + pDevEntry->Cfg80211ProbeReqCount--; + + if (pDevEntry->Cfg80211ProbeReqCount > 0) + pDevEntry->Cfg80211RegisterProbeReqFrame = TRUE; + else + pDevEntry->Cfg80211RegisterProbeReqFrame = FALSE; + +#ifndef RT_CFG80211_P2P_STATIC_CONCURRENT_DEVICE + return; +#endif /* RT_CFG80211_P2P_STATIC_CONCURRENT_DEVICE */ + + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* IF Not Exist on VIF List, the device must be MAIN_DEV */ + if (isReg) + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount++; + else + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount--; + + if (pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount > 0) + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterProbeReqFrame = TRUE; + else + { + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterProbeReqFrame = FALSE; + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount = 0; + } + + DBGPRINT(RT_DEBUG_INFO, ("[%d] pAd->Cfg80211RegisterProbeReqFrame=%d[%d]\n", + isReg, pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterProbeReqFrame, + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount)); +} + +VOID CFG80211DRV_OpsMgmtFrameActionRegister( + VOID *pAdOrg, + VOID *pData, + BOOLEAN isReg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pAdOrg; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + PNET_DEV pNewNetDev = (PNET_DEV) pData; + PLIST_HEADER pCacheList = &pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList; + PCFG80211_VIF_DEV pDevEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + /* Search the CFG80211 VIF List First */ + pListEntry = pCacheList->pHead; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + while (pDevEntry != NULL) + { + if (RTMPEqualMemory(pDevEntry->net_dev->dev_addr, pNewNetDev->dev_addr, MAC_ADDR_LEN)) + break; + + pListEntry = pListEntry->pNext; + pDevEntry = (PCFG80211_VIF_DEV)pListEntry; + } + + /* Check The Registration is for VIF Device */ + if ((pAd->cfg80211_ctrl.Cfg80211VifDevSet.vifDevList.size > 0) && + (pDevEntry != NULL)) + { + if (isReg) + pDevEntry->Cfg80211ActionCount++; + else + pDevEntry->Cfg80211ActionCount--; + + if (pDevEntry->Cfg80211ActionCount > 0) + pDevEntry->Cfg80211RegisterActionFrame = TRUE; + else + pDevEntry->Cfg80211RegisterActionFrame = FALSE; + + DBGPRINT(RT_DEBUG_INFO, ("[%d] TYPE pDevEntry->Cfg80211RegisterActionFrame=%d[%d]\n", + isReg, pDevEntry->Cfg80211RegisterActionFrame, pDevEntry->Cfg80211ActionCount)); + + return; + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* IF Not Exist on VIF List, the device must be MAIN_DEV */ + if (isReg) + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount++; + else + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount--; + + if (pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount > 0) + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterActionFrame = TRUE; + else + { + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterActionFrame = FALSE; + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount = 0; + } + + DBGPRINT(RT_DEBUG_INFO, ("[%d] TYPE pAd->Cfg80211RegisterActionFrame=%d[%d]\n", + isReg, pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterActionFrame, + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount)); +} + +VOID CFG80211DRV_OpsChangeBssParm( + VOID *pAdOrg, + VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_BSS_PARM *pBssInfo; + BOOLEAN TxPreamble; + + CFG80211DBG(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + pBssInfo = (CMD_RTPRIV_IOCTL_80211_BSS_PARM *)pData; + + /* Short Preamble */ + if (pBssInfo->use_short_preamble != -1) + { + CFG80211DBG(RT_DEBUG_TRACE, ("%s: ShortPreamble %d\n", __FUNCTION__, pBssInfo->use_short_preamble)); + pAd->CommonCfg.TxPreamble = (pBssInfo->use_short_preamble == 0 ? Rt802_11PreambleLong : Rt802_11PreambleShort); + TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); + MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); + } + + /* CTS Protection */ + if (pBssInfo->use_cts_prot != -1) + { + CFG80211DBG(RT_DEBUG_TRACE, ("%s: CTS Protection %d\n", __FUNCTION__, pBssInfo->use_cts_prot)); + } + + /* Short Slot */ + if (pBssInfo->use_short_slot_time != -1) + { + CFG80211DBG(RT_DEBUG_TRACE, ("%s: Short Slot %d\n", __FUNCTION__, pBssInfo->use_short_slot_time)); + } +} + +BOOLEAN CFG80211DRV_OpsSetChannel(RTMP_ADAPTER *pAd, VOID *pData) +{ + CMD_RTPRIV_IOCTL_80211_CHAN *pChan; + UINT8 ChanId, IfType, ChannelType; + UCHAR lock_channel; +#ifdef DOT11_N_SUPPORT + BOOLEAN FlgIsChanged; +#endif /* DOT11_N_SUPPORT */ + +/* + * enum nl80211_channel_type { + * NL80211_CHAN_NO_HT, + * NL80211_CHAN_HT20, + * NL80211_CHAN_HT40MINUS, + * NL80211_CHAN_HT40PLUS + * }; + */ + /* init */ + pChan = (CMD_RTPRIV_IOCTL_80211_CHAN *)pData; + ChanId = pChan->ChanId; + IfType = pChan->IfType; + ChannelType = pChan->ChanType; + + if (IfType != RT_CMD_80211_IFTYPE_MONITOR) + { + /* get channel BW */ + FlgIsChanged = TRUE; + + /* set to new channel BW */ + if (ChannelType == RT_CMD_80211_CHANTYPE_HT20) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; + pAd->CommonCfg.HT_Disable = 0; + } + else if (ChannelType == RT_CMD_80211_CHANTYPE_HT40MINUS) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + pAd->CommonCfg.HT_Disable = 0; + } + else if (ChannelType == RT_CMD_80211_CHANTYPE_HT40PLUS) + { + /* not support NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS */ + /* i.e. primary channel = 36, secondary channel must be 40 */ + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + pAd->CommonCfg.HT_Disable = 0; + } + else if (ChannelType == RT_CMD_80211_CHANTYPE_NOHT) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; + pAd->CommonCfg.HT_Disable = 1; + } + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> HT Disable = %d\n", pAd->CommonCfg.HT_Disable)); + } + else + { + /* for monitor mode */ + FlgIsChanged = TRUE; + pAd->CommonCfg.HT_Disable = 0; + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + + if (FlgIsChanged == TRUE) + SetCommonHT(pAd); + + /* switch to the channel with Common Channel */ + pAd->CommonCfg.Channel = ChanId; + pAd->MlmeAux.Channel = ChanId; + + /* CFG_TODO: for CentralChannel setting */ + //lock_channel = N_SetCenCh(pAd, pAd->CommonCfg.Channel); + //pAd->MlmeAux.CentralChannel = lock_channel; + + //if (pAd->LatchRfRegs.Channel != pAd->CommonCfg.Channel) + //{ + // AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + // AsicLockChannel(pAd, pAd->CommonCfg.Channel); + //} + + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + else if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + + bbp_set_bw(pAd, pAd->CommonCfg.RegTransmitSetting.field.BW); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel,FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> New CH = %d, New BW = %d with Ext[%d]\n", + pAd->CommonCfg.CentralChannel, pAd->CommonCfg.RegTransmitSetting.field.BW, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); + + if(IfType == RT_CMD_80211_IFTYPE_AP || + IfType == RT_CMD_80211_IFTYPE_P2P_GO) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Set the channel in AP Mode\n")); + return TRUE; + } +#ifdef CONFIG_STA_SUPPORT + if ((IfType == RT_CMD_80211_IFTYPE_STATION) && (FlgIsChanged == TRUE)) + { + /* + 1. Station mode; + 2. New BW settings is 20MHz but current BW is not 20MHz; + 3. New BW settings is 40MHz but current BW is 20MHz; + + Re-connect to the AP due to BW 20/40 or HT/non-HT change. + */ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Set the channel in STA Mode\n")); + } + + if (IfType == RT_CMD_80211_IFTYPE_ADHOC) + { + /* update IBSS beacon */ + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); + AsicEnableIbssSync(pAd); + + Set_SSID_Proc(pAd, (PSTRING)pAd->CommonCfg.Ssid); + } + + if (IfType == RT_CMD_80211_IFTYPE_MONITOR) + { + /* reset monitor mode in the new channel */ + Set_NetworkType_Proc(pAd, "Monitor"); + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, pChan->MonFilterFlag); + } +#endif /*CONFIG_STA_SUPPORT*/ + return TRUE; +} + +BOOLEAN CFG80211DRV_OpsJoinIbss( + VOID *pAdOrg, + VOID *pData) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_IBSS *pIbssInfo; + + + pIbssInfo = (CMD_RTPRIV_IOCTL_80211_IBSS *)pData; + pAd->StaCfg.bAutoReconnect = TRUE; + + pAd->CommonCfg.BeaconPeriod = pIbssInfo->BeaconInterval; + Set_SSID_Proc(pAd, (PSTRING)pIbssInfo->Ssid); +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + +BOOLEAN CFG80211DRV_OpsLeave( + VOID *pAdOrg, + UINT8 IfType) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + + MLME_DEAUTH_REQ_STRUCT DeAuthReq; + MLME_QUEUE_ELEM *pMsgElem = NULL; + + pAd->StaCfg.bAutoReconnect = FALSE; + pAd->cfg80211_ctrl.FlgCfg80211Connecting = FALSE; + + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + os_alloc_mem(pAd, (UCHAR **)&pMsgElem, sizeof(MLME_QUEUE_ELEM)); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (IfType == RT_CMD_80211_IFTYPE_P2P_CLIENT) + COPY_MAC_ADDR(DeAuthReq.Addr, pAd->ApCfg.ApCliTab[MAIN_MBSSID].MlmeAux.Bssid); + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); + + DeAuthReq.Reason = REASON_DEAUTH_STA_LEAVING; + pMsgElem->MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); + NdisMoveMemory(pMsgElem->Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT)); + MlmeDeauthReqAction(pAd, pMsgElem); + os_free_mem(NULL, pMsgElem); + pMsgElem = NULL; + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (IfType == RT_CMD_80211_IFTYPE_P2P_CLIENT) + ApCliLinkDown(pAd, MAIN_MBSSID /*ifIndex*/); + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + LinkDown(pAd, FALSE); + +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + + +BOOLEAN CFG80211DRV_StaGet( + VOID *pAdOrg, + VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_STA *pIbssInfo; + + pIbssInfo = (CMD_RTPRIV_IOCTL_80211_STA *)pData; + +#ifdef CONFIG_AP_SUPPORT +{ + MAC_TABLE_ENTRY *pEntry; + ULONG DataRate = 0; + UINT32 RSSI; + + + pEntry = MacTableLookup(pAd, pIbssInfo->MAC); + if (pEntry == NULL) + return FALSE; + + /* fill tx rate */ + RtmpDrvRateGet(pAd, pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.BW,pEntry->HTPhyMode.field.MCS, + newRateGetAntenna(pEntry->MaxHTPhyMode.field.MCS, pEntry->HTPhyMode.field.MODE),&DataRate); + DataRate /= 500000; + DataRate /= 2; + + if ((pEntry->HTPhyMode.field.MODE == MODE_HTMIX) || + (pEntry->HTPhyMode.field.MODE == MODE_HTGREENFIELD)) + { + if (pEntry->HTPhyMode.field.BW) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_BW_40; + + if (pEntry->HTPhyMode.field.ShortGI) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_SHORT_GI; + + pIbssInfo->TxRateMCS = pEntry->HTPhyMode.field.MCS; + } + else + { + pIbssInfo->TxRateFlags = RT_CMD_80211_TXRATE_LEGACY; + pIbssInfo->TxRateMCS = DataRate*10; /* unit: 100kbps */ + } + + /* fill signal */ + RSSI = RTMPAvgRssi(pAd, &pEntry->RssiSample); + pIbssInfo->Signal = RSSI; + + /* fill tx count */ + pIbssInfo->TxPacketCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + /* fill inactive time */ + pIbssInfo->InactiveTime = pEntry->NoDataIdleCount * 1000; /* unit: ms */ + pIbssInfo->InactiveTime *= MLME_TASK_EXEC_MULTIPLE; + pIbssInfo->InactiveTime /= 20; +} +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +{ + HTTRANSMIT_SETTING PhyInfo; + ULONG DataRate = 0; + UINT32 RSSI; + + + /* fill tx rate */ + if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + { + PhyInfo.word = pAd->StaCfg.wdev.HTPhyMode.word; + } + else + PhyInfo.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; + + RtmpDrvRateGet(pAd, PhyInfo.field.MODE, PhyInfo.field.ShortGI, + PhyInfo.field.BW,PhyInfo.field.MCS, + newRateGetAntenna(PhyInfo.field.MCS, PhyInfo.field.MODE),&DataRate); + DataRate /= 500000; + DataRate /= 2; + + if ((PhyInfo.field.MODE == MODE_HTMIX) || + (PhyInfo.field.MODE == MODE_HTGREENFIELD)) + { + if (PhyInfo.field.BW) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_BW_40; + + if (PhyInfo.field.ShortGI) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_SHORT_GI; + + pIbssInfo->TxRateMCS = PhyInfo.field.MCS; + } + else + { + pIbssInfo->TxRateFlags = RT_CMD_80211_TXRATE_LEGACY; + pIbssInfo->TxRateMCS = DataRate*10; /* unit: 100kbps */ + } + + /* fill signal */ + RSSI = RTMPAvgRssi(pAd, &pAd->StaCfg.RssiSample); + pIbssInfo->Signal = RSSI; +} +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + +BOOLEAN CFG80211DRV_StaKeyAdd( + VOID *pAdOrg, + VOID *pData) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_KEY *pKeyInfo; + + + pKeyInfo = (CMD_RTPRIV_IOCTL_80211_KEY *)pData; +#ifdef DOT11W_PMF_SUPPORT + if (pKeyInfo->KeyType == RT_CMD_80211_KEY_AES_CMAC) + { + PPMF_CFG pPmfCfg = pPmfCfg = &pAd->StaCfg.PmfCfg; + hex_dump("PMF IGTK pKeyInfo->KeyBuf=", (UINT8 *)pKeyInfo->KeyBuf, pKeyInfo->KeyLen); + DBGPRINT(RT_DEBUG_ERROR, ("PMF IGTK pKeyInfo->KeyId=%d\n",pKeyInfo->KeyId)); + + //only 4 or 5, no other case! + if (pKeyInfo->KeyId == 4 || pKeyInfo->KeyId == 5) + { + // no PN is passed, PN is useless in PMF_CalculateBIPMIC() + NdisZeroMemory(&pPmfCfg->IPN[pKeyInfo->KeyId -4][0], LEN_WPA_TSC); + NdisMoveMemory(&pPmfCfg->IGTK[pKeyInfo->KeyId -4][0], pKeyInfo->KeyBuf, pKeyInfo->KeyLen); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR !! pKeyInfo->KeyId=%d \n",pKeyInfo->KeyId)); + + } + + } + else +#endif /* DOT11W_PMF_SUPPORT */ + if (pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP40 || pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP104) + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_CMD_80211_KEY_WEP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc ==> %d, %d, %d...\n", pKeyInfo->KeyId, pKeyInfo->KeyType, strlen(pKeyInfo->KeyBuf))); + + RT_CMD_STA_IOCTL_SECURITY IoctlSec; + + IoctlSec.KeyIdx = pKeyInfo->KeyId; + IoctlSec.pData = pKeyInfo->KeyBuf; + IoctlSec.length = pKeyInfo->KeyLen; + + /* YF@20120327: Due to WepStatus will be set in the cfg connect function.*/ + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11Encryption2Enabled) + IoctlSec.Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP; + else if (pAd->StaCfg.wdev.WepStatus == Ndis802_11Encryption3Enabled) + IoctlSec.Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP; + IoctlSec.flags = RT_CMD_STA_IOCTL_SECURITY_ENABLED; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + if (pKeyInfo->bPairwise == FALSE ) +#else + if (pKeyInfo->KeyId > 0) +#endif + { + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + IoctlSec.Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + IoctlSec.Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP; + + DBGPRINT(RT_DEBUG_TRACE, ("Install GTK: %d\n", IoctlSec.Alg)); + IoctlSec.ext_flags = RT_CMD_STA_IOCTL_SECURTIY_EXT_GROUP_KEY; + } + else + { + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + IoctlSec.Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + IoctlSec.Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP; + + DBGPRINT(RT_DEBUG_TRACE, ("Install PTK: %d\n", IoctlSec.Alg)); + IoctlSec.ext_flags = RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY; + } + + /*Set_GroupKey_Proc(pAd, &IoctlSec) */ + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODEEXT, 0, + &IoctlSec, 0, INT_MAIN); + } +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + +BOOLEAN CFG80211DRV_Connect( + VOID *pAdOrg, + VOID *pData) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_CONNECT *pConnInfo; + UCHAR SSID[NDIS_802_11_LENGTH_SSID + 1]; /* Add One for SSID_Len == 32 */ + UINT32 SSIDLen; + RT_CMD_STA_IOCTL_SECURITY_ADV IoctlWpa; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_INFRA_ON) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211: Connected, disconnect first !\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211: No Connection\n")); + } + + pConnInfo = (CMD_RTPRIV_IOCTL_80211_CONNECT *)pData; + + /* change to infrastructure mode if we are in ADHOC mode */ + Set_NetworkType_Proc(pAd, "Infra"); + + SSIDLen = pConnInfo->SsidLen; + if (SSIDLen > NDIS_802_11_LENGTH_SSID) + { + SSIDLen = NDIS_802_11_LENGTH_SSID; + } + + memset(&SSID, 0, sizeof(SSID)); + memcpy(SSID, pConnInfo->pSsid, SSIDLen); + + if (pConnInfo->bWpsConnection) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS Connection onGoing.....\n")); + /* YF@20120327: Trigger Driver to Enable WPS function. */ + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP |= WPA_SUPPLICANT_ENABLE_WPS; /* Set_Wpa_Support(pAd, "3") */ + Set_AuthMode_Proc(pAd, "OPEN"); + Set_EncrypType_Proc(pAd, "NONE"); + Set_SSID_Proc(pAd, (PSTRING)SSID); + + return TRUE; + } + else + { + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; /* Set_Wpa_Support(pAd, "1")*/ + } + + /* set authentication mode */ + if (pConnInfo->WpaVer == 2) + { + if (pConnInfo->FlgIs8021x == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("WPA2\n")); + Set_AuthMode_Proc(pAd, "WPA2"); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WPA2PSK\n")); + Set_AuthMode_Proc(pAd, "WPA2PSK"); + } + } + else if (pConnInfo->WpaVer == 1) + { + if (pConnInfo->FlgIs8021x == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("WPA\n")); + Set_AuthMode_Proc(pAd, "WPA"); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK\n")); + Set_AuthMode_Proc(pAd, "WPAPSK"); + } + } + else if (pConnInfo->AuthType == Ndis802_11AuthModeAutoSwitch) + Set_AuthMode_Proc(pAd, "WEPAUTO"); + else if (pConnInfo->AuthType == Ndis802_11AuthModeShared) + Set_AuthMode_Proc(pAd, "SHARED"); + else + Set_AuthMode_Proc(pAd, "OPEN"); + + CFG80211DBG(RT_DEBUG_TRACE, + ("80211> AuthMode = %d\n", pAd->StaCfg.wdev.AuthMode)); + + /* set encryption mode */ + if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) + { + DBGPRINT(RT_DEBUG_TRACE, ("AES\n")); + Set_EncrypType_Proc(pAd, "AES"); + } + else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) + { + DBGPRINT(RT_DEBUG_TRACE, ("TKIP\n")); + Set_EncrypType_Proc(pAd, "TKIP"); + } + else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_WEP) + { + DBGPRINT(RT_DEBUG_TRACE, ("WEP\n")); + Set_EncrypType_Proc(pAd, "WEP"); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("NONE\n")); + Set_EncrypType_Proc(pAd, "NONE"); + } + + /* Groupwise Key Information Setting */ + IoctlWpa.flags = RT_CMD_STA_IOCTL_WPA_GROUP; + if (pConnInfo->GroupwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) + { + DBGPRINT(RT_DEBUG_TRACE, ("GTK AES\n")); + IoctlWpa.value = RT_CMD_STA_IOCTL_WPA_GROUP_CCMP; + RtmpIoctl_rt_ioctl_siwauth(pAd, &IoctlWpa, 0); + } + else if (pConnInfo->GroupwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) + { + DBGPRINT(RT_DEBUG_TRACE, ("GTK TKIP\n")); + IoctlWpa.value = RT_CMD_STA_IOCTL_WPA_GROUP_TKIP; + RtmpIoctl_rt_ioctl_siwauth(pAd, &IoctlWpa, 0); + } + + CFG80211DBG(RT_DEBUG_TRACE, + ("80211> EncrypType = %d\n", pAd->StaCfg.wdev.WepStatus)); + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Key = %s\n", pConnInfo->pKey)); + + /* set channel: STATION will auto-scan */ + + /* set WEP key */ + if (pConnInfo->pKey && + ((pConnInfo->GroupwiseEncrypType | pConnInfo->PairwiseEncrypType) & + RT_CMD_80211_CONN_ENCRYPT_WEP)) + { + UCHAR KeyBuf[50]; + + /* reset AuthMode and EncrypType */ + Set_EncrypType_Proc(pAd, "WEP"); + + /* reset key */ +#ifdef RT_CFG80211_DEBUG + hex_dump("KeyBuf=", (UINT8 *)pConnInfo->pKey, pConnInfo->KeyLen); +#endif /* RT_CFG80211_DEBUG */ + + pAd->StaCfg.wdev.DefaultKeyId = pConnInfo->KeyIdx; /* base 0 */ + if (pConnInfo->KeyLen >= sizeof(KeyBuf)) + return FALSE; + + memcpy(KeyBuf, pConnInfo->pKey, pConnInfo->KeyLen); + KeyBuf[pConnInfo->KeyLen] = 0x00; + + CFG80211DBG(RT_DEBUG_ERROR, + ("80211> pAd->StaCfg.DefaultKeyId = %d\n", + pAd->StaCfg.wdev.DefaultKeyId)); + + Set_Wep_Key_Proc(pAd, (PSTRING)KeyBuf, (INT)pConnInfo->KeyLen, (INT)pConnInfo->KeyIdx); + + } /* End of if */ + + /* TODO: We need to provide a command to set BSSID to associate a AP */ + pAd->cfg80211_ctrl.FlgCfg80211Connecting = TRUE; + +#ifdef DOT11W_PMF_SUPPORT + if (pConnInfo->mfp) + { + //Set_PMFSHA256_Proc(pAd,"1"); + Set_PMFMFPC_Proc(pAd,"1"); + } +#endif /* DOT11W_PMF_SUPPORT */ + + Set_SSID_Proc(pAd, (PSTRING)SSID); + CFG80211DBG(RT_DEBUG_TRACE, ("80211> Connecting SSID = %s\n", SSID)); +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + + +VOID CFG80211DRV_RegNotify( + VOID *pAdOrg, + VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_REG_NOTIFY *pRegInfo; + + + pRegInfo = (CMD_RTPRIV_IOCTL_80211_REG_NOTIFY *)pData; + + /* keep Alpha2 and we can re-call the function when interface is up */ + pAd->cfg80211_ctrl.Cfg80211_Alpha2[0] = pRegInfo->Alpha2[0]; + pAd->cfg80211_ctrl.Cfg80211_Alpha2[1] = pRegInfo->Alpha2[1]; + + /* apply the new regulatory rule */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + /* interface is up */ + CFG80211_RegRuleApply(pAd, pRegInfo->pWiphy, (UCHAR *)pRegInfo->Alpha2); + } + else + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> interface is down!\n")); + } +} + + +VOID CFG80211DRV_SurveyGet( + VOID *pAdOrg, + VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_SURVEY *pSurveyInfo; + + + pSurveyInfo = (CMD_RTPRIV_IOCTL_80211_SURVEY *)pData; + + pSurveyInfo->pCfg80211 = pAd->pCfg80211_CB; + +#ifdef AP_QLOAD_SUPPORT + pSurveyInfo->ChannelTimeBusy = pAd->phy_ctrl.QloadLatestChannelBusyTimePri; + pSurveyInfo->ChannelTimeExtBusy = pAd->phy_ctrl.QloadLatestChannelBusyTimeSec; +#endif /* AP_QLOAD_SUPPORT */ +} + + +VOID CFG80211_UnRegister( + IN VOID *pAdOrg, + IN VOID *pNetDev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + + /* sanity check */ + if (pAd->pCfg80211_CB == NULL) + return; + + + CFG80211OS_UnRegister(pAd->pCfg80211_CB, pNetDev); + RTMP_DRIVER_80211_SCAN_STATUS_LOCK_INIT(pAd, FALSE); + unregister_netdevice_notifier(&cfg80211_netdev_notifier); + + /* Reset CFG80211 Global Setting Here */ + DBGPRINT(RT_DEBUG_TRACE, ("==========> TYPE Reset CFG80211 Global Setting Here <==========\n")); + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterActionFrame = FALSE, + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount = 0; + + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterProbeReqFrame = FALSE; + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount = 0; + + pAd->pCfg80211_CB = NULL; + pAd->CommonCfg.HT_Disable = 0; + + /* It should be free when ScanEnd, + But Hit close the device in Scanning */ + if (pCfg80211_ctrl->pCfg80211ChanList != NULL) + { + os_free_mem(NULL, pCfg80211_ctrl->pCfg80211ChanList); + pCfg80211_ctrl->pCfg80211ChanList = NULL; + } + + pCfg80211_ctrl->Cfg80211ChanListLen = 0; + pCfg80211_ctrl->Cfg80211CurChanIndex = 0; + + if(pCfg80211_ctrl->pExtraIe) + { + os_free_mem(NULL, pCfg80211_ctrl->pExtraIe); + pCfg80211_ctrl->pExtraIe = NULL; + } + pCfg80211_ctrl->ExtraIeLen = 0; + + if(pCfg80211_ctrl->pAssocRspIe) + { + os_free_mem(NULL, pCfg80211_ctrl->pAssocRspIe); + pCfg80211_ctrl->pAssocRspIe = NULL; + } + pCfg80211_ctrl->assocRspIeLen = 0; + +/* +CFG_TODO + if (pAd->pTxStatusBuf != NULL) + { + os_free_mem(NULL, pAd->pTxStatusBuf); + pAd->pTxStatusBuf = NULL; + } + pAd->TxStatusBufLen = 0; +*/ +#ifdef CONFIG_AP_SUPPORT + if (pAd->cfg80211_ctrl.beacon_tail_buf != NULL) + { + os_free_mem(NULL, pAd->cfg80211_ctrl.beacon_tail_buf); + pAd->cfg80211_ctrl.beacon_tail_buf = NULL; + } + pAd->cfg80211_ctrl.beacon_tail_len = 0; + +#endif /* CONFIG_AP_SUPPORT */ + +} + + +/* +======================================================================== +Routine Description: + Parse and handle country region in beacon from associated AP. + +Arguments: + pAdCB - WLAN control block pointer + pVIE - Beacon elements + LenVIE - Total length of Beacon elements + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID CFG80211_BeaconCountryRegionParse( + IN VOID *pAdCB, + IN NDIS_802_11_VARIABLE_IEs *pVIE, + IN UINT16 LenVIE) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + UCHAR *pElement = (UCHAR *)pVIE; + UINT32 LenEmt; + + + while(LenVIE > 0) + { + pVIE = (NDIS_802_11_VARIABLE_IEs *)pElement; + + if (pVIE->ElementID == IE_COUNTRY) + { + /* send command to do regulation hint only when associated */ + RT_CFG80211_CRDA_REG_HINT11D(pAd, pVIE->data, pVIE->Length); + //RTEnqueueInternalCmd(pAd, CMDTHREAD_REG_HINT_11D, + // pVIE->data, pVIE->Length); + break; + } + + LenEmt = pVIE->Length + 2; + + if (LenVIE <= LenEmt) + break; /* length is not enough */ + + pElement += LenEmt; + LenVIE -= LenEmt; + } +} /* End of CFG80211_BeaconCountryRegionParse */ + +/* +======================================================================== +Routine Description: + Re-Initialize wireless channel/PHY in 2.4GHZ and 5GHZ. + +Arguments: + pAdCB - WLAN control block pointer + +Return Value: + NONE + +Note: + CFG80211_SupBandInit() is called in xx_probe(). +======================================================================== +*/ +#ifdef CONFIG_STA_SUPPORT +VOID CFG80211_LostApInform( + IN VOID *pAdCB) +{ + + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_CB *p80211CB = pAd->pCfg80211_CB; + + + pAd->StaCfg.bAutoReconnect = FALSE; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) + DBGPRINT(RT_DEBUG_TRACE, ("80211> CFG80211_LostApInform \n")); + cfg80211_disconnected(pAd->net_dev, 0, NULL, 0, GFP_KERNEL); +#else + DBGPRINT(RT_DEBUG_TRACE, ("80211> CFG80211_LostApInform ==> %d\n", + p80211CB->pCfg80211_Wdev->sme_state)); + if (p80211CB->pCfg80211_Wdev->sme_state == CFG80211_SME_CONNECTING) + { + cfg80211_connect_result(pAd->net_dev, NULL, NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); + } + else if (p80211CB->pCfg80211_Wdev->sme_state == CFG80211_SME_CONNECTED) + { + cfg80211_disconnected(pAd->net_dev, 0, NULL, 0, GFP_KERNEL); + } +#endif /* LINUX_VERSION_CODE: 3,11,0 */ + +} +#endif /*CONFIG_STA_SUPPORT*/ + + + +/* +======================================================================== +Routine Description: + Hint to the wireless core a regulatory domain from driver. + +Arguments: + pAd - WLAN control block pointer + pCountryIe - pointer to the country IE + CountryIeLen - length of the country IE + +Return Value: + NONE + +Note: + Must call the function in kernel thread. +======================================================================== +*/ +VOID CFG80211_RegHint( + IN VOID *pAdCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + + CFG80211OS_RegHint(CFG80211CB, pCountryIe, CountryIeLen); +} + + +/* +======================================================================== +Routine Description: + Hint to the wireless core a regulatory domain from country element. + +Arguments: + pAdCB - WLAN control block pointer + pCountryIe - pointer to the country IE + CountryIeLen - length of the country IE + +Return Value: + NONE + +Note: + Must call the function in kernel thread. +======================================================================== +*/ +VOID CFG80211_RegHint11D( + IN VOID *pAdCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen) +{ + /* no regulatory_hint_11d() in 2.6.32 */ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + + CFG80211OS_RegHint11D(CFG80211CB, pCountryIe, CountryIeLen); +} + + +/* +======================================================================== +Routine Description: + Apply new regulatory rule. + +Arguments: + pAdCB - WLAN control block pointer + pWiphy - Wireless hardware description + pAlpha2 - Regulation domain (2B) + +Return Value: + NONE + +Note: + Can only be called when interface is up. + + For general mac80211 device, it will be set to new power by Ops->config() + In rt2x00/, the settings is done in rt2x00lib_config(). +======================================================================== +*/ +VOID CFG80211_RegRuleApply( + IN VOID *pAdCB, + IN VOID *pWiphy, + IN UCHAR *pAlpha2) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + VOID *pBand24G, *pBand5G; + UINT32 IdBand, IdChan, IdPwr; + UINT32 ChanNum, ChanId, Power, RecId, DfsType; + BOOLEAN FlgIsRadar; + ULONG IrqFlags; +#ifdef DFS_SUPPORT + RADAR_DETECT_STRUCT *pRadarDetect; +#endif /* DFS_SUPPORT */ + + + CFG80211DBG(RT_DEBUG_TRACE, ("crda> CFG80211_RegRuleApply ==>\n")); + + /* init */ + pBand24G = NULL; + pBand5G = NULL; + + if (pAd == NULL) + return; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + /* zero first */ + NdisZeroMemory(pAd->ChannelList, + MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); + + /* 2.4GHZ & 5GHz */ + RecId = 0; +#ifdef DFS_SUPPORT + pRadarDetect = &pAd->CommonCfg.RadarDetect; +#endif /* DFS_SUPPORT */ + + /* find the DfsType */ + DfsType = CE; + + pBand24G = NULL; + pBand5G = NULL; + + if (CFG80211OS_BandInfoGet(CFG80211CB, pWiphy, &pBand24G, &pBand5G) == FALSE) + return; + +#ifdef EXT_BUILD_CHANNEL_LIST + if ((pAlpha2[0] != '0') && (pAlpha2[1] != '0')) + { + UINT32 IdReg; + + if (pBand5G != NULL) + { + for(IdReg=0; ; IdReg++) + { + if (ChRegion[IdReg].CountReg[0] == 0x00) + break; + + if ((pAlpha2[0] == ChRegion[IdReg].CountReg[0]) && + (pAlpha2[1] == ChRegion[IdReg].CountReg[1])) + { + if (pAd->CommonCfg.DfsType != MAX_RD_REGION) + DfsType = pAd->CommonCfg.DfsType; + else + DfsType = ChRegion[IdReg].DfsType; + + CFG80211DBG(RT_DEBUG_TRACE, + ("crda> find region %c%c, DFS Type %d\n", + pAlpha2[0], pAlpha2[1], DfsType)); + break; + } + } + } + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + + for(IdBand=0; IdBand<2; IdBand++) + { + if (((IdBand == 0) && (pBand24G == NULL)) || + ((IdBand == 1) && (pBand5G == NULL))) + { + continue; + } + + if (IdBand == 0) + { + CFG80211DBG(RT_DEBUG_TRACE, ("crda> reset chan/power for 2.4GHz\n")); + } + else + { + CFG80211DBG(RT_DEBUG_TRACE, ("crda> reset chan/power for 5GHz\n")); + } + + ChanNum = CFG80211OS_ChanNumGet(CFG80211CB, pWiphy, IdBand); + + for(IdChan=0; IdChanCommonCfg.PhyMode)) + { + /* 5G-only mode */ + if (ChanId <= CFG80211_NUM_OF_CHAN_2GHZ) + continue; + } + + if (!WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + /* 2.4G-only mode */ + if (ChanId > CFG80211_NUM_OF_CHAN_2GHZ) + continue; + } + + for(IdPwr=0; IdPwrTxPower[IdPwr].Channel) + { + /* init the channel info. */ + NdisMoveMemory(&pAd->ChannelList[RecId], + &pAd->TxPower[IdPwr], + sizeof(CHANNEL_TX_POWER)); + + /* keep channel number */ + pAd->ChannelList[RecId].Channel = ChanId; + + /* keep maximum tranmission power */ + pAd->ChannelList[RecId].MaxTxPwr = Power; + + /* keep DFS flag */ + if (FlgIsRadar == TRUE) + pAd->ChannelList[RecId].DfsReq = TRUE; + else + pAd->ChannelList[RecId].DfsReq = FALSE; + + /* keep DFS type */ + pAd->ChannelList[RecId].RegulatoryDomain = DfsType; + + /* re-set DFS info. */ + pAd->CommonCfg.RDDurRegion = DfsType; + + CFG80211DBG(RT_DEBUG_TRACE, + ("Chan %03d:\tpower %d dBm, " + "DFS %d, DFS Type %d\n", + ChanId, Power, + ((FlgIsRadar == TRUE)?1:0), + DfsType)); + + /* change to record next channel info. */ + RecId ++; + break; + } + } + } + } + + pAd->ChannelListNum = RecId; + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + CFG80211DBG(RT_DEBUG_TRACE, ("crda> Number of channels = %d\n", RecId)); +} /* End of CFG80211_RegRuleApply */ + +/* +======================================================================== +Routine Description: + Inform CFG80211 about association status. + +Arguments: + pAdCB - WLAN control block pointer + pBSSID - the BSSID of the AP + pReqIe - the element list in the association request frame + ReqIeLen - the request element length + pRspIe - the element list in the association response frame + RspIeLen - the response element length + FlgIsSuccess - 1: success; otherwise: fail + +Return Value: + None + +Note: +======================================================================== +*/ +VOID CFG80211_ConnectResultInform( + IN VOID *pAdCB, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211_ConnectResultInform ==>\n")); + + CFG80211OS_ConnectResultInform(CFG80211CB, + pBSSID, + pReqIe, + ReqIeLen, + pRspIe, + RspIeLen, + FlgIsSuccess); + + pAd->cfg80211_ctrl.FlgCfg80211Connecting = FALSE; +} /* End of CFG80211_ConnectResultInform */ + + + + +/* +======================================================================== +Routine Description: + Re-Initialize wireless channel/PHY in 2.4GHZ and 5GHZ. + +Arguments: + pAdCB - WLAN control block pointer + +Return Value: + TRUE - re-init successfully + FALSE - re-init fail + +Note: + CFG80211_SupBandInit() is called in xx_probe(). + But we do not have complete chip information in xx_probe() so we + need to re-init bands in xx_open(). +======================================================================== +*/ +BOOLEAN CFG80211_SupBandReInit( + IN VOID *pAdCB) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_BAND BandInfo; + + + CFG80211DBG(RT_DEBUG_TRACE, ("80211> re-init bands...\n")); + + /* re-init bands */ + NdisZeroMemory(&BandInfo, sizeof(BandInfo)); + CFG80211_BANDINFO_FILL(pAd, &BandInfo); + + return CFG80211OS_SupBandReInit(CFG80211CB, &BandInfo); +} /* End of CFG80211_SupBandReInit */ + +#ifdef CONFIG_STA_SUPPORT +//CMD_RTPRIV_IOCTL_80211_KEY_DEFAULT_SET: +INT CFG80211_setStaDefaultKey( + IN VOID *pAdCB, + IN UINT Data +) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + DBGPRINT(RT_DEBUG_TRACE, ("Set Sta Default Key: %d\n", Data)); + pAd->StaCfg.wdev.DefaultKeyId = Data; /* base 0 */ + return 0; +} + +#ifdef DOT11W_PMF_SUPPORT +INT CFG80211_setStaMgmtDefaultKey( + IN VOID *pAdCB, + IN UINT Data +) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + + DBGPRINT(RT_DEBUG_TRACE, ("Set Sta MgmtDefault Key: %d\n", Data)); + //pAd->StaCfg.wdev.MgmtDefaultKeyId = Data; /* base 0 */ + return 0; +} +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /*CONFIG_STA_SUPPORT*/ +INT CFG80211_reSetToDefault( + IN VOID *pAdCB) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; + DBGPRINT(RT_DEBUG_TRACE, (" %s\n", __FUNCTION__)); +#ifdef CONFIG_STA_SUPPORT + /* Driver Internal Parm */ + pAd->StaCfg.bAutoConnectByBssid = FALSE; +#endif /*CONFIG_STA_SUPPORT*/ + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterProbeReqFrame = FALSE; + pCfg80211_ctrl->cfg80211MainDev.Cfg80211RegisterActionFrame = FALSE; + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ProbeReqCount = 0; + pCfg80211_ctrl->cfg80211MainDev.Cfg80211ActionCount = 0; + + pCfg80211_ctrl->Cfg80211RocTimerInit = FALSE; + pCfg80211_ctrl->Cfg80211RocTimerRunning = FALSE; + pCfg80211_ctrl->FlgCfg80211Scanning = FALSE; + + return TRUE; +} + +/* +initList(&pAd->Cfg80211VifDevSet.vifDevList); +initList(&pAd->cfg80211_ctrl.cfg80211TxPacketList); +*/ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE +BOOLEAN CFG80211_checkScanResInKernelCache( + IN VOID *pAdCB, + IN UCHAR *pBSSID, + IN UCHAR *pSsid, + IN INT ssidLen) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pAd->pCfg80211_CB; + struct wiphy *pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + struct cfg80211_bss *bss; + + bss = cfg80211_get_bss(pWiphy, NULL, pBSSID, + pSsid, ssidLen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (bss) + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + cfg80211_put_bss(pWiphy, bss); +#else + cfg80211_put_bss(bss); +#endif + return TRUE; + } + + return FALSE; +} + +BOOLEAN CFG80211_checkScanTable( + IN VOID *pAdCB) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pAd->pCfg80211_CB; + struct wiphy *pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + ULONG bss_idx = BSS_NOT_FOUND; + struct cfg80211_bss *bss; + struct ieee80211_channel *chan; + UINT32 CenFreq; + UINT64 timestamp; + struct timeval tv; + UCHAR *ie, ieLen = 0; + BOOLEAN isOk = FALSE; + BSS_ENTRY *pBssEntry; + + USHORT ifIndex = 0; + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + + if (MAC_ADDR_EQUAL(pApCliEntry->MlmeAux.Bssid, ZERO_MAC_ADDR)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("pAd->ApCliMlmeAux.Bssid ==> ZERO_MAC_ADDR\n")); + //ToDo: pAd->ApCfg.ApCliTab[0].CfgApCliBssid + return FALSE; + } + + /* Fake TSF */ + do_gettimeofday(&tv); + timestamp = ((UINT64)tv.tv_sec * 1000000) + tv.tv_usec; + + bss = cfg80211_get_bss(pWiphy, NULL, pApCliEntry->MlmeAux.Bssid, + pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.SsidLen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (bss) + { + DBGPRINT(RT_DEBUG_TRACE, ("Found %s in Kernel_ScanTable with CH[%d]\n", pApCliEntry->MlmeAux.Ssid, bss->channel->center_freq)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + cfg80211_put_bss(pWiphy, bss); +#else + bss->tsf = timestamp; + cfg80211_put_bss(bss); +#endif + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't Found %s in Kernel_ScanTable & Try Fake it\n", pApCliEntry->MlmeAux.Ssid)); + } + + bss_idx = BssSsidTableSearchBySSID(&pAd->ScanTab, pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.SsidLen); + + if (bss_idx != BSS_NOT_FOUND) + { + /* Since the cfg80211 kernel scanTable not exist this Entry, + * Build an Entry for this connect inform event. + */ + + pBssEntry = &pAd->ScanTab.BssEntry[bss_idx]; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) + if (pAd->ScanTab.BssEntry[bss_idx].Channel > 14) + CenFreq = ieee80211_channel_to_frequency(pBssEntry->Channel , IEEE80211_BAND_5GHZ); + else + CenFreq = ieee80211_channel_to_frequency(pBssEntry->Channel , IEEE80211_BAND_2GHZ); +#else + CenFreq = ieee80211_channel_to_frequency(pBssEntry->Channel); +#endif + chan = ieee80211_get_channel(pWiphy, CenFreq); + + ieLen = 2 + pApCliEntry->MlmeAux.SsidLen + pBssEntry->VarIeFromProbeRspLen; + + os_alloc_mem(NULL, (UCHAR **)&ie, ieLen); + if (!ie) + { + CFG80211DBG(RT_DEBUG_ERROR, ("Memory Allocate Fail in CFG80211_checkScanTable\n")); + return FALSE; + } + + ie[0] = WLAN_EID_SSID; + ie[1] = pApCliEntry->MlmeAux.SsidLen; + NdisCopyMemory(ie + 2, pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.SsidLen); + NdisCopyMemory(ie + 2 + pApCliEntry->MlmeAux.SsidLen, pBssEntry->pVarIeFromProbRsp, + pBssEntry->VarIeFromProbeRspLen); + + bss = cfg80211_inform_bss(pWiphy, chan, + pApCliEntry->MlmeAux.Bssid, timestamp, WLAN_CAPABILITY_ESS, pApCliEntry->MlmeAux.BeaconPeriod, + ie, ieLen, +#ifdef CFG80211_SCAN_SIGNAL_AVG + (pBssEntry->AvgRssi * 100), +#else + (pBssEntry->Rssi * 100), +#endif + GFP_KERNEL); + if (bss) + { + printk("Fake New %s(%02x:%02x:%02x:%02x:%02x:%02x) in Kernel_ScanTable with CH[%d][%d] BI:%d len:%d\n", + pApCliEntry->MlmeAux.Ssid, + PRINT_MAC(pApCliEntry->MlmeAux.Bssid),bss->channel->center_freq, pBssEntry->Channel, + pApCliEntry->MlmeAux.BeaconPeriod, pBssEntry->VarIeFromProbeRspLen); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + cfg80211_put_bss(pWiphy, bss); +#else + cfg80211_put_bss(bss); +#endif + isOk = TRUE; + } + + if (ie != NULL) + os_free_mem(NULL, ie); + + if (isOk) + return TRUE; + } + else + printk("%s Not In Driver Scan Table\n", pApCliEntry->MlmeAux.Ssid); + + return FALSE; +} +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + +//CFG_TODO +UCHAR CFG80211_getCenCh(RTMP_ADAPTER *pAd, UCHAR prim_ch) +{ + UCHAR ret_channel; + + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + ret_channel = prim_ch + 2; + else + { + if (prim_ch == 14) + ret_channel = prim_ch - 1; + else + ret_channel = prim_ch - 2; + } + } + else + ret_channel = prim_ch; + + return ret_channel; +} + +#endif /* RT_CFG80211_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/inf_ppa.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/inf_ppa.c new file mode 100644 index 000000000..b0cbee312 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/inf_ppa.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * 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: + inf_ppa.c + + Abstract: + Only for Infineon PPA Direct path feature. + + + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + carella 06-01-2010 Created + + */ + +#ifdef INF_PPA_SUPPORT + +#include "rt_config.h" +#include +#include + +extern INT rt28xx_send_packets(struct sk_buff *skb_p, struct net_device *net_dev); + +int ifx_ra_start_xmit(struct net_device *rx_dev, struct net_device *tx_dev, struct sk_buff *skb, int len) +{ + if(tx_dev != NULL) + { + SET_OS_PKT_NETDEV(skb, tx_dev); + rt28xx_send_packets(skb, tx_dev); + } + else if(rx_dev != NULL) + { + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); + } + else + { + dev_kfree_skb_any(skb); + } + return 0; +} +#endif /* INF_PPA_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/multi_main_dev.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/multi_main_dev.c new file mode 100644 index 000000000..5e50d829d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/multi_main_dev.c @@ -0,0 +1,80 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifdef MULTI_INF_SUPPORT + +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +#include + + +/* Index 0 for 2.4G, 1 for 5Ghz Card */ +VOID* pAdGlobalList[2] = {NULL, NULL}; +/* + Driver module load/unload function +*/ +static int __init wifi_drv_init_module(void) +{ + int status = 0; + +#ifdef RTMP_PCI_SUPPORT + status = rt_pci_init_module(); + if (status) + printk("Register PCI device driver failed(%d)!\n", status); +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef RTMP_RBUS_SUPPORT + status = rt2880_module_init(); + if (status) + printk("Register RBUS device driver failed(%d)!\n", status); +#endif /* RTMP_RBUS_SUPPORT */ + + return status; +} + + +static void __exit wifi_drv_cleanup_module(void) +{ +#ifdef RTMP_PCI_SUPPORT + rt_pci_cleanup_module(); + printk("Unregister PCI device driver\n"); +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef RTMP_RBUS_SUPPORT + rt2880_module_exit(); +#endif /* RTMP_RBUS_SUPPORT */ +} + + +module_init(wifi_drv_init_module); +module_exit(wifi_drv_cleanup_module); + +#endif /* MULTI_INF_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/pci_main_dev.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/pci_main_dev.c new file mode 100644 index 000000000..e310a2234 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/pci_main_dev.c @@ -0,0 +1,550 @@ +/* + *************************************************************************** + * 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: + pci_main_dev.c + + Abstract: + Create and register network interface for PCI based chipsets in Linux platform. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#define RTMP_MODULE_OS + +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +#include + +#ifdef MULTI_INF_SUPPORT +/* Index 0 for 2.4G, 1 for 5Ghz Card */ +extern VOID* pAdGlobalList[2]; +#endif /* MULTI_INF_SUPPORT */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +#define DEVEXIT +#define DEVEXIT_P +#define DEVINIT +#define DEVINITDATA +#else +#define DEVEXIT __devexit +#define DEVEXIT_P __devexit_p +#define DEVINIT __devinit +#define DEVINITDATA __devinitdata +#endif + +/* + Ralink PCI device table, include all supported chipsets +*/ +static struct pci_device_id rt_pci_tbl[] DEVINITDATA = +{ +#ifdef RT8592 + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC8592_PCIe_DEVICE_ID)}, +#endif /* RT8592 */ +#ifdef MT76x2 + {PCI_DEVICE(0x1400, NIC7662_PCIe_DEVICE_ID)}, + {PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7662_PCIe_DEVICE_ID)}, + {PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7632_PCIe_DEVICE_ID)}, + {PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7612_PCIe_DEVICE_ID)}, + {PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7602_PCIe_DEVICE_ID)}, +#endif /* MT76x2 */ + {} /* terminate list */ +}; + +MODULE_DEVICE_TABLE(pci, rt_pci_tbl); + + +/*************************************************************************** + * + * PCI device initialization related procedures. + * + ***************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifdef CONFIG_PM + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) +#define pm_message_t u32 +#endif + +static int rt_pci_suspend(struct pci_dev *pci_dev, pm_message_t state) +{ + struct net_device *net_dev = pci_get_drvdata(pci_dev); + VOID *pAd = NULL; + INT32 retval = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("===>%s()\n", __FUNCTION__)); + + if (net_dev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); + } + else + { + ULONG IfNum; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* we can not use IFF_UP because ra0 down but ra1 up */ + /* and 1 suspend/resume function for 1 module, not for each interface */ + /* so Linux will call suspend/resume function once */ + RTMP_DRIVER_VIRTUAL_INF_NUM_GET(pAd, &IfNum); + if (IfNum > 0) + { + /* avoid users do suspend after interface is down */ + + /* stop interface */ + netif_carrier_off(net_dev); + netif_stop_queue(net_dev); + + /* mark device as removed from system and therefore no longer available */ + netif_device_detach(net_dev); + + /* mark halt flag */ +/* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ +/* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); */ + RTMP_DRIVER_PCI_SUSPEND(pAd); + + /* take down the device */ + rt28xx_close((PNET_DEV)net_dev); + + RT_MOD_DEC_USE_COUNT(); + } + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10) + /* + reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html + enable device to generate PME# when suspended + pci_choose_state(): Choose the power state of a PCI device to be suspended + */ + retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1); + /* save the PCI configuration space of a device before suspending */ + pci_save_state(pci_dev); + /* disable PCI device after use */ + pci_disable_device(pci_dev); + + retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("<===%s()\n", __FUNCTION__)); + return retval; +} + + +static int rt_pci_resume(struct pci_dev *pci_dev) +{ + struct net_device *net_dev = pci_get_drvdata(pci_dev); + VOID *pAd = NULL; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10) + INT32 retval; + + + /* + Set the power state of a PCI device + + PCI has 4 power states, DO (normal) ~ D3(less power) + you can find that in include/linux/pci.h + #define PCI_D0 ((pci_power_t __force) 0) + #define PCI_D1 ((pci_power_t __force) 1) + #define PCI_D2 ((pci_power_t __force) 2) + #define PCI_D3hot ((pci_power_t __force) 3) + #define PCI_D3cold ((pci_power_t __force) 4) + #define PCI_UNKNOWN ((pci_power_t __force) 5) + #define PCI_POWER_ERROR ((pci_power_t __force) -1) + */ + retval = pci_set_power_state(pci_dev, PCI_D0); + + /* restore the saved state of a PCI device */ + pci_restore_state(pci_dev); + + /* initialize device before it's used by a driver */ + if (pci_enable_device(pci_dev)) + { + printk("pci enable fail!\n"); + return 0; + } +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("===>%s()\n", __FUNCTION__)); + + if (net_dev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); + } + else + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd != NULL) + { + ULONG IfNum; + + /* + we can not use IFF_UP because ra0 down but ra1 up + and 1 suspend/resume function for 1 module, not for each interface + so Linux will call suspend/resume function once + */ + RTMP_DRIVER_VIRTUAL_INF_NUM_GET(pAd, &IfNum); + if (IfNum > 0) +/* if (VIRTUAL_IF_NUM(pAd) > 0) */ + { + /* mark device as attached from system and restart if needed */ + netif_device_attach(net_dev); + + if (rt28xx_open((PNET_DEV)net_dev) != 0) + { + /* open fail */ + DBGPRINT(RT_DEBUG_TRACE, ("<===%s()\n", __FUNCTION__)); + return 0; + } + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + +/* RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ +/* RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); */ + RTMP_DRIVER_PCI_RESUME(pAd); + + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + return 0; +} +#endif /* CONFIG_PM */ +#endif + + +/* + PCI device probe & initialization function +*/ +static int DEVINIT rt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + void *pAd = NULL, *handle; + struct net_device *net_dev; + const char *print_name; + unsigned long csr_addr; + int rv = 0; + RTMP_OS_NETDEV_OP_HOOK netDevHook; + unsigned long OpMode; +#ifdef DBG + ULONG start, end, diff_ms; + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&start); +#endif /* DBG */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + +/*PCIDevInit============================================== */ + /* wake up and enable device */ + if ((rv = pci_enable_device(pdev))!= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Enable PCI device failed, errno=%d!\n", rv)); + return rv; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + print_name = (char *) pci_name(pdev); +#else + print_name = pdev->slot_name; +#endif /* LINUX_VERSION_CODE */ + + if ((rv = pci_request_regions(pdev, print_name)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Request PCI resource failed, errno=%d!\n", rv)); + goto err_out; + } + + /* map physical address to virtual address for accessing register */ + csr_addr = (unsigned long) ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!csr_addr) + { + DBGPRINT(RT_DEBUG_ERROR, ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n", + print_name, (ULONG)pci_resource_len(pdev, 0), (ULONG)pci_resource_start(pdev, 0))); + goto err_out_free_res; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", print_name, + (ULONG)pci_resource_start(pdev, 0), (ULONG)csr_addr, pdev->irq)); + } + +#ifdef RT_SECURE_DMA + /* Map secure memory area to our pci_dev, for future dma buffer memory allocations */ + /* The numbers here will need to be changed to match the platform. Currently 16MBytes + * are allocated at address 256Mbyte + */ + + /* Example of code for ST platform */ + + DBGPRINT(RT_DEBUG_OFF, ("%s(): RT_SECURE_DMA prepare\n", __FUNCTION__)); + + if( ! dma_declare_coherent_memory(&(pdev->dev), 0x10000000UL, 0x10000000UL, 0x01000000UL, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE ) ) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): dma_declare_coherent_memory failed!\n", __FUNCTION__)); + goto err_out_iounmap; + } + +#endif + /* Set DMA master */ + pci_set_master(pdev); + + /* Allocate RTMP_ADAPTER adapter structure */ + os_alloc_mem(NULL, (UCHAR **)&handle, sizeof(struct os_cookie)); + if (handle == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Allocate memory for os handle failed!\n", __FUNCTION__)); + goto err_out_iounmap; + } + memset(handle, 0, sizeof(struct os_cookie)); + + ((POS_COOKIE)handle)->pci_dev = pdev; + +#ifdef OS_ABL_FUNC_SUPPORT +{ + RTMP_PCI_CONFIG PciConfig; + PciConfig.ConfigVendorID = PCI_VENDOR_ID; + /* get DRIVER operations */ + RTMP_DRV_OPS_FUNCTION(pRtmpDrvOps, NULL, &PciConfig, NULL); +} +#endif /* OS_ABL_FUNC_SUPPORT */ + + rv = RTMPAllocAdapterBlock(handle, &pAd); /* we may need the pdev for allocate structure of "RTMP_ADAPTER" */ + if (rv != NDIS_STATUS_SUCCESS) + goto err_out_iounmap; + +#ifdef MULTI_INF_SUPPORT + if (pAdGlobalList[0] == NULL) + pAdGlobalList[0] = pAd; + else if (pAdGlobalList[1] == NULL) + pAdGlobalList[1] = pAd; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s(): pAdGlobalList assign Error !\n", __FUNCTION__)); +#endif /* MULTI_INF_SUPPORT */ + + RTMP_DRIVER_PCI_CSR_SET(pAd, csr_addr); + + RTMP_DRIVER_PCIE_INIT(pAd, pdev); + +/*NetDevInit============================================== */ + net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); + if (net_dev == NULL) + goto err_out_free_radev; + + /* Here are the net_device structure with pci-bus specific parameters. */ + net_dev->irq = pdev->irq; /* Interrupt IRQ number */ + net_dev->base_addr = csr_addr; /* Save CSR virtual address and irq to device structure */ + pci_set_drvdata(pdev, net_dev); /* Set driver data */ + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +/* for supporting Network Manager */ + /* + Set the sysfs physical device reference for the network logical device + if set prior to registration will cause a symlink during initialization. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(net_dev, &(pdev->dev)); +#endif +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + +/*All done, it's time to register the net device to linux kernel. */ + /* Register this device */ +#ifdef RT_CFG80211_SUPPORT +{ +/* pAd->pCfgDev = &(pdev->dev); */ +/* pAd->CFG80211_Register = CFG80211_Register; */ +/* RTMP_DRIVER_CFG80211_INIT(pAd, pdev); */ + + /* + In 2.6.32, cfg80211 register must be before register_netdevice(); + We can not put the register in rt28xx_open(); + Or you will suffer NULL pointer in list_add of + cfg80211_netdev_notifier_call(). + */ + CFG80211_Register(pAd, &(pdev->dev), net_dev); +} +#endif /* RT_CFG80211_SUPPORT */ + + RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); + rv = RtmpOSNetDevAttach(OpMode, net_dev, &netDevHook); + if (rv) + goto err_out_free_netdev; + +#ifdef CONFIG_STA_SUPPORT +/* pAd->StaCfg.OriDevType = net_dev->type; */ + RTMP_DRIVER_STA_DEV_TYPE_SET(pAd, net_dev->type); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef PRE_ASSIGN_MAC_ADDR +{ + UCHAR mac_addr[MAC_ADDR_LEN]; + RTMP_DRIVER_MAC_ADDR_GET(pAd, &mac_addr[0]); + DBGPRINT(RT_DEBUG_TRACE, ("@%s MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, mac_addr[0], mac_addr[1], + mac_addr[2], mac_addr[3], + mac_addr[4], mac_addr[5])); + /* Set up the Mac address */ + RtmpOSNetDevAddrSet(OpMode, net_dev, &mac_addr[0], NULL); +} +#endif /* PRE_ASSIGN_MAC_ADDR */ + +#ifdef DBG + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&end); diff_ms = (end-start)*1000/OS_HZ; + DBGPRINT(RT_DEBUG_OFF, ("WiFi PCI Startup Time: %lu.%03lus\n",diff_ms/1000,diff_ms%1000)); +#endif /* DBG */ + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return 0; /* probe ok */ + + + /* --------------------------- ERROR HANDLE --------------------------- */ +err_out_free_netdev: + RtmpOSNetDevFree(net_dev); + +err_out_free_radev: + /* free RTMP_ADAPTER strcuture and os_cookie*/ + RTMPFreeAdapter(pAd); + +err_out_iounmap: + iounmap((void *)(csr_addr)); + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + +err_out_free_res: + pci_release_regions(pdev); + +err_out: + pci_disable_device(pdev); + + DBGPRINT(RT_DEBUG_ERROR, ("<=== %s() failed with rv = %d!\n", + __FUNCTION__, rv)); + + return -ENODEV; /* probe fail */ +} + + +static VOID DEVEXIT rt_pci_remove(struct pci_dev *pci_dev) +{ + PNET_DEV net_dev = pci_get_drvdata(pci_dev); + VOID *pAd = NULL; + ULONG csr_addr = net_dev->base_addr; + + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + if (pAd != NULL) + { + /* Unregister/Free all allocated net_device. */ + RtmpPhyNetDevExit(pAd, net_dev); + +#ifdef RT_CFG80211_SUPPORT + RTMP_DRIVER_80211_UNREGISTER(pAd, net_dev); +#endif /* RT_CFG80211_SUPPORT */ + + /* Free RTMP_ADAPTER related structures. */ + RtmpRaDevCtrlExit(pAd); + + /* Unmap CSR base address */ + iounmap((char *)(csr_addr)); + + /* release memory region */ + release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); + } + else + { + /* Unregister network device */ + RtmpOSNetDevDetach(net_dev); + + /* Unmap CSR base address */ + iounmap((char *)(net_dev->base_addr)); + + /* release memory region */ + release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); + } + +#ifdef RT_SECURE_DMA + dma_release_declared_memory(&(pci_dev->dev)); +#endif + /* Free the root net_device */ + RtmpOSNetDevFree(net_dev); +} + + +/* + Our PCI driver structure +*/ +static struct pci_driver rt_pci_driver = +{ + name: RTMP_DRV_NAME, + id_table: rt_pci_tbl, + probe: rt_pci_probe, +#if LINUX_VERSION_CODE >= 0x20412 + remove: DEVEXIT_P(rt_pci_remove), +#else + remove: __devexit(rt_pci_remove), +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifdef CONFIG_PM + suspend: rt_pci_suspend, + resume: rt_pci_resume, +#endif +#endif +}; + + +/* + Driver module load/unload function +*/ +int __init rt_pci_init_module(void) +{ + DBGPRINT(RT_DEBUG_ERROR, ("register %s\n", RTMP_DRV_NAME)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return pci_register_driver(&rt_pci_driver); +#else + return pci_module_init(&rt_pci_driver); +#endif +} + + +void __exit rt_pci_cleanup_module(void) +{ + pci_unregister_driver(&rt_pci_driver); +} + +#ifndef MULTI_INF_SUPPORT +module_init(rt_pci_init_module); +module_exit(rt_pci_cleanup_module); + +#ifdef CONFIG_STA_SUPPORT +#ifdef MODULE_VERSION +MODULE_VERSION(STA_DRIVER_VERSION); +#endif +#endif /* CONFIG_STA_SUPPORT */ + +#endif /* MULTI_INF_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rbus_main_dev.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rbus_main_dev.c new file mode 100644 index 000000000..84f1f984f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rbus_main_dev.c @@ -0,0 +1,283 @@ +/* + *************************************************************************** + * 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: + rbus_main_dev.c + + Abstract: + Create and register network interface for RBUS based chipsets in linux platform. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifdef RTMP_RBUS_SUPPORT + +#define RTMP_MODULE_OS + +#include "rt_config.h" + +#ifdef RT_CFG80211_SUPPORT +#include /* chrdev allocation */ +#include + +struct file_operations dev_reg_fops = { + .open = NULL, + .release = NULL, +}; + +#define DEVNUM_NAME "cfg_rbus" +#define DEVNUM_MINOR_START 0 +#define DEVNUM_COUNT 1 + +static dev_t dev; +static struct device *dev_ret; +static struct cdev dev_reg_cdev; +static struct class *cl; + +#endif /* RT_CFG80211_SUPPORT */ +static struct net_device *rt2880_dev = NULL; + +#if defined(CONFIG_RA_CLASSIFIER)&&(!defined(CONFIG_RA_CLASSIFIER_MODULE)) +extern int (*ra_classifier_init_func) (void) ; +extern void (*ra_classifier_release_func) (void) ; +extern struct proc_dir_entry *proc_ptr, *proc_ralink_wl_video; +#endif + +#ifdef MULTI_INF_SUPPORT +/* Index 0 for 2.4G, 1 for 5Ghz Card */ +extern VOID* pAdGlobalList[2]; +#endif /* MULTI_INF_SUPPORT */ + +int __init rt2880_module_init(void) +{ + struct net_device *net_dev; + ULONG csr_addr; + INT rv; + PVOID *handle = NULL; + RTMP_ADAPTER *pAd; + unsigned int dev_irq; + RTMP_OS_NETDEV_OP_HOOK netDevHook; +#ifdef DBG + ULONG start, end, diff_ms; + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&start); +#endif /* DBG */ + + DBGPRINT(RT_DEBUG_ERROR, ("===> rt2880_probe\n")); + +/*RtmpRaBusInit============================================ */ + /* map physical address to virtual address for accessing register */ + csr_addr = (unsigned long)RTMP_MAC_CSR_ADDR; + dev_irq = RTMP_MAC_IRQ_NUM; + +/*RtmpDevInit============================================== */ + /* Allocate RTMP_ADAPTER adapter structure */ +/* handle = kmalloc(sizeof(struct os_cookie) , GFP_KERNEL); */ + os_alloc_mem(NULL, (UCHAR **)&handle, sizeof(struct os_cookie)); + if (!handle) + { + DBGPRINT(RT_DEBUG_ERROR, ("Allocate memory for os_cookie failed!\n")); + goto err_out; + } + NdisZeroMemory(handle, sizeof(struct os_cookie)); + +#ifdef OS_ABL_FUNC_SUPPORT + /* get DRIVER operations */ + RTMP_DRV_OPS_FUNCTION(pRtmpDrvOps, NULL, NULL, NULL); +#endif /* OS_ABL_FUNC_SUPPORT */ + + rv = RTMPAllocAdapterBlock(handle, (VOID **)&pAd); + if (rv != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, (" RTMPAllocAdapterBlock != NDIS_STATUS_SUCCESS\n")); +/* kfree(handle); */ + os_free_mem(NULL, handle); + + goto err_out; + } + +#ifdef MULTI_INF_SUPPORT + if (pAdGlobalList[0] == NULL) + pAdGlobalList[0] = pAd; + else if (pAdGlobalList[1] == NULL) + pAdGlobalList[1] = pAd; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s(): pAdGlobalList assign Error !\n", __FUNCTION__)); +#endif /* MULTI_INF_SUPPORT */ + + + /* Here are the RTMP_ADAPTER structure with rbus-bus specific parameters. */ + pAd->CSRBaseAddress = (PUCHAR)csr_addr; + + RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_RBUS); + + +/*NetDevInit============================================== */ + net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); + if (net_dev == NULL) + goto err_out_free_radev; + + /* Here are the net_device structure with pci-bus specific parameters. */ + net_dev->irq = dev_irq; /* Interrupt IRQ number */ + net_dev->base_addr = csr_addr; /* Save CSR virtual address and irq to device structure */ + ((POS_COOKIE)handle)->pci_dev = NULL; + +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.OriDevType = net_dev->type; +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef RT_CFG80211_SUPPORT + /* + In 2.6.32, cfg80211 register must be before register_netdevice(); + We can not put the register in rt28xx_open(); + Or you will suffer NULL pointer in list_add of + cfg80211_netdev_notifier_call(). + */ + + /* register a dummy char device for CFG80211_Register because RBUS don't have a real device */ + + INT alloc_ret=0,cdev_err=0; + static unsigned int dev_reg_major = 0; + alloc_ret = alloc_chrdev_region(&dev, DEVNUM_MINOR_START, DEVNUM_COUNT, DEVNUM_NAME); + if(alloc_ret){ + DBGPRINT(RT_DEBUG_OFF, ("%s : could not allocate device\n", __func__)); + goto err_out_free_radev; + } + else{ + DBGPRINT(RT_DEBUG_OFF, ("%s : registered char dev with major number:%i, minor number:%i\n", + __func__, MAJOR(dev), MINOR(dev))); + dev_reg_major = MAJOR(dev); + } + cl = class_create(THIS_MODULE, "chardrv"); + dev_ret = device_create(cl, NULL, dev, NULL, "mynull"); + + cdev_init(&dev_reg_cdev, &dev_reg_fops); + dev_reg_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&dev_reg_cdev, MKDEV(dev_reg_major, 0), DEVNUM_COUNT); + if(cdev_err){ + DBGPRINT(RT_DEBUG_OFF, ("%s : could not add cdev\n", __func__)); + goto err_out_free_radev; + } + if(dev_ret == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("%s : dev_ret is NULL!!!\n", __func__)); + goto err_out_free_radev; + } + /* register a dummy char device done */ + + CFG80211_Register(pAd, dev_ret , net_dev); + +#endif /* RT_CFG80211_SUPPORT */ + + + /*All done, it's time to register the net device to kernel. */ + /* Register this device */ + rv = RtmpOSNetDevAttach(pAd->OpMode, net_dev, &netDevHook); + if (rv) + { + DBGPRINT(RT_DEBUG_ERROR, ("failed to call RtmpOSNetDevAttach(), rv=%d!\n", rv)); + goto err_out_free_netdev; + } + + + /* due to we didn't have any hook point when do module remove, we use this static as our hook point. */ + rt2880_dev = net_dev; + + wl_proc_init(); + + DBGPRINT(RT_DEBUG_ERROR, ("%s: at CSR addr 0x%lx, IRQ %u. \n", net_dev->name, (ULONG)csr_addr, net_dev->irq)); + +#ifdef DBG + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&end); diff_ms = (end-start)*1000/OS_HZ; + DBGPRINT(RT_DEBUG_OFF, ("WiFi RBUS Startup Time: %lu.%03lus\n",diff_ms/1000,diff_ms%1000)); +#endif /* DBG */ + + DBGPRINT(RT_DEBUG_ERROR, ("<=== rt2880_probe\n")); + +#if defined(CONFIG_RA_CLASSIFIER)&&(!defined(CONFIG_RA_CLASSIFIER_MODULE)) + proc_ptr = proc_ralink_wl_video; + if(ra_classifier_init_func!=NULL) + ra_classifier_init_func(); +#endif + + return 0; + +err_out_free_netdev: + RtmpOSNetDevFree(net_dev); + +err_out_free_radev: + /* free RTMP_ADAPTER strcuture and os_cookie*/ + RTMPFreeAdapter(pAd); + +err_out: + return -ENODEV; + +} + + +VOID __exit rt2880_module_exit(void) +{ + struct net_device *net_dev = rt2880_dev; + RTMP_ADAPTER *pAd; + + + if (net_dev == NULL) + return; + + /* pAd = net_dev->priv; */ + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd != NULL) + { + RtmpPhyNetDevExit(pAd, net_dev); + RtmpRaDevCtrlExit(pAd); + } + else + { + RtmpOSNetDevDetach(net_dev); + } + + /* Free the root net_device. */ + RtmpOSNetDevFree(net_dev); +#ifdef RT_CFG80211_SUPPORT + cdev_del(&dev_reg_cdev); + device_destroy(cl, dev); + class_destroy(cl); + unregister_chrdev_region(dev, 1); +#endif /* RT_CFG80211_SUPPORT */ + +#if defined(CONFIG_RA_CLASSIFIER)&&(!defined(CONFIG_RA_CLASSIFIER_MODULE)) + proc_ptr = proc_ralink_wl_video; + if(ra_classifier_release_func!=NULL) + ra_classifier_release_func(); +#endif + + wl_proc_exit(); +} + + +#ifndef MULTI_INF_SUPPORT +module_init(rt2880_module_init); +module_exit(rt2880_module_exit); +#endif /* MULTI_INF_SUPPORT */ + +#endif /* RTMP_RBUS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_linux.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_linux.c new file mode 100644 index 000000000..9f438fbf6 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_linux.c @@ -0,0 +1,4589 @@ +/**************************************************************************** + + Module Name: + UTIL/rt_linux.c + + Abstract: + All functions provided from OS module are put here. + + Note: + 1. Can not use sizeof() for a structure with any parameter included + by any compile option, such as RTMP_ADAPTER. + + Because the RTMP_ADAPTER size in the UTIL module is different with + DRIVER/NETIF. + + 2. Do not use any structure with any parameter included by PCI/USB/RBUS/ + AP/STA. + + Because the structure size in the UTIL module is different with + DRIVER/NETIF. + + 3. Do not use any structure defined in DRIVER module, EX: pAd. + So we can do module partition. + + Revision History: + Who When What + --------- ---------- ------------------------------------------- + +***************************************************************************/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL +#include +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" +#include "dot11i_wpa.h" +#include +#include +#include +#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE) +#include "../../../../../../../net/nat/hw_nat/ra_nat.h" +#include "../../../../../../../net/nat/hw_nat/frame_engine.h" +#endif + +/* TODO */ +#undef RT_CONFIG_IF_OPMODE_ON_AP +#undef RT_CONFIG_IF_OPMODE_ON_STA + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) if (__OpMode == OPMODE_AP) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) if (__OpMode == OPMODE_STA) +#else +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) +static inline void *netdev_priv(struct net_device *dev) +{ + return dev->priv; +} +#endif +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) +static inline void *netdev_priv(struct net_device *dev) +{ + return dev->priv; +} +#endif + +/* + Used for backward compatible with previous linux version which + used "net_device->priv" as device driver structure hooking point +*/ +static inline void netdev_priv_set(struct net_device *dev, void *priv) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) + dev->priv = priv; +#endif +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) + dev->priv = priv; +#endif +} + + +ULONG RTDebugLevel = RT_DEBUG_ERROR; +ULONG RTDebugFunc = 0; + +#ifdef OS_ABL_FUNC_SUPPORT +ULONG RTPktOffsetData = 0, RTPktOffsetLen = 0, RTPktOffsetCB = 0; +#endif /* OS_ABL_FUNC_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_RA_CLASSIFIER) || defined(CONFIG_RA_CLASSIFIER_MODULE) +extern int (*ra_classifier_hook_rx) (struct sk_buff *skb, unsigned long cycle); +extern volatile unsigned long classifier_cur_cycle; +#endif /* CONFIG_RA_CLASSIFIER */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef VENDOR_FEATURE4_SUPPORT +ULONG OS_NumOfMemAlloc = 0, OS_NumOfMemFree = 0; +#endif /* VENDOR_FEATURE4_SUPPORT */ +#ifdef VENDOR_FEATURE2_SUPPORT +ULONG OS_NumOfPktAlloc = 0, OS_NumOfPktFree = 0; +#endif /* VENDOR_FEATURE2_SUPPORT */ + +/* + * the lock will not be used in TX/RX + * path so throughput should not be impacted + */ +BOOLEAN FlgIsUtilInit = FALSE; +OS_NDIS_SPIN_LOCK UtilSemLock; + +BOOLEAN RTMP_OS_Alloc_RscOnly(VOID *pRscSrc, UINT32 RscLen); +BOOLEAN RTMP_OS_Remove_Rsc(LIST_HEADER *pRscList, VOID *pRscSrc); + +/* +======================================================================== +Routine Description: + Initialize something in UTIL module. + +Arguments: + None + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpUtilInit(VOID) +{ + if (FlgIsUtilInit == FALSE) { + OS_NdisAllocateSpinLock(&UtilSemLock); + FlgIsUtilInit = TRUE; + } +} + +/* timeout -- ms */ +static inline VOID __RTMP_SetPeriodicTimer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout * OS_HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +static inline VOID __RTMP_OS_Init_Timer( + IN VOID *pReserved, + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN TIMER_FUNCTION function, + IN PVOID data) +{ + if (!timer_pending(pTimer)) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) + timer_setup(pTimer, function, 0); +#else + init_timer(pTimer); + pTimer->data = (unsigned long)data; + pTimer->function = function; +#endif + } +} + +static inline VOID __RTMP_OS_Add_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN unsigned long timeout) +{ + if (timer_pending(pTimer)) + return; + + timeout = ((timeout * OS_HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +static inline VOID __RTMP_OS_Mod_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout * OS_HZ) / 1000); + mod_timer(pTimer, jiffies + timeout); +} + +static inline VOID __RTMP_OS_Del_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + OUT BOOLEAN *pCancelled) +{ + if (timer_pending(pTimer)) + *pCancelled = del_timer_sync(pTimer); + else + *pCancelled = TRUE; +} + +static inline VOID __RTMP_OS_Release_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer) +{ + /* nothing to do */ +} + + +/* Unify all delay routine by using udelay */ +VOID RtmpusecDelay(ULONG usec) +{ + ULONG i; + + for (i = 0; i < (usec / 50); i++) + udelay(50); + + if (usec % 50) + udelay(usec % 50); +} + + +VOID RtmpOsMsDelay(ULONG msec) +{ + mdelay(msec); +} + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time) +{ + time->u.LowPart = jiffies; +} + +void RTMP_GetCurrentSystemTick(ULONG *pNow) +{ + *pNow = jiffies; +} + +ULONG RTMPMsecsToJiffies(UINT32 m) +{ + + return msecs_to_jiffies(m); +} + +/* pAd MUST allow to be NULL */ + +NDIS_STATUS os_alloc_mem( + IN VOID *pReserved, + OUT UCHAR **mem, + IN ULONG size) +{ + *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC); + if (*mem) { +#ifdef VENDOR_FEATURE4_SUPPORT + OS_NumOfMemAlloc++; +#endif /* VENDOR_FEATURE4_SUPPORT */ + + return NDIS_STATUS_SUCCESS; + } else + return NDIS_STATUS_FAILURE; +} + +NDIS_STATUS os_alloc_mem_suspend( + IN VOID *pReserved, + OUT UCHAR **mem, + IN ULONG size) +{ + *mem = (PUCHAR) kmalloc(size, GFP_KERNEL); + if (*mem) { +#ifdef VENDOR_FEATURE4_SUPPORT + OS_NumOfMemAlloc++; +#endif /* VENDOR_FEATURE4_SUPPORT */ + + return NDIS_STATUS_SUCCESS; + } else + return NDIS_STATUS_FAILURE; +} + +/* pAd MUST allow to be NULL */ +NDIS_STATUS os_free_mem( + IN VOID *pReserved, + IN PVOID mem) +{ + ASSERT(mem); + kfree(mem); + +#ifdef VENDOR_FEATURE4_SUPPORT + OS_NumOfMemFree++; +#endif /* VENDOR_FEATURE4_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + +#if defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) + +extern int ra_mtd_write_nm(char *name, loff_t to, size_t len, const u_char *buf); +extern int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf); + +void RtmpFlashRead( + UCHAR *p, + ULONG a, + ULONG b) +{ + size_t retlen; + struct mtd_info *mtd_info = get_mtd_device_nm("factory"); + if (IS_ERR(mtd_info) || mtd_info == NULL) { + printk("ERROR: failed to find 'Factory' mtd partiton\n"); + return; + } + mtd_read(mtd_info, a, b, &retlen, p); + put_mtd_device(mtd_info); +} + +void RtmpFlashWrite( + UCHAR *p, + ULONG a, + ULONG b) +{ + size_t retlen; + struct mtd_info *mtd_info = get_mtd_device_nm("factory"); + if (IS_ERR(mtd_info) || mtd_info == NULL) { + printk("ERROR: failed to find 'Factory' mtd partiton\n"); + return; + } + mtd_write(mtd_info, a, b, &retlen, p); + put_mtd_device(mtd_info); +} +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + + +PNDIS_PACKET RtmpOSNetPktAlloc(VOID *dummy, int size) +{ + struct sk_buff *skb; + /* Add 2 more bytes for ip header alignment */ + skb = dev_alloc_skb(size + 2); + if (skb != NULL) + MEM_DBG_PKT_ALLOC_INC(skb); + + return ((PNDIS_PACKET) skb); +} + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer(VOID *dummy, ULONG len) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(len); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate frag rx %ld size packet\n", len)); + } + + if (pkt) { + MEM_DBG_PKT_ALLOC_INC(pkt); + } + + return (PNDIS_PACKET) pkt; +} + + + + +/* + The allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() +*/ +NDIS_STATUS RTMPAllocateNdisPacket( + IN VOID *pReserved, + OUT PNDIS_PACKET *ppPacket, + IN UCHAR *pHeader, + IN UINT HeaderLen, + IN UCHAR *pData, + IN UINT DataLen) +{ + struct sk_buff *pPacket; + + + ASSERT(pData); + ASSERT(DataLen); + + /* Add LEN_CCMP_HDR + LEN_CCMP_MIC for PMF */ + pPacket = dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING + LEN_CCMP_HDR + LEN_CCMP_MIC); + if (pPacket == NULL) { + *ppPacket = NULL; +#ifdef DBG + printk(KERN_ERR "RTMPAllocateNdisPacket Fail\n\n"); +#endif + return NDIS_STATUS_FAILURE; + } + MEM_DBG_PKT_ALLOC_INC(pPacket); + + /* Clone the frame content and update the length of packet */ + if (HeaderLen > 0) + NdisMoveMemory(pPacket->data, pHeader, HeaderLen); + if (DataLen > 0) + NdisMoveMemory(pPacket->data + HeaderLen, pData, DataLen); + skb_put(pPacket, HeaderLen + DataLen); +/* printk(KERN_ERR "%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));*/ + + *ppPacket = (PNDIS_PACKET)pPacket; + + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + Description: + This routine frees a miniport internally allocated NDIS_PACKET and its + corresponding NDIS_BUFFER and allocated memory. + ======================================================================== +*/ +VOID RTMPFreeNdisPacket(VOID *pReserved, PNDIS_PACKET pPacket) +{ + dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); + MEM_DBG_PKT_FREE_INC(pPacket); +} + + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *info, + OUT UCHAR **pSrcBufVA, + OUT UINT *pSrcBufLen) +{ + info->BufferCount = 1; + info->pFirstBuffer = (PNDIS_BUFFER) GET_OS_PKT_DATAPTR(pPacket); + info->PhysicalBufferCount = 1; + info->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); + +#ifdef TX_PKT_SG + if (RTMP_GET_PKT_SG(pPacket)) { + struct sk_buff *skb = (struct sk_buff *)pPacket; + int i, nr_frags = skb_shinfo(skb)->nr_frags; + + info->BufferCount = nr_frags + 1; + info->PhysicalBufferCount = info->BufferCount; + info->sg_list[0].data = (VOID *)GET_OS_PKT_DATAPTR(pPacket); + info->sg_list[0].len = skb_headlen(skb); + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + info->sg_list[i+1].data = ((void *) page_address(frag->page) + + frag->page_offset); + info->sg_list[i+1].len = frag->size; + } + } +#endif /* TX_PKT_SG */ +} + + + + +PNDIS_PACKET DuplicatePacket( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pRetPacket = NULL; + + skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); + if (skb) { + MEM_DBG_PKT_ALLOC_INC(skb); + skb->dev = pNetDev; + pRetPacket = OSPKT_TO_RTPKT(skb); + } + + return pRetPacket; + +} + + +PNDIS_PACKET duplicate_pkt( + IN PNET_DEV pNetDev, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pPacket = NULL; + + if ((skb = + __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) { + MEM_DBG_PKT_ALLOC_INC(skb); + + skb_reserve(skb, 2); + NdisMoveMemory(skb->tail, pHeader802_3, HdrLen); + skb_put(skb, HdrLen); + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = pNetDev; + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} + + +#define TKIP_TX_MIC_SIZE 8 +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(VOID *pReserved, PNDIS_PACKET pPacket) +{ + struct sk_buff *skb, *newskb; + + skb = RTPKT_TO_OSPKT(pPacket); + if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) { + /* alloc a new skb and copy the packet */ + newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); + + dev_kfree_skb_any(skb); + MEM_DBG_PKT_FREE_INC(skb); + + if (newskb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); + return NULL; + } + skb = newskb; + MEM_DBG_PKT_ALLOC_INC(skb); + } + + return OSPKT_TO_RTPKT(skb); + + +} + +#ifdef CONFIG_AP_SUPPORT +PNDIS_PACKET duplicate_pkt_with_VLAN( + IN PNET_DEV pNetDev, + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID) +{ + struct sk_buff *skb; + PNDIS_PACKET pPacket = NULL; + UINT16 VLAN_Size; + + if ((skb = __dev_alloc_skb(HdrLen + DataSize + LENGTH_802_1Q + 2, + MEM_ALLOC_FLAG)) != NULL) { + MEM_DBG_PKT_ALLOC_INC(skb); + + skb_reserve(skb, 2); + + /* copy header (maybe +VLAN tag) */ + VLAN_Size = VLAN_8023_Header_Copy(VLAN_VID, VLAN_Priority, + pHeader802_3, HdrLen, + skb->tail, FromWhichBSSID, + TPID); + skb_put(skb, HdrLen + VLAN_Size); + + /* copy data body */ + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = pNetDev; /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ======================================================================== + + Routine Description: + Send a L2 frame to upper daemon to trigger state machine + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPL2FrameTxAction( + IN VOID * pCtrlBkPtr, + IN PNET_DEV pNetDev, + IN RTMP_CB_8023_PACKET_ANNOUNCE _announce_802_3_packet, + IN UCHAR apidx, + IN UCHAR *pData, + IN UINT32 data_len, + IN UCHAR OpMode) +{ + struct sk_buff *skb = dev_alloc_skb(data_len + 2); + + if (!skb) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Error! Can't allocate a skb.\n", __FUNCTION__)); + return FALSE; + } + + MEM_DBG_PKT_ALLOC_INC(skb); + SET_OS_PKT_NETDEV(skb, pNetDev); + + /* 16 byte align the IP header */ + skb_reserve(skb, 2); + + /* Insert the frame content */ + NdisMoveMemory(GET_OS_PKT_DATAPTR(skb), pData, data_len); + + /* End this frame */ + skb_put(GET_OS_PKT_TYPE(skb), data_len); + + DBGPRINT(RT_DEBUG_TRACE, ("%s doen\n", __FUNCTION__)); + + _announce_802_3_packet(pCtrlBkPtr, skb, OpMode); + + return TRUE; + +} + + +PNDIS_PACKET ExpandPacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket, + IN UINT32 ext_head_len, + IN UINT32 ext_tail_len) +{ + struct sk_buff *skb, *newskb; + + skb = RTPKT_TO_OSPKT(pPacket); + if (skb_cloned(skb) || (skb_headroom(skb) < ext_head_len) + || (skb_tailroom(skb) < ext_tail_len)) { + UINT32 head_len = + (skb_headroom(skb) < + ext_head_len) ? ext_head_len : skb_headroom(skb); + UINT32 tail_len = + (skb_tailroom(skb) < + ext_tail_len) ? ext_tail_len : skb_tailroom(skb); + + /* alloc a new skb and copy the packet */ + newskb = skb_copy_expand(skb, head_len, tail_len, GFP_ATOMIC); + + dev_kfree_skb_any(skb); + MEM_DBG_PKT_FREE_INC(skb); + + if (newskb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("Extend Tx buffer for WPI failed!, dropping packet!\n")); + return NULL; + } + skb = newskb; + MEM_DBG_PKT_ALLOC_INC(skb); + } + + return OSPKT_TO_RTPKT(skb); + +} + +PNDIS_PACKET ClonePacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize) +{ + struct sk_buff *pRxPkt; + struct sk_buff *pClonedPkt; + + ASSERT(pPacket); + pRxPkt = RTPKT_TO_OSPKT(pPacket); + + /* clone the packet */ + pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); + + if (pClonedPkt) { + /* set the correct dataptr and data len */ + MEM_DBG_PKT_ALLOC_INC(pClonedPkt); + pClonedPkt->dev = pRxPkt->dev; + pClonedPkt->data = pData; + pClonedPkt->len = DataSize; + pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; + //ASSERT(DataSize < 1530); + if(DataSize > 1530) + DBGPRINT(RT_DEBUG_TRACE, + ("%s %d : DataSize > 1530 !\n",__FUNCTION__,__LINE__)); + } + return pClonedPkt; +} + +VOID RtmpOsPktInit( + IN PNDIS_PACKET pNetPkt, + IN PNET_DEV pNetDev, + IN UCHAR *pData, + IN USHORT DataSize) +{ + PNDIS_PACKET pRxPkt; + + pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + + SET_OS_PKT_NETDEV(pRxPkt, pNetDev); + SET_OS_PKT_DATAPTR(pRxPkt, pData); + SET_OS_PKT_LEN(pRxPkt, DataSize); + SET_OS_PKT_DATATAIL(pRxPkt, pData, DataSize); +} + + +void wlan_802_11_to_802_3_packet( + IN PNET_DEV pNetDev, + IN UCHAR OpMode, + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PNDIS_PACKET pRxPacket, + IN UCHAR *pData, + IN ULONG DataSize, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID + ) +{ + struct sk_buff *pOSPkt; + + ASSERT(pHeader802_3); + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + + pOSPkt->dev = pNetDev; + + { + pOSPkt->data = pData; + pOSPkt->len = DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; + } + + /* copy 802.3 header */ +#ifdef CONFIG_AP_SUPPORT + RT_CONFIG_IF_OPMODE_ON_AP(OpMode) + { + /* maybe insert VLAN tag to the received packet */ + UCHAR VLAN_Size = 0; + UCHAR *data_p; + + if (VLAN_VID != 0) + VLAN_Size = LENGTH_802_1Q; + + data_p = skb_push(pOSPkt, LENGTH_802_3 + VLAN_Size); + + VLAN_8023_Header_Copy(VLAN_VID, VLAN_Priority, + pHeader802_3, LENGTH_802_3, + data_p, FromWhichBSSID, TPID); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + RT_CONFIG_IF_OPMODE_ON_STA(OpMode) + { + NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); + } +#endif /* CONFIG_STA_SUPPORT */ + +} + + +#ifdef DBG +void hex_dump(char *str, UCHAR *pSrcBufVA, UINT SrcBufLen) +{ + unsigned char *pt; + int x; + + if (RTDebugLevel < RT_DEBUG_TRACE) + return; + + pt = pSrcBufVA; + printk("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen); + for (x = 0; x < SrcBufLen; x++) { + if (x % 16 == 0) + printk("0x%04x : ", x); + printk("%02x ", ((unsigned char)pt[x])); + if (x % 16 == 15) + printk("\n"); + } + printk("\n"); +} +#endif /* DBG */ + +#ifdef SYSTEM_LOG_SUPPORT +/* + ======================================================================== + + Routine Description: + Send log message through wireless event + + Support standard iw_event with IWEVCUSTOM. It is used below. + + iwreq_data.data.flags is used to store event_flag that is + defined by user. iwreq_data.data.length is the length of the + event log. + + The format of the event log is composed of the entry's MAC + address and the desired log message (refer to + pWirelessEventText). + + ex: 11:22:33:44:55:66 has associated successfully + + p.s. The requirement of Wireless Extension is v15 or newer. + + ======================================================================== +*/ +VOID RtmpOsSendWirelessEvent( + IN VOID *pAd, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi, + IN RTMP_OS_SEND_WLAN_EVENT pFunc) +{ +#if WIRELESS_EXT >= 15 + pFunc(pAd, Event_flag, pAddr, BssIdx, Rssi); +#else + DBGPRINT(RT_DEBUG_ERROR, + ("%s : The Wireless Extension MUST be v15 or newer.\n", + __FUNCTION__)); +#endif /* WIRELESS_EXT >= 15 */ +} +#endif /* SYSTEM_LOG_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID SendSignalToDaemon( + IN INT sig, + RTMP_OS_PID pid, + unsigned long pid_no) +{ +} +#endif /* CONFIG_AP_SUPPORT */ + + +/******************************************************************************* + + File open/close related functions. + + *******************************************************************************/ +RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode) +{ + struct file *filePtr; + + if (flag == RTMP_FILE_RDONLY) + flag = O_RDONLY; + else if (flag == RTMP_FILE_WRONLY) + flag = O_WRONLY; + else if (flag == RTMP_FILE_CREAT) + flag = O_CREAT; + else if (flag == RTMP_FILE_TRUNC) + flag = O_TRUNC; + + filePtr = filp_open(pPath, flag, 0); + if (IS_ERR(filePtr)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(filePtr), pPath)); + } + + return (RTMP_OS_FD) filePtr; +} + + +int RtmpOSFileClose(RTMP_OS_FD osfd) +{ + filp_close(osfd, NULL); + return 0; +} + + +void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset) +{ + osfd->f_pos = offset; +} + + +int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) + /* The object must have a read method */ + if (osfd->f_op && osfd->f_op->read) { + return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); +#else + if (osfd && osfd->f_mode & FMODE_CAN_READ) { + return kernel_read(osfd, pDataPtr, readLen, &osfd->f_pos); +#endif + } else { + DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); + return -1; + } +} + + +int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) + return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen, &osfd->f_pos); +#else + return kernel_write(osfd, pDataPtr, (size_t) writeLen, &osfd->f_pos); +#endif +} + + +static inline void __RtmpOSFSInfoChange(OS_FS_INFO * pOSFSInfo, BOOLEAN bSet) +{ + if (bSet) { + /* Save uid and gid used for filesystem access. */ + /* Set user and group to 0 (root) */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + pOSFSInfo->fsuid = current->fsuid; + pOSFSInfo->fsgid = current->fsgid; + current->fsuid = current->fsgid = 0; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + pOSFSInfo->fsuid = __kuid_val(current_fsuid()); + pOSFSInfo->fsgid = __kgid_val(current_fsgid()); +#else + pOSFSInfo->fsuid = current_fsuid(); + pOSFSInfo->fsgid = current_fsgid(); +#endif + pOSFSInfo->fs = get_fs(); + set_fs(KERNEL_DS); + } else { + set_fs(pOSFSInfo->fs); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + current->fsuid = pOSFSInfo->fsuid; + current->fsgid = pOSFSInfo->fsgid; +#endif + } +} + + +/******************************************************************************* + + Task create/management/kill related functions. + + *******************************************************************************/ +static inline NDIS_STATUS __RtmpOSTaskKill(OS_TASK *pTask) +{ + int ret = NDIS_STATUS_FAILURE; + +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task) { + kthread_stop(pTask->kthread_task); + ret = NDIS_STATUS_SUCCESS; + } +#else + CHECK_PID_LEGALITY(pTask->taskPID) { + DBGPRINT(RT_DEBUG_TRACE, + ("Terminate the task(%s) with pid(%d)!\n", + pTask->taskName, GET_PID_NUMBER(pTask->taskPID))); + mb(); + pTask->task_killed = 1; + mb(); + ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1); + if (ret) { + printk(KERN_WARNING + "kill task(%s) with pid(%d) failed(retVal=%d)!\n", + pTask->taskName, GET_PID_NUMBER(pTask->taskPID), + ret); + } else { + wait_for_completion(&pTask->taskComplete); + pTask->taskPID = THREAD_PID_INIT_VALUE; + pTask->task_killed = 0; + RTMP_SEM_EVENT_DESTORY(&pTask->taskSema); + ret = NDIS_STATUS_SUCCESS; + } + } +#endif + + return ret; + +} + + +static inline INT __RtmpOSTaskNotifyToExit(OS_TASK *pTask) +{ +#ifndef KTHREAD_SUPPORT + pTask->taskPID = THREAD_PID_INIT_VALUE; + complete_and_exit(&pTask->taskComplete, 0); +#endif + + return 0; +} + + +static inline void __RtmpOSTaskCustomize(OS_TASK *pTask) +{ +#ifndef KTHREAD_SUPPORT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + daemonize((PSTRING) & pTask->taskName[0] /*"%s",pAd->net_dev->name */ ); + + allow_signal(SIGTERM); + allow_signal(SIGKILL); + current->flags |= PF_NOFREEZE; +#else + unsigned long flags; + + daemonize(); + reparent_to_init(); + strcpy(current->comm, &pTask->taskName[0]); + + siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); + + /* Allow interception of SIGKILL only + * Don't allow other signals to interrupt the transmission */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + spin_lock_irqsave(¤t->sigmask_lock, flags); + flush_signals(current); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); +#endif +#endif + + RTMP_GET_OS_PID(pTask->taskPID, current->pid); + + /* signal that we've started the thread */ + complete(&pTask->taskComplete); + +#endif +} + + +static inline NDIS_STATUS __RtmpOSTaskAttach( + IN OS_TASK *pTask, + IN RTMP_OS_TASK_CALLBACK fn, + IN ULONG arg) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; +#ifndef KTHREAD_SUPPORT + pid_t pid_number = -1; +#endif /* KTHREAD_SUPPORT */ + +#ifdef KTHREAD_SUPPORT + pTask->task_killed = 0; + pTask->kthread_task = NULL; + pTask->kthread_task = + kthread_run((cast_fn) fn, (void *)arg, pTask->taskName); + if (IS_ERR(pTask->kthread_task)) + status = NDIS_STATUS_FAILURE; +#else + pid_number = + kernel_thread((cast_fn) fn, (void *)arg, RTMP_OS_MGMT_TASK_FLAGS); + if (pid_number < 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Attach task(%s) failed!\n", pTask->taskName)); + status = NDIS_STATUS_FAILURE; + } else { + /* Wait for the thread to start */ + wait_for_completion(&pTask->taskComplete); + status = NDIS_STATUS_SUCCESS; + } +#endif + return status; +} + + +static inline NDIS_STATUS __RtmpOSTaskInit( + IN OS_TASK *pTask, + IN PSTRING pTaskName, + IN VOID *pPriv, + IN LIST_HEADER *pSemList) +{ + int len; + + ASSERT(pTask); + +#ifndef KTHREAD_SUPPORT + NdisZeroMemory((PUCHAR) (pTask), sizeof (OS_TASK)); +#endif + + len = strlen(pTaskName); + len = len > (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len; + NdisMoveMemory(&pTask->taskName[0], pTaskName, len); + pTask->priv = pPriv; + +#ifndef KTHREAD_SUPPORT + RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema), pSemList); + pTask->taskPID = THREAD_PID_INIT_VALUE; + init_completion(&pTask->taskComplete); +#endif + +#ifdef KTHREAD_SUPPORT + init_waitqueue_head(&(pTask->kthread_q)); +#endif /* KTHREAD_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +BOOLEAN __RtmpOSTaskWait( + IN VOID *pReserved, + IN OS_TASK *pTask, + IN INT32 *pStatus) +{ +#ifdef KTHREAD_SUPPORT + RTMP_WAIT_EVENT_INTERRUPTIBLE((*pStatus), pTask); + + if ((pTask->task_killed == 1) || ((*pStatus) != 0)) + return FALSE; +#else + + RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), (*pStatus)); + + /* unlock the device pointers */ + if ((*pStatus) != 0) { +/* RTMP_SET_FLAG_(*pFlags, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ + return FALSE; + } +#endif /* KTHREAD_SUPPORT */ + + return TRUE; +} + + +#if LINUX_VERSION_CODE <= 0x20402 /* Red Hat 7.1 */ +struct net_device *alloc_netdev( + int sizeof_priv, + const char *mask, + void (*setup) (struct net_device *)) +{ + struct net_device *dev; + INT alloc_size; + + /* ensure 32-byte alignment of the private area */ + alloc_size = sizeof (*dev) + sizeof_priv + 31; + + dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL); + if (dev == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("alloc_netdev: Unable to allocate device memory.\n")); + return NULL; + } + + memset(dev, 0, alloc_size); + + if (sizeof_priv) + dev->priv = (void *)(((long)(dev + 1) + 31) & ~31); + + setup(dev); + strcpy(dev->name, mask); + + return dev; +} +#endif /* LINUX_VERSION_CODE */ + + +static UINT32 RtmpOSWirelessEventTranslate(IN UINT32 eventType) +{ + switch (eventType) { + case RT_WLAN_EVENT_CUSTOM: + eventType = IWEVCUSTOM; + break; + + case RT_WLAN_EVENT_CGIWAP: + eventType = SIOCGIWAP; + break; + +#if WIRELESS_EXT > 17 + case RT_WLAN_EVENT_ASSOC_REQ_IE: + eventType = IWEVASSOCREQIE; + break; +#endif /* WIRELESS_EXT */ + +#if WIRELESS_EXT >= 14 + case RT_WLAN_EVENT_SCAN: + eventType = SIOCGIWSCAN; + break; +#endif /* WIRELESS_EXT */ + + case RT_WLAN_EVENT_EXPIRED: + eventType = IWEVEXPIRED; + break; + + default: + printk("Unknown event: 0x%x\n", eventType); + break; + } + + return eventType; +} + + +int RtmpOSWrielessEventSend( + IN PNET_DEV pNetDev, + IN UINT32 eventType, + IN INT flags, + IN PUCHAR pSrcMac, + IN PUCHAR pData, + IN UINT32 dataLen) +{ + union iwreq_data wrqu; + + /* translate event type */ + eventType = RtmpOSWirelessEventTranslate(eventType); + + memset(&wrqu, 0, sizeof (wrqu)); + + if (flags > -1) + wrqu.data.flags = flags; + + if (pSrcMac) + memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); + + if ((pData != NULL) && (dataLen > 0)) + wrqu.data.length = dataLen; + else + wrqu.data.length = 0; + + wireless_send_event(pNetDev, eventType, &wrqu, (char *)pData); + return 0; +} + + +int RtmpOSWrielessEventSendExt( + IN PNET_DEV pNetDev, + IN UINT32 eventType, + IN INT flags, + IN PUCHAR pSrcMac, + IN PUCHAR pData, + IN UINT32 dataLen, + IN UINT32 family) +{ + union iwreq_data wrqu; + + /* translate event type */ + eventType = RtmpOSWirelessEventTranslate(eventType); + + /* translate event type */ + memset(&wrqu, 0, sizeof (wrqu)); + + if (flags > -1) + wrqu.data.flags = flags; + + if (pSrcMac) + memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); + + if ((pData != NULL) && (dataLen > 0)) + wrqu.data.length = dataLen; + + wrqu.addr.sa_family = family; + + wireless_send_event(pNetDev, eventType, &wrqu, (char *)pData); + return 0; +} + + +/* +======================================================================== +Routine Description: + Check if the network interface is up. + +Arguments: + *pDev - Network Interface + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSNetDevIsUp(VOID *pDev) +{ + struct net_device *pNetDev = (struct net_device *)pDev; + + if ((pNetDev == NULL) || !(pNetDev->flags & IFF_UP)) + return FALSE; + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Assign sys_handle data pointer (pAd) to the priv info structured linked to + the OS network interface. + +Arguments: + pDev - the os net device data structure + pPriv - the sys_handle want to assigned + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevPriv(VOID *pDev, VOID *pPriv) +{ + struct mt_dev_priv *priv_info = NULL; + + priv_info = (struct mt_dev_priv *)netdev_priv((struct net_device *)pDev); + + priv_info->sys_handle = (VOID *)pPriv; + priv_info->priv_flags = 0; +} + + +/* +======================================================================== +Routine Description: + Get wifi_dev from the priv info linked to OS network interface data structure. + +Arguments: + pDev - the device + +Return Value: + sys_handle + +Note: +======================================================================== +*/ +VOID *RtmpOsGetNetDevPriv(VOID *pDev) +{ + return ((struct mt_dev_priv *)netdev_priv((struct net_device *)pDev))->sys_handle; +} + + +VOID RtmpOsSetNetDevWdev(VOID *net_dev, VOID *wdev) +{ + struct mt_dev_priv *priv_info; + + priv_info = (struct mt_dev_priv *)netdev_priv((struct net_device *)net_dev); + priv_info->wifi_dev = wdev; +} + + +VOID *RtmpOsGetNetDevWdev(VOID *pDev) +{ + return ((struct mt_dev_priv *)netdev_priv((struct net_device *)pDev))->wifi_dev; +} + + +/* +======================================================================== +Routine Description: + Get private flags from the network interface. + +Arguments: + pDev - the device + +Return Value: + pPriv - the pointer + +Note: +======================================================================== +*/ +USHORT RtmpDevPrivFlagsGet(VOID *pDev) +{ + return ((struct mt_dev_priv *)netdev_priv((struct net_device *)pDev))->priv_flags; +} + + +/* +======================================================================== +Routine Description: + Get private flags from the network interface. + +Arguments: + pDev - the device + +Return Value: + pPriv - the pointer + +Note: +======================================================================== +*/ +VOID RtmpDevPrivFlagsSet(VOID *pDev, USHORT PrivFlags) +{ + struct mt_dev_priv *priv_info; + + priv_info = (struct mt_dev_priv *)netdev_priv((struct net_device *)pDev); + priv_info->priv_flags = PrivFlags; +} + +UCHAR get_sniffer_mode(VOID *pDev) +{ + struct mt_dev_priv *priv_info; + + priv_info = (struct mt_dev_priv *)netdev_priv((struct net_device *)pDev); + return priv_info->sniffer_mode; +} + +VOID set_sniffer_mode(VOID *net_dev, UCHAR sniffer_mode) +{ + struct mt_dev_priv *priv_info; + + priv_info = (struct mt_dev_priv *)netdev_priv((struct net_device *)net_dev); + priv_info->sniffer_mode = sniffer_mode; +} + +/* +======================================================================== +Routine Description: + Get network interface name. + +Arguments: + pDev - the device + +Return Value: + the name + +Note: +======================================================================== +*/ +char *RtmpOsGetNetDevName(VOID *pDev) +{ + return ((PNET_DEV) pDev)->name; +} + + +UINT32 RtmpOsGetNetIfIndex(IN VOID *pDev) { + return ((PNET_DEV) pDev)->ifindex; +} + + +int RtmpOSNetDevAddrSet( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN PUCHAR pMacAddr, + IN PUCHAR dev_name) +{ + struct net_device *net_dev = (struct net_device *)pNetDev; + +#ifdef CONFIG_STA_SUPPORT + /* work-around for the SuSE due to it has it's own interface name management system. */ + RT_CONFIG_IF_OPMODE_ON_STA(OpMode) { + if (dev_name != NULL) { + NdisZeroMemory(dev_name, 16); + NdisMoveMemory(dev_name, net_dev->name, strlen(net_dev->name)); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6); + + return 0; +} + + +/* + * Assign the network dev name for created Ralink WiFi interface. + */ +static int RtmpOSNetDevRequestName( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN PNET_DEV dev, + IN PSTRING pPrefixStr, + IN INT devIdx) +{ + PNET_DEV existNetDev; + STRING suffixName[IFNAMSIZ]; + STRING desiredName[IFNAMSIZ]; + int ifNameIdx, + prefixLen, + slotNameLen; + int Status; + + prefixLen = strlen(pPrefixStr); + ASSERT((prefixLen < IFNAMSIZ)); + + for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) { + memset(suffixName, 0, IFNAMSIZ); + memset(desiredName, 0, IFNAMSIZ); + strncpy(&desiredName[0], pPrefixStr, prefixLen); + +#ifdef MULTIPLE_CARD_SUPPORT +#ifdef RT_SOC_SUPPORT + if (MC_RowID > 0) + sprintf(suffixName, "i%d", ifNameIdx); + else +#else + if (MC_RowID >= 0) + sprintf(suffixName, "%02d_%d", MC_RowID, ifNameIdx); + else +#endif /* RT_SOC_SUPPORT */ +#endif /* MULTIPLE_CARD_SUPPORT */ + sprintf(suffixName, "%d", ifNameIdx); + + slotNameLen = strlen(suffixName); + ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ)); + strcat(desiredName, suffixName); + + existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]); + if (existNetDev == NULL) + break; + else + RtmpOSNetDeviceRefPut(existNetDev); + } + + if (ifNameIdx < 32) { +#ifdef HOSTAPD_SUPPORT + *pIoctlIF = ifNameIdx; +#endif /*HOSTAPD_SUPPORT */ + strcpy(&dev->name[0], &desiredName[0]); + Status = NDIS_STATUS_SUCCESS; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", + pPrefixStr)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + +void RtmpOSNetDevClose(PNET_DEV pNetDev) +{ + dev_close(pNetDev); +} + +void RtmpOSNetDevFree(PNET_DEV pNetDev) +{ + ASSERT(pNetDev); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + free_netdev(pNetDev); +#else + kfree(pNetDev); +#endif + +#ifdef VENDOR_FEATURE4_SUPPORT + printk("OS_NumOfMemAlloc = %ld, OS_NumOfMemFree = %ld\n", + OS_NumOfMemAlloc, OS_NumOfMemFree); +#endif /* VENDOR_FEATURE4_SUPPORT */ +#ifdef VENDOR_FEATURE2_SUPPORT + printk("OS_NumOfPktAlloc = %ld, OS_NumOfPktFree = %ld\n", + OS_NumOfPktAlloc, OS_NumOfPktFree); +#endif /* VENDOR_FEATURE2_SUPPORT */ +} + +INT RtmpOSNetDevAlloc( + IN PNET_DEV *new_dev_p, + IN UINT32 privDataSize) +{ + *new_dev_p = NULL; + + DBGPRINT(RT_DEBUG_TRACE, + ("Allocate a net device with private data size=%d!\n", + privDataSize)); +#if LINUX_VERSION_CODE <= 0x20402 /* Red Hat 7.1 */ + *new_dev_p = alloc_netdev(privDataSize, "eth%d", ether_setup); +#else + *new_dev_p = alloc_etherdev(privDataSize); +#endif /* LINUX_VERSION_CODE */ + + if (*new_dev_p) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +INT RtmpOSNetDevOpsAlloc(PVOID *pNetDevOps) +{ + *pNetDevOps = (PVOID) vmalloc(sizeof (struct net_device_ops)); + if (*pNetDevOps) { + NdisZeroMemory(*pNetDevOps, sizeof (struct net_device_ops)); + return NDIS_STATUS_SUCCESS; + } else { + return NDIS_STATUS_FAILURE; + } +} +#endif + + +PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName) +{ + PNET_DEV pTargetNetDev = NULL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName); +#else + ASSERT(pNetDev); + pTargetNetDev = dev_get_by_name(pNetDev->nd_net, pDevName); +#endif +#else + pTargetNetDev = dev_get_by_name(pDevName); +#endif /* KERNEL_VERSION(2,6,24) */ + +#else + int devNameLen; + + devNameLen = strlen(pDevName); + ASSERT((devNameLen <= IFNAMSIZ)); + + for (pTargetNetDev = dev_base; pTargetNetDev != NULL; + pTargetNetDev = pTargetNetDev->next) { + if (strncmp(pTargetNetDev->name, pDevName, devNameLen) == 0) + break; + } +#endif /* KERNEL_VERSION(2,5,0) */ + + return pTargetNetDev; +} + + +void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + /* + every time dev_get_by_name is called, and it has returned a valid struct + net_device*, dev_put should be called afterwards, because otherwise the + machine hangs when the device is unregistered (since dev->refcnt > 1). + */ + if (pNetDev) + dev_put(pNetDev); +#endif /* LINUX_VERSION_CODE */ +} + + +INT RtmpOSNetDevDestory(VOID *pReserved, PNET_DEV pNetDev) +{ + + /* TODO: Need to fix this */ + printk("WARNING: This function(%s) not implement yet!!!\n", + __FUNCTION__); + return 0; +} + + +void RtmpOSNetDevDetach(PNET_DEV pNetDev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + struct net_device_ops *pNetDevOps = (struct net_device_ops *)pNetDev->netdev_ops; +#endif + + unregister_netdevice(pNetDev); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + vfree(pNetDevOps); +#endif +} + + +void RtmpOSNetDevProtect(BOOLEAN lock_it) +{ + if (lock_it) + rtnl_lock(); + else + rtnl_unlock(); + +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +static void RALINK_ET_DrvInfoGet( + struct net_device *pDev, + struct ethtool_drvinfo *pInfo) +{ + strcpy(pInfo->driver, "RALINK WLAN"); + + + sprintf(pInfo->bus_info, "CSR 0x%lx", pDev->base_addr); +} + +static struct ethtool_ops RALINK_Ethtool_Ops = { + .get_drvinfo = RALINK_ET_DrvInfoGet, +}; +#endif + + +int RtmpOSNetDevAttach( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook) +{ + int ret, + rtnl_locked = FALSE; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + struct net_device_ops *pNetDevOps = (struct net_device_ops *)pNetDev->netdev_ops; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n")); + + /* If we need hook some callback function to the net device structrue, now do it. */ + if (pDevOpHook) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + pNetDevOps->ndo_open = pDevOpHook->open; + pNetDevOps->ndo_stop = pDevOpHook->stop; + pNetDevOps->ndo_start_xmit = + (HARD_START_XMIT_FUNC) (pDevOpHook->xmit); + pNetDevOps->ndo_do_ioctl = pDevOpHook->ioctl; +#else + pNetDev->open = pDevOpHook->open; + pNetDev->stop = pDevOpHook->stop; + pNetDev->hard_start_xmit = + (HARD_START_XMIT_FUNC) (pDevOpHook->xmit); + pNetDev->do_ioctl = pDevOpHook->ioctl; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + pNetDev->ethtool_ops = &RALINK_Ethtool_Ops; +#endif + + /* if you don't implement get_stats, just leave the callback function as NULL, a dummy + function will make kernel panic. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) + pNetDevOps->ndo_get_stats64 = pDevOpHook->get_stats; +#endif + + /* OS specific flags, here we used to indicate if we are virtual interface */ +/* pNetDev->priv_flags = pDevOpHook->priv_flags; */ + RT_DEV_PRIV_FLAGS_SET(pNetDev, pDevOpHook->priv_flags); + +#if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12) +/* pNetDev->get_wireless_stats = rt28xx_get_wireless_stats; */ + pNetDev->get_wireless_stats = pDevOpHook->get_wstats; +#endif + +#ifdef CONFIG_STA_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_STA) { +/* pNetDev->wireless_handlers = &rt28xx_iw_handler_def; */ + pNetDev->wireless_handlers = pDevOpHook->iw_handler; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_AP) { +/* pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def; */ + pNetDev->wireless_handlers = pDevOpHook->iw_handler; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + /* copy the net device mac address to the net_device structure. */ + NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], + MAC_ADDR_LEN); + + rtnl_locked = pDevOpHook->needProtcted; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + pNetDevOps->ndo_validate_addr = NULL; + /*pNetDev->netdev_ops = ops; */ +#else + pNetDev->validate_addr = NULL; +#endif +#endif + + if (rtnl_locked) + ret = register_netdevice(pNetDev); + else + ret = register_netdev(pNetDev); + + netif_stop_queue(pNetDev); + + DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret)); + if (ret == 0) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + + +PNET_DEV RtmpOSNetDevCreate( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN INT devType, + IN INT devNum, + IN INT privMemSize, + IN PSTRING pNamePrefix) +{ + struct net_device *pNetDev = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + struct net_device_ops *pNetDevOps = NULL; +#endif + int status; + + /* allocate a new network device */ + status = RtmpOSNetDevAlloc(&pNetDev, privMemSize); + if (status != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix)); + return NULL; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + status = RtmpOSNetDevOpsAlloc((PVOID) & pNetDevOps); + if (status != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate net device ops fail!\n")); + RtmpOSNetDevFree(pNetDev); + + return NULL; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate net device ops success!\n")); + pNetDev->netdev_ops = pNetDevOps; + } +#endif + /* find a available interface name, max 32 interfaces */ + status = RtmpOSNetDevRequestName(MC_RowID, pIoctlIF, pNetDev, pNamePrefix, devNum); + if (status != NDIS_STATUS_SUCCESS) { + /* error! no any available ra name can be used! */ + DBGPRINT(RT_DEBUG_ERROR, + ("Assign inf name (%s with suffix 0~32) failed\n", pNamePrefix)); + RtmpOSNetDevFree(pNetDev); + + return NULL; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s\n", + pNamePrefix, pNetDev->name)); + } + + return pNetDev; +} + + +#ifdef CONFIG_AP_SUPPORT +UCHAR VLAN_8023_Header_Copy( + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + OUT PUCHAR pData, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID) +{ + UINT16 TCI; + UCHAR VLAN_Size = 0; + + if (VLAN_VID != 0) { + /* need to insert VLAN tag */ + VLAN_Size = LENGTH_802_1Q; + + /* make up TCI field */ + TCI = (VLAN_VID & 0x0fff) | ((VLAN_Priority & 0x7) << 13); + +#ifndef RT_BIG_ENDIAN + TCI = SWAP16(TCI); +#endif /* RT_BIG_ENDIAN */ + + /* copy dst + src MAC (12B) */ + memcpy(pData, pHeader802_3, LENGTH_802_3_NO_TYPE); + + /* copy VLAN tag (4B) */ + /* do NOT use memcpy to speed up */ + *(UINT16 *) (pData + LENGTH_802_3_NO_TYPE) = *(UINT16 *) TPID; + *(UINT16 *) (pData + LENGTH_802_3_NO_TYPE + 2) = TCI; + + /* copy type/len (2B) */ + *(UINT16 *) (pData + LENGTH_802_3_NO_TYPE + LENGTH_802_1Q) = + *(UINT16 *) & pHeader802_3[LENGTH_802_3 - + LENGTH_802_3_TYPE]; + + /* copy tail if exist */ + if (HdrLen > LENGTH_802_3) + memcpy(pData + LENGTH_802_3 + LENGTH_802_1Q, pHeader802_3 + LENGTH_802_3, HdrLen - LENGTH_802_3); + } + else + { + /* no VLAN tag is needed to insert */ + memcpy(pData, pHeader802_3, HdrLen); + } + + return VLAN_Size; +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Allocate memory for adapter control block. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +NDIS_STATUS AdapterBlockAllocateMemory(VOID *handle, VOID **ppAd, UINT32 SizeOfpAd) +{ +#ifdef OS_ABL_FUNC_SUPPORT + /* get offset for sk_buff */ + { + struct sk_buff *pPkt = NULL; + + pPkt = kmalloc(sizeof (struct sk_buff), GFP_ATOMIC); + if (pPkt == NULL) { + *ppAd = NULL; + return NDIS_STATUS_FAILURE; + } + + RTPktOffsetData = (ULONG) (&(pPkt->data)) - (ULONG) pPkt; + RTPktOffsetLen = (ULONG) (&(pPkt->len)) - (ULONG) pPkt; + RTPktOffsetCB = (ULONG) (pPkt->cb) - (ULONG) pPkt; + kfree(pPkt); + + DBGPRINT(RT_DEBUG_TRACE, ("packet> data offset = %lu\n", RTPktOffsetData)); + DBGPRINT(RT_DEBUG_TRACE, ("packet> len offset = %lu\n", RTPktOffsetLen)); + DBGPRINT(RT_DEBUG_TRACE, ("packet> cb offset = %lu\n", RTPktOffsetCB)); + } +#endif /* OS_ABL_FUNC_SUPPORT */ + + *ppAd = (PVOID) vmalloc(SizeOfpAd); + if (*ppAd) { + NdisZeroMemory(*ppAd, SizeOfpAd); + return NDIS_STATUS_SUCCESS; + } else + return NDIS_STATUS_FAILURE; +} + + +/* ========================================================================== */ + +UINT RtmpOsWirelessExtVerGet(VOID) +{ + return WIRELESS_EXT; +} + + +VOID RtmpDrvAllMacPrint( + IN VOID *pReserved, + IN UINT32 *pBufMac, + IN UINT32 AddrStart, + IN UINT32 AddrEnd, + IN UINT32 AddrStep) +{ + struct file *file_w; + PSTRING fileName = "MacDump.txt"; + mm_segment_t orig_fs; + STRING *msg; + UINT32 macAddr = 0, macValue = 0; + + os_alloc_mem(NULL, (UCHAR **)&msg, 1024); + if (!msg) + return; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file */ + file_w = filp_open(fileName, O_WRONLY | O_CREAT, 0); + if (IS_ERR(file_w)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(file_w), fileName)); + } else { + if (file_w->f_op && file_w->f_op->write) { + file_w->f_pos = 0; + macAddr = AddrStart; + + while (macAddr <= AddrEnd) { +/* RTMP_IO_READ32(pAd, macAddr, &macValue); // sample */ + macValue = *pBufMac++; + sprintf(msg, "%04x = %08x\n", macAddr, macValue); + + /* write data to file */ + file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); + + printk("%s", msg); + macAddr += AddrStep; + } + sprintf(msg, "\nDump all MAC values to %s\n", fileName); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); + os_free_mem(NULL, msg); +} + + +VOID RtmpDrvAllE2PPrint( + IN VOID *pReserved, + IN USHORT *pMacContent, + IN UINT32 AddrEnd, + IN UINT32 AddrStep) +{ + struct file *file_w; + PSTRING fileName = "EEPROMDump.txt"; + mm_segment_t orig_fs; + STRING *msg; + USHORT eepAddr = 0; + USHORT eepValue; + + os_alloc_mem(NULL, (UCHAR **)&msg, 1024); + if (!msg) + return; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file */ + file_w = filp_open(fileName, O_WRONLY | O_CREAT, 0); + if (IS_ERR(file_w)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(file_w), fileName)); + } else { + if (file_w->f_op && file_w->f_op->write) { + file_w->f_pos = 0; + eepAddr = 0x00; + + while (eepAddr <= AddrEnd) { + eepValue = *pMacContent; + sprintf(msg, "%08x = %04x\n", eepAddr, eepValue); + + /* write data to file */ + file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); + + printk("%s", msg); + eepAddr += AddrStep; + pMacContent += (AddrStep >> 1); + } + sprintf(msg, "\nDump all EEPROM values to %s\n", + fileName); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); + os_free_mem(NULL, msg); +} + + +VOID RtmpDrvAllRFPrint( + IN VOID *pReserved, + IN UCHAR *pBuf, + IN UINT32 BufLen) +{ + struct file *file_w; + PSTRING fileName = "RFDump.txt"; + mm_segment_t orig_fs; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file */ + file_w = filp_open(fileName, O_WRONLY | O_CREAT, 0); + if (IS_ERR(file_w)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(file_w), fileName)); + } else { + if (file_w->f_op && file_w->f_op->write) { + file_w->f_pos = 0; + /* write data to file */ + file_w->f_op->write(file_w, pBuf, BufLen, &file_w->f_pos); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); +} + + +/* +======================================================================== +Routine Description: + Wake up the command thread. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsCmdUp(RTMP_OS_TASK *pCmdQTask) +{ + OS_TASK *pTask = RTMP_OS_TASK_GET(pCmdQTask); +#ifdef KTHREAD_SUPPORT + pTask->kthread_running = TRUE; + wake_up(&pTask->kthread_q); +#else + CHECK_PID_LEGALITY(pTask->taskPID) { + RTMP_SEM_EVENT_UP(&(pTask->taskSema)); + } +#endif /* KTHREAD_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Wake up USB Mlme thread. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsMlmeUp(IN RTMP_OS_TASK *pMlmeQTask) +{ + OS_TASK *pTask = RTMP_OS_TASK_GET(pMlmeQTask); + +#ifdef KTHREAD_SUPPORT + if ((pTask != NULL) && (pTask->kthread_task)) { + pTask->kthread_running = TRUE; + wake_up(&pTask->kthread_q); + } +#else + if (pTask != NULL) { + CHECK_PID_LEGALITY(pTask->taskPID) { + RTMP_SEM_EVENT_UP(&(pTask->taskSema)); + } + } +#endif /* KTHREAD_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Check if the file is error. + +Arguments: + pFile - the file + +Return Value: + OK or any error + +Note: + rt_linux.h, not rt_drv.h +======================================================================== +*/ +INT32 RtmpOsFileIsErr(IN VOID *pFile) +{ + return IS_FILE_OPEN_ERR(pFile); +} + +int RtmpOSIRQRelease( + IN PNET_DEV pNetDev, + IN UINT32 infType, + IN PPCI_DEV pci_dev, + IN BOOLEAN *pHaveMsi) +{ + struct net_device *net_dev = (struct net_device *)pNetDev; + +#ifdef RTMP_PCI_SUPPORT + if (infType == RTMP_DEV_INF_PCI || infType == RTMP_DEV_INF_PCIE) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + synchronize_irq(pci_dev->irq); +#endif + free_irq(pci_dev->irq, (net_dev)); + RTMP_MSI_DISABLE(pci_dev, pHaveMsi); + } +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + if (infType == RTMP_DEV_INF_RBUS) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + synchronize_irq(net_dev->irq); +#endif + free_irq(net_dev->irq, (net_dev)); + } +#endif /* RTMP_RBUS_SUPPORT */ + + return 0; +} + + +/* +======================================================================== +Routine Description: + Enable or disable wireless event sent. + +Arguments: + pReserved - Reserved + FlgIsWEntSup - TRUE or FALSE + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsWlanEventSet( + IN VOID *pReserved, + IN BOOLEAN *pCfgWEnt, + IN BOOLEAN FlgIsWEntSup) +{ +#if WIRELESS_EXT >= 15 +/* pAd->CommonCfg.bWirelessEvent = FlgIsWEntSup; */ + *pCfgWEnt = FlgIsWEntSup; +#else + *pCfgWEnt = 0; /* disable */ +#endif +} + +/* +======================================================================== +Routine Description: + vmalloc + +Arguments: + Size - memory size + +Return Value: + the memory + +Note: +======================================================================== +*/ +VOID *RtmpOsVmalloc(ULONG Size) +{ + return vmalloc(Size); +} + +/* +======================================================================== +Routine Description: + vfree + +Arguments: + pMem - the memory + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsVfree(VOID *pMem) +{ + if (pMem != NULL) + vfree(pMem); +} + +BOOLEAN RtmpOsStatsAlloc( + IN VOID **ppIwStats) +{ +#if WIRELESS_EXT >= 12 + os_alloc_mem(NULL, (UCHAR **) ppIwStats, sizeof (struct iw_statistics)); + if ((*ppIwStats) == NULL) { + return FALSE; + } + NdisZeroMemory((UCHAR *)* ppIwStats, sizeof (struct iw_statistics)); +#endif + + return TRUE; +} + +VOID RtmpOsTaskPidInit(RTMP_OS_PID *pPid) +{ + *pPid = THREAD_PID_INIT_VALUE; +} + +/* +======================================================================== +Routine Description: + Get the network interface for the packet. + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +PNET_DEV RtmpOsPktNetDevGet(VOID *pPkt) +{ + return GET_OS_PKT_NETDEV(pPkt); +} + + +#ifdef IAPP_SUPPORT +/* Layer 2 Update frame to switch/bridge */ +/* For any Layer2 devices, e.g., bridges, switches and other APs, the frame + can update their forwarding tables with the correct port to reach the new + location of the STA */ +typedef struct GNU_PACKED _RT_IAPP_L2_UPDATE_FRAME { + + UCHAR DA[ETH_ALEN]; /* broadcast MAC address */ + UCHAR SA[ETH_ALEN]; /* the MAC address of the STA that has just associated + or reassociated */ + USHORT Len; /* 8 octets */ + UCHAR DSAP; /* null */ + UCHAR SSAP; /* null */ + UCHAR Control; /* reference to IEEE Std 802.2 */ + UCHAR XIDInfo[3]; /* reference to IEEE Std 802.2 */ +} RT_IAPP_L2_UPDATE_FRAME, *PRT_IAPP_L2_UPDATE_FRAME; + + +PNDIS_PACKET RtmpOsPktIappMakeUp( + IN PNET_DEV pNetDev, + IN UINT8 *pMac) +{ + RT_IAPP_L2_UPDATE_FRAME frame_body; + INT size = sizeof (RT_IAPP_L2_UPDATE_FRAME); + PNDIS_PACKET pNetBuf; + + if (pNetDev == NULL) + return NULL; + + pNetBuf = RtmpOSNetPktAlloc(NULL, size); + if (!pNetBuf) { + DBGPRINT(RT_DEBUG_ERROR, ("Error! Can't allocate a skb.\n")); + return NULL; + } + + /* init the update frame body */ + NdisZeroMemory(&frame_body, size); + + memset(frame_body.DA, 0xFF, ETH_ALEN); + memcpy(frame_body.SA, pMac, ETH_ALEN); + + frame_body.Len = OS_HTONS(ETH_ALEN); + frame_body.DSAP = 0; + frame_body.SSAP = 0x01; + frame_body.Control = 0xAF; + + frame_body.XIDInfo[0] = 0x81; + frame_body.XIDInfo[1] = 1; + frame_body.XIDInfo[2] = 1 << 1; + + SET_OS_PKT_NETDEV(pNetBuf, pNetDev); + skb_reserve(pNetBuf, 2); + memcpy(skb_put(pNetBuf, size), &frame_body, size); + return pNetBuf; +} +#endif /* IAPP_SUPPORT */ + +/* +======================================================================== +Routine Description: + Flush a data cache line. + +Arguments: + AddrStart - the start address + Size - memory size + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsDCacheFlush( + IN ULONG AddrStart, + IN ULONG Size) +{ + RTMP_UTIL_DCACHE_FLUSH(AddrStart, Size); +} + + +#ifdef CONFIG_STA_SUPPORT +INT RtmpOSNotifyRawData( + IN PNET_DEV pNetDev, + IN PUCHAR buff, + IN INT len, + IN ULONG type, + IN USHORT protocol) +{ + struct sk_buff *skb = NULL; + + skb = dev_alloc_skb(len + 2); + + if (!skb) + { + DBGPRINT(RT_DEBUG_ERROR,( "%s: failed to allocate sk_buff for notification\n", pNetDev->name)); + return -ENOMEM; + } + else + { + skb_reserve(skb, 2); + memcpy(skb_put(skb, len), buff, len); + skb->len = len; + skb->dev = pNetDev; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)) + skb->mac.raw = skb->data; +#else + skb_set_mac_header(skb, 0); +#endif + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(protocol); + memset(skb->cb, 0, sizeof(skb->cb)); + + netif_rx(skb); + } + return 0; +} + +#endif /* CONFIG_STA_SUPPORT */ + + +void OS_SPIN_LOCK_IRQSAVE(NDIS_SPIN_LOCK *lock, unsigned long *flags) +{ + spin_lock_irqsave((spinlock_t *)(lock), *flags); +} + +void OS_SPIN_UNLOCK_IRQRESTORE(NDIS_SPIN_LOCK *lock, unsigned long *flags) +{ + spin_unlock_irqrestore((spinlock_t *)(lock), *flags); +} + +void OS_SPIN_LOCK(NDIS_SPIN_LOCK *lock) +{ + spin_lock((spinlock_t *)(lock)); +} + +void OS_SPIN_UNLOCK(NDIS_SPIN_LOCK *lock) +{ + spin_unlock((spinlock_t *)(lock)); +} + +void OS_SPIN_LOCK_IRQ(NDIS_SPIN_LOCK *lock) +{ + spin_lock_irq((spinlock_t *)(lock)); +} + +void OS_SPIN_UNLOCK_IRQ(NDIS_SPIN_LOCK *lock) +{ + spin_unlock_irq((spinlock_t *)(lock)); +} + +int OS_TEST_BIT(int bit, unsigned long *flags) +{ + return test_bit(bit, flags); +} + +void OS_SET_BIT(int bit, unsigned long *flags) +{ + set_bit(bit, flags); +} + +void OS_CLEAR_BIT(int bit, unsigned long *flags) +{ + clear_bit(bit, flags); +} + +#ifndef BB_SOC +void OS_LOAD_CODE_FROM_BIN(unsigned char **image, char *bin_name, void *inf_dev, UINT32 *code_len) +{ + struct device *dev = NULL; + const struct firmware *fw_entry; + +#ifdef RTMP_PCI_SUPPORT + dev = (struct device *)(&(((struct pci_dev *)(inf_dev))->dev)); +#endif + + + if (request_firmware(&fw_entry, bin_name, dev) != 0) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:fw not available(/lib/firmware/%s)\n", __FUNCTION__, bin_name)); + *image = NULL; + return; + } + + *image = kmalloc(fw_entry->size, GFP_KERNEL); + memcpy(*image, fw_entry->data, fw_entry->size); + *code_len = fw_entry->size; + + release_firmware(fw_entry); +} +#endif /* !BB_SOC */ + +#ifdef WSC_NFC_SUPPORT +INT RtmpOSNotifyRawData( + IN PNET_DEV pNetDev, + IN PUCHAR buff, + IN INT len, + IN ULONG type, + IN USHORT protocol) +{ + struct sk_buff *skb = NULL; + + skb = dev_alloc_skb(len+2); + + if (!skb) + { + DBGPRINT(RT_DEBUG_ERROR,( "%s: failed to allocate sk_buff for notification\n", pNetDev->name)); + return -ENOMEM; + } + else + { + skb_reserve(skb, 2); + memcpy(skb_put(skb, len), buff, len); + skb->len = len; + skb->dev = pNetDev; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)) + skb->mac.raw = skb->data; +#else + skb_set_mac_header(skb, 0); +#endif + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(protocol); + memset(skb->cb, 0, sizeof(skb->cb)); + + netif_rx(skb); + } + return 0; +} +#endif /* WSC_NFC_SUPPORT */ +#ifdef OS_ABL_FUNC_SUPPORT +/* +======================================================================== +Routine Description: + Change/Recover file UID/GID. + +Arguments: + pOSFSInfoOrg - the file + bSet - Change (TRUE) or Recover (FALSE) + +Return Value: + None + +Note: + rt_linux.h, not rt_drv.h +======================================================================== +*/ +void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet) +{ + OS_FS_INFO *pOSFSInfo; + + if (bSet == TRUE) { + os_alloc_mem(NULL, (UCHAR **) & (pOSFSInfoOrg->pContent), + sizeof (OS_FS_INFO)); + if (pOSFSInfoOrg->pContent == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc file info fail!\n", __FUNCTION__)); + return; + } else + memset(pOSFSInfoOrg->pContent, 0, sizeof (OS_FS_INFO)); + } + + pOSFSInfo = (OS_FS_INFO *) (pOSFSInfoOrg->pContent); + if (pOSFSInfo == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pOSFSInfo == NULL!\n", __FUNCTION__)); + return; + } + + __RtmpOSFSInfoChange(pOSFSInfo, bSet); + + if (bSet == FALSE) { + if (pOSFSInfoOrg->pContent != NULL) { + os_free_mem(NULL, pOSFSInfoOrg->pContent); + pOSFSInfoOrg->pContent = NULL; + } + } +} + +VOID RtmpOsInitCompletion(RTMP_OS_COMPLETION *pCompletion) +{ + RTMP_OS_Alloc_RscOnly(pCompletion, sizeof(struct completion)); + + init_completion((struct completion *)(pCompletion->pContent)); +} + +VOID RtmpOsExitCompletion(RTMP_OS_COMPLETION *pCompletion) +{ + if (pCompletion->pContent == NULL) + return FALSE; + + os_free_mem(NULL, pCompletion->pContent); + pCompletion->pContent = NULL; + +} + +VOID RtmpOsComplete(RTMP_OS_COMPLETION *pCompletion) +{ + if (pCompletion->pContent == NULL) + return FALSE; + + complete((struct completion *)(pCompletion->pContent)); + + return TRUE; +} + +ULONG RtmpOsWaitForCompletionTimeout(RTMP_OS_COMPLETION *pCompletion, ULONG Timeout) +{ + return wait_for_completion_timeout((struct completion *)(pCompletion->pContent), Timeout); +} + + +/* +======================================================================== +Routine Description: + Activate a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletSche(RTMP_NET_TASK_STRUCT *pTasklet) +{ + if (pTasklet->pContent == NULL) + return FALSE; + +#ifdef WORKQUEUE_BH + schedule_work((struct work_struct *)(pTasklet->pContent)); +#else + tasklet_hi_schedule((OS_NET_TASK_STRUCT *) (pTasklet->pContent)); +#endif /* WORKQUEUE_BH */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Initialize a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletInit( + RTMP_NET_TASK_STRUCT *pTasklet, + VOID (*pFunc) (unsigned long data), + ULONG Data, + LIST_HEADER *pTaskletList) +{ +#ifdef WORKQUEUE_BH + if (RTMP_OS_Alloc_RscOnly(pTasklet, sizeof (struct work_struct)) == FALSE) + return FALSE; + + INIT_WORK((struct work_struct *)(pTasklet->pContent), pFunc); +#else + + if (RTMP_OS_Alloc_RscOnly(pTasklet, sizeof (OS_NET_TASK_STRUCT)) == FALSE) + return FALSE; + + tasklet_init((OS_NET_TASK_STRUCT *) (pTasklet->pContent), pFunc, Data); +#endif /* WORKQUEUE_BH */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Delete a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletKill(RTMP_NET_TASK_STRUCT *pTasklet) +{ + if (pTasklet->pContent != NULL) { +#ifdef WORKQUEUE_BH + cancel_work_sync((OS_NET_TASK_STRUCT *) (pTasklet->pContent)); +#else + tasklet_kill((OS_NET_TASK_STRUCT *) (pTasklet->pContent)); +#endif /* WORKQUEUE_BH */ + + os_free_mem(NULL, pTasklet->pContent); + pTasklet->pContent = NULL; + } + + return TRUE; +} + + +VOID RtmpOsTaskletDataAssign(RTMP_NET_TASK_STRUCT *pTasklet, ULONG Data) +{ +#ifndef WORKQUEUE_BH + if (pTasklet->pContent != NULL) + ((OS_NET_TASK_STRUCT *) (pTasklet->pContent))->data = Data; +#endif /* WORKQUEUE_BH */ +} + + +INT32 RtmpOsTaskIsKilled(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return 1; + return pTask->task_killed; +} + + +VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return; + +#ifdef KTHREAD_SUPPORT + WAKE_UP(pTask); +#else + RTMP_SEM_EVENT_UP(&pTask->taskSema); +#endif +} + + +/* +======================================================================== +Routine Description: + Check if the task is legal. + +Arguments: + pPkt - the packet + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsCheckTaskLegality(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (!pTask) + return FALSE; + +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task == NULL) +#else + CHECK_PID_LEGALITY(pTask->taskPID); + else +#endif + return FALSE; + + return TRUE; +} + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_SetPeriodicTimer(pTimer, timeout); +} + + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + VOID *pReserved, + NDIS_MINIPORT_TIMER *pTimerOrg, + TIMER_FUNCTION function, + PVOID data, + LIST_HEADER *pTimerList) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + if (RTMP_OS_Alloc_RscOnly(pTimerOrg, sizeof (OS_NDIS_MINIPORT_TIMER)) == FALSE) + return; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_OS_Init_Timer(pReserved, pTimer, function, data); +} + + +VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + + if (pTimer) { + if (timer_pending(pTimer)) + return; + + __RTMP_OS_Add_Timer(pTimer, timeout); + } +} + + +VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_OS_Mod_Timer(pTimer, timeout); +} + + +VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_OS_Del_Timer(pTimer, pCancelled); +} + + +VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) { + __RTMP_OS_Release_Timer(pTimer); + + os_free_mem(NULL, pTimer); + pTimerOrg->pContent = NULL; + } +} + + +/* +======================================================================== +Routine Description: + Allocate a OS resource. + +Arguments: + pAd - WLAN control block pointer + pRsc - the resource + RscLen - resource length + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RTMP_OS_Alloc_Rsc( + LIST_HEADER *pRscList, + VOID *pRscSrc, + UINT32 RscLen) +{ + OS_RSTRUC *pRsc = (OS_RSTRUC *) pRscSrc; + + if (pRsc->pContent == NULL) { + /* new entry */ + os_alloc_mem(NULL, (UCHAR **) & (pRsc->pContent), RscLen); + if (pRsc->pContent == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc timer fail!\n", __FUNCTION__)); + return FALSE; + } else { + LIST_RESOURCE_OBJ_ENTRY *pObj; + + /* allocate resource record entry */ + os_alloc_mem(NULL, (UCHAR **) & (pObj), + sizeof (LIST_RESOURCE_OBJ_ENTRY)); + if (pObj == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc timer obj fail!\n", + __FUNCTION__)); + os_free_mem(NULL, pRsc->pContent); + pRsc->pContent = NULL; + return FALSE; + } else { + memset(pRsc->pContent, 0, RscLen); + pObj->pRscObj = (VOID *) pRsc; + + OS_SEM_LOCK(&UtilSemLock); + insertTailList(pRscList, (LIST_ENTRY *) pObj); + OS_SEM_UNLOCK(&UtilSemLock); + } + } + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Allocate a OS resource. + +Arguments: + pAd - WLAN control block pointer + pRsc - the resource + RscLen - resource length + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RTMP_OS_Alloc_RscOnly(VOID *pRscSrc, UINT32 RscLen) +{ + OS_RSTRUC *pRsc = (OS_RSTRUC *) pRscSrc; + + if (pRsc->pContent == NULL) { + /* new entry */ + os_alloc_mem(NULL, (UCHAR **) & (pRsc->pContent), RscLen); + if (pRsc->pContent == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc timer fail!\n", __FUNCTION__)); + return FALSE; + } + memset(pRsc->pContent, 0, RscLen); + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Remove a OS resource. + +Arguments: + pAd - WLAN control block pointer + pRsc - the resource + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RTMP_OS_Remove_Rsc( + LIST_HEADER *pRscList, + VOID *pRscSrc) +{ + LIST_RESOURCE_OBJ_ENTRY *pObj; + OS_RSTRUC *pRscHead, *pRsc, *pRscRev = (OS_RSTRUC *) pRscSrc; + pRscHead = NULL; + + OS_SEM_LOCK(&UtilSemLock); + while(TRUE) + { + pObj = (LIST_RESOURCE_OBJ_ENTRY *) removeHeadList(pRscList); + if (pRscHead == NULL) + pRscHead = pObj->pRscObj; /* backup first entry */ + else if (((ULONG)pRscHead) == ((ULONG)(pObj->pRscObj))) + break; /* has searched all entries */ + + pRsc = (OS_RSTRUC *) (pObj->pRscObj); + if ((ULONG)pRsc == (ULONG)pRscRev) + break; /* find it */ + + /* re-insert it */ + insertTailList(pRscList, (LIST_ENTRY *) pObj); + } + OS_SEM_UNLOCK(&UtilSemLock); + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Free all timers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_OS_Free_Rscs(LIST_HEADER *pRscList) +{ + LIST_RESOURCE_OBJ_ENTRY *pObj; + OS_RSTRUC *pRsc; + + OS_SEM_LOCK(&UtilSemLock); + while (TRUE) { + pObj = (LIST_RESOURCE_OBJ_ENTRY *) removeHeadList(pRscList); + if (pObj == NULL) + break; + pRsc = (OS_RSTRUC *) (pObj->pRscObj); + + if (pRsc->pContent != NULL) { + /* free the timer memory */ + os_free_mem(NULL, pRsc->pContent); + pRsc->pContent = NULL; + } else { + /* + The case is possible because some timers are released during + the driver life time, EX: we will release some timers in + MacTableDeleteEntry(). + But we do not recommend the behavior, i.e. not to release + timers in the driver life time; Or we can not cancel the + timer for timer preemption problem. + */ + } + + os_free_mem(NULL, pObj); /* free the timer record entry */ + } + OS_SEM_UNLOCK(&UtilSemLock); +} + + +/* +======================================================================== +Routine Description: + Allocate a kernel task. + +Arguments: + pTask - the task + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSTaskAlloc(RTMP_OS_TASK *pTask, LIST_HEADER *pTaskList) +{ + if (RTMP_OS_Alloc_RscOnly(pTask, sizeof (OS_TASK)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc task fail!\n", __FUNCTION__)); + return FALSE; /* allocate fail */ + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Free a kernel task. + +Arguments: + pTask - the task + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOSTaskFree(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask != NULL) { + os_free_mem(NULL, pTask); + pTaskOrg->pContent = NULL; + } +} + + +/* +======================================================================== +Routine Description: + Kill a kernel task. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + NDIS_STATUS Status; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask != NULL) { + Status = __RtmpOSTaskKill(pTask); + RtmpOSTaskFree(pTaskOrg); + return Status; + } + + return NDIS_STATUS_FAILURE; +} + + +/* +======================================================================== +Routine Description: + Notify kernel the task exit. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return 0; + return __RtmpOSTaskNotifyToExit(pTask); +} + + +/* +======================================================================== +Routine Description: + Customize the task. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOSTaskCustomize(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask) + __RtmpOSTaskCustomize(pTask); +} + + +/* +======================================================================== +Routine Description: + Activate a kernel task. + +Arguments: + pTaskOrg - the task + fn - task handler + arg - task input argument + +Return Value: + None + +Note: +======================================================================== +*/ +NDIS_STATUS RtmpOSTaskAttach( + RTMP_OS_TASK *pTaskOrg, + RTMP_OS_TASK_CALLBACK fn, + ULONG arg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return NDIS_STATUS_FAILURE; + return __RtmpOSTaskAttach(pTask, fn, arg); +} + + +/* +======================================================================== +Routine Description: + Initialize a kernel task. + +Arguments: + pTaskOrg - the task + pTaskName - task name + pPriv - task input argument + +Return Value: + None + +Note: +======================================================================== +*/ +NDIS_STATUS RtmpOSTaskInit( + RTMP_OS_TASK *pTaskOrg, + PSTRING pTaskName, + VOID *pPriv, + LIST_HEADER *pTaskList, + LIST_HEADER *pSemList) +{ + OS_TASK *pTask; + + if (RtmpOSTaskAlloc(pTaskOrg, pTaskList) == FALSE) + return NDIS_STATUS_FAILURE; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return NDIS_STATUS_FAILURE; + + return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList); +} + + +/* +======================================================================== +Routine Description: + Wait for a event in the task. + +Arguments: + pAd - WLAN control block pointer + pTaskOrg - the task + +Return Value: + TRUE + FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSTaskWait(VOID *pReserved, RTMP_OS_TASK *pTaskOrg, INT32 *pStatus) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return FALSE; + + return __RtmpOSTaskWait(pReserved, pTask, pStatus); +} + + +/* +======================================================================== +Routine Description: + Get private data for the task. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +VOID *RtmpOsTaskDataGet(RTMP_OS_TASK *pTaskOrg) +{ + if (pTaskOrg->pContent == NULL) + return NULL; + + return (((OS_TASK *) (pTaskOrg->pContent))->priv); +} + + +/* +======================================================================== +Routine Description: + Allocate a lock. + +Arguments: + pLock - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsAllocateLock(NDIS_SPIN_LOCK *pLock, LIST_HEADER *pLockList) +{ + if (RTMP_OS_Alloc_RscOnly(pLock, sizeof (OS_NDIS_SPIN_LOCK)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc lock fail!\n", __FUNCTION__)); + return FALSE; /* allocate fail */ + } + + OS_NdisAllocateSpinLock(pLock->pContent); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Free a lock. + +Arguments: + pLockOrg - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsFreeSpinLock(NDIS_SPIN_LOCK *pLockOrg) +{ + /* we will free all locks memory in RTMP_OS_FREE_LOCK() */ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_MINIPORT_TIMER *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_NdisFreeSpinLock(pLock); + + os_free_mem(NULL, pLock); + pLockOrg->pContent = NULL; + } +} + + +/* +======================================================================== +Routine Description: + Spin lock bh. + +Arguments: + pLockOrg - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSpinLockBh(NDIS_SPIN_LOCK *pLockOrg) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_SEM_LOCK(pLock); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Spin unlock bh. + +Arguments: + pLockOrg - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSpinUnLockBh(NDIS_SPIN_LOCK *pLockOrg) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_SEM_UNLOCK(pLock); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Interrupt lock. + +Arguments: + pLockOrg - the lock + pIrqFlags - the lock flags + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsIntLock(NDIS_SPIN_LOCK *pLockOrg, ULONG *pIrqFlags) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_INT_LOCK(pLock, *pIrqFlags); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Interrupt unlock. + +Arguments: + pLockOrg - the lock + IrqFlags - the lock flags + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsIntUnLock(NDIS_SPIN_LOCK *pLockOrg, ULONG IrqFlags) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_INT_UNLOCK(pLock, IrqFlags); + } else + printk("lock> warning! the lock was freed!\n"); +} + +void RtmpOsSpinLockIrqSave(NDIS_SPIN_LOCK *lock, unsigned long *flags) +{ + OS_NDIS_SPIN_LOCK *pLock; + pLock = (OS_NDIS_SPIN_LOCK *) (lock->pContent); + + if (pLock != NULL) + spin_lock_irqsave((spinlock_t *)(pLock), *flags); + else + printk("lock> warning! the lock was freed!\n"); + +} + +void RtmpOsSpinUnlockIrqRestore(NDIS_SPIN_LOCK *lock, unsigned long *flags) +{ + OS_NDIS_SPIN_LOCK *pLock; + pLock = (OS_NDIS_SPIN_LOCK *) (lock->pContent); + + if (pLock != NULL) + spin_unlock_irqrestore((spinlock_t *)(pLock), *flags); + else + printk("lock> warning! the lock was freed!\n"); +} + +void RtmpOsSpinLockIrq(NDIS_SPIN_LOCK *lock) +{ + OS_NDIS_SPIN_LOCK *pLock; + pLock = (OS_NDIS_SPIN_LOCK *) (lock->pContent); + + if (pLock != NULL) + spin_lock_irq((spinlock_t *)(pLock)); + else + printk("lock> warning! the lock was freed!\n"); +} + +void RtmpOsSpinUnlockIrq(NDIS_SPIN_LOCK *lock) +{ + OS_NDIS_SPIN_LOCK *pLock; + pLock = (OS_NDIS_SPIN_LOCK *) (lock->pContent); + + if (pLock != NULL) + spin_unlock_irq((spinlock_t *)(pLock)); + else + printk("lock> warning! the lock was freed!\n"); +} + +/* +======================================================================== +Routine Description: + Get MAC address for the network interface. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +unsigned char *RtmpOsNetDevGetPhyAddr(VOID *pDev) +{ + return RTMP_OS_NETDEV_GET_PHYADDR((PNET_DEV) pDev); +} + + +/* +======================================================================== +Routine Description: + Start network interface TX queue. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsNetQueueStart(PNET_DEV pDev) +{ + RTMP_OS_NETDEV_START_QUEUE(pDev); +} + + +/* +======================================================================== +Routine Description: + Stop network interface TX queue. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsNetQueueStop(PNET_DEV pDev) +{ + RTMP_OS_NETDEV_STOP_QUEUE(pDev); +} + + +/* +======================================================================== +Routine Description: + Wake up network interface TX queue. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsNetQueueWake(PNET_DEV pDev) +{ + RTMP_OS_NETDEV_WAKE_QUEUE(pDev); +} + + +/* +======================================================================== +Routine Description: + Assign network interface to the packet. + +Arguments: + pPkt - the packet + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetPktNetDev(VOID *pPkt, VOID *pDev) +{ + SET_OS_PKT_NETDEV(pPkt, (PNET_DEV) pDev); +} + + +/* +======================================================================== +Routine Description: + Assign network interface type. + +Arguments: + pDev - the device + Type - the type + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevType(VOID *pDev, USHORT Type) +{ + RTMP_OS_NETDEV_SET_TYPE((PNET_DEV) pDev, Type); +} + + +/* +======================================================================== +Routine Description: + Assign network interface type for monitor mode. + +Arguments: + pDev - the device + Type - the type + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevTypeMonitor(VOID *pDev) +{ + RTMP_OS_NETDEV_SET_TYPE((PNET_DEV) pDev, ARPHRD_IEEE80211_PRISM); +} + + +/* +======================================================================== +Routine Description: + Get PID. + +Arguments: + pPkt - the packet + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsGetPid(IN ULONG *pDst, + IN ULONG PID) +{ + RT_GET_OS_PID(*pDst, PID); +} + + +/* +======================================================================== +Routine Description: + Wait for a moment. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsWait(UINT32 Time) +{ + OS_WAIT(Time); +} + + +/* +======================================================================== +Routine Description: + Check if b is smaller than a. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTimerAfter(ULONG a, ULONG b) +{ + return RTMP_TIME_AFTER(a, b); +} + + +/* +======================================================================== +Routine Description: + Check if b is not smaller than a. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTimerBefore(ULONG a, ULONG b) +{ + return RTMP_TIME_BEFORE(a, b); +} + + +/* +======================================================================== +Routine Description: + Get current system time. + +Arguments: + pTime - system time (tick) + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsGetSystemUpTime(ULONG *pTime) +{ + NdisGetSystemUpTime(pTime); +} + +/* +======================================================================== +Routine Description: + Get OS tick unit. + +Arguments: + pOps - Utility table + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTickUnitGet(VOID) +{ + return HZ; +} + + +/* +======================================================================== +Routine Description: + ntohs + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsNtohs(UINT16 Value) +{ + return OS_NTOHS(Value); +} + + +/* +======================================================================== +Routine Description: + htons + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsHtons(UINT16 Value) +{ + return OS_HTONS(Value); +} + + +/* +======================================================================== +Routine Description: + ntohl + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsNtohl(UINT32 Value) +{ + return OS_NTOHL(Value); +} + +/* +======================================================================== +Routine Description: + htonl + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsHtonl(UINT32 Value) +{ + return OS_HTONL(Value); +} + + +/* +======================================================================== +Routine Description: + get_unaligned for 16-bit value. + +Arguments: + pWord - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsGetUnaligned(UINT16 *pWord) +{ + return get_unaligned(pWord); +} + +/* +======================================================================== +Routine Description: + get_unaligned for 32-bit value. + +Arguments: + pWord - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsGetUnaligned32(UINT32 *pWord) +{ + return get_unaligned(pWord); +} + +/* +======================================================================== +Routine Description: + get_unaligned for long-bit value. + +Arguments: + pWord - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +ULONG RtmpOsGetUnalignedlong(ULONG *pWord) +{ + return get_unaligned(pWord); +} + + +/* +======================================================================== +Routine Description: + Get maximum scan data length. + +Arguments: + None + +Return Value: + length + +Note: + Used in site servey. +======================================================================== +*/ +ULONG RtmpOsMaxScanDataGet(VOID) +{ + return IW_SCAN_MAX_DATA; +} + + +/* +======================================================================== +Routine Description: + copy_from_user + +Arguments: + to - + from - + n - size + +Return Value: + copy size + +Note: +======================================================================== +*/ +ULONG RtmpOsCopyFromUser(VOID *to, const void *from, ULONG n) +{ + return (copy_from_user(to, from, n)); +} + + +/* +======================================================================== +Routine Description: + copy_to_user + +Arguments: + to - + from - + n - size + +Return Value: + copy size + +Note: +======================================================================== +*/ +ULONG RtmpOsCopyToUser(VOID *to, const void *from, ULONG n) +{ + return (copy_to_user(to, from, n)); +} + + +/* +======================================================================== +Routine Description: + Initialize a semaphore. + +Arguments: + pSem - the semaphore + +Return Value: + TRUE - Successfully + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsSemaInitLocked(RTMP_OS_SEM *pSem, LIST_HEADER *pSemList) +{ + if (RTMP_OS_Alloc_RscOnly(pSem, sizeof (OS_SEM)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc semaphore fail!\n", __FUNCTION__)); + return FALSE; + } + + OS_SEM_EVENT_INIT_LOCKED((OS_SEM *) (pSem->pContent)); + return TRUE; +} + + + +/* +======================================================================== +Routine Description: + Initialize a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + TRUE - Successfully + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsSemaInit(RTMP_OS_SEM *pSem, LIST_HEADER *pSemList) +{ + if (RTMP_OS_Alloc_RscOnly(pSem, sizeof (OS_SEM)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc semaphore fail!\n", __FUNCTION__)); + return FALSE; + } + + OS_SEM_EVENT_INIT((OS_SEM *) (pSem->pContent)); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Destroy a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + TRUE - Successfully + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsSemaDestory(RTMP_OS_SEM *pSemOrg) +{ + OS_SEM *pSem; + + pSem = (OS_SEM *) (pSemOrg->pContent); + if (pSem != NULL) { + OS_SEM_EVENT_DESTORY(pSem); + + os_free_mem(NULL, pSem); + pSemOrg->pContent = NULL; + } else + printk("sem> warning! double-free sem!\n"); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Wait a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + 0 - Successfully + Otherwise - Fail + +Note: +======================================================================== +*/ +INT32 RtmpOsSemaWaitInterruptible(RTMP_OS_SEM *pSemOrg) +{ + OS_SEM *pSem; + INT Status = -1; + + pSem = (OS_SEM *) (pSemOrg->pContent); + if (pSem != NULL) + OS_SEM_EVENT_WAIT(pSem, Status); + return Status; +} + + +/* +======================================================================== +Routine Description: + Wake up a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSemaWakeUp(RTMP_OS_SEM *pSemOrg) +{ + OS_SEM *pSem; + + pSem = (OS_SEM *) (pSemOrg->pContent); + if (pSem != NULL) + OS_SEM_EVENT_UP(pSem); +} + + +/* +======================================================================== +Routine Description: + Check if we are in a interrupt. + +Arguments: + None + +Return Value: + 0 - No + Otherwise - Yes + +Note: +======================================================================== +*/ +INT32 RtmpOsIsInInterrupt(VOID) +{ + return (in_interrupt()); +} + + +/* +======================================================================== +Routine Description: + Copy the data buffer to the packet frame body. + +Arguments: + pAd - WLAN control block pointer + pNetPkt - the packet + ThisFrameLen - copy length + pData - the data buffer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktBodyCopy( + PNET_DEV pNetDev, + PNDIS_PACKET pNetPkt, + ULONG ThisFrameLen, + PUCHAR pData) +{ + memcpy(skb_put(pNetPkt, ThisFrameLen), pData, ThisFrameLen); + SET_OS_PKT_NETDEV(pNetPkt, pNetDev); +} + + +/* +======================================================================== +Routine Description: + Check if the packet is cloned. + +Arguments: + pNetPkt - the packet + +Return Value: + TRUE - Yes + Otherwise - No + +Note: +======================================================================== +*/ +INT RtmpOsIsPktCloned(PNDIS_PACKET pNetPkt) +{ + return OS_PKT_CLONED(pNetPkt); +} + + +/* +======================================================================== +Routine Description: + Duplicate a packet. + +Arguments: + pNetPkt - the packet + +Return Value: + the new packet + +Note: +======================================================================== +*/ +PNDIS_PACKET RtmpOsPktCopy(PNDIS_PACKET pNetPkt) +{ + return skb_copy(RTPKT_TO_OSPKT(pNetPkt), GFP_ATOMIC); +} + + +/* +======================================================================== +Routine Description: + Clone a packet. + +Arguments: + pNetPkt - the packet + +Return Value: + the cloned packet + +Note: +======================================================================== +*/ +PNDIS_PACKET RtmpOsPktClone(PNDIS_PACKET pNetPkt) +{ + return skb_clone(RTPKT_TO_OSPKT(pNetPkt), MEM_ALLOC_FLAG); +} + + +/* +======================================================================== +Routine Description: + Assign the data pointer for the packet. + +Arguments: + pNetPkt - the packet + *pData - the data buffer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktDataPtrAssign(PNDIS_PACKET pNetPkt, UCHAR *pData) +{ + SET_OS_PKT_DATAPTR(pNetPkt, pData); +} + + +/* +======================================================================== +Routine Description: + Assign the data length for the packet. + +Arguments: + pNetPkt - the packet + Len - the data length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktLenAssign(PNDIS_PACKET pNetPkt, LONG Len) +{ + SET_OS_PKT_LEN(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + Adjust the tail pointer for the packet. + +Arguments: + pNetPkt - the packet + removedTagLen - the size for adjustment + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktTailAdjust(PNDIS_PACKET pNetPkt, UINT removedTagLen) +{ + OS_PKT_TAIL_ADJUST(pNetPkt, removedTagLen); +} + + +/* +======================================================================== +Routine Description: + Adjust the data pointer for the packet. + +Arguments: + pNetPkt - the packet + Len - the size for adjustment + +Return Value: + the new data pointer for the packet + +Note: +======================================================================== +*/ +PUCHAR RtmpOsPktTailBufExtend(PNDIS_PACKET pNetPkt, UINT Len) +{ + return OS_PKT_TAIL_BUF_EXTEND(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + adjust headroom for the packet. + +Arguments: + pNetPkt - the packet + Len - the size for adjustment + +Return Value: + the new data pointer for the packet + +Note: +======================================================================== +*/ +VOID RtmpOsPktReserve(PNDIS_PACKET pNetPkt, UINT Len) +{ + OS_PKT_RESERVE(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + Adjust the data pointer for the packet. + +Arguments: + pNetPkt - the packet + Len - the size for adjustment + +Return Value: + the new data pointer for the packet + +Note: +======================================================================== +*/ +PUCHAR RtmpOsPktHeadBufExtend(PNDIS_PACKET pNetPkt, UINT Len) +{ + return OS_PKT_HEAD_BUF_EXTEND(pNetPkt, Len); +} + + +INT32 RtmpThreadPidKill(RTMP_OS_PID PID) +{ + return KILL_THREAD_PID(PID, SIGTERM, 1); +} + + +long RtmpOsSimpleStrtol(const char *cp, char **endp, unsigned int base) +{ + return simple_strtol(cp, endp, base); +} + + +BOOLEAN RtmpOsPktOffsetInit(VOID) +{ + struct sk_buff *pPkt = NULL; + + if ((RTPktOffsetData == 0) && (RTPktOffsetLen == 0) + && (RTPktOffsetCB == 0)) { + pPkt = kmalloc(sizeof (struct sk_buff), GFP_ATOMIC); + if (pPkt == NULL) + return FALSE; + + RTPktOffsetData = (ULONG) (&(pPkt->data)) - (ULONG) pPkt; + RTPktOffsetLen = (ULONG) (&(pPkt->len)) - (ULONG) pPkt; + RTPktOffsetCB = (ULONG) (pPkt->cb) - (ULONG) pPkt; + kfree(pPkt); + + DBGPRINT(RT_DEBUG_TRACE, + ("packet> data offset = %lu\n", RTPktOffsetData)); + DBGPRINT(RT_DEBUG_TRACE, + ("packet> len offset = %lu\n", RTPktOffsetLen)); + DBGPRINT(RT_DEBUG_TRACE, + ("packet> cb offset = %lu\n", RTPktOffsetCB)); + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Initialize the OS atomic_t. + +Arguments: + pAtomic - the atomic + +Return Value: + TRUE - allocation successfully + FALSE - allocation fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsAtomicInit(RTMP_OS_ATOMIC *pAtomic, LIST_HEADER *pAtomicList) +{ + if (RTMP_OS_Alloc_RscOnly(pAtomic, sizeof (atomic_t)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc atomic fail!\n", __FUNCTION__)); + return FALSE; /* allocate fail */ + } + + return TRUE; +} + +/* +======================================================================== +Routine Description: + Initialize the OS atomic_t. + +Arguments: + pAtomic - the atomic + +Return Value: + TRUE - allocation successfully + FALSE - allocation fail + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicDestroy(RTMP_OS_ATOMIC *pAtomic) +{ + if (pAtomic->pContent) { + os_free_mem(NULL, pAtomic->pContent); + pAtomic->pContent = NULL; + } +} + +/* +======================================================================== +Routine Description: + Atomic read a variable. + +Arguments: + pAtomic - the atomic + +Return Value: + content + +Note: +======================================================================== +*/ +LONG RtmpOsAtomicRead(RTMP_OS_ATOMIC *pAtomicSrc) +{ + if (pAtomicSrc->pContent) + return atomic_read((atomic_t *) (pAtomicSrc->pContent)); + else + return 0; +} + + +/* +======================================================================== +Routine Description: + Atomic dec a variable. + +Arguments: + pAtomic - the atomic + +Return Value: + content + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicDec(RTMP_OS_ATOMIC *pAtomicSrc) +{ + if (pAtomicSrc->pContent) + atomic_dec((atomic_t *) (pAtomicSrc->pContent)); +} + + +/* +======================================================================== +Routine Description: + Sets a 32-bit variable to the specified value as an atomic operation. + +Arguments: + pAtomic - the atomic + Value - the value to be exchanged + +Return Value: + the initial value of the pAtomicSrc parameter + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicInterlockedExchange( + RTMP_OS_ATOMIC *pAtomicSrc, + LONG Value) +{ + if (pAtomicSrc->pContent) + InterlockedExchange((atomic_t *) (pAtomicSrc->pContent), Value); +} + + +/* +======================================================================== +Routine Description: + Initialize the OS utilities. + +Arguments: + pOps - Utility table + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsOpsInit(RTMP_OS_ABL_OPS *pOps) +{ + pOps->ra_printk = (RTMP_PRINTK)printk; + pOps->ra_snprintf = (RTMP_SNPRINTF)snprintf; +} + +#else /* OS_ABL_FUNC_SUPPORT */ + + +void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet) +{ + __RtmpOSFSInfoChange(pOSFSInfoOrg, bSet); +} + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout) +{ + __RTMP_SetPeriodicTimer(pTimerOrg, timeout); +} + + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + VOID *pReserved, + NDIS_MINIPORT_TIMER *pTimerOrg, + TIMER_FUNCTION function, + PVOID data, + LIST_HEADER *pTimerList) +{ + __RTMP_OS_Init_Timer(pReserved, pTimerOrg, function, data); +} + + +VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout) +{ + __RTMP_OS_Add_Timer(pTimerOrg, timeout); +} + + +VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout) +{ + __RTMP_OS_Mod_Timer(pTimerOrg, timeout); +} + + +VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled) +{ + __RTMP_OS_Del_Timer(pTimerOrg, pCancelled); +} + + +VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg) +{ + __RTMP_OS_Release_Timer(pTimerOrg); +} + + +NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTask) +{ + return __RtmpOSTaskKill(pTask); +} + + +INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTask) +{ + return __RtmpOSTaskNotifyToExit(pTask); +} + + +void RtmpOSTaskCustomize(RTMP_OS_TASK *pTask) +{ + __RtmpOSTaskCustomize(pTask); +} + + +NDIS_STATUS RtmpOSTaskAttach( + RTMP_OS_TASK *pTask, + RTMP_OS_TASK_CALLBACK fn, + ULONG arg) +{ + return __RtmpOSTaskAttach(pTask, fn, arg); +} + + +NDIS_STATUS RtmpOSTaskInit( + RTMP_OS_TASK *pTask, + PSTRING pTaskName, + VOID *pPriv, + LIST_HEADER *pTaskList, + LIST_HEADER *pSemList) +{ + return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList); +} + + +BOOLEAN RtmpOSTaskWait(VOID *pReserved, RTMP_OS_TASK * pTask, INT32 *pStatus) +{ + return __RtmpOSTaskWait(pReserved, pTask, pStatus); +} + + +VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTask) +{ +#ifdef KTHREAD_SUPPORT + WAKE_UP(pTask); +#else + RTMP_SEM_EVENT_UP(&pTask->taskSema); +#endif +} + +#endif /* OS_ABL_FUNC_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_linux_symb.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_linux_symb.c new file mode 100644 index 000000000..a2e29dc6d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_linux_symb.c @@ -0,0 +1,329 @@ +/**************************************************************************** + + Module Name: + UTIL/rt_linux_symb.c + + Abstract: + All symbols provided from UTIL module are put here. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" + + +#ifdef OS_ABL_FUNC_SUPPORT + +EXPORT_SYMBOL(RTDebugLevel); +EXPORT_SYMBOL(RTDebugFunc); + +/* utility */ +EXPORT_SYMBOL(RtmpUtilInit); +EXPORT_SYMBOL(RTMPFreeNdisPacket); +EXPORT_SYMBOL(AdapterBlockAllocateMemory); + +EXPORT_SYMBOL(RTMP_SetPeriodicTimer); +EXPORT_SYMBOL(RTMP_OS_Add_Timer); +EXPORT_SYMBOL(RTMP_OS_Mod_Timer); +EXPORT_SYMBOL(RTMP_OS_Del_Timer); +EXPORT_SYMBOL(RTMP_OS_Init_Timer); +EXPORT_SYMBOL(RTMP_OS_Release_Timer); + +EXPORT_SYMBOL(RTMP_OS_Alloc_Rsc); +EXPORT_SYMBOL(RTMP_OS_Free_Rscs); + +EXPORT_SYMBOL(os_alloc_mem); +EXPORT_SYMBOL(os_alloc_mem_suspend); +EXPORT_SYMBOL(os_free_mem); + +EXPORT_SYMBOL(ExpandPacket); +EXPORT_SYMBOL(ClonePacket); +EXPORT_SYMBOL(RTMP_AllocateFragPacketBuffer); +EXPORT_SYMBOL(RtmpOSNetPktAlloc); +EXPORT_SYMBOL(duplicate_pkt_with_TKIP_MIC); +EXPORT_SYMBOL(RTMPAllocateNdisPacket); +EXPORT_SYMBOL(RTMP_QueryPacketInfo); +EXPORT_SYMBOL(DuplicatePacket); +EXPORT_SYMBOL(duplicate_pkt); +EXPORT_SYMBOL(RTMPL2FrameTxAction); +EXPORT_SYMBOL(RtmpOsPktBodyCopy); +EXPORT_SYMBOL(RtmpOsIsPktCloned); +EXPORT_SYMBOL(RtmpOsPktCopy); +EXPORT_SYMBOL(RtmpOsPktClone); +EXPORT_SYMBOL(RtmpOsPktDataPtrAssign); +EXPORT_SYMBOL(RtmpOsPktLenAssign); +EXPORT_SYMBOL(RtmpOsPktTailAdjust); +EXPORT_SYMBOL(RtmpOsPktTailBufExtend); +EXPORT_SYMBOL(RtmpOsPktHeadBufExtend); +EXPORT_SYMBOL(RtmpOsPktReserve); +EXPORT_SYMBOL(RtmpThreadPidKill); +#ifdef IAPP_SUPPORT +EXPORT_SYMBOL(RtmpOsPktIappMakeUp); +#endif /* IAPP_SUPPORT */ +EXPORT_SYMBOL(RtmpOsPktInit); +#ifdef CONFIG_AP_SUPPORT +EXPORT_SYMBOL(VLAN_8023_Header_Copy); +#endif /* CONFIG_AP_SUPPORT */ +EXPORT_SYMBOL(wlan_802_11_to_802_3_packet); +EXPORT_SYMBOL(RtmpOsPktOffsetInit); +EXPORT_SYMBOL(RtmpOSNetDevCreate); +EXPORT_SYMBOL(RtmpOSNetDevClose); +EXPORT_SYMBOL(RtmpOSNetDevAttach); +EXPORT_SYMBOL(RtmpOSNetDevDetach); +EXPORT_SYMBOL(RtmpOSNetDevFree); +EXPORT_SYMBOL(RtmpOSNetDevIsUp); +EXPORT_SYMBOL(RtmpOsNetDevGetPhyAddr); +EXPORT_SYMBOL(RtmpOsNetQueueStart); +EXPORT_SYMBOL(RtmpOsNetQueueStop); +EXPORT_SYMBOL(RtmpOsNetQueueWake); +EXPORT_SYMBOL(RtmpOsSetPktNetDev); +EXPORT_SYMBOL(RtmpOsPktNetDevGet); +EXPORT_SYMBOL(RtmpOsGetNetDevName); +EXPORT_SYMBOL(RtmpOsGetNetIfIndex); +EXPORT_SYMBOL(RtmpOsSetNetDevPriv); +EXPORT_SYMBOL(RtmpOsGetNetDevPriv); +EXPORT_SYMBOL(RtmpDevPrivFlagsGet); +EXPORT_SYMBOL(RtmpOsSetNetDevType); +EXPORT_SYMBOL(RtmpOsSetNetDevTypeMonitor); +EXPORT_SYMBOL(get_sniffer_mode); +EXPORT_SYMBOL(set_sniffer_mode); +#ifdef ETH_CONVERT_SUPPORT +EXPORT_SYMBOL(RtmpOsNetPrivGet); +#endif /* ETH_CONVERT_SUPPORT */ +EXPORT_SYMBOL(RtmpOSNetDevAddrSet); + +EXPORT_SYMBOL(RtmpOSFileOpen); +EXPORT_SYMBOL(RtmpOSFSInfoChange); +EXPORT_SYMBOL(RtmpOSFileWrite); +EXPORT_SYMBOL(RtmpOSFileRead); +EXPORT_SYMBOL(RtmpOSFileClose); +EXPORT_SYMBOL(RtmpOSFileSeek); +EXPORT_SYMBOL(RtmpOsFileIsErr); + +EXPORT_SYMBOL(RtmpOSTaskNotifyToExit); +EXPORT_SYMBOL(RtmpOSTaskInit); +EXPORT_SYMBOL(RtmpOSTaskAttach); +EXPORT_SYMBOL(RtmpOSTaskCustomize); +EXPORT_SYMBOL(RtmpOSTaskKill); +EXPORT_SYMBOL(RtmpOSTaskAlloc); +EXPORT_SYMBOL(RtmpOSTaskFree); +EXPORT_SYMBOL(RtmpOSTaskWait); +EXPORT_SYMBOL(RtmpOsCheckTaskLegality); +EXPORT_SYMBOL(RtmpOsTaskDataGet); +EXPORT_SYMBOL(RtmpOsTaskIsKilled); +EXPORT_SYMBOL(RtmpOsTaskWakeUp); +EXPORT_SYMBOL(RtmpOsInitCompletion); +EXPORT_SYMBOL(RtmpOsExitCompletion); +EXPORT_SYMBOL(RtmpOsComplete); +EXPORT_SYMBOL(RtmpOsWaitForCompletionTimeout); + +EXPORT_SYMBOL(RtmpOsTaskletSche); +EXPORT_SYMBOL(RtmpOsTaskletInit); +EXPORT_SYMBOL(RtmpOsTaskletKill); +EXPORT_SYMBOL(RtmpOsTaskletDataAssign); +EXPORT_SYMBOL(RtmpOsTaskPidInit); + +EXPORT_SYMBOL(RtmpOsAllocateLock); +EXPORT_SYMBOL(RtmpOsFreeSpinLock); +EXPORT_SYMBOL(RtmpOsSpinLockBh); +EXPORT_SYMBOL(RtmpOsSpinUnLockBh); +EXPORT_SYMBOL(RtmpOsIntLock); +EXPORT_SYMBOL(RtmpOsIntUnLock); + +EXPORT_SYMBOL(RtmpOsSemaInitLocked); +EXPORT_SYMBOL(RtmpOsSemaInit); +EXPORT_SYMBOL(RtmpOsSemaDestory); +EXPORT_SYMBOL(RtmpOsSemaWaitInterruptible); +EXPORT_SYMBOL(RtmpOsSemaWakeUp); +EXPORT_SYMBOL(RtmpOsMlmeUp); + +EXPORT_SYMBOL(RtmpOsGetPid); + +EXPORT_SYMBOL(RtmpOsWait); +EXPORT_SYMBOL(RtmpOsTimerAfter); +EXPORT_SYMBOL(RtmpOsTimerBefore); +EXPORT_SYMBOL(RtmpOsGetSystemUpTime); + +EXPORT_SYMBOL(RtmpOsDCacheFlush); + +#ifdef RTMP_PCI_SUPPORT +EXPORT_SYMBOL(RTMP_PCI_Readl); +EXPORT_SYMBOL(RTMP_PCI_Readw); +EXPORT_SYMBOL(RTMP_PCI_Readb); +EXPORT_SYMBOL(RTMP_PCI_Writel); +EXPORT_SYMBOL(RTMP_PCI_Writew); +EXPORT_SYMBOL(RTMP_PCI_Writeb); +EXPORT_SYMBOL(RtmpOsPciConfigReadWord); +EXPORT_SYMBOL(RtmpOsPciConfigWriteWord); +EXPORT_SYMBOL(RtmpOsPciConfigReadDWord); +EXPORT_SYMBOL(RtmpOsPciConfigWriteDWord); +EXPORT_SYMBOL(RtmpOsPciFindCapability); +EXPORT_SYMBOL(RtmpOsPciMsiEnable); +EXPORT_SYMBOL(RTMPFindHostPCIDev); +#endif /* RTMP_PCI_SUPPORT */ + +EXPORT_SYMBOL(RtmpOsNtohs); +EXPORT_SYMBOL(RtmpOsHtons); +EXPORT_SYMBOL(RtmpOsNtohl); +EXPORT_SYMBOL(RtmpOsHtonl); + +EXPORT_SYMBOL(RtmpOsVmalloc); +EXPORT_SYMBOL(RtmpOsVfree); +EXPORT_SYMBOL(RtmpOsCopyFromUser); +EXPORT_SYMBOL(RtmpOsCopyToUser); + +EXPORT_SYMBOL(RtmpOsCmdUp); +EXPORT_SYMBOL(RtmpOsCmdDisplayLenCheck); + +EXPORT_SYMBOL(hex_dump); +EXPORT_SYMBOL(RtmpOsSendWirelessEvent); +EXPORT_SYMBOL(RTMP_GetCurrentSystemTime); +EXPORT_SYMBOL(RTMP_GetCurrentSystemTick); +EXPORT_SYMBOL(RTMPMsecsToJiffies); +EXPORT_SYMBOL(RtmpusecDelay); +EXPORT_SYMBOL(RtmpOsMsDelay); +EXPORT_SYMBOL(RtmpOSWrielessEventSend); +EXPORT_SYMBOL(RtmpOSWrielessEventSendExt); +EXPORT_SYMBOL(RtmpOsTickUnitGet); +EXPORT_SYMBOL(RtmpOsOpsInit); +EXPORT_SYMBOL(RtmpOsGetUnaligned); +EXPORT_SYMBOL(RtmpOsGetUnaligned32); +EXPORT_SYMBOL(RtmpOsGetUnalignedlong); +EXPORT_SYMBOL(RtmpOsMaxScanDataGet); +EXPORT_SYMBOL(RtmpDrvRateGet); +EXPORT_SYMBOL(RtmpOsWirelessExtVerGet); +EXPORT_SYMBOL(rtstrchr); +EXPORT_SYMBOL(RtmpOsIsInInterrupt); +EXPORT_SYMBOL(RtmpOsSimpleStrtol); +EXPORT_SYMBOL(RtmpOsStatsAlloc); + +EXPORT_SYMBOL(RtmpOsAtomicInit); +EXPORT_SYMBOL(RtmpOsAtomicDestroy); +EXPORT_SYMBOL(RtmpOsAtomicRead); +EXPORT_SYMBOL(RtmpOsAtomicDec); +EXPORT_SYMBOL(RtmpOsAtomicInterlockedExchange); + +EXPORT_SYMBOL(RtmpDrvAllMacPrint); +EXPORT_SYMBOL(RtmpDrvAllE2PPrint); +EXPORT_SYMBOL(RtmpDrvAllRFPrint); +EXPORT_SYMBOL(RtmpOsGetNetDevWdev); +EXPORT_SYMBOL(RtmpOsSetNetDevWdev); +EXPORT_SYMBOL(RtmpMeshDown); +EXPORT_SYMBOL(RtmpOSIRQRelease); +EXPORT_SYMBOL(RtmpOsWlanEventSet); + +/* cfg80211 */ +#ifdef RT_CFG80211_SUPPORT +extern UCHAR Cfg80211_Chan[]; +EXPORT_SYMBOL(CFG80211OS_UnRegister); +EXPORT_SYMBOL(CFG80211_SupBandInit); +EXPORT_SYMBOL(Cfg80211_Chan); +EXPORT_SYMBOL(CFG80211OS_RegHint); +EXPORT_SYMBOL(CFG80211OS_RegHint11D); +EXPORT_SYMBOL(CFG80211OS_BandInfoGet); +EXPORT_SYMBOL(CFG80211OS_ChanNumGet); +EXPORT_SYMBOL(CFG80211OS_ChanInfoGet); +EXPORT_SYMBOL(CFG80211OS_ChanInfoInit); +EXPORT_SYMBOL(CFG80211OS_Scaning); +EXPORT_SYMBOL(CFG80211OS_ScanEnd); +EXPORT_SYMBOL(CFG80211OS_ConnectResultInform); +EXPORT_SYMBOL(CFG80211OS_P2pClientConnectResultInform); +EXPORT_SYMBOL(CFG80211OS_SupBandReInit); +EXPORT_SYMBOL(CFG80211OS_RxMgmt); +EXPORT_SYMBOL(CFG80211OS_TxStatus); +EXPORT_SYMBOL(CFG80211OS_NewSta); +EXPORT_SYMBOL(CFG80211OS_DelSta); +EXPORT_SYMBOL(CFG80211OS_MICFailReport); +#endif /* RT_CFG80211_SUPPORT */ + +/* global variables */ +EXPORT_SYMBOL(RTPktOffsetData); +EXPORT_SYMBOL(RTPktOffsetLen); +EXPORT_SYMBOL(RTPktOffsetCB); + +#ifdef VENDOR_FEATURE4_SUPPORT +EXPORT_SYMBOL(OS_NumOfMemAlloc); +EXPORT_SYMBOL(OS_NumOfMemFree); +#endif /* VENDOR_FEATURE4_SUPPORT */ + +#ifdef VENDOR_FEATURE2_SUPPORT +EXPORT_SYMBOL(OS_NumOfPktAlloc); +EXPORT_SYMBOL(OS_NumOfPktFree); +#endif /* VENDOR_FEATURE2_SUPPORT */ + +/* only for AP */ +#ifdef CONFIG_AP_SUPPORT +EXPORT_SYMBOL(duplicate_pkt_with_VLAN); +#ifdef BG_FT_SUPPORT +EXPORT_SYMBOL(BG_FTPH_Init); +EXPORT_SYMBOL(BG_FTPH_Remove); +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +//EXPORT_SYMBOL(ralinkrate); +EXPORT_SYMBOL(RalinkRate_HT_1NSS); +EXPORT_SYMBOL(RalinkRate_VHT_1NSS); +EXPORT_SYMBOL(RalinkRate_Legacy); +EXPORT_SYMBOL(RT_RateSize); +EXPORT_SYMBOL(send_prism_monitor_packets); +EXPORT_SYMBOL(send_radiotap_monitor_packets); +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +EXPORT_SYMBOL(wext_notify_event_assoc); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +EXPORT_SYMBOL(SendAssocIEsToWpaSupplicant); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT +EXPORT_SYMBOL(WpaSendMicFailureToWpaSupplicant); +#endif /* WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +/* only for PCI */ +#ifdef RTMP_MAC_PCI +EXPORT_SYMBOL(RTMP_AllocateRxPacketBuffer); +EXPORT_SYMBOL(RtmpFreeDescBuf); +EXPORT_SYMBOL(RtmpAllocDescBuf); +EXPORT_SYMBOL(linux_pci_unmap_single); +EXPORT_SYMBOL(linux_pci_map_single); +EXPORT_SYMBOL(RTMP_AllocateFirstTxBuffer); +EXPORT_SYMBOL(RTMP_FreeFirstTxBuffer); +#endif /* RTMP_MAC_PCI */ + +/* only for USB */ + +/* only for RBUS or flash-capable concurrent devices */ +#if defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT) +EXPORT_SYMBOL(RtmpFlashRead); +EXPORT_SYMBOL(RtmpFlashWrite); +#endif /* defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT) */ + +#ifdef CONFIG_STA_SUPPORT +EXPORT_SYMBOL(RtmpOSNotifyRawData); +#endif /* CONFIG_STA_SUPPORT */ + +EXPORT_SYMBOL(RtPrivIoctlSetVal); +EXPORT_SYMBOL(RtmpOsSpinLockIrqSave); +EXPORT_SYMBOL(RtmpOsSpinUnlockIrqRestore); +EXPORT_SYMBOL(RtmpOsSpinLockIrq); +EXPORT_SYMBOL(RtmpOsSpinUnlockIrq); +EXPORT_SYMBOL(OS_TEST_BIT); +EXPORT_SYMBOL(OS_SET_BIT); +EXPORT_SYMBOL(OS_CLEAR_BIT); +EXPORT_SYMBOL(OS_LOAD_CODE_FROM_BIN); +#endif /* OS_ABL_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_main_dev.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_main_dev.c new file mode 100644 index 000000000..c4622b7f4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_main_dev.c @@ -0,0 +1,963 @@ +/* + *************************************************************************** + * 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: + rt_main_dev.c + + Abstract: + Create and register network interface. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#define RTMP_MODULE_OS + +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#ifndef SA_SHIRQ +#define SA_SHIRQ IRQF_SHARED +#endif +#endif + +// TODO: shiang-6590, remove it when MP +#ifdef RTMP_MAC_PCI +MODULE_LICENSE("GPL"); +#endif /* RTMP_MAC_PCI */ +// TODO: End--- + + +#ifdef BTCOEX_CONCURRENT +int CoexChannel; +int CoexCenctralChannel; +int CoexChannelBw; +#endif + +/*---------------------------------------------------------------------*/ +/* Private Variables Used */ +/*---------------------------------------------------------------------*/ + +PSTRING mac = ""; /* default 00:00:00:00:00:00 */ +PSTRING mode = ""; /* supported mode: normal/ate/monitor; default: normal */ +PSTRING hostname = ""; /* default CMPC */ + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) +MODULE_PARM (mac, "s"); +MODULE_PARM(mode, "s"); +#else +module_param (mac, charp, 0); +module_param(mode, charp, 0); +#endif +MODULE_PARM_DESC (mac, "rt_wifi: wireless mac addr"); +MODULE_PARM_DESC (mode, "rt_wifi: wireless operation mode"); + +#ifdef OS_ABL_SUPPORT +RTMP_DRV_ABL_OPS RtmpDrvOps, *pRtmpDrvOps = &RtmpDrvOps; +RTMP_NET_ABL_OPS RtmpDrvNetOps, *pRtmpDrvNetOps = &RtmpDrvNetOps; +#endif /* OS_ABL_SUPPORT */ + + +/*---------------------------------------------------------------------*/ +/* Prototypes of Functions Used */ +/*---------------------------------------------------------------------*/ + +/* public function prototype */ +int rt28xx_close(VOID *net_dev); +int rt28xx_open(VOID *net_dev); + +/* private function prototype */ +INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); + +struct rtnl_link_stats64 * +RT28xx_get_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats); + + +/* +======================================================================== +Routine Description: + Close raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int MainVirtualIF_close(IN struct net_device *net_dev) +{ + VOID *pAd = NULL; + + pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); + + if (pAd == NULL) + return 0; + + netif_carrier_off(net_dev); + netif_stop_queue(net_dev); + + RTMPInfClose(pAd); + +#ifdef IFUP_IN_PROBE +#else + VIRTUAL_IF_DOWN(pAd); +#endif /* IFUP_IN_PROBE */ + + RT_MOD_DEC_USE_COUNT(); + + return 0; /* close ok */ +} + +/* +======================================================================== +Routine Description: + Open raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int MainVirtualIF_open(struct net_device *net_dev) +{ + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd == NULL) + return 0; + +#ifdef CONFIG_AP_SUPPORT + /* pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = TRUE; */ + RTMP_DRIVER_AP_MAIN_OPEN(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IFUP_IN_PROBE + while (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + OS_WAIT(10); + DBGPRINT(RT_DEBUG_TRACE, ("Card not ready, NDIS_STATUS_SUCCESS!\n")); + } +#else + if (VIRTUAL_IF_UP(pAd) != 0) + return -1; +#endif /* IFUP_IN_PROBE */ + + RT_MOD_INC_USE_COUNT(); + + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + + return 0; +} + + +/* +======================================================================== +Routine Description: + Close raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int rt28xx_close(VOID *dev) +{ + struct net_device * net_dev = (struct net_device *)dev; + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); + + if (pAd == NULL) + return 0; + + RTMPDrvClose(pAd, net_dev); + + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n")); + return 0; +} + + +/* +======================================================================== +Routine Description: + Open raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: +======================================================================== +*/ +int rt28xx_open(VOID *dev) +{ + struct net_device * net_dev = (struct net_device *)dev; + VOID *pAd = NULL; + int retval = 0; + ULONG OpMode; + +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + struct usb_interface *intf; + struct usb_device *pUsb_Dev; + INT pm_usage_cnt; +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ +#endif /* CONFIG_STA_SUPPORT */ + + + if (sizeof(ra_dma_addr_t) < sizeof(dma_addr_t)) + DBGPRINT(RT_DEBUG_ERROR, ("Fatal error for DMA address size!!!\n")); + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -1; + } + + RTMP_DRIVER_MCU_SLEEP_CLEAR(pAd); + + RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); + +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + + RTMP_DRIVER_USB_DEV_GET(pAd, &pUsb_Dev); + RTMP_DRIVER_USB_INTF_GET(pAd, &intf); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + pm_usage_cnt = atomic_read(&intf->pm_usage_cnt); +#else + pm_usage_cnt = intf->pm_usage_cnt; +#endif + if (pm_usage_cnt == 0) + { + int res=1; + + res = usb_autopm_get_interface(intf); + if (res) + { + DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_open autopm_resume fail!\n")); + return (-1);; + } + } +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ +#endif /* CONFIG_STA_SUPPORT */ + + +#if WIRELESS_EXT >= 12 +/* if (RT_DEV_PRIV_FLAGS_GET(net_dev) == INT_MAIN) */ + if (RTMP_DRIVER_MAIN_INF_CHECK(pAd, RT_DEV_PRIV_FLAGS_GET(net_dev)) == NDIS_STATUS_SUCCESS) + { +#ifdef CONFIG_APSTA_MIXED_SUPPORT + if (OpMode == OPMODE_AP) + net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def; +#endif /* CONFIG_STA_SUPPORT */ + } +#endif /* WIRELESS_EXT >= 12 */ + + /* + Request interrupt service routine for PCI device + register the interrupt routine with the os + + AP Channel auto-selection will be run in rt28xx_init(), + so we must reqister IRQ hander here. + */ + RtmpOSIRQRequest(net_dev); + + /* Init IRQ parameters stored in pAd */ +/* rtmp_irq_init(pAd); */ + RTMP_DRIVER_IRQ_INIT(pAd); + + /* Chip & other init */ + if (rt28xx_init(pAd, mac, hostname) == FALSE) + goto err; + +#ifdef MBSS_SUPPORT + /* + the function can not be moved to RT2860_probe() even register_netdev() + is changed as register_netdevice(). + Or in some PC, kernel will panic (Fedora 4) + */ +#if defined(P2P_APCLI_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + +#else + RT28xx_MBSS_Init(pAd, net_dev); +#endif /* P2P_APCLI_SUPPORT */ +#endif /* MBSS_SUPPORT */ + +#ifdef WDS_SUPPORT + RT28xx_WDS_Init(pAd, net_dev); +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT +#if defined(P2P_APCLI_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) +#else + RT28xx_ApCli_Init(pAd, net_dev); +#endif /* P2P_APCLI_SUPPORT || RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT + RT28xx_Monitor_Init(pAd, net_dev); +#endif /* CONFIG_SNIFFER_SUPPORT */ + + + +#ifdef RT_CFG80211_SUPPORT +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + RTMP_CFG80211_DummyP2pIf_Init(pAd); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#else +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + RTMP_DRIVER_CFG80211_START(pAd); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + + RTMPDrvOpen(pAd); + +#ifdef VENDOR_FEATURE2_SUPPORT + printk("Number of Packet Allocated in open = %lu\n", OS_NumOfPktAlloc); + printk("Number of Packet Freed in open = %lu\n", OS_NumOfPktFree); +#endif /* VENDOR_FEATURE2_SUPPORT */ + +#ifdef BTCOEX_CONCURRENT + CoexChannel =-1; + CoexCenctralChannel = -1; + CoexChannelBw = -1; +#endif + + return (retval); + +err: + RTMP_DRIVER_IRQ_RELEASE(pAd); + + return (-1); +} + + +PNET_DEV RtmpPhyNetDevInit(VOID *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevHook) +{ + struct net_device *net_dev = NULL; + ULONG InfId, OpMode; + + + RTMP_DRIVER_MAIN_INF_GET(pAd, &InfId); + +/* net_dev = RtmpOSNetDevCreate(pAd, INT_MAIN, 0, sizeof(struct mt_dev_priv), INF_MAIN_DEV_NAME); */ + RTMP_DRIVER_MAIN_INF_CREATE(pAd, &net_dev); + if (net_dev == NULL) + { + printk("%s(): main physical net device creation failed!\n", __FUNCTION__); + return NULL; + } + + NdisZeroMemory((unsigned char *)pNetDevHook, sizeof(RTMP_OS_NETDEV_OP_HOOK)); + pNetDevHook->open = MainVirtualIF_open; + pNetDevHook->stop = MainVirtualIF_close; + pNetDevHook->xmit = rt28xx_send_packets; +#ifdef IKANOS_VX_1X0 + pNetDevHook->xmit = IKANOS_DataFramesTx; +#endif /* IKANOS_VX_1X0 */ + pNetDevHook->ioctl = rt28xx_ioctl; + pNetDevHook->priv_flags = InfId; /*INT_MAIN; */ + pNetDevHook->get_stats = RT28xx_get_ether_stats64; + + pNetDevHook->needProtcted = FALSE; + +#if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12) + pNetDevHook->get_wstats = rt28xx_get_wireless_stats; +#endif + + RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); + + /* put private data structure */ + RTMP_OS_NETDEV_SET_PRIV(net_dev, pAd); + +#ifdef CONFIG_STA_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_STA) + { + pNetDevHook->iw_handler = (void *)&rt28xx_iw_handler_def; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_AP) + { + pNetDevHook->iw_handler = &rt28xx_ap_iw_handler_def; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + /* double-check if pAd is associated with the net_dev */ + if (RTMP_OS_NETDEV_GET_PRIV(net_dev) == NULL) + { + RtmpOSNetDevFree(net_dev); + return NULL; + } + + RTMP_DRIVER_NET_DEV_SET(pAd, net_dev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(net_dev); +#endif + + + + return net_dev; +} + + +VOID *RtmpNetEthConvertDevSearch(VOID *net_dev_, UCHAR *pData) +{ + struct net_device *pNetDev; + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + struct net_device *net_dev = (struct net_device *)net_dev_; + struct net *net; + net = dev_net(net_dev); + + BUG_ON(!net); + for_each_netdev(net, pNetDev) +#else + struct net *net; + + struct net_device *net_dev = (struct net_device *)net_dev_; + BUG_ON(!net_dev->nd_net); + net = net_dev->nd_net; + for_each_netdev(net, pNetDev) +#endif +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + for_each_netdev(pNetDev) +#else + for (pNetDev = dev_base; pNetDev; pNetDev = pNetDev->next) +#endif +#endif + { + if ((pNetDev->type == ARPHRD_ETHER) + && NdisEqualMemory(pNetDev->dev_addr, &pData[6], pNetDev->addr_len)) + break; + } + + return (VOID *)pNetDev; +} + + + + +/* +======================================================================== +Routine Description: + The entry point for Linux kernel sent packet to our driver. + +Arguments: + sk_buff *skb the pointer refer to a sk_buffer. + +Return Value: + 0 + +Note: + This function is the entry point of Tx Path for OS delivery packet to + our driver. You only can put OS-depened & STA/AP common handle procedures + in here. +======================================================================== +*/ +int rt28xx_packet_xmit(void *pkt) +{ + struct sk_buff *skb = (struct sk_buff *)pkt; + struct net_device *net_dev = skb->dev; + struct wifi_dev *wdev; + PNDIS_PACKET pPacket = (PNDIS_PACKET)skb; + + wdev = RTMP_OS_NETDEV_GET_WDEV(net_dev); + ASSERT(wdev); + + + return RTMPSendPackets((NDIS_HANDLE)wdev, (PPNDIS_PACKET) &pPacket, 1, + skb->len, RtmpNetEthConvertDevSearch); +} + + +/* +======================================================================== +Routine Description: + Send a packet to WLAN. + +Arguments: + skb_p points to our adapter + dev_p which WLAN network interface + +Return Value: + 0: transmit successfully + otherwise: transmit fail + +Note: +======================================================================== +*/ +int rt28xx_send_packets(struct sk_buff *skb, struct net_device *ndev) +{ + if (!(RTMP_OS_NETDEV_STATE_RUNNING(ndev))) + { + RELEASE_NDIS_PACKET(NULL, (PNDIS_PACKET)skb, NDIS_STATUS_FAILURE); + return 0; + } + + NdisZeroMemory((PUCHAR)&skb->cb[CB_OFF], 26); + MEM_DBG_PKT_ALLOC_INC(skb); + + return rt28xx_packet_xmit(skb); +} + + +#if WIRELESS_EXT >= 12 +/* This function will be called when query /proc */ +struct iw_statistics *rt28xx_get_wireless_stats(struct net_device *net_dev) +{ + VOID *pAd = NULL; + struct iw_statistics *pStats; + RT_CMD_IW_STATS DrvIwStats, *pDrvIwStats = &DrvIwStats; + + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + + DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); + + pDrvIwStats->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); + pDrvIwStats->dev_addr = (PUCHAR)net_dev->dev_addr; + + if (RTMP_DRIVER_IW_STATS_GET(pAd, pDrvIwStats) != NDIS_STATUS_SUCCESS) + return NULL; + + pStats = (struct iw_statistics *)(pDrvIwStats->pStats); + pStats->status = 0; /* Status - device dependent for now */ + + + pStats->qual.updated = 1; /* Flags to know if updated */ +#ifdef IW_QUAL_DBM + pStats->qual.updated |= IW_QUAL_DBM; /* Level + Noise are dBm */ +#endif /* IW_QUAL_DBM */ + pStats->qual.qual = pDrvIwStats->qual; + pStats->qual.level = pDrvIwStats->level; + pStats->qual.noise = pDrvIwStats->noise; + pStats->discard.nwid = 0; /* Rx : Wrong nwid/essid */ + pStats->miss.beacon = 0; /* Missed beacons/superframe */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); + return pStats; +} +#endif /* WIRELESS_EXT */ + + +INT rt28xx_ioctl(PNET_DEV net_dev, struct ifreq *rq, INT cmd) +{ + VOID *pAd = NULL; + INT ret = 0; + ULONG OpMode; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); + +#ifdef CONFIG_AP_SUPPORT +/* IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ + RT_CONFIG_IF_OPMODE_ON_AP(OpMode) + { + ret = rt28xx_ap_ioctl(net_dev, rq, cmd); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +/* IF_DEV_CONFIG_OPMODE_ON_STA(pAd) */ + RT_CONFIG_IF_OPMODE_ON_STA(OpMode) + { + ret = rt28xx_sta_ioctl(net_dev, rq, cmd); + } +#endif /* CONFIG_STA_SUPPORT */ + + return ret; +} + + +/* + ======================================================================== + + Routine Description: + return ethernet statistics counter + + Arguments: + net_dev Pointer to net_device + + Return Value: + rtnl_link_stats64* + + Note: + + ======================================================================== +*/ +struct rtnl_link_stats64 * +RT28xx_get_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats) +{ + RT_CMD_STATS64 WifStats; + VOID *pAd = NULL; + + if (net_dev) + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (!pAd) + return NULL; + + WifStats.pNetDev = net_dev; + RTMP_DRIVER_INF_STATS_GET(pAd, &WifStats); + + stats->rx_packets = WifStats.rx_packets; + stats->tx_packets = WifStats.tx_packets; + stats->rx_bytes = WifStats.rx_bytes; + stats->tx_bytes = WifStats.tx_bytes; + stats->rx_errors = WifStats.rx_errors; + stats->tx_errors = WifStats.tx_errors; + stats->rx_dropped = 0; + stats->tx_dropped = 0; + stats->multicast = WifStats.multicast; + stats->collisions = WifStats.collisions; + + stats->rx_length_errors = 0; + stats->rx_over_errors = WifStats.rx_over_errors; + stats->rx_crc_errors = 0; + stats->rx_frame_errors = WifStats.rx_frame_errors; + stats->rx_fifo_errors = WifStats.rx_fifo_errors; + stats->rx_missed_errors = 0; + + stats->tx_aborted_errors = 0; + stats->tx_carrier_errors = 0; + stats->tx_fifo_errors = 0; + stats->tx_heartbeat_errors = 0; + stats->tx_window_errors = 0; + + stats->rx_compressed = 0; + stats->tx_compressed = 0; + + return stats; +} + + +BOOLEAN RtmpPhyNetDevExit(VOID *pAd, PNET_DEV net_dev) +{ +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#if defined(P2P_APCLI_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) +#else + /* remove all AP-client virtual interfaces. */ + RT28xx_ApCli_Remove(pAd); +#endif /* P2P_APCLI_SUPPORT || RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + /* remove all WDS virtual interfaces. */ + RT28xx_WDS_Remove(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef MBSS_SUPPORT +#if defined(P2P_APCLI_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + +#else + RT28xx_MBSS_Remove(pAd); +#endif /* P2P_APCLI_SUPPORT */ +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT + RT28xx_Monitor_Remove(pAd); +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + RTMP_CFG80211_AllVirtualIF_Remove(pAd); + RTMP_CFG80211_DummyP2pIf_Remove(pAd); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#else +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef INF_PPA_SUPPORT + RTMP_DRIVER_INF_PPA_EXIT(pAd); +#endif /* INF_PPA_SUPPORT */ + + /* Unregister network device */ + if (net_dev != NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("RtmpOSNetDevDetach(): RtmpOSNetDeviceDetach(), dev->name=%s!\n", net_dev->name)); + RtmpOSNetDevProtect(1); + RtmpOSNetDevDetach(net_dev); + RtmpOSNetDevProtect(0); + } + + return TRUE; + +} + + +/******************************************************************************* + + Device IRQ related functions. + + *******************************************************************************/ +int RtmpOSIRQRequest(IN PNET_DEV pNetDev) +{ +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_RBUS_SUPPORT) + struct net_device *net_dev = pNetDev; +#endif + ULONG infType; + VOID *pAd = NULL; + int retval = 0; + + GET_PAD_FROM_NET_DEV(pAd, pNetDev); + + ASSERT(pAd); + + RTMP_DRIVER_INF_TYPE_GET(pAd, &infType); + +#ifdef RTMP_PCI_SUPPORT + if (infType == RTMP_DEV_INF_PCI || infType == RTMP_DEV_INF_PCIE) + { + struct pci_dev *pci_dev; + RTMP_DRIVER_PCI_MSI_ENABLE(pAd, &pci_dev); +#ifdef CONFIG_ARCH_MT7623 + retval = request_irq(pci_dev->irq, rt2860_interrupt, SA_SHIRQ|IRQF_TRIGGER_LOW, (net_dev)->name, (net_dev)); +#else + retval = request_irq(pci_dev->irq, rt2860_interrupt, SA_SHIRQ, (net_dev)->name, (net_dev)); +#endif + if (retval != 0) + printk("RT2860: request_irq ERROR(%d)\n", retval); + } +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + if (infType == RTMP_DEV_INF_RBUS) + { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + if ((retval = request_irq(net_dev->irq, rt2860_interrupt, IRQF_SHARED, net_dev->name ,net_dev))) +#else + if ((retval = request_irq(net_dev->irq,rt2860_interrupt, SA_INTERRUPT, net_dev->name ,net_dev))) +#endif + { + printk("RT2860: request_irq ERROR(%d)\n", retval); + } + } +#endif /* RTMP_RBUS_SUPPORT */ + + return retval; +} + +#ifdef WDS_SUPPORT +/* + ======================================================================== + + Routine Description: + return ethernet statistics counter + + Arguments: + net_dev Pointer to net_device + + Return Value: + rtnl_link_stats64 * + + Note: + + ======================================================================== +*/ +struct rtnl_link_stats64 * +RT28xx_get_wds_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats) +{ + RT_CMD_STATS64 WdsStats; + VOID *pAd = NULL; + + if (net_dev) + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (!pAd) + return NULL; + + WdsStats.pNetDev = net_dev; + + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WDS_STATS_GET, + 0, &WdsStats, RT_DEV_PRIV_FLAGS_GET(net_dev)) != NDIS_STATUS_SUCCESS) + return NULL; + + stats->rx_packets = WdsStats.rx_packets; + stats->tx_packets = WdsStats.tx_packets; + stats->rx_bytes = WdsStats.rx_bytes; + stats->tx_bytes = WdsStats.tx_bytes; + stats->rx_errors = WdsStats.rx_errors; + stats->tx_errors = 0; + stats->rx_dropped = 0; + stats->tx_dropped = 0; + stats->multicast = WdsStats.multicast; + stats->collisions = 0; + + stats->rx_length_errors = 0; + stats->rx_over_errors = 0; + stats->rx_crc_errors = 0; + stats->rx_frame_errors = 0; + stats->rx_fifo_errors = 0; + stats->rx_missed_errors = 0; + + stats->tx_aborted_errors = 0; + stats->tx_carrier_errors = 0; + stats->tx_fifo_errors = 0; + stats->tx_heartbeat_errors = 0; + stats->tx_window_errors = 0; + + stats->rx_compressed = 0; + stats->tx_compressed = 0; + + return stats; +} +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT +/* + ======================================================================== + + Routine Description: + return ethernet statistics counter + + Arguments: + net_dev Pointer to net_device + + Return Value: + rtnl_link_stats64 * + + Note: + + ======================================================================== +*/ +struct rtnl_link_stats64 * +RT28xx_get_apcli_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats) +{ + RT_CMD_STATS64 ApCliStats; + VOID *pAd = NULL; + + if (net_dev) + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (!pAd) + return NULL; + + ApCliStats.pNetDev = net_dev; + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APCLI_STATS_GET, + 0, &ApCliStats, RT_DEV_PRIV_FLAGS_GET(net_dev)) != NDIS_STATUS_SUCCESS) + return NULL; + + stats->rx_packets = ApCliStats.rx_packets; + stats->tx_packets = ApCliStats.tx_packets; + stats->rx_bytes = ApCliStats.rx_bytes; + stats->tx_bytes = ApCliStats.tx_bytes; + stats->rx_errors = ApCliStats.rx_errors; + stats->tx_errors = 0; + stats->rx_dropped = 0; + stats->tx_dropped = 0; + stats->multicast = ApCliStats.multicast; + stats->collisions = 0; + + stats->rx_length_errors = 0; + stats->rx_over_errors = 0; + stats->rx_crc_errors = 0; + stats->rx_frame_errors = 0; + stats->rx_fifo_errors = 0; + stats->rx_missed_errors = 0; + + stats->tx_aborted_errors = 0; + stats->tx_carrier_errors = 0; + stats->tx_fifo_errors = 0; + stats->tx_heartbeat_errors = 0; + stats->tx_window_errors = 0; + + stats->rx_compressed = 0; + stats->tx_compressed = 0; + + return stats; +} +#endif /* APCLI_SUPPORT */ + + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_pci_rbus.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_pci_rbus.c new file mode 100644 index 000000000..90da0b792 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_pci_rbus.c @@ -0,0 +1,83 @@ +/* + *************************************************************************** + * 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: + rt_pci_rbus.c + + Abstract: + Create and register network interface. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#define RTMP_MODULE_OS + +/*#include */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +#include + + +IRQ_HANDLE_TYPE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +rt2860_interrupt(int irq, void *dev_instance); +#else +rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +#endif + + +/*************************************************************************** + * + * Interface-depended memory allocation/Free related procedures. + * Mainly for Hardware TxDesc/RxDesc/MgmtDesc, DMA Memory for TxData/RxData, etc., + * + **************************************************************************/ + + +/*************************************************************************** + * + * interrupt handler related procedures. + * + **************************************************************************/ +/*int print_int_count; */ + +IRQ_HANDLE_TYPE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +rt2860_interrupt(int irq, void *dev_instance) +#else +rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +#endif +{ + struct net_device *net_dev = (struct net_device *) dev_instance; + VOID *pAd = NULL; +#ifdef MULTI_CORE_SUPPORT + unsigned long flags=0; +#endif /* MULTI_CORE_SUPPORT */ + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + RTMPHandleInterrupt(pAd); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return IRQ_HANDLED; +#endif + +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_proc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_proc.c new file mode 100644 index 000000000..b30f43848 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_proc.c @@ -0,0 +1,539 @@ +/* + *************************************************************************** + * 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: + rt_proc.c + + Abstract: + Create and register proc file system for ralink device + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include +#include +#include +#include + +#include "rt_config.h" + +int wl_proc_init(void); +int wl_proc_exit(void); + +#ifdef CONFIG_RALINK_RT2880 +#define PROCREG_DIR "rt2880" +#endif /* CONFIG_RALINK_RT2880 */ + +#ifdef CONFIG_RALINK_RT3052 +#define PROCREG_DIR "rt3052" +#endif /* CONFIG_RALINK_RT3052 */ + +#ifdef CONFIG_RALINK_RT2883 +#define PROCREG_DIR "rt2883" +#endif /* CONFIG_RALINK_RT2883 */ + +#ifdef CONFIG_RALINK_RT3883 +#define PROCREG_DIR "rt3883" +#endif /* CONFIG_RALINK_RT3883 */ + +#ifdef CONFIG_RALINK_RT5350 +#define PROCREG_DIR "rt5350" +#endif /* CONFIG_RALINK_RT5350 */ + +#ifndef PROCREG_DIR +#define PROCREG_DIR "rt2880" +#endif /* PROCREG_DIR */ + +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *procRegDir; + +#ifdef VIDEO_TURBINE_SUPPORT +extern BOOLEAN UpdateFromGlobal; +AP_VIDEO_STRUCT GLOBAL_AP_VIDEO_CONFIG; +/*struct proc_dir_entry *proc_ralink_platform, *proc_ralink_wl, *proc_ralink_wl_video; */ +struct proc_dir_entry *proc_ralink_wl, *proc_ralink_wl_video; +static struct proc_dir_entry *entry_wl_video_Update, *entry_wl_video_Enable, *entry_wl_video_ClassifierEnable, *entry_wl_video_HighTxMode, *entry_wl_video_TxPwr, *entry_wl_video_VideoMCSEnable, *entry_wl_video_VideoMCS, *entry_wl_video_TxBASize, *entry_wl_video_TxLifeTimeMode, *entry_wl_video_TxLifeTime, *entry_wl_video_TxRetryLimit; + + +ssize_t video_Update_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", UpdateFromGlobal); + *eof = 1; + return strlen(page); +} + +ssize_t video_Update_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + UpdateFromGlobal = val; + } + return count; +} + +ssize_t video_Enable_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.Enable); + *eof = 1; + return strlen(page); +} + +ssize_t video_Enable_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.Enable = val; + } + return count; +} + +ssize_t video_ClassifierEnable_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.ClassifierEnable); + *eof = 1; + return strlen(page); +} + +ssize_t video_ClassifierEnable_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.ClassifierEnable = val; + } + return count; +} + +ssize_t video_HighTxMode_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.HighTxMode); + *eof = 1; + return strlen(page); +} + +ssize_t video_HighTxMode_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.HighTxMode = val; + } + return count; +} + +ssize_t video_TxPwr_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.TxPwr); + *eof = 1; + return strlen(page); +} + +ssize_t video_TxPwr_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.TxPwr = val; + } + return count; +} + +ssize_t video_VideoMCSEnable_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.VideoMCSEnable); + *eof = 1; + return strlen(page); +} + +ssize_t video_VideoMCSEnable_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.VideoMCSEnable = val; + } + return count; +} + +ssize_t video_VideoMCS_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.VideoMCS); + *eof = 1; + return strlen(page); +} + +ssize_t video_VideoMCS_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.VideoMCS = val; + } + return count; +} + +ssize_t video_TxBASize_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.TxBASize); + *eof = 1; + return strlen(page); +} + +ssize_t video_TxBASize_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.TxBASize = val; + } + return count; +} + +ssize_t video_TxLifeTimeMode_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.TxLifeTimeMode); + *eof = 1; + return strlen(page); +} + +ssize_t video_TxLifeTimeMode_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.TxLifeTimeMode = val; + } + return count; +} + +ssize_t video_TxLifeTime_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "%d\n", GLOBAL_AP_VIDEO_CONFIG.TxLifeTime); + *eof = 1; + return strlen(page); +} + +ssize_t video_TxLifeTime_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 10); + + GLOBAL_AP_VIDEO_CONFIG.TxLifeTime = val; + } + return count; +} + +ssize_t video_TxRetryLimit_get(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + sprintf(page, "0x%x\n", GLOBAL_AP_VIDEO_CONFIG.TxRetryLimit); + *eof = 1; + return strlen(page); +} + +ssize_t video_TxRetryLimit_set(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *buf = kmalloc(count, GFP_KERNEL); + + if (buf) { + unsigned long val; + + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf) + val = simple_strtoul(buf, NULL, 16); + + GLOBAL_AP_VIDEO_CONFIG.TxRetryLimit = val; + } + return count; +} + +int wl_video_proc_init(void) +{ + GLOBAL_AP_VIDEO_CONFIG.Enable = FALSE; + GLOBAL_AP_VIDEO_CONFIG.ClassifierEnable = FALSE; + GLOBAL_AP_VIDEO_CONFIG.HighTxMode = FALSE; + GLOBAL_AP_VIDEO_CONFIG.TxPwr = 0; + GLOBAL_AP_VIDEO_CONFIG.VideoMCSEnable = FALSE; + GLOBAL_AP_VIDEO_CONFIG.VideoMCS = 0; + GLOBAL_AP_VIDEO_CONFIG.TxBASize = 0; + GLOBAL_AP_VIDEO_CONFIG.TxLifeTimeMode = FALSE; + GLOBAL_AP_VIDEO_CONFIG.TxLifeTime = 0; + GLOBAL_AP_VIDEO_CONFIG.TxRetryLimit = 0; + + proc_ralink_wl = proc_mkdir("wl", procRegDir); + + if (proc_ralink_wl) + proc_ralink_wl_video = proc_mkdir("VideoTurbine", proc_ralink_wl); + + if (proc_ralink_wl_video) { + entry_wl_video_Update = create_proc_entry("UpdateFromGlobal", 0, proc_ralink_wl_video); + if (entry_wl_video_Update) { + entry_wl_video_Update->read_proc = (read_proc_t*)&video_Update_get; + entry_wl_video_Update->write_proc = (write_proc_t*)&video_Update_set; + } + + entry_wl_video_Enable = create_proc_entry("Enable", 0, proc_ralink_wl_video); + if (entry_wl_video_Enable) { + entry_wl_video_Enable->read_proc = (read_proc_t*)&video_Enable_get; + entry_wl_video_Enable->write_proc = (write_proc_t*)&video_Enable_set; + } + + entry_wl_video_ClassifierEnable = create_proc_entry("ClassifierEnable", 0, proc_ralink_wl_video); + if (entry_wl_video_ClassifierEnable) { + entry_wl_video_ClassifierEnable->read_proc = (read_proc_t*)&video_ClassifierEnable_get; + entry_wl_video_ClassifierEnable->write_proc = (write_proc_t*)&video_ClassifierEnable_set; + } + + entry_wl_video_HighTxMode = create_proc_entry("HighTxMode", 0, proc_ralink_wl_video); + if (entry_wl_video_HighTxMode) { + entry_wl_video_HighTxMode->read_proc = (read_proc_t*)&video_HighTxMode_get; + entry_wl_video_HighTxMode->write_proc = (write_proc_t*)&video_HighTxMode_set; + } + + entry_wl_video_TxPwr = create_proc_entry("TxPwr", 0, proc_ralink_wl_video); + if (entry_wl_video_TxPwr) { + entry_wl_video_TxPwr->read_proc = (read_proc_t*)&video_TxPwr_get; + entry_wl_video_TxPwr->write_proc = (write_proc_t*)&video_TxPwr_set; + } + + entry_wl_video_VideoMCSEnable = create_proc_entry("VideoMCSEnable", 0, proc_ralink_wl_video); + if (entry_wl_video_VideoMCSEnable) { + entry_wl_video_VideoMCSEnable->read_proc = (read_proc_t*)&video_VideoMCSEnable_get; + entry_wl_video_VideoMCSEnable->write_proc = (write_proc_t*)&video_VideoMCSEnable_set; + } + + entry_wl_video_VideoMCS = create_proc_entry("VideoMCS", 0, proc_ralink_wl_video); + if (entry_wl_video_VideoMCS) { + entry_wl_video_VideoMCS->read_proc = (read_proc_t*)&video_VideoMCS_get; + entry_wl_video_VideoMCS->write_proc = (write_proc_t*)&video_VideoMCS_set; + } + + entry_wl_video_TxBASize = create_proc_entry("TxBASize", 0, proc_ralink_wl_video); + if (entry_wl_video_TxBASize) { + entry_wl_video_TxBASize->read_proc = (read_proc_t*)&video_TxBASize_get; + entry_wl_video_TxBASize->write_proc = (write_proc_t*)&video_TxBASize_set; + } + entry_wl_video_TxLifeTimeMode = create_proc_entry("TxLifeTimeMode", 0, proc_ralink_wl_video); + if (entry_wl_video_TxLifeTimeMode) { + entry_wl_video_TxLifeTimeMode->read_proc = (read_proc_t*)&video_TxLifeTimeMode_get; + entry_wl_video_TxLifeTimeMode->write_proc = (write_proc_t*)&video_TxLifeTimeMode_set; + } + + entry_wl_video_TxLifeTime = create_proc_entry("TxLifeTime", 0, proc_ralink_wl_video); + if (entry_wl_video_TxLifeTime) { + entry_wl_video_TxLifeTime->read_proc = (read_proc_t*)&video_TxLifeTime_get; + entry_wl_video_TxLifeTime->write_proc = (write_proc_t*)&video_TxLifeTime_set; + } + + entry_wl_video_TxRetryLimit = create_proc_entry("TxRetryLimit", 0, proc_ralink_wl_video); + if (entry_wl_video_TxRetryLimit) { + entry_wl_video_TxRetryLimit->read_proc = (read_proc_t*)&video_TxRetryLimit_get; + entry_wl_video_TxRetryLimit->write_proc = (write_proc_t*)&video_TxRetryLimit_set; + } + } + + return 0; +} + +int wl_video_proc_exit(void) +{ + + if (entry_wl_video_Enable) + remove_proc_entry("Enable", proc_ralink_wl_video); + + if (entry_wl_video_ClassifierEnable) + remove_proc_entry("ClassifierEnabl", proc_ralink_wl_video); + + if (entry_wl_video_HighTxMode) + remove_proc_entry("HighTxMode", proc_ralink_wl_video); + + if (entry_wl_video_TxPwr) + remove_proc_entry("TxPwr", proc_ralink_wl_video); + + if (entry_wl_video_VideoMCSEnable) + remove_proc_entry("VideoMCSEnable", proc_ralink_wl_video); + + if (entry_wl_video_VideoMCS) + remove_proc_entry("VideoMCS", proc_ralink_wl_video); + + if (entry_wl_video_TxBASize) + remove_proc_entry("TxBASize", proc_ralink_wl_video); + + if (entry_wl_video_TxLifeTimeMode) + remove_proc_entry("TxLifeTimeMode", proc_ralink_wl_video); + + if (entry_wl_video_TxLifeTime) + remove_proc_entry("TxLifeTime", proc_ralink_wl_video); + + if (entry_wl_video_TxRetryLimit) + remove_proc_entry("TxRetryLimit", proc_ralink_wl_video); + + if (proc_ralink_wl_video) + remove_proc_entry("Video", proc_ralink_wl); + + return 0; +} +#endif /* VIDEO_TURBINE_SUPPORT */ + +int wl_proc_init(void) +{ + if (procRegDir == NULL) + procRegDir = proc_mkdir(PROCREG_DIR, NULL); + + if (procRegDir) { +#ifdef VIDEO_TURBINE_SUPPORT + wl_video_proc_init(); +#endif /* VIDEO_TURBINE_SUPPORT */ + } + + return 0; +} + +int wl_proc_exit(void) +{ +#ifdef VIDEO_TURBINE_SUPPORT + if (proc_ralink_wl_video) { + wl_video_proc_exit(); + remove_proc_entry("Video", proc_ralink_wl); + } + if (proc_ralink_wl) + remove_proc_entry("wl", procRegDir); +#endif /* VIDEO_TURBINE_SUPPORT */ + + + return 0; +} +#else +int wl_proc_init(void) +{ + return 0; +} + +int wl_proc_exit(void) +{ + + return 0; +} +#endif /* CONFIG_PROC_FS */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_profile.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_profile.c new file mode 100644 index 000000000..bbd502237 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_profile.c @@ -0,0 +1,1604 @@ +/**************************************************************************** + * 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: + rt_profile.c + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#include "rt_config.h" + +#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE) +#include "../../../../../../../net/nat/hw_nat/ra_nat.h" +#include "../../../../../../../net/nat/hw_nat/frame_engine.h" +#endif + + +struct dev_type_name_map{ + INT type; + PSTRING prefix[2]; +}; + + +#define SECOND_INF_MAIN_DEV_NAME "rai" +#define SECOND_INF_MBSSID_DEV_NAME "rai" +#define SECOND_INF_WDS_DEV_NAME "wdsi" +#define SECOND_INF_APCLI_DEV_NAME "apclii" +#define SECOND_INF_MESH_DEV_NAME "meshi" +#define SECOND_INF_P2P_DEV_NAME "p2pi" +#define SECOND_INF_MONITOR_DEV_NAME "moni" + +#define xdef_to_str(s) def_to_str(s) +#define def_to_str(s) #s + +#define FIRST_AP_PROFILE_PATH "/etc/Wireless/RT2860/RT2860AP.dat" +#define FIRST_STA_PROFILE_PATH "/etc/Wireless/RT2860/RT2860STA.dat" +#define FIRST_IF_SINGLE_SKU_PATH "/etc/Wireless/RT2860/SingleSKU.dat" +#define FIRST_CHIP_ID xdef_to_str(CONFIG_RT_FIRST_CARD) + +#define SECOND_AP_PROFILE_PATH "/etc/wireless/mt7615/mt7615.2.dat" +#define SECOND_STA_PROFILE_PATH "/etc/Wireless/iNIC/iNIC_sta.dat" +#define SECOND_IF_SINGLE_SKU_PATH "/etc/Wireless/iNIC/SingleSKU.dat" +#define SECOND_CHIP_ID xdef_to_str(CONFIG_RT_SECOND_CARD) + +static struct dev_type_name_map prefix_map[] = +{ + {INT_MAIN, {INF_MAIN_DEV_NAME, SECOND_INF_MAIN_DEV_NAME}}, +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + {INT_MBSSID, {INF_MBSSID_DEV_NAME, SECOND_INF_MBSSID_DEV_NAME}}, +#endif /* MBSS_SUPPORT */ +#ifdef APCLI_SUPPORT + {INT_APCLI, {INF_APCLI_DEV_NAME, SECOND_INF_APCLI_DEV_NAME}}, +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + {INT_WDS, {INF_WDS_DEV_NAME, SECOND_INF_WDS_DEV_NAME}}, +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT + {INT_MONITOR, {INF_MONITOR_DEV_NAME, SECOND_INF_MONITOR_DEV_NAME}}, +#endif /* CONFIG_SNIFFER_SUPPORT */ + {0}, +}; + +struct dev_id_name_map{ + INT chip_id; + PSTRING chip_name; +}; + + +VOID get_dev_config_idx(RTMP_ADAPTER *pAd) +{ + INT idx = 0; + +#if defined (DRIVER_HAS_MULTI_DEV) + INT first_card = 0, second_card = 0; + static int probe_cnt = 1; + + A2Hex(first_card, FIRST_CHIP_ID); + A2Hex(second_card, SECOND_CHIP_ID); + + if (first_card == second_card) { + idx = probe_cnt; + probe_cnt--; + } else if (IS_MT76x2(pAd)) { + UINT32 chip_id = (pAd->ChipID >> 16); + if (chip_id == second_card) + idx = 1; + } else { +#ifdef RT6352 + if (IS_RT6352(pAd)) + idx = 0; + else +#endif + if (IS_RT8592(pAd)) + idx = 0; + else if (IS_RT5392(pAd) || IS_MT76x0(pAd)) + idx = 1; + } + + DBGPRINT(RT_DEBUG_OFF, ("chip_id1=0x%x, chip_id2=0x%x, pAd->MACVersion=0x%x, pAd->ChipID=0x%x, dev_idx=%d\n", + first_card, second_card, pAd->MACVersion, pAd->ChipID, idx)); +#endif + + pAd->dev_idx = idx; +} + + +UCHAR *get_dev_name_prefix(RTMP_ADAPTER *pAd, INT dev_type) +{ + struct dev_type_name_map *map; + INT type_idx = 0, dev_idx = pAd->dev_idx; + + do { + map = &prefix_map[type_idx]; + if (map->type == dev_type) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): dev_idx = %d, dev_name_prefix=%s\n", + __FUNCTION__, dev_idx, map->prefix[dev_idx])); + return map->prefix[dev_idx]; + } + type_idx++; + } while (prefix_map[type_idx].type != 0); + + return NULL; +} + + +static UCHAR *get_dev_profile(RTMP_ADAPTER *pAd) +{ + UCHAR *src = NULL; +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + src = AP_PROFILE_PATH_RBUS; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + src = STA_PROFILE_PATH_RBUS; + } +#endif /* CONFIG_STA_SUPPORT */ + } + else +#endif /* RTMP_RBUS_SUPPORT */ + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#if defined (DRIVER_HAS_MULTI_DEV) + INT card_idx = pAd->dev_idx; + + if (card_idx == 0) + src = FIRST_AP_PROFILE_PATH; + else if (card_idx == 1) + src = SECOND_AP_PROFILE_PATH; + else +#endif + src = AP_PROFILE_PATH; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#if defined (DRIVER_HAS_MULTI_DEV) + INT card_idx = pAd->dev_idx; + + if (card_idx == 0) + src = FIRST_STA_PROFILE_PATH; + else if (card_idx == 1) + src = SECOND_STA_PROFILE_PATH; + else +#endif + src = STA_PROFILE_PATH; + } +#endif /* CONFIG_STA_SUPPORT */ + } +#ifdef MULTIPLE_CARD_SUPPORT + src = (PSTRING)pAd->MC_FileName; +#endif /* MULTIPLE_CARD_SUPPORT */ + + return src; +} + +#ifdef SINGLE_SKU_V2 +static CHAR *get_sku_profile(RTMP_ADAPTER *pAd) +{ + CHAR *src = SINGLE_SKU_TABLE_FILE_NAME; + +#if defined (DRIVER_HAS_MULTI_DEV) + INT card_idx = pAd->dev_idx; + + if (card_idx == 0) + src = FIRST_IF_SINGLE_SKU_PATH; + else if (card_idx == 1) + src = SECOND_IF_SINGLE_SKU_PATH; +#endif + + return src; +} +#endif /* SINGLE_SKU_V2 */ + +NDIS_STATUS RTMPReadParametersHook(RTMP_ADAPTER *pAd) +{ + PSTRING src = NULL; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osFSInfo; + INT retval = NDIS_STATUS_FAILURE; + ULONG buf_size = MAX_INI_BUFFER_SIZE, fsize; + PSTRING buffer = NULL; + +#ifdef HOSTAPD_SUPPORT + int i; +#endif /*HOSTAPD_SUPPORT */ + + src = get_dev_profile(pAd); + if (src && *src) + { + RtmpOSFSInfoChange(&osFSInfo, TRUE); + srcf = RtmpOSFileOpen(src, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Open file \"%s\" failed!\n", src)); + } + else + { +#ifndef OS_ABL_SUPPORT + // TODO: need to roll back when convert into OSABL code +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) + fsize = (ULONG)file_inode(srcf)->i_size; +#else + fsize = (ULONG)srcf->f_dentry->d_inode->i_size; +#endif + if (buf_size < (fsize + 1)) + buf_size = fsize + 1; +#endif /* OS_ABL_SUPPORT */ + os_alloc_mem(pAd, (UCHAR **)&buffer, buf_size); + if (buffer) { + memset(buffer, 0x00, buf_size); + retval =RtmpOSFileRead(srcf, buffer, buf_size - 1); + if (retval > 0) + { + RTMPSetProfileParameters(pAd, buffer); + retval = NDIS_STATUS_SUCCESS; + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Read file \"%s\" failed(errCode=%d)!\n", src, retval)); + os_free_mem(NULL, buffer); + } else + retval = NDIS_STATUS_FAILURE; + + if (RtmpOSFileClose(srcf) != 0) + { + retval = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("Close file \"%s\" failed(errCode=%d)!\n", src, retval)); + } + } + + RtmpOSFSInfoChange(&osFSInfo, FALSE); + } + +#ifdef HOSTAPD_SUPPORT + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].Hostapd=Hostapd_Diable; + DBGPRINT(RT_DEBUG_TRACE, ("Reset ra%d hostapd support=FLASE", i)); + } +#endif /*HOSTAPD_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + RTMPSetSingleSKUParameters(pAd, get_sku_profile(pAd)); +#endif /* SINGLE_SKU_V2 */ + + return (retval); + +} + + +void RTMP_IndicateMediaState( + IN PRTMP_ADAPTER pAd, + IN NDIS_MEDIA_STATE media_state) +{ + pAd->IndicateMediaState = media_state; + +#ifdef SYSTEM_LOG_SUPPORT + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + else + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } +#endif /* SYSTEM_LOG_SUPPORT */ +} + + +void tbtt_tasklet(unsigned long data) +{ +#ifdef CONFIG_AP_SUPPORT +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, tbtt_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)data; +#endif /* WORKQUEUE_BH */ + +#ifdef RTMP_MAC_PCI + if (pAd->OpMode == OPMODE_AP) + { +#ifdef AP_QLOAD_SUPPORT + /* update channel utilization */ + QBSS_LoadUpdate(pAd, 0); +#endif /* AP_QLOAD_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_QuietUpdata(pAd); +#endif /* DOT11K_RRM_SUPPORT */ + } +#endif /* RTMP_MAC_PCI */ + +#ifdef RT_CFG80211_P2P_SUPPORT + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP) +#else + if (pAd->OpMode == OPMODE_AP) +#endif /* RT_CFG80211_P2P_SUPPORT */ + { + /* step 7 - if DTIM, then move backlogged bcast/mcast frames from PSQ to TXQ whenever DtimCount==0 */ +#ifdef RTMP_MAC_PCI + /* + NOTE: + This updated BEACON frame will be sent at "next" TBTT instead of at cureent TBTT. The reason is + because ASIC already fetch the BEACON content down to TX FIFO before driver can make any + modification. To compenstate this effect, the actual time to deilver PSQ frames will be + at the time that we wrapping around DtimCount from 0 to DtimPeriod-1 + */ + if (pAd->ApCfg.DtimCount == 0) +#endif /* RTMP_MAC_PCI */ + { + if (pAd->CommonCfg.bMcastTest == TRUE) + { + if (pAd->MacTab.fMcastPsQEnable == TRUE) + { + UINT32 macValue = 0, idx = 0, mask = 0; + + for (idx = 0; idx < 40; idx++) + { +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_IO_READ32(pAd, TXQ_STA, &macValue); + } + else + { +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + RTMP_IO_READ32(pAd, TXRXQ_STA, &macValue); +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + } +#endif /* RLT_MAC */ + if (macValue & 0x0000F800) + break; + else + RtmpusecDelay(50); + } + + RTMP_IO_WRITE32(pAd, TX_WCID_DROP_MASK0, 0xFFFFFFFE); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &macValue); + macValue |= 0x2; + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, macValue); + + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &macValue); + macValue |= 0x4; + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, macValue); + + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &macValue); + macValue |= 0x8; + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, macValue); + } + else + { +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + RTMP_IO_READ32(pAd, PBF_CFG, &macValue); + macValue |= 0x8; + RTMP_IO_WRITE32(pAd, PBF_CFG, macValue); + + RTMP_IO_READ32(pAd, PBF_CFG, &macValue); + macValue |= 0x4; + RTMP_IO_WRITE32(pAd, PBF_CFG, macValue); + } +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + } +#endif /* RLT_MAC */ + + for (idx = 0; idx < 200; idx++) + { + RTMP_IO_READ32(pAd, MCU_INT_STA, &macValue); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + mask = 0x02; + else +#endif /* RLT_MAC */ + mask = 0x04; + + if (macValue & mask) + break; + else + RtmpusecDelay(50); + } + + RTMP_IO_WRITE32(pAd, TX_WCID_DROP_MASK0, 0x0); + } + } + else + { + PQUEUE_ENTRY pEntry; + BOOLEAN bPS = FALSE; + UINT count = 0; + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + while (pAd->MacTab.McastPsQueue.Head) + { + bPS = TRUE; + if (pAd->TxSwQueue[QID_AC_BE].Number <= (pAd->TxSwQMaxLen + MAX_PACKETS_IN_MCAST_PS_QUEUE)) + { + pEntry = RemoveHeadQueue(&pAd->MacTab.McastPsQueue); + /*if(pAd->MacTab.McastPsQueue.Number) */ + if (count) + { + RTMP_SET_PACKET_MOREDATA(pEntry, TRUE); + } + InsertHeadQueue(&pAd->TxSwQueue[QID_AC_BE], pEntry); + count++; + } + else + { + break; + } + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + + if (pAd->MacTab.McastPsQueue.Number == 0) + { + UINT bss_index; + + /* clear MCAST/BCAST backlog bit for all BSS */ + for(bss_index=BSS0; bss_indexApCfg.BssidNum; bss_index++) + WLAN_MR_TIM_BCMC_CLEAR(bss_index); + } + pAd->MacTab.PsQIdleCount = 0; + + if (bPS == TRUE) + { + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, /*MAX_TX_IN_TBTT*/MAX_PACKETS_IN_MCAST_PS_QUEUE); + } + } + } + + if (pAd->CommonCfg.bMcastTest == TRUE) + { +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMP_IO_WRITE32(pAd, MCU_INT_STA, 0x2); + else +#endif /* RLT_MAC */ + RTMP_IO_WRITE32(pAd, MCU_INT_STA, 0x4); + + pAd->MacTab.fMcastPsQEnable = FALSE; + } + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +#ifdef WORKQUEUE_BH +void pretbtt_workq(struct work_struct *work) +#else +void pretbtt_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ +#ifdef CONFIG_AP_SUPPORT + UINT32 mac_414_value = 0; + +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, pretbtt_work); + PRTMP_ADAPTER pAd = pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; +#endif /* WORKQUEUE_BH */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMP_IO_WRITE32(pAd, MCU_INT_STA, 0x2); + else +#endif /* RLT_MAC */ + RTMP_IO_WRITE32(pAd, MCU_INT_STA, 0x4); + pAd->MacTab.fMcastPsQEnable = FALSE; + + if ((pAd->ApCfg.DtimCount == 0) && (pAd->MacTab.McastPsQueue.Head)) + { + UINT32 macValue; + PQUEUE_ENTRY pEntry; + BOOLEAN bPS = FALSE; + UINT count = 0; + unsigned long IrqFlags; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &macValue); + macValue &= (~0xE); + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, macValue); + } + else + { +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + RTMP_IO_READ32(pAd, PBF_CFG, &macValue); + macValue &= (~0xC); + RTMP_IO_WRITE32(pAd, PBF_CFG, macValue); + } +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + } +#endif /* RLT_MAC */ + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + while (pAd->MacTab.McastPsQueue.Head) + { + bPS = TRUE; + + if (pAd->TxSwQueue[QID_AC_BE].Number <= (MAX_PACKETS_IN_QUEUE + MAX_PACKETS_IN_MCAST_PS_QUEUE)) + { + pEntry = RemoveHeadQueue(&pAd->MacTab.McastPsQueue); + + if (count) + RTMP_SET_PACKET_MOREDATA(pEntry, TRUE); + + InsertHeadQueue(&pAd->TxSwQueue[QID_AC_BE], pEntry); + count++; + } + else + break; + } + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + if (pAd->MacTab.McastPsQueue.Number == 0) + { + UINT bss_index = 0; + + /* clear MCAST/BCAST backlog bit for all BSS */ + for (bss_index = BSS0; bss_index < pAd->ApCfg.BssidNum; bss_index++) + WLAN_MR_TIM_BCMC_CLEAR(bss_index); + } + pAd->MacTab.PsQIdleCount = 0; + + /* dequeue outgoing frames from TxSwQueue0 queue and process it */ + if (bPS == TRUE) + { + RTMPDeQueuePacket(pAd, FALSE, QID_AC_BE, /*MAX_TX_IN_TBTT*/MAX_PACKETS_IN_MCAST_PS_QUEUE); + pAd->MacTab.fMcastPsQEnable = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ +} + +#ifdef INF_PPA_SUPPORT +static INT process_nbns_packet( + IN PRTMP_ADAPTER pAd, + IN struct sk_buff *skb) +{ + UCHAR *data; + USHORT *eth_type; + + data = (UCHAR *)eth_hdr(skb); + if (data == 0) + { + data = (UCHAR *)skb->data; + if (data == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error\n", __FUNCTION__)); + return 1; + } + } + + eth_type = (USHORT *)&data[12]; + if (*eth_type == cpu_to_be16(ETH_P_IP)) + { + INT ip_h_len; + UCHAR *ip_h; + UCHAR *udp_h; + USHORT dport, host_dport; + + ip_h = data + 14; + ip_h_len = (ip_h[0] & 0x0f)*4; + + if (ip_h[9] == 0x11) /* UDP */ + { + udp_h = ip_h + ip_h_len; + memcpy(&dport, udp_h + 2, 2); + host_dport = ntohs(dport); + if ((host_dport == 67) || (host_dport == 68)) /* DHCP */ + { + return 0; + } + } + } + else if ((data[12] == 0x88) && (data[13] == 0x8e)) /* EAPOL */ + { + return 0; + } + return 1; +} +#endif /* INF_PPA_SUPPORT */ + +#if defined (CONFIG_WIFI_PKT_FWD) +struct net_device *rlt_dev_get_by_name(const char *name) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) + return dev_get_by_name(&init_net, name); +#else + return dev_get_by_name(name); +#endif +} + + +VOID ApCliLinkCoverRxPolicy( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + OUT BOOLEAN *DropPacket) +{ + void *opp_band_tbl =NULL; + void *band_tbl =NULL; + INVAILD_TRIGGER_MAC_ENTRY *pInvalidEntry = NULL; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL, *pOtherBandReptEntry = NULL; + PNDIS_PACKET pRxPkt = pPacket; + UCHAR *pPktHdr = NULL , isLinkValid; + + pPktHdr = GET_OS_PKT_DATAPTR(pRxPkt); + + if (wf_fwd_feedback_map_table) + wf_fwd_feedback_map_table(pAd, &band_tbl, &opp_band_tbl); + + if (opp_band_tbl == NULL) + return; + + if (IS_GROUP_MAC(pPktHdr)) { + pInvalidEntry = RepeaterInvaildMacLookup(pAd, pPktHdr+6); + pOtherBandReptEntry = RTMPLookupRepeaterCliEntry(opp_band_tbl, FALSE, pPktHdr+6, FALSE, &isLinkValid); + + if ((pInvalidEntry != NULL) || (pOtherBandReptEntry != NULL)) { + DBGPRINT(RT_DEBUG_INFO, ("%s, recv broadcast from InvalidRept Entry, drop this packet\n", __func__)); + *DropPacket = TRUE; + } + } +} +#endif /* CONFIG_WIFI_PKT_FWD */ + + +void announce_802_3_packet( + IN VOID *pAdSrc, + IN PNDIS_PACKET pNetPkt, + IN UCHAR OpMode) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + struct sk_buff *pRxPkt; + + ASSERT(pNetPkt); + MEM_DBG_PKT_FREE_INC(pNetPkt); + + pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MAT_SUPPORT + if (RTMP_MATPktRxNeedConvert(pAd, pRxPkt->dev)) + { +#if defined (CONFIG_WIFI_PKT_FWD) + BOOLEAN need_drop = FALSE; + + ApCliLinkCoverRxPolicy(pAd, pNetPkt, &need_drop); + + if (need_drop == TRUE) { + RELEASE_NDIS_PACKET(pAd, pRxPkt, NDIS_STATUS_FAILURE); + return; + } +#endif /* CONFIG_WIFI_PKT_FWD */ + RTMP_MATEngineRxHandle(pAd, pNetPkt, 0); + } +#endif /* MAT_SUPPORT */ + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef MAT_SUPPORT + if (RTMP_MATPktRxNeedConvert(pAd, pRxPkt->dev) && + (pAd->EthConvert.ECMode & ETH_CONVERT_MODE_DONGLE)) + RTMP_MATEngineRxHandle(pAd, pNetPkt, 0); +#endif /* MAT_SUPPORT */ + } +#endif /* ETH_CONVERT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + /* Push up the protocol stack */ +#ifdef CONFIG_AP_SUPPORT +#if defined(PLATFORM_BL2348) || defined(PLATFORM_BL23570) + { + extern int (*pToUpperLayerPktSent)(PNDIS_PACKET *pSkb); + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + pToUpperLayerPktSent(pNetPkt); + return; + } +#endif /* defined(PLATFORM_BL2348) || defined(PLATFORM_BL23570) */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IKANOS_VX_1X0 + { + IKANOS_DataFrameRx(pAd, pNetPkt); + return; + } +#endif /* IKANOS_VX_1X0 */ + +#ifdef INF_PPA_SUPPORT + { + if (ppa_hook_directpath_send_fn && (pAd->PPAEnable == TRUE)) + { + INT retVal, ret = 0; + UINT ppa_flags = 0; + + retVal = process_nbns_packet(pAd, pNetPkt); + + if (retVal > 0) + { + ret = ppa_hook_directpath_send_fn(pAd->g_if_id, pNetPkt, pNetPkt->len, ppa_flags); + if (ret == 0) + { + return; + } + netif_rx(pRxPkt); + } + else if (retVal == 0) + { + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + netif_rx(pRxPkt); + } + else + { + dev_kfree_skb_any(pNetPkt); + MEM_DBG_PKT_FREE_INC(pAd); + } + } + else + { + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + netif_rx(pRxPkt); + } + + return; + } +#endif /* INF_PPA_SUPPORT */ + +#ifdef CONFIG_RT2880_BRIDGING_ONLY + PACKET_CB_ASSIGN(pNetPkt, 22) = 0xa8; +#endif + +#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) + if(ra_classifier_hook_rx!= NULL) + { + unsigned long flags; + + RTMP_IRQ_LOCK(&pAd->page_lock, flags); + ra_classifier_hook_rx(pNetPkt, classifier_cur_cycle); + RTMP_IRQ_UNLOCK(&pAd->page_lock, flags); + } +#endif /* CONFIG_RA_CLASSIFIER */ + +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) +#if !defined(CONFIG_RA_NAT_NONE) + /* bruce+ + ra_sw_nat_hook_rx return 1 --> continue + ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx + */ + if (ra_sw_nat_hook_rx != NULL) + { + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + FOE_MAGIC_TAG(pRxPkt) = FOE_MAGIC_EXTIF; + if (ra_sw_nat_hook_rx(pRxPkt)) + { + FOE_MAGIC_TAG(pRxPkt) = 0; + netif_rx(pRxPkt); + } + return; + } +#endif /* CONFIG_RA_NAT_NONE */ +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef BG_FT_SUPPORT + if (BG_FTPH_PacketFromApHandle(pNetPkt) == 0) + return; +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef REDUCE_TCP_ACK_SUPPORT + ReduceAckUpdateDataCnx(pAd,pRxPkt); +#endif /* REDUCE_TCP_ACK_SUPPORT */ + + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + +#if defined (CONFIG_WIFI_PKT_FWD) + struct sk_buff *pOsRxPkt = RTPKT_TO_OSPKT(pRxPkt); + PNET_DEV rx_dev = RtmpOsPktNetDevGet(pRxPkt); + + /* all incoming packets should set CB to mark off which net device received and in which band */ + if ((rx_dev == rlt_dev_get_by_name("rai0")) || (rx_dev == rlt_dev_get_by_name("apclii0")) || + (rx_dev == rlt_dev_get_by_name("rai1")) || (rx_dev == rlt_dev_get_by_name("apclii1"))) { + RTMP_SET_PACKET_BAND(pOsRxPkt, RTMP_PACKET_SPECIFIC_5G); + + if (NdisEqualMemory(pOsRxPkt->dev->name, "apcli", 5)) + { + if (NdisEqualMemory(pOsRxPkt->dev->name, "apclii0", 7)) + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_CLIENT); + else + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_GUEST_CLIENT); + } + else + { + if (NdisEqualMemory(pOsRxPkt->dev->name, "rai0", 4)) + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_AP); + else + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_GUEST_AP); + } + } else { + RTMP_SET_PACKET_BAND(pOsRxPkt, RTMP_PACKET_SPECIFIC_2G); + + if (NdisEqualMemory(pOsRxPkt->dev->name, "apcli", 5)) + { + if (NdisEqualMemory(pOsRxPkt->dev->name, "apcli0", 6)) + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_2G_CLIENT); + else + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_2G_GUEST_CLIENT); + } + else + { + if (NdisEqualMemory(pOsRxPkt->dev->name, "ra0", 3)) + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_2G_AP); + else + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_2G_GUEST_AP); + } + } + + if (wf_fwd_rx_hook != NULL) + { + struct ethhdr *mh = eth_hdr(pRxPkt); + int ret = 0; + + if ((mh->h_dest[0] & 0x1) == 0x1) + { + if (NdisEqualMemory(pOsRxPkt->dev->name, "apcli", 5)) + { +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && + (RTMPQueryLookupRepeaterCliEntry(pAd, mh->h_source) == TRUE)) { + RELEASE_NDIS_PACKET(pAd, pRxPkt, NDIS_STATUS_FAILURE); + return; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + VOID *opp_band_tbl = NULL; + VOID *band_tbl = NULL; + + if (wf_fwd_feedback_map_table) + wf_fwd_feedback_map_table(pAd, &band_tbl, &opp_band_tbl); + +#ifdef APCLI_GUEST_NETWORK_SUPPORT + if ((NdisEqualMemory(pOsRxPkt->dev->name, "apcli0", 6)) || + (NdisEqualMemory(pOsRxPkt->dev->name, "apclii0", 7))) { +#endif /* APCLI_GUEST_NETWORK_SUPPORT */ + if ((opp_band_tbl != NULL) + && MAC_ADDR_EQUAL(((UCHAR *)((REPEATER_ADAPTER_DATA_TABLE *)opp_band_tbl)->Wdev_ifAddr), mh->h_source)) { + RELEASE_NDIS_PACKET(pAd, pRxPkt, NDIS_STATUS_FAILURE); + return; + } +#ifdef APCLI_GUEST_NETWORK_SUPPORT + } else { + if ((opp_band_pad != NULL) + && MAC_ADDR_EQUAL(opp_band_pad->ApCfg.ApCliTab[1].wdev.if_addr, mh->h_source)) { + RELEASE_NDIS_PACKET(pAd, pRxPkt, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* APCLI_GUEST_NETWORK_SUPPORT */ + } + } + } + + ret = wf_fwd_rx_hook(pRxPkt); + + if (ret == 0) { + return; + } else if (ret == 2) { + RELEASE_NDIS_PACKET(pAd, pRxPkt, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* CONFIG_WIFI_PKT_FWD */ + + netif_rx(pRxPkt); +} + + +#ifdef CONFIG_SNIFFER_SUPPORT + +INT Monitor_VirtualIF_Open(PNET_DEV dev_p) +{ + VOID *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + + DBGPRINT(RT_DEBUG_ERROR, ("%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_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_SNIFF_OPEN, 0, dev_p, 0); + + + //Monitor_Open(pAd,dev_p); + + return 0; +} + +INT Monitor_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_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_SNIFF_CLOSE, 0, dev_p, 0); + //Monitor_Close(pAd,dev_p); + + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; +} + + +VOID RT28xx_Monitor_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 = Monitor_VirtualIF_Open; + netDevOpHook.stop = Monitor_VirtualIF_Close; + netDevOpHook.xmit = rt28xx_send_packets; + netDevOpHook.ioctl = rt28xx_ioctl; + DBGPRINT(RT_DEBUG_OFF, ("%s: %d !!!!####!!!!!!\n",__FUNCTION__, __LINE__)); + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_SNIFF_INIT, 0, &netDevOpHook, 0); + +} +VOID RT28xx_Monitor_Remove(VOID *pAd) +{ + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_SNIFF_REMOVE, 0, NULL, 0); + +} + +void STA_MonPktSend(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + PNET_DEV pNetDev; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + USHORT DataSize; + UINT32 MaxRssi; + UINT32 timestamp; + CHAR RssiForRadiotap; + UCHAR L2PAD, PHYMODE, BW, ShortGI, MCS, LDPC, LDPC_EX_SYM, AMPDU, STBC, RSSI1; + UCHAR BssMonitorFlag11n, Channel, CentralChannel; + UCHAR *pData, *pDevName; + UCHAR sniffer_type = pAd->sniffer_ctl.sniffer_type; + UCHAR sideband_index = 0; + + ASSERT(pRxBlk->pRxPacket); + + if (pRxBlk->DataSize < 10) { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize)); + goto err_free_sk_buff; + } + + if (sniffer_type == RADIOTAP_TYPE) { + if (pRxBlk->DataSize + sizeof(struct mtk_radiotap_header) > RX_BUFFER_AGGRESIZE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(struct mtk_radiotap_header))); + goto err_free_sk_buff; + } + } + + if (sniffer_type == PRISM_TYPE) { + if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); + goto err_free_sk_buff; + } + } + + MaxRssi = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, pRxBlk->rssi[0], RSSI_0), + ConvertToRssi(pAd, pRxBlk->rssi[1], RSSI_1), + ConvertToRssi(pAd, pRxBlk->rssi[2], RSSI_2)); + + if (sniffer_type == RADIOTAP_TYPE){ + RssiForRadiotap = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, pRxBlk->rssi[0], RSSI_0), + ConvertToRssi(pAd, pRxBlk->rssi[1], RSSI_1), + ConvertToRssi(pAd, pRxBlk->rssi[2], RSSI_2)); + } + + pNetDev = pAd->monitor_ctrl.monitor_wdev.if_dev; //send packet to mon0 + //pNetDev = get_netdev_from_bssid(pAd, BSS0); + + pRxPacket = pRxBlk->pRxPacket; + pHeader = pRxBlk->pHeader; + pData = pRxBlk->pData; + DataSize = pRxBlk->DataSize; + L2PAD = pRxBlk->pRxInfo->L2PAD; + PHYMODE = pRxBlk->rx_rate.field.MODE; + BW = pRxBlk->rx_rate.field.BW; + + ShortGI = pRxBlk->rx_rate.field.ShortGI; + MCS = pRxBlk->rx_rate.field.MCS; + LDPC = pRxBlk->rx_rate.field.ldpc; + if (pAd->chipCap.hif_type == HIF_RLT) + LDPC_EX_SYM = pRxBlk->ldpc_ex_sym; + else + LDPC_EX_SYM = 0; + + AMPDU = pRxBlk->pRxInfo->AMPDU; + STBC = pRxBlk->rx_rate.field.STBC; + RSSI1 = pRxBlk->rssi[1]; + //if(pRxBlk->pRxWI->RXWI_N.bbp_rxinfo[12] != 0) +#ifdef RLT_MAC + NdisCopyMemory(×tamp,&pRxBlk->pRxWI->RXWI_N.bbp_rxinfo[12],4); +#endif + + BssMonitorFlag11n = 0; +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + BssMonitorFlag11n = (pAd->StaCfg.BssMonitorFlag & MONITOR_FLAG_11N_SNIFFER); +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + pDevName = (UCHAR *)RtmpOsGetNetDevName(pAd->net_dev); + Channel = pAd->CommonCfg.Channel; + + if (BW == BW_20) + CentralChannel = Channel; + else if (BW == BW_40) + CentralChannel = pAd->CommonCfg.CentralChannel; +#ifdef DOT11_VHT_AC + else if (BW == BW_80) + CentralChannel = pAd->CommonCfg.vht_cent_ch; +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_VHT_AC + if (BW == BW_80) { + sideband_index = vht_prim_ch_idx(CentralChannel, Channel); + } +#endif /* DOT11_VHT_AC */ + + if (sniffer_type == RADIOTAP_TYPE) { +#ifdef PPI_HEADER + send_ppi_monitor_packets(pNetDev, pRxPacket, (void *)pHeader, pData, DataSize, + L2PAD, PHYMODE, BW, ShortGI, MCS, LDPC, LDPC_EX_SYM, + AMPDU, STBC, RSSI1, pDevName, Channel, CentralChannel, + sideband_index, RssiForRadiotap,timestamp); + +#else + send_radiotap_monitor_packets(pNetDev, pRxPacket, (void *)pHeader, pData, DataSize, + L2PAD, PHYMODE, BW, ShortGI, MCS, LDPC, LDPC_EX_SYM, + AMPDU, STBC, RSSI1, pDevName, Channel, CentralChannel, + sideband_index, RssiForRadiotap,timestamp); +#endif + } + + if (sniffer_type == PRISM_TYPE) { + send_prism_monitor_packets(pNetDev, pRxPacket, (void *)pHeader, pData, DataSize, + L2PAD, PHYMODE, BW, ShortGI, MCS, AMPDU, STBC, RSSI1, + BssMonitorFlag11n, pDevName, Channel, CentralChannel, + MaxRssi); + } + + return; + +err_free_sk_buff: + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; +} +#endif /* CONFIG_SNIFFER_SUPPORT */ + + +extern NDIS_SPIN_LOCK TimerSemLock; + +VOID RTMPFreeAdapter(VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + POS_COOKIE os_cookie; + int index; + + os_cookie=(POS_COOKIE)pAd->OS_Cookie; + + if (pAd->BeaconBuf) + os_free_mem(NULL, pAd->BeaconBuf); + +#ifdef MULTIPLE_CARD_SUPPORT +#ifdef RTMP_FLASH_SUPPORT + if (pAd->eebuf && (pAd->eebuf != pAd->EEPROMImage)) + { + os_free_mem(NULL, pAd->eebuf); + pAd->eebuf = NULL; + } +#endif /* RTMP_FLASH_SUPPORT */ +#endif /* MULTIPLE_CARD_SUPPORT */ + + NdisFreeSpinLock(&pAd->MgmtRingLock); + +#ifdef RTMP_MAC_PCI + for (index = 0; index < NUM_OF_RX_RING; index++) + NdisFreeSpinLock(&pAd->RxRingLock[index]); + + NdisFreeSpinLock(&pAd->McuCmdLock); +#endif /* RTMP_MAC_PCI */ + +#if defined(RT3290) || defined(RLT_MAC) + NdisFreeSpinLock(&pAd->WlanEnLock); +#endif /* defined(RT3290) || defined(RLT_MAC) */ + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); + NdisFreeSpinLock(&pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + + NdisFreeSpinLock(&pAd->irq_lock); + +#ifdef RTMP_MAC_PCI + NdisFreeSpinLock(&pAd->LockInterrupt); +#ifdef CONFIG_ANDES_SUPPORT + NdisFreeSpinLock(&pAd->CtrlRingLock); + NdisFreeSpinLock(&pAd->mcu_atomic); +#endif /* CONFIG_ANDES_SUPPORT */ + NdisFreeSpinLock(&pAd->tssi_lock); +#endif /* RTMP_MAC_PCI */ + +#ifdef SPECIFIC_BCN_BUF_SUPPORT + NdisFreeSpinLock(&pAd->ShrMemLock); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + +#ifdef UAPSD_SUPPORT + NdisFreeSpinLock(&pAd->UAPSDEOSPLock); /* OS_ABL_SUPPORT */ +#endif /* UAPSD_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + NdisFreeSpinLock(&pAd->mpdu_blk_pool.lock); +#endif /* DOT11_N_SUPPORT */ + + if (pAd->iw_stats) + { + os_free_mem(NULL, pAd->iw_stats); + pAd->iw_stats = NULL; + } + + NdisFreeSpinLock(&TimerSemLock); + +#ifdef RALINK_ATE +#endif /* RALINK_ATE */ + + RTMP_OS_FREE_TIMER(pAd); + RTMP_OS_FREE_LOCK(pAd); + RTMP_OS_FREE_TASKLET(pAd); + RTMP_OS_FREE_TASK(pAd); + RTMP_OS_FREE_SEM(pAd); + RTMP_OS_FREE_ATOMIC(pAd); + + RtmpOsVfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa); */ + if (os_cookie) + os_free_mem(NULL, os_cookie); +} + + +#ifdef ETH_CONVERT_SUPPORT +static inline BOOLEAN rtmp_clone_mac( + RTMP_ADAPTER *pAd, + UCHAR *pkt, + RTMP_NET_ETH_CONVERT_DEV_SEARCH Func) +{ + ETH_CONVERT_STRUCT *eth_convert; + UCHAR *pData = GET_OS_PKT_DATAPTR(pkt); + BOOLEAN valid = TRUE; + + eth_convert = &pAd->EthConvert; + /* Don't move this checking into wdev_tx_pkts(), becasue the net_device is OS-depeneded. */ + if ((eth_convert->ECMode & ETH_CONVERT_MODE_CLONE) + && (!eth_convert->CloneMacVaild) + && (eth_convert->macAutoLearn) + && (!(pData[6] & 0x1))) + { + VOID *pNetDev = Func(pAd->net_dev, pData); + + if (!pNetDev) { + NdisMoveMemory(ð_convert->EthCloneMac[0], &pData[6], MAC_ADDR_LEN); + eth_convert->CloneMacVaild = TRUE; + } + } + + /* Drop pkt since we are in pure clone mode and the src is not the cloned mac address. */ + if ((eth_convert->ECMode == ETH_CONVERT_MODE_CLONE) + && (NdisEqualMemory(pAd->CurrentAddress, &pData[6], MAC_ADDR_LEN) == FALSE)) + valid = FALSE; + + return valid; +} +#endif /* ETH_CONVERT_SUPPORT */ + + +int RTMPSendPackets( + IN NDIS_HANDLE dev_hnd, + IN PPNDIS_PACKET pkt_list, + IN UINT pkt_cnt, + IN UINT32 pkt_total_len, + IN RTMP_NET_ETH_CONVERT_DEV_SEARCH Func) +{ + struct wifi_dev *wdev = (struct wifi_dev *)dev_hnd; + RTMP_ADAPTER *pAd; + PNDIS_PACKET pPacket = pkt_list[0]; + + ASSERT(wdev->sys_handle); + pAd = (RTMP_ADAPTER *)wdev->sys_handle; + INC_COUNTER64(pAd->WlanCounters.TransmitCountFrmOs); +#ifdef RTMP_MAC_PCI + /* Update timer to flush tx ring buffer */ + RTMPModTimer(&pAd->TxDoneCleanupTimer, 50); +#endif /* RTMP_MAC_PCI */ + + if (!pPacket) + return 0; + +#ifdef WSC_NFC_SUPPORT + { + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pPacket); + USHORT protocol = 0; + protocol = ntohs(pRxPkt->protocol); + if (protocol == 0x6605) + { + NfcParseRspCommand(pAd, pRxPkt->data, pRxPkt->len); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + return 0; + } + } +#endif /* WSC_NFC_SUPPORT */ + + if (pkt_total_len < 14) + { + hex_dump("bad packet", GET_OS_PKT_DATAPTR(pPacket), pkt_total_len); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return 0; + } + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + return 0; + } +#endif /* RALINK_ATE */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Drop send request since we are in monitor mode */ + if (MONITOR_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + return 0; + } + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_5VT_ENHANCE + RTMP_SET_PACKET_5VT(pPacket, 0); + if (*(int*)(GET_OS_PKT_CB(pPacket)) == BRIDGE_TAG) { + RTMP_SET_PACKET_5VT(pPacket, 1); + } +#endif /* CONFIG_5VT_ENHANCE */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT + if (wdev->wdev_type == WDEV_TYPE_STA) + { + if (rtmp_clone_mac(pAd, pPacket, Func) == FALSE) + { + /* Drop pkt since we are in pure clone mode and the src is not the cloned mac address. */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + goto done; + } + } +#endif /* ETH_CONVERT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#if defined (CONFIG_WIFI_PKT_FWD) + if (wf_fwd_tx_hook != NULL) + { + if (wf_fwd_tx_hook(pPacket) == 1) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return 0; + } + } +#endif /* CONFIG_WIFI_PKT_FWD */ + + wdev_tx_pkts((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1, wdev); + +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT +done: +#endif /* ETH_CONVERT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + return 0; +} + + +PNET_DEV get_netdev_from_bssid(RTMP_ADAPTER *pAd, UCHAR FromWhichBSSID) +{ + PNET_DEV dev_p = NULL; +#ifdef CONFIG_AP_SUPPORT + UCHAR infRealIdx; +#endif /* CONFIG_AP_SUPPORT */ + + do + { +#ifdef CONFIG_STA_SUPPORT +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO) + { + dev_p = pAd->ApCfg.MBSSID[BSS0].wdev.if_dev; + break; + } + else if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_CLI) + { + //CFG_TODO + break; + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + infRealIdx = FromWhichBSSID & (NET_DEVICE_REAL_IDX_MASK); +#ifdef APCLI_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) + { + dev_p = (infRealIdx >= MAX_APCLI_NUM ? NULL : pAd->ApCfg.ApCliTab[infRealIdx].wdev.if_dev); + break; + } +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) + { + dev_p = ((infRealIdx >= MAX_WDS_ENTRY) ? NULL : pAd->WdsTab.WdsEntry[infRealIdx].wdev.if_dev); + break; + } +#endif /* WDS_SUPPORT */ + + if ((FromWhichBSSID > 0) && + (FromWhichBSSID < pAd->ApCfg.BssidNum) && + (FromWhichBSSID < MAX_MBSSID_NUM(pAd)) && + (FromWhichBSSID < HW_BEACON_MAX_NUM)) + { + dev_p = pAd->ApCfg.MBSSID[FromWhichBSSID].wdev.if_dev; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + dev_p = pAd->net_dev; + } + + } while (FALSE); + + ASSERT(dev_p); + return dev_p; +} + + +#ifdef CONFIG_AP_SUPPORT +/* +======================================================================== +Routine Description: + Driver pre-Ioctl for AP. + +Arguments: + pAdSrc - WLAN control block pointer + pCB - the IOCTL parameters + +Return Value: + NDIS_STATUS_SUCCESS - IOCTL OK + Otherwise - IOCTL fail + +Note: +======================================================================== +*/ +INT RTMP_AP_IoctlPrepare(RTMP_ADAPTER *pAd, VOID *pCB) +{ + RT_CMD_AP_IOCTL_CONFIG *pConfig = (RT_CMD_AP_IOCTL_CONFIG *)pCB; + POS_COOKIE pObj; + USHORT index; + INT Status = NDIS_STATUS_SUCCESS; +#ifdef CONFIG_APSTA_MIXED_SUPPORT + INT cmd = 0xff; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if((pConfig->priv_flags == INT_MAIN) && !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + if (pConfig->pCmdData == NULL) + return Status; + + if (RtPrivIoctlSetVal() == pConfig->CmdId_RTPRIV_IOCTL_SET) + { + if (TRUE +#ifdef CONFIG_APSTA_MIXED_SUPPORT + && (strstr(pConfig->pCmdData, "OpMode") == NULL) +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#ifdef SINGLE_SKU + && (strstr(pConfig->pCmdData, "ModuleTxpower") == NULL) +#endif /* SINGLE_SKU */ + ) + { + return -ENETDOWN; + } + } + else + return -ENETDOWN; + } + + /* determine this ioctl command is comming from which interface. */ + if (pConfig->priv_flags == INT_MAIN) + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + else if (pConfig->priv_flags == INT_MBSSID) + { + pObj->ioctl_if_type = INT_MBSSID; +/* if (!RTMPEqualMemory(net_dev->name, pAd->net_dev->name, 3)) // for multi-physical card, no MBSSID */ + if (strcmp(pConfig->name, RtmpOsGetNetDevName(pAd->net_dev)) != 0) /* sample */ + { + for (index = 1; index < pAd->ApCfg.BssidNum; index++) + { + if (pAd->ApCfg.MBSSID[index].wdev.if_dev == pConfig->net_dev) + { + pObj->ioctl_if = index; + break; + } + } + /* Interface not found! */ + if(index == pAd->ApCfg.BssidNum) + return -ENETDOWN; + } + else /* ioctl command from I/F(ra0) */ + { + pObj->ioctl_if = MAIN_MBSSID; + } + MBSS_MR_APIDX_SANITY_CHECK(pAd, pObj->ioctl_if); + } +#ifdef WDS_SUPPORT + else if (pConfig->priv_flags == INT_WDS) + { + pObj->ioctl_if_type = INT_WDS; + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].wdev.if_dev == pConfig->net_dev) + { + pObj->ioctl_if = index; + break; + } + + if(index == MAX_WDS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): can not find wds I/F\n", __FUNCTION__)); + return -ENETDOWN; + } + } + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + else if (pConfig->priv_flags == INT_APCLI) + { + pObj->ioctl_if_type = INT_APCLI; + for (index = 0; index < MAX_APCLI_NUM; index++) + { + if (pAd->ApCfg.ApCliTab[index].wdev.if_dev == pConfig->net_dev) + { + pObj->ioctl_if = index; + break; + } + + if(index == MAX_APCLI_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): can not find Apcli I/F\n", __FUNCTION__)); + return -ENETDOWN; + } + } + APCLI_MR_APIDX_SANITY_CHECK(pObj->ioctl_if); + } +#endif /* APCLI_SUPPORT */ + else + { + /* DBGPRINT(RT_DEBUG_WARN, ("IOCTL is not supported in WDS interface\n")); */ + return -EOPNOTSUPP; + } + + pConfig->apidx = pObj->ioctl_if; + return Status; +} + + +VOID AP_E2PROM_IOCTL_PostCtrl( + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN PSTRING msg) +{ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +} + + +VOID IAPP_L2_UpdatePostCtrl( + IN PRTMP_ADAPTER pAd, + IN UINT8 *mac_p, + IN INT bssid) +{ +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WDS_SUPPORT +VOID AP_WDS_KeyNameMakeUp( + IN STRING *pKey, + IN UINT32 KeyMaxSize, + IN INT KeyId) +{ + snprintf(pKey, KeyMaxSize, "Wds%dKey", KeyId); +} +#endif /* WDS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_rbus_pci_drv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_rbus_pci_drv.c new file mode 100644 index 000000000..ab30b24f7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_rbus_pci_drv.c @@ -0,0 +1,2108 @@ +/**************************************************************************** + * 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. + ***************************************************************************/ + + + +#ifdef RTMP_MAC_PCI +#include "rt_config.h" + +#ifdef BB_SOC +__IMEM void rx_done_tasklet(unsigned long data); +#else +static void rx_done_tasklet(unsigned long data); +#endif +#ifdef CONFIG_ANDES_SUPPORT +static void rx1_done_tasklet(unsigned long data); +#endif /* CONFIG_ANDES_SUPPORT */ +static void mgmt_dma_done_tasklet(unsigned long data); +static void ac0_dma_done_tasklet(unsigned long data); +#ifdef RALINK_ATE +static void ate_ac0_dma_done_tasklet(unsigned long data); +#endif /* RALINK_ATE */ +static void ac1_dma_done_tasklet(unsigned long data); +static void ac2_dma_done_tasklet(unsigned long data); +static void ac3_dma_done_tasklet(unsigned long data); +static void hcca_dma_done_tasklet(unsigned long data); +static void fifo_statistic_full_tasklet(unsigned long data); + +#ifdef UAPSD_SUPPORT +static void uapsd_eosp_sent_tasklet(unsigned long data); +#endif /* UAPSD_SUPPORT */ + + +/*---------------------------------------------------------------------*/ +/* Symbol & Macro Definitions */ +/*---------------------------------------------------------------------*/ +NDIS_STATUS RtmpNetTaskInit(IN RTMP_ADAPTER *pAd) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + + RTMP_OS_TASKLET_INIT(pAd, &pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd); +#ifdef CONFIG_ANDES_SUPPORT + RTMP_OS_TASKLET_INIT(pAd, &pObj->rx1_done_task, rx1_done_tasklet, (unsigned long)pAd); +#endif /* CONFIG_ANDES_SUPPORT */ + RTMP_OS_TASKLET_INIT(pAd, &pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac0_dma_done_task, ac0_dma_done_tasklet, (unsigned long)pAd); +#ifdef RALINK_ATE + RTMP_OS_TASKLET_INIT(pAd, &pObj->ate_ac0_dma_done_task, ate_ac0_dma_done_tasklet, (unsigned long)pAd); +#endif /* RALINK_ATE */ + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac1_dma_done_task, ac1_dma_done_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac2_dma_done_task, ac2_dma_done_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac3_dma_done_task, ac3_dma_done_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->hcca_dma_done_task, hcca_dma_done_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->pretbtt_task, pretbtt_tasklet, (unsigned long)pAd); + RTMP_OS_TASKLET_INIT(pAd, &pObj->fifo_statistic_full_task, fifo_statistic_full_tasklet, (unsigned long)pAd); +#ifdef UAPSD_SUPPORT + RTMP_OS_TASKLET_INIT(pAd, &pObj->uapsd_eosp_sent_task, uapsd_eosp_sent_tasklet, (unsigned long)pAd); +#endif /* UAPSD_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DFS_SUPPORT + RTMP_OS_TASKLET_INIT(pAd, &pObj->dfs_task, dfs_tasklet, (unsigned long)pAd); +#endif /* DFS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +void RtmpNetTaskExit(IN RTMP_ADAPTER *pAd) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_OS_TASKLET_KILL(&pObj->rx_done_task); +#ifdef CONFIG_ANDES_SUPPORT + RTMP_OS_TASKLET_KILL(&pObj->rx1_done_task); +#endif /* CONFIG_ANDES_SUPPORT */ + RTMP_OS_TASKLET_KILL(&pObj->mgmt_dma_done_task); + RTMP_OS_TASKLET_KILL(&pObj->ac0_dma_done_task); +#ifdef RALINK_ATE + RTMP_OS_TASKLET_KILL(&pObj->ate_ac0_dma_done_task); +#endif /* RALINK_ATE */ + RTMP_OS_TASKLET_KILL(&pObj->ac1_dma_done_task); + RTMP_OS_TASKLET_KILL(&pObj->ac2_dma_done_task); + RTMP_OS_TASKLET_KILL(&pObj->ac3_dma_done_task); + RTMP_OS_TASKLET_KILL(&pObj->hcca_dma_done_task); + RTMP_OS_TASKLET_KILL(&pObj->tbtt_task); + RTMP_OS_TASKLET_KILL(&pObj->fifo_statistic_full_task); +#ifdef UAPSD_SUPPORT + RTMP_OS_TASKLET_KILL(&pObj->uapsd_eosp_sent_task); +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DFS_SUPPORT + RTMP_OS_TASKLET_KILL(&pObj->dfs_task); +#endif /* DFS_SUPPORT */ + + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +NDIS_STATUS RtmpMgmtTaskInit(IN RTMP_ADAPTER *pAd) +{ + RTMP_OS_TASK *pTask; + NDIS_STATUS status; + + + /* Creat Command Thread */ + pTask = &pAd->cmdQTask; + RTMP_OS_TASK_INIT(pTask, "RtmpCmdQTask", pAd); + status = RtmpOSTaskAttach(pTask, RTPCICmdThread, (ULONG)pTask); + if (status == NDIS_STATUS_FAILURE) + { +/* printk ("%s: unable to start RTPCICmdThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); */ + printk ("Unable to start RTPCICmdThread!\n"); + return NDIS_STATUS_FAILURE; + } + +#ifdef WSC_INCLUDED + /* start the crediential write task first. */ + WscThreadInit(pAd); +#endif /* WSC_INCLUDED */ + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Close kernel threads. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID RtmpMgmtTaskExit( + IN RTMP_ADAPTER *pAd) +{ + INT ret; + + + /* Terminate cmdQ thread */ + RTMP_OS_TASK_LEGALITY(&pAd->cmdQTask) + { + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; + NdisReleaseSpinLock(&pAd->CmdQLock); + + /*RTUSBCMDUp(&pAd->cmdQTask); */ + ret = RtmpOSTaskKill(&pAd->cmdQTask); + if (ret == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Kill command task fail!\n")); + } + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_UNKNOWN; + } + +#ifdef WSC_INCLUDED + WscThreadExit(pAd); +#endif /* WSC_INCLUDED */ + + return; +} + + +static inline void rt2860_int_enable(PRTMP_ADAPTER pAd, unsigned int mode) +{ + u32 regValue = 0; + + pAd->int_disable_mask &= ~(mode); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + if(IS_MT76x2(pAd)) + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask | RLT_INT_AC0_DLY); + else + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); +#endif /* RTMP_MAC */ + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); +#ifdef RTMP_MAC_PCI + //RTMP_IO_READ32(pAd, INT_MASK_CSR, ®Value); /* Push write command to take effect quickly (i.e. flush the write data) */ +#endif /* RTMP_MAC_PCI */ + if (regValue != 0) { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); + } +} + + +static inline void rt2860_int_disable(PRTMP_ADAPTER pAd, unsigned int mode) +{ + u32 regValue; + + pAd->int_disable_mask |= mode; + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); +#ifdef RTMP_MAC_PCI + //RTMP_IO_READ32(pAd, INT_MASK_CSR, ®Value); /* Push write command to take effect quickly (i.e. flush the write data) */ +#endif /* RTMP_MAC_PCI */ + if (regValue == 0) { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); + } +} + + +/*************************************************************************** + * + * tasklet related procedures. + * + **************************************************************************/ +static void mgmt_dma_done_tasklet(unsigned long data) +{ +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, mgmt_dma_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + unsigned long flags; + UINT32 INT_MGMT_DLY = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_MGMT_DLY = RLT_INT_MGMT_DLY; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_MGMT_DLY = RTMP_INT_MGMT_DLY; +#endif /* RTMP_MAC */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~INT_MGMT_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_MGMT_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + RTMPHandleMgmtRingDmaDoneInterrupt(pAd); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if (pAd->int_pending & INT_MGMT_DLY) + { + /* double check to avoid lose of interrupts */ + pObj = (POS_COOKIE) pAd->OS_Cookie; + RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, INT_MGMT_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +#ifdef BB_SOC +__IMEM void rx_done_tasklet(unsigned long data) +#else +static void rx_done_tasklet(unsigned long data) +#endif +{ + unsigned long flags; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, rx_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + UINT32 INT_RX = 0; + + pAd->rx_tasklet_counter++; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_RX = RLT_INT_RX_DATA; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_RX = RTMP_INT_RX; +#endif /* RTMP_MAC */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~(INT_RX); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TASKLET); +#endif /* UAPSD_SUPPORT */ + + pObj = (POS_COOKIE) pAd->OS_Cookie; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~(INT_RX); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = rtmp_rx_done_handle(pAd); + +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD_STOP(); +#endif /* UAPSD_SUPPORT */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid rotting packet */ + if ((pAd->int_pending & INT_RX) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->rx_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, INT_RX); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +#ifdef CONFIG_ANDES_SUPPORT +static void rx1_done_tasklet(unsigned long data) +{ + unsigned long flags; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, rx1_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~(RLT_INT_RX_CMD); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + pObj = (POS_COOKIE) pAd->OS_Cookie; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~(RLT_INT_RX_CMD); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RxRing1DoneInterruptHandle(pAd); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid rotting packet */ + if ((pAd->int_pending & RLT_INT_RX_CMD) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->rx1_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable Rx1INT again */ + rt2860_int_enable(pAd, RLT_INT_RX_CMD); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} +#endif /* CONFIG_ANDES_SUPPORT */ + + +void fifo_statistic_full_tasklet(unsigned long data) +{ + unsigned long flags; +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, fifo_statistic_full_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + UINT32 FifoStaFullInt = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + FifoStaFullInt = RLT_FifoStaFullInt; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + FifoStaFullInt = RTMP_FifoStaFullInt; +#endif /* RTMP_MAC */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~(FifoStaFullInt); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~(FifoStaFullInt); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + NICUpdateFifoStaCounters(pAd); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* + * double check to avoid rotting packet + */ + if (pAd->int_pending & FifoStaFullInt) + { + RTMP_OS_TASKLET_SCHE(&pObj->fifo_statistic_full_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, FifoStaFullInt); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + +} + + +static void hcca_dma_done_tasklet(unsigned long data) +{ +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, hcca_dma_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + unsigned long flags; + BOOLEAN bReschedule = 0; + UINT32 INT_HCCA_DLY = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_HCCA_DLY = RLT_INT_HCCA_DLY; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_HCCA_DLY = RTMP_INT_HCCA_DLY; +#endif /* RTMP_MAC */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~INT_HCCA_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_HCCA_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMPHandleTxRing8DmaDoneInterrupt(pAd); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, TX_HCCA_DONE); +#endif /* RTMP_MAC */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid lose of interrupts */ + if ((pAd->int_pending & INT_HCCA_DLY) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, INT_HCCA_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +static void ac3_dma_done_tasklet(unsigned long data) +{ +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, ac3_dma_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + unsigned long flags; + BOOLEAN bReschedule = 0; + UINT32 INT_AC3_DLY = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_AC3_DLY = RLT_INT_AC3_DLY; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_AC3_DLY = RTMP_INT_AC3_DLY; +#endif /* RTMP_MAC */ + + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~(INT_AC3_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC3_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, TX_AC3_DONE); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid lose of interrupts */ + if ((pAd->int_pending & INT_AC3_DLY) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, INT_AC3_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +static void ac2_dma_done_tasklet(unsigned long data) +{ +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, ac2_dma_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + unsigned long flags; + BOOLEAN bReschedule = 0; + UINT32 INT_AC2_DLY = 0; + + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_AC2_DLY = RLT_INT_AC2_DLY; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_AC2_DLY = RTMP_INT_AC2_DLY; +#endif /* RTMP_MAC */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~(INT_AC2_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC2_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, TX_AC2_DONE); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid lose of interrupts */ + if ((pAd->int_pending & INT_AC2_DLY) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, INT_AC2_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +static void ac1_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, ac1_dma_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + UINT32 INT_AC1_DLY = 0; + + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + INT_AC1_DLY = RLT_INT_AC1_DLY; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + INT_AC1_DLY = RTMP_INT_AC1_DLY; +#endif /* RTMP_MAC */ + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_disable_mask &= ~(INT_AC1_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC1_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, TX_AC1_DONE); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid lose of interrupts */ + if ((pAd->int_pending & INT_AC1_DLY) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_task); + + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + rt2860_int_enable(pAd, INT_AC1_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +static void ac0_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, ac0_dma_done_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + + pAd->tx_tasklet_counter++; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + if(IS_MT76x2(pAd)) + pAd->int_disable_mask &= ~(INT_TX_DLY); + else + pAd->int_disable_mask &= ~(RLT_INT_AC0_DLY); + } +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + pAd->int_disable_mask &= ~(RTMP_INT_AC0_DMA_DONE); +#endif /* RTMP_MAC */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT && IS_MT76x2(pAd)) + pAd->int_pending &= ~(INT_TX_DLY); + else + pAd->int_pending &= ~(RLT_INT_AC0_DLY); + /* 76x2 uses INT_TX_DLY, 76x0 uses RLT_INT_AC0_DLY */ +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + pAd->int_pending &= ~RTMP_INT_AC0_DMA_DONE; +#endif /* RTMP_MAC */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, TX_AC0_DONE); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* double check to avoid lose of interrupts */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + if(IS_MT76x2(pAd)) + { + if ((pAd->int_pending & INT_TX_DLY) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + } + else + { + if ((pAd->int_pending & RLT_INT_AC0_DLY) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + } + } +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if ((pAd->int_pending & RTMP_INT_AC0_DMA_DONE) || bReschedule) + { + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + } +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + if(IS_MT76x2(pAd)) + rt2860_int_enable(pAd, INT_TX_DLY); + else + rt2860_int_enable(pAd, RLT_INT_AC0_DLY); + } +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + rt2860_int_enable(pAd, RTMP_INT_AC0_DMA_DONE); +#endif /* RTMP_MAC */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +#ifdef RALINK_ATE +static void ate_ac0_dma_done_tasklet(unsigned long data) +{ + return; +} +#endif /* RALINK_ATE */ + + +#ifdef UAPSD_SUPPORT +/* +======================================================================== +Routine Description: + Used to send the EOSP frame. + +Arguments: + data Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +static void uapsd_eosp_sent_tasklet(unsigned long data) +{ +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, uapsd_eosp_sent_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; +#endif /* WORKQUEUE_BH */ + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +void schedule_dfs_task(PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + RTMP_OS_TASKLET_SCHE(&pObj->dfs_task); +} + + +void dfs_tasklet(unsigned long data) +{ +#ifdef WORKQUEUE_BH + struct work_struct *work = (struct work_struct *)data; + POS_COOKIE pObj = container_of(work, struct os_cookie, dfs_task); + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; +#endif /* WORKQUEUE_BH */ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + + if (pRadarDetect->DFSAPRestart == 1) + { + int i, j; + + pDfsSwParam->dfs_w_counter += 10; + /* reset period table */ + for (i = 0; i < pAd->chipCap.DfsEngineNum; i++) + { + for (j = 0; j < NEW_DFS_MPERIOD_ENT_NUM; j++) + { + pDfsSwParam->DFS_T[i][j].period = 0; + pDfsSwParam->DFS_T[i][j].idx = 0; + pDfsSwParam->DFS_T[i][j].idx2 = 0; + } + } + + APStop(pAd); + APStartUp(pAd); + pRadarDetect->DFSAPRestart = 0; + } + else + /* check radar here */ + { + int idx; + if (pRadarDetect->radarDeclared == 0) + { + for (idx = 0; idx < 3; idx++) + { + if (SWRadarCheck(pAd, idx) == 1) + { + /*find the radar signals */ + pRadarDetect->radarDeclared = 1; + break; + } + } + } + } +} +#endif /* DFS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +int print_int_count = 0; +VOID RTMPHandleInterrupt(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + UINT32 IntSource; + POS_COOKIE pObj; + unsigned long flags=0; + UINT32 INT_RX_DATA = 0, INT_RX_CMD=0, TxCoherent = 0, RxCoherent = 0, FifoStaFullInt = 0; + UINT32 INT_MGMT_DLY = 0, INT_HCCA_DLY = 0, INT_AC3_DLY = 0, INT_AC2_DLY = 0, INT_AC1_DLY = 0, INT_AC0_DLY = 0; + UINT32 PreTBTTInt = 0, TBTTInt = 0, GPTimeOutInt = 0; +#ifdef CARRIER_DETECTION_SUPPORT + UINT32 RadarInt = 0; +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + UINT32 AutoWakeupInt = 0; +#endif /* CONFIG_STA_SUPPORT */ + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + /* + Note 03312008: we can not return here before + + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); + Or kernel will panic after ifconfig ra0 down sometimes + */ + + /* Inital the Interrupt source. */ + IntSource = 0x00000000L; + + /* + Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp + And at the same time, clock maybe turned off that say there is no DMA service. + when ASIC get to sleep. + To prevent system hang on power saving. + We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up. + + RT2661 => when ASIC is sleeping, MAC register cannot be read and written. + RT2860 => when ASIC is sleeping, MAC register can be read and written. + */ + /* if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) */ + { + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource); /* write 1 to clear */ + } +/* else + DBGPRINT(RT_DEBUG_TRACE, (">>>fOP_STATUS_DOZE<<<\n")); */ + +//DBGPRINT(RT_DEBUG_OFF, ("%s():IntSource=0x%x\n", __FUNCTION__, IntSource.word)); + + + //if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |fRTMP_ADAPTER_HALT_IN_PROGRESS))) + // return; + + /* + Handle interrupt, walk through all bits + Should start from highest priority interrupt + The priority can be adjust by altering processing if statement + */ +#ifdef DBG +#endif + + if (IntSource == 0x0) + pAd->fake_int_counter++; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + INT_RX_DATA = RLT_INT_RX_DATA; + INT_RX_CMD = RLT_INT_RX_CMD; + TxCoherent = RLT_TxCoherent; + RxCoherent = RLT_RxCoherent; + FifoStaFullInt = RLT_FifoStaFullInt; + INT_MGMT_DLY = RLT_INT_MGMT_DLY; + INT_HCCA_DLY = RLT_INT_HCCA_DLY; + INT_AC3_DLY = RLT_INT_AC3_DLY; + INT_AC2_DLY = RLT_INT_AC2_DLY; + INT_AC1_DLY = RLT_INT_AC1_DLY; + INT_AC0_DLY = RLT_INT_AC0_DLY; + PreTBTTInt = RLT_PreTBTTInt; + TBTTInt = RLT_TBTTInt; + GPTimeOutInt = RLT_GPTimeOutInt; +#ifdef CARRIER_DETECTION_SUPPORT + RadarInt = RLT_RadarInt; +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + AutoWakeupInt = RLT_AutoWakeupInt; +#endif /* CONFIG_STA_SUPPORT */ + //McuCommand = RLT_McuCommand; + } +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + INT_RX_DATA = RTMP_INT_RX; + TxCoherent = RTMP_TxCoherent; + RxCoherent = RTMP_RxCoherent; + FifoStaFullInt = RTMP_FifoStaFullInt; + INT_MGMT_DLY = RTMP_INT_MGMT_DLY; + INT_HCCA_DLY = RTMP_INT_HCCA_DLY; + INT_AC3_DLY = RTMP_INT_AC3_DLY; + INT_AC2_DLY = RTMP_INT_AC2_DLY; + INT_AC1_DLY = RTMP_INT_AC1_DLY; + INT_AC0_DLY = RTMP_INT_AC0_DLY; + PreTBTTInt = RTMP_PreTBTTInt; + TBTTInt = RTMP_TBTTInt; + GPTimeOutInt = RTMP_GPTimeOutInt; +#ifdef CARRIER_DETECTION_SUPPORT + RadarInt = RTMP_RadarInt; +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + AutoWakeupInt = RTMP_AutoWakeupInt; +#endif /* CONFIG_STA_SUPPORT */ + //McuCommand = RTMP_McuCommand; + } +#endif /* RTMP_MAC */ + +#ifdef INF_VR9_HW_INT_WORKAROUND +redo: +#endif + + pAd->bPCIclkOff = FALSE; + + /* If required spinlock, each ISR has to acquire and release itself. */ + + /* Do nothing if NIC doesn't exist */ + if (IntSource == 0xffffffff) + { + RTMP_SET_FLAG(pAd, (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS)); + return; + } + + if (IntSource & TxCoherent) + { + /* + When the interrupt occurs, it means we kick a register to send + a packet, such as TX_MGMTCTX_IDX, but MAC finds some fields in + the transmit buffer descriptor is not correct, ex: all zeros. + */ + DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n")); + pAd->tx_coherent_counter++; + } + + if (IntSource & RxCoherent) + { + DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n")); + pAd->rx_coherent_counter++; + } + + if (IntSource & FifoStaFullInt) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & FifoStaFullInt) == 0) + { + pAd->fifo_int_counter++; + rt2860_int_disable(pAd, FifoStaFullInt); + RTMP_OS_TASKLET_SCHE(&pObj->fifo_statistic_full_task); + } + pAd->int_pending |= FifoStaFullInt; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource & INT_MGMT_DLY) + { + + #ifdef DMA_BUSY_RESET + pAd->TxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_MGMT_DLY) ==0) + { + rt2860_int_disable(pAd, INT_MGMT_DLY); + RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_task); + } + pAd->int_pending |= INT_MGMT_DLY ; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource & INT_RX_DATA) + { + + #ifdef DMA_BUSY_RESET + pAd->RxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_RX_DATA) == 0) + { +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD_START(); + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_ISR); +#endif /* UAPSD_SUPPORT */ + + pAd->rx_int_counter++; + rt2860_int_disable(pAd, INT_RX_DATA); + RTMP_OS_TASKLET_SCHE(&pObj->rx_done_task); + } + pAd->int_pending |= INT_RX_DATA; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + +#ifdef CONFIG_ANDES_SUPPORT + if (IntSource & INT_RX_CMD) + { + #ifdef DMA_BUSY_RESET + pAd->RxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_RX_CMD) == 0) + { + /* mask INT_R1 */ + rt2860_int_disable(pAd, INT_RX_CMD); + RTMP_OS_TASKLET_SCHE(&pObj->rx1_done_task); + } + pAd->int_pending |= INT_RX_CMD; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } +#endif /* CONFIG_ANDES_SUPPORT */ + + if (IntSource & INT_HCCA_DLY) + { + + #ifdef DMA_BUSY_RESET + pAd->TxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_HCCA_DLY) == 0) + { + pAd->hcca_int_counter++; + rt2860_int_disable(pAd, INT_HCCA_DLY); + RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_task); + } + pAd->int_pending |= INT_HCCA_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource & INT_AC3_DLY) + { + + #ifdef DMA_BUSY_RESET + pAd->TxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_AC3_DLY) == 0) + { + pAd->tx_ac3_int_counter++; + rt2860_int_disable(pAd, INT_AC3_DLY); + RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_task); + } + pAd->int_pending |= INT_AC3_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource & INT_AC2_DLY) + { + + #ifdef DMA_BUSY_RESET + pAd->TxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_AC2_DLY) == 0) + { + pAd->tx_ac2_int_counter++; + rt2860_int_disable(pAd, INT_AC2_DLY); + RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_task); + } + pAd->int_pending |= INT_AC2_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource & INT_AC1_DLY) + { + + #ifdef DMA_BUSY_RESET + pAd->TxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending |= INT_AC1_DLY; + + if ((pAd->int_disable_mask & INT_AC1_DLY) == 0) + { + pAd->tx_ac1_int_counter++; + rt2860_int_disable(pAd, INT_AC1_DLY); + RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_task); + } + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + //if (IntSource & INT_TX_DLY) { +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + if ( (IntSource & INT_TX_DLY) && (IntSource & INT_AC0_DLY) ) { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending |= INT_TX_DLY; + + if ((pAd->int_disable_mask & INT_TX_DLY) == 0) + rt2860_int_disable(pAd, INT_TX_DLY); + + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + } +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + if ( (IntSource & RTMP_INT_AC0_DLY) && (IntSource & INT_AC0_DLY) ) { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending |= RTMP_INT_AC0_DLY; + + if ((pAd->int_disable_mask & RTMP_INT_AC0_DLY) == 0) + rt2860_int_disable(pAd, RTMP_INT_AC0_DLY); + + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + } +#endif /* RTMP_MAC */ + + if (IntSource & INT_AC0_DLY) + { + #ifdef DMA_BUSY_RESET + pAd->TxDMACheckTimes = 0; + #endif /* DMA_BUSY_RESET */ +/* + if (IntSource.word & 0x2) { + u32 reg; + RTMP_IO_READ32(pAd, DELAY_INT_CFG, ®); + printk("IntSource = %08x, DELAY_REG = %08x\n", IntSource.word, reg); + } +*/ + //RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + //pAd->int_pending |= INT_AC0_DLY; + //if ((pAd->int_disable_mask & INT_AC0_DLY) == 0) + //{ + pAd->tx_int_counter++; + rt2860_int_disable(pAd, INT_AC0_DLY); + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task); + //} + //RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource & PreTBTTInt) + RTMPHandlePreTBTTInterrupt(pAd); + + if (IntSource & TBTTInt) + RTMPHandleTBTTInterrupt(pAd); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DFS_SUPPORT + if (IntSource & GPTimeOutInt) + NewTimerCB_Radar(pAd); +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + if ((IntSource & RadarInt)) + { + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + RTMPHandleRadarInterrupt(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT*/ + + } +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (IntSource & AutoWakeupInt) + RTMPHandleTwakeupInterrupt(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef INF_VR9_HW_INT_WORKAROUND + /* + We found the VR9 Demo board provide from Lantiq at 2010.3.8 will miss interrup sometime caused of Rx-Ring Full + and our driver no longer receive any packet after the interrupt missing. + Below patch was recommand by Lantiq for temp workaround. + And shall be remove in next VR9 platform. + */ + IntSource = 0x00000000L; + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource); /* write 1 to clear */ + if (IntSource != 0) + goto redo; +#endif + + return; +} + + +/* +======================================================================== +Routine Description: + PCI command kernel thread. + +Arguments: + *Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +INT RTPCICmdThread( + IN ULONG Context) +{ + RTMP_ADAPTER *pAd; + RTMP_OS_TASK *pTask; + int status; + status = 0; + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + RtmpOSTaskCustomize(pTask); + + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_RUNNING; + NdisReleaseSpinLock(&pAd->CmdQLock); + + while (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_RUNNING) + { + if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + if (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_STOPED) + break; + + if (!pAd->PM_FlgSuspend) + CMDHandler(pAd); + } + + if (!pAd->PM_FlgSuspend) + { /* Clear the CmdQElements. */ + CmdQElmt *pCmdQElmt = NULL; + + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; + while(pAd->CmdQ.size) + { + RTThreadDequeueCmd(&pAd->CmdQ, &pCmdQElmt); + if (pCmdQElmt) + { + if (pCmdQElmt->CmdFromNdis == TRUE) + { + if (pCmdQElmt->buffer != NULL) + os_free_mem(pAd, pCmdQElmt->buffer); + os_free_mem(pAd, (PUCHAR)pCmdQElmt); + } + else + { + if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0)) + os_free_mem(pAd, pCmdQElmt->buffer); + os_free_mem(pAd, (PUCHAR)pCmdQElmt); + } + } + } + + NdisReleaseSpinLock(&pAd->CmdQLock); + } + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + DBGPRINT(RT_DEBUG_TRACE,( "<---RTPCICmdThread\n")); + + RtmpOSTaskNotifyToExit(pTask); + return 0; + +} + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT +/* + ======================================================================== + + Routine Description: + + Arguments: + Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value. + Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1 + + ======================================================================== +*/ +VOID RTMPPCIeLinkCtrlValueRestore( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level) +{ + USHORT PCIePowerSaveLevel, reg16; + USHORT Configuration; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + return; + + /* Check PSControl Configuration */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + return; + + /*3090 will not execute the following codes. */ + /* Check interface : If not PCIe interface, return. */ + + + if (RT3593_DEVICE_ID_CHECK(pObj->DeviceID)) + return; + + +#ifdef RT3590 + if ((pObj->DeviceID == NIC3590_PCIe_DEVICE_ID) + ||(pObj->DeviceID == NIC3591_PCIe_DEVICE_ID) + ||(pObj->DeviceID == NIC3592_PCIe_DEVICE_ID)) + return; +#endif /* RT3390 */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); + PCIePowerSaveLevel = pAd->PCIePowerSaveLevel; + if ((PCIePowerSaveLevel&0xff) == 0xff) + { + DBGPRINT(RT_DEBUG_TRACE,("return \n")); + return; + } + + if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) + { + PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); + if ((Configuration != 0) && + (Configuration != 0xFFFF)) + { + Configuration &= 0xfefc; + /* If call from interface down, restore to orginial setting. */ + if (Level == RESTORE_CLOSE) + { + Configuration |= pAd->HostLnkCtrlConfiguration; + } + else + Configuration |= 0x0; + PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); + DBGPRINT(RT_DEBUG_TRACE, ("Restore PCI host : offset 0x%x = 0x%x\n", pAd->HostLnkCtrlOffset, Configuration)); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Restore PCI host : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n", Configuration)); + } + + if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) + { + PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); + if ((Configuration != 0) && + (Configuration != 0xFFFF)) + { + Configuration &= 0xfefc; + /* If call from interface down, restore to orginial setting. */ + if (Level == RESTORE_CLOSE) + Configuration |= pAd->RLnkCtrlConfiguration; + else + Configuration |= 0x0; + PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); + DBGPRINT(RT_DEBUG_TRACE, ("Restore Ralink : offset 0x%x = 0x%x\n", pAd->RLnkCtrlOffset, Configuration)); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Restore Ralink : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n", Configuration)); + } + + DBGPRINT(RT_DEBUG_TRACE,("%s <===\n", __FUNCTION__)); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value. + Because now frequently set our device to mode 1 or mode 3 will cause problem. + + ======================================================================== +*/ +VOID RTMPPCIeLinkCtrlSetting( + IN PRTMP_ADAPTER pAd, + IN USHORT Max) +{ + USHORT PCIePowerSaveLevel, reg16; + USHORT Configuration; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + return; + + /* Check PSControl Configuration */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + return; + + /* Check interface : If not PCIe interface, return. */ + /*Block 3090 to enter the following function */ + + + if (RT3593_DEVICE_ID_CHECK(pObj->DeviceID)) + return; + + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) + { + DBGPRINT(RT_DEBUG_INFO, ("RTMPPCIePowerLinkCtrl return on fRTMP_PS_CAN_GO_SLEEP flag\n")); + return; + } + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + PCIePowerSaveLevel = pAd->PCIePowerSaveLevel; + if ((PCIePowerSaveLevel&0xff) == 0xff) + { + DBGPRINT(RT_DEBUG_TRACE,("return \n")); + return; + } + PCIePowerSaveLevel = PCIePowerSaveLevel>>6; + + /* Skip non-exist deice right away */ + if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) + { + PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); + switch (PCIePowerSaveLevel) + { + case 0: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 */ + Configuration &= 0xfefc; + break; + case 1: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 */ + Configuration &= 0xfefc; + Configuration |= 0x1; + break; + case 2: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */ + Configuration &= 0xfefc; + Configuration |= 0x3; + break; + case 3: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 */ + Configuration &= 0xfefc; + Configuration |= 0x103; + break; + } + PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); + DBGPRINT(RT_DEBUG_TRACE, ("Write PCI host offset 0x%x = 0x%x\n", pAd->HostLnkCtrlOffset, Configuration)); + } + + if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) + { + /* first 2892 chip not allow to frequently set mode 3. will cause hang problem. */ + if (PCIePowerSaveLevel > Max) + PCIePowerSaveLevel = Max; + + PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); + Configuration |= 0x100; + PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); + DBGPRINT(RT_DEBUG_TRACE, ("Write Ralink device : offset 0x%x = 0x%x\n", pAd->RLnkCtrlOffset, Configuration)); + } + + DBGPRINT(RT_DEBUG_TRACE,("RTMPPCIePowerLinkCtrl <==============\n")); +} +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +/*************************************************************************** + * + * PCIe device initialization related procedures. + * + ***************************************************************************/ +VOID RTMPInitPCIeDevice( + IN RT_CMD_PCIE_INIT *pConfig, + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + VOID *pci_dev = pConfig->pPciDev; + USHORT device_id = 0; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + pci_read_config_word(pci_dev, pConfig->ConfigDeviceID, &device_id); + pObj->DeviceID = device_id; + DBGPRINT(RT_DEBUG_OFF, ("device_id =0x%x\n", device_id)); + + +#if defined(RT65xx) || defined(MT7601) +#ifdef RT8592 + if (device_id == NIC8592_PCIe_DEVICE_ID) { + UINT32 value; + pAd->infType = RTMP_DEV_INF_PCIE; + RTMP_IO_READ32(pAd, 0x00, &value); + pAd->ChipID = value; + rt85592_wlan_chip_onoff(pAd, TRUE, TRUE); + } +#endif /* RT8592 */ + + if (device_id == NIC7650_PCIe_DEVICE_ID || + device_id == NIC7630_PCIe_DEVICE_ID || + device_id == NIC7610_PCIe_DEVICE_ID || + (device_id == NIC7601_PCIe_DEVICE_ID) || + device_id == NIC7662_PCIe_DEVICE_ID || + device_id == NIC7632_PCIe_DEVICE_ID || + device_id == NIC7612_PCIe_DEVICE_ID || + device_id == NIC7602_PCIe_DEVICE_ID) + { + UINT32 value; + pAd->infType = RTMP_DEV_INF_PCIE; + RTMP_IO_READ32(pAd, 0x00, &value); + pAd->ChipID = value; + + if (MT_REV_LT(pAd, MT7612E, REV_MT76x2E3)) { + RTMP_IO_READ32(pAd, 0x70c, &value); + value |= (1 << 8); + value |= (1 << 9); + RTMP_IO_WRITE32(pAd, 0x70c, value); + mdelay(300); + } + + rlt_wlan_chip_onoff(pAd, TRUE, TRUE); + +#ifdef MT76x2 + if (IS_MT76x2(pAd)) + mt76x2_pwrOn(pAd); +#endif /* MT76x2 */ + } +#endif /* defined(RT65xx) || defined(MT7601) */ + + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE); + + if ((device_id == NIC2860_PCIe_DEVICE_ID) || + (device_id == NIC2790_PCIe_DEVICE_ID) || + (device_id == VEN_AWT_PCIe_DEVICE_ID) || + (device_id == NIC3090_PCIe_DEVICE_ID) || + (device_id == NIC3091_PCIe_DEVICE_ID) || + (device_id == NIC3092_PCIe_DEVICE_ID) || + (device_id == NIC3390_PCIe_DEVICE_ID) || + (device_id == NIC3593_PCI_OR_PCIe_DEVICE_ID)|| + (device_id == NIC3592_PCIe_DEVICE_ID) || + (device_id == NIC5390_PCIe_DEVICE_ID) || + (device_id == NIC539F_PCIe_DEVICE_ID) || + (device_id == NIC5392_PCIe_DEVICE_ID) || + (device_id == NIC5360_PCI_DEVICE_ID) || + (device_id == NIC5362_PCI_DEVICE_ID) || + (device_id == NIC5392_PCIe_DEVICE_ID) || + (device_id == NIC5362_PCI_DEVICE_ID) || + (device_id == NIC5592_PCIe_DEVICE_ID)) + { + UINT32 MacCsr0 = 0; + WaitForAsicReady(pAd); + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + +#ifdef CONFIG_STA_SUPPORT + pAd->chipCap.HW_PCIE_PS_SUPPORT=FALSE; + + if ((device_id == NIC3090_PCIe_DEVICE_ID) || + (device_id == NIC3091_PCIe_DEVICE_ID) || + (device_id == NIC3092_PCIe_DEVICE_ID) || + (device_id == NIC3390_PCIe_DEVICE_ID)|| + RT3593_DEVICE_ID_CHECK(device_id)) + { + /*Support HW new PCIe power-saving. */ + DBGPRINT(RT_DEBUG_TRACE, ("RTMPInitPCIeDevice::STA Support HW PCIe Power Saving\n")); + pAd->chipCap.HW_PCIE_PS_SUPPORT=TRUE; + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Support advanced power save after 2892/2790. */ + /* MAC version at offset 0x1000 is 0x2872XXXX/0x2870XXXX(PCIe, USB, SDIO). */ + if ((MacCsr0 & 0xffff0000) != 0x28600000) + { +#ifdef PCIE_PS_SUPPORT + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE); +#endif /* PCIE_PS_SUPPORT */ + RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_PCIE); + return; + } + + pAd->infType = RTMP_DEV_INF_PCIE; + } + + RtmpRaDevCtrlInit(pAd, pAd->infType); +} + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT +VOID RTMPInitPCIeLinkCtrlValue( + IN PRTMP_ADAPTER pAd) +{ + INT pos; + USHORT reg16, data2, PCIePowerSaveLevel, Configuration; + UINT32 MacValue; + BOOLEAN bFindIntel = FALSE; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not PCIe device.\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); + /* Init EEPROM, and save settings */ +#ifdef RT8592 + if (IS_RT8592(pAd)) { + // TODO: shiang-6590, what shall we do for this?? + } else +#endif /* RT8592 */ +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + ; + } else +#endif /* MT76x0 */ + if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd) || + IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd) || IS_RT5592(pAd))) + { + RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel); + pAd->PCIePowerSaveLevel = PCIePowerSaveLevel & 0xff; + pAd->LnkCtrlBitMask = 0; + if ((PCIePowerSaveLevel&0xff) == 0xff) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE); + DBGPRINT(RT_DEBUG_TRACE, ("====> PCIePowerSaveLevel = 0x%x.\n", PCIePowerSaveLevel)); + return; + } + else + { + PCIePowerSaveLevel &= 0x3; + RT28xx_EEPROM_READ16(pAd, 0x24, data2); + + if( !(((data2&0xff00) == 0x9200) && ((data2&0x80) !=0)) ) + { + if (PCIePowerSaveLevel > 1 ) + PCIePowerSaveLevel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("====> Write 0x83 = 0x%x.\n", PCIePowerSaveLevel)); + AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, 0x00, FALSE); + RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel); + PCIePowerSaveLevel &= 0xff; + PCIePowerSaveLevel = PCIePowerSaveLevel >> 6; + switch(PCIePowerSaveLevel) + { + case 0: /* Only support L0 */ + pAd->LnkCtrlBitMask = 0; + break; + case 1: /* Only enable L0s */ + pAd->LnkCtrlBitMask = 1; + break; + case 2: /* enable L1, L0s */ + pAd->LnkCtrlBitMask = 3; + break; + case 3: /* sync with host clk and enable L1, L0s */ + pAd->LnkCtrlBitMask = 0x103; + break; + } + RT28xx_EEPROM_READ16(pAd, 0x24, data2); + if ((PCIePowerSaveLevel&0xff) != 0xff) + { + PCIePowerSaveLevel &= 0x3; + + if( !(((data2&0xff00) == 0x9200) && ((data2&0x80) !=0)) ) + { + if (PCIePowerSaveLevel > 1 ) + PCIePowerSaveLevel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("====> rt28xx Write 0x83 Command = 0x%x.\n", PCIePowerSaveLevel)); + printk("\n\n\n%s:%d\n",__FUNCTION__,__LINE__); + + AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, 0x00); + } + DBGPRINT(RT_DEBUG_TRACE, ("====> LnkCtrlBitMask = 0x%x.\n", pAd->LnkCtrlBitMask)); + } + } + else if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd) || + IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd) || + IS_RT5592(pAd)) + { + UCHAR LinkCtrlSetting = 0; + + /* Check 3090E special setting chip. */ + RT28xx_EEPROM_READ16(pAd, 0x24, data2); + if ((data2 == 0x9280) && ((pAd->MACVersion&0xffff) == 0x0211)) + { + pAd->b3090ESpecialChip = TRUE; + DBGPRINT_RAW(RT_DEBUG_ERROR,("Special 3090E chip \n")); + } + + RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue); + /*enable WAKE_PCIE function, which forces to enable PCIE clock when mpu interrupt asserting. */ + /*Force PCIE 125MHz CLK to toggle */ + MacValue |= 0x402; + RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR,(" AUX_CTRL = 0x%32x\n", MacValue)); + + + + /* for RT30xx F and after, PCIe infterface, and for power solution 3 */ + if ((IS_VERSION_AFTER_F(pAd)) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode >= 2) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode <= 3)) + { + RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR,(" Read AUX_CTRL = 0x%x\n", MacValue)); + /* turn on bit 12. */ + /*enable 32KHz clock mode for power saving */ + MacValue |= 0x1000; + if (MacValue != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR,(" Write AUX_CTRL = 0x%x\n", MacValue)); + /* 1. if use PCIePowerSetting is 2 or 3, need to program OSC_CTRL to 0x3ff11. */ + MacValue = 0x3ff11; + RTMP_IO_WRITE32(pAd, OSC_CTRL, MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR,(" OSC_CTRL = 0x%x\n", MacValue)); + /* 2. Write PCI register Clk ref bit */ + RTMPrt3xSetPCIePowerLinkCtrl(pAd); + } + else + { + /* Error read Aux_Ctrl value. Force to use solution 1 */ + DBGPRINT(RT_DEBUG_ERROR,(" Error Value in AUX_CTRL = 0x%x\n", MacValue)); + pAd->StaCfg.PSControl.field.rt30xxPowerMode = 1; + DBGPRINT(RT_DEBUG_ERROR,(" Force to use power solution1 \n")); + } + } + /* 1. read setting from inf file. */ + + PCIePowerSaveLevel = (USHORT)pAd->StaCfg.PSControl.field.rt30xxPowerMode; + DBGPRINT(RT_DEBUG_ERROR, ("====> rt30xx Read PowerLevelMode = 0x%x.\n", PCIePowerSaveLevel)); + /* 2. Check EnableNewPS. */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + PCIePowerSaveLevel = 1; + + if (IS_VERSION_BEFORE_F(pAd) && (pAd->b3090ESpecialChip == FALSE)) + { + /* Chip Version E only allow 1, So force set 1. */ + PCIePowerSaveLevel &= 0x1; + pAd->PCIePowerSaveLevel = (USHORT)PCIePowerSaveLevel; + DBGPRINT(RT_DEBUG_TRACE, ("====> rt30xx E Write 0x83 Command = 0x%x.\n", PCIePowerSaveLevel)); + + AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, 0x00, FALSE); + } + else + { + /* Chip Version F and after only allow 1 or 2 or 3. This might be modified after new chip version come out. */ + if (!((PCIePowerSaveLevel == 1) || (PCIePowerSaveLevel == 3))) + PCIePowerSaveLevel = 1; + DBGPRINT(RT_DEBUG_ERROR, ("====> rt30xx F Write 0x83 Command = 0x%x.\n", PCIePowerSaveLevel)); + pAd->PCIePowerSaveLevel = (USHORT)PCIePowerSaveLevel; + /* for 3090F , we need to add high-byte arg for 0x83 command to indicate the link control setting in */ + /* PCI Configuration Space. Because firmware can't read PCI Configuration Space */ + if ((pAd->Rt3xxRalinkLinkCtrl & 0x2) && (pAd->Rt3xxHostLinkCtrl & 0x2)) + { + LinkCtrlSetting = 1; + } + DBGPRINT(RT_DEBUG_TRACE, ("====> rt30xxF LinkCtrlSetting = 0x%x.\n", LinkCtrlSetting)); + AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, LinkCtrlSetting, FALSE); + } + + } + + /* Find Ralink PCIe Device's Express Capability Offset */ + pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) + { + /* Ralink PCIe Device's Link Control Register Offset */ + pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, Configuration)); + pAd->RLnkCtrlConfiguration = (Configuration & 0x103); + Configuration &= 0xfefc; + Configuration |= (0x0); + + pObj->parent_pci_dev = RTMPFindHostPCIDev(pObj->pci_dev); + if (pObj->parent_pci_dev) + { + USHORT vendor_id; + + pci_read_config_word(pObj->parent_pci_dev, RTMP_OS_PCI_VENDOR_ID, &vendor_id); + vendor_id = le2cpu16(vendor_id); + if (vendor_id == PCIBUS_INTEL_VENDOR) + { + bFindIntel = TRUE; + RTMP_SET_PSFLAG(pAd, fRTMP_PS_TOGGLE_L1); + } + /* Find PCI-to-PCI Bridge Express Capability Offset */ + pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) + { + BOOLEAN bChange = FALSE; + /* PCI-to-PCI Bridge Link Control Register Offset */ + pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + pci_read_config_word(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, ("Read (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n", + pAd->HostLnkCtrlOffset, Configuration)); + pAd->HostLnkCtrlConfiguration = (Configuration & 0x103); + Configuration &= 0xfefc; + Configuration |= (0x0); + + switch (pObj->DeviceID) + { + + default: + break; + } + + if (bChange) + { + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, reg16); + DBGPRINT(RT_DEBUG_TRACE, ("Write (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n", + pAd->HostLnkCtrlOffset, Configuration)); + } + } + else + { + pAd->HostLnkCtrlOffset = 0; + DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot find PCI-to-PCI Bridge PCI Express Capability!\n", __FUNCTION__)); + } + } + } + else + { + pAd->RLnkCtrlOffset = 0; + pAd->HostLnkCtrlOffset = 0; + DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot find Ralink PCIe Device's PCI Express Capability!\n", __FUNCTION__)); + } + + if (bFindIntel == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Doesn't find Intel PCI host controller. \n")); + /* Doesn't switch L0, L1, So set PCIePowerSaveLevel to 0xff */ + pAd->PCIePowerSaveLevel = 0xff; + /* RT3090 will no co-existence with RT3593 */ + if ((pAd->RLnkCtrlOffset != 0)&&(pAd->chipCap.HW_PCIE_PS_SUPPORT==TRUE)) + { + pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, ("Read (Ralink 30xx PCIe Link Control Register) offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, Configuration)); + pAd->RLnkCtrlConfiguration = (Configuration & 0x103); + Configuration &= 0xfefc; + Configuration |= (0x0); + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, reg16); + DBGPRINT(RT_DEBUG_TRACE, ("Write (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", + pos + PCI_EXP_LNKCTL, Configuration)); + } + } +} + +/* + ======================================================================== + + Routine Description: + 1. Write a PCI register for rt30xx power solution 3 + + ======================================================================== +*/ +VOID RTMPrt3xSetPCIePowerLinkCtrl( + IN PRTMP_ADAPTER pAd) +{ + + ULONG HostConfiguration = 0; + ULONG Configuration; +/* + ULONG Vendor; + ULONG offset; +*/ + POS_COOKIE pObj; + INT pos; + USHORT reg16; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_INFO, ("RTMPrt3xSetPCIePowerLinkCtrl.===> %x\n", (UINT)pAd->StaCfg.PSControl.word)); + + /* Check PSControl Configuration */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + return; + pObj->parent_pci_dev = RTMPFindHostPCIDev(pObj->pci_dev); + if (pObj->parent_pci_dev) + { + + /* Find PCI-to-PCI Bridge Express Capability Offset */ + pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) + { + pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + } + /* If configurared to turn on L1. */ + HostConfiguration = 0; + if (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("Enter,PSM : Force ASPM \n")); + + /* Skip non-exist deice right away */ + if ((pAd->HostLnkCtrlOffset != 0)) + { + PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, HostConfiguration); + /* Prepare Configuration to write to Host */ + HostConfiguration |= 0x3; + PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, HostConfiguration); + pAd->Rt3xxHostLinkCtrl = HostConfiguration; + /* Because in rt30xxForceASPMTest Mode, Force turn on L0s, L1. */ + /* Fix HostConfiguration bit0:1 = 0x3 for later use. */ + HostConfiguration = 0x3; + DBGPRINT(RT_DEBUG_TRACE, ("PSM : Force ASPM : Host device L1/L0s Value = 0x%x\n",(UINT)HostConfiguration)); + } + } + else if (pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1) + { + + /* Skip non-exist deice right away */ + if ((pAd->HostLnkCtrlOffset != 0)) + { + PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, HostConfiguration); + pAd->Rt3xxHostLinkCtrl = HostConfiguration; + HostConfiguration &= 0x3; + DBGPRINT(RT_DEBUG_TRACE, ("PSM : Follow Host ASPM : Host device L1/L0s Value = 0x%x\n", (UINT)HostConfiguration)); + } + } + } + /* Prepare to write Ralink setting. */ + /* Find Ralink PCIe Device's Express Capability Offset */ + pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) + { + /* Ralink PCIe Device's Link Control Register Offset */ + pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, (UINT)Configuration)); + Configuration |= 0x100; + if ((pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1) + || (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1)) + { + switch(HostConfiguration) + { + case 0: + Configuration &= 0xffffffc; + break; + case 1: + Configuration &= 0xffffffc; + Configuration |= 0x1; + break; + case 2: + Configuration &= 0xffffffc; + Configuration |= 0x2; + break; + case 3: + Configuration |= 0x3; + break; + } + } + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, reg16); + pAd->Rt3xxRalinkLinkCtrl = Configuration; + DBGPRINT(RT_DEBUG_TRACE, ("PSM :Write Ralink device L1/L0s Value = 0x%x\n", (UINT)Configuration)); + } + DBGPRINT(RT_DEBUG_INFO,("PSM :RTMPrt3xSetPCIePowerLinkCtrl <==============\n")); + +} +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#endif /* RTMP_MAC_PCI */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_rbus_pci_util.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_rbus_pci_util.c new file mode 100644 index 000000000..1beddc9de --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_rbus_pci_util.c @@ -0,0 +1,504 @@ +/**************************************************************************** + + Module Name: + rt_rbus_pci_util.c + + Abstract: + Any utility is used in UTIL module for PCI/RBUS function. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" + + +#ifdef RTMP_MAC_PCI + +/* Function for Tx/Rx/Mgmt Desc Memory allocation. */ +void RtmpAllocDescBuf( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT VOID **VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS phy_addr) +{ + dma_addr_t DmaAddr = (dma_addr_t)(*phy_addr); + + *VirtualAddress = (PVOID)pci_alloc_consistent(pPciDev,sizeof(char)*Length, &DmaAddr); + *phy_addr = (NDIS_PHYSICAL_ADDRESS)DmaAddr; +} + + +/* Function for free allocated Desc Memory. */ +void RtmpFreeDescBuf( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN VOID *VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS phy_addr) +{ + dma_addr_t DmaAddr = (dma_addr_t)(phy_addr); + + pci_free_consistent(pPciDev, Length, VirtualAddress, DmaAddr); +} + + +/* Function for TxData DMA Memory allocation. */ +void RTMP_AllocateFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS phy_addr) +{ + dma_addr_t DmaAddr = (dma_addr_t)(*phy_addr); + + *VirtualAddress = (PVOID)pci_alloc_consistent(pPciDev,sizeof(char)*Length, &DmaAddr); + *phy_addr = (NDIS_PHYSICAL_ADDRESS)DmaAddr; +} + + +void RTMP_FreeFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + IN VOID *VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS phy_addr) +{ + dma_addr_t DmaAddr = (dma_addr_t)(phy_addr); + pci_free_consistent(pPciDev, Length, VirtualAddress, DmaAddr); +} + + +/* + * FUNCTION: Allocate a packet buffer for DMA + * ARGUMENTS: + * AdapterHandle: AdapterHandle + * Length: Number of bytes to allocate + * Cached: Whether or not the memory can be cached + * VirtualAddress: Pointer to memory is returned here + * phy_addr: Physical address corresponding to virtual address + * Notes: + * Cached is ignored: always cached memory + */ +PNDIS_PACKET RTMP_AllocateRxPacketBuffer( + IN VOID *pReserved, + IN VOID *pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT VOID **VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS phy_addr) +{ + struct sk_buff *pkt; + +/* pkt = dev_alloc_skb(Length); */ + DEV_ALLOC_SKB(pReserved, pkt, Length); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); + } + + if (pkt) { + *VirtualAddress = (PVOID) pkt->data; + *phy_addr = PCI_MAP_SINGLE_DEV(pPciDev, *VirtualAddress, Length, -1, RTMP_PCI_DMA_FROMDEVICE); + } else { + *VirtualAddress = (PVOID) NULL; + *phy_addr = (NDIS_PHYSICAL_ADDRESS) 0; + } + + return (PNDIS_PACKET) pkt; +} + + +/* + * invaild or writeback cache + * and convert virtual address to physical address + */ +ra_dma_addr_t linux_pci_map_single(void *pPciDev, void *ptr, size_t size, int sd_idx, int direction) +{ + if (direction == RTMP_PCI_DMA_TODEVICE) + direction = PCI_DMA_TODEVICE; + + if (direction == RTMP_PCI_DMA_FROMDEVICE) + direction = PCI_DMA_FROMDEVICE; + + /* + ------ Porting Information ------ + > For Tx Alloc: + mgmt packets => sd_idx = 0 + SwIdx: pAd->MgmtRing.TxCpuIdx + pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa; + + data packets => sd_idx = 1 + TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx + QueIdx: pTxBlk->QueIdx + pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa; + + > For Rx Alloc: + sd_idx = -1 + */ + +/* pAd = (PRTMP_ADAPTER)handle; */ +/* pObj = (POS_COOKIE)pAd->OS_Cookie; */ + + { + return (ra_dma_addr_t)pci_map_single(pPciDev, ptr, size, direction); + } + +} + +void linux_pci_unmap_single(void *pPciDev, ra_dma_addr_t radma_addr, size_t size, int direction) +{ + dma_addr_t DmaAddr = (dma_addr_t)radma_addr; + + + if (direction == RTMP_PCI_DMA_TODEVICE) + direction = PCI_DMA_TODEVICE; + + if (direction == RTMP_PCI_DMA_FROMDEVICE) + direction = PCI_DMA_FROMDEVICE; + + if (size > 0) + pci_unmap_single(pPciDev, DmaAddr, size, direction); + +} + + +#ifdef RTMP_PCI_SUPPORT +VOID *RTMPFindHostPCIDev(VOID *pPciDevSrc) +{ + struct pci_dev *pci_dev = (struct pci_dev *)pPciDevSrc; + USHORT reg16; + UCHAR reg8; + UINT DevFn; + PPCI_DEV pPci_dev; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); + + if (pci_dev->bus->parent) + { + for (DevFn = 0; DevFn < 255; DevFn++) + { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + pPci_dev = pci_get_slot(pci_dev->bus->parent, DevFn); +#else + pPci_dev = pci_find_slot(pci_dev->bus->parent->number, DevFn); +#endif + if (pPci_dev) + { + pci_read_config_word(pPci_dev, PCI_CLASS_DEVICE, ®16); + reg16 = le2cpu16(reg16); + pci_read_config_byte(pPci_dev, PCI_CB_CARD_BUS, ®8); + if ((reg16 == PCI_CLASS_BRIDGE_PCI) && + (reg8 == pci_dev->bus->number)) + return pPci_dev; + } + } + } + return NULL; +} +#endif /* RTMP_PCI_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Write 32-bit to a register. + +Arguments: + pAd - WLAN control block pointer + Offset - Register offset + Value - 32-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_PCI_Writel(ULONG Value, VOID *pAddr) +{ + writel(Value, pAddr); +} + + +/* +======================================================================== +Routine Description: + Write 16-bit to a register. + +Arguments: + pAd - WLAN control block pointer + Offset - Register offset + Value - 32-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_PCI_Writew(ULONG Value, VOID *pAddr) +{ + writew(Value, pAddr); +} + + +/* +======================================================================== +Routine Description: + Write 8-bit to a register. + +Arguments: + pAd - WLAN control block pointer + Offset - Register offset + Value - 32-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_PCI_Writeb(ULONG Value, VOID *pAddr) +{ + writeb(Value, pAddr); +} + + +/* +======================================================================== +Routine Description: + Read 32-bit from a register. + +Arguments: + pAd - WLAN control block pointer + Offset - Register offset + Value - 32-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +ULONG RTMP_PCI_Readl(VOID *pAddr) +{ + return readl(pAddr); +} + + +/* +======================================================================== +Routine Description: + Read 16-bit from a register. + +Arguments: + pAd - WLAN control block pointer + Offset - Register offset + Value - 16-bit value + +Return Value: + None + +Note: + No use. +======================================================================== +*/ +ULONG RTMP_PCI_Readw(VOID *pAddr) +{ + return readw(pAddr); +} + + +/* +======================================================================== +Routine Description: + Read 8-bit from a register. + +Arguments: + pAd - WLAN control block pointer + Offset - Register offset + Value - 16-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +ULONG RTMP_PCI_Readb(VOID *pAddr) +{ + return readb(pAddr); +} + + +/* +======================================================================== +Routine Description: + Read 16-bit from the PCI config space. + +Arguments: + pDev - PCI device + Offset - Register offset + Value - 16-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpOsPciConfigReadWord(VOID *pDev, UINT32 Offset, UINT16 *pValue) +{ + return pci_read_config_word((struct pci_dev *)pDev, Offset, pValue); +} + + +/* +======================================================================== +Routine Description: + Write 16-bit to the PCI config space. + +Arguments: + pDev - PCI device + Offset - Register offset + Value - 16-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpOsPciConfigWriteWord(VOID *pDev, UINT32 Offset, UINT16 Value) +{ + return pci_write_config_word((struct pci_dev *)pDev, Offset, Value); +} + + +/* +======================================================================== +Routine Description: + Read 32-bit from the PCI config space. + +Arguments: + pDev - PCI device + Offset - Register offset + Value - 32-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpOsPciConfigReadDWord(VOID *pDev, UINT32 Offset, UINT32 *pValue) +{ + return pci_read_config_dword((struct pci_dev *)pDev, Offset, pValue); +} + + +/* +======================================================================== +Routine Description: + Write 32-bit to the PCI config space. + +Arguments: + pDev - PCI device + Offset - Register offset + Value - 32-bit value + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpOsPciConfigWriteDWord(VOID *pDev, UINT32 Offset, UINT32 Value) +{ + return pci_write_config_dword((struct pci_dev *)pDev, Offset, Value); +} + + +/* +======================================================================== +Routine Description: + Query for devices' capabilities. + +Arguments: + pDev - PCI device + Cap - Capability code + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpOsPciFindCapability(VOID *pDev, INT Cap) +{ + return pci_find_capability(pDev, Cap); +} + + +#ifdef RTMP_PCI_SUPPORT +/* +======================================================================== +Routine Description: + Enable MSI function for PCI. + +Arguments: + pDev - PCI device + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpOsPciMsiEnable(VOID *pDev) +{ +#ifdef PCI_MSI_SUPPORT + return pci_enable_msi(pDev); +#else + return 0; +#endif +} + + +/* +======================================================================== +Routine Description: + Disable MSI function for PCI. + +Arguments: + pDev - PCI device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPciMsiDisable(VOID *pDev) +{ +#ifdef PCI_MSI_SUPPORT + pci_disable_msi(pDev); +#endif +} +#endif /* RTMP_PCI_SUPPORT */ + +#endif /* RTMP_MAC_PCI */ + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_symb.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_symb.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_symb.c rename to package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/rt_symb.c diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/sta_ioctl.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/sta_ioctl.c new file mode 100644 index 000000000..a9f9f4666 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/sta_ioctl.c @@ -0,0 +1,2833 @@ +/* + *************************************************************************** + * 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: + sta_ioctl.c + + Abstract: + IOCTL related subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Rory Chen 01-03-2003 created + Rory Chen 02-14-2005 modify to support RT61 +*/ + +#define RTMP_MODULE_OS + +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +/*#include "rt_config.h" */ + +#ifdef DBG +extern ULONG RTDebugLevel; +extern ULONG RTDebugFunc; +#endif + +#define NR_WEP_KEYS 4 +#define WEP_SMALL_KEY_LEN (40/8) +#define WEP_LARGE_KEY_LEN (104/8) + +#define GROUP_KEY_NO 4 + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_A, _B, _C, _D, _E) +#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_A, _B, _C, _D, _E) +#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_A, _B, _C, _D, _E, _F) +#else +#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_B, _C, _D, _E) +#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_B, _C, _D, _E) +#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_B, _C, _D, _E, _F) +#endif + +extern UCHAR CipherWpa2Template[]; + +typedef struct GNU_PACKED _RT_VERSION_INFO{ + UCHAR DriverVersionW; + UCHAR DriverVersionX; + UCHAR DriverVersionY; + UCHAR DriverVersionZ; + UINT DriverBuildYear; + UINT DriverBuildMonth; + UINT DriverBuildDay; +} RT_VERSION_INFO, *PRT_VERSION_INFO; + +struct iw_priv_args privtab[] = { +{ RTPRIV_IOCTL_SET, + IW_PRIV_TYPE_CHAR | 1024, 0, + "set"}, + +{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + ""}, +/* --- sub-ioctls definitions --- */ +#ifdef MAT_SUPPORT + { SHOW_IPV4_MAT_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "ipv4_matinfo" }, + { SHOW_IPV6_MAT_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "ipv6_matinfo" }, + { SHOW_ETH_CLONE_MAC, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "cloneMAC" }, +#endif /* MAT_SUPPORT */ + { SHOW_CONN_STATUS, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" }, + { SHOW_DRVIER_VERION, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" }, + { SHOW_BA_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" }, + { SHOW_DESC_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" }, + { RAIO_OFF, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" }, + { RAIO_ON, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" }, +#ifdef QOS_DLS_SUPPORT + { SHOW_DLS_ENTRY_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" }, +#endif /* QOS_DLS_SUPPORT */ + { SHOW_CFG_VALUE, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" }, + { SHOW_ADHOC_ENTRY_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "adhocEntry" }, +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + { SHOW_TDLS_ENTRY_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "tdlsentryinfo" }, +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + {SHOW_DEV_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "devinfo"}, + {SHOW_STA_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "stainfo"}, + {SHOW_TR_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "trinfo"}, + {SHOW_SYS_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sysinfo"}, + {SHOW_PWR_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "pwrinfo"}, + {SHOW_DIAGNOSE_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "diaginfo"}, +/* --- sub-ioctls relations --- */ + +#ifdef DBG +{ RTPRIV_IOCTL_BBP, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "bbp"}, +{ RTPRIV_IOCTL_MAC, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "mac"}, +#ifdef RTMP_RF_RW_SUPPORT +{ RTPRIV_IOCTL_RF, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "rf"}, +#endif /* RTMP_RF_RW_SUPPORT */ +{ RTPRIV_IOCTL_E2P, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "e2p"}, +#endif /* DBG */ + +{ RTPRIV_IOCTL_STATISTICS, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "stat"}, +{ RTPRIV_IOCTL_GSITESURVEY, + 0, IW_PRIV_TYPE_CHAR | 1024, + "get_site_survey"}, + +#ifdef WSC_STA_SUPPORT +{ RTPRIV_IOCTL_SET_WSC_PROFILE_U32_ITEM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, +{ RTPRIV_IOCTL_SET_WSC_PROFILE_U32_ITEM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "" }, +{ RTPRIV_IOCTL_SET_WSC_PROFILE_STRING_ITEM, + IW_PRIV_TYPE_CHAR | 128, 0, "" }, +/* --- sub-ioctls definitions --- */ + { WSC_CREDENTIAL_COUNT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wsc_cred_count" }, + { WSC_CREDENTIAL_SSID, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_cred_ssid" }, + { WSC_CREDENTIAL_AUTH_MODE, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_cred_auth" }, + { WSC_CREDENTIAL_ENCR_TYPE, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_cred_encr" }, + { WSC_CREDENTIAL_KEY_INDEX, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_cred_keyIdx" }, + { WSC_CREDENTIAL_KEY, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_cred_key" }, + { WSC_CREDENTIAL_MAC, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_cred_mac" }, + { WSC_SET_DRIVER_CONNECT_BY_CREDENTIAL_IDX, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wsc_conn_by_idx" }, + { WSC_SET_DRIVER_AUTO_CONNECT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wsc_auto_conn" }, + { WSC_SET_CONF_MODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wsc_conf_mode" }, + { WSC_SET_MODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wsc_mode" }, + { WSC_SET_PIN, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_pin" }, + { WSC_SET_SSID, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_ssid" }, + { WSC_SET_BSSID, + IW_PRIV_TYPE_CHAR | 128, 0, "wsc_bssid" }, + { WSC_START, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "wsc_start" }, + { WSC_STOP, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "wsc_stop" }, + { WSC_GEN_PIN_CODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "wsc_gen_pincode" }, + { WSC_AP_BAND, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wsc_ap_band" }, +/* --- sub-ioctls relations --- */ +#endif /* WSC_STA_SUPPORT */ +}; + + + +/* +This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function +*/ +int rt_ioctl_giwname(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + strncpy(name, "Ralink STA", IFNAMSIZ); + return 0; +} + +int rt_ioctl_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + VOID *pAd = NULL; +/* int chan = -1; */ + RT_CMD_STA_IOCTL_FREQ IoctlFreq, *pIoctlFreq = &IoctlFreq; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + if (freq->e > 1) + return -EINVAL; + + pIoctlFreq->m = freq->m; + pIoctlFreq->e = freq->e; + + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWFREQ, 0, + pIoctlFreq, 0, RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + return -EINVAL; + + return 0; +} + + +int rt_ioctl_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + VOID *pAd = NULL; + ULONG m = 2412000; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWFREQ, 0, + &m, RT_DEV_PRIV_FLAGS_GET(dev), RT_DEV_PRIV_FLAGS_GET(dev)); + + freq->m = m * 100; + freq->e = 1; + freq->i = 0; + + return 0; +} + + +int rt_ioctl_siwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + VOID *pAd = NULL; + LONG Mode; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (*mode == IW_MODE_ADHOC) + Mode = RTMP_CMD_STA_MODE_ADHOC; + else if (*mode == IW_MODE_INFRA) + Mode = RTMP_CMD_STA_MODE_INFRA; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + else if (*mode == IW_MODE_MONITOR) + Mode = RTMP_CMD_STA_MODE_MONITOR; +#endif /* LINUX_VERSION_CODE */ + else + { + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode)); + return -EINVAL; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWMODE, 0, + NULL, Mode, RT_DEV_PRIV_FLAGS_GET(dev)); + return 0; +} + + +int rt_ioctl_giwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + VOID *pAd = NULL; + ULONG Mode; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + return -ENETDOWN; + + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWMODE, 0, + &Mode, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + if (Mode == RTMP_CMD_STA_MODE_ADHOC) + *mode = IW_MODE_ADHOC; + else if (Mode == RTMP_CMD_STA_MODE_INFRA) + *mode = IW_MODE_INFRA; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + else if (Mode == RTMP_CMD_STA_MODE_MONITOR) { + *mode = IW_MODE_MONITOR; + +#define RADIOTAP_TYPE 0 +#define PRISM_TYPE 1 + + if (get_sniffer_mode(dev) == RADIOTAP_TYPE) + dev->type = ARPHRD_IEEE80211_RADIOTAP; + + if (get_sniffer_mode(dev) == PRISM_TYPE) + dev->type = ARPHRD_IEEE80211_PRISM; + + } +#endif /* LINUX_VERSION_CODE */ + else + *mode = IW_MODE_AUTO; + + DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode)); + return 0; +} + +int rt_ioctl_siwsens(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + return 0; +} + +int rt_ioctl_giwsens(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + return 0; +} + +int rt_ioctl_giwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + VOID *pAd = NULL; + struct iw_range *range = (struct iw_range *) extra; + u16 val; + int i; + ULONG Mode, ChannelListNum; + UCHAR *pChannel; + UINT32 *pFreq; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifndef RT_CFG80211_SUPPORT +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n")); + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->txpower_capa = IW_TXPOW_DBM; + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWMODE, 0, + &Mode, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + +/* if (INFRA_ON(pAd)||ADHOC_ON(pAd)) */ + if ((Mode == RTMP_CMD_STA_MODE_INFRA) || (Mode == RTMP_CMD_STA_MODE_ADHOC)) + { + range->min_pmp = 1 * 1024; + range->max_pmp = 65535 * 1024; + range->min_pmt = 1 * 1024; + range->max_pmt = 1000 * 1024; + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | + IW_POWER_UNICAST_R | IW_POWER_ALL_R; + } + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 14; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; + +/* range->num_channels = pAd->ChannelListNum; */ + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_CHAN_LIST_NUM_GET, 0, + &ChannelListNum, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + range->num_channels = ChannelListNum; + + os_alloc_mem(NULL, (UCHAR **)&pChannel, sizeof(UCHAR)*ChannelListNum); + if (pChannel == NULL) + return -ENOMEM; + os_alloc_mem(NULL, (UCHAR **)&pFreq, sizeof(UINT32)*ChannelListNum); + if (pFreq == NULL) + { + os_free_mem(NULL, pChannel); + return -ENOMEM; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_CHAN_LIST_GET, 0, + pChannel, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_FREQ_LIST_GET, 0, + pFreq, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + val = 0; + for (i = 1; i <= range->num_channels; i++) + { +/* u32 m = 2412000; */ + range->freq[val].i = pChannel[i-1]; +/* MAP_CHANNEL_ID_TO_KHZ(pAd->ChannelList[i-1].Channel, m); */ + range->freq[val].m = pFreq[i-1] * 100; /* OS_HZ */ + + range->freq[val].e = 1; + val++; + if (val == IW_MAX_FREQUENCIES) + break; + } + os_free_mem(NULL, pChannel); + os_free_mem(NULL, pFreq); + + range->num_frequency = val; + + range->max_qual.qual = 100; /* what is correct max? This was not + * documented exactly. At least + * 69 has been observed. */ + range->max_qual.level = 0; /* dB */ + range->max_qual.noise = 0; /* dB */ + + /* What would be suitable values for "average/typical" qual? */ + range->avg_qual.qual = 20; + range->avg_qual.level = -60; + range->avg_qual.noise = -95; + range->sensitivity = 3; + + range->max_encoding_tokens = NR_WEP_KEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + +#if WIRELESS_EXT > 17 + /* IW_ENC_CAPA_* bit field */ + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; +#endif + + return 0; +} + +int rt_ioctl_giwpriv( + struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ +#ifdef ANDROID_SUPPORT + VOID *pAd = NULL; + int len = 0; + char *ext; + int ret = 0; + + len = dwrq->length; + ext = kmalloc(len, /*GFP_KERNEL*/GFP_ATOMIC); + if(!ext) + return -ENOMEM; + + if (copy_from_user(ext, dwrq->pointer, len)) + { + kfree(ext); + printk("andriod_handle_private copy_from_user\n"); + return -EFAULT; + } + ext[len-1] = 0x00; + GET_PAD_FROM_NET_DEV(pAd, dev); + + if(rtstrcasecmp(ext,"START") == TRUE) + { + //Turn on Wi-Fi hardware + //OK if successful + printk("sSTART Turn on Wi-Fi hardware \n"); + kfree(ext); + return -1; + } + else if(rtstrcasecmp(ext,"STOP") == TRUE) + { + printk("STOP Turn off Wi-Fi hardware \n"); + kfree(ext); + return -1; + } + else if(rtstrcasecmp(ext,"RSSI") == TRUE) + { + CHAR AvgRssi0; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWPRIVRSSI, + 0, &AvgRssi0, 0, dev->priv_flags); + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)),"rssi %d", AvgRssi0); + } + else if(rtstrcasecmp(ext,"LINKSPEED") == TRUE) + { + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)),"LINKSPEED %d", 150); + } + else if(rtstrcasecmp(ext,"MACADDR") == TRUE) + { + UCHAR mac[6]; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIFHWADDR, + 0, mac, 0, dev->priv_flags); + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)), + "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + } + else if(rtstrcasecmp(ext,"SCAN-ACTIVE") == TRUE) + { + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)),"OK"); + } + else if(rtstrcasecmp(ext,"SCAN-PASSIVE") == TRUE) + { + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)),"OK"); + } + else + { + goto FREE_EXT; + } + + if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (UINT16)(strlen(ext)+1)) ) ) + ret = -EFAULT; + +FREE_EXT: + + kfree(ext); + + return ret; +#else + return 0; +#endif +} + + +int rt_ioctl_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + VOID *pAd = NULL; + UCHAR Bssid[6]; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWAP, 0, + (VOID *)(ap_addr->sa_data), 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN); + + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + + return 0; +} + +int rt_ioctl_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWAP, 0, + (VOID *)(ap_addr->sa_data), 0, + RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n")); + return -ENOTCONN; + } + ap_addr->sa_family = ARPHRD_ETHER; + + return 0; +} + +/* + * Units are in db above the noise floor. That means the + * rssi values reported in the tx/rx descriptors in the + * driver are the SNR expressed in db. + * + * If you assume that the noise floor is -95, which is an + * excellent assumption 99.5 % of the time, then you can + * derive the absolute signal level (i.e. -95 + rssi). + * There are some other slight factors to take into account + * depending on whether the rssi measurement is from 11b, + * 11g, or 11a. These differences are at most 2db and + * can be documented. + * + * NB: various calculations are based on the orinoco/wavelan + * drivers for compatibility + */ +static void set_quality(VOID *pAd, + struct iw_quality *iq, + RT_CMD_STA_IOCTL_BSS *pBss) +/* BSS_ENTRY *pBssEntry) */ +{ + + iq->qual = pBss->ChannelQuality; + iq->level = (__u8)(pBss->Rssi); + iq->noise = pBss->Noise; + +/* iq->updated = pAd->iw_stats.qual.updated; */ +/* iq->updated = ((struct iw_statistics *)(pAd->iw_stats))->qual.updated; */ + iq->updated = 1; /* Flags to know if updated */ + +#if WIRELESS_EXT >= 17 + iq->updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED; +#endif + +#if WIRELESS_EXT >= 19 + iq->updated |= IW_QUAL_DBM; /* Level + Noise are dBm */ +#endif +} + +int rt_ioctl_iwaplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + VOID *pAd = NULL; + +/* struct sockaddr addr[IW_MAX_AP]; */ + struct sockaddr *addr = NULL; + struct iw_quality qual[IW_MAX_AP]; + int i; + RT_CMD_STA_IOCTL_BSS_LIST BssList, *pBssList = &BssList; + RT_CMD_STA_IOCTL_BSS *pList; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + data->length = 0; + return 0; + /*return -ENETDOWN; */ + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&(pBssList->pList), sizeof(RT_CMD_STA_IOCTL_BSS_LIST) * IW_MAX_AP); + if (pBssList->pList == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return 0; + } + + os_alloc_mem(NULL, (UCHAR **)&addr, sizeof(struct sockaddr) * IW_MAX_AP); + if (addr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + os_free_mem(NULL, pBssList); + return 0; + } + + pBssList->MaxNum = IW_MAX_AP; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_BSS_LIST_GET, 0, + pBssList, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + for (i = 0; i = pBssList->BssNum) /*pAd->ScanTab.BssNr) */ + break; + addr[i].sa_family = ARPHRD_ETHER; + pList = (pBssList->pList) + i; + memcpy(addr[i].sa_data, pList->Bssid, MAC_ADDR_LEN); + set_quality(pAd, &qual[i], pList); /*&pAd->ScanTab.BssEntry[i]); */ + } + data->length = i; + memcpy(extra, &addr, i*sizeof(addr[0])); + data->flags = 1; /* signal quality present (sort of) */ + memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i])); + + os_free_mem(NULL, addr); + os_free_mem(NULL, pBssList->pList); + return 0; +} + +#if defined(SIOCGIWSCAN) || defined(RT_CFG80211_SUPPORT) +int rt_ioctl_siwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wreq, char *extra) +{ + VOID *pAd = NULL; + int Status = NDIS_STATUS_SUCCESS; + RT_CMD_STA_IOCTL_SCAN IoctlScan, *pIoctlScan = &IoctlScan; +#ifdef WPA_SUPPLICANT_SUPPORT + struct iw_scan_req *req = (struct iw_scan_req *)extra; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ +/* because android will set scan and get scan when interface down */ +#ifndef ANDROID_SUPPORT + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } +#endif /* ANDROID_SUPPORT */ + + + memset(pIoctlScan, 0, sizeof(RT_CMD_STA_IOCTL_SCAN)); +#ifdef WPA_SUPPLICANT_SUPPORT +#if WIRELESS_EXT > 17 + pIoctlScan->FlgScanThisSsid = (wreq->data.length == sizeof(struct iw_scan_req) && + wreq->data.flags & IW_SCAN_THIS_ESSID); + pIoctlScan->SsidLen = req->essid_len; + pIoctlScan->pSsid = (CHAR *)(req->essid); +#endif +#endif /* WPA_SUPPLICANT_SUPPORT */ + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWSCAN, 0, + pIoctlScan, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + RT_CMD_STATUS_TRANSLATE(pIoctlScan->Status); + Status = pIoctlScan->Status; + return Status; +} + +int rt_ioctl_giwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + VOID *pAd = NULL; + int i=0, status = 0; + PSTRING current_ev = extra, previous_ev = extra; + PSTRING end_buf; + PSTRING current_val; + STRING custom[MAX_CUSTOM_LEN] = {0}; +#ifndef IWEVGENIE + unsigned char idx; +#endif /* IWEVGENIE */ + struct iw_event iwe; + RT_CMD_STA_IOCTL_SCAN_TABLE IoctlScan, *pIoctlScan = &IoctlScan; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ +/* because android will set scan and get scan when interface down */ +#ifndef ANDROID_SUPPORT + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } +#endif /* ANDROID_SUPPORT */ + + + pIoctlScan->priv_flags = RT_DEV_PRIV_FLAGS_GET(dev); + pIoctlScan->pBssTable = NULL; + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWSCAN, 0, + pIoctlScan, 0, + RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + { + status = -EINVAL; + goto go_out; + } + + + if (pIoctlScan->BssNr == 0) + { + data->length = 0; + status = 0; + goto go_out; + } + +#if WIRELESS_EXT >= 17 + if (data->length > 0) + end_buf = extra + data->length; + else + end_buf = extra + IW_SCAN_MAX_DATA; +#else + end_buf = extra + IW_SCAN_MAX_DATA; +#endif + + for (i = 0; i < pIoctlScan->BssNr; i++) + { + if (current_ev >= end_buf) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /*MAC address */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &pIoctlScan->pBssTable[i].Bssid, ETH_ALEN); + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /* + Protocol: + it will show scanned AP's WirelessMode . + it might be + 802.11a + 802.11a/n + 802.11g/n + 802.11b/g/n + 802.11g + 802.11b/g + */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWNAME; + + + { + RT_CMD_STA_IOCTL_BSS_TABLE *pBssEntry=&pIoctlScan->pBssTable[i]; + BOOLEAN isGonly=FALSE; + int rateCnt=0; + + if (pBssEntry->Channel>14) + { + if (pBssEntry->HtCapabilityLen!=0) + strcpy(iwe.u.name,"802.11a/n"); + else + strcpy(iwe.u.name,"802.11a"); + } + else + { + /* + if one of non B mode rate is set supported rate . it mean G only. + */ + for (rateCnt=0;rateCntSupRateLen;rateCnt++) + { + /* + 6Mbps(140) 9Mbps(146) and >=12Mbps(152) are supported rate , it mean G only. + */ + if (pBssEntry->SupRate[rateCnt]==140 || pBssEntry->SupRate[rateCnt]==146 || pBssEntry->SupRate[rateCnt]>=152) + isGonly=TRUE; + } + + for (rateCnt=0;rateCntExtRateLen;rateCnt++) + { + if (pBssEntry->ExtRate[rateCnt]==140 || pBssEntry->ExtRate[rateCnt]==146 || pBssEntry->ExtRate[rateCnt]>=152) + isGonly=TRUE; + } + + + if (pBssEntry->HtCapabilityLen!=0) + { + if (isGonly==TRUE) + strcpy(iwe.u.name,"802.11g/n"); + else + strcpy(iwe.u.name,"802.11b/g/n"); + } + else + { + if (isGonly==TRUE) + strcpy(iwe.u.name,"802.11g"); + else + { + if (pBssEntry->SupRateLen==4 && pBssEntry->ExtRateLen==0) + strcpy(iwe.u.name,"802.11b"); + else + strcpy(iwe.u.name,"802.11b/g"); + } + } + } + } + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /*ESSID */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = pIoctlScan->pBssTable[i].SsidLen; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev,end_buf, &iwe, (PSTRING) pIoctlScan->pBssTable[i].Ssid); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /*Network Type */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (pIoctlScan->pBssTable[i].BssType == Ndis802_11IBSS) + { + iwe.u.mode = IW_MODE_ADHOC; + } + else if (pIoctlScan->pBssTable[i].BssType == Ndis802_11Infrastructure) + { + iwe.u.mode = IW_MODE_INFRA; + } + else + { + iwe.u.mode = IW_MODE_AUTO; + } + iwe.len = IW_EV_UINT_LEN; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /*Channel and Frequency */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + { + UCHAR ch = pIoctlScan->pBssTable[i].Channel; + ULONG m = 0; +/* MAP_CHANNEL_ID_TO_KHZ(ch, m); */ + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_CHID_2_FREQ, 0, + (VOID *)&m, ch, RT_DEV_PRIV_FLAGS_GET(dev)); + iwe.u.freq.m = m * 100; + iwe.u.freq.e = 1; + iwe.u.freq.i = 0; + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } + + /*Add quality statistics */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = 0; + iwe.u.qual.noise = 0; + set_quality(pAd, &iwe.u.qual, &pIoctlScan->pBssTable[i].Signal); + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /*Encyption key */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (pIoctlScan->pBssTable[i].FlgIsPrivacyOn) + iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (char *)pIoctlScan->MainSharedKey[(iwe.u.data.flags & IW_ENCODE_INDEX)-1]); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + + /*Bit Rate */ + /*================================ */ + if (pIoctlScan->pBssTable[i].SupRateLen) + { + UCHAR tmpRate = pIoctlScan->pBssTable[i].SupRate[pIoctlScan->pBssTable[i].SupRateLen-1]; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + current_val = current_ev + IW_EV_LCP_LEN; + if (tmpRate == 0x82) + iwe.u.bitrate.value = 1 * 1000000; + else if (tmpRate == 0x84) + iwe.u.bitrate.value = 2 * 1000000; + else if (tmpRate == 0x8B) + iwe.u.bitrate.value = 5.5 * 1000000; + else if (tmpRate == 0x96) + iwe.u.bitrate.value = 11 * 1000000; + else + iwe.u.bitrate.value = (tmpRate/2) * 1000000; + + if (pIoctlScan->pBssTable[i].ExtRateLen) + { + UCHAR tmpSupRate =(pIoctlScan->pBssTable[i].SupRate[pIoctlScan->pBssTable[i].SupRateLen-1]& 0x7f); + UCHAR tmpExtRate =(pIoctlScan->pBssTable[i].ExtRate[pIoctlScan->pBssTable[i].ExtRateLen-1]& 0x7f); + iwe.u.bitrate.value = (tmpSupRate > tmpExtRate) ? (tmpSupRate)*500000 : (tmpExtRate)*500000; + } + + if (tmpRate == 0x6c && pIoctlScan->pBssTable[i].HtCapabilityLen > 0) + { + +/* HT_CAP_INFO capInfo = pIoctlScan->pBssTable[i].HtCapability.HtCapInfo; */ + int shortGI = pIoctlScan->pBssTable[i].ChannelWidth ? pIoctlScan->pBssTable[i].ShortGIfor40 : pIoctlScan->pBssTable[i].ShortGIfor20; + //int maxMCS = pIoctlScan->pBssTable[i].MCSSet ? 15 : 7; + int maxMCS = 7; + if(pIoctlScan->pBssTable[i].HtCapabilityLen > 0 && pIoctlScan->pBssTable[i].VHTCapabilityLen > 0) + RtmpDrvRateGet(pAd, MODE_VHT, shortGI, + pIoctlScan->pBssTable[i].ChannelWidth, maxMCS, + newRateGetAntenna(maxMCS, MODE_VHT), &iwe.u.bitrate.value); + else if (pIoctlScan->pBssTable[i].HtCapabilityLen > 0) + RtmpDrvRateGet(pAd, MODE_HTMIX, shortGI, + pIoctlScan->pBssTable[i].ChannelWidth, maxMCS, + newRateGetAntenna(maxMCS, MODE_HTMIX), &iwe.u.bitrate.value); + } + + iwe.u.bitrate.disabled = 0; + current_val = IWE_STREAM_ADD_VALUE(info, current_ev, + current_val, end_buf, &iwe, + IW_EV_PARAM_LEN); + + if((current_val-current_ev)>IW_EV_LCP_LEN) + current_ev = current_val; + else + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } + +#ifdef IWEVGENIE + /*WPA IE */ + if (pIoctlScan->pBssTable[i].WpaIeLen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pIoctlScan->pBssTable[i].pWpaIe[0]), + pIoctlScan->pBssTable[i].WpaIeLen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pIoctlScan->pBssTable[i].WpaIeLen; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } + + /*WPA2 IE */ + if (pIoctlScan->pBssTable[i].RsnIeLen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pIoctlScan->pBssTable[i].pRsnIe[0]), + pIoctlScan->pBssTable[i].RsnIeLen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pIoctlScan->pBssTable[i].RsnIeLen; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } + + /*WPS IE */ + if (pIoctlScan->pBssTable[i].WpsIeLen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pIoctlScan->pBssTable[i].pWpsIe[0]), + pIoctlScan->pBssTable[i].WpsIeLen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pIoctlScan->pBssTable[i].WpsIeLen; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } +#else + /*WPA IE */ + /*================================ */ + if (pIoctlScan->pBssTable[i].WpaIeLen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pIoctlScan->pBssTable[i].WpaIeLen * 2) + 7; + NdisMoveMemory(custom, "wpa_ie=", 7); + for (idx = 0; idx < pIoctlScan->pBssTable[i].WpaIeLen; idx++) + sprintf(custom, "%s%02x", custom, pIoctlScan->pBssTable[i].pWpaIe[idx]); + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } + + /*WPA2 IE */ + if (pIoctlScan->pBssTable[i].RsnIeLen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pIoctlScan->pBssTable[i].RsnIeLen * 2) + 7; + NdisMoveMemory(custom, "rsn_ie=", 7); + for (idx = 0; idx < pIoctlScan->pBssTable[i].RsnIeLen; idx++) + sprintf(custom, "%s%02x", custom, pIoctlScan->pBssTable[i].pRsnIe[idx]); + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } + +#ifdef WSC_INCLUDED + /*WPS IE */ + if (pIoctlScan->pBssTable[i].WpsIeLen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pIoctlScan->pBssTable[i].WpsIeLen * 2) + 7; + NdisMoveMemory(custom, "wps_ie=", 7); + for (idx = 0; idx < pIoctlScan->pBssTable[i].WpsIeLen; idx++) + sprintf(custom, "%s%02x", custom, pIoctlScan->pBssTable[i].pWpsIe[idx]); + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) + { +#if WIRELESS_EXT >= 17 + status = -E2BIG; + goto go_out; +#else + break; +#endif + } + } +#endif /* WSC_INCLUDED */ + +#endif /* IWEVGENIE */ + } + + data->length = current_ev - extra; +/* pAd->StaCfg.bScanReqIsFromWebUI = FALSE; */ +/* DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAd->ScanTab.BssNr, data->length)); */ + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SCAN_END, 0, + NULL, data->length, RT_DEV_PRIV_FLAGS_GET(dev)); + +go_out: + if (pIoctlScan->pBssTable != NULL) + os_free_mem(NULL, pIoctlScan->pBssTable); + + return status; +} +#endif + +int rt_ioctl_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + VOID *pAd = NULL; + RT_CMD_STA_IOCTL_SSID IoctlEssid, *pIoctlEssid = &IoctlEssid; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->flags) + { + /* Includes null character. */ + if (data->length > (IW_ESSID_MAX_SIZE + 1)) + return -E2BIG; + } + + + pIoctlEssid->FlgAnySsid = data->flags; + pIoctlEssid->SsidLen = data->length; + pIoctlEssid->pSsid = (CHAR *)essid; + pIoctlEssid->Status = 0; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWESSID, 0, + pIoctlEssid, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + RT_CMD_STATUS_TRANSLATE(pIoctlEssid->Status); + return pIoctlEssid->Status; +} + +int rt_ioctl_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + VOID *pAd = NULL; + RT_CMD_STA_IOCTL_SSID IoctlEssid, *pIoctlEssid = &IoctlEssid; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + data->flags = 1; + + + pIoctlEssid->pSsid = (CHAR *)essid; + pIoctlEssid->Status = 0; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWESSID, 0, + pIoctlEssid, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + data->length = pIoctlEssid->SsidLen; + + RT_CMD_STATUS_TRANSLATE(pIoctlEssid->Status); + return pIoctlEssid->Status; +} + +int rt_ioctl_siwnickn(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *nickname) +{ + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->length > IW_ESSID_MAX_SIZE) + return -EINVAL; + + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWNICKN, 0, + nickname, data->length, RT_DEV_PRIV_FLAGS_GET(dev)); + return 0; +} + +int rt_ioctl_giwnickn(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *nickname) +{ + VOID *pAd = NULL; + RT_CMD_STA_IOCTL_NICK_NAME NickName, *pNickName = &NickName; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + data->length = 0; + return -ENETDOWN; + } + + + pNickName->NameLen = data->length; + pNickName->pName = (CHAR *)nickname; + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWNICKN, 0, + pNickName, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + data->length = pNickName->NameLen; + return 0; +} + +int rt_ioctl_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + VOID *pAd = NULL; + u16 val; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (rts->disabled) + val = MAX_RTS_THRESHOLD; + else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD) + return -EINVAL; + else if (rts->value == 0) + val = MAX_RTS_THRESHOLD; + else + val = rts->value; + +/* if (val != pAd->CommonCfg.RtsThreshold) */ +/* pAd->CommonCfg.RtsThreshold = val; */ + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWRTS, 0, + NULL, val, RT_DEV_PRIV_FLAGS_GET(dev)); + return 0; +} + +int rt_ioctl_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + VOID *pAd = NULL; + USHORT RtsThreshold; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWRTS, 0, + &RtsThreshold, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + rts->value = RtsThreshold; + rts->disabled = (rts->value == MAX_RTS_THRESHOLD); + rts->fixed = 1; + + return 0; +} + +int rt_ioctl_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + VOID *pAd = NULL; + u16 val; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (frag->disabled) + val = MAX_FRAG_THRESHOLD; + else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD) + val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */ + else if (frag->value == 0) + val = MAX_FRAG_THRESHOLD; + else + return -EINVAL; + +/* pAd->CommonCfg.FragmentThreshold = val; */ + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWFRAG, 0, + NULL, val, RT_DEV_PRIV_FLAGS_GET(dev)); + return 0; +} + +int rt_ioctl_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + VOID *pAd = NULL; + USHORT FragmentThreshold; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWFRAG, 0, + &FragmentThreshold, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + frag->value = FragmentThreshold; + frag->disabled = (frag->value == MAX_FRAG_THRESHOLD); + frag->fixed = 1; + + return 0; +} + +#define MAX_WEP_KEY_SIZE 13 +#define MIN_WEP_KEY_SIZE 5 +int rt_ioctl_siwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *extra) +{ + VOID *pAd = NULL; + RT_CMD_STA_IOCTL_SECURITY IoctlSec, *pIoctlSec = &IoctlSec; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlSec->pData = (CHAR *)extra; + pIoctlSec->length = erq->length; + pIoctlSec->KeyIdx = (erq->flags & IW_ENCODE_INDEX) - 1; + pIoctlSec->flags = 0; + + if (erq->flags & IW_ENCODE_DISABLED) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_DISABLED; + if (erq->flags & IW_ENCODE_RESTRICTED) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_RESTRICTED; + if (erq->flags & IW_ENCODE_OPEN) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_OPEN; + if (erq->flags & IW_ENCODE_NOKEY) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_NOKEY; + if (erq->flags & IW_ENCODE_MODE) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_MODE; + + pIoctlSec->Status = 0; + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODE, 0, + pIoctlSec, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + RT_CMD_STATUS_TRANSLATE(pIoctlSec->Status); + return pIoctlSec->Status; +} + +int +rt_ioctl_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ +/* int kid; */ + VOID *pAd = NULL; + RT_CMD_STA_IOCTL_SECURITY IoctlSec, *pIoctlSec = &IoctlSec; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlSec->pData = (CHAR *)key; + pIoctlSec->KeyIdx = erq->flags & IW_ENCODE_INDEX; + pIoctlSec->length = erq->length; + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODE, 0, + pIoctlSec, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + erq->length = pIoctlSec->length; + erq->flags = pIoctlSec->KeyIdx; + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_DISABLED) + erq->flags = RT_CMD_STA_IOCTL_SECURITY_DISABLED; + { + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_ENABLED) + erq->flags |= IW_ENCODE_ENABLED; + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_RESTRICTED) + erq->flags |= IW_ENCODE_RESTRICTED; + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_OPEN) + erq->flags |= IW_ENCODE_OPEN; + } + return 0; + +} + +int rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info, + void *w, char *extra) +{ + VOID *pAd; +/* POS_COOKIE pObj; */ + PSTRING this_char = extra; + PSTRING value = NULL; + int Status=0; + RT_CMD_PARAM_SET CmdParam; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + + + if (!*this_char) + return -EINVAL; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, this_char) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + else + { + if (!value && (strcmp(this_char, "SiteSurvey") != 0)) + return -EINVAL; + else if (!value && (strcmp(this_char, "SiteSurvey") == 0)) + goto SET_PROC; + + /* reject setting nothing besides ANY ssid(ssidLen=0) */ + if (!*value && (strcmp(this_char, "SSID") != 0)) + return -EINVAL; + } + +SET_PROC: + CmdParam.pThisChar = this_char; + CmdParam.pValue = value; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_PARAM_SET, 0, + &CmdParam, 0, RT_DEV_PRIV_FLAGS_GET(dev)); +/* Status = RTMPSTAPrivIoctlSet(pAd, this_char, value); */ + + return Status; +} + + +#ifdef WSC_STA_SUPPORT + +static int +rt_private_set_wsc_u32_item(struct net_device *dev, struct iw_request_info *info, + u32 *uwrq, char *extra) +{ + VOID *pAd = NULL; +/* int Status=0; */ +/* u32 subcmd = *uwrq; */ +/* PWSC_PROFILE pWscProfile = NULL; */ +/* u32 value = 0; */ + RT_CMD_STA_IOCTL_WSC_U32_ITEM IoctlWscU32, *pIoctlWscU32 = &IoctlWscU32; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlWscU32->pUWrq = uwrq; + pIoctlWscU32->Status = NDIS_STATUS_SUCCESS; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_U32_ITEM, 0, + pIoctlWscU32, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + RT_CMD_STATUS_TRANSLATE(pIoctlWscU32->Status); + return pIoctlWscU32->Status; +} + +static int +rt_private_set_wsc_string_item(struct net_device *dev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + RT_CMD_STA_IOCTL_WSC_STR_ITEM IoctlWscStr, *pIoctlWscStr = &IoctlWscStr; +/* int Status=0; */ +/* u32 subcmd = dwrq->flags; */ +/* u32 tmpProfileIndex = (u32)(extra[0] - 0x30); */ +/* u32 dataLen; */ + VOID *pAd = NULL; +/* PWSC_PROFILE pWscProfile = NULL; */ +/* USHORT tmpAuth = 0, tmpEncr = 0; */ + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlWscStr->Subcmd = dwrq->flags; + pIoctlWscStr->pData = (CHAR *)extra; + pIoctlWscStr->length = dwrq->length; + + pIoctlWscStr->Status = RTMP_STA_IoctlHandle(pAd, NULL, + CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_STR_ITEM, 0, + pIoctlWscStr, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + RT_CMD_STATUS_TRANSLATE(pIoctlWscStr->Status); + return pIoctlWscStr->Status; +} +#endif /* WSC_STA_SUPPORT */ + +static int +rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) +{ + INT Status = 0; + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (extra == NULL) + { + wrq->length = 0; + return -EIO; + } + + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_IW_GET_STATISTICS, 0, + extra, IW_PRIV_SIZE_MASK, RT_DEV_PRIV_FLAGS_GET(dev)); + + wrq->length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length)); + + return Status; +} + + +static int +rt_private_show(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, PSTRING extra) +{ + RTMP_IOCTL_INPUT_STRUCT wrqin; + INT Status = 0; + VOID *pAd; +/* POS_COOKIE pObj; */ + u32 subcmd = wrq->flags; + RT_CMD_STA_IOCTL_SHOW IoctlShow, *pIoctlShow = &IoctlShow; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + +/* pObj = (POS_COOKIE) pAd->OS_Cookie; */ + if (extra == NULL) + { + wrq->length = 0; + return -EIO; + } + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + + wrqin.u.data.pointer = wrq->pointer; + wrqin.u.data.length = wrq->length; + + pIoctlShow->pData = (CHAR *)extra; + pIoctlShow->MaxSize = IW_PRIV_SIZE_MASK; + pIoctlShow->InfType = RT_DEV_PRIV_FLAGS_GET(dev); + RTMP_STA_IoctlHandle(pAd, &wrqin, CMD_RTPRIV_IOCTL_SHOW, subcmd, + pIoctlShow, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + wrq->length = wrqin.u.data.length; + return Status; +} + +#ifdef SIOCSIWMLME +int rt_ioctl_siwmlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + VOID *pAd = NULL; + struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer; +/* MLME_QUEUE_ELEM MsgElem; */ +/* MLME_QUEUE_ELEM *pMsgElem = NULL; */ +/* MLME_DISASSOC_REQ_STRUCT DisAssocReq; */ +/* MLME_DEAUTH_REQ_STRUCT DeAuthReq; */ + ULONG Subcmd = 0; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (pMlme == NULL) + return -EINVAL; + + + switch(pMlme->cmd) + { +#ifdef IW_MLME_DEAUTH + case IW_MLME_DEAUTH: + Subcmd = RT_CMD_STA_IOCTL_IW_MLME_DEAUTH; + break; +#endif /* IW_MLME_DEAUTH */ +#ifdef IW_MLME_DISASSOC + case IW_MLME_DISASSOC: + Subcmd = RT_CMD_STA_IOCTL_IW_MLME_DISASSOC; + break; +#endif /* IW_MLME_DISASSOC */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__)); + break; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWMLME, Subcmd, + NULL, pMlme->reason_code, RT_DEV_PRIV_FLAGS_GET(dev)); + return 0; +} +#endif /* SIOCSIWMLME */ + +#if WIRELESS_EXT > 17 + + +int rt_ioctl_siwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; + struct iw_param *param = &wrqu->param; + RT_CMD_STA_IOCTL_SECURITY_ADV IoctlWpa, *pIoctlWpa = &IoctlWpa; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlWpa->flags = 0; + pIoctlWpa->value = param->value; /* default */ + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_VERSION; + if (param->value == IW_AUTH_WPA_VERSION_WPA) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_VERSION1; + else if (param->value == IW_AUTH_WPA_VERSION_WPA2) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_VERSION2; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_CIPHER_PAIRWISE: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_PAIRWISE; + if (param->value == IW_AUTH_CIPHER_NONE) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_PAIRWISE_NONE; + else if (param->value == IW_AUTH_CIPHER_WEP40) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP40; + else if (param->value == IW_AUTH_CIPHER_WEP104) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP104; + else if (param->value == IW_AUTH_CIPHER_TKIP) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_PAIRWISE_TKIP; + else if (param->value == IW_AUTH_CIPHER_CCMP) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_PAIRWISE_CCMP; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_CIPHER_GROUP: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_GROUP; + if (param->value == IW_AUTH_CIPHER_NONE) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_GROUP_NONE; + else if (param->value == IW_AUTH_CIPHER_WEP40) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_GROUP_WEP40; + else if (param->value == IW_AUTH_CIPHER_WEP104) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_GROUP_WEP104; + else if (param->value == IW_AUTH_CIPHER_TKIP) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_GROUP_TKIP; + else if (param->value == IW_AUTH_CIPHER_CCMP) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_GROUP_CCMP; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_KEY_MGMT: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_KEY_MGMT; + if (param->value == IW_AUTH_KEY_MGMT_802_1X) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_KEY_MGMT_1X; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_RX_UNENCRYPTED_EAPOL; + break; + case IW_AUTH_PRIVACY_INVOKED: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_PRIVACY_INVOKED; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_DROP_UNENCRYPTED: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_DROP_UNENCRYPTED - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_80211_AUTH_ALG: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG; + if (param->value & IW_AUTH_ALG_SHARED_KEY) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_SHARED; + else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_OPEN; + else if (param->value & IW_AUTH_ALG_LEAP) + pIoctlWpa->value = RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_LEAP; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_WPA_ENABLED: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value)); + break; + default: + return -EOPNOTSUPP; +} + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWAUTH, 0, + pIoctlWpa, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + return 0; +} + +int rt_ioctl_giwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; + struct iw_param *param = &wrqu->param; + RT_CMD_STA_IOCTL_SECURITY_ADV IoctlWpa, *pIoctlWpa = &IoctlWpa; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlWpa->flags = 0; + pIoctlWpa->value = 0; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED; + break; + + case IW_AUTH_80211_AUTH_ALG: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG; + break; + + case IW_AUTH_WPA_ENABLED: + pIoctlWpa->flags = RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED; + break; + + default: + return -EOPNOTSUPP; + } + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWAUTH, 0, + pIoctlWpa, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = pIoctlWpa->value; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = (pIoctlWpa->value == 0) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM; + break; + + case IW_AUTH_WPA_ENABLED: + param->value = pIoctlWpa->value; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value)); + return 0; +} + + +int rt_ioctl_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + VOID *pAd = NULL; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int /* keyIdx, */ alg = ext->alg; + RT_CMD_STA_IOCTL_SECURITY IoctlSec, *pIoctlSec = &IoctlSec; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlSec->pData = (CHAR *)ext->key; + pIoctlSec->length = ext->key_len; + pIoctlSec->KeyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + if (alg == IW_ENCODE_ALG_NONE ) + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_NONE; + else if (alg == IW_ENCODE_ALG_WEP) + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_WEP; + else if (alg == IW_ENCODE_ALG_TKIP) + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP; + else if (alg == IW_ENCODE_ALG_CCMP) + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP; + else + { + DBGPRINT(RT_DEBUG_WARN, ("Warning: Security type is not supported. (alg = %d) \n", alg)); + pIoctlSec->Alg = alg; + return -EOPNOTSUPP; + } + pIoctlSec->ext_flags = 0; + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + pIoctlSec->ext_flags |= RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY; + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + pIoctlSec->ext_flags |= RT_CMD_STA_IOCTL_SECURTIY_EXT_GROUP_KEY; + if (encoding->flags & IW_ENCODE_DISABLED) + pIoctlSec->flags = RT_CMD_STA_IOCTL_SECURITY_DISABLED; + else + pIoctlSec->flags = 0; + + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODEEXT, 0, + pIoctlSec, 0, RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + return -EINVAL; + + return 0; +} + +int +rt_ioctl_giwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; +/* PCHAR pKey = NULL; */ + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int /* idx, */ max_key_len; + RT_CMD_STA_IOCTL_SECURITY IoctlSec, *pIoctlSec = &IoctlSec; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n")); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + memset(ext, 0, sizeof(*ext)); + + + memset(pIoctlSec, 0, sizeof(RT_CMD_STA_IOCTL_SECURITY)); + pIoctlSec->KeyIdx = encoding->flags & IW_ENCODE_INDEX; + pIoctlSec->MaxKeyLen = max_key_len; + + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODEEXT, 0, + pIoctlSec, 0, RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + { + ext->key_len = 0; + RT_CMD_STATUS_TRANSLATE(pIoctlSec->Status); + return pIoctlSec->Status; + } + + encoding->flags = pIoctlSec->KeyIdx; + ext->key_len = pIoctlSec->length; + + if (pIoctlSec->Alg == RT_CMD_STA_IOCTL_SECURITY_ALG_NONE) + ext->alg = IW_ENCODE_ALG_NONE; + else if (pIoctlSec->Alg == RT_CMD_STA_IOCTL_SECURITY_ALG_WEP) + ext->alg = IW_ENCODE_ALG_WEP; + else if (pIoctlSec->Alg == RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP) + ext->alg = IW_ENCODE_ALG_TKIP; + else if (pIoctlSec->Alg == RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP) + ext->alg = IW_ENCODE_ALG_CCMP; + + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_DISABLED) + encoding->flags |= IW_ENCODE_DISABLED; + + if (ext->key_len && pIoctlSec->pData) + { + encoding->flags |= IW_ENCODE_ENABLED; + memcpy(ext->key, pIoctlSec->pData, ext->key_len); + } + + return 0; +} + +#ifdef SIOCSIWGENIE +int rt_ioctl_siwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } +#ifdef WPA_SUPPLICANT_SUPPORT + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWGENIE, 0, + extra, wrqu->data.length, + RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + return -EINVAL; + else + return 0; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + return -EOPNOTSUPP; +} +#endif /* SIOCSIWGENIE */ + +int rt_ioctl_giwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; + RT_CMD_STA_IOCTL_RSN_IE IoctlRsnIe, *pIoctlRsnIe = &IoctlRsnIe; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + pIoctlRsnIe->length = wrqu->data.length; + pIoctlRsnIe->pRsnIe = (UCHAR *)extra; + + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWGENIE, 0, + pIoctlRsnIe, 0, + RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + return -E2BIG; + + wrqu->data.length = pIoctlRsnIe->length; + return 0; +} + +int rt_ioctl_siwpmksa(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + VOID *pAd = NULL; + struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer; +/* INT CachedIdx = 0, idx = 0; */ + RT_CMD_STA_IOCTL_PMA_SA IoctlPmaSa, *pIoctlPmaSa = &IoctlPmaSa; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (pPmksa == NULL) + return -EINVAL; + + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n")); + + + if (pPmksa->cmd == IW_PMKSA_FLUSH) + pIoctlPmaSa->Cmd = RT_CMD_STA_IOCTL_PMA_SA_FLUSH; + else if (pPmksa->cmd == IW_PMKSA_REMOVE) + pIoctlPmaSa->Cmd = RT_CMD_STA_IOCTL_PMA_SA_REMOVE; + else if (pPmksa->cmd == IW_PMKSA_ADD) + pIoctlPmaSa->Cmd = RT_CMD_STA_IOCTL_PMA_SA_ADD; + else + pIoctlPmaSa->Cmd = 0; + pIoctlPmaSa->pBssid = (UCHAR *)pPmksa->bssid.sa_data; + pIoctlPmaSa->pPmkid = pPmksa->pmkid; + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWPMKSA, 0, + pIoctlPmaSa, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + + return 0; +} +#endif /* #if WIRELESS_EXT > 17 */ + +#ifdef DBG +static int +rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) +{ + RTMP_IOCTL_INPUT_STRUCT wrqin; + INT Status = 0; + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + wrqin.u.data.pointer = wrq->pointer; + wrqin.u.data.length = wrq->length; + + RTMP_STA_IoctlHandle(pAd, &wrqin, CMD_RTPRIV_IOCTL_BBP, 0, + extra, IW_PRIV_SIZE_MASK, RT_DEV_PRIV_FLAGS_GET(dev)); + + wrq->length = wrqin.u.data.length; + + + DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n")); + + return Status; +} +#endif /* DBG */ + +int rt_ioctl_siwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; + UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; + RT_CMD_RATE_SET CmdRate; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n")); + return -ENETDOWN; + } + + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed)); + /* rate = -1 => auto rate + rate = X, fixed = 1 => (fixed rate X) + */ + + + CmdRate.Rate = rate; + CmdRate.Fixed = fixed; + + if (RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWRATE, 0, + &CmdRate, 0, + RT_DEV_PRIV_FLAGS_GET(dev)) != NDIS_STATUS_SUCCESS) + return -EOPNOTSUPP; + + return 0; +} + +int rt_ioctl_giwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOID *pAd = NULL; +/* int rate_index = 0, rate_count = 0; */ +/* HTTRANSMIT_SETTING ht_setting; */ + ULONG Rate; + + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWRATE, 0, + &Rate, 0, RT_DEV_PRIV_FLAGS_GET(dev)); + wrqu->bitrate.value = Rate; + wrqu->bitrate.disabled = 0; + + return 0; +} + + +static const iw_handler rt_handler[] = +{ + (iw_handler) NULL, /* SIOCSIWCOMMIT */ + (iw_handler) rt_ioctl_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) rt_ioctl_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) rt_ioctl_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) rt_ioctl_siwmode, /* SIOCSIWMODE */ + (iw_handler) rt_ioctl_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ + (iw_handler) rt_ioctl_giwrange, /* SIOCGIWRANGE */ + (iw_handler) rt_ioctl_giwpriv, /* SIOCSIWPRIV for Android */ + (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ + (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ + (iw_handler) rt28xx_get_wireless_stats /* kernel code */, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) rt_ioctl_siwap, /* SIOCSIWAP */ + (iw_handler) rt_ioctl_giwap, /* SIOCGIWAP */ +#ifdef SIOCSIWMLME + (iw_handler) rt_ioctl_siwmlme, /* SIOCSIWMLME */ +#else + (iw_handler) NULL, /* SIOCSIWMLME */ +#endif /* SIOCSIWMLME */ + (iw_handler) rt_ioctl_iwaplist, /* SIOCGIWAPLIST */ +#ifdef SIOCGIWSCAN + (iw_handler) rt_ioctl_siwscan, /* SIOCSIWSCAN */ + (iw_handler) rt_ioctl_giwscan, /* SIOCGIWSCAN */ +#else + (iw_handler) NULL, /* SIOCSIWSCAN */ + (iw_handler) NULL, /* SIOCGIWSCAN */ +#endif /* SIOCGIWSCAN */ + (iw_handler) rt_ioctl_siwessid, /* SIOCSIWESSID */ + (iw_handler) rt_ioctl_giwessid, /* SIOCGIWESSID */ + (iw_handler) rt_ioctl_siwnickn, /* SIOCSIWNICKN */ + (iw_handler) rt_ioctl_giwnickn, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) rt_ioctl_siwrate, /* SIOCSIWRATE */ + (iw_handler) rt_ioctl_giwrate, /* SIOCGIWRATE */ + (iw_handler) rt_ioctl_siwrts, /* SIOCSIWRTS */ + (iw_handler) rt_ioctl_giwrts, /* SIOCGIWRTS */ + (iw_handler) rt_ioctl_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) rt_ioctl_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + (iw_handler) rt_ioctl_siwencode, /* SIOCSIWENCODE */ + (iw_handler) rt_ioctl_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ +#if WIRELESS_EXT > 17 + (iw_handler) rt_ioctl_siwgenie, /* SIOCSIWGENIE */ + (iw_handler) rt_ioctl_giwgenie, /* SIOCGIWGENIE */ + (iw_handler) rt_ioctl_siwauth, /* SIOCSIWAUTH */ + (iw_handler) rt_ioctl_giwauth, /* SIOCGIWAUTH */ + (iw_handler) rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ +#endif +}; + +static const iw_handler rt_priv_handlers[] = { + (iw_handler) NULL, /* + 0x00 */ + (iw_handler) NULL, /* + 0x01 */ +#ifndef CONFIG_AP_SUPPORT + (iw_handler) rt_ioctl_setparam, /* + 0x02 */ +#else + (iw_handler) NULL, /* + 0x02 */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef DBG + (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */ +#else + (iw_handler) NULL, /* + 0x03 */ +#endif + (iw_handler) NULL, /* + 0x04 */ + (iw_handler) NULL, /* + 0x05 */ + (iw_handler) NULL, /* + 0x06 */ + (iw_handler) NULL, /* + 0x07 */ + (iw_handler) NULL, /* + 0x08 */ + (iw_handler) rt_private_get_statistics, /* + 0x09 */ + (iw_handler) NULL, /* + 0x0A */ + (iw_handler) NULL, /* + 0x0B */ + (iw_handler) NULL, /* + 0x0C */ + (iw_handler) NULL, /* + 0x0D */ + (iw_handler) NULL, /* + 0x0E */ + (iw_handler) NULL, /* + 0x0F */ + (iw_handler) NULL, /* + 0x10 */ + (iw_handler) rt_private_show, /* + 0x11 */ + (iw_handler) NULL, /* + 0x12 */ + (iw_handler) NULL, /* + 0x13 */ +#ifdef WSC_STA_SUPPORT + (iw_handler) rt_private_set_wsc_u32_item, /* + 0x14 */ +#else + (iw_handler) NULL, /* + 0x14 */ +#endif /* WSC_STA_SUPPORT */ + (iw_handler) NULL, /* + 0x15 */ +#ifdef WSC_STA_SUPPORT + (iw_handler) rt_private_set_wsc_string_item, /* + 0x16 */ +#else + (iw_handler) NULL, /* + 0x16 */ +#endif /* WSC_STA_SUPPORT */ + (iw_handler) NULL, /* + 0x17 */ + (iw_handler) NULL, /* + 0x18 */ +}; + +const struct iw_handler_def rt28xx_iw_handler_def = +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + .standard = (iw_handler *) rt_handler, + .num_standard = sizeof(rt_handler) / sizeof(iw_handler), + .private = (iw_handler *) rt_priv_handlers, + .num_private = N(rt_priv_handlers), + .private_args = (struct iw_priv_args *) privtab, + .num_private_args = N(privtab), +#if IW_HANDLER_VERSION >= 7 + .get_wireless_stats = rt28xx_get_wireless_stats, +#endif +}; + + +INT rt28xx_sta_ioctl(struct net_device *net_dev, struct ifreq *rq, INT cmd) +{ +/* POS_COOKIE pObj; */ + VOID *pAd = NULL; + struct iwreq *wrqin = (struct iwreq *) rq; + RTMP_IOCTL_INPUT_STRUCT rt_wrq, *wrq = &rt_wrq; +/* BOOLEAN StateMachineTouched = FALSE; */ + INT Status = NDIS_STATUS_SUCCESS; + USHORT subcmd; + UINT32 org_len; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + wrq->u.data.pointer = wrqin->u.data.pointer; + wrq->u.data.length = wrqin->u.data.length; + org_len = wrq->u.data.length; + +/* pObj = (POS_COOKIE) pAd->OS_Cookie; */ + + /*check if the interface is down */ +/* if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + if (wrqin->u.data.pointer == NULL) + { + return Status; + } + + if (cmd != RTPRIV_IOCTL_SET) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + } + + + + switch(cmd) + { + case RTPRIV_IOCTL_ATE: + { + /* + ATE is always controlled by ra0 + */ + RTMP_COM_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_ATE, 0, wrqin->ifr_name, 0); + } + break; + + case SIOCGIFHWADDR: + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n")); +/* memcpy(wrqin->u.name, pAd->CurrentAddress, ETH_ALEN); */ + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIFHWADDR, + 0, wrqin->u.name, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); + break; + case SIOCGIWNAME: + { + char *name=&wrqin->u.name[0]; + rt_ioctl_giwname(net_dev, NULL, name, NULL); + break; + } + case SIOCGIWESSID: /*Get ESSID */ + { + struct iw_point *essid=&wrqin->u.essid; + rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer); + break; + } + case SIOCSIWESSID: /*Set ESSID */ + { + struct iw_point *essid=&wrqin->u.essid; + rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer); + break; + } + case SIOCSIWNWID: /* set network id (the cell) */ + case SIOCGIWNWID: /* get network id */ + Status = -EOPNOTSUPP; + break; + case SIOCSIWFREQ: /*set channel/frequency (Hz) */ + { + struct iw_freq *freq=&wrqin->u.freq; + rt_ioctl_siwfreq(net_dev, NULL, freq, NULL); + break; + } + case SIOCGIWFREQ: /* get channel/frequency (Hz) */ + { + struct iw_freq *freq=&wrqin->u.freq; + rt_ioctl_giwfreq(net_dev, NULL, freq, NULL); + break; + } + case SIOCSIWNICKN: /*set node name/nickname */ + { + /*struct iw_point *data=&wrq->u.data; */ + /*rt_ioctl_siwnickn(net_dev, NULL, data, NULL); */ + break; + } + case SIOCGIWNICKN: /*get node name/nickname */ + { + RT_CMD_STA_IOCTL_NICK_NAME NickName, *pNickName = &NickName; + CHAR nickname[IW_ESSID_MAX_SIZE+1]; + struct iw_point *erq = NULL; + erq = &wrqin->u.data; + + pNickName->NameLen = IW_ESSID_MAX_SIZE+1; + pNickName->pName = (CHAR *)nickname; + RTMP_STA_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCGIWNICKN, 0, + pNickName, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); + + erq->length = pNickName->NameLen; /*strlen((PSTRING) pAd->nickname); */ + Status = copy_to_user(erq->pointer, nickname, erq->length); + break; + } + case SIOCGIWRATE: /*get default bit rate (bps) */ + rt_ioctl_giwrate(net_dev, NULL, &wrqin->u, NULL); + break; + case SIOCSIWRATE: /*set default bit rate (bps) */ + rt_ioctl_siwrate(net_dev, NULL, &wrqin->u, NULL); + break; + case SIOCGIWRTS: /* get RTS/CTS threshold (bytes) */ + { + struct iw_param *rts=&wrqin->u.rts; + rt_ioctl_giwrts(net_dev, NULL, rts, NULL); + break; + } + case SIOCSIWRTS: /*set RTS/CTS threshold (bytes) */ + { + struct iw_param *rts=&wrqin->u.rts; + rt_ioctl_siwrts(net_dev, NULL, rts, NULL); + break; + } + case SIOCGIWFRAG: /*get fragmentation thr (bytes) */ + { + struct iw_param *frag=&wrqin->u.frag; + rt_ioctl_giwfrag(net_dev, NULL, frag, NULL); + break; + } + case SIOCSIWFRAG: /*set fragmentation thr (bytes) */ + { + struct iw_param *frag=&wrqin->u.frag; + rt_ioctl_siwfrag(net_dev, NULL, frag, NULL); + break; + } + case SIOCGIWENCODE: /*get encoding token & mode */ + { + struct iw_point *erq=&wrqin->u.encoding; + if(erq) + rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer); + break; + } + case SIOCSIWENCODE: /*set encoding token & mode */ + { + struct iw_point *erq=&wrqin->u.encoding; + if(erq) + rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer); + break; + } + case SIOCGIWAP: /*get access point MAC addresses */ + { + struct sockaddr *ap_addr=&wrqin->u.ap_addr; + rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + break; + } + case SIOCSIWAP: /*set access point MAC addresses */ + { + struct sockaddr *ap_addr=&wrqin->u.ap_addr; + rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + break; + } + case SIOCGIWMODE: /*get operation mode */ + { + __u32 *mode=&wrqin->u.mode; + rt_ioctl_giwmode(net_dev, NULL, mode, NULL); + break; + } + case SIOCSIWMODE: /*set operation mode */ + { + __u32 *mode=&wrqin->u.mode; + rt_ioctl_siwmode(net_dev, NULL, mode, NULL); + break; + } + case SIOCGIWSENS: /*get sensitivity (dBm) */ + case SIOCSIWSENS: /*set sensitivity (dBm) */ + case SIOCGIWPOWER: /*get Power Management settings */ + case SIOCSIWPOWER: /*set Power Management settings */ + case SIOCGIWTXPOW: /*get transmit power (dBm) */ + case SIOCSIWTXPOW: /*set transmit power (dBm) */ + case SIOCGIWRANGE: /*Get range of parameters */ + case SIOCGIWRETRY: /*get retry limits and lifetime */ + case SIOCSIWRETRY: /*set retry limits and lifetime */ + Status = -EOPNOTSUPP; + break; + + case RT_PRIV_IOCTL: +#ifdef RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT + //YF: Android Private Lib Entry + rt_android_private_command_entry(pAd, net_dev, rq, cmd); + break; +#endif /* RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT */ + + case RT_PRIV_IOCTL_EXT: + subcmd = wrqin->u.data.flags; + + Status = RTMP_STA_IoctlHandle(pAd, wrq, CMD_RT_PRIV_IOCTL, subcmd, + NULL, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); + break; + case SIOCGIWPRIV: + if (wrqin->u.data.pointer) + { + if ( access_ok(VERIFY_WRITE, wrqin->u.data.pointer, sizeof(privtab)) != TRUE) + break; + if ((sizeof(privtab) / sizeof(privtab[0])) <= wrq->u.data.length) + { + wrqin->u.data.length = sizeof(privtab) / sizeof(privtab[0]); + if (copy_to_user(wrqin->u.data.pointer, privtab, sizeof(privtab))) + Status = -EFAULT; + } + else + Status = -E2BIG; + } + break; + case RTPRIV_IOCTL_SET: + if(access_ok(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length) != TRUE) + break; + return rt_ioctl_setparam(net_dev, NULL, NULL, wrqin->u.data.pointer); + break; + case RTPRIV_IOCTL_GSITESURVEY: + RTMP_STA_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SITESURVEY_GET, 0, + NULL, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); +/* RTMPIoctlGetSiteSurvey(pAd, wrq); */ + break; +#ifdef DBG + case RTPRIV_IOCTL_MAC: + RTMP_STA_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_MAC, 0, + NULL, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); +/* RTMPIoctlMAC(pAd, wrq); */ + break; + case RTPRIV_IOCTL_E2P: + RTMP_STA_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_E2P, 0, + NULL, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); +/* RTMPIoctlE2PROM(pAd, wrq); */ + break; +#ifdef RTMP_RF_RW_SUPPORT + case RTPRIV_IOCTL_RF: + RTMP_STA_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_RF, 0, + NULL, 0, RT_DEV_PRIV_FLAGS_GET(net_dev)); +/* RTMPIoctlRF(pAd, wrq); */ + break; +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /* DBG */ + + case SIOCETHTOOL: + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + +/* if(StateMachineTouched) // Upper layer sent a MLME-related operations */ +/* RTMP_MLME_HANDLER(pAd); */ + + if (Status != 0) + { + RT_CMD_STATUS_TRANSLATE(Status); + } + else + { + /* + If wrq length is modified, we reset the lenght of origin wrq; + + Or we can not modify it because the address of wrq->u.data.length + maybe same as other union field, ex: iw_range, etc. + + if the length is not changed but we change it, the value for other + union will also be changed, this is not correct. + */ + if (wrq->u.data.length != org_len) + wrqin->u.data.length = wrq->u.data.length; + } + + return Status; +} + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/vr_bdlt.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/vr_bdlt.c new file mode 100644 index 000000000..f802db09f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/vr_bdlt.c @@ -0,0 +1,63 @@ +/**************************************************************************** + + Module Name: + vr_brlt.c + + Abstract: + Only for BroadLight 2348 platform. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Sample Lin 01-12-2010 Created + +***************************************************************************/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +#define MODULE_BDLT + +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rtmp_osabl.h" + + +#if defined(PLATFORM_BL2348) || defined(PLATFORM_BL23570) + +/* global variables */ +int (*pToUpperLayerPktSent)(struct sk_buff *pSkb) = netif_rx ; + + + + +/* +======================================================================== +Routine Description: + Assign the briding function. + +Arguments: + xi_destination_ptr - bridging function + +Return Value: + None + +Note: + The function name must be replace_upper_layer_packet_destination. +======================================================================== +*/ +VOID replace_upper_layer_packet_destination(VOID *pXiDestination) +{ + DBGPRINT(RT_DEBUG_TRACE, ("ralink broad light> replace_upper_layer_packet_destination\n")); + pToUpperLayerPktSent = pXiDestination ; +} /* End of replace_upper_layer_packet_destination */ + + +EXPORT_SYMBOL(pToUpperLayerPktSent); +EXPORT_SYMBOL(replace_upper_layer_packet_destination); + +#endif /* PLATFORM_BL2348 */ + + +/* End of vr_bdlt.c */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/vr_ikans.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/vr_ikans.c new file mode 100644 index 000000000..e67a1989e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/os/linux/vr_ikans.c @@ -0,0 +1,304 @@ +/**************************************************************************** + + Module Name: + vr_ikans.c + + Abstract: + Only for IKANOS Vx160 or Vx180 platform. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Sample Lin 01-28-2008 Created + +***************************************************************************/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +#define MODULE_IKANOS + +#include "rt_config.h" +#include +#include +#include +#include +#include +#include + + +#ifdef IKANOS_VX_1X0 + +#define IKANOS_PERAP_ID 7 /* IKANOS Fix Peripheral ID */ +#define K0_TO_K1(x) ((unsigned)(x)|0xA0000000) /* kseg0 to kseg1 */ +/*#define IKANOS_DEBUG */ + + +extern INT rt28xx_send_packets(struct sk_buff *skb_p, struct net_device *net_dev); +static INT32 IKANOS_WlanDataFramesTx(void *_pAdBuf, struct net_device *pNetDev); +static void IKANOS_WlanPktFromAp(apPreHeader_t *pFrame); + + +/* --------------------------------- Public -------------------------------- */ + +/* +======================================================================== +Routine Description: + Init IKANOS fast path function. + +Arguments: + pApMac - the MAC of AP + +Return Value: + None + +Note: + If you want to enable RX fast path, you must call the function. +======================================================================== +*/ +void VR_IKANOS_FP_Init(UINT8 BssNum, UINT8 *pApMac) +{ + UINT32 i; + UINT8 mac[6]; + + + memcpy(mac, pApMac, 6); + + /* add all MAC of multiple BSS */ + for(i=0; i WLAN transmit fast path function. + +Arguments: + skb - the transmitted packet (SKB packet format) + netdev - our WLAN network device + +Return Value: + + +Note: +======================================================================== +*/ +INT32 IKANOS_DataFramesTx(struct sk_buff *pSkb, struct net_device *pNetDev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pNetDev->priv; + IkanosWlanTxCbFuncP *fp = &IKANOS_WlanDataFramesTx; + + pSkb->apFlowData.txDev = pNetDev; + pSkb->apFlowData.txApId = IKANOS_PERAP_ID; + pAd->IkanosTxInfo.netdev = pNetDev; + pAd->IkanosTxInfo.fp = fp; + pSkb->apFlowData.txHandle = &(pAd->IkanosTxInfo); + ap2apFlowProcess(pSkb, pNetDev); + +#ifdef IKANOS_DEBUG + printk("ikanos> tx no fp\n"); /* debug use */ +#endif /* IKANOS_DEBUG */ + + return rt28xx_send_packets(pSkb, pNetDev); +} + + +/* +======================================================================== +Routine Description: + Ikanos WLAN --> LAN transmit fast path function. + +Arguments: + pAd - WLAN control block + pRxParam - + pSkb - the transmitted packet (SKB packet format) + Length - packet length + +Return Value: + None + +Note: + Because no unsigned long private parameters in apPreHeader_t can be used, + we use a global variable to record pAd. + So we can not use multiple card function in Ikanos platform. +======================================================================== +*/ +PRTMP_ADAPTER pIkanosAd; +void IKANOS_DataFrameRx(RTMP_ADAPTER *pAd, struct sk_buff *pSkb) +{ + apPreHeader_t *apBuf; + void *pRxParam = pSkb->dev; + UINT32 Length = pSkb->len; + + apBuf = (apPreHeader_t *)(translateMbuf2Apbuf(pSkb, 0)); + apBuf->flags1 = 1 << AP_FLAG1_IS_ETH_BIT; + apBuf->specInfoElement = RTMP_GET_PACKET_NET_DEVICE_MBSSID(pSkb); /* MBSS */ + pIkanosAd = pAd; + + apBuf->flags2 = 0; + + apClassify(IKANOS_PERAP_ID, apBuf, (void *)IKANOS_WlanPktFromAp); + dev_kfree_skb(pSkb); +} + + + +/* --------------------------------- Private -------------------------------- */ + +/* +======================================================================== +Routine Description: + Ikanos LAN --> WLAN transmit fast path function. + +Arguments: + _pAdBuf - the transmitted packet (Ikanos packet format) + netdev - our WLAN network device + +Return Value: + + +Note: +======================================================================== +*/ +static INT32 IKANOS_WlanDataFramesTx(void *_pAdBuf, struct net_device *pNetDev) +{ + apPreHeader_t *pApBuf = (apPreHeader_t *)_pAdBuf; + struct sk_buff *sk = NULL; + + sk = (struct sk_buff *)translateApbuf2Mbuf(pApBuf); + if (sk == NULL) + { + printk("ikanos> translateApbuf2Mbuf returned NULL!\n"); + return 1; + } + + sk->apFlowData.flags2 = 0; + sk->apFlowData.wlanFlags = 0; + sk->protocol = ETH_P_IP; + sk->dev = pNetDev; + sk->priority = 0; + + return rt28xx_send_packets(sk, pNetDev); +} + + +/* +======================================================================== +Routine Description: + Get real interface index, used in get_netdev_from_bssid() + +Arguments: + pAd - + FromWhichBSSID - + +Return Value: + None + +Note: +======================================================================== +*/ +static INT32 GetSpecInfoIdxFromBssid(PRTMP_ADAPTER pAd, INT32 FromWhichBSSID) +{ + INT32 IfIdx = MAIN_MBSSID; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) + { + IfIdx = MAX_MBSSID_NUM(pAd) + MAX_WDS_ENTRY; + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) + { + INT WdsIndex = FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS; + IfIdx = MAX_MBSSID_NUM(pAd) + WdsIndex; + } + else +#endif /* WDS_SUPPORT */ + { + IfIdx = FromWhichBSSID; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + IfIdx = MAIN_MBSSID; + } +#endif /* CONFIG_STA_SUPPORT */ + + return IfIdx; /* return one of MBSS */ +} + + +/* +======================================================================== +Routine Description: + Ikanos WLAN --> LAN transmit fast path function. + +Arguments: + pFrame - the received packet (Ikanos packet format) + +Return Value: + None + +Note: + Ikanos platform supports only 8 VAPs +======================================================================== +*/ +static void IKANOS_WlanPktFromAp(apPreHeader_t *pFrame) +{ + RTMP_ADAPTER *pAd; + struct net_device *dev = NULL; + struct sk_buff *skb; + INT32 index; + apPreHeader_t *apBuf = K0_TO_K1(pFrame); + + + pAd = pIkanosAd; + /*index = apBuf->specInfoElement; */ + /*dev = pAd->ApCfg.MBSSID[index].MSSIDDev; */ + index = GetSpecInfoIdxFromBssid(pAd, apBuf->specInfoElement); + dev = get_netdev_from_bssid(pAd, apBuf->specInfoElement); + if (dev == NULL) + { + printk("ikanos> %s: ERROR null device ***************\n", __FUNCTION__); + return; + } + + skb = (struct sk_buff *)translateApbuf2Mbuf(apBuf); + if (NULL == skb) + { + printk("ikanos> %s: skb is null *********************\n", __FUNCTION__); + return; + } + + pAd->IkanosRxInfo[index].netdev = dev; + pAd->IkanosRxInfo[index].fp = &IKANOS_WlanDataFramesTx; + + skb->dev = dev; + skb->apFlowData.rxApId = IKANOS_PERAP_ID; + /*skb->apFlowData.txHandle = &(txinforx[index]); */ + skb->apFlowData.rxHandle = &(pAd->IkanosRxInfo[index]); + skb->protocol = eth_type_trans(skb, skb->dev); + +#ifdef IKANOS_DEBUG + printk("ikanos> rx no fp!\n"); /* debug use */ +#endif /* IKANOS_DEBUG */ + + netif_rx(skb); + return; +} + +#endif /* IKANOS_VX_1X0 */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/mt_rf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/mt_rf.c new file mode 100644 index 000000000..576eed009 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/mt_rf.c @@ -0,0 +1,121 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_rf.c +*/ + +#include "rt_config.h" + +int mt_rf_write( + RTMP_ADAPTER *ad, + u8 rf_idx, + u16 offset, + u32 data) +{ + u32 i = 0; + u32 value; + int ret = 0; + + + /* rf data */ + RTMP_IO_WRITE32(ad, W_RFDATA, data); + + /* rf control */ + RTMP_IO_READ32(ad, RF_CTRL, &value); + + /* rf address */ + value &= ~RF_ADDR_MASK; + value |= RF_ADDR(offset); + + /* write control */ + value |= RF_R_W_CTRL; + + /* rf index */ + value &= ~RF_IDX_MASK; + value |= RF_IDX(rf_idx); + + RTMP_IO_WRITE32(ad, RF_CTRL, value); + + do { + RTMP_IO_READ32(ad, RF_CTRL, &value); + + if (RF_READY(value)) + break; + i++; + //RtmpOsMsDelay(1); + RtmpusecDelay(50); + //} while ((i < MAX_BUSY_COUNT) && (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))); + } while ((i < MAX_BUSY_COUNT_US) && (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + //if ((i == MAX_BUSY_COUNT) || (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + if ((i == MAX_BUSY_COUNT_US) || (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + ret = STATUS_UNSUCCESSFUL; + } + + + return ret; +} + +int mt_rf_read( + RTMP_ADAPTER *ad, + u8 rf_idx, + u16 offset, + u32 *data) +{ + u32 i = 0; + u32 value; + int ret; + + + /* rf control */ + RTMP_IO_READ32(ad, RF_CTRL, &value); + + /* rf address */ + value &= ~RF_ADDR_MASK; + value |= RF_ADDR(offset); + + /* read control */ + value &= ~RF_R_W_CTRL; + + /* rf index */ + value &= ~RF_IDX_MASK; + value |= RF_IDX(rf_idx); + + RTMP_IO_WRITE32(ad, RF_CTRL, value); + + do { + RTMP_IO_READ32(ad, RF_CTRL, &value); + + if (RF_READY(value)) + break; + i++; + //RtmpOsMsDelay(1); + RtmpusecDelay(50); + //} while ((i < MAX_BUSY_COUNT) && (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))); + } while ((i < MAX_BUSY_COUNT_US) && (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + //if ((i == MAX_BUSY_COUNT) || (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + if ((i == MAX_BUSY_COUNT_US) || (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + ret = STATUS_UNSUCCESSFUL; + goto done; + } + + /* rf data */ + RTMP_IO_READ32(ad, R_RFDATA, data); + +done: + + return ret; +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/phy.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/phy.c new file mode 100644 index 000000000..2dfa989ef --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/phy.c @@ -0,0 +1,181 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +INT phy_probe(RTMP_ADAPTER *pAd) +{ + + return TRUE; +} + + +NDIS_STATUS NICInitBBP(RTMP_ADAPTER *pAd) +{ + UINT32 Index = 0, val; + + /* Before program BBP, we need to wait BBP/RF get wake up.*/ + do + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &val); + if ((val & 0x03) == 0) /* if BB.RF is stable*/ + break; + + DBGPRINT(RT_DEBUG_TRACE, ("Check if MAC_STATUS_CFG is busy(=%x)\n", val)); + RtmpusecDelay(1000); + } while (Index++ < 100); + + if (pAd->phy_op && pAd->phy_op->bbp_init) + return pAd->phy_op->bbp_init(pAd); + else + return NDIS_STATUS_FAILURE; +} + + +INT bbp_get_temp(struct _RTMP_ADAPTER *pAd, CHAR *temp_val) +{ + if (pAd->phy_op && pAd->phy_op->bbp_get_temp) + return pAd->phy_op->bbp_get_temp(pAd, temp_val); + else + return FALSE; +} + + +INT bbp_tx_comp_init(RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode) +{ + if (pAd->phy_op && pAd->phy_op->bbp_tx_comp_init) + return pAd->phy_op->bbp_tx_comp_init(pAd, adc_insel, tssi_mode); + else + return FALSE; +} + + +INT bbp_set_txdac(struct _RTMP_ADAPTER *pAd, INT tx_dac) +{ + if (pAd->phy_op && pAd->phy_op->bbp_set_txdac) + return pAd->phy_op->bbp_set_txdac(pAd, tx_dac); + else + return FALSE; +} + + +INT bbp_set_rxpath(struct _RTMP_ADAPTER *pAd, INT rxpath) +{ + +//DBGPRINT(RT_DEBUG_OFF, ("%s(): rxpath=%d, Set AGC1_R0=0x%x, agc_r0=0x%x\n", __FUNCTION__, rxpath, agc, agc_r0)); +// RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc); +//DBGPRINT(RT_DEBUG_OFF, ("%s(): rxpath=%d, After write, Get AGC1_R0=0x%x,\n", __FUNCTION__, rxpath, agc)); + + if (pAd->phy_op && pAd->phy_op->bbp_set_rxpath) + return pAd->phy_op->bbp_set_rxpath(pAd, rxpath); + else + return FALSE; +} + + +INT bbp_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch) +{ + if (pAd->phy_op && pAd->phy_op->bbp_set_ctrlch) + return pAd->phy_op->bbp_set_ctrlch(pAd, ext_ch); + else + return FALSE; +} + + +INT bbp_set_bw(struct _RTMP_ADAPTER *pAd, UINT8 bw) +{ + INT result = FALSE; + + if (pAd->phy_op && pAd->phy_op->bbp_set_bw) + result = pAd->phy_op->bbp_set_bw(pAd, bw); + + if (result == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set PhyBW as %sHz.l\n", + __FUNCTION__, get_bw_str(bw))); + } + + return result; +} + + +INT bbp_set_mmps(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower) +{ + if (pAd->phy_op && pAd->phy_op->bbp_set_mmps) + return pAd->phy_op->bbp_set_mmps(pAd, ReduceCorePower); + else + return FALSE; +} + + +INT bbp_get_agc(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX chain) +{ + if (pAd->phy_op && pAd->phy_op->bbp_get_agc) + return pAd->phy_op->bbp_get_agc(pAd, agc, chain); + else + return FALSE; +} + + +INT bbp_set_agc(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX chain) +{ + if (pAd->phy_op && pAd->phy_op->bbp_set_agc) + return pAd->phy_op->bbp_set_agc(pAd, agc, chain); + else + return FALSE; +} + + +INT filter_coefficient_ctrl(RTMP_ADAPTER *pAd, UCHAR Channel) +{ + if (pAd->phy_op && pAd->phy_op->filter_coefficient_ctrl) + return pAd->phy_op->filter_coefficient_ctrl(pAd, Channel); + else + return FALSE; +} + + +UCHAR get_random_seed_by_phy(RTMP_ADAPTER *pAd) +{ + if (pAd->phy_op && pAd->phy_op->get_random_seed_by_phy) + return pAd->phy_op->get_random_seed_by_phy(pAd); + else + return 0; +} + + +INT bbp_is_ready(struct _RTMP_ADAPTER *pAd) +{ + if (pAd->phy_op && pAd->phy_op->bbp_is_ready) + return pAd->phy_op->bbp_is_ready(pAd); + else + return FALSE; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rf.c new file mode 100644 index 000000000..34aa7385a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rf.c @@ -0,0 +1,26 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + rf.c +*/ + +#include "rt_config.h" + +VOID InitRFRegisters( + IN RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Init RF Registers\n", __FUNCTION__)); + if (pAd->chipOps.AsicRfInit) + pAd->chipOps.AsicRfInit(pAd); +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rlt_phy.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rlt_phy.c new file mode 100644 index 000000000..626213752 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rlt_phy.c @@ -0,0 +1,480 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +#ifdef RLT_BBP + +static INT rlt_bbp_is_ready(struct _RTMP_ADAPTER *pAd) +{ + INT idx = 0; + UINT32 val; + + do + { + RTMP_BBP_IO_READ32(pAd, CORE_R0, &val); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + } while ((++idx < 20) && ((val == 0xffffffff) || (val == 0x0))); + + if (!((val == 0xffffffff) || (val == 0x0))) + { + DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", val)); + } + + return (((val == 0xffffffff) || (val == 0x0)) ? FALSE : TRUE); +} + + +static INT rlt_bbp_init(RTMP_ADAPTER *pAd) +{ + INT idx; + + /* Read BBP register, make sure BBP is up and running before write new data*/ + if (rlt_bbp_is_ready(pAd) == FALSE) + return NDIS_STATUS_FAILURE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Init BBP Registers\n", __FUNCTION__)); + + /* re-config specific BBP registers for individual chip */ + if (pAd->chipCap.pBBPRegTable) + { + RTMP_REG_PAIR *reg = (RTMP_REG_PAIR *)pAd->chipCap.pBBPRegTable; + + for (idx = 0; idx < pAd->chipCap.bbpRegTbSize; idx++) + { + RTMP_BBP_IO_WRITE32(pAd, reg[idx].Register, reg[idx].Value); + DBGPRINT(RT_DEBUG_INFO, ("BBP[%x]=0x%x\n", + reg[idx].Register, reg[idx].Value)); + } + } + + if (pAd->chipOps.AsicBbpInit != NULL) + pAd->chipOps.AsicBbpInit(pAd); + + // TODO: shiang-6590, check these bbp registers if need to remap to new BBP_Registers + + return NDIS_STATUS_SUCCESS; + +} + + +static INT rlt_bbp_get_temp(struct _RTMP_ADAPTER *pAd, CHAR *temp_val) +{ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + UINT32 bbp_val; + + RTMP_BBP_IO_READ32(pAd, CORE_R35, &bbp_val); + *temp_val = (CHAR)(bbp_val & 0xff); + + pAd->curr_temp = (bbp_val & 0xff); +#endif + return TRUE; +} + + +static INT rlt_bbp_tx_comp_init(RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode) +{ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + UINT32 bbp_val; + UCHAR rf_val; + + RTMP_BBP_IO_READ32(pAd, CORE_R34, &bbp_val); + bbp_val = (bbp_val & 0xe7); + bbp_val = (bbp_val | 0x80); + RTMP_BBP_IO_WRITE32(pAd, CORE_R34, bbp_val); + + RT30xxReadRFRegister(pAd, RF_R27, &rf_val); + rf_val = ((rf_val & 0x3f) | 0x40); + RT30xxWriteRFRegister(pAd, RF_R27, rf_val); + + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] Set RF_R27 to 0x%x\n", rf_val)); +#endif + return 0; +} + + +static INT rlt_bbp_set_txdac(struct _RTMP_ADAPTER *pAd, INT tx_dac) +{ + UINT32 txbe, txbe_r5 = 0; + + RTMP_BBP_IO_READ32(pAd, TXBE_R5, &txbe_r5); + txbe = txbe_r5 & (~0x3); + switch (tx_dac) + { + case 2: + txbe |= 0x3; + break; + case 1: + case 0: + default: + txbe &= (~0x3); + break; + } + + if (txbe != txbe_r5) + RTMP_BBP_IO_WRITE32(pAd, TXBE_R5, txbe); + + return TRUE; +} + + +static INT rlt_bbp_set_rxpath(struct _RTMP_ADAPTER *pAd, INT rxpath) +{ + UINT32 agc, agc_r0 = 0; + + RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc_r0); + agc = agc_r0 & (~0x18); + if(rxpath == 2) + agc |= (0x8); + else if(rxpath == 1) + agc |= (0x0); + +#ifdef RT8592 + if (IS_RT8592(pAd)) + agc |= (0x8); +#endif /* RT8592 */ + + if (agc != agc_r0) + RTMP_BBP_IO_WRITE32(pAd, AGC1_R0, agc); + +//DBGPRINT(RT_DEBUG_OFF, ("%s(): rxpath=%d, Set AGC1_R0=0x%x, agc_r0=0x%x\n", __FUNCTION__, rxpath, agc, agc_r0)); +// RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc); +//DBGPRINT(RT_DEBUG_OFF, ("%s(): rxpath=%d, After write, Get AGC1_R0=0x%x,\n", __FUNCTION__, rxpath, agc)); + + return TRUE; +} + + +static INT rlt_bbp_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch) +{ + UINT32 agc, agc_r0 = 0; + UINT32 be, be_r0 = 0; + + RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc_r0); + agc = agc_r0 & (~0x300); + RTMP_BBP_IO_READ32(pAd, TXBE_R0, &be_r0); + be = (be_r0 & (~0x03)); +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW == BW_80 && + pAd->CommonCfg.Channel >= 36 && + pAd->CommonCfg.vht_cent_ch) + { + if (pAd->CommonCfg.Channel < pAd->CommonCfg.vht_cent_ch) + { + switch (pAd->CommonCfg.vht_cent_ch - pAd->CommonCfg.Channel) + { + case 6: + be |= 0; + agc |=0x000; + break; + case 2: + be |= 1; + agc |=0x100; + break; + + } + } + else if (pAd->CommonCfg.Channel > pAd->CommonCfg.vht_cent_ch) + { + switch (pAd->CommonCfg.Channel - pAd->CommonCfg.vht_cent_ch) + { + case 6: + be |= 0x3; + agc |=0x300; + break; + case 2: + be |= 0x2; + agc |=0x200; + break; + } + } + } + else +#endif /* DOT11_VHT_AC */ + { + switch (ext_ch) + { + case EXTCHA_BELOW: + agc |= 0x100; + be |= 0x01; + break; + case EXTCHA_ABOVE: + agc &= (~0x300); + be &= (~0x03); + break; + case EXTCHA_NONE: + default: + agc &= (~0x300); + be &= (~0x03); + break; + } + } + if (agc != agc_r0) + RTMP_BBP_IO_WRITE32(pAd, AGC1_R0, agc); + + if (be != be_r0) + RTMP_BBP_IO_WRITE32(pAd, TXBE_R0, be); + +#ifdef RT8592 + //+++ BBP update:0921e3 + // TODO: shiang, move this code segment to other place! + if (IS_RT8592(pAd)) { + UINT32 mac_val[4] = {0xf1e4, 0xf2e1, 0xf41e, 0xf81b}; /* primary 0~3 */ + + RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc); + RTMP_IO_WRITE32(pAd, EXT_CCA_CFG, mac_val[agc & 0x3]); /* IC default value = 0xffe4 */ + } +#endif /* RT8592 */ + +//DBGPRINT(RT_DEBUG_OFF, ("%s(): ext_ch=%d, Set AGC1_R0=0x%x, agc_r0=0x%x\n", __FUNCTION__, ext_ch, agc, agc_r0)); +// RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc); +//DBGPRINT(RT_DEBUG_OFF, ("%s(): ext_ch=%d, After write, Get AGC1_R0=0x%x,\n", __FUNCTION__, ext_ch, agc)); + + return TRUE; +} + + +/* + <> + BBP bandwidth (CORE_R1[4:3]) change procedure: + 1. Hold BBP in reset by setting CORE_R4[0] to '1' + 2. Wait 0.5 us to ensure BBP is in the idle State + 3. Change BBP bandwidth with CORE_R1[4:3] + CORE_R1 (Bit4:3) + 0: 20MHz + 1: 10MHz (11J) + 2: 40MHz + 3: 80MHz + 4. Wait 0.5 us for BBP clocks to settle + 5. Release BBP from reset by clearing CORE_R4[0] +*/ +static INT rlt_bbp_set_bw(struct _RTMP_ADAPTER *pAd, UINT8 bw) +{ + UINT32 core, core_r1 = 0; + UINT32 agc, agc_r0 = 0; + + + + RTMP_BBP_IO_READ32(pAd, CORE_R1, &core_r1); + core = (core_r1 & (~0x18)); + RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc_r0); + agc = agc_r0 & (~0x7000); + switch (bw) + { + case BW_80: + core |= 0x18; + agc |= 0x7000; + break; + case BW_40: + core |= 0x10; + agc |= 0x3000; + break; + case BW_20: + core &= (~0x18); + agc |= 0x1000; + break; + case BW_10: + core |= 0x08; + agc |= 0x1000; + break; + } + +#ifdef RT8592 + if (IS_RT8592(pAd)) + core |= 0x2; // BBP update:0921e3 +#endif /* RT8592 */ + + if (core != core_r1) { + RTMP_BBP_IO_WRITE32(pAd, CORE_R1, core); + } + + if (agc != agc_r0) { + RTMP_BBP_IO_WRITE32(pAd, AGC1_R0, agc); +//DBGPRINT(RT_DEBUG_OFF, ("%s(): bw=%d, Set AGC1_R0=0x%x, agc_r0=0x%x\n", __FUNCTION__, bw, agc, agc_r0)); +// RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc); +//DBGPRINT(RT_DEBUG_OFF, ("%s(): bw=%d, After write, Get AGC1_R0=0x%x,\n", __FUNCTION__, bw, agc)); + } + + pAd->CommonCfg.BBPCurrentBW = bw; + + + return TRUE; +} + + +static INT rlt_bbp_set_mmps(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower) +{ + UINT32 bbp_val, org_val; + + RTMP_BBP_IO_READ32(pAd, AGC1_R0, &org_val); + bbp_val = org_val; + if (ReduceCorePower) + bbp_val |= 0x04; + else + bbp_val &= ~0x04; + + if (bbp_val != org_val) + RTMP_BBP_IO_WRITE32(pAd, AGC1_R0, bbp_val); + + return TRUE; +} + + +static INT rlt_bbp_get_agc(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX chain) +{ + UCHAR idx, val; + UINT32 bbp_val, bbp_reg = AGC1_R8; + + + if (((pAd->MACVersion & 0xffff0000) < 0x28830000) || + (pAd->Antenna.field.RxPath == 1)) + { + chain = RX_CHAIN_0; + } + + idx = val = 0; + while(chain != 0) + { + if (idx >= pAd->Antenna.field.RxPath) + break; + + if (chain & 0x01) + { + RTMP_BBP_IO_READ32(pAd, bbp_reg, &bbp_val); + val = ((bbp_val & (0x0000ff00)) >> 8) & 0xff; + break; + } + chain >>= 1; + bbp_reg += 4; + idx++; + } + + *agc = val; + + return NDIS_STATUS_SUCCESS; +} + + +static INT rlt_bbp_set_agc(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX chain) +{ + UCHAR idx = 0; + UINT32 bbp_val, bbp_reg = AGC1_R8; + + if (((pAd->MACVersion & 0xf0000000) < 0x28830000) || + (pAd->Antenna.field.RxPath == 1)) + { + chain = RX_CHAIN_0; + } + + while (chain != 0) + { + if (idx >= pAd->Antenna.field.RxPath) + break; + + if (idx & 0x01) + { + RTMP_BBP_IO_READ32(pAd, bbp_reg, &bbp_val); + bbp_val = (bbp_val & 0xffff00ff) | (agc << 8); + RTMP_BBP_IO_WRITE32(pAd, bbp_reg, bbp_val); + + DBGPRINT(RT_DEBUG_INFO, + ("%s(Idx):Write(R%d,val:0x%x) to Chain(0x%x, idx:%d)\n", + __FUNCTION__, bbp_reg, bbp_val, chain, idx)); + } + chain >>= 1; + bbp_reg += 4; + idx++; + } + + return TRUE; +} + + +static INT rlt_bbp_set_filter_coefficient_ctrl(RTMP_ADAPTER *pAd, UCHAR Channel) +{ + UINT32 bbp_val = 0, org_val = 0; + + if (Channel == 14) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + RTMP_BBP_IO_READ32(pAd, CORE_R1, &org_val); + bbp_val = org_val; + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + bbp_val |= 0x20; + else + bbp_val &= (~0x20); + + if (bbp_val != org_val) + RTMP_BBP_IO_WRITE32(pAd, CORE_R1, bbp_val); + } + + return TRUE; +} + + +static UCHAR rlt_bbp_get_random_seed(RTMP_ADAPTER *pAd) +{ + UINT32 value, value2; + UCHAR seed; + + RTMP_BBP_IO_READ32(pAd, AGC1_R16, &value); + seed = (UCHAR)((value & 0xff) ^ ((value & 0xff00) >> 8)^ + ((value & 0xff0000) >> 16)); + RTMP_BBP_IO_READ32(pAd, RXO_R9, &value2); + + return (UCHAR)(seed ^ (value2 & 0xff)^ ((value2 & 0xff00) >> 8)); +} + + +static struct phy_ops rlt_phy_ops = { + .bbp_init = rlt_bbp_init, + .bbp_is_ready = rlt_bbp_is_ready, + .get_random_seed_by_phy = rlt_bbp_get_random_seed, + .filter_coefficient_ctrl = rlt_bbp_set_filter_coefficient_ctrl, + .bbp_set_agc = rlt_bbp_set_agc, + .bbp_get_agc = rlt_bbp_get_agc, + .bbp_set_bw = rlt_bbp_set_bw, + .bbp_set_ctrlch = rlt_bbp_set_ctrlch, + .bbp_set_rxpath = rlt_bbp_set_rxpath, + .bbp_set_txdac = rlt_bbp_set_txdac, + .bbp_set_mmps = rlt_bbp_set_mmps, + .bbp_tx_comp_init = rlt_bbp_tx_comp_init, + .bbp_get_temp = rlt_bbp_get_temp, +}; + + +INT rlt_phy_probe(RTMP_ADAPTER *pAd) +{ + pAd->phy_op = &rlt_phy_ops; + + return TRUE; +} + +#endif /* RLT_BBP */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rlt_rf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rlt_rf.c new file mode 100644 index 000000000..1ea0a6941 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rlt_rf.c @@ -0,0 +1,253 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifdef RLT_RF + +#include "rt_config.h" + + +static inline BOOLEAN rf_csr_poll_idle(RTMP_ADAPTER *pAd, UINT32 *rfcsr) +{ + RF_CSR_CFG_STRUC *csr_val; + BOOLEAN idle = BUSY; + INT i = 0; + + do + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + break; + + RTMP_IO_READ32(pAd, RF_CSR_CFG, rfcsr); + + csr_val = (RF_CSR_CFG_STRUC *)rfcsr; +#ifdef RT6352 + if (IS_RT6352(pAd)) + idle = csr_val->bank_6352.RF_CSR_KICK; + else +#endif /* RT6352 */ +#ifdef RT65xx + if (IS_RT65XX(pAd)) + idle = csr_val->bank_65xx.RF_CSR_KICK; + else +#endif /* RT65xx */ + idle = csr_val->non_bank.RF_CSR_KICK; + + if (idle == IDLE) + break; + + i++; + } while (i < MAX_BUSY_COUNT); + + if ((i == MAX_BUSY_COUNT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed(cnt=%d)!\n", i)); + } + + return idle; +} + + +NDIS_STATUS rlt_rf_write( + IN PRTMP_ADAPTER pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + NDIS_STATUS ret; + + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("rlt_rf_write. Not allow to write RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + +#ifdef RLT_MAC + // TODO: shiang-usw, why we need to check this for MT7601?? Get these code from MT7601! + if (pAd->chipCap.hif_type == HIF_RLT) { + if (pAd->WlanFunCtrl.field.WLAN_EN == 0) + { + DBGPRINT_ERR(("rlt_rf_write. Not allow to write RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } + } +#endif /* RLT_MAC */ + + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + ret = STATUS_UNSUCCESSFUL; + if (rf_csr_poll_idle(pAd, &rfcsr.word) != IDLE) + goto done; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + rfcsr.bank_6352.RF_CSR_WR = 1; + rfcsr.bank_6352.RF_CSR_KICK = 1; + rfcsr.bank_6352.TESTCSR_RFACC_REGNUM = (regID | (bank << 6)); + rfcsr.bank_6352.RF_CSR_DATA = value; + } + else +#endif /* RT6352 */ +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + rfcsr.bank_65xx.RF_CSR_WR = 1; + rfcsr.bank_65xx.RF_CSR_KICK = 1; + rfcsr.bank_65xx.RF_CSR_REG_BANK = bank; + rfcsr.bank_65xx.RF_CSR_REG_ID = regID; + rfcsr.bank_65xx.RF_CSR_DATA = value; + } + else +#endif /* RT65xx */ + { + DBGPRINT_ERR(("%s():RF write with wrong handler!\n", __FUNCTION__)); + goto done; + } + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + ret = NDIS_STATUS_SUCCESS; + +done: + + return ret; +} + + +/* + ======================================================================== + + Routine Description: Read RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS rlt_rf_read( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR *pValue) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UINT i=0, k=0; + BOOLEAN rf_status; + NDIS_STATUS ret = STATUS_UNSUCCESSFUL; + + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("RT30xxReadRFRegister. Not allow to read RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + rfcsr.word = 0; + + for (i=0; iMACVersion)); + break; + } + + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + rf_status = rf_csr_poll_idle(pAd, &rfcsr.word); + if (rf_status == IDLE) + { +#ifdef RT6352 + if (IS_RT6352(pAd) && ((rfcsr.bank_6352.TESTCSR_RFACC_REGNUM & 0x3F) == regID)) + { + *pValue = (UCHAR)(rfcsr.bank_6352.RF_CSR_DATA); + break; + } +#endif /* RT6352 */ +#ifdef RT65xx + if (IS_RT65XX(pAd) && (rfcsr.bank_65xx.RF_CSR_REG_ID == regID) && + (rfcsr.bank_65xx.RF_CSR_REG_BANK == bank)) + { + *pValue = (UCHAR)(rfcsr.bank_65xx.RF_CSR_DATA); + break; + } +#endif /* RT65xx */ + } + } + + if (rf_status == BUSY) + { + DBGPRINT_ERR(("RF read R%d=0x%X fail, i[%d], k[%d]\n", regID, rfcsr.word,i,k)); + goto done; + } + ret = STATUS_SUCCESS; + +done: + + return ret; +} + +#endif /* RLT_RF */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rt_rf.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rt_rf.c new file mode 100644 index 000000000..0d4ffc1fe --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rt_rf.c @@ -0,0 +1,634 @@ +/* + *************************************************************************** + * 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_rf.c + + Abstract: + Ralink Wireless driver RF related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +#ifdef RTMP_RF_RW_SUPPORT +/* + ======================================================================== + + Routine Description: Read RF register through MAC with specified bit mask + + Arguments: + pAd - pointer to the adapter structure + regID - RF register ID + pValue1 - (RF value & BitMask) + pValue2 - (RF value & (~BitMask)) + BitMask - bit wise mask + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMP_ReadRF( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + OUT PUCHAR pValue1, + OUT PUCHAR pValue2, + IN UCHAR BitMask) +{ + UCHAR RfReg = 0; + RT30xxReadRFRegister(pAd, RegID, &RfReg); + if (pValue1 != NULL) + *pValue1 = RfReg & BitMask; + if (pValue2 != NULL) + *pValue2 = RfReg & (~BitMask); +} + +/* + ======================================================================== + + Routine Description: Write RF register through MAC with specified bit mask + + Arguments: + pAd - pointer to the adapter structure + regID - RF register ID + Value - only write the part of (Value & BitMask) to RF register + BitMask - bit wise mask + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMP_WriteRF( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + IN UCHAR Value, + IN UCHAR BitMask) +{ + UCHAR RfReg = 0; + RTMP_ReadRF(pAd, RegID, NULL, &RfReg, BitMask); + RfReg |= ((Value) & BitMask); + RT30xxWriteRFRegister(pAd, RegID, RfReg); +} + +/* + ======================================================================== + + Routine Description: Write RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS RT30xxWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR regID, + IN UCHAR value) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UINT i = 0; + NDIS_STATUS ret; + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("RT30xxWriteRFRegister. Not allow to write RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + + ret = STATUS_UNSUCCESSFUL; + do + { + RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); + + if (!rfcsr.non_bank.RF_CSR_KICK) + break; + i++; + } + while ((i < MAX_BUSY_COUNT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == MAX_BUSY_COUNT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s():RF Write failed(RetryCnt=%d, DevNotExistFlag=%d)\n", + __FUNCTION__, i, RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + goto done; + } + + rfcsr.non_bank.RF_CSR_WR = 1; + rfcsr.non_bank.RF_CSR_KICK = 1; + rfcsr.non_bank.TESTCSR_RFACC_REGNUM = regID; + + if ((pAd->chipCap.RfReg17WtMethod == RF_REG_WT_METHOD_STEP_ON) && (regID == RF_R17)) + { + UCHAR IdRf; + UCHAR RfValue; + BOOLEAN beAdd; + + RT30xxReadRFRegister(pAd, RF_R17, &RfValue); + beAdd = (RfValue < value) ? TRUE : FALSE; + IdRf = RfValue; + while(IdRf != value) + { + if (beAdd) + IdRf++; + else + IdRf--; + + rfcsr.non_bank.RF_CSR_DATA = IdRf; + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + RtmpOsMsDelay(1); + } + } + + rfcsr.non_bank.RF_CSR_DATA = value; + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + ret = NDIS_STATUS_SUCCESS; + +done: + + return ret; +} + + +/* + ======================================================================== + + Routine Description: Read RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS RT30xxReadRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR regID, + IN PUCHAR pValue) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UINT i=0, k=0; + NDIS_STATUS ret = STATUS_UNSUCCESSFUL; + + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("RT30xxReadRFRegister. Not allow to read RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + + for (i=0; ibPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("RT635xWriteRFRegister. Not allow to write RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + if (regID > pAd->chipCap.MaxNumOfRfId) + { + DBGPRINT(RT_DEBUG_ERROR, ("RegID=%d, pAd->chipCap.MaxNumOfRfId=%d\n", regID, pAd->chipCap.MaxNumOfRfId)); + } + + ret = STATUS_UNSUCCESSFUL; + do + { + RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); + + if (!rfcsr.bank_6352.RF_CSR_KICK) + break; + i++; + } + while ((i < MAX_BUSY_COUNT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == MAX_BUSY_COUNT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + goto done; + } + + rfcsr.bank_6352.RF_CSR_WR = 1; + rfcsr.bank_6352.RF_CSR_KICK = 1; + rfcsr.bank_6352.TESTCSR_RFACC_REGNUM = (regID | (bank << 6)); + + + rfcsr.bank_6352.RF_CSR_DATA = value; + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + ret = NDIS_STATUS_SUCCESS; + +done: + + return ret; +} + + +/* + ======================================================================== + + Routine Description: Read RT30xx RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS RT635xReadRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR bank, + IN UCHAR regID, + IN PUCHAR pValue) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UINT i=0, k=0; + NDIS_STATUS ret = STATUS_UNSUCCESSFUL; + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("%s():Not allow to read RF 0x%x : fail\n", __FUNCTION__, regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + if (regID > pAd->chipCap.MaxNumOfRfId) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():RegID=%d, MaxNumOfRfId=%d\n", + __FUNCTION__, regID, pAd->chipCap.MaxNumOfRfId)); + } + + for (i=0; ibank_6352.RF_CSR_KICK; + else +#endif /* RT6352 */ + idle = csr_val->non_bank.RF_CSR_KICK; + + if (idle == IDLE) + break; + + i++; + } while (i < MAX_BUSY_COUNT); + + if ((i == MAX_BUSY_COUNT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed(cnt=%d)!\n", i)); + } + + return idle; +} + + +NDIS_STATUS rtmp_rf_write( + IN PRTMP_ADAPTER pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + NDIS_STATUS ret; + + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("rtmp_rf_write. Not allow to write RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + ret = STATUS_UNSUCCESSFUL; + if (rtmp_rf_csr_poll_idle(pAd, &rfcsr.word) != IDLE) + goto done; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + rfcsr.bank_6352.RF_CSR_WR = 1; + rfcsr.bank_6352.RF_CSR_KICK = 1; + rfcsr.bank_6352.TESTCSR_RFACC_REGNUM = (regID | (bank << 6)); + rfcsr.bank_6352.RF_CSR_DATA = value; + } + else +#endif /* RT6352 */ + { + DBGPRINT_ERR(("%s():RF write with wrong handler!\n", __FUNCTION__)); + goto done; + } + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + ret = NDIS_STATUS_SUCCESS; + +done: + + return ret; +} + + +/* + ======================================================================== + + Routine Description: Read RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS rtmp_rf_read( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR *pValue) +{ + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UINT i=0, k=0; + BOOLEAN rf_status; + NDIS_STATUS ret = STATUS_UNSUCCESSFUL; + + +#ifdef RTMP_MAC_PCI + if ((pAd->bPCIclkOff == TRUE) || (pAd->LastMCUCmd == SLEEP_MCU_CMD)) + { + DBGPRINT_ERR(("rtmp_rf_read. Not allow to read RF 0x%x : fail\n", regID)); + return STATUS_UNSUCCESSFUL; + } +#endif /* RTMP_MAC_PCI */ + + + ASSERT((regID <= pAd->chipCap.MaxNumOfRfId)); + + rfcsr.word = 0; + + for (i=0; iMACVersion)); + break; + } + + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + rf_status = rtmp_rf_csr_poll_idle(pAd, &rfcsr.word); + if (rf_status == IDLE) + { +#ifdef RT6352 + if (IS_RT6352(pAd) && ((rfcsr.bank_6352.TESTCSR_RFACC_REGNUM & 0x3F) == regID)) + { + *pValue = (UCHAR)(rfcsr.bank_6352.RF_CSR_DATA); + break; + } +#endif /* RT6352 */ + } + } + + if (rf_status == BUSY) + { + DBGPRINT_ERR(("RF read R%d=0x%X fail, i[%d], k[%d]\n", regID, rfcsr.word,i,k)); + goto done; + } + ret = STATUS_SUCCESS; + +done: + + return ret; +} +#endif /* RT6352 */ + +/* + ======================================================================== + Routine Description: + Adjust frequency offset when do channel switching or frequency calabration. + + Arguments: + pAd - Adapter pointer + pRefFreqOffset in: referenced Frequency offset out: adjusted frequency offset + + Return Value: + None + + ======================================================================== +*/ +BOOLEAN RTMPAdjustFrequencyOffset(RTMP_ADAPTER *pAd,UCHAR *pRefFreqOffset) +{ + BOOLEAN RetVal = TRUE; + UCHAR RFValue = 0; + UCHAR PreRFValue = 0; + UCHAR FreqOffset = 0; + UCHAR HighCurrentBit = 0; + + RTMP_ReadRF(pAd, RF_R17, &FreqOffset, &HighCurrentBit, 0x7F); + PreRFValue = HighCurrentBit | FreqOffset; + FreqOffset = min((*pRefFreqOffset & 0x7F), 0x5F); + RFValue = HighCurrentBit | FreqOffset; + if (PreRFValue != RFValue) + { + RetVal = (RT30xxWriteRFRegister(pAd, RF_R17, RFValue) == STATUS_SUCCESS ? TRUE:FALSE); + } + + if (RetVal == FALSE) + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Error in tuning frequency offset !!\n", __FUNCTION__)); + else + *pRefFreqOffset = FreqOffset; + + return RetVal; + +} + +#endif /* RTMP_RF_RW_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rtmp_phy.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rtmp_phy.c new file mode 100644 index 000000000..9b08ddec7 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/phy/rtmp_phy.c @@ -0,0 +1,802 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + + +#include "rt_config.h" + + + +#ifdef RTMP_BBP +#ifdef RTMP_MAC_PCI +VOID RTMP_BBP_IO_READ8( + PRTMP_ADAPTER pAd, + UCHAR bbp_id, + UINT8 *pValue, + BOOLEAN bViaMCU) +{ + BBP_CSR_CFG_STRUC BbpCsr; + int _busyCnt, _secCnt, _regID; + ULONG __IrqFlags = 0; + +#ifdef RT65xx + if (IS_RT65XX(pAd)) + return; +#endif /* RT65xx */ + + + if ((bViaMCU) == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(pAd, __IrqFlags); + + _regID = ((bViaMCU) == TRUE ? H2M_BBP_AGENT : BBP_CSR_CFG); + for (_busyCnt=0; _busyCntBbpWriteLatch[bbp_id]; + if (bViaMCU == TRUE) + { + RTMP_IO_READ32(pAd, _regID, &BbpCsr.word); + BbpCsr.field.Busy = 0; + RTMP_IO_WRITE32(pAd, _regID, BbpCsr.word); + } + } + + if (bViaMCU == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, __IrqFlags); +} + + +VOID RTMP_BBP_IO_WRITE8( + RTMP_ADAPTER *pAd, + UCHAR bbp_id, + UINT8 Value, + BOOLEAN bViaMCU) +{ + BBP_CSR_CFG_STRUC BbpCsr; + int _busyCnt=0, _regID; + BOOLEAN brc; + ULONG __IrqFlags = 0; + +#ifdef RT65xx + if (IS_RT65XX(pAd)) + return; +#endif /* RT65xx */ + + + if (bViaMCU == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(pAd, __IrqFlags); + + _regID = (bViaMCU == TRUE ? H2M_BBP_AGENT : BBP_CSR_CFG); + for (_busyCnt=1; _busyCntOpMode == OPMODE_AP) + RtmpusecDelay(1000); + if (brc == FALSE) + { + BbpCsr.field.Busy = IDLE; + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); + } + } + pAd->BbpWriteLatch[bbp_id] = Value; + break; + } + if (_busyCnt == MAX_BUSY_COUNT) + { + DBGPRINT_ERR(("BBP write R%d fail\n", bbp_id)); + if(bViaMCU == TRUE) + { + RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); + BbpCsr.field.Busy = 0; + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); + } + } + if (bViaMCU == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, __IrqFlags); + +} +#endif /* RTMP_MAC_PCI */ + + +NTSTATUS RTMP_BBP_IO_READ8_BY_REG_ID( + RTMP_ADAPTER *pAd, + UINT32 Offset, + UINT8 *pValue) +{ +#ifdef RT65xx + if (IS_RT65XX(pAd)) + return STATUS_UNSUCCESSFUL; +#endif /* RT65xx */ + + +#ifdef RTMP_MAC_PCI +/* + This marco used for the BBP read operation which need via MCU. + But for some chipset which didn't have mcu (e.g., RBUS based chipset), we + will use this function too and didn't access the bbp register via the MCU. +*/ + if ((pAd)->bPCIclkOff == FALSE) + { + if ((pAd)->infType == RTMP_DEV_INF_RBUS) + RTMP_BBP_IO_READ8((pAd), (Offset), (pValue), FALSE); + else + if(IS_SUPPORT_PCIE_PS_L3((pAd))) + RTMP_PCIE_PS_L3_BBP_IO_READ8((pAd), (Offset), (pValue), TRUE); + else + RTMP_BBP_IO_READ8((pAd), (Offset), (pValue), TRUE); + } + + return STATUS_SUCCESS; +#endif /* RTMP_MAC_PCI */ +} + + +NTSTATUS RTMP_BBP_IO_WRITE8_BY_REG_ID( + RTMP_ADAPTER *pAd, + UINT32 Offset, + UINT8 Value) +{ +#ifdef RT65xx + if (IS_RT65XX(pAd)) + return STATUS_UNSUCCESSFUL; +#endif /* RT65xx */ + + +#ifdef RTMP_MAC_PCI +/* + This marco used for the BBP write operation which need via MCU. + But for some chipset which didn't have mcu (e.g., RBUS based chipset), we + will use this function too and didn't access the bbp register via the MCU. +*/ + if ((pAd)->bPCIclkOff == FALSE) + { + if ((pAd)->infType == RTMP_DEV_INF_RBUS) + RTMP_BBP_IO_WRITE8(pAd, Offset, Value, FALSE); + else + if(IS_SUPPORT_PCIE_PS_L3(pAd)) + RTMP_PCIE_PS_L3_BBP_IO_WRITE8(pAd, Offset, Value, TRUE); + else + RTMP_BBP_IO_WRITE8(pAd, Offset, Value, TRUE); + } + + return STATUS_SUCCESS; +#endif /* RTMP_MAC_PCI */ +} + + +/* BBP register initialization set*/ +REG_PAIR BBPRegTable[] = { + {BBP_R65, 0x2C}, /* fix rssi issue*/ + {BBP_R66, 0x38}, /* Also set this default value to pAd->BbpTuning.R66CurrentValue at initial*/ + {BBP_R68, 0x0B}, /* improve Rx sensitivity. */ + {BBP_R69, 0x12}, + {BBP_R70, 0xa}, /* BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa*/ + {BBP_R73, 0x10}, + {BBP_R81, 0x37}, + {BBP_R82, 0x62}, + {BBP_R83, 0x6A}, + {BBP_R84, 0x99}, /* 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before*/ + {BBP_R86, 0x00}, /* middle range issue, Rory @2008-01-28 */ + {BBP_R91, 0x04}, /* middle range issue, Rory @2008-01-28*/ + {BBP_R92, 0x00}, /* middle range issue, Rory @2008-01-28*/ + {BBP_R103, 0x00}, /* near range high-power issue, requested from Gary @2008-0528*/ + {BBP_R105, 0x05}, /* 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before.*/ +#ifdef DOT11_N_SUPPORT + {BBP_R106, 0x35}, /* Optimizing the Short GI sampling request from Gray @2009-0409*/ +#endif /* DOT11_N_SUPPORT */ +}; +#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR)) + + +static INT rtmp_bbp_is_ready(struct _RTMP_ADAPTER *pAd) +{ + INT idx = 0; + UCHAR val; + + do + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &val); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + } while ((++idx < 20) && ((val == 0xff) || (val == 0x00))); + + if (!((val == 0xff) || (val == 0x00))) + { + DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", val)); + } + + return (((val == 0xff) || (val == 0x00)) ? FALSE : TRUE); +} + + +static INT rtmp_bbp_init(RTMP_ADAPTER *pAd) +{ + INT Index = 0; + + /* Read BBP register, make sure BBP is up and running before write new data*/ + if (rtmp_bbp_is_ready(pAd)== FALSE) + return FALSE; + + Index = 0; + + /* Initialize BBP register to default value*/ + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) + { +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { + if (Index == BBP_R105) + { + /* + kurtis:0x01 ori 0x05 is for rt2860E to turn on FEQ control. + It is safe for rt2860D and before, because Bit 7:2 + are reserved in rt2860D and before. + */ + BBPRegTable[Index].Value=0x01; + DBGPRINT(RT_DEBUG_TRACE, + ("RBUS:BBP[%d] = %x\n",(INT)Index, + BBPRegTable[Index].Value)); + } + } +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef MICROWAVE_OVEN_SUPPORT +#endif /* MICROWAVE_OVEN_SUPPORT */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, + BBPRegTable[Index].Register, + BBPRegTable[Index].Value); + } + + /* re-config specific BBP registers for individual chip */ + if (pAd->chipCap.pBBPRegTable) + { + REG_PAIR *reg_list = pAd->chipCap.pBBPRegTable; + + for (Index = 0; Index < pAd->chipCap.bbpRegTbSize; Index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, + reg_list[Index].Register, + reg_list[Index].Value); + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R%d=0x%x\n", + reg_list[Index].Register, + reg_list[Index].Value)); + } + } + + if (pAd->chipOps.AsicBbpInit != NULL) + pAd->chipOps.AsicBbpInit(pAd); + + /* + For rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. + RT3090 should not program BBP R84 to 0x19, otherwise TX will block. + 3070/71/72,3090,3090A( are included in RT30xx),3572,3390 + */ + if (((pAd->MACVersion & 0xffff) != 0x0101) && + !(IS_RT30xx(pAd)|| IS_RT3572(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd) || IS_RT3290(pAd) || IS_MT7601(pAd) || IS_RT6352(pAd) || IS_MT76x2(pAd))) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); + + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); + } + + return TRUE; + +} + + +static INT rtmp_bbp_get_temp(struct _RTMP_ADAPTER *pAd, CHAR *temp_val) +{ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + BBP_R49_STRUC bbp_val; + + bbp_val.byte = 0; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &bbp_val.byte); + *temp_val = (CHAR)bbp_val.byte; + + pAd->curr_temp = (bbp_val.byte & 0xff); +#endif + + return TRUE; +} + + +static INT rtmp_bbp_tx_comp_init(RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode) +{ + UCHAR bbp_val, rf_val; + + + /* Set BBP_R47 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbp_val); + bbp_val &= 0xe7; + bbp_val |= ((tssi_mode << 3) & 0x18); + bbp_val |= 0x80; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbp_val); + + /* Set RF_R27 */ + RT30xxReadRFRegister(pAd, RF_R27, &rf_val); + rf_val &= 0x3f; + rf_val |= ((adc_insel << 6) & 0xc0); + RT30xxWriteRFRegister(pAd, RF_R27, rf_val); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] Set RF_R27 to 0x%x\n", rf_val)); + + return TRUE; +} + + +static INT rtmp_bbp_set_txdac(struct _RTMP_ADAPTER *pAd, INT tx_dac) +{ + UCHAR val, old_val = 0; + + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &old_val); + val = old_val & (~0x18); + switch (tx_dac) + { + case 2: + val |= 0x10; + break; + case 1: + val |= 0x08; + break; + case 0: + default: + break; + } + + if (val != old_val) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, val); + } + + return TRUE; +} + + +static INT rtmp_bbp_set_rxpath(struct _RTMP_ADAPTER *pAd, INT rxpath) +{ + UCHAR val = 0; + + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &val); + val &= (~0x18); + if(rxpath == 3) + val |= (0x10); + else if(rxpath == 2) + val |= (0x8); + else if(rxpath == 1) + val |= (0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, val); + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.BBPR3 = val; + } +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + + +static INT rtmp_bbp_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch) +{ + UCHAR val, old_val = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &old_val); + val = old_val; + switch (ext_ch) + { + case EXTCHA_BELOW: + val |= (0x20); + break; + case EXTCHA_ABOVE: + case EXTCHA_NONE: + val &= (~0x20); + break; + } + + if (val != old_val) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, val); + +#ifdef CONFIG_STA_SUPPORT +#ifdef RTMP_MAC_PCI + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.BBPR3 = val; + } +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + + +static INT rtmp_bbp_set_bw(struct _RTMP_ADAPTER *pAd, UINT8 bw) +{ + UCHAR val, old_val = 0; + BOOLEAN bstop = FALSE; + UINT32 Data, MTxCycle, macStatus; + + + if (bw != pAd->CommonCfg.BBPCurrentBW) + bstop = TRUE; + + if (bstop) + { + /* Disable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data &= (~0x0C); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + + /* Check MAC Tx/Rx idle */ + for (MTxCycle = 0; MTxCycle < 10000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &old_val); + val = (old_val & (~0x18)); + switch (bw) + { + case BW_20: + val &= (~0x18); + break; + case BW_40: + val |= (0x10); + break; + case BW_10: + val |= 0x08; + break; + } + + if (val != old_val) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, val); + } + + if (bstop) + { + /* Enable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + } + + pAd->CommonCfg.BBPCurrentBW = bw; + + return TRUE; +} + + +static INT rtmp_bbp_set_mmps(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower) +{ + UCHAR bbp_val, org_val; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &org_val); + bbp_val = org_val; + if (ReduceCorePower) + bbp_val |= 0x04; + else + bbp_val &= ~0x04; + + if (bbp_val != org_val) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbp_val); + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R95, &org_val); + bbp_val = org_val; + if (ReduceCorePower) { + bbp_val &= ~(0x80); /* bit 7 */ + } else { + if (pAd->Antenna.field.RxPath > 1) + bbp_val |= 0x80; + } + if (bbp_val != org_val) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, bbp_val); + } +#endif /* RT6352*/ + + return TRUE; +} + + +static NDIS_STATUS AsicBBPWriteWithRxChain( + IN RTMP_ADAPTER *pAd, + IN UCHAR bbpId, + IN CHAR bbpVal, + IN RX_CHAIN_IDX rx_ch_idx) +{ + UCHAR idx = 0, val = 0; + + if (((pAd->MACVersion & 0xffff0000) <= 0x30900000) || + (pAd->Antenna.field.RxPath == 1)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, bbpId, bbpVal); + return NDIS_STATUS_SUCCESS; + } + + while (rx_ch_idx != 0) + { + if (idx >= pAd->Antenna.field.RxPath) + break; + + if (rx_ch_idx & 0x01) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &val); + val = (val & (~0x60)) | (idx << 5); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, val); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, bbpId, bbpVal); + } +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_INFO, + ("%s(Idx):Write(R%d,val:0x%x) to Chain(0x%x, idx:%d)\n", + __FUNCTION__, bbpId, bbpVal, rx_ch_idx, idx)); + } + rx_ch_idx >>= 1; + idx++; + } + + return NDIS_STATUS_SUCCESS; +} + + +static NDIS_STATUS AsicBBPReadWithRxChain( + IN RTMP_ADAPTER *pAd, + IN UCHAR bbpId, + IN CHAR *pBbpVal, + IN RX_CHAIN_IDX rx_ch_idx) +{ + UCHAR idx, val; + + if (((pAd->MACVersion & 0xffff0000) <= 0x30900000) || + (pAd->Antenna.field.RxPath == 1)) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, pBbpVal); + return NDIS_STATUS_SUCCESS; + } + + idx = 0; + while(rx_ch_idx != 0) + { + if (idx >= pAd->Antenna.field.RxPath) + break; + + if (rx_ch_idx & 0x01) + { + val = 0; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &val); + val = (val & (~0x60)) | (idx << 5); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, val); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, pBbpVal); + } +#endif /* RTMP_MAC_PCI */ + break; + } + rx_ch_idx >>= 1; + idx++; + } + + return NDIS_STATUS_SUCCESS; +} + + +static INT rtmp_bbp_get_agc(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX idx) +{ + return AsicBBPReadWithRxChain(pAd, BBP_R66, agc, idx); +} + + +static INT rtmp_bbp_set_agc(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX idx) +{ + return AsicBBPWriteWithRxChain(pAd, BBP_R66, agc, idx); +} + + +static INT rtmp_bbp_set_filter_coefficient_ctrl(RTMP_ADAPTER *pAd, UCHAR Channel) +{ + UCHAR bbp_val = 0, org_val = 0; + + if (Channel == 14) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &org_val); + bbp_val = org_val; + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + bbp_val |= 0x20; + else + bbp_val &= (~0x20); + + if (bbp_val != org_val) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbp_val); + } + + return TRUE; +} + + +static UCHAR rtmp_bbp_get_random_seed(RTMP_ADAPTER *pAd) +{ + UCHAR value1, value2, value3, value4, value5; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &value1); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &value2); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &value3); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R53, &value4); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R54, &value5); + + return (value1^value2^value3^value4^value5); +} + + +static struct phy_ops rtmp_phy_ops = { + .bbp_init = rtmp_bbp_init, + .bbp_is_ready = rtmp_bbp_is_ready, + .get_random_seed_by_phy = rtmp_bbp_get_random_seed, + .filter_coefficient_ctrl = rtmp_bbp_set_filter_coefficient_ctrl, + .bbp_set_agc = rtmp_bbp_set_agc, + .bbp_get_agc = rtmp_bbp_get_agc, + .bbp_set_bw = rtmp_bbp_set_bw, + .bbp_set_ctrlch = rtmp_bbp_set_ctrlch, + .bbp_set_rxpath = rtmp_bbp_set_rxpath, + .bbp_set_txdac = rtmp_bbp_set_txdac, + .bbp_set_mmps = rtmp_bbp_set_mmps, + .bbp_tx_comp_init = rtmp_bbp_tx_comp_init, + .bbp_get_temp = rtmp_bbp_get_temp, +}; + + +INT rtmp_phy_probe(RTMP_ADAPTER *pAd) +{ + pAd->phy_op = &rtmp_phy_ops; + + return TRUE; +} + + +#ifdef PRE_ANT_SWITCH + +#endif /* PRE_ANT_SWITCH */ + + +#ifdef CFO_TRACK +#ifdef CONFIG_AP_SUPPORT +INT rtmp_cfo_track(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, INT lastClient) +{ + /* CFO Tracking */ + if (IS_RT3883(pAd)) + { + if (pAd->MacTab.Size !=1 || pAd->CommonCfg.CFOTrack==0) + { + /* Set to default */ + RT3883_AsicSetFreqOffset(pAd, pAd->RfFreqOffset); + } + else if ((lastClient < MAX_LEN_OF_MAC_TABLE) && (lastClient >=1) && + pAd->CommonCfg.CFOTrack < 8 && + pEntry->freqOffsetValid) + { + /* Track CFO */ + SHORT foValue, offset = pEntry->freqOffset; + UCHAR RFValue; + + RT30xxReadRFRegister(pAd, RF_R17, (PUCHAR)&RFValue); + RFValue &= 0x7F; + + if (offset > 32) + offset = 32; + else if (offset < -32) + offset = -32; + + foValue = RFValue - (offset/16); + if (foValue < 0) + foValue = 0; + else if (foValue > 0x5F) + foValue = 0x5F; + + if (foValue != RFValue) + RT3883_AsicSetFreqOffset(pAd, foValue); + + /* If CFOTrack!=1 then keep updating until CFOTrack==8 */ + if (pAd->CommonCfg.CFOTrack != 1) + pAd->CommonCfg.CFOTrack++; + + pEntry->freqOffsetValid = FALSE; + } + } + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CFO_TRACK */ + +#endif /* RTMP_BBP */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_ags.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_ags.c new file mode 100644 index 000000000..251516c8c --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_ags.c @@ -0,0 +1,2056 @@ +/**************************************************************************** + * 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 AGS (Adaptive Group Switching) function body. + +***************************************************************************/ + +#ifdef AGS_SUPPORT + +#include "rt_config.h" + + +/* + HT Rate Table format + [Item no.] [Mode]* [Mode]** [CurrMCS] [TrainUp] [TrainDown] [downMCS] [upMCS3] [upMCS2] [upMCS1] + + [Mode]*: + bit0: STBC -STBC_XXX + bit1: Short GI - GI_XXX + bit2~3: BW - BW_XXX + bit4~bit6: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF, 4: VHT) - MODE_XXX + bit7: Reserved + + [Mode]** + bit0~1: Nss - NSS_XXX (VHT only) + bit2~7: Reserved +*/ + +/* AGS: 1x1 HT-capable rate table */ +UCHAR AGS1x1HTRateTable[] = { + 0x09, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */ + 0x00, 0x21, 0, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */ + 0x01, 0x21, 0, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */ + 0x02, 0x21, 0, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */ + 0x03, 0x21, 0, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */ + 0x04, 0x21, 0, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */ + 0x05, 0x21, 0, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */ + 0x06, 0x21, 0, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */ + 0x07, 0x21, 0, 7, 8, 14, 6, 19, 12, 8, /* MCS 7 */ + 0x08, 0x23, 0, 7, 8, 14, 7, 19, 12, 8, /* MCS 7 + Short GI */ +}; + + +/* AGS: 2x2 HT-capable rate table */ +UCHAR AGS2x2HTRateTable[] = { + 0x11, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */ + 0x00, 0x21, 0, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */ + 0x01, 0x21, 0, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */ + 0x02, 0x21, 0, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */ + 0x03, 0x21, 0, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */ + 0x04, 0x21, 0, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */ + 0x05, 0x21, 0, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */ + 0x06, 0x21, 0, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */ + 0x07, 0x21, 0, 7, 8, 14, 6, 19, 12, 7, /* MCS 7 */ + 0x08, 0x20, 0, 8, 30, 50, 0, 16, 9, 2, /* MCS 8 */ + 0x09, 0x20, 0, 9, 20, 50, 8, 17, 10, 4, /* MCS 9 */ + 0x0A, 0x20, 0, 10, 20, 50, 9, 18, 11, 5, /* MCS 10 */ + 0x0B, 0x20, 0, 11, 15, 30, 10, 18, 12, 6, /* MCS 11 */ + 0x0C, 0x20, 0, 12, 15, 30, 11, 20, 13, 12, /* MCS 12 */ + 0x0D, 0x20, 0, 13, 8, 20, 12, 20, 14, 13, /* MCS 13 */ + 0x0E, 0x20, 0, 14, 8, 18, 13, 21, 15, 14, /* MCS 14 */ + 0x0F, 0x20, 0, 15, 8, 25, 14, 21, 16, 15, /* MCS 15 */ + 0x10, 0x22, 0, 15, 8, 25, 15, 21, 16, 16, /* MCS 15 + Short GI */ +}; + + +/* AGS: 3x3 HT-capable rate table */ +UCHAR AGS3x3HTRateTable[] = { + 0x19, 0x18, 0, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */ + 0x00, 0x21, 0, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */ + 0x01, 0x21, 0, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */ + 0x02, 0x21, 0, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */ + 0x03, 0x21, 0, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */ + 0x04, 0x21, 0, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */ + 0x05, 0x21, 0, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */ + 0x06, 0x21, 0, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */ + 0x07, 0x21, 0, 7, 8, 14, 6, 19, 12, 7, /* MCS 7 */ + 0x08, 0x20, 0, 8, 30, 50, 0, 16, 9, 2, /* MCS 8 */ + 0x09, 0x20, 0, 9, 20, 50, 8, 17, 10, 4, /* MCS 9 */ + 0x0A, 0x20, 0, 10, 20, 50, 9, 18, 11, 5, /* MCS 10 */ + 0x0B, 0x20, 0, 11, 15, 30, 10, 18, 12, 6, /* MCS 11 */ + 0x0C, 0x20, 0, 12, 15, 30, 11, 20, 13, 12, /* MCS 12 */ + 0x0D, 0x20, 0, 13, 8, 20, 12, 20, 14, 13, /* MCS 13 */ + 0x0E, 0x20, 0, 14, 8, 18, 13, 21, 15, 14, /* MCS 14 */ + 0x0F, 0x20, 0, 15, 8, 14, 14, 21, 15, 15, /* MCS 15 */ + 0x10, 0x20, 0, 16, 30, 50, 8, 17, 9, 3, /* MCS 16 */ + 0x11, 0x20, 0, 17, 20, 50, 16, 18, 11, 5, /* MCS 17 */ + 0x12, 0x20, 0, 18, 20, 50, 17, 19, 12, 7, /* MCS 18 */ + 0x13, 0x20, 0, 19, 15, 30, 18, 20, 13, 19, /* MCS 19 */ + 0x14, 0x20, 0, 20, 15, 30, 19, 21, 15, 20, /* MCS 20 */ + 0x15, 0x20, 0, 21, 8, 20, 20, 22, 21, 21, /* MCS 21 */ + 0x16, 0x20, 0, 22, 8, 20, 21, 23, 22, 22, /* MCS 22 */ + 0x17, 0x20, 0, 23, 6, 18, 22, 24, 23, 23, /* MCS 23 */ + 0x18, 0x22, 0, 23, 6, 14, 23, 24, 24, 24, /* MCS 23 + Short GI */ +}; + + +#ifdef DOT11_VHT_AC + +#define NSS_1 0 +#define NSS_2 1 +/* RSSI Offset table for Ags rate tuning */ +UCHAR AgsRssiOffsetTable[3][4] = +{ + // [i][] MAX System spatial stream capability: 1*1, 2*2, 3*3 + // [i][] MAX System Bandwidth: 20, 40, 80, 160 + // ---------------------- + {0, 2, 4, 6}, // For VHT 1*1: BW20, BW40, BW80, BW160 + {2, 4, 6, 8}, // For VHT 2*2: BW20, BW40, BW80, BW160 + {4, 6, 8, 10} // For VHT 3*3: BW20, BW40, BW80, BW160 +}; + + +/* + [Item no.] [Mode]* [Mode]** [CurrMCS] [TrainUp] [TrainDown] [downMCS] [upMCS3] [upMCS2] [upMCS1] + + Note: downMCS, upMCS3, upMCS2 and upMCS1 are zero-based array index. + + [Mode]*: + bit0: STBC -STBC_XXX + bit1: Short GI - GI_XXX + bit2~3: BW - BW_XXX + bit4~bit6: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF, 4: VHT) - MODE_XXX + bit7: Reserved + + [Mode]** + bit0~1: Nss - NSS_XXX (VHT only) + bit2~7: Reserved +*/ + +/* AGS: 1x1 VHT-capable rate table */ +UCHAR Ags1x1VhtRateTable[] = +{ + // Initial used item after association: the number of rate indexes, the initial MCS (index) + 9, 0x08, 0x00, 0, 0, 0, 0, 0, 0, 0, + 0, 0x41, 0x00, 0,/* VHT 1x1 MCS 0 */ 30, 101, 0, 0, 0, 1, + 1, 0x41, 0x00, 1,/* VHT 1x1 MCS 1 */ 20, 50, 0, 0, 0, 2, + 2, 0x41, 0x00, 2,/* VHT 1x1 MCS 2 */ 20, 50, 1, 0, 0, 3, + 3, 0x41, 0x00, 3,/* VHT 1x1 MCS 3 */ 15, 50, 2, 0, 0, 4, + 4, 0x41, 0x00, 4,/* VHT 1x1 MCS 4 */ 15, 30, 3, 0, 0, 5, + 5, 0x41, 0x00, 5,/* VHT 1x1 MCS 5 */ 10, 25, 4, 0, 0, 6, + 6, 0x41, 0x00, 6,/* VHT 1x1 MCS 6 */ 8, 14, 5, 0, 0, 7, + 7, 0x41, 0x00, 7,/* VHT 1x1 MCS 7 */ 8, 14, 6, 0, 0, 8, + 8, 0x43, 0x00, 7,/* VHT 1x1 MCS 7 + SGI */ 8, 14, 7, 0, 0, 8, +}; + + +/* AGS: 2x2 VHT-capable rate table */ +UCHAR Ags2x2VhtRateTable[] = { + // row #1 is initial used item after association: the number of rate indexes, the initial MCS (index) + 17, 0x10, 0x00, 0, 0, 0, 0, 0, 0, 0, + 0, 0x41, 0x00, 0, /* VHT 1x1 MCS 0 */ 30, 101, 0, 0, 8, 1, + 1, 0x41, 0x00, 1, /* VHT 1x1 MCS 1 */ 20, 50, 0, 0, 9, 2, + 2, 0x41, 0x00, 2, /* VHT 1x1 MCS 2 */ 20, 50, 1, 0, 9, 3, + 3, 0x41, 0x00, 3, /* VHT 1x1 MCS 3 */ 15, 50, 2, 0, 10, 4, + 4, 0x41, 0x00, 4, /* VHT 1x1 MCS 4 */ 15, 30, 3, 0, 11, 5, + 5, 0x41, 0x00, 5, /* VHT 1x1 MCS 5 */ 10, 25, 4, 0, 12, 6, + 6, 0x41, 0x00, 6, /* VHT 1x1 MCS 6 */ 8, 14, 5, 0, 12, 7, + 7, 0x41, 0x00, 7, /* VHT 1x1 MCS 7 */ 8, 14, 6, 0, 12, 7, + 8, 0x40, 0x01, 0, /* VHT 2x2 MCS 0 */ 30, 50, 0, 0, 9, 2, + 9, 0x40, 0x01, 1, /* VHT 2x2 MCS 1 */ 20, 50, 8, 0, 10, 4, + 10, 0x40, 0x01, 2, /* VHT 2x2 MCS 2 */ 20, 50, 9, 0, 11, 5, + 11, 0x40, 0x01, 3, /* VHT 2x2 MCS 3 */ 15, 30, 10, 0, 12, 6, + 12, 0x40, 0x01, 4, /* VHT 2x2 MCS 4 */ 15, 30, 11, 0, 13, 12, + 13, 0x40, 0x01, 5, /* VHT 2x2 MCS 5 */ 8, 20, 12, 0, 14, 13, + 14, 0x40, 0x01, 6, /* VHT 2x2 MCS 6 */ 8, 18, 13, 0, 15, 14, + 15, 0x40, 0x01, 7, /* VHT 2x2 MCS 7 */ 8, 25, 14, 0, 16, 15, + 16, 0x42, 0x01, 7, /* VHT 2x2 MCS 7 + SGI */ 8, 25, 15, 0, 16, 16, +}; +#endif /* DOT11_VHT_AC */ + + +INT Show_AGS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[1]; + UINT32 IdQuality; + + + DBGPRINT(RT_DEBUG_OFF, ("MCS Group\t\tMCS Index\n")); + DBGPRINT(RT_DEBUG_OFF, ("%d\t\t\t%d\n\n", pEntry->AGSCtrl.MCSGroup, pEntry->CurrTxRateIndex)); + + DBGPRINT(RT_DEBUG_OFF, ("MCS Quality:\n")); + for(IdQuality=0; IdQuality<=23; IdQuality++) + DBGPRINT(RT_DEBUG_OFF, ("%02d\t\t%d\n", IdQuality, pEntry->TxQuality[IdQuality])); + + return TRUE; +} + + +#ifdef CONFIG_STA_SUPPORT +/* + The dynamic Tx rate switching for AGS (Adaptive Group Switching) + + Parameters + pAd: The adapter data structure + pEntry: Pointer to a caller-supplied variable in which points to a MAC table entry + pTable: Pointer to a caller-supplied variable in wich points to a Tx rate switching table + TableSize: The size, in bytes, of the specified Tx rate switching table + pAGSStatisticsInfo: Pointer to a caller-supplied variable in which points to the statistics information + + Return Value: + None +*/ +VOID MlmeDynamicTxRateSwitchingAGS( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pTable, + IN UCHAR TableSize, + IN PAGS_STATISTICS_INFO pAGSStatisticsInfo, + IN UCHAR InitTxRateIdx) +{ + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + BOOLEAN bTxRateChanged = TRUE, bUpgradeQuality = FALSE; + RTMP_RA_AGS_TB *pCurrTxRate = NULL; + RTMP_RA_LEGACY_TB *pNextTxRate = NULL; + UCHAR TrainUp = 0, TrainDown = 0, next_grp; + CHAR RssiOffset = 0; + + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AGS: ---> %s\n", __FUNCTION__)); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: AccuTxTotalCnt = %d, TxSuccess = %d, TxRetransmit = %d, TxFailCount = %d, TxErrorRatio = %d\n", + __FUNCTION__, + pAGSStatisticsInfo->AccuTxTotalCnt, + pAGSStatisticsInfo->TxSuccess, + pAGSStatisticsInfo->TxRetransmit, + pAGSStatisticsInfo->TxFailCount, + pAGSStatisticsInfo->TxErrorRatio)); + + CurrRateIdx = pEntry->CurrTxRateIndex; + + if (CurrRateIdx >= TableSize) + CurrRateIdx = TableSize - 1; + + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(CurrRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + /* Select the next upgrade rate and the next downgrade rate, if any */ + do + { + if (pTable == AGS3x3HTRateTable) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: pEntry->AGSCtrl.MCSGroup = %d, TxQuality2[%d] = %d, " + "TxQuality1[%d] = %d, TxQuality0[%d] = %d, pCurrTxRate->upMcs1 = %d, " + "pCurrTxRate->ItemNo = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs3, + pEntry->TxQuality[pCurrTxRate->upMcs3], + pCurrTxRate->upMcs2, + pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, + pEntry->TxQuality[pCurrTxRate->upMcs1], + pCurrTxRate->upMcs1, + pCurrTxRate->ItemNo)); + + /* 3x3 peer device (Adhoc, DLS or AP) */ + /* for 3*3, pEntry->AGSCtrl.MCSGroup = 0, 3, 3, 3, ... */ + next_grp = pEntry->AGSCtrl.MCSGroup; + switch (pEntry->AGSCtrl.MCSGroup) + { + case 0: /* MCS selection in round robin policy (different MCS group) */ + { + UpRateIdx = pCurrTxRate->upMcs3; + next_grp = 3; + + /* MCS group #2 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs2]) && + (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) + { + UpRateIdx = pCurrTxRate->upMcs2; + next_grp = 2; + } + + /* MCS group #1 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)) + { + UpRateIdx = pCurrTxRate->upMcs1; + next_grp = 1; + } + } + break; + + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("AGS> Current Group:%d, Select UpRateIdx=%d in group %d\n", + pEntry->AGSCtrl.MCSGroup, UpRateIdx, next_grp)); + + + if ((pEntry->AGSCtrl.MCSGroup == 0) && + (((pEntry->TxQuality[pCurrTxRate->upMcs3] > pEntry->TxQuality[pCurrTxRate->upMcs2]) && (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) || + ((pEntry->TxQuality[pCurrTxRate->upMcs3] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)))) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: ##############\n", __FUNCTION__)); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: [3x3 peer device (Adhoc, DLS or AP)], Before - " + "pEntry->AGSCtrl.MCSGroup = %d, TxQuality2[%d] = %d, " + "TxQuality1[%d] = %d, TxQuality0[%d] = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs3, + pEntry->TxQuality[pCurrTxRate->upMcs3], + pCurrTxRate->upMcs2, + pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, + pEntry->TxQuality[pCurrTxRate->upMcs1])); + } + } + else if ((pTable == AGS2x2HTRateTable) +#ifdef DOT11_VHT_AC + || (pTable == Ags2x2VhtRateTable)) +#endif /* DOT11_VHT_AC*/ + ) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: pEntry->AGSCtrl.MCSGroup = %d, TxQuality1[%d] = %d, " + "TxQuality0[%d] = %d, pCurrTxRate->upMcs1 = %d, " + "pCurrTxRate->ItemNo = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs2, pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, pEntry->TxQuality[pCurrTxRate->upMcs1], + pCurrTxRate->upMcs1, pCurrTxRate->ItemNo)); + + /* 2x2 peer device (Adhoc, DLS or AP) */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 0: /* MCS selection in round robin policy */ + { + UpRateIdx = pCurrTxRate->upMcs2; + /* MCS group #1 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)) + UpRateIdx = pCurrTxRate->upMcs1; + } + break; + + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: [2x2 peer device (Adhoc, DLS or AP)], " + "Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + if ((pEntry->AGSCtrl.MCSGroup == 0) && + ((pEntry->TxQuality[pCurrTxRate->upMcs2] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo))) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: ###########\n", __FUNCTION__)); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: [2x2 peer device (Adhoc, DLS or AP)], Before - " + "pEntry->AGSCtrl.MCSGroup = %d, TxQuality1[%d] = %d, " + "TxQuality0[%d] = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs2, + pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, + pEntry->TxQuality[pCurrTxRate->upMcs1])); + } + } + else + { + /* 1x1 peer device (Adhoc, DLS or AP) */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 1: + case 0: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: [1x1 peer device (Adhoc, DLS or AP)], " + "Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup)); + } + break; + } + } + + + /* The STA uses the best Tx rate at this moment. */ + if (UpRateIdx == pEntry->CurrTxRateIndex) + { + /* current rate is the best one */ + pEntry->AGSCtrl.MCSGroup = 0; /* Try to escape the local optima */ + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> Current rate is the best one!\n")); + break; + } + + if ((pEntry->TxQuality[UpRateIdx] > 0) && (pEntry->AGSCtrl.MCSGroup > 0)) + { + /* + Quality of up rate is bad try to use lower group. + So continue to get the up rate index. + */ + pEntry->AGSCtrl.MCSGroup--; /* Try to use the MCS of the lower MCS group */ + } + else + { + break; + } + } while (1); + + DownRateIdx = pCurrTxRate->downMcs; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> UpRateIdx = %d, DownRateIdx = %d\n", + UpRateIdx, DownRateIdx)); + +#ifdef DOT11_N_SUPPORT + if ((pAGSStatisticsInfo->RSSI > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + /* Keep the TxRateChangeAction status */ + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + + /* MCS selection based on the RSSI information when the Tx samples are fewer than 15. */ + if (pAGSStatisticsInfo->AccuTxTotalCnt <= 15) + { + CHAR idx = 0; + UCHAR TxRateIdx; + UCHAR MCS[24] = {0}; + /* Check the existence and index of each needed MCS */ + +#ifdef DOT11_VHT_AC + if ((pTable == Ags2x2VhtRateTable) || (pTable == Ags1x1VhtRateTable)) + { + INT mcs_idx_offset; + while (idx < pTable[0]) + { + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + if (pCurrTxRate->Mode == MODE_VHT) + { + if (pCurrTxRate->Nss == NSS_1) + mcs_idx_offset = 0; + else if ((pCurrTxRate->Nss == NSS_2) && (pTable == Ags2x2VhtRateTable)) + mcs_idx_offset = 8; + + if ((pCurrTxRate->CurrMCS >= MCS_0) && (pCurrTxRate->CurrMCS <= MCS_7)) + MCS[pCurrTxRate->CurrMCS + mcs_idx_offset] = idx; + } + idx++; + } + } + else +#endif /* DOT11_VHT_AC */ + { + while (idx < pTable[0]) + { + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if (pCurrTxRate->CurrMCS >= MCS_0 && pCurrTxRate->CurrMCS <= MCS_23) + MCS[pCurrTxRate->CurrMCS] = idx; + idx++; + } + } + + /* peer device (Adhoc, DLS or AP) */ + RssiOffset = 0; + if (pTable == AGS3x3HTRateTable) + { + if (MCS[23] && (pAGSStatisticsInfo->RSSI > (-67 + RssiOffset))) + TxRateIdx = MCS[23]; + else if (MCS[22] && (pAGSStatisticsInfo->RSSI > (-69 + RssiOffset))) + TxRateIdx = MCS[22]; + else if (MCS[21] && (pAGSStatisticsInfo->RSSI > (-72 + RssiOffset))) + TxRateIdx = MCS[21]; + else if (MCS[20] && (pAGSStatisticsInfo->RSSI > (-74 + RssiOffset))) + TxRateIdx = MCS[20]; + else if (MCS[19] && (pAGSStatisticsInfo->RSSI > (-78 + RssiOffset))) + TxRateIdx = MCS[19]; + else if (MCS[18] && (pAGSStatisticsInfo->RSSI > (-80 + RssiOffset))) + TxRateIdx = MCS[18]; + else if (MCS[17] && (pAGSStatisticsInfo->RSSI > (-85 + RssiOffset))) + TxRateIdx = MCS[17]; + else + TxRateIdx = MCS[16]; + + pEntry->AGSCtrl.MCSGroup = 3; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> Group3 RSSI = %d, TxRateIdx = %d\n", + pAGSStatisticsInfo->RSSI, TxRateIdx)); + } + else if (pTable == AGS2x2HTRateTable) +#ifdef DOT11_VHT_AC + || (pTable == Ags2x2VhtRateTable)) +#endif /* DOT11_VHT_AC */ + ) + { +#ifdef DOT11_VHT_AC + if (pTable == Ags2x2VhtRateTable) + RssiOffset = AgsRssiOffsetTable[1][pAd->CommonCfg.BBPCurrentBW]; +#endif /* DOT11_VHT_AC */ + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: 2*2, RssiOffsetForAgs=%d\n", __FUNCTION__, RssiOffset)); + + if (MCS[15 && (pAGSStatisticsInfo->RSSI > (-69 + RssiOffset))) + TxRateIdx = MCS[15]; + else if (MCS[14 && (pAGSStatisticsInfo->RSSI > (-71 + RssiOffset))) + TxRateIdx = MCS[14]; + else if (MCS[13 && (pAGSStatisticsInfo->RSSI > (-74 + RssiOffset))) + TxRateIdx = MCS[13]; + else if (MCS[12 && (pAGSStatisticsInfo->RSSI > (-76 + RssiOffset))) + TxRateIdx = MCS[12]; + else if (MCS[11 && (pAGSStatisticsInfo->RSSI > (-80 + RssiOffset))) + TxRateIdx = MCS[11]; + else if (MCS[10 && (pAGSStatisticsInfo->RSSI > (-82 + RssiOffset))) + TxRateIdx = MCS[10]; + else if (MCS[9 && (pAGSStatisticsInfo->RSSI > (-87 + RssiOffset))) + TxRateIdx = MCS[9]; + else + TxRateIdx = MCS[8]; + + pEntry->AGSCtrl.MCSGroup = 2; + } + else + { +#ifdef DOT11_VHT_AC + if (pTable == Ags1x1VhtRateTable) + RssiOffset = AgsRssiOffsetTable[0][pAd->CommonCfg.BBPCurrentBW]; +#endif /* DOT11_VHT_AC */ + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: 1*1, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 1x1 peer device (Adhoc, DLS or AP) */ + if (MCS[7] && (pAGSStatisticsInfo->RSSI > (-71 + RssiOffset))) + TxRateIdx = MCS[7]; + else if (MCS[6] && (pAGSStatisticsInfo->RSSI > (-73 + RssiOffset))) + TxRateIdx = MCS[6]; + else if (MCS[5] && (pAGSStatisticsInfo->RSSI > (-76 + RssiOffset))) + TxRateIdx = MCS[5]; + else if (MCS[4] && (pAGSStatisticsInfo->RSSI > (-78 + RssiOffset))) + TxRateIdx = MCS[4]; + else if (MCS[3] && (pAGSStatisticsInfo->RSSI > (-82 + RssiOffset))) + TxRateIdx = MCS[3]; + else if (MCS[2] && (pAGSStatisticsInfo->RSSI > (-84 + RssiOffset))) + TxRateIdx = MCS[2]; + else if (MCS[1] && (pAGSStatisticsInfo->RSSI > (-89 + RssiOffset))) + TxRateIdx = MCS[1]; + else + TxRateIdx = MCS[0]; + + pEntry->AGSCtrl.MCSGroup = 1; + } + + pEntry->AGSCtrl.lastRateIdx = pEntry->CurrTxRateIndex; + pEntry->CurrTxRateIndex = TxRateIdx; + + pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + + RTMPZeroMemory(pEntry->TxQuality, (sizeof(USHORT) * (MAX_TX_RATE_INDEX+1))); + RTMPZeroMemory(pEntry->PER, (sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1))); + + pEntry->fLastSecAccordingRSSI = TRUE; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + return; + } + + /* The MCS selection is based on the RSSI and skips the rate tuning this time. */ + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: The MCS selection base on RSSI\n", __FUNCTION__)); + + return; + } + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: TrainUp:%d, TrainDown:%d\n", __FUNCTION__, TrainUp, TrainDown)); + + do + { + BOOLEAN bTrainUpDown = FALSE; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: TxQuality[CurrRateIdx(%d)] = %d, UpPenalty:%d\n", + __FUNCTION__, CurrRateIdx, + pEntry->TxQuality[CurrRateIdx], pEntry->TxRateUpPenalty)); + + if (pAGSStatisticsInfo->TxErrorRatio >= TrainDown) /* Poor quality */ + { + /* error ratio too high, do rate down */ + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: (DOWN) TxErrorRatio >= TrainDown\n",__FUNCTION__)); + bTrainUpDown = TRUE; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + } + else if (pAGSStatisticsInfo->TxErrorRatio <= TrainUp) /* Good quality */ + { + bTrainUpDown = TRUE; + bUpgradeQuality = TRUE; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: (UP) pEntry->TxQuality[CurrRateIdx] = %d, pEntry->TxRateUpPenalty = %d\n", + __FUNCTION__, + pEntry->TxQuality[CurrRateIdx], + pEntry->TxRateUpPenalty)); + + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; /* Good quality in the current Tx rate */ + + if (pEntry->TxRateUpPenalty) + pEntry->TxRateUpPenalty--; /* no use for the parameter */ + else + { + if (pEntry->TxQuality[pCurrTxRate->upMcs3] && (pCurrTxRate->upMcs3 != CurrRateIdx)) + pEntry->TxQuality[pCurrTxRate->upMcs3]--; + + if (pEntry->TxQuality[pCurrTxRate->upMcs2] && (pCurrTxRate->upMcs2 != CurrRateIdx)) + pEntry->TxQuality[pCurrTxRate->upMcs2]--; + + if (pEntry->TxQuality[pCurrTxRate->upMcs1] && (pCurrTxRate->upMcs1 != CurrRateIdx)) + pEntry->TxQuality[pCurrTxRate->upMcs1]--; + } + } + else if (pEntry->AGSCtrl.MCSGroup > 0) /* even if TxErrorRatio > TrainUp */ + { + /* not bad and not good */ + if (UpRateIdx != 0) + { + bTrainUpDown = TRUE; + + /* Good quality in the current Tx rate */ + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; + + /* It may improve next train-up Tx rate's quality */ + if (pEntry->TxQuality[UpRateIdx]) + pEntry->TxQuality[UpRateIdx]--; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> not bad and not good\n")); + } + } + + /* update error ratio for current MCS */ + pEntry->PER[CurrRateIdx] = (UCHAR)(pAGSStatisticsInfo->TxErrorRatio); + + /* Update the current Tx rate */ + if (bTrainUpDown) + { + /* need to rate up or down */ + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: bTrainUpDown = %d, CurrRateIdx = %d, DownRateIdx = %d, UpRateIdx = %d, pEntry->TxQuality[CurrRateIdx] = %d, pEntry->TxQuality[UpRateIdx] = %d\n", + __FUNCTION__, + bTrainUpDown, CurrRateIdx, DownRateIdx, UpRateIdx, + pEntry->TxQuality[CurrRateIdx], pEntry->TxQuality[UpRateIdx])); + + /* Downgrade Tx rate */ + if ((CurrRateIdx != DownRateIdx) && + (pEntry->TxQuality[CurrRateIdx] >= AGS_TX_QUALITY_WORST_BOUND)) + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("ags> rate down!\n")); + } + else if ((CurrRateIdx != UpRateIdx) && + (pEntry->TxQuality[UpRateIdx] <= 0)) /* Upgrade Tx rate */ + { + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("ags> rate up!\n")); + } + } + } while (FALSE); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: pEntry->CurrTxRateIndex = %d, CurrRateIdx = %d, pEntry->LastSecTxRateChangeAction = %d\n", + __FUNCTION__, + pEntry->CurrTxRateIndex, CurrRateIdx, + pEntry->LastSecTxRateChangeAction)); + + /* rate up/down post handle */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == RATE_UP)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: ++TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->LastSecTxRateChangeAction = RATE_UP; + pEntry->TxRateUpPenalty = 0; + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + pEntry->AGSCtrl.lastRateIdx = CurrRateIdx; + + bTxRateChanged = TRUE; + } + else if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == RATE_DOWN)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: --TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + pEntry->TxRateUpPenalty = 0; /* No penalty */ + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + pEntry->AGSCtrl.lastRateIdx = CurrRateIdx; + + bTxRateChanged = TRUE; + } + else /* Tx rate remains unchanged. */ + { + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; /* Tx rate remains unchanged. */ + bTxRateChanged = FALSE; + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> no rate up/down!\n")); + } + + /* Tx rate fast train up/down */ + if ((bTxRateChanged == TRUE) && + (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, pAd->ra_fast_interval); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + + pEntry->LastTxOkCount = pAGSStatisticsInfo->TxSuccess; + + /* set new tx rate */ + pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> set new rate MCS = %d!\n", pEntry->CurrTxRateIndex)); + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + + /* RDG threshold control for the infrastructure mode only */ + if (INFRA_ON(pAd)) + { + if ((pAd->CommonCfg.bRdg == TRUE) && + CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], + fCLIENT_STATUS_RDG_CAPABLE)) /* RDG capable */ + { + TXOP_THRESHOLD_CFG_STRUC TxopThCfg = {{0}}; + TX_LINK_CFG_STRUC TxLinkCfg = {{0}}; + + if ((pAd->RalinkCounters.OneSecReceivedByteCount > (pAd->RalinkCounters.OneSecTransmittedByteCount * 5)) && + (pNextTxRate->CurrMCS != MCS_23) && + ((pAd->RalinkCounters.OneSecReceivedByteCount + pAd->RalinkCounters.OneSecTransmittedByteCount) >= (50 * 1024))) + { + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, TXOP_THRES_CFG, &TxopThCfg.word); + TxopThCfg.field.RDG_IN_THRES = 0xFF; /* Similar to diable Rx RDG */ + TxopThCfg.field.RDG_OUT_THRES = 0x00; + RTMP_IO_WRITE32(pAd, TXOP_THRES_CFG, TxopThCfg.word); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("AGS: %s: RDG_IN_THRES = 0xFF\n", __FUNCTION__)); + } + else + { + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 1; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, TXOP_THRES_CFG, &TxopThCfg.word); + TxopThCfg.field.RDG_IN_THRES = 0x00; + TxopThCfg.field.RDG_OUT_THRES = 0x00; + RTMP_IO_WRITE32(pAd, TXOP_THRES_CFG, TxopThCfg.word); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("AGS: %s: RDG_IN_THRES = 0x00\n", __FUNCTION__)); + } + } + } + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AGS: <--- %s\n", __FUNCTION__)); +} + + +/* + Auto Tx rate faster train up/down for AGS (Adaptive Group Switching) + + Parameters + pAd: The adapter data structure + pEntry: Pointer to a caller-supplied variable in which points to a MAC table entry + pTable: Pointer to a caller-supplied variable in wich points to a Tx rate switching table + TableSize: The size, in bytes, of the specified Tx rate switching table + pAGSStatisticsInfo: Pointer to a caller-supplied variable in which points to the statistics information + + Return Value: + None +*/ +VOID StaQuickResponeForRateUpExecAGS( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pTable, + IN UCHAR TableSize, + IN PAGS_STATISTICS_INFO pAGSStatisticsInfo, + IN UCHAR InitTxRateIdx) +{ + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + BOOLEAN bTxRateChanged = TRUE; + RTMP_RA_AGS_TB *pCurrTxRate = NULL; + RTMP_RA_LEGACY_TB *pNextTxRate = NULL; + UCHAR TrainDown = 0, TrainUp = 0; + CHAR ratio = 0; + ULONG OneSecTxNoRetryOKRationCount = 0; + + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("QuickAGS: ---> %s\n", __FUNCTION__)); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: QuickAGS: AccuTxTotalCnt = %lu, TxSuccess = %lu, " + "TxRetransmit = %lu, TxFailCount = %lu, TxErrorRatio = %lu\n", + __FUNCTION__, + pAGSStatisticsInfo->AccuTxTotalCnt, + pAGSStatisticsInfo->TxSuccess, + pAGSStatisticsInfo->TxRetransmit, + pAGSStatisticsInfo->TxFailCount, + pAGSStatisticsInfo->TxErrorRatio)); + + CurrRateIdx = pEntry->CurrTxRateIndex; + + if (CurrRateIdx >= TableSize) + CurrRateIdx = TableSize - 1; + + UpRateIdx = DownRateIdx = pEntry->AGSCtrl.lastRateIdx; + + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(CurrRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if ((pAGSStatisticsInfo->RSSI > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + /* MCS selection based on the RSSI information when the Tx samples are fewer than 15. */ + if (pAGSStatisticsInfo->AccuTxTotalCnt <= 15) + { + RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1)); + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + + if ((pEntry->LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + } + else if ((pEntry->LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) + { + pEntry->CurrTxRateIndex = UpRateIdx; + } + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: QuickAGS: AccuTxTotalCnt <= 15, train back to original rate\n", + __FUNCTION__)); + + return; + } + + do + { + if (pEntry->LastTimeTxRateChangeAction == 0) + ratio = 5; + else + ratio = 4; + + if (pAGSStatisticsInfo->TxErrorRatio >= TrainDown) /* Poor quality */ + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + + pEntry->PER[CurrRateIdx] = (UCHAR)(pAGSStatisticsInfo->TxErrorRatio); + + OneSecTxNoRetryOKRationCount = (pAGSStatisticsInfo->TxSuccess * ratio); + + /* Tx rate down */ + if ((pEntry->LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + // Change Auto Rate tuning rule 1: Change from tx_ok to PER + if (pAGSStatisticsInfo->TxErrorRatio > TrainDown) /* Poor quality */ + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: (UP) bad Tx ok count (Current PER:%d, NewMcs's TrainDown:%d)\n", + __FUNCTION__, + pAGSStatisticsInfo->TxErrorRatio, TrainDown)); + } + else /* Good quality */ + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: (UP) keep rate-up (Current PER:%d, NewMcs's TrainDown:%d)\n", + __FUNCTION__, + pAGSStatisticsInfo->TxErrorRatio, + TrainDown)); + + RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1)); + + if (pEntry->AGSCtrl.MCSGroup == 0) + { + if (pTable == AGS3x3HTRateTable) + pEntry->AGSCtrl.MCSGroup = 3; + else if ((pTable == AGS2x2HTRateTable) || + (pTable == Ags2x2VhtRateTable)) + pEntry->AGSCtrl.MCSGroup = 2; + else + pEntry->AGSCtrl.MCSGroup = 1; + } + } + } + else if ((pEntry->LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) // Tx rate up + { + +// Don't quick check within train down case + } + }while (FALSE); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> new group = %d\n", pEntry->AGSCtrl.MCSGroup)); + + /* Last action is rate-up */ + if (pEntry->LastSecTxRateChangeAction == 1) + { + /* looking for the next group with valid MCS */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && (pEntry->AGSCtrl.MCSGroup > 0)) + { + pEntry->AGSCtrl.MCSGroup--; /* Try to use the MCS of the lower MCS group */ + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(DownRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + } + + /* UpRateIdx is for temp use in this section */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + case 0: + UpRateIdx = CurrRateIdx; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + /* Try to escape the local optima */ + if (UpRateIdx == pEntry->CurrTxRateIndex) + pEntry->AGSCtrl.MCSGroup = 0; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: next MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, pEntry->AGSCtrl.MCSGroup)); + + } + + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == 2)) /* Tx rate up */ + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: ++TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->TxRateUpPenalty = 0; + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; /*restore the TxQuality from max to 0 */ + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + } + else if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == 1)) /* Tx rate down */ + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: --TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->TxRateUpPenalty = 0; /* No penalty */ + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + } + else + { + bTxRateChanged = FALSE; + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: rate is not changed\n", + __FUNCTION__)); + } + + pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> confirm current rate MCS = %d!\n", pEntry->CurrTxRateIndex)); + + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("QuickAGS: <--- %s\n", __FUNCTION__)); +} +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +/* + The dynamic Tx rate switching for AGS in VHT(Adaptive Group Switching) + + Parameters + pAd: The adapter data structure + + Return Value: + None +*/ +VOID ApMlmeDynamicTxRateSwitchingAGS( + IN RTMP_ADAPTER *pAd, + IN INT idx) +{ + UCHAR *pTable, TableSize = 0; + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[idx]; + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + RTMP_RA_AGS_TB *pCurrTxRate = NULL; + RTMP_RA_LEGACY_TB *pNextTxRate = NULL; + BOOLEAN bTxRateChanged = TRUE, bUpgradeQuality = FALSE; + UCHAR TrainUp = 0, TrainDown = 0, next_grp; + CHAR RssiOffset = 0; + ULONG TxTotalCnt, TxErrorRatio = 0; + ULONG TxSuccess, TxRetransmit, TxFailCount; + AGS_STATISTICS_INFO AGSStatisticsInfo = {0}; + + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AGS: ---> %s\n", __FUNCTION__)); + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + +#ifdef FIFO_EXT_SUPPORT + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s()=>Wcid:%d, MCS:%d, TxErrRatio(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxTotalCnt = HwTxCnt; + TxErrorRatio = HwErrRatio; + + ApTxFailCntUpdate(pAd, pEntry, TxSuccess, TxRetransmit); + } +#endif /* FIFO_EXT_SUPPORT */ + + AGSStatisticsInfo.RSSI = RTMPAvgRssi(pAd, &pEntry->RssiSample); + AGSStatisticsInfo.TxErrorRatio = TxErrorRatio; + AGSStatisticsInfo.AccuTxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxSuccess = TxSuccess; + AGSStatisticsInfo.TxRetransmit = TxRetransmit; + AGSStatisticsInfo.TxFailCount = TxFailCount; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: AccuTxTotalCnt = %ld, TxSuccess = %ld, TxRetransmit = %ld, TxFailCount = %ld, TxErrorRatio = %ld\n", + __FUNCTION__, + AGSStatisticsInfo.AccuTxTotalCnt, + AGSStatisticsInfo.TxSuccess, + AGSStatisticsInfo.TxRetransmit, + AGSStatisticsInfo.TxFailCount, + AGSStatisticsInfo.TxErrorRatio)); + + pTable = pEntry->pTable; + TableSize = pTable[0]; + + CurrRateIdx = pEntry->CurrTxRateIndex; + + if (CurrRateIdx >= TableSize) + CurrRateIdx = TableSize - 1; + + + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(CurrRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + /* Select the next upgrade rate and the next downgrade rate, if any */ + do + { + if (pTable == AGS3x3HTRateTable) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: pEntry->AGSCtrl.MCSGroup = %d, TxQuality2[%d] = %d, " + "TxQuality1[%d] = %d, TxQuality0[%d] = %d, pCurrTxRate->upMcs1 = %d, " + "pCurrTxRate->ItemNo = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs3, + pEntry->TxQuality[pCurrTxRate->upMcs3], + pCurrTxRate->upMcs2, + pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, + pEntry->TxQuality[pCurrTxRate->upMcs1], + pCurrTxRate->upMcs1, + pCurrTxRate->ItemNo)); + + /* 3x3 */ + /* for 3*3, pEntry->AGSCtrl.MCSGroup = 0, 3, 3, 3, ... */ + next_grp = pEntry->AGSCtrl.MCSGroup; + switch (pEntry->AGSCtrl.MCSGroup) + { + case 0: /* MCS selection in round robin policy (different MCS group) */ + { + UpRateIdx = pCurrTxRate->upMcs3; + next_grp = 3; + + /* MCS group #2 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs2]) && + (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) + { + UpRateIdx = pCurrTxRate->upMcs2; + next_grp = 2; + } + + /* MCS group #1 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)) + { + UpRateIdx = pCurrTxRate->upMcs1; + next_grp = 1; + } + } + break; + + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("AGS> Current Group:%d, Select UpRateIdx=%d in group %d\n", + pEntry->AGSCtrl.MCSGroup, UpRateIdx, next_grp)); + + + if ((pEntry->AGSCtrl.MCSGroup == 0) && + (((pEntry->TxQuality[pCurrTxRate->upMcs3] > pEntry->TxQuality[pCurrTxRate->upMcs2]) && (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) || + ((pEntry->TxQuality[pCurrTxRate->upMcs3] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)))) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: ##############\n", __FUNCTION__)); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: [3x3 Before - " + "pEntry->AGSCtrl.MCSGroup = %d, TxQuality2[%d] = %d, " + "TxQuality1[%d] = %d, TxQuality0[%d] = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs3, + pEntry->TxQuality[pCurrTxRate->upMcs3], + pCurrTxRate->upMcs2, + pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, + pEntry->TxQuality[pCurrTxRate->upMcs1])); + } + } + else if ((pTable == AGS2x2HTRateTable) +#ifdef DOT11_VHT_AC + || (pTable == Ags2x2VhtRateTable) +#endif /* DOT11_VHT_AC*/ + ) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: pEntry->AGSCtrl.MCSGroup = %d, TxQuality1[%d] = %d, " + "TxQuality0[%d] = %d, pCurrTxRate->upMcs1 = %d, " + "pCurrTxRate->ItemNo = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs2, pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, pEntry->TxQuality[pCurrTxRate->upMcs1], + pCurrTxRate->upMcs1, pCurrTxRate->ItemNo)); + + /* 2x2 peer device (Adhoc, DLS or AP) */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 0: /* MCS selection in round robin policy */ + { + UpRateIdx = pCurrTxRate->upMcs2; + /* MCS group #1 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)) + UpRateIdx = pCurrTxRate->upMcs1; + } + break; + + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: [2x2 peer device (Adhoc, DLS or AP)], " + "Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + if ((pEntry->AGSCtrl.MCSGroup == 0) && + ((pEntry->TxQuality[pCurrTxRate->upMcs2] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo))) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: ###########\n", __FUNCTION__)); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: [2x2 peer device (Adhoc, DLS or AP)], Before - " + "pEntry->AGSCtrl.MCSGroup = %d, TxQuality1[%d] = %d, " + "TxQuality0[%d] = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup, + pCurrTxRate->upMcs2, + pEntry->TxQuality[pCurrTxRate->upMcs2], + pCurrTxRate->upMcs1, + pEntry->TxQuality[pCurrTxRate->upMcs1])); + } + } + else + { + /* 1x1 peer device (Adhoc, DLS or AP) */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 1: + case 0: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: [1x1 peer device (Adhoc, DLS or AP)], " + "Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup)); + } + break; + } + } + + + /* The STA uses the best Tx rate at this moment. */ + if (UpRateIdx == pEntry->CurrTxRateIndex) + { + /* current rate is the best one */ + pEntry->AGSCtrl.MCSGroup = 0; /* Try to escape the local optima */ + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> Current rate is the best one!\n")); + break; + } + + if ((pEntry->TxQuality[UpRateIdx] > 0) && (pEntry->AGSCtrl.MCSGroup > 0)) + { + /* + Quality of up rate is bad try to use lower group. + So continue to get the up rate index. + */ + pEntry->AGSCtrl.MCSGroup--; /* Try to use the MCS of the lower MCS group */ + } + else + { + break; + } + } while (1); + + DownRateIdx = pCurrTxRate->downMcs; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> UpRateIdx = %d, DownRateIdx = %d\n", + UpRateIdx, DownRateIdx)); + +#ifdef DOT11_N_SUPPORT + if ((AGSStatisticsInfo.RSSI > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + /* Keep the TxRateChangeAction status */ + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: Rssi = %d, TxSuccess = %lu, TxRetransmit = %lu, TxFailCount = %lu, TxErrorRatio = %lu\n", + __FUNCTION__, + AGSStatisticsInfo.RSSI, + AGSStatisticsInfo.TxSuccess, + AGSStatisticsInfo.TxRetransmit, + AGSStatisticsInfo.TxFailCount, + AGSStatisticsInfo.TxErrorRatio)); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: Before - CurrTxRateIdx = %d, MCS = %d, STBC = %d, ShortGI = %d, Mode = %d, " + "TrainUp = %d, TrainDown = %d, NextUp = %d, NextDown = %d, " + "CurrMCS = %d, pEntry->AGSCtrl.MCSGroup = %d, PER = %lu%%, Retry = %lu, NoRetry = %lu\n", + __FUNCTION__, + CurrRateIdx, + pCurrTxRate->CurrMCS, + pCurrTxRate->STBC, + pCurrTxRate->ShortGI, + pCurrTxRate->Mode, + TrainUp, + TrainDown, + UpRateIdx, + DownRateIdx, + pEntry->HTPhyMode.field.MCS, + pEntry->AGSCtrl.MCSGroup, + AGSStatisticsInfo.TxErrorRatio, + AGSStatisticsInfo.TxRetransmit, + AGSStatisticsInfo.TxSuccess)); + + /* MCS selection based on the RSSI information when the Tx samples are fewer than 15. */ + if (AGSStatisticsInfo.AccuTxTotalCnt <= 15) + { + CHAR idx = 0; + UCHAR TxRateIdx; + UCHAR MCS[24] = {0}; + /* Check the existence and index of each needed MCS */ + +#ifdef DOT11_VHT_AC + if ((pTable == Ags2x2VhtRateTable) || (pTable == Ags1x1VhtRateTable)) + { + INT mcs_idx_offset; + while (idx < pTable[0]) + { + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + if (pCurrTxRate->Mode == MODE_VHT) + { + if (pCurrTxRate->Nss == NSS_1) + mcs_idx_offset = 0; + else if ((pCurrTxRate->Nss == NSS_2) && (pTable == Ags2x2VhtRateTable)) + mcs_idx_offset = 8; + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid Nss(%d)\n", __FUNCTION__, pCurrTxRate->Nss)); + mcs_idx_offset = 0; + } + + if ((pCurrTxRate->CurrMCS <= MCS_7) /* && (pCurrTxRate->CurrMCS >= MCS_0) */) + MCS[pCurrTxRate->CurrMCS + mcs_idx_offset] = idx; + } + idx++; + } + } + else +#endif /* DOT11_VHT_AC */ + { + while (idx < pTable[0]) + { + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if (pCurrTxRate->CurrMCS <= MCS_23 /* && pCurrTxRate->CurrMCS >= MCS_0 */) + MCS[pCurrTxRate->CurrMCS] = idx; + idx++; + } + } + + /* peer device (Adhoc, DLS or AP) */ + RssiOffset = 0; + if (pTable == AGS3x3HTRateTable) + { + if (MCS[23] && (AGSStatisticsInfo.RSSI > (-67 + RssiOffset))) + TxRateIdx = MCS[23]; + else if (MCS[22] && (AGSStatisticsInfo.RSSI > (-69 + RssiOffset))) + TxRateIdx = MCS[22]; + else if (MCS[21] && (AGSStatisticsInfo.RSSI > (-72 + RssiOffset))) + TxRateIdx = MCS[21]; + else if (MCS[20] && (AGSStatisticsInfo.RSSI > (-74 + RssiOffset))) + TxRateIdx = MCS[20]; + else if (MCS[19] && (AGSStatisticsInfo.RSSI > (-78 + RssiOffset))) + TxRateIdx = MCS[19]; + else if (MCS[18] && (AGSStatisticsInfo.RSSI > (-80 + RssiOffset))) + TxRateIdx = MCS[18]; + else if (MCS[17] && (AGSStatisticsInfo.RSSI > (-85 + RssiOffset))) + TxRateIdx = MCS[17]; + else + TxRateIdx = MCS[16]; + + pEntry->AGSCtrl.MCSGroup = 3; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> Group3 RSSI = %d, TxRateIdx = %d\n", + AGSStatisticsInfo.RSSI, TxRateIdx)); + } + else if ((pTable == AGS2x2HTRateTable) +#ifdef DOT11_VHT_AC + || (pTable == Ags2x2VhtRateTable) +#endif /* DOT11_VHT_AC */ + ) + { +#ifdef DOT11_VHT_AC + if (pTable == Ags2x2VhtRateTable) + RssiOffset = AgsRssiOffsetTable[1][pAd->CommonCfg.BBPCurrentBW]; +#endif /* DOT11_VHT_AC */ + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: AGS: 2*2, RssiOffsetForAgs=%d\n", __FUNCTION__, RssiOffset)); + + if (MCS[15] && (AGSStatisticsInfo.RSSI > (-69 + RssiOffset))) + TxRateIdx = MCS[15]; + else if (MCS[14] && (AGSStatisticsInfo.RSSI > (-71 + RssiOffset))) + TxRateIdx = MCS[14]; + else if (MCS[13] && (AGSStatisticsInfo.RSSI > (-74 + RssiOffset))) + TxRateIdx = MCS[13]; + else if (MCS[12] && (AGSStatisticsInfo.RSSI > (-76 + RssiOffset))) + TxRateIdx = MCS[12]; + else if (MCS[11] && (AGSStatisticsInfo.RSSI > (-80 + RssiOffset))) + TxRateIdx = MCS[11]; + else if (MCS[10] && (AGSStatisticsInfo.RSSI > (-82 + RssiOffset))) + TxRateIdx = MCS[10]; + else if (MCS[9] && (AGSStatisticsInfo.RSSI > (-87 + RssiOffset))) + TxRateIdx = MCS[9]; + else + TxRateIdx = MCS[8]; + + pEntry->AGSCtrl.MCSGroup = 2; + } + else + { +#ifdef DOT11_VHT_AC + if (pTable == Ags1x1VhtRateTable) + RssiOffset = AgsRssiOffsetTable[0][pAd->CommonCfg.BBPCurrentBW]; +#endif /* DOT11_VHT_AC */ + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: 1*1, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 1x1 peer device (Adhoc, DLS or AP) */ + if (MCS[7] && (AGSStatisticsInfo.RSSI > (-71 + RssiOffset))) + TxRateIdx = MCS[7]; + else if (MCS[6] && (AGSStatisticsInfo.RSSI > (-73 + RssiOffset))) + TxRateIdx = MCS[6]; + else if (MCS[5] && (AGSStatisticsInfo.RSSI > (-76 + RssiOffset))) + TxRateIdx = MCS[5]; + else if (MCS[4] && (AGSStatisticsInfo.RSSI > (-78 + RssiOffset))) + TxRateIdx = MCS[4]; + else if (MCS[3] && (AGSStatisticsInfo.RSSI > (-82 + RssiOffset))) + TxRateIdx = MCS[3]; + else if (MCS[2] && (AGSStatisticsInfo.RSSI > (-84 + RssiOffset))) + TxRateIdx = MCS[2]; + else if (MCS[1] && (AGSStatisticsInfo.RSSI > (-89 + RssiOffset))) + TxRateIdx = MCS[1]; + else + TxRateIdx = MCS[0]; + + pEntry->AGSCtrl.MCSGroup = 1; + } + + pEntry->AGSCtrl.lastRateIdx = pEntry->CurrTxRateIndex; + pEntry->CurrTxRateIndex = TxRateIdx; + + pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + APMlmeSetTxRate(pAd, pEntry, pNextTxRate); + + RTMPZeroMemory(pEntry->TxQuality, (sizeof(USHORT) * (MAX_TX_RATE_INDEX+1))); + RTMPZeroMemory(pEntry->PER, (sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1))); + + pEntry->fLastSecAccordingRSSI = TRUE; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + return; + } + + /* The MCS selection is based on the RSSI and skips the rate tuning this time. */ + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: The MCS selection base on RSSI\n", __FUNCTION__)); + + return; + } + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: TrainUp:%d, TrainDown:%d\n", __FUNCTION__, TrainUp, TrainDown)); + + do + { + BOOLEAN bTrainUpDown = FALSE; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: TxQuality[CurrRateIdx(%d)] = %d, UpPenalty:%d\n", + __FUNCTION__, CurrRateIdx, + pEntry->TxQuality[CurrRateIdx], pEntry->TxRateUpPenalty)); + + if (AGSStatisticsInfo.TxErrorRatio >= TrainDown) /* Poor quality */ + { + /* error ratio too high, do rate down */ + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: (DOWN) TxErrorRatio >= TrainDown\n",__FUNCTION__)); + bTrainUpDown = TRUE; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + } + else if (AGSStatisticsInfo.TxErrorRatio <= TrainUp) /* Good quality */ + { + bTrainUpDown = TRUE; + bUpgradeQuality = TRUE; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: (UP) pEntry->TxQuality[CurrRateIdx] = %d, pEntry->TxRateUpPenalty = %d\n", + __FUNCTION__, + pEntry->TxQuality[CurrRateIdx], + pEntry->TxRateUpPenalty)); + + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; /* Good quality in the current Tx rate */ + + if (pEntry->TxRateUpPenalty) + pEntry->TxRateUpPenalty--; /* no use for the parameter */ + else + { + if (pEntry->TxQuality[pCurrTxRate->upMcs3] && (pCurrTxRate->upMcs3 != CurrRateIdx)) + pEntry->TxQuality[pCurrTxRate->upMcs3]--; + + if (pEntry->TxQuality[pCurrTxRate->upMcs2] && (pCurrTxRate->upMcs2 != CurrRateIdx)) + pEntry->TxQuality[pCurrTxRate->upMcs2]--; + + if (pEntry->TxQuality[pCurrTxRate->upMcs1] && (pCurrTxRate->upMcs1 != CurrRateIdx)) + pEntry->TxQuality[pCurrTxRate->upMcs1]--; + } + } + else if (pEntry->AGSCtrl.MCSGroup > 0) /* even if TxErrorRatio > TrainUp */ + { + /* not bad and not good */ + if (UpRateIdx != 0) + { + bTrainUpDown = FALSE; + + /* Good quality in the current Tx rate */ + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; + + /* It may improve next train-up Tx rate's quality */ + if (pEntry->TxQuality[UpRateIdx]) + pEntry->TxQuality[UpRateIdx]--; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> not bad and not good\n")); + } + } + + /* update error ratio for current MCS */ + pEntry->PER[CurrRateIdx] = (UCHAR)(AGSStatisticsInfo.TxErrorRatio); + + /* Update the current Tx rate */ + if (bTrainUpDown) + { + /* need to rate up or down */ + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: AGS: bTrainUpDown = %d, CurrRateIdx = %d, DownRateIdx = %d, UpRateIdx = %d, pEntry->TxQuality[CurrRateIdx] = %d, pEntry->TxQuality[UpRateIdx] = %d\n", + __FUNCTION__, + bTrainUpDown, CurrRateIdx, DownRateIdx, UpRateIdx, + pEntry->TxQuality[CurrRateIdx], pEntry->TxQuality[UpRateIdx])); + + /* Downgrade Tx rate */ + if ((CurrRateIdx != DownRateIdx) && + (pEntry->TxQuality[CurrRateIdx] >= AGS_TX_QUALITY_WORST_BOUND)) + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> rate down!\n")); + } + else if ((CurrRateIdx != UpRateIdx) && + (pEntry->TxQuality[UpRateIdx] <= 0)) /* Upgrade Tx rate */ + { + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> rate up!\n")); + } + } + } while (FALSE); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: pEntry->CurrTxRateIndex = %d, CurrRateIdx = %d, pEntry->LastSecTxRateChangeAction = %d\n", + __FUNCTION__, + pEntry->CurrTxRateIndex, CurrRateIdx, + pEntry->LastSecTxRateChangeAction)); + + /* rate up/down post handle */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == RATE_UP)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: ++TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->LastSecTxRateChangeAction = RATE_UP; + pEntry->TxRateUpPenalty = 0; + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + pEntry->AGSCtrl.lastRateIdx = CurrRateIdx; + + bTxRateChanged = TRUE; + } + else if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == RATE_DOWN)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: --TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + pEntry->TxRateUpPenalty = 0; /* No penalty */ + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + pEntry->AGSCtrl.lastRateIdx = CurrRateIdx; + + bTxRateChanged = TRUE; + } + else /* Tx rate remains unchanged. */ + { + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; /* Tx rate remains unchanged. */ + bTxRateChanged = FALSE; + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> no rate up/down!\n")); + } + + /* Tx rate fast train up/down */ + if ((bTxRateChanged == TRUE) && + (!pAd->ApCfg.ApQuickResponeForRateUpTimerRunning)) + { + RTMPSetTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, pAd->ra_fast_interval); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = TRUE; + } + pEntry->LastTxOkCount = AGSStatisticsInfo.TxSuccess; + + /* set new tx rate */ + pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> set new rate MCS = %d!\n", pEntry->CurrTxRateIndex)); + APMlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AGS: <--- %s\n", __FUNCTION__)); +} + + +/* + Auto Tx rate faster train up/down for AGS (Adaptive Group Switching) + + Parameters + pAd: The adapter data structure + pEntry: Pointer to a caller-supplied variable in which points to a MAC table entry + pTable: Pointer to a caller-supplied variable in wich points to a Tx rate switching table + TableSize: The size, in bytes, of the specified Tx rate switching table + pAGSStatisticsInfo: Pointer to a caller-supplied variable in which points to the statistics information + + Return Value: + None +*/ +VOID ApQuickResponeForRateUpExecAGS( + IN RTMP_ADAPTER *pAd, + IN INT idx) +{ + UCHAR *pTable, TableSize = 0; + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + RTMP_RA_AGS_TB *pCurrTxRate = NULL; + RTMP_RA_LEGACY_TB *pNextTxRate = NULL; + BOOLEAN bTxRateChanged = TRUE; + UCHAR TrainUp = 0, TrainDown = 0; + CHAR ratio = 0; + ULONG OneSecTxNoRetryOKRationCount = 0; + MAC_TABLE_ENTRY *pEntry; + AGS_STATISTICS_INFO AGSStatisticsInfo = {0}; + ULONG TxTotalCnt, TxErrorRatio = 0; + ULONG TxSuccess, TxRetransmit, TxFailCount; + + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("QuickAGS: ---> %s\n", __FUNCTION__)); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE; + + pEntry = &pAd->MacTab.Content[idx]; /* point to information of the individual station */ + pTable = pEntry->pTable; + TableSize = pTable[0]; + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + +#ifdef FIFO_EXT_SUPPORT + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s()=>Wcid:%d, MCS:%d, TxErrRatio(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxTotalCnt = HwTxCnt; + TxErrorRatio = HwErrRatio; + + ApTxFailCntUpdate(pAd, pEntry, TxSuccess, TxRetransmit); + } +#endif /* FIFO_EXT_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: QuickAGS: AccuTxTotalCnt = %lu, TxSuccess = %lu, " + "TxRetransmit = %lu, TxFailCount = %lu, TxErrorRatio = %lu\n", + __FUNCTION__, + AGSStatisticsInfo.AccuTxTotalCnt, + AGSStatisticsInfo.TxSuccess, + AGSStatisticsInfo.TxRetransmit, + AGSStatisticsInfo.TxFailCount, + AGSStatisticsInfo.TxErrorRatio)); + + CurrRateIdx = pEntry->CurrTxRateIndex; + + if (CurrRateIdx >= TableSize) + CurrRateIdx = TableSize - 1; + + UpRateIdx = DownRateIdx = pEntry->AGSCtrl.lastRateIdx; + + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(CurrRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if ((AGSStatisticsInfo.RSSI > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + /* MCS selection based on the RSSI information when the Tx samples are fewer than 15. */ + if (AGSStatisticsInfo.AccuTxTotalCnt <= 15) + { + RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1)); + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + + if ((pEntry->LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + } + else if ((pEntry->LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) + { + pEntry->CurrTxRateIndex = UpRateIdx; + } + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: QuickAGS: AccuTxTotalCnt <= 15, train back to original rate\n", + __FUNCTION__)); + + return; + } + + do + { + if (pEntry->LastTimeTxRateChangeAction == 0) + ratio = 5; + else + ratio = 4; + + if (AGSStatisticsInfo.TxErrorRatio >= TrainDown) /* Poor quality */ + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + + pEntry->PER[CurrRateIdx] = (UCHAR)(AGSStatisticsInfo.TxErrorRatio); + + OneSecTxNoRetryOKRationCount = (AGSStatisticsInfo.TxSuccess * ratio); + + /* Tx rate down */ + if ((pEntry->LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + // Change Auto Rate tuning rule 1: Change from tx_ok to PER + if (AGSStatisticsInfo.TxErrorRatio > TrainDown) /* Poor quality */ + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: QuickAGS: (UP) bad Tx ok count (Current PER:%ld, NewMcs's TrainDown:%d)\n", + __FUNCTION__, AGSStatisticsInfo.TxErrorRatio, TrainDown)); + } + else /* Good quality */ + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s: QuickAGS: (UP) keep rate-up (Current PER:%ld, NewMcs's TrainDown:%d)\n", + __FUNCTION__, AGSStatisticsInfo.TxErrorRatio, TrainDown)); + + RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1)); + + if (pEntry->AGSCtrl.MCSGroup == 0) + { + if (pTable == AGS3x3HTRateTable) + pEntry->AGSCtrl.MCSGroup = 3; + else if ((pTable == AGS2x2HTRateTable) || + (pTable == Ags2x2VhtRateTable)) + pEntry->AGSCtrl.MCSGroup = 2; + else + pEntry->AGSCtrl.MCSGroup = 1; + } + } + } + else if ((pEntry->LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) // Tx rate up + { + +// Don't quick check within train down case + } + }while (FALSE); + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, + ("ags> new group = %d\n", pEntry->AGSCtrl.MCSGroup)); + + /* Last action is rate-up */ + if (pEntry->LastSecTxRateChangeAction == 1) + { + /* looking for the next group with valid MCS */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && (pEntry->AGSCtrl.MCSGroup > 0)) + { + pEntry->AGSCtrl.MCSGroup--; /* Try to use the MCS of the lower MCS group */ + pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(DownRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + } + + /* UpRateIdx is for temp use in this section */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + + case 0: + UpRateIdx = CurrRateIdx; + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + /* Try to escape the local optima */ + if (UpRateIdx == pEntry->CurrTxRateIndex) + pEntry->AGSCtrl.MCSGroup = 0; + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: next MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, pEntry->AGSCtrl.MCSGroup)); + } + + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == 2)) /* Tx rate up */ + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: ++TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->TxRateUpPenalty = 0; + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; /*restore the TxQuality from max to 0 */ + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + } + else if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == 1)) /* Tx rate down */ + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: --TX rate from %d to %d\n", + __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex)); + + pEntry->TxRateUpPenalty = 0; /* No penalty */ + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + } + else + { + bTxRateChanged = FALSE; + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: rate is not changed\n", __FUNCTION__)); + } + + pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> confirm current rate MCS = %d!\n", pEntry->CurrTxRateIndex)); + + APMlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("QuickAGS: <--- %s\n", __FUNCTION__)); +} +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* AGS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_grp.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_grp.c new file mode 100644 index 000000000..82d91c947 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_grp.c @@ -0,0 +1,2828 @@ +/**************************************************************************** + * 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 Dynamic Rate Switch (AP/STA) function body. + + History: + +***************************************************************************/ + +#ifdef NEW_RATE_ADAPT_SUPPORT +#include "rt_config.h" + +VOID MlmeCaliRSSITable(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, CHAR Rssi, PUCHAR pTable) +{ + CHAR ii; + UCHAR EstiTxRateIdx = 0; + UCHAR WiFiMode, CurrMCSRate; + CHAR mcs[24]; + RTMP_RA_GRP_TB *pEstiTxRate, *pCurrTxRate; + + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, pEntry->CurrTxRateIndex); + + WiFiMode = pCurrTxRate->Mode; + CurrMCSRate = pCurrTxRate->CurrMCS; + + DBGPRINT(RT_DEBUG_TRACE ,("RSSI %d\n", Rssi)); + + if((WiFiMode == MODE_CCK) || (WiFiMode == MODE_OFDM)) + { + pEntry->RX_RSSI_MCS = 0; + return; + } + + // Cover 16dB, about 4~5 MCS Steps + for(ii = 4; ii > -12; ii--) + { + UCHAR EstiMCSRate; + /* Check existence and get index of each MCS */ + MlmeGetSupportedMcsAdapt(pAd, pEntry, GI_400, mcs); + EstiTxRateIdx = MlmeSelectTxRateAdapt(pAd, pEntry, mcs, Rssi, ii); + pEstiTxRate = PTX_RA_GRP_ENTRY(pTable, EstiTxRateIdx); + EstiMCSRate = pEstiTxRate->CurrMCS; + + pEntry->RX_RSSI_MCS = ii; + + if((WiFiMode == MODE_HTMIX) || (WiFiMode == MODE_HTGREENFIELD)) + { + DBGPRINT(RT_DEBUG_TRACE ,("HT Mode %d | %d\n", (EstiMCSRate & 0x07), (CurrMCSRate & 0x07))); + if((EstiMCSRate & 0x07) == (CurrMCSRate & 0x07)) + { + break; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE ,("VHT Mode %d | %d\n", EstiMCSRate, CurrMCSRate)); + if(EstiMCSRate == CurrMCSRate) + { + break; + } + } + } + + return; +} + + +/* + MlmeSetMcsGroup - set initial mcsGroup based on supported MCSs + On exit pEntry->mcsGroup is set to the mcsGroup +*/ +VOID MlmeSetMcsGroup(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ +#ifdef DOT11_VHT_AC + // TODO: shiang-6590, fix me!! + if (pEntry->SupportRateMode & SUPPORT_VHT_MODE) + { + if ((pAd->CommonCfg.TxStream == 2) && (pEntry->SupportVHTMCS[10] == 0x1)) + pEntry->mcsGroup = 2; + else + pEntry->mcsGroup = 1; + } + else +#endif /* DOT11_VHT_AC */ +#ifdef DOT11N_SS3_SUPPORT + if ((pEntry->HTCapability.MCSSet[2] == 0xff) && (pAd->CommonCfg.TxStream == 3)) + pEntry->mcsGroup = 3; + else +#endif /* DOT11N_SS3_SUPPORT */ + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && + (pEntry->HTCapability.MCSSet[1] == 0xff) && + (pAd->CommonCfg.TxStream > 1) && + ((pAd->CommonCfg.TxStream == 2) || (pEntry->HTCapability.MCSSet[2] == 0x0))) + pEntry->mcsGroup = 2; + else + pEntry->mcsGroup = 1; + +#ifdef THERMAL_PROTECT_SUPPORT + if (pAd->force_one_tx_stream == TRUE) + { + pEntry->mcsGroup = 1; + } +#endif /* THERMAL_PROTECT_SUPPORT */ +} + + +/* + MlmeSelectUpRate - select UpRate based on MCS group + returns the UpRate index and updates the MCS group +*/ +UCHAR MlmeSelectUpRate( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_GRP_TB *pCurrTxRate) +{ + UCHAR UpRateIdx = 0; + UCHAR grp_cnt; + +#ifdef DOT11_VHT_AC + if ((pEntry->pTable == RateTableVht2S) || (pEntry->pTable == RateTableVht2S_BW20) + || (pEntry->pTable == RateTableVht2S_BW40) || (pEntry->pTable == RateTableVht2S_MCS7) + || (pEntry->pTable == RateTableVht2S_2G_BW20) || (pEntry->pTable == RateTableVht2S_2G_BW40)) + grp_cnt = 2; + else if ((pEntry->pTable == RateTableVht1S) || (pEntry->pTable == RateTableVht1S_MCS9) + || (pEntry->pTable == RateTableVht1S_2G_BW20) || (pEntry->pTable == RateTableVht1S_2G_BW40)) + grp_cnt = 1; + else +#endif /* DOT11_VHT_AC */ + if ((pEntry->HTCapability.MCSSet[2] == 0xff) && (pAd->CommonCfg.TxStream == 3)) + grp_cnt =3; + else if ((pEntry->HTCapability.MCSSet[0] == 0xff) && + (pEntry->HTCapability.MCSSet[1] == 0xff) && + (pAd->CommonCfg.TxStream > 1) && + ((pAd->CommonCfg.TxStream == 2) || (pEntry->HTCapability.MCSSet[2] == 0x0))) + grp_cnt = 2; + else + grp_cnt = 1; + +#ifdef THERMAL_PROTECT_SUPPORT + if (pAd->force_one_tx_stream == TRUE) + { + grp_cnt = 1; + } +#endif /* THERMAL_PROTECT_SUPPORT */ + + + while (1) + { + if (grp_cnt == 3) + { + switch (pEntry->mcsGroup) + { + case 0:/* improvement: use round robin mcs when group == 0 */ + UpRateIdx = pCurrTxRate->upMcs3; + if (UpRateIdx == pCurrTxRate->ItemNo) + { + UpRateIdx = pCurrTxRate->upMcs2; + if (UpRateIdx == pCurrTxRate->ItemNo) + UpRateIdx = pCurrTxRate->upMcs1; + } + + if (MlmeGetTxQuality(pEntry, UpRateIdx) > MlmeGetTxQuality(pEntry, pCurrTxRate->upMcs2) && + pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo) + UpRateIdx = pCurrTxRate->upMcs2; + + if (MlmeGetTxQuality(pEntry, UpRateIdx) > MlmeGetTxQuality(pEntry, pCurrTxRate->upMcs1) && + pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo) + UpRateIdx = pCurrTxRate->upMcs1; + break; + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + default: + DBGPRINT_RAW(RT_DEBUG_ERROR, ("3ss:wrong mcsGroup value\n")); + break; + } + } + else if (grp_cnt == 2) + { + switch (pEntry->mcsGroup) + { + case 0: + UpRateIdx = pCurrTxRate->upMcs2; + if (UpRateIdx == pCurrTxRate->ItemNo) + UpRateIdx = pCurrTxRate->upMcs1; + + if (MlmeGetTxQuality(pEntry, UpRateIdx) > MlmeGetTxQuality(pEntry, pCurrTxRate->upMcs1) && + pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo) + UpRateIdx = pCurrTxRate->upMcs1; + break; + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + default: + DBGPRINT_RAW(RT_DEBUG_TRACE, ("2ss:wrong mcsGroup value %d\n", pEntry->mcsGroup)); + break; + } + } + else if (grp_cnt == 1) + { + switch (pEntry->mcsGroup) + { + case 1: + case 0: + UpRateIdx = pCurrTxRate->upMcs1; + break; + default: + DBGPRINT_RAW(RT_DEBUG_TRACE, ("1ss:wrong mcsGroup value %d\n", pEntry->mcsGroup)); + break; + } + } else { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("wrong mcsGroup cnt %d\n", grp_cnt)); + } + + /* If going up from CCK to MCS32 make sure it's allowed */ + if (PTX_RA_GRP_ENTRY(pEntry->pTable, UpRateIdx)->CurrMCS == 32) + { + /* If not allowed then skip over it */ + BOOLEAN mcs32Supported = 0; + BOOLEAN mcs0Fallback = 0; + + if ((pEntry->HTCapability.MCSSet[4] & 0x1) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_ENABLE_HT_DUP) +#endif /* DBG_CTRL_SUPPORT */ + ) + mcs32Supported = 1; + +#ifdef DBG_CTRL_SUPPORT + if ((pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS0)==0) + mcs0Fallback = 1; +#endif /* DBG_CTRL_SUPPORT */ + + if (pEntry->MaxHTPhyMode.field.BW != BW_40 || + pAd->CommonCfg.BBPCurrentBW != BW_40 || + (!mcs32Supported && !mcs0Fallback)) + { + UpRateIdx = PTX_RA_GRP_ENTRY(pEntry->pTable, UpRateIdx)->upMcs1; + pEntry->mcsGroup = 1; + break; + } + } + + /* If ShortGI and not allowed then mark it as bad. We'll try another group below */ + if (PTX_RA_GRP_ENTRY(pEntry->pTable, UpRateIdx)->ShortGI && + !pEntry->MaxHTPhyMode.field.ShortGI) + { + MlmeSetTxQuality(pEntry, UpRateIdx, DRS_TX_QUALITY_WORST_BOUND*2); + } + + /* If we reached the end of the group then select the best next time */ + if (UpRateIdx == pEntry->CurrTxRateIndex) + { + pEntry->mcsGroup = 0; + break; + } + + /* If the current group has bad TxQuality then try another group */ + if ((MlmeGetTxQuality(pEntry, UpRateIdx) > 0) && (pEntry->mcsGroup > 0)) + pEntry->mcsGroup--; + else + break; + } + + return UpRateIdx; +} + +/* + MlmeSelectDownRate - select DownRate. + pEntry->pTable is assumed to be a pointer to an adaptive rate table with mcsGroup values + CurrRateIdx - current rate index + returns the DownRate index. Down Rate = CurrRateIdx if there is no valid Down Rate +*/ +UCHAR MlmeSelectDownRate( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurrRateIdx) +{ + UCHAR DownRateIdx = PTX_RA_GRP_ENTRY(pEntry->pTable, CurrRateIdx)->downMcs; + RTMP_RA_GRP_TB *pDownRate; + + /* Loop until a valid down rate is found */ + while (1) { + pDownRate = PTX_RA_GRP_ENTRY(pEntry->pTable, DownRateIdx); + + /* Break out of loop if rate is valid */ + if (pDownRate->Mode==MODE_CCK) + { + /* CCK is valid only if in G band and if not disabled */ + if ((pAd->LatchRfRegs.Channel<=14 +#ifdef DBG_CTRL_SUPPORT + || (pAd->CommonCfg.DebugFlags & DBF_ENABLE_CCK_5G) +#endif /* DBG_CTRL_SUPPORT */ + ) +#ifdef DBG_CTRL_SUPPORT + && ((pAd->CommonCfg.DebugFlags & DBF_DISABLE_CCK)==0) +#endif /* DBG_CTRL_SUPPORT */ + ) + break; + } + else if (pDownRate->CurrMCS == MCS_32) + { + BOOLEAN valid_mcs32 = FALSE; + + if ((pEntry->MaxHTPhyMode.field.BW == BW_40 && pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef DOT11_VHT_AC + || (pEntry->MaxHTPhyMode.field.BW == BW_80 && pAd->CommonCfg.BBPCurrentBW == BW_80) +#endif /* DOT11_VHT_AC */ + ) + valid_mcs32 = TRUE; + + /* If 20MHz MCS0 fallback enabled and in 40MHz then MCS32 is valid and will be mapped to 20MHz MCS0 */ + if (valid_mcs32 +#ifdef DBG_CTRL_SUPPORT + && ((pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS0)==0) +#endif /* DBG_CTRL_SUPPORT */ + ) + break; + + /* MCS32 is valid if enabled and client supports it */ + if (valid_mcs32 && (pEntry->HTCapability.MCSSet[4] & 0x1) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_ENABLE_HT_DUP) +#endif /* DBG_CTRL_SUPPORT */ + ) + break; + } + else + break; /* All other rates are valid */ + + /* Return original rate if we reached the end without finding a valid rate */ + if (DownRateIdx == pDownRate->downMcs) + return CurrRateIdx; + + /* Otherwise try the next lower rate */ + DownRateIdx = pDownRate->downMcs; + } + + return DownRateIdx; +} + + +/* + MlmeSupportMaxRate - Limit Max Rate in the table of supported MCSs + pAd - pointer to adapter + pEntry - MAC Table entry. pEntry->pTable is a rate table with mcsGroup values +*/ +VOID MlmeLimitMaxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pRateIdx, + IN UCHAR ucDirection) +{ + PUCHAR pTable; + RTMP_RA_GRP_TB *pCurrTxRate, *pUpTxRate; + UCHAR CurrRateIdx, UpRateIdx; + UCHAR MAXMCSRate; + + pTable = pEntry->pTable; + + // Check Current Max Limit MCS Rate + if(ucDirection == RATE_NO_CHANGE) + { + CurrRateIdx = *pRateIdx; + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + + DBGPRINT(RT_DEBUG_INFO, ("Max MCS %X\n", pEntry->MaxHTPhyMode.field.MCS)); + + if(pCurrTxRate->CurrMCS == MCS_32) + return; + + //CCK / OFDM without Limit + if(pCurrTxRate->Mode < MODE_HTMIX) + return; + + if(pEntry->SupportRateMode & SUPPORT_VHT_MODE) { + MAXMCSRate = pEntry->MaxHTPhyMode.field.MCS & 0x0F; + } + else if(pEntry->SupportRateMode & SUPPORT_HT_MODE) { + if(pCurrTxRate->CurrMCS > MCS_8) { // 7612 Support Only 2SS + MAXMCSRate = pEntry->MaxHTPhyMode.field.MCS | 0x08; + } + else { + MAXMCSRate = pEntry->MaxHTPhyMode.field.MCS; + } + } + else { + return; + } + + while(pCurrTxRate->CurrMCS > MAXMCSRate) { + if(pCurrTxRate->CurrMCS == MCS_0) + break; + + CurrRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + } + + *pRateIdx = CurrRateIdx; + + return; + } + // Check Max Limit MCS Rate when happen up rate process + else if(ucDirection == RATE_UP) + { + UpRateIdx = *pRateIdx; + pUpTxRate = PTX_RA_GRP_ENTRY(pTable, UpRateIdx); + + if(pUpTxRate->CurrMCS == MCS_32) + return; + + //CCK / OFDM without Limit + if(pUpTxRate->Mode < MODE_HTMIX) + return; + + if(pEntry->SupportRateMode & SUPPORT_VHT_MODE) { + if(pUpTxRate->CurrMCS > (pEntry->MaxHTPhyMode.field.MCS & 0x0F)) + *pRateIdx = pEntry->CurrTxRateIndex; + } + else if(pEntry->SupportRateMode & SUPPORT_HT_MODE) { + if((pUpTxRate->CurrMCS & 0x07) > (pEntry->MaxHTPhyMode.field.MCS & 0x07)) + *pRateIdx = pEntry->CurrTxRateIndex; + } + return; + } + else + return; +} + +/* + MlmeGetSupportedMcsAdapt - fills in the table of supported MCSs + pAd - pointer to adapter + pEntry - MAC Table entry. pEntry->pTable is a rate table with mcsGroup values + mcs23GI - the MCS23 entry will have this guard interval + mcs - table of MCS index into the Rate Table. -1 => not supported +*/ +VOID MlmeGetSupportedMcsAdapt( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR mcs23GI, + OUT CHAR mcs[]) +{ + CHAR idx; + RTMP_RA_GRP_TB *pCurrTxRate; + UCHAR *pTable = pEntry->pTable; + + for (idx=0; idx<24; idx++) + mcs[idx] = -1; + +#ifdef DOT11_VHT_AC + if ((pEntry->pTable == RateTableVht1S) || (pEntry->pTable == RateTableVht2S) + || (pEntry->pTable == RateTableVht2S_BW20) + || (pEntry->pTable == RateTableVht2S_BW40) + || (pEntry->pTable == RateTableVht2S_MCS7) + || (pEntry->pTable == RateTableVht1S_2G_BW20) || (pEntry->pTable == RateTableVht1S_2G_BW40) + || (pEntry->pTable == RateTableVht2S_2G_BW20) || (pEntry->pTable == RateTableVht2S_2G_BW40) + ) + { + for (idx = 0; idx < RATE_TABLE_SIZE(pTable); idx++) + { + pCurrTxRate = PTX_RA_GRP_ENTRY(pEntry->pTable, idx); + if (pCurrTxRate->CurrMCS == MCS_RATE_6 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[20] = idx; + else if (pCurrTxRate->CurrMCS == MCS_RATE_9 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[21] = idx; + else if (pCurrTxRate->CurrMCS == MCS_RATE_12 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[22] = idx; + else if (pCurrTxRate->CurrMCS == MCS_RATE_18 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[23] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_0) && (pCurrTxRate->dataRate == 1) && (mcs[0] == -1)) + mcs[0] = idx; + else if (pCurrTxRate->CurrMCS == MCS_1 && pCurrTxRate->dataRate == 1) + mcs[1] = idx; + else if (pCurrTxRate->CurrMCS == MCS_2 && pCurrTxRate->dataRate == 1) + mcs[2] = idx; + else if (pCurrTxRate->CurrMCS == MCS_3 && pCurrTxRate->dataRate == 1) + mcs[3] = idx; + else if (pCurrTxRate->CurrMCS == MCS_4 && pCurrTxRate->dataRate == 1) + mcs[4] = idx; + else if (pCurrTxRate->CurrMCS == MCS_5 && pCurrTxRate->dataRate == 1) + mcs[5] = idx; + else if (pCurrTxRate->CurrMCS == MCS_6 && pCurrTxRate->dataRate == 1) + mcs[6] = idx; + else if (pCurrTxRate->CurrMCS == MCS_7 && pCurrTxRate->dataRate == 1) + mcs[7] = idx; + else if (pCurrTxRate->CurrMCS == MCS_8 && pCurrTxRate->dataRate == 1) + mcs[8] = idx; + else if (pCurrTxRate->CurrMCS == MCS_9 && pCurrTxRate->dataRate == 1) + mcs[9] = idx; + else if (pCurrTxRate->CurrMCS == MCS_0 && pCurrTxRate->dataRate == 2) + mcs[10] = idx; + else if (pCurrTxRate->CurrMCS == MCS_1 && pCurrTxRate->dataRate == 2) + mcs[11] = idx; + else if (pCurrTxRate->CurrMCS == MCS_2 && pCurrTxRate->dataRate == 2) + mcs[12] = idx; + else if (pCurrTxRate->CurrMCS == MCS_3 && pCurrTxRate->dataRate == 2) + mcs[13] = idx; + else if (pCurrTxRate->CurrMCS == MCS_4 && pCurrTxRate->dataRate == 2) + mcs[14] = idx; + else if (pCurrTxRate->CurrMCS == MCS_5 && pCurrTxRate->dataRate == 2) + mcs[15] = idx; + else if (pCurrTxRate->CurrMCS == MCS_6 && pCurrTxRate->dataRate == 2) + mcs[16] = idx; + else if (pCurrTxRate->CurrMCS == MCS_7 && pCurrTxRate->dataRate == 2) + mcs[17] = idx; + else if (pCurrTxRate->CurrMCS == MCS_8 && pCurrTxRate->dataRate == 2) + mcs[18] = idx; + else if (pCurrTxRate->CurrMCS == MCS_9 && pCurrTxRate->dataRate == 2) + mcs[19] = idx; + } + + return; + } + + if (pEntry->pTable == RateTableVht1S_MCS9) + { + for (idx = 0; idx < RATE_TABLE_SIZE(pTable); idx++) + { + pCurrTxRate = PTX_RA_GRP_ENTRY(pEntry->pTable, idx); + if (pCurrTxRate->CurrMCS == MCS_RATE_6 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[20] = idx; + else if (pCurrTxRate->CurrMCS == MCS_RATE_9 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[21] = idx; + else if (pCurrTxRate->CurrMCS == MCS_RATE_12 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[22] = idx; + else if (pCurrTxRate->CurrMCS == MCS_RATE_18 && pCurrTxRate->dataRate == 1 && pCurrTxRate->Mode == MODE_OFDM) + mcs[23] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_0) && (pCurrTxRate->dataRate == 1) && (mcs[0] == -1)) + mcs[0] = idx; + else if (pCurrTxRate->CurrMCS == MCS_1 && pCurrTxRate->dataRate == 1) + mcs[1] = idx; + else if (pCurrTxRate->CurrMCS == MCS_2 && pCurrTxRate->dataRate == 1) + mcs[2] = idx; + else if (pCurrTxRate->CurrMCS == MCS_3 && pCurrTxRate->dataRate == 1) + mcs[3] = idx; + else if (pCurrTxRate->CurrMCS == MCS_4 && pCurrTxRate->dataRate == 1) + mcs[4] = idx; + else if (pCurrTxRate->CurrMCS == MCS_5 && pCurrTxRate->dataRate == 1) + mcs[5] = idx; + else if (pCurrTxRate->CurrMCS == MCS_6 && pCurrTxRate->dataRate == 1) + mcs[6] = idx; + else if (pCurrTxRate->CurrMCS == MCS_7 && pCurrTxRate->dataRate == 1) + mcs[7] = idx; + else if (pCurrTxRate->CurrMCS == MCS_8 && pCurrTxRate->dataRate == 1) + mcs[8] = idx; + else if (pCurrTxRate->CurrMCS == MCS_9 && pCurrTxRate->dataRate == 1) + mcs[9] = idx; + } + + return; + } +#endif /* DOT11_VHT_AC */ + + /* check the existence and index of each needed MCS */ + for (idx = 0; idx < RATE_TABLE_SIZE(pTable); idx++) + { + pCurrTxRate = PTX_RA_GRP_ENTRY(pEntry->pTable, idx); + + if ((pCurrTxRate->CurrMCS >= 8 && pAd->CommonCfg.TxStream < 2) || + (pCurrTxRate->CurrMCS >= 16 && pAd->CommonCfg.TxStream < 3)) + continue; + + /* Rate Table may contain CCK and MCS rates. Give HT/Legacy priority over CCK */ + if (pCurrTxRate->CurrMCS==MCS_0 && (mcs[0]==-1 || pCurrTxRate->Mode!=MODE_CCK)) + mcs[0] = idx; + else if (pCurrTxRate->CurrMCS==MCS_1 && (mcs[1]==-1 || pCurrTxRate->Mode!=MODE_CCK)) + mcs[1] = idx; + else if (pCurrTxRate->CurrMCS==MCS_2 && (mcs[2]==-1 || pCurrTxRate->Mode!=MODE_CCK)) + mcs[2] = idx; + else if (pCurrTxRate->CurrMCS == MCS_3) + mcs[3] = idx; + else if (pCurrTxRate->CurrMCS == MCS_4) + mcs[4] = idx; + else if (pCurrTxRate->CurrMCS == MCS_5) + mcs[5] = idx; + else if (pCurrTxRate->CurrMCS == MCS_6) + mcs[6] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) + mcs[7] = idx; + else if (pCurrTxRate->CurrMCS == MCS_8) + mcs[8] = idx; + else if (pCurrTxRate->CurrMCS == MCS_9) + mcs[9] = idx; + else if (pCurrTxRate->CurrMCS == MCS_10) + mcs[10] = idx; + else if (pCurrTxRate->CurrMCS == MCS_11) + mcs[11] = idx; + else if (pCurrTxRate->CurrMCS == MCS_12) + mcs[12] = idx; + else if (pCurrTxRate->CurrMCS == MCS_13) + mcs[13] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_14) && (pCurrTxRate->ShortGI == GI_800)) + mcs[14] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) + mcs[15] = idx; + else if (pCurrTxRate->CurrMCS == MCS_16) + mcs[16] = idx; + else if (pCurrTxRate->CurrMCS == MCS_17) + mcs[17] = idx; + else if (pCurrTxRate->CurrMCS == MCS_18) + mcs[18] = idx; + else if (pCurrTxRate->CurrMCS == MCS_19) + mcs[19] = idx; + else if (pCurrTxRate->CurrMCS == MCS_20) + mcs[20] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_21) && (pCurrTxRate->ShortGI == GI_800)) + mcs[21] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_22) && (pCurrTxRate->ShortGI == GI_800)) + mcs[22] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_23) && (pCurrTxRate->ShortGI == mcs23GI)) + mcs[23] = idx; + } + +#ifdef DBG_CTRL_SUPPORT + /* Debug Option: Disable highest MCSs when picking initial MCS based on RSSI */ + if (pAd->CommonCfg.DebugFlags & DBF_INIT_MCS_DIS1) + mcs[23] = mcs[15] = mcs[7] = mcs[22] = mcs[14] = mcs[6] = 0; +#endif /* DBG_CTRL_SUPPORT */ + +} + + +UCHAR get_rate_idx_by_rate(RTMP_ADAPTER *pAd, UCHAR *rate_tb, USHORT rate) +{ + UCHAR tb_idx = 0; + +#ifdef DOT11_N_SUPPORT + if (ADAPT_RATE_TABLE(rate_tb)) + { + + } +#endif /* DOT11_N_SUPPORT */ + + return tb_idx; +} + +#ifdef NEW_RATE_ADAPT_QUICK_DOWN +/* QuickInitMCSRate now has bad algorithm and periodic drop PhyMode to CCK/0 */ +VOID TriggerQuickInitMCSRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UINT32 CheckInterval) +{ + PUCHAR pTable; + pTable = pEntry->pTable; + NdisZeroMemory(pEntry->DownTxMCSRate, sizeof(pEntry->DownTxMCSRate)); + +#ifdef DOT11_VHT_AC +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pTable == RateTableVht1S || pTable == RateTableVht2S || pTable == RateTableVht1S_MCS9 + || pTable == RateTableVht2S_BW20 + || pTable == RateTableVht2S_BW40 + || pTable == RateTableVht2S_MCS7 + || pTable == RateSwitchTableAdapt11N1S + || pTable == RateSwitchTableAdapt11N2S) + { + pEntry->LowPacket = TRUE; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!pAd->ApCfg.ApQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, CheckInterval); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, CheckInterval); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + } +#endif /* CONFIG_STA_SUPPORT */ + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ +#endif /* DOT11_VHT_AC */ +} + +BOOLEAN QuickInitMCSRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UINT16 PacketSucc, + IN UINT16 PacketErro) +{ + PUCHAR pTable; + UCHAR CurrRateIdx; + RTMP_RA_GRP_TB *pCurrTxRate; + + if(pEntry->LowPacket == TRUE) + { + CHAR DownIdx, MaxIdx = 0; + + pTable = pEntry->pTable; + CurrRateIdx = pEntry->CurrTxRateIndex; + if(PacketSucc) + MaxIdx = PacketErro/PacketSucc; + else + MaxIdx = 0; + + DBGPRINT(RT_DEBUG_TRACE ,("CR : Quick Fast Down MCS %d/%d=%d\n", + PacketErro, PacketSucc, MaxIdx)); + + if(MaxIdx >= (NUM_OF_SWFB-1)) + MaxIdx = (NUM_OF_SWFB-1); + + for(DownIdx=0; DownIdx < MaxIdx; DownIdx++) + { + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + + CurrRateIdx = pCurrTxRate->downMcs; + + if(pCurrTxRate->TrainDown > 100) + break; + } + + DBGPRINT(RT_DEBUG_TRACE ,("Quick Fast Down MCS %d %d %d\n", + CurrRateIdx, pEntry->CurrTxRateIndex, MaxIdx)); + + pEntry->CurrTxRateIndex = CurrRateIdx; + + pEntry->LastSaveRateIdx = CurrRateIdx; + + NdisZeroMemory(pEntry->DownTxMCSRate, sizeof(pEntry->DownTxMCSRate)); + + MlmeClearAllTxQuality(pEntry); /* clear all history */ + + MlmeNewTxRate(pAd, pEntry); + + pEntry->LowPacket = FALSE; + + return TRUE; + } + else + { + return FALSE; + } +} +#endif + +/* + MlmeSelectTxRateAdapt - select the MCS based on the RSSI and the available MCSs + pAd - pointer to adapter + pEntry - pointer to MAC table entry + mcs - table of MCS index into the Rate Table. -1 => not supported + Rssi - the Rssi value + RssiOffset - offset to apply to the Rssi +*/ +UCHAR MlmeSelectTxRateAdapt( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN CHAR mcs[], + IN CHAR Rssi, + IN CHAR RssiOffset) +{ + UCHAR TxRateIdx = 0; + UCHAR *pTable = pEntry->pTable; + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Add 6 dB of margin */ + if (pAd->CommonCfg.DebugFlags & DBF_INIT_MCS_MARGIN) + RssiOffset += 6; +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11_VHT_AC + if (pTable == RateTableVht1S || pTable == RateTableVht2S || pTable == RateTableVht1S_MCS9 + || pTable == RateTableVht2S_BW20 + || pTable == RateTableVht2S_BW40 + || pTable == RateTableVht2S_MCS7 + || pTable == RateTableVht1S_2G_BW20 + || pTable == RateTableVht1S_2G_BW40 + || pTable == RateTableVht2S_2G_BW20 + || pTable == RateTableVht2S_2G_BW40 + ) + { + if (pTable == RateTableVht2S || pTable == RateTableVht2S_BW40 + || (pTable == RateTableVht2S_2G_BW40)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: GRP: 2*2, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 2x2 peer device (Adhoc, DLS or AP) */ + if (mcs[19] && (Rssi > (-65 + RssiOffset))) { + TxRateIdx = mcs[19]; + } + else if (mcs[18] && (Rssi > (-67 + RssiOffset))) { + TxRateIdx = mcs[18]; + } + else if (mcs[17] && (Rssi > (-69 + RssiOffset))) { + TxRateIdx = mcs[17]; + } + else if (mcs[16] && (Rssi > (-71 + RssiOffset))) { + TxRateIdx = mcs[16]; + } + else if (mcs[15] && (Rssi > (-74 + RssiOffset))) { + TxRateIdx = mcs[15]; + } + else if (mcs[14] && (Rssi > (-76 + RssiOffset))) { + TxRateIdx = mcs[14]; + } + else if (mcs[3] && (Rssi > (-80 + RssiOffset))) { + TxRateIdx = mcs[3]; + } + else if (mcs[2] && (Rssi > (-82 + RssiOffset))) { + TxRateIdx = mcs[2]; + } + else if (mcs[23] && (Rssi > (-85 + RssiOffset))) { + TxRateIdx = mcs[23]; // OFDM 1x1 MCS3 BW20 + } + else if (mcs[22] && (Rssi > (-87 + RssiOffset))) { + TxRateIdx = mcs[22]; // OFDM 1x1 MCS2 BW20 + } + else { + TxRateIdx = mcs[20]; // OFDM 1x1 MCS0 BW20 + } + + pEntry->mcsGroup = 2; + } else if (pTable == RateTableVht2S_MCS7) { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: GRP: 2*2, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 2x2 peer device (Adhoc, DLS or AP) */ + if (mcs[17] && (Rssi > (-69 + RssiOffset))) { + TxRateIdx = mcs[17]; + } + else if (mcs[16] && (Rssi > (-71 + RssiOffset))) { + TxRateIdx = mcs[16]; + } + else if (mcs[15] && (Rssi > (-74 + RssiOffset))) { + TxRateIdx = mcs[15]; + } + else if (mcs[14] && (Rssi > (-76 + RssiOffset))) { + TxRateIdx = mcs[14]; + } + else if (mcs[3] && (Rssi > (-80 + RssiOffset))) { + TxRateIdx = mcs[3]; + } + else if (mcs[2] && (Rssi > (-82 + RssiOffset))) { + TxRateIdx = mcs[2]; + } + else if (mcs[23] && (Rssi > (-85 + RssiOffset))) { // add new condition + TxRateIdx = mcs[23]; // OFDM 1x1 MCS3 BW20 + } + else if (mcs[22] && (Rssi > (-87 + RssiOffset))) { + TxRateIdx = mcs[22]; // OFDM 1x1 MCS2 BW20 + } + else { + TxRateIdx = mcs[20]; // OFDM 1x1 MCS0 BW20 + } + + pEntry->mcsGroup = 2; + } + else if ((pTable == RateTableVht2S_BW20) + || (pTable == RateTableVht2S_2G_BW20)) + { + + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: GRP: 2*2, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 2x2 peer device (Adhoc, DLS or AP) */ + if (mcs[18] && (Rssi > (-67 + RssiOffset))) { + TxRateIdx = mcs[18]; + } + else if (mcs[17] && (Rssi > (-69 + RssiOffset))) { + TxRateIdx = mcs[17]; + } + else if (mcs[16] && (Rssi > (-71 + RssiOffset))) { + TxRateIdx = mcs[16]; + } + else if (mcs[15] && (Rssi > (-74 + RssiOffset))) { + TxRateIdx = mcs[15]; + } + else if (mcs[14] && (Rssi > (-76 + RssiOffset))) { + TxRateIdx = mcs[14]; + } + else if (mcs[3] && (Rssi > (-80 + RssiOffset))) { + TxRateIdx = mcs[3]; + } + else if (mcs[23] && (Rssi > (-85 + RssiOffset))) { + TxRateIdx = mcs[23]; + } + else if (mcs[22] && (Rssi > (-92 + RssiOffset))) { + TxRateIdx = mcs[22]; + } + else if (mcs[20] && (Rssi > (-94 + RssiOffset))) { + TxRateIdx = mcs[21]; + } + else { + TxRateIdx = mcs[20]; + } + + pEntry->mcsGroup = 2; + + } + else if ((pTable == RateTableVht1S_MCS9) + || (pTable == RateTableVht1S_2G_BW20) || (pTable == RateTableVht1S_2G_BW40)) + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: GRP: 1*1, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 1x1 peer device (Adhoc, DLS or AP) */ + if (mcs[9] && (Rssi > (-67 + RssiOffset))) + TxRateIdx = mcs[9]; + else if (mcs[8] && (Rssi > (-69 + RssiOffset))) + TxRateIdx = mcs[8]; + else if (mcs[7] && (Rssi > (-71 + RssiOffset))) + TxRateIdx = mcs[7]; + else if (mcs[6] && (Rssi > (-73 + RssiOffset))) + TxRateIdx = mcs[6]; + else if (mcs[5] && (Rssi > (-76 + RssiOffset))) + TxRateIdx = mcs[5]; + else if (mcs[3] && (Rssi > (-78 + RssiOffset))) + TxRateIdx = mcs[3]; + else if (mcs[2] && (Rssi > (-80 + RssiOffset))) // new + TxRateIdx = mcs[2]; + else if (mcs[23] && (Rssi > (-82 + RssiOffset))) + TxRateIdx = mcs[23]; // MCS_RATE_18 + else if (mcs[22] && (Rssi > (-84 + RssiOffset))) + TxRateIdx = mcs[22]; // MCS_RATE_12 + else if (mcs[21] && (Rssi > (-87 + RssiOffset))) // new + TxRateIdx = mcs[21]; // MCS_RATE_9 + //else if (mcs[20] && (Rssi > (-89 + RssiOffset))) + // TxRateIdx = mcs[20]; // MCS_RATE_9 + else + TxRateIdx = mcs[20]; // MCS_RATE_6 + + pEntry->mcsGroup = 1; + } + else + { + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: GRP: 1*1, RssiOffset=%d\n", __FUNCTION__, RssiOffset)); + + /* 1x1 peer device (Adhoc, DLS or AP) */ + if (mcs[7] && (Rssi > (-71 + RssiOffset))) + TxRateIdx = mcs[7]; + else if (mcs[6] && (Rssi > (-73 + RssiOffset))) + TxRateIdx = mcs[6]; + else if (mcs[5] && (Rssi > (-76 + RssiOffset))) + TxRateIdx = mcs[5]; + else if (mcs[4] && (Rssi > (-78 + RssiOffset))) + TxRateIdx = mcs[4]; + else if (mcs[23] && (Rssi > (-82 + RssiOffset))) + TxRateIdx = mcs[23]; // MCS_RATE_18 + else if (mcs[22] && (Rssi > (-84 + RssiOffset))) + TxRateIdx = mcs[22]; // MCS_RATE_12 + else if (mcs[21] && (Rssi > (-89 + RssiOffset))) + TxRateIdx = mcs[21]; // MCS_RATE_9 + else + TxRateIdx = mcs[0]; + + pEntry->mcsGroup = 1; + } + } + else +#endif /* DOT11_VHT_AC */ + if (ADAPT_RATE_TABLE(pTable) || + (pTable == RateSwitchTable11BGN3S) || + (pTable == RateSwitchTable11BGN3SForABand)) + {/* N mode with 3 stream */ + if ((pEntry->HTCapability.MCSSet[2] == 0xff) && +#ifdef THERMAL_PROTECT_SUPPORT + (pAd->force_one_tx_stream == FALSE) && +#endif /* THERMAL_PROTECT_SUPPORT */ + (pAd->CommonCfg.TxStream == 3) + ) + { + if (mcs[23]>=0 && (Rssi > (-72+RssiOffset))) + TxRateIdx = mcs[23]; + else if (mcs[22]>=0 && (Rssi > (-74+RssiOffset))) + TxRateIdx = mcs[22]; + else if (mcs[21]>=0 && (Rssi > (-77+RssiOffset))) + TxRateIdx = mcs[21]; + else if (mcs[20]>=0 && (Rssi > (-79+RssiOffset))) + TxRateIdx = mcs[20]; + else if (mcs[11]>=0 && (Rssi > (-81+RssiOffset))) + TxRateIdx = mcs[11]; + else if (mcs[10]>=0 && (Rssi > (-83+RssiOffset))) + TxRateIdx = mcs[10]; + else if (mcs[2]>=0 && (Rssi > (-86+RssiOffset))) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-88+RssiOffset))) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + + pEntry->mcsGroup = 3; + } + else if ((pEntry->HTCapability.MCSSet[0] == 0xff) && + (pEntry->HTCapability.MCSSet[1] == 0xff) && + (pAd->CommonCfg.TxStream > 1) && +#ifdef THERMAL_PROTECT_SUPPORT + (pAd->force_one_tx_stream == FALSE) && +#endif /* THERMAL_PROTECT_SUPPORT */ + ((pAd->CommonCfg.TxStream == 2) || (pEntry->HTCapability.MCSSet[2] == 0x0))) + { + if (mcs[15]>=0 && (Rssi > (-72+RssiOffset))) + TxRateIdx = mcs[15]; + else if (mcs[14]>=0 && (Rssi > (-74+RssiOffset))) + TxRateIdx = mcs[14]; + else if (mcs[13]>=0 && (Rssi > (-77+RssiOffset))) + TxRateIdx = mcs[13]; + else if (mcs[12]>=0 && (Rssi > (-79+RssiOffset))) + TxRateIdx = mcs[12]; + else if (mcs[11]>=0 && (Rssi > (-81+RssiOffset))) + TxRateIdx = mcs[11]; + else if (mcs[10]>=0 && (Rssi > (-83+RssiOffset))) + TxRateIdx = mcs[10]; + else if (mcs[2]>=0 && (Rssi > (-86+RssiOffset))) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-88+RssiOffset))) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + + pEntry->mcsGroup = 2; + } + else + { + if (mcs[7]>=0 && (Rssi > (-72+RssiOffset))) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > (-74+RssiOffset))) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > (-77+RssiOffset))) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > (-79+RssiOffset))) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi > (-81+RssiOffset))) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > (-83+RssiOffset))) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-86+RssiOffset))) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + + pEntry->mcsGroup = 1; + } + } + else if ((pTable == RateSwitchTable11BGN2S) || + (pTable == RateSwitchTable11BGN2SForABand) || + (pTable == RateSwitchTable11N2S) || + (pTable == RateSwitchTable11N2SForABand)) + {/* N mode with 2 stream */ + if (mcs[15]>=0 && (Rssi >= (-70+RssiOffset))) + TxRateIdx = mcs[15]; + else if (mcs[14]>=0 && (Rssi >= (-72+RssiOffset))) + TxRateIdx = mcs[14]; + else if (mcs[13]>=0 && (Rssi >= (-76+RssiOffset))) + TxRateIdx = mcs[13]; + else if (mcs[12]>=0 && (Rssi >= (-78+RssiOffset))) + TxRateIdx = mcs[12]; + else if (mcs[4]>=0 && (Rssi >= (-82+RssiOffset))) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi >= (-84+RssiOffset))) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi >= (-86+RssiOffset))) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi >= (-88+RssiOffset))) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else if ((pTable == RateSwitchTable11BGN1S) || + (pTable == RateSwitchTable11N1S) || + (pTable == RateSwitchTable11N1SForABand)) + {/* N mode with 1 stream */ + if (mcs[7]>=0 && (Rssi > (-72+RssiOffset))) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > (-74+RssiOffset))) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > (-77+RssiOffset))) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > (-79+RssiOffset))) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi > (-81+RssiOffset))) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > (-83+RssiOffset))) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-86+RssiOffset))) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else +#endif /* DOT11_N_SUPPORT */ + {/* Legacy mode */ + if (mcs[7]>=0 && (Rssi > -70)) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > -74)) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > -78)) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > -82)) + TxRateIdx = mcs[4]; + else if (mcs[4] == -1) /* for B-only mode */ + TxRateIdx = mcs[3]; + else if (mcs[3]>=0 && (Rssi > -85)) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > -87)) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > -90)) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + + return TxRateIdx; +} + + +/* + MlmeRAHybridRule - decide whether to keep the new rate or use old rate + pEntry - the MAC table entry for this STA + pCurrTxRate - pointer to Rate table entry for new up rate + NewTxOkCount - normalized count of Tx packets for new up rate + TxErrorRatio - the PER + returns + TRUE if old rate should be used +*/ +BOOLEAN MlmeRAHybridRule( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN RTMP_RA_GRP_TB *pCurrTxRate, + IN ULONG NewTxOkCount, + IN ULONG TxErrorRatio) +{ + + + DBGPRINT(RT_DEBUG_TRACE, ("RAA : Tx OK Counter %lu %lu\n", NewTxOkCount , pEntry->LastTxOkCount)); + + if ((120*NewTxOkCount > pAd->CommonCfg.TrainUpHighThrd*pEntry->LastTxOkCount) || + (TxErrorRatio < 10)) + return FALSE; + + return TRUE; +} + +/* + MlmeNewRateAdapt - perform Rate Adaptation based on PER using New RA algorithm + pEntry - the MAC table entry for this STA + UpRateIdx, DownRateIdx - UpRate and DownRate index + TrainUp, TrainDown - TrainUp and Train Down threhsolds + TxErrorRatio - the PER + + On exit: + pEntry->LastSecTxRateChangeAction = RATE_UP or RATE_DOWN if there was a change + pEntry->CurrTxRateIndex = new rate index + pEntry->TxQuality is updated +*/ +VOID MlmeNewRateAdapt( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN ULONG TrainUp, + IN ULONG TrainDown, + IN ULONG TxErrorRatio) +{ + USHORT phyRateLimit20 = 0; + BOOLEAN bTrainUp = FALSE; +#ifdef TXBF_SUPPORT + BOOLEAN invertTxBf = FALSE; +#endif /* TXBF_SUPPORT */ + UCHAR *pTable = pEntry->pTable; + UCHAR CurrRateIdx = pEntry->CurrTxRateIndex; + RTMP_RA_GRP_TB *pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + + pEntry->CurrTxRateStableTime++; + + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + + pEntry->LastSaveRateIdx = pEntry->CurrTxRateIndex; + + + if (TxErrorRatio >= TrainDown) + { +#ifdef TXBF_SUPPORT + RTMP_RA_GRP_TB *pDownRate, *pLastNonBfRate; +#endif /* TXBF_SUPPORT */ + + /* Downgrade TX quality if PER >= Rate-Down threshold */ + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + /* + Need to train down. If BF and last Non-BF is no worse than the down rate then + go to last Non-BF rate. Otherwise just go to the down rate + */ + + pDownRate = PTX_RA_GRP_ENTRY(pTable, DownRateIdx); + pLastNonBfRate = PTX_RA_GRP_ENTRY(pTable, pEntry->lastNonBfRate); + + if ((pEntry->phyETxBf || pEntry->phyITxBf) && + (pLastNonBfRate->dataRate >= pDownRate->dataRate) +#ifdef DBG_CTRL_SUPPORT + && ((pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA)==0) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = pEntry->lastNonBfRate; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + } + else +#endif /* TXBF_AWARE */ +#endif /* TXBF_SUPPORT */ + if (CurrRateIdx != DownRateIdx) + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + } + } + else + { + RTMP_RA_GRP_TB *pUpRate = PTX_RA_GRP_ENTRY(pTable, UpRateIdx); + + /* Upgrade TX quality if PER <= Rate-Up threshold */ + if (TxErrorRatio <= TrainUp) + { + bTrainUp = TRUE; + MlmeDecTxQuality(pEntry, CurrRateIdx); /* quality very good in CurrRate */ + + if (pEntry->TxRateUpPenalty) /* always == 0, always go to else */ + pEntry->TxRateUpPenalty --; + else + { + /* + Decrement the TxQuality of the UpRate and all of the MCS groups. + Note that UpRate may mot equal one of the MCS groups if MlmeSelectUpRate + skipped over a rate that is not valid for this configuration. + */ + MlmeDecTxQuality(pEntry, UpRateIdx); + + if (pCurrTxRate->upMcs3!=CurrRateIdx && + pCurrTxRate->upMcs3!=UpRateIdx) + MlmeDecTxQuality(pEntry, pCurrTxRate->upMcs3); + + if (pCurrTxRate->upMcs2!=CurrRateIdx && + pCurrTxRate->upMcs2!=UpRateIdx && + pCurrTxRate->upMcs2!=pCurrTxRate->upMcs3) + MlmeDecTxQuality(pEntry, pCurrTxRate->upMcs2); + + if (pCurrTxRate->upMcs1!=CurrRateIdx && + pCurrTxRate->upMcs1!=UpRateIdx && + pCurrTxRate->upMcs1!=pCurrTxRate->upMcs3 && + pCurrTxRate->upMcs1!=pCurrTxRate->upMcs2) + MlmeDecTxQuality(pEntry, pCurrTxRate->upMcs1); + } + } + else if (pEntry->mcsGroup > 0) /* even if TxErrorRatio > TrainUp */ + { + /* Moderate PER but some groups are not tried */ + bTrainUp = TRUE; + + /* TxQuality[CurrRateIdx] must be decremented so that mcs won't decrease wrongly */ + MlmeDecTxQuality(pEntry, CurrRateIdx); /* quality very good in CurrRate */ + MlmeDecTxQuality(pEntry, UpRateIdx); /* may improve next UP rate's quality */ + } + + /* Don't try up rate if it's greater than the limit */ + if ((phyRateLimit20 != 0) && (pUpRate->dataRate >= phyRateLimit20)) + return; + + /* If UpRate is good then train up in current BF state */ + if ((CurrRateIdx != UpRateIdx) && (MlmeGetTxQuality(pEntry, UpRateIdx) <= 0) && bTrainUp) + { + DBGPRINT(RT_DEBUG_TRACE, ("RAA : Up Rate %d\n", UpRateIdx)); + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + else +#ifdef DBG_CTRL_SUPPORT + if ((pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA)==0) +#endif /* DBG_CTRL_SUPPORT */ + { + /* If not at the highest rate then try inverting BF state */ + if (pEntry->phyETxBf || pEntry->phyITxBf) + { + /* If BF then try the same MCS non-BF unless PER is good */ + if (TxErrorRatio > TrainUp) + { + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; + + if (pEntry->TxQuality[CurrRateIdx]==0) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = CurrRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } + } + } + else if (pEntry->eTxBfEnCond>0 || pEntry->iTxBfEn) + { + /* First try Up Rate with BF */ + if ((CurrRateIdx != UpRateIdx) && + MlmeTxBfAllowed(pAd, pEntry, (RTMP_RA_LEGACY_TB *)pUpRate)) + { + if (pEntry->BfTxQuality[UpRateIdx]) + pEntry->BfTxQuality[UpRateIdx]--; + + if (pEntry->BfTxQuality[UpRateIdx]==0) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } + } + + /* Try Same Rate if Up Rate failed */ + if (pEntry->LastSecTxRateChangeAction==RATE_NO_CHANGE && + MlmeTxBfAllowed(pAd, pEntry, (RTMP_RA_LEGACY_TB *)pCurrTxRate)) + { + if (pEntry->BfTxQuality[CurrRateIdx]) + pEntry->BfTxQuality[CurrRateIdx]--; + + if (pEntry->BfTxQuality[CurrRateIdx]==0) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = CurrRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } + } + } + } +#endif /* TXBF_AWARE*/ +#endif /* TXBF_SUPPORT */ + } + + /* Handle the rate change */ + if ((pEntry->LastSecTxRateChangeAction != RATE_NO_CHANGE) +#ifdef DBG_CTRL_SUPPORT + || (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + if (pEntry->LastSecTxRateChangeAction!=RATE_NO_CHANGE) + { + DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: %sTX rate from %d to %d \n", + pEntry->LastSecTxRateChangeAction==RATE_UP? "++": "--", CurrRateIdx, pEntry->CurrTxRateIndex)); + } + + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; + + /* Save last rate information */ + pEntry->lastRateIdx = CurrRateIdx; +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + if (pEntry->eTxBfEnCond > 0) + { + pEntry->lastRatePhyTxBf = pEntry->phyETxBf; + pEntry->phyETxBf ^= invertTxBf; + } + else + { + pEntry->lastRatePhyTxBf = pEntry->phyITxBf; + pEntry->phyITxBf ^= invertTxBf; + } +#else +#ifdef MT76x2 + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + //For VHT Mode + if((pCurrTxRate->Mode == 4) && (pCurrTxRate->dataRate == 1)) + { + if (pEntry->eTxBfEnCond > 0) + { + pEntry->phyETxBf = TRUE; + pEntry->lastRatePhyTxBf = pEntry->phyETxBf; + } + else + { + pEntry->phyITxBf = TRUE; + pEntry->lastRatePhyTxBf = pEntry->phyITxBf; + } + } + //For HT Mode + else if((pCurrTxRate->Mode == 3 || pCurrTxRate->Mode == 2) + && (pCurrTxRate->CurrMCS < 8)) + { + if (pEntry->eTxBfEnCond > 0) + { + pEntry->phyETxBf = TRUE; + pEntry->lastRatePhyTxBf = pEntry->phyETxBf; + } + else + { + pEntry->phyITxBf = TRUE; + pEntry->lastRatePhyTxBf = pEntry->phyITxBf; + } + } + // Other OFDM and CCK + else + { + if (pEntry->eTxBfEnCond > 0) + { + pEntry->phyETxBf = FALSE; + pEntry->lastRatePhyTxBf = pEntry->phyETxBf; + } + else + { + pEntry->phyITxBf = FALSE; + pEntry->lastRatePhyTxBf = pEntry->phyITxBf; + } + } +#endif /* MT76x2 */ +#endif /* TXBF_AWARE */ +#endif /* TXBF_SUPPORT */ + + /* Update TxQuality */ + if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + MlmeSetTxQuality(pEntry, pEntry->CurrTxRateIndex, 0); + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + } + + /* Set timer for check in 100 msec */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!pAd->ApCfg.ApQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, pAd->ra_fast_interval); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, pAd->ra_fast_interval); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Update PHY rate */ + MlmeNewTxRate(pAd, pEntry); + } +} + + +#ifdef CONFIG_AP_SUPPORT +/* + ======================================================================== + Routine Description: + AP side, Auto TxRate faster train up timer call back function. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +VOID APQuickResponeForRateUpExecAdapt(/* actually for both up and down */ + IN PRTMP_ADAPTER pAd, + IN UINT idx) +{ + PUCHAR pTable; + UCHAR CurrRateIdx; + ULONG AccuTxTotalCnt, TxTotalCnt, TxCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + RTMP_RA_GRP_TB *pCurrTxRate; + UCHAR TrainUp, TrainDown; + CHAR Rssi, ratio; + ULONG TxSuccess, TxRetransmit, TxFailCount; + ULONG OneSecTxNoRetryOKRationCount; + BOOLEAN rateChanged; +#ifdef TXBF_SUPPORT + BOOLEAN CurrPhyETxBf, CurrPhyITxBf; +#endif /* TXBF_SUPPORT */ + + + pEntry = &pAd->MacTab.Content[idx]; + + //if(QuickInitMCSRate(pAd,pEntry) == TRUE) + // return; + + + pTable = pEntry->pTable; + + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TotalBeaconSentCount += TxStaCnt0.field.TxBeaconCount; + pAd->RadioStatsCounter.TotalTxCount += (StaTx1.field.TxSuccess + TxStaCnt0.field.TxFailCount + StaTx1.field.TxRetransmit + TxStaCnt0.field.TxBeaconCount); + pAd->RadioStatsCounter.TxRetryCount += StaTx1.field.TxRetransmit; +#endif + AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + + /* Rssi is calculated again with new formula?In rory's code, the average instead of max is used. */ + if (pAd->Antenna.field.TxPath > 1) + Rssi = (pEntry->RssiSample.AvgRssi0 + pEntry->RssiSample.AvgRssi1) >> 1; + else + Rssi = pEntry->RssiSample.AvgRssi0; + + TxCnt = AccuTxTotalCnt; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + TxCnt = TxTotalCnt; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + +#ifdef FIFO_EXT_SUPPORT + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s()=>Wcid:%d, MCS:%d, TxErrRation(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxErrorRatio = HwErrRatio; + TxTotalCnt = HwTxCnt; + TxCnt = HwTxCnt; + + ApTxFailCntUpdate(pAd, pEntry, TxSuccess, TxRetransmit); + } +#endif /* FIFO_EXT_SUPPORT */ + +#ifdef NEW_RATE_ADAPT_QUICK_DOWN +/* QuickInitMCSRate now has bad algorithm and periodic drop PhyMode to CCK/0 */ + if(QuickInitMCSRate(pAd,pEntry, TxSuccess, TxRetransmit) == TRUE) + return; +#endif + + DBGPRINT(RT_DEBUG_INFO, ("Quick PER %lu, Total Cnt %lu\n", TxErrorRatio, TxTotalCnt)); + +#ifdef MFB_SUPPORT + if (pEntry->fLastChangeAccordingMfb == TRUE) + { + pEntry->fLastChangeAccordingMfb = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("DRS: MCS is according to MFB, and ignore tuning this sec \n")); + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + return; + } +#endif /* MFB_SUPPORT */ + + /* Remember the current rate */ + CurrRateIdx = pEntry->CurrTxRateIndex; +#ifdef TXBF_SUPPORT + CurrPhyETxBf = pEntry->phyETxBf; + CurrPhyITxBf = pEntry->phyITxBf; +#endif /* TXBF_SUPPORT */ + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX) && pEntry->perThrdAdj == 1) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if ((pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) || (pAd->CommonCfg.DebugFlags & DBF_DBQ_RA_LOG)) + MlmeRALog(pAd, pEntry, RAL_QUICK_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + + /* Handle the low traffic case */ + if ((TxCnt <= 15) && + (pEntry->HTPhyMode.field.MODE == MODE_HTMIX) && + (pEntry->HTPhyMode.field.MCS > 1)) + { + /* Go back to the original rate */ + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, (" QuickDRS: TxTotalCnt <= 15, back to original rate \n")); + + MlmeNewTxRate(pAd, pEntry); + + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + + return; + } + + /* + Compare throughput. + LastTxCount is based on a time interval of 500 msec or "500 - pAd->ra_fast_interval" ms. + */ + if ((pEntry->LastTimeTxRateChangeAction == RATE_NO_CHANGE) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + ratio = RA_INTERVAL / pAd->ra_fast_interval; + else + ratio = (RA_INTERVAL - pAd->ra_fast_interval) / pAd->ra_fast_interval; + + if (pAd->MacTab.Size == 1) + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + else + //OneSecTxNoRetryOKRationCount = pEntry->OneSecTxNoRetryOkCount * ratio + (pEntry->OneSecTxNoRetryOkCount >> 1); + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio) + ((TxSuccess * ratio) >> 1); + + /* Downgrade TX quality if PER >= Rate-Down threshold */ + /* the only situation when pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND but no rate change */ + if (TxErrorRatio >= TrainDown) + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + + /* Perform DRS - consider TxRate Down first, then rate up. */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + BOOLEAN useOldRate; + + // TODO: gaa - Finalize the decision criterion + /* + 0=>Throughput. Use New Rate if New TP is better than Old TP + 1=>PER. Use New Rate if New PER is less than the TrainDown PER threshold + 2=>Hybrid. Use rate with best TP if difference > 10%. Otherwise use rate with Best Estimated TP + 3=>Hybrid with check that PERCommonCfg.TrainUpRule == 0) + { + useOldRate = (pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount; + } + else if (pAd->CommonCfg.TrainUpRule==2 && Rssi<=pAd->CommonCfg.TrainUpRuleRSSI) + { + useOldRate = MlmeRAHybridRule(pAd, pEntry, pCurrTxRate, OneSecTxNoRetryOKRationCount, TxErrorRatio); + } + else if (pAd->CommonCfg.TrainUpRule==3 && Rssi<=pAd->CommonCfg.TrainUpRuleRSSI) + { + useOldRate = (TxErrorRatio >= TrainDown) || + MlmeRAHybridRule(pAd, pEntry, pCurrTxRate, OneSecTxNoRetryOKRationCount, TxErrorRatio); + } + else + useOldRate = TxErrorRatio >= TrainDown; + if (useOldRate) + { + /* If PER>50% or TP 50) || (OneSecTxNoRetryOKRationCount < pEntry->LastTxOkCount/2)) + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND*2); + else + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + + MlmeRestoreLastRate(pEntry); + } + else + { + RTMP_RA_GRP_TB *pLastTxRate = PTX_RA_GRP_ENTRY(pTable, pEntry->lastRateIdx); + + /* Clear the history if we changed the MCS and PHY Rate */ + if ((pCurrTxRate->CurrMCS != pLastTxRate->CurrMCS) && + (pCurrTxRate->dataRate != pLastTxRate->dataRate)) + MlmeClearTxQuality(pEntry); + + if (pEntry->mcsGroup == 0) + MlmeSetMcsGroup(pAd, pEntry); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + (" QuickDRS: (Up) keep rate-up (L:%ld, C:%ld)\n", + pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + } + else if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) /* there will be train down again */ + { + MlmeSetMcsGroup(pAd, pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) direct train down (TxErrorRatio >= TrainDown)\n")); + } + else if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + if(TxErrorRatio >= TrainUp) + { + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) bad tx ok count (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + else + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) direct train down (TxErrorRatio >= TrainUp)\n")); + } + } + else + { + MlmeSetMcsGroup(pAd, pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) keep rate-down (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + } + + /* See if we reverted to the old rate */ +#ifdef TXBF_SUPPORT + rateChanged = (pEntry->CurrTxRateIndex != CurrRateIdx) || + (pEntry->phyETxBf!=CurrPhyETxBf) || (pEntry->phyITxBf!=CurrPhyITxBf); + + /* Remember last good non-BF rate */ + if (!pEntry->phyETxBf && !pEntry->phyITxBf) + pEntry->lastNonBfRate = pEntry->CurrTxRateIndex; +#else + rateChanged = (pEntry->CurrTxRateIndex != CurrRateIdx); +#endif /* TXBF_SUPPORT */ + + + /* Update mcsGroup */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + UCHAR UpRateIdx; + + /* If RATE_UP failed look for the next group with valid mcs */ + if (pEntry->CurrTxRateIndex != CurrRateIdx && pEntry->mcsGroup > 0) + { + pEntry->mcsGroup--; + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, pEntry->lastRateIdx); + } + + switch (pEntry->mcsGroup) + { + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + default: + UpRateIdx = CurrRateIdx; + break; + } + + if (UpRateIdx == pEntry->CurrTxRateIndex) + pEntry->mcsGroup = 0; + } + + + /* Handle change back to old rate */ + if (rateChanged) + { + /* Clear Old Rate's TxQuality */ + MlmeSetTxQuality(pEntry, pEntry->CurrTxRateIndex, 0); + + pEntry->TxRateUpPenalty = 0; /* redundant */ + pEntry->PER[pEntry->CurrTxRateIndex] = 0; /* redundant */ + + /* Set new Tx rate */ + MlmeNewTxRate(pAd, pEntry); + } + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ +} + + + +/* + ========================================================================== + Description: + This routine walks through the MAC table, see if TX rate change is + required for each associated client. + Output: + pEntry->CurrTxRate - + NOTE: + call this routine every second + ========================================================================== + */ +VOID APMlmeDynamicTxRateSwitchingAdapt(RTMP_ADAPTER *pAd, UINT i) +{ + PUCHAR pTable; + UCHAR UpRateIdx, DownRateIdx, CurrRateIdx, TrainUp, TrainDown; + ULONG TxTotalCnt, TxSuccess, TxRetransmit, TxFailCount, TxErrorRatio; + MAC_TABLE_ENTRY *pEntry; + RTMP_RA_GRP_TB *pCurrTxRate; + CHAR Rssi; + + pEntry = &pAd->MacTab.Content[i]; /* point to information of the individual station */ + pTable = pEntry->pTable; + TxTotalCnt = TxSuccess = TxRetransmit = TxFailCount = TxErrorRatio = 0; + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TotalBeaconSentCount += TxStaCnt0.field.TxBeaconCount; + pAd->RadioStatsCounter.TotalTxCount += (StaTx1.field.TxSuccess + TxStaCnt0.field.TxFailCount + StaTx1.field.TxRetransmit + TxStaCnt0.field.TxBeaconCount); + pAd->RadioStatsCounter.TxRetryCount += StaTx1.field.TxRetransmit; +#endif + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + +#ifdef FIFO_EXT_SUPPORT + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s()=>Wcid:%d, MCS:%d, TxErrRatio(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxTotalCnt = HwTxCnt; + TxErrorRatio = HwErrRatio; + + ApTxFailCntUpdate(pAd, pEntry, TxSuccess, TxRetransmit); + } +#endif /* FIFO_EXT_SUPPORT */ + + /* Save LastTxOkCount, LastTxPER and last MCS action for APQuickResponeForRateUpExec */ + pEntry->LastTxOkCount = TxSuccess; + pEntry->LastTxPER = (UCHAR)TxErrorRatio; + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + /* different calculation in APQuickResponeForRateUpExec() */ + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + if (pEntry->CurrTxRateIndex >= RATE_TABLE_SIZE(pTable)) + pEntry->CurrTxRateIndex = RATE_TABLE_SIZE(pTable) - 1; + + /* decide the next upgrade rate and downgrade rate, if any */ + CurrRateIdx = pEntry->CurrTxRateIndex; + + //Current Rate and Check Max MCS Rate + MlmeLimitMaxRate(pAd, pEntry, &CurrRateIdx, RATE_NO_CHANGE); + + //Up Rate and Check Max MCS Rate + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + pEntry->CurrTxRateIndex = CurrRateIdx; + UpRateIdx = MlmeSelectUpRate(pAd, pEntry, pCurrTxRate); + MlmeLimitMaxRate(pAd, pEntry, &UpRateIdx, RATE_UP); + + //Down Rate + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + + DBGPRINT(RT_DEBUG_TRACE, ("Average PER %lu, Cur %d, Up %d, Dn %d\n", TxErrorRatio, + CurrRateIdx, UpRateIdx, DownRateIdx)); + + DBGPRINT(RT_DEBUG_TRACE, ("RAA:Tx Quality 1SS %d, 2SS %d\n", + pEntry->TxQuality[pCurrTxRate->upMcs1], + pEntry->TxQuality[pCurrTxRate->upMcs2])); + + +#ifdef DOT11_N_SUPPORT + /* + when Rssi > -65, there is a lot of interference usually. therefore, + the algorithm tends to choose the mcs lower than the optimal one. + By increasing the thresholds, the chosen mcs will be closer to the + optimal mcs + */ + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX) && pEntry->perThrdAdj == 1) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if ((pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) || (pAd->CommonCfg.DebugFlags & DBF_DBQ_RA_LOG)) + MlmeRALog(pAd, pEntry, RAL_NEW_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef MFB_SUPPORT + if (pEntry->fLastChangeAccordingMfb == TRUE) + { + RTMP_RA_LEGACY_TB *pNextTxRate; + + /* with this method mfb result can be applied every 500msec, instead of immediately */ + NdisAcquireSpinLock(&pEntry->fLastChangeAccordingMfbLock); + pEntry->fLastChangeAccordingMfb = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + NdisReleaseSpinLock(&pEntry->fLastChangeAccordingMfbLock); + APMlmeSetTxRate(pAd, pEntry, pEntry->LegalMfbRS); + DBGPRINT(RT_DEBUG_INFO,("DRS: MCS is according to MFB, and ignore tuning this sec \n")); + MlmeClearAllTxQuality(pEntry); /* clear all history, same as train up, purpose??? */ + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + pEntry->CurrTxRateIndex = (pEntry->LegalMfbRS)->ItemNo; + pNextTxRate = (RTMP_RA_LEGACY_TB *) &pTable[(pEntry->CurrTxRateIndex+1)*10]; /* actually = pEntry->LegalMfbRS */ + return; + } +#endif /* MFB_SUPPORT */ + + + /* Handle low traffic case */ + if (TxTotalCnt <= 15) + { + pEntry->lowTrafficCount++; + if (pEntry->lowTrafficCount >= pAd->CommonCfg.lowTrafficThrd) + { + UCHAR TxRateIdx; + CHAR mcs[24]; + CHAR RssiOffset = 0; + + //pEntry->lowTrafficCount = 0; + + /* Check existence and get index of each MCS */ + MlmeGetSupportedMcsAdapt(pAd, pEntry, GI_400, mcs); + + if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || + (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand)) + { + RssiOffset = -12; + } + else if (ADAPT_RATE_TABLE(pTable)) + { + RssiOffset = -12; + } + else + { + RssiOffset = 5; + } + + TxRateIdx = pEntry->CurrTxRateIndex; + + /* Select the Tx rate based on the RSSI */ + if((pEntry->lowTrafficCount == pAd->CommonCfg.lowTrafficThrd) && + (pEntry->LastSaveRateIdx != 0xFF)) { + // Get Latest Rate Index to calibration once + MlmeCaliRSSITable(pAd, pEntry, Rssi, pTable); + TxRateIdx = MlmeSelectTxRateAdapt(pAd, pEntry, mcs, Rssi, pEntry->RX_RSSI_MCS); + DBGPRINT(RT_DEBUG_TRACE,("Update New MCS with Cali RSSI:%d\n", pEntry->RX_RSSI_MCS)); + } + else if((pEntry->lowTrafficCount > 60) || (pEntry->LastSaveRateIdx == 0xFF)) { + // 30 second and First Time + // Low Packet with holding safe MCS Rate + TxRateIdx = MlmeSelectTxRateAdapt(pAd, pEntry, mcs, Rssi, RssiOffset); + pEntry->lowTrafficCount = pAd->CommonCfg.lowTrafficThrd; + DBGPRINT(RT_DEBUG_TRACE,("Update New MCS with RSSI\n")); + } + + MlmeLimitMaxRate(pAd, pEntry, &TxRateIdx, RATE_NO_CHANGE); + pEntry->lastRateIdx = pEntry->CurrTxRateIndex; + MlmeSetMcsGroup(pAd, pEntry); + pEntry->CurrTxRateIndex = TxRateIdx; + +#ifdef TXBF_SUPPORT + //pEntry->phyETxBf = pEntry->phyITxBf = FALSE; +#endif /* TXBF_SUPPORT */ + MlmeNewTxRate(pAd, pEntry); + if (!pEntry->fLastSecAccordingRSSI) + { + DBGPRINT(RT_DEBUG_INFO,("DRS: TxTotalCnt <= 15, switch to MCS%d according to RSSI (%d), RssiOffset=%d\n", pEntry->HTPhyMode.field.MCS, Rssi, RssiOffset)); + } + + MlmeClearAllTxQuality(pEntry); /* clear all history */ + pEntry->fLastSecAccordingRSSI = TRUE; + } + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT +#ifdef DBG_CTRL_SUPPORT + /* In Unaware mode always try to send sounding */ + if (pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA) + eTxBFProbing(pAd, pEntry); +#endif /* DBG_CTRL_SUPPORT */ +#endif /* TXBF_SUPPORT */ + + pEntry->fLastSecAccordingRSSI = TRUE; + +#ifdef NEW_RATE_ADAPT_QUICK_DOWN +/* QuickInitMCSRate now has bad algorithm and periodic drop PhyMode to CCK/0 */ + if(TxTotalCnt) { + TriggerQuickInitMCSRate(pAd, pEntry, pAd->ra_fast_interval >> 1); + DBGPRINT(RT_DEBUG_TRACE ,("Trigger @ RSSI Mapping (Light Packet)\n")); + MlmeClearAllTxQuality(pEntry); /* clear all history */ + } +#endif + return; + } + + if(TxTotalCnt > 100) + pEntry->lowTrafficCount = 0; + + /* + After pEntry->fLastSecAccordingRSSI = TRUE; the for loop + continue. this condition is true when RateSwitching() is run + next time. + so the next rate adaptation is skipped. This mechanism is + deliberately designed by rory. + */ + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + /* DBGPRINT(RT_DEBUG_INFO,("DRS: MCS is according to RSSI, and ignore tuning this sec \n")); */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef NEW_RATE_ADAPT_QUICK_DOWN +/* QuickInitMCSRate now has bad algorithm and periodic drop PhyMode to CCK/0 */ + if(TxTotalCnt) { + TriggerQuickInitMCSRate(pAd, pEntry, pAd->ra_fast_interval >> 1); + DBGPRINT(RT_DEBUG_TRACE ,("Trigger @ RSSI Mapping (Light to Heavy Packet)\n")); + MlmeClearAllTxQuality(pEntry); /* clear all history */ + } +#endif + return; + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Select rate based on PER */ + MlmeNewRateAdapt(pAd, pEntry, UpRateIdx, DownRateIdx, TrainUp, TrainDown, TxErrorRatio); + +#ifdef DOT11N_SS3_SUPPORT + /* Turn off RDG when 3s and rx count > tx count*5 */ + MlmeCheckRDG(pAd, pEntry); +#endif /* DOT11N_SS3_SUPPORT */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +VOID StaQuickResponeForRateUpExecAdapt( + IN PRTMP_ADAPTER pAd, + IN ULONG i, + IN CHAR Rssi) +{ + PUCHAR pTable; + UCHAR CurrRateIdx; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + PMAC_TABLE_ENTRY pEntry; + RTMP_RA_GRP_TB *pCurrTxRate; + UCHAR TrainUp, TrainDown; + CHAR ratio; + ULONG TxSuccess, TxRetransmit, TxFailCount; + ULONG OneSecTxNoRetryOKRationCount; + BOOLEAN rateChanged; +#ifdef TXBF_SUPPORT + BOOLEAN CurrPhyETxBf, CurrPhyITxBf; +#endif /* TXBF_SUPPORT */ + + + pEntry = &pAd->MacTab.Content[i]; + pTable = pEntry->pTable; + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + } + + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + +#ifdef MFB_SUPPORT + if (pEntry->fLastChangeAccordingMfb == TRUE) + { + pEntry->fLastChangeAccordingMfb = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("DRS: MCS is according to MFB, and ignore tuning this sec \n")); + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + return; + } +#endif /* MFB_SUPPORT */ + + if(QuickInitMCSRate(pAd,pEntry, TxSuccess, TxRetransmit) == TRUE) + return; + + /* Remember the current rate */ + CurrRateIdx = pEntry->CurrTxRateIndex; +#ifdef TXBF_SUPPORT + CurrPhyETxBf = pEntry->phyETxBf; + CurrPhyITxBf = pEntry->phyITxBf; +#endif /* TXBF_SUPPORT */ + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX) && pEntry->perThrdAdj == 1) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if ((pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) || (pAd->CommonCfg.DebugFlags & DBF_DBQ_RA_LOG)) + MlmeRALog(pAd, pEntry, RAL_QUICK_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + + /* + CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + (criteria copied from RT2500 for Netopia case) + */ + if (TxTotalCnt <= 12) + { + /* Go back to the original rate */ + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: TxTotalCnt <= 12, back to original rate \n")); + + MlmeNewTxRate(pAd, pEntry); + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + return; + } + + /* + Compare throughput. + LastTxCount is based on a time interval of 500 msec or "500-pAd->ra_fast_interval" ms. + */ + if ((pEntry->LastTimeTxRateChangeAction == RATE_NO_CHANGE) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + ratio = RA_INTERVAL/pAd->ra_fast_interval; + else + ratio = (RA_INTERVAL-pAd->ra_fast_interval)/pAd->ra_fast_interval; + + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + + /* Downgrade TX quality if PER >= Rate-Down threshold */ + if (TxErrorRatio >= TrainDown) + { + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); /* the only situation when pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND but no rate change */ + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Perform DRS - consider TxRate Down first, then rate up. */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + BOOLEAN useOldRate; + + // TODO: gaa - Finalize the decision criterion + /* + 0=>Throughput. Use New Rate if New TP is better than Old TP + 1=>PER. Use New Rate if New PER is less than the TrainDown PER threshold + 2=>Hybrid. Use rate with best TP if difference > 10%. Otherwise use rate with Best Estimated TP + 3=>Hybrid with check that PERCommonCfg.TrainUpRule == 0) + { + useOldRate = (pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount; + } + else if (pAd->CommonCfg.TrainUpRule==2 && Rssi<=pAd->CommonCfg.TrainUpRuleRSSI) + { + useOldRate = MlmeRAHybridRule(pAd, pEntry, pCurrTxRate, OneSecTxNoRetryOKRationCount, TxErrorRatio); + } + else if (pAd->CommonCfg.TrainUpRule==3 && Rssi<=pAd->CommonCfg.TrainUpRuleRSSI) + { + useOldRate = (TxErrorRatio >= TrainDown) || + MlmeRAHybridRule(pAd, pEntry, pCurrTxRate, OneSecTxNoRetryOKRationCount, TxErrorRatio); + } + else + useOldRate = TxErrorRatio >= TrainDown; + if (useOldRate) + { + /* If PER>50% or TP 50) || (OneSecTxNoRetryOKRationCount < pEntry->LastTxOkCount/2)) + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND*2); + else + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Up) bad tx ok count (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + else + { + RTMP_RA_GRP_TB *pLastTxRate = PTX_RA_GRP_ENTRY(pTable, pEntry->lastRateIdx); + + /* Clear the history if we changed the MCS and PHY Rate */ + if ((pCurrTxRate->CurrMCS != pLastTxRate->CurrMCS) && + (pCurrTxRate->dataRate != pLastTxRate->dataRate)) + MlmeClearTxQuality(pEntry); + + if (pEntry->mcsGroup == 0) + MlmeSetMcsGroup(pAd, pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Up) keep rate-up (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + } + else if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) + { + MlmeSetMcsGroup(pAd, pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) direct train down (TxErrorRatio >= TrainDown)\n")); + } + else if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) bad tx ok count (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + else + { + MlmeSetMcsGroup(pAd, pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) keep rate-down (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + } + + /* See if we reverted to the old rate */ +#ifdef TXBF_SUPPORT + rateChanged = (pEntry->CurrTxRateIndex != CurrRateIdx) || + (pEntry->phyETxBf!=CurrPhyETxBf) || (pEntry->phyITxBf!=CurrPhyITxBf); + + /* Remember last good non-BF rate */ + if (!pEntry->phyETxBf && !pEntry->phyITxBf) + pEntry->lastNonBfRate = pEntry->CurrTxRateIndex; +#else + rateChanged = (pEntry->CurrTxRateIndex != CurrRateIdx); +#endif /* TXBF_SUPPORT */ + + /* Update mcsGroup */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + UCHAR UpRateIdx; + + /* If RATE_UP failed look for the next group with valid mcs */ + if (pEntry->CurrTxRateIndex != CurrRateIdx && pEntry->mcsGroup > 0) + { + pEntry->mcsGroup--; + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, pEntry->lastRateIdx); + } + + switch (pEntry->mcsGroup) + { + case 3: + UpRateIdx = pCurrTxRate->upMcs3; + break; + case 2: + UpRateIdx = pCurrTxRate->upMcs2; + break; + case 1: + UpRateIdx = pCurrTxRate->upMcs1; + break; + default: + UpRateIdx = CurrRateIdx; + break; + } + + if (UpRateIdx == pEntry->CurrTxRateIndex) + pEntry->mcsGroup = 0; + } + + /* Handle change back to old rate */ + if (rateChanged) + { + /* Clear Old Rate's history */ + MlmeSetTxQuality(pEntry, pEntry->CurrTxRateIndex, 0); + pEntry->TxRateUpPenalty = 0;/*redundant */ + pEntry->PER[pEntry->CurrTxRateIndex] = 0;/*redundant */ + + /* Set new Tx rate */ + MlmeNewTxRate(pAd, pEntry); + } + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ +} + + +VOID MlmeDynamicTxRateSwitchingAdapt( + IN PRTMP_ADAPTER pAd, + IN ULONG i, + IN ULONG TxSuccess, + IN ULONG TxRetransmit, + IN ULONG TxFailCount) +{ + PUCHAR pTable; + UCHAR UpRateIdx, DownRateIdx, CurrRateIdx; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + RTMP_RA_GRP_TB *pCurrTxRate; + UCHAR TrainUp, TrainDown; + CHAR Rssi; + + pEntry = &pAd->MacTab.Content[i]; + pTable = pEntry->pTable; + + if ((pAd->MacTab.Size == 1) || (IS_ENTRY_DLS(pEntry))) + { + Rssi = RTMPAvgRssi(pAd, &pAd->StaCfg.RssiSample); + + /* Update statistic counter */ + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; + +#ifdef FIFO_EXT_SUPPORT + if (pEntry->bUseHwFifoExt) + { + WCID_TX_CNT_STRUC wcidTxCnt; + ULONG HwTxCnt, HwErrRatio = 0; + + RTMP_IO_READ32(pAd, pAd->FifoExtTbl[pEntry->hwFifoExtIdx].hwTxCntCROffset, &wcidTxCnt.word); + + HwTxCnt = wcidTxCnt.field.succCnt + wcidTxCnt.field.reTryCnt; + if (HwTxCnt) + HwErrRatio = (wcidTxCnt.field.reTryCnt * 100) / HwTxCnt; + + DBGPRINT(RT_DEBUG_TRACE ,("%s():TxErrRatio(Wcid:%d, MCS:%d, Hw:0x%x-0x%x, Sw:0x%x-%x)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = wcidTxCnt.field.succCnt; + TxRetransmit = wcidTxCnt.field.reTryCnt; + TxErrorRatio = HwErrRatio; + TxTotalCnt = HwTxCnt; + } +#endif /* FIFO_EXT_SUPPORT */ + } + + /* Save LastTxOkCount, LastTxPER and last MCS action for StaQuickResponeForRateUpExec */ + pEntry->LastTxOkCount = TxSuccess; + pEntry->LastTxPER = (UCHAR)TxErrorRatio; + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + if (pEntry->CurrTxRateIndex >= RATE_TABLE_SIZE(pTable)) + pEntry->CurrTxRateIndex = RATE_TABLE_SIZE(pTable) - 1; + + /* decide the next upgrade rate and downgrade rate, if any */ + CurrRateIdx = pEntry->CurrTxRateIndex; + pCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + UpRateIdx = MlmeSelectUpRate(pAd, pEntry, pCurrTxRate); + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + +#ifdef DOT11_N_SUPPORT + /* + when Rssi > -65, there is a lot of interference usually. therefore, the algorithm tends to choose the mcs lower than the optimal one. + by increasing the thresholds, the chosen mcs will be closer to the optimal mcs + */ + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX) && pEntry->perThrdAdj == 1) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if ((pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) || (pAd->CommonCfg.DebugFlags & DBF_DBQ_RA_LOG)) + MlmeRALog(pAd, pEntry, RAL_NEW_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef MFB_SUPPORT + if (pEntry->fLastChangeAccordingMfb == TRUE) + { + pEntry->fLastChangeAccordingMfb = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + DBGPRINT_RAW(RT_DEBUG_TRACE,("DRS: MCS is according to MFB, and ignore tuning this sec \n")); + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + return; + } +#endif /* MFB_SUPPORT */ + + + /* + CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + (criteria copied from RT2500 for Netopia case) + */ + if (TxTotalCnt <= 15) + { + pEntry->lowTrafficCount++; + + if (pEntry->lowTrafficCount >= pAd->CommonCfg.lowTrafficThrd) + { + UCHAR TxRateIdx; + CHAR mcs[24]; + CHAR RssiOffset = 0; + + pEntry->lowTrafficCount = 0; + + /* Check existence and get index of each MCS */ + MlmeGetSupportedMcsAdapt(pAd, pEntry, GI_800, mcs); + + if (pAd->LatchRfRegs.Channel <= 14) + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RssiOffset = 2; + } + else if (ADAPT_RATE_TABLE(pTable)) + { + RssiOffset = -12; + } + else + { + RssiOffset = 5; + } + } + else + { + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RssiOffset = 5; + } + else if (ADAPT_RATE_TABLE(pTable)) + { + RssiOffset = -12; + } + else + { + RssiOffset = 8; + } + } + + //Low Packet with safe MCS Rate + if(pEntry->LastSaveRateIdx > 0) + { + /* Select the Tx rate based on the RSSI */ + if(pEntry->lowTrafficCount > 120) // 60 second + { + pEntry->LastSaveRateIdx = MlmeSelectTxRateAdapt(pAd, pEntry, mcs, Rssi, RssiOffset); + pEntry->lowTrafficCount = pAd->CommonCfg.lowTrafficThrd; + } + + TxRateIdx = pEntry->LastSaveRateIdx; + DBGPRINT(RT_DEBUG_INFO,("Save Rate %d %d\n", TxRateIdx, pEntry->lowTrafficCount)); + } + else + { + /* Select the Tx rate based on the RSSI */ + TxRateIdx = MlmeSelectTxRateAdapt(pAd, pEntry, mcs, Rssi, RssiOffset); + } + + /* if (TxRateIdx != pEntry->CurrTxRateIndex) */ + { + pEntry->lastRateIdx = pEntry->CurrTxRateIndex; + MlmeSetMcsGroup(pAd, pEntry); + + pEntry->CurrTxRateIndex = TxRateIdx; +#ifdef TXBF_SUPPORT + //pEntry->phyETxBf = pEntry->phyITxBf = FALSE; +#endif /* TXBF_SUPPORT */ + MlmeNewTxRate(pAd, pEntry); + if (!pEntry->fLastSecAccordingRSSI) + { + DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: TxTotalCnt <= 15, switch to MCS%d according to RSSI (%d), RssiOffset=%d\n", pEntry->HTPhyMode.field.MCS, Rssi, RssiOffset)); + } + } + + MlmeClearAllTxQuality(pEntry); /* clear all history */ + pEntry->fLastSecAccordingRSSI = TRUE; + } + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT +#ifdef DBG_CTRL_SUPPORT + /* In Unaware mode always try to send sounding */ + if (pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA) + eTxBFProbing(pAd, pEntry); +#endif /* DBG_CTRL_SUPPORT */ +#endif /* TXBF_SUPPORT */ + + if (TxTotalCnt > 0) + { + TriggerQuickInitMCSRate(pAd, pEntry, pAd->ra_fast_interval >> 1); + } + + return; + } + + pEntry->lowTrafficCount = 0; + + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + /* DBGPRINT_RAW(RT_DEBUG_TRACE,("DRS: MCS is according to RSSI, and ignore tuning this sec \n")); */ + + TriggerQuickInitMCSRate(pAd, pEntry, pAd->ra_fast_interval >> 1); + DBGPRINT(RT_DEBUG_TRACE ,("Trigger @ RSSI Mapping\n")); + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + return; + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Select rate based on PER */ + MlmeNewRateAdapt(pAd, pEntry, UpRateIdx, DownRateIdx, TrainUp, TrainDown, TxErrorRatio); + +#ifdef DOT11_VHT_AC + { + RTMP_RA_GRP_TB *pAGSCurrTxRate; + + pAGSCurrTxRate = PTX_RA_GRP_ENTRY(pTable, CurrRateIdx); + + DBGPRINT(RT_DEBUG_TRACE, ("Current Rate is %d\n",CurrRateIdx)); + + if((pEntry->pTable == RateTableVht1S) || (pEntry->pTable == RateTableVht2S) + || (pEntry->pTable == RateTableVht2S_BW20) || (pEntry->pTable == RateTableVht2S_BW40) + || (pEntry->pTable == RateTableVht2S_MCS7) || (pEntry->pTable == RateTableVht1S_2G_BW20) + || (pEntry->pTable == RateTableVht1S_2G_BW40) || (pEntry->pTable == RateTableVht2S_2G_BW20) + || (pEntry->pTable == RateTableVht2S_2G_BW40)) + { + if(pAGSCurrTxRate->dataRate == 2) + { + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, 0xBBA98800); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xEDCBA980); + } + else + { + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, 0x65432100); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xEDC74320); + } + + } + else if ((pEntry->pTable == RateSwitchTableAdapt11N1S) || (pEntry->pTable == RateSwitchTableAdapt11N2S)) + { + if(pAGSCurrTxRate->CurrMCS > 7) + { + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, 0xBBA98800); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xEDCBA980); + } + else + { + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, 0x65432100); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xEDC74320); + } + } + else + { + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, 0x65432100); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xEDCBA980); + } + } +#endif + + +#ifdef DOT11N_SS3_SUPPORT + /* Turn off RDG when 3SS and rx count > tx count*5 */ + MlmeCheckRDG(pAd, pEntry); +#endif /* DOT11N_SS3_SUPPORT */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + Set_RateTable_Proc - Display or replace byte for item in RateSwitchTableAdapt11N3S + usage: iwpriv ra0 set RateTable=[::] +*/ +INT Set_RateTable_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UCHAR *pTable, TableSize, InitTxRateIdx; + int i; + MAC_TABLE_ENTRY *pEntry; + int itemNo, rtIndex, value; + UCHAR *pRateEntry; + + /* Find first Associated STA in MAC table */ + for (i=1; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && pEntry->Sst==SST_ASSOC) + break; + } + + if (i==MAX_LEN_OF_MAC_TABLE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_RateTable_Proc: Empty MAC Table\n")); + return FALSE; + } + + /* Get peer's rate table */ + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + + /* Get rate index */ + itemNo = simple_strtol(arg, &arg, 10); + if (itemNo<0 || itemNo>=RATE_TABLE_SIZE(pTable)) + return FALSE; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + pRateEntry = (UCHAR *)PTX_RA_GRP_ENTRY(pTable, itemNo); + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pRateEntry = (UCHAR *)PTX_RA_LEGACY_ENTRY(pTable, itemNo); + + /* If no addtional parameters then print the entry */ + if (*arg != ':') { + DBGPRINT(RT_DEBUG_OFF, ("Set_RateTable_Proc::%d\n", itemNo)); + } + else { + /* Otherwise get the offset and the replace byte */ + while (*arg<'0' || *arg>'9') + arg++; + rtIndex = simple_strtol(arg, &arg, 10); + if (rtIndex<0 || rtIndex>9) + return FALSE; + + if (*arg!=':') + return FALSE; + while (*arg<'0' || *arg>'9') + arg++; + value = simple_strtol(arg, &arg, 10); + pRateEntry[rtIndex] = value; + DBGPRINT(RT_DEBUG_OFF, ("Set_RateTable_Proc::%d:%d:%d\n", itemNo, rtIndex, value)); + } + + DBGPRINT(RT_DEBUG_OFF, ("%d, 0x%02x, %d, %d, %d, %d, %d, %d, %d, %d\n", + pRateEntry[0], pRateEntry[1], pRateEntry[2], pRateEntry[3], pRateEntry[4], + pRateEntry[5], pRateEntry[6], pRateEntry[7], pRateEntry[8], pRateEntry[9])); + + return TRUE; +} + + +INT Set_PerThrdAdj_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i; + for (i=0; iMacTab.Content[i].perThrdAdj = simple_strtol(arg, 0, 10); + } + return TRUE; +} + +/* Set_LowTrafficThrd_Proc - set threshold for reverting to default MCS based on RSSI */ +INT Set_LowTrafficThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.lowTrafficThrd = simple_strtol(arg, 0, 10); + + return TRUE; +} + +/* Set_TrainUpRule_Proc - set rule for Quick DRS train up */ +INT Set_TrainUpRule_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.TrainUpRule = simple_strtol(arg, 0, 10); + + return TRUE; +} + +/* Set_TrainUpRuleRSSI_Proc - set RSSI threshold for Quick DRS Hybrid train up */ +INT Set_TrainUpRuleRSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.TrainUpRuleRSSI = simple_strtol(arg, 0, 10); + + return TRUE; +} + +/* Set_TrainUpLowThrd_Proc - set low threshold for Quick DRS Hybrid train up */ +INT Set_TrainUpLowThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.TrainUpLowThrd = simple_strtol(arg, 0, 10); + + return TRUE; +} + +/* Set_TrainUpHighThrd_Proc - set high threshold for Quick DRS Hybrid train up */ +INT Set_TrainUpHighThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.TrainUpHighThrd = simple_strtol(arg, 0, 10); + + return TRUE; +} + +#endif /* NEW_RATE_ADAPT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_legacy.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_legacy.c new file mode 100644 index 000000000..c090614ba --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/alg_legacy.c @@ -0,0 +1,1809 @@ +/**************************************************************************** + * 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 Dynamic Rate Switch (AP/STA) function body. + + History: + +***************************************************************************/ + +#include "rt_config.h" + + +#ifdef CONFIG_AP_SUPPORT +/* + ========================================================================== + Description: + This routine walks through the MAC table, see if TX rate change is + required for each associated client. + Output: + pEntry->CurrTxRate - + NOTE: + call this routine every second + ========================================================================== + */ +VOID APMlmeDynamicTxRateSwitching(RTMP_ADAPTER *pAd) +{ + UINT i; + PUCHAR pTable; + UCHAR TableSize = 0, InitTxRateIdx, TrainUp, TrainDown; + UCHAR UpRateIdx, DownRateIdx, CurrRateIdx; + MAC_TABLE_ENTRY *pEntry; + RTMP_RA_LEGACY_TB *pCurrTxRate, *pTmpTxRate = NULL; + CHAR Rssi, TmpIdx = 0; + ULONG TxTotalCnt, TxErrorRatio = 0, TxSuccess, TxRetransmit, TxFailCount; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif /* RALINK_ATE */ + + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + /* point to information of the individual station */ + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_NONE(pEntry)) + continue; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst != SST_ASSOC)) + continue; + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && (pEntry->Sst != SST_ASSOC)) + continue; +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry) && !WDS_IF_UP_CHECK(pAd, pEntry->wdev_idx)) + continue; +#endif /* WDS_SUPPORT */ + + + /* check if this entry need to switch rate automatically */ + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + pEntry->pTable = pTable; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + { + APMlmeDynamicTxRateSwitchingAdapt(pAd, i); + + continue; + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd) && AGS_IS_USING(pAd, pTable)) + { + ApMlmeDynamicTxRateSwitchingAGS(pAd, i); + continue; + } +#endif /* AGS_SUPPORT */ + + /* NICUpdateFifoStaCounters(pAd); */ + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TotalBeaconSentCount += TxStaCnt0.field.TxBeaconCount; + pAd->RadioStatsCounter.TotalTxCount += (StaTx1.field.TxSuccess + TxStaCnt0.field.TxFailCount + StaTx1.field.TxRetransmit + TxStaCnt0.field.TxBeaconCount); + pAd->RadioStatsCounter.TxRetryCount += StaTx1.field.TxRetransmit; +#endif + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap) + { + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s()=>Wcid:%d, MCS:%d, CuTxRaIdx=%d,TxErrRatio(Hw:%ld-%ld%%, Sw:%ld-%ld%%)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + pEntry->CurrTxRateIndex, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxTotalCnt = HwTxCnt; + TxErrorRatio = HwErrRatio; + + ApTxFailCntUpdate(pAd, pEntry, TxSuccess, TxRetransmit); + } + } +#endif /* FIFO_EXT_SUPPORT */ + + /* Save LastTxOkCount, LastTxPER and last MCS action for APQuickResponeForRateUpExec */ + pEntry->LastTxOkCount = TxSuccess; + pEntry->LastTxPER = (TxTotalCnt == 0 ? 0 : (UCHAR)TxErrorRatio); + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + /* different calculation in APQuickResponeForRateUpExec() */ + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + +#ifdef THERMAL_PROTECT_SUPPORT + if (pAd->force_one_tx_stream == TRUE) { + if (pEntry->CurrTxRateIndex > 0x0b) + pEntry->CurrTxRateIndex = TableSize - 1; + } +#endif /* THERMAL_PROTECT_SUPPORT */ + + CurrRateIdx = UpRateIdx = DownRateIdx = pEntry->CurrTxRateIndex; + + /* decide the next upgrade rate and downgrade rate, if any */ + pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + + /* decide the next upgrade rate and downgrade rate, if any*/ + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pTmpTxRate->Mode <= MODE_CCK) + { + if (pEntry->SupportCCKMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + } + else if (pTmpTxRate->Mode <= MODE_OFDM) + { + if (pEntry->SupportOFDMMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + } + else + { + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + } + TmpIdx++; + } + + TmpIdx = CurrRateIdx - 1; + while(TmpIdx >= 0) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pTmpTxRate->Mode <= MODE_CCK) + { + if (pEntry->SupportCCKMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + } + else if (pTmpTxRate->Mode <= MODE_OFDM) + { + if (pEntry->SupportOFDMMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + } + else + { + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + } + TmpIdx--; + } + } + else if (CurrRateIdx == 0) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pTmpTxRate->Mode <= MODE_CCK) + { + if (pEntry->SupportCCKMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + } + else if (pTmpTxRate->Mode <= MODE_OFDM) + { + if (pEntry->SupportOFDMMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + } + else + { + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + } + TmpIdx++; + } + + DownRateIdx = CurrRateIdx; + } + else if (CurrRateIdx == (TableSize - 1)) + { + UpRateIdx = CurrRateIdx; + + TmpIdx = CurrRateIdx - 1; + while(TmpIdx >= 0) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pTmpTxRate->Mode <= MODE_CCK) + { + if (pEntry->SupportCCKMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + } + else if (pTmpTxRate->Mode <= MODE_OFDM) + { + if (pEntry->SupportOFDMMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + } + else + { + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + } + TmpIdx--; + } + } + +#ifdef DOT11_N_SUPPORT + /* + when Rssi > -65, there is a lot of interference usually. therefore, the algorithm + tends to choose the mcs lower than the optimal one. + by increasing the thresholds, the chosen mcs will be closer to the optimal mcs + */ + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { +#ifdef NOISE_TEST_ADJUST + TrainUp = (pCurrTxRate->TrainUp << 1); + TrainDown = (pCurrTxRate->TrainDown << 1); +#else + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); +#endif /* NOISE_TEST_ADJUST */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if (pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) + MlmeRALog(pAd, pEntry, RAL_OLD_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + + + /* Check for low traffic case */ + if (TxTotalCnt <= 15) + { + UCHAR TxRateIdx; + CHAR mcs[24]; + CHAR RssiOffset = 0; + + pEntry->lowTrafficCount++; + + /* Check existence and get the index of each MCS */ + MlmeGetSupportedMcs(pAd, pTable, mcs); + +#ifdef NOISE_TEST_ADJUST + if (pAd->MacTab.Size > 5) { + if (Rssi > -78) + Rssi = -78; + else + RssiOffset += 3; + } +#endif /* NOISE_TEST_ADJUST */ + /* Select the Tx rate based on the RSSI */ + TxRateIdx = MlmeSelectTxRate(pAd, pEntry, mcs, Rssi, RssiOffset); + + + if (TxRateIdx != pEntry->CurrTxRateIndex + ) + { + pEntry->CurrTxRateIndex = TxRateIdx; + MlmeNewTxRate(pAd, pEntry); + if (!pEntry->fLastSecAccordingRSSI) + DBGPRINT(RT_DEBUG_INFO,("DRS: TxTotalCnt <= 15, switch MCS according to RSSI (%d)\n", Rssi)); + } + + MlmeClearAllTxQuality(pEntry); + pEntry->fLastSecAccordingRSSI = TRUE; + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + +#ifdef TXBF_SUPPORT +#ifdef DBG_CTRL_SUPPORT + /* In Unaware mode always try to send sounding */ + if (pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA) + eTxBFProbing(pAd, pEntry); +#endif /* DBG_CTRL_SUPPORT */ +#endif /* TXBF_SUPPORT */ + continue; + } + + pEntry->lowTrafficCount = 0; + + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + continue; + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Select rate based on PER */ + MlmeOldRateAdapt(pAd, pEntry, CurrRateIdx, UpRateIdx, DownRateIdx, TrainUp, TrainDown, TxErrorRatio); + +#ifdef DOT11N_SS3_SUPPORT + /* Turn off RDG when 3s and rx count > tx count*5 */ + MlmeCheckRDG(pAd, pEntry); +#endif /* DOT11N_SS3_SUPPORT */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + } +} + + +/* + ======================================================================== + Routine Description: + AP side, Auto TxRate faster train up timer call back function. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + UINT i; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR CurrRateIdx; + ULONG AccuTxTotalCnt, TxTotalCnt, TxCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + RTMP_RA_LEGACY_TB *pCurrTxRate; + UCHAR InitTxRateIdx, TrainUp, TrainDown; + CHAR Rssi, ratio; + ULONG TxSuccess, TxRetransmit, TxFailCount; +#ifdef TXBF_SUPPORT + BOOLEAN CurrPhyETxBf, CurrPhyITxBf; +#endif /* TXBF_SUPPORT */ + + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE; + + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_NONE(pEntry)) + continue; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst != SST_ASSOC)) + continue; + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && (pEntry->Sst != SST_ASSOC)) + continue; +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry) && !WDS_IF_UP_CHECK(pAd, pEntry->wdev_idx)) + continue; +#endif /* WDS_SUPPORT */ + + + + /* Do nothing if this entry didn't change */ + if (pEntry->LastSecTxRateChangeAction == RATE_NO_CHANGE +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + continue; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + pEntry->pTable = pTable; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + { + APQuickResponeForRateUpExecAdapt(pAd, i); + continue; + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + + if (pAd->MacTab.Size == 1) + { + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; +#ifdef CUSTOMER_DCC_FEATURE + pAd->RadioStatsCounter.TotalBeaconSentCount += TxStaCnt0.field.TxBeaconCount; + pAd->RadioStatsCounter.TotalTxCount += (StaTx1.field.TxSuccess + TxStaCnt0.field.TxFailCount + StaTx1.field.TxRetransmit + TxStaCnt0.field.TxBeaconCount); + pAd->RadioStatsCounter.TxRetryCount += StaTx1.field.TxRetransmit; +#endif + AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + + if (pAd->Antenna.field.TxPath > 1) + Rssi = (pEntry->RssiSample.AvgRssi0 + pEntry->RssiSample.AvgRssi1) >> 1; + else + Rssi = pEntry->RssiSample.AvgRssi0; + + TxCnt = AccuTxTotalCnt; + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + TxCnt = TxTotalCnt; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap) + { + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s()=>Wcid:%d, MCS:%d, TxErrRation(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxErrorRatio = HwErrRatio; + TxTotalCnt = HwTxCnt; + TxCnt = HwTxCnt; + + ApTxFailCntUpdate(pAd, pEntry, TxSuccess, TxRetransmit); + } + } +#endif /* FIFO_EXT_SUPPORT */ + +#ifdef THERMAL_PROTECT_SUPPORT + if (pAd->force_one_tx_stream == TRUE) { + if (pEntry->CurrTxRateIndex > 0x0b) + pEntry->CurrTxRateIndex = TableSize - 1; + } +#endif /* THERMAL_PROTECT_SUPPORT */ + + CurrRateIdx = pEntry->CurrTxRateIndex; +#ifdef TXBF_SUPPORT + CurrPhyETxBf = pEntry->phyETxBf; + CurrPhyITxBf = pEntry->phyITxBf; +#endif /* TXBF_SUPPORT */ + pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if (pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) + MlmeRALog(pAd, pEntry, RAL_QUICK_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + + if ((TxCnt <= 15) && + (pEntry->HTPhyMode.field.MODE == MODE_HTMIX) && + (pEntry->HTPhyMode.field.MCS > 1)) + { + MlmeClearAllTxQuality(pEntry); + + /* Set current up MCS at the worst quality */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + } + + /* Go back to the original rate */ + MlmeRestoreLastRate(pEntry); + + MlmeNewTxRate(pAd, pEntry); + + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + + continue; + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Compare throughput */ + do + { + ULONG OneSecTxNoRetryOKRationCount; + + /* + Compare throughput. + LastTxCount is based on a time interval of "500" msec or "500-pAd->ra_fast_interval" ms. + */ + if ((pEntry->LastTimeTxRateChangeAction == RATE_NO_CHANGE) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + ratio = RA_INTERVAL/pAd->ra_fast_interval; + else + ratio = (RA_INTERVAL-pAd->ra_fast_interval)/pAd->ra_fast_interval; + + /* downgrade TX quality if PER >= Rate-Down threshold */ + if (TxErrorRatio >= TrainDown) + { + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + } + + if (pAd->MacTab.Size == 1) + { + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + } + else + { + OneSecTxNoRetryOKRationCount = TxSuccess * ratio + (TxSuccess >> 1); + //OneSecTxNoRetryOKRationCount = pEntry->OneSecTxNoRetryOkCount * ratio + (pEntry->OneSecTxNoRetryOkCount >> 1); + } + + /* perform DRS - consider TxRate Down first, then rate up. */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { +// TODO: gaa - use different criterion for train up in Old RA? + /*if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) */ + if (TxErrorRatio >= TrainDown) + { +#ifdef TXBF_SUPPORT + /* If PER>50% or TP 50) || (OneSecTxNoRetryOKRationCount < pEntry->LastTxOkCount/2)) + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND*2); + else +#endif /* TXBF_SUPPORT */ + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + + MlmeRestoreLastRate(pEntry); + } + else + { + } + } + else if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + /* if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) */ + if ((TxErrorRatio >= 50) && (TxErrorRatio >= TrainDown)) + { + } + else if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + if(TxErrorRatio >= TrainUp) + { + MlmeRestoreLastRate(pEntry); + } + + } + else + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("QuickDRS: (Down) keep rate-down (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + } + }while (FALSE); + +#ifdef TXBF_SUPPORT + /* Remember last good non-BF rate */ + if (!pEntry->phyETxBf && !pEntry->phyITxBf) + pEntry->lastNonBfRate = pEntry->CurrTxRateIndex; +#endif /* TXBF_SUPPORT */ + + /* If rate changed then update the history and set the new tx rate */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) +#ifdef TXBF_SUPPORT + || (pEntry->phyETxBf!=CurrPhyETxBf) || (pEntry->phyITxBf!=CurrPhyITxBf) +#endif /* TXBF_SUPPORT */ + ) + { + /* if rate-up happen, clear all bad history of all TX rates */ + if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + pEntry->TxRateUpPenalty = 0; + if (pEntry->CurrTxRateIndex != CurrRateIdx) + MlmeClearTxQuality(pEntry); + } + /* if rate-down happen, only clear DownRate's bad history */ + else if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + pEntry->TxRateUpPenalty = 0; /* no penalty */ + MlmeSetTxQuality(pEntry, pEntry->CurrTxRateIndex, 0); + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + } + + MlmeNewTxRate(pAd, pEntry); + } + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + } +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + This routine calculates the acumulated TxPER of eaxh TxRate. And + according to the calculation result, change CommonCfg.TxRate which + is the stable TX Rate we expect the Radio situation could sustained. + + CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} + Output: + CommonCfg.TxRate - + + IRQL = DISPATCH_LEVEL + + NOTE: + call this routine every second + ========================================================================== + */ +VOID MlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd) +{ + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; + ULONG i, TxTotalCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + RTMP_RA_LEGACY_TB *pCurrTxRate, *pTmpTxRate = NULL; + UCHAR InitTxRateIdx, TrainUp, TrainDown; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + CHAR Rssi, TmpIdx = 0; + ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + RSSI_SAMPLE *pRssi = &pAd->StaCfg.RssiSample; +#ifdef AGS_SUPPORT + AGS_STATISTICS_INFO AGSStatisticsInfo = {0}; +#endif /* AGS_SUPPORT */ + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif /* RALINK_ATE */ + + /* Update statistic counter */ + NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_NONE(pEntry)) + continue; + + /* check if this entry need to switch rate automatically */ + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + pEntry->pTable = pTable; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + { + MlmeDynamicTxRateSwitchingAdapt(pAd, i, TxSuccess, TxRetransmit, TxFailCount); + continue; + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + + if ((pAd->MacTab.Size == 1) || IS_ENTRY_DLS(pEntry)) + { + Rssi = RTMPAvgRssi(pAd, pRssi); + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + ("DRS:Wcid=%d, TxSuccess=%ld, TxRetransmit=%ld, TxFailCount=%ld \n", + pEntry->wcid, TxSuccess, TxRetransmit, TxFailCount)); + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + { + + /* Gather the statistics information*/ + + AGSStatisticsInfo.RSSI = Rssi; + AGSStatisticsInfo.TxErrorRatio = TxErrorRatio; + AGSStatisticsInfo.AccuTxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxSuccess = TxSuccess; + AGSStatisticsInfo.TxRetransmit = TxRetransmit; + AGSStatisticsInfo.TxFailCount = TxFailCount; + } +#endif /* AGS_SUPPORT */ + } + else + { + if (INFRA_ON(pAd) && (i == 1)) + Rssi = RTMPAvgRssi(pAd, pRssi); + else + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + ("DRS:WCID=%d, OneSecTxNoRetry=%d, OneSecTxRetry=%d, OneSecTxFail=%d\n", + pEntry->wcid, + pEntry->OneSecTxNoRetryOkCount, + pEntry->OneSecTxRetryOkCount, + pEntry->OneSecTxFailCount)); + +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap) + { + if (NicGetMacFifoTxCnt(pAd, pEntry)) + { + ULONG HwTxCnt, HwErrRatio; + + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, + ("%s():Aid:%d, MCS:%d, CuTxRaIdx=%d,TxErrRatio(Hw:%d-%d%%, Sw:%d-%d%%)\n", + __FUNCTION__, pEntry->Aid, pEntry->HTPhyMode.field.MCS, + pEntry->CurrTxRateIndex, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxTotalCnt = HwTxCnt; + TxErrorRatio = HwErrRatio; + } + } +#endif /* FIFO_EXT_SUPPORT */ + + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + { + + /* Gather the statistics information*/ + + AGSStatisticsInfo.RSSI = Rssi; + AGSStatisticsInfo.TxErrorRatio = TxErrorRatio; + AGSStatisticsInfo.AccuTxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxSuccess = pEntry->OneSecTxNoRetryOkCount; + AGSStatisticsInfo.TxRetransmit = pEntry->OneSecTxRetryOkCount; + AGSStatisticsInfo.TxFailCount = pEntry->OneSecTxFailCount; + } +#endif /* AGS_SUPPORT */ + } + + if (TxTotalCnt) + { + if (TxErrorRatio == 100) + { + TX_RTY_CFG_STRUC TxRtyCfg,TxRtyCfgtmp; + ULONG Index; + UINT32 MACValue; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); + TxRtyCfgtmp.word = TxRtyCfg.word; + TxRtyCfg.field.LongRtyLimit = 0x0; + TxRtyCfg.field.ShortRtyLimit = 0x0; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); + + RtmpusecDelay(1); + + Index = 0; + MACValue = 0; + do + { + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + if ((MACValue & 0xffffff) == 0) + break; + Index++; + RtmpusecDelay(1000); + }while((Index < 330)&&(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))); + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); + TxRtyCfg.field.LongRtyLimit = TxRtyCfgtmp.field.LongRtyLimit; + TxRtyCfg.field.ShortRtyLimit = TxRtyCfgtmp.field.ShortRtyLimit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); + } + + } + + CurrRateIdx = pEntry->CurrTxRateIndex; + +#ifdef AGS_SUPPORT + if (AGS_IS_USING(pAd, pTable)) + { + /* The dynamic Tx rate switching for AGS (Adaptive Group Switching)*/ + MlmeDynamicTxRateSwitchingAGS(pAd, pEntry, pTable, TableSize, &AGSStatisticsInfo, InitTxRateIdx); + + continue; + } +#endif /* AGS_SUPPORT */ + + if (CurrRateIdx >= TableSize) + CurrRateIdx = TableSize - 1; + + UpRateIdx = DownRateIdx = CurrRateIdx; + + /* Save LastTxOkCount, LastTxPER and last MCS action for StaQuickResponeForRateUpExec */ + pEntry->LastTxOkCount = TxSuccess; + pEntry->LastTxPER = (TxTotalCnt == 0 ? 0 : (UCHAR)TxErrorRatio); + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + /* + When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pEntry->TxRateIndex. + So need to sync here. + */ + pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + if (pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) + { + /* + Need to sync Real Tx rate and our record. + Then return for next DRS. + */ + pEntry->CurrTxRateIndex = InitTxRateIdx; + MlmeNewTxRate(pAd, pEntry); + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + continue; + } + + /* decide the next upgrade rate and downgrade rate, if any */ + if ((pCurrTxRate->Mode <= MODE_CCK) && (pEntry->SupportRateMode <= SUPPORT_CCK_MODE)) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportCCKMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + TmpIdx++; + } + + TmpIdx = CurrRateIdx - 1; + while(TmpIdx >= 0) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportCCKMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + TmpIdx--; + } + } + else if ((pCurrTxRate->Mode <= MODE_OFDM) && (pEntry->SupportRateMode < SUPPORT_HT_MODE)) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportOFDMMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + TmpIdx++; + } + + TmpIdx = CurrRateIdx - 1; + while(TmpIdx >= 0) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportOFDMMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + TmpIdx--; + } + } + else + { + /* decide the next upgrade rate and downgrade rate, if any*/ + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + TmpIdx++; + } + + TmpIdx = CurrRateIdx - 1; + while(TmpIdx >= 0) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + TmpIdx--; + } + } + else if (CurrRateIdx == 0) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + UpRateIdx = TmpIdx; + break; + } + TmpIdx++; + } + + DownRateIdx = CurrRateIdx; + } + else if (CurrRateIdx == (TableSize - 1)) + { + UpRateIdx = CurrRateIdx; + + TmpIdx = CurrRateIdx - 1; + while(TmpIdx >= 0) + { + pTmpTxRate = PTX_RA_LEGACY_ENTRY(pTable, TmpIdx); + if (pEntry->SupportHTMCS[pTmpTxRate->CurrMCS] == TRUE) + { + DownRateIdx = TmpIdx; + break; + } + TmpIdx--; + } + } + } + + pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + +#ifdef DOT11_N_SUPPORT + + /* + when Rssi > -65, there is a lot of interference usually. therefore, the + algorithm tends to choose the mcs lower than the optimal one. + by increasing the thresholds, the chosen mcs will be closer to the optimal mcs + */ + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if (pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) + MlmeRALog(pAd, pEntry, RAL_OLD_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + + + + /* + CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + (criteria copied from RT2500 for Netopia case) + */ + if (TxTotalCnt <= 15) + { + UCHAR TxRateIdx; + CHAR mcs[24]; + CHAR RssiOffset = 0; + + /* Check existence and get the index of each MCS */ + MlmeGetSupportedMcs(pAd, pTable, mcs); + + if (pAd->LatchRfRegs.Channel <= 14) + { + RssiOffset = pAd->NicConfig2.field.ExternalLNAForG? 2: 5; + } + else + { + RssiOffset = pAd->NicConfig2.field.ExternalLNAForA? 5: 8; + } + + /* Select the Tx rate based on the RSSI */ + TxRateIdx = MlmeSelectTxRate(pAd, pEntry, mcs, Rssi, RssiOffset); + + + { + pEntry->CurrTxRateIndex = TxRateIdx; + MlmeNewTxRate(pAd, pEntry); + if (!pEntry->fLastSecAccordingRSSI) + DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: TxTotalCnt <= 15, switch MCS according to RSSI (%d), RssiOffset=%d\n", Rssi, RssiOffset)); + } + + MlmeClearAllTxQuality(pEntry); + pEntry->fLastSecAccordingRSSI = TRUE; + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT +#ifdef DBG_CTRL_SUPPORT + /* In Unaware mode always try to send sounding */ + if (pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA) + eTxBFProbing(pAd, pEntry); +#endif /* DBG_CTRL_SUPPORT */ +#endif /* TXBF_SUPPORT */ + + continue; + } + + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + continue; + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Select rate based on PER */ + MlmeOldRateAdapt(pAd, pEntry, CurrRateIdx, UpRateIdx, DownRateIdx, TrainUp, TrainDown, TxErrorRatio); + +#ifdef DOT11N_SS3_SUPPORT + /* Turn off RDG when 3s and rx count > tx count*5 */ + MlmeCheckRDG(pAd, pEntry); +#endif /* DOT11N_SS3_SUPPORT */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + } +} + + +/* + ======================================================================== + Routine Description: + Station side, Auto TxRate faster train up timer call back function. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +VOID StaQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + ULONG i; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR CurrRateIdx; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + RTMP_RA_LEGACY_TB *pCurrTxRate; + UCHAR InitTxRateIdx, TrainUp, TrainDown; + CHAR Rssi, ratio; + ULONG TxSuccess, TxRetransmit, TxFailCount; + MAC_TABLE_ENTRY *pEntry; +#ifdef TXBF_SUPPORT + BOOLEAN CurrPhyETxBf, CurrPhyITxBf; +#endif /* TXBF_SUPPORT */ +#ifdef AGS_SUPPORT + AGS_STATISTICS_INFO AGSStatisticsInfo = {0}; +#endif /* AGS_SUPPORT */ + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_NONE(pEntry)) + continue; + + /* check if this entry need to switch rate automatically */ + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + /* Do nothing if this entry didn't change */ + if (pEntry->LastSecTxRateChangeAction == RATE_NO_CHANGE +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + continue; + + if (INFRA_ON(pAd) && (i == 1)) + Rssi = RTMPAvgRssi(pAd, &pAd->StaCfg.RssiSample); + else + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + pEntry->pTable = pTable; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + { + StaQuickResponeForRateUpExecAdapt(pAd, i, Rssi); + continue; + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + + CurrRateIdx = pEntry->CurrTxRateIndex; +#ifdef TXBF_SUPPORT + CurrPhyETxBf = pEntry->phyETxBf; + CurrPhyITxBf = pEntry->phyITxBf; +#endif /* TXBF_SUPPORT */ + pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + if (pAd->MacTab.Size == 1) + { + /* Update statistic counter */ + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; +#endif /* STATS_COUNT_SUPPORT */ + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + { + + /* Gather the statistics information*/ + + AGSStatisticsInfo.RSSI = Rssi; + AGSStatisticsInfo.TxErrorRatio = TxErrorRatio; + AGSStatisticsInfo.AccuTxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxSuccess = TxSuccess; + AGSStatisticsInfo.TxRetransmit = TxRetransmit; + AGSStatisticsInfo.TxFailCount = TxFailCount; + } +#endif /* AGS_SUPPORT */ + } + else + { + TxRetransmit = pEntry->OneSecTxRetryOkCount; + TxSuccess = pEntry->OneSecTxNoRetryOkCount; + TxFailCount = pEntry->OneSecTxFailCount; + + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap) + { + if (pEntry->bUseHwFifoExt) + { + WCID_TX_CNT_STRUC wcidTxCnt; + ULONG HwTxCnt, HwErrRatio = 0; + + RTMP_IO_READ32(pAd, pAd->FifoExtTbl[pEntry->hwFifoExtIdx].hwTxCntCROffset, &wcidTxCnt.word); + + HwTxCnt = wcidTxCnt.field.succCnt + wcidTxCnt.field.reTryCnt; + if (HwTxCnt) + HwErrRatio = (wcidTxCnt.field.reTryCnt * 100) / HwTxCnt; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s():TxErrRatio(wcid:%d, MCS:%d, Hw:0x%x-0x%x, Sw:0x%x-%x)\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = wcidTxCnt.field.succCnt; + TxRetransmit = wcidTxCnt.field.reTryCnt; + TxErrorRatio = HwErrRatio; + TxTotalCnt = HwTxCnt; + } + } +#endif /* FIFO_EXT_SUPPORT */ + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + { + + /* Gather the statistics information*/ + + AGSStatisticsInfo.RSSI = Rssi; + AGSStatisticsInfo.TxErrorRatio = TxErrorRatio; + AGSStatisticsInfo.AccuTxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxTotalCnt = TxTotalCnt; + AGSStatisticsInfo.TxSuccess = pEntry->OneSecTxNoRetryOkCount; + AGSStatisticsInfo.TxRetransmit = pEntry->OneSecTxRetryOkCount; + AGSStatisticsInfo.TxFailCount = pEntry->OneSecTxFailCount; + } +#endif /* AGS_SUPPORT */ + } + +#ifdef AGS_SUPPORT + if (AGS_IS_USING(pAd, pTable)) + { + + /* The dynamic Tx rate switching for AGS (Adaptive Group Switching)*/ + + StaQuickResponeForRateUpExecAGS(pAd, pEntry, pTable, TableSize, &AGSStatisticsInfo, InitTxRateIdx); + + continue; /* Skip the remaining procedure of the old Tx rate switching*/ + } +#endif /* AGS_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Concise RA log */ + if (pAd->CommonCfg.DebugFlags & DBF_SHOW_RA_LOG) + MlmeRALog(pAd, pEntry, RAL_QUICK_DRS, TxErrorRatio, TxTotalCnt); +#endif /* DBG_CTRL_SUPPORT */ + + /* + CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + (criteria copied from RT2500 for Netopia case) + */ + if (TxTotalCnt <= 12) + { + MlmeClearAllTxQuality(pEntry); + + /* Set current up MCS at the worst quality */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + } + + /* Go back to the original rate */ + MlmeRestoreLastRate(pEntry); + MlmeNewTxRate(pAd, pEntry); + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + + continue; + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + /* Compare throughput */ + do + { + ULONG OneSecTxNoRetryOKRationCount; + + /* + Compare throughput. + LastTxCount is based on a time interval of 500 msec or "500-pAd->ra_fast_interval" ms. + */ + if ((pEntry->LastTimeTxRateChangeAction == RATE_NO_CHANGE) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + ratio = RA_INTERVAL/pAd->ra_fast_interval; + else + ratio = (RA_INTERVAL-pAd->ra_fast_interval)/pAd->ra_fast_interval; + + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + + /* downgrade TX quality if PER >= Rate-Down threshold */ + if (TxErrorRatio >= TrainDown) + { + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + } + + /* perform DRS - consider TxRate Down first, then rate up. */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + if (TxErrorRatio >= TrainDown) + { +#ifdef TXBF_SUPPORT + /* If PER>50% or TP 50) || (OneSecTxNoRetryOKRationCount < pEntry->LastTxOkCount/2)) + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND*2); + else +#endif /* TXBF_SUPPORT */ + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Up) bad tx ok count (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + else + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Up) keep rate-up (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + } + else if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + /* Note: AP had "(TxErrorRatio >= 50) && (TxErrorRatio >= TrainDown)" */ + if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) direct train down (TxErrorRatio >= TrainDown)\n")); + } + else if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + MlmeRestoreLastRate(pEntry); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) bad tx ok count (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + else + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,(" QuickDRS: (Down) keep rate-down (L:%ld, C:%ld)\n", pEntry->LastTxOkCount, OneSecTxNoRetryOKRationCount)); + } + }while (FALSE); + +#ifdef TXBF_SUPPORT + /* Remember last good non-BF rate */ + if (!pEntry->phyETxBf && !pEntry->phyITxBf) + pEntry->lastNonBfRate = pEntry->CurrTxRateIndex; +#endif /* TXBF_SUPPORT */ + + /* If rate changed then update the history and set the new tx rate */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) +#ifdef TXBF_SUPPORT + || (pEntry->phyETxBf!=CurrPhyETxBf) || (pEntry->phyITxBf!=CurrPhyITxBf) +#endif /* TXBF_SUPPORT */ + ) + { + /* if rate-up happen, clear all bad history of all TX rates */ + if (pEntry->LastSecTxRateChangeAction == RATE_DOWN) + { + /* DBGPRINT_RAW(RT_DEBUG_INFO,(" QuickDRS: ++TX rate from %d to %d \n", CurrRateIdx, pEntry->CurrTxRateIndex)); */ + + pEntry->TxRateUpPenalty = 0; + if (pEntry->CurrTxRateIndex != CurrRateIdx) + MlmeClearTxQuality(pEntry); + } + /* if rate-down happen, only clear DownRate's bad history */ + else if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + /* DBGPRINT_RAW(RT_DEBUG_INFO,(" QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pEntry->CurrTxRateIndex)); */ + + pEntry->TxRateUpPenalty = 0; /* no penalty */ + MlmeSetTxQuality(pEntry, pEntry->CurrTxRateIndex, 0); + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + } + + MlmeNewTxRate(pAd, pEntry); + } + + // TODO: should we reset all OneSecTx counters? + /* RESET_ONE_SEC_TX_CNT(pEntry); */ + } +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + MlmeOldRateAdapt - perform Rate Adaptation based on PER using old RA algorithm + pEntry - the MAC table entry + CurrRateIdx - the index of the current rate + UpRateIdx, DownRateIdx - UpRate and DownRate index + TrainUp, TrainDown - TrainUp and Train Down threhsolds + TxErrorRatio - the PER + + On exit: + pEntry->LastSecTxRateChangeAction = RATE_UP or RATE_DOWN if there was a change + pEntry->CurrTxRateIndex = new rate index + pEntry->TxQuality is updated +*/ +VOID MlmeOldRateAdapt( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurrRateIdx, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN ULONG TrainUp, + IN ULONG TrainDown, + IN ULONG TxErrorRatio) +{ + BOOLEAN bTrainUp = FALSE; +#ifdef TXBF_SUPPORT + UCHAR *pTable = pEntry->pTable; + BOOLEAN invertTxBf = FALSE; +#endif /* TXBF_SUPPORT */ + + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + + pEntry->CurrTxRateStableTime++; + + /* Downgrade TX quality if PER >= Rate-Down threshold */ + if (TxErrorRatio >= TrainDown) + { + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); +#ifdef TXBF_SUPPORT + /* + Need to train down. If BF and last Non-BF isn't too much lower then + go to last Non-BF rate. Otherwise just go to the down rate + */ + if ((pEntry->phyETxBf || pEntry->phyITxBf) && + (DownRateIdx - pEntry->lastNonBfRate)<2 +#ifdef DBG_CTRL_SUPPORT + && ((pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA)==0) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Go directly to last non-BF rate without 100 msec check */ + pEntry->CurrTxRateIndex = pEntry->lastNonBfRate; + pEntry->phyETxBf = pEntry->phyITxBf = FALSE; + MlmeNewTxRate(pAd, pEntry); + DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,("DRS: --TX rate from %d to %d \n", CurrRateIdx, pEntry->CurrTxRateIndex)); + return; + } + else +#endif /* TXBF_SUPPORT */ + if (CurrRateIdx != DownRateIdx) + { +#ifdef NOISE_TEST_ADJUST + UCHAR *pTable = pEntry->pTable; + CHAR Rssi; + RTMP_RA_LEGACY_TB *pCurrTxRate; + + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + + if((Rssi > -60) && (pCurrTxRate->CurrMCS == 3) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + } + else +#endif /* NOISE_TEST_ADJUST */ + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + } + } + } + else + { + /* Upgrade TX quality if PER <= Rate-Up threshold */ + if (TxErrorRatio <= TrainUp) + { + bTrainUp = TRUE; + MlmeDecTxQuality(pEntry, CurrRateIdx); /* quality very good in CurrRate */ + + if (pEntry->TxRateUpPenalty) + pEntry->TxRateUpPenalty --; + else + MlmeDecTxQuality(pEntry, UpRateIdx); /* may improve next UP rate's quality */ + } + + if (bTrainUp) + { + /* Train up if up rate quality is 0 */ + if ((CurrRateIdx != UpRateIdx) && (MlmeGetTxQuality(pEntry, UpRateIdx) <= 0)) + { + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } +#ifdef TXBF_SUPPORT + else if (((CurrRateIdx != UpRateIdx) || (TxErrorRatio > TrainUp)) +#ifdef DBG_CTRL_SUPPORT + && ((pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA)==0) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* UpRate TxQuality is not 0. Try to invert BF state */ + if (pEntry->phyETxBf || pEntry->phyITxBf) + { + /* BF tries same MCS, non-BF */ + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; + + if (pEntry->TxQuality[CurrRateIdx]==0) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = CurrRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } + } + else if (pEntry->eTxBfEnCond>0 || pEntry->iTxBfEn) + { + RTMP_RA_LEGACY_TB *pUpRate = PTX_RA_LEGACY_ENTRY(pTable, UpRateIdx); + RTMP_RA_LEGACY_TB *pCurrTxRate = PTX_RA_LEGACY_ENTRY(pTable, CurrRateIdx); + + /* First try Up Rate with BF */ + if ((CurrRateIdx != UpRateIdx) && MlmeTxBfAllowed(pAd, pEntry, pUpRate)) + { + if (pEntry->BfTxQuality[UpRateIdx]) + pEntry->BfTxQuality[UpRateIdx]--; + + if (pEntry->BfTxQuality[UpRateIdx]==0) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } + } + + /* Try Same Rate if Up Rate failed */ + if (pEntry->LastSecTxRateChangeAction==RATE_NO_CHANGE && + MlmeTxBfAllowed(pAd, pEntry, pCurrTxRate)) + { + if (pEntry->BfTxQuality[CurrRateIdx]) + pEntry->BfTxQuality[CurrRateIdx]--; + + if (pEntry->BfTxQuality[CurrRateIdx]==0) + { + invertTxBf = TRUE; + pEntry->CurrTxRateIndex = CurrRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } + } + } + } +#endif /* TXBF_SUPPORT */ + } + } + + /* Handle the rate change */ + if (pEntry->LastSecTxRateChangeAction != RATE_NO_CHANGE) + { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; + + /* Save last rate information */ + pEntry->lastRateIdx = CurrRateIdx; +#ifdef TXBF_SUPPORT + if (pEntry->eTxBfEnCond>0) + { + pEntry->lastRatePhyTxBf = pEntry->phyETxBf; + pEntry->phyETxBf ^= invertTxBf; + } + else + { + pEntry->lastRatePhyTxBf = pEntry->phyITxBf; + pEntry->phyITxBf ^= invertTxBf; + } +#endif /* TXBF_SUPPORT */ + + /* Update TxQuality */ + if (pEntry->LastSecTxRateChangeAction == RATE_UP) + { + /* Clear history if normal train up */ + if (pEntry->lastRateIdx != pEntry->CurrTxRateIndex) + MlmeClearTxQuality(pEntry); + } + else + { + /* Clear the down rate history */ + MlmeSetTxQuality(pEntry, pEntry->CurrTxRateIndex, 0); + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + } + + /* Set timer for check in 100 msec */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!pAd->ApCfg.ApQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, pAd->ra_fast_interval); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, pAd->ra_fast_interval); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* Update PHY rate */ + MlmeNewTxRate(pAd, pEntry); + } + +#ifdef THERMAL_PROTECT_SUPPORT + if ((pAd->force_one_tx_stream == TRUE) && + (pEntry->LastSecTxRateChangeAction == RATE_NO_CHANGE)) { + MlmeNewTxRate(pAd, pEntry); + } +#endif /* THERMAL_PROTECT_SUPPORT */ +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/ra_ctrl.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/ra_ctrl.c new file mode 100644 index 000000000..937d76691 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/rate_ctrl/ra_ctrl.c @@ -0,0 +1,3231 @@ +/**************************************************************************** + * 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. + ***************************************************************************/ + +#include "rt_config.h" + + + +UCHAR RateSwitchTable11B[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x04, 0x03, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, +}; + +UCHAR RateSwitchTable11BG[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0a, 0x00, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x10, 2, 20, 35, + 0x05, 0x10, 3, 16, 35, + 0x06, 0x10, 4, 10, 25, + 0x07, 0x10, 5, 16, 25, + 0x08, 0x10, 6, 10, 25, + 0x09, 0x10, 7, 10, 13, +}; + +UCHAR RateSwitchTable11G[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x08, 0x00, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x10, 0, 20, 101, + 0x01, 0x10, 1, 20, 35, + 0x02, 0x10, 2, 20, 35, + 0x03, 0x10, 3, 16, 35, + 0x04, 0x10, 4, 10, 25, + 0x05, 0x10, 5, 16, 25, + 0x06, 0x10, 6, 10, 25, + 0x07, 0x10, 7, 10, 13, +}; + + +#ifdef DOT11_N_SUPPORT +UCHAR RateSwitchTable11N1S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x21, 5, 10, 25, + 0x09, 0x21, 6, 8, 14, + 0x0a, 0x21, 7, 8, 14, + 0x0b, 0x23, 7, 8, 14, +}; + + +UCHAR RateSwitchTable11N2S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x20, 11, 15, 30, + 0x09, 0x20, 12, 15, 30, + 0x0a, 0x20, 13, 8, 20, + 0x0b, 0x20, 14, 8, 20, + 0x0c, 0x20, 15, 8, 25, + 0x0d, 0x22, 15, 8, 15, +}; + + +UCHAR RateSwitchTable11N3S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x11, 0x0c, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x20, 11, 15, 30, + 0x09, 0x20, 12, 15, 22, + 0x0a, 0x20, 13, 8, 20, + 0x0b, 0x20, 14, 8, 20, + 0x0c, 0x20, 20, 8, 20, + 0x0d, 0x20, 21, 8, 20, + 0x0e, 0x20, 22, 8, 20, + 0x0f, 0x20, 23, 8, 20, + 0x10, 0x22, 23, 8, 15, +}; + + +UCHAR RateSwitchTable11BGN1S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x21, 5, 10, 25, + 0x09, 0x21, 6, 8, 14, + 0x0a, 0x21, 7, 8, 14, + 0x0b, 0x23, 7, 8, 14, +}; + + +UCHAR RateSwitchTable11BGN2S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x20, 11, 15, 30, + 0x09, 0x20, 12, 15, 22, + 0x0a, 0x20, 13, 8, 20, + 0x0b, 0x20, 14, 8, 20, + 0x0c, 0x20, 15, 8, 20, + 0x0d, 0x22, 15, 8, 15, +}; + + +UCHAR RateSwitchTable11BGN3S[] = { /* 3*3*/ +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0e, 0x00, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x21, 0, 30,101, /*50*/ + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 20, 50, + 0x04, 0x21, 4, 15, 50, + 0x05, 0x20, 11, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + /*0x0a, 0x20, 20, 15, 30,*/ + 0x0a, 0x20, 21, 8, 20, + 0x0b, 0x20, 22, 8, 20, + 0x0c, 0x20, 23, 8, 25, + 0x0d, 0x22, 23, 8, 25, +}; + + +UCHAR RateSwitchTable11N1SForABand[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown */ +/* Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x09, 0x07, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 10, 25, + 0x06, 0x21, 6, 8, 14, + 0x07, 0x21, 7, 8, 14, + 0x08, 0x23, 7, 8, 14, +}; + + +UCHAR RateSwitchTable11N2SForABand[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0b, 0x09, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + + +UCHAR RateSwitchTable11BGN2SForABand[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0b, 0x09, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x21, 0, 30,101, /*50*/ + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + + +UCHAR RateSwitchTable11N3SForABand[] = { /* 3*3*/ +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0e, 0x09, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + /*0x0a, 0x22, 15, 8, 25,*/ + /*0x0a, 0x20, 20, 15, 30,*/ + 0x0a, 0x20, 21, 8, 20, + 0x0b, 0x20, 22, 8, 20, + 0x0c, 0x20, 23, 8, 25, + 0x0d, 0x22, 23, 8, 25, +}; + + +UCHAR RateSwitchTable11BGN3SForABand[] = { /* 3*3*/ +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x0e, 0x09, 0, 0, 0, /* Initial used item after association*/ + 0x00, 0x21, 0, 30,101, /*50*/ + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + /*0x0a, 0x22, 15, 8, 25,*/ + /*0x0a, 0x20, 20, 15, 30,*/ + 0x0a, 0x20, 21, 8, 20, + 0x0b, 0x20, 22, 8, 20, + 0x0c, 0x20, 23, 8, 25, + 0x0d, 0x22, 23, 8, 25, +}; + + +#ifdef NEW_RATE_ADAPT_SUPPORT + +#ifdef RANGE_EXTEND +#define SUPPORT_SHORT_GI_RA /* Support switching to Short GI rates in RA */ +#endif /* RANGE_EXTEND */ + +/* + Rate switch tables for New Rate Adaptation + + Each row has 10 bytes of data. + First row contains table information: + Byte0=the number of rate entries, Byte1=the initial rate. + Format of Mode byte: + Bit0: STBC, + Bit1: Short GI, + Bit4~6: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) +*/ +UCHAR RateSwitchTableAdapt11N1S[] = { +/* item no. mcs highPERThrd upMcs3 upMcs1 + mode lowPERThrd downMcs upMcs2 +*/ + 12, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x21, 0, 30, 50, 11, 1, 8, 1, 7,/* mcs0 */ + 1, 0x21, 1, 20, 50, 0, 16, 9, 2, 13,/* mcs1 */ + 2, 0x21, 2, 20, 50, 1, 17, 9, 3, 20,/* mcs2 */ + 3, 0x21, 3, 15, 50, 2, 17, 10, 4, 26,/* mcs3 */ + 4, 0x21, 4, 15, 30, 3, 18, 11, 5, 39,/* mcs4 */ + 5, 0x21, 5, 10, 25, 4, 18, 12, 6, 52,/* mcs5 */ + 6, 0x21, 6, 8, 14, 5, 19, 12, 7, 59,/* mcs6 */ + 7, 0x21, 7, 8, 14, 6, 19, 12, 8, 65,/* mcs7 */ + 8, 0x23, 7, 8, 14, 7, 19, 12, 8, 72,/* mcs7+short gi */ + + 9, 0x00, 0, 40, 101, 9 , 9, 9, 10, 1, /* cck-1M */ + 10, 0x00, 1, 40, 50, 9, 10, 10, 11, 2, /* cck-2M */ + 11, 0x10, 0, 30, 50, 10, 0, 0, 0, 6, /* OFDM 6M */ +}; + +#ifdef SUPPORT_SHORT_GI_RA +/* Indices for Short GI rates in 11N2S table */ + #define sg07 18 /* mcs7+shortGI index */ + #define sg14 17 /* mcs14+shortGI index */ + #define sg15 16 /* mcs15+shortGI index */ +#endif + +UCHAR RateSwitchTableAdapt11N2S[] = { +/* item no. mcs highPERThrd upMcs3 upMcs1 + mode lowPERThrd downMcs upMcs2 +*/ + 22, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x21, 0, 30, 50, 21, 1, 8, 1, 7,/* mcs0 */ + 1, 0x21, 1, 20, 50, 0, 16, 9, 2, 13,/* mcs1 */ + 2, 0x21, 2, 20, 50, 1, 17, 9, 3, 20,/* mcs2 */ + 3, 0x21, 3, 15, 50, 2, 17, 10, 4, 26,/* mcs3 */ + 4, 0x21, 4, 15, 30, 3, 18, 11, 5, 39,/* mcs4 */ + 5, 0x21, 5, 10, 25, 4, 18, 12, 6, 52,/* mcs5 */ + 6, 0x21, 6, 8, 14, 5, 19, 12, 7, 59,/* mcs6 */ +#ifdef SUPPORT_SHORT_GI_RA + 7, 0x21, 7, 8, 14, 6, 19, 12, sg07, 65,/* mcs7 */ +#else + 7, 0x21, 7, 8, 14, 6, 19, 12, 7, 65,/* mcs7 */ +#endif + 8, 0x20, 8, 30, 50, 0, 16, 9, 2, 13,/* mcs8 */ + 9, 0x20, 9, 20, 50, 8, 17, 10, 4, 26,/* mcs9 */ + 10, 0x20, 10, 20, 40, 9, 18, 11, 5, 39,/* mcs10 */ + 11, 0x20, 11, 15, 30, 10, 18, 12, 6, 52,/* mcs11 */ + 12, 0x20, 12, 15, 30, 11, 20, 13, 12, 78,/* mcs12 */ + 13, 0x20, 13, 8, 20, 12, 20, 14, 13, 104,/* mcs13 */ +#ifdef SUPPORT_SHORT_GI_RA + 14, 0x20, 14, 8, 18, 13, 21, 15,sg14, 117,/* mcs14 */ + 15, 0x20, 15, 8, 25, 14, 21,sg15,sg14, 130,/* mcs15 */ + 16, 0x22, 15, 8, 25, 15, 21,sg15,sg15, 144,/* mcs15+shortGI */ + + 17, 0x22, 14, 8, 14, 14, 21,sg15, 15, 130, /* mcs14+shortGI */ + 18, 0x23, 7, 8, 14, 7, 19, 12,sg07, 72, /* mcs7+shortGI */ +#else + 14, 0x20, 14, 8, 18, 13, 21, 15, 14, 117,/* mcs14 */ + 15, 0x20, 15, 8, 25, 14, 21, 16, 15, 130,/* mcs15 */ + 16, 0x22, 15, 8, 25, 15, 21, 16, 16, 144,/* mcs15+shortGI */ + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#endif + 19, 0x00, 0, 40, 101, 19 , 19, 19, 20, 1, /* cck-1M */ + 20, 0x00, 1, 40, 50, 19, 20, 20, 21, 2, /* cck-2M */ + 21, 0x10, 0, 30, 50, 20, 8, 8, 0, 7, /* OFDM 6M */ +}; + +#ifdef SUPPORT_SHORT_GI_RA +/* Indices for Short GI rates in 11N3S table */ + #undef sg07 + #undef sg14 + #undef sg15 + #define sg07 29 /* mcs7+shortGI index */ + #define sg14 27 /* mcs14+shortGI index */ + #define sg15 28 /* mcs15+shortGI index */ + #define sg21 25 /* mcs21+shortGI index */ + #define sg22 26 /* mcs22+shortGI index */ + #define sg23 24 /* mcs23+shortGI index */ +#endif + +UCHAR RateSwitchTableAdapt11N3S[] = { +/* item no mcs highPERThrd upMcs3 upMcs1 + mode lowPERThrd downMcs upMcs2 +*/ + 33, 23, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x21, 0, 30, 50, 32, 1, 8, 1, 7, /* mcs0 */ + 1, 0x21, 1, 20, 50, 0, 16, 9, 2, 13, /* mcs1 */ + 2, 0x21, 2, 20, 50, 1, 17, 9, 3, 20, /* mcs2 */ + 3, 0x21, 3, 15, 50, 2, 17, 10, 4, 26, /* mcs3 */ + 4, 0x21, 4, 15, 30, 3, 18, 11, 5, 39, /* mcs4 */ + 5, 0x21, 5, 10, 25, 4, 18, 12, 6, 52, /* mcs5 */ + 6, 0x21, 6, 8, 14, 5, 19, 12, 7, 59, /* mcs6 */ +#ifdef SUPPORT_SHORT_GI_RA + 7, 0x21, 7, 8, 14, 6, 19, 12, sg07, 65, /* mcs7 */ +#else + 7, 0x21, 7, 8, 14, 6, 19, 12, 7, 65, /* mcs7 */ +#endif /* SUPPORT_SHORT_GI_RA */ + 8, 0x20, 8, 30, 50, 0, 16, 9, 2, 13, /* mcs8 */ + 9, 0x20, 9, 20, 50, 8, 17, 10, 4, 26, /* mcs9 */ + 10, 0x20, 10, 20, 40, 9, 18, 11, 5, 39, /* mcs10 */ + 11, 0x20, 11, 15, 30, 10, 18, 12, 6, 52, /* mcs11 */ + 12, 0x20, 12, 15, 30, 11, 20, 13, 12, 78, /* mcs12 */ + 13, 0x20, 13, 8, 20, 12, 20, 14, 13, 104, /* mcs13 */ +#ifdef SUPPORT_SHORT_GI_RA + 14, 0x20, 14, 8, 18, 13, 21, 15, sg14, 117, /* mcs14 */ + 15, 0x20, 15, 8, 14, 14, 21, sg15, sg14, 130, /* mcs15 */ +#else + 14, 0x20, 14, 8, 18, 13, 21, 15, 14, 117, /* mcs14 */ + 15, 0x20, 15, 8, 14, 14, 21, 15, 15, 130, /* mcs15 */ +#endif /* SUPPORT_SHORT_GI_RA */ + 16, 0x20, 16, 30, 50, 8, 17, 9, 3, 20, /* mcs16 */ + 17, 0x20, 17, 20, 50, 16, 18, 11, 5, 39, /* mcs17 */ + 18, 0x20, 18, 20, 40, 17, 19, 12, 7, 59, /* mcs18 */ + 19, 0x20, 19, 15, 30, 18, 20, 13, 19, 78, /* mcs19 */ + 20, 0x20, 20, 15, 30, 19, 21, 15, 20, 117, /* mcs20 */ +#ifdef SUPPORT_SHORT_GI_RA + 21, 0x20, 21, 8, 20, 20, 22, sg21, 21, 156, /* mcs21 */ + 22, 0x20, 22, 8, 20, 21, 23, sg22, sg21, 176, /* mcs22 */ + 23, 0x20, 23, 6, 18, 22, sg23, 23, sg22, 195, /* mcs23 */ + 24, 0x22, 23, 6, 14, 23, sg23, sg23, sg23, 217, /* mcs23+shortGI */ + + 25, 0x22, 21, 6, 18, 21, sg22, 22, sg21, 173, /* mcs21+shortGI */ + 26, 0x22, 22, 6, 18, 22, sg23, 23, sg22, 195, /* mcs22+shortGI */ + 27, 0x22, 14, 8, 14, 14, 21, sg15, 15, 130, /* mcs14+shortGI */ + 28, 0x22, 15, 8, 14, 15, 21, sg15, sg15, 144, /* mcs15+shortGI */ + 29, 0x23, 7, 8, 14, 7, 19, 12, 29, 72, /* mcs7+shortGI */ +#else + 21, 0x20, 21, 8, 20, 20, 22, 21, 21, 156, /* mcs21 */ + 22, 0x20, 22, 8, 20, 21, 23, 22, 22, 176, /* mcs22 */ + 23, 0x20, 23, 6, 18, 22, 24, 23, 23, 195, /* mcs23 */ + 24, 0x22, 23, 6, 14, 23, 24, 24, 24, 217, /* mcs23+shortGI */ + 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#endif /* SUPPORT_SHORT_GI_RA */ + 30, 0x00, 0, 40, 101, 30 , 30, 30, 31, 1, /* cck-1M */ + 31, 0x00, 1, 40, 50, 30, 31, 31, 32, 2, /* cck-2M */ + 32, 0x21, 32, 30, 50, 31, 0, 8, 0, 7, /* mcs32 or 20M/mcs0 */ +}; + + +#ifdef DOT11_VHT_AC +/* + VHT-capable rate table + + Each row has 10 bytes of data. + + 1. First row contains table info, which is initial used item after assoc: + Byte0=the number of rate entries, Byte1=the initial rate. + + 2. rest rows Format: + [Index] [Mode] [nSS] [CurrMCS] [PERThrd Low/High] [downMCS] [upMCS3/2/1] + + [Mode]: + bit0: STBC + bit1: Short GI + bit2~3: BW - (20M/40M/80M) + bit4~bit6: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF, 4: VHT) - MODE_XXX + bit7: Reserved + [nSS]: + Number of Spatial Stream + + Note: downMCS, upMCS3, upMCS2 and upMCS1 are zero-based array index. +*/ +/* 1x1 VHT-capable rate table */ +UCHAR RateTableVht1S[] = +{ + 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, +/* [Idx] [Mode] [MCS] [PER_Low/High] [dMCS] [upMCS3/2/1] [nSS]*/ + 0, 0x10, 0, 30, 101, 0, 0, 0, 1, 1, + 1, 0x25, 0, 30, 50, 0, 0, 0, 2, 1, + 2, 0x49, 0, 30, 50, 1, 0, 0, 3, 1, + 3, 0x49, 1, 20, 50, 2, 0, 0, 4, 1, + 4, 0x49, 2, 20, 50, 3, 0, 0, 5, 1, + 5, 0x49, 3, 15, 50, 4, 0, 0, 6, 1, + 6, 0x49, 4, 15, 30, 5, 0, 0, 7, 1, + 7, 0x49, 5, 10, 25, 6, 0, 0, 8, 1, + 8, 0x49, 6, 8, 14, 7, 0, 0, 9, 1, + 9, 0x49, 7, 8, 14, 8, 0, 0, 10, 1, + 10, 0x4B, 7, 8, 14, 9, 0, 0, 10, 1, +}; + +//S4 +UCHAR RateTableVht1S_MCS9[] = +{ + 18, 17, 0, 0, 0, 0, 0, 0, 0, 0, +/* [Idx] [Mode] [MCS] [PER_Low/High] [dMCS] [upMCS3/2/1] [nSS] */ + 0, 0x10, 0, 30, 101, 0, 0, 0, 1, 1, /* OFDM, MCS0, BW20 */ + + 1, 0x11, 1, 20, 40, 0, 0, 0, 2, 1, /* OFDM 1x1 MCS1 BW20 */ + 2, 0x11, 2, 20, 35, 1, 0, 0, 3, 1, /* OFDM 1x1 MCS2 BW20 */ + 3, 0x11, 3, 15, 35, 2, 0, 0, 5, 1, /* OFDM 1X1 MCS3 BW20 */ + + 4, 0x45, 0, 20, 40, 2, 0, 0, 5, 1, /* VHT, MCS0, BW40, STBC */ + 5, 0x45, 1, 25, 50, 3, 0, 0, 9, 1, /* VHT, MCS1, BW40, STBC */ + 6, 0x45, 2, 15, 35, 5, 0, 0, 7, 1, /* VHT, MCS2, BW40, STBC */ + + 7, 0x49, 0, 30, 50, 6, 0, 0, 8, 1, /* VHT, MCS0, BW80, STBC */ + 8, 0x49, 1, 20, 35, 7, 0, 0, 9, 1, /* VHT, MCS1, BW80, STBC */ + 9, 0x49, 2, 20, 35, 8, 0, 0, 10, 1, /* VHT, MCS2, BW80, STBC */ + 10, 0x49, 3, 15, 30, 9, 0, 0, 11, 1, /* VHT, MCS3, BW80, STBC */ + 11, 0x49, 4, 15, 30, 10, 0, 0, 12, 1, /* VHT, MCS4, BW80, STBC */ + 12, 0x49, 5, 12, 25, 11, 0, 0, 13, 1, /* VHT, MCS5, BW80, STBC */ + 13, 0x49, 6, 12, 15, 12, 0, 0, 14, 1, /* VHT, MCS6, BW80, STBC */ + 14, 0x49, 7, 12, 15, 13, 0, 0, 15, 1, /* VHT, MCS7, BW80, STBC */ + 15, 0x49, 8, 12, 15, 14, 0, 0, 16, 1, /* VHT, MCS8, BW80, STBC */ + 16, 0x49, 9, 12, 15, 15, 0, 0, 17, 1, /* VHT, MCS9, BW80, STBC */ + 17, 0x4A, 9, 12, 15, 16, 0, 0, 17, 1, /* VHT, MCS9, BW80, SGI */ +}; +//S4 + +/* 2x2 VHT-capable rate table */ +// TODO: shiang-usw, refine this!! +UCHAR RateTableVht2S_old[] = +{ + 22, 21, 0, 0, 0, 0, 0, 0,0, 0, +/* [Idx] [Mode] [MCS] [PER_Low/High] [dMCS] [upMCS3/2/1] [nSS]*/ + 0, 0x10, 0, 30, 101, 0, 0, 1, 1, 1, /* OFDM 1x1 MCS0 BW20 */ + 1, 0x25, 0, 30, 50, 0, 0, 2, 2, 1, /* HT 1x1 MCS0 BW40 */ + 2, 0x49, 0, 30, 50, 1, 0, 10, 3, 1, /* VHT 1x1 MCS0 BW80 LGI */ + 3, 0x49, 1, 20, 50, 2, 0, 11, 4, 1, /* VHT 1x1 MCS1 BW80 LGI */ + 4, 0x49, 2, 20, 50, 3, 0, 11, 5, 1, /* VHT 1x1 MCS2 BW80 LGI */ + 5, 0x49, 3, 15, 50, 4, 0, 12, 6, 1, /* VHT 1x1 MCS3 BW80 LGI */ + 6, 0x49, 4, 15, 30, 5, 0, 13, 7, 1, /* VHT 1x1 MCS4 BW80 LGI */ + 7, 0x49, 5, 10, 25, 6, 0, 14, 8, 1, /* VHT 1x1 MCS5 BW80 LGI */ + 8, 0x49, 6, 8, 14, 7, 0, 14, 9, 1, /* VHT 1x1 MCS6 BW80 LGI */ + 9, 0x49, 7, 8, 14, 8, 0, 14, 9, 1, /* VHT 1x1 MCS7 BW80 LGI */ + 10, 0x48, 0, 30, 50, 2, 0, 11, 4, 2, /* VHT 2x2 MCS0 BW80 LGI */ + 11, 0x48, 1, 20, 50, 10, 0, 12, 6, 2, /* VHT 2x2 MCS1 BW80 LGI */ + 12, 0x48, 2, 20, 50, 11, 0, 13, 7, 2, /* VHT 2x2 MCS2 BW80 LGI */ + 13, 0x48, 3, 15, 30, 12, 0, 14, 8, 2, /* VHT 2x2 MCS3 BW80 LGI */ + 14, 0x48, 4, 15, 30, 13, 0, 15, 14, 2, /* VHT 2x2 MCS4 BW80 LGI */ + 15, 0x48, 5, 8, 20, 14, 0, 16, 15, 2, /* VHT 2x2 MCS5 BW80 LGI */ + 16, 0x48, 6, 8, 18, 15, 0, 17, 16, 2, /* VHT 2x2 MCS6 BW80 LGI */ + 17, 0x48, 7, 8, 25, 16, 0, 18, 17, 2, /* VHT 2x2 MCS7 BW80 LGI */ + 18, 0x4A, 7, 8, 25, 17, 0, 19, 18, 2, /* VHT 2x2 MCS7 BW80 SGI */ + 19, 0x48, 8, 8, 25, 18, 0, 20, 19, 2, /* VHT 2x2 MCS8 BW80 LGI */ + 20, 0x48, 9, 8, 25, 19, 0, 21, 20, 2, /* VHT 2x2 MCS9 BW80 LGI */ + 21, 0x4A, 9, 8, 25, 20, 0, 21, 21, 2, /* VHT 2x2 MCS9 BW80 SGI */ +}; + +UCHAR RateTableVht2S_MCS7[] = +{ + 41, 40, 0, 0, 0, 0, 0, 0, 0, 0, + /* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* The Data Rate of OFDM for long distance */ + 0, 0x11, 0, 20, 101, 0, 0, 1, 2, 1,/* OFDM 1x1 MCS0 BW20 */ + 1, 0x11, 1, 20, 40, 0, 0, 5, 2, 1,/* OFDM 1x1 MCS1 BW20 */ + 2, 0x11, 2, 20, 35, 1, 0, 6, 3, 1,/* OFDM 1x1 MCS2 BW20 */ + 3, 0x11, 3, 15, 35, 2, 0, 8, 8, 1,/* OFDM 1X1 MCS3 BW20 */ + + /* The Group Data Rate of 1SS VHT BW 20 */ + 4, 0x41, 0, 25, 50, 0, 0, 5, 7, 1,/* VHT 1x1 MCS0 BW20 */ + 5, 0x41, 1, 25, 50, 4, 0, 6, 8, 1,/* VHT 1X1 MCS1 BW20 */ + 6, 0x41, 2, 15, 35, 5, 0, 8, 8, 1,/* VHT 1X1 MCS2 BW20 */ + + /* The Group Data Rate of 1SS VHT BW 40 */ + 7, 0x45, 0, 25, 50, 6, 0, 8, 10, 1,/* VHT 1x1 MCS0 BW40 */ + 8, 0x45, 1, 25, 50, 7, 0, 9, 11, 1,/* VHT 1x1 MCS1 BW40 */ + 9, 0x45, 2, 15, 35, 8, 0, 11, 11, 1,/* VHT 1x1 MCS2 BW40 */ + + /* The Group Data Rate of 2SS VHT BW 40 */ + 10, 0x44, 0, 25, 50, 7, 0, 20, 11, 2,/* VHT 2x2 MCS0 BW40 */ + 11, 0x44, 1, 20, 35, 9, 0, 30, 12, 2,/* VHT 2x2 MCS1 BW40 */ + 12, 0x44, 2, 20, 35, 11, 0, 31, 13, 2,/* VHT 2x2 MCS2 BW40 */ + 13, 0x44, 3, 15, 30, 12, 0, 31, 14, 2,/* VHT 2x2 MCS3 BW40 */ + 14, 0x44, 4, 15, 30, 13, 0, 32, 15, 2,/* VHT 2x2 MCS4 BW40 */ + 15, 0x44, 5, 10, 25, 14, 0, 33, 33, 2,/* VHT 2x2 MCS5 BW40 */ + + /* The Group Not Used */ + 16, 0x44, 9, 0, 101, 40, 0, 40, 40, 2, + 17, 0x44, 9, 0, 101, 40, 0, 40, 40, 2, + 18, 0x44, 9, 0, 101, 40, 0, 40, 40, 2, + 19, 0x44, 9, 0, 101, 40, 0, 40, 40, 2, + + /* The Group Data Rate of 1SS with VHT BW80 */ + 20, 0x49, 0, 25, 50, 7, 0, 30, 21, 1,/* VHT 1x1 MCS0 BW80 LGI */ + 21, 0x49, 1, 20, 35, 9, 0, 31, 22, 1,/* VHT 1x1 MCS1 BW80 LGI */ + 22, 0x49, 2, 20, 35, 21, 0, 31, 23, 1,/* VHT 1x1 MCS2 BW80 LGI */ + 23, 0x49, 3, 15, 30, 22, 0, 32, 24, 1,/* VHT 1x1 MCS3 BW80 LGI */ + 24, 0x49, 4, 15, 30, 23, 0, 33, 25, 1,/* VHT 1x1 MCS4 BW80 LGI */ + 25, 0x49, 5, 10, 25, 24, 0, 34, 26, 1,/* VHT 1x1 MCS5 BW80 LGI */ + 26, 0x49, 6, 8, 15, 25, 0, 34, 27, 1,/* VHT 1x1 MCS6 BW80 LGI */ + 27, 0x49, 7, 8, 15, 26, 0, 34, 27, 1,/* VHT 1x1 MCS7 BW80 LGI */ + 28, 0x49, 8, 8, 15, 27, 0, 27, 27, 1,/* VHT 1x1 MCS8 BW80 LGI */ + 29, 0x49, 9, 8, 15, 28, 0, 27, 27, 1,/* VHT 1x1 MCS9 BW80 LGI */ + + /* The Group Data Rate of 2SS with VHT BW 80 */ + 30, 0x48, 0, 15, 30, 9, 0, 31, 22, 2,/* VHT 2x2 MCS0 BW80 LGI */ + 31, 0x48, 1, 15, 30, 30, 0, 32, 24, 2,/* VHT 2x2 MCS1 BW80 LGI */ + 32, 0x48, 2, 15, 30, 31, 0, 33, 25, 2,/* VHT 2x2 MCS2 BW80 LGI */ + 33, 0x48, 3, 15, 30, 32, 0, 34, 26, 2,/* VHT 2x2 MCS3 BW80 LGI */ + 34, 0x48, 4, 15, 30, 33, 0, 35, 29, 2,/* VHT 2x2 MCS4 BW80 LGI */ + 35, 0x48, 5, 8, 20, 34, 0, 36, 36, 2,/* VHT 2x2 MCS5 BW80 LGI */ + 36, 0x48, 6, 8, 20, 35, 0, 37, 37, 2,/* VHT 2x2 MCS6 BW80 LGI */ + 37, 0x48, 7, 8, 20, 36, 0, 38, 38, 2,/* VHT 2x2 MCS7 BW80 LGI */ + 38, 0x4A, 7, 5, 15, 37, 0, 38, 38, 2,/* VHT 2x2 MCS7 BW80 SGI */ + 39, 0x48, 9, 5, 15, 38, 0, 38, 38, 2,/* VHT 2x2 MCS9 BW80 LGI */ + 40, 0x4A, 9, 5, 15, 39, 0, 38, 38, 2,/* VHT 2x2 MCS9 BW80 SGI */ +}; + +UCHAR RateTableVht2S[] = +{ + 41, 40, 0, 0, 0, 0, 0, 0, 0, 0, +/* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* The Data Rate of OFDM for long distance */ + 0, 0x11, 0, 20, 101, 0, 0, 1, 1, 1,/* OFDM 1x1 MCS0 BW20 */ + 1, 0x11, 1, 20, 40, 0, 0, 2, 2, 1,/* OFDM 1x1 MCS1 BW20 */ + 2, 0x11, 2, 20, 35, 1, 0, 3, 3, 1,/* OFDM 1x1 MCS2 BW20 */ + 3, 0x11, 3, 15, 35, 2, 0, 8, 8, 1,/* OFDM 1X1 MCS3 BW20 */ + + /* The Group Data Rate of 1SS VHT BW 20 */ + 4, 0x11, 1, 20, 40, 0, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 1, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 2, 0, 8, 8, 1,/* OFDM 1X1 MCS3 BW20 */ + + /* The Group Data Rate of 1SS VHT BW 40 */ + 7, 0x45, 0, 25, 50, 3, 0, 8, 8, 1,/* VHT 1x1 MCS0 BW40 */ + 8, 0x45, 1, 25, 50, 3, 0, 9, 9, 1,/* VHT 1x1 MCS1 BW40 */ + 9, 0x45, 2, 15, 35, 8, 0, 21, 21, 1,/* VHT 1x1 MCS2 BW40 */ + 10, 0x45, 3, 15, 30, 9, 0, 15, 11, 1,/* VHT 1x1 MCS3 BW40 */ + 11, 0x45, 4, 15, 30, 10, 0, 16, 12, 1,/* VHT 1x1 MCS4 BW40 */ + 12, 0x45, 5, 10, 25, 11, 0, 16, 16, 1,/* VHT 1x1 MCS5 BW40 */ + + /* The Group Data Rate of 2SS VHT BW 40 */ + 13, 0x44, 0, 25, 50, 7, 0, 14, 14, 2,/* VHT 2x2 MCS0 BW40 */ + 14, 0x44, 1, 20, 35, 9, 0, 15, 15, 2,/* VHT 2x2 MCS1 BW40 */ + 15, 0x44, 2, 20, 35, 10, 0, 16, 16, 2,/* VHT 2x2 MCS2 BW40 */ + 16, 0x44, 3, 15, 30, 11, 0, 17, 17, 2,/* VHT 2x2 MCS3 BW40 */ + 17, 0x44, 4, 15, 30, 16, 0, 18, 18, 2,/* VHT 2x2 MCS4 BW40 */ + 18, 0x44, 5, 10, 25, 17, 0, 33, 33, 2,/* VHT 2x2 MCS5 BW40 */ + + /* The Group Not Used */ + 19, 0x44, 9, 0, 101, 40, 0, 40, 40, 2, + + /* The Group Data Rate of 1SS with VHT BW80 */ + 20, 0x49, 0, 25, 50, 8, 0, 21, 21, 1,/* VHT 1x1 MCS0 BW80 LGI */ + 21, 0x49, 1, 20, 35, 9, 0, 22, 22, 1,/* VHT 1x1 MCS1 BW80 LGI */ + 22, 0x49, 2, 20, 35, 21, 0, 23, 23, 1,/* VHT 1x1 MCS2 BW80 LGI */ + 23, 0x49, 3, 15, 30, 22, 0, 31, 24, 1,/* VHT 1x1 MCS3 BW80 LGI */ + 24, 0x49, 4, 15, 30, 23, 0, 32, 25, 1,/* VHT 1x1 MCS4 BW80 LGI */ + 25, 0x49, 5, 10, 25, 24, 0, 33, 26, 1,/* VHT 1x1 MCS5 BW80 LGI */ + 26, 0x49, 6, 8, 15, 25, 0, 34, 27, 1,/* VHT 1x1 MCS6 BW80 LGI */ + 27, 0x49, 7, 8, 15, 26, 0, 34, 28, 1,/* VHT 1x1 MCS7 BW80 LGI */ + 28, 0x49, 8, 8, 15, 27, 0, 35, 29, 1,/* VHT 1x1 MCS8 BW80 LGI */ + 29, 0x49, 9, 8, 15, 28, 0, 35, 35, 1,/* VHT 1x1 MCS9 BW80 LGI */ + + /* The Group Data Rate of 2SS with VHT BW 80 */ + 30, 0x48, 0, 15, 30, 9, 0, 31, 22, 2,/* VHT 2x2 MCS0 BW80 LGI */ + 31, 0x48, 1, 15, 30, 22, 0, 32, 24, 2,/* VHT 2x2 MCS1 BW80 LGI */ + 32, 0x48, 2, 15, 30, 23, 0, 33, 25, 2,/* VHT 2x2 MCS2 BW80 LGI */ + 33, 0x48, 3, 10, 25, 24, 0, 34, 26, 2,/* VHT 2x2 MCS3 BW80 LGI */ + 34, 0x48, 4, 8, 20, 33, 0, 35, 29, 2,/* VHT 2x2 MCS4 BW80 LGI */ + 35, 0x48, 5, 8, 20, 34, 0, 36, 36, 2,/* VHT 2x2 MCS5 BW80 LGI */ + 36, 0x48, 6, 8, 20, 35, 0, 37, 37, 2,/* VHT 2x2 MCS6 BW80 LGI */ + 37, 0x48, 7, 8, 20, 36, 0, 38, 38, 2,/* VHT 2x2 MCS7 BW80 LGI */ + 38, 0x48, 8, 5, 15, 37, 0, 39, 39, 2,/* VHT 2x2 MCS8 BW80 LGI */ + 39, 0x48, 9, 5, 15, 38, 0, 40, 40, 2,/* VHT 2x2 MCS9 BW80 LGI */ + 40, 0x4A, 9, 5, 15, 39, 0, 40, 40, 2,/* VHT 2x2 MCS9 BW80 SGI */ +}; + +UCHAR RateTableVht2S_BW40[] = +{ + 31, 30, 0, 0, 0, 0, 0, 0, 0, 0, +/* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* reserved */ + 0, 0x11, 0, 100, 101, 3, 0, 4, 4, 1, + 1, 0x11, 0, 100, 101, 3, 0, 4, 4, 1, + 2, 0x11, 0, 100, 101, 3, 0, 4, 4, 1, + + /* The Data Rate of OFDM for long distance */ + 3, 0x11, 0, 20, 101, 3, 0, 4, 4, 1,/* OFDM 1x1 MCS0 BW20 */ + 4, 0x11, 1, 20, 40, 3, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 4, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 5, 0, 11, 11, 1,/* OFDM 1x1 MCS3 BW20 */ + + /* The Data Rate of VHT BW 20/40 */ + 7, 0x41, 0, 15, 25, 3, 0, 10, 10, 1,/* VHT 1x1 MCS0 BW20 LGI*/ + 8, 0x00, 0, 0, 0, 0, 0, 0, 0, 1, + 9, 0x00, 0, 0, 0, 0, 0, 0, 0, 1, + + /* The Group Data Rate of 1SS with VHT BW40 */ + 10, 0x45, 0, 25, 50, 5, 0, 11, 11, 1,/* VHT 1x1 MCS0 BW40 LGI */ + 11, 0x45, 1, 25, 40, 6, 0, 12, 12, 1,/* VHT 1x1 MCS1 BW40 LGI */ + 12, 0x45, 2, 20, 35, 11, 0, 13, 13, 1,/* VHT 1x1 MCS2 BW40 LGI */ + 13, 0x45, 3, 15, 30, 12, 0, 22, 14, 1,/* VHT 1x1 MCS3 BW40 LGI */ + 14, 0x45, 4, 15, 30, 13, 0, 23, 15, 1,/* VHT 1x1 MCS4 BW40 LGI */ + 15, 0x45, 5, 10, 25, 14, 0, 24, 16, 1,/* VHT 1x1 MCS5 BW40 LGI */ + 16, 0x45, 6, 8, 15, 15, 0, 24, 17, 1,/* VHT 1x1 MCS6 BW40 LGI */ + 17, 0x45, 7, 8, 15, 16, 0, 24, 18, 1,/* VHT 1x1 MCS7 BW40 LGI */ + 18, 0x45, 8, 8, 15, 17, 0, 25, 19, 1,/* VHT 1x1 MCS8 BW40 LGI */ + 19, 0x45, 9, 8, 15, 18, 0, 25, 25, 1,/* VHT 1x1 MCS9 BW40 LGI */ + + /* The Group Data Rate of 2SS with VHT BW40 */ + + 20, 0x44, 0, 30, 50, 10, 0, 21, 12, 2,/* VHT 2x2 MCS0 BW40 LGI */ + 21, 0x44, 1, 30, 50, 20, 0, 22, 14, 2,/* VHT 2x2 MCS1 BW40 LGI */ + 22, 0x44, 2, 15, 30, 21, 0, 23, 15, 2,/* VHT 2x2 MCS2 BW40 LGI */ + 23, 0x44, 3, 15, 30, 22, 0, 24, 16, 2,/* VHT 2x2 MCS3 BW40 LGI */ + 24, 0x44, 4, 15, 30, 23, 0, 25, 19, 2,/* VHT 2x2 MCS4 BW40 LGI */ + 25, 0x44, 5, 8, 20, 24, 0, 26, 26, 2,/* VHT 2x2 MCS5 BW40 LGI */ + 26, 0x44, 6, 8, 20, 25, 0, 27, 27, 2,/* VHT 2x2 MCS6 BW40 LGI */ + 27, 0x44, 7, 8, 20, 26, 0, 28, 28, 2,/* VHT 2x2 MCS7 BW40 LGI */ + 28, 0x44, 8, 5, 15, 27, 0, 29, 29, 2,/* VHT 2x2 MCS8 BW40 LGI */ + 29, 0x44, 9, 5, 15, 28, 0, 30, 30, 2,/* VHT 2x2 MCS9 BW40 LGI */ + 30, 0x46, 9, 5, 15, 29, 0, 30, 30, 2,/* VHT 2x2 MCS9 BW40 SGI */ +}; + +UCHAR RateTableVht2S_BW20[] = + +{ + 30, 28, 0, 0, 0, 0, 0, 0, 0, 0, +/* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* reserved */ + 0, 0x11, 0, 100, 101, 3, 0, 4, 4, 1, + 1, 0x11, 0, 100, 101, 3, 0, 4, 4, 1, + 2, 0x11, 0, 100, 101, 3, 0, 4, 4, 1, + + /* The Data Rate of OFDM for long distance */ + 3, 0x11, 0, 20, 101, 3, 0, 4, 4, 1,/* OFDM 1x1 MCS0 BW20 */ + 4, 0x11, 1, 20, 40, 3, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 4, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 5, 0, 13, 13, 1,/* OFDM 1x1 MCS3 BW20 */ + + 7, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + + /* The Group Data Rate of 1SS with VHT BW80 */ + 10, 0x41, 0, 15, 25, 3, 0, 11, 11, 1,/* VHT 1x1 MCS0 BW20 LGI */ + 11, 0x41, 1, 20, 35, 4, 0, 12, 12, 1,/* VHT 1x1 MCS1 BW20 LGI */ + 12, 0x41, 2, 20, 35, 5, 0, 13, 13, 1,/* VHT 1x1 MCS2 BW20 LGI */ + 13, 0x41, 3, 15, 30, 12, 0, 22, 14, 1,/* VHT 1x1 MCS3 BW20 LGI */ + 14, 0x41, 4, 15, 30, 13, 0, 23, 15, 1,/* VHT 1x1 MCS4 BW20 LGI */ + 15, 0x41, 5, 10, 25, 14, 0, 24, 16, 1,/* VHT 1x1 MCS5 BW20 LGI */ + 16, 0x41, 6, 8, 15, 15, 0, 24, 17, 1,/* VHT 1x1 MCS6 BW20 LGI */ + 17, 0x41, 7, 8, 15, 16, 0, 24, 18, 1,/* VHT 1x1 MCS7 BW20 LGI */ + 18, 0x41, 8, 8, 15, 17, 0, 25, 25, 1,/* VHT 1x1 MCS8 BW20 LGI */ + 19, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + + /* The Group Data Rate of 2SS with VHT BW 80 */ + 20, 0x40, 0, 30, 50, 10, 0, 21, 12, 2,/* VHT 2x2 MCS0 BW20 LGI */ + 21, 0x40, 1, 30, 50, 20, 0, 22, 14, 2,/* VHT 2x2 MCS1 BW20 LGI */ + 22, 0x40, 2, 15, 30, 21, 0, 23, 15, 2,/* VHT 2x2 MCS2 BW20 LGI */ + 23, 0x40, 3, 15, 30, 22, 0, 24, 16, 2,/* VHT 2x2 MCS3 BW20 LGI */ + 24, 0x40, 4, 15, 30, 23, 0, 25, 25, 2,/* VHT 2x2 MCS4 BW20 LGI */ + 25, 0x40, 5, 8, 20, 24, 0, 26, 26, 2,/* VHT 2x2 MCS5 BW20 LGI */ + 26, 0x40, 6, 8, 20, 25, 0, 27, 27, 2,/* VHT 2x2 MCS6 BW20 LGI */ + 27, 0x40, 7, 8, 20, 26, 0, 28, 29, 2,/* VHT 2x2 MCS7 BW20 LGI */ + 28, 0x40, 8, 5, 15, 27, 0, 29, 29, 2,/* VHT 2x2 MCS8 BW20 LGI */ + 29, 0x42, 8, 5, 15, 28, 0, 29, 29, 2,/* VHT 2x2 MCS8 BW20 SGI */ +}; + + +UCHAR RateTableVht1S_2G_BW40[] = +{ + 21, 20, 0, 0, 0, 0, 0, 0, 0, 0, + /* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* The Data Rate of CCK for long distance */ + 0, 0x00, 0, 40, 101, 0, 0, 1, 1, 1,/* CCK 1x1 MCS0 BW20 */ + 1, 0x00, 1, 40, 50, 0, 0, 2, 2, 1,/* CCK 1x1 MCS1 BW20 */ + 2, 0x00, 2, 25, 45, 1, 0, 4, 4, 1,/* CCK 1x1 MCS2 BW20 */ + + /* The Data Rate of OFDM for long distance */ + 3, 0x11, 0, 20, 50, 2, 0, 4, 4, 1,/* OFDM 1x1 MCS0 BW20 */ + 4, 0x11, 1, 20, 40, 3, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 4, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 5, 0, 11, 11, 1,/* OFDM 1x1 MCS3 BW20 */ + + /* The Data Rate of VHT BW 20/40 */ + 7, 0x41, 0, 15, 25, 3, 0, 10, 10, 1,/* VHT 1x1 MCS0 BW20 LGI*/ + 8, 0x00, 0, 0, 0, 0, 0, 0, 0, 1, + 9, 0x00, 0, 0, 0, 0, 0, 0, 0, 1, + + /* The Group Data Rate of 1SS with VHT BW40 */ + 10, 0x45, 0, 25, 50, 7, 0, 20, 11, 1,/* VHT 1x1 MCS0 BW40 LGI */ + 11, 0x45, 1, 20, 35, 10, 0, 12, 12, 1,/* VHT 1x1 MCS1 BW40 LGI */ + 12, 0x45, 2, 20, 35, 11, 0, 13, 13, 1,/* VHT 1x1 MCS2 BW40 LGI */ + 13, 0x45, 3, 15, 30, 12, 0, 14, 14, 1,/* VHT 1x1 MCS3 BW40 LGI */ + 14, 0x45, 4, 15, 30, 13, 0, 15, 15, 1,/* VHT 1x1 MCS4 BW40 LGI */ + 15, 0x45, 5, 10, 25, 14, 0, 16, 16, 1,/* VHT 1x1 MCS5 BW40 LGI */ + 16, 0x45, 6, 8, 15, 15, 0, 17, 17, 1,/* VHT 1x1 MCS6 BW40 LGI */ + 17, 0x45, 7, 8, 15, 16, 0, 18, 18, 1,/* VHT 1x1 MCS7 BW40 LGI */ + 18, 0x45, 8, 8, 15, 17, 0, 19, 19, 1,/* VHT 1x1 MCS8 BW40 LGI */ + 19, 0x45, 9, 8, 15, 18, 0, 20, 20, 1,/* VHT 1x1 MCS9 BW40 LGI */ + 20, 0x47, 9, 8, 15, 19, 0, 20, 20, 1,/* VHT 1x1 MCS9 BW40 SGI */ +}; + +UCHAR RateTableVht1S_2G_BW20[] = +{ + 20, 19, 0, 0, 0, 0, 0, 0, 0, 0, + /* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* reserved */ + /* The Data Rate of CCK for long distance */ + 0, 0x00, 0, 40, 101, 0, 0, 1, 1, 1,/* CCK 1x1 MCS0 BW20 */ + 1, 0x00, 1, 40, 50, 0, 0, 2, 2, 1,/* CCK 1x1 MCS1 BW20 */ + 2, 0x00, 2, 25, 45, 1, 0, 4, 4, 1,/* CCK 1x1 MCS2 BW20 */ + + /* The Data Rate of OFDM for long distance */ + 3, 0x11, 0, 20, 50, 2, 0, 4, 4, 1,/* OFDM 1x1 MCS0 BW20 */ + 4, 0x11, 1, 20, 40, 3, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 4, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 5, 0, 13, 13, 1,/* OFDM 1x1 MCS3 BW20 */ + + /* The Data Rate of VHT BW 20/40 */ + 7, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + + /* The Group Data Rate of 1SS with VHT BW20 */ + 10, 0x41, 0, 15, 25, 3, 0, 11, 11, 1,/* VHT 1x1 MCS0 BW20 LGI */ + 11, 0x41, 1, 20, 35, 10, 0, 12, 12, 1,/* VHT 1x1 MCS1 BW20 LGI */ + 12, 0x41, 2, 20, 35, 11, 0, 13, 13, 1,/* VHT 1x1 MCS2 BW20 LGI */ + 13, 0x41, 3, 15, 30, 12, 0, 14, 14, 1,/* VHT 1x1 MCS3 BW20 LGI */ + 14, 0x41, 4, 15, 30, 13, 0, 15, 15, 1,/* VHT 1x1 MCS4 BW20 LGI */ + 15, 0x41, 5, 10, 25, 14, 0, 16, 16, 1,/* VHT 1x1 MCS5 BW20 LGI */ + 16, 0x41, 6, 8, 15, 15, 0, 17, 17, 1,/* VHT 1x1 MCS6 BW20 LGI */ + 17, 0x41, 7, 8, 15, 16, 0, 18, 18, 1,/* VHT 1x1 MCS7 BW20 LGI */ + 18, 0x41, 8, 8, 15, 17, 0, 19, 19, 1,/* VHT 1x1 MCS8 BW20 LGI */ + 19, 0x43, 8, 8, 15, 18, 0, 19, 19, 1,/* VHT 1x1 MCS8 BW20 SGI */ +}; + +UCHAR RateTableVht2S_2G_BW40[] = +{ + 31, 30, 0, 0, 0, 0, 0, 0, 0, 0, + /* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* The Data Rate of CCK for long distance */ + 0, 0x00, 0, 40, 101, 0, 0, 1, 1, 1,/* CCK 1x1 MCS0 BW20 */ + 1, 0x00, 1, 40, 50, 0, 0, 2, 2, 1,/* CCK 1x1 MCS1 BW20 */ + 2, 0x00, 2, 25, 45, 1, 0, 4, 4, 1,/* CCK 1x1 MCS2 BW20 */ + + /* The Data Rate of OFDM for long distance */ + 3, 0x11, 0, 20, 50, 2, 0, 4, 4, 1,/* OFDM 1x1 MCS0 BW20 */ + 4, 0x11, 1, 20, 40, 3, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 4, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 5, 0, 11, 11, 1,/* OFDM 1x1 MCS3 BW20 */ + + /* The Data Rate of VHT BW 20/40 */ + 7, 0x41, 0, 15, 25, 3, 0, 10, 10, 1,/* VHT 1x1 MCS0 BW20 LGI*/ + 8, 0x00, 0, 0, 0, 0, 0, 0, 0, 1, + 9, 0x00, 0, 0, 0, 0, 0, 0, 0, 1, + + /* The Group Data Rate of 1SS with VHT BW40 */ + 10, 0x45, 0, 25, 50, 7, 0, 20, 11, 1,/* VHT 1x1 MCS0 BW40 LGI */ + 11, 0x45, 1, 20, 35, 10, 0, 21, 12, 1,/* VHT 1x1 MCS1 BW40 LGI */ + 12, 0x45, 2, 20, 35, 11, 0, 21, 13, 1,/* VHT 1x1 MCS2 BW40 LGI */ + 13, 0x45, 3, 15, 30, 12, 0, 22, 14, 1,/* VHT 1x1 MCS3 BW40 LGI */ + 14, 0x45, 4, 15, 30, 13, 0, 23, 15, 1,/* VHT 1x1 MCS4 BW40 LGI */ + 15, 0x45, 5, 10, 25, 14, 0, 24, 16, 1,/* VHT 1x1 MCS5 BW40 LGI */ + 16, 0x45, 6, 8, 15, 15, 0, 24, 17, 1,/* VHT 1x1 MCS6 BW40 LGI */ + 17, 0x45, 7, 8, 15, 16, 0, 24, 18, 1,/* VHT 1x1 MCS7 BW40 LGI */ + 18, 0x45, 8, 8, 15, 17, 0, 25, 19, 1,/* VHT 1x1 MCS8 BW40 LGI */ + 19, 0x45, 9, 8, 15, 18, 0, 25, 25, 1,/* VHT 1x1 MCS9 BW40 LGI */ + + /* The Group Data Rate of 2SS with VHT BW40 */ + 20, 0x44, 0, 30, 50, 10, 0, 21, 12, 2,/* VHT 2x2 MCS0 BW40 LGI */ + 21, 0x44, 1, 30, 50, 20, 0, 22, 14, 2,/* VHT 2x2 MCS1 BW40 LGI */ + 22, 0x44, 2, 15, 30, 21, 0, 23, 15, 2,/* VHT 2x2 MCS2 BW40 LGI */ + 23, 0x44, 3, 15, 30, 22, 0, 24, 16, 2,/* VHT 2x2 MCS3 BW40 LGI */ + 24, 0x44, 4, 15, 30, 23, 0, 25, 19, 2,/* VHT 2x2 MCS4 BW40 LGI */ + 25, 0x44, 5, 8, 20, 24, 0, 26, 26, 2,/* VHT 2x2 MCS5 BW40 LGI */ + 26, 0x44, 6, 8, 20, 25, 0, 27, 27, 2,/* VHT 2x2 MCS6 BW40 LGI */ + 27, 0x44, 7, 8, 20, 26, 0, 28, 28, 2,/* VHT 2x2 MCS7 BW40 LGI */ + 28, 0x44, 8, 5, 15, 27, 0, 29, 29, 2,/* VHT 2x2 MCS8 BW40 LGI */ + 29, 0x44, 9, 5, 15, 28, 0, 30, 30, 2,/* VHT 2x2 MCS9 BW40 LGI */ + 30, 0x46, 9, 5, 15, 29, 0, 30, 30, 2,/* VHT 2x2 MCS9 BW40 SGI */ +}; + +UCHAR RateTableVht2S_2G_BW20[] = +{ + 30, 29, 0, 0, 0, 0, 0, 0, 0, 0, + /* [Idx] [Mode] [MCS] [PER_down/up] [dMCS] [upMCS3/2/1] [nSS] */ + /* reserved */ + /* The Data Rate of CCK for long distance */ + 0, 0x00, 0, 40, 101, 0, 0, 1, 1, 1,/* CCK 1x1 MCS0 BW20 */ + 1, 0x00, 1, 40, 50, 0, 0, 2, 2, 1,/* CCK 1x1 MCS1 BW20 */ + 2, 0x00, 2, 25, 45, 1, 0, 4, 4, 1,/* CCK 1x1 MCS2 BW20 */ + + /* The Data Rate of OFDM for long distance */ + 3, 0x11, 0, 20, 50, 2, 0, 4, 4, 1,/* OFDM 1x1 MCS0 BW20 */ + 4, 0x11, 1, 20, 40, 3, 0, 5, 5, 1,/* OFDM 1x1 MCS1 BW20 */ + 5, 0x11, 2, 20, 35, 4, 0, 6, 6, 1,/* OFDM 1x1 MCS2 BW20 */ + 6, 0x11, 3, 15, 35, 5, 0, 13, 13, 1,/* OFDM 1x1 MCS3 BW20 */ + + 7, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + + /* The Group Data Rate of 1SS with VHT BW20 */ + 10, 0x41, 0, 15, 25, 3, 0, 20, 11, 1,/* VHT 1x1 MCS0 BW20 LGI */ + 11, 0x41, 1, 20, 35, 10, 0, 21, 12, 1,/* VHT 1x1 MCS1 BW20 LGI */ + 12, 0x41, 2, 20, 35, 11, 0, 21, 13, 1,/* VHT 1x1 MCS2 BW20 LGI */ + 13, 0x41, 3, 15, 30, 12, 0, 22, 14, 1,/* VHT 1x1 MCS3 BW20 LGI */ + 14, 0x41, 4, 15, 30, 13, 0, 23, 15, 1,/* VHT 1x1 MCS4 BW20 LGI */ + 15, 0x41, 5, 10, 25, 14, 0, 24, 16, 1,/* VHT 1x1 MCS5 BW20 LGI */ + 16, 0x41, 6, 8, 15, 15, 0, 24, 17, 1,/* VHT 1x1 MCS6 BW20 LGI */ + 17, 0x41, 7, 8, 15, 16, 0, 24, 18, 1,/* VHT 1x1 MCS7 BW20 LGI */ + 18, 0x41, 8, 8, 15, 17, 0, 25, 25, 1,/* VHT 1x1 MCS8 BW20 LGI */ + 19, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, + + /* The Group Data Rate of 2SS with VHT BW20 */ + 20, 0x40, 0, 30, 50, 10, 0, 21, 12, 2,/* VHT 2x2 MCS0 BW20 LGI */ + 21, 0x40, 1, 30, 50, 20, 0, 22, 14, 2,/* VHT 2x2 MCS1 BW20 LGI */ + 22, 0x40, 2, 15, 30, 21, 0, 23, 15, 2,/* VHT 2x2 MCS2 BW20 LGI */ + 23, 0x40, 3, 15, 30, 22, 0, 24, 16, 2,/* VHT 2x2 MCS3 BW20 LGI */ + 24, 0x40, 4, 15, 30, 23, 0, 25, 25, 2,/* VHT 2x2 MCS4 BW20 LGI */ + 25, 0x40, 5, 8, 20, 24, 0, 26, 26, 2,/* VHT 2x2 MCS5 BW20 LGI */ + 26, 0x40, 6, 8, 20, 25, 0, 27, 27, 2,/* VHT 2x2 MCS6 BW20 LGI */ + 27, 0x40, 7, 8, 20, 26, 0, 28, 29, 2,/* VHT 2x2 MCS7 BW20 LGI */ + 28, 0x40, 8, 5, 15, 27, 0, 29, 29, 2,/* VHT 2x2 MCS8 BW20 LGI */ + 29, 0x42, 8, 5, 15, 28, 0, 29, 29, 2,/* VHT 2x2 MCS8 BW20 SGI */ +}; + +#endif /* DOT11_VHT_AC */ + +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#endif /* DOT11_N_SUPPORT */ + + +/* MlmeGetSupportedMcs - fills in the table of mcs with index into the pTable + pAd - pointer to adapter + pTable - pointer to the Rate Table. Assumed to be a table without mcsGroup values + mcs - table of MCS index into the Rate Table. -1 => not supported +*/ +VOID MlmeGetSupportedMcs( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pTable, + OUT CHAR mcs[]) +{ + CHAR idx; + RTMP_RA_LEGACY_TB *pCurrTxRate; + + for (idx = 0; idx < 24; idx++) + mcs[idx] = -1; + + /* check the existence and index of each needed MCS */ + for (idx=0; idxCurrMCS==MCS_0 && (mcs[0]==-1 || pCurrTxRate->Mode!=MODE_CCK)) + mcs[0] = idx; + else if (pCurrTxRate->CurrMCS==MCS_1 && (mcs[1]==-1 || pCurrTxRate->Mode!=MODE_CCK)) + mcs[1] = idx; + else if (pCurrTxRate->CurrMCS==MCS_2 && (mcs[2]==-1 || pCurrTxRate->Mode!=MODE_CCK)) + mcs[2] = idx; + else if (pCurrTxRate->CurrMCS == MCS_3) + mcs[3] = idx; + else if (pCurrTxRate->CurrMCS == MCS_4) + mcs[4] = idx; + else if (pCurrTxRate->CurrMCS == MCS_5) + mcs[5] = idx; + else if (pCurrTxRate->CurrMCS == MCS_6) + mcs[6] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) + mcs[7] = idx; +#ifdef DOT11_N_SUPPORT + else if (pCurrTxRate->CurrMCS == MCS_12) + mcs[12] = idx; + else if (pCurrTxRate->CurrMCS == MCS_13) + mcs[13] = idx; + else if (pCurrTxRate->CurrMCS == MCS_14) + mcs[14] = idx; + else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) + { + mcs[15] = idx; + } +#ifdef DOT11N_SS3_SUPPORT + else if (pCurrTxRate->CurrMCS == MCS_20) + mcs[20] = idx; + else if (pCurrTxRate->CurrMCS == MCS_21) + mcs[21] = idx; + else if (pCurrTxRate->CurrMCS == MCS_22) + mcs[22] = idx; + else if (pCurrTxRate->CurrMCS == MCS_23) + mcs[23] = idx; +#endif /* DOT11N_SS3_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + } + +#ifdef DBG_CTRL_SUPPORT + /* Debug Option: Disable highest MCSs when picking initial MCS based on RSSI */ + if (pAd->CommonCfg.DebugFlags & DBF_INIT_MCS_DIS1) + mcs[23] = mcs[15] = mcs[7] = mcs[22] = mcs[14] = mcs[6] = 0; +#endif /* DBG_CTRL_SUPPORT */ +} + + +/* MlmeClearTxQuality - Clear TxQuality history only for the active BF state */ +VOID MlmeClearTxQuality(MAC_TABLE_ENTRY *pEntry) +{ +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + if (pEntry->phyETxBf || pEntry->phyITxBf) + NdisZeroMemory(pEntry->BfTxQuality, sizeof(pEntry->BfTxQuality)); + else +#endif /* TXBF_AWARD */ +#endif /* TXBF_SUPPORT */ + NdisZeroMemory(pEntry->TxQuality, sizeof(pEntry->TxQuality)); + + NdisZeroMemory(pEntry->PER, sizeof(pEntry->PER)); +} + + +/* MlmeClearAllTxQuality - Clear both BF and non-BF TxQuality history */ +VOID MlmeClearAllTxQuality(MAC_TABLE_ENTRY *pEntry) +{ +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + NdisZeroMemory(pEntry->BfTxQuality, sizeof(pEntry->BfTxQuality)); +#endif /* TXBF_AWARD */ +#endif + NdisZeroMemory(pEntry->TxQuality, sizeof(pEntry->TxQuality)); + + NdisZeroMemory(pEntry->PER, sizeof(pEntry->PER)); +} + + +/* MlmeDecTxQuality - Decrement TxQuality of specified rate table entry */ +VOID MlmeDecTxQuality(MAC_TABLE_ENTRY *pEntry, UCHAR rateIndex) +{ +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + if (pEntry->phyETxBf || pEntry->phyITxBf) { + if (pEntry->BfTxQuality[rateIndex]) + pEntry->BfTxQuality[rateIndex]--; + } + else +#endif /* TXBF_AWARD */ +#endif /* TXBF_SUPPORT */ + if (pEntry->TxQuality[rateIndex]) + pEntry->TxQuality[rateIndex]--; +} + + +VOID MlmeSetTxQuality(MAC_TABLE_ENTRY *pEntry, UCHAR rate_idx, USHORT quality) +{ +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + if (pEntry->phyETxBf || pEntry->phyITxBf) + pEntry->BfTxQuality[rate_idx] = quality; + else +#endif /* TXBF_AWARD */ +#endif /* TXBF_SUPPORT */ + pEntry->TxQuality[rate_idx] = quality; +} + + +USHORT MlmeGetTxQuality(MAC_TABLE_ENTRY *pEntry, UCHAR rateIndex) +{ +#ifdef TXBF_SUPPORT +#ifdef TXBF_AWARE + if (pEntry->phyETxBf || pEntry->phyITxBf) + return pEntry->BfTxQuality[rateIndex]; +#endif /* TXBF_AWARD */ +#endif /* TXBF_SUPPORT */ + return pEntry->TxQuality[rateIndex]; +} + + +#ifdef MCS_LUT_SUPPORT +VOID asic_mcs_lut_update(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ +#ifdef PEER_DELBA_TX_ADAPT + if (pEntry->bPeerDelBaTxAdaptEn) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Rate not update due to bPeerDelBaTxAdaptEn is 0x%x.\n", + __FUNCTION__, pEntry->bPeerDelBaTxAdaptEn)); + return; + } +#endif /* PEER_DELBA_TX_ADAPT */ + + if(RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) && (pEntry->wcid < 128)) + { + UINT32 wcid_offset; + HW_RATE_CTRL_STRUCT rate_ctrl; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + rate_ctrl.RATE_CTRL_N.PHYMODE = pEntry->HTPhyMode.field.MODE; + rate_ctrl.RATE_CTRL_N.STBC = pEntry->HTPhyMode.field.STBC; + rate_ctrl.RATE_CTRL_N.ShortGI = pEntry->HTPhyMode.field.ShortGI; + rate_ctrl.RATE_CTRL_N.BW = pEntry->HTPhyMode.field.BW; + + if (pAd->chipCap.phy_caps & fPHY_CAP_LDPC) + rate_ctrl.RATE_CTRL_N.ldpc = pEntry->HTPhyMode.field.ldpc; + + rate_ctrl.RATE_CTRL_N.MCS = pEntry->HTPhyMode.field.MCS; +#ifdef TXBF_SUPPORT + rate_ctrl.RATE_CTRL_N.eTxBF = pEntry->HTPhyMode.field.eTxBF; + rate_ctrl.RATE_CTRL_N.iTxBF = pEntry->HTPhyMode.field.iTxBF; + + DBGPRINT(RT_DEBUG_TRACE, ("pEntry->HTPhyMode.field.eTxBF = %d, pEntry->HTPhyMode.field.iTxBF = %d\n", + pEntry->HTPhyMode.field.eTxBF, pEntry->HTPhyMode.field.iTxBF)); + + if (pEntry->HTPhyMode.field.eTxBF || pEntry->HTPhyMode.field.iTxBF) + rate_ctrl.RATE_CTRL_N.STBC = FALSE; +#endif /* RLT_MAC */ + } + else +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + rate_ctrl.RATE_CTRL_O.PHYMODE = pEntry->HTPhyMode.field.MODE; + rate_ctrl.RATE_CTRL_O.STBC = pEntry->HTPhyMode.field.STBC; + rate_ctrl.RATE_CTRL_O.ShortGI = pEntry->HTPhyMode.field.ShortGI; + rate_ctrl.RATE_CTRL_O.BW = pEntry->HTPhyMode.field.BW; + rate_ctrl.RATE_CTRL_O.MCS = pEntry->HTPhyMode.field.MCS; +#ifdef TXBF_SUPPORT + rate_ctrl.RATE_CTRL_O.eTxBF = pEntry->HTPhyMode.field.eTxBF; + rate_ctrl.RATE_CTRL_O.iTxBF = pEntry->HTPhyMode.field.iTxBF; + + if (pEntry->HTPhyMode.field.eTxBF || pEntry->HTPhyMode.field.iTxBF) + rate_ctrl.RATE_CTRL_O.STBC = FALSE; +#endif /* TXBF_SUPPORT */ + } + else +#endif /* RTMP_MAC */ + { + DBGPRINT(RT_DEBUG_ERROR, ("\x1b[31m%s: HIF Type Error !!!\x1b[m\n", __FUNCTION__)); + return; + } + + wcid_offset = MAC_MCS_LUT_BASE + (pEntry->wcid * 8); + + RTMP_IO_WRITE32(pAd, wcid_offset, rate_ctrl.word); + RTMP_IO_WRITE32(pAd, wcid_offset + 4, 0x00); + + DBGPRINT(RT_DEBUG_INFO, ("%s():MCS_LUT update, write to MAC=0x%08x, Value=0x%04x, WCID=%d\n", + __FUNCTION__, wcid_offset, pEntry->HTPhyMode.word, pEntry->wcid)); + + DBGPRINT_RAW(RT_DEBUG_INFO, ("\tWcid=%d, APMlmeSetTxRate - CurrTxRateIdx=%d, MCS=%d, STBC=%d, ShortGI=%d, Mode=%d, BW=%d \n" + "\t ETxBf=%d, ITxBf=%d\n\n", + pEntry->wcid, + pEntry->CurrTxRateIndex, + pEntry->HTPhyMode.field.MCS, + pEntry->HTPhyMode.field.STBC, + pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.MODE, + pEntry->HTPhyMode.field.BW, + pEntry->HTPhyMode.field.eTxBF, + pEntry->HTPhyMode.field.iTxBF)); + } +} +#endif /* MCS_LUT_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeSetTxRate( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_LEGACY_TB *pTxRate) +{ + UCHAR tx_mode = pTxRate->Mode; + UCHAR tx_bw = pTxRate->BW; + +#ifdef DOT11_VHT_AC + if ((pAd->chipCap.phy_caps & fPHY_CAP_VHT) && + ((pEntry->pTable == RateTableVht2S) || (pEntry->pTable == RateTableVht1S) || + (pEntry->pTable == RateTableVht1S_MCS9) || + (pEntry->pTable == RateTableVht2S_BW20) || + (pEntry->pTable == RateTableVht2S_BW40) || + (pEntry->pTable == RateTableVht2S_MCS7) || + (pEntry->pTable == RateTableVht1S_2G_BW20) || + (pEntry->pTable == RateTableVht1S_2G_BW40) || + (pEntry->pTable == RateTableVht2S_2G_BW20) || + (pEntry->pTable == RateTableVht2S_2G_BW40))) + { + RTMP_RA_GRP_TB *pAdaptTbEntry = (RTMP_RA_GRP_TB *)pTxRate; + UCHAR bw_cap = BW_20; + + if (pEntry->MaxHTPhyMode.field.BW != pAdaptTbEntry->BW) + { + switch (pEntry->MaxHTPhyMode.field.BW) + { + case BW_80: + bw_cap = pAdaptTbEntry->BW; + break; + case BW_40: + if (pAdaptTbEntry->BW == BW_80) + bw_cap = BW_40; + else + bw_cap = pAdaptTbEntry->BW; + break; + case BW_20: + default: + if (pAdaptTbEntry->BW == BW_80 || pAdaptTbEntry->BW == BW_40) + bw_cap = BW_20; + else + bw_cap = pAdaptTbEntry->BW; + break; + } + tx_bw = bw_cap; + } + else + tx_bw = pAdaptTbEntry->BW; + + if ((pEntry->force_op_mode == TRUE)) + { + switch (pEntry->operating_mode.ch_width) { + case 1: + bw_cap = BW_40; + break; + case 2: + bw_cap = BW_80; + break; + case 0: + default: + bw_cap = BW_20; + break; + } + if ((tx_bw != BW_10) && (tx_bw >= bw_cap)) + tx_bw = bw_cap; + } + +#ifdef RT8592 + if (IS_RT8592(pAd)) + tx_mode = ((tx_bw == BW_40) ? MODE_HTMIX : pAdaptTbEntry->Mode); +#endif + +#ifdef WFA_VHT_PF + if (pAd->CommonCfg.vht_bw_signal && tx_bw == BW_40 && + pAdaptTbEntry->Mode == MODE_VHT && + (pAd->MacTab.fAnyStation20Only == FALSE)) + { + // try to use BW_40 for VHT mode! + tx_mode = pAdaptTbEntry->Mode; + } +#endif /* WFA_VHT_PF */ +DBGPRINT(RT_DEBUG_INFO, ("%s(): txbw=%d, txmode=%d\n", __FUNCTION__, tx_bw, tx_mode)); + } +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT + if (tx_mode == MODE_HTMIX || tx_mode == MODE_HTGREENFIELD) + { + if ((pTxRate->STBC) && (pEntry->MaxHTPhyMode.field.STBC)) + pEntry->HTPhyMode.field.STBC = STBC_USE; + else + pEntry->HTPhyMode.field.STBC = STBC_NONE; + + if ((pTxRate->ShortGI || pAd->WIFItestbed.bShortGI) && (pEntry->MaxHTPhyMode.field.ShortGI)) + pEntry->HTPhyMode.field.ShortGI = GI_400; + else + pEntry->HTPhyMode.field.ShortGI = GI_800; + } + + /* TODO: will check ldpc if related to rate table */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE) || + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE)) { + pEntry->HTPhyMode.field.ldpc = TRUE; + } else { + pEntry->HTPhyMode.field.ldpc = FALSE; + } + +#ifdef DOT11_VHT_AC + if (tx_mode == MODE_VHT) + { + if (((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE)) || + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_2G_256QAM_CAPABLE)) && + (pTxRate->ShortGI +#ifdef WFA_VHT_PF + || pAd->vht_force_sgi +#endif /* WFA_VHT_PF */ + ) + ) + pEntry->HTPhyMode.field.ShortGI = GI_400; + else + pEntry->HTPhyMode.field.ShortGI = GI_800; + + if (pTxRate->STBC && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE))) + pEntry->HTPhyMode.field.STBC = STBC_USE; + else + pEntry->HTPhyMode.field.STBC = STBC_NONE; + } +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + /* fix drop to CCK in 5GHz */ + if (tx_mode == MODE_CCK && pAd->LatchRfRegs.Channel > 14) + { + tx_mode = MODE_OFDM; + } + + if (pTxRate->CurrMCS < MCS_AUTO) + pEntry->HTPhyMode.field.MCS = pTxRate->CurrMCS; + + pEntry->HTPhyMode.field.MODE = tx_mode; + +#ifdef DOT11_N_SUPPORT + if ((pAd->WIFItestbed.bGreenField & pEntry->HTCapability.HtCapInfo.GF) && (pEntry->HTPhyMode.field.MODE == MODE_HTMIX)) + { + /* force Tx GreenField */ + pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + + /* BW depends on BSSWidthTrigger and Negotiated BW */ + if (pAd->CommonCfg.bRcvBSSWidthTriggerEvents || + (pEntry->MaxHTPhyMode.field.BW==BW_20) || + (pAd->CommonCfg.BBPCurrentBW==BW_20)) + pEntry->HTPhyMode.field.BW = BW_20; + else + pEntry->HTPhyMode.field.BW = BW_40; + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW==BW_80 && + pEntry->MaxHTPhyMode.field.BW == BW_80 && + pEntry->MaxHTPhyMode.field.MODE == MODE_VHT) + pEntry->HTPhyMode.field.BW = BW_80; + +#ifdef NEW_RATE_ADAPT_SUPPORT + if ((pEntry->pTable == RateTableVht2S) || + (pEntry->pTable == RateTableVht2S_BW20) || + (pEntry->pTable == RateTableVht2S_BW40) || + (pEntry->pTable == RateTableVht1S) || + (pEntry->pTable == RateTableVht1S_MCS9) || + (pEntry->pTable == RateTableVht2S_MCS7) || + (pEntry->pTable == RateTableVht1S_2G_BW20) || + (pEntry->pTable == RateTableVht1S_2G_BW40) || + (pEntry->pTable == RateTableVht2S_2G_BW20) || + (pEntry->pTable == RateTableVht2S_2G_BW40)) + { + RTMP_RA_GRP_TB *pAdaptTbEntry = (RTMP_RA_GRP_TB *)pTxRate; + pEntry->HTPhyMode.field.MCS = pAdaptTbEntry->CurrMCS | ((pAdaptTbEntry->dataRate -1) <<4); + pEntry->HTPhyMode.field.BW = tx_bw; + +#ifdef WFA_VHT_PF + if ((pAd->vht_force_tx_stbc) + && (pEntry->HTPhyMode.field.MODE == MODE_VHT) + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE)) + && (pEntry->HTPhyMode.field.STBC == STBC_NONE) + ) + { + pEntry->HTPhyMode.field.MCS = pAdaptTbEntry->CurrMCS; + pEntry->HTPhyMode.field.STBC = STBC_USE; + } +#endif /* WFA_VHT_PF */ + } +#ifdef DOT11_VHT_AC + else if (IS_VHT_STA(pEntry)) + { + UCHAR bw_max = pEntry->MaxHTPhyMode.field.BW; + if (pEntry->force_op_mode == TRUE) + { + switch (pEntry->operating_mode.ch_width) { + case 1: + bw_max = BW_40; + break; + case 2: /* not support for BW_80 for other rate table */ + case 0: + default: + bw_max = BW_20; + break; + } + } + + if ( (bw_max != BW_10) && + (bw_max > pAd->CommonCfg.BBPCurrentBW)) + { + bw_max = pAd->CommonCfg.BBPCurrentBW; + } + pEntry->HTPhyMode.field.BW = bw_max; + } +#endif /* DOT11_VHT_AC */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + if (pEntry->pTable == Ags2x2VhtRateTable) + { + RTMP_RA_AGS_TB *pAgsTbEntry = (RTMP_RA_AGS_TB *)pTxRate; + pEntry->HTPhyMode.field.MCS = pAgsTbEntry->CurrMCS | (pAgsTbEntry->Nss <<4); + } +#endif /* AGS_SUPPORT */ +#endif /* DOT11_VHT_AC */ + +#ifdef RANGE_EXTEND +#ifdef NEW_RATE_ADAPT_SUPPORT + /* 20 MHz Fallback */ + if ((tx_mode == MODE_HTMIX || tx_mode == MODE_HTGREENFIELD) && + pEntry->HTPhyMode.field.BW == BW_40 && + ADAPT_RATE_TABLE(pEntry->pTable)) + { + if (pEntry->HTPhyMode.field.MCS == 32 +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS0) == 0 +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Map HT Duplicate to 20MHz MCS0 */ + pEntry->HTPhyMode.field.BW = BW_20; + pEntry->HTPhyMode.field.MCS = 0; + } + else if (pEntry->HTPhyMode.field.MCS == 0 && + (pAd->CommonCfg.DebugFlags & DBF_FORCE_20MHZ) == 0 +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS1) == 0 +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Map 40MHz MCS0 to 20MHz MCS1 */ + pEntry->HTPhyMode.field.BW = BW_20; + pEntry->HTPhyMode.field.MCS = 1; + } + else if (pEntry->HTPhyMode.field.MCS == 8 +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_ENABLE_20MHZ_MCS8) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Map 40MHz MCS8 to 20MHz MCS8 */ + pEntry->HTPhyMode.field.BW = BW_20; + } + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + /* Debug Option: Force BW */ + if (pAd->CommonCfg.DebugFlags & DBF_FORCE_40MHZ) + { + pEntry->HTPhyMode.field.BW = BW_40; + } + else if (pAd->CommonCfg.DebugFlags & DBF_FORCE_20MHZ) + { + pEntry->HTPhyMode.field.BW = BW_20; + } +#endif /* DBG_CTRL_SUPPORT */ +#endif /* RANGE_EXTEND */ + + /* Reexam each bandwidth's SGI support. */ + if ((pEntry->HTPhyMode.field.BW==BW_20 && !CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)) || + (pEntry->HTPhyMode.field.BW==BW_40 && !CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)) ) + pEntry->HTPhyMode.field.ShortGI = GI_800; + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Force Short GI */ + if (pAd->CommonCfg.DebugFlags & DBF_FORCE_SGI) + pEntry->HTPhyMode.field.ShortGI = GI_400; +#endif /* DBG_CTRL_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); + +#ifdef FIFO_EXT_SUPPORT + AsicFifoExtEntryClean(pAd, pEntry); +#endif /* FIFO_EXT_SUPPORT */ + +#ifdef MCS_LUT_SUPPORT + asic_mcs_lut_update(pAd, pEntry); + pEntry->LastTxRate = (USHORT) (pEntry->HTPhyMode.word); +#endif /* MCS_LUT_SUPPORT */ + + +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +VOID MlmeSetTxRate( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_LEGACY_TB *pTxRate) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + UCHAR MaxMode = MODE_OFDM; + UCHAR tx_mode = pTxRate->Mode; + UCHAR tx_bw = pTxRate->BW; + HTTRANSMIT_SETTING *tx_setting = &pAd->StaCfg.wdev.HTPhyMode; + +#ifdef DOT11_N_SUPPORT + MaxMode = MODE_HTGREENFIELD; + +#ifdef DOT11_VHT_AC + MaxMode = MODE_VHT; +#endif /* DOT11_VHT_AC */ + +#ifdef RT8592 + if (IS_RT8592(pAd) && (tx_mode == MODE_VHT) && (tx_bw == BW_40)) + tx_mode = MODE_HTMIX; +#endif /* RT8592 */ + + if (pTxRate->STBC && + (((pAd->StaCfg.wdev.MaxHTPhyMode.field.STBC) && (tx_mode == MODE_HTMIX || tx_mode == MODE_HTGREENFIELD)) +#ifdef DOT11_VHT_AC + ||((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE)) && (tx_mode == MODE_VHT)) +#endif /* DOT11_VHT_AC */ + ) + /* Fix Miracast Connection failed issue with S4 phone if STBC was enabled */ + && pEntry->MaxHTPhyMode.field.STBC + ) + wdev->HTPhyMode.field.STBC = STBC_USE; + else +#endif /* DOT11_N_SUPPORT */ + wdev->HTPhyMode.field.STBC = STBC_NONE; + + if (pTxRate->CurrMCS < MCS_AUTO) + wdev->HTPhyMode.field.MCS = pTxRate->CurrMCS; + + /* TODO: will check ldpc if related to rate table */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE) || + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE)) { + wdev->HTPhyMode.field.ldpc = TRUE; + } else { + wdev->HTPhyMode.field.ldpc = FALSE; + } + +#ifdef DOT11_VHT_AC +#ifdef NEW_RATE_ADAPT_SUPPORT + if ((pEntry->pTable == RateTableVht2S) || (pEntry->pTable == RateTableVht2S_BW20) || + (pEntry->pTable == RateTableVht2S_BW40) || + (pEntry->pTable == RateTableVht1S) || (pEntry->pTable == RateTableVht1S_MCS9) + || (pEntry->pTable == RateTableVht2S_MCS7) + || (pEntry->pTable == RateTableVht1S_2G_BW20) || (pEntry->pTable == RateTableVht1S_2G_BW40) + || (pEntry->pTable == RateTableVht2S_2G_BW20) || (pEntry->pTable == RateTableVht2S_2G_BW40)) + { + RTMP_RA_GRP_TB *pAdaptTbEntry = (RTMP_RA_GRP_TB *)pTxRate; + // TODO: shiang-usw, fix me for STA mode, original code use following code + pAd->StaCfg.wdev.HTPhyMode.field.MCS = pAdaptTbEntry->CurrMCS | ((pAdaptTbEntry->dataRate -1) <<4); + pAd->StaCfg.wdev.HTPhyMode.field.BW = pAdaptTbEntry->BW; + // TODO: shiang-usw, we should use this method! + wdev->HTPhyMode.field.MCS = pAdaptTbEntry->CurrMCS | ((pAdaptTbEntry->dataRate -1) <<4); + wdev->HTPhyMode.field.BW = pAdaptTbEntry->BW; + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + if (pEntry->pTable == Ags2x2VhtRateTable) + { + RTMP_RA_AGS_TB *pAgsTbEntry = (RTMP_RA_AGS_TB *)pTxRate; + pEntry->HTPhyMode.field.MCS = pAgsTbEntry->CurrMCS | (pAgsTbEntry->Nss <<4); + } +#endif /* AGS_SUPPORT */ +#endif /* DOT11_VHT_AC */ + + if (wdev->HTPhyMode.field.MCS > 7) + wdev->HTPhyMode.field.STBC = STBC_NONE; + + if (ADHOC_ON(pAd)) + { + /* If peer adhoc is b-only mode, we can't send 11g rate. */ + wdev->HTPhyMode.field.ShortGI = GI_800; + pEntry->HTPhyMode.field.STBC = STBC_NONE; + + /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */ + pEntry->HTPhyMode.field.MODE = tx_mode; + pEntry->HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + + /* Patch speed error in status page */ + wdev->HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; + } + else + { + USHORT OperationMode =0xffff; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.RegTransmitSetting.field.HTMODE == HTMODE_GF) && + (pAd->MlmeAux.HtCapability.HtCapInfo.GF == HTMODE_GF)) + wdev->HTPhyMode.field.MODE = MODE_HTGREENFIELD; + else +#endif /* DOT11_N_SUPPORT */ + if (tx_mode <= MaxMode) + wdev->HTPhyMode.field.MODE = tx_mode; + +#ifdef DOT11_N_SUPPORT + if (pTxRate->ShortGI && (wdev->MaxHTPhyMode.field.ShortGI)) + wdev->HTPhyMode.field.ShortGI = GI_400; + else +#endif /* DOT11_N_SUPPORT */ + wdev->HTPhyMode.field.ShortGI = GI_800; + +#ifdef DOT11_N_SUPPORT + /* BW depends on Negotiated BW */ + if(!IS_ENTRY_TDLS(pEntry)) + { + if (pEntry->MaxHTPhyMode.field.BW==BW_20 || pAd->CommonCfg.BBPCurrentBW==BW_20) + pEntry->HTPhyMode.field.BW = BW_20; + else + pEntry->HTPhyMode.field.BW = BW_40; + } +#ifdef DOT11_VHT_AC + if(!IS_ENTRY_TDLS(pEntry)) + { + if (pEntry->MaxHTPhyMode.field.BW==BW_80 || pAd->CommonCfg.BBPCurrentBW==BW_80) + pEntry->HTPhyMode.field.BW = BW_80; + } + if ((pEntry->force_op_mode == TRUE)) + { + UCHAR bw_cap = BW_20; + + switch (pEntry->operating_mode.ch_width) { + case 1: + bw_cap = BW_40; + break; + case 2: + bw_cap = BW_80; + break; + case 0: + default: + bw_cap = BW_20; + break; + } + if ((pEntry->HTPhyMode.field.BW != BW_10) && (pEntry->HTPhyMode.field.BW >= bw_cap)) + pEntry->HTPhyMode.field.BW = bw_cap; + } +#endif /* DOT11_VHT_AC */ + +#ifdef RANGE_EXTEND +#ifdef NEW_RATE_ADAPT_SUPPORT + /* 20 MHz Fallback */ + if (tx_mode >=MODE_HTMIX && pEntry->HTPhyMode.field.BW==BW_40 && + ADAPT_RATE_TABLE(pEntry->pTable) + ) + { + if ((wdev->HTPhyMode.field.MCS==32) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS0)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Map HT Duplicate to 20MHz MCS0 */ + pEntry->HTPhyMode.field.BW = BW_20; + wdev->HTPhyMode.field.MCS = 0; + if (pTxRate->STBC && wdev->MaxHTPhyMode.field.STBC) + wdev->HTPhyMode.field.STBC = STBC_USE; + } + else if (wdev->HTPhyMode.field.MCS==0 +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_20MHZ)==0 + && (pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS1)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Map 40MHz MCS0 to 20MHz MCS1 */ + pEntry->HTPhyMode.field.BW = BW_20; + wdev->HTPhyMode.field.MCS = 1; + } + else if (wdev->HTPhyMode.field.MCS==8 +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_ENABLE_20MHZ_MCS8) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + /* Map 40MHz MCS8 to 20MHz MCS8 */ + pEntry->HTPhyMode.field.BW = BW_20; + } + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + /* Debug Option: Force BW */ + if (pAd->CommonCfg.DebugFlags & DBF_FORCE_40MHZ) + pEntry->HTPhyMode.field.BW = BW_40; + else if (pAd->CommonCfg.DebugFlags & DBF_FORCE_20MHZ) + pEntry->HTPhyMode.field.BW = BW_20; +#endif /* DBG_CTRL_SUPPORT */ +#endif /* RANGE_EXTEND */ + + /* Reexam each bandwidth's SGI support. */ + if ((pEntry->HTPhyMode.field.BW==BW_20 && !CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)) || + (pEntry->HTPhyMode.field.BW==BW_40 && !CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)) ) + wdev->HTPhyMode.field.ShortGI = GI_800; + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Force Short GI */ + if (pAd->CommonCfg.DebugFlags & DBF_FORCE_SGI) + wdev->HTPhyMode.field.ShortGI = GI_400; +#endif /* DBG_CTRL_SUPPORT */ + + /* Turn RTS/CTS rate to 6Mbps. */ + if (((pEntry->HTPhyMode.field.MCS == 0) && (wdev->HTPhyMode.field.MCS != 0)) || + ((pEntry->HTPhyMode.field.MCS == 8) && (wdev->HTPhyMode.field.MCS != 8))) + { + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + OperationMode = HT_FORCERTSCTS; + else + OperationMode = pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; + } + else if ((pEntry->HTPhyMode.field.MCS != 0) && (wdev->HTPhyMode.field.MCS == 0)) + OperationMode = HT_RTSCTS_6M; + else if ((pEntry->HTPhyMode.field.MCS != 8) && (wdev->HTPhyMode.field.MCS == 8)) + OperationMode = HT_RTSCTS_6M; + + if (OperationMode != 0xffff) + AsicUpdateProtect(pAd, OperationMode , ALLN_SETPROTECT, TRUE, + (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.field.STBC = wdev->HTPhyMode.field.STBC; + pEntry->HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.ldpc = wdev->HTPhyMode.field.ldpc; + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pEntry->HTPhyMode.field.MODE = wdev->HTPhyMode.field.MODE; + } + +#ifdef MCS_LUT_SUPPORT + asic_mcs_lut_update(pAd, pEntry); +#endif /* MCS_LUT_SUPPORT */ + +} +#endif /* CONFIG_STA_SUPPORT */ + + +VOID MlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR **ppTable, + IN UCHAR *pTableSize, + IN UCHAR *pInitTxRateIdx) +{ + do + { +#ifdef DOT11_VHT_AC + INT mcs_idx, ss = 0, bw = pEntry->MaxHTPhyMode.field.BW; + + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pEntry->SupportRateMode & SUPPORT_VHT_MODE)) + { + for (mcs_idx = 0; mcs_idx < MAX_LEN_OF_VHT_RATES; mcs_idx++) + { + if (pEntry->SupportVHTMCS[mcs_idx]) + { + if (mcs_idx <= 9) + ss =1; + if (mcs_idx >= 10) + ss = 2; + } + } + +#ifdef THERMAL_PROTECT_SUPPORT + if (pAd->force_one_tx_stream == TRUE) + { + ss = 1; + } +#endif /* THERMAL_PROTECT_SUPPORT */ + +#ifdef WFA_VHT_PF + if ((pAd->CommonCfg.vht_nss_cap > 0) && + (ss > pAd->CommonCfg.vht_nss_cap)) + ss = pAd->CommonCfg.vht_nss_cap; +#endif /* WFA_VHT_PF */ + + if ((pEntry->force_op_mode == TRUE) && + (pEntry->operating_mode.rx_nss_type == 0)) + { + if (pEntry->operating_mode.rx_nss < pAd->CommonCfg.TxStream) + ss = pEntry->operating_mode.rx_nss + 1; + + switch (pEntry->operating_mode.ch_width) + { + case 0: + bw = BW_20; + break; + case 1: + bw = BW_40; + break; + case 2: + default: + bw = BW_80; + break; + } + } + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) { + if (ss == 2) { + if (pEntry->MaxHTPhyMode.field.BW == BW_20) { + *ppTable = RateTableVht2S_BW20; + } else if (pEntry->MaxHTPhyMode.field.BW == BW_40) { + *ppTable = RateTableVht2S_BW40; + } else if ((pEntry->SupportVHTMCS[MCS_8] == 1) && + (pEntry->SupportVHTMCS[MCS_9] == 1)) { + *ppTable = RateTableVht2S; + } else { + *ppTable = RateTableVht2S_MCS7; + } + } else if (ss == 1) { + if ((pEntry->SupportVHTMCS[MCS_8] == 1) && + (pEntry->SupportVHTMCS[MCS_9] == 1)) + *ppTable = RateTableVht1S_MCS9; + else + *ppTable = RateTableVht1S; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s(): Select RateTableVht%dS%s\n", + __FUNCTION__, (ss == 2 ? 2 : 1), + ((*ppTable == RateTableVht1S_MCS9) ? "_MCS9" : ""))); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:unknow ss(%d)\n", __FUNCTION__, ss)); + } + } +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + if (pAd->rateAlg == RATE_ALG_AGS) + { + if (ss == 2) + *ppTable = Ags2x2VhtRateTable; + else + *ppTable = Ags1x1VhtRateTable; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Select Ags%dx%dVhtRateTable\n", + __FUNCTION__, (ss == 2 ? 2 : 1), (ss == 2 ? 2 : 1))); + } +#endif /* AGS_SUPPORT */ + + if ((IS_RT8592(pAd) && ( bw != BW_40)) || + (!IS_RT8592(pAd))) + break; + +#ifdef WFA_VHT_PF + // TODO: shiang, add for Realtek behavior when run in BW signaling mode test and we are the testbed! + // TODO: add at 11/15! + if ((pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_DYNAMIC) && + (bw == BW_40) && + (pAd->MacTab.fAnyStation20Only == FALSE)) + break; +#endif /* WFA_VHT_PF */ + } + + if (IS_RT8592(pAd) && + WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pEntry->SupportRateMode & SUPPORT_VHT_MODE) && + bw == BW_40 && (pAd->LatchRfRegs.Channel > 14) + ) + { + if (ss == 1) { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N1S; + else +#endif + *ppTable = RateSwitchTable11N1SForABand; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Select RateSwitchTable%s11N1S%s\n", + __FUNCTION__, + ((pAd->rateAlg == RATE_ALG_GRP) ? "Adapt" : ""), + ((pAd->rateAlg == RATE_ALG_GRP) ? "ForABand" : ""))); + } + else if (ss == 2) + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) { + *ppTable = RateSwitchTableAdapt11N2S; + } else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + *ppTable = RateSwitchTable11BGN2SForABand; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Select RateSwitchTable%s11N2S%s\n", + __FUNCTION__, + ((pAd->rateAlg == RATE_ALG_GRP) ? "Adapt" : ""), + ((pAd->rateAlg == RATE_ALG_GRP) ? "ForABand" : ""))); + + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Invalid SS!\n", __FUNCTION__)); + } + + if (*ppTable) + break; + } +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) + { + /* for ADHOC mode */ +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) + {/* 11N 1S Adhoc*/ + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + *ppTable = AGS1x1HTRateTable; + else +#endif /* AGS_SUPPORT */ + { + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N1S; + else + *ppTable = RateSwitchTable11N1SForABand; + } + } + else if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && + (((pAd->Antenna.field.TxPath == 3) && (pEntry->HTCapability.MCSSet[2] == 0x00)) || (pAd->Antenna.field.TxPath == 2))) + {/* 11N 2S Adhoc*/ +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + { + *ppTable = AGS2x2HTRateTable; + } + else +#endif /* AGS_SUPPORT */ + { + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N2S; + else + *ppTable = RateSwitchTable11N2SForABand; + } + } +#ifdef AGS_SUPPORT + else if (SUPPORT_AGS(pAd) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && + (pEntry->HTCapability.MCSSet[2] != 0x00) && + (pAd->Antenna.field.TxPath == 3)) + { + *ppTable = AGS3x3HTRateTable; + } +#endif /* AGS_SUPPORT */ + else +#endif /* DOT11_N_SUPPORT */ + if ((pEntry->RateLen == 4) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif /* DOT11_N_SUPPORT */ + ) + *ppTable = RateSwitchTable11B; + else if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11BG; + else + *ppTable = RateSwitchTable11G; + break; + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&*/ + /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))*/ + if ((pEntry->SupportRateMode & (SUPPORT_OFDM_MODE)) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) + {/* 11BGN 1S AP*/ + +#ifdef DOT11_VHT_AC + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_2G_256QAM_CAPABLE) + && (pAd->LatchRfRegs.Channel <= 14)) + { + if (pEntry->MaxHTPhyMode.field.BW == BW_20) { + *ppTable = RateTableVht1S_2G_BW20; + } else if (pEntry->MaxHTPhyMode.field.BW == BW_40) { + *ppTable = RateTableVht1S_2G_BW40; + } + + break; + } +#endif /* DOT11_VHT_AC */ + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + *ppTable = AGS1x1HTRateTable; + else +#endif /* AGS_SUPPORT */ +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N1S; + else +#endif + if ((pAd->LatchRfRegs.Channel <= 14) && (pEntry->SupportRateMode & (SUPPORT_CCK_MODE))) + *ppTable = RateSwitchTable11BGN1S; + else + *ppTable = RateSwitchTable11N1SForABand; + + break; + } + +#ifdef AGS_SUPPORT + /* only for station */ + if (SUPPORT_AGS(pAd) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && + (pEntry->HTCapability.MCSSet[2] != 0x00) && + (pAd->CommonCfg.TxStream == 3)) + {/* 11N 3S */ + *ppTable = AGS3x3HTRateTable; + break; + } +#endif /* AGS_SUPPORT */ + + /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&*/ + /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))*/ + if ((pEntry->SupportRateMode & (SUPPORT_OFDM_MODE)) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && +#ifdef THERMAL_PROTECT_SUPPORT + (pAd->force_one_tx_stream == FALSE) && +#endif /* THERMAL_PROTECT_SUPPORT */ + (((pAd->Antenna.field.TxPath == 3) && (pEntry->HTCapability.MCSSet[2] == 0x00)) || (pAd->CommonCfg.TxStream == 2))) + {/* 11BGN 2S AP*/ +#ifdef DOT11_VHT_AC + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_2G_256QAM_CAPABLE) + && (pAd->LatchRfRegs.Channel <= 14)) + { + if (pEntry->MaxHTPhyMode.field.BW == BW_20) { + *ppTable = RateTableVht2S_2G_BW20; + } else if (pEntry->MaxHTPhyMode.field.BW == BW_40) { + *ppTable = RateTableVht2S_2G_BW40; + } + + break; + } +#endif /* DOT11_VHT_AC */ + +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + { + *ppTable = AGS2x2HTRateTable; + } + else +#endif /* AGS_SUPPORT */ +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) { + *ppTable = RateSwitchTableAdapt11N2S; + } else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if ((pAd->LatchRfRegs.Channel <= 14) && (pEntry->SupportRateMode & (SUPPORT_CCK_MODE))) + *ppTable = RateSwitchTable11BGN2S; + else + *ppTable = RateSwitchTable11BGN2SForABand; + + break; + } + +#ifdef DOT11N_SS3_SUPPORT + if ((pEntry->SupportRateMode & (SUPPORT_OFDM_MODE)) && + (pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && + (pEntry->HTCapability.MCSSet[2] != 0x00) && + (pAd->CommonCfg.TxStream == 3)) + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + { + *ppTable = RateSwitchTableAdapt11N3S; + } + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if ((pAd->LatchRfRegs.Channel <= 14) && (pEntry->SupportRateMode & (SUPPORT_CCK_MODE))) + *ppTable = RateSwitchTable11N3S; + else + *ppTable = RateSwitchTable11N3SForABand; + + break; + } +#endif /* DOT11N_SS3_SUPPORT */ + + /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))*/ + if ((pEntry->HTCapability.MCSSet[0] != 0x00) && + ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1) +#ifdef THERMAL_PROTECT_SUPPORT + || (pAd->force_one_tx_stream == TRUE) +#endif /* THERMAL_PROTECT_SUPPORT */ + )) + {/* 11N 1S AP*/ +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + *ppTable = AGS1x1HTRateTable; + else +#endif /* AGS_SUPPORT */ + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N1S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N1S; + else + *ppTable = RateSwitchTable11N1SForABand; + } + break; + } + + /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))*/ + if ((pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && + (pAd->CommonCfg.TxStream == 2) +#ifdef THERMAL_PROTECT_SUPPORT + && (pAd->force_one_tx_stream == FALSE) +#endif /* THERMAL_PROTECT_SUPPORT */ + ) + {/* 11N 2S AP*/ +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd)) + *ppTable = AGS2x2HTRateTable; + else +#endif /* AGS_SUPPORT */ + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) { + *ppTable = RateSwitchTableAdapt11N2S; + } else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N2S; + else + *ppTable = RateSwitchTable11N2SForABand; + } + break; + } + +#ifdef DOT11N_SS3_SUPPORT + if ((pEntry->HTCapability.MCSSet[0] != 0x00) && + (pEntry->HTCapability.MCSSet[1] != 0x00) && + (pEntry->HTCapability.MCSSet[2] != 0x00) && + (pAd->CommonCfg.TxStream == 3)) + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N3S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + { + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N3S; + else + *ppTable = RateSwitchTable11N3SForABand; + } + break; + } +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream == 3) + { + if (pEntry->HTCapability.MCSSet[0] != 0x00) + { + if (pEntry->HTCapability.MCSSet[1] == 0x00) + { /* Only support 1SS */ + if (pEntry->RateLen > 0) + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N1S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if ((pAd->LatchRfRegs.Channel <= 14) && (pEntry->SupportRateMode & (SUPPORT_CCK_MODE))) + *ppTable = RateSwitchTable11N1S; + else + *ppTable = RateSwitchTable11N1SForABand; + } + else + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N1S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N1S; + else + *ppTable = RateSwitchTable11N1SForABand; + } + break; + } + else if (pEntry->HTCapability.MCSSet[2] == 0x00) + { /* Only support 2SS */ + if (pEntry->RateLen > 0) + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N2S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if ((pAd->LatchRfRegs.Channel <= 14) && (pEntry->SupportRateMode & (SUPPORT_CCK_MODE))) + *ppTable = RateSwitchTable11BGN2S; + else + *ppTable = RateSwitchTable11BGN2SForABand; + } + else + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N2S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11N2S; + else + *ppTable = RateSwitchTable11N2SForABand; + } + break; + } + /* For 3SS case, we use the new rate table, so don't care it here */ + } + } +#endif /* DOT11N_SS3_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + if (((pEntry->SupportRateMode == SUPPORT_CCK_MODE) || + WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) +#ifdef DOT11_N_SUPPORT + /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */ + /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)*/ +#endif /* DOT11_N_SUPPORT */ + ) + {/* B only AP*/ + *ppTable = RateSwitchTable11B; + break; + } + + /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))*/ + if ((pEntry->SupportRateMode & (SUPPORT_CCK_MODE)) && + (pEntry->SupportRateMode & (SUPPORT_OFDM_MODE)) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif /* DOT11_N_SUPPORT */ + ) + {/* B/G mixed AP*/ + *ppTable = RateSwitchTable11BG; + break; + } + + /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))*/ + if ((pEntry->SupportRateMode & (SUPPORT_OFDM_MODE)) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif /* DOT11_N_SUPPORT */ + ) + {/* G only AP*/ + *ppTable = RateSwitchTable11G; + break; + } +#ifdef DOT11_N_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + { +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + { + if (pEntry->HTCapability.MCSSet[2] == 0) { + *ppTable = RateSwitchTableAdapt11N2S; + } else + *ppTable = RateSwitchTableAdapt11N3S; + } + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + { + if (pEntry->HTCapability.MCSSet[2] == 0) + *ppTable = RateSwitchTable11N2S; + else + *ppTable = RateSwitchTable11N3S; + } + } + else +#endif /* DOT11N_SS3_SUPPORT */ + { + /* + Temp solution for: + EX: when the extend rate only supports 6, 12, 24 in + the association req frame. So the pEntry->RateLen is 7. + */ + if (pAd->LatchRfRegs.Channel <= 14) + *ppTable = RateSwitchTable11BG; + else + *ppTable = RateSwitchTable11G; + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef DOT11_N_SUPPORT + /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))*/ + if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) +#endif /* DOT11_N_SUPPORT */ + { /* Legacy mode*/ + if (pAd->CommonCfg.MaxTxRate <= RATE_11) + { + *ppTable = RateSwitchTable11B; + } + else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11)) + { + *ppTable = RateSwitchTable11G; + } + else + { + *ppTable = RateSwitchTable11BG; + } + break; + } +#ifdef DOT11_N_SUPPORT +#ifdef AGS_SUPPORT + if (SUPPORT_AGS(pAd) && (pAd->CommonCfg.TxStream == 3)) + *ppTable = AGS3x3HTRateTable; + else +#endif /* AGS_SUPPORT */ + { + if (pAd->LatchRfRegs.Channel <= 14) + { + if (pAd->CommonCfg.TxStream == 1) + { + *ppTable = RateSwitchTable11N1S; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + } + else if (pAd->CommonCfg.TxStream == 2) + { + *ppTable = RateSwitchTable11N2S; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } + else + { +#ifdef DOT11N_SS3_SUPPORT +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N3S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + *ppTable = RateSwitchTable11N3S; + +#else + *ppTable = RateSwitchTable11N2S; +#endif /* DOT11N_SS3_SUPPORT */ + } + } + else + { + if (pAd->CommonCfg.TxStream == 1) + { + *ppTable = RateSwitchTable11N1S; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + } + else if (pAd->CommonCfg.TxStream == 2) + { + *ppTable = RateSwitchTable11N2S; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } + else + { +#ifdef DOT11N_SS3_SUPPORT +#ifdef NEW_RATE_ADAPT_SUPPORT + if (pAd->rateAlg == RATE_ALG_GRP) + *ppTable = RateSwitchTableAdapt11N3S; + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + *ppTable = RateSwitchTable11N3S; +#else + *ppTable = RateSwitchTable11N2SForABand; +#endif /* DOT11N_SS3_SUPPORT */ + } + } + } +#endif /* DOT11_N_SUPPORT */ + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", + pAd->StaActive.SupRateLen, + pAd->StaActive.ExtRateLen, + pAd->StaActive.SupportedPhyInfo.MCSSet[0], + pAd->StaActive.SupportedPhyInfo.MCSSet[1])); + } +#endif /* CONFIG_STA_SUPPORT */ + } while(FALSE); + + *pTableSize = RATE_TABLE_SIZE(*ppTable); + *pInitTxRateIdx = RATE_TABLE_INIT_INDEX(*ppTable); + +} + + + +/* + MlmeSelectTxRate - select the MCS based on the RSSI and the available MCSs + pAd - pointer to adapter + pEntry - pointer to MAC table entry + mcs - table of MCS index into the Rate Table. -1 => not supported + Rssi - the Rssi value + RssiOffset - offset to apply to the Rssi +*/ +UCHAR MlmeSelectTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN CHAR mcs[], + IN CHAR Rssi, + IN CHAR RssiOffset) +{ + UCHAR TxRateIdx = 0; + UCHAR *pTable = pEntry->pTable; + +#ifdef DOT11_N_SUPPORT +#ifdef NEW_RATE_ADAPT_SUPPORT +#ifdef DOT11_VHT_AC + if (pTable == RateTableVht2S || pTable == RateTableVht2S_BW20 || pTable == RateTableVht2S_BW40 + || (pTable == RateTableVht2S_MCS7) + || (pTable == RateTableVht2S_2G_BW20) || (pTable == RateTableVht2S_2G_BW40)) + { + /* VHT mode with 2SS */ + if (mcs[15]>=0 && (Rssi >= (-70+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_15])) + TxRateIdx = mcs[15]; + else if (mcs[14]>=0 && (Rssi >= (-72+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_14])) + TxRateIdx = mcs[14]; + else if (mcs[13]>=0 && (Rssi >= (-76+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_13])) + TxRateIdx = mcs[13]; + else if (mcs[12]>=0 && (Rssi >= (-78+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_12])) + TxRateIdx = mcs[12]; + else if (mcs[4]>=0 && (Rssi >= (-82+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_4])) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi >= (-84+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi >= (-86+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi >= (-88+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else if ((pTable == RateTableVht1S_MCS9) + || (pTable == RateTableVht1S_2G_BW20) || (pTable == RateTableVht1S_2G_BW40)) + { /* VHT mode with 1SS */ + if (mcs[9]>=0 && (Rssi > (-72+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_9])) + TxRateIdx = mcs[8]; + else if (mcs[8]>=0 && (Rssi > (-72+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_8])) + TxRateIdx = mcs[8]; + else if (mcs[7]>=0 && (Rssi > (-72+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_7])) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > (-74+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_6])) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > (-77+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_5])) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > (-79+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_4])) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi > (-81+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > (-83+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-86+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else if (pTable == RateTableVht1S) + { /* VHT mode with 1SS */ + if (mcs[7]>=0 && (Rssi > (-72+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_7])) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > (-74+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_6])) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > (-77+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_5])) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > (-79+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_4])) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi > (-81+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > (-83+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-86+RssiOffset)) && (pEntry->SupportVHTMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else +#endif /* DOT11_VHT_AC */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ +#ifdef DOT11N_SS3_SUPPORT + if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable11BGN3SForABand) +#ifdef NEW_RATE_ADAPT_SUPPORT + || (pTable == RateSwitchTableAdapt11N3S) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + ) + {/* N mode with 3 stream */ + if (mcs[23]>=0 && (Rssi >= (-66+RssiOffset)) && (pEntry->SupportHTMCS[MCS_23])) + TxRateIdx = mcs[23]; + else if (mcs[22]>=0 && (Rssi >= (-70+RssiOffset)) && (pEntry->SupportHTMCS[MCS_22])) + TxRateIdx = mcs[22]; + else if (mcs[21]>=0 && (Rssi >= (-72+RssiOffset)) && (pEntry->SupportHTMCS[MCS_21])) + TxRateIdx = mcs[21]; + else if (mcs[20]>=0 && (Rssi >= (-74+RssiOffset)) && (pEntry->SupportHTMCS[MCS_20])) + TxRateIdx = mcs[20]; + else if (mcs[13]>=0 && (Rssi >= (-76+RssiOffset)) && (pEntry->SupportHTMCS[MCS_13])) + TxRateIdx = mcs[13]; + else if (mcs[12]>=0 && (Rssi >= (-78+RssiOffset)) && (pEntry->SupportHTMCS[MCS_12])) + TxRateIdx = mcs[12]; + else if (mcs[4]>=0 && (Rssi >= (-82+RssiOffset)) && (pEntry->SupportHTMCS[MCS_4])) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi >= (-84+RssiOffset)) && (pEntry->SupportHTMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi >= (-86+RssiOffset)) && (pEntry->SupportHTMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi >= (-88+RssiOffset)) && (pEntry->SupportHTMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else +#endif /* DOT11N_SS3_SUPPORT */ + if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || + (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand) +#ifdef NEW_RATE_ADAPT_SUPPORT + || (pTable == RateSwitchTableAdapt11N2S) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + ) + {/* N mode with 2 stream */ + if (mcs[15]>=0 && (Rssi >= (-70+RssiOffset)) && (pEntry->SupportHTMCS[MCS_15])) + TxRateIdx = mcs[15]; + else if (mcs[14]>=0 && (Rssi >= (-72+RssiOffset)) && (pEntry->SupportHTMCS[MCS_14])) + TxRateIdx = mcs[14]; + else if (mcs[13]>=0 && (Rssi >= (-76+RssiOffset)) && (pEntry->SupportHTMCS[MCS_13])) + TxRateIdx = mcs[13]; + else if (mcs[12]>=0 && (Rssi >= (-78+RssiOffset)) && (pEntry->SupportHTMCS[MCS_12])) + TxRateIdx = mcs[12]; + else if (mcs[4]>=0 && (Rssi >= (-82+RssiOffset)) && (pEntry->SupportHTMCS[MCS_4])) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi >= (-84+RssiOffset)) && (pEntry->SupportHTMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi >= (-86+RssiOffset)) && (pEntry->SupportHTMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi >= (-88+RssiOffset)) && (pEntry->SupportHTMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + else if ((pTable == RateSwitchTable11BGN1S) || + (pTable == RateSwitchTable11N1S) || + (pTable == RateSwitchTable11N1SForABand) +#ifdef NEW_RATE_ADAPT_SUPPORT + || (pTable == RateSwitchTableAdapt11N1S) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + ) + {/* N mode with 1 stream */ + { + if (mcs[7]>=0 && (Rssi > (-72+RssiOffset)) && (pEntry->SupportHTMCS[MCS_7])) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > (-74+RssiOffset)) && (pEntry->SupportHTMCS[MCS_6])) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > (-77+RssiOffset)) && (pEntry->SupportHTMCS[MCS_5])) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > (-79+RssiOffset)) && (pEntry->SupportHTMCS[MCS_4])) + TxRateIdx = mcs[4]; + else if (mcs[3]>=0 && (Rssi > (-81+RssiOffset)) && (pEntry->SupportHTMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > (-83+RssiOffset)) && (pEntry->SupportHTMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > (-86+RssiOffset)) && (pEntry->SupportHTMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + } + else +#endif /* DOT11_N_SUPPORT */ + {/* Legacy mode */ + if (mcs[7]>=0 && (Rssi > -70) && (pEntry->SupportOFDMMCS[MCS_7])) + TxRateIdx = mcs[7]; + else if (mcs[6]>=0 && (Rssi > -74) && (pEntry->SupportOFDMMCS[MCS_7])) + TxRateIdx = mcs[6]; + else if (mcs[5]>=0 && (Rssi > -78) && (pEntry->SupportOFDMMCS[MCS_7])) + TxRateIdx = mcs[5]; + else if (mcs[4]>=0 && (Rssi > -82) && (pEntry->SupportOFDMMCS[MCS_7])) + TxRateIdx = mcs[4]; + else if (mcs[4] == -1) /* for B-only mode */ + { + if (mcs[3]>=0 && (Rssi > -85) && (pEntry->SupportCCKMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > -87) && (pEntry->SupportCCKMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > -90) && (pEntry->SupportCCKMCS[MCS_1])) + TxRateIdx = mcs[1]; + else if (pEntry->SupportCCKMCS[MCS_0]) + TxRateIdx = mcs[0]; + else + TxRateIdx = mcs[3]; + } + else if (mcs[3]>=0 && (Rssi > -85) && (pEntry->SupportOFDMMCS[MCS_3])) + TxRateIdx = mcs[3]; + else if (mcs[2]>=0 && (Rssi > -87) && (pEntry->SupportOFDMMCS[MCS_2])) + TxRateIdx = mcs[2]; + else if (mcs[1]>=0 && (Rssi > -90) && (pEntry->SupportOFDMMCS[MCS_1])) + TxRateIdx = mcs[1]; + else + TxRateIdx = mcs[0]; + } + + + return TxRateIdx; +} + + +/* MlmeRAInit - Initialize Rate Adaptation for this entry */ +VOID MlmeRAInit(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ +#ifdef NEW_RATE_ADAPT_SUPPORT + MlmeSetMcsGroup(pAd, pEntry); + + pEntry->lastRateIdx = 1; + pEntry->lowTrafficCount = 0; + pEntry->perThrdAdj = PER_THRD_ADJ; +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pEntry->lowTrafficCount = 0; + +#ifdef TXBF_SUPPORT + pEntry->phyETxBf = pEntry->phyITxBf = FALSE; + pEntry->lastRatePhyTxBf = FALSE; + pEntry->lastNonBfRate = 0; +#endif /* TXBF_SUPPORT */ + + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + pEntry->CurrTxRateIndex = 0; + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; + pEntry->LowPacket = FALSE; + pEntry->LastSaveRateIdx = 0; + NdisZeroMemory(pEntry->DownTxMCSRate, sizeof(pEntry->DownTxMCSRate)); + + MlmeClearAllTxQuality(pEntry); +} + + +/* #define TIMESTAMP_RA_LOG */ /* Include timestamp in RA Log */ + +/* + MlmeRALog - Prints concise Rate Adaptation log entry + The BF percentage counters are also updated +*/ +VOID MlmeRALog( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN RA_LOG_TYPE raLogType, + IN ULONG TxErrorRatio, + IN ULONG TxTotalCnt) +{ +#ifdef TXBF_SUPPORT + UINT ETxCount = pEntry->TxBFCounters.ETxSuccessCount + pEntry->TxBFCounters.ETxFailCount; + UINT ITxCount = pEntry->TxBFCounters.ITxSuccessCount + pEntry->TxBFCounters.ITxFailCount; + UINT TxCount = pEntry->TxBFCounters.TxSuccessCount + pEntry->TxBFCounters.TxFailCount + ETxCount + ITxCount; + ULONG bfRatio = 0; +#endif /* TXBF_SUPPORT */ +#ifdef TIMESTAMP_RA_LOG + ULONG newTime; + static ULONG saveRATime; + struct timeval tval; + + do_gettimeofday(&tval); + newTime = (tval.tv_sec*1000000L + tval.tv_usec); +#endif + + if (TxTotalCnt !=0 || raLogType==RAL_QUICK_DRS +#ifdef DBG_CTRL_SUPPORT + || (pAd->CommonCfg.DebugFlags & DBF_SHOW_ZERO_RA_LOG) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + BOOLEAN stbc, csd=FALSE; + ULONG tp; + + /* Get STBC and StreamMode state */ + stbc = (pEntry->HTPhyMode.field.STBC && pEntry->HTPhyMode.field.MCS<8); + +#ifdef STREAM_MODE_SUPPORT + if (pEntry->StreamModeMACReg != 0) + { + ULONG streamWord; + + RTMP_IO_READ32(pAd, pEntry->StreamModeMACReg+4, &streamWord); + if (pEntry->HTPhyMode.field.MCS < 8) + csd = (streamWord & 0x30000)==0x30000; + else if (pEntry->HTPhyMode.field.MCS < 16) + csd = (streamWord & 0xC0000)==0xC0000; + } +#endif /* STREAM_MODE_SUPPORT */ + + /* Normalized throughput - packets per RA Interval */ + if (raLogType==RAL_QUICK_DRS) + tp = (100-TxErrorRatio)*TxTotalCnt*RA_INTERVAL/(100*pAd->ra_fast_interval); + else if (pEntry->LastSecTxRateChangeAction==RATE_NO_CHANGE +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_FORCE_QUICK_DRS)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + tp = (100-TxErrorRatio)*TxTotalCnt/100; + else + tp = (100-TxErrorRatio)*TxTotalCnt*RA_INTERVAL/(100*(RA_INTERVAL-pAd->ra_fast_interval)); + +#ifdef TXBF_SUPPORT + /* Compute BF ratio in the last interval */ + if ((TxCount - pEntry->LastTxCount)>0) + { + if (pEntry->HTPhyMode.field.eTxBF) + bfRatio = 100*(ETxCount-pEntry->LastETxCount)/(TxCount - pEntry->LastTxCount); + else if (pEntry->HTPhyMode.field.iTxBF) + bfRatio = 100*(ITxCount-pEntry->LastITxCount)/(TxCount - pEntry->LastTxCount); + } + + if ((pEntry->HTPhyMode.field.eTxBF || pEntry->HTPhyMode.field.iTxBF) +#ifdef DBG_CTRL_SUPPORT + && (pAd->CommonCfg.DebugFlags & DBF_DBQ_RA_LOG)==0 +#endif /* DBG_CTRL_SUPPORT */ + ) + { + DBGPRINT_RAW(RT_DEBUG_ERROR,("%s[%d]: M=%d %c%c%c%c%c PER=%ld%% TP=%ld BF=%ld%% ", + raLogType==RAL_QUICK_DRS? " Q": (raLogType==RAL_NEW_DRS? "\nRA": "\nra"), + pEntry->wcid, pEntry->HTPhyMode.field.MCS, + pEntry->HTPhyMode.field.MODE==MODE_CCK? 'C': (pEntry->HTPhyMode.field.ShortGI? 'S': 'L'), + pEntry->HTPhyMode.field.BW? '4': '2', + stbc? 'S': 's', + csd? 'C': 'c', + pEntry->HTPhyMode.field.eTxBF? 'E': (pEntry->HTPhyMode.field.iTxBF? 'I': '-'), + TxErrorRatio, tp, bfRatio) ); + } + else +#endif /* TXBF_SUPPORT */ +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_RA_LOG) + { + struct { + USHORT phyMode; + USHORT per; + USHORT tp; + USHORT bfRatio; + } raLogInfo; + + raLogInfo.phyMode = pEntry->HTPhyMode.word; + raLogInfo.per = TxErrorRatio; + raLogInfo.tp = tp; +#ifdef TXBF_SUPPORT + raLogInfo.bfRatio = bfRatio; +#endif /* TXBF_SUPPORT */ + dbQueueEnqueue(0x7e, (UCHAR *)&raLogInfo); + } + else +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + { + DBGPRINT_RAW(RT_DEBUG_ERROR,("%s[%d]: M=%d %c%c%c%c- PER=%ld%% TP=%ld ", + raLogType==RAL_QUICK_DRS? " Q": (raLogType==RAL_NEW_DRS? "\nRA": "\nra"), + pEntry->wcid, pEntry->HTPhyMode.field.MCS, + pEntry->HTPhyMode.field.MODE==MODE_CCK? 'C': (pEntry->HTPhyMode.field.ShortGI? 'S': 'L'), + pEntry->HTPhyMode.field.BW? '4': '2', + stbc? 'S': 's', + csd? 'C': 'c', + TxErrorRatio, tp) ); + } + } + +#ifdef TXBF_SUPPORT + /* Remember previous counts */ + pEntry->LastETxCount = ETxCount; + pEntry->LastITxCount = ITxCount; + pEntry->LastTxCount = TxCount; +#endif /* TXBF_SUPPORT */ +#ifdef TIMESTAMP_RA_LOG + saveRATime = newTime; +#endif +} + + +/* MlmeRestoreLastRate - restore last saved rate */ +VOID MlmeRestoreLastRate( + IN PMAC_TABLE_ENTRY pEntry) +{ + pEntry->CurrTxRateIndex = pEntry->lastRateIdx; +#ifdef TXBF_SUPPORT + if (pEntry->eTxBfEnCond>0) + pEntry->phyETxBf = pEntry->lastRatePhyTxBf; + else + pEntry->phyITxBf = pEntry->lastRatePhyTxBf; +#endif /* TXBF_SUPPORT */ +} + + +#ifdef DOT11N_SS3_SUPPORT +/* MlmeCheckRDG - check if RDG should be enabled or disabled */ +VOID MlmeCheckRDG( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + PUCHAR pTable = pEntry->pTable; + + /* Turn off RDG when 3s and rx count > tx count*5 */ + if (((pTable == RateSwitchTable11BGN3S) || + (pTable == RateSwitchTable11BGN3SForABand) || + (pTable == RateSwitchTable11N3S) +#ifdef NEW_RATE_ADAPT_SUPPORT + || (pTable == RateSwitchTableAdapt11N3S) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + ) && pAd->RalinkCounters.OneSecReceivedByteCount > 50000 && + pAd->RalinkCounters.OneSecTransmittedByteCount > 50000 && + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE)) + { + TX_LINK_CFG_STRUC TxLinkCfg; + ULONG TxOpThres; + UCHAR TableStep; + RTMP_RA_LEGACY_TB *pTempTxRate; + +#ifdef NEW_RATE_ADAPT_SUPPORT + TableStep = ADAPT_RATE_TABLE(pTable)? 10: 5; +#else + TableStep = 5; +#endif + + pTempTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1)*TableStep]); + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + if (pAd->RalinkCounters.OneSecReceivedByteCount > (pAd->RalinkCounters.OneSecTransmittedByteCount * 5) && + pTempTxRate->CurrMCS != 23 && pTempTxRate->ShortGI != 1) + { + if (TxLinkCfg.field.TxRDGEn == 1) + { + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + RTMP_IO_READ32(pAd, TXOP_THRES_CFG, &TxOpThres); + TxOpThres |= 0xff00; + RTMP_IO_WRITE32(pAd, TXOP_THRES_CFG, TxOpThres); + DBGPRINT_RAW(RT_DEBUG_WARN,("DRS: RDG off!\n")); + } + } + else + { + if (TxLinkCfg.field.TxRDGEn == 0) + { + TxLinkCfg.field.TxRDGEn = 1; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + RTMP_IO_READ32(pAd, TXOP_THRES_CFG, &TxOpThres); + TxOpThres &= 0xffff00ff; + RTMP_IO_WRITE32(pAd, TXOP_THRES_CFG, TxOpThres); + DBGPRINT_RAW(RT_DEBUG_WARN,("DRS: RDG on!\n")); + } + } + } +} +#endif /* DOT11N_SS3_SUPPORT */ + + +#ifdef TXBF_SUPPORT +VOID txbf_rate_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + RTMP_RA_LEGACY_TB *pNextTxRate; + UCHAR *pTable = pEntry->pTable; + + + /* Get pointer to CurrTxRate entry */ +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + pNextTxRate = (RTMP_RA_LEGACY_TB *)PTX_RA_GRP_ENTRY(pTable, pEntry->CurrTxRateIndex); + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pNextTxRate = PTX_RA_LEGACY_ENTRY(pTable, pEntry->CurrTxRateIndex); + + /* If BF has been disabled then force a non-BF rate */ + pEntry->phyETxBf = (pEntry->eTxBfEnCond > 0) ? TRUE : FALSE; + pEntry->iTxBfEn = (pEntry->iTxBfEn > 0) ? TRUE : FALSE; + + + /* Set BF options */ + pEntry->HTPhyMode.field.eTxBF = pEntry->phyETxBf; + pEntry->HTPhyMode.field.iTxBF = pEntry->phyITxBf; + + /* Give ETxBF priority over ITxBF */ + if (pEntry->HTPhyMode.field.eTxBF) + pEntry->HTPhyMode.field.iTxBF = 0; + + /* In ITxBF mode force GI if we have no choice */ + if (pEntry->HTPhyMode.field.iTxBF && + (pEntry->OneSecRxLGICount + pEntry->OneSecRxSGICount) > 10) + { + if (pEntry->OneSecRxSGICount==0) + pEntry->HTPhyMode.field.ShortGI = GI_800; + + if (pEntry->OneSecRxLGICount==0) + { + if ((pEntry->HTPhyMode.field.BW==BW_20 && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)) || + (pEntry->HTPhyMode.field.BW==BW_40 && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) + pEntry->HTPhyMode.field.ShortGI = GI_400; + } + } + + /* Disable STBC if BF is enabled */ + if (pEntry->HTPhyMode.field.eTxBF || pEntry->HTPhyMode.field.iTxBF) + pEntry->HTPhyMode.field.STBC = STBC_NONE; +} +#endif /* TXBF_SUPPORT */ + + +INT rtmp_get_rate_from_rate_tb(UCHAR *table, INT idx, RTMP_TX_RATE *tx_rate) +{ +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(table)) { + RTMP_RA_GRP_TB *rate_entry; + + rate_entry = PTX_RA_GRP_ENTRY(table, idx); + tx_rate->mode = rate_entry->Mode; + tx_rate->bw = rate_entry->BW; + tx_rate->mcs = rate_entry->CurrMCS; + tx_rate->sgi = rate_entry->ShortGI; + tx_rate->stbc = rate_entry->STBC; +#ifdef DOT11_VHT_AC + if (table == RateTableVht1S || table == RateTableVht2S || + table == RateTableVht2S_BW40 || + table == RateTableVht2S_BW20 || table == RateTableVht1S_MCS9 + || (table == RateTableVht2S_MCS7) + || (table == RateTableVht1S_2G_BW20) + || (table == RateTableVht1S_2G_BW40) + || (table == RateTableVht2S_2G_BW20) + || (table == RateTableVht2S_2G_BW40)) + tx_rate->nss = rate_entry->dataRate; + else +#endif /* DOT11_VHT_AC */ + tx_rate->nss = 0; + } + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + { + RTMP_RA_LEGACY_TB *rate_entry; + + rate_entry = PTX_RA_LEGACY_ENTRY(table, idx); + tx_rate->mode = rate_entry->Mode; + tx_rate->bw = rate_entry->BW; + tx_rate->mcs = rate_entry->CurrMCS; + tx_rate->sgi = rate_entry->ShortGI; + tx_rate->stbc = rate_entry->STBC; + tx_rate->nss = 0; + } + + return TRUE; +} + + +/* + MlmeNewTxRate - called when a new TX rate was selected. Sets TX PHY to + rate selected by pEntry->CurrTxRateIndex in pTable; +*/ +VOID MlmeNewTxRate(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + RTMP_RA_LEGACY_TB *pNextTxRate; + RTMP_TX_RATE tx_rate; + UCHAR *pTable; + + if ((pEntry == NULL) || (pEntry->pTable == NULL)) + return; + else + pTable = pEntry->pTable; + + rtmp_get_rate_from_rate_tb(pEntry->pTable, pEntry->CurrTxRateIndex, &tx_rate); + /* Get pointer to CurrTxRate entry */ +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + pNextTxRate = (RTMP_RA_LEGACY_TB *)PTX_RA_GRP_ENTRY(pTable, pEntry->CurrTxRateIndex); + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pNextTxRate = PTX_RA_LEGACY_ENTRY(pTable, pEntry->CurrTxRateIndex); + + /* Set new rate */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APMlmeSetTxRate(pAd, pEntry, pNextTxRate); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* Disable invalid HT Duplicate modes to prevent PHY error */ + if (pEntry->HTPhyMode.field.MCS==32) + { + if ((pEntry->HTPhyMode.field.BW!=BW_40) && (pEntry->HTPhyMode.field.BW!=BW_80)) + pEntry->HTPhyMode.field.MCS = 0; + else + pEntry->HTPhyMode.field.STBC = 0; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + txbf_rate_adjust(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); + +#ifdef STREAM_MODE_SUPPORT + /* Enable/disable stream mode based on MCS */ + if (pAd->CommonCfg.StreamMode!=0 && + pEntry->StreamModeMACReg!=0) + { + UINT streamWord; + BOOLEAN mcsDisable; + + /* OFDM: depends on StreamModeMCS, CCK: always applies stream-mode */ + mcsDisable = (pEntry->HTPhyMode.field.MCS < 16) && + (pAd->CommonCfg.StreamModeMCS & (1<HTPhyMode.field.MCS))==0 && + (pEntry->HTPhyMode.field.MODE != MODE_CCK); + + streamWord = mcsDisable ? 0 : StreamModeRegVal(pAd); + + /* Update Stream Mode control reg */ + RTMP_IO_WRITE32(pAd, pEntry->StreamModeMACReg+4, streamWord | (ULONG)(pEntry->Addr[4]) | (ULONG)(pEntry->Addr[5] << 8)); + } +#endif /* STREAM_MODE_SUPPORT */ +} + + +VOID RTMPSetSupportMCS( + IN PRTMP_ADAPTER pAd, + IN UCHAR OpMode, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, +#ifdef DOT11_VHT_AC + IN UCHAR vht_cap_len, + IN VHT_CAP_IE *vht_cap, +#endif /* DOT11_VHT_AC */ + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen) +{ + UCHAR idx, SupportedRatesLen = 0; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + + if (SupRateLen > 0) + { + if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(SupportedRates, SupRate, SupRateLen); + SupportedRatesLen = SupRateLen; + } + else + { + UCHAR RateDefault[8] = {0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c}; + + NdisMoveMemory(SupportedRates, RateDefault, 8); + SupportedRatesLen = 8; + + DBGPRINT(RT_DEBUG_TRACE,("%s():wrong SUPP RATES., Len=%d\n", + __FUNCTION__, SupRateLen)); + } + } + + if (ExtRateLen > 0) + { + if ((SupRateLen + ExtRateLen) <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&SupportedRates[SupRateLen], ExtRate, ExtRateLen); + SupportedRatesLen += ExtRateLen; + } + else + { + NdisMoveMemory(&SupportedRates[SupRateLen], ExtRate, MAX_LEN_OF_SUPPORTED_RATES - ExtRateLen); + SupportedRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + + } + } + + /* Clear Supported MCS Table */ + NdisZeroMemory(pEntry->SupportCCKMCS, MAX_LEN_OF_CCK_RATES); + NdisZeroMemory(pEntry->SupportOFDMMCS, MAX_LEN_OF_OFDM_RATES); + NdisZeroMemory(pEntry->SupportHTMCS, MAX_LEN_OF_HT_RATES); +#ifdef DOT11_VHT_AC + NdisZeroMemory(pEntry->SupportVHTMCS, MAX_LEN_OF_VHT_RATES); +#endif /* DOT11_VHT_AC */ + + pEntry->SupportRateMode = 0; + + for(idx = 0; idx < SupportedRatesLen; idx ++) + { + switch((SupportedRates[idx] & 0x7F)*5) + { + case 10: + pEntry->SupportCCKMCS[MCS_0] = TRUE; + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; + + case 20: + pEntry->SupportCCKMCS[MCS_1] = TRUE; + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; + + case 55: + pEntry->SupportCCKMCS[MCS_2] = TRUE; + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; + + case 110: + pEntry->SupportCCKMCS[MCS_3] = TRUE; + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; + + case 60: + pEntry->SupportOFDMMCS[MCS_0] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 90: + pEntry->SupportOFDMMCS[MCS_1] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 120: + pEntry->SupportOFDMMCS[MCS_2] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 180: + pEntry->SupportOFDMMCS[MCS_3] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 240: + pEntry->SupportOFDMMCS[MCS_4] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 360: + pEntry->SupportOFDMMCS[MCS_5] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 480: + pEntry->SupportOFDMMCS[MCS_6] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + + case 540: + pEntry->SupportOFDMMCS[MCS_7] = TRUE; + pEntry->SupportRateMode |= SUPPORT_OFDM_MODE; + break; + } + } + + if (HtCapabilityLen) + { + RT_PHY_INFO *pDesired_ht_phy = NULL; + UCHAR j, bitmask; + CHAR i; + +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + pDesired_ht_phy = &pAd->StaCfg.wdev.DesiredHtPhyInfo; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry)) + pDesired_ht_phy = &pAd->WdsTab.WdsEntry[pEntry->apidx].wdev.DesiredHtPhyInfo; + else +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + pDesired_ht_phy = &pAd->ApCfg.ApCliTab[pEntry->apidx].wdev.DesiredHtPhyInfo; + else +#endif /* APCLI_SUPPORT */ + pDesired_ht_phy = &pAd->ApCfg.MBSSID[pEntry->apidx].wdev.DesiredHtPhyInfo; + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pDesired_ht_phy == NULL) + return; + + for (i = 23; i >= 0; i--) + { + j = i / 8; + bitmask = (1 << (i - (j * 8))); + + if ((pDesired_ht_phy->MCSSet[j] & bitmask) + && (pHtCapability->MCSSet[j] & bitmask)) + { + pEntry->SupportHTMCS[i] = TRUE; + pEntry->SupportRateMode |= SUPPORT_HT_MODE; + } + } + +#ifdef DOT11_VHT_AC + if ((vht_cap_len > 0)&& (vht_cap != NULL) && pDesired_ht_phy->bVhtEnable) + { + /* Currently we only support for MCS0~MCS7, so don't check mcs_map */ + NdisZeroMemory(&pEntry->SupportVHTMCS[0], sizeof(pEntry->SupportVHTMCS)); + switch (pAd->CommonCfg.TxStream) + { + case 2: + if (vht_cap->mcs_set.rx_mcs_map.mcs_ss2 < VHT_MCS_CAP_NA) + { + for (i = 10; i <= 17; i++) + pEntry->SupportVHTMCS[i] = TRUE; + + if (vht_cap->mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_8) { + pEntry->SupportVHTMCS[18] = TRUE; + } else if (vht_cap->mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_9) { + pEntry->SupportVHTMCS[18] = TRUE; + pEntry->SupportVHTMCS[19] = TRUE; + } + + pEntry->SupportRateMode |= SUPPORT_VHT_MODE; + } + case 1: + if (vht_cap->mcs_set.rx_mcs_map.mcs_ss1 < VHT_MCS_CAP_NA) + { + for (i = 0; i <= 7; i++) + pEntry->SupportVHTMCS[i] = TRUE; + + if (vht_cap->mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_8) { + pEntry->SupportVHTMCS[8] = TRUE; + } else if (vht_cap->mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_9) { + pEntry->SupportVHTMCS[8] = TRUE; + pEntry->SupportVHTMCS[9] = TRUE; + } + + pEntry->SupportRateMode |= SUPPORT_VHT_MODE; + } + default: + break; + } + } +#endif /* DOT11_VHT_AC */ + } +} + + +INT Set_RateAlg_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + UINT32 ra_alg; + + ra_alg = simple_strtol(arg, 0, 10); + + if ((ra_alg < RATE_ALG_MAX_NUM) && (ra_alg != pAd->rateAlg)) + { + UINT32 IdEntry; + + pAd->rateAlg = ra_alg; + for(IdEntry = 0; IdEntry < MAX_LEN_OF_MAC_TABLE; IdEntry++) + pAd->MacTab.Content[IdEntry].rateAlg = ra_alg; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s: Set Alg = %d\n", __FUNCTION__, ra_alg)); + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sniffer/sniffer_prism.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sniffer/sniffer_prism.c new file mode 100644 index 000000000..eb8adb768 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sniffer/sniffer_prism.c @@ -0,0 +1,243 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + sniffer_prism.c +*/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" + +void send_prism_monitor_packets(IN PNET_DEV pNetDev, + IN PNDIS_PACKET pRxPacket, + IN VOID *dot11_hdr, + IN UCHAR *pData, + IN USHORT DataSize, + IN UCHAR L2PAD, + IN UCHAR PHYMODE, + IN UCHAR BW, + IN UCHAR ShortGI, + IN UCHAR MCS, + IN UCHAR AMPDU, + IN UCHAR STBC, + IN UCHAR RSSI1, + IN UCHAR BssMonitorFlag11n, + IN UCHAR *pDevName, + IN UCHAR Channel, + IN UCHAR CentralChannel, + IN UINT32 MaxRssi) { + struct sk_buff *pOSPkt; + wlan_ng_prism2_header *ph; +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + ETHEREAL_RADIO h, *ph_11n33; /* for new 11n sniffer format */ +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + int rate_index = 0; + USHORT header_len = 0; + UCHAR temp_header[40] = {0}; + DOT_11_HDR *pHeader = (DOT_11_HDR *)dot11_hdr; + + MEM_DBG_PKT_FREE_INC(pRxPacket); + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + pOSPkt->dev = pNetDev; + if (pHeader->FC.Type == 0x2 /* FC_TYPE_DATA */) { + DataSize -= LENGTH_802_11; + if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; + + /* QOS */ + if (pHeader->FC.SubType & 0x08) { + header_len += 2; + /* Data skip QOS contorl field */ + DataSize -= 2; + } + + /* Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { + header_len += 4; + /* Data skip HTC contorl field */ + DataSize -= 4; + } + + /* Copy Header */ + if (header_len <= 40) + NdisMoveMemory(temp_header, pData, header_len); + + /* skip HW padding */ + if (L2PAD) + pData += (header_len + 2); + else + pData += header_len; + } + + if (DataSize < pOSPkt->len) { + skb_trim(pOSPkt, DataSize); + } else { + skb_put(pOSPkt, (DataSize - pOSPkt->len)); + } + + if ((pData - pOSPkt->data) > 0) { + skb_put(pOSPkt, (pData - pOSPkt->data)); + skb_pull(pOSPkt, (pData - pOSPkt->data)); + } + + if (skb_headroom(pOSPkt) < (sizeof (wlan_ng_prism2_header) + header_len)) { + if (pskb_expand_head(pOSPkt, (sizeof (wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Reallocate header size of sk_buff fail!\n", + __FUNCTION__)); + goto err_free_sk_buff; + } + } + + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, + header_len); + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + if (BssMonitorFlag11n == 0) +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + { + ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, + sizeof(wlan_ng_prism2_header)); + NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); + + ph->msgcode = DIDmsg_lnxind_wlansniffrm; + ph->msglen = sizeof (wlan_ng_prism2_header); + strcpy((PSTRING) ph->devname, (PSTRING) pDevName); + + ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + ph->hosttime.status = 0; + ph->hosttime.len = 4; + ph->hosttime.data = jiffies; + + ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + ph->mactime.status = 0; + ph->mactime.len = 0; + ph->mactime.data = 0; + + ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + ph->istx.status = 0; + ph->istx.len = 0; + ph->istx.data = 0; + + ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + ph->channel.status = 0; + ph->channel.len = 4; + + ph->channel.data = (u_int32_t)Channel; + + ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + ph->rssi.status = 0; + ph->rssi.len = 4; + ph->rssi.data = MaxRssi; + ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + ph->signal.status = 0; + ph->signal.len = 4; + ph->signal.data = 0; /*rssi + noise; */ + + ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + ph->noise.status = 0; + ph->noise.len = 4; + ph->noise.data = 0; + RtmpDrvRateGet(NULL, PHYMODE, ShortGI, BW, MCS, newRateGetAntenna(MCS, PHYMODE), &ph->rate.data); + ph->rate.data /= 1000000; + ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + ph->rate.status = 0; + ph->rate.len = 4; + + ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + ph->frmlen.status = 0; + ph->frmlen.len = 4; + ph->frmlen.data = (u_int32_t) DataSize; + } +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + else { + ph_11n33 = &h; + NdisZeroMemory((unsigned char *)ph_11n33, + sizeof (ETHEREAL_RADIO)); + + /*802.11n fields */ + if (MCS > 15) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_3x3; + + if (PHYMODE == MODE_HTGREENFIELD) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_GF; + + if (BW == 1) { + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW40; + } else if (Channel < CentralChannel) { + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW20U; + } else if (Channel > CentralChannel) { + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW20D; + } else { + ph_11n33->Flag_80211n |= + (WIRESHARK_11N_FLAG_BW20U | + WIRESHARK_11N_FLAG_BW20D); + } + + if (ShortGI == 1) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_SGI; + + if (AMPDU) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_AMPDU; + + if (STBC) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_STBC; + + ph_11n33->signal_level = (UCHAR) RSSI1; + + /* data_rate is the rate index in the wireshark rate table */ + if (PHYMODE >= MODE_HTMIX) { + if (MCS == 32) { + if (ShortGI) + ph_11n33->data_rate = 16; + else + ph_11n33->data_rate = 4; + } else if (MCS > 15) + ph_11n33->data_rate = + (16 * 4 + ((UCHAR) BW * 16) + + ((UCHAR) ShortGI * 32) + ((UCHAR) MCS)); + else + ph_11n33->data_rate = + 16 + ((UCHAR) BW * 16) + + ((UCHAR) ShortGI * 32) + ((UCHAR) MCS); + } else if (PHYMODE == MODE_OFDM) + ph_11n33->data_rate = (UCHAR) (MCS) + 4; + else + ph_11n33->data_rate = (UCHAR) (MCS); + + /*channel field */ + ph_11n33->channel = (UCHAR) Channel; + + NdisMoveMemory(skb_put(pOSPkt, sizeof (ETHEREAL_RADIO)), + (UCHAR *) ph_11n33, sizeof (ETHEREAL_RADIO)); + } +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx(pOSPkt); + return; + +err_free_sk_buff: + RELEASE_NDIS_PACKET(NULL, pRxPacket, NDIS_STATUS_FAILURE); + return; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sniffer/sniffer_radiotap.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sniffer/sniffer_radiotap.c new file mode 100644 index 000000000..134de3c83 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sniffer/sniffer_radiotap.c @@ -0,0 +1,906 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. 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 MediaTek. 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 MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + sniffer_radiotap.c +*/ +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" +#include "rt_config.h" + +#define ETH_P_ECONET 0x0018 +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) + + +void send_radiotap_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR LDPC, + UCHAR LDPC_EX_SYM, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UCHAR sideband_index, + CHAR MaxRssi, + UINT32 timestamp) { + struct sk_buff *pOSPkt; + int rate_index = 0; + USHORT header_len = 0; + UCHAR temp_header[40] = {0}; + struct mtk_radiotap_header *mtk_rt_hdr; + UINT32 varlen = 0, padding_len = 0; + UINT64 tmp64; + UINT32 tmp32; + UINT16 tmp16; + UCHAR *pos; + DOT_11_HDR *pHeader = (DOT_11_HDR *)dot11_hdr; + + MEM_DBG_PKT_FREE_INC(pRxPacket); + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + pOSPkt->dev = pNetDev; + if (pHeader->FC.Type == 0x2 /* FC_TYPE_DATA */) { + DataSize -= LENGTH_802_11; + if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; + + /* QOS */ + if (pHeader->FC.SubType & 0x08) { + header_len += 2; + /* Data skip QOS contorl field */ + DataSize -= 2; + } + + /* Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { + header_len += 4; + /* Data skip HTC contorl field */ + DataSize -= 4; + } + + /* Copy Header */ + if (header_len <= 40) + NdisMoveMemory(temp_header, pData, header_len); + + /* skip HW padding */ + if (L2PAD) + pData += (header_len + 2); + else + pData += header_len; + } + + if (DataSize < pOSPkt->len) { + skb_trim(pOSPkt, DataSize); + } else { + skb_put(pOSPkt, (DataSize - pOSPkt->len)); + } + + if ((pData - pOSPkt->data) > 0) { + skb_put(pOSPkt, (pData - pOSPkt->data)); + skb_pull(pOSPkt, (pData - pOSPkt->data)); + } + + if (skb_headroom(pOSPkt) < (sizeof(*mtk_rt_hdr) + header_len)) { + if (pskb_expand_head(pOSPkt, (sizeof(*mtk_rt_hdr) + header_len), 0, GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Reallocate header size of sk_buff fail!\n", + __FUNCTION__)); + goto err_free_sk_buff; + } + } + + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); + + /* tsf */ + padding_len = ((varlen % 8) == 0) ? 0 : (8 - (varlen % 8)); + varlen += (8 + padding_len); + + /* flags */ + varlen += 1; + + /* rate */ + if (PHYMODE < MODE_HTMIX) + varlen += 1; + + /* dBm ANT Signal */ + varlen += 1; + + /* channel frequency */ + padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); + varlen += (2 + padding_len); + + /* channel flags */ + varlen += 2; + + /* MCS */ + if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { + /* known */ + varlen += 1; + + /* flags */ + varlen += 1; + + /* index */ + varlen += 1; + } + + /* A-MPDU */ + if (AMPDU) { + /* reference number */ + padding_len = ((varlen % 4) == 0) ? 0 : (4 - (varlen % 4)); + varlen += (4 + padding_len); + + /* flags */ + varlen += 2; + + /* delimiter crc value */ + varlen += 1; + + /* reserved */ + varlen += 1; + } + + /* VHT */ + if (PHYMODE == MODE_VHT) { + /* known */ + padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); + varlen += (2 + padding_len); + + /* flags */ + varlen += 1; + + /* bandwidth */ + varlen += 1; + + /* mcs_nss */ + varlen += 4; + + /* coding */ + varlen += 1; + + /* group_id */ + varlen += 1; + + /* partial_aid */ + varlen += 2; + } + + mtk_rt_hdr = (struct mtk_radiotap_header *)skb_push(pOSPkt, sizeof(*mtk_rt_hdr) + varlen); + NdisZeroMemory(mtk_rt_hdr, sizeof(*mtk_rt_hdr) + varlen); + + mtk_rt_hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; + mtk_rt_hdr->rt_hdr.it_pad = 0; + mtk_rt_hdr->rt_hdr.it_len = cpu2le16(sizeof(*mtk_rt_hdr) + varlen); + mtk_rt_hdr->rt_hdr.it_present = cpu2le32( + (1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_FLAGS)); + + if (PHYMODE < MODE_HTMIX) { + mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_RATE); + } + + mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_CHANNEL); + + mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); + + if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { + mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_MCS); + } + + if (AMPDU) { + mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); + } + + if (PHYMODE == MODE_VHT) + mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_VHT); + + varlen = 0; + pos = mtk_rt_hdr->variable; + + padding_len = ((varlen % 8) == 0) ? 0 : (8 - (varlen % 8)); + pos += padding_len; + varlen += padding_len; + + /* tsf */ + tmp64 = timestamp; + NdisMoveMemory(pos, &tmp64, 8); + pos += 8; + varlen += 8; + + /* flags */ + *pos = 0; + pos++; + varlen++; + + /* rate */ + if (PHYMODE == MODE_OFDM) { + *pos = (UCHAR)RalinkRate_Legacy[MCS+4]; + pos++; + varlen++; + } else if (PHYMODE == MODE_CCK) { + *pos = (UCHAR)RalinkRate_Legacy[MCS]; + pos++; + varlen++; + } + + /* channel frequency */ + padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); + pos += padding_len; + varlen += padding_len; + +#define ieee80211chan2mhz(x) \ + (((x) <= 14) ? \ + (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \ + ((x) + 1000) * 5) + + tmp16 = cpu2le16(ieee80211chan2mhz(Channel)); + NdisMoveMemory(pos, &tmp16, 2); + pos += 2; + varlen += 2; + + if (Channel > 14) { + tmp16 = cpu2le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); + } else { + if (PHYMODE == MODE_CCK) { + tmp16 = cpu2le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); + } else { + tmp16 = cpu2le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); + } + } + + NdisMoveMemory(pos, &tmp16, 2); + pos += 2; + varlen += 2; + + /* dBm ANT Signal */ + *pos = MaxRssi; + pos++; + varlen++; + + /* HT MCS */ + if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { + + *pos = (IEEE80211_RADIOTAP_MCS_HAVE_BW | + IEEE80211_RADIOTAP_MCS_HAVE_MCS | + IEEE80211_RADIOTAP_MCS_HAVE_GI | + IEEE80211_RADIOTAP_MCS_HAVE_FMT | + IEEE80211_RADIOTAP_MCS_HAVE_FEC); + + pos++; + varlen++; + + /* BW */ + if (BW == 0) { + *pos = HT_BW(IEEE80211_RADIOTAP_MCS_BW_20); + } else { + *pos = HT_BW(IEEE80211_RADIOTAP_MCS_BW_40); + } + + /* HT GI */ + *pos |= HT_GI(ShortGI); + + /* HT format */ + if (PHYMODE == MODE_HTMIX) + *pos |= HT_FORMAT(0); + else if (PHYMODE == MODE_HTGREENFIELD) + *pos |= HT_FORMAT(1); + + /* HT FEC type */ + *pos |= HT_FEC_TYPE(LDPC); + + pos++; + varlen++; + + /* HT mcs index */ + *pos = MCS; + + pos++; + varlen++; + } + + if (AMPDU) { + /* reference number */ + padding_len = ((varlen % 4) == 0) ? 0 : (4 - (varlen % 4)); + varlen += padding_len; + pos += padding_len; + tmp32 = 0; + NdisMoveMemory(pos, &tmp32, 4); + pos += 4; + varlen += 2; + + /* flags */ + tmp16 = 0; + NdisMoveMemory(pos, &tmp16, 2); + pos += 2; + varlen += 2; + + /* delimiter CRC value */ + *pos = 0; + pos++; + varlen++; + + /* reserved */ + *pos = 0; + pos++; + varlen++; + } + +#ifdef DOT11_VHT_AC + /* VHT */ + if (PHYMODE == MODE_VHT) { + + /* known */ + padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); + varlen += padding_len; + pos += padding_len; + + tmp16 = cpu2le16(IEEE80211_RADIOTAP_VHT_KNOWN_STBC | + IEEE80211_RADIOTAP_VHT_KNOWN_GI | + IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM | + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH); + + NdisMoveMemory(pos, &tmp16, 2); + pos += 2; + varlen += 2; + + /* flags */ + *pos = (STBC?IEEE80211_RADIOTAP_VHT_FLAG_STBC:0); + *pos |= (ShortGI?IEEE80211_RADIOTAP_VHT_FLAG_SGI:0); + *pos |= (LDPC_EX_SYM?IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM:0); + + pos++; + varlen++; + + /* bandwidth */ + if (BW == 0) { + *pos = 0; + } else if (BW == 1) { + *pos = 1; + } else if (BW == 2) { + *pos = 4; + + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:unknow bw(%d)\n", __FUNCTION__, BW)); + } + + /* mcs_nss */ + pos++; + varlen++; + + /* vht_mcs_nss[0] */ + *pos = (GET_VHT_NSS(MCS) & 0x0f); + *pos |= ((GET_VHT_MCS(MCS) & 0x0f) << 4); + pos++; + varlen++; + + /* vht_mcs_nss[1] */ + *pos = 0; + pos++; + varlen++; + + /* vht_mcs_nss[2] */ + *pos = 0; + pos++; + varlen++; + + /* vht_mcs_nss[3] */ + *pos = 0; + pos++; + varlen++; + + /* coding */ + if (LDPC) + *pos = 1; + else + *pos = 0; + + pos++; + varlen++; + + /* group_id */ + *pos = 0; + pos++; + varlen++; + + /* partial aid */ + tmp16 = 0; + NdisMoveMemory(pos, &tmp16, 2); + pos += 2; + varlen += 2; + } +#endif /* DOT11_VHT_AC */ + + pOSPkt->dev = pOSPkt->dev; + pOSPkt->mac_header = pOSPkt->data; + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = __constant_htons(ETH_P_80211_RAW); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx_ni(pOSPkt); + return; + +err_free_sk_buff: + RELEASE_NDIS_PACKET(NULL, pRxPacket, NDIS_STATUS_FAILURE); + return; +} + + +#ifdef PPI_HEADER +void send_ppi_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR LDPC, + UCHAR LDPC_EX_SYM, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UCHAR sideband_index, + CHAR MaxRssi, + UINT32 timestamp) { + struct sk_buff *pOSPkt; + int rate_index = 0; + USHORT header_len = 0; + UCHAR temp_header[40] = {0}; + struct mtk_radiotap_header *mtk_rt_hdr; + + ppi_packetheader_t *ppi_pkthead; + ppi_fieldheader_t *ppi_fieldhead; + UCHAR *field_pos; + UINT16 nss; + UINT16 isht; + UINT32 itmp; + UINT16 mcs; + + UINT32 varlen = 0, padding_len = 0; + UINT64 tmp64; + UINT32 tmp32; + UINT16 tmp16; + UCHAR *pos; + DOT_11_HDR *pHeader = (DOT_11_HDR *)dot11_hdr; + + MEM_DBG_PKT_FREE_INC(pRxPacket); + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + pOSPkt->dev = pNetDev; + if (pHeader->FC.Type == 0x2 /* FC_TYPE_DATA */) { + DataSize -= LENGTH_802_11; + if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; + + /* QOS */ + if (pHeader->FC.SubType & 0x08) { + header_len += 2; + /* Data skip QOS contorl field */ + DataSize -= 2; + } + + /* Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { + header_len += 4; + /* Data skip HTC contorl field */ + DataSize -= 4; + } + + /* Copy Header */ + if (header_len <= 40) + NdisMoveMemory(temp_header, pData, header_len); + + /* skip HW padding */ + if (L2PAD) + pData += (header_len + 2); + else + pData += header_len; + } + + if (DataSize < pOSPkt->len) { + skb_trim(pOSPkt, DataSize); + } else { + skb_put(pOSPkt, (DataSize - pOSPkt->len)); + } + + if ((pData - pOSPkt->data) > 0) { + skb_put(pOSPkt, (pData - pOSPkt->data)); + skb_pull(pOSPkt, (pData - pOSPkt->data)); + } + + if (skb_headroom(pOSPkt) < (sizeof(ppi_packetheader_t) + header_len)) { + if (pskb_expand_head(pOSPkt, (sizeof(ppi_packetheader_t) + header_len), 0, GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Reallocate header size of sk_buff fail!\n", + __FUNCTION__)); + goto err_free_sk_buff; + } + } + + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); + + isht=0; + if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)){ + isht = sizeof(ppi_fieldheader_t) + SIZE_PPI_FIELD_80211n_MACPHYEXT; + // printk("HT"); + } + ppi_pkthead = (ppi_packetheader_t *)skb_push(pOSPkt, sizeof(ppi_packetheader_t) + sizeof(ppi_fieldheader_t) + + SIZE_PPI_FIELD_80211_COMMON + isht); + + NdisZeroMemory(ppi_pkthead, sizeof(ppi_packetheader_t) + sizeof(ppi_fieldheader_t) + + SIZE_PPI_FIELD_80211_COMMON + isht); + + ppi_pkthead->pph_version = 0; + ppi_pkthead->pph_flags = 0; + ppi_pkthead->pph_len = sizeof(ppi_packetheader_t) + sizeof(ppi_fieldheader_t) + SIZE_PPI_FIELD_80211_COMMON + isht; + ppi_pkthead->pph_dlt = 105; + field_pos = (UCHAR *)ppi_pkthead; + + ppi_fieldhead = (ppi_fieldheader_t *)(field_pos + sizeof(ppi_packetheader_t)); + field_pos = (UCHAR *)ppi_fieldhead; + + tmp16 = 2; + ppi_fieldhead->pfh_type = tmp16; + tmp16 = SIZE_PPI_FIELD_80211_COMMON; + ppi_fieldhead->pfh_datalen = tmp16; + + field_pos = (UCHAR *)(field_pos + sizeof(ppi_fieldheader_t)); + + //TSF-Timer + tmp64 = timestamp; + NdisMoveMemory(field_pos, &tmp64, 8); + field_pos += 8; + + //Flags + tmp16 = 0; + NdisMoveMemory(field_pos, &tmp16, 2); + field_pos += 2; + + /* rate */ + if (PHYMODE == MODE_OFDM) { + tmp16 = (UINT16)RalinkRate_Legacy[MCS+4]; + NdisMoveMemory(field_pos, &tmp16, 2); + field_pos += 2; + } else if (PHYMODE == MODE_CCK) { + tmp16 = (UINT16)RalinkRate_Legacy[MCS]; + NdisMoveMemory(field_pos, &tmp16, 2); + field_pos += 2; + }else if((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)){ + //For HT omnipeek will calculate rates + field_pos += 2; + }else if(PHYMODE == MODE_VHT){ + nss = (GET_VHT_NSS(MCS) & 0x0f); + mcs = (GET_VHT_MCS(MCS) & 0x0f); + tmp16 = (UINT16)(ieee80211_vhtinfo[mcs][BW][ShortGI][nss]); + tmp16 = tmp16*2; + // printk("-VHT %u %u-",tmp16,timestamp); + NdisMoveMemory(field_pos, &tmp16, 2); + field_pos += 2; + }else{ + field_pos += 2; + } + +#define ieee80211chan2mhz(x) \ + (((x) <= 14) ? \ + (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \ + ((x) + 1000) * 5) + + tmp16 = cpu2le16(ieee80211chan2mhz(Channel)); + NdisMoveMemory(field_pos, &tmp16, 2); + field_pos += 2; + + if (Channel > 14) { + tmp16 = cpu2le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); + } else { + if (PHYMODE == MODE_CCK) { + tmp16 = cpu2le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); + } else { + tmp16 = cpu2le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); + } + } + + + NdisMoveMemory(field_pos, &tmp16, 2); + field_pos += 2; + + //FHSS-Hopset + field_pos += 1; + + //FHSS-Pattern + field_pos += 1; + + /* dBm ANT Signal */ + *(field_pos) = MaxRssi; + field_pos += 1; + + //dBm ANT Noise + field_pos += 1; + + //802.11n MAC+PHY Extension + if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { + + ppi_fieldhead = (ppi_fieldheader_t *)(field_pos); + + tmp16 = 4; + ppi_fieldhead->pfh_type = tmp16; + tmp16 = SIZE_PPI_FIELD_80211n_MACPHYEXT; + ppi_fieldhead->pfh_datalen = tmp16; + field_pos = field_pos + sizeof(ppi_fieldheader_t); + + tmp32 = 0; + itmp = 1; + + if(PHYMODE == MODE_HTGREENFIELD){ + tmp32 |= itmp; + } + + if(BW == 1){ + tmp32 |= itmp<<1; + } + + if(ShortGI == 1){ + tmp32 |= itmp<<2; + } + + NdisMoveMemory(field_pos, &tmp32, 4); + + field_pos += 4; + + //A-MPDU-ID + field_pos += 4; + + //Num-Delimiters + field_pos += 1; + + //MCS + *field_pos = MCS; + field_pos += 1; + + //Num-Streams + field_pos += 1; + + //RSSI-Combined + field_pos += 1; + + //RSSI-Ant0Ctl + field_pos += 1; + + //RSSI-Ant1Ctl + field_pos += 1; + + //RSSI-Ant2Ctl + field_pos += 1; + + //RSSI-Ant3Ctl + field_pos += 1; + + //RSSI-Ant0Ext + field_pos += 1; + + //RSSI-Ant1Ext + field_pos += 1; + + //RSSI-Ant2Ext + field_pos += 1; + + //RSSI-Ant3Ext + field_pos += 1; + + //Extension Channel-Freq + field_pos += 2; + + //Extension Channel-Flags + field_pos += 2; + + //dBm-Ant0signal + field_pos += 1; + + //dBm-Ant0signal + field_pos += 1; + + //dBm-Ant1signal + field_pos += 1; + + //dBm-Ant1noise + field_pos += 1; + + //dBm-Ant2signal + field_pos += 1; + + //dBm-Ant2noise + field_pos += 1; + + //dBm-Ant3signal + field_pos += 1; + + //dBm-Ant3noise + field_pos += 1; + + //EVM0 + field_pos += 4; + + //EVM1 + field_pos += 4; + + //EVM2 + field_pos += 4; + + //EVM3 + field_pos += 4; + + } + + + pOSPkt->dev = pOSPkt->dev; + pOSPkt->mac_header = pOSPkt->data; + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = __constant_htons(ETH_P_80211_RAW); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx_ni(pOSPkt); + return; + +err_free_sk_buff: + RELEASE_NDIS_PACKET(NULL, pRxPacket, NDIS_STATUS_FAILURE); + return; +} +#endif + +VOID Monitor_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ + + PNET_DEV new_dev_p; + INT idx=0; + struct wifi_dev *wdev; + + UINT32 MC_RowID = 0, IoctlIF = 0; + char *dev_name; + + if(pAd->monitor_ctrl.monitor_initiated != FALSE) + { + printk("monitor interface already initiated.\n"); + return; + } + +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ + + dev_name = get_dev_name_prefix(pAd, INT_MONITOR); + //dev_name = "mon"; + + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MONITOR, idx,sizeof(struct mt_dev_priv), dev_name); + if (!new_dev_p) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Create net_device for %s(%d) fail!\n", + __FUNCTION__, dev_name, idx)); + return; + } + + wdev = &pAd->monitor_ctrl.monitor_wdev; + + //wdev->func_dev = pApCliEntry; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = new_dev_p; + //wdev->tx_pkt_allowed = ApCliAllowToSendPacket; + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + RTMP_OS_NETDEV_SET_WDEV(new_dev_p, wdev); + 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(new_dev_p))); + RtmpOSNetDevFree(new_dev_p); + return; + } + + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); + + pNetDevOps->priv_flags = INT_MONITOR; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + pNetDevOps->wdev = wdev; + NdisMoveMemory(pNetDevOps->devAddr, &wdev->if_addr[0], MAC_ADDR_LEN); + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + pAd->monitor_ctrl.monitor_initiated = TRUE; + return; +} + + +VOID Monitor_Remove(RTMP_ADAPTER *pAd) +{ + struct wifi_dev *wdev; + wdev = &pAd->monitor_ctrl.monitor_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; + pAd->monitor_ctrl.monitor_initiated = FALSE; + } + +} +BOOLEAN Monitor_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p) +{ + UINT32 Value = 0; + if (pAd->monitor_ctrl.monitor_wdev.if_dev == dev_p) + { +#ifdef PPI_HEADER +#define PPI_ARPHRD 1000 + + RTMP_OS_NETDEV_SET_TYPE(pAd->monitor_ctrl.monitor_wdev.if_dev,PPI_ARPHRD); +#else + RTMP_OS_NETDEV_SET_TYPE(pAd->monitor_ctrl.monitor_wdev.if_dev,ARPHRD_IEEE80211_RADIOTAP); +#endif + +//RxFilter will be decided by iwpriv set MonitorMode + } + + return TRUE; +} + + +BOOLEAN Monitor_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p) +{ + UINT32 Value = 0; + if (pAd->monitor_ctrl.monitor_wdev.if_dev == dev_p) + { + /* RTMP_OS_NETDEV_STOP_QUEUE(dev_p); */ + + /* resume normal settings */ +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.BssType = BSS_INFRA; +#else + pAd->ApCfg.BssType = BSS_INFRA; +#endif + + AsicSetRxFilter(pAd); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + return TRUE; + } + + + + return FALSE; +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/assoc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/assoc.c new file mode 100644 index 000000000..b08e16494 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/assoc.c @@ -0,0 +1,2065 @@ +/* + *************************************************************************** + * 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: + assoc.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-9-3 porting from RT2500 +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +UCHAR CipherWpaTemplate[] = { + 0xdd, /* WPA IE */ + 0x16, /* Length */ + 0x00, 0x50, 0xf2, 0x01, /* oui */ + 0x01, 0x00, /* Version */ + 0x00, 0x50, 0xf2, 0x02, /* Multicast */ + 0x01, 0x00, /* Number of unicast */ + 0x00, 0x50, 0xf2, 0x02, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x50, 0xf2, 0x01 /* authentication */ +}; + +UCHAR CipherWpa2Template[] = { + 0x30, /* RSN IE */ + 0x14, /* Length */ + 0x01, 0x00, /* Version */ + 0x00, 0x0f, 0xac, 0x02, /* group cipher, TKIP */ + 0x01, 0x00, /* number of pairwise */ + 0x00, 0x0f, 0xac, 0x02, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x0f, 0xac, 0x02, /* authentication */ + 0x00, 0x00, /* RSN capability */ +}; + + +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Reassociation timeout procedure. After reassociation timeout, this + function will be called and put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ReassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Disassociation timeout procedure. After disassociation timeout, this + function will be called and put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID DisassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + mlme assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored in the config + -# SSID + -# supported rates and their length + -# listen interval (Adapter->StaCfg.default_listen_count) + -# Transmit power (Adapter->StaCfg.tx_power) + Post : + -# An association request frame is generated and sent to the air + -# Association timer starts + -# Association state -> ASSOC_WAIT_RSP + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + ULONG Idx; + UCHAR ApAddr[6]; + HEADER_802_11 AssocHdr; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT ListenIntv; + ULONG Timeout; + USHORT CapabilityInfo; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + ULONG tmp; + USHORT VarIesOffset = 0; + USHORT Status; + + /* Block all authentication request durning WPA block period */ + if (pAd->StaCfg.bBlockAssoc == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Block Assoc request durning WPA block period!\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, + &Status, 0); + } + /* check sanity first */ + else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /*for dhcp,issue ,wpa_supplicant ioctl too fast , at link_up, it will add key before driver remove key */ + RTMPWPARemoveAllKeys(pAd); + + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); + + /* Get an unused nonpaged memory */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeAssocReqAction() allocate memory failed \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_ASSOC_CONF, 2, &Status, 0); + return; + } + + /* Add by James 03/06/27 */ + pAd->StaCfg.AssocInfo.Length = + sizeof (NDIS_802_11_ASSOCIATION_INFORMATION); + /* Association don't need to report MAC address */ + pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs = + NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; + pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; + pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; + /* Only reassociate need this */ + /*COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); */ + pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof (NDIS_802_11_ASSOCIATION_INFORMATION); + + NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN); + /* First add SSID */ + VarIesOffset = 0; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + VarIesOffset += pAd->MlmeAux.SsidLen; + + /* Second add Supported rates */ + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); + VarIesOffset += pAd->MlmeAux.SupRateLen; + /* End Add by James */ + + + + /* + CapabilityInfo already sync value with AP in PeerBeaconAtJoinAction. + But we need to clean Spectrum Management bit here, if we disable bIEEE80211H in infra sta + */ + if (!((pAd->CommonCfg.Channel > 14) && + (pAd->CommonCfg.bIEEE80211H == TRUE))) { + CapabilityInfo &= (~0x0100); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s ASSOC - Send ASSOC request...\n", __FUNCTION__)); + MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, + pAd->CurrentAddress, + ApAddr); + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRate, END_OF_ARGS); + FrameLen += tmp; + } +#ifdef DOT11R_FT_SUPPORT + /* Add MDIE if we are connection to DOT11R AP */ + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->MlmeAux.MdIeInfo.Len) { + /* MDIE */ + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, + pAd->MlmeAux.MdIeInfo.MdId, + pAd->MlmeAux.MdIeInfo.FtCapPlc); + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* HT */ + if ((pAd->MlmeAux.HtCapabilityLen > 0) + && WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && pAd->MlmeAux.APEdcaParm.bValid) { + ULONG TmpLen; + UCHAR HtLen, BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; + PHT_CAPABILITY_IE pHtCapability; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + NdisZeroMemory(&HtCapabilityTmp, sizeof (HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen); + *(USHORT *) (&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.HtCapInfo)); + *(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo)); + pHtCapability = &HtCapabilityTmp; +#else + pHtCapability = &pAd->MlmeAux.HtCapability; +#endif + + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) { + HtLen = SIZE_HT_CAP_IE + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &WpaIe, 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, + pHtCapability, END_OF_ARGS); + } else { + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &HtCapIe, 1, + &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, + pHtCapability, END_OF_ARGS); + } + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->MlmeAux.Channel > 14) && + (pAd->MlmeAux.vht_cap_len) + ) + { +#ifdef VHT_TXBF_SUPPORT + //Disable beamform capability in Associate Request with 3x3 AP to avoid throughput drop issue + // MT76x2 only supports up to 2x2 sounding feedback + Idx = BssTableSearch(&pAd->ScanTab, pAd->MlmeAux.Bssid, pAd->MlmeAux.Channel); + if (Idx != BSS_NOT_FOUND) + { + pAd->BeaconSndDimensionFlag = 0; + if (pAd->ScanTab.BssEntry[Idx].vht_cap_ie.vht_cap.num_snd_dimension >=2 ) + { + pAd->BeaconSndDimensionFlag = 1; + } + } +#endif /* VHT_TXBF_SUPPORT */ + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_ASSOC_REQ); + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + +#if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen; + + extInfoLen = sizeof (EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11N_DRAFT3 + if ((pAd->CommonCfg.bBssCoexEnable == TRUE) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && (pAd->CommonCfg.Channel <= 14) + ) { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#ifdef DOT11V_WNM_SUPPORT + if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd)) + extCapInfo.BssTransitionManmt = + pAd->MlmeAux.ExtCapInfo.BssTransitionManmt; + if (IS_WNMDMS_SUPPORT(pAd)) + extCapInfo.DMSSupport = + pAd->MlmeAux.ExtCapInfo.DMSSupport; +#endif /* DOT11V_WNM_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (IS_TDLS_SUPPORT(pAd)) + { + extCapInfo.UAPSDBufSTASupport = 1; + if (pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp) + { + extCapInfo.TDLSChSwitchSupport = 1; + } + else + extCapInfo.TDLSChSwitchSupport = 0; + + extCapInfo.TDLSSupport = 1; + } +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + extCapInfo.operating_mode_notification = 1; +#endif /* DOT11_VHT_AC */ + + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) */ + + /* add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION */ + /* Case I: (Aggregation + Piggy-Back) */ + /* 1. user enable aggregation, AND */ + /* 2. Mac support piggy-back */ + /* 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON */ + /* Case II: (Aggregation) */ + /* 1. user enable aggregation, AND */ + /* 2. AP annouces it's AGGREGATION-capable in BEACON */ + if (pAd->CommonCfg.bAggregationCapable) { + if ((pAd->CommonCfg.bPiggyBackCapable) + && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } else { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 9, + RalinkIe, END_OF_ARGS); + FrameLen += TmpLen; + } + + if (pAd->MlmeAux.APEdcaParm.bValid) { + if (pAd->StaCfg.UapsdInfo.bAPSDCapable + && pAd->MlmeAux.APEdcaParm.bAPSDCapable) { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR) & QosInfo; + } else { + /* The Parameter Set Count is set to 0 in the association request frames */ + /* WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); */ + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], END_OF_ARGS); + FrameLen += tmp; + } + + /* + Let WPA(#221) Element ID on the end of this association frame. + Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp. + For example: Put Vendor Specific IE on the front of WPA IE. + This happens on AP (Model No:Linksys WRK54G) + */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) +#ifdef WAPI_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) +#ifdef WSC_STA_SUPPORT + && ((pAd->StaCfg.WscControl.WscConfMode == WSC_DISABLE) || + ((pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + !(pAd->StaCfg.WscControl.bWscTrigger + ))) +#endif /* WSC_STA_SUPPORT */ + ) { + UCHAR RSNIe = IE_WPA; + + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) + || (wdev->AuthMode == + Ndis802_11AuthModeWPA2)) { + RSNIe = IE_WPA2; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) { + RSNIe = IE_WAPI; + } +#endif /* WAPI_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant == FALSE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, BSS0); + + /* Check for WPA PMK cache list */ + if (wdev->AuthMode == Ndis802_11AuthModeWPA2) { + INT idx; + BOOLEAN FoundPMK = FALSE; + /* Search chched PMKID, append it if existed */ + for (idx = 0; idx < PMKID_NO; idx++) { + if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6)) { + FoundPMK = TRUE; + break; + } + } + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + When AuthMode is WPA2-Enterprise and AP reboot or STA lost AP, + AP would not do PMK cache with STA after STA re-connect to AP again. + In this case, driver doesn't need to send PMKID to AP and WpaSupplicant. + */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) + && (NdisEqualMemory(pAd->MlmeAux.Bssid, pAd->CommonCfg.LastBssid, MAC_ADDR_LEN))) { + FoundPMK = FALSE; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + if (FoundPMK) { + /* Set PMK number */ + *(PUSHORT) & pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1; + NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], + &pAd->StaCfg.SavedPMK[idx].PMKID, 16); + pAd->StaCfg.RSNIE_Len += 18; + } + } + } +#ifdef WPA_SUPPLICANT_SUPPORT + /* + Can not use SIOCSIWGENIE definition, it is used in wireless.h + We will not see the definition in MODULE. + The definition can be saw in UTIL and NETIF. + */ +/* #ifdef SIOCSIWGENIE */ + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) + && (pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant == TRUE)) { + ; + } else +/* #endif */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + Can not use SIOCSIWGENIE definition, it is used in wireless.h + We will not see the definition in MODULE. + The definition can be saw in UTIL and NETIF. + */ +/* #ifdef SIOCSIWGENIE */ + if (((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x7F) != + WPA_SUPPLICANT_ENABLE) + || (pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant == FALSE)) +/* #endif */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + /* Append Variable IE */ + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1); + VarIesOffset += 1; + + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + VarIesOffset += pAd->StaCfg.RSNIE_Len; + + /* Set Variable IEs Length */ + pAd->StaCfg.ReqVarIELen = VarIesOffset; + } + } +#ifdef WPA_SUPPLICANT_SUPPORT + /* + Can not use SIOCSIWGENIE definition, it is used in wireless.h + We will not see the definition in MODULE. + The definition can be saw in UTIL and NETIF. + */ +/* #ifdef SIOCSIWGENIE */ + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) && + (pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant == TRUE)) { + ULONG TmpWpaAssocIeLen = 0; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpWpaAssocIeLen, + pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen, + pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe, END_OF_ARGS); + + FrameLen += TmpWpaAssocIeLen; + + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe, + pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen); + VarIesOffset += pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen; + + /* Set Variable IEs Length */ + pAd->StaCfg.ReqVarIELen = VarIesOffset; + } +/* #endif */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + /* Add WSC IE if we are connecting to WSC AP */ + if ((pAd->StaCfg.WscControl.WscEnAssociateIE) && + (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger + )) { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + os_alloc_mem(pAd, (UCHAR **) & pWscBuf, 512); + if (pWscBuf != NULL) { + NdisZeroMemory(pWscBuf, 512); + WscBuildAssocReqIE(&pAd->StaCfg.WscControl, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(pOutBuffer + FrameLen, + &WscTmpLen, WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } else + DBGPRINT(RT_DEBUG_WARN, + ("%s:: WscBuf Allocate failed!\n", + __FUNCTION__)); + } +#endif /* WSC_STA_SUPPORT */ +#ifdef WFD_SUPPORT +#ifdef RT_CFG80211_SUPPORT + if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) + { + ULONG WfdIeLen, WfdIeBitmap; + PUCHAR ptr; + + ptr = pOutBuffer + FrameLen; + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO); + WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &WfdIeLen); + FrameLen += WfdIeLen; + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* WFD_SUPPORT */ + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout); + pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, + &Status, 0); + } + +} + +/* + ========================================================================== + Description: + mlme reassoc req handling procedure + Parameters: + Elem - + Pre: + -# SSID (Adapter->StaCfg.ssid[]) + -# BSSID (AP address, Adapter->StaCfg.bssid) + -# Supported rates (Adapter->StaCfg.supported_rates[]) + -# Supported rates length (Adapter->StaCfg.supported_rates_len) + -# Tx power (Adapter->StaCfg.tx_power) + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + ULONG Idx; + UCHAR ApAddr[6]; + HEADER_802_11 ReassocHdr; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT CapabilityInfo, ListenIntv; + ULONG Timeout; + ULONG FrameLen = 0; + BOOLEAN TimerCancelled; + NDIS_STATUS NStatus; + ULONG tmp; + PUCHAR pOutBuffer = NULL; + USHORT Status; + + /* Block all authentication request durning WPA block period */ + if (pAd->StaCfg.bBlockAssoc == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Block ReAssoc request durning WPA block period!\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status, 0); + } + /* the parameters are the same as the association */ + else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + /*for dhcp,issue ,wpa_supplicant ioctl too fast , at link_up, it will add key before driver remove key */ + RTMPWPARemoveAllKeys(pAd); + + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeReassocReqAction() allocate memory failed \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_REASSOC_CONF, 2, &Status, 0); + return; + } + + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); + + /* make frame, use bssid as the AP address?? */ + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Send RE-ASSOC request...\n")); + MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, + pAd->CurrentAddress, + ApAddr); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), + &ReassocHdr, 2, &CapabilityInfo, 2, + &ListenIntv, MAC_ADDR_LEN, ApAddr, 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1, + &SupRateIe, 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRate, END_OF_ARGS); + FrameLen += tmp; + } +#ifdef DOT11R_FT_SUPPORT + /* Add MDIE if we are connection to DOT11R AP */ + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->MlmeAux.MdIeInfo.Len) + { + PUINT8 mdie_ptr; + UINT mdie_len = 0; + + /* MDIE */ + mdie_ptr = pOutBuffer + FrameLen; + mdie_len = 5; + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, + pAd->MlmeAux.MdIeInfo.MdId, + pAd->MlmeAux.MdIeInfo.FtCapPlc); + + /* Indicate the FT procedure */ + if (pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain && + pAd->StaCfg.WepStatus != Ndis802_11WEPDisabled) { + UINT8 FtIeLen = 0; + PMAC_TABLE_ENTRY pEntry; + FT_MIC_CTR_FIELD mic_ctr; + PUINT8 rsnie_ptr; + UINT rsnie_len = 0; + PUINT8 ftie_ptr; + UINT ftie_len = 0; + UINT8 ft_mic[16]; + + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + + /* Insert RSNIE[PMK-R1-NAME] */ + rsnie_ptr = pOutBuffer + FrameLen; + rsnie_len = 2 + pAd->StaCfg.RSNIE_Len + 2 + LEN_PMK_NAME; + + RTMPInsertRSNIE(pOutBuffer + FrameLen, + &FrameLen, + pAd->StaCfg.RSN_IE, + pAd->StaCfg.RSNIE_Len, + pEntry->FT_PMK_R1_NAME, + LEN_PMK_NAME); + + /* Insert FTIE[MIC, ANONCE, SNONCE, R1KH-ID, R0KH-ID] */ + FtIeLen = sizeof (FT_FTIE) + + (2 + MAC_ADDR_LEN) + + (2 + pAd->StaCfg.Dot11RCommInfo.R0khIdLen); + + ftie_ptr = pOutBuffer + FrameLen; + ftie_len = (2 + FtIeLen); + + mic_ctr.field.IECnt = 3; + NdisZeroMemory(ft_mic, 16); + FT_InsertFTIE(pAd, + pOutBuffer + FrameLen, + &FrameLen, + FtIeLen, + mic_ctr, + ft_mic, + pEntry->ANonce, pEntry->SNonce); + + FT_FTIE_InsertKhIdSubIE(pAd, + pOutBuffer + FrameLen, + &FrameLen, + FT_R1KH_ID, + pAd->MlmeAux.Bssid, + MAC_ADDR_LEN); + + FT_FTIE_InsertKhIdSubIE(pAd, + pOutBuffer + FrameLen, + &FrameLen, + FT_R0KH_ID, + &pAd->StaCfg.Dot11RCommInfo.R0khId[0], + pAd->StaCfg.Dot11RCommInfo.R0khIdLen); + + /* RIC-Request */ + if (pAd->MlmeAux.MdIeInfo.FtCapPlc.field.RsrReqCap + && pAd->StaCfg.Dot11RCommInfo.bSupportResource) { + } + + /* Calculate MIC */ + if (mic_ctr.field.IECnt) { + UINT8 ft_mic[16]; + PFT_FTIE pFtIe; + + FT_CalculateMIC(pAd->CurrentAddress, + pAd->MlmeAux.Bssid, + pEntry->PTK, + 5, + rsnie_ptr, + rsnie_len, + mdie_ptr, + mdie_len, + ftie_ptr, + ftie_len, + NULL, 0, ft_mic); + + /* Update the MIC field of FTIE */ + pFtIe = (PFT_FTIE) (ftie_ptr + 2); + NdisMoveMemory(pFtIe->MIC, ft_mic, 16); + } + + } + + } +#endif /* DOT11R_FT_SUPPORT */ + + if (pAd->MlmeAux.APEdcaParm.bValid) { + if (pAd->StaCfg.UapsdInfo.bAPSDCapable + && pAd->MlmeAux.APEdcaParm.bAPSDCapable) { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof (QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> MaxSPLength = %d!\n", QosInfo.MaxSPLength)); + WmeIe[8] |= *(PUCHAR) & QosInfo; + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], END_OF_ARGS); + FrameLen += tmp; +#ifdef DOT11_N_SUPPORT + /* HT */ + if ((pAd->MlmeAux.HtCapabilityLen > 0) + && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { + ULONG TmpLen; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + PHT_CAPABILITY_IE pHtCapability; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + NdisZeroMemory(&HtCapabilityTmp, sizeof (HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen); + *(USHORT *) (&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.HtCapInfo)); + *(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo)); + pHtCapability = &HtCapabilityTmp; +#else + pHtCapability = &pAd->MlmeAux.HtCapability; +#endif + + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) { + HtLen = SIZE_HT_CAP_IE + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &WpaIe, 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, + pHtCapability, END_OF_ARGS); + } else { + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &HtCapIe, 1, + &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, + pHtCapability, END_OF_ARGS); + } + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->MlmeAux.Channel > 14) && + (pAd->MlmeAux.vht_cap_len) + ) + { +#ifdef VHT_TXBF_SUPPORT + //Disable beamform capability in Associate Request with 3x3 AP to avoid throughput drop issue + // MT76x2 only supports up to 2x2 sounding feedback + Idx = BssTableSearch(&pAd->ScanTab, pAd->MlmeAux.Bssid, pAd->MlmeAux.Channel); + if (Idx != BSS_NOT_FOUND) + { + pAd->BeaconSndDimensionFlag = 0; + if (pAd->ScanTab.BssEntry[Idx].vht_cap_ie.vht_cap.num_snd_dimension >=2 ) + { + pAd->BeaconSndDimensionFlag = 1; + } + } +#endif /* VHT_TXBF_SUPPORT */ + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_ASSOC_REQ); + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + } // end of pAd->MlmeAux.APEdcaParm.bValid + + if (FALSE +#ifdef DOT11V_WNM_SUPPORT + || (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd) || IS_WNMDMS_SUPPORT(pAd)) +#endif /* DOT11V_WNM_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || IS_TDLS_SUPPORT(pAd) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + ) + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen; + + NdisZeroMemory(&extCapInfo, sizeof (EXT_CAP_INFO_ELEMENT)); + extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + +#ifdef DOT11V_WNM_SUPPORT + if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd)) + extCapInfo.BssTransitionManmt = + pAd->MlmeAux.ExtCapInfo.BssTransitionManmt; + if (IS_WNMDMS_SUPPORT(pAd)) + extCapInfo.DMSSupport = + pAd->MlmeAux.ExtCapInfo.DMSSupport; +#endif /* DOT11V_WNM_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (IS_TDLS_SUPPORT(pAd)) + { + extCapInfo.UAPSDBufSTASupport = 1; + if (pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp) + extCapInfo.TDLSChSwitchSupport = 1; + else + extCapInfo.TDLSChSwitchSupport = 0; + + extCapInfo.TDLSSupport = 1; + } +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &ExtCapIe, + 1 &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION */ + /* Case I: (Aggregation + Piggy-Back) */ + /* 1. user enable aggregation, AND */ + /* 2. Mac support piggy-back */ + /* 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON */ + /* Case II: (Aggregation) */ + /* 1. user enable aggregation, AND */ + /* 2. AP annouces it's AGGREGATION-capable in BEACON */ + if (pAd->CommonCfg.bAggregationCapable) { + if ((pAd->CommonCfg.bPiggyBackCapable) + && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } else { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 9, + RalinkIe, END_OF_ARGS); + FrameLen += TmpLen; + } +#ifdef WFD_SUPPORT +#ifdef RT_CFG80211_SUPPORT + if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) + { + ULONG WfdIeLen, WfdIeBitmap; + PUCHAR ptr; + + ptr = pOutBuffer + FrameLen; + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO); + WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &WfdIeLen); + FrameLen += WfdIeLen; + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* WFD_SUPPORT */ + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout * 2); /* in mSec */ + pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, + &Status, 0); + } +} + +/* + ========================================================================== + Description: + Upper layer issues disassoc request + Parameters: + Elem - + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_DISASSOC_REQ_STRUCT pDisassocReq; + HEADER_802_11 DisassocHdr; + PHEADER_802_11 pDisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + BOOLEAN TimerCancelled; + ULONG Timeout = 500; + USHORT Status; + + +#ifdef QOS_DLS_SUPPORT + /* send DLS-TEAR_DOWN message, */ + if (pAd->CommonCfg.bDLSCapable) { + UCHAR i; + + /* tear down local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + + /* tear down peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + } +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + if (IS_TDLS_SUPPORT(pAd)) + { + if (pAd->StaCfg.bRadio == TRUE) + { + TDLS_LinkTearDown(pAd, TRUE); + } + else + { + UCHAR idx; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + + // tear down tdls table entry + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + if (pTDLS->Valid && (pTDLS->Status >= TDLS_MODE_CONNECTED)) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + pTDLS->Token = 0; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + if (!VALID_WCID(pTDLS->MacTabMatchWCID)) + return; + + MacTableDeleteEntry(pAd,pTDLS->MacTabMatchWCID, pTDLS->MacAddr); + } + else if (pTDLS->Valid) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + pTDLS->Token = 0; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + } + } + } + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + /* skip sanity check */ + pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT) (Elem->Msg); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, + &Status, 0); + return; + } + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pAd->StaCfg.AuthMode, + BSS0, pDisassocReq->Addr, WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled); + + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n", + PRINT_MAC(pDisassocReq->Addr), pDisassocReq->Reason)); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, + pAd->CurrentAddress, + pDisassocReq->Addr); /* patch peap ttls switching issue */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &DisassocHdr, + 2, &pDisassocReq->Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + /* To patch Instance and Buffalo(N) AP */ + /* Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine */ + /* Therefore, we send both of them. */ + pDisassocHdr = (PHEADER_802_11) pOutBuffer; + pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; + COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr); + + RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */ + pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP; + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) { + /*send disassociate event to wpa_supplicant */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, + RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + + +/* mark here because linkdown also call this function */ + + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, NULL, BSS0, 0); + +} + +/* + ========================================================================== + Description: + peer sends assoc rsp back + Parameters: + Elme - MLME message containing the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo, Status, Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + BOOLEAN TimerCancelled; + UCHAR CkipFlag; + EDCA_PARM EdcaParm; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen = 0; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + MAC_TABLE_ENTRY *pEntry; + IE_LISTS *ie_list = NULL; + + + os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(IE_LISTS)); + if (ie_list == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("%s():mem alloc failed!\n", __FUNCTION__)); + return; + } + NdisZeroMemory((UCHAR *)ie_list, sizeof(IE_LISTS)); + + if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, + Addr2, &CapabilityInfo, &Status, &Aid, SupRate, + &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, + &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, + &NewExtChannelOffset, &EdcaParm, &ExtCapInfo, + &CkipFlag, ie_list)) + { + /* The frame is for me ? */ + if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s():ASSOC - receive ASSOC_RSP to me (status=%d)\n", __FUNCTION__, Status)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, + ("%s():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n", + __FUNCTION__, Elem->Wcid, + pAd->MacTab.Content[BSSID_WCID].AMsduSize, + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); +#endif /* DOT11_N_SUPPORT */ + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && pAd->MlmeAux.FtIeInfo.Len) { + FT_FTIE_INFO *pFtInfo = &pAd->MlmeAux.FtIeInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():ASSOC - FTIE\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_TRACE, + ("MIC Countrol IECnt: %x\n", pFtInfo->MICCtr.field.IECnt)); + hex_dump("ANonce", pFtInfo->ANonce, 32); + hex_dump("SNonce", pFtInfo->SNonce, 32); + if (pFtInfo->R1khIdLen) + hex_dump("R1KH-ID", pFtInfo->R1khId, pFtInfo->R1khIdLen); + if (pFtInfo->R0khIdLen) + hex_dump("R0KH-ID", pFtInfo->R0khId, pFtInfo->R0khIdLen); + if ((pAd->StaCfg.Dot11RCommInfo.R0khIdLen != pFtInfo->R0khIdLen) + || (!NdisEqualMemory(pFtInfo->R0khId, pFtInfo->R0khId, + pAd->StaCfg.Dot11RCommInfo.R0khIdLen))) + { + if (pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain) + Status = MLME_INVALID_FORMAT; + } + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + if (ExtCapInfo.BssTransitionManmt == 1) + pAd->StaCfg.bBSSMantAPSupport = TRUE; + if (ExtCapInfo.DMSSupport == 1) + pAd->StaCfg.bDMSAPSupport = TRUE; +#endif /* DOT11V_WNM_SUPPORT */ + + if (Status == MLME_SUCCESS) { + UCHAR MaxSupportedRateIn500Kbps = 0; + + /* + In roaming case, LinkDown wouldn't be invoked. + For preventing finding MacTable Hash index malfunction, + we need to do MacTableDeleteEntry here. + */ + pEntry = MacTableLookup(pAd, pAd->CommonCfg.Bssid); + if (pEntry) + { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + pEntry = NULL; + } + + MaxSupportedRateIn500Kbps = dot11_max_sup_rate(SupRateLen, &SupRate[0], + ExtRateLen, &ExtRate[0]); + /* go to procedure listed on page 376 */ + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &EdcaParm, + ie_list, + &HtCapability, HtCapabilityLen, + &AddHtInfo); + + StaUpdateMacTableEntry(pAd, + &pAd->MacTab.Content[BSSID_WCID], + MaxSupportedRateIn500Kbps, + &HtCapability, + HtCapabilityLen, &AddHtInfo, + AddHtInfoLen, + ie_list, + CapabilityInfo); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + &pAd->MacTab.Content[BSSID_WCID], + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len, + &ie_list->vht_cap, +#endif /* DOT11_VHT_AC */ + &HtCapability, + HtCapabilityLen); + +#ifdef DOT11W_PMF_SUPPORT + if (pAd->StaCfg.BssType == BSS_INFRA) + { + if (pAd->MlmeAux.BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) { + BSS_ENTRY *pInBss = NULL; + + pInBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pAd->MlmeAux.BssIdx]; + if (CLIENT_STATUS_TEST_FLAG(pInBss, fCLIENT_STATUS_PMF_CAPABLE)) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_PMF_CAPABLE); + if (CLIENT_STATUS_TEST_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256)) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_USE_SHA256); + } + } +#endif /* DOT11W_PMF_SUPPORT */ + } + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status, 0); + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + if (Status == MLME_SUCCESS) + { + PFRAME_802_11 pFrame = (PFRAME_802_11) (Elem->Msg); + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + UINT32 ie_len = 0; + /* Moved to after LinkUp() */ + /* + RT_CFG80211_CONN_RESULT_INFORM(pAd, pAd->MlmeAux.Bssid, + pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen, + &pFrame->Octet[6], + Elem->MsgLen - 6 - sizeof (HEADER_802_11), + TRUE); + */ + /* store the assoc IE */ + ie_len = (UINT32) (Elem->MsgLen - 6 - sizeof (HEADER_802_11)); + if (pFrame && ie_len > 0) + { + if (cfg80211_ctrl->pAssocRspIe) + os_free_mem(NULL, cfg80211_ctrl->pAssocRspIe); + cfg80211_ctrl->pAssocRspIe = NULL; + cfg80211_ctrl->assocRspIeLen = 0; + os_alloc_mem(pAd, (UCHAR **)&(cfg80211_ctrl->pAssocRspIe), ie_len); + if (cfg80211_ctrl->pAssocRspIe) + { + NdisMoveMemory(cfg80211_ctrl->pAssocRspIe, + &pFrame->Octet[6], ie_len); + cfg80211_ctrl->assocRspIeLen = (UINT32)ie_len; + CFG80211DBG(RT_DEBUG_TRACE, ("%s: AssocRsp IE Len = %u\n", __FUNCTION__, + cfg80211_ctrl->assocRspIeLen)); + } + else + { + CFG80211DBG(RT_DEBUG_ERROR, ("ERROR !!! %s:malloc failed!\n", __FUNCTION__)); + } + } + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - %s() sanity check fail\n", __FUNCTION__)); + } + + if (ie_list != NULL) + os_free_mem(NULL, ie_list); +} + + +/* + ========================================================================== + Description: + peer sends reassoc rsp + Parametrs: + Elem - MLME message cntaining the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerReassocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo; + USHORT Status; + USHORT Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR CkipFlag; + BOOLEAN TimerCancelled; + EDCA_PARM EdcaParm; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + IE_LISTS *ie_list = NULL; + + os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(IE_LISTS)); + if (ie_list == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("%s():mem alloc failed!\n", __FUNCTION__)); + return; + } + NdisZeroMemory((UCHAR *)ie_list, sizeof(IE_LISTS)); + + if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, + &CapabilityInfo, &Status, &Aid, SupRate, + &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, + &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, + &NewExtChannelOffset, &EdcaParm, &ExtCapInfo, + &CkipFlag, ie_list)) { + if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) { /* The frame is for me ? */ + DBGPRINT(RT_DEBUG_TRACE, + ("REASSOC - receive REASSOC_RSP to me (status=%d)\n", Status)); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, + &TimerCancelled); + + if (Status == MLME_SUCCESS) + { + UCHAR MaxSupportedRateIn500Kbps = 0; + PMAC_TABLE_ENTRY pEntry = NULL; + + /* + In roaming case, LinkDown wouldn't be invoked. + For preventing finding MacTable Hash index malfunction, + we need to do MacTableDeleteEntry here. + */ + pEntry = MacTableLookup(pAd, pAd->CommonCfg.Bssid); + if (pEntry) + { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + pEntry = NULL; + } + + MaxSupportedRateIn500Kbps = dot11_max_sup_rate(SupRateLen, &SupRate[0], ExtRateLen, &ExtRate[0]); + + + /* go to procedure listed on page 376 */ + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &EdcaParm, + ie_list, + &HtCapability, HtCapabilityLen, + &AddHtInfo); + + StaUpdateMacTableEntry(pAd, + &pAd->MacTab.Content[BSSID_WCID], + MaxSupportedRateIn500Kbps, + &HtCapability, + HtCapabilityLen, &AddHtInfo, + AddHtInfoLen, + ie_list, + CapabilityInfo); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + &pAd->MacTab.Content[BSSID_WCID], + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len, + &ie_list->vht_cap, +#endif /* DOT11_VHT_AC */ + &HtCapability, + HtCapabilityLen); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) { + SendAssocIEsToWpaSupplicant(pAd->net_dev, + pAd->StaCfg.ReqVarIEs, + pAd->StaCfg.ReqVarIELen); + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + RT_ASSOC_EVENT_FLAG, + NULL, NULL, 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + wext_notify_event_assoc(pAd->net_dev, + pAd->StaCfg.ReqVarIEs, + pAd->StaCfg.ReqVarIELen); + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CGIWAP, + -1, + &pAd->MlmeAux.Bssid[0], NULL, + 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + + } +#ifdef DOT11V_WNM_SUPPORT + if (ExtCapInfo.BssTransitionManmt == 1) + pAd->StaCfg.bBSSMantAPSupport = TRUE; + if (ExtCapInfo.DMSSupport == 1) + pAd->StaCfg.bDMSAPSupport = TRUE; +#endif /* DOT11V_WNM_SUPPORT */ + + /* CkipFlag is no use for reassociate */ + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status, 0); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("REASSOC - %s() sanity check fail\n", __FUNCTION__)); + } + + if (ie_list) + os_free_mem(pAd, ie_list); + +} + +/* + ========================================================================== + Description: + procedures on IEEE 802.11/1999 p.376 + Parametrs: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN IE_LISTS *ie_list, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ /* AP might use this additional ht info IE */ + ULONG Idx; + MAC_TABLE_ENTRY *pEntry; + + pAd->MlmeAux.BssType = BSS_INFRA; + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2); + pAd->MlmeAux.Aid = Aid; + pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + +#ifdef DOT11_N_SUPPORT + /* Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on. */ + if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) { + pEdcaParm->bValid = TRUE; + pEdcaParm->Aifsn[0] = 3; + pEdcaParm->Aifsn[1] = 7; + pEdcaParm->Aifsn[2] = 2; + pEdcaParm->Aifsn[3] = 2; + + pEdcaParm->Cwmin[0] = 4; + pEdcaParm->Cwmin[1] = 4; + pEdcaParm->Cwmin[2] = 3; + pEdcaParm->Cwmin[3] = 2; + + pEdcaParm->Cwmax[0] = 10; + pEdcaParm->Cwmax[1] = 10; + pEdcaParm->Cwmax[2] = 4; + pEdcaParm->Cwmax[3] = 3; + + pEdcaParm->Txop[0] = 0; + pEdcaParm->Txop[1] = 0; + pEdcaParm->Txop[2] = 96; + pEdcaParm->Txop[3] = 48; + + } +#endif /* DOT11_N_SUPPORT */ + + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof (EDCA_PARM)); + + /* filter out un-supported rates */ + pAd->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + + /* filter out un-supported rates */ + pAd->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0) { + RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); + } + DBGPRINT(RT_DEBUG_TRACE, + ("%s():=>AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", + __FUNCTION__, pEntry->AMsduSize, pEntry->ClientStatusFlags)); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s():=>(Mmps=%d, AmsduSize=%d, )\n", + __FUNCTION__, pEntry->MmpsMode, pEntry->AMsduSize)); + +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len > 0 && ie_list->vht_op_len > 0) { + RTMPCheckVht(pAd, BSSID_WCID, &ie_list->vht_cap, &ie_list->vht_op); + } +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + /* Set New WPA information */ + Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel); + if (Idx == BSS_NOT_FOUND) { + DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n")); + } else { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + /* Init variable */ + pEntry->RSNIE_Len = 0; + NdisZeroMemory(pEntry->RSN_IE, MAX_LEN_OF_RSNIE); + + /* Store appropriate RSN_IE for WPA SM negotiation later */ + if ((wdev->AuthMode >= Ndis802_11AuthModeWPA) + && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) { + PUCHAR pVIE; + USHORT len; + PEID_STRUCT pEid; + + pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs; + len = pAd->ScanTab.BssEntry[Idx].VarIELen; + +#ifdef PCIE_PS_SUPPORT + /* Don't allow to go to sleep mode if authmode is WPA-related. */ + /*This can make Authentication process more smoothly. */ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ + while (len > 0) { + pEid = (PEID_STRUCT) pVIE; + /* For WPA/WPAPSK */ + if ((pEid->Eid == IE_WPA) + && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && (wdev->AuthMode == Ndis802_11AuthModeWPA + || wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("%s():=> Store RSN_IE for WPA SM negotiation\n", __FUNCTION__)); + } + /* For WPA2/WPA2PSK */ + else if ((pEid->Eid == IE_RSN) + && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + && (wdev->AuthMode == Ndis802_11AuthModeWPA2 + || wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("%s():=> Store RSN_IE for WPA2 SM negotiation\n", __FUNCTION__)); + } +#ifdef WAPI_SUPPORT + /* For WAPI */ + else if ((pEid->Eid == IE_WAPI) + && (NdisEqualMemory(pEid->Octet + 4, WAPI_OUI, 3)) + && (wdev->AuthMode == Ndis802_11AuthModeWAICERT + || wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("%s():=> Store RSN_IE for WAPI SM negotiation\n", __FUNCTION__)); + } +#endif /* WAPI_SUPPORT */ + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain && + (pAd->MlmeAux.FtIeInfo.GtkLen != 0)) { + /* extract GTK related information */ + FT_ExtractGTKSubIe(pAd, + &pAd->MacTab.Content[MCAST_WCID], + &pAd->MlmeAux.FtIeInfo); + + } +#endif /* DOT11R_FT_SUPPORT */ + + } + + if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("%s():=> no RSN_IE\n", __FUNCTION__)); + } else { + hex_dump("RSN_IE", pEntry->RSN_IE, pEntry->RSNIE_Len); + } + } +} + +/* + ========================================================================== + Description: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDisassocAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n")); + if (PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerDisassocAction() Reason = %d\n", + Reason)); + if (INFRA_ON(pAd) + && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) { + + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, NULL, + BSS0, 0); + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pAd->StaCfg.AuthMode, + BSS0, + Addr2, WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + + /* + It is possible that AP sends dis-assoc frame(PeerDisassocAction) to STA + after driver enqueue MT2_MLME_DISASSOC_REQ (MlmeDisassocReqAction) + and set CntlMachine.CurrState = CNTL_WAIT_DISASSOC. + DisassocTimer is useless because AssocMachine.CurrState will set to ASSOC_IDLE here. + Therefore, we need to check CntlMachine.CurrState here and enqueue MT2_DISASSOC_CONF to + reset CntlMachine.CurrState to CNTL_IDLE state again. + */ + if (pAd->Mlme.CntlMachine.CurrState == + CNTL_WAIT_DISASSOC) { + USHORT Status; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_DISASSOC_CONF, 2, &Status, 0); + } else + LinkDown(pAd, TRUE); + + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) { + /*send disassociate event to wpa_supplicant */ + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + RT_DISASSOC_EVENT_FLAG, + NULL, NULL, 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ +/* mark here because linkdown also call this function */ + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerDisassocAction() sanity check fail\n")); + } + +} + +/* + ========================================================================== + Description: + what the state machine will do after assoc timeout + Parameters: + Elme - + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status, + 0); +} + +/* + ========================================================================== + Description: + what the state machine will do after reassoc timeout + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ReassocTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status, + 0); +} + +/* + ========================================================================== + Description: + what the state machine will do after disassoc timeout + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID DisassocTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status, + 0); +} + +VOID InvalidStateWhenAssoc(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status, + 0); +} + +VOID InvalidStateWhenReassoc(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status, + 0); +} + +VOID InvalidStateWhenDisassociate(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status, + 0); +} + +/* + ========================================================================== + Description: + right part of IEEE 802.11/1999 page 374 + Note: + This event should never cause ASSOC state machine perform state + transition, and has no relationship with CNTL machine. So we separate + this routine as a service outside of ASSOC state transition table. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID Cls3errAction(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + HEADER_802_11 DisassocHdr; + PHEADER_802_11 pDisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + USHORT Reason = REASON_CLS3ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Class 3 Error, Send DISASSOC frame\n")); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, + pAd->CurrentAddress, + pAd->CommonCfg.Bssid); /* patch peap ttls switching issue */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &DisassocHdr, + 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + /* To patch Instance and Buffalo(N) AP */ + /* Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine */ + /* Therefore, we send both of them. */ + pDisassocHdr = (PHEADER_802_11) pOutBuffer; + pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DisassocReason = REASON_CLS3ERR; + COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr); +} + + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID AssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, + (STATE_MACHINE_FUNC) Drop, ASSOC_IDLE, + ASSOC_MACHINE_BASE); + + /* first column */ + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) MlmeAssocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) MlmeReassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) MlmeDisassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + + /* second column */ + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAssoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenReassoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) + InvalidStateWhenDisassociate); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, + (STATE_MACHINE_FUNC) PeerAssocRspAction); + /* */ + /* Patch 3Com AP MOde:3CRWE454G72 */ + /* We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp. */ + /* */ + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, + (STATE_MACHINE_FUNC) PeerAssocRspAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, + (STATE_MACHINE_FUNC) AssocTimeoutAction); + + /* third column */ + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAssoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenReassoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) + InvalidStateWhenDisassociate); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, + (STATE_MACHINE_FUNC) PeerReassocRspAction); + /* */ + /* Patch, AP doesn't send Reassociate Rsp frame to Station. */ + /* */ + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, + (STATE_MACHINE_FUNC) PeerReassocRspAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, + (STATE_MACHINE_FUNC) ReassocTimeoutAction); + + /* fourth column */ + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAssoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenReassoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) + InvalidStateWhenDisassociate); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, + (STATE_MACHINE_FUNC) DisassocTimeoutAction); + + /* initialize the timer */ + RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, + GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, + GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, + GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE); +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/auth.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/auth.c new file mode 100644 index 000000000..e4461d581 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/auth.c @@ -0,0 +1,564 @@ +/* + *************************************************************************** + * 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: + auth.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ------------------------------------------- +*/ +#include "rt_config.h" + + +/* + ========================================================================== + Description: + function to be executed at timer thread when auth timer expires + ========================================================================== + */ +VOID AuthTimeout( + 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__)); + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + /* send a de-auth to reset AP's state machine (Patch AP-Dir635) */ + if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2) + Cls2errAction(pAd, pAd->MlmeAux.Bssid); + + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeAuthReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + if (AUTH_ReqSend(pAd, Elem, &pAd->MlmeAux.AuthTimer, "AUTH", 1, NULL, 0)) + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; + else { + USHORT Status; + + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAuthRspAtSeq2Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM * Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Seq, Status, RemoteStatus, Alg; + UCHAR iv_hdr[4]; + UCHAR *ChlgText = NULL; + UCHAR *CyperChlgText = NULL; + ULONG c_len = 0; + HEADER_802_11 AuthHdr; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Status2; + UCHAR ChallengeIe = IE_CHALLENGE_TEXT; + UCHAR len_challengeText = CIPHER_TEXT_LEN; + + os_alloc_mem(NULL, (UCHAR **) & ChlgText, CIPHER_TEXT_LEN); + if (ChlgText == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc mem fail\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, (UCHAR **) & CyperChlgText, CIPHER_TEXT_LEN + 8 + 8); + if (CyperChlgText == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: CyperChlgText Allocate memory fail!!!\n", + __FUNCTION__)); + os_free_mem(NULL, ChlgText); + return; + } + + if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (PCHAR)ChlgText)) { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", + Alg, Status)); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + + if (Status == MLME_SUCCESS) { + /* Authentication Mode "LEAP" has allow for CCX 1.X */ + if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, &Status, + 0); + } else { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + /* 2. shared key, need to be challenged */ + Seq++; + RemoteStatus = MLME_SUCCESS; + + /* Get an unused nonpaged memory */ + NStatus = + MlmeAllocateMemory(pAd, + &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status2 = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, + &Status2, 0); + goto LabelOK; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Send AUTH request seq#3...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, + SUBTYPE_AUTH, 0, Addr2, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + AuthHdr.FC.Wep = 1; + + /* TSC increment */ + INC_TX_TSC(pAd->SharedKey[BSS0][wdev->DefaultKeyId].TxTsc, LEN_WEP_TSC); + + /* Construct the 4-bytes WEP IV header */ + RTMPConstructWEPIVHdr(wdev->DefaultKeyId, + pAd->SharedKey[BSS0][wdev->DefaultKeyId].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, + &pAd->SharedKey[BSS0][wdev->DefaultKeyId], + CyperChlgText, c_len) == FALSE) { + MlmeFreeMemory(pAd, pOutBuffer); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status2 = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, + &Status2, 0); + 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, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; + } + } else { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, &Status, 0); + } + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - PeerAuthSanity() sanity check fail\n")); + } + + LabelOK: + if (ChlgText != NULL) + os_free_mem(NULL, ChlgText); + + if (CyperChlgText != NULL) + os_free_mem(NULL, CyperChlgText); + return; +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAuthRspAtSeq4Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Alg, Seq, Status; +/* CHAR ChlgText[CIPHER_TEXT_LEN]; */ + CHAR *ChlgText = NULL; + BOOLEAN TimerCancelled; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **) & ChlgText, CIPHER_TEXT_LEN); + if (ChlgText == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: ChlgText Allocate memory fail!!!\n", + __FUNCTION__)); + return; + } + + if (PeerAuthSanity + (pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, + ChlgText)) { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, + &TimerCancelled); + + if (Status != MLME_SUCCESS) { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + RTMPSendWirelessEvent(pAd, IW_SHARED_WEP_FAIL, + NULL, BSS0, 0); + } + + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, + 2, &Status, 0); + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n")); + } + + if (ChlgText != NULL) + os_free_mem(NULL, ChlgText); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDeauthReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_DEAUTH_REQ_STRUCT *pInfo; + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Status; + + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - MlmeDeauthReqAction() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, + &Status, 0); + return; + } +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pAd->StaCfg.AuthMode, + BSS0, pAd->MlmeAux.Bssid, WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Send DE-AUTH request (Reason=%d)...\n", + pInfo->Reason)); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), + &DeauthHdr, 2, &pInfo->Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DeauthReason = pInfo->Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status, + 0); + + /* send wireless event - for deauthentication */ + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, NULL, BSS0, 0); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AuthTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID InvalidStateWhenAuth(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", + pAd->Mlme.AuthMachine.CurrState)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); +} + + +/* + ========================================================================== + 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 + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID Cls2errAction(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Reason = REASON_CLS2ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Class 2 error, Send DEAUTH frame...\n")); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), + &DeauthHdr, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DeauthReason = Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr); +} + + +BOOLEAN AUTH_ReqSend( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem, + IN PRALINK_TIMER_STRUCT pAuthTimer, + IN PSTRING pSMName, + IN USHORT SeqNo, + IN PUCHAR pNewElement, + IN ULONG ElementLen) +{ + USHORT Alg, Seq, Status; + UCHAR Addr[6]; + ULONG Timeout; + HEADER_802_11 AuthHdr; + BOOLEAN TimerCancelled; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0, tmp = 0; + + /* Block all authentication request durning WPA block period */ + if (pAd->StaCfg.bBlockAssoc == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s - Block Auth request durning WPA block period!\n", + pSMName)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, + &Status, 0); + } + else if (MlmeAuthReqSanity(pAd, pElem->Msg, pElem->MsgLen, Addr, &Timeout, &Alg)) + { + /* reset timer */ + RTMPCancelTimer(pAuthTimer, &TimerCancelled); + + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); + pAd->MlmeAux.Alg = Alg; + Seq = SeqNo; + Status = MLME_SUCCESS; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", + pSMName, Alg)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, + 2, &Status, 0); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s - Send AUTH request seq#1 (Alg=%d)...\n", + pSMName, Alg)); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), + &AuthHdr, 2, &Alg, 2, &Seq, 2, &Status, + END_OF_ARGS); + + if (pNewElement && ElementLen) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + ElementLen, pNewElement, END_OF_ARGS); + FrameLen += tmp; + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(pAuthTimer, Timeout); + return TRUE; + } + else + { + DBGPRINT_ERR(("%s(): %s sanity check fail\n", __FUNCTION__, pSMName)); + return FALSE; + } + + return TRUE; +} + + +/* + ========================================================================== + 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 + + AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4 + MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth + MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action + MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action + + IRQL = PASSIVE_LEVEL + + ========================================================================== +*/ +void AuthStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, + (STATE_MACHINE_FUNC) Drop, AUTH_REQ_IDLE, + AUTH_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, + (STATE_MACHINE_FUNC) MlmeAuthReqAction); + + /* the second column */ + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, + (STATE_MACHINE_FUNC) PeerAuthRspAtSeq2Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, + (STATE_MACHINE_FUNC) AuthTimeoutAction); + + /* the third column */ + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, + (STATE_MACHINE_FUNC) PeerAuthRspAtSeq4Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, + (STATE_MACHINE_FUNC) AuthTimeoutAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, + GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE); +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/auth_rsp.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/auth_rsp.c new file mode 100644 index 000000000..adb1a511b --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/auth_rsp.c @@ -0,0 +1,213 @@ +/* + *************************************************************************** + * 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: + auth_rsp.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-10-1 copy from RT2560 +*/ +#include "rt_config.h" + +/* + ========================================================================== + Description: + authentication state machine init procedure + Parameters: + Sm - the state machine + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID AuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, + (STATE_MACHINE_FUNC) Drop, AUTH_RSP_IDLE, + AUTH_RSP_MACHINE_BASE); + + /* column 1 */ + StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, + (STATE_MACHINE_FUNC) PeerDeauthAction); + + /* column 2 */ + StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, + (STATE_MACHINE_FUNC) PeerDeauthAction); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID PeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status) +{ + HEADER_802_11 AuthHdr; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + + if (Reason != MLME_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n")); + return; + } + + /*Get an unused nonpaged memory */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), + &AuthHdr, 2, &Alg, 2, &Seq, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID PeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem) +{ + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + USHORT Reason; + BOOLEAN bDoIterate = FALSE; + + if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, Addr2, Addr3, &Reason)) { + if (INFRA_ON(pAd) + && (MAC_ADDR_EQUAL(Addr1, pAd->CurrentAddress) + || MAC_ADDR_EQUAL(Addr1, BROADCAST_ADDR)) + && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid) + && MAC_ADDR_EQUAL(Addr3, pAd->CommonCfg.Bssid) +#ifdef DOT11R_FT_SUPPORT + && ((pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain == FALSE) + || (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess == 0)) +#endif /* DOT11R_FT_SUPPORT */ + ) { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", + Reason)); + + if (Reason == REASON_4_WAY_TIMEOUT) + RTMPSendWirelessEvent(pAd, + IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, + NULL, 0, 0); + + if (Reason == REASON_GROUP_KEY_HS_TIMEOUT) + RTMPSendWirelessEvent(pAd, + IW_GROUP_HS_TIMEOUT_EVENT_FLAG, + NULL, 0, 0); + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + wdev->AuthMode, + BSS0, + Addr2, WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CGIWAP, -1, NULL, + NULL, 0); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + + /* send wireless event - for deauthentication */ + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, NULL, + BSS0, 0); + + + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + && (wdev->AuthMode == Ndis802_11AuthModeWPA2) + && (wdev->PortSecured == WPA_802_1X_PORT_SECURED)) + pAd->StaCfg.wpa_supplicant_info.bLostAp = TRUE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + /* + Some customer would set AP1 & AP2 same SSID, AuthMode & EncrypType but different WPAPSK, + therefore we need to do iterate here. + */ + if ((wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && + ((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) +#ifdef WSC_STA_SUPPORT + && (pAd->StaCfg.WscControl.WscState < WSC_STATE_LINK_UP) +#endif /* WSC_STA_SUPPORT */ + ) + bDoIterate = TRUE; + + LinkDown(pAd, TRUE); + + if (bDoIterate) { + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + + } +#ifdef ADHOC_WPA2PSK_SUPPORT + else if (ADHOC_ON(pAd) + && (MAC_ADDR_EQUAL(Addr1, pAd->CurrentAddress) + || MAC_ADDR_EQUAL(Addr1, BROADCAST_ADDR))) { + MAC_TABLE_ENTRY *pEntry; + + pEntry = MacTableLookup(pAd, Addr2); + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH_RSP - receive DE-AUTH from %02x:%02x:%02x:%02x:%02x:%02x \n", + PRINT_MAC(Addr2))); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH_RSP - PeerDeauthAction() sanity check fail\n")); + } +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/connect.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/connect.c new file mode 100644 index 000000000..c5a880f95 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/connect.c @@ -0,0 +1,3813 @@ +/* + *************************************************************************** + * 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: + connect.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-08-08 Major modification from RT2560 +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +UCHAR CipherSuiteWpaNoneTkip[] = { + 0x00, 0x50, 0xf2, 0x01, /* oui */ + 0x01, 0x00, /* Version */ + 0x00, 0x50, 0xf2, 0x02, /* Multicast */ + 0x01, 0x00, /* Number of unicast */ + 0x00, 0x50, 0xf2, 0x02, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x50, 0xf2, 0x00 /* authentication */ +}; +UCHAR CipherSuiteWpaNoneTkipLen = + (sizeof (CipherSuiteWpaNoneTkip) / sizeof (UCHAR)); + +UCHAR CipherSuiteWpaNoneAes[] = { + 0x00, 0x50, 0xf2, 0x01, /* oui */ + 0x01, 0x00, /* Version */ + 0x00, 0x50, 0xf2, 0x04, /* Multicast */ + 0x01, 0x00, /* Number of unicast */ + 0x00, 0x50, 0xf2, 0x04, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x50, 0xf2, 0x00 /* authentication */ +}; +UCHAR CipherSuiteWpaNoneAesLen = + (sizeof (CipherSuiteWpaNoneAes) / sizeof (UCHAR)); + +/* The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, */ +/* or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */ +/* All settings successfuly negotiated furing MLME state machines become final settings */ +/* and are copied to pAd->StaActive */ +#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + NdisZeroMemory((_pAd)->CommonCfg.Ssid, MAX_LEN_OF_SSID); \ + (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \ + NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \ + COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \ + (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel; \ + (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel; \ + (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid; \ + (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin; \ + (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo; \ + (_pAd)->StaActive.ExtCapInfo = (_pAd)->MlmeAux.ExtCapInfo; \ + (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod; \ + (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration; \ + (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod; \ + (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen; \ + NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\ + (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \ + NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\ + NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\ + COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \ + (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\ + COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\ + (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + + ========================================================================== +*/ +VOID MlmeCntlInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + /* Control state machine differs from other state machines, the interface */ + /* follows the standard interface */ + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID MlmeCntlMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem) +{ + switch (pAd->Mlme.CntlMachine.CurrState) { + case CNTL_IDLE: + CntlIdleProc(pAd, Elem); + break; + case CNTL_WAIT_DISASSOC: + CntlWaitDisassocProc(pAd, Elem); + break; + case CNTL_WAIT_JOIN: + CntlWaitJoinProc(pAd, Elem); + break; + + /* CNTL_WAIT_REASSOC is the only state in CNTL machine that does */ + /* not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". */ + /* Therefore not protected by NDIS's "only one outstanding OID request" */ + /* rule. Which means NDIS may SET OID in the middle of ROAMing attempts. */ + /* Current approach is to block new SET request at RTMPSetInformation() */ + /* when CntlMachine.CurrState is not CNTL_IDLE */ + case CNTL_WAIT_REASSOC: + CntlWaitReassocProc(pAd, Elem); + break; + + case CNTL_WAIT_START: + CntlWaitStartProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH: + CntlWaitAuthProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH2: + CntlWaitAuthProc2(pAd, Elem); + break; + case CNTL_WAIT_ASSOC: + CntlWaitAssocProc(pAd, Elem); + break; + + case CNTL_WAIT_OID_LIST_SCAN: + if (Elem->MsgType == MT2_SCAN_CONF) { + USHORT Status = MLME_SUCCESS; + + NdisMoveMemory(&Status, Elem->Msg, sizeof(USHORT)); + /* Resume TxRing after SCANING complete. We hope the out-of-service time */ + /* won't be too long to let upper layer time-out the waiting frames */ + RTMPResumeMsduTransmission(pAd); + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + + /* scan completed, init to not FastScan */ + pAd->StaCfg.bImprovedScan = FALSE; + +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_SCAN_END(pAd, FALSE); +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + /* */ + /* Set LED status to previous status. */ + /* */ + if (pAd->LedCntl.bLedOnScanning) { + pAd->LedCntl.bLedOnScanning = FALSE; + RTMPSetLED(pAd, pAd->LedCntl.LedStatus); + } +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef DOT11N_DRAFT3 + /* AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone. */ + if ((pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1) + && INFRA_ON(pAd) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) { + Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, + TRUE); + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if ( pAd->StaCfg.bAutoReconnect == TRUE && + pAd->IndicateMediaState != NdisMediaStateConnected && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI)) + { + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, (PCHAR)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + if (Status == MLME_SUCCESS) + { + { + /* + Maintain Scan Table + MaxBeaconRxTimeDiff: 120 seconds + MaxSameBeaconRxTimeCount: 1 + */ + MaintainBssTable(pAd, &pAd->ScanTab, 120, 2); + } + + { + RTMPSendWirelessEvent(pAd, IW_SCAN_COMPLETED_EVENT_FLAG, NULL, BSS0, 0); + +#ifdef WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_SCAN, -1, NULL, NULL, 0); +#endif /* WPA_SUPPLICANT_SUPPORT */ + } + + } +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_MLME_SCAN_DONE, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } +#endif /* IWSC_SUPPORT */ + } + break; + + case CNTL_WAIT_OID_DISASSOC: + if (Elem->MsgType == MT2_DISASSOC_CONF) { + LinkDown(pAd, FALSE); +/* +for android system , if connect ap1 and want to change to ap2 , +when disassoc from ap1 ,and send even_scan will direct connect to ap2 , not need to wait ui to scan and connect +*/ + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + break; + + case CNTL_WAIT_SCAN_FOR_CONNECT: + if (Elem->MsgType == MT2_SCAN_CONF) { + USHORT Status = MLME_SUCCESS; + NdisMoveMemory(&Status, Elem->Msg, sizeof(USHORT)); + /* Resume TxRing after SCANING complete. We hope the out-of-service time */ + /* won't be too long to let upper layer time-out the waiting frames */ + RTMPResumeMsduTransmission(pAd); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, (PCHAR)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } + break; + default: + DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", + Elem->MsgType)); + break; + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlIdleProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + switch (Elem->MsgType) { + case OID_802_11_SSID: + CntlOidSsidProc(pAd, Elem); + break; + + case OID_802_11_BSSID: + CntlOidRTBssidProc(pAd, Elem); + break; + + case OID_802_11_BSSID_LIST_SCAN: + CntlOidScanProc(pAd, Elem); + break; + + case OID_802_11_DISASSOCIATE: + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof (MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x7F) != + WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAd->MlmeAux.AutoReconnectSsidLen = 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen); + } + break; + + case MT2_MLME_ROAMING_REQ: + CntlMlmeRoamingProc(pAd, Elem); + break; + + case OID_802_11_MIC_FAILURE_REPORT_FRAME: + WpaMicFailureReportFrame(pAd, Elem); + break; + +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_SET_DLS_PARAM: + CntlOidDLSSetupProc(pAd, Elem); + break; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + case RT_OID_802_11_SET_TDLS_PARAM: + TDLS_CntlOidTDLSRequestProc(pAd, Elem); + break; +#endif /* DOT11Z_TDLS_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n", + Elem->MsgType)); + break; + } +} + +VOID CntlOidScanProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + ULONG BssIdx = BSS_NOT_FOUND; +/* BSS_ENTRY CurrBss; */ + BSS_ENTRY *pCurrBss = NULL; + +#ifdef RALINK_ATE +/* Disable scanning when ATE is running. */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **) & pCurrBss, sizeof (BSS_ENTRY)); + if (pCurrBss == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* record current BSS if network is connected. */ + /* 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + BssIdx = + BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, + (PUCHAR) pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen, + pAd->CommonCfg.Channel); + if (BssIdx != BSS_NOT_FOUND) { + NdisMoveMemory(pCurrBss, &pAd->ScanTab.BssEntry[BssIdx], + sizeof (BSS_ENTRY)); + } + } + + + ScanParmFill(pAd, &ScanReq, (PSTRING) Elem->Msg, Elem->MsgLen, BSS_ANY, + SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof (MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + if (pCurrBss != NULL) + os_free_mem(NULL, pCurrBss); +} + +/* + ========================================================================== + Description: + Before calling this routine, user desired SSID should already been + recorded in CommonCfg.Ssid[] + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidSsidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *) Elem->Msg; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + +#ifdef DOT11R_FT_SUPPORT + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain = FALSE; + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = 0; +#endif /* DOT11R_FT_SUPPORT */ + + /* Step 1. record the desired user settings to MlmeAux */ + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); + pAd->MlmeAux.SsidLen = (UCHAR) pOidSsid->SsidLength; + if (pAd->StaCfg.BssType == BSS_INFRA) + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + + pAd->StaCfg.bAutoConnectByBssid = FALSE; + + /*save connect info*/ + NdisZeroMemory(pAd->StaCfg.ConnectinfoSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->StaCfg.ConnectinfoSsid, pOidSsid->Ssid, pOidSsid->SsidLength); + pAd->StaCfg.ConnectinfoSsidLen = pOidSsid->SsidLength; + pAd->StaCfg.ConnectinfoBssType = pAd->StaCfg.BssType; + +#ifdef WSC_STA_SUPPORT + /* for M8 */ + NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->CommonCfg.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); + pAd->CommonCfg.SsidLen = (UCHAR) pOidSsid->SsidLength; +#endif /* WSC_STA_SUPPORT */ + + + /* Update Reconnect Ssid, that user desired to connect. */ + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + + /* + step 2. + find all matching BSS in the lastest SCAN result (inBssTab) + and log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order + */ + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, + (PCHAR) pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire ", + pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr)); + if (pAd->MlmeAux.SsidLen == MAX_LEN_OF_SSID) + hex_dump("\nSSID", pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + else + DBGPRINT(RT_DEBUG_TRACE, + ("(%d)SSID - %s\n", pAd->MlmeAux.SsidLen, + pAd->MlmeAux.Ssid)); + + if (INFRA_ON(pAd) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) + && NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) + && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) { + /* + Case 1. already connected with an AP who has the desired SSID + with highest RSSI + */ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /* Add checking Mode "LEAP" for CCX 1.0 */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WAPI_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK) + || (wdev->AuthMode == Ndis802_11AuthModeWAICERT) +#endif /* WAPI_SUPPORT */ + ) && + (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { + /* + case 1.1 For WPA, WPA-PSK, + if port is not secured, we have to redo connection process + */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof (MLME_DISASSOC_REQ_STRUCT), + &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } else if (pAd->bConfigChanged == TRUE) { + /* case 1.2 Important Config has changed, we have to reconnect to the same AP */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof (MLME_DISASSOC_REQ_STRUCT), + &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } else { + /* case 1.3. already connected to the SSID with highest RSSI. */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n")); + /* + (HCT 12.1) 1c_wlan_mediaevents required + media connect events are indicated when associating with the same AP + */ + if (INFRA_ON(pAd)) { + /* + Since MediaState already is NdisMediaStateConnected + We just indicate the connect event again to meet the WHQL required. + */ + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + pAd->ExtraInfo = GENERAL_LINK_UP; /* Update extra information to link is up */ + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CGIWAP, -1, + &pAd->MlmeAux.Bssid[0], NULL, + 0); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + } + } else if (INFRA_ON(pAd)) { + /* + For RT61 + [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) + RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect + But media status is connected, so the SSID not report correctly. + */ + if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) { + /* Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. */ + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + } + + /* + case 2. active INFRA association existent + Roaming is done within miniport driver, nothing to do with configuration + utility. so upon a new SET(OID_802_11_SSID) is received, we just + disassociate with the current associated AP, + then perform a new association with this new SSID, no matter the + new/old SSID are the same or not. + */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof (MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } else { + if (ADHOC_ON(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - drop current ADHOC\n")); + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + } + + if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) && + (pAd->StaCfg.bAutoReconnect == TRUE) && + (((pAd->MlmeAux.BssType == BSS_INFRA) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + || ((pAd->MlmeAux.BssType == BSS_ADHOC) && !pAd->StaCfg.bNotFirstScan)) + && (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE) + ) { + MLME_SCAN_REQ_STRUCT ScanReq; + + if (pAd->MlmeAux.BssType == BSS_ADHOC) + pAd->StaCfg.bNotFirstScan = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n")); + + if((pAd->StaCfg.ConnectinfoChannel != 0) && (pAd->StaCfg.Connectinfoflag == TRUE)) + { + ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_FORCE_SCAN_REQ, + sizeof (MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_SCAN_FOR_CONNECT; + } + else + { + ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof (MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + } + + /* Reset Missed scan number */ + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + pAd->StaCfg.bNotFirstScan = TRUE; + } else { +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT + /* LED indication. */ + if (pAd->MlmeAux.BssType == BSS_INFRA) { + LEDConnectionStart(pAd); + } +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + + if ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_33_BG_BAND) + { + BSS_ENTRY *entry; + // TODO: shiang-6590, check this "SavedPhyMode"! + entry = &pAd->MlmeAux.SsidBssTab.BssEntry[pAd->MlmeAux.BssIdx]; + if ((entry->Channel == 14) && (pAd->CommonCfg.SavedPhyMode = 0xff)) { + pAd->CommonCfg.SavedPhyMode = pAd->CommonCfg.PhyMode; + RTMPSetPhyMode(pAd, WMODE_B); + } else if (pAd->CommonCfg.SavedPhyMode != 0xff) { + RTMPSetPhyMode(pAd, pAd->CommonCfg.SavedPhyMode); + pAd->CommonCfg.SavedPhyMode = 0xFF; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():SavedPhyMode=0x%x! Channel=%d\n", + __FUNCTION__, pAd->CommonCfg.SavedPhyMode, entry->Channel)); + } + } + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } + +#ifdef RT_CFG80211_SUPPORT + if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) && (pAd->MlmeAux.BssType == BSS_INFRA) + && (pAd->cfg80211_ctrl.FlgCfg80211Connecting == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_MLME: No matching BSS, Report cfg80211_layer SM to Idle --> %d\n", + pAd->Mlme.CntlMachine.CurrState)); + + pAd->cfg80211_ctrl.Cfg_pending_SsidLen = pAd->MlmeAux.SsidLen; + NdisZeroMemory(pAd->cfg80211_ctrl.Cfg_pending_Ssid, MAX_LEN_OF_SSID + 1); + NdisMoveMemory(pAd->cfg80211_ctrl.Cfg_pending_Ssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + + RT_CFG80211_CONN_RESULT_INFORM(pAd, pAd->MlmeAux.Bssid, NULL, 0, NULL, 0, 0); + } +#endif /* RT_CFG80211_SUPPORT */ + } +} + +#ifdef WSC_STA_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWscIterate(RTMP_ADAPTER *pAd) +{ +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ + + /* Connect to the WPS-enabled AP by its BSSID directly. */ + /* Note: When WscState is equal to WSC_STATE_START, */ + /* pAd->StaCfg.WscControl.WscAPBssid has been filled with valid BSSID. */ + if ((pAd->StaCfg.WscControl.WscState >= WSC_STATE_START) && + (pAd->StaCfg.WscControl.WscStatus != STATUS_WSC_SCAN_AP)) { + /* Set WSC state to WSC_STATE_START */ + pAd->StaCfg.WscControl.WscState = WSC_STATE_START; + pAd->StaCfg.WscControl.WscStatus = STATUS_WSC_START_ASSOC; + + if (pAd->StaCfg.BssType == BSS_INFRA) { + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + MAC_ADDR_LEN, + pAd->StaCfg.WscControl.WscBssid, 0); + } else { + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof (NDIS_802_11_SSID), + (VOID *) & pAd->StaCfg.WscControl.WscSsid, + 0); + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + + RTMP_MLME_HANDLER(pAd); + } +#ifdef WSC_LED_SUPPORT + /* The protocol is connecting to a partner. */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ +} +#endif /* WSC_STA_SUPPORT */ + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidRTBssidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + ULONG BssIdx; + PUCHAR pOidBssid = (PUCHAR) Elem->Msg; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + MLME_JOIN_REQ_STRUCT JoinReq; + BSS_ENTRY *pInBss = NULL; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + +#ifdef WSC_STA_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* WSC_STA_SUPPORT */ + +#ifdef RALINK_ATE +/* No need to perform this routine when ATE is running. */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + /* record user desired settings */ + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid); + pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + + /*save connect info*/ + NdisZeroMemory(pAd->StaCfg.ConnectinfoBssid, MAC_ADDR_LEN); + NdisMoveMemory(pAd->StaCfg.ConnectinfoBssid, pOidBssid, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("ANDROID IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->StaCfg.ConnectinfoBssid))); + + /* find the desired BSS in the latest SCAN result table */ + BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) ; + else +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) ; + else +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + if ( +#ifdef WSC_STA_SUPPORT + (pWpsCtrl->WscConfMode == WSC_DISABLE) && +#endif /* WSC_STA_SUPPORT */ + (BssIdx != BSS_NOT_FOUND)) + { + pInBss = &pAd->ScanTab.BssEntry[BssIdx]; + + /* + If AP's SSID has been changed, STA cannot connect to this AP. + */ + if (SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, pInBss->Ssid, pInBss->SsidLen) == FALSE) + BssIdx = BSS_NOT_FOUND; + + if (wdev->AuthMode <= Ndis802_11AuthModeAutoSwitch) { + if (wdev->WepStatus != pInBss->WepStatus) + BssIdx = BSS_NOT_FOUND; + } else { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */ + if ((wdev->AuthMode != pInBss->AuthMode) && + (wdev->AuthMode != pInBss->AuthModeAux)) + BssIdx = BSS_NOT_FOUND; + } + } + +#ifdef WSC_STA_SUPPORT + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + ((pWpsCtrl->WscStatus == STATUS_WSC_START_ASSOC) || (pWpsCtrl->WscStatus == STATUS_WSC_LINK_UP)) && + (pAd->StaCfg.bSkipAutoScanConn == TRUE)) + pAd->StaCfg.bSkipAutoScanConn = FALSE; +#endif /* WSC_STA_SUPPORT */ + + if (BssIdx == BSS_NOT_FOUND) { + if (((pAd->StaCfg.BssType == BSS_INFRA) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) || + (pAd->StaCfg.bNotFirstScan == FALSE)) { + MLME_SCAN_REQ_STRUCT ScanReq; + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); + if (pAd->StaCfg.BssType == BSS_ADHOC) + pAd->StaCfg.bNotFirstScan = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - BSSID not found. start a new scan\n")); + + if((pAd->StaCfg.ConnectinfoChannel != 0)&& (pAd->StaCfg.Connectinfoflag == TRUE)) + { + DBGPRINT(RT_DEBUG_OFF, ("CntlOidRTBssidProc BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->StaCfg.ConnectinfoBssid))); + pAd->CommonCfg.Channel = pAd->StaCfg.ConnectinfoChannel; + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_FORCE_JOIN_REQ, + sizeof (MLME_JOIN_REQ_STRUCT), &JoinReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + else { + ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof (MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + } + /* Reset Missed scan number */ + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + } + else + { + MLME_START_REQ_STRUCT StartReq; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - BSSID not found. start a new ADHOC (Ssid=%s)...\n", + pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, (PCHAR)pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, + sizeof (MLME_START_REQ_STRUCT), &StartReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + return; + } + + pInBss = &pAd->ScanTab.BssEntry[BssIdx]; + /* Update Reconnect Ssid, that user desired to connect. */ + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + pAd->MlmeAux.AutoReconnectSsidLen = pInBss->SsidLen; + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pInBss->Ssid, pInBss->SsidLen); + + + /* copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? */ + /* Because we need this entry to become the JOIN target in later on SYNC state machine */ + pAd->MlmeAux.BssIdx = 0; + pAd->MlmeAux.SsidBssTab.BssNr = 1; + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], pInBss, + sizeof (BSS_ENTRY)); + + { + if (INFRA_ON(pAd)) { + /* disassoc from current AP first */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - disassociate with current AP ...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof (MLME_DISASSOC_REQ_STRUCT), + &DisassocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } else { + if (ADHOC_ON(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - drop current ADHOC\n")); + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, + fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, + NdisMediaStateDisconnected); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + } + + pInBss = &pAd->MlmeAux.SsidBssTab.BssEntry[0]; + + pAd->StaCfg.PairCipher = wdev->WepStatus; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + pAd->StaCfg.GroupCipher = wdev->WepStatus; + + /* Check cipher suite, AP must have more secured cipher than station setting */ + /* Set the Pairwise and Group cipher to match the intended AP setting */ + /* We can only connect to AP with less secured cipher setting */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) + || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) { + pAd->StaCfg.GroupCipher = pInBss->WPA.GroupCipher; + + if (wdev->WepStatus == pInBss->WPA.PairCipher) + pAd->StaCfg.PairCipher = pInBss->WPA.PairCipher; + else if (pInBss->WPA.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pInBss->WPA.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + } else + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pAd->StaCfg.GroupCipher = pInBss->WPA2.GroupCipher; + + if (wdev->WepStatus == pInBss->WPA2.PairCipher) + pAd->StaCfg.PairCipher = pInBss->WPA2.PairCipher; + else if (pInBss->WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pInBss->WPA2.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + + /* RSN capability */ + pAd->StaCfg.RsnCapability = pInBss->WPA2.RsnCapability; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) { + pAd->StaCfg.GroupCipher = pInBss->WAPI.GroupCipher; + pAd->StaCfg.PairCipher = pInBss->WAPI.PairCipher; + } +#endif /* WAPI_SUPPORT */ + + /* Set Mix cipher flag */ + pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + + /* No active association, join the BSS immediately */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n", + PRINT_MAC(pOidBssid))); + + JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, + sizeof (MLME_JOIN_REQ_STRUCT), &JoinReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + } +} + +/* Roaming is the only external request triggering CNTL state machine */ +/* despite of other "SET OID" operation. All "SET OID" related oerations */ +/* happen in sequence, because no other SET OID will be sent to this device */ +/* until the the previous SET operation is complete (successful o failed). */ +/* So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? */ +/* or been corrupted by other "SET OID"? */ +/* */ +/* IRQL = DISPATCH_LEVEL */ +VOID CntlMlmeRoamingProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +#ifdef DOT11R_FT_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + BSS_ENTRY *pTargetAP = &pAd->MlmeAux.RoamTab.BssEntry[0]; +#endif /* DOT11R_FT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Roaming in MlmeAux.RoamTab...\n")); + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain && + (pAd->CommonCfg.Channel != pTargetAP->Channel)) { + if (pEntry->MdIeInfo.FtCapPlc.field.FtOverDs) { + MLME_FT_REQ_STRUCT FtReq; + DBGPRINT(RT_DEBUG_TRACE, + ("Dot11r: pBss->Channel = %d. Use OTD.\n", + pTargetAP->Channel)); + FT_OTD_ActParmFill(pAd, &FtReq, pTargetAP->Bssid, + pTargetAP->AuthMode, + &pAd->StaCfg.Dot11RCommInfo.MdIeInfo, + &pAd->StaCfg.Dot11RCommInfo.FtIeInfo, + pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSN_IE); + + MlmeEnqueue(pAd, FT_OTD_ACT_STATE_MACHINE, + FT_OTD_MT2_MLME_REQ, + sizeof (MLME_FT_REQ_STRUCT), &FtReq, 0); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("CNTL - Shall not haapen!!\n")); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + { + + /*Let BBP register at 20MHz to do (fast) roaming. */ + bbp_set_bw(pAd, BW_20); + + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, + sizeof (pAd->MlmeAux.RoamTab)); + pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr; + + BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab, FALSE); + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } +} + +#ifdef QOS_DLS_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidDLSSetupProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_DLS pDLS = (PRT_802_11_DLS) Elem->Msg; + MLME_DLS_REQ_STRUCT MlmeDlsReq; + INT i; + USHORT reason = REASON_UNSPECIFY; + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - (OID set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d, TimeOut=%d, CountDownTimer=%d)\n", + pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], + pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5], + pDLS->Valid, pDLS->Status, pDLS->TimeOut, + pDLS->CountDownTimer)); + + if (!pAd->CommonCfg.bDLSCapable) + return; + + /* DLS will not be supported when Adhoc mode */ + if (INFRA_ON(pAd)) { + for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pDLS->TimeOut == + pAd->StaCfg.DLSEntry[i].TimeOut) + && MAC_ADDR_EQUAL(pDLS->MacAddr, + pAd->StaCfg.DLSEntry[i]. + MacAddr)) { + /* 1. Same setting, just drop it */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - setting unchanged\n")); + break; + } else if (!pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == + DLS_FINISH) + && MAC_ADDR_EQUAL(pDLS->MacAddr, + pAd->StaCfg.DLSEntry[i]. + MacAddr)) { + /* 2. Disable DLS link case, just tear down DLS link */ + reason = REASON_QOS_UNWANTED_MECHANISM; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - start tear down procedure\n")); + break; + } else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid + && !pAd->StaCfg.DLSEntry[i].Valid) { + /* 3. Enable case, start DLS setup procedure */ + NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, + sizeof (RT_802_11_DLS_UI)); + + /*Update countdown timer */ + pAd->StaCfg.DLSEntry[i].CountDownTimer = + pAd->StaCfg.DLSEntry[i].TimeOut; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_REQ, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - DLS setup case\n")); + break; + } else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid + && pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == + DLS_FINISH) + && !MAC_ADDR_EQUAL(pDLS->MacAddr, + pAd->StaCfg.DLSEntry[i]. + MacAddr)) { + /* 4. update mac case, tear down old DLS and setup new DLS */ + reason = REASON_QOS_UNWANTED_MECHANISM; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, + sizeof (RT_802_11_DLS_UI)); + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_REQ, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - DLS tear down and restart case\n")); + break; + } else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(pDLS->MacAddr, + pAd->StaCfg.DLSEntry[i]. + MacAddr) + && (pAd->StaCfg.DLSEntry[i].TimeOut != + pDLS->TimeOut)) { + /* 5. update timeout case, start DLS setup procedure (no tear down) */ + pAd->StaCfg.DLSEntry[i].TimeOut = pDLS->TimeOut; + /*Update countdown timer */ + pAd->StaCfg.DLSEntry[i].CountDownTimer = + pAd->StaCfg.DLSEntry[i].TimeOut; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_REQ, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - DLS update timeout case\n")); + break; + } else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status != + DLS_FINISH) + && MAC_ADDR_EQUAL(pDLS->MacAddr, + pAd->StaCfg.DLSEntry[i]. + MacAddr)) { + /* 6. re-setup case, start DLS setup procedure (no tear down) */ + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_REQ, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - DLS retry setup procedure\n")); + break; + } else { + DBGPRINT(RT_DEBUG_WARN, + ("CNTL - DLS not changed in entry - %d - Valid=%d, Status=%d, TimeOut=%d\n", + i, pAd->StaCfg.DLSEntry[i].Valid, + pAd->StaCfg.DLSEntry[i].Status, + pAd->StaCfg.DLSEntry[i].TimeOut)); + } + } + } +} +#endif /* QOS_DLS_SUPPORT */ + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitDisassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_START_REQ_STRUCT StartReq; + + if (Elem->MsgType == MT2_DISASSOC_CONF) { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n")); + + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, NULL, BSS0, + 0); + + LinkDown(pAd, FALSE); + + /* case 1. no matching BSS, and user wants ADHOC, so we just start a new one */ + if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) + && (pAd->StaCfg.BssType == BSS_ADHOC)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n", + pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, (PCHAR) pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, + sizeof (MLME_START_REQ_STRUCT), &StartReq, + 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + /* case 2. try each matched BSS */ + else { + /* + Some customer would set AP1 & AP2 same SSID, AuthMode & EncrypType but different WPAPSK, + therefore we need to try next AP here. + */ + /*pAd->MlmeAux.BssIdx = 0;*/ + pAd->MlmeAux.BssIdx++; + +#ifdef WSC_STA_SUPPORT + if (pAd->StaCfg.WscControl.WscState >= WSC_STATE_START) + CntlWscIterate(pAd); + else if (((pAd->StaCfg.WscControl.bWscTrigger == FALSE) + ) + && (pAd->StaCfg.WscControl.WscState != + WSC_STATE_INIT)) +#endif /* WSC_STA_SUPPORT */ + IterateOnBssTab(pAd); +#ifdef WSC_STA_SUPPORT + else + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#endif /* WSC_STA_SUPPORT */ + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitJoinProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_JOIN_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof (USHORT)); + if (Reason == MLME_SUCCESS) { + /* 1. joined an IBSS, we are pretty much done here */ + if (pAd->MlmeAux.BssType == BSS_ADHOC) { + /* */ + /* 5G bands rules of Japan: */ + /* Ad hoc must be disabled in W53(ch52,56,60,64) channels. */ + /* */ + + if ((pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", + pAd->CommonCfg.Channel)); + return; + } + + LinkUp(pAd, BSS_ADHOC); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + PRINT_MAC(pAd->CommonCfg.Bssid))); + + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + pAd->ExtraInfo = GENERAL_LINK_UP; + + RTMPSendWirelessEvent(pAd, IW_JOIN_IBSS_FLAG, NULL, BSS0, 0); + } + /* 2. joined a new INFRA network, start from authentication */ + else + { +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain) { + MLME_FT_OTA_AUTH_REQ_STRUCT FtOtaAuthReq; + + FT_OTA_AuthParmFill(pAd, + &FtOtaAuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_FT, + &pAd->StaCfg.Dot11RCommInfo); + + MlmeEnqueue(pAd, + FT_OTA_AUTH_STATE_MACHINE, + FT_OTA_MT2_MLME_AUTH_REQ, + sizeof(MLME_FT_OTA_AUTH_REQ_STRUCT), + &FtOtaAuthReq, 0); + } else +#endif /* DOT11R_FT_SUPPORT */ + { + /* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */ + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeShared) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_KEY); + } else { + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_OPEN); + } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, + MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), + &AuthReq, 0); + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH; + } + } + else + { + /* 3. failed, try next BSS */ + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitStartProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Result; + RT_PHY_INFO *rt_phy_info; + + + if (Elem->MsgType == MT2_START_CONF) { + NdisMoveMemory(&Result, Elem->Msg, sizeof (USHORT)); + if (Result == MLME_SUCCESS) { + /* */ + /* 5G bands rules of Japan: */ + /* Ad hoc must be disabled in W53(ch52,56,60,64) channels. */ + /* */ + + if ((pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel) + ) { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", + pAd->CommonCfg.Channel)); + return; + } + +#ifdef DOT11_N_SUPPORT + rt_phy_info = &pAd->StaActive.SupportedPhyInfo; + NdisZeroMemory(&rt_phy_info->MCSSet[0], 16); + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && (pAd->StaCfg.bAdhocN == TRUE) + && (!pAd->CommonCfg.HT_DisallowTKIP + || !IS_INVALID_HT_SECURITY(pAd->StaCfg.wdev.WepStatus))) + { + N_ChannelCheck(pAd); + SetCommonHT(pAd); + pAd->MlmeAux.CentralChannel = get_cent_ch_by_htinfo(pAd, + &pAd->CommonCfg.AddHTInfo, + &pAd->CommonCfg.HtCapability); + NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, + &pAd->CommonCfg.AddHTInfo, + sizeof (ADD_HT_INFO_IE)); + RTMPCheckHt(pAd, BSSID_WCID, + &pAd->CommonCfg.HtCapability, + &pAd->CommonCfg.AddHTInfo); + rt_phy_info->bHtEnable = TRUE; + NdisMoveMemory(&rt_phy_info->MCSSet[0], + &pAd->CommonCfg.HtCapability.MCSSet[0], 16); + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + pAd->MlmeAux.vht_cap_len) { + RT_VHT_CAP *rt_vht_cap = &pAd->StaActive.SupVhtCap; + + COPY_VHT_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + rt_vht_cap->vht_bw = BW_80; + rt_vht_cap->sgi_80m = pAd->MlmeAux.vht_cap.vht_cap.sgi_80M; + rt_vht_cap->vht_txstbc = pAd->MlmeAux.vht_cap.vht_cap.tx_stbc; + rt_vht_cap->vht_rxstbc = pAd->MlmeAux.vht_cap.vht_cap.rx_stbc; + rt_vht_cap->vht_htc = pAd->MlmeAux.vht_cap.vht_cap.htc_vht_cap; + } +#endif /* DOT11_VHT_AC */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + } + pAd->StaCfg.bAdhocCreator = TRUE; + LinkUp(pAd, BSS_ADHOC); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + /* Before send beacon, driver need do radar detection */ + + 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; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + PRINT_MAC(pAd->CommonCfg.Bssid))); + + RTMPSendWirelessEvent(pAd, IW_START_IBSS_FLAG, NULL, BSS0, 0); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAuthProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + Elem->MsgType == MT2_FT_OTD_CONF) { + DBGPRINT(RT_DEBUG_TRACE, ("FT_TEMP - CntlWaitFtProc\n")); + NdisMoveMemory(&Reason, Elem->Msg, sizeof (USHORT)); + if (Reason == MLME_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - FT OTD AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, + pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_REASSOC_REQ, + sizeof (MLME_ASSOC_REQ_STRUCT), &AssocReq, + 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } + } else +#endif /* DOT11R_FT_SUPPORT */ + if (Elem->MsgType == MT2_AUTH_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof (USHORT)); + if (Reason == MLME_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, + pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess != 0)) { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_REASSOC_REQ, + sizeof (MLME_ASSOC_REQ_STRUCT), + &AssocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } else +#endif /* DOT11R_FT_SUPPORT */ + { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_ASSOC_REQ, + sizeof (MLME_ASSOC_REQ_STRUCT), + &AssocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + } + } else { + /* This fail may because of the AP already keep us in its MAC table without */ + /* ageing-out. The previous authentication attempt must have let it remove us. */ + /* so try Authentication again may help. For D-Link DWL-900AP+ compatibility. */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - AUTH FAIL, try again...\n")); +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess == + FT_OTA_RESPONSE)) { + MLME_FT_OTA_AUTH_REQ_STRUCT FtOtaAuthReq; + + FT_OTA_AuthParmFill(pAd, + &FtOtaAuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_FT, + &pAd->StaCfg.Dot11RCommInfo); + + MlmeEnqueue(pAd, FT_OTA_AUTH_STATE_MACHINE, + FT_OTA_MT2_MLME_AUTH_REQ, + sizeof(MLME_FT_OTA_AUTH_REQ_STRUCT), + &FtOtaAuthReq, 0); + } else +#endif /* DOT11R_FT_SUPPORT */ + { + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeShared) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + /* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */ + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_KEY); + } else { + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_OPEN); + } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, + MT2_MLME_AUTH_REQ, + sizeof (MLME_AUTH_REQ_STRUCT), + &AuthReq, 0); + + } + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAuthProc2( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_AUTH_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof (USHORT)); + if (Reason == MLME_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, + pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess != 0)) { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_REASSOC_REQ, + sizeof (MLME_ASSOC_REQ_STRUCT), + &AssocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } else +#endif /* DOT11R_FT_SUPPORT */ + { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_ASSOC_REQ, + sizeof (MLME_ASSOC_REQ_STRUCT), + &AssocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + } + } + else + { +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess == FT_OTA_RESPONSE)) { + /* failed, try next BSS */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - FT_OTA_AUTH FAIL, give up; try next BSS\n")); + RTMP_STA_ENTRY_MAC_RESET(pAd, BSSID_WCID); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } else +#endif /* DOT11R_FT_SUPPORT */ + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeAutoSwitch) + && (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - AUTH FAIL, try OPEN system...\n")); + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, + Ndis802_11AuthModeOpen); + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, + MT2_MLME_AUTH_REQ, + sizeof (MLME_AUTH_REQ_STRUCT), + &AuthReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + } else { + /* not success, try next BSS */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - AUTH FAIL, give up; try next BSS\n")); +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_CONN_RESULT_INFORM(pAd, pAd->MlmeAux.Bssid, NULL, 0, + NULL, 0, 0); +#endif /* RT_CFG80211_SUPPORT */ + RTMP_STA_ENTRY_MAC_RESET(pAd, BSSID_WCID); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->MlmeAux.BssIdx++; + + IterateOnBssTab(pAd); + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAssocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + + if (Elem->MsgType == MT2_ASSOC_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof (USHORT)); + if (Reason == MLME_SUCCESS) { + LinkUp(pAd, BSS_INFRA); +#ifdef RT_CFG80211_SUPPORT + /* moved from assoc.c */ + { + PCFG80211_CTRL cfg80211_ctrl = &pAd->cfg80211_ctrl; + if (cfg80211_ctrl->pAssocRspIe && cfg80211_ctrl->assocRspIeLen) + { + RT_CFG80211_CONN_RESULT_INFORM(pAd, pAd->MlmeAux.Bssid, + pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen, + cfg80211_ctrl->pAssocRspIe, + cfg80211_ctrl->assocRspIeLen, + TRUE); + } + else + { + RT_CFG80211_CONN_RESULT_INFORM(pAd, pAd->MlmeAux.Bssid, + pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen, + NULL, + 0, + TRUE); + } + } +#endif /* RT_CFG80211_SUPPORT */ + + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, NULL, BSS0, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Association successful on BSS #%ld\n", pAd->MlmeAux.BssIdx)); + } else { + /* not success, try next BSS */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Association fails on BSS #%ld\n", pAd->MlmeAux.BssIdx)); +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_CONN_RESULT_INFORM(pAd, pAd->MlmeAux.Bssid, NULL, 0, + NULL, 0, 0); +#endif /* RT_CFG80211_SUPPORT */ + RTMP_STA_ENTRY_MAC_RESET(pAd, BSSID_WCID); + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitReassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Result; + + if (Elem->MsgType == MT2_REASSOC_CONF) { + NdisMoveMemory(&Result, Elem->Msg, sizeof (USHORT)); + if (Result == MLME_SUCCESS) { + /* send wireless event - for association */ + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, NULL, + BSS0, 0); + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain && + (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess == + FT_OTD_RESPONSE)) + InitChannelRelatedValue(pAd); +#endif /* DOT11R_FT_SUPPORT */ + + /* NDIS requires a new Link UP indication but no Link Down for RE-ASSOC */ + LinkUp(pAd, BSS_INFRA); + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Re-assocition successful on BSS #%ld\n", + pAd->MlmeAux.RoamIdx)); + } else { + /* reassoc failed, try to pick next BSS in the BSS Table */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Re-assocition fails on BSS #%ld\n", + pAd->MlmeAux.RoamIdx)); +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain && + (pAd->StaCfg.Dot11RCommInfo.FtRspSuccess == FT_OTD_RESPONSE) + ) + { + NDIS_802_11_SSID ApSsid; + + NdisZeroMemory(&ApSsid, sizeof (NDIS_802_11_SSID)); + ApSsid.SsidLength = pAd->MlmeAux.SsidLen; + NdisMoveMemory(ApSsid.Ssid, pAd->MlmeAux.Ssid, ApSsid.SsidLength); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof (NDIS_802_11_SSID), + (VOID *) & ApSsid, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + else +#endif /* DOT11R_FT_SUPPORT */ + { + pAd->MlmeAux.RoamIdx++; + IterateOnBssTab2(pAd); + } + } + } +} + +VOID AdhocTurnOnQos(RTMP_ADAPTER *pAd) +{ +#define AC0_DEF_TXOP 0 +#define AC1_DEF_TXOP 0 +#define AC2_DEF_TXOP 94 +#define AC3_DEF_TXOP 47 + + /* Turn on QOs if use HT rate. */ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; + pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID LinkUp(RTMP_ADAPTER *pAd, UCHAR BssType) +{ + ULONG Now; + UINT32 Data; + BOOLEAN Cancelled; + UCHAR idx = 0; + MAC_TABLE_ENTRY *pEntry = NULL; +#ifdef WSC_STA_SUPPORT + UCHAR tmpWscSsid[MAX_LEN_OF_SSID] = { 0 }; + UCHAR tmpWscSsidLen = 0; +#endif /* WSC_STA_SUPPORT */ + UINT32 pbf_reg = 0, pbf_val, burst_txop; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /* Init ChannelQuality to prevent DEAD_CQI at initial LinkUp */ + pAd->Mlme.ChannelQuality = 50; + + /* init to not doing improved scan */ + pAd->StaCfg.bImprovedScan = FALSE; + pAd->StaCfg.bNotFirstScan = TRUE; + pAd->StaCfg.bAutoConnectByBssid = FALSE; + + /* Within 10 seconds after link up, don't allow to go to sleep. */ + pAd->CountDowntoPsm = STAY_10_SECONDS_AWAKE; + +#ifdef DOT11R_FT_SUPPORT + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = 0; + if ((BssType == BSS_INFRA) && (pAd->StaCfg.Dot11RCommInfo.bFtSupport)) { + if (pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain == FALSE) { + FT_SET_MDID(pAd->StaCfg.Dot11RCommInfo.MdIeInfo.MdId, + pAd->MlmeAux.MdIeInfo.MdId); + NdisZeroMemory(pAd->StaCfg.Dot11RCommInfo.R0khId, + FT_ROKH_ID_LEN); + NdisMoveMemory(pAd->StaCfg.Dot11RCommInfo.R0khId, + pAd->MlmeAux.FtIeInfo.R0khId, + pAd->MlmeAux.FtIeInfo.R0khIdLen); + pAd->StaCfg.Dot11RCommInfo.R0khIdLen = pAd->MlmeAux.FtIeInfo.R0khIdLen; + + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) { + /* Update PMK. */ + if (pAd->StaCfg.WpaPassPhraseLen == 64) { + AtoH(pAd->StaCfg.WpaPassPhrase, pAd->StaCfg.PMK, 32); + } else { + UCHAR keyMaterial[40] = { 0 }; + RtmpPasswordHash(pAd->StaCfg.WpaPassPhrase, + pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, + keyMaterial); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + } + } + } + else + { + /* Update Reconnect Ssid, that user desired to connect. */ + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + } + } +#endif /* DOT11R_FT_SUPPORT */ + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + /* + ASSOC - DisassocTimeoutAction + CNTL - Dis-associate successful + !!! LINK DOWN !!! + [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) + */ + + /* + To prevent DisassocTimeoutAction to call Link down after we link up, + cancel the DisassocTimer no matter what it start or not. + */ + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + +#ifdef WSC_STA_SUPPORT + tmpWscSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(tmpWscSsid, pAd->CommonCfg.Ssid, tmpWscSsidLen); +#endif /* WSC_STA_SUPPORT */ + COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + +#ifdef DOT11_N_SUPPORT + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); +#endif /* DOT11_N_SUPPORT */ + + + if (BssType == BSS_ADHOC) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */ + /* No carrier detection when adhoc */ + /* CarrierDetectionStop(pAd); */ + pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && (pAd->StaCfg.bAdhocN == TRUE)) + AdhocTurnOnQos(pAd); +#endif /* DOT11_N_SUPPORT */ + + InitChannelRelatedValue(pAd); + } else { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + } + DBGPRINT(RT_DEBUG_TRACE, ("!!!%s LINK UP !!! \n", (BssType == BSS_ADHOC ? "ADHOC" : "Infra"))); + + DBGPRINT(RT_DEBUG_TRACE, + ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n", + BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity)); +#endif /* DOT11_N_SUPPORT */ + + /* + We cannot move AsicSetBssid to PeerBeaconAtJoinAction because + PeerBeaconAtJoinAction wouldn't be invoked in roaming case. + */ + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + +#ifdef STREAM_MODE_SUPPORT + /* Enable stream mode for BSSID MAC Address */ + pEntry->StreamModeMACReg = TX_CHAIN_ADDR1_L; + AsicSetStreamMode(pAd, &pAd->CommonCfg.Bssid[0], 1, TRUE); +#endif /* STREAM_MODE_SUPPORT */ + + AsicSetSlotTime(pAd, TRUE); + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + + /* + Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, + but normally it will not hit + */ + AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE); + +#ifdef DOT11_N_SUPPORT + if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) { + /* Update HT protectionfor based on AP's operating mode. */ + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) { + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, + TRUE); + } else + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, + FALSE); + } +#endif /* DOT11_N_SUPPORT */ + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastBeaconRxTime = Now; /* last RX timestamp */ + + if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) && + CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) { + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + + if (wdev->WepStatus <= Ndis802_11WEPDisabled) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP && + (wdev->WepStatus == Ndis802_11WEPEnabled) && + (wdev->IEEE8021X == TRUE)) + ; + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + } + + if (BssType == BSS_ADHOC) { + MakeIbssBeacon(pAd); + + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) { + ; /*Do nothing */ + } + else + { + AsicEnableIbssSync(pAd); + } + + /* In ad hoc mode, use MAC table from index 1. */ + /* p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. */ + AsicDelWcidTab(pAd, MCAST_WCID); + AsicDelWcidTab(pAd, 1); + + /* If WEP is enabled, add key material and cipherAlg into Asic */ + /* Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) */ + + if (wdev->WepStatus == Ndis802_11WEPEnabled) { + UCHAR CipherAlg; + + for (idx = 0; idx < SHARE_KEY_NUM; idx++) { + CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) { + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, idx, + &pAd->SharedKey[BSS0][idx]); + + if (idx == wdev->DefaultKeyId) { + INT cnt; + + /* Generate 3-bytes IV randomly for software encryption using */ + for (cnt = 0; cnt < LEN_WEP_TSC; cnt++) + pAd->SharedKey[BSS0][idx].TxTsc[cnt] = RandomByte(pAd); + + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, + idx, + CipherAlg, + MCAST_WCID, + SHAREDKEYTABLE); + } + } + } + } + /* If WPANone is enabled, add key material and cipherAlg into Asic */ + /* Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) */ + else if (wdev->AuthMode == Ndis802_11AuthModeWPANone) { + wdev->DefaultKeyId = 0; /* always be zero */ + + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof (CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TK); + + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, + &pAd->StaCfg.PMK[16], LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, + &pAd->StaCfg.PMK[16], LEN_TKIP_MIC); + } + + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else { + DBGPRINT(RT_DEBUG_TRACE, + ("Unknow Cipher (=%d), set Cipher to AES\n", + pAd->StaCfg.PairCipher)); + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + } + + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, + BSS0, 0, &pAd->SharedKey[BSS0][0]); + + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, 0, + pAd->SharedKey[BSS0][0].CipherAlg, MCAST_WCID, + SHAREDKEYTABLE); + } +#ifdef ADHOC_WPA2PSK_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + && (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + ) { + USHORT Wcid = 0; + + wdev->DefaultKeyId = 0; /* always be zero */ + + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof (CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TK); + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + + /* Generate GMK and GNonce randomly */ + GenRandom(pAd, pAd->CommonCfg.Bssid, pAd->StaCfg.GMK); + GenRandom(pAd, pAd->CommonCfg.Bssid, pAd->StaCfg.GNonce); + + /* Derive GTK per BSSID */ + WpaDeriveGTK(pAd->StaCfg.GMK, + pAd->StaCfg.GNonce, + pAd->CurrentAddress, + pAd->StaCfg.GTK, LEN_TKIP_GTK); + + if (pAd->StaCfg.GroupCipher == Ndis802_11AESEnable) { + NdisZeroMemory(&pAd->StaCfg.TxGTK, sizeof (CIPHER_KEY)); + NdisMoveMemory(pAd->StaCfg.TxGTK.Key, pAd->StaCfg.GTK, LEN_TK); + pAd->StaCfg.TxGTK.CipherAlg = CIPHER_AES; + pAd->StaCfg.TxGTK.KeyLen = LEN_TK; + + /* Add Pair-wise key to Asic */ + GET_GroupKey_WCID(pAd, Wcid, BSS0); + AsicAddPairwiseKeyEntry(pAd, + (UCHAR) Wcid, + &pAd->StaCfg.TxGTK); + + RTMPSetWcidSecurityInfo(pAd, + BSS0, 0, + pAd->StaCfg.TxGTK.CipherAlg, (UCHAR) Wcid, + PAIRWISEKEYTABLE); + } + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + } + else + { /* BSS_INFRA */ + /* Check the new SSID with last SSID */ + while (Cancelled == TRUE) { + if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen) { + if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0) { + /* Link to the old one no linkdown is required. */ + break; + } + } + /* Send link down event before set to link up */ + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n")); + break; + } + + /* + On WPA mode, Remove All Keys if not connect to the last BSSID + Key will be set after 4-way handshake + */ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { + /* Remove all WPA keys */ +#ifdef PCIE_PS_SUPPORT + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ +/* + for dhcp,issue ,wpa_supplicant ioctl too fast , at link_up, it will add key before driver remove key + move to assoc.c + */ +/* RTMPWPARemoveAllKeys(pAd);*/ + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + + +#ifdef SOFT_ENCRYPT + /* There are some situation to need to encryption by software + 1. The Client support PMF. It shall ony support AES cipher. + 2. The Client support WAPI. + If use RT3883 or later, HW can handle the above. + */ +#ifdef WAPI_SUPPORT + if (!(IS_HW_WAPI_SUPPORT(pAd)) + && (wdev->WepStatus == Ndis802_11EncryptionSMS4Enabled)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + { + if ((pAd->chipCap.FlgPMFEncrtptMode == PMF_ENCRYPT_MODE_0) + && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } + } +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /* SOFT_ENCRYPT */ + + } +#ifdef DOT11R_FT_SUPPORT + else { + /* + 11R only supports OPEN/NONE and WPA2PSK/TKIPAES now. + */ + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->MlmeAux.MdIeInfo.Len && + (wdev->AuthMode == Ndis802_11AuthModeOpen) && + (wdev->WepStatus == Ndis802_11WEPDisabled)) + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain = TRUE; + } +#endif /* DOT11R_FT_SUPPORT */ + + /* NOTE: */ + /* the decision of using "short slot time" or not may change dynamically due to */ + /* new STA association to the AP. so we have to decide that upon parsing BEACON, not here */ + + /* NOTE: */ + /* the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically */ + /* due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here */ + + ComposePsPoll(pAd); + ComposeNullFrame(pAd); + +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (CFG_P2PGO_ON(pAd)) + AsicEnableApBssSync(pAd); + else +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + AsicEnableBssSync(pAd); + + /* + Add BSSID to WCID search table + We cannot move this to PeerBeaconAtJoinAction because PeerBeaconAtJoinAction wouldn't be invoked in roaming case. + */ + AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(wdev->bssid, pAd->CommonCfg.Bssid); + + /* If WEP is enabled, add paiewise and shared key */ +#ifdef WPA_SUPPLICANT_SUPPORT + if (((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) && + (wdev->WepStatus == Ndis802_11WEPEnabled) && + (wdev->PortSecured == WPA_802_1X_PORT_SECURED)) || + ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) && + (wdev->WepStatus == Ndis802_11WEPEnabled))) +#else + if (wdev->WepStatus == Ndis802_11WEPEnabled) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + UCHAR CipherAlg; + + for (idx = 0; idx < SHARE_KEY_NUM; idx++) { + CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) { + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, idx, + &pAd->SharedKey[BSS0][idx]); + + if (idx == wdev->DefaultKeyId) { + /* STA doesn't need to set WCID attribute for group key */ + + /* Assign pairwise key info to Asic */ + pEntry->Aid = BSSID_WCID; + pEntry->wcid = BSSID_WCID; + RTMPSetWcidSecurityInfo(pAd, + BSS0, + idx, + CipherAlg, + pEntry->wcid, + SHAREDKEYTABLE); + } + } + } + } + /* For GUI ++ */ + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) && (wdev->WepStatus == Ndis802_11WEPEnabled) && (wdev->PortSecured == WPA_802_1X_PORT_SECURED)) + || ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) && (wdev->WepStatus == Ndis802_11WEPEnabled)) + || (wdev->WepStatus == Ndis802_11WEPDisabled)) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + pAd->ExtraInfo = GENERAL_LINK_UP; + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + } + } else if ((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + RTMPSetTimer(&pAd->Mlme.LinkDownTimer, LINK_DOWN_TIMEOUT); + +#ifdef WSC_STA_SUPPORT + if (pAd->StaCfg.WscControl.WscProfileRetryTimerRunning) { + RTMPSetTimer(&pAd->StaCfg.WscControl.WscProfileRetryTimer, + WSC_PROFILE_RETRY_TIME_OUT); + } +#endif /* WSC_STA_SUPPORT */ + } + + + +#ifdef DOT11R_FT_SUPPORT + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->MdIeInfo.Len = 0; + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->MlmeAux.MdIeInfo.Len && + (wdev->WepStatus == Ndis802_11WEPDisabled + || wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pEntry->MdIeInfo.Len = pAd->MlmeAux.MdIeInfo.Len; + FT_SET_MDID(pEntry->MdIeInfo.MdId, + pAd->MlmeAux.MdIeInfo.MdId); + pEntry->MdIeInfo.FtCapPlc.word = + pAd->MlmeAux.MdIeInfo.FtCapPlc.word; + if (pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain == TRUE) { + RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled); + + if (pEntry->WepStatus != Ndis802_11WEPDisabled) { + NdisMoveMemory(pEntry->PTK, + pAd->MacTab.Content[MCAST_WCID].PTK, + 64); + NdisReleaseSpinLock(&pAd->MacTabLock); + + WpaStaGroupKeySetting(pAd); + WpaStaPairwiseKeySetting(pAd); + } else + NdisReleaseSpinLock(&pAd->MacTabLock); + } else + NdisReleaseSpinLock(&pAd->MacTabLock); + } +#endif /* DOT11R_FT_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n", + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + + +#ifdef WSC_STA_SUPPORT + /* + 1. WSC initial connect to AP, set the correct parameters + 2. When security of Marvell WPS AP is OPEN/NONE, Marvell AP will send EAP-Req(ID) to STA immediately. + STA needs to receive this EAP-Req(ID) on time, because Marvell AP will not send again after STA sends EAPOL-Start. + */ + if ((pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger + )) { +#ifdef DOT11R_FT_SUPPORT + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain = FALSE; + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = 0; +#endif /* DOT11R_FT_SUPPORT */ + RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled); + + pAd->StaCfg.WscControl.WscState = WSC_STATE_LINK_UP; + pAd->StaCfg.WscControl.WscStatus = WSC_STATE_LINK_UP; + NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->CommonCfg.Ssid, tmpWscSsid, + tmpWscSsidLen); + pAd->CommonCfg.SsidLen = tmpWscSsidLen; + } else + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif /* CONFIG_AP_SUPPORT */ + &pAd->StaCfg.WscControl); +#endif /* WSC_STA_SUPPORT */ + + MlmeUpdateTxRates(pAd, TRUE, BSS0); +#ifdef DOT11_N_SUPPORT + MlmeUpdateHtTxRates(pAd, BSS0); + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d)\n", + pAd->StaActive.SupportedPhyInfo.bHtEnable)); +#endif /* DOT11_N_SUPPORT */ + +#ifdef WAPI_SUPPORT + if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) { + RTMPInitWapiRekeyTimerAction(pAd, pEntry); + } +#endif /* WAPI_SUPPORT */ + + if (pAd->CommonCfg.bAggregationCapable) { + if ((pAd->CommonCfg.bPiggyBackCapable) + && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + RTMPSetPiggyBack(pAd, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); + } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink Aggregation\n")); + } + } + + if (pAd->MlmeAux.APRalinkIe != 0x0) { +#ifdef DOT11_N_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE)) + AsicSetRDG(pAd, TRUE); +#endif /* DOT11_N_SUPPORT */ + + OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + } else { + OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + } + } + +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT + /* + LED indication. + + LEDConnectionCompletion(pAd, TRUE); + + If we call LEDConnectionCompletion, it will enqueue cmdthread to send asic mcu + command, this may be happen that sending the mcu command with + LED_NORMAL_CONNECTION_WITH_SECURITY will be later than sending the mcu + command with LED_LINK_UP. + + It will cause Tx power LED be unusual after scanning, since firmware + only do Tx power LED in link up state. + */ + /*if (pAd->StaCfg.WscControl.bWPSSession == FALSE) */ + if (pAd->StaCfg.WscControl.WscConfMode == WSC_DISABLE) { + if (LED_MODE(pAd) == WPS_LED_MODE_9) { /* LED mode 9. */ + /* The AP uses OPEN-NONE. */ + if ((wdev->AuthMode == Ndis802_11AuthModeOpen) + && (wdev->WepStatus == Ndis802_11WEPDisabled)) { + RTMPSetLED(pAd, LED_NORMAL_CONNECTION_WITHOUT_SECURITY); + DBGPRINT(RT_DEBUG_TRACE, + ("%s: LED_NORMAL_CONNECTION_WITHOUT_SECURITY\n", + __FUNCTION__)); + } else { /* The AP uses an encryption algorithm. */ + + RTMPSetLED(pAd, LED_NORMAL_CONNECTION_WITH_SECURITY); + DBGPRINT(RT_DEBUG_TRACE, + ("%s: LED_NORMAL_CONNECTION_WITH_SECURITY\n", + __FUNCTION__)); + } + } + } +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", + pAd->CommonCfg.BACapability.word, + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); +#endif /* DOT11_N_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_LINK_UP); +#endif /* LED_CONTROL_SUPPORT */ + + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + pAd->bConfigChanged = FALSE; /* Reset config flag */ + pAd->ExtraInfo = GENERAL_LINK_UP; /* Update extra information to link is up */ + + /* Set asic auto fall back */ + { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, + &pEntry->pTable, &TableSize, + &pAd->CommonCfg.TxRateIndex); + AsicUpdateAutoFallBackTable(pAd, pEntry->pTable); + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->HTPhyMode.word = wdev->HTPhyMode.word; + pEntry->MaxHTPhyMode.word = wdev->MaxHTPhyMode.word; +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + pAd->MlmeAux.vht_cap_len && pAd->MlmeAux.vht_op_len) { + vht_mode_adjust(pAd, pEntry, &pAd->MlmeAux.vht_cap, &pAd->MlmeAux.vht_op); + } +#endif /* DOT11_VHT_AC */ + + if (wdev->bAutoTxRateSwitch == FALSE) { + pEntry->bAutoTxRateSwitch = FALSE; +#ifdef DOT11_N_SUPPORT + if (pEntry->HTPhyMode.field.MCS == 32) + pEntry->HTPhyMode.field.ShortGI = GI_800; + + if ((pEntry->HTPhyMode.field.MCS > MCS_7) + || (pEntry->HTPhyMode.field.MCS == 32)) + pEntry->HTPhyMode.field.STBC = STBC_NONE; +#endif /* DOT11_N_SUPPORT */ + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM) + RTMPUpdateLegacyTxSetting((UCHAR) wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } else + pEntry->bAutoTxRateSwitch = TRUE; + + pEntry->wdev = wdev; + wdev->allow_data_tx = TRUE; + NdisReleaseSpinLock(&pAd->MacTabLock); + + /* Let Link Status Page display first initial rate. */ + pAd->LastTxRate = (USHORT) (pEntry->HTPhyMode.word); + + /* Select DAC according to HT or Legacy */ + if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) + { + { + if (pAd->Antenna.field.TxPath >= 2) + bbp_set_txdac(pAd, 2); + else + bbp_set_txdac(pAd, 0); + } + } else { + bbp_set_txdac(pAd, 0); + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) { + UINT32 factor = 0; + + /* If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. */ + /* Because our Init value is 1 at MACRegTable. */ + switch (pEntry->MaxRAmpduFactor) + { + case 0: + factor = 0x000A0fff; + break; + case 1: + factor = 0x000A1fff; + break; + case 2: + factor = 0x000A2fff; + break; + case 3: + factor = 0x000A3fff; + break; + default: + factor = 0x000A1fff; + break; + } + if (factor) + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, factor); + DBGPRINT(RT_DEBUG_TRACE, ("MaxRAmpduFactor=%d\n", pEntry->MaxRAmpduFactor)); + } +#endif /* DOT11_N_SUPPORT */ + + /* Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable */ + /* if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is. */ +#ifdef DOT11_N_SUPPORT + if (!((pAd->CommonCfg.RxStream == 1) && (pAd->CommonCfg.TxStream == 1)) + && (pAd->StaCfg.bForceTxBurst == FALSE) + && + (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) + && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))) { + burst_txop = 0; + pbf_val = 0x1F3F7F9F; + } else +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.bEnableTxBurst) { + burst_txop = 0x60; + pbf_val = 0x1F3FBF9F; + } else { + burst_txop = 0; + pbf_val = 0x1F3F7F9F; + } + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + pbf_reg = RLT_PBF_MAX_PCNT; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pbf_reg = PBF_MAX_PCNT; + RTMP_IO_WRITE32(pAd, pbf_reg, pbf_val); + } +#endif /* RTMP_MAC */ + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= burst_txop; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + +#ifdef DOT11_N_SUPPORT + /* Re-check to turn on TX burst or not. */ + if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) + && ((STA_WEP_ON(pAd)) || (STA_TKIP_ON(pAd)))) { + if (pAd->CommonCfg.bEnableTxBurst) { + UINT32 MACValue = 0; + /* Force disable TXOP value in this case. The same action in MLMEUpdateProtect too */ + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue); + MACValue &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue); + } + } +#endif /* DOT11_N_SUPPORT */ + + pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE; + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + If STA connects to different AP, STA couldn't send EAPOL_Start for WpaSupplicant. + */ + if ((pAd->StaCfg.BssType == BSS_INFRA) && + (wdev->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory(pAd->CommonCfg.Bssid, pAd->CommonCfg.LastBssid, MAC_ADDR_LEN) == FALSE) && + (pAd->StaCfg.wpa_supplicant_info.bLostAp == TRUE)) { + pAd->StaCfg.wpa_supplicant_info.bLostAp = FALSE; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + /* + Need to check this COPY. This COPY is from Windows Driver. + */ +#ifdef DOT11V_WNM_SUPPORT + WNM_Init(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + + /* BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap */ + /* Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. */ + /* Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. */ + + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->PortSecured = wdev->PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + + /* */ + /* Patch Atheros AP TX will breakdown issue. */ + /* AP Model: DLink DWL-8200AP */ + /* */ + if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) + && STA_TKIP_ON(pAd)) { + RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01); + } else { + RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00); + } + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + /*RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); */ + +#ifdef WSC_STA_SUPPORT + /* WSC initial connect to AP, jump to Wsc start action and set the correct parameters */ + if ((pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger + )) { + RtmpusecDelay(100000); /* 100 ms */ + if (pAd->StaCfg.BssType == BSS_INFRA) { + NdisMoveMemory(pAd->StaCfg.WscControl.WscPeerMAC, + pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + NdisMoveMemory(pAd->StaCfg.WscControl.EntryAddr, + pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + WscSendEapolStart(pAd, + pAd->StaCfg.WscControl.WscPeerMAC, STA_MODE); + } + } +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (INFRA_ON(pAd)) { + if ((pAd->CommonCfg.bBssCoexEnable == TRUE) + && (pAd->CommonCfg.Channel <= 14) + && (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) + && (pAd->MlmeAux.ExtCapInfo.BssCoexistMgmtSupport == 1)) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040); + BuildEffectedChannelList(pAd); + DBGPRINT(RT_DEBUG_TRACE, + ("LinkUP AP supports 20/40 BSS COEX, Dot11BssWidthTriggerScanInt[%d]\n", + pAd->CommonCfg.Dot11BssWidthTriggerScanInt)); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("not supports 20/40 BSS COEX !!! \n")); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->CommonCfg Info: bBssCoexEnable=%d, Channel=%d, CentralChannel=%d, PhyMode=%d\n", + pAd->CommonCfg.bBssCoexEnable, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel, pAd->CommonCfg.PhyMode)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->StaActive.SupportedHtPhy.bHtEnable=%d\n", + pAd->StaActive.SupportedPhyInfo.bHtEnable)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->MlmeAux.ExtCapInfo.BssCoexstSup=%d\n", + pAd->MlmeAux.ExtCapInfo.BssCoexistMgmtSupport)); + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + When AuthMode is WPA2-Enterprise and AP reboot or STA lost AP, + WpaSupplicant would not send EapolStart to AP after STA re-connect to AP again. + In this case, driver would send EapolStart to AP. + */ + if ((pAd->StaCfg.BssType == BSS_INFRA) && + (wdev->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory + (pAd->CommonCfg.Bssid, pAd->CommonCfg.LastBssid, MAC_ADDR_LEN)) + && (pAd->StaCfg.wpa_supplicant_info.bLostAp == TRUE)) { + WpaSendEapolStart(pAd, pAd->CommonCfg.Bssid); + pAd->StaCfg.wpa_supplicant_info.bLostAp = FALSE; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef CONFIG_MULTI_CHANNEL + RtmpPrepareHwNullFrame(pAd, + &pAd->MacTab.Content[BSSID_WCID], + FALSE, + FALSE, + 0, + OPMODE_STA, + PWR_SAVE, + 0, + 0); +#endif /* CONFIG_MULTI_CHANNEL */ + + + pAd->MacTab.MsduLifeTime = 5; /* default 5 seconds */ + +#ifdef MICROWAVE_OVEN_SUPPORT + pAd->CommonCfg.MO_Cfg.bEnable = TRUE; +#endif /* MICROWAVE_OVEN_SUPPORT */ + +} + + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + IsReqFromAP - Request from AP + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + We need more information to know it's this requst from AP. + If yes! we need to do extra handling, for example, remove the WPA key. + Otherwise on 4-way handshaking will faied, since the WPA key didn't be + remove while auto reconnect. + Disconnect request from AP, it means we will start afresh 4-way handshaking + on WPA mode. + + ========================================================================== +*/ +VOID LinkDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN IsReqFromAP) +{ + UCHAR i; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /* Do nothing if monitor mode is on */ + if (MONITOR_ON(pAd)) + return; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode. */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + +#ifdef PCIE_PS_SUPPORT + /* Not allow go to sleep within linkdown function. */ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ + + + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, NULL, BSS0, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + + /* reset to not doing improved scan */ + pAd->StaCfg.bImprovedScan = FALSE; + +#ifdef RT_CFG80211_SUPPORT + if (CFG80211DRV_OpsScanRunning(pAd)) + CFG80211DRV_OpsScanInLinkDownAction(pAd); +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef PCIE_PS_SUPPORT + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { + BOOLEAN Cancelled; + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } + + pAd->bPCIclkOff = FALSE; +#endif /* PCIE_PS_SUPPORT */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) +/*|| RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) */ + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + AsicForceWakeup(pAd, TRUE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + } + + if (ADHOC_ON(pAd)) { /* Adhoc mode link down */ + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n")); + +#ifdef ADHOC_WPA2PSK_SUPPORT + /* In an IBSS, a STA's SME responds to Deauthenticate frames from a STA by */ + /* deleting the PTKSA associated with that STA. (Spec. P802.11i/D10 P.19) */ + if (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) { + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i])) + MlmeDeAuthAction(pAd, + &pAd->MacTab.Content[i], + REASON_DEAUTH_STA_LEAVING, + FALSE); + } + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, + pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size)); + } else { /* Infra structure mode */ + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n")); + +#ifdef QOS_DLS_SUPPORT + /* DLS tear down frame must be sent before link down */ + /* send DLS-TEAR_DOWN message */ + if (pAd->CommonCfg.bDLSCapable) { + /* tear down local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + RTMPSendDLSTearDownFrame(pAd, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + /* tear down peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; + i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + } +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + if (IS_TDLS_SUPPORT(pAd)) { + TDLS_LinkTearDown(pAd, TRUE); + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + +#ifdef DOT11V_WNM_SUPPORT + WNM_Init(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + + /* Saved last SSID for linkup comparison */ + pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, + pAd->CommonCfg.LastSsidLen); + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n")); + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + } else { + if ((wdev->PortSecured == WPA_802_1X_PORT_SECURED) + || (wdev->AuthMode < Ndis802_11AuthModeWPA)) { + /* + If disassociation request is from NDIS, then we don't need + to delete BSSID from entry. Otherwise lost beacon or receive + De-Authentication from AP, then we should delete BSSID + from BssTable. + + If we don't delete from entry, roaming will fail. + */ + BssTableDeleteEntry(&pAd->ScanTab, + pAd->CommonCfg.Bssid, + pAd->CommonCfg.Channel); + } + } + + /* + restore back to - + 1. long slot (20 us) or short slot (9 us) time + 2. turn on/off RTS/CTS and/or CTS-to-self protection + 3. short preamble + */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + +#ifdef EXT_BUILD_CHANNEL_LIST + /* Country IE of the AP will be evaluated and will be used. */ + if (pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) { + NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], + &pAd->StaCfg.StaOriCountryCode[0], 2); + pAd->CommonCfg.Geography = pAd->StaCfg.StaOriGeography; + BuildChannelListEx(pAd); + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + + } + +#ifdef WAPI_SUPPORT + if (wdev->WepStatus == Ndis802_11EncryptionSMS4Enabled) { + /* Cancel rekey timer */ + RTMPCancelWapiRekeyTimerAction(pAd, + &pAd->MacTab.Content[BSSID_WCID]); + } +#endif /* WAPI_SUPPORT */ + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) + ) + MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, + pAd->MacTab.Content[i].Addr); + } + + AsicSetSlotTime(pAd, TRUE); /*FALSE); */ +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if ((!RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) && (!RTMP_CFG80211_VIF_P2P_CLI_ON(pAd))) +#else +#endif /* RT_CFG80211_P2P_SUPPORT */ + AsicSetEdcaParm(pAd, NULL); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_DOWN); + pAd->LedCntl.LedIndicatorStrength = 0xF0; + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */ +#endif /* LED_CONTROL_SUPPORT */ + + AsicDisableSync(pAd); + + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof (HT_CAPABILITY_IE)); + NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof (ADD_HT_INFO_IE)); + pAd->MlmeAux.HtCapabilityLen = 0; + pAd->MlmeAux.NewExtChannelOffset = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("LinkDownCleanMlmeAux.ExtCapInfo!\n")); + NdisZeroMemory((PUCHAR) (&pAd->MlmeAux.ExtCapInfo), + sizeof (EXT_CAP_INFO_ELEMENT)); +#endif /* DOT11_N_SUPPORT */ + + /* Reset WPA-PSK state. Only reset when supplicant enabled */ + if (pAd->StaCfg.WpaState != SS_NOTUSE) { + pAd->StaCfg.WpaState = SS_START; + /* Clear Replay counter */ + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + +#ifdef QOS_DLS_SUPPORT + if (pAd->CommonCfg.bDLSCapable) + NdisZeroMemory(pAd->StaCfg.DlsReplayCounter, 8); +#endif /* QOS_DLS_SUPPORT */ + } + + /* + if link down come from AP, we need to remove all WPA keys on WPA mode. + otherwise will cause 4-way handshaking failed, since the WPA key not empty. + */ + if ((IsReqFromAP) && (wdev->AuthMode >= Ndis802_11AuthModeWPA)) { + /* Remove all WPA keys */ + RTMPWPARemoveAllKeys(pAd); + } + + /* 802.1x port control */ +#ifdef WPA_SUPPLICANT_SUPPORT + /* Prevent clear PortSecured here with static WEP */ + /* NetworkManger set security policy first then set SSID to connect AP. */ + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP && + (wdev->WepStatus == Ndis802_11WEPEnabled) && + (wdev->IEEE8021X == FALSE)) { + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + } else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + NdisZeroMemory(&pAd->MacTab.Content[BSSID_WCID], sizeof(MAC_TABLE_ENTRY)); + pAd->MacTab.Content[BSSID_WCID].PortSecured = wdev->PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + + pAd->StaCfg.MicErrCnt = 0; + + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + /* Update extra information to link is up */ + pAd->ExtraInfo = GENERAL_LINK_DOWN; + + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + + + /* Clean association information */ + NdisZeroMemory(&pAd->StaCfg.AssocInfo, + sizeof (NDIS_802_11_ASSOCIATION_INFORMATION)); + pAd->StaCfg.AssocInfo.Length = + sizeof (NDIS_802_11_ASSOCIATION_INFORMATION); + pAd->StaCfg.ReqVarIELen = 0; + pAd->StaCfg.ResVarIELen = 0; + + + /* Reset RSSI value after link down */ + NdisZeroMemory((PUCHAR) (&pAd->StaCfg.RssiSample), + sizeof (pAd->StaCfg.RssiSample)); + + /* Restore MlmeRate */ + pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate; + pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate; + +#ifdef DOT11_N_SUPPORT + // TODO: shiang-6590, why we need to fallback to BW_20 here? How about the BW_10? + if (pAd->CommonCfg.BBPCurrentBW != BW_20) { + { + bbp_set_bw(pAd, BW_20); + } + } +#endif /* DOT11_N_SUPPORT */ + + { + /* Reset DAC */ + { + if (pAd->Antenna.field.TxPath >= 2) + bbp_set_txdac(pAd, 2); + else + bbp_set_txdac(pAd, 0); + } + } + + /* After Link down, reset piggy-back setting in ASIC. Disable RDG. */ + RTMPSetPiggyBack(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word; +#endif /* DOT11_N_SUPPORT */ + + /* Restore all settings in the following. */ + AsicUpdateProtect(pAd, 0, + (ALLN_SETPROTECT | CCKSETPROTECT | OFDMSETPROTECT), + TRUE, FALSE); + +#ifdef DOT11_N_SUPPORT + AsicSetRDG(pAd, FALSE); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SCAN_2040); + pAd->CommonCfg.BSSCoexist2040.word = 0; + TriEventInit(pAd); + for (i = 0; i < (pAd->ChannelListNum - 1); i++) { + pAd->ChannelList[i].bEffectedChannel = FALSE; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +/* Allow go to sleep after linkdown steps. */ +#ifdef PCIE_PS_SUPPORT + + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); +#endif /* PCIE_PS_SUPPORT */ + + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) { + /*send disassociate event to wpa_supplicant */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, + RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); + } +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CGIWAP, -1, NULL, + NULL, 0); +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + RT_CFG80211_LOST_AP_INFORM(pAd); +#endif /* RT_CFG80211_SUPPORT */ + + + if (pAd->StaCfg.BssType != BSS_ADHOC) + pAd->StaCfg.bNotFirstScan = FALSE; + else + pAd->StaCfg.bAdhocCreator = FALSE; + +/*After change from one ap to another , we need to re-init rssi for AdjustTxPower */ + pAd->StaCfg.RssiSample.AvgRssi0 = -127; + pAd->StaCfg.RssiSample.AvgRssi1 = -127; + pAd->StaCfg.RssiSample.AvgRssi2 = -127; + + NdisZeroMemory(pAd->StaCfg.ConnectinfoSsid, MAX_LEN_OF_SSID); + NdisZeroMemory(pAd->StaCfg.ConnectinfoBssid, MAC_ADDR_LEN); + pAd->StaCfg.ConnectinfoSsidLen = 0; + pAd->StaCfg.ConnectinfoBssType = 1; + pAd->StaCfg.ConnectinfoChannel = 0; + +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID IterateOnBssTab(RTMP_ADAPTER *pAd) +{ + MLME_START_REQ_STRUCT StartReq; + MLME_JOIN_REQ_STRUCT JoinReq; + ULONG BssIdx; + BSS_ENTRY *pInBss = NULL; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + + /* Change the wepstatus to original wepstatus */ + pAd->StaCfg.PairCipher = wdev->WepStatus; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + pAd->StaCfg.GroupCipher = wdev->WepStatus; + + BssIdx = pAd->MlmeAux.BssIdx; + + if (pAd->StaCfg.BssType == BSS_ADHOC) { + if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) { + pInBss = &pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - iterate BSS %ld of %d\n", BssIdx, + pAd->MlmeAux.SsidBssTab.BssNr)); + JoinParmFill(pAd, &JoinReq, BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, + sizeof (MLME_JOIN_REQ_STRUCT), &JoinReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; +#ifdef WSC_STA_SUPPORT + if (pAd->StaCfg.WscControl.WscState >= WSC_STATE_START) { + NdisMoveMemory(pAd->StaCfg.WscControl.WscPeerMAC, pInBss->MacAddr, + MAC_ADDR_LEN); + NdisMoveMemory(pAd->StaCfg.WscControl.EntryAddr, + pInBss->MacAddr, MAC_ADDR_LEN); + } +#endif /* WSC_STA_SUPPORT */ + return; + } +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.WscControl.bWscTrigger == TRUE) + { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_MLME_RECONNECT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } + else +#endif /* IWSC_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, (PCHAR) pAd->MlmeAux.Ssid,pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof (MLME_START_REQ_STRUCT), &StartReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + } + else if ((BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) && + (pAd->StaCfg.BssType == BSS_INFRA)) { + pInBss = &pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]; + /* Check cipher suite, AP must have more secured cipher than station setting */ + /* Set the Pairwise and Group cipher to match the intended AP setting */ + /* We can only connect to AP with less secured cipher setting */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) + || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) { + pAd->StaCfg.GroupCipher = pInBss->WPA.GroupCipher; + + if (wdev->WepStatus == pInBss->WPA.PairCipher) + pAd->StaCfg.PairCipher = pInBss->WPA.PairCipher; + else if (pInBss->WPA.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pInBss->WPA.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + } else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pAd->StaCfg.GroupCipher = pInBss->WPA2.GroupCipher; + + if (wdev->WepStatus == pInBss->WPA2.PairCipher) + pAd->StaCfg.PairCipher = pInBss->WPA2.PairCipher; + else if (pInBss->WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pInBss->WPA2.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + + /* RSN capability */ + pAd->StaCfg.RsnCapability = pInBss->WPA2.RsnCapability; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) { + pAd->StaCfg.GroupCipher = pInBss->WAPI.GroupCipher; + pAd->StaCfg.PairCipher = pInBss->WAPI.PairCipher; + } +#endif /* WAPI_SUPPORT */ + + /* Set Mix cipher flag */ + pAd->StaCfg.bMixCipher = + (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - iterate BSS %ld of %d\n", BssIdx, + pAd->MlmeAux.SsidBssTab.BssNr)); + JoinParmFill(pAd, &JoinReq, BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, + sizeof (MLME_JOIN_REQ_STRUCT), &JoinReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + else + { + /* no more BSS */ +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + } + + { + pAd->MlmeAux.SsidBssTab.BssNr = 0; + BssTableDeleteEntry(&pAd->ScanTab, + pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid, + pAd->MlmeAux.SsidBssTab.BssEntry[0].Channel); + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT + /* LED indication. */ + LEDConnectionCompletion(pAd, FALSE); +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + } +} + + +/* for re-association only */ +/* IRQL = DISPATCH_LEVEL */ +VOID IterateOnBssTab2(RTMP_ADAPTER *pAd) +{ + MLME_REASSOC_REQ_STRUCT ReassocReq; + ULONG BssIdx; + BSS_ENTRY *pBss; + + BssIdx = pAd->MlmeAux.RoamIdx; + pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx]; + + if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - iterate BSS %ld of %d\n", BssIdx, + pAd->MlmeAux.RoamTab.BssNr)); + + AsicSwitchChannel(pAd, pBss->Channel, FALSE); + AsicLockChannel(pAd, pBss->Channel); + + /* reassociate message has the same structure as associate message */ + AssocParmFill(pAd, &ReassocReq, pBss->Bssid, + pBss->CapabilityInfo, ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, + sizeof (MLME_REASSOC_REQ_STRUCT), &ReassocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } else { + /* no more BSS */ + UCHAR rf_channel = 0; + UINT8 rf_bw, ext_ch; + +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + { + rf_channel = pAd->CommonCfg.Channel; + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + } + + if (rf_channel != 0) { + AsicSetChannel(pAd, rf_channel, rf_bw, ext_ch, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s():CNTL - All roaming failed, restore to Channel(Ctrl=%d, Central = %d)\n", + __FUNCTION__, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID JoinParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx) +{ + JoinReq->BssIdx = BssIdx; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +#ifdef QOS_DLS_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID DlsParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, + IN PRT_802_11_DLS pDls, + IN USHORT reason) +{ + pDlsReq->pDLS = pDls; + pDlsReq->Reason = reason; +} +#endif /* QOS_DLS_SUPPORT */ + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID StartParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + ASSERT(SsidLen <= MAX_LEN_OF_SSID); + if (SsidLen > MAX_LEN_OF_SSID) + SsidLen = MAX_LEN_OF_SSID; + NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen); + StartReq->SsidLen = SsidLen; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg) +{ + COPY_MAC_ADDR(AuthReq->Addr, pAddr); + AuthReq->Alg = Alg; + AuthReq->Timeout = AUTH_TIMEOUT; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + +/* + ========================================================================== + Description: + Pre-build a BEACON frame in the shared memory + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +ULONG MakeIbssBeacon( + IN PRTMP_ADAPTER pAd) +{ + UCHAR DsLen = 1, IbssLen = 2; + UCHAR LocalErpIe[3] = { IE_ERP, 1, 0x04 }; + HEADER_802_11 BcnHdr; + USHORT CapabilityInfo; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + TXWI_STRUC *pTxWI = &pAd->BeaconTxWI; + UCHAR *pBeaconFrame = pAd->BeaconBuf; + BOOLEAN Privacy; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen = 0; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen = 0; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B) + && (pAd->CommonCfg.Channel <= 14)) { + SupRate[0] = 0x82; /* 1 mbps */ + SupRate[1] = 0x84; /* 2 mbps */ + SupRate[2] = 0x8b; /* 5.5 mbps */ + SupRate[3] = 0x96; /* 11 mbps */ + SupRateLen = 4; + ExtRateLen = 0; + } else if (pAd->CommonCfg.Channel > 14) { + SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */ + SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */ + SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */ + SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + SupRateLen = 8; + ExtRateLen = 0; + + /* */ + /* Also Update MlmeRate & RtsRate for G only & A only */ + /* */ + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } else { + SupRate[0] = 0x82; /* 1 mbps */ + SupRate[1] = 0x84; /* 2 mbps */ + SupRate[2] = 0x8b; /* 5.5 mbps */ + SupRate[3] = 0x96; /* 11 mbps */ + SupRateLen = 4; + + ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps, */ + ExtRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + ExtRate[2] = 0x18; /* 12 mbps, in units of 0.5 Mbps, */ + ExtRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + ExtRate[4] = 0x30; /* 24 mbps, in units of 0.5 Mbps, */ + ExtRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + ExtRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + ExtRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + ExtRateLen = 8; + } + + pAd->StaActive.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen); + pAd->StaActive.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen); + + /* compose IBSS beacon frame */ + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, + pAd->CurrentAddress, + pAd->CommonCfg.Bssid); + Privacy = (wdev->WepStatus == Ndis802_11WEPEnabled) + || (wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable); + CapabilityInfo = + CAP_GENERATE(0, 1, Privacy, + (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), + 0, 0); + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof (HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, 2, &pAd->StaActive.AtimWin, END_OF_ARGS); + + /* add ERP_IE and EXT_RAE IE of in 802.11g */ + if (ExtRateLen) { + ULONG tmp; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, ExtRate, END_OF_ARGS); + FrameLen += tmp; + } + + /* If adhoc secruity is set for WPA-None, append the cipher suite IE */ + /* Modify by Eddy, support WPA2PSK in Adhoc mode */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPANone) +#ifdef ADHOC_WPA2PSK_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#endif /* ADHOC_WPA2PSK_SUPPORT */ + ) { + UCHAR RSNIe = IE_WPA; + ULONG tmp; + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, BSS0); +#ifdef ADHOC_WPA2PSK_SUPPORT + if (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) + RSNIe = IE_RSN; +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } +#ifdef WSC_STA_SUPPORT + /* add Simple Config Information Element */ + if (pAd->StaCfg.WpsIEBeacon.ValueLen != 0) { + ULONG WscTmpLen = 0; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &WscTmpLen, + pAd->StaCfg.WpsIEBeacon.ValueLen, + pAd->StaCfg.WpsIEBeacon.Value, END_OF_ARGS); + FrameLen += WscTmpLen; + } +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && (pAd->StaCfg.bAdhocN == TRUE)) { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; + USHORT b2lTmp, b2lTmp2; +#endif + + /* add HT Capability IE */ + HtLen = sizeof (pAd->CommonCfg.HtCapability); + HtLen1 = sizeof (pAd->CommonCfg.AddHTInfo); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, + HtLen); + *(USHORT *) (&HtCapabilityTmp.HtCapInfo) = + SWAP16(*(USHORT *) (&HtCapabilityTmp.HtCapInfo)); + *(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo) = + SWAP16(*(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo)); + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, + HtLen1); + *(USHORT *) (&addHTInfoTmp.AddHtInfo2) = + SWAP16(*(USHORT *) (&addHTInfoTmp.AddHtInfo2)); + *(USHORT *) (&addHTInfoTmp.AddHtInfo3) = + SWAP16(*(USHORT *) (&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, END_OF_ARGS); +#endif + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ + + /*beacon use reserved WCID 0xff */ + if (pAd->CommonCfg.Channel > 14) { + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, + TRUE, 0, 0xff, FrameLen, PID_MGMT, PID_BEACON, + RATE_1, IFS_HTTXOP, + &pAd->CommonCfg.MlmeTransmit); + } else { + /* Set to use 1Mbps for Adhoc beacon. */ + HTTRANSMIT_SETTING Transmit; + Transmit.word = 0; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, + TRUE, 0, 0xff, FrameLen, PID_MGMT, PID_BEACON, + RATE_1, IFS_HTTXOP, &Transmit); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pBeaconFrame, DIR_WRITE, FALSE); + RTMPWIEndianChange(pAd, (PUCHAR) pTxWI, TYPE_TXWI); +#endif + + DBGPRINT(RT_DEBUG_TRACE, + ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n", + FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, + pAd->CommonCfg.PhyMode)); + return FrameLen; +} + +VOID InitChannelRelatedValue(RTMP_ADAPTER *pAd) +{ + UCHAR rf_channel; + UINT8 rf_bw, ext_ch; + +#ifdef RTMP_MAC_PCI + /* In power save , We will force use 1R. */ + /* So after link up, check Rx antenna # again. */ + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); +#endif /* RTMP_MAC_PCI */ + + pAd->CommonCfg.CentralChannel = pAd->MlmeAux.CentralChannel; + pAd->CommonCfg.Channel = pAd->MlmeAux.Channel; +#ifdef DOT11_N_SUPPORT + /* Change to AP channel */ + if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) { + rf_channel = pAd->CommonCfg.CentralChannel; + rf_bw = BW_40; + ext_ch = EXTCHA_ABOVE; + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + rf_channel = pAd->CommonCfg.CentralChannel; + rf_bw = BW_40; + ext_ch = EXTCHA_BELOW; + } else +#endif /* DOT11_N_SUPPORT */ + { + rf_channel = pAd->CommonCfg.CentralChannel; + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + } + + AsicSetChannel(pAd, rf_channel, rf_bw, ext_ch, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s():BW_%s, CtrlChannel=%d, CentralChannel=%d\n", + __FUNCTION__, (rf_bw == BW_40 ? "40" : "20"), + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + + /* Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission */ + bbp_get_agc(pAd, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); +} + +/* IRQL = DISPATCH_LEVEL */ +VOID MaintainBssTable( + IN PRTMP_ADAPTER pAd, + IN OUT BSS_TABLE *Tab, + IN ULONG MaxRxTimeDiff, + IN UCHAR MaxSameRxTimeCount) +{ + UCHAR i, j; + UCHAR total_bssNr = Tab->BssNr; + BOOLEAN bDelEntry = FALSE; + ULONG now_time = 0; + + for (i = 0; i < total_bssNr; i++) + { + BSS_ENTRY *pBss = &Tab->BssEntry[i]; + + bDelEntry = FALSE; + if (pBss->LastBeaconRxTimeA != pBss->LastBeaconRxTime) + { + pBss->LastBeaconRxTimeA = pBss->LastBeaconRxTime; + pBss->SameRxTimeCount = 0; + } + else + pBss->SameRxTimeCount++; + + NdisGetSystemUpTime(&now_time); + if (RTMP_TIME_AFTER(now_time, pBss->LastBeaconRxTime + (MaxRxTimeDiff * OS_HZ))) + bDelEntry = TRUE; + else if (pBss->SameRxTimeCount > MaxSameRxTimeCount) + bDelEntry = TRUE; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + && NdisEqualMemory(pBss->Ssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + bDelEntry = FALSE; + + if (bDelEntry) + { + UCHAR *pOldAddr = NULL; + + for (j = i; j < total_bssNr - 1; j++) + { + pOldAddr = Tab->BssEntry[j].pVarIeFromProbRsp; + NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); + if (pOldAddr) + { + RTMPZeroMemory(pOldAddr, MAX_VIE_LEN); + NdisMoveMemory(pOldAddr, + Tab->BssEntry[j + 1].pVarIeFromProbRsp, + Tab->BssEntry[j + 1].VarIeFromProbeRspLen); + Tab->BssEntry[j].pVarIeFromProbRsp = pOldAddr; + } + } + + pOldAddr = Tab->BssEntry[total_bssNr - 1].pVarIeFromProbRsp; + NdisZeroMemory(&(Tab->BssEntry[total_bssNr - 1]), sizeof(BSS_ENTRY)); + if (pOldAddr) + { + RTMPZeroMemory(pOldAddr, MAX_VIE_LEN); + } + + total_bssNr -= 1; + } + } + Tab->BssNr = total_bssNr; +} + +VOID AdjustChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *pBwFallBack, + IN USHORT ifIndex, + IN BOOLEAN BandWidth, + IN UCHAR PriCh, + IN UCHAR ExtraCh) +{ + UCHAR rf_channel; + UINT8 rf_bw = BW_20, ext_ch; + + // TODO: shiang-6590, this function need to revise to make sure two purpose can achieved! + // 1. Channel-binding rule between STA and P2P-GO mode + // 2. Stop MAC Tx/Rx when bandwidth change + + *pBwFallBack = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():CentralChannel=%d, Channel=%d, ChannelWidth=%d\n", + __FUNCTION__, ExtraCh, PriCh, BandWidth)); + + pAd->CommonCfg.CentralChannel = ExtraCh; + pAd->CommonCfg.Channel = PriCh; +#ifdef DOT11_N_SUPPORT + /* Change to AP channel */ + if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (BandWidth == BW_40)) + { + rf_channel = pAd->CommonCfg.CentralChannel; + rf_bw = BW_40; + ext_ch = EXTCHA_ABOVE; + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (BandWidth == BW_40)) + { + rf_channel = pAd->CommonCfg.CentralChannel; + rf_bw = BW_40; + ext_ch = EXTCHA_BELOW; + } + else +#endif /* DOT11_N_SUPPORT */ + { + rf_channel = pAd->CommonCfg.Channel; + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + } + +#ifdef DOT11_VHT_AC + pAd->CommonCfg.vht_cent_ch = ExtraCh; + if (rf_bw == BW_40 && + pAd->StaActive.SupportedPhyInfo.bVhtEnable == TRUE && + pAd->StaActive.SupportedPhyInfo.vht_bw == VHT_BW_80) { + rf_bw = BW_80; + rf_channel = pAd->CommonCfg.vht_cent_ch; + } + DBGPRINT(RT_DEBUG_OFF, ("%s(): Input BW=%d, rf_channel=%d, vht_bw=%d, Channel=%d, vht_cent_ch=%d!\n", + __FUNCTION__, rf_bw, rf_channel, pAd->CommonCfg.vht_bw, pAd->CommonCfg.Channel, + pAd->CommonCfg.vht_cent_ch)); +#endif /* DOT11_VHT_AC */ + + bbp_set_bw(pAd, rf_bw); + bbp_set_ctrlch(pAd, ext_ch); + rtmp_mac_set_ctrlch(pAd, ext_ch); + + AsicSetChannel(pAd, rf_channel, rf_bw, ext_ch, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s():BW_%s, RF-Ch=%d, CtrlCh=%d, HT-CentralCh=%d\n", + __FUNCTION__, (rf_bw == BW_80 ? "80" : (rf_bw == BW_40 ? "40": "20")), + pAd->LatchRfRegs.Channel, + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); +#ifdef DOT11_VHT_AC + DBGPRINT(RT_DEBUG_TRACE, ("VHT-CentralCh=%d\n", pAd->CommonCfg.vht_cent_ch)); +#endif /* DOT11_VHT_AC */ + + DBGPRINT(RT_DEBUG_TRACE, ("AdjustChannelRelatedValue ==> not any connection !!!\n")); + +#ifdef DYNAMIC_VGA_SUPPORT +#ifdef MT76x2 + if (IS_MT76x2(pAd)) { + mt76x2_reinit_agc_gain(pAd, pAd->hw_cfg.cent_ch); + mt76x2_reinit_hi_lna_gain(pAd, pAd->hw_cfg.cent_ch); + mt76x2_get_agc_gain(pAd, TRUE); + /* MAC will be disabled by calibration, so it should finish before any packet arrival */ + mt76x2_calibration(pAd, pAd->hw_cfg.cent_ch); + } +#endif /* MT76x2 */ +#endif /* DYNAMIC_VGA_SUPPORT */ +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/dls.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/dls.c new file mode 100644 index 000000000..87dc26ae9 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/dls.c @@ -0,0 +1,2077 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2005, 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: + dls.c + + Abstract: + Handle WMM-DLS state machine + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Rory Chen 02-14-2006 + Arvin Tai 06-03-2008 Modified for RT28xx + */ + +#include "rt_config.h" + +/* + ========================================================================== + Description: + dls state machine init, including state transition and timer init + Parameters: + Sm - pointer to the dls state machine + Note: + The state machine looks like this + + DLS_IDLE + MT2_MLME_DLS_REQUEST MlmeDlsReqAction + MT2_PEER_DLS_REQUEST PeerDlsReqAction + MT2_PEER_DLS_RESPONSE PeerDlsRspAction + MT2_MLME_DLS_TEARDOWN MlmeTearDownAction + MT2_PEER_DLS_TEARDOWN PeerTearDownAction + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +void DlsStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + + StateMachineInit(Sm, (STATE_MACHINE_FUNC *) Trans, MAX_DLS_STATE, + MAX_DLS_MSG, (STATE_MACHINE_FUNC) Drop, DLS_IDLE, + DLS_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, + (STATE_MACHINE_FUNC) MlmeDlsReqAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, + (STATE_MACHINE_FUNC) PeerDlsReqAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, + (STATE_MACHINE_FUNC) PeerDlsRspAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, + (STATE_MACHINE_FUNC) MlmeDlsTearDownAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, + (STATE_MACHINE_FUNC) PeerDlsTearDownAction); + + for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++) { + pAd->StaCfg.DLSEntry[i].pAd = pAd; + RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, + GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DlsReqHdr; + PRT_802_11_DLS pDLS = NULL; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_REQUEST; + ULONG tmp; + USHORT reason; + ULONG Timeout; + BOOLEAN TimerCancelled; + + if (!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("DLS - MlmeDlsReqAction() \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - MlmeDlsReqAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &DlsReqHdr, + 1, &Category, + 1, &Action, + 6, &pDLS->MacAddr, + 6, pAd->CurrentAddress, + 2, &pAd->StaActive.CapabilityInfo, + 2, &pDLS->TimeOut, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + /* add HT Capability IE */ + HtLen = sizeof (HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *) (&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.HtCapInfo)); + *(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, END_OF_ARGS); +#endif + FrameLen = FrameLen + tmp; + } +#endif /* DOT11_N_SUPPORT */ + + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + Timeout = DLS_TIMEOUT; + RTMPSetTimer(&pDLS->Timer, Timeout); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT StatusCode = MLME_SUCCESS; + HEADER_802_11 DlsRspHdr; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_RESPONSE; + ULONG tmp; + USHORT CapabilityInfo; + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT DLSTimeOut; + SHORT i; + ULONG Timeout; + BOOLEAN TimerCancelled; + PRT_802_11_DLS pDLS = NULL; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + + if (!PeerDlsReqSanity + (pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut, + &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, + &HtCapability)) + return; + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + MaxSupportedRateIn500Kbps = dot11_max_sup_rate(SupportedRatesLen, &SupportedRates[0], 0, NULL); + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - PeerDlsReqAction() allocate memory failed \n")); + return; + } + + if (!INFRA_ON(pAd)) { + StatusCode = MLME_REQUEST_DECLINED; + } else if (!pAd->CommonCfg.bWmmCapable) { + StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA; + } else if (!pAd->CommonCfg.bDLSCapable) { + StatusCode = MLME_REQUEST_DECLINED; + } else { + /* find table to update parameters */ + for (i = (MAX_NUM_OF_DLS_ENTRY - 1); i >= 0; i--) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + if (pAd->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + else { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + } + + pAd->StaCfg.DLSEntry[i].Sequence = 0; + pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; + pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + pDLS = &pAd->StaCfg.DLSEntry[i]; + break; + } + } + + /* can not find in table, create a new one */ + if (i < 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsReqAction() can not find same entry \n")); + for (i = (MAX_NUM_OF_DLS_ENTRY - 1); + i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--) { + if (!pAd->StaCfg.DLSEntry[i].Valid) { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + if (pAd->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + } else { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + } + + pAd->StaCfg.DLSEntry[i].Sequence = 0; + pAd->StaCfg.DLSEntry[i].Valid = TRUE; + pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; + pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; + NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN); + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + pDLS = &pAd->StaCfg.DLSEntry[i]; + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + set_entry_phy_cfg(pAd, pEntry); + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(SA))); + + ht_mode_adjust(pAd, pEntry, &HtCapability, &pAd->CommonCfg.DesiredHtPhy); + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &pAd->StaCfg.wdev.DesiredHtPhyInfo.MCSSet[0], &HtCapability.MCSSet[0]); + + if (pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS != MCS_AUTO) { + + DBGPRINT(RT_DEBUG_OFF, + ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS)); + set_ht_fixed_mcs(pAd, pEntry, pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS, pAd->StaCfg.wdev.HTPhyMode.field.MCS); + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR) HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR) HtCapability.HtCapInfo.AMsduSize; + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg + && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, + &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.wdev.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, + pEntry, + &pEntry->pTable, + &TableSize, + &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.wdev.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.wdev.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + break; + } + } + } + StatusCode = MLME_SUCCESS; + + /* can not find in table, create a new one */ + if (i < 0) { + StatusCode = MLME_QOS_UNSPECIFY; + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", + MAX_NUM_OF_DLS_ENTRY - + MAX_NUM_OF_INIT_DLS_ENTRY)); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n", + i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + } + + ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + /* Build basic frame first */ + if (StatusCode == MLME_SUCCESS) { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &DlsRspHdr, + 1, &Category, + 1, &Action, + 2, &StatusCode, + 6, SA, + 6, pAd->CurrentAddress, + 2, &pAd->StaActive.CapabilityInfo, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRate, END_OF_ARGS); + FrameLen += tmp; + } +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + /* add HT Capability IE */ + HtLen = sizeof (HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *) (&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.HtCapInfo)); + *(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *) (&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, END_OF_ARGS); +#endif + FrameLen = FrameLen + tmp; + } +#endif /* DOT11_N_SUPPORT */ + + if (pDLS && (pDLS->Status != DLS_FINISH)) { + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + Timeout = DLS_TIMEOUT; + RTMPSetTimer(&pDLS->Timer, Timeout); + } + } else { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &DlsRspHdr, + 1, &Category, + 1, &Action, + 2, &StatusCode, + 6, SA, 6, pAd->CurrentAddress, END_OF_ARGS); + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo; + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT StatusCode; + SHORT i; + BOOLEAN TimerCancelled; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + if (!PeerDlsRspSanity + (pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode, + &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, + &HtCapability)) + return; + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + MaxSupportedRateIn500Kbps = dot11_max_sup_rate(SupportedRatesLen, &SupportedRates[0], 0, NULL); + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n", + PRINT_MAC(SA), StatusCode, + CapabilityInfo)); + + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + if (StatusCode == MLME_SUCCESS) { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + set_entry_phy_cfg(pAd, pEntry); + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + DBGPRINT(RT_DEBUG_OFF, + ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(SA))); + + ht_mode_adjust(pAd, pEntry, &HtCapability, &pAd->CommonCfg.DesiredHtPhy); + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &pAd->StaCfg.wdev.DesiredHtPhyInfo.MCSSet[0], &HtCapability.MCSSet[0]); + + if (pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS != MCS_AUTO) + set_ht_fixed_mcs(pAd, pEntry, pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS, pAd->StaCfg.wdev.HTPhyMode.field.MCS); + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR) HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR) HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg + && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, + &HtCapability, + sizeof(HT_CAPABILITY_IE)); + } +#endif /* DOT11_N_SUPPORT */ + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.wdev.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, + &pEntry->pTable, + &TableSize, + &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.wdev.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.wdev.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode, + pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) { + /* If support WPA or WPA2, start STAKey hand shake, */ + /* If failed hand shake, just tear down peer DLS */ + if (RTMPSendSTAKeyRequest + (pAd, + pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], + reason); + MlmeEnqueue(pAd, + DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof(MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + pAd->StaCfg.DLSEntry[i].Status =DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid =FALSE; + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); + } else { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - waiting for STAKey handshake procedure\n")); + } + } else { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", + PRINT_MAC(SA))); + } + + /*initialize seq no for DLS frames. */ + pAd->StaCfg.DLSEntry[i].Sequence = 0; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + } else { + /* DLS setup procedure failed. */ + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, + &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - PeerDlsRspAction failed with StatusCode=%d \n", + StatusCode)); + } + } + } + + if (i >= MAX_NUM_OF_INIT_DLS_ENTRY) { + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsRspAction() update timeout value \n")); + for (i = (MAX_NUM_OF_DLS_ENTRY - 1); + i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + if (StatusCode == MLME_SUCCESS) { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + set_entry_phy_cfg(pAd, pEntry); + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(SA))); + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } else { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) { + pEntry->MaxHTPhyMode.field.BW = BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (HtCapability.HtCapInfo.ShortGIfor40)); + } else { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &pAd->StaCfg.wdev.DesiredHtPhyInfo.MCSSet[0], &HtCapability.MCSSet[0]); + + if (pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS != MCS_AUTO) { + DBGPRINT(RT_DEBUG_OFF, + ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS)); + set_ht_fixed_mcs(pAd, pEntry, pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS, pAd->StaCfg.wdev.HTPhyMode.field.MCS); + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR) HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR) HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, + &HtCapability, + sizeof(HT_CAPABILITY_IE)); + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.wdev.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, + pEntry, + &pEntry->pTable, + &TableSize, + &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.wdev.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.wdev.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) { + /* If support WPA or WPA2, start STAKey hand shake, */ + /* If failed hand shake, just tear down peer DLS */ + if (RTMPSendSTAKeyRequest + (pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + DlsParmFill(pAd, + &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], + reason); + MlmeEnqueue(pAd, + DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof(MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, + 0); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); + } else { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - waiting for STAKey handshake procedure\n")); + } + } else { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", + PRINT_MAC(SA))); + } + pAd->StaCfg.DLSEntry[i].Sequence = 0; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + } else { + /* DLS setup procedure failed. */ + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - PeerDlsRspAction failed with StatusCode=%d \n", + StatusCode)); + } + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_TEARDOWN; + USHORT ReasonCode = REASON_QOS_UNSPECIFY; + HEADER_802_11 DlsTearDownHdr; + PRT_802_11_DLS pDLS; + BOOLEAN TimerCancelled; + UCHAR i; + + if (!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode)) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", + ReasonCode)); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("DLS - MlmeDlsTearDownAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &DlsTearDownHdr, + 1, &Category, + 1, &Action, + 6, &pDLS->MacAddr, + 6, pAd->CurrentAddress, 2, &ReasonCode, END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + + /* Remove key in local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (MAC_ADDR_EQUAL + (pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) { + MacTableDeleteDlsEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + /* clear peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (MAC_ADDR_EQUAL + (pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, + &TimerCancelled); + MacTableDeleteDlsEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT ReasonCode; + UINT i; + BOOLEAN TimerCancelled; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + if (!PeerDlsTearDownSanity + (pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode)) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode)); + + /* clear local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, + &TimerCancelled); + /*AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); */ + /*AsicRemovePairwiseKeyEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); */ + MacTableDeleteDlsEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + /* clear peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, + &TimerCancelled); + /*AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); */ + /*AsicRemovePairwiseKeyEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); */ + MacTableDeleteDlsEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID RTMPCheckDLSTimeOut( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_UNSPECIFY; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + /* If timeout value is equaled to zero, it means always not be timeout. */ + + /* update local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if ((pAd->StaCfg.DLSEntry[i].Valid) + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) { + pAd->StaCfg.DLSEntry[i].CountDownTimer--; + + if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) { + reason = REASON_QOS_REQUEST_TIMEOUT; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + } + } + } + + /* update peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if ((pAd->StaCfg.DLSEntry[i].Valid) + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) { + pAd->StaCfg.DLSEntry[i].CountDownTimer--; + + if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) { + reason = REASON_QOS_REQUEST_TIMEOUT; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof (MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN RTMPRcvFrameDLSCheck( + IN RTMP_ADAPTER *pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN RXINFO_STRUC *pRxInfo) +{ + ULONG i; + BOOLEAN bFindEntry = FALSE; + BOOLEAN bSTAKeyFrame = FALSE; + PEAPOL_PACKET pEap; + PUCHAR pProto, pAddr = NULL; + PUCHAR pSTAKey = NULL; + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + UCHAR Mic[16], OldMic[16]; + UCHAR digest[80]; + UCHAR DlsPTK[80]; + UCHAR temp[64]; + BOOLEAN TimerCancelled; + CIPHER_KEY PairwiseKey; + + if (!pAd->CommonCfg.bDLSCapable) + return bSTAKeyFrame; + + if (!INFRA_ON(pAd)) + return bSTAKeyFrame; + + if (Len < LENGTH_802_11 + 6 + 2) /* LENGTH_802_11 + LLC + EAPOL protocol type */ + return bSTAKeyFrame; + + pProto = (PUCHAR) pHeader + LENGTH_802_11; + + if ((pHeader->FC.SubType & 0x08)) + pProto += 2; /* QOS Control field */ + + /* Skip 4-bytes for HTC */ + if (pHeader->FC.Order + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) { + pProto += 4; + } + + /* L2PAD bit on will pad 2 bytes at LLC */ + if (pRxInfo->L2PAD) { + pProto += 2; + } + + pProto += 6; /* 0xAA 0xAA 0xAA 0x00 0x00 0x00 */ + + if ((!(pHeader->FC.SubType & 0x08)) + && (!RTMPEqualMemory(EAPOL, pProto, 2))) + return bSTAKeyFrame; + + pAddr = pHeader->Addr2; + + if (RTMPEqualMemory(EAPOL, pProto, 2) + && (pAd->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA)) { + pEap = (PEAPOL_PACKET) (pProto + 2); + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", + Len, + (LENGTH_802_11 + 6 + 2 + 2 + + MIN_LEN_OF_EAPOL_KEY_MSG + 16), + pEap->KeyDesc.KeyInfo.KeyMic, + pEap->KeyDesc.KeyInfo.Install, + pEap->KeyDesc.KeyInfo.KeyAck, + pEap->KeyDesc.KeyInfo.Secure, + pEap->KeyDesc.KeyInfo.EKD_DL, + pEap->KeyDesc.KeyInfo.Error, + pEap->KeyDesc.KeyInfo.Request)); + + if ((Len >= + (LENGTH_802_11 + 6 + 2 + 2 + MIN_LEN_OF_EAPOL_KEY_MSG + + 16)) && pEap->KeyDesc.KeyInfo.KeyMic + && pEap->KeyDesc.KeyInfo.Install + && pEap->KeyDesc.KeyInfo.KeyAck + && pEap->KeyDesc.KeyInfo.Secure + && pEap->KeyDesc.KeyInfo.EKD_DL + && !pEap->KeyDesc.KeyInfo.Error + && !pEap->KeyDesc.KeyInfo.Request) { + /* First validate replay counter, only accept message with larger replay counter */ + /* Let equal pass, some AP start with all zero replay counter */ + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory + (pEap->KeyDesc.ReplayCounter, + pAd->StaCfg.ReplayCounter, + LEN_KEY_DESC_REPLAY) != 1) + && + (RTMPCompareMemory + (pEap->KeyDesc.ReplayCounter, ZeroReplay, + LEN_KEY_DESC_REPLAY) != 0)) + return bSTAKeyFrame; + + /*RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); */ + RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, + pEap->KeyDesc.ReplayCounter, + LEN_KEY_DESC_REPLAY); + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", + pAd->StaCfg.ReplayCounter[0], + pAd->StaCfg.ReplayCounter[1], + pAd->StaCfg.ReplayCounter[2], + pAd->StaCfg.ReplayCounter[3], + pAd->StaCfg.ReplayCounter[4], + pAd->StaCfg.ReplayCounter[5], + pAd->StaCfg.ReplayCounter[6], + pAd->StaCfg.ReplayCounter[7], Len, + pEap->KeyDesc.KeyData[1])); + + /* put these code segment to get the replay counter */ + if (pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + return bSTAKeyFrame; + + /* Check MIC value */ + /* Save the MIC and replace with zero */ + /* use proprietary PTK */ + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, + temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, + LEN_KEY_DESC_MIC); + NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) { + /* AES */ + RT_HMAC_SHA1(DlsPTK, LEN_PTK_KCK, (PUCHAR) pEap, + pEap->Body_Len[1] + 4, digest, + SHA1_DIGEST_SIZE); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } else { + RT_HMAC_MD5(DlsPTK, LEN_PTK_KCK, (PUCHAR) pEap, + pEap->Body_Len[1] + 4, Mic, + MD5_DIGEST_SIZE); + } + + if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) { + DBGPRINT(RT_DEBUG_ERROR, + ("MIC Different in Msg1 of STAKey handshake! \n")); + return bSTAKeyFrame; + } else + DBGPRINT(RT_DEBUG_TRACE, + ("MIC VALID in Msg1 of STAKey handshake! \n")); + if ((pEap->KeyDesc.KeyData[0] == 0xDD) + && (pEap->KeyDesc.KeyData[2] == 0x00) + && (pEap->KeyDesc.KeyData[3] == 0x0C) + && (pEap->KeyDesc.KeyData[4] == 0x43) + && (pEap->KeyDesc.KeyData[5] == 0x02)) { + pAddr = pEap->KeyDesc.KeyData + 8; /* Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2) */ + pSTAKey = pEap->KeyDesc.KeyData + 14; /* Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6) */ + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n", + PRINT_MAC(pAddr), Len, + pEap->KeyDesc.KeyData[1])); + + bSTAKeyFrame = TRUE; + } + + } + else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + MIN_LEN_OF_EAPOL_KEY_MSG)) + { + RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, + pEap->KeyDesc.ReplayCounter, + LEN_KEY_DESC_REPLAY); + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", + pAd->StaCfg.ReplayCounter[0], + pAd->StaCfg.ReplayCounter[1], + pAd->StaCfg.ReplayCounter[2], + pAd->StaCfg.ReplayCounter[3], + pAd->StaCfg.ReplayCounter[4], + pAd->StaCfg.ReplayCounter[5], + pAd->StaCfg.ReplayCounter[6], + pAd->StaCfg.ReplayCounter[7], Len, + pEap->KeyDesc.KeyData[1])); + } + } + + /* If timeout value is equaled to zero, it means always not be timeout. */ + /* update local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) { + if (bSTAKeyFrame) { + PMAC_TABLE_ENTRY pEntry; + + /* STAKey frame, add pairwise key table */ + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, + &TimerCancelled); + + PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TK); + NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_MIC); + NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_MIC); + + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) + PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + PairwiseKey.CipherAlg = CIPHER_AES; + + pEntry = DlsEntryTableLookup(pAd, + pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + + /* Add Pair-wise key to Asic */ + RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd, + (UCHAR) pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + &PairwiseKey); + + RTMP_SET_WCID_SEC_INFO(pAd, + BSS0, + 0, + PairwiseKey.CipherAlg, + (UCHAR) pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + PAIRWISEKEYTABLE); + + NdisMoveMemory(&pEntry->PairwiseKey, + &PairwiseKey, + sizeof (CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n")); + + RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Finish STAKey handshake procedure (Initiator side)\n")); + } else { + /* Data frame, update timeout value */ + if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) { + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + } + } + + bFindEntry = TRUE; + } + } + + /* update peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) { + if (bSTAKeyFrame) { + PMAC_TABLE_ENTRY pEntry = NULL; + + /* STAKey frame, add pairwise key table, and send STAkey Msg-2 */ + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + + PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TK); + NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_MIC); + NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_MIC); + + /*PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; */ + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) + PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + PairwiseKey.CipherAlg = CIPHER_AES; + + pEntry = DlsEntryTableLookup(pAd, + pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + /*AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast */ + /*AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); */ + + /* Add Pair-wise key to Asic */ + RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd, + (UCHAR) pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + &PairwiseKey); + + RTMP_SET_WCID_SEC_INFO(pAd, + BSS0, + 0, + PairwiseKey.CipherAlg, + (UCHAR) pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + PAIRWISEKEYTABLE); + + NdisMoveMemory(&pEntry->PairwiseKey, + &PairwiseKey, + sizeof (CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n")); + + /* If support WPA or WPA2, start STAKey hand shake, */ + /* If failed hand shake, just tear down peer DLS */ + if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS) { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, + &pAd->StaCfg.DLSEntry[i], + reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, + MT2_MLME_DLS_TEAR_DOWN, + sizeof(MLME_DLS_REQ_STRUCT), + &MlmeDlsReq, 0); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - Finish STAKey handshake procedure (Peer side)\n")); + } + } else { + /* Data frame, update timeout value */ + if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) { + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + } + } + + bFindEntry = TRUE; + } + } + + return bSTAKeyFrame; +} + +/* + ======================================================================== + + Routine Description: + Check if the frame can be sent through DLS direct link interface + + Arguments: + pAd Pointer to adapter + + Return Value: + DLS entry index + + Note: + + ======================================================================== +*/ +INT RTMPCheckDLSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + INT rval = -1; + INT i; + + if (!pAd->CommonCfg.bDLSCapable) + return rval; + + if (!INFRA_ON(pAd)) + return rval; + + do { + /* check local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + rval = i; + break; + } + } + + /* check peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; + i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + rval = i; + break; + } + } + } while (FALSE); + + return rval; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + HEADER_802_11 DlsTearDownHdr; + ULONG FrameLen = 0; + USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_TEARDOWN; + UCHAR i = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, pAd->CommonCfg.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), + &DlsTearDownHdr, 1, &Category, 1, &Action, 6, pDA, 6, + pAd->CurrentAddress, 2, &Reason, END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + /* Remove key in local dls table entry */ + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + MacTableDeleteDlsEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + /* Remove key in peer dls table entry */ + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if (pAd->StaCfg.DLSEntry[i].Valid + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) { + MacTableDeleteDlsEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + DBGPRINT(RT_DEBUG_TRACE, + ("Send DLS TearDown Frame and remove key in (i=%d) \n", i)); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +NDIS_STATUS RTMPSendSTAKeyRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + UCHAR Header802_3[14]; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + PEAPOL_PACKET pPacket; + UCHAR *mpool; + UCHAR Mic[16]; + UCHAR digest[80]; + PUCHAR pOutBuffer = NULL; + PNDIS_PACKET pNdisPacket; + UCHAR temp[64]; + UCHAR DlsPTK[80]; + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pDA))); + + pAd->Sequence++; + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, EAPOL); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *) & mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("!!!%s : no memory!!!\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + /* Zero message body */ + pPacket = (PEAPOL_PACKET) mpool; + NdisZeroMemory(pPacket, TX_EAPOL_BUFFER); + + pPacket->ProVer = EAPOL_VER; + pPacket->ProType = EAPOLKey; + pPacket->Body_Len[1] = sizeof (KEY_DESCRIPTER) + 6 + MAC_ADDR_LEN; /* data field contain KDE andPeer MAC address */ + + /* STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) */ + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPAPSK)) { + pPacket->KeyDesc.Type = WPA1_KEY_DESC; + } else if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pPacket->KeyDesc.Type = WPA2_KEY_DESC; + } + + /* Key descriptor version */ + pPacket->KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + || (pAd->StaCfg.GroupCipher == + Ndis802_11AESEnable)) ? (KEY_DESC_AES) + : (KEY_DESC_TKIP)); + + pPacket->KeyDesc.KeyInfo.KeyMic = 1; + pPacket->KeyDesc.KeyInfo.Secure = 1; + pPacket->KeyDesc.KeyInfo.Request = 1; + + pPacket->KeyDesc.KeyDataLen[1] = 12; + + /* use our own OUI to distinguish proprietary with standard. */ + pPacket->KeyDesc.KeyData[0] = 0xDD; + pPacket->KeyDesc.KeyData[1] = 0x0A; + pPacket->KeyDesc.KeyData[2] = 0x00; + pPacket->KeyDesc.KeyData[3] = 0x0C; + pPacket->KeyDesc.KeyData[4] = 0x43; + pPacket->KeyDesc.KeyData[5] = 0x03; + NdisMoveMemory(&pPacket->KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); + + NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, + pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + os_free_mem(NULL, mpool); + return NStatus; + } + /* Prepare EAPOL frame for MIC calculation */ + /* Be careful, only EAPOL frame is counted for MIC calculation */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + pPacket->Body_Len[1] + 4, pPacket, END_OF_ARGS); + + /* use proprietary PTK */ + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, + pAd->CurrentAddress, DlsPTK, LEN_PTK); + + /* calculate MIC */ + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) { + /* AES */ + NdisZeroMemory(digest, sizeof (digest)); + RT_HMAC_SHA1(DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, + SHA1_DIGEST_SIZE); + NdisMoveMemory(pPacket->KeyDesc.KeyMic, digest, + LEN_KEY_DESC_MIC); + } else { + NdisZeroMemory(Mic, sizeof (Mic)); + RT_HMAC_MD5(DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, + MD5_DIGEST_SIZE); + NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + } + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (Header802_3), Header802_3, + pPacket->Body_Len[1] + 4, pPacket, END_OF_ARGS); + + NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); + if (NStatus == NDIS_STATUS_SUCCESS) { + RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); + STASendPacket(pAd, pNdisPacket); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + MlmeFreeMemory(pAd, pOutBuffer); + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", + NStatus, FrameLen)); + + return NStatus; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + UCHAR Header802_3[14]; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + PEAPOL_PACKET pPacket; + UCHAR *mpool; + UCHAR Mic[16]; + UCHAR digest[80]; + PUCHAR pOutBuffer = NULL; + PNDIS_PACKET pNdisPacket; + UCHAR temp[64]; + UCHAR DlsPTK[80]; /* Due to dirver can not get PTK, use proprietary PTK */ + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pDA))); + + pAd->Sequence++; + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, EAPOL); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *) & mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("!!!%s : no memory!!!\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + /* Zero message body */ + pPacket = (PEAPOL_PACKET) mpool; + NdisZeroMemory(pPacket, TX_EAPOL_BUFFER); + + pPacket->ProVer = EAPOL_VER; + pPacket->ProType = EAPOLKey; + pPacket->Body_Len[1] = sizeof (KEY_DESCRIPTER) + 6 + MAC_ADDR_LEN; /* data field contain KDE and Peer MAC address */ + + /* STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) */ + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPAPSK)) { + pPacket->KeyDesc.Type = WPA1_KEY_DESC; + } else if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pPacket->KeyDesc.Type = WPA2_KEY_DESC; + } + + /* Key descriptor version */ + pPacket->KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + || (pAd->StaCfg.GroupCipher == + Ndis802_11AESEnable)) ? (KEY_DESC_AES) + : (KEY_DESC_TKIP)); + + pPacket->KeyDesc.KeyInfo.KeyMic = 1; + pPacket->KeyDesc.KeyInfo.Secure = 1; + + pPacket->KeyDesc.KeyDataLen[1] = 12; + + /* use our own OUI to distinguish proprietary with standard. */ + pPacket->KeyDesc.KeyData[0] = 0xDD; + pPacket->KeyDesc.KeyData[1] = 0x0A; + pPacket->KeyDesc.KeyData[2] = 0x00; + pPacket->KeyDesc.KeyData[3] = 0x0C; + pPacket->KeyDesc.KeyData[4] = 0x43; + pPacket->KeyDesc.KeyData[5] = 0x03; + NdisMoveMemory(&pPacket->KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); + + NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, + pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + os_free_mem(NULL, mpool); + return NStatus; + } + /* Prepare EAPOL frame for MIC calculation */ + /* Be careful, only EAPOL frame is counted for MIC calculation */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + pPacket->Body_Len[1] + 4, pPacket, END_OF_ARGS); + + /* use proprietary PTK */ + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, + pAd->CurrentAddress, DlsPTK, LEN_PTK); + + /* calculate MIC */ + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) { + /* AES */ + NdisZeroMemory(digest, sizeof (digest)); + RT_HMAC_SHA1(DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, + SHA1_DIGEST_SIZE); + NdisMoveMemory(pPacket->KeyDesc.KeyMic, digest, + LEN_KEY_DESC_MIC); + } else { + NdisZeroMemory(Mic, sizeof (Mic)); + RT_HMAC_MD5(DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, + MD5_DIGEST_SIZE); + NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + } + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (Header802_3), Header802_3, + pPacket->Body_Len[1] + 4, pPacket, END_OF_ARGS); + + NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); + if (NStatus == NDIS_STATUS_SUCCESS) { + RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); + STASendPacket(pAd, pNdisPacket); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + MlmeFreeMemory(pAd, pOutBuffer); + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", + NStatus, FrameLen)); + + return NStatus; +} + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason; + PRT_802_11_DLS pDLS = (PRT_802_11_DLS) FunctionContext; + PRTMP_ADAPTER pAd = NULL; + + if (pDLS == NULL) + return; + + pAd = (PRTMP_ADAPTER)pDLS->pAd; + + DBGPRINT(RT_DEBUG_TRACE, + ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pDLS->MacAddr))); + + if ((pDLS) && (pDLS->Valid)) { + reason = REASON_QOS_REQUEST_TIMEOUT; + pDLS->Valid = FALSE; + pDLS->Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, + sizeof (MLME_DLS_REQ_STRUCT), &MlmeDlsReq, 0); + RTMP_MLME_HANDLER(pAd); + } +} + +/* +================================================================ +Description : because DLS and CLI share the same WCID table in ASIC. +Mesh entry also insert to pAd->MacTab.content[]. +Also fills the pairwise key. +Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls +from index MAX_AID_BA. +================================================================ +*/ +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n")); + /* if FULL, return */ + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + do { + if ((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL) + break; + + /* allocate one MAC entry */ + pEntry = MacTableInsertEntry(pAd, pAddr, &pAd->StaCfg.wdev, + DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, + OPMODE_STA, + TRUE); + if (pEntry) { + pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->wcid; + pEntry->MatchDlsEntryIdx = DlsEntryIdx; + pEntry->AuthMode = pAd->StaCfg.wdev.AuthMode; + pEntry->WepStatus = pAd->StaCfg.wdev.WepStatus; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, + ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n", + pEntry->wcid, pAd->MacTab.Size)); + + /* If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry */ + if (IS_ENTRY_DLS(pEntry) + && (pAd->StaCfg.wdev.WepStatus == Ndis802_11WEPEnabled)) { + UCHAR KeyIdx = pAd->StaCfg.wdev.DefaultKeyId; + UCHAR CipherAlg; + + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + + RTMPSetWcidSecurityInfo(pAd, + BSS0, + pAd->StaCfg.wdev.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.wdev.DefaultKeyId].CipherAlg, pEntry->wcid, + SHAREDKEYTABLE); + } + + break; + } + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n")); + + return pEntry; +} + +/* + ========================================================================== + Description: + Delete all Mesh Entry in pAd->MacTab + ========================================================================== + */ +BOOLEAN MacTableDeleteDlsEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n")); + + if (!VALID_WCID(wcid)) + return FALSE; + + MacTableDeleteEntry(pAd, wcid, pAddr); + + DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n")); + + return TRUE; +} + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG HashIdx; + MAC_TABLE_ENTRY *pEntry = NULL; + + RTMP_SEM_LOCK(&pAd->MacTabLock); + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry) { + if (IS_ENTRY_DLS(pEntry) + && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { + if (bResetIdelCount) + pEntry->NoDataIdleCount = 0; + break; + } else + pEntry = pEntry->pNext; + } + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + return pEntry; +} + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG DLsIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_WCID(wcid)) + return NULL; + + RTMP_SEM_LOCK(&pAd->MacTabLock); + + do { + pCurEntry = &pAd->MacTab.Content[wcid]; + + DLsIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_DLS(pCurEntry)) { + DLsIndex = pCurEntry->MatchDlsEntryIdx; + } + + if (DLsIndex == 0xff) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) { + if (bResetIdelCount) + pCurEntry->NoDataIdleCount = 0; + pEntry = pCurEntry; + break; + } + } while (FALSE); + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + + return pEntry; +} + +INT Set_DlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + INT i; + + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-8s\n", "MAC", "TIMEOUT\n")); + for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++) { + if ((pAd->StaCfg.DLSEntry[i].Valid) + && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) { + PMAC_TABLE_ENTRY pEntry = + &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID]; + + DBGPRINT(RT_DEBUG_OFF, + ("%02x:%02x:%02x:%02x:%02x:%02x ", + PRINT_MAC(pAd->StaCfg.DLSEntry[i].MacAddr))); + DBGPRINT(RT_DEBUG_OFF, + ("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut)); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, + ("\n%-19s%-4s%-4s%-4s%-4s%-7s%-7s%-7s", "MAC", + "AID", "BSS", "PSM", "WMM", "RSSI0", "RSSI1", + "RSSI2")); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, + ("%-8s%-10s%-6s%-6s%-6s%-6s", "MIMOPS", "PhMd", + "BW", "MCS", "SGI", "STBC")); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, + ("\n%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], + pEntry->Addr[2], pEntry->Addr[3], + pEntry->Addr[4], pEntry->Addr[5])); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->apidx)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode)); + DBGPRINT(RT_DEBUG_OFF, + ("%-4d", + (int)CLIENT_STATUS_TEST_FLAG(pEntry, + fCLIENT_STATUS_WMM_CAPABLE))); + DBGPRINT(RT_DEBUG_OFF, + ("%-7d", pEntry->RssiSample.AvgRssi0)); + DBGPRINT(RT_DEBUG_OFF, + ("%-7d", pEntry->RssiSample.AvgRssi1)); + DBGPRINT(RT_DEBUG_OFF, + ("%-7d", pEntry->RssiSample.AvgRssi2)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->MmpsMode)); + DBGPRINT(RT_DEBUG_OFF, + ("%-10s", + get_phymode_str(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, + ("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW))); + DBGPRINT(RT_DEBUG_OFF, + ("%-6d", pEntry->HTPhyMode.field.MCS)); + DBGPRINT(RT_DEBUG_OFF, + ("%-6d", pEntry->HTPhyMode.field.ShortGI)); + DBGPRINT(RT_DEBUG_OFF, + ("%-6d", pEntry->HTPhyMode.field.STBC)); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, + ("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, + pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount - pEntry->DebugFIFOCount) * 100 / pEntry->DebugTxCount) : 0)); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + } + } + + return TRUE; +} + +INT Set_DlsAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR mac[MAC_ADDR_LEN]; + USHORT Timeout; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + RT_802_11_DLS Dls; + + if (strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format. */ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token) > 1)) { + Timeout = (USHORT) simple_strtol((token + 1), 0, 10); + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; + token = rstrtok(NULL, &sepValue[0]), i++) { + if ((strlen(token) != 2) || (!isxdigit(*token)) + || (!isxdigit(*(token + 1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if (i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, + ("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], (int)Timeout)); + + NdisZeroMemory(&Dls, sizeof (RT_802_11_DLS)); + Dls.TimeOut = Timeout; + COPY_MAC_ADDR(Dls.MacAddr, mac); + Dls.Valid = 1; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof (RT_802_11_DLS), &Dls, 0); + + return TRUE; + } + + return FALSE; + +} + +INT Set_DlsTearDownEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + PSTRING value; + INT i; + RT_802_11_DLS Dls; + + if (strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (i = 0, value = rstrtok(arg, ":"); value; + value = rstrtok(NULL, ":")) { + if ((strlen(value) != 2) || (!isxdigit(*value)) + || (!isxdigit(*(value + 1)))) + return FALSE; /*Invalid */ + + AtoH(value, &macAddr[i++], 2); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(macAddr))); + + NdisZeroMemory(&Dls, sizeof (RT_802_11_DLS)); + COPY_MAC_ADDR(Dls.MacAddr, macAddr); + Dls.Valid = 0; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof (RT_802_11_DLS), &Dls, 0); + + return TRUE; +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/ft_action.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/ft_action.c new file mode 100644 index 000000000..50a2557c4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/ft_action.c @@ -0,0 +1,498 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F, No. 36 TaiYuan St. Juebei City. + * Hsin-chu County, 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: + action_ft.c + + Abstract: + Handle State Machine for 802.11r Fast BSS Transition Over-The-DS action frame. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan 2008-12-17 Fast BSS Transition Over-The-DS State Machine. +*/ + +#ifdef DOT11R_FT_SUPPORT + +#include "rt_config.h" +#include "ft.h" + +BOOLEAN MlmeFtReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT PULONG pTimeout, + OUT FT_MDIE *pMdIe, + OUT UCHAR *pSnonce, + OUT UCHAR *pR0KhIdLen, + OUT UCHAR *pR0KhId, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pRSNIE) +{ + MLME_FT_REQ_STRUCT *pInfo; + + pInfo = (MLME_FT_REQ_STRUCT *) Msg; + *LengthVIE = 0; + *pR0KhIdLen = 0; + *pTimeout = 0; + + COPY_MAC_ADDR(pAddr, pInfo->TargetAddr); + RTMPMoveMemory(pMdIe, &pInfo->MdIe, sizeof (FT_MDIE)); + RTMPMoveMemory(pR0KhId, pInfo->R0khId, pInfo->R0khIdLen); + *pR0KhIdLen = pInfo->R0khIdLen; + RTMPMoveMemory(pSnonce, pInfo->SNonce, 32); + *LengthVIE = (USHORT) pInfo->VIeLen; + RTMPMoveMemory(pRSNIE, pInfo->VIe, *LengthVIE); + *pTimeout = pInfo->Timeout; + + COPY_MAC_ADDR(pAddr, pInfo->TargetAddr); + + return TRUE; +} + +BOOLEAN PeerFtRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT FT_FTIE *pFtIe, + OUT FT_MDIE *pMdIe, + OUT USHORT *pStatus) +{ + FT_OVER_DS_ACTION_RSP_ACK *pFtRspFrame = NULL; /*(FT_OVER_DS_ACTION_RSP_ACK)Msg; */ + UCHAR Category; + UCHAR Action; + PEID_STRUCT pEid; + CHAR *Ptr; + ULONG Length = 0; + + pFtRspFrame = (FT_OVER_DS_ACTION_RSP_ACK *) (Msg + LENGTH_802_11); + Ptr = (PCHAR) pFtRspFrame->InfoElm; + COPY_MAC_ADDR(pAddr, pFtRspFrame->TargetAP_Addr); + Action = pFtRspFrame->Action; + Category = pFtRspFrame->Category; + *pStatus = pFtRspFrame->StatusCode; + + if (Action != FT_ACTION_BT_RSP) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerFtRspSanity fail - wrong Action [%x]. \n", + Action)); + return FALSE; + } + + pEid = (PEID_STRUCT) Ptr; + Length = MsgLen - sizeof (FT_OVER_DS_ACTION_RSP_ACK) - LENGTH_802_11; + /* get variable fields from payload and advance the pointer */ + /*while ((Length + 2 + pEid->Len) <= MsgLen) */ + while ((Length > 0) && (Length >= (2 + pEid->Len))) { + switch (pEid->Eid) { + case IE_RSN: + break; + case IE_FT_MDIE: + if (pEid->Len == 3) { + NdisMoveMemory(pMdIe, pEid->Octet, pEid->Len); + } + DBGPRINT(RT_DEBUG_TRACE, + ("PeerFtRspSanity IE_MOBILITY_DOMAIN Mdid = [%x%x]. \n", + pMdIe->MdId[0], pMdIe->MdId[1])); + break; + case IE_FT_FTIE: + if (pEid->Len >= sizeof (FT_FTIE)) { + NdisMoveMemory(pFtIe, pEid->Octet, + sizeof (FT_FTIE)); + } + DBGPRINT(RT_DEBUG_TRACE, + ("PeerFtRspSanity IE_FAST_BSS_TRANSITION . \n")); + break; + } + Length -= (2 + pEid->Len); /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT) ((UCHAR *) pEid + 2 + pEid->Len); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + ft state machine init, including state transition and timer init + Parameters: + Sm - pointer to the dls state machine + Note: + The state machine looks like this + + FT_IDLE + MT2_MLME_FT_REQUEST MlmeDlsReqAction + MT2_PEER_DLS_REQUEST PeerDlsReqAction + MT2_PEER_DLS_RESPONSE PeerDlsRspAction + MT2_MLME_DLS_TEARDOWN MlmeTearDownAction + MT2_PEER_DLS_TEARDOWN PeerTearDownAction + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +void FT_OTD_StateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, FT_OTD_MAX_STATE, FT_OTD_MAX_MSG, + (STATE_MACHINE_FUNC) Drop, FT_OTD_IDLE, + FT_OTD_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, FT_OTD_IDLE, FT_OTD_MT2_MLME_REQ, + (STATE_MACHINE_FUNC) FT_OTD_ReqAction); + + StateMachineSetAction(Sm, FT_OTD_WAIT_SEQ2, FT_OTD_MT2_MLME_REQ, + (STATE_MACHINE_FUNC) FT_OTD_InvalidStateWhenFt); + StateMachineSetAction(Sm, FT_OTD_WAIT_SEQ2, FT_OTD_MT2_PEER_EVEN, + (STATE_MACHINE_FUNC) FT_OTD_PeerRspAtSeq2Action); + StateMachineSetAction(Sm, FT_OTD_WAIT_SEQ2, FT_OTD_MT2_TIMEOUT, + (STATE_MACHINE_FUNC) FT_OTD_TimeoutAction); + + StateMachineSetAction(Sm, FT_OTD_WAIT_SEQ4, FT_OTD_MT2_MLME_REQ, + (STATE_MACHINE_FUNC) FT_OTD_InvalidStateWhenFt); + StateMachineSetAction(Sm, FT_OTD_WAIT_SEQ4, FT_OTD_MT2_PEER_EVEN, + (STATE_MACHINE_FUNC) FT_OTD_PeerAckAtSeq4Action); + StateMachineSetAction(Sm, FT_OTD_WAIT_SEQ4, FT_OTD_MT2_TIMEOUT, + (STATE_MACHINE_FUNC) FT_OTD_TimeoutAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.FtOtdActTimer, + GET_TIMER_FUNCTION(FT_OTD_TimeoutAction), pAd, FALSE); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTD_ReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 FtReqHdr; + FT_MDIE MdIe; + UCHAR Snonce[32]; + UCHAR R0KhIdLen; + UCHAR R0KhId[FT_ROKH_ID_LEN + 1]; + UCHAR Category = FT_CATEGORY_BSS_TRANSITION; + UCHAR Action = FT_ACTION_BT_REQ; + ULONG Timeout = 0; + USHORT Status; + UCHAR TargetAddr[6]; + NDIS_802_11_VARIABLE_IEs *pRsnIE = NULL; + USHORT LenRsnIE; + + if (!MlmeFtReqSanity + (pAd, Elem->Msg, Elem->MsgLen, TargetAddr, &Timeout, &MdIe, Snonce, + &R0KhIdLen, R0KhId, &LenRsnIE, pRsnIE)) { + DBGPRINT_ERR(("FT_OTD_ACTION - FT_OTD_ReqAction() sanity check failed\n")); + pAd->Mlme.AuthMachine.CurrState = FT_OTD_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, + &Status, 0); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTD_ACTION :FT_OTD_ReqAction() \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("FT_OTD_ACTION :FT_OTD_ReqAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &FtReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, + pAd->CommonCfg.Bssid); + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof (HEADER_802_11), &FtReqHdr, + 1, &Category, + 1, &Action, + 6, pAd->CurrentAddress, 6, TargetAddr, END_OF_ARGS); + + /* MDIE */ + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, MdIe.MdId, + MdIe.FtCapPlc); + + /* Process with RSN */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { + FT_ConstructAuthReqInRsn(pAd, pOutBuffer, &FrameLen); + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.FtOtdActTimer, Timeout); + pAd->Mlme.FtOtdActMachine.CurrState = FT_OTD_WAIT_SEQ2; + +} + +VOID FT_OTD_PeerRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR TargetAddr[MAC_ADDR_LEN]; + USHORT Status; + BOOLEAN TimerCancelled; + ULONG BssIdx = 0; + FT_FTIE FtIe; + FT_MDIE MdIe; + PFRAME_802_11 pFrame = (PFRAME_802_11) Elem->Msg; + MLME_ASSOC_REQ_STRUCT AssocReq; + UCHAR BBPValue = 0; + + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - PeerFtRspAtSeq2Action MlmeAux.Bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->MlmeAux.Bssid))); + + if (PeerFtRspSanity + (pAd, Elem->Msg, Elem->MsgLen, TargetAddr, &FtIe, &MdIe, &Status)) { + if (MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pFrame->Hdr.Addr2)) { + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - Receive FT_RSP seq#2 to me ( Status=%d)\n", + Status)); + RTMPCancelTimer(&pAd->MlmeAux.FtOtdActTimer, + &TimerCancelled); + + if (Status == MLME_SUCCESS) { + UINT8 ptk_len; + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[MCAST_WCID]; + + NdisMoveMemory(pEntry->SNonce, FtIe.SNonce, 32); + + /* Get ANonce from authentication-response */ + NdisMoveMemory(pEntry->ANonce, FtIe.ANonce, 32); + + hex_dump("anonce", pEntry->ANonce, 32); + hex_dump("snonce", pEntry->SNonce, 32); + + FT_DerivePMKR1(pAd->StaCfg.Dot11RCommInfo.PMKR0, pAd->StaCfg.Dot11RCommInfo.PMKR0Name, TargetAddr, /*pAd->MlmeAux.Bssid, */ + pAd->CurrentAddress, + pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME); + + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + ptk_len = 32 + 32; + else + ptk_len = 32 + 16; + + /* Derive FT PTK and PTK-NAME */ + FT_DerivePTK(pEntry->FT_PMK_R1, pEntry->FT_PMK_R1_NAME, pEntry->ANonce, pEntry->SNonce, TargetAddr, /*pAd->MlmeAux.Bssid, */ + pAd->CurrentAddress, + ptk_len, + pEntry->PTK, pEntry->PTK_NAME); + + /* + How to know there is resource request session now ???????? + */ + if ((pAd->StaCfg.Dot11RCommInfo.bSupportResource) + && (pAd->MlmeAux.MdIeInfo.FtCapPlc.field.RsrReqCap)) { + /* Prepare to send FT Confirm packet. */ + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - Receive FT_RSP seq#2 to me, Prepare to send FT Confirm. \n")); + pAd->Mlme.FtOtdActMachine.CurrState = + FT_OTD_WAIT_SEQ4; + + } else { + BSS_ENTRY *pBss = NULL; + /* + Doesn't need to send FT Confirm packet. + */ + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - Receive FT_RSP seq#2 to me, Prepare to send Reassoc. \n")); + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = FT_OTD_RESPONSE; + pAd->Mlme.FtOtdActMachine.CurrState = FT_OTD_IDLE; + RTMPMoveMemory(pAd->MlmeAux.Bssid, TargetAddr, MAC_ADDR_LEN); + + /* + find the desired BSS in the latest SCAN result table + search 2.4G band first + */ + BssIdx = BssTableSearch(&pAd->ScanTab, TargetAddr, 1); + /* + search 5G band, if AP does not exist in 2.4G band + */ + if (BssIdx == BSS_NOT_FOUND) + BssIdx = BssTableSearch(&pAd->ScanTab, TargetAddr, 36); + if (BssIdx == BSS_NOT_FOUND) { + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + return; + } + + pBss = &pAd->ScanTab.BssEntry[BssIdx]; + pAd->MlmeAux.Channel = pBss->Channel; + pAd->MlmeAux.CentralChannel = pBss->CentralChannel; + RTMPZeroMemory(pAd->MlmeAux.ExtRate, + MAX_LEN_OF_SUPPORTED_RATES); + RTMPZeroMemory(pAd->MlmeAux.SupRate, + MAX_LEN_OF_SUPPORTED_RATES); + pAd->MlmeAux.ExtRateLen = pBss->ExtRateLen; + RTMPMoveMemory(pAd->MlmeAux.ExtRate, + pBss->ExtRate, + pBss->ExtRateLen); + pAd->MlmeAux.SupRateLen = pBss->SupRateLen; + RTMPMoveMemory(pAd->MlmeAux.SupRate, + pBss->SupRate, + pBss->SupRateLen); + + RTMPZeroMemory(pAd->MlmeAux.Ssid, + MAX_LEN_OF_SSID); + pAd->MlmeAux.SsidLen = pBss->SsidLen; + RTMPMoveMemory(pAd->MlmeAux.Ssid, + pBss->Ssid, + pBss->SsidLen); + + /* + StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability + */ + if (pBss->HtCapabilityLen) { + RTMPMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, + pBss->HtCapability.MCSSet, 16); + } else { + NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); + } + + bbp_set_bw(pAd, BW_20); + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + + RTMPUpdateMlmeRate(pAd); + + AssocParmFill(pAd, &AssocReq, + pAd->MlmeAux.Bssid, + pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_REASSOC_REQ, + sizeof + (MLME_ASSOC_REQ_STRUCT), + &AssocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } + + } else { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, pFrame->Hdr.Addr2); + pAd->Mlme.FtOtdActMachine.CurrState = FT_OTD_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_FT_OTD_CONF, 2, &Status, 0); + } + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - PeerFtRspSanity() sanity check fail\n")); + } +} + +VOID FT_OTD_PeerAckAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = FT_OTD_RESPONSE; + pAd->Mlme.FtOtdActMachine.CurrState = FT_OTD_IDLE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTD_TimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext; + USHORT Status; + + if (pAd != NULL) { + pAd->Mlme.FtOtdActMachine.CurrState = FT_OTD_IDLE; + Status = MLME_REJ_TIMEOUT; + /*MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_FT_OTD_CONF, 2, &Status, 0); */ + } + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTD_ACTION - FtTimeoutAction\n")); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTD_InvalidStateWhenFt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, + ("FT_OTD_ACTION - InvalidStateWhenFt (state=%lu), reset FT state machine\n", + pAd->Mlme.FtOtdActMachine.CurrState)); + pAd->Mlme.FtOtdActMachine.CurrState = FT_OTD_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_FT_OTD_CONF, 2, &Status, + 0); +} + +VOID FT_OTD_ActParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_FT_REQ_STRUCT *FtReq, + IN PUCHAR pAddr, + IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, + IN PFT_MDIE_INFO FtMdieInfo, + IN PFT_FTIE_INFO FtFtieInfo, + IN UCHAR VarIeLen, + IN PUCHAR pVarIe) +{ + RTMPZeroMemory(FtReq, sizeof (MLME_FT_REQ_STRUCT)); + COPY_MAC_ADDR(FtReq->TargetAddr, pAddr); + if (AuthMode >= Ndis802_11AuthModeWPA) + FtReq->HaveRSN = 1; + FtReq->Timeout = FT_ACT_TIMEOUT; + FT_SET_MDID(FtReq->MdIe.MdId, FtMdieInfo->MdId); + FtReq->MdIe.FtCapPlc.word = FtMdieInfo->FtCapPlc.word; + RTMPMoveMemory(&FtReq->SNonce[0], FtFtieInfo->SNonce, 32); + RTMPMoveMemory(&FtReq->R0khId[0], FtFtieInfo->R0khId, + FtFtieInfo->R0khIdLen); + FtReq->R0khIdLen = FtFtieInfo->R0khIdLen; + RTMPMoveMemory(&FtReq->VIe[0], pVarIe, VarIeLen); +} +#endif /* DOT11R_FT_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/ft_auth.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/ft_auth.c new file mode 100644 index 000000000..f3ee18d3d --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/ft_auth.c @@ -0,0 +1,439 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2008, 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_auth.c + + Abstract: + Handle State Machine for 802.11r Fast BSS Transition Over-The-Air auth frame. + +*/ +#ifdef DOT11R_FT_SUPPORT + +#include "rt_config.h" +#include "ft.h" + +BOOLEAN PeerFtAuthRspSanity( + IN PRTMP_ADAPTER pAd, + IN PUCHAR ApAddr, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT MAC_TABLE_ENTRY *pEntry) +{ + PEID_STRUCT pEid; + USHORT Length = 0; + UCHAR Sanity = 0; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + FT_MDIE MdIe; + UINT8 PMKR0Name[16]; + + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + + /* + Alg: 2 bytes + Seq: 2 bytes + Status: 2 bytes + */ + pEid = (PEID_STRUCT) &pFrame->Octet[6]; + while ((Length + 2 + (USHORT)pEid->Len) <= (MsgLen - LENGTH_802_11 - 6)) + { + switch(pEid->Eid) + { + case IE_FT_MDIE: + if (pEid->Len == sizeof(FT_MDIE)) + { + NdisZeroMemory(&MdIe, sizeof(FT_MDIE)); + NdisMoveMemory(&MdIe, &pEid->Octet[0], pEid->Len); + FT_SET_MDID(pEntry->MdIeInfo.MdId, MdIe.MdId); + pEntry->MdIeInfo.FtCapPlc.word = MdIe.FtCapPlc.word; + Sanity |= 0x01; + } + break; + case IE_FT_FTIE: + if (pEid->Len) + { + NdisMoveMemory(&pAd->MlmeAux.FtIeInfo.ANonce[0], &pEid->Octet[18], 32); + FT_FTIeParse(pEid->Len, + (PFT_FTIE)pEid/*(PFT_FTIE)&pEid->Octet[0]*/, + &pEntry->FtIeInfo.R1khId[0], + &pEntry->FtIeInfo.GtkLen, + &pEntry->FtIeInfo.GtkSubIE[0], + &pEntry->FtIeInfo.R0khIdLen, + &pEntry->FtIeInfo.R0khId[0]); + Sanity |= 0x02; + } + break; + + case IE_RSN: + if (pEid->Len > LEN_PMK_NAME) + { + /* Check PMKR0Name */ + NdisMoveMemory(&PMKR0Name[0], &pEid->Octet[pEid->Len - LEN_PMK_NAME], LEN_PMK_NAME); + if (NdisEqualMemory(&PMKR0Name[0], &pAd->StaCfg.Dot11RCommInfo.PMKR0Name[0], LEN_PMK_NAME)) + Sanity |= 0x04; + } + break; + } + Length = Length + 2 + (USHORT)pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + if ((Sanity & 0x01) == 0) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerFtAuthRspSanity - missing field, Sanity=0x%02x\n", Sanity)); + return FALSE; + } + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + if ((Sanity & 0x07) == 0) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerFtAuthRspSanity - missing field, Sanity=0x%02x\n", Sanity)); + return FALSE; + } + else + { + return TRUE; + } + } + + return TRUE; +} + +/* + ========================================================================== + 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 + + FT_OTA_AUTH_REQ_IDLE FT_OTA_AUTH_WAIT_RESP FT_OTA_AUTH_WAIT_ACK + FT_OTA_MT2_MLME_AUTH_REQ FT_OTA_MT2_MLME_AUTH_REQ invalid_state_when_auth invalid_state_when_auth + FT_OTA_MT2_PEER_AUTH_EVEN Drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action + FT_OTA_MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ + +void FT_OTA_AuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, FT_OTA_MAX_AUTH_STATE, FT_OTA_MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, FT_OTA_AUTH_REQ_IDLE, FT_OTA_AUTH_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, FT_OTA_AUTH_REQ_IDLE, FT_OTA_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)FT_OTA_MlmeAuthReqAction); + + /* the second column */ + StateMachineSetAction(Sm, FT_OTA_AUTH_WAIT_RESP, FT_OTA_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)FT_OTA_InvalidStateWhenAuth); + StateMachineSetAction(Sm, FT_OTA_AUTH_WAIT_RESP, FT_OTA_MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)FT_OTA_PeerAuthRspAction); + + /* the third column */ + StateMachineSetAction(Sm, FT_OTA_AUTH_WAIT_ACK, FT_OTA_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)FT_OTA_InvalidStateWhenAuth); + StateMachineSetAction(Sm, FT_OTA_AUTH_WAIT_ACK, FT_OTA_MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)FT_OTA_PeerAuthAckAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.FtOtaAuthTimer, GET_TIMER_FUNCTION(FT_OTA_AuthTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + function to be executed at timer thread when auth timer expires + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTA_AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + USHORT Status; + + DBGPRINT(RT_DEBUG_TRACE,("FT_OTA_AUTH - FT_OTA_AuthTimeout\n")); + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = FT_OTA_RESPONSE; + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_REQ_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + RTMP_MLME_HANDLER(pAd); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTA_MlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + PMLME_FT_OTA_AUTH_REQ_STRUCT pFtOtaAuthReq = (MLME_FT_OTA_AUTH_REQ_STRUCT *)Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTA_AUTH - FT_OTA_MlmeAuthReqAction allocate memory failed\n")); + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + return; + } + + /* MDIE */ + FT_InsertMdIE(pAd, pOutBuffer, &FrameLen, pFtOtaAuthReq->MdIe.MdId, pFtOtaAuthReq->MdIe.FtCapPlc); + + /* work in an RSN */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + FT_ConstructAuthReqInRsn(pAd, pOutBuffer, &FrameLen); + } + + if (AUTH_ReqSend(pAd, Elem, &pAd->MlmeAux.FtOtaAuthTimer, "FT_OTA_AUTH", 1, pOutBuffer, FrameLen)) + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_WAIT_RESP; + + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTA_PeerAuthRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Seq, Status, Alg; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UINT8 ptk_len; + UCHAR EleID; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, NULL)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && + (Alg == AUTH_MODE_FT) && + (Seq == 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTA_AUTH - Receive FT_OTA_AUTH_RSP to me (Alg=%d, Status=%d)\n", Alg, Status)); + RTMPCancelTimer(&pAd->MlmeAux.FtOtaAuthTimer, &TimerCancelled); + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = FT_OTA_RESPONSE; + if ((Status == MLME_SUCCESS) && + (PeerFtAuthRspSanity(pAd, Addr2, Elem->Msg, Elem->MsgLen, pEntry) == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : Ready to derive PMK \n", __FUNCTION__)); + + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + NdisMoveMemory(pEntry->SNonce, pAd->MlmeAux.FtIeInfo.SNonce, 32); + + /* Get ANonce from authentication-response */ + NdisMoveMemory(pEntry->ANonce, pAd->MlmeAux.FtIeInfo.ANonce, 32); + + FT_DerivePMKR1(pAd->StaCfg.Dot11RCommInfo.PMKR0, + pAd->StaCfg.Dot11RCommInfo.PMKR0Name, + pAd->MlmeAux.Bssid, + pAd->CurrentAddress, + pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME); + + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + ptk_len = 32+32; + else + ptk_len = 32+16; + + /* Derive FT PTK and PTK-NAME */ + FT_DerivePTK(pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME, + pEntry->ANonce, + pEntry->SNonce, + pAd->MlmeAux.Bssid, + pAd->CurrentAddress, + ptk_len, + pEntry->PTK, + pEntry->PTK_NAME); + + if ((pAd->MlmeAux.MdIeInfo.FtCapPlc.field.RsrReqCap == FALSE) || + (pAd->StaCfg.Dot11RCommInfo.bSupportResource == FALSE)) + { + /* + AP doesn't support resource request or + Station doesn't want to do resource request + */ + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + } + else + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTA_AUTH - FT_OTA_MlmeAuthReqAction allocate memory failed\n")); + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + return; + } + + /* Send Auth Confirm */ + /* RSNIE */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + FT_ConstructAuthReqInRsn(pAd, pOutBuffer, &FrameLen); + } + + /* MDIE */ + FT_InsertMdIE(pAd, + pOutBuffer, + &FrameLen, + pAd->MlmeAux.MdIeInfo.MdId, + pAd->MlmeAux.MdIeInfo.FtCapPlc); + + /* RIC-Request */ + EleID = IE_FT_RIC_DATA; + + AUTH_ReqSend(pAd, Elem, &pAd->MlmeAux.FtOtaAuthTimer, "FT_OTA_AUTH", 3, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_WAIT_ACK; + } + } + else + { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTA_PeerAuthAckAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Alg, Seq, Status; + BOOLEAN TimerCancelled; + + if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, NULL)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && + (Alg == AUTH_MODE_FT) && + (Seq == 4)) + { + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTA_AUTH - Receive FT_OTA_AUTH_ACK to me\n")); + RTMPCancelTimer(&pAd->MlmeAux.FtOtaAuthTimer, &TimerCancelled); + pAd->StaCfg.Dot11RCommInfo.FtRspSuccess = FT_OTA_RESPONSE; + if (Status == MLME_SUCCESS) + { + /* Retrieve Reassociation Deadline */ + + /* Check RIC-Response */ + } + else + { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + } + + pAd->Mlme.FtOtaAuthMachine.CurrState = FT_OTA_AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTA_AUTH - FT_OTA_PeerAuthAckAction() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID FT_OTA_InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + DBGPRINT(RT_DEBUG_TRACE, ("FT_OTA_AUTH - FT_OTA_InvalidStateWhenAuth (state=%ld), reset FT_OTA_AUTH state machine\n", pAd->Mlme.FtOtaAuthMachine.CurrState)); +} + +VOID FT_OTA_AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_FT_OTA_AUTH_REQ_STRUCT *pFtOtaAuthReq, + IN PUCHAR pAddr, + IN USHORT Alg, + IN PDOT11R_CMN_STRUC pCmmDot11rCfg) +{ + COPY_MAC_ADDR(pFtOtaAuthReq->Addr, pAddr); + pFtOtaAuthReq->Alg = Alg; + pFtOtaAuthReq->Timeout = (AUTH_TIMEOUT * 2); + + /* MDIE */ + pFtOtaAuthReq->MdIe.FtCapPlc.field.RsrReqCap = 0; + pFtOtaAuthReq->MdIe.FtCapPlc.field.FtOverDs = 0; + if (pCmmDot11rCfg->bSupportResource && pAd->MlmeAux.MdIeInfo.FtCapPlc.field.RsrReqCap) + pFtOtaAuthReq->MdIe.FtCapPlc.field.RsrReqCap = 1; + pFtOtaAuthReq->MdIe.FtCapPlc.field.FtOverDs = pAd->MlmeAux.MdIeInfo.FtCapPlc.field.FtOverDs; + FT_SET_MDID(pFtOtaAuthReq->MdIe.MdId, pCmmDot11rCfg->MdIeInfo.MdId); +} +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/rtmp_ckipmic.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/rtmp_ckipmic.c new file mode 100644 index 000000000..422cbc43f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/rtmp_ckipmic.c @@ -0,0 +1,569 @@ +/* + *************************************************************************** + * 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_ckipmic.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#include "rt_config.h" +#include "rtmp_ckipmic.h" + +#define MIC_ACCUM(v) pContext->accum += (ULONGLONG)v * RTMPMicGetCoefficient(pContext) +#define GB(p,i,s) ( ((ULONG) *((UCHAR*)(p)+i) ) << (s) ) +#define GETBIG32(p) GB(p,0,24)|GB(p,1,16)|GB(p,2,8)|GB(p,3,0) + +/*****************************/ +/******** SBOX Table *********/ +/*****************************/ + +UCHAR SboxTable[256] = +{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +/*===========================================================================*/ +/*=================== CKIP KEY PERMUTATION ==================================*/ +/*===========================================================================*/ + +/* 2-byte by 2-byte subset of the full AES table */ +static const USHORT Sbox[256] = +{ + 0xC6A5,0xF884,0xEE99,0xF68D,0xFF0D,0xD6BD,0xDEB1,0x9154, + 0x6050,0x0203,0xCEA9,0x567D,0xE719,0xB562,0x4DE6,0xEC9A, + 0x8F45,0x1F9D,0x8940,0xFA87,0xEF15,0xB2EB,0x8EC9,0xFB0B, + 0x41EC,0xB367,0x5FFD,0x45EA,0x23BF,0x53F7,0xE496,0x9B5B, + 0x75C2,0xE11C,0x3DAE,0x4C6A,0x6C5A,0x7E41,0xF502,0x834F, + 0x685C,0x51F4,0xD134,0xF908,0xE293,0xAB73,0x6253,0x2A3F, + 0x080C,0x9552,0x4665,0x9D5E,0x3028,0x37A1,0x0A0F,0x2FB5, + 0x0E09,0x2436,0x1B9B,0xDF3D,0xCD26,0x4E69,0x7FCD,0xEA9F, + 0x121B,0x1D9E,0x5874,0x342E,0x362D,0xDCB2,0xB4EE,0x5BFB, + 0xA4F6,0x764D,0xB761,0x7DCE,0x527B,0xDD3E,0x5E71,0x1397, + 0xA6F5,0xB968,0x0000,0xC12C,0x4060,0xE31F,0x79C8,0xB6ED, + 0xD4BE,0x8D46,0x67D9,0x724B,0x94DE,0x98D4,0xB0E8,0x854A, + 0xBB6B,0xC52A,0x4FE5,0xED16,0x86C5,0x9AD7,0x6655,0x1194, + 0x8ACF,0xE910,0x0406,0xFE81,0xA0F0,0x7844,0x25BA,0x4BE3, + 0xA2F3,0x5DFE,0x80C0,0x058A,0x3FAD,0x21BC,0x7048,0xF104, + 0x63DF,0x77C1,0xAF75,0x4263,0x2030,0xE51A,0xFD0E,0xBF6D, + 0x814C,0x1814,0x2635,0xC32F,0xBEE1,0x35A2,0x88CC,0x2E39, + 0x9357,0x55F2,0xFC82,0x7A47,0xC8AC,0xBAE7,0x322B,0xE695, + 0xC0A0,0x1998,0x9ED1,0xA37F,0x4466,0x547E,0x3BAB,0x0B83, + 0x8CCA,0xC729,0x6BD3,0x283C,0xA779,0xBCE2,0x161D,0xAD76, + 0xDB3B,0x6456,0x744E,0x141E,0x92DB,0x0C0A,0x486C,0xB8E4, + 0x9F5D,0xBD6E,0x43EF,0xC4A6,0x39A8,0x31A4,0xD337,0xF28B, + 0xD532,0x8B43,0x6E59,0xDAB7,0x018C,0xB164,0x9CD2,0x49E0, + 0xD8B4,0xACFA,0xF307,0xCF25,0xCAAF,0xF48E,0x47E9,0x1018, + 0x6FD5,0xF088,0x4A6F,0x5C72,0x3824,0x57F1,0x73C7,0x9751, + 0xCB23,0xA17C,0xE89C,0x3E21,0x96DD,0x61DC,0x0D86,0x0F85, + 0xE090,0x7C42,0x71C4,0xCCAA,0x90D8,0x0605,0xF701,0x1C12, + 0xC2A3,0x6A5F,0xAEF9,0x69D0,0x1791,0x9958,0x3A27,0x27B9, + 0xD938,0xEB13,0x2BB3,0x2233,0xD2BB,0xA970,0x0789,0x33A7, + 0x2DB6,0x3C22,0x1592,0xC920,0x8749,0xAAFF,0x5078,0xA57A, + 0x038F,0x59F8,0x0980,0x1A17,0x65DA,0xD731,0x84C6,0xD0B8, + 0x82C3,0x29B0,0x5A77,0x1E11,0x7BCB,0xA8FC,0x6DD6,0x2C3A + }; + +#define Lo8(v16) ((v16) & 0xFF) +#define Hi8(v16) (((v16) >> 8) & 0xFF) +#define u16Swap(i) ( (((i) >> 8) & 0xFF) | (((i) << 8) & 0xFF00) ) +#define _S_(i) (Sbox[Lo8(i)] ^ u16Swap(Sbox[Hi8(i)])) + +#define rotLeft_1(x) ((((x) << 1) | ((x) >> 15)) & 0xFFFF) +VOID CKIP_key_permute + ( + OUT UCHAR *PK, /* output permuted key */ + IN UCHAR *CK, /* input CKIP key */ + IN UCHAR toDsFromDs, /* input toDs/FromDs bits */ + IN UCHAR *piv /* input pointer to IV */ + ) +{ + int i; + USHORT H[2], tmp; /* H=32-bits of per-packet hash value */ + USHORT L[8], R[8]; /* L=u16 array of CK, R=u16 array of PK */ + + /* build L from input key */ + memset(L, 0, sizeof(L)); + for (i=0; i<16; i++) { + L[i>>1] |= ( ((USHORT)(CK[i])) << ( i & 1 ? 8 : 0) ); + } + + H[0] = (((USHORT)piv[0]) << 8) + piv[1]; + H[1] = ( ((USHORT)toDsFromDs) << 8) | piv[2]; + + for (i=0; i<8; i++) { + H[0] ^= L[i]; /* 16-bits of key material */ + tmp = _S_(H[0]); /* 16x16 permutation */ + H[0] = tmp ^ H[1]; /* set up for next round */ + H[1] = tmp; + R[i] = H[0]; /* store into key array */ + } + + /* sweep in the other direction */ + tmp=L[0]; + for (i=7; i>0; i--) { + R[i] = tmp = rotLeft_1(tmp) + R[i]; + } + + /* IV of the permuted key is unchanged */ + PK[0] = piv[0]; + PK[1] = piv[1]; + PK[2] = piv[2]; + + /* key portion of the permuted key is changed */ + for (i=3; i<16; i++) { + PK[i] = (UCHAR) (R[i>>1] >> (i & 1 ? 8 : 0)); + } +} + +/* prepare for calculation of a new mic */ +VOID RTMPCkipMicInit( + IN PMIC_CONTEXT pContext, + IN PUCHAR CK) +{ + /* prepare for new mic calculation */ + NdisMoveMemory(pContext->CK, CK, sizeof(pContext->CK)); + pContext->accum = 0; + pContext->position = 0; +} + +/* add some bytes to the mic calculation */ +VOID RTMPMicUpdate( + IN PMIC_CONTEXT pContext, + IN PUCHAR pOctets, + IN INT len) +{ + INT byte_position; + ULONG val; + + byte_position = (pContext->position & 3); + while (len > 0) { + /* build a 32-bit word for MIC multiply accumulate */ + do { + if (len == 0) return; + pContext->part[byte_position++] = *pOctets++; + pContext->position++; + len--; + } while (byte_position < 4); + /* have a full 32-bit word to process */ + val = GETBIG32(&pContext->part[0]); + MIC_ACCUM(val); + byte_position = 0; + } +} + +ULONG RTMPMicGetCoefficient( + IN PMIC_CONTEXT pContext) +{ + UCHAR aes_counter[16]; + INT coeff_position; + UCHAR *p; + + coeff_position = (pContext->position - 1) >> 2; + if ( (coeff_position & 3) == 0) { + /* fetching the first coefficient -- get new 16-byte aes counter output */ + u32 counter = (coeff_position >> 2); + + /* new counter value */ + memset(&aes_counter[0], 0, sizeof(aes_counter)); + aes_counter[15] = (UINT8)(counter >> 0); + aes_counter[14] = (UINT8)(counter >> 8); + aes_counter[13] = (UINT8)(counter >> 16); + aes_counter[12] = (UINT8)(counter >> 24); + + RTMPAesEncrypt(&pContext->CK[0], &aes_counter[0], pContext->coefficient); + } + p = &(pContext->coefficient[ (coeff_position & 3) << 2 ]); + return GETBIG32(p); +} + +/****************************************/ +/* aes128k128d() */ +/* Performs a 128 bit AES encrypt with */ +/* 128 bit data. */ +/****************************************/ +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<16; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +UCHAR RTMPCkipSbox( + IN UCHAR a) +{ + return SboxTable[(int)a]; +} + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<4; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +VOID next_key( + IN PUCHAR key, + IN INT round) +{ + UCHAR rcon; + UCHAR sbox_key[4]; + UCHAR rcon_table[12] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x36, 0x36 + }; + + sbox_key[0] = RTMPCkipSbox(key[13]); + sbox_key[1] = RTMPCkipSbox(key[14]); + sbox_key[2] = RTMPCkipSbox(key[15]); + sbox_key[3] = RTMPCkipSbox(key[12]); + + rcon = rcon_table[round]; + + xor_32(&key[0], sbox_key, &key[0]); + key[0] = key[0] ^ rcon; + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + + for (i=0; i< 16; i++) + { + out[i] = RTMPCkipSbox(in[i]); + } +} + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + UCHAR add1b[4]; + UCHAR add1bf7[4]; + UCHAR rotl[4]; + UCHAR swap_halfs[4]; + UCHAR andf7[4]; + UCHAR rotr[4]; + UCHAR temp[4]; + UCHAR tempb[4]; + + for (i=0 ; i<4; i++) + { + if ((in[i] & 0x80)== 0x80) + add1b[i] = 0x1b; + else + add1b[i] = 0x00; + } + + swap_halfs[0] = in[2]; /* Swap halfs */ + swap_halfs[1] = in[3]; + swap_halfs[2] = in[0]; + swap_halfs[3] = in[1]; + + rotl[0] = in[3]; /* Rotate left 8 bits */ + rotl[1] = in[0]; + rotl[2] = in[1]; + rotl[3] = in[2]; + + andf7[0] = in[0] & 0x7f; + andf7[1] = in[1] & 0x7f; + andf7[2] = in[2] & 0x7f; + andf7[3] = in[3] & 0x7f; + + for (i = 3; i>0; i--) /* logical shift left 1 bit */ + { + andf7[i] = andf7[i] << 1; + if ((andf7[i-1] & 0x80) == 0x80) + { + andf7[i] = (andf7[i] | 0x01); + } + } + andf7[0] = andf7[0] << 1; + andf7[0] = andf7[0] & 0xfe; + + xor_32(add1b, andf7, add1bf7); + + xor_32(in, add1bf7, rotr); + + temp[0] = rotr[0]; /* Rotate right 8 bits */ + rotr[0] = rotr[1]; + rotr[1] = rotr[2]; + rotr[2] = rotr[3]; + rotr[3] = temp[0]; + + xor_32(add1bf7, rotr, temp); + xor_32(swap_halfs, rotl,tempb); + xor_32(temp, tempb, out); +} + +VOID RTMPAesEncrypt( + IN PUCHAR key, + IN PUCHAR data, + IN PUCHAR ciphertext) +{ + INT round; + INT i; + UCHAR intermediatea[16]; + UCHAR intermediateb[16]; + UCHAR round_key[16]; + + for(i=0; i<16; i++) round_key[i] = key[i]; + + for (round = 0; round < 11; round++) + { + if (round == 0) + { + xor_128(round_key, data, ciphertext); + next_key(round_key, round); + } + else if (round == 10) + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + xor_128(intermediateb, round_key, ciphertext); + } + else /* 1 - 9 */ + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + mix_column(&intermediateb[0], &intermediatea[0]); + mix_column(&intermediateb[4], &intermediatea[4]); + mix_column(&intermediateb[8], &intermediatea[8]); + mix_column(&intermediateb[12], &intermediatea[12]); + xor_128(intermediatea, round_key, ciphertext); + next_key(round_key, round); + } + } + +} + +/* calculate the mic */ +VOID RTMPMicFinal( + IN PMIC_CONTEXT pContext, + OUT UCHAR digest[4]) +{ + INT byte_position; + ULONG val; + ULONGLONG sum, utmp; + LONGLONG stmp; + + /* deal with partial 32-bit word left over from last update */ + if ( (byte_position = (pContext->position & 3)) != 0) { + /* have a partial word in part to deal with -- zero unused bytes */ + do { + pContext->part[byte_position++] = 0; + pContext->position++; + } while (byte_position < 4); + val = GETBIG32(&pContext->part[0]); + MIC_ACCUM(val); + } + + /* reduce the accumulated u64 to a 32-bit MIC */ + sum = pContext->accum; + stmp = (sum & 0xffffffffL) - ((sum >> 32) * 15); + utmp = (stmp & 0xffffffffL) - ((stmp >> 32) * 15); + sum = utmp & 0xffffffffL; + if (utmp > 0x10000000fL) + sum -= 15; + + val = (ULONG)sum; + digest[0] = (UCHAR)((val>>24) & 0xFF); + digest[1] = (UCHAR) ((val>>16) & 0xFF); + digest[2] = (UCHAR) ((val>>8) & 0xFF); + digest[3] = (UCHAR)((val>>0) & 0xFF); +} + +VOID RTMPCkipInsertCMIC( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pMIC, + IN PUCHAR p80211hdr, + IN PNDIS_PACKET pPacket, + IN PCIPHER_KEY pKey, + IN PUCHAR mic_snap) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + ULONG SrcBufLen; + PUCHAR pDA, pSA, pProto; + UCHAR bigethlen[2]; + UCHAR ckip_ck[16]; + MIC_CONTEXT mic_ctx; + USHORT payloadlen; + UCHAR i; + + if (pKey == NULL) + { + DBGPRINT_ERR(("RTMPCkipInsertCMIC, Before to form the CKIP key (CK), pKey can't be NULL\n")); + return; + } + + switch (*(p80211hdr+1) & 3) + { + case 0: /* FromDs=0, ToDs=0 */ + pDA = p80211hdr+4; + pSA = p80211hdr+10; + break; + case 1: /* FromDs=0, ToDs=1 */ + pDA = p80211hdr+16; + pSA = p80211hdr+10; + break; + case 2: /* FromDs=1, ToDs=0 */ + pDA = p80211hdr+4; + pSA = p80211hdr+16; + break; + case 3: /* FromDs=1, ToDs=1 */ + pDA = p80211hdr+16; + pSA = p80211hdr+24; + break; + } + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (SrcBufLen < LENGTH_802_3) + return; + + pProto = pSrcBufVA + 12; + payloadlen = PacketInfo.TotalPacketLength - LENGTH_802_3 + 18; /* CKIP_LLC(8)+CMIC(4)+TxSEQ(4)+PROTO(2)=18 */ + + bigethlen[0] = (unsigned char)(payloadlen >> 8); + bigethlen[1] = (unsigned char)payloadlen; + + /* */ + /* Encryption Key expansion to form the CKIP Key (CKIP_CK). */ + /* */ + if (pKey->KeyLen < 16) + { + for(i = 0; i < (16 / pKey->KeyLen); i++) + { + NdisMoveMemory(ckip_ck + i * pKey->KeyLen, + pKey->Key, + pKey->KeyLen); + } + NdisMoveMemory(ckip_ck + i * pKey->KeyLen, + pKey->Key, + 16 - (i * pKey->KeyLen)); + } + else + { + NdisMoveMemory(ckip_ck, pKey->Key, pKey->KeyLen); + } + RTMPCkipMicInit(&mic_ctx, ckip_ck); + RTMPMicUpdate(&mic_ctx, pDA, MAC_ADDR_LEN); /* MIC <-- DA */ + RTMPMicUpdate(&mic_ctx, pSA, MAC_ADDR_LEN); /* MIC <-- SA */ + RTMPMicUpdate(&mic_ctx, bigethlen, 2); /* MIC <-- payload length starting from CKIP SNAP */ + RTMPMicUpdate(&mic_ctx, mic_snap, 8); /* MIC <-- snap header */ + RTMPMicUpdate(&mic_ctx, pAd->StaCfg.TxSEQ, 4); /* MIC <-- TxSEQ */ + RTMPMicUpdate(&mic_ctx, pProto, 2); /* MIC <-- Protocol */ + + pSrcBufVA += LENGTH_802_3; + SrcBufLen -= LENGTH_802_3; + + /* Mic <-- original payload. loop until all payload processed */ + do + { + if (SrcBufLen > 0) + RTMPMicUpdate(&mic_ctx, pSrcBufVA, SrcBufLen); + + NdisGetNextBuffer(PacketInfo.pFirstBuffer, &PacketInfo.pFirstBuffer); + if (PacketInfo.pFirstBuffer) + { + NDIS_QUERY_BUFFER(PacketInfo.pFirstBuffer, &pSrcBufVA, &SrcBufLen); + } + else + break; + } while (TRUE); + + RTMPMicFinal(&mic_ctx, pMIC); /* update MIC */ +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/rtmp_data.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/rtmp_data.c new file mode 100644 index 000000000..fbe317aed --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/rtmp_data.c @@ -0,0 +1,4470 @@ +/* + *************************************************************************** + * 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_data.c + + Abstract: + Data path subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + + + + + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UCHAR *pTmpBuf; + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) { + /* All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) */ + /* TBD : process fragmented EAPol frames */ + { + /* In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable */ + if ((pAd->StaCfg.wdev.IEEE8021X == TRUE) && + (pAd->StaCfg.wdev.WepStatus == Ndis802_11WEPEnabled) && + (EAP_CODE_SUCCESS == + WpaCheckEapCode(pAd, pRxBlk->pData, + pRxBlk->DataSize, + LENGTH_802_1_H))) { + PUCHAR Key; + UCHAR CipherAlg; + int idx = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); + STA_PORT_SECURED(pAd); + + if (pAd->StaCfg.wpa_supplicant_info.IEEE8021x_required_keys == FALSE) { + idx = pAd->StaCfg.wpa_supplicant_info.DesireSharedKeyId; + CipherAlg = pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx].CipherAlg; + Key = pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx].Key; + + if (pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx].KeyLen > 0) { + /* Set key material and cipherAlg to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + idx, + &pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx]); + + /* STA doesn't need to set WCID attribute for group key */ + + /* Assign pairwise key info */ + RTMP_SET_WCID_SEC_INFO(pAd, + BSS0, + idx, + CipherAlg, + BSSID_WCID, + SHAREDKEYTABLE); + + RTMP_IndicateMediaState(pAd, + NdisMediaStateConnected); + pAd->ExtraInfo = GENERAL_LINK_UP; + + /* For Preventing ShardKey Table is cleared by remove key procedure. */ + pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; + pAd->SharedKey[BSS0][idx].KeyLen = + pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx].KeyLen; + NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, + pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx].Key, + pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[idx].KeyLen); + } + } + } +#ifdef WSC_STA_SUPPORT + else { + /* report EAP packets to MLME to check this packet is WPS packet or not */ + if (pAd->StaCfg.WscControl.WscState >= WSC_STATE_LINK_UP) { + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + + REPORT_MGMT_FRAME_TO_MLME(pAd, + pRxBlk->wcid, + pTmpBuf, + pRxBlk->DataSize +LENGTH_802_11, + pRxBlk->rssi[0], + pRxBlk->rssi[1], + pRxBlk->rssi[2], + 0, + OPMODE_STA); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("!!! report EAPOL DATA to MLME (len=%d) !!!\n", + pRxBlk->DataSize)); + } + } +#endif /* WSC_STA_SUPPORT */ + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + } else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + /* + Special DATA frame that has to pass to MLME + 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process + 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process + */ + { + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, pRxBlk->rssi[0], + pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, + OPMODE_STA); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("!!! report EAPOL DATA to MLME (len=%d) !!!\n", + pRxBlk->DataSize)); + } + } + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; +} + + +VOID STARxDataFrameAnnounce( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + + /* non-EAP frame */ + if (!RTMPCheckWPAframe + (pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) { + /* before LINK UP, all DATA frames are rejected */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } +#ifdef DOT11Z_TDLS_SUPPORT + if (TDLS_CheckTDLSframe(pAd, pRxBlk->pData, pRxBlk->DataSize)) { + UCHAR *pTmpBuf; + + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, pRxBlk->rssi[0], + pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, + OPMODE_STA); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("!!! report TDLS Action DATA to MLME (len=%d) !!!\n", + pRxBlk->DataSize)); + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + + +#ifdef WAPI_SUPPORT + /* report to upper layer if the received frame is WAI frame */ + if (RTMPCheckWAIframe(pRxBlk->pData, pRxBlk->DataSize)) { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif /* WAPI_SUPPORT */ + + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + /* drop all non-EAP DATA frame before */ + /* this client's Port-Access-Control is secured */ + if (pRxBlk->pHeader->FC.Wep) { + /* unsupported cipher suite */ + if (wdev->WepStatus == Ndis802_11EncryptionDisabled) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + } else { + /* encryption in-use but receive a non-EAPOL clear text frame, drop it */ + if ((wdev->WepStatus != Ndis802_11EncryptionDisabled) + && (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + } + } + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); + + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) { + /* Normal legacy, AMPDU or AMSDU */ + CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, + FromWhichBSSID); + + } else { + /* ARALINK */ + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, + FromWhichBSSID); + } +#ifdef QOS_DLS_SUPPORT + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS); +#endif /* QOS_DLS_SUPPORT */ + } else { + RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) + && (pAd->CommonCfg.bDisableReordering == 0)) { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } else +#endif /* DOT11_N_SUPPORT */ + { + /* Determin the destination of the EAP frame */ + /* to WPA state machine or upper layer */ + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } +} + + +#ifdef HDR_TRANS_SUPPORT +VOID STARxDataFrameAnnounce_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + + /* non-EAP frame */ + if (!RTMPCheckWPAframe_Hdr_Trns + (pAd, pEntry, pRxBlk->pTransData, pRxBlk->TransDataSize, FromWhichBSSID)) { + /* before LINK UP, all DATA frames are rejected */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } +#ifdef DOT11Z_TDLS_SUPPORT + // TODO: check!!! + if (TDLS_CheckTDLSframe(pAd, pRxBlk->pData, pRxBlk->DataSize)) { + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + UCHAR *pTmpBuf; + + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, pRxBlk->rssi[0], + pRxBlk->rssi[1], pRxBlk->rssi[2], + 0, + OPMODE_STA); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("!!! report TDLS Action DATA to MLME (len=%d) !!!\n", + pRxBlk->DataSize)); + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef WAPI_SUPPORT + // TODO: Check! + /* report to upper layer if the received frame is WAI frame */ + if (RTMPCheckWAIframe(pRxBlk->pData, pRxBlk->DataSize)) { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif /* WAPI_SUPPORT */ + + { + /* drop all non-EAP DATA frame before */ + /* this client's Port-Access-Control is secured */ + if (pRxBlk->pHeader->FC.Wep) { + /* unsupported cipher suite */ + if (pAd->StaCfg.wdev.WepStatus == Ndis802_11EncryptionDisabled) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + } else { + /* encryption in-use but receive a non-EAPOL clear text frame, drop it */ + if ((pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + && (pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + } + } + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); + + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) { + /* Normal legacy, AMPDU or AMSDU */ + CmmRxnonRalinkFrameIndicate_Hdr_Trns(pAd, pRxBlk, + FromWhichBSSID); + + } else { + /* ARALINK */ + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, + FromWhichBSSID); + } +#ifdef QOS_DLS_SUPPORT + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS); +#endif /* QOS_DLS_SUPPORT */ + } else { + RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) + && (pAd->CommonCfg.bDisableReordering == 0)) { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } else +#endif /* DOT11_N_SUPPORT */ + { + /* Determin the destination of the EAP frame */ + /* to WPA state machine or upper layer */ + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, + FromWhichBSSID); + } + } +} +#endif /* HDR_TRANS_SUPPORT */ + + +/* For TKIP frame, calculate the MIC value */ +BOOLEAN STACheckTkipMICValue( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK * pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + UCHAR UserPriority = pRxBlk->UserPriority; + PCIPHER_KEY pWpaKey; + UCHAR *pDA, *pSA; + + pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->key_idx]; + + pDA = pHeader->Addr1; + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) { + pSA = pHeader->Addr3; + } else { + pSA = pHeader->Addr2; + } + + if (RTMPTkipCompareMICValue(pAd, + pData, + pDA, + pSA, + pWpaKey->RxMic, + UserPriority, DataSize) == FALSE) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n")); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) { + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, pHeader->Addr2, + (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE, + (INT) pRxBlk->key_idx, NULL); + } else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + RTMPReportMicError(pAd, pWpaKey); + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +/* + All Rx routines use RX_BLK structure to hande rx events + It is very important to build pRxBlk attributes + 1. pHeader pointer to 802.11 Header + 2. pData pointer to payload including LLC (just skip Header) + 3. set payload size including LLC to DataSize + 4. set some flags with RX_BLK_SET_FLAG() +*/ +VOID STAHandleRxDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR FromWhichBSSID = BSS0; + UCHAR UserPriority = 0; + +//+++Add by shiang for debug +//---Add by shiangf for debug + + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) { +#ifdef CLIENT_WDS + if ((pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + && IS_ENTRY_CLIENT(&pAd->MacTab.Content[pRxBlk->wcid])) { + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + } else +#endif /* CLIENT_WDS */ + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + else + { + +#ifdef QOS_DLS_SUPPORT + if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxBlk->MPDUtotalByteCnt, pRxInfo)) + return; +#endif /* QOS_DLS_SUPPORT */ + + /* Drop not my BSS frames */ + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + if (pRxInfo->MyBss == 0) { +#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) + /* When the p2p-IF up, the STA own address would be set as my_bssid address. + If receiving an "encrypted" broadcast packet(its WEP bit as 1) and doesn't match my BSSID, + Asic pass to driver with "Decrypted" marked as 0 in pRxInfo. + The condition is below, + 1. p2p IF is ON, + 2. the addr2 of the received packet is STA's BSSID, + 3. broadcast packet, + 4. from DS packet, + 5. Asic pass this packet to driver with "pRxInfo->Decrypted=0" + */ + if ( +#ifdef RT_CFG80211_P2P_SUPPORT + TRUE /* The dummy device always present for CFG80211 application*/ +#else + (P2P_INF_ON(pAd)) +#endif /* RT_CFG80211_P2P_SUPPORT */ + && (MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pHeader->Addr2)) + && (pRxInfo->Bcast || pRxInfo->Mcast) + && (pHeader->FC.FrDs == 1) + && (pHeader->FC.ToDs == 0) + && (pRxInfo->Decrypted == 0)) + { + /* set this m-cast frame is my-bss. */ + pRxInfo->MyBss = 1; + } + else +#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT*/ + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + + pAd->RalinkCounters.RxCountSinceLastNULL++; +#ifdef UAPSD_SUPPORT + if (pAd->StaCfg.UapsdInfo.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable + && (pHeader->FC.SubType & 0x08)) + { + UCHAR *pData; + DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n")); + + /* Qos bit 4 */ + pData = (PUCHAR) pHeader + LENGTH_802_11; + if ((*pData >> 4) & 0x01) + { +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + /* ccv EOSP frame so the peer can sleep */ + if (pEntry != NULL) + { + RTMP_PS_VIRTUAL_SLEEP(pEntry); + } + + if (pAd->StaCfg.FlgPsmCanNotSleep == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> Rcv EOSP frame but we can not sleep!\n")); + } + else +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + { + DBGPRINT(RT_DEBUG_INFO, + ("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); + pAd->CommonCfg.bInServicePeriod = FALSE; + + /* Force driver to fall into sleep mode when rcv EOSP frame */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { +#ifdef RTMP_MAC_PCI + USHORT TbttNumToNextWakeUp; + USHORT NextDtim = pAd->StaCfg.DtimPeriod; + ULONG Now; + + NdisGetSystemUpTime(&Now); + NextDtim -= (USHORT) (Now - pAd->StaCfg.LastBeaconRxTime) / pAd->CommonCfg.BeaconPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + RTMP_SET_PSM_BIT(pAd, PWR_SAVE); + /* if WMM-APSD is failed, try to disable following line */ + AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); +#endif /* RTMP_MAC_PCI */ + + } + } + } + + if ((pHeader->FC.MoreData) + && (pAd->CommonCfg.bInServicePeriod)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Sending another trigger frame when More Data bit is set to 1\n")); + } + } +#endif /* UAPSD_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + /* 1: PWR_SAVE, 0: PWR_ACTIVE */ + if (pEntry != NULL) + { + UCHAR OldPwrMgmt; + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; + + OldPwrMgmt = RtmpPsIndicate(pAd, pHeader->Addr2, + pRxBlk->wcid, pFmeCtrl->PwrMgmt); + +#ifdef UAPSD_SUPPORT + RTMP_PS_VIRTUAL_TIMEOUT_RESET(pEntry); + + if (pFmeCtrl->PwrMgmt) + { + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE)) && + (pFmeCtrl->SubType & 0x08)) + { + /* + In IEEE802.11e, 11.2.1.4 Power management with APSD, + If there is no unscheduled SP in progress, the unscheduled SP begins + when the QAP receives a trigger frame from a non-AP QSTA, which is a + QoS data or QoS Null frame associated with an AC the STA has + configured to be trigger-enabled. + + In WMM v1.1, A QoS Data or QoS Null frame that indicates transition + to/from Power Save Mode is not considered to be a Trigger Frame and + the AP shall not respond with a QoS Null frame. + */ + /* Trigger frame must be QoS data or QoS Null frame */ + UCHAR OldUP; + + if ((*(pRxBlk->pData+LENGTH_802_11) & 0x10) == 0) + { + /* this is not a EOSP frame */ + OldUP = (*(pRxBlk->pData+LENGTH_802_11) & 0x07); + if (OldPwrMgmt == PWR_SAVE) + { + //hex_dump("trigger frame", pRxBlk->pData, 26); + UAPSD_TriggerFrameHandle(pAd, pEntry, OldUP); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("This is a EOSP frame, not a trigger frame!\n")); + } + } + } +#endif /* UAPSD_SUPPORT */ + } +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */ + if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */ + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (pAd->StaCfg.BssType == BSS_INFRA) { + /* Infrastructure mode, check address 2 for BSSID */ + if (1 +#ifdef QOS_DLS_SUPPORT + && (!pAd->CommonCfg.bDLSCapable) +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + && (!IS_TDLS_SUPPORT(pAd)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + ) { + if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->MlmeAux.Bssid, 6)) + { + /* Receive frame not my BSSID */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + } + else + { /* Ad-Hoc mode or Not associated */ + + /* Ad-Hoc mode, check address 3 for BSSID */ + if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) { + /* Receive frame not my BSSID */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + /*/ find pEntry */ + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + } else { + /* IOT issue with Marvell test bed AP + Marvell AP ResetToOOB and do wps. + Because of AP send EAP Request too fast and without retransmit. + STA not yet add BSSID to WCID search table. + So, the EAP Request is dropped. + The patch lookup pEntry from MacTable. + */ + pEntry = MacTableLookup(pAd, &pHeader->Addr2[0]); + if ( pEntry == NULL ) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + /* infra or ad-hoc */ + if (pAd->StaCfg.BssType == BSS_INFRA) { + RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA); +#if defined(DOT11Z_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) + RX_BLK_SET_FLAG(pRxBlk, fRX_DLS); + else +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + { + ASSERT(pRxBlk->wcid == BSSID_WCID); + if (pRxBlk->wcid != BSSID_WCID) + { + printk("[%d] 1: %02x:%02x:%02x:%02x:%02x:%02x, 2: %02x:%02x:%02x:%02x:%02x:%02x, 3:%02x:%02x:%02x:%02x:%02x:%02x", + pRxBlk->wcid, PRINT_MAC(pHeader->Addr1), PRINT_MAC(pHeader->Addr2), PRINT_MAC(pHeader->Addr3)); + } + } + } + +#ifndef WFA_VHT_PF + // TODO: shiang@PF#2, is this atheros protection still necessary here??? + /* check Atheros Client */ + if ((pEntry->bIAmBadAtheros == FALSE) && (pRxInfo->AMPDU == 1) + && (pHeader->FC.Retry)) { + pEntry->bIAmBadAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; + if (!STA_AES_ON(pAd)) + RTMP_UPDATE_PROTECT(pAd, 8 , ALLN_SETPROTECT, TRUE, FALSE); + } +#endif /* WFA_VHT_PF */ + } + + + pRxBlk->pData = (UCHAR *) pHeader; + + /* + update RxBlk->pData, DataSize + 802.11 Header, QOS, HTC, Hw Padding + */ + /* 1. skip 802.11 HEADER */ +#ifdef CLIENT_WDS + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) { + pRxBlk->pData += LENGTH_802_11_WITH_ADDR4; + pRxBlk->DataSize -= LENGTH_802_11_WITH_ADDR4; + } else +#endif /* CLIENT_WDS */ + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + } + + /* 2. QOS */ + if (pHeader->FC.SubType & 0x08) { + RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); + UserPriority = *(pRxBlk->pData) & 0x0f; + /* bit 7 in QoS Control field signals the HT A-MSDU format */ + if ((*pRxBlk->pData) & 0x80) { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); + } + + /* skip QOS contorl field */ + pRxBlk->pData += 2; + pRxBlk->DataSize -= 2; + } + pRxBlk->UserPriority = UserPriority; + + /* check if need to resend PS Poll when received packet with MoreData = 1 */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (pRxInfo->U2M) + { + /* only for unicast packet */ + /* for TDLS power save, More Data bit is not used */ + if (((pEntry != NULL) && (!IS_ENTRY_TDLS(pEntry))) || (pEntry == NULL)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + { + if ((RtmpPktPmBitCheck(pAd) == TRUE) && (pHeader->FC.MoreData == 1)) + { + if ((((UserPriority == 0) || (UserPriority == 3)) && pAd->CommonCfg.bAPSDAC_BE == 0) || + (((UserPriority == 1) || (UserPriority == 2)) && pAd->CommonCfg.bAPSDAC_BK == 0) || + (((UserPriority == 4) || (UserPriority == 5)) && pAd->CommonCfg.bAPSDAC_VI == 0) || + (((UserPriority == 6) || (UserPriority == 7)) && pAd->CommonCfg.bAPSDAC_VO == 0)) + { + /* non-UAPSD delivery-enabled AC */ + RTMP_PS_POLL_ENQUEUE(pAd); + } + } + } +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + /* 3. Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { +#ifdef AGGREGATION_SUPPORT + if ((pRxBlk->rx_rate.field.MODE <= MODE_OFDM) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); + } else +#endif /* AGGREGATION_SUPPORT */ + { +#ifdef DOT11_N_SUPPORT + RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); + /* skip HTC contorl field */ + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; +#endif /* DOT11_N_SUPPORT */ + } + } + + /* 4. skip HW padding */ + if (pRxInfo->L2PAD) { + /* just move pData pointer, because DataSize excluding HW padding */ + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pRxBlk->pData += 2; + } +#ifdef DOT11_N_SUPPORT + if (pRxInfo->BA) { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); + } +#endif /* DOT11_N_SUPPORT */ + +#if defined(SOFT_ENCRYPT) || defined(ADHOC_WPA2PSK_SUPPORT) + /* Use software to decrypt the encrypted frame if necessary. + If a received "encrypted" unicast packet(its WEP bit as 1) + and it's passed to driver with "Decrypted" marked as 0 in pRxInfo. */ + if ((pHeader->FC.Wep == 1) && (pRxInfo->Decrypted == 0)) { + PCIPHER_KEY pSwKey = RTMPSwCipherKeySelection(pAd, + pRxBlk->pData, pRxBlk, + pEntry); + + /* Cipher key table selection */ + if (!pSwKey) { + DBGPRINT(RT_DEBUG_TRACE, ("No vaild cipher key for SW decryption!!!\n")); + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* Decryption by Software */ + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR) pHeader, + UserPriority, + pSwKey, + pRxBlk->pData, + &(pRxBlk->DataSize)) != + NDIS_STATUS_SUCCESS) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + /* Record the Decrypted bit as 1 */ + pRxInfo->Decrypted = 1; + } +#endif /* SOFT_ENCRYPT || ADHOC_WPA2PSK_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef TDLS_AUTOLINK_SUPPORT + if (pAd->StaCfg.TdlsInfo.TdlsAutoLink) + { + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) + TDLS_AutoSetupByRcvFrame(pAd, pHeader); + } +#endif /* TDLS_AUTOLINK_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + + /* Case I Process Broadcast & Multicast data frame */ + if (pRxInfo->Bcast || pRxInfo->Mcast) { +#ifdef STATS_COUNT_SUPPORT + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ + + /* Drop Mcast/Bcast frame with fragment bit on */ + if (pHeader->FC.MoreFrag) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* Filter out Bcast frame which AP relayed for us */ + if (pHeader->FC.FrDs + && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (ADHOC_ON(pAd)) { + MAC_TABLE_ENTRY *pAdhocEntry = NULL; + pAdhocEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pAdhocEntry) + Update_Rssi_Sample(pAd, &pAdhocEntry->RssiSample, pRxWI); + } + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef WFD_SUPPORT + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + pRxInfo->Bcast && + TDLS_CheckTDLSframe(pAd, pRxBlk->pData, pRxBlk->DataSize)) + { + UCHAR *pTmpBuf = pRxBlk->pData - LENGTH_802_11; + + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxBlk->wcid, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, + pRxBlk->rssi[0], + pRxBlk->rssi[1], + pRxBlk->rssi[2], + 0, + OPMODE_STA); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("!!! report TDLS Action DATA to MLME (len=%d) !!!\n", + pRxBlk->DataSize)); + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +#endif /* WFD_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + else if (pRxInfo->U2M) + { + pAd->LastRxRate = (ULONG)(pRxBlk->rx_rate.word); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) { + MAC_TABLE_ENTRY *pDlsEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + if (pDlsEntry && (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE)) { + Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI); + NdisAcquireSpinLock(&pAd->MacTabLock); + pDlsEntry->NoDataIdleCount = 0; + NdisReleaseSpinLock(&pAd->MacTabLock); + } + } + else +#endif + if (INFRA_ON(pAd)) { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + if (pEntry) + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + } + else if (ADHOC_ON(pAd)) { + MAC_TABLE_ENTRY *pAdhocEntry = NULL; + pAdhocEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pAdhocEntry) + Update_Rssi_Sample(pAd, &pAdhocEntry->RssiSample, pRxWI); + } + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + +#ifdef DBG_DIAGNOSE + if (pAd->DiagStruct.inited) { + struct dbg_diag_info *diag_info; + diag_info = &pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx]; + diag_info->RxDataCnt++; +#ifdef DBG_RX_MCS + if (pRxBlk->rx_rate.field.MODE == MODE_HTMIX || + pRxBlk->rx_rate.field.MODE == MODE_HTGREENFIELD) { + if (pRxBlk->rx_rate.field.MCS < MAX_MCS_SET) + diag_info->RxMcsCnt_HT[pRxBlk->rx_rate.field.MCS]++; + } +#ifdef DOT11_VHT_AC + if (pRxBlk->rx_rate.field.MODE == MODE_VHT) { + INT mcs_idx = ((pRxBlk->rx_rate.field.MCS >> 4) * 10) + + (pRxBlk->rx_rate.field.MCS & 0xf); + if (mcs_idx < MAX_VHT_MCS_SET) + diag_info->RxMcsCnt_VHT[mcs_idx]++; + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_RX_MCS */ + } +#endif /* DBG_DIAGNOSE */ + + pAd->StaCfg.LastSNR0 = (UCHAR) (pRxBlk->snr[0]); + pAd->StaCfg.LastSNR1 = (UCHAR) (pRxBlk->snr[1]); +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.RxStream == 3) + pAd->StaCfg.LastSNR2 = (UCHAR) (pRxBlk->snr[2]); +#endif /* DOT11N_SS3_SUPPORT */ + + pAd->RalinkCounters.OneSecRxOkDataCnt++; + + if (pEntry != NULL) + { + pEntry->LastRxRate = pAd->LastRxRate; +#ifdef TXBF_SUPPORT + //if (pRxWI->ShortGI) + if (pRxBlk->rx_rate.field.ShortGI) + pEntry->OneSecRxSGICount++; + else + pEntry->OneSecRxLGICount++; +#endif /* TXBF_SUPPORT */ + + pEntry->freqOffset = (CHAR)(pRxBlk->freq_offset); + pEntry->freqOffsetValid = TRUE; + + } + +#ifdef PRE_ANT_SWITCH +#endif /* PRE_ANT_SWITCH */ + +//Freddy +//#ifdef RTMP_MAC_USB + /* there's packet sent to me, keep awake for 1200ms */ + if (pAd->CountDowntoPsm < 12) + pAd->CountDowntoPsm = 12; +//#endif /* RTMP_MAC_USB */ + + if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) { + /* re-assemble the fragmented packets */ + /* return complete frame (pRxPacket) or NULL */ + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } + + if (pRxPacket) { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + /* process complete frame */ + if (bFragment && (pRxInfo->Decrypted) + && (pEntry->WepStatus == Ndis802_11TKIPEnable)) { + /* Minus MIC length */ + pRxBlk->DataSize -= 8; + + /* For TKIP frame, calculate the MIC value */ + if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) { + return; + } + } + + STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } else { + /* + just return because RTMPDeFragmentDataFrame() will release rx packet, + if packet is fragmented + */ + return; + } + } +#ifdef XLINK_SUPPORT + else if (pAd->StaCfg.PSPXlink) { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif /* XLINK_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + return; +} + + +#ifdef HDR_TRANS_SUPPORT +VOID STAHandleRxDataFrame_Hdr_Trns(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + RXWI_STRUC *pRxWI = pRxBlk->pRxWI; + HEADER_802_11 *pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR FromWhichBSSID = BSS0; + UCHAR UserPriority = 0; + UCHAR *pData; + +//+++Add by shiang for debug +//---Add by shiangf for debug + + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) { +#ifdef CLIENT_WDS + if ((pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + && IS_ENTRY_CLIENT(&pAd->MacTab.Content[pRxBlk->wcid])) { + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + } else +#endif /* CLIENT_WDS */ + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + else + { +#ifdef DOT11V_WNM_SUPPORT + RTMP_SET_WNM_DMS(pRxPacket, 0); + IS_WNM_DMS(pAd, pRxPacket, pHeader); +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef QOS_DLS_SUPPORT + if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxBlk->MPDUtotalByteCnt, pRxBlk->pRxInfo)) + return; +#endif /* QOS_DLS_SUPPORT */ + + /* Drop not my BSS frames */ + if (pRxInfo->MyBss == 0) { + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + + pAd->RalinkCounters.RxCountSinceLastNULL++; + if (pAd->StaCfg.UapsdInfo.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable + && (pHeader->FC.SubType & 0x08)) + { + DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n")); + + /* Qos bit 4 */ + pData = (PUCHAR) pHeader + LENGTH_802_11; + if ((*pData >> 4) & 0x01) + { + DBGPRINT(RT_DEBUG_INFO, + ("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); + pAd->CommonCfg.bInServicePeriod = FALSE; + + /* Force driver to fall into sleep mode when rcv EOSP frame */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { +#ifdef RTMP_MAC_PCI + USHORT TbttNumToNextWakeUp; + USHORT NextDtim = pAd->StaCfg.DtimPeriod; + ULONG Now; + + NdisGetSystemUpTime(&Now); + NextDtim -= (USHORT) (Now - pAd->StaCfg.LastBeaconRxTime) / pAd->CommonCfg.BeaconPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + RTMP_SET_PSM_BIT(pAd, PWR_SAVE); + /* if WMM-APSD is failed, try to disable following line */ + AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); +#endif /* RTMP_MAC_PCI */ + + } + } + + if ((pHeader->FC.MoreData) + && (pAd->CommonCfg.bInServicePeriod)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Sending another trigger frame when More Data bit is set to 1\n")); + } + } + + /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */ + if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */ + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (pAd->StaCfg.BssType == BSS_INFRA) { + /* Infrastructure mode, check address 2 for BSSID */ + if (1 +#ifdef QOS_DLS_SUPPORT + && (!pAd->CommonCfg.bDLSCapable) +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + && (!IS_TDLS_SUPPORT(pAd)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + ) { + if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->MlmeAux.Bssid, 6)) + { + /* Receive frame not my BSSID */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + } + else + { /* Ad-Hoc mode or Not associated */ + + /* Ad-Hoc mode, check address 3 for BSSID */ + if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) { + /* Receive frame not my BSSID */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + /*/ find pEntry */ + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + } else { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* infra or ad-hoc */ + if (pAd->StaCfg.BssType == BSS_INFRA) { + RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA); +#if defined(DOT11Z_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) + if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) + RX_BLK_SET_FLAG(pRxBlk, fRX_DLS); + else +#endif + ASSERT(pRxBlk->wcid == BSSID_WCID); + } + +#ifndef WFA_VHT_PF + // TODO: shiang@PF#2, is this atheros protection still necessary here??? + /* check Atheros Client */ + if ((pEntry->bIAmBadAtheros == FALSE) && (pRxInfo->AMPDU == 1) + && (pHeader->FC.Retry)) { + pEntry->bIAmBadAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; + if (!STA_AES_ON(pAd)) + RTMP_UPDATE_PROTECT(pAd, 8 , ALLN_SETPROTECT, TRUE, FALSE); + } +#endif /* WFA_VHT_PF */ + } + + +#ifdef RLT_MAC +#ifdef CONFIG_RX_CSO_SUPPORT + if (RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_RX_CSO_SUPPORT)) + { + RXFCE_INFO *pRxFceInfo = pRxBlk->pRxFceInfo; + + if ( pRxFceInfo->l3l4_done ) + { + + +/* + if ( (pRxFceInfo->ip_err) || (pRxFceInfo->tcp_err) + || (pRxFceInfo->udp_err) ) { + RTMP_SET_TCP_CHKSUM_FAIL(pRxPacket, TRUE); + } +*/ + // Linux always do IP header chksum + if ( (pRxFceInfo->tcp_err) || (pRxFceInfo->udp_err) ) { + RTMP_SET_TCP_CHKSUM_FAIL(pRxPacket, TRUE); + } + } + } +#endif /* CONFIG_RX_CSO_SUPPORT */ +#endif /* RLT_MAC */ + + pData = (UCHAR *) pHeader; + + /* + update RxBlk->pData, DataSize + 802.11 Header, QOS, HTC, Hw Padding + */ + /* 1. skip 802.11 HEADER */ +#ifdef CLIENT_WDS + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) { + pData += LENGTH_802_11_WITH_ADDR4; + } else +#endif /* CLIENT_WDS */ + { + pData += LENGTH_802_11; + } + + /* 2. QOS */ + if (pHeader->FC.SubType & 0x08) { + RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); + UserPriority = *(pData) & 0x0f; + /* bit 7 in QoS Control field signals the HT A-MSDU format */ + if ((*pData) & 0x80) { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); + } + + /* skip QOS contorl field */ + pData += 2; + } + pRxBlk->UserPriority = UserPriority; + + /* check if need to resend PS Poll when received packet with MoreData = 1 */ + if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) { + if ((((UserPriority == 0) || (UserPriority == 3)) && + pAd->CommonCfg.bAPSDAC_BE == 0) || + (((UserPriority == 1) || (UserPriority == 2)) && + pAd->CommonCfg.bAPSDAC_BK == 0) || + (((UserPriority == 4) || (UserPriority == 5)) && + pAd->CommonCfg.bAPSDAC_VI == 0) || + (((UserPriority == 6) || (UserPriority == 7)) && + pAd->CommonCfg.bAPSDAC_VO == 0)) { + /* non-UAPSD delivery-enabled AC */ + RTMP_PS_POLL_ENQUEUE(pAd); + } + } + + /* 3. Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { +#ifdef AGGREGATION_SUPPORT + if ((pRxBlk->rx_rate.field.MODE <= MODE_OFDM) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); + } else +#endif /* AGGREGATION_SUPPORT */ + { +#ifdef DOT11_N_SUPPORT + RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); + /* skip HTC contorl field */ + pData += 4; +#endif /* DOT11_N_SUPPORT */ + } + } + + /* 4. skip HW padding */ + if (pRxInfo->L2PAD) { + /* just move pData pointer, because DataSize excluding HW padding */ + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pData += 2; + } +#ifdef DOT11_N_SUPPORT + if (pRxInfo->BA) { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); + } +#endif /* DOT11_N_SUPPORT */ + +#if defined(SOFT_ENCRYPT) || defined(ADHOC_WPA2PSK_SUPPORT) + /* Use software to decrypt the encrypted frame if necessary. + If a received "encrypted" unicast packet(its WEP bit as 1) + and it's passed to driver with "Decrypted" marked as 0 in pRxInfo. */ + if ((pHeader->FC.Wep == 1) && (pRxInfo->Decrypted == 0)) { + PCIPHER_KEY pSwKey = RTMPSwCipherKeySelection(pAd, + pRxBlk->pData, pRxBlk, + pEntry); + + /* Cipher key table selection */ + if (!pSwKey) { + DBGPRINT(RT_DEBUG_TRACE, ("No vaild cipher key for SW decryption!!!\n")); + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* Decryption by Software */ + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR) pHeader, + UserPriority, + pSwKey, + pRxBlk->pTransData + 14, + &(pRxBlk->TransDataSize)) != + NDIS_STATUS_SUCCESS) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + /* Record the Decrypted bit as 1 */ + pRxInfo->Decrypted = 1; + } +#endif /* SOFT_ENCRYPT || ADHOC_WPA2PSK_SUPPORT */ + + /* Case I Process Broadcast & Multicast data frame */ + if (pRxInfo->Bcast || pRxInfo->Mcast) { +#ifdef STATS_COUNT_SUPPORT + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ + + /* Drop Mcast/Bcast frame with fragment bit on */ + if (pHeader->FC.MoreFrag) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + /* Filter out Bcast frame which AP relayed for us */ + if (pHeader->FC.FrDs + && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (ADHOC_ON(pAd)) { + MAC_TABLE_ENTRY *pAdhocEntry = NULL; + pAdhocEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pAdhocEntry) + Update_Rssi_Sample(pAd, &pAdhocEntry->RssiSample, pRxWI); + } + + Indicate_Legacy_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID); + return; + } + else if (pRxInfo->U2M) + { + pAd->LastRxRate = (ULONG)(pRxBlk->rx_rate.word); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) { + MAC_TABLE_ENTRY *pDlsEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + if (pDlsEntry && (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE)) { + Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI); + NdisAcquireSpinLock(&pAd->MacTabLock); + pDlsEntry->NoDataIdleCount = 0; + NdisReleaseSpinLock(&pAd->MacTabLock); + } + } + else +#endif + if (ADHOC_ON(pAd)) { + MAC_TABLE_ENTRY *pAdhocEntry = NULL; + pAdhocEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pAdhocEntry) + Update_Rssi_Sample(pAd, &pAdhocEntry->RssiSample, pRxWI); + } + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR) (pRxBlk->snr[0]); + pAd->StaCfg.LastSNR1 = (UCHAR) (pRxBlk->snr[1]); +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.RxStream == 3) + pAd->StaCfg.LastSNR2 = (UCHAR) (pRxBlk->snr[2]); +#endif /* DOT11N_SS3_SUPPORT */ + + pAd->RalinkCounters.OneSecRxOkDataCnt++; + + if (pEntry != NULL) + { + pEntry->LastRxRate = pAd->LastRxRate; +#ifdef TXBF_SUPPORT + if (pRxWI->ShortGI) + pEntry->OneSecRxSGICount++; + else + pEntry->OneSecRxLGICount++; +#endif /* TXBF_SUPPORT */ + + pEntry->freqOffset = (CHAR)(pRxBlk->freq_offset); + pEntry->freqOffsetValid = TRUE; + + } + +#ifdef PRE_ANT_SWITCH +#endif /* PRE_ANT_SWITCH */ + + /* there's packet sent to me, keep awake for 1200ms */ + if (pAd->CountDowntoPsm < 12) + pAd->CountDowntoPsm = 12; + + if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) { + /* re-assemble the fragmented packets */ + /* return complete frame (pRxPacket) or NULL */ + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } + + if (pRxPacket) { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + /* process complete frame */ + if (bFragment && (pRxInfo->Decrypted) + && (pEntry->WepStatus == Ndis802_11TKIPEnable)) { + /* Minus MIC length */ + pRxBlk->DataSize -= 8; + + /* For TKIP frame, calculate the MIC value */ + if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) { + return; + } + } + + STARxDataFrameAnnounce_Hdr_Trns(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } else { + /* + just return because RTMPDeFragmentDataFrame() will release rx packet, + if packet is fragmented + */ + return; + } + } +#ifdef XLINK_SUPPORT + else if (pAd->StaCfg.PSPXlink) { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif /* XLINK_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + return; +} +#endif /* HDR_TRANS_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd) +{ + AsicForceWakeup(pAd, FALSE); +} + + +/* +======================================================================== +Routine Description: + This routine is used to do packet parsing and classification for Tx packet + to STA device, and it will en-queue packets to our TxSwQ depends on AC + class. + +Arguments: + pAd Pointer to our adapter + pPacket Pointer to send packet + +Return Value: + NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQ. + NDIS_STATUS_FAILURE If failed to do en-queue. + +Note: + You only can put OS-indepened & STA related code in here. +======================================================================== +*/ +INT STASendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen, AllowFragSize; + UCHAR NumberOfFrag; + UCHAR QueIdx; + UCHAR UserPriority; + UCHAR Wcid; + unsigned long IrqFlags; + MAC_TABLE_ENTRY *pMacEntry = NULL; + struct wifi_dev *wdev; + + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if ((pSrcBufVA == NULL) || (SrcBufLen <= 14)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_ERROR, ("%s():pkt error(%p, %d)\n", + __FUNCTION__, pSrcBufVA, SrcBufLen)); + return NDIS_STATUS_FAILURE; + } + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + /* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */ + /* Note multicast packets in adhoc also use BSSID_WCID index. */ + { + if (pAd->StaCfg.BssType == BSS_INFRA) { +#if defined(QOS_DLS_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (VALID_WCID(Wcid) && + (IS_ENTRY_DLS(&pAd->MacTab.Content[Wcid]) || + IS_ENTRY_TDLS(&pAd->MacTab.Content[Wcid]))) { + DBGPRINT(RT_DEBUG_TRACE, ("assigning TDLS entry \n", __FUNCTION__)); + pMacEntry = &pAd->MacTab.Content[Wcid]; + } else +#endif /*defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)*/ + { + pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + } + } else if (ADHOC_ON(pAd)) { + if (*pSrcBufVA & 0x01) { + RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); + pMacEntry = &pAd->MacTab.Content[MCAST_WCID]; + } else { +#ifdef XLINK_SUPPORT + if (pAd->StaCfg.PSPXlink) { + pMacEntry = &pAd->MacTab.Content[MCAST_WCID]; + pMacEntry->Aid = MCAST_WCID; + } else +#endif /* XLINK_SUPPORT */ + pMacEntry = MacTableLookup(pAd, pSrcBufVA); + + if (pMacEntry) + RTMP_SET_PACKET_WCID(pPacket, pMacEntry->wcid); +#ifdef ETH_CONVERT_SUPPORT + else { + RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); + } +#endif /* ETH_CONVERT_SUPPORT */ + } + } + } + + if (!pMacEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s():No such Addr(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab\n", + __FUNCTION__, PRINT_MAC(pSrcBufVA))); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + if (ADHOC_ON(pAd) + ) { + RTMP_SET_PACKET_WCID(pPacket, (UCHAR) pMacEntry->wcid); + } + + wdev = &pAd->StaCfg.wdev; + + /* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */ + /* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */ + UserPriority = 0; + QueIdx = QID_AC_BE; + RTMPCheckEtherType(pAd, pPacket, pMacEntry, wdev, &UserPriority, &QueIdx); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + /* the code must behind RTMPCheckEtherType() to get QueIdx */ + if ((pMacEntry != NULL) && + (pMacEntry->PsMode == PWR_SAVE) && + (pMacEntry->FlgPsModeIsWakeForAWhile == FALSE) && + (pMacEntry->bAPSDDeliverEnabledPerAC[QueIdx] == 0)) + { + /* the packet will be sent to AP, not the peer directly */ + pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; + + /* for AP entry, pEntry->bAPSDDeliverEnabledPerAC[QueIdx] always is 0 */ + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + } +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef WAPI_SUPPORT + /* Check the status of the controlled port and filter the outgoing frame for WAPI */ + if (((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || + (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + && (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (RTMP_GET_PACKET_WAI(pPacket) == FALSE) + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s():Drop packet before port secured!\n", __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } +#endif /* WAPI_SUPPORT */ + + /* WPA 802.1x secured port control - drop all non-802.1x frame before port secured */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.wdev.IEEE8021X == TRUE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + ) + && ((wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + || (pAd->StaCfg.MicErrCnt >= 2)) + && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE) + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s():Drop packet before port secured!\n", __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } +#ifdef WSC_STA_SUPPORT + if ((pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger == TRUE) && + (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s():Drop packet before WPS process completed!\n", __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } +#endif /* WSC_STA_SUPPORT */ + + /* + STEP 1. Decide number of fragments required to deliver this MSDU. + The estimation here is not very accurate because difficult to + take encryption overhead into consideration here. The result + "NumberOfFrag" is then just used to pre-check if enough free + TXD are available to hold this MSDU. + */ + if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */ + NumberOfFrag = 1; + else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ + else if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ +#ifdef DOT11_N_SUPPORT + else if ((wdev->HTPhyMode.field.MODE == MODE_HTMIX) + || (wdev->HTPhyMode.field.MODE == MODE_HTGREENFIELD)) + NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */ +#endif /* DOT11_N_SUPPORT */ + else + { + /* + The calculated "NumberOfFrag" is a rough estimation because of various + encryption/encapsulation overhead not taken into consideration. This number is just + used to make sure enough free TXD are available before fragmentation takes place. + In case the actual required number of fragments of an NDIS packet + excceeds "NumberOfFrag"caculated here and not enough free TXD available, the + last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of + resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should + rarely happen and the penalty is just like a TX RETRY fail. Affordable. + */ + UINT32 Size; + + AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + Size = PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H; + NumberOfFrag = (Size / AllowFragSize) + 1; + /* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */ + if ((Size % AllowFragSize) == 0) { + NumberOfFrag--; + } + } + /* Save fragment number to Ndis packet reserved field */ + RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + +{ + BOOLEAN RTSRequired; + + /* + STEP 2. Check the requirement of RTS; decide packet TX rate + If multiple fragment required, RTS is required only for the first fragment + if the fragment size large than RTS threshold + */ + if (NumberOfFrag > 1) + RTSRequired = (pAd->CommonCfg.FragmentThreshold > pAd->CommonCfg.RtsThreshold) ? 1 : 0; + else + RTSRequired = (PacketInfo.TotalPacketLength > pAd->CommonCfg.RtsThreshold) ? 1 : 0; + RTMP_SET_PACKET_RTS(pPacket, RTSRequired); +} + + RTMP_SET_PACKET_UP(pPacket, UserPriority); + +#ifdef ETH_CONVERT_SUPPORT + if (pAd->StaCfg.bFragFlag == TRUE) { + static QUEUE_HEADER queue1[4], queue2[4]; + static BOOLEAN is_init = 0; + static INT32 ID1[4] = { -1, -1, -1, -1 }, ID2[4] = {-1, -1, -1, -1}; + static INT32 ID1_FragSize[4] = { -1, -1, -1, -1 }, ID2_FragSize[4] = {-1, -1, -1, -1}; + static ULONG jiffies1[4], jiffies2[4]; + + QUEUE_HEADER *pAC_Queue1, *pAC_Queue2; + INT32 *pAC_ID1, *pAC_ID2, *pAC_ID1_FragSize, *pAC_ID2_FragSize; + ULONG *pAC_Jiffies1, *pAC_Jiffies2; + + UINT32 i; + typedef union ip_flags_frag_offset { + struct { +#ifdef RT_BIG_ENDIAN + USHORT flags_reserved:1; + USHORT flags_may_frag:1; + USHORT flags_more_frag:1; + USHORT frag_offset:13; +#else + USHORT frag_offset:13; + USHORT flags_more_frag:1; + USHORT flags_may_frag:1; + USHORT flags_reserved:1; +#endif + } field; + USHORT word; + } IP_FLAGS_FRAG_OFFSET; + + typedef struct ip_v4_hdr { +#ifdef RT_BIG_ENDIAN + UCHAR version:4, ihl:4; +#else + UCHAR ihl:4, version:4; +#endif + UCHAR tos; + USHORT tot_len; + USHORT identifier; + } IP_V4_HDR; + + IP_V4_HDR *pIpv4Hdr, Ipv4Hdr; + IP_FLAGS_FRAG_OFFSET *pFlags_frag_offset, Flags_frag_offset; + ULONG Now; + + if (is_init == 0) { + for (i = 0; i < 4; i++) { + InitializeQueueHeader(&queue1[i]); + InitializeQueueHeader(&queue2[i]); + } + is_init = 1; + } + + pAC_Queue1 = &queue1[QueIdx]; + pAC_Queue2 = &queue2[QueIdx]; + pAC_ID1 = &ID1[QueIdx]; + pAC_ID2 = &ID2[QueIdx]; + pAC_ID1_FragSize = &ID1_FragSize[QueIdx]; + pAC_ID2_FragSize = &ID2_FragSize[QueIdx]; + pAC_Jiffies1 = &jiffies1[QueIdx]; + pAC_Jiffies2 = &jiffies2[QueIdx]; + + NdisGetSystemUpTime(&Now); + if ((pAC_Queue1->Number != 0) + && (RTMP_TIME_AFTER(Now, (*pAC_Jiffies1) + (1000 * OS_HZ)))) + { + PQUEUE_ENTRY pBackupPktEntry; + PNDIS_PACKET pBackupPkt; + + while (1) { + pBackupPktEntry = RemoveHeadQueue(pAC_Queue1); + if (pBackupPktEntry == NULL) + break; + pBackupPkt = QUEUE_ENTRY_TO_PACKET(pBackupPktEntry); + RELEASE_NDIS_PACKET(pAd, pBackupPkt, NDIS_STATUS_FAILURE); + } + + *pAC_ID1 = -1; + *pAC_ID1_FragSize = -1; + *pAC_Jiffies1 = 0; + } + + NdisGetSystemUpTime(&Now); + if ((pAC_Queue2->Number != 0) + && (RTMP_TIME_AFTER(Now, (*pAC_Jiffies2) + (1000 * OS_HZ)))) + { + PQUEUE_ENTRY pBackupPktEntry; + PNDIS_PACKET pBackupPkt; + + while (1) { + pBackupPktEntry = RemoveHeadQueue(pAC_Queue2); + if (pBackupPktEntry == NULL) + break; + pBackupPkt = QUEUE_ENTRY_TO_PACKET(pBackupPktEntry); + RELEASE_NDIS_PACKET(pAd, pBackupPkt, NDIS_STATUS_FAILURE); + } + + *pAC_ID2 = -1; + *pAC_ID2_FragSize = -1; + *pAC_Jiffies2 = 0; + } + + if (RTMP_GET_PACKET_IPV4(pPacket) && + ((pAd->TxSwQueue[QueIdx].Number >= (pAd->TxSwQMaxLen >> 1)) || + ((pAC_Queue1->Number) || (pAC_Queue2->Number))) + ) { + pIpv4Hdr = (IP_V4_HDR *) (PacketInfo.pFirstBuffer + LENGTH_802_3); + pFlags_frag_offset = + (IP_FLAGS_FRAG_OFFSET *) (PacketInfo.pFirstBuffer + LENGTH_802_3 + 6); + Flags_frag_offset.word = ntohs(pFlags_frag_offset->word); + Ipv4Hdr.identifier = ntohs(pIpv4Hdr->identifier); + Ipv4Hdr.tot_len = ntohs(pIpv4Hdr->tot_len); + Ipv4Hdr.ihl = pIpv4Hdr->ihl; + + /* check if 1st fragment */ + if ((Flags_frag_offset.field.flags_more_frag == 1) && + (Flags_frag_offset.field.frag_offset == 0)) { + NdisGetSystemUpTime(&Now); + if ((*pAC_ID1) == -1) { + *pAC_ID1 = Ipv4Hdr.identifier; + *pAC_Jiffies1 = Now; + *pAC_ID1_FragSize = Ipv4Hdr.tot_len - (Ipv4Hdr.ihl * 4); + InsertTailQueue(pAC_Queue1, PACKET_TO_QUEUE_ENTRY(pPacket)); + } else if ((*pAC_ID2) == -1) { + *pAC_ID2 = Ipv4Hdr.identifier; + *pAC_Jiffies2 = Now; + *pAC_ID2_FragSize = Ipv4Hdr.tot_len - (Ipv4Hdr.ihl * 4); + InsertTailQueue(pAC_Queue2, PACKET_TO_QUEUE_ENTRY(pPacket)); + } else { + QUEUE_HEADER *pTempqueue; + PQUEUE_ENTRY pBackupPktEntry; + PNDIS_PACKET pBackupPkt; + + /* free backup fragments */ + if ((*pAC_Jiffies1) > (*pAC_Jiffies2)) { + pTempqueue = pAC_Queue2; + *pAC_ID2 = Ipv4Hdr.identifier; + } else { + pTempqueue = pAC_Queue1; + *pAC_ID1 = Ipv4Hdr.identifier; + } + + if (pTempqueue->Number != 0) { + while (1) { + pBackupPktEntry = RemoveHeadQueue(pTempqueue); + if (pBackupPktEntry == NULL) + break; + pBackupPkt = QUEUE_ENTRY_TO_PACKET(pBackupPktEntry); + RELEASE_NDIS_PACKET(pAd, pBackupPkt, NDIS_STATUS_FAILURE); + } + } + } + } else { + /* check if last fragment */ + if ((Ipv4Hdr.identifier == (*pAC_ID1)) + || (Ipv4Hdr.identifier == (*pAC_ID2))) { + QUEUE_HEADER *pTempqueue; + PQUEUE_ENTRY pBackupPktEntry; + PNDIS_PACKET pBackupPkt; + + if (Ipv4Hdr.identifier == (*pAC_ID1)) { + InsertTailQueue(pAC_Queue1, PACKET_TO_QUEUE_ENTRY(pPacket)); + pTempqueue = pAC_Queue1; + } else { + InsertTailQueue(pAC_Queue2, PACKET_TO_QUEUE_ENTRY(pPacket)); + pTempqueue = pAC_Queue2; + } + + /* the last fragment */ + if ((Flags_frag_offset.field.flags_more_frag == 0) + && (Flags_frag_offset.field.frag_offset != 0)) { + UINT32 fragment_count = 0; + BOOLEAN bDrop = FALSE; + if (Ipv4Hdr.identifier == (*pAC_ID1)) { + fragment_count = ((Flags_frag_offset.field.frag_offset * 8) / (*pAC_ID1_FragSize)) + 1; + if (pTempqueue->Number != fragment_count) + bDrop = TRUE; + *pAC_ID1 = -1; + } + + if (Ipv4Hdr.identifier == (*pAC_ID2)) { + fragment_count = ((Flags_frag_offset.field.frag_offset * 8) / (*pAC_ID2_FragSize)) + 1; + if (pTempqueue->Number != fragment_count) + bDrop = TRUE; + *pAC_ID2 = -1; + } + + /* if number does not equal coreect fragment count or no enough space, */ + /* free backup fragments to SwTxQueue[] */ + if ((bDrop == TRUE) || + (pAd->TxSwQueue[QueIdx].Number > (pAd->TxSwQMaxLen - pTempqueue->Number))) { + while (1) { + pBackupPktEntry = RemoveHeadQueue(pTempqueue); + if (pBackupPktEntry == NULL) + break; + pBackupPkt = QUEUE_ENTRY_TO_PACKET(pBackupPktEntry); + RELEASE_NDIS_PACKET(pAd, pBackupPkt, NDIS_STATUS_FAILURE); + } + return + NDIS_STATUS_SUCCESS; + } + + /* move backup fragments to SwTxQueue[] */ + NdisAcquireSpinLock(&pAd->TxSwQueueLock[QueIdx]); + while (1) { + pBackupPktEntry = RemoveHeadQueue(pTempqueue); + if (pBackupPktEntry == NULL) + break; + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], pBackupPktEntry); + } + NdisReleaseSpinLock(&pAd->TxSwQueueLock[QueIdx]); + } + } else { + + /* + bypass none-fist fragmented packets (we should not drop this packet) + when + 1. (pAd->TxSwQueue[QueIdx].Number >= (pAd->TxSwQMaxLen[QueIdx] >> 1) + and + 2. two fragmented buffer are empty + */ + if (((*pAC_ID1) == -1) + && ((*pAC_ID2) == -1)) { + goto normal_drop; + } + + if ((Flags_frag_offset.field.flags_more_frag != 0) + && (Flags_frag_offset.field.frag_offset != 0)) { + NdisAcquireSpinLock(&pAd->TxSwQueueLock[QueIdx]); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + NdisReleaseSpinLock(&pAd->TxSwQueueLock[QueIdx]); + return NDIS_STATUS_SUCCESS; + } else { + goto normal_drop; + } + } + } + } else + goto normal_drop; + } + else + { + normal_drop: +#endif /* ETH_CONVERT_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + if ((pMacEntry != NULL) && + (pMacEntry->PsMode == PWR_SAVE) && + (pMacEntry->FlgPsModeIsWakeForAWhile == FALSE) && + (pMacEntry->bAPSDDeliverEnabledPerAC[QueIdx] != 0)) + { + /* + only UAPSD of the peer for the queue is set; + for non-UAPSD queue, we will send it to the AP. + */ + + if (RtmpInsertPsQueue(pAd, pPacket, pMacEntry, QueIdx) != NDIS_STATUS_SUCCESS) + return NDIS_STATUS_FAILURE; + } + else + /* non-PS mode or send PS packet to AP */ +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + { + /* Make sure SendTxWait queue resource won't be used by other threads */ + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) { + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pPacket); +#endif /* BLOCK_NET_IF */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } else { + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } +#ifdef ETH_CONVERT_SUPPORT + } +#endif /* ETH_CONVERT_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + RTMP_BASetup(pAd, pMacEntry, UserPriority); +#endif /* DOT11_N_SUPPORT */ + + pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; /* TODO: for debug only. to be removed */ + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + + Routine Description: + This subroutine will scan through releative ring descriptor to find + out avaliable free ring descriptor and compare with request size. + + Arguments: + pAd Pointer to our adapter + QueIdx Selected TX Ring + + Return Value: + NDIS_STATUS_FAILURE Not enough free descriptor + NDIS_STATUS_SUCCESS Enough free descriptor + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#ifdef RTMP_MAC_PCI +NDIS_STATUS RTMPFreeTXDRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs) +{ + ULONG FreeNumber = 0; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + + switch (QueIdx) { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + case QID_HCCA: + if (pAd->TxRing[QueIdx].TxSwFreeIdx > + pAd->TxRing[QueIdx].TxCpuIdx) + FreeNumber = + pAd->TxRing[QueIdx].TxSwFreeIdx - + pAd->TxRing[QueIdx].TxCpuIdx - 1; + else + FreeNumber = + pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - + pAd->TxRing[QueIdx].TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; + + case QID_MGMT: + if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx) + FreeNumber = + pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - + 1; + else + FreeNumber = + pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - + pAd->MgmtRing.TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; + +#ifdef CONFIG_ANDES_SUPPORT + case QID_CTRL: + if (pAd->CtrlRing.TxSwFreeIdx > pAd->CtrlRing.TxCpuIdx) + FreeNumber = + pAd->CtrlRing.TxSwFreeIdx - pAd->CtrlRing.TxCpuIdx - + 1; + else + FreeNumber = + pAd->CtrlRing.TxSwFreeIdx + MGMT_RING_SIZE - + pAd->CtrlRing.TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; +#endif /* CONFIG_ANDES_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); + break; + } + *FreeNumberIs = (UCHAR) FreeNumber; + + return (Status); +} +#endif /* RTMP_MAC_PCI */ + + + + +VOID RTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN USHORT PwrMgmt) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif /* RALINK_ATE */ + + /* WPA 802.1x secured port control */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.wdev.IEEE8021X == TRUE) +#endif +#ifdef WAPI_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { + return; + } + + NdisZeroMemory(NullFrame, 48); + Length = sizeof (HEADER_802_11); + + pHeader_802_11 = (PHEADER_802_11) NullFrame; + + pHeader_802_11->FC.Type = FC_TYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_DATA_NULL; + pHeader_802_11->FC.ToDs = 1; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + + if (pAd->CommonCfg.bAPSDForcePowerSave) { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } else { + 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) + pHeader_802_11->FC.PwrMgmt = PwrMgmt; + else + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + } + + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + pHeader_802_11->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ + + /* Prepare QosNull function frame */ + if (bQosNull) { + pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + NullFrame[Length] = 0; + NullFrame[Length + 1] = 0; + Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */ + } + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); + +} + + +/* +-------------------------------------------------------- +FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM + Find the WPA key, either Group or Pairwise Key + LEAP + TKIP also use WPA key. +-------------------------------------------------------- +Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst + In Cisco CCX 2.0 Leap Authentication + WepStatus is Ndis802_11WEPEnabled but the key will use PairwiseKey + Instead of the SharedKey, SharedKey Length may be Zero. +*/ +VOID STAFindCipherAlgorithm(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + NDIS_802_11_ENCRYPTION_STATUS Cipher; /* To indicate cipher used for this packet */ + UCHAR CipherAlg = CIPHER_NONE; /* cipher alogrithm */ + UCHAR KeyIdx = 0xff; + PUCHAR pSrcBufVA; + PCIPHER_KEY pKey = NULL; + PMAC_TABLE_ENTRY pMacEntry; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket); + pMacEntry = pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pMacEntry + && (pMacEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled)) { + if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)) { + /* WAI negotiation packet is always clear. */ + CipherAlg = CIPHER_NONE; + pKey = NULL; + } else { + KeyIdx = pMacEntry->usk_id; /* USK ID */ + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + if (CipherAlg == CIPHER_SMS4) { + pKey = &pMacEntry->PairwiseKey; +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + /* TSC increment pre encryption transmittion */ + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2); + } +#endif /* SOFT_ENCRYPT */ + } + } + } + else +#endif /* WAPI_SUPPORT */ + { + /* Select Cipher */ + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) + Cipher = pAd->StaCfg.GroupCipher; /* Cipher for Multicast or Broadcast */ + else + Cipher = pAd->StaCfg.PairCipher; /* Cipher for Unicast */ + + if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) { + ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128); + + /* 4-way handshaking frame must be clear */ + if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && + (pAd->SharedKey[BSS0][0].CipherAlg) && + (pAd->SharedKey[BSS0][0].KeyLen)) { + CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + KeyIdx = 0; + } + } else if (Cipher == Ndis802_11WEPEnabled) { + KeyIdx = wdev->DefaultKeyId; + } else if ((Cipher == Ndis802_11TKIPEnable) || + (Cipher == Ndis802_11AESEnable)) { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */ + KeyIdx = wdev->DefaultKeyId; + else if (pAd->SharedKey[BSS0][0].KeyLen) + KeyIdx = 0; + else + KeyIdx = wdev->DefaultKeyId; + } + + if (KeyIdx == 0xff) + CipherAlg = CIPHER_NONE; +#ifdef ADHOC_WPA2PSK_SUPPORT + else if ((ADHOC_ON(pAd)) + && (Cipher == Ndis802_11AESEnable) + && (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) + && (wdev->PortSecured == WPA_802_1X_PORT_SECURED)) { + CipherAlg = CIPHER_AES; + pKey = &pAd->SharedKey[BSS0][KeyIdx]; + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + else if ((Cipher == Ndis802_11EncryptionDisabled) + || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) + CipherAlg = CIPHER_NONE; +#ifdef WPA_SUPPLICANT_SUPPORT + else if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP && + (Cipher == Ndis802_11WEPEnabled) && + (wdev->IEEE8021X == TRUE) && + (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + CipherAlg = CIPHER_NONE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + else { + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + pKey = &pAd->SharedKey[BSS0][KeyIdx]; + } + } + + pTxBlk->CipherAlg = CipherAlg; + pTxBlk->pKey = pKey; + pTxBlk->KeyIdx = KeyIdx; +} + + +#ifdef HDR_TRANS_SUPPORT +VOID STABuildWifiInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + PWIFI_INFO_STRUC pWI; +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; +#endif /* QOS_DLS_SUPPORT */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + pTxBlk->MpduHeaderLen = WIFI_INFO_SIZE; + + pWI = + (WIFI_INFO_STRUC *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + + NdisZeroMemory(pWI, WIFI_INFO_SIZE); + + pWI->field.QoS = (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? 1 : 0; + +#ifdef QOS_DLS_SUPPORT + if (INFRA_ON(pAd)) { + /* Check if the frame can be sent through DLS direct link interface */ + /* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */ + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; + } +#endif /* QOS_DLS_SUPPORT */ + + if (pTxBlk->pMacEntry) { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) { + pWI->field.Seq_Num = + pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = + (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ; + } else { + pWI->field.Seq_Num = + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = + (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + } + } else { + pWI->field.Seq_Num = pAd->Sequence; + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ + } + + pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + if (pAd->StaCfg.BssType == BSS_INFRA) { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + pWI->field.Mode = 0; /* IBSS */ + else +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bTdlsEntry)) + pWI->field.Mode = 0; /* IBSS */ + else +#endif /* DOT11Z_TDLS_SUPPORT */ + pWI->field.Mode = 2; /* STA*/ + } else if (ADHOC_ON(pAd)) { + pWI->field.Mode = 0; /* IBSS */ + } + + if (pTxBlk->CipherAlg != CIPHER_NONE) + pWI->field.WEP = 1; + + if (pAd->CommonCfg.bAPSDForcePowerSave) + pWI->field.PS = PWR_SAVE; + else + pWI->field.PS = (pAd->StaCfg.Psm == PWR_SAVE); +} + + +VOID STABuildCacheWifiInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pWiInfo) +{ + PWIFI_INFO_STRUC pWI; + MAC_TABLE_ENTRY *pMacEntry; + + pWI = (PWIFI_INFO_STRUC)pWiInfo; + pMacEntry = pTxBlk->pMacEntry; + + pTxBlk->MpduHeaderLen = WIFI_INFO_SIZE; + + /* More Bit */ + pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + /* Sequence */ + pWI->field.Seq_Num = pMacEntry->TxSeq[pTxBlk->UserPriority]; + pMacEntry->TxSeq[pTxBlk->UserPriority] = + (pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + + { + /* Check if the frame can be sent through DLS direct link interface + If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */ +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; + + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; +#endif /* QOS_DLS_SUPPORT */ + + /* The addr3 of normal packet send from DS is Dest Mac address. */ +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) { + pWI->field.Mode = 0; /* IBSS */ + } else +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bTdlsEntry)) { + pWI->field.Mode = 0; /* IBSS */ + } else +#endif /* DOT11Z_TDLS_SUPPORT */ + if (ADHOC_ON(pAd)) + pWI->field.Mode = 0; /* IBSS */ + else { + pWI->field.Mode = 2; /* STA*/ + } + } + + /* + ----------------------------------------------------------------- + STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + ----------------------------------------------------------------- + */ + if (pAd->CommonCfg.bAPSDForcePowerSave) + pWI->field.PS = PWR_SAVE; + else + pWI->field.PS = (pAd->StaCfg.Psm == PWR_SAVE); +} +#endif /* HDR_TRANS_SUPPORT */ + + +VOID STABuildCommon802_11Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; +#endif /* QOS_DLS_SUPPORT */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + /* MAKE A COMMON 802.11 HEADER */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof (HEADER_802_11); + wifi_hdr = (HEADER_802_11 *)&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize + TSO_SIZE]; + NdisZeroMemory(wifi_hdr, sizeof (HEADER_802_11)); + + wifi_hdr->FC.FrDs = 0; + wifi_hdr->FC.Type = FC_TYPE_DATA; + wifi_hdr->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); + +#ifdef QOS_DLS_SUPPORT + if (INFRA_ON(pAd)) { + /* Check if the frame can be sent through DLS direct link interface */ + /* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */ + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; + } +#endif /* QOS_DLS_SUPPORT */ + + if (pTxBlk->pMacEntry) { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) { + wifi_hdr->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ; + } else { + wifi_hdr->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + } + } else { + wifi_hdr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ + } + + wifi_hdr->Frag = 0; + + wifi_hdr->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + { + if (pAd->StaCfg.BssType == BSS_INFRA) { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(wifi_hdr->Addr3, pAd->CommonCfg.Bssid); + wifi_hdr->FC.ToDs = 0; + } else +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bTdlsEntry)) { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(wifi_hdr->Addr3, pAd->CommonCfg.Bssid); + wifi_hdr->FC.ToDs = 0; + DBGPRINT(RT_DEBUG_TRACE, ("##### TDLS - set header ToDS 0 !!!!!!!!!\n")); + } else +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); + wifi_hdr->FC.ToDs = 1; +#ifdef CLIENT_WDS + if (!MAC_ADDR_EQUAL + ((pTxBlk->pSrcBufHeader + MAC_ADDR_LEN), + pAd->CurrentAddress)) { + wifi_hdr->FC.FrDs = 1; + COPY_MAC_ADDR(&wifi_hdr->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } +#endif /* CLIENT_WDS */ + } + } + else if (ADHOC_ON(pAd)) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pSrcBufHeader); +#ifdef XLINK_SUPPORT + if (pAd->StaCfg.PSPXlink) + /* copy the SA of ether frames to address 2 of 802.11 frame */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); + else +#endif /* XLINK_SUPPORT */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(wifi_hdr->Addr3, pAd->CommonCfg.Bssid); + wifi_hdr->FC.ToDs = 0; + } + } + + if (pTxBlk->CipherAlg != CIPHER_NONE) + wifi_hdr->FC.Wep = 1; + + /* + ----------------------------------------------------------------- + STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + ----------------------------------------------------------------- + */ + if (pAd->CommonCfg.bAPSDForcePowerSave) + wifi_hdr->FC.PwrMgmt = PWR_SAVE; + else + wifi_hdr->FC.PwrMgmt = (RtmpPktPmBitCheck(pAd) == TRUE); + +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE + if (INFRA_ON(pAd)) + { + if (CFG_P2PCLI_ON(pAd) && pAd->cfg80211_ctrl.bP2pCliPmEnable) + wifi_hdr->FC.PwrMgmt = PWR_SAVE; + } +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ +} + + +#ifdef DOT11_N_SUPPORT +VOID STABuildCache802_11Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pHeader) +{ + MAC_TABLE_ENTRY *pMacEntry; + PHEADER_802_11 pHeader80211; + + pHeader80211 = (PHEADER_802_11) pHeader; + pMacEntry = pTxBlk->pMacEntry; + + /* Update the cached 802.11 HEADER */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof (HEADER_802_11); + + /* More Bit */ + pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + /* Sequence */ + pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority]; + pMacEntry->TxSeq[pTxBlk->UserPriority] = + (pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + + { + /* Check if the frame can be sent through DLS direct link interface + If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */ +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; + + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; +#endif /* QOS_DLS_SUPPORT */ + + /* The addr3 of normal packet send from DS is Dest Mac address. */ +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) { + COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + pHeader80211->FC.ToDs = 0; + } else +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bTdlsEntry)) { + COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + } else +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + if (ADHOC_ON(pAd)) + COPY_MAC_ADDR(pHeader80211->Addr3, + pAd->CommonCfg.Bssid); + else { + COPY_MAC_ADDR(pHeader80211->Addr3, + pTxBlk->pSrcBufHeader); +#ifdef CLIENT_WDS + if (!MAC_ADDR_EQUAL + ((pTxBlk->pSrcBufHeader + MAC_ADDR_LEN), + pAd->CurrentAddress)) { + pHeader80211->FC.FrDs = 1; + COPY_MAC_ADDR(&pHeader80211->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } +#endif /* CLIENT_WDS */ + } + } + + /* + ----------------------------------------------------------------- + STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + ----------------------------------------------------------------- + */ + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader80211->FC.PwrMgmt = PWR_SAVE; + else + pHeader80211->FC.PwrMgmt = (RtmpPktPmBitCheck(pAd) == TRUE); +} +#endif /* DOT11_N_SUPPORT */ + + +static inline PUCHAR STA_Build_ARalink_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + HEADER_802_11 *pHeader_802_11; + PNDIS_PACKET pNextPacket; + UINT32 nextBufLen; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* steal "order" bit to mark "aggregation" */ + pHeader_802_11->FC.Order = 1; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + } + + /* padding at front of LLC header. LLC header should at 4-bytes aligment. */ + pTxBlk->HdrPadLen = (ULONG) pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG) (pHeaderBufPtr - pTxBlk->HdrPadLen); + + /* For RA Aggregation, */ + /* put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format */ + pQEntry = pTxBlk->TxPacketList.Head; + pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + nextBufLen = GET_OS_PKT_LEN(pNextPacket); + if (RTMP_GET_PACKET_VLAN(pNextPacket)) + nextBufLen -= LENGTH_802_1Q; + + *pHeaderBufPtr = (UCHAR) nextBufLen & 0xff; + *(pHeaderBufPtr + 1) = (UCHAR) (nextBufLen >> 8); + + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + + return pHeaderBufPtr; + +} + + +#ifdef DOT11_N_SUPPORT +static inline PUCHAR STA_Build_AMSDU_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + HEADER_802_11 *pHeader_802_11; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + /* build QOS Control bytes */ + *pHeaderBufPtr = + (pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg. + AckPolicy[pTxBlk->QueIdx] << 5); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + /* A-MSDU packet */ + *pHeaderBufPtr |= 0x80; + + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + + /* + padding at front of LLC header + LLC header should locate at 4-octets aligment + + @@@ MpduHeaderLen excluding padding @@@ + */ + pTxBlk->HdrPadLen = (ULONG) pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG) (pHeaderBufPtr - pTxBlk->HdrPadLen); + + return pHeaderBufPtr; + +} + + +#ifdef TXBF_SUPPORT +VOID STA_AMPDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN CHAR TxSndgTypePerEntry) +#else +VOID STA_AMPDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +#endif +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber = 0; + MAC_TABLE_ENTRY *pMacEntry; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + BOOLEAN bHTCPlus; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + ASSERT(pTxBlk); + + while (pTxBlk->TxPacketList.Head) { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + pMacEntry = pTxBlk->pMacEntry; + if ((pMacEntry->isCached) +#ifdef TXBF_SUPPORT + && (TxSndgTypePerEntry == SNDG_TYPE_DISABLE) +#endif // TXBF_SUPPORT // + ) + { + /* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!! */ +#ifndef VENDOR_FEATURE1_SUPPORT + NdisMoveMemory((PUCHAR) + (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + (PUCHAR) (&pMacEntry->CachedBuf[0]), + TXWISize + sizeof (HEADER_802_11)); +#else + pTxBlk->HeaderBuf = (UCHAR *) (pMacEntry->HeaderBuf); +#endif /* VENDOR_FEATURE1_SUPPORT */ + + pHeaderBufPtr = (UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]); + STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); + +#ifdef SOFT_ENCRYPT + RTMPUpdateSwCacheCipherInfo(pAd, pTxBlk, pHeaderBufPtr); +#endif /* SOFT_ENCRYPT */ + } else { + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + } + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + /* Check if the original data has enough buffer + to insert or append WPI related field. */ + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + continue; + } + } +#endif /* SOFT_ENCRYPT */ + +#ifdef VENDOR_FEATURE1_SUPPORT + if (pMacEntry->isCached + && (pMacEntry->Protocol == + RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket)) +#ifdef SOFT_ENCRYPT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt) +#endif /* SOFT_ENCRYPT */ +#ifdef TXBF_SUPPORT + && (TxSndgTypePerEntry == SNDG_TYPE_DISABLE) +#endif // TXBF_SUPPORT // + ) + { + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + pTxBlk->MpduHeaderLen = pMacEntry->MpduHeaderLen; + pHeaderBufPtr = ((UCHAR *) pHeader_802_11) + pTxBlk->MpduHeaderLen; + + pTxBlk->HdrPadLen = pMacEntry->HdrPadLen; + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = + pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + } + else +#endif /* VENDOR_FEATURE1_SUPPORT */ + { + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + /* + build QOS Control bytes + */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + + /* + build HTC+ + HTC control field following QoS field + */ + bHTCPlus = FALSE; + + if ((pAd->CommonCfg.bRdg == TRUE) + && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE) +#ifdef TXBF_SUPPORT + && (TxSndgTypePerEntry != SNDG_TYPE_NDP) +#endif /* TXBF_SUPPORT */ + ) + { + if (pMacEntry->isCached == FALSE) + { + /* mark HTC bit */ + pHeader_802_11->FC.Order = 1; + + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + ((PHT_CONTROL)pHeaderBufPtr)->RDG = 1; + } + + bHTCPlus = TRUE; + } + +#ifdef TXBF_SUPPORT + pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE; + + NdisAcquireSpinLock(&pMacEntry->TxSndgLock); + if (TxSndgTypePerEntry >= SNDG_TYPE_SOUNDING) + { + DBGPRINT(RT_DEBUG_TRACE, ("--Sounding in AMPDU: TxSndgType=%d, MCS=%d\n", + TxSndgTypePerEntry, + TxSndgTypePerEntry==SNDG_TYPE_NDP? pMacEntry->sndgMcs: pTxBlk->pTransmit->field.MCS)); + + // Set HTC bit + if (bHTCPlus == FALSE) + { + bHTCPlus = TRUE; + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + } + + if (TxSndgTypePerEntry == SNDG_TYPE_SOUNDING) + { + // Select compress if supported. Otherwise select noncompress + if (pAd->CommonCfg.ETxBfNoncompress==0 && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + } + else if (TxSndgTypePerEntry == SNDG_TYPE_NDP) + { + // Select compress if supported. Otherwise select noncompress + if (pAd->CommonCfg.ETxBfNoncompress==0 && + (pMacEntry->HTCapability.TxBFCap.ExpComBF>0) && + (pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8)) + ) + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3; + else + ((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2; + + // Set NDP Announcement + ((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 1; + + pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW; + pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs; + } + + pTxBlk->TxSndgPkt = TxSndgTypePerEntry; + //pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; + } + + NdisReleaseSpinLock(&pMacEntry->TxSndgLock); + +#ifdef MFB_SUPPORT +#if defined(MRQ_FORCE_TX)//have to replace this by the correct condition!!! + pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ; +#endif + if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) && + (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE))//because the signal format of sounding frmae may be different from normal data frame, which may result in different MFB + { + if (bHTCPlus == FALSE) + { + bHTCPlus = TRUE; + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + } + MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry); + } + + if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ && pMacEntry->toTxMfb == 1) + { + if (bHTCPlus == FALSE) + { + bHTCPlus = TRUE; + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + } + MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry);// not complete yet!!! + pMacEntry->toTxMfb = 0; + } +#endif // MFB_SUPPORT // +#endif // TXBF_SUPPORT // + + if (bHTCPlus) + { + pHeader_802_11->FC.Order = 1; + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + + /* pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */ + ASSERT(pTxBlk->MpduHeaderLen >= 24); + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + /* + padding at front of LLC header + LLC header should locate at 4-octets aligment + + @@@ MpduHeaderLen excluding padding @@@ + */ + pTxBlk->HdrPadLen = (ULONG) pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG) (pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef VENDOR_FEATURE1_SUPPORT + pMacEntry->HdrPadLen = pTxBlk->HdrPadLen; +#endif /* VENDOR_FEATURE1_SUPPORT */ + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + UCHAR iv_offset = 0, ext_offset = 0; + + /* + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, + pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, + &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (PUCHAR) + pHeader_802_11, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, + &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + + } else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufData - 2, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + } + +#ifdef VENDOR_FEATURE1_SUPPORT + pMacEntry->Protocol = + RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket); + pMacEntry->MpduHeaderLen = pTxBlk->MpduHeaderLen; +#endif /* VENDOR_FEATURE1_SUPPORT */ + } + + if ((pMacEntry->isCached) +#ifdef TXBF_SUPPORT + && (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE) +#endif // TXBF_SUPPORT // + ) + { + RTMPWriteTxWI_Cache(pAd, (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } else { + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + NdisZeroMemory((PUCHAR) (&pMacEntry->CachedBuf[0]), sizeof (pMacEntry->CachedBuf)); + NdisMoveMemory((PUCHAR) (&pMacEntry->CachedBuf[0]), (PUCHAR) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr -(PUCHAR) (&pTxBlk->HeaderBuf[TXINFO_SIZE]))); + +#ifdef VENDOR_FEATURE1_SUPPORT + /* use space to get performance enhancement */ + NdisZeroMemory((PUCHAR) (&pMacEntry->HeaderBuf[0]), sizeof (pMacEntry->HeaderBuf)); + NdisMoveMemory((PUCHAR) (&pMacEntry->HeaderBuf[0]), + (PUCHAR) (&pTxBlk->HeaderBuf[0]), + (pHeaderBufPtr - (PUCHAR) (&pTxBlk->HeaderBuf[0]))); +#endif /* VENDOR_FEATURE1_SUPPORT */ + + pMacEntry->isCached = TRUE; + } + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt != SNDG_TYPE_DISABLE) + pMacEntry->isCached = FALSE; +#endif // TXBF_SUPPORT // + +#ifdef STATS_COUNT_SUPPORT + /* calculate Transmitted AMPDU count and ByteCount */ + { + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* STATS_COUNT_SUPPORT */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* Kick out Tx */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + } +} + + +#ifdef HDR_TRANS_SUPPORT +VOID STA_AMPDU_Frame_Tx_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + UCHAR *pWiBufPtr; + USHORT FreeNumber = 0; + MAC_TABLE_ENTRY *pMacEntry; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + BOOLEAN bHTCPlus; + UINT8 TXWISize = pAd->chipCap.TXWISize; + PWIFI_INFO_STRUC pWI; + + ASSERT(pTxBlk); + + while (pTxBlk->TxPacketList.Head) { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + pMacEntry = pTxBlk->pMacEntry; + + if ((pMacEntry->isCached)) + { + /* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!! */ + NdisMoveMemory((PUCHAR) + (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + (PUCHAR) (&pMacEntry->CachedBuf[0]), + TXWISize + WIFI_INFO_SIZE); + + pWiBufPtr = (PUCHAR) (&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]); + + STABuildCacheWifiInfo(pAd, pTxBlk, pWiBufPtr); + + } else { + STAFindCipherAlgorithm(pAd, pTxBlk); + + STABuildWifiInfo(pAd, pTxBlk); + + pWiBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + } + + pWI = (PWIFI_INFO_STRUC)pWiBufPtr; + + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader; + + if (bVLANPkt) + pWI->field.VLAN = TRUE; + + pWI->field.TID = (pTxBlk->UserPriority & 0x0F); + + + { + /* + build HTC+ + HTC control field following QoS field + */ + bHTCPlus = FALSE; + + if ((pAd->CommonCfg.bRdg == TRUE) + && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE) + ) + { + if (pMacEntry->isCached == FALSE) + { + /* mark HTC bit */ + pWI->field.RDG = 1; + } + + bHTCPlus = TRUE; + } + + } + + if ((pMacEntry->isCached)) + { + RTMPWriteTxWI_Cache(pAd, + (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + pTxBlk); + } else { + RTMPWriteTxWI_Data(pAd, + (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + pTxBlk); + + NdisZeroMemory((PUCHAR) (&pMacEntry->CachedBuf[0]), + sizeof (pMacEntry->CachedBuf)); + NdisMoveMemory((PUCHAR) (&pMacEntry->CachedBuf[0]), + (PUCHAR) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + TXWISize + WIFI_INFO_SIZE); + + + pMacEntry->isCached = TRUE; + } + +#ifdef STATS_COUNT_SUPPORT + /* calculate Transmitted AMPDU count and ByteCount */ + { + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + } +#endif /* STATS_COUNT_SUPPORT */ + pTxBlk->NeedTrans = TRUE; + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* Kick out Tx */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + } + +} +#endif /* HDR_TRANS_SUPPORT */ + + +VOID STA_AMSDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber = 0; + USHORT subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding */ + USHORT totalMPDUSize = 0; + UCHAR *subFrameHeader; + UCHAR padding = 0; + USHORT FirstTx = 0, LastTxIdx = 0; + BOOLEAN bVLANPkt; + int frameNum = 0; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + ASSERT((pTxBlk->TxPacketList.Number > 1)); + + while (pTxBlk->TxPacketList.Head) { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = + (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) { + pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk); + + /* NOTE: TxWI->TxWIMPDUByteCnt will be updated after final frame was handled. */ + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } else { + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + padding = ROUND_UP(AMSDU_SUBHEAD_LEN + subFramePayloadLen, 4) - + (AMSDU_SUBHEAD_LEN + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, padding + AMSDU_SUBHEAD_LEN); + pHeaderBufPtr += padding; + pTxBlk->MpduHeaderLen = padding; + } + + /* + A-MSDU subframe + DA(6)+SA(6)+Length(2) + LLC/SNAP Encap + */ + subFrameHeader = pHeaderBufPtr; + subFramePayloadLen = pTxBlk->SrcBufLen; + + NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); + +#ifdef ETH_CONVERT_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bDonglePkt)) + NdisMoveMemory(&subFrameHeader[6], pAd->CurrentAddress, + 6); +#endif /* ETH_CONVERT_SUPPORT */ + + pHeaderBufPtr += AMSDU_SUBHEAD_LEN; + pTxBlk->MpduHeaderLen += AMSDU_SUBHEAD_LEN; + + /* Insert LLC-SNAP encapsulation - 8 octets */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + subFramePayloadLen = pTxBlk->SrcBufLen; + + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + subFramePayloadLen += LENGTH_802_1_H; + } + + /* update subFrame Length field */ + subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; + subFrameHeader[13] = subFramePayloadLen & 0xFF; + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + if (frameNum == 0) + FirstTx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &FreeNumber); + else + LastTxIdx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &FreeNumber); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + frameNum++; + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* calculate Transmitted AMSDU Count and ByteCount */ + { + pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart++; + pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += + totalMPDUSize; + } + + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + /* Kick out Tx */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} +#endif /* DOT11_N_SUPPORT */ + + +VOID STA_Legacy_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; + UCHAR *pHeaderBufPtr; + USHORT FreeNumber = 0; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } +#ifdef STATS_COUNT_SUPPORT + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } +#endif /* STATS_COUNT_SUPPORT */ + + if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate) + pTxBlk->TxRate = pAd->CommonCfg.MinTxRate; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + /* Check if the original data has enough buffer + to insert or append WPI related field. */ + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize + TSO_SIZE]; + wifi_hdr = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* build QOS Control bytes */ + *(pHeaderBufPtr) = + ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] << 5)); +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + } + + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (ULONG) pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG) (pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + UCHAR iv_offset = 0, ext_offset = 0; + + /* + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, + pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (UCHAR *)wifi_hdr, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + + } + else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufHeader + 12 + vlan_size, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + } + +#ifdef ADHOC_WPA2PSK_SUPPORT + if (ADHOC_ON(pAd) + && (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.GroupCipher == Ndis802_11AESEnable) + && (!pTxBlk->pMacEntry)) { + /* use Wcid as Hardware Key Index */ + GET_GroupKey_WCID(pAd, pTxBlk->Wcid, BSS0); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + /* + prepare for TXWI + use Wcid as Key Index + */ + + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* + Kick out Tx + */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +#ifdef HDR_TRANS_SUPPORT +VOID STA_Legacy_Frame_Tx_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber = 0; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + PWIFI_INFO_STRUC pWI; + + ASSERT(pTxBlk); + + //printk("STA_Legacy_Frame_Tx_Hdr_Trns\n"); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +#ifdef STATS_COUNT_SUPPORT + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } +#endif /* STATS_COUNT_SUPPORT */ + + + if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired); + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate) + pTxBlk->TxRate = pAd->CommonCfg.MinTxRate; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildWifiInfo(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + + pWI = (PWIFI_INFO_STRUC)pHeaderBufPtr; + + //hex_dump("wifi info:", pWI, sizeof(WIFI_INFO_STRUC)); + + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader; + + //hex_dump("pSrcBufData" , pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + + if(bVLANPkt) + pWI->field.VLAN = TRUE; + + pWI->field.TID = (pTxBlk->UserPriority & 0x0F); + + +#ifdef ADHOC_WPA2PSK_SUPPORT + if (ADHOC_ON(pAd) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.GroupCipher == Ndis802_11AESEnable) + && (!pTxBlk->pMacEntry)) { + /* use Wcid as Hardware Key Index */ + GET_GroupKey_WCID(pAd, pTxBlk->Wcid, BSS0); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + /* + prepare for TXWI + use Wcid as Key Index + */ + + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + pTxBlk->NeedTrans = TRUE; + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* + Kick out Tx + */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} +#endif /* HDR_TRANS_SUPPORT */ + +VOID STA_ARalink_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK * pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT freeCnt = 0; + USHORT totalMPDUSize = 0; + USHORT FirstTx, LastTxIdx; + int frameNum = 0; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + ASSERT(pTxBlk); + + ASSERT((pTxBlk->TxPacketList.Number == 2)); + + FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */ + while (pTxBlk->TxPacketList.Head) { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = + (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */ + + pHeaderBufPtr = + STA_Build_ARalink_Frame_Header(pAd, pTxBlk); + + /* + It's ok write the TxWI here, because the TxWI->TxWIMPDUByteCnt + will be updated after final frame was handled. + */ + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + + /* + Insert LLC-SNAP encapsulation - 8 octets + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } else { /* For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. */ + + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + pTxBlk->MpduHeaderLen = 0; + + /* + A-Ralink sub-sequent frame header is the same as 802.3 header. + DA(6)+SA(6)+FrameType(2) + */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, + 12); + pHeaderBufPtr += 12; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen = ARALINK_SUBHEAD_LEN; + } + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + /* FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + if (frameNum == 0) + FirstTx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &freeCnt); + else + LastTxIdx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &freeCnt); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + frameNum++; + + pAd->RalinkCounters.OneSecTxAggregationCount++; + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + /* + Kick out Tx + */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + +} + + +VOID STA_Fragment_Frame_Tx( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT freeCnt = 0; + UCHAR fragNum = 0; + PACKET_INFO PacketInfo; + USHORT EncryptionOverhead = 0; + UINT32 FreeMpduSize, SrcRemainingBytes; + USHORT AckDuration; + UINT NextMpduSize; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + HTTRANSMIT_SETTING *pTransmit; +#ifdef SOFT_ENCRYPT + PUCHAR tmp_ptr = NULL; + UINT32 buf_offset = 0; +#endif /* SOFT_ENCRYPT */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag)); + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + +#ifdef SOFT_ENCRYPT + /* + Check if the original data has enough buffer + to insert or append extended field. + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + + if (pTxBlk->CipherAlg == CIPHER_TKIP) { + pTxBlk->pPacket = + duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); + if (pTxBlk->pPacket == NULL) + return; + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, + &pTxBlk->pSrcBufHeader, + &pTxBlk->SrcBufLen); + } + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* + build QOS Control bytes + */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + } + + /* + padding at front of LLC header + LLC header should locate at 4-octets aligment + */ + pTxBlk->HdrPadLen = (ULONG) pHeaderBufPtr; + pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG) (pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + UCHAR iv_offset = 0; + + /* if original Ethernet frame contains no LLC/SNAP, */ + /* then an extra LLC/SNAP encap is required */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, + pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + } else +#endif /* SOFT_ENCRYPT */ + { + + + /* + Insert LLC-SNAP encapsulation - 8 octets + + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufHeader + 12 + vlan_size, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + + /* + If TKIP is used and fragmentation is required. Driver has to + append TKIP MIC at tail of the scatter buffer + MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC + */ + if (pTxBlk->CipherAlg == CIPHER_TKIP) { +#ifdef ETH_CONVERT_SUPPORT + /* + When enable dongle mode for EthernetConverter, we cannot directly calculate the + MIC value base on original 802.3 packet, we need use our MAC address as the + src MAC of 802.3 packet to calculate the MIC, so we use the "bDonglePkt" to + indicate if the function should calculate this packet base on origianl paylaod + or need to change the srcMAC as our MAC address. + */ + RTMPCalculateMICValue(pAd, pTxBlk->pPacket, + pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, + (TX_BLK_TEST_FLAG + (pTxBlk, fTX_bDonglePkt))); +#else + RTMPCalculateMICValue(pAd, pTxBlk->pPacket, + pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, + 0); +#endif /* ETH_CONVERT_SUPPORT */ + + /* + NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust + to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. + */ + NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, + &pAd->PrivateInfo.Tx.MIC[0], 8); + pTxBlk->SrcBufLen += 8; + pTxBlk->TotalFrameLen += 8; + } + + /* + calcuate the overhead bytes that encryption algorithm may add. This + affects the calculate of "duration" field + */ + if ((pTxBlk->CipherAlg == CIPHER_WEP64) + || (pTxBlk->CipherAlg == CIPHER_WEP128)) + EncryptionOverhead = 8; /* WEP: IV[4] + ICV[4]; */ + else if (pTxBlk->CipherAlg == CIPHER_TKIP) + EncryptionOverhead = 12; /* TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */ + else if (pTxBlk->CipherAlg == CIPHER_AES) + EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */ +#ifdef WAPI_SUPPORT + else if (pTxBlk->CipherAlg == CIPHER_SMS4) + EncryptionOverhead = 16; /* SMS4: MIC[16] */ +#endif /* WAPI_SUPPORT */ + else + EncryptionOverhead = 0; + + pTransmit = pTxBlk->pTransmit; + /* Decide the TX rate */ + if (pTransmit->field.MODE == MODE_CCK) + pTxBlk->TxRate = pTransmit->field.MCS; + else if (pTransmit->field.MODE == MODE_OFDM) + pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE; + else + pTxBlk->TxRate = RATE_6_5; + + /* decide how much time an ACK/CTS frame will consume in the air */ + if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE) + AckDuration = + RTMPCalcDuration(pAd, + pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], + 14); + else + AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14); + + /* Init the total payload length of this frame. */ + SrcRemainingBytes = pTxBlk->SrcBufLen; + + pTxBlk->TotalFragNum = 0xff; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + /* store the outgoing frame for calculating MIC per fragmented frame */ + os_alloc_mem(pAd, (PUCHAR *) & tmp_ptr, pTxBlk->SrcBufLen); + if (tmp_ptr == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("!!!%s : no memory for SW MIC calculation !!!\n", + __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + return; + } + NdisMoveMemory(tmp_ptr, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + } +#endif /* SOFT_ENCRYPT */ + + do { + FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC - pTxBlk->MpduHeaderLen; + if (SrcRemainingBytes <= FreeMpduSize) { /* this is the last or only fragment */ + + pTxBlk->SrcBufLen = SrcRemainingBytes; + + pHeader_802_11->FC.MoreFrag = 0; + pHeader_802_11->Duration = + pAd->CommonCfg.Dsifs + AckDuration; + + /* Indicate the lower layer that this's the last fragment. */ + pTxBlk->TotalFragNum = fragNum; + } else { /* more fragment is required */ + + pTxBlk->SrcBufLen = FreeMpduSize; + + NextMpduSize = + min(((UINT) SrcRemainingBytes - pTxBlk->SrcBufLen), + ((UINT) pAd->CommonCfg.FragmentThreshold)); + pHeader_802_11->FC.MoreFrag = 1; + pHeader_802_11->Duration = + (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + + RTMPCalcDuration(pAd, pTxBlk->TxRate, + NextMpduSize + EncryptionOverhead); + } + + SrcRemainingBytes -= pTxBlk->SrcBufLen; + + if (fragNum == 0) + pTxBlk->FrameGap = IFS_HTTXOP; + else + pTxBlk->FrameGap = IFS_SIFS; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + UCHAR ext_offset = 0; + + NdisMoveMemory(pTxBlk->pSrcBufData, + tmp_ptr + buf_offset, pTxBlk->SrcBufLen); + buf_offset += pTxBlk->SrcBufLen; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (PUCHAR) pHeader_802_11, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + + } +#endif /* SOFT_ENCRYPT */ + + RTMPWriteTxWI_Data(pAd, (TXWI_STRUC *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &freeCnt); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* Update the frame number, remaining size of the NDIS packet payload. */ +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { +#ifdef WAPI_SUPPORT + if (pTxBlk->CipherAlg == CIPHER_SMS4) { + /* incease WPI IV for next MPDU */ + inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WAPI_TSC, + 2); + /* Construct and insert WPI-SMS4 IV header to MPDU header */ + RTMPConstructWPIIVHdr(pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr - + (LEN_WPI_IV_HDR)); + } else +#endif /* WAPI_SUPPORT */ + if ((pTxBlk->CipherAlg == CIPHER_WEP64) + || (pTxBlk->CipherAlg == CIPHER_WEP128)) { + inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WEP_TSC, + 1); + /* Construct and insert 4-bytes WEP IV header to MPDU header */ + RTMPConstructWEPIVHdr(pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr - + (LEN_WEP_IV_HDR)); + } else if (pTxBlk->CipherAlg == CIPHER_TKIP) ; + else if (pTxBlk->CipherAlg == CIPHER_AES) { + inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WPA_TSC, + 1); + /* Construct and insert 8-bytes CCMP header to MPDU header */ + RTMPConstructCCMPHdr(pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr - + (LEN_CCMP_HDR)); + } + } else +#endif /* SOFT_ENCRYPT */ + { + /* space for 802.11 header. */ + if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap) + pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; + } + + fragNum++; + /* SrcRemainingBytes -= pTxBlk->SrcBufLen; */ + pTxBlk->pSrcBufData += pTxBlk->SrcBufLen; + + pHeader_802_11->Frag++; /* increase Frag # */ + + } while (SrcRemainingBytes > 0); + +#ifdef SOFT_ENCRYPT + if (tmp_ptr != NULL) + os_free_mem(pAd, tmp_ptr); +#endif /* SOFT_ENCRYPT */ + + /* + Kick out Tx + */ +#ifdef PCIE_PS_SUPPORT + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) +#endif /* PCIE_PS_SUPPORT */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \ + while(_pTxBlk->TxPacketList.Head) \ + { \ + _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \ + RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \ + } + + +#ifdef VHT_TXBF_SUPPORT +VOID STA_NDPA_Frame_Tx(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pMacEntry) +{ + UCHAR *buf; + VHT_NDPA_FRAME *vht_ndpa; + struct wifi_dev *wdev; + UINT frm_len, sta_cnt; + SNDING_STA_INFO *sta_info; + + + if (pMacEntry) + { + wdev = pMacEntry->wdev; + + if (MlmeAllocateMemory(pAd, &buf) != NDIS_STATUS_SUCCESS) + return; + + NdisZeroMemory(buf, MGMT_DMA_BUFFER_SIZE); + + vht_ndpa = (VHT_NDPA_FRAME *)buf; + frm_len = sizeof(VHT_NDPA_FRAME); + vht_ndpa->fc.Type = FC_TYPE_CNTL; + vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA; + COPY_MAC_ADDR(vht_ndpa->ra, pMacEntry->Addr); + COPY_MAC_ADDR(vht_ndpa->ta, wdev->if_addr); + + /* Currnetly we only support 1 STA for a VHT DNPA */ + sta_info = vht_ndpa->sta_info; + sta_info->aid12 = 0; + sta_info->fb_type = SNDING_FB_SU; + sta_info->nc_idx = 0; + vht_ndpa->token.token_num = pMacEntry->snd_dialog_token; + frm_len += sizeof(SNDING_STA_INFO); + + if (frm_len >= (MGMT_DMA_BUFFER_SIZE - sizeof(SNDING_STA_INFO))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): len(%d) too large!cnt=%d\n", + __FUNCTION__, frm_len, sta_cnt)); + } + + if (pMacEntry->snd_dialog_token & 0xc0) + pMacEntry->snd_dialog_token = 0; + else + pMacEntry->snd_dialog_token++; + + vht_ndpa->duration = 100; + + //DBGPRINT(RT_DEBUG_OFF, ("Send VHT NDPA Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + // PRINT_MAC(pMacEntry->Addr))); + //hex_dump("VHT NDPA Frame", buf, frm_len); + + // NDPA's BW needs to sync with Tx BW + pAd->CommonCfg.MlmeTransmit.field.BW = pMacEntry->HTPhyMode.field.BW; + + MiniportMMRequest(pAd, 0, buf, frm_len); + MlmeFreeMemory(pAd, buf); + } + + //pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; +} +#endif /* VHT_TXBF_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#ifdef TXBF_SUPPORT +NDIS_STATUS STAHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR QueIdx, UCHAR TxSndgTypePerEntry) +#else +NDIS_STATUS STAHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR QueIdx) +#endif +{ + NDIS_PACKET *pPacket; + PQUEUE_ENTRY pQEntry; + +#ifdef HDR_TRANS_SUPPORT + BOOLEAN bDoHdrTrans = TRUE; +#endif /* HDR_TRANS_SUPPORT */ + + /* + --------------------------------------------- + STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. + --------------------------------------------- + */ + ASSERT(pTxBlk->TxPacketList.Number); + if (pTxBlk->TxPacketList.Head == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("pTxBlk->TotalFrameNum == %ld!\n", + pTxBlk->TxPacketList.Number)); + return NDIS_STATUS_FAILURE; + } + + pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head); + + /* there's packet to be sent, keep awake for 1200ms */ + if (pAd->CountDowntoPsm < 12) + pAd->CountDowntoPsm = 12; + + /* ------------------------------------------------------------------ + STEP 1. WAKE UP PHY + outgoing frame always wakeup PHY to prevent frame lost and + turn off PSM bit to improve performance + ------------------------------------------------------------------ + not to change PSM bit, just send this frame out? + */ + if ((pAd->StaCfg.Psm == PWR_SAVE) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n")); +#ifdef RTMP_MAC_PCI + AsicForceWakeup(pAd, TRUE); +#endif /* RTMP_MAC_PCI */ + } + + /* It should not change PSM bit, when APSD turn on. */ + if ((! + (pAd->StaCfg.UapsdInfo.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable) + && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) + || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) { + if ((RtmpPktPmBitCheck(pAd) == TRUE) && + (pAd->StaCfg.WindowsPowerMode == + Ndis802_11PowerModeFast_PSP)) + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); + } + +#ifdef HDR_TRANS_SUPPORT +#ifdef SOFT_ENCRYPT + if ( TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) /* need LLC, not yet generated */ + bDoHdrTrans = FALSE; + else +#endif /* SOFT_ENCRYPT */ +#ifdef XLINK_SUPPORT + if ( pAd->StaCfg.PSPXlink ) /* Use SA as Address 2 */ + bDoHdrTrans = FALSE; + else +#endif /* XLINK_SUPPORT */ +#ifdef CLIENT_WDS + if (!MAC_ADDR_EQUAL /* 4 MAC Addresses */ + ((pTxBlk->pSrcBufHeader + MAC_ADDR_LEN), + pAd->CurrentAddress)) + bDoHdrTrans = FALSE; + else +#endif /* CLIENT_WDS */ + { +#ifdef TXBF_SUPPORT + bDoHdrTrans = FALSE; +#endif // TXBF_SUPPORT // + } +#endif /* HDR_TRANS_SUPPORT */ + + switch (pTxBlk->TxFrameType) { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: +#ifdef HDR_TRANS_SUPPORT + if (bDoHdrTrans) + STA_AMPDU_Frame_Tx_Hdr_Trns(pAd, pTxBlk); + else +#endif /* HDR_TRANS_SUPPORT */ +#ifdef TXBF_SUPPORT + STA_AMPDU_Frame_Tx(pAd, pTxBlk, TxSndgTypePerEntry); +#else + STA_AMPDU_Frame_Tx(pAd, pTxBlk); +#endif + + break; + case TX_AMSDU_FRAME: + STA_AMSDU_Frame_Tx(pAd, pTxBlk); + break; +#endif /* DOT11_N_SUPPORT */ + case TX_LEGACY_FRAME: + { +#ifdef HDR_TRANS_SUPPORT + if (bDoHdrTrans) + STA_Legacy_Frame_Tx_Hdr_Trns(pAd, pTxBlk); + else +#endif /* HDR_TRANS_SUPPORT */ + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + } + case TX_MCAST_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_RALINK_FRAME: + STA_ARalink_Frame_Tx(pAd, pTxBlk); + break; + case TX_FRAG_FRAME: + STA_Fragment_Frame_Tx(pAd, pTxBlk); + break; + default: + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, + ("Send a pacekt was not classified!! It should not happen!\n")); + while (pTxBlk->TxPacketList.Number) { + pQEntry = + RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_FAILURE); + } + } + break; + } + + return (NDIS_STATUS_SUCCESS); + +} + + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + if (TRUE + ) { + announce_802_3_packet(pAd, pPacket, OPMODE_STA); + } else { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sanity.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sanity.c new file mode 100644 index 000000000..63cec52ec --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sanity.c @@ -0,0 +1,433 @@ +/* + *************************************************************************** + * 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: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +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 BROADCOM_OUI[]; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeStartReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen) +{ + MLME_START_REQ_STRUCT *Info; + + Info = (MLME_START_REQ_STRUCT *) (Msg); + + if (Info->SsidLen > MAX_LEN_OF_SSID) { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong SSID length\n", + __FUNCTION__)); + return FALSE; + } + + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *ie_list) +{ + CHAR IeType, *Ptr; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PEID_STRUCT pEid; + ULONG Length = 0; +#ifdef DOT11R_FT_SUPPORT + FT_MIC_CONTENT ft_mic_cont; +#endif /* DOT11R_FT_SUPPORT */ + + *pNewExtChannelOffset = 0xff; + *pHtCapabilityLen = 0; + *pAddHtInfoLen = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + Ptr = (CHAR *) pFrame->Octet; + Length += LENGTH_802_11; + + NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); + Length += 2; + NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); + Length += 2; + *pCkipFlag = 0; + *pExtRateLen = 0; + pEdcaParm->bValid = FALSE; + + if (*pStatus != MLME_SUCCESS) + return TRUE; + + NdisMoveMemory(pAid, &pFrame->Octet[4], 2); + Length += 2; + + /* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */ + *pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */ + + /* -- get supported rates from payload and advance the pointer */ + IeType = pFrame->Octet[6]; + *pSupRateLen = pFrame->Octet[7]; + if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong SupportedRates IE\n", __FUNCTION__)); + return FALSE; + } else + NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); + +#ifdef DOT11R_FT_SUPPORT + NdisZeroMemory(&ft_mic_cont, sizeof (FT_MIC_CONTENT)); +#endif /* DOT11R_FT_SUPPORT */ + + Length = Length + 2 + *pSupRateLen; + + /* + many AP implement proprietary IEs in non-standard order, we'd better + tolerate mis-ordered IEs to get best compatibility + */ + pEid = (PEID_STRUCT) & pFrame->Octet[8 + (*pSupRateLen)]; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch (pEid->Eid) + { + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + +#ifdef DOT11_N_SUPPORT + case IE_HT_CAP: + case IE_HT_CAP2: + if (pEid->Len >= SIZE_HT_CAP_IE) { /* Note: allow extension.!! */ + NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); + + *(USHORT *) (&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *) (&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + + *pHtCapabilityLen = SIZE_HT_CAP_IE; + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_HT_CAP\n", __FUNCTION__)); + } + + break; + + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof (ADD_HT_INFO_IE)) { + /* + This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only + copy first sizeof(ADD_HT_INFO_IE) + */ + NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof (ADD_HT_INFO_IE)); + + *(USHORT *) (&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2)); + *(USHORT *) (&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3)); + + *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_ADD_HT\n", __FUNCTION__)); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) { + *pNewExtChannelOffset = pEid->Octet[0]; + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_SECONDARY_CH_OFFSET\n", __FUNCTION__)); + } + break; + +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (pEid->Len == sizeof(VHT_CAP_IE)) { + NdisMoveMemory(&ie_list->vht_cap, pEid->Octet, sizeof(VHT_CAP_IE)); + ie_list->vht_cap_len = sizeof(VHT_CAP_IE); + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP\n", __FUNCTION__)); + } + break; + + case IE_VHT_OP: + if (pEid->Len == sizeof(VHT_OP_IE)) { + NdisMoveMemory(&ie_list->vht_op, pEid->Octet, sizeof(VHT_OP_IE)); + ie_list->vht_op_len = sizeof(VHT_OP_IE); + }else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_OP\n", __FUNCTION__)); + } + break; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + case IE_VENDOR_SPECIFIC: + /* handle WME PARAMTER ELEMENT */ + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + /* parsing EDCA parameters */ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ + pEdcaParm->EdcaUpdateCount = + pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = + (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = (PUCHAR) & pEid->Octet[8]; + for (i = 0; i < 4; i++) { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ + pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f; /* b0~4 is Cwmin */ + pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4; /* b5~8 is Cwmax */ + pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */ + ptr += 4; /* point to next AC */ + } + } + break; +#ifdef DOT11R_FT_SUPPORT + case IE_FT_MDIE: + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport) { + if (pEid->Len + 2 != 5) { + DBGPRINT(RT_DEBUG_WARN, + ("%s - wrong length of IE_FT_MDIE \n", + __FUNCTION__)); + break; + } + /* + Record the MDIE of (re)association response of + Initial Mobility Domain Association. It's used in + FT 4-Way handshaking + */ + if (pAd->StaCfg.Dot11RCommInfo. + bInMobilityDomain == FALSE) + NdisMoveMemory(pAd->MlmeAux.InitialMDIE, + pEid, pEid->Len + 2); + + ft_mic_cont.mdie_ptr = (PUINT8) pEid; + ft_mic_cont.mdie_len = pEid->Len + 2; + } + break; + case IE_FT_FTIE: + pAd->MlmeAux.FtIeInfo.Len = 0; + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport) { + if (pEid->Len >= sizeof (FT_FTIE)) { + /* + Record the FTIE of (re)association response of + Initial Mobility Domain Association. It's used in + FT 4-Way handshaking + */ + if (pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain == FALSE) { + pAd->MlmeAux.InitialFTIE_Len = pEid->Len + 2; + NdisMoveMemory(pAd->MlmeAux.InitialFTIE, + pEid, pEid->Len + 2); + } + + FT_FillFtIeInfo(pEid, &pAd->MlmeAux.FtIeInfo); + ft_mic_cont.ftie_ptr = (PUINT8) pEid; + ft_mic_cont.ftie_len = pEid->Len + 2; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("%s():pEid->Len(%d) < sizeof(FT_FTIE)\n", __FUNCTION__, pEid->Len)); + } + break; + case IE_RSN: + ft_mic_cont.rsnie_ptr = (PUINT8) pEid; + ft_mic_cont.rsnie_len = pEid->Len + 2; + break; +#endif /* DOT11R_FT_SUPPORT */ + case IE_EXT_CAPABILITY: + if (pEid->Len >= 1) + { + UCHAR MaxSize; + UCHAR MySize = sizeof(EXT_CAP_INFO_ELEMENT); + + MaxSize = min(pEid->Len, MySize); + NdisMoveMemory(pExtCapInfo, &pEid->Octet[0], MaxSize); + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_EXT_CAPABILITY!\n")); + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s():ignore unrecognized EID = %d\n", __FUNCTION__, pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + +#ifdef DOT11R_FT_SUPPORT + /* Check the MIC during FT */ + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain && + pAd->StaCfg.WepStatus != Ndis802_11WEPDisabled) { + UINT8 rcvd_mic[16]; + UINT8 ft_mic[16]; + + NdisZeroMemory(rcvd_mic, 16); + NdisZeroMemory(ft_mic, 16); + NdisMoveMemory(rcvd_mic, ft_mic_cont.ftie_ptr + 4, 16); + + FT_CalculateMIC(pAd->CurrentAddress, + pAd->MlmeAux.Bssid, + pAd->MacTab.Content[MCAST_WCID].PTK, + 6, + ft_mic_cont.rsnie_ptr, + ft_mic_cont.rsnie_len, + ft_mic_cont.mdie_ptr, + ft_mic_cont.mdie_len, + ft_mic_cont.ftie_ptr, + ft_mic_cont.ftie_len, + ft_mic_cont.ric_ptr, + ft_mic_cont.ric_len, ft_mic); + if (RTMPEqualMemory(ft_mic, rcvd_mic, 16) == FALSE) { + DBGPRINT_ERR(("%s : MIC is different\n", __FUNCTION__)); + hex_dump("received MIC", rcvd_mic, 16); + hex_dump("desired MIC", ft_mic, 16); + + return FALSE; + } + } +#endif /* DOT11R_FT_SUPPORT */ + + return TRUE; +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe) +{ + UCHAR BitCntl, N1, N2, MyByte, MyBit; + CHAR *IdxPtr; + + IdxPtr = Ptr; + + IdxPtr++; + *TimLen = *IdxPtr; + + /* get DTIM Count from TIM element */ + IdxPtr++; + *DtimCount = *IdxPtr; + + /* get DTIM Period from TIM element */ + IdxPtr++; + *DtimPeriod = *IdxPtr; + + /* get Bitmap Control from TIM element */ + IdxPtr++; + BitCntl = *IdxPtr; + + if ((*DtimCount == 0) && (BitCntl & 0x01)) + *BcastFlag = TRUE; + else + *BcastFlag = FALSE; + + /* Parse Partial Virtual Bitmap from TIM element */ + N1 = BitCntl & 0xfe; /* N1 is the first bitmap byte# */ + N2 = *TimLen - 4 + N1; /* N2 is the last bitmap byte# */ + + if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3))) + *MessageToMe = FALSE; + else { + MyByte = (Aid >> 3) - N1; /* my byte position in the bitmap byte-stream */ + MyBit = Aid % 16 - ((MyByte & 0x01) ? 8 : 0); + + IdxPtr += (MyByte + 1); + + if (*IdxPtr & (0x01 << MyBit)) + *MessageToMe = TRUE; + else + *MessageToMe = FALSE; + } + + return TRUE; +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta.c new file mode 100644 index 000000000..b0a8bb573 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta.c @@ -0,0 +1,255 @@ +/* + *************************************************************************** + * 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: + sta.c + + Abstract: + initialization for STA module + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +VOID STARxErrorHandle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + +} + +/* + ======================================================================== + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error found + ======================================================================== +*/ +INT RTMPCheckRxError( + IN RTMP_ADAPTER *pAd, + IN HEADER_802_11 *pHeader, + IN RX_BLK *pRxBlk, + IN RXINFO_STRUC *pRxInfo) +{ + if(pRxInfo == NULL) + return NDIS_STATUS_FAILURE; + + /* Phy errors & CRC errors*/ + if (pRxInfo->Crc) + { + INT dBm = (pRxBlk->rssi[0]) - pAd->BbpRssiToDbmDelta; + + /* Check RSSI for Noise Hist statistic collection.*/ + if (dBm <= -87) + pAd->StaCfg.RPIDensity[0] += 1; + else if (dBm <= -82) + pAd->StaCfg.RPIDensity[1] += 1; + else if (dBm <= -77) + pAd->StaCfg.RPIDensity[2] += 1; + else if (dBm <= -72) + pAd->StaCfg.RPIDensity[3] += 1; + else if (dBm <= -67) + pAd->StaCfg.RPIDensity[4] += 1; + else if (dBm <= -62) + pAd->StaCfg.RPIDensity[5] += 1; + else if (dBm <= -57) + pAd->StaCfg.RPIDensity[6] += 1; + else if (dBm > -57) + pAd->StaCfg.RPIDensity[7] += 1; + + return NDIS_STATUS_FAILURE; + } + + /* Add Rx size to channel load counter, we should ignore error counts*/ + //pAd->StaCfg.CLBusyBytes += (pRxBlk->MPDUtotalByteCnt + 14); + + /* Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics*/ + if (pHeader != NULL) + { +#ifndef CLIENT_WDS + if (pHeader->FC.ToDs + ) + { + return NDIS_STATUS_FAILURE; + } +#endif /* CLIENT_WDS */ + } + + /* Paul 04-03 for OFDM Rx length issue*/ + if (pRxBlk->MPDUtotalByteCnt > MAX_AGGREGATION_SIZE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n")); + return NDIS_STATUS_FAILURE; + } + + /* + Drop not U2M frames, cant's drop here because we will drop beacon in this case + I am kind of doubting the U2M bit operation + */ + /* + if (pRxInfo->U2M == 0) + return NDIS_STATUS_FAILURE; + */ + + /* drop decyption fail frame*/ + if (pRxInfo->Decrypted && pRxInfo->CipherErr) + { + + if (pRxInfo->CipherErr == 2) + {DBGPRINT_RAW(RT_DEBUG_TRACE,("RxErr: ICV ok but MICErr"));} + else if (pRxInfo->CipherErr == 1) + {DBGPRINT_RAW(RT_DEBUG_TRACE,("RxErr: ICV Err"));} + else if (pRxInfo->CipherErr == 3) + DBGPRINT_RAW(RT_DEBUG_TRACE,("RxErr: Key not valid")); + + if (INFRA_ON(pAd) && pRxInfo->MyBss) { + if ((pRxInfo->CipherErr & 1) == 1) { + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID].Addr, + BSS0, 0); + } + + /* MIC Error*/ + if (pRxInfo->CipherErr == 2) { + CIPHER_KEY *pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->key_idx]; + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) + WpaSendMicFailureToWpaSupplicant(pAd->net_dev,pHeader->Addr2, + (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE, + (INT) pRxBlk->key_idx, NULL); + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + RTMPReportMicError(pAd, pWpaKey); + + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID].Addr, + BSS0, 0); + } + } + + DBGPRINT_RAW(RT_DEBUG_TRACE,("%s(): %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", + __FUNCTION__, pRxInfo->CipherErr, pRxBlk->MPDUtotalByteCnt, + pRxInfo->Mcast | pRxInfo->Bcast, pRxInfo->MyBss, pRxBlk->wcid, + pRxBlk->key_idx)); + + dump_rxinfo(pAd, pRxInfo); + dump_rxwi(pAd, pRxBlk->pRxWI); + hex_dump("ErrorPkt", (UCHAR *)pHeader, pRxBlk->MPDUtotalByteCnt); + + if (pHeader == NULL) + return NDIS_STATUS_SUCCESS; + + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + + +INT StaAllowToSendPacket( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + PNDIS_PACKET pPacket, + UCHAR *pWcid) +{ + BOOLEAN allowToSend; + + if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) + { + return FALSE; + } + else + { + if (ADHOC_ON(pAd)) + { + RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); + } + if (INFRA_ON(pAd) && (0 +#ifdef QOS_DLS_SUPPORT + || (pAd->CommonCfg.bDLSCapable) +#endif /* QOS_DLS_SUPPORT */ +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || IS_TDLS_SUPPORT(pAd) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + )) { + MAC_TABLE_ENTRY *pEntry; + PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + pEntry = MacTableLookup(pAd, pSrcBufVA); + + if (pEntry && (IS_ENTRY_DLS(pEntry) +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || IS_ENTRY_TDLS(pEntry) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + )) + { + *pWcid = pEntry->wcid; + } + else + *pWcid = 0; + } else { + *pWcid = 0; + } + + allowToSend = TRUE; + } + + return allowToSend; +} + + +INT StaAllowToSendPacket_new( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + IN UCHAR *pWcid) +{ + MAC_TABLE_ENTRY *pEntry; + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (MAC_ADDR_IS_GROUP(pSrcBufVA)) + { + *pWcid = MCAST_WCID; + return TRUE; + } + + pEntry = MacTableLookup(pAd, pSrcBufVA); + if (pEntry && (pEntry->Sst == SST_ASSOC)) + { + *pWcid = (UCHAR)pEntry->wcid; + return TRUE; + } + + return FALSE; +} + + +INT STAInitialize(RTMP_ADAPTER *pAd) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + wdev->wdev_type = WDEV_TYPE_STA; + wdev->tx_pkt_allowed = StaAllowToSendPacket; + wdev->allow_data_tx = TRUE; + + return 0; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta_cfg.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta_cfg.c new file mode 100644 index 000000000..805eea1b5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta_cfg.c @@ -0,0 +1,10878 @@ +/* + *************************************************************************** + * 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: + sta_ioctl.c + + Abstract: + IOCTL related subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + + +INT Set_AutoReconnect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AdhocN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +#ifdef RTMP_RBUS_SUPPORT +#ifdef LED_CONTROL_SUPPORT +INT Set_WlanLed_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + + +#ifdef CARRIER_DETECTION_SUPPORT +INT Set_StaCarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_DyncVgaEnable_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef IWSC_SUPPORT +INT Set_IWscLimitedUI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef IWSC_TEST_SUPPORT +INT Set_IWscDefaultSecurity_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IWscSmpbcEnrScanOnly_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IWscEmptySubmaskList_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IWscBlockConnection_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* IWSC_TEST_SUPPORT */ + +INT Set_IWscOOB_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_IWscSinglePIN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* IWSC_SUPPORT */ + +#ifdef CONFIG_SNIFFER_SUPPORT +INT set_monitor_channel(PRTMP_ADAPTER ad, PSTRING arg) +{ + INT bw = 0, channel = 0, pri_idx = 0, rv = 0; + UINT rf_val = 0; + UINT8 ext_ch; + + if (arg) { + rv = sscanf(arg, "%d,%d,%d", &(bw), &(channel), &(pri_idx)); + DBGPRINT(RT_DEBUG_TRACE, ("%s():rv = %d, bw = %d, channel = %d, pri_idx = %d\n", __FUNCTION__, rv, bw, channel, pri_idx)); + ad->CommonCfg.Channel = channel; + if (rv == 3) { + if (bw == BW_40) { + if (pri_idx == 0) { + ad->CommonCfg.CentralChannel = ad->CommonCfg.Channel + 2; + ext_ch = EXTCHA_ABOVE; + } else if (pri_idx == 1) { + ext_ch = EXTCHA_BELOW; + if (channel == 14) { + ad->CommonCfg.CentralChannel = ad->CommonCfg.Channel - 1; + } else { + ad->CommonCfg.CentralChannel = ad->CommonCfg.Channel - 2; + } + } else { + DBGPRINT(RT_DEBUG_ERROR, ("pri_idx(%d) is invalid\n")); + return FALSE; + } + } + } else if (rv == 2) { + if (bw == BW_20) { + ad->CommonCfg.CentralChannel = channel; + } else if ((bw == BW_80) && channel > 14) { +#ifdef DOT11_VHT_AC + ad->CommonCfg.vht_bw = VHT_BW_80; + ad->CommonCfg.vht_cent_ch = vht_cent_ch_freq(ad, ad->CommonCfg.Channel); +#endif + } else { + return FALSE; + } + } else { + + return FALSE; + } + } + + bbp_set_bw(ad, bw); + + /* TX/Rx : control channel setting */ + rtmp_mac_set_ctrlch(ad, ext_ch); + bbp_set_ctrlch(ad, ext_ch); + +#ifdef DOT11_VHT_AC + if (ad->CommonCfg.BBPCurrentBW == BW_80) + ad->hw_cfg.cent_ch = ad->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + ad->hw_cfg.cent_ch = ad->CommonCfg.CentralChannel; + + AsicSwitchChannel(ad, ad->hw_cfg.cent_ch, FALSE); + AsicLockChannel(ad, ad->hw_cfg.cent_ch); + + return TRUE; +} +#endif +#ifdef ED_MONITOR +//let run-time turn on/off +INT set_ed_chk_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_block_tx_thresh(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_false_cca_threshold(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_threshold(RTMP_ADAPTER *pAd, PSTRING arg); +INT show_ed_stat_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_current_rssi_threhold_proc(RTMP_ADAPTER *pAd, PSTRING arg); +INT set_ed_debug_proc(RTMP_ADAPTER *pAd, PSTRING arg); +#endif /* ED_MONITOR */ +INT show_ed_cnt_for_channel_quality(RTMP_ADAPTER *pAd, PSTRING arg); + + +static struct { + PSTRING name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); +} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { + {"DriverVersion", Set_DriverVersion_Proc}, + {"CountryRegion", Set_CountryRegion_Proc}, + {"CountryRegionABand", Set_CountryRegionABand_Proc}, + {"SSID", Set_SSID_Proc}, + {"WirelessMode", Set_WirelessMode_Proc}, + {"TxBurst", Set_TxBurst_Proc}, + {"TxPreamble", Set_TxPreamble_Proc}, + {"TxPower", Set_TxPower_Proc}, + {"Channel", Set_Channel_Proc}, + {"BGProtection", Set_BGProtection_Proc}, + {"RTSThreshold", Set_RTSThreshold_Proc}, + {"FragThreshold", Set_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Set_HtBw_Proc}, + {"HtMcs", Set_HtMcs_Proc}, + {"HtGi", Set_HtGi_Proc}, + {"HtOpMode", Set_HtOpMode_Proc}, + {"HtStbc", Set_HtStbc_Proc}, + {"HtExtcha", Set_HtExtcha_Proc}, + {"HtMpduDensity", Set_HtMpduDensity_Proc}, + {"HtBaWinSize", Set_HtBaWinSize_Proc}, + {"HtRdg", Set_HtRdg_Proc}, + {"HtAmsdu", Set_HtAmsdu_Proc}, + {"HtAutoBa", Set_HtAutoBa_Proc}, + {"HtBaDecline", Set_BADecline_Proc}, + {"HtProtect", Set_HtProtect_Proc}, + {"HtMimoPs", Set_HtMimoPs_Proc}, + {"HtDisallowTKIP", Set_HtDisallowTKIP_Proc}, +#ifdef DOT11N_DRAFT3 + {"HtBssCoex", Set_HT_BssCoex_Proc}, +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + {"VhtBw", Set_VhtBw_Proc}, + {"VhtStbc", Set_VhtStbc_Proc}, + {"VhtBwSignal", set_VhtBwSignal_Proc}, +#endif /* DOT11_VHT_AC */ + +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Set_PktAggregate_Proc}, +#endif /* AGGREGATION_SUPPORT */ + + {"WmmCapable", Set_WmmCapable_Proc}, + {"IEEE80211H", Set_IEEE80211H_Proc}, + {"NetworkType", Set_NetworkType_Proc}, + {"AuthMode", Set_AuthMode_Proc}, + {"EncrypType", Set_EncrypType_Proc}, + {"DefaultKeyID", Set_DefaultKeyID_Proc}, + {"Key1", Set_Key1_Proc}, + {"Key2", Set_Key2_Proc}, + {"Key3", Set_Key3_Proc}, + {"Key4", Set_Key4_Proc}, + {"WPAPSK", Set_WPAPSK_Proc}, + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"PSMode", Set_PSMode_Proc}, +#ifdef DBG + {"Debug", Set_Debug_Proc}, + {"DebugFunc", Set_DebugFunc_Proc}, +#endif /* DBG */ + +#ifdef TXBF_SUPPORT +#ifndef MT76x2 + {"TxBfTag", Set_TxBfTag_Proc}, + {"ReadITxBf", Set_ReadITxBf_Proc}, + {"WriteITxBf", Set_WriteITxBf_Proc}, + {"StatITxBf", Set_StatITxBf_Proc}, + {"ReadETxBf", Set_ReadETxBf_Proc}, + {"WriteETxBf", Set_WriteETxBf_Proc}, + {"StatETxBf", Set_StatETxBf_Proc}, + {"ETxBfTimeout", Set_ETxBfTimeout_Proc}, +#ifdef STA_ITXBF_SUPPORT + {"ITxBfTimeout", Set_ITxBfTimeout_Proc}, + {"InvTxBfTag", Set_InvTxBfTag_Proc}, + {"ITxBfCal", Set_ITxBfCal_Proc}, + {"ITxBfDivCal", Set_ITxBfDivCal_Proc}, + {"ITxBfLnaCal", Set_ITxBfLnaCal_Proc}, +#endif /* STA_ITXBF_SUPPORT */ +#else +#ifdef STA_ITXBF_SUPPORT + {"InvTxBfTag", Set_InvTxBfTag_Proc}, + {"ITxBfDivCal", Set_ITxBfDivCal_Proc}, + {"ITxBfEn", Set_ITxBfEn_Proc}, +#endif +#endif + {"ETxBfEnCond", Set_StaETxBfEnCond_Proc}, + {"ETxBfCodebook", Set_ETxBfCodebook_Proc}, + {"ETxBfCoefficient", Set_ETxBfCoefficient_Proc}, + {"ETxBfGrouping", Set_ETxBfGrouping_Proc}, + {"ETxBfNoncompress", Set_ETxBfNoncompress_Proc}, + {"ETxBfIncapable", Set_ETxBfIncapable_Proc}, + {"NoSndgCntThrd", Set_NoSndgCntThrd_Proc}, + {"NdpSndgStreams", Set_NdpSndgStreams_Proc}, + {"TriggerSounding", Set_Trigger_Sounding_Proc}, + +#ifdef MT76x2 + {"TxBfProfileTagHelp", Set_TxBfProfileTag_Help}, + {"TxBfProfileTagValid", Set_TxBfProfileTagValid}, + {"TxBfProfileTagTimeOut", Set_TxBfProfileTag_TimeOut}, + {"TxBfProfileTagMatrix", Set_TxBfProfileTag_Matrix}, + {"TxBfProfileTagSNR", Set_TxBfProfileTag_SNR}, + {"TxBfProfileTagTxScale", Set_TxBfProfileTag_TxScale}, + {"TxBfProfileTagMac", Set_TxBfProfileTag_MAC}, + {"TxBfProfileTagFlg", Set_TxBfProfileTag_Flg}, + {"TxBfProfileTagRead", Set_TxBfProfileTagRead}, + {"TxBfProfileTagWrite", Set_TxBfProfileTagWrite}, + {"TxBfProfileDataRead", Set_TxBfProfileDataRead}, + {"TxBfProfileDataWrite", Set_TxBfProfileDataWrite}, + {"TxBfProfileDataReadAll", Set_TxBfProfileDataReadAll}, + {"TxBfProfileDataWriteAll",Set_TxBfProfileDataWriteAll}, +#endif +#endif /* TXBF_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + {"StreamMode", Set_StreamMode_Proc}, + {"StreamModeMCS", Set_StreamModeMCS_Proc}, +#endif /* STREAM_MODE_SUPPORT */ + + {"RateAlg", Set_RateAlg_Proc}, +#ifdef NEW_RATE_ADAPT_SUPPORT + {"LowTrafficThrd", Set_LowTrafficThrd_Proc}, + {"TrainUpRule", Set_TrainUpRule_Proc}, + {"TrainUpRuleRSSI", Set_TrainUpRuleRSSI_Proc}, + {"TrainUpLowThrd", Set_TrainUpLowThrd_Proc}, + {"TrainUpHighThrd", Set_TrainUpHighThrd_Proc}, + {"RateTable", Set_RateTable_Proc}, +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef PRE_ANT_SWITCH + {"PreAntSwitch", Set_PreAntSwitch_Proc}, + {"PreAntSwitchRSSI", Set_PreAntSwitchRSSI_Proc}, + {"PreAntSwitchTimeout", Set_PreAntSwitchTimeout_Proc}, +#endif /* PRE_ANT_SWITCH */ + + +#ifdef DBG_CTRL_SUPPORT + {"DebugFlags", Set_DebugFlags_Proc}, +#ifdef INCLUDE_DEBUG_QUEUE + {"DebugQueue", Set_DebugQueue_Proc}, +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef RALINK_ATE + {"ATE", Set_ATE_Proc}, + {"ATEDA", Set_ATE_DA_Proc}, + {"ATESA", Set_ATE_SA_Proc}, + {"ATEBSSID", Set_ATE_BSSID_Proc}, + {"ATECHANNEL", Set_ATE_CHANNEL_Proc}, + {"ATEINITCHAN", Set_ATE_INIT_CHAN_Proc}, + {"ADCDump", Set_ADCDump_Proc}, +#ifdef RTMP_TEMPERATURE_CALIBRATION + {"ATETEMPCAL", Set_ATE_TEMP_CAL_Proc}, +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#ifdef RTMP_INTERNAL_TX_ALC + {"ATETSSICBA", Set_ATE_TSSI_CALIBRATION_Proc}, + {"ATETSSICBAEX", Set_ATE_TSSI_CALIBRATION_EX_Proc}, +#if defined(RT3350) || defined(RT3352) + {"ATETSSICALBRENABLE", RT335x_Set_ATE_TSSI_CALIBRATION_ENABLE_Proc}, +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + {"ATEREADEXTSSI", Set_ATE_READ_EXTERNAL_TSSI_Proc}, +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + {"ATETXPOW0", Set_ATE_TX_POWER0_Proc}, + {"ATETXPOW1", Set_ATE_TX_POWER1_Proc}, +#ifdef DOT11N_SS3_SUPPORT + {"ATETXPOW2", Set_ATE_TX_POWER2_Proc}, +#endif /* DOT11N_SS3_SUPPORT */ + {"ATETXPOWEVAL", Set_ATE_TX_POWER_EVALUATION_Proc}, + {"ATETXANT", Set_ATE_TX_Antenna_Proc}, + {"ATERXANT", Set_ATE_RX_Antenna_Proc}, + {"ATETXFREQOFFSET", Set_ATE_TX_FREQ_OFFSET_Proc}, + {"ATETXBW", Set_ATE_TX_BW_Proc}, + {"ATETXLEN", Set_ATE_TX_LENGTH_Proc}, + {"ATETXCNT", Set_ATE_TX_COUNT_Proc}, + {"ATETXMCS", Set_ATE_TX_MCS_Proc}, + {"ATETXSTBC", Set_ATE_TX_STBC_Proc}, + {"ATETXMODE", Set_ATE_TX_MODE_Proc}, + {"ATETXGI", Set_ATE_TX_GI_Proc}, + {"ATERXFER", Set_ATE_RX_FER_Proc}, + {"ATERRF", Set_ATE_Read_RF_Proc}, +#if (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) + {"ATEWRF1", Set_ATE_Write_RF1_Proc}, + {"ATEWRF2", Set_ATE_Write_RF2_Proc}, + {"ATEWRF3", Set_ATE_Write_RF3_Proc}, + {"ATEWRF4", Set_ATE_Write_RF4_Proc}, +#endif /* (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) */ + {"ATELDE2P", Set_ATE_Load_E2P_Proc}, +#ifdef RTMP_EFUSE_SUPPORT + {"ATELDE2PFROMBUF", Set_ATE_Load_E2P_From_Buf_Proc}, +#endif /* RTMP_EFUSE_SUPPORT */ + {"ATERE2P", Set_ATE_Read_E2P_Proc}, +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUUPORT */ +#ifdef SINGLE_SKU_V2 + {"ATESINGLESKU", Set_ATE_SINGLE_SKU_Proc}, +#endif + {"ATEAUTOALC", Set_ATE_AUTO_ALC_Proc}, + {"ATEIPG", Set_ATE_IPG_Proc}, + {"ATEPAYLOAD", Set_ATE_Payload_Proc}, + {"ATEFIXEDPAYLOAD", Set_ATE_Fixed_Payload_Proc}, +#ifdef TXBF_SUPPORT + {"ATETXBF", Set_ATE_TXBF_Proc}, + {"ATETXSOUNDING", Set_ATE_TXSOUNDING_Proc}, + {"ATETXBFDIVCAL", Set_ATE_TXBF_DIVCAL_Proc}, + {"ATETXBFLNACAL", Set_ATE_TXBF_LNACAL_Proc}, + {"ATETxBfGolden", Set_ATE_TXBF_GOLDEN_Proc}, +#endif /* TXBF_SUPPORT */ + {"ATESHOW", Set_ATE_Show_Proc}, + {"ATEHELP", Set_ATE_Help_Proc}, + +#ifdef RALINK_QA + {"TxStop", Set_TxStop_Proc}, + {"RxStop", Set_RxStop_Proc}, +#endif /* RALINK_QA */ + +#ifdef MT76x2 + {"ATEDOCAL", Set_ATE_DO_CALIBRATION_Proc}, + {"ATELoadCR", Set_ATE_Load_CR_Proc}, +#endif /* MT76x2 */ +#endif /* RALINK_ATE */ + +#ifdef WPA_SUPPLICANT_SUPPORT + {"WpaSupport", Set_Wpa_Support}, +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + {"WscUuidE", Set_WscUUIDE_Proc}, + {"WscGetConf", Set_WscGetConf_Proc}, + {"WscVendorPinCode", Set_WscVendorPinCode_Proc}, +#ifdef WSC_V2_SUPPORT + {"WscForceSetAP", Set_WscForceSetAP_Proc}, +#endif /* WSC_V2_SUPPORT */ +#ifdef IWSC_SUPPORT + {"IWscLimitedUI", Set_IWscLimitedUI_Proc}, +#ifdef IWSC_TEST_SUPPORT + {"IWscDefaultSecurity", Set_IWscDefaultSecurity_Proc}, + {"IWscSmpbcScanOnly", Set_IWscSmpbcEnrScanOnly_Proc}, + {"IWscEmptySubmaskList", Set_IWscEmptySubmaskList_Proc}, + {"IWscBlockConnection", Set_IWscBlockConnection_Proc}, +#endif /* IWSC_TEST_SUPPORT */ + {"IWscOOB", Set_IWscOOB_Proc}, + {"IWscSinglePIN", Set_IWscSinglePIN_Proc}, +#endif // IWSC_SUPPORT // +#endif /* WSC_STA_SUPPORT */ + +#ifdef ETH_CONVERT_SUPPORT + {"EthConvertMode", Set_EthConvertMode_Proc}, + {"EthCloneMac", Set_EthCloneMac_Proc}, +#endif /* ETH_CONVERT_SUPPORT */ + + +#ifdef DOT11R_FT_SUPPORT + {"ft", FT_Ioctl}, +#endif /* DOT11R_FT_SUPPORT */ + + {"FixedTxMode", Set_FixedTxMode_Proc}, +#ifdef CONFIG_APSTA_MIXED_SUPPORT + {"OpMode", Set_OpMode_Proc}, +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#ifdef ETH_CONVERT_SUPPORT + {"FragFlag", Set_FragTest_Proc}, +#endif /* ETH_CONVERT_SUPPORT */ +#ifdef DOT11_N_SUPPORT + {"TGnWifiTest", Set_TGnWifiTest_Proc}, +#endif /* DOT11_N_SUPPORT */ +#ifdef QOS_DLS_SUPPORT + {"DlsAddEntry", Set_DlsAddEntry_Proc}, + {"DlsTearDownEntry", Set_DlsTearDownEntry_Proc}, +#endif /* QOS_DLS_SUPPORT */ + {"LongRetry", Set_LongRetryLimit_Proc}, + {"ShortRetry", Set_ShortRetryLimit_Proc}, + {"AutoFallBack", Set_AutoFallBack_Proc}, +#ifdef EXT_BUILD_CHANNEL_LIST + {"11dClientMode", Set_Ieee80211dClientMode_Proc}, + {"CountryCode", Set_ExtCountryCode_Proc}, + {"DfsType", Set_ExtDfsType_Proc}, + {"ChannelListAdd", Set_ChannelListAdd_Proc}, + {"ChannelListShow", Set_ChannelListShow_Proc}, + {"ChannelListDel", Set_ChannelListDel_Proc}, +#endif /* EXT_BUILD_CHANNEL_LIST */ +#ifdef CARRIER_DETECTION_SUPPORT + {"CarrierDetect", Set_StaCarrierDetect_Proc}, +#endif /* CARRIER_DETECTION_SUPPORT */ + + +#ifdef RTMP_EFUSE_SUPPORT + {"efuseLoadFromBin", set_eFuseLoadFromBin_Proc}, /* For backward compatible, the usage is the same as bufferLoadFromBin + bufferWriteBack */ + {"efuseFreeNumber", set_eFuseGetFreeBlockCount_Proc}, + {"efuseDump", set_eFusedump_Proc}, +#ifdef RALINK_ATE + {"bufferLoadFromEfuse", Set_LoadEepromBufferFromEfuse_Proc}, + {"efuseBufferModeWriteBack", set_eFuseBufferModeWriteBack_Proc}, /* For backward compatible, the usage is the same as bufferWriteBack */ +#endif /* RALINK_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ + {"bufferLoadFromBin", Set_LoadEepromBufferFromBin_Proc}, + {"bufferWriteBack", Set_EepromBufferWriteBack_Proc}, + + + +#ifdef DOT11R_FT_SUPPORT + {"FtApBssid", Set_FtApBssid_Proc}, + {"FtSupport", Set_FtSupport_Proc}, +#endif /* DOT11R_FT_SUPPORT */ + {"BeaconLostTime", Set_BeaconLostTime_Proc}, + {"AutoRoaming", Set_AutoRoaming_Proc}, + {"SiteSurvey", Set_SiteSurvey_Proc}, + {"ForceTxBurst", Set_ForceTxBurst_Proc}, + +#ifdef RTMP_RBUS_SUPPORT +#ifdef LED_CONTROL_SUPPORT + {"WlanLed", Set_WlanLed_Proc}, +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + {"TdlsCapable", Set_TdlsCapable_Proc}, + {"TdlsSetup", Set_TdlsSetup_Proc}, + {"TdlsTearDown", Set_TdlsTearDown_Proc}, + {"TdlsDiscoveryReq", Set_TdlsDiscoveryReq_Proc}, + {"TdlsTPKLifeTime", Set_TdlsTPKLifeTime_Proc}, +#ifdef WFD_SUPPORT + {"TdlsTunneledReq", Set_TdlsTunneledReqProc}, +#endif /* WFD_SUPPORT */ + {"TdlsAcceptWeakSec", Set_TdlsAcceptWeakSecurityProc}, + {"TdlsChannelSwitch", Set_TdlsChannelSwitch_Proc}, + {"TdlsChannelSwitchBW", Set_TdlsChannelSwitchBW_Proc}, + {"TdlsChannelSwitchDisable", Set_TdlsChannelSwitchDisable_Proc}, +#ifdef TDLS_AUTOLINK_SUPPORT + {"TdlsAutoLink", Set_TdlsAutoLinkProc}, + {"TdlsRssiMeasurementPeriod", Set_TdlsRssiMeasurementPeriodProc}, + {"TdlsAutoDiscoveryPeriod", Set_TdlsAutoDiscoveryPeriodProc}, + {"TdlsAutoSetupRssiThreshold", Set_TdlsAutoSetupRssiThresholdProc}, + {"TdlsDisabledPeriodByTeardown", Set_TdlsDisabledPeriodByTeardownProc}, + {"TdlsAutoTeardownRssiThreshold", Set_TdlsAutoTeardownRssiThresholdProc}, +#endif // TDLS_AUTOLINK_SUPPORT // +#ifdef UAPSD_SUPPORT + {"tdls", TDLS_Ioctl}, +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ +#ifdef XLINK_SUPPORT + {"XlinkMode", Set_XlinkMode_Proc}, +#endif /* XLINK_SUPPORT */ + + + {"AutoReconnect", Set_AutoReconnect_Proc}, + {"AdhocN", Set_AdhocN_Proc}, +#ifdef AGS_SUPPORT + {"Ags", Show_AGS_Proc}, +#endif /* AGS_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) + {"wow_enable", Set_WOW_Enable}, + {"wow_gpio", Set_WOW_GPIO}, + {"wow_delay", Set_WOW_Delay}, + {"wow_hold", Set_WOW_Hold}, + {"wow_inband", Set_WOW_InBand}, +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + + {"VcoPeriod", Set_VcoPeriod_Proc}, +#ifdef CONFIG_SNIFFER_SUPPORT + {"MonitorMode", Set_MonitorMode_Proc}, +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef WFD_SUPPORT + {"WfdEnable", Set_WfdEnable_Proc}, +#ifdef RT_CFG80211_SUPPORT + {"WfdInsertIe", Set_WfdInsertIe_Proc}, +#endif /* RT_CFG80211_SUPPORT */ + {"WfdDevType", Set_WfdDeviceType_Proc}, + {"WfdCouple", Set_WfdCouple_Proc}, + {"WfdSessionAvail", Set_WfdSessionAvailable_Proc}, + {"WfdCP", Set_WfdCP_Proc}, + {"WfdRtspPort", Set_WfdRtspPort_Proc}, + {"WfdMaxThroughput", Set_WfdMaxThroughput_Proc}, + {"WfdLocalIp", Set_WfdLocalIp_Proc}, + {"WfdPeerRtspPort", Set_PeerRtspPort_Proc}, +#endif /* WFD_SUPPORT */ + +#ifdef SINGLE_SKU + {"ModuleTxpower", Set_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ + +#ifdef DOT11W_PMF_SUPPORT + {"PMFMFPC", Set_PMFMFPC_Proc}, + {"PMFMFPR", Set_PMFMFPR_Proc}, + {"PMFSHA256", Set_PMFSHA256_Proc}, +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + {"fpga_on", set_fpga_mode}, + {"dataphy", set_data_phy_mode}, + {"databw", set_data_bw}, + {"dataldpc", set_data_ldpc}, + {"datamcs", set_data_mcs}, + {"datagi", set_data_gi}, + {"databasize", set_data_basize}, + {"txcnt", set_tx_kickcnt}, +#endif /* CONFIG_FPGA_MODE */ + {"rf", set_rf}, +#ifdef DYNAMIC_VGA_SUPPORT + {"DyncVgaEnable", Set_DyncVgaEnable_Proc}, +#endif /* DYNAMIC_VGA_SUPPORT */ +#ifdef MICROWAVE_OVEN_SUPPORT + {"MO_FalseCCATh", Set_MO_FalseCCATh_Proc}, +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef ED_MONITOR + //let run-time turn on/off + {"ed_chk", set_ed_chk_proc}, + {"ed_current_rssi_th", set_ed_current_rssi_threhold_proc}, + {"ed_debug", set_ed_debug_proc}, + {"ed_th", set_ed_threshold}, + {"ed_false_cca_th", set_ed_false_cca_threshold}, + {"ed_blk_cnt", set_ed_block_tx_thresh}, + {"ed_stat", show_ed_stat_proc}, +#endif /* ED_MONITOR */ + {"ed_count_show", show_ed_cnt_for_channel_quality}, + +#ifdef CONFIG_SNIFFER_SUPPORT + {"mc", set_monitor_channel}, +#endif + {"tssi_enable", set_tssi_enable}, +#ifdef CONFIG_WIFI_TEST + {"pbf_loopback", set_pbf_loopback}, + {"pbf_rx_drop", set_pbf_rx_drop}, +#endif + {"fw_debug", set_fw_debug}, +#ifdef RT_CFG80211_SUPPORT + {"DisableCfg2040Scan", Set_DisableCfg2040Scan_Proc}, +#endif + {NULL,} +}; + + +INT RTMPSTAPrivIoctlSet( + IN RTMP_ADAPTER *pAd, + IN PSTRING SetProcName, + IN PSTRING ProcArg) +{ + int ret = 0; + + for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) + { + if (strcmp(SetProcName, PRTMP_PRIVATE_SET_PROC->name) == 0) + { + if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAd, ProcArg)) + { /*FALSE:Set private failed then return Invalid argument */ + return NDIS_STATUS_FAILURE; + } + break; /*Exit for loop. */ + } + } + + if(PRTMP_PRIVATE_SET_PROC->name == NULL) + { /*Not found argument */ + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", SetProcName, ProcArg)); + return -EINVAL; + + } + + return ret; +} + + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_SSID_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + NDIS_802_11_SSID Ssid, *pSsid=NULL; + BOOLEAN StateMachineTouched = FALSE; + int success = TRUE; + + + /* + Set the AutoReconnectSsid to prevent it reconnect to old SSID + Since calling this indicate user don't want to connect to that SSID anymore. + */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + if( strlen(arg) <= MAX_LEN_OF_SSID) + { + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + if (strlen(arg) != 0) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + else /*ANY ssid */ + { + Ssid.SsidLength = 0; + memcpy(Ssid.Ssid, "", 0); + pAd->StaCfg.BssType = BSS_INFRA; + pAd->StaCfg.wdev.AuthMode = Ndis802_11AuthModeOpen; + pAd->StaCfg.wdev.WepStatus = Ndis802_11EncryptionDisabled; + } + pSsid = &Ssid; + + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + if ((pAd->StaCfg.WpaPassPhraseLen >= 8) && + (pAd->StaCfg.WpaPassPhraseLen <= 64)) + { + UCHAR keyMaterial[40]; + + RTMPZeroMemory(pAd->StaCfg.PMK, 32); + if (pAd->StaCfg.WpaPassPhraseLen == 64) + { + AtoH((PSTRING) pAd->StaCfg.WpaPassPhrase, pAd->StaCfg.PMK, 32); + } + else + { + RtmpPasswordHash((PSTRING) pAd->StaCfg.WpaPassPhrase, Ssid.Ssid, Ssid.SsidLength, keyMaterial); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + } + } + + /* Record the desired user settings to MlmeAux */ + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid.Ssid, Ssid.SsidLength); + pAd->MlmeAux.SsidLen = (UCHAR)Ssid.SsidLength; + + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, Ssid.Ssid, Ssid.SsidLength); + pAd->MlmeAux.AutoReconnectSsidLen = (UCHAR)Ssid.SsidLength; + + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + pAd->StaCfg.bSkipAutoScanConn = FALSE; + pAd->bConfigChanged = TRUE; + pAd->StaCfg.bNotFirstScan = FALSE; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)pSsid, 0); + + StateMachineTouched = TRUE; + if (Ssid.SsidLength == MAX_LEN_OF_SSID) + hex_dump("Set_SSID_Proc::Ssid", Ssid.Ssid, Ssid.SsidLength); + else + DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); + } + else + success = FALSE; + + if (StateMachineTouched) /* Upper layer sent a MLME-related operations */ + RTMP_MLME_HANDLER(pAd); + + return success; +} + + +/* + ========================================================================== + Description: + Set WmmCapable Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bWmmCapable; + + bWmmCapable = simple_strtol(arg, 0, 10); + + if ((bWmmCapable == 1) + ) + pAd->CommonCfg.bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->CommonCfg.bWmmCapable = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n", + pAd->CommonCfg.bWmmCapable)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Network Type(Infrastructure/Adhoc mode) + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 Value = 0; + + if (strcmp(arg, "Adhoc") == 0) + { + if (pAd->StaCfg.BssType != BSS_ADHOC) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + if (MONITOR_ON(pAd)) + { + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAd, FALSE); + } + if (INFRA_ON(pAd)) + { + /*BOOLEAN Cancelled; */ + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAd, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n")); + } +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + pAd->StaCfg.BssType = BSS_ADHOC; + RTMP_OS_NETDEV_SET_TYPE(pAd->net_dev, pAd->StaCfg.OriDevType); + + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n")); + } + else if (strcmp(arg, "Infra") == 0) + { + if (pAd->StaCfg.BssType != BSS_INFRA) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + if (MONITOR_ON(pAd)) + { + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAd, FALSE); + } + if (ADHOC_ON(pAd)) + { + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAd, FALSE); + } +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + pAd->StaCfg.BssType = BSS_INFRA; + RTMP_OS_NETDEV_SET_TYPE(pAd->net_dev, pAd->StaCfg.OriDevType); + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n")); + } +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + /* + Monitor2 is for 3593 11n wireshark sniffer tool. + The name, Monitor2, follows the command format in RT2883. + */ + else if ((strcmp(arg, "Monitor") == 0) || (strcmp(arg, "Monitor2") == 0)) +#else + else if (strcmp(arg, "Monitor") == 0) +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + { + BCN_TIME_CFG_STRUC csr; + UCHAR rf_channel; + UINT8 rf_bw, ext_ch; + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + if (strcmp(arg, "Monitor2") == 0) + pAd->StaCfg.BssMonitorFlag |= MONITOR_FLAG_11N_SNIFFER; +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + /* disable all periodic state machine */ + pAd->StaCfg.bAutoReconnect = FALSE; + /* reset all mlme state machine */ + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n")); + if (pAd->CommonCfg.CentralChannel == 0) + { +#ifdef DOT11_N_SUPPORT + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_A | WMODE_AN)) + pAd->CommonCfg.CentralChannel = 36; + else +#endif /* DOT11_N_SUPPORT */ + pAd->CommonCfg.CentralChannel = 6; + } +#ifdef DOT11_N_SUPPORT + else + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + + /* same procedure with window driver */ +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + /* 40MHz ,control channel at lower */ + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + ext_ch = EXTCHA_ABOVE; + rf_bw = BW_40; + rf_channel = pAd->CommonCfg.CentralChannel; + } + else if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) + { + /* 40MHz ,control channel at upper */ + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + ext_ch = EXTCHA_BELOW; + rf_bw = BW_40; + rf_channel = pAd->CommonCfg.CentralChannel; + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* 20MHz */ + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + rf_channel = pAd->CommonCfg.Channel; + } + + AsicSetChannel(pAd, rf_channel, rf_bw, ext_ch, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s():BW_%s, CtrlChannel(%d), CentralChannel(%d) \n", + __FUNCTION__, (rf_bw == BW_40 ? "40" : "20"), + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + + + /* Enable Rx with promiscuous reception */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x3); + /* ASIC supporsts sniffer function with replacing RSSI with timestamp. */ + /*RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); */ + /*Value |= (0x80); */ + /*RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); */ + + /* disable sync */ + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + + pAd->StaCfg.BssType = BSS_MONITOR; + RTMP_OS_NETDEV_SET_TYPE_MONITOR(pAd->net_dev); + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n")); + } + + /* Set Rx Filter after eaxctly know what mode currently we work on */ + AsicSetRxFilter(pAd); + + /* Reset Ralink supplicant to not use, it will be set to start when UI set PMK key */ + pAd->StaCfg.WpaState = SS_NOTUSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAd->StaCfg.BssType)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (rtstrcasecmp(arg, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(arg, "OPEN") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOpen; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (rtstrcasecmp(arg, "WPANONE") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPANone; + else if ((rtstrcasecmp(arg, "WPA2PSK") == TRUE) || (rtstrcasecmp(arg, "WPAPSKWPA2PSK") == TRUE)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if (rtstrcasecmp(arg, "WPA") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if (rtstrcasecmp(arg, "WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WAPI_SUPPORT + else if (rtstrcasecmp(arg, "WAICERT") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWAICERT; + else if (rtstrcasecmp(arg, "WAIPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + return FALSE; + + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", wdev->AuthMode)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_EncrypType_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (rtstrcasecmp(arg, "NONE") == TRUE) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if (rtstrcasecmp(arg, "WEP") == TRUE) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11WEPEnabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if (rtstrcasecmp(arg, "TKIP") == TRUE) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11TKIPEnable; + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + pAd->StaCfg.GroupCipher = Ndis802_11TKIPEnable; + } + else if (rtstrcasecmp(arg, "AES") == TRUE) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11AESEnable; + pAd->StaCfg.PairCipher = Ndis802_11AESEnable; + pAd->StaCfg.GroupCipher = Ndis802_11AESEnable; + } +#ifdef WAPI_SUPPORT + else if (rtstrcasecmp(arg, "SMS4") == TRUE) + { + if ((wdev->AuthMode != Ndis802_11AuthModeWAICERT) && + (wdev->AuthMode != Ndis802_11AuthModeWAIPSK)) + return TRUE; /* do nothing */ + + wdev->WepStatus = Ndis802_11EncryptionSMS4Enabled; + pAd->StaCfg.PairCipher = Ndis802_11EncryptionSMS4Enabled; + pAd->StaCfg.GroupCipher = Ndis802_11EncryptionSMS4Enabled; + } +#endif /* WAPI_SUPPORT */ + else + return FALSE; + + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + /* Build all corresponding channel information */ + RTMPSetPhyMode(pAd, pAd->CommonCfg.cfg_wmode); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", wdev->WepStatus)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + ULONG KeyIdx; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAdapter->StaCfg.wdev.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.wdev.DefaultKeyId)); + + return TRUE; +} + +INT Set_Wep_Key_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING Key, + IN INT KeyLen, + IN INT KeyId) +{ + int i; + UCHAR CipherAlg = CIPHER_WEP64; + struct wifi_dev *wdev = &pAdapter->StaCfg.wdev; + + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + if ((KeyId < 0) || (KeyId > 3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_Wep_Key_Proc::Invalid KeyId (=%d)\n", KeyId)); + return FALSE; + } + + switch (KeyLen) + { + case 5: /* wep 40 Ascii type */ + pAdapter->SharedKey[BSS0][KeyId].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][KeyId].Key, Key, KeyLen); + CipherAlg = CIPHER_WEP64; + break; + + case 10: /* wep 40 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(Key+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][KeyId].KeyLen = KeyLen / 2 ; + AtoH(Key, pAdapter->SharedKey[BSS0][KeyId].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + break; + + case 13: /* wep 104 Ascii type */ + pAdapter->SharedKey[BSS0][KeyId].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][KeyId].Key, Key, KeyLen); + CipherAlg = CIPHER_WEP128; + break; + + case 26: /* wep 104 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(Key+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][KeyId].KeyLen = KeyLen / 2 ; + AtoH(Key, pAdapter->SharedKey[BSS0][KeyId].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + break; + + default: /* Invalid argument */ + DBGPRINT(RT_DEBUG_ERROR, ("Set_Wep_Key_Proc::Invalid argument (=%s)\n", Key)); + return FALSE; + } + + pAdapter->SharedKey[BSS0][KeyId].CipherAlg = CipherAlg; + + /* Set keys (into ASIC) */ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 0, + &pAdapter->SharedKey[BSS0][KeyId]); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WEP KEY1 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: /*wep 40 Ascii type */ + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: /*wep 40 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); + break; + case 13: /*wep 104 Ascii type */ + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: /*wep 104 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); + break; + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + + pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg; + + /* Set keys (into ASIC) */ + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 0, + &pAdapter->SharedKey[BSS0][0]); + } + + return TRUE; +} +/* + ========================================================================== + + Description: + Set WEP KEY2 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: /*wep 40 Ascii type */ + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: /*wep 40 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); + break; + case 13: /*wep 104 Ascii type */ + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: /*wep 104 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); + break; + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg; + + /* Set keys (into ASIC) */ + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 1, + &pAdapter->SharedKey[BSS0][1]); + } + + return TRUE; +} +/* + ========================================================================== + Description: + Set WEP KEY3 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: /*wep 40 Ascii type */ + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); + break; + case 10: /*wep 40 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); + break; + case 13: /*wep 104 Ascii type */ + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); + break; + case 26: /*wep 104 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); + break; + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg; + + /* Set keys (into ASIC) */ + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 2, + &pAdapter->SharedKey[BSS0][2]); + } + + return TRUE; +} +/* + ========================================================================== + Description: + Set WEP KEY4 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: /*wep 40 Ascii type */ + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: /*wep 40 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); + break; + case 13: /*wep 104 Ascii type */ + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: /*wep 104 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); + break; + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg; + + /* Set keys (into ASIC) */ + if (pAdapter->StaCfg.wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 3, + &pAdapter->SharedKey[BSS0][3]); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA PSK key + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WPAPSK_Proc(RTMP_ADAPTER *pAd, PSTRING arg) +{ + int status; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + + if ((wdev->AuthMode != Ndis802_11AuthModeWPAPSK) && + (wdev->AuthMode != Ndis802_11AuthModeWPA2PSK) && + (wdev->AuthMode != Ndis802_11AuthModeWPANone) +#ifdef WAPI_SUPPORT + && (wdev->AuthMode != Ndis802_11AuthModeWAICERT) + && (wdev->AuthMode != Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) + return TRUE; /* do nothing */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); + + status = RT_CfgSetWPAPSKKey(pAd, arg, strlen(arg), pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, pAd->StaCfg.PMK); + if (status == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc(): Set key failed!\n")); + return FALSE; + } + NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + NdisMoveMemory(pAd->StaCfg.WpaPassPhrase, arg, strlen(arg)); + pAd->StaCfg.WpaPassPhraseLen = (UINT)strlen(arg); + +#ifdef WSC_STA_SUPPORT + NdisZeroMemory(pAd->StaCfg.WscControl.WpaPsk, 64); + pAd->StaCfg.WscControl.WpaPskLen = 0; + NdisMoveMemory(pAd->StaCfg.WscControl.WpaPsk, arg, strlen(arg)); + pAd->StaCfg.WscControl.WpaPskLen = (INT)strlen(arg); +#endif /* WSC_STA_SUPPORT */ + +#ifdef WAPI_SUPPORT + NdisZeroMemory(pAd->StaCfg.WAPIPassPhrase, 64); + pAd->StaCfg.WAPIPassPhraseLen = 0; + NdisMoveMemory(pAd->StaCfg.WAPIPassPhrase, arg, strlen(arg)); + pAd->StaCfg.WAPIPassPhraseLen = (UINT)strlen(arg); +#endif /* WAPI_SUPPORT */ + + if(pAd->StaCfg.BssType == BSS_ADHOC && + wdev->AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->StaCfg.WpaState = SS_NOTUSE; + } + else + { + /* Start STA supplicant state machine */ + pAd->StaCfg.WpaState = SS_START; + } + + return TRUE; +} + + + +/* + ========================================================================== + Description: + Set Power Saving mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PSMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + if (pAdapter->StaCfg.BssType == BSS_INFRA) + { + if ((strcmp(arg, "Max_PSP") == 0) || + (strcmp(arg, "max_psp") == 0) || + (strcmp(arg, "MAX_PSP") == 0)) + { + /* do NOT turn on PSM bit here, wait until MlmeCheckPsmChange() */ + /* to exclude certain situations. */ + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + pAdapter->StaCfg.DefaultListenCount = 5; + + } + else if ((strcmp(arg, "Fast_PSP") == 0) || + (strcmp(arg, "fast_psp") == 0) || + (strcmp(arg, "FAST_PSP") == 0)) + { + /* do NOT turn on PSM bit here, wait until MlmeCheckPsmChange() */ + /* to exclude certain situations. */ + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; + pAdapter->StaCfg.DefaultListenCount = 3; + } + else if ((strcmp(arg, "Legacy_PSP") == 0) || + (strcmp(arg, "legacy_psp") == 0) || + (strcmp(arg, "LEGACY_PSP") == 0)) + { + /* do NOT turn on PSM bit here, wait until MlmeCheckPsmChange() */ + /* to exclude certain situations. */ + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAdapter->StaCfg.DefaultListenCount = 3; +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + pAdapter->StaCfg.DefaultListenCount = 1; +#endif // defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) // + } + else + { + /*Default Ndis802_11PowerModeCAM */ + /* clear PSM bit immediately */ + RTMP_SET_PSM_BIT(pAdapter, PWR_ACTIVE); + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode)); + } + else + return FALSE; + + + return TRUE; +} + +#ifdef WPA_SUPPLICANT_SUPPORT +/* + ========================================================================== + Description: + Set WpaSupport flag. + Value: + 0: Driver ignore wpa_supplicant. + 1: wpa_supplicant initiates scanning and AP selection. + 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + if ( simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + else if ( simple_strtol(arg, 0, 10) == 1) + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + else if ( simple_strtol(arg, 0, 10) == 2) + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; + else + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP)); + + return TRUE; +} +#endif /* WPA_SUPPLICANT_SUPPORT */ + + +#ifdef WSC_STA_SUPPORT +#define WSC_GET_CONF_MODE_EAP 1 +#define WSC_GET_CONF_MODE_UPNP 2 +INT Set_WscConfMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + pWscControl = &pAd->StaCfg.WscControl; + + if ( simple_strtol(arg, 0, 10) == 0) + pWscControl->WscConfMode = WSC_DISABLE; + else if ( simple_strtol(arg, 0, 10) == 1) + pWscControl->WscConfMode = WSC_ENROLLEE; + else if ( simple_strtol(arg, 0, 10) == 2) + pWscControl->WscConfMode = WSC_REGISTRAR; + else + pWscControl->WscConfMode = WSC_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra0) Set_WscConfMode_Proc::(WscConfMode(0,1,2)=%d)\n", pWscControl->WscConfMode)); + +#ifdef IWSC_SUPPORT +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + pIWscInfo->IWscConfMode = WSC_DISABLE; + if ( simple_strtol(arg, 0, 10) == 1) + pIWscInfo->IWscConfMode = WSC_ENROLLEE; + else if ( simple_strtol(arg, 0, 10) == 2) + pIWscInfo->IWscConfMode = WSC_REGISTRAR; + else + return FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra0) Set_WscConfMode_Proc::(IWscConfMode=%d)\n", pIWscInfo->IWscConfMode)); + } +#endif /* IWSC_TEST_SUPPORT */ +#endif /* IWSC_SUPPORT */ + + return TRUE; +} + +INT Set_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR IsAPConfigured = 1; + + IsAPConfigured = (UCHAR)simple_strtol(arg, 0, 10); + + if ((IsAPConfigured > 0) && (IsAPConfigured <= 2)) + pAd->StaCfg.WscControl.WscConfStatus = IsAPConfigured; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscConfStatus_Proc:: Set failed!!(WscConfStatus=%s), WscConfStatus is 1 or 2 \n", arg)); + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscConfStatus_Proc:: WscConfStatus is not changed (%d) \n", pAd->StaCfg.WscControl.WscConfStatus)); + return FALSE; /*Invalid argument */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscConfStatus_Proc::(WscConfStatus=%d)\n", pAd->StaCfg.WscControl.WscConfStatus)); + + return TRUE; +} + +INT Set_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + ULONG ApIdx = 0; + + pWscControl = &pAd->StaCfg.WscControl; + + NdisZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + + if( (strlen(arg) > 0) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + NdisMoveMemory(pWscControl->WscSsid.Ssid, arg, strlen(arg)); + pWscControl->WscSsid.SsidLength = strlen(arg); + + //add SSID into pAd->MlmeAux.Ssid + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, arg, strlen(arg)); + pAd->MlmeAux.SsidLen = strlen(arg); + + NdisZeroMemory(pWscControl->WscBssid, MAC_ADDR_LEN); + ApIdx = WscSearchWpsApBySSID(pAd, + pWscControl->WscSsid.Ssid, + pWscControl->WscSsid.SsidLength, + WSC_PIN_MODE); + if (ApIdx != BSS_NOT_FOUND) + { + NdisMoveMemory(pWscControl->WscBssid, pAd->ScanTab.BssEntry[ApIdx].Bssid,MAC_ADDR_LEN); + pAd->MlmeAux.Channel = pAd->ScanTab.BssEntry[ApIdx].Channel; + } + + hex_dump("Set_WscSsid_Proc:: WscBssid", pWscControl->WscBssid, MAC_ADDR_LEN); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscSsid_Proc:: (Select SsidLen=%d,Ssid=%s)\n", + pWscControl->WscSsid.SsidLength, pWscControl->WscSsid.Ssid)); + } + else + return FALSE; /*Invalid argument */ + + return TRUE; + +} + + +INT Set_WscBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR MacAddr[MAC_ADDR_LEN]; + + if (rtstrmactohex(arg, (PSTRING) &MacAddr[0]) == FALSE) + return FALSE; + + RTMPZeroMemory(pAd->StaCfg.WscControl.WscBssid, MAC_ADDR_LEN); + RTMPMoveMemory(pAd->StaCfg.WscControl.WscBssid, MacAddr, MAC_ADDR_LEN); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscBssid_Proc:: %02x:%02x:%02x:%02x:%02x:%02x\n", + MacAddr[0], MacAddr[1], MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5])); + + return TRUE; +} + +INT Set_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT WscMode; + PWSC_CTRL pWscControl; + pWscControl = &pAd->StaCfg.WscControl; + + WscMode = (INT)simple_strtol(arg, 0, 10); + + if ((WscMode == WSC_SMPBC_MODE) && + (pAd->StaCfg.BssType == BSS_INFRA)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc:: Set failed!!(Set_WscMode_Proc=%s)\n", arg)); + return FALSE; /*Invalid argument */ + } + + if ((WscMode == WSC_PIN_MODE ) || + (WscMode == WSC_PBC_MODE) || + (WscMode == WSC_SMPBC_MODE)) + { + /* save wsc mode */ + pWscControl->WscMode = WscMode; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc:: Set failed!!(Set_WscMode_Proc=%s)\n", arg)); + return FALSE; /*Invalid argument */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc::(WscMode=%d)\n", pWscControl->WscMode)); + + return TRUE; +} + +INT Set_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + BOOLEAN validatePin; + UINT PinCode = 0; + + pWscControl = &pAd->StaCfg.WscControl; + + PinCode = simple_strtol(arg, 0, 10); /* When PinCode is 03571361, return value is 3571361. */ + if ( strlen(arg) == 4 ) + validatePin = TRUE; + else + validatePin = ValidateChecksum(PinCode); + if (validatePin) + { + if (pWscControl->WscRejectSamePinFromEnrollee && + (PinCode == pWscControl->WscLastPinFromEnrollee)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PIN authentication or communication error occurs!!\n" + "Registrar does NOT accept the same PIN again!(PIN:%08u)\n", PinCode)); + return FALSE; + } + else + { + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + pWscControl->WscPinCode = PinCode; + pWscControl->WscLastPinFromEnrollee = pWscControl->WscPinCode; + if ( strlen(arg) == 4) + { + pWscControl->WscPinCodeLen = 4; + } + else + { + pWscControl->WscPinCodeLen = 8; + } + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pWscControl->bWscTrigger == TRUE)) + { + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_PEER_PIN, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } +#endif /* IWSC_SUPPORT */ + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscPinCode_Proc:: Checksum is invalid\n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra0) Set_WscPinCode_Proc::(PinCode=%d)\n", pWscControl->WscPinCode)); + + return TRUE; +} + +INT Set_WscUUIDE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + int i,UUIDLen; + UCHAR tmp_Uuid_Str[UUID_LEN_STR]; + UCHAR Wsc_Uuid_E[UUID_LEN_HEX]; + UCHAR uuidTmpStr[UUID_LEN_STR+2]; + WSC_UUID_T uuid_t; + + UUIDLen = strlen(arg); + if ( UUIDLen != 32) + { + DBGPRINT(RT_DEBUG_ERROR,("Length of UUID key is wrong length=%d\n",UUIDLen)); + return FALSE; + } + NdisMoveMemory(tmp_Uuid_Str, arg, UUIDLen); + pWscControl = &pAd->StaCfg.WscControl; + + for(i=0; i < UUIDLen; i++) + { + if( !isxdigit(tmp_Uuid_Str[i]) ) + { + DBGPRINT(RT_DEBUG_ERROR,("Input %d not Hex Value\n",i)); + return FALSE; //Not Hex value; + } + } + AtoH(tmp_Uuid_Str, Wsc_Uuid_E, UUID_LEN_HEX); + NdisMoveMemory(&uuid_t, Wsc_Uuid_E, UUID_LEN_HEX); + NdisZeroMemory(uuidTmpStr, sizeof(uuidTmpStr)); + sprintf(uuidTmpStr, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (unsigned int)uuid_t.timeLow, uuid_t.timeMid, uuid_t.timeHi_Version, uuid_t.clockSeqHi_Var, uuid_t.clockSeqLow, + uuid_t.node[0], uuid_t.node[1], uuid_t.node[2], uuid_t.node[3], uuid_t.node[4], uuid_t.node[5]); + + if (strlen(uuidTmpStr) > UUID_LEN_STR) + DBGPRINT(RT_DEBUG_ERROR, ("ERROR:UUID String size too large!\n")); + + strncpy((PSTRING)pWscControl->Wsc_Uuid_Str, uuidTmpStr, UUID_LEN_STR); + NdisMoveMemory(&pWscControl->Wsc_Uuid_E[0], Wsc_Uuid_E, UUID_LEN_HEX); + + DBGPRINT(RT_DEBUG_TRACE, ("The UUID Hex string is:")); + for (i=0; i< 16; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%02x", (pWscControl->Wsc_Uuid_E[i] & 0xff))); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + DBGPRINT(RT_DEBUG_TRACE, ("The UUID ASCII string is:%s!\n", pWscControl->Wsc_Uuid_Str)); + return 0; +} + +INT Set_WscGetConf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo; + INT idx; + BOOLEAN StateMachineTouched = FALSE; + +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ + +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + if (pAd->StaCfg.WscControl.bWscTrigger) + IWSC_Stop(pAd, TRUE); + else + IWSC_Stop(pAd, FALSE); + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + (pAd->StaCfg.IWscInfo.IpMethod == IWSC_IPV4_ASSIGNMENT) && + (pAd->StaCfg.IWscInfo.RegDepth != 0) && + (pAd->StaCfg.IWscInfo.AvaSubMaskListCount == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Empty Available IPv4 Submask List. Cannot be Registrar\n")); + pAd->StaCfg.WscControl.WscStatus = STATUS_WSC_EMPTY_IPV4_SUBMASK_LIST; + return TRUE; + } + MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_MLME_START, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + return TRUE; + } +#endif /* IWSC_SUPPORT */ + + pWscControl = &pAd->StaCfg.WscControl; + pWscUPnPNodeInfo = &pWscControl->WscUPnPNodeInfo; + + if (pWscControl->WscConfMode == WSC_DISABLE) + { + pWscControl->bWscTrigger = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGetConf_Proc: WPS is disabled.\n")); + return FALSE; + } + + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif /* CONFIG_AP_SUPPORT */ + pWscControl); + + /* trigger wsc re-generate public key */ + pWscControl->RegData.ReComputePke = 1; + + /* Change to init state before sending a disassociation frame */ + pAd->StaCfg.WscControl.WscState = WSC_STATE_INIT; + + /* 0. Send a disassoication frame */ + if (INFRA_ON(pAd)) + { + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + /* Set to immediately send the media disconnect event */ + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("disassociate with current AP before starting WPS\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + RTMP_MLME_HANDLER(pAd); + + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + pWscControl->bWscTrigger = FALSE; /* check to disable */ + OS_WAIT(500); /* leave enough time for this DISASSOC frame */ + } + else if (ADHOC_ON(pAd)) + { + USHORT TmpWscMode; + /* + Set the AutoReconnectSsid to prevent it reconnect to old SSID + Since calling this indicate user don't want to connect to that SSID anymore. + */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + if (pWscControl->WscMode == 1) + TmpWscMode = DEV_PASS_ID_PIN; + else + TmpWscMode = DEV_PASS_ID_PBC; + AsicDisableSync(pAd); + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, TRUE, TmpWscMode, pWscControl->WscConfigMethods, BSS0, NULL, 0, STA_MODE); + if (pWscControl->WscConfMode == WSC_REGISTRAR) + { + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_REGISTRAR, + pWscControl->WscConfStatus, + TRUE, + TmpWscMode, + pWscControl->WscConfigMethods, + BSS0, + NULL, + 0, + STA_MODE); + MakeIbssBeacon(pAd); + AsicEnableIbssSync(pAd); + } + else + { + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_ENROLLEE_INFO_ONLY, + pWscControl->WscConfStatus, + TRUE, + TmpWscMode, + pWscControl->WscConfigMethods, + BSS0, + NULL, + 0, + STA_MODE); + LinkDown(pAd, FALSE); + } + + } + + pWscControl->bWscTrigger = TRUE; + pWscControl->WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + + /* */ + /* Action : PIN, PBC */ + /* */ + if (pWscControl->WscMode == 1) + { + INT WaitCnt = 0; + /* PIN - default */ + + /* 2. Enqueue BSSID/SSID connection command */ + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + WscInitRegistrarPair(pAd, pWscControl, BSS0); + + /* + We need to make sure target AP is in the scan table. + */ + pAd->StaCfg.bSkipAutoScanConn = TRUE; + while ((ScanRunning(pAd) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); + + pAd->MlmeAux.AutoReconnectSsidLen= 0; + pAd->bConfigChanged = TRUE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + MAC_ADDR_LEN, + pAd->StaCfg.WscControl.WscBssid, 0); + pWscControl->WscState = WSC_STATE_START; + StateMachineTouched = TRUE; + + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + + /*WscSendUPnPConfReqMsg(pAd, apidx, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].Bssid, 3, 0); */ + } + else + { + if ((pAd->StaCfg.BssType == BSS_INFRA) || + (pWscControl->WscConfMode == WSC_ENROLLEE)) + { + pWscControl->WscSsid.SsidLength = 0; + NdisZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + RTMPZeroMemory(pWscControl->WscBssid, MAC_ADDR_LEN); + pWscControl->WscPBCBssCount = 0; + /* WPS - SW PBC */ + WscPushPBCAction(pAd, pWscControl); + StateMachineTouched = TRUE; + } + else + { + WscInitRegistrarPair(pAd, pWscControl, BSS0); + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->WscState = WSC_STATE_LINK_UP; + } + } + +#ifdef WSC_LED_SUPPORT +#ifdef CONFIG_WIFI_LED_SUPPORT + /* Change FW default mode to WPS LED share mode*/ + pAd->LedCntl.MCULedCntl.word &= 0x80; + pAd->LedCntl.MCULedCntl.word |= WPS_LED_MODE_SHARE; + + if (LED_MODE(pAd) == WPS_LED_MODE_SHARE) + { + WPSLEDStatus = LED_WPS_PRE_STAGE; + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_PREPOST_WIFI_LED_TIMEOUT); + } + else +#endif /* CONFIG_WIFI_LED_SUPPORT */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + + + /* Enrollee 192 random bytes for DH key generation */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + + if (pWscControl->WscProfileRetryTimerRunning) + { + BOOLEAN Cancelled; + pWscControl->WscProfileRetryTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscProfileRetryTimer, &Cancelled); + } + + if (StateMachineTouched) /* Upper layer sent a MLME-related operations */ + RTMP_MLME_HANDLER(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGetConf_Proc trigger WSC state machine\n")); + + return TRUE; +} + +#ifdef WSC_V2_SUPPORT +INT Set_WscForceSetAP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_V2_INFO pWscV2Info = &pAd->StaCfg.WscControl.WscV2Info; + + if (simple_strtol(arg, 0, 10) == 0) + pWscV2Info->bForceSetAP = FALSE; + else + pWscV2Info->bForceSetAP = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_WscForceSetAP_Proc::(bForceSetAP=%d)\n", pWscV2Info->bForceSetAP)); + return TRUE; +} +#endif /* WSC_V2_SUPPORT */ + + +#ifdef IWSC_SUPPORT +INT Set_IWscLimitedUI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + pWscControl = &pAd->StaCfg.WscControl; + + if ( simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.IWscInfo.bLimitedUI = FALSE; + else + pAd->StaCfg.IWscInfo.bLimitedUI = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_IWscLimitedUI_Proc::(bLimitedUI=%d)\n", pAd->StaCfg.IWscInfo.bLimitedUI)); + return TRUE; +} + +#ifdef IWSC_TEST_SUPPORT +INT Set_IWscDefaultSecurity_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + UINT8 TmpValue; + + pWscControl = &pAd->StaCfg.WscControl; + TmpValue = (UINT8)simple_strtol(arg, 0, 10); + if ((TmpValue != 0) && (TmpValue <= 3)) + { + pAd->StaCfg.IWscInfo.IWscDefaultSecurity = TmpValue; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(IWscDefaultSecurity=%d)\n", __FUNCTION__, pAd->StaCfg.IWscInfo.IWscDefaultSecurity)); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::(Value=%d)\n", __FUNCTION__, TmpValue)); + return FALSE; + } +} + +INT Set_IWscSmpbcEnrScanOnly_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PIWSC_INFO pIWscInfo; + + pIWscInfo = &pAd->StaCfg.IWscInfo; + if ( simple_strtol(arg, 0, 10) == 0) + pIWscInfo->bIwscSmpbcScanningOnly = FALSE; + else + pIWscInfo->bIwscSmpbcScanningOnly = TRUE; +} + +INT Set_IWscEmptySubmaskList_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PIWSC_INFO pIWscInfo; + + pIWscInfo = &pAd->StaCfg.IWscInfo; + if ( simple_strtol(arg, 0, 10) == 0) + pIWscInfo->bEmptySubmaskList = FALSE; + else + pIWscInfo->bEmptySubmaskList = TRUE; +} + +INT Set_IWscBlockConnection_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PIWSC_INFO pIWscInfo; + + pIWscInfo = &pAd->StaCfg.IWscInfo; + if ( simple_strtol(arg, 0, 10) == 0) + pIWscInfo->bBlockConnection = FALSE; + else + pIWscInfo->bBlockConnection = TRUE; + + if (pIWscInfo->bBlockConnection) + { + INT i; + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + } + + if (pAd->MacTab.Size == 0) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + } + } +} +#endif /* IWSC_TEST_SUPPORT */ + +INT Set_IWscOOB_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + NDIS_802_11_SSID Ssid; + USHORT WpaPskLen = 0; + + if (pAd->StaCfg.BssType != BSS_ADHOC) + { + if (INFRA_ON(pAd)) + { + /*BOOLEAN Cancelled; */ + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAd, FALSE); + } +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + pAd->StaCfg.BssType = BSS_ADHOC; + } + + pWscControl = &pAd->StaCfg.WscControl; + + pWscControl->WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + + pWscControl->WscConfMode = WSC_DISABLE; + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_IDLE; + pWscControl->bWscTrigger = FALSE; + NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE)); + sprintf(&Ssid.Ssid[0], "IWSC%02X%02X%02X", RandomByte(pAd), RandomByte(pAd), RandomByte(pAd)); + Ssid.SsidLength = strlen(&Ssid.Ssid[0]); + + WscGenRandomKey(pAd, pWscControl, pWscControl->WpaPsk, &WpaPskLen); + pWscControl->WpaPskLen = (INT)WpaPskLen; + NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + NdisMoveMemory(pAd->StaCfg.WpaPassPhrase, pWscControl->WpaPsk, pWscControl->WpaPskLen); + pAd->StaCfg.WpaPassPhraseLen = pWscControl->WpaPskLen; + pAd->StaCfg.wdev.AuthMode = Ndis802_11AuthModeWPA2PSK; + pAd->StaCfg.wdev.WepStatus = Ndis802_11AESEnable; + if ((pAd->StaCfg.WpaPassPhraseLen >= 8) && + (pAd->StaCfg.WpaPassPhraseLen <= 64)) + { + UCHAR keyMaterial[40]; + + RTMPZeroMemory(pAd->StaCfg.PMK, 32); + if (pAd->StaCfg.WpaPassPhraseLen == 64) + { + AtoH((PSTRING) pAd->StaCfg.WpaPassPhrase, pAd->StaCfg.PMK, 32); + } + else + { + RtmpPasswordHash((PSTRING) pAd->StaCfg.WpaPassPhrase, Ssid.Ssid, Ssid.SsidLength, keyMaterial); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + } + } + + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + pAd->bConfigChanged = TRUE; + pAd->StaCfg.IWscInfo.bDoNotChangeBSSID = FALSE; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)&Ssid, 0); + + RTMP_MLME_HANDLER(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_IWscOOB_Proc\n")); + return TRUE; +} + +INT Set_IWscSinglePIN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PWSC_CTRL pWscControl; + pWscControl = &pAd->StaCfg.WscControl; + + if ( simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.IWscInfo.bSinglePIN = FALSE; + else + pAd->StaCfg.IWscInfo.bSinglePIN = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_IWscSinglePIN_Proc::(bSinglePIN=%d)\n", pAd->StaCfg.IWscInfo.bSinglePIN)); + return TRUE; +} +#endif /* IWSC_SUPPORT */ + +#endif /* WSC_STA_SUPPORT */ + +INT Set_TGnWifiTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bTGnWifiTest = FALSE; + else + pAd->StaCfg.bTGnWifiTest = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest)); + return TRUE; +} + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; + else if (simple_strtol(arg, 0, 10) == 1) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible; + else if (simple_strtol(arg, 0, 10) == 2) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode)); + return TRUE; +} +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef CARRIER_DETECTION_SUPPORT +INT Set_StaCarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + else + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_StaCarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable)); + return TRUE; +} +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_DyncVgaEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + UINT32 bbp_val; + + Enable = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = (Enable > 0) ? TRUE : FALSE; + + if (pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable == FALSE) + { + RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val); + bbp_val = (bbp_val & 0xffff80ff) | (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val); + + if (pAd->CommonCfg.RxStream >= 2) { + RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val); + bbp_val = (bbp_val & 0xffff80ff) | (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DyncVgaEnable_Proc::(enable = %d)\n", pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable)); + + return TRUE; +} +#endif /* DYNAMIC_VGA_SUPPORT */ + +INT Show_Adhoc_MacTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING extra, + IN UINT32 size) +{ + INT i; + + sprintf(extra, "\n"); + +#ifdef DOT11_N_SUPPORT + sprintf(extra, "%sHT Operating Mode : %d\n", extra, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); +#endif /* DOT11_N_SUPPORT */ + + sprintf(extra + strlen(extra), "\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", + "MAC", "AID", "BSS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC"); + + for (i=1; iMacTab.Content[i]; + + if (strlen(extra) > (size - 30)) + break; + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) && (pEntry->Sst == SST_ASSOC)) + { + sprintf(extra + strlen(extra), "%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + sprintf(extra + strlen(extra), "%-4d", (int)pEntry->Aid); + sprintf(extra + strlen(extra), "%-4d", (int)pEntry->apidx); + sprintf(extra + strlen(extra), "%-7d", pEntry->RssiSample.AvgRssi0); + sprintf(extra + strlen(extra), "%-7d", pEntry->RssiSample.AvgRssi1); + sprintf(extra + strlen(extra), "%-7d", pEntry->RssiSample.AvgRssi2); + sprintf(extra + strlen(extra), "%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + sprintf(extra + strlen(extra), "%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); + sprintf(extra + strlen(extra), "%-6d", pEntry->HTPhyMode.field.MCS); + sprintf(extra + strlen(extra), "%-6d", pEntry->HTPhyMode.field.ShortGI); + sprintf(extra + strlen(extra), "%-6d", pEntry->HTPhyMode.field.STBC); + sprintf(extra + strlen(extra), "%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + sprintf(extra + strlen(extra), "\n"); + } + } + + return TRUE; +} + +#ifdef DOT11R_FT_SUPPORT +INT Set_FtApBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG BssIdx = 0; + MLME_JOIN_REQ_STRUCT JoinReq; + UCHAR MacAddr[MAC_ADDR_LEN]; + + if (rtstrmactohex(arg, (PSTRING) &MacAddr[0]) == FALSE) + return FALSE; + + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport == FALSE) + return FALSE; + + /* + find the desired BSS in the latest SCAN result table + search 2.4G band first + */ + BssIdx = BssTableSearch(&pAd->ScanTab, MacAddr, 1); + /* + search 5G band, if AP does not exist in 2.4G band + */ + if (BssIdx == BSS_NOT_FOUND) + BssIdx = BssTableSearch(&pAd->ScanTab, MacAddr, 36); + if (BssIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + return TRUE; + } + + if (pAd->CommonCfg.Channel != pAd->ScanTab.BssEntry[BssIdx].Channel) + { + MLME_FT_REQ_STRUCT FtReq; + DBGPRINT(RT_DEBUG_TRACE, ("Dot11r: pBss->Channel = %d. Use OTD.\n", pAd->ScanTab.BssEntry[BssIdx].Channel)); + FT_OTD_ActParmFill(pAd, + &FtReq, + MacAddr, + pAd->ScanTab.BssEntry[BssIdx].AuthMode, + &pAd->StaCfg.Dot11RCommInfo.MdIeInfo, + &pAd->StaCfg.Dot11RCommInfo.FtIeInfo, + pAd->StaCfg.ResVarIELen, pAd->StaCfg.ResVarIEs); + + MlmeEnqueue(pAd, FT_OTD_ACT_STATE_MACHINE, FT_OTD_MT2_MLME_REQ, + sizeof(MLME_FT_REQ_STRUCT), &FtReq, 0); + } + else + { + /* copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. */ + /* Because we need this entry to become the JOIN target in later on SYNC state machine */ + pAd->MlmeAux.BssIdx = 0; + pAd->MlmeAux.SsidBssTab.BssNr = 1; + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); + + JoinParmFill(pAd, &JoinReq, 0); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), + &JoinReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + + return TRUE; +} + +INT Set_FtSupport_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.Dot11RCommInfo.bFtSupport = FALSE; + else + pAd->StaCfg.Dot11RCommInfo.bFtSupport = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_FTSupport_Proc::(bFtSupport=%d)\n", pAd->StaCfg.Dot11RCommInfo.bFtSupport)); + return TRUE; +} +#endif /* DOT11R_FT_SUPPORT */ + +INT Set_BeaconLostTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG ltmp = (ULONG)simple_strtol(arg, 0, 10); + + if ((ltmp != 0) && (ltmp <= 60)) + pAd->StaCfg.BeaconLostTime = (ltmp * OS_HZ); + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_BeaconLostTime_Proc::(BeaconLostTime=%ld)\n", pAd->StaCfg.BeaconLostTime)); + return TRUE; +} + +INT Set_AutoRoaming_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bAutoRoaming = FALSE; + else + pAd->StaCfg.bAutoRoaming = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_AutoRoaming_Proc::(bAutoRoaming=%d)\n", pAd->StaCfg.bAutoRoaming)); + return TRUE; +} + + +/* + ========================================================================== + Description: + Issue a site survey command to driver + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set site_survey + ========================================================================== +*/ + +INT Set_ForceTxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bForceTxBurst = FALSE; + else + pAd->StaCfg.bForceTxBurst = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ForceTxBurst_Proc::(bForceTxBurst=%d)\n", pAd->StaCfg.bForceTxBurst)); + return TRUE; +} + +#ifdef XLINK_SUPPORT +INT Set_XlinkMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 Value = 0; + + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.PSPXlink = 0; + else + pAd->StaCfg.PSPXlink = 1; + + AsicSetRxFilter(pAd); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_XlinkMode_Proc::(PSPXlink=%d)\n", pAd->StaCfg.PSPXlink)); + return TRUE; +} +#endif /* XLINK_SUPPORT */ + +#ifdef ETH_CONVERT_SUPPORT +INT Set_FragTest_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAdapter->StaCfg.bFragFlag = FALSE; + else + pAdapter->StaCfg.bFragFlag = TRUE; + return TRUE; +} +#endif /* ETH_CONVERT_SUPPORT */ + + +VOID RTMPAddKey(RTMP_ADAPTER *pAd, PNDIS_802_11_KEY pKey) +{ + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); + + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + if (pKey->KeyIndex & 0x80000000) + { + if (wdev->AuthMode == Ndis802_11AuthModeWPANone) + { + NdisZeroMemory(pAd->StaCfg.PMK, 32); + NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength); + goto end; + } + /* Update PTK */ + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + /* Update these related information to MAC_TABLE_ENTRY */ + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_MIC); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + BSS0, + 0, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->wcid, + PAIRWISEKEYTABLE); + + if (wdev->AuthMode >= Ndis802_11AuthModeWPA2) + { + /* set 802.1x port control */ + STA_PORT_SECURED(pAd); + } + } + else + { + /* Update GTK */ + wdev->DefaultKeyId = (pKey->KeyIndex & 0xFF); + NdisZeroMemory(&pAd->SharedKey[BSS0][wdev->DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][wdev->DefaultKeyId].KeyLen = LEN_TK; + NdisMoveMemory(pAd->SharedKey[BSS0][wdev->DefaultKeyId].Key, pKey->KeyMaterial, LEN_TK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.GroupCipher == Ndis802_11TKIPEnable) + { + NdisMoveMemory(pAd->SharedKey[BSS0][wdev->DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][wdev->DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + NdisMoveMemory(pAd->SharedKey[BSS0][wdev->DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][wdev->DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + pAd->SharedKey[BSS0][wdev->DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11TKIPEnable) + pAd->SharedKey[BSS0][wdev->DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11AESEnable) + pAd->SharedKey[BSS0][wdev->DefaultKeyId].CipherAlg = CIPHER_AES; + + /* Update group key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + wdev->DefaultKeyId, + &pAd->SharedKey[BSS0][wdev->DefaultKeyId]); + + + /* set 802.1x port control */ + STA_PORT_SECURED(pAd); + } + } + else /* dynamic WEP from wpa_supplicant */ + { + UCHAR CipherAlg; + PUCHAR Key; + + if(pKey->KeyLength == 32) + goto end; + + KeyIdx = pKey->KeyIndex & 0x0fffffff; + + if (KeyIdx < 4) + { + /* it is a default shared key, for Pairwise key setting */ + if (pKey->KeyIndex & 0x80000000) + { + pEntry = MacTableLookup(pAd, pKey->BSSID); + + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n")); + + /* set key material and key length */ + pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* set Cipher type */ + if (pKey->KeyLength == 5) + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + else + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, + KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + } + } + else + { + /* Default key for tx (shared key) */ + wdev->DefaultKeyId = (UCHAR) KeyIdx; + + /* set key material and key length */ + pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* Set Ciper type */ + if (pKey->KeyLength == 5) + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128; + + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + Key = pAd->SharedKey[BSS0][KeyIdx].Key; + + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, &pAd->SharedKey[BSS0][KeyIdx]); + + } + } + } +end: + return; +} + + + +/* + ========================================================================== + Description: + Site survey entry point + + NOTE: + ========================================================================== +*/ +VOID StaSiteSurvey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_SSID pSsid, + IN UCHAR ScanType) +{ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, ignore this scanning. + */ + DBGPRINT(RT_DEBUG_TRACE, ("StaSiteSurvey:: Scanning now\n")); + return; + } + if (INFRA_ON(pAd)) + { + pAd->StaCfg.bImprovedScan = TRUE; + pAd->StaCfg.ScanChannelCnt = 0; /* reset channel counter to 0 */ + } + +#ifdef WSC_STA_SUPPORT + if (ScanType == SCAN_WSC_ACTIVE) + pAd->StaCfg.bImprovedScan = FALSE; +#endif /* WSC_STA_SUPPORT */ + + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + + + if (pSsid) + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + pSsid->SsidLength, + pSsid->Ssid, + 0); + else + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + "", + 0); + + RTMP_MLME_HANDLER(pAd); +} + +INT Set_AutoReconnect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bAutoReconnect = FALSE; + else + pAd->StaCfg.bAutoReconnect = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_AutoReconnect_Proc::(bAutoReconnect=%d)\n", pAd->StaCfg.bAutoReconnect)); + return TRUE; +} + +INT Set_AdhocN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef DOT11_N_SUPPORT + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bAdhocN = FALSE; + else + pAd->StaCfg.bAdhocN = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_AdhocN_Proc::(bAdhocN=%d)\n", pAd->StaCfg.bAdhocN)); +#endif /* DOT11_N_SUPPORT */ + return TRUE; +} + + +#ifdef RTMP_RBUS_SUPPORT +#ifdef LED_CONTROL_SUPPORT +INT Set_WlanLed_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bWlanLed; +#ifdef CONFIG_SWMCU_SUPPORT + PSWMCU_LED_CONTROL pSWMCULedCntl = &pAd->LedCntl.SWMCULedCntl; +#endif /* CONFIG_SWMCU_SUPPORT */ + BOOLEAN Cancelled; + + bWlanLed = (ULONG) simple_strtol(arg, 0, 10); +#ifdef CONFIG_SWMCU_SUPPORT + if (bWlanLed != pSWMCULedCntl->bWlanLed) +#endif /* CONFIG_SWMCU_SUPPORT */ + { + if (bWlanLed) + RTMPStartLEDMode(pAd); + else + RTMPExitLEDMode(pAd); + } + + return TRUE; +} +#endif /* LED_CONTROL_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +/* set WOW enable */ +INT Set_WOW_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 Val; + UINT8 Pin = pAd->WOW_Cfg.nSelectedGPIO; + ULONG Value = simple_strtol(arg, 0, 10); + + if (Value != 1) + Value = 0; /* default is disable */ + + pAd->WOW_Cfg.bEnable = (BOOLEAN)Value; + + /* pull GPIO high */ + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Val); + if (Pin <= 7) + { + Val &= ~(1UL << (Pin+8)); /* direction: 0 out, 1 in */ + Val |= 1UL << Pin; /* data */ + } + else + { + Val &= ~(1UL << (Pin+16)); /* direction: 0 out, 1 in */ + Val |= 1UL << (Pin+8); /* data */ + } + RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Val); + + DBGPRINT(RT_DEBUG_ERROR, ("WOW_Enable = %d, GPIO = %x\n", pAd->WOW_Cfg.bEnable, Val)); + + return TRUE; +} + +/* set GPIO pin for wake-up signal */ +INT Set_WOW_GPIO( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value = simple_strtol(arg, 0, 10); + + if (Value > 13) + Value = 1; /* default GPIO pin */ + + pAd->WOW_Cfg.nSelectedGPIO = (UINT8)Value; + DBGPRINT(RT_DEBUG_ERROR, ("WOW_GPIO = %d\n", pAd->WOW_Cfg.nSelectedGPIO)); + + return TRUE; +} + +/* set delay time for WOW really enable */ +INT Set_WOW_Delay( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value = simple_strtol(arg, 0, 10); + + if (Value > 255) + Value = 3; /* default delay time */ + + pAd->WOW_Cfg.nDelay = (UINT8)Value; + DBGPRINT(RT_DEBUG_ERROR, ("WOW_Delay = %d, equal to %d sec\n", pAd->WOW_Cfg.nDelay, (pAd->WOW_Cfg.nDelay+1)*3)); + + return TRUE; +} + +/* set wake up hold time */ +INT Set_WOW_Hold( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value = simple_strtol(arg, 0, 10); + + if (Value > 255) + Value = 1; /* pule hold time - unit: 10ms */ + + pAd->WOW_Cfg.nHoldTime = (UINT8)Value; + DBGPRINT(RT_DEBUG_ERROR, ("WOW_Hold = %d, equal to %d ms\n", pAd->WOW_Cfg.nHoldTime, (pAd->WOW_Cfg.nHoldTime)*10)); + + return TRUE; +} + +/* set wake up signal type */ +INT Set_WOW_InBand( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG Value = simple_strtol(arg, 0, 10); + + if (Value != 1) + Value = 0; /* use GPIO to wakeup system */ + + pAd->WOW_Cfg.bInBand = (UINT8)Value; + DBGPRINT(RT_DEBUG_ERROR, ("WOW_Inband = %d\n", pAd->WOW_Cfg.bInBand)); + + return TRUE; +} +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +INT RTMPSetInformation( + IN RTMP_ADAPTER *pAd, + INOUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd) +{ + RTMP_IOCTL_INPUT_STRUCT *wrq = (RTMP_IOCTL_INPUT_STRUCT *) rq; + NDIS_802_11_SSID Ssid; + NDIS_802_11_MAC_ADDRESS Bssid; + RT_802_11_PHY_MODE PhyMode; + RT_802_11_STA_CONFIG StaConfig; + NDIS_802_11_RATES aryRates; + RT_802_11_PREAMBLE Preamble; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; + NDIS_802_11_RTS_THRESHOLD RtsThresh = 0; + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + NDIS_802_11_POWER_MODE PowerMode; + PNDIS_802_11_KEY pKey = NULL; + PNDIS_802_11_WEP pWepKey =NULL; + PNDIS_802_11_REMOVE_KEY pRemoveKey = NULL; + NDIS_802_11_CONFIGURATION *pConfig = NULL; + NDIS_802_11_NETWORK_TYPE NetType; + ULONG Now; + UINT KeyIdx = 0; + INT Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G; + ULONG PowerTemp; + BOOLEAN RadioState; + BOOLEAN StateMachineTouched = FALSE; + PNDIS_802_11_PASSPHRASE ppassphrase = NULL; +#ifdef DOT11_N_SUPPORT + OID_SET_HT_PHYMODE HT_PhyMode; /*11n */ +#endif /* DOT11_N_SUPPORT */ +#ifdef WPA_SUPPLICANT_SUPPORT + PNDIS_802_11_PMKID pPmkId = NULL; + BOOLEAN IEEE8021xState = FALSE; + BOOLEAN IEEE8021x_required_keys = FALSE; + UCHAR wpa_supplicant_enable = 0; +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef SNMP_SUPPORT + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR ctmp; +#endif /* SNMP_SUPPORT */ + + +#ifdef WAPI_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* WAPI_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + UINT WPSLedMode10 = 0; +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + + + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + +#ifdef DOT11_N_SUPPORT + MaxPhyMode = PHY_11N_5G; +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(), 0x%08x\n", cmd&0x7FFF)); + switch(cmd & 0x7FFF) { + case RT_OID_802_11_COUNTRY_REGION: + if (wrq->u.data.length < sizeof(UCHAR)) + Status = -EINVAL; + /* Only avaliable when EEPROM not programming */ + else if (!(pAd->CommonCfg.CountryRegion & 0x80) && !(pAd->CommonCfg.CountryRegionForABand & 0x80)) + { + ULONG Country; + + Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length); + pAd->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF); + pAd->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF); + /* Build all corresponding channel information */ + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d B/G:%d)\n", pAd->CommonCfg.CountryRegionForABand, + pAd->CommonCfg.CountryRegion)); + } + break; + case OID_802_11_BSSID_LIST_SCAN: + RTMP_GetCurrentSystemTick(&Now); +/* Now = jiffies; */ + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAd->RalinkCounters.LastOneSecTotalTxCount)); + + if (MONITOR_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + break; + } + + /*Benson add 20080527, when radio off, sta don't need to scan */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + break; + + if (pAd->RalinkCounters.LastOneSecTotalTxCount > 100) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } + + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } + +#ifdef WSC_STA_SUPPORT + if ((pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.WscState >= WSC_STATE_LINK_UP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! WPS processing now! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } +#endif /* WSC_STA_SUPPORT */ + + StaSiteSurvey(pAd, NULL, SCAN_ACTIVE); + break; + case OID_802_11_SSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) + Status = -EINVAL; + else + { + PSTRING pSsidString = NULL; + Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); + if (Ssid.SsidLength > MAX_LEN_OF_SSID) + Status = -EINVAL; + else + { + if (Ssid.SsidLength == 0) + { + Set_SSID_Proc(pAd, ""); + } + else + { + os_alloc_mem(pAd, (UCHAR **)&pSsidString, MAX_LEN_OF_SSID+1); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength); + pSsidString[MAX_LEN_OF_SSID] = 0x00; + Set_SSID_Proc(pAd, pSsidString); + os_free_mem(NULL, pSsidString); + } + else + Status = -ENOMEM; + } + } + } + break; + case OID_802_11_SET_PASSPHRASE: + os_alloc_mem(pAd, (UCHAR **)&ppassphrase, wrq->u.data.length); + + if(ppassphrase== NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_PASSPHRASE, Failed!!\n")); + break; + } + else + { + Status = copy_from_user(ppassphrase, wrq->u.data.pointer, wrq->u.data.length); + + if (Status) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_PASSPHRASE, Failed (length mismatch)!!\n")); + } + else + { + if(ppassphrase->KeyLength < 8 || ppassphrase->KeyLength > 64) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_PASSPHRASE, Failed (len less than 8 or greater than 64)!!\n")); + } + else + { + /* set key passphrase and length */ + NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + NdisMoveMemory(pAd->StaCfg.WpaPassPhrase, &ppassphrase->KeyMaterial, ppassphrase->KeyLength); + pAd->StaCfg.WpaPassPhraseLen = ppassphrase->KeyLength; + hex_dump("pAd->StaCfg.WpaPassPhrase", pAd->StaCfg.WpaPassPhrase, 64); + printk("WpaPassPhrase=%s\n",pAd->StaCfg.WpaPassPhrase); + } + } + } + os_free_mem(NULL, ppassphrase); + break; + + case OID_802_11_BSSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length); + + /* tell CNTL state machine to call NdisMSetInformationComplete() after completing */ + /* this request, because this request is initiated by NDIS. */ + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + + /* Prevent to connect AP again in STAMlmePeriodicExec */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)&Bssid, 0); + Status = NDIS_STATUS_SUCCESS; + StateMachineTouched = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(Bssid))); + } + break; + case RT_OID_802_11_RADIO: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState)); + if (pAd->StaCfg.bSwRadio != RadioState) + { + pAd->StaCfg.bSwRadio = RadioState; + if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAd); + /* Update extra information */ + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + } + + MlmeRadioOff(pAd); + /* Update extra information */ + pAd->ExtraInfo = SW_RADIO_OFF; + } + } + } + } + break; + case RT_OID_802_11_PHY_MODE: + if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE)) + Status = -EINVAL; + else + { + // TODO: shiang-6590, fix this for PhyMode!! + Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length); + if (PhyMode <= MaxPhyMode) + { + pAd->CommonCfg.cfg_wmode = PhyMode; + RTMPSetPhyMode(pAd, PhyMode); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode)); + } + break; + case RT_OID_802_11_STA_CONFIG: + if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG)) + Status = -EINVAL; + else + { + UINT32 Value; + + Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length); + pAd->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst; + pAd->CommonCfg.UseBGProtection = StaConfig.UseBGProtection; + pAd->CommonCfg.bUseShortSlotTime = 1; /* 2003-10-30 always SHORT SLOT capable */ + if ((pAd->CommonCfg.PhyMode != StaConfig.AdhocMode) && + (StaConfig.AdhocMode <= MaxPhyMode)) + { + /* allow dynamic change of "USE OFDM rate or not" in ADHOC mode */ + /* if setting changed, need to reset current TX rate as well as BEACON frame format */ + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + RTMPSetPhyMode(pAd, StaConfig.AdhocMode); + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy to on-chip memory */ + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n", + pAd->CommonCfg.bEnableTxBurst, + pAd->CommonCfg.UseBGProtection, + pAd->CommonCfg.bUseShortSlotTime)); + + AsicSetRxFilter(pAd); + } + break; + case OID_802_11_DESIRED_RATES: + if (wrq->u.data.length != sizeof(NDIS_802_11_RATES)) + Status = -EINVAL; + else + { + Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length); + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAd->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAd->CommonCfg.DesireRate[0],pAd->CommonCfg.DesireRate[1], + pAd->CommonCfg.DesireRate[2],pAd->CommonCfg.DesireRate[3], + pAd->CommonCfg.DesireRate[4],pAd->CommonCfg.DesireRate[5], + pAd->CommonCfg.DesireRate[6],pAd->CommonCfg.DesireRate[7] )); + /* Changing DesiredRate may affect the MAX TX rate we used to TX frames out */ + MlmeUpdateTxRates(pAd, FALSE, 0); + } + break; + case RT_OID_802_11_PREAMBLE: + if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length); + if (Preamble == Rt802_11PreambleShort) + { + pAd->CommonCfg.TxPreamble = Preamble; + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); + } + else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto)) + { + /* if user wants AUTO, initialize to LONG here, then change according to AP's */ + /* capability upon association. */ + pAd->CommonCfg.TxPreamble = Preamble; + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); + } + else + { + Status = -EINVAL; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble)); + } + break; + case OID_802_11_WEP_STATUS: + if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length); + /* Since TKIP, AES, WEP are all supported. It should not have any invalid setting */ + if (WepStatus <= Ndis802_11Encryption3KeyAbsent) + { + if (pAd->StaCfg.wdev.WepStatus != WepStatus) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->StaCfg.wdev.WepStatus = WepStatus; + pAd->StaCfg.PairCipher = WepStatus; + pAd->StaCfg.GroupCipher = WepStatus; + + if (pAd->StaCfg.BssType == BSS_ADHOC) + RTMPSetPhyMode(pAd, pAd->CommonCfg.cfg_wmode); + } + else + { + Status = -EINVAL; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus)); + } + break; + case OID_802_11_AUTHENTICATION_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length); + if (AuthMode > Ndis802_11AuthModeMax) + { + Status = -EINVAL; + break; + } + else + { + if (wdev->AuthMode != AuthMode) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + wdev->AuthMode = AuthMode; + } + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n", wdev->AuthMode)); + } + break; + case OID_802_11_INFRASTRUCTURE_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length); + + if (BssType == Ndis802_11IBSS) + Set_NetworkType_Proc(pAd, "Adhoc"); + else if (BssType == Ndis802_11Infrastructure) + Set_NetworkType_Proc(pAd, "Infra"); + else if (BssType == Ndis802_11Monitor) + Set_NetworkType_Proc(pAd, "Monitor"); + else + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n")); + } + } + break; + case OID_802_11_REMOVE_WEP: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n")); + if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX)) + { + Status = -EINVAL; + } + else + { + KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer; + + if (KeyIdx & 0x80000000) + { + /* Should never set default bit when remove key */ + Status = -EINVAL; + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx >= 4){ + Status = -EINVAL; + } + else + { + pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, 0, (UCHAR)KeyIdx); + } + } + } + break; + case RT_OID_802_11_RESET_COUNTERS: + NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); + pAd->Counters8023.RxNoBuffer = 0; + pAd->Counters8023.GoodReceives = 0; + pAd->Counters8023.RxNoBuffer = 0; +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + int i; + for (i=0; iMacTab.Content[i].TxBFCounters, sizeof(pAd->MacTab.Content[i].TxBFCounters)); + } +#endif /* TXBF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n")); + break; + case OID_802_11_RTS_THRESHOLD: + if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD)) + Status = -EINVAL; + else + { + Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length); + if (RtsThresh > MAX_RTS_THRESHOLD) + { + Status = -EINVAL; + RtsThresh = 0; /* avoid compile warning in printk() */ + } + else + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh)); + break; + case OID_802_11_FRAGMENTATION_THRESHOLD: + if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD)) + { + Status = -EINVAL; + FragThresh = 0; /* avoid compile warning in printk() */ + } + else + { + Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length); + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { + if (FragThresh == 0) + { + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + } + else + Status = -EINVAL; + } + else + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh)); + break; + case OID_802_11_POWER_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE)) + { + Status = -EINVAL; + PowerMode = 0; /* avoid compile warning in printk() */ + } + else + { + Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length); + if (PowerMode == Ndis802_11PowerModeCAM) + Set_PSMode_Proc(pAd, "CAM"); + else if (PowerMode == Ndis802_11PowerModeMAX_PSP) + Set_PSMode_Proc(pAd, "Max_PSP"); + else if (PowerMode == Ndis802_11PowerModeFast_PSP) + Set_PSMode_Proc(pAd, "Fast_PSP"); + else if (PowerMode == Ndis802_11PowerModeLegacy_PSP) + Set_PSMode_Proc(pAd, "Legacy_PSP"); + else + Status = -EINVAL; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode)); + break; + case RT_OID_802_11_TX_POWER_LEVEL_1: + if (wrq->u.data.length < sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length); + if (PowerTemp > 100) + PowerTemp = 0xffffffff; /* AUTO */ + pAd->CommonCfg.TxPowerDefault = PowerTemp; /*keep current setting. */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); + } + break; + case OID_802_11_NETWORK_TYPE_IN_USE: + if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length); + + if (NetType == Ndis802_11DS) + RTMPSetPhyMode(pAd, WMODE_B); + else if (NetType == Ndis802_11OFDM24) + RTMPSetPhyMode(pAd, WMODE_B | WMODE_G); + else if (NetType == Ndis802_11OFDM5) + RTMPSetPhyMode(pAd, WMODE_A); + else + Status = -EINVAL; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType)); + } + break; + /* For WPA PSK PMK key */ + case RT_OID_802_11_ADD_WPA: + os_alloc_mem(pAd, (UCHAR **)&pKey, wrq->u.data.length); + if(pKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + if ((pKey->Length != wrq->u.data.length) || + (pKey->KeyLength > LEN_PMK)) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n")); + } + else + { + if ((wdev->AuthMode != Ndis802_11AuthModeWPAPSK) && + (wdev->AuthMode != Ndis802_11AuthModeWPA2PSK) && + (wdev->AuthMode != Ndis802_11AuthModeWPANone) ) + { + Status = -EOPNOTSUPP; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n")); + } + else if ((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPANone) ) /* Only for WPA PSK mode */ + { + NdisMoveMemory(pAd->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength); + /* Use RaConfig as PSK agent. */ + /* Start STA supplicant state machine */ + if (wdev->AuthMode != Ndis802_11AuthModeWPANone) + pAd->StaCfg.WpaState = SS_START; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + else + { + pAd->StaCfg.WpaState = SS_NOTUSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + } + os_free_mem(NULL, pKey); + break; + case OID_802_11_REMOVE_KEY: + os_alloc_mem(pAd, (UCHAR **)&pRemoveKey, wrq->u.data.length); + if(pRemoveKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length); + if (pRemoveKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n")); + } + else + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + RTMPWPARemoveKeyProc(pAd, pRemoveKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n")); + } + else + { + KeyIdx = pRemoveKey->KeyIndex; + + if (KeyIdx & 0x80000000) + { + /* Should never set default bit when remove key */ + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n")); + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx > 3) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx)); + } + else + { + pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, 0, (UCHAR)KeyIdx); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length)); + } + } + } + } + os_free_mem(NULL, pRemoveKey); + break; + /* New for WPA */ + case OID_802_11_ADD_KEY: + os_alloc_mem(pAd, (UCHAR **)&pKey, wrq->u.data.length); + if(pKey == NULL) + { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + if ((pKey->Length != wrq->u.data.length) || + (pKey->KeyLength > LEN_PMK)) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n")); + } + else + { + RTMPAddKey(pAd, pKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + os_free_mem(NULL, pKey); + break; + case OID_802_11_CONFIGURATION: + if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION)) + Status = -EINVAL; + else + { + os_alloc_mem(NULL, (UCHAR **)&pConfig, sizeof(NDIS_802_11_CONFIGURATION)); + if (pConfig != NULL) + { + Status = copy_from_user(pConfig, wrq->u.data.pointer, wrq->u.data.length); +/* pConfig = &Config; */ + + if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400)) + pAd->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod; + + pAd->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow; + MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAd->CommonCfg.Channel); + /* */ + /* Save the channel on MlmeAux for CntlOidRTBssidProc used. */ + /* */ + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n", + pConfig->BeaconPeriod, pConfig->ATIMWindow, pAd->CommonCfg.Channel)); + /* Config has changed */ + pAd->bConfigChanged = TRUE; + os_free_mem(NULL, pConfig); + } + } + break; +#ifdef DOT11_N_SUPPORT + case RT_OID_802_11_SET_HT_PHYMODE: + if (wrq->u.data.length != sizeof(OID_SET_HT_PHYMODE)) + Status = -EINVAL; + else + { + POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode; + + Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode (PhyMode = %d,TransmitNo = %d, HtMode = %d, ExtOffset = %d , MCS = %d, BW = %d, STBC = %d, SHORTGI = %d) \n", + pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset, + pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + RTMPSetHT(pAd, pHTPhyMode); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n", + wdev->HTPhyMode.field.MCS, wdev->HTPhyMode.field.BW, wdev->HTPhyMode.field.ShortGI, + wdev->HTPhyMode.field.STBC)); + break; +#endif /* DOT11_N_SUPPORT */ + case RT_OID_802_11_SET_APSD_SETTING: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + ULONG apsd ; + Status = copy_from_user(&apsd, wrq->u.data.pointer, wrq->u.data.length); + + /*------------------------------------------------------------------- + |B31~B7 | B6~B5 | B4 | B3 | B2 | B1 | B0 | + --------------------------------------------------------------------- + | Rsvd | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD Capable | + ---------------------------------------------------------------------*/ + pAd->StaCfg.UapsdInfo.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE; + pAd->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1) ? TRUE : FALSE; + pAd->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2) ? TRUE : FALSE; + pAd->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3) ? TRUE : FALSE; + pAd->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4) ? TRUE : FALSE; + pAd->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d], MaxSPLen=%d)\n", apsd, pAd->StaCfg.UapsdInfo.bAPSDCapable, + pAd->CommonCfg.bAPSDAC_BE, pAd->CommonCfg.bAPSDAC_BK, pAd->CommonCfg.bAPSDAC_VI, pAd->CommonCfg.bAPSDAC_VO, pAd->CommonCfg.MaxSPLength)); + } + break; + + case RT_OID_802_11_SET_APSD_PSM: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + /* Driver needs to notify AP when PSM changes */ + Status = copy_from_user(&pAd->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length); + if (pAd->CommonCfg.bAPSDForcePowerSave != pAd->StaCfg.Psm) + { + RTMP_SET_PSM_BIT(pAd, pAd->CommonCfg.bAPSDForcePowerSave); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAd->CommonCfg.bAPSDForcePowerSave)); + } + break; +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_SET_DLS: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + BOOLEAN oldvalue = pAd->CommonCfg.bDLSCapable; + Status = copy_from_user(&pAd->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length); + if (oldvalue && !pAd->CommonCfg.bDLSCapable) + { + int i; + /* tear down local dls table entry */ + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + /* tear down peer dls table entry */ + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + } + + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAd->CommonCfg.bDLSCapable)); + } + break; + + case RT_OID_802_11_SET_DLS_PARAM: + if (wrq->u.data.length != sizeof(RT_802_11_DLS_UI)) + Status = -EINVAL; + else + { + RT_802_11_DLS Dls; + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI)); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls, 0); + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n")); + } + break; +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + case RT_OID_802_11_SET_TDLS: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + BOOLEAN oldvalue = pAd->StaCfg.TdlsInfo.bTDLSCapable; + + Status = copy_from_user(&pAd->StaCfg.TdlsInfo.bTDLSCapable, wrq->u.data.pointer, wrq->u.data.length); + if (oldvalue && !pAd->StaCfg.TdlsInfo.bTDLSCapable) + { + /* tear down local dls table entry */ + TDLS_LinkTearDown(pAd, TRUE); + } + + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAd->CommonCfg.bDLSCapable)); + } + break; + + case RT_OID_802_11_SET_TDLS_PARAM: + if (wrq->u.data.length != sizeof(RT_802_11_TDLS_UI)) + Status = -EINVAL; + else + { + RT_802_11_TDLS TDLS; + + /* Initialized mlme request */ + RTMPZeroMemory(&TDLS, sizeof(RT_802_11_TDLS)); + RTMPMoveMemory(&TDLS, wrq->u.data.pointer, sizeof(RT_802_11_TDLS_UI)); + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_TDLS_PARAM, + sizeof(RT_802_11_TDLS), + &TDLS, 0); + + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_TDLS_PARAM \n")); + } + break; +#endif /* DOT11Z_TDLS_SUPPORT */ + + case RT_OID_802_11_SET_WMM: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&pAd->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d) \n", pAd->CommonCfg.bWmmCapable)); + } + break; + + case OID_802_11_DISASSOCIATE: + /* */ + /* Set NdisRadioStateOff to TRUE, instead of called MlmeRadioOff. */ + /* Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0 */ + /* when query OID_802_11_BSSID_LIST. */ + /* */ + /* TRUE: NumberOfItems will set to 0. */ + /* FALSE: NumberOfItems no change. */ + /* */ + pAd->CommonCfg.NdisRadioStateOff = TRUE; + /* Set to immediately send the media disconnect event */ + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n")); + +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT + if (pAd->StaCfg.WscControl.bSkipWPSTurnOffLED == FALSE) + { + UCHAR WPSLEDStatus = LED_WPS_TURN_LED_OFF; + BOOLEAN Cancelled; + RTMPSetLED(pAd, WPSLEDStatus); + /* Cancel the WPS LED timer. */ + RTMPCancelTimer(&pAd->StaCfg.WscControl.WscLEDTimer, &Cancelled); + } +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + + if (INFRA_ON(pAd)) + { + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_DISASSOCIATE, + 0, + NULL, 0); + + StateMachineTouched = TRUE; + } + break; + +#ifdef DOT11_N_SUPPORT + case RT_OID_802_11_SET_IMME_BA_CAP: + if (wrq->u.data.length != sizeof(OID_BACAP_STRUC)) + Status = -EINVAL; + else + { + OID_BACAP_STRUC Orde ; + Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length); + if (Orde.Policy > BA_NOTUSE) + { + Status = NDIS_STATUS_INVALID_DATA; + } + else if (Orde.Policy == BA_NOTUSE) + { + pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + pAd->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode; + pAd->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; + /* UPdata to HT IE */ + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; /* we only support immediate BA. */ + pAd->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode; + pAd->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; + + /* UPdata to HT IE */ + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; + + if (pAd->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF) + pAd->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF; + + } + + pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; + DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAd->CommonCfg.BACapability.field.Policy, + pAd->CommonCfg.BACapability.field.RxBAWinLimit,pAd->CommonCfg.BACapability.field.TxBAWinLimit, pAd->CommonCfg.BACapability.field.AutoBA)); + DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAd->CommonCfg.DesiredHtPhy.MimoPs, pAd->CommonCfg.DesiredHtPhy.AmsduEnable, + pAd->CommonCfg.DesiredHtPhy.AmsduSize, pAd->CommonCfg.DesiredHtPhy.MpduDensity)); + } + + break; + case RT_OID_802_11_ADD_IMME_BA: + DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n")); + if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) + Status = -EINVAL; + else + { + UCHAR index; + OID_ADD_BA_ENTRY BA; + MAC_TABLE_ENTRY *pEntry; + + Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length); + if (BA.TID > (NUM_OF_TID-1)) + { + Status = NDIS_STATUS_INVALID_DATA; + break; + } + else + { + /*BATableInsertEntry */ + /*As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID. */ + index = BA.TID; + /* in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too */ + pEntry = MacTableLookup(pAd, BA.MACAddr); + if (!pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5])); + break; + } + if (BA.IsRecipient == FALSE) + { + if (pEntry->bIAmBadAtheros == TRUE) + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 0x10; + + BAOriSessionSetUp(pAd, pEntry, index, 0, 100, TRUE); + } + else + { + /*BATableInsertEntry(pAd, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient); */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n", + BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2] + , BA.MACAddr[4], BA.MACAddr[5])); + } + } + break; + + case RT_OID_802_11_TEAR_IMME_BA: + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n")); + if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) + Status = -EINVAL; + else + { + POID_ADD_BA_ENTRY pBA; + MAC_TABLE_ENTRY *pEntry; + + os_alloc_mem(pAd, (UCHAR **)&pBA, wrq->u.data.length); + if (pBA == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n")); + Status = NDIS_STATUS_FAILURE; + } + else + { + Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid)); + + if (!pBA->bAllTid && (pBA->TID > (NUM_OF_TID-1))) + { + Status = NDIS_STATUS_INVALID_DATA; + os_free_mem(NULL, pBA); + break; + } + + if (pBA->IsRecipient == FALSE) + { + pEntry = MacTableLookup(pAd, pBA->MACAddr); + DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n")); + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n")); + BAOriSessionTearDown(pAd, pEntry->wcid, pBA->TID, FALSE, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + else + { + pEntry = MacTableLookup(pAd, pBA->MACAddr); + if (pEntry) + { + BARecSessionTearDown( pAd, (UCHAR)pEntry->wcid, pBA->TID, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + os_free_mem(NULL, pBA); + } + } + break; +#endif /* DOT11_N_SUPPORT */ + + /* For WPA_SUPPLICANT to set static wep key */ + case OID_802_11_ADD_WEP: + os_alloc_mem(pAd, (UCHAR **)&pWepKey, wrq->u.data.length); + + if(pWepKey == NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n")); + break; + } + Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length); + if (Status) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n")); + } + else + { + KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + /* KeyIdx must be 0 ~ 3 */ + if (KeyIdx >= 4) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n")); + } + else + { + UCHAR CipherAlg = 0; + PUCHAR Key; + + /* Zero the specific shared key */ + NdisZeroMemory(&pAd->SharedKey[BSS0][KeyIdx], sizeof(CIPHER_KEY)); + + /* set key material and key length */ + pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + + switch(pWepKey->KeyLength) + { + case 5: + CipherAlg = CIPHER_WEP64; + break; + case 13: + CipherAlg = CIPHER_WEP128; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n")); + Status = -EINVAL; + break; + } + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg; + + /* Default key for tx (shared key) */ + if (pWepKey->KeyIndex & 0x80000000) + { +#ifdef WPA_SUPPLICANT_SUPPORT + NdisZeroMemory(&pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[KeyIdx], sizeof(CIPHER_KEY)); + + /* set key material and key length */ + pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[KeyIdx].Key, + &pWepKey->KeyMaterial, + pWepKey->KeyLength); + pAd->StaCfg.wpa_supplicant_info.DesireSharedKeyId = KeyIdx; + pAd->StaCfg.wpa_supplicant_info.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg; +#endif /* WPA_SUPPLICANT_SUPPORT */ + wdev->DefaultKeyId = (UCHAR) KeyIdx; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (wdev->AuthMode >= Ndis802_11AuthModeWPA)) + { + Key = pWepKey->KeyMaterial; + + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, &pAd->SharedKey[BSS0][KeyIdx]); + + STA_PORT_SECURED(pAd); + } + else if (wdev->PortSecured == WPA_802_1X_PORT_SECURED) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + Key = pAd->SharedKey[BSS0][KeyIdx].Key; + + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, &pAd->SharedKey[BSS0][KeyIdx]); + + if (pWepKey->KeyIndex & 0x80000000) + { + /* Assign pairwise key info */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, + KeyIdx, + CipherAlg, + BSSID_WCID, + SHAREDKEYTABLE); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), Port %s Secured\n", + pWepKey->KeyIndex, pWepKey->KeyLength, + (wdev->PortSecured == WPA_802_1X_PORT_SECURED) ? "" : "NOT")); + } + } + os_free_mem(NULL, pWepKey); + break; +#ifdef WPA_SUPPLICANT_SUPPORT + case OID_SET_COUNTERMEASURES: + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pAd->StaCfg.bBlockAssoc = TRUE; + else + /* WPA MIC error should block association attempt for 60 seconds */ + pAd->StaCfg.bBlockAssoc = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAd->StaCfg.bBlockAssoc ? "TRUE":"FALSE")); + } + break; + case RT_OID_WPA_SUPPLICANT_SUPPORT: + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length); + if (wpa_supplicant_enable & WPA_SUPPLICANT_ENABLE_WPS) + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP |= WPA_SUPPLICANT_ENABLE_WPS; + else + { + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP = wpa_supplicant_enable; + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP &= 0x7F; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=0x%02X)\n", + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP)); + } + break; + case OID_802_11_DEAUTHENTICATION: + if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT)) + Status = -EINVAL; + else + { + MLME_DEAUTH_REQ_STRUCT *pInfo; + MLME_QUEUE_ELEM *MsgElem; + + os_alloc_mem(pAd, (UCHAR **)&MsgElem, sizeof(MLME_QUEUE_ELEM)); + if (MsgElem == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); + return -EINVAL; + } + + pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg; + Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); + MlmeDeauthReqAction(pAd, MsgElem); + os_free_mem(NULL, MsgElem); + + if (INFRA_ON(pAd)) + { + LinkDown(pAd, FALSE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + break; + case OID_802_11_DROP_UNENCRYPTED: + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pAd->StaCfg.wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pAd->StaCfg.wdev.PortSecured = WPA_802_1X_PORT_SECURED; + NdisAcquireSpinLock(&pAd->MacTabLock); + pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.wdev.PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled)); + } + break; + case OID_802_11_SET_IEEE8021X: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length); + pAd->StaCfg.wdev.IEEE8021X = IEEE8021xState; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState)); + } + break; + case OID_802_11_SET_IEEE8021X_REQUIRE_KEY: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length); + pAd->StaCfg.wpa_supplicant_info.IEEE8021x_required_keys = IEEE8021x_required_keys; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys)); + } + break; + case OID_802_11_PMKID: + os_alloc_mem(pAd, (UCHAR **)&pPmkId, wrq->u.data.length); + + if(pPmkId == NULL) { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length); + + /* check the PMKID information */ + if (pPmkId->BSSIDInfoCount == 0) + NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + else + { + PBSSID_INFO pBssIdInfo; + UINT BssIdx; + UINT CachedIdx; + + for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++) + { + /* point to the indexed BSSID_INFO structure */ + pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO)); + /* Find the entry in the saved data base. */ + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + /* compare the BSSID */ + if (NdisEqualMemory(pBssIdInfo->BSSID, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS))) + break; + } + + /* Found, replace it */ + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + pAd->StaCfg.SavedPMKNum++; + } + /* Not found, replace the last one */ + else + { + /* Randomly replace one */ + CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + } + } + } + if(pPmkId) + os_free_mem(NULL, pPmkId); + break; + + case RT_OID_WPS_PROBE_REQ_IE: + if (pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe) + { + os_free_mem(NULL, pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe); + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe = NULL; + } + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen = 0; + os_alloc_mem(pAd, (UCHAR **)&(pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe), wrq->u.data.length); + if (pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe) + { + Status = copy_from_user(pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe, wrq->u.data.pointer, wrq->u.data.length); + + if (Status) + { + Status = -EINVAL; + if (pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe) + { + os_free_mem(NULL, pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe); + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe = NULL; + } + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPS_PROBE_REQ_IE, Failed (copy_from_user failed)!!\n")); + } + else + { + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen = wrq->u.data.length; + hex_dump("WpsProbeReqIe", + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe, + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPS_PROBE_REQ_IE, WpsProbeReqIeLen = %d!!\n", + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen)); + } + } + else + Status = -ENOMEM; + break; +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + case RT_OID_WSC_EAPMSG: + { + RTMP_WSC_U2KMSG_HDR *msgHdr = NULL; + PUCHAR pUPnPMsg = NULL; + UINT msgLen = 0, Machine = 0, msgType = 0; + int retVal, senderID = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("WSC::RT_OID_WSC_EAPMSG, wrq->u.data.length=%d!\n", wrq->u.data.length)); + + msgLen = wrq->u.data.length; + os_alloc_mem(pAd, (UCHAR **)&pUPnPMsg, msgLen); + if (pUPnPMsg == NULL) + Status = -EINVAL; + else + { + memset(pUPnPMsg, 0, msgLen); + retVal = copy_from_user(pUPnPMsg, wrq->u.data.pointer, msgLen); + + msgHdr = (RTMP_WSC_U2KMSG_HDR *)pUPnPMsg; + senderID = *((int *)&msgHdr->Addr2); + /*assign the STATE_MACHINE type */ + { + Machine = WSC_STATE_MACHINE; + msgType = WSC_EAPOL_UPNP_MSG; + + retVal = MlmeEnqueueForWsc(pAd, msgHdr->envID, senderID, Machine, msgType, msgLen, pUPnPMsg); + if((retVal == FALSE) && (msgHdr->envID != 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeEnqueuForWsc return False and envID=0x%x!\n", msgHdr->envID)); + Status = -EINVAL; + } + } + + os_free_mem(NULL, pUPnPMsg); + } + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_EAPMSG finished!\n")); + } + break; + case RT_OID_WSC_SET_PROFILE: + if (wrq->u.data.length != sizeof(WSC_PROFILE)) + Status = -EINVAL; + else + { + PWSC_PROFILE pWscProfile = &pAd->StaCfg.WscControl.WscProfile; + NdisZeroMemory(pWscProfile, sizeof(WSC_PROFILE)); + Status = copy_from_user(pWscProfile, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_SET_PROFILE:: ProfileCnt = %d\n", pWscProfile->ProfileCnt)); + } + break; + + case RT_OID_WSC_SET_CONF_MODE: /* WPS disable, Enrollee or Registrar */ + if (wrq->u.data.length != sizeof(INT)) + Status = -EINVAL; + else + { + INT WscConfMode = 0; + Status = copy_from_user(&WscConfMode, wrq->u.data.pointer, wrq->u.data.length); + if (Status == 0) + { + if (WscConfMode == 2) + WscConfMode = 4; + + switch(WscConfMode) + { + case WSC_ENROLLEE: + Set_WscConfMode_Proc(pAd, "1"); + break; + case WSC_REGISTRAR: + Set_WscConfMode_Proc(pAd, "2"); + WscConfMode = 2; + break; + case WSC_DISABLE: + default: + Set_WscConfMode_Proc(pAd, "0"); + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_SET_CONF_MODE:: WscConfMode = %d\n", WscConfMode)); + } + break; + case RT_OID_WSC_SET_MODE: + if (wrq->u.data.length != sizeof(INT)) + Status = -EINVAL; + else + { + INT WscMode = 0; /* PIN or PBC */ + Status = copy_from_user(&WscMode, wrq->u.data.pointer, wrq->u.data.length); + if (Status == 0) + { + if (WscMode == WSC_PIN_MODE) /* PIN */ + { + if (Set_WscMode_Proc(pAd, "1") == FALSE) + Status = -EINVAL; + } + else if (WscMode == WSC_PBC_MODE) /* PBC */ + { + if (Set_WscMode_Proc(pAd, "2") == FALSE) + Status = -EINVAL; + } + else if (WscMode == WSC_SMPBC_MODE) /* SMPBC */ + { + if (Set_WscMode_Proc(pAd, "3") == FALSE) + Status = -EINVAL; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_SET_MODE::unknown WscMode = %d\n", WscMode)); + Status = -EINVAL; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_SET_MODE::WscMode = %d\n", WscMode)); + } + break; + case RT_OID_WSC_SET_PIN_CODE: + if (wrq->u.data.length != 8) /* PIN Code Length is 8 */ + Status = -EINVAL; + else + { + CHAR PinCode[9] = {0}; + Status = copy_from_user(&PinCode[0], wrq->u.data.pointer, wrq->u.data.length); + if (Status == 0) + { + if (Set_WscPinCode_Proc(pAd, (PSTRING) &PinCode[0]) == FALSE) + Status = -EINVAL; + } + } + break; + case RT_OID_WSC_SET_SSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) + Status = -EINVAL; + else + { + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); + Ssid.Ssid[NDIS_802_11_LENGTH_SSID-1] = 0x00; + Set_WscSsid_Proc(pAd, (PSTRING) Ssid.Ssid); + } + break; + case RT_OID_WSC_SET_CONN_BY_PROFILE_INDEX: + if (wrq->u.data.length != sizeof(UINT)) + Status = -EINVAL; + else + { + UINT wsc_profile_index = 0; /* PIN or PBC */ + PWSC_CTRL pWscControl = &pAd->StaCfg.WscControl; + unsigned long IrqFlags; + + Status = copy_from_user(&wsc_profile_index, wrq->u.data.pointer, wrq->u.data.length); + if (wsc_profile_index < pWscControl->WscProfile.ProfileCnt) + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + WscWriteConfToPortCfg(pAd, pWscControl, &pWscControl->WscProfile.Profile[wsc_profile_index], TRUE); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + LinkDown(pAd, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_SET_CONN_BY_PROFILE_INDEX:: wrong wsc_profile_index(%d)\n", wsc_profile_index)); + } + break; + case RT_OID_WSC_DRIVER_AUTO_CONNECT: + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&pAd->StaCfg.WscControl.WscDriverAutoConnect, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_DRIVER_AUTO_CONNECT::WscDriverAutoConnect is %d\n", + pAd->StaCfg.WscControl.WscDriverAutoConnect)); + } + break; + case RT_OID_WSC_SET_PASSPHRASE: + if (wrq->u.data.length > 64 || wrq->u.data.length < 8) + Status = -EINVAL; + else + { + Status = copy_from_user(pAd->StaCfg.WscControl.WpaPsk, wrq->u.data.pointer, wrq->u.data.length); + NdisZeroMemory(pAd->StaCfg.WscControl.WpaPsk, 64); + pAd->StaCfg.WscControl.WpaPskLen = wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_SET_PASSPHRASE::KeyLen(%d)\n", pAd->StaCfg.WscControl.WpaPskLen)); + } + break; +#endif /* WSC_STA_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + case RT_OID_LED_WPS_MODE10: + if(!(pAd->StaCfg.bRadio) || + (wrq->u.data.length != sizeof(UINT))) + Status = -EINVAL; + else + { + Status = copy_from_user(&WPSLedMode10, wrq->u.data.pointer, wrq->u.data.length); + if((WPSLedMode10 != LINK_STATUS_WPS_MODE10_TURN_ON) && + (WPSLedMode10 != LINK_STATUS_WPS_MODE10_FLASH) && + (WPSLedMode10 != LINK_STATUS_WPS_MODE10_TURN_OFF)) + { + Status = NDIS_STATUS_INVALID_DATA; + DBGPRINT(RT_DEBUG_INFO, ("WPS LED Mode 10::Parameter of LED Mode 10 must be 0x00, or 0x01, or 0x02\n")); + } + else + { +#ifdef RTMP_MAC_PCI + RTMPSetLED(pAd, WPSLedMode10); +#endif /* RTMP_MAC_PCI */ + } + } + break; +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef SNMP_SUPPORT + case OID_802_11_SHORTRETRYLIMIT: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + AsicSetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_SHORT, ShortRetryLimit); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (ShortRetryLimit=%ld)\n", ShortRetryLimit)); + } + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n")); + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + AsicSetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_LONG, LongRetryLimit); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (LongRetryLimit=%ld)\n", LongRetryLimit)); + } + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n")); + os_alloc_mem(pAd, (UCHAR **)&pKey, wrq->u.data.length); + if (pKey == NULL) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n")); + break; + } + + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + /*pKey = &WepKey; */ + + if ( pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n")); + } + KeyIdx = pKey->KeyIndex & 0x0fffffff; + DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength)); + + /* it is a shared key */ + if (KeyIdx >= 4) + Status = -EINVAL; + else + { + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); + if (pKey->KeyIndex & 0x80000000) + { + /* Default key for tx (shared key) */ + pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + } + /*RestartAPIsRequired = TRUE; */ + } + os_free_mem(NULL, pKey); + break; + + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n")); + + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + Status = copy_from_user(&pAd->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); + + break; + + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + STRING ChStr[5] = {0}; + Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length); + snprintf(ChStr, sizeof(ChStr), "%d", ctmp); + Set_Channel_Proc(pAd, ChStr); + } + break; +#endif /* SNMP_SUPPORT */ + + +#ifdef WAPI_SUPPORT + case OID_802_11_WAPI_PID: + { + unsigned long wapi_pid = 0; + if (copy_from_user(&pObj->wapi_pid, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + RTMP_GET_OS_PID(pObj->wapi_pid, wapi_pid); + pObj->wapi_pid_nr = wapi_pid; + DBGPRINT(RT_DEBUG_TRACE, ("OID_802_11_WAPI_PID::(WapiPid=%lu(0x%x))\n", wapi_pid, pObj->wapi_pid)); + } + } + break; + case OID_802_11_PORT_SECURE_STATE: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_PORT_SECURE_STATE, len=%d/%d\n", wrq->u.data.length, sizeof(WAPI_PORT_SECURE_STRUCT))); + if (wrq->u.data.length != sizeof(WAPI_PORT_SECURE_STRUCT)) + Status = -EINVAL; + else + { + WAPI_PORT_SECURE_STRUCT wapi_port; + + Status = copy_from_user(&wapi_port, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + if (INFRA_ON(pAd)) + { + if (NdisEqualMemory(pAd->MlmeAux.Bssid, wapi_port.Addr, MAC_ADDR_LEN)) + { + switch (wapi_port.state) + { + case WAPI_PORT_SECURED: + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + break; + + default: + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_PORT_SECURE_STATE (state=%d)\n", wapi_port.state)); + } + } + } + } + break; + + case OID_802_11_UCAST_KEY_INFO: + if (wrq->u.data.length != sizeof(WAPI_UCAST_KEY_STRUCT)) + Status = -EINVAL; + else + { + MAC_TABLE_ENTRY *pEntry = NULL; + WAPI_UCAST_KEY_STRUCT wapi_ukey; + + Status = copy_from_user(&wapi_ukey, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + if (INFRA_ON(pAd)) + { + if (NdisEqualMemory(pAd->MlmeAux.Bssid, wapi_ukey.Addr, MAC_ADDR_LEN)) + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + pEntry->usk_id = wapi_ukey.key_id; + NdisMoveMemory(pAd->StaCfg.PTK, wapi_ukey.PTK, 64); + NdisMoveMemory(pEntry->PTK, wapi_ukey.PTK, 64); + + /* Install pairwise key */ + WAPIInstallPairwiseKey(pAd, pEntry, FALSE); + + /* Start or re-start USK rekey mechanism, if necessary. */ + RTMPCancelWapiRekeyTimerAction(pAd, pEntry); + RTMPStartWapiRekeyTimerAction(pAd, pEntry); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_UCAST_KEY_INFO complete\n")); + hex_dump("WAPI UCAST KEY", pAd->StaCfg.PTK, 64); + } + } + } + } + break; + + case OID_802_11_MCAST_KEY_INFO: + if (wrq->u.data.length != sizeof(WAPI_MCAST_KEY_STRUCT)) + Status = -EINVAL; + else + { + WAPI_MCAST_KEY_STRUCT wapi_mkey; + + Status = copy_from_user(&wapi_mkey, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + /* Obtain the NMK and tx_iv of AE */ + pAd->StaCfg.DefaultKeyId = wapi_mkey.key_id; + /*NdisMoveMemory(pAd->StaCfg.rx_iv, wapi_mkey.m_tx_iv, LEN_WAPI_TSC); */ + NdisMoveMemory(pAd->StaCfg.NMK, wapi_mkey.NMK, 16); + + /* Calculate GTK */ + RTMPDeriveWapiGTK(pAd->StaCfg.NMK, pAd->StaCfg.GTK); + + /* Install Shared key */ + WAPIInstallSharedKey(pAd, + pAd->StaCfg.GroupCipher, + BSS0, + pAd->StaCfg.DefaultKeyId, + MCAST_WCID, + pAd->StaCfg.GTK); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MCAST_KEY_INFO complete\n")); + } + } + break; +#endif /* WAPI_SUPPORT */ + +#ifdef XLINK_SUPPORT + case RT_OID_802_11_SET_PSPXLINK_MODE: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&pAd->StaCfg.PSPXlink, wrq->u.data.pointer, wrq->u.data.length); + /*if (pAd->StaCfg.PSPXlink) + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS)*/ + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_PSPXLINK_MODE(=%d) \n", pAd->StaCfg.PSPXlink)); + } + break; +#endif /* XLINK_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + case RT_OID_802_11R_SUPPORT: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&pAd->StaCfg.Dot11RCommInfo.bFtSupport, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_SUPPORT(=%d) \n", pAd->StaCfg.Dot11RCommInfo.bFtSupport)); + } + break; +#endif /* DOT11R_FT_SUPPORT */ + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + + + return Status; +} + +INT RTMPQueryInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd) +{ + RTMP_IOCTL_INPUT_STRUCT *wrq = (RTMP_IOCTL_INPUT_STRUCT *) rq; + NDIS_802_11_BSSID_LIST_EX *pBssidList = NULL; + PNDIS_WLAN_BSSID_EX pBss; + NDIS_802_11_SSID Ssid; + NDIS_802_11_CONFIGURATION *pConfiguration = NULL; + RT_802_11_LINK_STATUS *pLinkStatus = NULL; + RT_802_11_STA_CONFIG *pStaConfig = NULL; + NDIS_802_11_STATISTICS *pStatistics = NULL; + NDIS_802_11_RTS_THRESHOLD RtsThresh; + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + NDIS_802_11_POWER_MODE PowerMode; + NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; + RT_802_11_PREAMBLE PreamType; + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_MEDIA_STATE MediaState; + ULONG BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0, RateValue=0; + USHORT BssLen = 0; + PUCHAR pBuf = NULL, pPtr; + INT Status = NDIS_STATUS_SUCCESS; + UINT we_version_compiled; + UCHAR i, Padding = 0; + BOOLEAN RadioState; + STRING driverVersion[8]; + OID_SET_HT_PHYMODE *pHTPhyMode = NULL; + HTTRANSMIT_SETTING HTPhyMode; +#ifdef WSC_STA_SUPPORT + UINT WscPinCode = 0; + PWSC_PROFILE pProfile; +#endif /* WSC_STA_SUPPORT */ + +#ifdef SNMP_SUPPORT + DefaultKeyIdxValue *pKeyIdxValue; + INT valueLen; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR tmp[64]; +#endif /*SNMP */ + + + + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + + switch(cmd) + { + case RT_OID_DEVICE_NAME: + wrq->u.data.length = sizeof(pAd->nickname); + Status = copy_to_user(wrq->u.data.pointer, pAd->nickname, wrq->u.data.length); + break; + case RT_OID_VERSION_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n")); + wrq->u.data.length = 8*sizeof(CHAR); + snprintf(&driverVersion[0], sizeof(driverVersion), "%s", STA_DRIVER_VERSION); + driverVersion[7] = '\0'; + if (copy_to_user(wrq->u.data.pointer, &driverVersion[0], wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + + case OID_802_11_BSSID_LIST: +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantScanCount = 0; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n", + pAd->ScanTab.BssNr)); + pAd->StaCfg.bSkipAutoScanConn = FALSE; + /* Claculate total buffer size required */ + BssBufSize = sizeof(ULONG); + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + /* Align pointer to 4 bytes boundary. */ + /*Padding = 4 - (pAd->ScanTab.BssEntry[i].VarIELen & 0x0003); */ + /*if (Padding == 4) */ + /* Padding = 0; */ + BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen + Padding); + } + + /* For safety issue, we add 256 bytes just in case */ + BssBufSize += 256; + /* Allocate the same size as passed from higher layer */ + os_alloc_mem(pAd, (UCHAR **)&pBuf, BssBufSize); + if(pBuf == NULL) + { + Status = -ENOMEM; + break; + } + + /* Init 802_11_BSSID_LIST_EX structure */ + NdisZeroMemory(pBuf, BssBufSize); + pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf; + pBssidList->NumberOfItems = pAd->ScanTab.BssNr; + + /* Calculate total buffer length */ + BssLen = 4; /* Consist of NumberOfItems */ + /* Point to start of NDIS_WLAN_BSSID_EX */ + /* pPtr = pBuf + sizeof(ULONG); */ + pPtr = (PUCHAR) &pBssidList->Bssid[0]; + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = (PNDIS_WLAN_BSSID_EX) pPtr; + NdisMoveMemory(&pBss->MacAddress, &pAd->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); + if ((pAd->ScanTab.BssEntry[i].Hidden == 1) && (pAd->StaCfg.bShowHiddenSSID == FALSE)) + { + /* */ + /* We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation */ + /* and then failed to send EAPOl farame. */ + /* */ + if ((wdev->AuthMode >= Ndis802_11AuthModeWPA) && (wdev->PortSecured != WPA_802_1X_PORT_SECURED)) + { + pBss->Ssid.SsidLength = pAd->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAd->ScanTab.BssEntry[i].Ssid, pAd->ScanTab.BssEntry[i].SsidLen); + } + else + pBss->Ssid.SsidLength = 0; + } + else + { + pBss->Ssid.SsidLength = pAd->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAd->ScanTab.BssEntry[i].Ssid, pAd->ScanTab.BssEntry[i].SsidLen); + } + pBss->Privacy = pAd->ScanTab.BssEntry[i].Privacy; + pBss->Rssi = pAd->ScanTab.BssEntry[i].Rssi - pAd->BbpRssiToDbmDelta; + pBss->MinSNR = pAd->ScanTab.BssEntry[i].MinSNR; + pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAd->ScanTab.BssEntry[i]); + pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION); + pBss->Configuration.BeaconPeriod = pAd->ScanTab.BssEntry[i].BeaconPeriod; + pBss->Configuration.ATIMWindow = pAd->ScanTab.BssEntry[i].AtimWin; + /*NdisMoveMemory(&pBss->QBssLoad, &pAd->ScanTab.BssEntry[i].QbssLoad, sizeof(QBSS_LOAD_UI)); */ + + MAP_CHANNEL_ID_TO_KHZ(pAd->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig); + + if (pAd->ScanTab.BssEntry[i].BssType == BSS_INFRA) + pBss->InfrastructureMode = Ndis802_11Infrastructure; + else + pBss->InfrastructureMode = Ndis802_11IBSS; + + NdisMoveMemory(pBss->SupportedRates, pAd->ScanTab.BssEntry[i].SupRate, pAd->ScanTab.BssEntry[i].SupRateLen); + NdisMoveMemory(pBss->SupportedRates + pAd->ScanTab.BssEntry[i].SupRateLen, + pAd->ScanTab.BssEntry[i].ExtRate, + pAd->ScanTab.BssEntry[i].ExtRateLen); + + if (pAd->ScanTab.BssEntry[i].VarIELen == 0) + { + pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAd->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + } + else + { + pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAd->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAd->ScanTab.BssEntry[i].VarIEs, pAd->ScanTab.BssEntry[i].VarIELen); + pPtr += pAd->ScanTab.BssEntry[i].VarIELen; + } + pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen + Padding); + + if (RtmpOsWirelessExtVerGet() < 17) + { + if ((BssLen + pBss->Length) < wrq->u.data.length) + BssLen += pBss->Length; + else + { + pBssidList->NumberOfItems = i; + break; + } + } + else + BssLen += pBss->Length; + + } + + if (RtmpOsWirelessExtVerGet() < 17) + wrq->u.data.length = BssLen; + else + { + if (BssLen > wrq->u.data.length) + { + os_free_mem(NULL, pBssidList); + return -E2BIG; + } + else + wrq->u.data.length = BssLen; + } + + Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen); + os_free_mem(NULL, pBssidList); + break; + case OID_802_3_CURRENT_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); + break; + case OID_GEN_MEDIA_CONNECT_STATUS: + if (pAd->IndicateMediaState == NdisMediaStateConnected) + MediaState = NdisMediaStateConnected; + else + MediaState = NdisMediaStateDisconnected; + + wrq->u.data.length = sizeof(NDIS_MEDIA_STATE); + Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length); + break; + case OID_802_11_BSSID: + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + { + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS)); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n")); + Status = -ENOTCONN; + } + break; + case OID_802_11_SSID: + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + Ssid.SsidLength = pAd->CommonCfg.SsidLen; + memcpy(Ssid.Ssid, pAd->CommonCfg.Ssid, Ssid.SsidLength); + wrq->u.data.length = sizeof(NDIS_802_11_SSID); + Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid)); + break; + case RT_OID_802_11_QUERY_LINK_STATUS: + os_alloc_mem(pAd, (UCHAR **)&pLinkStatus, sizeof(RT_802_11_LINK_STATUS)); + if (pLinkStatus) + { + pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAd->CommonCfg.TxRate]; /* unit : 500 kbps */ + pLinkStatus->ChannelQuality = pAd->Mlme.ChannelQuality; + pLinkStatus->RxByteCount = pAd->RalinkCounters.ReceivedByteCount; + pLinkStatus->TxByteCount = pAd->RalinkCounters.TransmittedByteCount; + pLinkStatus->CentralChannel = pAd->CommonCfg.CentralChannel; + wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS); + Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length); + os_free_mem(NULL, pLinkStatus); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_802_11_CONFIGURATION: + os_alloc_mem(pAd, (UCHAR **)&pConfiguration, sizeof(NDIS_802_11_CONFIGURATION)); + if (pConfiguration) + { + pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION); + pConfiguration->BeaconPeriod = pAd->CommonCfg.BeaconPeriod; + pConfiguration->ATIMWindow = pAd->StaActive.AtimWin; + MAP_CHANNEL_ID_TO_KHZ(pAd->CommonCfg.Channel, pConfiguration->DSConfig); + wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION); + Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n", + pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAd->CommonCfg.Channel)); + os_free_mem(NULL, pConfiguration); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_802_11_SNR_0: + if ((pAd->StaCfg.LastSNR0 > 0)) + { + ulInfo = ConvertToSnr(pAd, pAd->StaCfg.LastSNR0); + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo)); + } + else + Status = -EFAULT; + break; + case RT_OID_802_11_SNR_1: + if ((pAd->Antenna.field.RxPath > 1) && + (pAd->StaCfg.LastSNR1 > 0)) + { + ulInfo = ConvertToSnr(pAd, pAd->StaCfg.LastSNR1); + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo)); + } + else + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAd->StaCfg.LastSNR1=%d)\n",pAd->StaCfg.LastSNR1)); + break; + +#ifdef DOT11N_SS3_SUPPORT + case RT_OID_802_11_SNR_2: + if ((pAd->Antenna.field.RxPath > 2) && + (pAd->StaCfg.LastSNR2 > 0)) + { + ulInfo = ConvertToSnr(pAd, pAd->StaCfg.LastSNR2); + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_2(0x=%lx)\n",ulInfo)); + } + else + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_2(pAd->StaCfg.LastSNR2=%d)\n",pAd->StaCfg.LastSNR2)); + break; +#endif /* DOT11N_SS3_SUPPORT */ + + + case OID_802_11_RSSI_TRIGGER: + ulInfo = pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo)); + break; + case OID_802_11_RSSI: + case RT_OID_802_11_RSSI: + ulInfo = pAd->StaCfg.RssiSample.LastRssi0; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_RSSI_1: + ulInfo = pAd->StaCfg.RssiSample.LastRssi1; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_RSSI_2: + ulInfo = pAd->StaCfg.RssiSample.LastRssi2; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case OID_802_11_STATISTICS: + os_alloc_mem(pAd, (UCHAR **)&pStatistics, sizeof(NDIS_802_11_STATISTICS)); + if (pStatistics) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n")); + /* add the most up-to-date h/w raw counters into software counters */ + NICUpdateRawCounters(pAd); + + /* Sanity check for calculation of sucessful count */ + if (pAd->WlanCounters.TransmittedFragmentCount.QuadPart < pAd->WlanCounters.RetryCount.QuadPart) + pAd->WlanCounters.TransmittedFragmentCount.QuadPart = pAd->WlanCounters.RetryCount.QuadPart; + + pStatistics->TransmittedFragmentCount.QuadPart = pAd->WlanCounters.TransmittedFragmentCount.QuadPart + pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart;; + pStatistics->MulticastTransmittedFrameCount.QuadPart = pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart; + pStatistics->FailedCount.QuadPart = pAd->WlanCounters.FailedCount.QuadPart; + pStatistics->RetryCount.QuadPart = pAd->WlanCounters.RetryCount.QuadPart; + pStatistics->MultipleRetryCount.QuadPart = pAd->WlanCounters.MultipleRetryCount.QuadPart; + pStatistics->RTSSuccessCount.QuadPart = pAd->WlanCounters.RTSSuccessCount.QuadPart; + pStatistics->RTSFailureCount.QuadPart = pAd->WlanCounters.RTSFailureCount.QuadPart; + pStatistics->ACKFailureCount.QuadPart = pAd->WlanCounters.ACKFailureCount.QuadPart; + pStatistics->FrameDuplicateCount.QuadPart = pAd->WlanCounters.FrameDuplicateCount.QuadPart; + pStatistics->ReceivedFragmentCount.QuadPart = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + pStatistics->MulticastReceivedFrameCount.QuadPart = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; +#ifdef DBG + pStatistics->FCSErrorCount = pAd->RalinkCounters.RealFcsErrCount; +#else + pStatistics->FCSErrorCount.QuadPart = pAd->WlanCounters.FCSErrorCount.QuadPart; + pStatistics->FrameDuplicateCount.u.LowPart = pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100; +#endif + pStatistics->TransmittedFrameCount.QuadPart = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; + pStatistics->WEPUndecryptableCount.QuadPart = pAd->WlanCounters.WEPUndecryptableCount.QuadPart; + wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS); + Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length); + os_free_mem(NULL, pStatistics); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(mem alloc failed)\n")); + Status = -EFAULT; + } + break; + +#ifdef TXBF_SUPPORT + case RT_OID_802_11_QUERY_TXBF_TABLE: + if (pAd->chipCap.FlgHwTxBfCap) + { + INT i; + RT_802_11_TXBF_TABLE *pMacTab; + + pMacTab = (RT_802_11_TXBF_TABLE *)kmalloc(sizeof(RT_802_11_TXBF_TABLE), MEM_ALLOC_FLAG); + if (pMacTab) + { + pMacTab->Num = 0; + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + NdisMoveMemory(&pMacTab->Entry[pMacTab->Num], &pAd->MacTab.Content[i].TxBFCounters, sizeof(RT_COUNTER_TXBF)); + pMacTab->Num++; + } + } + + wrq->u.data.length = sizeof(RT_802_11_TXBF_TABLE); + Status = copy_to_user(wrq->u.data.pointer, pMacTab, wrq->u.data.length); + os_free_mem(NULL, pMacTab); + } + else + { + Status = -EFAULT; + } + } + else + Status = -EFAULT; + + break; +#endif /* TXBF_SUPPORT */ + + case OID_GEN_RCV_OK: + ulInfo = pAd->Counters8023.GoodReceives; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case OID_GEN_RCV_NO_BUFFER: + ulInfo = pAd->Counters8023.RxNoBuffer; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_PHY_MODE: + ulInfo = (ULONG)pAd->CommonCfg.PhyMode; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo)); + break; + case RT_OID_802_11_STA_CONFIG: + os_alloc_mem(pAd, (UCHAR **)&pStaConfig, sizeof(RT_802_11_STA_CONFIG)); + if (pStaConfig) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n")); + pStaConfig->EnableTxBurst = pAd->CommonCfg.bEnableTxBurst; + pStaConfig->EnableTurboRate = 0; + pStaConfig->UseBGProtection = pAd->CommonCfg.UseBGProtection; + pStaConfig->UseShortSlotTime = pAd->CommonCfg.bUseShortSlotTime; + /*pStaConfig->AdhocMode = pAd->StaCfg.AdhocMode; */ + pStaConfig->HwRadioStatus = (pAd->StaCfg.bHwRadio == TRUE) ? 1 : 0; + pStaConfig->Rsv1 = 0; + pStaConfig->SystemErrorBitmap = pAd->SystemErrorBitmap; + wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG); + Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length); + os_free_mem(NULL, pStaConfig); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(mem alloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_802_11_RTS_THRESHOLD: + RtsThresh = pAd->CommonCfg.RtsThreshold; + wrq->u.data.length = sizeof(RtsThresh); + Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh)); + break; + case OID_802_11_FRAGMENTATION_THRESHOLD: + FragThresh = pAd->CommonCfg.FragmentThreshold; + if (pAd->CommonCfg.bUseZeroToDisableFragment == TRUE) + FragThresh = 0; + wrq->u.data.length = sizeof(FragThresh); + Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh)); + break; + case OID_802_11_POWER_MODE: + PowerMode = pAd->StaCfg.WindowsPowerMode; + wrq->u.data.length = sizeof(PowerMode); + Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode)); + break; + case RT_OID_802_11_RADIO: + RadioState = (BOOLEAN) pAd->StaCfg.bSwRadio; + wrq->u.data.length = sizeof(RadioState); + Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState)); + break; + case OID_802_11_INFRASTRUCTURE_MODE: + if (pAd->StaCfg.BssType == BSS_ADHOC) + BssType = Ndis802_11IBSS; + else if (pAd->StaCfg.BssType == BSS_INFRA) + BssType = Ndis802_11Infrastructure; + else if (pAd->StaCfg.BssType == BSS_MONITOR) + BssType = Ndis802_11Monitor; + else + BssType = Ndis802_11AutoUnknown; + + wrq->u.data.length = sizeof(BssType); + Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType)); + break; + case RT_OID_802_11_PREAMBLE: + PreamType = pAd->CommonCfg.TxPreamble; + wrq->u.data.length = sizeof(PreamType); + Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType)); + break; + case OID_802_11_AUTHENTICATION_MODE: + AuthMode = pAd->StaCfg.wdev.AuthMode; + wrq->u.data.length = sizeof(AuthMode); + Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode)); + break; + case OID_802_11_WEP_STATUS: + WepStatus = pAd->StaCfg.wdev.WepStatus; + wrq->u.data.length = sizeof(WepStatus); + Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus)); + break; + case OID_802_11_TX_POWER_LEVEL: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.TxPower, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAd->CommonCfg.TxPower)); + break; + case RT_OID_802_11_TX_POWER_LEVEL_1: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.TxPowerPercentage, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); + break; + case OID_802_11_NETWORK_TYPES_SUPPORTED: + if ((pAd->RfIcType == RFIC_2850) || + (pAd->RfIcType == RFIC_2750) || + (pAd->RfIcType == RFIC_3052) || + (pAd->RfIcType == RFIC_3053) || + (pAd->RfIcType == RFIC_2853) || + (pAd->RfIcType == RFIC_3853) || + (pAd->RfIcType == RFIC_5592)) + { + NetworkTypeList[0] = 3; /* NumberOfItems = 3 */ + NetworkTypeList[1] = Ndis802_11DS; /* NetworkType[1] = 11b */ + NetworkTypeList[2] = Ndis802_11OFDM24; /* NetworkType[2] = 11g */ + NetworkTypeList[3] = Ndis802_11OFDM5; /* NetworkType[3] = 11a */ + wrq->u.data.length = 16; + Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); + } + else + { + NetworkTypeList[0] = 2; /* NumberOfItems = 2 */ + NetworkTypeList[1] = Ndis802_11DS; /* NetworkType[1] = 11b */ + NetworkTypeList[2] = Ndis802_11OFDM24; /* NetworkType[2] = 11g */ + wrq->u.data.length = 12; + Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n")); + break; + case OID_802_11_NETWORK_TYPE_IN_USE: + wrq->u.data.length = sizeof(ULONG); + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_A)) + ulInfo = Ndis802_11OFDM5; + else if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, (WMODE_G | WMODE_B)) || + WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_G)) + ulInfo = Ndis802_11OFDM24; + else + ulInfo = Ndis802_11DS; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_LAST_RX_RATE: + ulInfo = (ULONG)pAd->LastRxRate; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_LAST_TX_RATE: + ulInfo = (ULONG)pAd->LastTxRate; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_MAP_REAL_RX_RATE: + RateValue=0; + HTPhyMode.word =(USHORT) pAd->LastRxRate; + RtmpDrvRateGet(pAd, HTPhyMode.field.MODE, HTPhyMode.field.ShortGI, + HTPhyMode.field.BW,HTPhyMode.field.MCS, + newRateGetAntenna(HTPhyMode.field.MCS, HTPhyMode.field.MODE),&RateValue); + RateValue /= 500000; + RateValue /= 2; + + wrq->u.data.length = sizeof(RateValue); + Status = copy_to_user(wrq->u.data.pointer, &RateValue, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", RateValue)); + break; + case RT_OID_802_11_QUERY_MAP_REAL_TX_RATE: + RateValue=0; + HTPhyMode.word = (USHORT)pAd->LastTxRate; + RtmpDrvRateGet(pAd, HTPhyMode.field.MODE, HTPhyMode.field.ShortGI, + HTPhyMode.field.BW,HTPhyMode.field.MCS, + newRateGetAntenna(HTPhyMode.field.MCS, HTPhyMode.field.MODE),&RateValue); + RateValue /= 500000; + RateValue /= 2; + wrq->u.data.length = sizeof(RateValue); + Status = copy_to_user(wrq->u.data.pointer, &RateValue, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%ld)\n", RateValue)); + break; + case RT_OID_802_11_QUERY_TX_PHYMODE: + ulInfo = (ULONG)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_TX_PHYMODE (=%lx)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_EEPROM_VERSION: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAd->EepromVersion, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_FIRMWARE_VERSION: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAd->FirmwareVersion, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_NOISE_LEVEL: + { + UCHAR noise = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2) - + RTMPMinSnr(pAd, pAd->StaCfg.RssiSample.AvgSnr0, + pAd->StaCfg.RssiSample.AvgSnr1); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &noise, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", noise)); + } + break; + case RT_OID_802_11_EXTRA_INFO: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAd->ExtraInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAd->ExtraInfo)); + break; + case RT_OID_WE_VERSION_COMPILED: + wrq->u.data.length = sizeof(UINT); + we_version_compiled = RtmpOsWirelessExtVerGet(); + Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_APSD_SETTING: + apsd = (pAd->StaCfg.UapsdInfo.bAPSDCapable | (pAd->CommonCfg.bAPSDAC_BE << 1) | (pAd->CommonCfg.bAPSDAC_BK << 2) + | (pAd->CommonCfg.bAPSDAC_VI << 3) | (pAd->CommonCfg.bAPSDAC_VO << 4) | (pAd->CommonCfg.MaxSPLength << 5)); + + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n", + apsd,pAd->StaCfg.UapsdInfo.bAPSDCapable,pAd->CommonCfg.bAPSDAC_BE,pAd->CommonCfg.bAPSDAC_BK,pAd->CommonCfg.bAPSDAC_VI,pAd->CommonCfg.bAPSDAC_VO,pAd->CommonCfg.MaxSPLength)); + break; + case RT_OID_802_11_QUERY_APSD_PSM: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAd->CommonCfg.bAPSDForcePowerSave)); + break; + case RT_OID_802_11_QUERY_WMM: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bWmmCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n", pAd->CommonCfg.bWmmCapable)); + break; + + +#ifdef WPA_SUPPLICANT_SUPPORT + case RT_OID_NEW_DRIVER: + { + UCHAR enabled = 1; + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled)); + } + break; + case RT_OID_WPA_SUPPLICANT_SUPPORT: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, + &pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP, + wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP)); + break; +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + case RT_OID_WSC_QUERY_STATUS: + wrq->u.data.length = sizeof(INT); + if (copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.WscControl.WscStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_STATUS (=%d)\n", pAd->StaCfg.WscControl.WscStatus)); + break; + + case RT_OID_WSC_PIN_CODE: + wrq->u.data.length = sizeof(UINT); + WscPinCode = pAd->StaCfg.WscControl.WscEnrolleePinCode; + + if (copy_to_user(wrq->u.data.pointer, &WscPinCode, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_PIN_CODE (=%d)\n", WscPinCode)); + break; + + case RT_OID_WSC_QUERY_DEFAULT_PROFILE: + wrq->u.data.length = sizeof(WSC_PROFILE); + os_alloc_mem(pAd, (UCHAR **)&pProfile, sizeof(WSC_PROFILE)); + if (pProfile == NULL) + { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_WSC_QUERY_DEFAULT_PROFILE fail!\n")); + break; + } + + RTMPZeroMemory(pProfile, sizeof(WSC_PROFILE)); + WscCreateProfileFromCfg(pAd, STA_MODE, &pAd->StaCfg.WscControl, pProfile); + if (copy_to_user(wrq->u.data.pointer, pProfile, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WSC Profile:\n")); + DBGPRINT(RT_DEBUG_TRACE, ("SSID = %s\n", pProfile->Profile[0].SSID.Ssid)); + DBGPRINT(RT_DEBUG_TRACE, ("AuthType = %s\n", WscGetAuthTypeStr(pProfile->Profile[0].AuthType))); + DBGPRINT(RT_DEBUG_TRACE, ("EncrpType = %s\n", WscGetEncryTypeStr(pProfile->Profile[0].EncrType))); + + if (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_WEP) + { + DBGPRINT(RT_DEBUG_TRACE, ("WEP Key = %s\n", pProfile->Profile[0].Key)); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKey ID = %d\n", pProfile->Profile[0].KeyIndex)); + } + else if ((pProfile->Profile[0].EncrType == WSC_ENCRTYPE_TKIP) || (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_AES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PassPhrase Key = %s\n", pProfile->Profile[0].Key)); + pProfile->Profile[0].KeyIndex = 1; + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + + os_free_mem(NULL, pProfile); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_DEFAULT_PROFILE \n")); + break; + case RT_OID_802_11_WSC_QUERY_PROFILE: + wrq->u.data.length = sizeof(WSC_PROFILE); + os_alloc_mem(pAd, (UCHAR **)&pProfile, sizeof(WSC_PROFILE)); + if (pProfile == NULL) + { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_WSC_QUERY_PROFILE fail!\n")); + break; + } + + RTMPZeroMemory(pProfile, sizeof(WSC_PROFILE)); + NdisMoveMemory(pProfile, &pAd->StaCfg.WscControl.WscProfile, sizeof(WSC_PROFILE)); + if ((pProfile->Profile[0].AuthType == WSC_AUTHTYPE_OPEN) && (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_NONE)) + { + pProfile->Profile[0].KeyLength = 0; + NdisZeroMemory(pProfile->Profile[0].Key, 64); + } + if (copy_to_user(wrq->u.data.pointer, pProfile, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WSC Profile:\n")); + DBGPRINT(RT_DEBUG_TRACE, ("SSID = %s\n", pProfile->Profile[0].SSID.Ssid)); + DBGPRINT(RT_DEBUG_TRACE, ("AuthType = %s\n", WscGetAuthTypeStr(pProfile->Profile[0].AuthType))); + DBGPRINT(RT_DEBUG_TRACE, ("EncrpType = %s\n", WscGetEncryTypeStr(pProfile->Profile[0].EncrType))); + + if (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_WEP) + { + DBGPRINT(RT_DEBUG_TRACE, ("WEP Key = %s\n", pProfile->Profile[0].Key)); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKey ID = %d\n", pProfile->Profile[0].KeyIndex)); + } + else if ((pProfile->Profile[0].EncrType == WSC_ENCRTYPE_TKIP) || (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_AES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PassPhrase Key = %s\n", pProfile->Profile[0].Key)); + pProfile->Profile[0].KeyIndex = 1; + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + + os_free_mem(NULL, pProfile); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WSC_QUERY_PROFILE \n")); + break; + + case RT_OID_WSC_UUID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_UUID \n")); + wrq->u.data.length = UUID_LEN_STR; + if (copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.WscControl.Wsc_Uuid_Str[0], UUID_LEN_STR)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_MAC_ADDRESS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_MAC_ADDRESS \n")); + wrq->u.data.length = MAC_ADDR_LEN; + if (copy_to_user(wrq->u.data.pointer, pAd->CurrentAddress, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* WSC_STA_SUPPORT */ + case RT_OID_DRIVER_DEVICE_NAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n")); + wrq->u.data.length = 16; + if (copy_to_user(wrq->u.data.pointer, pAd->StaCfg.dev_name, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_802_11_QUERY_HT_PHYMODE: + os_alloc_mem(pAd, (UCHAR **)&pHTPhyMode, sizeof(OID_SET_HT_PHYMODE)); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = pAd->CommonCfg.PhyMode; + pHTPhyMode->HtMode = (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE; + pHTPhyMode->BW = (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW; + pHTPhyMode->MCS= (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS; + pHTPhyMode->SHORTGI= (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI; + pHTPhyMode->STBC= (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC; + + pHTPhyMode->ExtOffset = ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE)); + wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); + if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); + DBGPRINT(RT_DEBUG_TRACE, (" %s(): (.word = %x )\n", + __FUNCTION__, pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); + os_free_mem(NULL, pHTPhyMode); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(mem alloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_802_11_COUNTRY_REGION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n")); + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAd->CommonCfg.CountryRegionForABand; + ulInfo = (ulInfo << 8)|(pAd->CommonCfg.CountryRegion); + if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_802_11_QUERY_DAT_HT_PHYMODE: + os_alloc_mem(pAd, (UCHAR **)&pHTPhyMode, sizeof(OID_SET_HT_PHYMODE)); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = wmode_2_cfgmode(pAd->CommonCfg.PhyMode); + pHTPhyMode->HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; + pHTPhyMode->BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; + pHTPhyMode->MCS= (UCHAR)pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS; + pHTPhyMode->SHORTGI= (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; + pHTPhyMode->STBC= (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; + + wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); + if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): (.word = %x )\n", + __FUNCTION__, pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); + os_free_mem(NULL, pHTPhyMode); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(mem alloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT: + wrq->u.data.length = sizeof(UCHAR); + i = 0; +#ifdef MULTIPLE_CARD_SUPPORT + i = 1; +#endif /* MULTIPLE_CARD_SUPPORT */ + if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i)); + break; +#ifdef SNMP_SUPPORT + case RT_OID_802_11_MAC_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREROUI: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n")); + wrq->u.data.length = ManufacturerOUI_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTURERNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case RT_OID_802_11_RESOURCETYPEIDNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n")); + wrq->u.data.length = strlen(ResourceTypeIdName); + Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length); + break; + + case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n")); + ulInfo = 1; /* 1 is support wep else 2 is not support. */ + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + + case RT_OID_802_11_POWERMANAGEMENTMODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n")); + if (pAd->StaCfg.Psm == PSMP_ACTION) + ulInfo = 1; /* 1 is power active else 2 is power save. */ + else + ulInfo = 2; + + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n")); + pKeyIdxValue = wrq->u.data.pointer; + DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx)); + valueLen = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen; + NdisMoveMemory(pKeyIdxValue->Value, + &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + valueLen); + pKeyIdxValue->Value[valueLen]='\0'; + + wrq->u.data.length = sizeof(DefaultKeyIdxValue); + + Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", + pAd->StaCfg.DefaultKeyId, + wrq->u.data.length, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, + pAd->SharedKey[BSS0][0].Key[0], + pAd->SharedKey[BSS0][1].Key[0], + pAd->SharedKey[BSS0][2].Key[0], + pAd->SharedKey[BSS0][3].Key[0])); + break; + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.DefaultKeyId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAd->StaCfg.DefaultKeyId)); + break; + + case RT_OID_802_11_WEPKEYMAPPINGLENGTH: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, + &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, + wrq->u.data.length); + break; + + case OID_802_11_SHORTRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + ShortRetryLimit = AsicGetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_SHORT); + DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld\n", ShortRetryLimit)); + Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length); + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + LongRetryLimit = AsicGetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_LONG); + DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld\n", LongRetryLimit)); + Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length); + break; + + case RT_OID_802_11_PRODUCTID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); + +#ifdef RTMP_MAC_PCI + { + + USHORT device_id; + if (((POS_COOKIE)pAd->OS_Cookie)->pci_dev != NULL) + pci_read_config_word(((POS_COOKIE)pAd->OS_Cookie)->pci_dev, PCI_DEVICE_ID, &device_id); + else + DBGPRINT(RT_DEBUG_TRACE, (" pci_dev = NULL\n")); + snprintf((PSTRING)tmp, sizeof(tmp), "%04x %04x\n", NIC_PCI_VENDOR_ID, device_id); + } +#endif /* RTMP_MAC_PCI */ + wrq->u.data.length = strlen((PSTRING)tmp); + Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n")); + wrq->u.data.length = sizeof(UCHAR); + DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAd->CommonCfg.Channel)); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Channel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; +#endif /*SNMP_SUPPORT */ + + case OID_802_11_BUILD_CHANNEL_EX: + { + UCHAR value; + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n")); + wrq->u.data.length = sizeof(UCHAR); +#ifdef EXT_BUILD_CHANNEL_LIST + DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n")); + value = 1; +#else + DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n")); + value = 0; +#endif /* EXT_BUILD_CHANNEL_LIST */ + Status = copy_to_user(wrq->u.data.pointer, &value, 1); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + } + break; + + case OID_802_11_GET_CH_LIST: + { + PRT_CHANNEL_LIST_INFO pChListBuf; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n")); + if (pAd->ChannelListNum == 0) + { + wrq->u.data.length = 0; + break; + } + + os_alloc_mem(pAd, (UCHAR **)&pChListBuf, sizeof(RT_CHANNEL_LIST_INFO)); + if (pChListBuf == NULL) + { + wrq->u.data.length = 0; + break; + } + + pChListBuf->ChannelListNum = pAd->ChannelListNum; + for (i = 0; i < pChListBuf->ChannelListNum; i++) + pChListBuf->ChannelList[i] = pAd->ChannelList[i].Channel; + + wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO); + Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO)); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + + if (pChListBuf) + os_free_mem(NULL, pChListBuf); + } + break; + + case OID_802_11_GET_COUNTRY_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n")); + wrq->u.data.length = 2; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.CountryCode, 2); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; + +#ifdef EXT_BUILD_CHANNEL_LIST + case OID_802_11_GET_CHANNEL_GEOGRAPHY: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n")); + wrq->u.data.length = 1; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Geography, 1); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + + +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_QUERY_DLS: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bDLSCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAd->CommonCfg.bDLSCapable)); + break; + + case RT_OID_802_11_QUERY_DLS_PARAM: + { + PRT_802_11_DLS_INFO pDlsInfo; + os_alloc_mem(pAd, (UCHAR **)&pDlsInfo, sizeof(RT_802_11_DLS_INFO)); + if (pDlsInfo == NULL) + break; + + for (i=0; iEntry[i], &pAd->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI)); + } + + pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY; + wrq->u.data.length = sizeof(RT_802_11_DLS_INFO); + Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n")); + + if (pDlsInfo) + os_free_mem(NULL, pDlsInfo); + } + break; +#endif /* QOS_DLS_SUPPORT */ +#ifdef WAPI_SUPPORT + case OID_802_11_WAPI_CONFIGURATION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get WAPI Configuration(%d)\n", sizeof(WAPI_CONF))); + RTMPIoctlQueryWapiConf(pAd, wrq); + break; + case OID_802_11_WAPI_IE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WAPI_IE\n")); + if (wrq->u.data.length != sizeof(WAPI_WIE_STRUCT)) + Status = -EINVAL; + else + { + WAPI_WIE_STRUCT wapi_ie; + MAC_TABLE_ENTRY *pEntry; + + NdisZeroMemory(&wapi_ie, sizeof(WAPI_WIE_STRUCT)); + NdisMoveMemory(wapi_ie.addr, wrq->u.data.pointer, MAC_ADDR_LEN); + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + if ((NdisEqualMemory(pEntry->Addr, wapi_ie.addr, MAC_ADDR_LEN)) && + (pEntry->RSNIE_Len > 0)) + { + wapi_ie.wie_len = pEntry->RSNIE_Len; + NdisMoveMemory(wapi_ie.wie, pEntry->RSN_IE, pEntry->RSNIE_Len); + } + + if (copy_to_user(wrq->u.data.pointer, &wapi_ie, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + break; +#endif /* WAPI_SUPPORT */ + +#ifdef XLINK_SUPPORT + case OID_802_11_SET_PSPXLINK_MODE: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.PSPXlink, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SET_PSPXLINK_MODE(=%d)\n", pAd->StaCfg.PSPXlink)); + break; +#endif /* XLINK_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef WFD_SUPPORT + /* + * Query WFD TDLS connection status + * Value: + * 0: TDLS connecting or no link + * 4: TDLS connected + * 6: Peer PC (Preferred Connectivity) bit of WFD device is P2P + * 7: TDLS weak security + */ + case RT_OID_802_11_QUERY_WFD_TDLS_CONNECT_STATUS: + { + INT i; + UCHAR bFound = CONNECTING_OR_NO_LINK; + + if (pAd->StaCfg.WfdCfg.PeerPC == WFD_PC_P2P) + { + bFound = WFD_PEER_PC_P2P; + pAd->StaCfg.WfdCfg.PeerPC = WFD_PC_TDLS; + DBGPRINT(RT_DEBUG_ERROR, ("RT_OID_802_11_QUERY_WFD_TDLS_CONNECT_STATUS::Peer WFD PC is P2P!\n")); + } + else if (pAd->StaCfg.WfdCfg.TdlsSecurity == WFD_TDLS_WEAK_SECURITY) + { + bFound = WFD_PEER_TDLS_WEAK_SECURITY; + pAd->StaCfg.WfdCfg.TdlsSecurity = WFD_TDLS_STRONG_SECURITY; + DBGPRINT(RT_DEBUG_ERROR, ("RT_OID_802_11_QUERY_WFD_TDLS_CONNECT_STATUS::TDLS weak security!\n")); + } + else + { + for (i=0; iStaCfg.TdlsInfo.TDLSEntry[i].Valid) && (pAd->StaCfg.TdlsInfo.TDLSEntry[i].Status == TDLS_MODE_CONNECTED)) + break; + } + if (i == MAX_NUM_OF_TDLS_ENTRY) + bFound = CONNECTING_OR_NO_LINK; + else + bFound = TDLS_LINKED; + if (bFound == TDLS_LINKED) + DBGPRINT(RT_DEBUG_ERROR, ("RT_OID_802_11_QUERY_WFD_TDLS_CONNECT_STATUS:: TDLS Connected!\n")); + } + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &bFound, wrq->u.data.length); + } + break; + + /* + * Query peer WFD TDLS IP address + * Field | Size (octets) | Value | Description + * --------------------------------------------------------------------------------------------- + * Version | 1 | 1 | Version 1: IPv4 address field follows + * IPv4 address | 4 | (IP address) | This field is the IPv4 host address of the STA + */ + case RT_OID_802_11_QUERY_WFD_TDLS_PEER_IP_ADDR: + { + INT i; + UCHAR peer_ip_addr[5] = {0}; + for (i=0; iStaCfg.TdlsInfo.TDLSEntry[i].Valid) && (pAd->StaCfg.TdlsInfo.TDLSEntry[i].Status == TDLS_MODE_CONNECTED)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Peer IP Addr = %d.%d.%d.%d\n", + pAd->StaCfg.TdlsInfo.TDLSEntry[i].WfdEntryInfo.wfd_serv_disc_query_info.wfd_local_ip_ie[1], + pAd->StaCfg.TdlsInfo.TDLSEntry[i].WfdEntryInfo.wfd_serv_disc_query_info.wfd_local_ip_ie[2], + pAd->StaCfg.TdlsInfo.TDLSEntry[i].WfdEntryInfo.wfd_serv_disc_query_info.wfd_local_ip_ie[3], + pAd->StaCfg.TdlsInfo.TDLSEntry[i].WfdEntryInfo.wfd_serv_disc_query_info.wfd_local_ip_ie[4])); + RTMPMoveMemory(&peer_ip_addr, &pAd->StaCfg.TdlsInfo.TDLSEntry[i].WfdEntryInfo.wfd_serv_disc_query_info.wfd_local_ip_ie, sizeof(peer_ip_addr)); + break; + } + } + wrq->u.data.length = sizeof(peer_ip_addr); + Status = copy_to_user(wrq->u.data.pointer, &peer_ip_addr, wrq->u.data.length); + } + break; +#endif /* WFD_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + case OID_802_11_QUERY_WirelessMode: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.PhyMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_QUERY_WirelessMode(=%d)\n", pAd->CommonCfg.PhyMode)); + break; +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + case OID_802_11R_SUPPORT: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.Dot11RCommInfo.bFtSupport, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11R_SUPPORT(=%d)\n", pAd->StaCfg.Dot11RCommInfo.bFtSupport)); + break; + + case OID_802_11R_MDID: + wrq->u.data.length = 2; + memset(wrq->u.data.pointer,0x00,2); + Status = copy_to_user(wrq->u.data.pointer, pAd->StaCfg.Dot11RCommInfo.MdIeInfo.MdId, 2); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11R_MDID(=%x%x)\n", + pAd->StaCfg.Dot11RCommInfo.MdIeInfo.MdId[0], + pAd->StaCfg.Dot11RCommInfo.MdIeInfo.MdId[1])); + break; +#endif /* DOT11R_FT_SUPPORT */ + + +#ifdef IWSC_SUPPORT + case RT_OID_IWSC_SELF_IPV4: + if (wrq->u.data.length != sizeof(UINT32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query Failed::RT_OID_IWSC_SELF_IPV4(=%d)\n", wrq->u.data.length)); + Status = -EINVAL; + } + else + { + Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.IWscInfo.SelfIpv4Addr, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_IWSC_SELF_IPV4(=0x%08x), Status = %d\n", + pAd->StaCfg.IWscInfo.SelfIpv4Addr, Status)); + } + break; + + case RT_OID_IWSC_REGISTRAR_IPV4: + if (wrq->u.data.length != sizeof(UINT32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query Failed::RT_OID_IWSC_REGISTRAR_IPV4(=%d)\n", wrq->u.data.length)); + Status = -EINVAL; + } + else + { + Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.IWscInfo.RegIpv4Addr, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_IWSC_REGISTRAR_IPV4(=0x%08x), Status = %d\n", + pAd->StaCfg.IWscInfo.RegIpv4Addr, Status)); + } + break; + + case RT_OID_IWSC_SMPBC_ENROLLEE_COUNT: + if (wrq->u.data.length != sizeof(UINT8)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query Failed::RT_OID_IWSC_SMPBC_ENROLLEE_COUNT(=%d)\n", wrq->u.data.length)); + Status = -EINVAL; + } + else + { + Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.IWscInfo.SmpbcEnrolleeCount, sizeof(UINT8)); + DBGPRINT(RT_DEBUG_INFO, ("Query::RT_OID_IWSC_SMPBC_ENROLLEE_COUNT(=0x%08x), Status = %d\n", + pAd->StaCfg.IWscInfo.SmpbcEnrolleeCount, Status)); + } + break; +#endif /* IWSC_SUPPORT */ +#ifdef CONFIG_WIFI_TEST + case OID_WIFI_TEST_BBP: + + break; + case OID_WIFI_TEST_BBP32: + { + UINT32 Index; + UINT32 j = 0; + struct bbp32_info *Info; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, wrq->u.data.length); + + if (!pBuf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(pBuf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct bbp32_info *)pBuf; + + printk("Info->bbp_start = %x\n", Info->bbp_start); + printk("Info->bbp_end = %x\n", Info->bbp_end); + + + for (Index = Info->bbp_start; Index <= Info->bbp_end; Index += 4) + { + UINT32 Value; + RTMP_IO_READ32(pAd, Index + pAd->chipCap.BBPMemMapOffset, &Value); + printk("Offset = %x\n", Index + pAd->chipCap.BBPMemMapOffset); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->bbp_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, pBuf, wrq->u.data.length); + + os_free_mem(NULL, pBuf); + } + + + break; + case OID_WIFI_TEST_RF: + + break; +#ifdef RLT_RF + case OID_WIFI_TEST_RF_BANK: + { + UINT16 Index; + UINT16 j = 0; + struct rf_bank_info *Info; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, wrq->u.data.length); + + if (!pBuf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(pBuf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct rf_bank_info *)pBuf; + + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_bank = %x\n", Info->rf_bank)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + + for (Index = Info->rf_start; Index <= Info->rf_end; Index ++) + { + UINT8 Value; + rlt_rf_read(pAd, Info->rf_bank, Index, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Offset = %x\n", Index)); + DBGPRINT(RT_DEBUG_OFF, ("Value = %x\n", Value)); + NdisMoveMemory(Info->rf_value + j, &Value, 1); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, pBuf, wrq->u.data.length); + + os_free_mem(NULL, pBuf); + } + break; +#endif +#ifdef MT_RF + case OID_WIFI_TEST_RF_INDEX: + { + UINT16 Index; + UINT16 j = 0; + struct rf_index_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct rf_bank_info *)buf; + + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_index = %x\n", Info->rf_index)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + + for (Index = Info->rf_start; Index <= Info->rf_end; Index += 4) + { + UINT32 Value; + mt_rf_read(pAd, Info->rf_index, Index, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Offset = %x\n", Index)); + DBGPRINT(RT_DEBUG_OFF, ("Value = %x\n", Value)); + NdisMoveMemory(Info->rf_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif + case OID_WIFI_TEST_MEM_MAP_INFO: + { + UINT16 Index; + UINT16 j = 0; + struct mem_map_info *Info; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, wrq->u.data.length); + + if (!pBuf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(pBuf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct mem_map_info *)pBuf; + + printk("Info->base = %x\n", Info->base); + printk("Info->mem_map_start = %x\n", Info->mem_map_start); + printk("Info->mem_map_end = %x\n", Info->mem_map_end); + + + for (Index = Info->mem_map_start; Index <= Info->mem_map_end; Index += 4) + { + UINT32 Value; + read_reg(pAd, Info->base, Index, &Value); + NdisMoveMemory(Info->mem_map_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, pBuf, wrq->u.data.length); + + os_free_mem(NULL, pBuf); + } + break; + case OID_WIFI_TEST_E2P: + { + UINT16 Index; + UINT16 j = 0; + struct e2p_info *Info; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, wrq->u.data.length); + + if (!pBuf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(pBuf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct e2p_info *)pBuf; + + printk("Info->e2p_start = %x\n", Info->e2p_start); + printk("Info->e2p_end = %x\n", Info->e2p_end); + + + for (Index = Info->e2p_start; Index <= Info->e2p_end; Index += 2) + { + UINT16 Value; + RT28xx_EEPROM_READ16(pAd, Index, Value); + NdisMoveMemory(Info->e2p_value + j, &Value, 2); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, pBuf, wrq->u.data.length); + + os_free_mem(NULL, pBuf); + } + break; + case OID_WIFI_TEST_MAC: + { + UINT32 Index; + UINT32 j = 0; + struct mac_info *Info; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, wrq->u.data.length); + + if (!pBuf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(pBuf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct mac_info *)pBuf; + + printk("Info->mac_start = %x\n", Info->mac_start); + printk("Info->mac_end = %x\n", Info->mac_end); + + + for (Index = Info->mac_start; Index <= Info->mac_end; Index += 4) + { + UINT32 Value; + RTMP_IO_READ32(pAd, Index + pAd->chipCap.MacMemMapOffset, &Value); + printk("Offset = %x\n", Index + pAd->chipCap.MacMemMapOffset); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->mac_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, pBuf, wrq->u.data.length); + + os_free_mem(NULL, pBuf); + } + break; + case OID_WIFI_TEST_BBP_NUM: + { + struct bbp32_info Info; + Info.bbp_start = pAd->chipCap.BBPStart; + Info.bbp_end = pAd->chipCap.BBPEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_RF_NUM: + + break; +#ifdef RLT_RF + case OID_WIFI_TEST_RF_BANK_OFFSET: + { + struct rf_bank_info *Info; + struct RF_BANK_OFFSET *Offset; + UINT8 Index; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, sizeof(*Info) * pAd->chipCap.RFBankNum); + + if (!pBuf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Info = (struct rf_bank_info *)pBuf; + Offset = pAd->chipCap.RFBankOffset; + + DBGPRINT(RT_DEBUG_OFF, ("pAd->chipCap.RFBankNum = %d\n", pAd->chipCap.RFBankNum)); + + for (Index = 0; Index < pAd->chipCap.RFBankNum; Index++) + { + Info->rf_bank = Offset->RFBankIndex; + Info->rf_start = Offset->RFStart; + Info->rf_end =Offset->RFEnd; + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_bank = %d\n", Info->rf_bank)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + Info++; + Offset++; + } + + wrq->u.data.length = sizeof(*Info) * pAd->chipCap.RFBankNum; + Status = copy_to_user(wrq->u.data.pointer, pBuf, wrq->u.data.length); + + os_free_mem(NULL, pBuf); + } + break; +#endif +#ifdef MT_RF + case OID_WIFI_TEST_RF_INDEX_OFFSET: + { + struct rf_index_info *Info; + struct RF_INDEX_OFFSET *Offset; + UINT8 Index; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, sizeof(*Info) * pAd->chipCap.RFIndexNum); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Info = (struct rf_index_info *)buf; + Offset = pAd->chipCap.RFIndexOffset; + + DBGPRINT(RT_DEBUG_OFF, ("pAd->chipCap.RFIndexNum = %d\n", pAd->chipCap.RFIndexNum)); + + for (Index = 0; Index < pAd->chipCap.RFIndexNum; Index++) + { + Info->rf_index = Offset->RFIndex; + Info->rf_start = Offset->RFStart; + Info->rf_end =Offset->RFEnd; + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_index = %d\n", Info->rf_index)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + Info++; + Offset++; + } + + wrq->u.data.length = sizeof(*Info) * pAd->chipCap.RFIndexNum; + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif + case OID_WIFI_TEST_MAC_NUM: + { + struct mac_info Info; + Info.mac_start = pAd->chipCap.MacStart; + Info.mac_end = pAd->chipCap.MacEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_E2P_NUM: + { + struct e2p_info Info; + Info.e2p_start = pAd->chipCap.E2PStart; + Info.e2p_end = pAd->chipCap.E2PEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_MEM_MAP_NUM: + { + struct mem_map_info Info; + Info.mem_map_start = pAd->chipCap.MemMapStart; + Info.mem_map_end = pAd->chipCap.MemMapEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_PHY_MODE: + { + struct phy_mode_info info; + info.data_phy = pAd->fpga_ctl.rx_data_phy; + info.data_bw = pAd->fpga_ctl.rx_data_bw; + info.data_ldpc = pAd->fpga_ctl.rx_data_ldpc; + info.data_mcs = pAd->fpga_ctl.rx_data_mcs; + info.data_gi = pAd->fpga_ctl.rx_data_gi; + info.data_stbc = pAd->fpga_ctl.rx_data_stbc; + wrq->u.data.length = sizeof(info); + Status = copy_to_user(wrq->u.data.pointer, &info, wrq->u.data.length); + } + break; +#endif + default: + DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + return Status; +} + + +#ifdef DBG +/* + ========================================================================== + Description: + Read / Write MAC + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 mac 0 ==> read MAC where Addr=0x0 + 2.) iwpriv ra0 mac 0=12 ==> write MAC where Addr=0x0, value=12 + ========================================================================== +*/ +VOID RTMPIoctlMAC( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char, value; + INT j = 0, k = 0; + STRING *msg = NULL; + STRING *arg = NULL; + UINT32 macAddr = 0, macValue = 0; + UCHAR temp[16]; + STRING temp2[16]; + INT Status; + BOOLEAN bIsPrintAllMAC = FALSE; + + + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(STRING)*1024); + if (!msg) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelOK; + } + memset(msg, 0x00, 1024); + + os_alloc_mem(NULL, (UCHAR **)&arg, sizeof(STRING)*255); + if (arg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelOK; + } + memset(arg, 0x00, 255); + +DBGPRINT(RT_DEBUG_OFF, ("%s():wrq->u.data.length=%d, wrq->u.data.pointer=%s!\n", __FUNCTION__, wrq->u.data.length, wrq->u.data.pointer)); + if (wrq->u.data.length > 1) + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + arg[254] = 0x00; + sprintf(msg, "\n"); + + /*Parsing Read or Write */ + this_char = arg; + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + if(strlen(this_char) > 4) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto LabelOK; + } + + /* Mac Addr */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + if (macAddr < 0xFFFF) + { + RTMP_IO_READ32(pAd, macAddr, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=0x%04x, MacValue=%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%04x]:%08x ", macAddr , macValue); + } + else + {/*Invalid parametes, so default printk all mac */ + bIsPrintAllMAC = TRUE; + goto next; + } + } + } + else + { /*Write */ + memcpy(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + /* Sanity check */ + if((strlen(this_char) > 4) || strlen(temp2) > 8) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto LabelOK; + } + + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + goto LabelOK; + } + + /*MAC Addr */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + /*MAC value */ + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[8-k+j] = temp2[j]; + } + + while(k < 8) + temp2[7-k++]='0'; + temp2[8]='\0'; + + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 4); + macValue = (temp[0] << 24) + (temp[1] << 16) + (temp[2] << 8) + temp[3]; + + /* debug mode */ + if (macAddr == (HW_DEBUG_SETTING_BASE + 4)) + { + /* 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning */ + if (macValue & 0x000000ff) + { + pAd->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n")); + } + else + { + pAd->BbpTuning.bEnable = FALSE; + RTMP_CHIP_RX_SENSITIVITY_TUNING(pAd); + } + goto LabelOK; + } + + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=0x%04x, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAd, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%04x]:%08x ", macAddr, macValue); + } + } + else + bIsPrintAllMAC = TRUE; +next: + if (bIsPrintAllMAC) + { + UINT32 *pBufMac = NULL, *pBuf; + UINT32 AddrStart = 0x1000, AddrEnd = 0x1800; + UINT32 IdAddr; + + ASSERT((AddrEnd >= AddrStart)); + /* *2 for safe */ + os_alloc_mem(NULL, (UCHAR **)&pBufMac, (AddrEnd - AddrStart)*2); + if (pBufMac != NULL) + { + pBuf = pBufMac; + for(IdAddr=AddrStart; IdAddr<=AddrEnd; IdAddr+=4, pBuf++) + RTMP_IO_READ32(pAd, IdAddr, pBuf); + RtmpDrvAllMacPrint(pAd, pBufMac, AddrStart, AddrEnd, 4); +#if defined(RT65xx) || defined(MT7601) + if (IS_RT65XX(pAd)) { + pBuf = pBufMac; + AddrStart = 0x0; AddrEnd = 0x800; + for(IdAddr=AddrStart; IdAddr<=AddrEnd; IdAddr+=4, pBuf++) + RTMP_IO_READ32(pAd, IdAddr, pBuf); + RtmpDrvAllMacPrint(pAd, pBufMac, AddrStart, AddrEnd, 4); + } +#endif /* defined(RT65xx) || defined(MT7601) */ + os_free_mem(NULL, pBufMac); + } + } + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + /* Copy the information into the user buffer */ + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + +LabelOK: + if (msg != NULL) + os_free_mem(NULL, msg); + if (arg != NULL) + os_free_mem(NULL, arg); + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n")); + return; +} + +/* + ========================================================================== + Description: + Read / Write E2PROM + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 e2p 0 ==> read E2PROM where Addr=0x0 + 2.) iwpriv ra0 e2p 0=1234 ==> write E2PROM where Addr=0x0, value=1234 + ========================================================================== +*/ +VOID RTMPIoctlE2PROM( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char; + PSTRING value; + INT j = 0, k = 0; +/* STRING msg[1024]; */ + STRING *msg = NULL; +/* STRING arg[255]; */ + STRING *arg = NULL; + USHORT eepAddr = 0; + UCHAR temp[16]; + STRING temp2[16]; + USHORT eepValue; + int Status; + BOOLEAN bIsPrintAllE2P = FALSE; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(STRING)*1024); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelOK; + } + os_alloc_mem(NULL, (UCHAR **)&arg, sizeof(STRING)*255); + if (arg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelOK; + } + + memset(msg, 0x00, 1024); + memset(arg, 0x00, 255); + if (wrq->u.data.length > 1) /*No parameters. */ + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + sprintf(msg, "\n"); + arg[254] = 0x00; + + /*Parsing Read or Write */ + this_char = arg; + + + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + + /* Sanity check */ + if(strlen(this_char) > 4) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto LabelOK; + } + + /* E2PROM addr */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + if (eepAddr < 0xFFFF) + { + RT28xx_EEPROM_READ16(pAd, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%04X]:0x%04X ", eepAddr , eepValue); + } + else + {/*Invalid parametes, so default printk all bbp */ + bIsPrintAllE2P = TRUE; + goto next; + } + } + } + else + { /*Write */ + memcpy(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + /* Sanity check */ + if((strlen(this_char) > 4) || strlen(temp2) > 8) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + goto LabelOK; + } + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + goto LabelOK; + } + + /*MAC Addr */ + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + /*MAC value */ + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[4-k+j] = temp2[j]; + } + + while(k < 4) + temp2[3-k++]='0'; + temp2[4]='\0'; + + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 2); + eepValue = *temp*256 + temp[1]; + + RT28xx_EEPROM_WRITE16(pAd, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%02X]:%02X ", eepAddr, eepValue); + } + } + else + bIsPrintAllE2P = TRUE; +next: + if (bIsPrintAllE2P) + { + USHORT *pMacContent, *pMacIndex; + UINT32 ContentLen; + UINT32 AddrEnd = 0xFE; + + + ContentLen = AddrEnd+2; + os_alloc_mem(NULL, (UCHAR **)&pMacContent, ContentLen); + if (pMacContent == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("-->2) %s: Allocate memory fail!\n", __FUNCTION__)); + } + else + { + /* get MAC content */ + USHORT eepAddr = 0; + USHORT eepValue; + + pMacIndex = pMacContent; + while(eepAddr <= AddrEnd) + { + RT28xx_EEPROM_READ16(pAd, eepAddr, eepValue); + *pMacIndex = eepValue; + + pMacIndex ++; + eepAddr += 2; + } + + /* print content to a file */ + RtmpDrvAllE2PPrint(pAd, pMacContent, AddrEnd, 2); + os_free_mem(NULL, pMacContent); + } + + } + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + + /* Copy the information into the user buffer */ + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + +LabelOK: + if (msg != NULL) + os_free_mem(NULL, msg); + if (arg != NULL) + os_free_mem(NULL, arg); + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n")); + return; +} + +#ifdef RLT_RF +VOID RTMPIoctlRF_rlt( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PSTRING this_char; + PSTRING value; + UCHAR regRF = 0, rf_bank = 0; + PSTRING mpool, msg; + PSTRING arg; + PSTRING ptr; + INT rfId, maxRFIdx, bank_Id; + LONG rfValue; + BOOLEAN bIsPrintAllRF = FALSE, bFromUI; + INT memLen = sizeof(CHAR) * (2048+256+12); + INT argLen; + + maxRFIdx = pAdapter->chipCap.MaxNumOfRfId; + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlRF (maxRFIdx = %d)\n", maxRFIdx)); + + memLen = 12*(maxRFIdx+1)*MAC_RF_BANK; + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + bFromUI = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_UI) == RTPRIV_IOCTL_FLAG_UI) ? TRUE : FALSE; + + NdisZeroMemory(mpool, memLen); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (PSTRING)((ULONG)(msg+2048+3) & (ULONG)~0x03); + argLen = strlen((char *)(wrq->u.data.pointer)); + +// ++Alan test + if (wrq->u.data.length > 1) /*No parameters. */ + { + NdisMoveMemory(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + arg[254] = 0x00; + ptr = arg; + sprintf(msg, "\n"); + /*Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + goto next; + + if ((value = strchr(this_char,'=')) != NULL) + *value++ = 0; + + + if (!value || !*value) + { /*Read */ + + if ((value = strchr(this_char,'_')) != NULL) + *value++ = 0; + + if ( !value ) + { + bIsPrintAllRF = TRUE; + goto next; + } + + if ( (sscanf((PSTRING) this_char, "%d", &(bank_Id)) == 1) && (sscanf((PSTRING) value, "%d", &(rfId)) == 1)) + { + + if ( (rfId <= maxRFIdx) && (bank_Id <= MAC_RF_BANK)) + { + rlt_rf_read(pAdapter, bank_Id, rfId, ®RF); + + sprintf(msg+strlen(msg), "BANK%d_R%02d:%02X ", bank_Id, rfId, regRF); + } + else + {/*Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + goto next; + } + } + else + { + /* Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + goto next; + } + } + else + { /*Write */ + if ( sscanf(value, "%lx", &(rfValue)) == 1) + { + if ((value = strchr(this_char,'_')) != NULL) + *value++ = 0; + + if ( !value ) + { + bIsPrintAllRF = TRUE; + break; + } + + if ( (sscanf((PSTRING)this_char, "%d", &(bank_Id)) == 1) && (sscanf((PSTRING)value, "%d", &(rfId)) == 1)) + { + + if ( (rfId <= maxRFIdx) && (bank_Id <= MAC_RF_BANK) ) + { + rlt_rf_write(pAdapter, bank_Id, rfId, rfValue); + sprintf(msg+strlen(msg), "BANK%d_R%02d:%02X ", bank_Id, rfId, rfValue); + } + else + { + bIsPrintAllRF = TRUE; + break; + } + } + else + { + bIsPrintAllRF = TRUE; + break; + } + + } + else + { + bIsPrintAllRF = TRUE; + break; + } + } + + + } + + } + else + bIsPrintAllRF = TRUE; +// --Alan test + +next: + if (bIsPrintAllRF) + { + RTMPZeroMemory(msg, memLen); + sprintf(msg, "\n"); + for (bank_Id = 0; bank_Id <= MAC_RF_BANK; bank_Id++) + { + if (IS_MT76x0(pAdapter)) + { + if ((bank_Id <=4) && (bank_Id >=1)) + continue; + } + for (rfId = 0; rfId <= maxRFIdx; rfId++) + { + rlt_rf_read(pAdapter, bank_Id, rfId, ®RF); + sprintf(msg+strlen(msg), "%d %03d %02X\n", bank_Id, rfId, regRF); + } + } + RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); + /* Copy the information into the user buffer */ + +#ifdef LINUX + wrq->u.data.length = strlen("Dump to RFDump.txt"); + if (copy_to_user(wrq->u.data.pointer, "Dump to RFDump.txt", wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + else + { + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n")); +} +#endif /* RLT_RF */ + +#ifdef MT_RF +VOID RTMPIoctlRF_mt( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + CHAR *value; + UINT regRF = 0; + CHAR *mpool, *msg; /*msg[2048]; */ + BOOLEAN bIsPrintAllRF = TRUE; + UINT rfidx =0, offset = 0; + INT memLen = sizeof(CHAR) * 9000; //(2048+256+12); + + DBGPRINT(RT_DEBUG_TRACE, ("==>%s\n", __FUNCTION__)); + + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + NdisZeroMemory(mpool, memLen); + msg = (PSTRING)((ULONG)(mpool+3) & (ULONG)~0x03); + + if (bIsPrintAllRF) + { + RTMPZeroMemory(msg, memLen); + sprintf(msg, "\n"); + for (rfidx = 0; rfidx <= 1; rfidx++) + { + for (offset = 0; offset <= 0x3ff; offset+=4) + { + mt_rf_read(pAd, rfidx, offset, ®RF); + sprintf(msg+strlen(msg), "%d %03x = %08X\n", rfidx, offset, regRF); + } + offset = 0xfff; + mt_rf_read(pAd, rfidx, offset, ®RF); + sprintf(msg+strlen(msg), "%d %03x = %08X\n", rfidx, offset, regRF); + } + RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); + + DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg)=%d\n", (UINT32)strlen(msg))); + /* Copy the information into the user buffer */ +#ifdef LINUX + wrq->u.data.length = strlen("Dump to RFDump.txt"); + if (copy_to_user(wrq->u.data.pointer, "Dump to RFDump.txt", wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +} +#endif /* MT_RF */ + +#ifdef RTMP_RF_RW_SUPPORT +/* + ========================================================================== + Description: + Read / Write RF register +Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 rf ==> read all RF registers + 2.) iwpriv ra0 rf 1 ==> read RF where RegID=1 + 3.) iwpriv ra0 rf 1=10 ==> write RF R1=0x10 + ========================================================================== +*/ +VOID RTMPIoctlRF( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + CHAR *this_char; + CHAR *value; + UCHAR regRF = 0; + CHAR *mpool, *msg; /*msg[2048]; */ + CHAR *arg; /*arg[255]; */ + CHAR *ptr; + INT rfId; + LONG rfValue; + BOOLEAN bIsPrintAllRF = FALSE; + int maxRFIdx; + + +#ifdef RLT_RF + if (IS_MT76x0(pAd) || IS_MT7601(pAd) || IS_RT6352(pAd)) { + RTMPIoctlRF_rlt(pAd, wrq); + return; + } +#endif /* RLT_RF */ + +#ifdef MT_RF + if (IS_MT76x2(pAd)) { + RTMPIoctlRF_mt(pAd, wrq); + return; + } +#endif + + maxRFIdx = pAd->chipCap.MaxNumOfRfId; + + + os_alloc_mem(pAd, (UCHAR **)&mpool, sizeof(CHAR)*(2048+256+12)); + if (mpool == NULL) { + return; + } + + msg = (CHAR *)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (CHAR *)((ULONG)(msg+2048+3) & (ULONG)~0x03); + + memset(msg, 0x00, 2048); + memset(arg, 0x00, 255); + if (wrq->u.data.length > 1) /*No parameters. */ + { + NdisMoveMemory(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + arg[254] = 0x00; + ptr = arg; + sprintf(msg, "\n"); + /*Parsing Read or Write */ + while ((this_char = strsep((char **)&ptr, ",")) != NULL) + { + if (!*this_char) + goto next; + + if ((value = strchr(this_char,'=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + if (sscanf((PSTRING) this_char, "%d", &(rfId)) == 1) + { + if (rfId <= maxRFIdx) + { + RT30xxReadRFRegister(pAd, rfId, ®RF); + + sprintf(msg+strlen(msg), "R%02d:%02X ", rfId, regRF); + } + else + {/*Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + goto next; + } + } + else + { + /* Invalid parametes, so default printk all RF */ + bIsPrintAllRF = TRUE; + goto next; + } + } + else + { /*Write */ + if ((sscanf((PSTRING)this_char, "%d", &(rfId)) == 1) && (sscanf(value, "%lx", &(rfValue)) == 1)) + { + if (rfId <= maxRFIdx) + { + RT30xxReadRFRegister(pAd, rfId, ®RF); + RT30xxWriteRFRegister(pAd, rfId, rfValue); + /*Read it back for showing */ + RT30xxReadRFRegister(pAd, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d:%02X\n", rfId, regRF); + } + else + { + bIsPrintAllRF = TRUE; + break; + } + } + else + { + bIsPrintAllRF = TRUE; + break; + } + } + } + } + else + bIsPrintAllRF = TRUE; + +next: + /* Copy the information into the user buffer */ + if (bIsPrintAllRF) + { + memset(msg, 0x00, 2048); + sprintf(msg, "\n"); + for (rfId = 0; rfId <= maxRFIdx; rfId++) + { + RT30xxReadRFRegister(pAd, rfId, ®RF); + sprintf(msg+strlen(msg), "R%d = 0x%02X\n", rfId, regRF); + } + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + else + { + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +} +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /* DBG */ + + +#ifdef RT65xx +VOID RTMPIoctlBbp32( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN CHAR *extra, + IN UINT32 size) +{ + PSTRING this_char; + PSTRING value = NULL; + UINT32 regBBP = 0, bbpId; + UINT32 bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE; + +DBGPRINT(RT_DEBUG_OFF, ("Into RTMPIoctlBbp32()!\n")); + + if (wrq->u.data.length > 1) /*No parameters. */ + { + sprintf(extra, "\n"); + + /*Parsing Read or Write */ + this_char = wrq->u.data.pointer; + DBGPRINT(RT_DEBUG_INFO, ("this_char=%s\n", this_char)); + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { + /*Read */ + DBGPRINT(RT_DEBUG_INFO, ("this_char=%s, value=%s\n", this_char, value)); + + if (sscanf(this_char, "%x", &(bbpId)) == 1) + { + if ((bbpId <= 0x2fff) && (bbpId >= 0x2000)) + { + RTMP_BBP_IO_READ32(pAd, bbpId, ®BBP); + sprintf(extra+strlen(extra), "BBP[0x%04x]:%08x\n", bbpId, regBBP); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_INFO, ("msg=%s\n", extra)); + } + else + { + /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { + /*Write */ + DBGPRINT(RT_DEBUG_OFF, ("this_char=%s, value=%s\n", this_char, value)); + if ((sscanf(this_char, "%x", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1)) + { + DBGPRINT(RT_DEBUG_OFF, ("BBP[0x%04x]:%08x\n", bbpId, bbpValue)); + if ((bbpId <= 0x2fff) && (bbpId >= 0x2000)) + { + RTMP_BBP_IO_WRITE32(pAd, bbpId, bbpValue); + /* read it back for showing */ + RTMP_BBP_IO_READ32(pAd, bbpId, ®BBP); + sprintf(extra+strlen(extra), "BBP[0x%04x]:%08x\n", bbpId, regBBP); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_OFF, ("msg=%s\n", extra)); + } + else + { + /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + } + else + bIsPrintAllBBP = TRUE; + +next: + if (bIsPrintAllBBP) + { + static RTMP_REG_PAIR bbp_regs[]={ + {CORE_R1, CORE_R44}, + {IBI_R0, IBI_R11}, + {AGC1_R0, AGC1_R63}, + {TXC_R1, TXC_R1}, + {RXC_R1, RXC_R4}, + {TXO_R8, TXO_R8}, + {TXBE_R0, TXBE_R17}, + {RXFE_R0, RXFE_R4}, + {RXO_R13, RXO_R28}, + }; + UINT32 reg, i; + + + memset(extra, 0x00, size); + sprintf(extra, "\n"); + for (i = 0; i < sizeof(bbp_regs) / sizeof(RTMP_REG_PAIR); i++) + { + for (reg = bbp_regs[i].Register; reg <= bbp_regs[i].Value; reg += 4) + { + if (strlen(extra) >= (size - 20)) + break; + RTMP_BBP_IO_READ32(pAd, reg, ®BBP); + sprintf(extra+strlen(extra), "%04x = %08x\n", reg, regBBP); /* edit by johnli, change display format */ + } + } + + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->u.data.length)); + } +} +#endif /* RT65xx */ + + +VOID RTMPIoctlBbp( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN CHAR *extra, + IN UINT32 size) +{ +#ifdef RTMP_BBP + PSTRING this_char; + PSTRING value = NULL; + UCHAR regBBP = 0; + UINT32 bbpId; + UINT32 bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE; +#endif /* RTMP_BBP */ + +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + RTMPIoctlBbp32(pAd, wrq, extra, size); + return; + } +#endif /* RT65xx */ + +#ifdef RTMP_BBP + if (wrq->u.data.length > 1) /*No parameters. */ + { + sprintf(extra, "\n"); + + /*Parsing Read or Write */ + this_char = wrq->u.data.pointer; + DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char)); + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { /*Read */ + DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value)); + if (sscanf(this_char, "%d", &(bbpId)) == 1) + { + if (bbpId <= pAd->chipCap.MaxNumOfBbpId) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, ®BBP); + } + else +#endif /* RALINK_ATE */ + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, ®BBP); + } + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId, regBBP); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); + } + else + {/*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { /*Write */ + if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1)) + { + if (bbpId <= pAd->chipCap.MaxNumOfBbpId) + { +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, bbpId, bbpValue); + /* read it back for showing */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, ®BBP); + } + else +#endif /* RALINK_ATE */ + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, bbpId, bbpValue); + /* read it back for showing */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, ®BBP); + } + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId, regBBP); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); + } + else + {/*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { /*Invalid parametes, so default printk all bbp */ + bIsPrintAllBBP = TRUE; + goto next; + } + } + } + else + bIsPrintAllBBP = TRUE; + +next: + if (bIsPrintAllBBP) + { + memset(extra, 0x00, size); + sprintf(extra, "\n"); + for (bbpId = 0; bbpId <= pAd->chipCap.MaxNumOfBbpId; bbpId++) + { + if (strlen(extra) >= (size - 20)) + break; +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, ®BBP); + } + else +#endif /* RALINK_ATE */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, bbpId, ®BBP); + /*sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X ", bbpId, bbpId, regBBP); + if (bbpId%5 == 4)*/ + sprintf(extra+strlen(extra), "%03d = %02X\n", bbpId, regBBP); /* edit by johnli, change display format */ + } + + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->u.data.length)); + } +#endif /* RTMP_BBP*/ + +} + + + + +#ifdef DOT11_N_SUPPORT +void getBaInfo( + IN PRTMP_ADAPTER pAd, + IN PSTRING pOutBuf, + IN UINT32 size) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + + for (i=0; iMacTab.Content[i]; + if (((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry) || IS_ENTRY_TDLS(pEntry)) && (pEntry->Sst == SST_ASSOC)) + || IS_ENTRY_WDS(pEntry) || IS_ENTRY_MESH(pEntry)) + { + sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n", + pOutBuf, + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid); + + sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + { + pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; + sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); + } + } + sprintf(pOutBuf, "%s\n", pOutBuf); + + sprintf(pOutBuf, "%s[Originator]\n", pOutBuf); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + { + pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; + sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]); + } + } + sprintf(pOutBuf, "%s\n\n", pOutBuf); + } + if (strlen(pOutBuf) > (size - 30)) + break; + } + + return; +} +#endif /* DOT11_N_SUPPORT */ + + +VOID RTMPIoctlShow( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN UINT32 subcmd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SHOW *pIoctlShow = (RT_CMD_STA_IOCTL_SHOW *)pData; + POS_COOKIE pObj; + INT Status = 0; + char *extra = (char *)pIoctlShow->pData; + UINT32 size = (UINT32)(pIoctlShow->MaxSize); + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + switch(subcmd) + { +#ifdef ETH_CONVERT_SUPPORT +#ifdef MAT_SUPPORT + case SHOW_IPV4_MAT_INFO: + { + extern VOID getIPMacTbInfo(MAT_STRUCT *, char *, ULONG); + getIPMacTbInfo(&pAd->MatCfg, extra, size); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + } + break; + case SHOW_IPV6_MAT_INFO: + { + extern VOID getIPv6MacTbInfo(MAT_STRUCT *, char *, ULONG); + getIPv6MacTbInfo(&pAd->MatCfg, extra, size); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + } + break; + case SHOW_ETH_CLONE_MAC: + snprintf(extra, size, "%02X:%02X:%02X:%02X:%02X:%02X\n", pAd->EthConvert.EthCloneMac[0], + pAd->EthConvert.EthCloneMac[1], + pAd->EthConvert.EthCloneMac[2], + pAd->EthConvert.EthCloneMac[3], + pAd->EthConvert.EthCloneMac[4], + pAd->EthConvert.EthCloneMac[5]); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; +#endif /* MAT_SUPPORT */ +#endif /* ETH_CONVERT_SUPPORT */ + + case SHOW_CONN_STATUS: + if (MONITOR_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW) + snprintf(extra, size, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel); + else +#endif /* DOT11_N_SUPPORT */ + snprintf(extra, size, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel); + } + else + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + if (INFRA_ON(pAd)) + { + snprintf(extra, size, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n", + pAd->CommonCfg.Ssid, + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5]); + DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)); + } + else if (ADHOC_ON(pAd)) + snprintf(extra, size, "Connected\n"); + } + else + { + snprintf(extra, size, "Disconnected\n"); + DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n")); + } + } + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; + case SHOW_DRVIER_VERION: + snprintf(extra, size, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ ); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; +#ifdef DOT11_N_SUPPORT + case SHOW_BA_INFO: + getBaInfo(pAd, extra, size); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; +#endif /* DOT11_N_SUPPORT */ + case SHOW_DESC_INFO: + { + Show_DescInfo_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + case RAIO_OFF: + /* Link down first if any association exists*/ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + MLME_QUEUE_ELEM *pMsgElem; + + os_alloc_mem(NULL, (UCHAR **)&pMsgElem, sizeof(MLME_QUEUE_ELEM)); + if (pMsgElem) + { + COPY_MAC_ADDR(&DisReq.Addr, pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DISASSOC_STA_LEAVING; + + pMsgElem->Machine = ASSOC_STATE_MACHINE; + pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(pMsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + MlmeDisassocReqAction(pAd, pMsgElem); + os_free_mem(NULL, pMsgElem); + + RtmpusecDelay(1000); + } + } + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + } + pAd->StaCfg.bSwRadio = FALSE; + if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_CMD_RADIO_OFF); + MlmeRadioOff(pAd); + /* Update extra information */ + pAd->ExtraInfo = SW_RADIO_OFF; + } + } + snprintf(extra, size, "Radio Off\n"); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; + case RAIO_ON: + pAd->StaCfg.bSwRadio = TRUE; + /*if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) */ + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_CMD_RADIO_OFF); + MlmeRadioOn(pAd); + /* Update extra information */ + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + } + snprintf(extra, size, "Radio On\n"); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; + + +#ifdef QOS_DLS_SUPPORT + case SHOW_DLS_ENTRY_INFO: + { + Set_DlsEntryInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; +#endif /* QOS_DLS_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + case SHOW_TDLS_ENTRY_INFO: + { +#ifdef DOT11Z_TDLS_SUPPORT + Set_TdlsEntryInfo_Display_Proc(pAd, NULL); +#else + cfg_tdls_EntryInfo_Display_Proc(pAd, NULL); +#endif + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + case SHOW_CFG_VALUE: + { + Status = RTMPShowCfgValue(pAd, (PSTRING) wrq->u.data.pointer, + extra, pIoctlShow->MaxSize); + if (Status == 0) + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + } + break; + case SHOW_ADHOC_ENTRY_INFO: + Show_Adhoc_MacTable_Proc(pAd, extra, size); + wrq->u.data.length = strlen(extra) + 1; /* 1: size of '\0' */ + break; + + + case SHOW_DEV_INFO: + show_devinfo_proc(pAd, NULL); + wrq->u.data.length = 0; + break; + + case SHOW_STA_INFO: + Show_MacTable_Proc(pAd, NULL); + wrq->u.data.length = 0; + break; + + case SHOW_TR_INFO: + show_trinfo_proc(pAd, NULL); + wrq->u.data.length = 0; + break; + + case SHOW_SYS_INFO: + show_sysinfo_proc(pAd, NULL); + wrq->u.data.length = 0; + break; + + case SHOW_PWR_INFO: + show_pwr_info(pAd, NULL); + wrq->u.data.length = 0; + break; + + case SHOW_DIAGNOSE_INFO: + Show_Diag_Proc(pAd, NULL); + wrq->u.data.length = 0; + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd)); + break; + } +} + + +/* ------------------- Functions for Standard IOCTL ------------------------- */ +#define RTMP_STA_STANDARD_IOCTL_HANDLE(__pAd, __pData, __Data, __SubCmd) \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWFREQ: \ + return RtmpIoctl_rt_ioctl_siwfreq(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWFREQ: \ + return RtmpIoctl_rt_ioctl_giwfreq(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWMODE: \ + return RtmpIoctl_rt_ioctl_siwmode(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWMODE: \ + return RtmpIoctl_rt_ioctl_giwmode(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWAP: \ + return RtmpIoctl_rt_ioctl_siwap(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWAP: \ + return RtmpIoctl_rt_ioctl_giwap(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWSCAN: \ + return RtmpIoctl_rt_ioctl_siwscan(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWSCAN: \ + return RtmpIoctl_rt_ioctl_giwscan(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWESSID: \ + return RtmpIoctl_rt_ioctl_siwessid(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWESSID: \ + return RtmpIoctl_rt_ioctl_giwessid(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWNICKN: \ + return RtmpIoctl_rt_ioctl_siwnickn(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWNICKN: \ + return RtmpIoctl_rt_ioctl_giwnickn(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWRTS: \ + return RtmpIoctl_rt_ioctl_siwrts(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWRTS: \ + return RtmpIoctl_rt_ioctl_giwrts(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWFRAG: \ + return RtmpIoctl_rt_ioctl_siwfrag(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWFRAG: \ + return RtmpIoctl_rt_ioctl_giwfrag(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODE: \ + return RtmpIoctl_rt_ioctl_siwencode(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODE: \ + return RtmpIoctl_rt_ioctl_giwencode(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWMLME: \ + return RtmpIoctl_rt_ioctl_siwmlme(__pAd, __pData, __Data, __SubCmd);\ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWAUTH: \ + return RtmpIoctl_rt_ioctl_siwauth(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWAUTH: \ + return RtmpIoctl_rt_ioctl_giwauth(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODEEXT: \ + return RtmpIoctl_rt_ioctl_siwencodeext(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODEEXT: \ + return RtmpIoctl_rt_ioctl_giwencodeext(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWGENIE: \ + return RtmpIoctl_rt_ioctl_siwgenie(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWGENIE: \ + return RtmpIoctl_rt_ioctl_giwgenie(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWPMKSA: \ + return RtmpIoctl_rt_ioctl_siwpmksa(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWRATE: \ + return RtmpIoctl_rt_ioctl_siwrate(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIWRATE: \ + return RtmpIoctl_rt_ioctl_giwrate(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCGIFHWADDR: \ + return RtmpIoctl_rt_ioctl_gifhwaddr(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_SIOCSIWPRIVRSSI: \ + return RtmpIoctl_rt_ioctl_rssi(__pAd, __pData, __Data); \ + case CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_U32_ITEM: \ + return RtmpIoctl_rt_private_set_wsc_u32_item(__pAd, __pData, __Data);\ + case CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_STR_ITEM: \ + return RtmpIoctl_rt_private_set_wsc_string_item(__pAd, __pData, __Data);\ + case CMD_RTPRIV_IOCTL_STA_IW_GET_STATISTICS: \ + return RtmpIoctl_rt_private_get_statistics(__pAd, __pData, __Data); \ + ; + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWFREQ. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwfreq( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_FREQ *pIoctlFreq = (RT_CMD_STA_IOCTL_FREQ *)pData; + int chan = -1; + ULONG freq; + + if ( pIoctlFreq->m > 100000000 ) + freq = pIoctlFreq->m / 100000; + else if ( pIoctlFreq->m > 100000 ) + freq = pIoctlFreq->m / 100; + else + freq = pIoctlFreq->m; + + + if((pIoctlFreq->e == 0) && (freq <= 1000)) + chan = pIoctlFreq->m; /* Setting by channel number */ + else + { + MAP_KHZ_TO_CHANNEL_ID( freq , chan); /* Setting by frequency - search the table , like 2.412G, 2.422G, */ + } + + if (ChannelSanity(pAd, chan) == TRUE) + { + pAd->CommonCfg.Channel = chan; + /* Save the channel on MlmeAux for CntlOidRTBssidProc used. */ + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + /*save connect info*/ + pAd->StaCfg.ConnectinfoChannel = pAd->CommonCfg.Channel; + DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ(Channel=%d)\n", pAd->CommonCfg.Channel)); + } + else + return NDIS_STATUS_FAILURE; + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWFREQ. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwfreq( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + UCHAR ch; + ULONG m = 2412000; + + ch = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq %d\n", ch)); + + MAP_CHANNEL_ID_TO_KHZ(ch, m); + *(ULONG *)pData = m; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWMODE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwmode( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + switch(Data) + { + case RTMP_CMD_STA_MODE_ADHOC: + Set_NetworkType_Proc(pAd, "Adhoc"); + break; + case RTMP_CMD_STA_MODE_INFRA: + Set_NetworkType_Proc(pAd, "Infra"); + break; + case RTMP_CMD_STA_MODE_MONITOR: + Set_NetworkType_Proc(pAd, "Monitor"); + break; + } + + /* Reset Ralink supplicant to not use, it will be set to start when UI set PMK key */ + pAd->StaCfg.WpaState = SS_NOTUSE; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWMODE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwmode( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + if (ADHOC_ON(pAd)) + *(ULONG *)pData = RTMP_CMD_STA_MODE_ADHOC; + else if (INFRA_ON(pAd)) + *(ULONG *)pData = RTMP_CMD_STA_MODE_INFRA; + else if (MONITOR_ON(pAd)) + *(ULONG *)pData = RTMP_CMD_STA_MODE_MONITOR; + else + *(ULONG *)pData = RTMP_CMD_STA_MODE_AUTO; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWAP. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwap( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + UCHAR *pBssid = (UCHAR *)pData; + + + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RTMP_MLME_RESET_STATE_MACHINE(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + /* tell CNTL state machine to call NdisMSetInformationComplete() after completing */ + /* this request, because this request is initiated by NDIS. */ + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + /* Prevent to connect AP again in STAMlmePeriodicExec */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + + if (MAC_ADDR_EQUAL(pBssid, ZERO_MAC_ADDR)) + { + if (INFRA_ON(pAd)) + { + LinkDown(pAd, FALSE); + } + } + else + { + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)pBssid, 0); + } + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWAP. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwap( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + NdisMoveMemory(pData, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); +#ifdef WPA_SUPPLICANT_SUPPORT + /* Add for RT2870 */ + else if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + NdisMoveMemory(pData, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); +#endif /* WPA_SUPPLICANT_SUPPORT */ + else + return NDIS_STATUS_FAILURE; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWSCAN. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_siwscan(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /* + Can not use SIOCGIWSCAN definition, it is used in wireless.h + We will not see the definition in MODULE. + The definition can be saw in UTIL and NETIF. + */ +/* #if defined(SIOCGIWSCAN) || defined(RT_CFG80211_SUPPORT) */ + RT_CMD_STA_IOCTL_SCAN *pConfig = (RT_CMD_STA_IOCTL_SCAN *)pData; + int Status = NDIS_STATUS_SUCCESS; + + +#ifdef ANDROID_SUPPORT + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) +#ifdef IFUP_IN_PROBE + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) +#endif /* IFUP_IN_PROBE */ + ) + { + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_SCAN, -1, NULL, NULL, 0); + return NDIS_STATUS_SUCCESS; + } +#endif /* ANDROID_SUPPORT */ + + pConfig->Status = 0; + + if (MONITOR_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + pConfig->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_FAILURE; + } + + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantScanCount++; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + pAd->StaCfg.bSkipAutoScanConn = TRUE; + do{ + + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pConfig->FlgScanThisSsid) + { + NDIS_802_11_SSID Ssid; + Ssid.SsidLength = pConfig->SsidLen; + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwscan:: req.essid_len-%d, essid-%s\n", pConfig->SsidLen, pConfig->pSsid)); + NdisZeroMemory(&Ssid.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(Ssid.Ssid, pConfig->pSsid, Ssid.SsidLength); + StaSiteSurvey(pAd, &Ssid, SCAN_ACTIVE); + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + StaSiteSurvey(pAd, NULL, SCAN_ACTIVE); + }while(0); + + pConfig->Status = Status; +/* #endif */ /* SIOCGIWSCAN || RT_CFG80211_SUPPORT */ + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Set the signal quality. + +Arguments: + *pSignal - signal structure + pBssEntry - the BSS information + +Return Value: + None + +Note: +======================================================================== +*/ +static void set_quality( + IN RT_CMD_STA_IOCTL_BSS *pSignal, + IN BSS_ENTRY *pBssEntry) +{ + memcpy(pSignal->Bssid, pBssEntry->Bssid, MAC_ADDR_LEN); + + /* Normalize Rssi */ + if (pBssEntry->Rssi >= -50) + pSignal->ChannelQuality = 100; + else if (pBssEntry->Rssi >= -80) /* between -50 ~ -80dbm */ + pSignal->ChannelQuality = (__u8)(24 + ((pBssEntry->Rssi + 80) * 26)/10); + else if (pBssEntry->Rssi >= -90) /* between -80 ~ -90dbm */ + pSignal->ChannelQuality = (__u8)((pBssEntry->Rssi + 90) * 26)/10; + else + pSignal->ChannelQuality = 0; + + pSignal->Rssi = (__u8)(pBssEntry->Rssi); + + if (pBssEntry->Rssi >= -70) + pSignal->Noise = -92; + else + pSignal->Noise = pBssEntry->Rssi - pBssEntry->MinSNR; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWSCAN. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwscan( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SCAN_TABLE *pIoctlScan = (RT_CMD_STA_IOCTL_SCAN_TABLE *)pData; + RT_CMD_STA_IOCTL_BSS_TABLE *pBssTable; + BSS_ENTRY *pBssEntry; + UINT32 IdBss; + + + pIoctlScan->BssNr = 0; + + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantScanCount = 0; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + pIoctlScan->BssNr = pAd->ScanTab.BssNr; + if (pIoctlScan->BssNr == 0) + return NDIS_STATUS_SUCCESS; + + os_alloc_mem(NULL, (UCHAR **)&(pIoctlScan->pBssTable), + pAd->ScanTab.BssNr * sizeof(RT_CMD_STA_IOCTL_BSS_TABLE)); + if (pIoctlScan->pBssTable == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Allocate memory fail!\n")); + return NDIS_STATUS_FAILURE; + } + + for(IdBss=0; IdBssScanTab.BssNr; IdBss++) + { + HT_CAP_INFO capInfo = pAd->ScanTab.BssEntry[IdBss].HtCapability.HtCapInfo; + + pBssTable = pIoctlScan->pBssTable + IdBss; + pBssEntry = &pAd->ScanTab.BssEntry[IdBss]; + + memcpy(pBssTable->Bssid, pBssEntry->Bssid, ETH_ALEN); + pBssTable->Channel = pBssEntry->Channel; + pBssTable->BssType = pBssEntry->BssType; + pBssTable->HtCapabilityLen = pBssEntry->HtCapabilityLen; + memcpy(pBssTable->SupRate, pBssEntry->SupRate, 12); + pBssTable->SupRateLen = pBssEntry->SupRateLen; + memcpy(pBssTable->ExtRate, pBssEntry->ExtRate, 12); + pBssTable->ExtRateLen = pBssEntry->ExtRateLen; + pBssTable->SsidLen = pBssEntry->SsidLen; + memcpy(pBssTable->Ssid, pBssEntry->Ssid, 32); + pBssTable->CapabilityInfo = pBssEntry->CapabilityInfo; + pBssTable->ChannelWidth = capInfo.ChannelWidth; + pBssTable->ShortGIfor40 = capInfo.ShortGIfor40; + pBssTable->ShortGIfor20 = capInfo.ShortGIfor20; + pBssTable->MCSSet = pBssEntry->HtCapability.MCSSet[1]; + pBssTable->WpaIeLen = pBssEntry->WpaIE.IELen; + pBssTable->pWpaIe = pBssEntry->WpaIE.IE; + pBssTable->RsnIeLen = pBssEntry->RsnIE.IELen; + pBssTable->pRsnIe = pBssEntry->RsnIE.IE; + pBssTable->WpsIeLen = pBssEntry->WpsIE.IELen; + pBssTable->pWpsIe = pBssEntry->WpsIE.IE; + pBssTable->VHTCapabilityLen = pBssEntry->vht_cap_len; + pBssTable->FlgIsPrivacyOn = CAP_IS_PRIVACY_ON(pBssEntry->CapabilityInfo); + set_quality(&pBssTable->Signal, pBssEntry); + } + + memcpy(pIoctlScan->MainSharedKey[0], pAd->SharedKey[BSS0][0].Key, 16); + memcpy(pIoctlScan->MainSharedKey[1], pAd->SharedKey[BSS0][1].Key, 16); + memcpy(pIoctlScan->MainSharedKey[2], pAd->SharedKey[BSS0][2].Key, 16); + memcpy(pIoctlScan->MainSharedKey[3], pAd->SharedKey[BSS0][3].Key, 16); + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWESSID. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwessid( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SSID *pSsid = (RT_CMD_STA_IOCTL_SSID *)pData; + + if (pSsid->FlgAnySsid) + { + PSTRING pSsidString = NULL; + + /* Includes null character. */ + os_alloc_mem(NULL, (UCHAR **)&pSsidString, MAX_LEN_OF_SSID+1); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, pSsid->pSsid, pSsid->SsidLen); + if (Set_SSID_Proc(pAd, pSsidString) == FALSE) + { + os_free_mem(NULL, pSsidString); + pSsid->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_SUCCESS; + } + os_free_mem(NULL, pSsidString); + } + else + { + pSsid->Status = RTMP_IO_ENOMEM; + return NDIS_STATUS_SUCCESS; + } + } + else + { + /* ANY ssid */ + if (Set_SSID_Proc(pAd, "") == FALSE) + { + pSsid->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_SUCCESS; + } + } + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWESSID. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwessid( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SSID *pSsid = (RT_CMD_STA_IOCTL_SSID *)pData; + + if (MONITOR_ON(pAd)) + { + pSsid->SsidLen = 0; + return NDIS_STATUS_SUCCESS; + } + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n")); + pSsid->SsidLen = pAd->CommonCfg.SsidLen; + memcpy(pSsid->pSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + } + else + {/*the ANY ssid was specified */ + pSsid->SsidLen = 0; + DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n")); + } + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWNICKN. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwnickn( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + memset(pAd->nickname, 0, IW_ESSID_MAX_SIZE + 1); + memcpy(pAd->nickname, pData, Data); + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWNICKN. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwnickn( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_NICK_NAME *IoctlName = (RT_CMD_STA_IOCTL_NICK_NAME *)pData; + + + if (IoctlName->NameLen > strlen((PSTRING) pAd->nickname) + 1) + IoctlName->NameLen = strlen((PSTRING) pAd->nickname) + 1; + if (IoctlName->NameLen > 0) { + memcpy(IoctlName->pName, pAd->nickname, IoctlName->NameLen-1); + IoctlName->pName[IoctlName->NameLen-1] = '\0'; + } + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWRTS. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwrts( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + pAd->CommonCfg.RtsThreshold = Data; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWRTS. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwrts( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + *(USHORT *)pData = pAd->CommonCfg.RtsThreshold; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWFRAG. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwfrag( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + pAd->CommonCfg.FragmentThreshold = Data; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWFRAG. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwfrag( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + *(USHORT *)pData = pAd->CommonCfg.FragmentThreshold; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +#define NR_WEP_KEYS 4 +#define MAX_WEP_KEY_SIZE 13 +#define MIN_WEP_KEY_SIZE 5 +INT RtmpIoctl_rt_ioctl_siwencode(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if ((pIoctlSec->length == 0) && + (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_DISABLED)) + { + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + wdev->WepStatus = Ndis802_11WEPDisabled; + wdev->AuthMode = Ndis802_11AuthModeOpen; + goto done; + } + else if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_RESTRICTED || + pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_OPEN) + { + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + wdev->WepStatus = Ndis802_11WEPEnabled; + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_RESTRICTED) + wdev->AuthMode = Ndis802_11AuthModeShared; + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + } + + if (pIoctlSec->length > 0) + { + int keyIdx = pIoctlSec->KeyIdx; /*(erq->flags & IW_ENCODE_INDEX) - 1; */ + /* Check the size of the key */ + if (pIoctlSec->length > MAX_WEP_KEY_SIZE) + { + pIoctlSec->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_SUCCESS; + } + /* Check key index */ + if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + { + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n", + keyIdx, wdev->DefaultKeyId)); + + /*Using default key */ + keyIdx = wdev->DefaultKeyId; + } + else + wdev->DefaultKeyId = keyIdx; + + NdisZeroMemory(pAd->SharedKey[BSS0][keyIdx].Key, 16); + + if (pIoctlSec->length == MAX_WEP_KEY_SIZE) + { + pAd->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; + pAd->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; + } + else if (pIoctlSec->length == MIN_WEP_KEY_SIZE) + { + pAd->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; + pAd->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; + } + else + /* Disable the key */ + pAd->SharedKey[BSS0][keyIdx].KeyLen = 0; + + /* Check if the key is not marked as invalid */ + if(!(pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_NOKEY)) + { + /* Copy the key in the driver */ + NdisMoveMemory(pAd->SharedKey[BSS0][keyIdx].Key, pIoctlSec->pData, pIoctlSec->length); + } + } + else + { + /* Do we want to just set the transmit key index ? */ + int index = pIoctlSec->KeyIdx; /*(erq->flags & IW_ENCODE_INDEX) - 1; */ + if ((index >= 0) && (index < 4)) + { + pAd->StaCfg.wdev.DefaultKeyId = index; + } + else + /* Don't complain if only change the mode */ + if(!(pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_MODE)) + { + pIoctlSec->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_SUCCESS; + } + } + +done: + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n", pIoctlSec->flags)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n", wdev->AuthMode)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n", + wdev->DefaultKeyId , pAd->SharedKey[BSS0][wdev->DefaultKeyId].KeyLen)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n", wdev->WepStatus)); + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_giwencode(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + int kid; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + kid = pIoctlSec->KeyIdx; /*erq->flags & IW_ENCODE_INDEX; */ + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", kid)); + + if (wdev->WepStatus == Ndis802_11WEPDisabled) + { + pIoctlSec->length = 0; + pIoctlSec->flags = RT_CMD_STA_IOCTL_SECURITY_DISABLED; + } + else if ((kid > 0) && (kid <=4)) + { + /* copy wep key */ + pIoctlSec->KeyIdx = kid; + if (pIoctlSec->length > pAd->SharedKey[BSS0][kid-1].KeyLen) + pIoctlSec->length = pAd->SharedKey[BSS0][kid-1].KeyLen; + memcpy(pIoctlSec->pData, pAd->SharedKey[BSS0][kid-1].Key, pIoctlSec->length); + if (wdev->AuthMode == Ndis802_11AuthModeShared) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_RESTRICTED; /* XXX */ + else + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_OPEN; /* XXX */ + + } + else if (kid == 0) + { + if (wdev->AuthMode == Ndis802_11AuthModeShared) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_RESTRICTED; /* XXX */ + else + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_OPEN; /* XXX */ + pIoctlSec->length = pAd->SharedKey[BSS0][wdev->DefaultKeyId].KeyLen; + memcpy(pIoctlSec->pData, pAd->SharedKey[BSS0][wdev->DefaultKeyId].Key, pIoctlSec->length); + /* copy default key ID */ + if (wdev->AuthMode == Ndis802_11AuthModeShared) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_RESTRICTED; /* XXX */ + else + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_OPEN; /* XXX */ + pIoctlSec->KeyIdx = wdev->DefaultKeyId + 1; /* NB: base 1 */ + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_ENABLED; /* XXX */ + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWMLME. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwmlme( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data, + IN UINT32 Subcmd) +{ + MLME_QUEUE_ELEM *pMsgElem = NULL; + MLME_DISASSOC_REQ_STRUCT DisAssocReq; + MLME_DEAUTH_REQ_STRUCT DeAuthReq; + ULONG reason_code = (ULONG)Data; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pMsgElem, sizeof(MLME_QUEUE_ELEM)); + if (pMsgElem == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + switch(Subcmd) + { + case RT_CMD_STA_IOCTL_IW_MLME_DEAUTH: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__)); + COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); + DeAuthReq.Reason = reason_code; + pMsgElem->MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); + NdisMoveMemory(pMsgElem->Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT)); + MlmeDeauthReqAction(pAd, pMsgElem); + if (INFRA_ON(pAd)) + { + LinkDown(pAd, FALSE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + break; + case RT_CMD_STA_IOCTL_IW_MLME_DISASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__)); + NdisZeroMemory(pAd->StaCfg.ConnectinfoSsid, MAX_LEN_OF_SSID); + NdisZeroMemory(pAd->StaCfg.ConnectinfoBssid, MAC_ADDR_LEN); + pAd->StaCfg.ConnectinfoSsidLen = 0; + pAd->StaCfg.ConnectinfoBssType = 1; + pAd->StaCfg.ConnectinfoChannel = 0; + + COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid); + DisAssocReq.Reason = reason_code; + + pMsgElem->Machine = ASSOC_STATE_MACHINE; + pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(pMsgElem->Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, pMsgElem); + break; + } + + if (pMsgElem != NULL) + os_free_mem(NULL, pMsgElem); + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWAUTH. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwauth( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY_ADV *pIoctlWpa = (RT_CMD_STA_IOCTL_SECURITY_ADV *)pData; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + switch (pIoctlWpa->flags) + { + case RT_CMD_STA_IOCTL_WPA_VERSION: + if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_VERSION1) + { + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + if (pAd->StaCfg.BssType == BSS_ADHOC) + wdev->AuthMode = Ndis802_11AuthModeWPANone; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_VERSION2) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_PAIRWISE: + if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_NONE) + { + wdev->WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP40 || + pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP104) + { + wdev->WepStatus = Ndis802_11WEPEnabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.wdev.IEEE8021X = FALSE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_TKIP) + { + wdev->WepStatus = Ndis802_11TKIPEnable; + pAd->StaCfg.PairCipher = Ndis802_11TKIPEnable; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_CCMP) + { + wdev->WepStatus = Ndis802_11AESEnable; + pAd->StaCfg.PairCipher = Ndis802_11AESEnable; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_GROUP: + if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_GROUP_NONE) + { + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_GROUP_WEP40) + { + pAd->StaCfg.GroupCipher = Ndis802_11GroupWEP40Enabled; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_GROUP_WEP104) + { + pAd->StaCfg.GroupCipher = Ndis802_11GroupWEP104Enabled; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_GROUP_TKIP) + { + pAd->StaCfg.GroupCipher = Ndis802_11TKIPEnable; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_GROUP_CCMP) + { + pAd->StaCfg.GroupCipher = Ndis802_11AESEnable; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_KEY_MGMT: +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP &= 0x7F; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_KEY_MGMT_1X) + { + if (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) + { + wdev->AuthMode = Ndis802_11AuthModeWPA; +#ifdef WPA_SUPPLICANT_SUPPORT + wdev->IEEE8021X = FALSE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } + else if (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) + { + wdev->AuthMode = Ndis802_11AuthModeWPA2; +#ifdef WPA_SUPPLICANT_SUPPORT + wdev->IEEE8021X = FALSE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } +#ifdef WPA_SUPPLICANT_SUPPORT + else + /* WEP 1x */ + wdev->IEEE8021X = TRUE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + else if (pIoctlWpa->value == 0) + { + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_AUTH_RX_UNENCRYPTED_EAPOL: + break; + case RT_CMD_STA_IOCTL_WPA_AUTH_PRIVACY_INVOKED: + /*if (pIoctlWpa->value == 0) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + }*/ + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED: + if (pIoctlWpa->value != 0) + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_DROP_UNENCRYPTED - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG: + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, pIoctlWpa->value)); + break; + case RT_CMD_STA_IOCTL_WPA_AUTH_COUNTERMEASURES: + if (pIoctlWpa->value == 1 ) + pAd->StaCfg.bBlockAssoc = TRUE; + else + pAd->StaCfg.bBlockAssoc = FALSE; +} + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWAUTH. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwauth(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY_ADV *pIoctlWpa = (RT_CMD_STA_IOCTL_SECURITY_ADV *)pData; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + switch (pIoctlWpa->flags) { + case RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED: + pIoctlWpa->value = (wdev->WepStatus == Ndis802_11WEPDisabled) ? 0 : 1; + break; + + case RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG: + pIoctlWpa->value = (wdev->AuthMode == Ndis802_11AuthModeShared) ? 0 : 1; + break; + + case RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED: + pIoctlWpa->value = (wdev->AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0; + break; + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Set security key. + +Arguments: + pAd - WLAN control block pointer + keyIdx - key index + CipherAlg - cipher algorithm + bGTK - 1: the key is group key + *pKey - the key + +Return Value: + None + +Note: +======================================================================== +*/ +void fnSetCipherKey( + IN PRTMP_ADAPTER pAd, + IN INT keyIdx, + IN UCHAR CipherAlg, + IN BOOLEAN bGTK, + IN UCHAR *pKey) +{ + NdisZeroMemory(&pAd->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][keyIdx].KeyLen = LEN_TK; + NdisMoveMemory(pAd->SharedKey[BSS0][keyIdx].Key, pKey, LEN_TK); + NdisMoveMemory(pAd->SharedKey[BSS0][keyIdx].TxMic, pKey + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][keyIdx].RxMic, pKey + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + pAd->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg; + + if (!bGTK) + { + MAC_TABLE_ENTRY *pEntry; + /* Update these related information to MAC_TABLE_ENTRY */ + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][keyIdx].Key, LEN_TK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][keyIdx].RxMic, LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][keyIdx].TxMic, LEN_TKIP_MIC); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][keyIdx].CipherAlg; + + pEntry->PairwiseKey.KeyLen = LEN_TK; + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + BSS0, + 0, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->wcid, + PAIRWISEKEYTABLE); + } + else + { + pAd->StaCfg.wdev.DefaultKeyId = keyIdx; + /* Update group key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + keyIdx, + &pAd->SharedKey[BSS0][keyIdx]); + } +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWENCODEEXT. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_siwencodeext(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + int keyIdx; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if (pIoctlSec->flags == RT_CMD_STA_IOCTL_SECURITY_DISABLED) + { + keyIdx = pIoctlSec->KeyIdx; /*(encoding->flags & IW_ENCODE_INDEX) - 1; */ + /* set BSSID wcid entry of the Pair-wise Key table as no-security mode */ + AsicRemovePairwiseKeyEntry(pAd, BSSID_WCID); + pAd->SharedKey[BSS0][keyIdx].KeyLen = 0; + pAd->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, 0, (UCHAR)keyIdx); + NdisZeroMemory(&pAd->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!\n", __FUNCTION__)); + } + else + { + /* Get Key Index and convet to our own defined key index */ + keyIdx = pIoctlSec->KeyIdx; /*(encoding->flags & IW_ENCODE_INDEX) - 1; */ + if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + return NDIS_STATUS_FAILURE; + + if (pIoctlSec->ext_flags & RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY) + { + wdev->DefaultKeyId = keyIdx; + DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, wdev->DefaultKeyId)); + } + + switch (pIoctlSec->Alg) { + case RT_CMD_STA_IOCTL_SECURITY_ALG_NONE: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__)); + break; + case RT_CMD_STA_IOCTL_SECURITY_ALG_WEP: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, pIoctlSec->length, keyIdx)); + if (pIoctlSec->length == MAX_WEP_KEY_SIZE) + { + pAd->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; + pAd->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; + } + else if (pIoctlSec->length == MIN_WEP_KEY_SIZE) + { + pAd->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; + pAd->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; + } + else + return NDIS_STATUS_FAILURE; + + NdisZeroMemory(pAd->SharedKey[BSS0][keyIdx].Key, 16); + NdisMoveMemory(pAd->SharedKey[BSS0][keyIdx].Key, pIoctlSec->pData, pIoctlSec->length); + + if ((pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) || + (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)) + { + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, keyIdx, &pAd->SharedKey[BSS0][keyIdx]); + +/* + STA doesn't need to set WCID attribute for group key +*/ + STA_PORT_SECURED(pAd); + } + break; + case RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, pIoctlSec->length)); + if (pIoctlSec->length == 32) + { + if (wdev->AuthMode == Ndis802_11AuthModeWPANone) + { + RTMPZeroMemory(pAd->StaCfg.PMK, LEN_PMK); + RTMPMoveMemory(pAd->StaCfg.PMK, pIoctlSec->pData, pIoctlSec->length); + } + else + { + if (pIoctlSec->ext_flags & RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY) + { + fnSetCipherKey(pAd, keyIdx, CIPHER_TKIP, FALSE, pIoctlSec->pData); + if (wdev->AuthMode >= Ndis802_11AuthModeWPA2) + { + STA_PORT_SECURED(pAd); + } + } + else if (pIoctlSec->ext_flags & RT_CMD_STA_IOCTL_SECURTIY_EXT_GROUP_KEY) + { + fnSetCipherKey(pAd, keyIdx, CIPHER_TKIP, TRUE, pIoctlSec->pData); + + /* set 802.1x port control */ + STA_PORT_SECURED(pAd); + } + } + } + else + return NDIS_STATUS_FAILURE; + break; + case RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP: + if (wdev->AuthMode == Ndis802_11AuthModeWPANone) + { + RTMPZeroMemory(pAd->StaCfg.PMK, LEN_PMK); + RTMPMoveMemory(pAd->StaCfg.PMK, pIoctlSec->pData, pIoctlSec->length); + } + else + { + if (pIoctlSec->ext_flags & RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY) + { + fnSetCipherKey(pAd, keyIdx, CIPHER_AES, FALSE, pIoctlSec->pData); + if (wdev->AuthMode >= Ndis802_11AuthModeWPA2) + { + STA_PORT_SECURED(pAd); + } + } + else if (pIoctlSec->ext_flags & RT_CMD_STA_IOCTL_SECURTIY_EXT_GROUP_KEY) + { + fnSetCipherKey(pAd, keyIdx, CIPHER_AES, TRUE, pIoctlSec->pData); + + /* set 802.1x port control */ + STA_PORT_SECURED(pAd); + } + } + break; + default: + return NDIS_STATUS_FAILURE; + } + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWENCODEEXT. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_giwencodeext(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + int idx; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + idx = pIoctlSec->KeyIdx; + if (idx) + { + if (idx < 1 || idx > 4) + { + pIoctlSec->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_FAILURE; + } + idx--; + + if ((wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable)) + { + if (idx != wdev->DefaultKeyId) + { + pIoctlSec->Status = 0; + pIoctlSec->length = 0; + return NDIS_STATUS_FAILURE; + } + } + } + else + idx = wdev->DefaultKeyId; + + pIoctlSec->KeyIdx = idx + 1; + + pIoctlSec->length = 0; + switch(wdev->WepStatus) { + case Ndis802_11WEPDisabled: + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_NONE; + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_DISABLED; + break; + case Ndis802_11WEPEnabled: + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_WEP; + if (pAd->SharedKey[BSS0][idx].KeyLen > pIoctlSec->MaxKeyLen) + { + pIoctlSec->Status = RTMP_IO_E2BIG; + return NDIS_STATUS_FAILURE; + } + else + { + pIoctlSec->length = pAd->SharedKey[BSS0][idx].KeyLen; + pIoctlSec->pData = (PCHAR)&(pAd->SharedKey[BSS0][idx].Key[0]); + } + break; + case Ndis802_11TKIPEnable: + case Ndis802_11AESEnable: + if (wdev->WepStatus == Ndis802_11TKIPEnable) + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_TKIP; + else + pIoctlSec->Alg = RT_CMD_STA_IOCTL_SECURITY_ALG_CCMP; + + if (pIoctlSec->MaxKeyLen < 32) + { + pIoctlSec->Status = RTMP_IO_E2BIG; + return NDIS_STATUS_FAILURE; + } + else + { + pIoctlSec->length = 32; + pIoctlSec->pData = (PCHAR)&pAd->StaCfg.PMK[0]; + } + break; + default: + pIoctlSec->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWGENIE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwgenie( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ +#ifdef WPA_SUPPLICANT_SUPPORT + ULONG length = (ULONG)Data; + + + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwgenie\n")); + pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant = FALSE; + if ((length > 0) && (pData == NULL)) + { + return NDIS_STATUS_FAILURE; + } + else if (length) + { + if (pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe) + { + os_free_mem(NULL, pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe); + pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe = NULL; + } + os_alloc_mem(NULL, (UCHAR **)&pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe, length); + if (pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe) + { + pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen = length; + NdisMoveMemory(pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe, pData, pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen); + pAd->StaCfg.wpa_supplicant_info.bRSN_IE_FromWpaSupplicant = TRUE; + } + else + pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen = 0; + } + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWGENIE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwgenie(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_STA_IOCTL_RSN_IE *IoctlRsnIe = (RT_CMD_STA_IOCTL_RSN_IE *)pData; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if ((pAd->StaCfg.RSNIE_Len == 0) || + (wdev->AuthMode < Ndis802_11AuthModeWPA)) + { + IoctlRsnIe->length = 0; + return NDIS_STATUS_SUCCESS; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + /* + Can not use SIOCSIWGENIE definition, it is used in wireless.h + We will not see the definition in MODULE. + The definition can be saw in UTIL and NETIF. + */ +/* #ifdef SIOCSIWGENIE */ + if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE && + (pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen > 0)) + { + if (IoctlRsnIe->length < pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen) + return NDIS_STATUS_FAILURE; + + IoctlRsnIe->length = pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen; + memcpy(IoctlRsnIe->pRsnIe, pAd->StaCfg.wpa_supplicant_info.pWpaAssocIe, pAd->StaCfg.wpa_supplicant_info.WpaAssocIeLen); + } + else +/* #endif */ /* SIOCSIWGENIE */ +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + { + UCHAR RSNIe = IE_WPA; + + if (IoctlRsnIe->length < (pAd->StaCfg.RSNIE_Len + 2)) /* ID, Len */ + return NDIS_STATUS_FAILURE; + IoctlRsnIe->length = pAd->StaCfg.RSNIE_Len + 2; + + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2)) + RSNIe = IE_RSN; + + IoctlRsnIe->pRsnIe[0] = (char)RSNIe; + IoctlRsnIe->pRsnIe[1] = pAd->StaCfg.RSNIE_Len; + memcpy(IoctlRsnIe->pRsnIe+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWPMKSA. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_siwpmksa( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_PMA_SA *pIoctlPmaSa = (RT_CMD_STA_IOCTL_PMA_SA *)pData; + INT CachedIdx = 0, idx = 0; + + + switch(pIoctlPmaSa->Cmd) + { + case RT_CMD_STA_IOCTL_PMA_SA_FLUSH: + NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n")); + break; + case RT_CMD_STA_IOCTL_PMA_SA_REMOVE: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + /* compare the BSSID */ + if (NdisEqualMemory(pIoctlPmaSa->pBssid, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) + { + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN); + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16); + for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++) + { + NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16); + } + pAd->StaCfg.SavedPMKNum--; + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n")); + break; + case RT_CMD_STA_IOCTL_PMA_SA_ADD: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + /* compare the BSSID */ + if (NdisEqualMemory(pIoctlPmaSa->pBssid, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) + break; + } + + /* Found, replace it */ + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pIoctlPmaSa->pBssid, MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pIoctlPmaSa->pPmkid, 16); + pAd->StaCfg.SavedPMKNum++; + } + /* Not found, replace the last one */ + else + { + /* Randomly replace one */ + CachedIdx = (pIoctlPmaSa->pBssid[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pIoctlPmaSa->pBssid, MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pIoctlPmaSa->pPmkid, 16); + } + + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n")); + break; + default: + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n")); + break; + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWRATE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_siwrate(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + RT_CMD_RATE_SET *pCmdRate = (RT_CMD_RATE_SET *)pData; + UINT32 rate = pCmdRate->Rate; + UINT32 fixed = pCmdRate->Fixed; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /* + rate = -1 => auto rate + rate = X, => fixed = 1 and rate fixed at X + */ + if (rate == -1) + { + /*Auto Rate */ + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + wdev->bAutoTxRateSwitch = TRUE; + if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, -1); + +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + else + { + if (fixed) + { + wdev->bAutoTxRateSwitch = FALSE; + if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, rate); + else + { + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwrate::(HtMcs=%d)\n", wdev->DesiredTransmitSetting.field.MCS)); + } + else + { + /* TODO: rate = X, fixed = 0 => (rates <= X) */ + return NDIS_STATUS_FAILURE; + } + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWRATE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_giwrate(RTMP_ADAPTER *pAd, VOID *pData, ULONG Data) +{ + int rate_index = 0, rate_count = 0; + HTTRANSMIT_SETTING ht_setting; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + + if ((wdev->bAutoTxRateSwitch == FALSE) && + (INFRA_ON(pAd)) && + ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))) + ht_setting.word = wdev->HTPhyMode.word; + else + ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; +RtmpDrvRateGet(pAd,ht_setting.field.MODE,ht_setting.field.ShortGI,ht_setting.field.BW + ,ht_setting.field.MCS,newRateGetAntenna(ht_setting.field.MCS, ht_setting.field.MODE), + (UINT32 *)pData); + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIFHWADDR. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_gifhwaddr( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + memcpy(pData, pAd->CurrentAddress, ETH_ALEN); + return NDIS_STATUS_SUCCESS; +} + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCSIWPRIVRSSI. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_rssi( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + + (*(CHAR *)pData) = pAd->StaCfg.RssiSample.AvgRssi0; + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_IW_SET_PARAM_PRE. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_ioctl_setparam( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + POS_COOKIE pObj; + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_U32_ITEM. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_private_set_wsc_u32_item( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ +#ifdef WSC_STA_SUPPORT + RT_CMD_STA_IOCTL_WSC_U32_ITEM *pIoctlWscU32 = (RT_CMD_STA_IOCTL_WSC_U32_ITEM *)pData; + u32 subcmd = *(pIoctlWscU32->pUWrq); + PWSC_PROFILE pWscProfile = NULL; + u32 value = 0; + + pWscProfile = &pAd->StaCfg.WscControl.WscProfile; + + switch(subcmd) + { + case WSC_CREDENTIAL_COUNT: + value = *(pIoctlWscU32->pUWrq + 1); + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_COUNT, value = %d\n", __FUNCTION__, value)); + if (value <= 8) + { + pWscProfile->ProfileCnt = value; + } + else + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + case WSC_SET_DRIVER_CONNECT_BY_CREDENTIAL_IDX: + value = *(pIoctlWscU32->pUWrq + 1); + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_DRIVER_CONNECT_BY_CREDENTIAL_IDX, value = %d\n", __FUNCTION__, value)); + if ((value <= 7) && + (value < pWscProfile->ProfileCnt)) + { + WscWriteConfToPortCfg(pAd, &pAd->StaCfg.WscControl, &pAd->StaCfg.WscControl.WscProfile.Profile[value], TRUE); + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + LinkDown(pAd, TRUE); + } + else + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + case WSC_SET_DRIVER_AUTO_CONNECT: + value = *(pIoctlWscU32->pUWrq + 1); + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_DRIVER_AUTO_CONNECT, value = %d\n", __FUNCTION__, value)); + if ((value == 0x00) || + (value == 0x01) || + (value == 0x02)) + { + pAd->StaCfg.WscControl.WscDriverAutoConnect = value; + } + else + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + case WSC_SET_CONF_MODE: + value = *(pIoctlWscU32->pUWrq + 1); + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_CONF_MODE, value = %d\n", __FUNCTION__, value)); + if (value == 2) + value = 4; + switch(value) + { + case WSC_DISABLE: + Set_WscConfMode_Proc(pAd, "0"); + break; + case WSC_ENROLLEE: + Set_WscConfMode_Proc(pAd, "1"); + break; + case WSC_REGISTRAR: + Set_WscConfMode_Proc(pAd, "2"); + break; + default: + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + } + break; + case WSC_SET_MODE: + value = *(pIoctlWscU32->pUWrq + 1); + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_MODE, value = %d\n", __FUNCTION__, value)); + switch(value) + { + case WSC_PIN_MODE: + if (Set_WscMode_Proc(pAd, "1") == FALSE) + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + case WSC_PBC_MODE: + if (Set_WscMode_Proc(pAd, "2") == FALSE) + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + case WSC_SMPBC_MODE: + if (Set_WscMode_Proc(pAd, "3") == FALSE) + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + default: + pIoctlWscU32->Status = RTMP_IO_EINVAL; + break; + } + break; + case WSC_START: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_START\n", __FUNCTION__)); + Set_WscGetConf_Proc(pAd, "1"); + break; + case WSC_STOP: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_STOP\n", __FUNCTION__)); + + /* Disassociate the link if WPS is working. */ + if ( INFRA_ON(pAd) && + (pAd->StaCfg.WscControl.bWscTrigger == TRUE) && + (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) ) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + + /* Set to immediately send the media disconnect event */ + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("disassociate with current AP \n")); + DisassocParmFill(pAd, &DisReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + RTMP_MLME_HANDLER(pAd); + } + +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + pAd->StaCfg.WscControl.WscConfMode = WSC_DISABLE; + pAd->StaCfg.WscControl.WscState = WSC_STATE_INIT; + pAd->StaCfg.WscControl.WscStatus = STATUS_WSC_IDLE; + if (pAd->StaCfg.WscControl.bWscTrigger) + IWSC_Stop(pAd, TRUE); + else + IWSC_Stop(pAd, FALSE); + } + else +#endif /* IWSC_SUPPORT */ + { + /* Turn off WSC state matchine */ + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif /* CONFIG_AP_SUPPORT */ + &pAd->StaCfg.WscControl); + pAd->StaCfg.WscControl.WscConfMode = WSC_DISABLE; + BssTableDeleteEntry(&pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Bssid, pAd->MlmeAux.Channel); + } + break; + case WSC_GEN_PIN_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_GEN_PIN_CODE\n", __FUNCTION__)); + Set_WscGenPinCode_Proc(pAd, "1"); + break; + + case WSC_AP_BAND: + value = *(pIoctlWscU32->pUWrq + 1); + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_PBC_BAND, value = %d\n", __FUNCTION__, value)); + if (value < PREFERRED_WPS_AP_PHY_TYPE_MAXIMUM) + { + pAd->StaCfg.WscControl.WpsApBand= value; + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d, value = %d\n", __FUNCTION__, subcmd, value)); + break; + } +#endif /* WSC_STA_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_IW_SET_WSC_STR_ITEM. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_private_set_wsc_string_item( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ +#ifdef WSC_STA_SUPPORT + RT_CMD_STA_IOCTL_WSC_STR_ITEM *pIoctlWscStr = (RT_CMD_STA_IOCTL_WSC_STR_ITEM *)pData; +/* int Status=0; */ + UINT32 subcmd = pIoctlWscStr->Subcmd; + UINT32 tmpProfileIndex = (UINT32)(pIoctlWscStr->pData[0] - 0x30); + UINT32 dataLen; + PWSC_PROFILE pWscProfile = NULL; + USHORT tmpAuth = 0, tmpEncr = 0; + char *extra = (char *)pIoctlWscStr->pData; + + pWscProfile = &pAd->StaCfg.WscControl.WscProfile; + + if ((subcmd != WSC_SET_SSID) && + (subcmd != WSC_SET_PIN) && + (subcmd != WSC_SET_BSSID) && + (tmpProfileIndex > 7)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - subcmd = %d, tmpProfileIndex = %d\n", __FUNCTION__, subcmd, tmpProfileIndex)); + pIoctlWscStr->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_SUCCESS; + } + + if ((subcmd != WSC_SET_SSID) && + (subcmd != WSC_SET_PIN) && + (subcmd != WSC_SET_BSSID)) + /* extra: "1 input_string", dwrq->length includes '\0'. 3 is size of [index, blank and '\0'] */ + dataLen = pIoctlWscStr->length - 3; + else + dataLen = pIoctlWscStr->length; + + switch(subcmd) + { + case WSC_CREDENTIAL_SSID: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_SSID(%s)\n", __FUNCTION__, extra+2)); + if (dataLen == (NDIS_802_11_LENGTH_SSID+1)) + dataLen = NDIS_802_11_LENGTH_SSID; + if (dataLen > 0 && dataLen <= NDIS_802_11_LENGTH_SSID) + { + pWscProfile->Profile[tmpProfileIndex].SSID.SsidLength = dataLen; + NdisZeroMemory(pWscProfile->Profile[tmpProfileIndex].SSID.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pWscProfile->Profile[tmpProfileIndex].SSID.Ssid, extra+2, dataLen); + } + else + pIoctlWscStr->Status = RTMP_IO_E2BIG; + break; + case WSC_CREDENTIAL_AUTH_MODE: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_AUTH_MODE(%s)\n", __FUNCTION__, extra+2)); + if ((tmpAuth = WscGetAuthTypeFromStr(extra+2)) != 0) + { + pWscProfile->Profile[tmpProfileIndex].AuthType = tmpAuth; + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + break; + case WSC_CREDENTIAL_ENCR_TYPE: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_ENCR_TYPE(%s)\n", __FUNCTION__, extra+2)); + if ((tmpEncr = WscGetEncrypTypeFromStr(extra+2)) != 0) + { + pWscProfile->Profile[tmpProfileIndex].EncrType = tmpEncr; + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + break; + case WSC_CREDENTIAL_KEY_INDEX: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_KEY_INDEX(%s)\n", __FUNCTION__, extra+2)); + if ( *(extra+2) >= 0x31 && *(extra+2) <= 0x34) + { + pWscProfile->Profile[tmpProfileIndex].KeyIndex = (UCHAR)*(extra+2) - 0x30; + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + break; + case WSC_CREDENTIAL_KEY: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_KEY(%s)\n", __FUNCTION__, extra+2)); + if ((dataLen >= 8 && dataLen <= 64) || + (dataLen == 5 || dataLen == 10 || dataLen == 13 || dataLen == 26)) + { + pWscProfile->Profile[tmpProfileIndex].KeyLength = dataLen; + NdisZeroMemory(pWscProfile->Profile[tmpProfileIndex].Key, 64); + NdisMoveMemory(pWscProfile->Profile[tmpProfileIndex].Key, extra+2, dataLen); + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + break; + case WSC_CREDENTIAL_MAC: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_CREDENTIAL_MAC(%s)\n", __FUNCTION__, extra+2)); + { + INT sscanf_rv = 0; + UINT tmp_val[6] = {0}; + sscanf_rv = sscanf(extra+2, "%02x:%02x:%02x:%02x:%02x:%02x", + &tmp_val[0], + &tmp_val[1], + &tmp_val[2], + &tmp_val[3], + &tmp_val[4], + &tmp_val[5]); + if ( sscanf_rv == 6) + { + int ii; + NdisZeroMemory(pWscProfile->Profile[tmpProfileIndex].MacAddr, 6); + for (ii=0; ii<6; ii++) + pWscProfile->Profile[tmpProfileIndex].MacAddr[ii] = (UCHAR)tmp_val[ii]; + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + } + break; + case WSC_SET_SSID: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_SSID(%s)\n", __FUNCTION__, extra)); + if (dataLen == (NDIS_802_11_LENGTH_SSID+1)) + dataLen = NDIS_802_11_LENGTH_SSID; + if (dataLen > 0 && dataLen <= NDIS_802_11_LENGTH_SSID) + { + Set_WscSsid_Proc(pAd, (PSTRING) extra); + } + else + pIoctlWscStr->Status = RTMP_IO_E2BIG; + break; + case WSC_SET_PIN: + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_PIN, value = (%s)\n", __FUNCTION__, extra)); + if ( dataLen > 0 ) + { + if (Set_WscPinCode_Proc(pAd, extra) == FALSE) + pIoctlWscStr->Status = RTMP_IO_EINVAL; + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + break; + case WSC_SET_BSSID: + if ( dataLen > 0 ) + { + if (Set_WscBssid_Proc(pAd, (PSTRING) extra) == FALSE) + pIoctlWscStr->Status = RTMP_IO_EINVAL; + } + else + pIoctlWscStr->Status = RTMP_IO_EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SET_BSSID\n", __FUNCTION__)); + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd)); + break; + } +#endif /* WSC_STA_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_IW_GET_STATISTICS. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT +RtmpIoctl_rt_private_get_statistics( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + char *extra = (char *)pData; + ULONG txCount = 0; +#ifdef ENHANCED_STAT_DISPLAY + ULONG per, plr; +#endif +#ifdef WSC_STA_SUPPORT + UINT32 MaxSize = (UINT32)Data; +#endif /* WSC_STA_SUPPORT */ + + + sprintf(extra, "\n\n"); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + txCount = pAd->ate.TxDoneCount; + else +#endif /* RALINK_ATE */ + txCount = (ULONG)pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + + sprintf(extra+strlen(extra), "Tx success = %lu\n", txCount); +#ifdef ENHANCED_STAT_DISPLAY + per = txCount==0? 0: 1000*(pAd->WlanCounters.RetryCount.u.LowPart+pAd->WlanCounters.FailedCount.u.LowPart)/(pAd->WlanCounters.RetryCount.u.LowPart+pAd->WlanCounters.FailedCount.u.LowPart+txCount); + sprintf(extra+strlen(extra), "Tx retry count = %lu, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.RetryCount.u.LowPart, + per/10, per % 10); + plr = txCount==0? 0: 10000*pAd->WlanCounters.FailedCount.u.LowPart/(pAd->WlanCounters.FailedCount.u.LowPart+txCount); + sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry = %lu, PLR=%ld.%02ld%%\n", + (ULONG)pAd->WlanCounters.FailedCount.u.LowPart, plr/100, plr%100); +#else + sprintf(extra+strlen(extra), "Tx retry count = %lu\n", (ULONG)pAd->WlanCounters.RetryCount.u.LowPart); + sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry = %lu\n", (ULONG)pAd->WlanCounters.FailedCount.u.LowPart); + sprintf(extra+strlen(extra), "RTS Success Rcv CTS = %lu\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.u.LowPart); + sprintf(extra+strlen(extra), "RTS Fail Rcv CTS = %lu\n", (ULONG)pAd->WlanCounters.RTSFailureCount.u.LowPart); +#endif /* ENHANCED_STAT_DISPLAY */ + + sprintf(extra+strlen(extra), "Rx success = %lu\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart); +#ifdef ENHANCED_STAT_DISPLAY + per = pAd->WlanCounters.ReceivedFragmentCount.u.LowPart==0? 0: 1000*(pAd->WlanCounters.FCSErrorCount.u.LowPart)/(pAd->WlanCounters.FCSErrorCount.u.LowPart+pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + sprintf(extra+strlen(extra), "Rx with CRC = %ld, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.FCSErrorCount.u.LowPart, per/10, per % 10); + sprintf(extra+strlen(extra), "Rx drop due to out of resource = %lu\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(extra+strlen(extra), "Rx duplicate frame = %lu\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + + sprintf(extra+strlen(extra), "False CCA = %lu\n", (ULONG)pAd->RalinkCounters.FalseCCACnt); +#else + sprintf(extra+strlen(extra), "Rx with CRC = %lu\n", (ULONG)pAd->WlanCounters.FCSErrorCount.u.LowPart); + sprintf(extra+strlen(extra), "Rx drop due to out of resource = %lu\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(extra+strlen(extra), "Rx duplicate frame = %lu\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + + sprintf(extra+strlen(extra), "False CCA (one second) = %lu\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt); +#endif /* ENHANCED_STAT_DISPLAY */ + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + if (pAd->ate.RxAntennaSel == 0) + { + sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } + else + { + sprintf(extra+strlen(extra), "RSSI = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + } + } + else +#endif /* RALINK_ATE */ + { +#ifdef ENHANCED_STAT_DISPLAY + sprintf(extra+strlen(extra), "RSSI = %ld %ld %ld\n", + (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta), + (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta), + (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); + + // Display Last Rx Rate and BF SNR of first Associated entry in MAC table + if (pAd->MacTab.Size > 0) + { + static char *phyMode[5] = {"CCK", "OFDM", "MM", "GF", "VHT"}; + static char *bw[3] = {"20M", "40M", "80M"}; + static char *fec_coding[2] = {"bcc", "ldpc"}; + int i; + + for (i=1; iMacTab.Content[i]); + if (IS_ENTRY_CLIENT(pEntry) && pEntry->Sst==SST_ASSOC) + { + UINT32 lastRxRate = pEntry->LastRxRate; + UINT32 lastTxRate = pEntry->LastTxRate; + +#ifdef RT65xx + if (IS_RT65XX(pAd)) { + if (((lastTxRate >> 13) & 0x7) == 0x04) { + sprintf(extra+strlen(extra), "Last TX Rate = MCS%d, %dSS, %s, %s, %cGI, %s%s\n", + lastTxRate & 0x0F, + (((lastTxRate >> 4) & 0x3) + 1), + fec_coding[((lastTxRate >> 6) & 0x1)], + bw[((lastTxRate >> 7) & 0x3)], + ((lastTxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastTxRate >> 13) & 0x7], + ((lastTxRate >> 10) & 0x3)? ", STBC": " "); + + } else { + sprintf(extra+strlen(extra), "Last TX Rate = MCS%d, %s, %s, %cGI, %s%s\n", + lastTxRate & 0x3F, + fec_coding[((lastTxRate >> 6) & 0x1)], + bw[((lastTxRate >> 7) & 0x3)], + ((lastTxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastTxRate >> 13) & 0x7], + ((lastTxRate >> 10) & 0x3)? ", STBC": " "); + } + + if (((lastRxRate >> 13) & 0x7) == 0x04) { + sprintf(extra+strlen(extra), "Last RX Rate = MCS%d, %dSS, %s, %s, %cGI, %s%s\n", + lastRxRate & 0x0F, + (((lastRxRate >> 4) & 0x3) + 1), + fec_coding[((lastRxRate >> 6) & 0x1)], + bw[((lastRxRate >> 7) & 0x3)], + ((lastRxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastRxRate >> 13) & 0x7], + ((lastRxRate >> 10) & 0x3)? ", STBC": " "); + } else { + sprintf(extra+strlen(extra), "Last RX Rate = MCS%d, %s, %s, %cGI, %s%s\n", + lastRxRate & 0x3F, + fec_coding[((lastRxRate >> 6) & 0x1)], + bw[((lastRxRate >> 7) & 0x3)], + ((lastRxRate >> 9) & 0x1)? 'S': 'L', + phyMode[(lastRxRate >> 13) & 0x7], + ((lastRxRate >> 10) & 0x3)? ", STBC": " "); + } + } + + else +#endif + { + sprintf(extra+strlen(extra), "Last RX Rate = MCS %d, %2dM, %cGI, %s%s\n", + lastRxRate & 0x7F, ((lastRxRate>>7) & 0x1)? 40: 20, + ((lastRxRate>>8) & 0x1)? 'S': 'L', + phyMode[(lastRxRate>>14) & 0x3], + ((lastRxRate>>9) & 0x3)? ", STBC": " "); + } + break; + + } + } + } +#else + sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->StaCfg.RssiSample.AvgRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.AvgRssi2 - pAd->BbpRssiToDbmDelta)); +#endif /* ENHANCED_STAT_DISPLAY */ + + sprintf(extra+strlen(extra), "SNR-A = %ld\n", (LONG)(pAd->StaCfg.RssiSample.AvgSnr0)); + sprintf(extra+strlen(extra), "SNR-B (if available) = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.AvgSnr1)); + } + +#ifdef WPA_SUPPLICANT_SUPPORT + sprintf(extra+strlen(extra), "WpaSupplicantUP = %d\n\n", pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP); +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + sprintf(extra+strlen(extra), "FtSupport = %d\n\n", pAd->StaCfg.Dot11RCommInfo.bFtSupport); +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + /* display pin code */ + if (pAd->StaCfg.WscControl.WscEnrolleePinCodeLen == 8) + sprintf(extra+strlen(extra), "RT2860 Linux STA PinCode\t%08u\n", pAd->StaCfg.WscControl.WscEnrolleePinCode); + else + sprintf(extra+strlen(extra), "RT2860 Linux STA PinCode\t%04u\n", pAd->StaCfg.WscControl.WscEnrolleePinCode); +{ + char mode_str[16]={0}; + ULONG wps_status, wps_state; + int idx = 0; + + wps_state = pAd->StaCfg.WscControl.WscState; + wps_status = pAd->StaCfg.WscControl.WscStatus; + + if (pAd->StaCfg.WscControl.WscMode == WSC_PIN_MODE) + sprintf(mode_str, "PIN -"); + else + sprintf(mode_str, "PBC -"); + + sprintf(extra+strlen(extra), "WPS Information(Driver Auto-Connect is %s - %d):\n", + pAd->StaCfg.WscControl.WscDriverAutoConnect ? "Enabled":"Disabled", + pAd->StaCfg.WscControl.WscDriverAutoConnect); + /* display pin code */ + /*sprintf(extra+strlen(extra), "RT2860 Linux STA PinCode\t%08u\n", pAd->StaCfg.WscControl.WscEnrolleePinCode); */ + /* display status */ + if ((wps_state == WSC_STATE_OFF) || (wps_status & 0xff00)) + { + if (wps_status == STATUS_WSC_CONFIGURED) + { + sprintf(extra+strlen(extra), "WPS messages exchange successfully !!!\n"); + } + else if ((wps_status == STATUS_WSC_NOTUSED)) + { + sprintf(extra+strlen(extra), "WPS not used.\n"); + } + else if(wps_status & 0xff00) /* error message */ + { + if (wps_status == STATUS_WSC_PBC_TOO_MANY_AP) + sprintf(extra+strlen(extra), "%s Too many PBC AP. Stop WPS. \n", mode_str); + else if (wps_status == STATUS_WSC_PBC_NO_AP) + sprintf(extra+strlen(extra), "%s No available PBC AP. Please wait... \n", mode_str); + else if (wps_status & 0x0100) + sprintf(extra+strlen(extra), "%s Proceed to get the Registrar profile. Please wait... \n", mode_str); + else /* status of eap failed */ + sprintf(extra+strlen(extra), "WPS didn't complete !!!\n"); + } + else + { + /* wrong state */ + } + } + else + { + sprintf(extra+strlen(extra), "%s WPS Proceed. Please wait... \n", mode_str); + } + sprintf(extra+strlen(extra), "\n"); + sprintf(extra+strlen(extra), "WPS Profile Count = %d\n", pAd->StaCfg.WscControl.WscProfile.ProfileCnt); + for (idx = 0; idx < pAd->StaCfg.WscControl.WscProfile.ProfileCnt ; idx++) + { + PWSC_CREDENTIAL pCredential = &pAd->StaCfg.WscControl.WscProfile.Profile[idx]; + char ssid_print[MAX_LEN_OF_SSID + 1]; + NdisZeroMemory(&ssid_print[0], MAX_LEN_OF_SSID + 1); + if (strlen(extra) + sizeof(WSC_CREDENTIAL) >= MaxSize) + { + break; + } + + sprintf(extra+strlen(extra), "Profile[%d]:\n", idx); + NdisMoveMemory(&ssid_print[0], pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + sprintf(extra+strlen(extra), "SSID = %s\n", ssid_print); + sprintf(extra+strlen(extra), "MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + pCredential->MacAddr[0], + pCredential->MacAddr[1], + pCredential->MacAddr[2], + pCredential->MacAddr[3], + pCredential->MacAddr[4], + pCredential->MacAddr[5]); + sprintf(extra+strlen(extra), "AuthType = %s\n", WscGetAuthTypeStr(pCredential->AuthType)); + sprintf(extra+strlen(extra), "EncrypType = %s\n", WscGetEncryTypeStr(pCredential->EncrType)); + sprintf(extra+strlen(extra), "KeyIndex = %d\n", pCredential->KeyIndex); + if (pCredential->KeyLength != 0) + { + if (pCredential->AuthType & (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK | WSC_AUTHTYPE_WPANONE)) + { + if (pCredential->KeyLength < 64) + sprintf(extra+strlen(extra), "Key = %s\n", pCredential->Key); + else + { + char key_print[65] = {0}; + NdisMoveMemory(key_print, pCredential->Key, 64); + sprintf(extra+strlen(extra), "Key = %s\n", key_print); + } + } + else if ((pCredential->AuthType == WSC_AUTHTYPE_OPEN) || + (pCredential->AuthType == WSC_AUTHTYPE_SHARED)) + { + /*check key string is ASCII or not */ + if (RTMPCheckStrPrintAble((PCHAR)pCredential->Key, (UCHAR)pCredential->KeyLength)) + sprintf(extra+strlen(extra), "Key = %s\n", pCredential->Key); + else + { + int idx; + sprintf(extra+strlen(extra), "Key = "); + for (idx = 0; idx < pCredential->KeyLength; idx++) + sprintf(extra+strlen(extra), "%02X", pCredential->Key[idx]); + sprintf(extra+strlen(extra), "\n"); + } + } + } +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + sprintf(extra+strlen(extra), "Credential Registrar IPv4 Addr = %d:%d:%d:%d\n", + (pCredential->RegIpv4Addr & 0xFF000000)>>24, + (pCredential->RegIpv4Addr & 0x00FF0000)>>16, + (pCredential->RegIpv4Addr & 0x0000FF00)>>8, + (pCredential->RegIpv4Addr & 0x000000FF)); + sprintf(extra+strlen(extra), "Credential Entrollee IPv4 Addr = %d:%d:%d:%d\n", + (pCredential->EnrIpv4Addr & 0xFF000000)>>24, + (pCredential->EnrIpv4Addr & 0x00FF0000)>>16, + (pCredential->EnrIpv4Addr & 0x0000FF00)>>8, + (pCredential->EnrIpv4Addr & 0x000000FF)); + sprintf(extra+strlen(extra), "\nSelf IPv4 Addr = %d:%d:%d:%d\n", + (pIWscInfo->SelfIpv4Addr & 0xFF000000)>>24, + (pIWscInfo->SelfIpv4Addr & 0x00FF0000)>>16, + (pIWscInfo->SelfIpv4Addr & 0x0000FF00)>>8, + (pIWscInfo->SelfIpv4Addr & 0x000000FF)); + sprintf(extra+strlen(extra), "IPv4 Subnet Mask = %d:%d:%d:%d\n", + (pIWscInfo->Ipv4SubMask & 0xFF000000)>>24, + (pIWscInfo->Ipv4SubMask & 0x00FF0000)>>16, + (pIWscInfo->Ipv4SubMask & 0x0000FF00)>>8, + (pIWscInfo->Ipv4SubMask & 0x000000FF)); + sprintf(extra+strlen(extra), "AvaSubMaskListCount = %d", pIWscInfo->AvaSubMaskListCount); + } +#endif /* IWSC_SUPPORT */ + } + sprintf(extra+strlen(extra), "\n"); +} +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* Display Tx Aggregation statistics */ + DisplayTxAgg(pAd); +#endif /* DOT11_N_SUPPORT */ + return NDIS_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Communication with DRIVER module, whatever IOCTL. + +Arguments: + pAdSrc - WLAN control block pointer + *pRequest - the request from IOCTL + Command - communication command + Subcmd - communication sub-command + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RTMP_STA_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *pRequest, + IN INT Command, + IN USHORT Subcmd, + IN VOID *pData, + IN ULONG Data, + IN USHORT priv_flags) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT Status = NDIS_STATUS_SUCCESS; + + { /* determine this ioctl command is comming from which interface. */ + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + + /* handle by command */ + switch(Command) + { + case CMD_RT_PRIV_IOCTL: + if (Subcmd & OID_GET_SET_TOGGLE) + Status = RTMPSetInformation(pAd, pRequest, Subcmd); + else + Status = RTMPQueryInformation(pAd, pRequest, Subcmd); + break; + + case CMD_RTPRIV_IOCTL_PARAM_SET: + { + RT_CMD_PARAM_SET *pCmdParam = (RT_CMD_PARAM_SET *)pData; + PSTRING this_char = pCmdParam->pThisChar; + PSTRING value = pCmdParam->pValue; + + Status = RTMPSTAPrivIoctlSet(pAd, this_char, value); + } + break; + + case CMD_RTPRIV_IOCTL_SITESURVEY_GET: + RTMPIoctlGetSiteSurvey(pAd, pRequest); + break; + + case CMD_RTPRIV_IOCTL_MAC: + RTMPIoctlMAC(pAd, pRequest); + break; + + case CMD_RTPRIV_IOCTL_E2P: + RTMPIoctlE2PROM(pAd, pRequest); + break; + + case CMD_RTPRIV_IOCTL_RF: +#ifdef RTMP_RF_RW_SUPPORT + RTMPIoctlRF(pAd, pRequest); +#endif /* RTMP_RF_RW_SUPPORT */ + break; + + case CMD_RTPRIV_IOCTL_BBP: + RTMPIoctlBbp(pAd, pRequest, pData, Data); + break; + + case CMD_RTPRIV_IOCTL_SHOW: + RTMPIoctlShow(pAd, pRequest, Subcmd, pData, Data); + break; + + case CMD_RTPRIV_IOCTL_SITESURVEY: + StaSiteSurvey(pAd, (NDIS_802_11_SSID *)pData, Data); + break; + + case CMD_RTPRIV_IOCTL_CHID_2_FREQ: + RTMP_MapChannelID2KHZ(Data, (UINT32 *)pData); + break; + + case CMD_RTPRIV_IOCTL_FREQ_2_CHID: + RTMP_MapKHZ2ChannelID(Data, (UINT32 *)pData); + break; + + case CMD_RTPRIV_IOCTL_ORI_DEV_TYPE_SET: + pAd->StaCfg.OriDevType = Data; +#ifdef CONFIG_STA_SUPPORT +#ifdef CREDENTIAL_STORE + NdisAllocateSpinLock(pAd, &pAd->StaCtIf.Lock); +#endif /* CREDENTIAL_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + + break; + case CMD_RTPRIV_IOCTL_STA_SCAN_SANITY_CHECK: + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + pAd->StaCfg.bSkipAutoScanConn = TRUE; + return NDIS_STATUS_FAILURE; + } + + if (pAd->StaCfg.bImprovedScan) + { + /* + * Fast scanning doesn't complete yet. + */ + pAd->StaCfg.bSkipAutoScanConn = TRUE; + return NDIS_STATUS_FAILURE; + } + break; + + case CMD_RTPRIV_IOCTL_STA_SCAN_END: + pAd->StaCfg.bSkipAutoScanConn = FALSE; + DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %ld\n",pAd->ScanTab.BssNr , pAd->ScanTab.BssNr, Data)); + break; + + case CMD_RTPRIV_IOCTL_BSS_LIST_GET: + { + RT_CMD_STA_IOCTL_BSS_LIST *pBssList = (RT_CMD_STA_IOCTL_BSS_LIST *)pData; + RT_CMD_STA_IOCTL_BSS *pList; + UINT32 i; + + pBssList->BssNum = pAd->ScanTab.BssNr; + for (i = 0; i MaxNum ; i++) + { + if (i >= pAd->ScanTab.BssNr) + break; + pList = (pBssList->pList) + i; + set_quality(pList, &pAd->ScanTab.BssEntry[i]); + } + } + break; + + /* ------------------------------------------------------------------ */ + /* for standard IOCTL in LINUX OS */ + + RTMP_STA_STANDARD_IOCTL_HANDLE(pAd, pData, Data, Subcmd); + + /* ------------------------------------------------------------------ */ + + default: + /* for IOCTL that also can be used in AP mode */ + Status = RTMP_COM_IoctlHandle(pAd, pRequest, Command, Subcmd, pData, Data); + break; + } + + return Status; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta_iwsc.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta_iwsc.c new file mode 100644 index 000000000..320721f67 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sta_iwsc.c @@ -0,0 +1,1903 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-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. + *************************************************************************** + + Module Name: + sta_iwsc + + Abstract: + Handle IWSC for IBSS +*/ + +#ifdef IWSC_SUPPORT + +#include "rt_config.h" + +#define IWSC_SEL_REG_START_NOTITY 0 +#define IWSC_SEL_REG_FINISH_NOTITY 1 +#define IWSC_DEV_QUERY_REQUEST 2 +#define IWSC_DEV_QUERY_RESPONSE 3 + +#define IWSC_ENTRY_TIME_OUT 15000 + +extern UCHAR IWSC_OUI[]; +extern UCHAR ZERO_MAC_ADDR[]; +extern UCHAR IWSC_ACTION_OUI[]; + +VOID IWSC_MlmeStartAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_MlmeStopAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_InvalidState( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_ScanDoneAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_ReConnectAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_SendActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR FrameType); + +VOID IWSC_PeerAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_RoleAction( + IN PRTMP_ADAPTER pAd, + IN INT WscConfMode); + +ULONG IWSC_SearchWpsApByPinMethod( + IN PRTMP_ADAPTER pAd); + +VOID IWSC_GetConfigMethod( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pVIE, + IN INT VIELen, + OUT PUSHORT pConfigMethod); + +VOID IWSC_PeerProbeRequest( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_PeerProbeResponse( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_PeerPIN( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID IWSC_BuildDevQueryFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PUSHORT pIeLen); + +VOID IWSC_ResetIpContent( + IN PRTMP_ADAPTER pAd); + + +/* + ========================================================================== + Description: + IWSC state machine init, including state transition + Parameters: + Sm - pointer to the auth state machine + Note: + The state machine looks like this + ========================================================================== + */ +void IWSC_StateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, + Trans, + MAX_IWSC_STATE, + MAX_IWSC_MSG, + (STATE_MACHINE_FUNC)Drop, + IWSC_IDLE, + IWSC_MACHINE_BASE); + + StateMachineSetAction(Sm, IWSC_IDLE, IWSC_MT2_MLME_START, (STATE_MACHINE_FUNC)IWSC_MlmeStartAction); + StateMachineSetAction(Sm, IWSC_IDLE, IWSC_MT2_PEER_ACTION_FRAME, (STATE_MACHINE_FUNC)IWSC_PeerAction); + StateMachineSetAction(Sm, IWSC_IDLE, IWSC_MT2_MLME_SCAN_DONE, (STATE_MACHINE_FUNC)IWSC_ScanDoneAction); + StateMachineSetAction(Sm, IWSC_IDLE, IWSC_MT2_MLME_RECONNECT, (STATE_MACHINE_FUNC)IWSC_InvalidState); + + StateMachineSetAction(Sm, IWSC_START, IWSC_MT2_MLME_START, (STATE_MACHINE_FUNC)IWSC_MlmeStartAction); + StateMachineSetAction(Sm, IWSC_START, IWSC_MT2_MLME_STOP, (STATE_MACHINE_FUNC)IWSC_MlmeStopAction); + StateMachineSetAction(Sm, IWSC_START, IWSC_MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)IWSC_PeerProbeRequest); + StateMachineSetAction(Sm, IWSC_START, IWSC_MT2_MLME_SCAN_DONE, (STATE_MACHINE_FUNC)IWSC_ScanDoneAction); + StateMachineSetAction(Sm, IWSC_START, IWSC_MT2_MLME_RECONNECT, (STATE_MACHINE_FUNC)IWSC_ReConnectAction); + + StateMachineSetAction(Sm, IWSC_SCAN, IWSC_MT2_MLME_START, (STATE_MACHINE_FUNC)IWSC_MlmeStartAction); + StateMachineSetAction(Sm, IWSC_SCAN, IWSC_MT2_MLME_STOP, (STATE_MACHINE_FUNC)IWSC_MlmeStopAction); + StateMachineSetAction(Sm, IWSC_SCAN, IWSC_MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)IWSC_PeerProbeResponse); + StateMachineSetAction(Sm, IWSC_SCAN, IWSC_MT2_MLME_SCAN_DONE, (STATE_MACHINE_FUNC)IWSC_ScanDoneAction); + StateMachineSetAction(Sm, IWSC_SCAN, IWSC_MT2_MLME_RECONNECT, (STATE_MACHINE_FUNC)IWSC_InvalidState); + + StateMachineSetAction(Sm, IWSC_WAIT_PIN, IWSC_MT2_PEER_PIN, (STATE_MACHINE_FUNC)IWSC_PeerPIN); + StateMachineSetAction(Sm, IWSC_WAIT_PIN, IWSC_MT2_MLME_STOP, (STATE_MACHINE_FUNC)IWSC_MlmeStopAction); + + StateMachineSetAction(Sm, IWSC_WAIT_JOIN, IWSC_MT2_MLME_STOP, (STATE_MACHINE_FUNC)IWSC_MlmeStopAction); + +} + + +VOID IWSC_InvalidState(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + DBGPRINT(RT_DEBUG_TRACE, ("IWSC - InvalidState (state=%ld, msg_type = %ld)\n", + pAd->Mlme.IWscMachine.CurrState, pElem->MsgType)); +} + + +VOID IWSC_Init(RTMP_ADAPTER *pAd) +{ + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + + RTMPInitTimer(pAd, + &pIWscInfo->IWscT1Timer, + GET_TIMER_FUNCTION(IWSC_T1TimerAction), + pAd, + FALSE); + + RTMPInitTimer(pAd, + &pIWscInfo->IWscT2Timer, + GET_TIMER_FUNCTION(IWSC_T2TimerAction), + pAd, + FALSE); + + RTMPInitTimer(pAd, + &pIWscInfo->IWscEntryTimer, + GET_TIMER_FUNCTION(IWSC_EntryTimerAction), + pAd, + FALSE); + + RTMPInitTimer(pAd, + &pIWscInfo->IWscDevQueryTimer, + GET_TIMER_FUNCTION(IWSC_DevQueryAction), + pAd, + FALSE); + + pIWscInfo->bIWscT1TimerRunning = FALSE; + pIWscInfo->bIWscT2TimerRunning = FALSE; + pIWscInfo->bIWscEntryTimerRunning = FALSE; + pIWscInfo->bIWscDevQueryReqTimerRunning = FALSE; + pIWscInfo->bIWscDevQueryRspTimerRunning = FALSE; + + pIWscInfo->DialogToken = 0; + pIWscInfo->PeerDialogToken = 0; + pIWscInfo->bSelRegStart = FALSE; + pIWscInfo->bReStart = FALSE; + pIWscInfo->IWscSmpbcAcceptCount = 0; + pIWscInfo->bLimitedUI = FALSE; + pIWscInfo->bSinglePIN = FALSE; + pIWscInfo->bDoNotChangeBSSID = FALSE; + pIWscInfo->bSendEapolStart = FALSE; + pIWscInfo->IpConfMethod = (IWSC_IPV4_ASSIGNMENT | IWSC_DHCP_IPV4 | IWSC_STATIC_IPV4); + pIWscInfo->IpMethod = IWSC_IPV4_ASSIGNMENT; + pIWscInfo->SelfIpv4Addr = IWSC_DEFAULT_REG_IPV4_ADDR; + pIWscInfo->PeerIpv4Addr = 0; + pIWscInfo->RegIpv4Addr = 0; + pIWscInfo->Ipv4SubMask = IWSC_DEFAULT_IPV4_SUBMASK; + pIWscInfo->CurrentIpRange = IWSC_DEFAULT_IPV4_RANGE; + pIWscInfo->RegDepth = 0; + pIWscInfo->IpDevCount = 0; + pIWscInfo->AvaSubMaskListCount = IWSC_MAX_SUB_MASK_LIST_COUNT; + pIWscInfo->AvaSubMaskList[0] = IWSC_IPV4_RANGE1; + pIWscInfo->AvaSubMaskList[1] = IWSC_IPV4_RANGE2; + pIWscInfo->AvaSubMaskList[2] = IWSC_IPV4_RANGE3; + pIWscInfo->bAssignWscIPv4 = TRUE; + pIWscInfo->bDoNotStop = FALSE; + pIWscInfo->SmpbcEnrolleeCount = 0; + RTMPZeroMemory(pIWscInfo->RegMacAddr, MAC_ADDR_LEN); + RTMPZeroMemory(pIWscInfo->IWscDevQueryReqMacAddr, MAC_ADDR_LEN); + + initList(&pAd->StaCfg.WscControl.WscConfiguredPeerList); + NdisAllocateSpinLock(pAd, &pAd->StaCfg.WscControl.WscConfiguredPeerListSemLock); + +#ifdef IWSC_TEST_SUPPORT + pIWscInfo->IWscDefaultSecurity = 3; + pIWscInfo->bIwscSmpbcScanningOnly = FALSE; + pIWscInfo->bEmptySubmaskList = FALSE; +#endif // IWSC_TEST_SUPPORT // +} + + +VOID IWSC_Stop(RTMP_ADAPTER *pAd, BOOLEAN bSendNotification) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + BOOLEAN bCancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_Stop\n")); + + if (pIWscInfo->bIWscT1TimerRunning) + { + pIWscInfo->bIWscT1TimerRunning = FALSE; + RTMPCancelTimer(&pIWscInfo->IWscT1Timer, &bCancelled); + } + + if (pIWscInfo->bIWscT2TimerRunning) + { + pIWscInfo->bIWscT2TimerRunning = FALSE; + RTMPCancelTimer(&pIWscInfo->IWscT2Timer, &bCancelled); + } + + if (pIWscInfo->bIWscEntryTimerRunning) + { + pIWscInfo->bIWscEntryTimerRunning = FALSE; + RTMPCancelTimer(&pIWscInfo->IWscEntryTimer, &bCancelled); + } + + if (pWpsCtrl->WscPBCTimerRunning) + { + pWpsCtrl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWpsCtrl->WscPBCTimer, &bCancelled); + } + pIWscInfo->IWscSmpbcAcceptCount = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS) == FALSE) + { + AsicDisableSync(pAd); + pAd->StaCfg.WpsIEBeacon.ValueLen = 0; + pAd->StaCfg.WpsIEProbeResp.ValueLen = 0; + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ + + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif /* CONFIG_AP_SUPPORT */ + pWpsCtrl); + } + + if (bSendNotification) + { + /* + Send Selected Registrar Finish Notification (multicast action frame) + */ + IWSC_SendActionFrame(pAd, IWSC_SEL_REG_FINISH_NOTITY); + } + pAd->Mlme.IWscMachine.CurrState = IWSC_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_Stop\n")); +} + + +/**************************************************** IWSC Timer Function Begin ****************************************************/ +VOID IWSC_T1TimerAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + PWSC_CTRL pWpsCtrl = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! IWSC_T1TimerAction !!!\n")); + + if (pAd) + { + pWpsCtrl = &pAd->StaCfg.WscControl; + if (pWpsCtrl) + { + pAd->StaCfg.IWscInfo.bDoNotStop = FALSE; + if ((pWpsCtrl->WscConfMode == WSC_REGISTRAR) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + /* + Send Selected Registrar Finish Notification (multicast action frame) + */ + IWSC_Stop(pAd, TRUE); + } + else + IWSC_Stop(pAd, FALSE); + + pWpsCtrl->WscStatus = STATUS_WSC_IDLE; +#ifdef IWSC_TEST_SUPPORT + pAd->StaCfg.IWscInfo.IWscConfMode = WSC_DISABLE; +#endif // IWSC_TEST_SUPPORT // + RTMPSendWirelessEvent(pAd, IW_IWSC_T1_TIMER_TIMEOUT, NULL, pWpsCtrl->EntryIfIdx, 0); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_T1TimerAction - pWpsCtrl is null !!!\n")); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_T1TimerAction - pAd is null !!!\n")); +} + + +VOID IWSC_T2TimerAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + PWSC_CTRL pWpsCtrl = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! IWSC_T2TimerAction - Become Enrollee !!!\n")); + + if (pAd) + { + pWpsCtrl = &pAd->StaCfg.WscControl; + if (pWpsCtrl) + { + RTMPSendWirelessEvent(pAd, IW_IWSC_T2_TIMER_TIMEOUT, NULL, pWpsCtrl->EntryIfIdx, 0); + IWSC_RoleAction(pAd, WSC_ENROLLEE); + pAd->Mlme.IWscMachine.CurrState = IWSC_SCAN; + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_T2TimerAction - pWpsCtrl is null !!!\n")); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_T2TimerAction - pAd is null !!!\n")); +} + + +VOID IWSC_EntryTimerAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + PIWSC_INFO pIWscInfo = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! IWSC_EntryTimerAction !!!\n")); + if (pAd) + { + pIWscInfo = &pAd->StaCfg.IWscInfo; + if (pIWscInfo) + { + pIWscInfo->bIWscEntryTimerRunning = FALSE; + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_REGISTRAR, + pAd->StaCfg.WscControl.WscConfStatus, + TRUE, + DEV_PASS_ID_SMPBC, + pAd->StaCfg.WscControl.WscConfigMethods, + BSS0, + NULL, + 0, + STA_MODE); + RTMPSendWirelessEvent(pAd, IW_IWSC_ENTRY_TIMER_TIMEOUT, NULL, pAd->StaCfg.WscControl.EntryIfIdx, 0); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_EntryTimerAction - pIWscInfo is null !!!\n")); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_EntryTimerAction - pAd is null !!!\n")); +} + + +VOID IWSC_DevQueryAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + PIWSC_INFO pIWscInfo = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! IWSC_DevQueryAction !!!\n")); + if (pAd) + { + pIWscInfo = &pAd->StaCfg.IWscInfo; + if (pIWscInfo) + { + if (pIWscInfo->bIWscDevQueryReqTimerRunning) + { + pIWscInfo->bIWscDevQueryReqTimerRunning = FALSE; + IWSC_SendActionFrame(pAd, IWSC_DEV_QUERY_REQUEST); + RtmpusecDelay(200000); // 200 ms + IWSC_SendActionFrame(pAd, IWSC_DEV_QUERY_REQUEST); + RtmpusecDelay(200000); // 200 ms + IWSC_SendActionFrame(pAd, IWSC_DEV_QUERY_REQUEST); + } + if (pIWscInfo->bIWscDevQueryRspTimerRunning) + { + pIWscInfo->bIWscDevQueryRspTimerRunning = FALSE; + IWSC_SendActionFrame(pAd, IWSC_DEV_QUERY_RESPONSE); + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_DevQueryAction - pIWscInfo is null !!!\n")); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("!!! IWSC_DevQueryAction - pAd is null !!!\n")); +} +/**************************************************** IWSC Timer Function End ****************************************************/ + + +VOID IWSC_MlmeStartAction(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + + /* + Check IWSC State + */ + if (pAd->Mlme.IWscMachine.CurrState != IWSC_IDLE) + { + /* + Stop IWSC + */ + IWSC_Stop(pAd, FALSE); + } + + RTMPSetTimer(&pIWscInfo->IWscT1Timer, WSC_TWO_MINS_TIME_OUT); + pIWscInfo->bIWscT1TimerRunning = TRUE; + WscInitRegistrarPair(pAd, pWpsCtrl, BSS0); + WscGetRegDataPIN(pAd, pWpsCtrl->WscPinCode, pWpsCtrl); + pWpsCtrl->RegData.ReComputePke = 1; + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + IWSC_ResetIpContent(pAd); + } + pIWscInfo->SmpbcEnrolleeCount = 0; + pIWscInfo->IWscSmpbcAcceptCount = 0; + NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN); + + RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock); + WscClearPeerList(&pWpsCtrl->WscPeerList); + RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock); + + RTMP_SEM_LOCK(&pWpsCtrl->WscConfiguredPeerListSemLock); + WscClearPeerList(&pWpsCtrl->WscConfiguredPeerList); + RTMP_SEM_UNLOCK(&pWpsCtrl->WscConfiguredPeerListSemLock); + + if (pWpsCtrl->WscMode == WSC_SMPBC_MODE) + { + if (pWpsCtrl->WscConfMode == WSC_REGISTRAR) + { + RTMPSetTimer(&pIWscInfo->IWscEntryTimer, IWSC_ENTRY_TIME_OUT); + pIWscInfo->bIWscEntryTimerRunning = TRUE; + IWSC_RoleAction(pAd, WSC_REGISTRAR); + IWSC_SendActionFrame(pAd, IWSC_SEL_REG_START_NOTITY); + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + } + else + { + IWSC_RoleAction(pAd, WSC_ENROLLEE); + pAd->Mlme.IWscMachine.CurrState = IWSC_SCAN; + } + } + else + { +#ifdef IWSC_TEST_SUPPORT + if (pIWscInfo->IWscConfMode == WSC_ENROLLEE) + { + IWSC_RoleAction(pAd, WSC_ENROLLEE); + pAd->Mlme.IWscMachine.CurrState = IWSC_SCAN; + } + else +#endif // IWSC_TEST_SUPPORT // + { + IWSC_RoleAction(pAd, WSC_REGISTRAR); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + /* + [A member of IBSS] - Send Selected Registrar Start Notification (multicast action frame) + */ + IWSC_SendActionFrame(pAd, IWSC_SEL_REG_START_NOTITY); + } + else + { + if ((pAd->StaCfg.IWscInfo.bSinglePIN == FALSE) +#ifdef IWSC_TEST_SUPPORT + && (pIWscInfo->IWscConfMode == WSC_DISABLE) +#endif // IWSC_TEST_SUPPORT // + ) + { + /* + [!A member of IBSS] + */ + UCHAR RandomTime; + + RandomTime = RandomByte(pAd) & 0x3C; + if (RandomTime > 60) + RandomTime = 60; + else if (RandomTime < 20) + RandomTime = 20; + DBGPRINT(RT_DEBUG_TRACE, ("RandomTime = %d\n", RandomTime)); + RTMPSetTimer(&pIWscInfo->IWscT2Timer, (RandomTime*100)); + pIWscInfo->bIWscT2TimerRunning = TRUE; + } + } + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + } + } + pWpsCtrl->bWscTrigger = TRUE; +} + + +VOID IWSC_MlmeStopAction(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + + if (pAd->StaCfg.IWscInfo.bSinglePIN && + pAd->StaCfg.IWscInfo.bDoNotStop) + { + DBGPRINT(RT_DEBUG_TRACE, ("SinglePIN registrar now, keep going!!\n")); + pWpsCtrl->WscConfMode = WSC_REGISTRAR; + pWpsCtrl->RegData.ReComputePke = 1; + pWpsCtrl->bWscTrigger = TRUE; + pWpsCtrl->WscState = WSC_STATE_LINK_UP; + pWpsCtrl->WscStatus = STATUS_WSC_LINK_UP; + return; + } + +#ifdef IWSC_TEST_SUPPORT + pAd->StaCfg.IWscInfo.IWscConfMode = WSC_DISABLE; +#endif // IWSC_TEST_SUPPORT // + + /* + Check IWSC State + */ + if (pAd->Mlme.IWscMachine.CurrState != IWSC_IDLE) + { + /* + Stop IWSC + */ + if ((pWpsCtrl->WscConfMode == WSC_REGISTRAR) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + /* + Send Selected Registrar Finish Notification (multicast action frame) + */ + IWSC_Stop(pAd, TRUE); + } + else + IWSC_Stop(pAd, FALSE); + } + +} + + +VOID IWSC_ScanDoneAction(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + UCHAR RandomTime; + + if (pAd->Mlme.IWscMachine.CurrState != IWSC_SCAN) + { + if (pAd->Mlme.IWscMachine.CurrState != IWSC_IDLE) + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_ScanDoneAction:: CurrState = %ld\n", pAd->Mlme.IWscMachine.CurrState)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_ScanDoneAction\n")); + + if (pWpsCtrl->WscMode == WSC_PBC_MODE) + { + if (WscPBCExec(pAd, FALSE, pWpsCtrl) == FALSE) + { + if (pWpsCtrl->WscPBCBssCount > 1) + { + IWSC_Stop(pAd, FALSE); + } + else + { +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.IWscInfo.IWscConfMode != WSC_ENROLLEE) +#endif /* IWSC_TEST_SUPPORT */ + { + IWSC_RoleAction(pAd, WSC_REGISTRAR); + RandomTime = RandomByte(pAd) & 0x3C; + if (RandomTime > 60) + RandomTime = 60; + else if (RandomTime < 20) + RandomTime = 20; + DBGPRINT(RT_DEBUG_TRACE, ("RandomTime = %d\n", RandomTime)); + RTMPSetTimer(&pAd->StaCfg.IWscInfo.IWscT2Timer, (RandomTime*100)); + pAd->StaCfg.IWscInfo.bIWscT2TimerRunning = TRUE; + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + } +#ifdef IWSC_TEST_SUPPORT + else + { + RTMPSetTimer(&pWpsCtrl->WscScanTimer, 1000); + pWpsCtrl->WscScanTimerRunning = TRUE; + } +#endif /* IWSC_TEST_SUPPORT */ + } + } + else + { + BOOLEAN bCancel; + if (pWpsCtrl->WscPBCTimerRunning) + RTMPCancelTimer(&pWpsCtrl->WscPBCTimer, &bCancel); + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + pAd->StaCfg.IWscInfo.bSendEapolStart = TRUE; + } + } + else if (pWpsCtrl->WscMode == WSC_SMPBC_MODE) + { + WscPBCExec(pAd, FALSE, pWpsCtrl); +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.IWscInfo.bIwscSmpbcScanningOnly) + { + RTMPSetTimer(&pWpsCtrl->WscScanTimer, 1000); + pWpsCtrl->WscScanTimerRunning = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_ScanDoneAction\n")); + return; + } +#endif /* IWSC_TEST_SUPPORT */ + if (pWpsCtrl->WscPBCBssCount == 1) + { + pWpsCtrl->WscStatus = WSC_STATE_START; + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + pAd->StaCfg.IWscInfo.bSendEapolStart = TRUE; + } + else if (pWpsCtrl->WscPBCBssCount == 0) + { + RTMPSetTimer(&pWpsCtrl->WscScanTimer, 1000); + pWpsCtrl->WscScanTimerRunning = TRUE; + } + else + IWSC_Stop(pAd, FALSE); + } + else + { + { +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.IWscInfo.IWscConfMode == WSC_ENROLLEE) + { + WscScanExec(pAd); + } + else +#endif // IWSC_TEST_SUPPORT // + { + IWSC_RoleAction(pAd, WSC_REGISTRAR); + RandomTime = RandomByte(pAd) & 0x3C; + if (RandomTime > 60) + RandomTime = 60; + else if (RandomTime < 20) + RandomTime = 20; + DBGPRINT(RT_DEBUG_TRACE, ("RandomTime = %d\n", RandomTime)); + RTMPSetTimer(&pAd->StaCfg.IWscInfo.IWscT2Timer, (RandomTime*100)); + pAd->StaCfg.IWscInfo.bIWscT2TimerRunning = TRUE; + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_ScanDoneAction\n")); + +} + + +VOID IWSC_ReConnectAction(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> %s\n", __FUNCTION__)); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)&pWpsCtrl->WscSsid, 0); + RTMP_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("<----- %s\n", __FUNCTION__)); +} + + +VOID IWSC_BuildSelRegStartNotification(RTMP_ADAPTER *pAd, UCHAR *pOutBuf, USHORT *pIeLen) +{ + UCHAR *Data = NULL, *pData; + INT Len = 0, templen = 0; + WSC_CTRL *pWpsCtrl = &pAd->StaCfg.WscControl; + WSC_REG_DATA *pReg = (PWSC_REG_DATA) &pWpsCtrl->RegData; + USHORT tempVal = 0, ConfigError = htons(0); + WSC_IE_HEADER ieHdr; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_BuildSelRegStartNotification\n")); + + // WSC IE HEader + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; + ieHdr.oui[1] = 0x50; + ieHdr.oui[2] = 0xF2; + ieHdr.oui[3] = 0x10; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* Request Type */ + tempVal = WSC_MSGTYPE_REGISTRAR; + templen = AppendWSCTLV(WSC_ID_REQ_TYPE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* Config method */ + tempVal = htons(0x008c); + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* UUID */ + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, pReg->SelfInfo.Uuid, 0); + pData += templen; + Len += templen; + + /* Primary device type */ + templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0); + pData += templen; + Len += templen; + + /* RF band, shall change based on current channel */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, &pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /* Config error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0); + pData += templen; + Len += templen; + + /* Device Password ID */ + if (pWpsCtrl->WscMode == WSC_PIN_MODE) + tempVal = DEV_PASS_ID_PIN;//cpu2be16(DEV_PASS_ID_PIN); + else + tempVal = cpu2be16(DEV_PASS_ID_PBC); + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* MAC address */ + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pReg->SelfInfo.MacAddr, 0); + pData += templen; + Len += templen; + + ieHdr.length = ieHdr.length + Len; + + RTMPMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + RTMPMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); + *pIeLen = (USHORT)(sizeof(WSC_IE_HEADER) + Len); + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_BuildSelRegStartNotification\n")); +} + + +VOID IWSC_BuildSelRegFinishNotification( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PUSHORT pIeLen) +{ +// UCHAR Data[512]; + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWpsCtrl->RegData; + WSC_IE_HEADER ieHdr; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_BuildSelRegFinishNotification\n")); + + // WSC IE HEader + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; + ieHdr.oui[1] = 0x50; + ieHdr.oui[2] = 0xF2; + ieHdr.oui[3] = 0x10; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* Simple Config State */ + templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&pWpsCtrl->WscConfStatus, 0); + pData += templen; + Len += templen; + + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, &pAd->CurrentAddress[0], 0); + pData += templen; + Len += templen; + + ieHdr.length = ieHdr.length + Len; + + RTMPMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + RTMPMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); + *pIeLen = sizeof(WSC_IE_HEADER) + Len; + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_BuildSelRegFinishNotification\n")); +} + + +/* + IWSC Public Action Frame Format + ----------------------------------------------------------------------------------------------- + Field Size Value + ----------------------------------------------------------------------------------------------- + Category 1 Octet 0x04 + ----------------------------------------------------------------------------------------------- + Action field 1 Octet 0xDD + ----------------------------------------------------------------------------------------------- + OUI 3 Octets 0x50 0x6F 0x9A + ----------------------------------------------------------------------------------------------- + OUI type 1 Octet 0x10 + ----------------------------------------------------------------------------------------------- + OUI Subtype 1 Octet 0 - Selected Registrar Start Notification + 1 - Selected Registrar Finish Notification + 2 - Device Query Request + 3 - Device Query Response + 4 ~ 255 - Reserved + ----------------------------------------------------------------------------------------------- + Dialog Token 1 Octet nonzero value (to identify the request/response transaction + ----------------------------------------------------------------------------------------------- + Elements variable IWSC IE + (It has the Element ID(0xDD), Length, IWSC OUI(0x00 0x50 0xF2 0x10) + ----------------------------------------------------------------------------------------------- +*/ +VOID IWSC_SendActionFrame(RTMP_ADAPTER *pAd, UCHAR FrameType) +{ + HEADER_802_11 ActHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + UCHAR Category = CATEGORY_PUBLIC; + UCHAR Action = 9; + PUCHAR pWscBuf = NULL; + USHORT WscIeLen = 0; + ULONG WscTmpLen = 0; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + NDIS_STATUS NStatus; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("IWSC_SendStartNotification:: allocate memory failed \n")); + return; + } + + if (FrameType == IWSC_DEV_QUERY_RESPONSE) + ActHeaderInit(pAd, &ActHdr, pIWscInfo->IWscDevQueryReqMacAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &ActHdr, BROADCAST_ADDR, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + if (pIWscInfo->DialogToken == 0) + pIWscInfo->DialogToken = 1; + else + pIWscInfo->DialogToken++; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ActHdr, + 1, &Category, + 1, &Action, + 4, IWSC_ACTION_OUI, + 1, &FrameType, + 1, &pIWscInfo->DialogToken, + END_OF_ARGS); + + os_alloc_mem(NULL, &pWscBuf, 512); + if( pWscBuf != NULL) + { + NdisZeroMemory(pWscBuf, 512); + if (FrameType == IWSC_SEL_REG_START_NOTITY) + IWSC_BuildSelRegStartNotification(pAd, pWscBuf, &WscIeLen); + else if (FrameType == IWSC_SEL_REG_FINISH_NOTITY) + IWSC_BuildSelRegFinishNotification(pAd, pWscBuf, &WscIeLen); + else if (FrameType == IWSC_DEV_QUERY_REQUEST) + IWSC_BuildDevQueryFrame(pAd, pWscBuf, &WscIeLen); + else if (FrameType == IWSC_DEV_QUERY_RESPONSE) + IWSC_BuildDevQueryFrame(pAd, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +VOID IWSC_PeerAction(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + UCHAR Token = pElem->Msg[LENGTH_802_11+7]; + UCHAR FrameType = pElem->Msg[LENGTH_802_11+6]; + PUCHAR pData = pElem->Msg+(LENGTH_802_11+8); + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + INT Len = 0; + INT TotalLen = (INT)pElem->MsgLen - (LENGTH_802_11+8); + USHORT RegDPID; + USHORT RegCfgMethods; + UINT8 ReqType = 0; + UCHAR PeerMAC[MAC_ADDR_LEN]; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_PeerAction\n")); + + /* + Marvell STA always send same non-zero Token value, thus we don't need to check Token value here. + */ + { + /* + IWSC Element may not be first one element in Action frame. + */ + pIWscInfo->PeerDialogToken = Token; + for (;;) + { + Len = (INT)*(pData + 1); + /*hex_dump("sn - pData", pData, Len+2);*/ + pData = pData + 2; + if (NdisEqualMemory(pData, IWSC_OUI, 4)) + { + Len -= 4; // OUI Length + pData = pData + 4; + break; + } + + TotalLen -= (Len + 2); // 2: ID + Len + if (TotalLen <= 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("No IWSC IE!\n<----- IWSC_PeerAction\n")); + return; + } + pData = pData + Len; + } + + hex_dump("pData", pData, Len); + while (Len > 0) + { + WSC_IE WscIE; + PWSC_IE pWscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + /* Check for WSC IEs */ + pWscIE = &WscIE; + + if (be2cpu16(pWscIE->Type) == WSC_ID_REQ_TYPE) + { + ReqType = *(pData + 4); + } + + if (be2cpu16(pWscIE->Type) == WSC_ID_SEL_REG_CFG_METHODS) + { + NdisMoveMemory(&RegCfgMethods, pData + 4, sizeof(USHORT)); + RegCfgMethods = be2cpu16(RegCfgMethods); + } + + if (be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID) + { + NdisMoveMemory(&RegDPID, pData + 4, sizeof(USHORT)); + RegDPID = be2cpu16(RegDPID); + } + + if (be2cpu16(pWscIE->Type) == WSC_ID_MAC_ADDR) + { + RTMPMoveMemory(PeerMAC, pData + 4, MAC_ADDR_LEN); + } + + /* + Set the offset + Since Type and Length are both short type, we need to offset 4, not 2 + */ + pData += (be2cpu16(pWscIE->Length) + 4); + Len -= (be2cpu16(pWscIE->Length) + 4); + } + + if (FrameType == IWSC_SEL_REG_START_NOTITY) + { + DBGPRINT(RT_DEBUG_TRACE, ("Receive SelRegStartNotification from %02X:%02X:%02X:%02X:%02X:%02X!\n", + PeerMAC[0], PeerMAC[1], PeerMAC[2], PeerMAC[3], PeerMAC[4], PeerMAC[5])); + pIWscInfo->bSelRegStart = TRUE; + RTMPMoveMemory(pIWscInfo->RegMacAddr, PeerMAC, MAC_ADDR_LEN); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_IWSC_NOTIFIER, + pAd->StaCfg.WscControl.WscConfStatus, + TRUE, + RegDPID, + RegCfgMethods, + 0, + NULL, + 0, + STA_MODE); + } + else if (FrameType == IWSC_SEL_REG_FINISH_NOTITY) + { + DBGPRINT(RT_DEBUG_TRACE, ("Receive SelRegFinishNotification from %02X:%02X:%02X:%02X:%02X:%02X!\n", + PeerMAC[0], PeerMAC[1], PeerMAC[2], PeerMAC[3], PeerMAC[4], PeerMAC[5])); + if (NdisEqualMemory(pIWscInfo->RegMacAddr, PeerMAC, MAC_ADDR_LEN)) + { + pIWscInfo->bSelRegStart = FALSE; + NdisZeroMemory(pIWscInfo->RegMacAddr, MAC_ADDR_LEN); + } + if (pAd->StaCfg.WscControl.bWscTrigger == FALSE) + pAd->StaCfg.WpsIEProbeResp.ValueLen = 0; + } + else if (FrameType == IWSC_DEV_QUERY_REQUEST) + { + UCHAR RandomVal = RandomByte(pAd); + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("Receive Device Query Request from %02X:%02X:%02X:%02X:%02X:%02X!\n", + PeerMAC[0], PeerMAC[1], PeerMAC[2], PeerMAC[3], PeerMAC[4], PeerMAC[5])); + if (RandomVal < 20) + RandomVal = 20; + if (RandomVal > 50) + RandomVal = 50; + NdisMoveMemory(pIWscInfo->IWscDevQueryReqMacAddr, PeerMAC, MAC_ADDR_LEN); + RTMPSetTimer(&pIWscInfo->IWscDevQueryTimer, RandomVal*10); + pIWscInfo->bIWscDevQueryRspTimerRunning = TRUE; + +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.IWscInfo.bBlockConnection) + return; +#endif /* IWSC_TEST_SUPPORT */ + + pEntry = MacTableLookup(pAd, PeerMAC); + + if (pEntry == NULL) + { + // Another adhoc joining, add to our MAC table. + pEntry = MacTableInsertEntry(pAd, PeerMAC, &pAd->StaCfg.wdev, BSS0, OPMODE_STA, FALSE); + } + + if (pEntry) + { +#ifdef ADHOC_WPA2PSK_SUPPORT + //Adhoc support WPA2PSK by Eddy + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pEntry->WPA_Authenticator.WpaState < AS_INITPSK)) + { + INT len, i; + BOOLEAN bHigherMAC = FALSE; + + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisZeroMemory(&pEntry->WPA_Supplicant.ReplayCounter, LEN_KEY_DESC_REPLAY); + NdisZeroMemory(&pEntry->WPA_Authenticator.ReplayCounter, LEN_KEY_DESC_REPLAY); + pEntry->WPA_Authenticator.WpaState = AS_INITPSK; + pEntry->WPA_Supplicant.WpaState = AS_INITPSK; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + + // collapse into the ADHOC network which has bigger BSSID value. + for (i = 0; i < 6; i++) + { + if (PeerMAC[i] > pAd->CurrentAddress[i]) + { + bHigherMAC = TRUE; + break; + } + else if (PeerMAC[i] < pAd->CurrentAddress[i]) + break; + } + + hex_dump("IWSC_PeerAction:: PeerMAC", PeerMAC, MAC_ADDR_LEN); + hex_dump("IWSC_PeerAction:: pAd->CurrentAddress", pAd->CurrentAddress, MAC_ADDR_LEN); + pEntry->bPeerHigherMAC = bHigherMAC; + if (pEntry->bPeerHigherMAC == FALSE) + { + /* + My MAC address is higher than peer's MAC address. + */ + DBGPRINT(RT_DEBUG_TRACE, ("%s - EnqueueStartForPSKTimer.\n", __FUNCTION__)); + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + pEntry->bPeerHigherMAC = FALSE; + } + } + else +#endif // ADHOC_WPA2PSK_SUPPORT // + { + if (pAd->StaCfg.wdev.AuthMode < Ndis802_11AuthModeWPA) + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + } + } + } + else if (FrameType == IWSC_DEV_QUERY_RESPONSE) + { + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("Receive Device Query Response from %02X:%02X:%02X:%02X:%02X:%02X!\n", + PeerMAC[0], PeerMAC[1], PeerMAC[2], PeerMAC[3], PeerMAC[4], PeerMAC[5])); + + +#ifdef IWSC_TEST_SUPPORT + if (pAd->StaCfg.IWscInfo.bBlockConnection) + return; +#endif /* IWSC_TEST_SUPPORT */ + + pEntry = MacTableLookup(pAd, PeerMAC); + + if (pEntry == NULL) + { + // Another adhoc joining, add to our MAC table. + pEntry = MacTableInsertEntry(pAd, PeerMAC, &pAd->StaCfg.wdev, BSS0, OPMODE_STA, FALSE); + } + + if (pEntry) + { +#ifdef ADHOC_WPA2PSK_SUPPORT + //Adhoc support WPA2PSK by Eddy + if ((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pEntry->WPA_Authenticator.WpaState < AS_INITPSK)) + { + INT len, i; + BOOLEAN bHigherMAC = FALSE; + + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisZeroMemory(&pEntry->WPA_Supplicant.ReplayCounter, LEN_KEY_DESC_REPLAY); + NdisZeroMemory(&pEntry->WPA_Authenticator.ReplayCounter, LEN_KEY_DESC_REPLAY); + pEntry->WPA_Authenticator.WpaState = AS_INITPSK; + pEntry->WPA_Supplicant.WpaState = AS_INITPSK; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + + // collapse into the ADHOC network which has bigger BSSID value. + for (i = 0; i < 6; i++) + { + if (PeerMAC[i] > pAd->CurrentAddress[i]) + { + bHigherMAC = TRUE; + break; + } + else if (PeerMAC[i] < pAd->CurrentAddress[i]) + break; + } + + hex_dump("IWSC_PeerAction:: PeerMAC", PeerMAC, MAC_ADDR_LEN); + hex_dump("IWSC_PeerAction:: pAd->CurrentAddress", pAd->CurrentAddress, MAC_ADDR_LEN); + pEntry->bPeerHigherMAC = bHigherMAC; + if (pEntry->bPeerHigherMAC == FALSE) + { + /* + My MAC address is higher than peer's MAC address. + */ + DBGPRINT(RT_DEBUG_TRACE, ("%s - EnqueueStartForPSKTimer.\n", __FUNCTION__)); + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + pEntry->bPeerHigherMAC = FALSE; + } + } + else +#endif // ADHOC_WPA2PSK_SUPPORT // + { + if (pAd->StaCfg.wdev.AuthMode < Ndis802_11AuthModeWPA) + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unknow Frame Type!\n")); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_PeerAction\n")); +} + + +VOID IWSC_PeerProbeRequest(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWscCtrl = &pAd->StaCfg.WscControl; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + USHORT PeerConfigMethod = 0; + USHORT ConfigMethod = 0; + BOOLEAN Cancelled; + USHORT DPID = 0; + + if (pWscCtrl->WscConfMode != WSC_REGISTRAR) + { + DBGPRINT(RT_DEBUG_ERROR, ("IWSC_PeerProbeRequest:: Not Registrar now(WscConfMode = %d)\n" + , pWscCtrl->WscConfMode)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_PeerProbeRequest\n")); + + NdisMoveMemory(&PeerConfigMethod, pElem->Msg, pElem->MsgLen); + + if (pIWscInfo->bIWscT2TimerRunning) + { + RTMPCancelTimer(&pIWscInfo->IWscT2Timer, &Cancelled); + pIWscInfo->bIWscT2TimerRunning = FALSE; + } + + if (pWscCtrl->WscMode == WSC_PIN_MODE) + { + if (PeerConfigMethod & WPS_CONFIG_METHODS_KEYPAD) + { + if (pIWscInfo->bSinglePIN == FALSE) + { + pWscCtrl->WscEnrolleePinCode = WscRandomGeneratePinCode(pAd, BSS0); + pWscCtrl->WscEnrolleePinCodeLen = 8; + pWscCtrl->WscPinCodeLen = 8; + pWscCtrl->WscStatus = STATUS_WSC_IBSS_NEW_RANDOM_PIN; + } + else + pWscCtrl->WscStatus = STATUS_WSC_IBSS_FIXED_PIN; + + WscGetRegDataPIN(pAd, pWscCtrl->WscEnrolleePinCode, pWscCtrl); + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerProbeRequest:: WscPinCode = %08d\n", pWscCtrl->WscPinCode)); + } + else + { + if (pAd->StaCfg.IWscInfo.bLimitedUI) + { + DBGPRINT(RT_DEBUG_ERROR, + ("IWSC_PeerProbeRequest:: Both devices are limited UI. Shall we change to use PBC mode?\n")); + IWSC_Stop(pAd, FALSE); + return; + } + else + { + pWscCtrl->WscPinCode = 0; + pWscCtrl->WscStatus = STATUS_WSC_WAIT_PIN_CODE; + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerProbeRequest:: Please input Peer's PIN\n")); + } + } + if (PeerConfigMethod & WPS_CONFIG_METHODS_KEYPAD) + { + DPID = DEV_PASS_ID_REG; + ConfigMethod = WPS_CONFIG_METHODS_DISPLAY; + } + else + { + DPID = DEV_PASS_ID_PIN; + ConfigMethod = (WPS_CONFIG_METHODS_DISPLAY | WPS_CONFIG_METHODS_KEYPAD); + } + + AsicDisableSync(pAd); + WscBuildBeaconIE(pAd, + pWscCtrl->WscConfStatus, + TRUE, + DPID, + ConfigMethod, + BSS0, + NULL, + 0, + STA_MODE); + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_REGISTRAR, + pWscCtrl->WscConfStatus, + TRUE, + DPID, + ConfigMethod, + BSS0, + NULL, + 0, + STA_MODE); + } + pAd->Mlme.IWscMachine.CurrState = IWSC_WAIT_JOIN; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_PeerProbeRequest\n")); + return; +} + + +VOID IWSC_PeerProbeResponse(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWscCtrl = &pAd->StaCfg.WscControl; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + USHORT PeerConfigMethod = 0; + BOOLEAN Cancelled; + + if (pWscCtrl->WscConfMode != WSC_ENROLLEE) + { + DBGPRINT(RT_DEBUG_ERROR, ("IWSC_PeerProbeResponse:: Not Enrollee now(WscConfMode = %d)\n" + , pWscCtrl->WscConfMode)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_PeerProbeResponse\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + // Change back to original channel in case of doing scan + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // Resume MSDU which is turned off durning scan + RTMPResumeMsduTransmission(pAd); + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("Cancel Scan Timer\n")); + } + + NdisMoveMemory(&PeerConfigMethod, pElem->Msg, pElem->MsgLen); + + if (pAd->StaCfg.IWscInfo.bLimitedUI) + { + if (PeerConfigMethod & WPS_CONFIG_METHODS_KEYPAD) + { + if (pIWscInfo->bSinglePIN == FALSE) + { + pWscCtrl->WscEnrolleePinCode = WscRandomGeneratePinCode(pAd, BSS0); + pWscCtrl->WscEnrolleePinCodeLen = 8; + pWscCtrl->WscPinCodeLen = 8; + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerProbeResponse:: WscPinCode = %d\n", pWscCtrl->WscPinCode)); + pWscCtrl->WscStatus = STATUS_WSC_IBSS_NEW_RANDOM_PIN; + } + else + pWscCtrl->WscStatus = STATUS_WSC_IBSS_FIXED_PIN; + + WscGetRegDataPIN(pAd, pWscCtrl->WscEnrolleePinCode, pWscCtrl); + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + pAd->StaCfg.IWscInfo.bSendEapolStart = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("IWSC_PeerProbeRequest:: Both devices are limited UI. Shall we change to use PBC mode?\n")); + IWSC_Stop(pAd, FALSE); + return; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerProbeResponse:: Please input Peer's PIN\n")); + pAd->Mlme.IWscMachine.CurrState = IWSC_WAIT_PIN; + pWscCtrl->WscStatus = STATUS_WSC_WAIT_PIN_CODE; + } + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)&pWscCtrl->WscSsid, 0); + RTMP_MLME_HANDLER(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_PeerProbeResponse\n")); + return; +} + + +VOID IWSC_PeerPIN(RTMP_ADAPTER *pAd, PMLME_QUEUE_ELEM pElem) +{ + PWSC_CTRL pWscCtrl = &pAd->StaCfg.WscControl; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_PeerPIN\n")); + if (ADHOC_ON(pAd)) + { + NdisZeroMemory(pWscCtrl->EntryAddr, MAC_ADDR_LEN); + NdisMoveMemory(pWscCtrl->EntryAddr, pWscCtrl->WscPeerMAC, MAC_ADDR_LEN); + pWscCtrl->WscState = WSC_STATE_LINK_UP; + pWscCtrl->WscStatus = STATUS_WSC_LINK_UP; + WscSendEapolStart(pAd, pWscCtrl->WscPeerMAC, STA_MODE); + } + else + { + hex_dump("WscPeerMAC", pWscCtrl->WscPeerMAC, MAC_ADDR_LEN); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)&pWscCtrl->WscSsid, 0); + RTMP_MLME_HANDLER(pAd); + pAd->StaCfg.IWscInfo.bSendEapolStart = TRUE; + } + pAd->Mlme.IWscMachine.CurrState = IWSC_START; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_PeerPIN\n")); +} + + +BOOLEAN IWSC_PeerEapolStart(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + BOOLEAN Cancelled; + + if (pWpsCtrl->WscConfMode != WSC_REGISTRAR) + { + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerEapolStart:: Not Registrar now(WscConfMode = %d)\n", pWpsCtrl->WscConfMode)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_PeerEapolStart\n")); + + // Receive enrollee identity from EAP + if (pWpsCtrl->WscMode == WSC_PBC_MODE) + { + /* + Some WPS PBC Station select AP from UI directly; doesn't do PBC scan. + Need to check DPID from STA again here. + */ + WscPBC_DPID_FromSTA(pAd, pEntry->Addr); + WscPBCSessionOverlapCheck(pAd); + if ((pAd->CommonCfg.WscStaPbcProbeInfo.WscPBCStaProbeCount == 1) && + !NdisEqualMemory(pAd->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN) && + (NdisEqualMemory(pAd->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &pEntry->Addr[0], 6) == FALSE)) + { + pAd->CommonCfg.WscPBCOverlap = TRUE; + } + //if (pAd->CommonCfg.WscPBCOverlap) + { + hex_dump("EntryAddr", pWpsCtrl->EntryAddr, 6); + hex_dump("StaMacAddr0", pAd->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], 6); + hex_dump("StaMacAddr1", pAd->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[1], 6); + hex_dump("StaMacAddr2", pAd->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[2], 6); + hex_dump("StaMacAddr3", pAd->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[3], 6); + } + if (pAd->CommonCfg.WscPBCOverlap == TRUE) + { + // PBC session overlap + pWpsCtrl->WscStatus = STATUS_WSC_PBC_SESSION_OVERLAP; + RTMPSendWirelessEvent(pAd, IW_WSC_PBC_SESSION_OVERLAP, NULL, pWpsCtrl->EntryIfIdx, 0); + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerEapolStart: PBC Session Overlap!\n")); + IWSC_MlmeStopAction(pAd, NULL); + return FALSE; + } + } + else if (pWpsCtrl->WscMode == WSC_SMPBC_MODE) + { + if (pEntry->bIWscSmpbcAccept == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerEapolStart:: pEntry->bIWscSmpbcAccept == FALSE\n")); + return FALSE; + } + + if (pWpsCtrl->EapMsgRunning == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("IWSC_PeerEapolStart:: Busy now\n")); + return FALSE; + } + + if (pIWscInfo->bIWscT1TimerRunning) + { + RTMPCancelTimer(&pIWscInfo->IWscT1Timer, &Cancelled); + pIWscInfo->bIWscT1TimerRunning = FALSE; + } + } + + if (pIWscInfo->bIWscT2TimerRunning) + { + RTMPCancelTimer(&pIWscInfo->IWscT2Timer, &Cancelled); + pIWscInfo->bIWscT2TimerRunning = FALSE; + } + + if (MAC_ADDR_EQUAL(pWpsCtrl->EntryAddr, ZERO_MAC_ADDR)) + { + NdisMoveMemory(pWpsCtrl->EntryAddr, pEntry->Addr, MAC_ADDR_LEN); + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_PeerEapolStart\n")); + return TRUE; +} + + +VOID IWSC_RoleAction(RTMP_ADAPTER *pAd, INT WscConfMode) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + USHORT WscMode; + USHORT ConfigMethod = pWpsCtrl->WscConfigMethods; + + if (WscConfMode == WSC_REGISTRAR) + { + pWpsCtrl->WscConfMode = WSC_REGISTRAR; + AsicDisableSync(pAd); + + if (pWpsCtrl->WscMode == WSC_PBC_MODE) + WscMode = DEV_PASS_ID_PBC; + else if (pWpsCtrl->WscMode == WSC_SMPBC_MODE) + WscMode = DEV_PASS_ID_SMPBC; + else + { + WscMode = DEV_PASS_ID_REG; + } + + if (!pAd->StaCfg.IWscInfo.bLimitedUI) + ConfigMethod |= WPS_CONFIG_METHODS_KEYPAD; + else + ConfigMethod &= (~WPS_CONFIG_METHODS_KEYPAD); + WscBuildBeaconIE(pAd, pWpsCtrl->WscConfStatus, TRUE, WscMode, ConfigMethod, BSS0, NULL, 0, STA_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_REGISTRAR, pWpsCtrl->WscConfStatus, TRUE, WscMode, ConfigMethod, BSS0, NULL, 0, STA_MODE); + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ + pWpsCtrl->WscState = WSC_STATE_LINK_UP; + pWpsCtrl->WscStatus = STATUS_WSC_LINK_UP; + RTMPSendWirelessEvent(pAd, IW_IWSC_BECOME_REGISTRAR, NULL, pWpsCtrl->EntryIfIdx, 0); + } + else + { + pWpsCtrl->WscRejectSamePinFromEnrollee = FALSE; + pWpsCtrl->WscConfMode = WSC_ENROLLEE; + + /* + Set the AutoReconnectSsid to prevent it reconnect to old SSID + */ + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + AsicDisableSync(pAd); + pAd->StaCfg.WpsIEBeacon.ValueLen = 0; + pAd->StaCfg.WpsIEProbeResp.ValueLen = 0; + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ + + pWpsCtrl->WscState = WSC_STATE_START; + pWpsCtrl->WscStatus = STATUS_WSC_SCAN_AP; + NdisZeroMemory(&pWpsCtrl->WscSsid, sizeof(NDIS_802_11_SSID)); + RTMPSendWirelessEvent(pAd, IW_IWSC_BECOME_ENROLLEE, NULL, pWpsCtrl->EntryIfIdx, 0); + // For PBC, the PIN is all '0' + WscGetRegDataPIN(pAd, pWpsCtrl->WscPinCode, pWpsCtrl); + WscScanExec(pAd, pWpsCtrl); + } +} + + +VOID IWSC_AddSmpbcEnrollee(RTMP_ADAPTER *pAd, UCHAR *pPeerAddr) +{ + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + PMAC_TABLE_ENTRY pEntry = NULL; + PWSC_PEER_ENTRY pWscPeerEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_AddSmpbcEnrollee (WscConfMode = %d, WscStatus = %d)\n", + pWpsCtrl->WscConfMode, pWpsCtrl->WscStatus)); + + pWscPeerEntry = WscFindPeerEntry(&pWpsCtrl->WscPeerList, pPeerAddr); + if (pWscPeerEntry && + pWscPeerEntry->bIWscSmpbcAccept && + !pIWscInfo->bIWscEntryTimerRunning) + { + pEntry = MacTableLookup(pAd, pPeerAddr); + if (pEntry == NULL) + pEntry = MacTableInsertEntry(pAd, pPeerAddr, &pAd->StaCfg.wdev, BSS0, OPMODE_STA, FALSE); + if (pEntry) + { + pEntry->bIWscSmpbcAccept = TRUE; + if ((pWpsCtrl->WscConfMode == WSC_DISABLE) && + (pWpsCtrl->WscStatus == STATUS_WSC_CONFIGURED || pWpsCtrl->WscStatus == STATUS_WSC_IBSS_WAIT_NEXT_SMPBC_ENROLLEE)) + { + pWpsCtrl->WscConfMode = WSC_REGISTRAR; + pWpsCtrl->WscMode = WSC_SMPBC_MODE; + pWpsCtrl->WscState = WSC_STATE_LINK_UP; + pWpsCtrl->WscStatus = STATUS_WSC_LINK_UP; + pWpsCtrl->bWscTrigger = TRUE; + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_REGISTRAR, + pAd->StaCfg.WscControl.WscConfStatus, + TRUE, + DEV_PASS_ID_SMPBC, + pAd->StaCfg.WscControl.WscConfigMethods, + BSS0, + NULL, + 0, + STA_MODE); + } + DBGPRINT(RT_DEBUG_TRACE, ("SMPBC Enrollee - %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + } + } + else if (pIWscInfo->bIWscEntryTimerRunning) + { + pEntry = MacTableLookup(pAd, pPeerAddr); + if (pEntry == NULL) + { + pEntry = MacTableInsertEntry(pAd, pPeerAddr, &pAd->StaCfg.wdev, BSS0, OPMODE_STA, FALSE); + pWscPeerEntry = WscFindPeerEntry(&pWpsCtrl->WscPeerList, pPeerAddr); + if (pWscPeerEntry == NULL) + pIWscInfo->IWscSmpbcAcceptCount++; + } + + if (pEntry && !pEntry->bIWscSmpbcAccept) + { + pEntry->bIWscSmpbcAccept = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Accept this peer enrollee - %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + + WscInsertPeerEntryByMAC(&pWpsCtrl->WscPeerList, pPeerAddr); + pWscPeerEntry = WscFindPeerEntry(&pWpsCtrl->WscPeerList, pPeerAddr); + + if (pWscPeerEntry) + pWscPeerEntry->bIWscSmpbcAccept = TRUE; + + if ((pWpsCtrl->WscConfMode == WSC_DISABLE) && + (pWpsCtrl->WscStatus == STATUS_WSC_CONFIGURED || pWpsCtrl->WscStatus == STATUS_WSC_IBSS_WAIT_NEXT_SMPBC_ENROLLEE)) + { + pWpsCtrl->WscConfMode = WSC_REGISTRAR; + pWpsCtrl->WscMode = WSC_SMPBC_MODE; + pWpsCtrl->WscState = WSC_STATE_LINK_UP; + pWpsCtrl->WscStatus = STATUS_WSC_LINK_UP; + pWpsCtrl->bWscTrigger = TRUE; + } + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_REGISTRAR, + pAd->StaCfg.WscControl.WscConfStatus, + TRUE, + DEV_PASS_ID_SMPBC, + pAd->StaCfg.WscControl.WscConfigMethods, + BSS0, + NULL, + 0, + STA_MODE); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_AddSmpbcEnrollee\n")); + return; +} + + +ULONG IWSC_SearchWpsApByPinMethod(RTMP_ADAPTER *pAd) +{ + UCHAR i; + BSS_ENTRY *pBss; + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + if ((pBss->WpsAP) && + (pBss->BssType == BSS_ADHOC) && + ((pBss->WscDPIDFromWpsAP == DEV_PASS_ID_PIN) || (pBss->WscDPIDFromWpsAP == DEV_PASS_ID_REG))) + { + return (ULONG)i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +VOID IWSC_GetConfigMethod(RTMP_ADAPTER *pAd, UCHAR *pVIE, INT VIELen, USHORT *pConfigMethod) +{ + PUCHAR pData = pVIE; + INT Len = VIELen; + PBEACON_EID_STRUCT pEid; + USHORT Type = 0, TLV_Len = 0; + + while (Len > 0) + { + pEid = (PBEACON_EID_STRUCT) pData; + + // No match, skip the Eid and move forward, IE_WFA_WSC = 0xdd + if (pEid->Eid != IE_WFA_WSC) + { + // Set the offset and look for next IE + pData += (pEid->Len + 2); + Len -= (pEid->Len + 2); + continue; + } + else + { + // Found IE with 0xdd + // check for WSC OUI -- 00 50 f2 04 + if (NdisEqualMemory(pEid->Octet, IWSC_OUI, 4) == FALSE) + { + // Set the offset and look for next IE + pData += (pEid->Len + 2); + Len -= (pEid->Len + 2); + continue; + } + } + + // 3. Found AP with WSC IE in beacons, skip 6 bytes = 1 + 1 + 4 + pData += 6; + Len -= 6; + + // 4. Start to look the PBC type within WSC VarIE + while (Len > 0) + { + // Check for WSC IEs + NdisMoveMemory(&Type, pData, 2); + NdisMoveMemory(&TLV_Len, pData+2, 2); + + // Check for config method + if (be2cpu16(Type) == WSC_ID_SEL_REG_CFG_METHODS) + { + NdisMoveMemory(pConfigMethod, pData+4, 2); + *pConfigMethod = be2cpu16(*pConfigMethod); + } + + // Set the offset and look for PBC information + // Since Type and Length are both short type, we need to offset 4, not 2 + pData += (be2cpu16(TLV_Len) + 4); + Len -= (be2cpu16(TLV_Len) + 4); + } + } +} + + +VOID IWSC_BuildDevQueryFrame(RTMP_ADAPTER *pAd, UCHAR *pOutBuf, USHORT *pIeLen) +{ + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWpsCtrl->RegData; + USHORT tempVal = 0; + WSC_IE_HEADER ieHdr; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("-----> IWSC_BuildDevQueryFrame\n")); + + // WSC IE HEader + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; + ieHdr.oui[1] = 0x50; + ieHdr.oui[2] = 0xF2; + ieHdr.oui[3] = 0x10; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* MAC address */ + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pReg->SelfInfo.MacAddr, 0); + pData += templen; + Len += templen; + + /* Manufacture */ + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* Device Name */ + templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + ieHdr.length = ieHdr.length + Len; + + RTMPMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + RTMPMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); + *pIeLen = (USHORT)(sizeof(WSC_IE_HEADER) + Len); + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- IWSC_BuildDevQueryFrame\n")); +} + + +VOID IWSC_ResetIpContent(RTMP_ADAPTER *pAd) +{ + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- %s\n", __FUNCTION__)); + pIWscInfo->IpDevCount = 0; + pIWscInfo->RegDepth = 0; + pIWscInfo->AvaSubMaskListCount = IWSC_MAX_SUB_MASK_LIST_COUNT; + pIWscInfo->bAssignWscIPv4 = TRUE; + pIWscInfo->AvaSubMaskList[0] = IWSC_IPV4_RANGE1; + pIWscInfo->AvaSubMaskList[1] = IWSC_IPV4_RANGE2; + pIWscInfo->AvaSubMaskList[2] = IWSC_IPV4_RANGE3; + DBGPRINT(RT_DEBUG_TRACE, ("<----- %s\n", __FUNCTION__)); +} + + +BOOLEAN IWSC_IpContentForCredential(RTMP_ADAPTER *pAd) +{ + PIWSC_INFO pIWscInfo = &pAd->StaCfg.IWscInfo; + + if (pIWscInfo->IpDevCount >= IWSC_MAX_IP_DEV_COUNT) + { + DBGPRINT(RT_DEBUG_TRACE, ("pIWscInfo->IpDevCount = %d\n", + pIWscInfo->IpDevCount)); + return FALSE; + } + + if (pIWscInfo->bAssignWscIPv4 == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("pIWscInfo->bAssignWscIPv4 = %d\n", + pIWscInfo->bAssignWscIPv4)); + return FALSE; + } + if (pIWscInfo->RegDepth == 0) + { + pIWscInfo->IpDevCount++; + pIWscInfo->SelfIpv4Addr = IWSC_DEFAULT_REG_IPV4_ADDR; + pIWscInfo->PeerIpv4Addr = pIWscInfo->SelfIpv4Addr + pIWscInfo->IpDevCount; + DBGPRINT(RT_DEBUG_TRACE, ("1) SelfIpv4Addr = 0x%08x, PeerIpv4Addr = 0x%08x\n", + pIWscInfo->SelfIpv4Addr, + pIWscInfo->PeerIpv4Addr)); + return TRUE; + } + else + { + UINT32 shift_offset = 0; + UINT32 dev_count = (UINT32)(++pIWscInfo->IpDevCount); + if (pIWscInfo->SelfIpv4Addr == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("IMPOSSIBLE!! pIWscInfo->SelfIpv4Addr = %d\n", pIWscInfo->SelfIpv4Addr)); + return FALSE; + } + + if (pIWscInfo->CurrentIpRange == IWSC_IPV4_RANGE0) + { + shift_offset = 0; + } + else if (pIWscInfo->CurrentIpRange == IWSC_IPV4_RANGE1) + { + shift_offset = 6; + } + else if (pIWscInfo->CurrentIpRange == IWSC_IPV4_RANGE2) + { + shift_offset = 12; + } + else if (pIWscInfo->CurrentIpRange == IWSC_IPV4_RANGE3) + { + shift_offset = 18; + } + + pIWscInfo->PeerIpv4Addr = (pIWscInfo->SelfIpv4Addr & pIWscInfo->CurrentIpRange) + (dev_count << shift_offset); + DBGPRINT(RT_DEBUG_TRACE, ("2) SelfIpv4Addr = 0x%08x, PeerIpv4Addr = 0x%08x\n", + pIWscInfo->SelfIpv4Addr, + pIWscInfo->PeerIpv4Addr)); + return TRUE; + } +} +#endif /* IWSC_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sync.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sync.c new file mode 100644 index 000000000..ef7528944 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/sync.c @@ -0,0 +1,3281 @@ +/* + *************************************************************************** + * 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: + sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 modified for rt2561/2661 + Jan Lee 2006-08-01 modified for rt2860 for 802.11n +*/ +#include "rt_config.h" + +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) /* 2 sec */ + +/* + ========================================================================== + Description: + The sync state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + + ========================================================================== + */ +VOID SyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE); + + /* column 1 */ + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_FORCE_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeForceScanReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_FORCE_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeForceJoinReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction); + + /* column 2 */ + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + + /* column 3 */ + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction); + /* StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_CNCL, (STATE_MACHINE_FUNC)ScanCnclAction); */ + + /* resume scanning for fast-roaming */ + StateMachineSetAction(Sm, SCAN_PENDING, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); + StateMachineSetAction(Sm, SCAN_PENDING, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); + + /* timer init */ + RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + Beacon timeout handler, executed in timer thread + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n")); + + /* + Do nothing if the driver is starting halt state. + This might happen when timer already been fired before cancel timer with mlmehalt + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) + ) + { + bbp_set_bw(pAd, BW_40); + + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + } +#endif /* DOT11_N_SUPPORT */ + + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Scan timeout handler, executed in timer thread + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + + /* + Do nothing if the driver is starting halt state. + This might happen when timer already been fired before cancel timer with mlmehalt + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + + if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL, 0)) + { + RTMP_MLME_HANDLER(pAd); +} + else + { + /* To prevent SyncMachine.CurrState is SCAN_LISTEN forever. */ + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA, pAd->MlmeAux.ScanInfType); + RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, NULL, BSS0, 0); + } +} + + +VOID MlmeForceJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN TimerCancelled; + HEADER_802_11 Hdr80211; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + PUCHAR pSupRate = NULL; + UCHAR SupRateLen; + PUCHAR pExtRate = NULL; + UCHAR ExtRateLen; + UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; + UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); + MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); + +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeForeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); + +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + + if ( (RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeJoinReqAction: autopm_resume success\n")); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + } + else if ((RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == (-1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeJoinReqAction autopm_resume fail ------\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("MlmeJoinReqAction: autopm_resume do nothing \n")); + + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + +#ifdef PCIE_PS_SUPPORT + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } +#endif /* PCIE_PS_SUPPORT */ + + /* reset all the timers */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + { + RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->StaCfg.ConnectinfoSsid, pAd->StaCfg.ConnectinfoSsidLen); + pAd->MlmeAux.SsidLen = pAd->StaCfg.ConnectinfoSsidLen; + } + + pAd->MlmeAux.BssType = pAd->StaCfg.ConnectinfoBssType; + pAd->MlmeAux.Channel = pAd->StaCfg.ConnectinfoChannel; + + + /* Let BBP register at 20MHz to do scan */ + AsicSetChannel(pAd, pAd->MlmeAux.Channel, BW_20, EXTCHA_NONE, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + + RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); + + do + { + /* + send probe request + */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + if (pAd->MlmeAux.Channel <= 14) + { + pSupRate = pAd->CommonCfg.SupRate; + SupRateLen = pAd->CommonCfg.SupRateLen; + pExtRate = pAd->CommonCfg.ExtRate; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + else + { + /* + Overwrite Support Rate, CCK rate are not allowed + */ + pSupRate = ASupRate; + SupRateLen = ASupRateLen; + ExtRateLen = 0; + } + + if ((pAd->MlmeAux.BssType == BSS_INFRA) && (!MAC_ADDR_EQUAL(ZERO_MAC_ADDR, pAd->StaCfg.ConnectinfoBssid))) + { + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAd->StaCfg.ConnectinfoBssid); + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + } + else + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->CurrentAddress, + BROADCAST_ADDR); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pSupRate, + END_OF_ARGS); + + if (ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, pExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen != 0)) + { + ULONG WpsTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WpsTmpLen, + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen, + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe, + END_OF_ARGS); + + FrameLen += WpsTmpLen; + } + +#ifdef RT_CFG80211_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->cfg80211_ctrl.ExtraIeLen != 0)) + { + ULONG ExtraIeTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &ExtraIeTmpLen, + pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, + END_OF_ARGS); + + FrameLen += ExtraIeTmpLen; + } +#endif /* RT_CFG80211_SUPPORT */ + +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WFD_SUPPORT +#ifdef RT_CFG80211_SUPPORT + if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) + { + ULONG WfdIeLen, WfdIeBitmap; + PUCHAR ptr; + + ptr = pOutBuffer + FrameLen; + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO); + WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &WfdIeLen); + FrameLen += WfdIeLen; + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* WFD_SUPPORT */ + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } while (FALSE); + + DBGPRINT(0, ("FORCE JOIN SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->StaCfg.ConnectinfoChannel, PRINT_MAC(pAd->StaCfg.ConnectinfoBssid))); + + pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; +} + + +VOID MlmeForceScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType; + BOOLEAN TimerCancelled; + ULONG Now; + USHORT Status; + + /* + Check the total scan tries for one single OID command + If this is the CCX 2.0 Case, skip that! + */ + if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeForceScanReqAction before Startup\n")); + return; + } + + + /* first check the parameter sanity */ + if (MlmeScanReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + &BssType, + (PCHAR)Ssid, + &SsidLen, + &ScanType)) + { +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (pAd->ApCfg.ApCliTab[MAIN_MBSSID].Valid && RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: PWR_SAVE IN ForceScanStart\n")); + RT_CFG80211_P2P_CLI_SEND_NULL_FRAME(pAd, PWR_SAVE); + } +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* + To prevent data lost. + Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + And should send an NULL data with turned PSM bit off to AP, when scan progress done + */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + PWR_SAVE); + + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeForceScanReqAction -- Send PSM Data frame for off channel RM, SCAN_IN_PROGRESS=%d!\n", + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))); + OS_WAIT(20); + } + + /* + Check for channel load and noise hist request + Suspend MSDU only at scan request, not the last two mentioned + Suspend MSDU transmission here + YF: Move this line after SendNullFrame due to ScanInProg Flag + */ + RTMPSuspendMsduTransmission(pAd); + + RTMPSendWirelessEvent(pAd, IW_SCANNING_EVENT_FLAG, NULL, BSS0, 0); + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastScanTime = Now; + /* reset all the timers */ + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + + /* record desired BSS parameters */ + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.ScanType = ScanType; + pAd->MlmeAux.SsidLen = SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + + /* + Scanning was pending (for fast scanning) + */ + if ((pAd->StaCfg.bImprovedScan) && (pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING)) + { + pAd->MlmeAux.Channel = pAd->StaCfg.LastScanChannel; + } + else + { + if (pAd->StaCfg.bFastConnect && (pAd->CommonCfg.Channel != 0) && !pAd->StaCfg.bNotFirstScan) + { + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + } + else + /* start from the first channel */ + pAd->MlmeAux.Channel = FirstChannel(pAd); + } + + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Before scan, reset trigger event table. */ + TriEventInit(pAd); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + ScanNextChannel(pAd, OPMODE_STA, INT_MAIN); + if(pAd->StaCfg.ConnectinfoChannel != 0) + pAd->MlmeAux.Channel = 0; + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_SCAN_FOR_CONNECT; + } + else + { + DBGPRINT_ERR(("SYNC - MlmeForceScanReqAction() sanity check fail\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); + } +} + + + +/* + ========================================================================== + Description: + MLME SCAN req state machine procedure + ========================================================================== + */ +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType; + BOOLEAN TimerCancelled; + ULONG Now; + USHORT Status; + + /* + Check the total scan tries for one single OID command + If this is the CCX 2.0 Case, skip that! + */ + if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); + return; + } + +#ifdef PCIE_PS_SUPPORT + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + { + AsicSendCmdToMcuAndWait(pAd, 0x31, PowerWakeCID, 0x00, 0x02, FALSE); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, ("PSM - Issue Wake up command \n")); + } + else + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } + } +#endif /* PCIE_PS_SUPPORT */ + + /* first check the parameter sanity */ + if (MlmeScanReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + &BssType, + (PCHAR)Ssid, + &SsidLen, + &ScanType)) + { +#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE + if (pAd->ApCfg.ApCliTab[MAIN_MBSSID].Valid && RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: PWR_SAVE IN ScanStart\n")); + RT_CFG80211_P2P_CLI_SEND_NULL_FRAME(pAd, PWR_SAVE); + } + +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */ + + /* + To prevent data lost. + Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + And should send an NULL data with turned PSM bit off to AP, when scan progress done + */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + PWR_SAVE); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM, SCAN_IN_PROGRESS=%d!\n", + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))); + OS_WAIT(20); + } + + /* + Check for channel load and noise hist request + Suspend MSDU only at scan request, not the last two mentioned + Suspend MSDU transmission here + */ + RTMPSuspendMsduTransmission(pAd); + + RTMPSendWirelessEvent(pAd, IW_SCANNING_EVENT_FLAG, NULL, BSS0, 0); + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastScanTime = Now; + /* reset all the timers */ + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + + /* record desired BSS parameters */ + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.ScanType = ScanType; + pAd->MlmeAux.SsidLen = SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + + /* + Scanning was pending (for fast scanning) + */ + if ((pAd->StaCfg.bImprovedScan) && (pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING)) + { + pAd->MlmeAux.Channel = pAd->StaCfg.LastScanChannel; + } + else + { + if (pAd->StaCfg.bFastConnect && (pAd->CommonCfg.Channel != 0) && !pAd->StaCfg.bNotFirstScan) + { + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + } + else + { + { + /* start from the first channel */ + pAd->MlmeAux.Channel = FirstChannel(pAd); + } + } + } + + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Before scan, reset trigger event table. */ + TriEventInit(pAd); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + ScanNextChannel(pAd, OPMODE_STA, INT_MAIN); + } + else + { + DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); + } +} + +/* + ========================================================================== + Description: + MLME JOIN req state machine procedure + ========================================================================== + */ +VOID MlmeJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BSS_ENTRY *pBss; + BOOLEAN TimerCancelled; + HEADER_802_11 Hdr80211; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + PUCHAR pSupRate = NULL; + UCHAR SupRateLen; + PUCHAR pExtRate = NULL; + UCHAR ExtRateLen; + UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; + UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); + MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); +#ifdef WSC_STA_SUPPORT + BOOLEAN bHasWscIe = FALSE; +#endif /* WSC_STA_SUPPORT */ + +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + BOOLEAN bChangeInitBW = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + + if ( (RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeJoinReqAction: autopm_resume success\n")); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + } + else if ((RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == (-1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeJoinReqAction autopm_resume fail ------\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("MlmeJoinReqAction: autopm_resume do nothing \n")); + + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + + + +#ifdef PCIE_PS_SUPPORT + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } +#endif /* PCIE_PS_SUPPORT */ + + /* reset all the timers */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; + + /* record the desired SSID & BSSID we're waiting for */ + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); + + /* If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. */ + if (pBss->Hidden == 0) + { + RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); + pAd->MlmeAux.SsidLen = pBss->SsidLen; + } + + pAd->MlmeAux.BssType = pBss->BssType; + pAd->MlmeAux.Channel = pBss->Channel; + pAd->MlmeAux.CentralChannel = pBss->CentralChannel; + +#ifdef EXT_BUILD_CHANNEL_LIST + /* Country IE of the AP will be evaluated and will be used. */ + if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) && + (pBss->bHasCountryIE == TRUE)) + { + NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2); + if (pBss->CountryString[2] == 'I') + pAd->CommonCfg.Geography = IDOR; + else if (pBss->CountryString[2] == 'O') + pAd->CommonCfg.Geography = ODOR; + else + pAd->CommonCfg.Geography = BOTH; + BuildChannelListEx(pAd); + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + + { + bChangeInitBW = TRUE; + } + + + if (bChangeInitBW == TRUE) + { + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set BBP BW=20MHz\n", __FUNCTION__)); + + /* switch channel and waiting for beacon timer */ + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + } + +#ifdef WSC_STA_SUPPORT +#ifdef WSC_LED_SUPPORT + /* LED indication. */ + if (pAd->MlmeAux.BssType == BSS_INFRA) + { + LEDConnectionStart(pAd); + LEDConnectionCompletion(pAd, TRUE); + } +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + + RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); + + do + { + if (((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */ + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + { + /* We can't send any Probe request frame to meet 802.11h. */ + if (pBss->Hidden == 0) + break; + } + + /* + send probe request + */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + if (pAd->MlmeAux.Channel <= 14) + { + pSupRate = pAd->CommonCfg.SupRate; + SupRateLen = pAd->CommonCfg.SupRateLen; + pExtRate = pAd->CommonCfg.ExtRate; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + else + { + /* Overwrite Support Rate, CCK rate are not allowed */ + pSupRate = ASupRate; + SupRateLen = ASupRateLen; + ExtRateLen = 0; + } + + if (pAd->MlmeAux.BssType == BSS_INFRA) + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, + pAd->CurrentAddress, + pAd->MlmeAux.Bssid); + else + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->CurrentAddress, + BROADCAST_ADDR); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pSupRate, + END_OF_ARGS); + + if (ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, pExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + +#ifdef WSC_STA_SUPPORT + /* Append WSC information in probe request if WSC state is running */ + if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && + (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger + )) + bHasWscIe = TRUE; +#ifdef WSC_V2_SUPPORT + else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && + (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) + bHasWscIe = TRUE; +#endif /* WSC_V2_SUPPORT */ + + if (bHasWscIe) + { + UCHAR WscIeLen = 0; + UCHAR *WscBuf = NULL; + ULONG WscTmpLen = 0; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&WscBuf, 256); + if (WscBuf != NULL) + { + NdisZeroMemory(WscBuf, 256); + WscBuildProbeReqIE(pAd, STA_MODE, WscBuf, &WscIeLen); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, WscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, WscBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } +#endif /* WSC_STA_SUPPORT */ + + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen != 0)) + { + ULONG WpsTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WpsTmpLen, + pAd->StaCfg.wpa_supplicant_info.WpsProbeReqIeLen, + pAd->StaCfg.wpa_supplicant_info.pWpsProbeReqIe, + END_OF_ARGS); + + FrameLen += WpsTmpLen; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->cfg80211_ctrl.ExtraIeLen != 0)) + { + ULONG ExtraIeTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &ExtraIeTmpLen, + pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, + END_OF_ARGS); + + FrameLen += ExtraIeTmpLen; + } +#endif /* RT_CFG80211_SUPPORT */ + +#ifdef WFD_SUPPORT +#ifdef RT_CFG80211_SUPPORT + if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) + { + ULONG WfdIeLen, WfdIeBitmap; + PUCHAR ptr; + + ptr = pOutBuffer + FrameLen; + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO); + WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &WfdIeLen); + FrameLen += WfdIeLen; + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* WFD_SUPPORT */ + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", + pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + + pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; +} + +/* + ========================================================================== + Description: + MLME START Request state machine procedure, starting an IBSS + ========================================================================== + */ +VOID MlmeStartReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; + BOOLEAN TimerCancelled; + UCHAR *VarIE = NULL; /* New for WPA security suites */ + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + LARGE_INTEGER TimeStamp; + BOOLEAN Privacy; + USHORT Status; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + TimeStamp.u.LowPart = 0; + TimeStamp.u.HighPart = 0; + + if ((MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, (PCHAR)Ssid, &SsidLen)) && + (CHAN_PropertyCheck(pAd, pAd->MlmeAux.Channel, CHANNEL_NO_IBSS) == FALSE)) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + /* reset all the timers */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + /* Start a new IBSS. All IBSS parameters are decided now */ + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); + pAd->MlmeAux.BssType = BSS_ADHOC; + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + pAd->MlmeAux.SsidLen = SsidLen; + +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.IWscInfo.bDoNotChangeBSSID) + pAd->StaCfg.IWscInfo.bDoNotChangeBSSID = FALSE; + else +#endif /* IWSC_SUPPORT */ + { + /* generate a radom number as BSSID */ + MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n")); + } + + Privacy = (wdev->WepStatus == Ndis802_11WEPEnabled) || + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable); + pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0); + pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; + pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; + + pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->StaCfg.bAdhocN == TRUE)) + { + RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &wdev->DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); + pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE); + /* Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. */ + DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->MlmeAux.Channel > 14)) + { + build_vht_cap_ie(pAd, (UCHAR *)&pAd->MlmeAux.vht_cap); + pAd->MlmeAux.vht_cap_len = sizeof(VHT_CAP_IE); + } +#endif /* DOT11_VHT_AC */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + pAd->MlmeAux.HtCapabilityLen = 0; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16); + } + /* temporarily not support QOS in IBSS */ + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", + pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status, 0); + } + else + { + DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status, 0); + } + + if (VarIE != NULL) + os_free_mem(NULL, VarIE); +} + + +//+++Add by shiang to check correctness of new sanity function +VOID rtmp_dbg_sanity_diff(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + /* Parameters used for old sanity function */ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR *Ssid = NULL; + UCHAR SsidLen=0, DtimCount, DtimPeriod, BcastFlag, MessageToMe, NewChannel, Channel = 0, BssType; + CF_PARM CfParm = {0}; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + LARGE_INTEGER TimeStamp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR CkipFlag; + EDCA_PARM EdcaParm = {0}; + UCHAR AironetCellPowerLimit; + UCHAR SupRateLen, ExtRateLen; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability = {0}; + ULONG RalinkIe; + UCHAR AddHtInfoLen; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + UCHAR Erp; + UCHAR NewExtChannelOffset = 0xff; + USHORT LenVIE; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + UCHAR SelReg = 0; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + + + BCN_IE_LIST *ie_list = NULL; + BOOLEAN sanity_new, sanity_old; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + goto LabelErr; + os_alloc_mem(NULL, (UCHAR **)&pHtCapability, sizeof(HT_CAPABILITY_IE)); + if (pHtCapability == NULL) + goto LabelErr; + os_alloc_mem(NULL, (UCHAR **)&pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + if (pAddHtInfo == NULL) + goto LabelErr; + + + NdisZeroMemory(&QbssLoad, sizeof(QBSS_LOAD_PARM)); /* woody */ +#ifdef DOT11_N_SUPPORT + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); +#endif /* DOT11_N_SUPPORT */ + + NdisZeroMemory(Ssid, MAX_LEN_OF_SSID); + + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + goto LabelErr; + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + + + sanity_new = PeerBeaconAndProbeRspSanity(pAd, + &Elem->Msg[0], Elem->MsgLen, + Elem->Channel, + ie_list, &LenVIE, pVIE); + + sanity_old = PeerBeaconAndProbeRspSanity_Old(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + (PCHAR)Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + &PreNHtCapabilityLen, +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + &SelReg, +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE); + + if (sanity_old != sanity_new) + { + DBGPRINT(RT_DEBUG_ERROR, ("sanity mismatch, old=%d, new=%d\n", sanity_old, sanity_new)); + } + else + { + if (NdisCmpMemory(&ie_list->Addr2[0], &Addr2[0], MAC_ADDR_LEN) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Add2 mismatch!Old=%02x:%02x:%02x:%02x:%02x:%02x!New=%02x:%02x:%02x:%02x:%02x:%02x!\n", + PRINT_MAC(Addr2), PRINT_MAC(ie_list->Addr2))); + } + + if (NdisCmpMemory(&ie_list->Bssid[0], &Bssid[0], MAC_ADDR_LEN) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Bssid mismatch!Old=%02x:%02x:%02x:%02x:%02x:%02x!New=%02x:%02x:%02x:%02x:%02x:%02x!\n", + PRINT_MAC(Bssid), PRINT_MAC(ie_list->Bssid))); + } + + if (SsidLen != ie_list->SsidLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("SsidLen mismatch!Old=%d, New=%d\n", SsidLen, ie_list->SsidLen)); + } + + if (NdisCmpMemory(&ie_list->Ssid[0], &Ssid[0], SsidLen) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Ssid mismatch!Old=%s, New=%s\n", Ssid, ie_list->Ssid)); + } + + if (BssType != ie_list->BssType) + { + DBGPRINT(RT_DEBUG_ERROR, ("BssType mismatch!Old=%d, New=%d\n", BssType, ie_list->BssType)); + } + + if (BeaconPeriod != ie_list->BeaconPeriod) + { + DBGPRINT(RT_DEBUG_ERROR, ("BeaconPeriod mismatch!Old=%d, New=%d\n", BeaconPeriod, ie_list->BeaconPeriod)); + } + + if (Channel != ie_list->Channel) + { + DBGPRINT(RT_DEBUG_ERROR, ("Channel mismatch!Old=%d, New=%d\n", Channel, ie_list->Channel)); + } + + if (NewChannel != ie_list->NewChannel) + { + DBGPRINT(RT_DEBUG_ERROR, ("NewChannel mismatch!Old=%d, New=%d\n", NewChannel, ie_list->NewChannel)); + } + + if (NdisCmpMemory(&ie_list->TimeStamp, &TimeStamp, sizeof(LARGE_INTEGER)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("TimeStamp mismatch!Old=%d - %d, New=%d - %d\n", + TimeStamp.u.LowPart, TimeStamp.u.HighPart, + ie_list->TimeStamp.u.LowPart, ie_list->TimeStamp.u.HighPart)); + } + + if (NdisCmpMemory(&ie_list->CfParm, &CfParm, sizeof(CF_PARM)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("CFParam mismatch!\n")); + hex_dump("Old CFParam", (UCHAR *)&CfParm, sizeof(CF_PARM)); + hex_dump("New CFParam", (UCHAR *)&ie_list->CfParm, sizeof(CF_PARM)); + } + + if (AtimWin != ie_list->AtimWin) + { + DBGPRINT(RT_DEBUG_ERROR, ("AtimWin mismatch!Old=%d, New=%d\n", AtimWin, ie_list->AtimWin)); + } + + + if (CapabilityInfo != ie_list->CapabilityInfo) + { + DBGPRINT(RT_DEBUG_ERROR, ("CapabilityInfo mismatch!Old=%d, New=%d\n", CapabilityInfo, ie_list->CapabilityInfo)); + } + + if (Erp != ie_list->Erp) + { + DBGPRINT(RT_DEBUG_ERROR, ("Erp mismatch!Old=%d, New=%d\n", Erp, ie_list->Erp)); + } + + if (DtimCount != ie_list->DtimCount) + { + DBGPRINT(RT_DEBUG_ERROR, ("DtimCount mismatch!Old=%d, New=%d\n", DtimCount, ie_list->DtimCount)); + } + + if (DtimPeriod != ie_list->DtimPeriod) + { + DBGPRINT(RT_DEBUG_ERROR, ("DtimPeriod mismatch!Old=%d, New=%d\n", DtimPeriod, ie_list->DtimPeriod)); + } + + if (BcastFlag != ie_list->BcastFlag) + { + DBGPRINT(RT_DEBUG_ERROR, ("BcastFlag mismatch!Old=%d, New=%d\n", BcastFlag, ie_list->BcastFlag)); + } + + if (MessageToMe != ie_list->MessageToMe) + { + DBGPRINT(RT_DEBUG_ERROR, ("MessageToMe mismatch!Old=%d, New=%d\n", MessageToMe, ie_list->MessageToMe)); + } + + if (SupRateLen != ie_list->SupRateLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("SupRateLen mismatch!Old=%d, New=%d\n", SupRateLen, ie_list->SupRateLen)); + } + + if (NdisCmpMemory(&ie_list->SupRate[0], &SupRate, ie_list->SupRateLen) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("SupRate mismatch!\n")); + hex_dump("Old SupRate", (UCHAR *)&SupRate, ie_list->SupRateLen); + hex_dump("New SupRate", (UCHAR *)&ie_list->SupRate, ie_list->SupRateLen); + } + + + if (ExtRateLen != ie_list->ExtRateLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("ExtRateLen mismatch!Old=%d, New=%d\n", ExtRateLen, ie_list->ExtRateLen)); + } + if (NdisCmpMemory(&ie_list->ExtRate[0], &ExtRate, ie_list->ExtRateLen) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ExtRate mismatch!\n")); + hex_dump("Old ExtRate", (UCHAR *)&ExtRate, ie_list->ExtRateLen); + hex_dump("New ExtRate", (UCHAR *)&ie_list->ExtRate, ie_list->ExtRateLen); + } + + + if (CkipFlag != ie_list->CkipFlag) + { + DBGPRINT(RT_DEBUG_ERROR, ("CkipFlag mismatch!Old=%d, New=%d\n", CkipFlag, ie_list->CkipFlag)); + } + + if (AironetCellPowerLimit != ie_list->AironetCellPowerLimit) + { + DBGPRINT(RT_DEBUG_ERROR, ("AironetCellPowerLimit mismatch!Old=%d, New=%d\n", AironetCellPowerLimit, ie_list->AironetCellPowerLimit)); + } + if (NdisCmpMemory(&ie_list->EdcaParm, &EdcaParm, sizeof(EDCA_PARM)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("EdcaParm mismatch!\n")); + hex_dump("Old EdcaParm", (UCHAR *)&EdcaParm, sizeof(EDCA_PARM)); + hex_dump("New EdcaParm", (UCHAR *)&ie_list->EdcaParm, sizeof(EDCA_PARM)); + } + + if (NdisCmpMemory(&ie_list->QbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("QbssLoad mismatch!\n")); + hex_dump("Old QbssLoad", (UCHAR *)&QbssLoad, sizeof(QBSS_LOAD_PARM)); + hex_dump("New QbssLoad", (UCHAR *)&ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + } + + if (NdisCmpMemory(&ie_list->QosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("QosCapability mismatch!\n")); + hex_dump("Old QosCapability", (UCHAR *)&QosCapability, sizeof(QOS_CAPABILITY_PARM)); + hex_dump("New QosCapability", (UCHAR *)&ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + if (RalinkIe != ie_list->RalinkIe) + { + DBGPRINT(RT_DEBUG_ERROR, ("RalinkIe mismatch!Old=%lx, New=%lx\n", RalinkIe, ie_list->RalinkIe)); + } + + if (HtCapabilityLen != ie_list->HtCapabilityLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("HtCapabilityLen mismatch!Old=%d, New=%d\n", HtCapabilityLen, ie_list->HtCapabilityLen)); + } + +#ifdef CONFIG_STA_SUPPORT + if (PreNHtCapabilityLen != ie_list->PreNHtCapabilityLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("PreNHtCapabilityLen mismatch!Old=%d, New=%d\n", PreNHtCapabilityLen, ie_list->PreNHtCapabilityLen)); + } +#endif /* CONFIG_STA_SUPPORT */ + if (NdisCmpMemory(&ie_list->HtCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pHtCapability mismatch!\n")); + hex_dump("Old HtCapability", (UCHAR *)pHtCapability, sizeof(HT_CAPABILITY_IE)); + hex_dump("New HtCapability", (UCHAR *)&ie_list->HtCapability, sizeof(HT_CAPABILITY_IE)); + } + + if (NdisCmpMemory(&ie_list->ExtCapInfo, &ExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ExtCapInfo mismatch!\n")); + hex_dump("Old ExtCapInfo", (UCHAR *)&ExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)); + hex_dump("New ExtCapInfo", (UCHAR *)&ie_list->ExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)); + } + + if (AddHtInfoLen != ie_list->AddHtInfoLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("AddHtInfoLen mismatch!Old=%d, New=%d\n", AddHtInfoLen, ie_list->AddHtInfoLen)); + } + + if (NdisCmpMemory(&ie_list->AddHtInfo, pAddHtInfo, sizeof(ADD_HT_INFO_IE)) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("AddHtInfo mismatch!\n")); + hex_dump("Old AddHtInfo", (UCHAR *)pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + hex_dump("New AddHtInfo", (UCHAR *)&ie_list->AddHtInfo, sizeof(ADD_HT_INFO_IE)); + } + + if (NewExtChannelOffset != ie_list->NewExtChannelOffset) + { + DBGPRINT(RT_DEBUG_ERROR, ("AddHtInfoLen mismatch!Old=%d, New=%d\n", NewExtChannelOffset, ie_list->NewExtChannelOffset)); + } + } + goto LabelOK; + +LabelErr: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + +LabelOK: + if (Ssid != NULL) + os_free_mem(NULL, Ssid); + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (pHtCapability != NULL) + os_free_mem(NULL, pHtCapability); + if (pAddHtInfo != NULL) + os_free_mem(NULL, pAddHtInfo); + + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + +} +//---Add by shiang to check correctness of new sanity function + + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFrame; + USHORT LenVIE; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + BCN_IE_LIST *ie_list = NULL; + + + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (!ie_list) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc ie_list failed!\n", __FUNCTION__)); + return; + } + NdisZeroMemory((UCHAR *)ie_list, sizeof(BCN_IE_LIST)); + + /* Init Variable IE structure */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + goto LabelErr; + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + + pFrame = (PFRAME_802_11) Elem->Msg; + + + if (PeerBeaconAndProbeRspSanity(pAd, + &Elem->Msg[0], Elem->MsgLen, + Elem->Channel, + ie_list, &LenVIE, pVIE)) + { + ULONG Idx = 0; + CHAR Rssi = 0; + + Idx = BssTableSearch(&pAd->ScanTab, &ie_list->Bssid[0], ie_list->Channel); + if (Idx != BSS_NOT_FOUND) + Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; + + Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + +#ifdef DOT11_N_SUPPORT + if ((ie_list->HtCapabilityLen > 0) || (ie_list->PreNHtCapabilityLen > 0)) + ie_list->HtCapabilityLen = SIZE_HT_CAP_IE; +#endif /* DOT11_N_SUPPORT */ + + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE); +#ifdef DOT11_N_SUPPORT + /* TODO: Check for things need to do when enable "DOT11V_WNM_SUPPORT" */ +#ifdef DOT11N_DRAFT3 + /* Check if this scan channel is the effeced channel */ + if (INFRA_ON(pAd) + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + && ((ie_list->Channel > 0) && (ie_list->Channel <= 14))) + { + int chListIdx; + + /* find the channel list idx by the channel number */ + for (chListIdx = 0; chListIdx < pAd->ChannelListNum; chListIdx++) + { + if (ie_list->Channel == pAd->ChannelList[chListIdx].Channel) + break; + } + + if (chListIdx < pAd->ChannelListNum) + { + /* + If this channel is effected channel for the 20/40 coex operation. Check the related IEs. + */ + if (pAd->ChannelList[chListIdx].bEffectedChannel == TRUE) + { + UCHAR RegClass; + OVERLAP_BSS_SCAN_IE BssScan; + + /* Read Beacon's Reg Class IE if any. */ + PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &BssScan, &RegClass); + TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, &ie_list->Bssid[0], + &ie_list->HtCapability, ie_list->HtCapabilityLen, + RegClass, ie_list->Channel); + } + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + if (Idx != BSS_NOT_FOUND) + { + BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[Idx]; + NdisMoveMemory(pBssEntry->PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pBssEntry->TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pBssEntry->TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + + pBssEntry->MinSNR = Elem->Signal % 10; + if (pBssEntry->MinSNR == 0) + pBssEntry->MinSNR = -5; + + NdisMoveMemory(pBssEntry->MacAddr, &ie_list->Addr2[0], MAC_ADDR_LEN); + + if ((pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_RSP) && (LenVIE != 0)) + { + pBssEntry->VarIeFromProbeRspLen = 0; + if (pBssEntry->pVarIeFromProbRsp) + { + pBssEntry->VarIeFromProbeRspLen = LenVIE; + RTMPZeroMemory(pBssEntry->pVarIeFromProbRsp, MAX_VIE_LEN); + RTMPMoveMemory(pBssEntry->pVarIeFromProbRsp, pVIE, LenVIE); + } + } + } + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + if (RTMPEqualMemory(ie_list->Ssid, "DIRECT-", 7)) + DBGPRINT(RT_DEBUG_OFF, ("%s P2P_SCANNING: %s [%d]\n", __FUNCTION__, ie_list->Ssid, Idx)); + + RT_CFG80211_SCANNING_INFORM(pAd, Idx, Elem->Channel, (UCHAR *)pFrame, + Elem->MsgLen, Rssi); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + } + /* sanity check fail, ignored */ + goto LabelOK; + +LabelErr: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + +LabelOK: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + return; +} + + +/* + ========================================================================== + Description: + When waiting joining the (I)BSS, beacon received from external + ========================================================================== + */ +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN TimerCancelled; + USHORT LenVIE; + USHORT Status; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + ULONG Idx = 0; + CHAR Rssi = 0; + +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; + BOOLEAN bAllowNrate = FALSE; +#endif /* DOT11_N_SUPPORT */ + BCN_IE_LIST *ie_list = NULL; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + UCHAR SelReg = 0; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + goto LabelErr; + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + goto LabelErr; + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + ie_list, + &LenVIE, + pVIE)) + { + /* Disqualify 11b only adhoc when we are in 11g only adhoc mode */ + if ((ie_list->BssType == BSS_ADHOC) && + WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_G) && + ((ie_list->SupRateLen+ie_list->ExtRateLen)< 12)) + goto LabelOK; + + + /* + BEACON from desired BSS/IBSS found. We should be able to decide most + BSS parameters here. + Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? + Do we need to receover back all parameters belonging to previous BSS? + A. Should be not. There's no back-door recover to previous AP. It still need + a new JOIN-AUTH-ASSOC sequence. + */ + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, &ie_list->Bssid[0])) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():receive desired BEACON,Channel=%d\n", + __FUNCTION__, ie_list->Channel)); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + /* Update RSSI to prevent No signal display when cards first initialized */ + pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); + pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); + pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); + pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0; + pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3; + pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1; + pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3; + pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2; + pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3; + + /* + We need to check if SSID only set to any, then we can record the current SSID. + Otherwise will cause hidden SSID association failed. + */ + if (pAd->MlmeAux.SsidLen == 0) + { + NdisMoveMemory(pAd->MlmeAux.Ssid, ie_list->Ssid, ie_list->SsidLen); + pAd->MlmeAux.SsidLen = ie_list->SsidLen; + } + else + { + Idx = BssSsidTableSearch(&pAd->ScanTab, ie_list->Bssid, + pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, + ie_list->Channel); + + if (Idx == BSS_NOT_FOUND) + { + Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE); + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + ie_list->CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; + + pAd->ScanTab.BssEntry[Idx].MinSNR = Elem->Signal % 10; + if (pAd->ScanTab.BssEntry[Idx].MinSNR == 0) + pAd->ScanTab.BssEntry[Idx].MinSNR = -5; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].MacAddr, ie_list->Addr2, MAC_ADDR_LEN); + } + } + else + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) + ; + else +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WSC_STA_SUPPORT + if ((pAd->StaCfg.WscControl.WscState != WSC_STATE_OFF) + ) + ; + else +#endif /* WSC_STA_SUPPORT */ + { + + /* + Check if AP privacy is different Staion, if yes, + start a new scan and ignore the frame + (often happen during AP change privacy at short time) + */ + if ((((wdev->WepStatus != Ndis802_11WEPDisabled) << 4) ^ ie_list->CapabilityInfo) & 0x0010) + { +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + /* When using -Dwext and trigger WPS, do not check security. */ + if ( SelReg == 0 ) +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + { + MLME_SCAN_REQ_STRUCT ScanReq; + DBGPRINT(RT_DEBUG_TRACE, ("%s:AP privacy %d is differenct from STA privacy%d\n", + __FUNCTION__, (ie_list->CapabilityInfo & 0x0010) >> 4 , + wdev->WepStatus != Ndis802_11WEPDisabled)); + ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + RTMP_MLME_HANDLER(pAd); + goto LabelOK; + } + } + } + + /* Multiple SSID case, used correct CapabilityInfo */ + ie_list->CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; + } + } + pAd->MlmeAux.CapabilityInfo = ie_list->CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pAd->MlmeAux.BssType = ie_list->BssType; + pAd->MlmeAux.BeaconPeriod = ie_list->BeaconPeriod; + + /* + Some AP may carrys wrong beacon interval (ex. 0) in Beacon IE. + We need to check here for preventing divided by 0 error. + */ + if (pAd->MlmeAux.BeaconPeriod == 0) + pAd->MlmeAux.BeaconPeriod = 100; + + pAd->MlmeAux.Channel = ie_list->Channel; + pAd->MlmeAux.AtimWin = ie_list->AtimWin; + pAd->MlmeAux.CfpPeriod = ie_list->CfParm.CfpPeriod; + pAd->MlmeAux.CfpMaxDuration = ie_list->CfParm.CfpMaxDuration; + pAd->MlmeAux.APRalinkIe = ie_list->RalinkIe; + + /* + Copy AP's supported rate to MlmeAux for creating assoication request + Also filter out not supported rate + */ + pAd->MlmeAux.SupRateLen = ie_list->SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, ie_list->SupRate, ie_list->SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = ie_list->ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ie_list->ExtRate, ie_list->ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + + NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); + +#ifdef DOT11R_FT_SUPPORT + if (pAd->StaCfg.Dot11RCommInfo.bFtSupport && + FT_GetMDIE(pVIE, LenVIE, &pAd->MlmeAux.MdIeInfo)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MdId=%x%x, FtOverDs=%d, RsrReqCap=%d)\n", + pAd->MlmeAux.MdIeInfo.MdId[0], + pAd->MlmeAux.MdIeInfo.MdId[1], + pAd->MlmeAux.MdIeInfo.FtCapPlc.field.FtOverDs, + pAd->MlmeAux.MdIeInfo.FtCapPlc.field.RsrReqCap)); + } +#endif /* DOT11R_FT_SUPPORT */ + + /* Get the ext capability info element */ + NdisMoveMemory(&pAd->MlmeAux.ExtCapInfo, &ie_list->ExtCapInfo,sizeof(ie_list->ExtCapInfo)); + +#ifdef DOT11_VHT_AC + pAd->StaActive.SupportedPhyInfo.bVhtEnable = FALSE; + pAd->StaActive.SupportedPhyInfo.vht_bw = VHT_BW_2040; +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAux.ExtCapInfo=%d\n", pAd->MlmeAux.ExtCapInfo.BssCoexistMgmtSupport)); + if (pAd->CommonCfg.bBssCoexEnable == TRUE) + pAd->CommonCfg.ExtCapIE.BssCoexistMgmtSupport = 1; +#endif /* DOT11N_DRAFT3 */ + + if (((wdev->WepStatus != Ndis802_11WEPEnabled) && (wdev->WepStatus != Ndis802_11TKIPEnable)) + || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) + { + if ((pAd->StaCfg.BssType == BSS_INFRA) || + ((pAd->StaCfg.BssType == BSS_ADHOC) && (pAd->StaCfg.bAdhocN == TRUE))) + bAllowNrate = TRUE; + } + + pAd->MlmeAux.NewExtChannelOffset = ie_list->NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = ie_list->HtCapabilityLen; + + CentralChannel = ie_list->Channel; + + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + /* filter out un-supported ht rates */ + if (((ie_list->HtCapabilityLen > 0) || (ie_list->PreNHtCapabilityLen > 0)) && + (wdev->DesiredHtPhyInfo.bHtEnable) && + (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && bAllowNrate)) + { + RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &ie_list->AddHtInfo, SIZE_ADD_HT_INFO_IE); + + /* StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability */ + NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, ie_list->HtCapability.MCSSet, 16); + pAd->MlmeAux.NewExtChannelOffset = ie_list->NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + if (ie_list->PreNHtCapabilityLen > 0) + pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; + RTMPCheckHt(pAd, BSSID_WCID, &ie_list->HtCapability, &ie_list->AddHtInfo); + /* Copy AP Parameter to StaActive. This is also in LinkUp. */ + DBGPRINT(RT_DEBUG_TRACE, ("%s():(MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", + __FUNCTION__, pAd->StaActive.SupportedHtPhy.MpduDensity, + pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, + ie_list->HtCapability.HtCapInfo.ChannelWidth)); + + if (ie_list->AddHtInfoLen > 0) + { + /* Check again the Bandwidth capability of this AP. */ + CentralChannel = get_cent_ch_by_htinfo(pAd, + &ie_list->AddHtInfo, + &ie_list->HtCapability); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): HT-CtrlChannel=%d, CentralChannel=>%d\n", + __FUNCTION__, ie_list->AddHtInfo.ControlChan, CentralChannel)); + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->MlmeAux.Channel > 14) && + (ie_list->vht_cap_len) && (ie_list->vht_op_len)) + { + VHT_OP_INFO *vht_op = &ie_list->vht_op_ie.vht_op_info; + + RTMPZeroMemory(&pAd->MlmeAux.vht_cap, sizeof(VHT_CAP_IE)); + NdisMoveMemory(&pAd->MlmeAux.vht_cap, &ie_list->vht_cap_ie, ie_list->vht_cap_len); + pAd->MlmeAux.vht_cap_len = ie_list->vht_cap_len; + + RTMPZeroMemory(&pAd->MlmeAux.vht_op, sizeof(VHT_OP_IE)); + NdisMoveMemory(&pAd->MlmeAux.vht_op, &ie_list->vht_op_ie, ie_list->vht_op_len); + pAd->MlmeAux.vht_op_len = ie_list->vht_op_len; + + pAd->StaActive.SupportedPhyInfo.bVhtEnable = TRUE; + + if (vht_op->ch_width == 0) { + pAd->StaActive.SupportedPhyInfo.vht_bw = VHT_BW_2040; + } else if (vht_op->ch_width == 1) { + CentralChannel = vht_op->center_freq_1; + pAd->StaActive.SupportedPhyInfo.vht_bw = VHT_BW_80; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s(): CentralChannel=>%d\n", + __FUNCTION__, CentralChannel)); + } +#endif /* DOT11_VHT_AC */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* To prevent error, let legacy AP must have same CentralChannel and Channel. */ + if ((ie_list->HtCapabilityLen == 0) && (ie_list->PreNHtCapabilityLen == 0)) + pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; + + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; +#ifdef DOT11_VHT_AC + pAd->StaActive.SupportedPhyInfo.bVhtEnable = FALSE; + pAd->StaActive.SupportedPhyInfo.vht_bw = VHT_BW_2040; +#endif /* DOT11_VHT_AC */ + pAd->MlmeAux.NewExtChannelOffset = 0xff; + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + pAd->MlmeAux.HtCapabilityLen = 0; + RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + } + + pAd->hw_cfg.cent_ch = CentralChannel; + + pAd->MlmeAux.CentralChannel = pAd->hw_cfg.cent_ch; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): Set CentralChannel=%d\n", __FUNCTION__, pAd->MlmeAux.CentralChannel)); + + RTMPUpdateMlmeRate(pAd); + + /* copy QOS related information */ + if ((pAd->CommonCfg.bWmmCapable) +#ifdef DOT11_N_SUPPORT + || WMODE_CAP_N(pAd->CommonCfg.PhyMode) +#endif /* DOT11_N_SUPPORT */ + ) + { + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else + { + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + __FUNCTION__, pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.ExtRateLen)); + + if (ie_list->AironetCellPowerLimit != 0xFF) + { + /* We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, ie_list->AironetCellPowerLimit); + } + else /* Used the default TX Power Percentage. */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + + if (pAd->StaCfg.BssType == BSS_INFRA) + { + BOOLEAN InfraAP_BW; + UCHAR BwFallBack = 0; + + if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40) + InfraAP_BW = TRUE; + else + InfraAP_BW = FALSE; + + AdjustChannelRelatedValue(pAd, + &BwFallBack, + BSS0, + InfraAP_BW, + pAd->MlmeAux.Channel, + pAd->MlmeAux.CentralChannel); + } + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status, 0); + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + if (RTMPEqualMemory(ie_list->Ssid, "DIRECT-", 7)) + DBGPRINT(RT_DEBUG_OFF, ("%s P2P_SCANNING: %s [%d]\n", __FUNCTION__, ie_list->Ssid, Idx)); + + RT_CFG80211_SCANNING_INFORM(pAd, Idx, Elem->Channel, Elem->Msg, + Elem->MsgLen, Rssi); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + } + /* not to me BEACON, ignored */ + } + /* sanity check fail, ignore this frame */ + + goto LabelOK; + +LabelErr: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + +LabelOK: + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + + return; +} + +/* + ========================================================================== + Description: + receive BEACON from peer + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerBeacon(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR index=0; + USHORT TbttNumToNextWakeUp; + USHORT LenVIE; + UCHAR *VarIE = NULL; /* Total VIE length = MAX_VIE_LEN - -5 */ + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + BCN_IE_LIST *bcn_ie_list = NULL; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + UCHAR SelReg = 0; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) + )) + return; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&bcn_ie_list, sizeof(BCN_IE_LIST)); + if (bcn_ie_list == NULL) + goto LabelErr; + NdisZeroMemory(bcn_ie_list, sizeof(BCN_IE_LIST)); + + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + goto LabelErr; + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + bcn_ie_list, + &LenVIE, + pVIE)) + { + BOOLEAN is_my_bssid, is_my_ssid; + ULONG Bssidx, Now; + BSS_ENTRY *pBss; + CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + is_my_bssid = MAC_ADDR_EQUAL(bcn_ie_list->Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; + is_my_ssid = SSID_EQUAL(bcn_ie_list->Ssid, bcn_ie_list->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; + + + + + /* ignore BEACON not for my SSID */ + if ((!is_my_ssid) && (!is_my_bssid)) + goto LabelOK; + + /* It means STA waits disassoc completely from this AP, ignores this beacon. */ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) + goto LabelOK; + +#ifdef DOT11_N_SUPPORT + /* Copy Control channel for this BSSID. */ + if (bcn_ie_list->AddHtInfoLen != 0) + bcn_ie_list->Channel = bcn_ie_list->AddHtInfo.ControlChan; + + if ((bcn_ie_list->HtCapabilityLen > 0) || (bcn_ie_list->PreNHtCapabilityLen > 0)) + bcn_ie_list->HtCapabilityLen = SIZE_HT_CAP_IE; +#endif /* DOT11_N_SUPPORT */ + + /* Housekeeping "SsidBssTab" table for later-on ROAMing usage. */ + Bssidx = BssTableSearchWithSSID(&pAd->MlmeAux.SsidBssTab, bcn_ie_list->Bssid, bcn_ie_list->Ssid, bcn_ie_list->SsidLen, bcn_ie_list->Channel); + if (Bssidx == BSS_NOT_FOUND) + { + /* discover new AP of this network, create BSS entry */ + Bssidx = BssTableSetEntry(pAd, &pAd->MlmeAux.SsidBssTab, bcn_ie_list, RealRssi, LenVIE, pVIE); + if (Bssidx == BSS_NOT_FOUND) + ; + else + { + BSS_ENTRY *pBssEntry = &pAd->MlmeAux.SsidBssTab.BssEntry[Bssidx]; + NdisMoveMemory(&pBssEntry->PTSF[0], &Elem->Msg[24], 4); + NdisMoveMemory(&pBssEntry->TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pBssEntry->TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + pBssEntry->Rssi = RealRssi; + + NdisMoveMemory(pBssEntry->MacAddr, bcn_ie_list->Addr2, MAC_ADDR_LEN); + + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT +// if (RTMPEqualMemory(ie_list->Ssid, "DIRECT-", 7)) + DBGPRINT(RT_DEBUG_INFO, ("%s PASSIVE SCANNING: %s [%d]\n", __FUNCTION__, bcn_ie_list->Ssid, Bssidx)); + + RT_CFG80211_SCANNING_INFORM(pAd, Bssidx, Elem->Channel, Elem->Msg, + Elem->MsgLen, RealRssi); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + + } + } + + /* Update ScanTab */ + Bssidx = BssTableSearch(&pAd->ScanTab, bcn_ie_list->Bssid, bcn_ie_list->Channel); + if (Bssidx == BSS_NOT_FOUND) + { + /* discover new AP of this network, create BSS entry */ + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, bcn_ie_list, RealRssi, LenVIE, pVIE); + if (Bssidx == BSS_NOT_FOUND) /* return if BSS table full */ + goto LabelOK; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + pAd->ScanTab.BssEntry[Bssidx].MinSNR = Elem->Signal % 10; + if (pAd->ScanTab.BssEntry[Bssidx].MinSNR == 0) + pAd->ScanTab.BssEntry[Bssidx].MinSNR = -5; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].MacAddr, bcn_ie_list->Addr2, MAC_ADDR_LEN); + + + + } + + /* + if the ssid matched & bssid unmatched, we should select the bssid with large value. + This might happened when two STA start at the same time + */ + if ((! is_my_bssid) && ADHOC_ON(pAd)) + { + INT i; +#ifdef IWSC_SUPPORT + if ((pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) + { + ; + } + else +#endif /* IWSC_SUPPORT */ + /* Add the safeguard against the mismatch of adhoc wep status */ + if ((wdev->WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) || + (wdev->AuthMode != pAd->ScanTab.BssEntry[Bssidx].AuthMode)) + { + goto LabelOK; + } + /* collapse into the ADHOC network which has bigger BSSID value. */ + for (i = 0; i < 6; i++) + { + if (bcn_ie_list->Bssid[i] > pAd->CommonCfg.Bssid[i]) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(bcn_ie_list->Bssid))); + AsicDisableSync(pAd); + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, bcn_ie_list->Bssid); + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ + is_my_bssid = TRUE; + break; + } + else if (bcn_ie_list->Bssid[i] < pAd->CommonCfg.Bssid[i]) + break; + } + } + + + NdisGetSystemUpTime(&Now); + pBss = &pAd->ScanTab.BssEntry[Bssidx]; + pBss->Rssi = RealRssi; /* lastest RSSI */ + pBss->LastBeaconRxTime = Now; /* last RX timestamp */ + + /* + BEACON from my BSSID - either IBSS or INFRA network + */ + if (is_my_bssid) + { + RXWI_STRUC RxWI; + UINT8 RXWISize = pAd->chipCap.RXWISize; + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + OVERLAP_BSS_SCAN_IE BssScan; + UCHAR RegClass; + BOOLEAN brc; + + /* Read Beacon's Reg Class IE if any. */ + brc = PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &BssScan, &RegClass); + if (brc == TRUE) + { + UpdateBssScanParm(pAd, BssScan); + pAd->StaCfg.RegClass = RegClass; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + pAd->StaCfg.DtimCount = bcn_ie_list->DtimCount; + pAd->StaCfg.DtimPeriod = bcn_ie_list->DtimPeriod; + pAd->StaCfg.LastBeaconRxTime = Now; + + NdisZeroMemory(&RxWI, RXWISize); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + { + RxWI.RXWI_N.rssi[0]= Elem->Rssi0; + RxWI.RXWI_N.rssi[1] = Elem->Rssi1; + RxWI.RXWI_N.rssi[2] = Elem->Rssi2; + RxWI.RXWI_N.phy_mode = 0; /* Prevent SNR calculate error. */ + } + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + RxWI.RXWI_O.RSSI0= Elem->Rssi0; + RxWI.RXWI_O.RSSI1 = Elem->Rssi1; + RxWI.RXWI_O.RSSI2 = Elem->Rssi2; + RxWI.RXWI_O.phy_mode = 0; /* Prevent SNR calculate error. */ + } +#endif /* RTMP_MAC */ + if (INFRA_ON(pAd)) { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + if (pEntry) + { + Update_Rssi_Sample(pAd, &pEntry->RssiSample, &RxWI); +#ifdef RT_CFG80211_P2P_SINGLE_DEVICE + if (CFG_P2PCLI_ON(pAd)) + { + CFG80211_PeerP2pBeacon(pAd, bcn_ie_list->Addr2, Elem, bcn_ie_list->TimeStamp); + } +#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */ + } + } + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); + + if ((pAd->CommonCfg.bIEEE80211H == 1) && + (bcn_ie_list->NewChannel != 0) && + (bcn_ie_list->Channel != bcn_ie_list->NewChannel)) + { + /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */ + /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */ + AsicSwitchChannel(pAd, 1, FALSE); + AsicLockChannel(pAd, 1); + LinkDown(pAd, FALSE); + MlmeQueueInit(pAd, &pAd->Mlme.Queue); + BssTableInit(&pAd->ScanTab); + RtmpusecDelay(1000000); /* use delay to prevent STA do reassoc */ + + /* channel sanity check */ + for (index = 0 ; index < pAd->ChannelListNum; index++) + { + if (pAd->ChannelList[index].Channel == bcn_ie_list->NewChannel) + { + pAd->ScanTab.BssEntry[Bssidx].Channel = bcn_ie_list->NewChannel; + pAd->CommonCfg.Channel = bcn_ie_list->NewChannel; +#ifdef RT_CFG80211_SUPPORT + //CFG_TODO +#else + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); +#endif /* RT_CFG80211_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", bcn_ie_list->NewChannel)); + break; + } + } + + if (index >= pAd->ChannelListNum) + { + DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); + } + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) + ; + else +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WSC_STA_SUPPORT + if (pAd->StaCfg.WscControl.WscState == WSC_STATE_OFF) +#endif /* WSC_STA_SUPPORT */ + { + if ((((wdev->WepStatus != Ndis802_11WEPDisabled) << 4) ^ bcn_ie_list->CapabilityInfo) & 0x0010) + { + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + /* When using -Dwext and trigger WPS, do not check security. */ + if ( SelReg == 0 ) +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + { + /* + To prevent STA connect to OPEN/WEP AP when STA is OPEN/NONE or + STA connect to OPEN/NONE AP when STA is OPEN/WEP AP. + */ + DBGPRINT(RT_DEBUG_TRACE, ("%s:AP privacy:%x is differenct from STA privacy:%x\n", + __FUNCTION__, (bcn_ie_list->CapabilityInfo & 0x0010) >> 4 , + wdev->WepStatus != Ndis802_11WEPDisabled)); + if (INFRA_ON(pAd)) + { + LinkDown(pAd,FALSE); + BssTableInit(&pAd->ScanTab); + } + goto LabelOK; + } + } + } + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT +/* CFG80211_BeaconCountryRegionParse(pAd, pVIE, LenVIE); */ +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + + if (bcn_ie_list->AironetCellPowerLimit != 0xFF) + { + /* + We get the Cisco (ccx) "TxPower Limit" required + Changed to appropriate TxPower Limit for Ciso Compatible Extensions + */ + ChangeToCellPowerLimit(pAd, bcn_ie_list->AironetCellPowerLimit); + } + else + { + /* + AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. + Used the default TX Power Percentage, that set from UI. + */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + } + + if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(bcn_ie_list->CapabilityInfo))) + { + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + MAC_TABLE_ENTRY *pEntry; +#ifdef IWSC_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* IWSC_SUPPORT */ + + MaxSupportedRateIn500Kbps = dot11_max_sup_rate(bcn_ie_list->SupRateLen, &bcn_ie_list->SupRate[0], + bcn_ie_list->ExtRateLen, &bcn_ie_list->ExtRate[0]); + + /* look up the existing table */ + pEntry = MacTableLookup(pAd, bcn_ie_list->Addr2); + + /* + Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. + To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. + */ + if ((ADHOC_ON(pAd) && ((!pEntry) || (pEntry && IS_ENTRY_NONE(pEntry)))) || + (pEntry && RTMP_TIME_AFTER(Now, pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME))) + { + /* Another adhoc joining, add to our MAC table. */ + if (pEntry == NULL) + pEntry = MacTableInsertEntry(pAd, bcn_ie_list->Addr2, wdev, BSS0, OPMODE_STA, FALSE); + + if (pEntry == NULL) + goto LabelOK; + +#ifdef IWSC_SUPPORT + hex_dump("Another adhoc joining - Addr2", bcn_ie_list->Addr2, 6); + hex_dump("Another adhoc joining - WscPeerMAC", pAd->StaCfg.WscControl.WscPeerMAC, 6); + if ((NdisEqualMemory(bcn_ie_list->Addr2, pAd->StaCfg.WscControl.WscPeerMAC, MAC_ADDR_LEN)) && + (pAd->StaCfg.IWscInfo.bSendEapolStart == FALSE) && + (pWpsCtrl->bWscTrigger == TRUE)) + { + pAd->StaCfg.IWscInfo.bSendEapolStart = TRUE; + } +#endif /* IWSC_SUPPORT */ + +#ifdef DOT11_VHT_AC +{ + BOOLEAN result; + IE_LISTS *ielist; + + os_alloc_mem(NULL, (UCHAR **)&ielist, sizeof(IE_LISTS)); + if (!ielist) + goto LabelOK; + NdisZeroMemory((UCHAR *)ielist, sizeof(IE_LISTS)); + + if (bcn_ie_list->vht_cap_len && bcn_ie_list->vht_op_len) + { + NdisMoveMemory(&ielist->vht_cap, &bcn_ie_list->vht_cap_ie, sizeof(VHT_CAP_IE)); + NdisMoveMemory(&ielist->vht_op, &bcn_ie_list->vht_op_ie, sizeof(VHT_OP_IE)); + ielist->vht_cap_len = bcn_ie_list->vht_cap_len; + ielist->vht_op_len = bcn_ie_list->vht_op_len; + } + result = StaUpdateMacTableEntry(pAd, + pEntry, + MaxSupportedRateIn500Kbps, + &bcn_ie_list->HtCapability, + bcn_ie_list->HtCapabilityLen, + &bcn_ie_list->AddHtInfo, + bcn_ie_list->AddHtInfoLen, + ielist, + bcn_ie_list->CapabilityInfo); + + os_free_mem(NULL, ielist); + if ( result== FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); + goto LabelOK; + } +#ifdef IWSC_SUPPORT + else + pEntry->bUpdateInfoFromPeerBeacon = TRUE; +#endif /* IWSC_SUPPORT */ +} +#else + if (StaUpdateMacTableEntry(pAd, + pEntry, + MaxSupportedRateIn500Kbps, + &bcn_ie_list->HtCapability, + bcn_ie_list->HtCapabilityLen, + &bcn_ie_list->AddHtInfo, + bcn_ie_list->AddHtInfoLen, + NULL, + bcn_ie_list->CapabilityInfo) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); + goto LabelOK; + } +#ifdef IWSC_SUPPORT + else + pEntry->bUpdateInfoFromPeerBeacon = TRUE; +#endif /* IWSC_SUPPORT */ +#endif /* DOT11_VHT_AC */ + + if (ADHOC_ON(pAd) && pEntry) + { + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pEntry, + bcn_ie_list->SupRate, + bcn_ie_list->SupRateLen, + bcn_ie_list->ExtRate, + bcn_ie_list->ExtRateLen, +#ifdef DOT11_VHT_AC + bcn_ie_list->vht_cap_len, + &bcn_ie_list->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &bcn_ie_list->HtCapability, + bcn_ie_list->HtCapabilityLen); + } + + pEntry->LastBeaconRxTime = 0; + +#ifdef ADHOC_WPA2PSK_SUPPORT + /* Adhoc support WPA2PSK by Eddy */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pEntry->WPA_Authenticator.WpaState < AS_INITPSK) +#ifdef IWSC_SUPPORT + && ((pAd->StaCfg.WscControl.WscConfMode == WSC_DISABLE) || + (pAd->StaCfg.WscControl.bWscTrigger == FALSE) || + (NdisEqualMemory(pEntry->Addr, pAd->StaCfg.WscControl.WscPeerMAC, MAC_ADDR_LEN) == FALSE)) +#ifdef IWSC_TEST_SUPPORT + && (pAd->StaCfg.IWscInfo.bBlockConnection == FALSE) +#endif /* IWSC_TEST_SUPPORT */ +#endif // IWSC_SUPPORT // + ) + { + INT len, i; + PEID_STRUCT pEid; + NDIS_802_11_VARIABLE_IEs *pVIE2 = NULL; + BOOLEAN bHigherMAC = FALSE; + + pVIE2 = pVIE; + len = LenVIE; + while (len > 0) + { + pEid = (PEID_STRUCT) pVIE; + if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) + { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + } + pVIE2 += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisZeroMemory(&pEntry->WPA_Supplicant.ReplayCounter, LEN_KEY_DESC_REPLAY); + NdisZeroMemory(&pEntry->WPA_Authenticator.ReplayCounter, LEN_KEY_DESC_REPLAY); + pEntry->WPA_Authenticator.WpaState = AS_INITPSK; + pEntry->WPA_Supplicant.WpaState = AS_INITPSK; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + + for (i = 0; i < 6; i++) + { + if (bcn_ie_list->Addr2[i] > pAd->CurrentAddress[i]) + { + bHigherMAC = TRUE; + break; + } + else if (bcn_ie_list->Addr2[i] < pAd->CurrentAddress[i]) + break; + } + hex_dump("PeerBeacon:: Addr2", bcn_ie_list->Addr2, MAC_ADDR_LEN); + hex_dump("PeerBeacon:: CurrentAddress", pAd->CurrentAddress, MAC_ADDR_LEN); + pEntry->bPeerHigherMAC = bHigherMAC; + if (pEntry->bPeerHigherMAC == FALSE) + { + /* + My MAC address is higher than peer's MAC address. + */ + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - EnqueueStartForPSKTimer.\n")); + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + } + else + { + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + if (pEntry && (Elem->Wcid == RESERVED_WCID)) + { + idx = wdev->DefaultKeyId; + RTMP_SET_WCID_SEC_INFO(pAd, BSS0, idx, + pAd->SharedKey[BSS0][idx].CipherAlg, + pEntry->wcid, + SHAREDKEYTABLE); + } + } + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + pEntry->LastBeaconRxTime = Now; +#ifdef IWSC_SUPPORT + if (pEntry->bUpdateInfoFromPeerBeacon == FALSE) + { + if (StaUpdateMacTableEntry(pAd, + pEntry, + MaxSupportedRateIn500Kbps, + &bcn_ie_list->HtCapability, + bcn_ie_list->HtCapabilityLen, + &bcn_ie_list->AddHtInfo, + bcn_ie_list->AddHtInfoLen, + NULL, + bcn_ie_list->CapabilityInfo) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC 2 - Add Entry failed.\n")); + return; + } + + if (ADHOC_ON(pAd) && pEntry) + { + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pEntry, + bcn_ie_list->SupRate, + bcn_ie_list->SupRateLen, + bcn_ie_list->ExtRate, + bcn_ie_list->ExtRateLen, +#ifdef DOT11_VHT_AC + bcn_ie_list->vht_cap_len, + &bcn_ie_list->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &bcn_ie_list->HtCapability, + bcn_ie_list->HtCapabilityLen); + } + + pEntry->bUpdateInfoFromPeerBeacon = TRUE; + } +#endif /* IWSC_SUPPORT */ + } + + /* At least another peer in this IBSS, declare MediaState as CONNECTED */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + pAd->ExtraInfo = GENERAL_LINK_UP; + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); + } +#ifdef IWSC_SUPPORT + if (pAd->StaCfg.IWscInfo.bSendEapolStart && + (pAd->Mlme.IWscMachine.CurrState != IWSC_WAIT_PIN) && + (pAd->StaCfg.WscControl.WscConfMode == WSC_ENROLLEE)) + { + pAd->StaCfg.IWscInfo.bSendEapolStart = FALSE; + pWpsCtrl->WscState = WSC_STATE_LINK_UP; + pWpsCtrl->WscStatus = STATUS_WSC_LINK_UP; + NdisMoveMemory(pWpsCtrl->EntryAddr, pWpsCtrl->WscPeerMAC, MAC_ADDR_LEN); + WscSendEapolStart(pAd, pWpsCtrl->WscPeerMAC, STA_MODE); + } +#endif // IWSC_SUPPORT + } + + if (INFRA_ON(pAd)) + { + BOOLEAN bUseShortSlot, bUseBGProtection; + + /* + decide to use/change to - + 1. long slot (20 us) or short slot (9 us) time + 2. turn on/off RTS/CTS and/or CTS-to-self protection + 3. short preamble + */ + + + /* bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); */ + bUseShortSlot = CAP_IS_SHORT_SLOT(bcn_ie_list->CapabilityInfo); + if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) + AsicSetSlotTime(pAd, bUseShortSlot); + + bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || /* always use */ + ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(bcn_ie_list->Erp)); + + if (pAd->CommonCfg.Channel > 14) /* always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP */ + bUseBGProtection = FALSE; + + if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + if (bUseBGProtection) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, + (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT), + FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, + (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE, + (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + } + + DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); + } + +#ifdef DOT11_N_SUPPORT + /* check Ht protection mode. and adhere to the Non-GF device indication by AP. */ + if ((bcn_ie_list->AddHtInfoLen != 0) && + ((bcn_ie_list->AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || + (bcn_ie_list->AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) + { + pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = bcn_ie_list->AddHtInfo.AddHtInfo2.NonGfPresent; + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = bcn_ie_list->AddHtInfo.AddHtInfo2.OperaionMode; + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, + ALLN_SETPROTECT, FALSE, TRUE); + } + else + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, + ALLN_SETPROTECT, FALSE, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); + } +#endif /* DOT11_N_SUPPORT */ + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && + ERP_IS_USE_BARKER_PREAMBLE(bcn_ie_list->Erp)) + { + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); + } + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && + (bcn_ie_list->EdcaParm.bValid == TRUE) && + (bcn_ie_list->EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", + pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, + bcn_ie_list->EdcaParm.EdcaUpdateCount)); + AsicSetEdcaParm(pAd, &bcn_ie_list->EdcaParm); + } + + /* copy QOS related information */ + NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &bcn_ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &bcn_ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* + 2009: PF#1: 20/40 Coexistence in 2.4 GHz Band + When AP changes "STA Channel Width" and "Secondary Channel Offset" fields of HT Operation Element in the Beacon to 0 + */ + if ((bcn_ie_list->AddHtInfoLen != 0) && INFRA_ON(pAd) && pAd->CommonCfg.Channel <= 14) + { + BOOLEAN bChangeBW = FALSE; + + /* + 1) HT Information + 2) Secondary Channel Offset Element + + 40 -> 20 case + */ + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (((bcn_ie_list->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_NONE) && + (bcn_ie_list->AddHtInfo.AddHtInfo.RecomWidth == 0)) + ||(bcn_ie_list->NewExtChannelOffset==0x0) + ) + { + pAd->StaActive.SupportedHtPhy.ChannelWidth = BW_20; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW = 0; + + { + bChangeBW = TRUE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + DBGPRINT(RT_DEBUG_TRACE, ("FallBack from 40MHz to 20MHz(CtrlCh=%d, CentralCh=%d)\n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + CntlChannelWidth(pAd, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel, BW_20, 0); + } + } + } + + /* + 20 -> 40 case + 1.) Supported Channel Width Set Field of the HT Capabilities element of both STAs is set to a non-zero + 2.) Secondary Channel Offset field is SCA or SCB + 3.) 40MHzRegulatoryClass is TRUE (not implement it) + */ + else if (((pAd->CommonCfg.BBPCurrentBW == BW_20) ||(bcn_ie_list->NewExtChannelOffset!=0x0)) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth != BW_20) + ) + { + if ((bcn_ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) && + (bcn_ie_list->AddHtInfo.AddHtInfo.RecomWidth == 1) && + (bcn_ie_list->HtCapabilityLen>0) && (bcn_ie_list->HtCapability.HtCapInfo.ChannelWidth == 1) + ) + { + { + pAd->CommonCfg.CentralChannel = get_cent_ch_by_htinfo(pAd, + &bcn_ie_list->AddHtInfo, + &bcn_ie_list->HtCapability); + if (pAd->CommonCfg.CentralChannel != bcn_ie_list->AddHtInfo.ControlChan) + bChangeBW = TRUE; + + if (bChangeBW) + { + pAd->CommonCfg.Channel = bcn_ie_list->AddHtInfo.ControlChan; + pAd->StaActive.SupportedHtPhy.ChannelWidth = BW_40; + DBGPRINT(RT_DEBUG_TRACE, ("FallBack from 20MHz to 40MHz(CtrlCh=%d, CentralCh=%d)\n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + CntlChannelWidth(pAd, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel, BW_40, bcn_ie_list->AddHtInfo.AddHtInfo.ExtChanOffset); + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW = 1; + } + } + } + } + + if (bChangeBW) + { + pAd->CommonCfg.BSSCoexist2040.word = 0; + TriEventInit(pAd); + BuildEffectedChannelList(pAd); + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + } + + /* only INFRASTRUCTURE mode support power-saving feature */ + if ((INFRA_ON(pAd) && (RtmpPktPmBitCheck(pAd) == TRUE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) + { + UCHAR FreeNumber; + /* + 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL + 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE + 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE + 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE + 5. otherwise, put PHY back to sleep to save battery. + */ + if (bcn_ie_list->MessageToMe) + { +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + /* Restore to correct BBP R3 value */ + if (pAd->Antenna.field.RxPath > 1) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + /* Turn clk to 80Mhz. */ + } +#endif /* PCIE_PS_SUPPORT */ +#ifdef UAPSD_SUPPORT + if (pAd->StaCfg.UapsdInfo.bAPSDCapable && + pAd->CommonCfg.APEdcaParm.bAPSDCapable && + pAd->CommonCfg.bAPSDAC_BE && + pAd->CommonCfg.bAPSDAC_BK && + pAd->CommonCfg.bAPSDAC_VI && + pAd->CommonCfg.bAPSDAC_VO) + { + pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + TRUE, + pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + } + else +#endif /* UAPSD_SUPPORT */ + { + if (pAd->StaCfg.WindowsBatteryPowerMode == Ndis802_11PowerModeFast_PSP) + { + /* wake up and send a NULL frame with PM = 0 to the AP */ + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), + PWR_ACTIVE); + } + else + { + /* use PS-Poll to get any buffered packet */ + RTMP_PS_POLL_ENQUEUE(pAd); + } + } + } + else if (bcn_ie_list->BcastFlag && (bcn_ie_list->DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) + { +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + if (pAd->Antenna.field.RxPath > 1) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } +#endif /* PCIE_PS_SUPPORT */ + } + else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || + (pAd->TxSwQueue[QID_AC_BE].Number != 0) || + (pAd->TxSwQueue[QID_AC_VI].Number != 0) || + (pAd->TxSwQueue[QID_AC_VO].Number != 0) || + (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) + { + /* TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme */ + /* can we cheat here (i.e. just check MGMT & AC_BE) for better performance? */ +#ifdef PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + if (pAd->Antenna.field.RxPath > 1) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } +#endif /* PCIE_PS_SUPPORT */ + } + else + { + if ((pAd->CommonCfg.bACMAPSDTr[QID_AC_VO]) || + (pAd->CommonCfg.bACMAPSDTr[QID_AC_VI]) || + (pAd->CommonCfg.bACMAPSDTr[QID_AC_BK]) || + (pAd->CommonCfg.bACMAPSDTr[QID_AC_BE]) +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + || (pAd->StaCfg.FlgPsmCanNotSleep == TRUE) + || (RtmpPktPmBitCheck(pAd) == FALSE) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + ) + { + } + else + { + USHORT NextDtim = bcn_ie_list->DtimCount; + + if (NextDtim == 0) + NextDtim = bcn_ie_list->DtimPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + /* Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. */ + pAd->StaCfg.ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp; + AsicSleepThenAutoWakeup(pAd, pAd->StaCfg.ThisTbttNumToNextWakeUp); + } + } + } + } + + } + /* not my BSSID, ignore it */ + } + + /* sanity check fail, ignore this frame */ + goto LabelOK; + +LabelErr: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + +LabelOK: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (bcn_ie_list != NULL) + os_free_mem(NULL, bcn_ie_list); + + return; +} + +/* + ========================================================================== + Description: + Receive PROBE REQ from remote peer when operating in IBSS mode + ========================================================================== + */ +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PEER_PROBE_REQ_PARAM ProbeReqParam; +#ifdef DOT11_N_SUPPORT + UCHAR HtLen, AddHtLen, NewExtLen; +#endif /* DOT11_N_SUPPORT */ + HEADER_802_11 ProbeRspHdr; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1, IbssLen = 2; + UCHAR LocalErpIe[3] = {IE_ERP, 1, 0}; + BOOLEAN Privacy; + USHORT CapabilityInfo; + + + if (! ADHOC_ON(pAd)) + return; + + if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &ProbeReqParam)) + { + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + + if ((ProbeReqParam.SsidLen == 0) || + SSID_EQUAL(ProbeReqParam.Ssid, ProbeReqParam.SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + { + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, + 0, ProbeReqParam.Addr2, + pAd->CurrentAddress, + pAd->CommonCfg.Bssid); + + Privacy = (wdev->WepStatus == Ndis802_11WEPEnabled) || + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable); + CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, + 2, &pAd->StaActive.AtimWin, + END_OF_ARGS); + + if (pAd->StaActive.ExtRateLen) + { + ULONG tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &pAd->StaActive.ExtRateLen, + pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + /* Modify by Eddy, support WPA2PSK in Adhoc mode */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPANone) +#ifdef ADHOC_WPA2PSK_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#endif /* ADHOC_WPA2PSK_SUPPORT */ + ) + { + ULONG tmp; + UCHAR RSNIe = IE_WPA; + +#ifdef ADHOC_WPA2PSK_SUPPORT + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, BSS0); + if (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) + RSNIe = IE_RSN; +#endif /* ADHOC_WPA2PSK_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG TmpLen; + USHORT epigram_ie_len; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + NewExtLen = 1; + /* New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ + if (pAd->bBroadComHT == TRUE) + { + epigram_ie_len = pAd->MlmeAux.HtCapabilityLen + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &AddHtLen, + sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); + } + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef WSC_STA_SUPPORT + /* add Simple Config Information Element */ + if (pAd->StaCfg.WpsIEProbeResp.ValueLen != 0) + { + ULONG WscTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + pAd->StaCfg.WpsIEProbeResp.ValueLen, pAd->StaCfg.WpsIEProbeResp.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } +#endif /* WSC_STA_SUPPORT */ + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} + +VOID BeaconTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status, 0); +} + +/* + ========================================================================== + Description: + Scan timeout procedure. basically add channel index by 1 and rescan + ========================================================================== + */ +VOID ScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + + if (pAd->StaCfg.bFastConnect && !pAd->StaCfg.bNotFirstScan) + { + pAd->MlmeAux.Channel = 0; + pAd->StaCfg.bNotFirstScan = TRUE; + } + else + { + pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); + } + + /* Only one channel scanned for CISCO beacon request */ + if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) + pAd->MlmeAux.Channel = 0; + + /* this routine will stop if pAd->MlmeAux.Channel == 0 */ + ScanNextChannel(pAd, OPMODE_STA, pAd->MlmeAux.ScanInfType); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + + if (Elem->MsgType != MT2_MLME_SCAN_REQ) + DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + else + DBGPRINT(RT_DEBUG_TRACE, ("AYNC - Already in scanning, do nothing here.(state=%ld). \n", pAd->Mlme.SyncMachine.CurrState)); + + if (Elem->MsgType != MT2_MLME_SCAN_REQ) + { + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); + } +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld, msg=%ld). Reset SYNC machine\n", + pAd->Mlme.SyncMachine.CurrState, + Elem->MsgType)); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + RTMPResumeMsduTransmission(pAd); + } + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status, 0); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenStart( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status, 0); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID EnqueuePsPoll(RTMP_ADAPTER *pAd) +{ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + + if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) + pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; + MiniportMMRequest(pAd, QID_AC_BE, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + + /* Keep Waking up */ + if (pAd->CountDowntoPsm <= 0) + pAd->CountDowntoPsm = 2; /* 100 ms; stay awake 200ms at most, average will be 1xx ms */ +} + + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID EnqueueProbeRequest(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS NState; + PUCHAR pOutBuffer; + ULONG FrameLen = 0; + HEADER_802_11 Hdr80211; + + DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); + + NState = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NState == NDIS_STATUS_SUCCESS) + { + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->CurrentAddress, + BROADCAST_ADDR); + + /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + +} + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + +/* + ======================================================================== + + Routine Description: + Control Primary&Central Channel, ChannelWidth and Second Channel Offset + + Arguments: + pAd Pointer to our adapter + PrimaryChannel Primary Channel + CentralChannel Central Channel + ChannelWidth BW_20 or BW_40 + SecondaryChannelOffset EXTCHA_NONE, EXTCHA_ABOVE and EXTCHA_BELOW + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID CntlChannelWidth( + IN PRTMP_ADAPTER pAd, + IN UCHAR prim_ch, + IN UCHAR cent_ch, + IN UCHAR ch_bw, + IN UCHAR sec_ch_offset) +{ + UCHAR rf_channel = 0; + UINT8 rf_bw, ext_ch; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: PrimaryChannel[%d] \n",__FUNCTION__,prim_ch)); + DBGPRINT(RT_DEBUG_TRACE, ("%s: CentralChannel[%d] \n",__FUNCTION__,cent_ch)); + DBGPRINT(RT_DEBUG_TRACE, ("%s: ChannelWidth[%d] \n",__FUNCTION__,ch_bw)); + DBGPRINT(RT_DEBUG_TRACE, ("%s: SecondaryChannelOffset[%d] \n",__FUNCTION__,sec_ch_offset)); + +#ifdef DOT11_N_SUPPORT + /*Change to AP channel */ + if (ch_bw == BW_40) + { + if(sec_ch_offset == EXTCHA_ABOVE) + { + rf_bw = BW_40; + ext_ch = EXTCHA_ABOVE; + rf_channel = cent_ch; + } + else if (sec_ch_offset == EXTCHA_BELOW) + { + rf_bw = BW_40; + ext_ch = EXTCHA_BELOW; + rf_channel = cent_ch; + } + } + else +#endif /* DOT11_N_SUPPORT */ + { + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + rf_channel = prim_ch; + } + + if (rf_channel != 0) { + bbp_set_bw(pAd, rf_bw); + + /* Tx/ RX : control channel setting */ + bbp_set_ctrlch(pAd, ext_ch); + rtmp_mac_set_ctrlch(pAd, ext_ch); + + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); + +#ifdef RT28xx + RT28xx_ch_tunning(pAd, rf_bw); +#endif /* RT28xx */ + + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + + bbp_get_agc(pAd, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + } +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +/* + ========================================================================== + Description: + MLME Cancel the SCAN req state machine procedure + ========================================================================== + */ +VOID ScanCnclAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA, INT_MAIN); + + return; +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls.c new file mode 100644 index 000000000..3a7c5a37e --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls.c @@ -0,0 +1,5121 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + + #ifdef DOT11Z_TDLS_SUPPORT +#include +#include "rt_config.h" +#include "dot11z_tdls.h" + +UCHAR TDLS_LLC_SNAP_WITH_CATEGORY[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x89, 0x0d, PROTO_NAME_TDLS, CATEGORY_TDLS}; +#ifdef WFD_SUPPORT +UCHAR TDLS_LLC_SNAP_WITH_WFD_CATEGORY[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x89, 0x0d, PROTO_NAME_TDLS, CATEGORY_VENDOR_SPECIFIC_WFD}; +extern UCHAR WIFIDISPLAY_OUI[]; +#endif /* WFD_SUPPORT */ +UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; +extern UCHAR WPS_OUI[]; +extern UCHAR P2POUIBYTE[]; + + +typedef struct +{ + UCHAR regclass; // regulatory class + UCHAR spacing; // 0: 20Mhz, 1: 40Mhz + UCHAR channelset[16]; // max 15 channels, use 0 as terminator +} TDLS_REG_CLASS; + +TDLS_REG_CLASS tdls_reg_class[] = +{ + { 1, 0, {36, 40, 44, 48, 0}}, + { 2, 0, {52, 56, 60, 64, 0}}, + { 3, 0, {149, 153, 157, 161, 0}}, + { 4, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}}, + { 5, 0, {165, 0}}, + { 12, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0}}, + { 22, 1, {36, 44, 0}}, + { 23, 1, {52, 60, 0}}, + { 24, 1, {100, 108, 116, 124, 132, 0}}, + { 25, 1, {149, 157, 0}}, + { 26, 1, {149, 157, 0}}, + { 27, 1, {40, 48, 0}}, + { 28, 1, {56, 64, 0}}, + { 29, 1, {104, 112, 120, 128, 136, 0}}, + { 30, 1, {153, 161, 0}}, + { 31, 1, {153, 161, 0}}, + { 32, 1, {1, 2, 3, 4, 5, 6, 7, 0}}, + { 33, 1, {5, 6, 7, 8, 9, 10, 11, 0}}, + { 0, 0, {0}} // end +}; + +VOID +TDLS_Table_Init( + IN PRTMP_ADAPTER pAd) +{ + UCHAR idx; + PRT_802_11_TDLS pTDLS = NULL; + + /* initialize TDLS allocate spin lock */ + NdisAllocateSpinLock(pAd, &pAd->StaCfg.TdlsInfo.TDLSEntryLock); + NdisAllocateSpinLock(pAd, &pAd->StaCfg.TdlsInfo.TdlsChSwLock); + NdisAllocateSpinLock(pAd, &pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + pTDLS->Status = TDLS_MODE_NONE; +#ifdef WFD_SUPPORT + RTMPZeroMemory(&pTDLS->WfdEntryInfo, sizeof(WFD_ENTRY_INFO)); + pTDLS->WfdEntryInfo.wfd_PC = WFD_PC_TDLS; +#endif /* WFD_SUPPORT */ + } +} + +VOID +TDLS_Table_Destory( + IN PRTMP_ADAPTER pAd) +{ + UCHAR idx; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + +#ifdef UAPSD_SUPPORT + TDLS_UAPSDP_Release(pAd); +#endif /* UAPSD_SUPPORT */ + + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TDLSEntryLock); + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TdlsChSwLock); + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); + + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + pTDLS->Status = TDLS_MODE_NONE; + + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + RTMPCancelTimer(&pTDLS->ChannelSwitchTimer, &TimerCancelled); + RTMPCancelTimer(&pTDLS->ChannelSwitchTimeoutTimer, &TimerCancelled); + } + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + RTMPCancelTimer(&pTdlsControl->TdlsPeriodGoOffChTimer, &TimerCancelled); + RTMPCancelTimer(&pTdlsControl->TdlsPeriodGoBackBaseChTimer, &TimerCancelled); +} + +UCHAR TDLS_GetRegulatoryClass( + IN PRTMP_ADAPTER pAd, + IN UCHAR ChannelWidth, + IN UCHAR TargetChannel) +{ + int i=0; + UCHAR regclass = 0; + + do + { + if (tdls_reg_class[i].spacing == ChannelWidth) + { + int j=0; + + do + { + if (tdls_reg_class[i].channelset[j] == TargetChannel) + { + regclass = tdls_reg_class[i].regclass; + break; + } + j++; + } while (tdls_reg_class[i].channelset[j] != 0); + } + i++; + } while (tdls_reg_class[i].regclass != 0); + + return regclass; +} + +BOOLEAN +TDLS_IsValidChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) + +{ + INT i; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return FALSE; + else + return TRUE; +} + + +UCHAR +TDLS_GetExtCh( + IN UCHAR Channel, + IN UCHAR Direction) +{ + CHAR ExtCh; + + if (Direction == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + return ExtCh; +} + +#ifdef TDLS_AUTOLINK_SUPPORT +VOID +TDLS_ClearEntryList( + IN PLIST_HEADER pTdlsEnList) +{ + PLIST_ENTRY pEntry = NULL; + + pEntry = pTdlsEnList->pHead; + + while (pEntry != NULL) + { + removeHeadList(pTdlsEnList); + os_free_mem(NULL, pEntry); + pEntry = pTdlsEnList->pHead; + } + + return; +} + +PTDLS_DISCOVERY_ENTRY +TDLS_FindDiscoveryEntry( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr) +{ + PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = pTdlsEnList->pHead; + pPeerEntry = (PTDLS_DISCOVERY_ENTRY)pListEntry; + while (pPeerEntry != NULL) + { + if (NdisEqualMemory(pPeerEntry->Responder, pMacAddr, MAC_ADDR_LEN)) + return pPeerEntry; + pListEntry = pListEntry->pNext; + pPeerEntry = (PTDLS_DISCOVERY_ENTRY)pListEntry; + } + + return NULL; +} + +BOOLEAN +TDLS_InsertDiscoveryPeerEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr, + IN BOOLEAN bConnected) +{ + PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL; + + pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsEnList, pMacAddr); + if (pTdlsPeer) + { + NdisGetSystemUpTime(&pTdlsPeer->InitRefTime); + pTdlsPeer->bFirstTime = FALSE; + pTdlsPeer->bConnectedFirstTime = FALSE; + } + else + { + os_alloc_mem(NULL, (PUCHAR *)&pTdlsPeer, sizeof(TDLS_DISCOVERY_ENTRY)); + + if (pTdlsPeer) + { + DBGPRINT(RT_DEBUG_ERROR,("\n!!! Add %02x:%02x:%02x:%02x:%02x:%02x to discovery table !!!\n", + pMacAddr[0], pMacAddr[1], pMacAddr[2], pMacAddr[3], pMacAddr[4], pMacAddr[5])); + + NdisZeroMemory(pTdlsPeer, sizeof(TDLS_DISCOVERY_ENTRY)); + NdisMoveMemory(pTdlsPeer->Responder, pMacAddr, MAC_ADDR_LEN); + NdisGetSystemUpTime(&pTdlsPeer->InitRefTime); + pTdlsPeer->CurrentState = TDLS_DISCOVERY_IDLE; + pTdlsPeer->RetryCount = 0; + pTdlsPeer->bFirstTime = TRUE; + pTdlsPeer->bConnected = bConnected; + insertTailList(pTdlsEnList, (PLIST_ENTRY)pTdlsPeer); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return FALSE; + } + + } + + return TRUE; +} + +VOID TDLS_DelDiscoveryEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr) +{ + PLIST_ENTRY pListEntry = NULL; + PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL; + + pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsEnList, pMacAddr); + pListEntry = (PLIST_ENTRY)pPeerEntry; + + if (pPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR,("\n !!! Delete %02x:%02x:%02x:%02x:%02x:%02x from discovery table !!!\n", + pPeerEntry->Responder[0], + pPeerEntry->Responder[1], + pPeerEntry->Responder[2], + pPeerEntry->Responder[3], + pPeerEntry->Responder[4], + pPeerEntry->Responder[5])); + delEntryList(pTdlsEnList, pListEntry); + os_free_mem(NULL, pPeerEntry); + } +} + +VOID +TDLS_MaintainDiscoveryEntryList( + IN PRTMP_ADAPTER pAd) +{ + ULONG now_time = 0; + PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL, pTempListEntry = NULL; + PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + + NdisGetSystemUpTime(&now_time); + pListEntry = pTdlsDiscoveryEnList->pHead; + pPeerEntry = (PTDLS_DISCOVERY_ENTRY)pListEntry; + + while (pPeerEntry != NULL) + { + if (pPeerEntry->bConnected) + { + if (RTMP_TIME_AFTER(now_time, pPeerEntry->InitRefTime + (pAd->StaCfg.TdlsInfo.TdlsRssiMeasurementPeriod * ((1000 * OS_HZ)/1000)))) + { + BOOLEAN rv; + UCHAR PeerMAC[MAC_ADDR_LEN]; + + NdisMoveMemory(PeerMAC, pPeerEntry->Responder, MAC_ADDR_LEN); + + if (pPeerEntry->RetryCount >= 2) + { + /* tear down */ + if (INFRA_ON(pAd)) + { + MLME_TDLS_REQ_STRUCT MlmeTdlsReq; + USHORT Reason = REASON_UNSPECIFY; + INT idx; + + DBGPRINT(RT_DEBUG_ERROR,("\n !!! Will tear down %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + pPeerEntry->Responder[0], + pPeerEntry->Responder[1], + pPeerEntry->Responder[2], + pPeerEntry->Responder[3], + pPeerEntry->Responder[4], + pPeerEntry->Responder[5])); + + idx = TDLS_SearchLinkId(pAd, pPeerEntry->Responder); + + if (idx == -1 || idx == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - can not find or full the LinkId!\n")); + } + else if (idx >= 0) + { + Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Valid = FALSE; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Status = TDLS_MODE_NONE; + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[idx], Reason, FALSE); + + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TEAR_DOWN, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + + } + } + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + pTempListEntry = pListEntry->pNext; + DBGPRINT(RT_DEBUG_ERROR,("\n !!! peer connect and retrycount > 2 Delete %02x:%02x:%02x:%02x:%02x:%02x from discovery table !!!\n", + pPeerEntry->Responder[0], + pPeerEntry->Responder[1], + pPeerEntry->Responder[2], + pPeerEntry->Responder[3], + pPeerEntry->Responder[4], + pPeerEntry->Responder[5])); + delEntryList(pTdlsDiscoveryEnList, pListEntry); + os_free_mem(NULL, pPeerEntry); + pListEntry = pTempListEntry; + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + } + else + { + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + if (pPeerEntry->bConnectedFirstTime) + { + NdisGetSystemUpTime(&pPeerEntry->InitRefTime); + pPeerEntry->RetryCount = 0; + pPeerEntry->bConnected = TRUE; + rv = TRUE; + } + else + { + rv = TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscoveryEnList, + pPeerEntry->Responder, + TRUE); + } + pPeerEntry->RetryCount++; + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + + if (rv) + { + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_DISCOVER_REQ, + MAC_ADDR_LEN, + pPeerEntry->Responder, + 0); + } + pListEntry = pListEntry->pNext; + } + } + else + { + pListEntry = pListEntry->pNext; + } + } + else + { + if ((RTMP_TIME_AFTER(now_time, pPeerEntry->InitRefTime + TDLS_AUTO_DISCOVERY_INTERVAL)) && + (pPeerEntry->bFirstTime)) + { + BOOLEAN rv; + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + rv = TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscoveryEnList, + pPeerEntry->Responder, + FALSE); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + if (rv) + { + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_DISCOVER_REQ, + MAC_ADDR_LEN, + pPeerEntry->Responder, + 0); + } + + pListEntry = pListEntry->pNext; + } + else + { + if (RTMP_TIME_AFTER(now_time, pPeerEntry->InitRefTime + (5 * ((1000 * OS_HZ)/1000)))) + { + if (pPeerEntry->CurrentState != TDLS_DISCOVERY_TO_SETUP_DONE) + { + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + TDLS_InsertBlackEntryByMAC(pTdlsBlackEnList, pPeerEntry->Responder, TDLS_BLACK_AUTO_DISCOVERY); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + pTempListEntry = pListEntry->pNext; + DBGPRINT(RT_DEBUG_ERROR,("\n !!! peer disconnect and over 5 sec Delete %02x:%02x:%02x:%02x:%02x:%02x from discovery table !!!\n", + pPeerEntry->Responder[0], + pPeerEntry->Responder[1], + pPeerEntry->Responder[2], + pPeerEntry->Responder[3], + pPeerEntry->Responder[4], + pPeerEntry->Responder[5])); + delEntryList(pTdlsDiscoveryEnList, pListEntry); + os_free_mem(NULL, pPeerEntry); + pListEntry = pTempListEntry; + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + } + else + { + pListEntry = pListEntry->pNext; + } + } + else + { + pListEntry = pListEntry->pNext; + } + } + } + pPeerEntry = (PTDLS_DISCOVERY_ENTRY)pListEntry; + } +} + +PTDLS_BLACK_ENTRY +TDLS_FindBlackEntry( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr) +{ + PTDLS_BLACK_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL; + + pListEntry = pTdlsEnList->pHead; + pPeerEntry = (PTDLS_BLACK_ENTRY)pListEntry; + + while (pPeerEntry != NULL) + { + if (NdisEqualMemory(pPeerEntry->MacAddr, pMacAddr, MAC_ADDR_LEN)) + return pPeerEntry; + + pListEntry = pListEntry->pNext; + pPeerEntry = (PTDLS_BLACK_ENTRY)pListEntry; + } + + return NULL; +} + +VOID +TDLS_InsertBlackEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr, + IN UCHAR CurrentState) +{ + PTDLS_BLACK_ENTRY pTdlsBlack = NULL; + + pTdlsBlack = TDLS_FindBlackEntry(pTdlsEnList, pMacAddr); + if (pTdlsBlack) + { + NdisGetSystemUpTime(&pTdlsBlack->InitRefTime); + pTdlsBlack->CurrentState = CurrentState; + } + else + { + os_alloc_mem(NULL, (PUCHAR *)&pTdlsBlack, sizeof(TDLS_BLACK_ENTRY)); + + if (pTdlsBlack) + { + DBGPRINT(RT_DEBUG_ERROR,("\n Add %02x:%02x:%02x:%02x:%02x:%02x to black table!!!\n", + pMacAddr[0], pMacAddr[1], pMacAddr[2], pMacAddr[3], pMacAddr[4], pMacAddr[5])); + NdisZeroMemory(pTdlsBlack, sizeof(TDLS_BLACK_ENTRY)); + NdisMoveMemory(pTdlsBlack->MacAddr, pMacAddr, MAC_ADDR_LEN); + NdisGetSystemUpTime(&pTdlsBlack->InitRefTime); + pTdlsBlack->CurrentState = CurrentState; + insertTailList(pTdlsEnList, (PLIST_ENTRY)pTdlsBlack); + } + ASSERT(pTdlsBlack != NULL); + } +} + +VOID +TDLS_DelBlackEntryByMAC( + IN PLIST_HEADER pTdlsEnList, + IN PUCHAR pMacAddr) +{ + PLIST_ENTRY pListEntry = NULL; + PTDLS_BLACK_ENTRY pBlackEntry = NULL; + + pBlackEntry = TDLS_FindBlackEntry(pTdlsEnList, pMacAddr); + pListEntry = (PLIST_ENTRY)pBlackEntry; + + if (pBlackEntry) + { + DBGPRINT(RT_DEBUG_ERROR,("\n Delete %02x:%02x:%02x:%02x:%02x:%02x from black table!!!\n", + pBlackEntry->MacAddr[0], + pBlackEntry->MacAddr[1], + pBlackEntry->MacAddr[2], + pBlackEntry->MacAddr[3], + pBlackEntry->MacAddr[4], + pBlackEntry->MacAddr[5])); + + delEntryList(pTdlsEnList, pListEntry); + os_free_mem(NULL, pBlackEntry); + } +} + +VOID +TDLS_MaintainBlackList( + IN PRTMP_ADAPTER pAd, + IN PLIST_HEADER pTdlsBlackenList) +{ + PTDLS_BLACK_ENTRY pBlackEntry = NULL; + PLIST_ENTRY pListEntry = NULL, pTempListEntry = NULL; + ULONG now_time = 0; + + NdisGetSystemUpTime(&now_time); + pListEntry = pTdlsBlackenList->pHead; + pBlackEntry = (PTDLS_BLACK_ENTRY)pListEntry; + + while (pBlackEntry != NULL) + { + if (pBlackEntry->CurrentState == TDLS_BLACK_AUTO_DISCOVERY) + { + if (RTMP_TIME_AFTER(now_time, pBlackEntry->InitRefTime + (pAd->StaCfg.TdlsInfo.TdlsAutoDiscoveryPeriod * ((1000 * OS_HZ)/1000)))) + { + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + pTempListEntry = pListEntry->pNext; + DBGPRINT(RT_DEBUG_ERROR,("\n balck auto discovery after %d secs Delete %02x:%02x:%02x:%02x:%02x:%02x from black table !!!\n", + pAd->StaCfg.TdlsInfo.TdlsAutoDiscoveryPeriod, + pBlackEntry->MacAddr[0], + pBlackEntry->MacAddr[1], + pBlackEntry->MacAddr[2], + pBlackEntry->MacAddr[3], + pBlackEntry->MacAddr[4], + pBlackEntry->MacAddr[5])); + delEntryList(pTdlsBlackenList, pListEntry); + os_free_mem(NULL, pBlackEntry); + pListEntry = pTempListEntry; + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + } + else + { + pListEntry = pListEntry->pNext; + } + } + else if (pBlackEntry->CurrentState == TDLS_BLACK_TDLS_BY_TEARDOWN) + { + if (RTMP_TIME_AFTER(now_time, pBlackEntry->InitRefTime + (pAd->StaCfg.TdlsInfo.TdlsDisabledPeriodByTeardown * ((1000 * OS_HZ)/1000)))) + { + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + pTempListEntry = pListEntry->pNext; + DBGPRINT(RT_DEBUG_ERROR,("\n black tdls bt teardown after %d secs Delete %02x:%02x:%02x:%02x:%02x:%02x from black table!!!\n", + pAd->StaCfg.TdlsInfo.TdlsDisabledPeriodByTeardown, + pBlackEntry->MacAddr[0], + pBlackEntry->MacAddr[1], + pBlackEntry->MacAddr[2], + pBlackEntry->MacAddr[3], + pBlackEntry->MacAddr[4], + pBlackEntry->MacAddr[5])); + delEntryList(pTdlsBlackenList, pListEntry); + os_free_mem(NULL, pBlackEntry); + pListEntry = pTempListEntry; + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + } + else + { + pListEntry = pListEntry->pNext; + } + } + else + { + pListEntry = pListEntry->pNext; + } + pBlackEntry = (PTDLS_BLACK_ENTRY)pListEntry; + } +} + +UCHAR +TDLS_ValidIdLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + INT idIdx = MAX_NUM_OF_TDLS_ENTRY; + PRT_802_11_TDLS pTDLS = NULL; + + for (idIdx = 0; idIdx < MAX_NUM_OF_TDLS_ENTRY; idIdx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idIdx]; + + if (pTDLS->Valid && MAC_ADDR_EQUAL(pAddr, pTDLS->MacAddr)) + { + DBGPRINT(RT_DEBUG_INFO, ("TDLS_ValidIdLookup - Find Link ID with Peer Address %02x:%02x:%02x:%02x:%02x:%02x(%d) \n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], idIdx)); + break; + } + } + + if (idIdx == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_INFO, ("!!! TDLS_ValidIdLookup - not found !!!\n")); + return MAX_NUM_OF_TDLS_ENTRY; + } + + return idIdx; +} + +VOID TDLS_AutoSetupByRcvFrame(RTMP_ADAPTER *pAd, HEADER_802_11 *pHeader) +{ + PTDLS_BLACK_ENTRY pTdlsBlackEntry = NULL; + PTDLS_DISCOVERY_ENTRY pTdlsDiscoveryEntry = NULL; + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS ===> TDLS_AutoSetupByRcvFrame\n")); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + pTdlsBlackEntry = TDLS_FindBlackEntry(pTdlsBlackEnList, pHeader->Addr3); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + pTdlsDiscoveryEntry = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, pHeader->Addr3); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + + if ((pTdlsBlackEntry == NULL) && (pTdlsDiscoveryEntry == NULL)) + { + BOOLEAN rv; + UCHAR LinkId = 0xff; + + DBGPRINT(RT_DEBUG_ERROR, ("AutoSetupByRcvFrame trigger discovery request !!!\n")); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + rv = TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscoveryEnList, + pHeader->Addr3, + FALSE); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + LinkId = TDLS_ValidIdLookup(pAd, pHeader->Addr3); + + if (LinkId < MAX_NUM_OF_TDLS_ENTRY) + { + PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL; + + pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, pHeader->Addr3); + if (pTdlsPeer) + { + pTdlsPeer->bConnectedFirstTime = TRUE; + pTdlsPeer->bConnected = TRUE; + pTdlsPeer->RetryCount = 0; + pTdlsPeer->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE; + DBGPRINT(RT_DEBUG_ERROR, ("TDLS peer entry already on table !!!\n")); + } + } + else if (rv) + { + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_DISCOVER_REQ, + MAC_ADDR_LEN, + pHeader->Addr3, + 0); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS <=== TDLS_AutoSetupByRcvFrame\n")); +} +#endif /* TDLS_AUTOLINK_SUPPORT */ + +#ifdef WFD_SUPPORT +/* +========================================================================== + Description: WFD + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_TunneledProbeRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UCHAR Category = 0x7F; + UCHAR OUI[3] = {0x50, 0x6F, 0x9A}; + UCHAR FrameBodyType = 4; /* 4: Request. 5: Response. */ + PUCHAR pWfdIeLen = NULL; + UCHAR WfdIEFixed[6] = {0xdd, 0x0c, 0x50, 0x6f, 0x9a, 0x0a}; + UCHAR WfdIeLen = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS ===> TDLS_TunneledProbeRequest\n")); + + MAKE_802_3_HEADER(Header802_3, pMacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + 1, &Category, + 3, &OUI, + 1, &FrameBodyType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + + pWfdIeLen = pOutBuffer + FrameLen + 1; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, + 6, &WfdIEFixed, + END_OF_ARGS); + + WfdIeLen += TempLen; + FrameLen = FrameLen + TempLen; + + + TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_DEVICE_INFO, NULL, pOutBuffer + FrameLen, ACTION_WIFI_DIRECT); + FrameLen = FrameLen + TempLen; + WfdIeLen += TempLen; + + TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_ASSOCIATED_BSSID, NULL, pOutBuffer + FrameLen, ACTION_WIFI_DIRECT); + FrameLen = FrameLen + TempLen; + WfdIeLen += TempLen; + *pWfdIeLen = (WfdIeLen - 2); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS tunneled request send pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS <=== TDLS_TunneledProbeRequest\n")); + + return NStatus; +} + +/* +========================================================================== + Description: WFD + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_TunneledProbeResponse( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UCHAR Category = 0x7F; + UCHAR OUI[3] = {0x50, 0x6F, 0x9A}; + UCHAR FrameBodyType = 5; /* 4: Request. 5: Response. */ + PUCHAR pWfdIeLen = NULL; + UCHAR WfdIEFixed[6] = {0xdd, 0x0c, 0x50, 0x6f, 0x9a, 0x0a}; + UCHAR WfdIeLen = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS ===> TDLS_TunneledProbeResponse\n")); + + MAKE_802_3_HEADER(Header802_3, pMacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + 1, &Category, + 3, &OUI, + 1, &FrameBodyType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + pWfdIeLen = pOutBuffer + FrameLen + 1; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, + 6, &WfdIEFixed, + END_OF_ARGS); + + WfdIeLen += TempLen; + FrameLen = FrameLen + TempLen; + + TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_DEVICE_INFO, NULL, pOutBuffer + FrameLen, ACTION_WIFI_DIRECT); + FrameLen = FrameLen + TempLen; + WfdIeLen += TempLen; + + TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_ASSOCIATED_BSSID, NULL, pOutBuffer + FrameLen, ACTION_WIFI_DIRECT); + FrameLen = FrameLen + TempLen; + WfdIeLen += TempLen; + + TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_ALTERNATE_MAC_ADDR, NULL, pOutBuffer + FrameLen, ACTION_WIFI_DIRECT); + FrameLen = FrameLen + TempLen; + WfdIeLen += TempLen; + + *pWfdIeLen = (WfdIeLen - 2); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS tunneled request send pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("TDLS <=== TDLS_TunneledProbeResponse\n")); + + return NStatus; +} +#endif /* WFD_SUPPORT */ + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bTdlsCapable; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + bTdlsCapable = simple_strtol(arg, 0, 10); + + if (!bTdlsCapable && pAd->StaCfg.TdlsInfo.bTDLSCapable) + { + /* tear down local dls table entry */ + TDLS_LinkTearDown(pAd, TRUE); + } + + pAd->StaCfg.TdlsInfo.bTDLSCapable = bTdlsCapable; +#ifdef WFD_SUPPORT + if (pAd->StaCfg.TdlsInfo.bTDLSCapable) + pAd->StaCfg.WfdCfg.PC = WFD_PC_TDLS; + else + pAd->StaCfg.WfdCfg.PC = WFD_PC_P2P; +#endif /* WFD_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_TdlsCapableProc::(bTdlsCapable=%d)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.bTDLSCapable)); + + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsSetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + PSTRING value; + INT value_offset; + RT_802_11_TDLS Tdls; + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (value_offset=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &macAddr[value_offset++], 1); + } + + /* TDLS will not be supported when Adhoc mode */ + if (INFRA_ON(pAd)) + { + if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_OFF,("TDLS - Set_TdlsSetup_Proc() AP Prohibited TDLS !!!\n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("\n%02x:%02x:%02x:%02x:%02x:%02x\n", macAddr[0], macAddr[1], macAddr[2], + macAddr[3], macAddr[4], macAddr[5])); + + NdisZeroMemory(&Tdls, sizeof(RT_802_11_TDLS)); + Tdls.TimeOut = 0; + COPY_MAC_ADDR(Tdls.MacAddr, macAddr); + Tdls.Valid = 1; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_TDLS_PARAM, + sizeof(RT_802_11_TDLS), + &Tdls, + 0); + + RTMP_MLME_HANDLER(pAd); + + return TRUE; + } + + return FALSE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + PSTRING value; + INT value_offset; + CHAR idx; + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (value_offset=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &macAddr[value_offset++], 1); + } + + /* TDLS will not be supported when Adhoc mode */ + if (INFRA_ON(pAd)) + { + MLME_TDLS_REQ_STRUCT MlmeTdlsReq; + USHORT Reason = REASON_UNSPECIFY; + + DBGPRINT(RT_DEBUG_TRACE,("\n%02x:%02x:%02x:%02x:%02x:%02x\n", macAddr[0], macAddr[1], macAddr[2], + macAddr[3], macAddr[4], macAddr[5])); + + idx = TDLS_SearchLinkId(pAd, macAddr); + + if (idx == -1 || idx == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - Set_TdlsTearDown_Proc() can not find or full the LinkId!\n")); + return FALSE; + } + + if (idx >= 0) + { + Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Valid = FALSE; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Status = TDLS_MODE_NONE; + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[idx], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TEAR_DOWN, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + + return TRUE; + } + } + + return FALSE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsDiscoveryReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR PeerMacAddr[MAC_ADDR_LEN]; + PSTRING value; + INT value_offset; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (value_offset=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + AtoH(value, &PeerMacAddr[value_offset++], 1); + } + + /* TDLS will not be supported when Adhoc mode */ + if (INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR,("\n Discovery Peer %02x:%02x:%02x:%02x:%02x:%02x\n", + PeerMacAddr[0], PeerMacAddr[1], PeerMacAddr[2], + PeerMacAddr[3], PeerMacAddr[4], PeerMacAddr[5])); + + + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_DISCOVER_REQ, + MAC_ADDR_LEN, + PeerMacAddr, + 0); + + return TRUE; + } + + return FALSE; +} + +#ifdef WFD_SUPPORT +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsTunneledReqProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR PeerMacAddr[MAC_ADDR_LEN]; + PSTRING value; + INT value_offset; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (value_offset=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + AtoH(value, &PeerMacAddr[value_offset++], 1); + } + + /* TDLS will not be supported when Adhoc mode */ + if (INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR,("\n Discovery Peer %02x:%02x:%02x:%02x:%02x:%02x\n", + PeerMacAddr[0], PeerMacAddr[1], PeerMacAddr[2], + PeerMacAddr[3], PeerMacAddr[4], PeerMacAddr[5])); + + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TUNNELED_REQ, + MAC_ADDR_LEN, + PeerMacAddr, + 0); + + return TRUE; + } + + return FALSE; +} +#endif /* WFD_SUPPORT */ + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsAcceptWeakSecurityProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bAcceptWeakSecurity; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + bAcceptWeakSecurity = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.bAcceptWeakSecurity = bAcceptWeakSecurity; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_TdlsAcceptWeakSecurityProc::(bAcceptWeakSecurity=%d)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.bAcceptWeakSecurity)); + + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsTPKLifeTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 keyLifeTime; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + keyLifeTime = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime = keyLifeTime; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsTPKLifeTimeProc::(TdlsKeyLifeTime=%d)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime)); + + return TRUE; +} + +#ifdef TDLS_AUTOLINK_SUPPORT +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsAutoLinkProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bTdlsAutoLink; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + bTdlsAutoLink = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsAutoLink = (bTdlsAutoLink != 0 ? TRUE : FALSE); + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsAutoLinkProc::(TdlsAutoLink=%d)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsAutoLink)); + + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT +Set_TdlsRssiMeasurementPeriodProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT RssiMeasurementPeriod; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + RssiMeasurementPeriod = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsRssiMeasurementPeriod = RssiMeasurementPeriod; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsRssiMeasurementPeriodProc::(RssiMeasurementPeriod = %d secs)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsRssiMeasurementPeriod)); + + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT +Set_TdlsAutoDiscoveryPeriodProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT AutoDiscoveryPeriod; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + AutoDiscoveryPeriod = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsAutoDiscoveryPeriod = AutoDiscoveryPeriod; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsAutoDiscoveryPeriodProc::(AutoDiscoveryPeriod = %d secs)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsAutoDiscoveryPeriod)); + + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT +Set_TdlsAutoSetupRssiThresholdProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR AutoSetupRssiThreshold; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + AutoSetupRssiThreshold = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold = AutoSetupRssiThreshold; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsAutoSetupRssiThresholdProc::(AutoSetupRssiThreshold = %d dbm)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold)); + + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT +Set_TdlsDisabledPeriodByTeardownProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT DisabledPeriodByTeardown; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + DisabledPeriodByTeardown = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsDisabledPeriodByTeardown = DisabledPeriodByTeardown; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsDisabledPeriodByTeardownProc::(DisabledPeriodByTeardown = %d secs)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsDisabledPeriodByTeardown)); + + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT +Set_TdlsAutoTeardownRssiThresholdProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR AutoTeardownRssiThreshold; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + AutoTeardownRssiThreshold = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold = AutoTeardownRssiThreshold; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsAutoTeardownRssiThresholdProc::(AutoTeardownRssiThreshold = %d dbm)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold)); + + return TRUE; +} +#endif /* TDLS_AUTOLINK_SUPPORT */ + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsChannelSwitch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR PeerMAC[6], TargetChannel; + PSTRING token; + STRING sepValue[] = ":", DASH = '-'; + INT i; + +/* + The Set_TdlsChannelSwitchProc inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the channel value. +*/ + + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and channel value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + + if ((token != NULL) && (strlen(token)>1)) + { + TargetChannel = (UCHAR) simple_strtol((token+1), 0, 10); + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&PeerMAC[i]), 1); + } + + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\nChannel Switch Peer %02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + PeerMAC[0], PeerMAC[1], PeerMAC[2], PeerMAC[3], PeerMAC[4], PeerMAC[5], TargetChannel)); + + /* TDLS will not be supported when Adhoc mode */ + if (INFRA_ON(pAd)) + { + INT LinkId; + PRT_802_11_TDLS pTDLS = NULL; + PTDLS_STRUCT pTdlsControl = NULL; + + LinkId = TDLS_SearchLinkId(pAd, PeerMAC); + + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(%d): can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n", + __FUNCTION__,__LINE__, PeerMAC[0], PeerMAC[1], PeerMAC[2], PeerMAC[3], PeerMAC[4], PeerMAC[5])); + return FALSE; + } + + pTdlsControl = &pAd->StaCfg.TdlsInfo; + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + RtmpPrepareHwNullFrame(pAd, + &pAd->MacTab.Content[pTDLS->MacTabMatchWCID], + TRUE, + FALSE, + 0, + OPMODE_STA, + PWR_ACTIVE, + TRUE, + 1); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + + if (pTDLS->Valid && (pTDLS->Status == TDLS_MODE_CONNECTED)) + { + BOOLEAN TimerCancelled; + + RTMPCancelTimer(&pTdlsControl->TdlsPeriodGoOffChTimer, &TimerCancelled); + RTMPCancelTimer(&pTdlsControl->TdlsPeriodGoBackBaseChTimer, &TimerCancelled); + RTMPCancelTimer(&pTDLS->ChannelSwitchTimer, &TimerCancelled); + RTMPCancelTimer(&pTDLS->ChannelSwitchTimeoutTimer, &TimerCancelled); + + if (TargetChannel != pAd->CommonCfg.Channel) + { + RTMP_SEM_LOCK(&pTdlsControl->TdlsChSwLock); + pTdlsControl->bChannelSwitchInitiator = TRUE; + pTDLS->bDoingPeriodChannelSwitch = TRUE; + pTdlsControl->bDoingPeriodChannelSwitch = TRUE; + pTdlsControl->TdlsForcePowerSaveWithAP = FALSE; + pTdlsControl->TdlsGoBackStartTime = 0; + pTdlsControl->TdlsChannelSwitchRetryCount = 10; + pTdlsControl->TdlsDesireChannel = TargetChannel; + COPY_MAC_ADDR(pTdlsControl->TdlsDesireChSwMacAddr, PeerMAC); + RTMP_SEM_UNLOCK(&pTdlsControl->TdlsChSwLock); + + return TRUE; + } + } + } + } + + return FALSE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsChannelSwitchBW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ChannelBW; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + ChannelBW = simple_strtol(arg, 0, 10); + + pAd->StaCfg.TdlsInfo.TdlsDesireChannelBW = ChannelBW; + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsChannelSwitchBW_Proc::(TdlsChannelSwitchBW=%d)\n", + pObj->ioctl_if, pAd->StaCfg.TdlsInfo.TdlsDesireChannelBW)); + + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsChannelSwitchDisable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR idx = 0; + BOOLEAN bChannelSwitchDisable; + PRT_802_11_TDLS pTDLS = NULL; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + bChannelSwitchDisable = simple_strtol(arg, 0, 10); + + if (INFRA_ON(pAd)) + { + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if ((pTDLS->Valid) && (pTDLS->bDoingPeriodChannelSwitch) && + (pTDLS->Status == TDLS_MODE_CONNECTED)) + { + RTMP_SEM_LOCK(&pTdlsControl->TdlsChSwLock); + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->bChannelSwitchInitiator = FALSE; + RTMP_SEM_UNLOCK(&pTdlsControl->TdlsChSwLock); + break; + } + } + + if (idx < MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) Set_TdlsChannelSwitchDisable_Proc\n", pObj->ioctl_if)); + + return TRUE; + } + } + + return FALSE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InitPeerEntryRateCapability( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT *pCapabilityInfo, + IN UCHAR SupportRateLens, + IN UCHAR *pSupportRates, + IN UCHAR HtCapabilityLen, + IN HT_CAPABILITY_IE *pHtCapability) +{ + UCHAR MaxSupportedRate = RATE_11; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + + for (idx = 0; idx < SupportRateLens; idx++) + { + if (MaxSupportedRateIn500Kbps < (pSupportRates[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = pSupportRates[idx] & 0x7f; + } + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxDesiredRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + pEntry->HTCapability.MCSSet[2] = 0; + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; /*k,bitmask; */ + CHAR ii; + + DBGPRINT(RT_DEBUG_TRACE, + ("TDLS - Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + + if ((pHtCapability->HtCapInfo.GF) && + (pAd->CommonCfg.DesiredHtPhy.GF) && + (pAd->StaActive.SupportedHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((pHtCapability->HtCapInfo.ChannelWidth) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + /* find max fixed rate */ + for (ii = 23; ii >= 0; ii--) /* 3*3 */ + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.wdev.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (pHtCapability->MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + + if (ii==0) + break; + } + + if (pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + if (pAd->StaCfg.wdev.DesiredTransmitSetting.field.MCS == 32) + { + /* Fix MCS as HT Duplicated Mode */ + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.wdev.HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.wdev.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pHtCapability->ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else +#endif /* DOT11_N_SUPPORT */ + { + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + DBGPRINT(RT_DEBUG_OFF, ("TDLS - Receive Peer Legacy STA \n")); + } + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if ((pHtCapability->HtCapInfo.ChannelWidth) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && + (pAd->StaActive.SupportedHtPhy.ChannelWidth)) + { + pEntry->HTPhyMode.field.BW= BW_40; + } + else + { + pEntry->HTPhyMode.field.BW= BW_20; + } + + + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + + if (pAd->StaCfg.wdev.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.wdev.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.wdev.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + pEntry->RateLen = SupportRateLens; +} + +/* + ======================================================================== + + Routine Description: + Classify TDLS message type + + Arguments: + TDLSActionType Value of TDLS message type + MsgType Internal Message definition for MLME state machine + + Return Value: + TRUE Found appropriate message type + FALSE No appropriate message type + + ======================================================================== +*/ +BOOLEAN +TDLS_MsgTypeSubst( + IN UCHAR TDLSActionType, + OUT INT *MsgType) +{ + switch (TDLSActionType) + { + case TDLS_ACTION_CODE_SETUP_REQUEST: + *MsgType = MT2_PEER_TDLS_SETUP_REQ; + break; + case TDLS_ACTION_CODE_SETUP_RESPONSE: + *MsgType = MT2_PEER_TDLS_SETUP_RSP; + break; + case TDLS_ACTION_CODE_SETUP_CONFIRM: + *MsgType = MT2_PEER_TDLS_SETUP_CONF; + break; + case TDLS_ACTION_CODE_TEARDOWN: + *MsgType = MT2_PEER_TDLS_TEAR_DOWN; + break; + case TDLS_ACTION_CODE_DISCOVERY_REQUEST: + *MsgType = MT2_PEER_TDLS_DISCOVER_REQ; + break; + case TDLS_ACTION_CODE_PEER_TRAFFIC_INDICATION: /* for TDLS UAPSD */ + *MsgType = MT2_PEER_TDLS_TRAFFIC_IND; + break; + case TDLS_ACTION_CODE_PEER_TRAFFIC_RESPONSE: /* for TDLS UAPSD */ + *MsgType = MT2_PEER_TDLS_TRAFFIC_RSP; + break; + case TDLS_ACTION_CODE_CHANNEL_SWITCH_REQUEST: + *MsgType = MT2_PEER_TDLS_CH_SWITCH_REQ; + break; + case TDLS_ACTION_CODE_CHANNEL_SWITCH_RESPONSE: + *MsgType = MT2_PEER_TDLS_CH_SWITCH_RSP; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("TDLS_MsgTypeSubst : unsupported TDLS Action Type(%d); \n", TDLSActionType)); + return FALSE; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Check whether the received frame is TDLS frame. + + Arguments: + pAd - pointer to our pAdapter context + pData - the received frame + DataByteCount - the received frame's length + + Return: + TRUE - This frame is TDLS frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN TDLS_CheckTDLSframe( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCount) +{ + if(DataByteCount < (LENGTH_802_1_H + LENGTH_TDLS_H)) + return FALSE; + + + /* LLC Header(6) + TDLS Ethernet Type(2) + Protocol(1) + Category(1) */ + if (!NdisEqualMemory(TDLS_LLC_SNAP_WITH_CATEGORY, pData, LENGTH_802_1_H + 2) +#ifdef WFD_SUPPORT + && !NdisEqualMemory(TDLS_LLC_SNAP_WITH_WFD_CATEGORY, pData, LENGTH_802_1_H + 2) +#endif /* WFD_SUPPORT */ + ) + { + //hex_dump("TDLS_CheckTDLSframe Fail", pData, DataByteCount); + return FALSE; + } + else + hex_dump("TDLS_CheckTDLSframe", pData, DataByteCount); + + return TRUE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID TDLS_CntlOidTDLSRequestProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)Elem->Msg; + MLME_TDLS_REQ_STRUCT MlmeTdlsReq; + USHORT Reason = REASON_UNSPECIFY; + BOOLEAN TimerCancelled; + INT Idx, i; + + DBGPRINT(RT_DEBUG_TRACE,("CNTL - TDLS_CntlOidTDLSRequestProc set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d\n", + pTDLS->MacAddr[0], pTDLS->MacAddr[1], pTDLS->MacAddr[2], pTDLS->MacAddr[3], pTDLS->MacAddr[4], pTDLS->MacAddr[5], + pTDLS->Valid, pTDLS->Status)); + + if (!IS_TDLS_SUPPORT(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR,("CNTL - TDLS Capable disable !!!\n")); + return; + } + + if (!INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR,("CNTL - STA do not connect to AP !!!\n")); + return; + } + +#ifdef WFD_SUPPORT + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + (!pAd->StaCfg.TdlsInfo.bAcceptWeakSecurity) && + ((pAd->StaCfg.wdev.AuthMode != Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.wdev.WepStatus != Ndis802_11AESEnable))) + { + pAd->StaCfg.WfdCfg.TdlsSecurity = WFD_TDLS_WEAK_SECURITY; + return; + } + + /* Search P2P table for this MAC address before connecting TDLS */ + Idx = P2pGroupTabSearch(pAd, pTDLS->MacAddr); + if (Idx < MAX_P2P_GROUP_SIZE) + { + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + PWFD_SERV_DISC_QUERY_INFO pInfo = &pAd->P2pTable.Client[Idx].WfdEntryInfo.wfd_serv_disc_query_info; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::find entry in p2p table\n", __FUNCTION__)); + + /* If we can find the entry in the P2P table, check the alternate MAC address in the WFD IE */ + if (!MAC_ADDR_EQUAL(AllZero, pInfo->wfd_alternate_mac_addr_ie) && + !MAC_ADDR_EQUAL(pTDLS->MacAddr, pInfo->wfd_alternate_mac_addr_ie)) + { + /* + * If the alternate MAC address is not all zero and different with MAC address of this entry * + * It mean the interface for TDLS is different with the one of P2P entry * + * Copy the alternate MAC address to the entry for TDLS connection * + */ + COPY_MAC_ADDR(pTDLS->MacAddr, pInfo->wfd_alternate_mac_addr_ie); + DBGPRINT(RT_DEBUG_TRACE, ("WFD alternate mac address is:%02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pTDLS->MacAddr))); + } + } +#endif /* WFD_SUPPORT */ + + Idx = TDLS_SearchLinkId(pAd, pTDLS->MacAddr); + + if (Idx == -1) /* not found and the entry is not full */ + { + if (pTDLS->Valid) + { + /* 1. Enable case, start TDLS setup procedure */ + for (i = 0; i < MAX_NUM_OF_TDLS_ENTRY; i++) + { + if (!pAd->StaCfg.TdlsInfo.TDLSEntry[i].Valid) + { + NdisMoveMemory(&pAd->StaCfg.TdlsInfo.TDLSEntry[i], pTDLS, sizeof(RT_802_11_TDLS_UI)); + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[i], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_SETUP_REQ, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - TDLS setup case\n")); + break; + } + DBGPRINT(RT_DEBUG_ERROR,("CNTL - TDLS do not find vaild entry !!!!\n")); + } + } + else + DBGPRINT(RT_DEBUG_WARN,("CNTL - TDLS not changed in Idx = -1 (Valid=%d)\n", pTDLS->Valid)); + + } + else if (Idx == MAX_NUM_OF_TDLS_ENTRY) /* not found and full */ + { + if (pTDLS->Valid) + { + /* 2. table full, cancel the non-finished entry and restart a new one */ + for (i = 0; i < MAX_NUM_OF_TDLS_ENTRY; i++) + { + if ((pAd->StaCfg.TdlsInfo.TDLSEntry[i].Valid) &&(pAd->StaCfg.TdlsInfo.TDLSEntry[i].Status < TDLS_MODE_CONNECTED)) + { + /* update mac case */ + RTMPCancelTimer(&pAd->StaCfg.TdlsInfo.TDLSEntry[i].Timer, &TimerCancelled); + NdisMoveMemory(&pAd->StaCfg.TdlsInfo.TDLSEntry[i], pTDLS, sizeof(RT_802_11_TDLS_UI)); + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[i], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_SETUP_REQ, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - TDLS restart case\n")); + break; + } + } + } + else + DBGPRINT(RT_DEBUG_WARN,("CNTL - TDLS not changed in Idx = MAX_NUM_OF_TDLS_ENTRY (Valid=%d)\n", pTDLS->Valid)); + } + else /* found one in entry */ + { +#ifdef WFD_SUPPORT + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].WfdEntryInfo.wfd_PC == WFD_PC_P2P) + { + pAd->StaCfg.WfdCfg.PeerPC = WFD_PC_P2P; + + DBGPRINT(RT_DEBUG_TRACE,("CNTL - Peer TDLS PC is P2P\n")); + } + else +#endif /* WFD_SUPPORT */ + if ((!pTDLS->Valid) && (pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Status >= TDLS_MODE_CONNECTED)) + { + /* 3. Disable TDLS link case, just tear down TDLS link */ + Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON; + pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Valid = FALSE; + pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Status = TDLS_MODE_NONE; + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[Idx], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TEAR_DOWN, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - start tear down procedure\n")); + } + else if ((pTDLS->Valid) && (pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Status >= TDLS_MODE_CONNECTED)) + { + /* 4. re-setup case, tear down old link and re-start TDLS setup procedure */ + Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON; + pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Valid = FALSE; + pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Status = TDLS_MODE_NONE; + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[Idx], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TEAR_DOWN, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + + RTMPCancelTimer(&pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Timer, &TimerCancelled); + NdisMoveMemory(&pAd->StaCfg.TdlsInfo.TDLSEntry[Idx], pTDLS, sizeof(RT_802_11_TDLS_UI)); + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[Idx], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_SETUP_REQ, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - TDLS retry setup procedure\n")); + } + else + { +#ifdef WFD_SUPPORT + if (pAd->StaCfg.WfdCfg.bWfdEnable) + { + /* WFD will send TDLS tunneled request and receive reponse frame, + * this will add TDLS entry to TDLS table */ + RTMPCancelTimer(&pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Timer, &TimerCancelled); + NdisMoveMemory(&pAd->StaCfg.TdlsInfo.TDLSEntry[Idx], pTDLS, sizeof(RT_802_11_TDLS_UI)); + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[Idx], Reason, FALSE); + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_SETUP_REQ, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + } +#endif /* WFD_SUPPORT */ + DBGPRINT(RT_DEBUG_WARN,("CNTL - TDLS not changed in entry - %d - Valid=%d, Status=%d\n", + Idx, pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Valid, pAd->StaCfg.TdlsInfo.TDLSEntry[Idx].Status)); + } + } +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ + +/* Not found and full : return MAX_NUM_OF_TDLS_ENTRY + * not found and the entry is not full : return -1 + */ +INT TDLS_SearchLinkId( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + INT i = 0; + UCHAR empty = 0; + PRT_802_11_TDLS pTDLS = NULL; + + for (i = 0; i < MAX_NUM_OF_TDLS_ENTRY; i++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[i]; + if (!pTDLS->Valid) + empty |= 1; + + if (pTDLS->Valid && MAC_ADDR_EQUAL(pAddr, pTDLS->MacAddr)) + { + DBGPRINT(RT_DEBUG_INFO, ("TDLS_SearchLinkId - Find Link ID with Peer Address %02x:%02x:%02x:%02x:%02x:%02x(%d) \n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], i)); + break; + } + } + + if (i == MAX_NUM_OF_TDLS_ENTRY) + { + if (empty == 0) + { + DBGPRINT(RT_DEBUG_INFO, ("TDLS_SearchLinkId - not found and full\n")); + return MAX_NUM_OF_TDLS_ENTRY; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("TDLS_SearchLinkId - not found\n")); + return -1; + } + } + + return i; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID TDLS_MlmeParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_TDLS_REQ_STRUCT *pTdlsReq, + IN PRT_802_11_TDLS pTdls, + IN USHORT Reason, + IN BOOLEAN IsViaAP) +{ + pTdlsReq->pTDLS = pTdls; + pTdlsReq->Reason = Reason; + pTdlsReq->IsViaAP = IsViaAP; +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the TDLS Peer Key and its identifier TPK-Name. + (IEEE 802.11z/D4.0, 8.5.9.1) + + Arguments: + + Return Value: + + Note: + TPK = KDF-256(0, "TDLS PMK", min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || min(SNonce, ANonce) || max(SNonce, ANonce) || BSSID || N_KEY) + TPK-Name = Truncate-128(SHA-256(min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || min(SNonce, ANonce) || max(SNonce, ANonce) || BSSID || 256)) + ======================================================================== +*/ +VOID TDLS_FTDeriveTPK( + IN PUCHAR mac_i, + IN PUCHAR mac_r, + IN PUCHAR a_nonce, + IN PUCHAR s_nonce, + IN PUCHAR bssid, + IN UINT key_len, + OUT PUCHAR tpk, + OUT PUCHAR tpk_name) +{ + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + UCHAR temp_var[32]; + /*UINT key_len = LEN_PMK; */ + //USHORT len_in_bits = (key_len << 3) + 128; + UCHAR TPK_KEY_INPUT[LEN_PMK]; + + /* ================================ */ + /* TPK-Key-Input derivation */ + /* ================================ */ + /* + Refer to IEEE 802.11z-8.5.9.1 + TPK-Key-Input = + SHA-256(min (SNonce, ANonce) || max (SNonce, ANonce)) + */ + + /* Zero the context firstly */ + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate min(SNonce, ANonce) with 32-octets */ + if (RTMPCompareMemory(s_nonce, a_nonce, 32) == 1) + NdisMoveMemory(&context[c_len], a_nonce, 32); + else + NdisMoveMemory(&context[c_len], s_nonce, 32); + c_len += 32; + + /* concatenate max(SNonce, ANonce) with 32-octets */ + if (RTMPCompareMemory(s_nonce, a_nonce, 32) == 1) + NdisMoveMemory(&context[c_len], s_nonce, 32); + else + NdisMoveMemory(&context[c_len], a_nonce, 32); + c_len += 32; + + /* Zero key material */ + NdisZeroMemory(TPK_KEY_INPUT, LEN_PMK); + + RT_SHA256(context, c_len, TPK_KEY_INPUT); + + /* =============================== */ + /* TPK derivation */ + /* =============================== */ + + /* construct the concatenated context for TPK */ + /* min(MAC_I, MAC_R) (6 bytes) */ + /* max(MAC_I, MAC_R) (6 bytes) */ + /* BSSID (6 bytes) */ + /* Number of Key in bits(2 bytes) */ + + /* Initial the related parameter */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + NdisZeroMemory(temp_var, 32); + c_len = 0; + + /* concatenate min(MAC_I, MAC_R) with 6-octets */ + if (RTMPCompareMemory(mac_i, mac_r, 6) == 1) + NdisMoveMemory(temp_var, mac_r, 6); + else + NdisMoveMemory(temp_var, mac_i, 6); + NdisMoveMemory(&context[c_len], temp_var, 6); + c_len += 6; + + /* concatenate max(MAC_I, MAC_R) with 6-octets */ + if (RTMPCompareMemory(mac_i, mac_r, 6) == 1) + NdisMoveMemory(temp_var, mac_i, 6); + else + NdisMoveMemory(temp_var, mac_r, 6); + NdisMoveMemory(&context[c_len], temp_var, 6); + c_len += 6; + + /* concatenate the BSSID with 6-octets */ + NdisMoveMemory(&context[c_len], bssid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the N_KEY with 2-octets */ + //NdisMoveMemory(&context[c_len], &len_in_bits, 2); + //c_len += 2; + + /*hex_dump("TDLS_FTDeriveTPK", context, 128); */ + + /* Calculate a key material through FT-KDF */ + KDF(TPK_KEY_INPUT, + LEN_PMK, + (PUCHAR)"TDLS PMK", + 8, + context, + c_len, + temp_result, + (key_len + 16)); + NdisMoveMemory(tpk, temp_result, (key_len + 16)); + + hex_dump("TPK ", tpk , (key_len + 16)); + + + /* =============================== */ + /* TPK-Name derivation */ + /* =============================== */ + + /* construct the concatenated context for TPK-Name */ + /* min(MAC_I, MAC_R) (6 bytes) */ + /* max(MAC_I, MAC_R) (6 bytes) */ + /* min(SNonce, ANonce) (32 bytes) */ + /* max(SNonce, ANonce) (32 bytes) */ + /* BSSID (6 bytes) */ + /* Number of Key in bits(2 bytes) */ + + /* The context is the same as the contxex of TPK. */ + + /* Initial the related parameter */ + NdisZeroMemory(temp_result, 64); + + /* derive TPK-Name */ + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(tpk_name, temp_result, LEN_PMK_NAME); + + hex_dump("TPK-Name ", tpk_name, LEN_PMK_NAME); + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN MlmeTdlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_TDLS *pTDLS, + OUT PUINT16 pReason, + OUT BOOLEAN *pIsViaAP) +{ + MLME_TDLS_REQ_STRUCT *pInfo; + + pInfo = (MLME_TDLS_REQ_STRUCT *)Msg; + + *pTDLS = pInfo->pTDLS; + *pReason = pInfo->Reason; + *pIsViaAP = pInfo->IsViaAP;/* default = FALSE, not pass through AP */ + + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsSetupReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, +#ifdef WFD_SUPPORT + OUT ULONG *pWfdSubelementLen, + OUT PUCHAR pWfdSubelement, +#endif /* WFD_SUPPORT */ + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pSupRateLen, + OUT UCHAR SupRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR ExtRate[], + OUT BOOLEAN *pbWmmCapable, + OUT UCHAR *pQosCapability, + OUT UCHAR *pHtCapLen, + OUT HT_CAPABILITY_IE *pHtCap, + OUT UCHAR *pTdlsExtCapLen, + OUT EXT_CAP_INFO_ELEMENT *pTdlsExtCap, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + UCHAR LinkIdLen = 0; + UCHAR LinkIdBSSID[MAC_ADDR_LEN]; + UCHAR LinkIdInitiatorAddr[MAC_ADDR_LEN]; + UCHAR LinkIdResponderAddr[MAC_ADDR_LEN]; + + // Init output parameters + *pSupRateLen = 0; + *pExtRateLen = 0; + *pCapabilityInfo = 0; + *pHtCapLen = 0; + *pTdlsExtCapLen = 0; + *pbWmmCapable = FALSE; + *pQosCapability = 0; // default: no IE_QOS_CAPABILITY found + *pRsnLen = 0; + *pFTLen = 0; + *pTILen = 0; + + /* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), + TDLS Action header(3 bytes) and Payload (variable) + */ + if (MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (action header) \n", __FUNCTION__)); + return FALSE; + } + + // Offset to Dialog Token + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + + // Get the value of token from payload and advance the pointer + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (dialog token) \n", __FUNCTION__)); + return FALSE; + } + *pToken = *Ptr; + + // Offset to Capability + Ptr += 1; + RemainLen -= 1; + //Length += 1; + + // Get capability info from payload and advance the pointer + if (RemainLen < 2) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (capability) \n", __FUNCTION__)); + return FALSE; + } + NdisMoveMemory((PUCHAR)pCapabilityInfo, Ptr, 2); + + // Offset to other elements + Ptr += 2; + RemainLen -= 2; + + // Add for 2 necessary EID field check + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); + *pSupRateLen = pEid->Len; + } + else + return FALSE; + + break; + + case IE_COUNTRY: + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + + case IE_SUPP_CHANNELS: + break; + + case IE_RSN: + if ((pEid->Len + 2) < 64) + { + NdisMoveMemory(RsnIe, &pEid->Eid, pEid->Len + 2); + *pRsnLen = pEid->Len + 2; + } + break; + + case IE_EXT_CAPABILITY: + if (pEid->Len >= sizeof(EXT_CAP_INFO_ELEMENT)) + { + NdisMoveMemory(pTdlsExtCap, &pEid->Octet[0], sizeof(EXT_CAP_INFO_ELEMENT)); + *pTdlsExtCapLen = pEid->Len; + } + break; + + case IE_QOS_CAPABILITY: + if (pEid->Len == 1) + { + *pbWmmCapable = TRUE; + *pQosCapability = *(pEid->Octet); + } + break; + + case IE_FT_FTIE: + if ((pEid->Len) == sizeof(FT_FTIE)) + { + NdisMoveMemory(FTIe, &pEid->Eid, pEid->Len + 2); + *pFTLen = pEid->Len + 2; + } + break; + + case IE_FT_TIMEOUT_INTERVAL: + if ((pEid->Len + 2) == 7) + { + NdisMoveMemory(TIIe, &pEid->Eid, pEid->Len + 2); + *pTILen = pEid->Len + 2; + } + break; + + case IE_SUPP_REG_CLASS: + break; + + case IE_HT_CAP: + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCap, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + *pHtCapLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + } + } + break; + + case IE_2040_BSS_COEXIST: + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len >= TDLS_ELM_LEN_LINK_IDENTIFIER) + { + NdisMoveMemory(LinkIdBSSID, &pEid->Octet[0], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdInitiatorAddr, &pEid->Octet[6], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdResponderAddr, &pEid->Octet[12], MAC_ADDR_LEN); + LinkIdLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, &pEid->Octet[6], MAC_ADDR_LEN); + } + break; + + case IE_VENDOR_SPECIFIC: + // handle WME PARAMTER ELEMENT + if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + *pQosCapability = pEid->Octet[6]; + *pbWmmCapable = TRUE; + } +#ifdef WFD_SUPPORT + else if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + NdisEqualMemory(pEid->Octet, WIFIDISPLAY_OUI, 4) && (pEid->Len >= 4)) + { + hex_dump("WFD_IE", &pEid->Eid, pEid->Len +2); + RTMPMoveMemory(pWfdSubelement, &pEid->Eid, pEid->Len +2); + *pWfdSubelementLen = pEid->Len + 2; + } +#endif /* WFD_SUPPORT */ + break; + + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsSetupReqSanity - unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + if (LinkIdLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet - (link identifier) \n", __FUNCTION__)); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(LinkIdBSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(LinkIdResponderAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my MAC address\n", __FUNCTION__)); + return FALSE; + } + } + + /* Process in succeed */ + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsSetupRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, +#ifdef WFD_SUPPORT + OUT ULONG *pWfdSubelementLen, + OUT PUCHAR pWfdSubelement, +#endif /* WFD_SUPPORT */ + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pSupRateLen, + OUT UCHAR SupRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR ExtRate[], + OUT BOOLEAN *pbWmmCapable, + OUT UCHAR *pQosCapability, + OUT UCHAR *pHtCapLen, + OUT HT_CAPABILITY_IE *pHtCap, + OUT UCHAR *pTdlsExtCapLen, + OUT EXT_CAP_INFO_ELEMENT *pTdlsExtCap, + OUT USHORT *pStatusCode, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + UCHAR LinkIdLen = 0; + UCHAR LinkIdBSSID[MAC_ADDR_LEN]; + UCHAR LinkIdInitiatorAddr[MAC_ADDR_LEN]; + UCHAR LinkIdResponderAddr[MAC_ADDR_LEN]; + + // Init output parameters + *pSupRateLen = 0; + *pExtRateLen = 0; + *pCapabilityInfo = 0; + *pHtCapLen = 0; + *pTdlsExtCapLen = 0; + *pbWmmCapable = FALSE; + *pQosCapability= 0; // default: no IE_QOS_CAPABILITY found + *pStatusCode = MLME_SUCCESS; + *pRsnLen = 0; + *pFTLen = 0; + *pTILen = 0; + + // Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), TDLS Action header(3 bytes) and Payload (variable) + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (action header) \n", __FUNCTION__)); + return FALSE; + } + + // Offset to Status Code + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + + // Get the value of Status Code from payload and advance the pointer + if (RemainLen < 2) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (status code) \n", __FUNCTION__)); + return FALSE; + } + NdisMoveMemory(pStatusCode, Ptr, 2); + + if (*pStatusCode != MLME_SUCCESS) + return TRUE; // in the end of Setup Response frame + + // Offset to Dialog Token + Ptr += 2; + RemainLen -= 2; + + // Get the value of token from payload and advance the pointer + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (dialog token) \n", __FUNCTION__)); + return FALSE; + } + *pToken = *Ptr; + + // Offset to Capability + Ptr += 1; + RemainLen -= 1; + + // Get capability info from payload and advance the pointer + if (RemainLen < 2) + return FALSE; + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + + // Offset to other elements + Ptr += 2; + RemainLen -= 2; + + + // Add for 2 necessary EID field check + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(SupRate, &pEid->Octet[0], pEid->Len); + *pSupRateLen = pEid->Len; + } + else + return FALSE; + + break; + + case IE_COUNTRY: + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, &pEid->Octet[0], pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + + case IE_SUPP_CHANNELS: + break; + + case IE_RSN: + if ((pEid->Len + 2) < 64) + { + NdisMoveMemory(RsnIe, &pEid->Eid, pEid->Len + 2); + *pRsnLen = pEid->Len + 2; + } + break; + + case IE_EXT_CAPABILITY: + if (pEid->Len >= sizeof(EXT_CAP_INFO_ELEMENT)) + { + NdisMoveMemory(pTdlsExtCap, &pEid->Octet[0], sizeof(EXT_CAP_INFO_ELEMENT)); + *pTdlsExtCapLen = pEid->Len; + } + break; + + case IE_QOS_CAPABILITY: + if (pEid->Len == 1) + { + *pQosCapability = *(pEid->Octet); + *pbWmmCapable = TRUE; + } + break; + + case IE_FT_FTIE: + if ((pEid->Len) == sizeof(FT_FTIE)) + { + NdisMoveMemory(FTIe, &pEid->Eid, pEid->Len + 2); + *pFTLen = pEid->Len + 2; + } + break; + + case IE_FT_TIMEOUT_INTERVAL: + if ((pEid->Len + 2) == 7) + { + NdisMoveMemory(TIIe, &pEid->Eid, pEid->Len + 2); + *pTILen = pEid->Len + 2; + } + break; + + case IE_SUPP_REG_CLASS: + break; + + case IE_HT_CAP: + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCap, &pEid->Octet[0], sizeof(HT_CAPABILITY_IE)); + *pHtCapLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + } + } + + break; + + case IE_2040_BSS_COEXIST: + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len >= TDLS_ELM_LEN_LINK_IDENTIFIER) + { + NdisMoveMemory(LinkIdBSSID, &pEid->Octet[0], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdInitiatorAddr, &pEid->Octet[6], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdResponderAddr, &pEid->Octet[12], MAC_ADDR_LEN); + LinkIdLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, &pEid->Octet[12], MAC_ADDR_LEN); + } + break; + + case IE_VENDOR_SPECIFIC: + // handle WME PARAMTER ELEMENT + if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + *pQosCapability = pEid->Octet[6]; + *pbWmmCapable = TRUE; + } +#ifdef WFD_SUPPORT + else if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + NdisEqualMemory(pEid->Octet, WIFIDISPLAY_OUI, 4) && (pEid->Len >= 4)) + { + ULONG WfdSubelementLen = 0; + PUCHAR WfdSubelement = NULL; + + hex_dump("WFD_IE", &pEid->Eid, pEid->Len +2); + RTMPMoveMemory(pWfdSubelement, &pEid->Eid, pEid->Len +2); + *pWfdSubelementLen = pEid->Len + 2; + } +#endif /* WFD_SUPPORT */ + break; + + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsSetupRspSanity - unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + if (LinkIdLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet - (link identifier) \n", __FUNCTION__)); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(LinkIdBSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(LinkIdInitiatorAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my MAC address\n", __FUNCTION__)); + return FALSE; + } + } + + /* Process in succeed */ + *pStatusCode = MLME_SUCCESS; + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsSetupConfSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT EDCA_PARM *pEdcaParm, + OUT USHORT *pStatusCode, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + UCHAR LinkIdLen = 0; + UCHAR LinkIdBSSID[MAC_ADDR_LEN]; + UCHAR LinkIdInitiatorAddr[MAC_ADDR_LEN]; + UCHAR LinkIdResponderAddr[MAC_ADDR_LEN]; + + // Init output parameters + *pCapabilityInfo = 0; + *pStatusCode = MLME_REQUEST_DECLINED; + //pEdcaParm = 0; // default: no IE_EDCA_PARAMETER found + *pRsnLen = 0; + *pFTLen = 0; + *pTILen = 0; + + // Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), TDLS Action header(3 bytes) and Payload (variable) + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (action header) \n", __FUNCTION__)); + return FALSE; + } + // Offset to Status Code + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + + // Get the value of Status Code from payload and advance the pointer + if (RemainLen < 2) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (status code) \n", __FUNCTION__)); + return FALSE; + } + NdisMoveMemory(pStatusCode, Ptr, 2); + + if (*pStatusCode != MLME_SUCCESS) + return TRUE; // in the end of Setup Response frame + + // Offset to Dialog Token + Ptr += 2; + RemainLen -= 2; + + // Get the value of token from payload and advance the pointer + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (dialog token) \n", __FUNCTION__)); + return FALSE; + } + + *pToken = *Ptr; + + // Offset to other elements + Ptr += 1; + RemainLen -= 1; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_RSN: + if ((pEid->Len + 2) < 64) + { + NdisMoveMemory(RsnIe, &pEid->Eid, pEid->Len + 2); + *pRsnLen = pEid->Len + 2; + } + break; + + case IE_EDCA_PARAMETER: + break; + + case IE_VENDOR_SPECIFIC: + // handle WME PARAMTER ELEMENT + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + //pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0xff; + //pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us + ptr += 4; // point to next AC + } + } + break; + + case IE_FT_FTIE: + if ((pEid->Len) == sizeof(FT_FTIE)) + { + NdisMoveMemory(FTIe, &pEid->Eid, pEid->Len + 2); + *pFTLen = pEid->Len + 2; + } + break; + + case IE_FT_TIMEOUT_INTERVAL: + if ((pEid->Len + 2) == 7) + { + NdisMoveMemory(TIIe, &pEid->Eid, pEid->Len + 2); + *pTILen = pEid->Len + 2; + } + break; + + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only + // copy first sizeof(ADD_HT_INFO_IE) + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsSetupConfSanity - wrong IE_ADD_HT. \n")); + } + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len >= TDLS_ELM_LEN_LINK_IDENTIFIER) + { + NdisMoveMemory(LinkIdBSSID, &pEid->Octet[0], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdInitiatorAddr, &pEid->Octet[6], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdResponderAddr, &pEid->Octet[12], MAC_ADDR_LEN); + LinkIdLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, &pEid->Octet[6], MAC_ADDR_LEN); + } + break; + + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsSetupConfSanity - unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + + if (LinkIdLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet - (link identifier) \n", __FUNCTION__)); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(LinkIdBSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(LinkIdResponderAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my MAC address\n", __FUNCTION__)); + return FALSE; + } + } + + /* Process in succeed */ + *pStatusCode = MLME_SUCCESS; + + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pSA, + OUT BOOLEAN *pIsInitator, + OUT USHORT *pReasonCode, + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[]) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + UCHAR LinkIdLen = 0; + UCHAR LinkIdBSSID[MAC_ADDR_LEN]; + UCHAR LinkIdInitiatorAddr[MAC_ADDR_LEN]; + UCHAR LinkIdResponderAddr[MAC_ADDR_LEN]; + + // Init output parameters + *pReasonCode = 0; + *pFTLen = 0 ; + + // Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), TDLS Action header(3 bytes) and Payload (variable) + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (cation header) \n", __FUNCTION__)); + return FALSE; + } + // Offset to Reason Code + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + + // Get the value of Reason Code from payload and advance the pointer + if (RemainLen < 2) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (reason code) \n", __FUNCTION__)); + return FALSE; + } + NdisMoveMemory(pReasonCode, Ptr, 2); + + + // Offset to other elements + Ptr += 2; + RemainLen -= 2; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_FT_FTIE: + if ((pEid->Len) == sizeof(FT_FTIE)) + { + NdisMoveMemory(FTIe, &pEid->Eid, pEid->Len + 2); + *pFTLen = pEid->Len + 2; + } + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len == TDLS_ELM_LEN_LINK_IDENTIFIER) + { + NdisMoveMemory(LinkIdBSSID, &pEid->Octet[0], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdInitiatorAddr, &pEid->Octet[6], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdResponderAddr, &pEid->Octet[12], MAC_ADDR_LEN); + LinkIdLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, &pEid->Octet[12], MAC_ADDR_LEN); + } + break; + + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsTearDownSanity - unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + if (LinkIdLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet - (link identifier) \n", __FUNCTION__)); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(LinkIdBSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return FALSE; + } + + // Check if my MAC address and then find out SA + if (!MAC_ADDR_EQUAL(pAd->CurrentAddress, LinkIdInitiatorAddr)) + { + if (!MAC_ADDR_EQUAL(pAd->CurrentAddress, LinkIdResponderAddr)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my Address\n", __FUNCTION__)); + return FALSE; + } + else + { + *pIsInitator = TRUE; // peer are Initator. + NdisMoveMemory(pSA, LinkIdInitiatorAddr, MAC_ADDR_LEN); + } + } + else + { + *pIsInitator = FALSE; // peer are not Initator. + NdisMoveMemory(pSA, LinkIdResponderAddr, MAC_ADDR_LEN); + } + } + + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsDiscovReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pSA, + OUT UCHAR *pToken) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + + // Init output parameters + *pToken = 0; + + /* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes) + TDLS Action header(payload type + category + action)(3 bytes) and Payload (variable) + */ + if (MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + 3)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (action header) \n", __FUNCTION__)); + return FALSE; + } + + /* Offset to Dialog Token */ + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + 3); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + 3); + + /* Get the value of token from payload and advance the pointer */ + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (dialog token) \n", __FUNCTION__)); + return FALSE; + } + + *pToken = *Ptr; + + /* Offset to Link Identifier */ + Ptr += 1; + RemainLen -= 1; + + /* Get BSSID, SA and DA from payload and advance the pointer */ + if ((RemainLen < 20) || (Ptr[0] != IE_TDLS_LINK_IDENTIFIER) || (Ptr[1] != 18)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (link identifier) \n", __FUNCTION__)); + return FALSE; + } + if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my MAC address\n", __FUNCTION__)); + return FALSE; + } + + NdisMoveMemory(pSA, Ptr+8, MAC_ADDR_LEN); + + // Process in succeed + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsDiscovRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pToken, + OUT UCHAR *pSA, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pSupRateLen, + OUT UCHAR SupRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pHtCapLen, + OUT HT_CAPABILITY_IE *pHtCap, + OUT UCHAR *pTdlsExtCapLen, + OUT EXT_CAP_INFO_ELEMENT *pTdlsExtCap, + OUT UCHAR *pRsnLen, + OUT UCHAR RsnIe[], + OUT UCHAR *pFTLen, + OUT UCHAR FTIe[], + OUT UCHAR *pTILen, + OUT UCHAR TIIe[]) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + UCHAR LinkIdLen = 0; + UCHAR LinkIdBSSID[MAC_ADDR_LEN]; + UCHAR LinkIdInitiatorAddr[MAC_ADDR_LEN]; + UCHAR LinkIdResponderAddr[MAC_ADDR_LEN]; + + /* Init output parameters */ + *pSupRateLen = 0; + *pExtRateLen = 0; + *pCapabilityInfo = 0; + *pHtCapLen = 0; + *pTdlsExtCapLen = 0; + *pRsnLen = 0; + *pFTLen = 0; + *pTILen = 0; + LinkIdLen = 0; + + /* Message contains 802.11 header (24 bytes), + public action(2 bytes), TDLS Action header(2 bytes) and Payload (variable) + */ + if (RemainLen < (LENGTH_802_11 + 2 + 2)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (action header) \n", __FUNCTION__)); + return FALSE; + } + + /* Offset to Dialog Token */ + Ptr += (LENGTH_802_11 + 2 + 2); + RemainLen -= (LENGTH_802_11 + 2 + 2); + + // Get the value of token from payload and advance the pointer + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (dialog token) \n", __FUNCTION__)); + return FALSE; + } + *pToken = *Ptr; + + /* Offset to Capability */ + Ptr += 1; + RemainLen -= 1; + + /* Get capability info from payload and advance the pointer */ + if (RemainLen < 2) + return FALSE; + + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + + /* Offset to other elements */ + Ptr += 2; + RemainLen -= 2; + + /* Add for 2 necessary EID field check */ + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(SupRate, &pEid->Octet[0], pEid->Len); + *pSupRateLen = pEid->Len; + } + else + return FALSE; + + break; + + case IE_COUNTRY: + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, &pEid->Octet[0], pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + + case IE_SUPP_CHANNELS: + break; + + case IE_RSN: + if ((pEid->Len + 2) < 64) + { + NdisMoveMemory(RsnIe, &pEid->Eid, pEid->Len + 2); + *pRsnLen = pEid->Len + 2; + } + break; + + case IE_EXT_CAPABILITY: + if (pEid->Len >= sizeof(EXT_CAP_INFO_ELEMENT)) + { + NdisMoveMemory(pTdlsExtCap, &pEid->Octet[0], sizeof(EXT_CAP_INFO_ELEMENT)); + *pTdlsExtCapLen = pEid->Len; + } + break; + + + + case IE_FT_FTIE: + if ((pEid->Len) == sizeof(FT_FTIE)) + { + NdisMoveMemory(FTIe, &pEid->Eid, pEid->Len + 2); + *pFTLen = pEid->Len + 2; + } + break; + + case IE_FT_TIMEOUT_INTERVAL: + if ((pEid->Len + 2) == 7) + { + NdisMoveMemory(TIIe, &pEid->Eid, pEid->Len + 2); + *pTILen = pEid->Len + 2; + } + break; + + case IE_SUPP_REG_CLASS: + break; + + case IE_HT_CAP: + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCap, &pEid->Octet[0], sizeof(HT_CAPABILITY_IE)); + *pHtCapLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + } + } + + break; + + case IE_2040_BSS_COEXIST: + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len >= TDLS_ELM_LEN_LINK_IDENTIFIER) + { + NdisMoveMemory(LinkIdBSSID, &pEid->Octet[0], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdInitiatorAddr, &pEid->Octet[6], MAC_ADDR_LEN); + NdisMoveMemory(LinkIdResponderAddr, &pEid->Octet[12], MAC_ADDR_LEN); + LinkIdLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, &pEid->Octet[12], MAC_ADDR_LEN); + } + break; + + default: + /* Unknown IE, we have to pass it as variable IEs */ + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsDiscovRspSanity - unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + if (LinkIdLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet - (link identifier) \n", __FUNCTION__)); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(LinkIdBSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(LinkIdInitiatorAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my MAC address\n", __FUNCTION__)); + return FALSE; + } + } + + /* Process in succeed */ + return TRUE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsChannelSwitchReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pPeerAddr, + OUT BOOLEAN *pIsInitator, + OUT UCHAR *pTargetChannel, + OUT UCHAR *pRegulatoryClass, + OUT UCHAR *pNewExtChannelOffset, + OUT USHORT *pChSwitchTime, + OUT USHORT *pChSwitchTimeOut) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + PHEADER_802_11 pHeader; + BOOLEAN rv = TRUE; + + /* init value */ + *pNewExtChannelOffset = 0; + + /* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), TDLS Action header(3 bytes) and Payload (variable) */ + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (ation header) \n", __FUNCTION__)); + return FALSE; + } + + pHeader = (PHEADER_802_11)Ptr; + COPY_MAC_ADDR(pPeerAddr, &pHeader->Addr2); + + /* Offset to Target Channel */ + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + + /* Get the value of target channel from payload and advance the pointer */ + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (target channel) \n", __FUNCTION__)); + return FALSE; + } + + *pTargetChannel = *Ptr; + + /* Offset to Regulatory Class */ + Ptr += 1; + RemainLen -= 1; + + /* Get the value of regulatory class from payload and advance the pointer */ + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (regulatory class) \n", __FUNCTION__)); + return FALSE; + } + + *pRegulatoryClass = *Ptr; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s() - Regulatory class = %d \n", __FUNCTION__, *pRegulatoryClass)); + + /* Offset to other elements */ + Ptr += 1; + RemainLen -= 1; + + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + rv = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__)); + } + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len != TDLS_ELM_LEN_LINK_IDENTIFIER) + { + rv = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s() - wrong IE_TDLS_LINK_IDENTIFIER. \n", __FUNCTION__)); + } + break; + + case IE_TDLS_CHANNEL_SWITCH_TIMING: + if (pEid->Len == 4) + { + NdisMoveMemory(pChSwitchTime, &pEid->Octet[0], 2); + NdisMoveMemory(pChSwitchTimeOut, &pEid->Octet[2], 2); + } + else + { + rv = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s() - wrong IE_TDLS_CHANNEL_SWITCH_TIMING. \n", __FUNCTION__)); + } + break; + + default: + /* Unknown IE, we have to pass it as variable IEs */ + DBGPRINT(RT_DEBUG_WARN, ("%s() - unrecognized EID = %d\n", __FUNCTION__, pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return rv; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsChannelSwitchRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pPeerAddr, + OUT USHORT *pStatusCode, + OUT USHORT *pChSwitchTime, + OUT USHORT *pChSwitchTimeOut) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + PHEADER_802_11 pHeader; + BOOLEAN rv = TRUE; + + // Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), TDLS Action header(3 bytes) and Payload (variable) + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (ation header) \n", __FUNCTION__)); + return FALSE; + } + + pHeader = (PHEADER_802_11)Ptr; + COPY_MAC_ADDR(pPeerAddr, &pHeader->Addr2); + + // Offset to Status Code + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_TDLS_PAYLOAD_H); + + // Get the value of Status Code from payload and advance the pointer + if (RemainLen < 2) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (status code) \n", __FUNCTION__)); + return FALSE; + } + NdisMoveMemory(pStatusCode, Ptr, 2); + + // Offset to other elements + Ptr += 2; + RemainLen -= 2; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= RemainLen) + { + switch(pEid->Eid) + { + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len != TDLS_ELM_LEN_LINK_IDENTIFIER) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - wrong IE_TDLS_LINK_IDENTIFIER. \n", __FUNCTION__)); + rv = FALSE; + } + break; + + case IE_TDLS_CHANNEL_SWITCH_TIMING: + if (pEid->Len == 4) + { + NdisMoveMemory(pChSwitchTime, &pEid->Octet[0], 2); + NdisMoveMemory(pChSwitchTimeOut, &pEid->Octet[2], 2); + + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - wrong IE_TDLS_CHANNEL_SWITCH_TIMING. \n", __FUNCTION__)); + rv = FALSE; + } + break; + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("%s() - unrecognized EID = %d\n", __FUNCTION__, pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return rv; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +ULONG PeerTdlsBasicSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN BOOLEAN bInitiator, + OUT UCHAR *pToken, + OUT UCHAR *pSA) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + + /* + Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes), + TDLS Action header(3 bytes) and Payload (variable) + */ + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + 3)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - " + "Invaild packet length - (action header) \n", + __FUNCTION__)); + return 0; + } + + /* Offset to Dialog Token */ + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + 3); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + 3); + + /* Get the value of token from payload and advance the pointer */ + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - " + "Invaild packet length - (dialog token) \n", + __FUNCTION__)); + return 0; + } + *pToken = *Ptr; + + /* Offset to Link Identifier */ + Ptr += 1; + RemainLen -= 1; + + /* Get BSSID, SA and DA from payload and advance the pointer */ + if (RemainLen < 20 || Ptr[0] != IE_TDLS_LINK_IDENTIFIER || Ptr[1] != 18) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - " + "Invaild packet length - (link identifier) \n", + __FUNCTION__)); + return 0; + } + + if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - " + "It's not my BSSID\n", + __FUNCTION__)); + return 0; + } + + if (bInitiator) + { + if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - " + "It's not my MAC address\n", + __FUNCTION__)); + hex_dump("Dst Mac=", Ptr+14, 6); + return 0; + } + NdisMoveMemory(pSA, Ptr+8, MAC_ADDR_LEN); + } + else + { + if (!MAC_ADDR_EQUAL(Ptr+8, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - " + "It's not my MAC address\n", + __FUNCTION__)); + hex_dump("Dst Mac=", Ptr+8, 6); + return 0; + } + NdisMoveMemory(pSA, Ptr+14, MAC_ADDR_LEN); + } + + /* Offset to PU Buffer Status */ + Ptr += 20; + RemainLen -= 20; + return (MsgLen - RemainLen); +} + +#ifdef WFD_SUPPORT +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN TDLS_PeerTunneledProbeReqRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT UCHAR *pChannel, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, + OUT ULONG *pWfdSubelementLen, + OUT PUCHAR pWfdSubelement) +{ + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc = FALSE; + PUCHAR Ptr; + BOOLEAN bFirstP2pOUI = TRUE; + BOOLEAN bLastIsP2pOUI = FALSE; + PUCHAR pP2PIeConLen = NULL; /* pointer to 2 bytes to indicate Contenated length of all P2P IE */ + ULONG P2PIeConLen = 0; /* Contenated length of all P2P IE */ + ULONG idx; + + pFrame = (PFRAME_802_11)Msg; + Length = LENGTH_802_11; + + *P2PSubelementLen = 0; +#ifdef WFD_SUPPORT + *pWfdSubelementLen = 0; +#endif /* WFD_SUPPORT */ + *pSsidLen = 0; + *Peerip = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + Ptr = pFrame->Octet; + + hex_dump("TDLS_PeerTunneledProbeReqRspSanity", Ptr, MsgLen - LENGTH_802_11); + /* LLC+SNAP */ + Ptr += LENGTH_802_1_H; + Length += LENGTH_802_1_H; + + /* Payload Type(1) + Category(1) + OU(3) + Frame Body Type(1) */ + Ptr += 6; + Length += 6; + + pEid = (PEID_STRUCT) Ptr; + printk("starting parsing form:: %02x %02x %02x %02x\n", *Ptr, *(Ptr+1), *(Ptr+2), *(Ptr+3)); + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_SSID: + bLastIsP2pOUI = FALSE; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + RTMPMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + } + break; + case IE_VENDOR_SPECIFIC: + bLastIsP2pOUI = FALSE; + /* Check the OUI version, filter out non-standard usage */ + if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) && (pEid->Len >= 4)) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, pEid->Len +2); + *P2PSubelementLen = pEid->Len +2; + } + else if (*P2PSubelementLen > 0) + { + if (((*P2PSubelementLen) + (pEid->Len+2)) <= MAX_VIE_LEN) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! 111 Sum of P2PSubelementLen= %lu, > MAX_VIE_LEN !!\n", __FUNCTION__ ,((*P2PSubelementLen) + (pEid->Len+2)))); + return FALSE; + } + } + } + else if (NdisEqualMemory(pEid->Octet, P2POUIBYTE, 4) && (pEid->Len >= 4)) + { + brc = TRUE; + bLastIsP2pOUI = TRUE; + /* If this is the first P2P OUI. Then also append P2P OUI. */ + if (bFirstP2pOUI == TRUE) + { + /* Althought this is first P2P IE. */ + /* still need to Check *P2PSubelementLen, because *P2PSubelementLen also includes WPS IE. */ + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, 2); + *(pP2pSubelement + 2) = 0; + /* Make one more byte for P2P accumulated length. */ + RTMPMoveMemory(pP2pSubelement + 3, &pEid->Octet[0], pEid->Len); + pP2PIeConLen = pP2pSubelement + *P2PSubelementLen + 1; + *P2PSubelementLen = (pEid->Len + 3); + P2PIeConLen = pEid->Len; /* Real P2P IE length is Len. */ + DBGPRINT(RT_DEBUG_INFO, ("SYNC -1-1 P2PIeConLen = %ld\n", P2PIeConLen)); + } + else if (*P2PSubelementLen > 0) + { + if (((*P2PSubelementLen) + (pEid->Len+3)) <= MAX_VIE_LEN) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, 2); + *(pP2pSubelement + *P2PSubelementLen + 2) = 0; + /* Make one more byte for P2P accumulated length. */ + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen + 3, &pEid->Octet[0], pEid->Len); + pP2PIeConLen = pP2pSubelement + *P2PSubelementLen + 1; + *P2PSubelementLen += (pEid->Len+3); + /* bFirstP2pOUI is TURE. So use = */ + P2PIeConLen = pEid->Len; + DBGPRINT(RT_DEBUG_INFO, (" -1-2 P2PIeConLen = %ld\n", P2PIeConLen)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! 222 Sum of P2PSubelementLen= %lu, > MAX_VIE_LEN !!\n", __FUNCTION__ ,((*P2PSubelementLen) + (pEid->Len+3)))); + return FALSE; + } + } + bFirstP2pOUI = FALSE; + } + else if (bLastIsP2pOUI == TRUE) + { + /* If this is not the first P2P OUI. Then don't append P2P OUI. */ + /* because our parse function doesn't need so many P2P OUI. */ + if ((*P2PSubelementLen > 0) && (pEid->Len > 4)) + { + if (((*P2PSubelementLen) + (pEid->Len-4)) <= MAX_VIE_LEN) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Octet[4], pEid->Len-4); + *P2PSubelementLen += (pEid->Len-4); + P2PIeConLen += (pEid->Len - 4); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! 333 Sum of P2PSubelementLen= %lu, > MAX_VIE_LEN !!\n", __FUNCTION__ ,((*P2PSubelementLen) + (pEid->Len-4)))); + return FALSE; + } + } + } + } + else if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + NdisEqualMemory(pEid->Octet, WIFIDISPLAY_OUI, 4) && (pEid->Len >= 4)) + { + hex_dump("WFD_IE", &pEid->Eid, pEid->Len +2); + RTMPMoveMemory(pWfdSubelement, &pEid->Eid, pEid->Len +2); + *pWfdSubelementLen = pEid->Len + 2; + } + break; + default : + bLastIsP2pOUI = FALSE; + break; + + } + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + + } + + if ((P2PIeConLen != 0) && (pP2PIeConLen != NULL)) + { + *pP2PIeConLen = (UCHAR)(P2PIeConLen%256); + *(pP2PIeConLen+1) = (UCHAR)(P2PIeConLen/256); + DBGPRINT(RT_DEBUG_INFO, (" - 3 P2PIeConLen = %ld. /256 = %ld. *P2PSubelementLen = %ld \n", P2PIeConLen, (P2PIeConLen/256), *P2PSubelementLen)); + DBGPRINT(RT_DEBUG_INFO, (" - %x %x \n", *pP2PIeConLen, *(pP2PIeConLen+1) )); + for (idx = 0; idx < (*P2PSubelementLen);) + { + DBGPRINT_RAW(RT_DEBUG_INFO, ("%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-", + *(pP2pSubelement+idx), *(pP2pSubelement+idx+1), *(pP2pSubelement+idx+2), *(pP2pSubelement+idx+3) + ,*(pP2pSubelement+idx+4) ,*(pP2pSubelement+idx+5) ,*(pP2pSubelement+idx+6),*(pP2pSubelement+idx+7) + ,*(pP2pSubelement+idx+8),*(pP2pSubelement+idx+9),*(pP2pSubelement+idx+10),*(pP2pSubelement+idx+11))); + + idx = idx + 12; + } + + } + return brc; +} +#endif /* WFD_SUPPORT */ + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_SendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; + UCHAR idx; + PRT_802_11_TDLS pTDLS = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + /* WPA 802.1x secured port control */ + if (((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.wdev.IEEE8021X == TRUE) +#endif +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && + (pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + return; + } + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if ((pTDLS->Valid) && (pTDLS->Status == TDLS_MODE_CONNECTED)) + { + NdisZeroMemory(NullFrame, 48); + Length = sizeof(HEADER_802_11); + + pHeader_802_11 = (PHEADER_802_11) NullFrame; + + pHeader_802_11->FC.Type = FC_TYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_DATA_NULL; + pHeader_802_11->FC.ToDs = 0; + pHeader_802_11->FC.FrDs = 0; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTDLS->MacAddr); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + + if (pAd->CommonCfg.bAPSDForcePowerSave) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } + else + { + pHeader_802_11->FC.PwrMgmt = (RtmpPktPmBitCheck(pAd) == TRUE) ? 1: 0; + } + + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + + pAd->Sequence++; + pHeader_802_11->Sequence = pAd->Sequence; + + /* Prepare QosNull function frame */ + if (bQosNull) + { + pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + NullFrame[Length] = 0; + NullFrame[Length+1] = 0; + Length += 2;/* if pad with 2 bytes for alignment, APSD will fail */ + } + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_LinkMaintenance( + IN PRTMP_ADAPTER pAd) +{ + UCHAR idx; + PRT_802_11_TDLS pTDLS = NULL; +#ifdef TDLS_AUTOLINK_SUPPORT + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; +#endif // TDLS_AUTOLINK_SUPPORT // + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if ((pTDLS->Valid == TRUE) && (pTDLS->Status == TDLS_MODE_CONNECTED)) + { + UCHAR wcid = pTDLS->MacTabMatchWCID; + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[wcid]; + + if(!IS_ENTRY_TDLS(pEntry)) + continue; + + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->TdlsKeyLifeTimeCount++; + NdisReleaseSpinLock(&pAd->MacTabLock); + + if (pEntry->TdlsKeyLifeTimeCount >= pTDLS->KeyLifetime) + { +#ifdef TDLS_AUTOLINK_SUPPORT + PLIST_HEADER pTdlsDiscovryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; +#endif // TDLS_AUTOLINK_SUPPORT // + DBGPRINT(RT_DEBUG_WARN, + ("ageout %02x:%02x:%02x:%02x:%02x:%02x from TDLS #%d after %d-sec silence\n", + PRINT_MAC(pEntry->Addr), idx, TDLS_ENTRY_AGEOUT_TIME)); + + NdisAcquireSpinLock(&pAd->StaCfg.TdlsInfo.TDLSEntryLock); + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + pTDLS->Status = TDLS_MODE_NONE; + NdisReleaseSpinLock(&pAd->StaCfg.TdlsInfo.TDLSEntryLock); + + TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON, FALSE); +#ifdef TDLS_AUTOLINK_SUPPORT + TDLS_DelDiscoveryEntryByMAC(pTdlsDiscovryEnList, pTDLS->MacAddr); +#endif // TDLS_AUTOLINK_SUPPORT // + + MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, pTDLS->MacAddr); + } + } + + /* UAPSD also use the variable to do some check */ + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->NoDataIdleCount++; + NdisReleaseSpinLock(&pAd->MacTabLock); + +#ifdef TDLS_UAPSD_DEBUG + /* virtual timeout handle */ + RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(pEntry); +#else /* TDLS_UAPSD_DEBUG */ +#ifdef UAPSD_SUPPORT + /* one second timer */ + UAPSD_QueueMaintenance(pAd, pEntry); +#endif /* UAPSD_SUPPORT */ +#endif /* TDLS_UAPSD_DEBUG */ + } + } + +#ifdef TDLS_AUTOLINK_SUPPORT + TDLS_MaintainBlackList(pAd, pTdlsBlackEnList); +#endif // TDLS_AUTOLINK_SUPPORT // +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + INT i; + + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s\n", "MAC\n")); + for (i=0; iStaCfg.TdlsInfo.TDLSEntry[i].Valid) && (pAd->StaCfg.TdlsInfo.TDLSEntry[i].Status == TDLS_MODE_CONNECTED)) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacTabMatchWCID]; + + DBGPRINT(RT_DEBUG_OFF, ("%02x:%02x:%02x:%02x:%02x:%02x \n", + pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacAddr[0], pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacAddr[1], pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacAddr[2], + pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacAddr[3], pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacAddr[4], pAd->StaCfg.TdlsInfo.TDLSEntry[i].MacAddr[5])); + /*DBGPRINT(RT_DEBUG_OFF, ("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut)); */ + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-4s%-4s%-4s%-7s%-7s%-7s","MAC", "AID", "BSS", "PSM", "WMM", "RSSI0", "RSSI1", "RSSI2")); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("%-8s%-10s%-6s%-6s%-6s%-6s", "MIMOPS", "PhMd", "BW", "MCS", "SGI", "STBC")); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("\n%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5])); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->apidx)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi0)); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi1)); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi2)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->MmpsMode)); + DBGPRINT(RT_DEBUG_OFF, ("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW))); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.STBC)); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0)); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + } + } + + return TRUE; +} + +#define PKT_CHANNEL_MAX_WAIT_CYCLE 100 + +VOID +TDLS_DisableMacTxRx( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data = 0; + UINT32 macStatus; + UINT32 MTxCycle; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ===> \n", __FUNCTION__)); + + //Disable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data &= (~0xC); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + + // Check MAC Tx/Rx idle + for (MTxCycle = 0; MTxCycle < PKT_CHANNEL_MAX_WAIT_CYCLE; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(1000); + else + break; + } + + if (MTxCycle == PKT_CHANNEL_MAX_WAIT_CYCLE) + { + printk("Polling MAC idle to max !!\n"); + } +} + +VOID +TDLS_EnableMacTx( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ===> \n", __FUNCTION__)); + + //Enable MAC Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x4; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); +} + +VOID +TDLS_EnableMacRx( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ===> \n", __FUNCTION__)); + + //Enable MAC Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x8; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); +} + +VOID +TDLS_EnableMacTxRx( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ===> \n", __FUNCTION__)); + + //Enable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0xC; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); +} + + +// TODO: shiang-usw, need to revise for new arch +VOID TDLS_DisablePktChannel(RTMP_ADAPTER *pAd, UCHAR QSel) +{ + UINT32 Data = 0; + UINT32 MTxCycle = 0, MaxCycle = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FixME!!\n", __FUNCTION__)); + return; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + /* Set HCCA/EDCA Q mode to manual-mode */ + RTMP_IO_READ32(pAd, PBF_CFG, &Data); + Data |= ((1 << 10) | (1 << 11)); + RTMP_IO_WRITE32(pAd, PBF_CFG, Data); + + +#ifdef RTMP_MAC_PCI + if (QSel == FIFO_HCCA) + { + /* Polling HCCA Out-Q until empty */ + for (MTxCycle = 0; MTxCycle < 10; MTxCycle++) + { + RTMP_IO_READ32(pAd, TXRXQ_STA, &Data); + + if (((Data >> 11) & 0x1f) == 0) + break; + else + RtmpusecDelay(1000); + } + } + else if (QSel == FIFO_EDCA) + { + /* Polling EDCA Out-Q until empty */ + for (MTxCycle = 0; MTxCycle < 10; MTxCycle++) + { + RTMP_IO_READ32(pAd, TXRXQ_STA, &Data); + + if (((Data >> 19) & 0x1f) == 0) + break; + else + RtmpusecDelay(1000); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("unknow Out-Q\n")); + return; + } + + if (MTxCycle >= 10) + DBGPRINT(RT_DEBUG_ERROR, ("Polling %s Out-Q max\n", (QSel == FIFO_EDCA ? "EDCA" : "HCCA"))); + + /* Disable PBF HCCA/EDCA */ + RTMP_IO_READ32(pAd, PBF_CFG, &Data); + Data &= (~0xC); + RTMP_IO_WRITE32(pAd, PBF_CFG, Data); +#endif /* RTMP_MAC_PCI */ +#endif /* RTMP_MAC */ +} + + +VOID TDLS_EnablePktChannel(RTMP_ADAPTER *pAd, UCHAR QSel) +{ + UINT32 Data = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FixME!!\n", __FUNCTION__)); + return; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + RTMP_IO_READ32(pAd, PBF_CFG, &Data); + + if (QSel == FIFO_HCCA) + { + Data |= 0x8; + Data &= ~(1 << 11); + } + else if (QSel == FIFO_EDCA) + { + Data |=0x4; + Data &= ~(1 << 10); + } + else + { + Data |= 0xC; + Data &= ~(1 << 10); + Data &= ~(1 << 11); + } + + RTMP_IO_WRITE32(pAd, PBF_CFG, Data); +#endif /* RTMP_MAC */ +} + +VOID +TDLS_InitChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bEnableMACTxRx, + IN UCHAR TargetChannel, + IN UCHAR TargetChannelBW) +{ + UCHAR Value = 0; + UINT32 Data = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s() ===> \n", __FUNCTION__)); + +#ifdef RTMP_MAC_PCI + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); +#endif /* RTMP_MAC_PCI */ + + + if (pAd->StaCfg.TdlsInfo.TdlsCurrentTargetChannel == TargetChannel) + { +#ifdef RTMP_MAC_PCI + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); +#endif /* RTMP_MAC_PCI */ + + + return; + } + + pAd->StaCfg.TdlsInfo.TdlsCurrentTargetChannel = TargetChannel; + +#ifdef RTMP_MAC_PCI + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); +#endif /* RTMP_MAC_PCI */ + + + TDLS_DisableMacTxRx(pAd); + +#ifdef DOT11_N_SUPPORT + if (TargetChannelBW == EXTCHA_ABOVE) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, (TargetChannel + 2), FALSE); + AsicLockChannel(pAd, (TargetChannel + 2)); + + /* TX/RX Bandwidth control */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + /* RX : control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_WARN, ("A. %d. %ld @!\n", TargetChannel, (jiffies * 1000) / OS_HZ)); + } + else if (TargetChannelBW == EXTCHA_BELOW) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, (TargetChannel - 2), FALSE); + AsicLockChannel(pAd, (TargetChannel - 2)); + + /* TX/RX Bandwidth control */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + /* RX : control channel at upper */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_WARN, ("B. %d. %ld @!\n", TargetChannel, (jiffies * 1000) / OS_HZ)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* Must using 20MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAd, TargetChannel, FALSE); + AsicLockChannel(pAd, TargetChannel); + + /* TX/RX Bandwidth control */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_WARN, ("%d... %ld @!\n", TargetChannel, (jiffies * 1000) / OS_HZ)); + } + + if (bEnableMACTxRx) + { + /* Enable MAC Tx/Rx to receive packet */ + TDLS_EnableMacTxRx(pAd); + } + else + { + /* Enable MAC Rx to receive packet */ + TDLS_EnableMacRx(pAd); + } + + pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannel = TargetChannel; + pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannelBW = (TargetChannelBW == EXTCHA_NONE) ? (BW_20) : (BW_40); + + //RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + //AsicBBPReadWithRxChain(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + + DBGPRINT(RT_DEBUG_TRACE, ("%s() <=== \n", __FUNCTION__)); + +} + +VOID TDLS_UpdateHwNullFramePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR PwrMgmt, + IN CHAR Index) +{ + UINT32 longValue; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + RTMP_IO_READ32(pAd, pAd->NullBufOffset[Index] + TXWISize, &longValue); + if (PwrMgmt == PWR_ACTIVE) + longValue &= (~0x00001000); + else + longValue |= 0x00001000; + RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[Index] + TXWISize, longValue); +} + +VOID TDLS_KickOutHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR PwrMgmt, + IN CHAR Index) +{ + TDLS_UpdateHwNullFramePwr(pAd, PwrMgmt, Index); + + /* kick NULL frame #0 */ + RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x80); +} + +#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ + do{ \ + if (bIntContext == FALSE) \ + RTMP_IRQ_LOCK((lock), IrqFlags); \ + }while(0) + +#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ + do{ \ + if (bIntContext == FALSE) \ + RTMP_IRQ_UNLOCK((lock), IrqFlags); \ + }while(0) + +NDIS_STATUS +TDLS_SendOutActionFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN UCHAR FrameType) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + UINT AllowFragSize; + UCHAR NumberOfFrag; + UCHAR RTSRequired; + UCHAR QueIdx, UserPriority; + unsigned int IrqFlags; + UCHAR Rate; + TX_BLK TxBlk; + TX_BLK *pTxBlk; + BOOLEAN hasTxDesc = FALSE; + PNDIS_PACKET pPacket; + NDIS_STATUS Status; +#ifdef RTMP_MAC_PCI + ULONG FreeNumber[NUM_OF_TX_RING]; +#endif /* RTMP_MAC_PCI */ + + if ((!pEntry) || (!IS_ENTRY_TDLS(pEntry))) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() --> unknow Entry !!!\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + /* build a NDIS packet*/ + Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("%s (error:: can't allocate NDIS PACKET)\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value*/ + if(pEntry->apidx != 0) + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx); + + RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); + RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); + + if (FrameType != 0) + RTMP_SET_TDLS_SPECIFIC_PACKET(pPacket, FrameType); + else + RTMP_SET_TDLS_SPECIFIC_PACKET(pPacket, 0); + + /* Prepare packet information structure for buffer descriptor */ + /* chained within a single NDIS packet. */ + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - pSrcBufVA == NULL !!!SrcBufLen=%x\n", __FUNCTION__, SrcBufLen)); + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + if (SrcBufLen < 14) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - Ndis Packet buffer error !!!\n", __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + + /* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */ + /* Note multicast packets in adhoc also use BSSID_WCID index. */ + + if (pAd->StaCfg.BssType == BSS_INFRA) + { + if (VALID_WCID(pEntry->Aid) && + (IS_ENTRY_TDLS(&pAd->MacTab.Content[pEntry->Aid]))) + { + pEntry = &pAd->MacTab.Content[pEntry->Aid]; + Rate = pAd->MacTab.Content[pEntry->Aid].CurrTxRate; + } + else + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + Rate = pAd->CommonCfg.TxRate; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - TDLS can't work in ADHOC !!!\n", __FUNCTION__)); + + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() -Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", + __FUNCTION__, PRINT_MAC(pSrcBufVA))); + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + /* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */ + /* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */ + UserPriority = 5; + QueIdx = QID_AC_VI; + RTMP_SET_PACKET_TDLS(pPacket, 1); + +#ifdef UAPSD_SUPPORT + /* the code must behind RTMPCheckEtherType() to get QueIdx */ + if ((pEntry != NULL) && + (pEntry->PsMode == PWR_SAVE) && + (pEntry->FlgPsModeIsWakeForAWhile == FALSE) && + (pEntry->bAPSDDeliverEnabledPerAC[QueIdx] == 0)) + { + /* the packet will be sent to AP, not the peer directly */ + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + /* for AP entry, pEntry->bAPSDDeliverEnabledPerAC[QueIdx] always is 0 */ + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + Rate = pAd->CommonCfg.TxRate; + } +#endif /* UAPSD_SUPPORT */ + + /* + STEP 1. Decide number of fragments required to deliver this MSDU. + The estimation here is not very accurate because difficult to + take encryption overhead into consideration here. The result + "NumberOfFrag" is then just used to pre-check if enough free + TXD are available to hold this MSDU. + */ + if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */ + NumberOfFrag = 1; + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE)) + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ +#ifdef DOT11_N_SUPPORT + else if ((pEntry->HTPhyMode.field.MODE == MODE_HTMIX) + || (pEntry->HTPhyMode.field.MODE == MODE_HTGREENFIELD)) + NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */ +#endif /* DOT11_N_SUPPORT */ + else { + /* + The calculated "NumberOfFrag" is a rough estimation because of various + encryption/encapsulation overhead not taken into consideration. This number is just + used to make sure enough free TXD are available before fragmentation takes place. + In case the actual required number of fragments of an NDIS packet + excceeds "NumberOfFrag"caculated here and not enough free TXD available, the + last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of + resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should + rarely happen and the penalty is just like a TX RETRY fail. Affordable. + */ + + AllowFragSize = + (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - + LENGTH_CRC; + NumberOfFrag = + ((PacketInfo.TotalPacketLength - LENGTH_802_3 + + LENGTH_802_1_H) / AllowFragSize) + 1; + /* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */ + if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + + LENGTH_802_1_H) % AllowFragSize) == 0) { + NumberOfFrag--; + } + } + + /* Save fragment number to Ndis packet reserved field */ + RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + + /* + STEP 2. Check the requirement of RTS: + If multiple fragment required, RTS is required only for the first fragment + if the fragment size large than RTS threshold + For RT28xx, Let ASIC send RTS/CTS + */ + if (NumberOfFrag > 1) + RTSRequired = + (pAd->CommonCfg.FragmentThreshold > + pAd->CommonCfg.RtsThreshold) ? 1 : 0; + else + RTSRequired = + (PacketInfo.TotalPacketLength > + pAd->CommonCfg.RtsThreshold) ? 1 : 0; + + /* Save RTS requirement to Ndis packet reserved field */ + RTMP_SET_PACKET_RTS(pPacket, RTSRequired); + + RTMP_SET_PACKET_TXRATE(pPacket, Rate); + + RTMP_SET_PACKET_UP(pPacket, UserPriority); + +#ifdef UAPSD_SUPPORT + if ((pEntry != NULL) && + (pEntry->PsMode == PWR_SAVE) && + (pEntry->FlgPsModeIsWakeForAWhile == FALSE) && + (pEntry->bAPSDDeliverEnabledPerAC[QueIdx] != 0)) + { + /* + only UAPSD of the peer for the queue is set; + for non-UAPSD queue, we will send it to the AP. + */ + if (RtmpInsertPsQueue(pAd, pPacket, pEntry, QueIdx) != NDIS_STATUS_SUCCESS) + return NDIS_STATUS_FAILURE; + } +#endif /* UAPSD_SUPPORT */ + + //RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); + + DEQUEUE_LOCK(&pAd->irq_lock, FALSE, IrqFlags); +#ifdef RTMP_MAC_PCI + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + + if (FreeNumber[QueIdx] <= 5) + { + /* free Tx(QueIdx) resources*/ + RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + } +#endif /* RTMP_MAC_PCI */ + + pTxBlk = &TxBlk; + NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); + /*InitializeQueueHeader(&pTxBlk->TxPacketList); Didn't need it because we already memzero it.*/ + pTxBlk->QueIdx = QueIdx; + +#ifdef VENDOR_FEATURE1_SUPPORT + pTxBlk->HeaderBuf = (UCHAR *)pTxBlk->HeaderBuffer; +#endif /* VENDOR_FEATURE1_SUPPORT */ + + /* Early check to make sure we have enoguh Tx Resource.*/ + hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if (!hasTxDesc) + { + pAd->PrivateInfo.TxRingFullCnt++; + + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + DEQUEUE_UNLOCK(&pAd->irq_lock, FALSE, IrqFlags); + return NDIS_STATUS_FAILURE; + } + + pTxBlk->TxFrameType = TX_LEGACY_FRAME; + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/ + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + pTxBlk->pPacket = pPacket; + + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + + + STAHardTransmit(pAd, pTxBlk, QueIdx); + +#ifdef RTMP_MAC_PCI + DEQUEUE_UNLOCK(&pAd->irq_lock, FALSE, IrqFlags); +#endif /* RTMP_MAC_PCI */ + +#ifdef VENDOR_FEATURE1_SUPPORT + if (++pAd->FifoUpdateDone >= 4) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#else + NICUpdateFifoStaCounters(pAd); +#endif /* VENDOR_FEATURE1_SUPPORT */ + + //RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + + + return NDIS_STATUS_SUCCESS; +} + +VOID TDLS_SendOutNullFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN bQosNull, + IN BOOLEAN bWaitACK) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; +#ifdef RTMP_MAC_PCI + UINT8 TXWISize = pAd->chipCap.TXWISize; + UCHAR rtmpHwHdr[TXINFO_SIZE + pAd->chipCap.TXWISize]; + ULONG FreeNum; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PNDIS_PACKET pPacket; + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + /* WPA 802.1x secured port control */ + if (((pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && + (pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_ERROR, ("===> %s() - Port not Secured !!!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(NullFrame, 48); + Length = sizeof(HEADER_802_11); + + pHeader_802_11 = (PHEADER_802_11) NullFrame; + + pHeader_802_11->FC.Type = FC_TYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_DATA_NULL; + pHeader_802_11->FC.ToDs = 0; + pHeader_802_11->FC.FrDs = 0; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pEntry->Addr); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + + if (pAd->CommonCfg.bAPSDForcePowerSave) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } + else + { + pHeader_802_11->FC.PwrMgmt = (RtmpPktPmBitCheck(pAd) == TRUE) ? 1: 0; + } + + pAd->Sequence++; + pHeader_802_11->Sequence = pAd->Sequence; + + /* Prepare QosNull function frame */ + if (bQosNull) + { + pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + NullFrame[Length] = 0; + NullFrame[Length+1] = 0; + Length += 2;/* if pad with 2 bytes for alignment, APSD will fail */ + } + + +#ifdef RTMP_MAC_PCI + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + /* Reset is in progress, stop immediately*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + return; + } + + FreeNum = GET_MGMTRING_FREENO(pAd); + + if ((FreeNum > 0)) + { + /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870*/ + NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWISize)); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWISize), NullFrame, Length); + + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() (error:: can't allocate NDIS PACKET)\n", __FUNCTION__)); + return; + } + +#ifdef UAPSD_SUPPORT + UAPSD_MR_QOS_NULL_HANDLE(pAd, NullFrame, pPacket); +#endif /* UAPSD_SUPPORT */ + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - pSrcBufVA == NULL !!!SrcBufLen=%x\n", __FUNCTION__, SrcBufLen)); + + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return; + } + + if (bWaitACK) + RTMP_SET_PACKET_TDLS_WAIT_ACK(pPacket, 1); + else + RTMP_SET_PACKET_TDLS_WAIT_ACK(pPacket, 0); + + MlmeHardTransmitMgmtRing(pAd, QID_AC_BE, pPacket); + } + else + { + pAd->RalinkCounters.MgmtRingFullCount++; + + DBGPRINT(RT_DEBUG_ERROR, ("not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", + pAd->RalinkCounters.MgmtRingFullCount)); + } +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); +} + +VOID TdlsMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = FC_TYPE_DATA; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + pHdr80211->FC.FrDs = 0; + + if (ToDs == 1) + { + COPY_MAC_ADDR(pHdr80211->Addr1, pBssid); + COPY_MAC_ADDR(pHdr80211->Addr3, pDA); + } + else + { + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); + } + + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); +} + +VOID TDLS_SoftwareRecovery( + IN PRTMP_ADAPTER pAd) +{ + ULONG Now; + ULONG BPtoJiffies; + UINT32 Data; + + NdisGetSystemUpTime(&Now); + + BPtoJiffies = (((pAd->CommonCfg.BeaconPeriod * 1024 / 1000) * OS_HZ) / 1000); + + if (RTMP_TIME_AFTER(Now, pAd->StaCfg.LastBeaconRxTime + (3 * BPtoJiffies * pAd->StaCfg.DtimPeriod))) + { + UCHAR Value = 0; + UINT32 Data = 0; + UCHAR idx; + PRT_802_11_TDLS pTDLS = NULL; + PMAC_TABLE_ENTRY pMacEntry; + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + if (pTDLS->Valid && (pTDLS->Status >= TDLS_MODE_CONNECTED)) + { + break; + } + } + + if (idx >= MAX_NUM_OF_TDLS_ENTRY) + { + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + return; + } + + pAd->StaCfg.TdlsInfo.TdlsCurrentTargetChannel = pAd->CommonCfg.Channel; + + TDLS_DisableMacTxRx(pAd); + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, (pAd->CommonCfg.Channel + 2), FALSE); + AsicLockChannel(pAd, (pAd->CommonCfg.Channel + 2)); + + /* TX/RX Bandwidth control */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + /* RX : control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_WARN, ("A. %d. %ld @!\n", pAd->CommonCfg.Channel, (jiffies * 1000) / OS_HZ)); + } + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, (pAd->CommonCfg.Channel - 2), FALSE); + AsicLockChannel(pAd, (pAd->CommonCfg.Channel - 2)); + + /* TX/RX Bandwidth control */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + /* RX : control channel at upper */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_WARN, ("B. %d. %ld @!\n", pAd->CommonCfg.Channel, (jiffies * 1000) / OS_HZ)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* Must using 20MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel , FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel ); + + /* TX/RX Bandwidth control */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + /* TX : control channel at lower */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + /* RX : control channel at upper */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_WARN, ("%d... %ld @!\n", pAd->CommonCfg.Channel, (jiffies * 1000) / OS_HZ)); + } + + /* Enable MAC Tx/Rx to receive packet */ + TDLS_EnableMacTxRx(pAd); + + pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannel = pAd->CommonCfg.Channel; + pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannelBW = (pAd->CommonCfg.Channel == EXTCHA_NONE) ? (BW_20) : (BW_40); + + //RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + //AsicBBPReadWithRxChain(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + printk("1000.\n"); + } +} +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_chswitch_mng.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_chswitch_mng.c new file mode 100644 index 000000000..e49dd5aeb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_chswitch_mng.c @@ -0,0 +1,1473 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT + +#include +#include "rt_config.h" + +/* + ========================================================================== + Description: + tdls state machine init, including state transition and timer init + Parameters: + Sm - pointer to the dls state machine + Note: + The state machine looks like this + + TDLS_IDLE + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID TDLS_ChSwStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + PRT_802_11_TDLS pTDLS = NULL; + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MAX_TDLS_STATE, + (ULONG)MAX_TDLS_CHSW_MSG, (STATE_MACHINE_FUNC)Drop, TDLS_IDLE, TDLS_CHSW_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_CH_SWITCH_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeChannelSwitchAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_CH_SWITCH_RSP, (STATE_MACHINE_FUNC)TDLS_MlmeChannelSwitchRspAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_CH_SWITCH_REQ, (STATE_MACHINE_FUNC)TDLS_PeerChannelSwitchReqAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_CH_SWITCH_RSP, (STATE_MACHINE_FUNC)TDLS_PeerChannelSwitchRspAction); + + for (i = 0; i < MAX_NUMBER_OF_DLS_ENTRY; i++) + { + pAd->StaCfg.TdlsInfo.TDLSEntry[i].pAd = pAd; + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[i]; + + RTMPInitTimer(pAd, &pTDLS->ChannelSwitchTimer, + GET_TIMER_FUNCTION(TDLS_ChannelSwitchTimeAction), pTDLS, FALSE); + RTMPInitTimer(pAd, &pTDLS->ChannelSwitchTimeoutTimer, + GET_TIMER_FUNCTION(TDLS_ChannelSwitchTimeOutAction), pTDLS, FALSE); + } + + RTMPInitTimer(pAd, &pAd->StaCfg.TdlsInfo.TdlsDisableChannelSwitchTimer, + GET_TIMER_FUNCTION(TDLS_DisablePeriodChannelSwitchAction), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->StaCfg.TdlsInfo.TdlsPeriodGoOffChTimer, + GET_TIMER_FUNCTION(TDLS_BaseChExpired), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->StaCfg.TdlsInfo.TdlsPeriodGoBackBaseChTimer, + GET_TIMER_FUNCTION(TDLS_OffChExpired), pAd, FALSE); +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_BuildChannelSwitchRequest( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pPeerAddr, + IN USHORT ChSwitchTime, + IN USHORT ChSwitchTimeOut, + IN UCHAR TargetChannel, + IN UCHAR TargetChannelBW) +{ + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + PRT_802_11_TDLS pTDLS = NULL; + INT LinkId = 0xff; + + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_CHANNEL_SWITCH_REQUEST); + + /* Target Channel */ + TDLS_InsertTargetChannel(pAd, (pFrameBuf + *pFrameLen), pFrameLen, TargetChannel); + + /* Regulatory Class */ + TDLS_InsertRegulatoryClass(pAd, (pFrameBuf + *pFrameLen), pFrameLen, TargetChannel, TargetChannelBW); + + /* Secondary Channel Offset */ + if(TargetChannelBW != EXTCHA_NONE) + { + if (TargetChannel > 14) + { + if ((TargetChannel == 36) || (TargetChannel == 44) || (TargetChannel == 52) || + (TargetChannel == 60) || (TargetChannel == 100) || (TargetChannel == 108) || + (TargetChannel == 116) || (TargetChannel == 124) || (TargetChannel == 132) || + (TargetChannel == 149) || (TargetChannel == 157)) + { + TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, EXTCHA_ABOVE); + pTdlsControl->TdlsDesireChannelBW = EXTCHA_ABOVE; + + } + else if ((TargetChannel == 40) || (TargetChannel == 48) || (TargetChannel == 56) | + (TargetChannel == 64) || (TargetChannel == 104) || (TargetChannel == 112) || + (TargetChannel == 120) || (TargetChannel == 128) || (TargetChannel == 136) || + (TargetChannel == 153) || (TargetChannel == 161)) + { + TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, EXTCHA_BELOW); + pTdlsControl->TdlsDesireChannelBW = EXTCHA_BELOW; + } + } + else + { + UCHAR ExtCh; + UCHAR Dir = TargetChannelBW; + + ExtCh = TDLS_GetExtCh(TargetChannel, Dir); + + if (TDLS_IsValidChannel(pAd, ExtCh)) + { + TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, Dir); + pTdlsControl->TdlsDesireChannelBW = Dir; + } + else + { + Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + ExtCh = TDLS_GetExtCh(TargetChannel, Dir); + + if (TDLS_IsValidChannel(pAd, ExtCh)) + { + TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, Dir); + pTdlsControl->TdlsDesireChannelBW = Dir; + } + } + } + } + else + { + pTdlsControl->TdlsDesireChannelBW = EXTCHA_NONE; + } + + /* fill link identifier */ + LinkId = TDLS_SearchLinkId(pAd, pPeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("%s - can not find the LinkId!\n", __FUNCTION__)); + return; + } + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + if (pTDLS->bInitiator) + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pPeerAddr, pAd->CurrentAddress); + else + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pPeerAddr); + + /* Channel Switch Timing */ + TDLS_InsertChannelSwitchTimingIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ChSwitchTime, ChSwitchTimeOut); +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_BuildChannelSwitchResponse( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN USHORT ChSwitchTime, + IN USHORT ChSwitchTimeOut, + IN UINT16 ReasonCode) +{ + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_CHANNEL_SWITCH_RESPONSE); + + /* fill reason code */ + TDLS_InsertReasonCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ReasonCode); + + /* fill link identifier */ + if (pTDLS->bInitiator) + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr, pAd->CurrentAddress); + else + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); + + /* Channel Switch Timing */ + TDLS_InsertChannelSwitchTimingIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ChSwitchTime, ChSwitchTimeOut); +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_ChannelSwitchReqAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pPeerAddr, + IN UCHAR TargetChannel, + IN UCHAR TargetChannelBW) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + MAKE_802_3_HEADER(Header802_3, pPeerAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildChannelSwitchRequest(pAd, + pOutBuffer, + &FrameLen, + pPeerAddr, + TDLS_CHANNEL_SWITCH_TIME, + TDLS_CHANNEL_SWITCH_TIMEOUT, + TargetChannel, + TargetChannelBW); + + pEntry = MacTableLookup(pAd, pPeerAddr); + + if (pEntry && IS_ENTRY_TDLS(pEntry)) + { + pTDLS->ChannelSwitchCurrentState = TDLS_CHANNEL_SWITCH_WAIT_RSP; + + TDLS_SendChannelSwitchActionFrame(pAd, + pEntry, + Header802_3, + LENGTH_802_3, + pOutBuffer, + (UINT)FrameLen, + FALSE); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't find TDLS entry on Mac TABLE !!!!\n")); + } + + hex_dump("TDLS switch channel request send pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_ChannelSwitchRspAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN USHORT ChSwitchTime, + IN USHORT ChSwitchTimeOut, + IN UINT16 StatusCode, + IN UCHAR FrameType) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return NStatus; + } + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildChannelSwitchResponse(pAd, + pOutBuffer, + &FrameLen, + pTDLS, + ChSwitchTime, + ChSwitchTimeOut, + StatusCode); + + TDLS_SendChannelSwitchActionFrame(pAd, + &pAd->MacTab.Content[pTDLS->MacTabMatchWCID], + Header802_3, + LENGTH_802_3, + pOutBuffer, + (UINT)FrameLen, + FrameType); + + hex_dump("TDLS send channel switch response pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +VOID +TDLS_TriggerChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR DtimCount) +{ + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + PRT_802_11_TDLS pTdlsEntry = NULL; + BOOLEAN bCanDoChSwitch = FALSE; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + INT LinkId = 0xff; + + RTMP_SEM_LOCK(&pTdlsControl->TdlsChSwLock); + if (INFRA_ON(pAd) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (pTdlsControl->bDoingPeriodChannelSwitch) && + (pTdlsControl->bChannelSwitchInitiator)) + bCanDoChSwitch = TRUE; + RTMP_SEM_UNLOCK(&pTdlsControl->TdlsChSwLock); + + if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s - AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__)); + return; + } + + if (bCanDoChSwitch) + { + if (DtimCount == 0) + { + BOOLEAN TimerCancelled; + ULONG Now, Now1, Now2; + + DBGPRINT(RT_DEBUG_ERROR, ("101. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + NdisGetSystemUpTime(&Now); + + if (pTdlsControl->TdlsGoBackStartTime == 0) + Now2 = (pTdlsControl->TdlsActiveSwitchTime / 1000); + else + { + if (pTdlsControl->TdlsGoBackStartTime > Now) + { + Now2 = (pTdlsControl->TdlsActiveSwitchTime / 1000); + } + else + { + Now1 = Now - pTdlsControl->TdlsGoBackStartTime; + Now2 = ((Now1 * 1000) / OS_HZ); + } + } + + /* Drop not within my TDLS Table that created before ! */ + LinkId = TDLS_SearchLinkId(pAd, pTdlsControl->TdlsDesireChSwMacAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + RTMPCancelTimer(&pTdlsControl->TdlsPeriodGoBackBaseChTimer, &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR, ("%s() - can not find the LinkId!\n", __FUNCTION__)); + return; + } + + /* Point to the current Link ID */ + pTdlsEntry = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + if (pTdlsEntry->Valid && pTdlsEntry->bDoingPeriodChannelSwitch) + { + pTdlsControl->TdlsForcePowerSaveWithAP = TRUE; + + + if (Now2 >= (pTdlsControl->TdlsActiveSwitchTime / 1000)) + RtmpOsMsDelay(9); + else + RtmpOsMsDelay(((pTdlsControl->TdlsActiveSwitchTime / 1000) - Now2) + 9); + + TDLS_KickOutHwNullFrame(pAd, PWR_SAVE, 0); + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + RTMPSetTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, + ((pAd->StaCfg.DtimPeriod * pAd->CommonCfg.BeaconPeriod) - 5)); + + /* Build TDLS channel switch Request Frame */ + NStatus = TDLS_ChannelSwitchReqAction(pAd, + pTdlsEntry, + pTdlsEntry->MacAddr, + pTdlsControl->TdlsDesireChannel, + pTdlsControl->TdlsDesireChannelBW); + + if (NStatus != NDIS_STATUS_SUCCESS) + DBGPRINT(RT_DEBUG_ERROR,("%s() - Build Channel Switch Request Fail !!!\n", __FUNCTION__)); + else + pTdlsControl->TdlsChannelSwitchPairCount++; + } + } + } +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_TDLS_CH_SWITCH_STRUCT pChSwReq = NULL; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + PRT_802_11_TDLS pTDLS = NULL; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + INT LinkId = 0xff; + BOOLEAN TimerCancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + pChSwReq = (PMLME_TDLS_CH_SWITCH_STRUCT)Elem->Msg; + + if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s - AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__)); + return; + } + + if (INFRA_ON(pAd)) + { + /* Drop not within my TDLS Table that created before ! */ + LinkId = TDLS_SearchLinkId(pAd, pChSwReq->PeerMacAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("%s() - can not find the LinkId!\n", __FUNCTION__)); + return; + } + + /* Point to the current Link ID */ + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + pTdlsControl->TdlsForcePowerSaveWithAP = TRUE; + + TDLS_KickOutHwNullFrame(pAd, PWR_SAVE, 0); + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + RTMPSetTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, + ((pAd->StaCfg.DtimPeriod * pAd->CommonCfg.BeaconPeriod) - 5)); + + /* Build TDLS channel switch Request Frame */ + NStatus = TDLS_ChannelSwitchReqAction(pAd, + pTDLS, + pChSwReq->PeerMacAddr, + pChSwReq->TargetChannel, + pChSwReq->TargetChannelBW); + + if (NStatus != NDIS_STATUS_SUCCESS) + DBGPRINT(RT_DEBUG_ERROR,("%s() - Build Channel Switch Request Fail !!!\n", __FUNCTION__)); + else + pTdlsControl->TdlsChannelSwitchPairCount++; + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("%s - TDLS only support infra mode !!!\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeChannelSwitchRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_TDLS_CH_SWITCH_STRUCT pMlmeChSwitchRsp = NULL; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + PRT_802_11_TDLS pTdls = NULL; + INT LinkId = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + pMlmeChSwitchRsp = (PMLME_TDLS_CH_SWITCH_STRUCT)Elem->Msg; + + if (INFRA_ON(pAd)) + { + // Drop not within my TDLS Table that created before ! + LinkId = TDLS_SearchLinkId(pAd, pMlmeChSwitchRsp->PeerMacAddr); + + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - can not find the LinkId!\n", __FUNCTION__)); + return; + } + + /* Point to the current Link ID */ + pTdls = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + /* Build TDLS channel switch Request Frame */ + NStatus = TDLS_ChannelSwitchRspAction(pAd, + pTdls, + pTdls->ChSwitchTime, + pTdls->ChSwitchTimeout, + MLME_SUCCESS, + RTMP_TDLS_SPECIFIC_NOACK); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - Build Channel Switch Response Fail !!!\n", __FUNCTION__)); + } + else + { + RtmpusecDelay(300); + NdisGetSystemUpTime(&pAd->StaCfg.TdlsInfo.TdlsGoBackStartTime); + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + TDLS_DisablePktChannel(pAd, FIFO_HCCA); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("%s - TDLS only support infra mode !!!\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerChannelSwitchReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_TDLS pTDLS = NULL; + INT LinkId = 0xff; + UCHAR PeerAddr[MAC_ADDR_LEN]; + BOOLEAN IsInitator; + UCHAR TargetChannel; + UCHAR RegulatoryClass; + UCHAR NewExtChannelOffset = 0xff; + USHORT PeerChSwitchTime; + USHORT PeerChSwitchTimeOut; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + USHORT StatusCode = MLME_SUCCESS; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + /* Not TDLS Capable, ignore it */ + if (!IS_TDLS_SUPPORT(pAd)) + return; + + if (!INFRA_ON(pAd)) + return; + + if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_OFF,("%s - AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__)); + return; + } + + hex_dump("TDLS peer channel switch request receive pack", Elem->Msg, Elem->MsgLen); + + if (!PeerTdlsChannelSwitchReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + PeerAddr, + &IsInitator, + &TargetChannel, + &RegulatoryClass, + &NewExtChannelOffset, + &PeerChSwitchTime, + &PeerChSwitchTimeOut)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n", + __FUNCTION__, PRINT_MAC(PeerAddr))); + return; + } + + if (RtmpPktPmBitCheck(pAd)) + { + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); + TDLS_SendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + } + + DBGPRINT(RT_DEBUG_WARN, ("%s(): from %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + __FUNCTION__, PRINT_MAC(PeerAddr))); + + DBGPRINT(RT_DEBUG_ERROR, ("300. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + /* Drop not within my TDLS Table that created before ! */ + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n", + __FUNCTION__, PRINT_MAC(PeerAddr))); + return; + } + + if (pTdlsControl->bChannelSwitchInitiator == FALSE) + { + pTdlsControl->TdlsForcePowerSaveWithAP = TRUE; + TDLS_KickOutHwNullFrame(pAd, PWR_SAVE, 0); + } + + /* Point to the current Link ID */ + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + if (TDLS_CHANNEL_SWITCH_TIME >= PeerChSwitchTime) + PeerChSwitchTime = TDLS_CHANNEL_SWITCH_TIME; + + if (TDLS_CHANNEL_SWITCH_TIMEOUT >= PeerChSwitchTimeOut) + PeerChSwitchTimeOut = TDLS_CHANNEL_SWITCH_TIMEOUT; + + { + UINT32 macCfg, TxCount; + UINT32 MTxCycle; + UCHAR TdlsFrameType = 0; + + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + + + if (TargetChannel != pAd->CommonCfg.Channel) + TdlsFrameType = RTMP_TDLS_SPECIFIC_WAIT_ACK; + else + TdlsFrameType = (RTMP_TDLS_SPECIFIC_WAIT_ACK + RTMP_TDLS_SPECIFIC_PKTQ_HCCA); + + NStatus = TDLS_ChannelSwitchRspAction(pAd, + pTDLS, + PeerChSwitchTime, + PeerChSwitchTimeOut, + StatusCode, + TdlsFrameType); + + for (MTxCycle = 0; MTxCycle < 50; MTxCycle++) + { + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + TxCount = macCfg & 0x0000ffff; + if (TxCount > 0) + { + DBGPRINT(RT_DEBUG_WARN, ("MTxCycle = %d, %ld !!!\n", MTxCycle, (jiffies * 1000) / OS_HZ)); + break; + } + else + RtmpusecDelay(1000); + } + + if (MTxCycle >= 50) + { + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + + NStatus = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("%s() - TDLS Transmit Channel Switch Response Fail !!!\n", __FUNCTION__)); + } + } + + if (NStatus == NDIS_STATUS_SUCCESS) + { + if (TargetChannel != pAd->CommonCfg.Channel) + { + BOOLEAN TimerCancelled; + + pTdlsControl->TdlsDesireChannel = TargetChannel; + + if (NewExtChannelOffset != 0) + pTdlsControl->TdlsDesireChannelBW = NewExtChannelOffset; + else + pTdlsControl->TdlsDesireChannelBW = EXTCHA_NONE; + + pTDLS->ChSwitchTime = PeerChSwitchTime; + pTdlsControl->TdlsActiveSwitchTime = PeerChSwitchTime; + pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut; + pTdlsControl->TdlsActiveSwitchTimeOut = PeerChSwitchTimeOut; + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + + /* Cancel the timer since the received packet to me. */ + RTMPCancelTimer(&pTDLS->ChannelSwitchTimeoutTimer, &TimerCancelled); + RTMPSetTimer(&pTDLS->ChannelSwitchTimeoutTimer, (PeerChSwitchTimeOut / 1000)); + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + pTDLS->bDoingPeriodChannelSwitch = TRUE; + pTdlsControl->bChannelSwitchWaitSuccess = TRUE; + pTdlsControl->bDoingPeriodChannelSwitch = TRUE; + + if (RTDebugLevel < RT_DEBUG_WARN) + RtmpusecDelay(300); + else + DBGPRINT(RT_DEBUG_WARN, ("1041. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + TDLS_DisablePktChannel(pAd, FIFO_EDCA); + + TDLS_InitChannelRelatedValue(pAd, FALSE, TargetChannel, NewExtChannelOffset); + + } + else + { + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->TdlsForcePowerSaveWithAP = FALSE; + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RtmpusecDelay(300); + + TDLS_DisablePktChannel(pAd, FIFO_HCCA); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerChannelSwitchRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_TDLS pTDLS = NULL; + INT LinkId = 0xff; + UCHAR PeerAddr[MAC_ADDR_LEN]; + BOOLEAN TimerCancelled; + USHORT PeerChSwitchTime; + USHORT PeerChSwitchTimeOut; + USHORT StatusCode = MLME_SUCCESS; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + if (!INFRA_ON(pAd)) + return; + + /* Not TDLS Capable, ignore it */ + if (!IS_TDLS_SUPPORT(pAd)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s() - from %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + __FUNCTION__, PRINT_MAC(PeerAddr))); + + hex_dump("TDLS peer channel switch response receive pack", Elem->Msg, Elem->MsgLen); + + if (!PeerTdlsChannelSwitchRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + PeerAddr, + &StatusCode, + &PeerChSwitchTime, + &PeerChSwitchTimeOut)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - Sanity Check Fail !!!\n", __FUNCTION__)); + return; + } + + /* Drop not within my TDLS Table that created before ! */ + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - can not find the MAC on TDLS Table !!!\n", __FUNCTION__)); + return; + } + + /* Point to the current Link ID */ + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + if ((pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE) && + (StatusCode == MLME_REQUEST_DECLINED)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - received a failed StatusCode = %d on Unsolicited response !!!\n", + __FUNCTION__, StatusCode)); + return; + } + + if (StatusCode == MLME_REQUEST_DECLINED) + { + if ((pTdlsControl->TdlsChannelSwitchRetryCount > 0) && + (pTDLS->bDoingPeriodChannelSwitch) && + (pTdlsControl->bDoingPeriodChannelSwitch)) + { + pTdlsControl->TdlsChannelSwitchRetryCount--; + + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - received a failed StatusCode = %d re-try again !!!\n", + __FUNCTION__, StatusCode)); + } + else + { + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->TdlsForcePowerSaveWithAP = FALSE; + } + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + + DBGPRINT(RT_DEBUG_ERROR,("%s() - received a failed StatusCode = %d !!!\n", + __FUNCTION__, StatusCode )); + return; + } + + if (StatusCode == MLME_SUCCESS) + { + if (pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE) + { + if (pTdlsControl->bChannelSwitchInitiator) + { + DBGPRINT(RT_DEBUG_TRACE,("%s() - i am Initiator !!!\n", __FUNCTION__)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("%s() - i am responder!!!\n", __FUNCTION__)); + } + + //if (pAd->LatchRfRegs.Channel != pAd->CommonCfg.CentralChannel) + if (pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannel != pAd->CommonCfg.Channel) + { + DBGPRINT(RT_DEBUG_WARN, ("106. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + NdisGetSystemUpTime(&pTdlsControl->TdlsGoBackStartTime); + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + TDLS_DisablePktChannel(pAd, FIFO_HCCA); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + } + } + else + { + if (pTdlsControl->TdlsDesireChannel != pAd->CommonCfg.Channel) + { + if (pTdlsControl->bChannelSwitchInitiator) + { + pTdlsControl->TdlsChannelSwitchPairCount--; + pTdlsControl->TdlsChannelSwitchRetryCount = 10; + + if (TDLS_CHANNEL_SWITCH_TIME >= PeerChSwitchTime) + PeerChSwitchTime = TDLS_CHANNEL_SWITCH_TIME; + + if (TDLS_CHANNEL_SWITCH_TIMEOUT >= PeerChSwitchTimeOut) + PeerChSwitchTimeOut = TDLS_CHANNEL_SWITCH_TIMEOUT; + + pTDLS->ChSwitchTime = PeerChSwitchTime; + pTdlsControl->TdlsActiveSwitchTime = PeerChSwitchTime; + pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut; + pTdlsControl->TdlsActiveSwitchTimeOut = PeerChSwitchTimeOut; + pTDLS->ChannelSwitchCurrentState = TDLS_CHANNEL_SWITCH_NONE; + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + //Cancel the timer since the received packet to me. + RTMPCancelTimer(&pTDLS->ChannelSwitchTimer, &TimerCancelled); + RTMPSetTimer(&pTDLS->ChannelSwitchTimer, (PeerChSwitchTime / 1000)); + NdisGetSystemUpTime(&pTdlsControl->TdlsChSwSilenceTime); + if (RTDebugLevel < RT_DEBUG_WARN) + RtmpusecDelay(300); + else + DBGPRINT(RT_DEBUG_ERROR, ("104. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + TDLS_DisablePktChannel(pAd, FIFO_EDCA); + + TDLS_InitChannelRelatedValue(pAd, FALSE, pTdlsControl->TdlsDesireChannel, pTdlsControl->TdlsDesireChannelBW); + } + } + else + { + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->bDoingPeriodChannelSwitch = FALSE; + pTdlsControl->TdlsForcePowerSaveWithAP = FALSE; + + if (pTdlsControl->bChannelSwitchInitiator) + { + pTdlsControl->bChannelSwitchInitiator = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("%s() - i am channel switch Initiator !!!\n", __FUNCTION__)); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - i am channel switch responder!!!\n", __FUNCTION__)); + } + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + + //if (pAd->LatchRfRegs.Channel != pAd->CommonCfg.CentralChannel) + if (pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannel != pAd->CommonCfg.Channel) + { + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + TDLS_DisablePktChannel(pAd, FIFO_HCCA); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + } + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +VOID +TDLS_ForceSendChannelSwitchResponse( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS) +{ + DBGPRINT(RT_DEBUG_TRACE,("===> %s() \n", __FUNCTION__)); + + if (INFRA_ON(pAd)) + { + /* Build TDLS channel switch Response Frame */ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildChannelSwitchResponse(pAd, + pOutBuffer, + &FrameLen, + pTDLS, + pTDLS->ChSwitchTime, + pTDLS->ChSwitchTimeout, + MLME_SUCCESS); + TDLS_SendChannelSwitchActionFrame(pAd, + &pAd->MacTab.Content[pTDLS->MacTabMatchWCID], + Header802_3, + LENGTH_802_3, + pOutBuffer, + (UINT)FrameLen, + RTMP_TDLS_SPECIFIC_NOACK); + if (NStatus != NDIS_STATUS_SUCCESS) + DBGPRINT(RT_DEBUG_ERROR,("%s - Build Channel Switch Response Fail !!!\n", __FUNCTION__)); + else + hex_dump("TDLS send channel switch response pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("%s - TDLS only support infra mode !!!\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE,("<=== %s() \n", __FUNCTION__)); + + return; +} + +VOID +TDLS_SendChannelSwitchActionFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN UCHAR FrameType) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status; + + DBGPRINT(RT_DEBUG_TRACE,("===> %s() \n", __FUNCTION__)); + + if ((!pEntry) || (!IS_ENTRY_TDLS(pEntry))) + return; + + do { + /* build a NDIS packet*/ + Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + break; + + + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value*/ + if(pEntry->apidx != 0) + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx); + + RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); + RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); + + if (FrameType > 0) + RTMP_SET_TDLS_SPECIFIC_PACKET(pPacket, FrameType); + else + RTMP_SET_TDLS_SPECIFIC_PACKET(pPacket, 0); + + /* send out the packet*/ + Status = STASendPacket(pAd, pPacket); + if (Status == NDIS_STATUS_SUCCESS) + { + UCHAR Index; + + /* Dequeue one frame from TxSwQueue0..3 queue and process it*/ + /* There are three place calling dequeue for TX ring.*/ + /* 1. Here, right after queueing the frame.*/ + /* 2. At the end of TxRingTxDone service routine.*/ + /* 3. Upon NDIS call RTMPSendPackets*/ + if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + for(Index = 0; Index < 5; Index ++) + if(pAd->TxSwQueue[Index].Number > 0) + RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS); + } + } + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE,("<=== %s() \n", __FUNCTION__)); + + return; +} + +VOID TDLS_OffChExpired( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + UCHAR idx = 0; + ULONG Now, GapJiffies, BPtoJiffies, CurTime; + + if ((pAd != NULL) && INFRA_ON(pAd)) + { + if (pAd->StaCfg.DtimPeriod > 1) + { + NdisGetSystemUpTime(&Now); + BPtoJiffies = (((pAd->CommonCfg.BeaconPeriod * 1024 / 1000) * OS_HZ) / 1000); + + if (RTMP_TIME_AFTER(pAd->StaCfg.LastBeaconRxTime + (BPtoJiffies * pAd->StaCfg.DtimPeriod), Now)) + { + GapJiffies = (pAd->StaCfg.LastBeaconRxTime + (pAd->StaCfg.DtimPeriod* BPtoJiffies) - Now); + CurTime = (GapJiffies * 1000) / OS_HZ; + + if (CurTime >= (pAd->CommonCfg.BeaconPeriod + 20)) + { + RTMPModTimer(&pTdlsControl->TdlsPeriodGoBackBaseChTimer, pAd->CommonCfg.BeaconPeriod); + goto done; + } + else + { + if (CurTime > 20) + { + RTMPModTimer(&pTdlsControl->TdlsPeriodGoBackBaseChTimer, CurTime - 20); + goto done; + } + } + } + } + + //if (pAd->LatchRfRegs.Channel != pAd->CommonCfg.CentralChannel) + if (pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannel != pAd->CommonCfg.Channel) + { + BOOLEAN TimerCancelled; + + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + + if (pTdlsControl->bChannelSwitchInitiator) + DBGPRINT(RT_DEBUG_WARN, ("200. Initiator %ld !!!\n", (jiffies * 1000) / OS_HZ)); + else + DBGPRINT(RT_DEBUG_WARN, ("201. Responder %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + RTMPCancelTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, &TimerCancelled); + RTMPSetTimer(&pTdlsControl->TdlsDisableChannelSwitchTimer, ((pAd->StaCfg.DtimPeriod * pAd->CommonCfg.BeaconPeriod) - 11)); + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + PRT_802_11_TDLS pTdlsEntry = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (pTdlsEntry->Valid) + { + TDLS_ForceSendChannelSwitchResponse(pAd, pTdlsEntry); + } + } + + RtmpusecDelay(4000); + NdisGetSystemUpTime(&pTdlsControl->TdlsGoBackStartTime); + + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + + TDLS_DisablePktChannel(pAd, FIFO_HCCA); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + } + else + { + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + DBGPRINT(RT_DEBUG_INFO, ("I am lready on Base Channel :(%d) !!!\n", pAd->CommonCfg.Channel)); + } + } + +done: + + return; +} + +VOID TDLS_BaseChExpired( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + PRT_802_11_TDLS pTdlsEntry = NULL; + + if ((pAd != NULL) && INFRA_ON(pAd)) + { + UCHAR idx = 0; + MLME_TDLS_CH_SWITCH_STRUCT TdlsChSwitch; + + if (pTdlsControl->bChannelSwitchInitiator == FALSE) + return; + + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTdlsEntry = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (pTdlsEntry->Valid && pTdlsEntry->bDoingPeriodChannelSwitch) + { + NdisZeroMemory(&TdlsChSwitch, sizeof(MLME_TDLS_CH_SWITCH_STRUCT)); + COPY_MAC_ADDR(TdlsChSwitch.PeerMacAddr, pTdlsEntry->MacAddr); + TdlsChSwitch.TargetChannel = pTdlsControl->TdlsDesireChannel; + TdlsChSwitch.TargetChannelBW = pTdlsControl->TdlsDesireChannelBW; + + DBGPRINT(RT_DEBUG_WARN, ("102. %d,%d,%ld !!!\n", + pTdlsControl->TdlsDesireChannel, pTdlsControl->TdlsDesireChannelBW, (jiffies * 1000) / OS_HZ)); + + MlmeEnqueue(pAd, + TDLS_CHSW_STATE_MACHINE, + MT2_MLME_TDLS_CH_SWITCH_REQ, + sizeof(MLME_TDLS_CH_SWITCH_STRUCT), + &TdlsChSwitch, + 0); + + RTMP_MLME_HANDLER(pAd); + } + } + } +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_ChannelSwitchTimeAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)FunctionContext; + PRTMP_ADAPTER pAd = pTDLS->pAd; + UINT32 macCfg, TxCount; + UINT32 MTxCycle; + UINT16 MaxWaitingTime; + ULONG Now, RealSwitchTime; + + DBGPRINT(RT_DEBUG_TRACE, ("Channel switch procedure for (%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pTDLS->MacAddr))); + + NdisGetSystemUpTime(&Now); + + RealSwitchTime = ((Now - pAd->StaCfg.TdlsInfo.TdlsChSwSilenceTime) * 1000) / OS_HZ; + + if (RealSwitchTime < (pTDLS->ChSwitchTime / 1000)) + RtmpOsMsDelay((pTDLS->ChSwitchTime / 1000) - RealSwitchTime); + + TDLS_EnableMacTx(pAd); + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + RtmpusecDelay(2000); + + DBGPRINT(RT_DEBUG_ERROR, ("105. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + TDLS_SendOutNullFrame(pAd, &pAd->MacTab.Content[pTDLS->MacTabMatchWCID], TRUE, TRUE); + + MaxWaitingTime = (pTDLS->ChSwitchTimeout - pTDLS->ChSwitchTime); + for (MTxCycle = 0; MTxCycle < MaxWaitingTime; MTxCycle+= 1000) + { + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + TxCount = macCfg & 0x0000ffff; + + if (TxCount > 0) + break; + else + RtmpusecDelay(1000); + } + + if (MTxCycle == MaxWaitingTime) + { + DBGPRINT(RT_DEBUG_ERROR, ("24. %ld @!!!\n", (jiffies * 1000) / OS_HZ)); + + NdisGetSystemUpTime(&pAd->StaCfg.TdlsInfo.TdlsGoBackStartTime); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + } + else + TDLS_EnablePktChannel(pAd, FIFO_HCCA); + + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_ChannelSwitchTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)FunctionContext; + PRTMP_ADAPTER pAd = pTDLS->pAd; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + + DBGPRINT(RT_DEBUG_WARN, + ("Channel switch timeout , terminate the channel switch procedure (%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pTDLS->MacAddr))); + + DBGPRINT(RT_DEBUG_ERROR, ("Channel switch timeout\n")); + + pTdlsControl->bChannelSwitchWaitSuccess = FALSE; + pTdlsControl->bDoingPeriodChannelSwitch = FALSE; + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + + return; +} + +VOID +TDLS_DisablePeriodChannelSwitchAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PTDLS_STRUCT pTdlsControl = &pAd->StaCfg.TdlsInfo; + + if (!(pAd->StaCfg.TdlsInfo.bChannelSwitchInitiator)) + { + pTdlsControl->bChannelSwitchInitiator = FALSE; + pTdlsControl->bDoingPeriodChannelSwitch = FALSE; + } + + pTdlsControl->TdlsForcePowerSaveWithAP = FALSE; + + if (pAd->StaCfg.TdlsInfo.TdlsAsicOperateChannel != pAd->CommonCfg.Channel) + { + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + TDLS_DisablePktChannel(pAd, FIFO_HCCA); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, TRUE, pAd->CommonCfg.Channel, EXTCHA_NONE); + } + +#ifdef RTMP_MAC_PCI + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); +#endif /* RTMP_MAC_PCI */ + pAd->StaCfg.TdlsInfo.TdlsCurrentTargetChannel = pAd->CommonCfg.Channel; +#ifdef RTMP_MAC_PCI + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsInitChannelLock); +#endif /* RTMP_MAC_PCI */ + + TDLS_EnableMacTxRx(pAd); + TDLS_KickOutHwNullFrame(pAd, PWR_ACTIVE, 0); + TDLS_EnablePktChannel(pAd, FIFO_HCCA | FIFO_EDCA); + RTMP_CLEAR_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE); + RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev); + + return; +} +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_ctrl.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_ctrl.c new file mode 100644 index 000000000..b09719f93 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_ctrl.c @@ -0,0 +1,34 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT + +#include "rt_config.h" +//#include "dot11r_ft.h" + + +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_link_mng.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_link_mng.c new file mode 100644 index 000000000..b6413fbe4 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_link_mng.c @@ -0,0 +1,3770 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT + +#include "rt_config.h" + +UCHAR TdlsZeroSsid[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}; + +UCHAR CipherSuiteTDLSWpa2PskAes[] = { + 0x30, // RSN IE + 0x14, // Length + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x07, // no group cipher + 0x01, 0x00, // number of pairwise + 0x00, 0x0f, 0xAC, 0x04, // unicast, AES + 0x01, 0x00, // number of authentication method + 0x00, 0x0f, 0xAC, TDLS_AKM_SUITE_PSK, // TDLS authentication + 0x00, 0x02, // RSN capability, peer key enabled + }; +UCHAR CipherSuiteTDLSLen = sizeof(CipherSuiteTDLSWpa2PskAes)/ sizeof(UCHAR); + +/* + ========================================================================== + Description: + dls state machine init, including state transition and timer init + Parameters: + Sm - pointer to the dls state machine + Note: + The state machine looks like this + + DLS_IDLE + MT2_MLME_DLS_REQUEST MlmeDlsReqAction + MT2_PEER_DLS_REQUEST PeerDlsReqAction + MT2_PEER_DLS_RESPONSE PeerDlsRspAction + MT2_MLME_DLS_TEARDOWN MlmeTearDownAction + MT2_PEER_DLS_TEARDOWN PeerTearDownAction + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID TDLS_StateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + PRT_802_11_TDLS pTDLS = NULL; + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MAX_TDLS_STATE, + (ULONG)MAX_TDLS_MSG, (STATE_MACHINE_FUNC)Drop, TDLS_IDLE, TDLS_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_SETUP_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeSetupReqAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_SETUP_REQ, (STATE_MACHINE_FUNC)TDLS_PeerSetupReqAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_SETUP_RSP, (STATE_MACHINE_FUNC)TDLS_PeerSetupRspAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_SETUP_CONF,(STATE_MACHINE_FUNC)TDLS_PeerSetupConfAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_TEAR_DOWN, (STATE_MACHINE_FUNC)TDLS_MlmeTearDownAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_TEAR_DOWN, (STATE_MACHINE_FUNC)TDLS_PeerTearDownAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_DISCOVER_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeDiscoveryReqAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_DISCOVER_REQ, (STATE_MACHINE_FUNC)TDLS_PeerDiscoveryReqAction); +#ifdef WFD_SUPPORT + StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_TUNNELED_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeTunneledReqAction); + StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_TUNNELED_REQ, (STATE_MACHINE_FUNC)TDLS_PeerTunneledReqRspAction); +#endif /* WFD_SUPPORT */ + + for (i = 0; i < MAX_NUMBER_OF_DLS_ENTRY; i++) + { + pAd->StaCfg.TdlsInfo.TDLSEntry[i].pAd = pAd; + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[i]; + + RTMPInitTimer(pAd, &pTDLS->Timer, GET_TIMER_FUNCTION(TDLS_LinkTimeoutAction), pTDLS, FALSE); + } + +#ifdef UAPSD_SUPPORT + TDLS_UAPSDP_Init(pAd, Sm); +#endif /* UAPSD_SUPPORT */ +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_BuildSetupRequest( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS) +{ + ULONG Timeout = TDLS_TIMEOUT; + BOOLEAN TimerCancelled; + + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_REQUEST); + + /* fill Dialog Token */ + pAd->StaCfg.TdlsInfo.TdlsDialogToken++; + if (pAd->StaCfg.TdlsInfo.TdlsDialogToken == 0) + pAd->StaCfg.TdlsInfo.TdlsDialogToken++; + + pTDLS->Token = pAd->StaCfg.TdlsInfo.TdlsDialogToken; + TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token); + + // fill capability + TDLS_InsertCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill support rate + TDLS_InsertSupportRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill country + TDLS_InsertCountryIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill ext rate + TDLS_InsertExtRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill support channels + TDLS_InsertSupportChannelIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill RSN if security is not NONE + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + UCHAR CipherTmp[64] = {0}; + UCHAR CipherTmpLen = 0; + ULONG tmp; + + // RSNIE (7.3.2.25) + CipherTmpLen = CipherSuiteTDLSLen; + NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); + + // Insert RSN_IE to outgoing frame + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp, + CipherTmpLen, &CipherTmp, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + tmp; + } + + // fill Extended Capabilities (7.3.2.27) + TDLS_InsertExtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill Qos Capability + //TDLS_InsertQosCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // TPK Handshake if RSNA Enabled + // Pack TPK Message 1 here! + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + FT_FTIE FtIe; + UINT32 KeyLifetime = pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime; // sec + UCHAR Length; + + // FTIE (7.3.2.48) + NdisZeroMemory(&FtIe, sizeof(FtIe)); + Length = sizeof(FtIe); + + // generate SNonce + GenRandom(pAd, pAd->CurrentAddress, FtIe.SNonce); + hex_dump("TDLS - Generate SNonce ", FtIe.SNonce, 32); + NdisMoveMemory(pTDLS->SNonce, FtIe.SNonce, 32); + + TDLS_InsertFTIE(pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + Length, + FtIe.MICCtr, + FtIe.MIC, + FtIe.ANonce, + FtIe.SNonce); + + // Timeout Interval (7.3.2.49) + TDLS_InsertTimeoutIntervalIE(pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + 2, /* key lifetime interval */ + KeyLifetime); + + pTDLS->KeyLifetime = KeyLifetime; + } + + // fill Supported Regulatory Classes + TDLS_SupportedRegulatoryClasses(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + +#ifdef DOT11_N_SUPPORT + // fill HT Capability + TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill 20/40 BSS Coexistence (7.3.2.61) +#ifdef DOT11N_DRAFT3 + TDLS_InsertBSSCoexistenceIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + /* fill link identifier */ + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); + + // fill WMM + TDLS_InsertWMMIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, TRUE); + +#ifdef WFD_SUPPORT + { + ULONG WfdIeLen = 0, WfdIeBitmap; + + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_LOCAL_IP_ADDR); + WfdMakeWfdIE(pAd, WfdIeBitmap, (pFrameBuf + *pFrameLen), &WfdIeLen); + *pFrameLen += WfdIeLen; + } +#endif /* WFD_SUPPORT */ + + // ==>> Set sendout timer + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + RTMPSetTimer(&pTDLS->Timer, Timeout); + + // ==>> State Change + pTDLS->Status = TDLS_MODE_WAIT_RESPONSE; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_BuildSetupResponse( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode) +{ + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_RESPONSE); + + /* fill status code */ + TDLS_InsertStatusCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, StatusCode); + + /* fill Dialog Token */ + TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token); + + if (StatusCode == MLME_SUCCESS) + { + // fill capability + TDLS_InsertCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill support rate + TDLS_InsertSupportRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill country + TDLS_InsertCountryIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill ext rate + TDLS_InsertExtRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill support channels + TDLS_InsertSupportChannelIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill Qos Capability + //TDLS_InsertQosCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + + // fill RSN + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + ULONG tmp; + + // RSNIE (7.3.2.25) + // Insert RSN_IE of the Peer TDLS to outgoing frame + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp, + RsnLen, pRsnIe, + END_OF_ARGS); + *pFrameLen = *pFrameLen + tmp; + } + + // fill Extended Capabilities (7.3.2.27) + TDLS_InsertExtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill WMM + TDLS_InsertWMMIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen,TRUE); + + // TPK Handshake if RSNA Enabled + // Pack TPK Message 2 here! + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + FT_FTIE *ft; + UINT key_len = 16; + + // FTIE (7.3.2.48) + // Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) + + // point to the element of IE + ft = (FT_FTIE *)(pFTIe + 2); + // generate ANonce + GenRandom(pAd, pAd->CurrentAddress, ft->ANonce); + hex_dump("TDLS - Generate ANonce ", ft->ANonce, 32); + // set MIC field to zero before MIC calculation + NdisZeroMemory(ft->MIC, 16); + // copy SNonce from peer TDLS + NdisMoveMemory(ft->SNonce, pTDLS->SNonce, 32); + // copy ANonce to TDLS entry + NdisMoveMemory(pTDLS->ANonce, ft->ANonce, 32); + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // Derive TPK-KCK for MIC key, TPK-TK for direct link data + TDLS_FTDeriveTPK( + pTDLS->MacAddr, /* MAC Address of Initiator */ + pAd->CurrentAddress, /* I am Responder */ + pTDLS->ANonce, + pTDLS->SNonce, + pAd->CommonCfg.Bssid, + key_len, + pTDLS->TPK, + pTDLS->TPKName); + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //////////////////////////////////////////////////////////////////////// + // The MIC field of FTIE shall be calculated on the concatenation, in the following order, of + // 1. MAC_I (6 bytes) + // 2. MAC_R (6 bytes) + // 3. Transaction Sequence = 2 (1 byte) + // 4. Link Identifier (20 bytes) + // 5. RSN IE without the IE header (20 bytes) + // 6. Timeout Interval IE (7 bytes) + // 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) + { + UCHAR content[512]; + ULONG c_len = 0; + ULONG tmp_len = 0; + UCHAR Seq = 2; + UCHAR mic[16]; + UCHAR LinkIdentifier[20]; + UINT tmp_aes_len = 0; + + NdisZeroMemory(LinkIdentifier, 20); + LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; + LinkIdentifier[1] = 18; + NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); + NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6); + NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6); + + NdisZeroMemory(mic, sizeof(mic)); + + /* make a header frame for calculating MIC. */ + MakeOutgoingFrame(content, &tmp_len, + MAC_ADDR_LEN, pTDLS->MacAddr, + MAC_ADDR_LEN, pAd->CurrentAddress, + 1, &Seq, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Link Identifier */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 20, LinkIdentifier, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate RSNIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + RsnLen, pRsnIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Timeout Interval IE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 7, pTIIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate FTIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + (sizeof(FT_FTIE) + 2), pFTIe, + END_OF_ARGS); + c_len += tmp_len; + + /* Calculate MIC */ + //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); + + /* Compute AES-128-CMAC over the concatenation */ + tmp_aes_len = AES_KEY128_LENGTH; + AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); + + // Fill Mic to ft struct + NdisMoveMemory(ft->MIC, mic, 16); + + } + //////////////////////////////////////////////////////////////////////// + + // Insert FT_IE to outgoing frame + TDLS_InsertFTIE( + pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + sizeof(FT_FTIE), + ft->MICCtr, + ft->MIC, + ft->ANonce, + ft->SNonce); + + // Timeout Interval (7.3.2.49) + // Insert TI_IE to outgoing frame + TDLS_InsertTimeoutIntervalIE( + pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + 2, /* key lifetime interval */ + pTDLS->KeyLifetime); + } + + // fill Supported Regulatory Classes + TDLS_SupportedRegulatoryClasses(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + +#ifdef DOT11_N_SUPPORT + // fill HT Capability + TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + + // fill 20/40 BSS Coexistence (7.3.2.61) +#ifdef DOT11N_DRAFT3 + TDLS_InsertBSSCoexistenceIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + /* fill link identifier */ + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr, pAd->CurrentAddress); + +#ifdef WFD_SUPPORT + { + ULONG WfdIeLen = 0, WfdIeBitmap; + + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_LOCAL_IP_ADDR); + WfdMakeWfdIE(pAd, WfdIeBitmap, (pFrameBuf + *pFrameLen), &WfdIeLen); + *pFrameLen += WfdIeLen; + } +#endif /* WFD_SUPPORT */ + + } +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_BuildSetupConfirm( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode) +{ + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_CONFIRM); + + /* fill status code */ + TDLS_InsertStatusCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, StatusCode); + + /* fill Dialog Token */ + TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token); + + // fill Qos Capability + //TDLS_InsertEDCAParameterSetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS); + + // TPK Handshake if RSNA Enabled + // Pack TPK Message 3 here! + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + FT_FTIE *ft; + ULONG tmp; + + // RSNIE (7.3.2.25) + // Insert RSN_IE of the Peer TDLS to outgoing frame + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp, + RsnLen, pRsnIe, + END_OF_ARGS); + *pFrameLen = *pFrameLen + tmp; + + + // FTIE (7.3.2.48) + // Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) + + // point to the element of IE + ft = (FT_FTIE *)(pFTIe + 2); + // set MIC field to zero before MIC calculation + NdisZeroMemory(ft->MIC, 16); + + //////////////////////////////////////////////////////////////////////// + // The MIC field of FTIE shall be calculated on the concatenation, in the following order, of + // 1. MAC_I (6 bytes) + // 2. MAC_R (6 bytes) + // 3. Transaction Sequence = 2 (1 byte) + // 4. Link Identifier (20 bytes) + // 5. RSN IE without the IE header (20 bytes) + // 6. Timeout Interval IE (7 bytes) + // 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) + { + UCHAR content[512]; + ULONG c_len = 0; + ULONG tmp_len = 0; + UCHAR Seq = 3; + UCHAR mic[16]; + UCHAR LinkIdentifier[20]; + UINT tmp_aes_len = 0; + + NdisZeroMemory(LinkIdentifier, 20); + LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; + LinkIdentifier[1] = 18; + NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); + NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6); + NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6); + + NdisZeroMemory(mic, sizeof(mic)); + + /* make a header frame for calculating MIC. */ + MakeOutgoingFrame(content, &tmp_len, + MAC_ADDR_LEN, pAd->CurrentAddress, + MAC_ADDR_LEN, pTDLS->MacAddr, + 1, &Seq, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Link Identifier */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 20, LinkIdentifier, + END_OF_ARGS); + c_len += tmp_len; + + + /* concatenate RSNIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + RsnLen, pRsnIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Timeout Interval IE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 7, pTIIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate FTIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + (sizeof(FT_FTIE) + 2), pFTIe, + END_OF_ARGS); + c_len += tmp_len; + + /* Calculate MIC */ + //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); + + /* Compute AES-128-CMAC over the concatenation */ + tmp_aes_len = AES_KEY128_LENGTH; + AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); + + // Fill Mic to ft struct + NdisMoveMemory(ft->MIC, mic, 16); + } + //////////////////////////////////////////////////////////////////////// + + // Insert FT_IE to outgoing frame + TDLS_InsertFTIE( + pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + sizeof(FT_FTIE), + ft->MICCtr, + ft->MIC, + ft->ANonce, + ft->SNonce); + + // Timeout Interval (7.3.2.49) + // Insert TI_IE to outgoing frame + TDLS_InsertTimeoutIntervalIE( + pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + 2, /* key lifetime interval */ + pTDLS->KeyLifetime); + + } + +#ifdef DOT11_N_SUPPORT + // fill HT Capability + TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); +#endif // DOT11_N_SUPPORT // + + /* fill link identifier */ + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); + + // fill WMM Parameter IE + TDLS_InsertWMMParameterIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); + +#ifdef WFD_SUPPORT + { + ULONG WfdIeLen = 0, WfdIeBitmap; + + WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | + (0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_LOCAL_IP_ADDR); + WfdMakeWfdIE(pAd, WfdIeBitmap, (pFrameBuf + *pFrameLen), &WfdIeLen); + *pFrameLen += WfdIeLen; + } +#endif /* WFD_SUPPORT */ + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_BuildTeardown( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UINT16 ReasonCode) +{ + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_TEARDOWN); + + /* fill reason code */ + TDLS_InsertReasonCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ReasonCode); + + // FTIE includes if RSNA Enabled + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + UCHAR FTIe[128]; + FT_FTIE *ft = NULL; + UCHAR content[256]; + ULONG c_len = 0; + ULONG tmp_len = 0; + UCHAR seq = 4; + UCHAR mic[16]; + UCHAR LinkIdentifier[20]; + UINT tmp_aes_len = 0; + + NdisZeroMemory(LinkIdentifier, 20); + LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; + LinkIdentifier[1] = 18; + + NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); + if (pTDLS->bInitiator) + { + NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6); + NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6); + } + else + { + NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6); + NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6); + } + + + // FTIE (7.3.2.48) + // The contents of FTIE in the TDLS Teardown frame shall be the same as that included + // in the TPK Handshake Message3 with the exception of the MIC field. + + /* Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) */ + + // point to the element of IE + NdisZeroMemory(FTIe, sizeof(FTIe)); + FTIe[0] = IE_FT_FTIE; + FTIe[1] = sizeof(FT_FTIE); + ft = (PFT_FTIE)&FTIe[2]; + NdisMoveMemory(ft->ANonce, pTDLS->ANonce, 32); + NdisMoveMemory(ft->SNonce, pTDLS->SNonce, 32); + + //////////////////////////////////////////////////////////////////////// + // The MIC field of FTIE shall be calculated on the concatenation, in the following order, of + // 1. Link Identifier (20 bytes) + // 2. Reason Code (2 bytes) + // 3. Dialog token (1 byte) + // 4. Transaction Sequence = 4 (1 byte) + // 5. FTIE with the MIC field of FTIE set to zero (84 bytes) + + /* concatenate Link Identifier, Reason Code, Dialog token, Transaction Sequence */ + MakeOutgoingFrame(content, &tmp_len, + sizeof(LinkIdentifier), LinkIdentifier, + 2, &ReasonCode, + 1, &pTDLS->Token, + 1, &seq, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate FTIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + FTIe[1] + 2, FTIe, + END_OF_ARGS); + c_len += tmp_len; + + /* Calculate MIC */ + NdisZeroMemory(mic, sizeof(mic)); + //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); + + /* Compute AES-128-CMAC over the concatenation */ + tmp_aes_len = AES_KEY128_LENGTH; + AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); + + /* Fill Mic to ft struct */ + NdisMoveMemory(ft->MIC, mic, 16); + //////////////////////////////////////////////////////////////////////// + + // Insert FT_IE to outgoing frame + TDLS_InsertFTIE( + pAd, + (pFrameBuf + *pFrameLen), + pFrameLen, + FTIe[1], + ft->MICCtr, + ft->MIC, + ft->ANonce, + ft->SNonce); + } + + /* fill link identifier */ + if (pTDLS->bInitiator) + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr, pAd->CurrentAddress); + else + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +USHORT TDLS_TPKMsg1Process( + IN PRTMP_ADAPTER pAd, +#ifdef WFD_SUPPORT + IN ULONG WfdSubelementLen, +#endif /* WFD_SUPPORT */ + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pRsnIe, + IN UCHAR RsnLen, + IN PUCHAR pFTIe, + IN UCHAR FTLen, + IN PUCHAR pTIIe, + IN UCHAR TILen) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR CipherTmp[64] = {0}; + UCHAR CipherTmpLen = 0; + FT_FTIE *ft = NULL; + + /* Validate RsnIE */ + /* */ + if (RsnLen == 0) /* RSN not exist */ + return MLME_INVALID_INFORMATION_ELEMENT; + + if (pRsnIe[2] < 1) /* Smaller version */ + return MLME_NOT_SUPPORT_RSN_VERSION; + + CipherTmpLen = CipherSuiteTDLSLen; + NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); + + if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM + return MLME_INVALID_AKMP; + + //if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability + if (((pRsnIe[20] & 0x2) != 0) || ((pRsnIe[21] & 0x2) == 0)) + return MLME_INVALID_RSN_CAPABILITIES; + + //if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, RsnLen) == 0)) // Invalid Pairwise Cipher + // todo make check + //if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, (RsnLen - 2)) == 0)) + // return REASON_UCIPHER_NOT_VALID; + + // Validate FTIE + // + ft = (PFT_FTIE)(pFTIe + 2); // point to the element of IE + if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 || + (RTMPEqualMemory(ft->MIC, TdlsZeroSsid, 16) == 0) || (RTMPEqualMemory(ft->ANonce, TdlsZeroSsid, 32) == 0)) + return REASON_FT_INVALID_FTIE; + + // Validate TIIE + // + //if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < keyLifeTime)) + if ((TILen != 7) || (pTIIe[2] != 2)) + return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME; + + return StatusCode; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +USHORT TDLS_TPKMsg2Process( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pRsnIe, + IN UCHAR RsnLen, + IN PUCHAR pFTIe, + IN UCHAR FTLen, + IN PUCHAR pTIIe, + IN UCHAR TILen, + OUT PUCHAR pTPK, + OUT PUCHAR pTPKName) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR CipherTmp[64] = {0}; + UCHAR CipherTmpLen = 0; + FT_FTIE *ft = NULL; + UCHAR oldMic[16]; + UCHAR LinkIdentifier[20]; + UINT key_len = 16; + UINT32 keyLifeTime = pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime; + + /* Validate RsnIE */ + /* */ + if (RsnLen == 0) /* RSN not exist */ + return MLME_INVALID_INFORMATION_ELEMENT; + + if (pRsnIe[2] < 1) /* Smaller version */ + return MLME_NOT_SUPPORT_RSN_VERSION; + + CipherTmpLen = CipherSuiteTDLSLen; + NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); + + if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM + return MLME_INVALID_AKMP; + + //if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability + if (((pRsnIe[20] & 0x2) != 0) || ((pRsnIe[21] & 0x2) == 0)) + return MLME_INVALID_RSN_CAPABILITIES; + + // todo make check + //if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, RsnLen) == 0)) // Invalid Pairwise Cipher + //if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, (RsnLen - 2)) == 0)) + //return REASON_UCIPHER_NOT_VALID; + + // Validate FTIE + // + ft = (PFT_FTIE)(pFTIe + 2); // point to the element of IE + if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 || + (RTMPEqualMemory(ft->SNonce, pTDLS->SNonce, 32) == 0)) + return REASON_FT_INVALID_FTIE; + + // Validate TIIE + // + if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < keyLifeTime)) + return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME; + + + // Validate the MIC field of FTIE + // + + // point to the element of IE + ft = (PFT_FTIE)(pFTIe + 2); + // backup MIC fromm the peer TDLS + NdisMoveMemory(oldMic, ft->MIC, 16); + + + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ + /* Derive TPK-KCK for MIC key, TPK-TK for direct link data */ + TDLS_FTDeriveTPK( + pAd->CurrentAddress, /* I am Initiator */ + pTDLS->MacAddr, /* MAC Address of Responder */ + ft->ANonce, + ft->SNonce, + pAd->CommonCfg.Bssid, + key_len, + pTPK, + pTPKName); + + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ + + /* set MIC field to zero before MIC calculation */ + NdisZeroMemory(ft->MIC, 16); + + /* Construct LinkIdentifier (IE + Length + BSSID + Initiator MAC + Responder MAC) */ + NdisZeroMemory(LinkIdentifier, 20); + LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; + LinkIdentifier[1] = 18; + NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); + NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6); + NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6); + + /*////////////////////////////////////////////////////////////////////*/ + /* The MIC field of FTIE shall be calculated on the concatenation, in the following order, of */ + /* 1. MAC_I (6 bytes) */ + /* 2. MAC_R (6 bytes) */ + /* 3. Transaction Sequence = 2 (1 byte) */ + /* 4. Link Identifier (20 bytes) */ + /* 5. RSN IE without the IE header (20 bytes) */ + /* 6. Timeout Interval IE (7 bytes) */ + /* 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) */ + { + UCHAR content[512]; + ULONG c_len = 0; + ULONG tmp_len = 0; + UCHAR Seq = 2; + UCHAR mic[16]; + UINT tmp_aes_len = 0; + + NdisZeroMemory(mic, sizeof(mic)); + + /* make a header frame for calculating MIC. */ + MakeOutgoingFrame(content, &tmp_len, + MAC_ADDR_LEN, pAd->CurrentAddress, + MAC_ADDR_LEN, pTDLS->MacAddr, + 1, &Seq, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Link Identifier */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 20, LinkIdentifier, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate RSNIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + RsnLen, pRsnIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Timeout Interval IE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 7, pTIIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate FTIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + (sizeof(FT_FTIE) + 2), pFTIe, + END_OF_ARGS); + c_len += tmp_len; + + /* Calculate MIC */ + //AES_128_CMAC(pTPK, content, c_len, mic); + + /* Compute AES-128-CMAC over the concatenation */ + tmp_aes_len = AES_KEY128_LENGTH; + AES_CMAC(content, c_len, pTPK, 16, mic, &tmp_aes_len); + + NdisMoveMemory(ft->MIC, mic, 16); + + } + /*////////////////////////////////////////////////////////////////////*/ + + if (RTMPEqualMemory(oldMic, ft->MIC, 16) == 0) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS_TPKMsg2Process() MIC Error!!! \n")); + return MLME_REQUEST_DECLINED; + } + + return StatusCode; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +USHORT TDLS_TPKMsg3Process( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN PUCHAR pRsnIe, + IN UCHAR RsnLen, + IN PUCHAR pFTIe, + IN UCHAR FTLen, + IN PUCHAR pTIIe, + IN UCHAR TILen) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR CipherTmp[64] = {0}; + UCHAR CipherTmpLen = 0; + FT_FTIE *ft = NULL; + UCHAR oldMic[16]; + UCHAR LinkIdentifier[20]; + + /* Validate RsnIE */ + /* */ + if (RsnLen == 0) /* RSN not exist */ + return MLME_INVALID_INFORMATION_ELEMENT; + + if (pRsnIe[2] < 1) /* Smaller version */ + return MLME_NOT_SUPPORT_RSN_VERSION; + + CipherTmpLen = CipherSuiteTDLSLen; + NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); + + if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM + return MLME_INVALID_AKMP; + + //if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability + if (((pRsnIe[20] & 0x2) != 0) || ((pRsnIe[21] & 0x2) == 0)) + return MLME_INVALID_RSN_CAPABILITIES; + + // todo make check + //if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, (RsnLen - 2)) == 0)) // Invalid Pairwise Cipher + //return REASON_UCIPHER_NOT_VALID; + + // Validate FTIE + // + ft = (PFT_FTIE)(pFTIe + 2); // point to the element of IE + if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 || + (RTMPEqualMemory(ft->SNonce, pTDLS->SNonce, 32) == 0) || (RTMPEqualMemory(ft->ANonce, pTDLS->ANonce, 32) == 0)) + return REASON_FT_INVALID_FTIE; + + // Validate TIIE + // + if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < pTDLS->KeyLifetime)) + return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME; + + // Validate the MIC field of FTIE + // + + // point to the element of IE + ft = (PFT_FTIE)(pFTIe + 2); + // backup MIC fromm the peer TDLS + NdisMoveMemory(oldMic, ft->MIC, 16); + + + // set MIC field to zero before MIC calculation + NdisZeroMemory(ft->MIC, 16); + + // Construct LinkIdentifier (IE + Length + BSSID + Initiator MAC + Responder MAC) + NdisZeroMemory(LinkIdentifier, 20); + LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; + LinkIdentifier[1] = 18; + NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); + NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6); + NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6); + + /*////////////////////////////////////////////////////////////////////*/ + /* The MIC field of FTIE shall be calculated on the concatenation, in the following order, of */ + /* 1. MAC_I (6 bytes) */ + /* 2. MAC_R (6 bytes) */ + /* 3. Transaction Sequence = 3 (1 byte) */ + /* 4. Link Identifier (20 bytes) */ + /* 5. RSN IE without the IE header (20 bytes) */ + /* 6. Timeout Interval IE (7 bytes) */ + /* 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) */ + { + UCHAR content[512]; + ULONG c_len = 0; + ULONG tmp_len = 0; + UCHAR Seq = 3; + UCHAR mic[16]; + UINT tmp_aes_len = 0; + + NdisZeroMemory(mic, sizeof(mic)); + + /* make a header frame for calculating MIC. */ + MakeOutgoingFrame(content, &tmp_len, + MAC_ADDR_LEN, pTDLS->MacAddr, + MAC_ADDR_LEN, pAd->CurrentAddress, + 1, &Seq, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Link Identifier */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 20, LinkIdentifier, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate RSNIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + RsnLen, pRsnIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate Timeout Interval IE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + 7, pTIIe, + END_OF_ARGS); + c_len += tmp_len; + + /* concatenate FTIE */ + MakeOutgoingFrame(content + c_len, &tmp_len, + (sizeof(FT_FTIE) + 2), pFTIe, + END_OF_ARGS); + c_len += tmp_len; + + /* Calculate MIC */ + //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); + + /* Compute AES-128-CMAC over the concatenation */ + tmp_aes_len = AES_KEY128_LENGTH; + AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); + + NdisMoveMemory(ft->MIC, mic, 16); + + } + /*////////////////////////////////////////////////////////////////////*/ + + if (RTMPEqualMemory(oldMic, ft->MIC, 16) == 0) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS_TPKMsg3Process() MIC Error!!! \n")); + return MLME_REQUEST_DECLINED; + } + + + return StatusCode; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_DiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + MAKE_802_3_HEADER(Header802_3, pMacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + /* fill action code */ + TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_DISCOVERY_REQUEST); + + /* fill Dialog Token */ + pAd->StaCfg.TdlsInfo.TdlsDialogToken++; + + if (pAd->StaCfg.TdlsInfo.TdlsDialogToken == 0) + pAd->StaCfg.TdlsInfo.TdlsDialogToken++; + + TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, pAd->StaCfg.TdlsInfo.TdlsDialogToken); + + /* fill link identifier */ + TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pAd->CurrentAddress, pMacAddr); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS discovery request send pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +NDIS_STATUS +TDLS_DiscoveryRspAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerToken, + IN PUCHAR pPeerMac) +{ + PUCHAR pOutBuffer = NULL; + FRAME_ACTION_HDR Frame; + ULONG FrameLen = 0; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return NStatus; + } + + ActHeaderInit(pAd, &Frame.Hdr, pPeerMac, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + Frame.Category = CATEGORY_PUBLIC; + Frame.Action = ACTION_TDLS_DISCOVERY_RSP; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + /* fill action code */ + //TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_TDLS, 14); + + /* fill Dialog Token */ + TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, PeerToken); + + // fill capability + TDLS_InsertCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + // fill support rate + TDLS_InsertSupportRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + // fill ext rate + TDLS_InsertExtRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + // fill support channels + TDLS_InsertSupportChannelIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + UCHAR CipherTmp[64] = {0}; + UCHAR CipherTmpLen = 0; + ULONG tmp; + + // RSNIE (7.3.2.25) + CipherTmpLen = CipherSuiteTDLSLen; + NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); + + // Insert RSN_IE to outgoing frame + MakeOutgoingFrame((pOutBuffer + FrameLen), &tmp, + CipherTmpLen, &CipherTmp, + END_OF_ARGS); + + FrameLen = FrameLen + tmp; + } + + // fill Extended Capabilities (7.3.2.27) + TDLS_InsertExtCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + // TPK Handshake if RSNA Enabled + // Pack TPK Message 1 here! + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + FT_FTIE FtIe; + ULONG KeyLifetime = pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime; // sec + UCHAR Length; + UCHAR SNonce[32]; // Generated in Message 2, random variable + + // FTIE (7.3.2.48) + NdisZeroMemory(&FtIe, sizeof(FtIe)); + Length = sizeof(FtIe); + + // generate SNonce + GenRandom(pAd, pAd->CurrentAddress, FtIe.SNonce); + hex_dump("TDLS - Generate SNonce ", FtIe.SNonce, 32); + NdisMoveMemory(SNonce, FtIe.SNonce, 32); + + TDLS_InsertFTIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + Length, + FtIe.MICCtr, + FtIe.MIC, + FtIe.ANonce, + FtIe.SNonce); + + // Timeout Interval (7.3.2.49) + TDLS_InsertTimeoutIntervalIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + 2, /* key lifetime interval */ + KeyLifetime); + } + + // fill Supported Regulatory Classes + TDLS_SupportedRegulatoryClasses(pAd, (pOutBuffer + FrameLen), &FrameLen); + +#ifdef DOT11_N_SUPPORT + // fill HT Capability + TDLS_InsertHtCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + // fill 20/40 BSS Coexistence (7.3.2.61) +#ifdef DOT11N_DRAFT3 + TDLS_InsertBSSCoexistenceIE(pAd, (pOutBuffer + FrameLen), &FrameLen); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + /* fill link identifier */ + TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pPeerMac, pAd->CurrentAddress); + + hex_dump("TDLS discovery response send pack", pOutBuffer, FrameLen); + + MiniportMMRequest(pAd, QID_AC_VI, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_SetupRequestAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + NdisZeroMemory(Header802_3, LENGTH_802_3); + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, &pAd->CurrentAddress[0], TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return NStatus; + } + + /* enter ACTIVE mode */ + TDLS_CHANGE_TO_ACTIVE(pAd); + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildSetupRequest(pAd, pOutBuffer, &FrameLen, pTDLS); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS setup request send pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_SetupResponseAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return NStatus; + } + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildSetupResponse(pAd, pOutBuffer, &FrameLen, pTDLS, RsnLen, pRsnIe, FTLen, pFTIe, TILen, pTIIe, StatusCode); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS send setup response pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_SetupConfirmAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR RsnLen, + IN PUCHAR pRsnIe, + IN UCHAR FTLen, + IN PUCHAR pFTIe, + IN UCHAR TILen, + IN PUCHAR pTIIe, + IN UINT16 StatusCode) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return NStatus; + } + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildSetupConfirm(pAd, pOutBuffer, &FrameLen, pTDLS, RsnLen, pRsnIe, FTLen, pFTIe, TILen, pTIIe, StatusCode); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS setup confirm pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + TDLS_RECOVER_POWER_SAVE(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_LinkTearDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bDirect) +{ + UCHAR idx; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + /* tear down tdls table entry */ + for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (pTDLS->Valid && (pTDLS->Status >= TDLS_MODE_CONNECTED)) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + pTDLS->Token = 0; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + if (!VALID_WCID(pTDLS->MacTabMatchWCID)) + return; + + if (pAd->StaCfg.bRadio == TRUE) + { + if (bDirect) + TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON, TRUE); + else + TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_DUE_TO_PEER_STA_UNREACHABLE, FALSE); + } + + MacTableDeleteEntry(pAd,pTDLS->MacTabMatchWCID, pTDLS->MacAddr); + } + else if (pTDLS->Valid) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + pTDLS->Token = 0; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + } + } + +#ifdef TDLS_AUTOLINK_SUPPORT + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_ClearEntryList(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + TDLS_ClearEntryList(&pAd->StaCfg.TdlsInfo.TdlsBlackList); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); +#endif /* TDLS_AUTOLINK_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_TearDownPeerLink( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerAddr, + IN BOOLEAN bDirect) +{ + UCHAR EntryIdx; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + // tear down tdls table entry + for (EntryIdx = 0; EntryIdx < MAX_NUM_OF_TDLS_ENTRY; EntryIdx++) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[EntryIdx]; + + if ((pTDLS->Valid) && (pTDLS->Status >= TDLS_MODE_CONNECTED) && MAC_ADDR_EQUAL(pPeerAddr, pTDLS->MacAddr)) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + if (!VALID_WCID(pTDLS->MacTabMatchWCID)) + return; + + if (bDirect) + TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON, TRUE); + else + TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_DUE_TO_PEER_STA_UNREACHABLE, FALSE); + + MacTableDeleteEntry(pAd,pTDLS->MacTabMatchWCID, pTDLS->MacAddr); + + break; + } + } + + if (EntryIdx == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - Peer MAC - not found !!!\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +NDIS_STATUS +TDLS_TearDownAction( + IN PRTMP_ADAPTER pAd, + IN PRT_802_11_TDLS pTDLS, + IN UINT16 ReasonCode, + IN BOOLEAN bDirect) +{ + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + UCHAR idx = 1; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* Allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - %s() allocate memory failed \n", __FUNCTION__)); + return NStatus; + } + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildTeardown(pAd, pOutBuffer, &FrameLen, pTDLS, ReasonCode); + + if (bDirect == TRUE) + idx = pTDLS->MacTabMatchWCID; + else + idx = BSSID_WCID; + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[idx], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE); + + hex_dump("TDLS teardown send pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return NStatus; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeDiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PeerMacAddr[MAC_ADDR_LEN]; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; +#ifdef TDLS_AUTOLINK_SUPPORT + PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL; +#endif // TDLS_AUTOLINK_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + NdisMoveMemory(PeerMacAddr, Elem->Msg, MAC_ADDR_LEN); + + if (INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("Send Discovery Request to Peer ::%02x:%02x:%02x:%02x:%02x:%02x !!!\n", + PRINT_MAC(PeerMacAddr))); + + /* Build TDLS Discovery Request Frame */ + NStatus = TDLS_DiscoveryReqAction(pAd, PeerMacAddr); + if (NStatus != NDIS_STATUS_SUCCESS) + { +#ifdef TDLS_AUTOLINK_SUPPORT + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_DelDiscoveryEntryByMAC(pTdlsDiscoveryEnList, PeerMacAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); +#endif // TDLS_AUTOLINK_SUPPORT // + DBGPRINT(RT_DEBUG_ERROR,("%s() - Build Discovery Setup Request Fail !!!\n", __FUNCTION__)); + } + else + { +#ifdef TDLS_AUTOLINK_SUPPORT + pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, PeerMacAddr); +#endif // TDLS_AUTOLINK_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - Build Discovery Setup Request Fail, Because STA is not connect to AP!!!\n", + __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +#ifdef WFD_SUPPORT +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeTunneledReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PeerMacAddr[MAC_ADDR_LEN]; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; +#ifdef TDLS_AUTOLINK_SUPPORT + PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsDiscovPeerList; + PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL; +#endif // TDLS_AUTOLINK_SUPPORT // + + DBGPRINT(RT_DEBUG_ERROR,("===> TDLS_MlmeTunneledProbeReqAction() \n")); + + NdisMoveMemory(PeerMacAddr, Elem->Msg, MAC_ADDR_LEN); + + if (INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Send Tunneled Probe Request to Peer ::%02x:%02x:%02x:%02x:%02x:%02x !!!\n", + PeerMacAddr[0], PeerMacAddr[1], PeerMacAddr[2], + PeerMacAddr[3], PeerMacAddr[4], PeerMacAddr[5])); + + /* Build TDLS Tunneled Probe Request Frame */ + NStatus = TDLS_TunneledProbeRequest(pAd, PeerMacAddr); + if (NStatus != NDIS_STATUS_SUCCESS) + { +#ifdef TDLS_AUTOLINK_SUPPORT + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsDiscovPeerListSemLock); + TDLS_DelDiscoveryEntryByMAC(pTdlsDiscoveryEnList, PeerMacAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsDiscovPeerListSemLock); +#endif // TDLS_AUTOLINK_SUPPORT // + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeTunneledProbeReqAction() Build Tunneled Probe Request Fail !!!\n")); + } + else + { +#ifdef TDLS_AUTOLINK_SUPPORT + pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, PeerMacAddr); +#endif // TDLS_AUTOLINK_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeTunneledProbeReqAction() Build Tunneled Probe Request Fail, Because STA is not connect to AP!!!\n")); + } + + DBGPRINT(RT_DEBUG_ERROR,("<=== TDLS_MlmeTunneledProbeReqAction() \n")); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerTunneledReqRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UCHAR Token; + UCHAR PeerAddr[MAC_ADDR_LEN]; + ULONG RemainLen = Elem->MsgLen; + PFRAME_802_11 pFrame; + pFrame = (PFRAME_802_11)Elem->Msg; + CHAR *Ptr =(CHAR *)Elem->Msg; + PRT_802_11_TDLS pTDLS = NULL; + BOOLEAN TimerCancelled; + + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerTunneledReqRspAction() \n")); + + /* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes) + TDLS Action header(payload type + category + action)(3 bytes) and Payload (variable) + */ + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + 3)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("TDLS_PeerTunneledReq/RspAction --> Invaild packet length - (action header) \n")); + return; + } + + // Offset to Payload Type + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + 1); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + 1); + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS_PeerTunneledReqRspAction --> Gategory = %02x. OUI = %02x-%02x-%02x.\n", *Ptr, *(Ptr+1), *(Ptr+2), *(Ptr+3))); + // Get the value of token from payload and advance the pointer + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (dialog token) \n")); + return; + } + + /* Frame Body Type */ + Ptr += 4; + RemainLen -= 4; + + if (RemainLen < 7) + { + DBGPRINT(RT_DEBUG_ERROR, ("PeerTdlsDiscovReqSanity --> remain length is not enough = %d.\n", RemainLen)); + return; + } + + if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr3, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsTunneledReqSanity --> It's not my BSSID[%02x:%02x:%02x:%02x:%02x:%02x] Addr3[%02x:%02x:%02x:%02x:%02x:%02x]\n", PRINT_MAC(pAd->CommonCfg.Bssid), PRINT_MAC(pFrame->Hdr.Addr3))); + //return; + } + + NdisMoveMemory(PeerAddr, pFrame->Hdr.Addr3, MAC_ADDR_LEN); + + if ((*Ptr == WFD_TUNNELED_PROBE_REQ) || + (*Ptr == WFD_TUNNELED_PROBE_RSP)) + { + PWFD_DEVICE_INFO pWfd_info; + SHORT idx; + + for (idx = MAX_NUM_OF_TDLS_ENTRY - 1; idx >= 0; idx--) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (pTDLS->Valid && MAC_ADDR_EQUAL(PeerAddr, pTDLS->MacAddr)) + { + DBGPRINT(RT_DEBUG_TRACE,("%s::find the same entry and discard it\n", __FUNCTION__)); + break; + } + } + + if (idx < 0) + { + for (idx = (MAX_NUM_OF_TDLS_ENTRY - 1); idx >= 0; idx--) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (!pTDLS->Valid) + { + RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled); + pTDLS->Valid = TRUE; + NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqRspAction() create a new entry \n")); + + break; + } + } + } + + + if (idx < 0) + { + // Table full !!!!! + DBGPRINT(RT_DEBUG_ERROR,("%s::TDLSEntry table full(only can support %d TDLS session) \n", + __FUNCTION__, MAX_NUM_OF_TDLS_ENTRY)); + } + else if (pTDLS) + { + UCHAR Addr2[6], SsidLen = 0; + UCHAR Ssid[32]; + ULONG Peerip; + UCHAR DsChannel = 0; + ULONG P2PSubelementLen = 0; + PUCHAR P2pSubelement = NULL; + ULONG WfdSubelementLen = 0; + PUCHAR WfdSubelement = NULL; + + os_alloc_mem(pAd, &P2pSubelement, MAX_VIE_LEN); + + if (P2pSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN)); + return; + } + + os_alloc_mem(pAd, &WfdSubelement, MAX_VIE_LEN); + + if (WfdSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN)); + os_free_mem(pAd, P2pSubelement); + return; + } + + (TDLS_PeerTunneledProbeReqRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Addr2, + Ssid, + &SsidLen, + &Peerip, + &DsChannel, + &P2PSubelementLen, + P2pSubelement, + &WfdSubelementLen, + WfdSubelement)); + + if (WfdSubelementLen > 0) + { + WfdParseSubElmt(pAd, + &pTDLS->WfdEntryInfo, + (PVOID)WfdSubelement, + WfdSubelementLen); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:: WFD Element IE Len is 0.\n", __FUNCTION__)); + + if (P2pSubelement) + os_free_mem(pAd, P2pSubelement); + if (WfdSubelement) + os_free_mem(pAd, WfdSubelement); + + if (*Ptr == WFD_TUNNELED_PROBE_REQ) + { + DBGPRINT(RT_DEBUG_ERROR,("Receive Tunneled probe request frame\n")); + + /* Build TDLS Discovery Response Frame */ + NStatus = TDLS_TunneledProbeResponse(pAd, PeerAddr); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerTunneledReqRspAction() Build Tunneled Response Fail !!!\n")); + } + } + else + DBGPRINT(RT_DEBUG_ERROR,("Receive Tunneled probe response frame\n")); + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s::unknown Type = %02x.\n", __FUNCTION__, *Ptr+4)); + + return; +} +#endif /* WFD_SUPPORT */ + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerDiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UCHAR Token; + UCHAR PeerAddr[MAC_ADDR_LEN]; + ULONG RemainLen = Elem->MsgLen; + CHAR *Ptr =(CHAR *)Elem->Msg; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + /* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes) + TDLS Action header(payload type + category + action)(3 bytes) and Payload (variable) + */ + if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + 3)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (action header) \n", __FUNCTION__)); + return; + } + + // Offset to Dialog Token + Ptr += (LENGTH_802_11 + LENGTH_802_1_H + 3); + RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + 3); + + // Get the value of token from payload and advance the pointer + if (RemainLen < 1) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (dialog token) \n", __FUNCTION__)); + return; + } + + Token = *Ptr; + + // Offset to Link Identifier + Ptr += 1; + RemainLen -= 1; + + // Get BSSID, SA and DA from payload and advance the pointer + if ((RemainLen < 20) || (Ptr[0] != IE_TDLS_LINK_IDENTIFIER) || (Ptr[1] != 18)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - Invaild packet length - (link identifier) \n", __FUNCTION__)); + return; + } + if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my BSSID\n", __FUNCTION__)); + return; + } + else if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%s() - It's not my MAC address\n", __FUNCTION__)); + return; + } + + NdisMoveMemory(PeerAddr, Ptr+8, MAC_ADDR_LEN); + + /* Build TDLS Discovery Response Frame */ + NStatus = TDLS_DiscoveryRspAction(pAd, Token, PeerAddr); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s() - Build Discovery Response Fail !!!\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_DiscoveryRspPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN VOID *Msg, + IN ULONG MsgLen) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR Token; + UCHAR PeerAddr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen, HtCapLen, ExtCapLen, RsnLen, FTLen, TILen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + HT_CAPABILITY_IE HtCap; + EXT_CAP_INFO_ELEMENT ExtCap; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + hex_dump("TDLS discovery response receive pack", Msg, MsgLen); + + if (!PeerTdlsDiscovRspSanity( + pAd, + Msg, + MsgLen, + &Token, + PeerAddr, + &CapabilityInfo, + &SupRateLen, + &SupRate[0], + &ExtRateLen, + &ExtRate[0], + &HtCapLen, + &HtCap, + &ExtCapLen, + &ExtCap, + &RsnLen, + RsnIe, + &FTLen, + FTIe, + &TILen, + TIIe)) + { + StatusCode = MLME_REQUEST_DECLINED; + } + + COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr2); + + if (StatusCode == MLME_SUCCESS) + { +#ifdef TDLS_AUTOLINK_SUPPORT + if (pAd->StaCfg.TdlsInfo.TdlsAutoLink) + { + PLIST_HEADER pTdlsDiscovryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL; + + pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscovryEnList, PeerAddr); + + if (pTdlsPeer) + { + PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + CHAR Rssi = -99; + + 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_ERROR, ("Discovery Response Rssi = %d !!!\n" , Rssi)); + + if (pTdlsPeer->bConnected) + { + if ((pTdlsPeer->bConnectedFirstTime) && (pTdlsPeer->RetryCount == 1)) + { + pTdlsPeer->AvgRssi0 = Rssi; + pTdlsPeer->RetryCount--; + pTdlsPeer->bConnectedFirstTime = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("Connected first time discovery !!!\n")); + } + else + { + if (pTdlsPeer->RetryCount == 1) + { + if ((Rssi < pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold) && + (pTdlsPeer->AvgRssi0 < pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold)) + { + /* Tear Down */ + if (INFRA_ON(pAd)) + { + MLME_TDLS_REQ_STRUCT MlmeTdlsReq; + USHORT Reason = REASON_UNSPECIFY; + INT idx; + + DBGPRINT(RT_DEBUG_ERROR,("\n !!! Will tear down %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + pTdlsPeer->Responder[0], + pTdlsPeer->Responder[1], + pTdlsPeer->Responder[2], + pTdlsPeer->Responder[3], + pTdlsPeer->Responder[4], + pTdlsPeer->Responder[5])); + + idx = TDLS_SearchLinkId(pAd, pTdlsPeer->Responder); + + if (idx == -1 || idx == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - can not find or full the LinkId!\n")); + } + else if (idx >= 0) + { + Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Valid = FALSE; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Status = TDLS_MODE_NONE; + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[idx], Reason, FALSE); + + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TEAR_DOWN, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + + } + } + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_DelDiscoveryEntryByMAC(pTdlsDiscovryEnList, PeerAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + } + else + { + pTdlsPeer->AvgRssi0 = Rssi; + pTdlsPeer->RetryCount--; + } + } + else if (pTdlsPeer->RetryCount > 1) + { + if (Rssi < pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold) + { + /* Tear Down */ + if (INFRA_ON(pAd)) + { + MLME_TDLS_REQ_STRUCT MlmeTdlsReq; + USHORT Reason = REASON_UNSPECIFY; + INT idx; + + DBGPRINT(RT_DEBUG_ERROR,("\n !!! Will tear down %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + pTdlsPeer->Responder[0], + pTdlsPeer->Responder[1], + pTdlsPeer->Responder[2], + pTdlsPeer->Responder[3], + pTdlsPeer->Responder[4], + pTdlsPeer->Responder[5])); + + idx = TDLS_SearchLinkId(pAd, pTdlsPeer->Responder); + + if (idx == -1 || idx == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - can not find or full the LinkId!\n")); + } + else if (idx >= 0) + { + Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Valid = FALSE; + pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Status = TDLS_MODE_NONE; + TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[idx], Reason, FALSE); + + MlmeEnqueue(pAd, + TDLS_STATE_MACHINE, + MT2_MLME_TDLS_TEAR_DOWN, + sizeof(MLME_TDLS_REQ_STRUCT), + &MlmeTdlsReq, + 0); + + } + } + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_DelDiscoveryEntryByMAC(pTdlsDiscovryEnList, PeerAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + } + else + { + pTdlsPeer->AvgRssi0 = Rssi; + pTdlsPeer->RetryCount = 0; + } + } + } + } + else + { + if (pTdlsPeer->CurrentState == TDLS_DISCOVERY_IDLE) + { + pTdlsPeer->CurrentState = TDLS_DISCOVERY_FIRST_TIME; + pTdlsPeer->AvgRssi0 = Rssi; + } + else if (pTdlsPeer->CurrentState == TDLS_DISCOVERY_FIRST_TIME) + { + if ((pTdlsPeer->AvgRssi0 > pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold) && + (Rssi > pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold)) + { + if (INFRA_ON(pAd) && (pTdlsPeer->bConnected == FALSE)) + { + INT LinkId = 0xff; + + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + RT_802_11_TDLS Tdls; + + DBGPRINT(RT_DEBUG_ERROR,("\n!!! Auto Setup TDLS to %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + pTdlsPeer->Responder[0], + pTdlsPeer->Responder[1], + pTdlsPeer->Responder[2], + pTdlsPeer->Responder[3], + pTdlsPeer->Responder[4], + pTdlsPeer->Responder[5])); + NdisZeroMemory(&Tdls, sizeof(RT_802_11_TDLS)); + Tdls.TimeOut = 0; + COPY_MAC_ADDR(Tdls.MacAddr, pTdlsPeer->Responder); + Tdls.Valid = 1; + + pTdlsPeer->CurrentState = TDLS_DISCOVERY_TO_SETUP; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_TDLS_PARAM, + sizeof(RT_802_11_TDLS), + &Tdls, + 0); + } + else + { + PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL; + PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscovEnList, PeerAddr, TRUE); + pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsDiscovEnList, PeerAddr); + if (pPeerEntry) + { + pPeerEntry->bConnectedFirstTime = TRUE; + pPeerEntry->bConnected = TRUE; + pPeerEntry->RetryCount = 0; + pPeerEntry->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE; + } + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + TDLS_DelBlackEntryByMAC(pTdlsBlackEnList, PeerAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + } + } + } + else + { + pTdlsPeer->CurrentState = TDLS_DISCOVERY_TO_SETUP_FAIL; + } + } + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("Can't find discovery entry on discovery table !!!\n")); + } + } +#endif // TDLS_AUTOLINK_SUPPORT // + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeSetupReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_TDLS pTDLS = NULL; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + MLME_TDLS_REQ_STRUCT *pInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + pInfo = (MLME_TDLS_REQ_STRUCT *)Elem->Msg; + + pTDLS = pInfo->pTDLS; + + if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - AP Prohibited TDLS !!!\n", __FUNCTION__)); + return; + } + + /* Build TDLS Setup Request Frame */ + NStatus = TDLS_SetupRequestAction(pAd, pTDLS); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s() - Build Setup Request Fail !!!\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerSetupReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT StatusCode = MLME_SUCCESS; + SHORT idx; + ULONG Timeout = TDLS_TIMEOUT; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + RT_802_11_TDLS TmpTDLS; + UCHAR Token; + UCHAR PeerAddr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen, HtCapLen, ExtCapLen, RsnLen, FTLen, TILen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + UCHAR QosCapability; + HT_CAPABILITY_IE HtCap; + EXT_CAP_INFO_ELEMENT ExtCap; + BOOLEAN bDiscard = FALSE; + BOOLEAN bWmmCapable; +#ifdef WFD_SUPPORT + ULONG WfdSubelementLen = 0; + PUCHAR WfdSubelement = NULL; +#endif /* WFD_SUPPORT */ + +#ifdef WFD_SUPPORT + os_alloc_mem(pAd, &WfdSubelement, MAX_VIE_LEN); + if (WfdSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN)); + return; + } +#endif /* WFD_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + // Not TDLS Capable, ignore it + if (!IS_TDLS_SUPPORT(pAd)) + goto CleanUp; + + // Not BSS mode, ignore it + if (!INFRA_ON(pAd)) + goto CleanUp; + + if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - AP Prohibited TDLS !!!\n", __FUNCTION__)); + goto CleanUp; + } + + // Init all kinds of fields within the packet + NdisZeroMemory(&CapabilityInfo, sizeof(CapabilityInfo)); + NdisZeroMemory(&HtCap, sizeof(HtCap)); + NdisZeroMemory(&ExtCap, sizeof(ExtCap)); + NdisZeroMemory(RsnIe, sizeof(RsnIe)); + NdisZeroMemory(FTIe, sizeof(FTIe)); + NdisZeroMemory(TIIe, sizeof(TIIe)); + + hex_dump("TDLS setup request receive pack", Elem->Msg, Elem->MsgLen); + + if (!PeerTdlsSetupReqSanity( + pAd, + Elem->Msg, + Elem->MsgLen, +#ifdef WFD_SUPPORT + &WfdSubelementLen, + WfdSubelement, +#endif /* WFD_SUPPORT */ + &Token, + PeerAddr, + &CapabilityInfo, + &SupRateLen, + &SupRate[0], + &ExtRateLen, + &ExtRate[0], + &bWmmCapable, + &QosCapability, + &HtCapLen, + &HtCap, + &ExtCapLen, + &ExtCap, + &RsnLen, + RsnIe, + &FTLen, + FTIe, + &TILen, + TIIe)) + { + StatusCode = MLME_REQUEST_DECLINED; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s() - received a request from %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(PeerAddr))); + + if ((pAd->StaCfg.wdev.WepStatus != Ndis802_11WEPDisabled) && (RsnLen == 0)) + { + StatusCode = MLME_INVALID_SECURITY_POLICY; + } + +#ifdef WFD_SUPPORT + /* WFD spec. 4.5.3 Establish WFD Connection using TDLS + * If an associated infrastructure AP uses WEP or WPA for the link between the AP and the WFD device, + * the WFD device shall not accept the TDLS Setup Request frame for WFD connection but reject it by + * sending TDLS Setup Response frame with indicating status code as 5 (Security disabled). + */ + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && WfdSubelementLen) + { + if (RsnLen == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::No RSN IE and peer is WFD device, return weak security(5)!\n", __FUNCTION__)); + StatusCode = MLME_SECURITY_WEAK; + } + if ((pAd->StaCfg.wdev.AuthMode != Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.wdev.WepStatus != Ndis802_11Encryption3Enabled)) // Pairwise cipher suite is not AES + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::AP Security is not WPA2PSK/AES and peer is WFD device, return weak security(5)!\n", __FUNCTION__)); + StatusCode = MLME_SECURITY_WEAK; + } + } +#endif /* WFD_SUPPORT */ +#ifdef TDLS_AUTOLINK_SUPPORT + if (pAd->StaCfg.TdlsInfo.TdlsAutoLink) + { + PTDLS_BLACK_ENTRY pTdlsBlackEntry = NULL; + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + pTdlsBlackEntry = TDLS_FindBlackEntry(pTdlsBlackEnList, PeerAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + + if (pTdlsBlackEntry) + { + if (pTdlsBlackEntry->CurrentState == TDLS_BLACK_TDLS_BY_TEARDOWN) + StatusCode = MLME_REQUEST_DECLINED; + } + } +#endif // TDLS_AUTOLINK_SUPPORT // + + /* Find table to update parameters. */ + if (StatusCode == MLME_SUCCESS) + { + for (idx = MAX_NUM_OF_TDLS_ENTRY - 1; idx >= 0; idx--) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (pTDLS->Valid && MAC_ADDR_EQUAL(PeerAddr, pTDLS->MacAddr)) + { + if (pTDLS->Status == TDLS_MODE_WAIT_RESPONSE) + { + if (RTMPCompareMemory(PeerAddr, pAd->CurrentAddress, MAC_ADDR_LEN) == 2) + { + /* + 11.20.2 TDLS Link Establishment + + 4. The TDLS setup request frame is received after sending a TDLS Setup Request frame and before + receiving the corresponding TDLS Setup Response frame, and the source address of the received + TDLS Setup Request frame is lower than its own MAC address. In this case, the TDLS responder + STA shall terminate the TDLS setup it initiated. The TDLS responder STA shall send a response + frame. + */ + RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled); + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN); + pTDLS->Status = TDLS_MODE_NONE; + idx = -1; + DBGPRINT(RT_DEBUG_ERROR,("%s() - find the same entry \n", __FUNCTION__)); + } + else + { + /* + 11.20.2 TDLS Link Establishment + + 3. The TDLS setup request is received after sending a TDLS Setup Request frame and before + receiving the corresponding TDLS Setup Response frame, and the source address of the received + TDLS Setup Request frame is higher than its own MAC address, in which case the TDLS + responder STA shall silently discard the message and the TDLS responder STA shall send no + TDLS Setup Response frame. + */ + bDiscard = TRUE; + DBGPRINT(RT_DEBUG_ERROR,("%s() - find the same entry and discard it\n", __FUNCTION__)); + } + } + else if (pTDLS->Status == TDLS_MODE_CONNECTED) + { + if(pTDLS->bInitiator == FALSE) + { + /* + If a TDLS Setup Request frame is received from a TDLS responder STA with + which a currently active TDLS session exists, then the receiving STA shall + tear down the existing TDLS direct link as if a TDLS Teardown frame was received, + and respond with a TDLS Setup Response frame. + */ + if (!VALID_WCID(pTDLS->MacTabMatchWCID)) + goto CleanUp; + + MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, pTDLS->MacAddr); + + RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled); + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN); + pTDLS->Status = TDLS_MODE_NONE; + } + } + + break; + } + } + + if (bDiscard == TRUE) + goto CleanUp; + + if (idx >= 0) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + if (pTDLS->Token == Token) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - receive the same token TDLS request !!!\n", __FUNCTION__)); + goto CleanUp;; + } + } + + /* Can not find in table, create a new one */ + if (idx < 0) + { + for (idx = (MAX_NUM_OF_TDLS_ENTRY - 1); idx >= 0; idx--) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + + if (!pTDLS->Valid) + { + RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled); + pTDLS->Valid = TRUE; + NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("%s() -create a new entry \n", __FUNCTION__)); + + break; + } + } + } + + + if (idx < 0) + { + /* Table full !!!!! */ + StatusCode = MLME_REQUEST_DECLINED; + DBGPRINT(RT_DEBUG_ERROR, ("%s() - TDLSEntry table full(only can support %d TDLS session) \n", + __FUNCTION__, MAX_NUM_OF_TDLS_ENTRY)); + } + else if (pTDLS) + { + // + // Process TPK Handshake Message 1 here! + // + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + USHORT Result; + + // RSNIE (7.3.2.25), FTIE (7.3.2.48), Timeout Interval (7.3.2.49) + Result = TDLS_TPKMsg1Process(pAd, +#ifdef WFD_SUPPORT + WfdSubelementLen, +#endif /* WFD_SUPPORT */ + pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen); + if (Result != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - TDLS_TPKMsg1Process() Failed, reason=%d \n", + __FUNCTION__, Result)); + + if (Result == MLME_REQUEST_DECLINED) // if mic error , ignore + { + goto CleanUp; + } + else + { + StatusCode = Result; + goto send_out; + } + } + + // Copy SNonce, Key lifetime + pTDLS->KeyLifetime = le2cpu32(*((PULONG) (TIIe + 3))); + NdisMoveMemory(pTDLS->SNonce, &FTIe[52], 32); + } + + + // + // Update temporarliy settings. Try to match Initiator's capabilities + // + pTDLS->Token = Token; + + // I am Responder.And peer are Initiator + pTDLS->bInitiator = TRUE; + pTDLS->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + + // Copy Initiator's supported rate and filter out not supported rate + pTDLS->SupRateLen = SupRateLen; + NdisMoveMemory(pTDLS->SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pTDLS->SupRate, &pTDLS->SupRateLen); + pTDLS->ExtRateLen = ExtRateLen; + NdisMoveMemory(pTDLS->ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pTDLS->ExtRate, &pTDLS->ExtRateLen); + + // Filter out un-supported ht rates + if ((HtCapLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + // HtCapability carries Responder's capability, so not copy from Initiator here. + RTMPZeroMemory(&pTDLS->HtCapability, SIZE_HT_CAP_IE); + pTDLS->HtCapabilityLen = SIZE_HT_CAP_IE; + NdisMoveMemory(&pTDLS->HtCapability, &HtCap, SIZE_HT_CAP_IE); + } + else + { + pTDLS->HtCapabilityLen = 0; + RTMPZeroMemory(&pTDLS->HtCapability, SIZE_HT_CAP_IE); + } + + // Copy extended capability + NdisMoveMemory(&pTDLS->TdlsExtCap, &ExtCap, sizeof(EXT_CAP_INFO_ELEMENT)); + + // Copy QOS related information + pTDLS->QosCapability = QosCapability; + pTDLS->bWmmCapable = bWmmCapable; +#ifdef WFD_SUPPORT + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + WfdSubelementLen > 0) + { + WfdParseSubElmt(pAd, + &pTDLS->WfdEntryInfo, + (PVOID)WfdSubelement, + WfdSubelementLen); + + /* WFD spec. 4.5.3 Establish WFD Connection using TDLS + * If the type of WFD device indicated in WFD Device Type bits (B1B0) in WFD Device Information field in + * WFD IE within the received TDLS Setup Request frame is different from the expected value, + * the recipient should respond using TDLS Setup Response frame with setting Status Code to 38 + * (The request has not been successful as one or more parameters have invalid values). + */ + if (pTDLS->WfdEntryInfo.wfd_devive_type == WFD_SOURCE_PRIMARY_SINK) + StatusCode = MLME_REQUEST_WITH_INVALID_PARAM; + else + { + switch (pAd->StaCfg.WfdCfg.DeviceType) + { + case WFD_SOURCE: + if (pTDLS->WfdEntryInfo.wfd_devive_type == WFD_SOURCE) + StatusCode = MLME_REQUEST_WITH_INVALID_PARAM; + break; + case WFD_PRIMARY_SINK: + case WFD_SECONDARY_SINK: + if ((pTDLS->WfdEntryInfo.wfd_devive_type == WFD_PRIMARY_SINK) || + (pTDLS->WfdEntryInfo.wfd_devive_type == WFD_SECONDARY_SINK)) + StatusCode = MLME_REQUEST_WITH_INVALID_PARAM; + break; + } + } + + if (StatusCode == MLME_REQUEST_WITH_INVALID_PARAM) + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Peer device type is not the expected value,\nMy WFD Device Type = %d, Peer WFD Device Type = %d\n", + __FUNCTION__, pAd->StaCfg.WfdCfg.DeviceType, pTDLS->WfdEntryInfo.wfd_devive_type)); + else + DBGPRINT(RT_DEBUG_TRACE, ("%s:: My WFD Device Type = %d, Peer WFD Device Type = %d\n", __FUNCTION__, + pAd->StaCfg.WfdCfg.DeviceType, pTDLS->WfdEntryInfo.wfd_devive_type)); + } +#endif /* WFD_SUPPORT */ + } + } + +send_out: + + if (StatusCode != MLME_SUCCESS) + { + NdisZeroMemory(&TmpTDLS, sizeof(RT_802_11_TDLS)); + pTDLS = &TmpTDLS; + NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN); + pTDLS->Token = Token; + } + + TDLS_SetupResponseAction(pAd, pTDLS, RsnLen, RsnIe, FTLen, FTIe, TILen, TIIe, StatusCode); + + if (StatusCode == MLME_SUCCESS) + { + /* Set sendout timer */ + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + RTMPSetTimer(&pTDLS->Timer, Timeout); + pTDLS->Valid = TRUE; + + /* State Change */ + pTDLS->Status = TDLS_MODE_WAIT_CONFIRM; + + } + +CleanUp: +#ifdef WFD_SUPPORT + os_free_mem(pAd, WfdSubelement); +#endif /* WFD_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerSetupRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT StatusCode = MLME_SUCCESS, LocalStatusCode = MLME_SUCCESS; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + UCHAR Token; + UCHAR PeerAddr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen, HtCapLen, ExtCapLen, RsnLen, FTLen, TILen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + UCHAR QosCapability; + BOOLEAN bWmmCapable; + HT_CAPABILITY_IE HtCap; + EXT_CAP_INFO_ELEMENT ExtCap; + INT LinkId = 0xff; + UCHAR TPK[LEN_PMK], TPKName[LEN_PMK_NAME]; + PMAC_TABLE_ENTRY pMacEntry = NULL; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; +#ifdef WFD_SUPPORT + ULONG WfdSubelementLen = 0; + PUCHAR WfdSubelement = NULL; +#endif /* WFD_SUPPORT */ + +#ifdef WFD_SUPPORT + os_alloc_mem(pAd, &WfdSubelement, MAX_VIE_LEN); + if (WfdSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN)); + return; + } +#endif /* WFD_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + // Not TDLS Capable, ignore it + if (!IS_TDLS_SUPPORT(pAd)) + goto CleanUp; + + // Not BSS mode, ignore it + if (!INFRA_ON(pAd)) + goto CleanUp; + + hex_dump("TDLS setup response receive pack", Elem->Msg, Elem->MsgLen); + + // Init all kinds of fields within the packet + NdisZeroMemory(&CapabilityInfo, sizeof(CapabilityInfo)); + NdisZeroMemory(&HtCap, sizeof(HtCap)); + NdisZeroMemory(&ExtCap, sizeof(ExtCap)); + NdisZeroMemory(RsnIe, sizeof(RsnIe)); + NdisZeroMemory(FTIe, sizeof(FTIe)); + NdisZeroMemory(TIIe, sizeof(TIIe)); + + if (!PeerTdlsSetupRspSanity( + pAd, + Elem->Msg, + Elem->MsgLen, +#ifdef WFD_SUPPORT + &WfdSubelementLen, + WfdSubelement, +#endif /* WFD_SUPPORT */ + &Token, + PeerAddr, + &CapabilityInfo, + &SupRateLen, + SupRate, + &ExtRateLen, + ExtRate, + &bWmmCapable, + &QosCapability, + &HtCapLen, + &HtCap, + &ExtCapLen, + &ExtCap, + &StatusCode, + &RsnLen, + RsnIe, + &FTLen, + FTIe, + &TILen, + TIIe)) + { + LocalStatusCode = MLME_REQUEST_DECLINED; + } + + + DBGPRINT(RT_DEBUG_ERROR, ("%s() - received a response from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d\n", + __FUNCTION__, PRINT_MAC(PeerAddr), StatusCode)); + + if (StatusCode != MLME_SUCCESS) + { + COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3); + } + + // Drop not within my TDLS Table that created before ! + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("%s() - can not find the LinkId!\n", __FUNCTION__)); + goto CleanUp; + } + + // Point to the current Link ID + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + // Cancel the timer since the received packet to me. + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + // Received a error code from the Peer TDLS. + // Let's terminate the setup procedure right now. + if (StatusCode != MLME_SUCCESS) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + +#ifdef WFD_SUPPORT + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + (StatusCode == MLME_SECURITY_WEAK)) + pAd->StaCfg.WfdCfg.TdlsSecurity = WFD_TDLS_WEAK_SECURITY; +#endif /* WFD_SUPPORT */ + + DBGPRINT(RT_DEBUG_ERROR, + ("%s() - received a failed StatusCode, terminate the setup procedure \n", __FUNCTION__)); + + goto CleanUp; + } + else + StatusCode = LocalStatusCode; + + // + // Validate the content on Setup Response Frame + // + while (StatusCode == MLME_SUCCESS) + { + // Invalid TDLS State + if (pTDLS->Status != TDLS_MODE_WAIT_RESPONSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s() - Not in TDLS_MODE_WAIT_RESPONSE STATE\n", __FUNCTION__)); + StatusCode = MLME_REQUEST_DECLINED; + break; + } + + // Is the same Dialog Token? + if (pTDLS->Token != Token) + { + DBGPRINT(RT_DEBUG_ERROR,("%s() - Not match with Dialig Token my token = %d, peer token = %d\n", + __FUNCTION__, pTDLS->Token, Token)); + + StatusCode = MLME_REQUEST_DECLINED; + break; + } + + // Process TPK Handshake Message 2 here! + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + USHORT Result; + + // RSNIE (7.3.2.25), FTIE (7.3.2.48), Timeout Interval (7.3.2.49) + Result = TDLS_TPKMsg2Process(pAd, pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen, TPK, TPKName); + if (Result != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() - TDLS_TPKMsg2Process() Failed, reason=%d \n", __FUNCTION__, Result)); + if (Result == MLME_REQUEST_DECLINED) // if mic error , ignore + { + goto CleanUp; + } + else + { + StatusCode = Result; + goto send_out; + } + } + // Copy ANonce, Key lifetime, TPK, TPK Name + pTDLS->KeyLifetime = le2cpu32(*((PULONG) (TIIe + 3))); + NdisMoveMemory(pTDLS->ANonce, &FTIe[20], 32); + NdisMoveMemory(pTDLS->TPK, TPK, LEN_PMK); + NdisMoveMemory(pTDLS->TPKName, TPKName, LEN_PMK_NAME); + } + + // Update parameters + if (StatusCode == MLME_SUCCESS) + { + // I am Initiator. And peer are Responder + pTDLS->bInitiator = FALSE; + // Capabilities + pTDLS->CapabilityInfo = CapabilityInfo; + + pTDLS->SupRateLen = SupRateLen; + pTDLS->ExtRateLen = ExtRateLen; + + // Copy ht capabilities from the Peer TDLS + if ((HtCapLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + NdisMoveMemory(&pTDLS->HtCapability, &HtCap, HtCapLen); + pTDLS->HtCapabilityLen = HtCapLen; + } + else + { + pTDLS->HtCapabilityLen = 0; + RTMPZeroMemory(&pTDLS->HtCapability, SIZE_HT_CAP_IE); + } + + // Copy extended capability + NdisMoveMemory(&pTDLS->TdlsExtCap, &ExtCap, sizeof(EXT_CAP_INFO_ELEMENT)); + + // Copy QOS related information + pTDLS->QosCapability = QosCapability; + pTDLS->bWmmCapable = bWmmCapable; + + // Copy TPK related information + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + // SNonce, Key lifetime + } +#ifdef WFD_SUPPORT + if (WfdSubelementLen > 0) + { + WfdParseSubElmt(pAd, + &pTDLS->WfdEntryInfo, + (PVOID)WfdSubelement, + WfdSubelementLen); + } +#endif /* WFD_SUPPORT */ + + } + + break; + } + + // + // Insert into mac table + // + if (StatusCode == MLME_SUCCESS) + { +#ifdef WFA_TESTBED_FUNCTION_SUPPORT + if (pAd->StaCfg.bSetFailOnSetupConf == TRUE) + goto send_out; +#endif // WFA_TESTBED_FUNCTION_SUPPORT // + + // allocate one MAC entry + pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr); + + if (pMacEntry && IS_ENTRY_TDLS(pMacEntry)) + DBGPRINT(RT_DEBUG_ERROR,("%s() - MacTable Entry exist !!!\n", __FUNCTION__)); + else + pMacEntry = MacTableInsertEntry(pAd, + pTDLS->MacAddr, + &pAd->StaCfg.wdev, + BSS0 + MIN_NET_DEVICE_FOR_TDLS, + OPMODE_STA, + TRUE); + + if (pMacEntry) + { + pTDLS->MacTabMatchWCID = pMacEntry->Aid; + pMacEntry->AuthMode = pAd->StaCfg.wdev.AuthMode; + pMacEntry->WepStatus = pAd->StaCfg.wdev.WepStatus; + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->Sst = SST_ASSOC; + +#ifdef UAPSD_SUPPORT + /* update UAPSD */ + UAPSD_AssocParse(pAd, pMacEntry, &QosCapability, + pAd->StaCfg.UapsdInfo.bAPSDCapable); +#endif /* UAPSD_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, + ("MacTableInsertTDlsEntry - allocate entry #%d, Total= %d\n", + pMacEntry->Aid, pAd->MacTab.Size)); + + // Set WMM capability + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable)) + { + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("TDLS - WMM Capable\n")); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + + TDLS_InitPeerEntryRateCapability(pAd, + pMacEntry, + &CapabilityInfo, + SupRateLen, + SupRate, + HtCapLen, + &HtCap); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pMacEntry, + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, +#ifdef DOT11_VHT_AC + 0, + NULL, +#endif /* DOT11_VHT_AC */ + &HtCap, + HtCapLen); + + // + // Install Peer Key if RSNA Enabled + // + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + // Write to ASIC on-chip table. + if ( pMacEntry->Aid > 1) + { + CIPHER_KEY PairwiseKey; + + PairwiseKey.CipherAlg = CIPHER_AES; + + // Set Peer Key + PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(PairwiseKey.Key, &pTDLS->TPK[16], LEN_TK); + + RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd, + pMacEntry->Aid, + &PairwiseKey); + + RTMP_SET_WCID_SEC_INFO(pAd, + BSS0, + 0, + PairwiseKey.CipherAlg, + pMacEntry->Aid, + PAIRWISEKEYTABLE); + + NdisMoveMemory(&pMacEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); + + pMacEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + pMacEntry->WepStatus = Ndis802_11Encryption3Enabled; + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + + } + } + else + { + StatusCode = MLME_REQUEST_DECLINED; + DBGPRINT(RT_DEBUG_ERROR,("%s() - MacTableInsertEntry failed\n", __FUNCTION__)); + } + } + else + StatusCode = MLME_REQUEST_DECLINED; + +send_out: + + if (StatusCode == MLME_SUCCESS) + { + TDLS_SetupConfirmAction(pAd, pTDLS, RsnLen, RsnIe, FTLen, FTIe, TILen, TIIe, StatusCode); + + pTDLS->ChSwitchTime = TDLS_CHANNEL_SWITCH_TIME; + pTDLS->ChSwitchTimeout = TDLS_CHANNEL_SWITCH_TIMEOUT; + pTDLS->Status = TDLS_MODE_CONNECTED; + pAd->StaCfg.TdlsInfo.TdlsForcePowerSaveWithAP = FALSE; + + TDLS_UAPSD_ENTRY_INIT(pTDLS); + +#ifdef TDLS_AUTOLINK_SUPPORT + if (pAd->StaCfg.TdlsInfo.TdlsAutoLink) + { + PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL; + PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscovEnList, pTDLS->MacAddr, TRUE); + pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsDiscovEnList, pTDLS->MacAddr); + if (pPeerEntry) + { + pPeerEntry->bConnectedFirstTime = TRUE; + pPeerEntry->bConnected = TRUE; + pPeerEntry->RetryCount = 0; + pPeerEntry->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE; + } + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + TDLS_DelBlackEntryByMAC(pTdlsBlackEnList, pTDLS->MacAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + } +#endif // TDLS_AUTOLINK_SUPPORT // + } + else + { + if ((pTDLS->Status >= TDLS_MODE_CONNECTED) && (pTDLS->Token == Token)) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - receive the same token TDLS response !!!\n", __FUNCTION__)); + goto CleanUp; + } + + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + } + +CleanUp: +#ifdef WFD_SUPPORT + os_free_mem(pAd, WfdSubelement); +#endif /* WFD_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerSetupConfAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT StatusCode = MLME_SUCCESS, LocalStatusCode = MLME_SUCCESS; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + UCHAR Token; + UCHAR PeerAddr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + EDCA_PARM EdcaParm; + INT LinkId = 0xff; + UCHAR RsnLen, FTLen, TILen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + PMAC_TABLE_ENTRY pMacEntry = NULL; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s()\n", __FUNCTION__)); + + // Not TDLS Capable, ignore it + if (!IS_TDLS_SUPPORT(pAd)) + return; + + // Not BSS mode, ignore it + if (!INFRA_ON(pAd)) + return; + + hex_dump("TDLS setup confirm receive pack", Elem->Msg, Elem->MsgLen); + + // Init all kinds of fields within the packet + NdisZeroMemory(&EdcaParm, sizeof(EdcaParm)); + NdisZeroMemory(&CapabilityInfo, sizeof(CapabilityInfo)); + NdisZeroMemory(RsnIe, sizeof(RsnIe)); + NdisZeroMemory(FTIe, sizeof(FTIe)); + NdisZeroMemory(TIIe, sizeof(TIIe)); + NdisZeroMemory(&LinkIdent, sizeof(LinkIdent)); + + if (!PeerTdlsSetupConfSanity( + pAd, + Elem->Msg, + Elem->MsgLen, + &Token, + PeerAddr, + &CapabilityInfo, + &EdcaParm, + &StatusCode, + &RsnLen, + RsnIe, + &FTLen, + FTIe, + &TILen, + TIIe)) + { + LocalStatusCode = MLME_REQUEST_DECLINED; + } + + if (StatusCode != MLME_SUCCESS) + { + COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3); + } + + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() received a confirm from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d\n", + PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5], StatusCode)); + + // Drop not within my TDLS Table that created before ! + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + return; + + // Point to the current Link ID + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + // Cancel the timer since the received packet to me. + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + + + // Received a error code from the Peer TDLS. + // Let's terminate the setup procedure right now. + if (StatusCode != MLME_SUCCESS) + { + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + +#ifdef WFD_SUPPORT + if ((pAd->StaCfg.WfdCfg.bWfdEnable) && + (StatusCode == MLME_SECURITY_WEAK)) + pAd->StaCfg.WfdCfg.TdlsSecurity = WFD_TDLS_WEAK_SECURITY; +#endif /* WFD_SUPPORT */ + + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() received a failed StatusCode, terminate the setup procedure \n")); + + return; + } + else + StatusCode = LocalStatusCode; + + // + // Validate the content on Setup Confirm Frame + // + while (StatusCode == MLME_SUCCESS) + { + // Invalid TDLS State + if (pTDLS->Status != TDLS_MODE_WAIT_CONFIRM) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() Not in TDLS_MODE_WAIT_CONFIRM STATE\n")); + StatusCode = MLME_REQUEST_DECLINED; + break; + } + + // Is the same Dialog Token? + if (pTDLS->Token != Token) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() Not match with Dialig Token \n")); + StatusCode = MLME_REQUEST_DECLINED; + break; + } + + // Process TPK Handshake Message 3 here! + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + USHORT Result; + + // RSNIE (7.3.2.25), FTIE (7.3.2.48), Timeout Interval (7.3.2.49) + Result = TDLS_TPKMsg3Process(pAd, pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen); + if (Result != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TPKMsg3Process() Failed, reason=%d \n", Result)); + StatusCode = Result; + break; + } + } + + // Update parameters + if (StatusCode == MLME_SUCCESS) + { + // I am Responder.And peer are Initiator + pTDLS->bInitiator = TRUE; + + // Copy EDCA Parameters + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable)) + NdisMoveMemory(&pTDLS->EdcaParm, &EdcaParm, sizeof(EDCA_PARM)); + else + NdisZeroMemory(&pTDLS->EdcaParm, sizeof(EDCA_PARM)); + + // Copy TPK related information + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + // SNonce, Key lifetime + } + } + + break; + } + + // + // Insert into mac table + // + if (StatusCode == MLME_SUCCESS) + { + // allocate one MAC entry + pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr); + if (pMacEntry && IS_ENTRY_TDLS(pMacEntry)) + DBGPRINT(RT_DEBUG_ERROR,("TDLS - MacTable Entry exist !!!\n")); + else + pMacEntry = MacTableInsertEntry(pAd, pTDLS->MacAddr, &pAd->StaCfg.wdev, BSS0 + MIN_NET_DEVICE_FOR_TDLS, OPMODE_STA, TRUE); + + if (pMacEntry) + { + pTDLS->MacTabMatchWCID = pMacEntry->Aid; + pMacEntry->AuthMode = pAd->StaCfg.wdev.AuthMode; + pMacEntry->WepStatus = pAd->StaCfg.wdev.WepStatus; + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->Sst = SST_ASSOC; + pMacEntry->MatchTdlsEntryIdx = LinkId; + +#ifdef UAPSD_SUPPORT + /* update UAPSD */ + pTDLS->QosCapability |= (pTDLS->EdcaParm.EdcaUpdateCount & 0x0f); + + UAPSD_AssocParse(pAd, pMacEntry, &pTDLS->QosCapability, + pAd->StaCfg.UapsdInfo.bAPSDCapable); +#endif /* UAPSD_SUPPORT */ + + DBGPRINT(RT_DEBUG_ERROR, ("MacTableInsertTDlsEntry - allocate entry #%d, Total= %d\n",pMacEntry->Aid, pAd->MacTab.Size)); + + // Set WMM capability + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable)) + { + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + DBGPRINT(RT_DEBUG_ERROR, ("TDLS - WMM Capable\n")); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + + TDLS_InitPeerEntryRateCapability(pAd, + pMacEntry, + &pTDLS->CapabilityInfo, + pTDLS->SupRateLen, + pTDLS->SupRate, + pTDLS->HtCapabilityLen, + &pTDLS->HtCapability); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pMacEntry, + pTDLS->SupRate, + pTDLS->SupRateLen, + pTDLS->ExtRate, + pTDLS->ExtRateLen, +#ifdef DOT11_VHT_AC + pTDLS->vht_cap_len, + pTDLS->vht_cap, +#endif /* DOT11_VHT_AC */ + &pTDLS->HtCapability, + pTDLS->HtCapabilityLen); + + // + // Install Peer Key if RSNA Enabled + // + if (pAd->StaCfg.wdev.WepStatus != Ndis802_11EncryptionDisabled) + { + // Write to ASIC on-chip table. + if ( pMacEntry->Aid > 1) + { + CIPHER_KEY PairwiseKey; + + PairwiseKey.CipherAlg = CIPHER_AES; + + // Set Peer Key + PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(PairwiseKey.Key, &pTDLS->TPK[16], LEN_TK); + + RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd, + pMacEntry->Aid, + &PairwiseKey); + + RTMP_SET_WCID_SEC_INFO(pAd, + BSS0, + 0, + PairwiseKey.CipherAlg, + pMacEntry->Aid, + PAIRWISEKEYTABLE); + + NdisMoveMemory(&pMacEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); + + pMacEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + pMacEntry->WepStatus = Ndis802_11Encryption3Enabled; + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + + } + + pTDLS->Status = TDLS_MODE_CONNECTED; + pTDLS->ChSwitchTime = TDLS_CHANNEL_SWITCH_TIME; + pTDLS->ChSwitchTimeout = TDLS_CHANNEL_SWITCH_TIMEOUT; + pAd->StaCfg.TdlsInfo.TdlsForcePowerSaveWithAP = FALSE; + + TDLS_UAPSD_ENTRY_INIT(pTDLS); + +#ifdef TDLS_AUTOLINK_SUPPORT + if (pAd->StaCfg.TdlsInfo.TdlsAutoLink) + { + PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL; + PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscovEnList, pTDLS->MacAddr, TRUE); + pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsDiscovEnList, pTDLS->MacAddr); + if (pPeerEntry) + { + pPeerEntry->bConnectedFirstTime = TRUE; + pPeerEntry->bConnected = TRUE; + pPeerEntry->RetryCount = 0; + pPeerEntry->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE; + } + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + TDLS_DelBlackEntryByMAC(pTdlsBlackEnList, pTDLS->MacAddr); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + } +#endif // TDLS_AUTOLINK_SUPPORT // + } + else + { + StatusCode = MLME_REQUEST_DECLINED; + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerSetupConfAction() MacTableInsertEntry failed\n")); + } + } + else + { + if ((pTDLS->Status >= TDLS_MODE_CONNECTED) && (pTDLS->Token == Token)) + { + DBGPRINT(RT_DEBUG_WARN, ("TDLS - TDLS_PeerSetupConfAction() receive the same token TDLS confirm !!!\n")); + return; + } + + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + StatusCode = MLME_REQUEST_DECLINED; + } + + pAd->StaCfg.TdlsInfo.TdlsDialogToken = Token; + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s()\n", __FUNCTION__)); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + PRT_802_11_TDLS pTDLS = NULL; + UINT16 ReasonCode; + BOOLEAN IsViaAP = FALSE; + + DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_MlmeTearDownAction() \n")); + + if (!MlmeTdlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pTDLS, &ReasonCode, &IsViaAP)) + return; + + /* Build TDLS Setup Request Frame via direct link*/ + NStatus = TDLS_TearDownAction(pAd, pTDLS, ReasonCode, TRUE); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeTearDownAction() Build Setup Request Fail !!!\n")); + } + else + { + BOOLEAN TimerCancelled; + + if (!VALID_WCID(pTDLS->MacTabMatchWCID)) + return; + + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, pTDLS->MacAddr); + } + + DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_MlmeTearDownAction() \n")); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_PeerTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR SA[MAC_ADDR_LEN]; + USHORT ReasonCode; + PRT_802_11_TDLS pTDLS = NULL; + INT LinkId = 0xff; + BOOLEAN IsInitator; + BOOLEAN TimerCancelled; + UCHAR FTLen; + UCHAR FTIe[128]; + PHEADER_802_11 pHdr; + + DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_PeerTearDownAction() \n")); + + // Not TDLS Capable, ignore it + if (!IS_TDLS_SUPPORT(pAd)) + return; + + if (!INFRA_ON(pAd)) + return; + + hex_dump("TDLS TearDown receive pack", Elem->Msg, Elem->MsgLen); + + // Init FTIe + NdisZeroMemory(FTIe, sizeof(FTIe)); + + if (!PeerTdlsTearDownSanity(pAd, + Elem->Msg, + Elem->MsgLen, + SA, + &IsInitator, + &ReasonCode, + &FTLen, + FTIe)) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + return; + } + + pHdr = (PHEADER_802_11)Elem->Msg; + + if (pHdr->FC.FrDs == 1) + { + COPY_MAC_ADDR(SA, &pHdr->Addr3); + } + else + { + COPY_MAC_ADDR(SA, &pHdr->Addr2); + } + + DBGPRINT(RT_DEBUG_OFF,("TDLS - PeerTdlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode)); + + // Drop not within my TDLS Table that created before ! + LinkId = TDLS_SearchLinkId(pAd, SA); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsTearDownAction() can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + return; + } + + // Point to the current Link ID + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + // Cancel the timer since the received packet to me. + //RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + // Drop mismatched identifier. + if (pTDLS->bInitiator != IsInitator) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsTearDownAction() pTDLS->bInitiator = %x parse = %x !!!\n", + pTDLS->bInitiator, IsInitator)); + return; + } + + + // clear tdls table entry + if (pTDLS->Valid && MAC_ADDR_EQUAL(SA, pTDLS->MacAddr)) + { +#ifdef TDLS_AUTOLINK_SUPPORT + PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList; + PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList; +#endif // TDLS_AUTOLINK_SUPPORT // + + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Token = 0; + pTDLS->Valid = FALSE; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, SA); + +#ifdef TDLS_AUTOLINK_SUPPORT + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + TDLS_InsertBlackEntryByMAC(pTdlsBlackEnList, SA, TDLS_BLACK_TDLS_BY_TEARDOWN); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock); + + RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); + TDLS_DelDiscoveryEntryByMAC(pTdlsDiscoveryEnList, SA); + RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock); +#endif // TDLS_AUTOLINK_SUPPORT // + } + + DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_PeerTearDownAction() \n")); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_LinkTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)FunctionContext; + PRTMP_ADAPTER pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("TdlsTimeout - Failed to wait for the response, terminate the setup procedure (%02x:%02x:%02x:%02x:%02x:%02x)\n", + pTDLS->MacAddr[0], pTDLS->MacAddr[1], pTDLS->MacAddr[2], pTDLS->MacAddr[3], pTDLS->MacAddr[4], pTDLS->MacAddr[5])); + + /* + 11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA + When no corresponding TDLS Peer Traffic Response frame has been + received within dot11TDLSResponseTimeout after sending a TDLS Peer + Traffic Indication frame, the STA shall tear down the direct link. + */ + pAd = pTDLS->pAd; + if (pTDLS->FlgIsWaitingUapsdTraRsp == TRUE) + { + /* timeout for traffic response frame */ + + /* TODO: tear down the link with the peer */ + DBGPRINT(RT_DEBUG_OFF, ("tdls uapsd> traffic rsp timeout!!!\n")); + pTDLS->FlgIsWaitingUapsdTraRsp = FALSE; + TDLS_TearDownPeerLink(pAd, pTDLS->MacAddr, FALSE); + return; + } + + if ((pTDLS) && (pTDLS->Valid) && (pTDLS->Status < TDLS_MODE_CONNECTED)) + { + pTDLS->Valid = FALSE; + pTDLS->Status = TDLS_MODE_NONE; + } +} +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_tlv.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_tlv.c new file mode 100644 index 000000000..4d45ff3a5 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_tlv.c @@ -0,0 +1,1059 @@ +/**************************************************************************** + * 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: + tdls.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Arvin Tai 17-04-2009 created for 802.11z + */ + +#ifdef DOT11Z_TDLS_SUPPORT + +#include "rt_config.h" + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode) +{ + ULONG TempLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &Category, + 1, &ActCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertStatusCode( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 StatusCode) +{ + ULONG TempLen; + + StatusCode = cpu2le16(StatusCode); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, &StatusCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertReasonCode( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 ReasonCode) +{ + ULONG TempLen; + + ReasonCode = cpu2le16(ReasonCode); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, &ReasonCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertDialogToken( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 DialogToken) +{ + ULONG TempLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &DialogToken, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertLinkIdentifierIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pInitAddr, + IN PUCHAR pRespAddr) +{ + ULONG TempLen; + UCHAR TDLS_IE = IE_TDLS_LINK_IDENTIFIER; + UCHAR TDLS_IE_LEN = TDLS_ELM_LEN_LINK_IDENTIFIER; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &TDLS_IE, + 1, &TDLS_IE_LEN, + 6, pAd->CommonCfg.Bssid, + 6, pInitAddr, + 6, pRespAddr, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 2, &pAd->StaActive.CapabilityInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertSSIDIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertSupportRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertCountryIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + // add country IE, power constraint IE + if (pAd->CommonCfg.bCountryFlag) + { + ULONG TmpLen, TmpLen2=0; + UCHAR TmpFrame[256]; + UCHAR CountryIe = IE_COUNTRY; + + NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); + + // prepare channel information + { + UCHAR regclass; + UCHAR RegluatoryRxtIdent = 221; + UCHAR CoverageClass = 0; + + regclass = TDLS_GetRegulatoryClass(pAd, pAd->CommonCfg.RegTransmitSetting.field.BW, pAd->CommonCfg.Channel); + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &RegluatoryRxtIdent, + 1, ®class, + 1, &CoverageClass, + END_OF_ARGS); + TmpLen2 += TmpLen; + } + + // need to do the padding bit check, and concatenate it + if ((TmpLen2%2) == 0) + { + UCHAR TmpLen3 = TmpLen2 + 4; + MakeOutgoingFrame(pFrameBuf, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 3, pAd->CommonCfg.CountryCode, + TmpLen2+1, TmpFrame, + END_OF_ARGS); + } + else + { + UCHAR TmpLen3 = TmpLen2+3; + MakeOutgoingFrame(pFrameBuf, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 3, pAd->CommonCfg.CountryCode, + TmpLen2, TmpFrame, + END_OF_ARGS); + } + + *pFrameLen = *pFrameLen + TmpLen; + } + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertSupportChannelIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + if (pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp) + { + UCHAR SupportChIe = IE_SUPP_CHANNELS; + UCHAR ch_set[32], list_len; + ULONG buf_len; + + NdisZeroMemory(ch_set, sizeof(ch_set)); + list_len = 0; + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + { + ch_set[list_len] = 1; // first channel + ch_set[list_len+1] = 11; // channel number + list_len += 2; + } + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + ch_set[list_len] = 36; // first channel + ch_set[list_len+1] = 8; // channel number + list_len += 2; + + ch_set[list_len] = 149; // first channel + ch_set[list_len+1] = 4; // channel number + list_len += 2; + } + + if (list_len > 0) { + MakeOutgoingFrame(pFrameBuf, &buf_len, + 1, &SupportChIe, + 1, &list_len, + list_len, &ch_set[0], + END_OF_ARGS); + *pFrameLen = *pFrameLen + buf_len; + } + } + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertExtRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + if (pAd->StaActive.ExtRateLen != 0) + { + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ExtRateIe, + 1, &pAd->StaActive.ExtRateLen, + pAd->StaActive.ExtRateLen, pAd->StaActive.ExtRate, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertQosCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + /* if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) || (pAd->CommonCfg.bWmmCapable)) */ + if (pAd->CommonCfg.bWmmCapable) + { + UCHAR QOS_CAP_IE = 46; + UCHAR QOS_CAP_IE_LEN = 1; + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + + if (pAd->StaCfg.UapsdInfo.bAPSDCapable) + { + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.TDLS_bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.TDLS_bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.TDLS_bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.TDLS_bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.TDLS_MaxSPLength; + } + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &QOS_CAP_IE, + 1, &QOS_CAP_IE_LEN, + 1, &QosInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertWMMIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN BOOLEAN bEnable) +{ + ULONG TempLen; + + if (pAd->CommonCfg.bWmmCapable) + { + QBSS_STA_INFO_PARM QosInfo; + UCHAR WmeParmIe[8] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + + if (pAd->StaCfg.UapsdInfo.bAPSDCapable) + { + if (bEnable) + { + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.TDLS_bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.TDLS_bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.TDLS_bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.TDLS_bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.TDLS_MaxSPLength; + } + DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> UAPSD %d %d %d %d %d!\n", + pAd->CommonCfg.TDLS_bAPSDAC_BE, + pAd->CommonCfg.TDLS_bAPSDAC_BK, + pAd->CommonCfg.TDLS_bAPSDAC_VI, + pAd->CommonCfg.TDLS_bAPSDAC_VO, + pAd->CommonCfg.TDLS_MaxSPLength)); + } + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 8, WmeParmIe, + 1, &QosInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertEDCAParameterSetIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS) +{ + ULONG TempLen; + + if ((WMODE_CAP_N(pAd->CommonCfg.PhyMode) || (pAd->CommonCfg.bWmmCapable)) && (pTDLS->bWmmCapable)) + { + USHORT idx; + + /* When the BSS is QoS capable, then the BSS QoS parameters shall be + * used by the TDLS peer STAs on the AP's channel, and the values + * indicated inside the TDLS Setup Confirm frame apply only for the + * off-channel. The EDCA parameters for the off-channel should be + * the same as those on the AP's channel when QoS is supported by the BSS, + * because this may optimize the channel switching process. + */ + + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + + /* Reset EdcaParam */ + NdisZeroMemory(&pTDLS->EdcaParm, sizeof(EDCA_PARM)); + /* Enable EdcaParm used in non-QBSS. */ + pTDLS->EdcaParm.bValid = TRUE; + + pTDLS->EdcaParm.bQAck = FALSE; + pTDLS->EdcaParm.bQueueRequest = FALSE; + pTDLS->EdcaParm.bTxopRequest = FALSE; + + WmeParmIe[2] = ((UCHAR)pTDLS->EdcaParm.bQAck << 4) + + ((UCHAR)pTDLS->EdcaParm.bQueueRequest << 5) + + ((UCHAR)pTDLS->EdcaParm.bTxopRequest << 6); + + pTDLS->EdcaParm.EdcaUpdateCount = 1; + WmeParmIe[8] = pTDLS->EdcaParm.EdcaUpdateCount & 0x0f; + + WmeParmIe[8] |= pTDLS->EdcaParm.bAPSDCapable << 7; + + /* By hardcoded */ + pTDLS->EdcaParm.Aifsn[0] = 3; + pTDLS->EdcaParm.Aifsn[1] = 7; + pTDLS->EdcaParm.Aifsn[2] = 2; + pTDLS->EdcaParm.Aifsn[3] = 2; + + pTDLS->EdcaParm.Cwmin[0] = 4; + pTDLS->EdcaParm.Cwmin[1] = 4; + pTDLS->EdcaParm.Cwmin[2] = 3; + pTDLS->EdcaParm.Cwmin[3] = 2; + + pTDLS->EdcaParm.Cwmax[0] = 10; + pTDLS->EdcaParm.Cwmax[1] = 10; + pTDLS->EdcaParm.Cwmax[2] = 4; + pTDLS->EdcaParm.Cwmax[3] = 3; + + pTDLS->EdcaParm.Txop[0] = 0; + pTDLS->EdcaParm.Txop[1] = 0; + pTDLS->EdcaParm.Txop[2] = 96; + pTDLS->EdcaParm.Txop[3] = 48; + + for (idx=QID_AC_BE; idx<=QID_AC_VO; idx++) + { + WmeParmIe[10+ (idx*4)] = (idx << 5) + /* b5-6 is ACI */ + ((UCHAR)pTDLS->EdcaParm.bACM[idx] << 4) + /* b4 is ACM */ + (pTDLS->EdcaParm.Aifsn[idx] & 0x0f); /* b0-3 is AIFSN */ + WmeParmIe[11+ (idx*4)] = (pTDLS->EdcaParm.Cwmax[idx] << 4) + /* b5-8 is CWMAX */ + (pTDLS->EdcaParm.Cwmin[idx] & 0x0f); /* b0-3 is CWMIN */ + WmeParmIe[12+ (idx*4)] = (UCHAR)(pTDLS->EdcaParm.Txop[idx] & 0xff); /* low byte of TXOP */ + WmeParmIe[13+ (idx*4)] = (UCHAR)(pTDLS->EdcaParm.Txop[idx] >> 8); /* high byte of TXOP */ + } + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 26, WmeParmIe, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertWMMParameterIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + if ((WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || (pAd->CommonCfg.bWmmCapable)) + { + QBSS_STA_INFO_PARM QosInfo; + ULONG TempLen; + USHORT idx; + + /* When the BSS is QoS capable, then the BSS QoS parameters shall be + * used by the TDLS peer STAs on the AP's channel, and the values + * indicated inside the TDLS Setup Confirm frame apply only for the + * off-channel. The EDCA parameters for the off-channel should be + * the same as those on the AP's channel when QoS is supported by the BSS, + * because this may optimize the channel switching process. + */ + + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + + if (pAd->StaCfg.UapsdInfo.bAPSDCapable) + { + + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.TDLS_bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.TDLS_bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.TDLS_bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.TDLS_bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.TDLS_MaxSPLength; + + DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> UAPSD %d %d %d %d %d!\n", + pAd->CommonCfg.TDLS_bAPSDAC_BE, + pAd->CommonCfg.TDLS_bAPSDAC_BK, + pAd->CommonCfg.TDLS_bAPSDAC_VI, + pAd->CommonCfg.TDLS_bAPSDAC_VO, + pAd->CommonCfg.TDLS_MaxSPLength)); + } + + WmeParmIe[8] |= *(PUCHAR)&QosInfo; + + for (idx=QID_AC_BE; idx<=QID_AC_VO; idx++) + { + WmeParmIe[10+ (idx*4)] = (idx << 5) + // b5-6 is ACI + ((UCHAR)pAd->CommonCfg.APEdcaParm.bACM[idx] << 4) + // b4 is ACM + (pAd->CommonCfg.APEdcaParm.Aifsn[idx] & 0x0f); // b0-3 is AIFSN + WmeParmIe[11+ (idx*4)] = (pAd->CommonCfg.APEdcaParm.Cwmax[idx] << 4) + // b5-8 is CWMAX + (pAd->CommonCfg.APEdcaParm.Cwmin[idx] & 0x0f); // b0-3 is CWMIN + WmeParmIe[12+ (idx*4)] = (UCHAR)(pAd->CommonCfg.APEdcaParm.Txop[idx] & 0xff); // low byte of TXOP + WmeParmIe[13+ (idx*4)] = (UCHAR)(pAd->CommonCfg.APEdcaParm.Txop[idx] >> 8); // high byte of TXOP + } + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 26, WmeParmIe, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +#ifdef DOT11_N_SUPPORT +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertHtCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + UCHAR HtLen; + HT_CAPABILITY_IE HtCapabilityTmp; + + HtLen = sizeof(HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + HtCapabilityTmp.HtCapInfo.ChannelWidth = pAd->CommonCfg.RegTransmitSetting.field.BW; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + HtCapabilityTmp.HtCapInfo.ChannelWidth = pAd->CommonCfg.RegTransmitSetting.field.BW; + + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +#ifdef DOT11N_DRAFT3 +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +/* 20/40 BSS Coexistence (7.3.2.61) */ +VOID +TDLS_InsertBSSCoexistenceIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + //if (pAd->CommonCfg.BACapability.field.b2040CoexistScanSup == 1) + { + UCHAR Length = 1; + BSS_2040_COEXIST_IE BssCoexistence; + + memset(&BssCoexistence, 0, sizeof(BSS_2040_COEXIST_IE)); + BssCoexistence.field.InfoReq = 1; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &BssCoexistIe, + 1, &Length, + 1, &BssCoexistence.word, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertExtCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR Length = sizeof(EXT_CAP_INFO_ELEMENT); + EXT_CAP_INFO_ELEMENT extCapInfo; + + Length = sizeof(EXT_CAP_INFO_ELEMENT); + + NdisZeroMemory(&extCapInfo, Length); + +#ifdef DOT11N_DRAFT3 + if ((pAd->CommonCfg.bBssCoexEnable == TRUE) && + (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) && + (pAd->CommonCfg.Channel <= 14)) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif // DOT11N_DRAFT3 // + + if (pAd->StaCfg.TdlsInfo.TdlsChSwitchSupp) + extCapInfo.TDLSChSwitchSupport = 1; + + if (pAd->StaCfg.UapsdInfo.bAPSDCapable) + extCapInfo.UAPSDBufSTASupport = 1; + + extCapInfo.TDLSSupport = 1; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ExtCapIe, + 1, &Length, + sizeof(EXT_CAP_INFO_ELEMENT), &extCapInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_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; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_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; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertTargetChannel( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TargetCh) +{ + ULONG TempLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &TargetCh, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertRegulatoryClass( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TargetCh, + IN UINT8 ChWidth) +{ + ULONG TempLen; + UCHAR regclass; + UCHAR BandWidth = 0; + + if (ChWidth != 0) + BandWidth = 1; + + regclass = TDLS_GetRegulatoryClass(pAd, BandWidth, TargetCh); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, ®class, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_InsertSecondaryChOffsetIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR Offset) +{ + ULONG TempLen; + UCHAR length = 1; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &NewExtChanIe, + 1, &length, + 1, &Offset, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + +VOID +TDLS_InsertChannelSwitchTimingIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN USHORT SwitchTime, + IN USHORT SwitchTimeOut) +{ + ULONG TempLen; + UCHAR TDLS_IE = IE_TDLS_CHANNEL_SWITCH_TIMING; + UCHAR TDLS_IE_LEN = 4; + UINT16 SwitchTimeBuf = cpu2le16(SwitchTime); + UINT16 SwitchTimeOutBuf = cpu2le16(SwitchTimeOut); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &TDLS_IE, + 1, &TDLS_IE_LEN, + 2, &SwitchTimeBuf, + 2, &SwitchTimeOutBuf, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_SupportedRegulatoryClasses( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR TDLS_IE = IE_SUPP_REG_CLASS; + //UCHAR Length = 6; + //UCHAR SuppClassesList[] = {1,2,3,32,33}; + UCHAR Length = 16; + UCHAR SuppClassesList[] = {1, 2, 3, 4, 12, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33}; + UCHAR regclass; + + regclass = TDLS_GetRegulatoryClass(pAd, pAd->CommonCfg.RegTransmitSetting.field.BW, pAd->CommonCfg.Channel); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &TDLS_IE, + 1, &Length, + 1, ®class, + 15, SuppClassesList, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +#ifdef UAPSD_SUPPORT +VOID TDLS_InsertPuBufferStatus( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR *pPeerMac) +{ + MAC_TABLE_ENTRY *pMacEntry; + ULONG TempLen; + UINT8 Length; + UINT8 IeIdPuBufferStatus; + UINT8 PuBufferStatus; + UINT8 FlgIsAnyPktForBK, FlgIsAnyPktForBE; + UINT8 FlgIsAnyPktForVI, FlgIsAnyPktForVO; + + + /* get pEntry */ + pMacEntry = MacTableLookup(pAd, pPeerMac); + + if (pMacEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such peer in %s!\n", + __FUNCTION__)); + return; + } + + /* init */ + Length = 1; + IeIdPuBufferStatus = IE_TDLS_PU_BUFFER_STATUS; + PuBufferStatus = 0; + + /* get queue status */ + UAPSD_QueueStatusGet(pAd, pMacEntry, + &FlgIsAnyPktForBK, &FlgIsAnyPktForBE, + &FlgIsAnyPktForVI, &FlgIsAnyPktForVO); + PuBufferStatus |= (FlgIsAnyPktForBK == TRUE)? 0x01: 0x00; + PuBufferStatus |= (FlgIsAnyPktForBE == TRUE)? 0x02: 0x00; + PuBufferStatus |= (FlgIsAnyPktForVI == TRUE)? 0x04: 0x00; + PuBufferStatus |= (FlgIsAnyPktForVO == TRUE)? 0x08: 0x00; + + /* init element */ + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &IeIdPuBufferStatus, + 1, &Length, + 1, &PuBufferStatus, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_uapsd.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_uapsd.c new file mode 100644 index 000000000..c2b31c173 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/tdls_uapsd.c @@ -0,0 +1,1801 @@ +/**************************************************************************** + * 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 TDLS UAPSD functions. + +***************************************************************************/ + + +#ifdef UAPSD_SUPPORT + +#define MODULE_TDLS_UAPSD +#include "rt_config.h" + +/* receive a traffic indication frame */ +static VOID TDLS_UAPSD_PeerTrafficIndAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *pElem); +/* receive a traffic response frame */ +static VOID TDLS_UAPSD_PeerTrafficRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *pElem); + +/* build the traffic indication frame */ +static ULONG TDLS_UAPSD_TrafficIndBuild( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac, + OUT UCHAR *pFrameBuf, + OUT UCHAR *pHeader802_3); +/* build the traffic indication frame payload */ +static VOID TDLS_UAPSD_TrafficIndPayloadBuild( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS); + +/* send a traffic indication frame */ +static NDIS_STATUS TDLS_UAPSD_TrafficIndSend( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac); +/* send a traffic response frame */ +static NDIS_STATUS TDLS_UAPSD_TrafficRspSend( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac, + IN UCHAR PeerToken); +/* build the traffic response frame body */ +static VOID TDLS_UAPSD_TrafficRspBuild( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR PeerToken); + +/* get argument number value */ +static UINT32 TDLS_UAPSD_CmdUtilNumGet( + IN CHAR **ppArgv); +/* get argument MAC value */ +static VOID TDLS_UAPSD_CmdUtilMacGet( + IN CHAR **ppArgv, + IN UCHAR *pDevMac); + +/* simulate to send a TDLS Setup request to a peer */ +static VOID TDLS_UAPSD_CmdSimSetupReqSend( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv); + +/* simulate to receive a TDLS Traffic response from a peer */ +static VOID TDLS_UAPSD_CmdSimTrafficRspRcv( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv); + +/* simulate to receive a TDLS Traffic indication from a peer */ +static VOID TDLS_UAPSD_CmdSimTrafficIndRcv( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv); + +/* simulate to change the power save of a peer */ +static VOID TDLS_UAPSD_CmdSimPeerPowerSaveChg( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv); + +/* simulate to change our power save */ +static VOID TDLS_UAPSD_CmdSimSelfPowerSaveChg( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv); + +/* simulate to send a TDLS Traffic response to a peer */ +static VOID TDLS_UAPSD_CmdSimTrafficRspSnd( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv); + + + + +/* public functions */ +/* +======================================================================== +Routine Description: + Initialze TDLS UAPSD function. + +Arguments: + pAd - WLAN control block pointer + pFSM - TDLS Finite State Machine + +Return Value: + TRUE - init ok + FALSE - init fail + +Note: + Peer U-APSD Sleep STA is default feature in spec. + Peer U-APSD Buffer STA is optional feature in spec. +======================================================================== +*/ +BOOLEAN TDLS_UAPSDP_Init( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *pFSM) +{ + /* init FSM */ + StateMachineSetAction(pFSM, TDLS_IDLE, MT2_PEER_TDLS_TRAFFIC_IND, + (STATE_MACHINE_FUNC)TDLS_UAPSD_PeerTrafficIndAction); + StateMachineSetAction(pFSM, TDLS_IDLE, MT2_PEER_TDLS_TRAFFIC_RSP, + (STATE_MACHINE_FUNC)TDLS_UAPSD_PeerTrafficRspAction); + + /* init lock */ + NdisAllocateSpinLock(pAd, &pAd->StaCfg.TdlsInfo.TDLSUapsdLock); + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> initialization ok!\n")); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Release TDLS UAPSD function. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + TRUE - release ok + FALSE - release fail + +Note: +======================================================================== +*/ +BOOLEAN TDLS_UAPSDP_Release( + IN PRTMP_ADAPTER pAd) +{ + /* free lock */ + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TDLSUapsdLock); + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Send a traffic indication frame. + +Arguments: + pAd - WLAN control block pointer + pPeerMac - the peer MAC + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + +Note: + 11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA + + A PU buffer STA shall transmit a unicast TDLS Peer Traffic + Indication frame to a PU sleep STA, through the AP, if and only if + all of the following conditions are met: + + -- A frame with an RA corresponding to a PU sleep STA was placed + into a buffer at the PU buffer STA; + -- The buffer into which the frame was placed contained no other + frames with the same RA; and + -- One or more periods of dot11TDLSPeerUAPSDIndicationWindow + beacon intervals have expired after the last service period. +======================================================================== +*/ +NDIS_STATUS TDLS_UAPSDP_TrafficIndSend( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac) +{ + NDIS_STATUS NStatus; + + + TDLS_SEMLOCK(pAd); + NStatus = TDLS_UAPSD_TrafficIndSend(pAd, pPeerMac); + TDLS_SEMUNLOCK(pAd); + + return NStatus; +} + + +/* +======================================================================== +Routine Description: + Check if ASIC can go to sleep mode. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + Check all TDLS entries and return TRUE if all SPs are closed. +======================================================================== +*/ +BOOLEAN TDLS_UAPSDP_AsicCanSleep( + IN PRTMP_ADAPTER pAd) +{ + RT_802_11_TDLS *pTDLS; + UINT32 IdEntry; + BOOLEAN FlgAllSpClosed = TRUE; + + + TDLS_SEMLOCK(pAd); + + /* check if all SPs are closed */ + for(IdEntry=0; IdEntryStaCfg.TdlsInfo.TDLSEntry[IdEntry]; + + if ((pTDLS->Valid == TRUE) && + (pTDLS->Status == TDLS_MODE_CONNECTED)) + { + UINT32 Wcid = pTDLS->MacTabMatchWCID; + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[Wcid]; + + + if (!IS_ENTRY_TDLS(pEntry)) + continue; + + /* + Two cases we can not sleep: + 1. One of any SP is not ended. + 2. A traffic indication is sent and no response is received. + */ + if ((pEntry->bAPSDFlagSPStart != 0) || + (pTDLS->FlgIsWaitingUapsdTraRsp == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("tdls uapsd> SP not close or Ind sent (%d %d)!\n", + pEntry->bAPSDFlagSPStart, + pTDLS->FlgIsWaitingUapsdTraRsp)); + hex_dump("pEntry=", pEntry->Addr, 6); + FlgAllSpClosed = FALSE; + break; + } + } + } + + TDLS_SEMUNLOCK(pAd); + + return FlgAllSpClosed; +} + + +/* +======================================================================== +Routine Description: + Check if ASIC can go to sleep mode. + +Arguments: + pAd - WLAN control block pointer + PsmOld - Current power save mode + PsmNew - New power save mode + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TDLS_UAPSDP_PsmModeChange( + IN PRTMP_ADAPTER pAd, + IN USHORT PsmOld, + IN USHORT PsmNew) +{ + MAC_TABLE_ENTRY *pMacEntry; + RT_802_11_TDLS *pTDLS; + UINT32 IdTdls; + struct wifi_dev *wdev =&pAd->StaCfg.wdev; + + if (PsmOld == PsmNew) + return; /* no inform needs */ + + /* sanity check */ + /* WPA 802.1x secured port control */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif +#ifdef WAPI_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWAICERT) + || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && + (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + return; /* port not yet secure */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> our PSM mode change!\n")); + + /* indicate the peer */ + TDLS_SEMLOCK(pAd); + + for(IdTdls=0; IdTdlsStaCfg.TdlsInfo.TDLSEntry[IdTdls]; + + if ((pTDLS->Valid) && (pTDLS->Status == TDLS_MODE_CONNECTED)) + { + /* get MAC Entry */ + pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr); + if (pMacEntry == NULL) + continue; /* check next one */ + + /* check if the peer is in ACTIVE mode */ + if (TDLS_UAPSD_ARE_PEER_IN_ACTIVE(pMacEntry)) + { + /* + pMacEntry->RssiSample.LastRssi0 is used to check if + we have ever received any packet from the peer. + */ + /* send a null frame to the peer directly */ + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> send a NULL frame!\n")); + + RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, + pAd->CommonCfg.TxRate, pMacEntry->Aid, + pMacEntry->apidx, TRUE, FALSE, 0); + continue; + } + + /* + Send traffic indication frame to the peer when the peer + is in power-save mode. + */ + TDLS_UAPSD_TrafficIndSend(pAd, pMacEntry->Addr); + } + } + + TDLS_SEMUNLOCK(pAd); +} + + + + +/* private functions */ +/* +======================================================================== +Routine Description: + Display the UAPSD information for a peer. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=01_[PEER MAC] +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdPeerInfoDisplay( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + MAC_TABLE_ENTRY *pMacEntry; + UCHAR PeerMac[6]; + UINT32 IdAcNum; + + + /* get MAC address */ + TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac); + + /* get pEntry */ + pMacEntry = MacTableLookup(pAd, PeerMac); + + if (pMacEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such peer!\n")); + return; + } + + /* display UAPSD information */ + if (TDLS_UAPSD_ARE_PEER_IN_PS(pMacEntry)) + printk("\n EDCA AC UAPSD information: (POWER SAVE)\n"); + else + printk("\n EDCA AC UAPSD information: (ACTIVE)\n"); + /* End of if */ + + if (pMacEntry->MaxSPLength != 0) + { + printk(" Max SP Length: %d (%d frames)\n", + pMacEntry->MaxSPLength, pMacEntry->MaxSPLength<<1); + } + else + printk(" Max SP Length: 0 (all frames)\n"); + /* End of if */ + + printk(" UAPSD/AC AC0 AC1 AC2 AC3"); + printk("\n Tr/De "); + + for(IdAcNum=0; IdAcNum<4; IdAcNum++) + { + printk("%d/%d ", + pMacEntry->bAPSDCapablePerAC[IdAcNum], + pMacEntry->bAPSDDeliverEnabledPerAC[IdAcNum]); + } /* End of for */ + + printk("\n"); +} + + +/* +======================================================================== +Routine Description: + Display our UAPSD information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=02 + + 2. 11.2.1.14 Peer U-APSD + A STA that configured Peer U-APSD at a TDLS peer STA enters power save + mode on a TDLS direct link after the successful transmission to the + TDLS peer STA over the direct link of an acknowledged MPDU with the + Power Management field set to one. +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdSelfInfoDisplay( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + if (TDLS_UAPSD_ARE_WE_IN_PS(pAd)) + printk("\n EDCA AC UAPSD information: (POWER SAVE)\n"); + else + printk("\n EDCA AC UAPSD information: (ACTIVE)\n"); + /* End of if */ + + if (pAd->CommonCfg.MaxSPLength != 0) + { + printk(" Max SP Length: %d (%d frames)\n", + pAd->CommonCfg.MaxSPLength, pAd->CommonCfg.MaxSPLength<<1); + } + else + printk(" Max SP Length: 0 (all frames)\n"); + /* End of if */ + + printk(" AP UAPSD/AC AC0 AC1 AC2 AC3"); + + printk("\n Tr/De %d/%d %d/%d %d/%d %d/%d\n\n", + pAd->CommonCfg.bACMAPSDTr[0], + pAd->CommonCfg.bAPSDAC_BE, + pAd->CommonCfg.bACMAPSDTr[1], + pAd->CommonCfg.bAPSDAC_BK, + pAd->CommonCfg.bACMAPSDTr[2], + pAd->CommonCfg.bAPSDAC_VI, + pAd->CommonCfg.bACMAPSDTr[3], + pAd->CommonCfg.bAPSDAC_VO); + + printk(" TDLS UAPSD/AC AC0 AC1 AC2 AC3"); + + printk("\n Tr/De %d/%d %d/%d %d/%d %d/%d\n", + pAd->CommonCfg.TDLS_bAPSDAC_BE, + pAd->CommonCfg.TDLS_bAPSDAC_BE, + pAd->CommonCfg.TDLS_bAPSDAC_BK, + pAd->CommonCfg.TDLS_bAPSDAC_BK, + pAd->CommonCfg.TDLS_bAPSDAC_VI, + pAd->CommonCfg.TDLS_bAPSDAC_VI, + pAd->CommonCfg.TDLS_bAPSDAC_VO, + pAd->CommonCfg.TDLS_bAPSDAC_VO); + + printk("\n"); +} + + +/* +======================================================================== +Routine Description: + Configure our UAPSD information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=03_1_1_1_1_0 + + [UAPSD for BE] [UAPSD for BK] [UAPSD for VI] [UAPSD for VO] + [Max SP length] +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdConfigure( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + pAd->CommonCfg.TDLS_bAPSDAC_BE = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + pAd->CommonCfg.TDLS_bAPSDAC_BK = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + pAd->CommonCfg.TDLS_bAPSDAC_VI = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + pAd->CommonCfg.TDLS_bAPSDAC_VO = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + pAd->CommonCfg.TDLS_MaxSPLength = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> configure our UAPSD to %d %d %d %d %d\n", + pAd->CommonCfg.TDLS_bAPSDAC_BE, + pAd->CommonCfg.TDLS_bAPSDAC_BK, + pAd->CommonCfg.TDLS_bAPSDAC_VI, + pAd->CommonCfg.TDLS_bAPSDAC_VO, + pAd->CommonCfg.TDLS_MaxSPLength)); +} + + + + +#define TDLS_UAPSD_PEER_SHOW 01 /* tdls uapsd peer display */ +#define TDLS_UAPSD_SELF_SHOW 02 /* tdls uapsd self display */ +#define TDLS_UAPSD_CONFIG 03 /* tdls uapsd configure */ + +#ifdef TDLS_UAPSD_DEBUG +#define TDLS_UAPSD_SIM_SETUP_REQ 51 /* tdls setup request */ +#define TDLS_UAPSD_SIM_TRAFFIC_RSP_RCV 52 /* tdls traffic rsp receive */ +#define TDLS_UAPSD_SIM_TRAFFIC_IND_RCV 53 /* tdls traffic ind receive */ +#define TDLS_UAPSD_SIM_PEER_PS 54 /* tdls peer ps mode change */ +#define TDLS_UAPSD_SIM_PS 55 /* tdls ps mode change */ +#define TDLS_UAPSD_SIM_TRAFFIC_RSP_SND 56 /* tdls traffic rsp send */ +#define TDLS_UAPSD_SIM_BEACON_LOST 57 /* tdls beacon lost */ +#endif /* TDLS_UAPSD_DEBUG */ + +/* +======================================================================== +Routine Description: + Test command. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + 0 - OK + others - FAIL +======================================================================== +*/ +INT TDLS_Ioctl( + IN PRTMP_ADAPTER pAd, + IN PSTRING pArgvIn) +{ + CHAR BufCmd[3] = { 0, 0, 0 }; + CHAR *pArgv, *pParam; + UINT32 Command; + INT32 Argc; + + + /* init */ + pArgv = (CHAR *)pArgvIn; + + /* get command type */ + /* command format is iwpriv ra0 set tdls=[cmd id]_[arg1]_......_[argn] */ + NdisCopyMemory(BufCmd, pArgv, 2); + Command = simple_strtol((PSTRING)BufCmd, 0, 10); + pArgv += 2; /* skip command field */ + + /* get Argc number */ + Argc = 0; + pParam = pArgv; + + while(1) + { + if (*pParam == '_') + Argc ++; + /* End of if */ + + if ((*pParam == 0x00) || (Argc > 20)) + break; + /* End of if */ + + pParam++; + } /* End of while */ + + pArgv++; /* skip _ points to arg1 */ + + /* handle the command */ + switch(Command) + { + case TDLS_UAPSD_PEER_SHOW: /* display peer uapsd info */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> display peer UAPSD information\n")); + TDLS_UAPSD_CmdPeerInfoDisplay(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SELF_SHOW: /* display self uapsd info */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> display self UAPSD information\n")); + TDLS_UAPSD_CmdSelfInfoDisplay(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_CONFIG: /* tdls uapsd configure */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> configure our UAPSD\n")); + TDLS_UAPSD_CmdConfigure(pAd, Argc, pArgv); + break; + +#ifdef TDLS_UAPSD_DEBUG + case TDLS_UAPSD_SIM_SETUP_REQ: /* tdls setup request */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate to send a setup request\n")); + TDLS_UAPSD_CmdSimSetupReqSend(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SIM_TRAFFIC_RSP_RCV: /* tdls traffic response */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate to receive a traffic response\n")); + TDLS_UAPSD_CmdSimTrafficRspRcv(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SIM_TRAFFIC_IND_RCV: /* tdls traffic indication */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate to receive a traffic indication\n")); + TDLS_UAPSD_CmdSimTrafficIndRcv(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SIM_PEER_PS: /* tdls peer power save */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate to change the peer power save\n")); + TDLS_UAPSD_CmdSimPeerPowerSaveChg(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SIM_PS: /* tdls power save */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate to change our power save\n")); + TDLS_UAPSD_CmdSimSelfPowerSaveChg(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SIM_TRAFFIC_RSP_SND: /* tdls traffic response */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate to send traffic response\n")); + TDLS_UAPSD_CmdSimTrafficRspSnd(pAd, Argc, pArgv); + break; + + case TDLS_UAPSD_SIM_BEACON_LOST: /* tdls beacon lost */ + DBGPRINT(RT_DEBUG_TRACE, + ("tdls_cmd> simulate the beacon lost case\n")); + pAd->Mlme.ChannelQuality = 0; + + if (pAd->StaCfg.bAutoConnectByBssid) + pAd->StaCfg.bAutoConnectByBssid = FALSE; + + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + + /* Lost AP, send disconnect & link down event*/ + LinkDown(pAd, FALSE); + break; +#endif /* TDLS_UAPSD_DEBUG */ + + default: /* error command type */ + DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such command!\n")); + return -EINVAL; /* input error */ + } /* End of switch */ + + return 0; /* ok */ +} + + +/* +======================================================================== +Routine Description: + Set our UAPSD. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + 0 - OK + others - FAIL +======================================================================== +*/ +INT Set_TdlsUapsdProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING pArgvIn) +{ + return TDLS_Ioctl(pAd, pArgvIn); +} + + + + +/* private function */ +/* +======================================================================== +Routine Description: + Build the traffic indication frame. + +Arguments: + pAd - WLAN control block pointer + pPeerMac - the peer + pFrameBuf - frame + pHeader802_3 - frame header + +Return Value: + Frame Length + +Note: +======================================================================== +*/ +static ULONG TDLS_UAPSD_TrafficIndBuild( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac, + OUT UCHAR *pFrameBuf, + OUT UCHAR *pHeader802_3) +{ + RT_802_11_TDLS *pTDLS = NULL; + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + ULONG FrameLen = 0; + INT32 LinkId; + BOOLEAN TimerCancelled; + + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + /* search TDLS entry */ + LinkId = TDLS_SearchLinkId(pAd, pPeerMac); + if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s: can not find the LinkId!\n", __FUNCTION__)); + TDLS_UAPSD_REBUILD_LINK(pAd, pPeerMac); + goto LabelExit; + } + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId)); + + pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId); + + /* sanity check */ + if (TDLS_UAPSD_IS_CONN_NOT_BUILT(pTDLS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> link is not yet built " + "so we can not send a traffic ind to the peer!!!")); + goto LabelExit; + } + + if (pTDLS->FlgIsWaitingUapsdTraRsp == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> traffic ind was sent before!\n")); + goto LabelExit; /* has sent it */ + } + + pTDLS->FlgIsWaitingUapsdTraRsp = TRUE; + + /* init packet header */ + MAKE_802_3_HEADER(pHeader802_3, pTDLS->MacAddr, + pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* build the frame */ + TDLS_UAPSD_TrafficIndPayloadBuild(pAd, pFrameBuf, &FrameLen, pTDLS); + + hex_dump("TDLS UAPSD Peer Traffic Ind sending packet", pFrameBuf, FrameLen); + /* + 11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA + When no corresponding TDLS Peer Traffic Response frame has been + received within dot11TDLSResponseTimeout after sending a TDLS Peer + Traffic Indication frame, the STA shall tear down the direct link. + + The default value is 5 seconds. + */ + /* set traffic indication timer */ + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + RTMPSetTimer(&pTDLS->Timer, TDLS_TIMEOUT); + + /* free resources */ +LabelExit: + return FrameLen; +} + + +/* +======================================================================== +Routine Description: + Build the traffic indication frame payload. + +Arguments: + pAd - WLAN control block pointer + pFrameBuf - frame + pFrameLen - frame length + pTDLS - TDLS link entry + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TDLS_UAPSD_TrafficIndPayloadBuild( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS) +{ + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + ULONG TempLen; + UCHAR Token; // Dialog token + + + /* fill remote frame type */ + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + *pFrameLen = TempLen; + + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_PEER_TRAFFIC_INDICATION); + + /* fill Dialog Token */ + TDLS_UAPSD_DIALOG_GET(pAd, Token); + TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + Token); + + /* fill link identifier */ + if (pTDLS->bInitiator) + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pTDLS->MacAddr, pAd->CurrentAddress); + else + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pAd->CurrentAddress, pTDLS->MacAddr); + + /* fill PU buffer status */ + TDLS_InsertPuBufferStatus(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pTDLS->MacAddr); +} + + +/* +======================================================================== +Routine Description: + Send a traffic indication frame. + +Arguments: + pAd - WLAN control block pointer + pPeerMac - the peer MAC + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + +Note: + 11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA + + A PU buffer STA shall transmit a unicast TDLS Peer Traffic + Indication frame to a PU sleep STA, through the AP, if and only if + all of the following conditions are met: + + -- A frame with an RA corresponding to a PU sleep STA was placed + into a buffer at the PU buffer STA; + -- The buffer into which the frame was placed contained no other + frames with the same RA; and + -- One or more periods of dot11TDLSPeerUAPSDIndicationWindow + beacon intervals have expired after the last service period. +======================================================================== +*/ +static NDIS_STATUS TDLS_UAPSD_TrafficIndSend( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac) +{ + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + UCHAR Header802_3[14]; + NDIS_STATUS NStatus = NDIS_STATUS_FAILURE; + + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + /* allocate resources */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + goto LabelExit; + + FrameLen = TDLS_UAPSD_TrafficIndBuild(pAd, pPeerMac, + pOutBuffer, Header802_3); + if (FrameLen <= 0) + goto LabelExit; + + /* + Keep ACTIVE and do not enter sleep mode until all EOSPs are sent + and we will wake up our ASIC in STAHardTransmit() of + TDLS_UAPSD_PKT_SEND_THROUGH_AP() if we are sleep. + */ + ASIC_PS_CAN_NOT_SLEEP(pAd); + + /* send the frame to the peer with AP's help */ + TDLS_UAPSD_PKT_SEND_THROUGH_AP(pAd, Header802_3, pOutBuffer, FrameLen); +/* hex_dump("TDLS traffic indication send pack", pOutBuffer, FrameLen); */ + + NStatus = NDIS_STATUS_SUCCESS; + + /* free resources */ +LabelExit: + if (pOutBuffer != NULL) + MlmeFreeMemory(pAd, pOutBuffer); + return NStatus; +} + + +/* +======================================================================== +Routine Description: + Send a traffic response frame. + +Arguments: + pAd - WLAN control block pointer + pTDLS - the peer entry + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +static NDIS_STATUS TDLS_UAPSD_TrafficRspSend( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pPeerMac, + IN UCHAR PeerToken) +{ + MAC_TABLE_ENTRY *pMacEntry; + RT_802_11_TDLS *pTDLS = NULL; + UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + UCHAR Header802_3[14]; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG TempLen; + INT32 LinkId; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + NDIS_STATUS NStatus = NDIS_STATUS_FAILURE; + + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + /* search TDLS entry */ + LinkId = TDLS_SearchLinkId(pAd, pPeerMac); + if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s: can not find the LinkId!\n", __FUNCTION__)); + TDLS_UAPSD_REBUILD_LINK(pAd, pPeerMac); + goto LabelExit; + } + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId)); + + pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId); + + /* sanity check */ + if (TDLS_UAPSD_IS_CONN_NOT_BUILT(pTDLS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> link is not yet built " + "so we can not send a traffic ind to the peer!!!")); + goto LabelExit; + } + + /* init */ + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, + pAd->CurrentAddress, TDLS_ETHERTYPE); + + /* allocate buffer for transmitting message */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + goto LabelExit; + + /* build the frame */ + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + FrameLen = FrameLen + TempLen; + + TDLS_UAPSD_TrafficRspBuild(pAd, pOutBuffer, &FrameLen, pTDLS, PeerToken); + + hex_dump("TDLS UAPSD Peer Traffic Response sending packet", pOutBuffer, FrameLen); + + /* need to set the power save mode of the peer to ACTIVE */ + /* we will recover its mode after EOSP frame is received */ + pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr); + if (pMacEntry == NULL) + goto LabelExit; + + /* peer can not sleep for a while */ + RTMP_PS_VIRTUAL_WAKEUP_PEER(pMacEntry); + + /* send the frame to the peer without AP's help */ + TDLS_UAPSD_PKT_SEND_TO_PEER(pAd, Header802_3, pOutBuffer, FrameLen, pTDLS); +/* hex_dump("TDLS traffic response send pack", pOutBuffer, FrameLen); */ + + NStatus = NDIS_STATUS_SUCCESS; + + /* free resources */ +LabelExit: + if (pOutBuffer != NULL) + MlmeFreeMemory(pAd, pOutBuffer); + return NStatus; +} + + +/* +======================================================================== +Routine Description: + Build the traffic response frame body. + +Arguments: + pAd - WLAN control block pointer + pFrameBuf - frame + pFrameLen - frame length + pTDLS - TDLS link entry + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TDLS_UAPSD_TrafficRspBuild( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PRT_802_11_TDLS pTDLS, + IN UCHAR PeerToken) +{ + /* fill action code */ + TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_PEER_TRAFFIC_RESPONSE); + + /* fill Dialog Token */ + TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + PeerToken); + + /* fill link identifier */ + if (pTDLS->bInitiator) + { + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pTDLS->MacAddr, pAd->CurrentAddress); + } + else + { + TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pAd->CurrentAddress, pTDLS->MacAddr); + } +} + + +/* +======================================================================== +Routine Description: + Receive a traffic indication frame. + +Arguments: + pAd - WLAN control block pointer + pElem - the frame information + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TDLS_UAPSD_PeerTrafficIndAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *pElem) +{ + UCHAR Token; + UCHAR PeerAddr[6]; + UCHAR PeerAddr1[6]; + ULONG OffsetPuBuff; + INT LinkId = 0xff; + PRT_802_11_TDLS pTDLS = NULL; + PFRAME_802_11 pFrame = (PFRAME_802_11)pElem->Msg; + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> ====> %s\n", __FUNCTION__)); + + /* Not TDLS Capable, ignore it */ + if (!IS_TDLS_SUPPORT(pAd)) + return; + + /* Not BSS mode, ignore it */ + if (!INFRA_ON(pAd)) + return; + + hex_dump("TDLS UAPSD Peer Traffic Ind receive pack", pElem->Msg, pElem->MsgLen); + + /* sanity check */ + if (TDLS_UAPSD_ARE_WE_IN_ACTIVE(pAd)) + return; /* we are not in power-save mode */ + + COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3); + // Drop not within my TDLS Table that created before ! + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_UAPSD_PeerTrafficIndAction() can not find the LinkId!\n")); + return; + } + + // Point to the current Link ID + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + OffsetPuBuff = PeerTdlsBasicSanity(pAd, + pElem->Msg, + pElem->MsgLen, + pTDLS->bInitiator, + &Token, + PeerAddr1); + if (OffsetPuBuff <= 0) + return; + +/* hex_dump("PeerAddr=", PeerAddr, 6); */ + DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> PU Buffer Status = 0x%x\n", + pElem->Msg[OffsetPuBuff+2])); /* 2: skip ID and length field */ + + /* reply a response frame with UP = 5 */ + /* for TDLS UAPSD, all AC will be UAPSD mode */ + TDLS_UAPSD_TrafficRspSend(pAd, PeerAddr, Token); +} + + +/* +======================================================================== +Routine Description: + Receive a traffic response frame. + +Arguments: + pAd - WLAN control block pointer + pElem - the frame information +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TDLS_UAPSD_PeerTrafficRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *pElem) +{ + UCHAR Token; + UCHAR PeerAddr[6]; + UCHAR PeerAddr1[6]; + RT_802_11_TDLS *pTDLS; + INT32 LinkId = 0xff; + BOOLEAN TimerCancelled; + PFRAME_802_11 pFrame = (PFRAME_802_11)pElem->Msg; + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> ====> %s\n", __FUNCTION__)); + + /* Not TDLS Capable, ignore it */ + if (!IS_TDLS_SUPPORT(pAd)) + return; + + /* Not BSS mode, ignore it */ + if (!INFRA_ON(pAd)) + return; + + hex_dump("TDLS UAPSD Peer Traffic Response receive pack", pElem->Msg, pElem->MsgLen); + + COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr2); + // Drop not within my TDLS Table that created before ! + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: can not find the LinkId!\n", __FUNCTION__)); + return; + } + + // Point to the current Link ID + pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + /* sanity check */ + PeerTdlsBasicSanity(pAd, + pElem->Msg, + pElem->MsgLen, + pTDLS->bInitiator, + &Token, + PeerAddr1); + +/* hex_dump("PeerAddr=", PeerAddr, 6); */ + + /* search TDLS entry */ + LinkId = TDLS_SearchLinkId(pAd, PeerAddr); + if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s: can not find the LinkId!\n", __FUNCTION__)); + TDLS_UAPSD_REBUILD_LINK(pAd, PeerAddr); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId)); + + /* cancel waiting flag to avoid tear down the link */ + pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId); + pTDLS->FlgIsWaitingUapsdTraRsp = FALSE; + RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); + + /* check if we can sleep if we are sleep mode */ + RtmpAsicSleepHandle(pAd); +} + + +/* +======================================================================== +Routine Description: + Get argument number value. + +Arguments: + *pArgv - input parameters + +Return Value: + decimal number + +Note: +======================================================================== +*/ +static UINT32 TDLS_UAPSD_CmdUtilNumGet( + IN CHAR **ppArgv) +{ + CHAR Buf[20], *pNum; + UINT32 ID; + + + pNum = (*ppArgv); + + for(ID=0; IDTimeOut = 0; + COPY_MAC_ADDR(pTDLS->MacAddr, PeerMac); + pTDLS->Valid = 1; + + /* search a empty entry */ + for(IdTdls=0; IdTdlsStaCfg.TdlsInfo.TDLSEntry[IdTdls].Valid) + { + NdisMoveMemory(&pAd->StaCfg.TdlsInfo.TDLSEntry[IdTdls], + pTDLS, sizeof(RT_802_11_TDLS_UI)); + break; + } + } + if (IdTdls == MAX_NUM_OF_TDLS_ENTRY) + { + MlmeFreeMemory(pAd, pOutBuffer); + os_free_mem(NULL, pElem); + return; + } + + /* init request frame */ + MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, + pAd->CurrentAddress, TDLS_ETHERTYPE); + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + TDLS_BuildSetupRequest(pAd, pOutBuffer, &FrameLen, + TDLS_UAPSD_ENTRY_GET(pAd, IdTdls)); + hex_dump("Request=", pOutBuffer, FrameLen); + + TDLS_UAPSD_PKT_SEND_THROUGH_AP(pAd, Header802_3, pOutBuffer, FrameLen); + + /* init response frame */ + FrameLen += LENGTH_802_11 + LENGTH_802_1_H; + pElem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + FrameLen; + + /* copy payload type, category, action (3B) */ + memcpy(pElem->Msg + LENGTH_802_11 + LENGTH_802_1_H, + pOutBuffer, 3); + /* status code = 0x00 00 (2B) */ + *(USHORT *)(pElem->Msg + LENGTH_802_11 + LENGTH_802_1_H + 3) = 0x00; + + /* copy others */ + memcpy(pElem->Msg + LENGTH_802_11 + LENGTH_802_1_H + 3 + 2, + pOutBuffer + 3, FrameLen - 3); + + /* handle response frame */ + TDLS_PeerSetupRspAction(pAd, pElem); + + /* free memory */ + MlmeFreeMemory(pAd, pOutBuffer); + os_free_mem(NULL, pElem); +} /* End of TDLS_UAPSD_CmdSimSetupReqSend */ + + +/* +======================================================================== +Routine Description: + Simulate to receive a TDLS Traffic response from a peer. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=52_[PEER MAC] + + 2. In the actual case, the traffic response frame will be handled in + STAHandleRxDataFrame() because the traffic response frame is a + DATA frame, not management action frame. +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdSimTrafficRspRcv( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + MAC_TABLE_ENTRY *pMacEntry; + UCHAR PeerMac[6]; + RT_802_11_TDLS *pTDLS = NULL; + INT32 LinkId; + + + /* get MAC address */ + TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac); + + /* get pEntry */ + pMacEntry = MacTableLookup(pAd, PeerMac); + + if (pMacEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such peer!\n")); + return; + } + + /* search TDLS entry */ + LinkId = TDLS_SearchLinkId(pAd, PeerMac); + if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: can not find the LinkId!\n", __FUNCTION__)); + TDLS_UAPSD_REBUILD_LINK(pAd, PeerMac); + return; + } + + DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> LinkId = %d\n", LinkId)); + + /* cancel waiting flag to avoid tear down the link */ + pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId); + pTDLS->FlgIsWaitingUapsdTraRsp = FALSE; + + /* handle UAPSD SP */ + /* + TDLS uses Ethertype 89-0d frames, as defined in Annex U. + The TDLS payload contains a TDLS Action frame body as is specified + in 7.4.11. The UP shall be AC_VI, unless otherwise specified. + + So these TDLS action frames are DATA frame, not management frame. + */ + UAPSD_TriggerFrameHandle(pAd, pMacEntry, 5); +} + + +/* +======================================================================== +Routine Description: + Simulate to receive a TDLS Traffic indication from a peer. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=53_[PEER MAC] +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdSimTrafficIndRcv( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + UCHAR PeerMac[6]; + MLME_QUEUE_ELEM *pElem = NULL; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + INT32 LinkId; + RT_802_11_TDLS *pTDLS = NULL; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UCHAR RemoteFrameType = PROTO_NAME_TDLS; + ULONG TempLen; + UCHAR Token; // Dialog token + + + /* get MAC address */ + TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac); + + /* allocate resources */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + goto LabelExit; + + /* make up a virtual traffic indication frame */ + /* search TDLS entry */ + LinkId = TDLS_SearchLinkId(pAd, PeerMac); + if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: can not find the LinkId!\n", __FUNCTION__)); + TDLS_UAPSD_REBUILD_LINK(pAd, PeerMac); + goto LabelExit; + } + pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId); + + /* build the frame */ + /* fill remote frame type */ + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + FrameLen = TempLen; + + /* fill action code */ + TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_REQUEST); + + /* fill Dialog Token */ + TDLS_UAPSD_DIALOG_GET(pAd, Token); + TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, + Token); + + /* fill link identifier */ + TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen, + pTDLS->MacAddr, pAd->CurrentAddress); + + /* fill PU buffer status */ + TDLS_InsertPuBufferStatus(pAd, (pOutBuffer + FrameLen), &FrameLen, + pTDLS->MacAddr); + + if (FrameLen <= 0) + goto LabelExit; + +/* hex_dump("TDLS traffic indication send pack", pOutBuffer, FrameLen); */ + + /* allocate resources */ + os_alloc_mem(NULL, (UCHAR **)&pElem, sizeof(MLME_QUEUE_ELEM)); + if (pElem == NULL) + goto LabelExit; + + /* copy the indication frame */ + FrameLen += LENGTH_802_11 + LENGTH_802_1_H; + pElem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + FrameLen; + + /* copy payload */ + memcpy(pElem->Msg + LENGTH_802_11 + LENGTH_802_1_H, + pOutBuffer, FrameLen); + + /* handle it */ + TDLS_UAPSD_PeerTrafficIndAction(pAd, pElem); + + /* free resources */ +LabelExit: + if (pElem != NULL) + os_free_mem(NULL, pElem); + if (pOutBuffer != NULL) + MlmeFreeMemory(pAd, pOutBuffer); +} + + +/* +======================================================================== +Routine Description: + Simulate to change the power save of a peer. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=54_[PEER MAC]_[0/1] +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdSimPeerPowerSaveChg( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + MAC_TABLE_ENTRY *pMacEntry; + UCHAR PeerMac[6]; + UINT32 PeerPsMode; + + + /* get MAC address */ + TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac); + + /* get pEntry */ + pMacEntry = MacTableLookup(pAd, PeerMac); + + if (pMacEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such peer!\n")); + return; + } + + /* change mode */ + PeerPsMode = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + + if (PeerPsMode != 0) + { + pMacEntry->PsMode = PWR_ACTIVE; + DBGPRINT(RT_DEBUG_TRACE, ("tdls_cmd> Change to ACTIVE!\n")); + } + else + { + pMacEntry->PsMode = PWR_SAVE; + DBGPRINT(RT_DEBUG_TRACE, ("tdls_cmd> Change to POWER SAVE!\n")); + } +} + + +/* +======================================================================== +Routine Description: + Simulate to change our power save. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=55_[0/1] +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdSimSelfPowerSaveChg( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + UINT32 PeerPsMode; + + + PeerPsMode = TDLS_UAPSD_CmdUtilNumGet(&pArgv); + + if (PeerPsMode != 0) + { + pAd->StaCfg.Psm = PWR_ACTIVE; + DBGPRINT(RT_DEBUG_TRACE, ("tdls_cmd> Change to ACTIVE!\n")); + } + else + { + pAd->StaCfg.Psm = PWR_SAVE; + DBGPRINT(RT_DEBUG_TRACE, ("tdls_cmd> Change to POWER SAVE!\n")); + } +} + + +/* +======================================================================== +Routine Description: + Simulate to send a TDLS Traffic response to a peer. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + iwpriv ra0 set tdls=56_[PEER MAC] +======================================================================== +*/ +static VOID TDLS_UAPSD_CmdSimTrafficRspSnd( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + MAC_TABLE_ENTRY *pMacEntry; + UCHAR PeerMac[6]; + UCHAR Token = 0; + + + /* get MAC address */ + TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac); + + /* get pEntry */ + pMacEntry = MacTableLookup(pAd, PeerMac); + + if (pMacEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such peer!\n")); + return; + } + + /* send reponse */ + TDLS_UAPSD_TrafficRspSend(pAd, PeerMac, Token); +} + +#endif /* UAPSD_SUPPORT */ + +/* End of tdls_uapsd.c */ diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/wpa.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/wpa.c new file mode 100644 index 000000000..c55596483 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/sta/wpa.c @@ -0,0 +1,372 @@ +/* + *************************************************************************** + * 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: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + + +/* + * inc_byte_array - Increment arbitrary length byte array by one + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the last byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ + +/* + ======================================================================== + + Routine Description: + Process MIC error indication and record MIC error timer. + + Arguments: + pAd Pointer to our adapter + pWpaKey Pointer to the WPA key structure + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReportMicError(RTMP_ADAPTER *pAd, PCIPHER_KEY pWpaKey) +{ + ULONG Now; + UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); + + /* Record Last MIC error time and count */ + NdisGetSystemUpTime(&Now); + if (pAd->StaCfg.MicErrCnt == 0) + { + pAd->StaCfg.MicErrCnt++; + pAd->StaCfg.LastMicErrorTime = Now; + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + } + else if (pAd->StaCfg.MicErrCnt == 1) + { + if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) + { + /* Update Last MIC error time, this did not violate two MIC errors within 60 seconds */ + pAd->StaCfg.LastMicErrorTime = Now; + } + else + { + RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + pAd->StaCfg.LastMicErrorTime = Now; + /* Violate MIC error counts, MIC countermeasures kicks in */ + pAd->StaCfg.MicErrCnt++; + + /* + We shall block all reception + We shall clean all Tx ring and disassoicate from AP after next EAPOL frame + + No necessary to clean all Tx ring, on HardTransmit will stop sending non-802.1X EAPOL packets + if pAd->StaCfg.MicErrCnt greater than 2. + */ + } + } + else + { + /* MIC error count >= 2 */ + /* This should not happen */ + ; + } + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_MIC_FAILURE_REPORT_FRAME, + 1, + &unicastKey, 0); + + if (pAd->StaCfg.MicErrCnt == 2) + { + RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); + } +} + +VOID WpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + UCHAR *mpool; + PEAPOL_PACKET pPacket; + UCHAR Mic[16]; + BOOLEAN bUnicast; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); + + bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); + pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); + + /* init 802.3 header and Fill Packet */ + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + /* Allocate memory for output */ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pPacket = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pPacket, TX_EAPOL_BUFFER); + + pPacket->ProVer = EAPOL_VER; + pPacket->ProType = EAPOLKey; + + pPacket->KeyDesc.Type = WPA1_KEY_DESC; + + /* Request field presented */ + pPacket->KeyDesc.KeyInfo.Request = 1; + + if(pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) + pPacket->KeyDesc.KeyInfo.KeyDescVer = 2; + else /* TKIP */ + pPacket->KeyDesc.KeyInfo.KeyDescVer = 1; + + pPacket->KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); + + /* KeyMic field presented */ + pPacket->KeyDesc.KeyInfo.KeyMic = 1; + + /* Error field presented */ + pPacket->KeyDesc.KeyInfo.Error = 1; + + /* Update packet length after decide Key data payload */ + SET_UINT16_TO_ARRARY(pPacket->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG) + + /* Key Replay Count */ + NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + inc_byte_array(pAd->StaCfg.ReplayCounter, 8); + + /* Convert to little-endian format. */ + *((USHORT *)&pPacket->KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&pPacket->KeyDesc.KeyInfo)); + + + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /* allocate memory */ + if(pOutBuffer == NULL) + { + os_free_mem(NULL, mpool); + return; + } + + /* + Prepare EAPOL frame for MIC calculation + Be careful, only EAPOL frame is counted for MIC calculation + */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, pPacket, + END_OF_ARGS); + + /* Prepare and Fill MIC value */ + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) + { /* AES */ + UCHAR digest[20] = {0}; + RT_HMAC_SHA1(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { /* TKIP */ + RT_HMAC_MD5(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); + } + NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + /* copy frame to Tx ring and send MIC failure report frame to authenticator */ + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], + Header802_3, LENGTH_802_3, + (PUCHAR)pPacket, + CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, FALSE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); +} + + +VOID WpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + /* disassoc from current AP first */ + DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + pAd->StaCfg.bBlockAssoc = TRUE; +} + + +VOID WpaStaPairwiseKeySetting(RTMP_ADAPTER *pAd) +{ + PCIPHER_KEY pSharedKey; + PMAC_TABLE_ENTRY pEntry; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + /* Pairwise key shall use key#0 */ + pSharedKey = &pAd->SharedKey[BSS0][0]; + + NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); + + /* Prepare pair-wise key information into shared key table */ + NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); + pSharedKey->KeyLen = LEN_TK; + NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TK); + NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_MIC], LEN_TKIP_MIC); + + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == Ndis802_11TKIPEnable) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11AESEnable) + pSharedKey->CipherAlg = CIPHER_AES; + else + pSharedKey->CipherAlg = CIPHER_NONE; + + /* Update these related information to MAC_TABLE_ENTRY */ + NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_MIC], LEN_TKIP_MIC); + pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; + + /* Update pairwise key information to ASIC Shared Key Table */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + 0, + pSharedKey); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMP_SET_WCID_SEC_INFO(pAd, + BSS0, + 0, + pSharedKey->CipherAlg, + BSSID_WCID, + SHAREDKEYTABLE); + + RTMP_SET_PORT_SECURED(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : AID(%d) port secured\n", __FUNCTION__, pEntry->Aid)); + +} + + +VOID WpaStaGroupKeySetting(RTMP_ADAPTER *pAd) +{ + PCIPHER_KEY pSharedKey; + + pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.wdev.DefaultKeyId]; + + /* Prepare pair-wise key information into shared key table */ + NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); + pSharedKey->KeyLen = LEN_TK; + NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TK); + NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], LEN_TKIP_MIC); + + /* Update Shared Key CipherAlg */ + pSharedKey->CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11TKIPEnable) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11AESEnable) + pSharedKey->CipherAlg = CIPHER_AES; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) + pSharedKey->CipherAlg = CIPHER_WEP64; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) + pSharedKey->CipherAlg = CIPHER_WEP128; + + /* Update group key information to ASIC Shared Key Table */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + pAd->StaCfg.wdev.DefaultKeyId, + pSharedKey); + + /* STA doesn't need to set WCID attribute for group key */ +} + + +/* + ======================================================================== + + Routine Description: + Send EAPoL-Start packet to AP. + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after link up + 1. Change the correct parameters + 2. Send EAPOL - START + + ======================================================================== +*/ +VOID WpaSendEapolStart(RTMP_ADAPTER *pAd, UCHAR *pBssid) +{ + IEEE8021X_FRAME Packet; + UCHAR Header802_3[14]; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaSendEapolStart\n")); + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + MAKE_802_3_HEADER(Header802_3, pBssid, &pAd->CurrentAddress[0], EAPOL); + + /* Zero message 2 body */ + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.Version = EAPOL_VER; + Packet.Type = EAPOLStart; + Packet.Length = cpu2be16(0); + + /* Copy frame to Tx ring */ + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, &pAd->MacTab.Content[BSSID_WCID], + Header802_3, LENGTH_802_3, (PUCHAR)&Packet, 4, TRUE); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaSendEapolStart\n")); +} + + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/Makefile b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/Makefile new file mode 100644 index 000000000..89edb6ddb --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/Makefile @@ -0,0 +1,5 @@ +all: + gcc -g bin2h.c -o bin2h + gcc -g dat2h.c -o dat2h +clean: + rm -f *.o bin2h dat2h diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/bin2h.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/bin2h.c new file mode 100644 index 000000000..d32b4b7f8 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/bin2h.c @@ -0,0 +1,450 @@ +/* + *************************************************************************** + * MediaTek Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 1997-2012, MediaTek, Inc. + * + * All rights reserved. MediaTek 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 MediaTek. 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 MediaTek Technology, Inc. is obtained. + *************************************************************************** + +*/ + +#include +#include +#include + +int bin2h(char *infname, char *outfname, char *fw_name) +{ + int ret = 0; + FILE *infile, *outfile; + unsigned char c; + int i=0; + + infile = fopen(infname,"r"); + + if (infile == (FILE *) NULL) { + printf("Can't read file %s \n",infname); + return -1; + } + + outfile = fopen(outfname,"w"); + + if (outfile == (FILE *) NULL) { + printf("Can't open write file %s \n",outfname); + return -1; + } + + fputs("/* AUTO GEN PLEASE DO NOT MODIFY IT */ \n",outfile); + fputs("/* AUTO GEN PLEASE DO NOT MODIFY IT */ \n",outfile); + fputs("\n",outfile); + fputs("\n",outfile); + + fprintf(outfile, "UCHAR %s[] = {\n", fw_name); + + while(1) { + char cc[3]; + + c = getc(infile); + + if (feof(infile)) + break; + + memset(cc,0,2); + + if (i >= 16) { + fputs("\n", outfile); + i = 0; + } + + fputs("0x", outfile); + sprintf(cc,"%02x",c); + fputs(cc, outfile); + fputs(", ", outfile); + i++; + } + + fputs("} ;\n", outfile); + fclose(infile); + fclose(outfile); +} + +int main(int argc ,char *argv[]) +{ + char infname[512], ine2pname[512], in_rom_patch[512]; + char outfname[512], oute2pname[512], out_rom_patch[512]; + char chipsets[1024]; + char fw_name[128], e2p_name[128], rom_patch_name[128]; + char *rt28xxdir; + char *chipset, *token; + char *wow, *rt28xx_mode; + int is_bin2h_fw = 0, is_bin2h_rom_patch = 0, is_bin2h_e2p=0; + + rt28xxdir = (char *)getenv("RT28xx_DIR"); + chipset = (char *)getenv("CHIPSET"); + memcpy(chipsets, chipset, strlen(chipset)); + wow = (char *)getenv("HAS_WOW_SUPPORT"); + rt28xx_mode = (char *)getenv("RT28xx_MODE"); + + if(!rt28xxdir) { + printf("Environment value \"RT28xx_DIR\" not export \n"); + return -1; + } + + if(!chipset) { + printf("Environment value \"CHIPSET\" not export \n"); + return -1; + } + + if (strlen(rt28xxdir) > (sizeof(infname)-100)) { + printf("Environment value \"RT28xx_DIR\" is too long!\n"); + return -1; + } + + chipset = strtok(chipsets, " "); + + while (chipset != NULL) { + printf("chipset = %s\n", chipset); + memset(infname, 0, 512); + memset(ine2pname, 0, 512); + memset(outfname, 0, 512); + memset(oute2pname, 0, 512); + memset(fw_name, 0, 128); + memset(e2p_name, 0, 128); + memset(in_rom_patch, 0, 512); + memset(out_rom_patch, 0, 512); + memset(rom_patch_name, 0, 128); + strcat(infname,rt28xxdir); + strcat(ine2pname, rt28xxdir); + strcat(in_rom_patch, rt28xxdir); + strcat(outfname,rt28xxdir); + strcat(oute2pname, rt28xxdir); + strcat(out_rom_patch, rt28xxdir); + is_bin2h_fw = 0; + is_bin2h_rom_patch = 0; + is_bin2h_e2p = 0; + if (strncmp(chipset, "2860",4) == 0) { + strcat(infname,"/mcu/bin/rt2860.bin"); + strcat(outfname,"/include/mcu/rt2860_firmware.h"); + strcat(fw_name, "RT2860_FirmwareImage"); + is_bin2h_fw = 1; + } else if (strncmp(chipset, "2870",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "3090",4) == 0) { + strcat(infname,"/mcu/bin/rt2860.bin"); + strcat(outfname,"/include/mcu/rt2860_firmware.h"); + strcat(fw_name, "RT2860_FirmwareImage"); + is_bin2h_fw = 1; + } else if (strncmp(chipset, "2070",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "3070",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "3572",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "3573",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "3370",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "5370",4) == 0) { + if ((strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) { + strcat(infname,"/mcu/bin/rt2870_wow.bin"); + strcat(outfname,"/include/mcu/rt2870_wow_firmware.h"); + strcat(fw_name, "RT2870_WOW_FirmwareImage"); + is_bin2h_fw = 1; + } else { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } + } else if (strncmp(chipset, "5572",4) == 0) { + strcat(infname,"/mcu/bin/rt2870.bin"); + strcat(outfname,"/include/mcu/rt2870_firmware.h"); + strcat(fw_name, "RT2870_FirmwareImage"); + is_bin2h_fw = 1; + } else if (strncmp(chipset, "5592",4) == 0) { + strcat(infname,"/mcu/bin/rt2860.bin"); + strcat(outfname,"/include/mcu/rt2860_firmware.h"); + strcat(fw_name, "RT2860_FirmwareImage"); + is_bin2h_fw = 1; + } else if ((strncmp(chipset, "mt7601e", 7) == 0) + || (strncmp(chipset, "mt7601u", 7) == 0)) { + strcat(infname,"/mcu/bin/MT7601_formal_1.6.bin"); + //strcat(infname,"/mcu/bin/MT7601.bin"); + strcat(outfname,"/include/mcu/mt7601_firmware.h"); + strcat(fw_name, "MT7601_FirmwareImage"); + is_bin2h_fw = 1; + strcat(ine2pname, "/eeprom/MT7601_USB_V0_D-20130416.bin"); + strcat(oute2pname, "/include/eeprom/mt7601_e2p.h"); + strcat(e2p_name, "MT7601_E2PImage"); + is_bin2h_e2p = 1; + } else if ((strncmp(chipset, "mt7650e", 7) == 0) + || (strncmp(chipset, "mt7650u", 7) == 0) + || (strncmp(chipset, "mt7630e", 7) == 0) + || (strncmp(chipset, "mt7630u", 7) == 0)) { + //strcat(infname, "/mcu/bin/MT7650_E2_hdr.20121031.modify.USB.flow.bin"); // pmu + strcat(infname, "/mcu/bin/MT7650.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210302000.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_10292045.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr.for.PMU.print.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_20121029.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210231140.bin"); // atomic bw + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210181030.bin"); // PMU + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210180939.bin"); // PMU + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210151438.bin"); // led + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210171346.bin"); + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210151547.bin"); + //strcat(infname, "/mcu/bin/MT7650_1012.bin"); + //strcat(infname,"/mcu/bin/MT7610.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_201210031435.bin"); + //strcat(infname,"/mcu/bin/MT7610_201210021430.bin"); // turn on debug log same as 10020138.bin + //strcat(infname,"/mcu/bin/MT7610_201210020138.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_10021442.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_1002.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_shang_1001.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_Lv5.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_Lv4.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_20120919.bin"); // wifi + //strcat(infname,"/mcu/bin/MT7650E2_V01007870_20120921.bin"); // bt + //strcat(infname,"/mcu/bin/MT7650.bin"); + strcat(outfname,"/include/mcu/mt7650_firmware.h"); + strcat(fw_name, "MT7650_FirmwareImage"); + is_bin2h_fw = 1; + } else if ((strncmp(chipset, "mt7610e", 7) == 0) + || (strncmp(chipset, "mt7610u", 7) == 0)) { + //strcat(infname, "/mcu/bin/MT7650_E2_hdr.20121031.modify.USB.flow.bin"); // pmu + strcat(infname, "/mcu/bin/MT7650.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr.20121031.modify.USB.flow.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650E2_3_4V01008449_20121207.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210302000.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_10292045.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr.for.PMU.print.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_20121029.bin"); // pmu + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210231140.bin"); // atomic bw + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210181030.bin"); // PMU + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210181030.bin"); // PMU + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210180939.bin"); // PMU + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210151438.bin"); // led + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210171346.bin"); + //strcat(infname, "/mcu/bin/MT7650_E2_hdr_201210151547.bin"); + //strcat(infname, "/mcu/bin/MT7650_1012.bin"); + //strcat(infname,"/mcu/bin/MT7610.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_201210031435.bin"); + //strcat(infname,"/mcu/bin/MT7610_201210021430.bin"); // turn on debug log same as 10020138.bin + //strcat(infname,"/mcu/bin/MT7610_201210031425.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_10021442.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_shang_1001.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_1002.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_Lv5.bin"); + //strcat(infname,"/mcu/bin/MT7610_201210020138.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_Lv4.bin"); + //strcat(infname,"/mcu/bin/MT7650_E2_hdr_20120919.bin"); + strcat(outfname, "/include/mcu/mt7610_firmware.h"); + strcat(fw_name, "MT7610_FirmwareImage"); + is_bin2h_fw = 1; + + if ((strncmp(chipset, "mt7610e", 7) == 0)) { + strcat(ine2pname, "/eeprom/MT7610U_FEM_V1_1.bin"); + strcat(oute2pname, "/include/eeprom/mt7610e_e2p.h"); + strcat(e2p_name, "MT7610E_E2PImage"); + } else if ((strncmp(chipset, "mt7610u", 7) == 0)) { + strcat(ine2pname, "/eeprom/MT7610U_FEM_V1_1.bin"); + strcat(oute2pname, "/include/eeprom/mt7610u_e2p.h"); + strcat(e2p_name, "MT7610U_E2PImage"); + } + } else if ((strncmp(chipset, "mt7662e", 7) == 0) + || (strncmp(chipset, "mt7662u", 7) == 0) + || (strncmp(chipset, "mt7632e", 7) == 0) + || (strncmp(chipset, "mt7632u", 7) == 0) + || (strncmp(chipset, "mt7612e", 7) == 0) + || (strncmp(chipset, "mt7612u", 7) == 0)) { + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_2SS.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_1SS.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_debug.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130605_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_RADIO_OFF.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_tssi_average.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_tssi_0618.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.4.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.8.bin"); + strcat(infname, "/mcu/bin/MT7662_E3_v1.9.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.7.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.6_20140905.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.6.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.5.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20140220.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20140213.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.3.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20131211.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20131127.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_v1.1.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20131111.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130913.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130904.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130903.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130829.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130826.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130817.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130814.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130813.bin"); + //strcat(infname, "/mcu/bin/mt7662_firmware_e3_20130811.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130729_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130703_b2.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130701_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130624_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130619_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130529_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_COEX_20130528.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_BT_COEX_20130502.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130521_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130520_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130514_tssi_fix.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130514_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130509_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130508_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130507_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130430_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130424.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130423_b2.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130423.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130422.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130419.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130418.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130416.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130415.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130411_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130408_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130402.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130321_b2.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130314_b1.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130313.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130311.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130308.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_latest_0306.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_0306_ram_reset.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_0306.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_0305_new3.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_0305_new.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_2013_03_03.bin"); + //strcat(infname, "/mcu/bin/WIFI_RAM_CODE_ALL_20130304_fpga.bin"); + strcat(outfname, "/include/mcu/mt7662_firmware.h"); + strcat(fw_name, "MT7662_FirmwareImage"); + strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P69.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P48.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e3_hdr_v0.0.0.1.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_v0.0.0.9.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_coex_v0.0.0.2.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_v0.0.0.8.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_v0.0.0.7.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_v0.0.0.6.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_20130426.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_v0.0.0.5.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7612_patch_e1_hdr_0417.bin"); + //strcat(in_rom_patch, "/mcu/bin/mt7662_patch_e1_hdr_v0.0.0.3.bin"); + strcat(out_rom_patch, "/include/mcu/mt7662_rom_patch.h"); + strcat(rom_patch_name, "mt7662_rom_patch"); + strcat(ine2pname, "/eeprom/MT7612E_EEPROM_layout_20131121_2G5G_ePAeLNA_TXTC_off.bin"); + //strcat(ine2pname, "/eeprom/MT7612E3_EEPROM_layout_20131022_2G5G_iPAiLNA_wTSSI_default_slope_offset.bin"); + strcat(oute2pname, "/include/eeprom/mt76x2_e2p.h"); + strcat(e2p_name, "MT76x2_E2PImage"); + is_bin2h_fw = 1; + is_bin2h_rom_patch = 1; + is_bin2h_e2p = 1; + } else if ((strncmp(chipset, "mt7662tu", 8) == 0) + || (strncmp(chipset, "mt7632tu", 8) == 0) + || (strncmp(chipset, "mt7612tu", 8) == 0)) { + strcat(infname, "/mcu/bin/mt7662t_firmware_e1.bin"); + strcat(outfname, "/include/mcu/mt7662t_firmware.h"); + strcat(fw_name, "MT7662T_FirmwareImage"); + strcat(in_rom_patch, "/mcu/bin/mt7662t_patch_e1_hdr.bin"); + strcat(out_rom_patch, "/include/mcu/mt7662t_rom_patch.h"); + strcat(rom_patch_name, "mt7662t_rom_patch"); + is_bin2h_fw = 1; + is_bin2h_rom_patch = 1; + + } else { + printf("unknown chipset = %s\n", chipset); + } + + if (is_bin2h_fw) + bin2h(infname, outfname, fw_name); + + if (is_bin2h_rom_patch) + bin2h(in_rom_patch, out_rom_patch, rom_patch_name); + + if (is_bin2h_e2p) + bin2h(ine2pname, oute2pname, e2p_name); + + chipset = strtok(NULL, " "); + } + + exit(0); +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/dat2h.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/dat2h.c new file mode 100644 index 000000000..00b3756ea --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/dat2h.c @@ -0,0 +1,120 @@ +/* + *************************************************************************** + * MediaTek Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 1997-2012, MediaTek, Inc. + * + * All rights reserved. MediaTek 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 MediaTek. 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 MediaTek Technology, Inc. is obtained. + *************************************************************************** + +*/ + +#include +#include +#include + +int dat2h(char *infname, char *outfname, char *struct_name) +{ + int ret = 0; + FILE *infile, *outfile; + int i=0; + char *check; + + outfile = fopen(outfname,"w"); + + if (outfile == (FILE *) NULL) { + printf("Can't open write file %s \n",outfname); + return -1; + } + + fputs("/* AUTO GEN PLEASE DO NOT MODIFY IT */ \n",outfile); + fputs("/* AUTO GEN PLEASE DO NOT MODIFY IT */ \n",outfile); + fputs("\n",outfile); + fputs("\n",outfile); + + + + infile = fopen(infname,"r"); + + + if (infile == (FILE *) NULL) { + printf("Can't read file %s \n",infname); + fprintf(outfile, "PUCHAR %s = NULL;\n", struct_name); + fclose(outfile); + return -1; + } + + fprintf(outfile, "PUCHAR %s = \n", struct_name); + + + while(1) { + char c[512]; + fgets (c , 510 , infile); + if(feof(infile)) + break; + if(strstr(c,"#The word of \"Default\"")!=NULL) + continue; + + if(c[strlen(c)-1]=='\n') + c[strlen(c)-1] = '\0'; + + fputc('"', outfile); + strcat(c,"\\n\""); + fputs(c, outfile); + + fputs("\n", outfile); + + } + + fputs(";\n", outfile); + fclose(infile); + fclose(outfile); +} + +int main(int argc ,char *argv[]) +{ + char infname[512]; + char outfname[512]; + + char struct_name[128]="default_profile_buffer"; + char *rt28xxdir,*rt28xx_mode; + + rt28xxdir = (char *)getenv("RT28xx_DIR"); + rt28xx_mode = (char *)getenv("RT28xx_MODE"); + + + if(!rt28xxdir) { + printf("Environment value \"RT28xx_DIR\" not export \n"); + return -1; + } + + if (strlen(rt28xxdir) > (sizeof(infname)-100)) { + printf("Environment value \"RT28xx_DIR\" is too long!\n"); + return -1; + } + + memset(infname, 0, 512); + memset(outfname, 0, 512); + strcat(infname,rt28xxdir); + strcat(outfname,rt28xxdir); + if(strncmp(rt28xx_mode, "STA", 3) == 0) + strcat(infname,"/conf/RT2870STA.dat"); + else + strcat(infname,"/conf/RT2870AP.dat"); + + printf("### dat2h input: %s \n",infname); + strcat(outfname,"/include/default_profile.h"); + + dat2h(infname, outfname, struct_name); + + + exit(0); +} diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662_freq_plan.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662_freq_plan.c new file mode 100644 index 000000000..97fe46a3a --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662_freq_plan.c @@ -0,0 +1,137 @@ +#include +#include +#include + +typedef struct _CH_FREQ_MAP_{ + unsigned short channel; + unsigned short freqKHz; +} CH_FREQ_MAP; + +#define FREQ_REF 40 +#define FREQ_REF_CYCLES 89 +#define DOUBLER 1 + +CH_FREQ_MAP CH_HZ_ID_MAP[]= + { + {1, 2412}, + {2, 2417}, + {3, 2422}, + {4, 2427}, + {5, 2432}, + {6, 2437}, + {7, 2442}, + {8, 2447}, + {9, 2452}, + {10, 2457}, + {11, 2462}, + {12, 2467}, + {13, 2472}, + {14, 2484}, + + /* UNII */ + {36, 5180}, + {40, 5200}, + {44, 5220}, + {48, 5240}, + {52, 5260}, + {56, 5280}, + {60, 5300}, + {64, 5320}, + {149, 5745}, + {153, 5765}, + {157, 5785}, + {161, 5805}, + {165, 5825}, + {167, 5835}, + {169, 5845}, + {171, 5855}, + {173, 5865}, + + /* HiperLAN2 */ + {100, 5500}, + {104, 5520}, + {108, 5540}, + {112, 5560}, + {116, 5580}, + {120, 5600}, + {124, 5620}, + {128, 5640}, + {132, 5660}, + {136, 5680}, + {140, 5700}, + + /* Japan MMAC */ + {34, 5170}, + {38, 5190}, + {42, 5210}, + {46, 5230}, + + /* Japan */ + {183, 4915}, + {184, 4920}, + {185, 4925}, + {187, 4935}, + {188, 4940}, + {189, 4945}, + {192, 4960}, + {196, 4980}, + {200, 5000}, + {204, 5020}, + {208, 5040}, /* Japan, means J08 */ + {212, 5060}, /* Japan, means J12 */ + {216, 5080}, /* Japan, means J16 */ +}; + +int CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP)/sizeof(CH_FREQ_MAP)); + +void MapChannelID2KHZ( + unsigned char Ch, + double *pFreq) +{ + int chIdx; + for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++) + { + if ((Ch) == CH_HZ_ID_MAP[chIdx].channel) + { + (*pFreq) = CH_HZ_ID_MAP[chIdx].freqKHz * 1000; + break; + } + } + if (chIdx == CH_HZ_ID_MAP_NUM) + (*pFreq) = 2412000; +} + +int main(int argc, char *argv[]) +{ + unsigned long fcal_target, integer, fraction; + double fvco, n, freq_ref_cycles, freq_ref, fch = 0; + int i; + + freq_ref_cycles = FREQ_REF_CYCLES; + freq_ref = FREQ_REF; + + for (i = 0; i < CH_HZ_ID_MAP_NUM; i++) { + /* FCAL target */ + MapChannelID2KHZ(CH_HZ_ID_MAP[i].channel, &fch); + + if (CH_HZ_ID_MAP[i].channel <= 14) { + fvco = (fch / 1000) * 4 / 3; + } else + fvco = (fch / 1000) * 2 / 3; + + //printf("%f\n", fvco); + fcal_target = (unsigned long)(((freq_ref_cycles / freq_ref * fvco) + 1) + 0.5); + + /* SDM integer & fraction */ + n = fvco / freq_ref; + + //printf("%f\n", n); + + integer = (unsigned long)(n); + fraction = (unsigned long)((n - integer) * (1 << 20)); + + printf("\t{%d, %ld, %ld, %ld},\n", CH_HZ_ID_MAP[i].channel, fcal_target, integer, fraction); + } + + return 0; +} diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/mt7662e_ap.sh b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662e_ap.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/mt7662e_ap.sh rename to package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662e_ap.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/mt7662e_sta.sh b/package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662e_sta.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/mt7662e_sta.sh rename to package/lean/mt/drivers/mt7612e/src/mt76x2/tools/mt7662e_sta.sh diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2/tx_rx/wdev_tx.c b/package/lean/mt/drivers/mt7612e/src/mt76x2/tx_rx/wdev_tx.c new file mode 100644 index 000000000..b2bb19a54 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2/tx_rx/wdev_tx.c @@ -0,0 +1,321 @@ +/* + *************************************************************************** + * 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: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + +INT rtmp_wdev_idx_unreg(RTMP_ADAPTER *pAd, struct wifi_dev *wdev) +{ + INT idx; + ULONG flags; + + if (!wdev) + return -1; + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + for (idx = 0; idx < WDEV_NUM_MAX; idx++) { + if (pAd->wdev_list[idx] == wdev) { + DBGPRINT(RT_DEBUG_WARN, + ("unregister wdev(type:%d, idx:%d) from wdev_list\n", + wdev->wdev_type, wdev->wdev_idx)); + pAd->wdev_list[idx] = NULL; + wdev->wdev_idx = WDEV_NUM_MAX; + break; + } + } + + if (idx == WDEV_NUM_MAX) { + DBGPRINT(RT_DEBUG_ERROR, + ("Cannot found wdev(%p, type:%d, idx:%d) in wdev_list\n", + wdev, wdev->wdev_type, wdev->wdev_idx)); + DBGPRINT(RT_DEBUG_OFF, ("Dump wdev_list:\n")); + for (idx = 0; idx < WDEV_NUM_MAX; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("Idx %d: 0x%p\n", idx, pAd->wdev_list[idx])); + } + } + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + + return ((idx < WDEV_NUM_MAX) ? 0 : -1); + +} + + +INT rtmp_wdev_idx_reg(RTMP_ADAPTER *pAd, struct wifi_dev *wdev) +{ + INT idx; + ULONG flags; + + if (!wdev) + return -1; + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + for (idx = 0; idx < WDEV_NUM_MAX; idx++) { + if (pAd->wdev_list[idx] == wdev) { + DBGPRINT(RT_DEBUG_WARN, + ("wdev(type:%d) already registered and idx(%d) %smatch\n", + wdev->wdev_type, wdev->wdev_idx, + ((idx != wdev->wdev_idx) ? "mis" : ""))); + break; + } + if (pAd->wdev_list[idx] == NULL) { + pAd->wdev_list[idx] = wdev; + break; + } + } + + wdev->wdev_idx = idx; + if (idx < WDEV_NUM_MAX) { + DBGPRINT(RT_DEBUG_TRACE, ("Assign wdev_idx=%d\n", idx)); + } + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + + return ((idx < WDEV_NUM_MAX) ? idx : -1); +} + +#ifdef DELAYED_TCP_ACK +UINT flush_tcp_ack_queue(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY pEntry, BOOLEAN bCancelTimer) +{ + PNDIS_PACKET pPacket; + BOOLEAN Cancelled; + UINT cnt = 0; + + if (bCancelTimer && pEntry->QueueAckTimerRunning == TRUE) + RTMPCancelTimer(&pEntry->QueueAckTimer, &Cancelled); + + pEntry->QueueAckTimerRunning = FALSE; + + while (1) + { + pPacket = skb_dequeue(&pEntry->ack_queue); + if (pPacket == NULL) + break; + + cnt++; + APSendPacket(pAd, pPacket); + } + + return cnt; +} + +VOID RTMPQueueAckPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + PNDIS_PACKET pPacket; + UINT cnt= 0; + if (pEntry) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + cnt = flush_tcp_ack_queue(pAd, pEntry, FALSE); + pAd->CommonCfg.AckTimeout += cnt; + + if (cnt <= TCP_ACK_BURST_LEVEL) + pAd->CommonCfg.TcpAck[cnt]++; + else + printk("TcpAck: cnt not range=%d\n", cnt); + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } +} + +/* Delayed TCP Ack */ +BOOLEAN delay_tcp_ack(RTMP_ADAPTER *pAd, UCHAR wcid, PNDIS_PACKET pPacket) +{ + PUCHAR pSrcBuf; + UINT32 pktLen, qlen; + PMAC_TABLE_ENTRY pEntry; + BOOLEAN bDelay = FALSE; + pEntry = &pAd->MacTab.Content[wcid]; + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + pktLen = GET_OS_PKT_LEN(pPacket); + + if (pAd->CommonCfg.ACKQEN == 1) + { + /* get Ethernet protocol field*/ + USHORT TypeLen = OS_NTOHS(*((UINT16 *)(pSrcBuf + 12))); + + /* bypass VALN 802.1Q field */ + if(TypeLen == 0x8100) + pSrcBuf += 4; + else if ((TypeLen==0x9100) || (TypeLen==0x9200) || (TypeLen==0x9300)) + pSrcBuf += 8; + + if ((TypeLen == 0x0800) /* Type: IP (0x0800) */ + && (pSrcBuf[23] == 0x06) /* Protocol: TCP (0x06) */ + && (pktLen >= 48) && ((pSrcBuf[47]&0x10) == 0x10)) /* Flags: Ack bit is set */ + { + skb_queue_tail(&pEntry->ack_queue, pPacket); + qlen = skb_queue_len(&pEntry->ack_queue); + bDelay = TRUE; + + if (qlen == 1) + { + if (pEntry->QueueAckTimerRunning == FALSE) + { + DBGPRINT(RT_DEBUG_LOUD, ("found tcp ack..\n")); + RTMPSetTimer(&pEntry->QueueAckTimer, pAd->CommonCfg.AckWaitTime); + pEntry->QueueAckTimerRunning = TRUE; + } + } + else if ((qlen >= pAd->CommonCfg.Acklen) + || ((pSrcBuf[47]&0x03) != 0) /* Flags: FIN(bit0) or SYN(bit1) is set */ + || (pktLen > 66)) /* TCP ACK with other payload in IPv4 format */ + { + pAd->CommonCfg.AckNOTimeout += flush_tcp_ack_queue(pAd, pEntry, TRUE); + } + } + } + else + { + flush_tcp_ack_queue(pAd, pEntry, TRUE); + } + + return bDelay; +} +#endif /* DELAYED_TCP_ACK */ + +/* +======================================================================== +Routine Description: + Early checking and OS-depened parsing for Tx packet to AP device. + +Arguments: + NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. + PPNDIS_PACKET ppPacketArray The packet array need to do transmission. + UINT NumberOfPackets Number of packet in packet array. + +Return Value: + NONE + +Note: + This function do early checking and classification for send-out packet. + You only can put OS-depened & AP related code in here. +======================================================================== +*/ +VOID wdev_tx_pkts(NDIS_HANDLE dev_hnd, PPNDIS_PACKET pkt_list, UINT pkt_cnt, struct wifi_dev *wdev) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)dev_hnd; + PNDIS_PACKET pPacket; + BOOLEAN allowToSend; + UCHAR wcid = MCAST_WCID; + UINT Index; + + + + for (Index = 0; Index < pkt_cnt; Index++) + { + pPacket = pkt_list[Index]; + + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + { + /* Drop send request since hardware is in reset state */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + continue; + } + +#ifdef RT_CFG80211_SUPPORT + if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP && (wdev->Hostapd != Hostapd_CFG) +#ifdef RT_CFG80211_P2P_SUPPORT + && (!RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) +#endif /*RT_CFG80211_P2P_SUPPORT*/ + ) + { + /* Drop send request since hardware is in reset state */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + continue; + } +#endif /*RT_CFG80211_SUPPORT*/ + + if ((wdev->allow_data_tx == TRUE) && (wdev->tx_pkt_allowed)) + allowToSend = wdev->tx_pkt_allowed(pAd, wdev, pPacket, &wcid); + else + allowToSend = FALSE; + + if (allowToSend == TRUE) + { + RTMP_SET_PACKET_WCID(pPacket, wcid); + RTMP_SET_PACKET_WDEV(pPacket, wdev->wdev_idx); + NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); + pAd->RalinkCounters.PendingNdisPacketCount++; + + /* + WIFI HNAT need to learn packets going to which interface from skb cb setting. + @20150325 + */ +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) +#if !defined(CONFIG_RA_NAT_NONE) + if (ra_sw_nat_hook_tx != NULL) + { + ra_sw_nat_hook_tx(pPacket, 0); + } +#endif +#endif + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DELAYED_TCP_ACK + if(!delay_tcp_ack(pAd, wcid, pPacket)) +#endif /* DELAYED_TCP_ACK */ +#ifdef REDUCE_TCP_ACK_SUPPORT + if (ReduceTcpAck(pAd, pPacket) == FALSE) +#endif /* REDUCE_TCP_ACK_SUPPORT */ + { + BOOLEAN bResult = APSendPacket(pAd, pPacket); +#ifdef MWDS + if((wcid == MCAST_WCID) && (bResult == NDIS_STATUS_SUCCESS)) + MWDSSendClonePacket(pAd, pPacket, NULL); +#endif /* MWDS */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef RT_CFG80211_P2P_SUPPORT + if (RTMP_GET_PACKET_OPMODE(pPacket)) + APSendPacket(pAd, pPacket); + else +#endif /* RT_CFG80211_P2P_SUPPORT */ + STASendPacket(pAd, pPacket); + } +#endif /* CONFIG_STA_SUPPORT */ + } else { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + + /* Dequeue outgoing frames from TxSwQueue[] and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2_ap/Kconfig b/package/lean/mt/drivers/mt7612e/src/mt76x2_ap/Kconfig new file mode 100644 index 000000000..69837e774 --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2_ap/Kconfig @@ -0,0 +1,171 @@ +config MT76X2_AP + tristate "MediaTek MT7620/MT7602E/7612E 802.11 AP driver" + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV + +config MT76X2_AP_LED + bool "LED support" + depends on MT76X2_AP + default y + +config MT76X2_AP_LED_SOFT + bool "Soft LED support" + depends on MT76X2_AP && !MT76X2_AP_LED && RALINK_GPIO_LED + default n + +config MT76X2_AP_LED_SOFT_GPIO + int "Soft LED GPIO pin (dev #0)" + depends on MT76X2_AP + depends on MT76X2_AP_LED_SOFT + default -1 + +config MT76X2_AP_LED_SOFT_GPIO_DEV1 + int "Soft LED GPIO pin (dev #1)" + depends on MT76X2_AP + depends on MT76X2_AP_LED_SOFT + depends on (RT_FIRST_IF_MT7602E || RT_FIRST_IF_MT7612E || RT_FIRST_IF_MT7620) && (RT_SECOND_IF_MT7602E || RT_SECOND_IF_MT7612E) + default -1 + +config MT76X2_AP_LLTD + bool "LLTD (Link Layer Topology Discovery Protocol)" + depends on MT76X2_AP + default y + +config MT76X2_AP_WDS + bool "WDS support" + depends on MT76X2_AP + default y + +config MT76X2_AP_MBSS + bool "MBSSID support" + depends on MT76X2_AP + default y + +config MT76X2_AP_MBSS_NEW_MBSSID_MODE + bool "New MBSSID mode support" + depends on MT76X2_AP + depends on MT76X2_AP_MBSS + default n + +config MT76X2_AP_APCLI + bool "AP-Client support" + depends on MT76X2_AP + default y + +config MT76X2_AP_APCLI_CERT + bool "AP-Client TGn Cert support" + depends on MT76X2_AP + depends on MT76X2_AP_APCLI + default n + +config MT76X2_AP_APCLI_AUTO_BW + bool "AP-Client Auto Bandwidth Support" + depends on MT76X2_AP + depends on MT76X2_AP_APCLI + default n + +config MT76X2_AP_MAC_REPEATER + bool "MAC Repeater Mode support" + depends on MT76X2_AP + depends on MT76X2_AP_APCLI + default n + +config MT76X2_AP_MWDS + bool "Wireless Mixed Bridge Mode (MWDS)" + depends on MT76X2_AP + select MT76X2_AP_APCLI + default n + +config MT76X2_AP_SMART_MESH + bool "Smart Mesh" + depends on MT76X2_AP + select MT76X2_AP_MWDS + default n + +config MT76X2_AP_CON_WPS + bool "Concurrent WPS support" + depends on MT76X2_AP + depends on MT76X2_AP_APCLI + depends on RT_WSC_V2 + default n + +config MT76X2_AP_AIRPLAY + bool "AirPlay support" + depends on MT76X2_AP + default n + +config MT76X2_AP_DFS + bool "DFS support" + depends on MT76X2_AP + default n + +config MT76X2_AP_CARRIER + bool "Carrier Detection support" + depends on MT76X2_AP + default n + +config MT76X2_AP_GREENAP + bool "Green AP mode support" + depends on MT76X2_AP + depends on RT_FIRST_IF_MT7620 + +config MT76X2_AP_IDS + bool "IDS (Intrusion Detection System) support" + depends on MT76X2_AP + default n + +config MT76X2_AP_DLS + bool "802.11e DLS (Direct-Link Setup) support" + depends on MT76X2_AP + default n + +config MT76X2_AP_80211AC_VHT + bool "802.11ac support" + depends on MT76X2_AP + depends on (RT_FIRST_IF_MT7612E || RT_SECOND_IF_MT7612E) + default y + +config MT76X2_AP_TXBF_SUPPORT + bool "Tx Beam Forming support" + depends on MT76X2_AP + depends on (RT_FIRST_IF_MT7612E || RT_SECOND_IF_MT7612E) + default n + +choice + prompt "MT7620 Power Design" + depends on MT76X2_AP + depends on RT_FIRST_IF_MT7620 + default MT76X2_AP_INTERNAL_PA_INTERNAL_LNA +config MT76X2_AP_INTERNAL_PA_INTERNAL_LNA + bool "Internal PA & Internal LNA" +config MT76X2_AP_INTERNAL_PA_EXTERNAL_LNA + bool "Internal PA & External LNA" +config MT76X2_AP_EXTERNAL_PA_EXTERNAL_LNA + bool "External PA & External LNA" +endchoice + +config MT76X2_AP_RTMP_INTERNAL_TX_ALC + bool "MT7620 TSSI Compensation (Internal TX ALC)" + depends on MT76X2_AP + depends on RT_FIRST_IF_MT7620 + depends on !MT76X2_AP_EXTERNAL_PA_EXTERNAL_LNA + default n + +config MT76X2_AP_RTMP_TEMPERATURE_COMPENSATION + bool "MT7620 Temperature Compensation (External TX ALC)" + depends on MT76X2_AP + depends on RT_FIRST_IF_MT7620 + default n + +config MT76X2_AP_ADJ_PWR_CONSUMPTION + bool "MT7620 Reduce Power Consumption" + depends on MT76X2_AP + depends on RT_FIRST_IF_MT7620 + default n + +config RT_READ_MAC_FROM_MTD + bool "Read and set MAC address from MTD/EEPROM" + depends on (RT_FIRST_IF_MT7615E && RT_SECOND_IF_MT7612E) + default y + diff --git a/package/lean/mt/drivers/mt7612e/src/mt76x2_ap/Makefile b/package/lean/mt/drivers/mt7612e/src/mt76x2_ap/Makefile new file mode 100644 index 000000000..641d2ae1f --- /dev/null +++ b/package/lean/mt/drivers/mt7612e/src/mt76x2_ap/Makefile @@ -0,0 +1,560 @@ +RT_DRV_DIR := mt76x2 +RT_DRV_PATH := ../$(RT_DRV_DIR) +RT_DRV_NAME := mt76x2_ap + + + + +obj-m += $(RT_DRV_NAME).o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_md5.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_sha2.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_hmac.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_aes.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_arc4.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/mlme.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/action.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ba_action.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_wep.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_wpa.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_tkip.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_aes.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_data.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_data_pci.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_mac_pci.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_sync.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_sanity.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_info.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_cfg.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_profile.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_asic.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_cmd.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_radar.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rtmp_init.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rtmp_init_inf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rtmp_timer.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rt_channel.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rt_os_util.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/spectrum.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/txpower.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/scan.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ps.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/uapsd.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/eeprom.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ee_flash.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ee_efuse.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ee_prom.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/tx_rx/wdev_tx.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mgmt/mgmt_entrytb.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mgmt/mgmt_ht.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mac/rtmp_mac.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mcu/mcu.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/rf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/rt_rf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/phy.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/chips/rtmp_chip.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/rate_ctrl/ra_ctrl.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/rate_ctrl/alg_legacy.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/rate_ctrl/alg_grp.o +#$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/rate_ctrl/alg_ags.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_assoc.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_auth.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_connect.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_mlme.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_sanity.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_sync.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_wpa.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_data.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_autoChSel.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_qload.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_cfg.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/ap_ioctl.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_proc.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_linux.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_profile.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_main_dev.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_rbus_pci_drv.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_rbus_pci_util.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rt_pci_rbus.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/multi_main_dev.o + +### MT7620 (RBUS) +ifeq ($(CHIP_MT7620),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/chips/rt6352.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/chips/rtxx_dft.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rtmp_swmcu.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_rf_cal.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_loft_cal.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/rlt_rf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/rtmp_phy.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mac/ral_omac.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/rbus_main_dev.o +ifeq ($(CONFIG_RT_ATE),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ate/chips/rt6352_ate.o +endif +endif + +### MT7602E/MT7612E (PCIe) + +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/chips/rt65xx.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/chips/mt76x2.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mcu/mcu_and.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/mt_rf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/phy/rlt_phy.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mac/ral_nmac.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/pci_main_dev.o +ifeq ($(CONFIG_RT_ATE),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ate/chips/mt76x2_ate.o +endif + + +ifeq ($(CONFIG_RT_ATE),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ate/common/rt_ate.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ate/common/ate_pci.o +ifeq ($(CONFIG_RT_QA),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ate/common/rt_qa.o +endif +endif + +ifeq ($(CONFIG_AP_LED),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rt_led.o +endif + +ifeq ($(CONFIG_AP_WDS),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_wds.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_wds_inf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/client_wds.o +endif + +ifeq ($(CONFIG_AP_MBSS),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_mbss.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_mbss_inf.o +endif + +ifeq ($(CONFIG_AP_APCLI),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_apcli.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_apcli_inf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/apcli_assoc.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/apcli_auth.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/apcli_ctrl.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/apcli_sync.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_mat.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_mat_iparp.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_mat_pppoe.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_mat_ipv6.o +ifeq ($(CONFIG_AP_APCLI_AUTO_BW),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/apcli_autobw.o +endif +ifeq ($(CONFIG_AP_MAC_REPEATER),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_repeater.o +endif +endif + +ifeq ($(CONFIG_AP_MWDS),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/mwds.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/routing_tab.o +ifeq ($(CONFIG_AP_SMART_MESH),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/smart_mesh.o +endif +endif + +ifeq ($(CONFIG_AP_80211AC_VHT),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/vht.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/mgmt/mgmt_vht.o +endif + +ifeq ($(CONFIG_AP_GREENAP),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/hw_ctrl/greenap.o +endif + +ifeq ($(CONFIG_AP_DLS),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_dls.o +endif + +ifeq ($(CONFIG_AP_IDS),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_ids.o +endif + +ifeq ($(CONFIG_AP_DFS),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_dfs.o +endif + +ifeq ($(CONFIG_AP_CARRIER),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_cs.o +endif + + + +ifeq ($(CONFIG_RT_WSC),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wsc.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wsc_tlv.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_dh.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wsc_ufd.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/crypt_biginteger.o +ifeq ($(CONFIG_RT_WSC_V2),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wsc_v2.o +endif +ifeq ($(CONFIG_RT_WSC_NFC),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/nfc.o +endif +endif + +ifeq ($(CONFIG_RT_WAPI),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wapi.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wapi_sms4.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/wapi_crypt.o +endif + +ifeq ($(CONFIG_RT_80211W_PMF),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/pmf.o +endif + +ifeq ($(CONFIG_RT_IGMP_SNOOP),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/igmp_snoop.o +endif + +ifeq ($(CONFIG_RT_NETIF_BLOCK),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/netif_block.o +endif + +ifeq ($(CONFIG_RT_CSO),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/naf/net_acc.o +endif + +ifeq ($(CONFIG_RT_VIDEO_TURBINE),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/cmm_video.o +endif + +ifeq ($(CONFIG_RT_BAND_STEERING),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_band_steering.o +endif + +ifeq ($(CONFIG_RT_DOT11R_FT),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ft.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ft_tlv.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ft_iocl.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/ft_rc.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/ap/ap_ftkd.o +endif + +ifeq ($(CONFIG_RT_DOT11K_RRM),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rrm_tlv.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rrm_sanity.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/rrm.o +endif + +ifeq ($(CONFIG_RT_CFG80211),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_scan.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_rx.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_tx.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_inf.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_p2p.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_ap.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211drv.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211_util.o +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/os/linux/cfg80211/cfg80211.o +endif + +ifeq ($(CONFIG_RT_DEBUG),y) +$(RT_DRV_NAME)-objs += $(RT_DRV_PATH)/common/sys_log.o +endif + +################### +# CFLAGS +################## + +EXTRA_CFLAGS = -Wall -Wstrict-prototypes -Wno-trigraphs -Wno-unused -Wno-declaration-after-statement +EXTRA_CFLAGS += -I$(src)/../mt76x2/include +ifeq ($(CONFIG_RT_ATE),y) +EXTRA_CFLAGS += -I$(src)/../mt76x2/ate/include +endif +EXTRA_CFLAGS += -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX +EXTRA_CFLAGS += -DCONFIG_AP_SUPPORT -DUAPSD_SUPPORT -DDOT11_N_SUPPORT -DDOT1X_SUPPORT +EXTRA_CFLAGS += -DAP_SCAN_SUPPORT -DSCAN_SUPPORT +#EXTRA_CFLAGS += -DAP_PARTIAL_SCAN_SUPPORT +EXTRA_CFLAGS += -DSTATS_COUNT_SUPPORT -DENHANCED_STAT_DISPLAY +EXTRA_CFLAGS += -DRSSI_FEEDBACK +EXTRA_CFLAGS += -DRESOURCE_PRE_ALLOC +EXTRA_CFLAGS += -DEAPOL_QUEUE_SUPPORT +EXTRA_CFLAGS += -DDATA_QUEUE_RESERVE +EXTRA_CFLAGS += -DFORCE_ANNOUNCE_CRITICAL_AMPDU +#EXTRA_CFLAGS += -DPS_ENTRY_MAITENANCE +#EXTRA_CFLAGS += -DSYSTEM_LOG_SUPPORT + +ifeq ($(CONFIG_RT_FIRST_CARD),2860) +EXTRA_CFLAGS += -DRT_SOC_SUPPORT +endif + +# do not lock CountryRegion from EEPROM +EXTRA_CFLAGS += -DEEPROM_COUNTRY_UNLOCK + +# provide internal eFuse memory support +#EXTRA_CFLAGS += -DRTMP_EFUSE_SUPPORT -DCAL_FREE_IC_SUPPORT + +# provide information on the current STA population and traffic levels in the QBSS +#EXTRA_CFLAGS += -DAP_QLOAD_SUPPORT -DQLOAD_FUNC_BUSY_TIME_STATS + +ifneq ($(CONFIG_RA_HW_NAT_WIFI),y) +EXTRA_CFLAGS += -DCONFIG_RA_NAT_NONE +endif + +ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y) +EXTRA_CFLAGS += -DWORKQUEUE_BH +endif + +### MT7620 (RBUS) +ifeq ($(CHIP_MT7620),y) +EXTRA_CFLAGS += -DRT6352 -DCONFIG_SWMCU_SUPPORT +EXTRA_CFLAGS += -DRTMP_RBUS_SUPPORT -DRTMP_MAC_PCI +EXTRA_CFLAGS += -DRTMP_MAC -DRTMP_BBP -DRLT_RF -DRTMP_RF_RW_SUPPORT +EXTRA_CFLAGS += -DVCORECAL_SUPPORT +EXTRA_CFLAGS += -DLOFT_IQ_CAL_SUPPORT +EXTRA_CFLAGS += -DRTMP_TEMPERATURE_CALIBRATION +EXTRA_CFLAGS += -DFIFO_EXT_SUPPORT +EXTRA_CFLAGS += -DDYNAMIC_VGA_SUPPORT +#EXTRA_CFLAGS += -DMICROWAVE_OVEN_SUPPORT +EXTRA_CFLAGS += -DMCS_LUT_SUPPORT -DPEER_DELBA_TX_ADAPT +EXTRA_CFLAGS += -DDROP_MASK_SUPPORT +EXTRA_CFLAGS += -DMULTI_CLIENT_SUPPORT +#EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +#EXTRA_CFLAGS += -DTHERMAL_PROTECT_SUPPORT +ifeq ($(CONFIG_AP_RTMP_INTERNAL_TX_ALC),y) +EXTRA_CFLAGS += -DRTMP_INTERNAL_TX_ALC +endif +ifeq ($(CONFIG_AP_RTMP_TEMPERATURE_COMPENSATION),y) +EXTRA_CFLAGS += -DRTMP_TEMPERATURE_COMPENSATION +endif +ifeq ($(CONFIG_AP_ADJ_PWR_CONSUMPTION),y) +EXTRA_CFLAGS += -DADJUST_POWER_CONSUMPTION_SUPPORT +endif +ifeq ($(CONFIG_AP_INTERNAL_PA_EXTERNAL_LNA),y) +EXTRA_CFLAGS += -DRT6352_EL_SUPPORT +endif +ifeq ($(CONFIG_AP_EXTERNAL_PA_EXTERNAL_LNA),y) +EXTRA_CFLAGS += -DRT6352_EP_SUPPORT -DRT6352_EL_SUPPORT +endif +endif + +### MT7602E/MT7612E (PCIe) +EXTRA_CFLAGS += -DRTMP_FLASH_SUPPORT +EXTRA_CFLAGS += -DREAD_MAC_FROM_EEPROM +EXTRA_CFLAGS +=-DCONFIG_RT_FIRST_IF_RF_OFFSET=0x0000 +EXTRA_CFLAGS +=-DCONFIG_RT_FIRST_CARD=7603 +EXTRA_CFLAGS +=-DCONFIG_RT_FIRST_CARD_EEPROM="flash" +EXTRA_CFLAGS +=-DCONFIG_RT_SECOND_IF_RF_OFFSET=0x8000 +EXTRA_CFLAGS +=-DCONFIG_RT_SECOND_CARD_EEPROM="flash" +EXTRA_CFLAGS +=-DCONFIG_RT_SECOND_CARD=7612 +EXTRA_CFLAGS += -DRT65xx -DMT76x2 -DMT7612 +#EXTRA_CFLAGS += -DCONFIG_FPGA_MODE +EXTRA_CFLAGS += -DRTMP_PCI_SUPPORT -DRTMP_MAC_PCI +EXTRA_CFLAGS += -DRLT_MAC -DRLT_BBP -DMT_RF -DRTMP_RF_RW_SUPPORT +EXTRA_CFLAGS += -DA_BAND_SUPPORT +EXTRA_CFLAGS += -DRX_DMA_SCATTER -DCONFIG_ANDES_SUPPORT +EXTRA_CFLAGS += -DNEW_RATE_ADAPT_SUPPORT +#EXTRA_CFLAGS += -DNEW_RATE_ADAPT_QUICK_DOWN # has dropdown to CCK/0 issue on 5GHz +EXTRA_CFLAGS += -DFIFO_EXT_SUPPORT +EXTRA_CFLAGS += -DDYNAMIC_VGA_SUPPORT +#EXTRA_CFLAGS += -DMICROWAVE_OVEN_SUPPORT +EXTRA_CFLAGS += -DMCS_LUT_SUPPORT -DPEER_DELBA_TX_ADAPT +EXTRA_CFLAGS += -DDROP_MASK_SUPPORT +EXTRA_CFLAGS += -DMULTI_CLIENT_SUPPORT +EXTRA_CFLAGS += -DRTMP_TEMPERATURE_TX_ALC +#EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +#EXTRA_CFLAGS += -DSPECIFIC_TX_POWER_SUPPORT +#EXTRA_CFLAGS += -DTHERMAL_PROTECT_SUPPORT +#EXTRA_CFLAGS += -DDMA_BUSY_RESET +EXTRA_CFLAGS += -DDBG -DUAPSD_DEBUG +#EXTRA_CFLAGS += -DREAD_MAC_FROM_EEPROM +#EXTRA_CFLAGS += -DDBG_DIAGNOSE -DDBG_RX_MCS -DDBG_TX_MCS + + +ifeq ($(CONFIG_RT_ATE),y) +EXTRA_CFLAGS += -DRALINK_ATE -DCONFIG_RT2880_ATE_CMD_NEW +EXTRA_CFLAGS += -DRTMP_EFUSE_SUPPORT -DCAL_FREE_IC_SUPPORT +ifeq ($(CONFIG_RT_QA),y) +EXTRA_CFLAGS += -DRALINK_QA +endif +endif + +ifeq ($(CONFIG_AP_DLS),y) +EXTRA_CFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(CONFIG_AP_IDS),y) +EXTRA_CFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(CONFIG_AP_DFS),y) +EXTRA_CFLAGS += -DDFS_SUPPORT -DDFS_ATP_SUPPORT +endif + +ifeq ($(CONFIG_AP_CARRIER),y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(CONFIG_AP_GREENAP),y) +EXTRA_CFLAGS += -DGREENAP_SUPPORT +endif + +ifeq ($(CONFIG_AP_80211AC_VHT),y) +EXTRA_CFLAGS += -DDOT11_VHT_AC +endif + + + +ifeq ($(CONFIG_AP_LED),y) +EXTRA_CFLAGS += -DLED_CONTROL_SUPPORT +ifeq ($(CONFIG_RT_WSC),y) +EXTRA_CFLAGS += -DWSC_LED_SUPPORT +endif +endif + +ifeq ($(CONFIG_AP_LED_SOFT),y) +EXTRA_CFLAGS += -DLED_SOFT_SUPPORT +EXTRA_CFLAGS += -DLED_SOFT_BLINK_GPIO=$(CONFIG_AP_LED_SOFT_GPIO) +ifdef CONFIG_MT76X2_AP_LED_SOFT_GPIO_DEV1 +EXTRA_CFLAGS += -DLED_SOFT_BLINK_GPIO_DEV1=$(CONFIG_AP_LED_SOFT_GPIO_DEV1) +else +EXTRA_CFLAGS += -DLED_SOFT_BLINK_GPIO_DEV1=-1 +endif +endif + +ifeq ($(CONFIG_AP_LLTD),y) +EXTRA_CFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(CONFIG_AP_WDS),y) +EXTRA_CFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(CONFIG_AP_MBSS),y) +EXTRA_CFLAGS += -DMBSS_SUPPORT +ifeq ($(CONFIG_AP_MBSS_NEW_MBSSID_MODE),y) +EXTRA_CFLAGS += -DNEW_MBSSID_MODE +EXTRA_CFLAGS += -DENHANCE_NEW_MBSSID_MODE +endif +endif + +ifeq ($(CONFIG_AP_APCLI),y) +EXTRA_CFLAGS += -DAPCLI_SUPPORT -DMAT_SUPPORT -DTRAFFIC_BASED_TXOP +EXTRA_CFLAGS += -DAPCLI_AUTO_CONNECT_SUPPORT +EXTRA_CFLAGS += -DMAC_APCLI_SUPPORT +ifeq ($(CONFIG_AP_APCLI_AUTO_BW),y) +EXTRA_CFLAGS += -DAPCLI_AUTO_BW_SUPPORT +endif +ifeq ($(CONFIG_AP_MAC_REPEATER),y) +EXTRA_CFLAGS += -DMAC_REPEATER_SUPPORT +endif +ifeq ($(CONFIG_AP_APCLI_CERT),y) +EXTRA_CFLAGS += -DAPCLI_CERT_SUPPORT +endif +ifeq ($(CONFIG_AP_CON_WPS),y) +EXTRA_CFLAGS += -DCON_WPS -DCON_WPS_AP_SAME_UUID +endif +endif + +ifeq ($(CONFIG_AP_AIRPLAY),y) +EXTRA_CFLAGS += -DAIRPLAY_SUPPORT +endif + +ifeq ($(CONFIG_AP_MWDS),y) +EXTRA_CFLAGS += -DMWDS -DROUTING_TAB_SUPPORT +ifeq ($(CONFIG_AP_SMART_MESH),y) +EXTRA_CFLAGS += -DSMART_MESH -DSMART_MESH_MONITOR -DSMART_MESH_HIDDEN_WPS +endif +endif + +ifeq ($(CONFIG_RT_WSC),y) +EXTRA_CFLAGS += -DWSC_AP_SUPPORT +ifeq ($(CONFIG_RT_WSC_V2),y) +EXTRA_CFLAGS += -DWSC_V2_SUPPORT +endif +ifeq ($(CONFIG_RT_WSC_NFC),y) +EXTRA_CFLAGS += -DWSC_NFC_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT_80211N_DRAFT3),y) +EXTRA_CFLAGS += -DDOT11N_DRAFT3 +endif + +ifeq ($(CONFIG_RT_WAPI),y) +EXTRA_CFLAGS += -DWAPI_SUPPORT +endif + +ifeq ($(CONFIG_RT_80211W_PMF),y) +EXTRA_CFLAGS += -DDOT11W_PMF_SUPPORT -DSOFT_ENCRYPT +endif + +ifeq ($(CONFIG_RT_ED_MONITOR),y) +EXTRA_CFLAGS += -DED_MONITOR -DED_SMART +endif + +ifeq ($(CONFIG_RT_IGMP_SNOOP),y) +EXTRA_CFLAGS += -DIGMP_SNOOP_SUPPORT +ifeq ($(CONFIG_AP_MWDS),y) +EXTRA_CFLAGS += -DIGMP_MESH +endif +endif + +ifeq ($(CONFIG_RT_MCAST_RATE_SPECIFIC),y) +EXTRA_CFLAGS += -DMCAST_RATE_SPECIFIC +endif + +ifeq ($(CONFIG_RT_VIDEO_TURBINE),y) +EXTRA_CFLAGS += -DVIDEO_TURBINE_SUPPORT +endif + +ifeq ($(CONFIG_RT_BAND_STEERING),y) +EXTRA_CFLAGS += -DBAND_STEERING +endif + +ifeq ($(CONFIG_RT_DOT11R_FT),y) +EXTRA_CFLAGS += -DDOT11R_FT_SUPPORT -DIAPP_SUPPORT +endif + +ifeq ($(CONFIG_RT_DOT11K_RRM),y) +EXTRA_CFLAGS += -DDOT11K_RRM_SUPPORT -DAPPLE_11K_IOT +endif + +ifeq ($(CONFIG_RT_HDR_TRANS),y) +EXTRA_CFLAGS += -DHDR_TRANS_SUPPORT +endif + +ifeq ($(CONFIG_RT_CSO),y) +EXTRA_CFLAGS += -DCONFIG_CSO_SUPPORT -DCONFIG_TSO_SUPPORT +endif + +ifeq ($(CONFIG_RT_DELAYED_TCP_ACK),y) +EXTRA_CFLAGS += -DDELAYED_TCP_ACK +endif + +ifeq ($(CONFIG_RT_SINGLE_SKU),y) +EXTRA_CFLAGS += -DSINGLE_SKU_V2 +endif + +ifeq ($(CONFIG_RT_MEMORY_OPTIMIZATION),y) +EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION +endif + +ifeq ($(CONFIG_RT_NETIF_BLOCK),y) +EXTRA_CFLAGS += -DBLOCK_NET_IF +endif + +ifeq ($(CONFIG_RT_SNMP),y) +EXTRA_CFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(CONFIG_RT_CFG80211),y) +EXTRA_CFLAGS += -DRT_CFG80211_SUPPORT -DEXT_BUILD_CHANNEL_LIST +endif + +ifeq ($(CONFIG_RT_BIG_ENDIAN),y) +EXTRA_CFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(CONFIG_RT_MC_SUPPORT),y) +EXTRA_CFLAGS += -DMULTIPLE_CARD_SUPPORT +endif +WFLAGS += -Wno-error=date-time + diff --git a/package/lean/mt/drivers/mt7615d/Makefile b/package/lean/mt/drivers/mt7615d/Makefile index 6dcffe6e6..dd4d13025 100644 --- a/package/lean/mt/drivers/mt7615d/Makefile +++ b/package/lean/mt/drivers/mt7615d/Makefile @@ -1,45 +1,223 @@ +# All rights reserved. # -# Copyright (C) 2015-2016 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v3. -# +# 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:=kmod-mt7615d -PKG_VERSION:=1 -PKG_RELEASE:=1 +PKG_NAME:=mt7615d +P4REV:=8 +PKG_VERSION:=5.0.4.0 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME) +PKG_KCONFIG:= \ + AP_SUPPORT \ + RT_FIRST_CARD \ + RT_SECOND_CARD \ + RT_FIRST_IF_RF_OFFSET \ + RT_SECOND_IF_RF_OFFSET \ + MT_WIFI \ + WIFI_BASIC_FUNC \ + MT_WIFI_PATH \ + FIRST_IF_NONE \ + FIRST_IF_EEPROM_FLASH \ + FIRST_IF_EEPROM_EFUSE \ + RT_FIRST_CARD_EEPROM \ + SECOND_IF_NONE \ + SECOND_IF_EEPROM_FLASH \ + SECOND_IF_EEPROM_PROM \ + SECOND_IF_EEPROM_EFUSE \ + RT_SECOND_CARD_EEPROM \ + MULTI_INF_SUPPORT \ + WIFI_BASIC_FUNC \ + WIRELESS_EXT \ + WEXT_SPY \ + WEXT_PRIV \ + DOT11_N_SUPPORT \ + DOT11_VHT_AC \ + WIFI_DRIVER \ + G_BAND_256QAM_SUPPORT \ + BRCM_256QAM_SUPPORT \ + ICAP_SUPPORT \ + MT_AP_SUPPORT \ + BACKGROUND_SCAN_SUPPORT \ + SMART_CARRIER_SENSE_SUPPORT \ + MT_DFS_SUPPORT \ + HDR_TRANS_TX_SUPPORT \ + CHIP_MT7615E \ + HDR_TRANS_RX_SUPPORT \ + DBDC_MODE \ + MULTI_PROFILE_SUPPORT \ + DEFAULT_5G_PROFILE \ + SUPPORT_DYNAMIC_TXOP \ + WSC_INCLUDED \ + MT_STA_SUPPORT \ + WSC_V2_SUPPORT \ + DOT11W_PMF_SUPPORT \ + PASSPOINT_R2 \ + TXBF_SUPPORT \ + IGMP_SNOOP_SUPPORT \ + RATE_ADAPTION \ + RATE_ADAPT_AGBS_SUPPORT \ + RTMP_FLASH_SUPPORT \ + ATE_SUPPORT \ + UAPSD \ + RLT_MAC \ + RLT_BBP \ + RLT_RF \ + RTMP_MAC \ + RTMP_BBP \ + RTMP_RF \ + RTMP_PCI_SUPPORT \ + RTMP_USB_SUPPORT \ + RTMP_RBUS_SUPPORT \ + WIFI_MODE_AP \ + WIFI_MODE_STA \ + WIRELESS_EXT \ + WEXT_SPY \ + WEXT_PRIV \ + WDS_SUPPORT \ + MBSS_SUPPORT \ + APCLI_SUPPORT \ + APCLI_CERT_SUPPORT \ + MAC_REPEATER_SUPPORT \ + RALINK_RT6352 \ + RALINK_MT7620 \ + RALINK_MT7603E \ + CON_WPS_SUPPORT \ + VOW_SUPPORT \ + BAND_STEERING \ + TXOP_ARBITER \ + CFG_SUPPORT_DYNAMIC_TXOP \ + WIFI_MODE_BOTH \ + WIFI_RLT_MAC \ + RLT_MAC \ + WIFI_RTMP_MAC \ + RTMP_MAC \ + WIFI_MT_MAC \ + CHIP_MT7603E \ + CHIP_MT7615E \ + MT_MAC \ + RATE_ADAPTION \ + SUPPORT_OPENWRT \ + SDK_USER_LIGHTY \ + MUMIMO_SUPPORT \ + MU_RA_SUPPORT \ + LED_CONTROL_SUPPORT \ + RA_HW_NAT \ + RA_HW_NAT_WIFI_NEW_ARCH \ + CFG80211_SUPPORT \ + SER_SUPPORT \ + GREENAP_SUPPORT \ + RADIUS_ACCOUNTING_SUPPORT \ + TPC_SUPPORT \ + RLM_CAL_CACHE_SUPPORT \ + RF_LOCKDOWN_SUPPORT \ + PASSPOINT_R2 \ + RED_SUPPORT \ + FIRST_IF_EPAELNA \ + FIRST_IF_IPAILNA \ + FIRST_IF_IPAELNA \ + FIRST_IF_EPAILNA \ + SECOND_IF_EPAELNA \ + SECOND_IF_IPAILNA \ + SECOND_IF_IPAELNA \ + SECOND_IF_EPAILNA \ + THIRD_IF_EPAELNA \ + THIRD_IF_IPAILNA \ + THIRD_IF_IPAELNA \ + THIRD_IF_EPAILNA \ + WIFI_PKT_FWD \ + DOT11K_RRM_SUPPORT \ + DOT11R_FT_SUPPORT \ + MBO_SUPPORT \ + WIFI_PKT_FWD_V1 \ + FIRST_IF_MT7615E \ + FIRST_IF_MT7622 \ + FIRST_IF_MT7626 \ + SECOND_IF_MT7615E \ + THIRD_IF_NONE \ + THIRD_IF_MT7615E \ + RT_THIRD_CARD \ + RT_THIRD_IF_RF_OFFSET \ + THIRD_IF_EEPROM_FLASH \ + THIRD_IF_EEPROM_PROM \ + THIRD_IF_EEPROM_EFUSE \ + RT_THIRD_CARD_EEPROM \ + SPECTRUM_SUPPORT \ + MULTI_PROFILE_SUPPORT \ + PRE_CAL_TRX_SET1_SUPPORT \ + MWDS \ + MCAST_RATE_SPECIFIC \ + WLAN_HOOK \ + COEX_SUPPORT \ + EASY_SETUP_SUPPORT \ + EVENT_NOTIFIER_SUPPORT \ + AIR_MONITOR \ + WNM_SUPPORT \ + INTERWORKING \ + LINUX_NET_TXQ_SUPPORT \ + CHIP_MT7622 \ + CHIP_MT7626 \ + WHNAT_SUPPORT \ + FAST_NAT_SUPPORT \ + PRE_CAL_TRX_SET2_SUPPORT \ + LINK_TEST_SUPPORT \ + TCP_RACK_SUPPORT \ + FQ_SCH_SUPPORT \ + BRCM_256QAM_SUPPORT \ + VHT_TXBF_2G_EPIGRAM_IE_SUPPORT \ + DSCP_PRI_SUPPORT \ + PCIE_ASPM_DYM_CTRL_SUPPORT \ + +PKG_CONFIG_DEPENDS:=$(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_MTK_$c),CONFIG_$(c))) include $(INCLUDE_DIR)/package.mk -define Package/$(PKG_NAME) - CATEGORY:=Kernel modules - SUBMENU:=Wireless Drivers - TITLE:=MTK wifi AP driver (DBDC) - DEPENDS:= +TAR_CMD=$(HOST_TAR) -C $(1)/ $(TAR_OPTIONS) + +define KernelPackage/mt7615d + CATEGORY:=Kernel modules + TITLE:=MTK wifi AP driver + DEPENDS:=@TARGET_ramips +ifneq ($(CONFIG_MTK_WHNAT_SUPPORT), ) + FILES:=$(PKG_BUILD_DIR)/mt_wifi_ap/mt_wifi.ko \ + $(PKG_BUILD_DIR)/mt_wifi/embedded/tools/plug_in/whnat/mt_whnat.ko + AUTOLOAD:=$(call AutoProbe,mt_wifi mt_whnat) +else + FILES:=$(PKG_BUILD_DIR)/mt_wifi_ap/mt_wifi.ko + AUTOLOAD:=$(call AutoProbe,mt_wifi) +endif + SUBMENU:=Wireless Drivers + MENU:=1 endef -define Package/$(PKG_NAME)/config -config 7615_DBDC_MODE - bool "MTK wifi AP driver (DBDC)" - default y if TARGET_ramips_mt7621_DEVICE_phicomm_k2p - default n -endef - -define Package/$(PKG_NAME)/description -MTK wifi AP driver (DBDC) for K2P -endef - -define Build/Prepare -endef - -define Build/Configure +define KernelPackage/mt7615d/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)/mt_wifi_ap" \ + $(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_MTK_$c),CONFIG_$(c)=$(CONFIG_MTK_$(c)))) \ + modules endef -define Package/$(PKG_NAME)/install +define KernelPackage/mt7615d/install + $(INSTALL_DIR) $(1)/etc/wireless/ + $(INSTALL_DIR) $(1)/etc/wireless/mt7615/ +ifneq ($(CONFIG_MTK_DBDC_MODE), ) + $(INSTALL_BIN) ./files/dbdc.l1profile.dat $(1)/etc/wireless/l1profile.dat + $(INSTALL_BIN) ./files/mt7615.1.2G.dat $(1)/etc/wireless/mt7615/ + $(INSTALL_BIN) ./files/mt7615.1.5G.dat $(1)/etc/wireless/mt7615/ +else + $(INSTALL_BIN) ./files/l1profile.dat $(1)/etc/wireless/ + $(INSTALL_BIN) ./files/mt7615.1.dat $(1)/etc/wireless/mt7615/ + $(INSTALL_BIN) ./files/mt7615.2.dat $(1)/etc/wireless/mt7615/ +endif endef -$(eval $(call BuildPackage,$(PKG_NAME))) +$(eval $(call KernelPackage,mt7615d)) diff --git a/package/lean/mt/drivers/mt_wifi/config.dbdc b/package/lean/mt/drivers/mt7615d/config.in similarity index 96% rename from package/lean/mt/drivers/mt_wifi/config.dbdc rename to package/lean/mt/drivers/mt7615d/config.in index 82a890057..24f1bcd67 100644 --- a/package/lean/mt/drivers/mt_wifi/config.dbdc +++ b/package/lean/mt/drivers/mt7615d/config.in @@ -1,14 +1,14 @@ -if PACKAGE_kmod-mt_wifi +if PACKAGE_kmod-mt7615d config MTK_SUPPORT_OPENWRT bool default y - depends on PACKAGE_kmod-mt_wifi + depends on PACKAGE_kmod-mt7615d config MTK_WIFI_DRIVER bool default y - depends on PACKAGE_kmod-mt_wifi + depends on PACKAGE_kmod-mt7615d select MTK_WIFI_MT_MAC select MTK_MT_MAC select MTK_FIRST_IF_MT7615E @@ -21,7 +21,7 @@ config MTK_WIFI_DRIVER if MTK_WIFI_DRIVER choice - prompt "Choose First WiFi Interface DBDC" + prompt "Choose First WiFi Interface" config MTK_FIRST_IF_MT7615E bool "MT7615E" @@ -40,7 +40,7 @@ choice select MTK_WIFI_MT_MAC select MTK_MT_MAC select MTK_CHIP_MT7626 - + config MTK_FIRST_IF_NONE bool "None" endchoice @@ -50,7 +50,7 @@ choice config MTK_SECOND_IF_NONE bool "None" - + config MTK_SECOND_IF_MT7615E bool "MT7615E" select MTK_WIFI_MT_MAC @@ -122,7 +122,7 @@ choice config MTK_FIRST_IF_EEPROM_FLASH bool "FLASH" - + config MTK_FIRST_IF_EEPROM_PROM bool "EEPROM" @@ -181,7 +181,7 @@ config MTK_RT_THIRD_CARD_EEPROM default "prom" if MTK_THIRD_IF_EEPROM_PROM default "efuse" if MTK_THIRD_IF_EEPROM_EFUSE default "flash" if MTK_THIRD_IF_EEPROM_FLASH - + config MTK_MULTI_INF_SUPPORT bool default y if !MTK_FIRST_IF_NONE && !MTK_SECOND_IF_NONE @@ -218,7 +218,7 @@ config MTK_VHT_TXBF_2G_EPIGRAM_IE_SUPPORT bool "BRCM 2.4G VHT Sounding support" depends on MTK_WIFI_DRIVER default y - + config MTK_TPC_SUPPORT bool "802.11h TPC Support" depends on MTK_WIFI_DRIVER @@ -271,18 +271,21 @@ config MTK_DBDC_MODE depends on MTK_CHIP_MT7615E || MTK_CHIP_MT7626 select MULTI_PROFILE_SUPPORT select DEFAULT_5G_PROFILE - default y + default y if TARGET_ramips_mt7621_DEVICE_phicomm_k2p + default n config MTK_MULTI_PROFILE_SUPPORT - bool "Multi Profile Support" - depends on MTK_DBDC_MODE - default y + bool "Multi Profile Support" + depends on MTK_DBDC_MODE + default y if TARGET_ramips_mt7621_DEVICE_phicomm_k2p + default n config MTK_DEFAULT_5G_PROFILE bool "5G default profile for DBDC" depends on MTK_DBDC_MODE # depends on MTK_MULTI_PROFILE_SUPPORT - default y + default y if TARGET_ramips_mt7621_DEVICE_phicomm_k2p + default n config MTK_WSC_INCLUDED bool "WSC (WiFi Simple Config)" @@ -311,13 +314,13 @@ config MTK_FAST_NAT_SUPPORT bool "Fast-NAT support" # depends on RA_HW_NAT_WIFI default n - + config MTK_WHNAT_SUPPORT tristate "Wifi Hardware NAT support" depends on MTK_CHIP_MT7615E depends on MTK_WLAN_HOOK depends on MTK_FAST_NAT_SUPPORT - select PACKAGE_kmod-hw_nat + select PACKAGE_kmod-hw_nat default n #config LLTD_SUPPORT @@ -424,7 +427,7 @@ config MTK_PRE_CAL_TRX_SET2_SUPPORT config MTK_RF_LOCKDOWN_SUPPORT bool "RF Lockdown Support" depends on MTK_WIFI_DRIVER - default n + default n config MTK_LINK_TEST_SUPPORT bool "Link Test Support" @@ -503,22 +506,22 @@ config MTK_FDB_SUPPORT choice prompt "PA LNA Type of 1st Card" depends on ! MTK_FIRST_IF_NONE - + config MTK_FIRST_IF_IPAILNA - bool "iPAiLNA" + bool "iPAiLNA" config MTK_FIRST_IF_IPAELNA bool "iPAeLNA" config MTK_FIRST_IF_EPAELNA - bool "ePAeLNA" + bool "ePAeLNA" # config MTK_FIRST_IF_EPAILNA # bool "ePAiLNA" endchoice choice prompt "PA LNA Type of 2nd Card" depends on ! MTK_SECOND_IF_NONE - + config MTK_SECOND_IF_IPAILNA - bool "iPAiLNA" + bool "iPAiLNA" config MTK_SECOND_IF_IPAELNA bool "iPAeLNA" config MTK_SECOND_IF_EPAELNA @@ -529,17 +532,17 @@ endchoice choice prompt "PA LNA Type of 3rd Card" depends on ! MTK_THIRD_IF_NONE - + config MTK_THIRD_IF_EPAELNA bool "ePAeLNA" config MTK_THIRD_IF_IPAILNA - bool "iPAiLNA" + bool "iPAiLNA" config MTK_THIRD_IF_IPAELNA bool "iPAeLNA" # config MTK_THIRD_IF_EPAILNA # bool "ePAiLNA" endchoice -#### PA_LNA_Type choice END +#### PA_LNA_Type choice END # # Section for chip architectures @@ -653,10 +656,10 @@ config MTK_MWDS default n config MTK_MUMIMO_SUPPORT - bool "MU-MIMO Support" - depends on MTK_WIFI_DRIVER - select MTK_MU_RA_SUPPORT - default y + bool "MU-MIMO Support" + depends on MTK_WIFI_DRIVER + select MTK_MU_RA_SUPPORT + default y config MTK_MU_RA_SUPPORT bool "MU-RGA Support" @@ -686,7 +689,7 @@ config MTK_DSCP_PRI_SUPPORT bool "Dscp Priority Mapping Support" depends on MTK_MT_AP_SUPPORT default n - + config MTK_CON_WPS_SUPPORT bool "Concurrent WPS Support" depends on MTK_MT_AP_SUPPORT @@ -755,7 +758,7 @@ config MTK_GREENAP_SUPPORT bool "GreenAP Support" depends on MTK_MT_AP_SUPPORT default n - + config MTK_PCIE_ASPM_DYM_CTRL_SUPPORT bool "Pcie Aspm Dynamic Control Support" depends on MTK_MT_AP_SUPPORT @@ -769,7 +772,7 @@ config MTK_COEX_SUPPORT config MTK_EASY_SETUP_SUPPORT bool "Whole Home Coverage - Easy Setup" depends on MTK_MT_AP_SUPPORT - default n + default n config MTK_EVENT_NOTIFIER_SUPPORT bool "Whole Home Coverage - Event Notifier" @@ -813,7 +816,7 @@ config MTK_WIFI_MT_MAC bool default y depends on MTK_MT_WIFI - + if MTK_WIFI_RLT_MAC config MTK_RLT_MAC bool @@ -865,5 +868,5 @@ if MTK_CHIP_MT7615E || MTK_CHIP_MT7622 || MTK_CHIP_MT7626 endif endif #MTK_WIFI_DRIVER# -endif #PACKAGE_kmod-mt_wifi# +endif #PACKAGE_kmod-mt7615d# diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/l1profile.dat b/package/lean/mt/drivers/mt7615d/files/dbdc.l1profile.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/dbdc/l1profile.dat rename to package/lean/mt/drivers/mt7615d/files/dbdc.l1profile.dat diff --git a/package/lean/mt/drivers/mt7615d/files/l1profile.dat b/package/lean/mt/drivers/mt7615d/files/l1profile.dat new file mode 100644 index 000000000..7b75d07c4 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/files/l1profile.dat @@ -0,0 +1,23 @@ +Default +INDEX0=MT7615 +INDEX0_profile_path=/etc/wireless/mt7615/mt7615.1.dat +INDEX0_EEPROM_offset=0x0 +INDEX0_EEPROM_size=0x4000 +INDEX0_EEPROM_name=e2p +INDEX0_main_ifname=ra0 +INDEX0_ext_ifname=ra +INDEX0_wds_ifname=wds +INDEX0_apcli_ifname=apcli +INDEX0_single_sku_path=/etc_ro/Wireless/SingleSKU_mt7615e-sku.dat +INDEX0_bf_sku_path=/etc_ro/Wireless/SingleSKU_mt7615e-sku-bf.dat +INDEX1=MT7615 +INDEX1_profile_path=/etc/wireless/mt7615/mt7615.2.dat +INDEX1_EEPROM_offset=0x8000 +INDEX1_EEPROM_size=0x4000 +INDEX1_EEPROM_name=e2p +INDEX1_main_ifname=rai0 +INDEX1_ext_ifname=rai +INDEX1_wds_ifname=wdsi +INDEX1_apcli_ifname=apclii +INDEX1_single_sku_path=/etc_ro/Wireless/SingleSKU_mt7615e-sku.dat +INDEX1_bf_sku_path=/etc_ro/Wireless/SingleSKU_mt7615e-sku-bf.dat diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615.1.2G.dat b/package/lean/mt/drivers/mt7615d/files/mt7615.1.2G.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/dbdc/mt7615.1.2G.dat rename to package/lean/mt/drivers/mt7615d/files/mt7615.1.2G.dat diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615.1.5G.dat b/package/lean/mt/drivers/mt7615d/files/mt7615.1.5G.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/dbdc/mt7615.1.5G.dat rename to package/lean/mt/drivers/mt7615d/files/mt7615.1.5G.dat diff --git a/package/lean/mt/drivers/mt_wifi/files/mt7615.1.2G.dat b/package/lean/mt/drivers/mt7615d/files/mt7615.1.dat similarity index 99% rename from package/lean/mt/drivers/mt_wifi/files/mt7615.1.2G.dat rename to package/lean/mt/drivers/mt7615d/files/mt7615.1.dat index f19fcacc5..71f486e05 100644 --- a/package/lean/mt/drivers/mt_wifi/files/mt7615.1.2G.dat +++ b/package/lean/mt/drivers/mt7615d/files/mt7615.1.dat @@ -90,7 +90,7 @@ CountryRegion=5 CountryRegionABand=7 CP_SUPPORT=2 CSPeriod=6 -DBDC_MODE=1 +DBDC_MODE=0 DebugFlags=0 DefaultKeyID=1 DfsCalibration=0 @@ -108,6 +108,7 @@ EthConvertMode=dongle EtherTrafficBand=0 Ethifname= ETxBfEnCond=1 +ITxBfEnCond=1 FineAGC=0 FixedTxMode= ForceRoamSupport= diff --git a/package/lean/mt/drivers/mt_wifi/files/mt7615.2.dat b/package/lean/mt/drivers/mt7615d/files/mt7615.2.dat similarity index 99% rename from package/lean/mt/drivers/mt_wifi/files/mt7615.2.dat rename to package/lean/mt/drivers/mt7615d/files/mt7615.2.dat index 356c45e57..4218b7011 100644 --- a/package/lean/mt/drivers/mt_wifi/files/mt7615.2.dat +++ b/package/lean/mt/drivers/mt7615d/files/mt7615.2.dat @@ -83,7 +83,7 @@ BW_Priority= BW_Root=0 CalCacheApply=0 CarrierDetect=0 -Channel=44 +Channel=36 ChannelGrp= CountryCode=US CountryRegion=5 @@ -108,6 +108,7 @@ EthConvertMode=dongle EtherTrafficBand=0 Ethifname= ETxBfEnCond=1 +ITxBfEnCond=1 FineAGC=0 FixedTxMode= ForceRoamSupport= @@ -133,9 +134,9 @@ HT_MCS=33 HT_MpduDensity=5 HT_OpMode=0 HT_PROTECT=1 -HT_RxStream=4 +HT_RxStream=2 HT_STBC=1 -HT_TxStream=4 +HT_TxStream=2 IcapMode=0 idle_timeout_interval=0 IEEE80211H=1 diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615E1_EEPROM.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615E1_EEPROM.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615E1_EEPROM.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615E1_EEPROM.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_noReOrdering.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_noReOrdering.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_noReOrdering.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_noReOrdering.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_plain.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_plain.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_plain_20141024_1.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain_20141024_1.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_plain_20141024_1.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain_20141024_1.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_plain_20150206_1_asic.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain_20150206_1_asic.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/MT7615_cr4_plain_20150206_1_asic.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain_20150206_1_asic.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/WIFI_RAM_CODE_MT7615.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/WIFI_RAM_CODE_MT7615.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/WIFI_RAM_CODE_MT7615_E1.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615_E1.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/WIFI_RAM_CODE_MT7615_E1.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615_E1.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/WIFI_RAM_CODE_MT7615_plain.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615_plain.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/WIFI_RAM_CODE_MT7615_plain.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615_plain.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAeLNA/MT7615_EEPROM1.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM1.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAeLNA/MT7615_EEPROM1.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM1.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAeLNA/MT7615_EEPROM2.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM2.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAeLNA/MT7615_EEPROM2.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM2.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAeLNA/MT7615_EEPROM3.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM3.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAeLNA/MT7615_EEPROM3.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM3.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAiLNA/MT7615_EEPROM1.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM1.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAiLNA/MT7615_EEPROM1.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM1.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAiLNA/MT7615_EEPROM2.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM2.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAiLNA/MT7615_EEPROM2.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM2.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAiLNA/MT7615_EEPROM3.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM3.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/ePAiLNA/MT7615_EEPROM3.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM3.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAeLNA/MT7615_EEPROM1.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM1.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAeLNA/MT7615_EEPROM1.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM1.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAeLNA/MT7615_EEPROM2.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM2.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAeLNA/MT7615_EEPROM2.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM2.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAeLNA/MT7615_EEPROM3.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM3.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAeLNA/MT7615_EEPROM3.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM3.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAiLNA/MT7615_EEPROM1.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM1.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAiLNA/MT7615_EEPROM1.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM1.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAiLNA/MT7615_EEPROM2.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM2.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAiLNA/MT7615_EEPROM2.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM2.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAiLNA/MT7615_EEPROM3.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM3.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/iPAiLNA/MT7615_EEPROM3.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM3.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7615/mt7615_patch_e3_hdr.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7615/mt7615_patch_e3_hdr.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7615/mt7615_patch_e3_hdr.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7615/mt7615_patch_e3_hdr.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7622/MT7622_EEPROM.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7622/MT7622_EEPROM.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7622/MT7622_EEPROM.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7622/MT7622_EEPROM.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7622/WIFI_RAM_CODE_MT7622_E2.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7622/WIFI_RAM_CODE_MT7622_E2.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7622/WIFI_RAM_CODE_MT7622_E2.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7622/WIFI_RAM_CODE_MT7622_E2.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7622/ePAeLNA/MT7622_EEPROM.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7622/ePAeLNA/MT7622_EEPROM.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7622/ePAeLNA/MT7622_EEPROM.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7622/ePAeLNA/MT7622_EEPROM.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7622/iPAeLNA/MT7622_EEPROM.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7622/iPAeLNA/MT7622_EEPROM.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7622/iPAeLNA/MT7622_EEPROM.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7622/iPAeLNA/MT7622_EEPROM.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7622/iPAiLNA/MT7622_EEPROM.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7622/iPAiLNA/MT7622_EEPROM.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7622/iPAiLNA/MT7622_EEPROM.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7622/iPAiLNA/MT7622_EEPROM.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/bin/mt7622/mt7622_patch_e2_hdr.bin b/package/lean/mt/drivers/mt7615d/src/bin/mt7622/mt7622_patch_e2_hdr.bin similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/bin/mt7622/mt7622_patch_e2_hdr.bin rename to package/lean/mt/drivers/mt7615d/src/bin/mt7622/mt7622_patch_e2_hdr.bin diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/LoopBack.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/LoopBack.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/LoopBack.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/LoopBack.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/ate_agent.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/ate_agent.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/ate_agent.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/ate_agent.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/LoopBack.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/LoopBack.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/LoopBack.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/LoopBack.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/ate.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/ate.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/ate.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/ate.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/ate_agent.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/ate_agent.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/ate_agent.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/ate_agent.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/meta_agent.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/meta_agent.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/meta_agent.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/meta_agent.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/mt_testmode.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/mt_testmode.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/mt_testmode_dmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode_dmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/mt_testmode_dmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode_dmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/mt_testmode_smac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode_smac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/mt_testmode_smac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode_smac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/qa_agent.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/qa_agent.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/qa_agent.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/qa_agent.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/testmode_common.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/testmode_common.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/testmode_common.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/testmode_common.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/testmode_ioctl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/testmode_ioctl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/include/testmode_ioctl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/testmode_ioctl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/meta_agent.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/meta_agent.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/meta_agent.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/meta_agent.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_ate.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_ate.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_ate.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_ate.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_testmode.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_testmode.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_testmode_dmac.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode_dmac.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_testmode_dmac.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode_dmac.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_testmode_smac.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode_smac.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/mt_mac/mt_testmode_smac.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode_smac.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/qa_agent.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/qa_agent.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/qa_agent.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/qa_agent.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/testmode_ioctl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/testmode_ioctl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/ate/testmode_ioctl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/testmode_ioctl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7615.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7615.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7615.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7615.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7615_dbg.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7615_dbg.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7615_dbg.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7615_dbg.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7622.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7622.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7622.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7622.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7622_dbg.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7622_dbg.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/mt7622_dbg.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7622_dbg.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/rtmp_chip.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/rtmp_chip.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/chips/rtmp_chip.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/rtmp_chip.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Kconfig b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Kconfig similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Kconfig rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Kconfig diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Pack_Release.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Pack_Release.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Pack_Release.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Pack_Release.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Release.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Release.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Release.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Release.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Release_Notes.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Release_Notes.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/Release_Notes.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Release_Notes.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_apcli.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_apcli.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_apcli.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_apcli.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_apcli_inf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_apcli_inf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_apcli_inf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_apcli_inf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_assoc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_assoc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_assoc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_assoc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_auth.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_auth.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_auth.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_auth.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_autoChSel.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_autoChSel.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_autoChSel.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_autoChSel.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_band_steering.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_band_steering.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_band_steering.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_band_steering.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_cfg.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_cfg.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_cfg.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_cfg.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_data.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_data.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_data.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_data.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_ftkd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_ftkd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_ftkd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_ftkd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_ids.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_ids.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_ids.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_ids.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mbss.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mbss.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mbss.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mbss.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mbss_inf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mbss_inf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mbss_inf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mbss_inf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mlme.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mlme.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mlme.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mlme.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mumimo.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mumimo.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mumimo.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mumimo.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mura.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mura.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_mura.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mura.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_nps.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_nps.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_nps.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_nps.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_qload.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_qload.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_qload.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_qload.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_repeater.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_repeater.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_repeater.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_repeater.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_sanity.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sanity.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_sanity.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sanity.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_sec.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sec.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_sec.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sec.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_sync.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sync.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_sync.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sync.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_vow.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_vow.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_vow.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_vow.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_wds.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wds.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_wds.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wds.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_wds_inf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wds_inf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_wds_inf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wds_inf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_wpa.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wpa.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/ap_wpa.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wpa.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_assoc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_assoc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_assoc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_assoc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_auth.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_auth.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_auth.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_auth.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_link_cover.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_link_cover.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_link_cover.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_link_cover.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_sync.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_sync.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/ap/apcli_sync.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_sync.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/a4_conn.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/a4_conn.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/a4_conn.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/a4_conn.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/action.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/action.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/action.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/action.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ba_action.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ba_action.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ba_action.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ba_action.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/bcn.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/bcn.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/bcn.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/bcn.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/bgnd_scan.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/bgnd_scan.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/bgnd_scan.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/bgnd_scan.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/client_wds.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/client_wds.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/client_wds.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/client_wds.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_cfg.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cfg.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_cfg.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cfg.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_cmd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cmd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_cmd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cmd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_cs.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cs.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_cs.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cs.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_data.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_data.c similarity index 99% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_data.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_data.c index 0495eee46..c18f10b5a 100644 --- a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_data.c +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_data.c @@ -7077,7 +7077,6 @@ BOOLEAN rtmp_rx_done_handle(RTMP_ADAPTER *pAd) } #endif /* RTMP_MAC_PCI */ - os_zero_mem(&rxblk, sizeof(RX_BLK)); pRxBlk = &rxblk; pRxPacket = op->get_pkt_from_rx_resource(pAd, &bReschedule, &RxPending, HIF_RX_IDX0); diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_info.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_info.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_info.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_info.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_info_element.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_info_element.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_info_element.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_info_element.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mac_pci.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mac_pci.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mac_pci.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mac_pci.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat_iparp.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_iparp.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat_iparp.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_iparp.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat_ipv6.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_ipv6.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat_ipv6.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_ipv6.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat_pppoe.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_pppoe.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mat_pppoe.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_pppoe.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mumimo.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mumimo.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_mumimo.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mumimo.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_profile.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_profile.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_profile.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_profile.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_radar.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_radar.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_radar.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_radar.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_rdm_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rdm_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_rdm_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rdm_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_rf_cal.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rf_cal.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_rf_cal.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rf_cal.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_rvr_dbg.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rvr_dbg.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_rvr_dbg.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rvr_dbg.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_sanity.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_sanity.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_sanity.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_sanity.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_sync.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_sync.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_sync.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_sync.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_tcprack.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_tcprack.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_tcprack.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_tcprack.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_txbf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_txbf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_txbf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_txbf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_video.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_video.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cmm_video.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_video.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cut_through.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cut_through.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/cut_through.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cut_through.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ee_efuse.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_efuse.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ee_efuse.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_efuse.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ee_flash.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_flash.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ee_flash.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_flash.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ee_prom.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_prom.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ee_prom.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_prom.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/eeprom.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/eeprom.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/eeprom.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/eeprom.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fp_fair_qm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fp_fair_qm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fp_fair_qm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fp_fair_qm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fp_qm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fp_qm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fp_qm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fp_qm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fpga.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fpga.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fpga.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fpga.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fq_qm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fq_qm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/fq_qm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fq_qm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft_iocl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_iocl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft_iocl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_iocl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft_rc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_rc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft_rc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_rc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft_tlv.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_tlv.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ft_tlv.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_tlv.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ftm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ftm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ftm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ftm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/gas.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/gas.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/gas.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/gas.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/hif_pci.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/hif_pci.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/hif_pci.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/hif_pci.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/hotspot.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/hotspot.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/hotspot.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/hotspot.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/icap.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/icap.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/icap.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/icap.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/igmp_snoop.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/igmp_snoop.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/igmp_snoop.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/igmp_snoop.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/map.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/map.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/map.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/map.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mbo.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mbo.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mbo.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mbo.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/misc_app.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/misc_app.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/misc_app.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/misc_app.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mlme.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mlme.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mlme.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mlme.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mt_io.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mt_io.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mt_io.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mt_io.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mt_ps.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mt_ps.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/mt_ps.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mt_ps.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/multi_channel.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/multi_channel.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/multi_channel.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/multi_channel.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/multi_profile.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/multi_profile.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/multi_profile.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/multi_profile.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/netif_block.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/netif_block.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/netif_block.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/netif_block.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/nfc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/nfc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/nfc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/nfc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/op_class.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/op_class.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/op_class.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/op_class.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ps.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ps.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ps.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ps.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/qm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/qm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/qm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/qm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ra_ac_q_mgmt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ra_ac_q_mgmt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ra_ac_q_mgmt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ra_ac_q_mgmt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ral_ps.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ral_ps.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/ral_ps.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ral_ps.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/routing_tab.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/routing_tab.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/routing_tab.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/routing_tab.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rrm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rrm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rrm_sanity.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm_sanity.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rrm_sanity.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm_sanity.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rrm_tlv.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm_tlv.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rrm_tlv.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm_tlv.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rt_channel.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_channel.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rt_channel.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_channel.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rt_led.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_led.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rt_led.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_led.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rt_os_util.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_os_util.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rt_os_util.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_os_util.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rtmp_init.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_init.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rtmp_init.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_init.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rtmp_init_inf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_init_inf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rtmp_init_inf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_init_inf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rtmp_timer.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_timer.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/rtmp_timer.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_timer.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/scan.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/scan.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/scan.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/scan.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/scs.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/scs.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/scs.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/scs.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/smartant.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/smartant.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/smartant.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/smartant.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/sniffer_prism.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sniffer_prism.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/sniffer_prism.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sniffer_prism.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/sniffer_radiotap.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sniffer_radiotap.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/sniffer_radiotap.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sniffer_radiotap.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/spectrum.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/spectrum.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/spectrum.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/spectrum.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/sys_log.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sys_log.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/sys_log.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sys_log.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/txpower.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/txpower.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/txpower.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/txpower.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/txs.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/txs.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/txs.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/txs.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/uapsd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/uapsd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/uapsd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/uapsd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/vendor.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/vendor.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/vendor.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/vendor.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/verf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/verf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/verf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/verf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/vht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/vht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/vht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/vht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wdev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wdev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wdev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wdev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wifi_sys_info.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wifi_sys_info.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wifi_sys_info.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wifi_sys_info.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wifi_sys_notify.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wifi_sys_notify.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wifi_sys_notify.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wifi_sys_notify.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wnm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wnm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wnm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wnm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc_tlv.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_tlv.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc_tlv.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_tlv.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc_ufd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_ufd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc_ufd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_ufd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc_v2.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_v2.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/common/wsc_v2.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_v2.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/Doxyfile b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/Doxyfile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/Doxyfile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/Doxyfile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/FirmwareHistory.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/FirmwareHistory.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/FirmwareHistory.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/FirmwareHistory.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/History.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/History.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/History_sta_pci.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History_sta_pci.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/History_sta_pci.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History_sta_pci.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/History_sta_usb.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History_sta_usb.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/History_sta_usb.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History_sta_usb.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/README b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/README rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_pci b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_pci new file mode 100644 index 000000000..fc8020d73 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_pci @@ -0,0 +1,528 @@ +* README +* +* Ralink Tech Inc. +* +* http://www.ralinktech.com +* + +======================================================================= +ModelName: +=========== +RT2860 Wireless Lan Linux Driver + + +======================================================================= +Driver lName: +============= +rt2860.o/rt2860.ko + + +======================================================================= +Supporting Kernel: +=================== +linux kernel 2.4 and 2.6 series. +Tested in Redhat 7.3 or later. + + +======================================================================= +Description: +============= +This is a linux device driver for Ralink RT2860 ABGN WLAN Card. + + +======================================================================= +Contents: +============= +Makefile : Makefile +*.c : c files +*.h : header files + + +======================================================================= +Features: +========== + This driver implements basic IEEE802.11. Infrastructure and adhoc mode with + open or shared or WPA-PSK or WPA2-PSK authentication method. + NONE, WEP, TKIP and AES encryption. + + +======================================================================= +Build Instructions: +==================== + +1> $tar -xvzf DPB_RT2860_Linux_STA_x.x.x.x.tgz + go to "./DPB_RT2860_Linux_STA_x.x.x.x" directory. + +2> In Makefile + set the "MODE = STA" in Makefile and chose the TARGET to Linux by set "TARGET = LINUX" + define the linux kernel source include file path LINUX_SRC + modify to meet your need. + +3> In os/linux/config.mk + define the GCC and LD of the target machine + define the compiler flags CFLAGS + modify to meet your need. + ** Build for being controlled by NetworkManager or wpa_supplicant wext functions + Please set 'HAS_WPA_SUPPLICANT=y' and 'HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y'. + => #>cd wpa_supplicant-x.x + => #>./wpa_supplicant -Dwext -ira0 -c wpa_supplicant.conf -d + ** Build for being controlled by WpaSupplicant with Ralink Driver + Please set 'HAS_WPA_SUPPLICANT=y' and 'HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n'. + => #>cd wpa_supplicant-0.5.7 + => #>./wpa_supplicant -Dralink -ira0 -c wpa_supplicant.conf -d + +4> $make + # compile driver source code + # To fix "error: too few arguments to function iwe_stream_add_event" + => $patch -i os/linux/sta_ioctl.c.patch os/linux/sta_ioctl.c + +5> $cp RT2860STA.dat /etc/Wireless/RT2860STA/RT2860STA.dat + +6> load driver + #[kernel 2.4] + # $/sbin/insmod rt2860sta.o + # $/sbin/ifconfig ra0 inet YOUR_IP up + + #[kernel 2.6] + # $/sbin/insmod rt2860sta.ko + # $/sbin/ifconfig ra0 inet YOUR_IP up + +7> unload driver + $/sbin/ifconfig ra0 down + $/sbin/rmmod rt2860sta + +======================================================================= +CONFIGURATION: +==================== +RT2860 driver can be configured via following interfaces, +i.e. (i)"iwconfig" command, (ii)"iwpriv" command, (iii) configuration file + +i) iwconfig comes with kernel. +ii) iwpriv usage, please refer to file "iwpriv_usage.txt" for details. +iii)modify configuration file "RT2860STA.dat" in /etc/Wireless/RT2860STA/RT2860STA.dat. + +Configuration File : RT2860STA.dat +--------------------------------------- +# Copy this file to /etc/Wireless/RT2860STA/RT2860STA.dat +# This file is a binary file and will be read on loading rt.o module. +# +# Use "vi -b rt61sta.dat" to modify settings according to your need. +# +# 1.) set NetworkType to "Adhoc" for using Adhoc-mode, otherwise using Infrastructure +# 2.) set Channel to "0" for auto-select on Infrastructure mode +# 3.) set SSID for connecting to your Accss-point. +# 4.) AuthMode can be "WEPAUTO", "OPEN", "SHARED", "WPAPSK", "WPA2PSK", "WPANONE" +# 5.) EncrypType can be "NONE", "WEP", "TKIP", "AES" +# for more information refer to the Readme file. +# +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode= +SSID=Dennis2860AP +NetworkType=Infra +WirelessMode=9 +Channel=0 +BeaconPeriod=100 +TxPower=100 +BGProtection=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +WmmCapable=0 +AckPolicy=0;0;0;0 +AuthMode=OPEN +EncrypType=NONE +WPAPSK= +DefaultKeyID=1 +Key1Type=0 +Key1Str= +Key2Type=0 +Key2Str= +Key3Type=0 +Key3Str= +Key4Type=0 +Key4Str= +PSMode=CAM +FastRoaming=0 +RoamThreshold=70 +HT_RDG=1 +HT_EXTCHA=0 +HT_OpMode=1 +HT_MpduDensity=4 +HT_BW=1 +HT_AutoBA=1 +HT_BADecline=0 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +HT_MIMOPSMode=3 +EthConvertMode= +EthCloneMac= +IEEE80211H=0 +TGnWifiTest=0 +WirelessEvent=0 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +CarrierDetect=0 + +----------------------------------------------- +*NOTE: + WMM parameters + WmmCapable Set it as 1 to turn on WMM Qos support + AckPolicy1~4 Ack policy which support normal Ack or no Ack + (AC_BK, AC_BE, AC_VI, AC_VO) + + All WMM parameters do not support iwpriv command but WmmCapable, + please store all parameter to RT2860STA.dat, and restart driver. + +----------------------------------------------- +syntax is 'Param'='Value' and describes below. + +@> CountryRegion=value + value + 0: use 1 ~ 11 Channel + 1: use 1 ~ 13 Channel + 2: use 10 ~ 11 Channel + 3: use 10 ~ 13 Channel + 4: use 14 Channel + 5: use 1 ~ 14 Channel + 6: use 3 ~ 9 Channel + 7: use 5 ~ 13 Channel + 31: use 1 ~ 14 Channel (ch1-11:active scan, ch12-14 passive scan) + +@> CountryRegionABand=value + value + 0: use 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 Channel + 1: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 Channel + 2: use 36, 40, 44, 48, 52, 56, 60, 64 Channel + 3: use 52, 56, 60, 64, 149, 153, 157, 161 Channel + 4: use 149, 153, 157, 161, 165 Channel + 5: use 149, 153, 157, 161 Channel + 6: use 36, 40, 44, 48 Channel + 7: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 Channel + 8: use 52, 56, 60, 64 Channel + 9: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 Channel + 10: use 36, 40, 44, 48, 149, 153, 157, 161, 165 Channel + 11: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 Channel + +@> CountryCode=value + value + AG, AR, AW, AU, AT, BS, BB, BM, BR, BE, BG, CA, KY, CL, CN, CO, CR, CY, CZ, DK, DO, EC, SV, FI, FR, DE, + GR, GU, GT, HT, HN, HK, HU, IS, IN, ID, IE, IL, IT, JP, JO, LV, LI, LT, LU, MY, MT, MA, MX, NL, NZ, NO, + PE, PT, PL, RO, RU, SA, CS, SG, SK, SI, ZA, KR, ES, SE, CH, TW, TR, GB, UA, AE, US, VE + "" => using default setting: 2.4 G - ch 1~11; 5G - ch 52~64, 100~140, 149~165 + +@> SSID=value + value + 0~z, 1~32 ascii characters. + +@> WirelessMode=value + value + 0: legacy 11b/g mixed + 1: legacy 11B only + 2: legacy 11A only //Not support in RfIcType=1(id=RFIC_5225) and RfIcType=2(id=RFIC_5325) + 3: legacy 11a/b/g mixed //Not support in RfIcType=1(id=RFIC_5225) and RfIcType=2(id=RFIC_5325) + 4: legacy 11G only + 5: 11ABGN mixed + 6: 11N only + 7: 11GN mixed + 8: 11AN mixed + 9: 11BGN mixed + 10: 11AGN mixed + +@> Channel=value + value + depends on CountryRegion or CountryRegionABand + +@> BGProtection=value + value + 0: Auto + 1: Always on + 2: Always off + +@> TxPreamble=value + value + 0:Preamble Long + 1:Preamble Short + 2:Auto + +@> RTSThreshold=value + value + 1~2347 + +@> FragThreshold=value + value + 256~2346 + +@> TxBurst=value + value + 0: Disable + 1: Enable + +@> NetworkType=value + value + Infra: infrastructure mode + Adhoc: adhoc mode + +@> AuthMode=value + value + OPEN For open system + SHARED For shared key system + WEPAUTO Auto switch between OPEN and SHARED + WPAPSK For WPA pre-shared key (Infra) + WPA2PSK For WPA2 pre-shared key (Infra) + WPANONE For WPA pre-shared key (Adhoc) + WPA Use WPA-Supplicant + WPA2 Use WPA-Supplicant + +@> EncrypType=value + value + NONE For AuthMode=OPEN + WEP For AuthMode=OPEN or AuthMode=SHARED + TKIP For AuthMode=WPAPSK or WPA2PSK + AES For AuthMode=WPAPSK or WPA2PSK + +@> DefaultKeyID=value + value + 1~4 + +@> Key1=value + Key2=value + Key3=value + Key4=value + value + 10 or 26 hexadecimal characters eg: 012345678 + 5 or 13 ascii characters eg: passd + (usage : "iwpriv" only) + +@> Key1Type=vaule + Key2Type=value + Key3Type=vaule + Key4Type=vaule + value + 0 hexadecimal type + 1 assic type + (usage : reading profile only) + +@> Key1Str=value + Key2Str=value + Key3Str=vaule + Key4Str=vaule + value + 10 or 26 characters (key type=0) + 5 or 13 characters (key type=1) + (usage : reading profile only) + +@> WPAPSK=value + value + 8~63 ASCII or + 64 HEX characters + +@> WmmCapable=value + value + 0: Disable WMM + 1: Enable WMM + +@> PSMode=value + value + CAM Constantly Awake Mode + Max_PSP Max Power Savings + Fast_PSP Power Save Mode + +@> FastRoaming=value + value + 0 Disabled + 1 Enabled + +@> RoamThreshold=value + value + Positive Interger(dBm) + +@> HT_RDG=value + value + 0 Disabled + 1 Enabled + +@> HT_EXTCHA=value (Extended Channel Switch Announcement) + value + 0 Below + 1 Above + +@> HT_OpMode=value + value + 0 HT mixed format + 1 HT greenfield format + +@> HT_MpduDensity=value + value (based on 802.11n D2.0) + 0: no restriction + 1: 1/4 gs + 2: 1/2 gs + 3: 1 gs + 4: 2 gs + 5: 4 gs + 6: 8 gs + 7: 16 gs + +@> HT_BW=value + value + 0 20MHz + 1 40MHz + +@> HT_AutoBA=value + value + 0 Disabled + 1 Enabled + +@> HT_BADecline + value + 0 Disabled + 1 Enabled + +@> HT_AMSDU=value + value + 0 Disabled + 1 Enabled + +@> HT_BAWinSize=value + value + 1 ~ 64 + +@> HT_GI=value + value + 0 long GI + 1 short GI + +@> HT_MCS=value + value + 0 ~ 15 + 33: auto + +@> HT_MIMOPSMode=value + value (based on 802.11n D2.0) + 0 Static SM Power Save Mode + 1 Dynamic SM Power Save Mode + 2 Reserved + 3 SM enabled + (not fully support yet) + +@> EthConvertMode=value + value + dongle + clone + hybrid + +@> EthCloneMac=value + value + xx:xx:xx:xx:xx:xx + +@> IEEE80211H=value + value + 0 Disabled + 1 Enabled + +@> TGnWifiTest=value + value + 0 Disabled + 1 Enabled + +@> WirelessEvent=value + value + 0 Disabled + 1 Enabled + +@> MeshId=value + value + Length 1~32 ascii characters + +@> MeshAutoLink=value + value + 0 Disabled + 1 Enabled + +@> MeshAuthMode=value + value + OPEN For open system + WPANONE For WPA pre-shared key (Adhoc) + +@> MeshEncrypType=value + value + NONE For MeshAuthMode=OPEN + WEP For MeshAuthMode=OPEN + TKIP For MeshAuthMode=WPANONE + AES For MeshAuthMode=WPANONE + +@> MeshWPAKEY=value + value + 8~63 ASCII or + 64 HEX characters + +@> MeshDefaultkey=value + value + 1~4 + +@> MeshWEPKEY=value + value + 10 or 26 characters + 5 or 13 characters + +@> CarrierDetect=value + value + 0 Disabled + 1 Enabled + +MORE INFORMATION +================================================================================= +If you want for rt2860 driver to auto-load at boot time: +A) choose ra0 for first RT2860 WLAN card, ra1 for second RT2860 WLAN card, etc. + +B) create(edit) 'ifcfg-ra0' file in /etc/sysconfig/network-scripts/, + edit( or add the line) in /etc/modules.conf: + alias ra0 rt2860sta + +C) edit(create) the file /etc/sysconfig/network-scripts/ifcfg-ra0 + DEVICE='ra0' + ONBOOT='yes' + + +NOTE: + if you use dhcp, add this line too . + BOOTPROTO='dhcp' + +*D) To ease the Default Gateway setting, + add the line + GATEWAY=x.x.x.x + in /etc/sysconfig/network + +======================================================================= +Dongle/Clone Features: +====================== +A) Dongle mode: + Provides a 1-to-N MAC address mapping mechanism such that more than one PC behind the STA + can transparently connect to the AP. + +B) Clone mode: + Provides a 1-to-1 MAC address mapping mechanism. + STA can use own MAC as SA MAC or + use user desired MAC as SA MAC or + use source MAC of first packet coming from wired device as SA MAC. + NOTE: In this mode, only the PC who own the specified MAC can connect to the AP. + + +C) Hybrid mode(Dongle+Clone): + Provides a 1-to-N MAC address mapping mechanism such that more than one PC behind the STA + can transparently connect to the AP. + STA can use own MAC as SA MAC or + use user desired MAC as SA MAC or + use source MAC of first packet coming from wired device as SA MAC. + +D) Please refer to "Config STA to link as dongle mode..." in iwpriv_usage.txt for releated commands. \ No newline at end of file diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/README_STA_usb b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_usb similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/README_STA_usb rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_usb diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/RT2860card.readme b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/RT2860card.readme similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/RT2860card.readme rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/RT2860card.readme diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/RT_WIFI_Revision_History_2010_April.xls b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/RT_WIFI_Revision_History_2010_April.xls similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/RT_WIFI_Revision_History_2010_April.xls rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/RT_WIFI_Revision_History_2010_April.xls diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/VxWorks.README b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/VxWorks.README similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/VxWorks.README rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/VxWorks.README diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/ate_iwpriv_usage.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/ate_iwpriv_usage.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/ate_iwpriv_usage.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/ate_iwpriv_usage.txt diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/brftph_usage.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/brftph_usage.txt new file mode 100644 index 000000000..63392e86d --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/brftph_usage.txt @@ -0,0 +1,68 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +The steps for bridge fast path function in wireless driver: + +1. Change HAS_BGFP_SUPPORT=y and HAS_BGFP_OPEN_SUPPORT=y + Note1: When you just only want to enable fast path in WLAN module, you can + only enable HAS_BGFP_SUPPORT. + Note2: When you want to enable fast path in WLAN and Ethernet module, you + need to enable HAS_BGFP_SUPPORT and HAS_BGFP_OPEN_SUPPORT. + + +The steps for bridge fast path function in ethernet driver: + +1. Find the function you pass received packets to upper layer. +2. Path code to the function. + +Note: If the ethernet driver is a library type, i.e. ***.ko, you must insert +the ethernet driver to the Linux kernel before RALINK WLAN driver. + +For examples: + +1. Declare a symbol and a function prototype. + UINT32 (*RALINK_FP_Handle)(PNDIS_PACKET pPacket); + EXPORT_SYMBOL(RALINK_FP_Handle); + +2. Support your received handler, called packet_forward() + + In Linux, find the keyword, netif_rx(), such as + packet_forward() + { + ...... + + // pass the packet to upper layer + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); + } + +3. Change the code segment to + packet_forward() + { + UINT32 HandRst = 1; + + ...... + + if (RALINK_FP_Handle != NULL) + HandRst = RALINK_FP_Handle(skb); + + if (HandRst != 0) + { + // pass the packet to upper layer + // printk("pass to upper layer!\n"); + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); + } + } diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/header_translation.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/header_translation.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/header_translation.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/header_translation.txt diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/iwpriv_usage.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/iwpriv_usage.txt new file mode 100644 index 000000000..940d646c9 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/iwpriv_usage.txt @@ -0,0 +1,447 @@ +iwpriv +================= +This is detailed explanation of each parameters for iwpriv. +Before reading this document, make sure you already read README. + +------------------------------------------------------------------------------------------------------- +USAGE: + iwpriv ra0 commands val + +NOTE: + Wireless Extension Private Handlers + +where +[commands] [val] + {range} +----------------- ------------------------------------------------- +wsc_conf_mode {0, 1, 2} + ::Set WPS conf mode + 0: WPS Disabled + 1: Enrollee + 2: Registrar + +wsc_mode {1, 2} + ::PIN or PBC + 1: PIN + 2: PBC + +wsc_pin {00000000 ~ 99999999} + ::Set Enrollee's PIN Code + +wsc_ssid {0~z, 1~32 ascii characters} + ::Set WPS AP SSID + +wsc_start NULL + ::Trigger RT2860 STA driver to do WPS process + +wsc_stop NULL + ::Stop WPS process + +wsc_gen_pincode NULL + ::Generate new PIN code + +wsc_cred_count {1 ~ 8} + ::Set count of WPS credential + +wsc_cred_ssid {"idx ssid_str"} + ::Set SSID into credtentail[idx] + idx: 0 ~ 7 + ssid_str: 0~z, 1~32 ascii characters + +wsc_cred_auth {"idx auth_str"} + ::Set AuthMode into credtentail[idx] + idx: 0 ~ 7 + auth_str: OPEN, WPAPSK, WPA2PSK, SHARED, WPA, WPA2 + +wsc_cred_encr {"idx encr_str"} + ::Set EncrypType into credtentail[idx] + idx: 0 ~ 7 + encr_str: NONE, WEP, TKIP, AES + +wsc_cred_keyIdx {"idx key_index"} + ::Set Key Index into credtentail[idx] + idx: 0 ~ 7 + key_index: 1 ~ 4 + +wsc_cred_key {"idx key"} + ::Set Key into credtentail[idx] + idx: 0 ~ 7 + key: ASCII string (wep_key_len(=5,13), passphrase_len(=8~63)) + OR + Hex string (wep_key_len(=10,26), passphrase_len(=64)) + +wsc_cred_mac {"idx mac_str"} + ::Set AP's MAC into credtentail[idx] + idx: 0 ~ 7 + mac_str: xx:xx:xx:xx:xx:xx + +wsc_conn_by_idx {0 ~ 7} + ::Connect AP by credential index + +wsc_auto_conn {0, 1} + ::Set driver to re-connecting to AP or not after registration. + 0: Disabled, driver won't re-connect to AP with new configurations. + 1: Enabled, driver will re-connect to AP with new configurations. + +wsc_ap_band {0, 1, 2} + ::Set prefer band to do WPS with dual band WPS AP + 0 : prefer 2.4G + 1 : prefer 5G + 2 : auto + Default value is auto (2) + +------------------------------------------------------------------------------------------------------- +USAGE: + iwpriv ra0 set [parameters]=[val] + +NOTE: + Execute one iwpriv/set command simultaneously. + +where +[parameters] [val] + {range} +----------------- ------------------------------------------------- +CountryRegion {0~7} + ::Set country region + 0: 1 ~ 11 ch + 1: 1 ~ 13 ch + 2: 10, 11 ch + 3: 10 ~ 13 ch + 4: 14 ch + 5: 1 ~ 14 ch + 6: 3 ~ 9 ch + 7: 5 ~ 13 ch + 31: 1 ~ 14 ch (ch1-11:active scan, ch12-14 passive scan) + +CountryRegionABand {0~11} + ::Set country region for A band + 0: 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 ch + 1: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 ch + 2: 36, 40, 44, 48, 52, 56, 60, 64 ch + 3: 52, 56, 60, 64, 149, 153, 157, 161 ch + 4: 149, 153, 157, 161, 165 ch + 5: 149, 153, 157, 161 ch + 6: 36, 40, 44, 48 ch + 7: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 ch + 8: 52, 56, 60, 64 ch + 9: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 ch + 10: 36, 40, 44, 48, 149, 153, 157, 161, 165 ch + 11: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 ch + +SSID {0~z, 1~32 ascii characters} + ::Set AP SSID + +WirelessMode {0~10} + ::Set Wireless Mode + 0: legacy 11b/g mixed + 1: legacy 11B only + 2: legacy 11A only + 3: legacy 11a/b/g mixed + 4: legacy 11G only + 5: 11ABGN mixed + 6: 11N only + 7: 11GN mixed + 8: 11AN mixed + 9: 11BGN mixed + 10: 11AGN mixed + +Channel depends on CountryRegion or CountryRegionForABand + ::Set Channel + +BGProtection {0~2} + ::Set 11B/11G Protection + 0:Auto, + 1:Always on, + 2:Always off + +TxPreamble {0~2} + ::Set TxPreamble + 0:Preamble Long, + 1:Preamble Short, + 2:Auto + +RTSThreshold {1~2347} + ::Set RTS Threshold + +FragThreshold {256~2346} + ::Set Fragment Threshold + +TxBurst {0,1} + ::Set TxBurst Enable or Disable + 0:Disable, + 1:Enable + +NetworkType {Infra,Adhoc} + ::Set Network type + +AuthMode {OPEN,SHARED,WEPAUTO,WPAPSK,WPA2PSK,WPANONE} + ::Set Authentication Mode + +EncrypType {NONE,WEP,TKIP,AES} + ::Set Encryption Type + +DefaultKeyID {1~4} + ::Set Default Key ID + + +Key1 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key1 String + +Key2 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key2 String + +Key3 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key3 String + +Key4 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key4 String + +WPAPSK {8~63 ascii or 64 hex characters} + ::WPA Pre-Shared Key + +WmmCapable {0,1} + ::Set WMM Capable + 0:Disable WMM, + 1:Enable WMM + +PSMode {CAM, MAX_PSP, FAST_PSP} + ::Set Power Saving Mode + +HtBw {0,1} + ::Set BandWidth + 0: 20Hz + 1: 40Hz + +HtMcs {0 ~ 15, 33} + ::Set MCS + 33: Auto Rate + +HtGi {0,1} + ::Set Guard Interval(GI) + 0: long GI + 1: short GI + +HtOpMode {0,1} + ::Set HT Operation Mode + 0: HT mixed format + 1: HT greenfield format + +HtExtcha {0,1} + ::Set Extended Channel Switch Announcement + 0: Below + 1: Above + +HtMpduDensity {0 ~ 7} + ::Set The Minimum Time Between MPDUs within an AMPDU + +HtBaWinSize {1 ~ 64} + ::Set BA WinSize + +HtRdg {0,1} + ::Set RDG Capable + 0: Disabled + 1: Enabled + +HtAmsdu {0,1} + ::Set AMSDU Capable + 0: Disabled + 1: Enabled + +HtAutoBa {0,1} + ::Set Auto BA Capable + 0: Disabled + 1: Enabled + +HtBaDecline {0,1} + ::Reject BA request from AP + 0: Disabled + 1: Enabled + +HtProtect {0,1} + ::Set HT Protect Capable + 0: Disabled + 1: Enabled + +FixedTxMode {CCK, OFDM} + :: Set Fixed Tx Mode for fixed rate setting + Mode = CCK + MCS = 0 => 1Mbps + = 1 => 2Mbps + = 2 => 5.5 Mbps + = 3 => 11 Mbps + Mode = OFDM + MCS = 0 => 6Mbps + = 1 => 9Mbps + = 2 => 12Mbps + = 3 => 18Mbps + = 4 => 24Mbps + = 5 => 36Mbps + = 6 => 48Mbps + = 7 => 54Mbps + +==> Build Ethernet Convert function. Please set 'HAS_ETH_CONVERT_SUPPORT=y' in os/linux/config.mk +EthConvertMode {dongle, clone, hybrid} + ::Set Ethernet Convert Mode + +EthCloneMac {xx:xx:xx:xx:xx:xx} + :: Set Clone MAC + +LongRetry {0,255} + :: Set Tx Long Retry Limit + +ShortRetry {0,255} + :: Set Tx Short Retry Limit + +MeshId {Length 1~32 ascii characters} + :: Set Mesh ID + +MeshHostName {Length 1~32 ascii characters} + :: Set Mesh Host Name + +MeshAutoLink {1,0} + :: Set Mesh Auto Link Capable + 0: Disabled + 1: Enabled + +MeshAddLink {xx:xx:xx:xx:xx:xx} + :: Add Mesh Link + +MeshDelLink {xx:xx:xx:xx:xx:xx} + :: Delete Mesh Link + +MeshMultiCastAgeOut {20 ~ 65535 seconds} + :: Set AgeOut time for Mesh MultiCast + +MeshAuthMode {OPEN, WPANONE} + :: Set Mesh Authentication Mode + +MeshEncrypType {NONE, WEP, TKIP, AES} + :: Set Mesh Encryption Type + +MeshDefaultkey {1 ~ 4} + :: Set Mesh Default Key ID + +MeshWEPKEY {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + :: Set Mesh WEP Key String + +MeshWPAKEY {8~63 ascii or 64 hex characters} + :: Set Mesh WPA Pre-Shared Key + +Examples +=================================================================== +------------------------------------------------------------------------------------------------------- +a> Config STA to link with AP which is OPEN/NONE(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=OPEN + 3. iwpriv ra0 set EncrypType=NONE + 4. iwpriv ra0 set SSID="AP's SSID" + +b> Config STA to link with AP which is SHARED/WEP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=SHARED + 3. iwpriv ra0 set EncrypType=WEP + 4. iwpriv ra0 set DefaultKeyID=1 + 5. iwpriv ra0 set Key1="AP's wep key" + 6. iwpriv ra0 set SSID="AP's SSID" + +c> Config STA to link with AP which is WPAPSK/TKIP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=WPAPSK + 3. iwpriv ra0 set EncrypType=TKIP + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK="AP's wpa-preshared key" + 6. iwpriv ra0 set SSID="AP's SSID" + +d> Config STA to link with AP which is WPAPSK/AES(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=WPAPSK + 3. iwpriv ra0 set EncrypType=AES + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK="AP's wpa-preshared key" + 6. iwpriv ra0 set SSID="AP's SSID" + +e> Config STA to link with AP which is WPA2PSK/TKIP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=WPA2PSK + 3. iwpriv ra0 set EncrypType=TKIP + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK=12345678 + 6. iwpriv ra0 set SSID="AP's SSID" + +f> Config STA to create/link as adhoc mode, which is OPEN/NONE(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Adhoc + 2. iwpriv ra0 set AuthMode=OPEN + 3. iwpriv ra0 set EncrypType=NONE + 4. iwpriv ra0 set SSID="Adhoc's SSID" + +g> Config STA to create/link as adhoc mode, which is WPANONE/TKIP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Adhoc + 2. iwpriv ra0 set AuthMode=WPANONE + 3. iwpriv ra0 set EncrypType=TKIP + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK=12345678 + 6. iwpriv ra0 set SSID="AP's SSID" + +h> Get site survey + usage: iwpriv ra0 get_site_survey + +i> Get Statistics + usage: iwpriv ra0 stat ; read statistic counter + iwpriv ra0 set ResetCounter=0 ; reset statistic counter + +j> Link with an AP which is the largest strength ; set ANY SSID (ssidLen=0) + usage: iwconfig ra0 essid "" + or + usage: iwpriv ra0 set SSID="" + +k> Config STA to link as dongle mode with STA own MAC + usage: iwpriv ra0 set EthConvertMode=dongle + +l> Config STA to link as clone mode + usage: iwpriv ra0 set EthConvertMode=clone + iwpriv ra0 set EthCloneMac="Desired MAC" ;; 00:00:00:00:00:00 means using STA own MAC + ;; FF:FF:FF:FF:FF:FF means using source MAC of first packet coming from wired device + +m> Config STA to link as hybrid(dongle+clone) mode + usage: iwpriv ra0 set EthConvertMode=hybrid + iwpriv ra0 set EthCloneMac="Desired MAC" ;; 00:00:00:00:00:00 means using STA own MAC + ;; FF:FF:FF:FF:FF:FF means using source MAC of first packet coming from wired device + +=================================================================== + +iwlist +================= +This is detailed explanation of each parameters for iwlist. + +------------------------------------------------------------------------------------------------------- +iwlist ra0 scanning ; list the results after scanning(manual rescan) + + + +======================================================================================================= + +iwconfig +================= +The following are our support in standard configuration - iwconfig + +------------------------------------------------------------------------------------------------------- +iwconfig ra0 essid {NN|on|off} ; set essid +iwconfig ra0 mode {managed|ad-hoc|...} ; set wireless mode +>> rt2860sta driver support monitor mode with linux kernel > 2.4.20. +>> Note: For using monitor mode => if mesh interface is ON, please down the mesh interface first. +iwconfig ra0 freq N.NNNN[k|M|G]] ; set frequency +iwconfig ra0 channel N ; set channel +iwconfig ra0 ap {N|off|auto} ; set AP address +iwconfig ra0 nick N ; set nickname +iwconfig ra0 rate {N|auto|fixed} ; set rate (only support legacy rate setting) +iwconfig ra0 rts {N|auto|fixed|off} ; set RTS threshold +iwconfig ra0 frag {N|auto|fixed|off} ; set Fragment threshold +iwconfig ra0 enc {NNNN-NNNN|off} ; set encryption type +iwconfig ra0 power {period N|timeout N} ; set power management modes + +*** Wireless extension usage please refer to man page of 'iwconfig', 'iwlist' and 'iwpriv'. *** diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/mainpage.dox b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mainpage.dox similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/mainpage.dox rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mainpage.dox diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mbss_phy.readme b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mbss_phy.readme new file mode 100644 index 000000000..fd89411a6 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mbss_phy.readme @@ -0,0 +1,65 @@ +Readme for different phy mode of different BSS as below: + +1. Extend WirelessMode usage in DAT file + + EX: WirelessMode=0;9;1;9 i.e. bg, bgn, b-only, bgn, pAd->CommonCfg.PhyMode will be 9 + + EX: WirelessMode=0;0;1;0 i.e. bg, bg, b-only, bg, pAd->CommonCfg.PhyMode will be 0 + + + + +2. Add a new parameter, PhyMode, in MULTISSID_STRUCT structure + + + +3. Use pAd->ApCfg.MBSSID[apidx].PhyMode, not pAd->CommonCfg.PhyMode in APUpdateBeaconFrame() + + Use pAd->ApCfg.MBSSID[apidx].PhyMode, not pAd->CommonCfg.PhyMode in APPeerProbeReqAction() + + + +4. Use maximum capability for all BSS in RT_CfgSetWirelessMode(). + + EX: In MBSS mode, BSS0 is 11g-only, BSS1 is 11b-only, pAd->CommonCfg.PhyMode will be 11bg-mixed. + + EX: In MBSS mode, BSS0 is 11n-2.4G-only, BSS1 is also 11n-2.4G-only, pAd->CommonCfg.PhyMode will be 11n-2.4G-only, not 11bgn-mixed. + + EX: In MBSS mode, BSS0 is 11b-only, BSS1 is also 11b-only, pAd->CommonCfg.PhyMode will be 11b-only. + + EX: In MBSS mode, BSS0 is 11b-only, BSS1 is also 11bgn-mixed, pAd->CommonCfg.PhyMode will be 11bgn-mixed. + + + + So no impact for GreenAP mode. Check with K.H. + + + +5. Add two new command + + (1) iwpriv ra0 set MBSSWirelessMode=[0 ~ 11] + + Set different phy mode for different BSS. + + (2) iwpriv ra0 show mbss + + Show current phy mode for different BSS. EX: + + + + BSS Idx Phy Mode + MAX BGN Mixed + 0 BG Mixed + 1 BG Mixed + 2 BG Mixed + 3 BGN Mixed + + + +6. When ra0 use 2.4G, users set ra1 to 5G, ra0 will be same as ra1. + When ra0 use 5G, users set ra1 to 2.4G, ra0 will be same as ra1. + EX: BSS0 is 11bg-mixed, then users set BSS1 to 11a-only, ra0 will be 11a-only, not 11an-mixed. + EX: BSS0 is 11bg-mixed, then users set BSS1 to 11an-mixed, ra0 will be 11an-mixed. + + +7. Use CONFIG_AP_SUPPORT and MBSS_SUPPORT to include these codes. diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/sta_ate_iwpriv_usage.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/sta_ate_iwpriv_usage.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/doc/sta_ate_iwpriv_usage.txt rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/sta_ate_iwpriv_usage.txt diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/wps_iwpriv_usage.txt b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/wps_iwpriv_usage.txt new file mode 100644 index 000000000..89d87b922 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/wps_iwpriv_usage.txt @@ -0,0 +1,173 @@ +/* + * README: WPS STA as an Enrollee or Registrar +*/ + +0. Build WPS function. Please set 'HAS_WSC=y'. + +1. Enrollee Mode + +1.1) PIN mode: + +Running Scenarios (case 'a' and 'b') + -------------------------------------------------------- + a. Adding an Enrollee to AP+Registrar (EAP) + [AP+Registrar]<----EAP--->[Enrollee Client] + -------------------------------------------------------- + b. Adding an Enrollee with external Registrar (UPnP/EAP) + [External Registrar]<----UPnP--->[AP_Proxy]<---EAP--->[Enrollee Client] + -------------------------------------------------------- + Note: 'EAP' indicates to use wireless medium and 'UPnP' indicates to use + wired or wireless medium. + +(i) [Registrar] or [AP+Registrar] + Enter the Enrollee PinCode on the Registrar and start WPS on the Registrar. + Note: How to get the Enrollee PinCode? Use 'iwpriv ra0 stat' on the Enrollee. + +(ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 1 ;; Enrollee + iwpriv ra0 wsc_mode 1 ;; PIN + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4G, 1: prefer 5G + iwpriv ra0 wsc_ssid "AP's SSID" + iwpriv ra0 wsc_start + +{iii) If the registration is successful, the Enrollee will be re-configured + with the new parameters, and will connect to the AP with these new parameters. + +1.2) PBC mode: + + Running Scenarios (case 'a' only) + -------------------------------------------------------- + a. Adding an Enrollee to AP+Registrar (EAP) + [AP+Registrar]<----EAP--->[Client] + -------------------------------------------------------- + +(i) [AP+Registrar] + Start PBC on the Registrar. + +{ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 1 ;; Enrollee + iwpriv ra0 wsc_mode 2 ;; PBC + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4G, 1: prefer 5G + iwpriv ra0 wsc_start + +{iii) If the registration is successful, the Enrollee will be re-configured + with the new parameters, and will connect to the AP with these new parameters. + + +2. Registrar Mode + +2.1) PIN mode: + +Running Scenarios (case 'a' and 'b') + -------------------------------------------------------- + a. Configure the un-configured AP + [Unconfigured AP]<----EAP--->[Registrar] + -------------------------------------------------------- + b. Configure the configured AP + [Configured AP]<----EAP--->[Registrar] + -------------------------------------------------------- + +(i) [AP] + Start PIN on the Enrollee WPS AP. + +(ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 2 ;; Registrar + iwpriv ra0 wsc_mode 1 ;; PIN + iwpriv ra0 wsc_pin xxxxxxxx ;; AP's PIN Code + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4G, 1: prefer 5G + iwpriv ra0 wsc_ssid "AP's SSID" + iwpriv ra0 wsc_start + +{iii) If the registration is successful; + in case 'a': + The Registrar will be re-configured with the new parameters, + and will connect to the AP with these new parameters; + in case 'b': + The Registrar will be re-configured with AP's configurations, + and will connect to the AP with these new parameters. + +2.2) PBC mode: + same scenarios as PIN mod + +(i) [AP] + Start PBC on the Enrollee WPS AP. + +(ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 2 ;; Registrar + iwpriv ra0 wsc_mode 2 ;; PBC + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4, 1: prefer 5G + iwpriv ra0 wsc_start + +{iii) If the registration is successful; + in case 'a': + The Registrar will be re-configured with the new parameters, + and will connect to the AP with these new parameters; + in case 'b': + The Registrar will be re-configured with AP's configurations, + and will connect to the AP with these new parameters. + + +3. Others + iwpriv ra0 wsc_cred_count 1 ;; Set count of credentials, Only support one credential for M8 in Registrar mode. + integer: 1 ~ 8 + + iwpriv ra0 wsc_cred_ssid "idx ssid_str" ;; Set SSID into credtentail[idx] + string: + idx: 0 ~ 7 + ssid_str: SSID for AP + example: + iwpriv ra0 wsc_cred_ssid "0 wps_ap1" + + iwpriv ra0 wsc_cred_auth "idx auth_str" ;; Set AuthMode into credtentail[idx] + string: + idx: 0 ~ 7 + auth_str: OPEN, WPAPSK, WPA2PSK, SHARED, WPA, WPA2 + example: + iwpriv ra0 wsc_cred_auth "0 WPAPSK" + + iwpriv ra0 wsc_cred_encr "idx encr_str" ;; Set EncrypType into credtentail[idx] + string: + idx: 0 ~ 7 + encr_str: NONE, WEP, TKIP, AES + example: + iwpriv ra0 wsc_cred_encr "0 TKIP" + + iwpriv ra0 wsc_cred_keyIdx "idx key_index" ;; Set Key Index into credtentail[idx] + string: + idx: 0 ~ 7 + key_index: 1 ~ 4 + example: + iwpriv ra0 wsc_cred_keyIdx "0 1" + + iwpriv ra0 wsc_cred_key "idx key" ;; Set Key into credtentail[idx] + string: + idx: 0 ~ 7 + key: ASCII string (wep_key_len(=5,13), passphrase_len(=8~63)) + OR + Hex string (wep_key_len(=10,26), passphrase_len(=64)) + example: + iwpriv ra0 wsc_cred_key "0 12345678" ;; Passphrase + iwpriv ra0 wsc_cred_key "0 abcd" ;; WEP Key + + iwpriv ra0 wsc_cred_mac "idx mac_str" ;; Set AP's MAC into credtentail[idx] + string: + idx: 0 ~ 7 + mac_str: xx:xx:xx:xx:xx:xx + example: + iwpriv ra0 wsc_cred_mac "0 00:11:22:33:44:55" + + iwpriv ra0 wsc_conn_by_idx 0 ;; Connect AP by credential index. + integer: 0 ~ 7 + + iwpriv ra0 wsc_auto_conn 0 ;; If the registration is successful, driver will re-connect to AP or not. + integer: 0 ;; Disabled, driver won't re-connect to AP with new configurations. + 1 ;; Enabled, driver will re-connect to AP with new configurations. + Note. Default value is 1. + + iwpriv ra0 wsc_stop ;; Stop WSC work and don't wait upon two-minute timeout + iwpriv ra0 wsc_ap_band val + val: 0 ;; prefer 2.4G AP + 1 ;; prefer 5G AP + 2 ;; Auto + iwpriv ra0 stat ;; Read statistics counter and WPS status. + \ No newline at end of file diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/hdev_basic.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/hdev_basic.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/hdev_basic.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/hdev_basic.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/omac_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/omac_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/omac_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/omac_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/radio_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/radio_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/radio_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/radio_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/wmm_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/wmm_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/wmm_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/wmm_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/wtbl_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/wtbl_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev/wtbl_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/wtbl_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hdev_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_basic.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_basic.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_basic.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_basic.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_cmd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_cmd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_cmd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_cmd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v1.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v1.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v1.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v1.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v2.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v2.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v2.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v2.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/a4_conn.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/a4_conn.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/a4_conn.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/a4_conn.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/action.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/action.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/action.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/action.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ags.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ags.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ags.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ags.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_apcli.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_apcli.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_apcli.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_apcli.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_autoChSel.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_autoChSel.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_autoChSel.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_autoChSel.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_autoChSel_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_autoChSel_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_autoChSel_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_autoChSel_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_cfg.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_cfg.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_cfg.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_cfg.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_ids.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_ids.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_ids.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_ids.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_mbss.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mbss.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_mbss.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mbss.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_mumimo.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mumimo.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_mumimo.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mumimo.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_mura.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mura.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_mura.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mura.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_repeater.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_repeater.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_repeater.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_repeater.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_vow.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_vow.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_vow.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_vow.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_wds.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_wds.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ap_wds.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_wds.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/arris_mod_api.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/arris_mod_api.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/arris_mod_api.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/arris_mod_api.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/arris_wps_gpio_handler.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/arris_wps_gpio_handler.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/arris_wps_gpio_handler.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/arris_wps_gpio_handler.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/band_steering.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/band_steering.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/band_steering.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/band_steering.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/band_steering_def.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/band_steering_def.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/band_steering_def.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/band_steering_def.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/bcn.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bcn.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/bcn.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bcn.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/bgnd_scan.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bgnd_scan.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/bgnd_scan.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bgnd_scan.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/bgnd_scan_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bgnd_scan_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/bgnd_scan_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bgnd_scan_cmm.h diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/br_ftph.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/br_ftph.h new file mode 100644 index 000000000..7810cf134 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/br_ftph.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * 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 Bridge Fast Path Related Structure & Definition. + +***************************************************************************/ + +#ifndef __BR_FTPH_H__ +#define __BR_FTPH_H__ + +/* Public function prototype */ +/* +======================================================================== +Routine Description: + Init bridge fast path module. + +Arguments: + None + +Return Value: + None + +Note: + Used in module init. +======================================================================== +*/ +VOID BG_FTPH_Init(VOID); + +/* +======================================================================== +Routine Description: + Remove bridge fast path module. + +Arguments: + None + +Return Value: + None + +Note: + Used in module remove. +======================================================================== +*/ +VOID BG_FTPH_Remove(VOID); + +/* +======================================================================== +Routine Description: + Forward the received packet. + +Arguments: + pPacket - the received packet + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 BG_FTPH_PacketFromApHandle( + IN PNDIS_PACKET pPacket); + +#endif /* __BR_FTPH_H__ */ + +/* End of br_ftph.h */ + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cfg80211.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cfg80211.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cfg80211_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cfg80211_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cfg80211extr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211extr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cfg80211extr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211extr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/chlist.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/chlist.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/chlist.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/chlist.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/client_wds.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/client_wds.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/client_wds.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/client_wds.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/client_wds_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/client_wds_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/client_wds_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/client_wds_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cmm_cmd.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_cmd.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cmm_cmd.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_cmd.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cmm_rvr_dbg.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_rvr_dbg.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cmm_rvr_dbg.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_rvr_dbg.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cmm_tcprack.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_tcprack.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cmm_tcprack.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_tcprack.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cs.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cs.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cs.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cs.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cut_through.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cut_through.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/cut_through.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cut_through.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11_base.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11_base.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11_base.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11_base.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11ac_vht.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11ac_vht.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11ac_vht.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11ac_vht.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11k_rrm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11k_rrm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11k_rrm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11k_rrm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11n_ht.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11n_ht.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11n_ht.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11n_ht.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11r_ft.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11r_ft.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11r_ft.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11r_ft.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11u_interworking.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11u_interworking.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11u_interworking.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11u_interworking.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11v_wnm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11v_wnm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/dot11v_wnm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11v_wnm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAeLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAeLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAeLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAeLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAiLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAiLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAiLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAiLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAeLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAeLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAeLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAeLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAiLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAiLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAiLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAiLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_ePAeLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_ePAeLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_ePAeLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_ePAeLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAeLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAeLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAeLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAeLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAiLNA.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAiLNA.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAiLNA.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAiLNA.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7663_e2p.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7663_e2p.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt7663_e2p.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7663_e2p.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt_dmac_e2p_def.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt_dmac_e2p_def.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt_dmac_e2p_def.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt_dmac_e2p_def.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt_e2p_def.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt_e2p_def.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/eeprom/mt_e2p_def.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt_e2p_def.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/efuse.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/efuse.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/efuse.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/efuse.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/event_common.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/event_common.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/event_common.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/event_common.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/firmware.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/firmware.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/firmware.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/firmware.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/fp_qm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fp_qm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/fp_qm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fp_qm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/fq_qm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fq_qm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/fq_qm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fq_qm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/frame_hdr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/frame_hdr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/frame_hdr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/frame_hdr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/frq_cal.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/frq_cal.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/frq_cal.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/frq_cal.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/fsm/fsm_sync.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fsm/fsm_sync.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/fsm/fsm_sync.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fsm/fsm_sync.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ft.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ft.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ft.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ft.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ft_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ft_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ft_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ft_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ftm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ftm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ftm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ftm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ftm_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ftm_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ftm_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ftm_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/gas.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/gas.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/gas.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/gas.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hdev/hdev.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev/hdev.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hdev/hdev.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev/hdev.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hdev/hdev_basic.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev/hdev_basic.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hdev/hdev_basic.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev/hdev_basic.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hdev_ctrl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev_ctrl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hdev_ctrl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev_ctrl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hotspot.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hotspot.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hotspot.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hotspot.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hw_ctrl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hw_ctrl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hw_ctrl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hw_ctrl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hw_ctrl_basic.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hw_ctrl_basic.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/hw_ctrl_basic.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hw_ctrl_basic.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/icap.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/icap.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/icap.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/icap.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/iface.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/iface.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/iface.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/iface.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/iface_util.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/iface_util.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/iface_util.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/iface_util.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/mtk_hif.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/mtk_hif.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/mtk_hif.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/mtk_hif.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/rtmp_inf_pcirbs.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_inf_pcirbs.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/rtmp_inf_pcirbs.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_inf_pcirbs.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/rtmp_pci.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_pci.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/rtmp_pci.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_pci.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/rtmp_rbs.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_rbs.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/iface/rtmp_rbs.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_rbs.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/igmp_snoop.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/igmp_snoop.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/igmp_snoop.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/igmp_snoop.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ipv6.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ipv6.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ipv6.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ipv6.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/l1profile.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/l1profile.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/l1profile.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/l1profile.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/map.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/map.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/map.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/map.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mat.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mat.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mat.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mat.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mbo.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mbo.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mbo.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mbo.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/andes_core.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/andes_core.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/andes_core.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/andes_core.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/andes_mt.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/andes_mt.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/andes_mt.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/andes_mt.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/btcoex.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/btcoex.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/btcoex.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/btcoex.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mcu.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mcu.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mcu.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mcu.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_cr4_firmware.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_cr4_firmware.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_cr4_firmware.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_cr4_firmware.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_firmware.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_firmware.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_firmware.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_firmware.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_firmware_e1.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_firmware_e1.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_firmware_e1.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_firmware_e1.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch_e1.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch_e1.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch_e1.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch_e1.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7622_firmware.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_firmware.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7622_firmware.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_firmware.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7622_firmware_e2.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_firmware_e2.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7622_firmware_e2.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_firmware_e2.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7622_rom_patch_e2.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_rom_patch_e2.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mcu/mt7622_rom_patch_e2.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_rom_patch_e2.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/meminfo_list.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/meminfo_list.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/meminfo_list.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/meminfo_list.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mgmt/be_export.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mgmt/be_export.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mgmt/be_export.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mgmt/be_export.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mgmt/be_internal.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mgmt/be_internal.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mgmt/be_internal.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mgmt/be_internal.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/misc_app.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/misc_app.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/misc_app.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/misc_app.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mlme.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mlme.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme.h diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme_sys.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme_sys.h new file mode 100644 index 000000000..f36fabaaf --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme_sys.h @@ -0,0 +1,9 @@ +/* + +*/ + + +#include "rtmp_type.h" + + + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mt_io.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mt_io.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mt_io.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mt_io.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mt_rdm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mt_rdm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/mt_rdm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mt_rdm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/netif_block.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/netif_block.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/netif_block.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/netif_block.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/nfc.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/nfc.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/nfc.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/nfc.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/oid.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/oid.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/oid.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/oid.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/oid_struct.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/oid_struct.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/oid_struct.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/oid_struct.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/qm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/qm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/qm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/qm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ra_ac_q_mgmt.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ra_ac_q_mgmt.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/ra_ac_q_mgmt.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ra_ac_q_mgmt.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/radar.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/radar.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/radar.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/radar.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/routing_tab.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/routing_tab.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/routing_tab.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/routing_tab.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rrm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rrm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rrm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rrm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rrm_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rrm_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rrm_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rrm_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_cal.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_cal.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_cal.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_cal.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_config.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_config.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_config.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_config.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_led.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_led.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_led.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_led.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_os_net.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_os_net.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_os_net.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_os_net.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_os_util.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_os_util.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_os_util.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_os_util.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_txbf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_txbf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_txbf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_txbf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_udma.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_udma.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rt_udma.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_udma.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_chip.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_chip.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_chip.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_chip.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_cmd.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_cmd.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_cmd.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_cmd.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_comm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_comm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_comm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_comm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_def.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_def.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_def.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_def.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_dmacb.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_dmacb.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_dmacb.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_dmacb.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_dot11.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_dot11.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_dot11.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_dot11.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_iface.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_iface.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_iface.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_iface.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_os.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_os.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_os.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_os.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_osabl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_osabl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_osabl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_osabl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_timer.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_timer.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_timer.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_timer.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_type.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_type.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/rtmp_type.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_type.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/scs.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/scs.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/scs.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/scs.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/bn.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/bn.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/bn.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/bn.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_aes.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_aes.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_aes.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_aes.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_arc4.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_arc4.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_arc4.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_arc4.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_biginteger.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_biginteger.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_biginteger.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_biginteger.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_bignum.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_bignum.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_bignum.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_bignum.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_dh.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_dh.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_dh.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_dh.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_hmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_hmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_hmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_hmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_md5.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_md5.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_md5.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_md5.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_sha2.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_sha2.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/crypt_sha2.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_sha2.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/dh_key.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dh_key.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/dh_key.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dh_key.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/dot11i_wpa.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dot11i_wpa.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/dot11i_wpa.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dot11i_wpa.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/dot11w_pmf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dot11w_pmf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/dot11w_pmf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dot11w_pmf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/ecc.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/ecc.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/ecc.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/ecc.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/owe_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/owe_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/owe_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/owe_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/pmf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/pmf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/pmf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/pmf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/pmf_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/pmf_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/pmf_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/pmf_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sae.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sae.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sae.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sae.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sae_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sae_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sae_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sae_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sec.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sec.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sec.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sec.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sec_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sec_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/sec_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sec_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/wpa.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/wpa.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/wpa.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/wpa.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/wpa_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/wpa_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/security/wpa_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/wpa_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/smartant.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/smartant.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/smartant.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/smartant.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sniffer/radiotap.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sniffer/radiotap.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sniffer/radiotap.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sniffer/radiotap.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sniffer/sniffer.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sniffer/sniffer.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sniffer/sniffer.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sniffer/sniffer.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/spectrum.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/spectrum.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/spectrum.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/spectrum.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/spectrum_def.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/spectrum_def.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/spectrum_def.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/spectrum_def.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sta.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sta.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sta.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sta.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sta_cfg.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sta_cfg.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/sta_cfg.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sta_cfg.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/tm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/tm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/tr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/tr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/tx_power.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tx_power.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/tx_power.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tx_power.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/uapsd.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/uapsd.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/uapsd.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/uapsd.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vendor.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vendor.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vendor.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vendor.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vht.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vht.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vht.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vht.h diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/video.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/video.h new file mode 100644 index 000000000..54ec5e690 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/video.h @@ -0,0 +1,12 @@ +#ifdef VIDEO_TURBINE_SUPPORT +extern AP_VIDEO_STRUCT GLOBAL_AP_VIDEO_CONFIG; + +VOID VideoModeUpdate(IN PRTMP_ADAPTER pAd); +VOID VideoModeDynamicTune(IN PRTMP_ADAPTER pAd); +UINT32 GetAsicDefaultRetry(IN PRTMP_ADAPTER pAd); +UCHAR GetAsicDefaultTxBA(IN PRTMP_ADAPTER pAd); +UINT32 GetAsicVideoRetry(IN PRTMP_ADAPTER pAd); +UCHAR GetAsicVideoTxBA(IN PRTMP_ADAPTER pAd); +VOID VideoConfigInit(IN PRTMP_ADAPTER pAd); +#endif /* VIDEO_TURBINE_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vr_ikans.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vr_ikans.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vr_ikans.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vr_ikans.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vrut_ubm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vrut_ubm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/vrut_ubm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vrut_ubm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wapp/wapp.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wapp/wapp.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wapp/wapp.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wapp/wapp.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wapp/wapp_cmm_type.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wapp/wapp_cmm_type.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wapp/wapp_cmm_type.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wapp/wapp_cmm_type.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wfa_p2p.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wfa_p2p.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wfa_p2p.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wfa_p2p.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wifi_sys_notify.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wifi_sys_notify.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wifi_sys_notify.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wifi_sys_notify.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wlan_config/config_export.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wlan_config/config_export.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wlan_config/config_export.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wlan_config/config_export.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wlan_config/config_internal.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wlan_config/config_internal.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wlan_config/config_internal.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wlan_config/config_internal.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wnm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wnm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wnm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wnm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wnm_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wnm_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wnm_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wnm_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wsc.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wsc.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wsc.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wsc.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wsc_tlv.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wsc_tlv.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/include/wsc_tlv.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wsc_tlv.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mcu/andes_core.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/andes_core.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mcu/andes_core.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/andes_core.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mcu/andes_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/andes_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mcu/andes_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/andes_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mcu/mcu.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/mcu.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mcu/mcu.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/mcu.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_basic.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_basic.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_basic.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_basic.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_ht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_ht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_ht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_ht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_phy.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_phy.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_phy.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_phy.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_vht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_vht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/be_vht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_vht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/bss_ops.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/bss_ops.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/bss_ops.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/bss_ops.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_entrytb.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_entrytb.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_entrytb.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_entrytb.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_ht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_ht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_ht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_ht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_hw.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_hw.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_hw.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_hw.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_vht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_vht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/mgmt/mgmt_vht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_vht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wdma.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wdma.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wdma.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wdma.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wdma.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wdma.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wdma.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wdma.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wed.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wed.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wed.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wed.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wed_def.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed_def.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/wed_def.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed_def.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_basic.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_basic.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_basic.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_basic.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_basic.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_basic.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_basic.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_basic.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hif.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hif.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hif.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hif.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hif.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hif.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hif.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hif.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hw.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hw.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hw.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hw.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hw.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hw.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_hw.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hw.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_main.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_main.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_main.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_main.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_proc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_proc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_proc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_proc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_ser.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_ser.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_ser.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_ser.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_wifi.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_wifi.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/plug_in/whnat/woe_wifi.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_wifi.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/bn_lib.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/bn_lib.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/bn_lib.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/bn_lib.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_aes.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_aes.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_aes.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_aes.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_sec.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_sec.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_sec.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_sec.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_tkip.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_tkip.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_tkip.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_tkip.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_wep.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_wep.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_wep.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_wep.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_wpa.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_wpa.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/cmm_wpa.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_wpa.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_aes.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_aes.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_aes.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_aes.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_arc4.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_arc4.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_arc4.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_arc4.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_biginteger.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_biginteger.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_biginteger.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_biginteger.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_bignum.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_bignum.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_bignum.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_bignum.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_dh.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_dh.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_dh.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_dh.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_hmac.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_hmac.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_hmac.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_hmac.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_md5.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_md5.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_md5.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_md5.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_sha2.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_sha2.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/crypt_sha2.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_sha2.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/dh_key.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/dh_key.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/dh_key.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/dh_key.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/ecc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/ecc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/ecc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/ecc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/owe.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/owe.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/owe.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/owe.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/pmf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/pmf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/pmf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/pmf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/sae.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/sae.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/security/sae.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/sae.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/auto_build_kernel_4_4.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/auto_build_kernel_4_4.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/auto_build_kernel_4_4.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/auto_build_kernel_4_4.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/bin2h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/bin2h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/bin2h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/bin2h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/bin2h.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/bin2h.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/bin2h.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/bin2h.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/build-check-jedi.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/build-check-jedi.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/build-check-jedi.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/build-check-jedi.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/check_build_script.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/check_build_script.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/check_build_script.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/check_build_script.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/i.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/i.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/i.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/i.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/mt7662_freq_plan.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662_freq_plan.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/mt7662_freq_plan.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662_freq_plan.c diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_ap.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_ap.sh new file mode 100644 index 000000000..3fc98ed02 --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_ap.sh @@ -0,0 +1,4 @@ +ifconfig ra0 down +rmmod mt7662e_ap.ko +insmod ../os/linux/mt7662e_ap.ko mac=00:0c:43:11:22:22 +ifconfig ra0 up diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_sta.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_sta.sh new file mode 100644 index 000000000..7d7141b9d --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_sta.sh @@ -0,0 +1,4 @@ +ifconfig ra0 down +rmmod mt7662e_sta.ko +insmod ../os/linux/mt7662e_sta.ko mac=00:0c:43:11:22:22 +ifconfig ra0 up diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/r.sh b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/r.sh similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/tools/r.sh rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/r.sh diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/unload b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/unload similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/unload rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/unload diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wapp/wapp.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wapp/wapp.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wapp/wapp.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wapp/wapp.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_basic.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_basic.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_basic.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_basic.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_ht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_ht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_ht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_ht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_phy.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_phy.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_phy.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_phy.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_vht.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_vht.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/embedded/wlan_config/config_vht.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_vht.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic_mt_dmac.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt_dmac.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic_mt_dmac.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt_dmac.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic_mt_fw.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt_fw.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_asic_mt_fw.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt_fw.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_chip.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_chip.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_chip.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_chip.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_chip_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_chip_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/cmm_chip_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_chip_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/coex.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/coex.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/coex.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/coex.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/greenap.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/greenap.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/greenap.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/greenap.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/hw_init.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/hw_init.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/hw_init.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/hw_init.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/mt_gpio.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/mt_gpio.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/hw_ctrl/mt_gpio.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/mt_gpio.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/chip_id.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/chip_id.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/chip_id.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/chip_id.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7615.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7615.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7615.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7615.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7615_cr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7615_cr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7615_cr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7615_cr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7622.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7622.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7622.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7622.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7622_cr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7622_cr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7622_cr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7622_cr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7663_cr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7663_cr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/mt7663_cr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7663_cr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/p18_cr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/p18_cr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/chip/p18_cr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/p18_cr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/debug.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/debug.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/debug.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/debug.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/link_list.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/link_list.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/link_list.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/link_list.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/module.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/module.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/module.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/module.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/mt_os_util.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/mt_os_util.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/mt_os_util.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/mt_os_util.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/wifi_sys_info.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/wifi_sys_info.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/common/wifi_sys_info.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/wifi_sys_info.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/eeprom/mt_tx_pwr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/eeprom/mt_tx_pwr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/eeprom/mt_tx_pwr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/eeprom/mt_tx_pwr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hif/hif.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hif/hif.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hif/hif.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hif/hif.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hif/mt_hif_pci.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hif/mt_hif_pci.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hif/mt_hif_pci.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hif/mt_hif_pci.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_asic.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_asic.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_asic_mt.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic_mt.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_asic_mt.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic_mt.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_asic_mt_fw.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic_mt_fw.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_asic_mt_fw.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic_mt_fw.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_chip.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_chip.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/cmm_chip.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_chip.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/hw_init.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/hw_init.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/hw_ctrl/hw_init.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/hw_init.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/client.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/client.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/client.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/client.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/dma_sch.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/dma_sch.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/dma_sch.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/dma_sch.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/gpio.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/gpio.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/gpio.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/gpio.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/hw_amsdu.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/hw_amsdu.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/hw_amsdu.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/hw_amsdu.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/mt_dmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/mt_dmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/mt_dmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/mt_dmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/pse.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/pse.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/pse.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/pse.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_agg.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_agg.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_agg.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_agg.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_aon.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_aon.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_aon.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_aon.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_arb.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_arb.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_arb.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_arb.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfg.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfg.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfg.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfg.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfgoff.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfgoff.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfgoff.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfgoff.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_dma.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_dma.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_dma.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_dma.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_etbf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_etbf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_etbf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_etbf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_int_wakeup_top.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_int_wakeup_top.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_int_wakeup_top.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_int_wakeup_top.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_lpon_top.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_lpon_top.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_lpon_top.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_lpon_top.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_mib.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_mib.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_mib.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_mib.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_mu.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_mu.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_mu.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_mu.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_pf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_pf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_pf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_pf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_phy.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_phy.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_phy.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_phy.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_ple.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_ple.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_ple.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_ple.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_pp.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_pp.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_pp.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_pp.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_rmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_rmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_rmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_rmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_sec.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_sec.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_sec.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_sec.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_tmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_tmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_tmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_tmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_trb.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_trb.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_trb.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_trb.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbloff.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbloff.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbloff.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbloff.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtblon.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtblon.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtblon.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtblon.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/mt_mac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/mt_mac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/mt_mac_ctrl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac_ctrl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/mt_mac_ctrl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac_ctrl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/mt_mac_pci.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac_pci.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/mt_mac_pci.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac_pci.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/client.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/client.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/client.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/client.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/dma_sch.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/dma_sch.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/dma_sch.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/dma_sch.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/gpio.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/gpio.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/gpio.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/gpio.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/mt_mac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/mt_mac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/mt_mac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/mt_mac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/mt_smac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/mt_smac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/mt_smac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/mt_smac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/pse.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/pse.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/pse.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/pse.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_agg.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_agg.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_agg.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_agg.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_aon.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_aon.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_aon.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_aon.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_arb.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_arb.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_arb.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_arb.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_cfgoff.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_cfgoff.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_cfgoff.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_cfgoff.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_dma.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_dma.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_dma.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_dma.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_int_wakeup_top.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_int_wakeup_top.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_int_wakeup_top.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_int_wakeup_top.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_lpon_top.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_lpon_top.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_lpon_top.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_lpon_top.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_mib.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_mib.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_mib.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_mib.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_pf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_pf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_pf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_pf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_phy.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_phy.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_phy.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_phy.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_rmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_rmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_rmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_rmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_sec.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_sec.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_sec.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_sec.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_tmac.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_tmac.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_tmac.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_tmac.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_trb.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_trb.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_trb.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_trb.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbloff.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbloff.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbloff.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbloff.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_wtblon.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtblon.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/smac/wf_wtblon.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtblon.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/top.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/top.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mac/mac_mt/top.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/top.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mcu/fwdl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/fwdl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mcu/fwdl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/fwdl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mcu/mt_cmd.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/mt_cmd.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mcu/mt_cmd.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/mt_cmd.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mcu/mt_fdb.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/mt_fdb.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/mcu/mt_fdb.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/mt_fdb.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/bb_soc.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/bb_soc.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/bb_soc.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/bb_soc.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/diag.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/diag.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/diag.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/diag.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/pkt_meta.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/pkt_meta.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/pkt_meta.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/pkt_meta.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_drv.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_drv.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_drv.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_drv.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_ecos_type.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_ecos_type.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_ecos_type.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_ecos_type.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_linux.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_linux.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_linux_cmm.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux_cmm.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_linux_cmm.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux_cmm.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_linux_txrx_hook.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux_txrx_hook.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_linux_txrx_hook.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux_txrx_hook.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_os.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_os.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_os.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_os.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_win.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_win.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_win.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_win.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_wince.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_wince.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/rt_wince.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_wince.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/trace.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/trace.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/trace.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/trace.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/wbsys_res.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/wbsys_res.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/os/wbsys_res.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/wbsys_res.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/mt_bbp.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_bbp.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/mt_bbp.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_bbp.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/mt_phy.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_phy.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/mt_phy.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_phy.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/mt_rf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_rf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/mt_rf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_rf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/phy.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/phy.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/phy.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/phy.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/rlm_cal_cache.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/rlm_cal_cache.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/rlm_cal_cache.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/rlm_cal_cache.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/wf_phy_back.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/wf_phy_back.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/phy/wf_phy_back.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/wf_phy_back.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/protocol/protection.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/protocol/protection.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/protocol/protection.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/protocol/protection.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/protocol/tmr.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/protocol/tmr.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/protocol/tmr.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/protocol/tmr.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/rate_ctrl/ra_ctrl.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/rate_ctrl/ra_ctrl.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/rate_ctrl/ra_ctrl.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/rate_ctrl/ra_ctrl.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txbf/mt_txbf.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txbf/mt_txbf.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txbf/mt_txbf.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txbf/mt_txbf.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txbf/mt_txbf_cal.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txbf/mt_txbf_cal.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txbf/mt_txbf_cal.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txbf/mt_txbf_cal.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_1.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_1.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_1.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_1.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_10.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_10.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_10.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_10.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_11.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_11.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_11.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_11.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_12.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_12.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_12.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_12.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_13.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_13.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_13.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_13.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_14.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_14.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_14.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_14.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_15.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_15.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_15.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_15.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_16.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_16.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_16.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_16.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_17.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_17.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_17.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_17.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_18.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_18.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_18.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_18.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_19.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_19.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_19.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_19.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_2.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_2.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_2.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_2.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_20.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_20.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_20.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_20.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_3.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_3.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_3.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_3.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_4.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_4.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_4.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_4.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_5.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_5.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_5.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_5.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_6.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_6.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_6.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_6.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_7.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_7.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_7.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_7.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_8.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_8.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_8.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_8.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_9.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_9.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/BFBackoffTable_9.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_9.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_1.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_1.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_1.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_1.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_10.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_10.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_10.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_10.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_11.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_11.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_11.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_11.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_12.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_12.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_12.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_12.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_13.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_13.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_13.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_13.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_14.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_14.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_14.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_14.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_15.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_15.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_15.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_15.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_16.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_16.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_16.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_16.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_17.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_17.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_17.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_17.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_18.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_18.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_18.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_18.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_19.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_19.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_19.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_19.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_2.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_2.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_2.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_2.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_20.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_20.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_20.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_20.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_3.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_3.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_3.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_3.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_4.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_4.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_4.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_4.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_5.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_5.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_5.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_5.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_6.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_6.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_6.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_6.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_7.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_7.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_7.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_7.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_8.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_8.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_8.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_8.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_9.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_9.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/SKUTable_9.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_9.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/single_sku.h b/package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/single_sku.h similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/include/txpwr/single_sku.h rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/single_sku.h diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/license/MTK_LICENSE b/package/lean/mt/drivers/mt7615d/src/mt_wifi/license/MTK_LICENSE similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/license/MTK_LICENSE rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/license/MTK_LICENSE diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/license/NOTICE b/package/lean/mt/drivers/mt7615d/src/mt_wifi/license/NOTICE similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/license/NOTICE rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/license/NOTICE diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mac/mt_dmac.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mac/mt_dmac.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mac/mt_dmac.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mac/mt_dmac.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mac/mt_mac.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mac/mt_mac.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mac/mt_mac.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mac/mt_mac.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/fw_cmd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fw_cmd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/fw_cmd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fw_cmd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/fwdl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/fwdl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/fwdl_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/fwdl_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/mt_cmd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/mt_cmd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/mt_cmd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/mt_cmd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/mt_fdb.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/mt_fdb.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/mcu/mt_fdb.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/mt_fdb.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.ap.soc b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.ap.soc similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.ap.soc rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.ap.soc diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_3_18 b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_3_18 similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_3_18 rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_3_18 diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_4_4 b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_4_4 similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_4_4 rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_4_4 diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_ap b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_ap similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_ap rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_ap diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_sta b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_sta similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.mt_wifi_sta rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_sta diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.rlt_wifi b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.rlt_wifi rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.rlt_wifi_ap b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi_ap similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.rlt_wifi_ap rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi_ap diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.rlt_wifi_sta b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi_sta similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.rlt_wifi_sta rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi_sta diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.sta.soc b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.sta.soc similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.sta.soc rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.sta.soc diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.wifi b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.wifi similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Kconfig.wifi rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.wifi diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile-3.10.14.mt_wifi_ap b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile-3.10.14.mt_wifi_ap similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile-3.10.14.mt_wifi_ap rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile-3.10.14.mt_wifi_ap diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.4 b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4 similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.4 rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4 diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.4.netif b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4.netif similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.4.netif rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4.netif diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.4.util b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4.util similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.4.util rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4.util diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.6 b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6 similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.6 rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6 diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.6.netif b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6.netif similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.6.netif rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6.netif diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.6.util b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6.util similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.6.util rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6.util diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.ap.soc b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.ap.soc similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.ap.soc rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.ap.soc diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.ap.usb b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.ap.usb similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.ap.usb rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.ap.usb diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.clean b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.clean similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.clean rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.clean diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.libautoprovision.6 b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.libautoprovision.6 similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.libautoprovision.6 rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.libautoprovision.6 diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.mt_wifi_ap b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.mt_wifi_ap similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.mt_wifi_ap rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.mt_wifi_ap diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.mt_wifi_sta b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.mt_wifi_sta similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.mt_wifi_sta rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.mt_wifi_sta diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap.7637e b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap.7637e similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap.7637e rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap.7637e diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.rlt_wifi_sta b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_sta similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.rlt_wifi_sta rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_sta diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.sta.soc b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.sta.soc similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/Makefile.sta.soc rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.sta.soc diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/android_priv_cmd.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/android_priv_cmd.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/android_priv_cmd.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/android_priv_cmd.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/ap_ioctl.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/ap_ioctl.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/ap_ioctl.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/ap_ioctl.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/bb_soc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/bb_soc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/bb_soc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/bb_soc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/br_ftph.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/br_ftph.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/br_ftph.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/br_ftph.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_ap.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_ap.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_ap.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_ap.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_apcli.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_apcli.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_apcli.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_apcli.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_inf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_inf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_inf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_inf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_p2p.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_p2p.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_p2p.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_p2p.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_rx.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_rx.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_rx.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_rx.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_scan.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_scan.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_scan.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_scan.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_tdls.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_tdls.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_tdls.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_tdls.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_tx.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_tx.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_tx.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_tx.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_util.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_util.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211_util.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_util.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211drv.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211drv.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/cfg80211/cfg80211drv.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211drv.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/config.mk b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/config.mk similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/config.mk rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/config.mk diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/config.mk.cfg80211 b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/config.mk.cfg80211 similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/config.mk.cfg80211 rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/config.mk.cfg80211 diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/diag.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/diag.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/diag.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/diag.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/inf_ppa.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/inf_ppa.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/inf_ppa.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/inf_ppa.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/mt_fwdump.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/mt_fwdump.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/mt_fwdump.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/mt_fwdump.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/multi_main_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/multi_main_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/multi_main_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/multi_main_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/pci_main_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/pci_main_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/pci_main_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/pci_main_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rbus_main_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rbus_main_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rbus_main_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rbus_main_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rbus_prop_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rbus_prop_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rbus_prop_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rbus_prop_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_linux.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_linux.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_linux.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_linux.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_linux_symb.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_linux_symb.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_linux_symb.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_linux_symb.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_main_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_main_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_main_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_main_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_pci_rbus.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_pci_rbus.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_pci_rbus.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_pci_rbus.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_proc.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_proc.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_proc.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_proc.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_profile.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_profile.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_profile.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_profile.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_rbus_pci_drv.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_rbus_pci_drv.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_rbus_pci_drv.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_rbus_pci_drv.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_rbus_pci_util.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_rbus_pci_util.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_rbus_pci_util.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_rbus_pci_util.c diff --git a/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_symb.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_symb.c new file mode 100644 index 000000000..9b2b1e71f --- /dev/null +++ b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_symb.c @@ -0,0 +1,9 @@ +#ifdef OS_ABL_SUPPORT + +#include +#include "rt_config.h" + +EXPORT_SYMBOL(RTMP_DRV_OPS_FUNCTION); + +#endif /* OS_ABL_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_txrx_hook.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_txrx_hook.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_txrx_hook.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_txrx_hook.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_udma.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_udma.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/rt_udma.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_udma.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/tm.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/tm.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/tm.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/tm.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/trace.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/trace.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/trace.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/trace.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/unload b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/unload similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/unload rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/unload diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/vr_bdlt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/vr_bdlt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/vr_bdlt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/vr_bdlt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/vr_ikans.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/vr_ikans.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/vr_ikans.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/vr_ikans.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/wbsys_main_dev.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/wbsys_main_dev.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/os/linux/wbsys_main_dev.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/wbsys_main_dev.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/mt_phy.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/mt_phy.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/mt_phy.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/mt_phy.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/mt_rf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/mt_rf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/mt_rf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/mt_rf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/phy.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/phy.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/phy.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/phy.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/rf.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/rf.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/rf.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/rf.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/rlm_cal_cache.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/rlm_cal_cache.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/phy/rlm_cal_cache.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/rlm_cal_cache.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/protocol/protection.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/protocol/protection.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/protocol/protection.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/protocol/protection.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/protocol/tmr.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/protocol/tmr.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/protocol/tmr.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/protocol/tmr.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_cfg.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_cfg.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_cfg.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_cfg.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_ctrl_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_ctrl_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_ctrl_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_ctrl_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_ctrl_mt_drv.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_ctrl_mt_drv.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_ctrl_mt_drv.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_ctrl_mt_drv.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_wrapper_embedded.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_wrapper_embedded.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/rate_ctrl/ra_wrapper_embedded.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_wrapper_embedded.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txbf/cmm_txbf_cal_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/cmm_txbf_cal_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txbf/cmm_txbf_cal_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/cmm_txbf_cal_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txbf/cmm_txbf_mt.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/cmm_txbf_mt.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txbf/cmm_txbf_mt.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/cmm_txbf_mt.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txbf/txbf_wrapper_embedded.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/txbf_wrapper_embedded.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txbf/txbf_wrapper_embedded.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/txbf_wrapper_embedded.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/dat2h.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/dat2h.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/dat2h.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/dat2h.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/single_sku.c b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/single_sku.c similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/single_sku.c rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/single_sku.c diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_1.dat b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_1.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_1.dat rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_1.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_1.dat b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_1.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_1.dat rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_1.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_default.dat b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_default.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_default.dat rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_default.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_default.dat b/package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_default.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_default.dat rename to package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_default.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi_ap/Kconfig b/package/lean/mt/drivers/mt7615d/src/mt_wifi_ap/Kconfig similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi_ap/Kconfig rename to package/lean/mt/drivers/mt7615d/src/mt_wifi_ap/Kconfig diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi_ap/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi_ap/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi_ap/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi_ap/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi_sta/Kconfig b/package/lean/mt/drivers/mt7615d/src/mt_wifi_sta/Kconfig similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi_sta/Kconfig rename to package/lean/mt/drivers/mt7615d/src/mt_wifi_sta/Kconfig diff --git a/package/lean/mt/drivers/mt_wifi/src/mt_wifi_sta/Makefile b/package/lean/mt/drivers/mt7615d/src/mt_wifi_sta/Makefile similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/mt_wifi_sta/Makefile rename to package/lean/mt/drivers/mt7615d/src/mt_wifi_sta/Makefile diff --git a/package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/RT2860.dat b/package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/RT2860.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/RT2860.dat rename to package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/RT2860.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/Readme.txt b/package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/Readme.txt similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/Readme.txt rename to package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/Readme.txt diff --git a/package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/iNic_ap.dat b/package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/iNic_ap.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/iNic_ap.dat rename to package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/iNic_ap.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/l1profile.dat b/package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/l1profile.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/l1profile.dat rename to package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/l1profile.dat diff --git a/package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/mt7615_3.dat b/package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/mt7615_3.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/src/wlan_cfg/mt7622/mt7615_3.dat rename to package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/mt7615_3.dat diff --git a/package/lean/mt/drivers/mt_wifi/Makefile b/package/lean/mt/drivers/mt_wifi/Makefile index aa990a6f0..439f0fde0 100644 --- a/package/lean/mt/drivers/mt_wifi/Makefile +++ b/package/lean/mt/drivers/mt_wifi/Makefile @@ -1,240 +1,62 @@ -# 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:=mt_wifi -P4REV:=10 -PKG_VERSION:=5.0.4.0 +PKG_VERSION:=1 +PKG_RELEASE:=1 -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME) +PKG_CONFIG_DEPENDS := \ + CONFIG_MTK_CHIP_MT7603E_MT7612E \ + CONFIG_MTK_CHIP_MT7603E_MT7615E \ + CONFIG_MTK_CHIP_MT7615E include $(INCLUDE_DIR)/package.mk -TAR_CMD=$(HOST_TAR) -C $(1)/ $(TAR_OPTIONS) - -define KernelPackage/mt_wifi - CATEGORY:=Kernel modules - TITLE:=MTK wifi AP driver -ifneq ($(CONFIG_MTK_WHNAT_SUPPORT), ) - FILES:=$(PKG_BUILD_DIR)/mt_wifi_ap/mt_wifi.ko \ - $(PKG_BUILD_DIR)/mt_wifi/embedded/tools/plug_in/whnat/mt_whnat.ko - AUTOLOAD:=$(call AutoProbe,mt_wifi mt_whnat) -else - FILES:=$(PKG_BUILD_DIR)/mt_wifi_ap/mt_wifi.ko - AUTOLOAD:=$(call AutoProbe,mt_wifi) -endif - SUBMENU:=Wireless Drivers - MENU:=1 +define Package/mt_wifi + SECTION:=net + CATEGORY:=Network + TITLE:=MTK wifi AP config + DEPENDS:=@TARGET_ramips + SUBMENU:=Wireless endef -ifeq ($(CONFIG_7615_DBDC_MODE),y) - CONFIG_FILE:=dbdc -else - CONFIG_FILE:=in -endif - -define KernelPackage/mt_wifi/config - source "$(SOURCE)/config.$(CONFIG_FILE)" +define Package/mt_wifi/config + source "$(SOURCE)/config.in" endef -PKG_KCONFIG:= \ - AP_SUPPORT \ - RT_FIRST_CARD \ - RT_SECOND_CARD \ - RT_FIRST_IF_RF_OFFSET \ - RT_SECOND_IF_RF_OFFSET \ - MT_WIFI \ - WIFI_BASIC_FUNC \ - MT_WIFI_PATH \ - FIRST_IF_NONE \ - FIRST_IF_EEPROM_FLASH \ - FIRST_IF_EEPROM_EFUSE \ - RT_FIRST_CARD_EEPROM \ - SECOND_IF_NONE \ - SECOND_IF_EEPROM_FLASH \ - SECOND_IF_EEPROM_PROM \ - SECOND_IF_EEPROM_EFUSE \ - RT_SECOND_CARD_EEPROM \ - MULTI_INF_SUPPORT \ - WIFI_BASIC_FUNC \ - WIRELESS_EXT \ - WEXT_SPY \ - WEXT_PRIV \ - DOT11_N_SUPPORT \ - DOT11_VHT_AC \ - WIFI_DRIVER \ - G_BAND_256QAM_SUPPORT \ - BRCM_256QAM_SUPPORT \ - ICAP_SUPPORT \ - MT_AP_SUPPORT \ - BACKGROUND_SCAN_SUPPORT \ - SMART_CARRIER_SENSE_SUPPORT \ - MT_DFS_SUPPORT \ - HDR_TRANS_TX_SUPPORT \ - CHIP_MT7615E \ - HDR_TRANS_RX_SUPPORT \ - DBDC_MODE \ - MULTI_PROFILE_SUPPORT \ - DEFAULT_5G_PROFILE \ - SUPPORT_DYNAMIC_TXOP \ - WSC_INCLUDED \ - MT_STA_SUPPORT \ - WSC_V2_SUPPORT \ - DOT11W_PMF_SUPPORT \ - PASSPOINT_R2 \ - TXBF_SUPPORT \ - IGMP_SNOOP_SUPPORT \ - RATE_ADAPTION \ - RATE_ADAPT_AGBS_SUPPORT \ - RTMP_FLASH_SUPPORT \ - ATE_SUPPORT \ - UAPSD \ - RLT_MAC \ - RLT_BBP \ - RLT_RF \ - RTMP_MAC \ - RTMP_BBP \ - RTMP_RF \ - RTMP_PCI_SUPPORT \ - RTMP_USB_SUPPORT \ - RTMP_RBUS_SUPPORT \ - WIFI_MODE_AP \ - WIFI_MODE_STA \ - WIRELESS_EXT \ - WEXT_SPY \ - WEXT_PRIV \ - WDS_SUPPORT \ - MBSS_SUPPORT \ - APCLI_SUPPORT \ - APCLI_CERT_SUPPORT \ - MAC_REPEATER_SUPPORT \ - RALINK_RT6352 \ - RALINK_MT7620 \ - RALINK_MT7603E \ - CON_WPS_SUPPORT \ - VOW_SUPPORT \ - BAND_STEERING \ - TXOP_ARBITER \ - CFG_SUPPORT_DYNAMIC_TXOP \ - WIFI_MODE_BOTH \ - WIFI_RLT_MAC \ - RLT_MAC \ - WIFI_RTMP_MAC \ - RTMP_MAC \ - WIFI_MT_MAC \ - CHIP_MT7603E \ - CHIP_MT7615E \ - MT_MAC \ - RATE_ADAPTION \ - SUPPORT_OPENWRT \ - SDK_USER_LIGHTY \ - MUMIMO_SUPPORT \ - MU_RA_SUPPORT \ - LED_CONTROL_SUPPORT \ - RA_HW_NAT \ - RA_HW_NAT_WIFI_NEW_ARCH \ - CFG80211_SUPPORT \ - SER_SUPPORT \ - GREENAP_SUPPORT \ - RADIUS_ACCOUNTING_SUPPORT \ - TPC_SUPPORT \ - RLM_CAL_CACHE_SUPPORT \ - RF_LOCKDOWN_SUPPORT \ - PASSPOINT_R2 \ - RED_SUPPORT \ - FIRST_IF_EPAELNA \ - FIRST_IF_IPAILNA \ - FIRST_IF_IPAELNA \ - FIRST_IF_EPAILNA \ - SECOND_IF_EPAELNA \ - SECOND_IF_IPAILNA \ - SECOND_IF_IPAELNA \ - SECOND_IF_EPAILNA \ - THIRD_IF_EPAELNA \ - THIRD_IF_IPAILNA \ - THIRD_IF_IPAELNA \ - THIRD_IF_EPAILNA \ - WIFI_PKT_FWD \ - DOT11K_RRM_SUPPORT \ - DOT11R_FT_SUPPORT \ - MBO_SUPPORT \ - WIFI_PKT_FWD_V1 \ - FIRST_IF_MT7615E \ - FIRST_IF_MT7622 \ - FIRST_IF_MT7626 \ - SECOND_IF_MT7615E \ - THIRD_IF_NONE \ - THIRD_IF_MT7615E \ - RT_THIRD_CARD \ - RT_THIRD_IF_RF_OFFSET \ - THIRD_IF_EEPROM_FLASH \ - THIRD_IF_EEPROM_PROM \ - THIRD_IF_EEPROM_EFUSE \ - RT_THIRD_CARD_EEPROM \ - SPECTRUM_SUPPORT \ - MULTI_PROFILE_SUPPORT \ - PRE_CAL_TRX_SET1_SUPPORT \ - MWDS \ - MCAST_RATE_SPECIFIC \ - WLAN_HOOK \ - COEX_SUPPORT \ - EASY_SETUP_SUPPORT \ - EVENT_NOTIFIER_SUPPORT \ - AIR_MONITOR \ - WNM_SUPPORT \ - INTERWORKING \ - LINUX_NET_TXQ_SUPPORT \ - CHIP_MT7622 \ - CHIP_MT7626 \ - WHNAT_SUPPORT \ - FAST_NAT_SUPPORT \ - PRE_CAL_TRX_SET2_SUPPORT \ - LINK_TEST_SUPPORT \ - TCP_RACK_SUPPORT \ - FQ_SCH_SUPPORT \ - BRCM_256QAM_SUPPORT \ - VHT_TXBF_2G_EPIGRAM_IE_SUPPORT \ - DSCP_PRI_SUPPORT \ - PCIE_ASPM_DYM_CTRL_SUPPORT \ - -PKG_CONFIG_DEPENDS:=$(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_MTK_$c),CONFIG_$(c))) +define Package/mt_wifi/description + MT_WiFi auto config for mt7603/mt7612/mt7615 chips +endef define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" V=1 \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)/mt_wifi_ap" \ - $(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_MTK_$c),CONFIG_$(c)=$(CONFIG_MTK_$(c)))) \ - modules endef -define KernelPackage/mt_wifi/install +define Package/mt_wifi/install $(INSTALL_DIR) $(1)/etc/init.d/ $(INSTALL_DIR) $(1)/lib/wifi/ $(INSTALL_DIR) $(1)/etc/wireless/mt7615/ - $(INSTALL_DIR) $(1)/etc/wireless/mt7603/ $(INSTALL_DIR) $(1)/etc_ro/Wireless/RT2860AP/ -ifeq ($(CONFIG_7615_DBDC_MODE),y) - $(INSTALL_BIN) ./dbdc/l1profile.dat $(1)/etc/wireless/ - $(INSTALL_BIN) ./dbdc/mt7615.1.2G.dat $(1)/etc/wireless/mt7615/ - $(INSTALL_BIN) ./dbdc/mt7615.1.5G.dat $(1)/etc/wireless/mt7615/ - $(INSTALL_BIN) ./dbdc/SingleSKU.dat $(1)/etc_ro/Wireless/RT2860AP/ - $(INSTALL_BIN) ./dbdc/SingleSKU_BF.dat $(1)/etc_ro/Wireless/RT2860AP/ - $(INSTALL_BIN) ./dbdc/mt7615.lua $(1)/lib/wifi - $(INSTALL_BIN) ./dbdc/firmware.sh $(1)/etc/init.d/ + $(INSTALL_DIR) $(1)/lib/preinit/ +ifeq ($(CONFIG_MTK_CHIP_MT7603E_MT7612E),y) + $(INSTALL_BIN) ./files/7603_7612-l1profile.dat $(1)/etc/wireless/l1profile.dat + $(INSTALL_BIN) ./files/mt7603.dat $(1)/etc/wireless/mt7615/mt7615.1.dat + $(INSTALL_BIN) ./files/mt7612.dat $(1)/etc/wireless/mt7615/mt7615.2.dat + $(INSTALL_BIN) ./files/82_load_wifi.sh $(1)/lib/preinit/ +else ifeq ($(CONFIG_MTK_CHIP_MT7603E_MT7615E),y) + $(INSTALL_BIN) ./files/7603_7615-l1profile.dat $(1)/etc/wireless/l1profile.dat + $(INSTALL_BIN) ./files/mt7603.dat $(1)/etc/wireless/mt7615/mt7615.1.dat + $(INSTALL_BIN) ./files/mt7615.dat $(1)/etc/wireless/mt7615/mt7615.2.dat + $(INSTALL_BIN) ./files/82_load_wifi.sh $(1)/lib/preinit/ else - $(INSTALL_BIN) ./files/l1profile.dat $(1)/etc/wireless/ - $(INSTALL_BIN) ./files/mt7615.1.dat $(1)/etc/wireless/mt7615/ - $(INSTALL_BIN) ./files/mt7615.2.dat $(1)/etc/wireless/mt7615/ +endif $(INSTALL_BIN) ./files/SingleSKU.dat $(1)/etc_ro/Wireless/RT2860AP/ $(INSTALL_BIN) ./files/SingleSKU_BF.dat $(1)/etc_ro/Wireless/RT2860AP/ $(INSTALL_BIN) ./files/mt7615.lua $(1)/lib/wifi $(INSTALL_BIN) ./files/firmware.sh $(1)/etc/init.d/ -endif endef -$(eval $(call KernelPackage,mt_wifi)) +$(eval $(call BuildPackage,mt_wifi)) diff --git a/package/lean/mt/drivers/mt_wifi/config.in b/package/lean/mt/drivers/mt_wifi/config.in index c9a2bf819..9b3e9ebdc 100644 --- a/package/lean/mt/drivers/mt_wifi/config.in +++ b/package/lean/mt/drivers/mt_wifi/config.in @@ -1,871 +1,19 @@ -if PACKAGE_kmod-mt_wifi +menu "MT_WIFI Configuration" + depends on PACKAGE_mt_wifi -config MTK_SUPPORT_OPENWRT - bool - default y - depends on PACKAGE_kmod-mt_wifi - -config MTK_WIFI_DRIVER - bool - default y - depends on PACKAGE_kmod-mt_wifi - select MTK_WIFI_MT_MAC - select MTK_MT_MAC - select MTK_FIRST_IF_MT7615E - #select MTK_CHIP_MT7622 - #select MTK_CHIP_MT7626 - #select MTK_SECOND_IF_MT7615E - #select MTK_THIRD_IF_MT7615E - #select MTK_CHIP_MT7615E - -if MTK_WIFI_DRIVER - -choice - prompt "Choose First WiFi Interface" - - config MTK_FIRST_IF_NONE - bool "None" - - config MTK_FIRST_IF_MT7615E - bool "MT7615E" - select MTK_WIFI_MT_MAC - select MTK_MT_MAC - select MTK_CHIP_MT7615E - - config MTK_FIRST_IF_MT7622 - bool "MT7622" - select MTK_WIFI_MT_MAC - select MTK_MT_MAC - select MTK_CHIP_MT7622 - - config MTK_FIRST_IF_MT7626 - bool "MT7626" - select MTK_WIFI_MT_MAC - select MTK_MT_MAC - select MTK_CHIP_MT7626 - - -endchoice - -choice - prompt "Choose Second WiFi Interface" - - config MTK_SECOND_IF_MT7615E - bool "MT7615E" - select MTK_WIFI_MT_MAC - select MTK_CHIP_MT7615E - select MTK_MULTI_INF_SUPPORT - - config MTK_SECOND_IF_NONE - bool "None" - -endchoice - -choice - prompt "Choose Third WiFi Interface" - config MTK_THIRD_IF_NONE - bool "None" - - config MTK_THIRD_IF_MT7615E - bool "MT7615E" - select MTK_WIFI_MT_MAC - select MTK_CHIP_MT7615E - select MTK_MULTI_INF_SUPPORT - -endchoice - -config MTK_RT_FIRST_CARD - int - depends on ! MTK_FIRST_IF_NONE - default 7615 if MTK_FIRST_IF_MT7615E - default 7622 if MTK_FIRST_IF_MT7622 - default 7626 if MTK_FIRST_IF_MT7626 - -config MTK_RT_SECOND_CARD - int - depends on ! MTK_SECOND_IF_NONE - default 7615 if MTK_SECOND_IF_MT7615E - -config MTK_RT_THIRD_CARD - int - depends on ! MTK_THIRD_IF_NONE - default 7615 if MTK_THIRD_IF_MT7615E - -config MTK_RT_FIRST_IF_RF_OFFSET - hex - depends on ! MTK_FIRST_IF_NONE - default 0xc0000 - -config MTK_RT_SECOND_IF_RF_OFFSET - hex - depends on ! MTK_SECOND_IF_NONE - default 0xc8000 - -config MTK_RT_THIRD_IF_RF_OFFSET - hex - depends on ! MTK_THIRD_IF_NONE - default 0xd0000 - -config MTK_MT_WIFI - tristate "MT WIFI Driver" - select MTK_WIFI_BASIC_FUNC if MTK_MT_WIFI - default y - -config MTK_MT_WIFI_PATH - string - depends on MTK_MT_WIFI - default "mt_wifi" - -if MTK_MT_WIFI -menu "WiFi Generic Feature Options" -choice - prompt "EEPROM Type of 1st Card" - depends on ! MTK_FIRST_IF_NONE - - config MTK_FIRST_IF_EEPROM_FLASH - bool "FLASH" - - config MTK_FIRST_IF_EEPROM_PROM - bool "EEPROM" - - config MTK_FIRST_IF_EEPROM_EFUSE - bool "EFUSE" - -endchoice - -config MTK_RT_FIRST_CARD_EEPROM - string - depends on ! MTK_FIRST_IF_NONE - default "prom" if MTK_FIRST_IF_EEPROM_PROM - default "efuse" if MTK_FIRST_IF_EEPROM_EFUSE - default "flash" if MTK_FIRST_IF_EEPROM_FLASH - -choice - prompt "EEPROM Type of 2nd Card" - depends on ! MTK_SECOND_IF_NONE - - config MTK_SECOND_IF_EEPROM_FLASH - bool "FLASH" - - config MTK_SECOND_IF_EEPROM_PROM - bool "EEPROM" - - config MTK_SECOND_IF_EEPROM_EFUSE - bool "EFUSE" - -endchoice - -config MTK_RT_SECOND_CARD_EEPROM - string - depends on ! MTK_SECOND_IF_NONE - default "prom" if MTK_SECOND_IF_EEPROM_PROM - default "efuse" if MTK_SECOND_IF_EEPROM_EFUSE - default "flash" if MTK_SECOND_IF_EEPROM_FLASH - -choice - prompt "EEPROM Type of 3th Card" - depends on ! MTK_THIRD_IF_NONE - - config MTK_THIRD_IF_EEPROM_FLASH - bool "FLASH" - - config MTK_THIRD_IF_EEPROM_PROM - bool "EEPROM" - - config MTK_THIRD_IF_EEPROM_EFUSE - bool "EFUSE" - -endchoice - -config MTK_RT_THIRD_CARD_EEPROM - string - depends on ! MTK_THIRD_IF_NONE - default "prom" if MTK_THIRD_IF_EEPROM_PROM - default "efuse" if MTK_THIRD_IF_EEPROM_EFUSE - default "flash" if MTK_THIRD_IF_EEPROM_FLASH - -config MTK_MULTI_INF_SUPPORT - bool - default y if !MTK_FIRST_IF_NONE && !MTK_SECOND_IF_NONE - -config MTK_WIFI_BASIC_FUNC - bool "Basic Functions" - select MTK_WIRELESS_EXT - select MTK_WEXT_SPY - select MTK_WEXT_PRIV - -config MTK_DOT11_N_SUPPORT - bool "802.11n support" - default y - -config MTK_DOT11_VHT_AC - bool "802.11AC support" - depends on MTK_WIFI_DRIVER - depends on MTK_DOT11_N_SUPPORT - default y - -config MTK_G_BAND_256QAM_SUPPORT - bool "2.4G 256QAM support" - depends on MTK_WIFI_DRIVER - depends on MTK_DOT11_VHT_AC - default y - -config MTK_BRCM_256QAM_SUPPORT - bool "BRCM 2.4G 256QAM support" - depends on MTK_WIFI_DRIVER - depends on MTK_G_BAND_256QAM_SUPPORT - default y - -config MTK_VHT_TXBF_2G_EPIGRAM_IE_SUPPORT - bool "BRCM 2.4G VHT Sounding support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_TPC_SUPPORT - bool "802.11h TPC Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_ICAP_SUPPORT - bool "ICAP Support" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT - default y - -config MTK_SPECTRUM_SUPPORT - bool "Wifi Spectrum Support" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT - default y - -config MTK_BACKGROUND_SCAN_SUPPORT - bool "Background Scan Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_SMART_CARRIER_SENSE_SUPPORT - bool "Smart Carrier Sense Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_MT_DFS_SUPPORT - bool "Dynamic Frequency Selection Support" - depends on MTK_WIFI_DRIVER - default y - -#config WFA_VHT_R2_PF -# bool "WFA VHT R2 Plugfest" -# depends on DOT11_VHT_AC -# default n - -config MTK_HDR_TRANS_TX_SUPPORT - bool "Tx Header Translation" - depends on MTK_CHIP_MT7615E || MTK_CHIP_MT7622 || MTK_CHIP_MT7626 - default y - -config MTK_HDR_TRANS_RX_SUPPORT - bool "Rx Header Translation" - depends on MTK_CHIP_MT7615E || MTK_CHIP_MT7622 || MTK_CHIP_MT7626 - default y - -config MTK_DBDC_MODE - bool "dbdc mode support" - depends on MTK_CHIP_MT7615E || MTK_CHIP_MT7626 - select MULTI_PROFILE_SUPPORT - select DEFAULT_5G_PROFILE +config MTK_CHIP_MT7603E_MT7612E + bool "MTK_CHIP_MT7603E_MT7612E" + default y if PACKAGE_kmod-mt7603e && PACKAGE_kmod-mt76x2e default n -config MTK_MULTI_PROFILE_SUPPORT - bool "Multi Profile Support" - depends on MTK_DBDC_MODE - default n - -config MTK_DEFAULT_5G_PROFILE - bool "5G default profile for DBDC" - depends on MTK_DBDC_MODE -# depends on MTK_MULTI_PROFILE_SUPPORT +config MTK_CHIP_MT7603E_MT7615E + bool "MTK_CHIP_MT7603E_MT7615E" + default y if PACKAGE_kmod-mt7603e && PACKAGE_kmod-mt7615d default n -config MTK_WSC_INCLUDED - bool "WSC (WiFi Simple Config)" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT || MTK_MT_STA_SUPPORT - default y - -config MTK_WSC_V2_SUPPORT - bool "WSC V2(WiFi Simple Config Version 2.0)" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT || MTK_MT_STA_SUPPORT - default y - -config MTK_DOT11W_PMF_SUPPORT - bool "PMF" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT || MTK_MT_STA_SUPPORT - default y - -config MTK_TXBF_SUPPORT - bool "Tx Bean Forming Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_FAST_NAT_SUPPORT - bool "Fast-NAT support" -# depends on RA_HW_NAT_WIFI - default n - -config MTK_WHNAT_SUPPORT - tristate "Wifi Hardware NAT support" - depends on MTK_CHIP_MT7615E - depends on MTK_WLAN_HOOK - depends on MTK_FAST_NAT_SUPPORT - select PACKAGE_kmod-hw_nat +config MTK_CHIP_MT7615E + bool "MTK_CHIP_MT7615E" + default y if PACKAGE_kmod-mt7615d && !PACKAGE_kmod-mt7603e default n -#config LLTD_SUPPORT -# bool "LLTD (Link Layer Topology Discovery Protocol)" -# depends on WIFI_DRIVER -# depends on MT_AP_SUPPORT -# default n - -#config QOS_DLS_SUPPORT -# bool "802.11e DLS ((Direct-Link Setup) Support" -# depends on WIFI_DRIVER -# depends on MT_AP_SUPPORT -# default n - -#config WAPI_SUPPORT -# bool "WAPI Support" -# depends on WIFI_DRIVER -# default n - -config MTK_FTM_SUPPORT - bool "FTM Support" - depends on MTK_WIFI_DRIVER - select MTK_PASSPOINT_R2 - default n - -#config CARRIER_DETECTION_SUPPORT -# bool "Carrier Detect" -# depends on WIFI_DRIVER -# default n - -config MTK_IGMP_SNOOP_SUPPORT - bool "IGMP snooping" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT - default y - -#config BLOCK_NET_IF -# bool "NETIF Block" -# depends on WIFI_DRIVER -# depends on MT_AP_SUPPORT -# default n -# help -# Support Net interface block while Tx-Sw queue full - -#config RATE_ADAPTION -# bool "New Rate Adaptation support" -# depends on WIFI_DRIVER -# default y - -#config NEW_RATE_ADAPT_SUPPORT -# bool "Intelligent Rate Adaption" -# depends on WIFI_DRIVER && RATE_ADAPTION -# default y - -#config AGS_SUPPORT -# bool "Adaptive Group Switching" -# depends on WIFI_DRIVER && RATE_ADAPTION -# depends on MT_AP_SUPPORT || MT_STA_SUPPORT -# default n - -#config RATE_ADAPT_AGBS_SUPPORT -# bool "Adaptive AGBS Mode" -# depends on WIFI_DRIVER && RATE_ADAPTION -# depends on MT_AP_SUPPORT || MT_STA_SUPPORT -# default y - -#config IDS_SUPPORT -# bool "IDS (Intrusion Detection System) Support" -# depends on WIFI_DRIVER -# depends on MT_AP_SUPPORT -# default n - -#config WIFI_WORK_QUEUE -# bool "Work Queue" -# depends on WIFI_DRIVER -# default n - -#config WIFI_SKB_RECYCLE -# bool "SKB Recycle(Linux)" -# depends on WIFI_DRIVER -# depends on MT_AP_SUPPORT -# default n - -config MTK_RTMP_FLASH_SUPPORT - bool "Flash Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_PRE_CAL_TRX_SET1_SUPPORT - bool "Calibration To Flash/BinFile Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_RLM_CAL_CACHE_SUPPORT - bool "RlmCalibrationCache Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_PRE_CAL_TRX_SET2_SUPPORT - bool "Pre-calibration to Flash Support" - depends on MTK_WIFI_DRIVER - default y - -config MTK_RF_LOCKDOWN_SUPPORT - bool "RF Lockdown Support" - depends on MTK_WIFI_DRIVER - default n - -config MTK_LINK_TEST_SUPPORT - bool "Link Test Support" - depends on MTK_WIFI_DRIVER - default n - -#config MTK_LED_CONTROL_SUPPORT -# bool "LED Support" -# depends on MTK_WIFI_DRIVER -# depends on MTK_MT_AP_SUPPORT -# default n - -config MTK_ATE_SUPPORT - bool "ATE/QA Support" - depends on MTK_WIFI_DRIVER - default y - -#config MTK_MEMORY_OPTIMIZATION -# bool "Memory Optimization" -# depends on MTK_WIFI_DRIVER -# default n - -config MTK_PASSPOINT_R2 - bool "Passpoint Release-2 Support" - depends on MTK_WIFI_DRIVER - select MTK_DOT11W_PMF_SUPPORT - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_MBO_SUPPORT - bool "MBO Support" - depends on MTK_WIFI_DRIVER - select MTK_INTERWORKING - select MTK_WNM_SUPPORT - select MTK_DOT11K_RRM_SUPPORT - select MTK_DOT11R_FT_SUPPORT - select MTK_DOT11W_PMF_SUPPORT - default n - -#config TRACE_TCP_PKT -# bool "TCP DATA/ACK packets trace log" -# depends on WIFI_DRIVER -# default n - -config MTK_UAPSD - bool "UAPSD support" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT || MTK_MT_STA_SUPPORT - default y - -config MTK_TCP_RACK_SUPPORT - bool "TCP Reduced ACK support" - depends on MTK_WIFI_DRIVER - default y - -#### PA_LNA_Type choice - -config MTK_RED_SUPPORT - bool "RED(Random Early Drop) support" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT || MTK_MT_STA_SUPPORT - default y - -config MTK_FQ_SCH_SUPPORT - bool "Fair Queueing support" - depends on MTK_WIFI_DRIVER - depends on MTK_MT_AP_SUPPORT && MTK_VOW_SUPPORT - depends on MTK_CHIP_MT7622 - default y - -config MTK_FDB_SUPPORT - bool "FW Debug Port" - depends on MTK_WIFI_DRIVER - default n - -choice - prompt "PA LNA Type of 1st Card" - depends on ! MTK_FIRST_IF_NONE - - config MTK_FIRST_IF_IPAILNA - bool "iPAiLNA" - config MTK_FIRST_IF_IPAELNA - bool "iPAeLNA" - config MTK_FIRST_IF_EPAELNA - bool "ePAeLNA" -# config MTK_FIRST_IF_EPAILNA -# bool "ePAiLNA" -endchoice -choice - prompt "PA LNA Type of 2nd Card" - depends on ! MTK_SECOND_IF_NONE - - config MTK_SECOND_IF_IPAILNA - bool "iPAiLNA" - config MTK_SECOND_IF_IPAELNA - bool "iPAeLNA" - config MTK_SECOND_IF_EPAELNA - bool "ePAeLNA" -# config MTK_SECOND_IF_EPAILNA -# bool "ePAiLNA" -endchoice -choice - prompt "PA LNA Type of 3rd Card" - depends on ! MTK_THIRD_IF_NONE - - config MTK_THIRD_IF_EPAELNA - bool "ePAeLNA" - config MTK_THIRD_IF_IPAILNA - bool "iPAiLNA" - config MTK_THIRD_IF_IPAELNA - bool "iPAeLNA" -# config MTK_THIRD_IF_EPAILNA -# bool "ePAiLNA" -endchoice -#### PA_LNA_Type choice END - -# -# Section for chip architectures -# -# "RLT MAC Support" -config MTK_RLT_MAC - bool - depends on MTK_WIFI_DRIVER - default n - -config MTK_RLT_BBP - bool - -config MTK_RLT_RF - bool - -# "RTMP MAC Support" -config MTK_RTMP_MAC - bool - depends on MTK_WIFI_DRIVER - default n - -config MTK_RTMP_BBP - bool - -config MTK_RTMP_RF - bool - -# -# Section for interfaces -# -config MTK_RTMP_PCI_SUPPORT - bool - -config MTK_RTMP_USB_SUPPORT - bool - -config MTK_RTMP_RBUS_SUPPORT - bool - endmenu - -menu "WiFi Operation Modes" - -config MTK_WIFI_MODE_AP - tristate "AP" - default y - select MTK_MT_AP_SUPPORT - -config MTK_WIFI_MODE_STA - tristate "STA" - select MTK_MT_STA_SUPPORT - -config MTK_WIFI_MODE_BOTH - tristate "APSTA" - select MTK_MT_AP_SUPPORT - select MTK_MT_STA_SUPPORT - - -config MTK_MT_AP_SUPPORT - tristate "Ralink RT2860 802.11n AP support" -# depends on NET_RADIO - select MTK_WIRELESS_EXT - select MTK_WEXT_SPY - select MTK_WEXT_PRIV - default y - -config MTK_WDS_SUPPORT - bool "WDS" - depends on MTK_MT_AP_SUPPORT - default y - -config MTK_MBSS_SUPPORT - bool "MBSSID" - depends on MTK_MT_AP_SUPPORT - default y - -#config NEW_MBSSID_MODE -# bool "New MBSSID MODE" -# depends on MT_AP_SUPPORT && MBSS_SUPPORT -# depends on RALINK_RT3883 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 || RALINK_MT7620 -# default y - -#config ENHANCE_NEW_MBSSID_MODE -# bool "Enhanced MBSSID mode" -# depends on NEW_MBSSID_MODE -# default y - -config MTK_APCLI_SUPPORT - bool "AP-Client Support" - depends on MTK_MT_AP_SUPPORT - default y - -config MTK_APCLI_CERT_SUPPORT - bool "AP-Client TGn Cert Support" - depends on MTK_MT_AP_SUPPORT - depends on MTK_APCLI_SUPPORT - default n - -config MTK_MAC_REPEATER_SUPPORT - bool "MAC Repeater Support" - depends on MTK_MT_AP_SUPPORT - depends on MTK_APCLI_SUPPORT - depends on MTK_RALINK_RT6352 || MTK_RALINK_MT7620 || MTK_RALINK_MT7603E || MTK_MT_AP_SUPPORT - default y - -config MTK_MWDS - bool "Mixed WDS(MWDS)" - depends on MTK_MT_AP_SUPPORT - select MTK_APCLI_SUPPORT - default n - -config MTK_MUMIMO_SUPPORT - bool "MU-MIMO Support" - depends on MTK_WIFI_DRIVER - select MTK_MU_RA_SUPPORT - default y - -config MTK_MU_RA_SUPPORT - bool "MU-RGA Support" - depends on MTK_MUMIMO_SUPPORT - -config MTK_DOT11R_FT_SUPPORT - bool "802.11r Fast BSS Transition" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_DOT11K_RRM_SUPPORT - bool "802.11k Radio Resource Management" - depends on MTK_MT_AP_SUPPORT - default n - -#config SNIFFER_SUPPORT -# bool "SNIFFER" -# depends on MT_AP_SUPPORT -# default n - -config MTK_CFG80211_SUPPORT - bool "CFG80211" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_DSCP_PRI_SUPPORT - bool "Dscp Priority Mapping Support" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_CON_WPS_SUPPORT - bool "Concurrent WPS Support" - depends on MTK_MT_AP_SUPPORT - depends on MTK_APCLI_SUPPORT - depends on MTK_WSC_INCLUDED - depends on MTK_WSC_V2_SUPPORT -# depends on MTK_MULTI_INF_SUPPORT - default n - -#config LLTD_SUPPORT -# bool "LLTD (Link Layer Topology Discovery Protocol)" -# depends on MT_AP_SUPPORT - -#config COC_SUPPORT -# bool "CoC Support" -# depends on MT_AP_SUPPORT -# default n - -#config RT2860V2_SNMP -# bool "Net-SNMP Support" -# depends on MT_AP_SUPPORT - -config MTK_MCAST_RATE_SPECIFIC - bool "User specific tx rate of mcast pkt" - depends on MTK_MT_AP_SUPPORT - default y - -#config EXT_BUILD_CHANNEL_LIST -# bool "Extension Channel List" -# depends on MT_AP_SUPPORT - -#config AUTO_CH_SELECT_ENHANCE -# bool "Auto Channel Selection Enhancement" -# depends on MT_AP_SUPPORT - -config MTK_VOW_SUPPORT - bool "MediaAir(VOW) support" - depends on MTK_MT_AP_SUPPORT - default y - -#config AIRPLAY_SUPPORT -# bool "AIRPLAY Support" -# depends on MT_AP_SUPPORT -# default n - -config MTK_BAND_STEERING - bool "Band Steering" - depends on MTK_MT_AP_SUPPORT - default y - -config MTK_LED_CONTROL_SUPPORT - bool "LED Control Support" - default n - -config MTK_WLAN_HOOK - bool "WLAN hook Support" - depends on MTK_WIFI_DRIVER - default n - -config MTK_RADIUS_ACCOUNTING_SUPPORT - bool "Radius Accounting Support" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_GREENAP_SUPPORT - bool "GreenAP Support" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_PCIE_ASPM_DYM_CTRL_SUPPORT - bool "Pcie Aspm Dynamic Control Support" - depends on MTK_MT_AP_SUPPORT - default y - -config MTK_COEX_SUPPORT - bool "Coex Support" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_EASY_SETUP_SUPPORT - bool "Whole Home Coverage - Easy Setup" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_EVENT_NOTIFIER_SUPPORT - bool "Whole Home Coverage - Event Notifier" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_AIR_MONITOR - bool "Air Monitor" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_WNM_SUPPORT - bool "802.11v WNM Support" - depends on MTK_MT_AP_SUPPORT - default n - -config MTK_INTERWORKING - bool "802.11u Interworking" - depends on MTK_MT_AP_SUPPORT - default n - -#config ROAMING_ENHANCE_SUPPORT -# bool "Roaming Enhance Support" -# depends on MT_AP_SUPPORT -# depends on APCLI_SUPPORT -# default n - -config MTK_LINUX_NET_TXQ_SUPPORT - bool "NET TX Queue Support" - default y - -#config WIFI_FWD_SUPPORT -# bool "WiFi Forwarding Support" -# default n - -endmenu - -endif - -config MTK_WIFI_MT_MAC - bool - default y - depends on MTK_MT_WIFI - -if MTK_WIFI_RLT_MAC - config MTK_RLT_MAC - bool - default y -endif - -if MTK_WIFI_RTMP_MAC - config MTK_RTMP_MAC - bool - default y -endif - -if MTK_WIFI_MT_MAC - config MTK_MT_MAC - bool - default y - - config MTK_CHIP_MT7603E - bool - default n - - config MTK_CHIP_MT7615E - bool - default n - - config MTK_CHIP_MT7622 - bool - default n - - config MTK_CHIP_MT7663E - bool - default n - - config MTK_CHIP_MT7626 - bool - default n -endif - -if MTK_CHIP_MT7615E || MTK_CHIP_MT7622 || MTK_CHIP_MT7626 - config MTK_MT_MAC - bool - default y - select MTK_RATE_ADAPTION - select MTK_RATE_ADAPT_AGBS_SUPPORT - select MTK_DOT11_N_SUPPORT - select MTK_DOT11_VHT_AC - select MTK_HDR_TRANS_TX_SUPPORT - select MTK_HDR_TRANS_RX_SUPPORT -endif - -endif #MTK_WIFI_DRIVER# -endif #PACKAGE_kmod-mt_wifi# - diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/SingleSKU.dat b/package/lean/mt/drivers/mt_wifi/dbdc/SingleSKU.dat deleted file mode 100644 index be9c0d353..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/SingleSKU.dat +++ /dev/null @@ -1,65 +0,0 @@ -# Single SKU Max Power Table | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 2.4G Channel |CCK | | | |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |Txstream_Delta | | | | | | | | | | | | | | | | | | | | | -Band: 2.4G |CCK_1M |CCK_2M |CCK_5.5M |CCK_11M |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | | | | | | | | | | | | | | | | | -Ch1 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |20 |12 |18 |16 |8 | |8 | |8 | |9 |11 |12 |2 |1 |3 | | | | | | | | | | | | | | | | | | | -Ch2 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |19 |19 |10 |12 |8 | |8 | |8 | |9 |16 |12 |5 |4 |0 | | | | | | | | | | | | | | | | | | | -Ch3 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |17 |18 |16 |20 |8 | |8 | |8 | |12 |8 |20 |0 |2 |0 | | | | | | | | | | | | | | | | | | | -Ch4 |8 | |8 | |8 | |8 | |8 | |8 |8 |9 |8 | |8 | |8 | |14 |10 |14 |18 |8 | |8 | |8 | |14 |12 |10 |3 |4 |5 | | | | | | | | | | | | | | | | | | | -Ch5 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |10 |13 |11 |8 |8 | |8 | |8 | |12 |8 |9 |4 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch6 |8 | |8 | |8 | |8 | |8 | |8 |8 |13 |8 | |8 | |8 | |11 |9 |12 |16 |8 | |8 | |8 | |9 |17 |11 |5 |2 |1 | | | | | | | | | | | | | | | | | | | -Ch7 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |14 |11 |13 |18 |8 | |8 | |8 | |16 |13 |10 |2 |5 |4 | | | | | | | | | | | | | | | | | | | -Ch8 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |14 |9 |11 |10 |8 | |8 | |8 | |11 |14 |8 |5 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch9 |8 | |8 | |8 | |8 | |8 | |8 |8 |11 |8 | |8 | |8 | |12 |9 |15 |19 |8 | |8 | |8 | |14 |20 |12 |2 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch10 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |17 |14 |17 |15 |8 | |8 | |8 | |9 |17 |8 |2 |4 |2 | | | | | | | | | | | | | | | | | | | -Ch11 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |20 |10 |20 |18 |8 | |8 | |8 | |12 |8 |20 |3 |1 |4 | | | | | | | | | | | | | | | | | | | -Ch12 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |20 |16 |17 |9 |8 | |8 | |8 | |11 |20 |9 |0 |0 |1 | | | | | | | | | | | | | | | | | | | -Ch13 |8 | |8 | |8 | |8 | |8 | |8 |8 |8 |8 | |8 | |8 | |11 |16 |19 |16 |8 | |8 | |8 | |15 |12 |12 |2 |0 |2 | | | | | | | | | | | | | | | | | | | -Ch14 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |15 |17 |16 |14 |8 | |8 | |8 | |12 |14 |20 |4 |1 |5 | | | | | | | | | | | | | | | | | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 5G Channel |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |VHT80 | | | | | | | | | |VHT160 | | | | | | | | | |Txstream_Delta | | | | | -Band: 5G |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |VHT80_MCS0 |VHT80_MCS1 |VHT80_MCS2 |VHT80_MCS3 |VHT80_MCS4 |VHT80_MCS5 |VHT80_MCS6 |VHT80_MCS7 |VHT80_MCS8 |VHT80_MCS9 |VHT160_MCS0 |VHT160_MCS1 |VHT160_MCS2 |VHT160_MCS3 |VHT160_MCS4 |VHT160_MCS5 |VHT160_MCS6 |VHT160_MCS7 |VHT160_MCS8 |VHT160_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | -Ch184 |18 | |18 | |18 | |18 |18 |15 |18 | |12 | |13 | |11 |14 |16 |16 |12 | |12 | |13 | |20 |17 |16 |17 |18 | |9 | |16 | |17 |20 |18 |16 |19 | |15 | |9 | |17 |8 |17 |0 |4 |4 | | | -Ch188 |18 | |18 | |18 | |18 |18 |16 |20 | |9 | |9 | |11 |8 |12 |18 |15 | |11 | |11 | |14 |8 |17 |16 |16 | |16 | |12 | |8 |13 |19 |18 |11 | |9 | |12 | |14 |8 |13 |5 |2 |0 | | | -Ch192 |18 | |18 | |18 | |18 |18 |15 |9 | |11 | |9 | |15 |14 |11 |19 |15 | |8 | |18 | |20 |20 |8 |9 |9 | |9 | |11 | |18 |13 |14 |20 |18 | |10 | |14 | |12 |13 |16 |0 |2 |0 | | | -Ch196 |18 | |18 | |18 | |18 |18 |10 |11 | |19 | |13 | |12 |11 |10 |13 |11 | |19 | |10 | |16 |20 |15 |15 |8 | |14 | |8 | |18 |20 |15 |17 |17 | |14 | |12 | |12 |8 |16 |4 |3 |2 | | | -Ch8 |18 | |18 | |18 | |18 |18 |18 |13 | |19 | |20 | |18 |10 |9 |8 |8 | |17 | |15 | |17 |9 |18 |19 |11 | |12 | |15 | |20 |12 |12 |13 |9 | |9 | |15 | |10 |11 |17 |4 |3 |3 | | | -Ch12 |18 | |18 | |18 | |18 |18 |17 |20 | |14 | |10 | |10 |16 |15 |13 |11 | |15 | |16 | |17 |11 |15 |9 |18 | |8 | |20 | |19 |11 |9 |20 |8 | |18 | |8 | |8 |18 |18 |1 |3 |4 | | | -Ch16 |18 | |18 | |18 | |18 |18 |10 |18 | |18 | |8 | |19 |8 |12 |19 |16 | |19 | |18 | |16 |19 |12 |18 |18 | |9 | |10 | |18 |20 |20 |20 |9 | |11 | |20 | |17 |14 |16 |2 |2 |2 | | | -Ch36 |18 | |18 | |18 | |18 |18 |18 |19 | |8 | |11 | |16 |10 |9 |19 |11 | |19 | |9 | |8 |19 |8 |11 |17 | |20 | |14 | |9 |19 |19 |20 |13 | |12 | |19 | |13 |17 |9 |5 |1 |2 | | | -Ch40 |18 | |18 | |18 | |18 |18 |13 |20 | |13 | |19 | |16 |11 |14 |17 |17 | |14 | |8 | |13 |8 |10 |20 |10 | |9 | |14 | |11 |14 |17 |9 |20 | |15 | |19 | |9 |8 |11 |3 |1 |1 | | | -Ch44 |18 | |18 | |18 | |18 |18 |10 |14 | |19 | |20 | |17 |16 |12 |18 |8 | |17 | |18 | |15 |19 |14 |11 |13 | |14 | |12 | |16 |16 |19 |13 |14 | |19 | |14 | |20 |20 |11 |5 |1 |0 | | | -Ch48 |18 | |18 | |18 | |18 |18 |8 |12 | |12 | |19 | |11 |8 |11 |20 |12 | |12 | |11 | |15 |16 |10 |12 |16 | |11 | |15 | |18 |19 |17 |16 |17 | |11 | |8 | |10 |16 |16 |5 |5 |0 | | | -Ch52 |18 | |18 | |18 | |18 |18 |15 |12 | |15 | |20 | |9 |10 |10 |14 |8 | |20 | |10 | |16 |17 |18 |11 |16 | |17 | |10 | |17 |12 |13 |17 |17 | |13 | |18 | |18 |20 |13 |4 |3 |4 | | | -Ch56 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |20 |13 |14 |11 | |10 | |20 | |10 |8 |16 |12 |10 | |16 | |11 | |9 |11 |14 |17 |12 | |17 | |13 | |18 |10 |19 |0 |3 |3 | | | -Ch60 |18 | |18 | |18 | |18 |18 |14 |11 | |8 | |20 | |13 |16 |13 |11 |20 | |9 | |17 | |16 |11 |8 |12 |17 | |15 | |8 | |16 |10 |20 |19 |15 | |13 | |9 | |17 |18 |11 |4 |1 |2 | | | -Ch64 |18 | |18 | |18 | |18 |18 |13 |14 | |8 | |12 | |17 |8 |12 |18 |17 | |17 | |14 | |18 |8 |8 |20 |17 | |16 | |20 | |9 |15 |11 |10 |11 | |18 | |10 | |10 |15 |19 |2 |1 |4 | | | -Ch68 |18 | |18 | |18 | |18 |18 |14 |19 | |17 | |9 | |18 |19 |20 |12 |14 | |8 | |14 | |20 |20 |18 |9 |18 | |11 | |19 | |19 |10 |11 |8 |18 | |9 | |8 | |16 |11 |8 |3 |3 |1 | | | -Ch72 |18 | |18 | |18 | |18 |18 |19 |13 | |20 | |11 | |16 |9 |19 |20 |19 | |14 | |8 | |9 |17 |13 |19 |15 | |8 | |9 | |19 |14 |19 |15 |18 | |16 | |12 | |13 |15 |10 |4 |3 |1 | | | -Ch76 |18 | |18 | |18 | |18 |18 |17 |13 | |16 | |20 | |16 |8 |9 |20 |11 | |17 | |11 | |8 |18 |9 |20 |9 | |17 | |16 | |11 |11 |11 |18 |10 | |13 | |W | |20 |17 |8 |1 |3 |3 | | | -Ch80 |18 | |18 | |18 | |18 |18 |14 |20 | |13 | |13 | |17 |8 |10 |16 |8 | |9 | |19 | |16 |17 |17 |19 |15 | |9 | |13 | |16 |13 |14 |12 |9 | |20 | |20 | |14 |18 |18 |0 |4 |2 | | | -Ch84 |18 | |18 | |18 | |18 |18 |11 |18 | |20 | |9 | |13 |14 |11 |16 |15 | |12 | |11 | |9 |19 |13 |11 |11 | |9 | |15 | |16 |18 |13 |12 |8 | |8 | |8 | |10 |12 |15 |3 |2 |5 | | | -Ch88 |18 | |18 | |18 | |18 |18 |18 |19 | |9 | |17 | |15 |8 |19 |11 |11 | |14 | |9 | |14 |20 |20 |11 |11 | |15 | |12 | |14 |11 |8 |18 |15 | |19 | |18 | |12 |20 |16 |5 |5 |1 | | | -Ch92 |18 | |18 | |18 | |18 |18 |11 |8 | |15 | |13 | |13 |13 |13 |16 |14 | |14 | |9 | |9 |15 |20 |11 |17 | |10 | |14 | |13 |17 |11 |8 |18 | |20 | |8 | |10 |19 |18 |1 |4 |4 | | | -Ch96 |18 | |18 | |18 | |18 |18 |8 |12 | |16 | |9 | |13 |12 |9 |8 |11 | |8 | |8 | |19 |11 |15 |16 |8 | |11 | |16 | |18 |16 |9 |19 |9 | |10 | |15 | |19 |19 |15 |4 |2 |4 | | | -Ch100 |18 | |18 | |18 | |18 |18 |18 |13 | |20 | |20 | |12 |9 |19 |10 |9 | |14 | |8 | |19 |10 |17 |9 |10 | |10 | |8 | |13 |12 |11 |20 |11 | |16 | |18 | |14 |16 |19 |1 |1 |2 | | | -Ch104 |18 | |18 | |18 | |18 |18 |19 |12 | |20 | |14 | |16 |15 |9 |19 |11 | |15 | |11 | |12 |18 |15 |11 |15 | |19 | |10 | |14 |15 |19 |9 |13 | |19 | |13 | |11 |11 |17 |2 |2 |0 | | | -Ch108 |18 | |18 | |18 | |18 |18 |18 |15 | |13 | |16 | |11 |19 |19 |18 |19 | |12 | |17 | |8 |9 |10 |8 |8 | |18 | |8 | |10 |11 |17 |15 |10 | |19 | |13 | |16 |10 |15 |0 |2 |3 | | | -Ch112 |18 | |18 | |18 | |18 |18 |8 |13 | |9 | |17 | |9 |15 |17 |10 |19 | |9 | |19 | |11 |16 |14 |16 |8 | |18 | |13 | |16 |13 |17 |19 |11 | |8 | |8 | |18 |14 |17 |5 |2 |5 | | | -Ch116 |18 | |18 | |18 | |18 |18 |8 |20 | |11 | |15 | |8 |11 |8 |18 |15 | |13 | |17 | |14 |13 |9 |8 |14 | |14 | |11 | |9 |19 |17 |11 |11 | |8 | |20 | |8 |10 |20 |5 |2 |1 | | | -Ch120 |18 | |18 | |18 | |18 |18 |14 |20 | |8 | |20 | |14 |10 |10 |17 |12 | |16 | |20 | |10 |20 |17 |18 |9 | |15 | |14 | |17 |13 |14 |16 |8 | |18 | |10 | |15 |12 |12 |1 |5 |3 | | | -Ch124 |18 | |18 | |18 | |18 |18 |20 |9 | |17 | |12 | |12 |8 |14 |8 |8 | |20 | |17 | |16 |20 |13 |14 |16 | |10 | |14 | |20 |15 |17 |8 |10 | |13 | |13 | |11 |13 |9 |5 |0 |5 | | | -Ch128 |18 | |18 | |18 | |18 |18 |9 |19 | |9 | |14 | |8 |14 |11 |9 |14 | |16 | |15 | |14 |10 |15 |14 |14 | |20 | |10 | |16 |15 |11 |12 |13 | |13 | |13 | |12 |15 |20 |1 |4 |3 | | | -Ch132 |18 | |18 | |18 | |18 |18 |20 |16 | |13 | |8 | |18 |11 |20 |12 |11 | |11 | |14 | |12 |13 |8 |12 |13 | |10 | |20 | |19 |12 |13 |14 |12 | |11 | |19 | |19 |20 |8 |3 |1 |4 | | | -Ch136 |18 | |18 | |18 | |18 |18 |12 |12 | |19 | |10 | |20 |10 |8 |17 |8 | |12 | |10 | |10 |13 |13 |12 |8 | |11 | |18 | |14 |12 |17 |8 |14 | |14 | |9 | |11 |18 |14 |1 |2 |2 | | | -Ch140 |18 | |18 | |18 | |18 |18 |12 |10 | |13 | |9 | |16 |8 |20 |10 |17 | |8 | |15 | |13 |20 |15 |10 |18 | |13 | |12 | |12 |16 |18 |12 |17 | |10 | |16 | |11 |15 |14 |3 |2 |5 | | | -Ch144 |18 | |18 | |18 | |18 |18 |19 |9 | |15 | |8 | |13 |18 |17 |9 |19 | |16 | |11 | |20 |12 |15 |19 |10 | |17 | |15 | |17 |14 |9 |9 |13 | |17 | |16 | |10 |9 |10 |1 |5 |2 | | | -Ch149 |18 | |18 | |18 | |18 |18 |15 |20 | |12 | |19 | |19 |19 |10 |10 |13 | |15 | |19 | |12 |19 |10 |14 |15 | |10 | |15 | |9 |8 |11 |15 |13 | |10 | |16 | |15 |18 |12 |5 |5 |2 | | | -Ch153 |18 | |18 | |18 | |18 |18 |20 |17 | |8 | |19 | |16 |20 |13 |16 |18 | |14 | |11 | |10 |16 |16 |19 |15 | |13 | |17 | |19 |18 |19 |20 |8 | |18 | |9 | |17 |11 |11 |1 |2 |1 | | | -Ch157 |18 | |18 | |18 | |18 |18 |13 |17 | |12 | |19 | |16 |8 |17 |11 |12 | |15 | |14 | |18 |11 |12 |9 |18 | |20 | |13 | |16 |13 |20 |17 |19 | |10 | |12 | |20 |18 |16 |5 |2 |3 | | | -Ch161 |18 | |18 | |18 | |18 |18 |12 |12 | |16 | |12 | |15 |11 |18 |11 |13 | |17 | |19 | |11 |13 |13 |9 |15 | |10 | |10 | |19 |13 |20 |13 |9 | |8 | |8 | |20 |14 |12 |0 |4 |1 | | | -Ch165 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |8 |19 |15 |10 | |17 | |13 | |13 |19 |20 |8 |18 | |15 | |20 | |16 |9 |14 |11 |20 | |11 | |19 | |15 |16 |8 |1 |2 |0 | | | -Ch169 |18 | |18 | |18 | |18 |18 |8 |17 | |17 | |13 | |16 |8 |14 |18 |11 | |8 | |18 | |20 |14 |8 |17 |8 | |13 | |18 | |19 |20 |19 |20 |17 | |13 | |20 | |9 |15 |18 |0 |3 |4 | | | -Ch173 |18 | |18 | |18 | |18 |18 |14 |9 | |13 | |12 | |15 |14 |15 |10 |10 | |18 | |16 | |16 |8 |13 |16 |11 | |11 | |13 | |13 |15 |12 |20 |15 | |14 | |13 | |16 |11 |14 |3 |3 |4 | | | -Ch177 |18 | |18 | |18 | |18 |18 |19 |18 | |16 | |10 | |20 |13 |11 |16 |12 | |16 | |18 | |18 |11 |18 |8 |13 | |14 | |11 | |18 |14 |16 |16 |19 | |16 | |13 | |15 |8 |13 |5 |0 |0 | | | -Ch181 |18 | |18 | |18 | |18 |18 |20 |11 | |10 | |9 | |8 |9 |15 |15 |8 | |8 | |12 | |11 |9 |18 |20 |11 | |17 | |11 | |8 |15 |8 |18 |12 | |18 | |16 | |19 |9 |14 |4 |1 |4 | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/SingleSKU_BF.dat b/package/lean/mt/drivers/mt_wifi/dbdc/SingleSKU_BF.dat deleted file mode 100644 index be9c0d353..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/SingleSKU_BF.dat +++ /dev/null @@ -1,65 +0,0 @@ -# Single SKU Max Power Table | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 2.4G Channel |CCK | | | |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |Txstream_Delta | | | | | | | | | | | | | | | | | | | | | -Band: 2.4G |CCK_1M |CCK_2M |CCK_5.5M |CCK_11M |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | | | | | | | | | | | | | | | | | -Ch1 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |20 |12 |18 |16 |8 | |8 | |8 | |9 |11 |12 |2 |1 |3 | | | | | | | | | | | | | | | | | | | -Ch2 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |19 |19 |10 |12 |8 | |8 | |8 | |9 |16 |12 |5 |4 |0 | | | | | | | | | | | | | | | | | | | -Ch3 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |17 |18 |16 |20 |8 | |8 | |8 | |12 |8 |20 |0 |2 |0 | | | | | | | | | | | | | | | | | | | -Ch4 |8 | |8 | |8 | |8 | |8 | |8 |8 |9 |8 | |8 | |8 | |14 |10 |14 |18 |8 | |8 | |8 | |14 |12 |10 |3 |4 |5 | | | | | | | | | | | | | | | | | | | -Ch5 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |10 |13 |11 |8 |8 | |8 | |8 | |12 |8 |9 |4 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch6 |8 | |8 | |8 | |8 | |8 | |8 |8 |13 |8 | |8 | |8 | |11 |9 |12 |16 |8 | |8 | |8 | |9 |17 |11 |5 |2 |1 | | | | | | | | | | | | | | | | | | | -Ch7 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |14 |11 |13 |18 |8 | |8 | |8 | |16 |13 |10 |2 |5 |4 | | | | | | | | | | | | | | | | | | | -Ch8 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |14 |9 |11 |10 |8 | |8 | |8 | |11 |14 |8 |5 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch9 |8 | |8 | |8 | |8 | |8 | |8 |8 |11 |8 | |8 | |8 | |12 |9 |15 |19 |8 | |8 | |8 | |14 |20 |12 |2 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch10 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |17 |14 |17 |15 |8 | |8 | |8 | |9 |17 |8 |2 |4 |2 | | | | | | | | | | | | | | | | | | | -Ch11 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |20 |10 |20 |18 |8 | |8 | |8 | |12 |8 |20 |3 |1 |4 | | | | | | | | | | | | | | | | | | | -Ch12 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |20 |16 |17 |9 |8 | |8 | |8 | |11 |20 |9 |0 |0 |1 | | | | | | | | | | | | | | | | | | | -Ch13 |8 | |8 | |8 | |8 | |8 | |8 |8 |8 |8 | |8 | |8 | |11 |16 |19 |16 |8 | |8 | |8 | |15 |12 |12 |2 |0 |2 | | | | | | | | | | | | | | | | | | | -Ch14 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |15 |17 |16 |14 |8 | |8 | |8 | |12 |14 |20 |4 |1 |5 | | | | | | | | | | | | | | | | | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 5G Channel |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |VHT80 | | | | | | | | | |VHT160 | | | | | | | | | |Txstream_Delta | | | | | -Band: 5G |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |VHT80_MCS0 |VHT80_MCS1 |VHT80_MCS2 |VHT80_MCS3 |VHT80_MCS4 |VHT80_MCS5 |VHT80_MCS6 |VHT80_MCS7 |VHT80_MCS8 |VHT80_MCS9 |VHT160_MCS0 |VHT160_MCS1 |VHT160_MCS2 |VHT160_MCS3 |VHT160_MCS4 |VHT160_MCS5 |VHT160_MCS6 |VHT160_MCS7 |VHT160_MCS8 |VHT160_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | -Ch184 |18 | |18 | |18 | |18 |18 |15 |18 | |12 | |13 | |11 |14 |16 |16 |12 | |12 | |13 | |20 |17 |16 |17 |18 | |9 | |16 | |17 |20 |18 |16 |19 | |15 | |9 | |17 |8 |17 |0 |4 |4 | | | -Ch188 |18 | |18 | |18 | |18 |18 |16 |20 | |9 | |9 | |11 |8 |12 |18 |15 | |11 | |11 | |14 |8 |17 |16 |16 | |16 | |12 | |8 |13 |19 |18 |11 | |9 | |12 | |14 |8 |13 |5 |2 |0 | | | -Ch192 |18 | |18 | |18 | |18 |18 |15 |9 | |11 | |9 | |15 |14 |11 |19 |15 | |8 | |18 | |20 |20 |8 |9 |9 | |9 | |11 | |18 |13 |14 |20 |18 | |10 | |14 | |12 |13 |16 |0 |2 |0 | | | -Ch196 |18 | |18 | |18 | |18 |18 |10 |11 | |19 | |13 | |12 |11 |10 |13 |11 | |19 | |10 | |16 |20 |15 |15 |8 | |14 | |8 | |18 |20 |15 |17 |17 | |14 | |12 | |12 |8 |16 |4 |3 |2 | | | -Ch8 |18 | |18 | |18 | |18 |18 |18 |13 | |19 | |20 | |18 |10 |9 |8 |8 | |17 | |15 | |17 |9 |18 |19 |11 | |12 | |15 | |20 |12 |12 |13 |9 | |9 | |15 | |10 |11 |17 |4 |3 |3 | | | -Ch12 |18 | |18 | |18 | |18 |18 |17 |20 | |14 | |10 | |10 |16 |15 |13 |11 | |15 | |16 | |17 |11 |15 |9 |18 | |8 | |20 | |19 |11 |9 |20 |8 | |18 | |8 | |8 |18 |18 |1 |3 |4 | | | -Ch16 |18 | |18 | |18 | |18 |18 |10 |18 | |18 | |8 | |19 |8 |12 |19 |16 | |19 | |18 | |16 |19 |12 |18 |18 | |9 | |10 | |18 |20 |20 |20 |9 | |11 | |20 | |17 |14 |16 |2 |2 |2 | | | -Ch36 |18 | |18 | |18 | |18 |18 |18 |19 | |8 | |11 | |16 |10 |9 |19 |11 | |19 | |9 | |8 |19 |8 |11 |17 | |20 | |14 | |9 |19 |19 |20 |13 | |12 | |19 | |13 |17 |9 |5 |1 |2 | | | -Ch40 |18 | |18 | |18 | |18 |18 |13 |20 | |13 | |19 | |16 |11 |14 |17 |17 | |14 | |8 | |13 |8 |10 |20 |10 | |9 | |14 | |11 |14 |17 |9 |20 | |15 | |19 | |9 |8 |11 |3 |1 |1 | | | -Ch44 |18 | |18 | |18 | |18 |18 |10 |14 | |19 | |20 | |17 |16 |12 |18 |8 | |17 | |18 | |15 |19 |14 |11 |13 | |14 | |12 | |16 |16 |19 |13 |14 | |19 | |14 | |20 |20 |11 |5 |1 |0 | | | -Ch48 |18 | |18 | |18 | |18 |18 |8 |12 | |12 | |19 | |11 |8 |11 |20 |12 | |12 | |11 | |15 |16 |10 |12 |16 | |11 | |15 | |18 |19 |17 |16 |17 | |11 | |8 | |10 |16 |16 |5 |5 |0 | | | -Ch52 |18 | |18 | |18 | |18 |18 |15 |12 | |15 | |20 | |9 |10 |10 |14 |8 | |20 | |10 | |16 |17 |18 |11 |16 | |17 | |10 | |17 |12 |13 |17 |17 | |13 | |18 | |18 |20 |13 |4 |3 |4 | | | -Ch56 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |20 |13 |14 |11 | |10 | |20 | |10 |8 |16 |12 |10 | |16 | |11 | |9 |11 |14 |17 |12 | |17 | |13 | |18 |10 |19 |0 |3 |3 | | | -Ch60 |18 | |18 | |18 | |18 |18 |14 |11 | |8 | |20 | |13 |16 |13 |11 |20 | |9 | |17 | |16 |11 |8 |12 |17 | |15 | |8 | |16 |10 |20 |19 |15 | |13 | |9 | |17 |18 |11 |4 |1 |2 | | | -Ch64 |18 | |18 | |18 | |18 |18 |13 |14 | |8 | |12 | |17 |8 |12 |18 |17 | |17 | |14 | |18 |8 |8 |20 |17 | |16 | |20 | |9 |15 |11 |10 |11 | |18 | |10 | |10 |15 |19 |2 |1 |4 | | | -Ch68 |18 | |18 | |18 | |18 |18 |14 |19 | |17 | |9 | |18 |19 |20 |12 |14 | |8 | |14 | |20 |20 |18 |9 |18 | |11 | |19 | |19 |10 |11 |8 |18 | |9 | |8 | |16 |11 |8 |3 |3 |1 | | | -Ch72 |18 | |18 | |18 | |18 |18 |19 |13 | |20 | |11 | |16 |9 |19 |20 |19 | |14 | |8 | |9 |17 |13 |19 |15 | |8 | |9 | |19 |14 |19 |15 |18 | |16 | |12 | |13 |15 |10 |4 |3 |1 | | | -Ch76 |18 | |18 | |18 | |18 |18 |17 |13 | |16 | |20 | |16 |8 |9 |20 |11 | |17 | |11 | |8 |18 |9 |20 |9 | |17 | |16 | |11 |11 |11 |18 |10 | |13 | |W | |20 |17 |8 |1 |3 |3 | | | -Ch80 |18 | |18 | |18 | |18 |18 |14 |20 | |13 | |13 | |17 |8 |10 |16 |8 | |9 | |19 | |16 |17 |17 |19 |15 | |9 | |13 | |16 |13 |14 |12 |9 | |20 | |20 | |14 |18 |18 |0 |4 |2 | | | -Ch84 |18 | |18 | |18 | |18 |18 |11 |18 | |20 | |9 | |13 |14 |11 |16 |15 | |12 | |11 | |9 |19 |13 |11 |11 | |9 | |15 | |16 |18 |13 |12 |8 | |8 | |8 | |10 |12 |15 |3 |2 |5 | | | -Ch88 |18 | |18 | |18 | |18 |18 |18 |19 | |9 | |17 | |15 |8 |19 |11 |11 | |14 | |9 | |14 |20 |20 |11 |11 | |15 | |12 | |14 |11 |8 |18 |15 | |19 | |18 | |12 |20 |16 |5 |5 |1 | | | -Ch92 |18 | |18 | |18 | |18 |18 |11 |8 | |15 | |13 | |13 |13 |13 |16 |14 | |14 | |9 | |9 |15 |20 |11 |17 | |10 | |14 | |13 |17 |11 |8 |18 | |20 | |8 | |10 |19 |18 |1 |4 |4 | | | -Ch96 |18 | |18 | |18 | |18 |18 |8 |12 | |16 | |9 | |13 |12 |9 |8 |11 | |8 | |8 | |19 |11 |15 |16 |8 | |11 | |16 | |18 |16 |9 |19 |9 | |10 | |15 | |19 |19 |15 |4 |2 |4 | | | -Ch100 |18 | |18 | |18 | |18 |18 |18 |13 | |20 | |20 | |12 |9 |19 |10 |9 | |14 | |8 | |19 |10 |17 |9 |10 | |10 | |8 | |13 |12 |11 |20 |11 | |16 | |18 | |14 |16 |19 |1 |1 |2 | | | -Ch104 |18 | |18 | |18 | |18 |18 |19 |12 | |20 | |14 | |16 |15 |9 |19 |11 | |15 | |11 | |12 |18 |15 |11 |15 | |19 | |10 | |14 |15 |19 |9 |13 | |19 | |13 | |11 |11 |17 |2 |2 |0 | | | -Ch108 |18 | |18 | |18 | |18 |18 |18 |15 | |13 | |16 | |11 |19 |19 |18 |19 | |12 | |17 | |8 |9 |10 |8 |8 | |18 | |8 | |10 |11 |17 |15 |10 | |19 | |13 | |16 |10 |15 |0 |2 |3 | | | -Ch112 |18 | |18 | |18 | |18 |18 |8 |13 | |9 | |17 | |9 |15 |17 |10 |19 | |9 | |19 | |11 |16 |14 |16 |8 | |18 | |13 | |16 |13 |17 |19 |11 | |8 | |8 | |18 |14 |17 |5 |2 |5 | | | -Ch116 |18 | |18 | |18 | |18 |18 |8 |20 | |11 | |15 | |8 |11 |8 |18 |15 | |13 | |17 | |14 |13 |9 |8 |14 | |14 | |11 | |9 |19 |17 |11 |11 | |8 | |20 | |8 |10 |20 |5 |2 |1 | | | -Ch120 |18 | |18 | |18 | |18 |18 |14 |20 | |8 | |20 | |14 |10 |10 |17 |12 | |16 | |20 | |10 |20 |17 |18 |9 | |15 | |14 | |17 |13 |14 |16 |8 | |18 | |10 | |15 |12 |12 |1 |5 |3 | | | -Ch124 |18 | |18 | |18 | |18 |18 |20 |9 | |17 | |12 | |12 |8 |14 |8 |8 | |20 | |17 | |16 |20 |13 |14 |16 | |10 | |14 | |20 |15 |17 |8 |10 | |13 | |13 | |11 |13 |9 |5 |0 |5 | | | -Ch128 |18 | |18 | |18 | |18 |18 |9 |19 | |9 | |14 | |8 |14 |11 |9 |14 | |16 | |15 | |14 |10 |15 |14 |14 | |20 | |10 | |16 |15 |11 |12 |13 | |13 | |13 | |12 |15 |20 |1 |4 |3 | | | -Ch132 |18 | |18 | |18 | |18 |18 |20 |16 | |13 | |8 | |18 |11 |20 |12 |11 | |11 | |14 | |12 |13 |8 |12 |13 | |10 | |20 | |19 |12 |13 |14 |12 | |11 | |19 | |19 |20 |8 |3 |1 |4 | | | -Ch136 |18 | |18 | |18 | |18 |18 |12 |12 | |19 | |10 | |20 |10 |8 |17 |8 | |12 | |10 | |10 |13 |13 |12 |8 | |11 | |18 | |14 |12 |17 |8 |14 | |14 | |9 | |11 |18 |14 |1 |2 |2 | | | -Ch140 |18 | |18 | |18 | |18 |18 |12 |10 | |13 | |9 | |16 |8 |20 |10 |17 | |8 | |15 | |13 |20 |15 |10 |18 | |13 | |12 | |12 |16 |18 |12 |17 | |10 | |16 | |11 |15 |14 |3 |2 |5 | | | -Ch144 |18 | |18 | |18 | |18 |18 |19 |9 | |15 | |8 | |13 |18 |17 |9 |19 | |16 | |11 | |20 |12 |15 |19 |10 | |17 | |15 | |17 |14 |9 |9 |13 | |17 | |16 | |10 |9 |10 |1 |5 |2 | | | -Ch149 |18 | |18 | |18 | |18 |18 |15 |20 | |12 | |19 | |19 |19 |10 |10 |13 | |15 | |19 | |12 |19 |10 |14 |15 | |10 | |15 | |9 |8 |11 |15 |13 | |10 | |16 | |15 |18 |12 |5 |5 |2 | | | -Ch153 |18 | |18 | |18 | |18 |18 |20 |17 | |8 | |19 | |16 |20 |13 |16 |18 | |14 | |11 | |10 |16 |16 |19 |15 | |13 | |17 | |19 |18 |19 |20 |8 | |18 | |9 | |17 |11 |11 |1 |2 |1 | | | -Ch157 |18 | |18 | |18 | |18 |18 |13 |17 | |12 | |19 | |16 |8 |17 |11 |12 | |15 | |14 | |18 |11 |12 |9 |18 | |20 | |13 | |16 |13 |20 |17 |19 | |10 | |12 | |20 |18 |16 |5 |2 |3 | | | -Ch161 |18 | |18 | |18 | |18 |18 |12 |12 | |16 | |12 | |15 |11 |18 |11 |13 | |17 | |19 | |11 |13 |13 |9 |15 | |10 | |10 | |19 |13 |20 |13 |9 | |8 | |8 | |20 |14 |12 |0 |4 |1 | | | -Ch165 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |8 |19 |15 |10 | |17 | |13 | |13 |19 |20 |8 |18 | |15 | |20 | |16 |9 |14 |11 |20 | |11 | |19 | |15 |16 |8 |1 |2 |0 | | | -Ch169 |18 | |18 | |18 | |18 |18 |8 |17 | |17 | |13 | |16 |8 |14 |18 |11 | |8 | |18 | |20 |14 |8 |17 |8 | |13 | |18 | |19 |20 |19 |20 |17 | |13 | |20 | |9 |15 |18 |0 |3 |4 | | | -Ch173 |18 | |18 | |18 | |18 |18 |14 |9 | |13 | |12 | |15 |14 |15 |10 |10 | |18 | |16 | |16 |8 |13 |16 |11 | |11 | |13 | |13 |15 |12 |20 |15 | |14 | |13 | |16 |11 |14 |3 |3 |4 | | | -Ch177 |18 | |18 | |18 | |18 |18 |19 |18 | |16 | |10 | |20 |13 |11 |16 |12 | |16 | |18 | |18 |11 |18 |8 |13 | |14 | |11 | |18 |14 |16 |16 |19 | |16 | |13 | |15 |8 |13 |5 |0 |0 | | | -Ch181 |18 | |18 | |18 | |18 |18 |20 |11 | |10 | |9 | |8 |9 |15 |15 |8 | |8 | |12 | |11 |9 |18 |20 |11 | |17 | |11 | |8 |15 |8 |18 |12 | |18 | |16 | |19 |9 |14 |4 |1 |4 | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/firmware.sh b/package/lean/mt/drivers/mt_wifi/dbdc/firmware.sh deleted file mode 100644 index abdade9c7..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/firmware.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh /etc/rc.common -chmod 777 /sbin/mtkwifi -START=15 -STOP=15 - -USE_PROCD=1 - -start_service() { - [ -f /etc/hotplug.d/firmware/11-mtk-wifi-e2p ] && sh /etc/hotplug.d/firmware/11-mtk-wifi-e2p -} - -stop_service() { - echo 'do nothing' > /dev/null -} - - diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615.lua b/package/lean/mt/drivers/mt_wifi/dbdc/mt7615.lua deleted file mode 100644 index 8612a5d0d..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615.lua +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/lua --- Alternative for OpenWrt's /sbin/wifi. --- Copyright Not Reserved. --- Hua Shao - -package.path = '/lib/wifi/?.lua;'..package.path - -local vif_prefix = {"ra", "rai", "rae", "rax", "ray", "raz", - "apcli", "apclix", "apclii", "apcliy", "apclie", "apcliz", } - -local function esc(x) - return (x:gsub('%%', '%%%%') - :gsub('^%^', '%%^') - :gsub('%$$', '%%$') - :gsub('%(', '%%(') - :gsub('%)', '%%)') - :gsub('%.', '%%.') - :gsub('%[', '%%[') - :gsub('%]', '%%]') - :gsub('%*', '%%*') - :gsub('%+', '%%+') - :gsub('%-', '%%-') - :gsub('%?', '%%?')) -end - -function add_vif_into_lan(vif) - local mtkwifi = require("mtkwifi") - local brvifs = mtkwifi.__trim( - mtkwifi.read_pipe("uci get network.lan.ifname")) - if not string.match(brvifs, esc(vif)) then - nixio.syslog("debug", "mt7615_up: add "..vif.." into lan") - brvifs = brvifs.." "..vif - os.execute("uci set network.lan.ifname=\""..brvifs.."\"") - os.execute("uci commit") - -- os.execute("brctl addif br-lan "..vif) - os.execute("ubus call network.interface.lan add_device \"{\\\"name\\\":\\\""..vif.."\\\"}\"") - end -end - -function mt7615_up(devname) - local nixio = require("nixio") - local mtkwifi = require("mtkwifi") - - nixio.syslog("debug", "mt7615_up called!") - - local devs, l1parser = mtkwifi.__get_l1dat() - -- l1 profile present, good! - if l1parser and devs then - dev = devs.devname_ridx[devname] - if not dev then - nixio.syslog("err", "mt7615_up: dev "..devname.." not found!") - return - end - -- we have to bring up main_ifname first, main_ifname will create all other vifs. - if mtkwifi.exists("/sys/class/net/"..dev.main_ifname) then - nixio.syslog("debug", "mt7615_up: ifconfig "..dev.main_ifname.." up") - os.execute("ifconfig "..dev.main_ifname.." up") - add_vif_into_lan(dev.main_ifname) - else - nixio.syslog("err", "mt7615_up: main_ifname "..dev.main_ifname.." missing, quit!") - return - end - for _,vif in ipairs(string.split(mtkwifi.read_pipe("ls /sys/class/net"), "\n")) - do - if vif ~= dev.main_ifname and - ( string.match(vif, esc(dev.ext_ifname).."[0-9]+") - or string.match(vif, esc(dev.apcli_ifname).."[0-9]+") - or string.match(vif, esc(dev.wds_ifname).."[0-9]+") - or string.match(vif, esc(dev.mesh_ifname).."[0-9]+")) - then - nixio.syslog("debug", "mt7615_up: ifconfig "..vif.."0 up") - os.execute("ifconfig "..vif.." up") - add_vif_into_lan(vif) - -- else nixio.syslog("debug", "mt7615_up: skip "..vif..", prefix not match "..pre) - end - end - elseif mtkwifi.exists("/etc/wireless/mt7615/"..devname..".dat") then - for _, pre in ipairs(vif_prefix) do - -- we have to bring up root vif first, root vif will create all other vifs. - if mtkwifi.exists("/sys/class/net/"..pre.."0") then - nixio.syslog("debug", "mt7615_up: ifconfig "..pre.."0 up") - os.execute("ifconfig "..pre.."0 up") - add_vif_into_lan(pre.."0") - end - - for _,vif in ipairs(string.split(mtkwifi.read_pipe("ls /sys/class/net"), "\n")) - do - -- nixio.syslog("debug", "mt7615_up: navigate "..pre) - if string.match(vif, pre.."[1-9]+") then - nixio.syslog("debug", "mt7615_up: ifconfig "..vif.." up") - os.execute("ifconfig "..vif.." up") - add_vif_into_lan(vif) - -- else nixio.syslog("debug", "mt7615_up: skip "..vif..", prefix not match "..pre) - end - end - end - else nixio.syslog("debug", "mt7615_up: skip "..devname..", config not exist") - end - - os.execute(" rm -rf /tmp/mtk/wifi/mt7615*.need_reload") -end - -function mt7615_down(devname) - local nixio = require("nixio") - local mtkwifi = require("mtkwifi") - nixio.syslog("debug", "mt7615_down called!") - - local devs, l1parser = mtkwifi.__get_l1dat() - -- l1 profile present, good! - if l1parser and devs then - dev = devs.devname_ridx[devname] - if not dev then - nixio.syslog("err", "mt7615_down: dev "..devname.." not found!") - return - end - - for _,vif in ipairs(string.split(mtkwifi.read_pipe("ls /sys/class/net"), "\n")) - do - if vif == dev.main_ifname - or string.match(vif, esc(dev.ext_ifname).."[0-9]+") - or string.match(vif, esc(dev.apcli_ifname).."[0-9]+") - or string.match(vif, esc(dev.wds_ifname).."[0-9]+") - or string.match(vif, esc(dev.mesh_ifname).."[0-9]+") - then - nixio.syslog("debug", "mt7615_down: ifconfig "..vif.." down") - os.execute("ifconfig "..vif.." down") - local brvifs = mtkwifi.__trim(mtkwifi.read_pipe("uci get network.lan.ifname")) - if string.match(brvifs, esc(vif)) then - brvifs = mtkwifi.__trim(string.gsub(brvifs, esc(vif), "")) - nixio.syslog("debug", "mt7615_down: remove "..vif.." from lan") - os.execute("uci set network.lan.ifname=\""..brvifs.."\"") - os.execute("uci commit") - os.execute("ubus call network.interface.lan remove_device \"{\\\"name\\\":\\\""..vif.."\\\"}\"") - end - -- else nixio.syslog("debug", "mt7615_down: skip "..vif..", prefix not match "..pre) - end - end - elseif mtkwifi.exists("/etc/wireless/mt7615/"..devname..".dat") then - for _, pre in ipairs(vif_prefix) do - for _,vif in ipairs(string.split(mtkwifi.read_pipe("ls /sys/class/net"), "\n")) - do - if string.match(vif, pre.."[0-9]+") then - nixio.syslog("debug", "mt7615_down: ifconfig "..vif.."down") - os.execute("ifconfig "..vif.." down") - local brvifs = mtkwifi.read_pipe("uci get network.lan.ifname") - if string.match(brvifs, vif) then - brvifs = mtkwifi.__trim(string.gsub(brvifs, vif, "")) - nixio.syslog("debug", "mt7615_down: remove "..vif.." from lan") - os.execute("uci set network.lan.ifname=\""..brvifs.."\"") - os.execute("uci commit") - os.execute("ubus call network.interface.lan remove_device \"{\\\"name\\\":\\\""..vif.."\\\"}\"") - end - -- else nixio.syslog("debug", "mt7615_down: skip "..vif..", prefix not match "..pre) - end - end - end - else nixio.syslog("debug", "mt7615_down: skip "..devname..", config not exist") - end - - os.execute(" rm -rf /tmp/mtk/wifi/mt7615*.need_reload") -end - -function mt7615_reload(devname) - local nixio = require("nixio") - nixio.syslog("debug", "mt7615_reload called!") - mt7615_down(devname) - mt7615_up(devname) -end - -function mt7615_restart(devname) - local nixio = require("nixio") - nixio.syslog("debug", "mt7615_restart called!") - mt7615_down(devname) - os.execute("rmmod mt7615") - os.execute("modprobe mt7615") - mt7615_up(devname) -end - -function mt7615_reset(devname) - local nixio = require("nixio") - local mtkwifi = require("mtkwifi") - nixio.syslog("debug", "mt7615_reset called!") - if mtkwifi.exists("/rom/etc/wireless/mt7615/") then - os.execute("rm -rf /etc/wireless/mt7615/") - os.execute("cp -rf /rom/etc/wireless/mt7615/ /etc/wireless/") - mt7615_reload(devname) - else - nixio.syslog("debug", "mt7615_reset: /rom"..profile.." missing, unable to reset!") - end -end - -function mt7615_status(devname) - return wifi_common_status() -end - -function mt7615_detect(devname) - local nixio = require("nixio") - local mtkwifi = require("mtkwifi") - nixio.syslog("debug", "mt7615_detect called!") - - for _,dev in ipairs(mtkwifi.get_all_devs()) do - local relname = string.format("%s%d%d",dev.maindev,dev.mainidx,dev.subidx) - print([[ -config wifi-device ]]..relname.."\n"..[[ - option type mt7615 - option vendor ralink -]]) - for _,vif in ipairs(dev.vifs) do - print([[ -config wifi-iface - option device ]]..relname.."\n"..[[ - option ifname ]]..vif.vifname.."\n"..[[ - option network lan - option mode ap - option ssid ]]..vif.__ssid.."\n") - end - end -end - diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e-sku-bf.dat b/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e-sku-bf.dat deleted file mode 100644 index be9c0d353..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e-sku-bf.dat +++ /dev/null @@ -1,65 +0,0 @@ -# Single SKU Max Power Table | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 2.4G Channel |CCK | | | |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |Txstream_Delta | | | | | | | | | | | | | | | | | | | | | -Band: 2.4G |CCK_1M |CCK_2M |CCK_5.5M |CCK_11M |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | | | | | | | | | | | | | | | | | -Ch1 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |20 |12 |18 |16 |8 | |8 | |8 | |9 |11 |12 |2 |1 |3 | | | | | | | | | | | | | | | | | | | -Ch2 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |19 |19 |10 |12 |8 | |8 | |8 | |9 |16 |12 |5 |4 |0 | | | | | | | | | | | | | | | | | | | -Ch3 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |17 |18 |16 |20 |8 | |8 | |8 | |12 |8 |20 |0 |2 |0 | | | | | | | | | | | | | | | | | | | -Ch4 |8 | |8 | |8 | |8 | |8 | |8 |8 |9 |8 | |8 | |8 | |14 |10 |14 |18 |8 | |8 | |8 | |14 |12 |10 |3 |4 |5 | | | | | | | | | | | | | | | | | | | -Ch5 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |10 |13 |11 |8 |8 | |8 | |8 | |12 |8 |9 |4 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch6 |8 | |8 | |8 | |8 | |8 | |8 |8 |13 |8 | |8 | |8 | |11 |9 |12 |16 |8 | |8 | |8 | |9 |17 |11 |5 |2 |1 | | | | | | | | | | | | | | | | | | | -Ch7 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |14 |11 |13 |18 |8 | |8 | |8 | |16 |13 |10 |2 |5 |4 | | | | | | | | | | | | | | | | | | | -Ch8 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |14 |9 |11 |10 |8 | |8 | |8 | |11 |14 |8 |5 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch9 |8 | |8 | |8 | |8 | |8 | |8 |8 |11 |8 | |8 | |8 | |12 |9 |15 |19 |8 | |8 | |8 | |14 |20 |12 |2 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch10 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |17 |14 |17 |15 |8 | |8 | |8 | |9 |17 |8 |2 |4 |2 | | | | | | | | | | | | | | | | | | | -Ch11 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |20 |10 |20 |18 |8 | |8 | |8 | |12 |8 |20 |3 |1 |4 | | | | | | | | | | | | | | | | | | | -Ch12 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |20 |16 |17 |9 |8 | |8 | |8 | |11 |20 |9 |0 |0 |1 | | | | | | | | | | | | | | | | | | | -Ch13 |8 | |8 | |8 | |8 | |8 | |8 |8 |8 |8 | |8 | |8 | |11 |16 |19 |16 |8 | |8 | |8 | |15 |12 |12 |2 |0 |2 | | | | | | | | | | | | | | | | | | | -Ch14 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |15 |17 |16 |14 |8 | |8 | |8 | |12 |14 |20 |4 |1 |5 | | | | | | | | | | | | | | | | | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 5G Channel |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |VHT80 | | | | | | | | | |VHT160 | | | | | | | | | |Txstream_Delta | | | | | -Band: 5G |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |VHT80_MCS0 |VHT80_MCS1 |VHT80_MCS2 |VHT80_MCS3 |VHT80_MCS4 |VHT80_MCS5 |VHT80_MCS6 |VHT80_MCS7 |VHT80_MCS8 |VHT80_MCS9 |VHT160_MCS0 |VHT160_MCS1 |VHT160_MCS2 |VHT160_MCS3 |VHT160_MCS4 |VHT160_MCS5 |VHT160_MCS6 |VHT160_MCS7 |VHT160_MCS8 |VHT160_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | -Ch184 |18 | |18 | |18 | |18 |18 |15 |18 | |12 | |13 | |11 |14 |16 |16 |12 | |12 | |13 | |20 |17 |16 |17 |18 | |9 | |16 | |17 |20 |18 |16 |19 | |15 | |9 | |17 |8 |17 |0 |4 |4 | | | -Ch188 |18 | |18 | |18 | |18 |18 |16 |20 | |9 | |9 | |11 |8 |12 |18 |15 | |11 | |11 | |14 |8 |17 |16 |16 | |16 | |12 | |8 |13 |19 |18 |11 | |9 | |12 | |14 |8 |13 |5 |2 |0 | | | -Ch192 |18 | |18 | |18 | |18 |18 |15 |9 | |11 | |9 | |15 |14 |11 |19 |15 | |8 | |18 | |20 |20 |8 |9 |9 | |9 | |11 | |18 |13 |14 |20 |18 | |10 | |14 | |12 |13 |16 |0 |2 |0 | | | -Ch196 |18 | |18 | |18 | |18 |18 |10 |11 | |19 | |13 | |12 |11 |10 |13 |11 | |19 | |10 | |16 |20 |15 |15 |8 | |14 | |8 | |18 |20 |15 |17 |17 | |14 | |12 | |12 |8 |16 |4 |3 |2 | | | -Ch8 |18 | |18 | |18 | |18 |18 |18 |13 | |19 | |20 | |18 |10 |9 |8 |8 | |17 | |15 | |17 |9 |18 |19 |11 | |12 | |15 | |20 |12 |12 |13 |9 | |9 | |15 | |10 |11 |17 |4 |3 |3 | | | -Ch12 |18 | |18 | |18 | |18 |18 |17 |20 | |14 | |10 | |10 |16 |15 |13 |11 | |15 | |16 | |17 |11 |15 |9 |18 | |8 | |20 | |19 |11 |9 |20 |8 | |18 | |8 | |8 |18 |18 |1 |3 |4 | | | -Ch16 |18 | |18 | |18 | |18 |18 |10 |18 | |18 | |8 | |19 |8 |12 |19 |16 | |19 | |18 | |16 |19 |12 |18 |18 | |9 | |10 | |18 |20 |20 |20 |9 | |11 | |20 | |17 |14 |16 |2 |2 |2 | | | -Ch36 |18 | |18 | |18 | |18 |18 |18 |19 | |8 | |11 | |16 |10 |9 |19 |11 | |19 | |9 | |8 |19 |8 |11 |17 | |20 | |14 | |9 |19 |19 |20 |13 | |12 | |19 | |13 |17 |9 |5 |1 |2 | | | -Ch40 |18 | |18 | |18 | |18 |18 |13 |20 | |13 | |19 | |16 |11 |14 |17 |17 | |14 | |8 | |13 |8 |10 |20 |10 | |9 | |14 | |11 |14 |17 |9 |20 | |15 | |19 | |9 |8 |11 |3 |1 |1 | | | -Ch44 |18 | |18 | |18 | |18 |18 |10 |14 | |19 | |20 | |17 |16 |12 |18 |8 | |17 | |18 | |15 |19 |14 |11 |13 | |14 | |12 | |16 |16 |19 |13 |14 | |19 | |14 | |20 |20 |11 |5 |1 |0 | | | -Ch48 |18 | |18 | |18 | |18 |18 |8 |12 | |12 | |19 | |11 |8 |11 |20 |12 | |12 | |11 | |15 |16 |10 |12 |16 | |11 | |15 | |18 |19 |17 |16 |17 | |11 | |8 | |10 |16 |16 |5 |5 |0 | | | -Ch52 |18 | |18 | |18 | |18 |18 |15 |12 | |15 | |20 | |9 |10 |10 |14 |8 | |20 | |10 | |16 |17 |18 |11 |16 | |17 | |10 | |17 |12 |13 |17 |17 | |13 | |18 | |18 |20 |13 |4 |3 |4 | | | -Ch56 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |20 |13 |14 |11 | |10 | |20 | |10 |8 |16 |12 |10 | |16 | |11 | |9 |11 |14 |17 |12 | |17 | |13 | |18 |10 |19 |0 |3 |3 | | | -Ch60 |18 | |18 | |18 | |18 |18 |14 |11 | |8 | |20 | |13 |16 |13 |11 |20 | |9 | |17 | |16 |11 |8 |12 |17 | |15 | |8 | |16 |10 |20 |19 |15 | |13 | |9 | |17 |18 |11 |4 |1 |2 | | | -Ch64 |18 | |18 | |18 | |18 |18 |13 |14 | |8 | |12 | |17 |8 |12 |18 |17 | |17 | |14 | |18 |8 |8 |20 |17 | |16 | |20 | |9 |15 |11 |10 |11 | |18 | |10 | |10 |15 |19 |2 |1 |4 | | | -Ch68 |18 | |18 | |18 | |18 |18 |14 |19 | |17 | |9 | |18 |19 |20 |12 |14 | |8 | |14 | |20 |20 |18 |9 |18 | |11 | |19 | |19 |10 |11 |8 |18 | |9 | |8 | |16 |11 |8 |3 |3 |1 | | | -Ch72 |18 | |18 | |18 | |18 |18 |19 |13 | |20 | |11 | |16 |9 |19 |20 |19 | |14 | |8 | |9 |17 |13 |19 |15 | |8 | |9 | |19 |14 |19 |15 |18 | |16 | |12 | |13 |15 |10 |4 |3 |1 | | | -Ch76 |18 | |18 | |18 | |18 |18 |17 |13 | |16 | |20 | |16 |8 |9 |20 |11 | |17 | |11 | |8 |18 |9 |20 |9 | |17 | |16 | |11 |11 |11 |18 |10 | |13 | |W | |20 |17 |8 |1 |3 |3 | | | -Ch80 |18 | |18 | |18 | |18 |18 |14 |20 | |13 | |13 | |17 |8 |10 |16 |8 | |9 | |19 | |16 |17 |17 |19 |15 | |9 | |13 | |16 |13 |14 |12 |9 | |20 | |20 | |14 |18 |18 |0 |4 |2 | | | -Ch84 |18 | |18 | |18 | |18 |18 |11 |18 | |20 | |9 | |13 |14 |11 |16 |15 | |12 | |11 | |9 |19 |13 |11 |11 | |9 | |15 | |16 |18 |13 |12 |8 | |8 | |8 | |10 |12 |15 |3 |2 |5 | | | -Ch88 |18 | |18 | |18 | |18 |18 |18 |19 | |9 | |17 | |15 |8 |19 |11 |11 | |14 | |9 | |14 |20 |20 |11 |11 | |15 | |12 | |14 |11 |8 |18 |15 | |19 | |18 | |12 |20 |16 |5 |5 |1 | | | -Ch92 |18 | |18 | |18 | |18 |18 |11 |8 | |15 | |13 | |13 |13 |13 |16 |14 | |14 | |9 | |9 |15 |20 |11 |17 | |10 | |14 | |13 |17 |11 |8 |18 | |20 | |8 | |10 |19 |18 |1 |4 |4 | | | -Ch96 |18 | |18 | |18 | |18 |18 |8 |12 | |16 | |9 | |13 |12 |9 |8 |11 | |8 | |8 | |19 |11 |15 |16 |8 | |11 | |16 | |18 |16 |9 |19 |9 | |10 | |15 | |19 |19 |15 |4 |2 |4 | | | -Ch100 |18 | |18 | |18 | |18 |18 |18 |13 | |20 | |20 | |12 |9 |19 |10 |9 | |14 | |8 | |19 |10 |17 |9 |10 | |10 | |8 | |13 |12 |11 |20 |11 | |16 | |18 | |14 |16 |19 |1 |1 |2 | | | -Ch104 |18 | |18 | |18 | |18 |18 |19 |12 | |20 | |14 | |16 |15 |9 |19 |11 | |15 | |11 | |12 |18 |15 |11 |15 | |19 | |10 | |14 |15 |19 |9 |13 | |19 | |13 | |11 |11 |17 |2 |2 |0 | | | -Ch108 |18 | |18 | |18 | |18 |18 |18 |15 | |13 | |16 | |11 |19 |19 |18 |19 | |12 | |17 | |8 |9 |10 |8 |8 | |18 | |8 | |10 |11 |17 |15 |10 | |19 | |13 | |16 |10 |15 |0 |2 |3 | | | -Ch112 |18 | |18 | |18 | |18 |18 |8 |13 | |9 | |17 | |9 |15 |17 |10 |19 | |9 | |19 | |11 |16 |14 |16 |8 | |18 | |13 | |16 |13 |17 |19 |11 | |8 | |8 | |18 |14 |17 |5 |2 |5 | | | -Ch116 |18 | |18 | |18 | |18 |18 |8 |20 | |11 | |15 | |8 |11 |8 |18 |15 | |13 | |17 | |14 |13 |9 |8 |14 | |14 | |11 | |9 |19 |17 |11 |11 | |8 | |20 | |8 |10 |20 |5 |2 |1 | | | -Ch120 |18 | |18 | |18 | |18 |18 |14 |20 | |8 | |20 | |14 |10 |10 |17 |12 | |16 | |20 | |10 |20 |17 |18 |9 | |15 | |14 | |17 |13 |14 |16 |8 | |18 | |10 | |15 |12 |12 |1 |5 |3 | | | -Ch124 |18 | |18 | |18 | |18 |18 |20 |9 | |17 | |12 | |12 |8 |14 |8 |8 | |20 | |17 | |16 |20 |13 |14 |16 | |10 | |14 | |20 |15 |17 |8 |10 | |13 | |13 | |11 |13 |9 |5 |0 |5 | | | -Ch128 |18 | |18 | |18 | |18 |18 |9 |19 | |9 | |14 | |8 |14 |11 |9 |14 | |16 | |15 | |14 |10 |15 |14 |14 | |20 | |10 | |16 |15 |11 |12 |13 | |13 | |13 | |12 |15 |20 |1 |4 |3 | | | -Ch132 |18 | |18 | |18 | |18 |18 |20 |16 | |13 | |8 | |18 |11 |20 |12 |11 | |11 | |14 | |12 |13 |8 |12 |13 | |10 | |20 | |19 |12 |13 |14 |12 | |11 | |19 | |19 |20 |8 |3 |1 |4 | | | -Ch136 |18 | |18 | |18 | |18 |18 |12 |12 | |19 | |10 | |20 |10 |8 |17 |8 | |12 | |10 | |10 |13 |13 |12 |8 | |11 | |18 | |14 |12 |17 |8 |14 | |14 | |9 | |11 |18 |14 |1 |2 |2 | | | -Ch140 |18 | |18 | |18 | |18 |18 |12 |10 | |13 | |9 | |16 |8 |20 |10 |17 | |8 | |15 | |13 |20 |15 |10 |18 | |13 | |12 | |12 |16 |18 |12 |17 | |10 | |16 | |11 |15 |14 |3 |2 |5 | | | -Ch144 |18 | |18 | |18 | |18 |18 |19 |9 | |15 | |8 | |13 |18 |17 |9 |19 | |16 | |11 | |20 |12 |15 |19 |10 | |17 | |15 | |17 |14 |9 |9 |13 | |17 | |16 | |10 |9 |10 |1 |5 |2 | | | -Ch149 |18 | |18 | |18 | |18 |18 |15 |20 | |12 | |19 | |19 |19 |10 |10 |13 | |15 | |19 | |12 |19 |10 |14 |15 | |10 | |15 | |9 |8 |11 |15 |13 | |10 | |16 | |15 |18 |12 |5 |5 |2 | | | -Ch153 |18 | |18 | |18 | |18 |18 |20 |17 | |8 | |19 | |16 |20 |13 |16 |18 | |14 | |11 | |10 |16 |16 |19 |15 | |13 | |17 | |19 |18 |19 |20 |8 | |18 | |9 | |17 |11 |11 |1 |2 |1 | | | -Ch157 |18 | |18 | |18 | |18 |18 |13 |17 | |12 | |19 | |16 |8 |17 |11 |12 | |15 | |14 | |18 |11 |12 |9 |18 | |20 | |13 | |16 |13 |20 |17 |19 | |10 | |12 | |20 |18 |16 |5 |2 |3 | | | -Ch161 |18 | |18 | |18 | |18 |18 |12 |12 | |16 | |12 | |15 |11 |18 |11 |13 | |17 | |19 | |11 |13 |13 |9 |15 | |10 | |10 | |19 |13 |20 |13 |9 | |8 | |8 | |20 |14 |12 |0 |4 |1 | | | -Ch165 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |8 |19 |15 |10 | |17 | |13 | |13 |19 |20 |8 |18 | |15 | |20 | |16 |9 |14 |11 |20 | |11 | |19 | |15 |16 |8 |1 |2 |0 | | | -Ch169 |18 | |18 | |18 | |18 |18 |8 |17 | |17 | |13 | |16 |8 |14 |18 |11 | |8 | |18 | |20 |14 |8 |17 |8 | |13 | |18 | |19 |20 |19 |20 |17 | |13 | |20 | |9 |15 |18 |0 |3 |4 | | | -Ch173 |18 | |18 | |18 | |18 |18 |14 |9 | |13 | |12 | |15 |14 |15 |10 |10 | |18 | |16 | |16 |8 |13 |16 |11 | |11 | |13 | |13 |15 |12 |20 |15 | |14 | |13 | |16 |11 |14 |3 |3 |4 | | | -Ch177 |18 | |18 | |18 | |18 |18 |19 |18 | |16 | |10 | |20 |13 |11 |16 |12 | |16 | |18 | |18 |11 |18 |8 |13 | |14 | |11 | |18 |14 |16 |16 |19 | |16 | |13 | |15 |8 |13 |5 |0 |0 | | | -Ch181 |18 | |18 | |18 | |18 |18 |20 |11 | |10 | |9 | |8 |9 |15 |15 |8 | |8 | |12 | |11 |9 |18 |20 |11 | |17 | |11 | |8 |15 |8 |18 |12 | |18 | |16 | |19 |9 |14 |4 |1 |4 | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e-sku.dat b/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e-sku.dat deleted file mode 100644 index be9c0d353..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e-sku.dat +++ /dev/null @@ -1,65 +0,0 @@ -# Single SKU Max Power Table | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 2.4G Channel |CCK | | | |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |Txstream_Delta | | | | | | | | | | | | | | | | | | | | | -Band: 2.4G |CCK_1M |CCK_2M |CCK_5.5M |CCK_11M |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | | | | | | | | | | | | | | | | | -Ch1 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |20 |12 |18 |16 |8 | |8 | |8 | |9 |11 |12 |2 |1 |3 | | | | | | | | | | | | | | | | | | | -Ch2 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |19 |19 |10 |12 |8 | |8 | |8 | |9 |16 |12 |5 |4 |0 | | | | | | | | | | | | | | | | | | | -Ch3 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |17 |18 |16 |20 |8 | |8 | |8 | |12 |8 |20 |0 |2 |0 | | | | | | | | | | | | | | | | | | | -Ch4 |8 | |8 | |8 | |8 | |8 | |8 |8 |9 |8 | |8 | |8 | |14 |10 |14 |18 |8 | |8 | |8 | |14 |12 |10 |3 |4 |5 | | | | | | | | | | | | | | | | | | | -Ch5 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |10 |13 |11 |8 |8 | |8 | |8 | |12 |8 |9 |4 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch6 |8 | |8 | |8 | |8 | |8 | |8 |8 |13 |8 | |8 | |8 | |11 |9 |12 |16 |8 | |8 | |8 | |9 |17 |11 |5 |2 |1 | | | | | | | | | | | | | | | | | | | -Ch7 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |14 |11 |13 |18 |8 | |8 | |8 | |16 |13 |10 |2 |5 |4 | | | | | | | | | | | | | | | | | | | -Ch8 |8 | |8 | |8 | |8 | |8 | |8 |8 |15 |8 | |8 | |8 | |14 |9 |11 |10 |8 | |8 | |8 | |11 |14 |8 |5 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch9 |8 | |8 | |8 | |8 | |8 | |8 |8 |11 |8 | |8 | |8 | |12 |9 |15 |19 |8 | |8 | |8 | |14 |20 |12 |2 |5 |3 | | | | | | | | | | | | | | | | | | | -Ch10 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |17 |14 |17 |15 |8 | |8 | |8 | |9 |17 |8 |2 |4 |2 | | | | | | | | | | | | | | | | | | | -Ch11 |8 | |8 | |8 | |8 | |8 | |8 |8 |14 |8 | |8 | |8 | |20 |10 |20 |18 |8 | |8 | |8 | |12 |8 |20 |3 |1 |4 | | | | | | | | | | | | | | | | | | | -Ch12 |8 | |8 | |8 | |8 | |8 | |8 |8 |18 |8 | |8 | |8 | |20 |16 |17 |9 |8 | |8 | |8 | |11 |20 |9 |0 |0 |1 | | | | | | | | | | | | | | | | | | | -Ch13 |8 | |8 | |8 | |8 | |8 | |8 |8 |8 |8 | |8 | |8 | |11 |16 |19 |16 |8 | |8 | |8 | |15 |12 |12 |2 |0 |2 | | | | | | | | | | | | | | | | | | | -Ch14 |8 | |8 | |8 | |8 | |8 | |8 |8 |10 |8 | |8 | |8 | |15 |17 |16 |14 |8 | |8 | |8 | |12 |14 |20 |4 |1 |5 | | | | | | | | | | | | | | | | | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -# 5G Channel |OFDM | | | | | | | |VHT20 | | | | | | | | | |VHT40 | | | | | | | | | |VHT80 | | | | | | | | | |VHT160 | | | | | | | | | |Txstream_Delta | | | | | -Band: 5G |OFDM_6M |OFDM_9M |OFDM_12M |OFDM_18M |OFDM_24M |OFDM_36M |OFDM_48M |OFDM_54M |VHT20_MCS0 |VHT20_MCS1 |VHT20_MCS2 |VHT20_MCS3 |VHT20_MCS4 |VHT20_MCS5 |VHT20_MCS6 |VHT20_MCS7 |VHT20_MCS8 |VHT20_MCS9 |VHT40_MCS0 |VHT40_MCS1 |VHT40_MCS2 |VHT40_MCS3 |VHT40_MCS4 |VHT40_MCS5 |VHT40_MCS6 |VHT40_MCS7 |VHT40_MCS8 |VHT40_MCS9 |VHT80_MCS0 |VHT80_MCS1 |VHT80_MCS2 |VHT80_MCS3 |VHT80_MCS4 |VHT80_MCS5 |VHT80_MCS6 |VHT80_MCS7 |VHT80_MCS8 |VHT80_MCS9 |VHT160_MCS0 |VHT160_MCS1 |VHT160_MCS2 |VHT160_MCS3 |VHT160_MCS4 |VHT160_MCS5 |VHT160_MCS6 |VHT160_MCS7 |VHT160_MCS8 |VHT160_MCS9 |Txstream_3T |Txstream_2T |Txstream_1T | | | -Ch184 |18 | |18 | |18 | |18 |18 |15 |18 | |12 | |13 | |11 |14 |16 |16 |12 | |12 | |13 | |20 |17 |16 |17 |18 | |9 | |16 | |17 |20 |18 |16 |19 | |15 | |9 | |17 |8 |17 |0 |4 |4 | | | -Ch188 |18 | |18 | |18 | |18 |18 |16 |20 | |9 | |9 | |11 |8 |12 |18 |15 | |11 | |11 | |14 |8 |17 |16 |16 | |16 | |12 | |8 |13 |19 |18 |11 | |9 | |12 | |14 |8 |13 |5 |2 |0 | | | -Ch192 |18 | |18 | |18 | |18 |18 |15 |9 | |11 | |9 | |15 |14 |11 |19 |15 | |8 | |18 | |20 |20 |8 |9 |9 | |9 | |11 | |18 |13 |14 |20 |18 | |10 | |14 | |12 |13 |16 |0 |2 |0 | | | -Ch196 |18 | |18 | |18 | |18 |18 |10 |11 | |19 | |13 | |12 |11 |10 |13 |11 | |19 | |10 | |16 |20 |15 |15 |8 | |14 | |8 | |18 |20 |15 |17 |17 | |14 | |12 | |12 |8 |16 |4 |3 |2 | | | -Ch8 |18 | |18 | |18 | |18 |18 |18 |13 | |19 | |20 | |18 |10 |9 |8 |8 | |17 | |15 | |17 |9 |18 |19 |11 | |12 | |15 | |20 |12 |12 |13 |9 | |9 | |15 | |10 |11 |17 |4 |3 |3 | | | -Ch12 |18 | |18 | |18 | |18 |18 |17 |20 | |14 | |10 | |10 |16 |15 |13 |11 | |15 | |16 | |17 |11 |15 |9 |18 | |8 | |20 | |19 |11 |9 |20 |8 | |18 | |8 | |8 |18 |18 |1 |3 |4 | | | -Ch16 |18 | |18 | |18 | |18 |18 |10 |18 | |18 | |8 | |19 |8 |12 |19 |16 | |19 | |18 | |16 |19 |12 |18 |18 | |9 | |10 | |18 |20 |20 |20 |9 | |11 | |20 | |17 |14 |16 |2 |2 |2 | | | -Ch36 |18 | |18 | |18 | |18 |18 |18 |19 | |8 | |11 | |16 |10 |9 |19 |11 | |19 | |9 | |8 |19 |8 |11 |17 | |20 | |14 | |9 |19 |19 |20 |13 | |12 | |19 | |13 |17 |9 |5 |1 |2 | | | -Ch40 |18 | |18 | |18 | |18 |18 |13 |20 | |13 | |19 | |16 |11 |14 |17 |17 | |14 | |8 | |13 |8 |10 |20 |10 | |9 | |14 | |11 |14 |17 |9 |20 | |15 | |19 | |9 |8 |11 |3 |1 |1 | | | -Ch44 |18 | |18 | |18 | |18 |18 |10 |14 | |19 | |20 | |17 |16 |12 |18 |8 | |17 | |18 | |15 |19 |14 |11 |13 | |14 | |12 | |16 |16 |19 |13 |14 | |19 | |14 | |20 |20 |11 |5 |1 |0 | | | -Ch48 |18 | |18 | |18 | |18 |18 |8 |12 | |12 | |19 | |11 |8 |11 |20 |12 | |12 | |11 | |15 |16 |10 |12 |16 | |11 | |15 | |18 |19 |17 |16 |17 | |11 | |8 | |10 |16 |16 |5 |5 |0 | | | -Ch52 |18 | |18 | |18 | |18 |18 |15 |12 | |15 | |20 | |9 |10 |10 |14 |8 | |20 | |10 | |16 |17 |18 |11 |16 | |17 | |10 | |17 |12 |13 |17 |17 | |13 | |18 | |18 |20 |13 |4 |3 |4 | | | -Ch56 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |20 |13 |14 |11 | |10 | |20 | |10 |8 |16 |12 |10 | |16 | |11 | |9 |11 |14 |17 |12 | |17 | |13 | |18 |10 |19 |0 |3 |3 | | | -Ch60 |18 | |18 | |18 | |18 |18 |14 |11 | |8 | |20 | |13 |16 |13 |11 |20 | |9 | |17 | |16 |11 |8 |12 |17 | |15 | |8 | |16 |10 |20 |19 |15 | |13 | |9 | |17 |18 |11 |4 |1 |2 | | | -Ch64 |18 | |18 | |18 | |18 |18 |13 |14 | |8 | |12 | |17 |8 |12 |18 |17 | |17 | |14 | |18 |8 |8 |20 |17 | |16 | |20 | |9 |15 |11 |10 |11 | |18 | |10 | |10 |15 |19 |2 |1 |4 | | | -Ch68 |18 | |18 | |18 | |18 |18 |14 |19 | |17 | |9 | |18 |19 |20 |12 |14 | |8 | |14 | |20 |20 |18 |9 |18 | |11 | |19 | |19 |10 |11 |8 |18 | |9 | |8 | |16 |11 |8 |3 |3 |1 | | | -Ch72 |18 | |18 | |18 | |18 |18 |19 |13 | |20 | |11 | |16 |9 |19 |20 |19 | |14 | |8 | |9 |17 |13 |19 |15 | |8 | |9 | |19 |14 |19 |15 |18 | |16 | |12 | |13 |15 |10 |4 |3 |1 | | | -Ch76 |18 | |18 | |18 | |18 |18 |17 |13 | |16 | |20 | |16 |8 |9 |20 |11 | |17 | |11 | |8 |18 |9 |20 |9 | |17 | |16 | |11 |11 |11 |18 |10 | |13 | |W | |20 |17 |8 |1 |3 |3 | | | -Ch80 |18 | |18 | |18 | |18 |18 |14 |20 | |13 | |13 | |17 |8 |10 |16 |8 | |9 | |19 | |16 |17 |17 |19 |15 | |9 | |13 | |16 |13 |14 |12 |9 | |20 | |20 | |14 |18 |18 |0 |4 |2 | | | -Ch84 |18 | |18 | |18 | |18 |18 |11 |18 | |20 | |9 | |13 |14 |11 |16 |15 | |12 | |11 | |9 |19 |13 |11 |11 | |9 | |15 | |16 |18 |13 |12 |8 | |8 | |8 | |10 |12 |15 |3 |2 |5 | | | -Ch88 |18 | |18 | |18 | |18 |18 |18 |19 | |9 | |17 | |15 |8 |19 |11 |11 | |14 | |9 | |14 |20 |20 |11 |11 | |15 | |12 | |14 |11 |8 |18 |15 | |19 | |18 | |12 |20 |16 |5 |5 |1 | | | -Ch92 |18 | |18 | |18 | |18 |18 |11 |8 | |15 | |13 | |13 |13 |13 |16 |14 | |14 | |9 | |9 |15 |20 |11 |17 | |10 | |14 | |13 |17 |11 |8 |18 | |20 | |8 | |10 |19 |18 |1 |4 |4 | | | -Ch96 |18 | |18 | |18 | |18 |18 |8 |12 | |16 | |9 | |13 |12 |9 |8 |11 | |8 | |8 | |19 |11 |15 |16 |8 | |11 | |16 | |18 |16 |9 |19 |9 | |10 | |15 | |19 |19 |15 |4 |2 |4 | | | -Ch100 |18 | |18 | |18 | |18 |18 |18 |13 | |20 | |20 | |12 |9 |19 |10 |9 | |14 | |8 | |19 |10 |17 |9 |10 | |10 | |8 | |13 |12 |11 |20 |11 | |16 | |18 | |14 |16 |19 |1 |1 |2 | | | -Ch104 |18 | |18 | |18 | |18 |18 |19 |12 | |20 | |14 | |16 |15 |9 |19 |11 | |15 | |11 | |12 |18 |15 |11 |15 | |19 | |10 | |14 |15 |19 |9 |13 | |19 | |13 | |11 |11 |17 |2 |2 |0 | | | -Ch108 |18 | |18 | |18 | |18 |18 |18 |15 | |13 | |16 | |11 |19 |19 |18 |19 | |12 | |17 | |8 |9 |10 |8 |8 | |18 | |8 | |10 |11 |17 |15 |10 | |19 | |13 | |16 |10 |15 |0 |2 |3 | | | -Ch112 |18 | |18 | |18 | |18 |18 |8 |13 | |9 | |17 | |9 |15 |17 |10 |19 | |9 | |19 | |11 |16 |14 |16 |8 | |18 | |13 | |16 |13 |17 |19 |11 | |8 | |8 | |18 |14 |17 |5 |2 |5 | | | -Ch116 |18 | |18 | |18 | |18 |18 |8 |20 | |11 | |15 | |8 |11 |8 |18 |15 | |13 | |17 | |14 |13 |9 |8 |14 | |14 | |11 | |9 |19 |17 |11 |11 | |8 | |20 | |8 |10 |20 |5 |2 |1 | | | -Ch120 |18 | |18 | |18 | |18 |18 |14 |20 | |8 | |20 | |14 |10 |10 |17 |12 | |16 | |20 | |10 |20 |17 |18 |9 | |15 | |14 | |17 |13 |14 |16 |8 | |18 | |10 | |15 |12 |12 |1 |5 |3 | | | -Ch124 |18 | |18 | |18 | |18 |18 |20 |9 | |17 | |12 | |12 |8 |14 |8 |8 | |20 | |17 | |16 |20 |13 |14 |16 | |10 | |14 | |20 |15 |17 |8 |10 | |13 | |13 | |11 |13 |9 |5 |0 |5 | | | -Ch128 |18 | |18 | |18 | |18 |18 |9 |19 | |9 | |14 | |8 |14 |11 |9 |14 | |16 | |15 | |14 |10 |15 |14 |14 | |20 | |10 | |16 |15 |11 |12 |13 | |13 | |13 | |12 |15 |20 |1 |4 |3 | | | -Ch132 |18 | |18 | |18 | |18 |18 |20 |16 | |13 | |8 | |18 |11 |20 |12 |11 | |11 | |14 | |12 |13 |8 |12 |13 | |10 | |20 | |19 |12 |13 |14 |12 | |11 | |19 | |19 |20 |8 |3 |1 |4 | | | -Ch136 |18 | |18 | |18 | |18 |18 |12 |12 | |19 | |10 | |20 |10 |8 |17 |8 | |12 | |10 | |10 |13 |13 |12 |8 | |11 | |18 | |14 |12 |17 |8 |14 | |14 | |9 | |11 |18 |14 |1 |2 |2 | | | -Ch140 |18 | |18 | |18 | |18 |18 |12 |10 | |13 | |9 | |16 |8 |20 |10 |17 | |8 | |15 | |13 |20 |15 |10 |18 | |13 | |12 | |12 |16 |18 |12 |17 | |10 | |16 | |11 |15 |14 |3 |2 |5 | | | -Ch144 |18 | |18 | |18 | |18 |18 |19 |9 | |15 | |8 | |13 |18 |17 |9 |19 | |16 | |11 | |20 |12 |15 |19 |10 | |17 | |15 | |17 |14 |9 |9 |13 | |17 | |16 | |10 |9 |10 |1 |5 |2 | | | -Ch149 |18 | |18 | |18 | |18 |18 |15 |20 | |12 | |19 | |19 |19 |10 |10 |13 | |15 | |19 | |12 |19 |10 |14 |15 | |10 | |15 | |9 |8 |11 |15 |13 | |10 | |16 | |15 |18 |12 |5 |5 |2 | | | -Ch153 |18 | |18 | |18 | |18 |18 |20 |17 | |8 | |19 | |16 |20 |13 |16 |18 | |14 | |11 | |10 |16 |16 |19 |15 | |13 | |17 | |19 |18 |19 |20 |8 | |18 | |9 | |17 |11 |11 |1 |2 |1 | | | -Ch157 |18 | |18 | |18 | |18 |18 |13 |17 | |12 | |19 | |16 |8 |17 |11 |12 | |15 | |14 | |18 |11 |12 |9 |18 | |20 | |13 | |16 |13 |20 |17 |19 | |10 | |12 | |20 |18 |16 |5 |2 |3 | | | -Ch161 |18 | |18 | |18 | |18 |18 |12 |12 | |16 | |12 | |15 |11 |18 |11 |13 | |17 | |19 | |11 |13 |13 |9 |15 | |10 | |10 | |19 |13 |20 |13 |9 | |8 | |8 | |20 |14 |12 |0 |4 |1 | | | -Ch165 |18 | |18 | |18 | |18 |18 |13 |16 | |15 | |13 | |15 |8 |19 |15 |10 | |17 | |13 | |13 |19 |20 |8 |18 | |15 | |20 | |16 |9 |14 |11 |20 | |11 | |19 | |15 |16 |8 |1 |2 |0 | | | -Ch169 |18 | |18 | |18 | |18 |18 |8 |17 | |17 | |13 | |16 |8 |14 |18 |11 | |8 | |18 | |20 |14 |8 |17 |8 | |13 | |18 | |19 |20 |19 |20 |17 | |13 | |20 | |9 |15 |18 |0 |3 |4 | | | -Ch173 |18 | |18 | |18 | |18 |18 |14 |9 | |13 | |12 | |15 |14 |15 |10 |10 | |18 | |16 | |16 |8 |13 |16 |11 | |11 | |13 | |13 |15 |12 |20 |15 | |14 | |13 | |16 |11 |14 |3 |3 |4 | | | -Ch177 |18 | |18 | |18 | |18 |18 |19 |18 | |16 | |10 | |20 |13 |11 |16 |12 | |16 | |18 | |18 |11 |18 |8 |13 | |14 | |11 | |18 |14 |16 |16 |19 | |16 | |13 | |15 |8 |13 |5 |0 |0 | | | -Ch181 |18 | |18 | |18 | |18 |18 |20 |11 | |10 | |9 | |8 |9 |15 |15 |8 | |8 | |12 | |11 |9 |18 |20 |11 | |17 | |11 | |8 |15 |8 |18 |12 | |18 | |16 | |19 |9 |14 |4 |1 |4 | | | - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.1.dat b/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.1.dat deleted file mode 100644 index f58d6ba52..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.1.dat +++ /dev/null @@ -1,410 +0,0 @@ -#The word of "Default" must not be removed -Default -AccessControlList0= -AccessControlList1= -AccessControlList10= -AccessControlList11= -AccessControlList12= -AccessControlList13= -AccessControlList14= -AccessControlList15= -AccessControlList2= -AccessControlList3= -AccessControlList4= -AccessControlList5= -AccessControlList6= -AccessControlList7= -AccessControlList8= -AccessControlList9= -AccessPolicy0=0 -AccessPolicy1=0 -AccessPolicy10=0 -AccessPolicy11=0 -AccessPolicy12=0 -AccessPolicy13=0 -AccessPolicy14=0 -AccessPolicy15=0 -AccessPolicy2=0 -AccessPolicy3=0 -AccessPolicy4=0 -AccessPolicy5=0 -AccessPolicy6=0 -AccessPolicy7=0 -AccessPolicy8=0 -AccessPolicy9=0 -AckPolicy=0;0;0;0 -APACM=0;0;0;0 -APAifsn=3;7;1;1 -ApCliAuthMode= -ApCliBssid= -ApCliDefaultKeyID= -ApCliEnable= -ApCliKey1Str= -ApCliKey1Str1= -ApCliKey1Type= -ApCliKey2Str= -ApCliKey2Str1= -ApCliKey2Type= -ApCliKey3Str= -ApCliKey3Str1= -ApCliKey3Type= -ApCliKey4Str= -ApCliKey4Str1= -ApCliKey4Type= -ApCliSsid= -ApCliWirelessMode= -ApCliWPAPSK= -ApCliWPAPSK1= -APCwmax=6;10;4;3 -APCwmin=4;4;3;2 -APSDCapable=1 -APTxop=0;0;94;47 -AuthMode=OPEN -AutoChannelSelect=3 -AutoChannelSkipList= -AutoProvisionEn=0 -BandSteering=0 -BasicRate=15 -BeaconPeriod=100 -BFBACKOFFenable=0 -BgndScanSkipCh= -BGProtection=0 -BndStrgBssIdx= -BSSACM=0;0;0;0 -BSSAifsn=3;7;2;2 -BSSCwmax=10;10;4;3 -BSSCwmin=4;4;3;2 -BssidNum=1 -BSSTxop=0;0;94;47 -BW_Enable=0 -BW_Guarantee_Rate= -BW_Maximum_Rate= -BW_Priority= -BW_Root=0 -CalCacheApply=0 -CarrierDetect=0 -Channel=0 -ChannelGrp= -CountryCode=US -CountryRegion=5 -CountryRegionABand=7 -CP_SUPPORT=2 -CSPeriod=6 -DBDC_MODE=0 -DebugFlags=0 -DefaultKeyID=1 -DfsCalibration=0 -DfsEnable=0 -DfsFalseAlarmPrevent=1 -DfsZeroWait=0 -DfsZeroWaitCacTime=255 -DisableOLBC=0 -DtimPeriod=1 -E2pAccessMode=2 -EAPifname=br-lan -EDCCAEnable=1 -EncrypType=NONE -EthConvertMode=dongle -EtherTrafficBand=0 -Ethifname= -ETxBfEnCond=1 -FineAGC=0 -FixedTxMode= -ForceRoamSupport= -FragThreshold=2346 -FreqDelta=0 -FtSupport=0 -GreenAP=1 -G_BAND_256QAM=1 -HideSSID=0 -HT_AMSDU=1 -HT_AutoBA=1 -HT_BADecline=0 -HT_BAWinSize=64 -HT_BSSCoexistence=1 -HT_BW=1 -HT_DisallowTKIP=1 -HT_EXTCHA=1 -HT_GI=1 -HT_HTC=1 -HT_LDPC=1 -HT_LinkAdapt=0 -HT_MCS=33 -HT_MpduDensity=5 -HT_OpMode=0 -HT_PROTECT=1 -HT_RDG=0 -HT_RxStream=4 -HT_STBC=1 -HT_TxStream=4 -IcapMode=0 -idle_timeout_interval=0 -IEEE80211H=1 -IEEE8021X=0 -IgmpSnEnable=0 -ITxBfEn=1 -Key1Str= -Key1Str1= -Key1Str10= -Key1Str11= -Key1Str12= -Key1Str13= -Key1Str14= -Key1Str15= -Key1Str16= -Key1Str2= -Key1Str3= -Key1Str4= -Key1Str5= -Key1Str6= -Key1Str7= -Key1Str8= -Key1Str9= -Key1Type=0 -Key2Str= -Key2Str1= -Key2Str10= -Key2Str11= -Key2Str12= -Key2Str13= -Key2Str14= -Key2Str15= -Key2Str16= -Key2Str2= -Key2Str3= -Key2Str4= -Key2Str5= -Key2Str6= -Key2Str7= -Key2Str8= -Key2Str9= -Key2Type=0 -Key3Str= -Key3Str1= -Key3Str10= -Key3Str11= -Key3Str12= -Key3Str13= -Key3Str14= -Key3Str15= -Key3Str16= -Key3Str2= -Key3Str3= -Key3Str4= -Key3Str5= -Key3Str6= -Key3Str7= -Key3Str8= -Key3Str9= -Key3Type=0 -Key4Str= -Key4Str1= -Key4Str10= -Key4Str11= -Key4Str12= -Key4Str13= -Key4Str14= -Key4Str15= -Key4Str16= -Key4Str2= -Key4Str3= -Key4Str4= -Key4Str5= -Key4Str6= -Key4Str7= -Key4Str8= -Key4Str9= -Key4Type=0 -LinkTestSupport=0 -MACRepeaterEn= -MACRepeaterOuiMode=2 -MeshAuthMode= -MeshAutoLink=0 -MeshDefaultkey=0 -MeshEncrypType= -MeshId= -MeshWEPKEY= -MeshWPAKEY= -MUTxRxEnable=0 -NoForwarding=0 -NoForwardingBTNBSSID=0 -own_ip_addr=192.168.1.1 -PcieAspm=0 -PERCENTAGEenable=0 -PhyRateLimit=0 -PMFMFPC=1 -PMFMFPR=0 -PMFSHA256=0 -PMKCachePeriod=10 -PowerUpCckOfdm=0:0:0:0:0:0:0 -PowerUpHT20=0:0:0:0:0:0:0 -PowerUpHT40=0:0:0:0:0:0:0 -PowerUpVHT160=0:0:0:0:0:0:0 -PowerUpVHT20=0:0:0:0:0:0:0 -PowerUpVHT40=0:0:0:0:0:0:0 -PowerUpVHT80=0:0:0:0:0:0:0 -PreAntSwitch= -PreAuth=0 -PreAuthifname=br-lan -RadioLinkSelection=0 -RadioOn=1 -RADIUS_Acct_Key= -RADIUS_Acct_Port=1813 -RADIUS_Acct_Server= -RADIUS_Key1= -RADIUS_Key10= -RADIUS_Key11= -RADIUS_Key12= -RADIUS_Key13= -RADIUS_Key14= -RADIUS_Key15= -RADIUS_Key16= -RADIUS_Key2= -RADIUS_Key3= -RADIUS_Key4= -RADIUS_Key5= -RADIUS_Key6= -RADIUS_Key7= -RADIUS_Key8= -RADIUS_Key9= -RADIUS_Port=1812 -RADIUS_Server=0 -RDRegion= -RED_Enable=1 -RekeyInterval=3600 -RekeyMethod=DISABLE -RRMEnable=0 -RTSThreshold=2347 -session_timeout_interval=0 -ShortSlot=1 -SKUenable=0 -SSID= -SSID1=WITHUSP-5.0 -SSID10= -SSID11= -SSID12= -SSID13= -SSID14= -SSID15= -SSID16= -SSID2= -SSID3= -SSID4= -SSID5= -SSID6= -SSID7= -SSID8= -SSID9= -StationKeepAlive=0 -StreamMode=0 -StreamModeMac0= -StreamModeMac1= -StreamModeMac2= -StreamModeMac3= -TGnWifiTest=0 -ThermalRecal=0 -TxBurst=1 -TxPower=100 -TxPreamble=1 -VHT_BW=1 -VHT_BW_SIGNAL=0 -VHT_LDPC=1 -VHT_Sec80_Channel=0 -VHT_SGI=1 -VHT_STBC=1 -VLANID=0 -VLANPriority=0 -VLANTag=0 -VOW_Airtime_Ctrl_En=0 -VOW_Airtime_Fairness_En=1 -VOW_BW_Ctrl=0 -VOW_Group_Backlog= -VOW_Group_DWRR_Max_Wait_Time= -VOW_Group_DWRR_Quantum= -VOW_Group_Max_Airtime_Bucket_Size= -VOW_Group_Max_Rate= -VOW_Group_Max_Rate_Bucket_Size= -VOW_Group_Max_Ratio= -VOW_Group_Max_Wait_Time= -VOW_Group_Min_Airtime_Bucket_Size= -VOW_Group_Min_Rate= -VOW_Group_Min_Rate_Bucket_Size= -VOW_Group_Min_Ratio= -VOW_Rate_Ctrl_En=0 -VOW_Refill_Period= -VOW_RX_En=1 -VOW_Sta_BE_DWRR_Quantum= -VOW_Sta_BK_DWRR_Quantum= -VOW_Sta_DWRR_Max_Wait_Time= -VOW_Sta_VI_DWRR_Quantum= -VOW_Sta_VO_DWRR_Quantum= -VOW_WATF_Enable= -VOW_WATF_MAC_LV0= -VOW_WATF_MAC_LV1= -VOW_WATF_MAC_LV2= -VOW_WATF_MAC_LV3= -VOW_WATF_Q_LV0= -VOW_WATF_Q_LV1= -VOW_WATF_Q_LV2= -VOW_WATF_Q_LV3= -VOW_WMM_Search_Rule_Band0= -VOW_WMM_Search_Rule_Band1= -WapiAsCertPath= -WapiAsIpAddr= -WapiAsPort= -Wapiifname= -WapiPsk1= -WapiPsk10= -WapiPsk11= -WapiPsk12= -WapiPsk13= -WapiPsk14= -WapiPsk15= -WapiPsk16= -WapiPsk2= -WapiPsk3= -WapiPsk4= -WapiPsk5= -WapiPsk6= -WapiPsk7= -WapiPsk8= -WapiPsk9= -WapiPskType= -WapiUserCertPath= -WCNTest=0 -Wds0Key= -Wds1Key= -Wds2Key= -Wds3Key= -WdsEnable=0 -WdsEncrypType=NONE -WdsList= -WdsPhyMode=0 -WHNAT=1 -WiFiTest=0 -WirelessMode=14 -WmmCapable=1 -WPAPSK= -WPAPSK1=12345678 -WPAPSK10= -WPAPSK11= -WPAPSK12= -WPAPSK13= -WPAPSK14= -WPAPSK15= -WPAPSK16= -WPAPSK2= -WPAPSK3= -WPAPSK4= -WPAPSK5= -WPAPSK6= -WPAPSK7= -WPAPSK8= -WPAPSK9= -WscConfMode=0 -WscConfStatus=2 -WEP1Type1=0 -WEP2Type1=0 -WEP3Type1=0 -WEP4Type1=0 -WPSRadio=0 diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.eeprom.bin b/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.eeprom.bin deleted file mode 100644 index 32556855c..000000000 Binary files a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.eeprom.bin and /dev/null differ diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7622.1.dat b/package/lean/mt/drivers/mt_wifi/dbdc/mt7622.1.dat deleted file mode 100644 index 49cac22a8..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/mt7622.1.dat +++ /dev/null @@ -1,412 +0,0 @@ -#The word of "Default" must not be removed -Default -AccessControlList0= -AccessControlList1= -AccessControlList10= -AccessControlList11= -AccessControlList12= -AccessControlList13= -AccessControlList14= -AccessControlList15= -AccessControlList2= -AccessControlList3= -AccessControlList4= -AccessControlList5= -AccessControlList6= -AccessControlList7= -AccessControlList8= -AccessControlList9= -AccessPolicy0=0 -AccessPolicy1=0 -AccessPolicy10=0 -AccessPolicy11=0 -AccessPolicy12=0 -AccessPolicy13=0 -AccessPolicy14=0 -AccessPolicy15=0 -AccessPolicy2=0 -AccessPolicy3=0 -AccessPolicy4=0 -AccessPolicy5=0 -AccessPolicy6=0 -AccessPolicy7=0 -AccessPolicy8=0 -AccessPolicy9=0 -AckPolicy=0;0;0;0 -APACM=0;0;0;0 -APAifsn=3;7;1;1 -ApCliAuthMode= -ApCliBssid= -ApCliDefaultKeyID= -ApCliEnable= -ApCliEncrypType= -ApCliKey1Str= -ApCliKey1Str1= -ApCliKey1Type= -ApCliKey2Str= -ApCliKey2Str1= -ApCliKey2Type= -ApCliKey3Str= -ApCliKey3Str1= -ApCliKey3Type= -ApCliKey4Str= -ApCliKey4Str1= -ApCliKey4Type= -ApCliSsid= -ApCliWirelessMode= -ApCliWPAPSK= -ApCliWPAPSK1= -APCwmax=6;10;4;3 -APCwmin=4;4;3;2 -APSDCapable=1 -APTxop=0;0;94;47 -AuthMode=OPEN -AutoChannelSelect=3 -AutoChannelSkipList= -AutoProvisionEn=0 -BandSteering=0 -BasicRate=15 -BeaconPeriod=100 -BFBACKOFFenable=0 -BgndScanSkipCh= -BGProtection=0 -BndStrgBssIdx= -BSSACM=0;0;0;0 -BSSAifsn=3;7;2;2 -BSSCwmax=10;10;4;3 -BSSCwmin=4;4;3;2 -BssidNum=1 -BSSTxop=0;0;94;47 -BW_Enable=0 -BW_Guarantee_Rate= -BW_Maximum_Rate= -BW_Priority= -BW_Root=0 -CalCacheApply=0 -CarrierDetect=0 -Channel=0 -ChannelGrp= -CountryCode=US -CountryRegion=5 -CountryRegionABand=7 -CP_SUPPORT=2 -CSPeriod=6 -DBDC_MODE=0 -DebugFlags=0 -DefaultKeyID=1 -DfsCalibration=0 -DfsEnable=0 -DfsFalseAlarmPrevent=1 -DfsZeroWait=0 -DfsZeroWaitCacTime=255 -DisableOLBC=0 -DtimPeriod=1 -E2pAccessMode=2 -EAPifname=br-lan -EDCCAEnable=1 -EncrypType=NONE -EthConvertMode=dongle -EtherTrafficBand=0 -Ethifname= -ETxBfEnCond=1 -FineAGC=0 -FixedTxMode= -ForceRoamSupport= -FragThreshold=2346 -FreqDelta=0 -FtSupport=0 -GreenAP=1 -G_BAND_256QAM=1 -HideSSID=0 -HT_AMSDU=1 -HT_AutoBA=1 -HT_BADecline=0 -HT_BAWinSize=64 -HT_BSSCoexistence=1 -HT_BW=1 -HT_DisallowTKIP=1 -HT_EXTCHA=1 -HT_GI=1 -HT_HTC=1 -HT_LDPC=1 -HT_LinkAdapt=0 -HT_MCS=33 -HT_MpduDensity=5 -HT_OpMode=0 -HT_PROTECT=1 -HT_RDG=0 -HT_RxStream=4 -HT_STBC=1 -HT_TxStream=4 -IcapMode=0 -idle_timeout_interval=0 -IEEE80211H=1 -IEEE8021X=0 -IgmpSnEnable=0 -ITxBfEn=1 -Key1Str= -Key1Str1= -Key1Str10= -Key1Str11= -Key1Str12= -Key1Str13= -Key1Str14= -Key1Str15= -Key1Str16= -Key1Str2= -Key1Str3= -Key1Str4= -Key1Str5= -Key1Str6= -Key1Str7= -Key1Str8= -Key1Str9= -Key1Type=0 -Key2Str= -Key2Str1= -Key2Str10= -Key2Str11= -Key2Str12= -Key2Str13= -Key2Str14= -Key2Str15= -Key2Str16= -Key2Str2= -Key2Str3= -Key2Str4= -Key2Str5= -Key2Str6= -Key2Str7= -Key2Str8= -Key2Str9= -Key2Type=0 -Key3Str= -Key3Str1= -Key3Str10= -Key3Str11= -Key3Str12= -Key3Str13= -Key3Str14= -Key3Str15= -Key3Str16= -Key3Str2= -Key3Str3= -Key3Str4= -Key3Str5= -Key3Str6= -Key3Str7= -Key3Str8= -Key3Str9= -Key3Type=0 -Key4Str= -Key4Str1= -Key4Str10= -Key4Str11= -Key4Str12= -Key4Str13= -Key4Str14= -Key4Str15= -Key4Str16= -Key4Str2= -Key4Str3= -Key4Str4= -Key4Str5= -Key4Str6= -Key4Str7= -Key4Str8= -Key4Str9= -Key4Type=0 -LinkTestSupport=0 -MACRepeaterEn= -MACRepeaterOuiMode=2 -MeshAuthMode= -MeshAutoLink=0 -MeshDefaultkey=0 -MeshEncrypType= -MeshId= -MeshWEPKEY= -MeshWPAKEY= -MUTxRxEnable=0 -NoForwarding=0 -NoForwardingBTNBSSID=0 -own_ip_addr=192.168.1.1 -PcieAspm=0 -PERCENTAGEenable=0 -PhyRateLimit=0 -PMFMFPC=1 -PMFMFPR=0 -PMFSHA256=0 -PMKCachePeriod=10 -PowerUpCckOfdm=0:0:0:0:0:0:0 -PowerUpHT20=0:0:0:0:0:0:0 -PowerUpHT40=0:0:0:0:0:0:0 -PowerUpVHT160=0:0:0:0:0:0:0 -PowerUpVHT20=0:0:0:0:0:0:0 -PowerUpVHT40=0:0:0:0:0:0:0 -PowerUpVHT80=0:0:0:0:0:0:0 -PreAntSwitch= -PreAuth=0 -PreAuthifname=br-lan -RadioLinkSelection=0 -RadioOn=1 -RADIUS_Acct_Key= -RADIUS_Acct_Port=1813 -RADIUS_Acct_Server= -RADIUS_Key1= -RADIUS_Key10= -RADIUS_Key11= -RADIUS_Key12= -RADIUS_Key13= -RADIUS_Key14= -RADIUS_Key15= -RADIUS_Key16= -RADIUS_Key2= -RADIUS_Key3= -RADIUS_Key4= -RADIUS_Key5= -RADIUS_Key6= -RADIUS_Key7= -RADIUS_Key8= -RADIUS_Key9= -RADIUS_Port=1812 -RADIUS_Server=0 -RDRegion= -RED_Enable=1 -RekeyInterval=3600 -RekeyMethod=DISABLE -RRMEnable=0 -RTSThreshold=2347 -session_timeout_interval=0 -ShortSlot=1 -SKUenable=0 -SSID= -SSID1=WITHUSP-2.4 -SSID10= -SSID11= -SSID12= -SSID13= -SSID14= -SSID15= -SSID16= -SSID2= -SSID3= -SSID4= -SSID5= -SSID6= -SSID7= -SSID8= -SSID9= -StationKeepAlive=0 -StreamMode=0 -StreamModeMac0= -StreamModeMac1= -StreamModeMac2= -StreamModeMac3= -TGnWifiTest=0 -ThermalRecal=0 -CCKTxStream=4 -TxBurst=1 -TxPower=100 -TxPreamble=1 -VHT_BW=0 -VHT_BW_SIGNAL=0 -VHT_LDPC=1 -VHT_Sec80_Channel=0 -VHT_SGI=1 -VHT_STBC=1 -VLANID=0 -VLANPriority=0 -VLANTag=0 -VOW_Airtime_Ctrl_En=0 -VOW_Airtime_Fairness_En=1 -VOW_BW_Ctrl=0 -VOW_Group_Backlog= -VOW_Group_DWRR_Max_Wait_Time= -VOW_Group_DWRR_Quantum= -VOW_Group_Max_Airtime_Bucket_Size= -VOW_Group_Max_Rate= -VOW_Group_Max_Rate_Bucket_Size= -VOW_Group_Max_Ratio= -VOW_Group_Max_Wait_Time= -VOW_Group_Min_Airtime_Bucket_Size= -VOW_Group_Min_Rate= -VOW_Group_Min_Rate_Bucket_Size= -VOW_Group_Min_Ratio= -VOW_Rate_Ctrl_En=0 -VOW_Refill_Period= -VOW_RX_En=1 -VOW_Sta_BE_DWRR_Quantum= -VOW_Sta_BK_DWRR_Quantum= -VOW_Sta_DWRR_Max_Wait_Time= -VOW_Sta_VI_DWRR_Quantum= -VOW_Sta_VO_DWRR_Quantum= -VOW_WATF_Enable= -VOW_WATF_MAC_LV0= -VOW_WATF_MAC_LV1= -VOW_WATF_MAC_LV2= -VOW_WATF_MAC_LV3= -VOW_WATF_Q_LV0= -VOW_WATF_Q_LV1= -VOW_WATF_Q_LV2= -VOW_WATF_Q_LV3= -VOW_WMM_Search_Rule_Band0= -VOW_WMM_Search_Rule_Band1= -WapiAsCertPath= -WapiAsIpAddr= -WapiAsPort= -Wapiifname= -WapiPsk1= -WapiPsk10= -WapiPsk11= -WapiPsk12= -WapiPsk13= -WapiPsk14= -WapiPsk15= -WapiPsk16= -WapiPsk2= -WapiPsk3= -WapiPsk4= -WapiPsk5= -WapiPsk6= -WapiPsk7= -WapiPsk8= -WapiPsk9= -WapiPskType= -WapiUserCertPath= -WCNTest=0 -Wds0Key= -Wds1Key= -Wds2Key= -Wds3Key= -WdsEnable=0 -WdsEncrypType=NONE -WdsList= -WdsPhyMode=0 -WHNAT=0 -WiFiTest=0 -WirelessMode=9 -WmmCapable=1 -WPAPSK= -WPAPSK1=12345678 -WPAPSK10= -WPAPSK11= -WPAPSK12= -WPAPSK13= -WPAPSK14= -WPAPSK15= -WPAPSK16= -WPAPSK2= -WPAPSK3= -WPAPSK4= -WPAPSK5= -WPAPSK6= -WPAPSK7= -WPAPSK8= -WPAPSK9= -WscConfMode=0 -WscConfStatus=2 -WEP1Type1=0 -WEP2Type1=0 -WEP3Type1=0 -WEP4Type1=0 -WPSRadio=0 diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/wifi_services.lua b/package/lean/mt/drivers/mt_wifi/dbdc/wifi_services.lua deleted file mode 100644 index 77579d39e..000000000 --- a/package/lean/mt/drivers/mt_wifi/dbdc/wifi_services.lua +++ /dev/null @@ -1,98 +0,0 @@ ---This file is created for check some deamons like miniupnpd,8021xd... - - local mtkwifi = require("mtkwifi") - local devs = mtkwifi.get_all_devs() - local nixio = require("nixio") - -function miniupnpd_chk(devname,vif,enable) - local WAN_IF=mtkwifi.__trim(mtkwifi.read_pipe("uci -q get network.wan.ifname")) - - os.execute("rm -rf /etc/miniupnpd.conf") - os.execute("iptables -t nat -F MINIUPNPD 1>/dev/null 2>&1") - --rmeoving the rule to MINIUPNPD - os.execute("iptables-t nat -D PREROUTING -i "..WAN_IF.." -j MINIUPNPD 1>/dev/null 2>&1") - os.execute("iptables-t nat -X MINIUPNPD 1>/dev/null 2>&1") - - --removing the MINIUPNPD chain for filter - os.execute("iptables -t filter -F MINIUPNPD 1>/dev/null 2>&1") - --adding the rule to MINIUPNPD - - os.execute("iptables -t filter -D FORWARD -i "..WAN_IF.." ! -o "..WAN_IF.." -j MINIUPNPD 1>/dev/null 2>&1") - os.execute("iptables -t filter -X MINIUPNPD 1>/dev/null 2>&1") - - os.execute("iptables -t nat -N MINIUPNPD") - os.execute("iptables -t nat -A PREROUTING -i "..WAN_IF.." -j MINIUPNPD") - os.execute("iptables -t filter -N MINIUPNPD") - os.execute("iptables -t filter -A FORWARD -i "..WAN_IF.." ! -o "..WAN_IF.." -j MINIUPNPD") - - if mtkwifi.exists("/tmp/run/miniupnpd."..vif) then - os.execute("cat /tmp/run/miniupnpd."..vif.." | xargs kill -9") - end - - if enable then - local profile = mtkwifi.search_dev_and_profile()[devname] - local cfgs = mtkwifi.load_profile(profile) - local ssid_index = devs[devname]["vifs"][vif].vifidx - local wsc_conf_mode = "" - local PORT_NUM = 7777+(string.byte(vif, -1)+string.byte(vif, -2)) - local LAN_IPADDR = mtkwifi.__trim(mtkwifi.read_pipe("uci -q get network.lan.ipaddr")) - local LAN_MASK = mtkwifi.__trim(mtkwifi.read_pipe("uci -q get network.lan.netmask")) - local port = 6352 + (string.byte(vif, -1)+string.byte(vif, -2)) - LAN_IPADDR = LAN_IPADDR.."/"..LAN_MASK - wsc_conf_mode = mtkwifi.token_get(cfgs["WscConfMode"], ssid_index, "") - - local file = io.open("/etc/miniupnpd.conf", "w") - if nil == file then - nixio.syslog("debug","open file /etc/miniupnpd.conf fail") - end - - file:write("ext_ifname=",WAN_IF,'\n','\n', - "listening_ip=",LAN_IPADDR,'\n','\n', - "port=",port,'\n','\n', - "bitrate_up=800000000",'\n', - "bitrate_down=800000000",'\n','\n', - "secure_mode=no",'\n','\n', - "system_uptime=yes",'\n','\n', - "notify_interval=30",'\n','\n', - "uuid=68555350-3352-3883-2883-335030522880",'\n','\n', - "serial=12345678",'\n','\n', - "model_number=1",'\n','\n', - "enable_upnp=no",'\n','\n') - file:close() - - if wsc_conf_mode ~= "" and wsc_conf_mode ~= "0" then - os.execute("miniupnpd -m 1 -I "..vif.." -P /var/run/miniupnpd."..vif.." -G -i "..WAN_IF.." -a "..LAN_IPADDR.." -n "..PORT_NUM) - end - end -end - -function d8021xd_chk(devname,prefix,main_ifname,enable) - local profile = mtkwifi.search_dev_and_profile()[devname] - local cfgs = mtkwifi.load_profile(profile) - local auth_mode = cfgs.AuthMode - local ieee8021x = cfgs.IEEE8021X - local pat_auth_mode = {"WPA$", "WPA;", "WPA2$", "WPA2;", "WPA1WPA2$", "WPA1WPA2;"} - local pat_ieee8021x = {"1$", "1;"} - local apd_en = false - if mtkwifi.exists("/tmp/run/8021xd_"..main_ifname..".pid") then - os.execute("cat /tmp/run/8021xd_"..main_ifname..".pid | xargs kill -9") - os.execute("rm /tmp/run/8021xd_"..main_ifname..".pid") - end - if enable then - for _, pat in ipairs(pat_auth_mode) do - if string.find(auth_mode, pat) then - apd_en = true - end - end - - for _, pat in ipairs(pat_ieee8021x) do - if string.find(ieee8021x, pat) then - apd_en = true - end - end - - if apd_en then - os.execute("8021xd -p "..prefix.. " -i "..main_ifname) - end - end -end diff --git a/package/lean/mt/drivers/mt_wifi/files/7603_7612-l1profile.dat b/package/lean/mt/drivers/mt_wifi/files/7603_7612-l1profile.dat new file mode 100644 index 000000000..393d31c07 --- /dev/null +++ b/package/lean/mt/drivers/mt_wifi/files/7603_7612-l1profile.dat @@ -0,0 +1,21 @@ +Default +INDEX0=MT7603 +INDEX0_profile_path=/etc/wireless/mt7615/mt7615.1.dat +INDEX0_EEPROM_offset=0x0 +INDEX0_EEPROM_size=0x400 +INDEX0_EEPROM_name=e2p +INDEX0_main_ifname=ra0 +INDEX0_ext_ifname=ra +INDEX0_wds_ifname=wds +INDEX0_apcli_ifname=apcli +INDEX1=MT7612 +INDEX1_profile_path=/etc/wireless/mt7615/mt7615.2.dat +INDEX1_EEPROM_offset=0x8000 +INDEX1_EEPROM_size=0x4000 +INDEX1_EEPROM_name=e2p +INDEX1_main_ifname=rai0 +INDEX1_ext_ifname=rai +INDEX1_wds_ifname=wdsi +INDEX1_apcli_ifname=apclii +INDEX1_single_sku_path=/etc_ro/Wireless/SingleSKU_mt7615e-sku.dat +INDEX1_bf_sku_path=/etc_ro/Wireless/SingleSKU_mt7615e-sku-bf.dat diff --git a/package/lean/mt/drivers/mt_wifi/files/l1profile.dat b/package/lean/mt/drivers/mt_wifi/files/7603_7615-l1profile.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/files/l1profile.dat rename to package/lean/mt/drivers/mt_wifi/files/7603_7615-l1profile.dat diff --git a/package/lean/mt/drivers/mt_wifi/files/82_load_wifi.sh b/package/lean/mt/drivers/mt_wifi/files/82_load_wifi.sh new file mode 100644 index 000000000..3c40e1518 --- /dev/null +++ b/package/lean/mt/drivers/mt_wifi/files/82_load_wifi.sh @@ -0,0 +1,9 @@ +. /lib/functions.sh + +load_wifi() { + local kernel_version=$(uname -r) + [ -e "/lib/modules/$kernel_version/mt7603e.ko" ] && modprobe mt7603e + [ -e "/lib/modules/$kernel_version/mt76x2_ap.ko" ] && modprobe mt76x2_ap +} + +boot_hook_add preinit_main load_wifi diff --git a/package/lean/mt/drivers/mt_wifi/files/firmware.sh b/package/lean/mt/drivers/mt_wifi/files/firmware.sh index abdade9c7..bcc8240ea 100644 --- a/package/lean/mt/drivers/mt_wifi/files/firmware.sh +++ b/package/lean/mt/drivers/mt_wifi/files/firmware.sh @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -chmod 777 /sbin/mtkwifi +chmod 0755 /sbin/mtkwifi START=15 STOP=15 diff --git a/package/lean/mt/drivers/mt_wifi/files/mt7615.1.dat b/package/lean/mt/drivers/mt_wifi/files/mt7603.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/files/mt7615.1.dat rename to package/lean/mt/drivers/mt_wifi/files/mt7603.dat diff --git a/package/lean/mt/drivers/mt_wifi/files/mt7612.dat b/package/lean/mt/drivers/mt_wifi/files/mt7612.dat new file mode 100644 index 000000000..e61a3fc60 --- /dev/null +++ b/package/lean/mt/drivers/mt_wifi/files/mt7612.dat @@ -0,0 +1,250 @@ +#The word of "Default" must not be removed +Default +CountryRegion=1 +CountryRegionABand=0 +CountryCode=US +ChannelGeography=2 +BssidNum=1 +SSID1=OpenWrt_5G +SSID2= +SSID3= +SSID4= +SSID5= +SSID6= +SSID7= +SSID8= +WirelessMode=14 +E2pAccessMode=2 +Channel=36 +AutoChannelSelect=2 +AutoChannelSkipList=52;56;60;64 +BasicRate=336 +BeaconPeriod=100 +DtimPeriod=1 +TxPower=100 +DisableOLBC=0 +BGProtection=2 +TxPreamble=1 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=1 +FreqDelta=0 +WmmCapable=0;0 +APAifsn=3;7;1;1 +APCwmin=4;4;3;2 +APCwmax=6;10;4;3 +APTxop=0;0;94;47 +APACM=0;0;0;0 +BSSAifsn=3;7;2;2 +BSSCwmin=4;4;3;2 +BSSCwmax=10;10;4;3 +BSSTxop=0;0;94;47 +BSSACM=0;0;0;0 +AckPolicy=0;0;0;0 +APSDCapable=0 +DLSCapable=0;0 +NoForwarding=0;1 +NoForwardingMBCast=0;1 +NoForwardingBTNBSSID=1 +HideSSID=0;0 +ShortSlot=1 +IEEE80211H=0 +CarrierDetect=0 +PreAntSwitch= +PhyRateLimit=0 +DebugFlags=0 +FineAGC=0 +StreamMode=3 +StreamModeMac0= +StreamModeMac1= +StreamModeMac2= +StreamModeMac3= +CSPeriod=10 +RDRegion=FCC +StationKeepAlive=0;0 +DfsLowerLimit=0 +DfsUpperLimit=0 +DfsIndoor=0 +DFSParamFromConfig=0 +DfsOutdoor=0 +DfsEnable=0 +FCCParamCh0= +FCCParamCh1= +FCCParamCh2= +FCCParamCh3= +CEParamCh0= +CEParamCh1= +CEParamCh2= +CEParamCh3= +JAPParamCh0= +JAPParamCh1= +JAPParamCh2= +JAPParamCh3= +JAPW53ParamCh0= +JAPW53ParamCh1= +JAPW53ParamCh2= +JAPW53ParamCh3= +FixDfsLimit=0 +LongPulseRadarTh=0 +AvgRssiReq=0 +DFS_R66=0 +BlockCh= +GreenAP=0 +AuthMode=WPA2PSK;OPEN +EncrypType=AES;NONE +WapiPsk1= +WapiPsk2= +WapiPsk3= +WapiPsk4= +WapiPsk5= +WapiPsk6= +WapiPsk7= +WapiPsk8= +WapiPskType= +Wapiifname= +WapiAsCertPath= +WapiUserCertPath= +WapiAsIpAddr= +WapiAsPort= +MeshAutoLink=0 +MeshAuthMode= +MeshEncrypType= +MeshDefaultkey=0 +MeshWEPKEY= +MeshWPAKEY= +MeshId= +RekeyMethod=TIME +RekeyInterval=3600 +PMKCachePeriod=10 +WPAPSK1=1234567890 +WPAPSK2= +WPAPSK3= +WPAPSK4= +WPAPSK5= +WPAPSK6= +WPAPSK7= +WPAPSK8= +DefaultKeyID=1 +Key1Type=0 +Key1Str1= +Key1Str2= +Key1Str3= +Key1Str4= +Key1Str5= +Key1Str6= +Key1Str7= +Key1Str8= +Key2Type=0 +Key2Str1= +Key2Str2= +Key2Str3= +Key2Str4= +Key2Str5= +Key2Str6= +Key2Str7= +Key2Str8= +Key3Type=0 +Key3Str1= +Key3Str2= +Key3Str3= +Key3Str4= +Key3Str5= +Key3Str6= +Key3Str7= +Key3Str8= +Key4Type=0 +Key4Str1= +Key4Str2= +Key4Str3= +Key4Str4= +Key4Str5= +Key4Str6= +Key4Str7= +Key4Str8= +HSCounter=0 +HT_HTC=0 +HT_RDG=0 +HT_LinkAdapt=0 +HT_OpMode=0 +HT_MpduDensity=5 +HT_EXTCHA=1 +HT_BW=1 +HT_BSSCoexistence=0 +HT_BSSCoexAPCntThr=10 +HT_AutoBA=1 +HT_BADecline=0 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_STBC=1 +FixedTxMode=0;0 +HT_MCS=33;33 +HT_TxStream=2 +HT_RxStream=2 +HT_PROTECT=1 +HT_DisallowTKIP=0 +HT_LDPC=0 +VHT_BW=1 +VHT_SGI=1 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=1 +VHT_STBC=0 +WscConfMode=0 +WscConfStatus=2 +WscVendorPinCode=12345670 +WscManufacturer=Youhua Technology +WscModelName=WPS Router +WscDeviceName=WPS Router +WscModelNumber=WR1200JS +WscSerialNumber=00000000 +WscV2Support=1 +ITxBfEn=1 +ETxBfEnCond=1 +ITxBfEnCond=1 +AccessPolicy0=0 +AccessControlList0= +AccessPolicy1=0 +AccessControlList1= +AccessPolicy2=0 +AccessControlList2= +AccessPolicy3=0 +AccessControlList3= +AccessPolicy4=0 +AccessControlList4= +AccessPolicy5=0 +AccessControlList5= +AccessPolicy6=0 +AccessControlList6= +AccessPolicy7=0 +AccessControlList7= +AccessPolicy8=0 +AccessControlList8= +WdsEnable=0 +WdsEncrypType=NONE +WdsList= +WdsKey= +session_timeout_interval=0 +own_ip_addr= +EAPifname= +PreAuthifname= +PreAuth=0;0 +IEEE8021X=0;0 +RADIUS_Server=; +RADIUS_Port=1812;1812 +RADIUS_Key1= +RADIUS_Key2= +RADIUS_Key3= +RADIUS_Key4= +RADIUS_Key5= +RADIUS_Key6= +RADIUS_Key7= +RADIUS_Key8= +WiFiTest=0 +TGnWifiTest=0 +RadioOn=1 +IgmpSnEnable=1 +McastPhyMode=2 +McastMcs=0 + diff --git a/package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.2.dat b/package/lean/mt/drivers/mt_wifi/files/mt7615.dat similarity index 100% rename from package/lean/mt/drivers/mt_wifi/dbdc/mt7615e.2.dat rename to package/lean/mt/drivers/mt_wifi/files/mt7615.dat diff --git a/package/lean/mt/drivers/mt_wifi/files/mt7615e.1.dat b/package/lean/mt/drivers/mt_wifi/files/mt7615e.1.dat deleted file mode 100644 index f58d6ba52..000000000 --- a/package/lean/mt/drivers/mt_wifi/files/mt7615e.1.dat +++ /dev/null @@ -1,410 +0,0 @@ -#The word of "Default" must not be removed -Default -AccessControlList0= -AccessControlList1= -AccessControlList10= -AccessControlList11= -AccessControlList12= -AccessControlList13= -AccessControlList14= -AccessControlList15= -AccessControlList2= -AccessControlList3= -AccessControlList4= -AccessControlList5= -AccessControlList6= -AccessControlList7= -AccessControlList8= -AccessControlList9= -AccessPolicy0=0 -AccessPolicy1=0 -AccessPolicy10=0 -AccessPolicy11=0 -AccessPolicy12=0 -AccessPolicy13=0 -AccessPolicy14=0 -AccessPolicy15=0 -AccessPolicy2=0 -AccessPolicy3=0 -AccessPolicy4=0 -AccessPolicy5=0 -AccessPolicy6=0 -AccessPolicy7=0 -AccessPolicy8=0 -AccessPolicy9=0 -AckPolicy=0;0;0;0 -APACM=0;0;0;0 -APAifsn=3;7;1;1 -ApCliAuthMode= -ApCliBssid= -ApCliDefaultKeyID= -ApCliEnable= -ApCliKey1Str= -ApCliKey1Str1= -ApCliKey1Type= -ApCliKey2Str= -ApCliKey2Str1= -ApCliKey2Type= -ApCliKey3Str= -ApCliKey3Str1= -ApCliKey3Type= -ApCliKey4Str= -ApCliKey4Str1= -ApCliKey4Type= -ApCliSsid= -ApCliWirelessMode= -ApCliWPAPSK= -ApCliWPAPSK1= -APCwmax=6;10;4;3 -APCwmin=4;4;3;2 -APSDCapable=1 -APTxop=0;0;94;47 -AuthMode=OPEN -AutoChannelSelect=3 -AutoChannelSkipList= -AutoProvisionEn=0 -BandSteering=0 -BasicRate=15 -BeaconPeriod=100 -BFBACKOFFenable=0 -BgndScanSkipCh= -BGProtection=0 -BndStrgBssIdx= -BSSACM=0;0;0;0 -BSSAifsn=3;7;2;2 -BSSCwmax=10;10;4;3 -BSSCwmin=4;4;3;2 -BssidNum=1 -BSSTxop=0;0;94;47 -BW_Enable=0 -BW_Guarantee_Rate= -BW_Maximum_Rate= -BW_Priority= -BW_Root=0 -CalCacheApply=0 -CarrierDetect=0 -Channel=0 -ChannelGrp= -CountryCode=US -CountryRegion=5 -CountryRegionABand=7 -CP_SUPPORT=2 -CSPeriod=6 -DBDC_MODE=0 -DebugFlags=0 -DefaultKeyID=1 -DfsCalibration=0 -DfsEnable=0 -DfsFalseAlarmPrevent=1 -DfsZeroWait=0 -DfsZeroWaitCacTime=255 -DisableOLBC=0 -DtimPeriod=1 -E2pAccessMode=2 -EAPifname=br-lan -EDCCAEnable=1 -EncrypType=NONE -EthConvertMode=dongle -EtherTrafficBand=0 -Ethifname= -ETxBfEnCond=1 -FineAGC=0 -FixedTxMode= -ForceRoamSupport= -FragThreshold=2346 -FreqDelta=0 -FtSupport=0 -GreenAP=1 -G_BAND_256QAM=1 -HideSSID=0 -HT_AMSDU=1 -HT_AutoBA=1 -HT_BADecline=0 -HT_BAWinSize=64 -HT_BSSCoexistence=1 -HT_BW=1 -HT_DisallowTKIP=1 -HT_EXTCHA=1 -HT_GI=1 -HT_HTC=1 -HT_LDPC=1 -HT_LinkAdapt=0 -HT_MCS=33 -HT_MpduDensity=5 -HT_OpMode=0 -HT_PROTECT=1 -HT_RDG=0 -HT_RxStream=4 -HT_STBC=1 -HT_TxStream=4 -IcapMode=0 -idle_timeout_interval=0 -IEEE80211H=1 -IEEE8021X=0 -IgmpSnEnable=0 -ITxBfEn=1 -Key1Str= -Key1Str1= -Key1Str10= -Key1Str11= -Key1Str12= -Key1Str13= -Key1Str14= -Key1Str15= -Key1Str16= -Key1Str2= -Key1Str3= -Key1Str4= -Key1Str5= -Key1Str6= -Key1Str7= -Key1Str8= -Key1Str9= -Key1Type=0 -Key2Str= -Key2Str1= -Key2Str10= -Key2Str11= -Key2Str12= -Key2Str13= -Key2Str14= -Key2Str15= -Key2Str16= -Key2Str2= -Key2Str3= -Key2Str4= -Key2Str5= -Key2Str6= -Key2Str7= -Key2Str8= -Key2Str9= -Key2Type=0 -Key3Str= -Key3Str1= -Key3Str10= -Key3Str11= -Key3Str12= -Key3Str13= -Key3Str14= -Key3Str15= -Key3Str16= -Key3Str2= -Key3Str3= -Key3Str4= -Key3Str5= -Key3Str6= -Key3Str7= -Key3Str8= -Key3Str9= -Key3Type=0 -Key4Str= -Key4Str1= -Key4Str10= -Key4Str11= -Key4Str12= -Key4Str13= -Key4Str14= -Key4Str15= -Key4Str16= -Key4Str2= -Key4Str3= -Key4Str4= -Key4Str5= -Key4Str6= -Key4Str7= -Key4Str8= -Key4Str9= -Key4Type=0 -LinkTestSupport=0 -MACRepeaterEn= -MACRepeaterOuiMode=2 -MeshAuthMode= -MeshAutoLink=0 -MeshDefaultkey=0 -MeshEncrypType= -MeshId= -MeshWEPKEY= -MeshWPAKEY= -MUTxRxEnable=0 -NoForwarding=0 -NoForwardingBTNBSSID=0 -own_ip_addr=192.168.1.1 -PcieAspm=0 -PERCENTAGEenable=0 -PhyRateLimit=0 -PMFMFPC=1 -PMFMFPR=0 -PMFSHA256=0 -PMKCachePeriod=10 -PowerUpCckOfdm=0:0:0:0:0:0:0 -PowerUpHT20=0:0:0:0:0:0:0 -PowerUpHT40=0:0:0:0:0:0:0 -PowerUpVHT160=0:0:0:0:0:0:0 -PowerUpVHT20=0:0:0:0:0:0:0 -PowerUpVHT40=0:0:0:0:0:0:0 -PowerUpVHT80=0:0:0:0:0:0:0 -PreAntSwitch= -PreAuth=0 -PreAuthifname=br-lan -RadioLinkSelection=0 -RadioOn=1 -RADIUS_Acct_Key= -RADIUS_Acct_Port=1813 -RADIUS_Acct_Server= -RADIUS_Key1= -RADIUS_Key10= -RADIUS_Key11= -RADIUS_Key12= -RADIUS_Key13= -RADIUS_Key14= -RADIUS_Key15= -RADIUS_Key16= -RADIUS_Key2= -RADIUS_Key3= -RADIUS_Key4= -RADIUS_Key5= -RADIUS_Key6= -RADIUS_Key7= -RADIUS_Key8= -RADIUS_Key9= -RADIUS_Port=1812 -RADIUS_Server=0 -RDRegion= -RED_Enable=1 -RekeyInterval=3600 -RekeyMethod=DISABLE -RRMEnable=0 -RTSThreshold=2347 -session_timeout_interval=0 -ShortSlot=1 -SKUenable=0 -SSID= -SSID1=WITHUSP-5.0 -SSID10= -SSID11= -SSID12= -SSID13= -SSID14= -SSID15= -SSID16= -SSID2= -SSID3= -SSID4= -SSID5= -SSID6= -SSID7= -SSID8= -SSID9= -StationKeepAlive=0 -StreamMode=0 -StreamModeMac0= -StreamModeMac1= -StreamModeMac2= -StreamModeMac3= -TGnWifiTest=0 -ThermalRecal=0 -TxBurst=1 -TxPower=100 -TxPreamble=1 -VHT_BW=1 -VHT_BW_SIGNAL=0 -VHT_LDPC=1 -VHT_Sec80_Channel=0 -VHT_SGI=1 -VHT_STBC=1 -VLANID=0 -VLANPriority=0 -VLANTag=0 -VOW_Airtime_Ctrl_En=0 -VOW_Airtime_Fairness_En=1 -VOW_BW_Ctrl=0 -VOW_Group_Backlog= -VOW_Group_DWRR_Max_Wait_Time= -VOW_Group_DWRR_Quantum= -VOW_Group_Max_Airtime_Bucket_Size= -VOW_Group_Max_Rate= -VOW_Group_Max_Rate_Bucket_Size= -VOW_Group_Max_Ratio= -VOW_Group_Max_Wait_Time= -VOW_Group_Min_Airtime_Bucket_Size= -VOW_Group_Min_Rate= -VOW_Group_Min_Rate_Bucket_Size= -VOW_Group_Min_Ratio= -VOW_Rate_Ctrl_En=0 -VOW_Refill_Period= -VOW_RX_En=1 -VOW_Sta_BE_DWRR_Quantum= -VOW_Sta_BK_DWRR_Quantum= -VOW_Sta_DWRR_Max_Wait_Time= -VOW_Sta_VI_DWRR_Quantum= -VOW_Sta_VO_DWRR_Quantum= -VOW_WATF_Enable= -VOW_WATF_MAC_LV0= -VOW_WATF_MAC_LV1= -VOW_WATF_MAC_LV2= -VOW_WATF_MAC_LV3= -VOW_WATF_Q_LV0= -VOW_WATF_Q_LV1= -VOW_WATF_Q_LV2= -VOW_WATF_Q_LV3= -VOW_WMM_Search_Rule_Band0= -VOW_WMM_Search_Rule_Band1= -WapiAsCertPath= -WapiAsIpAddr= -WapiAsPort= -Wapiifname= -WapiPsk1= -WapiPsk10= -WapiPsk11= -WapiPsk12= -WapiPsk13= -WapiPsk14= -WapiPsk15= -WapiPsk16= -WapiPsk2= -WapiPsk3= -WapiPsk4= -WapiPsk5= -WapiPsk6= -WapiPsk7= -WapiPsk8= -WapiPsk9= -WapiPskType= -WapiUserCertPath= -WCNTest=0 -Wds0Key= -Wds1Key= -Wds2Key= -Wds3Key= -WdsEnable=0 -WdsEncrypType=NONE -WdsList= -WdsPhyMode=0 -WHNAT=1 -WiFiTest=0 -WirelessMode=14 -WmmCapable=1 -WPAPSK= -WPAPSK1=12345678 -WPAPSK10= -WPAPSK11= -WPAPSK12= -WPAPSK13= -WPAPSK14= -WPAPSK15= -WPAPSK16= -WPAPSK2= -WPAPSK3= -WPAPSK4= -WPAPSK5= -WPAPSK6= -WPAPSK7= -WPAPSK8= -WPAPSK9= -WscConfMode=0 -WscConfStatus=2 -WEP1Type1=0 -WEP2Type1=0 -WEP3Type1=0 -WEP4Type1=0 -WPSRadio=0 diff --git a/package/lean/mt/drivers/mt_wifi/files/mt7615e.2.dat b/package/lean/mt/drivers/mt_wifi/files/mt7615e.2.dat deleted file mode 100644 index 56f39e1e9..000000000 --- a/package/lean/mt/drivers/mt_wifi/files/mt7615e.2.dat +++ /dev/null @@ -1,412 +0,0 @@ -#The word of "Default" must not be removed -Default -AccessControlList0= -AccessControlList1= -AccessControlList10= -AccessControlList11= -AccessControlList12= -AccessControlList13= -AccessControlList14= -AccessControlList15= -AccessControlList2= -AccessControlList3= -AccessControlList4= -AccessControlList5= -AccessControlList6= -AccessControlList7= -AccessControlList8= -AccessControlList9= -AccessPolicy0=0 -AccessPolicy1=0 -AccessPolicy10=0 -AccessPolicy11=0 -AccessPolicy12=0 -AccessPolicy13=0 -AccessPolicy14=0 -AccessPolicy15=0 -AccessPolicy2=0 -AccessPolicy3=0 -AccessPolicy4=0 -AccessPolicy5=0 -AccessPolicy6=0 -AccessPolicy7=0 -AccessPolicy8=0 -AccessPolicy9=0 -AckPolicy=0;0;0;0 -APACM=0;0;0;0 -APAifsn=3;7;1;1 -ApCliAuthMode= -ApCliBssid= -ApCliDefaultKeyID= -ApCliEnable= -ApCliEncrypType= -ApCliKey1Str= -ApCliKey1Str1= -ApCliKey1Type= -ApCliKey2Str= -ApCliKey2Str1= -ApCliKey2Type= -ApCliKey3Str= -ApCliKey3Str1= -ApCliKey3Type= -ApCliKey4Str= -ApCliKey4Str1= -ApCliKey4Type= -ApCliSsid= -ApCliWirelessMode= -ApCliWPAPSK= -ApCliWPAPSK1= -APCwmax=6;10;4;3 -APCwmin=4;4;3;2 -APSDCapable=1 -APTxop=0;0;94;47 -AuthMode=OPEN -AutoChannelSelect=3 -AutoChannelSkipList= -AutoProvisionEn=0 -BandSteering=0 -BasicRate=15 -BeaconPeriod=100 -BFBACKOFFenable=0 -BgndScanSkipCh= -BGProtection=0 -BndStrgBssIdx= -BSSACM=0;0;0;0 -BSSAifsn=3;7;2;2 -BSSCwmax=10;10;4;3 -BSSCwmin=4;4;3;2 -BssidNum=1 -BSSTxop=0;0;94;47 -BW_Enable=0 -BW_Guarantee_Rate= -BW_Maximum_Rate= -BW_Priority= -BW_Root=0 -CalCacheApply=0 -CarrierDetect=0 -Channel=0 -ChannelGrp= -CountryCode=US -CountryRegion=5 -CountryRegionABand=7 -CP_SUPPORT=2 -CSPeriod=6 -DBDC_MODE=0 -DebugFlags=0 -DefaultKeyID=1 -DfsCalibration=0 -DfsEnable=0 -DfsFalseAlarmPrevent=1 -DfsZeroWait=0 -DfsZeroWaitCacTime=255 -DisableOLBC=0 -DtimPeriod=1 -E2pAccessMode=1 -EAPifname=br-lan -EDCCAEnable=1 -EncrypType=NONE -EthConvertMode=dongle -EtherTrafficBand=0 -Ethifname= -ETxBfEnCond=1 -FineAGC=0 -FixedTxMode= -ForceRoamSupport= -FragThreshold=2346 -FreqDelta=0 -FtSupport=0 -GreenAP=1 -G_BAND_256QAM=1 -HideSSID=0 -HT_AMSDU=1 -HT_AutoBA=1 -HT_BADecline=0 -HT_BAWinSize=64 -HT_BSSCoexistence=1 -HT_BW=1 -HT_DisallowTKIP=1 -HT_EXTCHA=1 -HT_GI=1 -HT_HTC=1 -HT_LDPC=1 -HT_LinkAdapt=0 -HT_MCS=33 -HT_MpduDensity=5 -HT_OpMode=0 -HT_PROTECT=1 -HT_RDG=0 -HT_RxStream=4 -HT_STBC=1 -HT_TxStream=4 -IcapMode=0 -idle_timeout_interval=0 -IEEE80211H=1 -IEEE8021X=0 -IgmpSnEnable=0 -ITxBfEn=1 -Key1Str= -Key1Str1= -Key1Str10= -Key1Str11= -Key1Str12= -Key1Str13= -Key1Str14= -Key1Str15= -Key1Str16= -Key1Str2= -Key1Str3= -Key1Str4= -Key1Str5= -Key1Str6= -Key1Str7= -Key1Str8= -Key1Str9= -Key1Type=0 -Key2Str= -Key2Str1= -Key2Str10= -Key2Str11= -Key2Str12= -Key2Str13= -Key2Str14= -Key2Str15= -Key2Str16= -Key2Str2= -Key2Str3= -Key2Str4= -Key2Str5= -Key2Str6= -Key2Str7= -Key2Str8= -Key2Str9= -Key2Type=0 -Key3Str= -Key3Str1= -Key3Str10= -Key3Str11= -Key3Str12= -Key3Str13= -Key3Str14= -Key3Str15= -Key3Str16= -Key3Str2= -Key3Str3= -Key3Str4= -Key3Str5= -Key3Str6= -Key3Str7= -Key3Str8= -Key3Str9= -Key3Type=0 -Key4Str= -Key4Str1= -Key4Str10= -Key4Str11= -Key4Str12= -Key4Str13= -Key4Str14= -Key4Str15= -Key4Str16= -Key4Str2= -Key4Str3= -Key4Str4= -Key4Str5= -Key4Str6= -Key4Str7= -Key4Str8= -Key4Str9= -Key4Type=0 -LinkTestSupport=0 -MACRepeaterEn= -MACRepeaterOuiMode=2 -MeshAuthMode= -MeshAutoLink=0 -MeshDefaultkey=0 -MeshEncrypType= -MeshId= -MeshWEPKEY= -MeshWPAKEY= -MUTxRxEnable=0 -NoForwarding=0 -NoForwardingBTNBSSID=0 -own_ip_addr=192.168.1.1 - -PcieAspm=0 -PERCENTAGEenable=0 -PhyRateLimit=0 -PMFMFPC=1 -PMFMFPR=0 -PMFSHA256=0 -PMKCachePeriod=10 -PowerUpCckOfdm=0:0:0:0:0:0:0 -PowerUpHT20=0:0:0:0:0:0:0 -PowerUpHT40=0:0:0:0:0:0:0 -PowerUpVHT160=0:0:0:0:0:0:0 -PowerUpVHT20=0:0:0:0:0:0:0 -PowerUpVHT40=0:0:0:0:0:0:0 -PowerUpVHT80=0:0:0:0:0:0:0 -PreAntSwitch= -PreAuth=0 -PreAuthifname=br-lan -RadioLinkSelection=0 -RadioOn=1 -RADIUS_Acct_Key= -RADIUS_Acct_Port=1813 -RADIUS_Acct_Server= -RADIUS_Key1= -RADIUS_Key10= -RADIUS_Key11= -RADIUS_Key12= -RADIUS_Key13= -RADIUS_Key14= -RADIUS_Key15= -RADIUS_Key16= -RADIUS_Key2= -RADIUS_Key3= -RADIUS_Key4= -RADIUS_Key5= -RADIUS_Key6= -RADIUS_Key7= -RADIUS_Key8= -RADIUS_Key9= -RADIUS_Port=1812 -RADIUS_Server=0 -RDRegion= -RED_Enable=1 -RekeyInterval=3600 -RekeyMethod=DISABLE -RRMEnable=0 -RTSThreshold=2347 -session_timeout_interval=0 -ShortSlot=1 -SKUenable=0 -SSID= -SSID1=MTK_AP3 -SSID10= -SSID11= -SSID12= -SSID13= -SSID14= -SSID15= -SSID16= -SSID2= -SSID3= -SSID4= -SSID5= -SSID6= -SSID7= -SSID8= -SSID9= -StationKeepAlive=0 -StreamMode=0 -StreamModeMac0= -StreamModeMac1= -StreamModeMac2= -StreamModeMac3= -TGnWifiTest=0 -ThermalRecal=0 -TxBurst=1 -TxPower=100 -TxPreamble=1 -VHT_BW=1 -VHT_BW_SIGNAL=0 -VHT_LDPC=1 -VHT_Sec80_Channel=0 -VHT_SGI=1 -VHT_STBC=1 -VLANID=0 -VLANPriority=0 -VLANTag=0 -VOW_Airtime_Ctrl_En= -VOW_Airtime_Fairness_En=1 -VOW_BW_Ctrl=0 -VOW_Group_Backlog= -VOW_Group_DWRR_Max_Wait_Time= -VOW_Group_DWRR_Quantum= -VOW_Group_Max_Airtime_Bucket_Size= -VOW_Group_Max_Rate= -VOW_Group_Max_Rate_Bucket_Size= -VOW_Group_Max_Ratio= -VOW_Group_Max_Wait_Time= -VOW_Group_Min_Airtime_Bucket_Size= -VOW_Group_Min_Rate= -VOW_Group_Min_Rate_Bucket_Size= -VOW_Group_Min_Ratio= -VOW_Rate_Ctrl_En= -VOW_Refill_Period= -VOW_RX_En=1 -VOW_Sta_BE_DWRR_Quantum= -VOW_Sta_BK_DWRR_Quantum= -VOW_Sta_DWRR_Max_Wait_Time= -VOW_Sta_VI_DWRR_Quantum= -VOW_Sta_VO_DWRR_Quantum= -VOW_WATF_Enable= -VOW_WATF_MAC_LV0= -VOW_WATF_MAC_LV1= -VOW_WATF_MAC_LV2= -VOW_WATF_MAC_LV3= -VOW_WATF_Q_LV0= -VOW_WATF_Q_LV1= -VOW_WATF_Q_LV2= -VOW_WATF_Q_LV3= -VOW_WMM_Search_Rule_Band0= -VOW_WMM_Search_Rule_Band1= -WapiAsCertPath= -WapiAsIpAddr= -WapiAsPort= -Wapiifname= -WapiPsk1= -WapiPsk10= -WapiPsk11= -WapiPsk12= -WapiPsk13= -WapiPsk14= -WapiPsk15= -WapiPsk16= -WapiPsk2= -WapiPsk3= -WapiPsk4= -WapiPsk5= -WapiPsk6= -WapiPsk7= -WapiPsk8= -WapiPsk9= -WapiPskType= -WapiUserCertPath= -WCNTest=0 -Wds0Key= -Wds1Key= -Wds2Key= -Wds3Key= -WdsEnable=0 -WdsEncrypType=NONE -WdsList= -WdsPhyMode=0 -WHNAT=1 -WiFiTest=0 -WirelessMode=14 -WmmCapable=1 -WPAPSK= -WPAPSK1=12345678 -WPAPSK10= -WPAPSK11= -WPAPSK12= -WPAPSK13= -WPAPSK14= -WPAPSK15= -WPAPSK16= -WPAPSK2= -WPAPSK3= -WPAPSK4= -WPAPSK5= -WPAPSK6= -WPAPSK7= -WPAPSK8= -WPAPSK9= -WscConfMode=0 -WscConfStatus=2 -WEP1Type1=0 -WEP2Type1=0 -WEP3Type1=0 -WEP4Type1=0 -WPSRadio=0 diff --git a/package/lean/mt/luci-app-mtwifi/Makefile b/package/lean/mt/luci-app-mtwifi/Makefile index 751ac1f04..fe0a7cdf9 100644 --- a/package/lean/mt/luci-app-mtwifi/Makefile +++ b/package/lean/mt/luci-app-mtwifi/Makefile @@ -4,10 +4,10 @@ PKG_LICENSE:=GPLv2 PKG_MAINTAINER:=Hua Shao LUCI_TITLE:=LuCI support for mt wifi driver -LUCI_DEPENDS:=@TARGET_ramips +LUCI_DEPENDS:=@TARGET_ramips +mt_wifi LUCI_PKGARCH:=all PKG_VERSION:=1 -PKG_RELEASE:=11 +PKG_RELEASE:=12 define Package/luci-app-mtwifi/conffiles /etc/wireless/mt7615/ diff --git a/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_dev_cfg.htm b/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_dev_cfg.htm index 76ae55dcc..6de961432 100644 --- a/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_dev_cfg.htm +++ b/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_dev_cfg.htm @@ -37,7 +37,7 @@ local cfgs = mtkwifi.load_profile(dev.profile)
" enctype="multipart/form-data" onreset="return cbi_validate_reset(this)" onsubmit="return cbi_validate_form(this, 'Some fields are invalid, cannot save values!')" autocomplete="false">
- Device Configurations - <%=devname%> + 无线高级设置 - <%=devname%> <% local diff = mtkwifi.diff_profile(dev.profile) if next(diff) ~= nil then @@ -50,7 +50,7 @@ if next(diff) ~= nil then - + - + - + <% if cfgs.HT_OpMode then %> - + @@ -117,7 +117,7 @@ if next(diff) ~= nil then <% end %> - + <% if cfgs.VHT_BW then %> - + @@ -162,8 +162,8 @@ if next(diff) ~= nil then @@ -172,8 +172,8 @@ if next(diff) ~= nil then @@ -182,8 +182,8 @@ if next(diff) ~= nil then @@ -192,8 +192,8 @@ if next(diff) ~= nil then @@ -202,8 +202,8 @@ if next(diff) ~= nil then @@ -224,8 +224,8 @@ if next(diff) ~= nil then @@ -234,8 +234,8 @@ if next(diff) ~= nil then @@ -245,8 +245,8 @@ if next(diff) ~= nil then @@ -268,8 +268,8 @@ if next(diff) ~= nil then @@ -278,7 +278,7 @@ if next(diff) ~= nil then @@ -287,7 +287,7 @@ if next(diff) ~= nil then @@ -296,7 +296,7 @@ if next(diff) ~= nil then @@ -305,7 +305,7 @@ if next(diff) ~= nil then @@ -314,7 +314,7 @@ if next(diff) ~= nil then @@ -323,8 +323,8 @@ if next(diff) ~= nil then @@ -333,8 +333,8 @@ if next(diff) ~= nil then @@ -343,8 +343,8 @@ if next(diff) ~= nil then @@ -353,8 +353,8 @@ if next(diff) ~= nil then @@ -363,8 +363,8 @@ if next(diff) ~= nil then @@ -374,18 +374,18 @@ if next(diff) ~= nil then
- - - - + + + +
" enctype="multipart/form-data" onreset="return cbi_validate_reset(this)" onsubmit="return cbi_validate_form(this, 'Some fields are invalid, cannot save values!')" autocomplete="off">
- Raw Configurations ( Edit WiFi profile directly ) -

WARNING : DO NOT MESS WITH IT IF YOU DON'T UNDERSTAND IT!

+ 无线参数(直接修改无线配置) +

警告 : 如果你不了解请不要修改!

- '" type="button" /> - - '" /> + '" type="button" /> + + '" />
diff --git a/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_overview.htm b/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_overview.htm index 23ef1e83b..1d6216566 100644 --- a/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_overview.htm +++ b/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_overview.htm @@ -47,9 +47,9 @@ local devs = mtkwifi.get_all_devs() 模式: <% if dev.ApCliEnable == "1" then %> APCli <% else %> Master AP<% end %> @@ -64,7 +64,7 @@ local devs = mtkwifi.get_all_devs() <% end %> - <% end %> diff --git a/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_vif_cfg.htm b/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_vif_cfg.htm index 7d214526e..597c4a396 100644 --- a/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_vif_cfg.htm +++ b/package/lean/mt/luci-app-mtwifi/luasrc/view/admin_mtk/mtk_wifi_vif_cfg.htm @@ -68,7 +68,7 @@ local WscValue = mtkwifi.token_get(cfgs["WscConfMode"], vifidx, "0") or "0" <% else %>
- 无线配置 - <%=vifname and devname.."@"..vifname or devname%> + 无线高级设置 - <%=vifname and devname.."@"..vifname or devname%> <% local diff = mtkwifi.diff_profile(dev.profile) if next(diff) ~= nil then diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index d43bd8432..ddf4bb6c7 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -233,8 +233,8 @@ define Device/d-team_newifi-d2 IMAGE_SIZE := 32448k DEVICE_VENDOR := Newifi DEVICE_MODEL := D2 - DEVICE_PACKAGES := kmod-mt7603 kmod-mt76x2 kmod-usb3 \ - kmod-usb-ledtrig-usbport wpad-openssl + DEVICE_PACKAGES := kmod-mt7603e kmod-mt76x2e kmod-usb3 \ + kmod-usb-ledtrig-usbport luci-app-mtwifi endef TARGET_DEVICES += d-team_newifi-d2 @@ -694,7 +694,7 @@ define Device/netgear_r6850 SERCOMM_HWVER := A001 SERCOMM_SWVER := 0x0052 IMAGE_SIZE := 40960k - DEVICE_PACKAGES += -kmod-mt7603 -wpad-openssl kmod-mt7603e luci-app-mtwifi kmod-mt_wifi + DEVICE_PACKAGES += kmod-mt7603e kmod-mt7615d luci-app-mtwifi endef TARGET_DEVICES += netgear_r6850 @@ -1017,7 +1017,7 @@ define Device/xiaomi_mi-router-ac2100 IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Mi Router AC2100 - DEVICE_PACKAGES := -kmod-mt7603 -wpad-openssl kmod-mt7603e luci-app-mtwifi kmod-mt_wifi uboot-envtools + DEVICE_PACKAGES := kmod-mt7603e kmod-mt7615d luci-app-mtwifi uboot-envtools endef TARGET_DEVICES += xiaomi_mi-router-ac2100 @@ -1034,7 +1034,7 @@ define Device/xiaomi_redmi-router-ac2100 IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | check-size $$$$(IMAGE_SIZE) DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Redmi Router AC2100 - DEVICE_PACKAGES := -kmod-mt7603 -wpad-openssl kmod-mt7603e luci-app-mtwifi kmod-mt_wifi uboot-envtools + DEVICE_PACKAGES := kmod-mt7603e kmod-mt7615d luci-app-mtwifi uboot-envtools endef TARGET_DEVICES += xiaomi_redmi-router-ac2100 diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index cd20b1e4c..501125ee0 100755 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -20,6 +20,9 @@ ramips_setup_interfaces() xiaomi,mir4) ucidef_set_interfaces_lan_wan "lan1 lan2" "wan" ;; + d-team,newifi-d2) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 ra0 rai0" "wan" + ;; gehua,ghl-r-001|\ hiwifi,hc5962|\ xiaomi,mir3p|\
Mode模式
Channel信道 @@ -69,7 +69,7 @@ if next(diff) ~= nil then <% if cfgs.ApCliEnable == "1" then %> APClient/Repeater Mode. <% end %>
Country Code区域代码
Operating Mode无线模式
Channel BandWidth信道带宽
2G 40Mhz Ext Channel2G 40MHZ模式辅助信道 @@ -152,8 +152,8 @@ if next(diff) ~= nil then
STBC - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
A-MSDU - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
Auto Block ACK - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
Decline BA Request - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
HT Disallow TKIP - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
HT LDPC - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
VHT STBC - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
VHT BW Signaling - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用 checked="checked"<% end %>/> Dynamic
VHT LDPC - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
HT Protection - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
Beacon Interval - ms(range 20-999, default 100) + ms(范围 20-999, 默认值 100)
Data Beacon Rate (DTIM) - ms(range 1-255, default 1) + ms(范围 1-255, 默认值 1)
Fragment Threshold - (range 256-2346, default 2346) + (范围 256-2346, 默认值 2346)
RTS Threshold - (range 256-2347, default 2347) + (范围 256-2347, 默认值 2347)
TX Power - dbm(range 1-100, default 100) + dbm(范围 1-100, 默认值 100)
Short Preamble - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
Short Slot - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
TX Burst - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
Packet Aggregate - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
802.11H - checked="checked"<% end %>/> Enable - checked="checked"<% end %>/> Disable + checked="checked"<% end %>/> 启用 + checked="checked"<% end %>/> 禁用
- - '" /> - '" /> + + '" /> + '" />
Interface: <%=vif.vifname%> | SSID: <%=vif.__ssid%> | 信道: <%=vif.__channel or dev.Channel%> + 接口: <%=vif.vifname%> | 无线名称: <%=vif.__ssid%> | 信道: <%=vif.__channel or dev.Channel%>
<% if vif.state == "up" then %> BSSID::<%=vif.__bssid%> | 无线模式: <%=dev.WirelessModeList[tonumber(vif.__wirelessmode or dev.WirelessMode)]%> @@ -74,14 +74,14 @@ local devs = mtkwifi.get_all_devs()
<% if not vif.state then %> - + <% elseif vif.state == "up" then %> - '" /> + '" /> <% else %> - '" /> + '" /> <% end %> - '" /> - '" /> + '" /> + '" />